diff --git a/crates/game-service/src/battle_session.rs b/crates/game-service/src/battle_session.rs index 23426b9..788144b 100644 --- a/crates/game-service/src/battle_session.rs +++ b/crates/game-service/src/battle_session.rs @@ -114,7 +114,7 @@ impl BattleSession { } }) } - fn snapshot_message(&mut self) -> Option { + pub fn snapshot_message(&mut self) -> Option { let snapshot = self.mode.snapshot().ok()?; let report = verify_snapshot(&snapshot); let unit = self @@ -344,6 +344,11 @@ impl BattleRegistry { session.push_outbound(message); } } + pub async fn resend(&self, account: AccountRef) -> Option { + let handle = self.session(account).await?; + let mut session = handle.lock().await; + session.snapshot_message() + } pub async fn send(&self, account: AccountRef, message: WireMessage) { if let Some(handle) = self.session(account).await { handle.lock().await.push_outbound(message); diff --git a/crates/game-service/src/service.rs b/crates/game-service/src/service.rs index 69d4f7a..4f98fd0 100644 --- a/crates/game-service/src/service.rs +++ b/crates/game-service/src/service.rs @@ -481,6 +481,9 @@ impl GameApi for GameService { self.running_battles.answer_emote(account).await; Ok(()) } + async fn request_sector_state(&self, account: AccountRef) -> RpcResult> { + Ok(self.running_battles.resend(account).await.into_iter().collect()) + } async fn sector_command(&self, account: AccountRef, payload: Vec) -> RpcResult<()> { let Ok(sector) = SectorCommandMessage::from_bytes(&payload) else { return Ok(()); @@ -567,6 +570,9 @@ impl RpcService for GameService { GameRequest::BattleTick { account } => Ok(GameResponse::messages( self.battle_tick(account).await?, )), + GameRequest::RequestSectorState { account } => Ok(GameResponse::messages( + self.request_sector_state(account).await?, + )), GameRequest::SectorCommand { account, payload } => { self.sector_command(account, payload).await?; Ok(GameResponse::Empty) diff --git a/crates/gateway/src/backend.rs b/crates/gateway/src/backend.rs index 089cdc7..21df291 100644 --- a/crates/gateway/src/backend.rs +++ b/crates/gateway/src/backend.rs @@ -147,6 +147,13 @@ impl GameApi for RemoteGame { .await?; Ok(()) } + async fn request_sector_state(&self, account: AccountRef) -> RpcResult> { + Ok(self + .client + .call(&GameRequest::RequestSectorState { account }) + .await? + .into_messages()) + } async fn disconnect(&self, account: AccountRef) -> RpcResult<()> { self.client .call(&GameRequest::Disconnect { account }) diff --git a/crates/gateway/src/message_manager.rs b/crates/gateway/src/message_manager.rs index ebac6d0..2ff2eb4 100644 --- a/crates/gateway/src/message_manager.rs +++ b/crates/gateway/src/message_manager.rs @@ -99,6 +99,19 @@ impl MessageManager { self.stop_battle_ticker(); self.push_home(HomeRequestKind::GoHome).await } + message_type::REQUEST_SECTOR_STATE => { + let Some(account) = self.account else { + return Ok(()); + }; + tracing::info!(peer = %self.peer, "client asked for the sector state"); + match self.backends.game.request_sector_state(account).await { + Ok(replies) => self.push_wire_messages(replies).await?, + Err(error) => { + tracing::warn!(peer = %self.peer, %error, "could not serve the sector state") + } + } + Ok(()) + } message_type::SECTOR_COMMAND => { let Some(account) = self.account else { return Ok(()); diff --git a/crates/logic/src/messages/mod.rs b/crates/logic/src/messages/mod.rs index 9e70c65..d356991 100644 --- a/crates/logic/src/messages/mod.rs +++ b/crates/logic/src/messages/mod.rs @@ -12,6 +12,7 @@ mod matchmake; mod out_of_sync; mod own_home_data; mod battle_event; +mod request_sector_state; mod sector_command; mod sector_state; mod server_error; @@ -35,6 +36,7 @@ pub use matchmake::{CancelMatchmakeDoneMessage, HomeLogicStoppedMessage, StopHom pub use out_of_sync::OutOfSyncMessage; pub use own_home_data::OwnHomeDataMessage; pub use battle_event::{BattleEventMessage, SendBattleEventMessage}; +pub use request_sector_state::RequestSectorStateMessage; pub use sector_command::SectorCommandMessage; pub use sector_state::SectorStateMessage; pub use server_error::ServerErrorMessage; @@ -53,6 +55,7 @@ pub mod message_type { pub const START_MISSION: u16 = 14104; pub const HOME_LOGIC_STOPPED: u16 = 14105; pub const CANCEL_MATCHMAKE: u16 = 14107; + pub const REQUEST_SECTOR_STATE: u16 = 12903; pub const SECTOR_COMMAND: u16 = 12904; pub const SEND_BATTLE_EVENT: u16 = 12951; pub const BATTLE_EVENT: u16 = 22952; diff --git a/crates/logic/src/messages/request_sector_state.rs b/crates/logic/src/messages/request_sector_state.rs new file mode 100644 index 0000000..502838f --- /dev/null +++ b/crates/logic/src/messages/request_sector_state.rs @@ -0,0 +1,7 @@ +use titan::Message; +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Message)] +#[message(id = 12903, direction = "client", name = "RequestSectorStateMessage")] +pub struct RequestSectorStateMessage { + #[codec(vint)] + pub client_tick: i32, +} diff --git a/crates/service-rpc/src/game.rs b/crates/service-rpc/src/game.rs index b9c4982..a265177 100644 --- a/crates/service-rpc/src/game.rs +++ b/crates/service-rpc/src/game.rs @@ -56,6 +56,9 @@ pub enum GameRequest { BattleTick { account: AccountRef, }, + RequestSectorState { + account: AccountRef, + }, SectorCommand { account: AccountRef, #[serde(with = "crate::base64::serde_bytes")] @@ -117,5 +120,6 @@ pub trait GameApi: Send + Sync + 'static { async fn battle_event(&self, account: AccountRef, payload: Vec) -> RpcResult<()>; async fn cancel_matchmake(&self, account: AccountRef) -> RpcResult<()>; async fn sector_command(&self, account: AccountRef, payload: Vec) -> RpcResult<()>; + async fn request_sector_state(&self, account: AccountRef) -> RpcResult>; async fn disconnect(&self, account: AccountRef) -> RpcResult<()>; }