package net.minestom.server.command.builder; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import net.minestom.server.command.CommandSender; import net.minestom.server.command.builder.arguments.Argument; import net.minestom.server.command.builder.arguments.ArgumentLiteral; import net.minestom.server.command.builder.arguments.ArgumentType; import net.minestom.server.command.builder.arguments.ArgumentWord; import net.minestom.server.command.builder.condition.CommandCondition; import net.minestom.server.utils.StringUtils; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.*; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.stream.Stream; /** * Represents a command which has suggestion/auto-completion. *
* The command works using a list of valid syntaxes. * For instance we could build the command * "/health set Notch 50" into multiple argument types "/health [set/add/remove] [username] [integer]" *
* All the default argument types can be found in {@link ArgumentType} * and the syntax be created/registered using {@link #addSyntax(CommandExecutor, Argument[])}. *
* If the command is executed with an incorrect syntax or without any argument, the default {@link CommandExecutor} will be called, * you can set it using {@link #setDefaultExecutor(CommandExecutor)}. *
* Before any syntax to be successfully executed the {@link CommandSender} needs to validated * the {@link CommandCondition} sets with {@link #setCondition(CommandCondition)} (ignored if null). *
* Some {@link Argument} could also require additional condition (eg: a number which need to be between 2 values),
* in this case, if the whole syntax is correct but not the argument condition,
* you can listen to its error code using {@link #setArgumentCallback(ArgumentCallback, Argument)} or {@link Argument#setCallback(ArgumentCallback)}.
*/
public class Command {
public final static Logger LOGGER = LoggerFactory.getLogger(Command.class);
private final String name;
private final String[] aliases;
private final String[] names;
private ArgumentCallback syntaxErrorCallback;
private CommandCondition condition;
private final List
* It is called after the parsing and just before the execution no matter the syntax used and can be used to check permissions or
* the {@link CommandSender} type.
*
* Worth mentioning that the condition is also used to know if the command known from a player (at connection).
*
* @return the command condition, null if not any
*/
@Nullable
public CommandCondition getCondition() {
return condition;
}
/**
* Sets the {@link CommandCondition}.
*
* @param commandCondition the new command condition, null to do not call anything
* @see #getCondition()
*/
public void setCondition(@Nullable CommandCondition commandCondition) {
this.condition = commandCondition;
}
/**
* Sets an {@link ArgumentCallback}.
*
* The argument callback is called when there's an error in the argument.
*
* @param callback the callback for the argument
* @param argument the argument which get the callback
*/
public void setArgumentCallback(@NotNull ArgumentCallback callback, @NotNull Argument> argument) {
argument.setCallback(callback);
}
public void addSubcommand(@NotNull Command command) {
this.subcommands.add(command);
}
@NotNull
public List
* A syntax is simply a list of arguments and an executor called when successfully parsed.
*
* @param commandCondition the condition to use the syntax
* @param executor the executor to call when the syntax is successfully received
* @param args all the arguments of the syntax, the length needs to be higher than 0
* @return the created {@link CommandSyntax syntaxes},
* there can be multiple of them when optional arguments are used
*/
@NotNull
public Collection
* Currently in beta as the format is not final.
*
* @param executor the syntax executor
* @param format the syntax format
* @return the newly created {@link CommandSyntax syntaxes}.
*/
@ApiStatus.Experimental
public @NotNull Collection
* Include {@link #getName()} and {@link #getAliases()}.
*
* @return this command names
*/
public @NotNull String[] getNames() {
return names;
}
public ArgumentCallback syntaxErrorCallback() {
return syntaxErrorCallback;
}
public void setSyntaxErrorCallback(ArgumentCallback syntaxErrorCallback) {
this.syntaxErrorCallback = syntaxErrorCallback;
}
/**
* This was an ambiguous method which is no longer supported by the new parser.
* WARNING: the {@link CommandCondition} is not executed, and all the {@link CommandSyntax} are not checked,
* this is called every time a {@link CommandSender} send a command which start by {@link #getName()} or {@link #getAliases()}.
*
* 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 context the UNCHECKED context of the command, some can be null even when unexpected
* @param command the raw UNCHECKED received command
*/
public void globalListener(@NotNull CommandSender sender, @NotNull CommandContext context, @NotNull String command) {
}
@ApiStatus.Experimental
public @NotNull Set
* Updating: If you were using this method to set
* - an executor for a command without arguments you should
* use {@link #addSyntax(CommandExecutor, Argument[])} without arguments
* - a syntax error handler you should use the new {@link #setSyntaxErrorCallback(ArgumentCallback)}
*/
@Deprecated(forRemoval = true)
public void setDefaultExecutor(@Nullable CommandExecutor executor) {
throw new RuntimeException("Unsupported operation! See method javadoc.");
}
/**
* Gets all the syntaxes of this command.
*
* @return a collection containing all this command syntaxes
* @see #addSyntax(CommandExecutor, Argument[])
*/
public @NotNull Collection> arguments = new ArrayList<>();
}
}