Cleanup basic command parsing

This commit is contained in:
TheMode 2021-08-19 09:06:24 +02:00
parent 7d752cc323
commit 987e355a70
2 changed files with 44 additions and 66 deletions

View File

@ -99,22 +99,17 @@ public final class CommandManager {
* @return the execution result * @return the execution result
*/ */
public @NotNull CommandResult execute(@NotNull CommandSender sender, @NotNull String command) { public @NotNull CommandResult execute(@NotNull CommandSender sender, @NotNull String command) {
// Command event // Command event
if (sender instanceof Player) { if (sender instanceof Player) {
Player player = (Player) sender; final Player player = (Player) sender;
PlayerCommandEvent playerCommandEvent = new PlayerCommandEvent(player, command); PlayerCommandEvent playerCommandEvent = new PlayerCommandEvent(player, command);
EventDispatcher.call(playerCommandEvent); EventDispatcher.call(playerCommandEvent);
if (playerCommandEvent.isCancelled()) if (playerCommandEvent.isCancelled())
return CommandResult.of(CommandResult.Type.CANCELLED, command); return CommandResult.of(CommandResult.Type.CANCELLED, command);
command = playerCommandEvent.getCommand(); command = playerCommandEvent.getCommand();
} }
// Process the command // Process the command
final var result = dispatcher.execute(sender, command); final CommandResult result = dispatcher.execute(sender, command);
if (result.getType() == CommandResult.Type.UNKNOWN) { if (result.getType() == CommandResult.Type.UNKNOWN) {
if (unknownCommandCallback != null) { if (unknownCommandCallback != null) {
this.unknownCommandCallback.apply(sender, command); this.unknownCommandCallback.apply(sender, command);

View File

@ -65,8 +65,7 @@ public class CommandDispatcher {
this.cache.invalidateAll(); this.cache.invalidateAll();
} }
@NotNull public @NotNull Set<Command> getCommands() {
public Set<Command> getCommands() {
return Collections.unmodifiableSet(commands); return Collections.unmodifiableSet(commands);
} }
@ -76,8 +75,7 @@ public class CommandDispatcher {
* @param commandName the command name * @param commandName the command name
* @return the {@link Command} associated with the name, null if not any * @return the {@link Command} associated with the name, null if not any
*/ */
@Nullable public @Nullable Command findCommand(@NotNull String commandName) {
public Command findCommand(@NotNull String commandName) {
commandName = commandName.toLowerCase(); commandName = commandName.toLowerCase();
return commandMap.getOrDefault(commandName, null); return commandMap.getOrDefault(commandName, null);
} }
@ -89,8 +87,7 @@ public class CommandDispatcher {
* @param commandString the command with the argument(s) * @param commandString the command with the argument(s)
* @return the command result * @return the command result
*/ */
@NotNull public @NotNull CommandResult execute(@NotNull CommandSender source, @NotNull String commandString) {
public CommandResult execute(@NotNull CommandSender source, @NotNull String commandString) {
CommandResult commandResult = parse(commandString); CommandResult commandResult = parse(commandString);
ParsedCommand parsedCommand = commandResult.parsedCommand; ParsedCommand parsedCommand = commandResult.parsedCommand;
if (parsedCommand != null) { if (parsedCommand != null) {
@ -105,10 +102,8 @@ public class CommandDispatcher {
* @param commandString the command (containing the command name and the args if any) * @param commandString the command (containing the command name and the args if any)
* @return the parsing result * @return the parsing result
*/ */
@NotNull public @NotNull CommandResult parse(@NotNull String commandString) {
public CommandResult parse(@NotNull String commandString) {
commandString = commandString.trim(); commandString = commandString.trim();
// Verify if the result is cached // Verify if the result is cached
{ {
final CommandResult cachedResult = cache.getIfPresent(commandString); final CommandResult cachedResult = cache.getIfPresent(commandString);
@ -134,18 +129,15 @@ public class CommandDispatcher {
findParsedCommand(command, commandName, commandQueryResult.args, commandString, result); findParsedCommand(command, commandName, commandQueryResult.args, commandString, result);
// Cache result // Cache result
{ this.cache.put(commandString, result);
this.cache.put(commandString, result);
}
return result; return result;
} }
@Nullable private @Nullable ParsedCommand findParsedCommand(@NotNull Command command,
private ParsedCommand findParsedCommand(@NotNull Command command, @NotNull String commandName, @NotNull String[] args,
@NotNull String commandName, @NotNull String[] args, @NotNull String commandString,
@NotNull String commandString, @NotNull CommandResult result) {
@NotNull CommandResult result) {
final boolean hasArgument = args.length > 0; final boolean hasArgument = args.length > 0;
// Search for subcommand // Search for subcommand
@ -162,41 +154,37 @@ public class CommandDispatcher {
final String input = commandName + StringUtils.SPACE + String.join(StringUtils.SPACE, args); final String input = commandName + StringUtils.SPACE + String.join(StringUtils.SPACE, args);
ParsedCommand parsedCommand = new ParsedCommand(); ParsedCommand parsedCommand = new ParsedCommand();
parsedCommand.command = command; parsedCommand.command = command;
parsedCommand.commandString = commandString; parsedCommand.commandString = commandString;
// The default executor should be used if no argument is provided // The default executor should be used if no argument is provided
{ if (!hasArgument) {
if (!hasArgument) { Optional<CommandSyntax> optionalSyntax = command.getSyntaxes()
Optional<CommandSyntax> optionalSyntax = command.getSyntaxes() .stream()
.stream() .filter(syntax -> syntax.getArguments().length == 0)
.filter(syntax -> syntax.getArguments().length == 0) .findFirst();
.findFirst();
if (optionalSyntax.isPresent()) { if (optionalSyntax.isPresent()) {
// Empty syntax found // Empty syntax found
final CommandSyntax syntax = optionalSyntax.get(); final CommandSyntax syntax = optionalSyntax.get();
parsedCommand.syntax = syntax;
parsedCommand.executor = syntax.getExecutor();
parsedCommand.context = new CommandContext(input);
parsedCommand.syntax = syntax; result.type = CommandResult.Type.SUCCESS;
parsedCommand.executor = syntax.getExecutor(); result.parsedCommand = parsedCommand;
return parsedCommand;
} else {
// No empty syntax, use default executor if any
final CommandExecutor defaultExecutor = command.getDefaultExecutor();
if (defaultExecutor != null) {
parsedCommand.executor = defaultExecutor;
parsedCommand.context = new CommandContext(input); parsedCommand.context = new CommandContext(input);
result.type = CommandResult.Type.SUCCESS; result.type = CommandResult.Type.SUCCESS;
result.parsedCommand = parsedCommand; result.parsedCommand = parsedCommand;
return parsedCommand; return parsedCommand;
} else {
// No empty syntax, use default executor if any
final CommandExecutor defaultExecutor = command.getDefaultExecutor();
if (defaultExecutor != null) {
parsedCommand.executor = defaultExecutor;
parsedCommand.context = new CommandContext(input);
result.type = CommandResult.Type.SUCCESS;
result.parsedCommand = parsedCommand;
return parsedCommand;
}
} }
} }
} }
@ -207,7 +195,6 @@ public class CommandDispatcher {
final Collection<CommandSyntax> syntaxes = command.getSyntaxes(); final Collection<CommandSyntax> syntaxes = command.getSyntaxes();
// Contains all the fully validated syntaxes (we later find the one with the most amount of arguments) // Contains all the fully validated syntaxes (we later find the one with the most amount of arguments)
List<ValidSyntaxHolder> validSyntaxes = new ArrayList<>(syntaxes.size()); List<ValidSyntaxHolder> validSyntaxes = new ArrayList<>(syntaxes.size());
// Contains all the syntaxes that are not fully correct, used to later, retrieve the "most correct syntax" // 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 // Number of correct argument - The data about the failing argument
Int2ObjectRBTreeMap<CommandSuggestionHolder> syntaxesSuggestions = new Int2ObjectRBTreeMap<>(Collections.reverseOrder()); Int2ObjectRBTreeMap<CommandSuggestionHolder> syntaxesSuggestions = new Int2ObjectRBTreeMap<>(Collections.reverseOrder());
@ -233,29 +220,25 @@ public class CommandDispatcher {
result.parsedCommand = parsedCommand; result.parsedCommand = parsedCommand;
return parsedCommand; return parsedCommand;
} }
} }
// No all-correct syntax, find the closest one to use the argument callback // No all-correct syntax, find the closest one to use the argument callback
{ if (!syntaxesSuggestions.isEmpty()) {
// Get closest valid syntax final int max = syntaxesSuggestions.firstIntKey(); // number of correct arguments in the most correct syntax
if (!syntaxesSuggestions.isEmpty()) { final CommandSuggestionHolder suggestionHolder = syntaxesSuggestions.get(max);
final int max = syntaxesSuggestions.firstIntKey(); // number of correct arguments in the most correct syntax final CommandSyntax syntax = suggestionHolder.syntax;
final CommandSuggestionHolder suggestionHolder = syntaxesSuggestions.get(max); final ArgumentSyntaxException argumentSyntaxException = suggestionHolder.argumentSyntaxException;
final CommandSyntax syntax = suggestionHolder.syntax; final int argIndex = suggestionHolder.argIndex;
final ArgumentSyntaxException argumentSyntaxException = suggestionHolder.argumentSyntaxException;
final int argIndex = suggestionHolder.argIndex;
// Found the closest syntax with at least 1 correct argument // Found the closest syntax with at least 1 correct argument
final Argument<?> argument = syntax.getArguments()[argIndex]; final Argument<?> argument = syntax.getArguments()[argIndex];
if (argument.hasErrorCallback()) { if (argument.hasErrorCallback() && argumentSyntaxException != null) {
parsedCommand.callback = argument.getCallback(); parsedCommand.callback = argument.getCallback();
parsedCommand.argumentSyntaxException = argumentSyntaxException; parsedCommand.argumentSyntaxException = argumentSyntaxException;
result.type = CommandResult.Type.INVALID_SYNTAX; result.type = CommandResult.Type.INVALID_SYNTAX;
result.parsedCommand = parsedCommand; result.parsedCommand = parsedCommand;
return parsedCommand; return parsedCommand;
}
} }
} }