@Override
  public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
    String name = cmd.getName();
    if (!commandMap.containsKey(name)) {
      // That command doesn't belong to us
      return true;
    }

    SearchResult result = searchCommand(name, args);
    if (result == null || result.container == null) {
      sender.sendMessage(messageBundle.getMessage("message-unknown-command"));
      return true;
    }

    CommandContainer command = result.container;
    int deepness = result.deepness;

    // Cut the args to be suitable to the sub-command-deepness
    String[] cutArgs = new String[args.length - deepness];
    System.arraycopy(args, deepness, cutArgs, 0, args.length - deepness);

    CommandContext context = new CommandContext(cutArgs, command, sender);
    command.execute(
        context, messageBundle, permissionChecker, this.args.toArray(new Object[this.args.size()]));
    return true;
  }
  @Override
  public List<String> onTabComplete(
      CommandSender sender, Command cmd, String alias, String[] args) {
    String name = cmd.getName();
    if (!commandMap.containsKey(name)) {
      // That command doesn't belong to us
      return null;
    }

    SearchResult result = searchCommand(name, args);
    if (result == null || result.container == null) {
      return null;
    }

    CommandContainer container = result.container;
    int deepness = result.deepness;

    // Cut the args to be suitable to the sub-command-deepness
    String[] cutArgs = new String[args.length - deepness];
    System.arraycopy(args, deepness, cutArgs, 0, args.length - deepness);

    CommandContext context = new CommandContext(cutArgs, container, sender);
    List<String> tabCompletes =
        container.tabComplete(
            context, permissionChecker, this.args.toArray(new Object[this.args.size()]));
    if (tabCompletes == null) {
      tabCompletes = Lists.newArrayList();
    }

    if (args.length > 0 && !args[args.length - 1].isEmpty()) {
      // Remove unrelevant completes
      String lastArgument = args[args.length - 1];

      Iterator<String> iterator = tabCompletes.iterator();
      while (iterator.hasNext()) {
        String complete = iterator.next().toLowerCase();

        if (!complete.startsWith(lastArgument.toLowerCase())) {
          iterator.remove();
        }
      }
    }

    return tabCompletes;
  }
  /**
   * Creates a new server on TCP port 25565 and starts listening for connections.
   *
   * @param args The command-line arguments.
   */
  public static void main(String[] args) {
    try {
      ConfigurationSerialization.registerClass(GlowOfflinePlayer.class);
      GlowPotionEffect.register();

      // parse arguments and read config
      final ServerConfig config = parseArguments(args);
      if (config == null) {
        return;
      }

      // start server
      final GlowServer server = new GlowServer(config);
      server.start();
      server.bind();
      server.bindQuery();
      server.bindRcon();
      logger.info("Ready for connections.");
    } catch (Throwable t) {
      logger.log(Level.SEVERE, "Error during server startup.", t);
      System.exit(1);
    }
  }