From 8e8f52009d2a9f204f25a2c8cfef05532a934533 Mon Sep 17 00:00:00 2001 From: Frederik van der Els <49305700+xpple@users.noreply.github.com> Date: Tue, 11 Jun 2024 22:38:53 +0200 Subject: [PATCH] Rely on ClientboundPlayerChatPacket for C2C packets (#641) --- .../clientcommands/c2c/C2CPacket.java | 7 ++++ .../clientcommands/c2c/C2CPacketHandler.java | 14 +++++-- .../c2c/packets/MessageC2CPacket.java | 3 +- .../packets/PutTicTacToeMarkC2CPacket.java | 3 +- .../packets/StartTicTacToeGameC2CPacket.java | 3 +- ...onentMixin.java => ChatListenerMixin.java} | 40 +++++++++---------- src/main/resources/mixins.clientcommands.json | 2 +- 7 files changed, 42 insertions(+), 30 deletions(-) create mode 100644 src/main/java/net/earthcomputer/clientcommands/c2c/C2CPacket.java rename src/main/java/net/earthcomputer/clientcommands/mixin/c2c/{ChatComponentMixin.java => ChatListenerMixin.java} (52%) diff --git a/src/main/java/net/earthcomputer/clientcommands/c2c/C2CPacket.java b/src/main/java/net/earthcomputer/clientcommands/c2c/C2CPacket.java new file mode 100644 index 000000000..1b1c99e4e --- /dev/null +++ b/src/main/java/net/earthcomputer/clientcommands/c2c/C2CPacket.java @@ -0,0 +1,7 @@ +package net.earthcomputer.clientcommands.c2c; + +import net.minecraft.network.protocol.Packet; + +public interface C2CPacket extends Packet { + String sender(); +} diff --git a/src/main/java/net/earthcomputer/clientcommands/c2c/C2CPacketHandler.java b/src/main/java/net/earthcomputer/clientcommands/c2c/C2CPacketHandler.java index 701240f2c..1afe41abf 100644 --- a/src/main/java/net/earthcomputer/clientcommands/c2c/C2CPacketHandler.java +++ b/src/main/java/net/earthcomputer/clientcommands/c2c/C2CPacketHandler.java @@ -51,6 +51,8 @@ public class C2CPacketHandler implements C2CPacketListener { .addPacket(PutTicTacToeMarkC2CPacket.ID, PutTicTacToeMarkC2CPacket.CODEC) ); + public static final String C2C_PACKET_HEADER = "CCΕNC:"; + private static final C2CPacketHandler instance = new C2CPacketHandler(); private C2CPacketHandler() { @@ -106,7 +108,7 @@ public void sendPacket(Packet packet, PlayerInfo recipient) t System.arraycopy(encrypted[i], 0, joined, i * 256, 256); } String packetString = ConversionHelper.BaseUTF8.toUnicode(joined); - String commandString = "w " + recipient.getProfile().getName() + " CCENC:" + packetString; + String commandString = "w " + recipient.getProfile().getName() + ' ' + C2C_PACKET_HEADER + packetString; if (commandString.length() >= SharedConstants.MAX_CHAT_LENGTH) { throw MESSAGE_TOO_LONG_EXCEPTION.create(commandString.length()); } @@ -115,7 +117,7 @@ public void sendPacket(Packet packet, PlayerInfo recipient) t OutgoingPacketFilter.addPacket(packetString); } - public static boolean handleC2CPacket(String content) { + public static boolean handleC2CPacket(String content, String sender) { byte[] encrypted = ConversionHelper.BaseUTF8.fromUnicode(content); // round down to multiple of 256 bytes int length = encrypted.length & ~0xFF; @@ -157,9 +159,9 @@ public static boolean handleC2CPacket(String content) { return false; } FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.wrappedBuffer(uncompressed)); - Packet packet; + C2CPacket packet; try { - packet = protocolInfo.codec().decode(buf); + packet = (C2CPacket) protocolInfo.codec().decode(buf); } catch (Throwable e) { LOGGER.error("Error decoding C2C packet", e); return false; @@ -168,6 +170,10 @@ public static boolean handleC2CPacket(String content) { LOGGER.error("Found extra bytes while reading C2C packet {}", packet.type()); return false; } + if (!packet.sender().equals(sender)) { + LOGGER.error("Detected mismatching packet sender. Expected {}, got {}", sender, packet.sender()); + return false; + } ListenCommand.onPacket(packet, ListenCommand.PacketFlow.C2C_INBOUND); try { packet.handle(C2CPacketHandler.getInstance()); diff --git a/src/main/java/net/earthcomputer/clientcommands/c2c/packets/MessageC2CPacket.java b/src/main/java/net/earthcomputer/clientcommands/c2c/packets/MessageC2CPacket.java index ba44756b6..d7aa0b791 100644 --- a/src/main/java/net/earthcomputer/clientcommands/c2c/packets/MessageC2CPacket.java +++ b/src/main/java/net/earthcomputer/clientcommands/c2c/packets/MessageC2CPacket.java @@ -1,5 +1,6 @@ package net.earthcomputer.clientcommands.c2c.packets; +import net.earthcomputer.clientcommands.c2c.C2CPacket; import net.earthcomputer.clientcommands.c2c.C2CPacketListener; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf; @@ -9,7 +10,7 @@ import net.minecraft.network.protocol.PacketType; import net.minecraft.resources.ResourceLocation; -public record MessageC2CPacket(String sender, String message) implements Packet { +public record MessageC2CPacket(String sender, String message) implements C2CPacket { public static final StreamCodec CODEC = Packet.codec(MessageC2CPacket::write, MessageC2CPacket::new); public static final PacketType ID = new PacketType<>(PacketFlow.CLIENTBOUND, new ResourceLocation("clientcommands", "message")); diff --git a/src/main/java/net/earthcomputer/clientcommands/c2c/packets/PutTicTacToeMarkC2CPacket.java b/src/main/java/net/earthcomputer/clientcommands/c2c/packets/PutTicTacToeMarkC2CPacket.java index 1bac5f3a8..8470faf8a 100644 --- a/src/main/java/net/earthcomputer/clientcommands/c2c/packets/PutTicTacToeMarkC2CPacket.java +++ b/src/main/java/net/earthcomputer/clientcommands/c2c/packets/PutTicTacToeMarkC2CPacket.java @@ -1,5 +1,6 @@ package net.earthcomputer.clientcommands.c2c.packets; +import net.earthcomputer.clientcommands.c2c.C2CPacket; import net.earthcomputer.clientcommands.c2c.C2CPacketListener; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf; @@ -9,7 +10,7 @@ import net.minecraft.network.protocol.PacketType; import net.minecraft.resources.ResourceLocation; -public record PutTicTacToeMarkC2CPacket(String sender, byte x, byte y) implements Packet { +public record PutTicTacToeMarkC2CPacket(String sender, byte x, byte y) implements C2CPacket { public static final StreamCodec CODEC = Packet.codec(PutTicTacToeMarkC2CPacket::write, PutTicTacToeMarkC2CPacket::new); public static final PacketType ID = new PacketType<>(PacketFlow.CLIENTBOUND, new ResourceLocation("clientcommands", "put_tic_tac_toe_mark")); diff --git a/src/main/java/net/earthcomputer/clientcommands/c2c/packets/StartTicTacToeGameC2CPacket.java b/src/main/java/net/earthcomputer/clientcommands/c2c/packets/StartTicTacToeGameC2CPacket.java index 5d375ae5f..43db41226 100644 --- a/src/main/java/net/earthcomputer/clientcommands/c2c/packets/StartTicTacToeGameC2CPacket.java +++ b/src/main/java/net/earthcomputer/clientcommands/c2c/packets/StartTicTacToeGameC2CPacket.java @@ -1,5 +1,6 @@ package net.earthcomputer.clientcommands.c2c.packets; +import net.earthcomputer.clientcommands.c2c.C2CPacket; import net.earthcomputer.clientcommands.c2c.C2CPacketListener; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf; @@ -9,7 +10,7 @@ import net.minecraft.network.protocol.PacketType; import net.minecraft.resources.ResourceLocation; -public record StartTicTacToeGameC2CPacket(String sender, boolean accept) implements Packet { +public record StartTicTacToeGameC2CPacket(String sender, boolean accept) implements C2CPacket { public static final StreamCodec CODEC = Packet.codec(StartTicTacToeGameC2CPacket::write, StartTicTacToeGameC2CPacket::new); public static final PacketType ID = new PacketType<>(PacketFlow.CLIENTBOUND, new ResourceLocation("clientcommands", "start_tic_tac_toe_game")); diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/c2c/ChatComponentMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/c2c/ChatListenerMixin.java similarity index 52% rename from src/main/java/net/earthcomputer/clientcommands/mixin/c2c/ChatComponentMixin.java rename to src/main/java/net/earthcomputer/clientcommands/mixin/c2c/ChatListenerMixin.java index 723c3b4f9..7d27b11e8 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/c2c/ChatComponentMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/c2c/ChatListenerMixin.java @@ -1,56 +1,52 @@ package net.earthcomputer.clientcommands.mixin.c2c; +import com.mojang.authlib.GameProfile; import net.earthcomputer.clientcommands.Configs; import net.earthcomputer.clientcommands.c2c.C2CPacketHandler; import net.earthcomputer.clientcommands.c2c.OutgoingPacketFilter; import net.minecraft.ChatFormatting; -import net.minecraft.client.GuiMessageTag; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.components.ChatComponent; +import net.minecraft.client.multiplayer.chat.ChatListener; +import net.minecraft.network.chat.ChatType; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.HoverEvent; -import net.minecraft.network.chat.MessageSignature; +import net.minecraft.network.chat.PlayerChatMessage; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -@Mixin(ChatComponent.class) -public class ChatComponentMixin { +import java.time.Instant; +@Mixin(ChatListener.class) +public class ChatListenerMixin { @Shadow @Final private Minecraft minecraft; - @Inject(method = "addMessage(Lnet/minecraft/network/chat/Component;Lnet/minecraft/network/chat/MessageSignature;Lnet/minecraft/client/GuiMessageTag;)V", at = @At("HEAD"), cancellable = true) - private void onC2CPacket(Component message, MessageSignature signature, GuiMessageTag tag, CallbackInfo ci) { - handleIfPacket(message, ci); - } - - @Unique - private void handleIfPacket(Component content, CallbackInfo ci) { - String string = content.getString(); - int index = string.indexOf("CCENC:"); + @Inject(method = "showMessageToPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/chat/ChatTrustLevel;createTag(Lnet/minecraft/network/chat/PlayerChatMessage;)Lnet/minecraft/client/GuiMessageTag;"), cancellable = true) + private void onC2CPacket(ChatType.Bound boundChatType, PlayerChatMessage chatMessage, Component decoratedServerContent, GameProfile gameProfile, boolean onlyShowSecureChat, Instant timestamp, CallbackInfoReturnable cir) { + String string = chatMessage.signedContent(); + int index = string.indexOf(C2CPacketHandler.C2C_PACKET_HEADER); if (index == -1) { return; } - String packetString = string.substring(index + 6); + String packetString = string.substring(index + C2CPacketHandler.C2C_PACKET_HEADER.length()); if (!Configs.acceptC2CPackets) { if (OutgoingPacketFilter.removeIfContains(packetString)) { this.minecraft.gui.getChat().addMessage(Component.translatable("c2cpacket.sentC2CPacket")); } else { - this.minecraft.gui.getChat().addMessage(Component.translatable("c2cpacket.receivedC2CPacket").withStyle(s -> s.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, content)))); + this.minecraft.gui.getChat().addMessage(Component.translatable("c2cpacket.receivedC2CPacket").withStyle(s -> s.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, boundChatType.decorate(chatMessage.decoratedContent()))))); } - ci.cancel(); + cir.setReturnValue(false); return; } if (OutgoingPacketFilter.removeIfContains(packetString)) { - ci.cancel(); + cir.setReturnValue(false); return; } - if (C2CPacketHandler.handleC2CPacket(packetString)) { - ci.cancel(); + if (C2CPacketHandler.handleC2CPacket(packetString, gameProfile.getName())) { + cir.setReturnValue(true); } else { this.minecraft.gui.getChat().addMessage(Component.translatable("c2cpacket.malformedPacket").withStyle(ChatFormatting.RED)); } diff --git a/src/main/resources/mixins.clientcommands.json b/src/main/resources/mixins.clientcommands.json index df7f8eb86..83a57fea6 100644 --- a/src/main/resources/mixins.clientcommands.json +++ b/src/main/resources/mixins.clientcommands.json @@ -3,7 +3,6 @@ "package": "net.earthcomputer.clientcommands.mixin", "compatibilityLevel": "JAVA_21", "mixins": [ - "c2c.ChatComponentMixin", "commands.enchant.EnchantmentDefinitionMixin", "commands.enchant.EnchantmentHelperMixin", "commands.enchant.EnchantmentScreenMixin", @@ -65,6 +64,7 @@ "requireAnnotations": true }, "client": [ + "c2c.ChatListenerMixin", "c2c.ClientPacketListenerMixin", "commands.alias.ClientSuggestionProviderMixin", "commands.enchant.MultiPlayerGameModeMixin",