/** * Attempt to execute a command. This version takes a separate command name (for the root command) * and then a list of following arguments. * * @param cmd command to run * @param args arguments * @param player command source * @param methodArgs method arguments * @throws CommandException */ public void execute(String cmd, String[] args, T player, Object... methodArgs) throws CommandException { String[] newArgs = new String[args.length + 1]; System.arraycopy(args, 0, newArgs, 1, args.length); newArgs[0] = cmd; Object[] newMethodArgs = new Object[methodArgs.length + 1]; System.arraycopy(methodArgs, 0, newMethodArgs, 1, methodArgs.length); executeMethod(null, newArgs, player, newMethodArgs, 0); }
/** * Attempt to execute a command. * * @param parent * @param args * @param player * @param methodArgs * @param level * @throws CommandException */ public void executeMethod(Method parent, String[] args, T player, Object[] methodArgs, int level) throws CommandException { String cmdName = args[level]; Map<String, Method> map = commands.get(parent); Method method = map.get(cmdName.toLowerCase()); if (method == null) { if (parent == null) { // Root throw new UnhandledCommandException(); } else { throw new MissingNestedCommandException( "Unknown command: " + cmdName, getNestedUsage(args, level - 1, parent, player)); } } checkPermission(player, method); int argsCount = args.length - 1 - level; // checks if we need to execute the body of the nested command method (false) // or display the help what commands are available (true) // this is all for an args count of 0 if it is > 0 and a NestedCommand Annotation is present // it will always handle the methods that NestedCommand points to // e.g.: // - /cmd - @NestedCommand(executeBody = true) will go into the else loop and execute code in // that method // - /cmd <arg1> <arg2> - @NestedCommand(executeBody = true) will always go to the nested // command class // - /cmd <arg1> - @NestedCommand(executeBody = false) will always go to the nested command // class not matter the args boolean executeNested = method.isAnnotationPresent(NestedCommand.class) && (argsCount > 0 || !method.getAnnotation(NestedCommand.class).executeBody()); if (executeNested) { if (argsCount == 0) { throw new MissingNestedCommandException( "Sub-command required.", getNestedUsage(args, level, method, player)); } else { executeMethod(method, args, player, methodArgs, level + 1); } } else if (method.isAnnotationPresent(CommandAlias.class)) { CommandAlias aCmd = method.getAnnotation(CommandAlias.class); executeMethod(parent, aCmd.value(), player, methodArgs, level); } else { if (method.isAnnotationPresent(RequireSenderType.class)) { WrappedCommandSender.Type requiredType = method.getAnnotation(RequireSenderType.class).value(); if (!getType(player).equals(requiredType)) { throw new CommandUsageException( "Wrong sender type.", String.format( "You need to be a %s to use this command!", requiredType.name().toLowerCase())); } } Command cmd = method.getAnnotation(Command.class); String[] newArgs = new String[args.length - level]; System.arraycopy(args, level, newArgs, 0, args.length - level); final Set<Character> valueFlags = new HashSet<Character>(); char[] flags = cmd.flags().toCharArray(); Set<Character> newFlags = new HashSet<Character>(); for (int i = 0; i < flags.length; ++i) { if (flags.length > i + 1 && flags[i + 1] == ':') { valueFlags.add(flags[i]); ++i; } newFlags.add(flags[i]); } CommandContext context = new CommandContext(newArgs, valueFlags); if (context.argsLength() < cmd.min()) { throw new CommandUsageException("Too few arguments.", getUsage(args, level, cmd)); } if (cmd.max() != -1 && context.argsLength() > cmd.max()) { throw new CommandUsageException("Too many arguments.", getUsage(args, level, cmd)); } if (!cmd.anyFlags()) { for (char flag : context.getFlags()) { if (!newFlags.contains(flag)) { throw new CommandUsageException("Unknown flag: " + flag, getUsage(args, level, cmd)); } } } methodArgs[0] = context; Object instance = instances.get(method); invokeMethod(parent, args, player, method, instance, methodArgs, argsCount); } }