use std::sync::Arc; use service_rpc::{ AccountRef, AuthApi, AuthRequest, AuthResponse, DeviceInfo, GameApi, GameRequest, GameResponse, HomeRequestKind, LoginOutcome, RpcClient, RpcError, RpcResult, WireMessage, }; pub struct Backends { pub auth: Arc, pub game: Arc, } impl Backends { pub fn new(auth: Arc, game: Arc) -> Arc { Arc::new(Self { auth, game }) } pub fn remote(auth_endpoint: &str, game_endpoint: &str) -> Arc { Self::new( Arc::new(RemoteAuth::new(auth_endpoint)), Arc::new(RemoteGame::new(game_endpoint)), ) } } pub struct RemoteAuth { client: RpcClient, } impl RemoteAuth { pub fn new(endpoint: impl Into) -> Self { Self { client: RpcClient::new(endpoint), } } } #[async_trait::async_trait] impl AuthApi for RemoteAuth { async fn login( &self, account: AccountRef, pass_token: Option, device: DeviceInfo, ) -> RpcResult { match self .client .call(&AuthRequest::Login { account, pass_token, device, }) .await? { AuthResponse::Login(outcome) => Ok(outcome), other => Err(RpcError::Rejected(format!( "unexpected auth reply {other:?}" ))), } } async fn resolve(&self, account: AccountRef) -> RpcResult { match self.client.call(&AuthRequest::Resolve { account }).await? { AuthResponse::Resolved { known } => Ok(known), other => Err(RpcError::Rejected(format!( "unexpected auth reply {other:?}" ))), } } } pub struct RemoteGame { client: RpcClient, } impl RemoteGame { pub fn new(endpoint: impl Into) -> Self { Self { client: RpcClient::new(endpoint), } } } #[async_trait::async_trait] impl GameApi for RemoteGame { async fn load_home( &self, account: AccountRef, kind: HomeRequestKind, ) -> RpcResult> { Ok(self .client .call(&GameRequest::LoadHome { account, kind }) .await? .into_messages()) } async fn client_capabilities(&self, account: AccountRef, ping_ms: i32) -> RpcResult<()> { self.client .call(&GameRequest::ClientCapabilities { account, ping_ms }) .await?; Ok(()) } async fn start_mission( &self, account: AccountRef, payload: Vec, ) -> RpcResult> { Ok(self .client .call(&GameRequest::StartMission { account, payload }) .await? .into_messages()) } async fn home_logic_stopped( &self, account: AccountRef, payload: Vec, ) -> RpcResult> { Ok(self .client .call(&GameRequest::HomeLogicStopped { account, payload }) .await? .into_messages()) } async fn end_client_turn( &self, account: AccountRef, payload: Vec, ) -> RpcResult> { Ok(self .client .call(&GameRequest::EndClientTurn { account, payload }) .await? .into_messages()) } async fn battle_tick(&self, account: AccountRef) -> RpcResult> { Ok(self .client .call(&GameRequest::BattleTick { account }) .await? .into_messages()) } async fn battle_event(&self, account: AccountRef, payload: Vec) -> RpcResult<()> { self.client .call(&GameRequest::BattleEvent { account, payload }) .await?; Ok(()) } async fn cancel_matchmake(&self, account: AccountRef) -> RpcResult<()> { self.client .call(&GameRequest::CancelMatchmake { account }) .await?; Ok(()) } async fn sector_command(&self, account: AccountRef, payload: Vec) -> RpcResult<()> { self.client .call(&GameRequest::SectorCommand { account, payload }) .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 }) .await?; Ok(()) } }