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