diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolStates.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolStates.java new file mode 100644 index 000000000..9b1729508 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolStates.java @@ -0,0 +1,797 @@ +/* + * Copyright (C) 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; + +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_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_13; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_14; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_14_4; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_15; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_15_2; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_16; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_16_1; +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_17_1; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_18; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_18_2; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_19; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_19_1; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_19_3; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_19_4; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_20; +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_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; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_9_1; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_9_4; + +import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction; +import com.velocitypowered.proxy.protocol.packet.AvailableCommandsPacket; +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.ClientboundSoundEntityPacket; +import com.velocitypowered.proxy.protocol.packet.ClientboundStopSoundPacket; +import com.velocitypowered.proxy.protocol.packet.ClientboundStoreCookiePacket; +import com.velocitypowered.proxy.protocol.packet.DialogClearPacket; +import com.velocitypowered.proxy.protocol.packet.DialogShowPacket; +import com.velocitypowered.proxy.protocol.packet.DisconnectPacket; +import com.velocitypowered.proxy.protocol.packet.EncryptionRequestPacket; +import com.velocitypowered.proxy.protocol.packet.EncryptionResponsePacket; +import com.velocitypowered.proxy.protocol.packet.HandshakePacket; +import com.velocitypowered.proxy.protocol.packet.HeaderAndFooterPacket; +import com.velocitypowered.proxy.protocol.packet.JoinGamePacket; +import com.velocitypowered.proxy.protocol.packet.KeepAlivePacket; +import com.velocitypowered.proxy.protocol.packet.LegacyPlayerListItemPacket; +import com.velocitypowered.proxy.protocol.packet.LoginAcknowledgedPacket; +import com.velocitypowered.proxy.protocol.packet.LoginPluginMessagePacket; +import com.velocitypowered.proxy.protocol.packet.LoginPluginResponsePacket; +import com.velocitypowered.proxy.protocol.packet.PingIdentifyPacket; +import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket; +import com.velocitypowered.proxy.protocol.packet.RemovePlayerInfoPacket; +import com.velocitypowered.proxy.protocol.packet.RemoveResourcePackPacket; +import com.velocitypowered.proxy.protocol.packet.ResourcePackRequestPacket; +import com.velocitypowered.proxy.protocol.packet.ResourcePackResponsePacket; +import com.velocitypowered.proxy.protocol.packet.RespawnPacket; +import com.velocitypowered.proxy.protocol.packet.ServerDataPacket; +import com.velocitypowered.proxy.protocol.packet.ServerLoginPacket; +import com.velocitypowered.proxy.protocol.packet.ServerLoginSuccessPacket; +import com.velocitypowered.proxy.protocol.packet.ServerboundCookieResponsePacket; +import com.velocitypowered.proxy.protocol.packet.ServerboundCustomClickActionPacket; +import com.velocitypowered.proxy.protocol.packet.SetCompressionPacket; +import com.velocitypowered.proxy.protocol.packet.StatusPingPacket; +import com.velocitypowered.proxy.protocol.packet.StatusRequestPacket; +import com.velocitypowered.proxy.protocol.packet.StatusResponsePacket; +import com.velocitypowered.proxy.protocol.packet.TabCompleteRequestPacket; +import com.velocitypowered.proxy.protocol.packet.TabCompleteResponsePacket; +import com.velocitypowered.proxy.protocol.packet.TransferPacket; +import com.velocitypowered.proxy.protocol.packet.UpsertPlayerInfoPacket; +import com.velocitypowered.proxy.protocol.packet.chat.ChatAcknowledgementPacket; +import com.velocitypowered.proxy.protocol.packet.chat.PlayerChatCompletionPacket; +import com.velocitypowered.proxy.protocol.packet.chat.SystemChatPacket; +import com.velocitypowered.proxy.protocol.packet.chat.keyed.KeyedPlayerChatPacket; +import com.velocitypowered.proxy.protocol.packet.chat.keyed.KeyedPlayerCommandPacket; +import com.velocitypowered.proxy.protocol.packet.chat.legacy.LegacyChatPacket; +import com.velocitypowered.proxy.protocol.packet.chat.session.SessionPlayerChatPacket; +import com.velocitypowered.proxy.protocol.packet.chat.session.SessionPlayerCommandPacket; +import com.velocitypowered.proxy.protocol.packet.chat.session.UnsignedPlayerCommandPacket; +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; +import com.velocitypowered.proxy.protocol.packet.config.StartUpdatePacket; +import com.velocitypowered.proxy.protocol.packet.config.TagsUpdatePacket; +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 com.velocitypowered.proxy.protocol.registry.MultiVersionPacketRegistry; +import com.velocitypowered.proxy.protocol.registry.MultiVersionPacketRegistry.VersionRange; +import com.velocitypowered.proxy.protocol.registry.ProtocolToPacketRegistry; +import com.velocitypowered.proxy.protocol.registry.SimplePacketRegistry; + +/** + * Defines the packet mappings for all protocol states and versions supported by Velocity. + */ +public class ProtocolStates { + + public static final ProtocolToPacketRegistry HANDSHAKE_CLIENTBOUND; + public static final ProtocolToPacketRegistry HANDSHAKE_SERVERBOUND; + public static final ProtocolToPacketRegistry STATUS_SERVERBOUND; + public static final ProtocolToPacketRegistry STATUS_CLIENTBOUND; + public static final ProtocolToPacketRegistry CONFIG_SERVERBOUND; + public static final ProtocolToPacketRegistry CONFIG_CLIENTBOUND; + public static final ProtocolToPacketRegistry PLAY_SERVERBOUND; + public static final ProtocolToPacketRegistry PLAY_CLIENTBOUND; + public static final ProtocolToPacketRegistry LOGIN_SERVERBOUND; + public static final ProtocolToPacketRegistry LOGIN_CLIENTBOUND; + + static { + HANDSHAKE_CLIENTBOUND = new SimplePacketRegistry(Direction.CLIENTBOUND); + + SimplePacketRegistry handshakeServerbound = new SimplePacketRegistry(Direction.SERVERBOUND); + handshakeServerbound.register(0x00, HandshakePacket.class, HandshakePacket.Codec.INSTANCE); + HANDSHAKE_SERVERBOUND = handshakeServerbound; + + SimplePacketRegistry statusServerbound = new SimplePacketRegistry(Direction.SERVERBOUND); + statusServerbound.register(0x00, + StatusRequestPacket.class, StatusRequestPacket.Codec.INSTANCE); + statusServerbound.register(0x01, StatusPingPacket.class, StatusPingPacket.Codec.INSTANCE); + STATUS_SERVERBOUND = statusServerbound; + + SimplePacketRegistry statusClientbound = new SimplePacketRegistry(Direction.CLIENTBOUND); + statusClientbound.register(0x00, + StatusResponsePacket.class, StatusResponsePacket.Codec.INSTANCE); + statusClientbound.register(0x01, StatusPingPacket.class, StatusPingPacket.Codec.INSTANCE); + STATUS_CLIENTBOUND = statusClientbound; + + CONFIG_SERVERBOUND = MultiVersionPacketRegistry.builder(Direction.SERVERBOUND) + .register(ClientSettingsPacket.class, ClientSettingsPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_2, 0x00)) + .register(ServerboundCookieResponsePacket.class, + ServerboundCookieResponsePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_5, 0x01)) + .register(PluginMessagePacket.class, PluginMessagePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_3, 0x01), + VersionRange.of(MINECRAFT_1_20_5, 0x02)) + .register(FinishedUpdatePacket.class, FinishedUpdatePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_3, 0x02), + VersionRange.of(MINECRAFT_1_20_5, 0x03)) + .register(KeepAlivePacket.class, KeepAlivePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_3, 0x03), + VersionRange.of(MINECRAFT_1_20_5, 0x04)) + .register(PingIdentifyPacket.class, PingIdentifyPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_3, 0x04), + VersionRange.of(MINECRAFT_1_20_5, 0x05)) + .register(ResourcePackResponsePacket.class, ResourcePackResponsePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_3, 0x05), + VersionRange.of(MINECRAFT_1_20_5, 0x06)) + .register(KnownPacksPacket.class, KnownPacksPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_5, 0x07)) + .register(ServerboundCustomClickActionPacket.class, + ServerboundCustomClickActionPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_21_6, 0x08)) + .register(CodeOfConductAcceptPacket.class, CodeOfConductAcceptPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_21_9, 0x09)) + .build(); + + CONFIG_CLIENTBOUND = MultiVersionPacketRegistry.builder(Direction.CLIENTBOUND) + .register(ClientboundCookieRequestPacket.class, + ClientboundCookieRequestPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_5, 0x00)) + .register(PluginMessagePacket.class, PluginMessagePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_3, 0x00), + VersionRange.of(MINECRAFT_1_20_5, 0x01)) + .register(DisconnectPacket.class, new DisconnectPacket.Codec(StateRegistry.CONFIG), + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_3, 0x01), + VersionRange.of(MINECRAFT_1_20_5, 0x02)) + .register(FinishedUpdatePacket.class, FinishedUpdatePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_3, 0x02), + VersionRange.of(MINECRAFT_1_20_5, 0x03)) + .register(KeepAlivePacket.class, KeepAlivePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_3, 0x03), + VersionRange.of(MINECRAFT_1_20_5, 0x04)) + .register(PingIdentifyPacket.class, PingIdentifyPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_3, 0x04), + VersionRange.of(MINECRAFT_1_20_5, 0x05)) + .register(RegistrySyncPacket.class, RegistrySyncPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_3, 0x05), + VersionRange.of(MINECRAFT_1_20_5, 0x07)) + .register(RemoveResourcePackPacket.class, RemoveResourcePackPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_3, MINECRAFT_1_20_3, 0x06), + VersionRange.of(MINECRAFT_1_20_5, 0x08)) + .register(ResourcePackRequestPacket.class, ResourcePackRequestPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_2, 0x06), + VersionRange.of(MINECRAFT_1_20_3, MINECRAFT_1_20_3, 0x07), + VersionRange.of(MINECRAFT_1_20_5, 0x09)) + .register(ClientboundStoreCookiePacket.class, ClientboundStoreCookiePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_5, 0x0A)) + .register(TransferPacket.class, TransferPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_5, 0x0B)) + .register(ActiveFeaturesPacket.class, ActiveFeaturesPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_2, 0x07), + VersionRange.of(MINECRAFT_1_20_3, MINECRAFT_1_20_3, 0x08), + VersionRange.of(MINECRAFT_1_20_5, 0x0C)) + .register(TagsUpdatePacket.class, TagsUpdatePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_2, 0x08), + VersionRange.of(MINECRAFT_1_20_3, MINECRAFT_1_20_3, 0x09), + VersionRange.of(MINECRAFT_1_20_5, 0x0D)) + .register(KnownPacksPacket.class, KnownPacksPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_5, 0x0E)) + .register(ClientboundCustomReportDetailsPacket.class, + ClientboundCustomReportDetailsPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_21, 0x0F)) + .register(ClientboundServerLinksPacket.class, ClientboundServerLinksPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_21, 0x10)) + .register(DialogClearPacket.class, DialogClearPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_21_6, 0x11)) + .register(DialogShowPacket.class, new DialogShowPacket.Codec(StateRegistry.CONFIG), + VersionRange.of(MINECRAFT_1_21_6, 0x12)) + .register(CodeOfConductPacket.class, CodeOfConductPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_21_9, 0x13)) + .build(); + + LOGIN_SERVERBOUND = MultiVersionPacketRegistry.builder(Direction.SERVERBOUND) + .register(ServerLoginPacket.class, ServerLoginPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_7_2, 0x00)) + .register(EncryptionResponsePacket.class, EncryptionResponsePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_7_2, 0x01)) + .register(LoginPluginResponsePacket.class, LoginPluginResponsePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_13, 0x02)) + .register(LoginAcknowledgedPacket.class, LoginAcknowledgedPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_2, 0x03)) + .register(ServerboundCookieResponsePacket.class, + ServerboundCookieResponsePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_5, 0x04)) + .build(); + + LOGIN_CLIENTBOUND = MultiVersionPacketRegistry.builder(Direction.CLIENTBOUND) + .register(DisconnectPacket.class, new DisconnectPacket.Codec(StateRegistry.LOGIN), + VersionRange.of(MINECRAFT_1_7_2, 0x00)) + .register(EncryptionRequestPacket.class, EncryptionRequestPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_7_2, 0x01)) + .register(ServerLoginSuccessPacket.class, ServerLoginSuccessPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_7_2, 0x02)) + .register(SetCompressionPacket.class, SetCompressionPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_8, 0x03)) + .register(LoginPluginMessagePacket.class, LoginPluginMessagePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_13, 0x04)) + .register(ClientboundCookieRequestPacket.class, + ClientboundCookieRequestPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_5, 0x05)) + .build(); + + // PLAY state is much larger, will continue below + PLAY_SERVERBOUND = buildPlayServerbound(); + PLAY_CLIENTBOUND = buildPlayClientbound(); + } + + private static ProtocolToPacketRegistry buildPlayServerbound() { + return MultiVersionPacketRegistry.builder(Direction.SERVERBOUND) + .register(TabCompleteRequestPacket.class, TabCompleteRequestPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_7_2, MINECRAFT_1_8, 0x14), + VersionRange.of(MINECRAFT_1_9, MINECRAFT_1_11, 0x01), + VersionRange.of(MINECRAFT_1_12, MINECRAFT_1_12, 0x02), + VersionRange.of(MINECRAFT_1_12_1, MINECRAFT_1_12_1, 0x01), + VersionRange.of(MINECRAFT_1_13, MINECRAFT_1_13, 0x05), + VersionRange.of(MINECRAFT_1_14, MINECRAFT_1_18_2, 0x06), + VersionRange.of(MINECRAFT_1_19, MINECRAFT_1_19, 0x08), + VersionRange.of(MINECRAFT_1_19_1, MINECRAFT_1_19_1, 0x09), + VersionRange.of(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x08), + VersionRange.of(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x09), + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_3, 0x0A), + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x0B), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x0D), + VersionRange.of(MINECRAFT_1_21_6, 0x0E)) + .register(LegacyChatPacket.class, LegacyChatPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_7_2, MINECRAFT_1_8, 0x01), + VersionRange.of(MINECRAFT_1_9, MINECRAFT_1_11, 0x02), + VersionRange.of(MINECRAFT_1_12, MINECRAFT_1_12, 0x03), + VersionRange.of(MINECRAFT_1_12_1, MINECRAFT_1_13, 0x02), + VersionRange.of(MINECRAFT_1_14, MINECRAFT_1_18_2, 0x03)) + .register(ChatAcknowledgementPacket.class, ChatAcknowledgementPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_19_3, MINECRAFT_1_21, 0x03), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x04), + VersionRange.of(MINECRAFT_1_21_6, 0x05)) + .register(KeyedPlayerCommandPacket.class, KeyedPlayerCommandPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_19, MINECRAFT_1_19, 0x03), + VersionRange.of(MINECRAFT_1_19_1, MINECRAFT_1_19_1, 0x04)) + .register(KeyedPlayerChatPacket.class, KeyedPlayerChatPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_19, MINECRAFT_1_19, 0x04), + VersionRange.of(MINECRAFT_1_19_1, MINECRAFT_1_19_1, 0x05)) + .register(SessionPlayerCommandPacket.class, SessionPlayerCommandPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_19_3, MINECRAFT_1_20_3, 0x04), + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x05), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x06), + VersionRange.of(MINECRAFT_1_21_6, 0x07)) + .register(UnsignedPlayerCommandPacket.class, UnsignedPlayerCommandPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x04), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x05), + VersionRange.of(MINECRAFT_1_21_6, 0x06)) + .register(SessionPlayerChatPacket.class, SessionPlayerChatPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_19_3, MINECRAFT_1_20_3, 0x05), + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x06), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x07), + VersionRange.of(MINECRAFT_1_21_6, 0x08)) + .register(ClientSettingsPacket.class, ClientSettingsPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_7_2, MINECRAFT_1_8, 0x15), + VersionRange.of(MINECRAFT_1_9, MINECRAFT_1_11, 0x04), + VersionRange.of(MINECRAFT_1_12, MINECRAFT_1_12, 0x05), + VersionRange.of(MINECRAFT_1_12_1, MINECRAFT_1_13, 0x04), + VersionRange.of(MINECRAFT_1_14, MINECRAFT_1_18_2, 0x05), + VersionRange.of(MINECRAFT_1_19, MINECRAFT_1_19, 0x07), + VersionRange.of(MINECRAFT_1_19_1, MINECRAFT_1_19_1, 0x08), + VersionRange.of(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x07), + VersionRange.of(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x08), + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_3, 0x09), + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x0A), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x0C), + VersionRange.of(MINECRAFT_1_21_6, 0x0D)) + .register(ServerboundCookieResponsePacket.class, + ServerboundCookieResponsePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x11), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x13), + VersionRange.of(MINECRAFT_1_21_6, 0x14)) + .register(PluginMessagePacket.class, PluginMessagePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_7_2, MINECRAFT_1_8, 0x17), + VersionRange.of(MINECRAFT_1_9, MINECRAFT_1_11, 0x09), + VersionRange.of(MINECRAFT_1_12, MINECRAFT_1_12, 0x0A), + VersionRange.of(MINECRAFT_1_12_1, MINECRAFT_1_12_1, 0x09), + VersionRange.of(MINECRAFT_1_13, MINECRAFT_1_13, 0x0A), + VersionRange.of(MINECRAFT_1_14, MINECRAFT_1_16_4, 0x0B), + VersionRange.of(MINECRAFT_1_17, MINECRAFT_1_18_2, 0x0A), + VersionRange.of(MINECRAFT_1_19, MINECRAFT_1_19, 0x0C), + VersionRange.of(MINECRAFT_1_19_1, MINECRAFT_1_19_1, 0x0D), + VersionRange.of(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x0C), + VersionRange.of(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x0D), + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_2, 0x0F), + VersionRange.of(MINECRAFT_1_20_3, MINECRAFT_1_20_3, 0x10), + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x12), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x14), + VersionRange.of(MINECRAFT_1_21_6, 0x15)) + .register(KeepAlivePacket.class, KeepAlivePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_7_2, MINECRAFT_1_8, 0x00), + VersionRange.of(MINECRAFT_1_9, MINECRAFT_1_11, 0x0B), + VersionRange.of(MINECRAFT_1_12, MINECRAFT_1_12, 0x0C), + VersionRange.of(MINECRAFT_1_12_1, MINECRAFT_1_12_1, 0x0B), + VersionRange.of(MINECRAFT_1_13, MINECRAFT_1_13, 0x0E), + VersionRange.of(MINECRAFT_1_14, MINECRAFT_1_15_2, 0x0F), + VersionRange.of(MINECRAFT_1_16, MINECRAFT_1_16_4, 0x10), + VersionRange.of(MINECRAFT_1_17, MINECRAFT_1_18_2, 0x0F), + VersionRange.of(MINECRAFT_1_19, MINECRAFT_1_19, 0x11), + VersionRange.of(MINECRAFT_1_19_1, MINECRAFT_1_19_1, 0x12), + VersionRange.of(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x11), + VersionRange.of(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x12), + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_2, 0x14), + VersionRange.of(MINECRAFT_1_20_3, MINECRAFT_1_20_3, 0x15), + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x18), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x1A), + VersionRange.of(MINECRAFT_1_21_6, 0x1B)) + .register(ResourcePackResponsePacket.class, ResourcePackResponsePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_8, MINECRAFT_1_8, 0x19), + VersionRange.of(MINECRAFT_1_9, MINECRAFT_1_11, 0x16), + VersionRange.of(MINECRAFT_1_12, MINECRAFT_1_12, 0x18), + VersionRange.of(MINECRAFT_1_13, MINECRAFT_1_13, 0x1D), + VersionRange.of(MINECRAFT_1_14, MINECRAFT_1_15_2, 0x1F), + VersionRange.of(MINECRAFT_1_16, MINECRAFT_1_16_1, 0x20), + VersionRange.of(MINECRAFT_1_16_2, MINECRAFT_1_18_2, 0x21), + VersionRange.of(MINECRAFT_1_19, MINECRAFT_1_19, 0x23), + VersionRange.of(MINECRAFT_1_19_1, MINECRAFT_1_20, 0x24), + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_2, 0x27), + VersionRange.of(MINECRAFT_1_20_3, MINECRAFT_1_20_3, 0x28), + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x2B), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_2, 0x2D), + VersionRange.of(MINECRAFT_1_21_4, MINECRAFT_1_21_4, 0x2F), + VersionRange.of(MINECRAFT_1_21_6, 0x30)) + .register(FinishedUpdatePacket.class, FinishedUpdatePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_3, 0x0B), + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x0C), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x0E), + VersionRange.of(MINECRAFT_1_21_6, 0x0F)) + .build(); + } + + private static ProtocolToPacketRegistry buildPlayClientbound() { + return MultiVersionPacketRegistry.builder(Direction.CLIENTBOUND) + .register(BossBarPacket.class, BossBarPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_9, MINECRAFT_1_14, 0x0C), + VersionRange.of(MINECRAFT_1_15, MINECRAFT_1_15_2, 0x0D), + VersionRange.of(MINECRAFT_1_16, MINECRAFT_1_16_4, 0x0C), + VersionRange.of(MINECRAFT_1_17, MINECRAFT_1_18_2, 0x0D), + VersionRange.of(MINECRAFT_1_19, MINECRAFT_1_19_3, 0x0A), + VersionRange.of(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x0B), + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_21_4, 0x0A), + VersionRange.of(MINECRAFT_1_21_5, 0x09)) + .register(LegacyChatPacket.class, LegacyChatPacket.Codec.INSTANCE, + VersionRange.encodeOnly(MINECRAFT_1_7_2, MINECRAFT_1_8, 0x02), + VersionRange.encodeOnly(MINECRAFT_1_9, MINECRAFT_1_12, 0x0F), + VersionRange.encodeOnly(MINECRAFT_1_13, MINECRAFT_1_13, 0x0E), + VersionRange.encodeOnly(MINECRAFT_1_15, MINECRAFT_1_15_2, 0x0F), + VersionRange.encodeOnly(MINECRAFT_1_16, MINECRAFT_1_16_4, 0x0E), + VersionRange.encodeOnly(MINECRAFT_1_17, MINECRAFT_1_18_2, 0x0F)) + .register(TabCompleteResponsePacket.class, TabCompleteResponsePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_7_2, MINECRAFT_1_8, 0x3A), + VersionRange.of(MINECRAFT_1_9, MINECRAFT_1_12, 0x0E), + VersionRange.of(MINECRAFT_1_13, MINECRAFT_1_14, 0x10), + VersionRange.of(MINECRAFT_1_15, MINECRAFT_1_15_2, 0x11), + VersionRange.of(MINECRAFT_1_16, MINECRAFT_1_16_1, 0x10), + VersionRange.of(MINECRAFT_1_16_2, MINECRAFT_1_16_4, 0x0F), + VersionRange.of(MINECRAFT_1_17, MINECRAFT_1_18_2, 0x11), + VersionRange.of(MINECRAFT_1_19, MINECRAFT_1_19_1, 0x0E), + VersionRange.of(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x0D), + VersionRange.of(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x0F), + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_21_4, 0x10), + VersionRange.of(MINECRAFT_1_21_5, 0x0F)) + .register(AvailableCommandsPacket.class, AvailableCommandsPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_13, MINECRAFT_1_14, 0x11), + VersionRange.of(MINECRAFT_1_15, MINECRAFT_1_15_2, 0x12), + VersionRange.of(MINECRAFT_1_16, MINECRAFT_1_16_1, 0x11), + VersionRange.of(MINECRAFT_1_16_2, MINECRAFT_1_16_4, 0x10), + VersionRange.of(MINECRAFT_1_17, MINECRAFT_1_18_2, 0x12), + VersionRange.of(MINECRAFT_1_19, MINECRAFT_1_19_1, 0x0F), + VersionRange.of(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x0E), + VersionRange.of(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x10), + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_21_4, 0x11), + VersionRange.of(MINECRAFT_1_21_5, 0x10)) + .register(ClientboundCookieRequestPacket.class, + ClientboundCookieRequestPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21_4, 0x16), + VersionRange.of(MINECRAFT_1_21_5, 0x15)) + .register(ClientboundSoundEntityPacket.class, ClientboundSoundEntityPacket.Codec.INSTANCE, + VersionRange.encodeOnly(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x5D), + VersionRange.encodeOnly(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x61), + VersionRange.encodeOnly(MINECRAFT_1_20_2, MINECRAFT_1_20_2, 0x63), + VersionRange.encodeOnly(MINECRAFT_1_20_3, MINECRAFT_1_20_3, 0x65), + VersionRange.encodeOnly(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x67), + VersionRange.encodeOnly(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x6E), + VersionRange.encodeOnly(MINECRAFT_1_21_5, MINECRAFT_1_21_6, 0x6D), + VersionRange.encodeOnly(MINECRAFT_1_21_9, 0x72)) + .register(ClientboundStopSoundPacket.class, ClientboundStopSoundPacket.Codec.INSTANCE, + VersionRange.encodeOnly(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x5F), + VersionRange.encodeOnly(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x63), + VersionRange.encodeOnly(MINECRAFT_1_20_2, MINECRAFT_1_20_2, 0x66), + VersionRange.encodeOnly(MINECRAFT_1_20_3, MINECRAFT_1_20_3, 0x68), + VersionRange.encodeOnly(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x6A), + VersionRange.encodeOnly(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x71), + VersionRange.encodeOnly(MINECRAFT_1_21_5, MINECRAFT_1_21_6, 0x70), + VersionRange.encodeOnly(MINECRAFT_1_21_9, 0x75)) + .register(PluginMessagePacket.class, PluginMessagePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_7_2, MINECRAFT_1_8, 0x3F), + VersionRange.of(MINECRAFT_1_9, MINECRAFT_1_12, 0x18), + VersionRange.of(MINECRAFT_1_13, MINECRAFT_1_13, 0x19), + VersionRange.of(MINECRAFT_1_14, MINECRAFT_1_14, 0x18), + VersionRange.of(MINECRAFT_1_15, MINECRAFT_1_15_2, 0x19), + VersionRange.of(MINECRAFT_1_16, MINECRAFT_1_16_1, 0x18), + VersionRange.of(MINECRAFT_1_16_2, MINECRAFT_1_16_4, 0x17), + VersionRange.of(MINECRAFT_1_17, MINECRAFT_1_18_2, 0x18), + VersionRange.of(MINECRAFT_1_19, MINECRAFT_1_19, 0x15), + VersionRange.of(MINECRAFT_1_19_1, MINECRAFT_1_19_1, 0x16), + VersionRange.of(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x15), + VersionRange.of(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x17), + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_3, 0x18), + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21_4, 0x19), + VersionRange.of(MINECRAFT_1_21_5, 0x18)) + .register(DisconnectPacket.class, new DisconnectPacket.Codec(StateRegistry.PLAY), + VersionRange.of(MINECRAFT_1_7_2, MINECRAFT_1_8, 0x40), + VersionRange.of(MINECRAFT_1_9, MINECRAFT_1_12, 0x1A), + VersionRange.of(MINECRAFT_1_13, MINECRAFT_1_13, 0x1B), + VersionRange.of(MINECRAFT_1_14, MINECRAFT_1_14, 0x1A), + VersionRange.of(MINECRAFT_1_15, MINECRAFT_1_15_2, 0x1B), + VersionRange.of(MINECRAFT_1_16, MINECRAFT_1_16_1, 0x1A), + VersionRange.of(MINECRAFT_1_16_2, MINECRAFT_1_16_4, 0x19), + VersionRange.of(MINECRAFT_1_17, MINECRAFT_1_18_2, 0x1A), + VersionRange.of(MINECRAFT_1_19, MINECRAFT_1_19, 0x17), + VersionRange.of(MINECRAFT_1_19_1, MINECRAFT_1_19_1, 0x19), + VersionRange.of(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x17), + VersionRange.of(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x1A), + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_3, 0x1B), + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21_4, 0x1D), + VersionRange.of(MINECRAFT_1_21_5, MINECRAFT_1_21_6, 0x1C), + VersionRange.of(MINECRAFT_1_21_9, 0x20)) + .register(KeepAlivePacket.class, KeepAlivePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_7_2, MINECRAFT_1_8, 0x00), + VersionRange.of(MINECRAFT_1_9, MINECRAFT_1_12, 0x1F), + VersionRange.of(MINECRAFT_1_13, MINECRAFT_1_13, 0x21), + VersionRange.of(MINECRAFT_1_14, MINECRAFT_1_14_4, 0x20), + VersionRange.of(MINECRAFT_1_15, MINECRAFT_1_15_2, 0x21), + VersionRange.of(MINECRAFT_1_16, MINECRAFT_1_16_1, 0x20), + VersionRange.of(MINECRAFT_1_16_2, MINECRAFT_1_16_4, 0x1F), + VersionRange.of(MINECRAFT_1_17, MINECRAFT_1_18_2, 0x21), + VersionRange.of(MINECRAFT_1_19, MINECRAFT_1_19, 0x1E), + VersionRange.of(MINECRAFT_1_19_1, MINECRAFT_1_19_1, 0x20), + VersionRange.of(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x1F), + VersionRange.of(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x23), + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_3, 0x24), + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x26), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x27), + VersionRange.of(MINECRAFT_1_21_5, MINECRAFT_1_21_6, 0x26), + VersionRange.of(MINECRAFT_1_21_9, 0x2B)) + .register(JoinGamePacket.class, JoinGamePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_7_2, MINECRAFT_1_8, 0x01), + VersionRange.of(MINECRAFT_1_9, MINECRAFT_1_12, 0x23), + VersionRange.of(MINECRAFT_1_13, MINECRAFT_1_14, 0x25), + VersionRange.of(MINECRAFT_1_15, MINECRAFT_1_15_2, 0x26), + VersionRange.of(MINECRAFT_1_16, MINECRAFT_1_16_1, 0x25), + VersionRange.of(MINECRAFT_1_16_2, MINECRAFT_1_16_4, 0x24), + VersionRange.of(MINECRAFT_1_17, MINECRAFT_1_18_2, 0x26), + VersionRange.of(MINECRAFT_1_19, MINECRAFT_1_19, 0x23), + VersionRange.of(MINECRAFT_1_19_1, MINECRAFT_1_19_1, 0x25), + VersionRange.of(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x24), + VersionRange.of(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x28), + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_3, 0x29), + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x2B), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x2C), + VersionRange.of(MINECRAFT_1_21_5, MINECRAFT_1_21_6, 0x2B), + VersionRange.of(MINECRAFT_1_21_9, 0x30)) + .register(RespawnPacket.class, RespawnPacket.Codec.INSTANCE, + VersionRange.encodeOnly(MINECRAFT_1_7_2, MINECRAFT_1_8, 0x07), + VersionRange.encodeOnly(MINECRAFT_1_9, MINECRAFT_1_11, 0x33), + VersionRange.encodeOnly(MINECRAFT_1_12, MINECRAFT_1_12, 0x34), + VersionRange.encodeOnly(MINECRAFT_1_12_1, MINECRAFT_1_12_1, 0x35), + VersionRange.encodeOnly(MINECRAFT_1_13, MINECRAFT_1_13, 0x38), + VersionRange.encodeOnly(MINECRAFT_1_14, MINECRAFT_1_14, 0x3A), + VersionRange.encodeOnly(MINECRAFT_1_15, MINECRAFT_1_15_2, 0x3B), + VersionRange.encodeOnly(MINECRAFT_1_16, MINECRAFT_1_16_1, 0x3A), + VersionRange.encodeOnly(MINECRAFT_1_16_2, MINECRAFT_1_16_4, 0x39), + VersionRange.encodeOnly(MINECRAFT_1_17, MINECRAFT_1_18_2, 0x3D), + VersionRange.encodeOnly(MINECRAFT_1_19, MINECRAFT_1_19, 0x3B), + VersionRange.encodeOnly(MINECRAFT_1_19_1, MINECRAFT_1_19_1, 0x3E), + VersionRange.encodeOnly(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x3D), + VersionRange.encodeOnly(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x41), + VersionRange.encodeOnly(MINECRAFT_1_20_2, MINECRAFT_1_20_2, 0x43), + VersionRange.encodeOnly(MINECRAFT_1_20_3, MINECRAFT_1_20_3, 0x45), + VersionRange.encodeOnly(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x47), + VersionRange.encodeOnly(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x4C), + VersionRange.encodeOnly(MINECRAFT_1_21_5, MINECRAFT_1_21_6, 0x4B), + VersionRange.encodeOnly(MINECRAFT_1_21_9, 0x50)) + .register(RemoveResourcePackPacket.class, RemoveResourcePackPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_3, MINECRAFT_1_20_3, 0x43), + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x45), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x4A), + VersionRange.of(MINECRAFT_1_21_5, MINECRAFT_1_21_6, 0x49), + VersionRange.of(MINECRAFT_1_21_9, 0x4E)) + .register(ResourcePackRequestPacket.class, ResourcePackRequestPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_8, MINECRAFT_1_8, 0x48), + VersionRange.of(MINECRAFT_1_9, MINECRAFT_1_11, 0x32), + VersionRange.of(MINECRAFT_1_12, MINECRAFT_1_12, 0x33), + VersionRange.of(MINECRAFT_1_12_1, MINECRAFT_1_12_1, 0x34), + VersionRange.of(MINECRAFT_1_13, MINECRAFT_1_13, 0x37), + VersionRange.of(MINECRAFT_1_14, MINECRAFT_1_14, 0x39), + VersionRange.of(MINECRAFT_1_15, MINECRAFT_1_15_2, 0x3A), + VersionRange.of(MINECRAFT_1_16, MINECRAFT_1_16_1, 0x39), + VersionRange.of(MINECRAFT_1_16_2, MINECRAFT_1_16_4, 0x38), + VersionRange.of(MINECRAFT_1_17, MINECRAFT_1_18_2, 0x3C), + VersionRange.of(MINECRAFT_1_19, MINECRAFT_1_19, 0x3A), + VersionRange.of(MINECRAFT_1_19_1, MINECRAFT_1_19_1, 0x3D), + VersionRange.of(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x3C), + VersionRange.of(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x40), + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_2, 0x42), + VersionRange.of(MINECRAFT_1_20_3, MINECRAFT_1_20_3, 0x44), + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x46), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x4B), + VersionRange.of(MINECRAFT_1_21_5, MINECRAFT_1_21_6, 0x4A), + VersionRange.of(MINECRAFT_1_21_9, 0x4F)) + .register(HeaderAndFooterPacket.class, HeaderAndFooterPacket.Codec.INSTANCE, + VersionRange.encodeOnly(MINECRAFT_1_8, MINECRAFT_1_8, 0x47), + VersionRange.encodeOnly(MINECRAFT_1_9, MINECRAFT_1_9_1, 0x48), + VersionRange.encodeOnly(MINECRAFT_1_9_4, MINECRAFT_1_11, 0x47), + VersionRange.encodeOnly(MINECRAFT_1_12, MINECRAFT_1_12, 0x49), + VersionRange.encodeOnly(MINECRAFT_1_12_1, MINECRAFT_1_12_1, 0x4A), + VersionRange.encodeOnly(MINECRAFT_1_13, MINECRAFT_1_13, 0x4E), + VersionRange.encodeOnly(MINECRAFT_1_14, MINECRAFT_1_14, 0x53), + VersionRange.encodeOnly(MINECRAFT_1_15, MINECRAFT_1_15_2, 0x54), + VersionRange.encodeOnly(MINECRAFT_1_16, MINECRAFT_1_16_4, 0x53), + VersionRange.encodeOnly(MINECRAFT_1_17, MINECRAFT_1_17_1, 0x5E), + VersionRange.encodeOnly(MINECRAFT_1_18, MINECRAFT_1_18_2, 0x5F), + VersionRange.encodeOnly(MINECRAFT_1_19, MINECRAFT_1_19, 0x60), + VersionRange.encodeOnly(MINECRAFT_1_19_1, MINECRAFT_1_19_1, 0x63), + VersionRange.encodeOnly(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x61), + VersionRange.encodeOnly(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x65), + VersionRange.encodeOnly(MINECRAFT_1_20_2, MINECRAFT_1_20_2, 0x68), + VersionRange.encodeOnly(MINECRAFT_1_20_3, MINECRAFT_1_20_3, 0x6A), + VersionRange.encodeOnly(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x6D), + VersionRange.encodeOnly(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x74), + VersionRange.encodeOnly(MINECRAFT_1_21_5, MINECRAFT_1_21_6, 0x73), + VersionRange.encodeOnly(MINECRAFT_1_21_9, 0x78)) + .register(LegacyTitlePacket.class, LegacyTitlePacket.Codec.INSTANCE, + VersionRange.encodeOnly(MINECRAFT_1_8, MINECRAFT_1_11, 0x45), + VersionRange.encodeOnly(MINECRAFT_1_12, MINECRAFT_1_12, 0x47), + VersionRange.encodeOnly(MINECRAFT_1_12_1, MINECRAFT_1_12_1, 0x48), + VersionRange.encodeOnly(MINECRAFT_1_13, MINECRAFT_1_13, 0x4B), + VersionRange.encodeOnly(MINECRAFT_1_14, MINECRAFT_1_14_4, 0x4F), + VersionRange.encodeOnly(MINECRAFT_1_15, MINECRAFT_1_15_2, 0x50), + VersionRange.encodeOnly(MINECRAFT_1_16, MINECRAFT_1_16_4, 0x4F)) + .register(TitleSubtitlePacket.class, TitleSubtitlePacket.Codec.INSTANCE, + VersionRange.encodeOnly(MINECRAFT_1_17, MINECRAFT_1_17_1, 0x57), + VersionRange.encodeOnly(MINECRAFT_1_18, MINECRAFT_1_18_2, 0x58), + VersionRange.encodeOnly(MINECRAFT_1_19_1, MINECRAFT_1_19_1, 0x5B), + VersionRange.encodeOnly(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x59), + VersionRange.encodeOnly(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x5D), + VersionRange.encodeOnly(MINECRAFT_1_20_2, MINECRAFT_1_20_2, 0x5F), + VersionRange.encodeOnly(MINECRAFT_1_20_3, MINECRAFT_1_20_3, 0x61), + VersionRange.encodeOnly(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x63), + VersionRange.encodeOnly(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x6A), + VersionRange.encodeOnly(MINECRAFT_1_21_5, MINECRAFT_1_21_6, 0x69), + VersionRange.encodeOnly(MINECRAFT_1_21_9, 0x6E)) + .register(TitleTextPacket.class, TitleTextPacket.Codec.INSTANCE, + VersionRange.encodeOnly(MINECRAFT_1_17, MINECRAFT_1_17_1, 0x59), + VersionRange.encodeOnly(MINECRAFT_1_18, MINECRAFT_1_18_2, 0x5A), + VersionRange.encodeOnly(MINECRAFT_1_19_1, MINECRAFT_1_19_1, 0x5D), + VersionRange.encodeOnly(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x5B), + VersionRange.encodeOnly(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x5F), + VersionRange.encodeOnly(MINECRAFT_1_20_2, MINECRAFT_1_20_2, 0x61), + VersionRange.encodeOnly(MINECRAFT_1_20_3, MINECRAFT_1_20_3, 0x63), + VersionRange.encodeOnly(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x65), + VersionRange.encodeOnly(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x6C), + VersionRange.encodeOnly(MINECRAFT_1_21_5, MINECRAFT_1_21_6, 0x6B), + VersionRange.encodeOnly(MINECRAFT_1_21_9, 0x70)) + .register(TitleActionbarPacket.class, TitleActionbarPacket.Codec.INSTANCE, + VersionRange.encodeOnly(MINECRAFT_1_17, MINECRAFT_1_18_2, 0x41), + VersionRange.encodeOnly(MINECRAFT_1_19, MINECRAFT_1_19, 0x40), + VersionRange.encodeOnly(MINECRAFT_1_19_1, MINECRAFT_1_19_1, 0x43), + VersionRange.encodeOnly(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x42), + VersionRange.encodeOnly(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x46), + VersionRange.encodeOnly(MINECRAFT_1_20_2, MINECRAFT_1_20_2, 0x48), + VersionRange.encodeOnly(MINECRAFT_1_20_3, MINECRAFT_1_20_3, 0x4A), + VersionRange.encodeOnly(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x4C), + VersionRange.encodeOnly(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x51), + VersionRange.encodeOnly(MINECRAFT_1_21_5, MINECRAFT_1_21_6, 0x50), + VersionRange.encodeOnly(MINECRAFT_1_21_9, 0x55)) + .register(TitleTimesPacket.class, TitleTimesPacket.Codec.INSTANCE, + VersionRange.encodeOnly(MINECRAFT_1_17, MINECRAFT_1_17_1, 0x5A), + VersionRange.encodeOnly(MINECRAFT_1_18, MINECRAFT_1_18_2, 0x5B), + VersionRange.encodeOnly(MINECRAFT_1_19_1, MINECRAFT_1_19_1, 0x5E), + VersionRange.encodeOnly(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x5C), + VersionRange.encodeOnly(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x60), + VersionRange.encodeOnly(MINECRAFT_1_20_2, MINECRAFT_1_20_2, 0x62), + VersionRange.encodeOnly(MINECRAFT_1_20_3, MINECRAFT_1_20_3, 0x64), + VersionRange.encodeOnly(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x66), + VersionRange.encodeOnly(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x6D), + VersionRange.encodeOnly(MINECRAFT_1_21_5, MINECRAFT_1_21_6, 0x6C), + VersionRange.encodeOnly(MINECRAFT_1_21_9, 0x71)) + .register(TitleClearPacket.class, TitleClearPacket.Codec.INSTANCE, + VersionRange.encodeOnly(MINECRAFT_1_17, MINECRAFT_1_18_2, 0x10), + VersionRange.encodeOnly(MINECRAFT_1_19, MINECRAFT_1_19_1, 0x0D), + VersionRange.encodeOnly(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x0C), + VersionRange.encodeOnly(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x0E), + VersionRange.encodeOnly(MINECRAFT_1_20_2, MINECRAFT_1_21_4, 0x0F), + VersionRange.encodeOnly(MINECRAFT_1_21_5, 0x0E)) + .register(LegacyPlayerListItemPacket.class, LegacyPlayerListItemPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_7_2, MINECRAFT_1_8, 0x38), + VersionRange.of(MINECRAFT_1_9, MINECRAFT_1_12, 0x2D), + VersionRange.of(MINECRAFT_1_12_1, MINECRAFT_1_12_1, 0x2E), + VersionRange.of(MINECRAFT_1_13, MINECRAFT_1_13, 0x30), + VersionRange.of(MINECRAFT_1_14, MINECRAFT_1_14, 0x33), + VersionRange.of(MINECRAFT_1_15, MINECRAFT_1_15_2, 0x34), + VersionRange.of(MINECRAFT_1_16, MINECRAFT_1_16_1, 0x33), + VersionRange.of(MINECRAFT_1_16_2, MINECRAFT_1_16_4, 0x32), + VersionRange.of(MINECRAFT_1_17, MINECRAFT_1_18_2, 0x36), + VersionRange.of(MINECRAFT_1_19, MINECRAFT_1_19, 0x34), + VersionRange.of(MINECRAFT_1_19_1, MINECRAFT_1_19_1, 0x37)) + .register(RemovePlayerInfoPacket.class, RemovePlayerInfoPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x35), + VersionRange.of(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x39), + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_3, 0x3B), + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x3D), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x3F), + VersionRange.of(MINECRAFT_1_21_5, MINECRAFT_1_21_6, 0x3E), + VersionRange.of(MINECRAFT_1_21_9, 0x43)) + .register(UpsertPlayerInfoPacket.class, UpsertPlayerInfoPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x36), + VersionRange.of(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x3A), + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_3, 0x3C), + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x3E), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x40), + VersionRange.of(MINECRAFT_1_21_5, MINECRAFT_1_21_6, 0x3F), + VersionRange.of(MINECRAFT_1_21_9, 0x44)) + .register(ClientboundStoreCookiePacket.class, ClientboundStoreCookiePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x6B), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x72), + VersionRange.of(MINECRAFT_1_21_5, MINECRAFT_1_21_6, 0x71), + VersionRange.of(MINECRAFT_1_21_9, 0x76)) + .register(SystemChatPacket.class, SystemChatPacket.Codec.INSTANCE, + VersionRange.encodeOnly(MINECRAFT_1_19, MINECRAFT_1_19, 0x5F), + VersionRange.encodeOnly(MINECRAFT_1_19_1, MINECRAFT_1_19_1, 0x62), + VersionRange.encodeOnly(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x60), + VersionRange.encodeOnly(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x64), + VersionRange.encodeOnly(MINECRAFT_1_20_2, MINECRAFT_1_20_2, 0x67), + VersionRange.encodeOnly(MINECRAFT_1_20_3, MINECRAFT_1_20_3, 0x69), + VersionRange.encodeOnly(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x6C), + VersionRange.encodeOnly(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x73), + VersionRange.encodeOnly(MINECRAFT_1_21_5, MINECRAFT_1_21_6, 0x72), + VersionRange.encodeOnly(MINECRAFT_1_21_9, 0x77)) + .register(PlayerChatCompletionPacket.class, PlayerChatCompletionPacket.Codec.INSTANCE, + VersionRange.encodeOnly(MINECRAFT_1_19_1, MINECRAFT_1_19_1, 0x15), + VersionRange.encodeOnly(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x14), + VersionRange.encodeOnly(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x16), + VersionRange.encodeOnly(MINECRAFT_1_20_2, MINECRAFT_1_20_3, 0x17), + VersionRange.encodeOnly(MINECRAFT_1_20_5, MINECRAFT_1_21_4, 0x18), + VersionRange.encodeOnly(MINECRAFT_1_21_5, 0x17)) + .register(ServerDataPacket.class, ServerDataPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_19, MINECRAFT_1_19, 0x3F), + VersionRange.of(MINECRAFT_1_19_1, MINECRAFT_1_19_1, 0x42), + VersionRange.of(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x41), + VersionRange.of(MINECRAFT_1_19_4, MINECRAFT_1_20, 0x45), + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_2, 0x47), + VersionRange.of(MINECRAFT_1_20_3, MINECRAFT_1_20_3, 0x49), + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x4B), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x50), + VersionRange.of(MINECRAFT_1_21_5, MINECRAFT_1_21_6, 0x4F), + VersionRange.of(MINECRAFT_1_21_9, 0x54)) + .register(StartUpdatePacket.class, StartUpdatePacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_2, MINECRAFT_1_20_2, 0x65), + VersionRange.of(MINECRAFT_1_20_3, MINECRAFT_1_20_3, 0x67), + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x69), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_4, 0x70), + VersionRange.of(MINECRAFT_1_21_5, MINECRAFT_1_21_6, 0x6F), + VersionRange.of(MINECRAFT_1_21_9, 0x74)) + .register(BundleDelimiterPacket.class, BundleDelimiterPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_19_4, 0x00)) + .register(TransferPacket.class, TransferPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_20_5, MINECRAFT_1_21, 0x73), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_6, 0x7A), + VersionRange.of(MINECRAFT_1_21_9, 0x7F)) + .register(ClientboundCustomReportDetailsPacket.class, + ClientboundCustomReportDetailsPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_21, MINECRAFT_1_21, 0x7A), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_6, 0x81), + VersionRange.of(MINECRAFT_1_21_9, 0x86)) + .register(ClientboundServerLinksPacket.class, ClientboundServerLinksPacket.Codec.INSTANCE, + VersionRange.of(MINECRAFT_1_21, MINECRAFT_1_21, 0x7B), + VersionRange.of(MINECRAFT_1_21_2, MINECRAFT_1_21_6, 0x82), + VersionRange.of(MINECRAFT_1_21_9, 0x87)) + .build(); + } + + public static ProtocolToPacketRegistry handshake(Direction direction) { + return direction == Direction.SERVERBOUND ? HANDSHAKE_SERVERBOUND : HANDSHAKE_CLIENTBOUND; + } + + public static ProtocolToPacketRegistry status(Direction direction) { + return direction == Direction.SERVERBOUND ? STATUS_SERVERBOUND : STATUS_CLIENTBOUND; + } + + public static ProtocolToPacketRegistry login(Direction direction) { + return direction == Direction.SERVERBOUND ? LOGIN_SERVERBOUND : LOGIN_CLIENTBOUND; + } + + public static ProtocolToPacketRegistry configuration(Direction direction) { + return direction == Direction.SERVERBOUND ? CONFIG_SERVERBOUND : CONFIG_CLIENTBOUND; + } + + public static ProtocolToPacketRegistry play(Direction direction) { + return direction == Direction.SERVERBOUND ? PLAY_SERVERBOUND : PLAY_CLIENTBOUND; + } + + /** + * Looks up the packet registry for the specified state and direction. + * + * @param registry the protocol state + * @param direction the packet direction + * @return the packet registry for the specified state and direction + */ + public static ProtocolToPacketRegistry lookup(StateRegistry registry, Direction direction) { + return switch (registry) { + case HANDSHAKE -> handshake(direction); + case STATUS -> status(direction); + case LOGIN -> login(direction); + case CONFIG -> configuration(direction); + case PLAY -> play(direction); + }; + } +} 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 d4bd8dbc9..50eaa7c04 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java @@ -17,844 +17,23 @@ package com.velocitypowered.proxy.protocol; -import static com.google.common.collect.Iterables.getLast; -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_13; -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_18; -import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_18_2; -import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_19; -import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_19_1; -import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_19_3; -import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_19_4; -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_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; -import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_9_4; -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; -import static com.velocitypowered.proxy.protocol.ProtocolUtils.Direction.CLIENTBOUND; -import static com.velocitypowered.proxy.protocol.ProtocolUtils.Direction.SERVERBOUND; import com.velocitypowered.api.network.ProtocolState; -import com.velocitypowered.api.network.ProtocolVersion; -import com.velocitypowered.proxy.protocol.packet.AvailableCommandsPacket; -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.ClientboundSoundEntityPacket; -import com.velocitypowered.proxy.protocol.packet.ClientboundStopSoundPacket; -import com.velocitypowered.proxy.protocol.packet.ClientboundStoreCookiePacket; -import com.velocitypowered.proxy.protocol.packet.DialogClearPacket; -import com.velocitypowered.proxy.protocol.packet.DialogShowPacket; -import com.velocitypowered.proxy.protocol.packet.DisconnectPacket; -import com.velocitypowered.proxy.protocol.packet.EncryptionRequestPacket; -import com.velocitypowered.proxy.protocol.packet.EncryptionResponsePacket; -import com.velocitypowered.proxy.protocol.packet.HandshakePacket; -import com.velocitypowered.proxy.protocol.packet.HeaderAndFooterPacket; -import com.velocitypowered.proxy.protocol.packet.JoinGamePacket; -import com.velocitypowered.proxy.protocol.packet.KeepAlivePacket; -import com.velocitypowered.proxy.protocol.packet.LegacyPlayerListItemPacket; -import com.velocitypowered.proxy.protocol.packet.LoginAcknowledgedPacket; -import com.velocitypowered.proxy.protocol.packet.LoginPluginMessagePacket; -import com.velocitypowered.proxy.protocol.packet.LoginPluginResponsePacket; -import com.velocitypowered.proxy.protocol.packet.PingIdentifyPacket; -import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket; -import com.velocitypowered.proxy.protocol.packet.RemovePlayerInfoPacket; -import com.velocitypowered.proxy.protocol.packet.RemoveResourcePackPacket; -import com.velocitypowered.proxy.protocol.packet.ResourcePackRequestPacket; -import com.velocitypowered.proxy.protocol.packet.ResourcePackResponsePacket; -import com.velocitypowered.proxy.protocol.packet.RespawnPacket; -import com.velocitypowered.proxy.protocol.packet.ServerDataPacket; -import com.velocitypowered.proxy.protocol.packet.ServerLoginPacket; -import com.velocitypowered.proxy.protocol.packet.ServerLoginSuccessPacket; -import com.velocitypowered.proxy.protocol.packet.ServerboundCookieResponsePacket; -import com.velocitypowered.proxy.protocol.packet.ServerboundCustomClickActionPacket; -import com.velocitypowered.proxy.protocol.packet.SetCompressionPacket; -import com.velocitypowered.proxy.protocol.packet.StatusPingPacket; -import com.velocitypowered.proxy.protocol.packet.StatusRequestPacket; -import com.velocitypowered.proxy.protocol.packet.StatusResponsePacket; -import com.velocitypowered.proxy.protocol.packet.TabCompleteRequestPacket; -import com.velocitypowered.proxy.protocol.packet.TabCompleteResponsePacket; -import com.velocitypowered.proxy.protocol.packet.TransferPacket; -import com.velocitypowered.proxy.protocol.packet.UpsertPlayerInfoPacket; -import com.velocitypowered.proxy.protocol.packet.chat.ChatAcknowledgementPacket; -import com.velocitypowered.proxy.protocol.packet.chat.PlayerChatCompletionPacket; -import com.velocitypowered.proxy.protocol.packet.chat.SystemChatPacket; -import com.velocitypowered.proxy.protocol.packet.chat.keyed.KeyedPlayerChatPacket; -import com.velocitypowered.proxy.protocol.packet.chat.keyed.KeyedPlayerCommandPacket; -import com.velocitypowered.proxy.protocol.packet.chat.legacy.LegacyChatPacket; -import com.velocitypowered.proxy.protocol.packet.chat.session.SessionPlayerChatPacket; -import com.velocitypowered.proxy.protocol.packet.chat.session.SessionPlayerCommandPacket; -import com.velocitypowered.proxy.protocol.packet.chat.session.UnsignedPlayerCommandPacket; -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; -import com.velocitypowered.proxy.protocol.packet.config.StartUpdatePacket; -import com.velocitypowered.proxy.protocol.packet.config.TagsUpdatePacket; -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 edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import io.netty.util.collection.IntObjectHashMap; -import io.netty.util.collection.IntObjectMap; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import java.util.Collections; -import java.util.EnumMap; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import org.checkerframework.checker.nullness.qual.Nullable; /** * Registry of all Minecraft protocol states and the packets for each state. */ public enum StateRegistry { - HANDSHAKE { - { - serverbound.register(HandshakePacket.class, new HandshakePacket.Codec(), - map(0x00, MINECRAFT_1_7_2, false)); - } - }, - STATUS { - { - serverbound.register( - StatusRequestPacket.class, new StatusRequestPacket.Codec(), - map(0x00, MINECRAFT_1_7_2, false)); - serverbound.register(StatusPingPacket.class, new StatusPingPacket.Codec(), - map(0x01, MINECRAFT_1_7_2, false)); - - clientbound.register( - StatusResponsePacket.class, new StatusResponsePacket.Codec(), - map(0x00, MINECRAFT_1_7_2, false)); - clientbound.register(StatusPingPacket.class, new StatusPingPacket.Codec(), - map(0x01, MINECRAFT_1_7_2, false)); - } - }, - CONFIG { - { - serverbound.register( - ClientSettingsPacket.class, new ClientSettingsPacket.Codec(), - map(0x00, MINECRAFT_1_20_2, false)); - serverbound.register( - ServerboundCookieResponsePacket.class, new ServerboundCookieResponsePacket.Codec(), - map(0x01, MINECRAFT_1_20_5, false)); - serverbound.register( - PluginMessagePacket.class, new PluginMessagePacket.Codec(), - map(0x01, MINECRAFT_1_20_2, false), - map(0x02, MINECRAFT_1_20_5, false)); - serverbound.register( - FinishedUpdatePacket.class, new FinishedUpdatePacket.Codec(), - map(0x02, MINECRAFT_1_20_2, false), - map(0x03, MINECRAFT_1_20_5, false)); - serverbound.register(KeepAlivePacket.class, new KeepAlivePacket.Codec(), - map(0x03, MINECRAFT_1_20_2, false), - map(0x04, MINECRAFT_1_20_5, false)); - serverbound.register( - PingIdentifyPacket.class, new PingIdentifyPacket.Codec(), - map(0x04, MINECRAFT_1_20_2, false), - map(0x05, MINECRAFT_1_20_5, false)); - serverbound.register( - ResourcePackResponsePacket.class, - new ResourcePackResponsePacket.Codec(), - map(0x05, MINECRAFT_1_20_2, false), - map(0x06, MINECRAFT_1_20_5, false)); - serverbound.register( - KnownPacksPacket.class, - new KnownPacksPacket.Codec(), - map(0x07, MINECRAFT_1_20_5, false)); - serverbound.register(ServerboundCustomClickActionPacket.class, new ServerboundCustomClickActionPacket.Codec(), - map(0x08, MINECRAFT_1_21_6, false)); - serverbound.register( - CodeOfConductAcceptPacket.class, - new CodeOfConductAcceptPacket.Codec(), - map(0x09, MINECRAFT_1_21_9, false)); - - clientbound.register( - ClientboundCookieRequestPacket.class, new ClientboundCookieRequestPacket.Codec(), - map(0x00, MINECRAFT_1_20_5, false)); - clientbound.register( - PluginMessagePacket.class, new PluginMessagePacket.Codec(), - map(0x00, MINECRAFT_1_20_2, false), - map(0x01, MINECRAFT_1_20_5, false)); - clientbound.register( - DisconnectPacket.class, new DisconnectPacket.Codec(this), - map(0x01, MINECRAFT_1_20_2, false), - map(0x02, MINECRAFT_1_20_5, false)); - clientbound.register( - FinishedUpdatePacket.class, new FinishedUpdatePacket.Codec(), - map(0x02, MINECRAFT_1_20_2, false), - map(0x03, MINECRAFT_1_20_5, false)); - clientbound.register(KeepAlivePacket.class, new KeepAlivePacket.Codec(), - map(0x03, MINECRAFT_1_20_2, false), - map(0x04, MINECRAFT_1_20_5, false)); - clientbound.register( - PingIdentifyPacket.class, new PingIdentifyPacket.Codec(), - map(0x04, MINECRAFT_1_20_2, false), - map(0x05, MINECRAFT_1_20_5, false)); - clientbound.register( - RegistrySyncPacket.class, new RegistrySyncPacket.Codec(), - map(0x05, MINECRAFT_1_20_2, false), - map(0x07, MINECRAFT_1_20_5, false)); - clientbound.register( - RemoveResourcePackPacket.class, new RemoveResourcePackPacket.Codec(), - map(0x06, MINECRAFT_1_20_3, false), - map(0x08, MINECRAFT_1_20_5, false)); - clientbound.register(ResourcePackRequestPacket.class, new ResourcePackRequestPacket.Codec(), - map(0x06, MINECRAFT_1_20_2, false), - map(0x07, MINECRAFT_1_20_3, false), - map(0x09, MINECRAFT_1_20_5, false)); - clientbound.register( - ClientboundStoreCookiePacket.class, new ClientboundStoreCookiePacket.Codec(), - map(0x0A, MINECRAFT_1_20_5, false)); - clientbound.register(TransferPacket.class, new TransferPacket.Codec(), - map(0x0B, MINECRAFT_1_20_5, false)); - clientbound.register(ActiveFeaturesPacket.class, new ActiveFeaturesPacket.Codec(), - map(0x07, MINECRAFT_1_20_2, false), - map(0x08, MINECRAFT_1_20_3, false), - map(0x0C, MINECRAFT_1_20_5, false)); - clientbound.register(TagsUpdatePacket.class, new TagsUpdatePacket.Codec(), - map(0x08, MINECRAFT_1_20_2, false), - map(0x09, MINECRAFT_1_20_3, false), - map(0x0D, MINECRAFT_1_20_5, false)); - clientbound.register(KnownPacksPacket.class, new KnownPacksPacket.Codec(), - map(0x0E, MINECRAFT_1_20_5, false)); - clientbound.register(ClientboundCustomReportDetailsPacket.class, new ClientboundCustomReportDetailsPacket.Codec(), - map(0x0F, MINECRAFT_1_21, false)); - clientbound.register(ClientboundServerLinksPacket.class, new ClientboundServerLinksPacket.Codec(), - map(0x10, MINECRAFT_1_21, false)); - clientbound.register(DialogClearPacket.class, new DialogClearPacket.Codec(), - map(0x11, MINECRAFT_1_21_6, false)); - clientbound.register(DialogShowPacket.class, new DialogShowPacket.Codec(this), - map(0x12, MINECRAFT_1_21_6, false)); - clientbound.register(CodeOfConductPacket.class, new CodeOfConductPacket.Codec(), - map(0x13, MINECRAFT_1_21_9, false)); - } - }, - PLAY { - { - serverbound.fallback = false; - clientbound.fallback = false; - - serverbound.register(TabCompleteRequestPacket.class, new TabCompleteRequestPacket.Codec(), - map(0x14, MINECRAFT_1_7_2, false), - map(0x01, MINECRAFT_1_9, false), - map(0x02, MINECRAFT_1_12, false), - map(0x01, MINECRAFT_1_12_1, false), - map(0x05, MINECRAFT_1_13, false), - map(0x06, MINECRAFT_1_14, false), - map(0x08, MINECRAFT_1_19, false), - map(0x09, MINECRAFT_1_19_1, false), - 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(0x0D, MINECRAFT_1_21_2, false), - map(0x0E, MINECRAFT_1_21_6, false)); - serverbound.register( - LegacyChatPacket.class, - new LegacyChatPacket.Codec(), - map(0x01, MINECRAFT_1_7_2, false), - map(0x02, MINECRAFT_1_9, false), - map(0x03, MINECRAFT_1_12, false), - map(0x02, MINECRAFT_1_12_1, false), - map(0x03, MINECRAFT_1_14, MINECRAFT_1_18_2, false)); - serverbound.register( - ChatAcknowledgementPacket.class, - new ChatAcknowledgementPacket.Codec(), - map(0x03, MINECRAFT_1_19_3, false), - map(0x04, MINECRAFT_1_21_2, false), - map(0x05, MINECRAFT_1_21_6, false)); - serverbound.register(KeyedPlayerCommandPacket.class, new KeyedPlayerCommandPacket.Codec(), - map(0x03, MINECRAFT_1_19, false), - map(0x04, MINECRAFT_1_19_1, MINECRAFT_1_19_1, false)); - serverbound.register(KeyedPlayerChatPacket.class, new KeyedPlayerChatPacket.Codec(), - map(0x04, MINECRAFT_1_19, false), - map(0x05, MINECRAFT_1_19_1, MINECRAFT_1_19_1, false)); - serverbound.register(SessionPlayerCommandPacket.class, new SessionPlayerCommandPacket.Codec(), - map(0x04, MINECRAFT_1_19_3, false), - map(0x05, MINECRAFT_1_20_5, false), - map(0x06, MINECRAFT_1_21_2, false), - map(0x07, MINECRAFT_1_21_6, false)); - serverbound.register(UnsignedPlayerCommandPacket.class, new UnsignedPlayerCommandPacket.Codec(), - map(0x04, MINECRAFT_1_20_5, false), - map(0x05, MINECRAFT_1_21_2, false), - map(0x06, MINECRAFT_1_21_6, false)); - serverbound.register( - SessionPlayerChatPacket.class, - new SessionPlayerChatPacket.Codec(), - map(0x05, MINECRAFT_1_19_3, false), - map(0x06, MINECRAFT_1_20_5, false), - map(0x07, MINECRAFT_1_21_2, false), - map(0x08, MINECRAFT_1_21_6, false)); - serverbound.register( - ClientSettingsPacket.class, - new ClientSettingsPacket.Codec(), - map(0x15, MINECRAFT_1_7_2, false), - map(0x04, MINECRAFT_1_9, false), - map(0x05, MINECRAFT_1_12, false), - map(0x04, MINECRAFT_1_12_1, false), - map(0x05, MINECRAFT_1_14, false), - map(0x07, MINECRAFT_1_19, false), - map(0x08, MINECRAFT_1_19_1, false), - 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(0x0C, MINECRAFT_1_21_2, false), - map(0x0D, MINECRAFT_1_21_6, false)); - serverbound.register( - ServerboundCookieResponsePacket.class, new ServerboundCookieResponsePacket.Codec(), - map(0x11, MINECRAFT_1_20_5, false), - map(0x13, MINECRAFT_1_21_2, false), - map(0x14, MINECRAFT_1_21_6, false)); - serverbound.register( - PluginMessagePacket.class, - new PluginMessagePacket.Codec(), - map(0x17, MINECRAFT_1_7_2, false), - map(0x09, MINECRAFT_1_9, false), - 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(0x0A, MINECRAFT_1_17, false), - map(0x0C, MINECRAFT_1_19, false), - map(0x0D, MINECRAFT_1_19_1, false), - map(0x0C, MINECRAFT_1_19_3, false), - 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(0x14, MINECRAFT_1_21_2, false), - map(0x15, MINECRAFT_1_21_6, false)); - serverbound.register( - KeepAlivePacket.class, - new KeepAlivePacket.Codec(), - map(0x00, MINECRAFT_1_7_2, false), - map(0x0B, MINECRAFT_1_9, false), - map(0x0C, MINECRAFT_1_12, false), - 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(0x0F, MINECRAFT_1_17, false), - map(0x11, MINECRAFT_1_19, false), - map(0x12, MINECRAFT_1_19_1, false), - map(0x11, MINECRAFT_1_19_3, false), - 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(0x1A, MINECRAFT_1_21_2, false), - map(0x1B, MINECRAFT_1_21_6, false)); - serverbound.register( - ResourcePackResponsePacket.class, - new ResourcePackResponsePacket.Codec(), - map(0x19, MINECRAFT_1_8, false), - map(0x16, MINECRAFT_1_9, false), - map(0x18, MINECRAFT_1_12, false), - 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(0x23, MINECRAFT_1_19, false), - 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(0x2D, MINECRAFT_1_21_2, false), - map(0x2F, MINECRAFT_1_21_4, false), - map(0x30, MINECRAFT_1_21_6, false)); - serverbound.register( - FinishedUpdatePacket.class, new FinishedUpdatePacket.Codec(), - map(0x0B, MINECRAFT_1_20_2, false), - map(0x0C, MINECRAFT_1_20_5, false), - map(0x0E, MINECRAFT_1_21_2, false), - map(0x0F, MINECRAFT_1_21_6, false)); - - clientbound.register( - BossBarPacket.class, - new BossBarPacket.Codec(), - map(0x0C, MINECRAFT_1_9, false), - map(0x0D, MINECRAFT_1_15, false), - map(0x0C, MINECRAFT_1_16, false), - map(0x0D, MINECRAFT_1_17, false), - map(0x0A, MINECRAFT_1_19, false), - map(0x0B, MINECRAFT_1_19_4, false), - map(0x0A, MINECRAFT_1_20_2, false), - map(0x09, MINECRAFT_1_21_5, false)); - clientbound.register( - LegacyChatPacket.class, - new LegacyChatPacket.Codec(), - 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(0x0F, MINECRAFT_1_17, MINECRAFT_1_18_2, true)); - clientbound.register(TabCompleteResponsePacket.class, new TabCompleteResponsePacket.Codec(), - 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(0x11, MINECRAFT_1_17, false), - map(0x0E, MINECRAFT_1_19, false), - map(0x0D, MINECRAFT_1_19_3, false), - map(0x0F, MINECRAFT_1_19_4, false), - map(0x10, MINECRAFT_1_20_2, false), - map(0x0F, MINECRAFT_1_21_5, false)); - clientbound.register( - AvailableCommandsPacket.class, - new AvailableCommandsPacket.Codec(), - 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(0x12, MINECRAFT_1_17, false), - map(0x0F, MINECRAFT_1_19, false), - map(0x0E, MINECRAFT_1_19_3, false), - map(0x10, MINECRAFT_1_19_4, false), - map(0x11, MINECRAFT_1_20_2, false), - map(0x10, MINECRAFT_1_21_5, false)); - clientbound.register( - ClientboundCookieRequestPacket.class, new ClientboundCookieRequestPacket.Codec(), - map(0x16, MINECRAFT_1_20_5, false), - map(0x15, MINECRAFT_1_21_5, false)); - clientbound.register( - ClientboundSoundEntityPacket.class, new ClientboundSoundEntityPacket.Codec(), - map(0x5D, MINECRAFT_1_19_3, true), - map(0x61, MINECRAFT_1_19_4, true), - map(0x63, MINECRAFT_1_20_2, true), - map(0x65, MINECRAFT_1_20_3, true), - map(0x67, MINECRAFT_1_20_5, true), - map(0x6E, MINECRAFT_1_21_2, true), - map(0x6D, MINECRAFT_1_21_5, true), - map(0x72, MINECRAFT_1_21_9, true)); - clientbound.register( - ClientboundStopSoundPacket.class, new ClientboundStopSoundPacket.Codec(), - map(0x5F, MINECRAFT_1_19_3, true), - map(0x63, MINECRAFT_1_19_4, true), - map(0x66, MINECRAFT_1_20_2, true), - map(0x68, MINECRAFT_1_20_3, true), - map(0x6A, MINECRAFT_1_20_5, true), - map(0x71, MINECRAFT_1_21_2, true), - map(0x70, MINECRAFT_1_21_5, true), - map(0x75, MINECRAFT_1_21_9, true)); - clientbound.register( - PluginMessagePacket.class, - new PluginMessagePacket.Codec(), - map(0x3F, MINECRAFT_1_7_2, false), - map(0x18, MINECRAFT_1_9, false), - map(0x19, MINECRAFT_1_13, false), - 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(0x18, MINECRAFT_1_17, false), - map(0x15, MINECRAFT_1_19, false), - map(0x16, MINECRAFT_1_19_1, false), - map(0x15, MINECRAFT_1_19_3, false), - map(0x17, MINECRAFT_1_19_4, false), - map(0x18, MINECRAFT_1_20_2, false), - map(0x19, MINECRAFT_1_20_5, false), - map(0x18, MINECRAFT_1_21_5, false)); - clientbound.register( - DisconnectPacket.class, - new DisconnectPacket.Codec(this), - map(0x40, MINECRAFT_1_7_2, false), - map(0x1A, MINECRAFT_1_9, false), - map(0x1B, MINECRAFT_1_13, false), - 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(0x1A, MINECRAFT_1_17, false), - map(0x17, MINECRAFT_1_19, false), - map(0x19, MINECRAFT_1_19_1, false), - map(0x17, MINECRAFT_1_19_3, false), - 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(0x20, MINECRAFT_1_21_9, false)); - clientbound.register( - KeepAlivePacket.class, - new KeepAlivePacket.Codec(), - map(0x00, MINECRAFT_1_7_2, false), - map(0x1F, MINECRAFT_1_9, false), - map(0x21, MINECRAFT_1_13, false), - 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(0x21, MINECRAFT_1_17, false), - map(0x1E, MINECRAFT_1_19, false), - map(0x20, MINECRAFT_1_19_1, false), - 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(0x27, MINECRAFT_1_21_2, false), - map(0x26, MINECRAFT_1_21_5, false), - map(0x2B, MINECRAFT_1_21_9, false)); - clientbound.register( - JoinGamePacket.class, - new JoinGamePacket.Codec(), - map(0x01, MINECRAFT_1_7_2, false), - map(0x23, MINECRAFT_1_9, false), - map(0x25, MINECRAFT_1_13, false), - 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(0x26, MINECRAFT_1_17, false), - map(0x23, MINECRAFT_1_19, false), - map(0x25, MINECRAFT_1_19_1, false), - 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(0x2C, MINECRAFT_1_21_2, false), - map(0x2B, MINECRAFT_1_21_5, false), - map(0x30, MINECRAFT_1_21_9, false)); - clientbound.register( - RespawnPacket.class, - new RespawnPacket.Codec(), - map(0x07, MINECRAFT_1_7_2, true), - map(0x33, MINECRAFT_1_9, true), - map(0x34, MINECRAFT_1_12, true), - map(0x35, MINECRAFT_1_12_1, true), - map(0x38, MINECRAFT_1_13, true), - 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(0x3D, MINECRAFT_1_17, true), - map(0x3B, MINECRAFT_1_19, true), - map(0x3E, MINECRAFT_1_19_1, true), - map(0x3D, MINECRAFT_1_19_3, true), - 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(0x4C, MINECRAFT_1_21_2, true), - map(0x4B, MINECRAFT_1_21_5, true), - map(0x50, MINECRAFT_1_21_9, true)); - clientbound.register( - RemoveResourcePackPacket.class, - new RemoveResourcePackPacket.Codec(), - 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(0x4E, MINECRAFT_1_21_9, false)); - clientbound.register( - ResourcePackRequestPacket.class, - new ResourcePackRequestPacket.Codec(), - 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(0x3C, MINECRAFT_1_17, false), - map(0x3A, MINECRAFT_1_19, false), - map(0x3D, MINECRAFT_1_19_1, false), - map(0x3C, MINECRAFT_1_19_3, false), - 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(0x4B, MINECRAFT_1_21_2, false), - map(0x4A, MINECRAFT_1_21_5, false), - map(0x4F, MINECRAFT_1_21_9, false)); - clientbound.register( - HeaderAndFooterPacket.class, - new HeaderAndFooterPacket.Codec(), - map(0x47, MINECRAFT_1_8, true), - map(0x48, MINECRAFT_1_9, true), - map(0x47, MINECRAFT_1_9_4, true), - map(0x49, MINECRAFT_1_12, true), - map(0x4A, MINECRAFT_1_12_1, true), - 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(0x5E, MINECRAFT_1_17, true), - map(0x5F, MINECRAFT_1_18, true), - map(0x60, MINECRAFT_1_19, true), - map(0x63, MINECRAFT_1_19_1, true), - map(0x61, MINECRAFT_1_19_3, true), - 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(0x74, MINECRAFT_1_21_2, true), - map(0x73, MINECRAFT_1_21_5, true), - map(0x78, MINECRAFT_1_21_9, true)); - clientbound.register( - LegacyTitlePacket.class, - new LegacyTitlePacket.Codec(), - map(0x45, MINECRAFT_1_8, true), - map(0x45, MINECRAFT_1_9, true), - map(0x47, MINECRAFT_1_12, true), - map(0x48, MINECRAFT_1_12_1, true), - map(0x4B, MINECRAFT_1_13, true), - 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, new TitleSubtitlePacket.Codec(), - map(0x57, MINECRAFT_1_17, true), - map(0x58, MINECRAFT_1_18, true), - map(0x5B, MINECRAFT_1_19_1, true), - map(0x59, MINECRAFT_1_19_3, true), - 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(0x6A, MINECRAFT_1_21_2, true), - map(0x69, MINECRAFT_1_21_5, true), - map(0x6E, MINECRAFT_1_21_9, true)); - clientbound.register( - TitleTextPacket.class, - new TitleTextPacket.Codec(), - map(0x59, MINECRAFT_1_17, true), - map(0x5A, MINECRAFT_1_18, true), - map(0x5D, MINECRAFT_1_19_1, true), - map(0x5B, MINECRAFT_1_19_3, true), - 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(0x6C, MINECRAFT_1_21_2, true), - map(0x6B, MINECRAFT_1_21_5, true), - map(0x70, MINECRAFT_1_21_9, true)); - clientbound.register( - TitleActionbarPacket.class, - new TitleActionbarPacket.Codec(), - map(0x41, MINECRAFT_1_17, true), - map(0x40, MINECRAFT_1_19, true), - map(0x43, MINECRAFT_1_19_1, true), - map(0x42, MINECRAFT_1_19_3, true), - 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(0x51, MINECRAFT_1_21_2, true), - map(0x50, MINECRAFT_1_21_5, true), - map(0x55, MINECRAFT_1_21_9, true)); - clientbound.register( - TitleTimesPacket.class, - new TitleTimesPacket.Codec(), - map(0x5A, MINECRAFT_1_17, true), - map(0x5B, MINECRAFT_1_18, true), - map(0x5E, MINECRAFT_1_19_1, true), - map(0x5C, MINECRAFT_1_19_3, true), - 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(0x6D, MINECRAFT_1_21_2, true), - map(0x6C, MINECRAFT_1_21_5, true), - map(0x71, MINECRAFT_1_21_9, true)); - clientbound.register( - TitleClearPacket.class, - new TitleClearPacket.Codec(), - map(0x10, MINECRAFT_1_17, true), - map(0x0D, MINECRAFT_1_19, true), - map(0x0C, MINECRAFT_1_19_3, true), - map(0x0E, MINECRAFT_1_19_4, true), - map(0x0F, MINECRAFT_1_20_2, true), - map(0x0E, MINECRAFT_1_21_5, true)); - clientbound.register( - LegacyPlayerListItemPacket.class, - new LegacyPlayerListItemPacket.Codec(), - map(0x38, MINECRAFT_1_7_2, false), - map(0x2D, MINECRAFT_1_9, false), - map(0x2E, MINECRAFT_1_12_1, false), - map(0x30, MINECRAFT_1_13, false), - 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(0x36, MINECRAFT_1_17, false), - map(0x34, MINECRAFT_1_19, false), - map(0x37, MINECRAFT_1_19_1, MINECRAFT_1_19_1, false)); - clientbound.register(RemovePlayerInfoPacket.class, new RemovePlayerInfoPacket.Codec(), - 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(0x3F, MINECRAFT_1_21_2, false), - map(0x3E, MINECRAFT_1_21_5, false), - map(0x43, MINECRAFT_1_21_9, false)); - clientbound.register( - UpsertPlayerInfoPacket.class, - new UpsertPlayerInfoPacket.Codec(), - 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(0x40, MINECRAFT_1_21_2, false), - map(0x3F, MINECRAFT_1_21_5, false), - map(0x44, MINECRAFT_1_21_9, false)); - clientbound.register( - ClientboundStoreCookiePacket.class, new ClientboundStoreCookiePacket.Codec(), - 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)); - clientbound.register( - SystemChatPacket.class, - new SystemChatPacket.Codec(), - map(0x5F, MINECRAFT_1_19, true), - map(0x62, MINECRAFT_1_19_1, true), - map(0x60, MINECRAFT_1_19_3, true), - 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(0x73, MINECRAFT_1_21_2, true), - map(0x72, MINECRAFT_1_21_5, true), - map(0x77, MINECRAFT_1_21_9, true)); - clientbound.register( - PlayerChatCompletionPacket.class, - new PlayerChatCompletionPacket.Codec(), - map(0x15, MINECRAFT_1_19_1, true), - map(0x14, MINECRAFT_1_19_3, true), - map(0x16, MINECRAFT_1_19_4, true), - map(0x17, MINECRAFT_1_20_2, true), - map(0x18, MINECRAFT_1_20_5, true), - map(0x17, MINECRAFT_1_21_5, true)); - clientbound.register( - ServerDataPacket.class, - new ServerDataPacket.Codec(), - map(0x3F, MINECRAFT_1_19, false), - map(0x42, MINECRAFT_1_19_1, false), - map(0x41, MINECRAFT_1_19_3, false), - 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(0x50, MINECRAFT_1_21_2, false), - map(0x4F, MINECRAFT_1_21_5, false), - map(0x54, MINECRAFT_1_21_9, false)); - clientbound.register( - StartUpdatePacket.class, - new StartUpdatePacket.Codec(), - map(0x65, MINECRAFT_1_20_2, false), - 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(0x74, MINECRAFT_1_21_9, false)); - clientbound.register( - BundleDelimiterPacket.class, - new BundleDelimiterPacket.Codec(), - map(0x00, MINECRAFT_1_19_4, false)); - clientbound.register( - TransferPacket.class, - new TransferPacket.Codec(), - map(0x73, MINECRAFT_1_20_5, false), - map(0x7A, MINECRAFT_1_21_2, false), - map(0x7F, MINECRAFT_1_21_9, false)); - clientbound.register( - ClientboundCustomReportDetailsPacket.class, - new ClientboundCustomReportDetailsPacket.Codec(), - map(0x7A, MINECRAFT_1_21, false), - map(0x81, MINECRAFT_1_21_2, false), - map(0x86, MINECRAFT_1_21_9, false)); - clientbound.register( - ClientboundServerLinksPacket.class, - new ClientboundServerLinksPacket.Codec(), - map(0x7B, MINECRAFT_1_21, false), - map(0x82, MINECRAFT_1_21_2, false), - map(0x87, MINECRAFT_1_21_9, false)); - } - }, - LOGIN { - { - serverbound.register(ServerLoginPacket.class, - new ServerLoginPacket.Codec(), - map(0x00, MINECRAFT_1_7_2, false)); - serverbound.register( - EncryptionResponsePacket.class, new EncryptionResponsePacket.Codec(), - map(0x01, MINECRAFT_1_7_2, false)); - serverbound.register( - LoginPluginResponsePacket.class, new LoginPluginResponsePacket.Codec(), - map(0x02, MINECRAFT_1_13, false)); - serverbound.register( - LoginAcknowledgedPacket.class, new LoginAcknowledgedPacket.Codec(), - map(0x03, MINECRAFT_1_20_2, false)); - serverbound.register( - ServerboundCookieResponsePacket.class, new ServerboundCookieResponsePacket.Codec(), - map(0x04, MINECRAFT_1_20_5, false)); - - clientbound.register( - DisconnectPacket.class, new DisconnectPacket.Codec(this), - map(0x00, MINECRAFT_1_7_2, false)); - clientbound.register( - EncryptionRequestPacket.class, new EncryptionRequestPacket.Codec(), - map(0x01, MINECRAFT_1_7_2, false)); - clientbound.register( - ServerLoginSuccessPacket.class, new ServerLoginSuccessPacket.Codec(), - map(0x02, MINECRAFT_1_7_2, false)); - clientbound.register( - SetCompressionPacket.class, new SetCompressionPacket.Codec(), - map(0x03, MINECRAFT_1_8, false)); - clientbound.register( - LoginPluginMessagePacket.class, - new LoginPluginMessagePacket.Codec(), - map(0x04, MINECRAFT_1_13, false)); - clientbound.register( - ClientboundCookieRequestPacket.class, new ClientboundCookieRequestPacket.Codec(), - map(0x05, MINECRAFT_1_20_5, false)); - } - }; + HANDSHAKE, + STATUS, + CONFIG, + PLAY, + LOGIN; public static final int STATUS_ID = 1; public static final int LOGIN_ID = 2; public static final int TRANSFER_ID = 3; - protected final PacketRegistry clientbound = new PacketRegistry(CLIENTBOUND, this); - protected final PacketRegistry serverbound = new PacketRegistry(SERVERBOUND, this); - - public StateRegistry.PacketRegistry.ProtocolRegistry getProtocolRegistry(Direction direction, - ProtocolVersion version) { - return (direction == SERVERBOUND ? serverbound : clientbound).getProtocolRegistry(version); - } /** * Gets the API representation of the StateRegistry. @@ -870,256 +49,4 @@ public enum StateRegistry { case PLAY -> ProtocolState.PLAY; }; } - - /** - * Packet registry. - */ - public static class PacketRegistry { - - private final Direction direction; - private final StateRegistry registry; - private final Map versions; - private boolean fallback = true; - - PacketRegistry(Direction direction, StateRegistry registry) { - this.direction = direction; - this.registry = registry; - - Map mutableVersions = new EnumMap<>(ProtocolVersion.class); - for (ProtocolVersion version : ProtocolVersion.values()) { - if (!version.isLegacy() && !version.isUnknown()) { - mutableVersions.put(version, new ProtocolRegistry(version)); - } - } - - this.versions = Collections.unmodifiableMap(mutableVersions); - } - - ProtocolRegistry getProtocolRegistry(final ProtocolVersion version) { - ProtocolRegistry registry = versions.get(version); - if (registry == null) { - if (fallback) { - return getProtocolRegistry(MINIMUM_VERSION); - } - throw new IllegalArgumentException("Could not find data for protocol version " + version); - } - return registry; - } - -

