// Generated by delombok at Tue Oct 21 21:24:10 UTC 2025
package net.md_5.bungee.protocol;

import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import java.util.function.Supplier;
import net.md_5.bungee.protocol.packet.BossBar;
import net.md_5.bungee.protocol.packet.BundleDelimiter;
import net.md_5.bungee.protocol.packet.Chat;
import net.md_5.bungee.protocol.packet.ClearDialog;
import net.md_5.bungee.protocol.packet.ClearTitles;
import net.md_5.bungee.protocol.packet.ClientChat;
import net.md_5.bungee.protocol.packet.ClientCommand;
import net.md_5.bungee.protocol.packet.ClientSettings;
import net.md_5.bungee.protocol.packet.Commands;
import net.md_5.bungee.protocol.packet.CookieRequest;
import net.md_5.bungee.protocol.packet.CookieResponse;
import net.md_5.bungee.protocol.packet.CustomClickAction;
import net.md_5.bungee.protocol.packet.DisconnectReportDetails;
import net.md_5.bungee.protocol.packet.EncryptionRequest;
import net.md_5.bungee.protocol.packet.EncryptionResponse;
import net.md_5.bungee.protocol.packet.EntityStatus;
import net.md_5.bungee.protocol.packet.FinishConfiguration;
import net.md_5.bungee.protocol.packet.GameState;
import net.md_5.bungee.protocol.packet.Handshake;
import net.md_5.bungee.protocol.packet.KeepAlive;
import net.md_5.bungee.protocol.packet.Kick;
import net.md_5.bungee.protocol.packet.Login;
import net.md_5.bungee.protocol.packet.LoginAcknowledged;
import net.md_5.bungee.protocol.packet.LoginPayloadRequest;
import net.md_5.bungee.protocol.packet.LoginPayloadResponse;
import net.md_5.bungee.protocol.packet.LoginRequest;
import net.md_5.bungee.protocol.packet.LoginSuccess;
import net.md_5.bungee.protocol.packet.PingPacket;
import net.md_5.bungee.protocol.packet.PlayerListHeaderFooter;
import net.md_5.bungee.protocol.packet.PlayerListItem;
import net.md_5.bungee.protocol.packet.PlayerListItemRemove;
import net.md_5.bungee.protocol.packet.PlayerListItemUpdate;
import net.md_5.bungee.protocol.packet.PluginMessage;
import net.md_5.bungee.protocol.packet.Respawn;
import net.md_5.bungee.protocol.packet.ScoreboardDisplay;
import net.md_5.bungee.protocol.packet.ScoreboardObjective;
import net.md_5.bungee.protocol.packet.ScoreboardScore;
import net.md_5.bungee.protocol.packet.ScoreboardScoreReset;
import net.md_5.bungee.protocol.packet.ServerData;
import net.md_5.bungee.protocol.packet.ServerLinks;
import net.md_5.bungee.protocol.packet.SetCompression;
import net.md_5.bungee.protocol.packet.ShowDialog;
import net.md_5.bungee.protocol.packet.ShowDialogDirect;
import net.md_5.bungee.protocol.packet.StartConfiguration;
import net.md_5.bungee.protocol.packet.StatusRequest;
import net.md_5.bungee.protocol.packet.StatusResponse;
import net.md_5.bungee.protocol.packet.StoreCookie;
import net.md_5.bungee.protocol.packet.Subtitle;
import net.md_5.bungee.protocol.packet.SystemChat;
import net.md_5.bungee.protocol.packet.TabCompleteRequest;
import net.md_5.bungee.protocol.packet.TabCompleteResponse;
import net.md_5.bungee.protocol.packet.Team;
import net.md_5.bungee.protocol.packet.Title;
import net.md_5.bungee.protocol.packet.TitleTimes;
import net.md_5.bungee.protocol.packet.Transfer;
import net.md_5.bungee.protocol.packet.UnsignedClientCommand;
import net.md_5.bungee.protocol.packet.ViewDistance;

public enum Protocol {
    // Undef
    HANDSHAKE {
        {
            TO_SERVER.registerPacket(Handshake.class, Handshake::new, map(ProtocolConstants.MINECRAFT_1_8, 0));
        }
    },
    
