8 Commits
Author SHA1 Message Date
CreeperMaxCZ 204ff4b850 feat: support for getting proxies from url 2022-07-30 21:35:13 +02:00
CreeperMaxCZ 655bc70eaa feat: option to use nicks from file 2022-07-30 20:46:29 +02:00
CreeperMaxCZ 67de645f90 update version to 1.2.1 2022-05-12 21:53:53 +02:00
CreeperMaxCZ 997c8b8294 update readme with 1.18.2 support 2022-05-12 21:51:59 +02:00
CreeperMaxCZ f64b9d60d5 update library to 1.18.2 2022-05-12 21:51:07 +02:00
CreeperMaxCZ 3498663c01 Merge pull request #28 from sans404-dev/main
Fix build bug - library rename, exclude duplicates option
2022-05-07 15:07:12 +02:00
Sans404 a073d75081 Fix build bug 2022-05-05 00:14:37 +03:00
CreeperMaxCZ 934cc22306 socks proxy support, version bump 2022-03-20 15:38:34 +01:00
6 changed files with 172 additions and 12 deletions

No files matched your search

+7 -3
View File
@@ -1,14 +1,15 @@
# Minecraft bot stress tester # Minecraft bot stress tester
🤖 A simple open source app written in Java used for stress testing Minecraft servers with bots (fake players). 🤖 A simple open source app written in Java used for stress testing Minecraft servers with bots (fake players).
💥 It can be also used to test plugins or minigames. 💥 It can be also used to test plugins or minigames.
✔️ The MC version of the bots is 1.18 (supports 1.18.1). ✔️ The MC version of the bots is 1.18 (supports 1.18.2).
## 🆒 Features ## 🆒 Features
- ✅ Connect as many bots as you want - ✅ Connect as many bots as you want
- ✅ Use SOCKS4 or SOCKS5 proxies from file or URL
- ✅ Receive colored or noncolored chat - ✅ Receive colored or noncolored chat
- ✅ Set connection delay - ✅ Set connection delay
- ✅ Set message or command on join - ✅ Set message or command on join
- ✅ Generate random or real looking nicknames - ✅ Generate random or real looking nicknames or load from file
## 📖 Usage ## 📖 Usage
Minimal Java version: 8 Minimal Java version: 8
@@ -17,7 +18,7 @@ Use of pre-compiled jar from [releases](https://github.com/crpmax/mc-bots/releas
When running, you can write a chat message to the terminal to send it by all bots. When running, you can write a chat message to the terminal to send it by all bots.
## 🧪 Example ## 🧪 Example
`java -jar mc-bots-1.0.0.jar -s 192.168.0.189:25565 -d 10 11 -r -p BOT_ -c 30` `java -jar mc-bots-1.2.0.jar -s 192.168.0.189:25565 -d 10 11 -r -p BOT_ -c 30`
<img src="https://imgur.com/XWcckas.png" title="Connected bots" width="350px"/> <img src="https://imgur.com/XWcckas.png" title="Connected bots" width="350px"/>
<img src="https://imgur.com/CvJq1Io.gif" title="Sending chat message by bots" width="350px"/> <img src="https://imgur.com/CvJq1Io.gif" title="Sending chat message by bots" width="350px"/>
@@ -32,6 +33,9 @@ When running, you can write a chat message to the terminal to send it by all bot
`-n` Do not use color in terminal - useful when the terminal does not support it `-n` Do not use color in terminal - useful when the terminal does not support it
`-m` Minimal run - do not use any listeners, will not receive chat, useful for large amounts of bots `-m` Minimal run - do not use any listeners, will not receive chat, useful for large amounts of bots
`-x` The most minimal run - No listeners, no control, no chat - useful for large amounts of bots for better performance `-x` The most minimal run - No listeners, no control, no chat - useful for large amounts of bots for better performance
`-t` Set proxy type - SOCKS4 or SOCKS5
`-l` Set proxy list file
`-nicks` Set nicknames file
## ⚠ DISCLAIMER ## ⚠ DISCLAIMER
**This app is made for educational and testing purposes only. **This app is made for educational and testing purposes only.
+3 -2
View File
@@ -3,7 +3,7 @@ plugins {
} }
group 'me.creepermaxcz.mc-bots' group 'me.creepermaxcz.mc-bots'
version '1.1.0' version '1.2.2'
sourceCompatibility = 1.8 sourceCompatibility = 1.8
targetCompatibility = 1.8 targetCompatibility = 1.8
@@ -14,7 +14,7 @@ repositories {
} }
dependencies { dependencies {
implementation 'com.github.Steveice10:MCProtocolLib:1.18-2' implementation 'com.github.GeyserMC:MCProtocolLib:1.18.2-1'
implementation 'commons-cli:commons-cli:1.5.0' implementation 'commons-cli:commons-cli:1.5.0'
implementation 'com.diogonunes:JColor:5.2.0' implementation 'com.diogonunes:JColor:5.2.0'
implementation 'dnsjava:dnsjava:3.4.3' implementation 'dnsjava:dnsjava:3.4.3'
@@ -24,6 +24,7 @@ dependencies {
jar { jar {
manifest { manifest {
attributes 'Main-Class': 'me.creepermaxcz.mcbots.Main' attributes 'Main-Class': 'me.creepermaxcz.mcbots.Main'
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
} }
from { from {
configurations.runtimeClasspath.filter{ it.exists() }.collect { it.isDirectory() ? it : zipTree(it) } configurations.runtimeClasspath.filter{ it.exists() }.collect { it.isDirectory() ? it : zipTree(it) }
@@ -29,7 +29,7 @@ public class Bot extends Thread {
Log.info("Creating bot", nickname); Log.info("Creating bot", nickname);
protocol = new MinecraftProtocol(nickname); protocol = new MinecraftProtocol(nickname);
client = new TcpClientSession(address.getHostString(), address.getPort(), protocol); client = new TcpClientSession(address.getHostString(), address.getPort(), protocol, proxy);
} }
@Override @Override
@@ -27,6 +27,13 @@ public class Log {
log("INFO | "); log("INFO | ");
} }
public static void warn(String ...in) {
log("WARN | " + String.join(" ", in));
}
public static void warn() {
log("WARN | ");
}
public static void chat(String ...in) { public static void chat(String ...in) {
log("CHAT | " + String.join(" ", in)); log("CHAT | " + String.join(" ", in));
} }
+122 -3
View File
@@ -1,17 +1,19 @@
package me.creepermaxcz.mcbots; package me.creepermaxcz.mcbots;
import com.github.steveice10.packetlib.ProxyInfo;
import org.apache.commons.cli.*; import org.apache.commons.cli.*;
import org.xbill.DNS.Lookup; import org.xbill.DNS.Lookup;
import org.xbill.DNS.Record; import org.xbill.DNS.Record;
import org.xbill.DNS.SRVRecord; import org.xbill.DNS.SRVRecord;
import org.xbill.DNS.Type; import org.xbill.DNS.Type;
import java.net.InetAddress; import java.io.*;
import java.net.InetSocketAddress; import java.net.*;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Scanner; import java.util.Scanner;
public class Main { public class Main {
public static boolean coloredChat = true; public static boolean coloredChat = true;
@@ -26,6 +28,12 @@ public class Main {
private static boolean mostMinimal = false; private static boolean mostMinimal = false;
public static String joinMessage; public static String joinMessage;
private static boolean useProxies = false;
private static final ArrayList<InetSocketAddress> proxies = new ArrayList<>();
private static int proxyIndex = 0;
private static int proxyCount = 0;
private static ProxyInfo.Type proxyType;
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
Options options = new Options(); Options options = new Options();
@@ -47,6 +55,11 @@ public class Main {
options.addOption("x", "most-minimal", false, "minimal run without any control, just connect the bots"); options.addOption("x", "most-minimal", false, "minimal run without any control, just connect the bots");
options.addOption("j", "join-msg", true, "join message / command"); options.addOption("j", "join-msg", true, "join message / command");
options.addOption("l", "proxy-list", true, "Path or URL to proxy list file with proxy:port on every line");
options.addOption("t", "proxy-type", true, "Proxy type: SOCKS4 or SOCKS5");
options.addOption("nicks", true, "Path to nicks file with nick on every line");
CommandLineParser parser = new DefaultParser(); CommandLineParser parser = new DefaultParser();
CommandLine cmd = null; CommandLine cmd = null;
@@ -58,6 +71,76 @@ public class Main {
System.exit(1); System.exit(1);
} }
if (cmd.hasOption('t') && cmd.hasOption('l')) {
String typeStr = cmd.getOptionValue('t').toUpperCase();
//get proxy type
try {
proxyType = ProxyInfo.Type.valueOf(typeStr);
} catch (IllegalArgumentException e) {
Log.error("Inavlid proxy type, use SOCKS4 or SOCKS5.");
System.exit(1);
}
String proxyPath = cmd.getOptionValue("l");
//read proxy list file
try {
try {
//try to read specified path as URL
URL url = new URL(proxyPath);
BufferedReader read = new BufferedReader(
new InputStreamReader(url.openStream()));
Log.info("Reading proxies from URL");
String line;
while ((line = read.readLine()) != null) {
try {
String[] parts = line.trim().split(":");
if (parts.length == 2) {
int port = Integer.parseInt(parts[1]);
proxies.add(new InetSocketAddress(parts[0], port));
proxyCount++;
}
}
catch (Exception ignored) { }
}
read.close();
} catch (MalformedURLException e) {
Log.info("Specified proxy file is not a URL, trying to read file");
Scanner scanner = new Scanner(new File(proxyPath));
while (scanner.hasNextLine()) {
try {
String[] parts = scanner.nextLine().trim().split(":");
if (parts.length == 2) {
int port = Integer.parseInt(parts[1]);
proxies.add(new InetSocketAddress(parts[0], port));
proxyCount++;
}
}
catch (Exception ignored) { }
}
scanner.close();
}
} catch (FileNotFoundException e) {
Log.error("Invalid proxy list file path.");
System.exit(1);
}
if (proxyCount > 0) {
useProxies = true;
Log.info("Loaded " + proxyCount + " valid proxies");
} else {
Log.error("No valid proxies loaded");
System.exit(1);
}
}
botCount = Integer.parseInt(cmd.getOptionValue('c', "1")); botCount = Integer.parseInt(cmd.getOptionValue('c', "1"));
@@ -104,7 +187,18 @@ public class Main {
boolean realNicknames = cmd.hasOption('r'); boolean realNicknames = cmd.hasOption('r');
NickGenerator nickGen = new NickGenerator(); NickGenerator nickGen = new NickGenerator();
if (cmd.hasOption("nicks")) {
Log.info("Loading nicknames from specified file");
int nicksCount = nickGen.loadFromFile(cmd.getOptionValue("nicks"));
if (nicksCount < botCount) {
Log.warn("Nickname count is lower than bot count!");
Thread.sleep(3000);
}
} else {
nickGen.setReal(realNicknames); nickGen.setReal(realNicknames);
}
nickGen.setPrefix(cmd.getOptionValue('p', "")); nickGen.setPrefix(cmd.getOptionValue('p', ""));
InetSocketAddress inetAddr = new InetSocketAddress( InetSocketAddress inetAddr = new InetSocketAddress(
@@ -119,10 +213,35 @@ public class Main {
new Thread(() -> { new Thread(() -> {
for (int i = 0; i < botCount; i++) { for (int i = 0; i < botCount; i++) {
try { try {
ProxyInfo proxyInfo = null;
if (useProxies) {
InetSocketAddress proxySocket = proxies.get(proxyIndex);
if (!minimal) {
Log.info(
"Using proxy: (" + proxyIndex + ")",
proxySocket.getHostString() + ":" + proxySocket.getPort()
);
}
proxyInfo = new ProxyInfo(
proxyType,
proxySocket
);
//increment or reset current proxy index
if (proxyIndex < (proxyCount - 1)) {
proxyIndex++;
} else {
proxyIndex = 0;
}
}
Bot bot = new Bot( Bot bot = new Bot(
nickGen.nextNick(), nickGen.nextNick(),
inetAddr, inetAddr,
null proxyInfo
); );
bot.start(); bot.start();
@@ -1,11 +1,12 @@
package me.creepermaxcz.mcbots; package me.creepermaxcz.mcbots;
import java.io.BufferedReader; import java.io.*;
import java.io.InputStream; import java.net.InetSocketAddress;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class NickGenerator { public class NickGenerator {
@@ -25,6 +26,34 @@ public class NickGenerator {
private String prefix = ""; private String prefix = "";
public int loadFromFile(String filePath) {
lines = new ArrayList<>();
try {
Scanner scanner = new Scanner(new File(filePath));
while (scanner.hasNextLine()) {
try {
String line = scanner.nextLine().trim();
//add only valid nicknames
if (line.matches("^[a-zA-Z0-9_]{3,16}$")) {
lines.add(line);
}
}
catch (Exception ignored) { }
}
scanner.close();
} catch (FileNotFoundException e) {
Log.error("Invalid nicknames list file path");
System.exit(1);
}
linesSize = lines.size();
Log.info("Loaded " + linesSize + " valid nicknames");
real = true;
return linesSize;
}
private void loadLines() { private void loadLines() {
try (InputStream resource = getClass().getResourceAsStream("/files/nicks.txt")) { try (InputStream resource = getClass().getResourceAsStream("/files/nicks.txt")) {
lines = new BufferedReader( lines = new BufferedReader(