From fa114e7e23f92b6928272a99860e6c2db660c512 Mon Sep 17 00:00:00 2001 From: lukas0008 Date: Sun, 8 Sep 2024 17:44:09 +0200 Subject: [PATCH] Cleanup Server struct This cleanup's goal is to make all `Server` functions only require &self. This means that `Server` can now be a `Arc` instead of `Arc>`, which solves a lot of deadlock problems. --- pumpkin-inventory/src/open_container.rs | 8 ++-- pumpkin/src/client/authentication.rs | 12 +++--- pumpkin/src/client/client_packet.rs | 29 +++++++------- pumpkin/src/client/container.rs | 51 ++++++++++++++----------- pumpkin/src/client/mod.rs | 5 ++- pumpkin/src/client/player_packet.rs | 44 +++++++++++---------- pumpkin/src/commands/cmd_echest.rs | 20 ++++++---- pumpkin/src/commands/dispatcher.rs | 7 ++-- pumpkin/src/commands/mod.rs | 8 ++++ pumpkin/src/commands/tree.rs | 9 ++--- pumpkin/src/commands/tree_builder.rs | 18 +++------ pumpkin/src/entity/player.rs | 4 +- pumpkin/src/main.rs | 14 +++---- pumpkin/src/rcon/mod.rs | 20 ++-------- pumpkin/src/server/mod.rs | 18 ++++++--- 15 files changed, 136 insertions(+), 131 deletions(-) diff --git a/pumpkin-inventory/src/open_container.rs b/pumpkin-inventory/src/open_container.rs index df052755f..25207d018 100644 --- a/pumpkin-inventory/src/open_container.rs +++ b/pumpkin-inventory/src/open_container.rs @@ -1,14 +1,14 @@ use crate::{Container, WindowType}; use pumpkin_world::item::ItemStack; -use std::sync::Mutex; +use std::sync::{Arc, Mutex}; pub struct OpenContainer { players: Vec, - container: Mutex>, + container: Arc>>, } impl OpenContainer { - pub fn try_open(&self, player_id: i32) -> Option<&Mutex>> { + pub fn try_open(&self, player_id: i32) -> Option<&Arc>>> { if !self.players.contains(&player_id) { dbg!("couldn't open container"); return None; @@ -38,7 +38,7 @@ impl OpenContainer { pub fn empty(player_id: i32) -> Self { Self { players: vec![player_id], - container: Mutex::new(Box::new(Chest::new())), + container: Arc::new(Mutex::new(Box::new(Chest::new()))), } } diff --git a/pumpkin/src/client/authentication.rs b/pumpkin/src/client/authentication.rs index 1320d934d..60d6c5523 100644 --- a/pumpkin/src/client/authentication.rs +++ b/pumpkin/src/client/authentication.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, net::IpAddr}; +use std::{collections::HashMap, net::IpAddr, sync::Arc}; use base64::{engine::general_purpose, Engine}; use num_bigint::BigInt; @@ -13,13 +13,13 @@ use uuid::Uuid; use crate::server::Server; #[derive(Deserialize, Clone, Debug)] -#[expect(non_snake_case)] #[expect(dead_code)] +#[serde(rename_all = "camelCase")] pub struct ProfileTextures { timestamp: i64, - profileId: Uuid, - profileName: String, - signatureRequired: bool, + profile_id: Uuid, + profile_name: String, + signature_required: bool, textures: HashMap, } @@ -43,7 +43,7 @@ pub async fn authenticate( username: &str, server_hash: &str, ip: &IpAddr, - server: &mut Server, + server: &Arc, ) -> Result { assert!(ADVANCED_CONFIG.authentication.enabled); assert!(server.auth_client.is_some()); diff --git a/pumpkin/src/client/client_packet.rs b/pumpkin/src/client/client_packet.rs index 43a8e865d..8f43fc21c 100644 --- a/pumpkin/src/client/client_packet.rs +++ b/pumpkin/src/client/client_packet.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use num_traits::FromPrimitive; use pumpkin_config::{ADVANCED_CONFIG, BASIC_CONFIG}; use pumpkin_core::text::TextComponent; @@ -35,7 +37,7 @@ use super::{ /// NEVER TRUST THE CLIENT. HANDLE EVERY ERROR, UNWRAP/EXPECT /// TODO: REMOVE ALL UNWRAPS impl Client { - pub fn handle_handshake(&mut self, _server: &mut Server, handshake: SHandShake) { + pub fn handle_handshake(&mut self, _server: &Arc, handshake: SHandShake) { dbg!("handshake"); self.protocol_version = handshake.protocol_version.0; self.connection_state = handshake.next_state; @@ -53,24 +55,21 @@ impl Client { } } - pub fn handle_status_request(&mut self, server: &mut Server, _status_request: SStatusRequest) { + pub fn handle_status_request(&mut self, server: &Arc, _status_request: SStatusRequest) { self.send_packet(&CStatusResponse::new(&server.status_response_json)); } - pub fn handle_ping_request(&mut self, _server: &mut Server, ping_request: SStatusPingRequest) { + pub fn handle_ping_request(&mut self, _server: &Arc, ping_request: SStatusPingRequest) { dbg!("ping"); self.send_packet(&CPingResponse::new(ping_request.payload)); self.close(); } fn is_valid_player_name(name: &str) -> bool { - name.len() <= 16 - && name - .chars() - .all(|c| c > 32 as u8 as char && c < 127 as u8 as char) + name.len() <= 16 && name.chars().all(|c| c > 32 as char && c < 127 as char) } - pub fn handle_login_start(&mut self, server: &mut Server, login_start: SLoginStart) { + pub fn handle_login_start(&mut self, server: &Arc, login_start: SLoginStart) { log::debug!("login start, State {:?}", self.connection_state); if !Self::is_valid_player_name(&login_start.name) { @@ -107,7 +106,7 @@ impl Client { pub async fn handle_encryption_response( &mut self, - server: &mut Server, + server: &Arc, encryption_response: SEncryptionResponse, ) { let shared_secret = server @@ -185,14 +184,14 @@ impl Client { pub fn handle_plugin_response( &mut self, - _server: &mut Server, + _server: &Arc, _plugin_response: SLoginPluginResponse, ) { } pub fn handle_login_acknowledged( &mut self, - server: &mut Server, + server: &Arc, _login_acknowledged: SLoginAcknowledged, ) { self.connection_state = ConnectionState::Config; @@ -227,7 +226,7 @@ impl Client { } pub fn handle_client_information_config( &mut self, - _server: &mut Server, + _server: &Arc, client_information: SClientInformationConfig, ) { dbg!("got client settings"); @@ -243,7 +242,7 @@ impl Client { }); } - pub fn handle_plugin_message(&mut self, _server: &mut Server, plugin_message: SPluginMessage) { + pub fn handle_plugin_message(&mut self, _server: &Arc, plugin_message: SPluginMessage) { if plugin_message.channel.starts_with("minecraft:brand") || plugin_message.channel.starts_with("MC|Brand") { @@ -255,7 +254,7 @@ impl Client { } } - pub fn handle_known_packs(&mut self, server: &mut Server, _config_acknowledged: SKnownPacks) { + pub fn handle_known_packs(&mut self, server: &Arc, _config_acknowledged: SKnownPacks) { for registry in &server.cached_registry { self.send_packet(&CRegistryData::new( ®istry.registry_id, @@ -270,7 +269,7 @@ impl Client { pub async fn handle_config_acknowledged( &mut self, - _server: &mut Server, + _server: &Arc, _config_acknowledged: SAcknowledgeFinishConfig, ) { dbg!("config acknowledged"); diff --git a/pumpkin/src/client/container.rs b/pumpkin/src/client/container.rs index eb9a2f97a..68b4391b9 100644 --- a/pumpkin/src/client/container.rs +++ b/pumpkin/src/client/container.rs @@ -19,11 +19,12 @@ use pumpkin_world::item::ItemStack; use std::sync::{Arc, Mutex}; impl Player { - pub fn open_container(&mut self, server: &mut Server, minecraft_menu_id: &str) { + pub fn open_container(&mut self, server: &Arc, minecraft_menu_id: &str) { self.inventory.state_id = 0; let total_opened_containers = self.inventory.total_opened_containers; - let mut container = self - .get_open_container(server) + let container = self.get_open_container(server); + let mut container = container + .as_ref() .map(|container| container.lock().unwrap()); let menu_protocol_id = (*pumpkin_world::global_registry::REGISTRY .get("minecraft:menu") @@ -97,11 +98,12 @@ impl Player { pub async fn handle_click_container( &mut self, - server: &mut Server, + server: &Arc, packet: SClickContainer, ) -> Result<(), InventoryError> { - let mut opened_container = self - .get_open_container(server) + let opened_container = self.get_open_container(server); + let mut opened_container = opened_container + .as_ref() .map(|container| container.lock().unwrap()); let drag_handler = &server.drag_handler; @@ -165,7 +167,10 @@ impl Player { } self.mouse_drag(drag_handler, opened_container.as_deref_mut(), drag_state) } - ClickType::DropType(_drop_type) => {dbg!("todo"); Ok(())}, + ClickType::DropType(_drop_type) => { + dbg!("todo"); + Ok(()) + } }?; if let Some(mut opened_container) = opened_container { if update_whole_container { @@ -355,14 +360,19 @@ impl Player { &mut self, server: &Server, ) -> Vec>> { - let player_ids = server - .open_containers - .get(&self.open_container.unwrap()) - .unwrap() - .all_player_ids() - .into_iter() - .filter(|player_id| *player_id != self.entity_id()) - .collect_vec(); + let player_ids = { + let open_containers = server + .open_containers + .read() + .expect("open_containers is poisoned"); + open_containers + .get(&self.open_container.unwrap()) + .unwrap() + .all_player_ids() + .into_iter() + .filter(|player_id| *player_id != self.entity_id()) + .collect_vec() + }; let player_token = self.client.token; // TODO: Figure out better way to get only the players from player_ids @@ -415,19 +425,14 @@ impl Player { for player in players { let mut player = player.lock().unwrap(); - let mut container = player - .get_open_container(server) - .map(|container| container.lock().unwrap()); + let container = player.get_open_container(server); + let mut container = container.as_ref().map(|v| v.lock().unwrap()); player.set_container_content(container.as_deref_mut()); - drop(container) } Ok(()) } - pub fn get_open_container<'a>( - &self, - server: &'a Server, - ) -> Option<&'a Mutex>> { + pub fn get_open_container(&self, server: &Server) -> Option>>> { if let Some(id) = self.open_container { server.try_get_container(self.entity_id(), id) } else { diff --git a/pumpkin/src/client/mod.rs b/pumpkin/src/client/mod.rs index eadb15632..7a7d9ba05 100644 --- a/pumpkin/src/client/mod.rs +++ b/pumpkin/src/client/mod.rs @@ -1,6 +1,7 @@ use std::{ io::{self, Write}, net::SocketAddr, + sync::Arc, }; use crate::{ @@ -148,7 +149,7 @@ impl Client { Ok(()) } - pub async fn process_packets(&mut self, server: &mut Server) { + pub async fn process_packets(&mut self, server: &Arc) { while let Some(mut packet) = self.client_packets_queue.pop() { match self.handle_packet(server, &mut packet).await { Ok(_) => {} @@ -164,7 +165,7 @@ impl Client { /// Handles an incoming decoded not Play state Packet pub async fn handle_packet( &mut self, - server: &mut Server, + server: &Arc, packet: &mut RawPacket, ) -> Result<(), DeserializerError> { // TODO: handle each packet's Error instead of calling .unwrap() diff --git a/pumpkin/src/client/player_packet.rs b/pumpkin/src/client/player_packet.rs index 1a2c872c8..ac40d57b1 100644 --- a/pumpkin/src/client/player_packet.rs +++ b/pumpkin/src/client/player_packet.rs @@ -1,4 +1,4 @@ -use std::f32::consts::PI; +use std::{f32::consts::PI, sync::Arc}; use crate::{ commands::CommandSender, @@ -43,7 +43,7 @@ fn modulus(a: f32, b: f32) -> f32 { impl Player { pub fn handle_confirm_teleport( &mut self, - _server: &mut Server, + _server: &Arc, confirm_teleport: SConfirmTeleport, ) { if let Some((id, position)) = self.awaiting_teleport.as_ref() { @@ -70,7 +70,7 @@ impl Player { pos.clamp(-2.0E7, 2.0E7) } - pub async fn handle_position(&mut self, _server: &mut Server, position: SPlayerPosition) { + pub async fn handle_position(&mut self, _server: &Arc, position: SPlayerPosition) { if position.x.is_nan() || position.feet_y.is_nan() || position.z.is_nan() { self.kick(TextComponent::text("Invalid movement")); return; @@ -118,7 +118,7 @@ impl Player { pub async fn handle_position_rotation( &mut self, - _server: &mut Server, + _server: &Arc, position_rotation: SPlayerPositionRotation, ) { if position_rotation.x.is_nan() @@ -188,7 +188,7 @@ impl Player { player_chunker::update_position(&world, self).await; } - pub async fn handle_rotation(&mut self, _server: &mut Server, rotation: SPlayerRotation) { + pub async fn handle_rotation(&mut self, _server: &Arc, rotation: SPlayerRotation) { if !rotation.yaw.is_finite() || !rotation.pitch.is_finite() { self.kick(TextComponent::text("Invalid rotation")); return; @@ -213,16 +213,16 @@ impl Player { world.broadcast_packet(&[self.client.token], &packet); } - pub fn handle_chat_command(&mut self, server: &mut Server, command: SChatCommand) { + pub fn handle_chat_command(&mut self, server: &Arc, command: SChatCommand) { let dispatcher = server.command_dispatcher.clone(); dispatcher.handle_command(&mut CommandSender::Player(self), server, &command.command); } - pub fn handle_player_ground(&mut self, _server: &mut Server, ground: SSetPlayerGround) { + pub fn handle_player_ground(&mut self, _server: &Arc, ground: SSetPlayerGround) { self.entity.on_ground = ground.on_ground; } - pub async fn handle_player_command(&mut self, _server: &mut Server, command: SPlayerCommand) { + pub async fn handle_player_command(&mut self, _server: &Arc, command: SPlayerCommand) { if command.entity_id != self.entity.entity_id.into() { return; } @@ -267,7 +267,7 @@ impl Player { } } - pub async fn handle_swing_arm(&mut self, _server: &mut Server, swing_arm: SSwingArm) { + pub async fn handle_swing_arm(&mut self, _server: &Arc, swing_arm: SSwingArm) { match Hand::from_i32(swing_arm.hand.0) { Some(hand) => { let animation = match hand { @@ -287,7 +287,7 @@ impl Player { }; } - pub async fn handle_chat_message(&mut self, _server: &mut Server, chat_message: SChatMessage) { + pub async fn handle_chat_message(&mut self, _server: &Arc, chat_message: SChatMessage) { dbg!("got message"); let message = chat_message.message; @@ -331,7 +331,7 @@ impl Player { pub fn handle_client_information_play( &mut self, - _server: &mut Server, + _server: &Arc, client_information: SClientInformationPlay, ) { if let (Some(main_hand), Some(chat_mode)) = ( @@ -353,7 +353,7 @@ impl Player { } } - pub async fn handle_interact(&mut self, _: &mut Server, interact: SInteract) { + pub async fn handle_interact(&mut self, _: &Arc, interact: SInteract) { let sneaking = interact.sneaking; if self.entity.sneaking != sneaking { self.entity.set_sneaking(&mut self.client, sneaking).await; @@ -422,7 +422,7 @@ impl Player { } pub async fn handle_player_action( &mut self, - _server: &mut Server, + _server: &Arc, player_action: SPlayerAction, ) { match Status::from_i32(player_action.status.0) { @@ -497,12 +497,12 @@ impl Player { } } - pub fn handle_play_ping_request(&mut self, _server: &mut Server, request: SPlayPingRequest) { + pub fn handle_play_ping_request(&mut self, _server: &Arc, request: SPlayPingRequest) { self.client .send_packet(&CPingResponse::new(request.payload)); } - pub async fn handle_use_item_on(&mut self, _server: &mut Server, use_item_on: SUseItemOn) { + pub async fn handle_use_item_on(&mut self, _server: &Arc, use_item_on: SUseItemOn) { let location = use_item_on.location; if !self.can_interact_with_block_at(&location, 1.0) { @@ -539,12 +539,12 @@ impl Player { } } - pub fn handle_use_item(&mut self, _server: &mut Server, _use_item: SUseItem) { + pub fn handle_use_item(&mut self, _server: &Arc, _use_item: SUseItem) { // TODO: handle packet correctly log::error!("An item was used(SUseItem), but the packet is not implemented yet"); } - pub fn handle_set_held_item(&mut self, _server: &mut Server, held: SSetHeldItem) { + pub fn handle_set_held_item(&mut self, _server: &Arc, held: SSetHeldItem) { let slot = held.slot; if !(0..=8).contains(&slot) { self.kick(TextComponent::text("Invalid held slot")) @@ -554,7 +554,7 @@ impl Player { pub fn handle_set_creative_slot( &mut self, - _server: &mut Server, + _server: &Arc, packet: SSetCreativeSlot, ) -> Result<(), InventoryError> { if self.gamemode != GameMode::Creative { @@ -567,11 +567,15 @@ impl Player { // TODO: // This function will in the future be used to keep track of if the client is in a valid state. // But this is not possible yet - pub fn handle_close_container(&mut self, server: &mut Server, packet: SCloseContainer) { + pub fn handle_close_container(&mut self, server: &Arc, packet: SCloseContainer) { // window_id 0 represents both 9x1 Generic AND inventory here self.inventory.state_id = 0; if let Some(id) = self.open_container { - if let Some(container) = server.open_containers.get_mut(&id) { + let mut open_containers = server + .open_containers + .write() + .expect("open_containers got poisoned"); + if let Some(container) = open_containers.get_mut(&id) { container.remove_player(self.entity_id()) } self.open_container = None; diff --git a/pumpkin/src/commands/cmd_echest.rs b/pumpkin/src/commands/cmd_echest.rs index d082ad1d3..c942d4c31 100644 --- a/pumpkin/src/commands/cmd_echest.rs +++ b/pumpkin/src/commands/cmd_echest.rs @@ -12,13 +12,19 @@ pub(crate) fn init_command_tree<'a>() -> CommandTree<'a> { if let Some(player) = sender.as_mut_player() { let entity_id = player.entity_id(); player.open_container = Some(0); - match server.open_containers.get_mut(&0) { - Some(ender_chest) => { - ender_chest.add_player(entity_id); - } - None => { - let open_container = OpenContainer::empty(entity_id); - server.open_containers.insert(0, open_container); + { + let mut open_containers = server + .open_containers + .write() + .expect("open_containers got poisoned"); + match open_containers.get_mut(&0) { + Some(ender_chest) => { + ender_chest.add_player(entity_id); + } + None => { + let open_container = OpenContainer::empty(entity_id); + open_containers.insert(0, open_container); + } } } player.open_container(server, "minecraft:generic_9x3"); diff --git a/pumpkin/src/commands/dispatcher.rs b/pumpkin/src/commands/dispatcher.rs index 04ccc3b77..e22f709df 100644 --- a/pumpkin/src/commands/dispatcher.rs +++ b/pumpkin/src/commands/dispatcher.rs @@ -7,6 +7,7 @@ use crate::commands::tree::{Command, CommandTree, ConsumedArgs, NodeType, RawArg use crate::commands::CommandSender; use crate::server::Server; use std::collections::HashMap; +use std::sync::Arc; #[derive(Debug)] pub(crate) enum InvalidTreeError { @@ -26,7 +27,7 @@ pub struct CommandDispatcher<'a> { /// Stores registered [CommandTree]s and dispatches commands to them. impl<'a> CommandDispatcher<'a> { - pub fn handle_command(&self, sender: &mut CommandSender, server: &mut Server, cmd: &str) { + pub fn handle_command(&self, sender: &mut CommandSender, server: &Arc, cmd: &str) { if let Err(err) = self.dispatch(sender, server, cmd) { sender.send_message( TextComponent::text(&err).color_named(pumpkin_core::text::color::NamedColor::Red), @@ -38,7 +39,7 @@ impl<'a> CommandDispatcher<'a> { pub(crate) fn dispatch( &'a self, src: &mut CommandSender, - server: &mut Server, + server: &Arc, cmd: &str, ) -> Result<(), String> { let mut parts = cmd.split_ascii_whitespace(); @@ -86,7 +87,7 @@ impl<'a> CommandDispatcher<'a> { fn try_is_fitting_path( src: &mut CommandSender, - server: &mut Server, + server: &Arc, path: Vec, tree: &CommandTree, mut raw_args: RawArgs, diff --git a/pumpkin/src/commands/mod.rs b/pumpkin/src/commands/mod.rs index f03a65014..3b3350b0d 100644 --- a/pumpkin/src/commands/mod.rs +++ b/pumpkin/src/commands/mod.rs @@ -1,7 +1,12 @@ +use std::sync::Arc; + +use dispatcher::InvalidTreeError; use pumpkin_core::text::TextComponent; +use tree::ConsumedArgs; use crate::commands::dispatcher::CommandDispatcher; use crate::entity::player::Player; +use crate::server::Server; mod arg_player; mod cmd_echest; mod cmd_gamemode; @@ -73,3 +78,6 @@ pub fn default_dispatcher<'a>() -> CommandDispatcher<'a> { dispatcher } + +type RunFunctionType = (dyn Fn(&mut CommandSender, &Arc, &ConsumedArgs) -> Result<(), InvalidTreeError> + + Sync); diff --git a/pumpkin/src/commands/tree.rs b/pumpkin/src/commands/tree.rs index 63243be59..6f1d8517f 100644 --- a/pumpkin/src/commands/tree.rs +++ b/pumpkin/src/commands/tree.rs @@ -1,8 +1,6 @@ -use std::collections::{HashMap, VecDeque}; - -use crate::commands::dispatcher::InvalidTreeError; +use super::RunFunctionType; use crate::commands::CommandSender; -use crate::server::Server; +use std::collections::{HashMap, VecDeque}; /// see [crate::commands::tree_builder::argument] pub(crate) type RawArgs<'a> = Vec<&'a str>; @@ -20,8 +18,7 @@ pub(crate) struct Node<'a> { pub(crate) enum NodeType<'a> { ExecuteLeaf { - run: &'a (dyn Fn(&mut CommandSender, &mut Server, &ConsumedArgs) -> Result<(), InvalidTreeError> - + Sync), + run: &'a RunFunctionType, }, Literal { string: &'a str, diff --git a/pumpkin/src/commands/tree_builder.rs b/pumpkin/src/commands/tree_builder.rs index acb285259..00a5449f1 100644 --- a/pumpkin/src/commands/tree_builder.rs +++ b/pumpkin/src/commands/tree_builder.rs @@ -1,7 +1,7 @@ -use crate::commands::dispatcher::InvalidTreeError; -use crate::commands::tree::{ArgumentConsumer, CommandTree, ConsumedArgs, Node, NodeType}; +use crate::commands::tree::{ArgumentConsumer, CommandTree, Node, NodeType}; use crate::commands::CommandSender; -use crate::server::Server; + +use super::RunFunctionType; impl<'a> CommandTree<'a> { /// Add a child [Node] to the root of this [CommandTree]. @@ -40,11 +40,7 @@ impl<'a> CommandTree<'a> { /// desired type. /// /// Also see [NonLeafNodeBuilder::execute]. - pub fn execute( - mut self, - run: &'a (dyn Fn(&mut CommandSender, &mut Server, &ConsumedArgs) -> Result<(), InvalidTreeError> - + Sync), - ) -> Self { + pub fn execute(mut self, run: &'a RunFunctionType) -> Self { let node = Node { node_type: NodeType::ExecuteLeaf { run }, children: Vec::new(), @@ -117,11 +113,7 @@ impl<'a> NonLeafNodeBuilder<'a> { /// desired type. /// /// Also see [CommandTree::execute]. - pub fn execute( - mut self, - run: &'a (dyn Fn(&mut CommandSender, &mut Server, &ConsumedArgs) -> Result<(), InvalidTreeError> - + Sync), - ) -> Self { + pub fn execute(mut self, run: &'a RunFunctionType) -> Self { self.leaf_nodes.push(LeafNodeBuilder { node_type: NodeType::ExecuteLeaf { run }, }); diff --git a/pumpkin/src/entity/player.rs b/pumpkin/src/entity/player.rs index 647333c83..774d308ec 100644 --- a/pumpkin/src/entity/player.rs +++ b/pumpkin/src/entity/player.rs @@ -263,7 +263,7 @@ impl Player { } impl Player { - pub async fn process_packets(&mut self, server: &mut Server) { + pub async fn process_packets(&mut self, server: &Arc) { while let Some(mut packet) = self.client.client_packets_queue.pop() { match self.handle_play_packet(server, &mut packet).await { Ok(_) => {} @@ -278,7 +278,7 @@ impl Player { pub async fn handle_play_packet( &mut self, - server: &mut Server, + server: &Arc, packet: &mut RawPacket, ) -> Result<(), DeserializerError> { let bytebuf = &mut packet.bytebuf; diff --git a/pumpkin/src/main.rs b/pumpkin/src/main.rs index 3f88fd85d..4be8e54c6 100644 --- a/pumpkin/src/main.rs +++ b/pumpkin/src/main.rs @@ -81,12 +81,12 @@ fn main() -> io::Result<()> { let mut clients: HashMap = HashMap::new(); let mut players: HashMap>> = HashMap::new(); - let server = Arc::new(tokio::sync::Mutex::new(Server::new())); + let server = Arc::new(Server::new()); log::info!("Started Server took {}ms", time.elapsed().as_millis()); log::info!("You now can connect to the server, Listening on {}", addr); - let server1 = server.clone(); if use_console { + let server = server.clone(); tokio::spawn(async move { let stdin = std::io::stdin(); loop { @@ -96,11 +96,10 @@ fn main() -> io::Result<()> { .expect("Failed to read console line"); if !out.is_empty() { - let mut server = server1.lock().await; let dispatcher = server.command_dispatcher.clone(); dispatcher.handle_command( &mut commands::CommandSender::Console, - &mut server, + &server, &out, ); } @@ -163,8 +162,7 @@ fn main() -> io::Result<()> { let mut player = player.lock().unwrap(); player.client.poll(event).await; if !player.client.closed { - let mut server = server.lock().await; - player.process_packets(&mut server).await; + player.process_packets(&server).await; } if player.client.closed { drop(player); @@ -181,8 +179,7 @@ fn main() -> io::Result<()> { let (done, make_player) = if let Some(client) = clients.get_mut(&token) { client.poll(event).await; if !client.closed { - let mut server = server.lock().await; - client.process_packets(&mut server).await; + client.process_packets(&server).await; } (client.closed, client.make_player) } else { @@ -195,7 +192,6 @@ fn main() -> io::Result<()> { poll.registry().deregister(&mut client.connection)?; } else if make_player { let token = client.token; - let mut server = server.lock().await; let (player, world) = server.add_player(token, client).await; players.insert(token, player.clone()); let mut world = world.lock().await; diff --git a/pumpkin/src/rcon/mod.rs b/pumpkin/src/rcon/mod.rs index 126ad5735..a2cf8dfc2 100644 --- a/pumpkin/src/rcon/mod.rs +++ b/pumpkin/src/rcon/mod.rs @@ -31,10 +31,7 @@ const SERVER: Token = Token(0); pub struct RCONServer {} impl RCONServer { - pub async fn new( - config: &RCONConfig, - server: Arc>, - ) -> Result { + pub async fn new(config: &RCONConfig, server: Arc) -> Result { assert!(config.enabled, "RCON is not enabled"); let mut poll = Poll::new().unwrap(); let mut listener = TcpListener::bind(config.address).unwrap(); @@ -128,11 +125,7 @@ impl RCONClient { } } - pub async fn handle( - &mut self, - server: &Arc>, - password: &str, - ) -> bool { + pub async fn handle(&mut self, server: &Arc, password: &str) -> bool { if !self.closed { loop { match self.read_bytes() { @@ -158,11 +151,7 @@ impl RCONClient { self.closed } - async fn poll( - &mut self, - server: &Arc>, - password: &str, - ) -> Result<(), PacketError> { + async fn poll(&mut self, server: &Arc, password: &str) -> Result<(), PacketError> { loop { let packet = match self.receive_packet().await? { Some(p) => p, @@ -193,11 +182,10 @@ impl RCONClient { PacketType::ExecCommand => { if self.logged_in { let mut output = Vec::new(); - let mut server = server.lock().await; let dispatcher = server.command_dispatcher.clone(); dispatcher.handle_command( &mut crate::commands::CommandSender::Rcon(&mut output), - &mut server, + server, packet.get_body(), ); for line in output { diff --git a/pumpkin/src/server/mod.rs b/pumpkin/src/server/mod.rs index 0216d7a62..d9aaf61a3 100644 --- a/pumpkin/src/server/mod.rs +++ b/pumpkin/src/server/mod.rs @@ -11,6 +11,7 @@ use pumpkin_protocol::{ }; use pumpkin_world::dimension::Dimension; use std::collections::HashMap; +use std::sync::RwLock; use std::{ io::Cursor, path::Path, @@ -56,7 +57,7 @@ pub struct Server { /// Cache the registry so we don't have to parse it every time a player joins pub cached_registry: Vec, - pub open_containers: HashMap, + pub open_containers: RwLock>, pub drag_handler: DragHandler, entity_id: AtomicI32, @@ -104,7 +105,7 @@ impl Server { Self { plugin_loader, cached_registry: Registry::get_static(), - open_containers: HashMap::new(), + open_containers: RwLock::new(HashMap::new()), drag_handler: DragHandler::new(), // 0 is invalid entity_id: 2.into(), @@ -121,7 +122,7 @@ impl Server { } pub async fn add_player( - &mut self, + &self, token: Token, client: Client, ) -> (Arc>, Arc>) { @@ -148,8 +149,15 @@ impl Server { &self, player_id: EntityId, container_id: u64, - ) -> Option<&Mutex>> { - self.open_containers.get(&container_id)?.try_open(player_id) + ) -> Option>>> { + let open_containers = self + .open_containers + .read() + .expect("open_containers is poisoned"); + open_containers + .get(&container_id)? + .try_open(player_id) + .cloned() } /// Sends a Packet to all Players in all worlds