diff options
author | Katharina Fey <kookie@spacekookie.de> | 2021-02-06 19:40:53 +0100 |
---|---|---|
committer | Katharina Fey <kookie@spacekookie.de> | 2021-02-06 19:42:04 +0100 |
commit | cf9392a33bb99ae581f818d3ddb8be1231521a02 (patch) | |
tree | 8295d8a4ed199c3263eadd8f1a508b98567a44f7 /games/rstnode/rst-core/src/server.rs | |
parent | 56d96b2f22bf6a61ff992b000215dc3a2c2448ad (diff) |
rstnode: restructure project into workspace and sub-crates
Diffstat (limited to 'games/rstnode/rst-core/src/server.rs')
-rw-r--r-- | games/rstnode/rst-core/src/server.rs | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/games/rstnode/rst-core/src/server.rs b/games/rstnode/rst-core/src/server.rs new file mode 100644 index 000000000000..3d95c3638c98 --- /dev/null +++ b/games/rstnode/rst-core/src/server.rs @@ -0,0 +1,155 @@ +//! Game server state handler +//! +//! A server can host many lobbies at the same time. It listens for +//! connections according to a address given to the initialiser. + +use crate::{ + _if::GameIf, + _match::Match, + data::Player, + lobby::LobbyList, + map::Map, + users::UserStore, + wire::{ + Action, AuthErr, Lobby, LobbyErr, LobbyId, LobbyUpdate, MatchErr, MatchId, RegErr, + Response, UpdateState, User, UserId, + }, +}; +use async_std::sync::{Arc, Mutex, RwLock}; +use async_trait::async_trait; +use chrono::{DateTime, Utc}; +use std::{collections::BTreeMap, path::Path}; + +/// A convenience result wrapper for server actions +pub type ServerResult<T> = Result<T, ServerErr>; +pub enum ServerErr { + /// The requested directory is corrupted + NoSuchDir, + /// Corrupted game state + Corrupted, + /// No such match found + NoSuchMatch, +} + +/// The game's server backend +pub struct Server { + matches: BTreeMap<MatchId, Mutex<Match>>, + users: UserStore, + lobbies: LobbyList, +} + +impl Server { + /// Create a new game server + fn new() -> Self { + Self { + matches: Default::default(), + users: UserStore::new(), + lobbies: LobbyList::new(), + } + } + + /// Open the state dir of a game server + pub async fn open(self: Arc<Self>, path: &Path) -> ServerResult<()> { + Ok(()) + } + + /// Stop accepting new game connections and shutdown gracefully + /// + /// Returns the number of matches still going on. + pub async fn shutdown(self: Arc<Self>) -> ServerResult<u64> { + Ok(0) + } + + /// Save and close the statedir and kicking all players + /// + /// Returns the number of players that were kicked off the server + /// prematurely. + pub async fn kill(self: Arc<Self>) -> ServerResult<u64> { + Ok(0) + } + + pub async fn update_map<F>(self: Arc<Self>, id: MatchId, cb: F) -> ServerResult<Response> + where + F: Fn(&mut Map) -> ServerResult<Response>, + { + match self.matches.get(&id) { + Some(ref m) => m.lock().await.map.update(cb), + None => Err(ServerErr::NoSuchMatch), + } + } + + pub async fn update_players<F>(self: Arc<Self>, id: MatchId, cb: F) -> ServerResult<Response> + where + F: Fn(&mut Vec<Player>) -> ServerResult<Response>, + { + match self.matches.get(&id) { + Some(ref mut m) => cb(&mut m.lock().await.players), + None => Err(ServerErr::NoSuchMatch), + } + } +} + +#[async_trait] +impl GameIf for Server { + async fn register(self: Arc<Self>, name: String, pw: String) -> Result<UserId, RegErr> { + unimplemented!() + } + + async fn login(self: Arc<Self>, name: String, pw: String) -> Result<User, AuthErr> { + unimplemented!() + } + + async fn logout(self: Arc<Self>, user: User) -> Result<(), AuthErr> { + unimplemented!() + } + + async fn anonymous(self: Arc<Self>, name: String) -> Result<User, AuthErr> { + let (_, auth) = self.users.add(name, None, true).await; + Ok(auth) + } + + async fn join(self: Arc<Self>, user: User, lobby: LobbyId) -> Result<Lobby, LobbyErr> { + let mu = self.users.get(&user).await?; + self.lobbies.get_mut(lobby, |mut l| l.join(&mu)).await + } + + async fn leave(self: Arc<Self>, user: User, lobby: LobbyId) -> Result<(), LobbyErr> { + let mu = self.users.get(&user).await?; + self.lobbies.get_mut(lobby, |mut l| l.leave(&mu)).await + } + + async fn ready( + self: Arc<Self>, + user: User, + lobby: LobbyId, + ready: bool, + ) -> Result<LobbyUpdate, LobbyErr> { + self.lobbies + .get_mut(lobby, |mut l| l.ready(user, ready)) + .await + } + + /// A start request was received + async fn start_req( + self: Arc<Self>, + user: UserId, + lobby: LobbyId, + ) -> Result<DateTime<Utc>, LobbyErr> { + self.lobbies.get_mut(lobby, |mut l| l.start(user)).await?; + let lob = self.lobbies.consume(lobby).await?; + Ok(Utc::now()) + } + + async fn perform_action( + self: Arc<Self>, + user: User, + mtch: MatchId, + act: Action, + ) -> UpdateState { + unimplemented!() + } + + async fn leave_match(self: Arc<Self>, user: User, mtch: MatchId) -> Result<(), MatchErr> { + unimplemented!() + } +} |