mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Correct localisation of numeric values, use coordinate conversions in rtsim
This commit is contained in:
parent
0c688a9b50
commit
16e3227f78
@ -19,11 +19,11 @@ use std::{borrow::Cow, io};
|
|||||||
use assets::{source::DirEntry, AssetExt, AssetGuard, AssetHandle, ReloadWatcher, SharedString};
|
use assets::{source::DirEntry, AssetExt, AssetGuard, AssetHandle, ReloadWatcher, SharedString};
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
// Re-export because I don't like prefix
|
// Re-export because I don't like prefix
|
||||||
use common::comp::Content;
|
use common::comp::{Content, LocalizationArg};
|
||||||
use common_assets as assets;
|
use common_assets as assets;
|
||||||
|
|
||||||
// Re-export for argument creation
|
// Re-export for argument creation
|
||||||
pub use fluent::fluent_args;
|
pub use fluent::{fluent_args, FluentValue};
|
||||||
pub use fluent_bundle::FluentArgs;
|
pub use fluent_bundle::FluentArgs;
|
||||||
|
|
||||||
/// The reference language, aka the more up-to-date localization data.
|
/// The reference language, aka the more up-to-date localization data.
|
||||||
@ -332,7 +332,7 @@ impl LocalizationGuard {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Localize the given context.
|
/// Localize the given content.
|
||||||
pub fn get_content(&self, content: &Content) -> String {
|
pub fn get_content(&self, content: &Content) -> String {
|
||||||
match content {
|
match content {
|
||||||
Content::Plain(text) => text.clone(),
|
Content::Plain(text) => text.clone(),
|
||||||
@ -342,7 +342,14 @@ impl LocalizationGuard {
|
|||||||
*seed,
|
*seed,
|
||||||
&args
|
&args
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(k, content)| (k, self.get_content(content)))
|
.map(|(k, arg)| {
|
||||||
|
(k, match arg {
|
||||||
|
LocalizationArg::Content(content) => {
|
||||||
|
FluentValue::String(self.get_content(content).into())
|
||||||
|
},
|
||||||
|
LocalizationArg::Nat(n) => FluentValue::from(n),
|
||||||
|
})
|
||||||
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
)
|
)
|
||||||
.into_owned(),
|
.into_owned(),
|
||||||
|
@ -199,20 +199,56 @@ pub enum Content {
|
|||||||
/// deterministic (but pseudorandom) localised output
|
/// deterministic (but pseudorandom) localised output
|
||||||
seed: u16,
|
seed: u16,
|
||||||
/// i18n arguments
|
/// i18n arguments
|
||||||
args: HashMap<String, Content>,
|
args: HashMap<String, LocalizationArg>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove impl and make use of `Plain` explicit (to discourage it)
|
// TODO: Remove impl and make use of `Plain(...)` explicit (to discourage it)
|
||||||
impl From<String> for Content {
|
impl From<String> for Content {
|
||||||
fn from(text: String) -> Self { Self::Plain(text) }
|
fn from(text: String) -> Self { Self::Plain(text) }
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove impl and make use of `Plain` explicit (to discourage it)
|
// TODO: Remove impl and make use of `Plain(...)` explicit (to discourage it)
|
||||||
impl<'a> From<&'a str> for Content {
|
impl<'a> From<&'a str> for Content {
|
||||||
fn from(text: &'a str) -> Self { Self::Plain(text.to_string()) }
|
fn from(text: &'a str) -> Self { Self::Plain(text.to_string()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A localisation argument for localised content (see [`Content::Localized`]).
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub enum LocalizationArg {
|
||||||
|
/// The localisation argument is itself a section of content.
|
||||||
|
///
|
||||||
|
/// Note that this allows [`Content`] to recursively refer to itself. It may
|
||||||
|
/// be tempting to decide to parameterise everything, having dialogue
|
||||||
|
/// generated with a compact tree. "It's simpler!", you might say. False.
|
||||||
|
/// Over-parameterisation is an anti-pattern that hurts translators. Where
|
||||||
|
/// possible, prefer fewer levels of nesting unless doing so would
|
||||||
|
/// result in an intractably larger number of combinations. See [here](https://github.com/projectfluent/fluent/wiki/Good-Practices-for-Developers#prefer-wet-over-dry) for the
|
||||||
|
/// guidance provided by the docs for `fluent`, the localisation library
|
||||||
|
/// used by clients.
|
||||||
|
Content(Content),
|
||||||
|
/// The localisation argument is a natural number
|
||||||
|
Nat(u64),
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Remove impl and make use of `Content(Plain(...))` explicit (to
|
||||||
|
// discourage it)
|
||||||
|
impl From<String> for LocalizationArg {
|
||||||
|
fn from(text: String) -> Self { Self::Content(Content::Plain(text)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Remove impl and make use of `Content(Plain(...))` explicit (to
|
||||||
|
// discourage it)
|
||||||
|
impl<'a> From<&'a str> for LocalizationArg {
|
||||||
|
fn from(text: &'a str) -> Self { Self::Content(Content::Plain(text.to_string())) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Remove impl and make use of `Content(Plain(...))` explicit (to
|
||||||
|
// discourage it)
|
||||||
|
impl From<u64> for LocalizationArg {
|
||||||
|
fn from(n: u64) -> Self { Self::Nat(n) }
|
||||||
|
}
|
||||||
|
|
||||||
impl Content {
|
impl Content {
|
||||||
pub fn localized(key: impl ToString) -> Self {
|
pub fn localized(key: impl ToString) -> Self {
|
||||||
Self::Localized {
|
Self::Localized {
|
||||||
@ -222,7 +258,7 @@ impl Content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn localized_with_args<'a, A: Into<Content>>(
|
pub fn localized_with_args<'a, A: Into<LocalizationArg>>(
|
||||||
key: impl ToString,
|
key: impl ToString,
|
||||||
args: impl IntoIterator<Item = (&'a str, A)>,
|
args: impl IntoIterator<Item = (&'a str, A)>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@ -341,6 +377,8 @@ impl<G> GenericChatMsg<G> {
|
|||||||
|
|
||||||
pub fn content(&self) -> &Content { &self.content }
|
pub fn content(&self) -> &Content { &self.content }
|
||||||
|
|
||||||
|
pub fn into_content(self) -> Content { self.content }
|
||||||
|
|
||||||
pub fn set_content(&mut self, content: Content) { self.content = content; }
|
pub fn set_content(&mut self, content: Content) { self.content = content; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,8 +75,8 @@ pub use self::{
|
|||||||
},
|
},
|
||||||
character_state::{CharacterActivity, CharacterState, StateUpdate},
|
character_state::{CharacterActivity, CharacterState, StateUpdate},
|
||||||
chat::{
|
chat::{
|
||||||
ChatMode, ChatMsg, ChatType, Content, Faction, SpeechBubble, SpeechBubbleType,
|
ChatMode, ChatMsg, ChatType, Content, Faction, LocalizationArg, SpeechBubble,
|
||||||
UnresolvedChatMsg,
|
SpeechBubbleType, UnresolvedChatMsg,
|
||||||
},
|
},
|
||||||
combo::Combo,
|
combo::Combo,
|
||||||
controller::{
|
controller::{
|
||||||
|
@ -84,7 +84,9 @@ pub trait CoordinateConversions {
|
|||||||
|
|
||||||
impl CoordinateConversions for Vec2<i32> {
|
impl CoordinateConversions for Vec2<i32> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn wpos_to_cpos(&self) -> Self { self.map2(TerrainChunkSize::RECT_SIZE, |e, sz| e / sz as i32) }
|
fn wpos_to_cpos(&self) -> Self {
|
||||||
|
self.map2(TerrainChunkSize::RECT_SIZE, |e, sz| e.div_euclid(sz as i32))
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn cpos_to_wpos(&self) -> Self { self.map2(TerrainChunkSize::RECT_SIZE, |e, sz| e * sz as i32) }
|
fn cpos_to_wpos(&self) -> Self { self.map2(TerrainChunkSize::RECT_SIZE, |e, sz| e * sz as i32) }
|
||||||
|
@ -12,8 +12,7 @@ use common::{
|
|||||||
Actor, ChunkResource, FactionId, NpcAction, NpcActivity, Personality, SiteId, VehicleId,
|
Actor, ChunkResource, FactionId, NpcAction, NpcActivity, Personality, SiteId, VehicleId,
|
||||||
},
|
},
|
||||||
store::Id,
|
store::Id,
|
||||||
terrain::TerrainChunkSize,
|
terrain::CoordinateConversions,
|
||||||
vol::RectVolSize,
|
|
||||||
};
|
};
|
||||||
use hashbrown::{HashMap, HashSet};
|
use hashbrown::{HashMap, HashSet};
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
@ -349,12 +348,7 @@ impl Npcs {
|
|||||||
wpos: Vec3<f32>,
|
wpos: Vec3<f32>,
|
||||||
radius: f32,
|
radius: f32,
|
||||||
) -> impl Iterator<Item = Actor> + '_ {
|
) -> impl Iterator<Item = Actor> + '_ {
|
||||||
let chunk_pos = wpos
|
let chunk_pos = wpos.xy().as_().wpos_to_cpos();
|
||||||
.xy()
|
|
||||||
.as_::<i32>()
|
|
||||||
.map2(TerrainChunkSize::RECT_SIZE.as_::<i32>(), |e, sz| {
|
|
||||||
e.div_euclid(sz)
|
|
||||||
});
|
|
||||||
let r_sqr = radius * radius;
|
let r_sqr = radius * radius;
|
||||||
LOCALITY
|
LOCALITY
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -16,9 +16,8 @@ use common::{
|
|||||||
rtsim::{ChunkResource, Profession, SiteId},
|
rtsim::{ChunkResource, Profession, SiteId},
|
||||||
spiral::Spiral2d,
|
spiral::Spiral2d,
|
||||||
store::Id,
|
store::Id,
|
||||||
terrain::{SiteKindMeta, TerrainChunkSize},
|
terrain::{CoordinateConversions, SiteKindMeta, TerrainChunkSize},
|
||||||
time::DayPeriod,
|
time::DayPeriod,
|
||||||
vol::RectVolSize,
|
|
||||||
};
|
};
|
||||||
use fxhash::FxHasher64;
|
use fxhash::FxHasher64;
|
||||||
use itertools::{Either, Itertools};
|
use itertools::{Either, Itertools};
|
||||||
@ -333,7 +332,7 @@ where
|
|||||||
let wpos_site = |wpos: Vec2<f32>| {
|
let wpos_site = |wpos: Vec2<f32>| {
|
||||||
ctx.world
|
ctx.world
|
||||||
.sim()
|
.sim()
|
||||||
.get(wpos.as_::<i32>() / TerrainChunkSize::RECT_SIZE.as_())
|
.get(wpos.as_().wpos_to_cpos())
|
||||||
.and_then(|chunk| chunk.sites.first().copied())
|
.and_then(|chunk| chunk.sites.first().copied())
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -568,7 +567,7 @@ fn hunt_animals() -> impl Action {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn find_forest(ctx: &mut NpcCtx) -> Option<Vec2<f32>> {
|
fn find_forest(ctx: &mut NpcCtx) -> Option<Vec2<f32>> {
|
||||||
let chunk_pos = ctx.npc.wpos.xy().as_() / TerrainChunkSize::RECT_SIZE.as_();
|
let chunk_pos = ctx.npc.wpos.xy().as_().wpos_to_cpos();
|
||||||
Spiral2d::new()
|
Spiral2d::new()
|
||||||
.skip(ctx.rng.gen_range(1..=8))
|
.skip(ctx.rng.gen_range(1..=8))
|
||||||
.take(49)
|
.take(49)
|
||||||
@ -801,8 +800,7 @@ fn chunk_path(
|
|||||||
.filter_map(|p| Some((p, chunk_height(p)?)))
|
.filter_map(|p| Some((p, chunk_height(p)?)))
|
||||||
},
|
},
|
||||||
|(p0, h0), (p1, h1)| {
|
|(p0, h0), (p1, h1)| {
|
||||||
let diff =
|
let diff = (p0 - p1).as_().cpos_to_wpos().with_z((h0 - h1) as f32);
|
||||||
((p0 - p1).as_() * TerrainChunkSize::RECT_SIZE.as_()).with_z((h0 - h1) as f32);
|
|
||||||
|
|
||||||
diff.magnitude_squared()
|
diff.magnitude_squared()
|
||||||
},
|
},
|
||||||
@ -841,9 +839,8 @@ fn pilot() -> impl Action {
|
|||||||
})
|
})
|
||||||
.choose(&mut ctx.rng);
|
.choose(&mut ctx.rng);
|
||||||
if let Some((_id, site)) = site {
|
if let Some((_id, site)) = site {
|
||||||
let start_chunk =
|
let start_chunk = ctx.npc.wpos.xy().as_().wpos_to_cpos();
|
||||||
ctx.npc.wpos.xy().as_::<i32>() / TerrainChunkSize::RECT_SIZE.as_::<i32>();
|
let end_chunk = site.wpos.wpos_to_cpos();
|
||||||
let end_chunk = site.wpos / TerrainChunkSize::RECT_SIZE.as_::<i32>();
|
|
||||||
chunk_path(start_chunk, end_chunk, |chunk| {
|
chunk_path(start_chunk, end_chunk, |chunk| {
|
||||||
ctx.world
|
ctx.world
|
||||||
.sim()
|
.sim()
|
||||||
@ -861,7 +858,7 @@ fn pilot() -> impl Action {
|
|||||||
fn captain() -> impl Action {
|
fn captain() -> impl Action {
|
||||||
// For now just randomly travel the sea
|
// For now just randomly travel the sea
|
||||||
now(|ctx| {
|
now(|ctx| {
|
||||||
let chunk = ctx.npc.wpos.xy().as_::<i32>() / TerrainChunkSize::RECT_SIZE.as_::<i32>();
|
let chunk = ctx.npc.wpos.xy().as_().wpos_to_cpos();
|
||||||
if let Some(chunk) = NEIGHBORS
|
if let Some(chunk) = NEIGHBORS
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|neighbor| chunk + neighbor)
|
.map(|neighbor| chunk + neighbor)
|
||||||
|
@ -6,8 +6,7 @@ use crate::{
|
|||||||
use common::{
|
use common::{
|
||||||
comp::{self, Body},
|
comp::{self, Body},
|
||||||
rtsim::{Actor, NpcAction, NpcActivity, Personality},
|
rtsim::{Actor, NpcAction, NpcActivity, Personality},
|
||||||
terrain::TerrainChunkSize,
|
terrain::CoordinateConversions,
|
||||||
vol::RectVolSize,
|
|
||||||
};
|
};
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use rand_chacha::ChaChaRng;
|
use rand_chacha::ChaChaRng;
|
||||||
@ -180,11 +179,7 @@ fn on_tick(ctx: EventCtx<SimulateNpcs, OnTick>) {
|
|||||||
| common::comp::ship::Body::AirBalloon => true,
|
| common::comp::ship::Body::AirBalloon => true,
|
||||||
common::comp::ship::Body::SailBoat
|
common::comp::ship::Body::SailBoat
|
||||||
| common::comp::ship::Body::Galleon => {
|
| common::comp::ship::Body::Galleon => {
|
||||||
let chunk_pos =
|
let chunk_pos = wpos.xy().as_().wpos_to_cpos();
|
||||||
wpos.xy().as_::<i32>().map2(
|
|
||||||
TerrainChunkSize::RECT_SIZE.as_::<i32>(),
|
|
||||||
|e, sz| e.div_euclid(sz),
|
|
||||||
);
|
|
||||||
ctx.world
|
ctx.world
|
||||||
.sim()
|
.sim()
|
||||||
.get(chunk_pos)
|
.get(chunk_pos)
|
||||||
|
@ -2,7 +2,7 @@ use crate::{
|
|||||||
event::{EventCtx, OnDeath, OnSetup, OnTick},
|
event::{EventCtx, OnDeath, OnSetup, OnTick},
|
||||||
RtState, Rule, RuleError,
|
RtState, Rule, RuleError,
|
||||||
};
|
};
|
||||||
use common::{grid::Grid, rtsim::Actor, terrain::TerrainChunkSize, vol::RectVolSize};
|
use common::{grid::Grid, rtsim::Actor, terrain::CoordinateConversions};
|
||||||
|
|
||||||
pub struct SyncNpcs;
|
pub struct SyncNpcs;
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ fn on_tick(ctx: EventCtx<SyncNpcs, OnTick>) {
|
|||||||
let data = &mut *ctx.state.data_mut();
|
let data = &mut *ctx.state.data_mut();
|
||||||
// Update vehicle grid cells
|
// Update vehicle grid cells
|
||||||
for (vehicle_id, vehicle) in data.npcs.vehicles.iter_mut() {
|
for (vehicle_id, vehicle) in data.npcs.vehicles.iter_mut() {
|
||||||
let chunk_pos = vehicle.wpos.xy().as_::<i32>() / TerrainChunkSize::RECT_SIZE.as_::<i32>();
|
let chunk_pos = vehicle.wpos.xy().as_().wpos_to_cpos();
|
||||||
if vehicle.chunk_pos != Some(chunk_pos) {
|
if vehicle.chunk_pos != Some(chunk_pos) {
|
||||||
if let Some(cell) = vehicle
|
if let Some(cell) = vehicle
|
||||||
.chunk_pos
|
.chunk_pos
|
||||||
@ -66,14 +66,7 @@ fn on_tick(ctx: EventCtx<SyncNpcs, OnTick>) {
|
|||||||
npc.current_site = ctx
|
npc.current_site = ctx
|
||||||
.world
|
.world
|
||||||
.sim()
|
.sim()
|
||||||
.get(
|
.get(npc.wpos.xy().as_().wpos_to_cpos())
|
||||||
npc.wpos
|
|
||||||
.xy()
|
|
||||||
.as_::<i32>()
|
|
||||||
.map2(TerrainChunkSize::RECT_SIZE.as_::<i32>(), |e, sz| {
|
|
||||||
e.div_euclid(sz)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.and_then(|chunk| {
|
.and_then(|chunk| {
|
||||||
chunk
|
chunk
|
||||||
.sites
|
.sites
|
||||||
@ -99,13 +92,7 @@ fn on_tick(ctx: EventCtx<SyncNpcs, OnTick>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update the NPC's grid cell
|
// Update the NPC's grid cell
|
||||||
let chunk_pos = npc
|
let chunk_pos = npc.wpos.xy().as_().wpos_to_cpos();
|
||||||
.wpos
|
|
||||||
.xy()
|
|
||||||
.as_::<i32>()
|
|
||||||
.map2(TerrainChunkSize::RECT_SIZE.as_::<i32>(), |e, sz| {
|
|
||||||
e.div_euclid(sz)
|
|
||||||
});
|
|
||||||
if npc.chunk_pos != Some(chunk_pos) {
|
if npc.chunk_pos != Some(chunk_pos) {
|
||||||
if let Some(cell) = npc
|
if let Some(cell) = npc
|
||||||
.chunk_pos
|
.chunk_pos
|
||||||
|
@ -1515,6 +1515,8 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Pass a localisation key instead of `Content` to avoid allocating if
|
||||||
|
// we're not permitted to speak.
|
||||||
pub fn chat_npc_if_allowed_to_speak(
|
pub fn chat_npc_if_allowed_to_speak(
|
||||||
&self,
|
&self,
|
||||||
msg: Content,
|
msg: Content,
|
||||||
|
@ -201,7 +201,10 @@ impl RtSim {
|
|||||||
debug!("Saving rtsim data...");
|
debug!("Saving rtsim data...");
|
||||||
|
|
||||||
// Create the save thread if it doesn't already exist
|
// Create the save thread if it doesn't already exist
|
||||||
// TODO: Use the slow job pool eventually
|
// We're not using the slow job pool here for two reasons:
|
||||||
|
// 1) The thread is mostly blocked on IO, not compute
|
||||||
|
// 2) We need to synchronise saves to ensure monotonicity, which slow jobs
|
||||||
|
// aren't designed to allow
|
||||||
let (tx, _) = self.save_thread.get_or_insert_with(|| {
|
let (tx, _) = self.save_thread.get_or_insert_with(|| {
|
||||||
trace!("Starting rtsim data save thread...");
|
trace!("Starting rtsim data save thread...");
|
||||||
let (tx, rx) = unbounded();
|
let (tx, rx) = unbounded();
|
||||||
|
@ -9,9 +9,8 @@ use common::{
|
|||||||
resources::{DeltaTime, Time, TimeOfDay},
|
resources::{DeltaTime, Time, TimeOfDay},
|
||||||
rtsim::{Actor, RtSimEntity, RtSimVehicle},
|
rtsim::{Actor, RtSimEntity, RtSimVehicle},
|
||||||
slowjob::SlowJobPool,
|
slowjob::SlowJobPool,
|
||||||
terrain::{CoordinateConversions, TerrainChunkSize},
|
terrain::CoordinateConversions,
|
||||||
trade::{Good, SiteInformation},
|
trade::{Good, SiteInformation},
|
||||||
vol::RectVolSize,
|
|
||||||
LoadoutBuilder,
|
LoadoutBuilder,
|
||||||
};
|
};
|
||||||
use common_ecs::{Job, Origin, Phase, System};
|
use common_ecs::{Job, Origin, Phase, System};
|
||||||
@ -236,13 +235,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
data.npcs.character_map.clear();
|
data.npcs.character_map.clear();
|
||||||
for (presence, wpos) in (&presences, &positions).join() {
|
for (presence, wpos) in (&presences, &positions).join() {
|
||||||
if let PresenceKind::Character(character) = &presence.kind {
|
if let PresenceKind::Character(character) = &presence.kind {
|
||||||
let chunk_pos = wpos
|
let chunk_pos = wpos.0.xy().as_().wpos_to_cpos();
|
||||||
.0
|
|
||||||
.xy()
|
|
||||||
.as_::<i32>()
|
|
||||||
.map2(TerrainChunkSize::RECT_SIZE.as_::<i32>(), |e, sz| {
|
|
||||||
e.div_euclid(sz)
|
|
||||||
});
|
|
||||||
data.npcs
|
data.npcs
|
||||||
.character_map
|
.character_map
|
||||||
.entry(chunk_pos)
|
.entry(chunk_pos)
|
||||||
|
@ -874,7 +874,7 @@ impl StateExt for State {
|
|||||||
} else {
|
} else {
|
||||||
self.notify_players(ServerGeneral::server_msg(
|
self.notify_players(ServerGeneral::server_msg(
|
||||||
comp::ChatType::Kill(kill_source.clone(), *uid),
|
comp::ChatType::Kill(kill_source.clone(), *uid),
|
||||||
msg.content().clone(),
|
msg.into_content(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -384,8 +384,7 @@ impl SessionState {
|
|||||||
.new_message(ChatType::CommandError.into_msg(match time {
|
.new_message(ChatType::CommandError.into_msg(match time {
|
||||||
0 => Content::localized("hud-chat-goodbye"),
|
0 => Content::localized("hud-chat-goodbye"),
|
||||||
_ => Content::localized_with_args("hud-chat-connection_lost", [(
|
_ => Content::localized_with_args("hud-chat-connection_lost", [(
|
||||||
"time",
|
"time", time,
|
||||||
time.to_string(),
|
|
||||||
)]),
|
)]),
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
@ -988,7 +987,7 @@ impl PlayState for SessionState {
|
|||||||
self.hud.new_message(ChatType::Meta.into_msg(
|
self.hud.new_message(ChatType::Meta.into_msg(
|
||||||
Content::localized_with_args(
|
Content::localized_with_args(
|
||||||
"hud-trade-invite_sent",
|
"hud-trade-invite_sent",
|
||||||
[("playername", name.as_str())],
|
[("playername", name)],
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
client.send_invite(uid, InviteKind::Trade)
|
client.send_invite(uid, InviteKind::Trade)
|
||||||
|
Loading…
Reference in New Issue
Block a user