예제 #1
0
public class RegularBot implements EventListener {
  private final RegularBotControlsUI ui;
  private final ExecutorService service = Executors.newCachedThreadPool();
  private final RegularBotData data;
  private final List<Command> commands;
  private MinecraftBot bot;

  private int loadingState = 0;

  public RegularBot(RegularBotControlsUI ui, RegularBotData data) {
    this.ui = ui;
    data.lock();
    this.data = data;
    commands = new ArrayList<Command>();
    commands.addAll(Arrays.asList((Command[]) DefaultCommands.values()));
    status("Waiting.");
    progress(0, false);
    connect();
  }

  public void connect() {
    service.execute(
        new Runnable() {
          @Override
          public void run() {
            MinecraftBotData.Builder builder = MinecraftBotData.builder();
            builder.username(data.username).password(data.password);

            String server = data.server;
            int port = 25565;
            if (server.contains(":")) {
              String[] parts = server.split(":");
              server = parts[0];
              port = Integer.parseInt(parts[1]);
            }
            builder.server(server).port(port);

            if (data.proxy != null) {
              String proxy = data.proxy;
              int proxyPort;
              ProxyType type = null;
              if (proxy.contains(":")) {
                String[] parts = proxy.split(":");
                proxy = parts[0];
                proxyPort = Integer.parseInt(parts[1]);
                if (parts.length > 2) {
                  try {
                    type = ProxyType.values()[Integer.parseInt(parts[2])];
                  } catch (NumberFormatException exception) {
                    type = ProxyType.valueOf(parts[2].toUpperCase());
                  }
                }
              } else throw new IllegalArgumentException("Invalid proxy");
              ProxyData data =
                  new ProxyData(proxy, proxyPort, type == null ? ProxyType.SOCKS : type);
              builder.socksProxy(data);
            }
            MinecraftBotData botData = builder.build();

            clearLog();
            log("[BOT] Connecting...");
            status("Connecting...");
            progress(true);
            try {
              bot = new MinecraftBot(GUIBotWrapper.getInstance().getDarkBot(), botData);
            } catch (Exception exception) {
              exception.printStackTrace();

              Throwable cause = exception.getCause();
              if (cause != null && cause instanceof AuthenticationException) {
                log("[BOT] Error: Invalid login (" + cause.getMessage() + ")");
              } else {
                log("[BOT] Error: Unable to connect (" + exception.toString() + ")");
              }
              status("Waiting.");
              progress(false);
              return;
            }
            progress(20, false);
            status("Logging in...");
            bot.getEventManager().registerListener(RegularBot.this);
            TaskManager taskManager = bot.getTaskManager();
            for (Class<? extends Task> task : data.tasks) {
              try {
                Constructor<? extends Task> constructor = task.getConstructor(MinecraftBot.class);
                taskManager.registerTask(constructor.newInstance(bot));
              } catch (Exception exception) {
              }
            }
          }
        });
  }

  public void disconnect() {
    if (bot != null) {
      System.out.println("Disconnected");
      bot.getConnectionHandler().disconnect("");
      bot.getEventManager().unregisterListener(this);
      bot = null;
      loadingState = 0;
      status("Waiting.");
      progress(0, false);
    }
  }

  @EventHandler
  public void onDisconnect(DisconnectEvent event) {
    String reason = event.getReason();
    log("[BOT] Disconnected" + (reason != null && reason.length() > 0 ? ": " + reason : "") + ".");
  }

  @EventHandler
  public void onChatReceived(ChatReceivedEvent event) {
    log("[CHAT] " + event.getMessage());
  }

  @EventHandler
  public void onLogin(LoginEvent event) {
    status("Loading...");
    progress(40);
    loadingState = 1;
  }

  @EventHandler
  public void onTeleport(TeleportEvent event) {
    if (loadingState == 1) {
      progress(60);
      loadingState = 2;
    }
  }

