Add Gender marker for body

- Add gender() method on body, which is derived from body_type
- Expose it in ChatContext so that chat i18n can use it.
This commit is contained in:
juliancoffee 2024-01-19 22:33:50 +02:00
parent 3ebf17370c
commit af396aa8dd
4 changed files with 132 additions and 38 deletions

View File

@ -2870,10 +2870,13 @@ impl Client {
}
/// Change player alias to "You" if client belongs to matching player
// TODO: move this to voxygen or i18n-helpers and properly localize there
// or what's better, just remove completely, it won't properly work with
// localization anyway.
pub fn personalize_alias(&self, uid: Uid, alias: String) -> String {
let client_uid = self.uid().expect("Client doesn't have a Uid!!!");
if client_uid == uid {
"You".to_string() // TODO: Localize
"You".to_string()
} else {
alias
}
@ -2886,7 +2889,9 @@ impl Client {
you: self.uid().expect("Client doesn't have a Uid!!!"),
player_alias: HashMap::new(),
entity_name: HashMap::new(),
gender: HashMap::new(),
};
let name_of_uid = |uid| {
let ecs = self.state.ecs();
(
@ -2897,53 +2902,67 @@ impl Client {
.find(|(_, u)| u == &uid)
.map(|(c, _)| c.name.clone())
};
let mut alias_of_uid = |uid| match self.player_list.get(uid) {
Some(player_info) => {
result.player_alias.insert(*uid, player_info.clone());
},
None => {
result
.entity_name
.insert(*uid, name_of_uid(uid).unwrap_or_else(|| "<?>".to_string()));
},
let gender_of_uid = |uid| {
let ecs = self.state.ecs();
(
&ecs.read_storage::<comp::Stats>(),
&ecs.read_storage::<Uid>(),
)
.join()
.find(|(_, u)| u == &uid)
.map(|(c, _)| c.original_body.gender())
};
let mut add_data_of = |uid| {
match self.player_list.get(uid) {
Some(player_info) => {
result.player_alias.insert(*uid, player_info.clone());
},
None => {
result
.entity_name
.insert(*uid, name_of_uid(uid).unwrap_or_else(|| "<?>".to_string()));
},
};
result
.gender
.insert(*uid, gender_of_uid(uid).unwrap_or(comp::Gender::Masculine));
};
match &msg.chat_type {
comp::ChatType::Online(uid) | comp::ChatType::Offline(uid) => {
alias_of_uid(uid);
},
comp::ChatType::CommandError => (),
comp::ChatType::CommandInfo => (),
comp::ChatType::FactionMeta(_) => (),
comp::ChatType::GroupMeta(_) => (),
comp::ChatType::Online(uid) | comp::ChatType::Offline(uid) => add_data_of(uid),
comp::ChatType::Kill(kill_source, victim) => {
alias_of_uid(victim);
add_data_of(victim);
match kill_source {
KillSource::Player(attacker_uid, _) => {
alias_of_uid(attacker_uid);
add_data_of(attacker_uid);
},
KillSource::NonPlayer(_, _) => (),
KillSource::Environment(_) => (),
KillSource::FallDamage => (),
KillSource::Suicide => (),
KillSource::NonExistent(_) => (),
KillSource::Other => (),
KillSource::NonPlayer(_, _)
| KillSource::Environment(_)
| KillSource::FallDamage
| KillSource::Suicide
| KillSource::NonExistent(_)
| KillSource::Other => (),
};
},
comp::ChatType::Tell(from, to) | comp::ChatType::NpcTell(from, to) => {
alias_of_uid(from);
alias_of_uid(to);
add_data_of(from);
add_data_of(to);
},
comp::ChatType::Say(uid)
| comp::ChatType::Region(uid)
| comp::ChatType::World(uid)
| comp::ChatType::NpcSay(uid) => {
alias_of_uid(uid);
},
comp::ChatType::Group(uid, _) | comp::ChatType::Faction(uid, _) => {
alias_of_uid(uid);
},
comp::ChatType::Npc(uid) => alias_of_uid(uid),
comp::ChatType::Meta => (),
| comp::ChatType::NpcSay(uid)
| comp::ChatType::Group(uid, _)
| comp::ChatType::Faction(uid, _)
| comp::ChatType::Npc(uid) => add_data_of(uid),
comp::ChatType::CommandError
| comp::ChatType::CommandInfo
| comp::ChatType::FactionMeta(_)
| comp::ChatType::GroupMeta(_)
| comp::ChatType::Meta => (),
};
result
}

View File

@ -6,7 +6,7 @@ use crate::sync;
use common::{
calendar::Calendar,
character::{self, CharacterItem},
comp::{self, invite::InviteKind, item::MaterialStatManifest, Content},
comp::{self, body::Gender, invite::InviteKind, item::MaterialStatManifest, Content},
event::UpdateCharacterMetadata,
lod,
outcome::Outcome,
@ -35,7 +35,7 @@ pub enum ServerMsg {
Init(Box<ServerInit>),
/// Result to `ClientMsg::Register`. send ONCE
RegisterAnswer(ServerRegisterAnswer),
///Msg that can be send ALWAYS as soon as client is registered, e.g. `Chat`
/// Msg that can be send ALWAYS as soon as client is registered, e.g. `Chat`
General(ServerGeneral),
Ping(PingMsg),
}
@ -259,6 +259,7 @@ pub struct ChatTypeContext {
pub you: Uid,
pub player_alias: HashMap<Uid, PlayerInfo>,
pub entity_name: HashMap<Uid, String>,
pub gender: HashMap<Uid, Gender>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]

View File

@ -198,6 +198,12 @@ impl<
const EXTENSION: &'static str = "ron";
}
// Grammatical gender
pub enum Gender {
Masculine,
Feminine,
}
impl Body {
pub fn is_same_species_as(&self, other: &Body) -> bool {
match self {
@ -1352,6 +1358,74 @@ impl Body {
_ => Content::localized("body-generic"),
}
}
pub fn gender(&self) -> Gender {
match self {
Body::Humanoid(b) => match b.body_type {
humanoid::BodyType::Male => Gender::Masculine,
humanoid::BodyType::Female => Gender::Feminine,
},
Body::QuadrupedSmall(b) => match b.body_type {
quadruped_small::BodyType::Male => Gender::Masculine,
quadruped_small::BodyType::Female => Gender::Feminine,
},
Body::QuadrupedMedium(b) => match b.body_type {
quadruped_medium::BodyType::Male => Gender::Masculine,
quadruped_medium::BodyType::Female => Gender::Feminine,
},
Body::BirdMedium(b) => match b.body_type {
bird_medium::BodyType::Male => Gender::Masculine,
bird_medium::BodyType::Female => Gender::Feminine,
},
Body::FishMedium(b) => match b.body_type {
fish_medium::BodyType::Male => Gender::Masculine,
fish_medium::BodyType::Female => Gender::Feminine,
},
Body::Dragon(b) => match b.body_type {
dragon::BodyType::Male => Gender::Masculine,
dragon::BodyType::Female => Gender::Feminine,
},
Body::BirdLarge(b) => match b.body_type {
bird_large::BodyType::Male => Gender::Masculine,
bird_large::BodyType::Female => Gender::Feminine,
},
Body::FishSmall(b) => match b.body_type {
fish_small::BodyType::Male => Gender::Masculine,
fish_small::BodyType::Female => Gender::Feminine,
},
Body::BipedLarge(b) => match b.body_type {
biped_large::BodyType::Male => Gender::Masculine,
biped_large::BodyType::Female => Gender::Feminine,
},
Body::BipedSmall(b) => match b.body_type {
biped_small::BodyType::Male => Gender::Masculine,
biped_small::BodyType::Female => Gender::Feminine,
},
Body::Golem(b) => match b.body_type {
golem::BodyType::Male => Gender::Masculine,
golem::BodyType::Female => Gender::Feminine,
},
Body::Theropod(b) => match b.body_type {
theropod::BodyType::Male => Gender::Masculine,
theropod::BodyType::Female => Gender::Feminine,
},
Body::QuadrupedLow(b) => match b.body_type {
quadruped_low::BodyType::Male => Gender::Masculine,
quadruped_low::BodyType::Female => Gender::Feminine,
},
Body::Arthropod(b) => match b.body_type {
arthropod::BodyType::Male => Gender::Masculine,
arthropod::BodyType::Female => Gender::Feminine,
},
Body::Crustacean(b) => match b.body_type {
crustacean::BodyType::Male => Gender::Masculine,
crustacean::BodyType::Female => Gender::Feminine,
},
Body::ItemDrop(_) | Body::Object(_) | Body::Ship(_) => {
panic!("we don't care about item gender")
},
}
}
}
impl Component for Body {

View File

@ -54,7 +54,7 @@ pub use self::{
body::{
arthropod, biped_large, biped_small, bird_large, bird_medium, crustacean, dragon,
fish_medium, fish_small, golem, humanoid, item_drop, object, quadruped_low,
quadruped_medium, quadruped_small, ship, theropod, AllBodies, Body, BodyData,
quadruped_medium, quadruped_small, ship, theropod, AllBodies, Body, BodyData, Gender,
},
buff::{
Buff, BuffCategory, BuffChange, BuffData, BuffEffect, BuffKey, BuffKind, BuffSource, Buffs,