    // 0
    GAME {
        {
            TO_CLIENT.registerPacket(BundleDelimiter.class, BundleDelimiter::new, map(ProtocolConstants.MINECRAFT_1_19_4, 0));
            TO_CLIENT.registerPacket(KeepAlive.class, KeepAlive::new, map(ProtocolConstants.MINECRAFT_1_8, 0), map(ProtocolConstants.MINECRAFT_1_9, 31), map(ProtocolConstants.MINECRAFT_1_13, 33), map(ProtocolConstants.MINECRAFT_1_14, 32), map(ProtocolConstants.MINECRAFT_1_15, 33), map(ProtocolConstants.MINECRAFT_1_16, 32), map(ProtocolConstants.MINECRAFT_1_16_2, 31), map(ProtocolConstants.MINECRAFT_1_17, 33), map(ProtocolConstants.MINECRAFT_1_19, 30), map(ProtocolConstants.MINECRAFT_1_19_1, 32), map(ProtocolConstants.MINECRAFT_1_19_3, 31), map(ProtocolConstants.MINECRAFT_1_19_4, 35), map(ProtocolConstants.MINECRAFT_1_20_2, 36), map(ProtocolConstants.MINECRAFT_1_20_5, 38), map(ProtocolConstants.MINECRAFT_1_21_2, 39), map(ProtocolConstants.MINECRAFT_1_21_5, 38), map(ProtocolConstants.MINECRAFT_1_21_9, 43));
            TO_CLIENT.registerPacket(Login.class, Login::new, map(ProtocolConstants.MINECRAFT_1_8, 1), map(ProtocolConstants.MINECRAFT_1_9, 35), map(ProtocolConstants.MINECRAFT_1_13, 37), map(ProtocolConstants.MINECRAFT_1_15, 38), map(ProtocolConstants.MINECRAFT_1_16, 37), map(ProtocolConstants.MINECRAFT_1_16_2, 36), map(ProtocolConstants.MINECRAFT_1_17, 38), map(ProtocolConstants.MINECRAFT_1_19, 35), map(ProtocolConstants.MINECRAFT_1_19_1, 37), map(ProtocolConstants.MINECRAFT_1_19_3, 36), map(ProtocolConstants.MINECRAFT_1_19_4, 40), map(ProtocolConstants.MINECRAFT_1_20_2, 41), map(ProtocolConstants.MINECRAFT_1_20_5, 43), map(ProtocolConstants.MINECRAFT_1_21_2, 44), map(ProtocolConstants.MINECRAFT_1_21_5, 43), map(ProtocolConstants.MINECRAFT_1_21_9, 48));
            TO_CLIENT.registerPacket(Chat.class, Chat::new, RegisterType.ENCODE, map(ProtocolConstants.MINECRAFT_1_8, 2), map(ProtocolConstants.MINECRAFT_1_9, 15), map(ProtocolConstants.MINECRAFT_1_13, 14), map(ProtocolConstants.MINECRAFT_1_15, 15), map(ProtocolConstants.MINECRAFT_1_16, 14), map(ProtocolConstants.MINECRAFT_1_17, 15), map(ProtocolConstants.MINECRAFT_1_19, -1));
            TO_CLIENT.registerPacket(Respawn.class, Respawn::new, map(ProtocolConstants.MINECRAFT_1_8, 7), map(ProtocolConstants.MINECRAFT_1_9, 51), map(ProtocolConstants.MINECRAFT_1_12, 52), map(ProtocolConstants.MINECRAFT_1_12_1, 53), map(ProtocolConstants.MINECRAFT_1_13, 56), map(ProtocolConstants.MINECRAFT_1_14, 58), map(ProtocolConstants.MINECRAFT_1_15, 59), map(ProtocolConstants.MINECRAFT_1_16, 58), map(ProtocolConstants.MINECRAFT_1_16_2, 57), map(ProtocolConstants.MINECRAFT_1_17, 61), map(ProtocolConstants.MINECRAFT_1_19, 59), map(ProtocolConstants.MINECRAFT_1_19_1, 62), map(ProtocolConstants.MINECRAFT_1_19_3, 61), map(ProtocolConstants.MINECRAFT_1_19_4, 65), map(ProtocolConstants.MINECRAFT_1_20_2, 67), map(ProtocolConstants.MINECRAFT_1_20_3, 69), map(ProtocolConstants.MINECRAFT_1_20_5, 71), map(ProtocolConstants.MINECRAFT_1_21_2, 76), map(ProtocolConstants.MINECRAFT_1_21_5, 75), map(ProtocolConstants.MINECRAFT_1_21_9, 80));
            TO_CLIENT.registerPacket(BossBar.class, BossBar::new, map(ProtocolConstants.MINECRAFT_1_9, 12), map(ProtocolConstants.MINECRAFT_1_15, 13), map(ProtocolConstants.MINECRAFT_1_16, 12), map(ProtocolConstants.MINECRAFT_1_17, 13), map(ProtocolConstants.MINECRAFT_1_19, 10), map(ProtocolConstants.MINECRAFT_1_19_4, 11), map(ProtocolConstants.MINECRAFT_1_20_2, 10), map(ProtocolConstants.MINECRAFT_1_21_5, 9));
            TO_CLIENT.registerPacket(PlayerListItem.class,  // PlayerInfo
            PlayerListItem::new, map(ProtocolConstants.MINECRAFT_1_8, 56), map(ProtocolConstants.MINECRAFT_1_9, 45), map(ProtocolConstants.MINECRAFT_1_12_1, 46), map(ProtocolConstants.MINECRAFT_1_13, 48), map(ProtocolConstants.MINECRAFT_1_14, 51), map(ProtocolConstants.MINECRAFT_1_15, 52), map(ProtocolConstants.MINECRAFT_1_16, 51), map(ProtocolConstants.MINECRAFT_1_16_2, 50), map(ProtocolConstants.MINECRAFT_1_17, 54), map(ProtocolConstants.MINECRAFT_1_19, 52), map(ProtocolConstants.MINECRAFT_1_19_1, 55), map(ProtocolConstants.MINECRAFT_1_19_3, -1));
            TO_CLIENT.registerPacket(TabCompleteResponse.class, TabCompleteResponse::new, map(ProtocolConstants.MINECRAFT_1_8, 58), map(ProtocolConstants.MINECRAFT_1_9, 14), map(ProtocolConstants.MINECRAFT_1_13, 16), map(ProtocolConstants.MINECRAFT_1_15, 17), map(ProtocolConstants.MINECRAFT_1_16, 16), map(ProtocolConstants.MINECRAFT_1_16_2, 15), map(ProtocolConstants.MINECRAFT_1_17, 17), map(ProtocolConstants.MINECRAFT_1_19, 14), map(ProtocolConstants.MINECRAFT_1_19_3, 13), map(ProtocolConstants.MINECRAFT_1_19_4, 15), map(ProtocolConstants.MINECRAFT_1_20_2, 16), map(ProtocolConstants.MINECRAFT_1_21_5, 15));
            TO_CLIENT.registerPacket(ScoreboardObjective.class, ScoreboardObjective::new, map(ProtocolConstants.MINECRAFT_1_8, 59), map(ProtocolConstants.MINECRAFT_1_9, 63), map(ProtocolConstants.MINECRAFT_1_12, 65), map(ProtocolConstants.MINECRAFT_1_12_1, 66), map(ProtocolConstants.MINECRAFT_1_13, 69), map(ProtocolConstants.MINECRAFT_1_14, 73), map(ProtocolConstants.MINECRAFT_1_15, 74), map(ProtocolConstants.MINECRAFT_1_17, 83), map(ProtocolConstants.MINECRAFT_1_19_1, 86), map(ProtocolConstants.MINECRAFT_1_19_3, 84), map(ProtocolConstants.MINECRAFT_1_19_4, 88), map(ProtocolConstants.MINECRAFT_1_20_2, 90), map(ProtocolConstants.MINECRAFT_1_20_3, 92), map(ProtocolConstants.MINECRAFT_1_20_5, 94), map(ProtocolConstants.MINECRAFT_1_21_2, 100), map(ProtocolConstants.MINECRAFT_1_21_5, 99), map(ProtocolConstants.MINECRAFT_1_21_9, 104));
            TO_CLIENT.registerPacket(ScoreboardScore.class, ScoreboardScore::new, map(ProtocolConstants.MINECRAFT_1_8, 60), map(ProtocolConstants.MINECRAFT_1_9, 66), map(ProtocolConstants.MINECRAFT_1_12, 68), map(ProtocolConstants.MINECRAFT_1_12_1, 69), map(ProtocolConstants.MINECRAFT_1_13, 72), map(ProtocolConstants.MINECRAFT_1_14, 76), map(ProtocolConstants.MINECRAFT_1_15, 77), map(ProtocolConstants.MINECRAFT_1_17, 86), map(ProtocolConstants.MINECRAFT_1_19_1, 89), map(ProtocolConstants.MINECRAFT_1_19_3, 87), map(ProtocolConstants.MINECRAFT_1_19_4, 91), map(ProtocolConstants.MINECRAFT_1_20_2, 93), map(ProtocolConstants.MINECRAFT_1_20_3, 95), map(ProtocolConstants.MINECRAFT_1_20_5, 97), map(ProtocolConstants.MINECRAFT_1_21_2, 104), map(ProtocolConstants.MINECRAFT_1_21_5, 103), map(ProtocolConstants.MINECRAFT_1_21_9, 108));
            TO_CLIENT.registerPacket(ScoreboardScoreReset.class, ScoreboardScoreReset::new, map(ProtocolConstants.MINECRAFT_1_20_3, 66), map(ProtocolConstants.MINECRAFT_1_20_5, 68), map(ProtocolConstants.MINECRAFT_1_21_2, 73), map(ProtocolConstants.MINECRAFT_1_21_5, 72), map(ProtocolConstants.MINECRAFT_1_21_9, 77));
            TO_CLIENT.registerPacket(ScoreboardDisplay.class, ScoreboardDisplay::new, map(ProtocolConstants.MINECRAFT_1_8, 61), map(ProtocolConstants.MINECRAFT_1_9, 56), map(ProtocolConstants.MINECRAFT_1_12, 58), map(ProtocolConstants.MINECRAFT_1_12_1, 59), map(ProtocolConstants.MINECRAFT_1_13, 62), map(ProtocolConstants.MINECRAFT_1_14, 66), map(ProtocolConstants.MINECRAFT_1_15, 67), map(ProtocolConstants.MINECRAFT_1_17, 76), map(ProtocolConstants.MINECRAFT_1_19_1, 79), map(ProtocolConstants.MINECRAFT_1_19_3, 77), map(ProtocolConstants.MINECRAFT_1_19_4, 81), map(ProtocolConstants.MINECRAFT_1_20_2, 83), map(ProtocolConstants.MINECRAFT_1_20_3, 85), map(ProtocolConstants.MINECRAFT_1_20_5, 87), map(ProtocolConstants.MINECRAFT_1_21_2, 92), map(ProtocolConstants.MINECRAFT_1_21_5, 91), map(ProtocolConstants.MINECRAFT_1_21_9, 96));
            TO_CLIENT.registerPacket(Team.class, Team::new, map(ProtocolConstants.MINECRAFT_1_8, 62), map(ProtocolConstants.MINECRAFT_1_9, 65), map(ProtocolConstants.MINECRAFT_1_12, 67), map(ProtocolConstants.MINECRAFT_1_12_1, 68), map(ProtocolConstants.MINECRAFT_1_13, 71), map(ProtocolConstants.MINECRAFT_1_14, 75), map(ProtocolConstants.MINECRAFT_1_15, 76), map(ProtocolConstants.MINECRAFT_1_17, 85), map(ProtocolConstants.MINECRAFT_1_19_1, 88), map(ProtocolConstants.MINECRAFT_1_19_3, 86), map(ProtocolConstants.MINECRAFT_1_19_4, 90), map(ProtocolConstants.MINECRAFT_1_20_2, 92), map(ProtocolConstants.MINECRAFT_1_20_3, 94), map(ProtocolConstants.MINECRAFT_1_20_5, 96), map(ProtocolConstants.MINECRAFT_1_21_2, 103), map(ProtocolConstants.MINECRAFT_1_21_5, 102), map(ProtocolConstants.MINECRAFT_1_21_9, 107));
            TO_CLIENT.registerPacket(PluginMessage.class, PluginMessage::new, map(ProtocolConstants.MINECRAFT_1_8, 63), map(ProtocolConstants.MINECRAFT_1_9, 24), map(ProtocolConstants.MINECRAFT_1_13, 25), map(ProtocolConstants.MINECRAFT_1_14, 24), map(ProtocolConstants.MINECRAFT_1_15, 25), map(ProtocolConstants.MINECRAFT_1_16, 24), map(ProtocolConstants.MINECRAFT_1_16_2, 23), map(ProtocolConstants.MINECRAFT_1_17, 24), map(ProtocolConstants.MINECRAFT_1_19, 21), map(ProtocolConstants.MINECRAFT_1_19_1, 22), map(ProtocolConstants.MINECRAFT_1_19_3, 21), map(ProtocolConstants.MINECRAFT_1_19_4, 23), map(ProtocolConstants.MINECRAFT_1_20_2, 24), map(ProtocolConstants.MINECRAFT_1_20_5, 25), map(ProtocolConstants.MINECRAFT_1_21_5, 24));
            TO_CLIENT.registerPacket(Kick.class, Kick::new, map(ProtocolConstants.MINECRAFT_1_8, 64), map(ProtocolConstants.MINECRAFT_1_9, 26), map(ProtocolConstants.MINECRAFT_1_13, 27), map(ProtocolConstants.MINECRAFT_1_14, 26), map(ProtocolConstants.MINECRAFT_1_15, 27), map(ProtocolConstants.MINECRAFT_1_16, 26), map(ProtocolConstants.MINECRAFT_1_16_2, 25), map(ProtocolConstants.MINECRAFT_1_17, 26), map(ProtocolConstants.MINECRAFT_1_19, 23), map(ProtocolConstants.MINECRAFT_1_19_1, 25), map(ProtocolConstants.MINECRAFT_1_19_3, 23), map(ProtocolConstants.MINECRAFT_1_19_4, 26), map(ProtocolConstants.MINECRAFT_1_20_2, 27), map(ProtocolConstants.MINECRAFT_1_20_5, 29), map(ProtocolConstants.MINECRAFT_1_21_5, 28), map(ProtocolConstants.MINECRAFT_1_21_9, 32));
            TO_CLIENT.registerPacket(Title.class, Title::new, RegisterType.ENCODE, map(ProtocolConstants.MINECRAFT_1_8, 69), map(ProtocolConstants.MINECRAFT_1_12, 71), map(ProtocolConstants.MINECRAFT_1_12_1, 72), map(ProtocolConstants.MINECRAFT_1_13, 75), map(ProtocolConstants.MINECRAFT_1_14, 79), map(ProtocolConstants.MINECRAFT_1_15, 80), map(ProtocolConstants.MINECRAFT_1_16, 79), map(ProtocolConstants.MINECRAFT_1_17, 89), map(ProtocolConstants.MINECRAFT_1_18, 90), map(ProtocolConstants.MINECRAFT_1_19_1, 93), map(ProtocolConstants.MINECRAFT_1_19_3, 91), map(ProtocolConstants.MINECRAFT_1_19_4, 95), map(ProtocolConstants.MINECRAFT_1_20_2, 97), map(ProtocolConstants.MINECRAFT_1_20_3, 99), map(ProtocolConstants.MINECRAFT_1_20_5, 101), map(ProtocolConstants.MINECRAFT_1_21_2, 108), map(ProtocolConstants.MINECRAFT_1_21_5, 107), map(ProtocolConstants.MINECRAFT_1_21_9, 112));
            TO_CLIENT.registerPacket(ClearTitles.class, ClearTitles::new, RegisterType.ENCODE, map(ProtocolConstants.MINECRAFT_1_17, 16), map(ProtocolConstants.MINECRAFT_1_19, 13), map(ProtocolConstants.MINECRAFT_1_19_3, 12), map(ProtocolConstants.MINECRAFT_1_19_4, 14), map(ProtocolConstants.MINECRAFT_1_20_2, 15), map(ProtocolConstants.MINECRAFT_1_21_5, 14));
            TO_CLIENT.registerPacket(Subtitle.class, Subtitle::new, RegisterType.ENCODE, map(ProtocolConstants.MINECRAFT_1_17, 87), map(ProtocolConstants.MINECRAFT_1_18, 88), map(ProtocolConstants.MINECRAFT_1_19_1, 91), map(ProtocolConstants.MINECRAFT_1_19_3, 89), map(ProtocolConstants.MINECRAFT_1_19_4, 93), map(ProtocolConstants.MINECRAFT_1_20_2, 95), map(ProtocolConstants.MINECRAFT_1_20_3, 97), map(ProtocolConstants.MINECRAFT_1_20_5, 99), map(ProtocolConstants.MINECRAFT_1_21_2, 106), map(ProtocolConstants.MINECRAFT_1_21_5, 105), map(ProtocolConstants.MINECRAFT_1_21_9, 110));
            TO_CLIENT.registerPacket(TitleTimes.class, TitleTimes::new, RegisterType.ENCODE, map(ProtocolConstants.MINECRAFT_1_17, 90), map(ProtocolConstants.MINECRAFT_1_18, 91), map(ProtocolConstants.MINECRAFT_1_19_1, 94), map(ProtocolConstants.MINECRAFT_1_19_3, 92), map(ProtocolConstants.MINECRAFT_1_19_4, 96), map(ProtocolConstants.MINECRAFT_1_20_2, 98), map(ProtocolConstants.MINECRAFT_1_20_3, 100), map(ProtocolConstants.MINECRAFT_1_20_5, 102), map(ProtocolConstants.MINECRAFT_1_21_2, 109), map(ProtocolConstants.MINECRAFT_1_21_5, 108), map(ProtocolConstants.MINECRAFT_1_21_9, 113));
            TO_CLIENT.registerPacket(SystemChat.class, SystemChat::new, RegisterType.ENCODE, map(ProtocolConstants.MINECRAFT_1_19, 95), map(ProtocolConstants.MINECRAFT_1_19_1, 98), map(ProtocolConstants.MINECRAFT_1_19_3, 96), map(ProtocolConstants.MINECRAFT_1_19_4, 100), map(ProtocolConstants.MINECRAFT_1_20_2, 103), map(ProtocolConstants.MINECRAFT_1_20_3, 105), map(ProtocolConstants.MINECRAFT_1_20_5, 108), map(ProtocolConstants.MINECRAFT_1_21_2, 115), map(ProtocolConstants.MINECRAFT_1_21_5, 114), map(ProtocolConstants.MINECRAFT_1_21_9, 119));
            TO_CLIENT.registerPacket(PlayerListHeaderFooter.class, PlayerListHeaderFooter::new, RegisterType.ENCODE, map(ProtocolConstants.MINECRAFT_1_8, 71), map(ProtocolConstants.MINECRAFT_1_9, 72), map(ProtocolConstants.MINECRAFT_1_9_4, 71), map(ProtocolConstants.MINECRAFT_1_12, 73), map(ProtocolConstants.MINECRAFT_1_12_1, 74), map(ProtocolConstants.MINECRAFT_1_13, 78), map(ProtocolConstants.MINECRAFT_1_14, 83), map(ProtocolConstants.MINECRAFT_1_15, 84), map(ProtocolConstants.MINECRAFT_1_16, 83), map(ProtocolConstants.MINECRAFT_1_17, 94), map(ProtocolConstants.MINECRAFT_1_18, 95), map(ProtocolConstants.MINECRAFT_1_19, 96), map(ProtocolConstants.MINECRAFT_1_19_1, 99), map(ProtocolConstants.MINECRAFT_1_19_3, 97), map(ProtocolConstants.MINECRAFT_1_19_4, 101), map(ProtocolConstants.MINECRAFT_1_20_2, 104), map(ProtocolConstants.MINECRAFT_1_20_3, 106), map(ProtocolConstants.MINECRAFT_1_20_5, 109), map(ProtocolConstants.MINECRAFT_1_21_2, 116), map(ProtocolConstants.MINECRAFT_1_21_5, 115), map(ProtocolConstants.MINECRAFT_1_21_9, 120));
            TO_CLIENT.registerPacket(EntityStatus.class, EntityStatus::new, RegisterType.ENCODE, map(ProtocolConstants.MINECRAFT_1_8, 26), map(ProtocolConstants.MINECRAFT_1_9, 27), map(ProtocolConstants.MINECRAFT_1_13, 28), map(ProtocolConstants.MINECRAFT_1_14, 27), map(ProtocolConstants.MINECRAFT_1_15, 28), map(ProtocolConstants.MINECRAFT_1_16, 27), map(ProtocolConstants.MINECRAFT_1_16_2, 26), map(ProtocolConstants.MINECRAFT_1_17, 27), map(ProtocolConstants.MINECRAFT_1_19, 24), map(ProtocolConstants.MINECRAFT_1_19_1, 26), map(ProtocolConstants.MINECRAFT_1_19_3, 25), map(ProtocolConstants.MINECRAFT_1_19_4, 28), map(ProtocolConstants.MINECRAFT_1_20_2, 29), map(ProtocolConstants.MINECRAFT_1_20_5, 31), map(ProtocolConstants.MINECRAFT_1_21_5, 30), map(ProtocolConstants.MINECRAFT_1_21_9, 34));
            TO_CLIENT.registerPacket(Commands.class, Commands::new, map(ProtocolConstants.MINECRAFT_1_13, 17), map(ProtocolConstants.MINECRAFT_1_15, 18), map(ProtocolConstants.MINECRAFT_1_16, 17), map(ProtocolConstants.MINECRAFT_1_16_2, 16), map(ProtocolConstants.MINECRAFT_1_17, 18), map(ProtocolConstants.MINECRAFT_1_19, 15), map(ProtocolConstants.MINECRAFT_1_19_3, 14), map(ProtocolConstants.MINECRAFT_1_19_4, 16), map(ProtocolConstants.MINECRAFT_1_20_2, 17), map(ProtocolConstants.MINECRAFT_1_21_5, 16));
            TO_CLIENT.registerPacket(GameState.class, GameState::new, RegisterType.ENCODE, map(ProtocolConstants.MINECRAFT_1_15, 31), map(ProtocolConstants.MINECRAFT_1_16, 30), map(ProtocolConstants.MINECRAFT_1_16_2, 29), map(ProtocolConstants.MINECRAFT_1_17, 30), map(ProtocolConstants.MINECRAFT_1_19, 27), map(ProtocolConstants.MINECRAFT_1_19_1, 29), map(ProtocolConstants.MINECRAFT_1_19_3, 28), map(ProtocolConstants.MINECRAFT_1_19_4, 31), map(ProtocolConstants.MINECRAFT_1_20_2, 32), map(ProtocolConstants.MINECRAFT_1_20_5, 34), map(ProtocolConstants.MINECRAFT_1_21_2, 35), map(ProtocolConstants.MINECRAFT_1_21_5, 34), map(ProtocolConstants.MINECRAFT_1_21_9, 38));
            TO_CLIENT.registerPacket(ViewDistance.class, ViewDistance::new, RegisterType.ENCODE, map(ProtocolConstants.MINECRAFT_1_14, 65), map(ProtocolConstants.MINECRAFT_1_15, 66), map(ProtocolConstants.MINECRAFT_1_16, 65), map(ProtocolConstants.MINECRAFT_1_17, 74), map(ProtocolConstants.MINECRAFT_1_19, 73), map(ProtocolConstants.MINECRAFT_1_19_1, 76), map(ProtocolConstants.MINECRAFT_1_19_3, 75), map(ProtocolConstants.MINECRAFT_1_19_4, 79), map(ProtocolConstants.MINECRAFT_1_20_2, 81), map(ProtocolConstants.MINECRAFT_1_20_3, 83), map(ProtocolConstants.MINECRAFT_1_20_5, 85), map(ProtocolConstants.MINECRAFT_1_21_2, 89), map(ProtocolConstants.MINECRAFT_1_21_5, 88), map(ProtocolConstants.MINECRAFT_1_21_9, 93));
            TO_CLIENT.registerPacket(ServerData.class, ServerData::new, map(ProtocolConstants.MINECRAFT_1_19, 63), map(ProtocolConstants.MINECRAFT_1_19_1, 66), map(ProtocolConstants.MINECRAFT_1_19_3, 65), map(ProtocolConstants.MINECRAFT_1_19_4, 69), map(ProtocolConstants.MINECRAFT_1_20_2, 71), map(ProtocolConstants.MINECRAFT_1_20_3, 73), map(ProtocolConstants.MINECRAFT_1_20_5, 75), map(ProtocolConstants.MINECRAFT_1_21_2, 80), map(ProtocolConstants.MINECRAFT_1_21_5, 79), map(ProtocolConstants.MINECRAFT_1_21_9, 84));
            TO_CLIENT.registerPacket(PlayerListItemRemove.class, PlayerListItemRemove::new, map(ProtocolConstants.MINECRAFT_1_19_3, 53), map(ProtocolConstants.MINECRAFT_1_19_4, 57), map(ProtocolConstants.MINECRAFT_1_20_2, 59), map(ProtocolConstants.MINECRAFT_1_20_5, 61), map(ProtocolConstants.MINECRAFT_1_21_2, 63), map(ProtocolConstants.MINECRAFT_1_21_5, 62), map(ProtocolConstants.MINECRAFT_1_21_9, 67));
            TO_CLIENT.registerPacket(PlayerListItemUpdate.class, PlayerListItemUpdate::new, map(ProtocolConstants.MINECRAFT_1_19_3, 54), map(ProtocolConstants.MINECRAFT_1_19_4, 58), map(ProtocolConstants.MINECRAFT_1_20_2, 60), map(ProtocolConstants.MINECRAFT_1_20_5, 62), map(ProtocolConstants.MINECRAFT_1_21_2, 64), map(ProtocolConstants.MINECRAFT_1_21_5, 63), map(ProtocolConstants.MINECRAFT_1_21_9, 68));
            TO_CLIENT.registerPacket(StartConfiguration.class, StartConfiguration::new, map(ProtocolConstants.MINECRAFT_1_20_2, 101), map(ProtocolConstants.MINECRAFT_1_20_3, 103), map(ProtocolConstants.MINECRAFT_1_20_5, 105), map(ProtocolConstants.MINECRAFT_1_21_2, 112), map(ProtocolConstants.MINECRAFT_1_21_5, 111), map(ProtocolConstants.MINECRAFT_1_21_9, 116));
            TO_CLIENT.registerPacket(CookieRequest.class, CookieRequest::new, map(ProtocolConstants.MINECRAFT_1_20_5, 22), map(ProtocolConstants.MINECRAFT_1_21_5, 21));
            TO_CLIENT.registerPacket(StoreCookie.class, StoreCookie::new, RegisterType.ENCODE, map(ProtocolConstants.MINECRAFT_1_20_5, 107), map(ProtocolConstants.MINECRAFT_1_21_2, 114), map(ProtocolConstants.MINECRAFT_1_21_5, 113), map(ProtocolConstants.MINECRAFT_1_21_9, 118));
            TO_CLIENT.registerPacket(Transfer.class, Transfer::new, RegisterType.ENCODE, map(ProtocolConstants.MINECRAFT_1_20_5, 115), map(ProtocolConstants.MINECRAFT_1_21_2, 122), map(ProtocolConstants.MINECRAFT_1_21_9, 127));
            TO_CLIENT.registerPacket(DisconnectReportDetails.class, DisconnectReportDetails::new, RegisterType.ENCODE, map(ProtocolConstants.MINECRAFT_1_21, 122), map(ProtocolConstants.MINECRAFT_1_21_2, 129), map(ProtocolConstants.MINECRAFT_1_21_9, 134));
            TO_CLIENT.registerPacket(ServerLinks.class, ServerLinks::new, RegisterType.ENCODE, map(ProtocolConstants.MINECRAFT_1_21, 123), map(ProtocolConstants.MINECRAFT_1_21_2, 130), map(ProtocolConstants.MINECRAFT_1_21_9, 135));
            TO_CLIENT.registerPacket(ClearDialog.class, ClearDialog::new, RegisterType.ENCODE, map(ProtocolConstants.MINECRAFT_1_21_6, 132), map(ProtocolConstants.MINECRAFT_1_21_9, 137));
            TO_CLIENT.registerPacket(ShowDialog.class, ShowDialog::new, RegisterType.ENCODE, map(ProtocolConstants.MINECRAFT_1_21_6, 133), map(ProtocolConstants.MINECRAFT_1_21_9, 138));
            TO_SERVER.registerPacket(KeepAlive.class, KeepAlive::new, map(ProtocolConstants.MINECRAFT_1_8, 0), map(ProtocolConstants.MINECRAFT_1_9, 11), map(ProtocolConstants.MINECRAFT_1_12, 12), map(ProtocolConstants.MINECRAFT_1_12_1, 11), map(ProtocolConstants.MINECRAFT_1_13, 14), map(ProtocolConstants.MINECRAFT_1_14, 15), map(ProtocolConstants.MINECRAFT_1_16, 16), map(ProtocolConstants.MINECRAFT_1_17, 15), map(ProtocolConstants.MINECRAFT_1_19, 17), map(ProtocolConstants.MINECRAFT_1_19_1, 18), map(ProtocolConstants.MINECRAFT_1_19_3, 17), map(ProtocolConstants.MINECRAFT_1_19_4, 18), map(ProtocolConstants.MINECRAFT_1_20_2, 20), map(ProtocolConstants.MINECRAFT_1_20_3, 21), map(ProtocolConstants.MINECRAFT_1_20_5, 24), map(ProtocolConstants.MINECRAFT_1_21_2, 26), map(ProtocolConstants.MINECRAFT_1_21_6, 27));
            TO_SERVER.registerPacket(Chat.class, Chat::new, map(ProtocolConstants.MINECRAFT_1_8, 1), map(ProtocolConstants.MINECRAFT_1_9, 2), map(ProtocolConstants.MINECRAFT_1_12, 3), map(ProtocolConstants.MINECRAFT_1_12_1, 2), map(ProtocolConstants.MINECRAFT_1_14, 3), map(ProtocolConstants.MINECRAFT_1_19, -1));
            TO_SERVER.registerPacket(ClientCommand.class, ClientCommand::new, map(ProtocolConstants.MINECRAFT_1_19, 3), map(ProtocolConstants.MINECRAFT_1_19_1, 4), map(ProtocolConstants.MINECRAFT_1_20_5, 5), map(ProtocolConstants.MINECRAFT_1_21_2, 6), map(ProtocolConstants.MINECRAFT_1_21_6, 7));
            TO_SERVER.registerPacket(UnsignedClientCommand.class, UnsignedClientCommand::new, map(ProtocolConstants.MINECRAFT_1_20_5, 4), map(ProtocolConstants.MINECRAFT_1_21_2, 5), map(ProtocolConstants.MINECRAFT_1_21_6, 6));
            TO_SERVER.registerPacket(ClientChat.class, ClientChat::new, map(ProtocolConstants.MINECRAFT_1_19, 4), map(ProtocolConstants.MINECRAFT_1_19_1, 5), map(ProtocolConstants.MINECRAFT_1_20_5, 6), map(ProtocolConstants.MINECRAFT_1_21_2, 7), map(ProtocolConstants.MINECRAFT_1_21_6, 8));
            TO_SERVER.registerPacket(TabCompleteRequest.class, TabCompleteRequest::new, map(ProtocolConstants.MINECRAFT_1_8, 20), map(ProtocolConstants.MINECRAFT_1_9, 1), map(ProtocolConstants.MINECRAFT_1_12, 2), map(ProtocolConstants.MINECRAFT_1_12_1, 1), map(ProtocolConstants.MINECRAFT_1_13, 5), map(ProtocolConstants.MINECRAFT_1_14, 6), map(ProtocolConstants.MINECRAFT_1_19, 8), map(ProtocolConstants.MINECRAFT_1_19_1, 9), map(ProtocolConstants.MINECRAFT_1_19_3, 8), map(ProtocolConstants.MINECRAFT_1_19_4, 9), map(ProtocolConstants.MINECRAFT_1_20_2, 10), map(ProtocolConstants.MINECRAFT_1_20_5, 11), map(ProtocolConstants.MINECRAFT_1_21_2, 13), map(ProtocolConstants.MINECRAFT_1_21_6, 14));
            TO_SERVER.registerPacket(ClientSettings.class, ClientSettings::new, map(ProtocolConstants.MINECRAFT_1_8, 21), map(ProtocolConstants.MINECRAFT_1_9, 4), map(ProtocolConstants.MINECRAFT_1_12, 5), map(ProtocolConstants.MINECRAFT_1_12_1, 4), map(ProtocolConstants.MINECRAFT_1_14, 5), map(ProtocolConstants.MINECRAFT_1_19, 7), map(ProtocolConstants.MINECRAFT_1_19_1, 8), map(ProtocolConstants.MINECRAFT_1_19_3, 7), map(ProtocolConstants.MINECRAFT_1_19_4, 8), map(ProtocolConstants.MINECRAFT_1_20_2, 9), map(ProtocolConstants.MINECRAFT_1_20_5, 10), map(ProtocolConstants.MINECRAFT_1_21_2, 12), map(ProtocolConstants.MINECRAFT_1_21_6, 13));
            TO_SERVER.registerPacket(PluginMessage.class, PluginMessage::new, map(ProtocolConstants.MINECRAFT_1_8, 23), map(ProtocolConstants.MINECRAFT_1_9, 9), map(ProtocolConstants.MINECRAFT_1_12, 10), map(ProtocolConstants.MINECRAFT_1_12_1, 9), map(ProtocolConstants.MINECRAFT_1_13, 10), map(ProtocolConstants.MINECRAFT_1_14, 11), map(ProtocolConstants.MINECRAFT_1_17, 10), map(ProtocolConstants.MINECRAFT_1_19, 12), map(ProtocolConstants.MINECRAFT_1_19_1, 13), map(ProtocolConstants.MINECRAFT_1_19_3, 12), map(ProtocolConstants.MINECRAFT_1_19_4, 13), map(ProtocolConstants.MINECRAFT_1_20_2, 15), map(ProtocolConstants.MINECRAFT_1_20_3, 16), map(ProtocolConstants.MINECRAFT_1_20_5, 18), map(ProtocolConstants.MINECRAFT_1_21_2, 20), map(ProtocolConstants.MINECRAFT_1_21_6, 21));
            TO_SERVER.registerPacket(StartConfiguration.class, StartConfiguration::new, map(ProtocolConstants.MINECRAFT_1_20_2, 11), map(ProtocolConstants.MINECRAFT_1_20_5, 12), map(ProtocolConstants.MINECRAFT_1_21_2, 14), map(ProtocolConstants.MINECRAFT_1_21_6, 15));
            TO_SERVER.registerPacket(CookieResponse.class, CookieResponse::new, map(ProtocolConstants.MINECRAFT_1_20_5, 17), map(ProtocolConstants.MINECRAFT_1_21_2, 19), map(ProtocolConstants.MINECRAFT_1_21_6, 20));
            TO_SERVER.registerPacket(CustomClickAction.class, CustomClickAction::new, map(ProtocolConstants.MINECRAFT_1_21_6, 65));
        }
    },
    
