aboutsummaryrefslogtreecommitdiff
path: root/games/rstnode/rst-server/src/server.rs
diff options
context:
space:
mode:
Diffstat (limited to 'games/rstnode/rst-server/src/server.rs')
-rw-r--r--games/rstnode/rst-server/src/server.rs153
1 files changed, 153 insertions, 0 deletions
diff --git a/games/rstnode/rst-server/src/server.rs b/games/rstnode/rst-server/src/server.rs
new file mode 100644
index 000000000000..9badba85d1a6
--- /dev/null
+++ b/games/rstnode/rst-server/src/server.rs
@@ -0,0 +1,153 @@
+//! 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 async_std::sync::{Arc, Mutex};
+use async_trait::async_trait;
+use chrono::{DateTime, Utc};
+use rst_core::{
+ data::Player,
+ lobby::LobbyList,
+ map::Map,
+ users::UserStore,
+ wire::{
+ Action, AuthErr, Lobby, LobbyErr, LobbyId, LobbyUpdate, MatchErr, MatchId, RegErr,
+ Response, UpdateState, User, UserId,
+ },
+ GameIf, Match,
+};
+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
+ pub(crate) fn new() -> Arc<Self> {
+ Arc::new(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> {
+ todo!()
+ }
+
+ async fn login(self: Arc<Self>, _name: String, _pw: String) -> Result<User, AuthErr> {
+ todo!()
+ }
+
+ async fn logout(self: Arc<Self>, _user: User) -> Result<(), AuthErr> {
+ todo!()
+ }
+
+ async fn anonymous(self: Arc<Self>, name: String) -> Result<User, AuthErr> {
+ // let (_, auth) = self.users.add(name, None, true).await;
+ // Ok(auth)
+ todo!()
+ }
+
+ 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, |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, |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, |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, |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!()
+ }
+}