mirror of
https://github.com/Minestom/Minestom.git
synced 2025-03-02 11:21:15 +01:00
Added support for command syntaxes with optional arguments (default values)
This commit is contained in:
parent
2ec727d5f8
commit
4bf120b714
@ -14,6 +14,7 @@ import net.minestom.server.utils.math.FloatRange;
|
||||
import net.minestom.server.utils.math.IntRange;
|
||||
import net.minestom.server.utils.time.UpdateOption;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBT;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
|
||||
@ -164,4 +165,15 @@ public final class Arguments {
|
||||
this.args.clear();
|
||||
}
|
||||
|
||||
protected void retrieveDefaultValues(@Nullable Map<String, Object> defaultValuesMap) {
|
||||
if (defaultValuesMap == null)
|
||||
return;
|
||||
|
||||
for (Map.Entry<String, Object> entry : defaultValuesMap.entrySet()) {
|
||||
final String key = entry.getKey();
|
||||
if (!args.containsKey(key))
|
||||
this.args.put(key, entry.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -10,10 +10,10 @@ import net.minestom.server.command.builder.condition.CommandCondition;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Represents a command which has suggestion/auto-completion.
|
||||
@ -37,6 +37,8 @@ import java.util.List;
|
||||
*/
|
||||
public class Command {
|
||||
|
||||
public final static Logger LOGGER = LoggerFactory.getLogger(Command.class);
|
||||
|
||||
private final String name;
|
||||
private final String[] aliases;
|
||||
|
||||
@ -114,27 +116,83 @@ public class Command {
|
||||
* @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}
|
||||
* @return the created {@link CommandSyntax syntaxes},
|
||||
* there can be multiple of them when optional arguments are used
|
||||
*/
|
||||
public CommandSyntax addSyntax(@Nullable CommandCondition commandCondition,
|
||||
@NotNull CommandExecutor executor,
|
||||
@NotNull Argument<?>... args) {
|
||||
@NotNull
|
||||
public Collection<CommandSyntax> addSyntax(@Nullable CommandCondition commandCondition,
|
||||
@NotNull CommandExecutor executor,
|
||||
@NotNull Argument<?>... args) {
|
||||
Check.argCondition(args.length == 0,
|
||||
"The syntax argument cannot be empty, consider using Command#setDefaultExecutor");
|
||||
final CommandSyntax syntax = new CommandSyntax(commandCondition, executor, args);
|
||||
this.syntaxes.add(syntax);
|
||||
return syntax;
|
||||
|
||||
// Check optional argument(s)
|
||||
boolean hasOptional = false;
|
||||
{
|
||||
for (Argument<?> argument : args) {
|
||||
if (argument.isOptional()) {
|
||||
hasOptional = true;
|
||||
}
|
||||
if (hasOptional && !argument.isOptional()) {
|
||||
LOGGER.warn("Optional arguments are followed by a non-optional one, the default values will be ignored.");
|
||||
hasOptional = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasOptional) {
|
||||
final CommandSyntax syntax = new CommandSyntax(commandCondition, executor, args);
|
||||
this.syntaxes.add(syntax);
|
||||
return Collections.singleton(syntax);
|
||||
} else {
|
||||
List<CommandSyntax> optionalSyntaxes = new ArrayList<>();
|
||||
|
||||
// the 'args' array starts by all the required arguments, followed by the optional ones
|
||||
List<Argument<?>> requiredArguments = new ArrayList<>();
|
||||
Map<String, Object> defaultValuesMap = new HashMap<>();
|
||||
boolean optionalBranch = false;
|
||||
int i = 0;
|
||||
for (Argument<?> argument : args) {
|
||||
final boolean isLast = ++i == args.length;
|
||||
if (argument.isOptional()) {
|
||||
// Set default value
|
||||
defaultValuesMap.put(argument.getId(), argument.getDefaultValue());
|
||||
|
||||
if (!optionalBranch && !requiredArguments.isEmpty()) {
|
||||
// First optional argument, create a syntax with current cached arguments
|
||||
final CommandSyntax syntax = new CommandSyntax(commandCondition, executor, defaultValuesMap,
|
||||
requiredArguments.toArray(new Argument[0]));
|
||||
optionalSyntaxes.add(syntax);
|
||||
optionalBranch = true;
|
||||
} else {
|
||||
// New optional argument, save syntax with current cached arguments and save default value
|
||||
final CommandSyntax syntax = new CommandSyntax(commandCondition, executor, defaultValuesMap,
|
||||
requiredArguments.toArray(new Argument[0]));
|
||||
optionalSyntaxes.add(syntax);
|
||||
}
|
||||
}
|
||||
requiredArguments.add(argument);
|
||||
if (isLast) {
|
||||
// Create the last syntax
|
||||
final CommandSyntax syntax = new CommandSyntax(commandCondition, executor, defaultValuesMap,
|
||||
requiredArguments.toArray(new Argument[0]));
|
||||
optionalSyntaxes.add(syntax);
|
||||
}
|
||||
}
|
||||
|
||||
this.syntaxes.addAll(optionalSyntaxes);
|
||||
return optionalSyntaxes;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new syntax in the command without any condition.
|
||||
* Adds a new syntax without condition.
|
||||
*
|
||||
* @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}
|
||||
* @see #addSyntax(CommandCondition, CommandExecutor, Argument[])
|
||||
*/
|
||||
public CommandSyntax addSyntax(@NotNull CommandExecutor executor, @NotNull Argument<?>... args) {
|
||||
@NotNull
|
||||
public Collection<CommandSyntax> addSyntax(@NotNull CommandExecutor executor, @NotNull Argument<?>... args) {
|
||||
return addSyntax(null, executor, args);
|
||||
}
|
||||
|
||||
|
@ -144,8 +144,8 @@ public class CommandDispatcher {
|
||||
|
||||
boolean useRemaining = false;
|
||||
// Check the validity of the arguments...
|
||||
for (int argCount = 0; argCount < syntax.getArguments().length; argCount++) {
|
||||
final Argument<?> argument = syntax.getArguments()[argCount];
|
||||
for (int argCount = 0; argCount < arguments.length; argCount++) {
|
||||
final Argument<?> argument = arguments[argCount];
|
||||
useRemaining = argument.useRemaining();
|
||||
|
||||
// the correction result of the argument
|
||||
@ -399,6 +399,7 @@ public class CommandDispatcher {
|
||||
// The executor is from a syntax
|
||||
final CommandCondition commandCondition = syntax.getCommandCondition();
|
||||
if (commandCondition == null || commandCondition.canUse(source, commandString)) {
|
||||
arguments.retrieveDefaultValues(syntax.getDefaultValuesMap());
|
||||
executor.apply(source, arguments);
|
||||
}
|
||||
} else {
|
||||
|
@ -6,6 +6,8 @@ import net.minestom.server.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents a syntax in {@link Command}
|
||||
* which is initialized with {@link Command#addSyntax(CommandExecutor, Argument[])}.
|
||||
@ -14,16 +16,27 @@ public class CommandSyntax {
|
||||
|
||||
private CommandCondition commandCondition;
|
||||
private CommandExecutor executor;
|
||||
|
||||
private final Map<String, Object> defaultValuesMap;
|
||||
private final Argument<?>[] args;
|
||||
|
||||
protected CommandSyntax(@Nullable CommandCondition commandCondition,
|
||||
@NotNull CommandExecutor commandExecutor,
|
||||
@Nullable Map<String, Object> defaultValuesMap,
|
||||
@NotNull Argument<?>... args) {
|
||||
this.commandCondition = commandCondition;
|
||||
this.executor = commandExecutor;
|
||||
|
||||
this.defaultValuesMap = defaultValuesMap;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
protected CommandSyntax(@Nullable CommandCondition commandCondition,
|
||||
@NotNull CommandExecutor commandExecutor,
|
||||
@NotNull Argument<?>... args) {
|
||||
this(commandCondition, commandExecutor, null, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the condition to use this syntax.
|
||||
*
|
||||
@ -66,6 +79,11 @@ public class CommandSyntax {
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected Map<String, Object> getDefaultValuesMap() {
|
||||
return defaultValuesMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the required {@link Argument} for this syntax.
|
||||
*
|
||||
|
@ -3,6 +3,7 @@ package net.minestom.server.command.builder.arguments;
|
||||
import net.minestom.server.command.builder.ArgumentCallback;
|
||||
import net.minestom.server.command.builder.Command;
|
||||
import net.minestom.server.command.builder.CommandExecutor;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@ -29,6 +30,8 @@ public abstract class Argument<T> {
|
||||
|
||||
private ArgumentCallback callback;
|
||||
|
||||
private T defaultValue;
|
||||
|
||||
/**
|
||||
* Creates a new argument.
|
||||
*
|
||||
@ -146,6 +149,23 @@ public abstract class Argument<T> {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
public boolean isOptional() {
|
||||
return defaultValue != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Argument<T> setDefaultValue(@Nullable T defaultValue) {
|
||||
Check.argCondition(defaultValue != null && getConditionResult(defaultValue) != SUCCESS,
|
||||
"The default value needs to validate the argument condition!");
|
||||
this.defaultValue = defaultValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if the argument has any error callback.
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user