fixing format issue and adding -rm parameter for excutring random moves on bots each ms #112
No files matched your search
@@ -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
|
||||
- ✅ Online (premium) account support with login using Microsoft
|
||||
- ✅ Control all or selected bots
|
||||
- ✅ Random movement simulation
|
||||
- ✅ Automatic jump when stuck (obstacle avoidance)
|
||||
|
||||
## 📖 Usage
|
||||
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`
|
||||
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/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
|
||||
`-o` Use online (premium) account (login with Microsoft OAuth)
|
||||
`-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
|
||||
|
||||
|
||||
@@ -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!
|
||||
`.list` or `.ls` - list all connected bots
|
||||
`.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
|
||||
|
||||
## ⚠ DISCLAIMER
|
||||
|
||||
@@ -43,6 +43,17 @@ public class Bot extends Thread {
|
||||
|
||||
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) {
|
||||
this.nickname = protocol.getProfile().getName();
|
||||
this.address = address;
|
||||
@@ -205,6 +216,69 @@ public class Bot extends Thread {
|
||||
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() {
|
||||
return connected;
|
||||
}
|
||||
|
||||
@@ -87,6 +87,8 @@ public class Main {
|
||||
|
||||
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();
|
||||
CommandLine cmd = null;
|
||||
|
||||
@@ -370,6 +372,19 @@ public class Main {
|
||||
}, 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();
|
||||
LineReader lineReader = LineReaderBuilder.builder()
|
||||
.terminal(terminal)
|
||||
@@ -451,6 +466,15 @@ public class Main {
|
||||
for (Bot bot : bots) {
|
||||
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")) {
|
||||
int limit = -1;
|
||||
if (split.length >= 2) {
|
||||
|
||||
@@ -152,8 +152,11 @@ public class Utils {
|
||||
Component component = arg.asComponent();
|
||||
if (component instanceof TranslatableComponent) {
|
||||
placeholders.add(translate((TranslatableComponent) component));
|
||||
} else if (arg instanceof TextComponent) {
|
||||
} else if (component instanceof TextComponent) {
|
||||
placeholders.add(getFullText((TextComponent) component, false));
|
||||
} else {
|
||||
// Fallback for other component types
|
||||
placeholders.add(component.toString());
|
||||
}
|
||||
}
|
||||
//Log.info(Arrays.toString(placeholders.toArray()));
|
||||
@@ -161,6 +164,8 @@ public class Utils {
|
||||
return String.format(base, placeholders.toArray());
|
||||
} catch (Exception e) {
|
||||
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 {
|
||||
return base;
|
||||
|
||||
Reference in new issue
Block a user