  @EventHandler
  public void onWindowUpdate(WindowUpdateEvent event) {
    if (loadingState == 2 && event.getWindowId() == 0) {
      loadingState = 3;
      progress(80);
    }
  }

  @EventHandler
  public void onHealthUpdate(HealthUpdateEvent event) {
    ui.updateStatus();
    if (loadingState == 3) {
      loadingState = 4;
      status("Connected.");
      progress(100);
    }
    if (event.getHealth() <= 0) bot.getEventManager().sendEvent(new RequestRespawnEvent());
  }

  public void clearLog() {
    ui.clearLog();
  }

  public void log(String text) {
    ui.log(text);
  }

  public void status(String status) {
    ui.setStatus(status);
  }

  public void progress(int percentage) {
    ui.setProgress(percentage);
  }

  public void progress(boolean indeterminate) {
    ui.setProgress(indeterminate);
  }

  public void progress(int percentage, boolean indeterminate) {
    ui.setProgress(percentage, indeterminate);
  }

  public void executeCommand(String commandText) {
    String[] parts = commandText.split(" ");
    String commandName = parts[0];
    String[] args = new String[parts.length - 1];
    for (int i = 1; i < parts.length; i++) args[i - 1] = parts[i];

    Command targetCommand = null;
    synchronized (commands) {
      for (Command command : commands)
        if (commandName.equalsIgnoreCase(command.getName())) targetCommand = command;
    }

    if (targetCommand == null) log("[BOT] Unknown command.");
    else if (!targetCommand.execute(this, args)) log("[BOT] Invalid command usage.");
  }

  public MinecraftBot getBot() {
    return bot;
  }

  public RegularBotData getData() {
    return data;
  }

  public List<Command> getCommands() {
    synchronized (commands) {
      return Collections.unmodifiableList(commands);
    }
  }

  public static class RegularBotData {
    private String username, password, server, proxy;
    private List<Class<? extends Task>> tasks;

    private boolean locked = false;

    public String getUsername() {
      return username;
    }

    public String getPassword() {
      return password;
    }

    public String getServer() {
      return server;
    }

    public String getProxy() {
      return proxy;
    }

    public List<Class<? extends Task>> getTasks() {
      return tasks;
    }

    public synchronized void setUsername(String username) {
      if (locked) throw new UnsupportedOperationException();
      this.username = username;
    }

    public synchronized void setPassword(String password) {
      if (locked) throw new UnsupportedOperationException();
      this.password = password;
    }

    public synchronized void setServer(String server) {
      if (locked) throw new UnsupportedOperationException();
      this.server = server;
    }

    public synchronized void setProxy(String proxy) {
      if (locked) throw new UnsupportedOperationException();
      this.proxy = proxy;
    }

    public synchronized void setTasks(List<Class<? extends Task>> tasks) {
      if (locked) throw new UnsupportedOperationException();
      if (tasks == null) throw new NullPointerException();
      this.tasks = Collections.unmodifiableList(tasks);
    }

