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;
  }