    // 1
    STATUS {
        {
            TO_CLIENT.registerPacket(StatusResponse.class, StatusResponse::new, map(ProtocolConstants.MINECRAFT_1_8, 0));
            TO_CLIENT.registerPacket(PingPacket.class, PingPacket::new, map(ProtocolConstants.MINECRAFT_1_8, 1));
            TO_SERVER.registerPacket(StatusRequest.class, StatusRequest::new, map(ProtocolConstants.MINECRAFT_1_8, 0));
            TO_SERVER.registerPacket(PingPacket.class, PingPacket::new, map(ProtocolConstants.MINECRAFT_1_8, 1));
        }
    },
    
    //2
    LOGIN {
        {
            TO_CLIENT.registerPacket(Kick.class, Kick::new, map(ProtocolConstants.MINECRAFT_1_8, 0));
            TO_CLIENT.registerPacket(EncryptionRequest.class, EncryptionRequest::new, map(ProtocolConstants.MINECRAFT_1_8, 1));
            TO_CLIENT.registerPacket(LoginSuccess.class, LoginSuccess::new, map(ProtocolConstants.MINECRAFT_1_8, 2));
            TO_CLIENT.registerPacket(SetCompression.class, SetCompression::new, map(ProtocolConstants.MINECRAFT_1_8, 3));
            TO_CLIENT.registerPacket(LoginPayloadRequest.class, LoginPayloadRequest::new, map(ProtocolConstants.MINECRAFT_1_13, 4));
            TO_CLIENT.registerPacket(CookieRequest.class, CookieRequest::new, map(ProtocolConstants.MINECRAFT_1_20_5, 5));
            TO_SERVER.registerPacket(LoginRequest.class, LoginRequest::new, map(ProtocolConstants.MINECRAFT_1_8, 0));
            TO_SERVER.registerPacket(EncryptionResponse.class, EncryptionResponse::new, map(ProtocolConstants.MINECRAFT_1_8, 1));
            TO_SERVER.registerPacket(LoginPayloadResponse.class, LoginPayloadResponse::new, map(ProtocolConstants.MINECRAFT_1_13, 2));
            TO_SERVER.registerPacket(LoginAcknowledged.class, LoginAcknowledged::new, map(ProtocolConstants.MINECRAFT_1_20_2, 3));
            TO_SERVER.registerPacket(CookieResponse.class, CookieResponse::new, map(ProtocolConstants.MINECRAFT_1_20_5, 4));
        }
    },
    
