Expose player gender to existing chat messages

TODO: localize /tell and expose gender in 'hud-chat-you'
This commit is contained in:
juliancoffee 2024-02-02 20:25:46 +02:00
parent 490a8d8776
commit f7b8e079b4

View File

@ -1,9 +1,12 @@
#![feature(let_chains)] #![feature(let_chains)]
use std::borrow::Cow; use std::borrow::Cow;
use common::comp::{ use common::{
chat::{KillSource, KillType}, comp::{
BuffKind, ChatMsg, ChatType, Content, chat::{KillSource, KillType},
BuffKind, ChatMsg, ChatType, Content,
},
uid::Uid,
}; };
use common_net::msg::{ChatTypeContext, PlayerInfo}; use common_net::msg::{ChatTypeContext, PlayerInfo};
use i18n::Localization; use i18n::Localization;
@ -16,8 +19,8 @@ pub fn localize_chat_message(
) -> (ChatType<String>, String) { ) -> (ChatType<String>, String) {
let info = lookup_fn(&msg); let info = lookup_fn(&msg);
let name_format = |uid: &common::uid::Uid| match info.player_alias.get(uid).cloned() { let name_format_or_you = |you, uid: &Uid| match info.player_alias.get(uid).cloned() {
Some(pi) => insert_alias(info.you == *uid, pi, localization), Some(pi) => insert_alias(you && info.you == *uid, pi, localization),
None => info None => info
.entity_name .entity_name
.get(uid) .get(uid)
@ -25,8 +28,13 @@ pub fn localize_chat_message(
.expect("client didn't proved enough info"), .expect("client didn't proved enough info"),
}; };
let message_format = |from: &common::uid::Uid, content: &Content, group: Option<&String>| { let name_format = |uid: &Uid| name_format_or_you(false, uid);
let alias = name_format(from);
// FIXME: this shouldn't pass review!
let gender_str = |uid: &Uid| "he".to_owned();
let message_format = |from: &Uid, content: &Content, group: Option<&String>| {
let alias = name_format_or_you(true, from);
let name = if let Some(pi) = info.player_alias.get(from).cloned() && show_char_name { let name = if let Some(pi) = info.player_alias.get(from).cloned() && show_char_name {
pi.character.map(|c| c.name) pi.character.map(|c| c.name)
} else { } else {
@ -35,8 +43,8 @@ pub fn localize_chat_message(
let message = localization.get_content(content); let message = localization.get_content(content);
match (group, name) { match (group, name) {
(Some(group), None) => format!("({group}) [{alias}]: {message}"), (Some(group), None) => format!("({group}) [{alias}]: {message}"),
(None, None) => format!("[{alias}]: {message}"),
(Some(group), Some(name)) => format!("({group}) [{alias}] {name}: {message}"), (Some(group), Some(name)) => format!("({group}) [{alias}] {name}: {message}"),
(None, None) => format!("[{alias}]: {message}"),
(None, Some(name)) => format!("[{alias}] {name}: {message}"), (None, Some(name)) => format!("[{alias}] {name}: {message}"),
} }
}; };
@ -44,19 +52,20 @@ pub fn localize_chat_message(
let new_msg = match &msg.chat_type { let new_msg = match &msg.chat_type {
ChatType::Online(uid) => localization ChatType::Online(uid) => localization
.get_msg_ctx("hud-chat-online_msg", &i18n::fluent_args! { .get_msg_ctx("hud-chat-online_msg", &i18n::fluent_args! {
"user_gender" => gender_str(uid),
"name" => name_format(uid), "name" => name_format(uid),
}) })
.into_owned(), .into_owned(),
ChatType::Offline(uid) => localization ChatType::Offline(uid) => localization
.get_msg_ctx("hud-chat-offline_msg", &i18n::fluent_args! { .get_msg_ctx("hud-chat-offline_msg", &i18n::fluent_args! {
"name" => name_format(uid "user_gender" => gender_str(uid),
), "name" => name_format(uid),
}) })
.into_owned(), .into_owned(),
ChatType::CommandError => localization.get_content(msg.content()), ChatType::CommandError
ChatType::CommandInfo => localization.get_content(msg.content()), | ChatType::CommandInfo
ChatType::FactionMeta(_) => localization.get_content(msg.content()), | ChatType::FactionMeta(_)
ChatType::GroupMeta(_) => localization.get_content(msg.content()), | ChatType::GroupMeta(_) => localization.get_content(msg.content()),
ChatType::Tell(from, to) => { ChatType::Tell(from, to) => {
let from_alias = name_format(from); let from_alias = name_format(from);
let to_alias = name_format(to); let to_alias = name_format(to);
@ -73,15 +82,15 @@ pub fn localize_chat_message(
) )
} }
}, },
ChatType::Say(uid) => message_format(uid, msg.content(), None), ChatType::Say(uid) | ChatType::Region(uid) | ChatType::World(uid) => {
ChatType::Group(uid, s) => message_format(uid, msg.content(), Some(s)), message_format(uid, msg.content(), None)
ChatType::Faction(uid, s) => message_format(uid, msg.content(), Some(s)), },
ChatType::Region(uid) => message_format(uid, msg.content(), None), ChatType::Group(uid, descriptor) | ChatType::Faction(uid, descriptor) => {
ChatType::World(uid) => message_format(uid, msg.content(), None), message_format(uid, msg.content(), Some(descriptor))
},
// NPCs can't talk. Should be filtered by hud/mod.rs for voxygen and // NPCs can't talk. Should be filtered by hud/mod.rs for voxygen and
// should be filtered by server (due to not having a Pos) for chat-cli // should be filtered by server (due to not having a Pos) for chat-cli
ChatType::Npc(uid) => message_format(uid, msg.content(), None), ChatType::Npc(uid) | ChatType::NpcSay(uid) => message_format(uid, msg.content(), None),
ChatType::NpcSay(uid) => message_format(uid, msg.content(), None),
ChatType::NpcTell(from, to) => { ChatType::NpcTell(from, to) => {
let from_alias = name_format(from); let from_alias = name_format(from);
let to_alias = name_format(to); let to_alias = name_format(to);
@ -100,158 +109,183 @@ pub fn localize_chat_message(
}, },
ChatType::Meta => localization.get_content(msg.content()), ChatType::Meta => localization.get_content(msg.content()),
ChatType::Kill(kill_source, victim) => { ChatType::Kill(kill_source, victim) => {
let get_buff_ident = |buff| match buff { localize_kill_message(kill_source, victim, name_format, gender_str, localization)
BuffKind::Burning => "burning",
BuffKind::Bleeding => "bleeding",
BuffKind::Cursed => "curse",
BuffKind::Crippled => "crippled",
BuffKind::Frozen => "frozen",
BuffKind::Regeneration
| BuffKind::Saturation
| BuffKind::Potion
| BuffKind::Agility
| BuffKind::CampfireHeal
| BuffKind::EnergyRegen
| BuffKind::IncreaseMaxEnergy
| BuffKind::IncreaseMaxHealth
| BuffKind::Invulnerability
| BuffKind::ProtectingWard
| BuffKind::Frenzied
| BuffKind::Hastened
| BuffKind::Fortitude
| BuffKind::Reckless
| BuffKind::Flame
| BuffKind::Frigid
| BuffKind::Lifesteal
// | BuffKind::SalamanderAspect
| BuffKind::ImminentCritical
| BuffKind::Fury
| BuffKind::Sunderer
| BuffKind::Defiance
| BuffKind::Bloodfeast
| BuffKind::Berserk => {
tracing::error!("Player was killed by a positive buff!");
"mysterious"
},
BuffKind::Wet
| BuffKind::Ensnared
| BuffKind::Poisoned
| BuffKind::Parried
| BuffKind::PotionSickness
| BuffKind::Polymorphed
| BuffKind::Heatstroke => {
tracing::error!("Player was killed by a debuff that doesn't do damage!");
"mysterious"
},
};
match kill_source {
// Buff deaths
KillSource::Player(attacker, KillType::Buff(buff_kind)) => {
let buff_ident = get_buff_ident(*buff_kind);
let s = localization
.get_attr_ctx(
"hud-chat-died_of_pvp_buff_msg",
buff_ident,
&i18n::fluent_args! {
"victim" => name_format(victim),
"attacker" => name_format(attacker),
},
)
.into_owned();
Cow::Owned(s)
},
KillSource::NonPlayer(attacker_name, KillType::Buff(buff_kind)) => {
let buff_ident = get_buff_ident(*buff_kind);
let s = localization
.get_attr_ctx(
"hud-chat-died_of_npc_buff_msg",
buff_ident,
&i18n::fluent_args! {
"victim" => name_format(victim),
"attacker" => attacker_name,
},
)
.into_owned();
Cow::Owned(s)
},
KillSource::NonExistent(KillType::Buff(buff_kind)) => {
let buff_ident = get_buff_ident(*buff_kind);
let s = localization
.get_attr_ctx(
"hud-chat-died_of_buff_nonexistent_msg",
buff_ident,
&i18n::fluent_args! {
"victim" => name_format(victim),
},
)
.into_owned();
Cow::Owned(s)
},
// PvP deaths
KillSource::Player(attacker, kill_type) => {
let key = match kill_type {
KillType::Melee => "hud-chat-pvp_melee_kill_msg",
KillType::Projectile => "hud-chat-pvp_ranged_kill_msg",
KillType::Explosion => "hud-chat-pvp_explosion_kill_msg",
KillType::Energy => "hud-chat-pvp_energy_kill_msg",
KillType::Other => "hud-chat-pvp_other_kill_msg",
&KillType::Buff(_) => unreachable!("handled above"),
};
localization.get_msg_ctx(key, &i18n::fluent_args! {
"victim" => name_format(victim),
"attacker" => name_format(attacker),
})
},
// PvE deaths
KillSource::NonPlayer(attacker_name, kill_type) => {
let key = match kill_type {
KillType::Melee => "hud-chat-npc_melee_kill_msg",
KillType::Projectile => "hud-chat-npc_ranged_kill_msg",
KillType::Explosion => "hud-chat-npc_explosion_kill_msg",
KillType::Energy => "hud-chat-npc_energy_kill_msg",
KillType::Other => "hud-chat-npc_other_kill_msg",
&KillType::Buff(_) => unreachable!("handled above"),
};
localization.get_msg_ctx(key, &i18n::fluent_args! {
"victim" => name_format(victim),
"attacker" => attacker_name,
})
},
// Other deaths
KillSource::Environment(environment) => {
localization.get_msg_ctx("hud-chat-environment_kill_msg", &i18n::fluent_args! {
"name" => name_format(victim),
"environment" => environment,
})
},
KillSource::FallDamage => {
localization.get_msg_ctx("hud-chat-fall_kill_msg", &i18n::fluent_args! {
"name" => name_format(victim),
})
},
KillSource::Suicide => {
localization.get_msg_ctx("hud-chat-suicide_msg", &i18n::fluent_args! {
"name" => name_format(victim),
})
},
KillSource::NonExistent(_) | KillSource::Other => {
localization.get_msg_ctx("hud-chat-default_death_msg", &i18n::fluent_args! {
"name" => name_format(victim),
})
},
}
.into_owned()
}, },
}; };
(msg.chat_type, new_msg) (msg.chat_type, new_msg)
} }
fn localize_kill_message(
kill_source: &KillSource,
victim: &Uid,
name_format: impl Fn(&Uid) -> String,
gender_str: impl Fn(&Uid) -> String,
localization: &Localization,
) -> String {
match kill_source {
// Buff deaths
KillSource::Player(attacker, KillType::Buff(buff_kind)) => {
let buff_ident = get_buff_ident(*buff_kind);
let s = localization
.get_attr_ctx(
"hud-chat-died_of_pvp_buff_msg",
buff_ident,
&i18n::fluent_args! {
"victim" => name_format(victim),
"victim_gender" => gender_str(victim),
"attacker" => name_format(attacker),
"attacker_gender" => gender_str(attacker),
},
)
.into_owned();
Cow::Owned(s)
},
KillSource::NonPlayer(attacker_name, KillType::Buff(buff_kind)) => {
let buff_ident = get_buff_ident(*buff_kind);
let s = localization
.get_attr_ctx(
"hud-chat-died_of_npc_buff_msg",
buff_ident,
&i18n::fluent_args! {
"victim" => name_format(victim),
"victim_gender" => gender_str(victim),
"attacker" => attacker_name,
},
)
.into_owned();
Cow::Owned(s)
},
KillSource::NonExistent(KillType::Buff(buff_kind)) => {
let buff_ident = get_buff_ident(*buff_kind);
let s = localization
.get_attr_ctx(
"hud-chat-died_of_buff_nonexistent_msg",
buff_ident,
&i18n::fluent_args! {
"victim" => name_format(victim),
"victim_gender" => gender_str(victim),
},
)
.into_owned();
Cow::Owned(s)
},
// PvP deaths
KillSource::Player(attacker, kill_type) => {
let key = match kill_type {
KillType::Melee => "hud-chat-pvp_melee_kill_msg",
KillType::Projectile => "hud-chat-pvp_ranged_kill_msg",
KillType::Explosion => "hud-chat-pvp_explosion_kill_msg",
KillType::Energy => "hud-chat-pvp_energy_kill_msg",
KillType::Other => "hud-chat-pvp_other_kill_msg",
&KillType::Buff(_) => unreachable!("handled above"),
};
localization.get_msg_ctx(key, &i18n::fluent_args! {
"victim" => name_format(victim),
"victim_gender" => gender_str(victim),
"attacker" => name_format(attacker),
"attacker_gender" => gender_str(attacker),
})
},
// PvE deaths
KillSource::NonPlayer(attacker_name, kill_type) => {
let key = match kill_type {
KillType::Melee => "hud-chat-npc_melee_kill_msg",
KillType::Projectile => "hud-chat-npc_ranged_kill_msg",
KillType::Explosion => "hud-chat-npc_explosion_kill_msg",
KillType::Energy => "hud-chat-npc_energy_kill_msg",
KillType::Other => "hud-chat-npc_other_kill_msg",
&KillType::Buff(_) => unreachable!("handled above"),
};
localization.get_msg_ctx(key, &i18n::fluent_args! {
"victim" => name_format(victim),
"victim_gender" => gender_str(victim),
"attacker" => attacker_name,
})
},
// Other deaths
KillSource::Environment(environment) => {
localization.get_msg_ctx("hud-chat-environment_kill_msg", &i18n::fluent_args! {
"name" => name_format(victim),
"victim_gender" => gender_str(victim),
"environment" => environment,
})
},
KillSource::FallDamage => {
localization.get_msg_ctx("hud-chat-fall_kill_msg", &i18n::fluent_args! {
"name" => name_format(victim),
"victim_gender" => gender_str(victim),
})
},
KillSource::Suicide => {
localization.get_msg_ctx("hud-chat-suicide_msg", &i18n::fluent_args! {
"name" => name_format(victim),
"victim_gender" => gender_str(victim),
})
},
KillSource::NonExistent(_) | KillSource::Other => {
localization.get_msg_ctx("hud-chat-default_death_msg", &i18n::fluent_args! {
"name" => name_format(victim),
"victim_gender" => gender_str(victim),
})
},
}
.into_owned()
}
// determine attr for `hud-chat-died-of-buff`
fn get_buff_ident(buff: BuffKind) -> &'static str {
match buff {
BuffKind::Burning => "burning",
BuffKind::Bleeding => "bleeding",
BuffKind::Cursed => "curse",
BuffKind::Crippled => "crippled",
BuffKind::Frozen => "frozen",
BuffKind::Regeneration
| BuffKind::Saturation
| BuffKind::Potion
| BuffKind::Agility
| BuffKind::CampfireHeal
| BuffKind::EnergyRegen
| BuffKind::IncreaseMaxEnergy
| BuffKind::IncreaseMaxHealth
| BuffKind::Invulnerability
| BuffKind::ProtectingWard
| BuffKind::Frenzied
| BuffKind::Hastened
| BuffKind::Fortitude
| BuffKind::Reckless
| BuffKind::Flame
| BuffKind::Frigid
| BuffKind::Lifesteal
// | BuffKind::SalamanderAspect
| BuffKind::ImminentCritical
| BuffKind::Fury
| BuffKind::Sunderer
| BuffKind::Defiance
| BuffKind::Bloodfeast
| BuffKind::Berserk => {
tracing::error!("Player was killed by a positive buff!");
"mysterious"
},
BuffKind::Wet
| BuffKind::Ensnared
| BuffKind::Poisoned
| BuffKind::Parried
| BuffKind::PotionSickness
| BuffKind::Polymorphed
| BuffKind::Heatstroke => {
tracing::error!("Player was killed by a debuff that doesn't do damage!");
"mysterious"
},
}
}
fn insert_alias(you: bool, info: PlayerInfo, localization: &Localization) -> String { fn insert_alias(you: bool, info: PlayerInfo, localization: &Localization) -> String {
// FIXME: this should take gender into account
const YOU: &str = "hud-chat-you"; const YOU: &str = "hud-chat-you";
// Leave space for a mod badge icon. // Leave space for a mod badge icon.
const MOD_SPACING: &str = " "; const MOD_SPACING: &str = " ";
@ -259,7 +293,7 @@ fn insert_alias(you: bool, info: PlayerInfo, localization: &Localization) -> Str
(false, false) => info.player_alias, (false, false) => info.player_alias,
(false, true) => localization.get_msg(YOU).to_string(), (false, true) => localization.get_msg(YOU).to_string(),
(true, false) => format!("{}{}", MOD_SPACING, info.player_alias), (true, false) => format!("{}{}", MOD_SPACING, info.player_alias),
(true, true) => format!("{}{}", MOD_SPACING, &localization.get_msg(YOU),), (true, true) => format!("{}{}", MOD_SPACING, &localization.get_msg(YOU)),
} }
} }