diff --git a/src/main/java/net/minestom/server/MinecraftServer.java b/src/main/java/net/minestom/server/MinecraftServer.java index d96556dde..3edfbb63d 100644 --- a/src/main/java/net/minestom/server/MinecraftServer.java +++ b/src/main/java/net/minestom/server/MinecraftServer.java @@ -46,8 +46,8 @@ public final class MinecraftServer { public final static Logger LOGGER = LoggerFactory.getLogger(MinecraftServer.class); - public static final String VERSION_NAME = "1.19.1-pre4"; - public static final int PROTOCOL_VERSION = 1073741921; + public static final String VERSION_NAME = "1.19.1-pre5"; + public static final int PROTOCOL_VERSION = 1073741922; // Threads public static final String THREAD_NAME_BENCHMARK = "Ms-Benchmark"; diff --git a/src/main/java/net/minestom/server/crypto/ArgumentSignatures.java b/src/main/java/net/minestom/server/crypto/ArgumentSignatures.java new file mode 100644 index 000000000..45e8627f9 --- /dev/null +++ b/src/main/java/net/minestom/server/crypto/ArgumentSignatures.java @@ -0,0 +1,35 @@ +package net.minestom.server.crypto; + +import net.minestom.server.utils.binary.BinaryReader; +import net.minestom.server.utils.binary.BinaryWriter; +import net.minestom.server.utils.binary.Writeable; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public record ArgumentSignatures(@NotNull List<@NotNull Entry> entries) implements Writeable { + public ArgumentSignatures { + entries = List.copyOf(entries); + } + + public ArgumentSignatures(BinaryReader reader) { + this(reader.readVarIntList(Entry::new)); + } + + @Override + public void write(@NotNull BinaryWriter writer) { + writer.writeVarIntList(entries, BinaryWriter::write); + } + + public record Entry(@NotNull String name, @NotNull MessageSignature signature) implements Writeable { + public Entry(BinaryReader reader) { + this(reader.readSizedString(), new MessageSignature(reader)); + } + + @Override + public void write(@NotNull BinaryWriter writer) { + writer.writeSizedString(name); + writer.write(signature); + } + } +} diff --git a/src/main/java/net/minestom/server/crypto/LastSeenMessages.java b/src/main/java/net/minestom/server/crypto/LastSeenMessages.java new file mode 100644 index 000000000..5e0742681 --- /dev/null +++ b/src/main/java/net/minestom/server/crypto/LastSeenMessages.java @@ -0,0 +1,50 @@ +package net.minestom.server.crypto; + +import net.minestom.server.utils.binary.BinaryReader; +import net.minestom.server.utils.binary.BinaryWriter; +import net.minestom.server.utils.binary.Writeable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.UUID; + +public record LastSeenMessages(@NotNull List<@NotNull Entry> entries) implements Writeable { + public LastSeenMessages { + entries = List.copyOf(entries); + } + + public LastSeenMessages(BinaryReader reader) { + this(reader.readVarIntList(Entry::new)); + } + + @Override + public void write(@NotNull BinaryWriter writer) { + + } + + public record Entry(UUID uuid, MessageSignature lastSignature) implements Writeable { + public Entry(BinaryReader reader) { + this(reader.readUuid(), new MessageSignature(reader)); + } + + @Override + public void write(@NotNull BinaryWriter writer) { + writer.writeUuid(uuid); + writer.write(lastSignature); + } + } + + public record Update(LastSeenMessages lastSeen, @Nullable Entry lastReceived) implements Writeable { + public Update(BinaryReader reader) { + this(new LastSeenMessages(reader), reader.readBoolean() ? new Entry(reader) : null); + } + + @Override + public void write(@NotNull BinaryWriter writer) { + writer.write(lastSeen); + writer.writeBoolean(lastReceived != null); + if (lastReceived != null) writer.write(lastReceived); + } + } +} diff --git a/src/main/java/net/minestom/server/crypto/MessageSignature.java b/src/main/java/net/minestom/server/crypto/MessageSignature.java index 98a6258cd..70b8496c0 100644 --- a/src/main/java/net/minestom/server/crypto/MessageSignature.java +++ b/src/main/java/net/minestom/server/crypto/MessageSignature.java @@ -3,33 +3,15 @@ package net.minestom.server.crypto; import net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryWriter; import net.minestom.server.utils.binary.Writeable; -import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; -import java.time.Instant; -import java.util.UUID; - -public record MessageSignature(UUID signer, Instant timestamp, long salt, byte[] signature) implements Writeable { - public static final UUID UNSIGNED_SENDER = new UUID(0, 0); - public static final MessageSignature UNSIGNED = new MessageSignature(UNSIGNED_SENDER, Instant.ofEpochMilli(0), 0, new byte[0]); - - public MessageSignature(UUID signer, BinaryReader reader) { - this(signer, Instant.ofEpochMilli(reader.readLong()), reader.readLong(), reader.readByteArray()); - } - - @Contract("_ -> new") - public MessageSignature withSigner(UUID uuid) { - return new MessageSignature(uuid, timestamp, salt, signature); - } - - public boolean unsigned() { - return signer.equals(UNSIGNED_SENDER); +public record MessageSignature(byte @NotNull [] signature) implements Writeable { + public MessageSignature(BinaryReader reader) { + this(reader.readByteArray()); } @Override public void write(@NotNull BinaryWriter writer) { - writer.writeLong(timestamp.toEpochMilli()); - writer.writeLong(salt); writer.writeByteArray(signature); } } diff --git a/src/main/java/net/minestom/server/crypto/SignedMessageHeader.java b/src/main/java/net/minestom/server/crypto/SignedMessageHeader.java new file mode 100644 index 000000000..036e2cd6d --- /dev/null +++ b/src/main/java/net/minestom/server/crypto/SignedMessageHeader.java @@ -0,0 +1,22 @@ +package net.minestom.server.crypto; + +import net.minestom.server.utils.binary.BinaryReader; +import net.minestom.server.utils.binary.BinaryWriter; +import net.minestom.server.utils.binary.Writeable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.UUID; + +public record SignedMessageHeader(@Nullable MessageSignature previousSignature, UUID sender) implements Writeable { + public SignedMessageHeader(BinaryReader reader) { + this(reader.readBoolean() ? new MessageSignature(reader) : null, reader.readUuid()); + } + + @Override + public void write(@NotNull BinaryWriter writer) { + writer.writeBoolean(previousSignature != null); + if (previousSignature != null) writer.write(previousSignature); + writer.writeUuid(sender); + } +} diff --git a/src/main/java/net/minestom/server/network/packet/client/ClientPacketsHandler.java b/src/main/java/net/minestom/server/network/packet/client/ClientPacketsHandler.java index af7c83a95..e25f66280 100644 --- a/src/main/java/net/minestom/server/network/packet/client/ClientPacketsHandler.java +++ b/src/main/java/net/minestom/server/network/packet/client/ClientPacketsHandler.java @@ -55,53 +55,54 @@ public sealed class ClientPacketsHandler permits ClientPacketsHandler.Status, Cl register(0x00, ClientTeleportConfirmPacket::new); register(0x01, ClientQueryBlockNbtPacket::new); // 0x02 difficulty packet - register(0x03, ClientCommandChatPacket::new); - register(0x04, ClientChatMessagePacket::new); - register(0x05, ClientChatPreviewPacket::new); - register(0x06, ClientStatusPacket::new); - register(0x07, ClientSettingsPacket::new); - register(0x08, ClientTabCompletePacket::new); - register(0x09, ClientClickWindowButtonPacket::new); - register(0x0A, ClientClickWindowPacket::new); - register(0x0B, ClientCloseWindowPacket::new); - register(0x0C, ClientPluginMessagePacket::new); - register(0x0D, ClientEditBookPacket::new); - register(0x0E, ClientQueryEntityNbtPacket::new); - register(0x0F, ClientInteractEntityPacket::new); - register(0x10, ClientGenerateStructurePacket::new); - register(0x11, ClientKeepAlivePacket::new); + register(0x03, ClientChatAckPacket::new); + register(0x04, ClientCommandChatPacket::new); + register(0x05, ClientChatMessagePacket::new); + register(0x06, ClientChatPreviewPacket::new); + register(0x07, ClientStatusPacket::new); + register(0x08, ClientSettingsPacket::new); + register(0x09, ClientTabCompletePacket::new); + register(0x0A, ClientClickWindowButtonPacket::new); + register(0x0B, ClientClickWindowPacket::new); + register(0x0C, ClientCloseWindowPacket::new); + register(0x0D, ClientPluginMessagePacket::new); + register(0x0E, ClientEditBookPacket::new); + register(0x0F, ClientQueryEntityNbtPacket::new); + register(0x10, ClientInteractEntityPacket::new); + register(0x11, ClientGenerateStructurePacket::new); + register(0x12, ClientKeepAlivePacket::new); // 0x12 packet not used server-side - register(0x13, ClientPlayerPositionPacket::new); - register(0x14, ClientPlayerPositionAndRotationPacket::new); - register(0x15, ClientPlayerRotationPacket::new); - register(0x16, ClientPlayerPacket::new); - register(0x17, ClientVehicleMovePacket::new); - register(0x18, ClientSteerBoatPacket::new); - register(0x19, ClientPickItemPacket::new); - register(0x1A, ClientCraftRecipeRequest::new); - register(0x1B, ClientPlayerAbilitiesPacket::new); - register(0x1C, ClientPlayerDiggingPacket::new); - register(0x1D, ClientEntityActionPacket::new); - register(0x1E, ClientSteerVehiclePacket::new); - register(0x1F, ClientPongPacket::new); - register(0x20, ClientSetRecipeBookStatePacket::new); - register(0x21, ClientSetDisplayedRecipePacket::new); - register(0x22, ClientNameItemPacket::new); - register(0x23, ClientResourcePackStatusPacket::new); - register(0x24, ClientAdvancementTabPacket::new); - register(0x25, ClientSelectTradePacket::new); - register(0x26, ClientSetBeaconEffectPacket::new); - register(0x27, ClientHeldItemChangePacket::new); - register(0x28, ClientUpdateCommandBlockPacket::new); - register(0x29, ClientUpdateCommandBlockMinecartPacket::new); - register(0x2A, ClientCreativeInventoryActionPacket::new); + register(0x14, ClientPlayerPositionPacket::new); + register(0x15, ClientPlayerPositionAndRotationPacket::new); + register(0x16, ClientPlayerRotationPacket::new); + register(0x17, ClientPlayerPacket::new); + register(0x18, ClientVehicleMovePacket::new); + register(0x19, ClientSteerBoatPacket::new); + register(0x1A, ClientPickItemPacket::new); + register(0x1B, ClientCraftRecipeRequest::new); + register(0x1C, ClientPlayerAbilitiesPacket::new); + register(0x1D, ClientPlayerDiggingPacket::new); + register(0x1E, ClientEntityActionPacket::new); + register(0x1F, ClientSteerVehiclePacket::new); + register(0x20, ClientPongPacket::new); + register(0x21, ClientSetRecipeBookStatePacket::new); + register(0x22, ClientSetDisplayedRecipePacket::new); + register(0x23, ClientNameItemPacket::new); + register(0x24, ClientResourcePackStatusPacket::new); + register(0x25, ClientAdvancementTabPacket::new); + register(0x26, ClientSelectTradePacket::new); + register(0x27, ClientSetBeaconEffectPacket::new); + register(0x28, ClientHeldItemChangePacket::new); + register(0x29, ClientUpdateCommandBlockPacket::new); + register(0x2A, ClientUpdateCommandBlockMinecartPacket::new); + register(0x2B, ClientCreativeInventoryActionPacket::new); // 0x2B Update Jigsaw Block - register(0x2C, ClientUpdateStructureBlockPacket::new); - register(0x2D, ClientUpdateSignPacket::new); - register(0x2E, ClientAnimationPacket::new); - register(0x2F, ClientSpectatePacket::new); - register(0x30, ClientPlayerBlockPlacementPacket::new); - register(0x31, ClientUseItemPacket::new); + register(0x2D, ClientUpdateStructureBlockPacket::new); + register(0x2E, ClientUpdateSignPacket::new); + register(0x2F, ClientAnimationPacket::new); + register(0x30, ClientSpectatePacket::new); + register(0x31, ClientPlayerBlockPlacementPacket::new); + register(0x32, ClientUseItemPacket::new); } } } diff --git a/src/main/java/net/minestom/server/network/packet/client/play/ClientChatAckPacket.java b/src/main/java/net/minestom/server/network/packet/client/play/ClientChatAckPacket.java new file mode 100644 index 000000000..4032d1932 --- /dev/null +++ b/src/main/java/net/minestom/server/network/packet/client/play/ClientChatAckPacket.java @@ -0,0 +1,18 @@ +package net.minestom.server.network.packet.client.play; + +import net.minestom.server.crypto.LastSeenMessages; +import net.minestom.server.network.packet.client.ClientPacket; +import net.minestom.server.utils.binary.BinaryReader; +import net.minestom.server.utils.binary.BinaryWriter; +import org.jetbrains.annotations.NotNull; + +public record ClientChatAckPacket(@NotNull LastSeenMessages.Update update) implements ClientPacket { + public ClientChatAckPacket(BinaryReader reader) { + this(new LastSeenMessages.Update(reader)); + } + + @Override + public void write(@NotNull BinaryWriter writer) { + writer.write(update); + } +} diff --git a/src/main/java/net/minestom/server/network/packet/client/play/ClientChatMessagePacket.java b/src/main/java/net/minestom/server/network/packet/client/play/ClientChatMessagePacket.java index e8678228b..73192ad85 100644 --- a/src/main/java/net/minestom/server/network/packet/client/play/ClientChatMessagePacket.java +++ b/src/main/java/net/minestom/server/network/packet/client/play/ClientChatMessagePacket.java @@ -1,13 +1,16 @@ package net.minestom.server.network.packet.client.play; +import net.minestom.server.crypto.LastSeenMessages; import net.minestom.server.crypto.MessageSignature; import net.minestom.server.network.packet.client.ClientPacket; import net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryWriter; import org.jetbrains.annotations.NotNull; -public record ClientChatMessagePacket(@NotNull String message, @NotNull MessageSignature signature, - boolean signedPreview) implements ClientPacket { +public record ClientChatMessagePacket(@NotNull String message, + long timestamp, long salt, @NotNull MessageSignature signature, + boolean signedPreview, + @NotNull LastSeenMessages.Update lastSeenMessages) implements ClientPacket { public ClientChatMessagePacket { if (message.length() > 256) { throw new IllegalArgumentException("Message cannot be more than 256 characters long."); @@ -15,14 +18,19 @@ public record ClientChatMessagePacket(@NotNull String message, @NotNull MessageS } public ClientChatMessagePacket(BinaryReader reader) { - this(reader.readSizedString(256), new MessageSignature(null, reader), - reader.readBoolean()); + this(reader.readSizedString(256), + reader.readLong(), reader.readLong(), new MessageSignature(reader), + reader.readBoolean(), + new LastSeenMessages.Update(reader)); } @Override public void write(@NotNull BinaryWriter writer) { writer.writeSizedString(message); + writer.writeLong(timestamp); + writer.writeLong(salt); writer.write(signature); writer.writeBoolean(signedPreview); + writer.write(lastSeenMessages); } } diff --git a/src/main/java/net/minestom/server/network/packet/client/play/ClientCommandChatPacket.java b/src/main/java/net/minestom/server/network/packet/client/play/ClientCommandChatPacket.java index fd7116b3f..5375e4f41 100644 --- a/src/main/java/net/minestom/server/network/packet/client/play/ClientCommandChatPacket.java +++ b/src/main/java/net/minestom/server/network/packet/client/play/ClientCommandChatPacket.java @@ -1,23 +1,18 @@ package net.minestom.server.network.packet.client.play; +import net.minestom.server.crypto.ArgumentSignatures; import net.minestom.server.network.packet.client.ClientPacket; import net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryWriter; import org.jetbrains.annotations.NotNull; -import java.util.HashMap; -import java.util.Map; - public record ClientCommandChatPacket(@NotNull String message, long timestamp, - long salt, Map signatures, + long salt, @NotNull ArgumentSignatures signatures, boolean signed) implements ClientPacket { - public ClientCommandChatPacket { - signatures = Map.copyOf(signatures); - } public ClientCommandChatPacket(BinaryReader reader) { this(reader.readSizedString(256), reader.readLong(), - reader.readLong(), readSignature(reader), reader.readBoolean()); + reader.readLong(), new ArgumentSignatures(reader), reader.readBoolean()); } @Override @@ -25,21 +20,7 @@ public record ClientCommandChatPacket(@NotNull String message, long timestamp, writer.writeSizedString(message); writer.writeLong(timestamp); writer.writeLong(salt); - this.signatures.forEach((s, bytes) -> { - writer.writeSizedString(s); - writer.writeByteArray(bytes); - }); + writer.write(signatures); writer.writeBoolean(signed); } - - private static Map readSignature(BinaryReader reader) { - final int length = reader.readVarInt(); - Map signatures = new HashMap<>(); - for (int i = 0; i < length; i++) { - final String s = reader.readSizedString(256); - final byte[] bytes = reader.readByteArray(); - signatures.put(s, bytes); - } - return Map.copyOf(signatures); - } } diff --git a/src/main/java/net/minestom/server/network/packet/server/ServerPacketIdentifier.java b/src/main/java/net/minestom/server/network/packet/server/ServerPacketIdentifier.java index 58ab9499b..fc4a119e5 100644 --- a/src/main/java/net/minestom/server/network/packet/server/ServerPacketIdentifier.java +++ b/src/main/java/net/minestom/server/network/packet/server/ServerPacketIdentifier.java @@ -61,8 +61,8 @@ public final class ServerPacketIdentifier { public static final int PING = nextPlayId(); public static final int CRAFT_RECIPE_RESPONSE = nextPlayId(); public static final int PLAYER_ABILITIES = nextPlayId(); - public static final int PLAYER_CHAT = nextPlayId(); public static final int PLAYER_CHAT_HEADER = nextPlayId(); + public static final int PLAYER_CHAT = nextPlayId(); public static final int END_COMBAT_EVENT = nextPlayId(); public static final int ENTER_COMBAT_EVENT = nextPlayId(); public static final int DEATH_COMBAT_EVENT = nextPlayId(); diff --git a/src/main/java/net/minestom/server/network/packet/server/play/DeleteChatPacket.java b/src/main/java/net/minestom/server/network/packet/server/play/DeleteChatPacket.java index 6267b66f4..7796c6c9d 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/DeleteChatPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/DeleteChatPacket.java @@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull; public record DeleteChatPacket(@NotNull MessageSignature signature) implements ServerPacket { public DeleteChatPacket(BinaryReader reader) { - this(new MessageSignature(MessageSignature.UNSIGNED_SENDER, reader)); + this(new MessageSignature(reader)); } @Override diff --git a/src/main/java/net/minestom/server/network/packet/server/play/PlayerChatHeaderPacket.java b/src/main/java/net/minestom/server/network/packet/server/play/PlayerChatHeaderPacket.java index a320b8b6c..65741a7ce 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/PlayerChatHeaderPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/PlayerChatHeaderPacket.java @@ -1,21 +1,22 @@ package net.minestom.server.network.packet.server.play; import net.minestom.server.crypto.MessageSignature; +import net.minestom.server.crypto.SignedMessageHeader; import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.network.packet.server.ServerPacketIdentifier; import net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryWriter; import org.jetbrains.annotations.NotNull; -public record PlayerChatHeaderPacket(@NotNull Object header, @NotNull MessageSignature signature, +public record PlayerChatHeaderPacket(@NotNull SignedMessageHeader messageHeader, @NotNull MessageSignature signature, byte[] bodyDigest) implements ServerPacket { public PlayerChatHeaderPacket(BinaryReader reader) { - this(null, new MessageSignature(MessageSignature.UNSIGNED_SENDER, reader), reader.readByteArray()); + this(new SignedMessageHeader(reader), new MessageSignature(reader), reader.readByteArray()); } @Override public void write(@NotNull BinaryWriter writer) { - // TODO write header + writer.write(messageHeader); writer.write(signature); writer.writeByteArray(bodyDigest); } diff --git a/src/main/java/net/minestom/server/network/packet/server/play/PlayerChatMessagePacket.java b/src/main/java/net/minestom/server/network/packet/server/play/PlayerChatMessagePacket.java index 93237eb27..2bed23388 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/PlayerChatMessagePacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/PlayerChatMessagePacket.java @@ -26,7 +26,7 @@ public record PlayerChatMessagePacket(@NotNull Component signedContent, @Nullabl this(reader.readComponent(), reader.readBoolean() ? reader.readComponent() : null, reader.readVarInt(), reader.readUuid(), reader.readComponent(), reader.readBoolean() ? reader.readComponent() : null, - new MessageSignature(null, reader)); + new MessageSignature(reader)); } @Override