    private synchronized void lock() {
      locked = true;
    }
  }
}
예제 #2
0
  public static void main(String[] args) {
    // TODO main
    OptionParser parser = new OptionParser();
    parser.acceptsAll(Arrays.asList("h", "help"), "Show this help dialog.");
    OptionSpec<String> serverOption =
        parser
            .acceptsAll(Arrays.asList("s", "server"), "Server to join.")
            .withRequiredArg()
            .describedAs("server-address[:port]");
    OptionSpec<String> proxyOption =
        parser
            .acceptsAll(
                Arrays.asList("P", "proxy"),
                "SOCKS proxy to use. Ignored in presence of 'socks-proxy-list'.")
            .withRequiredArg()
            .describedAs("proxy-address");
    OptionSpec<String> ownerOption =
        parser
            .acceptsAll(
                Arrays.asList("o", "owner"), "Owner of the bot (username of in-game control).")
            .withRequiredArg()
            .describedAs("username");
    OptionSpec<?> offlineOption =
        parser.acceptsAll(
            Arrays.asList("O", "offline"),
            "Offline-mode. Ignores 'password' and 'account-list' (will "
                + "generate random usernames if 'username' is not supplied).");
    OptionSpec<?> autoRejoinOption =
        parser.acceptsAll(Arrays.asList("a", "auto-rejoin"), "Auto-rejoin a server on disconnect.");
    OptionSpec<Integer> loginDelayOption =
        parser
            .acceptsAll(
                Arrays.asList("d", "login-delay"),
                "Delay between bot joins, in milliseconds. 5000 is "
                    + "recommended if not using socks proxies.")
            .withRequiredArg()
            .describedAs("delay")
            .ofType(Integer.class);
    OptionSpec<Integer> botAmountOption =
        parser
            .acceptsAll(
                Arrays.asList("b", "bot-amount"),
                "Amount of bots to join. Must be <= amount of accounts.")
            .withRequiredArg()
            .describedAs("amount")
            .ofType(Integer.class);

    OptionSpec<String> accountListOption =
        parser
            .accepts(
                "account-list",
                "File containing a list of accounts, in username/email:password format.")
            .withRequiredArg()
            .describedAs("file");
    OptionSpec<String> socksProxyListOption =
        parser
            .accepts(
                "socks-proxy-list",
                "File containing a list of SOCKS proxies, in address:port format.")
            .withRequiredArg()
            .describedAs("file");
    OptionSpec<String> httpProxyListOption =
        parser
            .accepts(
                "http-proxy-list",
                "File containing a list of HTTP proxies, in address:port format.")
            .withRequiredArg()
            .describedAs("file");

    OptionSet options;
    try {
      options = parser.parse(args);
    } catch (OptionException exception) {
      try {
        parser.printHelpOn(System.out);
      } catch (Exception exception1) {
        exception1.printStackTrace();
      }
      return;
    }

    if (options.has("help")) {
      printHelp(parser);
      return;
    }

    final boolean offline = options.has(offlineOption);
    final boolean autoRejoin = options.has(autoRejoinOption);

    final List<String> accounts;
    if (options.has(accountListOption)) {
      accounts = loadAccounts(options.valueOf(accountListOption));
    } else if (!offline) {
      System.out.println("Option 'accounts' must be supplied in " + "absence of option 'offline'.");
      printHelp(parser);
      return;
    } else accounts = null;

    final String server;
    if (!options.has(serverOption)) {
      System.out.println("Option 'server' required.");
      printHelp(parser);
      return;
    } else server = options.valueOf(serverOption);

    final String owner;
    if (!options.has(ownerOption)) {
      System.out.println("Option 'owner' required.");
      printHelp(parser);
      return;
    } else owner = options.valueOf(ownerOption);

    final List<String> socksProxies;
    if (options.has(socksProxyListOption))
      socksProxies = loadProxies(options.valueOf(socksProxyListOption));
    else socksProxies = null;
    final boolean useProxy = socksProxies != null;

    final List<String> httpProxies;
    if (options.has(httpProxyListOption))
      httpProxies = loadLoginProxies(options.valueOf(httpProxyListOption));
    else if (!offline && accounts != null) {
      System.out.println(
          "Option 'http-proxy-list' required if " + "option 'account-list' is supplied.");
      printHelp(parser);
      return;
    } else httpProxies = null;

    final int loginDelay;
    if (options.has(loginDelayOption)) loginDelay = options.valueOf(loginDelayOption);
    else loginDelay = 0;

    final int botAmount;
    if (!options.has(botAmountOption)) {
      System.out.println("Option 'bot-amount' required.");
      printHelp(parser);
      return;
    } else botAmount = options.valueOf(botAmountOption);

    initGui();
    while (!sessions.get()) {
      synchronized (sessions) {
        try {
          sessions.wait(5000);
        } catch (InterruptedException exception) {
        }
      }
    }

    final Queue<Runnable> lockQueue = new ArrayDeque<Runnable>();

    ExecutorService service = Executors.newFixedThreadPool(botAmount + (loginDelay > 0 ? 1 : 0));
    final Object firstWait = new Object();
    if (loginDelay > 0) {
      service.execute(
          new Runnable() {
            @Override
            public void run() {
              synchronized (firstWait) {
                try {
                  firstWait.wait();
                } catch (InterruptedException exception) {
                }
              }
              while (true) {
                if (die) return;
                while (slotsTaken.get() >= 2) {
                  synchronized (slotsTaken) {
                    try {
                      slotsTaken.wait(500);
                    } catch (InterruptedException exception) {
                    }
                  }
                }
                synchronized (lockQueue) {
                  if (lockQueue.size() > 0) {
                    Runnable thread = lockQueue.poll();
                    synchronized (thread) {
                      thread.notifyAll();
                    }
                    lockQueue.offer(thread);
                  } else continue;
                }
                try {
                  Thread.sleep(loginDelay);
                } catch (InterruptedException exception) {
                }
                while (!sessions.get()) {
                  synchronized (sessions) {
                    try {
                      sessions.wait(5000);
                    } catch (InterruptedException exception) {
                    }
                  }
                }
              }
            }
          });
    }
    final List<String> accountsInUse = new ArrayList<String>();
    for (int i = 0; i < botAmount; i++) {
      final int botNumber = i;
      Runnable runnable =
          new Runnable() {
            @Override
            public void run() {
              if (loginDelay > 0)
                synchronized (lockQueue) {
                  lockQueue.add(this);
                }
              Random random = new Random();

              if (!offline) {
                boolean authenticated = false;
                user:
                while (true) {
                  if (authenticated) {
                    authenticated = false;
                    sessionCount.decrementAndGet();
                  }
                  Session session = null;
                  String loginProxy;
                  String account = accounts.get(random.nextInt(accounts.size()));
                  synchronized (accountsInUse) {
                    if (accountsInUse.size() == accounts.size()) System.exit(0);
                    while (accountsInUse.contains(account))
                      account = accounts.get(random.nextInt(accounts.size()));
                    accountsInUse.add(account);
                  }
                  String[] accountParts = account.split(":");
                  while (true) {
                    while (!sessions.get()) {
                      synchronized (sessions) {
                        try {
                          sessions.wait(5000);
                        } catch (InterruptedException exception) {
                        }
                      }
                    }
                    loginProxy = httpProxies.get(random.nextInt(httpProxies.size()));
                    try {
                      session = Util.retrieveSession(accountParts[0], accountParts[1], loginProxy);
                      // addAccount(session);
                      sessionCount.incrementAndGet();
                      authenticated = true;
                      break;
                    } catch (AuthenticationException exception) {
                      System.err.println("[Bot" + botNumber + "] " + exception);
                      if (!exception.getMessage().startsWith("Exception"))
                        // && !exception.getMessage().equals(
                        // "Too many failed logins"))
                        continue user;
                    }
                  }
                  System.out.println(
                      "["
                          + session.getUsername()
                          + "] Password: "******", Session ID: "
                          + session.getSessionId());
                  while (!joins.get()) {
                    synchronized (joins) {
                      try {
                        joins.wait(5000);
                      } catch (InterruptedException exception) {
                      }
                    }
                  }
                  if (loginDelay > 0) {
                    synchronized (this) {
                      try {
                        synchronized (firstWait) {
                          firstWait.notifyAll();
                        }
                        wait();
                      } catch (InterruptedException exception) {
                      }
                    }
                  }

                  while (true) {
                    String proxy =
                        useProxy ? socksProxies.get(random.nextInt(socksProxies.size())) : null;
                    try {
                      new DarkBotMCSpambot(
                          DARK_BOT,
                          server,
                          session.getUsername(),
                          session.getPassword(),
                          session.getSessionId(),
                          null,
                          proxy,
                          owner);
                      if (die) break user;
                      else if (!autoRejoin) break;
                    } catch (Exception exception) {
                      exception.printStackTrace();
                      System.out.println(
                          "["
                              + session.getUsername()
                              + "] Error connecting: "
                              + exception.getCause().toString());
                    }
                  }
                  System.out.println("[" + session.getUsername() + "] Account failed");
                }
              } else {
                while (true) {
                  String proxy =
                      useProxy ? socksProxies.get(random.nextInt(socksProxies.size())) : null;
                  try {
                    String username = "";
                    if (accounts != null) {
                      username = accounts.get(random.nextInt(accounts.size())).split(":")[0];
                      synchronized (accountsInUse) {
                        while (accountsInUse.contains(username))
                          username = accounts.get(random.nextInt(accounts.size()));
                        accountsInUse.add(username);
                      }
                    } else
                      for (int i = 0; i < 10 + random.nextInt(6); i++)
                        username += alphas[random.nextInt(alphas.length)];
                    if (loginDelay > 0) {
                      synchronized (this) {
                        try {
                          synchronized (firstWait) {
                            firstWait.notifyAll();
                          }
                          wait();
                        } catch (InterruptedException exception) {
                        }
                      }
                    }
                    new DarkBotMCSpambot(DARK_BOT, server, username, "", "", null, proxy, owner);
                    if (die || !autoRejoin) break;
                    else continue;
                  } catch (Exception exception) {
                    System.out.println(
                        "[Bot" + botNumber + "] Error connecting: " + exception.toString());
                  }
                }
              }
            }
          };
      service.execute(runnable);
    }
    service.shutdown();
    while (!service.isTerminated()) {
      try {
        service.awaitTermination(9000, TimeUnit.DAYS);
      } catch (InterruptedException exception) {
        exception.printStackTrace();
      }
    }
    System.exit(0);
  }
