diff --git a/client/src/lib.rs b/client/src/lib.rs index 2f22d94242..01c24a81c5 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -25,10 +25,9 @@ use common::{ }, event::{EventBus, LocalEvent}, msg::{ - validate_chat_msg, ChatMsgValidationError, ClientCharacterScreen, ClientGeneral, - ClientInGame, ClientIngame, ClientMsg, ClientRegister, ClientType, DisconnectReason, - InviteAnswer, Notification, PingMsg, PlayerInfo, PlayerListUpdate, RegisterError, - ServerCharacterScreen, ServerGeneral, ServerInGame, ServerInfo, ServerInit, + validate_chat_msg, ChatMsgValidationError, ClientGeneral, ClientInGame, ClientMsg, + ClientRegister, ClientType, DisconnectReason, InviteAnswer, Notification, PingMsg, + PlayerInfo, PlayerListUpdate, RegisterError, ServerGeneral, ServerInfo, ServerInit, ServerRegisterAnswer, MAX_BYTES_CHAT_MSG, }, outcome::Outcome, @@ -71,7 +70,7 @@ pub enum Event { pub struct Client { registered: bool, - in_game: Option, + in_game: Option, thread_pool: ThreadPool, pub server_info: ServerInfo, /// Just the "base" layer for LOD; currently includes colors and nothing @@ -466,39 +465,46 @@ impl Client { let msg: ClientMsg = msg.into(); #[cfg(debug_assertions)] { - // These assertions verify that the state is correct when a message is sent! - match &msg { - ClientMsg::Type(_) | ClientMsg::Register(_) => assert!( - !self.registered, - "must not send msg when already registered" - ), - ClientMsg::CharacterScreen(_) => { - assert!( - self.registered, - "must not send character_screen msg when not registered" - ); - assert!( - self.in_game.is_none(), - "must not send character_screen msg when not in character screen" - ); - }, - ClientMsg::InGame(_) => assert!( - self.in_game.is_some(), - "must not send in_game msg when not in game" - ), - ClientMsg::General(_) => assert!( - self.registered, - "must not send general msg when not registered" - ), - ClientMsg::Ping(_) => (), - } + const C_TYPE: ClientType = ClientType::Game; + let verified = msg.verify(C_TYPE, self.registered, self.in_game); + assert!( + verified, + format!( + "c_type: {:?}, registered: {}, in_game: {:?}, msg: {:?}", + C_TYPE, self.registered, self.in_game, msg + ) + ); } match msg { ClientMsg::Type(msg) => self.register_stream.send(msg), ClientMsg::Register(msg) => self.register_stream.send(msg), - ClientMsg::CharacterScreen(msg) => self.character_screen_stream.send(msg), - ClientMsg::InGame(msg) => self.in_game_stream.send(msg), - ClientMsg::General(msg) => self.general_stream.send(msg), + ClientMsg::General(msg) => { + let stream = match msg { + ClientGeneral::RequestCharacterList + | ClientGeneral::CreateCharacter { .. } + | ClientGeneral::DeleteCharacter(_) + | ClientGeneral::Character(_) + | ClientGeneral::Spectate => &mut self.character_screen_stream, + //Only in game + ClientGeneral::ControllerInputs(_) + | ClientGeneral::ControlEvent(_) + | ClientGeneral::ControlAction(_) + | ClientGeneral::SetViewDistance(_) + | ClientGeneral::BreakBlock(_) + | ClientGeneral::PlaceBlock(_, _) + | ClientGeneral::ExitInGame + | ClientGeneral::PlayerPhysics { .. } + | ClientGeneral::TerrainChunkRequest { .. } + | ClientGeneral::UnlockSkill(_) + | ClientGeneral::RefundSkill(_) + | ClientGeneral::UnlockSkillGroup(_) => &mut self.in_game_stream, + //Always possible + ClientGeneral::ChatMsg(_) + | ClientGeneral::Disconnect + | ClientGeneral::Terminate => &mut self.general_stream, + }; + stream.send(msg) + }, ClientMsg::Ping(msg) => self.ping_stream.send(msg), } } @@ -518,10 +524,10 @@ impl Client { /// Request a state transition to `ClientState::Character`. pub fn request_character(&mut self, character_id: CharacterId) { - self.send_msg(ClientCharacterScreen::Character(character_id)); + self.send_msg(ClientGeneral::Character(character_id)); //Assume we are in_game unless server tells us otherwise - self.in_game = Some(ClientIngame::Character); + self.in_game = Some(ClientInGame::Character); self.active_character_id = Some(character_id); } @@ -529,19 +535,19 @@ impl Client { /// Load the current players character list pub fn load_character_list(&mut self) { self.character_list.loading = true; - self.send_msg(ClientCharacterScreen::RequestCharacterList); + self.send_msg(ClientGeneral::RequestCharacterList); } /// New character creation pub fn create_character(&mut self, alias: String, tool: Option, body: comp::Body) { self.character_list.loading = true; - self.send_msg(ClientCharacterScreen::CreateCharacter { alias, tool, body }); + self.send_msg(ClientGeneral::CreateCharacter { alias, tool, body }); } /// Character deletion pub fn delete_character(&mut self, character_id: CharacterId) { self.character_list.loading = true; - self.send_msg(ClientCharacterScreen::DeleteCharacter(character_id)); + self.send_msg(ClientGeneral::DeleteCharacter(character_id)); } /// Send disconnect message to the server @@ -552,34 +558,34 @@ impl Client { /// Request a state transition to `ClientState::Registered` from an ingame /// state. - pub fn request_remove_character(&mut self) { self.send_msg(ClientInGame::ExitInGame); } + pub fn request_remove_character(&mut self) { self.send_msg(ClientGeneral::ExitInGame); } pub fn set_view_distance(&mut self, view_distance: u32) { self.view_distance = Some(view_distance.max(1).min(65)); - self.send_msg(ClientInGame::SetViewDistance(self.view_distance.unwrap())); + self.send_msg(ClientGeneral::SetViewDistance(self.view_distance.unwrap())); } pub fn use_slot(&mut self, slot: comp::slot::Slot) { - self.send_msg(ClientInGame::ControlEvent(ControlEvent::InventoryManip( + self.send_msg(ClientGeneral::ControlEvent(ControlEvent::InventoryManip( InventoryManip::Use(slot), ))); } pub fn swap_slots(&mut self, a: comp::slot::Slot, b: comp::slot::Slot) { - self.send_msg(ClientInGame::ControlEvent(ControlEvent::InventoryManip( + self.send_msg(ClientGeneral::ControlEvent(ControlEvent::InventoryManip( InventoryManip::Swap(a, b), ))); } pub fn drop_slot(&mut self, slot: comp::slot::Slot) { - self.send_msg(ClientInGame::ControlEvent(ControlEvent::InventoryManip( + self.send_msg(ClientGeneral::ControlEvent(ControlEvent::InventoryManip( InventoryManip::Drop(slot), ))); } pub fn pick_up(&mut self, entity: EcsEntity) { if let Some(uid) = self.state.read_component_copied(entity) { - self.send_msg(ClientInGame::ControlEvent(ControlEvent::InventoryManip( + self.send_msg(ClientGeneral::ControlEvent(ControlEvent::InventoryManip( InventoryManip::Pickup(uid), ))); } @@ -599,7 +605,7 @@ impl Client { pub fn craft_recipe(&mut self, recipe: &str) -> bool { if self.can_craft_recipe(recipe) { - self.send_msg(ClientInGame::ControlEvent(ControlEvent::InventoryManip( + self.send_msg(ClientGeneral::ControlEvent(ControlEvent::InventoryManip( InventoryManip::CraftRecipe(recipe.to_string()), ))); true @@ -618,11 +624,11 @@ impl Client { } pub fn enable_lantern(&mut self) { - self.send_msg(ClientInGame::ControlEvent(ControlEvent::EnableLantern)); + self.send_msg(ClientGeneral::ControlEvent(ControlEvent::EnableLantern)); } pub fn disable_lantern(&mut self) { - self.send_msg(ClientInGame::ControlEvent(ControlEvent::DisableLantern)); + self.send_msg(ClientGeneral::ControlEvent(ControlEvent::DisableLantern)); } pub fn max_group_size(&self) -> u32 { self.max_group_size } @@ -640,7 +646,7 @@ impl Client { pub fn pending_invites(&self) -> &HashSet { &self.pending_invites } pub fn send_group_invite(&mut self, invitee: Uid) { - self.send_msg(ClientInGame::ControlEvent(ControlEvent::GroupManip( + self.send_msg(ClientGeneral::ControlEvent(ControlEvent::GroupManip( GroupManip::Invite(invitee), ))) } @@ -648,7 +654,7 @@ impl Client { pub fn accept_group_invite(&mut self) { // Clear invite self.group_invite.take(); - self.send_msg(ClientInGame::ControlEvent(ControlEvent::GroupManip( + self.send_msg(ClientGeneral::ControlEvent(ControlEvent::GroupManip( GroupManip::Accept, ))); } @@ -656,25 +662,25 @@ impl Client { pub fn decline_group_invite(&mut self) { // Clear invite self.group_invite.take(); - self.send_msg(ClientInGame::ControlEvent(ControlEvent::GroupManip( + self.send_msg(ClientGeneral::ControlEvent(ControlEvent::GroupManip( GroupManip::Decline, ))); } pub fn leave_group(&mut self) { - self.send_msg(ClientInGame::ControlEvent(ControlEvent::GroupManip( + self.send_msg(ClientGeneral::ControlEvent(ControlEvent::GroupManip( GroupManip::Leave, ))); } pub fn kick_from_group(&mut self, uid: Uid) { - self.send_msg(ClientInGame::ControlEvent(ControlEvent::GroupManip( + self.send_msg(ClientGeneral::ControlEvent(ControlEvent::GroupManip( GroupManip::Kick(uid), ))); } pub fn assign_group_leader(&mut self, uid: Uid) { - self.send_msg(ClientInGame::ControlEvent(ControlEvent::GroupManip( + self.send_msg(ClientGeneral::ControlEvent(ControlEvent::GroupManip( GroupManip::AssignLeader(uid), ))); } @@ -697,11 +703,11 @@ impl Client { pub fn mount(&mut self, entity: EcsEntity) { if let Some(uid) = self.state.read_component_copied(entity) { - self.send_msg(ClientInGame::ControlEvent(ControlEvent::Mount(uid))); + self.send_msg(ClientGeneral::ControlEvent(ControlEvent::Mount(uid))); } } - pub fn unmount(&mut self) { self.send_msg(ClientInGame::ControlEvent(ControlEvent::Unmount)); } + pub fn unmount(&mut self) { self.send_msg(ClientGeneral::ControlEvent(ControlEvent::Unmount)); } pub fn respawn(&mut self) { if self @@ -711,7 +717,7 @@ impl Client { .get(self.entity) .map_or(false, |s| s.is_dead) { - self.send_msg(ClientInGame::ControlEvent(ControlEvent::Respawn)); + self.send_msg(ClientGeneral::ControlEvent(ControlEvent::Respawn)); } } @@ -808,7 +814,7 @@ impl Client { { controller.actions.push(control_action); } - self.send_msg(ClientInGame::ControlAction(control_action)); + self.send_msg(ClientGeneral::ControlAction(control_action)); } pub fn view_distance(&self) -> Option { self.view_distance } @@ -852,13 +858,15 @@ impl Client { } pub fn place_block(&mut self, pos: Vec3, block: Block) { - self.send_msg(ClientInGame::PlaceBlock(pos, block)); + self.send_msg(ClientGeneral::PlaceBlock(pos, block)); } - pub fn remove_block(&mut self, pos: Vec3) { self.send_msg(ClientInGame::BreakBlock(pos)); } + pub fn remove_block(&mut self, pos: Vec3) { + self.send_msg(ClientGeneral::BreakBlock(pos)); + } pub fn collect_block(&mut self, pos: Vec3) { - self.send_msg(ClientInGame::ControlEvent(ControlEvent::InventoryManip( + self.send_msg(ClientGeneral::ControlEvent(ControlEvent::InventoryManip( InventoryManip::Collect(pos), ))); } @@ -915,7 +923,7 @@ impl Client { "Couldn't access controller component on client entity" ); } - self.send_msg_err(ClientInGame::ControllerInputs(inputs))?; + self.send_msg_err(ClientGeneral::ControllerInputs(inputs))?; } // 2) Build up a list of events for this frame, to be passed to the frontend. @@ -1019,7 +1027,7 @@ impl Client { if self.state.terrain().get_key(*key).is_none() { if !skip_mode && !self.pending_chunks.contains_key(key) { if self.pending_chunks.len() < 4 { - self.send_msg_err(ClientInGame::TerrainChunkRequest { + self.send_msg_err(ClientGeneral::TerrainChunkRequest { key: *key, })?; self.pending_chunks.insert(*key, Instant::now()); @@ -1065,7 +1073,7 @@ impl Client { self.state.read_storage().get(self.entity).cloned(), ) { self.in_game_stream - .send(ClientInGame::PlayerPhysics { pos, vel, ori })?; + .send(ClientGeneral::PlayerPhysics { pos, vel, ori })?; } } @@ -1237,6 +1245,7 @@ impl Client { ServerGeneral::Notification(n) => { frontend_events.push(Event::Notification(n)); }, + _ => unreachable!("Not a general msg"), } Ok(()) } @@ -1244,10 +1253,10 @@ impl Client { fn handle_server_in_game_msg( &mut self, frontend_events: &mut Vec, - msg: ServerInGame, + msg: ServerGeneral, ) -> Result<(), Error> { match msg { - ServerInGame::GroupUpdate(change_notification) => { + ServerGeneral::GroupUpdate(change_notification) => { use comp::group::ChangeNotification::*; // Note: we use a hashmap since this would not work with entities outside // the view distance @@ -1319,15 +1328,15 @@ impl Client { }, } }, - ServerInGame::GroupInvite { inviter, timeout } => { + ServerGeneral::GroupInvite { inviter, timeout } => { self.group_invite = Some((inviter, std::time::Instant::now(), timeout)); }, - ServerInGame::InvitePending(uid) => { + ServerGeneral::InvitePending(uid) => { if !self.pending_invites.insert(uid) { warn!("Received message about pending invite that was already pending"); } }, - ServerInGame::InviteComplete { target, answer } => { + ServerGeneral::InviteComplete { target, answer } => { if !self.pending_invites.remove(&target) { warn!( "Received completed invite message for invite that was not in the list of \ @@ -1345,11 +1354,11 @@ impl Client { frontend_events.push(Event::Chat(comp::ChatType::Meta.chat_msg(msg))); }, // Cleanup for when the client goes back to the `in_game = None` - ServerInGame::ExitInGameSuccess => { + ServerGeneral::ExitInGameSuccess => { self.in_game = None; self.clean_state(); }, - ServerInGame::InventoryUpdate(mut inventory, event) => { + ServerGeneral::InventoryUpdate(mut inventory, event) => { match event { InventoryUpdateEvent::CollectFailed => {}, _ => { @@ -1363,25 +1372,25 @@ impl Client { frontend_events.push(Event::InventoryUpdated(event)); }, - ServerInGame::TerrainChunkUpdate { key, chunk } => { + ServerGeneral::TerrainChunkUpdate { key, chunk } => { if let Ok(chunk) = chunk { self.state.insert_chunk(key, *chunk); } self.pending_chunks.remove(&key); }, - ServerInGame::TerrainBlockUpdates(mut blocks) => { + ServerGeneral::TerrainBlockUpdates(mut blocks) => { blocks.drain().for_each(|(pos, block)| { self.state.set_block(pos, block); }); }, - ServerInGame::SetViewDistance(vd) => { + ServerGeneral::SetViewDistance(vd) => { self.view_distance = Some(vd); frontend_events.push(Event::SetViewDistance(vd)); }, - ServerInGame::Outcomes(outcomes) => { + ServerGeneral::Outcomes(outcomes) => { frontend_events.extend(outcomes.into_iter().map(Event::Outcome)) }, - ServerInGame::Knockback(impulse) => { + ServerGeneral::Knockback(impulse) => { self.state .ecs() .read_resource::>() @@ -1390,35 +1399,34 @@ impl Client { impulse, }); }, + _ => unreachable!("Not a in_game message"), } Ok(()) } - fn handle_server_character_screen_msg( - &mut self, - msg: ServerCharacterScreen, - ) -> Result<(), Error> { + fn handle_server_character_screen_msg(&mut self, msg: ServerGeneral) -> Result<(), Error> { match msg { - ServerCharacterScreen::CharacterListUpdate(character_list) => { + ServerGeneral::CharacterListUpdate(character_list) => { self.character_list.characters = character_list; self.character_list.loading = false; }, - ServerCharacterScreen::CharacterActionError(error) => { + ServerGeneral::CharacterActionError(error) => { warn!("CharacterActionError: {:?}.", error); self.character_list.error = Some(error); }, - ServerCharacterScreen::CharacterDataLoadError(error) => { + ServerGeneral::CharacterDataLoadError(error) => { trace!("Handling join error by server"); self.in_game = None; self.clean_state(); self.character_list.error = Some(error); }, - ServerCharacterScreen::CharacterSuccess => { + ServerGeneral::CharacterSuccess => { debug!("client is now in ingame state on server"); if let Some(vd) = self.view_distance { self.set_view_distance(vd); } }, + _ => unreachable!("Not a character_screen msg"), } Ok(()) } @@ -1518,7 +1526,7 @@ impl Client { pub fn uid(&self) -> Option { self.state.read_component_copied(self.entity) } - pub fn in_game(&self) -> Option { self.in_game } + pub fn in_game(&self) -> Option { self.in_game } pub fn registered(&self) -> bool { self.registered } diff --git a/common/src/msg/client.rs b/common/src/msg/client.rs index 2339bcab12..e8b8be3b02 100644 --- a/common/src/msg/client.rs +++ b/common/src/msg/client.rs @@ -12,16 +12,13 @@ use vek::*; /// streams though). It's used to verify the correctness of the state in /// debug_assertions #[derive(Debug, Clone)] +#[allow(clippy::clippy::large_enum_variant)] pub enum ClientMsg { ///Send on the first connection ONCE to identify client intention for /// server Type(ClientType), ///Send ONCE to register/auth to the server Register(ClientRegister), - ///Msg only to send while in character screen, e.g. `CreateCharacter` - CharacterScreen(ClientCharacterScreen), - ///Msg only to send while playing in game, e.g. `PlayerPositionUpdates` - InGame(ClientInGame), ///Msg that can be send ALWAYS as soon as we are registered, e.g. `Chat` General(ClientGeneral), Ping(PingMsg), @@ -47,9 +44,10 @@ pub struct ClientRegister { pub token_or_username: String, } -//messages send by clients only valid when in character screen -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub enum ClientCharacterScreen { +/// Messages sent from the client to the server +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum ClientGeneral { + //Only in Character Screen RequestCharacterList, CreateCharacter { alias: String, @@ -59,11 +57,7 @@ pub enum ClientCharacterScreen { DeleteCharacter(CharacterId), Character(CharacterId), Spectate, -} - -//messages send by clients only valid when in game (with a character) -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub enum ClientInGame { + //Only in game ControllerInputs(comp::ControllerInputs), ControlEvent(comp::ControlEvent), ControlAction(comp::ControlAction), @@ -82,16 +76,59 @@ pub enum ClientInGame { UnlockSkill(Skill), RefundSkill(Skill), UnlockSkillGroup(SkillGroupType), -} - -/// Messages sent from the client to the server -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum ClientGeneral { + //Always possible ChatMsg(String), Disconnect, Terminate, } +impl ClientMsg { + pub fn verify( + &self, + c_type: ClientType, + registered: bool, + in_game: Option, + ) -> bool { + match self { + ClientMsg::Type(t) => c_type == *t, + ClientMsg::Register(_) => !registered && in_game.is_none(), + ClientMsg::General(g) => { + registered + && match g { + ClientGeneral::RequestCharacterList + | ClientGeneral::CreateCharacter { .. } + | ClientGeneral::DeleteCharacter(_) => { + c_type != ClientType::ChatOnly && in_game.is_none() + }, + ClientGeneral::Character(_) | ClientGeneral::Spectate => { + c_type == ClientType::Game && in_game.is_none() + }, + //Only in game + ClientGeneral::ControllerInputs(_) + | ClientGeneral::ControlEvent(_) + | ClientGeneral::ControlAction(_) + | ClientGeneral::SetViewDistance(_) + | ClientGeneral::BreakBlock(_) + | ClientGeneral::PlaceBlock(_, _) + | ClientGeneral::ExitInGame + | ClientGeneral::PlayerPhysics { .. } + | ClientGeneral::TerrainChunkRequest { .. } + | ClientGeneral::UnlockSkill(_) + | ClientGeneral::RefundSkill(_) + | ClientGeneral::UnlockSkillGroup(_) => { + c_type == ClientType::Game && in_game.is_some() + }, + //Always possible + ClientGeneral::ChatMsg(_) + | ClientGeneral::Disconnect + | ClientGeneral::Terminate => true, + } + }, + ClientMsg::Ping(_) => true, + } + } +} + /* end of 2nd level Enums */ @@ -104,14 +141,6 @@ impl Into for ClientRegister { fn into(self) -> ClientMsg { ClientMsg::Register(self) } } -impl Into for ClientCharacterScreen { - fn into(self) -> ClientMsg { ClientMsg::CharacterScreen(self) } -} - -impl Into for ClientInGame { - fn into(self) -> ClientMsg { ClientMsg::InGame(self) } -} - impl Into for ClientGeneral { fn into(self) -> ClientMsg { ClientMsg::General(self) } } diff --git a/common/src/msg/mod.rs b/common/src/msg/mod.rs index b4ea9fe6fe..a7e4802a89 100644 --- a/common/src/msg/mod.rs +++ b/common/src/msg/mod.rs @@ -5,21 +5,18 @@ pub mod world_packet; // Reexports pub use self::{ - client::{ - ClientCharacterScreen, ClientGeneral, ClientInGame, ClientMsg, ClientRegister, ClientType, - }, + client::{ClientGeneral, ClientMsg, ClientRegister, ClientType}, ecs_packet::EcsCompPacket, server::{ CharacterInfo, DisconnectReason, InviteAnswer, Notification, PlayerInfo, PlayerListUpdate, - RegisterError, ServerCharacterScreen, ServerGeneral, ServerInGame, ServerInfo, ServerInit, - ServerMsg, ServerRegisterAnswer, + RegisterError, ServerGeneral, ServerInfo, ServerInit, ServerMsg, ServerRegisterAnswer, }, world_packet::WorldMapMsg, }; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] -pub enum ClientIngame { +pub enum ClientInGame { Spectator, Character, } diff --git a/common/src/msg/server.rs b/common/src/msg/server.rs index 82b861ef6e..b54ca91a4b 100644 --- a/common/src/msg/server.rs +++ b/common/src/msg/server.rs @@ -1,4 +1,4 @@ -use super::{EcsCompPacket, PingMsg}; +use super::{ClientType, EcsCompPacket, PingMsg}; use crate::{ character::CharacterItem, comp, @@ -24,12 +24,6 @@ pub enum ServerMsg { Init(ServerInit), /// Result to `ClientMsg::Register`. send ONCE RegisterAnswer(ServerRegisterAnswer), - /// Msg only to send when client is on the character screen, e.g. - /// `CharacterListUpdate` - CharacterScreen(ServerCharacterScreen), - /// Msg only to send when client is playing in game, e.g. - /// `TerrainChunkUpdate` - InGame(ServerInGame), ///Msg that can be send ALWAYS as soon as client is registered, e.g. `Chat` General(ServerGeneral), Ping(PingMsg), @@ -65,9 +59,10 @@ pub enum ServerInit { pub type ServerRegisterAnswer = Result<(), RegisterError>; -//Messages only allowed while client in character screen +/// Messages sent from the server to the client #[derive(Debug, Clone, Serialize, Deserialize)] -pub enum ServerCharacterScreen { +pub enum ServerGeneral { + //Character Screen related /// An error occurred while loading character data CharacterDataLoadError(String), /// A list of characters belonging to the a authenticated player was sent @@ -75,23 +70,21 @@ pub enum ServerCharacterScreen { /// An error occurred while creating or deleting a character CharacterActionError(String), CharacterSuccess, -} - -//Messages only allowed while client is in game (with a character) -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum ServerInGame { + //Ingame related GroupUpdate(comp::group::ChangeNotification), - // Indicate to the client that they are invited to join a group + /// Indicate to the client that they are invited to join a group GroupInvite { inviter: sync::Uid, timeout: std::time::Duration, }, - // Indicate to the client that their sent invite was not invalid and is currently pending + /// Indicate to the client that their sent invite was not invalid and is + /// currently pending InvitePending(sync::Uid), - // Note: this could potentially include all the failure cases such as inviting yourself in - // which case the `InvitePending` message could be removed and the client could consider their - // invite pending until they receive this message - // Indicate to the client the result of their invite + /// Note: this could potentially include all the failure cases such as + /// inviting yourself in which case the `InvitePending` message could be + /// removed and the client could consider their invite pending until + /// they receive this message Indicate to the client the result of their + /// invite InviteComplete { target: sync::Uid, answer: InviteAnswer, @@ -108,11 +101,7 @@ pub enum ServerInGame { SetViewDistance(u32), Outcomes(Vec), Knockback(Vec3), -} - -/// Messages sent from the server to the client -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum ServerGeneral { + // Always possible PlayerListUpdate(PlayerListUpdate), /// A message to go into the client chat box. The client is responsible for /// formatting the message and turning it into a speech bubble. @@ -190,6 +179,61 @@ pub enum RegisterError { //TODO: InvalidAlias, } +impl ServerMsg { + pub fn verify( + &self, + c_type: ClientType, + registered: bool, + in_game: Option, + ) -> bool { + match self { + ServerMsg::Info(_) | ServerMsg::Init(_) | ServerMsg::RegisterAnswer(_) => { + !registered && in_game.is_none() + }, + ServerMsg::General(g) => { + registered + && match g { + //Character Screen related + ServerGeneral::CharacterDataLoadError(_) + | ServerGeneral::CharacterListUpdate(_) + | ServerGeneral::CharacterActionError(_) => { + c_type != ClientType::ChatOnly && in_game.is_none() + }, + ServerGeneral::CharacterSuccess => { + c_type == ClientType::Game && in_game.is_none() + }, + //Ingame related + ServerGeneral::GroupUpdate(_) + | ServerGeneral::GroupInvite { .. } + | ServerGeneral::InvitePending(_) + | ServerGeneral::InviteComplete { .. } + | ServerGeneral::ExitInGameSuccess + | ServerGeneral::InventoryUpdate(_, _) + | ServerGeneral::TerrainChunkUpdate { .. } + | ServerGeneral::TerrainBlockUpdates(_) + | ServerGeneral::SetViewDistance(_) + | ServerGeneral::Outcomes(_) + | ServerGeneral::Knockback(_) => { + c_type == ClientType::Game && in_game.is_some() + }, + // Always possible + ServerGeneral::PlayerListUpdate(_) + | ServerGeneral::ChatMsg(_) + | ServerGeneral::SetPlayerEntity(_) + | ServerGeneral::TimeOfDay(_) + | ServerGeneral::EntitySync(_) + | ServerGeneral::CompSync(_) + | ServerGeneral::CreateEntity(_) + | ServerGeneral::DeleteEntity(_) + | ServerGeneral::Disconnect(_) + | ServerGeneral::Notification(_) => true, + } + }, + ServerMsg::Ping(_) => true, + } + } +} + impl From for RegisterError { fn from(err: AuthClientError) -> Self { Self::AuthError(err.to_string()) } } @@ -210,14 +254,6 @@ impl Into for ServerRegisterAnswer { fn into(self) -> ServerMsg { ServerMsg::RegisterAnswer(self) } } -impl Into for ServerCharacterScreen { - fn into(self) -> ServerMsg { ServerMsg::CharacterScreen(self) } -} - -impl Into for ServerInGame { - fn into(self) -> ServerMsg { ServerMsg::InGame(self) } -} - impl Into for ServerGeneral { fn into(self) -> ServerMsg { ServerMsg::General(self) } } diff --git a/server/src/client.rs b/server/src/client.rs index 9b33e6f5f8..e2bfcf6d6f 100644 --- a/server/src/client.rs +++ b/server/src/client.rs @@ -1,5 +1,5 @@ use crate::error::Error; -use common::msg::{ClientIngame, ClientType, ServerMsg}; +use common::msg::{ClientInGame, ClientType, ServerGeneral, ServerMsg}; use hashbrown::HashSet; use network::{Participant, Stream}; use serde::{de::DeserializeOwned, Serialize}; @@ -11,7 +11,7 @@ use vek::*; pub struct Client { pub registered: bool, pub client_type: ClientType, - pub in_game: Option, + pub in_game: Option, pub participant: Option, pub general_stream: Stream, pub ping_stream: Stream, @@ -59,16 +59,38 @@ impl Client { ServerMsg::RegisterAnswer(msg) => { Self::internal_send(&mut self.network_error, &mut self.register_stream, &msg) }, - ServerMsg::CharacterScreen(msg) => Self::internal_send( - &mut self.network_error, - &mut self.character_screen_stream, - &msg, - ), - ServerMsg::InGame(msg) => { - Self::internal_send(&mut self.network_error, &mut self.in_game_stream, &msg) - }, ServerMsg::General(msg) => { - Self::internal_send(&mut self.network_error, &mut self.general_stream, &msg) + let stream = match &msg { + //Character Screen related + ServerGeneral::CharacterDataLoadError(_) + | ServerGeneral::CharacterListUpdate(_) + | ServerGeneral::CharacterActionError(_) + | ServerGeneral::CharacterSuccess => &mut self.character_screen_stream, + //Ingame related + ServerGeneral::GroupUpdate(_) + | ServerGeneral::GroupInvite { .. } + | ServerGeneral::InvitePending(_) + | ServerGeneral::InviteComplete { .. } + | ServerGeneral::ExitInGameSuccess + | ServerGeneral::InventoryUpdate(_, _) + | ServerGeneral::TerrainChunkUpdate { .. } + | ServerGeneral::TerrainBlockUpdates(_) + | ServerGeneral::SetViewDistance(_) + | ServerGeneral::Outcomes(_) + | ServerGeneral::Knockback(_) => &mut self.in_game_stream, + // Always possible + ServerGeneral::PlayerListUpdate(_) + | ServerGeneral::ChatMsg(_) + | ServerGeneral::SetPlayerEntity(_) + | ServerGeneral::TimeOfDay(_) + | ServerGeneral::EntitySync(_) + | ServerGeneral::CompSync(_) + | ServerGeneral::CreateEntity(_) + | ServerGeneral::DeleteEntity(_) + | ServerGeneral::Disconnect(_) + | ServerGeneral::Notification(_) => &mut self.general_stream, + }; + Self::internal_send(&mut self.network_error, stream, &msg) }, ServerMsg::Ping(msg) => { Self::internal_send(&mut self.network_error, &mut self.ping_stream, &msg) diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 4d0b61d807..1d07f1e837 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -12,7 +12,7 @@ use common::{ cmd::{ChatCommand, CHAT_COMMANDS, CHAT_SHORTCUTS}, comp::{self, ChatType, Item, LightEmitter, WaypointArea}, event::{EventBus, ServerEvent}, - msg::{DisconnectReason, Notification, PlayerListUpdate, ServerGeneral, ServerInGame}, + msg::{DisconnectReason, Notification, PlayerListUpdate, ServerGeneral}, npc::{self, get_npc_name}, state::TimeOfDay, sync::{Uid, WorldSyncExt}, @@ -669,7 +669,9 @@ fn handle_spawn( .try_map(|e| uids.get(e).copied()) .map(|g| (g, c)) }) - .map(|(g, c)| c.send_msg(ServerInGame::GroupUpdate(g))); + .map(|(g, c)| { + c.send_msg(ServerGeneral::GroupUpdate(g)) + }); }, ); } else if let Some(group) = match alignment { diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index d480302e82..21e3221744 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -12,7 +12,7 @@ use common::{ Player, Pos, Stats, }, lottery::Lottery, - msg::{PlayerListUpdate, ServerGeneral, ServerInGame}, + msg::{PlayerListUpdate, ServerGeneral}, outcome::Outcome, state::BlockChange, sync::{Uid, UidAllocator, WorldSyncExt}, @@ -44,7 +44,7 @@ pub fn handle_knockback(server: &Server, entity: EcsEntity, impulse: Vec3) } let mut clients = state.ecs().write_storage::(); if let Some(client) = clients.get_mut(entity) { - client.send_msg(ServerInGame::Knockback(impulse)); + client.send_msg(ServerGeneral::Knockback(impulse)); } } diff --git a/server/src/events/group_manip.rs b/server/src/events/group_manip.rs index bbaf5c0b32..78c0df462b 100644 --- a/server/src/events/group_manip.rs +++ b/server/src/events/group_manip.rs @@ -5,7 +5,7 @@ use common::{ group::{self, Group, GroupManager, Invite, PendingInvites}, ChatType, GroupManip, }, - msg::{InviteAnswer, ServerInGame}, + msg::{InviteAnswer, ServerGeneral}, sync, sync::WorldSyncExt, }; @@ -155,7 +155,7 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani (clients.get_mut(invitee), uids.get(entity).copied()) { if send_invite() { - client.send_msg(ServerInGame::GroupInvite { + client.send_msg(ServerGeneral::GroupInvite { inviter, timeout: PRESENTED_INVITE_TIMEOUT_DUR, }); @@ -171,7 +171,7 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani // Notify inviter that the invite is pending if invite_sent { if let Some(client) = clients.get_mut(entity) { - client.send_msg(ServerInGame::InvitePending(uid)); + client.send_msg(ServerGeneral::InvitePending(uid)); } } }, @@ -196,7 +196,7 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani if let (Some(client), Some(target)) = (clients.get_mut(inviter), uids.get(entity).copied()) { - client.send_msg(ServerInGame::InviteComplete { + client.send_msg(ServerGeneral::InviteComplete { target, answer: InviteAnswer::Accepted, }) @@ -217,7 +217,7 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani .try_map(|e| uids.get(e).copied()) .map(|g| (g, c)) }) - .map(|(g, c)| c.send_msg(ServerInGame::GroupUpdate(g))); + .map(|(g, c)| c.send_msg(ServerGeneral::GroupUpdate(g))); }, ); } @@ -244,7 +244,7 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani if let (Some(client), Some(target)) = (clients.get_mut(inviter), uids.get(entity).copied()) { - client.send_msg(ServerInGame::InviteComplete { + client.send_msg(ServerGeneral::InviteComplete { target, answer: InviteAnswer::Declined, }) @@ -269,7 +269,7 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani .try_map(|e| uids.get(e).copied()) .map(|g| (g, c)) }) - .map(|(g, c)| c.send_msg(ServerInGame::GroupUpdate(g))); + .map(|(g, c)| c.send_msg(ServerGeneral::GroupUpdate(g))); }, ); }, @@ -336,7 +336,7 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani .try_map(|e| uids.get(e).copied()) .map(|g| (g, c)) }) - .map(|(g, c)| c.send_msg(ServerInGame::GroupUpdate(g))); + .map(|(g, c)| c.send_msg(ServerGeneral::GroupUpdate(g))); }, ); @@ -410,7 +410,7 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani .try_map(|e| uids.get(e).copied()) .map(|g| (g, c)) }) - .map(|(g, c)| c.send_msg(ServerInGame::GroupUpdate(g))); + .map(|(g, c)| c.send_msg(ServerGeneral::GroupUpdate(g))); }, ); // Tell them they are the leader diff --git a/server/src/events/inventory_manip.rs b/server/src/events/inventory_manip.rs index 2f39db3811..c8f2bbd512 100644 --- a/server/src/events/inventory_manip.rs +++ b/server/src/events/inventory_manip.rs @@ -5,7 +5,7 @@ use common::{ slot::{self, Slot}, Pos, MAX_PICKUP_RANGE_SQR, }, - msg::ServerInGame, + msg::ServerGeneral, recipe::default_recipe_book, sync::{Uid, WorldSyncExt}, vol::ReadVol, @@ -281,7 +281,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv .map(|g| (g, c)) }) .map(|(g, c)| { - c.send_msg(ServerInGame::GroupUpdate(g)) + c.send_msg(ServerGeneral::GroupUpdate(g)) }); }, ); diff --git a/server/src/events/player.rs b/server/src/events/player.rs index 50380a8349..e466a5b116 100644 --- a/server/src/events/player.rs +++ b/server/src/events/player.rs @@ -5,7 +5,7 @@ use crate::{ use common::{ comp, comp::{group, Player}, - msg::{PlayerListUpdate, ServerGeneral, ServerInGame}, + msg::{PlayerListUpdate, ServerGeneral}, span, sync::{Uid, UidAllocator}, }; @@ -34,7 +34,7 @@ pub fn handle_exit_ingame(server: &mut Server, entity: EcsEntity) { if let (Some(mut client), Some(uid), Some(player)) = (maybe_client, maybe_uid, maybe_player) { // Tell client its request was successful client.in_game = None; - client.send_msg(ServerInGame::ExitInGameSuccess); + client.send_msg(ServerGeneral::ExitInGameSuccess); let entity_builder = state.ecs_mut().create_entity().with(client).with(player); diff --git a/server/src/lib.rs b/server/src/lib.rs index 138ac9c50e..d2a6111f05 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -47,8 +47,7 @@ use common::{ comp::{self, ChatType}, event::{EventBus, ServerEvent}, msg::{ - ClientType, DisconnectReason, ServerCharacterScreen, ServerGeneral, ServerInfo, ServerInit, - ServerMsg, WorldMapMsg, + ClientType, DisconnectReason, ServerGeneral, ServerInfo, ServerInit, ServerMsg, WorldMapMsg, }, outcome::Outcome, recipe::default_recipe_book, @@ -527,11 +526,11 @@ impl Server { CharacterLoaderResponseType::CharacterList(result) => match result { Ok(character_list_data) => self.notify_client( query_result.entity, - ServerCharacterScreen::CharacterListUpdate(character_list_data), + ServerGeneral::CharacterListUpdate(character_list_data), ), Err(error) => self.notify_client( query_result.entity, - ServerCharacterScreen::CharacterActionError(error.to_string()), + ServerGeneral::CharacterActionError(error.to_string()), ), }, CharacterLoaderResponseType::CharacterData(result) => { @@ -546,7 +545,7 @@ impl Server { // to display self.notify_client( query_result.entity, - ServerCharacterScreen::CharacterDataLoadError(error.to_string()), + ServerGeneral::CharacterDataLoadError(error.to_string()), ); // Clean up the entity data on the server diff --git a/server/src/state_ext.rs b/server/src/state_ext.rs index 807b553ef9..2b2c173a38 100644 --- a/server/src/state_ext.rs +++ b/server/src/state_ext.rs @@ -5,10 +5,7 @@ use common::{ character::CharacterId, comp, effect::Effect, - msg::{ - CharacterInfo, ClientIngame, PlayerListUpdate, ServerCharacterScreen, ServerGeneral, - ServerInGame, ServerMsg, - }, + msg::{CharacterInfo, ClientInGame, PlayerListUpdate, ServerGeneral, ServerMsg}, state::State, sync::{Uid, UidAllocator, WorldSyncExt}, util::Dir, @@ -63,7 +60,7 @@ pub trait StateExt { /// Iterates over registered clients and send each `ServerMsg` fn send_chat(&self, msg: comp::UnresolvedChatMsg); fn notify_registered_clients(&self, msg: ServerGeneral); - fn notify_in_game_clients(&self, msg: ServerInGame); + fn notify_in_game_clients(&self, msg: ServerGeneral); /// Delete an entity, recording the deletion in [`DeletedEntities`] fn delete_entity_recorded( &mut self, @@ -220,8 +217,8 @@ impl StateExt for State { // Tell the client its request was successful. if let Some(client) = self.ecs().write_storage::().get_mut(entity) { - client.in_game = Some(ClientIngame::Character); - client.send_msg(ServerCharacterScreen::CharacterSuccess) + client.in_game = Some(ClientInGame::Character); + client.send_msg(ServerGeneral::CharacterSuccess) } } @@ -368,7 +365,7 @@ impl StateExt for State { } /// Sends the message to all clients playing in game - fn notify_in_game_clients(&self, msg: ServerInGame) { + fn notify_in_game_clients(&self, msg: ServerGeneral) { let msg: ServerMsg = msg.into(); for client in (&mut self.ecs().write_storage::()) .join() @@ -401,7 +398,7 @@ impl StateExt for State { .try_map(|e| uids.get(e).copied()) .map(|g| (g, c)) }) - .map(|(g, c)| c.send_msg(ServerInGame::GroupUpdate(g))); + .map(|(g, c)| c.send_msg(ServerGeneral::GroupUpdate(g))); }, ); } diff --git a/server/src/sys/entity_sync.rs b/server/src/sys/entity_sync.rs index 9f163db12e..0442a04e8e 100644 --- a/server/src/sys/entity_sync.rs +++ b/server/src/sys/entity_sync.rs @@ -8,7 +8,7 @@ use crate::{ }; use common::{ comp::{ForceUpdate, Inventory, InventoryUpdate, Last, Ori, Player, Pos, Vel}, - msg::{ServerGeneral, ServerInGame}, + msg::ServerGeneral, outcome::Outcome, region::{Event as RegionEvent, RegionMap}, span, @@ -320,7 +320,7 @@ impl<'a> System<'a> for Sys { // Sync inventories for (client, inventory, update) in (&mut clients, &inventories, &inventory_updates).join() { - client.send_msg(ServerInGame::InventoryUpdate( + client.send_msg(ServerGeneral::InventoryUpdate( inventory.clone(), update.event(), )); @@ -341,7 +341,7 @@ impl<'a> System<'a> for Sys { .cloned() .collect::>(); if !outcomes.is_empty() { - client.send_msg(ServerInGame::Outcomes(outcomes)); + client.send_msg(ServerGeneral::Outcomes(outcomes)); } } outcomes.clear(); diff --git a/server/src/sys/invite_timeout.rs b/server/src/sys/invite_timeout.rs index 9cf3f71455..42f6603fe8 100644 --- a/server/src/sys/invite_timeout.rs +++ b/server/src/sys/invite_timeout.rs @@ -2,7 +2,7 @@ use super::SysTimer; use crate::client::Client; use common::{ comp::group::{Invite, PendingInvites}, - msg::{InviteAnswer, ServerInGame}, + msg::{InviteAnswer, ServerGeneral}, span, sync::Uid, }; @@ -54,7 +54,7 @@ impl<'a> System<'a> for Sys { if let (Some(client), Some(target)) = (clients.get_mut(*inviter), uids.get(invitee).copied()) { - client.send_msg(ServerInGame::InviteComplete { + client.send_msg(ServerGeneral::InviteComplete { target, answer: InviteAnswer::TimedOut, }) diff --git a/server/src/sys/message.rs b/server/src/sys/message.rs index 16631c6234..9a9dfc92d3 100644 --- a/server/src/sys/message.rs +++ b/server/src/sys/message.rs @@ -15,10 +15,9 @@ use common::{ }, event::{EventBus, ServerEvent}, msg::{ - validate_chat_msg, CharacterInfo, ChatMsgValidationError, ClientCharacterScreen, - ClientGeneral, ClientInGame, ClientIngame, ClientRegister, DisconnectReason, PingMsg, - PlayerInfo, PlayerListUpdate, RegisterError, ServerCharacterScreen, ServerGeneral, - ServerInGame, ServerRegisterAnswer, MAX_BYTES_CHAT_MSG, + validate_chat_msg, CharacterInfo, ChatMsgValidationError, ClientGeneral, ClientInGame, + ClientRegister, DisconnectReason, PingMsg, PlayerInfo, PlayerListUpdate, RegisterError, + ServerGeneral, ServerRegisterAnswer, MAX_BYTES_CHAT_MSG, }, span, state::{BlockChange, Time}, @@ -79,6 +78,7 @@ impl Sys { .inc(); server_emitter.emit(ServerEvent::ClientDisconnect(entity)); }, + _ => unreachable!("not a client_general msg"), } Ok(()) } @@ -100,24 +100,24 @@ impl Sys { players: &mut WriteStorage<'_, Player>, controllers: &mut WriteStorage<'_, Controller>, settings: &Read<'_, Settings>, - msg: ClientInGame, + msg: ClientGeneral, ) -> Result<(), crate::error::Error> { if client.in_game.is_none() { debug!(?entity, "client is not in_game, ignoring msg"); trace!(?msg, "ignored msg content"); - if matches!(msg, ClientInGame::TerrainChunkRequest{ .. }) { + if matches!(msg, ClientGeneral::TerrainChunkRequest{ .. }) { network_metrics.chunks_request_dropped.inc(); } return Ok(()); } match msg { // Go back to registered state (char selection screen) - ClientInGame::ExitInGame => { + ClientGeneral::ExitInGame => { client.in_game = None; server_emitter.emit(ServerEvent::ExitIngame { entity }); - client.send_msg(ServerInGame::ExitInGameSuccess); + client.send_msg(ServerGeneral::ExitInGameSuccess); }, - ClientInGame::SetViewDistance(view_distance) => { + ClientGeneral::SetViewDistance(view_distance) => { players.get_mut(entity).map(|player| { player.view_distance = Some( settings @@ -133,20 +133,20 @@ impl Sys { .map(|max| view_distance > max) .unwrap_or(false) { - client.send_msg(ServerInGame::SetViewDistance( + client.send_msg(ServerGeneral::SetViewDistance( settings.max_view_distance.unwrap_or(0), )); } }, - ClientInGame::ControllerInputs(inputs) => { - if let Some(ClientIngame::Character) = client.in_game { + ClientGeneral::ControllerInputs(inputs) => { + if let Some(ClientInGame::Character) = client.in_game { if let Some(controller) = controllers.get_mut(entity) { controller.inputs.update_with_new(inputs); } } }, - ClientInGame::ControlEvent(event) => { - if let Some(ClientIngame::Character) = client.in_game { + ClientGeneral::ControlEvent(event) => { + if let Some(ClientInGame::Character) = client.in_game { // Skip respawn if client entity is alive if let ControlEvent::Respawn = event { if stats.get(entity).map_or(true, |s| !s.is_dead) { @@ -159,15 +159,15 @@ impl Sys { } } }, - ClientInGame::ControlAction(event) => { - if let Some(ClientIngame::Character) = client.in_game { + ClientGeneral::ControlAction(event) => { + if let Some(ClientInGame::Character) = client.in_game { if let Some(controller) = controllers.get_mut(entity) { controller.actions.push(event); } } }, - ClientInGame::PlayerPhysics { pos, vel, ori } => { - if let Some(ClientIngame::Character) = client.in_game { + ClientGeneral::PlayerPhysics { pos, vel, ori } => { + if let Some(ClientInGame::Character) = client.in_game { if force_updates.get(entity).is_none() && stats.get(entity).map_or(true, |s| !s.is_dead) { @@ -177,17 +177,17 @@ impl Sys { } } }, - ClientInGame::BreakBlock(pos) => { + ClientGeneral::BreakBlock(pos) => { if let Some(block) = can_build.get(entity).and_then(|_| terrain.get(pos).ok()) { block_changes.set(pos, block.into_vacant()); } }, - ClientInGame::PlaceBlock(pos, block) => { + ClientGeneral::PlaceBlock(pos, block) => { if can_build.get(entity).is_some() { block_changes.try_set(pos, block); } }, - ClientInGame::TerrainChunkRequest { key } => { + ClientGeneral::TerrainChunkRequest { key } => { let in_vd = if let (Some(view_distance), Some(pos)) = ( players.get(entity).and_then(|p| p.view_distance), positions.get(entity), @@ -203,7 +203,7 @@ impl Sys { match terrain.get_key(key) { Some(chunk) => { network_metrics.chunks_served_from_memory.inc(); - client.send_msg(ServerInGame::TerrainChunkUpdate { + client.send_msg(ServerGeneral::TerrainChunkUpdate { key, chunk: Ok(Box::new(chunk.clone())), }) @@ -217,21 +217,22 @@ impl Sys { network_metrics.chunks_request_dropped.inc(); } }, - ClientInGame::UnlockSkill(skill) => { + ClientGeneral::UnlockSkill(skill) => { stats .get_mut(entity) .map(|s| s.skill_set.unlock_skill(skill)); }, - ClientInGame::RefundSkill(skill) => { + ClientGeneral::RefundSkill(skill) => { stats .get_mut(entity) .map(|s| s.skill_set.refund_skill(skill)); }, - ClientInGame::UnlockSkillGroup(skill_group_type) => { + ClientGeneral::UnlockSkillGroup(skill_group_type) => { stats .get_mut(entity) .map(|s| s.skill_set.unlock_skill_group(skill_group_type)); }, + _ => unreachable!("not a client_in_game msg"), } Ok(()) } @@ -247,17 +248,15 @@ impl Sys { players: &mut WriteStorage<'_, Player>, editable_settings: &ReadExpect<'_, EditableSettings>, alias_validator: &ReadExpect<'_, AliasValidator>, - msg: ClientCharacterScreen, + msg: ClientGeneral, ) -> Result<(), crate::error::Error> { match msg { // Request spectator state - ClientCharacterScreen::Spectate if client.registered => { - client.in_game = Some(ClientIngame::Spectator) + ClientGeneral::Spectate if client.registered => { + client.in_game = Some(ClientInGame::Spectator) }, - ClientCharacterScreen::Spectate => { - debug!("dropped Spectate msg from unregistered client") - }, - ClientCharacterScreen::Character(character_id) + ClientGeneral::Spectate => debug!("dropped Spectate msg from unregistered client"), + ClientGeneral::Character(character_id) if client.registered && client.in_game.is_none() => { if let Some(player) = players.get(entity) { @@ -296,27 +295,25 @@ impl Sys { } } } else { - client.send_msg(ServerCharacterScreen::CharacterDataLoadError(String::from( + client.send_msg(ServerGeneral::CharacterDataLoadError(String::from( "Failed to fetch player entity", ))) } } - ClientCharacterScreen::Character(_) => { + ClientGeneral::Character(_) => { let registered = client.registered; let in_game = client.in_game; debug!(?registered, ?in_game, "dropped Character msg from client"); }, - ClientCharacterScreen::RequestCharacterList => { + ClientGeneral::RequestCharacterList => { if let Some(player) = players.get(entity) { character_loader.load_character_list(entity, player.uuid().to_string()) } }, - ClientCharacterScreen::CreateCharacter { alias, tool, body } => { + ClientGeneral::CreateCharacter { alias, tool, body } => { if let Err(error) = alias_validator.validate(&alias) { debug!(?error, ?alias, "denied alias as it contained a banned word"); - client.send_msg(ServerCharacterScreen::CharacterActionError( - error.to_string(), - )); + client.send_msg(ServerGeneral::CharacterActionError(error.to_string())); } else if let Some(player) = players.get(entity) { character_creator::create_character( entity, @@ -328,7 +325,7 @@ impl Sys { ); } }, - ClientCharacterScreen::DeleteCharacter(character_id) => { + ClientGeneral::DeleteCharacter(character_id) => { if let Some(player) = players.get(entity) { character_loader.delete_character( entity, @@ -337,6 +334,7 @@ impl Sys { ); } }, + _ => unreachable!("not a client_character_screen msg"), } Ok(()) } @@ -379,7 +377,7 @@ impl Sys { }; const INITIAL_VD: Option = Some(5); //will be changed after login - let player = Player::new(username.clone(), None, INITIAL_VD, uuid); + let player = Player::new(username, None, INITIAL_VD, uuid); let is_admin = editable_settings.admins.contains(&uuid); if !player.is_valid() { diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs index c29330addf..eafa24b0ff 100644 --- a/server/src/sys/terrain.rs +++ b/server/src/sys/terrain.rs @@ -4,7 +4,7 @@ use common::{ comp::{self, bird_medium, Alignment, Player, Pos}, event::{EventBus, ServerEvent}, generation::get_npc_name, - msg::ServerInGame, + msg::ServerGeneral, npc::NPC_NAMES, span, state::TerrainChanges, @@ -63,7 +63,7 @@ impl<'a> System<'a> for Sys { Ok((chunk, supplement)) => (chunk, supplement), Err(Some(entity)) => { if let Some(client) = clients.get_mut(entity) { - client.send_msg(ServerInGame::TerrainChunkUpdate { + client.send_msg(ServerGeneral::TerrainChunkUpdate { key, chunk: Err(()), }); @@ -90,7 +90,7 @@ impl<'a> System<'a> for Sys { .magnitude_squared(); if adjusted_dist_sqr <= view_distance.pow(2) { - client.send_msg(ServerInGame::TerrainChunkUpdate { + client.send_msg(ServerGeneral::TerrainChunkUpdate { key, chunk: Ok(Box::new(chunk.clone())), }); diff --git a/server/src/sys/terrain_sync.rs b/server/src/sys/terrain_sync.rs index 876b3b94eb..a2e21f42a9 100644 --- a/server/src/sys/terrain_sync.rs +++ b/server/src/sys/terrain_sync.rs @@ -2,7 +2,7 @@ use super::SysTimer; use crate::client::Client; use common::{ comp::{Player, Pos}, - msg::ServerInGame, + msg::ServerGeneral, span, state::TerrainChanges, terrain::TerrainGrid, @@ -38,7 +38,7 @@ impl<'a> System<'a> for Sys { .map(|vd| super::terrain::chunk_in_vd(pos.0, *chunk_key, &terrain, vd)) .unwrap_or(false) { - client.send_msg(ServerInGame::TerrainChunkUpdate { + client.send_msg(ServerGeneral::TerrainChunkUpdate { key: *chunk_key, chunk: Ok(Box::new(match terrain.get_key(*chunk_key) { Some(chunk) => chunk.clone(), @@ -51,7 +51,7 @@ impl<'a> System<'a> for Sys { // TODO: Don't send all changed blocks to all clients // Sync changed blocks - let msg = ServerInGame::TerrainBlockUpdates(terrain_changes.modified_blocks.clone()); + let msg = ServerGeneral::TerrainBlockUpdates(terrain_changes.modified_blocks.clone()); for (player, client) in (&players, &mut clients).join() { if player.view_distance.is_some() { client.send_msg(msg.clone());