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 FinishConfigurationListener(), NetworkReflections.clazz$ClientboundFinishConfigurationPacket);
registerNMSPacketConsumer(new LoginFinishedListener(), NetworkReflections.clazz$ClientboundLoginFinishedPacket); registerNMSPacketConsumer(new LoginFinishedListener(), NetworkReflections.clazz$ClientboundLoginFinishedPacket);
registerNMSPacketConsumer(new UpdateTagsListener(), NetworkReflections.clazz$ClientboundUpdateTagsPacket); 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); registerNMSPacketConsumer(new ContainerClickListener1_21_5(), VersionHelper.isOrAbove1_21_5() ? NetworkReflections.clazz$ServerboundContainerClickPacket : null);
registerS2CGamePacketListener(new ForgetLevelChunkListener(), this.packetIds.clientboundForgetLevelChunkPacket(), "ClientboundForgetLevelChunkPacket"); registerS2CGamePacketListener(new ForgetLevelChunkListener(), this.packetIds.clientboundForgetLevelChunkPacket(), "ClientboundForgetLevelChunkPacket");
registerS2CGamePacketListener(new SetScoreListener1_20_3(), VersionHelper.isOrAbove1_20_3() ? this.packetIds.clientboundSetScorePacket() : -1, "ClientboundSetScorePacket"); 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 { 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) ReflectionUtils.getDeclaredConstructor(clazz$ClientboundMoveEntityPacket$Pos, int.class, short.class, short.class, short.class, boolean.class)
); );
// 1.20.2+ // 1.20.1
public static final Class<?> clazz$ServerboundClientInformationPacket = public static final Class<?> clazz$ServerboundClientInformationPacket0 =
ReflectionUtils.getClazz(BukkitReflectionUtils.assembleMCClass("network.protocol.common.ServerboundClientInformationPacket")); 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+ // 1.20.2+
public static final Constructor<?> constructor$ServerboundClientInformationPacket = Optional.ofNullable(clazz$ServerboundClientInformationPacket) public static final Class<?> clazz$ServerboundClientInformationPacket1 = MiscUtils.requireNonNullIf(
.map(it -> ReflectionUtils.getConstructor(it, 1)) ReflectionUtils.getClazz(BukkitReflectionUtils.assembleMCClass("network.protocol.common.ServerboundClientInformationPacket")),
.orElse(null); VersionHelper.isOrAbove1_20_2()
);
// 1.20.2+ // 1.20.2+
public static final Field field$ServerboundClientInformationPacket$information = Optional.ofNullable(clazz$ServerboundClientInformationPacket) public static final Field field$ServerboundClientInformationPacket$information = MiscUtils.requireNonNullIf(
.map(it -> ReflectionUtils.getDeclaredField(it, 0)) Optional.ofNullable(clazz$ServerboundClientInformationPacket1)
.orElse(null); .map(it -> ReflectionUtils.getDeclaredField(it, CoreReflections.clazz$ClientInformation, 0))
.orElse(null),
VersionHelper.isOrAbove1_20_2()
);
public static final Class<?> clazz$ClientboundSetTitleTextPacket = requireNonNull( public static final Class<?> clazz$ClientboundSetTitleTextPacket = requireNonNull(
ReflectionUtils.getClazz( ReflectionUtils.getClazz(

View File

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

View File

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