Implement MR!1043 changes suggested by Imbris

This commit is contained in:
CapsizeGlimmer 2020-06-11 01:16:42 -04:00 committed by Forest Anderson
parent 34acc4ddf3
commit b7d7696d89
11 changed files with 59 additions and 103 deletions

View File

@ -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)
}

View File

@ -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<F>(&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(),
}
}
}

View File

@ -119,7 +119,7 @@ pub enum ServerEvent {
ClientDisconnect(EcsEntity),
ChunkRequest(EcsEntity, Vec2<i32>),
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),
}

View File

@ -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)),
);
}
}

View File

@ -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

View File

@ -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::<Client>(),
&ecs.read_storage::<comp::Pos>(),
)
.join()
{
let entity_opt = msg.uid().and_then(|uid| {
(*ecs.read_resource::<UidAllocator>()).retrieve_entity_internal(uid.0)
});
let positions = ecs.read_storage::<comp::Pos>();
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::<UidAllocator>()).retrieve_entity_internal(uid.0);
let positions = ecs.read_storage::<comp::Pos>();
if let Some(speaker_pos) = entity_opt.and_then(|e| positions.get(e)) {
for (client, pos) in (&mut ecs.write_storage::<Client>(), &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::<Client>(),
&ecs.read_storage::<comp::Pos>(),
)
.join()
{
let entity_opt = msg.uid().and_then(|uid| {
(*ecs.read_resource::<UidAllocator>()).retrieve_entity_internal(uid.0)
});
let positions = ecs.read_storage::<comp::Pos>();
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::<UidAllocator>()).retrieve_entity_internal(uid.0);
let positions = ecs.read_storage::<comp::Pos>();
if let Some(speaker_pos) = entity_opt.and_then(|e| positions.get(e)) {
for (client, pos) in (&mut ecs.write_storage::<Client>(), &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::<Client>(),
&ecs.read_storage::<comp::Pos>(),
)
.join()
{
let entity_opt = msg.uid().and_then(|uid| {
(*ecs.read_resource::<UidAllocator>()).retrieve_entity_internal(uid.0)
});
let positions = ecs.read_storage::<comp::Pos>();
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::<UidAllocator>()).retrieve_entity_internal(uid.0);
let positions = ecs.read_storage::<comp::Pos>();
if let Some(speaker_pos) = entity_opt.and_then(|e| positions.get(e)) {
for (client, pos) in (&mut ecs.write_storage::<Client>(), &positions).join() {
if is_within(comp::ChatMsg::NPC_DISTANCE, pos, speaker_pos) {
client.notify(ServerMsg::ChatMsg(msg.clone()));
}
}
}
},

View File

@ -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 {

View File

@ -22,8 +22,6 @@ pub type TerrainSyncTimer = SysTimer<terrain_sync::Sys>;
pub type WaypointTimer = SysTimer<waypoint::Sys>;
pub type PersistenceTimer = SysTimer<persistence::Sys>;
pub type PersistenceScheduler = SysScheduler<persistence::Sys>;
//pub type StatsPersistenceTimer = SysTimer<persistence::stats::Sys>;
//pub type StatsPersistenceScheduler = SysScheduler<persistence::stats::Sys>;
// System names
// Note: commented names may be useful in the future
@ -34,14 +32,11 @@ pub type PersistenceScheduler = SysScheduler<persistence::Sys>;
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) {

View File

@ -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::<Vec<_>>(),
)
});
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;
}

View File

@ -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(

View File

@ -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)