From efad9ec03e332aad7683991118592783f937e567 Mon Sep 17 00:00:00 2001 From: Luuk van Oijen Date: Thu, 9 Nov 2023 10:57:34 +0100 Subject: [PATCH] implemented the playerlist and player count --- src/server/client.rs | 2 ++ src/server/mod.rs | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/server/client.rs b/src/server/client.rs index d9f1d33..dcf290e 100644 --- a/src/server/client.rs +++ b/src/server/client.rs @@ -322,6 +322,7 @@ impl Client { self.disconnect(); } + // Panics when userdata is not set! pub fn get_name(&self) -> &str { &self.info.as_ref().unwrap().username } @@ -330,6 +331,7 @@ impl Client { self.id } + // Panics when userdata is not set! pub fn get_roles(&self) -> &str { &self.info.as_ref().unwrap().roles } diff --git a/src/server/mod.rs b/src/server/mod.rs index b391d29..ec818a0 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -47,6 +47,8 @@ pub struct Server { connect_runtime_handle: JoinHandle<()>, config: Arc, + + last_plist_update: Instant, } impl Server { @@ -107,6 +109,8 @@ impl Server { } if set.is_empty() == false { + // Because join_next() is cancel safe, we can simply cancel it after N duration + // so at worst this client acceptance loop blocks for N duration tokio::select!( _ = set.join_next() => {}, _ = tokio::time::sleep(tokio::time::Duration::from_secs(1)) => {}, @@ -127,6 +131,8 @@ impl Server { connect_runtime_handle: connect_runtime_handle, config: config, + + last_plist_update: Instant::now(), }) } @@ -216,9 +222,32 @@ impl Server { } } + // Update the player list + if self.last_plist_update.elapsed().as_secs() >= 1 { + self.last_plist_update = Instant::now(); + + let mut players = String::new(); + + for client in &self.clients { + players.push_str(&format!("{},", client.get_name())); + } + + if players.ends_with(",") { + players.remove(players.len() - 1); + } + + let player_count = self.clients.len(); + let max_players = self.config.general.max_players; + + let data = format!("Ss{player_count}/{max_players}:{players}"); + + self.broadcast(Packet::Raw(RawPacket::from_str(&data)), None).await; + } + Ok(()) } + // NOTE: Skips all clients that are currently connecting! async fn broadcast(&self, packet: Packet, owner: Option) { for client in &self.clients { if let Some(id) = owner { @@ -226,6 +255,9 @@ impl Server { continue; } } + if client.state == ClientState::Connecting { + continue; + } client.queue_packet(packet.clone()).await; } }