diff --git a/src/main/java/net/minestom/server/command/CommandManager.java b/src/main/java/net/minestom/server/command/CommandManager.java index cbc9c1ff0..e05759cf4 100644 --- a/src/main/java/net/minestom/server/command/CommandManager.java +++ b/src/main/java/net/minestom/server/command/CommandManager.java @@ -418,7 +418,7 @@ public final class CommandManager { // Contains the arguments of the already-parsed syntaxes List[]> syntaxesArguments = new ArrayList<>(); // Contains the nodes of an argument - Map, DeclareCommandsPacket.Node[]> storedArgumentsNodes = new HashMap<>(); + Map, List> storedArgumentsNodes = new HashMap<>(); for (CommandSyntax syntax : syntaxes) { final CommandCondition commandCondition = syntax.getCommandCondition(); @@ -430,77 +430,70 @@ public final class CommandManager { NodeMaker nodeMaker = new NodeMaker(); // Represent the last nodes computed in the last iteration - //DeclareCommandsPacket.Node[] lastNodes = null; + DeclareCommandsPacket.Node[] lastNodes = new DeclareCommandsPacket.Node[]{literalNode}; // Represent the children of the last node - IntList argChildren = null; + IntList argChildren = cmdChildren; + + int lastArgumentNodeIndex = 0; final Argument[] arguments = syntax.getArguments(); for (int i = 0; i < arguments.length; i++) { final Argument argument = arguments[i]; - final boolean isFirst = i == 0; final boolean isLast = i == arguments.length - 1; - // Find shared part - boolean foundSharedPart = false; - for (Argument[] parsedArguments : syntaxesArguments) { - if (ArrayUtils.sameStart(arguments, parsedArguments, i + 1)) { - final Argument sharedArgument = parsedArguments[i]; + // Search previously parsed syntaxes to find identical part in order to create a node between those + { + // Find shared part + boolean foundSharedPart = false; + for (Argument[] parsedArguments : syntaxesArguments) { + if (ArrayUtils.sameStart(arguments, parsedArguments, i + 1)) { + final Argument sharedArgument = parsedArguments[i]; + final List storedNodes = storedArgumentsNodes.get(sharedArgument); - argChildren = new IntArrayList(); - nodeMaker.setLastNodes(storedArgumentsNodes.get(sharedArgument)); - foundSharedPart = true; - } - } - if (foundSharedPart) { - continue; - } - - - argument.processNodes(nodeMaker, isLast); - final DeclareCommandsPacket.Node[] argumentNodes = nodeMaker.getCurrentNodes(); - storedArgumentsNodes.put(argument, argumentNodes); - for (DeclareCommandsPacket.Node node : argumentNodes) { - final int childId = nodes.size(); - - if (isFirst) { - // Add to main command child - cmdChildren.add(childId); - } else { - // Add to previous argument children - argChildren.add(childId); - } - - final DeclareCommandsPacket.Node[] lastNodes = nodeMaker.getLastNodes(); - if (lastNodes != null) { - final int[] children = ArrayUtils.toArray(argChildren); - - for (DeclareCommandsPacket.Node lastNode : lastNodes) { - lastNode.children = lastNode.children == null ? - children : - ArrayUtils.concatenateIntArrays(lastNode.children, children); + argChildren = new IntArrayList(); + lastNodes = storedNodes.get(storedNodes.size() - Math.max(arguments.length, parsedArguments.length)); + foundSharedPart = true; } } - - // Always add to the main node list - nodes.add(node); + if (foundSharedPart) { + continue; + } } - //System.out.println("debug: " + argument.getId() + " : " + isFirst + " : " + isLast); - //System.out.println("debug2: " + i); - //System.out.println("size: " + (argChildren != null ? argChildren.size() : "NULL")); + // Process the nodes for the argument + { + argument.processNodes(nodeMaker, isLast); - if (isLast) { - // Last argument doesn't have children - final int[] children = new int[0]; + // Each node array represent a layer + final List nodesLayer = nodeMaker.getNodes(); + storedArgumentsNodes.put(argument, nodesLayer); + for (int nodeIndex = lastArgumentNodeIndex; nodeIndex < nodesLayer.size(); nodeIndex++) { + final DeclareCommandsPacket.Node[] argumentNodes = nodesLayer.get(nodeIndex); - for (DeclareCommandsPacket.Node node : argumentNodes) { - node.children = children; + for (DeclareCommandsPacket.Node argumentNode : argumentNodes) { + final int childId = nodes.size(); + argChildren.add(childId); + + // Append to the last node + { + final int[] children = ArrayUtils.toArray(argChildren); + for (DeclareCommandsPacket.Node lastNode : lastNodes) { + lastNode.children = lastNode.children == null ? + children : + ArrayUtils.concatenateIntArrays(lastNode.children, children); + } + } + + nodes.add(argumentNode); + } + + lastNodes = argumentNodes; + argChildren = new IntArrayList(); } - } else { - // Create children list which will be filled during next iteration - argChildren = new IntArrayList(); - nodeMaker.setLastNodes(argumentNodes); + + // Used to do not re-compute the previous arguments + lastArgumentNodeIndex = nodesLayer.size(); } } diff --git a/src/main/java/net/minestom/server/command/builder/NodeMaker.java b/src/main/java/net/minestom/server/command/builder/NodeMaker.java index db3807741..cbe1afd42 100644 --- a/src/main/java/net/minestom/server/command/builder/NodeMaker.java +++ b/src/main/java/net/minestom/server/command/builder/NodeMaker.java @@ -2,32 +2,26 @@ package net.minestom.server.command.builder; import net.minestom.server.network.packet.server.play.DeclareCommandsPacket; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; public class NodeMaker { - private DeclareCommandsPacket.Node[] lastNodes; - private DeclareCommandsPacket.Node[] currentNodes; + private final List nodes = new ArrayList<>(2); - public DeclareCommandsPacket.Node[] getCurrentNodes() { - return currentNodes; + public DeclareCommandsPacket.Node[] getLatestNodes() { + if (nodes.isEmpty()) + return null; + return nodes.get(nodes.size() - 1); } public void addNodes(@NotNull DeclareCommandsPacket.Node[] nodes) { - this.currentNodes = nodes; + this.nodes.add(nodes); } - /** - * Represents the nodes computed in the last iteration. - * - * @return the previous nodes, null if none - */ - @Nullable - public DeclareCommandsPacket.Node[] getLastNodes() { - return lastNodes; - } - - public void setLastNodes(DeclareCommandsPacket.Node[] lastNodes) { - this.lastNodes = lastNodes; + @NotNull + public List getNodes() { + return nodes; } } diff --git a/src/main/java/net/minestom/server/command/builder/arguments/Argument.java b/src/main/java/net/minestom/server/command/builder/arguments/Argument.java index 489e84c39..48e15bf88 100644 --- a/src/main/java/net/minestom/server/command/builder/arguments/Argument.java +++ b/src/main/java/net/minestom/server/command/builder/arguments/Argument.java @@ -23,7 +23,6 @@ public abstract class Argument { private final String id; private final boolean allowSpace; private final boolean useRemaining; - private Argument redirect; private ArgumentCallback callback; @@ -195,4 +194,18 @@ public abstract class Argument { return callback != null; } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Argument argument = (Argument) o; + + return id.equals(argument.id); + } + + @Override + public int hashCode() { + return id.hashCode(); + } } diff --git a/src/main/java/net/minestom/server/command/builder/arguments/ArgumentCommand.java b/src/main/java/net/minestom/server/command/builder/arguments/ArgumentCommand.java index 905602847..4bfa95e3c 100644 --- a/src/main/java/net/minestom/server/command/builder/arguments/ArgumentCommand.java +++ b/src/main/java/net/minestom/server/command/builder/arguments/ArgumentCommand.java @@ -30,7 +30,7 @@ public class ArgumentCommand extends Argument { @Override public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) { - final DeclareCommandsPacket.Node[] lastNodes = nodeMaker.getLastNodes(); + final DeclareCommandsPacket.Node[] lastNodes = nodeMaker.getLatestNodes(); // FIXME check if lastNodes is null for (DeclareCommandsPacket.Node node : lastNodes) { diff --git a/src/main/java/net/minestom/server/command/builder/arguments/ArgumentWord.java b/src/main/java/net/minestom/server/command/builder/arguments/ArgumentWord.java index 239ff5b50..64a6a7239 100644 --- a/src/main/java/net/minestom/server/command/builder/arguments/ArgumentWord.java +++ b/src/main/java/net/minestom/server/command/builder/arguments/ArgumentWord.java @@ -8,7 +8,6 @@ import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Arrays; import java.util.function.Consumer; /** @@ -126,17 +125,4 @@ public class ArgumentWord extends Argument { public String[] getRestrictions() { return restrictions; } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ArgumentWord that = (ArgumentWord) o; - return Arrays.equals(restrictions, that.restrictions); - } - - @Override - public int hashCode() { - return Arrays.hashCode(restrictions); - } }