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 7f6912a6..6653ff9c 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -96,7 +96,8 @@ public enum ProtocolVersion implements Ordered { MINECRAFT_1_21_9(773, "1.21.9", "1.21.10"), MINECRAFT_1_21_11(774, "1.21.11"), MINECRAFT_26_1(775, "26.1", "26.1.1", "26.1.2"), - MINECRAFT_26_2(776, "26.2"); + MINECRAFT_26_2(776, "26.2"), + MINECRAFT_26_3(777, "26.3"); 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 00783dbf..9df71c3f 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java @@ -23,6 +23,7 @@ import com.velocitypowered.proxy.protocol.packet.BossBarPacket; import com.velocitypowered.proxy.protocol.packet.BundleDelimiterPacket; import com.velocitypowered.proxy.protocol.packet.ClientSettingsPacket; import com.velocitypowered.proxy.protocol.packet.ClientboundCookieRequestPacket; +import com.velocitypowered.proxy.protocol.packet.ClientboundPostEffectsPacket; import com.velocitypowered.proxy.protocol.packet.ClientboundSoundEntityPacket; import com.velocitypowered.proxy.protocol.packet.ClientboundStopSoundPacket; import com.velocitypowered.proxy.protocol.packet.ClientboundStoreCookiePacket; @@ -404,4 +405,8 @@ public interface MinecraftSessionHandler { default boolean handle(ClientboundStopSoundPacket packet) { return false; } + + default boolean handle(ClientboundPostEffectsPacket packet) { + return false; + } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java index 328252ea..f5ed5d3e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java @@ -143,6 +143,7 @@ public enum ProtocolUtils { .build(); public static final int DEFAULT_MAX_STRING_SIZE = 65536; // 64KiB + private static final int DEFAULT_MAX_KEY_ARRAY_SIZE = 1024; private static final int MAXIMUM_VARINT_SIZE = 5; private static final BinaryTagType[] BINARY_TAG_TYPES = new BinaryTagType[] { BinaryTagTypes.END, BinaryTagTypes.BYTE, BinaryTagTypes.SHORT, BinaryTagTypes.INT, @@ -349,15 +350,20 @@ public enum ProtocolUtils { writeString(buf, key.asMinimalString()); } + public static Key[] readKeyArray(ByteBuf buf) { + return readKeyArray(buf, DEFAULT_MAX_KEY_ARRAY_SIZE); + } + /** * Reads a standard Mojang Text namespaced:key array from the buffer. * * @param buf the buffer to read from * @return the decoded key array */ - public static Key[] readKeyArray(ByteBuf buf) { + public static Key[] readKeyArray(ByteBuf buf, int cap) { int length = readVarInt(buf); checkFrame(length >= 0, "Got a negative-length array (%s)", length); + checkFrame(length <= cap, "Bad key array size (got %s, maximum is %s)", length, cap); checkFrame(buf.isReadable(length), "Trying to read an array that is too long (wanted %s, only have %s)", length, buf.readableBytes()); 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 b35bf1c7..1da9c424 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java @@ -47,6 +47,7 @@ import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_8; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_9; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_9_4; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_26_1; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_26_3; import static com.velocitypowered.api.network.ProtocolVersion.MINIMUM_VERSION; import static com.velocitypowered.api.network.ProtocolVersion.SUPPORTED_VERSIONS; import static com.velocitypowered.proxy.protocol.ProtocolUtils.Direction; @@ -60,6 +61,7 @@ import com.velocitypowered.proxy.protocol.packet.BossBarPacket; import com.velocitypowered.proxy.protocol.packet.BundleDelimiterPacket; import com.velocitypowered.proxy.protocol.packet.ClientSettingsPacket; import com.velocitypowered.proxy.protocol.packet.ClientboundCookieRequestPacket; +import com.velocitypowered.proxy.protocol.packet.ClientboundPostEffectsPacket; import com.velocitypowered.proxy.protocol.packet.ClientboundSoundEntityPacket; import com.velocitypowered.proxy.protocol.packet.ClientboundStopSoundPacket; import com.velocitypowered.proxy.protocol.packet.ClientboundStoreCookiePacket; @@ -234,31 +236,44 @@ public enum StateRegistry { map(0x06, MINECRAFT_1_20_2, false), map(0x07, MINECRAFT_1_20_3, false), map(0x09, MINECRAFT_1_20_5, false)); + clientbound.register( + ClientboundPostEffectsPacket.class, ClientboundPostEffectsPacket::new, + map(0x0A, MINECRAFT_26_3, false)); clientbound.register( ClientboundStoreCookiePacket.class, ClientboundStoreCookiePacket::new, - map(0x0A, MINECRAFT_1_20_5, false)); + map(0x0A, MINECRAFT_1_20_5, false), + map(0x0B, MINECRAFT_26_3, false)); clientbound.register(TransferPacket.class, TransferPacket::new, - map(0x0B, MINECRAFT_1_20_5, false)); + map(0x0B, MINECRAFT_1_20_5, false), + map(0x0C, MINECRAFT_26_3, false)); clientbound.register(ActiveFeaturesPacket.class, ActiveFeaturesPacket::new, map(0x07, MINECRAFT_1_20_2, false), map(0x08, MINECRAFT_1_20_3, false), - map(0x0C, MINECRAFT_1_20_5, false)); + map(0x0C, MINECRAFT_1_20_5, false), + map(0x0D, MINECRAFT_26_3, false)); clientbound.register(TagsUpdatePacket.class, TagsUpdatePacket::new, map(0x08, MINECRAFT_1_20_2, false), map(0x09, MINECRAFT_1_20_3, false), - map(0x0D, MINECRAFT_1_20_5, false)); + map(0x0D, MINECRAFT_1_20_5, false), + map(0x0E, MINECRAFT_26_3, false)); clientbound.register(KnownPacksPacket.class, KnownPacksPacket::new, - map(0x0E, MINECRAFT_1_20_5, false)); + map(0x0E, MINECRAFT_1_20_5, false), + map(0x0F, MINECRAFT_26_3, false)); clientbound.register(ClientboundCustomReportDetailsPacket.class, ClientboundCustomReportDetailsPacket::new, - map(0x0F, MINECRAFT_1_21, false)); + map(0x0F, MINECRAFT_1_21, false), + map(0x10, MINECRAFT_26_3, false)); clientbound.register(ClientboundServerLinksPacket.class, ClientboundServerLinksPacket::new, - map(0x10, MINECRAFT_1_21, false)); + map(0x10, MINECRAFT_1_21, false), + map(0x11, MINECRAFT_26_3, false)); clientbound.register(DialogClearPacket.class, () -> DialogClearPacket.INSTANCE, - map(0x11, MINECRAFT_1_21_6, false)); + map(0x11, MINECRAFT_1_21_6, false), + map(0x12, MINECRAFT_26_3, false)); clientbound.register(DialogShowPacket.class, () -> new DialogShowPacket(this), - map(0x12, MINECRAFT_1_21_6, false)); + map(0x12, MINECRAFT_1_21_6, false), + map(0x13, MINECRAFT_26_3, false)); clientbound.register(CodeOfConductPacket.class, CodeOfConductPacket::new, - map(0x13, MINECRAFT_1_21_9, false)); + map(0x13, MINECRAFT_1_21_9, false), + map(0x14, MINECRAFT_26_3, false)); } }, PLAY { @@ -410,7 +425,8 @@ public enum StateRegistry { map(0x2D, MINECRAFT_1_21_2, false), map(0x2F, MINECRAFT_1_21_4, false), map(0x30, MINECRAFT_1_21_6, false), - map(0x31, MINECRAFT_26_1, false)); + map(0x31, MINECRAFT_26_1, false), + map(0x32, MINECRAFT_26_3, false)); serverbound.register( FinishedUpdatePacket.class, () -> FinishedUpdatePacket.INSTANCE, map(0x0B, MINECRAFT_1_20_2, false), @@ -469,6 +485,9 @@ public enum StateRegistry { ClientboundCookieRequestPacket.class, ClientboundCookieRequestPacket::new, map(0x16, MINECRAFT_1_20_5, false), map(0x15, MINECRAFT_1_21_5, false)); + clientbound.register( + ClientboundPostEffectsPacket.class, ClientboundPostEffectsPacket::new, + map(0x53, MINECRAFT_26_3, false)); clientbound.register( ClientboundSoundEntityPacket.class, ClientboundSoundEntityPacket::new, map(0x5D, MINECRAFT_1_19_3, true), @@ -479,7 +498,8 @@ public enum StateRegistry { map(0x6E, MINECRAFT_1_21_2, true), map(0x6D, MINECRAFT_1_21_5, true), map(0x72, MINECRAFT_1_21_9, true), - map(0x74, MINECRAFT_26_1, true)); + map(0x74, MINECRAFT_26_1, true), + map(0x76, MINECRAFT_26_3, true)); clientbound.register( ClientboundStopSoundPacket.class, ClientboundStopSoundPacket::new, map(0x5F, MINECRAFT_1_19_3, true), @@ -490,7 +510,8 @@ public enum StateRegistry { map(0x71, MINECRAFT_1_21_2, true), map(0x70, MINECRAFT_1_21_5, true), map(0x75, MINECRAFT_1_21_9, true), - map(0x77, MINECRAFT_26_1, true)); + map(0x77, MINECRAFT_26_1, true), + map(0x79, MINECRAFT_26_3, true)); clientbound.register( PluginMessagePacket.class, PluginMessagePacket::new, @@ -548,7 +569,8 @@ public enum StateRegistry { map(0x27, MINECRAFT_1_21_2, false), map(0x26, MINECRAFT_1_21_5, false), map(0x2B, MINECRAFT_1_21_9, false), - map(0x2C, MINECRAFT_26_1, false)); + map(0x2C, MINECRAFT_26_1, false), + map(0x2D, MINECRAFT_26_3, false)); clientbound.register( JoinGamePacket.class, JoinGamePacket::new, @@ -569,7 +591,8 @@ public enum StateRegistry { map(0x2C, MINECRAFT_1_21_2, false), map(0x2B, MINECRAFT_1_21_5, false), map(0x30, MINECRAFT_1_21_9, false), - map(0x31, MINECRAFT_26_1, false)); + map(0x31, MINECRAFT_26_1, false), + map(0x32, MINECRAFT_26_3, false)); clientbound.register( RespawnPacket.class, RespawnPacket::new, @@ -593,7 +616,8 @@ public enum StateRegistry { map(0x4C, MINECRAFT_1_21_2, true), map(0x4B, MINECRAFT_1_21_5, true), map(0x50, MINECRAFT_1_21_9, true), - map(0x52, MINECRAFT_26_1, true)); + map(0x52, MINECRAFT_26_1, true), + map(0x54, MINECRAFT_26_3, true)); clientbound.register( RemoveResourcePackPacket.class, RemoveResourcePackPacket::new, @@ -602,7 +626,8 @@ public enum StateRegistry { map(0x4A, MINECRAFT_1_21_2, false), map(0x49, MINECRAFT_1_21_5, false), map(0x4E, MINECRAFT_1_21_9, false), - map(0x50, MINECRAFT_26_1, false)); + map(0x50, MINECRAFT_26_1, false), + map(0x51, MINECRAFT_26_3, false)); clientbound.register( ResourcePackRequestPacket.class, ResourcePackRequestPacket::new, @@ -626,7 +651,8 @@ public enum StateRegistry { map(0x4B, MINECRAFT_1_21_2, false), map(0x4A, MINECRAFT_1_21_5, false), map(0x4F, MINECRAFT_1_21_9, false), - map(0x51, MINECRAFT_26_1, false)); + map(0x51, MINECRAFT_26_1, false), + map(0x52, MINECRAFT_26_3, false)); clientbound.register( HeaderAndFooterPacket.class, HeaderAndFooterPacket::new, @@ -651,7 +677,8 @@ public enum StateRegistry { map(0x74, MINECRAFT_1_21_2, true), map(0x73, MINECRAFT_1_21_5, true), map(0x78, MINECRAFT_1_21_9, true), - map(0x7A, MINECRAFT_26_1, true)); + map(0x7A, MINECRAFT_26_1, true), + map(0x7D, MINECRAFT_26_3, true)); clientbound.register( LegacyTitlePacket.class, LegacyTitlePacket::new, @@ -675,7 +702,8 @@ public enum StateRegistry { map(0x6A, MINECRAFT_1_21_2, true), map(0x69, MINECRAFT_1_21_5, true), map(0x6E, MINECRAFT_1_21_9, true), - map(0x70, MINECRAFT_26_1, true)); + map(0x70, MINECRAFT_26_1, true), + map(0x72, MINECRAFT_26_3, true)); clientbound.register( TitleTextPacket.class, TitleTextPacket::new, @@ -690,7 +718,8 @@ public enum StateRegistry { map(0x6C, MINECRAFT_1_21_2, true), map(0x6B, MINECRAFT_1_21_5, true), map(0x70, MINECRAFT_1_21_9, true), - map(0x72, MINECRAFT_26_1, true)); + map(0x72, MINECRAFT_26_1, true), + map(0x74, MINECRAFT_26_3, true)); clientbound.register( TitleActionbarPacket.class, TitleActionbarPacket::new, @@ -705,7 +734,8 @@ public enum StateRegistry { map(0x51, MINECRAFT_1_21_2, true), map(0x50, MINECRAFT_1_21_5, true), map(0x55, MINECRAFT_1_21_9, true), - map(0x57, MINECRAFT_26_1, true)); + map(0x57, MINECRAFT_26_1, true), + map(0x59, MINECRAFT_26_3, true)); clientbound.register( TitleTimesPacket.class, TitleTimesPacket::new, @@ -720,7 +750,8 @@ public enum StateRegistry { map(0x6D, MINECRAFT_1_21_2, true), map(0x6C, MINECRAFT_1_21_5, true), map(0x71, MINECRAFT_1_21_9, true), - map(0x73, MINECRAFT_26_1, true)); + map(0x73, MINECRAFT_26_1, true), + map(0x75, MINECRAFT_26_3, true)); clientbound.register( TitleClearPacket.class, TitleClearPacket::new, @@ -752,7 +783,8 @@ public enum StateRegistry { map(0x3F, MINECRAFT_1_21_2, false), map(0x3E, MINECRAFT_1_21_5, false), map(0x43, MINECRAFT_1_21_9, false), - map(0x45, MINECRAFT_26_1, false)); + map(0x45, MINECRAFT_26_1, false), + map(0x46, MINECRAFT_26_3, false)); clientbound.register( UpsertPlayerInfoPacket.class, UpsertPlayerInfoPacket::new, @@ -763,14 +795,16 @@ public enum StateRegistry { map(0x40, MINECRAFT_1_21_2, false), map(0x3F, MINECRAFT_1_21_5, false), map(0x44, MINECRAFT_1_21_9, false), - map(0x46, MINECRAFT_26_1, false)); + map(0x46, MINECRAFT_26_1, false), + map(0x47, MINECRAFT_26_3, false)); clientbound.register( ClientboundStoreCookiePacket.class, ClientboundStoreCookiePacket::new, map(0x6B, MINECRAFT_1_20_5, false), map(0x72, MINECRAFT_1_21_2, false), map(0x71, MINECRAFT_1_21_5, false), map(0x76, MINECRAFT_1_21_9, false), - map(0x78, MINECRAFT_26_1, false)); + map(0x78, MINECRAFT_26_1, false), + map(0x7A, MINECRAFT_26_3, false)); clientbound.register( SystemChatPacket.class, SystemChatPacket::new, @@ -784,7 +818,8 @@ public enum StateRegistry { map(0x73, MINECRAFT_1_21_2, true), map(0x72, MINECRAFT_1_21_5, true), map(0x77, MINECRAFT_1_21_9, true), - map(0x79, MINECRAFT_26_1, true)); + map(0x79, MINECRAFT_26_1, true), + map(0x7C, MINECRAFT_26_3, true)); clientbound.register( PlayerChatCompletionPacket.class, PlayerChatCompletionPacket::new, @@ -807,7 +842,8 @@ public enum StateRegistry { map(0x50, MINECRAFT_1_21_2, false), map(0x4F, MINECRAFT_1_21_5, false), map(0x54, MINECRAFT_1_21_9, false), - map(0x56, MINECRAFT_26_1, false)); + map(0x56, MINECRAFT_26_1, false), + map(0x58, MINECRAFT_26_3, false)); clientbound.register( StartUpdatePacket.class, () -> StartUpdatePacket.INSTANCE, @@ -817,7 +853,8 @@ public enum StateRegistry { map(0x70, MINECRAFT_1_21_2, false), map(0x6F, MINECRAFT_1_21_5, false), map(0x74, MINECRAFT_1_21_9, false), - map(0x76, MINECRAFT_26_1, false)); + map(0x76, MINECRAFT_26_1, false), + map(0x78, MINECRAFT_26_3, false)); clientbound.register( BundleDelimiterPacket.class, () -> BundleDelimiterPacket.INSTANCE, @@ -828,21 +865,24 @@ public enum StateRegistry { map(0x73, MINECRAFT_1_20_5, false), map(0x7A, MINECRAFT_1_21_2, false), map(0x7F, MINECRAFT_1_21_9, false), - map(0x81, MINECRAFT_26_1, false)); + map(0x81, MINECRAFT_26_1, false), + map(0x84, MINECRAFT_26_3, false)); clientbound.register( ClientboundCustomReportDetailsPacket.class, ClientboundCustomReportDetailsPacket::new, map(0x7A, MINECRAFT_1_21, false), map(0x81, MINECRAFT_1_21_2, false), map(0x86, MINECRAFT_1_21_9, false), - map(0x88, MINECRAFT_26_1, false)); + map(0x88, MINECRAFT_26_1, false), + map(0x8B, MINECRAFT_26_3, false)); clientbound.register( ClientboundServerLinksPacket.class, ClientboundServerLinksPacket::new, map(0x7B, MINECRAFT_1_21, false), map(0x82, MINECRAFT_1_21_2, false), map(0x87, MINECRAFT_1_21_9, false), - map(0x89, MINECRAFT_26_1, false)); + map(0x89, MINECRAFT_26_1, false), + map(0x8C, MINECRAFT_26_3, false)); } }, LOGIN { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundPostEffectsPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundPostEffectsPacket.java new file mode 100644 index 00000000..19d4f403 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundPostEffectsPacket.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2018-2026 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 com.velocitypowered.proxy.protocol.ProtocolUtils.Direction; +import io.netty.buffer.ByteBuf; +import net.kyori.adventure.key.Key; + +public final class ClientboundPostEffectsPacket implements MinecraftPacket { + + private Key[] postEffects; + + public ClientboundPostEffectsPacket() { + } + + public ClientboundPostEffectsPacket(Key[] postEffects) { + this.postEffects = postEffects; + } + + @Override + public void decode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) { + this.postEffects = ProtocolUtils.readKeyArray(buf); + } + + @Override + public void encode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) { + ProtocolUtils.writeKeyArray(buf, this.postEffects); + } + + @Override + public boolean handle(MinecraftSessionHandler handler) { + return handler.handle(this); + } +} 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 645dc7b6..ca777a27 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 @@ -32,7 +32,7 @@ public class JoinGamePacket implements MinecraftPacket { private static final BinaryTagIO.Reader JOINGAME_READER = BinaryTagIO.reader(4 * 1024 * 1024); private int entityId; - private short gamemode; + private int gamemode; private int dimension; private long partialHashedSeed; // 1.15+ private short difficulty; @@ -47,7 +47,7 @@ public class JoinGamePacket implements MinecraftPacket { private CompoundBinaryTag registry; // 1.16+ private DimensionInfo dimensionInfo; // 1.16+ private CompoundBinaryTag currentDimensionData; // 1.16.2+ - private short previousGamemode; // 1.16+ + private int previousGamemode; // 1.16+ private int simulationDistance; // 1.18+ private @Nullable Pair lastDeathPosition; // 1.19+ private int portalCooldown; // 1.20+ @@ -63,11 +63,11 @@ public class JoinGamePacket implements MinecraftPacket { this.entityId = entityId; } - public short getGamemode() { + public int getGamemode() { return gamemode; } - public void setGamemode(short gamemode) { + public void setGamemode(int gamemode) { this.gamemode = gamemode; } @@ -131,11 +131,11 @@ public class JoinGamePacket implements MinecraftPacket { this.dimensionInfo = dimensionInfo; } - public short getPreviousGamemode() { + public int getPreviousGamemode() { return previousGamemode; } - public void setPreviousGamemode(short previousGamemode) { + public void setPreviousGamemode(int previousGamemode) { this.previousGamemode = previousGamemode; } @@ -345,8 +345,13 @@ public class JoinGamePacket implements MinecraftPacket { String levelName = ProtocolUtils.readString(buf); this.partialHashedSeed = buf.readLong(); - this.gamemode = buf.readByte(); - this.previousGamemode = buf.readByte(); + if (version.noLessThan(ProtocolVersion.MINECRAFT_26_3)) { + this.gamemode = ProtocolUtils.readVarInt(buf); + this.previousGamemode = ProtocolUtils.readVarInt(buf); // game mode + 1 or 0 + } else { + this.gamemode = buf.readByte(); + this.previousGamemode = buf.readByte(); // game mode or -1 + } boolean isDebug = buf.readBoolean(); boolean isFlat = buf.readBoolean(); @@ -498,8 +503,13 @@ public class JoinGamePacket implements MinecraftPacket { ProtocolUtils.writeString(buf, dimensionInfo.getLevelName()); buf.writeLong(partialHashedSeed); - buf.writeByte(gamemode); - buf.writeByte(previousGamemode); + if (version.noLessThan(ProtocolVersion.MINECRAFT_26_3)) { + ProtocolUtils.writeVarInt(buf, this.gamemode); + ProtocolUtils.writeVarInt(buf, this.previousGamemode); + } else { + buf.writeByte(this.gamemode); + buf.writeByte(this.previousGamemode); + } buf.writeBoolean(dimensionInfo.isDebugType()); buf.writeBoolean(dimensionInfo.isFlat()); 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 fd9c8ca7..d20c253f 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 @@ -33,11 +33,11 @@ public class RespawnPacket implements MinecraftPacket { private int dimension; private long partialHashedSeed; private short difficulty; - private short gamemode; + private int gamemode; private String levelType = ""; private byte dataToKeep; // 1.16+ private DimensionInfo dimensionInfo; // 1.16-1.16.1 - private short previousGamemode; // 1.16+ + private int previousGamemode; // 1.16+ private CompoundBinaryTag currentDimensionData; // 1.16.2+ private @Nullable Pair lastDeathPosition; // 1.19+ private int portalCooldown; // 1.20+ @@ -46,9 +46,9 @@ public class RespawnPacket implements MinecraftPacket { public RespawnPacket() { } - public RespawnPacket(int dimension, long partialHashedSeed, short difficulty, short gamemode, + public RespawnPacket(int dimension, long partialHashedSeed, short difficulty, int gamemode, String levelType, byte dataToKeep, DimensionInfo dimensionInfo, - short previousGamemode, CompoundBinaryTag currentDimensionData, + int previousGamemode, CompoundBinaryTag currentDimensionData, @Nullable Pair lastDeathPosition, int portalCooldown, int seaLevel) { this.dimension = dimension; @@ -97,11 +97,11 @@ public class RespawnPacket implements MinecraftPacket { this.difficulty = difficulty; } - public short getGamemode() { + public int getGamemode() { return gamemode; } - public void setGamemode(short gamemode) { + public void setGamemode(int gamemode) { this.gamemode = gamemode; } @@ -121,11 +121,11 @@ public class RespawnPacket implements MinecraftPacket { this.dataToKeep = dataToKeep; } - public short getPreviousGamemode() { + public int getPreviousGamemode() { return previousGamemode; } - public void setPreviousGamemode(short previousGamemode) { + public void setPreviousGamemode(int previousGamemode) { this.previousGamemode = previousGamemode; } @@ -197,9 +197,17 @@ public class RespawnPacket implements MinecraftPacket { if (version.noLessThan(ProtocolVersion.MINECRAFT_1_15)) { this.partialHashedSeed = buf.readLong(); } - this.gamemode = buf.readByte(); + if (version.noLessThan(ProtocolVersion.MINECRAFT_26_3)) { + this.gamemode = ProtocolUtils.readVarInt(buf); + } else { + this.gamemode = buf.readByte(); + } if (version.noLessThan(ProtocolVersion.MINECRAFT_1_16)) { - this.previousGamemode = buf.readByte(); + if (version.noLessThan(ProtocolVersion.MINECRAFT_26_3)) { + this.previousGamemode = ProtocolUtils.readVarInt(buf); + } else { + this.previousGamemode = buf.readByte(); + } boolean isDebug = buf.readBoolean(); boolean isFlat = buf.readBoolean(); this.dimensionInfo = new DimensionInfo(dimensionKey, levelName, isFlat, isDebug, version); @@ -249,9 +257,17 @@ public class RespawnPacket implements MinecraftPacket { if (version.noLessThan(ProtocolVersion.MINECRAFT_1_15)) { buf.writeLong(partialHashedSeed); } - buf.writeByte(gamemode); + if (version.noLessThan(ProtocolVersion.MINECRAFT_26_3)) { + ProtocolUtils.writeVarInt(buf, this.gamemode); + } else { + buf.writeByte(this.gamemode); + } if (version.noLessThan(ProtocolVersion.MINECRAFT_1_16)) { - buf.writeByte(previousGamemode); + if (version.noLessThan(ProtocolVersion.MINECRAFT_26_3)) { + ProtocolUtils.writeVarInt(buf, this.previousGamemode); + } else { + buf.writeByte(this.previousGamemode); + } buf.writeBoolean(dimensionInfo.isDebugType()); buf.writeBoolean(dimensionInfo.isFlat()); if (version.lessThan(ProtocolVersion.MINECRAFT_1_19_3)) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java index 3c57cd75..6d735fa8 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java @@ -25,6 +25,7 @@ import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_20_5; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_21_5; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_21_6; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_26_2; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_26_3; import static com.velocitypowered.proxy.protocol.packet.brigadier.ArgumentIdentifier.id; import static com.velocitypowered.proxy.protocol.packet.brigadier.ArgumentIdentifier.mapSet; import static com.velocitypowered.proxy.protocol.packet.brigadier.DoubleArgumentPropertySerializer.DOUBLE; @@ -273,16 +274,21 @@ public class ArgumentPropertyRegistry { empty(id("minecraft:heightmap", mapSet(MINECRAFT_1_21_6, 51), mapSet(MINECRAFT_1_21_5, 50), mapSet(MINECRAFT_1_20_3, 49), mapSet(MINECRAFT_1_19_4, 47))); // 1.19.4 - empty(id("minecraft:uuid", mapSet(MINECRAFT_1_21_6, 56), mapSet(MINECRAFT_1_21_5, 54),mapSet(MINECRAFT_1_20_5, 53), mapSet(MINECRAFT_1_20_3, 48), - mapSet(MINECRAFT_1_19_4, 48), mapSet(MINECRAFT_1_19, 47))); // added in 1.16 + empty(id("minecraft:uuid", mapSet(MINECRAFT_26_3, 61), mapSet(MINECRAFT_1_21_6, 56), mapSet(MINECRAFT_1_21_5, 54), mapSet(MINECRAFT_1_20_5, 53), + mapSet(MINECRAFT_1_20_3, 48), mapSet(MINECRAFT_1_19_4, 48), mapSet(MINECRAFT_1_19, 47))); // added in 1.16 empty(id("minecraft:loot_table", mapSet(MINECRAFT_1_21_6, 52), mapSet(MINECRAFT_1_21_5, 51), mapSet(MINECRAFT_1_20_5, 50))); empty(id("minecraft:loot_predicate", mapSet(MINECRAFT_1_21_6, 53), mapSet(MINECRAFT_1_21_5, 52), mapSet(MINECRAFT_1_20_5, 51))); empty(id("minecraft:loot_modifier", mapSet(MINECRAFT_1_21_6, 54), mapSet(MINECRAFT_1_21_5, 53), mapSet(MINECRAFT_1_20_5, 52))); empty(id("minecraft:hex_color", mapSet(MINECRAFT_1_21_6, 17))); // added in 1.21.6 - empty(id("minecraft:dialog", mapSet(MINECRAFT_1_21_6, 55))); // added in 1.21.6 + empty(id("minecraft:dialog", mapSet(MINECRAFT_26_3, 58), mapSet(MINECRAFT_1_21_6, 55))); // added in 1.21.6 empty(id("minecraft:team_color", mapSet(MINECRAFT_26_2, 16))); // renamed from color in 26.2 + empty(id("minecraft:context_float_provider", mapSet(MINECRAFT_26_3, 55))); // added in 26.3 + empty(id("minecraft:context_int_provider", mapSet(MINECRAFT_26_3, 56))); // added in 26.3 + empty(id("minecraft:slot_source", mapSet(MINECRAFT_26_3, 57))); // added in 26.3 + empty(id("minecraft:feature", mapSet(MINECRAFT_26_3, 59))); // added in 26.3 + empty(id("minecraft:swing_animation", mapSet(MINECRAFT_26_3, 60))); // added in 26.3 // Crossstitch support register(id("crossstitch:mod_argument", mapSet(MINECRAFT_1_19, -256)), ModArgumentProperty.class, MOD);