Replace Arguments by CommandContext

This commit is contained in:
themode 2021-03-10 06:38:51 +01:00
parent b03b35b881
commit 67b3b37813
10 changed files with 71 additions and 47 deletions

View File

@ -23,15 +23,10 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
/** /**
* Class used to retrieve argument data in a {@link CommandExecutor}. * @deprecated renamed to {@link CommandContext}
* <p>
* All id are the one specified in the {@link net.minestom.server.command.builder.arguments.Argument} constructor.
* <p>
* All methods are @{@link NotNull} in the sense that you should not have to verify their validity since if the syntax
* is called, it means that all of its arguments are correct. Be aware that trying to retrieve an argument not present
* in the syntax will result in a {@link NullPointerException}.
*/ */
public final class Arguments { @Deprecated
public class Arguments {
private Map<String, Object> args = new HashMap<>(); private Map<String, Object> args = new HashMap<>();
@ -52,7 +47,7 @@ public final class Arguments {
public boolean has(@NotNull Argument<?> argument) { public boolean has(@NotNull Argument<?> argument) {
return args.containsKey(argument.getId()); return args.containsKey(argument.getId());
} }
public boolean has(@NotNull String identifier) { public boolean has(@NotNull String identifier) {
return args.containsKey(identifier); return args.containsKey(identifier);
} }

View File

@ -282,11 +282,11 @@ public class Command {
* <p> * <p>
* Can be used if you wish to still suggest the player syntaxes but want to parse things mostly by yourself. * Can be used if you wish to still suggest the player syntaxes but want to parse things mostly by yourself.
* *
* @param sender the {@link CommandSender} * @param sender the {@link CommandSender}
* @param arguments the UNCHECKED arguments of the command, some can be null even when unexpected * @param context the UNCHECKED context of the command, some can be null even when unexpected
* @param command the raw UNCHECKED received command * @param command the raw UNCHECKED received command
*/ */
public void globalListener(@NotNull CommandSender sender, @NotNull Arguments arguments, @NotNull String command) { public void globalListener(@NotNull CommandSender sender, @NotNull CommandContext context, @NotNull String command) {
} }
public static boolean isValidName(@NotNull Command command, @NotNull String name) { public static boolean isValidName(@NotNull Command command, @NotNull String name) {

View File

@ -0,0 +1,27 @@
package net.minestom.server.command.builder;
import net.minestom.server.command.builder.arguments.Argument;
import org.jetbrains.annotations.NotNull;
/**
* Class used to retrieve argument data in a {@link CommandExecutor}.
* <p>
* All id are the one specified in the {@link Argument} constructor.
* <p>
* All methods are @{@link NotNull} in the sense that you should not have to verify their validity since if the syntax
* is called, it means that all of its arguments are correct. Be aware that trying to retrieve an argument not present
* in the syntax will result in a {@link NullPointerException}.
*/
public class CommandContext extends Arguments {
private final String input;
public CommandContext(@NotNull String input) {
this.input = input;
}
@NotNull
public String getInput() {
return input;
}
}

View File

@ -129,7 +129,7 @@ public class CommandDispatcher {
CommandResult result = new CommandResult(); CommandResult result = new CommandResult();
result.input = commandString; result.input = commandString;
// Find the used syntax and fill CommandResult#type and CommandResult#parsedCommand // Find the used syntax and fill CommandResult#type and CommandResult#parsedCommand
findParsedCommand(command, args, result); findParsedCommand(command, commandName, args, result);
// Cache result // Cache result
{ {
@ -140,7 +140,7 @@ public class CommandDispatcher {
} }
@Nullable @Nullable
private ParsedCommand findParsedCommand(@NotNull Command command, @NotNull String[] args, @NotNull CommandResult result) { private ParsedCommand findParsedCommand(@NotNull Command command, @NotNull String commandName, @NotNull String[] args, @NotNull CommandResult result) {
final boolean hasArgument = args.length > 0; final boolean hasArgument = args.length > 0;
// Search for subcommand // Search for subcommand
@ -148,11 +148,13 @@ public class CommandDispatcher {
final String firstArgument = args[0]; final String firstArgument = args[0];
for (Command subcommand : command.getSubcommands()) { for (Command subcommand : command.getSubcommands()) {
if (Command.isValidName(subcommand, firstArgument)) { if (Command.isValidName(subcommand, firstArgument)) {
return findParsedCommand(subcommand, Arrays.copyOfRange(args, 1, args.length), result); return findParsedCommand(subcommand, firstArgument, Arrays.copyOfRange(args, 1, args.length), result);
} }
} }
} }
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;
@ -162,7 +164,7 @@ public class CommandDispatcher {
final CommandExecutor defaultExecutor = command.getDefaultExecutor(); final CommandExecutor defaultExecutor = command.getDefaultExecutor();
if (defaultExecutor != null && !hasArgument) { if (defaultExecutor != null && !hasArgument) {
parsedCommand.executor = defaultExecutor; parsedCommand.executor = defaultExecutor;
parsedCommand.arguments = new Arguments(); parsedCommand.context = new CommandContext(input);
result.type = CommandResult.Type.SUCCESS; result.type = CommandResult.Type.SUCCESS;
result.parsedCommand = parsedCommand; result.parsedCommand = parsedCommand;
@ -187,16 +189,16 @@ public class CommandDispatcher {
// Check if there is at least one correct syntax // Check if there is at least one correct syntax
if (!validSyntaxes.isEmpty()) { if (!validSyntaxes.isEmpty()) {
Arguments executorArgs = new Arguments(); CommandContext context = new CommandContext(input);
// Search the syntax with all perfect args // Search the syntax with all perfect args
final ValidSyntaxHolder finalValidSyntax = CommandParser.findMostCorrectSyntax(validSyntaxes, executorArgs); final ValidSyntaxHolder finalValidSyntax = CommandParser.findMostCorrectSyntax(validSyntaxes, context);
if (finalValidSyntax != null) { if (finalValidSyntax != null) {
// A fully correct syntax has been found, use it // A fully correct syntax has been found, use it
final CommandSyntax syntax = finalValidSyntax.syntax; final CommandSyntax syntax = finalValidSyntax.syntax;
parsedCommand.syntax = syntax; parsedCommand.syntax = syntax;
parsedCommand.executor = syntax.getExecutor(); parsedCommand.executor = syntax.getExecutor();
parsedCommand.arguments = executorArgs; parsedCommand.context = context;
result.type = CommandResult.Type.SUCCESS; result.type = CommandResult.Type.SUCCESS;
result.parsedCommand = parsedCommand; result.parsedCommand = parsedCommand;
@ -230,7 +232,7 @@ public class CommandDispatcher {
// No syntax found // No syntax found
result.type = CommandResult.Type.INVALID_SYNTAX; result.type = CommandResult.Type.INVALID_SYNTAX;
result.parsedCommand = ParsedCommand.withDefaultExecutor(command); result.parsedCommand = ParsedCommand.withDefaultExecutor(command, input);
return result.parsedCommand; return result.parsedCommand;
} }
} }

View File

@ -14,9 +14,8 @@ public interface CommandExecutor {
/** /**
* Executes the command callback once the syntax has been called (or the default executor). * Executes the command callback once the syntax has been called (or the default executor).
* *
* @param sender the sender of the command * @param sender the sender of the command
* @param args contains all the parsed arguments, * @param context the command context, used to retrieve the arguments and various other things
* the id is the one initialized when creating the argument object
*/ */
void apply(@NotNull CommandSender sender, @NotNull Arguments args); void apply(@NotNull CommandSender sender, @NotNull CommandContext context);
} }

View File

@ -18,7 +18,7 @@ public class ParsedCommand {
protected CommandSyntax syntax; protected CommandSyntax syntax;
protected CommandExecutor executor; protected CommandExecutor executor;
protected Arguments arguments; protected CommandContext context;
// Argument Callback // Argument Callback
protected ArgumentCallback callback; protected ArgumentCallback callback;
@ -37,7 +37,7 @@ public class ParsedCommand {
@Nullable @Nullable
public CommandData execute(@NotNull CommandSender source, @NotNull String commandString) { public CommandData execute(@NotNull CommandSender source, @NotNull String commandString) {
// Global listener // Global listener
command.globalListener(source, arguments, commandString); command.globalListener(source, context, commandString);
// Command condition check // Command condition check
final CommandCondition condition = command.getCondition(); final CommandCondition condition = command.getCondition();
if (condition != null) { if (condition != null) {
@ -53,12 +53,12 @@ public class ParsedCommand {
// The executor is from a syntax // The executor is from a syntax
final CommandCondition commandCondition = syntax.getCommandCondition(); final CommandCondition commandCondition = syntax.getCommandCondition();
if (commandCondition == null || commandCondition.canUse(source, commandString)) { if (commandCondition == null || commandCondition.canUse(source, commandString)) {
arguments.retrieveDefaultValues(syntax.getDefaultValuesMap()); context.retrieveDefaultValues(syntax.getDefaultValuesMap());
executor.apply(source, arguments); executor.apply(source, context);
} }
} else { } else {
// The executor is probably the default one // The executor is probably the default one
executor.apply(source, arguments); executor.apply(source, context);
} }
} else if (callback != null && argumentSyntaxException != null) { } else if (callback != null && argumentSyntaxException != null) {
// No syntax has been validated but the faulty argument with a callback has been found // No syntax has been validated but the faulty argument with a callback has been found
@ -66,20 +66,20 @@ public class ParsedCommand {
callback.apply(source, argumentSyntaxException); callback.apply(source, argumentSyntaxException);
} }
if (arguments == null) { if (context == null) {
// Argument callbacks cannot return data // Argument callbacks cannot return data
return null; return null;
} }
return arguments.getReturnData(); return context.getReturnData();
} }
@NotNull @NotNull
public static ParsedCommand withDefaultExecutor(@NotNull Command command) { public static ParsedCommand withDefaultExecutor(@NotNull Command command, @NotNull String input) {
ParsedCommand parsedCommand = new ParsedCommand(); ParsedCommand parsedCommand = new ParsedCommand();
parsedCommand.command = command; parsedCommand.command = command;
parsedCommand.executor = command.getDefaultExecutor(); parsedCommand.executor = command.getDefaultExecutor();
parsedCommand.arguments = new Arguments(); parsedCommand.context = new CommandContext(input);
return parsedCommand; return parsedCommand;
} }

View File

@ -1,6 +1,6 @@
package net.minestom.server.command.builder.arguments; package net.minestom.server.command.builder.arguments;
import net.minestom.server.command.builder.Arguments; import net.minestom.server.command.builder.CommandContext;
import net.minestom.server.command.builder.NodeMaker; import net.minestom.server.command.builder.NodeMaker;
import net.minestom.server.command.builder.exception.ArgumentSyntaxException; import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
import net.minestom.server.command.builder.parser.CommandParser; import net.minestom.server.command.builder.parser.CommandParser;
@ -11,7 +11,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class ArgumentGroup extends Argument<Arguments> { public class ArgumentGroup extends Argument<CommandContext> {
public static final int INVALID_ARGUMENTS_ERROR = 1; public static final int INVALID_ARGUMENTS_ERROR = 1;
@ -24,17 +24,17 @@ public class ArgumentGroup extends Argument<Arguments> {
@NotNull @NotNull
@Override @Override
public Arguments parse(@NotNull String input) throws ArgumentSyntaxException { public CommandContext parse(@NotNull String input) throws ArgumentSyntaxException {
List<ValidSyntaxHolder> validSyntaxes = new ArrayList<>(); List<ValidSyntaxHolder> validSyntaxes = new ArrayList<>();
CommandParser.parse(null, group, input.split(StringUtils.SPACE), validSyntaxes, null); CommandParser.parse(null, group, input.split(StringUtils.SPACE), validSyntaxes, null);
Arguments arguments = new Arguments(); CommandContext context = new CommandContext(input);
CommandParser.findMostCorrectSyntax(validSyntaxes, arguments); CommandParser.findMostCorrectSyntax(validSyntaxes, context);
if (validSyntaxes.isEmpty()) { if (validSyntaxes.isEmpty()) {
throw new ArgumentSyntaxException("Invalid arguments", input, INVALID_ARGUMENTS_ERROR); throw new ArgumentSyntaxException("Invalid arguments", input, INVALID_ARGUMENTS_ERROR);
} }
return arguments; return context;
} }
@Override @Override

View File

@ -3,6 +3,7 @@ package net.minestom.server.command.builder.parser;
import it.unimi.dsi.fastutil.ints.Int2ObjectRBTreeMap; import it.unimi.dsi.fastutil.ints.Int2ObjectRBTreeMap;
import net.minestom.server.command.builder.Arguments; import net.minestom.server.command.builder.Arguments;
import net.minestom.server.command.builder.Command; import net.minestom.server.command.builder.Command;
import net.minestom.server.command.builder.CommandContext;
import net.minestom.server.command.builder.CommandSyntax; import net.minestom.server.command.builder.CommandSyntax;
import net.minestom.server.command.builder.arguments.Argument; import net.minestom.server.command.builder.arguments.Argument;
import net.minestom.server.command.builder.exception.ArgumentSyntaxException; import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
@ -71,12 +72,12 @@ public class CommandParser {
* valid arguments. * valid arguments.
* *
* @param validSyntaxes the list containing all the valid syntaxes * @param validSyntaxes the list containing all the valid syntaxes
* @param executorArgs the recipient of the argument parsed values * @param context the recipient of the argument parsed values
* @return the command syntax with all of its arguments correct and with the most arguments count, null if not any * @return the command syntax with all of its arguments correct and with the most arguments count, null if not any
*/ */
@Nullable @Nullable
public static ValidSyntaxHolder findMostCorrectSyntax(@NotNull List<ValidSyntaxHolder> validSyntaxes, public static ValidSyntaxHolder findMostCorrectSyntax(@NotNull List<ValidSyntaxHolder> validSyntaxes,
@NotNull Arguments executorArgs) { @NotNull CommandContext context) {
if (validSyntaxes.isEmpty()) { if (validSyntaxes.isEmpty()) {
return null; return null;
} }
@ -109,7 +110,7 @@ public class CommandParser {
// Get the arguments values // Get the arguments values
if (finalSyntax != null) { if (finalSyntax != null) {
executorArgs.copy(finalArguments); context.copy(finalArguments);
} }
return finalSyntax; return finalSyntax;

View File

@ -26,7 +26,7 @@ public class TabCompleteListener {
final String text = packet.text; final String text = packet.text;
{ {
String commandString = packet.text.replaceFirst("/", ""); String commandString = packet.text.replaceFirst(CommandManager.COMMAND_PREFIX, "");
String[] split = commandString.split(StringUtils.SPACE); String[] split = commandString.split(StringUtils.SPACE);
String commandName = split[0]; String commandName = split[0];
final CommandDispatcher commandDispatcher = MinecraftServer.getCommandManager().getDispatcher(); final CommandDispatcher commandDispatcher = MinecraftServer.getCommandManager().getDispatcher();
@ -50,7 +50,7 @@ public class TabCompleteListener {
final int inputLength = input.length(); final int inputLength = input.length();
final int commandLength = Arrays.stream(split).map(String::length).reduce(0, Integer::sum) + final int commandLength = Arrays.stream(split).map(String::length).reduce(0, Integer::sum) +
StringUtils.countMatches(args, " "); StringUtils.countMatches(args, StringUtils.SPACE);
final int trailingSpaces = !input.isEmpty() ? text.length() - text.trim().length() : 0; final int trailingSpaces = !input.isEmpty() ? text.length() - text.trim().length() : 0;
final int start = commandLength - inputLength + 1 - trailingSpaces; final int start = commandLength - inputLength + 1 - trailingSpaces;

View File

@ -26,8 +26,8 @@ public class TestCommand extends Command {
var test3 = Integer("msg3"); var test3 = Integer("msg3");
addSyntax((sender, args) -> { addSyntax((sender, context) -> {
System.out.println("COMMAND SYNTAX"); System.out.println("input: "+context.getInput());
}, test3, test1); }, test3, test1);
} }