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 8bb0c98b0..1c6b6d536 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -87,7 +87,8 @@ public enum ProtocolVersion implements Ordered { MINECRAFT_1_20_2(764, "1.20.2"), MINECRAFT_1_20_3(765, "1.20.3", "1.20.4"), MINECRAFT_1_20_5(766, "1.20.5", "1.20.6"), - MINECRAFT_1_21(767, "1.21", "1.21.1"); + MINECRAFT_1_21(767, "1.21", "1.21.1"), + MINECRAFT_1_21_2(768, "1.21.2"); private static final int SNAPSHOT_BIT = 30; diff --git a/api/src/main/java/com/velocitypowered/api/proxy/player/PlayerSettings.java b/api/src/main/java/com/velocitypowered/api/proxy/player/PlayerSettings.java index 320b1c203..416cbf154 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/player/PlayerSettings.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/player/PlayerSettings.java @@ -68,6 +68,20 @@ public interface PlayerSettings { */ boolean isClientListingAllowed(); + /** + * Returns if the client has text filtering enabled. + * + * @return if text filtering is enabled + */ + boolean isTextFilteringEnabled(); + + /** + * Returns the selected "Particles" option state. + * + * @return the particle option + */ + ParticleStatus getParticleStatus(); + /** * The client's current chat display mode. */ @@ -84,4 +98,13 @@ public interface PlayerSettings { LEFT, RIGHT } + + /** + * The client's current "Particles" option state. + */ + enum ParticleStatus { + ALL, + DECREASED, + MINIMAL + } } 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 5032ff1f4..f8d3107cc 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 @@ -30,7 +30,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; public class ClientSettingsWrapper implements PlayerSettings { static final PlayerSettings DEFAULT = new ClientSettingsWrapper( - new ClientSettingsPacket("en_US", (byte) 10, 0, true, (short) 127, 1, true, false)); + new ClientSettingsPacket("en_us", (byte) 2, 0, true, (short) 0, 1, false, false, 0)); private final ClientSettingsPacket settings; private final SkinParts parts; @@ -56,11 +56,11 @@ public class ClientSettingsWrapper implements PlayerSettings { @Override public ChatMode getChatMode() { - int chat = settings.getChatVisibility(); - if (chat < 0 || chat > 2) { - return ChatMode.SHOWN; - } - return ChatMode.values()[chat]; + return switch (settings.getChatVisibility()) { + case 1 -> ChatMode.COMMANDS_ONLY; + case 2 -> ChatMode.HIDDEN; + default -> ChatMode.SHOWN; + }; } @Override @@ -83,6 +83,20 @@ public class ClientSettingsWrapper implements PlayerSettings { return settings.isClientListingAllowed(); } + @Override + public boolean isTextFilteringEnabled() { + return settings.isTextFilteringEnabled(); + } + + @Override + public ParticleStatus getParticleStatus() { + return switch (settings.getParticleStatus()) { + case 1 -> ParticleStatus.DECREASED; + case 2 -> ParticleStatus.MINIMAL; + default -> ParticleStatus.ALL; + }; + } + @Override public boolean equals(@Nullable final Object o) { if (this == o) { 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 41d444a36..1bd70248a 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java @@ -37,6 +37,7 @@ import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_20_2; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_20_3; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_20_5; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_21; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_21_2; 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; @@ -252,7 +253,8 @@ public enum StateRegistry { map(0x08, MINECRAFT_1_19_3, false), map(0x09, MINECRAFT_1_19_4, false), map(0x0A, MINECRAFT_1_20_2, false), - map(0x0B, MINECRAFT_1_20_5, false)); + map(0x0B, MINECRAFT_1_20_5, false), + map(0x0D, MINECRAFT_1_21_2, false)); serverbound.register( LegacyChatPacket.class, LegacyChatPacket::new, @@ -264,7 +266,8 @@ public enum StateRegistry { serverbound.register( ChatAcknowledgementPacket.class, ChatAcknowledgementPacket::new, - map(0x03, MINECRAFT_1_19_3, false)); + map(0x03, MINECRAFT_1_19_3, false), + map(0x04, MINECRAFT_1_21_2, false)); serverbound.register(KeyedPlayerCommandPacket.class, KeyedPlayerCommandPacket::new, map(0x03, MINECRAFT_1_19, false), map(0x04, MINECRAFT_1_19_1, MINECRAFT_1_19_1, false)); @@ -273,14 +276,17 @@ public enum StateRegistry { map(0x05, MINECRAFT_1_19_1, MINECRAFT_1_19_1, false)); serverbound.register(SessionPlayerCommandPacket.class, SessionPlayerCommandPacket::new, map(0x04, MINECRAFT_1_19_3, false), - map(0x05, MINECRAFT_1_20_5, false)); + map(0x05, MINECRAFT_1_20_5, false), + map(0x06, MINECRAFT_1_21_2, false)); serverbound.register(UnsignedPlayerCommandPacket.class, UnsignedPlayerCommandPacket::new, - map(0x04, MINECRAFT_1_20_5, false)); + map(0x04, MINECRAFT_1_20_5, false), + map(0x05, MINECRAFT_1_21_2, false)); serverbound.register( SessionPlayerChatPacket.class, SessionPlayerChatPacket::new, map(0x05, MINECRAFT_1_19_3, false), - map(0x06, MINECRAFT_1_20_5, false)); + map(0x06, MINECRAFT_1_20_5, false), + map(0x07, MINECRAFT_1_21_2, false)); serverbound.register( ClientSettingsPacket.class, ClientSettingsPacket::new, @@ -294,10 +300,12 @@ public enum StateRegistry { map(0x07, MINECRAFT_1_19_3, false), map(0x08, MINECRAFT_1_19_4, false), map(0x09, MINECRAFT_1_20_2, false), - map(0x0A, MINECRAFT_1_20_5, false)); + map(0x0A, MINECRAFT_1_20_5, false), + map(0x0C, MINECRAFT_1_21_2, false)); serverbound.register( ServerboundCookieResponsePacket.class, ServerboundCookieResponsePacket::new, - map(0x11, MINECRAFT_1_20_5, false)); + map(0x11, MINECRAFT_1_20_5, false), + map(0x13, MINECRAFT_1_21_2, false)); serverbound.register( PluginMessagePacket.class, PluginMessagePacket::new, @@ -314,7 +322,8 @@ public enum StateRegistry { map(0x0D, MINECRAFT_1_19_4, false), map(0x0F, MINECRAFT_1_20_2, false), map(0x10, MINECRAFT_1_20_3, false), - map(0x12, MINECRAFT_1_20_5, false)); + map(0x12, MINECRAFT_1_20_5, false), + map(0x14, MINECRAFT_1_21_2, false)); serverbound.register( KeepAlivePacket.class, KeepAlivePacket::new, @@ -332,7 +341,8 @@ public enum StateRegistry { map(0x12, MINECRAFT_1_19_4, false), map(0x14, MINECRAFT_1_20_2, false), map(0x15, MINECRAFT_1_20_3, false), - map(0x18, MINECRAFT_1_20_5, false)); + map(0x18, MINECRAFT_1_20_5, false), + map(0x1A, MINECRAFT_1_21_2, false)); serverbound.register( ResourcePackResponsePacket.class, ResourcePackResponsePacket::new, @@ -347,11 +357,13 @@ public enum StateRegistry { map(0x24, MINECRAFT_1_19_1, false), map(0x27, MINECRAFT_1_20_2, false), map(0x28, MINECRAFT_1_20_3, false), - map(0x2B, MINECRAFT_1_20_5, false)); + map(0x2B, MINECRAFT_1_20_5, false), + map(0x2D, MINECRAFT_1_21_2, false)); serverbound.register( FinishedUpdatePacket.class, () -> FinishedUpdatePacket.INSTANCE, map(0x0B, MINECRAFT_1_20_2, false), - map(0x0C, MINECRAFT_1_20_5, false)); + map(0x0C, MINECRAFT_1_20_5, false), + map(0x0E, MINECRAFT_1_21_2, false)); clientbound.register( BossBarPacket.class, @@ -449,7 +461,8 @@ public enum StateRegistry { map(0x1F, MINECRAFT_1_19_3, false), map(0x23, MINECRAFT_1_19_4, false), map(0x24, MINECRAFT_1_20_2, false), - map(0x26, MINECRAFT_1_20_5, false)); + map(0x26, MINECRAFT_1_20_5, false), + map(0x27, MINECRAFT_1_21_2, false)); clientbound.register( JoinGamePacket.class, JoinGamePacket::new, @@ -466,7 +479,8 @@ public enum StateRegistry { map(0x24, MINECRAFT_1_19_3, false), map(0x28, MINECRAFT_1_19_4, false), map(0x29, MINECRAFT_1_20_2, false), - map(0x2B, MINECRAFT_1_20_5, false)); + map(0x2B, MINECRAFT_1_20_5, false), + map(0x2C, MINECRAFT_1_21_2, false)); clientbound.register( RespawnPacket.class, RespawnPacket::new, @@ -486,12 +500,14 @@ public enum StateRegistry { map(0x41, MINECRAFT_1_19_4, true), map(0x43, MINECRAFT_1_20_2, true), map(0x45, MINECRAFT_1_20_3, true), - map(0x47, MINECRAFT_1_20_5, true)); + map(0x47, MINECRAFT_1_20_5, true), + map(0x4C, MINECRAFT_1_21_2, true)); clientbound.register( RemoveResourcePackPacket.class, RemoveResourcePackPacket::new, map(0x43, MINECRAFT_1_20_3, false), - map(0x45, MINECRAFT_1_20_5, false)); + map(0x45, MINECRAFT_1_20_5, false), + map(0x4A, MINECRAFT_1_21_2, false)); clientbound.register( ResourcePackRequestPacket.class, ResourcePackRequestPacket::new, @@ -511,7 +527,8 @@ public enum StateRegistry { map(0x40, MINECRAFT_1_19_4, false), map(0x42, MINECRAFT_1_20_2, false), map(0x44, MINECRAFT_1_20_3, false), - map(0x46, MINECRAFT_1_20_5, false)); + map(0x46, MINECRAFT_1_20_5, false), + map(0x4B, MINECRAFT_1_21_2, false)); clientbound.register( HeaderAndFooterPacket.class, HeaderAndFooterPacket::new, @@ -532,7 +549,8 @@ public enum StateRegistry { map(0x65, MINECRAFT_1_19_4, true), map(0x68, MINECRAFT_1_20_2, true), map(0x6A, MINECRAFT_1_20_3, true), - map(0x6D, MINECRAFT_1_20_5, true)); + map(0x6D, MINECRAFT_1_20_5, true), + map(0x74, MINECRAFT_1_21_2, true)); clientbound.register( LegacyTitlePacket.class, LegacyTitlePacket::new, @@ -552,7 +570,8 @@ public enum StateRegistry { map(0x5D, MINECRAFT_1_19_4, true), map(0x5F, MINECRAFT_1_20_2, true), map(0x61, MINECRAFT_1_20_3, true), - map(0x63, MINECRAFT_1_20_5, true)); + map(0x63, MINECRAFT_1_20_5, true), + map(0x6A, MINECRAFT_1_21_2, true)); clientbound.register( TitleTextPacket.class, TitleTextPacket::new, @@ -563,7 +582,8 @@ public enum StateRegistry { map(0x5F, MINECRAFT_1_19_4, true), map(0x61, MINECRAFT_1_20_2, true), map(0x63, MINECRAFT_1_20_3, true), - map(0x65, MINECRAFT_1_20_5, true)); + map(0x65, MINECRAFT_1_20_5, true), + map(0x6C, MINECRAFT_1_21_2, true)); clientbound.register( TitleActionbarPacket.class, TitleActionbarPacket::new, @@ -574,7 +594,8 @@ public enum StateRegistry { map(0x46, MINECRAFT_1_19_4, true), map(0x48, MINECRAFT_1_20_2, true), map(0x4A, MINECRAFT_1_20_3, true), - map(0x4C, MINECRAFT_1_20_5, true)); + map(0x4C, MINECRAFT_1_20_5, true), + map(0x51, MINECRAFT_1_21_2, true)); clientbound.register( TitleTimesPacket.class, TitleTimesPacket::new, @@ -585,7 +606,8 @@ public enum StateRegistry { map(0x60, MINECRAFT_1_19_4, true), map(0x62, MINECRAFT_1_20_2, true), map(0x64, MINECRAFT_1_20_3, true), - map(0x66, MINECRAFT_1_20_5, true)); + map(0x66, MINECRAFT_1_20_5, true), + map(0x6D, MINECRAFT_1_21_2, true)); clientbound.register( TitleClearPacket.class, TitleClearPacket::new, @@ -612,17 +634,20 @@ public enum StateRegistry { map(0x35, MINECRAFT_1_19_3, false), map(0x39, MINECRAFT_1_19_4, false), map(0x3B, MINECRAFT_1_20_2, false), - map(0x3D, MINECRAFT_1_20_5, false)); + map(0x3D, MINECRAFT_1_20_5, false), + map(0x3F, MINECRAFT_1_21_2, false)); clientbound.register( UpsertPlayerInfoPacket.class, UpsertPlayerInfoPacket::new, map(0x36, MINECRAFT_1_19_3, false), map(0x3A, MINECRAFT_1_19_4, false), map(0x3C, MINECRAFT_1_20_2, false), - map(0x3E, MINECRAFT_1_20_5, false)); + map(0x3E, MINECRAFT_1_20_5, false), + map(0x40, MINECRAFT_1_21_2, false)); clientbound.register( ClientboundStoreCookiePacket.class, ClientboundStoreCookiePacket::new, - map(0x6B, MINECRAFT_1_20_5, false)); + map(0x6B, MINECRAFT_1_20_5, false), + map(0x72, MINECRAFT_1_21_2, false)); clientbound.register( SystemChatPacket.class, SystemChatPacket::new, @@ -632,7 +657,8 @@ public enum StateRegistry { map(0x64, MINECRAFT_1_19_4, true), map(0x67, MINECRAFT_1_20_2, true), map(0x69, MINECRAFT_1_20_3, true), - map(0x6C, MINECRAFT_1_20_5, true)); + map(0x6C, MINECRAFT_1_20_5, true), + map(0x73, MINECRAFT_1_21_2, true)); clientbound.register( PlayerChatCompletionPacket.class, PlayerChatCompletionPacket::new, @@ -650,13 +676,15 @@ public enum StateRegistry { map(0x45, MINECRAFT_1_19_4, false), map(0x47, MINECRAFT_1_20_2, false), map(0x49, MINECRAFT_1_20_3, false), - map(0x4B, MINECRAFT_1_20_5, false)); + map(0x4B, MINECRAFT_1_20_5, false), + map(0x50, MINECRAFT_1_21_2, false)); clientbound.register( StartUpdatePacket.class, () -> StartUpdatePacket.INSTANCE, map(0x65, MINECRAFT_1_20_2, false), map(0x67, MINECRAFT_1_20_3, false), - map(0x69, MINECRAFT_1_20_5, false)); + map(0x69, MINECRAFT_1_20_5, false), + map(0x70, MINECRAFT_1_21_2, false)); clientbound.register( BundleDelimiterPacket.class, () -> BundleDelimiterPacket.INSTANCE, @@ -664,12 +692,18 @@ public enum StateRegistry { clientbound.register( TransferPacket.class, TransferPacket::new, - map(0x73, MINECRAFT_1_20_5, false) - ); - clientbound.register(ClientboundCustomReportDetailsPacket.class, ClientboundCustomReportDetailsPacket::new, - map(0x7A, MINECRAFT_1_21, false)); - clientbound.register(ClientboundServerLinksPacket.class, ClientboundServerLinksPacket::new, - map(0x7B, MINECRAFT_1_21, false)); + map(0x73, MINECRAFT_1_20_5, false), + map(0x7A, MINECRAFT_1_21_2, false)); + clientbound.register( + ClientboundCustomReportDetailsPacket.class, + ClientboundCustomReportDetailsPacket::new, + map(0x7A, MINECRAFT_1_21, false), + map(0x81, MINECRAFT_1_21_2, false)); + clientbound.register( + ClientboundServerLinksPacket.class, + ClientboundServerLinksPacket::new, + map(0x7B, MINECRAFT_1_21, false), + map(0x82, MINECRAFT_1_21_2, false)); } }, LOGIN { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientSettingsPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientSettingsPacket.java index 0e3668030..39e6fde02 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientSettingsPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientSettingsPacket.java @@ -34,21 +34,25 @@ public class ClientSettingsPacket implements MinecraftPacket { private byte difficulty; // 1.7 Protocol private short skinParts; private int mainHand; - private boolean chatFilteringEnabled; // Added in 1.17 + private boolean textFilteringEnabled; // Added in 1.17 private boolean clientListingAllowed; // Added in 1.18, overwrites server-list "anonymous" mode + private int particleStatus; // Added in 1.21.2 public ClientSettingsPacket() { } public ClientSettingsPacket(String locale, byte viewDistance, int chatVisibility, boolean chatColors, - short skinParts, int mainHand, boolean chatFilteringEnabled, boolean clientListingAllowed) { + short skinParts, int mainHand, boolean textFilteringEnabled, boolean clientListingAllowed, + int particleStatus) { this.locale = locale; this.viewDistance = viewDistance; this.chatVisibility = chatVisibility; this.chatColors = chatColors; this.skinParts = skinParts; this.mainHand = mainHand; + this.textFilteringEnabled = textFilteringEnabled; this.clientListingAllowed = clientListingAllowed; + this.particleStatus = particleStatus; } public String getLocale() { @@ -102,12 +106,12 @@ public class ClientSettingsPacket implements MinecraftPacket { this.mainHand = mainHand; } - public boolean isChatFilteringEnabled() { - return chatFilteringEnabled; + public boolean isTextFilteringEnabled() { + return textFilteringEnabled; } - public void setChatFilteringEnabled(boolean chatFilteringEnabled) { - this.chatFilteringEnabled = chatFilteringEnabled; + public void setTextFilteringEnabled(boolean textFilteringEnabled) { + this.textFilteringEnabled = textFilteringEnabled; } public boolean isClientListingAllowed() { @@ -118,12 +122,20 @@ public class ClientSettingsPacket implements MinecraftPacket { this.clientListingAllowed = clientListingAllowed; } + public int getParticleStatus() { + return particleStatus; + } + + public void setParticleStatus(int particleStatus) { + this.particleStatus = particleStatus; + } + @Override public String toString() { return "ClientSettings{" + "locale='" + locale + '\'' + ", viewDistance=" + viewDistance + ", chatVisibility=" + chatVisibility + ", chatColors=" + chatColors + ", skinParts=" + - skinParts + ", mainHand=" + mainHand + ", chatFilteringEnabled=" + chatFilteringEnabled + - ", clientListingAllowed=" + clientListingAllowed + '}'; + skinParts + ", mainHand=" + mainHand + ", chatFilteringEnabled=" + textFilteringEnabled + + ", clientListingAllowed=" + clientListingAllowed + ", particleStatus=" + particleStatus + '}'; } @Override @@ -143,10 +155,14 @@ public class ClientSettingsPacket implements MinecraftPacket { this.mainHand = ProtocolUtils.readVarInt(buf); if (version.noLessThan(ProtocolVersion.MINECRAFT_1_17)) { - this.chatFilteringEnabled = buf.readBoolean(); + this.textFilteringEnabled = buf.readBoolean(); if (version.noLessThan(ProtocolVersion.MINECRAFT_1_18)) { this.clientListingAllowed = buf.readBoolean(); + + if (version.noLessThan(ProtocolVersion.MINECRAFT_1_21_2)) { + this.particleStatus = ProtocolUtils.readVarInt(buf); + } } } } @@ -172,11 +188,15 @@ public class ClientSettingsPacket implements MinecraftPacket { ProtocolUtils.writeVarInt(buf, mainHand); if (version.noLessThan(ProtocolVersion.MINECRAFT_1_17)) { - buf.writeBoolean(chatFilteringEnabled); + buf.writeBoolean(textFilteringEnabled); if (version.noLessThan(ProtocolVersion.MINECRAFT_1_18)) { buf.writeBoolean(clientListingAllowed); } + + if (version.noLessThan(ProtocolVersion.MINECRAFT_1_21_2)) { + ProtocolUtils.writeVarInt(buf, particleStatus); + } } } } @@ -201,8 +221,9 @@ public class ClientSettingsPacket implements MinecraftPacket { && difficulty == that.difficulty && skinParts == that.skinParts && mainHand == that.mainHand - && chatFilteringEnabled == that.chatFilteringEnabled + && textFilteringEnabled == that.textFilteringEnabled && clientListingAllowed == that.clientListingAllowed + && particleStatus == that.particleStatus && Objects.equals(locale, that.locale); } @@ -216,7 +237,8 @@ public class ClientSettingsPacket implements MinecraftPacket { difficulty, skinParts, mainHand, - chatFilteringEnabled, - clientListingAllowed); + textFilteringEnabled, + clientListingAllowed, + particleStatus); } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGamePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGamePacket.java index f1d2b6400..787d858eb 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGamePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGamePacket.java @@ -51,6 +51,7 @@ public class JoinGamePacket implements MinecraftPacket { private int simulationDistance; // 1.18+ private @Nullable Pair lastDeathPosition; // 1.19+ private int portalCooldown; // 1.20+ + private int seaLevel; // 1.21.2+ private boolean enforcesSecureChat; // 1.20.5+ public int getEntityId() { @@ -181,6 +182,14 @@ public class JoinGamePacket implements MinecraftPacket { this.portalCooldown = portalCooldown; } + public int getSeaLevel() { + return seaLevel; + } + + public void setSeaLevel(int seaLevel) { + this.seaLevel = seaLevel; + } + public boolean getEnforcesSecureChat() { return this.enforcesSecureChat; } @@ -204,6 +213,7 @@ public class JoinGamePacket implements MinecraftPacket { dimensionInfo + '\'' + ", currentDimensionData='" + currentDimensionData + '\'' + ", previousGamemode=" + previousGamemode + ", simulationDistance=" + simulationDistance + ", lastDeathPosition='" + lastDeathPosition + '\'' + ", portalCooldown=" + portalCooldown + + ", seaLevel=" + seaLevel + '}'; } @@ -343,6 +353,11 @@ public class JoinGamePacket implements MinecraftPacket { } this.portalCooldown = ProtocolUtils.readVarInt(buf); + + if (version.noLessThan(ProtocolVersion.MINECRAFT_1_21_2)) { + this.seaLevel = ProtocolUtils.readVarInt(buf); + } + if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20_5)) { this.enforcesSecureChat = buf.readBoolean(); } @@ -491,6 +506,10 @@ public class JoinGamePacket implements MinecraftPacket { ProtocolUtils.writeVarInt(buf, portalCooldown); + if (version.noLessThan(ProtocolVersion.MINECRAFT_1_21_2)) { + ProtocolUtils.writeVarInt(buf, seaLevel); + } + if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20_5)) { buf.writeBoolean(this.enforcesSecureChat); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RespawnPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RespawnPacket.java index ceaee9fd2..9304dc3f9 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RespawnPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RespawnPacket.java @@ -41,6 +41,7 @@ public class RespawnPacket implements MinecraftPacket { private CompoundBinaryTag currentDimensionData; // 1.16.2+ private @Nullable Pair lastDeathPosition; // 1.19+ private int portalCooldown; // 1.20+ + private int seaLevel; // 1.21.2+ public RespawnPacket() { } @@ -48,7 +49,8 @@ public class RespawnPacket implements MinecraftPacket { public RespawnPacket(int dimension, long partialHashedSeed, short difficulty, short gamemode, String levelType, byte dataToKeep, DimensionInfo dimensionInfo, short previousGamemode, CompoundBinaryTag currentDimensionData, - @Nullable Pair lastDeathPosition, int portalCooldown) { + @Nullable Pair lastDeathPosition, int portalCooldown, + int seaLevel) { this.dimension = dimension; this.partialHashedSeed = partialHashedSeed; this.difficulty = difficulty; @@ -60,13 +62,15 @@ public class RespawnPacket implements MinecraftPacket { this.currentDimensionData = currentDimensionData; this.lastDeathPosition = lastDeathPosition; this.portalCooldown = portalCooldown; + this.seaLevel = seaLevel; } public static RespawnPacket fromJoinGame(JoinGamePacket joinGame) { return new RespawnPacket(joinGame.getDimension(), joinGame.getPartialHashedSeed(), joinGame.getDifficulty(), joinGame.getGamemode(), joinGame.getLevelType(), (byte) 0, joinGame.getDimensionInfo(), joinGame.getPreviousGamemode(), - joinGame.getCurrentDimensionData(), joinGame.getLastDeathPosition(), joinGame.getPortalCooldown()); + joinGame.getCurrentDimensionData(), joinGame.getLastDeathPosition(), + joinGame.getPortalCooldown(), joinGame.getSeaLevel()); } public int getDimension() { @@ -141,6 +145,14 @@ public class RespawnPacket implements MinecraftPacket { this.portalCooldown = portalCooldown; } + public int getSeaLevel() { + return seaLevel; + } + + public void setSeaLevel(int seaLevel) { + this.seaLevel = seaLevel; + } + @Override public String toString() { return "Respawn{" @@ -155,6 +167,7 @@ public class RespawnPacket implements MinecraftPacket { + ", previousGamemode=" + previousGamemode + ", dimensionData=" + currentDimensionData + ", portalCooldown=" + portalCooldown + + ", seaLevel=" + seaLevel + '}'; } @@ -204,6 +217,9 @@ public class RespawnPacket implements MinecraftPacket { if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20)) { this.portalCooldown = ProtocolUtils.readVarInt(buf); } + if (version.noLessThan(ProtocolVersion.MINECRAFT_1_21_2)) { + this.seaLevel = ProtocolUtils.readVarInt(buf); + } if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20_2)) { this.dataToKeep = buf.readByte(); } @@ -262,6 +278,10 @@ public class RespawnPacket implements MinecraftPacket { ProtocolUtils.writeVarInt(buf, portalCooldown); } + if (version.noLessThan(ProtocolVersion.MINECRAFT_1_12_1)) { + ProtocolUtils.writeVarInt(buf, seaLevel); + } + if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20_2)) { buf.writeByte(dataToKeep); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/UpsertPlayerInfoPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/UpsertPlayerInfoPacket.java index 4c70536b0..e2d40d2e3 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/UpsertPlayerInfoPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/UpsertPlayerInfoPacket.java @@ -188,6 +188,11 @@ public class UpsertPlayerInfoPacket implements MinecraftPacket { if (info.displayName != null) { info.displayName.write(buf); } + }), + UPDATE_LIST_ORDER((version, buf, info) -> { // read + info.listOrder = ProtocolUtils.readVarInt(buf); + }, (version, buf, info) -> { // write + ProtocolUtils.writeVarInt(buf, info.listOrder); }); private final Read read; @@ -218,6 +223,7 @@ public class UpsertPlayerInfoPacket implements MinecraftPacket { private int gameMode; @Nullable private ComponentHolder displayName; + private int listOrder; @Nullable private RemoteChatSession chatSession; @@ -250,6 +256,10 @@ public class UpsertPlayerInfoPacket implements MinecraftPacket { return displayName; } + public int getListOrder() { + return listOrder; + } + @Nullable public RemoteChatSession getChatSession() { return chatSession; @@ -275,6 +285,10 @@ public class UpsertPlayerInfoPacket implements MinecraftPacket { this.displayName = displayName; } + public void setListOrder(int listOrder) { + this.listOrder = listOrder; + } + public void setChatSession(@Nullable RemoteChatSession chatSession) { this.chatSession = chatSession; } @@ -288,6 +302,7 @@ public class UpsertPlayerInfoPacket implements MinecraftPacket { ", latency=" + latency + ", gameMode=" + gameMode + ", displayName=" + displayName + + ", listOrder=" + listOrder + ", chatSession=" + chatSession + '}'; }