diff --git a/README.md b/README.md index 3620561..3d4847e 100644 --- a/README.md +++ b/README.md @@ -7,4 +7,10 @@ mæk ˈrrɪzᵊl ˈdrɪzᵊl TODO: - [x] ~~Fix error on disconnect~~ - [x] ~~Command support~~ +- [ ] Operators +- [ ] Finish command support (Event Listeners) +- [ ] Finish the readme +- [ ] Fix player id/thread allocator + +Backburner: - [ ] classicube extensions diff --git a/rte/config.toml b/rte/config.toml index 576b26f..d752a33 100644 --- a/rte/config.toml +++ b/rte/config.toml @@ -2,6 +2,7 @@ name = "mcrizzledizzle default" motd = "For shits and giggles" port = 25565 +max_players = 3 [world] world = "world.wrld" # Custom world type, not interchangable with other servers diff --git a/src/config.rs b/src/config.rs index 9f1cd06..a6d1715 100644 --- a/src/config.rs +++ b/src/config.rs @@ -20,6 +20,7 @@ pub struct Config { #[serde(default)] pub struct ServerConfig { pub port: u16, + pub max_players: u8, // Upper limit pub name: String, pub motd: String, } @@ -28,6 +29,7 @@ impl Default for ServerConfig { fn default() -> Self { Self { port: 25565, + max_players: 255, name: "Default".to_string(), motd: "Default".to_string(), } @@ -64,6 +66,7 @@ impl Config { name = "mcrizzledizzle default" motd = "For shits and giggles" port = 25565 +max_players = 255 [world] world = "world.wrld" # Custom world type, not interchangable with other servers diff --git a/src/main.rs b/src/main.rs index ac6fb69..b8a759b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ use log::{error, info}; use simple_logger::SimpleLogger; +use std::io::Write; use std::net::{SocketAddr, TcpListener}; use std::sync::{Arc, Mutex}; @@ -17,6 +18,7 @@ use error::AppError; use extensions::{Extensions, PlayersWrapper, WorldWrapper}; use network::handle_client; use player::{Player, SpecialPlayers}; +use utils::{client_disconnect, server_identification}; use world::World; fn main() { @@ -57,21 +59,43 @@ fn run() -> Result<(), AppError> { WorldWrapper::new(world_arc.clone()), )?); - info!("Server listening on {}", 25565); + info!("Server listening on {}", config.server.port); for stream in listener.incoming() { let players_arc_clone = Arc::clone(&players_arc); let world_arc_clone = Arc::clone(&world_arc); let extensions_arc_clone = Arc::clone(&extensions); - handle_client( - config.clone().server, - stream?, - thread_number, - players_arc_clone, - world_arc_clone, - extensions_arc_clone, - ); - thread_number = thread_number.wrapping_add(1); + let mut insertion_attempts: u8 = 0; + while players_arc.lock()?[thread_number as usize].id != SpecialPlayers::SelfPlayer as u8 + && insertion_attempts < config.server.max_players + { + insertion_attempts += 1; + // One is reserved for communications + if thread_number < config.server.max_players - 1 { + thread_number += 1; + } else { + thread_number = 0; + } + } + if insertion_attempts == config.server.max_players { + // Server must be full + // Seems silly that we have to ident to kick clients, but I didn't make the protocol + let mut disconnect_packets: Vec = Vec::new(); + disconnect_packets + .extend_from_slice(&server_identification(config.server.clone(), false)); + disconnect_packets + .extend_from_slice(&client_disconnect("Server is full! Try again later")); + stream?.write_all(&disconnect_packets)?; + } else { + handle_client( + config.clone().server, + stream?, + thread_number, + players_arc_clone, + world_arc_clone, + extensions_arc_clone, + ); + } } Ok(()) } diff --git a/src/network.rs b/src/network.rs index 0f3a8f2..df5153c 100644 --- a/src/network.rs +++ b/src/network.rs @@ -282,7 +282,7 @@ pub fn handle_client( break; } - sleep(Duration::from_millis(1)); // 1000 TPS TODO: Delta time + sleep(Duration::from_millis(50)); // 1000 TPS TODO: Delta time { let mut players = players_arc_clone.lock().unwrap(); if !players[client_number as usize].outgoing_data.is_empty() {