// Generated by delombok at Sat Oct 04 04:46:56 UTC 2025
package net.md_5.bungee.protocol.packet;

import com.google.common.base.Preconditions;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.arguments.DoubleArgumentType;
import com.mojang.brigadier.arguments.FloatArgumentType;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.arguments.LongArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import com.mojang.brigadier.tree.ArgumentCommandNode;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.LiteralCommandNode;
import com.mojang.brigadier.tree.RootCommandNode;
import io.netty.buffer.ByteBuf;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Deque;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.ProtocolConstants;

public class Commands extends DefinedPacket {
    private static final int FLAG_TYPE = 3;
    private static final int FLAG_EXECUTABLE = 4;
    private static final int FLAG_REDIRECT = 8;
    private static final int FLAG_SUGGESTIONS = 16;
    //
    private static final int NODE_ROOT = 0;
    private static final int NODE_LITERAL = 1;
    private static final int NODE_ARGUMENT = 2;
    //
    private RootCommandNode root;

    @Override
    public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) {
        int nodeCount = readVarInt(buf);
        NetworkNode[] nodes = new NetworkNode[nodeCount];
        Deque<NetworkNode> nodeQueue = new ArrayDeque<>(nodes.length);
        for (int i = 0; i < nodeCount; i++) {
            byte flags = buf.readByte();
            int[] children = readVarIntArray(buf);
            int redirectNode = ((flags & FLAG_REDIRECT) != 0) ? readVarInt(buf) : 0;
            ArgumentBuilder argumentBuilder;
            switch (flags & FLAG_TYPE) {
            case NODE_ROOT: 
                argumentBuilder = null;
                break;
            case NODE_LITERAL: 
                argumentBuilder = LiteralArgumentBuilder.literal(readString(buf));
                break;
            case NODE_ARGUMENT: 
                String name = readString(buf);
                argumentBuilder = RequiredArgumentBuilder.argument(name, ArgumentRegistry.read(buf, protocolVersion));
                if ((flags & FLAG_SUGGESTIONS) != 0) {
                    String suggster = readString(buf);
                    ((RequiredArgumentBuilder) argumentBuilder).suggests(SuggestionRegistry.getProvider(suggster));
                }
                break;
            default: 
                throw new IllegalArgumentException("Unhandled node type " + flags);
            }
            NetworkNode node = new NetworkNode(argumentBuilder, flags, redirectNode, children);
            nodes[i] = node;
            nodeQueue.add(node);
        }
        boolean mustCycle;
        do {
            if (nodeQueue.isEmpty()) {
                int rootIndex = readVarInt(buf);
                root = (RootCommandNode<?>) nodes[rootIndex].command;
                return;
            }
            mustCycle = false;
            for (Iterator<NetworkNode> iter = nodeQueue.iterator(); iter.hasNext(); ) {
                NetworkNode node = iter.next();
                if (node.buildSelf(nodes)) {
                    iter.remove();
                    mustCycle = true;
                }
            }
        } while (mustCycle);
        throw new IllegalStateException("Did not finish building root node");
    }

    @Override
    public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) {
        Map<CommandNode, Integer> indexMap = new LinkedHashMap<>();
        Deque<CommandNode> nodeQueue = new ArrayDeque<>();
        nodeQueue.add(root);
        while (!nodeQueue.isEmpty()) {
            CommandNode command = nodeQueue.pollFirst();
            if (!indexMap.containsKey(command)) {
                // Index the new node
                int currentIndex = indexMap.size();
                indexMap.put(command, currentIndex);
                // Queue children and redirect for processing
                nodeQueue.addAll(command.getChildren());
                if (command.getRedirect() != null) {
                    nodeQueue.add(command.getRedirect());
                }
            }
        }
        // Write out size
        writeVarInt(indexMap.size(), buf);
        int currentIndex = 0;
        for (Map.Entry<CommandNode, Integer> entry : indexMap.entrySet()) {
            // Using a LinkedHashMap, but sanity check this assumption
            Preconditions.checkState(entry.getValue() == currentIndex++, "Iteration out of order!");
            CommandNode node = entry.getKey();
            byte flags = 0;
            if (node.getRedirect() != null) {
                flags |= FLAG_REDIRECT;
            }
            if (node.getCommand() != null) {
                flags |= FLAG_EXECUTABLE;
            }
            if (node instanceof RootCommandNode) {
                flags |= NODE_ROOT;
            } else if (node instanceof LiteralCommandNode) {
                flags |= NODE_LITERAL;
            } else if (node instanceof ArgumentCommandNode) {
                flags |= NODE_ARGUMENT;
                if (((ArgumentCommandNode) node).getCustomSuggestions() != null) {
                    flags |= FLAG_SUGGESTIONS;
                }
            } else {
                throw new IllegalArgumentException("Unhandled node type " + node);
            }
            buf.writeByte(flags);
            writeVarInt(node.getChildren().size(), buf);
            for (CommandNode child : (Collection<CommandNode>) node.getChildren()) {
                writeVarInt(indexMap.get(child), buf);
            }
            if (node.getRedirect() != null) {
                writeVarInt(indexMap.get(node.getRedirect()), buf);
            }
            if (node instanceof LiteralCommandNode) {
                writeString(((LiteralCommandNode) node).getLiteral(), buf);
            } else if (node instanceof ArgumentCommandNode) {
                ArgumentCommandNode argumentNode = (ArgumentCommandNode) node;
                writeString(argumentNode.getName(), buf);
                ArgumentRegistry.write(argumentNode.getType(), buf, protocolVersion);
                if (argumentNode.getCustomSuggestions() != null) {
                    writeString(SuggestionRegistry.getKey(argumentNode.getCustomSuggestions()), buf);
                }
            }
        }
        // Get, check, and write the root index (should be first)
        int rootIndex = indexMap.get(root);
        Preconditions.checkState(rootIndex == 0, "How did root not land up at index 0?!?");
        writeVarInt(rootIndex, buf);
    }

    @Override
    public void handle(AbstractPacketHandler handler) throws Exception {
        handler.handle(this);
    }


    private static class NetworkNode {
        private final ArgumentBuilder argumentBuilder;
        private final byte flags;
        private final int redirectNode;
        private final int[] children;
        private CommandNode command;

        private boolean buildSelf(NetworkNode[] otherNodes) {
            // First cycle
            if (command == null) {
                // Root node is merely the root
                if (argumentBuilder == null) {
                    command = new RootCommandNode();
                } else {
                    // Add the redirect
                    if ((flags & FLAG_REDIRECT) != 0) {
                        if (otherNodes[redirectNode].command == null) {
                            return false;
                        }
                        argumentBuilder.redirect(otherNodes[redirectNode].command);
                    }
                    // Add dummy executable
                    if ((flags & FLAG_EXECUTABLE) != 0) {
                        argumentBuilder.executes(new Command() {
                            @Override
                            public int run(CommandContext context) throws CommandSyntaxException {
                                return 0;
                            }
                        });
                    }
                    // Build our self command
                    command = argumentBuilder.build();
                }
            }
            // Check that we have processed all children thus far
            for (int childIndex : children) {
                if (otherNodes[childIndex].command == null) {
                    // If not, we have to do another cycle
                    return false;
                }
            }
            for (int childIndex : children) {
                CommandNode<?> child = otherNodes[childIndex].command;
                Preconditions.checkArgument(!(child instanceof RootCommandNode), "Cannot have RootCommandNode as child");
                command.addChild(child);
            }
            return true;
        }

        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public NetworkNode(final ArgumentBuilder argumentBuilder, final byte flags, final int redirectNode, final int[] children) {
            this.argumentBuilder = argumentBuilder;
            this.flags = flags;
            this.redirectNode = redirectNode;
            this.children = children;
        }

        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public ArgumentBuilder getArgumentBuilder() {
            return this.argumentBuilder;
        }

        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public byte getFlags() {
            return this.flags;
        }

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

        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public int[] getChildren() {
            return this.children;
        }

        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public CommandNode getCommand() {
            return this.command;
        }

        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public void setCommand(final CommandNode command) {
            this.command = command;
        }

        @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 Commands.NetworkNode)) return false;
            final Commands.NetworkNode other = (Commands.NetworkNode) o;
            if (!other.canEqual((java.lang.Object) this)) return false;
            if (this.getFlags() != other.getFlags()) return false;
            if (this.getRedirectNode() != other.getRedirectNode()) return false;
            final java.lang.Object this$argumentBuilder = this.getArgumentBuilder();
            final java.lang.Object other$argumentBuilder = other.getArgumentBuilder();
            if (this$argumentBuilder == null ? other$argumentBuilder != null : !this$argumentBuilder.equals(other$argumentBuilder)) return false;
            if (!java.util.Arrays.equals(this.getChildren(), other.getChildren())) return false;
            final java.lang.Object this$command = this.getCommand();
            final java.lang.Object other$command = other.getCommand();
            if (this$command == null ? other$command != null : !this$command.equals(other$command)) return false;
            return true;
        }

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

        @java.lang.Override
        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public int hashCode() {
            final int PRIME = 59;
            int result = 1;
            result = result * PRIME + this.getFlags();
            result = result * PRIME + this.getRedirectNode();
            final java.lang.Object $argumentBuilder = this.getArgumentBuilder();
            result = result * PRIME + ($argumentBuilder == null ? 43 : $argumentBuilder.hashCode());
            result = result * PRIME + java.util.Arrays.hashCode(this.getChildren());
            final java.lang.Object $command = this.getCommand();
            result = result * PRIME + ($command == null ? 43 : $command.hashCode());
            return result;
        }

        @java.lang.Override
        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public java.lang.String toString() {
            return "Commands.NetworkNode(argumentBuilder=" + this.getArgumentBuilder() + ", flags=" + this.getFlags() + ", redirectNode=" + this.getRedirectNode() + ", children=" + java.util.Arrays.toString(this.getChildren()) + ", command=" + this.getCommand() + ")";
        }
    }


    private static class ArgumentRegistry {
        private static final Map<String, ArgumentSerializer> PROVIDERS = new HashMap<>();
        private static final ArgumentSerializer[] IDS_1_19;
        private static final ArgumentSerializer[] IDS_1_19_3;
        private static final ArgumentSerializer[] IDS_1_19_4;
        private static final ArgumentSerializer[] IDS_1_20_3;
        private static final ArgumentSerializer[] IDS_1_20_5;
        private static final ArgumentSerializer[] IDS_1_21_5;
        private static final ArgumentSerializer[] IDS_1_21_6;
        private static final Map<Class<?>, ProperArgumentSerializer<?>> PROPER_PROVIDERS = new HashMap<>();
        //
        private static final ArgumentSerializer<Void> VOID = new ArgumentSerializer<Void>() {
            @Override
            protected Void read(ByteBuf buf) {
                return null;
            }
            @Override
            protected void write(ByteBuf buf, Void t) {
            }
        };
        private static final ArgumentSerializer<Boolean> BOOLEAN = new ArgumentSerializer<Boolean>() {
            @Override
            protected Boolean read(ByteBuf buf) {
                return buf.readBoolean();
            }
            @Override
            protected void write(ByteBuf buf, Boolean t) {
                buf.writeBoolean(t);
            }
        };
        private static final ArgumentSerializer<Byte> BYTE = new ArgumentSerializer<Byte>() {
            @Override
            protected Byte read(ByteBuf buf) {
                return buf.readByte();
            }
            @Override
            protected void write(ByteBuf buf, Byte t) {
                buf.writeByte(t);
            }
        };
        private static final ArgumentSerializer<FloatArgumentType> FLOAT_RANGE = new ArgumentSerializer<FloatArgumentType>() {
            @Override
            protected FloatArgumentType read(ByteBuf buf) {
                byte flags = buf.readByte();
                float min = (flags & 1) != 0 ? buf.readFloat() : -Float.MAX_VALUE;
                float max = (flags & 2) != 0 ? buf.readFloat() : Float.MAX_VALUE;
                return FloatArgumentType.floatArg(min, max);
            }
            @Override
            protected void write(ByteBuf buf, FloatArgumentType t) {
                boolean hasMin = t.getMinimum() != -Float.MAX_VALUE;
                boolean hasMax = t.getMaximum() != Float.MAX_VALUE;
                buf.writeByte(binaryFlag(hasMin, hasMax));
                if (hasMin) {
                    buf.writeFloat(t.getMinimum());
                }
                if (hasMax) {
                    buf.writeFloat(t.getMaximum());
                }
            }
        };
        private static final ArgumentSerializer<DoubleArgumentType> DOUBLE_RANGE = new ArgumentSerializer<DoubleArgumentType>() {
            @Override
            protected DoubleArgumentType read(ByteBuf buf) {
                byte flags = buf.readByte();
                double min = (flags & 1) != 0 ? buf.readDouble() : -Double.MAX_VALUE;
                double max = (flags & 2) != 0 ? buf.readDouble() : Double.MAX_VALUE;
                return DoubleArgumentType.doubleArg(min, max);
            }
            @Override
            protected void write(ByteBuf buf, DoubleArgumentType t) {
                boolean hasMin = t.getMinimum() != -Double.MAX_VALUE;
                boolean hasMax = t.getMaximum() != Double.MAX_VALUE;
                buf.writeByte(binaryFlag(hasMin, hasMax));
                if (hasMin) {
                    buf.writeDouble(t.getMinimum());
                }
                if (hasMax) {
                    buf.writeDouble(t.getMaximum());
                }
            }
        };
        private static final ArgumentSerializer<IntegerArgumentType> INTEGER_RANGE = new ArgumentSerializer<IntegerArgumentType>() {
            @Override
            protected IntegerArgumentType read(ByteBuf buf) {
                byte flags = buf.readByte();
                int min = (flags & 1) != 0 ? buf.readInt() : Integer.MIN_VALUE;
                int max = (flags & 2) != 0 ? buf.readInt() : Integer.MAX_VALUE;
                return IntegerArgumentType.integer(min, max);
            }
            @Override
            protected void write(ByteBuf buf, IntegerArgumentType t) {
                boolean hasMin = t.getMinimum() != Integer.MIN_VALUE;
                boolean hasMax = t.getMaximum() != Integer.MAX_VALUE;
                buf.writeByte(binaryFlag(hasMin, hasMax));
                if (hasMin) {
                    buf.writeInt(t.getMinimum());
                }
                if (hasMax) {
                    buf.writeInt(t.getMaximum());
                }
            }
        };
        private static final ArgumentSerializer<Integer> INTEGER = new ArgumentSerializer<Integer>() {
            @Override
            protected Integer read(ByteBuf buf) {
                return buf.readInt();
            }
            @Override
            protected void write(ByteBuf buf, Integer t) {
                buf.writeInt(t);
            }
        };
        private static final ArgumentSerializer<LongArgumentType> LONG_RANGE = new ArgumentSerializer<LongArgumentType>() {
            @Override
            protected LongArgumentType read(ByteBuf buf) {
                byte flags = buf.readByte();
                long min = (flags & 1) != 0 ? buf.readLong() : Long.MIN_VALUE;
                long max = (flags & 2) != 0 ? buf.readLong() : Long.MAX_VALUE;
                return LongArgumentType.longArg(min, max);
            }
            @Override
            protected void write(ByteBuf buf, LongArgumentType t) {
                boolean hasMin = t.getMinimum() != Long.MIN_VALUE;
                boolean hasMax = t.getMaximum() != Long.MAX_VALUE;
                buf.writeByte(binaryFlag(hasMin, hasMax));
                if (hasMin) {
                    buf.writeLong(t.getMinimum());
                }
                if (hasMax) {
                    buf.writeLong(t.getMaximum());
                }
            }
        };
        private static final ProperArgumentSerializer<StringArgumentType> STRING = new ProperArgumentSerializer<StringArgumentType>() {
            @Override
            protected StringArgumentType read(ByteBuf buf) {
                int val = readVarInt(buf);
                switch (val) {
                case 0: 
                    return StringArgumentType.word();
                case 1: 
                    return StringArgumentType.string();
                case 2: 
                    return StringArgumentType.greedyString();
                default: 
                    throw new IllegalArgumentException("Unknown string type " + val);
                }
            }
            @Override
            protected void write(ByteBuf buf, StringArgumentType t) {
                writeVarInt(t.getType().ordinal(), buf);
            }
            @Override
            protected int getIntKey() {
                return 5;
            }
            @Override
            protected String getKey() {
                return "brigadier:string";
            }
        };
        private static final ArgumentSerializer<String> RAW_STRING = new ArgumentSerializer<String>() {
            @Override
            protected String read(ByteBuf buf) {
                return DefinedPacket.readString(buf);
            }
            @Override
            protected void write(ByteBuf buf, String t) {
                DefinedPacket.writeString(t, buf);
            }
        };

        static {
            register("brigadier:bool", VOID);
            register("brigadier:float", FLOAT_RANGE);
            register("brigadier:double", DOUBLE_RANGE);
            register("brigadier:integer", INTEGER_RANGE);
            register("brigadier:long", LONG_RANGE);
            register("brigadier:string", STRING);
            PROPER_PROVIDERS.put(StringArgumentType.class, STRING);
            register("minecraft:entity", BYTE);
            register("minecraft:game_profile", VOID);
            register("minecraft:block_pos", VOID);
            register("minecraft:column_pos", VOID);
            register("minecraft:vec3", VOID);
            register("minecraft:vec2", VOID);
            register("minecraft:block_state", VOID);
            register("minecraft:block_predicate", VOID);
            register("minecraft:item_stack", VOID);
            register("minecraft:item_predicate", VOID);
            register("minecraft:color", VOID);
            register("minecraft:component", VOID);
            register("minecraft:message", VOID);
            register("minecraft:nbt_compound_tag", VOID); // 1.14
            register("minecraft:nbt_tag", VOID); // 1.14
            register("minecraft:nbt_path", VOID);
            register("minecraft:objective", VOID);
            register("minecraft:objective_criteria", VOID);
            register("minecraft:operation", VOID);
            register("minecraft:particle", VOID);
            register("minecraft:angle", VOID); // 1.16.2
            register("minecraft:rotation", VOID);
            register("minecraft:scoreboard_slot", VOID);
            register("minecraft:score_holder", BYTE);
            register("minecraft:swizzle", VOID);
            register("minecraft:team", VOID);
            register("minecraft:item_slot", VOID);
            register("minecraft:resource_location", VOID);
            register("minecraft:mob_effect", VOID);
            register("minecraft:function", VOID);
            register("minecraft:entity_anchor", VOID);
            register("minecraft:int_range", VOID);
            register("minecraft:float_range", VOID);
            register("minecraft:item_enchantment", VOID);
            register("minecraft:entity_summon", VOID);
            register("minecraft:dimension", VOID);
            register("minecraft:time", VOID); // 1.14
            register("minecraft:resource_or_tag", RAW_STRING); // 1.18.2
            register("minecraft:resource", RAW_STRING); // 1.18.2
            register("minecraft:uuid", VOID); // 1.16
            register("minecraft:nbt", VOID); // 1.13 // removed
            IDS_1_19 = new ArgumentSerializer[] {get("brigadier:bool", VOID), get("brigadier:float", FLOAT_RANGE), get("brigadier:double", DOUBLE_RANGE), get("brigadier:integer", INTEGER_RANGE), get("brigadier:long", LONG_RANGE), get("brigadier:string", STRING), get("minecraft:entity", BYTE), get("minecraft:game_profile", VOID), get("minecraft:block_pos", VOID), get("minecraft:column_pos", VOID), get("minecraft:vec3", VOID), get("minecraft:vec2", VOID), get("minecraft:block_state", VOID), get("minecraft:block_predicate", VOID), get("minecraft:item_stack", VOID), get("minecraft:item_predicate", VOID), get("minecraft:color", VOID), get("minecraft:component", VOID), get("minecraft:message", VOID), get("minecraft:nbt_compound_tag", VOID), get("minecraft:nbt_tag", VOID), get("minecraft:nbt_path", VOID), get("minecraft:objective", VOID), get("minecraft:objective_criteria", VOID), get("minecraft:operation", VOID), get("minecraft:particle", VOID), get("minecraft:angle", VOID), get("minecraft:rotation", VOID), get("minecraft:scoreboard_slot", VOID), get("minecraft:score_holder", BYTE), get("minecraft:swizzle", VOID), get("minecraft:team", VOID), get("minecraft:item_slot", VOID), get("minecraft:resource_location", VOID), get("minecraft:mob_effect", VOID), get("minecraft:function", VOID), get("minecraft:entity_anchor", VOID), get("minecraft:int_range", VOID), get("minecraft:float_range", VOID), get("minecraft:item_enchantment", VOID), get("minecraft:entity_summon", VOID), get("minecraft:dimension", VOID), get("minecraft:time", VOID), get("minecraft:resource_or_tag", RAW_STRING), get("minecraft:resource", RAW_STRING), get("minecraft:template_mirror", VOID), get("minecraft:template_rotation", VOID), get("minecraft:uuid", VOID)};
            IDS_1_19_3 = new ArgumentSerializer[] {get("brigadier:bool", VOID), get("brigadier:float", FLOAT_RANGE), get("brigadier:double", DOUBLE_RANGE), get("brigadier:integer", INTEGER_RANGE), get("brigadier:long", LONG_RANGE), get("brigadier:string", STRING), get("minecraft:entity", BYTE), get("minecraft:game_profile", VOID), get("minecraft:block_pos", VOID), get("minecraft:column_pos", VOID), get("minecraft:vec3", VOID), get("minecraft:vec2", VOID), get("minecraft:block_state", VOID), get("minecraft:block_predicate", VOID), get("minecraft:item_stack", VOID), get("minecraft:item_predicate", VOID), get("minecraft:color", VOID), get("minecraft:component", VOID), get("minecraft:message", VOID), get("minecraft:nbt_compound_tag", VOID), get("minecraft:nbt_tag", VOID), get("minecraft:nbt_path", VOID), get("minecraft:objective", VOID), get("minecraft:objective_criteria", VOID), get("minecraft:operation", VOID), get("minecraft:particle", VOID), get("minecraft:angle", VOID), get("minecraft:rotation", VOID), get("minecraft:scoreboard_slot", VOID), get("minecraft:score_holder", BYTE), get("minecraft:swizzle", VOID), get("minecraft:team", VOID), get("minecraft:item_slot", VOID), get("minecraft:resource_location", VOID), get("minecraft:function", VOID), get("minecraft:entity_anchor", VOID), get("minecraft:int_range", VOID), get("minecraft:float_range", VOID), get("minecraft:dimension", VOID), get("minecraft:gamemode", VOID), get("minecraft:time", VOID), get("minecraft:resource_or_tag", RAW_STRING), get("minecraft:resource_or_tag_key", RAW_STRING), get("minecraft:resource", RAW_STRING), get("minecraft:resource_key", RAW_STRING), get("minecraft:template_mirror", VOID), get("minecraft:template_rotation", VOID), get("minecraft:uuid", VOID)};
            IDS_1_19_4 = new ArgumentSerializer[] {get("brigadier:bool", VOID), get("brigadier:float", FLOAT_RANGE), get("brigadier:double", DOUBLE_RANGE), get("brigadier:integer", INTEGER_RANGE), get("brigadier:long", LONG_RANGE), get("brigadier:string", STRING), get("minecraft:entity", BYTE), get("minecraft:game_profile", VOID), get("minecraft:block_pos", VOID), get("minecraft:column_pos", VOID), get("minecraft:vec3", VOID), get("minecraft:vec2", VOID), get("minecraft:block_state", VOID), get("minecraft:block_predicate", VOID), get("minecraft:item_stack", VOID), get("minecraft:item_predicate", VOID), get("minecraft:color", VOID), get("minecraft:component", VOID), get("minecraft:message", VOID), get("minecraft:nbt_compound_tag", VOID), get("minecraft:nbt_tag", VOID), get("minecraft:nbt_path", VOID), get("minecraft:objective", VOID), get("minecraft:objective_criteria", VOID), get("minecraft:operation", VOID), get("minecraft:particle", VOID), get("minecraft:angle", VOID), get("minecraft:rotation", VOID), get("minecraft:scoreboard_slot", VOID), get("minecraft:score_holder", BYTE), get("minecraft:swizzle", VOID), get("minecraft:team", VOID), get("minecraft:item_slot", VOID), get("minecraft:resource_location", VOID), get("minecraft:function", VOID), get("minecraft:entity_anchor", VOID), get("minecraft:int_range", VOID), get("minecraft:float_range", VOID), get("minecraft:dimension", VOID), get("minecraft:gamemode", VOID), get("minecraft:time", INTEGER), get("minecraft:resource_or_tag", RAW_STRING), get("minecraft:resource_or_tag_key", RAW_STRING), get("minecraft:resource", RAW_STRING), get("minecraft:resource_key", RAW_STRING), get("minecraft:template_mirror", VOID), get("minecraft:template_rotation", VOID), get("minecraft:heightmap", VOID), get("minecraft:uuid", VOID)};
            IDS_1_20_3 = new ArgumentSerializer[] {get("brigadier:bool", VOID), get("brigadier:float", FLOAT_RANGE), get("brigadier:double", DOUBLE_RANGE), get("brigadier:integer", INTEGER_RANGE), get("brigadier:long", LONG_RANGE), get("brigadier:string", STRING), get("minecraft:entity", BYTE), get("minecraft:game_profile", VOID), get("minecraft:block_pos", VOID), get("minecraft:column_pos", VOID), get("minecraft:vec3", VOID), get("minecraft:vec2", VOID), get("minecraft:block_state", VOID), get("minecraft:block_predicate", VOID), get("minecraft:item_stack", VOID), get("minecraft:item_predicate", VOID), get("minecraft:color", VOID), get("minecraft:component", VOID), get("minecraft:style", VOID), get("minecraft:message", VOID), get("minecraft:nbt_compound_tag", VOID), get("minecraft:nbt_tag", VOID), get("minecraft:nbt_path", VOID), get("minecraft:objective", VOID), get("minecraft:objective_criteria", VOID), get("minecraft:operation", VOID), get("minecraft:particle", VOID), get("minecraft:angle", VOID), get("minecraft:rotation", VOID), get("minecraft:scoreboard_slot", VOID), get("minecraft:score_holder", BYTE), get("minecraft:swizzle", VOID), get("minecraft:team", VOID), get("minecraft:item_slot", VOID), get("minecraft:resource_location", VOID), get("minecraft:function", VOID), get("minecraft:entity_anchor", VOID), get("minecraft:int_range", VOID), get("minecraft:float_range", VOID), get("minecraft:dimension", VOID), get("minecraft:gamemode", VOID), get("minecraft:time", INTEGER), get("minecraft:resource_or_tag", RAW_STRING), get("minecraft:resource_or_tag_key", RAW_STRING), get("minecraft:resource", RAW_STRING), get("minecraft:resource_key", RAW_STRING), get("minecraft:template_mirror", VOID), get("minecraft:template_rotation", VOID), get("minecraft:heightmap", VOID), get("minecraft:uuid", VOID)};
            IDS_1_20_5 = new ArgumentSerializer[] {get("brigadier:bool", VOID), get("brigadier:float", FLOAT_RANGE), get("brigadier:double", DOUBLE_RANGE), get("brigadier:integer", INTEGER_RANGE), get("brigadier:long", LONG_RANGE), get("brigadier:string", STRING), get("minecraft:entity", BYTE), get("minecraft:game_profile", VOID), get("minecraft:block_pos", VOID), get("minecraft:column_pos", VOID), get("minecraft:vec3", VOID), get("minecraft:vec2", VOID), get("minecraft:block_state", VOID), get("minecraft:block_predicate", VOID), get("minecraft:item_stack", VOID), get("minecraft:item_predicate", VOID), get("minecraft:color", VOID), get("minecraft:component", VOID), get("minecraft:style", VOID), get("minecraft:message", VOID), get("minecraft:nbt_compound_tag", VOID), get("minecraft:nbt_tag", VOID), get("minecraft:nbt_path", VOID), get("minecraft:objective", VOID), get("minecraft:objective_criteria", VOID), get("minecraft:operation", VOID), get("minecraft:particle", VOID), get("minecraft:angle", VOID), get("minecraft:rotation", VOID), get("minecraft:scoreboard_slot", VOID), get("minecraft:score_holder", BYTE), get("minecraft:swizzle", VOID), get("minecraft:team", VOID), get("minecraft:item_slot", VOID), get("minecraft:item_slots", VOID), get("minecraft:resource_location", VOID), get("minecraft:function", VOID), get("minecraft:entity_anchor", VOID), get("minecraft:int_range", VOID), get("minecraft:float_range", VOID), get("minecraft:dimension", VOID), get("minecraft:gamemode", VOID), get("minecraft:time", INTEGER), get("minecraft:resource_or_tag", RAW_STRING), get("minecraft:resource_or_tag_key", RAW_STRING), get("minecraft:resource", RAW_STRING), get("minecraft:resource_key", RAW_STRING), get("minecraft:template_mirror", VOID), get("minecraft:template_rotation", VOID), get("minecraft:heightmap", VOID), get("minecraft:loot_table", VOID), get("minecraft:loot_predicate", VOID), get("minecraft:loot_modifier", VOID), get("minecraft:uuid", VOID)};
            IDS_1_21_5 = new ArgumentSerializer[] {get("brigadier:bool", VOID), get("brigadier:float", FLOAT_RANGE), get("brigadier:double", DOUBLE_RANGE), get("brigadier:integer", INTEGER_RANGE), get("brigadier:long", LONG_RANGE), get("brigadier:string", STRING), get("minecraft:entity", BYTE), get("minecraft:game_profile", VOID), get("minecraft:block_pos", VOID), get("minecraft:column_pos", VOID), get("minecraft:vec3", VOID), get("minecraft:vec2", VOID), get("minecraft:block_state", VOID), get("minecraft:block_predicate", VOID), get("minecraft:item_stack", VOID), get("minecraft:item_predicate", VOID), get("minecraft:color", VOID), get("minecraft:component", VOID), get("minecraft:style", VOID), get("minecraft:message", VOID), get("minecraft:nbt_compound_tag", VOID), get("minecraft:nbt_tag", VOID), get("minecraft:nbt_path", VOID), get("minecraft:objective", VOID), get("minecraft:objective_criteria", VOID), get("minecraft:operation", VOID), get("minecraft:particle", VOID), get("minecraft:angle", VOID), get("minecraft:rotation", VOID), get("minecraft:scoreboard_slot", VOID), get("minecraft:score_holder", BYTE), get("minecraft:swizzle", VOID), get("minecraft:team", VOID), get("minecraft:item_slot", VOID), get("minecraft:item_slots", VOID), get("minecraft:resource_location", VOID), get("minecraft:function", VOID), get("minecraft:entity_anchor", VOID), get("minecraft:int_range", VOID), get("minecraft:float_range", VOID), get("minecraft:dimension", VOID), get("minecraft:gamemode", VOID), get("minecraft:time", INTEGER), get("minecraft:resource_or_tag", RAW_STRING), get("minecraft:resource_or_tag_key", RAW_STRING), get("minecraft:resource", RAW_STRING), get("minecraft:resource_key", RAW_STRING), get("minecraft:resource_selector", RAW_STRING), get("minecraft:template_mirror", VOID), get("minecraft:template_rotation", VOID), get("minecraft:heightmap", VOID), get("minecraft:loot_table", VOID), get("minecraft:loot_predicate", VOID), get("minecraft:loot_modifier", VOID), get("minecraft:uuid", VOID)};
            IDS_1_21_6 = new ArgumentSerializer[] {get("brigadier:bool", VOID), get("brigadier:float", FLOAT_RANGE), get("brigadier:double", DOUBLE_RANGE), get("brigadier:integer", INTEGER_RANGE), get("brigadier:long", LONG_RANGE), get("brigadier:string", STRING), get("minecraft:entity", BYTE), get("minecraft:game_profile", VOID), get("minecraft:block_pos", VOID), get("minecraft:column_pos", VOID), get("minecraft:vec3", VOID), get("minecraft:vec2", VOID), get("minecraft:block_state", VOID), get("minecraft:block_predicate", VOID), get("minecraft:item_stack", VOID), get("minecraft:item_predicate", VOID), get("minecraft:color", VOID), get("minecraft:hex_color", VOID), get("minecraft:component", VOID), get("minecraft:style", VOID), get("minecraft:message", VOID), get("minecraft:nbt_compound_tag", VOID), get("minecraft:nbt_tag", VOID), get("minecraft:nbt_path", VOID), get("minecraft:objective", VOID), get("minecraft:objective_criteria", VOID), get("minecraft:operation", VOID), get("minecraft:particle", VOID), get("minecraft:angle", VOID), get("minecraft:rotation", VOID), get("minecraft:scoreboard_slot", VOID), get("minecraft:score_holder", BYTE), get("minecraft:swizzle", VOID), get("minecraft:team", VOID), get("minecraft:item_slot", VOID), get("minecraft:item_slots", VOID), get("minecraft:resource_location", VOID), get("minecraft:function", VOID), get("minecraft:entity_anchor", VOID), get("minecraft:int_range", VOID), get("minecraft:float_range", VOID), get("minecraft:dimension", VOID), get("minecraft:gamemode", VOID), get("minecraft:time", INTEGER), get("minecraft:resource_or_tag", RAW_STRING), get("minecraft:resource_or_tag_key", RAW_STRING), get("minecraft:resource", RAW_STRING), get("minecraft:resource_key", RAW_STRING), get("minecraft:resource_selector", RAW_STRING), get("minecraft:template_mirror", VOID), get("minecraft:template_rotation", VOID), get("minecraft:heightmap", VOID), get("minecraft:loot_table", VOID), get("minecraft:loot_predicate", VOID), get("minecraft:loot_modifier", VOID), get("minecraft:dialog", VOID), get("minecraft:uuid", VOID)};
        }

        private static void register(String name, ArgumentSerializer serializer) {
            PROVIDERS.put(name, serializer);
        }

        private static ArgumentSerializer get(String name, ArgumentSerializer serializer) {
            return serializer;
        }

        private static ArgumentType<?> read(ByteBuf buf, int protocolVersion) {
            Object key;
            ArgumentSerializer reader;
            if (protocolVersion >= ProtocolConstants.MINECRAFT_1_19) {
                key = readVarInt(buf);
                if (protocolVersion >= ProtocolConstants.MINECRAFT_1_21_6) {
                    reader = IDS_1_21_6[(Integer) key];
                } else if (protocolVersion >= ProtocolConstants.MINECRAFT_1_21_5) {
                    reader = IDS_1_21_5[(Integer) key];
                } else if (protocolVersion >= ProtocolConstants.MINECRAFT_1_20_5) {
                    reader = IDS_1_20_5[(Integer) key];
                } else if (protocolVersion >= ProtocolConstants.MINECRAFT_1_20_3) {
                    reader = IDS_1_20_3[(Integer) key];
                } else if (protocolVersion >= ProtocolConstants.MINECRAFT_1_19_4) {
                    reader = IDS_1_19_4[(Integer) key];
                } else if (protocolVersion >= ProtocolConstants.MINECRAFT_1_19_3) {
                    reader = IDS_1_19_3[(Integer) key];
                } else {
                    reader = IDS_1_19[(Integer) key];
                }
            } else {
                key = readString(buf);
                reader = PROVIDERS.get((String) key);
            }
            Preconditions.checkArgument(reader != null, "No provider for argument " + key);
            Object val = reader.read(buf);
            return val != null && PROPER_PROVIDERS.containsKey(val.getClass()) ? (ArgumentType<?>) val : new DummyType(key, reader, val);
        }

        private static void write(ArgumentType<?> arg, ByteBuf buf, int protocolVersion) {
            ProperArgumentSerializer proper = PROPER_PROVIDERS.get(arg.getClass());
            if (proper != null) {
                if (protocolVersion >= ProtocolConstants.MINECRAFT_1_19) {
                    writeVarInt(proper.getIntKey(), buf);
                } else {
                    writeString(proper.getKey(), buf);
                }
                proper.write(buf, arg);
            } else {
                Preconditions.checkArgument(arg instanceof DummyType, "Non dummy arg " + arg.getClass());
                DummyType dummy = (DummyType) arg;
                if (dummy.key instanceof Integer) {
                    writeVarInt((Integer) dummy.key, buf);
                } else {
                    writeString((String) dummy.key, buf);
                }
                dummy.serializer.write(buf, dummy.value);
            }
        }


        private static class DummyType<T> implements ArgumentType<T> {
            private final Object key;
            private final ArgumentSerializer<T> serializer;
            private final T value;

            @Override
            public T parse(StringReader reader) throws CommandSyntaxException {
                throw new UnsupportedOperationException("Not supported.");
            }

            @java.lang.SuppressWarnings("all")
            @lombok.Generated
            public DummyType(final Object key, final ArgumentSerializer<T> serializer, final T value) {
                this.key = key;
                this.serializer = serializer;
                this.value = value;
            }

            @java.lang.SuppressWarnings("all")
            @lombok.Generated
            public Object getKey() {
                return this.key;
            }

            @java.lang.SuppressWarnings("all")
            @lombok.Generated
            public ArgumentSerializer<T> getSerializer() {
                return this.serializer;
            }

            @java.lang.SuppressWarnings("all")
            @lombok.Generated
            public T getValue() {
                return this.value;
            }

            @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 Commands.ArgumentRegistry.DummyType)) return false;
                final Commands.ArgumentRegistry.DummyType<?> other = (Commands.ArgumentRegistry.DummyType<?>) o;
                if (!other.canEqual((java.lang.Object) this)) return false;
                final java.lang.Object this$key = this.getKey();
                final java.lang.Object other$key = other.getKey();
                if (this$key == null ? other$key != null : !this$key.equals(other$key)) return false;
                final java.lang.Object this$serializer = this.getSerializer();
                final java.lang.Object other$serializer = other.getSerializer();
                if (this$serializer == null ? other$serializer != null : !this$serializer.equals(other$serializer)) return false;
                final java.lang.Object this$value = this.getValue();
                final java.lang.Object other$value = other.getValue();
                if (this$value == null ? other$value != null : !this$value.equals(other$value)) return false;
                return true;
            }

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

            @java.lang.Override
            @java.lang.SuppressWarnings("all")
            @lombok.Generated
            public int hashCode() {
                final int PRIME = 59;
                int result = 1;
                final java.lang.Object $key = this.getKey();
                result = result * PRIME + ($key == null ? 43 : $key.hashCode());
                final java.lang.Object $serializer = this.getSerializer();
                result = result * PRIME + ($serializer == null ? 43 : $serializer.hashCode());
                final java.lang.Object $value = this.getValue();
                result = result * PRIME + ($value == null ? 43 : $value.hashCode());
                return result;
            }

            @java.lang.Override
            @java.lang.SuppressWarnings("all")
            @lombok.Generated
            public java.lang.String toString() {
                return "Commands.ArgumentRegistry.DummyType(key=" + this.getKey() + ", serializer=" + this.getSerializer() + ", value=" + this.getValue() + ")";
            }
        }


        private static abstract class ArgumentSerializer<T> {
            protected abstract T read(ByteBuf buf);

            protected abstract void write(ByteBuf buf, T t);
        }


        private static abstract class ProperArgumentSerializer<T> extends ArgumentSerializer<T> {
            protected abstract int getIntKey();

            protected abstract String getKey();
        }

        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public ArgumentRegistry() {
        }

        @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 Commands.ArgumentRegistry)) return false;
            final Commands.ArgumentRegistry other = (Commands.ArgumentRegistry) o;
            if (!other.canEqual((java.lang.Object) this)) return false;
            return true;
        }

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

        @java.lang.Override
        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public int hashCode() {
            final int result = 1;
            return result;
        }

        @java.lang.Override
        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public java.lang.String toString() {
            return "Commands.ArgumentRegistry()";
        }
    }


    public static class SuggestionRegistry {
        public static final SuggestionProvider ASK_SERVER = new DummyProvider("minecraft:ask_server");
        private static final Map<String, SuggestionProvider<DummyProvider>> PROVIDERS = new HashMap<>();

        static {
            PROVIDERS.put("minecraft:ask_server", ASK_SERVER);
            registerDummy("minecraft:all_recipes");
            registerDummy("minecraft:available_sounds");
            registerDummy("minecraft:available_biomes");
            registerDummy("minecraft:summonable_entities");
        }

        private static void registerDummy(String name) {
            PROVIDERS.put(name, new DummyProvider(name));
        }

        private static SuggestionProvider<DummyProvider> getProvider(String key) {
            SuggestionProvider<DummyProvider> provider = PROVIDERS.get(key);
            Preconditions.checkArgument(provider != null, "Unknown completion provider " + key);
            return provider;
        }

        private static String getKey(SuggestionProvider<DummyProvider> provider) {
            Preconditions.checkArgument(provider instanceof DummyProvider, "Non dummy provider " + provider);
            return ((DummyProvider) provider).key;
        }


        private static final class DummyProvider implements SuggestionProvider<DummyProvider> {
            private final String key;

            @Override
            public CompletableFuture<Suggestions> getSuggestions(CommandContext<DummyProvider> context, SuggestionsBuilder builder) throws CommandSyntaxException {
                return builder.buildFuture();
            }

            @java.lang.SuppressWarnings("all")
            @lombok.Generated
            public DummyProvider(final String key) {
                this.key = key;
            }

            @java.lang.SuppressWarnings("all")
            @lombok.Generated
            public String getKey() {
                return this.key;
            }

            @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 Commands.SuggestionRegistry.DummyProvider)) return false;
                final Commands.SuggestionRegistry.DummyProvider other = (Commands.SuggestionRegistry.DummyProvider) o;
                final java.lang.Object this$key = this.getKey();
                final java.lang.Object other$key = other.getKey();
                if (this$key == null ? other$key != null : !this$key.equals(other$key)) return false;
                return true;
            }

            @java.lang.Override
            @java.lang.SuppressWarnings("all")
            @lombok.Generated
            public int hashCode() {
                final int PRIME = 59;
                int result = 1;
                final java.lang.Object $key = this.getKey();
                result = result * PRIME + ($key == null ? 43 : $key.hashCode());
                return result;
            }

            @java.lang.Override
            @java.lang.SuppressWarnings("all")
            @lombok.Generated
            public java.lang.String toString() {
                return "Commands.SuggestionRegistry.DummyProvider(key=" + this.getKey() + ")";
            }
        }

        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public SuggestionRegistry() {
        }

        @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 Commands.SuggestionRegistry)) return false;
            final Commands.SuggestionRegistry other = (Commands.SuggestionRegistry) o;
            if (!other.canEqual((java.lang.Object) this)) return false;
            return true;
        }

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

        @java.lang.Override
        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public int hashCode() {
            final int result = 1;
            return result;
        }

        @java.lang.Override
        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public java.lang.String toString() {
            return "Commands.SuggestionRegistry()";
        }
    }

    private static byte binaryFlag(boolean first, boolean second) {
        byte ret = 0;
        if (first) {
            ret = (byte) (ret | 1);
        }
        if (second) {
            ret = (byte) (ret | 2);
        }
        return ret;
    }

    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public RootCommandNode getRoot() {
        return this.root;
    }

    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public void setRoot(final RootCommandNode root) {
        this.root = root;
    }

    @java.lang.Override
    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public java.lang.String toString() {
        return "Commands(root=" + this.getRoot() + ")";
    }

    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public Commands() {
    }

    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public Commands(final RootCommandNode root) {
        this.root = root;
    }

    @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 Commands)) return false;
        final Commands other = (Commands) o;
        if (!other.canEqual((java.lang.Object) this)) return false;
        final java.lang.Object this$root = this.getRoot();
        final java.lang.Object other$root = other.getRoot();
        if (this$root == null ? other$root != null : !this$root.equals(other$root)) return false;
        return true;
    }

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

    @java.lang.Override
    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public int hashCode() {
        final int PRIME = 59;
        int result = 1;
        final java.lang.Object $root = this.getRoot();
        result = result * PRIME + ($root == null ? 43 : $root.hashCode());
        return result;
    }
}
