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 root = rootBuilder.build(); 090 boolean isForwardingCommand = rootCommand.getDefCommand() instanceof ForwardingCommand; 091 092 for (Map.Entry<String, RegisteredCommand> subCommand : rootCommand.getSubCommands().entries()) { 093 if ((BaseCommand.isSpecialSubcommand(subCommand.getKey()) && !isForwardingCommand) || (!subCommand.getKey().equals("help") && subCommand.getValue().prefSubCommand.equals("help"))) { 094 // don't register stuff like __catchunknown and don't help command aliases 095 continue; 096 } 097 098 // handle sub sub commands 099 String commandName = subCommand.getKey(); 100 CommandNode<S> currentParent = root; 101 CommandNode<S> subCommandNode; 102 Predicate<S> subPermChecker = sender -> permCheckerSub.test(subCommand.getValue(), sender); 103 if (!isForwardingCommand) { 104 if (commandName.contains(" ")) { 105 String[] split = ACFPatterns.SPACE.split(commandName); 106 for (int i = 0; i < split.length - 1; i++) { 107 if (currentParent.getChild(split[i]) == null) { 108 LiteralCommandNode<S> sub = LiteralArgumentBuilder.<S>literal(split[i]) 109 .requires(subPermChecker).build(); 110 currentParent.addChild(sub); 111 currentParent = sub; 112 } else { 113 currentParent = currentParent.getChild(split[i]); 114 } 115 } 116 commandName = split[split.length - 1]; 117 } 118 119 subCommandNode = currentParent.getChild(commandName); 120 if (subCommandNode == null) { 121 LiteralArgumentBuilder<S> argumentBuilder = LiteralArgumentBuilder.<S>literal(commandName) 122 .requires(subPermChecker); 123 124 // if we have no params, this command is actually executable 125 if (subCommand.getValue().consumeInputResolvers == 0) { 126 argumentBuilder.executes(executor); 127 } 128 subCommandNode = argumentBuilder.build(); 129 } 130 } else { 131 subCommandNode = root; 132 } 133 134 CommandNode<S> paramNode = subCommandNode; 135 CommandParameter[] parameters = subCommand.getValue().parameters; 136 for (int i = 0; i < parameters.length; i++) { 137 CommandParameter param = parameters[i]; 138 CommandParameter nextParam = param.getNextParam(); 139 if (param.isCommandIssuer() || (param.canExecuteWithoutInput() && nextParam != null && !nextParam.canExecuteWithoutInput())) { 140 continue; 141 } 142 RequiredArgumentBuilder<S, Object> builder = RequiredArgumentBuilder 143 .<S, Object>argument(param.getName(), getArgumentTypeByClazz(param)) 144 .suggests(suggestionProvider) 145 .requires(sender -> permCheckerSub.test(subCommand.getValue(), sender)); 146 147 if (nextParam != null && nextParam.canExecuteWithoutInput()) { 148 builder.executes(executor); 149 } 150 151 CommandNode<S> subSubCommand = builder.build(); 152 paramNode.addChild(subSubCommand); 153 paramNode = subSubCommand; 154 } 155 156 if (!isForwardingCommand) { 157 currentParent.addChild(subCommandNode); 158 } 159 } 160 161 return root; 162 } 163 164}