From 7f0964155c6f8f186dc7ae368e567ed42e5ff40d Mon Sep 17 00:00:00 2001 From: "Five (Xer)" Date: Wed, 4 Nov 2020 22:35:27 +0100 Subject: [PATCH 01/30] Snapshot 20w45a --- .../api/network/ProtocolVersion.java | 3 ++- .../com/velocitypowered/api/proxy/Player.java | 15 +++++++++++++++ .../proxy/connection/client/ConnectedPlayer.java | 9 ++++++++- .../protocol/packet/ResourcePackRequest.java | 15 +++++++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index 8b3632f9f..6cf31f06b 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -53,7 +53,8 @@ public enum ProtocolVersion { MINECRAFT_1_16_1(736, "1.16.1"), MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), - MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"); + MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), + MINECRAFT_1_17(754, 5, "1.17"); // Note: this probably isnt intentional private static final int SNAPSHOT_BIT = 30; diff --git a/api/src/main/java/com/velocitypowered/api/proxy/Player.java b/api/src/main/java/com/velocitypowered/api/proxy/Player.java index 540adc75e..1a09ae3ca 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/Player.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/Player.java @@ -239,4 +239,19 @@ public interface Player extends CommandSource, Identified, InboundConnection, */ @Override boolean sendPluginMessage(ChannelIdentifier identifier, byte[] data); + + /** + * Sends the specified resource pack from {@code url} to the user, using the specified 20-byte + * SHA-1 hash. To monitor the status of the sent resource pack, subscribe to + * {@link PlayerResourcePackStatusEvent}. + * In 1.17 and newer you can additionally specify + * whether the resource pack is required or not. Setting this for an older client will have + * no effect. + * + * @param url the URL for the resource pack + * @param hash the SHA-1 hash value for the resource pack + * @param isRequired flag to set the resource pack as required in 1.17+ + */ + void sendResourcePack(String url, byte[] hash, boolean isRequired); + } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java index fe49f71ee..9d6e98eac 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java @@ -871,12 +871,13 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { ResourcePackRequest request = new ResourcePackRequest(); request.setUrl(url); request.setHash(""); + request.setRequired(false); connection.write(request); } } @Override - public void sendResourcePack(String url, byte[] hash) { + public void sendResourcePack(String url, byte[] hash, boolean isRequired) { Preconditions.checkNotNull(url, "url"); Preconditions.checkNotNull(hash, "hash"); Preconditions.checkArgument(hash.length == 20, "Hash length is not 20"); @@ -885,10 +886,16 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { ResourcePackRequest request = new ResourcePackRequest(); request.setUrl(url); request.setHash(ByteBufUtil.hexDump(hash)); + request.setRequired(isRequired); connection.write(request); } } + @Override + public void sendResourcePack(String url, byte[] hash) { + sendResourcePack(url, hash, false); + } + /** * Sends a {@link KeepAlive} packet to the player with a random ID. * The response will be ignored by Velocity as it will not match the diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackRequest.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackRequest.java index 522ddc2c7..c2115970d 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackRequest.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackRequest.java @@ -30,6 +30,7 @@ public class ResourcePackRequest implements MinecraftPacket { private @MonotonicNonNull String url; private @MonotonicNonNull String hash; + private boolean isRequired; // 1.17+ public @Nullable String getUrl() { return url; @@ -39,6 +40,10 @@ public class ResourcePackRequest implements MinecraftPacket { this.url = url; } + public boolean isRequired() { + return isRequired; + } + public @Nullable String getHash() { return hash; } @@ -47,10 +52,17 @@ public class ResourcePackRequest implements MinecraftPacket { this.hash = hash; } + public void setRequired(boolean required) { + isRequired = required; + } + @Override public void decode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) { this.url = ProtocolUtils.readString(buf); this.hash = ProtocolUtils.readString(buf); + if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_17) >= 0) { + this.isRequired = buf.readBoolean(); + } } @Override @@ -60,6 +72,9 @@ public class ResourcePackRequest implements MinecraftPacket { } ProtocolUtils.writeString(buf, url); ProtocolUtils.writeString(buf, hash); + if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_17) >= 0) { + buf.writeBoolean(isRequired); + } } @Override From d444bed96b7ddae64b00dccb8b3a8fc4c7e4a226 Mon Sep 17 00:00:00 2001 From: "Five (Xer)" Date: Thu, 5 Nov 2020 10:01:05 +0100 Subject: [PATCH 02/30] Adjust snapshot -> final version --- .../java/com/velocitypowered/api/network/ProtocolVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index 6cf31f06b..67cd49963 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(754, 5, "1.17"); // Note: this probably isnt intentional + MINECRAFT_1_17(-1, 5, "1.17"); // Note: Indev as of 20w45a (754, borked by Mojang) private static final int SNAPSHOT_BIT = 30; From d8a39fc43897aefe488afa2ed83170f45505819f Mon Sep 17 00:00:00 2001 From: "Five (Xer)" Date: Wed, 11 Nov 2020 20:12:47 +0100 Subject: [PATCH 03/30] Snapshot 20w46a --- .../com/velocitypowered/api/network/ProtocolVersion.java | 2 +- api/src/main/java/com/velocitypowered/api/proxy/Player.java | 4 +++- .../proxy/connection/client/ConnectedPlayer.java | 5 ----- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index 67cd49963..aaa04f9a7 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 5, "1.17"); // Note: Indev as of 20w45a (754, borked by Mojang) + MINECRAFT_1_17(-1, 6, "1.17"); // Note: Indev as of 20w45a (754, borked by Mojang) private static final int SNAPSHOT_BIT = 30; diff --git a/api/src/main/java/com/velocitypowered/api/proxy/Player.java b/api/src/main/java/com/velocitypowered/api/proxy/Player.java index 1a09ae3ca..4635c74fa 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/Player.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/Player.java @@ -226,7 +226,9 @@ public interface Player extends CommandSource, Identified, InboundConnection, * @param url the URL for the resource pack * @param hash the SHA-1 hash value for the resource pack */ - void sendResourcePack(String url, byte[] hash); + default void sendResourcePack(String url, byte[] hash) { + sendResourcePack(url, hash, false); + } /** * Note that this method does not send a plugin message to the server the player diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java index 9d6e98eac..602c002c1 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java @@ -891,11 +891,6 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { } } - @Override - public void sendResourcePack(String url, byte[] hash) { - sendResourcePack(url, hash, false); - } - /** * Sends a {@link KeepAlive} packet to the player with a random ID. * The response will be ignored by Velocity as it will not match the From b588bfe448fdd635b21881b34cd6bf419bcb5e8d Mon Sep 17 00:00:00 2001 From: "Five (Xer)" Date: Wed, 25 Nov 2020 18:34:45 +0100 Subject: [PATCH 04/30] Snapshot 20w48a --- .../java/com/velocitypowered/api/network/ProtocolVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index aaa04f9a7..183dfbf4c 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 6, "1.17"); // Note: Indev as of 20w45a (754, borked by Mojang) + MINECRAFT_1_17(-1, 7, "1.17"); // Note: Indev as of 20w45a (754, borked by Mojang) private static final int SNAPSHOT_BIT = 30; From 040cc29c34adf5bbb19ceb6cb5f70d94d8847f8e Mon Sep 17 00:00:00 2001 From: "Five (Xer)" Date: Wed, 2 Dec 2020 20:39:34 +0100 Subject: [PATCH 05/30] Snapshot 20w49a --- .../api/network/ProtocolVersion.java | 2 +- .../connection/registry/DimensionData.java | 35 ++++++++++++++-- .../proxy/protocol/StateRegistry.java | 40 +++++++++++++------ 3 files changed, 60 insertions(+), 17 deletions(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index 183dfbf4c..d60192074 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 7, "1.17"); // Note: Indev as of 20w45a (754, borked by Mojang) + MINECRAFT_1_17(-1, 8, "1.17"); // Note: Indev as of 20w45a (754, borked by Mojang) private static final int SNAPSHOT_BIT = 30; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionData.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionData.java index 406bce93a..7640d331f 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionData.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionData.java @@ -43,6 +43,8 @@ public final class DimensionData { private final @Nullable Boolean createDragonFight; private final @Nullable Double coordinateScale; private final @Nullable String effects; + private final @Nullable Integer minY; // Required and added by 1.17 + private final @Nullable Integer height; // Required and added by 1.17 /** * Initializes a new {@link DimensionData} instance. @@ -64,6 +66,8 @@ public final class DimensionData { * @param createDragonFight optional. Internal flag used in the end dimension * @param coordinateScale optional, unknown purpose * @param effects optional, unknown purpose + * @param minY the world effective lowest build-level + * @param height the world height above zero */ public DimensionData(String registryIdentifier, @Nullable Integer dimensionId, @@ -75,7 +79,8 @@ public final class DimensionData { int logicalHeight, String burningBehaviourIdentifier, @Nullable Long fixedTime, @Nullable Boolean createDragonFight, @Nullable Double coordinateScale, - @Nullable String effects) { + @Nullable String effects, + @Nullable Integer minY, @Nullable Integer height) { Preconditions.checkNotNull( registryIdentifier, "registryIdentifier cannot be null"); Preconditions.checkArgument(registryIdentifier.length() > 0, @@ -103,6 +108,8 @@ public final class DimensionData { this.createDragonFight = createDragonFight; this.coordinateScale = coordinateScale; this.effects = effects; + this.minY = minY; + this.height = height; } public String getRegistryIdentifier() { @@ -173,6 +180,14 @@ public final class DimensionData { return coordinateScale; } + public @Nullable Integer getMinY() { + return minY; + } + + public @Nullable Integer getHeight() { + return height; + } + /** * Returns a fresh {@link DimensionData} with the specified {@code registryIdentifier} * and {@code dimensionId}. @@ -186,7 +201,7 @@ public final class DimensionData { return new DimensionData(registryIdentifier, dimensionId, isNatural, ambientLight, isShrunk, isUltrawarm, hasCeiling, hasSkylight, isPiglinSafe, doBedsWork, doRespawnAnchorsWork, hasRaids, logicalHeight, burningBehaviourIdentifier, fixedTime, createDragonFight, - coordinateScale, effects); + coordinateScale, effects, minY, height); } public boolean isUnannotated() { @@ -223,11 +238,19 @@ public final class DimensionData { ? details.getDouble("coordinate_scale") : null; String effects = details.keySet().contains("effects") ? details.getString("effects") : null; + Integer minY = details.keySet().contains("min_y") ? details.getInt("min_y") : null; + Integer height = details.keySet().contains("height") ? details.getInt("height") : null; + if (version.compareTo(ProtocolVersion.MINECRAFT_1_17) >= 0) { + Preconditions.checkNotNull(height, + "DimensionData requires 'minY' to be present for this version"); + Preconditions.checkNotNull(minY, + "DimensionData requires 'height' to be present for this version"); + } return new DimensionData( UNKNOWN_DIMENSION_ID, null, isNatural, ambientLight, isShrunk, isUltrawarm, hasCeiling, hasSkylight, isPiglinSafe, doBedsWork, doRespawnAnchorsWork, hasRaids, logicalHeight, burningBehaviourIdentifier, fixedTime, hasEnderdragonFight, - coordinateScale, effects); + coordinateScale, effects, minY, height); } /** @@ -306,6 +329,12 @@ public final class DimensionData { if (effects != null) { ret.putString("effects", effects); } + if (minY != null) { + ret.putInt("min_y", minY); + } + if (height != null) { + ret.putInt("height", height); + } return ret.build(); } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java index 87bc5d091..c3c25d91c 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java @@ -25,6 +25,7 @@ import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_14; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_15; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_16; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_16_2; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_17; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_7_2; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_8; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_9; @@ -145,25 +146,29 @@ public enum StateRegistry { clientbound.register(BossBar.class, BossBar::new, map(0x0C, MINECRAFT_1_9, false), map(0x0D, MINECRAFT_1_15, false), - map(0x0C, MINECRAFT_1_16, false)); + map(0x0C, MINECRAFT_1_16, false), + map(0x0D, MINECRAFT_1_17, false)); clientbound.register(Chat.class, Chat::new, map(0x02, MINECRAFT_1_7_2, true), map(0x0F, MINECRAFT_1_9, true), map(0x0E, MINECRAFT_1_13, true), map(0x0F, MINECRAFT_1_15, true), - map(0x0E, MINECRAFT_1_16, true)); + map(0x0E, MINECRAFT_1_16, true), + map(0x0F, MINECRAFT_1_17, true)); clientbound.register(TabCompleteResponse.class, TabCompleteResponse::new, map(0x3A, MINECRAFT_1_7_2, false), map(0x0E, MINECRAFT_1_9, false), map(0x10, MINECRAFT_1_13, false), map(0x11, MINECRAFT_1_15, false), map(0x10, MINECRAFT_1_16, false), - map(0x0F, MINECRAFT_1_16_2, false)); + map(0x0F, MINECRAFT_1_16_2, false), + map(0x10, MINECRAFT_1_17, false)); clientbound.register(AvailableCommands.class, AvailableCommands::new, map(0x11, MINECRAFT_1_13, false), map(0x12, MINECRAFT_1_15, false), map(0x11, MINECRAFT_1_16, false), - map(0x10, MINECRAFT_1_16_2, false)); + map(0x10, MINECRAFT_1_16_2, false), + map(0x11, MINECRAFT_1_17, false)); clientbound.register(PluginMessage.class, PluginMessage::new, map(0x3F, MINECRAFT_1_7_2, false), map(0x18, MINECRAFT_1_9, false), @@ -171,7 +176,8 @@ public enum StateRegistry { map(0x18, MINECRAFT_1_14, false), map(0x19, MINECRAFT_1_15, false), map(0x18, MINECRAFT_1_16, false), - map(0x17, MINECRAFT_1_16_2, false)); + map(0x17, MINECRAFT_1_16_2, false), + map(0x18, MINECRAFT_1_17, false)); clientbound.register(Disconnect.class, Disconnect::new, map(0x40, MINECRAFT_1_7_2, false), map(0x1A, MINECRAFT_1_9, false), @@ -179,7 +185,8 @@ public enum StateRegistry { map(0x1A, MINECRAFT_1_14, false), map(0x1B, MINECRAFT_1_15, false), map(0x1A, MINECRAFT_1_16, false), - map(0x19, MINECRAFT_1_16_2, false)); + map(0x19, MINECRAFT_1_16_2, false), + map(0x1A, MINECRAFT_1_17, false)); clientbound.register(KeepAlive.class, KeepAlive::new, map(0x00, MINECRAFT_1_7_2, false), map(0x1F, MINECRAFT_1_9, false), @@ -187,7 +194,8 @@ public enum StateRegistry { map(0x20, MINECRAFT_1_14, false), map(0x21, MINECRAFT_1_15, false), map(0x20, MINECRAFT_1_16, false), - map(0x1F, MINECRAFT_1_16_2, false)); + map(0x1F, MINECRAFT_1_16_2, false), + map(0x20, MINECRAFT_1_17, false)); clientbound.register(JoinGame.class, JoinGame::new, map(0x01, MINECRAFT_1_7_2, false), map(0x23, MINECRAFT_1_9, false), @@ -195,7 +203,8 @@ public enum StateRegistry { map(0x25, MINECRAFT_1_14, false), map(0x26, MINECRAFT_1_15, false), map(0x25, MINECRAFT_1_16, false), - map(0x24, MINECRAFT_1_16_2, false)); + map(0x24, MINECRAFT_1_16_2, false), + map(0x25, MINECRAFT_1_17, false)); clientbound.register(Respawn.class, Respawn::new, map(0x07, MINECRAFT_1_7_2, true), map(0x33, MINECRAFT_1_9, true), @@ -205,7 +214,8 @@ public enum StateRegistry { map(0x3A, MINECRAFT_1_14, true), map(0x3B, MINECRAFT_1_15, true), map(0x3A, MINECRAFT_1_16, true), - map(0x39, MINECRAFT_1_16_2, true)); + map(0x39, MINECRAFT_1_16_2, true), + map(0x3A, MINECRAFT_1_17, true)); clientbound.register(ResourcePackRequest.class, ResourcePackRequest::new, map(0x48, MINECRAFT_1_8, true), map(0x32, MINECRAFT_1_9, true), @@ -215,7 +225,8 @@ public enum StateRegistry { map(0x39, MINECRAFT_1_14, true), map(0x3A, MINECRAFT_1_15, true), map(0x39, MINECRAFT_1_16, true), - map(0x38, MINECRAFT_1_16_2, true)); + map(0x38, MINECRAFT_1_16_2, true), + map(0x39, MINECRAFT_1_17, true)); clientbound.register(HeaderAndFooter.class, HeaderAndFooter::new, map(0x47, MINECRAFT_1_8, true), map(0x48, MINECRAFT_1_9, true), @@ -225,7 +236,8 @@ public enum StateRegistry { map(0x4E, MINECRAFT_1_13, true), map(0x53, MINECRAFT_1_14, true), map(0x54, MINECRAFT_1_15, true), - map(0x53, MINECRAFT_1_16, true)); + map(0x53, MINECRAFT_1_16, true), + map(0x54, MINECRAFT_1_17, true)); clientbound.register(TitlePacket.class, TitlePacket::new, map(0x45, MINECRAFT_1_8, true), map(0x45, MINECRAFT_1_9, true), @@ -234,7 +246,8 @@ public enum StateRegistry { map(0x4B, MINECRAFT_1_13, true), map(0x4F, MINECRAFT_1_14, true), map(0x50, MINECRAFT_1_15, true), - map(0x4F, MINECRAFT_1_16, true)); + map(0x4F, MINECRAFT_1_16, true), + map(0x50, MINECRAFT_1_17, true)); clientbound.register(PlayerListItem.class, PlayerListItem::new, map(0x38, MINECRAFT_1_7_2, false), map(0x2D, MINECRAFT_1_9, false), @@ -243,7 +256,8 @@ public enum StateRegistry { map(0x33, MINECRAFT_1_14, false), map(0x34, MINECRAFT_1_15, false), map(0x33, MINECRAFT_1_16, false), - map(0x32, MINECRAFT_1_16_2, false)); + map(0x32, MINECRAFT_1_16_2, false), + map(0x33, MINECRAFT_1_17, false)); } }, LOGIN { From 76493549bf6ba8faf33bfa4bd72003075c089054 Mon Sep 17 00:00:00 2001 From: "FivePB (Xer)" Date: Fri, 18 Dec 2020 20:06:12 +0100 Subject: [PATCH 06/30] Snapshot 20w51a --- .../java/com/velocitypowered/api/network/ProtocolVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index d60192074..01b02b1be 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 8, "1.17"); // Note: Indev as of 20w45a (754, borked by Mojang) + MINECRAFT_1_17(-1, 9, "1.17"); // Note: Indev as of 20w45a (754, borked by Mojang) private static final int SNAPSHOT_BIT = 30; From f0d9a445ed1421d9d38ef5bb6785c6b60a5252af Mon Sep 17 00:00:00 2001 From: FivePB Date: Wed, 20 Jan 2021 20:13:56 +0100 Subject: [PATCH 07/30] Snapshot 21w03a --- .../java/com/velocitypowered/api/network/ProtocolVersion.java | 2 +- api/src/main/java/com/velocitypowered/api/proxy/Player.java | 4 +++- .../proxy/connection/registry/DimensionData.java | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index 01b02b1be..7f6ee7fe5 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 9, "1.17"); // Note: Indev as of 20w45a (754, borked by Mojang) + MINECRAFT_1_17(-1, 11, "1.17"); // Snapshot: 21w03a, future protocol: 755 private static final int SNAPSHOT_BIT = 30; diff --git a/api/src/main/java/com/velocitypowered/api/proxy/Player.java b/api/src/main/java/com/velocitypowered/api/proxy/Player.java index 4635c74fa..5fb68d4c9 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/Player.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/Player.java @@ -252,8 +252,10 @@ public interface Player extends CommandSource, Identified, InboundConnection, * * @param url the URL for the resource pack * @param hash the SHA-1 hash value for the resource pack - * @param isRequired flag to set the resource pack as required in 1.17+ + * @param isRequired Only in 1.17+ or newer: If true shows the pack as required to play, + * and removes the decline option. Declining it anyway will disconnect the user. */ void sendResourcePack(String url, byte[] hash, boolean isRequired); } + diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionData.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionData.java index 7640d331f..07b69baef 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionData.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionData.java @@ -242,9 +242,9 @@ public final class DimensionData { Integer height = details.keySet().contains("height") ? details.getInt("height") : null; if (version.compareTo(ProtocolVersion.MINECRAFT_1_17) >= 0) { Preconditions.checkNotNull(height, - "DimensionData requires 'minY' to be present for this version"); - Preconditions.checkNotNull(minY, "DimensionData requires 'height' to be present for this version"); + Preconditions.checkNotNull(minY, + "DimensionData requires 'minY' to be present for this version"); } return new DimensionData( UNKNOWN_DIMENSION_ID, null, isNatural, ambientLight, isShrunk, From 7ea7e775647992215fe8db8b5f99227327d5b6fe Mon Sep 17 00:00:00 2001 From: "FivePB (Xer)" Date: Wed, 3 Feb 2021 23:49:49 +0100 Subject: [PATCH 08/30] Snapshot 21w05a --- .../java/com/velocitypowered/api/network/ProtocolVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index 7f6ee7fe5..ce3f4d8c9 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 11, "1.17"); // Snapshot: 21w03a, future protocol: 755 + MINECRAFT_1_17(-1, 12, "1.17"); // Snapshot: 21w05a, future protocol: 755 private static final int SNAPSHOT_BIT = 30; From 03327c2677be75fb0a0970f9ee8cad24c34e6292 Mon Sep 17 00:00:00 2001 From: "Five (Xer)" Date: Fri, 5 Feb 2021 08:05:46 +0100 Subject: [PATCH 09/30] Snapshot 21w05b --- .../java/com/velocitypowered/api/network/ProtocolVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index ce3f4d8c9..96c16cec0 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 12, "1.17"); // Snapshot: 21w05a, future protocol: 755 + MINECRAFT_1_17(-1, 13, "1.17"); // Snapshot: 21w05b, future protocol: 755 private static final int SNAPSHOT_BIT = 30; From c9e92bcc53a239c5ec9061c0209f6f1e072ac5f4 Mon Sep 17 00:00:00 2001 From: "Five (Xer)" Date: Wed, 10 Feb 2021 19:58:46 +0100 Subject: [PATCH 10/30] Snapshot 21w06a --- .../java/com/velocitypowered/api/network/ProtocolVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index 96c16cec0..e09ac5519 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 13, "1.17"); // Snapshot: 21w05b, future protocol: 755 + MINECRAFT_1_17(-1, 14, "1.17"); // Snapshot: 21w06a, future protocol: 755 private static final int SNAPSHOT_BIT = 30; From b19cf16345c30d03aeed4f96fe3cd249566486e3 Mon Sep 17 00:00:00 2001 From: "Five (Xer)" Date: Thu, 18 Feb 2021 22:02:26 +0100 Subject: [PATCH 11/30] Snapshot 21w07a --- .../api/network/ProtocolVersion.java | 2 +- .../client/ClientSettingsWrapper.java | 2 +- .../proxy/protocol/packet/ClientSettings.java | 20 ++++++++++++++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index e09ac5519..8637d76b0 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 14, "1.17"); // Snapshot: 21w06a, future protocol: 755 + MINECRAFT_1_17(-1, 15, "1.17"); // Snapshot: 21w07a, future protocol: 755 private static final int SNAPSHOT_BIT = 30; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientSettingsWrapper.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientSettingsWrapper.java index b268ee19c..38942fa16 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientSettingsWrapper.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientSettingsWrapper.java @@ -26,7 +26,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; public class ClientSettingsWrapper implements PlayerSettings { static final PlayerSettings DEFAULT = new ClientSettingsWrapper( - new ClientSettings("en_US", (byte) 10, 0, true, (short) 127, 1)); + new ClientSettings("en_US", (byte) 10, 0, true, (short) 127, 1, true)); private final ClientSettings settings; private final SkinParts parts; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientSettings.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientSettings.java index a2d7e32bc..ef3818c99 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientSettings.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientSettings.java @@ -33,12 +33,13 @@ public class ClientSettings implements MinecraftPacket { private byte difficulty; // 1.7 Protocol private short skinParts; private int mainHand; + private boolean chatFilteringEnabled; // Added in 1.17 public ClientSettings() { } public ClientSettings(String locale, byte viewDistance, int chatVisibility, boolean chatColors, - short skinParts, int mainHand) { + short skinParts, int mainHand, boolean chatFilteringEnabled) { this.locale = locale; this.viewDistance = viewDistance; this.chatVisibility = chatVisibility; @@ -98,6 +99,14 @@ public class ClientSettings implements MinecraftPacket { this.mainHand = mainHand; } + public boolean isChatFilteringEnabled() { + return chatFilteringEnabled; + } + + public void setChatFilteringEnabled(boolean chatFilteringEnabled) { + this.chatFilteringEnabled = chatFilteringEnabled; + } + @Override public String toString() { return "ClientSettings{" @@ -107,6 +116,7 @@ public class ClientSettings implements MinecraftPacket { + ", chatColors=" + chatColors + ", skinParts=" + skinParts + ", mainHand=" + mainHand + + ", chatFilteringEnabled=" + chatFilteringEnabled + '}'; } @@ -125,6 +135,10 @@ public class ClientSettings implements MinecraftPacket { if (version.compareTo(ProtocolVersion.MINECRAFT_1_9) >= 0) { this.mainHand = ProtocolUtils.readVarInt(buf); + + if (version.compareTo(ProtocolVersion.MINECRAFT_1_17) >= 0) { + this.chatFilteringEnabled = buf.readBoolean(); + } } } @@ -146,6 +160,10 @@ public class ClientSettings implements MinecraftPacket { if (version.compareTo(ProtocolVersion.MINECRAFT_1_9) >= 0) { ProtocolUtils.writeVarInt(buf, mainHand); + + if (version.compareTo(ProtocolVersion.MINECRAFT_1_17) >= 0) { + buf.writeBoolean(chatFilteringEnabled); + } } } From 22bc7590446d292800b7012c1592008cd42774bc Mon Sep 17 00:00:00 2001 From: "Five (Xer)" Date: Thu, 25 Feb 2021 14:42:23 +0100 Subject: [PATCH 12/30] Snapshot 21w08a --- .../api/network/ProtocolVersion.java | 2 +- .../connection/MinecraftSessionHandler.java | 29 ++- .../client/ClientPlaySessionHandler.java | 5 +- .../connection/client/ConnectedPlayer.java | 47 +++-- .../proxy/protocol/StateRegistry.java | 78 ++++++-- .../proxy/protocol/packet/TitlePacket.java | 174 ------------------ .../packet/title/GenericTitlePacket.java | 136 ++++++++++++++ .../packet/title/LegacyTitlePacket.java | 124 +++++++++++++ .../packet/title/TitleActionbarPacket.java | 59 ++++++ .../packet/title/TitleClearPacket.java | 57 ++++++ .../packet/title/TitleSubtitlePacket.java | 59 ++++++ .../packet/title/TitleTextPacket.java | 59 ++++++ .../packet/title/TitleTimesPacket.java | 85 +++++++++ .../proxy/protocol/PacketRegistryTest.java | 42 +++-- 14 files changed, 726 insertions(+), 230 deletions(-) delete mode 100644 proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TitlePacket.java create mode 100644 proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/GenericTitlePacket.java create mode 100644 proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/LegacyTitlePacket.java create mode 100644 proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleActionbarPacket.java create mode 100644 proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleClearPacket.java create mode 100644 proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleSubtitlePacket.java create mode 100644 proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleTextPacket.java create mode 100644 proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleTimesPacket.java diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index 8637d76b0..0149970e6 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 15, "1.17"); // Snapshot: 21w07a, future protocol: 755 + MINECRAFT_1_17(-1, 16, "1.17"); // Snapshot: 21w08a, future protocol: 755 private static final int SNAPSHOT_BIT = 30; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java index 3dcb3807a..e72f42d64 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java @@ -46,7 +46,12 @@ import com.velocitypowered.proxy.protocol.packet.StatusRequest; import com.velocitypowered.proxy.protocol.packet.StatusResponse; import com.velocitypowered.proxy.protocol.packet.TabCompleteRequest; import com.velocitypowered.proxy.protocol.packet.TabCompleteResponse; -import com.velocitypowered.proxy.protocol.packet.TitlePacket; +import com.velocitypowered.proxy.protocol.packet.title.LegacyTitlePacket; +import com.velocitypowered.proxy.protocol.packet.title.TitleActionbarPacket; +import com.velocitypowered.proxy.protocol.packet.title.TitleClearPacket; +import com.velocitypowered.proxy.protocol.packet.title.TitleSubtitlePacket; +import com.velocitypowered.proxy.protocol.packet.title.TitleTextPacket; +import com.velocitypowered.proxy.protocol.packet.title.TitleTimesPacket; import io.netty.buffer.ByteBuf; public interface MinecraftSessionHandler { @@ -191,7 +196,27 @@ public interface MinecraftSessionHandler { return false; } - default boolean handle(TitlePacket packet) { + default boolean handle(LegacyTitlePacket packet) { + return false; + } + + default boolean handle(TitleTextPacket packet) { + return false; + } + + default boolean handle(TitleSubtitlePacket packet) { + return false; + } + + default boolean handle(TitleActionbarPacket packet) { + return false; + } + + default boolean handle(TitleTimesPacket packet) { + return false; + } + + default boolean handle(TitleClearPacket packet) { return false; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java index 8ac397500..0c2b402eb 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java @@ -53,7 +53,7 @@ import com.velocitypowered.proxy.protocol.packet.Respawn; import com.velocitypowered.proxy.protocol.packet.TabCompleteRequest; import com.velocitypowered.proxy.protocol.packet.TabCompleteResponse; import com.velocitypowered.proxy.protocol.packet.TabCompleteResponse.Offer; -import com.velocitypowered.proxy.protocol.packet.TitlePacket; +import com.velocitypowered.proxy.protocol.packet.title.GenericTitlePacket; import com.velocitypowered.proxy.protocol.util.PluginMessageUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; @@ -400,7 +400,8 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { // Clear any title from the previous server. if (player.getProtocolVersion().compareTo(MINECRAFT_1_8) >= 0) { player.getConnection() - .delayedWrite(TitlePacket.resetForProtocolVersion(player.getProtocolVersion())); + .delayedWrite(GenericTitlePacket.constructTitlePacket( + GenericTitlePacket.ActionType.RESET, player.getProtocolVersion())); } // Flush everything diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java index 602c002c1..1a1a0d444 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java @@ -66,7 +66,7 @@ import com.velocitypowered.proxy.protocol.packet.HeaderAndFooter; import com.velocitypowered.proxy.protocol.packet.KeepAlive; import com.velocitypowered.proxy.protocol.packet.PluginMessage; import com.velocitypowered.proxy.protocol.packet.ResourcePackRequest; -import com.velocitypowered.proxy.protocol.packet.TitlePacket; +import com.velocitypowered.proxy.protocol.packet.title.GenericTitlePacket; import com.velocitypowered.proxy.protocol.util.PluginMessageUtil; import com.velocitypowered.proxy.server.VelocityRegisteredServer; import com.velocitypowered.proxy.tablist.VelocityTabList; @@ -262,8 +262,8 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { if (position == MessagePosition.ACTION_BAR) { if (getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_11) >= 0) { // We can use the title packet instead. - TitlePacket pkt = new TitlePacket(); - pkt.setAction(TitlePacket.SET_ACTION_BAR); + GenericTitlePacket pkt = GenericTitlePacket.constructTitlePacket( + GenericTitlePacket.ActionType.SET_ACTION_BAR, this.getProtocolVersion()); pkt.setComponent(net.kyori.text.serializer.gson.GsonComponentSerializer.INSTANCE .serialize(component)); connection.write(pkt); @@ -307,8 +307,8 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { ProtocolVersion playerVersion = getProtocolVersion(); if (playerVersion.compareTo(ProtocolVersion.MINECRAFT_1_11) >= 0) { // Use the title packet instead. - TitlePacket pkt = new TitlePacket(); - pkt.setAction(TitlePacket.SET_ACTION_BAR); + GenericTitlePacket pkt = GenericTitlePacket.constructTitlePacket( + GenericTitlePacket.ActionType.SET_ACTION_BAR, playerVersion); pkt.setComponent(ProtocolUtils.getJsonChatSerializer(playerVersion) .serialize(message)); connection.write(pkt); @@ -359,17 +359,18 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { GsonComponentSerializer serializer = ProtocolUtils.getJsonChatSerializer(this .getProtocolVersion()); - TitlePacket titlePkt = new TitlePacket(); - titlePkt.setAction(TitlePacket.SET_TITLE); + GenericTitlePacket titlePkt = GenericTitlePacket.constructTitlePacket( + GenericTitlePacket.ActionType.SET_TITLE, this.getProtocolVersion()); titlePkt.setComponent(serializer.serialize(title.title())); connection.delayedWrite(titlePkt); - TitlePacket subtitlePkt = new TitlePacket(); - subtitlePkt.setAction(TitlePacket.SET_SUBTITLE); + GenericTitlePacket subtitlePkt = GenericTitlePacket.constructTitlePacket( + GenericTitlePacket.ActionType.SET_SUBTITLE, this.getProtocolVersion()); subtitlePkt.setComponent(serializer.serialize(title.subtitle())); connection.delayedWrite(subtitlePkt); - TitlePacket timesPkt = TitlePacket.timesForProtocolVersion(this.getProtocolVersion()); + GenericTitlePacket timesPkt = GenericTitlePacket.constructTitlePacket( + GenericTitlePacket.ActionType.SET_TIMES, this.getProtocolVersion()); net.kyori.adventure.title.Title.Times times = title.times(); if (times != null) { timesPkt.setFadeIn((int) DurationUtils.toTicks(times.fadeIn())); @@ -385,14 +386,16 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { @Override public void clearTitle() { if (this.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { - connection.write(TitlePacket.hideForProtocolVersion(this.getProtocolVersion())); + connection.write(GenericTitlePacket.constructTitlePacket( + GenericTitlePacket.ActionType.HIDE, this.getProtocolVersion())); } } @Override public void resetTitle() { if (this.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { - connection.write(TitlePacket.resetForProtocolVersion(this.getProtocolVersion())); + connection.write(GenericTitlePacket.constructTitlePacket( + GenericTitlePacket.ActionType.RESET, this.getProtocolVersion())); } } @@ -487,20 +490,23 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { ProtocolVersion protocolVersion = connection.getProtocolVersion(); if (title.equals(Titles.reset())) { - connection.write(TitlePacket.resetForProtocolVersion(protocolVersion)); + connection.write(GenericTitlePacket.constructTitlePacket( + GenericTitlePacket.ActionType.RESET, protocolVersion)); } else if (title.equals(Titles.hide())) { - connection.write(TitlePacket.hideForProtocolVersion(protocolVersion)); + connection.write(GenericTitlePacket.constructTitlePacket( + GenericTitlePacket.ActionType.HIDE, protocolVersion)); } else if (title instanceof TextTitle) { TextTitle tt = (TextTitle) title; if (tt.isResetBeforeSend()) { - connection.delayedWrite(TitlePacket.resetForProtocolVersion(protocolVersion)); + connection.delayedWrite(GenericTitlePacket.constructTitlePacket( + GenericTitlePacket.ActionType.RESET, protocolVersion)); } Optional titleText = tt.getTitle(); if (titleText.isPresent()) { - TitlePacket titlePkt = new TitlePacket(); - titlePkt.setAction(TitlePacket.SET_TITLE); + GenericTitlePacket titlePkt = GenericTitlePacket.constructTitlePacket( + GenericTitlePacket.ActionType.SET_TITLE, protocolVersion); titlePkt.setComponent(net.kyori.text.serializer.gson.GsonComponentSerializer.INSTANCE .serialize(titleText.get())); connection.delayedWrite(titlePkt); @@ -508,15 +514,16 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { Optional subtitleText = tt.getSubtitle(); if (subtitleText.isPresent()) { - TitlePacket titlePkt = new TitlePacket(); - titlePkt.setAction(TitlePacket.SET_SUBTITLE); + GenericTitlePacket titlePkt = GenericTitlePacket.constructTitlePacket( + GenericTitlePacket.ActionType.SET_SUBTITLE, protocolVersion); titlePkt.setComponent(net.kyori.text.serializer.gson.GsonComponentSerializer.INSTANCE .serialize(subtitleText.get())); connection.delayedWrite(titlePkt); } if (tt.areTimesSet()) { - TitlePacket timesPkt = TitlePacket.timesForProtocolVersion(protocolVersion); + GenericTitlePacket timesPkt = GenericTitlePacket.constructTitlePacket( + GenericTitlePacket.ActionType.SET_TIMES, protocolVersion); timesPkt.setFadeIn(tt.getFadeIn()); timesPkt.setStay(tt.getStay()); timesPkt.setFadeOut(tt.getFadeOut()); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java index c3c25d91c..6baa55046 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java @@ -25,6 +25,7 @@ import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_14; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_15; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_16; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_16_2; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_16_4; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_17; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_7_2; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_8; @@ -61,7 +62,12 @@ import com.velocitypowered.proxy.protocol.packet.StatusRequest; import com.velocitypowered.proxy.protocol.packet.StatusResponse; import com.velocitypowered.proxy.protocol.packet.TabCompleteRequest; import com.velocitypowered.proxy.protocol.packet.TabCompleteResponse; -import com.velocitypowered.proxy.protocol.packet.TitlePacket; +import com.velocitypowered.proxy.protocol.packet.title.LegacyTitlePacket; +import com.velocitypowered.proxy.protocol.packet.title.TitleActionbarPacket; +import com.velocitypowered.proxy.protocol.packet.title.TitleClearPacket; +import com.velocitypowered.proxy.protocol.packet.title.TitleSubtitlePacket; +import com.velocitypowered.proxy.protocol.packet.title.TitleTextPacket; +import com.velocitypowered.proxy.protocol.packet.title.TitleTimesPacket; import io.netty.util.collection.IntObjectHashMap; import io.netty.util.collection.IntObjectMap; import it.unimi.dsi.fastutil.objects.Object2IntMap; @@ -162,13 +168,13 @@ public enum StateRegistry { map(0x11, MINECRAFT_1_15, false), map(0x10, MINECRAFT_1_16, false), map(0x0F, MINECRAFT_1_16_2, false), - map(0x10, MINECRAFT_1_17, false)); + map(0x11, MINECRAFT_1_17, false)); clientbound.register(AvailableCommands.class, AvailableCommands::new, map(0x11, MINECRAFT_1_13, false), map(0x12, MINECRAFT_1_15, false), map(0x11, MINECRAFT_1_16, false), map(0x10, MINECRAFT_1_16_2, false), - map(0x11, MINECRAFT_1_17, false)); + map(0x12, MINECRAFT_1_17, false)); clientbound.register(PluginMessage.class, PluginMessage::new, map(0x3F, MINECRAFT_1_7_2, false), map(0x18, MINECRAFT_1_9, false), @@ -177,7 +183,7 @@ public enum StateRegistry { map(0x19, MINECRAFT_1_15, false), map(0x18, MINECRAFT_1_16, false), map(0x17, MINECRAFT_1_16_2, false), - map(0x18, MINECRAFT_1_17, false)); + map(0x19, MINECRAFT_1_17, false)); clientbound.register(Disconnect.class, Disconnect::new, map(0x40, MINECRAFT_1_7_2, false), map(0x1A, MINECRAFT_1_9, false), @@ -186,7 +192,7 @@ public enum StateRegistry { map(0x1B, MINECRAFT_1_15, false), map(0x1A, MINECRAFT_1_16, false), map(0x19, MINECRAFT_1_16_2, false), - map(0x1A, MINECRAFT_1_17, false)); + map(0x1B, MINECRAFT_1_17, false)); clientbound.register(KeepAlive.class, KeepAlive::new, map(0x00, MINECRAFT_1_7_2, false), map(0x1F, MINECRAFT_1_9, false), @@ -195,7 +201,7 @@ public enum StateRegistry { map(0x21, MINECRAFT_1_15, false), map(0x20, MINECRAFT_1_16, false), map(0x1F, MINECRAFT_1_16_2, false), - map(0x20, MINECRAFT_1_17, false)); + map(0x22, MINECRAFT_1_17, false)); clientbound.register(JoinGame.class, JoinGame::new, map(0x01, MINECRAFT_1_7_2, false), map(0x23, MINECRAFT_1_9, false), @@ -204,7 +210,7 @@ public enum StateRegistry { map(0x26, MINECRAFT_1_15, false), map(0x25, MINECRAFT_1_16, false), map(0x24, MINECRAFT_1_16_2, false), - map(0x25, MINECRAFT_1_17, false)); + map(0x27, MINECRAFT_1_17, false)); clientbound.register(Respawn.class, Respawn::new, map(0x07, MINECRAFT_1_7_2, true), map(0x33, MINECRAFT_1_9, true), @@ -215,7 +221,7 @@ public enum StateRegistry { map(0x3B, MINECRAFT_1_15, true), map(0x3A, MINECRAFT_1_16, true), map(0x39, MINECRAFT_1_16_2, true), - map(0x3A, MINECRAFT_1_17, true)); + map(0x3D, MINECRAFT_1_17, true)); clientbound.register(ResourcePackRequest.class, ResourcePackRequest::new, map(0x48, MINECRAFT_1_8, true), map(0x32, MINECRAFT_1_9, true), @@ -226,7 +232,7 @@ public enum StateRegistry { map(0x3A, MINECRAFT_1_15, true), map(0x39, MINECRAFT_1_16, true), map(0x38, MINECRAFT_1_16_2, true), - map(0x39, MINECRAFT_1_17, true)); + map(0x3C, MINECRAFT_1_17, true)); clientbound.register(HeaderAndFooter.class, HeaderAndFooter::new, map(0x47, MINECRAFT_1_8, true), map(0x48, MINECRAFT_1_9, true), @@ -237,8 +243,8 @@ public enum StateRegistry { map(0x53, MINECRAFT_1_14, true), map(0x54, MINECRAFT_1_15, true), map(0x53, MINECRAFT_1_16, true), - map(0x54, MINECRAFT_1_17, true)); - clientbound.register(TitlePacket.class, TitlePacket::new, + map(0x5E, MINECRAFT_1_17, true)); + clientbound.register(LegacyTitlePacket.class, LegacyTitlePacket::new, map(0x45, MINECRAFT_1_8, true), map(0x45, MINECRAFT_1_9, true), map(0x47, MINECRAFT_1_12, true), @@ -246,8 +252,17 @@ public enum StateRegistry { map(0x4B, MINECRAFT_1_13, true), map(0x4F, MINECRAFT_1_14, true), map(0x50, MINECRAFT_1_15, true), - map(0x4F, MINECRAFT_1_16, true), - map(0x50, MINECRAFT_1_17, true)); + map(0x4F, MINECRAFT_1_16, MINECRAFT_1_16_4, true)); + clientbound.register(TitleSubtitlePacket.class, TitleSubtitlePacket::new, // TODO: fix + map(0x57, MINECRAFT_1_17, true)); + clientbound.register(TitleTextPacket.class, TitleTextPacket::new, // TODO: fix + map(0x5A, MINECRAFT_1_17, true)); + clientbound.register(TitleActionbarPacket.class, TitleActionbarPacket::new, // TODO: fix + map(0x41, MINECRAFT_1_17, true)); + clientbound.register(TitleTimesPacket.class, TitleTimesPacket::new, // TODO: fix + map(0x59, MINECRAFT_1_17, true)); + clientbound.register(TitleClearPacket.class, TitleClearPacket::new, // TODO: fix + map(0x10, MINECRAFT_1_17, true)); clientbound.register(PlayerListItem.class, PlayerListItem::new, map(0x38, MINECRAFT_1_7_2, false), map(0x2D, MINECRAFT_1_9, false), @@ -257,7 +272,7 @@ public enum StateRegistry { map(0x34, MINECRAFT_1_15, false), map(0x33, MINECRAFT_1_16, false), map(0x32, MINECRAFT_1_16_2, false), - map(0x33, MINECRAFT_1_17, false)); + map(0x36, MINECRAFT_1_17, false)); } }, LOGIN { @@ -325,8 +340,20 @@ public enum StateRegistry { for (int i = 0; i < mappings.length; i++) { PacketMapping current = mappings[i]; PacketMapping next = (i + 1 < mappings.length) ? mappings[i + 1] : current; + ProtocolVersion from = current.protocolVersion; - ProtocolVersion to = current == next ? getLast(SUPPORTED_VERSIONS) : next.protocolVersion; + ProtocolVersion lastValid = current.lastValidProtocolVersion; + if (lastValid != null) { + if (next != current) { + throw new IllegalArgumentException("Cannot add a mapping after last valid mapping"); + } + if (from.compareTo(lastValid) > 0) { + throw new IllegalArgumentException( + "Last mapping version cannot be higher than highest mapping version"); + } + } + ProtocolVersion to = current == next ? lastValid != null + ? lastValid : getLast(SUPPORTED_VERSIONS) : next.protocolVersion; if (from.compareTo(to) >= 0 && from != getLast(SUPPORTED_VERSIONS)) { throw new IllegalArgumentException(String.format( @@ -414,10 +441,13 @@ public enum StateRegistry { private final int id; private final ProtocolVersion protocolVersion; private final boolean encodeOnly; + private final @Nullable ProtocolVersion lastValidProtocolVersion; - PacketMapping(int id, ProtocolVersion protocolVersion, boolean packetDecoding) { + PacketMapping(int id, ProtocolVersion protocolVersion, + ProtocolVersion lastValidProtocolVersion, boolean packetDecoding) { this.id = id; this.protocolVersion = protocolVersion; + this.lastValidProtocolVersion = lastValidProtocolVersion; this.encodeOnly = packetDecoding; } @@ -459,7 +489,21 @@ public enum StateRegistry { * @return PacketMapping with the provided arguments */ private static PacketMapping map(int id, ProtocolVersion version, boolean encodeOnly) { - return new PacketMapping(id, version, encodeOnly); + return map(id, version, null, encodeOnly); + } + + /** + * Creates a PacketMapping using the provided arguments. + * + * @param id Packet Id + * @param version Protocol version + * @param encodeOnly When true packet decoding will be disabled + * @param lastValidProtocolVersion Last version this Mapping is valid at + * @return PacketMapping with the provided arguments + */ + private static PacketMapping map(int id, ProtocolVersion version, + ProtocolVersion lastValidProtocolVersion, boolean encodeOnly) { + return new PacketMapping(id, version, lastValidProtocolVersion, encodeOnly); } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TitlePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TitlePacket.java deleted file mode 100644 index 49fe876df..000000000 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TitlePacket.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2018 Velocity Contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.velocitypowered.proxy.protocol.packet; - -import com.velocitypowered.api.network.ProtocolVersion; -import com.velocitypowered.proxy.connection.MinecraftSessionHandler; -import com.velocitypowered.proxy.protocol.MinecraftPacket; -import com.velocitypowered.proxy.protocol.ProtocolUtils; -import io.netty.buffer.ByteBuf; -import org.checkerframework.checker.nullness.qual.Nullable; - -public class TitlePacket implements MinecraftPacket { - - public static final int SET_TITLE = 0; - public static final int SET_SUBTITLE = 1; - public static final int SET_ACTION_BAR = 2; - public static final int SET_TIMES = 3; - public static final int SET_TIMES_OLD = 2; - public static final int HIDE = 4; - public static final int HIDE_OLD = 3; - public static final int RESET = 5; - public static final int RESET_OLD = 4; - - private int action; - private @Nullable String component; - private int fadeIn; - private int stay; - private int fadeOut; - - @Override - public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { - throw new UnsupportedOperationException(); // encode only - } - - @Override - public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { - ProtocolUtils.writeVarInt(buf, action); - if (version.compareTo(ProtocolVersion.MINECRAFT_1_11) >= 0) { - // 1.11+ shifted the action enum by 1 to handle the action bar - switch (action) { - case SET_TITLE: - case SET_SUBTITLE: - case SET_ACTION_BAR: - if (component == null) { - throw new IllegalStateException("No component found for " + action); - } - ProtocolUtils.writeString(buf, component); - break; - case SET_TIMES: - buf.writeInt(fadeIn); - buf.writeInt(stay); - buf.writeInt(fadeOut); - break; - case HIDE: - case RESET: - break; - default: - throw new UnsupportedOperationException("Unknown action " + action); - } - } else { - switch (action) { - case SET_TITLE: - case SET_SUBTITLE: - if (component == null) { - throw new IllegalStateException("No component found for " + action); - } - ProtocolUtils.writeString(buf, component); - break; - case SET_TIMES_OLD: - buf.writeInt(fadeIn); - buf.writeInt(stay); - buf.writeInt(fadeOut); - break; - case HIDE_OLD: - case RESET_OLD: - break; - default: - throw new UnsupportedOperationException("Unknown action " + action); - } - } - } - - public int getAction() { - return action; - } - - public void setAction(int action) { - this.action = action; - } - - public @Nullable String getComponent() { - return component; - } - - public void setComponent(@Nullable String component) { - this.component = component; - } - - public int getFadeIn() { - return fadeIn; - } - - public void setFadeIn(int fadeIn) { - this.fadeIn = fadeIn; - } - - public int getStay() { - return stay; - } - - public void setStay(int stay) { - this.stay = stay; - } - - public int getFadeOut() { - return fadeOut; - } - - public void setFadeOut(int fadeOut) { - this.fadeOut = fadeOut; - } - - public static TitlePacket hideForProtocolVersion(ProtocolVersion version) { - TitlePacket packet = new TitlePacket(); - packet.setAction(version.compareTo(ProtocolVersion.MINECRAFT_1_11) >= 0 ? TitlePacket.HIDE - : TitlePacket.HIDE_OLD); - return packet; - } - - public static TitlePacket resetForProtocolVersion(ProtocolVersion version) { - TitlePacket packet = new TitlePacket(); - packet.setAction(version.compareTo(ProtocolVersion.MINECRAFT_1_11) >= 0 ? TitlePacket.RESET - : TitlePacket.RESET_OLD); - return packet; - } - - public static TitlePacket timesForProtocolVersion(ProtocolVersion version) { - TitlePacket packet = new TitlePacket(); - packet.setAction(version.compareTo(ProtocolVersion.MINECRAFT_1_11) >= 0 ? TitlePacket.SET_TIMES - : TitlePacket.SET_TIMES_OLD); - return packet; - } - - @Override - public String toString() { - return "TitlePacket{" - + "action=" + action - + ", component='" + component + '\'' - + ", fadeIn=" + fadeIn - + ", stay=" + stay - + ", fadeOut=" + fadeOut - + '}'; - } - - @Override - public boolean handle(MinecraftSessionHandler handler) { - return handler.handle(this); - } -} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/GenericTitlePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/GenericTitlePacket.java new file mode 100644 index 000000000..38c890c03 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/GenericTitlePacket.java @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2018 Velocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.velocitypowered.proxy.protocol.packet.title; + +import com.velocitypowered.api.network.ProtocolVersion; +import com.velocitypowered.proxy.protocol.MinecraftPacket; +import com.velocitypowered.proxy.protocol.ProtocolUtils; +import io.netty.buffer.ByteBuf; +import org.checkerframework.checker.nullness.qual.Nullable; + +public abstract class GenericTitlePacket implements MinecraftPacket { + + public enum ActionType { + SET_TITLE(0), + SET_SUBTITLE(1), + SET_ACTION_BAR(2), + SET_TIMES(3), + HIDE(4), + RESET(5); + + private final int action; + + ActionType(int action) { + this.action = action; + } + + public int getAction(ProtocolVersion version) { + return version.compareTo(ProtocolVersion.MINECRAFT_1_11) < 0 + ? action > 2 ? action - 1 : action : action; + } + } + + + private ActionType action; + + protected void setAction(ActionType action) { + this.action = action; + } + + public final ActionType getAction() { + return action; + } + + public String getComponent() { + throw new UnsupportedOperationException("Invalid function for this TitlePacket ActionType"); + } + + public void setComponent(String component) { + throw new UnsupportedOperationException("Invalid function for this TitlePacket ActionType"); + } + + public int getFadeIn() { + throw new UnsupportedOperationException("Invalid function for this TitlePacket ActionType"); + } + + public void setFadeIn(int fadeIn) { + throw new UnsupportedOperationException("Invalid function for this TitlePacket ActionType"); + } + + public int getStay() { + throw new UnsupportedOperationException("Invalid function for this TitlePacket ActionType"); + } + + public void setStay(int stay) { + throw new UnsupportedOperationException("Invalid function for this TitlePacket ActionType"); + } + + public int getFadeOut() { + throw new UnsupportedOperationException("Invalid function for this TitlePacket ActionType"); + } + + public void setFadeOut(int fadeOut) { + throw new UnsupportedOperationException("Invalid function for this TitlePacket ActionType"); + } + + + + @Override + public final void decode(ByteBuf buf, ProtocolUtils.Direction direction, + ProtocolVersion version) { + throw new UnsupportedOperationException(); // encode only + } + + /** + * Creates a version and type dependent TitlePacket. + * + * @param type Action the packet should invoke + * @param version Protocol version of the target player + * @return GenericTitlePacket instance that follows the invoker type/version + */ + public static GenericTitlePacket constructTitlePacket(ActionType type, ProtocolVersion version) { + GenericTitlePacket packet = null; + if (version.compareTo(ProtocolVersion.MINECRAFT_1_17) >= 0) { + switch (type) { + case SET_ACTION_BAR: + packet = new TitleActionbarPacket(); + break; + case SET_SUBTITLE: + packet = new TitleSubtitlePacket(); + break; + case SET_TIMES: + packet = new TitleTimesPacket(); + break; + case SET_TITLE: + packet = new TitleTextPacket(); + break; + case HIDE: + case RESET: + packet = new TitleClearPacket(); + break; + default: + throw new IllegalArgumentException("Invalid ActionType"); + } + } else { + packet = new LegacyTitlePacket(); + } + packet.setAction(type); + return packet; + } + +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/LegacyTitlePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/LegacyTitlePacket.java new file mode 100644 index 000000000..7b25325e6 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/LegacyTitlePacket.java @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2018 Velocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.velocitypowered.proxy.protocol.packet.title; + +import com.velocitypowered.api.network.ProtocolVersion; +import com.velocitypowered.proxy.connection.MinecraftSessionHandler; +import com.velocitypowered.proxy.protocol.ProtocolUtils; +import io.netty.buffer.ByteBuf; +import org.checkerframework.checker.nullness.qual.Nullable; + +public class LegacyTitlePacket extends GenericTitlePacket { + + private @Nullable String component; + private int fadeIn; + private int stay; + private int fadeOut; + + @Override + public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { + if (version.compareTo(ProtocolVersion.MINECRAFT_1_11) < 0 + && getAction() == ActionType.SET_ACTION_BAR) { + throw new IllegalStateException("Action bars are only supported on 1.11 and newer"); + } + ProtocolUtils.writeVarInt(buf, getAction().getAction(version)); + + switch (getAction()) { + case SET_TITLE: + case SET_SUBTITLE: + case SET_ACTION_BAR: + if (component == null) { + throw new IllegalStateException("No component found for " + getAction()); + } + ProtocolUtils.writeString(buf, component); + break; + case SET_TIMES: + buf.writeInt(fadeIn); + buf.writeInt(stay); + buf.writeInt(fadeOut); + break; + case HIDE: + case RESET: + break; + default: + throw new UnsupportedOperationException("Unknown action " + getAction()); + } + + } + + @Override + public void setAction(ActionType action) { + super.setAction(action); + } + + @Override + public @Nullable String getComponent() { + return component; + } + + @Override + public void setComponent(@Nullable String component) { + this.component = component; + } + + @Override + public int getFadeIn() { + return fadeIn; + } + + @Override + public void setFadeIn(int fadeIn) { + this.fadeIn = fadeIn; + } + + @Override + public int getStay() { + return stay; + } + + @Override + public void setStay(int stay) { + this.stay = stay; + } + + @Override + public int getFadeOut() { + return fadeOut; + } + + @Override + public void setFadeOut(int fadeOut) { + this.fadeOut = fadeOut; + } + + @Override + public String toString() { + return "GenericTitlePacket{" + + "action=" + getAction() + + ", component='" + component + '\'' + + ", fadeIn=" + fadeIn + + ", stay=" + stay + + ", fadeOut=" + fadeOut + + '}'; + } + + @Override + public boolean handle(MinecraftSessionHandler handler) { + return handler.handle(this); + } +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleActionbarPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleActionbarPacket.java new file mode 100644 index 000000000..e875ae3cd --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleActionbarPacket.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2018 Velocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.velocitypowered.proxy.protocol.packet.title; + +import com.velocitypowered.api.network.ProtocolVersion; +import com.velocitypowered.proxy.connection.MinecraftSessionHandler; +import com.velocitypowered.proxy.protocol.ProtocolUtils; +import io.netty.buffer.ByteBuf; + +public class TitleActionbarPacket extends GenericTitlePacket { + + private String component; + + public TitleActionbarPacket() { + setAction(ActionType.SET_TITLE); + } + + @Override + public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { + ProtocolUtils.writeString(buf, component); + } + + @Override + public String getComponent() { + return component; + } + + @Override + public void setComponent(String component) { + this.component = component; + } + + @Override + public String toString() { + return "TitleActionbarPacket{" + + ", component='" + component + '\'' + + '}'; + } + + @Override + public boolean handle(MinecraftSessionHandler handler) { + return handler.handle(this); + } +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleClearPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleClearPacket.java new file mode 100644 index 000000000..8ee0289ab --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleClearPacket.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2018 Velocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.velocitypowered.proxy.protocol.packet.title; + +import com.velocitypowered.api.network.ProtocolVersion; +import com.velocitypowered.proxy.connection.MinecraftSessionHandler; +import com.velocitypowered.proxy.protocol.ProtocolUtils; +import io.netty.buffer.ByteBuf; + +public class TitleClearPacket extends GenericTitlePacket { + + private boolean resetTimes; + + public TitleClearPacket() { + setAction(ActionType.HIDE); + } + + @Override + public void setAction(ActionType action) { + if (action != ActionType.HIDE && action != ActionType.RESET) { + throw new IllegalArgumentException("TitleClearPacket only accepts CLEAR and RESET actions"); + } + super.setAction(action); + } + + @Override + public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { + buf.writeBoolean(getAction() == ActionType.RESET); + } + + @Override + public String toString() { + return "TitleClearPacket{" + + ", reset=" + resetTimes + + '}'; + } + + @Override + public boolean handle(MinecraftSessionHandler handler) { + return handler.handle(this); + } +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleSubtitlePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleSubtitlePacket.java new file mode 100644 index 000000000..1640862f7 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleSubtitlePacket.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2018 Velocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.velocitypowered.proxy.protocol.packet.title; + +import com.velocitypowered.api.network.ProtocolVersion; +import com.velocitypowered.proxy.connection.MinecraftSessionHandler; +import com.velocitypowered.proxy.protocol.ProtocolUtils; +import io.netty.buffer.ByteBuf; + +public class TitleSubtitlePacket extends GenericTitlePacket { + + private String component; + + public TitleSubtitlePacket() { + setAction(ActionType.SET_SUBTITLE); + } + + @Override + public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { + ProtocolUtils.writeString(buf, component); + } + + @Override + public String getComponent() { + return component; + } + + @Override + public void setComponent(String component) { + this.component = component; + } + + @Override + public String toString() { + return "TitleSubtitlePacket{" + + ", component='" + component + '\'' + + '}'; + } + + @Override + public boolean handle(MinecraftSessionHandler handler) { + return handler.handle(this); + } +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleTextPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleTextPacket.java new file mode 100644 index 000000000..135eb27e4 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleTextPacket.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2018 Velocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.velocitypowered.proxy.protocol.packet.title; + +import com.velocitypowered.api.network.ProtocolVersion; +import com.velocitypowered.proxy.connection.MinecraftSessionHandler; +import com.velocitypowered.proxy.protocol.ProtocolUtils; +import io.netty.buffer.ByteBuf; + +public class TitleTextPacket extends GenericTitlePacket { + + private String component; + + public TitleTextPacket() { + setAction(ActionType.SET_TITLE); + } + + @Override + public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { + ProtocolUtils.writeString(buf, component); + } + + @Override + public String getComponent() { + return component; + } + + @Override + public void setComponent(String component) { + this.component = component; + } + + @Override + public String toString() { + return "TitleTextPacket{" + + ", component='" + component + '\'' + + '}'; + } + + @Override + public boolean handle(MinecraftSessionHandler handler) { + return handler.handle(this); + } +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleTimesPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleTimesPacket.java new file mode 100644 index 000000000..7450caccd --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleTimesPacket.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2018 Velocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.velocitypowered.proxy.protocol.packet.title; + +import com.velocitypowered.api.network.ProtocolVersion; +import com.velocitypowered.proxy.connection.MinecraftSessionHandler; +import com.velocitypowered.proxy.protocol.ProtocolUtils; +import io.netty.buffer.ByteBuf; + +public class TitleTimesPacket extends GenericTitlePacket { + + private int fadeIn; + private int stay; + private int fadeOut; + + public TitleTimesPacket() { + setAction(ActionType.SET_TIMES); + } + + @Override + public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { + buf.writeInt(fadeIn); + buf.writeInt(stay); + buf.writeInt(fadeOut); + } + + @Override + public int getFadeIn() { + return fadeIn; + } + + @Override + public void setFadeIn(int fadeIn) { + this.fadeIn = fadeIn; + } + + @Override + public int getStay() { + return stay; + } + + @Override + public void setStay(int stay) { + this.stay = stay; + } + + @Override + public int getFadeOut() { + return fadeOut; + } + + @Override + public void setFadeOut(int fadeOut) { + this.fadeOut = fadeOut; + } + + @Override + public String toString() { + return "TitleTimesPacket{" + + ", fadeIn=" + fadeIn + + ", stay=" + stay + + ", fadeOut=" + fadeOut + + '}'; + } + + @Override + public boolean handle(MinecraftSessionHandler handler) { + return handler.handle(this); + } +} diff --git a/proxy/src/test/java/com/velocitypowered/proxy/protocol/PacketRegistryTest.java b/proxy/src/test/java/com/velocitypowered/proxy/protocol/PacketRegistryTest.java index 1780d14ac..b2f6e857a 100644 --- a/proxy/src/test/java/com/velocitypowered/proxy/protocol/PacketRegistryTest.java +++ b/proxy/src/test/java/com/velocitypowered/proxy/protocol/PacketRegistryTest.java @@ -23,7 +23,11 @@ import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_12; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_12_1; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_12_2; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_13; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_14; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_14_2; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_15; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_16; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_16_2; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_8; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -43,8 +47,9 @@ class PacketRegistryTest { StateRegistry.PacketRegistry registry = new StateRegistry.PacketRegistry( ProtocolUtils.Direction.CLIENTBOUND); registry.register(Handshake.class, Handshake::new, - new StateRegistry.PacketMapping(0x01, MINECRAFT_1_8, false), - new StateRegistry.PacketMapping(0x00, MINECRAFT_1_12, false)); + new StateRegistry.PacketMapping(0x01, MINECRAFT_1_8, null, false), + new StateRegistry.PacketMapping(0x00, MINECRAFT_1_12, null, false), + new StateRegistry.PacketMapping(0x00, MINECRAFT_1_15, MINECRAFT_1_16, false)); return registry; } @@ -73,6 +78,8 @@ class PacketRegistryTest { "Registry did not return the correct packet ID"); assertNull(registry.getProtocolRegistry(MINECRAFT_1_14_2).createPacket(0x01), "Registry should return a null"); + assertNull(registry.getProtocolRegistry(MINECRAFT_1_16_2).createPacket(0), + "Registry should return null"); } @Test @@ -91,12 +98,19 @@ class PacketRegistryTest { ProtocolUtils.Direction.CLIENTBOUND); assertThrows(IllegalArgumentException.class, () -> registry.register(Handshake.class, Handshake::new, - new StateRegistry.PacketMapping(0x01, MINECRAFT_1_13, false), - new StateRegistry.PacketMapping(0x00, MINECRAFT_1_8, false))); + new StateRegistry.PacketMapping(0x01, MINECRAFT_1_13, null, false), + new StateRegistry.PacketMapping(0x00, MINECRAFT_1_8, null, false))); assertThrows(IllegalArgumentException.class, () -> registry.register(Handshake.class, Handshake::new, - new StateRegistry.PacketMapping(0x01, MINECRAFT_1_13, false), - new StateRegistry.PacketMapping(0x01, MINECRAFT_1_13, false))); + new StateRegistry.PacketMapping(0x01, MINECRAFT_1_13, null, false), + new StateRegistry.PacketMapping(0x01, MINECRAFT_1_13, null, false))); + assertThrows(IllegalArgumentException.class, + () -> registry.register(Handshake.class, Handshake::new, + new StateRegistry.PacketMapping(0x01, MINECRAFT_1_13, MINECRAFT_1_8, false))); + assertThrows(IllegalArgumentException.class, + () -> registry.register(Handshake.class, Handshake::new, + new StateRegistry.PacketMapping(0x01, MINECRAFT_1_8, MINECRAFT_1_14, false), + new StateRegistry.PacketMapping(0x00, MINECRAFT_1_16, null, false))); } @Test @@ -104,13 +118,13 @@ class PacketRegistryTest { StateRegistry.PacketRegistry registry = new StateRegistry.PacketRegistry( ProtocolUtils.Direction.CLIENTBOUND); registry.register(Handshake.class, Handshake::new, - new StateRegistry.PacketMapping(0x00, MINECRAFT_1_8, false)); + new StateRegistry.PacketMapping(0x00, MINECRAFT_1_8, null, false)); assertThrows(IllegalArgumentException.class, () -> registry.register(Handshake.class, Handshake::new, - new StateRegistry.PacketMapping(0x01, MINECRAFT_1_12, false))); + new StateRegistry.PacketMapping(0x01, MINECRAFT_1_12, null, false))); assertThrows(IllegalArgumentException.class, () -> registry.register(StatusPing.class, StatusPing::new, - new StateRegistry.PacketMapping(0x00, MINECRAFT_1_13, false))); + new StateRegistry.PacketMapping(0x00, MINECRAFT_1_13, null, false))); } @Test @@ -118,9 +132,9 @@ class PacketRegistryTest { StateRegistry.PacketRegistry registry = new StateRegistry.PacketRegistry( ProtocolUtils.Direction.CLIENTBOUND); assertDoesNotThrow(() -> registry.register(Handshake.class, Handshake::new, - new StateRegistry.PacketMapping(0x00, MINECRAFT_1_8, false), + new StateRegistry.PacketMapping(0x00, MINECRAFT_1_8, null, false), new StateRegistry.PacketMapping(0x01, getLast(ProtocolVersion.SUPPORTED_VERSIONS), - false))); + null, false))); } @Test @@ -128,9 +142,9 @@ class PacketRegistryTest { StateRegistry.PacketRegistry registry = new StateRegistry.PacketRegistry( ProtocolUtils.Direction.CLIENTBOUND); registry.register(Handshake.class, Handshake::new, - new StateRegistry.PacketMapping(0x00, MINECRAFT_1_12, false), - new StateRegistry.PacketMapping(0x01, MINECRAFT_1_12_1, false), - new StateRegistry.PacketMapping(0x02, MINECRAFT_1_13, false)); + new StateRegistry.PacketMapping(0x00, MINECRAFT_1_12, null, false), + new StateRegistry.PacketMapping(0x01, MINECRAFT_1_12_1, null, false), + new StateRegistry.PacketMapping(0x02, MINECRAFT_1_13, null, false)); assertEquals(Handshake.class, registry.getProtocolRegistry(MINECRAFT_1_12).createPacket(0x00).getClass()); assertEquals(Handshake.class, From 6207647aae96021a113e30c2b0acef83c3d0b728 Mon Sep 17 00:00:00 2001 From: "Five (Xer)" Date: Thu, 25 Feb 2021 14:49:29 +0100 Subject: [PATCH 13/30] Remove leftovers --- .../velocitypowered/proxy/protocol/StateRegistry.java | 10 +++++----- .../proxy/protocol/packet/title/TitleClearPacket.java | 4 +--- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java index 6baa55046..243239eb0 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java @@ -253,15 +253,15 @@ public enum StateRegistry { map(0x4F, MINECRAFT_1_14, true), map(0x50, MINECRAFT_1_15, true), map(0x4F, MINECRAFT_1_16, MINECRAFT_1_16_4, true)); - clientbound.register(TitleSubtitlePacket.class, TitleSubtitlePacket::new, // TODO: fix + clientbound.register(TitleSubtitlePacket.class, TitleSubtitlePacket::new, map(0x57, MINECRAFT_1_17, true)); - clientbound.register(TitleTextPacket.class, TitleTextPacket::new, // TODO: fix + clientbound.register(TitleTextPacket.class, TitleTextPacket::new, map(0x5A, MINECRAFT_1_17, true)); - clientbound.register(TitleActionbarPacket.class, TitleActionbarPacket::new, // TODO: fix + clientbound.register(TitleActionbarPacket.class, TitleActionbarPacket::new, map(0x41, MINECRAFT_1_17, true)); - clientbound.register(TitleTimesPacket.class, TitleTimesPacket::new, // TODO: fix + clientbound.register(TitleTimesPacket.class, TitleTimesPacket::new, map(0x59, MINECRAFT_1_17, true)); - clientbound.register(TitleClearPacket.class, TitleClearPacket::new, // TODO: fix + clientbound.register(TitleClearPacket.class, TitleClearPacket::new, map(0x10, MINECRAFT_1_17, true)); clientbound.register(PlayerListItem.class, PlayerListItem::new, map(0x38, MINECRAFT_1_7_2, false), diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleClearPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleClearPacket.java index 8ee0289ab..626abb517 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleClearPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleClearPacket.java @@ -24,8 +24,6 @@ import io.netty.buffer.ByteBuf; public class TitleClearPacket extends GenericTitlePacket { - private boolean resetTimes; - public TitleClearPacket() { setAction(ActionType.HIDE); } @@ -46,7 +44,7 @@ public class TitleClearPacket extends GenericTitlePacket { @Override public String toString() { return "TitleClearPacket{" - + ", reset=" + resetTimes + + ", resetTimes=" + (getAction() == ActionType.RESET) + '}'; } From 581303a54c9263b05191f629f9c9c574bb873443 Mon Sep 17 00:00:00 2001 From: "Five (Xer)" Date: Thu, 11 Mar 2021 09:53:55 +0100 Subject: [PATCH 14/30] Snaphot 21w10a --- .../api/network/ProtocolVersion.java | 2 +- .../proxy/protocol/StateRegistry.java | 31 ++++++++++--------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index 0149970e6..13d2c8124 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 16, "1.17"); // Snapshot: 21w08a, future protocol: 755 + MINECRAFT_1_17(-1, 18, "1.17"); // Snapshot: 21w10a, future protocol: 755 private static final int SNAPSHOT_BIT = 30; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java index 243239eb0..213e15222 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java @@ -131,7 +131,8 @@ public enum StateRegistry { map(0x0A, MINECRAFT_1_12, false), map(0x09, MINECRAFT_1_12_1, false), map(0x0A, MINECRAFT_1_13, false), - map(0x0B, MINECRAFT_1_14, false)); + map(0x0B, MINECRAFT_1_14, false), + map(0x0A, MINECRAFT_1_17, false)); serverbound.register(KeepAlive.class, KeepAlive::new, map(0x00, MINECRAFT_1_7_2, false), map(0x0B, MINECRAFT_1_9, false), @@ -139,7 +140,8 @@ public enum StateRegistry { map(0x0B, MINECRAFT_1_12_1, false), map(0x0E, MINECRAFT_1_13, false), map(0x0F, MINECRAFT_1_14, false), - map(0x10, MINECRAFT_1_16, false)); + map(0x10, MINECRAFT_1_16, false), + map(0x0F, MINECRAFT_1_17, false)); serverbound.register(ResourcePackResponse.class, ResourcePackResponse::new, map(0x19, MINECRAFT_1_8, false), map(0x16, MINECRAFT_1_9, false), @@ -147,7 +149,8 @@ public enum StateRegistry { map(0x1D, MINECRAFT_1_13, false), map(0x1F, MINECRAFT_1_14, false), map(0x20, MINECRAFT_1_16, false), - map(0x21, MINECRAFT_1_16_2, false)); + map(0x21, MINECRAFT_1_16_2, false), + map(0x20, MINECRAFT_1_17, false)); clientbound.register(BossBar.class, BossBar::new, map(0x0C, MINECRAFT_1_9, false), @@ -183,7 +186,7 @@ public enum StateRegistry { map(0x19, MINECRAFT_1_15, false), map(0x18, MINECRAFT_1_16, false), map(0x17, MINECRAFT_1_16_2, false), - map(0x19, MINECRAFT_1_17, false)); + map(0x18, MINECRAFT_1_17, false)); clientbound.register(Disconnect.class, Disconnect::new, map(0x40, MINECRAFT_1_7_2, false), map(0x1A, MINECRAFT_1_9, false), @@ -192,7 +195,7 @@ public enum StateRegistry { map(0x1B, MINECRAFT_1_15, false), map(0x1A, MINECRAFT_1_16, false), map(0x19, MINECRAFT_1_16_2, false), - map(0x1B, MINECRAFT_1_17, false)); + map(0x1A, MINECRAFT_1_17, false)); clientbound.register(KeepAlive.class, KeepAlive::new, map(0x00, MINECRAFT_1_7_2, false), map(0x1F, MINECRAFT_1_9, false), @@ -201,7 +204,7 @@ public enum StateRegistry { map(0x21, MINECRAFT_1_15, false), map(0x20, MINECRAFT_1_16, false), map(0x1F, MINECRAFT_1_16_2, false), - map(0x22, MINECRAFT_1_17, false)); + map(0x21, MINECRAFT_1_17, false)); clientbound.register(JoinGame.class, JoinGame::new, map(0x01, MINECRAFT_1_7_2, false), map(0x23, MINECRAFT_1_9, false), @@ -210,7 +213,7 @@ public enum StateRegistry { map(0x26, MINECRAFT_1_15, false), map(0x25, MINECRAFT_1_16, false), map(0x24, MINECRAFT_1_16_2, false), - map(0x27, MINECRAFT_1_17, false)); + map(0x26, MINECRAFT_1_17, false)); clientbound.register(Respawn.class, Respawn::new, map(0x07, MINECRAFT_1_7_2, true), map(0x33, MINECRAFT_1_9, true), @@ -221,7 +224,7 @@ public enum StateRegistry { map(0x3B, MINECRAFT_1_15, true), map(0x3A, MINECRAFT_1_16, true), map(0x39, MINECRAFT_1_16_2, true), - map(0x3D, MINECRAFT_1_17, true)); + map(0x3C, MINECRAFT_1_17, true)); clientbound.register(ResourcePackRequest.class, ResourcePackRequest::new, map(0x48, MINECRAFT_1_8, true), map(0x32, MINECRAFT_1_9, true), @@ -232,7 +235,7 @@ public enum StateRegistry { map(0x3A, MINECRAFT_1_15, true), map(0x39, MINECRAFT_1_16, true), map(0x38, MINECRAFT_1_16_2, true), - map(0x3C, MINECRAFT_1_17, true)); + map(0x3B, MINECRAFT_1_17, true)); clientbound.register(HeaderAndFooter.class, HeaderAndFooter::new, map(0x47, MINECRAFT_1_8, true), map(0x48, MINECRAFT_1_9, true), @@ -243,7 +246,7 @@ public enum StateRegistry { map(0x53, MINECRAFT_1_14, true), map(0x54, MINECRAFT_1_15, true), map(0x53, MINECRAFT_1_16, true), - map(0x5E, MINECRAFT_1_17, true)); + map(0x5D, MINECRAFT_1_17, true)); clientbound.register(LegacyTitlePacket.class, LegacyTitlePacket::new, map(0x45, MINECRAFT_1_8, true), map(0x45, MINECRAFT_1_9, true), @@ -254,11 +257,11 @@ public enum StateRegistry { map(0x50, MINECRAFT_1_15, true), map(0x4F, MINECRAFT_1_16, MINECRAFT_1_16_4, true)); clientbound.register(TitleSubtitlePacket.class, TitleSubtitlePacket::new, - map(0x57, MINECRAFT_1_17, true)); + map(0x56, MINECRAFT_1_17, true)); clientbound.register(TitleTextPacket.class, TitleTextPacket::new, - map(0x5A, MINECRAFT_1_17, true)); + map(0x58, MINECRAFT_1_17, true)); clientbound.register(TitleActionbarPacket.class, TitleActionbarPacket::new, - map(0x41, MINECRAFT_1_17, true)); + map(0x40, MINECRAFT_1_17, true)); clientbound.register(TitleTimesPacket.class, TitleTimesPacket::new, map(0x59, MINECRAFT_1_17, true)); clientbound.register(TitleClearPacket.class, TitleClearPacket::new, @@ -272,7 +275,7 @@ public enum StateRegistry { map(0x34, MINECRAFT_1_15, false), map(0x33, MINECRAFT_1_16, false), map(0x32, MINECRAFT_1_16_2, false), - map(0x36, MINECRAFT_1_17, false)); + map(0x35, MINECRAFT_1_17, false)); } }, LOGIN { From f6e023bf60b6f119c4b380c214121cf884035645 Mon Sep 17 00:00:00 2001 From: "Five (Xer)" Date: Wed, 17 Mar 2021 17:08:31 +0100 Subject: [PATCH 15/30] Snapshot 21w11a --- .../java/com/velocitypowered/api/network/ProtocolVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index 13d2c8124..1fbebd5c6 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 18, "1.17"); // Snapshot: 21w10a, future protocol: 755 + MINECRAFT_1_17(-1, 19, "1.17"); // Snapshot: 21w11a, future protocol: 755 private static final int SNAPSHOT_BIT = 30; From 625fa9b0ada6b656d713e828619ac083099b1d87 Mon Sep 17 00:00:00 2001 From: "Five (Xer)" Date: Wed, 31 Mar 2021 20:22:46 +0200 Subject: [PATCH 16/30] Snapshot 21w13a --- .../java/com/velocitypowered/api/network/ProtocolVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index 1fbebd5c6..cc4b641a1 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 19, "1.17"); // Snapshot: 21w11a, future protocol: 755 + MINECRAFT_1_17(-1, 20, "1.17"); // Snapshot: 21w13a, future protocol: 755 private static final int SNAPSHOT_BIT = 30; From 22202094958dc3a5a807f1e17b13ebc01a39f72b Mon Sep 17 00:00:00 2001 From: "Five (Xer)" Date: Wed, 14 Apr 2021 19:35:40 +0200 Subject: [PATCH 17/30] Snapshot 21w14a --- .../java/com/velocitypowered/api/network/ProtocolVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index cc4b641a1..5d843d88d 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 20, "1.17"); // Snapshot: 21w13a, future protocol: 755 + MINECRAFT_1_17(-1, 21, "1.17"); // Snapshot: 21w14a, future protocol: 755 private static final int SNAPSHOT_BIT = 30; From 8def411b2b99bf952d7f857196a4095c409ec9fd Mon Sep 17 00:00:00 2001 From: FivePB Date: Thu, 13 May 2021 17:06:27 +0200 Subject: [PATCH 18/30] Snapshot 21w15a --- .../player/PlayerResourcePackStatusEvent.java | 61 ++++++++ .../api/network/ProtocolVersion.java | 2 +- .../com/velocitypowered/api/proxy/Player.java | 54 ++++--- .../api/proxy/ProxyServer.java | 21 +++ .../api/proxy/player/ResourcePackInfo.java | 120 +++++++++++++++ .../velocitypowered/proxy/VelocityServer.java | 7 + .../backend/BackendPlaySessionHandler.java | 19 +++ .../client/ClientPlaySessionHandler.java | 7 +- .../connection/client/ConnectedPlayer.java | 139 ++++++++++++++++-- .../player/VelocityResourcePackInfo.java | 110 ++++++++++++++ .../proxy/protocol/StateRegistry.java | 20 +-- .../protocol/packet/ResourcePackRequest.java | 24 +++ .../protocol/packet/ResourcePackResponse.java | 4 + 13 files changed, 540 insertions(+), 48 deletions(-) create mode 100644 api/src/main/java/com/velocitypowered/api/proxy/player/ResourcePackInfo.java create mode 100644 proxy/src/main/java/com/velocitypowered/proxy/connection/player/VelocityResourcePackInfo.java diff --git a/api/src/main/java/com/velocitypowered/api/event/player/PlayerResourcePackStatusEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/PlayerResourcePackStatusEvent.java index 5bffcce89..a490b6791 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/PlayerResourcePackStatusEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/PlayerResourcePackStatusEvent.java @@ -8,7 +8,11 @@ package com.velocitypowered.api.event.player; import com.google.common.base.Preconditions; +import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.api.proxy.player.ResourcePackInfo; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.checkerframework.checker.nullness.qual.Nullable; /** * This event is fired when the status of a resource pack sent to the player by the server is @@ -18,10 +22,29 @@ public class PlayerResourcePackStatusEvent { private final Player player; private final Status status; + private final @MonotonicNonNull ResourcePackInfo packInfo; + private boolean overwriteKick; + + /** + * Instates this event. + * @deprecated Use {@link PlayerResourcePackStatusEvent#PlayerResourcePackStatusEvent + * (Player, Status, ResourcePackInfo)} instead. + */ + @Deprecated public PlayerResourcePackStatusEvent(Player player, Status status) { this.player = Preconditions.checkNotNull(player, "player"); this.status = Preconditions.checkNotNull(status, "status"); + this.packInfo = null; + } + + /** + * Instates this event. + */ + public PlayerResourcePackStatusEvent(Player player, Status status, ResourcePackInfo packInfo) { + this.player = Preconditions.checkNotNull(player, "player"); + this.status = Preconditions.checkNotNull(status, "status"); + this.packInfo = packInfo; } /** @@ -42,11 +65,49 @@ public class PlayerResourcePackStatusEvent { return status; } + /** + * Returns the {@link ResourcePackInfo} this response is for. + * + * @return the resource-pack info or null if no request was recorded + */ + @Nullable + public ResourcePackInfo getPackInfo() { + return packInfo; + } + + /** + * Gets whether or not to override the kick resulting from + * {@link ResourcePackInfo#getShouldForce()} being true. + * + * @return whether or not to overwrite the result + */ + public boolean isOverwriteKick() { + return overwriteKick; + } + + /** + * Set to true to prevent {@link ResourcePackInfo#getShouldForce()} + * from kicking the player. + * Overwriting this kick is only possible on versions older than 1.17, + * as the client or server will enforce this regardless. Cancelling the resulting + * kick-events will not prevent the player from disconnecting from the proxy. + * + * @param overwriteKick whether or not to cancel the kick + * @throws IllegalArgumentException if the player version is 1.17 or newer + */ + public void setOverwriteKick(boolean overwriteKick) { + Preconditions.checkArgument(player.getProtocolVersion() + .compareTo(ProtocolVersion.MINECRAFT_1_17) < 0, + "overwriteKick is not supported on 1.17 or newer"); + this.overwriteKick = overwriteKick; + } + @Override public String toString() { return "PlayerResourcePackStatusEvent{" + "player=" + player + ", status=" + status + + ", packInfo=" + packInfo + '}'; } diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index 5d843d88d..10b3595f6 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 21, "1.17"); // Snapshot: 21w14a, future protocol: 755 + MINECRAFT_1_17(-1, 22, "1.17"); // Snapshot: 21w15a, future protocol: 755 private static final int SNAPSHOT_BIT = 30; diff --git a/api/src/main/java/com/velocitypowered/api/proxy/Player.java b/api/src/main/java/com/velocitypowered/api/proxy/Player.java index 5fb68d4c9..d22f0caf2 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/Player.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/Player.java @@ -13,6 +13,7 @@ import com.velocitypowered.api.proxy.messages.ChannelIdentifier; import com.velocitypowered.api.proxy.messages.ChannelMessageSink; import com.velocitypowered.api.proxy.messages.ChannelMessageSource; import com.velocitypowered.api.proxy.player.PlayerSettings; +import com.velocitypowered.api.proxy.player.ResourcePackInfo; import com.velocitypowered.api.proxy.player.TabList; import com.velocitypowered.api.proxy.server.RegisteredServer; import com.velocitypowered.api.util.GameProfile; @@ -25,6 +26,7 @@ import java.util.UUID; import net.kyori.adventure.identity.Identified; import net.kyori.adventure.identity.Identity; import net.kyori.adventure.text.Component; +import org.checkerframework.checker.nullness.qual.Nullable; /** * Represents a player who is connected to the proxy. @@ -215,7 +217,9 @@ public interface Player extends CommandSource, Identified, InboundConnection, * sent resource pack, subscribe to {@link PlayerResourcePackStatusEvent}. * * @param url the URL for the resource pack + * @deprecated Use {@link #sendResourcePackOffer(ResourcePackInfo)} instead */ + @Deprecated void sendResourcePack(String url); /** @@ -225,10 +229,37 @@ public interface Player extends CommandSource, Identified, InboundConnection, * * @param url the URL for the resource pack * @param hash the SHA-1 hash value for the resource pack + * @deprecated Use {@link #sendResourcePackOffer(ResourcePackInfo)} instead */ - default void sendResourcePack(String url, byte[] hash) { - sendResourcePack(url, hash, false); - } + @Deprecated + void sendResourcePack(String url, byte[] hash); + + /** + * Queues and sends a new Resource-pack offer to the player. + * To monitor the status of the sent resource pack, subscribe to + * {@link PlayerResourcePackStatusEvent}. + * + * @param packInfo the resource-pack in question + */ + void sendResourcePackOffer(ResourcePackInfo packInfo); + + /** + * Gets the {@link ResourcePackInfo} of the currently applied + * resource-pack or null if none. + * + * @return the applied resource pack + */ + @Nullable + ResourcePackInfo getAppliedResourcePack(); + + /** + * Gets the {@link ResourcePackInfo} of the currently accepted + * and currently downloading resource-pack or null if none. + * + * @return the pending resource pack + */ + @Nullable + ResourcePackInfo getPendingResourcePack(); /** * Note that this method does not send a plugin message to the server the player @@ -241,21 +272,4 @@ public interface Player extends CommandSource, Identified, InboundConnection, */ @Override boolean sendPluginMessage(ChannelIdentifier identifier, byte[] data); - - /** - * Sends the specified resource pack from {@code url} to the user, using the specified 20-byte - * SHA-1 hash. To monitor the status of the sent resource pack, subscribe to - * {@link PlayerResourcePackStatusEvent}. - * In 1.17 and newer you can additionally specify - * whether the resource pack is required or not. Setting this for an older client will have - * no effect. - * - * @param url the URL for the resource pack - * @param hash the SHA-1 hash value for the resource pack - * @param isRequired Only in 1.17+ or newer: If true shows the pack as required to play, - * and removes the decline option. Declining it anyway will disconnect the user. - */ - void sendResourcePack(String url, byte[] hash, boolean isRequired); - } - diff --git a/api/src/main/java/com/velocitypowered/api/proxy/ProxyServer.java b/api/src/main/java/com/velocitypowered/api/proxy/ProxyServer.java index 073cd3bb7..bd3430a13 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/ProxyServer.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/ProxyServer.java @@ -13,6 +13,7 @@ import com.velocitypowered.api.event.EventManager; import com.velocitypowered.api.plugin.PluginManager; import com.velocitypowered.api.proxy.config.ProxyConfig; import com.velocitypowered.api.proxy.messages.ChannelRegistrar; +import com.velocitypowered.api.proxy.player.ResourcePackInfo; import com.velocitypowered.api.proxy.server.RegisteredServer; import com.velocitypowered.api.proxy.server.ServerInfo; import com.velocitypowered.api.scheduler.Scheduler; @@ -217,4 +218,24 @@ public interface ProxyServer extends Audience { @NonNull BossBar createBossBar(net.kyori.text.Component title, @NonNull BossBarColor color, @NonNull BossBarOverlay overlay, float progress); + + /** + * Creates a builder to build a {@link ResourcePackInfo} instance for use with + * {@link com.velocitypowered.api.proxy.Player#sendResourcePackOffer(ResourcePackInfo)}. + * + *

Note: The resource-pack location should always: + * - Use HTTPS with a valid certificate. + * - Be in a crawler-accessible location. Having it behind Cloudflare or Cloudfront + * may cause issues in downloading. + * - Be in location with appropriate bandwidth so the download does not time out or fail.

+ * + *

Do also make sure that the resource pack is in the correct format for the version + * of the client. It is also highly recommended to always provide the resource-pack SHA-1 hash + * of the resource pack with {@link ResourcePackInfo.Builder#setHash(byte[])} + * whenever possible to save bandwidth.

+ * + * @param url The url where the resource pack can be found + * @return a ResourcePackInfo builder + */ + ResourcePackInfo.Builder createResourcePackBuilder(String url); } diff --git a/api/src/main/java/com/velocitypowered/api/proxy/player/ResourcePackInfo.java b/api/src/main/java/com/velocitypowered/api/proxy/player/ResourcePackInfo.java new file mode 100644 index 000000000..067dd26ba --- /dev/null +++ b/api/src/main/java/com/velocitypowered/api/proxy/player/ResourcePackInfo.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2018 Velocity Contributors + * + * The Velocity API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the api top-level directory. + */ + +package com.velocitypowered.api.proxy.player; + +import net.kyori.adventure.text.Component; +import org.checkerframework.checker.nullness.qual.Nullable; + +public interface ResourcePackInfo { + + /** + * Gets the link the resource-pack can be found at. + * + * @return the location of the resource-pack + */ + String getUrl(); + + /** + * Gets the {@link Component} that is displayed on the resource-pack prompt. + * This is only displayed if the client version is 1.17 or newer. + * + * @return the prompt if present or null otherwise + */ + @Nullable + Component getPrompt(); + + /** + * Gets whether or not the acceptance of the resource-pack is enforced. + * See {@link Builder#setShouldForce(boolean)} for more information. + * + * @return whether or not to force usage of this resource-pack + */ + boolean getShouldForce(); + + /** + * Gets the SHA-1 hash of the resource-pack + * See {@link Builder#setHash(byte[])} for more information. + * + * @return the hash if present or null otherwise + */ + @Nullable + byte[] getHash(); + + /** + * Gets the {@link Origin} of the resource-pack. + * + * @return the origin of the resource pack + */ + Origin getOrigin(); + + interface Builder { + + /** + * Sets the resource-pack as required to play on the network. + * This feature was introduced in 1.17. + * Setting this to true has one of two effects: + * If the client is on 1.17 or newer: + * - The resource-pack prompt will display without a decline button + * - Accept or disconnect are the only available options but players may still press escape. + * - Forces the resource-pack offer prompt to display even if the player has + * previously declined or disabled resource packs + * - The player will be disconnected from the network if they close/skip the prompt. + * If the client is on a version older than 1.17: + * - If the player accepts the resource pack or has previously accepted a resource-pack + * then nothing else will happen. + * - If the player declines the resource pack or has previously declined a resource-pack + * the player will be disconnected from the network + * + * @param shouldForce whether or not to force the client to accept the resource pack + */ + Builder setShouldForce(boolean shouldForce); + + /** + * Sets the SHA-1 hash of the provided resource pack. + * Note: It is recommended to always set this hash. + * If this hash is not set/ not present then the client will always download + * the resource pack even if it may still be cached. By having this hash present, + * the client will check first whether or not a resource pack by this hash is cached + * before downloading. + * + * @param hash the SHA-1 hash of the resource-pack + */ + Builder setHash(@Nullable byte[] hash); + + /** + * Sets a {@link Component} to display on the download prompt. + * This will only display if the client version is 1.17 or newer. + * + * @param prompt the component to display + */ + Builder setPrompt(@Nullable Component prompt); + + /** + * Builds the {@link ResourcePackInfo} from the provided info for use with + * {@link com.velocitypowered.api.proxy.Player#sendResourcePackOffer(ResourcePackInfo)}. + * Note: Some features may be version-dependent. Check before use. + * + * @return a ResourcePackInfo instance from the provided information + */ + ResourcePackInfo build(); + } + + /** + * Represents the origin of the resource-pack. + */ + enum Origin { + /** + * Resource-pack originated from the downstream server. + */ + DOWNSTREAM_SERVER, + /** + * The player declined to download the resource pack. + */ + PLUGIN_ON_PROXY + } +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java b/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java index 63b3b7550..725e8403b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java @@ -30,6 +30,7 @@ import com.velocitypowered.api.plugin.PluginContainer; import com.velocitypowered.api.plugin.PluginManager; import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.ProxyServer; +import com.velocitypowered.api.proxy.player.ResourcePackInfo; import com.velocitypowered.api.proxy.server.RegisteredServer; import com.velocitypowered.api.proxy.server.ServerInfo; import com.velocitypowered.api.util.Favicon; @@ -45,6 +46,7 @@ import com.velocitypowered.proxy.command.builtin.ShutdownCommand; import com.velocitypowered.proxy.command.builtin.VelocityCommand; import com.velocitypowered.proxy.config.VelocityConfiguration; import com.velocitypowered.proxy.connection.client.ConnectedPlayer; +import com.velocitypowered.proxy.connection.player.VelocityResourcePackInfo; import com.velocitypowered.proxy.console.VelocityConsole; import com.velocitypowered.proxy.network.ConnectionManager; import com.velocitypowered.proxy.plugin.VelocityEventManager; @@ -682,4 +684,9 @@ public class VelocityServer implements ProxyServer, ForwardingAudience { return version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0 ? POST_1_16_PING_SERIALIZER : PRE_1_16_PING_SERIALIZER; } + + @Override + public ResourcePackInfo.Builder createResourcePackBuilder(String url) { + return new VelocityResourcePackInfo.BuilderImpl(url); + } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java index b3c7133cf..f42a6c085 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java @@ -19,6 +19,7 @@ package com.velocitypowered.proxy.connection.backend; import static com.velocitypowered.proxy.connection.backend.BungeeCordMessageResponder.getBungeeCordChannel; +import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.tree.CommandNode; @@ -28,10 +29,12 @@ import com.velocitypowered.api.event.command.PlayerAvailableCommandsEvent; import com.velocitypowered.api.event.connection.PluginMessageEvent; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.proxy.messages.ChannelIdentifier; +import com.velocitypowered.api.proxy.player.ResourcePackInfo; import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.MinecraftSessionHandler; import com.velocitypowered.proxy.connection.client.ClientPlaySessionHandler; +import com.velocitypowered.proxy.connection.player.VelocityResourcePackInfo; import com.velocitypowered.proxy.connection.util.ConnectionMessages; import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.packet.AvailableCommands; @@ -40,6 +43,7 @@ import com.velocitypowered.proxy.protocol.packet.Disconnect; import com.velocitypowered.proxy.protocol.packet.KeepAlive; import com.velocitypowered.proxy.protocol.packet.PlayerListItem; import com.velocitypowered.proxy.protocol.packet.PluginMessage; +import com.velocitypowered.proxy.protocol.packet.ResourcePackRequest; import com.velocitypowered.proxy.protocol.packet.TabCompleteResponse; import com.velocitypowered.proxy.protocol.util.PluginMessageUtil; import io.netty.buffer.ByteBuf; @@ -128,6 +132,21 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler { return false; // forward } + @Override + public boolean handle(ResourcePackRequest packet) { + ResourcePackInfo.Builder builder = new VelocityResourcePackInfo.BuilderImpl( + Preconditions.checkNotNull(packet.getUrl())) + .setPrompt(packet.getPrompt()) + .setShouldForce(packet.isRequired()); + // Why SpotBugs decides that this is unsafe I have no idea; + if (packet.getHash() != null && !Preconditions.checkNotNull(packet.getHash()).isEmpty()) { + builder.setHash(ByteBufUtil.decodeHexDump(packet.getHash())); + } + + serverConn.getPlayer().queueResourcePack(builder.build()); + return true; + } + @Override public boolean handle(PluginMessage packet) { if (bungeecordMessageResponder.process(packet)) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java index 0c2b402eb..7c8729610 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java @@ -33,6 +33,7 @@ import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.proxy.messages.ChannelIdentifier; import com.velocitypowered.api.proxy.messages.LegacyChannelIdentifier; import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier; +import com.velocitypowered.api.proxy.player.ResourcePackInfo; import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.connection.ConnectionTypes; import com.velocitypowered.proxy.connection.MinecraftConnection; @@ -72,6 +73,7 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.Nullable; /** @@ -283,9 +285,8 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { @Override public boolean handle(ResourcePackResponse packet) { - server.getEventManager().fireAndForget(new PlayerResourcePackStatusEvent(player, - packet.getStatus())); - return false; + return player.onResourcePackResponse(packet.getStatus(), + ByteBufUtil.decodeHexDump(packet.getHash())); } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java index 1a1a0d444..459a7ea26 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java @@ -31,6 +31,7 @@ import com.velocitypowered.api.event.player.KickedFromServerEvent.Notify; import com.velocitypowered.api.event.player.KickedFromServerEvent.RedirectPlayer; import com.velocitypowered.api.event.player.KickedFromServerEvent.ServerKickResult; import com.velocitypowered.api.event.player.PlayerModInfoEvent; +import com.velocitypowered.api.event.player.PlayerResourcePackStatusEvent; import com.velocitypowered.api.event.player.PlayerSettingsChangedEvent; import com.velocitypowered.api.event.player.ServerPreConnectEvent; import com.velocitypowered.api.network.ProtocolVersion; @@ -42,6 +43,7 @@ import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.ServerConnection; import com.velocitypowered.api.proxy.messages.ChannelIdentifier; import com.velocitypowered.api.proxy.player.PlayerSettings; +import com.velocitypowered.api.proxy.player.ResourcePackInfo; import com.velocitypowered.api.proxy.server.RegisteredServer; import com.velocitypowered.api.util.GameProfile; import com.velocitypowered.api.util.MessagePosition; @@ -55,6 +57,7 @@ import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.MinecraftConnectionAssociation; import com.velocitypowered.proxy.connection.backend.VelocityServerConnection; import com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeConstants; +import com.velocitypowered.proxy.connection.player.VelocityResourcePackInfo; import com.velocitypowered.proxy.connection.util.ConnectionMessages; import com.velocitypowered.proxy.connection.util.ConnectionRequestResults.Impl; import com.velocitypowered.proxy.protocol.ProtocolUtils; @@ -76,12 +79,14 @@ import com.velocitypowered.proxy.util.collect.CappedSet; import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; import java.net.InetSocketAddress; +import java.util.ArrayDeque; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.Optional; +import java.util.Queue; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; @@ -133,6 +138,10 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { private final Collection knownChannels; private final CompletableFuture teardownFuture = new CompletableFuture<>(); private @MonotonicNonNull List serversToTry = null; + private @MonotonicNonNull Boolean previousResourceResponse; + private final Queue outstandingResourcePacks = new ArrayDeque<>(); + private @Nullable ResourcePackInfo pendingResourcePack; + private @Nullable ResourcePackInfo appliedResourcePack; ConnectedPlayer(VelocityServer server, GameProfile profile, MinecraftConnection connection, @Nullable InetSocketAddress virtualHost, boolean onlineMode) { @@ -871,31 +880,133 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { } @Override + @Deprecated public void sendResourcePack(String url) { - Preconditions.checkNotNull(url, "url"); + sendResourcePackOffer(new VelocityResourcePackInfo.BuilderImpl(url).build()); + } + @Override + @Deprecated + public void sendResourcePack(String url, byte[] hash) { + sendResourcePackOffer(new VelocityResourcePackInfo.BuilderImpl(url).setHash(hash).build()); + } + + @Override + public void sendResourcePackOffer(ResourcePackInfo packInfo) { if (this.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { + Preconditions.checkNotNull(packInfo, "packInfo"); + queueResourcePack(packInfo); + } + } + + /** + * Queues a resource-pack for sending to the player and sends it + * immediately if the queue is empty. + */ + public void queueResourcePack(ResourcePackInfo info) { + outstandingResourcePacks.add(info); + if (outstandingResourcePacks.size() == 1) { + tickResourcePackQueue(); + } + } + + private void tickResourcePackQueue() { + ResourcePackInfo queued = outstandingResourcePacks.peek(); + + if (queued != null) { + // Check if the player declined a resource pack once already + if (previousResourceResponse != null && !previousResourceResponse) { + // If that happened we can flush the queue right away. + // Unless its 1.17+ and forced it will come back denied anyway + while (!outstandingResourcePacks.isEmpty()) { + queued = outstandingResourcePacks.peek(); + if (queued.getShouldForce() && getProtocolVersion() + .compareTo(ProtocolVersion.MINECRAFT_1_17) >= 0) { + break; + } + onResourcePackResponse(PlayerResourcePackStatusEvent.Status.DECLINED, new byte[0]); + queued = null; + } + if (queued == null) { + // Exit as the queue was cleared + return; + } + } + ResourcePackRequest request = new ResourcePackRequest(); - request.setUrl(url); - request.setHash(""); - request.setRequired(false); + request.setUrl(queued.getUrl()); + if (queued.getHash() != null) { + request.setHash(ByteBufUtil.hexDump(queued.getHash())); + } else { + request.setHash(""); + } + request.setRequired(queued.getShouldForce()); + request.setPrompt(queued.getPrompt()); + connection.write(request); } } @Override - public void sendResourcePack(String url, byte[] hash, boolean isRequired) { - Preconditions.checkNotNull(url, "url"); - Preconditions.checkNotNull(hash, "hash"); - Preconditions.checkArgument(hash.length == 20, "Hash length is not 20"); + public @Nullable ResourcePackInfo getAppliedResourcePack() { + return appliedResourcePack; + } - if (this.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { - ResourcePackRequest request = new ResourcePackRequest(); - request.setUrl(url); - request.setHash(ByteBufUtil.hexDump(hash)); - request.setRequired(isRequired); - connection.write(request); + @Override + public @Nullable ResourcePackInfo getPendingResourcePack() { + return pendingResourcePack; + } + + /** + * Processes a client response to a sent resource-pack. + */ + public boolean onResourcePackResponse(PlayerResourcePackStatusEvent.Status status, + @Nullable byte[] hash) { + + final boolean peek = status == PlayerResourcePackStatusEvent.Status.ACCEPTED; + final ResourcePackInfo queued = peek + ? outstandingResourcePacks.peek() : outstandingResourcePacks.poll(); + + server.getEventManager().fire(new PlayerResourcePackStatusEvent(this, status, queued)) + .thenAcceptAsync(event -> { + if (event.getStatus() == PlayerResourcePackStatusEvent.Status.DECLINED + && event.getPackInfo() != null && event.getPackInfo().getShouldForce() + && (!event.isOverwriteKick() || event.getPlayer() + .getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_17) >= 0) + ) { + event.getPlayer().disconnect(Component + .translatable("multiplayer.requiredTexturePrompt.disconnect")); + } + }); + + + switch (status) { + case ACCEPTED: + previousResourceResponse = true; + pendingResourcePack = queued; + break; + case DECLINED: + previousResourceResponse = false; + break; + case SUCCESSFUL: + appliedResourcePack = queued; + pendingResourcePack = null; + break; + case FAILED_DOWNLOAD: + pendingResourcePack = null; + break; + default: + break; } + + if (!peek) { + CompletableFuture.supplyAsync(() -> { + tickResourcePackQueue(); + return true; + }); + } + + return queued != null && queued.getOrigin() == ResourcePackInfo.Origin.DOWNSTREAM_SERVER; } /** diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/player/VelocityResourcePackInfo.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/player/VelocityResourcePackInfo.java new file mode 100644 index 000000000..250e9b3aa --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/player/VelocityResourcePackInfo.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2018 Velocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.velocitypowered.proxy.connection.player; + +import com.google.common.base.Preconditions; +import com.velocitypowered.api.proxy.player.ResourcePackInfo; +import net.kyori.adventure.text.Component; +import org.checkerframework.checker.nullness.qual.Nullable; + +public final class VelocityResourcePackInfo implements ResourcePackInfo { + private final String url; + private final @Nullable byte[] hash; + private final boolean shouldForce; + private final @Nullable Component prompt; // 1.17+ only + private final Origin origin; + + private VelocityResourcePackInfo(String url, @Nullable byte[] hash, boolean shouldForce, + @Nullable Component prompt, Origin origin) { + this.url = url; + this.hash = hash; + this.shouldForce = shouldForce; + this.prompt = prompt; + this.origin = origin; + } + + @Override + public String getUrl() { + return url; + } + + @Override + public @Nullable Component getPrompt() { + return prompt; + } + + @Override + public boolean getShouldForce() { + return shouldForce; + } + + @Override + public @Nullable byte[] getHash() { + return hash == null ? null : hash.clone(); // Thanks spotbugs, very helpful. + } + + @Override + public Origin getOrigin() { + return origin; + } + + public static final class BuilderImpl implements ResourcePackInfo.Builder { + private final String url; + private boolean shouldForce; + private @Nullable byte[] hash; + private @Nullable Component prompt; + private Origin origin = Origin.PLUGIN_ON_PROXY; + + public BuilderImpl(String url) { + this.url = Preconditions.checkNotNull(url, "url"); + } + + @Override + public BuilderImpl setShouldForce(boolean shouldForce) { + this.shouldForce = shouldForce; + return this; + } + + @Override + public BuilderImpl setHash(@Nullable byte[] hash) { + if (hash != null) { + Preconditions.checkArgument(hash.length == 20, "Hash length is not 20"); + this.hash = hash.clone(); // Thanks spotbugs, very helpful. + } else { + this.hash = null; + } + return this; + } + + @Override + public BuilderImpl setPrompt(@Nullable Component prompt) { + this.prompt = prompt; + return this; + } + + @Override + public ResourcePackInfo build() { + return new VelocityResourcePackInfo(url, hash, shouldForce, prompt, origin); + } + + public void setOrigin(Origin origin) { + this.origin = origin; + } + } + +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java index 213e15222..b56cb8f02 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java @@ -226,16 +226,16 @@ public enum StateRegistry { map(0x39, MINECRAFT_1_16_2, true), map(0x3C, MINECRAFT_1_17, true)); clientbound.register(ResourcePackRequest.class, ResourcePackRequest::new, - map(0x48, MINECRAFT_1_8, true), - map(0x32, MINECRAFT_1_9, true), - map(0x33, MINECRAFT_1_12, true), - map(0x34, MINECRAFT_1_12_1, true), - map(0x37, MINECRAFT_1_13, true), - map(0x39, MINECRAFT_1_14, true), - map(0x3A, MINECRAFT_1_15, true), - map(0x39, MINECRAFT_1_16, true), - map(0x38, MINECRAFT_1_16_2, true), - map(0x3B, MINECRAFT_1_17, true)); + map(0x48, MINECRAFT_1_8, false), + map(0x32, MINECRAFT_1_9, false), + map(0x33, MINECRAFT_1_12, false), + map(0x34, MINECRAFT_1_12_1, false), + map(0x37, MINECRAFT_1_13, false), + map(0x39, MINECRAFT_1_14, false), + map(0x3A, MINECRAFT_1_15, false), + map(0x39, MINECRAFT_1_16, false), + map(0x38, MINECRAFT_1_16_2, false), + map(0x3B, MINECRAFT_1_17, false)); clientbound.register(HeaderAndFooter.class, HeaderAndFooter::new, map(0x47, MINECRAFT_1_8, true), map(0x48, MINECRAFT_1_9, true), diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackRequest.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackRequest.java index c2115970d..d17505560 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackRequest.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackRequest.java @@ -23,6 +23,8 @@ import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction; import io.netty.buffer.ByteBuf; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -31,6 +33,7 @@ public class ResourcePackRequest implements MinecraftPacket { private @MonotonicNonNull String url; private @MonotonicNonNull String hash; private boolean isRequired; // 1.17+ + private @Nullable Component prompt; // 1.17+ public @Nullable String getUrl() { return url; @@ -56,12 +59,25 @@ public class ResourcePackRequest implements MinecraftPacket { isRequired = required; } + public @Nullable Component getPrompt() { + return prompt; + } + + public void setPrompt(Component prompt) { + this.prompt = prompt; + } + @Override public void decode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) { this.url = ProtocolUtils.readString(buf); this.hash = ProtocolUtils.readString(buf); if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_17) >= 0) { this.isRequired = buf.readBoolean(); + if (buf.readBoolean()) { + this.prompt = GsonComponentSerializer.gson().deserialize(ProtocolUtils.readString(buf)); + } else { + this.prompt = null; + } } } @@ -74,6 +90,12 @@ public class ResourcePackRequest implements MinecraftPacket { ProtocolUtils.writeString(buf, hash); if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_17) >= 0) { buf.writeBoolean(isRequired); + if (prompt != null) { + buf.writeBoolean(true); + ProtocolUtils.writeString(buf, GsonComponentSerializer.gson().serialize(prompt)); + } else { + buf.writeBoolean(false); + } } } @@ -87,6 +109,8 @@ public class ResourcePackRequest implements MinecraftPacket { return "ResourcePackRequest{" + "url='" + url + '\'' + ", hash='" + hash + '\'' + + ", isRequired=" + isRequired + + ", prompt='" + prompt + '\'' + '}'; } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackResponse.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackResponse.java index 245e2f501..3269ff0d5 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackResponse.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackResponse.java @@ -38,6 +38,10 @@ public class ResourcePackResponse implements MinecraftPacket { return status; } + public String getHash() { + return hash; + } + @Override public void decode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) { if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_9_4) <= 0) { From be1848f8e72962b53af6b1cfc83c1b0ccf795f6c Mon Sep 17 00:00:00 2001 From: FivePB Date: Thu, 13 May 2021 17:09:50 +0200 Subject: [PATCH 19/30] Snapshot 21w16a --- .../java/com/velocitypowered/api/network/ProtocolVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index 10b3595f6..b93fdbf39 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 22, "1.17"); // Snapshot: 21w15a, future protocol: 755 + MINECRAFT_1_17(-1, 23, "1.17"); // Snapshot: 21w16a, future protocol: 755 private static final int SNAPSHOT_BIT = 30; From 00f81a3fd70842b2285327abbf640e7e17c7b083 Mon Sep 17 00:00:00 2001 From: FivePB Date: Thu, 13 May 2021 17:12:37 +0200 Subject: [PATCH 20/30] Snapshot 21w17a --- .../java/com/velocitypowered/api/network/ProtocolVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index b93fdbf39..120f55334 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 23, "1.17"); // Snapshot: 21w16a, future protocol: 755 + MINECRAFT_1_17(-1, 25, "1.17"); // Snapshot: 21w17a, future protocol: 755 private static final int SNAPSHOT_BIT = 30; From 6eb2432e8865618642f980109621d2ee6507f3cf Mon Sep 17 00:00:00 2001 From: FivePB Date: Thu, 13 May 2021 17:13:08 +0200 Subject: [PATCH 21/30] Snapshot 21w18a --- .../java/com/velocitypowered/api/network/ProtocolVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index 120f55334..80316d298 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 25, "1.17"); // Snapshot: 21w17a, future protocol: 755 + MINECRAFT_1_17(-1, 26, "1.17"); // Snapshot: 21w18a, future protocol: 755 private static final int SNAPSHOT_BIT = 30; From 18466bb59586bc37598a60f9a10b8e659010777f Mon Sep 17 00:00:00 2001 From: FivePB Date: Thu, 13 May 2021 17:24:51 +0200 Subject: [PATCH 22/30] Snapshot 21w19a --- .../api/network/ProtocolVersion.java | 2 +- .../proxy/protocol/StateRegistry.java | 21 +++++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index 80316d298..dc17efb23 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 26, "1.17"); // Snapshot: 21w18a, future protocol: 755 + MINECRAFT_1_17(-1, 27, "1.17"); // Snapshot: 21w19a, future protocol: 755 private static final int SNAPSHOT_BIT = 30; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java index b56cb8f02..8e787539f 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java @@ -149,8 +149,7 @@ public enum StateRegistry { map(0x1D, MINECRAFT_1_13, false), map(0x1F, MINECRAFT_1_14, false), map(0x20, MINECRAFT_1_16, false), - map(0x21, MINECRAFT_1_16_2, false), - map(0x20, MINECRAFT_1_17, false)); + map(0x21, MINECRAFT_1_16_2, false)); clientbound.register(BossBar.class, BossBar::new, map(0x0C, MINECRAFT_1_9, false), @@ -224,7 +223,7 @@ public enum StateRegistry { map(0x3B, MINECRAFT_1_15, true), map(0x3A, MINECRAFT_1_16, true), map(0x39, MINECRAFT_1_16_2, true), - map(0x3C, MINECRAFT_1_17, true)); + map(0x3D, MINECRAFT_1_17, true)); clientbound.register(ResourcePackRequest.class, ResourcePackRequest::new, map(0x48, MINECRAFT_1_8, false), map(0x32, MINECRAFT_1_9, false), @@ -235,7 +234,7 @@ public enum StateRegistry { map(0x3A, MINECRAFT_1_15, false), map(0x39, MINECRAFT_1_16, false), map(0x38, MINECRAFT_1_16_2, false), - map(0x3B, MINECRAFT_1_17, false)); + map(0x3C, MINECRAFT_1_17, false)); clientbound.register(HeaderAndFooter.class, HeaderAndFooter::new, map(0x47, MINECRAFT_1_8, true), map(0x48, MINECRAFT_1_9, true), @@ -246,7 +245,7 @@ public enum StateRegistry { map(0x53, MINECRAFT_1_14, true), map(0x54, MINECRAFT_1_15, true), map(0x53, MINECRAFT_1_16, true), - map(0x5D, MINECRAFT_1_17, true)); + map(0x5E, MINECRAFT_1_17, true)); clientbound.register(LegacyTitlePacket.class, LegacyTitlePacket::new, map(0x45, MINECRAFT_1_8, true), map(0x45, MINECRAFT_1_9, true), @@ -257,13 +256,13 @@ public enum StateRegistry { map(0x50, MINECRAFT_1_15, true), map(0x4F, MINECRAFT_1_16, MINECRAFT_1_16_4, true)); clientbound.register(TitleSubtitlePacket.class, TitleSubtitlePacket::new, - map(0x56, MINECRAFT_1_17, true)); + map(0x57, MINECRAFT_1_17, true)); clientbound.register(TitleTextPacket.class, TitleTextPacket::new, - map(0x58, MINECRAFT_1_17, true)); - clientbound.register(TitleActionbarPacket.class, TitleActionbarPacket::new, - map(0x40, MINECRAFT_1_17, true)); - clientbound.register(TitleTimesPacket.class, TitleTimesPacket::new, map(0x59, MINECRAFT_1_17, true)); + clientbound.register(TitleActionbarPacket.class, TitleActionbarPacket::new, + map(0x41, MINECRAFT_1_17, true)); + clientbound.register(TitleTimesPacket.class, TitleTimesPacket::new, + map(0x5A, MINECRAFT_1_17, true)); clientbound.register(TitleClearPacket.class, TitleClearPacket::new, map(0x10, MINECRAFT_1_17, true)); clientbound.register(PlayerListItem.class, PlayerListItem::new, @@ -275,7 +274,7 @@ public enum StateRegistry { map(0x34, MINECRAFT_1_15, false), map(0x33, MINECRAFT_1_16, false), map(0x32, MINECRAFT_1_16_2, false), - map(0x35, MINECRAFT_1_17, false)); + map(0x36, MINECRAFT_1_17, false)); } }, LOGIN { From 10bfd8685e2d242006f45558139ddeb0b353d259 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Thu, 27 May 2021 11:02:07 -0400 Subject: [PATCH 23/30] Minecraft 1.17-pre1 --- .../java/com/velocitypowered/api/network/ProtocolVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index dc17efb23..f67431c33 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 27, "1.17"); // Snapshot: 21w19a, future protocol: 755 + MINECRAFT_1_17(-1, 29, "1.17"); // Snapshot: 1.17-pre1, future protocol: 755 private static final int SNAPSHOT_BIT = 30; From c161a3859c52f65f21852f029ef940c6aaccc34c Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Mon, 31 May 2021 12:47:13 -0400 Subject: [PATCH 24/30] 1.17-pre2 --- .../java/com/velocitypowered/api/network/ProtocolVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index f67431c33..d01e82938 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 29, "1.17"); // Snapshot: 1.17-pre1, future protocol: 755 + MINECRAFT_1_17(-1, 30, "1.17"); // Snapshot: 1.17-pre2, future protocol: 755 private static final int SNAPSHOT_BIT = 30; From f67dc3ffc8c4fe0f59d1e46b8842982af833000c Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Tue, 1 Jun 2021 13:36:28 -0400 Subject: [PATCH 25/30] Minecraft 1.17-pre3 --- .../java/com/velocitypowered/api/network/ProtocolVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index d01e82938..09a3dc4c4 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 30, "1.17"); // Snapshot: 1.17-pre2, future protocol: 755 + MINECRAFT_1_17(-1, 31, "1.17"); // Snapshot: 1.17-pre3, future protocol: 755 private static final int SNAPSHOT_BIT = 30; From 3eb64855d3164c313c19e3b91ddb221d19882a23 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Thu, 3 Jun 2021 02:50:16 -0400 Subject: [PATCH 26/30] Minecraft 1.17-pre4 --- .../java/com/velocitypowered/api/network/ProtocolVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index 09a3dc4c4..f57938558 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 31, "1.17"); // Snapshot: 1.17-pre3, future protocol: 755 + MINECRAFT_1_17(-1, 32, "1.17"); // Snapshot: 1.17-pre4, future protocol: 755 private static final int SNAPSHOT_BIT = 30; From 100eedf1023f742b9d73c5c00cb1489e7401713f Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Thu, 3 Jun 2021 14:40:06 -0400 Subject: [PATCH 27/30] Minecraft 1.17-pre5 --- .../java/com/velocitypowered/api/network/ProtocolVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index f57938558..68f62749f 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 32, "1.17"); // Snapshot: 1.17-pre4, future protocol: 755 + MINECRAFT_1_17(-1, 33, "1.17"); // Snapshot: 1.17-pre5, future protocol: 755 private static final int SNAPSHOT_BIT = 30; From df21105701c4fb7f8f55ab8a50aad08c1f321d41 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Fri, 4 Jun 2021 17:48:45 -0400 Subject: [PATCH 28/30] Minecraft 1.17-rc1 --- .../java/com/velocitypowered/api/network/ProtocolVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index 68f62749f..20662ab66 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -54,7 +54,7 @@ public enum ProtocolVersion { MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), - MINECRAFT_1_17(-1, 33, "1.17"); // Snapshot: 1.17-pre5, future protocol: 755 + MINECRAFT_1_17(-1, 34, "1.17"); // Snapshot: 1.17-rc1, future protocol: 755 private static final int SNAPSHOT_BIT = 30; From 59b29a075e0abe4e9aeca393975a1cfbead35ee9 Mon Sep 17 00:00:00 2001 From: FivePB Date: Sat, 5 Jun 2021 16:07:24 +0200 Subject: [PATCH 29/30] Improve new Resource-pack API --- .../java/com/velocitypowered/api/proxy/Player.java | 11 +++++++---- .../com/velocitypowered/api/proxy/ProxyServer.java | 10 ++++++---- .../api/proxy/player/ResourcePackInfo.java | 2 +- .../proxy/connection/client/ConnectedPlayer.java | 3 +-- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/api/src/main/java/com/velocitypowered/api/proxy/Player.java b/api/src/main/java/com/velocitypowered/api/proxy/Player.java index d22f0caf2..51d966044 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/Player.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/Player.java @@ -238,6 +238,8 @@ public interface Player extends CommandSource, Identified, InboundConnection, * Queues and sends a new Resource-pack offer to the player. * To monitor the status of the sent resource pack, subscribe to * {@link PlayerResourcePackStatusEvent}. + * To create a {@link ResourcePackInfo} use the + * {@link ProxyServer#createResourcePackBuilder(String)} builder. * * @param packInfo the resource-pack in question */ @@ -247,16 +249,17 @@ public interface Player extends CommandSource, Identified, InboundConnection, * Gets the {@link ResourcePackInfo} of the currently applied * resource-pack or null if none. * - * @return the applied resource pack + * @return the applied resource pack or null if none. */ @Nullable ResourcePackInfo getAppliedResourcePack(); /** - * Gets the {@link ResourcePackInfo} of the currently accepted - * and currently downloading resource-pack or null if none. + * Gets the {@link ResourcePackInfo} of the resource pack + * the user is currently downloading or is currently + * prompted to install or null if none. * - * @return the pending resource pack + * @return the pending resource pack or null if none */ @Nullable ResourcePackInfo getPendingResourcePack(); diff --git a/api/src/main/java/com/velocitypowered/api/proxy/ProxyServer.java b/api/src/main/java/com/velocitypowered/api/proxy/ProxyServer.java index bd3430a13..6f2e518f6 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/ProxyServer.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/ProxyServer.java @@ -225,14 +225,16 @@ public interface ProxyServer extends Audience { * *

Note: The resource-pack location should always: * - Use HTTPS with a valid certificate. - * - Be in a crawler-accessible location. Having it behind Cloudflare or Cloudfront - * may cause issues in downloading. - * - Be in location with appropriate bandwidth so the download does not time out or fail.

+ * - Be in a crawler-accessible location. Having it behind Cloudflare or other DoS/Bot/crawler + * protection may cause issues in downloading. + * - Be on a web-server with enough bandwidth and reliable connection + * so the download does not time out or fail.

* *

Do also make sure that the resource pack is in the correct format for the version * of the client. It is also highly recommended to always provide the resource-pack SHA-1 hash * of the resource pack with {@link ResourcePackInfo.Builder#setHash(byte[])} - * whenever possible to save bandwidth.

+ * whenever possible to save bandwidth. If a hash is present the client will first check + * if it already has a resource pack by that hash cached.

* * @param url The url where the resource pack can be found * @return a ResourcePackInfo builder diff --git a/api/src/main/java/com/velocitypowered/api/proxy/player/ResourcePackInfo.java b/api/src/main/java/com/velocitypowered/api/proxy/player/ResourcePackInfo.java index 067dd26ba..4643dd422 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/player/ResourcePackInfo.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/player/ResourcePackInfo.java @@ -113,7 +113,7 @@ public interface ResourcePackInfo { */ DOWNSTREAM_SERVER, /** - * The player declined to download the resource pack. + * The resource-pack originated from a plugin on this proxy. */ PLUGIN_ON_PROXY } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java index 459a7ea26..26ba80c24 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java @@ -1000,9 +1000,8 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { } if (!peek) { - CompletableFuture.supplyAsync(() -> { + connection.eventLoop().execute(() -> { tickResourcePackQueue(); - return true; }); } From 43b72ff8260b23b3e3f6c01036ab11c717da14ab Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Sun, 6 Jun 2021 00:20:47 +0000 Subject: [PATCH 30/30] Apply some spelling fixes from code review Co-authored-by: Hugo Manrique --- .../api/event/player/PlayerResourcePackStatusEvent.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/src/main/java/com/velocitypowered/api/event/player/PlayerResourcePackStatusEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/PlayerResourcePackStatusEvent.java index a490b6791..bfd7a5ea5 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/PlayerResourcePackStatusEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/PlayerResourcePackStatusEvent.java @@ -27,7 +27,7 @@ public class PlayerResourcePackStatusEvent { /** - * Instates this event. + * Instantiates this event. * @deprecated Use {@link PlayerResourcePackStatusEvent#PlayerResourcePackStatusEvent * (Player, Status, ResourcePackInfo)} instead. */ @@ -39,7 +39,7 @@ public class PlayerResourcePackStatusEvent { } /** - * Instates this event. + * Instantiates this event. */ public PlayerResourcePackStatusEvent(Player player, Status status, ResourcePackInfo packInfo) { this.player = Preconditions.checkNotNull(player, "player");