Rewrite of the command nodes creation

This commit is contained in:
themode 2021-02-11 06:37:09 +01:00
parent ab9ddebfea
commit f639ac83f7
5 changed files with 76 additions and 90 deletions

View File

@ -418,7 +418,7 @@ public final class CommandManager {
// Contains the arguments of the already-parsed syntaxes // Contains the arguments of the already-parsed syntaxes
List<Argument<?>[]> syntaxesArguments = new ArrayList<>(); List<Argument<?>[]> syntaxesArguments = new ArrayList<>();
// Contains the nodes of an argument // Contains the nodes of an argument
Map<Argument<?>, DeclareCommandsPacket.Node[]> storedArgumentsNodes = new HashMap<>(); Map<Argument<?>, List<DeclareCommandsPacket.Node[]>> storedArgumentsNodes = new HashMap<>();
for (CommandSyntax syntax : syntaxes) { for (CommandSyntax syntax : syntaxes) {
final CommandCondition commandCondition = syntax.getCommandCondition(); final CommandCondition commandCondition = syntax.getCommandCondition();
@ -430,51 +430,54 @@ public final class CommandManager {
NodeMaker nodeMaker = new NodeMaker(); NodeMaker nodeMaker = new NodeMaker();
// Represent the last nodes computed in the last iteration // 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 // Represent the children of the last node
IntList argChildren = null; IntList argChildren = cmdChildren;
int lastArgumentNodeIndex = 0;
final Argument<?>[] arguments = syntax.getArguments(); final Argument<?>[] arguments = syntax.getArguments();
for (int i = 0; i < arguments.length; i++) { for (int i = 0; i < arguments.length; i++) {
final Argument<?> argument = arguments[i]; final Argument<?> argument = arguments[i];
final boolean isFirst = i == 0;
final boolean isLast = i == arguments.length - 1; final boolean isLast = i == arguments.length - 1;
// Search previously parsed syntaxes to find identical part in order to create a node between those
{
// Find shared part // Find shared part
boolean foundSharedPart = false; boolean foundSharedPart = false;
for (Argument<?>[] parsedArguments : syntaxesArguments) { for (Argument<?>[] parsedArguments : syntaxesArguments) {
if (ArrayUtils.sameStart(arguments, parsedArguments, i + 1)) { if (ArrayUtils.sameStart(arguments, parsedArguments, i + 1)) {
final Argument<?> sharedArgument = parsedArguments[i]; final Argument<?> sharedArgument = parsedArguments[i];
final List<DeclareCommandsPacket.Node[]> storedNodes = storedArgumentsNodes.get(sharedArgument);
argChildren = new IntArrayList(); argChildren = new IntArrayList();
nodeMaker.setLastNodes(storedArgumentsNodes.get(sharedArgument)); lastNodes = storedNodes.get(storedNodes.size() - Math.max(arguments.length, parsedArguments.length));
foundSharedPart = true; foundSharedPart = true;
} }
} }
if (foundSharedPart) { if (foundSharedPart) {
continue; 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(); // Process the nodes for the argument
if (lastNodes != null) { {
final int[] children = ArrayUtils.toArray(argChildren); argument.processNodes(nodeMaker, isLast);
// Each node array represent a layer
final List<DeclareCommandsPacket.Node[]> 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 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) { for (DeclareCommandsPacket.Node lastNode : lastNodes) {
lastNode.children = lastNode.children == null ? lastNode.children = lastNode.children == null ?
children : children :
@ -482,25 +485,15 @@ public final class CommandManager {
} }
} }
// Always add to the main node list nodes.add(argumentNode);
nodes.add(node);
} }
//System.out.println("debug: " + argument.getId() + " : " + isFirst + " : " + isLast); lastNodes = argumentNodes;
//System.out.println("debug2: " + i);
//System.out.println("size: " + (argChildren != null ? argChildren.size() : "NULL"));
if (isLast) {
// Last argument doesn't have children
final int[] children = new int[0];
for (DeclareCommandsPacket.Node node : argumentNodes) {
node.children = children;
}
} else {
// Create children list which will be filled during next iteration
argChildren = new IntArrayList(); argChildren = new IntArrayList();
nodeMaker.setLastNodes(argumentNodes); }
// Used to do not re-compute the previous arguments
lastArgumentNodeIndex = nodesLayer.size();
} }
} }

View File

@ -2,32 +2,26 @@ package net.minestom.server.command.builder;
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket; import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public class NodeMaker { public class NodeMaker {
private DeclareCommandsPacket.Node[] lastNodes; private final List<DeclareCommandsPacket.Node[]> nodes = new ArrayList<>(2);
private DeclareCommandsPacket.Node[] currentNodes;
public DeclareCommandsPacket.Node[] getCurrentNodes() { public DeclareCommandsPacket.Node[] getLatestNodes() {
return currentNodes; if (nodes.isEmpty())
return null;
return nodes.get(nodes.size() - 1);
} }
public void addNodes(@NotNull DeclareCommandsPacket.Node[] nodes) { public void addNodes(@NotNull DeclareCommandsPacket.Node[] nodes) {
this.currentNodes = nodes; this.nodes.add(nodes);
} }
/** @NotNull
* Represents the nodes computed in the last iteration. public List<DeclareCommandsPacket.Node[]> getNodes() {
* return nodes;
* @return the previous nodes, null if none
*/
@Nullable
public DeclareCommandsPacket.Node[] getLastNodes() {
return lastNodes;
}
public void setLastNodes(DeclareCommandsPacket.Node[] lastNodes) {
this.lastNodes = lastNodes;
} }
} }

View File

@ -23,7 +23,6 @@ public abstract class Argument<T> {
private final String id; private final String id;
private final boolean allowSpace; private final boolean allowSpace;
private final boolean useRemaining; private final boolean useRemaining;
private Argument<?> redirect;
private ArgumentCallback callback; private ArgumentCallback callback;
@ -195,4 +194,18 @@ public abstract class Argument<T> {
return callback != null; 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();
}
} }

View File

@ -30,7 +30,7 @@ public class ArgumentCommand extends Argument<CommandResult> {
@Override @Override
public void processNodes(@NotNull NodeMaker nodeMaker, boolean executable) { 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 // FIXME check if lastNodes is null
for (DeclareCommandsPacket.Node node : lastNodes) { for (DeclareCommandsPacket.Node node : lastNodes) {

View File

@ -8,7 +8,6 @@ import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.function.Consumer; import java.util.function.Consumer;
/** /**
@ -126,17 +125,4 @@ public class ArgumentWord extends Argument<String> {
public String[] getRestrictions() { public String[] getRestrictions() {
return restrictions; 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);
}
} }