    // 3
    CONFIGURATION {
        {
            TO_CLIENT.registerPacket(CookieRequest.class, CookieRequest::new, map(ProtocolConstants.MINECRAFT_1_20_5, 0));
            TO_CLIENT.registerPacket(PluginMessage.class, PluginMessage::new, map(ProtocolConstants.MINECRAFT_1_20_2, 0), map(ProtocolConstants.MINECRAFT_1_20_5, 1));
            TO_CLIENT.registerPacket(Kick.class, Kick::new, map(ProtocolConstants.MINECRAFT_1_20_2, 1), map(ProtocolConstants.MINECRAFT_1_20_5, 2));
            TO_CLIENT.registerPacket(FinishConfiguration.class, FinishConfiguration::new, map(ProtocolConstants.MINECRAFT_1_20_2, 2), map(ProtocolConstants.MINECRAFT_1_20_5, 3));
            TO_CLIENT.registerPacket(KeepAlive.class, KeepAlive::new, map(ProtocolConstants.MINECRAFT_1_20_2, 3), map(ProtocolConstants.MINECRAFT_1_20_5, 4));
            TO_CLIENT.registerPacket(StoreCookie.class, StoreCookie::new, RegisterType.ENCODE, map(ProtocolConstants.MINECRAFT_1_20_5, 10));
            TO_CLIENT.registerPacket(Transfer.class, Transfer::new, RegisterType.ENCODE, map(ProtocolConstants.MINECRAFT_1_20_5, 11));
            TO_CLIENT.registerPacket(DisconnectReportDetails.class, DisconnectReportDetails::new, RegisterType.ENCODE, map(ProtocolConstants.MINECRAFT_1_21, 15));
            TO_CLIENT.registerPacket(ServerLinks.class, ServerLinks::new, RegisterType.ENCODE, map(ProtocolConstants.MINECRAFT_1_21, 16));
            TO_CLIENT.registerPacket(ClearDialog.class, ClearDialog::new, RegisterType.ENCODE, map(ProtocolConstants.MINECRAFT_1_21_6, 17));
            TO_CLIENT.registerPacket(ShowDialogDirect.class, ShowDialogDirect::new, RegisterType.ENCODE, map(ProtocolConstants.MINECRAFT_1_21_6, 18));
            TO_SERVER.registerPacket(ClientSettings.class, ClientSettings::new, map(ProtocolConstants.MINECRAFT_1_20_2, 0));
            TO_SERVER.registerPacket(PluginMessage.class, PluginMessage::new, map(ProtocolConstants.MINECRAFT_1_20_2, 1), map(ProtocolConstants.MINECRAFT_1_20_5, 2));
            TO_SERVER.registerPacket(FinishConfiguration.class, FinishConfiguration::new, map(ProtocolConstants.MINECRAFT_1_20_2, 2), map(ProtocolConstants.MINECRAFT_1_20_5, 3));
            TO_SERVER.registerPacket(KeepAlive.class, KeepAlive::new, map(ProtocolConstants.MINECRAFT_1_20_2, 3), map(ProtocolConstants.MINECRAFT_1_20_5, 4));
            TO_SERVER.registerPacket(CustomClickAction.class, CustomClickAction::new, map(ProtocolConstants.MINECRAFT_1_21_6, 8));
        }
    };
    /*========================================================================*/
    public static final int MAX_PACKET_ID = 255;
    /*========================================================================*/
    public final DirectionData TO_SERVER = new DirectionData(this, ProtocolConstants.Direction.TO_SERVER);
    public final DirectionData TO_CLIENT = new DirectionData(this, ProtocolConstants.Direction.TO_CLIENT);

