mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Implement gender, kind of
This commit is contained in:
parent
273ac621a9
commit
eeb7cab8c3
@ -2911,7 +2911,7 @@ impl Client {
|
|||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
.find(|(_, u)| u == &uid)
|
.find(|(_, u)| u == &uid)
|
||||||
.map(|(c, _)| c.original_body.gender())
|
.and_then(|(c, _)| c.original_body.humanoid_gender())
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut add_data_of = |uid| {
|
let mut add_data_of = |uid| {
|
||||||
|
@ -198,7 +198,14 @@ impl<
|
|||||||
const EXTENSION: &'static str = "ron";
|
const EXTENSION: &'static str = "ron";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grammatical gender
|
// Semantic gender aka body_type
|
||||||
|
//
|
||||||
|
// Should be used for localization with extreme care.
|
||||||
|
// For basically everything except *maybe* humanoids, it's simply wrong to
|
||||||
|
// assume that this may be used as grammatical gender.
|
||||||
|
//
|
||||||
|
// TODO: remove this and instead add GUI for players to choose preferred gender.
|
||||||
|
// Read a comment for `gender_str` in voxygen/i18n-helpers/src/lib.rs.
|
||||||
pub enum Gender {
|
pub enum Gender {
|
||||||
Masculine,
|
Masculine,
|
||||||
Feminine,
|
Feminine,
|
||||||
@ -1359,71 +1366,14 @@ impl Body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gender(&self) -> Gender {
|
// Read comment on `Gender` for more
|
||||||
|
pub fn humanoid_gender(&self) -> Option<Gender> {
|
||||||
match self {
|
match self {
|
||||||
Body::Humanoid(b) => match b.body_type {
|
Body::Humanoid(b) => match b.body_type {
|
||||||
humanoid::BodyType::Male => Gender::Masculine,
|
humanoid::BodyType::Male => Some(Gender::Masculine),
|
||||||
humanoid::BodyType::Female => Gender::Feminine,
|
humanoid::BodyType::Female => Some(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")
|
|
||||||
},
|
},
|
||||||
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ use std::borrow::Cow;
|
|||||||
|
|
||||||
use common::{
|
use common::{
|
||||||
comp::{
|
comp::{
|
||||||
|
body::Gender,
|
||||||
chat::{KillSource, KillType},
|
chat::{KillSource, KillType},
|
||||||
BuffKind, ChatMsg, ChatType, Content,
|
BuffKind, ChatMsg, ChatType, Content,
|
||||||
},
|
},
|
||||||
@ -38,8 +39,91 @@ pub fn localize_chat_message(
|
|||||||
// This includes every notification-like message, like death.
|
// This includes every notification-like message, like death.
|
||||||
let name_format = |uid: &Uid| name_format_or_complex(false, uid);
|
let name_format = |uid: &Uid| name_format_or_complex(false, uid);
|
||||||
|
|
||||||
// FIXME: this shouldn't pass the review!
|
// This is a hack, kind of.
|
||||||
let gender_str = |uid: &Uid| "he".to_owned();
|
//
|
||||||
|
// Current implementation just checks if our player is humanoid, and if so,
|
||||||
|
// we take the body_type of its character and assume it as grammatical gender.
|
||||||
|
//
|
||||||
|
// In short,
|
||||||
|
// body_type of character
|
||||||
|
// -> sex of character
|
||||||
|
// -> gender of player.
|
||||||
|
// -> grammatical gender for use in messages.
|
||||||
|
//
|
||||||
|
// This is obviously, wrong, but it's good enough approximation, after all,
|
||||||
|
// players do choose their characters.
|
||||||
|
//
|
||||||
|
// In the future, we will want special GUI where players can specify their
|
||||||
|
// gender (and change it!), and we do want to handle more genders than just
|
||||||
|
// male and female.
|
||||||
|
//
|
||||||
|
// Ideally, the system should handle following (if we exclude plurals):
|
||||||
|
// - Female
|
||||||
|
// - Male
|
||||||
|
// - Neuter (or fallback Female)
|
||||||
|
// - Neuter (or fallback Male)
|
||||||
|
// - Intermediate (or fallback Female)
|
||||||
|
// - Intermediate (or fallback Male)
|
||||||
|
// and maybe more, not sure.
|
||||||
|
//
|
||||||
|
// What is supported by language and what is not, as well as maybe how to
|
||||||
|
// convert genders into strings to match, should go into _manifest.ron file
|
||||||
|
//
|
||||||
|
// So let's say language only supports male and female, we will convert all
|
||||||
|
// genders to these, using some fallbacks, and pass it.
|
||||||
|
//
|
||||||
|
// If the language can represent Female, Male and Neuter, we can pass these.
|
||||||
|
//
|
||||||
|
// Exact design of such a complex system is honestly up to discussion.
|
||||||
|
let gender_str = |uid: &Uid| match info.gender.get(uid) {
|
||||||
|
Some(Gender::Feminine) => "she".to_owned(),
|
||||||
|
Some(Gender::Masculine) => "he".to_owned(),
|
||||||
|
None => "??".to_owned(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is where the most fun begings.
|
||||||
|
//
|
||||||
|
// Unlike people, "items" can have their own gender, which is completely
|
||||||
|
// independent of everything, including common sense.
|
||||||
|
//
|
||||||
|
// For example, word "masculinity" can be feminine in some languages,
|
||||||
|
// as well as word "boy", and vice versa.
|
||||||
|
//
|
||||||
|
// So we can't rely on body_type, at all. And even if we did try, our
|
||||||
|
// body_type isn't even always represents animal sex, there are some
|
||||||
|
// animals that use body_type to represent their kind, like different
|
||||||
|
// types of Fox ("male" fox is forest, "female" is arctic one).
|
||||||
|
// And what about Mindflayer? They do have varied body_type, but do they
|
||||||
|
// even have concept of gender?
|
||||||
|
//
|
||||||
|
// Our use case is probably less cryptic, after all we are limited by
|
||||||
|
// mostly sentient things, but that doesn't help at all.
|
||||||
|
//
|
||||||
|
// Common example is word "spider", which can be feminine in one languages
|
||||||
|
// and masculine in other, and sometimes even neuter.
|
||||||
|
//
|
||||||
|
// Oh, and I want to add that we are talking about grammatical genders, and
|
||||||
|
// languages define their own grammar. There are languages that have more
|
||||||
|
// than three grammatical genders, there are languages that don't have
|
||||||
|
// male/female distinction and instead realy on animacy/non-animacy.
|
||||||
|
// What has an animacy and what doesn't is for language to decide.
|
||||||
|
// There are languages as well that mix these concepts and may have neuter,
|
||||||
|
// female, masculine with animacy, masculine with animacy. Some languages
|
||||||
|
// have their own scheme of things that arbitrarily picks noun-class per
|
||||||
|
// noun.
|
||||||
|
// Don't get me wrong. *All* languages do pick the gender for the word
|
||||||
|
// arbitrary as I showed at the beginning, it's just some languages have
|
||||||
|
// not just different mapping, but different gender set as well.
|
||||||
|
//
|
||||||
|
// The *only* option we have is fetch the gender per each name entry from
|
||||||
|
// localization files.
|
||||||
|
//
|
||||||
|
// I'm not 100% sure what should be the implementation of it, but I imagine
|
||||||
|
// that Stats::name() should be changed to include a way to reference where
|
||||||
|
// to grab the gender associated with this name, so translation then can
|
||||||
|
// pick right article or use right adjective/verb connected with NPC in the
|
||||||
|
// context of the message.
|
||||||
|
let _gender_str_npc = || "idk".to_owned();
|
||||||
|
|
||||||
let message_format = |from: &Uid, content: &Content, group: Option<&String>| {
|
let message_format = |from: &Uid, content: &Content, group: Option<&String>| {
|
||||||
let alias = name_format_or_complex(true, from);
|
let alias = name_format_or_complex(true, from);
|
||||||
@ -325,6 +409,9 @@ fn get_buff_ident(buff: BuffKind) -> &'static str {
|
|||||||
|
|
||||||
// TODO: consider fetching "you" string from localization and somehow fetching
|
// TODO: consider fetching "you" string from localization and somehow fetching
|
||||||
// user's gender and putting it as argument.
|
// user's gender and putting it as argument.
|
||||||
|
//
|
||||||
|
// Altenatively, which would be a better design, pass 'is_you' to
|
||||||
|
// hud-chat-message and provide $mod_spacing attribute to use.
|
||||||
fn insert_alias(_replace_you: bool, info: PlayerInfo, _localization: &Localization) -> String {
|
fn insert_alias(_replace_you: bool, info: PlayerInfo, _localization: &Localization) -> String {
|
||||||
// Leave space for a mod badge icon.
|
// Leave space for a mod badge icon.
|
||||||
const MOD_SPACING: &str = " ";
|
const MOD_SPACING: &str = " ";
|
||||||
|
Loading…
Reference in New Issue
Block a user