mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'xMAC94x/chat_cleanup' into 'master'
xmac94x/chat cleanup See merge request veloren/veloren!3617
This commit is contained in:
commit
abbcc45fe6
41
Cargo.lock
generated
41
Cargo.lock
generated
@ -6675,6 +6675,7 @@ dependencies = [
|
||||
"tokio",
|
||||
"tracing",
|
||||
"vek 0.15.8",
|
||||
"veloren-client-i18n",
|
||||
"veloren-common",
|
||||
"veloren-common-base",
|
||||
"veloren-common-ecs",
|
||||
@ -6683,6 +6684,25 @@ dependencies = [
|
||||
"veloren-common-state",
|
||||
"veloren-common-systems",
|
||||
"veloren-network",
|
||||
"veloren-voxygen-i18n-helpers",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "veloren-client-i18n"
|
||||
version = "0.13.0"
|
||||
dependencies = [
|
||||
"clap 3.2.22",
|
||||
"deunicode",
|
||||
"fluent",
|
||||
"fluent-bundle",
|
||||
"fluent-syntax",
|
||||
"hashbrown 0.12.3",
|
||||
"intl-memoizer",
|
||||
"ron 0.8.0",
|
||||
"serde",
|
||||
"tracing",
|
||||
"unic-langid",
|
||||
"veloren-common-assets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -7080,6 +7100,7 @@ dependencies = [
|
||||
"treeculler",
|
||||
"vek 0.15.8",
|
||||
"veloren-client",
|
||||
"veloren-client-i18n",
|
||||
"veloren-common",
|
||||
"veloren-common-base",
|
||||
"veloren-common-ecs",
|
||||
@ -7090,7 +7111,7 @@ dependencies = [
|
||||
"veloren-server",
|
||||
"veloren-voxygen-anim",
|
||||
"veloren-voxygen-egui",
|
||||
"veloren-voxygen-i18n",
|
||||
"veloren-voxygen-i18n-helpers",
|
||||
"veloren-world",
|
||||
"wgpu",
|
||||
"wgpu-profiler",
|
||||
@ -7124,21 +7145,13 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "veloren-voxygen-i18n"
|
||||
version = "0.13.0"
|
||||
name = "veloren-voxygen-i18n-helpers"
|
||||
version = "0.10.0"
|
||||
dependencies = [
|
||||
"clap 3.2.22",
|
||||
"deunicode",
|
||||
"fluent",
|
||||
"fluent-bundle",
|
||||
"fluent-syntax",
|
||||
"hashbrown 0.12.3",
|
||||
"intl-memoizer",
|
||||
"ron 0.8.0",
|
||||
"serde",
|
||||
"tracing",
|
||||
"unic-langid",
|
||||
"veloren-common-assets",
|
||||
"veloren-client-i18n",
|
||||
"veloren-common",
|
||||
"veloren-common-net",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -12,6 +12,7 @@ members = [
|
||||
"common/systems",
|
||||
"common/frontend",
|
||||
"client",
|
||||
"client/i18n",
|
||||
"plugin/api",
|
||||
"plugin/derive",
|
||||
"plugin/rt",
|
||||
@ -20,7 +21,7 @@ members = [
|
||||
"server-cli",
|
||||
"voxygen",
|
||||
"voxygen/anim",
|
||||
"voxygen/i18n",
|
||||
"voxygen/i18n-helpers",
|
||||
"voxygen/egui",
|
||||
"world",
|
||||
"network",
|
||||
|
@ -1,4 +1,6 @@
|
||||
hud-chat-all = Alle
|
||||
hud-chat-you = Du
|
||||
hud-chat-mod = Mod
|
||||
hud-chat-chat_tab_hover_tooltip = Rechtsklick für Einstellungen
|
||||
hud-outcome-burning = An Verbrennung gestorben
|
||||
hud-outcome-curse = An Verfluchung gestorben
|
||||
|
@ -1,28 +1,39 @@
|
||||
hud-chat-all = All
|
||||
hud-chat-chat_tab_hover_tooltip = Right click for settings
|
||||
## Player events
|
||||
hud-chat-online_msg = [{ $name }] is online now
|
||||
hud-chat-offline_msg = [{ $name }] went offline
|
||||
## Buff outcomes
|
||||
hud-outcome-burning = died of: burning
|
||||
hud-outcome-curse = died of: curse
|
||||
hud-outcome-bleeding = died of: bleeding
|
||||
hud-outcome-crippled = died of: crippled
|
||||
hud-outcome-frozen = died of: frozen
|
||||
hud-chat-online_msg = [{ $name }] is online now
|
||||
hud-chat-offline_msg = [{ $name }] went offline
|
||||
hud-chat-default_death_msg = [{ $name }] died
|
||||
hud-chat-environmental_kill_msg = [{ $name }] died in { $environment }
|
||||
hud-chat-fall_kill_msg = [{ $name }] died from fall damage
|
||||
hud-chat-suicide_msg = [{ $name }] died from self-inflicted wounds
|
||||
hud-outcome-mysterious = died of: secret
|
||||
## Buff deaths
|
||||
hud-chat-died_of_pvp_buff_msg = [{ $victim }] { $died_of_buff } caused by [{ $attacker }]
|
||||
hud-chat-died_of_buff_nonexistent_msg = [{ $victim }] { $died_of_buff }
|
||||
hud-chat-died_of_npc_buff_msg = [{ $victim }] { $died_of_buff } caused by { $attacker }
|
||||
## PvP deaths
|
||||
hud-chat-pvp_melee_kill_msg = [{ $attacker }] defeated [{ $victim }]
|
||||
hud-chat-pvp_ranged_kill_msg = [{ $attacker }] shot [{ $victim }]
|
||||
hud-chat-pvp_explosion_kill_msg = [{ $attacker }] blew up [{ $victim }]
|
||||
hud-chat-pvp_energy_kill_msg = [{ $attacker }] killed [{ $victim }] with magic
|
||||
hud-chat-died_of_buff_nonexistent_msg = [{ $victim }] { $died_of_buff }
|
||||
hud-chat-died_of_npc_buff_msg = [{ $victim }] { $died_of_buff } caused by { $attacker }
|
||||
hud-chat-pvp_other_kill_msg = [{ $attacker }] killed [{ $victim }]
|
||||
## PvE deaths
|
||||
hud-chat-npc_melee_kill_msg = { $attacker } killed [{ $victim }]
|
||||
hud-chat-npc_ranged_kill_msg = { $attacker } shot [{ $victim }]
|
||||
hud-chat-npc_explosion_kill_msg = { $attacker } blew up [{ $victim }]
|
||||
hud-chat-npc_energy_kill_msg = { $attacker } killed [{ $victim }] with magic
|
||||
hud-chat-npc_other_kill_msg = { $attacker } killed [{ $victim }]
|
||||
## Other deaths
|
||||
hud-chat-environmental_kill_msg = [{ $name }] died in { $environment }
|
||||
hud-chat-fall_kill_msg = [{ $name }] died from fall damage
|
||||
hud-chat-suicide_msg = [{ $name }] died from self-inflicted wounds
|
||||
hud-chat-default_death_msg = [{ $name }] died
|
||||
## Utils
|
||||
hud-chat-all = All
|
||||
hud-chat-you = You
|
||||
hud-chat-mod = Mod
|
||||
hud-chat-chat_tab_hover_tooltip = Right click for settings
|
||||
hud-loot-pickup-msg = {$actor} picked up { $amount ->
|
||||
[one] { $item }
|
||||
*[other] {$amount}x {$item}
|
||||
|
@ -7,7 +7,7 @@ edition = "2021"
|
||||
[features]
|
||||
simd = ["vek/platform_intrinsics"]
|
||||
plugins = ["common-state/plugins"]
|
||||
bin_bot = ["common-ecs", "serde", "ron", "clap", "structopt", "rustyline", "common-frontend", "async-channel"]
|
||||
bin_bot = ["common-ecs", "serde", "ron", "clap", "structopt", "rustyline", "common-frontend", "async-channel", "voxygen-i18n-helpers", "client-i18n"]
|
||||
tracy = ["common-base/tracy"]
|
||||
tick_network = []
|
||||
|
||||
@ -37,6 +37,8 @@ authc = { git = "https://gitlab.com/veloren/auth.git", rev = "fb3dcbc4962b367253
|
||||
#bot only
|
||||
async-channel = { version = "1.6", optional = true }
|
||||
common-ecs = { package = "veloren-common-ecs", path = "../common/ecs", optional = true }
|
||||
voxygen-i18n-helpers = { package = "veloren-voxygen-i18n-helpers", path = "../voxygen/i18n-helpers", optional = true }
|
||||
client-i18n = { package = "veloren-client-i18n", path = "i18n", optional = true }
|
||||
serde = { version = "1.0", features = [ "rc", "derive" ], optional = true }
|
||||
ron = { version = "0.8", default-features = false, optional = true }
|
||||
clap = { version = "3.1.8", optional = true, features = ["color", "std"] }
|
||||
@ -47,6 +49,8 @@ termcolor = { version = "1.1", optional = true }
|
||||
common-frontend = { package = "veloren-common-frontend", path = "../common/frontend", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
voxygen-i18n-helpers = { package = "veloren-voxygen-i18n-helpers", path = "../voxygen/i18n-helpers" }
|
||||
client-i18n = { package = "veloren-client-i18n", path = "i18n" }
|
||||
|
||||
[[example]]
|
||||
name = "chat-cli"
|
||||
|
@ -1,6 +1,7 @@
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(clippy::clone_on_ref_ptr)]
|
||||
|
||||
use client_i18n::LocalizationHandle;
|
||||
use common::{clock::Clock, comp};
|
||||
use std::{
|
||||
io,
|
||||
@ -11,6 +12,7 @@ use std::{
|
||||
use tokio::runtime::Runtime;
|
||||
use tracing::{error, info};
|
||||
use veloren_client::{addr::ConnectionArgs, Client, Event};
|
||||
use voxygen_i18n_helpers::localize_chat_message;
|
||||
|
||||
const TPS: u64 = 10; // Low value is okay, just reading messages.
|
||||
|
||||
@ -28,6 +30,10 @@ fn main() {
|
||||
// Initialize logging.
|
||||
common_frontend::init_stdout(None);
|
||||
|
||||
info!("loading localisation");
|
||||
|
||||
let localisation = LocalizationHandle::load_expect("en");
|
||||
|
||||
info!("Starting chat-cli...");
|
||||
|
||||
// Set up an fps clock.
|
||||
@ -63,7 +69,7 @@ fn main() {
|
||||
|
||||
println!("Server info: {:?}", client.server_info());
|
||||
|
||||
println!("Players online: {:?}", client.players().collect::<Vec<_>>());
|
||||
let mut player_printed = false;
|
||||
|
||||
let (tx, rx) = mpsc::channel();
|
||||
thread::spawn(move || {
|
||||
@ -89,7 +95,16 @@ fn main() {
|
||||
const SHOW_NAME: bool = false;
|
||||
for event in events {
|
||||
match event {
|
||||
Event::Chat(m) => println!("{}", client.format_message(&m, SHOW_NAME)),
|
||||
Event::Chat(m) => println!(
|
||||
"{}",
|
||||
localize_chat_message(
|
||||
m,
|
||||
|msg| client.lockup_msg_context(msg),
|
||||
&localisation.read(),
|
||||
SHOW_NAME,
|
||||
)
|
||||
.message
|
||||
),
|
||||
Event::Disconnect => {}, // TODO
|
||||
Event::DisconnectionNotification(time) => {
|
||||
let message = match time {
|
||||
@ -108,5 +123,10 @@ fn main() {
|
||||
|
||||
// Wait for the next tick.
|
||||
clock.tick();
|
||||
|
||||
if !player_printed {
|
||||
println!("Players online: {:?}", client.players().collect::<Vec<_>>());
|
||||
player_printed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
[package]
|
||||
authors = ["juliancoffee <lightdarkdaughter@gmail.com>"]
|
||||
edition = "2021"
|
||||
name = "veloren-voxygen-i18n"
|
||||
description = "Crate for internalization and diagnostic of existing localizations."
|
||||
name = "veloren-client-i18n"
|
||||
description = "Optional crate for internalization and diagnostic of existing localizations for frontends to consume"
|
||||
version = "0.13.0"
|
||||
|
||||
[dependencies]
|
@ -21,7 +21,7 @@ use common::{
|
||||
character::{CharacterId, CharacterItem},
|
||||
comp::{
|
||||
self,
|
||||
chat::{KillSource, KillType},
|
||||
chat::KillSource,
|
||||
controller::CraftEvent,
|
||||
group,
|
||||
inventory::item::{modular, tool, ItemKind},
|
||||
@ -56,9 +56,9 @@ use common_net::{
|
||||
msg::{
|
||||
self,
|
||||
world_msg::{EconomyInfo, PoiInfo, SiteId, SiteInfo},
|
||||
ClientGeneral, ClientMsg, ClientRegister, ClientType, DisconnectReason, InviteAnswer,
|
||||
Notification, PingMsg, PlayerInfo, PlayerListUpdate, PresenceKind, RegisterError,
|
||||
ServerGeneral, ServerInit, ServerRegisterAnswer,
|
||||
ChatTypeContext, ClientGeneral, ClientMsg, ClientRegister, ClientType, DisconnectReason,
|
||||
InviteAnswer, Notification, PingMsg, PlayerInfo, PlayerListUpdate, PresenceKind,
|
||||
RegisterError, ServerGeneral, ServerInit, ServerRegisterAnswer,
|
||||
},
|
||||
sync::WorldSyncExt,
|
||||
};
|
||||
@ -2641,11 +2641,14 @@ impl Client {
|
||||
}
|
||||
}
|
||||
|
||||
/// Format a message for the client (voxygen chat box or chat-cli)
|
||||
pub fn format_message(&self, msg: &comp::ChatMsg, character_name: bool) -> String {
|
||||
let comp::ChatMsg {
|
||||
chat_type, message, ..
|
||||
} = &msg;
|
||||
/// Get important information from client that is necessary for message
|
||||
/// localisation
|
||||
pub fn lockup_msg_context(&self, msg: &comp::ChatMsg) -> ChatTypeContext {
|
||||
let mut result = ChatTypeContext {
|
||||
you: self.uid().expect("Client doesn't have a Uid!!!"),
|
||||
player_alias: HashMap::new(),
|
||||
entity_name: HashMap::new(),
|
||||
};
|
||||
let name_of_uid = |uid| {
|
||||
let ecs = self.state.ecs();
|
||||
(
|
||||
@ -2656,192 +2659,55 @@ impl Client {
|
||||
.find(|(_, u)| u == &uid)
|
||||
.map(|(c, _)| c.name.clone())
|
||||
};
|
||||
let alias_of_uid = |uid| {
|
||||
self.player_list.get(uid).map_or(
|
||||
name_of_uid(uid).unwrap_or_else(|| "<?>".to_string()),
|
||||
|player_info| {
|
||||
if player_info.is_moderator {
|
||||
format!(
|
||||
"MOD - {}",
|
||||
self.personalize_alias(*uid, player_info.player_alias.clone())
|
||||
)
|
||||
} else {
|
||||
self.personalize_alias(*uid, player_info.player_alias.clone())
|
||||
}
|
||||
},
|
||||
)
|
||||
};
|
||||
let message_format = |uid, message, group| {
|
||||
let alias = alias_of_uid(uid);
|
||||
let name = if character_name {
|
||||
name_of_uid(uid)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
match (group, name) {
|
||||
(Some(group), None) => format!("({}) [{}]: {}", group, alias, message),
|
||||
(None, None) => format!("[{}]: {}", alias, message),
|
||||
(Some(group), Some(name)) => {
|
||||
format!("({}) [{}] {}: {}", group, alias, name, message)
|
||||
},
|
||||
(None, Some(name)) => format!("[{}] {}: {}", alias, name, message),
|
||||
}
|
||||
};
|
||||
match chat_type {
|
||||
// For ChatType::{Online, Offline, Kill} these message strings are localized
|
||||
// in voxygen/src/hud/chat.rs before being formatted here.
|
||||
// Kill messages are generated in server/src/events/entity_manipulation.rs
|
||||
// fn handle_destroy
|
||||
comp::ChatType::Online(uid) => {
|
||||
// Default message formats if no localized message string is set by hud
|
||||
// Needed for cli clients that don't set localization info
|
||||
if message.is_empty() {
|
||||
format!("[{}] came online", alias_of_uid(uid))
|
||||
} else {
|
||||
message.replace("{name}", &alias_of_uid(uid))
|
||||
}
|
||||
let mut alias_of_uid = |uid| match self.player_list.get(uid) {
|
||||
Some(player_info) => {
|
||||
result.player_alias.insert(*uid, player_info.clone());
|
||||
},
|
||||
comp::ChatType::Offline(uid) => {
|
||||
// Default message formats if no localized message string is set by hud
|
||||
// Needed for cli clients that don't set localization info
|
||||
if message.is_empty() {
|
||||
format!("[{}] went offline", alias_of_uid(uid))
|
||||
} else {
|
||||
message.replace("{name}", &alias_of_uid(uid))
|
||||
}
|
||||
None => {
|
||||
result
|
||||
.entity_name
|
||||
.insert(*uid, name_of_uid(uid).unwrap_or_else(|| "<?>".to_string()));
|
||||
},
|
||||
comp::ChatType::CommandError => message.to_string(),
|
||||
comp::ChatType::CommandInfo => message.to_string(),
|
||||
comp::ChatType::FactionMeta(_) => message.to_string(),
|
||||
comp::ChatType::GroupMeta(_) => message.to_string(),
|
||||
};
|
||||
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::Kill(kill_source, victim) => {
|
||||
// Default message formats if no localized message string is set by hud
|
||||
// Needed for cli clients that don't set localization info
|
||||
if message.is_empty() {
|
||||
match kill_source {
|
||||
KillSource::Player(attacker_uid, KillType::Buff(buff_kind)) => format!(
|
||||
"[{}] died of {} caused by [{}]",
|
||||
alias_of_uid(victim),
|
||||
format!("{:?}", buff_kind).to_lowercase().as_str(),
|
||||
alias_of_uid(attacker_uid)
|
||||
),
|
||||
KillSource::Player(attacker_uid, KillType::Melee) => format!(
|
||||
"[{}] killed [{}]",
|
||||
alias_of_uid(attacker_uid),
|
||||
alias_of_uid(victim)
|
||||
),
|
||||
KillSource::Player(attacker_uid, KillType::Projectile) => format!(
|
||||
"[{}] shot [{}]",
|
||||
alias_of_uid(attacker_uid),
|
||||
alias_of_uid(victim)
|
||||
),
|
||||
KillSource::Player(attacker_uid, KillType::Explosion) => format!(
|
||||
"[{}] blew up [{}]",
|
||||
alias_of_uid(attacker_uid),
|
||||
alias_of_uid(victim)
|
||||
),
|
||||
KillSource::Player(attacker_uid, KillType::Energy) => format!(
|
||||
"[{}] used magic to kill [{}]",
|
||||
alias_of_uid(attacker_uid),
|
||||
alias_of_uid(victim)
|
||||
),
|
||||
KillSource::Player(attacker_uid, KillType::Other) => format!(
|
||||
"[{}] killed [{}]",
|
||||
alias_of_uid(attacker_uid),
|
||||
alias_of_uid(victim)
|
||||
),
|
||||
KillSource::NonExistent(KillType::Buff(buff_kind)) => format!(
|
||||
"[{}] died of {}",
|
||||
alias_of_uid(victim),
|
||||
format!("{:?}", buff_kind).to_lowercase().as_str()
|
||||
),
|
||||
KillSource::NonPlayer(attacker_name, KillType::Buff(buff_kind)) => format!(
|
||||
"[{}] died of {} caused by {}",
|
||||
alias_of_uid(victim),
|
||||
format!("{:?}", buff_kind).to_lowercase().as_str(),
|
||||
attacker_name
|
||||
),
|
||||
KillSource::NonPlayer(attacker_name, KillType::Melee) => {
|
||||
format!("{} killed [{}]", attacker_name, alias_of_uid(victim))
|
||||
},
|
||||
KillSource::NonPlayer(attacker_name, KillType::Projectile) => {
|
||||
format!("{} shot [{}]", attacker_name, alias_of_uid(victim))
|
||||
},
|
||||
KillSource::NonPlayer(attacker_name, KillType::Explosion) => {
|
||||
format!("{} blew up [{}]", attacker_name, alias_of_uid(victim))
|
||||
},
|
||||
KillSource::NonPlayer(attacker_name, KillType::Energy) => format!(
|
||||
"{} used magic to kill [{}]",
|
||||
attacker_name,
|
||||
alias_of_uid(victim)
|
||||
),
|
||||
KillSource::NonPlayer(attacker_name, KillType::Other) => {
|
||||
format!("{} killed [{}]", attacker_name, alias_of_uid(victim))
|
||||
},
|
||||
KillSource::Environment(environment) => {
|
||||
format!("[{}] died in {}", alias_of_uid(victim), environment)
|
||||
},
|
||||
KillSource::FallDamage => {
|
||||
format!("[{}] died from fall damage", alias_of_uid(victim))
|
||||
},
|
||||
KillSource::Suicide => {
|
||||
format!("[{}] died from self-inflicted wounds", alias_of_uid(victim))
|
||||
},
|
||||
KillSource::NonExistent(_) => format!("[{}] died", alias_of_uid(victim)),
|
||||
KillSource::Other => format!("[{}] died", alias_of_uid(victim)),
|
||||
}
|
||||
} else {
|
||||
match kill_source {
|
||||
KillSource::Player(attacker_uid, _) => message
|
||||
.replace("{attacker}", &alias_of_uid(attacker_uid))
|
||||
.replace("{victim}", &alias_of_uid(victim)),
|
||||
KillSource::NonExistent(KillType::Buff(_)) => {
|
||||
message.replace("{victim}", &alias_of_uid(victim))
|
||||
},
|
||||
KillSource::NonPlayer(attacker_name, _) => message
|
||||
.replace("{attacker}", attacker_name)
|
||||
.replace("{victim}", &alias_of_uid(victim)),
|
||||
KillSource::Environment(environment) => message
|
||||
.replace("{name}", &alias_of_uid(victim))
|
||||
.replace("{environment}", environment),
|
||||
KillSource::FallDamage => message.replace("{name}", &alias_of_uid(victim)),
|
||||
KillSource::Suicide => message.replace("{name}", &alias_of_uid(victim)),
|
||||
KillSource::NonExistent(_) => {
|
||||
message.replace("{name}", &alias_of_uid(victim))
|
||||
},
|
||||
KillSource::Other => message.replace("{name}", &alias_of_uid(victim)),
|
||||
}
|
||||
}
|
||||
alias_of_uid(victim);
|
||||
match kill_source {
|
||||
KillSource::Player(attacker_uid, _) => {
|
||||
alias_of_uid(attacker_uid);
|
||||
},
|
||||
KillSource::NonPlayer(_, _) => (),
|
||||
KillSource::Environment(_) => (),
|
||||
KillSource::FallDamage => (),
|
||||
KillSource::Suicide => (),
|
||||
KillSource::NonExistent(_) => (),
|
||||
KillSource::Other => (),
|
||||
};
|
||||
},
|
||||
comp::ChatType::Tell(from, to) => {
|
||||
let from_alias = alias_of_uid(from);
|
||||
let to_alias = alias_of_uid(to);
|
||||
if Some(*from) == self.uid() {
|
||||
format!("To [{}]: {}", to_alias, message)
|
||||
} else {
|
||||
format!("From [{}]: {}", from_alias, message)
|
||||
}
|
||||
comp::ChatType::Tell(from, to) | comp::ChatType::NpcTell(from, to, _) => {
|
||||
alias_of_uid(from);
|
||||
alias_of_uid(to);
|
||||
},
|
||||
comp::ChatType::Say(uid) => message_format(uid, message, None),
|
||||
comp::ChatType::Group(uid, s) => message_format(uid, message, Some(s)),
|
||||
comp::ChatType::Faction(uid, s) => message_format(uid, message, Some(s)),
|
||||
comp::ChatType::Region(uid) => message_format(uid, message, None),
|
||||
comp::ChatType::World(uid) => message_format(uid, message, None),
|
||||
// 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
|
||||
comp::ChatType::Npc(_uid, _r) => "".to_string(),
|
||||
comp::ChatType::NpcSay(uid, _r) => message_format(uid, message, None),
|
||||
comp::ChatType::NpcTell(from, to, _r) => {
|
||||
let from_alias = alias_of_uid(from);
|
||||
let to_alias = alias_of_uid(to);
|
||||
if Some(*from) == self.uid() {
|
||||
format!("To [{}]: {}", to_alias, message)
|
||||
} else {
|
||||
format!("From [{}]: {}", from_alias, message)
|
||||
}
|
||||
comp::ChatType::Say(uid)
|
||||
| comp::ChatType::Region(uid)
|
||||
| comp::ChatType::World(uid)
|
||||
| comp::ChatType::NpcSay(uid, _) => {
|
||||
alias_of_uid(uid);
|
||||
},
|
||||
comp::ChatType::Meta => message.to_string(),
|
||||
}
|
||||
comp::ChatType::Group(uid, _) | comp::ChatType::Faction(uid, _) => {
|
||||
alias_of_uid(uid);
|
||||
},
|
||||
comp::ChatType::Npc(uid, _) => alias_of_uid(uid),
|
||||
comp::ChatType::Meta => (),
|
||||
};
|
||||
result
|
||||
}
|
||||
|
||||
/// Execute a single client tick:
|
||||
@ -2944,6 +2810,7 @@ impl Drop for Client {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use client_i18n::LocalizationHandle;
|
||||
|
||||
#[test]
|
||||
/// THIS TEST VERIFIES THE CONSTANT API.
|
||||
@ -2953,6 +2820,7 @@ mod tests {
|
||||
/// CONTACT @Core Developer BEFORE MERGING CHANGES TO THIS TEST
|
||||
fn constant_api_test() {
|
||||
use common::clock::Clock;
|
||||
use voxygen_i18n_helpers::localize_chat_message;
|
||||
|
||||
const SPT: f64 = 1.0 / 60.0;
|
||||
|
||||
@ -2972,6 +2840,7 @@ mod tests {
|
||||
password,
|
||||
|suggestion: &str| suggestion == auth_server,
|
||||
));
|
||||
let localisation = LocalizationHandle::load_expect("en");
|
||||
|
||||
let _ = veloren_client.map(|mut client| {
|
||||
//clock
|
||||
@ -2990,7 +2859,13 @@ mod tests {
|
||||
match event {
|
||||
Event::Chat(msg) => {
|
||||
let msg: comp::ChatMsg = msg;
|
||||
let _s: String = client.format_message(&msg, true);
|
||||
let _s: String = localize_chat_message(
|
||||
msg,
|
||||
|msg| client.lockup_msg_context(msg),
|
||||
&localisation.read(),
|
||||
true,
|
||||
)
|
||||
.message;
|
||||
},
|
||||
Event::Disconnect => {},
|
||||
Event::DisconnectionNotification(_) => {
|
||||
|
@ -13,9 +13,9 @@ pub use self::{
|
||||
},
|
||||
ecs_packet::EcsCompPacket,
|
||||
server::{
|
||||
CharacterInfo, DisconnectReason, InviteAnswer, Notification, PlayerInfo, PlayerListUpdate,
|
||||
RegisterError, SerializedTerrainChunk, ServerGeneral, ServerInfo, ServerInit, ServerMsg,
|
||||
ServerRegisterAnswer,
|
||||
CharacterInfo, ChatTypeContext, DisconnectReason, InviteAnswer, Notification, PlayerInfo,
|
||||
PlayerListUpdate, RegisterError, SerializedTerrainChunk, ServerGeneral, ServerInfo,
|
||||
ServerInit, ServerMsg, ServerRegisterAnswer,
|
||||
},
|
||||
world_msg::WorldMapMsg,
|
||||
};
|
||||
|
@ -245,6 +245,13 @@ pub struct PlayerInfo {
|
||||
pub uuid: Uuid,
|
||||
}
|
||||
|
||||
/// used for localisation, filled by client and used by i18n code
|
||||
pub struct ChatTypeContext {
|
||||
pub you: Uid,
|
||||
pub player_alias: HashMap<Uid, PlayerInfo>,
|
||||
pub entity_name: HashMap<Uid, String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct CharacterInfo {
|
||||
pub name: String,
|
||||
|
@ -49,7 +49,8 @@ common-systems = {package = "veloren-common-systems", path = "../common/systems"
|
||||
common-state = {package = "veloren-common-state", path = "../common/state"}
|
||||
|
||||
anim = {package = "veloren-voxygen-anim", path = "anim"}
|
||||
i18n = {package = "veloren-voxygen-i18n", path = "i18n"}
|
||||
i18n = {package = "veloren-client-i18n", path = "../client/i18n"}
|
||||
i18n-helpers = {package = "veloren-voxygen-i18n-helpers", path = "i18n-helpers"}
|
||||
voxygen-egui = {package = "veloren-voxygen-egui", path = "egui", optional = true }
|
||||
|
||||
# Graphics
|
||||
|
13
voxygen/i18n-helpers/Cargo.toml
Normal file
13
voxygen/i18n-helpers/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
||||
[package]
|
||||
authors = ["juliancoffee <lightdarkdaughter@gmail.com>"]
|
||||
edition = "2021"
|
||||
name = "veloren-voxygen-i18n-helpers"
|
||||
description = "Crate for internalization and diagnostic of existing localizations."
|
||||
version = "0.10.0"
|
||||
|
||||
[dependencies]
|
||||
common-net = {package = "veloren-common-net", path = "../../common/net"}
|
||||
common = {package = "veloren-common", path = "../../common"}
|
||||
i18n = {package = "veloren-client-i18n", path = "../../client/i18n"}
|
||||
# Utility
|
||||
tracing = "0.1"
|
222
voxygen/i18n-helpers/src/lib.rs
Normal file
222
voxygen/i18n-helpers/src/lib.rs
Normal file
@ -0,0 +1,222 @@
|
||||
#![feature(let_chains)]
|
||||
use common::comp::{
|
||||
chat::{KillSource, KillType},
|
||||
BuffKind, ChatMsg, ChatType,
|
||||
};
|
||||
use common_net::msg::{ChatTypeContext, PlayerInfo};
|
||||
use i18n::Localization;
|
||||
|
||||
pub fn localize_chat_message(
|
||||
mut msg: ChatMsg,
|
||||
lookup_fn: impl Fn(&ChatMsg) -> ChatTypeContext,
|
||||
localisation: &Localization,
|
||||
show_char_name: bool,
|
||||
) -> ChatMsg {
|
||||
let info = lookup_fn(&msg);
|
||||
|
||||
let name_format = |uid: &common::uid::Uid| match info.player_alias.get(uid).cloned() {
|
||||
Some(pi) => insert_alias(info.you == *uid, pi, localisation),
|
||||
None => info
|
||||
.entity_name
|
||||
.get(uid)
|
||||
.cloned()
|
||||
.expect("client didn't proved enough info"),
|
||||
};
|
||||
|
||||
let message_format = |from: &common::uid::Uid, message: &str, group: Option<&String>| {
|
||||
let alias = name_format(from);
|
||||
let name = if let Some(pi) = info.player_alias.get(from).cloned() && show_char_name {
|
||||
pi.character.map(|c| c.name)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
match (group, name) {
|
||||
(Some(group), None) => format!("({group}) [{alias}]: {message}"),
|
||||
(None, None) => format!("[{alias}]: {message}"),
|
||||
(Some(group), Some(name)) => format!("({group}) [{alias}] {name}: {message}"),
|
||||
(None, Some(name)) => format!("[{alias}] {name}: {message}"),
|
||||
}
|
||||
};
|
||||
|
||||
let new_msg = match &msg.chat_type {
|
||||
ChatType::Online(uid) => localisation
|
||||
.get_msg_ctx("hud-chat-online_msg", &i18n::fluent_args! {
|
||||
"name" => name_format(uid),
|
||||
})
|
||||
.into_owned(),
|
||||
ChatType::Offline(uid) => localisation
|
||||
.get_msg_ctx("hud-chat-offline_msg", &i18n::fluent_args! {
|
||||
"name" => name_format(uid
|
||||
),
|
||||
})
|
||||
.into_owned(),
|
||||
ChatType::CommandError => msg.message.to_string(),
|
||||
ChatType::CommandInfo => msg.message.to_string(),
|
||||
ChatType::FactionMeta(_) => msg.message.to_string(),
|
||||
ChatType::GroupMeta(_) => msg.message.to_string(),
|
||||
ChatType::Tell(from, to) => {
|
||||
let from_alias = name_format(from);
|
||||
let to_alias = name_format(to);
|
||||
// TODO: internationalise
|
||||
if *from == info.you {
|
||||
format!("To [{to_alias}]: {}", msg.message)
|
||||
} else {
|
||||
format!("From [{from_alias}]: {}", msg.message)
|
||||
}
|
||||
},
|
||||
ChatType::Say(uid) => message_format(uid, &msg.message, None),
|
||||
ChatType::Group(uid, s) => message_format(uid, &msg.message, Some(s)),
|
||||
ChatType::Faction(uid, s) => message_format(uid, &msg.message, Some(s)),
|
||||
ChatType::Region(uid) => message_format(uid, &msg.message, None),
|
||||
ChatType::World(uid) => message_format(uid, &msg.message, None),
|
||||
// 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
|
||||
ChatType::Npc(uid, _r) => message_format(uid, &msg.message, None),
|
||||
ChatType::NpcSay(uid, _r) => message_format(uid, &msg.message, None),
|
||||
ChatType::NpcTell(from, to, _r) => {
|
||||
let from_alias = name_format(from);
|
||||
let to_alias = name_format(to);
|
||||
// TODO: internationalise
|
||||
if *from == info.you {
|
||||
format!("To [{to_alias}]: {}", msg.message)
|
||||
} else {
|
||||
format!("From [{from_alias}]: {}", msg.message)
|
||||
}
|
||||
},
|
||||
ChatType::Meta => msg.message.to_string(),
|
||||
ChatType::Kill(kill_source, victim) => {
|
||||
let i18n_buff = |buff| match buff {
|
||||
BuffKind::Burning => "hud-outcome-burning",
|
||||
BuffKind::Bleeding => "hud-outcome-bleeding",
|
||||
BuffKind::Cursed => "hud-outcome-curse",
|
||||
BuffKind::Crippled => "hud-outcome-crippled",
|
||||
BuffKind::Frozen => "hud-outcome-frozen",
|
||||
BuffKind::Regeneration
|
||||
| BuffKind::Saturation
|
||||
| BuffKind::Potion
|
||||
| BuffKind::CampfireHeal
|
||||
| BuffKind::EnergyRegen
|
||||
| BuffKind::IncreaseMaxEnergy
|
||||
| BuffKind::IncreaseMaxHealth
|
||||
| BuffKind::Invulnerability
|
||||
| BuffKind::ProtectingWard
|
||||
| BuffKind::Frenzied
|
||||
| BuffKind::Hastened => {
|
||||
tracing::error!("Player was killed by a positive buff!");
|
||||
"hud-outcome-mysterious"
|
||||
},
|
||||
BuffKind::Wet | BuffKind::Ensnared | BuffKind::Poisoned => {
|
||||
tracing::error!("Player was killed by a debuff that doesn't do damage!");
|
||||
"hud-outcome-mysterious"
|
||||
},
|
||||
};
|
||||
|
||||
match kill_source {
|
||||
// Buff deaths
|
||||
KillSource::Player(attacker, KillType::Buff(buff_kind)) => {
|
||||
let i18n_buff = i18n_buff(*buff_kind);
|
||||
let buff = localisation.get_msg(i18n_buff);
|
||||
|
||||
localisation.get_msg_ctx("hud-chat-died_of_pvp_buff_msg", &i18n::fluent_args! {
|
||||
"victim" => name_format(victim),
|
||||
"died_of_buff" => buff,
|
||||
"attacker" => name_format(attacker),
|
||||
})
|
||||
},
|
||||
KillSource::NonPlayer(attacker_name, KillType::Buff(buff_kind)) => {
|
||||
let i18n_buff = i18n_buff(*buff_kind);
|
||||
let buff = localisation.get_msg(i18n_buff);
|
||||
|
||||
localisation.get_msg_ctx("hud-chat-died_of_npc_buff_msg", &i18n::fluent_args! {
|
||||
"victim" => name_format(victim),
|
||||
"died_of_buff" => buff,
|
||||
"attacker" => attacker_name,
|
||||
})
|
||||
},
|
||||
KillSource::NonExistent(KillType::Buff(buff_kind)) => {
|
||||
let i18n_buff = i18n_buff(*buff_kind);
|
||||
let buff = localisation.get_msg(i18n_buff);
|
||||
|
||||
localisation.get_msg_ctx(
|
||||
"hud-chat-died_of_buff_nonexistent_msg",
|
||||
&i18n::fluent_args! {
|
||||
"victim" => name_format(victim),
|
||||
"died_of_buff" => buff,
|
||||
},
|
||||
)
|
||||
},
|
||||
// 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"),
|
||||
};
|
||||
localisation.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"),
|
||||
};
|
||||
localisation.get_msg_ctx(key, &i18n::fluent_args! {
|
||||
"victim" => name_format(victim),
|
||||
"attacker" => attacker_name,
|
||||
})
|
||||
},
|
||||
// Other deaths
|
||||
KillSource::Environment(environment) => {
|
||||
localisation.get_msg_ctx("hud-chat-environment_kill_msg", &i18n::fluent_args! {
|
||||
"name" => name_format(victim),
|
||||
"environment" => environment,
|
||||
})
|
||||
},
|
||||
KillSource::FallDamage => {
|
||||
localisation.get_msg_ctx("hud-chat-fall_kill_msg", &i18n::fluent_args! {
|
||||
"name" => name_format(victim),
|
||||
})
|
||||
},
|
||||
KillSource::Suicide => {
|
||||
localisation.get_msg_ctx("hud-chat-suicide_msg", &i18n::fluent_args! {
|
||||
"name" => name_format(victim),
|
||||
})
|
||||
},
|
||||
KillSource::NonExistent(_) | KillSource::Other => {
|
||||
localisation.get_msg_ctx("hud-chat-default_death_msg", &i18n::fluent_args! {
|
||||
"name" => name_format(victim),
|
||||
})
|
||||
},
|
||||
}
|
||||
.to_string()
|
||||
},
|
||||
};
|
||||
|
||||
msg.message = new_msg;
|
||||
msg
|
||||
}
|
||||
|
||||
fn insert_alias(you: bool, info: PlayerInfo, localisation: &Localization) -> String {
|
||||
const YOU: &str = "hud-chat-you";
|
||||
const MOD: &str = "hud-chat-mod";
|
||||
match (info.is_moderator, you) {
|
||||
(false, false) => info.player_alias,
|
||||
(false, true) => localisation.get_msg(YOU).to_string(),
|
||||
(true, false) => format!("{} - {}", &localisation.get_msg(MOD), info.player_alias),
|
||||
(true, true) => format!(
|
||||
"{} - {}",
|
||||
&localisation.get_msg(MOD),
|
||||
&localisation.get_msg(YOU)
|
||||
),
|
||||
}
|
||||
}
|
@ -4,11 +4,7 @@ use super::{
|
||||
};
|
||||
use crate::{cmd::complete, settings::chat::MAX_CHAT_TABS, ui::fonts::Fonts, GlobalState};
|
||||
use client::Client;
|
||||
use common::comp::{
|
||||
chat::{KillSource, KillType},
|
||||
group::Role,
|
||||
BuffKind, ChatMode, ChatMsg, ChatType,
|
||||
};
|
||||
use common::comp::{group::Role, ChatMode, ChatMsg, ChatType};
|
||||
use conrod_core::{
|
||||
color,
|
||||
input::Key,
|
||||
@ -22,6 +18,7 @@ use conrod_core::{
|
||||
WidgetCommon,
|
||||
};
|
||||
use i18n::Localization;
|
||||
use i18n_helpers::localize_chat_message;
|
||||
use std::collections::{HashSet, VecDeque};
|
||||
|
||||
widget_ids! {
|
||||
@ -422,39 +419,12 @@ impl<'a> Widget for Chat<'a> {
|
||||
.messages
|
||||
.iter()
|
||||
.map(|m| {
|
||||
let mut message = m.clone();
|
||||
if let Some(template_key) = get_chat_template_key(&message.chat_type) {
|
||||
// FIXME (i18n death messages):
|
||||
// Death message is half localized in voxygen, half in client.
|
||||
// Make this not.
|
||||
message.message = self
|
||||
.localized_strings
|
||||
.get_msg_ctx(template_key, &i18n::fluent_args! {
|
||||
"attacker" => "{attacker}",
|
||||
"name" => "{name}",
|
||||
"died_of_buff" => "{died_of_buff}",
|
||||
"victim" => "{victim}",
|
||||
"environment" => "{environment}",
|
||||
})
|
||||
.into_owned();
|
||||
|
||||
if let ChatType::Kill(kill_source, _) = &message.chat_type {
|
||||
match kill_source {
|
||||
KillSource::Player(_, KillType::Buff(buffkind))
|
||||
| KillSource::NonExistent(KillType::Buff(buffkind))
|
||||
| KillSource::NonPlayer(_, KillType::Buff(buffkind)) => {
|
||||
message.message = insert_killing_buff(
|
||||
*buffkind,
|
||||
self.localized_strings,
|
||||
&message.message,
|
||||
);
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
message.message = self.client.format_message(&message, show_char_name);
|
||||
message
|
||||
localize_chat_message(
|
||||
m.clone(),
|
||||
|msg| self.client.lockup_msg_context(msg),
|
||||
self.localized_strings,
|
||||
show_char_name,
|
||||
)
|
||||
})
|
||||
.filter(|m| {
|
||||
if let Some(chat_tab) = current_chat_tab {
|
||||
@ -777,63 +747,6 @@ fn render_chat_line(chat_type: &ChatType<String>, imgs: &Imgs) -> (Color, conrod
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_killing_buff(buff: BuffKind, localized_strings: &Localization, template: &str) -> String {
|
||||
let buff_outcome = match buff {
|
||||
BuffKind::Burning => "hud-outcome-burning",
|
||||
BuffKind::Bleeding => "hud-outcome-bleeding",
|
||||
BuffKind::Cursed => "hud-outcome-curse",
|
||||
BuffKind::Crippled => "hud-outcome-crippled",
|
||||
BuffKind::Frozen => "hud-outcome-frozen",
|
||||
BuffKind::Regeneration
|
||||
| BuffKind::Saturation
|
||||
| BuffKind::Potion
|
||||
| BuffKind::CampfireHeal
|
||||
| BuffKind::EnergyRegen
|
||||
| BuffKind::IncreaseMaxEnergy
|
||||
| BuffKind::IncreaseMaxHealth
|
||||
| BuffKind::Invulnerability
|
||||
| BuffKind::ProtectingWard
|
||||
| BuffKind::Frenzied
|
||||
| BuffKind::Hastened => {
|
||||
tracing::error!("Player was killed by a positive buff!");
|
||||
"hud-outcome-mysterious"
|
||||
},
|
||||
BuffKind::Wet | BuffKind::Ensnared | BuffKind::Poisoned => {
|
||||
tracing::error!("Player was killed by a debuff that doesn't do damage!");
|
||||
"hud-outcome-mysterious"
|
||||
},
|
||||
};
|
||||
|
||||
template.replace("{died_of_buff}", &localized_strings.get_msg(buff_outcome))
|
||||
}
|
||||
|
||||
fn get_chat_template_key(chat_type: &ChatType<String>) -> Option<&str> {
|
||||
Some(match chat_type {
|
||||
ChatType::Online(_) => "hud-chat-online_msg",
|
||||
ChatType::Offline(_) => "hud-chat-offline_msg",
|
||||
ChatType::Kill(kill_source, _) => match kill_source {
|
||||
KillSource::Player(_, KillType::Buff(_)) => "hud-chat-died_of_pvp_buff_msg",
|
||||
KillSource::Player(_, KillType::Melee) => "hud-chat-pvp_melee_kill_msg",
|
||||
KillSource::Player(_, KillType::Projectile) => "hud-chat-pvp_ranged_kill_msg",
|
||||
KillSource::Player(_, KillType::Explosion) => "hud-chat-pvp_explosion_kill_msg",
|
||||
KillSource::Player(_, KillType::Energy) => "hud-chat-pvp_energy_kill_msg",
|
||||
KillSource::Player(_, KillType::Other) => "hud-chat-pvp_other_kill_msg",
|
||||
KillSource::NonExistent(KillType::Buff(_)) => "hud-chat-died_of_buff_nonexistent_msg",
|
||||
KillSource::NonPlayer(_, KillType::Buff(_)) => "hud-chat-died_of_npc_buff_msg",
|
||||
KillSource::NonPlayer(_, KillType::Melee) => "hud-chat-npc_melee_kill_msg",
|
||||
KillSource::NonPlayer(_, KillType::Projectile) => "hud-chat-npc_ranged_kill_msg",
|
||||
KillSource::NonPlayer(_, KillType::Explosion) => "hud-chat-npc_explosion_kill_msg",
|
||||
KillSource::NonPlayer(_, KillType::Energy) => "hud-chat-npc_energy_kill_msg",
|
||||
KillSource::NonPlayer(_, KillType::Other) => "hud-chat-npc_other_kill_msg",
|
||||
KillSource::Environment(_) => "hud-chat-environmental_kill_msg",
|
||||
KillSource::FallDamage => "hud-chat-fall_kill_msg",
|
||||
KillSource::Suicide => "hud-chat-suicide_msg",
|
||||
KillSource::NonExistent(_) | KillSource::Other => "hud-chat-default_death_msg",
|
||||
},
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_cmd(msg: &str) -> Result<(String, Vec<String>), String> {
|
||||
use chumsky::prelude::*;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user