diff --git a/Cargo.toml b/Cargo.toml index 119dd89..6ad3ffd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ simple_logger = "5.0.0" clap = { version = "4.5.30", features = ["derive"] } # Networking tokio = { version = "1.43.0", features = ["net", "io-util"] } -pumpkin-protocol = { git = "https://github.com/Pumpkin-MC/Pumpkin", package = "pumpkin-protocol", default-features = false, features = ["packets"]} +pumpkin-protocol = { git = "https://github.com/Pumpkin-MC/Pumpkin", package = "pumpkin-protocol", default-features = false, features = ["packets"] } crossbeam = "0.8.4" uuid = "1.14.0" \ No newline at end of file diff --git a/src/client.rs b/src/client.rs index b12bb3d..cefe23f 100644 --- a/src/client.rs +++ b/src/client.rs @@ -17,7 +17,6 @@ use pumpkin_protocol::{ packet_decoder::PacketDecoder, packet_encoder::PacketEncoder, }; use std::collections::VecDeque; -use std::net::SocketAddr; use std::sync::{Arc, atomic::AtomicBool}; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::{ @@ -170,11 +169,11 @@ impl Client { } } - pub async fn join_server(&self, address: SocketAddr, name: String) { + pub async fn join_server(&self, ip: String, port: u16, name: String) { self.send_packet(&SHandShake { protocol_version: VarInt(CURRENT_MC_PROTOCOL.get() as i32), - server_address: address.ip().to_string(), - server_port: address.port(), + server_address: ip, + server_port: port, next_state: pumpkin_protocol::ConnectionState::Login, }) .await; @@ -214,7 +213,7 @@ impl Client { .await } CLoginDisconnect::PACKET_ID => { - log::error!("Kicking in Login State"); + log::error!("Kicking in Login State with reason:\n{}", String::from_utf8_lossy(packet.bytebuf.iter().as_slice())); self.close().await; } CLoginSuccess::PACKET_ID => { diff --git a/src/main.rs b/src/main.rs index a1ce7fb..a2f1593 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use std::net::SocketAddr; +use std::sync::{atomic::{AtomicUsize, Ordering}, Arc}; use clap::Parser; use client::Client; @@ -11,6 +11,8 @@ mod client; struct Args { #[arg(short, long)] ip: String, + #[arg(short, long, default_value_t = 25565)] + port: u16, #[arg(short, long, default_value_t = 1)] count: u32, } @@ -19,17 +21,26 @@ struct Args { async fn main() { simple_logger::init_with_level(log::Level::Info).unwrap(); let args = Args::parse(); - let address = args.ip.parse::().unwrap(); - log::info!("{} Bots will Join {}", args.count, address); - let mut join_handles = Vec::with_capacity(args.count as usize); + let address = Arc::new(args.ip); + let port = args.port; - for i in 0..args.count { - let stream = TcpStream::connect(address) - .await - .expect("Failed to connect to Ip"); - let client = Client::new(stream); - client.join_server(address, format!("BOT_{}", i)).await; - let join_handle = tokio::spawn(async move { + log::info!("{} Bots will Join {}", args.count, address); + + let counter = Arc::new(AtomicUsize::new(0)); + for _ in 0..args.count { + let counter = counter.clone(); + let address = address.clone(); + + tokio::spawn(async move { + let stream = TcpStream::connect(address.to_string() + ":" + &port.to_string()) + .await + .expect("Failed to connect to Ip"); + let client = Client::new(stream); + let i = counter.fetch_add(1, Ordering::Relaxed); + + client.join_server(address.to_string(), port, format!("BOT_{i}")).await; + log::info!("{}/{} Bots Joined", i + 1, args.count); + loop { if !client.poll().await { break; @@ -37,15 +48,10 @@ async fn main() { client.process_packets().await; } }); - join_handles.push(join_handle); - log::info!("{}/{} Bots Joined", i + 1, args.count); - } + }; + // Graceful shutdown on Ctrl+C tokio::signal::ctrl_c().await.unwrap(); log::info!("Shutting down..."); - - // Wait for all bot tasks to exit - for handle in join_handles { - handle.abort(); - } } +