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 039fec40..916e3db5 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -92,7 +92,8 @@ public enum ProtocolVersion implements Ordered { MINECRAFT_1_21_4(769, "1.21.4"), MINECRAFT_1_21_5(770, "1.21.5"), MINECRAFT_1_21_6(771, "1.21.6"), - MINECRAFT_1_21_7(772, "1.21.7", "1.21.8"); + MINECRAFT_1_21_7(772, "1.21.7", "1.21.8"), + MINECRAFT_1_21_9(773, "1.21.9"); 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 a3ba0005..94620218 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java @@ -70,6 +70,8 @@ import com.velocitypowered.proxy.protocol.packet.chat.session.SessionPlayerComma import com.velocitypowered.proxy.protocol.packet.config.ActiveFeaturesPacket; import com.velocitypowered.proxy.protocol.packet.config.ClientboundCustomReportDetailsPacket; import com.velocitypowered.proxy.protocol.packet.config.ClientboundServerLinksPacket; +import com.velocitypowered.proxy.protocol.packet.config.CodeOfConductAcceptPacket; +import com.velocitypowered.proxy.protocol.packet.config.CodeOfConductPacket; import com.velocitypowered.proxy.protocol.packet.config.FinishedUpdatePacket; import com.velocitypowered.proxy.protocol.packet.config.KnownPacksPacket; import com.velocitypowered.proxy.protocol.packet.config.RegistrySyncPacket; @@ -380,4 +382,12 @@ public interface MinecraftSessionHandler { return false; } + default boolean handle(CodeOfConductPacket packet) { + return false; + } + + default boolean handle(CodeOfConductAcceptPacket packet) { + return false; + } + } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/ConfigSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/ConfigSessionHandler.java index fb0e48d1..90bb1a30 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/ConfigSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/ConfigSessionHandler.java @@ -52,6 +52,7 @@ import com.velocitypowered.proxy.protocol.packet.ResourcePackResponsePacket; import com.velocitypowered.proxy.protocol.packet.TransferPacket; import com.velocitypowered.proxy.protocol.packet.config.ClientboundCustomReportDetailsPacket; import com.velocitypowered.proxy.protocol.packet.config.ClientboundServerLinksPacket; +import com.velocitypowered.proxy.protocol.packet.config.CodeOfConductPacket; import com.velocitypowered.proxy.protocol.packet.config.FinishedUpdatePacket; import com.velocitypowered.proxy.protocol.packet.config.RegistrySyncPacket; import com.velocitypowered.proxy.protocol.packet.config.StartUpdatePacket; @@ -358,6 +359,12 @@ public class ConfigSessionHandler implements MinecraftSessionHandler { return true; } + @Override + public boolean handle(CodeOfConductPacket packet) { + this.serverConn.getPlayer().getConnection().write(packet.retain()); + return true; + } + @Override public void disconnected() { resultFuture.completeExceptionally( diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientConfigSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientConfigSessionHandler.java index 6117721a..776f99d6 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientConfigSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientConfigSessionHandler.java @@ -41,6 +41,7 @@ import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket; import com.velocitypowered.proxy.protocol.packet.ResourcePackResponsePacket; import com.velocitypowered.proxy.protocol.packet.ServerboundCookieResponsePacket; import com.velocitypowered.proxy.protocol.packet.ServerboundCustomClickActionPacket; +import com.velocitypowered.proxy.protocol.packet.config.CodeOfConductAcceptPacket; import com.velocitypowered.proxy.protocol.packet.config.FinishedUpdatePacket; import com.velocitypowered.proxy.protocol.packet.config.KnownPacksPacket; import com.velocitypowered.proxy.protocol.util.PluginMessageUtil; @@ -216,6 +217,16 @@ public class ClientConfigSessionHandler implements MinecraftSessionHandler { return false; } + @Override + public boolean handle(CodeOfConductAcceptPacket packet) { + if (this.player.getConnectionInFlight() != null) { + this.player.getConnectionInFlight().ensureConnected().write(packet); + return true; + } + + return false; + } + @Override public void handleGeneric(MinecraftPacket packet) { VelocityServerConnection serverConnection = player.getConnectedServer(); 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 e9ff3289..42d60029 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java @@ -41,6 +41,7 @@ import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_21_2; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_21_4; 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_1_21_9; 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; @@ -104,6 +105,8 @@ import com.velocitypowered.proxy.protocol.packet.chat.session.UnsignedPlayerComm import com.velocitypowered.proxy.protocol.packet.config.ActiveFeaturesPacket; import com.velocitypowered.proxy.protocol.packet.config.ClientboundCustomReportDetailsPacket; import com.velocitypowered.proxy.protocol.packet.config.ClientboundServerLinksPacket; +import com.velocitypowered.proxy.protocol.packet.config.CodeOfConductAcceptPacket; +import com.velocitypowered.proxy.protocol.packet.config.CodeOfConductPacket; import com.velocitypowered.proxy.protocol.packet.config.FinishedUpdatePacket; import com.velocitypowered.proxy.protocol.packet.config.KnownPacksPacket; import com.velocitypowered.proxy.protocol.packet.config.RegistrySyncPacket; @@ -188,6 +191,10 @@ public enum StateRegistry { map(0x07, MINECRAFT_1_20_5, false)); serverbound.register(ServerboundCustomClickActionPacket.class, ServerboundCustomClickActionPacket::new, map(0x08, MINECRAFT_1_21_6, false)); + serverbound.register( + CodeOfConductAcceptPacket.class, + () -> CodeOfConductAcceptPacket.INSTANCE, + map(0x09, MINECRAFT_1_21_9, false)); clientbound.register( ClientboundCookieRequestPacket.class, ClientboundCookieRequestPacket::new, @@ -246,6 +253,8 @@ public enum StateRegistry { map(0x11, MINECRAFT_1_21_6, false)); clientbound.register(DialogShowPacket.class, () -> new DialogShowPacket(this), map(0x12, MINECRAFT_1_21_6, false)); + clientbound.register(CodeOfConductPacket.class, CodeOfConductPacket::new, + map(0x13, MINECRAFT_1_21_9, false)); } }, PLAY { @@ -474,7 +483,8 @@ public enum StateRegistry { map(0x1A, MINECRAFT_1_19_4, false), map(0x1B, MINECRAFT_1_20_2, false), map(0x1D, MINECRAFT_1_20_5, false), - map(0x1C, MINECRAFT_1_21_5, false)); + map(0x1C, MINECRAFT_1_21_5, false), + map(0x20, MINECRAFT_1_21_9, false)); clientbound.register( KeepAlivePacket.class, KeepAlivePacket::new, @@ -493,7 +503,8 @@ public enum StateRegistry { map(0x24, MINECRAFT_1_20_2, false), map(0x26, MINECRAFT_1_20_5, false), map(0x27, MINECRAFT_1_21_2, false), - map(0x26, MINECRAFT_1_21_5, false)); + map(0x26, MINECRAFT_1_21_5, false), + map(0x2B, MINECRAFT_1_21_9, false)); clientbound.register( JoinGamePacket.class, JoinGamePacket::new, @@ -512,7 +523,8 @@ public enum StateRegistry { map(0x29, MINECRAFT_1_20_2, false), map(0x2B, MINECRAFT_1_20_5, false), map(0x2C, MINECRAFT_1_21_2, false), - map(0x2B, MINECRAFT_1_21_5, false)); + map(0x2B, MINECRAFT_1_21_5, false), + map(0x30, MINECRAFT_1_21_9, false)); clientbound.register( RespawnPacket.class, RespawnPacket::new, @@ -534,14 +546,16 @@ public enum StateRegistry { map(0x45, MINECRAFT_1_20_3, true), map(0x47, MINECRAFT_1_20_5, true), map(0x4C, MINECRAFT_1_21_2, true), - map(0x4B, MINECRAFT_1_21_5, true)); + map(0x4B, MINECRAFT_1_21_5, true), + map(0x50, MINECRAFT_1_21_9, true)); clientbound.register( RemoveResourcePackPacket.class, RemoveResourcePackPacket::new, map(0x43, MINECRAFT_1_20_3, false), map(0x45, MINECRAFT_1_20_5, false), map(0x4A, MINECRAFT_1_21_2, false), - map(0x49, MINECRAFT_1_21_5, false)); + map(0x49, MINECRAFT_1_21_5, false), + map(0x4E, MINECRAFT_1_21_9, false)); clientbound.register( ResourcePackRequestPacket.class, ResourcePackRequestPacket::new, @@ -563,7 +577,8 @@ public enum StateRegistry { map(0x44, MINECRAFT_1_20_3, false), map(0x46, MINECRAFT_1_20_5, false), map(0x4B, MINECRAFT_1_21_2, false), - map(0x4A, MINECRAFT_1_21_5, false)); + map(0x4A, MINECRAFT_1_21_5, false), + map(0x4F, MINECRAFT_1_21_9, false)); clientbound.register( HeaderAndFooterPacket.class, HeaderAndFooterPacket::new, @@ -586,7 +601,8 @@ public enum StateRegistry { map(0x6A, MINECRAFT_1_20_3, true), map(0x6D, MINECRAFT_1_20_5, true), map(0x74, MINECRAFT_1_21_2, true), - map(0x73, MINECRAFT_1_21_5, true)); + map(0x73, MINECRAFT_1_21_5, true), + map(0x78, MINECRAFT_1_21_9, true)); clientbound.register( LegacyTitlePacket.class, LegacyTitlePacket::new, @@ -608,7 +624,8 @@ public enum StateRegistry { map(0x61, MINECRAFT_1_20_3, true), map(0x63, MINECRAFT_1_20_5, true), map(0x6A, MINECRAFT_1_21_2, true), - map(0x69, MINECRAFT_1_21_5, true)); + map(0x69, MINECRAFT_1_21_5, true), + map(0x6E, MINECRAFT_1_21_9, true)); clientbound.register( TitleTextPacket.class, TitleTextPacket::new, @@ -621,7 +638,8 @@ public enum StateRegistry { map(0x63, MINECRAFT_1_20_3, true), map(0x65, MINECRAFT_1_20_5, true), map(0x6C, MINECRAFT_1_21_2, true), - map(0x6B, MINECRAFT_1_21_5, true)); + map(0x6B, MINECRAFT_1_21_5, true), + map(0x70, MINECRAFT_1_21_9, true)); clientbound.register( TitleActionbarPacket.class, TitleActionbarPacket::new, @@ -634,7 +652,8 @@ public enum StateRegistry { map(0x4A, MINECRAFT_1_20_3, true), map(0x4C, MINECRAFT_1_20_5, true), map(0x51, MINECRAFT_1_21_2, true), - map(0x50, MINECRAFT_1_21_5, true)); + map(0x50, MINECRAFT_1_21_5, true), + map(0x55, MINECRAFT_1_21_9, true)); clientbound.register( TitleTimesPacket.class, TitleTimesPacket::new, @@ -647,7 +666,8 @@ public enum StateRegistry { map(0x64, MINECRAFT_1_20_3, true), map(0x66, MINECRAFT_1_20_5, true), map(0x6D, MINECRAFT_1_21_2, true), - map(0x6C, MINECRAFT_1_21_5, true)); + map(0x6C, MINECRAFT_1_21_5, true), + map(0x71, MINECRAFT_1_21_9, true)); clientbound.register( TitleClearPacket.class, TitleClearPacket::new, @@ -677,7 +697,8 @@ public enum StateRegistry { map(0x3B, MINECRAFT_1_20_2, false), map(0x3D, MINECRAFT_1_20_5, false), map(0x3F, MINECRAFT_1_21_2, false), - map(0x3E, MINECRAFT_1_21_5, false)); + map(0x3E, MINECRAFT_1_21_5, false), + map(0x43, MINECRAFT_1_21_9, false)); clientbound.register( UpsertPlayerInfoPacket.class, UpsertPlayerInfoPacket::new, @@ -686,12 +707,14 @@ public enum StateRegistry { map(0x3C, MINECRAFT_1_20_2, false), map(0x3E, MINECRAFT_1_20_5, false), map(0x40, MINECRAFT_1_21_2, false), - map(0x3F, MINECRAFT_1_21_5, false)); + map(0x3F, MINECRAFT_1_21_5, false), + map(0x44, MINECRAFT_1_21_9, 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(0x71, MINECRAFT_1_21_5, false), + map(0x76, MINECRAFT_1_21_9, false)); clientbound.register( SystemChatPacket.class, SystemChatPacket::new, @@ -703,7 +726,8 @@ public enum StateRegistry { map(0x69, MINECRAFT_1_20_3, true), map(0x6C, MINECRAFT_1_20_5, true), map(0x73, MINECRAFT_1_21_2, true), - map(0x72, MINECRAFT_1_21_5, true)); + map(0x72, MINECRAFT_1_21_5, true), + map(0x77, MINECRAFT_1_21_9, true)); clientbound.register( PlayerChatCompletionPacket.class, PlayerChatCompletionPacket::new, @@ -724,7 +748,8 @@ public enum StateRegistry { map(0x49, MINECRAFT_1_20_3, false), map(0x4B, MINECRAFT_1_20_5, false), map(0x50, MINECRAFT_1_21_2, false), - map(0x4F, MINECRAFT_1_21_5, false)); + map(0x4F, MINECRAFT_1_21_5, false), + map(0x54, MINECRAFT_1_21_9, false)); clientbound.register( StartUpdatePacket.class, () -> StartUpdatePacket.INSTANCE, @@ -732,7 +757,8 @@ public enum StateRegistry { map(0x67, MINECRAFT_1_20_3, false), map(0x69, MINECRAFT_1_20_5, false), map(0x70, MINECRAFT_1_21_2, false), - map(0x6F, MINECRAFT_1_21_5, false)); + map(0x6F, MINECRAFT_1_21_5, false), + map(0x74, MINECRAFT_1_21_9, false)); clientbound.register( BundleDelimiterPacket.class, () -> BundleDelimiterPacket.INSTANCE, @@ -741,17 +767,20 @@ public enum StateRegistry { TransferPacket.class, TransferPacket::new, map(0x73, MINECRAFT_1_20_5, false), - map(0x7A, MINECRAFT_1_21_2, false)); + map(0x7A, MINECRAFT_1_21_2, false), + map(0x7F, MINECRAFT_1_21_9, false)); clientbound.register( ClientboundCustomReportDetailsPacket.class, ClientboundCustomReportDetailsPacket::new, map(0x7A, MINECRAFT_1_21, false), - map(0x81, MINECRAFT_1_21_2, false)); + map(0x81, MINECRAFT_1_21_2, false), + map(0x86, MINECRAFT_1_21_9, false)); clientbound.register( ClientboundServerLinksPacket.class, ClientboundServerLinksPacket::new, map(0x7B, MINECRAFT_1_21, false), - map(0x82, MINECRAFT_1_21_2, false)); + map(0x82, MINECRAFT_1_21_2, false), + map(0x87, MINECRAFT_1_21_9, false)); } }, LOGIN { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/CodeOfConductAcceptPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/CodeOfConductAcceptPacket.java new file mode 100644 index 00000000..e9811f9f --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/CodeOfConductAcceptPacket.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2018-2025 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.config; + +import com.velocitypowered.api.network.ProtocolVersion; +import com.velocitypowered.proxy.connection.MinecraftSessionHandler; +import com.velocitypowered.proxy.protocol.MinecraftPacket; +import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction; +import io.netty.buffer.ByteBuf; + +public class CodeOfConductAcceptPacket implements MinecraftPacket { + + public static final CodeOfConductAcceptPacket INSTANCE = new CodeOfConductAcceptPacket(); + + private CodeOfConductAcceptPacket() { + } + + @Override + public void decode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) { + } + + @Override + public void encode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) { + } + + @Override + public boolean handle(MinecraftSessionHandler handler) { + return handler.handle(this); + } +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/CodeOfConductPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/CodeOfConductPacket.java new file mode 100644 index 00000000..44adb743 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/CodeOfConductPacket.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2018-2025 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.config; + +import com.velocitypowered.api.network.ProtocolVersion; +import com.velocitypowered.proxy.connection.MinecraftSessionHandler; +import com.velocitypowered.proxy.protocol.MinecraftPacket; +import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction; +import com.velocitypowered.proxy.protocol.util.DeferredByteBufHolder; +import io.netty.buffer.ByteBuf; + +public class CodeOfConductPacket extends DeferredByteBufHolder implements MinecraftPacket { + + public CodeOfConductPacket() { + super(null); + } + + @Override + public void decode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) { + this.replace(buf.readRetainedSlice(buf.readableBytes())); + } + + @Override + public void encode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) { + buf.writeBytes(this.content()); + } + + @Override + public boolean handle(MinecraftSessionHandler handler) { + return handler.handle(this); + } +}