diff --git a/client/src/lib.rs b/client/src/lib.rs index 502340162f..77dbeeca91 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -1034,7 +1034,7 @@ impl Client { }; let message_format = |uid, message, group| { if let Some(group) = group { - format!("{{{}}} [{}]: {}", group, alias_of_uid(uid), message) + format!("({}) [{}]: {}", group, alias_of_uid(uid), message) } else { format!("[{}]: {}", alias_of_uid(uid), message) } diff --git a/common/src/comp/chat.rs b/common/src/comp/chat.rs index b93aebfbc6..420f46bdea 100644 --- a/common/src/comp/chat.rs +++ b/common/src/comp/chat.rs @@ -96,10 +96,10 @@ impl ChatMsg { pub fn to_bubble(&self) -> Option<(SpeechBubble, Uid)> { let icon = self.icon(); if let ChatType::Npc(from, r) = self.chat_type { - Some((SpeechBubble::npc_new(self.message.clone(), r, icon), from)) + Some((SpeechBubble::npc_new(&self.message, r, icon), from)) } else { self.uid() - .map(|from| (SpeechBubble::player_new(self.message.clone(), icon), from)) + .map(|from| (SpeechBubble::player_new(&self.message, icon), from)) } } @@ -194,8 +194,8 @@ impl SpeechBubble { /// Default duration in seconds of speech bubbles pub const DEFAULT_DURATION: f64 = 5.0; - pub fn npc_new(i18n_key: String, r: u16, icon: SpeechBubbleIcon) -> Self { - let message = SpeechBubbleMessage::Localized(i18n_key, r); + pub fn npc_new(i18n_key: &str, r: u16, icon: SpeechBubbleIcon) -> Self { + let message = SpeechBubbleMessage::Localized(i18n_key.to_string(), r); let timeout = Instant::now() + Duration::from_secs_f64(SpeechBubble::DEFAULT_DURATION); Self { message, @@ -204,8 +204,8 @@ impl SpeechBubble { } } - pub fn player_new(message: String, icon: SpeechBubbleIcon) -> Self { - let message = SpeechBubbleMessage::Plain(message); + pub fn player_new(message: &str, icon: SpeechBubbleIcon) -> Self { + let message = SpeechBubbleMessage::Plain(message.to_string()); let timeout = Instant::now() + Duration::from_secs_f64(SpeechBubble::DEFAULT_DURATION); Self { message, @@ -216,11 +216,11 @@ impl SpeechBubble { pub fn message(&self, i18n_variation: F) -> String where - F: Fn(String, u16) -> String, + F: Fn(&str, u16) -> String, { match &self.message { SpeechBubbleMessage::Plain(m) => m.to_string(), - SpeechBubbleMessage::Localized(k, i) => i18n_variation(k.to_string(), *i).to_string(), + SpeechBubbleMessage::Localized(k, i) => i18n_variation(&k, *i).to_string(), } } } diff --git a/common/src/event.rs b/common/src/event.rs index 3790cfb49d..d578029a3e 100644 --- a/common/src/event.rs +++ b/common/src/event.rs @@ -119,7 +119,7 @@ pub enum ServerEvent { ClientDisconnect(EcsEntity), ChunkRequest(EcsEntity, Vec2), ChatCmd(EcsEntity, String), - /// Send a chat message from an npc to the player + /// Send a chat message to the player from an npc or other player Chat(comp::ChatMsg), } diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 46219c0fe2..30f4f87d6d 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -392,12 +392,11 @@ fn handle_alias( action: &ChatCommand, ) { if client != target { - // Prevent people abusing /sudo + // Notify target that an admin changed the alias due to /sudo server.notify_client( - client, - ServerMsg::private(String::from("Don't call people names. It's mean.")), + target, + ServerMsg::private(String::from("An admin changed your alias.")), ); - return; } if let Ok(alias) = scan_fmt!(&args, &action.arg_fmt(), String) { if !comp::Player::alias_is_valid(&alias) { @@ -1284,7 +1283,7 @@ fn handle_join_group( // TODO notify group server.notify_client( client, - ServerMsg::private(format!("Joined group {{{}}}", group)), + ServerMsg::private(format!("Joined group ({})", group)), ); } else { let mode = comp::ChatMode::default(); @@ -1293,7 +1292,7 @@ fn handle_join_group( // TODO notify group server.notify_client( client, - ServerMsg::private(format!("Left group {{{}}}", group)), + ServerMsg::private(format!("Left group ({})", group)), ); } } diff --git a/server/src/lib.rs b/server/src/lib.rs index 0c7177c3a6..c18a22d421 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -115,7 +115,6 @@ impl Server { state.ecs_mut().insert(sys::TerrainTimer::default()); state.ecs_mut().insert(sys::WaypointTimer::default()); state.ecs_mut().insert(sys::PersistenceTimer::default()); - //state.ecs_mut().insert(sys::StatsPersistenceTimer::default()); // System schedulers to control execution of systems state diff --git a/server/src/state_ext.rs b/server/src/state_ext.rs index 7ad4462584..2fa9a4f4ef 100644 --- a/server/src/state_ext.rs +++ b/server/src/state_ext.rs @@ -244,13 +244,8 @@ impl StateExt for State { /// by location. Faction and group are limited by component. fn send_chat(&self, msg: comp::ChatMsg) { let ecs = self.ecs(); - let is_within = |target, a: &comp::Pos, b_opt: Option<&comp::Pos>| { - if let Some(b) = b_opt { - a.0.distance(b.0) < target - } else { - false - } - }; + let is_within = + |target, a: &comp::Pos, b: &comp::Pos| a.0.distance_squared(b.0) < target * target; match &msg.chat_type { comp::ChatType::Broadcast | comp::ChatType::Kill @@ -271,54 +266,39 @@ impl StateExt for State { } }, - comp::ChatType::Say(_u) => { - for (client, pos) in ( - &mut ecs.write_storage::(), - &ecs.read_storage::(), - ) - .join() - { - let entity_opt = msg.uid().and_then(|uid| { - (*ecs.read_resource::()).retrieve_entity_internal(uid.0) - }); - let positions = ecs.read_storage::(); - let pos_opt = entity_opt.and_then(|e| positions.get(e)); - if is_within(comp::ChatMsg::SAY_DISTANCE, pos, pos_opt) { - client.notify(ServerMsg::ChatMsg(msg.clone())); + comp::ChatType::Say(uid) => { + let entity_opt = + (*ecs.read_resource::()).retrieve_entity_internal(uid.0); + let positions = ecs.read_storage::(); + if let Some(speaker_pos) = entity_opt.and_then(|e| positions.get(e)) { + for (client, pos) in (&mut ecs.write_storage::(), &positions).join() { + if is_within(comp::ChatMsg::SAY_DISTANCE, pos, speaker_pos) { + client.notify(ServerMsg::ChatMsg(msg.clone())); + } } } }, - comp::ChatType::Region(_u) => { - for (client, pos) in ( - &mut ecs.write_storage::(), - &ecs.read_storage::(), - ) - .join() - { - let entity_opt = msg.uid().and_then(|uid| { - (*ecs.read_resource::()).retrieve_entity_internal(uid.0) - }); - let positions = ecs.read_storage::(); - let pos_opt = entity_opt.and_then(|e| positions.get(e)); - if is_within(comp::ChatMsg::REGION_DISTANCE, pos, pos_opt) { - client.notify(ServerMsg::ChatMsg(msg.clone())); + comp::ChatType::Region(uid) => { + let entity_opt = + (*ecs.read_resource::()).retrieve_entity_internal(uid.0); + let positions = ecs.read_storage::(); + if let Some(speaker_pos) = entity_opt.and_then(|e| positions.get(e)) { + for (client, pos) in (&mut ecs.write_storage::(), &positions).join() { + if is_within(comp::ChatMsg::REGION_DISTANCE, pos, speaker_pos) { + client.notify(ServerMsg::ChatMsg(msg.clone())); + } } } }, - comp::ChatType::Npc(_u, _r) => { - for (client, pos) in ( - &mut ecs.write_storage::(), - &ecs.read_storage::(), - ) - .join() - { - let entity_opt = msg.uid().and_then(|uid| { - (*ecs.read_resource::()).retrieve_entity_internal(uid.0) - }); - let positions = ecs.read_storage::(); - let pos_opt = entity_opt.and_then(|e| positions.get(e)); - if is_within(comp::ChatMsg::NPC_DISTANCE, pos, pos_opt) { - client.notify(ServerMsg::ChatMsg(msg.clone())); + comp::ChatType::Npc(uid, _r) => { + let entity_opt = + (*ecs.read_resource::()).retrieve_entity_internal(uid.0); + let positions = ecs.read_storage::(); + if let Some(speaker_pos) = entity_opt.and_then(|e| positions.get(e)) { + for (client, pos) in (&mut ecs.write_storage::(), &positions).join() { + if is_within(comp::ChatMsg::NPC_DISTANCE, pos, speaker_pos) { + client.notify(ServerMsg::ChatMsg(msg.clone())); + } } } }, diff --git a/server/src/sys/message.rs b/server/src/sys/message.rs index 3c35a02fd8..280dd48c40 100644 --- a/server/src/sys/message.rs +++ b/server/src/sys/message.rs @@ -337,10 +337,7 @@ impl<'a> System<'a> for Sys { | ClientState::Character => match validate_chat_msg(&message) { Ok(()) => { if let Some(from) = uids.get(entity) { - let mode = chat_modes - .get(entity) - .map(Clone::clone) - .unwrap_or(ChatMode::default()); + let mode = chat_modes.get(entity).cloned().unwrap_or_default(); let msg = mode.new_message(*from, message); new_chat_msgs.push((Some(entity), msg)); } else { diff --git a/server/src/sys/mod.rs b/server/src/sys/mod.rs index 38aa19d4f5..41a7227bb2 100644 --- a/server/src/sys/mod.rs +++ b/server/src/sys/mod.rs @@ -22,8 +22,6 @@ pub type TerrainSyncTimer = SysTimer; pub type WaypointTimer = SysTimer; pub type PersistenceTimer = SysTimer; pub type PersistenceScheduler = SysScheduler; -//pub type StatsPersistenceTimer = SysTimer; -//pub type StatsPersistenceScheduler = SysScheduler; // System names // Note: commented names may be useful in the future @@ -34,14 +32,11 @@ pub type PersistenceScheduler = SysScheduler; const TERRAIN_SYS: &str = "server_terrain_sys"; const WAYPOINT_SYS: &str = "waypoint_sys"; const PERSISTENCE_SYS: &str = "persistence_sys"; -//const STATS_PERSISTENCE_SYS: &str = "stats_persistence_sys"; pub fn add_server_systems(dispatch_builder: &mut DispatcherBuilder) { dispatch_builder.add(terrain::Sys, TERRAIN_SYS, &[]); dispatch_builder.add(waypoint::Sys, WAYPOINT_SYS, &[]); dispatch_builder.add(persistence::Sys, PERSISTENCE_SYS, &[]); - //dispatch_builder.add(persistence::stats::Sys, STATS_PERSISTENCE_SYS, - // &[]); } pub fn run_sync_systems(ecs: &mut specs::World) { diff --git a/voxygen/src/hud/chat.rs b/voxygen/src/hud/chat.rs index 8c19a63166..4497145443 100644 --- a/voxygen/src/hud/chat.rs +++ b/voxygen/src/hud/chat.rs @@ -163,17 +163,7 @@ impl<'a> Widget for Chat<'a> { let transp = self.global_state.settings.gameplay.chat_transp; // Maintain scrolling. if !self.new_messages.is_empty() { - state.update(|s| { - s.messages.extend( - self.new_messages - .drain(..) - .map(|msg| { - // TODO format!([{}] {}, name, msg) - msg - }) - .collect::>(), - ) - }); + state.update(|s| s.messages.extend(self.new_messages.drain(..))); ui.scroll_widget(state.ids.message_box, [0.0, std::f64::MAX]); } @@ -354,8 +344,7 @@ impl<'a> Widget for Chat<'a> { Dimension::Absolute(y) => y + 2.0, _ => 0.0, }; - let widget = text.h(y); - item.set(widget, ui); + item.set(text.h(y), ui); let icon_id = state.ids.chat_icons[item.i]; Image::new(icon) .w_h(16.0, 16.0) @@ -365,11 +354,13 @@ impl<'a> Widget for Chat<'a> { } else { // Spacer at bottom of the last message so that it is not cut off. // Needs to be larger than the space above. - let widget = Text::new("") - .font_size(self.fonts.opensans.scale(6)) - .font_id(self.fonts.opensans.conrod_id) - .w(CHAT_BOX_WIDTH); - item.set(widget, ui); + item.set( + Text::new("") + .font_size(self.fonts.opensans.scale(6)) + .font_id(self.fonts.opensans.conrod_id) + .w(CHAT_BOX_WIDTH), + ui, + ); }; } @@ -432,7 +423,6 @@ fn do_tab_completion(cursor: usize, input: &str, word: &str) -> (String, usize) if char_i < cursor { pre_ws = Some(byte_i); } else { - assert_eq!(post_ws, None); // TODO debug post_ws = Some(byte_i); break; } diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index efcb3c5190..747e5545eb 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -940,8 +940,9 @@ impl Hud { } // Pop speech bubbles + let now = Instant::now(); self.speech_bubbles - .retain(|_uid, bubble| bubble.timeout > Instant::now()); + .retain(|_uid, bubble| bubble.timeout > now); // Push speech bubbles for msg in self.new_messages.iter() { @@ -1570,13 +1571,8 @@ impl Hud { } // Don't put NPC messages in chat box. - self.new_messages.retain(|m| { - if let comp::ChatType::Npc(_, _) = m.chat_type { - false - } else { - true - } - }); + self.new_messages + .retain(|m| !matches!(m.chat_type, comp::ChatType::Npc(_, _))); // Chat box match Chat::new( diff --git a/voxygen/src/hud/overhead.rs b/voxygen/src/hud/overhead.rs index dc7e4bae46..5dbb1c8b33 100644 --- a/voxygen/src/hud/overhead.rs +++ b/voxygen/src/hud/overhead.rs @@ -148,7 +148,7 @@ impl<'a> Widget for Overhead<'a> { if let Some(bubble) = self.bubble { let dark_mode = self.settings.speech_bubble_dark_mode; let localizer = - |s: String, i| -> String { self.voxygen_i18n.get_variation(&s, i).to_string() }; + |s: &str, i| -> String { self.voxygen_i18n.get_variation(&s, i).to_string() }; let bubble_contents: String = bubble.message(localizer); let mut text = Text::new(&bubble_contents)