    public static void main(String[] args) {
        for (int version : ProtocolConstants.SUPPORTED_VERSION_IDS) {
            dump(version);
        }
    }

    private static void dump(int version) {
        for (Protocol protocol : Protocol.values()) {
            dump(version, protocol);
        }
    }

    private static void dump(int version, Protocol protocol) {
        dump(version, protocol.TO_CLIENT);
        dump(version, protocol.TO_SERVER);
    }

    private static void dump(int version, DirectionData data) {
        for (int id = 0; id < MAX_PACKET_ID; id++) {
            DefinedPacket packet = data.createPacket(id, version);
            if (packet != null) {
                System.out.println(version + " " + data.protocolPhase + " " + data.direction + " " + id + " " + packet.getClass().getSimpleName());
            }
        }
    }


    private static class ProtocolData {
        private final int protocolVersion;
        private final Object2IntMap<Class<? extends DefinedPacket>> packetMap = new Object2IntOpenHashMap<>(MAX_PACKET_ID);
        @SuppressWarnings("unchecked")
        private final Supplier<? extends DefinedPacket>[] packetConstructors = new Supplier[MAX_PACKET_ID];

        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public ProtocolData(final int protocolVersion) {
            this.protocolVersion = protocolVersion;
        }

        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public int getProtocolVersion() {
            return this.protocolVersion;
        }

        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public Object2IntMap<Class<? extends DefinedPacket>> getPacketMap() {
            return this.packetMap;
        }

        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public Supplier<? extends DefinedPacket>[] getPacketConstructors() {
            return this.packetConstructors;
        }

