From 288c7cdbfaadb045dbb144af659133fa467817d0 Mon Sep 17 00:00:00 2001 From: scott-c Date: Tue, 19 May 2020 19:46:06 +0800 Subject: [PATCH 01/12] fix #562 Confusing chat alias --- server/src/sys/message.rs | 6 ++++-- voxygen/src/hud/social.rs | 17 +++++++++++------ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/server/src/sys/message.rs b/server/src/sys/message.rs index 3e18372abd..1fdd8433cd 100644 --- a/server/src/sys/message.rs +++ b/server/src/sys/message.rs @@ -408,10 +408,12 @@ impl<'a> System<'a> for Sys { let _ = speech_bubbles.insert(entity, bubble); match players.get(entity) { Some(player) => { + let stat = + stats.get(entity).expect("Expected stat.name for player"); if admins.get(entity).is_some() { - format!("[ADMIN][{}] {}", &player.alias, message) + format!("[ADMIN][{}] {}", &stat.name, message) } else { - format!("[{}] {}", &player.alias, message) + format!("[{}] {}", &stat.name, message) } }, None => format!("[] {}", message), diff --git a/voxygen/src/hud/social.rs b/voxygen/src/hud/social.rs index c278ec1963..6fb94996fa 100644 --- a/voxygen/src/hud/social.rs +++ b/voxygen/src/hud/social.rs @@ -193,12 +193,17 @@ impl<'a> Widget for Social<'a> { .color(TEXT_COLOR) .set(ids.online_title, ui); for (i, (_, player_alias)) in self.client.player_list.iter().enumerate() { - Text::new(player_alias) - .down(3.0) - .font_size(self.fonts.cyri.scale(15)) - .font_id(self.fonts.cyri.conrod_id) - .color(TEXT_COLOR) - .set(ids.player_names[i], ui); + Text::new(&format!( + "({}) {} Lvl {}", + player_alias, + self.client.character_list.characters[i].character.alias, + self.client.character_list.characters[i].level + )) + .down(3.0) + .font_size(self.fonts.cyri.scale(15)) + .font_id(self.fonts.cyri.conrod_id) + .color(TEXT_COLOR) + .set(ids.player_names[i], ui); } } From fefd643657a63772666c363288dcd63b0c77c8aa Mon Sep 17 00:00:00 2001 From: scott-c Date: Tue, 19 May 2020 19:56:51 +0800 Subject: [PATCH 02/12] Fix unused variable compiler warning --- server/src/sys/message.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/server/src/sys/message.rs b/server/src/sys/message.rs index 1fdd8433cd..2b883d75b0 100644 --- a/server/src/sys/message.rs +++ b/server/src/sys/message.rs @@ -406,10 +406,8 @@ impl<'a> System<'a> for Sys { } else { let bubble = SpeechBubble::player_new(message.clone(), *time); let _ = speech_bubbles.insert(entity, bubble); - match players.get(entity) { - Some(player) => { - let stat = - stats.get(entity).expect("Expected stat.name for player"); + match stats.get(entity) { + Some(stat) => { if admins.get(entity).is_some() { format!("[ADMIN][{}] {}", &stat.name, message) } else { From 66f6368e8321a609cb265ee2ecc7f63f82db8794 Mon Sep 17 00:00:00 2001 From: scott-c Date: Wed, 20 May 2020 11:36:17 +0800 Subject: [PATCH 03/12] Handle out of bounds panic --- voxygen/src/hud/social.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/voxygen/src/hud/social.rs b/voxygen/src/hud/social.rs index 6fb94996fa..6ae106d9e8 100644 --- a/voxygen/src/hud/social.rs +++ b/voxygen/src/hud/social.rs @@ -194,10 +194,16 @@ impl<'a> Widget for Social<'a> { .set(ids.online_title, ui); for (i, (_, player_alias)) in self.client.player_list.iter().enumerate() { Text::new(&format!( - "({}) {} Lvl {}", + "[{}] {} Lvl {}", player_alias, - self.client.character_list.characters[i].character.alias, - self.client.character_list.characters[i].level + match self.client.character_list.characters.get(i) { + Some(s) => &s.character.alias, + None => "", + }, + match self.client.character_list.characters.get(i) { + Some(s) => s.level.to_string(), + None => "".to_string(), + }, )) .down(3.0) .font_size(self.fonts.cyri.scale(15)) From 636fcafd2eda6f39939c2936489394f4cfa67d17 Mon Sep 17 00:00:00 2001 From: scott-c Date: Wed, 20 May 2020 11:37:14 +0800 Subject: [PATCH 04/12] Restore player alias being displayed in chat --- server/src/sys/message.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/server/src/sys/message.rs b/server/src/sys/message.rs index 2b883d75b0..0c32efadb4 100644 --- a/server/src/sys/message.rs +++ b/server/src/sys/message.rs @@ -406,16 +406,22 @@ impl<'a> System<'a> for Sys { } else { let bubble = SpeechBubble::player_new(message.clone(), *time); let _ = speech_bubbles.insert(entity, bubble); - match stats.get(entity) { - Some(stat) => { - if admins.get(entity).is_some() { - format!("[ADMIN][{}] {}", &stat.name, message) - } else { - format!("[{}] {}", &stat.name, message) - } + format!( + "{}[{}] {}: {}", + match admins.get(entity) { + Some(_) => "[ADMIN]", + None => "", }, - None => format!("[] {}", message), - } + match players.get(entity) { + Some(player) => &player.alias, + None => "", + }, + match stats.get(entity) { + Some(stat) => &stat.name, + None => "", + }, + message + ) } } else { message From c23183b1ca5153d5a852208b75939fd3f1225de1 Mon Sep 17 00:00:00 2001 From: scott-c Date: Wed, 20 May 2020 19:59:44 +0800 Subject: [PATCH 05/12] Add character name and level to social window --- client/src/cmd.rs | 1 + client/src/lib.rs | 16 +++++++++------- common/src/msg/mod.rs | 3 ++- common/src/msg/server.rs | 11 +++++++++-- server/src/sys/message.rs | 28 +++++++++++++++++++--------- voxygen/src/hud/social.rs | 14 ++++---------- 6 files changed, 44 insertions(+), 29 deletions(-) diff --git a/client/src/cmd.rs b/client/src/cmd.rs index f24152fd92..2fc1e68db7 100644 --- a/client/src/cmd.rs +++ b/client/src/cmd.rs @@ -40,6 +40,7 @@ fn complete_player(part: &str, client: &Client) -> Vec { client .player_list .values() + .map(|player_info| &player_info.player_alias) .filter(|alias| alias.starts_with(part)) .cloned() .collect() diff --git a/client/src/lib.rs b/client/src/lib.rs index c8d21a84c8..bc646abd40 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -23,7 +23,7 @@ use common::{ event::{EventBus, SfxEvent, SfxEventItem}, msg::{ validate_chat_msg, ChatMsgValidationError, ClientMsg, ClientState, Notification, - PlayerListUpdate, RegisterError, RequestStateError, ServerInfo, ServerMsg, + PlayerInfo, PlayerListUpdate, RegisterError, RequestStateError, ServerInfo, ServerMsg, MAX_BYTES_CHAT_MSG, }, net::PostBox, @@ -68,7 +68,7 @@ pub struct Client { thread_pool: ThreadPool, pub server_info: ServerInfo, pub world_map: (Arc, Vec2), - pub player_list: HashMap, + pub player_list: HashMap, pub character_list: CharacterList, postbox: PostBox, @@ -734,13 +734,15 @@ impl Client { ServerMsg::PlayerListUpdate(PlayerListUpdate::Init(list)) => { self.player_list = list }, - ServerMsg::PlayerListUpdate(PlayerListUpdate::Add(uid, name)) => { - if let Some(old_name) = self.player_list.insert(uid, name.clone()) { + ServerMsg::PlayerListUpdate(PlayerListUpdate::Add(uid, player_info)) => { + if let Some(old_player_info) = + self.player_list.insert(uid, player_info.clone()) + { warn!( "Received msg to insert {} with uid {} into the player list but \ there was already an entry for {} with the same uid that was \ overwritten!", - name, uid, old_name + player_info.player_alias, uid, old_player_info.player_alias ); } }, @@ -754,8 +756,8 @@ impl Client { } }, ServerMsg::PlayerListUpdate(PlayerListUpdate::Alias(uid, new_name)) => { - if let Some(name) = self.player_list.get_mut(&uid) { - *name = new_name; + if let Some(player_info) = self.player_list.get_mut(&uid) { + player_info.player_alias = new_name; } else { warn!( "Received msg to alias player with uid {} to {} but this uid is \ diff --git a/common/src/msg/mod.rs b/common/src/msg/mod.rs index c045383dd0..3e5c6d28ea 100644 --- a/common/src/msg/mod.rs +++ b/common/src/msg/mod.rs @@ -7,7 +7,8 @@ pub use self::{ client::ClientMsg, ecs_packet::EcsCompPacket, server::{ - Notification, PlayerListUpdate, RegisterError, RequestStateError, ServerInfo, ServerMsg, + Notification, PlayerInfo, PlayerListUpdate, RegisterError, RequestStateError, ServerInfo, + ServerMsg, }, }; diff --git a/common/src/msg/server.rs b/common/src/msg/server.rs index ae0a3a4aa8..58e536024f 100644 --- a/common/src/msg/server.rs +++ b/common/src/msg/server.rs @@ -20,12 +20,19 @@ pub struct ServerInfo { #[derive(Debug, Clone, Serialize, Deserialize)] pub enum PlayerListUpdate { - Init(HashMap), - Add(u64, String), + Init(HashMap), + Add(u64, PlayerInfo), Remove(u64), Alias(u64, String), } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct PlayerInfo { + pub player_alias: String, + pub character_name: String, + pub character_level: u32, +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub enum Notification { WaypointSaved, diff --git a/server/src/sys/message.rs b/server/src/sys/message.rs index 0c32efadb4..1eedd4fda3 100644 --- a/server/src/sys/message.rs +++ b/server/src/sys/message.rs @@ -10,8 +10,8 @@ use common::{ }, event::{EventBus, ServerEvent}, msg::{ - validate_chat_msg, ChatMsgValidationError, ClientMsg, ClientState, PlayerListUpdate, - RequestStateError, ServerMsg, MAX_BYTES_CHAT_MSG, + validate_chat_msg, ChatMsgValidationError, ClientMsg, ClientState, PlayerInfo, + PlayerListUpdate, RequestStateError, ServerMsg, MAX_BYTES_CHAT_MSG, }, state::{BlockChange, Time}, sync::Uid, @@ -83,9 +83,15 @@ impl<'a> System<'a> for Sys { let mut new_chat_msgs = Vec::new(); // Player list to send new players. - let player_list = (&uids, &players) + let player_list = (&uids, &players, &stats) .join() - .map(|(uid, player)| ((*uid).into(), player.alias.clone())) + .map(|(uid, player, stats)| { + ((*uid).into(), PlayerInfo { + player_alias: player.alias.clone(), + character_name: stats.name.clone(), + character_level: stats.level.level(), + }) + }) .collect::>(); // List of new players to update player lists of all clients. let mut new_players = Vec::new(); @@ -382,11 +388,15 @@ impl<'a> System<'a> for Sys { // 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 msg = ServerMsg::PlayerListUpdate(PlayerListUpdate::Add( - (*uid).into(), - player.alias.clone(), - )); + if let (Some(uid), Some(player), Some(stats)) = + (uids.get(entity), players.get(entity), stats.get(entity)) + { + let msg = + ServerMsg::PlayerListUpdate(PlayerListUpdate::Add((*uid).into(), PlayerInfo { + player_alias: player.alias.clone(), + character_name: stats.name.clone(), + character_level: stats.level.level(), // TODO: stats.level.amount, + })); for client in (&mut clients).join().filter(|c| c.is_registered()) { client.notify(msg.clone()) } diff --git a/voxygen/src/hud/social.rs b/voxygen/src/hud/social.rs index 6ae106d9e8..cfb52293b6 100644 --- a/voxygen/src/hud/social.rs +++ b/voxygen/src/hud/social.rs @@ -192,18 +192,12 @@ impl<'a> Widget for Social<'a> { .font_id(self.fonts.cyri.conrod_id) .color(TEXT_COLOR) .set(ids.online_title, ui); - for (i, (_, player_alias)) in self.client.player_list.iter().enumerate() { + for (i, (_, player_info)) in self.client.player_list.iter().enumerate() { Text::new(&format!( "[{}] {} Lvl {}", - player_alias, - match self.client.character_list.characters.get(i) { - Some(s) => &s.character.alias, - None => "", - }, - match self.client.character_list.characters.get(i) { - Some(s) => s.level.to_string(), - None => "".to_string(), - }, + player_info.player_alias, + player_info.character_name, + player_info.character_level )) .down(3.0) .font_size(self.fonts.cyri.scale(15)) From 136bf271b8218a4e6b30f7883f6ce138031e8672 Mon Sep 17 00:00:00 2001 From: scott-c Date: Sun, 24 May 2020 17:20:54 +0800 Subject: [PATCH 06/12] Fix social list having incorrect player count --- client/src/lib.rs | 17 +++++++++++++++++ common/src/msg/mod.rs | 4 ++-- common/src/msg/server.rs | 11 +++++++++-- server/src/sys/message.rs | 18 +++++++++--------- voxygen/src/hud/social.rs | 8 +++++--- 5 files changed, 42 insertions(+), 16 deletions(-) diff --git a/client/src/lib.rs b/client/src/lib.rs index bc646abd40..f6ba8a588d 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -746,6 +746,23 @@ impl Client { ); } }, + ServerMsg::PlayerListUpdate(PlayerListUpdate::SelectedCharacter( + uid, + char_info, + )) => { + warn!( + "ServerMsg::PlayerListUpdate PlayerListUpdate::LevelChange not \ + implemented: {} {:?}", + uid, char_info + ); + }, + ServerMsg::PlayerListUpdate(PlayerListUpdate::LevelChange(uid, next_level)) => { + warn!( + "ServerMsg::PlayerListUpdate PlayerListUpdate::LevelChange not \ + implemented: {} {}", + uid, next_level + ); + }, ServerMsg::PlayerListUpdate(PlayerListUpdate::Remove(uid)) => { if self.player_list.remove(&uid).is_none() { warn!( diff --git a/common/src/msg/mod.rs b/common/src/msg/mod.rs index 3e5c6d28ea..dc3ff97552 100644 --- a/common/src/msg/mod.rs +++ b/common/src/msg/mod.rs @@ -7,8 +7,8 @@ pub use self::{ client::ClientMsg, ecs_packet::EcsCompPacket, server::{ - Notification, PlayerInfo, PlayerListUpdate, RegisterError, RequestStateError, ServerInfo, - ServerMsg, + CharacterInfo, Notification, PlayerInfo, PlayerListUpdate, RegisterError, + RequestStateError, ServerInfo, ServerMsg, }, }; diff --git a/common/src/msg/server.rs b/common/src/msg/server.rs index 58e536024f..42501f5d7f 100644 --- a/common/src/msg/server.rs +++ b/common/src/msg/server.rs @@ -22,6 +22,8 @@ pub struct ServerInfo { pub enum PlayerListUpdate { Init(HashMap), Add(u64, PlayerInfo), + SelectedCharacter(u64, CharacterInfo), + LevelChange(u64, u32), Remove(u64), Alias(u64, String), } @@ -29,8 +31,13 @@ pub enum PlayerListUpdate { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct PlayerInfo { pub player_alias: String, - pub character_name: String, - pub character_level: u32, + pub character: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CharacterInfo { + pub name: String, + pub level: u32, } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/server/src/sys/message.rs b/server/src/sys/message.rs index 1eedd4fda3..1c639f61c1 100644 --- a/server/src/sys/message.rs +++ b/server/src/sys/message.rs @@ -10,8 +10,8 @@ use common::{ }, event::{EventBus, ServerEvent}, msg::{ - validate_chat_msg, ChatMsgValidationError, ClientMsg, ClientState, PlayerInfo, - PlayerListUpdate, RequestStateError, ServerMsg, MAX_BYTES_CHAT_MSG, + validate_chat_msg, CharacterInfo, ChatMsgValidationError, ClientMsg, ClientState, + PlayerInfo, PlayerListUpdate, RequestStateError, ServerMsg, MAX_BYTES_CHAT_MSG, }, state::{BlockChange, Time}, sync::Uid, @@ -88,8 +88,11 @@ impl<'a> System<'a> for Sys { .map(|(uid, player, stats)| { ((*uid).into(), PlayerInfo { player_alias: player.alias.clone(), - character_name: stats.name.clone(), - character_level: stats.level.level(), + // TODO: player might not have a character selected + character: Some(CharacterInfo { + name: stats.name.clone(), + level: stats.level.level(), + }), }) }) .collect::>(); @@ -388,14 +391,11 @@ impl<'a> System<'a> for Sys { // Handle new players. // Tell all clients to add them to the player list. for entity in new_players { - if let (Some(uid), Some(player), Some(stats)) = - (uids.get(entity), players.get(entity), stats.get(entity)) - { + if let (Some(uid), Some(player)) = (uids.get(entity), players.get(entity)) { let msg = ServerMsg::PlayerListUpdate(PlayerListUpdate::Add((*uid).into(), PlayerInfo { player_alias: player.alias.clone(), - character_name: stats.name.clone(), - character_level: stats.level.level(), // TODO: stats.level.amount, + character: None, // new players will be on character select. })); for client in (&mut clients).join().filter(|c| c.is_registered()) { client.notify(msg.clone()) diff --git a/voxygen/src/hud/social.rs b/voxygen/src/hud/social.rs index cfb52293b6..fd214d098c 100644 --- a/voxygen/src/hud/social.rs +++ b/voxygen/src/hud/social.rs @@ -194,10 +194,12 @@ impl<'a> Widget for Social<'a> { .set(ids.online_title, ui); for (i, (_, player_info)) in self.client.player_list.iter().enumerate() { Text::new(&format!( - "[{}] {} Lvl {}", + "[{}] {}", player_info.player_alias, - player_info.character_name, - player_info.character_level + match &player_info.character { + Some(character) => format!("{} Lvl {}", &character.name, &character.level), + None => "".to_string(), // character select or spectating + } )) .down(3.0) .font_size(self.fonts.cyri.scale(15)) From 730399b5f467d7efb31993a6c17fe3c0b43a21a8 Mon Sep 17 00:00:00 2001 From: scott-c Date: Mon, 1 Jun 2020 15:31:13 +0800 Subject: [PATCH 07/12] Add character select network event --- client/src/lib.rs | 37 +++++++++++++++++++++++++++---------- server/src/state_ext.rs | 22 +++++++++++++++++++++- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/client/src/lib.rs b/client/src/lib.rs index f6ba8a588d..0f0eb33f22 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -750,18 +750,35 @@ impl Client { uid, char_info, )) => { - warn!( - "ServerMsg::PlayerListUpdate PlayerListUpdate::LevelChange not \ - implemented: {} {:?}", - uid, char_info - ); + if let Some(player_info) = self.player_list.get_mut(&uid) { + player_info.character = Some(char_info); + } else { + warn!( + "Received msg to update character info for uid {}, but they were \ + not in the list.", + uid + ); + } }, ServerMsg::PlayerListUpdate(PlayerListUpdate::LevelChange(uid, next_level)) => { - warn!( - "ServerMsg::PlayerListUpdate PlayerListUpdate::LevelChange not \ - implemented: {} {}", - uid, next_level - ); + if let Some(player_info) = self.player_list.get_mut(&uid) { + if let Some(character) = &player_info.character { + // TODO: assign next value + // &character.level = next_level; + } else { + warn!( + "Received msg to update character level info to {} for uid \ + {}, but this player's character is None.", + next_level, uid + ); + } + } else { + warn!( + "Received msg to update character level info to {} for uid {}, \ + but they were not in the list.", + next_level, uid + ); + } }, ServerMsg::PlayerListUpdate(PlayerListUpdate::Remove(uid)) => { if self.player_list.remove(&uid).is_none() { diff --git a/server/src/state_ext.rs b/server/src/state_ext.rs index 5834792165..2783f24ef4 100644 --- a/server/src/state_ext.rs +++ b/server/src/state_ext.rs @@ -6,7 +6,9 @@ use common::{ assets, comp::{self, item}, effect::Effect, - msg::{ClientState, RegisterError, RequestStateError, ServerMsg}, + msg::{ + CharacterInfo, ClientState, PlayerListUpdate, RegisterError, RequestStateError, ServerMsg, + }, state::State, sync::{Uid, WorldSyncExt}, util::Dir, @@ -279,6 +281,24 @@ impl StateExt for State { self.write_component(entity, comp::Admin); } + let uids = &self.ecs().read_storage::(); + let uid = uids + .get(entity) + .expect("Failed to fetch uid component for entity.") + .0; + + let stats = &self.ecs().read_storage::(); + let stat = stats + .get(entity) + .expect("Failed to fetch stats component for entity."); + + self.notify_registered_clients(ServerMsg::PlayerListUpdate( + PlayerListUpdate::SelectedCharacter(uid, CharacterInfo { + name: stat.name.to_string(), + level: stat.level.level(), + }), + )); + // Tell the client its request was successful. if let Some(client) = self.ecs().write_storage::().get_mut(entity) { client.allow_state(ClientState::Character); From 7eb1b2c2637fdee96f9b70d02f043d4242819338 Mon Sep 17 00:00:00 2001 From: scott-c Date: Mon, 1 Jun 2020 17:21:33 +0800 Subject: [PATCH 08/12] Add level up network event --- client/src/lib.rs | 29 +++++++++++------------- common/src/event.rs | 1 + common/src/sys/stats.rs | 1 + server/src/events/entity_manipulation.rs | 16 ++++++++++++- server/src/events/mod.rs | 4 +++- 5 files changed, 33 insertions(+), 18 deletions(-) diff --git a/client/src/lib.rs b/client/src/lib.rs index 0f0eb33f22..f078192d21 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -762,22 +762,19 @@ impl Client { }, ServerMsg::PlayerListUpdate(PlayerListUpdate::LevelChange(uid, next_level)) => { if let Some(player_info) = self.player_list.get_mut(&uid) { - if let Some(character) = &player_info.character { - // TODO: assign next value - // &character.level = next_level; - } else { - warn!( - "Received msg to update character level info to {} for uid \ - {}, but this player's character is None.", - next_level, uid - ); - } - } else { - warn!( - "Received msg to update character level info to {} for uid {}, \ - but they were not in the list.", - next_level, uid - ); + player_info.character = match &player_info.character { + Some(character) => Some(common::msg::CharacterInfo { + name: character.name.to_string(), + level: next_level, + }), + None => { + warn!( + "Received msg to update character level info to {} for \ + uid {}, but this player's character is None.", + next_level, uid + ); + }, + }; } }, ServerMsg::PlayerListUpdate(PlayerListUpdate::Remove(uid)) => { diff --git a/common/src/event.rs b/common/src/event.rs index 762703337d..b8f5cc6a80 100644 --- a/common/src/event.rs +++ b/common/src/event.rs @@ -90,6 +90,7 @@ pub enum ServerEvent { Mount(EcsEntity, EcsEntity), Unmount(EcsEntity), Possess(Uid, Uid), + LevelUp(EcsEntity, u32), SelectCharacter { entity: EcsEntity, character_id: i32, diff --git a/common/src/sys/stats.rs b/common/src/sys/stats.rs index 448b97fec8..5321b54c7a 100644 --- a/common/src/sys/stats.rs +++ b/common/src/sys/stats.rs @@ -66,6 +66,7 @@ impl<'a> System<'a> for Sys { stat.exp.change_by(-(stat.exp.maximum() as i64)); stat.level.change_by(1); stat.exp.update_maximum(stat.level.level()); + server_event_emitter.emit(ServerEvent::LevelUp(entity, stat.level.level())); } stat.update_max_hp(); diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index 266145cbe3..45be81d287 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -2,7 +2,7 @@ use crate::{client::Client, Server, SpawnPoint, StateExt}; use common::{ assets, comp::{self, object, Body, HealthChange, HealthSource, Item, Player, Stats}, - msg::ServerMsg, + msg::{PlayerListUpdate, ServerMsg}, state::BlockChange, sync::{Uid, WorldSyncExt}, sys::combat::{BLOCK_ANGLE, BLOCK_EFFICIENCY}, @@ -295,3 +295,17 @@ pub fn handle_explosion(server: &Server, pos: Vec3, power: f32, owner: Opti .cast(); } } + +pub fn handle_level_up(server: &mut Server, entity: EcsEntity, new_level: u32) { + let uids = server.state.ecs().read_storage::(); + let uid = uids + .get(entity) + .expect("Failed to fetch uid component for entity.") + .0; + + server + .state + .notify_registered_clients(ServerMsg::PlayerListUpdate(PlayerListUpdate::LevelChange( + uid, new_level, + ))); +} diff --git a/server/src/events/mod.rs b/server/src/events/mod.rs index d36f86e9d4..04d540badc 100644 --- a/server/src/events/mod.rs +++ b/server/src/events/mod.rs @@ -4,7 +4,8 @@ use entity_creation::{ handle_create_character, handle_create_npc, handle_create_waypoint, handle_shoot, }; use entity_manipulation::{ - handle_damage, handle_destroy, handle_explosion, handle_land_on_ground, handle_respawn, + handle_damage, handle_destroy, handle_explosion, handle_land_on_ground, handle_level_up, + handle_respawn, }; use interaction::{handle_lantern, handle_mount, handle_possess, handle_unmount}; use inventory_manip::handle_inventory; @@ -75,6 +76,7 @@ impl Server { body, main, } => handle_create_character(self, entity, character_id, body, main), + ServerEvent::LevelUp(entity, new_level) => handle_level_up(self, entity, new_level), ServerEvent::ExitIngame { entity } => handle_exit_ingame(self, entity), ServerEvent::CreateNpc { pos, From bfd97cac7e6b1d9d9467f98ae3978f823b259e56 Mon Sep 17 00:00:00 2001 From: scott-c Date: Mon, 1 Jun 2020 17:59:10 +0800 Subject: [PATCH 09/12] Fix build error --- client/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/lib.rs b/client/src/lib.rs index f078192d21..7d1437cf55 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -773,6 +773,8 @@ impl Client { uid {}, but this player's character is None.", next_level, uid ); + + None }, }; } From fe20da392325e211396e99f464a9d81acc4b077c Mon Sep 17 00:00:00 2001 From: scott-c Date: Mon, 1 Jun 2020 18:06:30 +0800 Subject: [PATCH 10/12] send level change event for set_level command --- server/src/cmd.rs | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 512769861e..02a9600ee3 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -1125,14 +1125,31 @@ fn handle_set_level( let (a_lvl, a_alias) = scan_fmt_some!(&args, &action.arg_fmt(), u32, String); if let Some(lvl) = a_lvl { - let ecs = server.state.ecs_mut(); - let target = find_target(&ecs, a_alias, target); + let target = find_target(&server.state.ecs(), a_alias, target); let mut error_msg = None; match target { Ok(player) => { - if let Some(stats) = ecs.write_storage::().get_mut(player) { + let uid = server + .state + .ecs() + .read_storage::() + .get(player) + .expect("Failed to get uid for player") + .0; + server + .state + .notify_registered_clients(ServerMsg::PlayerListUpdate( + PlayerListUpdate::LevelChange(uid, lvl), + )); + + if let Some(stats) = server + .state + .ecs_mut() + .write_storage::() + .get_mut(player) + { stats.level.set_level(lvl); stats.update_max_hp(); From 2d3f81b4c1536721f6d9778ad38ef92f15bb6684 Mon Sep 17 00:00:00 2001 From: scott-c Date: Mon, 1 Jun 2020 21:01:10 +0800 Subject: [PATCH 11/12] Add character info to /players command --- server/src/cmd.rs | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 02a9600ee3..0e380369ab 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -514,26 +514,28 @@ fn handle_players( _action: &ChatCommand, ) { let ecs = server.state.ecs(); - let players = ecs.read_storage::(); - let count = players.join().count(); - let header_message: String = format!("{} online players: \n", count); - if count > 0 { - let mut player_iter = players.join(); - let first = player_iter - .next() - .expect("Player iterator returned none.") - .alias - .to_owned(); - let player_list = player_iter.fold(first, |mut s, p| { - s += ",\n"; - s += &p.alias; - s - }); - server.notify_client(client, ServerMsg::private(header_message + &player_list)); - } else { - server.notify_client(client, ServerMsg::private(header_message)); - } + let entity_tuples = ( + &ecs.entities(), + &ecs.read_storage::(), + &ecs.read_storage::(), + ); + + server.notify_client( + client, + ServerMsg::private(entity_tuples.join().fold( + format!("{} online players:", entity_tuples.join().count()), + |s, (_, player, stat)| { + format!( + "{}\n[{}]{} Lvl {}", + s, + player.alias, + stat.name, + stat.level.level() + ) + }, + )), + ); } fn handle_build( From c899bdf6ab0d8e6dca54dd791dd6fda35373736f Mon Sep 17 00:00:00 2001 From: scott-c Date: Mon, 1 Jun 2020 22:21:54 +0800 Subject: [PATCH 12/12] Add to changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 372ff1f3b0..2bb2b31c15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Speech bubbles appear when nearby players talk - NPCs call for help when attacked - Eyebrows and shapes can now be selected +- Character name and level information to chat, social tab and `/players` command. ### Changed