Nodes in command can now be shared with each other

This commit is contained in:
themode 2020-10-28 01:02:12 +01:00
parent 758c132645
commit d49ddc52b6
6 changed files with 115 additions and 39 deletions

View File

@ -201,6 +201,7 @@ public final class CommandManager {
// Contains the children of the main node (all commands name)
IntList rootChildren = new IntArrayList();
// Brigadier-like commands
for (Command command : dispatcher.getCommands()) {
// Check if player should see this command
final CommandCondition commandCondition = command.getCondition();
@ -281,7 +282,7 @@ public final class CommandManager {
}
/**
* Adds a command's syntaxes to the nodes list.
* Adds the command's syntaxes to the nodes list.
*
* @param nodes the nodes of the packet
* @param cmdChildren the main root of this command
@ -300,6 +301,11 @@ public final class CommandManager {
rootChildren.add(nodes.size());
nodes.add(literalNode);
// Contains the arguments of the already-parsed syntaxes
List<Argument[]> syntaxesArguments = new ArrayList<>();
// Contains the nodes of an argument
Map<Argument, List<DeclareCommandsPacket.Node>> storedArgumentsNodes = new HashMap<>();
for (CommandSyntax syntax : syntaxes) {
// Represent the last nodes computed in the last iteration
List<DeclareCommandsPacket.Node> lastNodes = null;
@ -313,8 +319,23 @@ public final class CommandManager {
final boolean isFirst = i == 0;
final boolean isLast = i == arguments.length - 1;
boolean foundSharedPart = false;
for (Argument[] parsedArguments : syntaxesArguments) {
if (ArrayUtils.sameStart(arguments, parsedArguments, i + 1)) {
final Argument sharedArgument = parsedArguments[i];
argChildren = new IntArrayList();
lastNodes = storedArgumentsNodes.get(sharedArgument);
foundSharedPart = true;
}
}
if (foundSharedPart) {
continue;
}
final List<DeclareCommandsPacket.Node> argumentNodes = toNodes(argument, isLast);
storedArgumentsNodes.put(argument, argumentNodes);
for (DeclareCommandsPacket.Node node : argumentNodes) {
final int childId = nodes.size();
@ -328,7 +349,11 @@ public final class CommandManager {
if (lastNodes != null) {
final int[] children = ArrayUtils.toArray(argChildren);
lastNodes.forEach(n -> n.children = children);
lastNodes.forEach(n -> {
n.children = n.children == null ?
children :
ArrayUtils.concatenateIntArrays(n.children, children);
});
}
nodes.add(node);
@ -349,6 +374,8 @@ public final class CommandManager {
}
}
syntaxesArguments.add(arguments);
}
final int[] children = ArrayUtils.toArray(cmdChildren);
//System.out.println("test " + children.length + " : " + children[0]);

View File

@ -113,4 +113,8 @@ public class Arguments {
this.args.put(id, value);
}
protected void clear() {
this.args.clear();
}
}

View File

@ -172,39 +172,60 @@ public class CommandDispatcher {
}
}
// Find the valid syntax with the most of args
CommandSyntax finalSyntax = null;
for (CommandSyntax syntax : validSyntaxes) {
if (finalSyntax == null || finalSyntax.getArguments().length < syntax.getArguments().length) {
finalSyntax = syntax;
}
}
if (!validSyntaxes.isEmpty()) {
// Search the syntax with all perfect args
for (CommandSyntax syntax : validSyntaxes) {
boolean fullyCorrect = true;
// Verify args conditions of finalSyntax
if (finalSyntax != null) {
final Argument[] arguments = finalSyntax.getArguments();
final String[] argsValues = syntaxesValues.get(finalSyntax);
for (int i = 0; i < arguments.length; i++) {
final Argument argument = arguments[i];
final String argValue = argsValues[i];
// Finally parse it
final Object parsedValue = argument.parse(argValue);
final int conditionResult = argument.getConditionResult(parsedValue);
if (conditionResult == Argument.SUCCESS) {
executorArgs.setArg(argument.getId(), parsedValue);
} else {
// Condition of an argument not correct, use the argument callback
result.callback = argument.getCallback();
result.value = argValue;
result.error = conditionResult;
final Argument[] arguments = syntax.getArguments();
final String[] argsValues = syntaxesValues.get(syntax);
for (int i = 0; i < arguments.length; i++) {
final Argument argument = arguments[i];
final String argValue = argsValues[i];
// Finally parse it
final Object parsedValue = argument.parse(argValue);
final int conditionResult = argument.getConditionResult(parsedValue);
if (conditionResult == Argument.SUCCESS) {
executorArgs.setArg(argument.getId(), parsedValue);
} else {
fullyCorrect = false;
}
}
if (fullyCorrect) {
result.executor = syntax.getExecutor();
result.arguments = executorArgs;
return result;
} else {
executorArgs.clear();
}
}
// Search the first syntax with an incorrect argument
for (CommandSyntax syntax : validSyntaxes) {
final Argument[] arguments = syntax.getArguments();
final String[] argsValues = syntaxesValues.get(syntax);
for (int i = 0; i < arguments.length; i++) {
final Argument argument = arguments[i];
final String argValue = argsValues[i];
// Finally parse it
final Object parsedValue = argument.parse(argValue);
final int conditionResult = argument.getConditionResult(parsedValue);
if (conditionResult != Argument.SUCCESS) {
// Condition of an argument not correct, use the argument callback
result.callback = argument.getCallback();
result.value = argValue;
result.error = conditionResult;
return result;
}
}
}
}
// If command isn't correct, find the closest
if (finalSyntax == null) {
{
// Get closest valid syntax
if (!syntaxesSuggestions.isEmpty()) {
final int max = syntaxesSuggestions.firstKey(); // number of correct arguments
@ -233,8 +254,8 @@ public class CommandDispatcher {
}
}
// Use finalSyntax, or default executor if no syntax has been found
result.executor = finalSyntax == null ? command.getDefaultExecutor() : finalSyntax.getExecutor();
// Use the default executor
result.executor = command.getDefaultExecutor();
result.arguments = executorArgs;
return result;

View File

@ -100,16 +100,16 @@ public class PlayerInventory implements InventoryModifier, InventoryClickHandler
itemStack = addItemStackEvent.getItemStack();
StackingRule stackingRule = itemStack.getStackingRule();
final StackingRule stackingRule = itemStack.getStackingRule();
for (int i = 0; i < items.length - 10; i++) {
ItemStack item = items[i];
StackingRule itemStackingRule = item.getStackingRule();
final StackingRule itemStackingRule = item.getStackingRule();
if (itemStackingRule.canBeStacked(itemStack, item)) {
int itemAmount = itemStackingRule.getAmount(item);
final int itemAmount = itemStackingRule.getAmount(item);
if (itemAmount == stackingRule.getMaxSize())
continue;
int itemStackAmount = itemStackingRule.getAmount(itemStack);
int totalAmount = itemStackAmount + itemAmount;
final int itemStackAmount = itemStackingRule.getAmount(itemStack);
final int totalAmount = itemStackAmount + itemAmount;
if (!stackingRule.canApply(itemStack, totalAmount)) {
item = itemStackingRule.apply(item, itemStackingRule.getMaxSize());

View File

@ -3,7 +3,8 @@ package net.minestom.server.resourcepack;
import net.minestom.server.entity.Player;
/**
* Represents the result of {@link Player#setResourcePack(ResourcePack)}.
* Represents the result of {@link Player#setResourcePack(ResourcePack)} in
* {@link net.minestom.server.event.player.PlayerResourcePackStatusEvent}.
*/
public enum ResourcePackStatus {
SUCCESS, DECLINED, FAILED_DOWNLOAD, ACCEPTED

View File

@ -11,16 +11,17 @@ public final class ArrayUtils {
}
public static byte[] concatenateByteArrays(@NotNull byte[]... arrays) {
public static int[] concatenateIntArrays(@NotNull int[]... arrays) {
int totalLength = 0;
for (byte[] array : arrays) {
for (int[] array : arrays) {
totalLength += array.length;
}
byte[] result = new byte[totalLength];
int[] result = new int[totalLength];
int startingPos = 0;
for (byte[] array : arrays) {
for (int[] array : arrays) {
System.arraycopy(array, 0, result, startingPos, array.length);
startingPos += array.length;
}
return result;
@ -71,6 +72,28 @@ public final class ArrayUtils {
return array;
}
/**
* Gets if two arrays share the same start until {@code length}
*
* @param array1 the first array
* @param array2 the second array
* @param length the length to check (0-length)
* @param <T> the type of the arrays
* @return true if both arrays share the same start
*/
public static <T> boolean sameStart(T[] array1, T[] array2, int length) {
for (int i = 0; i < length; i++) {
final T value1 = array1[i];
for (int j = 0; j < length; j++) {
final T value2 = array2[j];
if (!value1.equals(value2)) {
return false;
}
}
}
return true;
}
/**
* Fills an array using a supplier.
*