        @java.lang.Override
        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public boolean equals(final java.lang.Object o) {
            if (o == this) return true;
            if (!(o instanceof Protocol.ProtocolData)) return false;
            final Protocol.ProtocolData other = (Protocol.ProtocolData) o;
            if (!other.canEqual((java.lang.Object) this)) return false;
            if (this.getProtocolVersion() != other.getProtocolVersion()) return false;
            final java.lang.Object this$packetMap = this.getPacketMap();
            final java.lang.Object other$packetMap = other.getPacketMap();
            if (this$packetMap == null ? other$packetMap != null : !this$packetMap.equals(other$packetMap)) return false;
            if (!java.util.Arrays.deepEquals(this.getPacketConstructors(), other.getPacketConstructors())) return false;
            return true;
        }

        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        protected boolean canEqual(final java.lang.Object other) {
            return other instanceof Protocol.ProtocolData;
        }

        @java.lang.Override
        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public int hashCode() {
            final int PRIME = 59;
            int result = 1;
            result = result * PRIME + this.getProtocolVersion();
            final java.lang.Object $packetMap = this.getPacketMap();
            result = result * PRIME + ($packetMap == null ? 43 : $packetMap.hashCode());
            result = result * PRIME + java.util.Arrays.deepHashCode(this.getPacketConstructors());
            return result;
        }

