9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-19 15:09:15 +00:00

增强客户端语言获取

This commit is contained in:
XiaoMoMi
2025-11-26 17:27:41 +08:00
parent 809ef571b1
commit 3f623eff1b
4 changed files with 63 additions and 12 deletions

View File

@@ -358,6 +358,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
registerNMSPacketConsumer(new FinishConfigurationListener(), NetworkReflections.clazz$ClientboundFinishConfigurationPacket);
registerNMSPacketConsumer(new LoginFinishedListener(), NetworkReflections.clazz$ClientboundLoginFinishedPacket);
registerNMSPacketConsumer(new UpdateTagsListener(), NetworkReflections.clazz$ClientboundUpdateTagsPacket);
registerNMSPacketConsumer(new ClientInformationListener(), VersionHelper.isOrAbove1_20_2() ? NetworkReflections.clazz$ServerboundClientInformationPacket1 : NetworkReflections.clazz$ServerboundClientInformationPacket0);
registerNMSPacketConsumer(new ContainerClickListener1_21_5(), VersionHelper.isOrAbove1_21_5() ? NetworkReflections.clazz$ServerboundContainerClickPacket : null);
registerS2CGamePacketListener(new ForgetLevelChunkListener(), this.packetIds.clientboundForgetLevelChunkPacket(), "ClientboundForgetLevelChunkPacket");
registerS2CGamePacketListener(new SetScoreListener1_20_3(), VersionHelper.isOrAbove1_20_3() ? this.packetIds.clientboundSetScorePacket() : -1, "ClientboundSetScorePacket");
@@ -1288,6 +1289,27 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
}
}
public static class ClientInformationListener implements NMSPacketListener {
@Override
public void onPacketReceive(NetWorkUser user, NMSPacketEvent event, Object packet) {
try {
if (VersionHelper.isOrAbove1_20_2()) {
Object clientInfo = NetworkReflections.field$ServerboundClientInformationPacket$information.get(packet);
if (clientInfo == null) return;
String locale = (String) CoreReflections.field$ClientInformation$language.get(clientInfo);
if (locale == null) return;
((BukkitServerPlayer) user).setClientLocale(TranslationManager.parseLocale(locale));
} else {
String locale = (String) NetworkReflections.field$ServerboundClientInformationPacket$language.get(packet);
if (locale == null) return;
((BukkitServerPlayer) user).setClientLocale(TranslationManager.parseLocale(locale));
}
} catch (ReflectiveOperationException e) {
CraftEngine.instance().logger().warn("Failed to handle ServerboundClientInformationPacket", e);
}
}
}
public static class SetCreativeSlotListener implements NMSPacketListener {

View File

@@ -1087,20 +1087,31 @@ public final class NetworkReflections {
ReflectionUtils.getDeclaredConstructor(clazz$ClientboundMoveEntityPacket$Pos, int.class, short.class, short.class, short.class, boolean.class)
);
// 1.20.2+
public static final Class<?> clazz$ServerboundClientInformationPacket =
ReflectionUtils.getClazz(BukkitReflectionUtils.assembleMCClass("network.protocol.common.ServerboundClientInformationPacket"));
// 1.20.1
public static final Class<?> clazz$ServerboundClientInformationPacket0 =
BukkitReflectionUtils.findReobfOrMojmapClass(
"network.protocol.game.PacketPlayInSettings",
"network.protocol.game.ServerboundClientInformationPacket"
);
// 1.20.1
public static final Field field$ServerboundClientInformationPacket$language = MiscUtils.requireNonNullIf(Optional.ofNullable(clazz$ServerboundClientInformationPacket0)
.map(it -> ReflectionUtils.getDeclaredField(it, String.class, 0))
.orElse(null), !VersionHelper.isOrAbove1_20_2());
// 1.20.2+
public static final Constructor<?> constructor$ServerboundClientInformationPacket = Optional.ofNullable(clazz$ServerboundClientInformationPacket)
.map(it -> ReflectionUtils.getConstructor(it, 1))
.orElse(null);
public static final Class<?> clazz$ServerboundClientInformationPacket1 = MiscUtils.requireNonNullIf(
ReflectionUtils.getClazz(BukkitReflectionUtils.assembleMCClass("network.protocol.common.ServerboundClientInformationPacket")),
VersionHelper.isOrAbove1_20_2()
);
// 1.20.2+
public static final Field field$ServerboundClientInformationPacket$information = Optional.ofNullable(clazz$ServerboundClientInformationPacket)
.map(it -> ReflectionUtils.getDeclaredField(it, 0))
.orElse(null);
public static final Field field$ServerboundClientInformationPacket$information = MiscUtils.requireNonNullIf(
Optional.ofNullable(clazz$ServerboundClientInformationPacket1)
.map(it -> ReflectionUtils.getDeclaredField(it, CoreReflections.clazz$ClientInformation, 0))
.orElse(null),
VersionHelper.isOrAbove1_20_2()
);
public static final Class<?> clazz$ClientboundSetTitleTextPacket = requireNonNull(
ReflectionUtils.getClazz(

View File

@@ -127,9 +127,11 @@ public class BukkitServerPlayer extends Player {
private ConcurrentLong2ReferenceChainedHashTable<ChunkStatus> trackedChunks;
// entity view
private Map<Integer, EntityPacketHandler> entityTypeView;
// selected client locale
// 通过指令或api设定的语言
@Nullable
private Locale selectedLocale;
// 客户端选择的语言
private Locale clientLocale;
// 存储客户端在发送停止破坏包前正在破坏的最后一个方块
private BlockPos lastStopMiningPos;
// 修复连续挖掘的标志位
@@ -1233,7 +1235,21 @@ public class BukkitServerPlayer extends Player {
@Override
public Locale locale() {
return this.platformPlayer().locale();
if (this.clientLocale != null) {
return this.clientLocale;
} else {
org.bukkit.entity.Player player = this.platformPlayer();
if (player != null) {
return player.locale();
} else {
return Locale.US;
}
}
}
@Override
public void setClientLocale(Locale clientLocale) {
this.clientLocale = clientLocale;
}
@Override

View File

@@ -180,6 +180,8 @@ public abstract class Player extends AbstractEntity implements NetWorkUser {
public abstract Locale locale();
public abstract void setClientLocale(Locale clientLocale);
public abstract Locale selectedLocale();
public abstract void setSelectedLocale(@Nullable Locale locale);