diff options
author | metamuffin <metamuffin@disroot.org> | 2024-09-18 15:42:19 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2024-09-18 15:42:19 +0200 |
commit | fb6ca2a4b9d78dd80dbdf37b2926d9ede4108e8b (patch) | |
tree | 76b1a77dcd3ae29595caaa6423a18b5ce29e32db /server | |
parent | e5fdbaadbf01f14290e70c49482e1dce3c9816d8 (diff) | |
download | hurrycurry-fb6ca2a4b9d78dd80dbdf37b2926d9ede4108e8b.tar hurrycurry-fb6ca2a4b9d78dd80dbdf37b2926d9ede4108e8b.tar.bz2 hurrycurry-fb6ca2a4b9d78dd80dbdf37b2926d9ede4108e8b.tar.zst |
translate server messages
Diffstat (limited to 'server')
-rw-r--r-- | server/bot/src/main.rs | 7 | ||||
-rw-r--r-- | server/protocol/src/lib.rs | 8 | ||||
-rw-r--r-- | server/replaytool/src/main.rs | 18 | ||||
-rw-r--r-- | server/src/commands.rs | 10 | ||||
-rw-r--r-- | server/src/entity/book.rs | 3 | ||||
-rw-r--r-- | server/src/entity/campaign.rs | 10 | ||||
-rw-r--r-- | server/src/entity/mod.rs | 4 | ||||
-rw-r--r-- | server/src/entity/tutorial.rs | 4 | ||||
-rw-r--r-- | server/src/lib.rs | 39 | ||||
-rw-r--r-- | server/src/main.rs | 13 | ||||
-rw-r--r-- | server/src/server.rs | 38 | ||||
-rw-r--r-- | server/src/state.rs | 24 |
12 files changed, 119 insertions, 59 deletions
diff --git a/server/bot/src/main.rs b/server/bot/src/main.rs index d4d21d35..0e6aed36 100644 --- a/server/bot/src/main.rs +++ b/server/bot/src/main.rs @@ -78,8 +78,11 @@ fn main() -> Result<()> { .map(|(_, c)| c()) .unwrap_or_else(|| panic!("unknown algo {:?}", args.algo)), }), - PacketC::Error { message } => { - warn!("server error message: {message}"); + PacketC::ServerMessage { + message, + error: true, + } => { + warn!("server error message: {message:?}"); } _ => (), } diff --git a/server/protocol/src/lib.rs b/server/protocol/src/lib.rs index b8f30ce7..fb6ad46e 100644 --- a/server/protocol/src/lib.rs +++ b/server/protocol/src/lib.rs @@ -27,7 +27,7 @@ pub use glam; pub mod movement; -pub const VERSION: (u32, u32) = (6, 0); +pub const VERSION: (u32, u32) = (7, 0); pub const BINCODE_CONFIG: Configuration<LittleEndian, Varint, Limit<4096>> = standard().with_limit(); @@ -220,7 +220,8 @@ pub enum PacketC { player: PlayerID, }, ServerMessage { - text: String, + message: Message, + error: bool, }, ServerHint { #[bincode(with_serde)] @@ -232,9 +233,6 @@ pub enum PacketC { state: bool, lobby: bool, }, - Error { - message: String, - }, Menu(Menu), MovementSync { player: PlayerID, diff --git a/server/replaytool/src/main.rs b/server/replaytool/src/main.rs index a6ad70fd..530d1a76 100644 --- a/server/replaytool/src/main.rs +++ b/server/replaytool/src/main.rs @@ -19,7 +19,7 @@ use anyhow::{anyhow, Context}; use async_compression::tokio::{bufread::ZstdDecoder, write::ZstdEncoder}; use clap::Parser; use futures_util::{SinkExt, StreamExt}; -use hurrycurry_protocol::{PacketC, PacketS}; +use hurrycurry_protocol::{Message, PacketC, PacketS}; use log::{debug, info, warn, LevelFilter}; use serde::{Deserialize, Serialize}; use std::{ @@ -32,7 +32,7 @@ use tokio::{ net::TcpListener, time::sleep, }; -use tokio_tungstenite::tungstenite::Message; +use tokio_tungstenite::tungstenite; #[derive(Parser)] enum Args { @@ -121,7 +121,7 @@ async fn main() -> anyhow::Result<()> { .await?; 'outer: while let Some(Ok(message)) = sock.next().await { match message { - Message::Text(line) => { + tungstenite::Message::Text(line) => { let packet: PacketS = match serde_json::from_str(&line) { Ok(p) => p, Err(e) => { @@ -135,7 +135,11 @@ async fn main() -> anyhow::Result<()> { PacketS::Join { .. } => { sock.send(tokio_tungstenite::tungstenite::Message::Text( serde_json::to_string(&PacketC::ServerMessage { - text: "Replays cannot be joined".to_string(), + message: Message::Translation { + id: "s.replay.cannot_join".to_owned(), + params: vec![], + }, + error: true, }) .unwrap(), )) @@ -160,7 +164,7 @@ async fn main() -> anyhow::Result<()> { x => warn!("unhandled client packet: {x:?}"), } } - Message::Close(_) => break, + tungstenite::Message::Close(_) => break, _ => (), } } @@ -182,7 +186,7 @@ pub async fn do_record(output: &Path, url: &str) -> anyhow::Result<()> { while let Some(Ok(message)) = sock.next().await { match message { - Message::Text(line) => { + tungstenite::Message::Text(line) => { let packet: PacketC = serde_json::from_str(&line).context("invalid packet")?; debug!("<- {packet:?}"); @@ -206,7 +210,7 @@ pub async fn do_record(output: &Path, url: &str) -> anyhow::Result<()> { break; } } - Message::Close(_) => break, + tungstenite::Message::Close(_) => break, _ => (), } } diff --git a/server/src/commands.rs b/server/src/commands.rs index b06d9261..8e6f32c7 100644 --- a/server/src/commands.rs +++ b/server/src/commands.rs @@ -18,6 +18,7 @@ use crate::{ entity::{bot::BotDriver, tutorial::Tutorial}, server::Server, + trm, }; use anyhow::{anyhow, bail, Result}; use clap::{Parser, ValueEnum}; @@ -131,14 +132,17 @@ impl Server { Command::End => { self.tx .send(PacketC::ServerMessage { - text: format!( - "Game was aborted by {}.", - self.game + message: trm!( + "s.state.game_aborted", + s = self + .game .players .get(&player) .ok_or(anyhow!("player missing"))? .name + .clone() ), + error: false, }) .ok(); self.load(self.index.generate("lobby").await?, None); diff --git a/server/src/entity/book.rs b/server/src/entity/book.rs index 9c1192da..11ec847b 100644 --- a/server/src/entity/book.rs +++ b/server/src/entity/book.rs @@ -16,6 +16,7 @@ */ use super::{Entity, EntityContext}; +use crate::TrError; use anyhow::Result; use hurrycurry_protocol::{glam::IVec2, Menu, PacketC, PlayerID}; @@ -28,7 +29,7 @@ impl Entity for Book { c: EntityContext<'_>, pos: Option<IVec2>, _player: PlayerID, - ) -> Result<bool> { + ) -> Result<bool, TrError> { if pos == Some(self.0) { c.packet_out.push_back(PacketC::Menu(Menu::Book)); return Ok(true); diff --git a/server/src/entity/campaign.rs b/server/src/entity/campaign.rs index 934f7542..5d669a4d 100644 --- a/server/src/entity/campaign.rs +++ b/server/src/entity/campaign.rs @@ -16,7 +16,7 @@ */ use super::{Entity, EntityContext}; -use crate::{scoreboard::ScoreboardStore, server::GameServerExt}; +use crate::{scoreboard::ScoreboardStore, server::GameServerExt, trm, TrError}; use anyhow::Result; use hurrycurry_protocol::{ glam::{IVec2, Vec2}, @@ -79,10 +79,14 @@ impl Entity for Gate { c: EntityContext<'_>, pos: Option<IVec2>, _player: PlayerID, - ) -> Result<bool> { + ) -> Result<bool, TrError> { if !self.unlocked && pos == Some(self.location) { c.packet_out.push_back(PacketC::ServerMessage { - text: format!("To unlock: \n\n{}", self.condition.show(c.scoreboard)), + message: trm!( + "s.campaign.unlock_condition", + s = self.condition.show(c.scoreboard) // TODO localize + ), + error: false, }); return Ok(true); } diff --git a/server/src/entity/mod.rs b/server/src/entity/mod.rs index f87dbb32..532031d5 100644 --- a/server/src/entity/mod.rs +++ b/server/src/entity/mod.rs @@ -25,7 +25,7 @@ pub mod item_portal; pub mod player_portal; pub mod tutorial; -use crate::{data::ItemTileRegistry, scoreboard::ScoreboardStore}; +use crate::{data::ItemTileRegistry, scoreboard::ScoreboardStore, TrError}; use anyhow::{anyhow, Result}; use book::Book; use campaign::{Gate, GateCondition, Map}; @@ -68,7 +68,7 @@ pub trait Entity { _c: EntityContext<'_>, _pos: Option<IVec2>, _player: PlayerID, - ) -> Result<bool> { + ) -> Result<bool, TrError> { Ok(false) } } diff --git a/server/src/entity/tutorial.rs b/server/src/entity/tutorial.rs index fba43fd0..9b2146d2 100644 --- a/server/src/entity/tutorial.rs +++ b/server/src/entity/tutorial.rs @@ -1,4 +1,4 @@ -use crate::trm; +use crate::{trm, TrError}; use super::{Entity, EntityContext}; use anyhow::Result; @@ -70,7 +70,7 @@ impl Entity for Tutorial { _c: EntityContext<'_>, _pos: Option<IVec2>, _player: PlayerID, - ) -> Result<bool> { + ) -> Result<bool, TrError> { Ok(false) } } diff --git a/server/src/lib.rs b/server/src/lib.rs index 3969c67c..306ebd40 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -24,7 +24,7 @@ pub mod scoreboard; pub mod server; pub mod state; -use hurrycurry_protocol::glam::Vec2; +use hurrycurry_protocol::{glam::Vec2, Message}; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct ConnectionID(pub i64); @@ -66,3 +66,40 @@ macro_rules! trm_param { hurrycurry_protocol::Message::Tile($x) }; } + +#[derive(Debug)] +pub struct TrError { + pub id: &'static str, + pub params: Vec<Message>, +} +impl From<TrError> for Message { + fn from(value: TrError) -> Self { + Self::Translation { + id: value.id.to_owned(), + params: value.params, + } + } +} + +#[macro_export] +macro_rules! tre { + ($id:literal $(, $typ:ident = $param:expr)*) => { + crate::TrError { + id: $id, + params: vec![$(crate::tre_param!($typ, $param)),*] + } + }; +} + +#[macro_export] +macro_rules! tre_param { + (s, $x:expr) => { + hurrycurry_protocol::Message::Text($x) + }; + (i, $x:expr) => { + hurrycurry_protocol::Message::Item($x) + }; + (t, $x:expr) => { + hurrycurry_protocol::Message::Tile($x) + }; +} diff --git a/server/src/main.rs b/server/src/main.rs index de680200..20d9908d 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -22,7 +22,7 @@ use hurrycurry_protocol::{PacketC, PacketS, BINCODE_CONFIG, VERSION}; use hurrycurry_server::{ data::DATA_DIR, server::{GameServerExt, Server}, - ConnectionID, + trm, ConnectionID, }; use log::{debug, info, trace, warn, LevelFilter}; use std::{ @@ -168,8 +168,8 @@ async fn run(addr: SocketAddr) -> anyhow::Result<()> { rx = rx.resubscribe(); warn!("Client was lagging; resubscribed: {e}"); PacketC::ServerMessage { - text: "Lagging behind. Some clientbound packets were dropped." - .to_string(), + message: trm!("s.state.overflow_resubscribe"), + error: true, } } }), @@ -226,9 +226,10 @@ async fn run(addr: SocketAddr) -> anyhow::Result<()> { let packet_out = match state.write().await.packet_in_outer(id, packet).await { Ok(packets) => packets, Err(e) => { - warn!("Client error: {e}"); - vec![PacketC::Error { - message: format!("{e}"), + warn!("Client error: {e:?}"); + vec![PacketC::ServerMessage { + message: e.into(), + error: true, }] } }; diff --git a/server/src/server.rs b/server/src/server.rs index 848e2bb4..c9961412 100644 --- a/server/src/server.rs +++ b/server/src/server.rs @@ -20,9 +20,9 @@ use crate::{ entity::{Entities, EntityContext}, interaction::{interact, tick_slot}, scoreboard::ScoreboardStore, - ConnectionID, + tre, ConnectionID, TrError, }; -use anyhow::{anyhow, bail, Context, Result}; +use anyhow::{Context, Result}; use hurrycurry_client_lib::{Game, Involvement, Item, Player, Tile}; use hurrycurry_protocol::{ glam::{IVec2, Vec2}, @@ -341,7 +341,11 @@ impl Server { self.entities = entities; } - pub fn packet_in(&mut self, packet: PacketS, replies: &mut Vec<PacketC>) -> Result<()> { + pub fn packet_in( + &mut self, + packet: PacketS, + replies: &mut Vec<PacketC>, + ) -> Result<(), TrError> { match packet { PacketS::Join { name, @@ -362,7 +366,7 @@ impl Server { .game .players .remove(&player) - .ok_or(anyhow!("player does not exist"))?; + .ok_or(tre!("s.error.no_player"))?; self.game.players_spatial_index.remove_entry(player); @@ -394,7 +398,7 @@ impl Server { .game .players .get_mut(&player) - .ok_or(anyhow!("player does not exist"))?; + .ok_or(tre!("s.error.no_player"))?; pd.movement.input(direction, boost); @@ -437,25 +441,25 @@ impl Server { .game .players .get_mut(&pid) - .ok_or(anyhow!("player does not exist"))?; + .ok_or(tre!("s.error.no_player"))?; let (pos, edge) = match (pos, player.interacting) { (None, None) => return Ok(()), // this is silent because of auto release (None, Some(pos)) => (pos, false), (Some(pos), None) => (pos, true), - (Some(_), Some(_)) => bail!("already interacting"), + (Some(_), Some(_)) => return Err(tre!("s.error.already_interacting")), }; let entpos = pos.as_vec2() + Vec2::splat(0.5); if edge && entpos.distance(player.movement.position) > 2. { - bail!("interacting too far from player"); + return Err(tre!("s.error.interacting_too_far")); } let tile = self .game .tiles .get_mut(&pos) - .ok_or(anyhow!("tile does not exist"))?; + .ok_or(tre!("s.error.no_tile"))?; // No going back from here on @@ -476,10 +480,10 @@ impl Server { .game .players .get_many_mut([&pid, &base_pid]) - .ok_or(anyhow!("Interacting with yourself. This is impossible."))?; + .ok_or(tre!("s.error.self_interact"))?; if this.character < 0 || other.character < 0 { - bail!("You shall not interact with customers.") + return Err(tre!("s.error.customer_interact")); } interact( @@ -501,7 +505,7 @@ impl Server { .game .players .get_mut(&pid) - .ok_or(anyhow!("The player does not exist"))?; + .ok_or(tre!("s.error.no_player"))?; interact( &self.game.data, @@ -548,11 +552,7 @@ impl Server { }) } PacketS::ReplaceHand { item, player } => { - let pdata = self - .game - .players - .get_mut(&player) - .ok_or(anyhow!("The player does not exist"))?; + let pdata = self.game.players.get_mut(&player).ok_or(tre!(""))?; pdata.item = item.map(|i| Item { kind: i, active: None, @@ -568,7 +568,7 @@ impl Server { self.game.score.points += score.points; self.score_changed = true; } - PacketS::ReplayTick { .. } => bail!("Packet not supported in this session"), + PacketS::ReplayTick { .. } => return Err(tre!("s.error.packet_not_supported")), } Ok(()) } @@ -681,7 +681,7 @@ impl Server { while let Some(p) = self.packet_loopback.pop_front() { if let Err(e) = self.packet_in(p, &mut vec![]) { - warn!("Internal packet errored: {e}"); + warn!("Internal packet errored: {e:?}"); } } diff --git a/server/src/state.rs b/server/src/state.rs index 09e7031e..9086248a 100644 --- a/server/src/state.rs +++ b/server/src/state.rs @@ -15,8 +15,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -use crate::{server::Server, ConnectionID}; -use anyhow::{bail, Result}; +use crate::{server::Server, tre, trm, ConnectionID, TrError}; +use anyhow::Result; use hurrycurry_protocol::{Message, PacketC, PacketS, PlayerID}; use log::{debug, trace}; @@ -41,10 +41,10 @@ impl Server { &mut self, conn: ConnectionID, packet: PacketS, - ) -> Result<Vec<PacketC>> { + ) -> Result<Vec<PacketC>, TrError> { if let Some(p) = get_packet_player(&packet) { if !self.connections.entry(conn).or_default().contains(&p) { - bail!("Packet sent to a player that is not owned by this connection."); + return Err(tre!("s.state.packet_sender_invalid")); } } let mut replies = Vec::new(); @@ -58,7 +58,8 @@ impl Server { Ok(packets) => return Ok(packets), Err(e) => { return Ok(vec![PacketC::ServerMessage { - text: format!("{e}"), + message: Message::Text(format!("{e}")), // TODO localize + error: true, }]); } } @@ -68,7 +69,7 @@ impl Server { } PacketS::Join { .. } => { if self.connections.entry(conn).or_default().len() > 8 { - bail!("Players-per-connection limit exceeded.") + return Err(tre!("s.state.conn_too_many_players")); } } _ => (), @@ -84,10 +85,17 @@ impl Server { if self.count_chefs() == 0 && !self.game.lobby { self.tx .send(PacketC::ServerMessage { - text: "Game was aborted due to a lack of players".to_string(), + message: trm!("s.state.abort_no_players"), + error: false, }) .ok(); - self.load(self.index.generate("lobby").await?, None); + self.load( + self.index + .generate("lobby") + .await + .map_err(|m| tre!("s.error.map_load", s = format!("{m}")))?, + None, + ); } Ok(replies) } |