        @java.lang.Override
        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public java.lang.String toString() {
            return "Protocol.ProtocolData(protocolVersion=" + this.getProtocolVersion() + ", packetMap=" + this.getPacketMap() + ", packetConstructors=" + java.util.Arrays.deepToString(this.getPacketConstructors()) + ")";
        }
    }


    private static class ProtocolMapping {
        private final int protocolVersion;
        private final int packetID;

        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public ProtocolMapping(final int protocolVersion, final int packetID) {
            this.protocolVersion = protocolVersion;
            this.packetID = packetID;
        }

        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public int getProtocolVersion() {
            return this.protocolVersion;
        }

        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public int getPacketID() {
            return this.packetID;
        }

        @java.lang.Override
        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public boolean equals(final java.lang.Object o) {
            if (o == this) return true;
            if (!(o instanceof Protocol.ProtocolMapping)) return false;
            final Protocol.ProtocolMapping other = (Protocol.ProtocolMapping) o;
            if (!other.canEqual((java.lang.Object) this)) return false;
            if (this.getProtocolVersion() != other.getProtocolVersion()) return false;
            if (this.getPacketID() != other.getPacketID()) return false;
            return true;
        }

        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        protected boolean canEqual(final java.lang.Object other) {
            return other instanceof Protocol.ProtocolMapping;
        }

