Minestom/src/main/java/net/minestom/server/network/packet/server/play/DeclareCommandsPacket.java

151 lines
5.6 KiB
Java
Raw Normal View History

2020-04-24 03:25:58 +02:00
package net.minestom.server.network.packet.server.play;
2019-08-23 15:37:38 +02:00
2022-09-05 13:54:58 +02:00
import net.minestom.server.command.builder.arguments.Argument;
import net.minestom.server.network.ConnectionState;
2022-10-29 11:02:22 +02:00
import net.minestom.server.network.NetworkBuffer;
2020-04-24 03:25:58 +02:00
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.registry.StaticProtocolObject;
import net.minestom.server.utils.PacketUtils;
import org.jetbrains.annotations.NotNull;
2019-08-23 15:37:38 +02:00
2021-11-30 17:49:41 +01:00
import java.util.List;
2022-07-05 20:01:51 +02:00
import java.util.function.Function;
2019-08-23 15:37:38 +02:00
2022-10-29 11:02:22 +02:00
import static net.minestom.server.network.NetworkBuffer.*;
2021-11-30 17:49:41 +01:00
public record DeclareCommandsPacket(@NotNull List<Node> nodes,
int rootIndex) implements ServerPacket {
public DeclareCommandsPacket {
nodes = List.copyOf(nodes);
}
2019-08-23 15:37:38 +02:00
2022-10-29 11:02:22 +02:00
public DeclareCommandsPacket(@NotNull NetworkBuffer reader) {
this(reader.readCollection(r -> {
2021-11-30 17:49:41 +01:00
Node node = new Node();
node.read(r);
return node;
2022-10-29 11:02:22 +02:00
}), reader.read(VAR_INT));
2019-08-23 15:37:38 +02:00
}
@Override
2022-10-29 11:02:22 +02:00
public void write(@NotNull NetworkBuffer writer) {
writer.writeCollection(nodes);
writer.write(VAR_INT, rootIndex);
}
2019-08-23 15:37:38 +02:00
@Override
public int getId(@NotNull ConnectionState state) {
return switch (state) {
case PLAY -> ServerPacketIdentifier.DECLARE_COMMANDS;
default -> PacketUtils.invalidPacketState(getClass(), state, ConnectionState.PLAY);
};
2019-08-23 15:37:38 +02:00
}
2022-10-29 11:02:22 +02:00
public static final class Node implements NetworkBuffer.Writer {
2019-08-23 15:37:38 +02:00
public byte flags;
public int[] children = new int[0];
2019-08-23 15:37:38 +02:00
public int redirectedNode; // Only if flags & 0x08
public String name = ""; // Only for literal and argument
2022-09-05 13:54:58 +02:00
public String parser; // Only for argument
public byte[] properties; // Only for argument
public String suggestionsType = ""; // Only if flags 0x10
2019-08-23 15:37:38 +02:00
@Override
2022-10-29 11:02:22 +02:00
public void write(@NotNull NetworkBuffer writer) {
writer.write(BYTE, flags);
2019-08-31 07:54:53 +02:00
if (children != null && children.length > 262114) {
throw new RuntimeException("Children length " + children.length + " is bigger than the maximum allowed " + 262114);
}
2022-10-29 11:02:22 +02:00
writer.write(VAR_INT_ARRAY, children);
2019-08-23 15:37:38 +02:00
if ((flags & 0x08) != 0) {
2022-10-29 11:02:22 +02:00
writer.write(VAR_INT, redirectedNode);
2019-08-23 15:37:38 +02:00
}
if (isLiteral() || isArgument()) {
2022-10-29 11:02:22 +02:00
writer.write(STRING, name);
2019-08-23 15:37:38 +02:00
}
if (isArgument()) {
2022-09-05 13:54:58 +02:00
final int parserId = Argument.CONTAINER.toId(parser);
2022-10-29 11:02:22 +02:00
writer.write(VAR_INT, parserId);
2019-08-23 15:37:38 +02:00
if (properties != null) {
2022-10-29 11:02:22 +02:00
writer.write(RAW_BYTES, properties);
2019-08-23 15:37:38 +02:00
}
}
if ((flags & 0x10) != 0) {
2022-10-29 11:02:22 +02:00
writer.write(STRING, suggestionsType);
2019-08-23 15:37:38 +02:00
}
}
2022-10-29 11:02:22 +02:00
public void read(@NotNull NetworkBuffer reader) {
flags = reader.read(BYTE);
children = reader.read(VAR_INT_ARRAY);
if ((flags & 0x08) != 0) {
2022-10-29 11:02:22 +02:00
redirectedNode = reader.read(VAR_INT);
}
2019-08-23 15:37:38 +02:00
if (isLiteral() || isArgument()) {
2022-10-29 11:02:22 +02:00
name = reader.read(STRING);
}
if (isArgument()) {
final StaticProtocolObject object = Argument.CONTAINER.getId(reader.read(VAR_INT));
2022-09-05 13:54:58 +02:00
parser = object.name();
properties = getProperties(reader, parser);
}
if ((flags & 0x10) != 0) {
2022-10-29 11:02:22 +02:00
suggestionsType = reader.read(STRING);
}
}
2022-10-29 11:02:22 +02:00
private byte[] getProperties(@NotNull NetworkBuffer reader, String parser) {
final Function<Function<NetworkBuffer, ?>, byte[]> minMaxExtractor = (via) -> reader.extractBytes((extractor) -> {
byte flags = extractor.read(BYTE);
2022-07-05 20:01:51 +02:00
if ((flags & 0x01) == 0x01) {
2022-10-29 11:02:22 +02:00
via.apply(extractor); // min
2022-07-05 20:01:51 +02:00
}
if ((flags & 0x02) == 0x02) {
2022-10-29 11:02:22 +02:00
via.apply(extractor); // max
2022-07-05 20:01:51 +02:00
}
});
return switch (parser) {
2022-10-29 11:02:22 +02:00
case "brigadier:double" -> minMaxExtractor.apply(b -> b.read(DOUBLE));
case "brigadier:integer" -> minMaxExtractor.apply(b -> b.read(INT));
case "brigadier:float" -> minMaxExtractor.apply(b -> b.read(FLOAT));
case "brigadier:long" -> minMaxExtractor.apply(b -> b.read(LONG));
case "brigadier:string" -> reader.extractBytes(b -> b.read(VAR_INT));
case "minecraft:entity", "minecraft:score_holder" -> reader.extractBytes(b -> b.read(BYTE));
case "minecraft:range" ->
reader.extractBytes(b -> b.read(BOOLEAN)); // https://wiki.vg/Command_Data#minecraft:range, looks fishy
case "minecraft:resource_or_tag", "minecraft:registry" -> reader.extractBytes(b -> b.read(STRING));
default -> new byte[0]; // unknown
};
2019-08-23 15:37:38 +02:00
}
private boolean isLiteral() {
return (flags & 0b1) != 0;
}
private boolean isArgument() {
return (flags & 0b10) != 0;
}
}
public static byte getFlag(@NotNull NodeType type, boolean executable, boolean redirect, boolean suggestionType) {
2021-11-30 17:49:41 +01:00
byte result = (byte) type.ordinal();
if (executable) result |= 0x04;
if (redirect) result |= 0x08;
if (suggestionType) result |= 0x10;
return result;
}
public enum NodeType {
2021-11-30 17:49:41 +01:00
ROOT, LITERAL, ARGUMENT, NONE;
}
2019-08-23 15:37:38 +02:00
}