ClientboundCommandsPacket.java
net.minecraft.network.protocol.game.ClientboundCommandsPacket
信息
- 全限定名:net.minecraft.network.protocol.game.ClientboundCommandsPacket
- 类型:public class
- 包:net.minecraft.network.protocol.game
- 源码路径:src/main/java/net/minecraft/network/protocol/game/ClientboundCommandsPacket.java
- 起始行号:L31
- 实现:Packet
- 职责:
TODO
字段/常量
-
STREAM_CODEC- 类型:
StreamCodec<FriendlyByteBuf,ClientboundCommandsPacket> - 修饰符:
public static final - 源码定位:
L32 - 说明:
TODO
- 类型:
-
MASK_TYPE- 类型:
byte - 修饰符:
private static final - 源码定位:
L35 - 说明:
TODO
- 类型:
-
FLAG_EXECUTABLE- 类型:
byte - 修饰符:
private static final - 源码定位:
L36 - 说明:
TODO
- 类型:
-
FLAG_REDIRECT- 类型:
byte - 修饰符:
private static final - 源码定位:
L37 - 说明:
TODO
- 类型:
-
FLAG_CUSTOM_SUGGESTIONS- 类型:
byte - 修饰符:
private static final - 源码定位:
L38 - 说明:
TODO
- 类型:
-
FLAG_RESTRICTED- 类型:
byte - 修饰符:
private static final - 源码定位:
L39 - 说明:
TODO
- 类型:
-
TYPE_ROOT- 类型:
byte - 修饰符:
private static final - 源码定位:
L40 - 说明:
TODO
- 类型:
-
TYPE_LITERAL- 类型:
byte - 修饰符:
private static final - 源码定位:
L41 - 说明:
TODO
- 类型:
-
TYPE_ARGUMENT- 类型:
byte - 修饰符:
private static final - 源码定位:
L42 - 说明:
TODO
- 类型:
-
rootIndex- 类型:
int - 修饰符:
private final - 源码定位:
L43 - 说明:
TODO
- 类型:
-
entries- 类型:
List<ClientboundCommandsPacket.Entry> - 修饰符:
private final - 源码定位:
L44 - 说明:
TODO
- 类型:
内部类/嵌套类型
-
net.minecraft.network.protocol.game.ClientboundCommandsPacket.ArgumentNodeStub- 类型:
record - 修饰符:
private - 源码定位:
L200 - 说明:
TODO
- 类型:
-
net.minecraft.network.protocol.game.ClientboundCommandsPacket.Entry- 类型:
record - 修饰符:
private - 源码定位:
L229 - 说明:
TODO
- 类型:
-
net.minecraft.network.protocol.game.ClientboundCommandsPacket.LiteralNodeStub- 类型:
record - 修饰符:
private - 源码定位:
L257 - 说明:
TODO
- 类型:
-
net.minecraft.network.protocol.game.ClientboundCommandsPacket.NodeBuilder- 类型:
interface - 修饰符:
public - 源码定位:
L269 - 说明:
TODO
- 类型:
-
net.minecraft.network.protocol.game.ClientboundCommandsPacket.NodeInspector- 类型:
interface - 修饰符:
public - 源码定位:
L277 - 说明:
TODO
- 类型:
-
net.minecraft.network.protocol.game.ClientboundCommandsPacket.NodeResolver- 类型:
class - 修饰符:
private static - 源码定位:
L285 - 说明:
TODO
- 类型:
-
net.minecraft.network.protocol.game.ClientboundCommandsPacket.NodeStub- 类型:
interface - 修饰符:
private - 源码定位:
L334 - 说明:
TODO
- 类型:
构造器
public ClientboundCommandsPacket(RootCommandNode<S> root, ClientboundCommandsPacket.NodeInspector<S> inspector) @ L46
- 构造器名:ClientboundCommandsPacket
- 源码定位:L46
- 修饰符:public
参数:
- root: RootCommandNode
- inspector: ClientboundCommandsPacket.NodeInspector
说明:
TODO
private ClientboundCommandsPacket(FriendlyByteBuf input) @ L52
- 构造器名:ClientboundCommandsPacket
- 源码定位:L52
- 修饰符:private
参数:
- input: FriendlyByteBuf
说明:
TODO
方法
下面的方法块按源码顺序生成。
private void write(FriendlyByteBuf output) @ L58
- 方法名:write
- 源码定位:L58
- 返回类型:void
- 修饰符:private
参数:
- output: FriendlyByteBuf
说明:
TODO
private static void validateEntries(List<ClientboundCommandsPacket.Entry> entries, BiPredicate<ClientboundCommandsPacket.Entry,IntSet> validator) @ L63
- 方法名:validateEntries
- 源码定位:L63
- 返回类型:void
- 修饰符:private static
参数:
- entries: List<ClientboundCommandsPacket.Entry>
- validator: BiPredicate<ClientboundCommandsPacket.Entry,IntSet>
说明:
TODO
private static void validateEntries(List<ClientboundCommandsPacket.Entry> entries) @ L74
- 方法名:validateEntries
- 源码定位:L74
- 返回类型:void
- 修饰符:private static
参数:
- entries: List<ClientboundCommandsPacket.Entry>
说明:
TODO
private static <S> Object2IntMap<CommandNode<S>> enumerateNodes(RootCommandNode<S> root) @ L79
- 方法名:enumerateNodes
- 源码定位:L79
- 返回类型:
Object2IntMap<CommandNode> - 修饰符:private static
参数:
- root: RootCommandNode
说明:
TODO
private static <S> List<ClientboundCommandsPacket.Entry> createEntries(Object2IntMap<CommandNode<S>> nodeToId, ClientboundCommandsPacket.NodeInspector<S> inspector) @ L99
- 方法名:createEntries
- 源码定位:L99
- 返回类型:
List<ClientboundCommandsPacket.Entry> - 修饰符:private static
参数:
- nodeToId: Object2IntMap<CommandNode
> - inspector: ClientboundCommandsPacket.NodeInspector
说明:
TODO
private static ClientboundCommandsPacket.Entry readNode(FriendlyByteBuf input) @ L112
- 方法名:readNode
- 源码定位:L112
- 返回类型:ClientboundCommandsPacket.Entry
- 修饰符:private static
参数:
- input: FriendlyByteBuf
说明:
TODO
private static ClientboundCommandsPacket.NodeStub read(FriendlyByteBuf input, byte flags) @ L120
- 方法名:read
- 源码定位:L120
- 返回类型:ClientboundCommandsPacket.NodeStub
- 修饰符:private static
参数:
- input: FriendlyByteBuf
- flags: byte
说明:
TODO
private static <S> ClientboundCommandsPacket.Entry createEntry(CommandNode<S> node, ClientboundCommandsPacket.NodeInspector<S> inspector, Object2IntMap<CommandNode<S>> ids) @ L141
- 方法名:createEntry
- 源码定位:L141
- 返回类型:
ClientboundCommandsPacket.Entry - 修饰符:private static
参数:
- node: CommandNode
- inspector: ClientboundCommandsPacket.NodeInspector
- ids: Object2IntMap<CommandNode
>
说明:
TODO
public PacketType<ClientboundCommandsPacket> type() @ L187
- 方法名:type
- 源码定位:L187
- 返回类型:PacketType
- 修饰符:public
参数:
- 无
说明:
TODO
public void handle(ClientGamePacketListener listener) @ L192
- 方法名:handle
- 源码定位:L192
- 返回类型:void
- 修饰符:public
参数:
- listener: ClientGamePacketListener
说明:
TODO
public <S> RootCommandNode<S> getRoot(CommandBuildContext context, ClientboundCommandsPacket.NodeBuilder<S> builder) @ L196
- 方法名:getRoot
- 源码定位:L196
- 返回类型:
RootCommandNode - 修饰符:public
参数:
- context: CommandBuildContext
- builder: ClientboundCommandsPacket.NodeBuilder
说明:
TODO
代码
public class ClientboundCommandsPacket implements Packet<ClientGamePacketListener> {
public static final StreamCodec<FriendlyByteBuf, ClientboundCommandsPacket> 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<ClientboundCommandsPacket.Entry> entries;
public <S> ClientboundCommandsPacket(RootCommandNode<S> root, ClientboundCommandsPacket.NodeInspector<S> inspector) {
Object2IntMap<CommandNode<S>> nodeToId = enumerateNodes(root);
this.entries = createEntries(nodeToId, inspector);
this.rootIndex = nodeToId.getInt(root);
}
private ClientboundCommandsPacket(FriendlyByteBuf input) {
this.entries = input.readList(ClientboundCommandsPacket::readNode);
this.rootIndex = input.readVarInt();
validateEntries(this.entries);
}
private void write(FriendlyByteBuf output) {
output.writeCollection(this.entries, (buffer, entry) -> entry.write(buffer));
output.writeVarInt(this.rootIndex);
}
private static void validateEntries(List<ClientboundCommandsPacket.Entry> entries, BiPredicate<ClientboundCommandsPacket.Entry, IntSet> validator) {
IntSet elementsToCheck = new IntOpenHashSet(IntSets.fromTo(0, entries.size()));
while (!elementsToCheck.isEmpty()) {
boolean worked = elementsToCheck.removeIf(index -> validator.test(entries.get(index), elementsToCheck));
if (!worked) {
throw new IllegalStateException("Server sent an impossible command tree");
}
}
}
private static void validateEntries(List<ClientboundCommandsPacket.Entry> entries) {
validateEntries(entries, ClientboundCommandsPacket.Entry::canBuild);
validateEntries(entries, ClientboundCommandsPacket.Entry::canResolve);
}
private static <S> Object2IntMap<CommandNode<S>> enumerateNodes(RootCommandNode<S> root) {
Object2IntMap<CommandNode<S>> nodeToId = new Object2IntOpenHashMap<>();
Queue<CommandNode<S>> queue = new ArrayDeque<>();
queue.add(root);
CommandNode<S> node;
while ((node = queue.poll()) != null) {
if (!nodeToId.containsKey(node)) {
int id = nodeToId.size();
nodeToId.put(node, id);
queue.addAll(node.getChildren());
if (node.getRedirect() != null) {
queue.add(node.getRedirect());
}
}
}
return nodeToId;
}
private static <S> List<ClientboundCommandsPacket.Entry> createEntries(
Object2IntMap<CommandNode<S>> nodeToId, ClientboundCommandsPacket.NodeInspector<S> inspector
) {
ObjectArrayList<ClientboundCommandsPacket.Entry> result = new ObjectArrayList<>(nodeToId.size());
result.size(nodeToId.size());
for (Object2IntMap.Entry<CommandNode<S>> entry : Object2IntMaps.fastIterable(nodeToId)) {
result.set(entry.getIntValue(), createEntry(entry.getKey(), inspector, nodeToId));
}
return result;
}
private static ClientboundCommandsPacket.Entry readNode(FriendlyByteBuf input) {
byte flags = input.readByte();
int[] children = input.readVarIntArray();
int redirect = (flags & 8) != 0 ? input.readVarInt() : 0;
ClientboundCommandsPacket.NodeStub stub = read(input, flags);
return new ClientboundCommandsPacket.Entry(stub, flags, redirect, children);
}
private static ClientboundCommandsPacket.@Nullable NodeStub read(FriendlyByteBuf input, byte flags) {
int type = flags & 3;
if (type == 2) {
String name = input.readUtf();
int id = input.readVarInt();
ArgumentTypeInfo<?, ?> argumentType = BuiltInRegistries.COMMAND_ARGUMENT_TYPE.byId(id);
if (argumentType == null) {
return null;
} else {
ArgumentTypeInfo.Template<?> argument = argumentType.deserializeFromNetwork(input);
Identifier suggestionId = (flags & 16) != 0 ? input.readIdentifier() : null;
return new ClientboundCommandsPacket.ArgumentNodeStub(name, argument, suggestionId);
}
} else if (type == 1) {
String id = input.readUtf();
return new ClientboundCommandsPacket.LiteralNodeStub(id);
} else {
return null;
}
}
private static <S> ClientboundCommandsPacket.Entry createEntry(
CommandNode<S> node, ClientboundCommandsPacket.NodeInspector<S> inspector, Object2IntMap<CommandNode<S>> ids
) {
int flags = 0;
int redirect;
if (node.getRedirect() != null) {
flags |= 8;
redirect = ids.getInt(node.getRedirect());
} else {
redirect = 0;
}
if (inspector.isExecutable(node)) {
flags |= 4;
}
if (inspector.isRestricted(node)) {
flags |= 32;
}
ClientboundCommandsPacket.NodeStub nodeStub;
switch (node) {
case RootCommandNode<S> ignored:
flags |= 0;
nodeStub = null;
break;
case ArgumentCommandNode<S, ?> arg:
Identifier suggestionId = inspector.suggestionId(arg);
nodeStub = new ClientboundCommandsPacket.ArgumentNodeStub(arg.getName(), ArgumentTypeInfos.unpack(arg.getType()), suggestionId);
flags |= 2;
if (suggestionId != null) {
flags |= 16;
}
break;
case LiteralCommandNode<S> literal:
nodeStub = new ClientboundCommandsPacket.LiteralNodeStub(literal.getLiteral());
flags |= 1;
break;
default:
throw new UnsupportedOperationException("Unknown node type " + node);
}
int[] childrenIds = node.getChildren().stream().mapToInt(ids::getInt).toArray();
return new ClientboundCommandsPacket.Entry(nodeStub, flags, redirect, childrenIds);
}
@Override
public PacketType<ClientboundCommandsPacket> type() {
return GamePacketTypes.CLIENTBOUND_COMMANDS;
}
public void handle(ClientGamePacketListener listener) {
listener.handleCommands(this);
}
public <S> RootCommandNode<S> getRoot(CommandBuildContext context, ClientboundCommandsPacket.NodeBuilder<S> builder) {
return (RootCommandNode<S>)new ClientboundCommandsPacket.NodeResolver<>(context, builder, this.entries).resolve(this.rootIndex);
}
private record ArgumentNodeStub(String id, ArgumentTypeInfo.Template<?> argumentType, @Nullable Identifier suggestionId)
implements ClientboundCommandsPacket.NodeStub {
@Override
public <S> ArgumentBuilder<S, ?> build(CommandBuildContext context, ClientboundCommandsPacket.NodeBuilder<S> builder) {
ArgumentType<?> type = this.argumentType.instantiate(context);
return builder.createArgument(this.id, type, this.suggestionId);
}
@Override
public void write(FriendlyByteBuf output) {
output.writeUtf(this.id);
serializeCap(output, this.argumentType);
if (this.suggestionId != null) {
output.writeIdentifier(this.suggestionId);
}
}
private static <A extends ArgumentType<?>> void serializeCap(FriendlyByteBuf output, ArgumentTypeInfo.Template<A> argumentType) {
serializeCap(output, argumentType.type(), argumentType);
}
private static <A extends ArgumentType<?>, T extends ArgumentTypeInfo.Template<A>> void serializeCap(
FriendlyByteBuf output, ArgumentTypeInfo<A, T> info, ArgumentTypeInfo.Template<A> argumentType
) {
output.writeVarInt(BuiltInRegistries.COMMAND_ARGUMENT_TYPE.getId(info));
info.serializeToNetwork((T)argumentType, output);
}
}
private record Entry(ClientboundCommandsPacket.@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) {
return (this.flags & 8) != 0 ? !unbuiltNodes.contains(this.redirect) : true;
}
public boolean canResolve(IntSet unresolvedNodes) {
for (int child : this.children) {
if (unresolvedNodes.contains(child)) {
return false;
}
}
return true;
}
}
private record LiteralNodeStub(String id) implements ClientboundCommandsPacket.NodeStub {
@Override
public <S> ArgumentBuilder<S, ?> build(CommandBuildContext context, ClientboundCommandsPacket.NodeBuilder<S> builder) {
return builder.createLiteral(this.id);
}
@Override
public void write(FriendlyByteBuf output) {
output.writeUtf(this.id);
}
}
public interface NodeBuilder<S> {
ArgumentBuilder<S, ?> createLiteral(String id);
ArgumentBuilder<S, ?> createArgument(String id, ArgumentType<?> argumentType, @Nullable Identifier suggestionId);
ArgumentBuilder<S, ?> configure(ArgumentBuilder<S, ?> input, boolean executable, boolean restricted);
}
public interface NodeInspector<S> {
@Nullable Identifier suggestionId(ArgumentCommandNode<S, ?> node);
boolean isExecutable(CommandNode<S> node);
boolean isRestricted(CommandNode<S> node);
}
private static class NodeResolver<S> {
private final CommandBuildContext context;
private final ClientboundCommandsPacket.NodeBuilder<S> builder;
private final List<ClientboundCommandsPacket.Entry> entries;
private final List<CommandNode<S>> nodes;
private NodeResolver(CommandBuildContext context, ClientboundCommandsPacket.NodeBuilder<S> builder, List<ClientboundCommandsPacket.Entry> entries) {
this.context = context;
this.builder = builder;
this.entries = entries;
ObjectArrayList<CommandNode<S>> nodes = new ObjectArrayList<>();
nodes.size(entries.size());
this.nodes = nodes;
}
public CommandNode<S> resolve(int index) {
CommandNode<S> currentNode = this.nodes.get(index);
if (currentNode != null) {
return currentNode;
} else {
ClientboundCommandsPacket.Entry entry = this.entries.get(index);
CommandNode<S> result;
if (entry.stub == null) {
result = new RootCommandNode<>();
} else {
ArgumentBuilder<S, ?> 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 & 32) != 0;
result = this.builder.configure(resultBuilder, isExecutable, isRestricted).build();
}
this.nodes.set(index, result);
for (int childId : entry.children) {
CommandNode<S> child = this.resolve(childId);
if (!(child instanceof RootCommandNode)) {
result.addChild(child);
}
}
return result;
}
}
}
private interface NodeStub {
<S> ArgumentBuilder<S, ?> build(CommandBuildContext context, ClientboundCommandsPacket.NodeBuilder<S> builder);
void write(FriendlyByteBuf output);
}
}引用的其他类
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
ArgumentTypeInfos.unpack()
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
字段
- 引用位置:
-
- 引用位置:
实现/方法调用 - 关联成员:
Packet.codec()
- 引用位置:
-
- 引用位置:
返回值
- 引用位置:
-
- 引用位置:
参数
- 引用位置: