001package co.aikar.commands; 002 003import com.mojang.brigadier.Command; 004import com.mojang.brigadier.arguments.ArgumentType; 005import com.mojang.brigadier.arguments.BoolArgumentType; 006import com.mojang.brigadier.arguments.DoubleArgumentType; 007import com.mojang.brigadier.arguments.FloatArgumentType; 008import com.mojang.brigadier.arguments.IntegerArgumentType; 009import com.mojang.brigadier.arguments.StringArgumentType; 010import com.mojang.brigadier.builder.LiteralArgumentBuilder; 011import com.mojang.brigadier.builder.RequiredArgumentBuilder; 012import com.mojang.brigadier.suggestion.SuggestionProvider; 013import com.mojang.brigadier.tree.CommandNode; 014import com.mojang.brigadier.tree.LiteralCommandNode; 015 016import java.util.HashMap; 017import java.util.Map; 018import java.util.function.BiPredicate; 019import java.util.function.Predicate; 020 021/** 022 * Handles registering of commands into brigadier 023 * 024 * @param <S> 025 * @author MiniDigger 026 * @deprecated Unstable API 027 */ 028@Deprecated 029@UnstableAPI 030public class ACFBrigadierManager<S> { 031 032 protected final CommandManager<?, ?, ?, ?, ?, ?> manager; 033 034 private final Map<Class<?>, ArgumentType<?>> arguments = new HashMap<>(); 035 036 /** 037 * Constructs a new brigadier manager, utilizing the currently active command manager 038 * 039 * @param manager 040 */ 041 ACFBrigadierManager(CommandManager<?, ?, ?, ?, ?, ?> manager) { 042 manager.verifyUnstableAPI("brigadier"); 043 044 this.manager = manager; 045 046 // TODO support stuff like min max via brigadier? 047 registerArgument(String.class, StringArgumentType.word()); 048 registerArgument(float.class, FloatArgumentType.floatArg()); 049 registerArgument(Float.class, FloatArgumentType.floatArg()); 050 registerArgument(double.class, DoubleArgumentType.doubleArg()); 051 registerArgument(Double.class, DoubleArgumentType.doubleArg()); 052 registerArgument(boolean.class, BoolArgumentType.bool()); 053 registerArgument(Boolean.class, BoolArgumentType.bool()); 054 registerArgument(int.class, IntegerArgumentType.integer()); 055 registerArgument(Integer.class, IntegerArgumentType.integer()); 056 // We use integer for long due to Bungee bug, plus should really be considered same on client 057 registerArgument(long.class, IntegerArgumentType.integer()); 058 registerArgument(Long.class, IntegerArgumentType.integer()); 059 } 060 061 <T> void registerArgument(Class<T> clazz, ArgumentType<?> type) { 062 arguments.put(clazz, type); 063 } 064 065 ArgumentType<Object> getArgumentTypeByClazz(CommandParameter param) { 066 if (param.consumesRest) { 067 //noinspection unchecked 068 return (ArgumentType<Object>) (ArgumentType<?>) StringArgumentType.greedyString(); 069 } 070 //noinspection unchecked 071 return (ArgumentType<Object>) arguments.getOrDefault(param.getType(), StringArgumentType.string()); 072 } 073 074 /** 075 * Registers the given RootCommand into the given brigadir command node, utilizing the provided suggestion provider, executor and permission predicate.<br> 076 * <p> 077 * It recreates the root command node! 078 */ 079 LiteralCommandNode<S> register(RootCommand rootCommand, 080 LiteralCommandNode<S> root, 081 SuggestionProvider<S> suggestionProvider, 082 Command<S> executor, 083 BiPredicate<RootCommand, S> permCheckerRoot, 084 BiPredicate<RegisteredCommand, S> permCheckerSub) { 085 // recreate root to get rid of bukkits default arg 086 LiteralArgumentBuilder<S> rootBuilder = LiteralArgumentBuilder.<S>literal(root.getLiteral()) 087 .requires(sender -> permCheckerRoot.test(rootCommand, sender)); 088 089 RegisteredCommand defaultCommand = rootCommand.getDefaultRegisteredCommand(); 090 if (defaultCommand != null) { 091 if (defaultCommand.requiredResolvers == 0) { 092 rootBuilder.executes(executor); 093 } 094 } 095 096 root = rootBuilder.build(); 097 boolean isForwardingCommand = rootCommand.getDefCommand() instanceof ForwardingCommand; 098 099 if (defaultCommand != null) { 100 registerParameters(defaultCommand, root, suggestionProvider, executor, permCheckerSub); 101 } 102 103 for (Map.Entry<String, RegisteredCommand> subCommand : rootCommand.getSubCommands().entries()) { 104 if ((BaseCommand.isSpecialSubcommand(subCommand.getKey()) && !isForwardingCommand) || (!subCommand.getKey().equals("help") && subCommand.getValue().prefSubCommand.equals("help"))) { 105 // don't register stuff like __catchunknown and don't help command aliases 106 continue; 107 } 108 109 // handle sub sub commands 110 String commandName = subCommand.getKey(); 111 CommandNode<S> currentParent = root; 112 CommandNode<S> subCommandNode; 113 Predicate<S> subPermChecker = sender -> permCheckerSub.test(subCommand.getValue(), sender); 114 if (!isForwardingCommand) { 115 if (commandName.contains(" ")) { 116 String[] split = ACFPatterns.SPACE.split(commandName); 117 for (int i = 0; i < split.length - 1; i++) { 118 if (currentParent.getChild(split[i]) == null) { 119 LiteralCommandNode<S> sub = LiteralArgumentBuilder.<S>literal(split[i]) 120 .requires(subPermChecker).build(); 121 currentParent.addChild(sub); 122 currentParent = sub; 123 } else { 124 currentParent = currentParent.getChild(split[i]); 125 } 126 } 127 commandName = split[split.length - 1]; 128 } 129 130 subCommandNode = currentParent.getChild(commandName); 131 if (subCommandNode == null) { 132 LiteralArgumentBuilder<S> argumentBuilder = LiteralArgumentBuilder.<S>literal(commandName) 133 .requires(subPermChecker); 134 135 // if we have no required params, this command is actually executable 136 if (subCommand.getValue().requiredResolvers == 0) { 137 argumentBuilder.executes(executor); 138 } 139 subCommandNode = argumentBuilder.build(); 140 } 141 } else { 142 subCommandNode = root; 143 } 144 145 registerParameters(subCommand.getValue(), subCommandNode, suggestionProvider, executor, permCheckerSub); 146 147 if (!isForwardingCommand) { 148 currentParent.addChild(subCommandNode); 149 } 150 } 151 152 return root; 153 } 154 155 void registerParameters(RegisteredCommand command, 156 CommandNode<S> node, 157 SuggestionProvider<S> suggestionProvider, 158 Command<S> executor, 159 BiPredicate<RegisteredCommand, S> permChecker) { 160 for (int i = 0; i < command.parameters.length; i++) { 161 CommandParameter param = command.parameters[i]; 162 CommandParameter nextParam = param.getNextParam(); 163 if (param.isCommandIssuer() || (param.canExecuteWithoutInput() && nextParam != null && !nextParam.canExecuteWithoutInput())) { 164 continue; 165 } 166 RequiredArgumentBuilder<S, Object> builder = RequiredArgumentBuilder 167 .<S, Object>argument(param.getName(), getArgumentTypeByClazz(param)) 168 .suggests(suggestionProvider) 169 .requires(sender -> permChecker.test(command, sender)); 170 171 if (nextParam == null || nextParam.canExecuteWithoutInput()) { 172 builder.executes(executor); 173 } 174 175 CommandNode<S> subSubCommand = builder.build(); 176 node.addChild(subSubCommand); 177 node = subSubCommand; 178 } 179 } 180 181}