From b4a3f12bfeee4d2efde6626cdcef37d074c5d8af Mon Sep 17 00:00:00 2001 From: MATRIX-feather Date: Tue, 26 Nov 2024 00:30:42 +0800 Subject: [PATCH] =?UTF-8?q?misc:=20=E6=B7=BB=E5=8A=A0=E5=AF=B9=E6=97=A7?= =?UTF-8?q?=E7=89=88=E6=B6=88=E6=81=AF=E5=BA=8F=E5=88=97=E5=8C=96=E6=96=B9?= =?UTF-8?q?=E6=A1=88=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../network/server/MorphClientHandler.java | 156 ++++++++++-------- .../handlers/LegacyCommandPacketHandler.java | 21 ++- 2 files changed, 107 insertions(+), 70 deletions(-) diff --git a/src/main/java/xyz/nifeather/morph/network/server/MorphClientHandler.java b/src/main/java/xyz/nifeather/morph/network/server/MorphClientHandler.java index c5db1be4..4412d000 100644 --- a/src/main/java/xyz/nifeather/morph/network/server/MorphClientHandler.java +++ b/src/main/java/xyz/nifeather/morph/network/server/MorphClientHandler.java @@ -1,10 +1,7 @@ package xyz.nifeather.morph.network.server; -import com.google.common.io.ByteStreams; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.kyori.adventure.text.Component; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket; @@ -47,6 +44,7 @@ import xyz.nifeather.morph.network.server.handlers.ICommandPacketHandler; import xyz.nifeather.morph.network.server.handlers.LegacyCommandPacketHandler; +import java.nio.charset.StandardCharsets; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; @@ -69,12 +67,16 @@ public boolean logInComingPackets() return logInComingPackets.get(); } - private void sendPacket(String channel, Player player, String message) + private void sendPacket(String channel, Player player, String message, boolean legacy) { - var buffer = new FriendlyByteBuf(Unpooled.buffer()).writeUtf(message); + var buffer = new FriendlyByteBuf(Unpooled.buffer()); + if (!legacy) + buffer.writeUtf(message); + else + buffer.writeBytes(message.getBytes(StandardCharsets.UTF_8)); if (logOutGoingPackets.get()) - logPacket(true, player, channel, message, buffer.array().length); + logPacket(true, player, channel, message, buffer.readableBytes()); this.sendPacketRaw(channel, player, buffer, false); } @@ -192,15 +194,17 @@ private void load(MorphPlugin plugin, MorphConfigManager configManager) var messenger = Bukkit.getMessenger(); - // 注册init频道处理 + // 注册incoming频道 messenger.registerIncomingPluginChannel(plugin, MessageChannel.initializeChannel, this::handleInitializeMessage); - // 注册api频道处理 messenger.registerIncomingPluginChannel(plugin, MessageChannel.versionChannel, this::handleVersionMessage); - - // 注册command频道处理 messenger.registerIncomingPluginChannel(plugin, MessageChannel.commandChannel, this::handleCommandMessage); + // Legacy incoming channels + // todo: Remove legacy packetbuf support along with 1.23 update + messenger.registerIncomingPluginChannel(plugin, MessageChannel.versionChannelLegacy, this::handleVersionMessageLegacy); + messenger.registerIncomingPluginChannel(plugin, MessageChannel.commandChannelLegacy, this::handleCommandMessageLegacy); + // 注册outgoing频道 messenger.registerOutgoingPluginChannel(plugin, MessageChannel.initializeChannel); messenger.registerOutgoingPluginChannel(plugin, MessageChannel.versionChannel); @@ -294,17 +298,17 @@ public void handleInitializeMessage(@NotNull String cN, @NotNull Player player, session.initializeState = InitializeState.HANDSHAKE; session.isLegacyPacketBuf = isLegacyBuf; - this.sendPacket(MessageChannel.initializeChannel, player, newProtocolIdentify); + this.sendPacket(MessageChannel.initializeChannel, player, newProtocolIdentify, isLegacyBuf); } - public void handleVersionMessage(@NotNull String cN, @NotNull Player player, byte @NotNull [] data) + private void handleVersionInput(ICommandPacketHandler commandPacketHandler, String sourceChannel, Player player, byte[] data) { if (!allowClient.get()) return; if (logInComingPackets.get()) - logPacket(false, player, cN, data); + logPacket(false, player, sourceChannel, data); - var result = CommandPacketHandler.INSTANCE.handleVersionData(player, data); + var result = commandPacketHandler.handleVersionData(player, data); if (!result.success()) { logger.info("Packet decode failed for player %s, Rejecting...".formatted(player.getName())); @@ -346,21 +350,23 @@ public void handleVersionMessage(@NotNull String cN, @NotNull Player player, byt var session = this.getOrCreateSession(player); session.initializeState = InitializeState.API_CHECKED; - this.sendPacket(MessageChannel.versionChannel, player, targetApiVersion); + if (!session.isLegacyPacketBuf) + this.sendPacket(MessageChannel.versionChannel, player, targetApiVersion); + else + this.sendPacket(MessageChannel.versionChannelLegacy, player, targetApiVersion); } - public void handleCommandMessage(@NotNull String cN, @NotNull Player player, byte @NotNull [] data) + private void handleCommandInput(ICommandPacketHandler commandPacketHandler, String sourceChannel, Player player, byte[] data) { if (!allowClient.get()) return; if (logInComingPackets.get()) - logPacket(false, player, cN, data); + logPacket(false, player, sourceChannel, data); - //在API检查完成之前忽略客户端的所有指令 - if (this.getPlayerConnectionState(player).worseThan(InitializeState.API_CHECKED)) - return; + var session = getSession(player); + if (session == null || session.initializeState.worseThan(InitializeState.API_CHECKED)) return; - var result = CommandPacketHandler.INSTANCE.handleCommandData(player, data); + var result = commandPacketHandler.handleCommandData(player, data); if (!result.success()) { logger.info("Packet decode failed for player %s, Rejecting...".formatted(player.getName())); @@ -368,7 +374,7 @@ public void handleCommandMessage(@NotNull String cN, @NotNull Player player, byt return; } - var input = result.result(); + String input = result.result(); var str = input.split(" ", 2); @@ -388,17 +394,38 @@ public void handleCommandMessage(@NotNull String cN, @NotNull Player player, byt } else { - logger.warn("Unknown server command: " + baseCommand); + logger.warn("Unknown server command '%s', rejecting...".formatted(baseCommand)); + rejectPlayer(player); } } - private final Map playerSessionMap = new ConcurrentHashMap<>(); + private void handleCommandMessageLegacy(@NotNull String cN, @NotNull Player player, @NotNull byte[] data) + { + this.handleCommandInput(LegacyCommandPacketHandler.INSTANCE, cN, player, data); + } + + private void handleVersionMessageLegacy(@NotNull String cN, @NotNull Player player, @NotNull byte[] data) + { + this.handleVersionInput(LegacyCommandPacketHandler.INSTANCE, cN, player, data); + } + + public void handleVersionMessage(@NotNull String cN, @NotNull Player player, byte @NotNull [] data) + { + this.handleVersionInput(CommandPacketHandler.INSTANCE, cN, player, data); + } + + public void handleCommandMessage(@NotNull String cN, @NotNull Player player, byte @NotNull [] data) + { + this.handleCommandInput(CommandPacketHandler.INSTANCE, cN, player, data); + } + + private final Map playerSessionMap = new ConcurrentHashMap<>(); private PlayerSession createSession(Player player, boolean isUsingLegacyBuf) { var uuid = player.getUniqueId(); - var cached = playerSessionMap.getOrDefault(uuid, null); + var cached = playerSessionMap.getOrDefault(player, null); if (cached != null) return cached; @@ -408,14 +435,14 @@ private PlayerSession createSession(Player player, boolean isUsingLegacyBuf) .isLegacy(isUsingLegacyBuf) .build(); - playerSessionMap.put(uuid, instance); + playerSessionMap.put(player, instance); return instance; } @Nullable public PlayerSession getSession(Player player) { - return playerSessionMap.getOrDefault(player.getUniqueId(), null); + return playerSessionMap.getOrDefault(player, null); } @NotNull @@ -689,14 +716,7 @@ public boolean isPlayerConnected(Player player) @Override public List getConnectedPlayers() { - var list = new ObjectArrayList(); - for (UUID uuid : this.playerSessionMap.keySet()) - { - var player = Bukkit.getPlayer(uuid); - if (player != null) list.add(player); - } - - return list; + return playerSessionMap.keySet().stream().toList(); } //endregion Player Status/Option @@ -714,7 +734,14 @@ private boolean sendCommand(Player player, AbstractS2CCommand command, boolea if ((!allowClient.get() || !this.clientConnected(player)) && !forceSend) return false; - this.sendPacket(MessageChannel.commandChannel, player, cmd); + var session = this.getSession(player); + var isLegacy = session == null || session.isLegacyPacketBuf; + + if (!isLegacy) + this.sendPacket(MessageChannel.commandChannel, player, cmd, false); + else + this.sendPacket(MessageChannel.commandChannelLegacy, player, cmd, true); + return true; } @@ -737,47 +764,44 @@ public void onInitialCommand(C2SInitialCommand c2SInitialCommand) if (session.connectionState != ConnectionState.JOINED) session.connectionState = ConnectionState.CONNECTING; - this.waitUntilReady(player, () -> - { - //再检查一遍玩家有没有初始化完成 - if (clientInitialized(player)) - return; + //再检查一遍玩家有没有初始化完成 + if (clientInitialized(player)) + return; - var config = manager.getPlayerMeta(player); - var list = config.getUnlockedDisguiseIdentifiers(); - refreshPlayerClientMorphs(list, player); + var config = manager.getPlayerMeta(player); + var list = config.getUnlockedDisguiseIdentifiers(); + refreshPlayerClientMorphs(list, player); - var state = manager.getDisguiseStateFor(player); + var state = manager.getDisguiseStateFor(player); - if (state != null) - manager.refreshClientState(state); + if (state != null) + manager.refreshClientState(state); - sendCommand(player, new S2CSetSelfViewingCommand(config.showDisguiseToSelf)); - sendCommand(player, new S2CSetModifyBoundingBoxCommand(modifyBoundingBoxes.get())); + sendCommand(player, new S2CSetSelfViewingCommand(config.showDisguiseToSelf)); + sendCommand(player, new S2CSetModifyBoundingBoxCommand(modifyBoundingBoxes.get())); - if (player.hasPermission(CommonPermissions.DISGUISE_REVEALING)) - sendCommand(player, manager.genMapCommand()); + if (player.hasPermission(CommonPermissions.DISGUISE_REVEALING)) + sendCommand(player, manager.genMapCommand()); - //TODO: 独立客户端渲染器 - if (state != null && state.getDisguiseWrapper().getBackend().dependsClientRenderer()) - { - sendCommand(player, manager.genRenderSyncCommand()); + //TODO: 独立客户端渲染器 + if (state != null && state.getDisguiseWrapper().getBackend().dependsClientRenderer()) + { + sendCommand(player, manager.genRenderSyncCommand()); - var disguises = manager.getActiveDisguises(); - for (DisguiseState bindingState : disguises) - { - var bindingPlayer = bindingState.getPlayer(); + var disguises = manager.getActiveDisguises(); + for (DisguiseState bindingState : disguises) + { + var bindingPlayer = bindingState.getPlayer(); - var packet = networkingHelper.prepareMeta(bindingPlayer) - .forDisguiseState(bindingState) - .build(); + var packet = networkingHelper.prepareMeta(bindingPlayer) + .forDisguiseState(bindingState) + .build(); - this.sendCommand(player, packet); - } + this.sendCommand(player, packet); } + } - session.initializeState = InitializeState.DONE; - }); + session.initializeState = InitializeState.DONE; } @Override diff --git a/src/main/java/xyz/nifeather/morph/network/server/handlers/LegacyCommandPacketHandler.java b/src/main/java/xyz/nifeather/morph/network/server/handlers/LegacyCommandPacketHandler.java index da64b101..32eac477 100644 --- a/src/main/java/xyz/nifeather/morph/network/server/handlers/LegacyCommandPacketHandler.java +++ b/src/main/java/xyz/nifeather/morph/network/server/handlers/LegacyCommandPacketHandler.java @@ -1,24 +1,37 @@ package xyz.nifeather.morph.network.server.handlers; -import org.apache.commons.lang.NotImplementedException; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import xyz.nifeather.morph.network.server.handlers.results.CommandHandleResult; import xyz.nifeather.morph.network.server.handlers.results.VersionHandleResult; -public class LegacyCommandPacketHandler implements ICommandPacketHandler +import java.nio.charset.StandardCharsets; + +public class LegacyCommandPacketHandler extends AbstractCommandPacketHandler { + public static final LegacyCommandPacketHandler INSTANCE = new LegacyCommandPacketHandler(); + @Override @NotNull public VersionHandleResult handleVersionData(Player player, byte @NotNull [] rawData) { - throw new NotImplementedException(); + try + { + var clientVersionStr = new String(rawData, StandardCharsets.UTF_8); + + return VersionHandleResult.from(Integer.parseInt(clientVersionStr)); + } + catch (Throwable t) + { + logger.error("Failed to decode client version from legacy buffer: " + t.getMessage()); + return VersionHandleResult.fail(); + } } @Override @NotNull public CommandHandleResult handleCommandData(Player player, byte @NotNull [] rawData) { - throw new NotImplementedException(); + return CommandHandleResult.from(new String(rawData, StandardCharsets.UTF_8)); } }