예제 #3
0
  public static void main(String[] args) {
    // TODO main
    OptionParser parser = new OptionParser();
    parser.acceptsAll(Arrays.asList("h", "help"), "Show this help dialog.");
    OptionSpec<String> serverOption =
        parser
            .acceptsAll(Arrays.asList("s", "server"), "Server to join.")
            .withRequiredArg()
            .describedAs("server-address[:port]");
    OptionSpec<String> proxyOption =
        parser
            .acceptsAll(
                Arrays.asList("P", "proxy"),
                "SOCKS proxy to use. Ignored in presence of 'socks-proxy-list'.")
            .withRequiredArg()
            .describedAs("proxy-address");
    OptionSpec<String> ownerOption =
        parser
            .acceptsAll(
                Arrays.asList("o", "owner"), "Owner of the bot (username of in-game control).")
            .withRequiredArg()
            .describedAs("username");
    OptionSpec<?> offlineOption =
        parser.acceptsAll(
            Arrays.asList("O", "offline"),
            "Offline-mode. Ignores 'password' and 'account-list' (will "
                + "generate random usernames if 'username' is not supplied).");
    OptionSpec<?> autoRejoinOption =
        parser.acceptsAll(Arrays.asList("a", "auto-rejoin"), "Auto-rejoin a server on disconnect.");
    OptionSpec<Integer> loginDelayOption =
        parser
            .acceptsAll(
                Arrays.asList("d", "login-delay"),
                "Delay between bot joins, in milliseconds. 5000 is "
                    + "recommended if not using socks proxies.")
            .withRequiredArg()
            .describedAs("delay")
            .ofType(Integer.class);
    OptionSpec<Integer> botAmountOption =
        parser
            .acceptsAll(
                Arrays.asList("b", "bot-amount"),
                "Amount of bots to join. Must be <= amount of accounts.")
            .withRequiredArg()
            .describedAs("amount")
            .ofType(Integer.class);
    OptionSpec<String> protocolOption =
        parser
            .accepts(
                "protocol",
                "Protocol version to use. Can be either protocol number or Minecraft version.")
            .withRequiredArg();
    OptionSpec<?> protocolsOption =
        parser.accepts("protocols", "List available protocols and exit.");

    OptionSpec<String> accountListOption =
        parser
            .accepts(
                "account-list",
                "File containing a list of accounts, in username/email:password format.")
            .withRequiredArg()
            .describedAs("file");
    OptionSpec<String> socksProxyListOption =
        parser
            .accepts(
                "socks-proxy-list",
                "File containing a list of SOCKS proxies, in address:port format.")
            .withRequiredArg()
            .describedAs("file");
    OptionSpec<String> httpProxyListOption =
        parser
            .accepts(
                "http-proxy-list",
                "File containing a list of HTTP proxies, in address:port format.")
            .withRequiredArg()
            .describedAs("file");
    OptionSpec<String> captchaListOption =
        parser
            .accepts("captcha-list", "File containing a list of chat baised captcha to bypass.")
            .withRequiredArg()
            .describedAs("file");

    OptionSet options;
    try {
      options = parser.parse(args);
    } catch (OptionException exception) {
      try {
        parser.printHelpOn(System.out);
      } catch (Exception exception1) {
        exception1.printStackTrace();
      }
      return;
    }

    if (options.has("help")) {
      printHelp(parser);
      return;
    }
    if (options.has(protocolsOption)) {
      System.out.println("Available protocols:");
      for (ProtocolProvider provider : ProtocolProvider.getProviders())
        System.out.println(
            "\t"
                + provider.getMinecraftVersion()
                + " ("
                + provider.getSupportedVersion()
                + "): "
                + provider.getClass().getName());
      System.out.println(
          "If no protocols are listed above, you may attempt to specify a protocol version in case the provider is actually in the class-path.");
      return;
    }

    final boolean offline = options.has(offlineOption);
    final boolean autoRejoin = options.has(autoRejoinOption);

    final List<String> accounts;
    if (options.has(accountListOption)) {
      accounts = loadAccounts(options.valueOf(accountListOption));
    } else if (!offline) {
      System.out.println("Option 'accounts' must be supplied in " + "absence of option 'offline'.");
      printHelp(parser);
      return;
    } else accounts = null;

    final List<String> captcha;
    if (options.has(captchaListOption)) readCaptchaFile(options.valueOf(captchaListOption));

    final String server;
    if (!options.has(serverOption)) {
      System.out.println("Option 'server' required.");
      printHelp(parser);
      return;
    } else server = options.valueOf(serverOption);

    final String owner;
    if (!options.has(ownerOption)) {
      System.out.println("Option 'owner' required.");
      printHelp(parser);
      return;
    } else owner = options.valueOf(ownerOption);

    final int protocol;
    if (options.has(protocolOption)) {
      String protocolString = options.valueOf(protocolOption);
      int parsedProtocol;
      try {
        parsedProtocol = Integer.parseInt(protocolString);
      } catch (NumberFormatException exception) {
        ProtocolProvider foundProvider = null;
        for (ProtocolProvider provider : ProtocolProvider.getProviders())
          if (protocolString.equals(provider.getMinecraftVersion())) foundProvider = provider;
        if (foundProvider == null) {
          System.out.println("No provider found for Minecraft version '" + protocolString + "'.");
          return;
        } else parsedProtocol = foundProvider.getSupportedVersion();
      }
      protocol = parsedProtocol;
    } else protocol = MinecraftBot.LATEST_PROTOCOL;

    final List<String> socksProxies;
    if (options.has(socksProxyListOption))
      socksProxies = loadProxies(options.valueOf(socksProxyListOption));
    else socksProxies = null;
    final boolean useProxy = socksProxies != null;

    final List<String> httpProxies;
    if (options.has(httpProxyListOption))
      httpProxies = loadLoginProxies(options.valueOf(httpProxyListOption));
    else if (!offline && accounts != null) {
      System.out.println(
          "Option 'http-proxy-list' required if " + "option 'account-list' is supplied.");
      printHelp(parser);
      return;
    } else httpProxies = null;

    final int loginDelay;
    if (options.has(loginDelayOption)) loginDelay = options.valueOf(loginDelayOption);
    else loginDelay = 0;

    final int botAmount;
    if (!options.has(botAmountOption)) {
      System.out.println("Option 'bot-amount' required.");
      printHelp(parser);
      return;
    } else botAmount = options.valueOf(botAmountOption);

    initGui();
    while (!sessions.get()) {
      synchronized (sessions) {
        try {
          sessions.wait(5000);
        } catch (InterruptedException exception) {
        }
      }
    }

    final Queue<Runnable> lockQueue = new ArrayDeque<Runnable>();

    ExecutorService service = Executors.newFixedThreadPool(botAmount + (loginDelay > 0 ? 1 : 0));
    final Object firstWait = new Object();
    if (loginDelay > 0) {
      service.execute(
          new Runnable() {
            @Override
            public void run() {
              synchronized (firstWait) {
                try {
                  firstWait.wait();
                } catch (InterruptedException exception) {
                }
              }
              while (true) {
                try {
                  Thread.sleep(loginDelay);
                } catch (InterruptedException exception) {
                }
                synchronized (lockQueue) {
                  if (lockQueue.size() > 0) {
                    Runnable thread = lockQueue.poll();
                    synchronized (thread) {
                      thread.notifyAll();
                    }
                    lockQueue.offer(thread);
                  } else continue;
                }
                while (!sessions.get()) {
                  synchronized (sessions) {
                    try {
                      sessions.wait(5000);
                    } catch (InterruptedException exception) {
                    }
                  }
                }
              }
            }
          });
    }
    final List<String> accountsInUse = new ArrayList<String>();
    final Map<String, AtomicInteger> workingProxies = new HashMap<String, AtomicInteger>();
    for (int i = 0; i < botAmount; i++) {
      final int botNumber = i;
      Runnable runnable =
          new Runnable() {
            @Override
            public void run() {
              if (loginDelay > 0)
                synchronized (lockQueue) {
                  lockQueue.add(this);
                }
              Random random = new Random();

              if (!offline) {
                AuthService authService = new LegacyAuthService();
                boolean authenticated = false;
                user:
                while (true) {
                  if (authenticated) {
                    authenticated = false;
                    sessionCount.decrementAndGet();
                  }
                  Session session = null;
                  String loginProxy;
                  String account = accounts.get(random.nextInt(accounts.size()));
                  synchronized (accountsInUse) {
                    if (accountsInUse.size() == accounts.size()) System.exit(0);
                    while (accountsInUse.contains(account))
                      account = accounts.get(random.nextInt(accounts.size()));
                    accountsInUse.add(account);
                  }
                  String[] accountParts = account.split(":");
                  while (true) {
                    while (!sessions.get()) {
                      synchronized (sessions) {
                        try {
                          sessions.wait(5000);
                        } catch (InterruptedException exception) {
                        }
                      }
                    }
                    synchronized (workingProxies) {
                      Iterator<String> iterator = workingProxies.keySet().iterator();
                      if (iterator.hasNext()) loginProxy = iterator.next();
                      else loginProxy = httpProxies.get(random.nextInt(httpProxies.size()));
                      ;
                    }
                    try {
                      session =
                          authService.login(
                              accountParts[0],
                              accountParts[1],
                              toProxy(loginProxy, Proxy.Type.HTTP));
                      // addAccount(session);
                      synchronized (workingProxies) {
                        AtomicInteger count = workingProxies.get(loginProxy);
                        if (count != null) count.set(0);
                        else workingProxies.put(loginProxy, new AtomicInteger());
                      }
                      sessionCount.incrementAndGet();
                      authenticated = true;
                      break;
                    } catch (IOException exception) {
                      synchronized (workingProxies) {
                        workingProxies.remove(loginProxy);
                      }
                      System.err.println("[Bot" + botNumber + "] " + loginProxy + ": " + exception);
                    } catch (AuthenticationException exception) {
                      if (exception.getMessage().contains("Too many failed logins")) {
                        synchronized (workingProxies) {
                          AtomicInteger count = workingProxies.get(loginProxy);
                          if (count != null && count.incrementAndGet() >= 5)
                            workingProxies.remove(loginProxy);
                        }
                      }
                      System.err.println("[Bot" + botNumber + "] " + loginProxy + ": " + exception);
                      continue user;
                    }
                  }
                  System.out.println("[" + session.getUsername() + "] " + session);
                  while (!joins.get()) {
                    synchronized (joins) {
                      try {
                        joins.wait(5000);
                      } catch (InterruptedException exception) {
                      }
                    }
                  }
                  if (loginDelay > 0) {
                    synchronized (this) {
                      try {
                        synchronized (firstWait) {
                          firstWait.notifyAll();
                        }
                        wait();
                      } catch (InterruptedException exception) {
                      }
                    }
                  }

                  while (true) {
                    String proxy =
                        useProxy ? socksProxies.get(random.nextInt(socksProxies.size())) : null;
                    try {
                      DarkBotMCSpambot bot =
                          new DarkBotMCSpambot(
                              generateData(
                                  server,
                                  session.getUsername(),
                                  session.getPassword(),
                                  authService,
                                  session,
                                  protocol,
                                  null,
                                  proxy),
                              owner);
                      while (bot.getBot().isConnected()) {
                        try {
                          Thread.sleep(500);
                        } catch (InterruptedException exception) {
                          exception.printStackTrace();
                        }
                      }
                      if (!autoRejoin) break;
                    } catch (Exception exception) {
                      exception.printStackTrace();
                      System.out.println(
                          "["
                              + session.getUsername()
                              + "] Error connecting: "
                              + exception.getCause().toString());
                    }
                  }
                  System.out.println("[" + session.getUsername() + "] Account failed");
                }
              } else {
                while (true) {
                  String proxy =
                      useProxy ? socksProxies.get(random.nextInt(socksProxies.size())) : null;
                  try {
                    String username;
                    if (accounts != null) {
                      username = accounts.get(random.nextInt(accounts.size())).split(":")[0];
                      synchronized (accountsInUse) {
                        while (accountsInUse.contains(username))
                          username = accounts.get(random.nextInt(accounts.size()));
                        accountsInUse.add(username);
                      }
                    } else username = Util.generateRandomString(10 + random.nextInt(6));
                    if (loginDelay > 0) {
                      synchronized (this) {
                        try {
                          synchronized (firstWait) {
                            firstWait.notifyAll();
                          }
                          wait();
                        } catch (InterruptedException exception) {
                        }
                      }
                    }
                    DarkBotMCSpambot bot =
                        new DarkBotMCSpambot(
                            generateData(server, username, null, null, null, protocol, null, proxy),
                            owner);
                    while (bot.getBot().isConnected()) {
                      try {
                        Thread.sleep(500);
                      } catch (InterruptedException exception) {
                        exception.printStackTrace();
                      }
                    }
                    if (!autoRejoin) break;
                    else continue;
                  } catch (Exception exception) {
                    System.out.println(
                        "[Bot" + botNumber + "] Error connecting: " + exception.toString());
                  }
                }
              }
            }
          };
      service.execute(runnable);
    }
    service.shutdown();
    while (!service.isTerminated()) {
      try {
        service.awaitTermination(9000, TimeUnit.DAYS);
      } catch (InterruptedException exception) {
        exception.printStackTrace();
      }
    }
    System.exit(0);
  }