mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-27 19:47:44 +01:00
Simplify command graph generation (#1200)
This commit is contained in:
parent
d47e761bf7
commit
793561e0cb
@ -52,6 +52,8 @@ public class Main {
|
||||
commandManager.register(new AutoViewCommand());
|
||||
commandManager.register(new SaveCommand());
|
||||
commandManager.register(new GamemodeCommand());
|
||||
commandManager.register(new ExecuteCommand());
|
||||
commandManager.register(new RedirectTestCommand());
|
||||
|
||||
|
||||
commandManager.setUnknownCommandCallback((sender, command) -> sender.sendMessage(Component.text("Unknown command", NamedTextColor.RED)));
|
||||
|
@ -0,0 +1,14 @@
|
||||
package net.minestom.demo.commands;
|
||||
|
||||
import net.minestom.server.command.builder.Command;
|
||||
import net.minestom.server.command.builder.arguments.ArgumentCommand;
|
||||
|
||||
public class ExecuteCommand extends Command {
|
||||
|
||||
public ExecuteCommand() {
|
||||
super("execute");
|
||||
ArgumentCommand run = new ArgumentCommand("run");
|
||||
|
||||
addSyntax(((sender, context) -> {}), run);
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package net.minestom.demo.commands;
|
||||
|
||||
import net.minestom.server.command.builder.Command;
|
||||
import net.minestom.server.command.builder.arguments.ArgumentLiteral;
|
||||
import net.minestom.server.command.builder.arguments.ArgumentLoop;
|
||||
|
||||
public class RedirectTestCommand extends Command {
|
||||
public RedirectTestCommand() {
|
||||
super("redirect");
|
||||
|
||||
final ArgumentLiteral a = new ArgumentLiteral("a");
|
||||
final ArgumentLiteral b = new ArgumentLiteral("b");
|
||||
final ArgumentLiteral c = new ArgumentLiteral("c");
|
||||
final ArgumentLiteral d = new ArgumentLiteral("d");
|
||||
|
||||
addSyntax(((sender, context) -> {}), new ArgumentLoop<>("test", a,b,c,d));
|
||||
}
|
||||
}
|
@ -1,27 +1,20 @@
|
||||
package net.minestom.server.command;
|
||||
|
||||
import it.unimi.dsi.fastutil.Pair;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import net.minestom.server.command.builder.*;
|
||||
import net.minestom.server.command.builder.Command;
|
||||
import net.minestom.server.command.builder.CommandDispatcher;
|
||||
import net.minestom.server.command.builder.CommandResult;
|
||||
import net.minestom.server.command.builder.CommandSyntax;
|
||||
import net.minestom.server.command.builder.arguments.Argument;
|
||||
import net.minestom.server.command.builder.arguments.minecraft.SuggestionType;
|
||||
import net.minestom.server.command.builder.condition.CommandCondition;
|
||||
import net.minestom.server.command.builder.parser.ArgumentQueryResult;
|
||||
import net.minestom.server.command.builder.parser.CommandParser;
|
||||
import net.minestom.server.command.builder.parser.CommandQueryResult;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.EventDispatcher;
|
||||
import net.minestom.server.event.player.PlayerCommandEvent;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import net.minestom.server.utils.ArrayUtils;
|
||||
import net.minestom.server.utils.callback.CommandCallback;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Manager used to register {@link Command commands}.
|
||||
* <p>
|
||||
@ -167,282 +160,43 @@ public final class CommandManager {
|
||||
* @return the {@link DeclareCommandsPacket} for {@code player}
|
||||
*/
|
||||
public @NotNull DeclareCommandsPacket createDeclareCommandsPacket(@NotNull Player player) {
|
||||
return buildPacket(player);
|
||||
}
|
||||
final GraphBuilder factory = new GraphBuilder();
|
||||
|
||||
/**
|
||||
* Builds the {@link DeclareCommandsPacket} for a {@link Player}.
|
||||
*
|
||||
* @param player the player to build the packet for
|
||||
* @return the commands packet for the specific player
|
||||
*/
|
||||
private @NotNull DeclareCommandsPacket buildPacket(@NotNull Player player) {
|
||||
List<DeclareCommandsPacket.Node> nodes = new ArrayList<>();
|
||||
// Contains the children of the main node (all commands name)
|
||||
IntList rootChildren = new IntArrayList();
|
||||
for (Command command : this.dispatcher.getCommands()) {
|
||||
// Check if user can use the command
|
||||
final CommandCondition condition = command.getCondition();
|
||||
if (condition != null && !condition.canUse(player, null)) continue;
|
||||
|
||||
// Root node
|
||||
DeclareCommandsPacket.Node rootNode = new DeclareCommandsPacket.Node();
|
||||
rootNode.flags = 0;
|
||||
nodes.add(rootNode);
|
||||
// Add command to the graph
|
||||
// Create the command's root node
|
||||
final Node cmdNode = factory.createLiteralNode(command.getName(), true,
|
||||
command.getDefaultExecutor() != null, command.getAliases(), null);
|
||||
|
||||
Map<Command, Integer> commandIdentityMap = new IdentityHashMap<>();
|
||||
Map<Argument<?>, Integer> argumentIdentityMap = new IdentityHashMap<>();
|
||||
|
||||
List<Pair<String, NodeMaker.Request>> nodeRequests = new ArrayList<>();
|
||||
|
||||
// Brigadier-like commands
|
||||
for (Command command : dispatcher.getCommands()) {
|
||||
final int commandNodeIndex = serializeCommand(player, command, nodes, rootChildren, commandIdentityMap, argumentIdentityMap, nodeRequests);
|
||||
commandIdentityMap.put(command, commandNodeIndex);
|
||||
}
|
||||
|
||||
// Answer to all node requests
|
||||
for (Pair<String, NodeMaker.Request> pair : nodeRequests) {
|
||||
String input = pair.left();
|
||||
NodeMaker.Request request = pair.right();
|
||||
|
||||
final CommandQueryResult commandQueryResult = CommandParser.findCommand(dispatcher, input);
|
||||
if (commandQueryResult == null) {
|
||||
// Invalid command, return root node
|
||||
request.retrieve(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
final ArgumentQueryResult queryResult = CommandParser.findEligibleArgument(commandQueryResult.command(),
|
||||
commandQueryResult.args(), input, false, true, syntax -> true, argument -> true);
|
||||
if (queryResult == null) {
|
||||
// Invalid argument, return command node (default to root)
|
||||
final int commandNode = commandIdentityMap.getOrDefault(commandQueryResult.command(), 0);
|
||||
request.retrieve(commandNode);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Retrieve argument node
|
||||
final int argumentNode = argumentIdentityMap.getOrDefault(queryResult.argument(), 0);
|
||||
request.retrieve(argumentNode);
|
||||
}
|
||||
// Add root node children
|
||||
rootNode.children = rootChildren.toIntArray();
|
||||
return new DeclareCommandsPacket(nodes, 0);
|
||||
}
|
||||
|
||||
private int serializeCommand(CommandSender sender, Command command,
|
||||
List<DeclareCommandsPacket.Node> nodes,
|
||||
IntList rootChildren,
|
||||
Map<Command, Integer> commandIdentityMap,
|
||||
Map<Argument<?>, Integer> argumentIdentityMap,
|
||||
List<Pair<String, NodeMaker.Request>> nodeRequests) {
|
||||
// Check if player should see this command
|
||||
final CommandCondition commandCondition = command.getCondition();
|
||||
if (commandCondition != null) {
|
||||
// Do not show command if return false
|
||||
if (!commandCondition.canUse(sender, null)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// The main root of this command
|
||||
IntList cmdChildren = new IntArrayList();
|
||||
final Collection<CommandSyntax> syntaxes = command.getSyntaxes();
|
||||
|
||||
// Create command for main name
|
||||
final DeclareCommandsPacket.Node mainNode = createCommandNodes(sender, nodes, cmdChildren,
|
||||
command.getName(), syntaxes, rootChildren, argumentIdentityMap, nodeRequests);
|
||||
final int mainNodeIndex = nodes.indexOf(mainNode);
|
||||
|
||||
// Serialize all the subcommands
|
||||
for (Command subcommand : command.getSubcommands()) {
|
||||
final int subNodeIndex = serializeCommand(sender, subcommand, nodes, cmdChildren, commandIdentityMap, argumentIdentityMap, nodeRequests);
|
||||
if (subNodeIndex != -1) {
|
||||
mainNode.children = ArrayUtils.concatenateIntArrays(mainNode.children, new int[]{subNodeIndex});
|
||||
commandIdentityMap.put(subcommand, subNodeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// Use redirection to hook aliases with the command
|
||||
final String[] aliases = command.getAliases();
|
||||
if (aliases != null) {
|
||||
for (String alias : aliases) {
|
||||
DeclareCommandsPacket.Node aliasNode = new DeclareCommandsPacket.Node();
|
||||
aliasNode.flags = DeclareCommandsPacket.getFlag(DeclareCommandsPacket.NodeType.LITERAL,
|
||||
false, true, false);
|
||||
aliasNode.name = alias;
|
||||
aliasNode.redirectedNode = mainNodeIndex;
|
||||
|
||||
addCommandNameNode(aliasNode, rootChildren, nodes);
|
||||
}
|
||||
}
|
||||
|
||||
return mainNodeIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the command's syntaxes to the nodes list.
|
||||
*
|
||||
* @param sender the potential sender of the command
|
||||
* @param nodes the nodes of the packet
|
||||
* @param cmdChildren the main root of this command
|
||||
* @param name the name of the command (or the alias)
|
||||
* @param syntaxes the syntaxes of the command
|
||||
* @param rootChildren the children of the main node (all commands name)
|
||||
* @return The index of the main node for alias redirection
|
||||
*/
|
||||
private DeclareCommandsPacket.Node createCommandNodes(@NotNull CommandSender sender,
|
||||
@NotNull List<DeclareCommandsPacket.Node> nodes,
|
||||
@NotNull IntList cmdChildren,
|
||||
@NotNull String name,
|
||||
@NotNull Collection<CommandSyntax> syntaxes,
|
||||
@NotNull IntList rootChildren,
|
||||
@NotNull Map<Argument<?>, Integer> argumentIdentityMap,
|
||||
@NotNull List<Pair<String, NodeMaker.Request>> nodeRequests) {
|
||||
|
||||
DeclareCommandsPacket.Node literalNode = createMainNode(name, syntaxes.isEmpty());
|
||||
|
||||
final int literalNodeId = addCommandNameNode(literalNode, rootChildren, nodes);
|
||||
|
||||
// Contains the arguments of the already-parsed syntaxes
|
||||
Map<CommandSyntax, Argument<?>[]> syntaxesArguments = new HashMap<>();
|
||||
// Contains the nodes of an argument
|
||||
Map<IndexedArgument, List<DeclareCommandsPacket.Node[]>> storedArgumentsNodes = new HashMap<>();
|
||||
|
||||
// Sort syntaxes by argument count. Brigadier requires it.
|
||||
syntaxes = syntaxes.stream().sorted(Comparator.comparingInt(o -> -o.getArguments().length)).toList();
|
||||
for (CommandSyntax syntax : syntaxes) {
|
||||
final CommandCondition commandCondition = syntax.getCommandCondition();
|
||||
if (commandCondition != null && !commandCondition.canUse(sender, null)) {
|
||||
// Sender does not have the right to use this syntax, ignore it
|
||||
continue;
|
||||
}
|
||||
|
||||
// Represent the last nodes computed in the last iteration
|
||||
DeclareCommandsPacket.Node[] lastNodes = new DeclareCommandsPacket.Node[]{literalNode};
|
||||
|
||||
// Represent the children of the last node
|
||||
IntList argChildren = cmdChildren;
|
||||
|
||||
NodeMaker nodeMaker = new NodeMaker(lastNodes, literalNodeId);
|
||||
int lastArgumentNodeIndex = nodeMaker.getNodesCount();
|
||||
|
||||
final Argument<?>[] arguments = syntax.getArguments();
|
||||
for (int i = 0; i < arguments.length; i++) {
|
||||
final Argument<?> argument = arguments[i];
|
||||
final boolean isLast = i == arguments.length - 1;
|
||||
|
||||
// Search previously parsed syntaxes to find identical part in order to create a link between those
|
||||
{
|
||||
// Find shared part
|
||||
boolean foundSharedPart = false;
|
||||
for (var entry : syntaxesArguments.entrySet()) {
|
||||
final var parsedArguments = entry.getValue();
|
||||
final int index = i + 1;
|
||||
if (Arrays.mismatch(arguments, 0, index, parsedArguments, 0, index) == -1) {
|
||||
final Argument<?> sharedArgument = parsedArguments[i];
|
||||
final var sharedSyntax = entry.getKey();
|
||||
final var indexed = new IndexedArgument(sharedSyntax, sharedArgument, i);
|
||||
final List<DeclareCommandsPacket.Node[]> storedNodes = storedArgumentsNodes.get(indexed);
|
||||
if (storedNodes == null)
|
||||
continue; // Retrieved argument has already been redirected
|
||||
|
||||
argChildren = new IntArrayList();
|
||||
lastNodes = storedNodes.get(storedNodes.size() > index ? index : i);
|
||||
foundSharedPart = true;
|
||||
}
|
||||
// Add syntax to the command
|
||||
for (CommandSyntax syntax : command.getSyntaxes()) {
|
||||
boolean executable = false;
|
||||
Node[] lastArgNodes = new Node[] {cmdNode}; // First arg links to cmd root
|
||||
@NotNull Argument<?>[] arguments = syntax.getArguments();
|
||||
for (int i = 0; i < arguments.length; i++) {
|
||||
Argument<?> argument = arguments[i];
|
||||
// Determine if command is executable here
|
||||
if (executable && argument.getDefaultValue() == null) {
|
||||
// Optional arg was followed by a non-optional
|
||||
throw new RuntimeException("");//todo exception
|
||||
}
|
||||
if (foundSharedPart) {
|
||||
continue;
|
||||
if (!executable && i < arguments.length-1 && arguments[i+1].getDefaultValue() != null || i+1 == arguments.length) {
|
||||
executable = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Process the nodes for the argument
|
||||
{
|
||||
argument.processNodes(nodeMaker, isLast);
|
||||
|
||||
// Each node array represent a layer
|
||||
final List<DeclareCommandsPacket.Node[]> nodesLayer = nodeMaker.getNodes();
|
||||
storedArgumentsNodes.put(new IndexedArgument(syntax, argument, i), new ArrayList<>(nodesLayer));
|
||||
for (int nodeIndex = lastArgumentNodeIndex; nodeIndex < nodesLayer.size(); nodeIndex++) {
|
||||
final NodeMaker.ConfiguredNodes configuredNodes = nodeMaker.getConfiguredNodes().get(nodeIndex);
|
||||
final NodeMaker.Options options = configuredNodes.getOptions();
|
||||
final DeclareCommandsPacket.Node[] argumentNodes = nodesLayer.get(nodeIndex);
|
||||
|
||||
for (DeclareCommandsPacket.Node argumentNode : argumentNodes) {
|
||||
final int childId = nodes.size();
|
||||
nodeMaker.getNodeIdsMap().put(argumentNode, childId);
|
||||
argChildren.add(childId);
|
||||
|
||||
// Enable ASK_SERVER suggestion if required
|
||||
{
|
||||
if (argument.hasSuggestion()) {
|
||||
argumentNode.flags |= 0x10; // Suggestion flag
|
||||
argumentNode.suggestionsType = SuggestionType.ASK_SERVER.getIdentifier();
|
||||
}
|
||||
}
|
||||
|
||||
// Append to the last node
|
||||
{
|
||||
final int[] children = argChildren.toIntArray();
|
||||
for (DeclareCommandsPacket.Node lastNode : lastNodes) {
|
||||
lastNode.children = lastNode.children == null ?
|
||||
children :
|
||||
ArrayUtils.concatenateIntArrays(lastNode.children, children);
|
||||
}
|
||||
}
|
||||
|
||||
nodes.add(argumentNode);
|
||||
}
|
||||
|
||||
if (options.shouldUpdateLastNode()) {
|
||||
// 'previousNodes' used if the nodes options require to overwrite the parent
|
||||
final DeclareCommandsPacket.Node[] previousNodes = options.getPreviousNodes();
|
||||
|
||||
lastNodes = previousNodes != null ? previousNodes : argumentNodes;
|
||||
argChildren = new IntArrayList();
|
||||
}
|
||||
// Append current node to previous
|
||||
final Node[] argNodes = factory.createArgumentNode(argument, executable);
|
||||
for (Node lastArgNode : lastArgNodes) {
|
||||
lastArgNode.addChild(argNodes);
|
||||
}
|
||||
|
||||
// Used to do not re-compute the previous arguments
|
||||
lastArgumentNodeIndex = nodesLayer.size();
|
||||
lastArgNodes = argNodes;
|
||||
}
|
||||
}
|
||||
|
||||
nodeRequests.addAll(nodeMaker.getNodeRequests());
|
||||
|
||||
syntaxesArguments.put(syntax, arguments);
|
||||
}
|
||||
|
||||
storedArgumentsNodes.forEach((indexedArgument, argNodes) -> {
|
||||
int value = 0;
|
||||
for (DeclareCommandsPacket.Node[] n1 : argNodes) {
|
||||
for (DeclareCommandsPacket.Node n2 : n1) {
|
||||
value = nodes.indexOf(n2);
|
||||
}
|
||||
}
|
||||
// FIXME: add syntax for indexing
|
||||
argumentIdentityMap.put(indexedArgument.argument, value);
|
||||
});
|
||||
|
||||
literalNode.children = cmdChildren.toIntArray();
|
||||
return literalNode;
|
||||
return factory.createCommandPacket();
|
||||
}
|
||||
|
||||
private @NotNull DeclareCommandsPacket.Node createMainNode(@NotNull String name, boolean executable) {
|
||||
DeclareCommandsPacket.Node literalNode = new DeclareCommandsPacket.Node();
|
||||
literalNode.flags = DeclareCommandsPacket.getFlag(DeclareCommandsPacket.NodeType.LITERAL, executable, false, false);
|
||||
literalNode.name = name;
|
||||
|
||||
return literalNode;
|
||||
}
|
||||
|
||||
private int addCommandNameNode(@NotNull DeclareCommandsPacket.Node commandNode,
|
||||
@NotNull IntList rootChildren,
|
||||
@NotNull List<DeclareCommandsPacket.Node> nodes) {
|
||||
final int node = nodes.size();
|
||||
rootChildren.add(node);
|
||||
nodes.add(commandNode);
|
||||
return node;
|
||||
}
|
||||
|
||||
private record IndexedArgument(CommandSyntax syntax, Argument<?> argument, int index) {}
|
||||
|
||||
}
|
||||
|
108
src/main/java/net/minestom/server/command/GraphBuilder.java
Normal file
108
src/main/java/net/minestom/server/command/GraphBuilder.java
Normal file
@ -0,0 +1,108 @@
|
||||
package net.minestom.server.command;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectSet;
|
||||
import net.minestom.server.command.builder.arguments.*;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
final class GraphBuilder {
|
||||
private final AtomicInteger idSource = new AtomicInteger();
|
||||
private final ObjectSet<Node> nodes = new ObjectOpenHashSet<>();
|
||||
private final ObjectSet<Supplier<Boolean>> redirectWaitList = new ObjectOpenHashSet<>();
|
||||
private final Node root = rootNode();
|
||||
|
||||
private Node rootNode() {
|
||||
final Node rootNode = new Node(idSource.getAndIncrement());
|
||||
nodes.add(rootNode);
|
||||
return rootNode;
|
||||
}
|
||||
|
||||
public Node createLiteralNode(String name, boolean addToRoot, boolean executable, @Nullable String[] aliases, @Nullable Integer redirectTo) {
|
||||
if (aliases != null) {
|
||||
final Node node = createLiteralNode(name, addToRoot, executable, null, null);
|
||||
for (String alias : aliases) {
|
||||
createLiteralNode(alias, addToRoot, false, null, node.getId());
|
||||
}
|
||||
return node;
|
||||
} else {
|
||||
final Node literalNode = new Node(idSource.getAndIncrement(), name, redirectTo);
|
||||
literalNode.setExecutable(executable);
|
||||
nodes.add(literalNode);
|
||||
if (addToRoot) root.addChild(literalNode);
|
||||
return literalNode;
|
||||
}
|
||||
}
|
||||
|
||||
public Node[] createArgumentNode(Argument<?> argument, boolean executable) {
|
||||
final Node[] nodes;
|
||||
Integer overrideRedirectTarget = null;
|
||||
if (argument instanceof ArgumentEnum<?> argumentEnum) {
|
||||
nodes = argumentEnum.entries().stream().map(x -> createLiteralNode(x, false, executable, null, null)).toArray(Node[]::new);
|
||||
} else if (argument instanceof ArgumentGroup argumentGroup) {
|
||||
nodes = argumentGroup.group().stream().map(x -> createArgumentNode(x, executable)).flatMap(Stream::of).toArray(Node[]::new);
|
||||
} else if (argument instanceof ArgumentLoop<?> argumentLoop) {
|
||||
overrideRedirectTarget = idSource.get()-1;
|
||||
nodes = argumentLoop.arguments().stream().map(x -> createArgumentNode(x, executable)).flatMap(Stream::of).toArray(Node[]::new);
|
||||
} else {
|
||||
if (argument instanceof ArgumentCommand) {
|
||||
return new Node[]{createLiteralNode(argument.getId(), false, false, null, 0)};
|
||||
}
|
||||
final int id = idSource.getAndIncrement();
|
||||
nodes = new Node[] {argument instanceof ArgumentLiteral ? new Node(id, argument.getId(), null) : new Node(id, argument)};
|
||||
}
|
||||
for (Node node : nodes) {
|
||||
node.setExecutable(executable);
|
||||
this.nodes.add(node);
|
||||
Integer finalOverrideRedirectTarget = overrideRedirectTarget;
|
||||
if (finalOverrideRedirectTarget != null) {
|
||||
redirectWaitList.add(() -> {
|
||||
int target = finalOverrideRedirectTarget;
|
||||
if (target != -1) {
|
||||
node.setRedirectTarget(target);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private int tryResolveId(String[] path) {
|
||||
if (path.length == 0) {
|
||||
return root.getId();
|
||||
} else {
|
||||
Node target = root;
|
||||
for (String next : path) {
|
||||
Node finalTarget = target;
|
||||
final Optional<Node> result = nodes.stream().filter(finalTarget::isParentOf)
|
||||
.filter(x -> x.name().equals(next)).findFirst();
|
||||
if (result.isEmpty()) {
|
||||
return -1;
|
||||
} else {
|
||||
target = result.get();
|
||||
}
|
||||
}
|
||||
return target.getId();
|
||||
}
|
||||
}
|
||||
|
||||
private void finalizeStructure() {
|
||||
redirectWaitList.removeIf(Supplier::get);
|
||||
if (redirectWaitList.size() > 0)
|
||||
throw new RuntimeException("Could not set redirects for all arguments! Did you provide a correct id path which doesn't rely on redirects?");
|
||||
}
|
||||
|
||||
public DeclareCommandsPacket createCommandPacket() {
|
||||
finalizeStructure();
|
||||
return new DeclareCommandsPacket(nodes.stream().sorted(Comparator.comparingInt(Node::getId))
|
||||
.map(Node::getPacketNode).toList(), root.getId());
|
||||
}
|
||||
}
|
88
src/main/java/net/minestom/server/command/Node.java
Normal file
88
src/main/java/net/minestom/server/command/Node.java
Normal file
@ -0,0 +1,88 @@
|
||||
package net.minestom.server.command;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import net.minestom.server.command.builder.arguments.Argument;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
|
||||
final class Node {
|
||||
private final int id;
|
||||
private final IntSet children;
|
||||
private final DeclareCommandsPacket.NodeType type;
|
||||
private String name;
|
||||
private Integer redirectTarget;
|
||||
private Argument<?> argument;
|
||||
private boolean executable;
|
||||
|
||||
Node(int id, DeclareCommandsPacket.NodeType type) {
|
||||
this.id = id;
|
||||
this.children = new IntOpenHashSet();
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
Node(int id) {
|
||||
this(id, DeclareCommandsPacket.NodeType.ROOT);
|
||||
}
|
||||
|
||||
Node(int id, String name, Integer redirectTarget) {
|
||||
this(id, DeclareCommandsPacket.NodeType.LITERAL);
|
||||
setName(name);
|
||||
setRedirectTarget(redirectTarget);
|
||||
}
|
||||
|
||||
Node(int id, Argument<?> argument) {
|
||||
this(id, DeclareCommandsPacket.NodeType.ARGUMENT);
|
||||
setName(argument.getId());
|
||||
this.argument = argument;
|
||||
}
|
||||
|
||||
public void setExecutable(boolean executable) {
|
||||
this.executable = executable;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setRedirectTarget(Integer redirectTarget) {
|
||||
this.redirectTarget = redirectTarget;
|
||||
}
|
||||
|
||||
public void addChild(Node ...nodes) {
|
||||
for (Node node : nodes) {
|
||||
children.add(node.id);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isParentOf(Node node) {
|
||||
return children.contains(node.getId());
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public DeclareCommandsPacket.Node getPacketNode() {
|
||||
final DeclareCommandsPacket.Node node = new DeclareCommandsPacket.Node();
|
||||
node.children = children.toIntArray();
|
||||
node.flags = DeclareCommandsPacket.getFlag(type, executable, redirectTarget != null,
|
||||
type == DeclareCommandsPacket.NodeType.ARGUMENT && argument.hasSuggestion());
|
||||
node.name = name;
|
||||
if (redirectTarget != null) {
|
||||
node.redirectedNode = redirectTarget;
|
||||
}
|
||||
if (type == DeclareCommandsPacket.NodeType.ARGUMENT) {
|
||||
node.properties = argument.nodeProperties();
|
||||
node.parser = argument.parser();
|
||||
if (argument.hasSuggestion()) {
|
||||
//noinspection ConstantConditions
|
||||
node.suggestionsType = argument.suggestionType().getIdentifier();
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
}
|
@ -1,123 +0,0 @@
|
||||
package net.minestom.server.command.builder;
|
||||
|
||||
import it.unimi.dsi.fastutil.Pair;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class NodeMaker {
|
||||
|
||||
private final List<ConfiguredNodes> configuredNodes = new ArrayList<>(2);
|
||||
private final List<DeclareCommandsPacket.Node[]> nodes = new ArrayList<>(2);
|
||||
private final Object2IntMap<DeclareCommandsPacket.Node> nodeIdsMap = new Object2IntOpenHashMap<>();
|
||||
|
||||
private final List<Pair<String, Request>> nodeRequests = new ArrayList<>();
|
||||
|
||||
public NodeMaker(@NotNull DeclareCommandsPacket.Node[] commandNodes, int id) {
|
||||
addNodes(commandNodes);
|
||||
for (DeclareCommandsPacket.Node node : commandNodes) {
|
||||
this.nodeIdsMap.put(node, id);
|
||||
}
|
||||
}
|
||||
|
||||
public ConfiguredNodes getLatestConfiguredNodes() {
|
||||
if (configuredNodes.isEmpty())
|
||||
return null;
|
||||
return configuredNodes.get(configuredNodes.size() - 1);
|
||||
}
|
||||
|
||||
public DeclareCommandsPacket.Node[] getLatestNodes() {
|
||||
ConfiguredNodes configuredNodes = getLatestConfiguredNodes();
|
||||
return configuredNodes != null ? configuredNodes.nodes : null;
|
||||
}
|
||||
|
||||
public int getNodesCount() {
|
||||
return nodes.size();
|
||||
}
|
||||
|
||||
public void addNodes(@NotNull DeclareCommandsPacket.Node[] nodes) {
|
||||
Options options = new Options();
|
||||
this.configuredNodes.add(ConfiguredNodes.of(nodes, options));
|
||||
this.nodes.add(nodes);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<ConfiguredNodes> getConfiguredNodes() {
|
||||
return configuredNodes;
|
||||
}
|
||||
|
||||
public List<DeclareCommandsPacket.Node[]> getNodes() {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Object2IntMap<DeclareCommandsPacket.Node> getNodeIdsMap() {
|
||||
return nodeIdsMap;
|
||||
}
|
||||
|
||||
public void request(String input, Request request) {
|
||||
this.nodeRequests.add(Pair.of(input, request));
|
||||
}
|
||||
|
||||
public List<Pair<String, Request>> getNodeRequests() {
|
||||
return nodeRequests;
|
||||
}
|
||||
|
||||
public static class ConfiguredNodes {
|
||||
private DeclareCommandsPacket.Node[] nodes;
|
||||
private Options options;
|
||||
|
||||
private static ConfiguredNodes of(DeclareCommandsPacket.Node[] nodes, Options options) {
|
||||
ConfiguredNodes configuredNodes = new ConfiguredNodes();
|
||||
configuredNodes.nodes = nodes;
|
||||
configuredNodes.options = options;
|
||||
return configuredNodes;
|
||||
}
|
||||
|
||||
public DeclareCommandsPacket.Node[] getNodes() {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
public Options getOptions() {
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Options {
|
||||
|
||||
private boolean updateLastNode = true;
|
||||
private DeclareCommandsPacket.Node[] previousNodes;
|
||||
|
||||
public static Options init() {
|
||||
return new Options();
|
||||
}
|
||||
|
||||
public boolean shouldUpdateLastNode() {
|
||||
return updateLastNode;
|
||||
}
|
||||
|
||||
public Options updateLastNode(boolean updateLastNode) {
|
||||
this.updateLastNode = updateLastNode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DeclareCommandsPacket.Node[] getPreviousNodes() {
|
||||
return previousNodes;
|
||||
}
|
||||
|
||||
public Options setPreviousNodes(DeclareCommandsPacket.Node[] previousNodes) {
|
||||
this.previousNodes = previousNodes;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Request {
|
||||
void retrieve(int id);
|
||||
}
|
||||
|
||||
}
|
@ -3,10 +3,9 @@ package net.minestom.server.command.builder.arguments;
|
||||
import net.minestom.server.command.builder.ArgumentCallback;
|
||||
import net.minestom.server.command.builder.Command;
|
||||
import net.minestom.server.command.builder.CommandExecutor;
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.arguments.minecraft.SuggestionType;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.command.builder.suggestion.SuggestionCallback;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -35,6 +34,7 @@ public abstract class Argument<T> {
|
||||
private Supplier<T> defaultValue;
|
||||
|
||||
private SuggestionCallback suggestionCallback;
|
||||
protected SuggestionType suggestionType;
|
||||
|
||||
/**
|
||||
* Creates a new argument.
|
||||
@ -91,30 +91,14 @@ public abstract class Argument<T> {
|
||||
*/
|
||||
public abstract @NotNull T parse(@NotNull String input) throws ArgumentSyntaxException;
|
||||
|
||||
/**
|
||||
* Turns the argument into a list of nodes for command dispatching. Make sure to set the Node's parser.
|
||||
*
|
||||
* @param nodeMaker helper object used to create and modify nodes
|
||||
* @param executable true if this will be the last argument, false otherwise
|
||||
*/
|
||||
public abstract void processNodes(@NotNull NodeMaker nodeMaker, boolean executable);
|
||||
public abstract String parser();
|
||||
|
||||
/**
|
||||
* Builds an argument node.
|
||||
*
|
||||
* @param argument the argument
|
||||
* @param executable true if this will be the last argument, false otherwise
|
||||
* @return the created {@link DeclareCommandsPacket.Node}
|
||||
*/
|
||||
@NotNull
|
||||
protected static DeclareCommandsPacket.Node simpleArgumentNode(@NotNull Argument<?> argument,
|
||||
boolean executable, boolean redirect, boolean suggestion) {
|
||||
DeclareCommandsPacket.Node argumentNode = new DeclareCommandsPacket.Node();
|
||||
public byte @Nullable [] nodeProperties() {
|
||||
return null;
|
||||
}
|
||||
|
||||
argumentNode.flags = DeclareCommandsPacket.getFlag(DeclareCommandsPacket.NodeType.ARGUMENT, executable, redirect, suggestion);
|
||||
argumentNode.name = argument.getId();
|
||||
|
||||
return argumentNode;
|
||||
public @Nullable SuggestionType suggestionType() {
|
||||
return suggestionType;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -242,6 +226,7 @@ public abstract class Argument<T> {
|
||||
*/
|
||||
public Argument<T> setSuggestionCallback(@NotNull SuggestionCallback suggestionCallback) {
|
||||
this.suggestionCallback = suggestionCallback;
|
||||
this.suggestionType = SuggestionType.ASK_SERVER;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -251,7 +236,7 @@ public abstract class Argument<T> {
|
||||
* @return If this argument has a suggestion.
|
||||
*/
|
||||
public boolean hasSuggestion() {
|
||||
return suggestionCallback != null;
|
||||
return suggestionType != null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -317,8 +302,8 @@ public abstract class Argument<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
argument.processNodes(nodeMaker, executable);
|
||||
public String parser() {
|
||||
return argument.parser();
|
||||
}
|
||||
}
|
||||
|
||||
@ -346,8 +331,8 @@ public abstract class Argument<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
argument.processNodes(nodeMaker, executable);
|
||||
public String parser() {
|
||||
return argument.parser();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
package net.minestom.server.command.builder.arguments;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@ -30,13 +28,9 @@ public class ArgumentBoolean extends Argument<Boolean> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, false);
|
||||
argumentNode.parser = "brigadier:bool";
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
public String parser() {
|
||||
return "brigadier:bool";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("Boolean<%s>", getId());
|
||||
|
@ -3,9 +3,7 @@ package net.minestom.server.command.builder.arguments;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.command.builder.CommandDispatcher;
|
||||
import net.minestom.server.command.builder.CommandResult;
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import net.minestom.server.utils.StringUtils;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -37,22 +35,8 @@ public class ArgumentCommand extends Argument<CommandResult> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
final DeclareCommandsPacket.Node[] lastNodes = nodeMaker.getLatestNodes();
|
||||
|
||||
if (!shortcut.isEmpty()) {
|
||||
nodeMaker.request(shortcut, (id) -> {
|
||||
for (DeclareCommandsPacket.Node node : lastNodes) {
|
||||
node.flags |= 0x08; // Redirection mask
|
||||
node.redirectedNode = id;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
for (DeclareCommandsPacket.Node node : lastNodes) {
|
||||
node.flags |= 0x08; // Redirection mask
|
||||
node.redirectedNode = 0; // Redirect to root
|
||||
}
|
||||
}
|
||||
public String parser() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isOnlyCorrect() {
|
||||
|
@ -1,10 +1,10 @@
|
||||
package net.minestom.server.command.builder.arguments;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
@ -40,20 +40,12 @@ public class ArgumentEnum<E extends Enum> extends Argument<E> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
// Create a primitive array for mapping
|
||||
DeclareCommandsPacket.Node[] nodes = new DeclareCommandsPacket.Node[this.values.length];
|
||||
public String parser() {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create a node for each restrictions as literal
|
||||
for (int i = 0; i < nodes.length; i++) {
|
||||
DeclareCommandsPacket.Node argumentNode = new DeclareCommandsPacket.Node();
|
||||
|
||||
argumentNode.flags = DeclareCommandsPacket.getFlag(DeclareCommandsPacket.NodeType.LITERAL,
|
||||
executable, false, false);
|
||||
argumentNode.name = this.format.formatter.apply(this.values[i].name());
|
||||
nodes[i] = argumentNode;
|
||||
}
|
||||
nodeMaker.addNodes(nodes);
|
||||
public List<String> entries() {
|
||||
return Arrays.stream(values).map(x -> format.formatter.apply(x.name())).toList();
|
||||
}
|
||||
|
||||
public enum Format {
|
||||
|
@ -1,7 +1,6 @@
|
||||
package net.minestom.server.command.builder.arguments;
|
||||
|
||||
import net.minestom.server.command.builder.CommandContext;
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.command.builder.parser.CommandParser;
|
||||
import net.minestom.server.command.builder.parser.ValidSyntaxHolder;
|
||||
@ -38,10 +37,11 @@ public class ArgumentGroup extends Argument<CommandContext> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
for (int i = 0; i < group.length; i++) {
|
||||
final boolean isLast = i == group.length - 1;
|
||||
group[i].processNodes(nodeMaker, executable && isLast);
|
||||
}
|
||||
public String parser() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<Argument<?>> group() {
|
||||
return List.of(group);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
package net.minestom.server.command.builder.arguments;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ArgumentLiteral extends Argument<String> {
|
||||
@ -23,13 +21,8 @@ public class ArgumentLiteral extends Argument<String> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node literalNode = new DeclareCommandsPacket.Node();
|
||||
literalNode.flags = DeclareCommandsPacket.getFlag(DeclareCommandsPacket.NodeType.LITERAL,
|
||||
executable, false, false);
|
||||
literalNode.name = getId();
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{literalNode});
|
||||
public String parser() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,8 +1,6 @@
|
||||
package net.minestom.server.command.builder.arguments;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import net.minestom.server.utils.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -58,24 +56,12 @@ public class ArgumentLoop<T> extends Argument<List<T>> {
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<Argument<T>> arguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node[] latestNodes = nodeMaker.getLatestNodes();
|
||||
|
||||
for (DeclareCommandsPacket.Node latestNode : latestNodes) {
|
||||
final int id = nodeMaker.getNodeIdsMap().getInt(latestNode);
|
||||
|
||||
for (Argument<T> argument : arguments) {
|
||||
argument.processNodes(nodeMaker, executable);
|
||||
|
||||
NodeMaker.ConfiguredNodes configuredNodes = nodeMaker.getLatestConfiguredNodes();
|
||||
// For the next loop argument to start at the same place
|
||||
configuredNodes.getOptions().setPreviousNodes(latestNodes);
|
||||
for (DeclareCommandsPacket.Node lastArgumentNode : configuredNodes.getNodes()) {
|
||||
lastArgumentNode.flags |= 0x08;
|
||||
lastArgumentNode.redirectedNode = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
public String parser() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
package net.minestom.server.command.builder.arguments;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import net.minestom.server.utils.StringUtils;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Argument which will take a quoted string.
|
||||
@ -31,15 +30,15 @@ public class ArgumentString extends Argument<String> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, false);
|
||||
public String parser() {
|
||||
return "brigadier:string";
|
||||
}
|
||||
|
||||
argumentNode.parser = "brigadier:string";
|
||||
argumentNode.properties = BinaryWriter.makeArray(packetWriter -> {
|
||||
@Override
|
||||
public byte @Nullable [] nodeProperties() {
|
||||
return BinaryWriter.makeArray(packetWriter -> {
|
||||
packetWriter.writeVarInt(1); // Quotable phrase
|
||||
});
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,10 +1,9 @@
|
||||
package net.minestom.server.command.builder.arguments;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import net.minestom.server.utils.StringUtils;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -26,15 +25,15 @@ public class ArgumentStringArray extends Argument<String[]> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, false);
|
||||
public String parser() {
|
||||
return "brigadier:string";
|
||||
}
|
||||
|
||||
argumentNode.parser = "brigadier:string";
|
||||
argumentNode.properties = BinaryWriter.makeArray(packetWriter -> {
|
||||
@Override
|
||||
public byte @Nullable [] nodeProperties() {
|
||||
return BinaryWriter.makeArray(packetWriter -> {
|
||||
packetWriter.writeVarInt(2); // Greedy phrase
|
||||
});
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,7 +1,10 @@
|
||||
package net.minestom.server.command.builder.arguments;
|
||||
|
||||
import net.minestom.server.command.builder.arguments.minecraft.*;
|
||||
import net.minestom.server.command.builder.arguments.minecraft.registry.*;
|
||||
import net.minestom.server.command.builder.arguments.minecraft.registry.ArgumentEnchantment;
|
||||
import net.minestom.server.command.builder.arguments.minecraft.registry.ArgumentEntityType;
|
||||
import net.minestom.server.command.builder.arguments.minecraft.registry.ArgumentParticle;
|
||||
import net.minestom.server.command.builder.arguments.minecraft.registry.ArgumentPotionEffect;
|
||||
import net.minestom.server.command.builder.arguments.number.ArgumentDouble;
|
||||
import net.minestom.server.command.builder.arguments.number.ArgumentFloat;
|
||||
import net.minestom.server.command.builder.arguments.number.ArgumentInteger;
|
||||
|
@ -1,11 +1,9 @@
|
||||
package net.minestom.server.command.builder.arguments;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import net.minestom.server.utils.StringUtils;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import net.minestom.server.utils.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@ -70,32 +68,15 @@ public class ArgumentWord extends Argument<String> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
if (restrictions != null) {
|
||||
public String parser() {
|
||||
return "brigadier:string";
|
||||
}
|
||||
|
||||
// Create a primitive array for mapping
|
||||
DeclareCommandsPacket.Node[] nodes = new DeclareCommandsPacket.Node[this.restrictions.length];
|
||||
|
||||
// Create a node for each restrictions as literal
|
||||
for (int i = 0; i < nodes.length; i++) {
|
||||
DeclareCommandsPacket.Node argumentNode = new DeclareCommandsPacket.Node();
|
||||
|
||||
argumentNode.flags = DeclareCommandsPacket.getFlag(DeclareCommandsPacket.NodeType.LITERAL,
|
||||
executable, false, false);
|
||||
argumentNode.name = this.restrictions[i];
|
||||
nodes[i] = argumentNode;
|
||||
|
||||
}
|
||||
nodeMaker.addNodes(nodes);
|
||||
} else {
|
||||
// Can be any word, add only one argument node
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, false);
|
||||
argumentNode.parser = "brigadier:string";
|
||||
argumentNode.properties = BinaryWriter.makeArray(packetWriter -> {
|
||||
packetWriter.writeVarInt(0); // Single word
|
||||
});
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
}
|
||||
@Override
|
||||
public byte @Nullable [] nodeProperties() {
|
||||
return BinaryWriter.makeArray(packetWriter -> {
|
||||
packetWriter.writeVarInt(0); // Single word
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,10 +1,8 @@
|
||||
package net.minestom.server.command.builder.arguments.minecraft;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.arguments.Argument;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import net.minestom.server.utils.block.BlockUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -25,11 +23,8 @@ public class ArgumentBlockState extends Argument<Block> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, false);
|
||||
argumentNode.parser = "minecraft:block_state";
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
public String parser() {
|
||||
return "minecraft:block_state";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2,10 +2,8 @@ package net.minestom.server.command.builder.arguments.minecraft;
|
||||
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.arguments.Argument;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@ -41,11 +39,8 @@ public class ArgumentColor extends Argument<Style> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, false);
|
||||
argumentNode.parser = "minecraft:color";
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
public String parser() {
|
||||
return "minecraft:color";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3,10 +3,8 @@ package net.minestom.server.command.builder.arguments.minecraft;
|
||||
import com.google.gson.JsonParseException;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.arguments.Argument;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ArgumentComponent extends Argument<Component> {
|
||||
@ -28,12 +26,8 @@ public class ArgumentComponent extends Argument<Component> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, false);
|
||||
|
||||
argumentNode.parser = "minecraft:component";
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
public String parser() {
|
||||
return "minecraft:component";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,16 +1,15 @@
|
||||
package net.minestom.server.command.builder.arguments.minecraft;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.arguments.Argument;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.GameMode;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import net.minestom.server.utils.StringUtils;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import net.minestom.server.utils.entity.EntityFinder;
|
||||
import net.minestom.server.utils.math.IntRange;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@ -72,10 +71,13 @@ public class ArgumentEntity extends Argument<EntityFinder> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, false);
|
||||
argumentNode.parser = "minecraft:entity";
|
||||
argumentNode.properties = BinaryWriter.makeArray(packetWriter -> {
|
||||
public String parser() {
|
||||
return "minecraft:entity";
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte @Nullable [] nodeProperties() {
|
||||
return BinaryWriter.makeArray(packetWriter -> {
|
||||
byte mask = 0;
|
||||
if (this.isOnlySingleEntity()) {
|
||||
mask |= 0x01;
|
||||
@ -85,8 +87,6 @@ public class ArgumentEntity extends Argument<EntityFinder> {
|
||||
}
|
||||
packetWriter.writeByte(mask);
|
||||
});
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -10,7 +10,12 @@ import net.minestom.server.utils.math.FloatRange;
|
||||
public class ArgumentFloatRange extends ArgumentRange<FloatRange, Float> {
|
||||
|
||||
public ArgumentFloatRange(String id) {
|
||||
super(id, "minecraft:float_range", -Float.MAX_VALUE, Float.MAX_VALUE, Float::parseFloat, FloatRange::new);
|
||||
super(id, -Float.MAX_VALUE, Float.MAX_VALUE, Float::parseFloat, FloatRange::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parser() {
|
||||
return "minecraft:float_range";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -10,7 +10,12 @@ import net.minestom.server.utils.math.IntRange;
|
||||
public class ArgumentIntRange extends ArgumentRange<IntRange, Integer> {
|
||||
|
||||
public ArgumentIntRange(String id) {
|
||||
super(id, "minecraft:int_range", Integer.MIN_VALUE, Integer.MAX_VALUE, Integer::parseInt, IntRange::new);
|
||||
super(id, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer::parseInt, IntRange::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parser() {
|
||||
return "minecraft:int_range";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,11 +1,9 @@
|
||||
package net.minestom.server.command.builder.arguments.minecraft;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.arguments.Argument;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTException;
|
||||
@ -37,11 +35,8 @@ public class ArgumentItemStack extends Argument<ItemStack> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, false);
|
||||
argumentNode.parser = "minecraft:item_stack";
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
public String parser() {
|
||||
return "minecraft:item_stack";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,9 +1,7 @@
|
||||
package net.minestom.server.command.builder.arguments.minecraft;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.arguments.Argument;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBT;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
@ -41,11 +39,8 @@ public class ArgumentNbtCompoundTag extends Argument<NBTCompound> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, false);
|
||||
argumentNode.parser = "minecraft:nbt_compound_tag";
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
public String parser() {
|
||||
return "minecraft:nbt_compound_tag";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,9 +1,7 @@
|
||||
package net.minestom.server.command.builder.arguments.minecraft;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.arguments.Argument;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBT;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTException;
|
||||
@ -37,11 +35,8 @@ public class ArgumentNbtTag extends Argument<NBT> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, false);
|
||||
argumentNode.parser = "minecraft:nbt_tag";
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
public String parser() {
|
||||
return "minecraft:nbt_tag";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,9 +1,7 @@
|
||||
package net.minestom.server.command.builder.arguments.minecraft;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.arguments.Argument;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import net.minestom.server.utils.math.Range;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -22,15 +20,13 @@ public abstract class ArgumentRange<T extends Range<N>, N extends Number> extend
|
||||
private final N min;
|
||||
private final N max;
|
||||
private final Function<String, N> parser;
|
||||
private final String parserName;
|
||||
private final BiFunction<N, N, T> rangeConstructor;
|
||||
|
||||
public ArgumentRange(@NotNull String id, String parserName, N min, N max, Function<String, N> parser, BiFunction<N, N, T> rangeConstructor) {
|
||||
public ArgumentRange(@NotNull String id, N min, N max, Function<String, N> parser, BiFunction<N, N, T> rangeConstructor) {
|
||||
super(id);
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
this.parser = parser;
|
||||
this.parserName = parserName;
|
||||
this.rangeConstructor = rangeConstructor;
|
||||
}
|
||||
|
||||
@ -69,13 +65,4 @@ public abstract class ArgumentRange<T extends Range<N>, N extends Number> extend
|
||||
}
|
||||
throw new ArgumentSyntaxException("Invalid range format", input, FORMAT_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, false);
|
||||
argumentNode.parser = parserName;
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
package net.minestom.server.command.builder.arguments.minecraft;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.arguments.Argument;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import net.minestom.server.utils.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -25,11 +23,8 @@ public class ArgumentResourceLocation extends Argument<String> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, false);
|
||||
argumentNode.parser = "minecraft:resource_location";
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
public String parser() {
|
||||
return "minecraft:resource_location";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2,10 +2,8 @@ package net.minestom.server.command.builder.arguments.minecraft;
|
||||
|
||||
import it.unimi.dsi.fastutil.chars.CharArrayList;
|
||||
import it.unimi.dsi.fastutil.chars.CharList;
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.arguments.Argument;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import net.minestom.server.utils.time.TimeUnit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -62,11 +60,8 @@ public class ArgumentTime extends Argument<Duration> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, false);
|
||||
argumentNode.parser = "minecraft:time";
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
public String parser() {
|
||||
return "minecraft:time";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,9 +1,7 @@
|
||||
package net.minestom.server.command.builder.arguments.minecraft;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.arguments.Argument;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.UUID;
|
||||
@ -27,11 +25,8 @@ public class ArgumentUUID extends Argument<UUID> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, false);
|
||||
argumentNode.parser = "minecraft:uuid";
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
public String parser() {
|
||||
return "minecraft:uuid";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,8 +1,6 @@
|
||||
package net.minestom.server.command.builder.arguments.minecraft.registry;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.item.Enchantment;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@ -15,16 +13,13 @@ public class ArgumentEnchantment extends ArgumentRegistry<Enchantment> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enchantment getRegistry(@NotNull String value) {
|
||||
return Enchantment.fromNamespaceId(value);
|
||||
public String parser() {
|
||||
return "minecraft:item_enchantment";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, false);
|
||||
argumentNode.parser = "minecraft:item_enchantment";
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
public Enchantment getRegistry(@NotNull String value) {
|
||||
return Enchantment.fromNamespaceId(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,9 +1,7 @@
|
||||
package net.minestom.server.command.builder.arguments.minecraft.registry;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.arguments.minecraft.SuggestionType;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@ -13,6 +11,12 @@ public class ArgumentEntityType extends ArgumentRegistry<EntityType> {
|
||||
|
||||
public ArgumentEntityType(String id) {
|
||||
super(id);
|
||||
suggestionType = SuggestionType.SUMMONABLE_ENTITIES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parser() {
|
||||
return "minecraft:resource_location";
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -20,15 +24,6 @@ public class ArgumentEntityType extends ArgumentRegistry<EntityType> {
|
||||
return EntityType.fromNamespaceId(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, true);
|
||||
argumentNode.parser = "minecraft:resource_location";
|
||||
argumentNode.suggestionsType = SuggestionType.SUMMONABLE_ENTITIES.getIdentifier();
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("EntityType<%s>", getId());
|
||||
|
@ -1,7 +1,5 @@
|
||||
package net.minestom.server.command.builder.arguments.minecraft.registry;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import net.minestom.server.particle.Particle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -15,16 +13,13 @@ public class ArgumentParticle extends ArgumentRegistry<Particle> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Particle getRegistry(@NotNull String value) {
|
||||
return Particle.fromNamespaceId(value);
|
||||
public String parser() {
|
||||
return "minecraft:particle";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, false);
|
||||
argumentNode.parser = "minecraft:particle";
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
public Particle getRegistry(@NotNull String value) {
|
||||
return Particle.fromNamespaceId(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,7 +1,5 @@
|
||||
package net.minestom.server.command.builder.arguments.minecraft.registry;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import net.minestom.server.potion.PotionEffect;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -15,16 +13,13 @@ public class ArgumentPotionEffect extends ArgumentRegistry<PotionEffect> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PotionEffect getRegistry(@NotNull String value) {
|
||||
return PotionEffect.fromNamespaceId(value);
|
||||
public String parser() {
|
||||
return "minecraft:mob_effect";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, false);
|
||||
argumentNode.parser = "minecraft:mob_effect";
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
public PotionEffect getRegistry(@NotNull String value) {
|
||||
return PotionEffect.fromNamespaceId(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,9 +1,7 @@
|
||||
package net.minestom.server.command.builder.arguments.number;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.arguments.Argument;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -67,19 +65,19 @@ public class ArgumentNumber<T extends Number> extends Argument<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, false);
|
||||
public String parser() {
|
||||
return parserName;
|
||||
}
|
||||
|
||||
argumentNode.parser = parserName;
|
||||
argumentNode.properties = BinaryWriter.makeArray(packetWriter -> {
|
||||
@Override
|
||||
public byte @Nullable [] nodeProperties() {
|
||||
return BinaryWriter.makeArray(packetWriter -> {
|
||||
packetWriter.writeByte(getNumberProperties());
|
||||
if (this.hasMin())
|
||||
propertiesWriter.accept(packetWriter, getMin());
|
||||
if (this.hasMax())
|
||||
propertiesWriter.accept(packetWriter, getMax());
|
||||
});
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
@ -1,7 +1,5 @@
|
||||
package net.minestom.server.command.builder.arguments.relative;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Function;
|
||||
@ -18,11 +16,8 @@ public class ArgumentRelativeBlockPosition extends ArgumentRelativeVec {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, false);
|
||||
argumentNode.parser = "minecraft:block_pos";
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
public String parser() {
|
||||
return "minecraft:block_pos";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,8 +1,6 @@
|
||||
package net.minestom.server.command.builder.arguments.relative;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.coordinate.Vec;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Function;
|
||||
@ -19,11 +17,8 @@ public class ArgumentRelativeVec2 extends ArgumentRelativeVec {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, false);
|
||||
argumentNode.parser = "minecraft:vec2";
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
public String parser() {
|
||||
return "minecraft:vec2";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,8 +1,6 @@
|
||||
package net.minestom.server.command.builder.arguments.relative;
|
||||
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.coordinate.Vec;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Function;
|
||||
@ -19,11 +17,8 @@ public class ArgumentRelativeVec3 extends ArgumentRelativeVec {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) {
|
||||
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(this, executable, false, false);
|
||||
argumentNode.parser = "minecraft:vec3";
|
||||
|
||||
nodeMaker.addNodes(new DeclareCommandsPacket.Node[]{argumentNode});
|
||||
public String parser() {
|
||||
return "minecraft:vec3";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,11 +1,9 @@
|
||||
package net.minestom.server.command;
|
||||
|
||||
import net.minestom.server.command.builder.Command;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
@ -47,40 +45,15 @@ public class CommandManagerTest {
|
||||
assertTrue(check.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeclareCommandsPacket() {
|
||||
var manager = new CommandManager();
|
||||
|
||||
var player = new Player(UUID.randomUUID(), "TestPlayer", null) {
|
||||
@Override
|
||||
protected void playerConnectionInit() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnline() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
manager.register(new Command("name"));
|
||||
|
||||
var packet = manager.createDeclareCommandsPacket(player);
|
||||
|
||||
assertEquals(packet.rootIndex(), 0);
|
||||
assertEquals(packet.nodes().size(), 2);
|
||||
assertNodeEquals(packet.nodes().get(0), (byte) 0, new int[]{1}, 0, "", "", null, "");
|
||||
assertNodeEquals(packet.nodes().get(1), (byte) 5, new int[0], 0, "name", "", null, "");
|
||||
}
|
||||
|
||||
private static void assertNodeEquals(DeclareCommandsPacket.Node node, byte flags, int[] children, int redirectedNode,
|
||||
String name, String parser, byte[] properties, String suggestionsType) {
|
||||
assertEquals(node.flags, flags);
|
||||
assertArrayEquals(node.children, children);
|
||||
assertEquals(node.redirectedNode, redirectedNode);
|
||||
assertEquals(node.name, name);
|
||||
assertEquals(node.parser, parser);
|
||||
assertArrayEquals(node.properties, properties);
|
||||
assertEquals(node.suggestionsType, suggestionsType);
|
||||
assertEquals(flags, node.flags);
|
||||
assertArrayEquals(children, node.children);
|
||||
assertEquals(redirectedNode, node.redirectedNode);
|
||||
assertEquals(name, node.name);
|
||||
assertEquals(parser, node.parser);
|
||||
assertArrayEquals(properties, node.properties);
|
||||
assertEquals(suggestionsType, node.suggestionsType);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user