Compare commits

..

No commits in common. "master" and "1.0.1" have entirely different histories.

6 changed files with 1004 additions and 2148 deletions

View File

@ -17,7 +17,7 @@ jobs:
toolchain: toolchain:
- stable - stable
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v4
- run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }} - run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}
- uses: Swatinem/rust-cache@v2 - uses: Swatinem/rust-cache@v2
- run: cargo fmt --check - run: cargo fmt --check
@ -29,7 +29,7 @@ jobs:
toolchain: toolchain:
- stable - stable
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v4
- run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }} - run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}
- uses: Swatinem/rust-cache@v2 - uses: Swatinem/rust-cache@v2
- run: cargo clippy --all-targets --all-features - run: cargo clippy --all-targets --all-features
@ -42,7 +42,7 @@ jobs:
toolchain: toolchain:
- stable - stable
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v4
- run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }} - run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}
- uses: Swatinem/rust-cache@v2 - uses: Swatinem/rust-cache@v2
- run: cargo test --verbose - run: cargo test --verbose

1427
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -10,21 +10,15 @@ codegen-units = 1
[dependencies] [dependencies]
# log # log
log = "0.4" log = "0.4"
simple_logger = "5.2.0" simple_logger = "5.1.0"
# CLI # CLI
clap = { version = "4.6.6", features = ["derive"] } clap = { version = "4.5.56", features = ["derive"] }
# Networking # Networking
tokio = { version = "1.53.1", features = ["net", "io-util"] } tokio = { version = "1.49.0", features = ["net", "io-util"] }
pumpkin-protocol = { git = "https://github.com/Pumpkin-MC/Pumpkin", package = "pumpkin-protocol", default-features = false, features = ["serverbound", "clientbound"]} pumpkin-protocol = { git = "https://github.com/Pumpkin-MC/Pumpkin", package = "pumpkin-protocol", default-features = false, features = ["serverbound", "clientbound"]}
pumpkin-util = { git = "https://github.com/Pumpkin-MC/Pumpkin", package = "pumpkin-util"} pumpkin-util = { git = "https://github.com/Pumpkin-MC/Pumpkin", package = "pumpkin-util"}
pumpkin-data = { git = "https://github.com/Pumpkin-MC/Pumpkin", package = "pumpkin-data"} pumpkin-data = { git = "https://github.com/Pumpkin-MC/Pumpkin", package = "pumpkin-data"}
crossbeam = "0.8.4" crossbeam = "0.8.4"
uuid = "1.25.0" uuid = "1.20.0"
rand = { git = "https://github.com/rust-random/rand"} rand = { git = "https://github.com/rust-random/rand"}
rsa = { version = "=0.10.0-rc.18", default-features = false, features = ["std", "encoding"] }
[patch."https://github.com/Pumpkin-MC/Pumpkin"]
pumpkin-protocol = { path = "../Pumpkin/crates/pumpkin-protocol" }
pumpkin-util = { path = "../Pumpkin/crates/pumpkin-util" }
pumpkin-data = { path = "../Pumpkin/crates/pumpkin-data" }

View File

