aboutsummaryrefslogtreecommitdiff
path: root/games/rstnode/src/server.rs
diff options
context:
space:
mode:
Diffstat (limited to 'games/rstnode/src/server.rs')
-rw-r--r--games/rstnode/src/server.rs150
1 files changed, 150 insertions, 0 deletions
diff --git a/games/rstnode/src/server.rs b/games/rstnode/src/server.rs
new file mode 100644
index 000000000000..7a2fad27bb1f
--- /dev/null
+++ b/games/rstnode/src/server.rs
@@ -0,0 +1,150 @@
+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!()
+ }
+}