From 91ae85efa51337402c6c93b9eba1d1c9f93b2b6d Mon Sep 17 00:00:00 2001 From: Snowiiii Date: Tue, 22 Oct 2024 17:40:26 +0200 Subject: [PATCH] Add new player to server list --- pumpkin/src/client/client_packet.rs | 3 +- pumpkin/src/main.rs | 8 ++++-- pumpkin/src/server/connection_cache.rs | 38 +++++++++++++++++++++----- pumpkin/src/server/mod.rs | 21 ++++++++++---- 4 files changed, 54 insertions(+), 16 deletions(-) diff --git a/pumpkin/src/client/client_packet.rs b/pumpkin/src/client/client_packet.rs index 05e57d5c2..821571a1e 100644 --- a/pumpkin/src/client/client_packet.rs +++ b/pumpkin/src/client/client_packet.rs @@ -61,7 +61,8 @@ impl Client { pub async fn handle_status_request(&self, server: &Server, _status_request: SStatusRequest) { log::debug!("Handling status request for id {}", self.id); - self.send_packet(&server.get_status()).await; + let status = server.get_status(); + self.send_packet(&status.lock().await.get_status()).await; } pub async fn handle_ping_request(&self, ping_request: SStatusPingRequest) { diff --git a/pumpkin/src/main.rs b/pumpkin/src/main.rs index 0e0fcde60..0d8422e88 100644 --- a/pumpkin/src/main.rs +++ b/pumpkin/src/main.rs @@ -171,7 +171,7 @@ async fn main() -> io::Result<()> { ticker.run(&server).await; }); } - let mut unique_id = 0; + let mut player_count = 0; loop { // Asynchronously wait for an inbound socket. let (connection, address) = listener.accept().await?; @@ -180,8 +180,8 @@ async fn main() -> io::Result<()> { log::warn!("failed to set TCP_NODELAY {e}"); } - unique_id += 1; - let id = unique_id; + player_count += 1; + let id = player_count; log::info!( "Accepted connection from: {} (id: {})", @@ -223,7 +223,9 @@ async fn main() -> io::Result<()> { }; } player.remove().await; + server.remove_player().await; } }); + player_count -= 1; } } diff --git a/pumpkin/src/server/connection_cache.rs b/pumpkin/src/server/connection_cache.rs index 0dd34b61a..49eeff040 100644 --- a/pumpkin/src/server/connection_cache.rs +++ b/pumpkin/src/server/connection_cache.rs @@ -10,7 +10,7 @@ use base64::{engine::general_purpose, Engine as _}; use pumpkin_config::{BasicConfiguration, BASIC_CONFIG}; use pumpkin_protocol::{ client::{config::CPluginMessage, status::CStatusResponse}, - Players, Sample, StatusResponse, VarInt, Version, CURRENT_MC_PROTOCOL, + Players, StatusResponse, VarInt, Version, CURRENT_MC_PROTOCOL, }; use super::CURRENT_MC_VERSION; @@ -39,7 +39,7 @@ fn load_icon_from_bytes(png_data: &[u8]) -> Result } pub struct CachedStatus { - _status_response: StatusResponse, + status_response: StatusResponse, // We cache the json response here so we don't parse it every time someone makes a Status request. // Keep in mind that we must parse this again, when the StatusResponse changes which usually happen when a player joins or leaves status_response_json: String, @@ -76,7 +76,7 @@ impl CachedStatus { .expect("Failed to parse Status response into JSON"); Self { - _status_response: status_response, + status_response, status_response_json, } } @@ -85,6 +85,27 @@ impl CachedStatus { CStatusResponse::new(&self.status_response_json) } + // TODO: Player samples + pub fn add_player(&mut self) { + let status_response = &mut self.status_response; + if let Some(players) = &mut status_response.players { + players.online += 1; + } + + self.status_response_json = serde_json::to_string(&status_response) + .expect("Failed to parse Status response into JSON"); + } + + pub fn remove_player(&mut self) { + let status_response = &mut self.status_response; + if let Some(players) = &mut status_response.players { + players.online -= 1; + } + + self.status_response_json = serde_json::to_string(&status_response) + .expect("Failed to parse Status response into JSON"); + } + pub fn build_response(config: &BasicConfiguration) -> StatusResponse { let icon = if config.use_favicon { let icon_path = &config.favicon_path; @@ -112,10 +133,7 @@ impl CachedStatus { players: Some(Players { max: config.max_players, online: 0, - sample: vec![Sample { - name: String::new(), - id: String::new(), - }], + sample: vec![], }), description: config.motd.clone(), favicon: icon, @@ -123,3 +141,9 @@ impl CachedStatus { } } } + +impl Default for CachedStatus { + fn default() -> Self { + Self::new() + } +} diff --git a/pumpkin/src/server/mod.rs b/pumpkin/src/server/mod.rs index 5a72102c4..8d264a191 100644 --- a/pumpkin/src/server/mod.rs +++ b/pumpkin/src/server/mod.rs @@ -6,7 +6,6 @@ use pumpkin_entity::EntityId; use pumpkin_inventory::drag_handler::DragHandler; use pumpkin_inventory::{Container, OpenContainer}; use pumpkin_protocol::client::login::CEncryptionRequest; -use pumpkin_protocol::client::status::CStatusResponse; use pumpkin_protocol::{client::config::CPluginMessage, ClientPacket}; use pumpkin_registry::Registry; use pumpkin_world::dimension::Dimension; @@ -37,7 +36,7 @@ pub const CURRENT_MC_VERSION: &str = "1.21.1"; pub struct Server { key_store: KeyStore, - server_listing: CachedStatus, + server_listing: Mutex, server_branding: CachedBranding, pub command_dispatcher: Arc>, @@ -89,7 +88,7 @@ impl Server { command_dispatcher: Arc::new(command_dispatcher), auth_client, key_store: KeyStore::new(), - server_listing: CachedStatus::new(), + server_listing: Mutex::new(CachedStatus::new()), server_branding: CachedBranding::new(), } } @@ -106,9 +105,21 @@ impl Server { let player = Arc::new(Player::new(client, world.clone(), entity_id, gamemode).await); world.add_player(id, player.clone()).await; + // TODO: Config if we want increase online + if let Some(config) = player.client.config.lock().await.as_ref() { + // TODO: Config so we can also just ignore this hehe + if config.server_listing { + self.server_listing.lock().await.add_player(); + } + } (player, world.clone()) } + pub async fn remove_player(&self) { + // TODO: Config if we want increase online + self.server_listing.lock().await.remove_player(); + } + pub async fn try_get_container( &self, player_id: EntityId, @@ -151,8 +162,8 @@ impl Server { self.server_branding.get_branding() } - pub fn get_status(&self) -> CStatusResponse<'_> { - self.server_listing.get_status() + pub fn get_status(&self) -> &Mutex { + &self.server_listing } pub fn encryption_request<'a>(