@ -1,7 +1,7 @@
<div align="center"> <div align="center">
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
![Current version)](https://img.shields.io/badge/current_version-1.26-blue) ![Current version)](https://img.shields.io/badge/current_version-1.21.11-blue)
A tool to stress test Minecraft servers by simulating numerous bot connections, helping identify performance bottlenecks and stability issues. A tool to stress test Minecraft servers by simulating numerous bot connections, helping identify performance bottlenecks and stability issues.
![Screenshot_20250223_154536](https://github.com/user-attachments/assets/b1379060-e375-44dc-95a3-91f1f2fb52dd) ![Screenshot_20250223_154536](https://github.com/user-attachments/assets/b1379060-e375-44dc-95a3-91f1f2fb52dd)
@ -39,10 +39,6 @@ Here's a detailed breakdown of all available command-line arguments:
- The timeout (in milliseconds) for each bot connection. - The timeout (in milliseconds) for each bot connection.
- Example: `--delay 500` (500 milliseconds delay) - Example: `--delay 500` (500 milliseconds delay)
- **`--enable_spam_message <false/true>` (Optional, Default: `true`):**
- Enable periodic chat spam messages.
- Example: `--enable_spam_message true`
- **`--spam_message "<message>"` (Optional, Default: `Please do not spam!`):** - **`--spam_message "<message>"` (Optional, Default: `Please do not spam!`):**
- Will send a Chat message with the specified `spam_message_delay`. - Will send a Chat message with the specified `spam_message_delay`.
- Example: `--spam_message "Hello, I'm a Robot"` - Example: `--spam_message "Hello, I'm a Robot"`
@ -50,21 +46,15 @@ Here's a detailed breakdown of all available command-line arguments:
- **`--spam_message_delay_min <delay>` (Optional, Default: `150`):** - **`--spam_message_delay_min <delay>` (Optional, Default: `150`):**
- The minimal delay (in milliseconds) between spam message. - The minimal delay (in milliseconds) between spam message.
- Example: `--spam_message_delay_min 100` (100 milliseconds delay) - Example: `--spam_message_delay_min 100` (100 milliseconds delay)
- **`--spam_message_delay_max <delay>` (Optional, Default: `250`):** - **`--spam_message_delay_max <delay>` (Optional, Default: `350`):**
- The maximal delay (in milliseconds) between spam message. - The maximal delay (in milliseconds) between spam message.
- Example: `--spam_message_delay_max 250` (250 milliseconds delay) - Example: `--spam_message_delay_max 100` (100 milliseconds delay)
- **`--spam_message_delay_max <delay>` (Optional, Default: `350`):**
- The maximal delay (in milliseconds) between spam message.
- Example: `--spam_message_delay_max 100` (100 milliseconds delay)
- **`--enable_rotation <false/true>` (Optional, Default: `true`):** - **`--enable_rotation <false/true>` (Optional, Default: `true`):**
- Enable random head rotations. - Enable random head rotations.
- Example: `--enable_rotation true` - Example: `--enable_rotation true`
- **`--enable_swing <false/true>` (Optional, Default: `true`):** - **`--enable_swing <false/true>` (Optional, Default: `true`):**
- Enable random arm swings. - Enable random arm swings.
- Example: `--enable_swing true` - Example: `--enable_swing true`
- **`--enable_movement <false/true>` (Optional, Default: `true`):**
- Enable random bot movement and walking.
- Example: `--enable_movement true`
- **`--enable_jumping <false/true>` (Optional, Default: `true`):**
- Enable jumping while moving.
- Example: `--enable_jumping true`
- **`--enable_physics <false/true>` (Optional, Default: `true`):**
- Enable physics simulation (gravity, friction, inertia, server knockback).
- Example: `--enable_physics true`

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
use std::{net::SocketAddr, sync::Arc, sync::atomic::Ordering, time::Duration}; use std::{net::SocketAddr, sync::Arc, time::Duration};
use clap::Parser; use clap::Parser;
use client::Client; use client::Client;
@ -18,25 +18,17 @@ pub struct Args {
#[arg(short, long, default_value_t = 5000)] #[arg(short, long, default_value_t = 5000)]
pub timeout: u64, pub timeout: u64,
#[arg(long, default_value_t = true, default_missing_value = "true", num_args = 0..=1, action = clap::ArgAction::Set, alias = "enable_spam_message")] #[arg(long, default_value = "Please do not spam!")]
pub enable_spam_message: bool,
#[arg(long, default_value = "Please do not spam!", alias = "spam_message")]
pub spam_message: Option<String>, pub spam_message: Option<String>,
#[arg(long, default_value_t = 150, alias = "spam_message_delay_min")] #[arg(long, default_value_t = 150)]
pub spam_message_delay_min: u32, pub spam_message_delay_min: u32,
#[arg(long, default_value_t = 250, alias = "spam_message_delay_max")] #[arg(long, default_value_t = 250)]
pub spam_message_delay_max: u32, pub spam_message_delay_max: u32,
#[arg(long, default_value_t = true, default_missing_value = "true", num_args = 0..=1, action = clap::ArgAction::Set, alias = "enable_rotation")] #[arg(long, default_value_t = true)]
pub enable_rotation: bool, pub enable_rotation: bool,
#[arg(long, default_value_t = true, default_missing_value = "true", num_args = 0..=1, action = clap::ArgAction::Set, alias = "enable_swing")] #[arg(long, default_value_t = true)]
pub enable_swing: bool, pub enable_swing: bool,
#[arg(long, default_value_t = true, default_missing_value = "true", num_args = 0..=1, action = clap::ArgAction::Set, alias = "enable_movement")]
pub enable_movement: bool,
#[arg(long, default_value_t = true, default_missing_value = "true", num_args = 0..=1, action = clap::ArgAction::Set, alias = "enable_jumping")]
pub enable_jumping: bool,
#[arg(long, default_value_t = true, default_missing_value = "true", num_args = 0..=1, action = clap::ArgAction::Set, alias = "enable_physics")]
pub enable_physics: bool,
} }
#[tokio::main] #[tokio::main]
@ -70,7 +62,7 @@ async fn main() {
"Bot {} connection to {} timed out after {}ms", "Bot {} connection to {} timed out after {}ms",
i + 1, i + 1,
address, address,
args.timeout bot_count
); );
continue; continue;
} }
@ -79,25 +71,21 @@ async fn main() {
client.join_server(address, format!("BOT_{i}")).await; client.join_server(address, format!("BOT_{i}")).await;
let cloned_args = args.clone(); let cloned_args = args.clone();
let client_tick = client.clone(); let join_handle = tokio::spawn(async move {
let tick_handle = tokio::spawn(async move { let mut tick_interval = tokio::time::interval(Duration::from_millis(5));
let mut tick_interval = tokio::time::interval(Duration::from_millis(50));
tick_interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); tick_interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
while !client_tick.closed.load(Ordering::Relaxed) { loop {
tick_interval.tick().await; tokio::select! {
client_tick.tick(&cloned_args).await; res = client.process_packets() => {
if !res { break; }
}
_ = tick_interval.tick() => {
client.tick(&cloned_args).await;
}
}
} }
}); });
join_handles.push(join_handle);
let client_proc = client.clone();
let proc_handle = tokio::spawn(async move {
while client_proc.process_packets().await {
// Keep reading and processing incoming packets without cancellation
}
});
join_handles.push(tick_handle);
join_handles.push(proc_handle);
log::info!("{}/{} Bots Joined", i + 1, bot_count); log::info!("{}/{} Bots Joined", i + 1, bot_count);
} }
// Graceful shutdown on Ctrl+C // Graceful shutdown on Ctrl+C