mirror of
https://github.com/aikar/commands.git
synced 2026-06-07 09:22:16 +00:00
0f75b89a2e
This fixes issues with optional arguments and Default subcommands
182 lines
7.8 KiB
Java
182 lines
7.8 KiB
Java
package co.aikar.commands;
|
|
|
|
import com.mojang.brigadier.Command;
|
|
import com.mojang.brigadier.arguments.ArgumentType;
|
|
import com.mojang.brigadier.arguments.BoolArgumentType;
|
|
import com.mojang.brigadier.arguments.DoubleArgumentType;
|
|
import com.mojang.brigadier.arguments.FloatArgumentType;
|
|
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
|
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
|
import com.mojang.brigadier.suggestion.SuggestionProvider;
|
|
import com.mojang.brigadier.tree.CommandNode;
|
|
import com.mojang.brigadier.tree.LiteralCommandNode;
|
|
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
import java.util.function.BiPredicate;
|
|
import java.util.function.Predicate;
|
|
|
|
/**
|
|
* Handles registering of commands into brigadier
|
|
*
|
|
* @param <S>
|
|
* @author MiniDigger
|
|
* @deprecated Unstable API
|
|
*/
|
|
@Deprecated
|
|
@UnstableAPI
|
|
public class ACFBrigadierManager<S> {
|
|
|
|
protected final CommandManager<?, ?, ?, ?, ?, ?> manager;
|
|
|
|
private final Map<Class<?>, ArgumentType<?>> arguments = new HashMap<>();
|
|
|
|
/**
|
|
* Constructs a new brigadier manager, utilizing the currently active command manager
|
|
*
|
|
* @param manager
|
|
*/
|
|
ACFBrigadierManager(CommandManager<?, ?, ?, ?, ?, ?> manager) {
|
|
manager.verifyUnstableAPI("brigadier");
|
|
|
|
this.manager = manager;
|
|
|
|
// TODO support stuff like min max via brigadier?
|
|
registerArgument(String.class, StringArgumentType.word());
|
|
registerArgument(float.class, FloatArgumentType.floatArg());
|
|
registerArgument(Float.class, FloatArgumentType.floatArg());
|
|
registerArgument(double.class, DoubleArgumentType.doubleArg());
|
|
registerArgument(Double.class, DoubleArgumentType.doubleArg());
|
|
registerArgument(boolean.class, BoolArgumentType.bool());
|
|
registerArgument(Boolean.class, BoolArgumentType.bool());
|
|
registerArgument(int.class, IntegerArgumentType.integer());
|
|
registerArgument(Integer.class, IntegerArgumentType.integer());
|
|
// We use integer for long due to Bungee bug, plus should really be considered same on client
|
|
registerArgument(long.class, IntegerArgumentType.integer());
|
|
registerArgument(Long.class, IntegerArgumentType.integer());
|
|
}
|
|
|
|
<T> void registerArgument(Class<T> clazz, ArgumentType<?> type) {
|
|
arguments.put(clazz, type);
|
|
}
|
|
|
|
ArgumentType<Object> getArgumentTypeByClazz(CommandParameter param) {
|
|
if (param.consumesRest) {
|
|
//noinspection unchecked
|
|
return (ArgumentType<Object>) (ArgumentType<?>) StringArgumentType.greedyString();
|
|
}
|
|
//noinspection unchecked
|
|
return (ArgumentType<Object>) arguments.getOrDefault(param.getType(), StringArgumentType.string());
|
|
}
|
|
|
|
/**
|
|
* Registers the given RootCommand into the given brigadir command node, utilizing the provided suggestion provider, executor and permission predicate.<br>
|
|
* <p>
|
|
* It recreates the root command node!
|
|
*/
|
|
LiteralCommandNode<S> register(RootCommand rootCommand,
|
|
LiteralCommandNode<S> root,
|
|
SuggestionProvider<S> suggestionProvider,
|
|
Command<S> executor,
|
|
BiPredicate<RootCommand, S> permCheckerRoot,
|
|
BiPredicate<RegisteredCommand, S> permCheckerSub) {
|
|
// recreate root to get rid of bukkits default arg
|
|
LiteralArgumentBuilder<S> rootBuilder = LiteralArgumentBuilder.<S>literal(root.getLiteral())
|
|
.requires(sender -> permCheckerRoot.test(rootCommand, sender));
|
|
|
|
RegisteredCommand defaultCommand = rootCommand.getDefaultRegisteredCommand();
|
|
if (defaultCommand != null) {
|
|
if (defaultCommand.requiredResolvers == 0) {
|
|
rootBuilder.executes(executor);
|
|
}
|
|
}
|
|
|
|
root = rootBuilder.build();
|
|
boolean isForwardingCommand = rootCommand.getDefCommand() instanceof ForwardingCommand;
|
|
|
|
if (defaultCommand != null) {
|
|
registerParameters(defaultCommand, root, suggestionProvider, executor, permCheckerSub);
|
|
}
|
|
|
|
for (Map.Entry<String, RegisteredCommand> subCommand : rootCommand.getSubCommands().entries()) {
|
|
if ((BaseCommand.isSpecialSubcommand(subCommand.getKey()) && !isForwardingCommand) || (!subCommand.getKey().equals("help") && subCommand.getValue().prefSubCommand.equals("help"))) {
|
|
// don't register stuff like __catchunknown and don't help command aliases
|
|
continue;
|
|
}
|
|
|
|
// handle sub sub commands
|
|
String commandName = subCommand.getKey();
|
|
CommandNode<S> currentParent = root;
|
|
CommandNode<S> subCommandNode;
|
|
Predicate<S> subPermChecker = sender -> permCheckerSub.test(subCommand.getValue(), sender);
|
|
if (!isForwardingCommand) {
|
|
if (commandName.contains(" ")) {
|
|
String[] split = ACFPatterns.SPACE.split(commandName);
|
|
for (int i = 0; i < split.length - 1; i++) {
|
|
if (currentParent.getChild(split[i]) == null) {
|
|
LiteralCommandNode<S> sub = LiteralArgumentBuilder.<S>literal(split[i])
|
|
.requires(subPermChecker).build();
|
|
currentParent.addChild(sub);
|
|
currentParent = sub;
|
|
} else {
|
|
currentParent = currentParent.getChild(split[i]);
|
|
}
|
|
}
|
|
commandName = split[split.length - 1];
|
|
}
|
|
|
|
subCommandNode = currentParent.getChild(commandName);
|
|
if (subCommandNode == null) {
|
|
LiteralArgumentBuilder<S> argumentBuilder = LiteralArgumentBuilder.<S>literal(commandName)
|
|
.requires(subPermChecker);
|
|
|
|
// if we have no required params, this command is actually executable
|
|
if (subCommand.getValue().requiredResolvers == 0) {
|
|
argumentBuilder.executes(executor);
|
|
}
|
|
subCommandNode = argumentBuilder.build();
|
|
}
|
|
} else {
|
|
subCommandNode = root;
|
|
}
|
|
|
|
registerParameters(subCommand.getValue(), subCommandNode, suggestionProvider, executor, permCheckerSub);
|
|
|
|
if (!isForwardingCommand) {
|
|
currentParent.addChild(subCommandNode);
|
|
}
|
|
}
|
|
|
|
return root;
|
|
}
|
|
|
|
void registerParameters(RegisteredCommand command,
|
|
CommandNode<S> node,
|
|
SuggestionProvider<S> suggestionProvider,
|
|
Command<S> executor,
|
|
BiPredicate<RegisteredCommand, S> permChecker) {
|
|
for (int i = 0; i < command.parameters.length; i++) {
|
|
CommandParameter param = command.parameters[i];
|
|
CommandParameter nextParam = param.getNextParam();
|
|
if (param.isCommandIssuer() || (param.canExecuteWithoutInput() && nextParam != null && !nextParam.canExecuteWithoutInput())) {
|
|
continue;
|
|
}
|
|
RequiredArgumentBuilder<S, Object> builder = RequiredArgumentBuilder
|
|
.<S, Object>argument(param.getName(), getArgumentTypeByClazz(param))
|
|
.suggests(suggestionProvider)
|
|
.requires(sender -> permChecker.test(command, sender));
|
|
|
|
if (nextParam == null || nextParam.canExecuteWithoutInput()) {
|
|
builder.executes(executor);
|
|
}
|
|
|
|
CommandNode<S> subSubCommand = builder.build();
|
|
node.addChild(subSubCommand);
|
|
node = subSubCommand;
|
|
}
|
|
}
|
|
|
|
}
|