aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/_if.rs20
-rw-r--r--src/_match.rs52
-rw-r--r--src/bin/game.rs5
-rw-r--r--src/bin/server.rs6
-rw-r--r--src/config.rs41
-rw-r--r--src/data.rs17
-rw-r--r--src/lib.rs20
-rw-r--r--src/lobby.rs136
-rw-r--r--src/main.rs42
-rw-r--r--src/map.rs29
-rw-r--r--src/mapstore.rs17
-rw-r--r--src/server.rs45
-rw-r--r--src/users.rs10
-rw-r--r--src/wire/mod.rs23
-rw-r--r--src/wire/resp.rs17
15 files changed, 362 insertions, 118 deletions
diff --git a/src/_if.rs b/src/_if.rs
index 91cb3a2daf18..59d80fb165af 100644
--- a/src/_if.rs
+++ b/src/_if.rs
@@ -1,11 +1,11 @@
//! A common trait interface between the server and the client
use crate::wire::{
- Action, AuthErr, Lobby, LobbyId, MatchErr, MatchId, RegErr, RoomErr, RoomUpdate, UpdateState,
+ Action, AuthErr, Lobby, LobbyErr, LobbyId, LobbyUpdate, MatchErr, MatchId, RegErr, UpdateState,
User, UserId,
};
-use async_trait::async_trait;
use async_std::sync::Arc;
+use async_trait::async_trait;
use chrono::{DateTime, Utc};
/// The main game interface implemented by the server and client
@@ -24,19 +24,25 @@ pub trait GameIf {
async fn anonymous(self: Arc<Self>, name: String) -> Result<User, AuthErr>;
/// Join a match-making lobby
- async fn join(self: Arc<Self>, user: User, lobby: LobbyId) -> Result<Lobby, RoomErr>;
+ async fn join(self: Arc<Self>, user: User, lobby: LobbyId) -> Result<Lobby, LobbyErr>;
/// Leave a match-making lobby
- async fn leave(self: Arc<Self>, user: User, lobby: LobbyId) -> Result<(), RoomErr>;
+ async fn leave(self: Arc<Self>, user: User, lobby: LobbyId) -> Result<(), LobbyErr>;
/// Set the player's ready state
- async fn ready(self: Arc<Self>, user: User, lobby: LobbyId, ready: bool) -> RoomUpdate;
+ async fn ready(
+ self: Arc<Self>,
+ user: User,
+ lobby: LobbyId,
+ ready: bool,
+ ) -> Result<LobbyUpdate, LobbyErr>;
/// Send a start request (as lobby admin)
- async fn start_req(self: Arc<Self>, user: User, lobby: LobbyId) -> DateTime<Utc>;
+ async fn start_req(self: Arc<Self>, user: UserId, lobby: LobbyId) -> Result<DateTime<Utc>, LobbyErr>;
/// Perform a game action as a user
- async fn perform_action(self: Arc<Self>, user: User, mtch: MatchId, act: Action) -> UpdateState;
+ async fn perform_action(self: Arc<Self>, user: User, mtch: MatchId, act: Action)
+ -> UpdateState;
/// Leave a match
async fn leave_match(self: Arc<Self>, user: User, mtch: MatchId) -> Result<(), MatchErr>;
diff --git a/src/_match.rs b/src/_match.rs
new file mode 100644
index 000000000000..23d3be8aeb0d
--- /dev/null
+++ b/src/_match.rs
@@ -0,0 +1,52 @@
+use crate::{
+ data::Player,
+ lobby::MetaLobby,
+ map::Map,
+ wire::{LobbyUser, MatchId, UserId},
+};
+use async_std::sync::Arc;
+use chrono::{DateTime, Utc};
+use serde::{Deserialize, Serialize};
+
+/// Describes a match for the server
+pub struct Match {
+ /// The match id
+ pub id: MatchId,
+ /// The list of active players
+ pub players: Vec<Player>,
+ /// The active game map
+ pub map: Map,
+ /// The time the match was initialised
+ pub init_t: DateTime<Utc>,
+ /// The synced time the match was started
+ pub start_t: Option<DateTime<Utc>>,
+}
+
+impl From<MetaLobby> for Match {
+ fn from(ml: MetaLobby) -> Self {
+ Self {
+ id: ml.inner.id,
+ players: ml
+ .inner
+ .players
+ .into_iter()
+ .map(|lu| Player {
+ id: lu.id,
+ name: lu.name,
+ color: lu.color,
+ money: 0.into(),
+ })
+ .collect(),
+ map: Map::new(),
+ init_t: Utc::now(),
+ start_t: None,
+ }
+ }
+}
+
+impl Match {
+ /// Set the start time of the match, which may be in the future
+ pub fn set_start(&mut self, t: DateTime<Utc>) {
+ self.start_t = Some(t);
+ }
+}
diff --git a/src/bin/game.rs b/src/bin/game.rs
new file mode 100644
index 000000000000..9bf9fc9f9631
--- /dev/null
+++ b/src/bin/game.rs
@@ -0,0 +1,5 @@
+//! The main game UI client
+
+fn main() {
+
+}
diff --git a/src/bin/server.rs b/src/bin/server.rs
new file mode 100644
index 000000000000..47db85926ac1
--- /dev/null
+++ b/src/bin/server.rs
@@ -0,0 +1,6 @@
+//! The dedicated server binary
+
+
+fn main() {
+
+}
diff --git a/src/config.rs b/src/config.rs
new file mode 100644
index 000000000000..8a1b0b4deb0a
--- /dev/null
+++ b/src/config.rs
@@ -0,0 +1,41 @@
+//! The file formats backing maps and other configs
+
+use crate::data::{NodeId, LinkId};
+use serde::{Serialize, Deserialize};
+use std::path::Path;
+
+/// A config tree that describes a map
+#[derive(Serialize, Deserialize)]
+pub struct MapCfg {
+ /// The set of nodes
+ pub nodes: Vec<NodeCfg>,
+ /// Links connecting nodes
+ pub links: Vec<LinkCfg>,
+ /// Default spawn points (player count)
+ pub spawns: Vec<SpawnCfg>,
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct NodeCfg {
+ /// Node ID
+ pub id: NodeId,
+ /// Render/world position
+ pub x: f64,
+ pub y: f64,
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct LinkCfg {
+ /// The link ID
+ id: LinkId,
+ /// List of connectioned nodes
+ con: Vec<NodeId>,
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct SpawnCfg {
+ /// The node of the spawn point
+ pub n_id: NodeId,
+ /// At what number of players is this spawn available?
+ pub max_players: usize,
+}
diff --git a/src/data.rs b/src/data.rs
index 4cfe0c09e463..940bda10e7e8 100644
--- a/src/data.rs
+++ b/src/data.rs
@@ -78,13 +78,13 @@ pub type PlayerId = usize;
#[derive(Serialize, Deserialize)]
pub struct Player {
/// A unique player ID (per match)
- id: PlayerId,
+ pub id: PlayerId,
/// The player name
- name: String,
+ pub name: String,
/// Player color
- color: Color,
+ pub color: Color,
/// The player's money
- money: AtomicU16,
+ pub money: AtomicU16,
}
/// Optionally, players can create teams
@@ -144,7 +144,7 @@ pub trait ColorPalette {
/// Create a new color palette
fn palette() -> Self;
/// Get a palette without a certain colour
- fn without(b: &Color) -> Self;
+ fn without(&mut self, b: &Color);
/// Mix a color back into the available palette
fn remix(&mut self, new: Color);
}
@@ -167,8 +167,11 @@ impl ColorPalette for Vec<Color> {
pal
}
- fn without(b: &Color) -> Self {
- Self::palette().into_iter().filter(|a| a == b).collect()
+ /// Drop a colour from the palette
+ fn without(&mut self, b: &Color) {
+ if let Some(pos) = self.into_iter().rposition(|a| a == b) {
+ self.remove(pos);
+ }
}
fn remix(&mut self, new: Color) {
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 000000000000..d6e3f246a08d
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,20 @@
+#![allow(warnings)]
+
+mod _if;
+pub use _if::GameIf;
+
+pub mod data;
+pub mod gens;
+
+mod _match;
+mod config;
+mod io;
+mod lobby;
+mod map;
+mod mapstore;
+mod server;
+mod stats;
+mod users;
+mod wire;
+
+pub use identity::Identity as Id;
diff --git a/src/lobby.rs b/src/lobby.rs
index ac6ab305414a..496f98bd7b6f 100644
--- a/src/lobby.rs
+++ b/src/lobby.rs
@@ -3,7 +3,7 @@
use crate::{
data::{Color, ColorPalette},
users::MetaUser,
- wire::{Lobby, LobbyId, LobbyUser},
+ wire::{Lobby, LobbyErr, LobbyId, LobbyUpdate, LobbyUser, User, UserId},
};
use async_std::sync::{Arc, RwLock};
use std::{
@@ -14,15 +14,60 @@ use std::{
/// A list of all the lobbies on the server
pub struct LobbyList {
max: AtomicUsize,
- users: RwLock<BTreeMap<LobbyId, Arc<MetaLobby>>>,
+ lobbies: RwLock<BTreeMap<LobbyId, MetaLobby>>,
+}
+
+impl LobbyList {
+ pub fn new() -> Self {
+ Self {
+ max: 0.into(),
+ lobbies: Default::default(),
+ }
+ }
+
+ /// Create a new lobby
+ pub async fn create(&self, map: String) -> LobbyId {
+ let id = self.max.fetch_add(1, Ordering::Relaxed);
+ self.lobbies
+ .write()
+ .await
+ .insert(id, MetaLobby::create(id, map));
+ id
+ }
+
+ /// Remove a lobby by ID
+ pub async fn destroy(&self, id: LobbyId) -> Result<(), LobbyErr> {
+ self.consume(id).await.map(|_| ())
+ }
+
+ /// Remove and return the lobby
+ pub async fn consume(&self, id: LobbyId) -> Result<MetaLobby, LobbyErr> {
+ self.lobbies
+ .write()
+ .await
+ .remove(&id)
+ .map_or(Err(LobbyErr::NoSuchRoom), |l| Ok(l))
+ }
+
+ /// Get mutable access to a lobby
+ pub async fn get_mut<F, T>(&self, id: LobbyId, cb: F) -> Result<T, LobbyErr>
+ where
+ F: Fn(&mut MetaLobby) -> T,
+ {
+ self.lobbies
+ .write()
+ .await
+ .get_mut(&id)
+ .map_or(Err(LobbyErr::OtherError), |ref mut l| Ok(cb(l)))
+ }
}
/// Additional state held by the server
///
/// The meta lobby will also sync updates to all connected users, when updates are made to the lobby
pub struct MetaLobby {
- palette: Vec<Color>,
- inner: Lobby,
+ pub palette: Vec<Color>,
+ pub inner: Lobby,
}
impl MetaLobby {
@@ -38,21 +83,19 @@ impl MetaLobby {
}
}
- pub fn join(&mut self, user: MetaUser) {
+ pub fn join(&mut self, user: &MetaUser) -> Lobby {
let color = if &user.name == "spacekookie" {
let color = Color::blue();
+ self.palette.without(&color);
- let num = self.inner.players.len();
- self.palette = Vec::without(&color);
- let in_use = self.palette.split_off(num);
-
- self.inner
+ if let Some(user) = self
+ .inner
.players
.iter_mut()
- .zip(in_use.into_iter())
- .for_each(|(user, color)| {
- user.color = color;
- });
+ .find(|u| u.color == Color::blue())
+ {
+ user.color = self.palette.remove(0);
+ }
color
} else {
@@ -60,14 +103,17 @@ impl MetaLobby {
};
self.inner.players.push(LobbyUser {
+ admin: false,
id: user.id,
- name: user.name,
+ name: user.name.clone(),
ready: false,
color,
});
+
+ self.inner.clone()
}
- pub fn leave(&mut self, user: MetaUser) {
+ pub fn leave(&mut self, user: &MetaUser) {
let (pos, user) = self
.inner
.players
@@ -84,4 +130,62 @@ impl MetaLobby {
self.palette.remix(user.color);
self.inner.players.remove(pos);
}
+
+ /// Check if a user is even present in a lobby
+ ///
+ /// Perform this prerequisite check before making other user-specific changes to the lobby
+ pub fn in_lobby(&self, user: UserId) -> bool {
+ self.inner
+ .players
+ .iter()
+ .find(|u| u.id == user)
+ .map(|_| true)
+ .unwrap_or(false)
+ }
+
+ /// Set the ready state for a user
+ pub fn ready(&mut self, user: User, ready: bool) -> LobbyUpdate {
+ if let Some(user) = self
+ .inner
+ .players
+ .iter_mut()
+ .find(|u| u.id == user.id)
+ .as_mut()
+ {
+ user.ready = ready;
+ }
+
+ LobbyUpdate::Ready(
+ self.inner
+ .players
+ .iter()
+ .filter_map(|u| if u.ready { Some(u.id) } else { None })
+ .collect(),
+ )
+ }
+
+ /// Try to start a game, if the user can and everybody is ready
+ pub fn start(&mut self, user: UserId) -> Result<(), LobbyErr> {
+ if let Some(_) = self
+ .inner
+ .players
+ .iter()
+ .filter(|u| u.admin)
+ .find(|u| u.id == user)
+ {
+ return Err(LobbyErr::NotAuthorized);
+ };
+
+ match self
+ .inner
+ .players
+ .iter()
+ .filter(|u| !u.ready)
+ .collect::<Vec<_>>()
+ .len()
+ {
+ 0 => Err(LobbyErr::NotAllReady),
+ _ => Ok(()),
+ }
+ }
}
diff --git a/src/main.rs b/src/main.rs
deleted file mode 100644
index 976a99af2895..000000000000
--- a/src/main.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-#![allow(warnings)]
-
-mod _if;
-mod data;
-mod gens;
-mod io;
-mod lobby;
-mod map;
-mod server;
-mod stats;
-mod users;
-mod wire;
-
-pub(crate) use identity::Identity as Id;
-
-use ggez::{
- self, conf,
- event::{self, EventHandler},
- Context, ContextBuilder, GameResult,
-};
-
-struct GameState;
-
-impl EventHandler for GameState {
- fn update(&mut self, _: &mut Context) -> GameResult {
- Ok(())
- }
-
- fn draw(&mut self, _: &mut Context) -> GameResult {
- Ok(())
- }
-}
-
-fn main() -> GameResult {
- let cb = ContextBuilder::new("RstNode", "Katharina Fey")
- .window_setup(conf::WindowSetup::default().title("RstNode").vsync(true))
- .window_mode(conf::WindowMode::default().dimensions(800.0, 600.0));
-
- let (ctx, el) = &mut cb.build()?;
- let mut game = GameState; // smash the state
- event::run(ctx, el, &mut game)
-}
diff --git a/src/map.rs b/src/map.rs
index f977bec93e1d..212ce75100ad 100644
--- a/src/map.rs
+++ b/src/map.rs
@@ -1,31 +1,42 @@
//! Implements a map graph and world logic
use crate::{
- data::{Link, Node},
- server::{ServerResult, ServerErr},
- wire::Response
+ config::{LinkCfg, MapCfg, NodeCfg},
+ data::{Link, Node, NodeId},
+ server::{ServerErr, ServerResult},
+ wire::Response,
};
use async_std::sync::Arc;
-use serde::{Deserialize, Serialize};
+use quadtree_rs::Quadtree;
use std::collections::BTreeMap;
+pub struct MapNode {
+ pos: (f64, f64),
+ inner: Node,
+}
+
/// A map that people fight on
///
/// A map is defined by it's graph relationships, but also where on
/// the map nodes are placed, how much spacing there is, etc. All
/// this information is encoded in the same structs because it's
/// static, and just more convenient.
-#[derive(Default, Serialize, Deserialize)]
pub struct Map {
- /// Node IDs mapped to node objects
- nodes: BTreeMap<u16, Arc<Node>>,
+ /// Node IDs mapped to coordinates
+ nodes: BTreeMap<NodeId, (i64, i64)>,
/// Link IDs mapped to link objects
links: BTreeMap<u16, Arc<Link>>,
+ /// A coordinate map for the network
+ coord: Quadtree<i64, Arc<MapNode>>,
}
impl Map {
- pub fn new() -> Arc<Self> {
- Arc::new(Self::default())
+ pub fn new() -> Self {
+ Self {
+ nodes: BTreeMap::new(),
+ links: BTreeMap::new(),
+ coord: Quadtree::new(2),
+ }
}
pub fn update<F>(&mut self, cb: F) -> ServerResult<Response>
diff --git a/src/mapstore.rs b/src/mapstore.rs
new file mode 100644
index 000000000000..85c5e36ef93b
--- /dev/null
+++ b/src/mapstore.rs
@@ -0,0 +1,17 @@
+//! Map store
+
+use crate::config::MapCfg;
+use std::{collections::BTreeMap, fs, path::Path};
+
+pub struct MapStore {
+ configs: BTreeMap<String, MapCfg>,
+}
+
+impl MapStore {
+ /// Load a set of map configs
+ pub fn load_path(&mut self, path: &Path) {
+ fs::read_dir(&path).unwrap().for_each(|d| {
+ let name = d.unwrap().file_name().into_string().unwrap();
+ });
+ }
+}
diff --git a/src/server.rs b/src/server.rs
index 6ddfb70a9d41..7a2fad27bb1f 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -1,10 +1,13 @@
use crate::{
_if::GameIf,
+ _match::Match,
+ data::Player,
+ lobby::LobbyList,
map::Map,
users::UserStore,
wire::{
- Action, AuthErr, Lobby, LobbyId, Match, MatchErr, MatchId, MatchUser, RegErr, Response,
- RoomErr, RoomUpdate, UpdateState, User, UserId,
+ Action, AuthErr, Lobby, LobbyErr, LobbyId, LobbyUpdate, MatchErr, MatchId, RegErr,
+ Response, UpdateState, User, UserId,
},
};
use async_std::sync::{Arc, Mutex, RwLock};
@@ -27,6 +30,7 @@ pub enum ServerErr {
pub struct Server {
matches: BTreeMap<MatchId, Mutex<Match>>,
users: UserStore,
+ lobbies: LobbyList,
}
impl Server {
@@ -35,6 +39,7 @@ impl Server {
Self {
matches: Default::default(),
users: UserStore::new(),
+ lobbies: LobbyList::new(),
}
}
@@ -63,14 +68,14 @@ impl Server {
F: Fn(&mut Map) -> ServerResult<Response>,
{
match self.matches.get(&id) {
- Some(ref mut m) => m.lock().await.map.update(cb),
+ 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<MatchUser>) -> ServerResult<Response>,
+ F: Fn(&mut Vec<Player>) -> ServerResult<Response>,
{
match self.matches.get(&id) {
Some(ref mut m) => cb(&mut m.lock().await.players),
@@ -98,20 +103,36 @@ impl GameIf for Server {
Ok(auth)
}
- async fn join(self: Arc<Self>, user: User, lobby: LobbyId) -> Result<Lobby, RoomErr> {
- unimplemented!()
+ 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<(), RoomErr> {
- unimplemented!()
+ 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) -> RoomUpdate {
- unimplemented!()
+ 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
}
- async fn start_req(self: Arc<Self>, user: User, lobby: LobbyId) -> DateTime<Utc> {
- unimplemented!()
+ /// 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(
diff --git a/src/users.rs b/src/users.rs
index edc3c13fe3b1..0c93b83ec1da 100644
--- a/src/users.rs
+++ b/src/users.rs
@@ -1,7 +1,7 @@
//! A users abstraction module
use crate::{
- wire::{User, UserId},
+ wire::{LobbyErr, User, UserId},
Id,
};
use async_std::sync::{Arc, RwLock};
@@ -31,6 +31,14 @@ impl UserStore {
}
}
+ /// Get the metadata user for a login user
+ pub async fn get(&self, user: &User) -> Result<Arc<MetaUser>, LobbyErr> {
+ match self.users.read().await.get(&user.id) {
+ Some(ref u) => Ok(Arc::clone(u)),
+ None => Err(LobbyErr::OtherError),
+ }
+ }
+
pub async fn add<S: Into<Option<String>>>(
&self,
name: String,
diff --git a/src/wire/mod.rs b/src/wire/mod.rs
index bf8dea0e8131..b1c231b44580 100644
--- a/src/wire/mod.rs
+++ b/src/wire/mod.rs
@@ -23,7 +23,7 @@ use serde::{Deserialize, Serialize};
pub type UserId = usize;
/// Represents a user payload
-#[derive(Clone, Serialize, Deserialize)]
+#[derive(Copy, Clone, Serialize, Deserialize)]
pub struct User {
/// The internal user ID
pub id: UserId,
@@ -34,7 +34,7 @@ pub struct User {
}
/// A more lobby specific abstraction for a user
-#[derive(Serialize, Deserialize)]
+#[derive(Clone, Serialize, Deserialize)]
pub struct LobbyUser {
/// The user ID
pub id: UserId,
@@ -42,6 +42,8 @@ pub struct LobbyUser {
pub name: String,
/// Are they ready?
pub ready: bool,
+ /// Are they the lobby admin?
+ pub admin: bool,
/// The colour they will be in the match
pub color: Color,
}
@@ -50,7 +52,7 @@ pub struct LobbyUser {
pub type LobbyId = usize;
/// Represent a lobby
-#[derive(Serialize, Deserialize)]
+#[derive(Clone, Serialize, Deserialize)]
pub struct Lobby {
/// The ID of the lobby
pub id: LobbyId,
@@ -65,19 +67,4 @@ pub struct Lobby {
/// An alias for a match ID
pub type MatchId = usize;
-/// Mapping users to a player in game
-#[derive(Serialize, Deserialize)]
-pub struct MatchUser {
- pub user: User,
- pub player: Player,
-}
-#[derive(Serialize, Deserialize)]
-pub struct Match {
- /// The match id
- pub id: MatchId,
- /// The list of active players
- pub players: Vec<MatchUser>,
- /// The active game map
- pub map: Map,
-}
diff --git a/src/wire/resp.rs b/src/wire/resp.rs
index b9f41fbe93e4..4812baf13e39 100644
--- a/src/wire/resp.rs
+++ b/src/wire/resp.rs
@@ -16,18 +16,17 @@ pub enum Response {
/// Get a list of available <name-room> pairs
Rooms(Vec<(String, LobbyId)>),
/// A user joins a game lobby
- Join(Result<Lobby, RoomErr>),
+ Join(Result<Lobby, LobbyErr>),
/// A user leaves a game lobby
- Leave(Result<(), RoomErr>),
+ Leave(Result<(), LobbyErr>),
/// Get the new set of ready states
- Ready(RoomUpdate),
+ Ready(LobbyUpdate),
/// Receiving a start request time
StartReq(DateTime<Utc>),
/// Response to the action with the state update
GameUpdate(UpdateState),
/// Leave the match (forfeit)
LeaveGame(Result<(), MatchErr>),
-
}
#[derive(Serialize, Deserialize)]
@@ -53,17 +52,23 @@ pub enum AuthErr {
}
#[derive(Serialize, Deserialize)]
-pub enum RoomErr {
+pub enum LobbyErr {
/// The requested room is already full
RoomFull,
/// The room id is unknown
NoSuchRoom,
/// Previously not in room
NotInRoom,
+ /// Not everybody was ready
+ NotAllReady,
+ /// A request was sent by someone who isn't authorised
+ NotAuthorized,
+ /// Other internal error, try again?
+ OtherError,
}
#[derive(Serialize, Deserialize)]
-pub enum RoomUpdate {
+pub enum LobbyUpdate {
/// The set of ready users
Ready(Vec<UserId>),
}