diff options
Diffstat (limited to 'server/src')
-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 |
9 files changed, 100 insertions, 45 deletions
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) } |