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 * @author MiniDigger * @deprecated Unstable API */ @Deprecated @UnstableAPI public class ACFBrigadierManager { protected final CommandManager manager; private final Map, 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()); } void registerArgument(Class clazz, ArgumentType type) { arguments.put(clazz, type); } ArgumentType getArgumentTypeByClazz(CommandParameter param) { if (param.consumesRest) { //noinspection unchecked return (ArgumentType) (ArgumentType) StringArgumentType.greedyString(); } //noinspection unchecked return (ArgumentType) 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.
*

* It recreates the root command node! */ LiteralCommandNode register(RootCommand rootCommand, LiteralCommandNode root, SuggestionProvider suggestionProvider, Command executor, BiPredicate permCheckerRoot, BiPredicate permCheckerSub) { // recreate root to get rid of bukkits default arg LiteralArgumentBuilder rootBuilder = LiteralArgumentBuilder.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 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 currentParent = root; CommandNode subCommandNode; Predicate 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 sub = LiteralArgumentBuilder.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 argumentBuilder = LiteralArgumentBuilder.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 node, SuggestionProvider suggestionProvider, Command executor, BiPredicate 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 builder = RequiredArgumentBuilder .argument(param.getName(), getArgumentTypeByClazz(param)) .suggests(suggestionProvider) .requires(sender -> permChecker.test(command, sender)); if (nextParam == null || nextParam.canExecuteWithoutInput()) { builder.executes(executor); } CommandNode subSubCommand = builder.build(); node.addChild(subSubCommand); node = subSubCommand; } } }