From 734891738f76f1c0eddd4127b77eb762e500921e Mon Sep 17 00:00:00 2001 From: ccgauche Date: Tue, 9 Mar 2021 21:16:23 +0100 Subject: [PATCH] Moved back register to a system --- common/sys/src/plugin/memory_manager.rs | 14 +- common/sys/src/state.rs | 9 +- server/src/lib.rs | 89 ++----------- server/src/login_provider.rs | 2 +- server/src/register.rs | 92 ------------- server/src/sys/msg/mod.rs | 1 + server/src/sys/msg/register.rs | 164 ++++++++++++++++++++++++ 7 files changed, 187 insertions(+), 184 deletions(-) delete mode 100644 server/src/register.rs create mode 100644 server/src/sys/msg/register.rs diff --git a/common/sys/src/plugin/memory_manager.rs b/common/sys/src/plugin/memory_manager.rs index d62f7bfb83..b13f2843fd 100644 --- a/common/sys/src/plugin/memory_manager.rs +++ b/common/sys/src/plugin/memory_manager.rs @@ -1,7 +1,7 @@ use std::sync::atomic::{AtomicPtr, AtomicU32, AtomicU64, Ordering}; use serde::{de::DeserializeOwned, Serialize}; -use specs::{shred::Fetch, Entities, ReadStorage}; +use specs::{Entities, Read, ReadStorage}; use wasmer::{Function, Memory, Value}; use common::{ @@ -11,17 +11,17 @@ use common::{ use super::errors::{MemoryAllocationError, PluginModuleError}; -pub struct EcsWorld<'a> { - pub entities: Entities<'a>, - pub health: ReadStorage<'a, Health>, - pub uid: ReadStorage<'a, Uid>, +pub struct EcsWorld<'a, 'b> { + pub entities: &'b Entities<'a>, + pub health: &'b ReadStorage<'a, Health>, + pub uid: &'b ReadStorage<'a, Uid>, //pub player: ReadStorage<'a, Player>, - pub uid_allocator: Fetch<'a, UidAllocator>, + pub uid_allocator: &'b Read<'a, UidAllocator>, } /// This structure wraps the ECS pointer to ensure safety pub struct EcsAccessManager { - ecs_pointer: AtomicPtr>, + ecs_pointer: AtomicPtr>, } impl Default for EcsAccessManager { diff --git a/common/sys/src/state.rs b/common/sys/src/state.rs index 99da5167e5..bc256766c5 100644 --- a/common/sys/src/state.rs +++ b/common/sys/src/state.rs @@ -10,6 +10,7 @@ use common::{ terrain::{Block, TerrainChunk, TerrainGrid}, time::DayPeriod, trade::Trades, + uid::UidAllocator, vol::{ReadVol, WriteVol}, }; use common_base::span; @@ -212,10 +213,10 @@ impl State { ecs.insert(match PluginMgr::from_assets() { Ok(plugin_mgr) => { let ecs_world = EcsWorld { - entities: ecs.entities(), - health: ecs.read_component(), - uid: ecs.read_component(), - uid_allocator: ecs.read_resource(), + entities: &ecs.entities(), + health: &ecs.read_component(), + uid: &ecs.read_component(), + uid_allocator: &ecs.read_resource::().into(), //player: Either::First(ecs.read_component()), }; if let Err(e) = plugin_mgr diff --git a/server/src/lib.rs b/server/src/lib.rs index 23416918bc..4ccb17dccb 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -24,7 +24,6 @@ pub mod login_provider; pub mod metrics; pub mod persistence; pub mod presence; -mod register; pub mod rtsim; pub mod settings; pub mod state_ext; @@ -59,27 +58,26 @@ use common::{ assets::AssetExt, cmd::ChatCommand, comp, - comp::{item::MaterialStatManifest, Admin, CharacterAbility, Player, Stats}, + comp::{item::MaterialStatManifest, CharacterAbility}, event::{EventBus, ServerEvent}, recipe::default_recipe_book, resources::TimeOfDay, rtsim::RtSimEntity, terrain::TerrainChunkSize, + uid::UidAllocator, vol::{ReadVol, RectVolSize}, }; use common_ecs::run_now; use common_net::{ msg::{ - CharacterInfo, ClientType, DisconnectReason, PlayerInfo, PlayerListUpdate, ServerGeneral, - ServerInfo, ServerInit, ServerMsg, WorldMapMsg, + ClientType, DisconnectReason, ServerGeneral, ServerInfo, ServerInit, ServerMsg, WorldMapMsg, }, sync::WorldSyncExt, }; #[cfg(feature = "plugins")] use common_sys::plugin::PluginMgr; use common_sys::{plugin::memory_manager::EcsWorld, state::State}; -use hashbrown::HashMap; -use metrics::{EcsSystemMetrics, PhysicsMetrics, PlayerMetrics, TickMetrics}; +use metrics::{EcsSystemMetrics, PhysicsMetrics, TickMetrics}; use network::{Network, Pid, ProtocolAddr}; use persistence::{ character_loader::{CharacterLoader, CharacterLoaderResponseKind}, @@ -498,7 +496,7 @@ impl Server { // (e.g. run before controller system) //TODO: run in parallel run_now::(&self.state.ecs()); - self.register_run(); + run_now::(&self.state.ecs()); run_now::(&self.state.ecs()); run_now::(&self.state.ecs()); run_now::(&self.state.ecs()); @@ -725,75 +723,6 @@ impl Server { self.state.cleanup(); } - pub fn register_run(&mut self) { - let world = self.state_mut().ecs_mut(); - let entities = world.entities(); - let player_metrics = world.read_resource::(); - let uids = world.read_storage::(); - let clients = world.read_storage::(); - let mut players = world.write_storage::(); - let stats = world.read_storage::(); - let mut login_provider = world.write_resource::(); - let mut admins = world.write_storage::(); - let editable_settings = world.read_resource::(); - - // Player list to send new players. - let player_list = (&uids, &players, stats.maybe(), admins.maybe()) - .join() - .map(|(uid, player, stats, admin)| { - (*uid, PlayerInfo { - is_online: true, - is_admin: admin.is_some(), - player_alias: player.alias.clone(), - character: stats.map(|stats| CharacterInfo { - name: stats.name.clone(), - }), - }) - }) - .collect::>(); - // List of new players to update player lists of all clients. - let mut new_players = Vec::new(); - - for (entity, client) in (&entities, &clients).join() { - let _ = sys::msg::try_recv_all(client, 0, |client, msg| { - register::handle_register_msg( - &world, - &player_list, - &mut new_players, - entity, - client, - &player_metrics, - &mut login_provider, - &mut admins, - &mut players, - &editable_settings, - msg, - ) - }); - } - - // Handle new players. - // Tell all clients to add them to the player list. - for entity in new_players { - if let (Some(uid), Some(player)) = (uids.get(entity), players.get(entity)) { - let mut lazy_msg = None; - for (_, client) in (&players, &clients).join() { - if lazy_msg.is_none() { - lazy_msg = Some(client.prepare(ServerGeneral::PlayerListUpdate( - PlayerListUpdate::Add(*uid, PlayerInfo { - player_alias: player.alias.clone(), - is_online: true, - is_admin: admins.get(entity).is_some(), - character: None, // new players will be on character select. - }), - ))); - } - lazy_msg.as_ref().map(|ref msg| client.send_prepared(&msg)); - } - } - } - } - fn initialize_client( &mut self, client: crate::connection_handler::IncomingClient, @@ -912,10 +841,10 @@ impl Server { { let plugin_manager = self.state.ecs().read_resource::(); let ecs_world = EcsWorld { - entities: self.state.ecs().entities(), - health: self.state.ecs().read_component(), - uid: self.state.ecs().read_component(), - uid_allocator: self.state.ecs().read_resource(), + entities: &self.state.ecs().entities(), + health: &self.state.ecs().read_component(), + uid: &self.state.ecs().read_component(), + uid_allocator: &self.state.ecs().read_resource::().into(), }; let rs = plugin_manager.execute_event( &ecs_world, diff --git a/server/src/login_provider.rs b/server/src/login_provider.rs index 616d0c33da..2c2e84ed88 100644 --- a/server/src/login_provider.rs +++ b/server/src/login_provider.rs @@ -57,7 +57,7 @@ impl LoginProvider { pub fn try_login( &mut self, username_or_token: &str, - world: &EcsWorld, + #[cfg(feature = "plugins")] world: &EcsWorld, #[cfg(feature = "plugins")] plugin_manager: &PluginMgr, admins: &HashSet, whitelist: &HashSet, diff --git a/server/src/register.rs b/server/src/register.rs deleted file mode 100644 index f7837354a5..0000000000 --- a/server/src/register.rs +++ /dev/null @@ -1,92 +0,0 @@ -use common::comp::{Admin, Player}; -use common_net::msg::{ - ClientRegister, PlayerInfo, PlayerListUpdate, RegisterError, ServerGeneral, - ServerRegisterAnswer, -}; - -use common_sys::plugin::memory_manager::EcsWorld; -#[cfg(feature = "plugins")] -use common_sys::plugin::PluginMgr; -use hashbrown::HashMap; -use plugin_api::Uid; -use specs::{ - shred::{Fetch, FetchMut}, - Entity, World, WorldExt, WriteStorage, -}; - -use crate::{ - client::Client, login_provider::LoginProvider, metrics::PlayerMetrics, EditableSettings, -}; - -#[allow(clippy::too_many_arguments)] -pub(crate) fn handle_register_msg( - world: &World, - player_list: &HashMap, - new_players: &mut Vec, - entity: Entity, - client: &Client, - player_metrics: &Fetch<'_, PlayerMetrics>, - login_provider: &mut FetchMut<'_, LoginProvider>, - admins: &mut WriteStorage<'_, Admin>, - players: &mut WriteStorage<'_, Player>, - editable_settings: &Fetch<'_, EditableSettings>, - msg: ClientRegister, -) -> Result<(), crate::error::Error> { - #[cfg(feature = "plugins")] - let plugin_mgr = world.read_resource::(); - let ecs_world = EcsWorld { - entities: world.entities(), - health: world.read_component(), - uid: world.read_component(), - uid_allocator: world.read_resource(), - }; - let (username, uuid) = match login_provider.try_login( - &msg.token_or_username, - &ecs_world, - #[cfg(feature = "plugins")] - &plugin_mgr, - &*editable_settings.admins, - &*editable_settings.whitelist, - &*editable_settings.banlist, - ) { - Err(err) => { - client.send(ServerRegisterAnswer::Err(err))?; - return Ok(()); - }, - Ok((username, uuid)) => (username, uuid), - }; - - let player = Player::new(username, uuid); - let is_admin = editable_settings.admins.contains(&uuid); - - if !player.is_valid() { - // Invalid player - client.send(ServerRegisterAnswer::Err(RegisterError::InvalidCharacter))?; - return Ok(()); - } - - if !players.contains(entity) { - // Add Player component to this client - let _ = players.insert(entity, player); - player_metrics.players_connected.inc(); - - // Give the Admin component to the player if their name exists in - // admin list - if is_admin { - let _ = admins.insert(entity, Admin); - } - - // Tell the client its request was successful. - client.send(ServerRegisterAnswer::Ok(()))?; - - // Send initial player list - client.send(ServerGeneral::PlayerListUpdate(PlayerListUpdate::Init( - player_list.clone(), - )))?; - - // Add to list to notify all clients of the new player - new_players.push(entity); - } - - Ok(()) -} diff --git a/server/src/sys/msg/mod.rs b/server/src/sys/msg/mod.rs index e50d09ca90..9fceb19428 100644 --- a/server/src/sys/msg/mod.rs +++ b/server/src/sys/msg/mod.rs @@ -2,6 +2,7 @@ pub mod character_screen; pub mod general; pub mod in_game; pub mod ping; +pub mod register; use crate::client::Client; use serde::de::DeserializeOwned; diff --git a/server/src/sys/msg/register.rs b/server/src/sys/msg/register.rs new file mode 100644 index 0000000000..ceb640267f --- /dev/null +++ b/server/src/sys/msg/register.rs @@ -0,0 +1,164 @@ +use crate::{ + client::Client, login_provider::LoginProvider, metrics::PlayerMetrics, EditableSettings, +}; +use common::{ + comp::{Admin, Player, Stats}, + uid::{Uid, UidAllocator}, +}; +use common_ecs::{Job, Origin, Phase, System}; +use common_net::msg::{ + CharacterInfo, ClientRegister, PlayerInfo, PlayerListUpdate, RegisterError, ServerGeneral, + ServerRegisterAnswer, +}; +use hashbrown::HashMap; +use plugin_api::Health; +use specs::{Entities, Join, Read, ReadExpect, ReadStorage, WriteExpect, WriteStorage}; + +use common_sys::plugin::memory_manager::EcsWorld; + +#[cfg(feature = "plugins")] +use common_sys::plugin::PluginMgr; + +/// This system will handle new messages from clients +#[derive(Default)] +pub struct Sys; +impl<'a> System<'a> for Sys { + #[allow(clippy::type_complexity)] + type SystemData = ( + Entities<'a>, + ReadExpect<'a, PlayerMetrics>, + ReadStorage<'a, Health>, + ReadStorage<'a, Uid>, + ReadStorage<'a, Client>, + WriteStorage<'a, Player>, + Read<'a, UidAllocator>, + Read<'a, PluginMgr>, + ReadStorage<'a, Stats>, + WriteExpect<'a, LoginProvider>, + WriteStorage<'a, Admin>, + ReadExpect<'a, EditableSettings>, + ); + + const NAME: &'static str = "msg::register"; + const ORIGIN: Origin = Origin::Server; + const PHASE: Phase = Phase::Create; + + fn run( + _job: &mut Job, + ( + entities, + player_metrics, + health_comp, + uids, + clients, + mut players, + uid_allocator, + plugin_mgr, + stats, + mut login_provider, + mut admins, + editable_settings, + ): Self::SystemData, + ) { + // Player list to send new players. + let player_list = (&uids, &players, stats.maybe(), admins.maybe()) + .join() + .map(|(uid, player, stats, admin)| { + (*uid, PlayerInfo { + is_online: true, + is_admin: admin.is_some(), + player_alias: player.alias.clone(), + character: stats.map(|stats| CharacterInfo { + name: stats.name.clone(), + }), + }) + }) + .collect::>(); + // List of new players to update player lists of all clients. + let mut new_players = Vec::new(); + + #[cfg(feature = "plugins")] + let ecs_world = EcsWorld { + entities: &entities, + health: &health_comp, + uid: &uids, + uid_allocator: &uid_allocator, + }; + + for (entity, client) in (&entities, &clients).join() { + let _ = super::try_recv_all(client, 0, |client, msg: ClientRegister| { + let (username, uuid) = match login_provider.try_login( + &msg.token_or_username, + #[cfg(feature = "plugins")] + &ecs_world, + #[cfg(feature = "plugins")] + &plugin_mgr, + &*editable_settings.admins, + &*editable_settings.whitelist, + &*editable_settings.banlist, + ) { + Err(err) => { + client.send(ServerRegisterAnswer::Err(err))?; + return Ok(()); + }, + Ok((username, uuid)) => (username, uuid), + }; + + let player = Player::new(username, uuid); + let is_admin = editable_settings.admins.contains(&uuid); + + if !player.is_valid() { + // Invalid player + client.send(ServerRegisterAnswer::Err(RegisterError::InvalidCharacter))?; + return Ok(()); + } + + if !players.contains(entity) { + // Add Player component to this client + let _ = players.insert(entity, player); + player_metrics.players_connected.inc(); + + // Give the Admin component to the player if their name exists in + // admin list + if is_admin { + let _ = admins.insert(entity, Admin); + } + + // Tell the client its request was successful. + client.send(ServerRegisterAnswer::Ok(()))?; + + // Send initial player list + client.send(ServerGeneral::PlayerListUpdate(PlayerListUpdate::Init( + player_list.clone(), + )))?; + + // Add to list to notify all clients of the new player + new_players.push(entity); + } + + Ok(()) + }); + } + + // Handle new players. + // Tell all clients to add them to the player list. + for entity in new_players { + if let (Some(uid), Some(player)) = (uids.get(entity), players.get(entity)) { + let mut lazy_msg = None; + for (_, client) in (&players, &clients).join() { + if lazy_msg.is_none() { + lazy_msg = Some(client.prepare(ServerGeneral::PlayerListUpdate( + PlayerListUpdate::Add(*uid, PlayerInfo { + player_alias: player.alias.clone(), + is_online: true, + is_admin: admins.get(entity).is_some(), + character: None, // new players will be on character select. + }), + ))); + } + lazy_msg.as_ref().map(|ref msg| client.send_prepared(&msg)); + } + } + } + } +}