        @java.lang.Override
        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public int hashCode() {
            final int PRIME = 59;
            int result = 1;
            result = result * PRIME + this.getProtocolVersion();
            result = result * PRIME + this.getPacketID();
            return result;
        }

        @java.lang.Override
        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public java.lang.String toString() {
            return "Protocol.ProtocolMapping(protocolVersion=" + this.getProtocolVersion() + ", packetID=" + this.getPacketID() + ")";
        }
    }


    private enum RegisterType {
        // packet is registered to be encoded (only sent, never handled)
        ENCODE, 
        // packet is registered to be decoded (only handled never modified)
        DECODE, 
        // packet is registered to be both, encoded and decoded
        BOTH;

        public boolean encode() {
            return this == BOTH || this == ENCODE;
        }

        public boolean decode() {
            return this == BOTH || this == DECODE;
        }
    }

    // Helper method
    private static ProtocolMapping map(int protocol, int id) {
        return new ProtocolMapping(protocol, id);
    }


    public static final class DirectionData {
        private final Int2ObjectMap<ProtocolData> protocols = new Int2ObjectOpenHashMap<>();
        //
        private final Protocol protocolPhase;
        private final ProtocolConstants.Direction direction;

        public DirectionData(Protocol protocolPhase, ProtocolConstants.Direction direction) {
            this.protocolPhase = protocolPhase;
            this.direction = direction;
            for (int protocol : ProtocolConstants.SUPPORTED_VERSION_IDS) {
                protocols.put(protocol, new ProtocolData(protocol));
            }
        }

        private ProtocolData getProtocolData(int version) {
            ProtocolData protocol = protocols.get(version);
            if (protocol == null && (protocolPhase != Protocol.GAME)) {
                protocol = Iterables.getFirst(protocols.values(), null);
            }
            return protocol;
        }

        public final DefinedPacket createPacket(int id, int version) {
            ProtocolData protocolData = getProtocolData(version);
            if (protocolData == null) {
                throw new BadPacketException("Unsupported protocol version " + version);
            }
            if (id > MAX_PACKET_ID || id < 0) {
                throw new BadPacketException("Packet with id " + id + " outside of range");
            }
            Supplier<? extends DefinedPacket> constructor = protocolData.packetConstructors[id];
            return (constructor == null) ? null : constructor.get();
        }

        private void registerPacket(Class<? extends DefinedPacket> packetClass, Supplier<? extends DefinedPacket> constructor, ProtocolMapping... mappings) {
            registerPacket(packetClass, constructor, RegisterType.BOTH, mappings);
        }

        private void registerPacket(Class<? extends DefinedPacket> packetClass, Supplier<? extends DefinedPacket> constructor, RegisterType registerType, ProtocolMapping... mappings) {
            int mappingIndex = 0;
            ProtocolMapping mapping = mappings[mappingIndex];
            for (int protocol : ProtocolConstants.SUPPORTED_VERSION_IDS) {
                if (protocol < mapping.protocolVersion) {
                    // This is a new packet, skip it till we reach the next protocol
                    continue;
                }
                if (mapping.protocolVersion < protocol && mappingIndex + 1 < mappings.length) {
                    // Mapping is non current, but the next one may be ok
                    ProtocolMapping nextMapping = mappings[mappingIndex + 1];
                    if (nextMapping.protocolVersion == protocol) {
                        Preconditions.checkState(nextMapping.packetID != mapping.packetID, "Duplicate packet mapping (%s, %s)", mapping.protocolVersion, nextMapping.protocolVersion);
                        mapping = nextMapping;
                        mappingIndex++;
                    }
                }
                if (mapping.packetID < 0) {
                    break;
                }
                ProtocolData data = protocols.get(protocol);
                Preconditions.checkState(data.packetConstructors[mapping.packetID] == null, "Duplicate packet mapping (%s)", mapping.packetID);
                Preconditions.checkState(!data.packetMap.containsKey(packetClass), "Duplicate packet mapping (%s)", mapping.packetID);
                if (registerType.encode()) {
                    data.packetMap.put(packetClass, mapping.packetID);
                }
                if (registerType.decode()) {
                    data.packetConstructors[mapping.packetID] = constructor;
                }
            }
        }

        public boolean hasPacket(Class<? extends DefinedPacket> packet, int version) {
            ProtocolData protocolData = getProtocolData(version);
            if (protocolData == null) {
                throw new BadPacketException("Unsupported protocol version");
            }
            return protocolData.packetMap.containsKey(packet);
        }

        final int getId(Class<? extends DefinedPacket> packet, int version) {
            ProtocolData protocolData = getProtocolData(version);
            if (protocolData == null) {
                throw new BadPacketException("Unsupported protocol version");
            }
            Preconditions.checkArgument(protocolData.packetMap.containsKey(packet), "Cannot get ID for packet %s in phase %s with direction %s", packet, protocolPhase, direction);
            return protocolData.packetMap.get(packet);
        }

        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public ProtocolConstants.Direction getDirection() {
            return this.direction;
        }
    }
}
