fixing format issue and adding -rm parameter for excutring random moves on bots each ms #112

Closed
moeelbadri wants to merge 2 commits from main into main
pull from: main
5 changed files with 114 additions and 2 deletions

No files matched your search

+7
View File
@@ -13,6 +13,8 @@ For older MC versions please look in the [releases](https://github.com/crpmax/mc
- ✅ Generate random or real looking nicknames or load from file - ✅ Generate random or real looking nicknames or load from file
- ✅ Online (premium) account support with login using Microsoft - ✅ Online (premium) account support with login using Microsoft
- ✅ Control all or selected bots - ✅ Control all or selected bots
- ✅ Random movement simulation
- ✅ Automatic jump when stuck (obstacle avoidance)
## 📖 Usage ## 📖 Usage
Minimal Java version: 17 Minimal Java version: 17
@@ -24,6 +26,9 @@ When running, you can write a chat message to the terminal to send it by all bot
`java -jar mc-bots-1.2.17.jar -s 192.168.0.189:25565 -p BOT_ -d 4000 5000 -c 30 -r` `java -jar mc-bots-1.2.17.jar -s 192.168.0.189:25565 -p BOT_ -d 4000 5000 -c 30 -r`
This will connect 30 bots to server at 192.168.0.189:25565 with delay 4000-5000 ms and will use real-looking nicknames prefixed with BOT_ This will connect 30 bots to server at 192.168.0.189:25565 with delay 4000-5000 ms and will use real-looking nicknames prefixed with BOT_
`java -jar mc-bots-1.2.17.jar -s 192.168.0.189:25565 -c 10 -rm 1000 -g`
This will connect 10 bots with random movement every 1 second and gravity simulation enabled
<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"/>
@@ -42,6 +47,7 @@ This will connect 30 bots to server at 192.168.0.189:25565 with delay 4000-5000
`-g` Try to simulate gravity by falling down `-g` Try to simulate gravity by falling down
`-o` Use online (premium) account (login with Microsoft OAuth) `-o` Use online (premium) account (login with Microsoft OAuth)
`-ar <delay>` Set auto-respawn delay (default is 100 ms, set to -1 to disable) `-ar <delay>` Set auto-respawn delay (default is 100 ms, set to -1 to disable)
`-rm <interval>` Enable random movement with specified interval in milliseconds (e.g. 2000 for 2 seconds)
`--nicks <file>` Set nicknames file `--nicks <file>` Set nicknames file
@@ -50,6 +56,7 @@ Commands can be typed to the console. They are prefixed with `.` or `!`.
Without the prefix it will be sent as a chat message! Without the prefix it will be sent as a chat message!
`.list` or `.ls` - list all connected bots `.list` or `.ls` - list all connected bots
`.control <nick>` or `.ctrl <nick>` - select one or multiple bots to control `.control <nick>` or `.ctrl <nick>` - select one or multiple bots to control
`.jump` or `.j` - make bots jump (useful for testing or getting unstuck)
`.exit <limit>` or `.leave <limit>` - disconnect all or specified number of bots `.exit <limit>` or `.leave <limit>` - disconnect all or specified number of bots
## ⚠ DISCLAIMER ## ⚠ DISCLAIMER
+3 -1
View File
@@ -1,2 +1,4 @@
rootProject.name = 'mc-bots' rootProject.name = 'mc-bots'
#org.gradle.java.installations.fromEnv=JAVA_HOME
#org.gradle.java.installations.auto-download=false
org.gradle.configuration-cache=true
@@ -42,6 +42,17 @@ public class Bot extends Thread {
private boolean connected; private boolean connected;
private boolean manualDisconnecting = false; private boolean manualDisconnecting = false;
private Random movementRandom = new Random();
private double currentDirection = 0;
private int stepsInDirection = 0;
private int maxStepsInDirection = 0;
// Stuck detection variables
private double previousX = 0, previousZ = 0;
private int stuckCounter = 0;
private static final int STUCK_THRESHOLD = 3; // Consider stuck after 3 failed moves
private static final double MIN_MOVEMENT = 0.01; // Minimum movement to not be considered stuck
public Bot(MinecraftProtocol protocol, InetSocketAddress address, ProxyInfo proxy) { public Bot(MinecraftProtocol protocol, InetSocketAddress address, ProxyInfo proxy) {
this.nickname = protocol.getProfile().getName(); this.nickname = protocol.getProfile().getName();
@@ -204,6 +215,69 @@ public class Bot extends Thread {
{ {
client.send(new ServerboundMovePlayerPosPacket(true, false, x, y, z)); client.send(new ServerboundMovePlayerPosPacket(true, false, x, y, z));
} }
public void jump() {
if (connected && lastZ != -1) {
// Jump by moving up 0.42 blocks (standard Minecraft jump height)
move(0, 0.42, 0);
}
}
public void forceJump() {
// Force jump regardless of stuck status (for manual testing)
jump();
}
public void moveRandomly() {
if (connected && lastZ != -1) {
// Store current position before moving
double currentX = lastX;
double currentZ = lastZ;
// Check if we need a new direction
if (stepsInDirection >= maxStepsInDirection) {
// Pick new random direction and duration
currentDirection = movementRandom.nextDouble() * 2 * Math.PI;
maxStepsInDirection = 3 + movementRandom.nextInt(8); // Walk 3-10 steps in one direction
stepsInDirection = 0;
}
// Move in current direction with realistic speed
double speed = 0.08; // About 0.08 blocks per movement call
double deltaX = Math.cos(currentDirection) * speed;
double deltaZ = Math.sin(currentDirection) * speed;
// Occasionally stop moving (simulate standing still)
if (movementRandom.nextDouble() < 0.1) {
deltaX = 0;
deltaZ = 0;
}
// Check if bot is stuck (hasn't moved much from previous position)
double distanceMoved = Math.sqrt(Math.pow(currentX - previousX, 2) + Math.pow(currentZ - previousZ, 2));
if (distanceMoved < MIN_MOVEMENT && (deltaX != 0 || deltaZ != 0)) {
stuckCounter++;
if (stuckCounter >= STUCK_THRESHOLD) {
// Bot is stuck, try jumping and change direction
jump();
currentDirection = movementRandom.nextDouble() * 2 * Math.PI; // New random direction
stuckCounter = 0; // Reset stuck counter
stepsInDirection = maxStepsInDirection; // Force new direction next time
}
} else {
stuckCounter = 0; // Reset if bot moved successfully
}
// Store position for next stuck check
previousX = currentX;
previousZ = currentZ;
move(deltaX, 0, deltaZ);
stepsInDirection++;
}
}
public boolean isConnected() { public boolean isConnected() {
return connected; return connected;
@@ -86,6 +86,8 @@ public class Main {
options.addOption("o", "online", false, "Use online mode (premium) account"); options.addOption("o", "online", false, "Use online mode (premium) account");
options.addOption("ar", "auto-respawn", true, "Set autorespawn delay (-1 to disable)"); options.addOption("ar", "auto-respawn", true, "Set autorespawn delay (-1 to disable)");
options.addOption("rm", "random-move", true, "Enable random movement with interval in ms (e.g. 2000)");
CommandLineParser parser = new DefaultParser(); CommandLineParser parser = new DefaultParser();
CommandLine cmd = null; CommandLine cmd = null;
@@ -369,6 +371,19 @@ public class Main {
} }
}, 1000L, 500L); }, 1000L, 500L);
} }
//random movement timer
if (cmd.hasOption("rm")) {
long moveInterval = Long.parseLong(cmd.getOptionValue("rm", "2000"));
Log.info("Random movement enabled with interval: " + moveInterval + "ms");
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
bots.forEach(Bot::moveRandomly);
}
}, moveInterval, moveInterval);
}
Terminal terminal = TerminalBuilder.builder().build(); Terminal terminal = TerminalBuilder.builder().build();
LineReader lineReader = LineReaderBuilder.builder() LineReader lineReader = LineReaderBuilder.builder()
@@ -451,6 +466,15 @@ public class Main {
for (Bot bot : bots) { for (Bot bot : bots) {
Log.info(bot.getNickname(), bot.hasMainListener() ? "[MainListener]" : ""); Log.info(bot.getNickname(), bot.hasMainListener() ? "[MainListener]" : "");
} }
} else if (commandName.equalsIgnoreCase("jump") || commandName.equalsIgnoreCase("j")) {
// Jump command for testing
if (!controlledBots.isEmpty()) {
Log.info("Making controlled bots jump");
controlledBots.forEach(Bot::forceJump);
} else {
Log.info("Making all bots jump");
bots.forEach(Bot::forceJump);
}
} else if (commandName.equalsIgnoreCase("leave") || commandName.equalsIgnoreCase("exit")) { } else if (commandName.equalsIgnoreCase("leave") || commandName.equalsIgnoreCase("exit")) {
int limit = -1; int limit = -1;
if (split.length >= 2) { if (split.length >= 2) {
@@ -152,8 +152,11 @@ public class Utils {
Component component = arg.asComponent(); Component component = arg.asComponent();
if (component instanceof TranslatableComponent) { if (component instanceof TranslatableComponent) {
placeholders.add(translate((TranslatableComponent) component)); placeholders.add(translate((TranslatableComponent) component));
} else if (arg instanceof TextComponent) { } else if (component instanceof TextComponent) {
placeholders.add(getFullText((TextComponent) component, false)); placeholders.add(getFullText((TextComponent) component, false));
} else {
// Fallback for other component types
placeholders.add(component.toString());
} }
} }
//Log.info(Arrays.toString(placeholders.toArray())); //Log.info(Arrays.toString(placeholders.toArray()));
@@ -161,6 +164,8 @@ public class Utils {
return String.format(base, placeholders.toArray()); return String.format(base, placeholders.toArray());
} catch (Exception e) { } catch (Exception e) {
Log.error("Error formatting '"+base+"' with placeholders " + Arrays.toString(placeholders.toArray())); Log.error("Error formatting '"+base+"' with placeholders " + Arrays.toString(placeholders.toArray()));
// Return a fallback message instead of empty string
return key + " " + String.join(" ", placeholders);
} }
} else { } else {
return base; return base;