2020-07-10 16:37:18 +02:00
|
|
|
package net.minestom.server.command.builder;
|
|
|
|
|
2021-01-15 22:04:57 +01:00
|
|
|
import it.unimi.dsi.fastutil.ints.Int2ObjectRBTreeMap;
|
2020-07-14 13:35:07 +02:00
|
|
|
import net.minestom.server.command.CommandSender;
|
2020-07-10 16:37:18 +02:00
|
|
|
import net.minestom.server.command.builder.arguments.Argument;
|
|
|
|
import net.minestom.server.command.builder.condition.CommandCondition;
|
2021-01-08 03:07:37 +01:00
|
|
|
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
2020-10-29 19:51:10 +01:00
|
|
|
import org.jetbrains.annotations.NotNull;
|
2020-10-28 01:29:05 +01:00
|
|
|
import org.jetbrains.annotations.Nullable;
|
2020-07-10 16:37:18 +02:00
|
|
|
|
|
|
|
import java.util.*;
|
|
|
|
import java.util.regex.Pattern;
|
|
|
|
|
2020-10-15 14:36:21 +02:00
|
|
|
/**
|
|
|
|
* Class responsible for parsing {@link Command}.
|
|
|
|
*/
|
2020-07-14 13:35:07 +02:00
|
|
|
public class CommandDispatcher {
|
2020-07-10 16:37:18 +02:00
|
|
|
|
2020-10-15 14:36:21 +02:00
|
|
|
private final Map<String, Command> commandMap = new HashMap<>();
|
2021-02-10 00:24:23 +01:00
|
|
|
private final Set<Command> commands = new HashSet<>();
|
2020-07-10 16:37:18 +02:00
|
|
|
|
2020-11-14 01:39:51 +01:00
|
|
|
/**
|
|
|
|
* Registers a command,
|
|
|
|
* be aware that registering a command name or alias will override the previous entry.
|
|
|
|
*
|
|
|
|
* @param command the command to register
|
|
|
|
*/
|
2020-10-29 19:51:10 +01:00
|
|
|
public void register(@NotNull Command command) {
|
2020-08-04 06:14:42 +02:00
|
|
|
this.commandMap.put(command.getName().toLowerCase(), command);
|
2020-10-29 19:51:10 +01:00
|
|
|
|
|
|
|
// Register aliases
|
|
|
|
final String[] aliases = command.getAliases();
|
|
|
|
if (aliases != null) {
|
2021-02-09 18:24:50 +01:00
|
|
|
for (String alias : aliases) {
|
2020-10-29 19:51:10 +01:00
|
|
|
this.commandMap.put(alias.toLowerCase(), command);
|
|
|
|
}
|
2020-07-10 16:37:18 +02:00
|
|
|
}
|
2021-02-10 00:24:23 +01:00
|
|
|
|
|
|
|
this.commands.add(command);
|
2020-07-10 16:37:18 +02:00
|
|
|
}
|
|
|
|
|
2020-11-24 22:56:12 +01:00
|
|
|
public void unregister(@NotNull Command command) {
|
2020-12-12 06:13:50 +01:00
|
|
|
this.commandMap.remove(command.getName().toLowerCase());
|
|
|
|
|
|
|
|
final String[] aliases = command.getAliases();
|
|
|
|
if (aliases != null) {
|
|
|
|
for (String alias : aliases) {
|
|
|
|
this.commandMap.remove(alias.toLowerCase());
|
|
|
|
}
|
2020-11-06 16:03:08 +01:00
|
|
|
}
|
2021-02-10 00:24:23 +01:00
|
|
|
|
|
|
|
this.commands.remove(command);
|
2020-11-06 16:03:08 +01:00
|
|
|
}
|
|
|
|
|
2020-08-03 06:36:42 +02:00
|
|
|
/**
|
2020-10-29 19:51:10 +01:00
|
|
|
* Parses the given command.
|
2020-08-03 06:36:42 +02:00
|
|
|
*
|
|
|
|
* @param commandString the command (containing the command name and the args if any)
|
|
|
|
* @return the result of the parsing, null if the command doesn't exist
|
|
|
|
*/
|
2021-01-15 19:26:12 +01:00
|
|
|
@Nullable
|
2020-10-29 19:51:10 +01:00
|
|
|
public CommandResult parse(@NotNull String commandString) {
|
2020-07-10 16:37:18 +02:00
|
|
|
commandString = commandString.trim();
|
|
|
|
|
|
|
|
// Split space
|
2021-01-08 03:07:37 +01:00
|
|
|
final String[] parts = commandString.split(StringUtils.SPACE);
|
2020-10-29 19:51:10 +01:00
|
|
|
final String commandName = parts[0];
|
2020-07-10 16:37:18 +02:00
|
|
|
|
2020-08-03 06:36:42 +02:00
|
|
|
final Command command = findCommand(commandName);
|
|
|
|
// Check if the command exists
|
2020-07-10 16:37:18 +02:00
|
|
|
if (command == null)
|
|
|
|
return null;
|
|
|
|
|
2021-02-09 18:24:50 +01:00
|
|
|
// Removes the command's name + the space after
|
|
|
|
final String[] args = commandString.replaceFirst(Pattern.quote(commandName), "").trim().split(StringUtils.SPACE);
|
|
|
|
|
2020-08-03 06:36:42 +02:00
|
|
|
// Find the used syntax, or check which argument is wrong
|
2020-07-10 16:37:18 +02:00
|
|
|
return findCommandResult(command, args);
|
|
|
|
}
|
|
|
|
|
2020-12-15 09:30:09 +01:00
|
|
|
/**
|
2021-02-08 03:42:35 +01:00
|
|
|
* Checks if the command exists, and execute it.
|
2020-12-15 09:30:09 +01:00
|
|
|
*
|
|
|
|
* @param source the command source
|
|
|
|
* @param commandString the command with the argument(s)
|
2021-02-08 03:42:35 +01:00
|
|
|
* @return the command data, null if none
|
2020-12-15 09:30:09 +01:00
|
|
|
*/
|
2021-02-08 03:42:35 +01:00
|
|
|
@Nullable
|
2021-02-08 04:08:22 +01:00
|
|
|
public CommandData execute(@NotNull CommandSender source, @NotNull String commandString) {
|
2020-07-10 16:37:18 +02:00
|
|
|
CommandResult result = parse(commandString);
|
2020-12-15 09:30:09 +01:00
|
|
|
if (result != null) {
|
2021-02-08 03:42:35 +01:00
|
|
|
return result.execute(source, commandString);
|
2020-12-15 09:30:09 +01:00
|
|
|
}
|
2021-02-08 03:42:35 +01:00
|
|
|
return null;
|
2020-07-10 16:37:18 +02:00
|
|
|
}
|
|
|
|
|
2020-10-29 19:51:10 +01:00
|
|
|
@NotNull
|
2021-02-10 00:27:41 +01:00
|
|
|
public Set<Command> getCommands() {
|
|
|
|
return Collections.unmodifiableSet(commands);
|
2020-07-10 16:37:18 +02:00
|
|
|
}
|
|
|
|
|
2020-08-04 06:14:42 +02:00
|
|
|
/**
|
2020-10-15 21:16:31 +02:00
|
|
|
* GetS the command class associated with the name;
|
2020-08-04 06:14:42 +02:00
|
|
|
*
|
|
|
|
* @param commandName the command name
|
|
|
|
* @return the {@link Command} associated with the name, null if not any
|
|
|
|
*/
|
2020-10-29 19:51:10 +01:00
|
|
|
@Nullable
|
|
|
|
public Command findCommand(@NotNull String commandName) {
|
2020-08-04 06:14:42 +02:00
|
|
|
commandName = commandName.toLowerCase();
|
2020-10-15 14:36:21 +02:00
|
|
|
return commandMap.getOrDefault(commandName, null);
|
2020-07-10 16:37:18 +02:00
|
|
|
}
|
|
|
|
|
2021-01-05 21:54:17 +01:00
|
|
|
@NotNull
|
2020-10-29 19:51:10 +01:00
|
|
|
private CommandResult findCommandResult(@NotNull Command command, @NotNull String[] args) {
|
2020-07-10 16:37:18 +02:00
|
|
|
CommandResult result = new CommandResult();
|
|
|
|
result.command = command;
|
|
|
|
|
|
|
|
Arguments executorArgs = new Arguments();
|
|
|
|
|
2020-10-29 19:51:10 +01:00
|
|
|
// The default executor should be used if no argument is provided
|
2020-07-10 16:37:18 +02:00
|
|
|
if (args[0].length() == 0) {
|
|
|
|
result.executor = command.getDefaultExecutor();
|
|
|
|
result.arguments = executorArgs;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-10-29 19:51:10 +01:00
|
|
|
// SYNTAXES PARSING
|
2020-07-10 16:37:18 +02:00
|
|
|
|
2020-10-29 19:51:10 +01:00
|
|
|
// All the registered syntaxes of the command
|
2020-08-03 06:36:42 +02:00
|
|
|
final Collection<CommandSyntax> syntaxes = command.getSyntaxes();
|
2020-10-29 19:51:10 +01:00
|
|
|
// Contains all the fully validated syntaxes (we later find the one with the most amount of arguments)
|
2021-02-10 00:24:23 +01:00
|
|
|
List<ValidSyntaxHolder> validSyntaxes = new ArrayList<>(syntaxes.size());
|
2020-07-10 16:37:18 +02:00
|
|
|
|
2020-10-29 19:51:10 +01:00
|
|
|
// Contains all the syntaxes that are not fully correct, used to later, retrieve the "most correct syntax"
|
|
|
|
// Number of correct argument - The data about the failing argument
|
2021-01-15 22:04:57 +01:00
|
|
|
Int2ObjectRBTreeMap<CommandSuggestionHolder> syntaxesSuggestions = new Int2ObjectRBTreeMap<>(Collections.reverseOrder());
|
2020-07-10 16:37:18 +02:00
|
|
|
|
|
|
|
for (CommandSyntax syntax : syntaxes) {
|
2021-02-09 01:33:56 +01:00
|
|
|
// List of all arguments in the current syntax
|
2020-10-29 22:52:07 +01:00
|
|
|
final Argument<?>[] arguments = syntax.getArguments();
|
2021-02-09 01:33:56 +01:00
|
|
|
// Empty object containing the maximum amount of argument results of the syntax.
|
2021-02-09 02:59:46 +01:00
|
|
|
final List<Object> argsValues = new ArrayList<>(arguments.length);
|
2020-07-10 16:37:18 +02:00
|
|
|
|
|
|
|
boolean syntaxCorrect = true;
|
2020-11-03 23:31:26 +01:00
|
|
|
// The current index in the raw command string arguments
|
2021-01-08 03:07:37 +01:00
|
|
|
int splitIndex = 0;
|
2020-07-10 16:37:18 +02:00
|
|
|
|
2021-02-09 02:59:46 +01:00
|
|
|
boolean useRemaining = false;
|
2020-10-29 19:51:10 +01:00
|
|
|
// Check the validity of the arguments...
|
2021-01-01 23:36:53 +01:00
|
|
|
for (int argCount = 0; argCount < arguments.length; argCount++) {
|
2021-01-08 03:07:37 +01:00
|
|
|
final boolean lastArgumentIteration = argCount + 1 == arguments.length;
|
2021-01-01 23:36:53 +01:00
|
|
|
final Argument<?> argument = arguments[argCount];
|
2020-07-10 16:37:18 +02:00
|
|
|
useRemaining = argument.useRemaining();
|
|
|
|
|
2021-01-08 03:07:37 +01:00
|
|
|
// the parsed argument value, null if incorrect
|
|
|
|
Object parsedValue;
|
|
|
|
// the argument exception, null if the input is correct
|
|
|
|
ArgumentSyntaxException argumentSyntaxException = null;
|
2020-08-03 10:35:46 +02:00
|
|
|
// true if the arg is valid, false otherwise
|
2020-07-10 16:37:18 +02:00
|
|
|
boolean correct = false;
|
2020-08-03 10:35:46 +02:00
|
|
|
// the raw string representing the correct argument syntax
|
2020-08-19 01:24:51 +02:00
|
|
|
StringBuilder argValue = new StringBuilder();
|
2020-07-10 16:37:18 +02:00
|
|
|
|
|
|
|
if (useRemaining) {
|
2021-01-08 03:07:37 +01:00
|
|
|
final boolean hasArgs = args.length > splitIndex;
|
2020-11-03 23:31:26 +01:00
|
|
|
// Verify if there is any string part available
|
|
|
|
if (hasArgs) {
|
|
|
|
// Argument is supposed to take the rest of the command input
|
2021-01-08 03:07:37 +01:00
|
|
|
for (int i = splitIndex; i < args.length; i++) {
|
2020-11-03 23:31:26 +01:00
|
|
|
final String arg = args[i];
|
|
|
|
if (argValue.length() > 0)
|
2021-01-08 03:07:37 +01:00
|
|
|
argValue.append(StringUtils.SPACE);
|
2020-11-03 23:31:26 +01:00
|
|
|
argValue.append(arg);
|
|
|
|
}
|
2020-07-10 16:37:18 +02:00
|
|
|
|
2020-11-03 23:31:26 +01:00
|
|
|
final String argValueString = argValue.toString();
|
2020-08-19 01:24:51 +02:00
|
|
|
|
2021-01-08 03:07:37 +01:00
|
|
|
try {
|
|
|
|
parsedValue = argument.parse(argValueString);
|
2020-11-03 23:31:26 +01:00
|
|
|
correct = true;
|
2021-02-09 02:59:46 +01:00
|
|
|
argsValues.add(parsedValue);
|
2021-01-08 03:07:37 +01:00
|
|
|
} catch (ArgumentSyntaxException exception) {
|
|
|
|
argumentSyntaxException = exception;
|
2020-11-03 23:31:26 +01:00
|
|
|
}
|
2020-07-10 16:37:18 +02:00
|
|
|
}
|
|
|
|
} else {
|
2020-10-29 19:51:10 +01:00
|
|
|
// Argument is either single-word or can accept optional delimited space(s)
|
2021-01-08 03:07:37 +01:00
|
|
|
for (int i = splitIndex; i < args.length; i++) {
|
2020-11-26 00:57:01 +01:00
|
|
|
final String rawArg = args[i];
|
2020-07-10 16:37:18 +02:00
|
|
|
|
2020-11-26 00:57:01 +01:00
|
|
|
argValue.append(rawArg);
|
2020-08-19 01:24:51 +02:00
|
|
|
|
|
|
|
final String argValueString = argValue.toString();
|
2020-07-10 16:37:18 +02:00
|
|
|
|
2021-01-08 03:07:37 +01:00
|
|
|
try {
|
|
|
|
parsedValue = argument.parse(argValueString);
|
|
|
|
|
|
|
|
// Prevent quitting the parsing too soon if the argument
|
|
|
|
// does not allow space
|
|
|
|
if (lastArgumentIteration && i + 1 < args.length) {
|
|
|
|
if (!argument.allowSpace())
|
|
|
|
break;
|
|
|
|
argValue.append(StringUtils.SPACE);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-07-10 16:37:18 +02:00
|
|
|
correct = true;
|
2021-02-09 02:59:46 +01:00
|
|
|
argsValues.add(parsedValue);
|
2021-01-08 03:07:37 +01:00
|
|
|
splitIndex = i + 1;
|
2020-07-10 16:37:18 +02:00
|
|
|
break;
|
2021-01-08 03:07:37 +01:00
|
|
|
} catch (ArgumentSyntaxException exception) {
|
|
|
|
argumentSyntaxException = exception;
|
|
|
|
|
2020-07-10 16:37:18 +02:00
|
|
|
if (!argument.allowSpace())
|
|
|
|
break;
|
2021-01-08 03:07:37 +01:00
|
|
|
argValue.append(StringUtils.SPACE);
|
2020-07-10 16:37:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-29 19:51:10 +01:00
|
|
|
if (!correct) {
|
2020-10-15 14:36:21 +02:00
|
|
|
// Argument is not correct, add it to the syntax suggestion with the number
|
|
|
|
// of correct argument(s) and do not check the next syntax argument
|
2020-07-10 16:37:18 +02:00
|
|
|
syntaxCorrect = false;
|
|
|
|
CommandSuggestionHolder suggestionHolder = new CommandSuggestionHolder();
|
|
|
|
suggestionHolder.syntax = syntax;
|
2021-01-08 03:07:37 +01:00
|
|
|
suggestionHolder.argumentSyntaxException = argumentSyntaxException;
|
2020-07-10 16:37:18 +02:00
|
|
|
suggestionHolder.argIndex = argCount;
|
|
|
|
syntaxesSuggestions.put(argCount, suggestionHolder);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-10-15 14:36:21 +02:00
|
|
|
|
|
|
|
// Add the syntax to the list of valid syntaxes if correct
|
2020-07-10 16:37:18 +02:00
|
|
|
if (syntaxCorrect) {
|
2021-02-09 02:59:46 +01:00
|
|
|
if (arguments.length == argsValues.size() || useRemaining) {
|
|
|
|
ValidSyntaxHolder validSyntaxHolder = new ValidSyntaxHolder();
|
|
|
|
validSyntaxHolder.syntax = syntax;
|
|
|
|
validSyntaxHolder.argumentsValue = argsValues;
|
2021-01-08 03:07:37 +01:00
|
|
|
|
2021-02-09 02:59:46 +01:00
|
|
|
validSyntaxes.add(validSyntaxHolder);
|
|
|
|
}
|
2020-07-10 16:37:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-29 19:51:10 +01:00
|
|
|
// Check if there is at least one correct syntax
|
2020-10-28 01:02:12 +01:00
|
|
|
if (!validSyntaxes.isEmpty()) {
|
|
|
|
// Search the syntax with all perfect args
|
2021-01-08 03:07:37 +01:00
|
|
|
final CommandSyntax finalSyntax = findMostCorrectSyntax(validSyntaxes, executorArgs);
|
2020-10-28 01:29:05 +01:00
|
|
|
if (finalSyntax != null) {
|
2020-10-29 19:51:10 +01:00
|
|
|
// A fully correct syntax has been found, use it
|
2020-11-04 04:45:46 +01:00
|
|
|
result.syntax = finalSyntax;
|
2020-10-28 01:29:05 +01:00
|
|
|
result.executor = finalSyntax.getExecutor();
|
|
|
|
result.arguments = executorArgs;
|
|
|
|
return result;
|
2020-10-28 01:02:12 +01:00
|
|
|
}
|
2020-07-10 16:37:18 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-10-29 19:51:10 +01:00
|
|
|
// No all-correct syntax, find the closest one to use the argument callback
|
2020-10-28 01:02:12 +01:00
|
|
|
{
|
2020-07-10 16:37:18 +02:00
|
|
|
// Get closest valid syntax
|
|
|
|
if (!syntaxesSuggestions.isEmpty()) {
|
2021-01-15 22:04:57 +01:00
|
|
|
final int max = syntaxesSuggestions.firstIntKey(); // number of correct arguments in the most correct syntax
|
2021-01-11 01:54:59 +01:00
|
|
|
final CommandSuggestionHolder suggestionHolder = syntaxesSuggestions.get(max);
|
|
|
|
final CommandSyntax syntax = suggestionHolder.syntax;
|
|
|
|
final ArgumentSyntaxException argumentSyntaxException = suggestionHolder.argumentSyntaxException;
|
|
|
|
final int argIndex = suggestionHolder.argIndex;
|
|
|
|
|
|
|
|
// Found the closest syntax with at least 1 correct argument
|
|
|
|
final Argument<?> argument = syntax.getArguments()[argIndex];
|
|
|
|
if (argument.hasErrorCallback()) {
|
|
|
|
result.callback = argument.getCallback();
|
|
|
|
result.argumentSyntaxException = argumentSyntaxException;
|
|
|
|
|
|
|
|
return result;
|
2020-10-29 19:51:10 +01:00
|
|
|
}
|
2020-07-10 16:37:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-29 19:51:10 +01:00
|
|
|
// Use the default executor at last resort
|
2020-10-28 01:02:12 +01:00
|
|
|
result.executor = command.getDefaultExecutor();
|
2020-07-10 16:37:18 +02:00
|
|
|
result.arguments = executorArgs;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-10-29 19:51:10 +01:00
|
|
|
/**
|
|
|
|
* Retrieves from the valid syntax map the arguments condition result and get the one with the most
|
|
|
|
* valid arguments.
|
|
|
|
*
|
2021-01-08 03:07:37 +01:00
|
|
|
* @param validSyntaxes the list containing all the valid syntaxes
|
|
|
|
* @param executorArgs the recipient of the argument parsed values
|
2020-10-29 19:51:10 +01:00
|
|
|
* @return the command syntax with all of its arguments correct and with the most arguments count, null if not any
|
|
|
|
*/
|
2020-10-28 01:29:05 +01:00
|
|
|
@Nullable
|
2021-01-08 03:07:37 +01:00
|
|
|
private CommandSyntax findMostCorrectSyntax(@NotNull List<ValidSyntaxHolder> validSyntaxes,
|
2020-10-29 19:51:10 +01:00
|
|
|
@NotNull Arguments executorArgs) {
|
2020-10-28 01:29:05 +01:00
|
|
|
CommandSyntax finalSyntax = null;
|
|
|
|
int maxArguments = 0;
|
2021-01-08 03:07:37 +01:00
|
|
|
Arguments finalArguments = null;
|
|
|
|
|
|
|
|
for (ValidSyntaxHolder validSyntaxHolder : validSyntaxes) {
|
|
|
|
final CommandSyntax syntax = validSyntaxHolder.syntax;
|
2020-10-28 01:29:05 +01:00
|
|
|
|
2020-10-29 22:52:07 +01:00
|
|
|
final Argument<?>[] arguments = syntax.getArguments();
|
2021-01-08 03:07:37 +01:00
|
|
|
final int argumentsCount = arguments.length;
|
2021-02-09 02:59:46 +01:00
|
|
|
final List<Object> argsValues = validSyntaxHolder.argumentsValue;
|
2021-01-08 03:07:37 +01:00
|
|
|
|
2021-02-09 02:59:46 +01:00
|
|
|
final int argsSize = argsValues.size();
|
2020-10-28 01:29:05 +01:00
|
|
|
|
2021-01-08 03:07:37 +01:00
|
|
|
if (argsSize > maxArguments) {
|
2020-10-28 01:29:05 +01:00
|
|
|
finalSyntax = syntax;
|
2021-01-08 03:07:37 +01:00
|
|
|
maxArguments = argsSize;
|
|
|
|
|
|
|
|
// Fill arguments map
|
|
|
|
Arguments syntaxValues = new Arguments();
|
|
|
|
for (int i = 0; i < argumentsCount; i++) {
|
|
|
|
final Argument<?> argument = arguments[i];
|
2021-02-09 02:59:46 +01:00
|
|
|
final Object argumentValue = argsValues.get(i);
|
2021-01-08 03:07:37 +01:00
|
|
|
|
|
|
|
syntaxValues.setArg(argument.getId(), argumentValue);
|
|
|
|
}
|
|
|
|
finalArguments = syntaxValues;
|
2020-10-28 01:29:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-28 01:55:44 +01:00
|
|
|
// Get the arguments values
|
|
|
|
if (finalSyntax != null) {
|
2021-01-08 03:07:37 +01:00
|
|
|
executorArgs.copy(finalArguments);
|
2020-10-28 01:55:44 +01:00
|
|
|
}
|
|
|
|
|
2020-10-28 01:29:05 +01:00
|
|
|
return finalSyntax;
|
|
|
|
}
|
|
|
|
|
2021-01-08 03:07:37 +01:00
|
|
|
/**
|
|
|
|
* Holds the data of a validated syntax.
|
|
|
|
*/
|
|
|
|
private static class ValidSyntaxHolder {
|
|
|
|
private CommandSyntax syntax;
|
|
|
|
/**
|
|
|
|
* (Argument index/Argument parsed object)
|
|
|
|
*/
|
2021-02-09 02:59:46 +01:00
|
|
|
private List<Object> argumentsValue;
|
2021-01-08 03:07:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Holds the data of an invalidated syntax.
|
|
|
|
*/
|
2020-08-19 01:24:51 +02:00
|
|
|
private static class CommandSuggestionHolder {
|
2020-07-10 16:37:18 +02:00
|
|
|
private CommandSyntax syntax;
|
2021-01-08 03:07:37 +01:00
|
|
|
private ArgumentSyntaxException argumentSyntaxException;
|
2020-07-10 16:37:18 +02:00
|
|
|
private int argIndex;
|
|
|
|
}
|
|
|
|
|
2020-10-08 01:28:40 +02:00
|
|
|
/**
|
2020-10-15 14:36:21 +02:00
|
|
|
* Represents a {@link Command} ready to be executed (already parsed).
|
2020-10-08 01:28:40 +02:00
|
|
|
*/
|
2020-08-19 01:24:51 +02:00
|
|
|
private static class CommandResult {
|
2020-10-08 01:28:40 +02:00
|
|
|
|
2020-07-10 16:37:18 +02:00
|
|
|
// Command
|
2020-07-14 13:35:07 +02:00
|
|
|
private Command command;
|
2020-07-10 16:37:18 +02:00
|
|
|
|
|
|
|
// Command Executor
|
2020-11-04 04:45:46 +01:00
|
|
|
private CommandSyntax syntax;
|
|
|
|
|
2020-07-10 16:37:18 +02:00
|
|
|
private CommandExecutor executor;
|
|
|
|
private Arguments arguments;
|
|
|
|
|
|
|
|
// Argument Callback
|
|
|
|
private ArgumentCallback callback;
|
2021-01-08 03:07:37 +01:00
|
|
|
private ArgumentSyntaxException argumentSyntaxException;
|
2020-07-10 16:37:18 +02:00
|
|
|
|
2020-08-03 06:36:42 +02:00
|
|
|
/**
|
2020-10-29 19:51:10 +01:00
|
|
|
* Executes the command for the given source.
|
2020-08-03 06:36:42 +02:00
|
|
|
* <p>
|
2020-10-15 14:36:21 +02:00
|
|
|
* The command will not be executed if {@link Command#getCondition()}
|
|
|
|
* is not validated.
|
2020-08-03 06:36:42 +02:00
|
|
|
*
|
2020-10-08 01:21:15 +02:00
|
|
|
* @param source the command source
|
|
|
|
* @param commandString the command string
|
2021-02-08 03:42:35 +01:00
|
|
|
* @return the command data, null if none
|
2020-08-03 06:36:42 +02:00
|
|
|
*/
|
2021-02-08 03:42:35 +01:00
|
|
|
@Nullable
|
2021-02-08 04:08:22 +01:00
|
|
|
public CommandData execute(@NotNull CommandSender source, @NotNull String commandString) {
|
2020-10-08 01:21:15 +02:00
|
|
|
// Global listener
|
|
|
|
command.globalListener(source, arguments, commandString);
|
2020-11-04 04:45:46 +01:00
|
|
|
// Command condition check
|
2020-08-03 06:36:42 +02:00
|
|
|
final CommandCondition condition = command.getCondition();
|
2020-07-10 16:37:18 +02:00
|
|
|
if (condition != null) {
|
2020-11-04 04:45:46 +01:00
|
|
|
final boolean result = condition.canUse(source, commandString);
|
2020-07-10 16:37:18 +02:00
|
|
|
if (!result)
|
2021-02-08 03:42:35 +01:00
|
|
|
return null;
|
2020-07-10 16:37:18 +02:00
|
|
|
}
|
|
|
|
// Condition is respected
|
|
|
|
if (executor != null) {
|
2020-08-03 06:36:42 +02:00
|
|
|
// An executor has been found
|
2020-11-04 04:45:46 +01:00
|
|
|
|
|
|
|
if (syntax != null) {
|
|
|
|
// The executor is from a syntax
|
|
|
|
final CommandCondition commandCondition = syntax.getCommandCondition();
|
|
|
|
if (commandCondition == null || commandCondition.canUse(source, commandString)) {
|
2021-01-01 23:36:53 +01:00
|
|
|
arguments.retrieveDefaultValues(syntax.getDefaultValuesMap());
|
2020-11-04 04:45:46 +01:00
|
|
|
executor.apply(source, arguments);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// The executor is probably the default one
|
|
|
|
executor.apply(source, arguments);
|
|
|
|
}
|
2021-01-08 03:07:37 +01:00
|
|
|
} else if (callback != null && argumentSyntaxException != null) {
|
2020-10-08 01:28:40 +02:00
|
|
|
// No syntax has been validated but the faulty argument with a callback has been found
|
2020-08-03 06:36:42 +02:00
|
|
|
// Execute the faulty argument callback
|
2021-01-08 03:07:37 +01:00
|
|
|
callback.apply(source, argumentSyntaxException);
|
2020-07-10 16:37:18 +02:00
|
|
|
}
|
2021-02-08 03:42:35 +01:00
|
|
|
|
2021-02-08 04:08:22 +01:00
|
|
|
return arguments.getReturnData();
|
2020-07-10 16:37:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|