diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/Protocol1_20_5To1_20_3.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/Protocol1_20_5To1_20_3.java index f774b9c8c..2d2b17ab0 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/Protocol1_20_5To1_20_3.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/Protocol1_20_5To1_20_3.java @@ -22,9 +22,11 @@ import com.viaversion.viaversion.api.minecraft.RegistryType; import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey; import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5; import com.viaversion.viaversion.api.protocol.AbstractProtocol; +import com.viaversion.viaversion.api.protocol.packet.PacketWrapper; import com.viaversion.viaversion.api.protocol.packet.State; import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider; import com.viaversion.viaversion.api.protocol.packet.provider.SimplePacketTypesProvider; +import com.viaversion.viaversion.api.protocol.remapper.PacketHandler; import com.viaversion.viaversion.api.type.Type; import com.viaversion.viaversion.api.type.types.misc.ParticleType; import com.viaversion.viaversion.api.type.types.version.Types1_20_5; @@ -91,21 +93,47 @@ public final class Protocol1_20_5To1_20_3 extends AbstractProtocol wrapper.user().get(AcknowledgedMessagesStorage.class).add()); + registerClientbound(ClientboundPackets1_20_3.PLAYER_CHAT, wrapper -> { + wrapper.passthrough(Type.UUID); // Sender + wrapper.passthrough(Type.VAR_INT); // Index + final byte[] signature = wrapper.passthrough(Type.OPTIONAL_SIGNATURE_BYTES); + + final AcknowledgedMessagesStorage storage = wrapper.user().get(AcknowledgedMessagesStorage.class); + if (signature != null && signature.length != 0) { + if (storage.add(signature) && storage.offset() > 64) { + final PacketWrapper chatAck = wrapper.create(ServerboundPackets1_20_3.CHAT_ACK); + chatAck.write(Type.VAR_INT, storage.offset()); + chatAck.sendToServer(Protocol1_20_5To1_20_3.class); + + storage.clearOffset(); + } + } + }); registerServerbound(ServerboundPackets1_20_5.CHAT_MESSAGE, wrapper -> wrapper.user().get(AcknowledgedMessagesStorage.class).clearOffset()); - registerServerbound(ServerboundPackets1_20_5.CHAT_ACK, wrapper -> wrapper.user().get(AcknowledgedMessagesStorage.class).clearOffset()); - registerServerbound(ServerboundPackets1_20_5.CHAT_COMMAND_SIGNED, ServerboundPackets1_20_3.CHAT_COMMAND); + registerServerbound(ServerboundPackets1_20_5.CHAT_COMMAND_SIGNED, ServerboundPackets1_20_3.CHAT_COMMAND, wrapper -> { + wrapper.passthrough(Type.STRING); // Command + wrapper.passthrough(Type.LONG); // Timestamp + wrapper.passthrough(Type.LONG); // Salt + final int signatures = wrapper.passthrough(Type.VAR_INT); + for (int i = 0; i < signatures; i++) { + wrapper.passthrough(Type.STRING); // Argument name + wrapper.passthrough(Type.SIGNATURE_BYTES); // Signature + } + + wrapper.read(Type.VAR_INT); // Offset + wrapper.read(Type.ACKNOWLEDGED_BIT_SET); // Acknowledged + getChatAckHandler().handle(wrapper); + }); registerServerbound(ServerboundPackets1_20_5.CHAT_COMMAND, wrapper -> { wrapper.passthrough(Type.STRING); // Command - final AcknowledgedMessagesStorage messagesStorage = wrapper.user().get(AcknowledgedMessagesStorage.class); wrapper.write(Type.LONG, System.currentTimeMillis()); // Timestamp wrapper.write(Type.LONG, 0L); // Salt wrapper.write(Type.VAR_INT, 0); // No signatures - wrapper.write(Type.VAR_INT, messagesStorage.offset()); // TODO Fix offset - wrapper.write(Type.ACKNOWLEDGED_BIT_SET, messagesStorage.toAck()); - messagesStorage.clearOffset(); + getChatAckHandler().handle(wrapper); }); + cancelServerbound(ServerboundPackets1_20_5.CHAT_ACK); + registerClientbound(ClientboundPackets1_20_3.START_CONFIGURATION, wrapper -> wrapper.user().put(new AcknowledgedMessagesStorage())); new CommandRewriter1_19_4<>(this).registerDeclareCommands1_19(ClientboundPackets1_20_3.DECLARE_COMMANDS); @@ -117,6 +145,15 @@ public final class Protocol1_20_5To1_20_3 extends AbstractProtocol { + final AcknowledgedMessagesStorage storage = wrapper.user().get(AcknowledgedMessagesStorage.class); + wrapper.write(Type.VAR_INT, storage.offset()); + wrapper.write(Type.ACKNOWLEDGED_BIT_SET, storage.toAck()); + storage.clearOffset(); + }; + } + @Override protected void onMappingDataLoaded() { super.onMappingDataLoaded(); diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/rewriter/StructuredDataConverter.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/rewriter/StructuredDataConverter.java index 085c85dc0..cd566c892 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/rewriter/StructuredDataConverter.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/rewriter/StructuredDataConverter.java @@ -513,6 +513,7 @@ public final class StructuredDataConverter { } // If multiple item components which previously were stored in BlockEntityTag are present, we need to merge them + private static CompoundTag getBlockEntityTag(final CompoundTag tag) { return getOrCreate(tag, "BlockEntityTag"); } diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/storage/AcknowledgedMessagesStorage.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/storage/AcknowledgedMessagesStorage.java index 6f81c91dc..ca4586fca 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/storage/AcknowledgedMessagesStorage.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/storage/AcknowledgedMessagesStorage.java @@ -18,6 +18,7 @@ package com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.storage; import com.viaversion.viaversion.api.connection.StorableObject; +import java.util.Arrays; import java.util.BitSet; public final class AcknowledgedMessagesStorage implements StorableObject { @@ -25,11 +26,17 @@ public final class AcknowledgedMessagesStorage implements StorableObject { private final boolean[] trackedMessages = new boolean[MAX_HISTORY]; private int offset; private int tail; + private byte[] lastMessage; - public void add() { + public boolean add(final byte[] message) { + if (Arrays.equals(message, lastMessage)) { + return false; + } + this.lastMessage = message; this.offset++; this.trackedMessages[this.tail] = true; this.tail = (this.tail + 1) % MAX_HISTORY; + return true; } public BitSet toAck() {