void register(Class

clazz, PacketCodec

codec, - PacketMapping... mappings) { - if (mappings.length == 0) { - throw new IllegalArgumentException("At least one mapping must be provided."); - } - - 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 lastValid = current.lastValidProtocolVersion; - if (lastValid != null) { - if (next != current) { - throw new IllegalArgumentException("Cannot add a mapping after last valid mapping"); - } - if (from.greaterThan(lastValid)) { - 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; - - ProtocolVersion lastInList = lastValid != null ? lastValid : getLast(SUPPORTED_VERSIONS); - - if (from.noLessThan(to) && from != lastInList) { - throw new IllegalArgumentException(String.format( - "Next mapping version (%s) should be lower then current (%s)", to, from)); - } - - for (ProtocolVersion protocol : EnumSet.range(from, to)) { - if (protocol == to && next != current) { - break; - } - ProtocolRegistry registry = this.versions.get(protocol); - if (registry == null) { - throw new IllegalArgumentException( - "Unknown protocol version " + current.protocolVersion); - } - - if (registry.packetIdToCodec.containsKey(current.id)) { - throw new IllegalArgumentException( - "Can not register class " - + clazz.getSimpleName() - + " with id " - + current.id - + " for " - + registry.version - + " because another packet is already registered"); - } - - if (registry.packetClassToId.containsKey(clazz)) { - throw new IllegalArgumentException( - clazz.getSimpleName() + " is already registered for version " + registry.version); - } - - if (!current.encodeOnly) { - registry.packetIdToCodec.put(current.id, codec); - } - registry.packetClassToCodec.put(clazz, codec); - registry.packetClassToId.put(clazz, current.id); - } - } - } - - /** - * Protocol registry. - */ - public class ProtocolRegistry { - - public final ProtocolVersion version; - final IntObjectMap> packetIdToCodec = - new IntObjectHashMap<>(16, 0.5f); - - final Map, PacketCodec> packetClassToCodec = - new HashMap<>(16, 0.5f); - final Object2IntMap> packetClassToId = - new Object2IntOpenHashMap<>(16, 0.5f); - - ProtocolRegistry(final ProtocolVersion version) { - this.version = version; - this.packetClassToId.defaultReturnValue(Integer.MIN_VALUE); - } - - /** - * Gets the codec for the specified packet {@code id}. - * - * @param id the packet ID - * @return the packet codec, or {@code null} if the ID is not registered - */ - public @Nullable PacketCodec getCodec(final int id) { - return this.packetIdToCodec.get(id); - } - - /** - * Gets the codec for the specified packet class. - * - * @param packetClass the packet class - * @return the packet codec, or {@code null} if the class is not registered - */ - @SuppressWarnings("unchecked") - public @Nullable PacketCodec getCodec( - final Class packetClass) { - return (PacketCodec) this.packetClassToCodec.get(packetClass); - } - - /** - * Attempts to look up the packet ID for an {@code packet}. - * - * @param packet the packet to look up - * @return the packet ID - * @throws IllegalArgumentException if the packet ID is not found - */ - public int getPacketId(final MinecraftPacket packet) { - final int id = this.packetClassToId.getInt(packet.getClass()); - if (id == Integer.MIN_VALUE) { - throw new IllegalArgumentException(String.format( - "Unable to find id for packet of type %s in %s protocol %s phase %s", - packet.getClass().getName(), PacketRegistry.this.direction, - this.version, PacketRegistry.this.registry - )); - } - return id; - } - - /** - * Checks if the registry contains a packet with the specified {@code id}. - * - * @param packet the packet to check - * @return {@code true} if the packet is registered, {@code false} otherwise - */ - public boolean containsPacket(final MinecraftPacket packet) { - return this.packetClassToId.containsKey(packet.getClass()); - } - } - } - - /** - * Packet mapping. - */ - public static final class PacketMapping { - - private final int id; - private final ProtocolVersion protocolVersion; - private final boolean encodeOnly; - private final @Nullable ProtocolVersion lastValidProtocolVersion; - - PacketMapping(int id, ProtocolVersion protocolVersion, - @Nullable ProtocolVersion lastValidProtocolVersion, - boolean packetDecoding) { - this.id = id; - this.protocolVersion = protocolVersion; - this.lastValidProtocolVersion = lastValidProtocolVersion; - this.encodeOnly = packetDecoding; - } - - @Override - public String toString() { - return "PacketMapping{" - + "id=" - + id - + ", protocolVersion=" - + protocolVersion - + ", encodeOnly=" - + encodeOnly - + '}'; - } - - @Override - public boolean equals(@Nullable Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - PacketMapping that = (PacketMapping) o; - return id == that.id - && protocolVersion == that.protocolVersion - && encodeOnly == that.encodeOnly; - } - - @Override - public int hashCode() { - return Objects.hash(id, protocolVersion, 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 - * @return PacketMapping with the provided arguments - */ - @SuppressFBWarnings({"UPM_UNCALLED_PRIVATE_METHOD"}) - private static PacketMapping map(int id, ProtocolVersion version, boolean 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); - } - } \ No newline at end of file diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftDecoder.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftDecoder.java index 45b79b3dc..fad9f52eb 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftDecoder.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftDecoder.java @@ -20,8 +20,10 @@ package com.velocitypowered.proxy.protocol.netty; import com.google.common.base.Preconditions; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.protocol.MinecraftPacket; +import com.velocitypowered.proxy.protocol.ProtocolStates; import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.StateRegistry; +import com.velocitypowered.proxy.protocol.registry.PacketRegistry; import com.velocitypowered.proxy.util.except.QuietRuntimeException; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; @@ -39,8 +41,9 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter { + "information, launch Velocity with -Dvelocity.packet-decode-logging=true to see more."); private final ProtocolUtils.Direction direction; + private ProtocolVersion version; private StateRegistry state; - private StateRegistry.PacketRegistry.ProtocolRegistry registry; + private PacketRegistry registry; /** * Creates a new {@code MinecraftDecoder} decoding packets from the specified {@code direction}. @@ -49,8 +52,8 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter { */ public MinecraftDecoder(ProtocolUtils.Direction direction) { this.direction = Preconditions.checkNotNull(direction, "direction"); - this.registry = StateRegistry.HANDSHAKE.getProtocolRegistry( - direction, ProtocolVersion.MINIMUM_VERSION); + this.version = ProtocolVersion.MINIMUM_VERSION; + this.registry = ProtocolStates.handshake(direction).forVersion(ProtocolVersion.MINIMUM_VERSION); this.state = StateRegistry.HANDSHAKE; } @@ -82,11 +85,13 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter { MinecraftPacket packet; try { - packet = codec.decode(buf, direction, registry.version); + packet = codec.decode(buf, direction, this.version); } catch (Exception e) { throw handleDecodeFailure(e, codec, packetId); } + System.out.println(packet); + if (buf.isReadable()) { throw handleOverflow(packet, buf.readerIndex(), buf.writerIndex()); } @@ -100,8 +105,8 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter { private void doLengthSanityChecks(ByteBuf buf, com.velocitypowered.proxy.protocol.PacketCodec codec) throws Exception { - int expectedMinLen = codec.decodeExpectedMinLength(buf, direction, registry.version); - int expectedMaxLen = codec.decodeExpectedMaxLength(buf, direction, registry.version); + int expectedMinLen = codec.decodeExpectedMinLength(buf, direction, this.version); + int expectedMaxLen = codec.decodeExpectedMaxLength(buf, direction, this.version); if (expectedMaxLen != -1 && buf.readableBytes() > expectedMaxLen) { throw handleOverflow(codec, expectedMaxLen, buf.readableBytes()); } @@ -153,17 +158,18 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter { } private String getExtraConnectionDetail(int packetId) { - return "Direction " + direction + " Protocol " + registry.version + " State " + state + return "Direction " + direction + " Protocol " + this.version + " State " + state + " ID 0x" + Integer.toHexString(packetId); } public void setProtocolVersion(ProtocolVersion protocolVersion) { - this.registry = state.getProtocolRegistry(direction, protocolVersion); + this.version = protocolVersion; + this.registry = ProtocolStates.lookup(this.state, this.direction).forVersion(protocolVersion); } public void setState(StateRegistry state) { this.state = state; - this.setProtocolVersion(registry.version); + this.registry = ProtocolStates.lookup(this.state, this.direction).forVersion(this.version); } public ProtocolUtils.Direction getDirection() { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftEncoder.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftEncoder.java index 9e7344eb5..fa649327f 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftEncoder.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftEncoder.java @@ -21,8 +21,10 @@ import com.google.common.base.Preconditions; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.PacketCodec; +import com.velocitypowered.proxy.protocol.ProtocolStates; import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.StateRegistry; +import com.velocitypowered.proxy.protocol.registry.PacketRegistry; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; @@ -33,8 +35,9 @@ import io.netty.handler.codec.MessageToByteEncoder; public class MinecraftEncoder extends MessageToByteEncoder { private final ProtocolUtils.Direction direction; + private ProtocolVersion version; private StateRegistry state; - private StateRegistry.PacketRegistry.ProtocolRegistry registry; + private PacketRegistry registry; /** * Creates a new {@code MinecraftEncoder} encoding packets for the specified {@code direction}. @@ -43,8 +46,8 @@ public class MinecraftEncoder extends MessageToByteEncoder { */ public MinecraftEncoder(ProtocolUtils.Direction direction) { this.direction = Preconditions.checkNotNull(direction, "direction"); - this.registry = StateRegistry.HANDSHAKE.getProtocolRegistry( - direction, ProtocolVersion.MINIMUM_VERSION); + this.version = ProtocolVersion.MINIMUM_VERSION; + this.registry = ProtocolStates.handshake(direction).forVersion(ProtocolVersion.MINIMUM_VERSION); this.state = StateRegistry.HANDSHAKE; } @@ -52,13 +55,14 @@ public class MinecraftEncoder extends MessageToByteEncoder { @SuppressWarnings("unchecked") protected void encode(ChannelHandlerContext ctx, MinecraftPacket msg, ByteBuf out) { PacketCodec codec = (PacketCodec) this.registry.getCodec(msg.getClass()); + System.out.println(msg); if (codec == null) { throw new IllegalArgumentException("No codec found for packet: " + msg.getClass()); } int packetId = this.registry.getPacketId(msg); ProtocolUtils.writeVarInt(out, packetId); - codec.encode(msg, out, direction, registry.version); + codec.encode(msg, out, direction, version); } @Override @@ -71,7 +75,7 @@ public class MinecraftEncoder extends MessageToByteEncoder { int hint = -1; if (codec != null) { - hint = codec.encodeSizeHint(msg, direction, registry.version); + hint = codec.encodeSizeHint(msg, direction, version); } if (hint < 0) { @@ -84,12 +88,13 @@ public class MinecraftEncoder extends MessageToByteEncoder { } public void setProtocolVersion(final ProtocolVersion protocolVersion) { - this.registry = state.getProtocolRegistry(direction, protocolVersion); + this.version = protocolVersion; + this.registry = ProtocolStates.lookup(this.state, this.direction).forVersion(protocolVersion); } public void setState(StateRegistry state) { this.state = state; - this.setProtocolVersion(registry.version); + this.registry = ProtocolStates.lookup(state, this.direction).forVersion(version); } public ProtocolUtils.Direction getDirection() { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftVarintFrameDecoder.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftVarintFrameDecoder.java index e7af83458..0cedb7aac 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftVarintFrameDecoder.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftVarintFrameDecoder.java @@ -21,8 +21,10 @@ import static io.netty.util.ByteProcessor.FIND_NON_NUL; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.protocol.PacketCodec; +import com.velocitypowered.proxy.protocol.ProtocolStates; import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.StateRegistry; +import com.velocitypowered.proxy.protocol.registry.PacketRegistry; import com.velocitypowered.proxy.util.except.QuietDecoderException; import com.velocitypowered.proxy.util.except.QuietRuntimeException; import io.netty.buffer.ByteBuf; @@ -50,7 +52,7 @@ public class MinecraftVarintFrameDecoder extends ByteToMessageDecoder { new QuietDecoderException("Unknown packet"); private final ProtocolUtils.Direction direction; - private final StateRegistry.PacketRegistry.ProtocolRegistry registry; + private final PacketRegistry registry; private StateRegistry state; /** @@ -60,8 +62,7 @@ public class MinecraftVarintFrameDecoder extends ByteToMessageDecoder { */ public MinecraftVarintFrameDecoder(ProtocolUtils.Direction direction) { this.direction = direction; - this.registry = StateRegistry.HANDSHAKE.getProtocolRegistry( - direction, ProtocolVersion.MINIMUM_VERSION); + this.registry = ProtocolStates.handshake(direction).forVersion(ProtocolVersion.MINIMUM_VERSION); this.state = StateRegistry.HANDSHAKE; } @@ -110,9 +111,6 @@ public class MinecraftVarintFrameDecoder extends ByteToMessageDecoder { } private boolean validateServerboundHandshakePacket(ByteBuf in, int length) throws Exception { - StateRegistry.PacketRegistry.ProtocolRegistry registry = - state.getProtocolRegistry(direction, ProtocolVersion.MINIMUM_VERSION); - final int index = in.readerIndex(); final int packetId = readRawVarInt21(in); // Index hasn't changed, we've read nothing @@ -130,8 +128,8 @@ public class MinecraftVarintFrameDecoder extends ByteToMessageDecoder { // We 'technically' have the incoming bytes of a payload here, and so, these can actually parse // the packet if needed, so, we'll take advantage of the existing methods - int expectedMinLen = codec.decodeExpectedMinLength(in, direction, registry.version); - int expectedMaxLen = codec.decodeExpectedMaxLength(in, direction, registry.version); + int expectedMinLen = codec.decodeExpectedMinLength(in, direction, ProtocolVersion.MINIMUM_VERSION); + int expectedMaxLen = codec.decodeExpectedMaxLength(in, direction, ProtocolVersion.MINIMUM_VERSION); if (expectedMaxLen != -1 && payloadLength > expectedMaxLen) { throw handleOverflow(expectedMaxLen, in.readableBytes()); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/PlayPacketQueueInboundHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/PlayPacketQueueInboundHandler.java index 1affc13bc..5d76d6eba 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/PlayPacketQueueInboundHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/PlayPacketQueueInboundHandler.java @@ -19,8 +19,9 @@ package com.velocitypowered.proxy.protocol.netty; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.protocol.MinecraftPacket; +import com.velocitypowered.proxy.protocol.ProtocolStates; import com.velocitypowered.proxy.protocol.ProtocolUtils; -import com.velocitypowered.proxy.protocol.StateRegistry; +import com.velocitypowered.proxy.protocol.registry.PacketRegistry; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.util.ReferenceCountUtil; @@ -41,7 +42,7 @@ import org.jetbrains.annotations.NotNull; */ public class PlayPacketQueueInboundHandler extends ChannelDuplexHandler { - private final StateRegistry.PacketRegistry.ProtocolRegistry registry; + private final PacketRegistry registry; private final Queue queue = new ArrayDeque<>(); /** @@ -50,7 +51,7 @@ public class PlayPacketQueueInboundHandler extends ChannelDuplexHandler { * @param version the protocol version */ public PlayPacketQueueInboundHandler(ProtocolVersion version, ProtocolUtils.Direction direction) { - this.registry = StateRegistry.CONFIG.getProtocolRegistry(direction, version); + this.registry = ProtocolStates.configuration(direction).forVersion(version); } @Override @@ -58,7 +59,7 @@ public class PlayPacketQueueInboundHandler extends ChannelDuplexHandler { if (msg instanceof final MinecraftPacket packet) { // If the packet exists in the CONFIG state, we want to always // ensure that it gets handled by the current handler - if (this.registry.containsPacket(packet)) { + if (this.registry.canDecodePacket(packet)) { ctx.fireChannelRead(msg); return; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/PlayPacketQueueOutboundHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/PlayPacketQueueOutboundHandler.java index c57271040..14f23c7a8 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/PlayPacketQueueOutboundHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/PlayPacketQueueOutboundHandler.java @@ -19,8 +19,9 @@ package com.velocitypowered.proxy.protocol.netty; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.protocol.MinecraftPacket; +import com.velocitypowered.proxy.protocol.ProtocolStates; import com.velocitypowered.proxy.protocol.ProtocolUtils; -import com.velocitypowered.proxy.protocol.StateRegistry; +import com.velocitypowered.proxy.protocol.registry.PacketRegistry; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; @@ -42,7 +43,7 @@ import org.jetbrains.annotations.NotNull; */ public class PlayPacketQueueOutboundHandler extends ChannelDuplexHandler { - private final StateRegistry.PacketRegistry.ProtocolRegistry registry; + private final PacketRegistry registry; private final Queue queue = new ArrayDeque<>(); /** @@ -51,7 +52,7 @@ public class PlayPacketQueueOutboundHandler extends ChannelDuplexHandler { * @param version the protocol version */ public PlayPacketQueueOutboundHandler(ProtocolVersion version, ProtocolUtils.Direction direction) { - this.registry = StateRegistry.CONFIG.getProtocolRegistry(direction, version); + this.registry = ProtocolStates.configuration(direction).forVersion(version); } @Override @@ -63,7 +64,7 @@ public class PlayPacketQueueOutboundHandler extends ChannelDuplexHandler { // If the packet exists in the CONFIG state, we want to always // ensure that it gets sent out to the client - if (this.registry.containsPacket(packet)) { + if (this.registry.canDecodePacket(packet)) { ctx.write(msg, promise); return; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/AvailableCommandsPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/AvailableCommandsPacket.java index abe70d7e0..d03a95f1d 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/AvailableCommandsPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/AvailableCommandsPacket.java @@ -86,6 +86,8 @@ public final class AvailableCommandsPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public AvailableCommandsPacket decode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/BossBarPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/BossBarPacket.java index b20dccddf..103d35cb0 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/BossBarPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/BossBarPacket.java @@ -122,6 +122,8 @@ public record BossBarPacket(UUID uuid, int action, @Nullable ComponentHolder nam } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public BossBarPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/BundleDelimiterPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/BundleDelimiterPacket.java index 51339cf8c..6e110d45b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/BundleDelimiterPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/BundleDelimiterPacket.java @@ -36,10 +36,12 @@ public final class BundleDelimiterPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public BundleDelimiterPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { - return INSTANCE; + return BundleDelimiterPacket.INSTANCE; } @Override 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 91bed4cc0..5d8f17ba0 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 @@ -141,6 +141,8 @@ public final class ClientSettingsPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public ClientSettingsPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundCookieRequestPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundCookieRequestPacket.java index a6a9fd33d..82368d7fa 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundCookieRequestPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundCookieRequestPacket.java @@ -38,6 +38,8 @@ public record ClientboundCookieRequestPacket(Key key) implements MinecraftPacket } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public ClientboundCookieRequestPacket decode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundSoundEntityPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundSoundEntityPacket.java index daa34a3e8..2abfabb9f 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundSoundEntityPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundSoundEntityPacket.java @@ -37,6 +37,8 @@ public record ClientboundSoundEntityPacket(Sound sound, @Nullable Float fixedRan } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public ClientboundSoundEntityPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundStopSoundPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundStopSoundPacket.java index 8ebc46b48..9d85af827 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundStopSoundPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundStopSoundPacket.java @@ -42,6 +42,8 @@ public record ClientboundStopSoundPacket(@Nullable Sound.Source source, } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public ClientboundStopSoundPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundStoreCookiePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundStoreCookiePacket.java index 47c3bf9c6..a071ddbf7 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundStoreCookiePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundStoreCookiePacket.java @@ -34,6 +34,8 @@ public record ClientboundStoreCookiePacket(Key key, byte[] payload) implements M } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public ClientboundStoreCookiePacket decode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/DialogClearPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/DialogClearPacket.java index 8103ccdb2..0f06acc24 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/DialogClearPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/DialogClearPacket.java @@ -37,10 +37,12 @@ public final class DialogClearPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public DialogClearPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { - return INSTANCE; + return DialogClearPacket.INSTANCE; } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionRequestPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionRequestPacket.java index bb15ef366..5a4ea974b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionRequestPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionRequestPacket.java @@ -79,6 +79,8 @@ public final class EncryptionRequestPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public EncryptionRequestPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionResponsePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionResponsePacket.java index ccadb397a..8566982bf 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionResponsePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionResponsePacket.java @@ -85,6 +85,8 @@ public final class EncryptionResponsePacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public EncryptionResponsePacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/HandshakePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/HandshakePacket.java index 38abc1999..9fd1943bb 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/HandshakePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/HandshakePacket.java @@ -104,6 +104,8 @@ public final class HandshakePacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public HandshakePacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion ignored) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/HeaderAndFooterPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/HeaderAndFooterPacket.java index 619fed85e..c184ec996 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/HeaderAndFooterPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/HeaderAndFooterPacket.java @@ -52,6 +52,8 @@ public record HeaderAndFooterPacket(ComponentHolder header, } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public HeaderAndFooterPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { 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 cfaa46524..80f170ce7 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 @@ -196,6 +196,8 @@ public final class JoinGamePacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public JoinGamePacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/KeepAlivePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/KeepAlivePacket.java index d514b1a01..a24668a4b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/KeepAlivePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/KeepAlivePacket.java @@ -43,6 +43,8 @@ public record KeepAlivePacket(long randomId) implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public KeepAlivePacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyHandshakePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyHandshakePacket.java index 4dfbfbb81..bfc793c6b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyHandshakePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyHandshakePacket.java @@ -37,6 +37,8 @@ public final class LegacyHandshakePacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public LegacyHandshakePacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyPingPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyPingPacket.java index 145af5125..ee1e10ca8 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyPingPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyPingPacket.java @@ -64,6 +64,8 @@ public final class LegacyPingPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public LegacyPingPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyPlayerListItemPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyPlayerListItemPacket.java index f972c0b3c..3bfe5db63 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyPlayerListItemPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyPlayerListItemPacket.java @@ -64,6 +64,8 @@ public final class LegacyPlayerListItemPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public LegacyPlayerListItemPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginAcknowledgedPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginAcknowledgedPacket.java index a2ed268ad..a40f3c332 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginAcknowledgedPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginAcknowledgedPacket.java @@ -37,10 +37,12 @@ public final class LoginAcknowledgedPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public LoginAcknowledgedPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { - return INSTANCE; + return LoginAcknowledgedPacket.INSTANCE; } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginPluginMessagePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginPluginMessagePacket.java index c788311cc..fafd6f0e5 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginPluginMessagePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginPluginMessagePacket.java @@ -61,6 +61,8 @@ public final class LoginPluginMessagePacket extends DefaultByteBufHolder impleme } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public LoginPluginMessagePacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginPluginResponsePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginPluginResponsePacket.java index bc3b273c0..ba4b520ea 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginPluginResponsePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginPluginResponsePacket.java @@ -70,6 +70,8 @@ public final class LoginPluginResponsePacket extends DefaultByteBufHolder } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public LoginPluginResponsePacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PingIdentifyPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PingIdentifyPacket.java index ca621716f..6b01a1503 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PingIdentifyPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PingIdentifyPacket.java @@ -32,6 +32,8 @@ public record PingIdentifyPacket(int id) implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public PingIdentifyPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PluginMessagePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PluginMessagePacket.java index 50da2b91a..dca6cd003 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PluginMessagePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PluginMessagePacket.java @@ -94,6 +94,8 @@ public final class PluginMessagePacket extends DefaultByteBufHolder implements M } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public PluginMessagePacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RemovePlayerInfoPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RemovePlayerInfoPacket.java index 4c8c8402a..a2a97f928 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RemovePlayerInfoPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RemovePlayerInfoPacket.java @@ -39,6 +39,8 @@ public record RemovePlayerInfoPacket(Collection profilesToRemove) implemen } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public RemovePlayerInfoPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RemoveResourcePackPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RemoveResourcePackPacket.java index dcde828b0..3bd41e874 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RemoveResourcePackPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RemoveResourcePackPacket.java @@ -39,6 +39,8 @@ public record RemoveResourcePackPacket(@Nullable UUID id) implements MinecraftPa } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public RemoveResourcePackPacket decode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackRequestPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackRequestPacket.java index 3a782d3d6..eb2aaf3dc 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackRequestPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackRequestPacket.java @@ -103,6 +103,8 @@ public final class ResourcePackRequestPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public ResourcePackRequestPacket decode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackResponsePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackResponsePacket.java index 3b6ec2552..5fc3b664d 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackResponsePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackResponsePacket.java @@ -49,6 +49,8 @@ public record ResourcePackResponsePacket(UUID id, String hash, } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public ResourcePackResponsePacket decode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) { 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 be47bdcda..7293a794a 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 @@ -151,6 +151,8 @@ public final class RespawnPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public RespawnPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerDataPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerDataPacket.java index ab54ec44d..cb058b26e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerDataPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerDataPacket.java @@ -61,6 +61,8 @@ public final class ServerDataPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public ServerDataPacket decode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginPacket.java index 1a9ed47af..334497830 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginPacket.java @@ -83,6 +83,8 @@ public final class ServerLoginPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public ServerLoginPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginSuccessPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginSuccessPacket.java index ae395e317..db300a5f2 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginSuccessPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginSuccessPacket.java @@ -71,6 +71,8 @@ public final class ServerLoginSuccessPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public ServerLoginSuccessPacket decode(ByteBuf buf, Direction direction, ProtocolVersion version) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerboundCookieResponsePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerboundCookieResponsePacket.java index 32beeccb2..0eae56d52 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerboundCookieResponsePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerboundCookieResponsePacket.java @@ -44,6 +44,8 @@ public record ServerboundCookieResponsePacket(Key key, } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public ServerboundCookieResponsePacket decode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerboundCustomClickActionPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerboundCustomClickActionPacket.java index 9eb434e36..a32236748 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerboundCustomClickActionPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerboundCustomClickActionPacket.java @@ -79,6 +79,8 @@ public class ServerboundCustomClickActionPacket extends DefaultByteBufHolder } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public ServerboundCustomClickActionPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/SetCompressionPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/SetCompressionPacket.java index 53bedf8ea..3c057251c 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/SetCompressionPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/SetCompressionPacket.java @@ -43,6 +43,8 @@ public record SetCompressionPacket(int threshold) implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public SetCompressionPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusPingPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusPingPacket.java index 9b49d914d..9aa34961b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusPingPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusPingPacket.java @@ -33,6 +33,8 @@ public record StatusPingPacket(long randomId) implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public StatusPingPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusRequestPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusRequestPacket.java index ab3fe1f77..6dfef9376 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusRequestPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusRequestPacket.java @@ -43,10 +43,12 @@ public final class StatusRequestPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public StatusRequestPacket decode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) { - return INSTANCE; + return StatusRequestPacket.INSTANCE; } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusResponsePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusResponsePacket.java index 2e9836442..bf66f94d0 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusResponsePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusResponsePacket.java @@ -57,6 +57,8 @@ public final class StatusResponsePacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public StatusResponsePacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TabCompleteRequestPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TabCompleteRequestPacket.java index 202e7c466..86de169a9 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TabCompleteRequestPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TabCompleteRequestPacket.java @@ -89,6 +89,8 @@ public final class TabCompleteRequestPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public TabCompleteRequestPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TabCompleteResponsePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TabCompleteResponsePacket.java index f263af2b0..b4de69fb3 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TabCompleteResponsePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TabCompleteResponsePacket.java @@ -97,6 +97,8 @@ public final class TabCompleteResponsePacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public TabCompleteResponsePacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TransferPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TransferPacket.java index c8b468c75..d9f83c7c5 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TransferPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TransferPacket.java @@ -50,6 +50,8 @@ public record TransferPacket(String host, int port) implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public TransferPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { 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 9f829d6bf..c44010aed 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 @@ -64,6 +64,8 @@ public final class UpsertPlayerInfoPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public UpsertPlayerInfoPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatAcknowledgementPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatAcknowledgementPacket.java index 0fd6e2525..7c458bbcd 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatAcknowledgementPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatAcknowledgementPacket.java @@ -39,6 +39,8 @@ public record ChatAcknowledgementPacket(int offset) implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public ChatAcknowledgementPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/PlayerChatCompletionPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/PlayerChatCompletionPacket.java index 2a793453f..4d6ea1627 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/PlayerChatCompletionPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/PlayerChatCompletionPacket.java @@ -58,6 +58,8 @@ public final class PlayerChatCompletionPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public PlayerChatCompletionPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/SystemChatPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/SystemChatPacket.java index efe480950..bf66ffca7 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/SystemChatPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/SystemChatPacket.java @@ -60,6 +60,8 @@ public final class SystemChatPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public SystemChatPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedPlayerChatPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedPlayerChatPacket.java index 84378c0e3..68d044fd5 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedPlayerChatPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedPlayerChatPacket.java @@ -81,6 +81,8 @@ public final class KeyedPlayerChatPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public KeyedPlayerChatPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedPlayerCommandPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedPlayerCommandPacket.java index c4e4deb73..06eb9b9af 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedPlayerCommandPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedPlayerCommandPacket.java @@ -95,6 +95,8 @@ public final class KeyedPlayerCommandPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public KeyedPlayerCommandPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyChatPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyChatPacket.java index fed490bc4..8469b7059 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyChatPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyChatPacket.java @@ -45,6 +45,8 @@ public record LegacyChatPacket(String message, byte type, @Nullable UUID sender) } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public LegacyChatPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionPlayerChatPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionPlayerChatPacket.java index 14556afca..8e226f7c0 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionPlayerChatPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionPlayerChatPacket.java @@ -85,6 +85,8 @@ public class SessionPlayerChatPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public SessionPlayerChatPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionPlayerCommandPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionPlayerCommandPacket.java index 988d68dcb..94af39b0f 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionPlayerCommandPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionPlayerCommandPacket.java @@ -89,6 +89,8 @@ public class SessionPlayerCommandPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public SessionPlayerCommandPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/UnsignedPlayerCommandPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/UnsignedPlayerCommandPacket.java index ccc0b9b1b..7948c7c8e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/UnsignedPlayerCommandPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/UnsignedPlayerCommandPacket.java @@ -56,6 +56,8 @@ public final class UnsignedPlayerCommandPacket extends SessionPlayerCommandPacke } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public UnsignedPlayerCommandPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ActiveFeaturesPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ActiveFeaturesPacket.java index f7290ecac..53c2a2417 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ActiveFeaturesPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ActiveFeaturesPacket.java @@ -41,6 +41,8 @@ public record ActiveFeaturesPacket(Key[] activeFeatures) implements MinecraftPac } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public ActiveFeaturesPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ClientboundCustomReportDetailsPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ClientboundCustomReportDetailsPacket.java index 4820da37d..1410380b7 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ClientboundCustomReportDetailsPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ClientboundCustomReportDetailsPacket.java @@ -28,16 +28,14 @@ import java.util.Map; public record ClientboundCustomReportDetailsPacket(Map details) implements MinecraftPacket { - public ClientboundCustomReportDetailsPacket() { - this(Map.of()); - } - @Override public boolean handle(MinecraftSessionHandler handler) { return handler.handle(this); } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public ClientboundCustomReportDetailsPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ClientboundServerLinksPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ClientboundServerLinksPacket.java index 1c0619027..1a0229acc 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ClientboundServerLinksPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ClientboundServerLinksPacket.java @@ -62,6 +62,8 @@ public record ClientboundServerLinksPacket(List serverLinks) impleme } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public ClientboundServerLinksPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { 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 index 9b290c163..9f1b59ec3 100644 --- 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 @@ -37,10 +37,12 @@ public final class CodeOfConductAcceptPacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public CodeOfConductAcceptPacket decode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) { - return INSTANCE; + return CodeOfConductAcceptPacket.INSTANCE; } @Override 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 index 8cd632dbd..e9e2cbb44 100644 --- 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 @@ -77,6 +77,8 @@ public class CodeOfConductPacket extends DefaultByteBufHolder implements Minecra } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public CodeOfConductPacket decode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) { return new CodeOfConductPacket(buf.readRetainedSlice(buf.readableBytes())); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/FinishedUpdatePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/FinishedUpdatePacket.java index e356d17e0..c2f7faff5 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/FinishedUpdatePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/FinishedUpdatePacket.java @@ -36,10 +36,12 @@ public final class FinishedUpdatePacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public FinishedUpdatePacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { - return INSTANCE; + return FinishedUpdatePacket.INSTANCE; } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/KnownPacksPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/KnownPacksPacket.java index 780b43b04..5be96c225 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/KnownPacksPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/KnownPacksPacket.java @@ -49,6 +49,8 @@ public record KnownPacksPacket(KnownPack[] packs) implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + private static final int MAX_LENGTH_PACKS = Integer.getInteger("velocity.max-known-packs", 64); private static final QuietDecoderException TOO_MANY_PACKS = new QuietDecoderException("too many known packs"); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/RegistrySyncPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/RegistrySyncPacket.java index 6dc6c52ed..945f085a9 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/RegistrySyncPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/RegistrySyncPacket.java @@ -42,6 +42,8 @@ public final class RegistrySyncPacket extends DefaultByteBufHolder implements Mi } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public RegistrySyncPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/StartUpdatePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/StartUpdatePacket.java index 33067ea06..f1b8825d3 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/StartUpdatePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/StartUpdatePacket.java @@ -36,10 +36,12 @@ public final class StartUpdatePacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public StartUpdatePacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { - return INSTANCE; + return StartUpdatePacket.INSTANCE; } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/TagsUpdatePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/TagsUpdatePacket.java index 677533cd9..1520296f7 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/TagsUpdatePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/TagsUpdatePacket.java @@ -46,6 +46,8 @@ public final class TagsUpdatePacket implements MinecraftPacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public TagsUpdatePacket decode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) { 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 index 889933145..fcdc14af3 100644 --- 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 @@ -78,6 +78,8 @@ public final class LegacyTitlePacket extends GenericTitlePacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public LegacyTitlePacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { 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 index 464e9afc3..4ed5771d7 100644 --- 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 @@ -51,6 +51,8 @@ public final class TitleActionbarPacket extends GenericTitlePacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public TitleActionbarPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { 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 f29422b6b..c343f1f39 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 @@ -49,6 +49,8 @@ public final class TitleClearPacket extends GenericTitlePacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public TitleClearPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { 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 index 95d950224..5914c1dfc 100644 --- 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 @@ -51,6 +51,8 @@ public final class TitleSubtitlePacket extends GenericTitlePacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public TitleSubtitlePacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { 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 index 3e6a960f4..7ec462da5 100644 --- 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 @@ -51,6 +51,8 @@ public final class TitleTextPacket extends GenericTitlePacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public TitleTextPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { 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 index 69764e767..81294deb5 100644 --- 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 @@ -66,6 +66,8 @@ public final class TitleTimesPacket extends GenericTitlePacket { } public static class Codec implements PacketCodec { + public static final Codec INSTANCE = new Codec(); + @Override public TitleTimesPacket decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/registry/MultiVersionPacketRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/registry/MultiVersionPacketRegistry.java new file mode 100644 index 000000000..448d41778 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/registry/MultiVersionPacketRegistry.java @@ -0,0 +1,376 @@ +/* + * Copyright (C) 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.registry; + +import com.velocitypowered.api.network.ProtocolVersion; +import com.velocitypowered.proxy.protocol.MinecraftPacket; +import com.velocitypowered.proxy.protocol.PacketCodec; +import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction; +import io.netty.util.collection.IntObjectHashMap; +import io.netty.util.collection.IntObjectMap; +import it.unimi.dsi.fastutil.Hash.Strategy; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; +import java.util.Collections; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import org.checkerframework.checker.nullness.qual.Nullable; + +/** + * A multi-version packet registry that supports different packet ID mappings across protocol + * versions. This implementation optimizes memory usage by reusing mapping data structures across + * versions when the mappings are identical. + */ +public class MultiVersionPacketRegistry implements ProtocolToPacketRegistry { + + private final Map versionMappings; + + private MultiVersionPacketRegistry( + Map versionMappings) { + this.versionMappings = versionMappings; + } + + @Override + public PacketRegistry forVersion(ProtocolVersion version) { + VersionMapping mapping = this.versionMappings.get(version); + if (mapping == null) { + throw new IllegalArgumentException(String.format("Invalid version %s", version)); + } + return mapping; + } + + /** + * Holds the packet mappings for a specific protocol version or a range of versions. + * Instances are shared across versions when the mappings are identical. + */ + private static class VersionMapping implements PacketRegistry { + + final IntObjectMap> packetIdToCodec; + final Map, PacketCodec> + packetClassToCodec; + final Object2IntMap> packetClassToId; + final Direction direction; + final ProtocolVersion version; + + VersionMapping(Direction direction, ProtocolVersion version) { + this.direction = direction; + this.version = version; + this.packetIdToCodec = new IntObjectHashMap<>(16, 0.5f); + this.packetClassToCodec = new HashMap<>(16, 0.5f); + this.packetClassToId = new Object2IntOpenHashMap<>(16, 0.5f); + this.packetClassToId.defaultReturnValue(Integer.MIN_VALUE); + } + + void register(int id, Class packet, + PacketCodec codec, boolean encodeOnly) { + if (!encodeOnly) { + this.packetIdToCodec.put(id, codec); + } + this.packetClassToCodec.put(packet, codec); + this.packetClassToId.put(packet, id); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + VersionMapping that = (VersionMapping) o; + return Objects.equals(packetIdToCodec, that.packetIdToCodec) + && Objects.equals(packetClassToCodec, that.packetClassToCodec) + && Objects.equals(packetClassToId, that.packetClassToId) + && Objects.equals(direction, that.direction) + && Objects.equals(version, that.version); + } + + public boolean equalsNonStrict(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + VersionMapping that = (VersionMapping) o; + return Objects.equals(packetIdToCodec, that.packetIdToCodec) + && Objects.equals(packetClassToCodec, that.packetClassToCodec) + && Objects.equals(packetClassToId, that.packetClassToId); + } + + @Override + public int hashCode() { + return Objects.hash(packetIdToCodec, packetClassToCodec, packetClassToId, direction, version); + } + + public int hashCodeNonStrict() { + return Objects.hash(packetIdToCodec, packetClassToCodec, packetClassToId); + } + + @Override + public @Nullable PacketCodec getCodec(int id) { + return packetIdToCodec.get(id); + } + + @Override + @SuppressWarnings("unchecked") + public @Nullable PacketCodec getCodec(Class packetClass) { + return (PacketCodec) packetClassToCodec.get(packetClass); + } + + @Override + public int getPacketId(MinecraftPacket packet) { + final int id = packetClassToId.getInt(packet.getClass()); + if (id == Integer.MIN_VALUE) { + throw new IllegalArgumentException(String.format( + "Unable to find id for packet of type %s in %s protocol %s", + packet.getClass().getName(), direction, version + )); + } + return id; + } + + @Override + public boolean canDecodePacket(MinecraftPacket packet) { + return packetClassToId.containsKey(packet.getClass()); + } + } + + /** + * Creates a new builder for constructing a multi-version packet registry. + * + * @param direction the packet direction (clientbound or serverbound) + * @return a new builder instance + */ + public static Builder builder(Direction direction) { + return new Builder(direction); + } + + /** + * Builder for constructing a MultiVersionPacketRegistry with optimized memory usage. + */ + public static class Builder { + + private final Direction direction; + private final Map workingMappings = + new EnumMap<>(ProtocolVersion.class); + + private Builder(Direction direction) { + this.direction = direction; + } + + /** + * Registers a packet for a specific protocol version with a given ID. + * + * @param packetClass the packet class + * @param codec the packet codec + * @param version the protocol version + * @param packetId the packet ID + * @param the packet type + * @return this builder + */ + public Builder register( + Class packetClass, + PacketCodec codec, + ProtocolVersion version, + int packetId) { + return register(packetClass, codec, version, null, packetId, false); + } + + /** + * Registers a packet for a range of protocol versions with a given ID. + * + * @param packetClass the packet class + * @param codec the packet codec + * @param startVersion the starting protocol version (inclusive) + * @param endVersion the ending protocol version (inclusive), or null for all future versions + * @param packetId the packet ID + * @param encodeOnly if true, the packet will only be registered for encoding, not decoding + * @param the packet type + * @return this builder + */ + public Builder register( + Class packetClass, + PacketCodec codec, + ProtocolVersion startVersion, + @Nullable ProtocolVersion endVersion, + int packetId, + boolean encodeOnly) { + + ProtocolVersion end = endVersion != null ? endVersion : ProtocolVersion.MAXIMUM_VERSION; + + // Validate version range + if (startVersion.greaterThan(end)) { + throw new IllegalArgumentException(String.format( + "Start version %s is greater than end version %s", startVersion, end + )); + } + + // Register for all versions in the range + for (ProtocolVersion version : ProtocolVersion.values()) { + if (version.isLegacy() || version.isUnknown()) { + continue; + } + if (version.noLessThan(startVersion) && version.noGreaterThan(end)) { + VersionMapping versionMapping = workingMappings.computeIfAbsent(version, v -> new VersionMapping(direction, version)); + if (versionMapping.packetClassToCodec.containsKey(packetClass)) { + throw new IllegalArgumentException(String.format( + "Packet %s already registered for version %s", packetClass.getName(), version + )); + } + versionMapping.register(packetId, packetClass, codec, encodeOnly); + } + } + + return this; + } + + /** + * Registers a packet for multiple version ranges. + * + * @param packetClass the packet class + * @param codec the packet codec + * @param ranges the version ranges to register + * @param the packet type + * @return this builder + */ + public Builder register( + Class packetClass, + PacketCodec codec, + VersionRange... ranges) { + if (ranges.length == 0) { + throw new IllegalArgumentException("At least one version range must be provided"); + } + for (VersionRange range : ranges) { + register(packetClass, codec, range.start, range.end, range.packetId, range.encodeOnly); + } + return this; + } + + /** + * Builds the multi-version packet registry, optimizing memory by reusing identical mappings + * across versions. + * + * @return the constructed registry + */ + public MultiVersionPacketRegistry build() { + // Optimize by reusing identical mappings across versions + Map optimized = new EnumMap<>(ProtocolVersion.class); + Map deduplicationMap = new Object2ObjectOpenCustomHashMap<>( + new Strategy<>() { + @Override + public int hashCode(VersionMapping o) { + return o.hashCodeNonStrict(); + } + + @Override + public boolean equals(VersionMapping a, VersionMapping b) { + return a.equalsNonStrict(b); + } + }); + + for (Map.Entry entry : workingMappings.entrySet()) { + VersionMapping mapping = entry.getValue(); + VersionMapping canonical = deduplicationMap.get(mapping); + if (canonical == null) { + // First time seeing this mapping, use it as the canonical version + deduplicationMap.put(mapping, mapping); + canonical = mapping; + } + // Reuse the canonical mapping + optimized.put(entry.getKey(), canonical); + } + + return new MultiVersionPacketRegistry(Collections.unmodifiableMap(optimized)); + } + } + + /** + * Represents a version range for packet registration. + */ + public static class VersionRange { + + final ProtocolVersion start; + final @Nullable ProtocolVersion end; + final int packetId; + final boolean encodeOnly; + + private VersionRange( + ProtocolVersion start, + @Nullable ProtocolVersion end, + int packetId, + boolean encodeOnly) { + this.start = start; + this.end = end; + this.packetId = packetId; + this.encodeOnly = encodeOnly; + } + + /** + * Creates a version range starting from the specified version and continuing to all future + * versions. + * + * @param start the starting version + * @param packetId the packet ID + * @return a new version range + */ + public static VersionRange of(ProtocolVersion start, int packetId) { + return new VersionRange(start, null, packetId, false); + } + + /** + * Creates a version range from start to end (inclusive). + * + * @param start the starting version + * @param end the ending version + * @param packetId the packet ID + * @return a new version range + */ + public static VersionRange of(ProtocolVersion start, ProtocolVersion end, int packetId) { + return new VersionRange(start, end, packetId, false); + } + + /** + * Creates an encode-only version range starting from the specified version. + * + * @param start the starting version + * @param packetId the packet ID + * @return a new version range + */ + public static VersionRange encodeOnly(ProtocolVersion start, int packetId) { + return new VersionRange(start, null, packetId, true); + } + + /** + * Creates an encode-only version range from start to end (inclusive). + * + * @param start the starting version + * @param end the ending version + * @param packetId the packet ID + * @return a new version range + */ + public static VersionRange encodeOnly( + ProtocolVersion start, ProtocolVersion end, int packetId) { + return new VersionRange(start, end, packetId, true); + } + } +} \ No newline at end of file diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/registry/PacketRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/registry/PacketRegistry.java new file mode 100644 index 000000000..b9034d8bd --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/registry/PacketRegistry.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 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.registry; + +import com.velocitypowered.proxy.protocol.MinecraftPacket; +import com.velocitypowered.proxy.protocol.PacketCodec; +import org.checkerframework.checker.nullness.qual.Nullable; + +/** + * Interface for retrieving packet codecs and IDs for a specific protocol version. + */ +public interface PacketRegistry { + @Nullable + PacketCodec getCodec(final int id); + + @Nullable PacketCodec getCodec( + final Class packetClass); + + int getPacketId(final MinecraftPacket packet); + + boolean canDecodePacket(MinecraftPacket packet); +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/registry/ProtocolToPacketRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/registry/ProtocolToPacketRegistry.java new file mode 100644 index 000000000..85282a7bb --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/registry/ProtocolToPacketRegistry.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 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.registry; + +import com.velocitypowered.api.network.ProtocolVersion; + +/** + * Registry mapping protocol versions to their packet registries. + */ +public interface ProtocolToPacketRegistry { + PacketRegistry forVersion(ProtocolVersion version); +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/registry/SimplePacketRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/registry/SimplePacketRegistry.java new file mode 100644 index 000000000..eb20f205e --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/registry/SimplePacketRegistry.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 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.registry; + +import com.velocitypowered.api.network.ProtocolVersion; +import com.velocitypowered.proxy.protocol.MinecraftPacket; +import com.velocitypowered.proxy.protocol.PacketCodec; +import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction; +import io.netty.util.collection.IntObjectHashMap; +import io.netty.util.collection.IntObjectMap; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import java.util.HashMap; +import java.util.Map; +import org.checkerframework.checker.nullness.qual.Nullable; + +/** + * Extremely simple packet registry implementation that assumes every protocol version is + * the same. + */ +public class SimplePacketRegistry implements PacketRegistry, ProtocolToPacketRegistry { + private final IntObjectMap> packetIdToCodec = + new IntObjectHashMap<>(16, 0.5f); + private final Map, PacketCodec> packetClassToCodec = + new HashMap<>(16, 0.5f); + private final Object2IntMap> packetClassToId = + new Object2IntOpenHashMap<>(16, 0.5f); + private final Direction direction; + + public SimplePacketRegistry(Direction direction) { + this.direction = direction; + this.packetClassToId.defaultReturnValue(Integer.MIN_VALUE); + } + + /** + * Registers a packet for this protocol version. + * + * @param id the packet ID + * @param packet the packet class + * @param codec the packet codec + */ + public void register(int id, Class packet, PacketCodec codec) { + this.packetIdToCodec.put(id, codec); + this.packetClassToCodec.put(packet, codec); + this.packetClassToId.put(packet, id); + } + + @Override + public @Nullable PacketCodec getCodec(int id) { + return this.packetIdToCodec.get(id); + } + + @Override + public @Nullable PacketCodec getCodec(Class packetClass) { + return (PacketCodec) this.packetClassToCodec.get(packetClass); + } + + @Override + public int getPacketId(MinecraftPacket packet) { + final int id = this.packetClassToId.getInt(packet.getClass()); + if (id == Integer.MIN_VALUE) { + throw new IllegalArgumentException(String.format( + "Unable to find id for packet of type %s in %s phase %s", + packet.getClass().getName(), direction, this + )); + } + return id; + } + + @Override + public boolean canDecodePacket(MinecraftPacket packet) { + return packetClassToId.containsKey(packet.getClass()); + } + + @Override + public PacketRegistry forVersion(ProtocolVersion version) { + return 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 cedcc1e8e..6ccfd4ec9 100644 --- a/proxy/src/test/java/com/velocitypowered/proxy/protocol/PacketRegistryTest.java +++ b/proxy/src/test/java/com/velocitypowered/proxy/protocol/PacketRegistryTest.java @@ -18,6 +18,7 @@ package com.velocitypowered.proxy.protocol; import static com.google.common.collect.Iterables.getLast; +import static com.velocitypowered.api.network.ProtocolVersion.MAXIMUM_VERSION; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_11; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_12; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_12_1; @@ -25,136 +26,414 @@ 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_14_4; 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; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.protocol.packet.HandshakePacket; import com.velocitypowered.proxy.protocol.packet.StatusPingPacket; +import com.velocitypowered.proxy.protocol.registry.MultiVersionPacketRegistry; +import com.velocitypowered.proxy.protocol.registry.MultiVersionPacketRegistry.VersionRange; +import com.velocitypowered.proxy.protocol.registry.SimplePacketRegistry; import org.junit.jupiter.api.Test; class PacketRegistryTest { - private StateRegistry.PacketRegistry setupRegistry() { - StateRegistry.PacketRegistry registry = new StateRegistry.PacketRegistry( - ProtocolUtils.Direction.CLIENTBOUND, StateRegistry.PLAY); - registry.register(HandshakePacket.class, new HandshakePacket.Codec(), - 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; + /** + * Sets up a multi-version registry with HandshakePacket mapped to different IDs across version + * ranges. + */ + private MultiVersionPacketRegistry setupRegistry() { + return MultiVersionPacketRegistry.builder(ProtocolUtils.Direction.CLIENTBOUND) + .register(HandshakePacket.class, new HandshakePacket.Codec(), + VersionRange.of(MINECRAFT_1_8, MINECRAFT_1_11, 0x01), + VersionRange.of(MINECRAFT_1_12, MINECRAFT_1_14_4, 0x00), + VersionRange.of(MINECRAFT_1_15, MAXIMUM_VERSION, 0x00)) + .build(); } + // ==================== Basic Functionality Tests ==================== + @Test void packetRegistryWorks() { - StateRegistry.PacketRegistry registry = setupRegistry(); - PacketCodec packet = registry.getProtocolRegistry(MINECRAFT_1_12).getCodec(0); + MultiVersionPacketRegistry registry = setupRegistry(); + PacketCodec packet = registry.forVersion(MINECRAFT_1_12).getCodec(0); assertNotNull(packet, "Packet was not found in registry"); assertEquals(HandshakePacket.Codec.class, packet.getClass(), "Registry returned wrong class"); - assertEquals(0, registry.getProtocolRegistry(MINECRAFT_1_12).getPacketId(new HandshakePacket()), + assertEquals(0, registry.forVersion(MINECRAFT_1_12).getPacketId(new HandshakePacket()), "Registry did not return the correct packet ID"); } @Test void packetRegistryLinkingWorks() { - StateRegistry.PacketRegistry registry = setupRegistry(); - PacketCodec packet = registry.getProtocolRegistry(MINECRAFT_1_12_1).getCodec(0); + MultiVersionPacketRegistry registry = setupRegistry(); + PacketCodec packet = registry.forVersion(MINECRAFT_1_12_1).getCodec(0); assertNotNull(packet, "Packet was not found in registry"); assertEquals(HandshakePacket.Codec.class, packet.getClass(), "Registry returned wrong class"); HandshakePacket handshakePacket = new HandshakePacket(); - assertEquals(0, registry.getProtocolRegistry(MINECRAFT_1_12_1).getPacketId(handshakePacket), + assertEquals(0, registry.forVersion(MINECRAFT_1_12_1).getPacketId(handshakePacket), "Registry did not return the correct packet ID"); - assertEquals(0, registry.getProtocolRegistry(MINECRAFT_1_14_2).getPacketId(handshakePacket), + assertEquals(0, registry.forVersion(MINECRAFT_1_14_2).getPacketId(handshakePacket), "Registry did not return the correct packet ID"); - assertEquals(1, registry.getProtocolRegistry(MINECRAFT_1_11).getPacketId(handshakePacket), + assertEquals(1, registry.forVersion(MINECRAFT_1_11).getPacketId(handshakePacket), "Registry did not return the correct packet ID"); - assertNull(registry.getProtocolRegistry(MINECRAFT_1_14_2).getCodec(0x01), + assertNull(registry.forVersion(MINECRAFT_1_14_2).getCodec(0x01), "Registry should return a null"); - assertNull(registry.getProtocolRegistry(MINECRAFT_1_16_2).getCodec(0), - "Registry should return null"); - } - - @Test - void failOnNoMappings() { - StateRegistry.PacketRegistry registry = new StateRegistry.PacketRegistry( - ProtocolUtils.Direction.CLIENTBOUND, StateRegistry.PLAY); - assertThrows(IllegalArgumentException.class, - () -> registry.register(HandshakePacket.class, new HandshakePacket.Codec())); - assertThrows(IllegalArgumentException.class, - () -> registry.getProtocolRegistry(ProtocolVersion.UNKNOWN) - .getPacketId(new HandshakePacket())); - } - - @Test - void failOnWrongOrder() { - StateRegistry.PacketRegistry registry = new StateRegistry.PacketRegistry( - ProtocolUtils.Direction.CLIENTBOUND, StateRegistry.PLAY); - assertThrows(IllegalArgumentException.class, - () -> registry.register(HandshakePacket.class, new HandshakePacket.Codec(), - new StateRegistry.PacketMapping(0x01, MINECRAFT_1_13, null, false), - new StateRegistry.PacketMapping(0x00, MINECRAFT_1_8, null, false))); - assertThrows(IllegalArgumentException.class, - () -> registry.register(HandshakePacket.class, new HandshakePacket.Codec(), - new StateRegistry.PacketMapping(0x01, MINECRAFT_1_13, null, false), - new StateRegistry.PacketMapping(0x01, MINECRAFT_1_13, null, false))); - assertThrows(IllegalArgumentException.class, - () -> registry.register(HandshakePacket.class, new HandshakePacket.Codec(), - new StateRegistry.PacketMapping(0x01, MINECRAFT_1_13, MINECRAFT_1_8, false))); - assertThrows(IllegalArgumentException.class, - () -> registry.register(HandshakePacket.class, new HandshakePacket.Codec(), - new StateRegistry.PacketMapping(0x01, MINECRAFT_1_8, MINECRAFT_1_14, false), - new StateRegistry.PacketMapping(0x00, MINECRAFT_1_16, null, false))); - } - - @Test - void failOnDuplicate() { - StateRegistry.PacketRegistry registry = new StateRegistry.PacketRegistry( - ProtocolUtils.Direction.CLIENTBOUND, StateRegistry.PLAY); - registry.register(HandshakePacket.class, new HandshakePacket.Codec(), - new StateRegistry.PacketMapping(0x00, MINECRAFT_1_8, null, false)); - assertThrows(IllegalArgumentException.class, - () -> registry.register(HandshakePacket.class, new HandshakePacket.Codec(), - new StateRegistry.PacketMapping(0x01, MINECRAFT_1_12, null, false))); - assertThrows(IllegalArgumentException.class, - () -> registry.register(StatusPingPacket.class, new StatusPingPacket.Codec(), - new StateRegistry.PacketMapping(0x00, MINECRAFT_1_13, null, false))); - } - - @Test - void shouldNotFailWhenRegisterLatestProtocolVersion() { - StateRegistry.PacketRegistry registry = new StateRegistry.PacketRegistry( - ProtocolUtils.Direction.CLIENTBOUND, StateRegistry.PLAY); - assertDoesNotThrow(() -> registry.register(HandshakePacket.class, new HandshakePacket.Codec(), - new StateRegistry.PacketMapping(0x00, MINECRAFT_1_8, null, false), - new StateRegistry.PacketMapping(0x01, getLast(ProtocolVersion.SUPPORTED_VERSIONS), - null, false))); + // 1.16_2 is >= 1.15, so it should have codec for 0x00 from the last range + assertNotNull(registry.forVersion(MINECRAFT_1_16_2).getCodec(0), + "1.16_2 should have codec for 0x00 from 1.15+ range"); } @Test void registrySuppliesCorrectPacketsByProtocol() { - StateRegistry.PacketRegistry registry = new StateRegistry.PacketRegistry( - ProtocolUtils.Direction.CLIENTBOUND, StateRegistry.PLAY); - registry.register(HandshakePacket.class, new HandshakePacket.Codec(), - 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)); + MultiVersionPacketRegistry registry = MultiVersionPacketRegistry.builder(ProtocolUtils.Direction.CLIENTBOUND) + .register(HandshakePacket.class, new HandshakePacket.Codec(), + VersionRange.of(MINECRAFT_1_12, MINECRAFT_1_12, 0x00), + VersionRange.of(MINECRAFT_1_12_1, MINECRAFT_1_12_2, 0x01), + VersionRange.of(MINECRAFT_1_13, MINECRAFT_1_14_4, 0x02)) + .build(); + assertNotNull(registry.forVersion(MINECRAFT_1_12).getCodec(0x00)); assertEquals(HandshakePacket.Codec.class, - registry.getProtocolRegistry(MINECRAFT_1_12).getCodec(0x00).getClass()); + registry.forVersion(MINECRAFT_1_12).getCodec(0x00).getClass()); + assertNotNull(registry.forVersion(MINECRAFT_1_12_1).getCodec(0x01)); assertEquals(HandshakePacket.Codec.class, - registry.getProtocolRegistry(MINECRAFT_1_12_1).getCodec(0x01).getClass()); + registry.forVersion(MINECRAFT_1_12_1).getCodec(0x01).getClass()); + assertNotNull(registry.forVersion(MINECRAFT_1_12_2).getCodec(0x01)); assertEquals(HandshakePacket.Codec.class, - registry.getProtocolRegistry(MINECRAFT_1_12_2).getCodec(0x01).getClass()); + registry.forVersion(MINECRAFT_1_12_2).getCodec(0x01).getClass()); + assertNotNull(registry.forVersion(MINECRAFT_1_13).getCodec(0x02)); assertEquals(HandshakePacket.Codec.class, - registry.getProtocolRegistry(MINECRAFT_1_13).getCodec(0x02).getClass()); + registry.forVersion(MINECRAFT_1_13).getCodec(0x02).getClass()); + assertNotNull(registry.forVersion(MINECRAFT_1_14_2).getCodec(0x02)); assertEquals(HandshakePacket.Codec.class, - registry.getProtocolRegistry(MINECRAFT_1_14_2).getCodec(0x02).getClass()); + registry.forVersion(MINECRAFT_1_14_2).getCodec(0x02).getClass()); + } + + // ==================== Error Handling Tests ==================== + + @Test + void failOnNoMappings() { + assertThrows(IllegalArgumentException.class, + () -> MultiVersionPacketRegistry.builder(ProtocolUtils.Direction.CLIENTBOUND) + .build() + .forVersion(ProtocolVersion.UNKNOWN)); + } + + @Test + void failOnWrongVersionOrder() { + // End version before start version + assertThrows(IllegalArgumentException.class, + () -> MultiVersionPacketRegistry.builder(ProtocolUtils.Direction.CLIENTBOUND) + .register(HandshakePacket.class, new HandshakePacket.Codec(), + VersionRange.of(MINECRAFT_1_13, 0x01), + VersionRange.of(MINECRAFT_1_8, 0x00)) + .build()); + } + + @Test + void failOnInvalidRangeStartGreaterThanEnd() { + // Single VersionRange with start > end + assertThrows(IllegalArgumentException.class, + () -> MultiVersionPacketRegistry.builder(ProtocolUtils.Direction.CLIENTBOUND) + .register(HandshakePacket.class, new HandshakePacket.Codec(), + VersionRange.of(MINECRAFT_1_13, MINECRAFT_1_8, 0x01)) + .build()); + } + + @Test + void failOnDuplicateVersionRanges() { + // Two ranges covering the same version + assertThrows(IllegalArgumentException.class, + () -> MultiVersionPacketRegistry.builder(ProtocolUtils.Direction.CLIENTBOUND) + .register(HandshakePacket.class, new HandshakePacket.Codec(), + VersionRange.of(MINECRAFT_1_13, 0x01), + VersionRange.of(MINECRAFT_1_13, 0x01)) + .build()); + } + + @Test + void failOnOverlappingVersionRanges() { + // Same packet registered twice with overlapping versions should fail + assertThrows(IllegalArgumentException.class, + () -> MultiVersionPacketRegistry.builder(ProtocolUtils.Direction.CLIENTBOUND) + .register(HandshakePacket.class, new HandshakePacket.Codec(), + VersionRange.of(MINECRAFT_1_8, MINECRAFT_1_14, 0x01)) + .register(HandshakePacket.class, new HandshakePacket.Codec(), + VersionRange.of(MINECRAFT_1_12, MINECRAFT_1_16, 0x00)) + .build()); + } + + @Test + void failOnDuplicatePacketClass() { + // Same packet class registered twice for overlapping versions + assertThrows(IllegalArgumentException.class, + () -> MultiVersionPacketRegistry.builder(ProtocolUtils.Direction.CLIENTBOUND) + .register(HandshakePacket.class, new HandshakePacket.Codec(), + VersionRange.of(MINECRAFT_1_8, MINECRAFT_1_14, 0x00)) + .register(HandshakePacket.class, new HandshakePacket.Codec(), + VersionRange.of(MINECRAFT_1_12, 0x01)) + .build()); + } + + @Test + void allowDifferentPacketsWithSameIdInDifferentVersions() { + // Different packets can have the same ID in different version ranges + assertDoesNotThrow( + () -> MultiVersionPacketRegistry.builder(ProtocolUtils.Direction.CLIENTBOUND) + .register(HandshakePacket.class, new HandshakePacket.Codec(), + VersionRange.of(MINECRAFT_1_8, MINECRAFT_1_12, 0x00)) + .register(StatusPingPacket.class, new StatusPingPacket.Codec(), + VersionRange.of(MINECRAFT_1_13, MAXIMUM_VERSION, 0x00)) + .build()); + } + + @Test + void failOnInvalidPacketIdLookup() { + MultiVersionPacketRegistry registry = setupRegistry(); + // Try to get packet ID for a packet type that doesn't exist in the registry + assertThrows(IllegalArgumentException.class, + () -> registry.forVersion(MINECRAFT_1_12).getPacketId(new StatusPingPacket(0L))); + } + + // ==================== Edge Cases and Boundaries ==================== + + @Test + void shouldNotFailWhenRegisterLatestProtocolVersion() { + assertDoesNotThrow(() -> MultiVersionPacketRegistry.builder(ProtocolUtils.Direction.CLIENTBOUND) + .register(HandshakePacket.class, new HandshakePacket.Codec(), + VersionRange.of(MINECRAFT_1_8, MINECRAFT_1_14_4, 0x00), + VersionRange.of(getLast(ProtocolVersion.SUPPORTED_VERSIONS), 0x01)) + .build()); + } + + @Test + void versionBoundaryTransition() { + // Test that version boundaries are handled correctly + MultiVersionPacketRegistry registry = MultiVersionPacketRegistry.builder(ProtocolUtils.Direction.CLIENTBOUND) + .register(HandshakePacket.class, new HandshakePacket.Codec(), + VersionRange.of(MINECRAFT_1_12, MINECRAFT_1_12, 0x00), + VersionRange.of(MINECRAFT_1_13, MAXIMUM_VERSION, 0x01)) + .build(); + + // 1.12 should have ID 0x00 + assertEquals(0x00, registry.forVersion(MINECRAFT_1_12).getPacketId(new HandshakePacket())); + // 1.13 should have ID 0x01 + assertEquals(0x01, registry.forVersion(MINECRAFT_1_13).getPacketId(new HandshakePacket())); + } + + @Test + void multiplePacketsInSingleRegistry() { + // Test registry with multiple packet types + MultiVersionPacketRegistry registry = MultiVersionPacketRegistry.builder(ProtocolUtils.Direction.CLIENTBOUND) + .register(HandshakePacket.class, new HandshakePacket.Codec(), + VersionRange.of(MINECRAFT_1_12, 0x00)) + .register(StatusPingPacket.class, new StatusPingPacket.Codec(), + VersionRange.of(MINECRAFT_1_12, 0x01)) + .build(); + + assertEquals(0x00, registry.forVersion(MINECRAFT_1_12).getPacketId(new HandshakePacket())); + assertEquals(0x01, registry.forVersion(MINECRAFT_1_12).getPacketId(new StatusPingPacket(0L))); + assertNotNull(registry.forVersion(MINECRAFT_1_12).getCodec(0x00)); + assertNotNull(registry.forVersion(MINECRAFT_1_12).getCodec(0x01)); + } + + // ==================== Encode-Only Tests ==================== + + @Test + void encodeOnlyPacketsCanBeEncoded() { + // Encode-only packets should be decodable by class but not by ID + MultiVersionPacketRegistry registry = MultiVersionPacketRegistry.builder(ProtocolUtils.Direction.CLIENTBOUND) + .register(HandshakePacket.class, new HandshakePacket.Codec(), + VersionRange.encodeOnly(MINECRAFT_1_12, 0x00)) + .build(); + + // Should be able to get codec by class + assertNotNull(registry.forVersion(MINECRAFT_1_12).getCodec(HandshakePacket.class)); + // Should NOT be able to get codec by ID + assertNull(registry.forVersion(MINECRAFT_1_12).getCodec(0x00)); + } + + @Test + void encodeOnlyPacketMultipleVersions() { + MultiVersionPacketRegistry registry = MultiVersionPacketRegistry.builder(ProtocolUtils.Direction.CLIENTBOUND) + .register(HandshakePacket.class, new HandshakePacket.Codec(), + VersionRange.encodeOnly(MINECRAFT_1_8, MINECRAFT_1_12, 0x00), + VersionRange.of(MINECRAFT_1_13, 0x01)) + .build(); + + // 1.8-1.12 should be encode-only (no decode by ID) + assertNull(registry.forVersion(MINECRAFT_1_12).getCodec(0x00)); + assertNotNull(registry.forVersion(MINECRAFT_1_12).getCodec(HandshakePacket.class)); + + // 1.13+ should be decodable by ID + assertNotNull(registry.forVersion(MINECRAFT_1_13).getCodec(0x01)); + } + + // ==================== Codec Retrieval Tests ==================== + + @Test + void getCodecByClassWorks() { + MultiVersionPacketRegistry registry = setupRegistry(); + PacketCodec codec = registry.forVersion(MINECRAFT_1_12) + .getCodec(HandshakePacket.class); + assertNotNull(codec, "Should be able to retrieve codec by class"); + assertEquals(HandshakePacket.Codec.class, codec.getClass()); + } + + @Test + void getCodecByClassReturnsNullForUnregisteredPacket() { + MultiVersionPacketRegistry registry = setupRegistry(); + PacketCodec codec = registry.forVersion(MINECRAFT_1_12) + .getCodec(StatusPingPacket.class); + assertNull(codec, "Should return null for unregistered packet class"); + } + + @Test + void getCodecByIdReturnsNullForInvalidId() { + MultiVersionPacketRegistry registry = setupRegistry(); + PacketCodec codec = registry.forVersion(MINECRAFT_1_12).getCodec(0xFF); + assertNull(codec, "Should return null for invalid packet ID"); + } + + // ==================== CanDecodePacket Tests ==================== + + @Test + void canDecodePacketReturnsTrue() { + MultiVersionPacketRegistry registry = setupRegistry(); + assertTrue(registry.forVersion(MINECRAFT_1_12).canDecodePacket(new HandshakePacket()), + "Should be able to decode HandshakePacket in 1.12"); + } + + @Test + void canDecodePacketReturnsFalse() { + MultiVersionPacketRegistry registry = setupRegistry(); + assertFalse(registry.forVersion(MINECRAFT_1_12).canDecodePacket(new StatusPingPacket(0L)), + "Should not be able to decode StatusPingPacket in 1.12"); + } + + @Test + void encodeOnlyPacketCanBeIdentified() { + MultiVersionPacketRegistry registry = MultiVersionPacketRegistry.builder(ProtocolUtils.Direction.CLIENTBOUND) + .register(HandshakePacket.class, new HandshakePacket.Codec(), + VersionRange.encodeOnly(MINECRAFT_1_12, 0x00)) + .build(); + + // Encode-only packets can still be identified by class for encoding purposes + assertTrue(registry.forVersion(MINECRAFT_1_12).canDecodePacket(new HandshakePacket()), + "Encode-only packets can be identified for encoding"); + // But cannot be decoded by ID (not in packetIdToCodec) + assertNull(registry.forVersion(MINECRAFT_1_12).getCodec(0x00), + "Encode-only packets cannot be decoded from ID"); + } + + // ==================== SimplePacketRegistry Tests ==================== + + @Test + void simplePacketRegistryWorks() { + SimplePacketRegistry registry = new SimplePacketRegistry(ProtocolUtils.Direction.CLIENTBOUND); + registry.register(0x00, HandshakePacket.class, new HandshakePacket.Codec()); + + PacketCodec codec = registry.getCodec(0x00); + assertNotNull(codec, "Should retrieve codec by ID"); + assertEquals(HandshakePacket.Codec.class, codec.getClass()); + } + + @Test + void simplePacketRegistryCodecByClass() { + SimplePacketRegistry registry = new SimplePacketRegistry(ProtocolUtils.Direction.CLIENTBOUND); + registry.register(0x00, HandshakePacket.class, new HandshakePacket.Codec()); + + PacketCodec codec = registry.getCodec(HandshakePacket.class); + assertNotNull(codec, "Should retrieve codec by class"); + assertEquals(HandshakePacket.Codec.class, codec.getClass()); + } + + @Test + void simplePacketRegistryGetPacketId() { + SimplePacketRegistry registry = new SimplePacketRegistry(ProtocolUtils.Direction.CLIENTBOUND); + registry.register(0x42, HandshakePacket.class, new HandshakePacket.Codec()); + + int id = registry.getPacketId(new HandshakePacket()); + assertEquals(0x42, id, "Should return correct packet ID"); + } + + @Test + void simplePacketRegistryFailsOnUnregisteredPacket() { + SimplePacketRegistry registry = new SimplePacketRegistry(ProtocolUtils.Direction.CLIENTBOUND); + registry.register(0x00, HandshakePacket.class, new HandshakePacket.Codec()); + + assertThrows(IllegalArgumentException.class, + () -> registry.getPacketId(new StatusPingPacket(0L)), + "Should fail when packet is not registered"); + } + + @Test + void simplePacketRegistryCanDecodePacket() { + SimplePacketRegistry registry = new SimplePacketRegistry(ProtocolUtils.Direction.CLIENTBOUND); + registry.register(0x00, HandshakePacket.class, new HandshakePacket.Codec()); + + assertTrue(registry.canDecodePacket(new HandshakePacket()), + "Should be able to decode registered packet"); + assertFalse(registry.canDecodePacket(new StatusPingPacket(0L)), + "Should not be able to decode unregistered packet"); + } + + // ==================== Direction Tests ==================== + + @Test + void registriesWithDifferentDirections() { + // CLIENTBOUND registry + MultiVersionPacketRegistry clientbound = MultiVersionPacketRegistry.builder(ProtocolUtils.Direction.CLIENTBOUND) + .register(HandshakePacket.class, new HandshakePacket.Codec(), + VersionRange.of(MINECRAFT_1_12, 0x00)) + .build(); + + // SERVERBOUND registry with different ID + MultiVersionPacketRegistry serverbound = MultiVersionPacketRegistry.builder(ProtocolUtils.Direction.SERVERBOUND) + .register(HandshakePacket.class, new HandshakePacket.Codec(), + VersionRange.of(MINECRAFT_1_12, 0x01)) + .build(); + + assertEquals(0x00, clientbound.forVersion(MINECRAFT_1_12).getPacketId(new HandshakePacket())); + assertEquals(0x01, serverbound.forVersion(MINECRAFT_1_12).getPacketId(new HandshakePacket())); + } + + // ==================== Wide Version Range Tests ==================== + + @Test + void wideVersionRangeSpanningManyVersions() { + // Register packet across many versions with same ID + MultiVersionPacketRegistry registry = MultiVersionPacketRegistry.builder(ProtocolUtils.Direction.CLIENTBOUND) + .register(HandshakePacket.class, new HandshakePacket.Codec(), + VersionRange.of(MINECRAFT_1_8, MAXIMUM_VERSION, 0x00)) + .build(); + + // Should work for all supported versions in range + assertEquals(0x00, registry.forVersion(MINECRAFT_1_8).getPacketId(new HandshakePacket())); + assertEquals(0x00, registry.forVersion(MINECRAFT_1_12).getPacketId(new HandshakePacket())); + assertEquals(0x00, registry.forVersion(MINECRAFT_1_16_2).getPacketId(new HandshakePacket())); + } + + @Test + void nullEndVersionRangeHandling() { + // Test with null end version (should extend to MAXIMUM_VERSION) + MultiVersionPacketRegistry registry = MultiVersionPacketRegistry.builder(ProtocolUtils.Direction.CLIENTBOUND) + .register(HandshakePacket.class, new HandshakePacket.Codec(), + VersionRange.of(MINECRAFT_1_15, 0x00)) + .build(); + + assertEquals(0x00, registry.forVersion(MINECRAFT_1_15).getPacketId(new HandshakePacket())); + assertEquals(0x00, registry.forVersion(MINECRAFT_1_16_2).getPacketId(new HandshakePacket())); } } \ No newline at end of file