private String createUsage(Method method) { MCCommand cmd = method.getAnnotation(MCCommand.class); List<String> str = new ArrayList<String>(); String thecmd = cmd.cmds().length > 0 ? cmd.cmds()[0] : ""; String thesubcmd = cmd.subCmds().length > 0 ? cmd.subCmds()[0] : null; Class<?> types[] = method.getParameterTypes(); if (commandIndex == 0) { str.add(thecmd); if (thesubcmd != null) { str.add(thesubcmd); } } for (int i = 1; i < types.length; i++) { Class<?> theclass = types[i]; str.add(getUsageString(theclass)); if (i == commandIndex) { str.add(thecmd); if (thesubcmd != null) { str.add(thesubcmd); } } } return StringUtils.join(str, " "); }
private void addUsage(MethodWrapper method, MCCommand mc) { /// save the usages, for showing help messages if (!mc.usage().isEmpty()) { method.usage = mc.usage(); } else { /// Generate an automatic usage string method.usage = createUsage(method.method); } usage.add(method); }
private String createUsage(Method method) { MCCommand cmd = method.getAnnotation(MCCommand.class); StringBuilder sb = new StringBuilder(cmd.cmds().length > 0 ? cmd.cmds()[0] + " " : ""); int startIndex = 1; if (cmd.subCmds().length > 0) { sb.append(cmd.subCmds()[0] + " "); startIndex = 2; } Class<?> types[] = method.getParameterTypes(); for (int i = startIndex; i < types.length; i++) { Class<?> theclass = types[i]; sb.append(getUsageString(theclass)); } return sb.toString(); }
public void addMethods(Object obj, Method[] methodArray) { for (Method method : methodArray) { MCCommand mc = method.getAnnotation(MCCommand.class); if (mc == null) continue; Class<?> types[] = method.getParameterTypes(); if (types.length == 0 || !validCommandSenderClass(types[0])) { System.err.println("MCCommands must start with a CommandSender,Player, or ArenaPlayer"); continue; } if (mc.cmds().length == 0) { /// There is no subcommand. just the command itself with arguments addMethod(obj, method, mc, DEFAULT_CMD); } else { /// For each of the cmds, store them with the method for (String cmd : mc.cmds()) { addMethod(obj, method, mc, cmd.toLowerCase()); } } } }
public int compare(MethodWrapper mw1, MethodWrapper mw2) { MCCommand cmd1 = mw1.getCommand(); MCCommand cmd2 = mw2.getCommand(); int c = new Float(mw1.getHelpOrder()).compareTo(mw2.getHelpOrder()); if (c != 0) return c; c = new Integer(cmd1.order()).compareTo(cmd2.order()); return c != 0 ? c : new Integer(cmd1.hashCode()).compareTo(cmd2.hashCode()); }
private void addMethod(Object obj, Method method, MCCommand mc, String cmd) { int ml = method.getParameterTypes().length; if (mc.subCmds().length == 0) { TreeMap<Integer, MethodWrapper> mthds = methods.get(cmd); if (mthds == null) { mthds = new TreeMap<Integer, MethodWrapper>(); } int order = (mc.order() != -1 ? mc.order() * 100000 : Integer.MAX_VALUE) - ml * 100 - mthds.size(); MethodWrapper mw = new MethodWrapper(obj, method); mthds.put(order, mw); methods.put(cmd, mthds); addUsage(mw, mc); } else { Map<String, TreeMap<Integer, MethodWrapper>> basemthds = subCmdMethods.get(cmd); if (basemthds == null) { basemthds = new HashMap<String, TreeMap<Integer, MethodWrapper>>(); subCmdMethods.put(cmd, basemthds); } for (String subcmd : mc.subCmds()) { TreeMap<Integer, MethodWrapper> mthds = basemthds.get(subcmd); if (mthds == null) { mthds = new TreeMap<Integer, MethodWrapper>(); basemthds.put(subcmd, mthds); } int order = (mc.order() != -1 ? mc.order() * 100000 : Integer.MAX_VALUE) - ml * 100 - mthds.size(); MethodWrapper mw = new MethodWrapper(obj, method); /// Set help order if (mc.helpOrder() == Integer.MAX_VALUE) { mw.helpOrder = (float) (Integer.MAX_VALUE - usage.size()); } mthds.put(order, mw); addUsage(mw, mc); } } }
public void help(CommandSender sender, Command command, String[] args) { Integer page = 1; if (args != null && args.length > 1) { try { page = Integer.valueOf(args[1]); } catch (Exception e) { sendMessage( sender, ChatColor.RED + " " + args[1] + " is not a number, showing help for page 1."); } } List<String> available = new ArrayList<String>(); List<String> unavailable = new ArrayList<String>(); List<String> onlyop = new ArrayList<String>(); Set<Method> dups = new HashSet<Method>(); for (MethodWrapper mw : usage) { if (!dups.add(mw.method)) continue; MCCommand cmd = mw.getCommand(); final String use = "&6/" + command.getName() + " " + mw.usage; if (cmd.op() && !sender.isOp()) continue; else if (cmd.admin() && !hasAdminPerms(sender)) continue; else if (!cmd.perm().isEmpty() && !sender.hasPermission(cmd.perm())) unavailable.add(use); else available.add(use); } int npages = available.size() + unavailable.size(); if (sender.isOp()) npages += onlyop.size(); npages = (int) Math.ceil((float) npages / LINES_PER_PAGE); if (page > npages || page <= 0) { if (npages <= 0) { sendMessage(sender, "&4There are no methods for this command"); } else { sendMessage(sender, "&4That page doesnt exist, try 1-" + npages); } return; } if (command != null && command.getAliases() != null && !command.getAliases().isEmpty()) { String aliases = StringUtils.join(command.getAliases(), ", "); sendMessage( sender, "&eShowing page &6" + page + "/" + npages + "&6 : /" + command.getName() + " help <page number>"); sendMessage(sender, "&e command &6" + command.getName() + "&e has aliases: &6" + aliases); } else { sendMessage( sender, "&eShowing page &6" + page + "/" + npages + "&6 : /cmd help <page number>"); } int i = 0; for (String use : available) { i++; if (i < (page - 1) * LINES_PER_PAGE || i >= page * LINES_PER_PAGE) continue; sendMessage(sender, use); } for (String use : unavailable) { i++; if (i < (page - 1) * LINES_PER_PAGE || i >= page * LINES_PER_PAGE) continue; sendMessage(sender, ChatColor.RED + "[Insufficient Perms] " + use); } if (sender.isOp()) { for (String use : onlyop) { i++; if (i < (page - 1) * LINES_PER_PAGE || i >= page * LINES_PER_PAGE) continue; sendMessage(sender, ChatColor.AQUA + "[OP only] &6" + use); } } }
protected Arguments verifyArgs( MethodWrapper mwrapper, MCCommand cmd, CommandSender sender, Command command, String label, String[] args, int startIndex) throws IllegalArgumentException { if (DEBUG) { Log.info( " method=" + mwrapper.method.getName() + " verifyArgs " + cmd + " sender=" + sender + ", label=" + label + " args=" + args); for (String arg : args) { Log.info(" -- arg=" + arg); } for (Class<?> t : mwrapper.method.getParameterTypes()) { Log.info(" -- type=" + t); } } final int paramLength = mwrapper.method.getParameterTypes().length; /// Check our permissions if (!cmd.perm().isEmpty() && !sender.hasPermission(cmd.perm()) && !(cmd.admin() && hasAdminPerms(sender))) throw new IllegalArgumentException("You don't have permission to use this command"); /// Verify min number of arguments if (args.length < cmd.min()) { throw new IllegalArgumentException("You need at least " + cmd.min() + " arguments"); } /// Verfiy max number of arguments if (args.length > cmd.max()) { throw new IllegalArgumentException("You need less than " + cmd.max() + " arguments"); } /// Verfiy max number of arguments if (cmd.exact() != -1 && args.length != cmd.exact()) { throw new IllegalArgumentException("You need exactly " + cmd.exact() + " arguments"); } final boolean isPlayer = sender instanceof Player; final boolean isOp = (isPlayer && sender.isOp()) || sender == null || sender instanceof ConsoleCommandSender; if (cmd.op() && !isOp) throw new IllegalArgumentException("You need to be op to use this command"); if (cmd.admin() && !isOp && (isPlayer && !hasAdminPerms(sender))) throw new IllegalArgumentException("You need to be an Admin to use this command"); Class<?> types[] = mwrapper.method.getParameterTypes(); // /// In game check if (types[0] == Player.class && !isPlayer) { throw new IllegalArgumentException(ONLY_INGAME); } int strIndex = startIndex /*skip the label*/, objIndex = 1; Arguments newArgs = new Arguments(); // / Our return value Object[] objs = new Object[paramLength]; // / Our new array of castable arguments newArgs.args = objs; // / Set our return object with the new castable arguments objs[0] = verifySender(sender, types[0]); AtomicBoolean usedString = new AtomicBoolean(); for (int i = 1; i < types.length; i++) { Class<?> clazz = types[i]; usedString.set(false); try { if (CommandSender.class == clazz) { objs[objIndex] = sender; } else if (String[].class == clazz) { objs[objIndex] = args; } else if (Object[].class == clazz) { objs[objIndex] = args; } else { String str = strIndex < args.length ? args[strIndex] : null; objs[objIndex] = verifyArg(clazz, command, str, usedString); if (objs[objIndex] == null) { throw new IllegalArgumentException("Argument " + args[strIndex] + " can not be null"); } } if (DEBUG) Log.info( " " + objIndex + " : " + strIndex + " " + (args.length > strIndex ? args[strIndex] : null) + " <-> " + objs[objIndex] + " !!!!!!!!!!!!!!!!!!!!!!!!!!! Cs = " + clazz.getCanonicalName()); if (usedString.get()) { strIndex++; } } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException("You didnt supply enough arguments for this method"); } objIndex++; } /// Verify alphanumeric if (cmd.alphanum().length > 0) { for (int index : cmd.alphanum()) { if (index >= args.length) throw new IllegalArgumentException("String Index out of range. "); if (!args[index].matches("[a-zA-Z0-9_]*")) { throw new IllegalArgumentException( "argument '" + args[index] + "' can only be alphanumeric with underscores"); } } } return newArgs; /// Success }
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { TreeMap<Integer, MethodWrapper> methodmap = null; /// No method to handle, show some help if ((args.length == 0 && !methods.containsKey(DEFAULT_CMD)) || (args.length > 0 && (args[0].equals("?") || args[0].equals("help")))) { showHelp(sender, command, args); return true; } final int length = args.length; final String cmd = length > 0 ? args[0].toLowerCase() : null; final String subcmd = length > 1 ? args[1].toLowerCase() : null; int startIndex = 0; /// check for subcommands if (subcmd != null && subCmdMethods.containsKey(cmd) && subCmdMethods.get(cmd).containsKey(subcmd)) { methodmap = subCmdMethods.get(cmd).get(subcmd); startIndex = 2; } if (methodmap == null && cmd != null) { // / Find our method, and verify all the annotations methodmap = methods.get(cmd); if (methodmap != null) startIndex = 1; } if (methodmap == null) { // / our last attempt methodmap = methods.get(DEFAULT_CMD); } if (methodmap == null || methodmap.isEmpty()) { return sendMessage( sender, "&cThat command does not exist!&6 /" + command.getLabel() + " help &c for help"); } MCCommand mccmd = null; List<CommandException> errs = null; boolean success = false; for (MethodWrapper mwrapper : methodmap.values()) { mccmd = mwrapper.method.getAnnotation(MCCommand.class); final boolean isOp = sender == null || sender.isOp() || sender instanceof ConsoleCommandSender; if (mccmd.op() && !isOp || mccmd.admin() && !hasAdminPerms(sender)) // / no op, no pass continue; Arguments newArgs = null; try { newArgs = verifyArgs(mwrapper, mccmd, sender, command, label, args, startIndex); Object completed = mwrapper.method.invoke(mwrapper.obj, newArgs.args); if (completed != null && completed instanceof Boolean) { success = (Boolean) completed; if (!success) { String usage = mwrapper.usage; if (usage != null && !usage.isEmpty()) { sendMessage(sender, usage); } } } else { success = true; } break; /// success on one } catch ( IllegalArgumentException e) { // / One of the arguments wasn't correct, store the message if (errs == null) errs = new ArrayList<CommandException>(); errs.add(new CommandException(e, mwrapper)); } catch (Exception e) { // / Just all around bad logInvocationError(e, mwrapper, newArgs); } } /// and handle all errors if (!success && errs != null && !errs.isEmpty()) { HashSet<String> usages = new HashSet<String>(); for (CommandException e : errs) { usages.add( ChatColor.GOLD + command.getLabel() + " " + e.mw.usage + " &c:" + e.err.getMessage()); } for (String msg : usages) { sendMessage(sender, msg); } } return true; }