/* * Decompiled with CFR 0.152. * * Could not load the following classes: * com.mojang.brigadier.arguments.ArgumentType * com.mojang.brigadier.builder.ArgumentBuilder * com.mojang.brigadier.tree.ArgumentCommandNode * com.mojang.brigadier.tree.CommandNode * com.mojang.brigadier.tree.LiteralCommandNode * com.mojang.brigadier.tree.RootCommandNode * it.unimi.dsi.fastutil.ints.IntCollection * it.unimi.dsi.fastutil.ints.IntOpenHashSet * it.unimi.dsi.fastutil.ints.IntSet * it.unimi.dsi.fastutil.ints.IntSets * it.unimi.dsi.fastutil.objects.Object2IntMap * it.unimi.dsi.fastutil.objects.Object2IntMap$Entry * it.unimi.dsi.fastutil.objects.Object2IntMaps * it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap * it.unimi.dsi.fastutil.objects.ObjectArrayList * org.jspecify.annotations.Nullable */ package net.minecraft.network.protocol.game; import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.builder.ArgumentBuilder; 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 it.unimi.dsi.fastutil.ints.IntCollection; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.ints.IntSets; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntMaps; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import java.lang.runtime.SwitchBootstraps; import java.util.ArrayDeque; import java.util.List; import java.util.Objects; import java.util.function.BiPredicate; import net.minecraft.commands.CommandBuildContext; import net.minecraft.commands.synchronization.ArgumentTypeInfo; import net.minecraft.commands.synchronization.ArgumentTypeInfos; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.PacketType; import net.minecraft.network.protocol.game.ClientGamePacketListener; import net.minecraft.network.protocol.game.GamePacketTypes; import net.minecraft.resources.Identifier; import org.jspecify.annotations.Nullable; public class ClientboundCommandsPacket implements Packet { public static final StreamCodec STREAM_CODEC = Packet.codec(ClientboundCommandsPacket::write, ClientboundCommandsPacket::new); private static final byte MASK_TYPE = 3; private static final byte FLAG_EXECUTABLE = 4; private static final byte FLAG_REDIRECT = 8; private static final byte FLAG_CUSTOM_SUGGESTIONS = 16; private static final byte FLAG_RESTRICTED = 32; private static final byte TYPE_ROOT = 0; private static final byte TYPE_LITERAL = 1; private static final byte TYPE_ARGUMENT = 2; private final int rootIndex; private final List entries; public ClientboundCommandsPacket(RootCommandNode root, NodeInspector inspector) { Object2IntMap> nodeToId = ClientboundCommandsPacket.enumerateNodes(root); this.entries = ClientboundCommandsPacket.createEntries(nodeToId, inspector); this.rootIndex = nodeToId.getInt(root); } private ClientboundCommandsPacket(FriendlyByteBuf input) { this.entries = input.readList(ClientboundCommandsPacket::readNode); this.rootIndex = input.readVarInt(); ClientboundCommandsPacket.validateEntries(this.entries); } private void write(FriendlyByteBuf output) { output.writeCollection(this.entries, (buffer, entry) -> entry.write((FriendlyByteBuf)((Object)buffer))); output.writeVarInt(this.rootIndex); } private static void validateEntries(List entries, BiPredicate validator) { IntOpenHashSet elementsToCheck = new IntOpenHashSet((IntCollection)IntSets.fromTo((int)0, (int)entries.size())); while (!elementsToCheck.isEmpty()) { boolean worked = elementsToCheck.removeIf(arg_0 -> ClientboundCommandsPacket.lambda$validateEntries$1(validator, entries, (IntSet)elementsToCheck, arg_0)); if (worked) continue; throw new IllegalStateException("Server sent an impossible command tree"); } } private static void validateEntries(List entries) { ClientboundCommandsPacket.validateEntries(entries, Entry::canBuild); ClientboundCommandsPacket.validateEntries(entries, Entry::canResolve); } private static Object2IntMap> enumerateNodes(RootCommandNode root) { CommandNode node; Object2IntOpenHashMap nodeToId = new Object2IntOpenHashMap(); ArrayDeque queue = new ArrayDeque(); queue.add(root); while ((node = (CommandNode)queue.poll()) != null) { if (nodeToId.containsKey((Object)node)) continue; int id = nodeToId.size(); nodeToId.put((Object)node, id); queue.addAll(node.getChildren()); if (node.getRedirect() == null) continue; queue.add(node.getRedirect()); } return nodeToId; } private static List createEntries(Object2IntMap> nodeToId, NodeInspector inspector) { ObjectArrayList result = new ObjectArrayList(nodeToId.size()); result.size(nodeToId.size()); for (Object2IntMap.Entry entry : Object2IntMaps.fastIterable(nodeToId)) { result.set(entry.getIntValue(), (Object)ClientboundCommandsPacket.createEntry((CommandNode)entry.getKey(), inspector, nodeToId)); } return result; } private static Entry readNode(FriendlyByteBuf input) { byte flags = input.readByte(); int[] children = input.readVarIntArray(); int redirect = (flags & 8) != 0 ? input.readVarInt() : 0; NodeStub stub = ClientboundCommandsPacket.read(input, flags); return new Entry(stub, flags, redirect, children); } private static @Nullable NodeStub read(FriendlyByteBuf input, byte flags) { int type = flags & 3; if (type == 2) { String name = input.readUtf(); int id = input.readVarInt(); ArgumentTypeInfo argumentType = (ArgumentTypeInfo)BuiltInRegistries.COMMAND_ARGUMENT_TYPE.byId(id); if (argumentType == null) { return null; } Object argument = argumentType.deserializeFromNetwork(input); Identifier suggestionId = (flags & 0x10) != 0 ? input.readIdentifier() : null; return new ArgumentNodeStub(name, (ArgumentTypeInfo.Template)argument, suggestionId); } if (type == 1) { String id = input.readUtf(); return new LiteralNodeStub(id); } return null; } private static Entry createEntry(CommandNode node, NodeInspector inspector, Object2IntMap> ids) { Record nodeStub; int redirect; int flags = 0; if (node.getRedirect() != null) { flags |= 8; redirect = ids.getInt((Object)node.getRedirect()); } else { redirect = 0; } if (inspector.isExecutable(node)) { flags |= 4; } if (inspector.isRestricted(node)) { flags |= 0x20; } CommandNode commandNode = node; Objects.requireNonNull(commandNode); CommandNode commandNode2 = commandNode; int n = 0; switch (SwitchBootstraps.typeSwitch("typeSwitch", new Object[]{RootCommandNode.class, ArgumentCommandNode.class, LiteralCommandNode.class}, commandNode2, n)) { case 0: { RootCommandNode ignored = (RootCommandNode)commandNode2; flags |= 0; nodeStub = null; break; } case 1: { ArgumentCommandNode arg = (ArgumentCommandNode)commandNode2; Identifier suggestionId = inspector.suggestionId(arg); nodeStub = new ArgumentNodeStub(arg.getName(), ArgumentTypeInfos.unpack(arg.getType()), suggestionId); flags |= 2; if (suggestionId != null) { flags |= 0x10; } break; } case 2: { LiteralCommandNode literal = (LiteralCommandNode)commandNode2; nodeStub = new LiteralNodeStub(literal.getLiteral()); flags |= 1; break; } default: { throw new UnsupportedOperationException("Unknown node type " + String.valueOf(node)); } } int[] childrenIds = node.getChildren().stream().mapToInt(arg_0 -> ids.getInt(arg_0)).toArray(); return new Entry((NodeStub)((Object)nodeStub), flags, redirect, childrenIds); } @Override public PacketType type() { return GamePacketTypes.CLIENTBOUND_COMMANDS; } @Override public void handle(ClientGamePacketListener listener) { listener.handleCommands(this); } public RootCommandNode getRoot(CommandBuildContext context, NodeBuilder builder) { return (RootCommandNode)new NodeResolver(context, builder, this.entries).resolve(this.rootIndex); } private static /* synthetic */ boolean lambda$validateEntries$1(BiPredicate validator, List entries, IntSet elementsToCheck, int index) { return validator.test((Entry)entries.get(index), elementsToCheck); } public static interface NodeInspector { public @Nullable Identifier suggestionId(ArgumentCommandNode var1); public boolean isExecutable(CommandNode var1); public boolean isRestricted(CommandNode var1); } private record Entry(@Nullable NodeStub stub, int flags, int redirect, int[] children) { public void write(FriendlyByteBuf output) { output.writeByte(this.flags); output.writeVarIntArray(this.children); if ((this.flags & 8) != 0) { output.writeVarInt(this.redirect); } if (this.stub != null) { this.stub.write(output); } } public boolean canBuild(IntSet unbuiltNodes) { if ((this.flags & 8) != 0) { return !unbuiltNodes.contains(this.redirect); } return true; } public boolean canResolve(IntSet unresolvedNodes) { for (int child : this.children) { if (!unresolvedNodes.contains(child)) continue; return false; } return true; } } private static interface NodeStub { public ArgumentBuilder build(CommandBuildContext var1, NodeBuilder var2); public void write(FriendlyByteBuf var1); } private record ArgumentNodeStub(String id, ArgumentTypeInfo.Template argumentType, @Nullable Identifier suggestionId) implements NodeStub { @Override public ArgumentBuilder build(CommandBuildContext context, NodeBuilder builder) { Object type = this.argumentType.instantiate(context); return builder.createArgument(this.id, (ArgumentType)type, this.suggestionId); } @Override public void write(FriendlyByteBuf output) { output.writeUtf(this.id); ArgumentNodeStub.serializeCap(output, this.argumentType); if (this.suggestionId != null) { output.writeIdentifier(this.suggestionId); } } private static > void serializeCap(FriendlyByteBuf output, ArgumentTypeInfo.Template argumentType) { ArgumentNodeStub.serializeCap(output, argumentType.type(), argumentType); } private static , T extends ArgumentTypeInfo.Template> void serializeCap(FriendlyByteBuf output, ArgumentTypeInfo info, ArgumentTypeInfo.Template argumentType) { output.writeVarInt(BuiltInRegistries.COMMAND_ARGUMENT_TYPE.getId(info)); info.serializeToNetwork(argumentType, output); } } private record LiteralNodeStub(String id) implements NodeStub { @Override public ArgumentBuilder build(CommandBuildContext context, NodeBuilder builder) { return builder.createLiteral(this.id); } @Override public void write(FriendlyByteBuf output) { output.writeUtf(this.id); } } private static class NodeResolver { private final CommandBuildContext context; private final NodeBuilder builder; private final List entries; private final List> nodes; private NodeResolver(CommandBuildContext context, NodeBuilder builder, List entries) { this.context = context; this.builder = builder; this.entries = entries; ObjectArrayList nodes = new ObjectArrayList(); nodes.size(entries.size()); this.nodes = nodes; } public CommandNode resolve(int index) { RootCommandNode result; CommandNode currentNode = this.nodes.get(index); if (currentNode != null) { return currentNode; } Entry entry = this.entries.get(index); if (entry.stub == null) { result = new RootCommandNode(); } else { ArgumentBuilder resultBuilder = entry.stub.build(this.context, this.builder); if ((entry.flags & 8) != 0) { resultBuilder.redirect(this.resolve(entry.redirect)); } boolean isExecutable = (entry.flags & 4) != 0; boolean isRestricted = (entry.flags & 0x20) != 0; result = this.builder.configure(resultBuilder, isExecutable, isRestricted).build(); } this.nodes.set(index, (CommandNode)result); for (int childId : entry.children) { CommandNode child = this.resolve(childId); if (child instanceof RootCommandNode) continue; result.addChild(child); } return result; } } public static interface NodeBuilder { public ArgumentBuilder createLiteral(String var1); public ArgumentBuilder createArgument(String var1, ArgumentType var2, @Nullable Identifier var3); public ArgumentBuilder configure(ArgumentBuilder var1, boolean var2, boolean var3); } }