aboutsummaryrefslogtreecommitdiff
path: root/games/rstnode/rst-core/src
diff options
context:
space:
mode:
Diffstat (limited to 'games/rstnode/rst-core/src')
-rw-r--r--games/rstnode/rst-core/src/_if.rs4
-rw-r--r--games/rstnode/rst-core/src/_match.rs12
-rw-r--r--games/rstnode/rst-core/src/data.rs49
-rw-r--r--games/rstnode/rst-core/src/error.rs51
-rw-r--r--games/rstnode/rst-core/src/lib.rs9
-rw-r--r--games/rstnode/rst-core/src/lobby.rs3
-rw-r--r--games/rstnode/rst-core/src/mailbox.rs78
-rw-r--r--games/rstnode/rst-core/src/map.rs20
-rw-r--r--games/rstnode/rst-core/src/net/endpoint.rs49
-rw-r--r--games/rstnode/rst-core/src/net/gen.rs52
-rw-r--r--games/rstnode/rst-core/src/net/handler.rs17
-rw-r--r--games/rstnode/rst-core/src/net/mod.rs20
-rw-r--r--games/rstnode/rst-core/src/net/parser.rs17
-rw-r--r--games/rstnode/rst-core/src/server.rs62
-rw-r--r--games/rstnode/rst-core/src/wire/game/action.rs (renamed from games/rstnode/rst-core/src/wire/action.rs)0
-rw-r--r--games/rstnode/rst-core/src/wire/game/mod.rs5
-rw-r--r--games/rstnode/rst-core/src/wire/game/update.rs (renamed from games/rstnode/rst-core/src/wire/update.rs)19
-rw-r--r--games/rstnode/rst-core/src/wire/mod.rs11
-rw-r--r--games/rstnode/rst-core/src/wire/proto/mod.rs25
-rw-r--r--games/rstnode/rst-core/src/wire/proto/request.rs41
-rw-r--r--games/rstnode/rst-core/src/wire/proto/response.rs0
-rw-r--r--games/rstnode/rst-core/src/wire/req.rs2
-rw-r--r--games/rstnode/rst-core/src/wire/resp.rs10
23 files changed, 472 insertions, 84 deletions
diff --git a/games/rstnode/rst-core/src/_if.rs b/games/rstnode/rst-core/src/_if.rs
index 1a842840708c..f3ed8ee5ffde 100644
--- a/games/rstnode/rst-core/src/_if.rs
+++ b/games/rstnode/rst-core/src/_if.rs
@@ -1,8 +1,8 @@
//! A common trait interface between the server and the client
use crate::wire::{
- Action, AuthErr, Lobby, LobbyErr, LobbyId, LobbyUpdate, MatchErr, MatchId, RegErr, UpdateState,
- User, UserId,
+ game::Action, AuthErr, Lobby, LobbyErr, LobbyId, LobbyUpdate, MatchErr, MatchId, RegErr,
+ UpdateState, User, UserId,
};
use async_std::sync::Arc;
use async_trait::async_trait;
diff --git a/games/rstnode/rst-core/src/_match.rs b/games/rstnode/rst-core/src/_match.rs
index ce75af5af393..e1cc45374ebc 100644
--- a/games/rstnode/rst-core/src/_match.rs
+++ b/games/rstnode/rst-core/src/_match.rs
@@ -1,8 +1,9 @@
use crate::{
data::Player,
lobby::MetaLobby,
+ mailbox::{Inbox, Outbox},
map::Map,
- wire::{Action, LobbyUser, MatchId, UserId},
+ wire::{game::Action, LobbyUser, MatchId, UserId},
};
use async_std::sync::{Arc, RwLock};
use chrono::{DateTime, Utc};
@@ -23,7 +24,9 @@ pub struct Match {
/// The active game map
pub map: Map,
/// Input inbox (handled in-order each game tick)
- inbox: RwLock<VecDeque<Action>>,
+ inbox: Inbox,
+ /// Update outbox
+ outbox: Outbox,
/// The time the match was initialised
init_t: DateTime<Utc>,
/// The synced time the match was started
@@ -46,7 +49,8 @@ impl From<MetaLobby> for Match {
})
.collect(),
map: Map::new(),
- inbox: Default::default(),
+ inbox: Inbox::new(),
+ outbox: Outbox::new(),
init_t: Utc::now(),
start_t: None,
}
@@ -61,7 +65,7 @@ impl Match {
/// Queue a new game action
pub async fn queue(&self, cmd: Action) {
- self.inbox.write().await.push_back(cmd);
+ self.inbox.queue(cmd).await;
}
pub async fn handle_inbox(&mut self) {
diff --git a/games/rstnode/rst-core/src/data.rs b/games/rstnode/rst-core/src/data.rs
index d0494fdef3e2..44d4e2a1a456 100644
--- a/games/rstnode/rst-core/src/data.rs
+++ b/games/rstnode/rst-core/src/data.rs
@@ -4,10 +4,13 @@
use crate::io::Io;
use async_std::sync::Arc;
-use rand::seq::SliceRandom;
-use rand::thread_rng;
+use rand::{seq::SliceRandom, thread_rng};
+use ratman::Router;
use serde::{Deserialize, Serialize};
-use std::sync::atomic::{AtomicBool, AtomicU16, AtomicU32};
+use std::{
+ collections::VecDeque,
+ sync::atomic::{AtomicBool, AtomicU16, AtomicU32, Ordering},
+};
pub type NodeId = usize;
@@ -31,9 +34,12 @@ pub struct Node {
pub links: u8,
/// Active link states
pub link_states: Vec<Arc<Link>>,
+ /// Router state
+ #[serde(skip)]
+ pub router: Option<Router>,
/// Input buffer
#[serde(skip)]
- pub buffer: Vec<Packet>,
+ pub buffer: VecDeque<Packet>,
}
pub type LinkId = usize;
@@ -42,19 +48,19 @@ pub type LinkId = usize;
#[derive(Serialize, Deserialize)]
pub struct Link {
/// This link ID
- id: LinkId,
+ pub id: LinkId,
/// Node 1
- a: NodeId,
+ pub a: NodeId,
/// Node 2
- b: NodeId,
+ pub b: NodeId,
/// The step length
- length: usize,
+ pub length: usize,
/// Packets present on this link
#[serde(skip)]
- pp: Vec<(Packet, AtomicU32)>,
+ pub pp: Vec<(Packet, AtomicU32)>,
/// Actual Rx, Tx pair
#[serde(skip)]
- io: Io,
+ pub io: Io,
}
pub type PacketId = usize;
@@ -86,8 +92,27 @@ pub struct Player {
pub money: AtomicU16,
}
+// This is required because atomics can't safely be cloned
+impl Clone for Player {
+ fn clone(&self) -> Self {
+ let Self {
+ ref id,
+ ref name,
+ ref color,
+ ref money,
+ } = self;
+
+ Self {
+ id: id.clone(),
+ name: name.clone(),
+ color: color.clone(),
+ money: money.load(Ordering::Relaxed).into(),
+ }
+ }
+}
+
/// Optionally, players can create teams
-#[derive(Serialize, Deserialize)]
+#[derive(Clone, Serialize, Deserialize)]
pub struct Team {
/// Name of the team
name: String,
@@ -189,8 +214,6 @@ pub enum Owner {
Player(Player),
}
-
-
/// Encodes upgrade level without numbers
#[derive(Copy, Clone, Serialize, Deserialize)]
pub enum Level {
diff --git a/games/rstnode/rst-core/src/error.rs b/games/rstnode/rst-core/src/error.rs
new file mode 100644
index 000000000000..38c93bbe823f
--- /dev/null
+++ b/games/rstnode/rst-core/src/error.rs
@@ -0,0 +1,51 @@
+pub use crate::wire::{AuthErr, LobbyErr, MatchErr, RegErr};
+use serde::{Deserialize, Serialize};
+use std::fmt::{self, Display, Formatter};
+
+/// A wrapper around the different RST node errors that can occur
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub enum Error {
+ /// Failure in the registration process
+ Register(RegErr),
+ /// Failure in the authentication process
+ Auth(AuthErr),
+ /// Failure handling a lobby
+ Lobby(LobbyErr),
+ /// Failure in a match setting
+ Match(MatchErr),
+}
+
+impl std::error::Error for Error {}
+
+impl Display for Error {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ write!(f, "An RST error")
+ }
+}
+
+/// A RST Node specific error
+pub type Result<T> = std::result::Result<T, Error>;
+
+impl From<RegErr> for Error {
+ fn from(e: RegErr) -> Self {
+ Error::Register(e)
+ }
+}
+
+impl From<AuthErr> for Error {
+ fn from(e: AuthErr) -> Self {
+ Error::Auth(e)
+ }
+}
+
+impl From<LobbyErr> for Error {
+ fn from(e: LobbyErr) -> Self {
+ Error::Lobby(e)
+ }
+}
+
+impl From<MatchErr> for Error {
+ fn from(e: MatchErr) -> Self {
+ Error::Match(e)
+ }
+}
diff --git a/games/rstnode/rst-core/src/lib.rs b/games/rstnode/rst-core/src/lib.rs
index 5ee4e49750c9..dc1a84f63b58 100644
--- a/games/rstnode/rst-core/src/lib.rs
+++ b/games/rstnode/rst-core/src/lib.rs
@@ -13,9 +13,15 @@
//! which is them implemented by [Server](crate::server::Server), and
//! [MatchClient](crate::client::MatchClient).
+// Remove the warning spam
+#![allow(warnings)]
+
#[macro_use]
extern crate const_env;
+#[macro_use]
+extern crate tracing;
+
pub(crate) mod _loop;
mod _if;
@@ -26,11 +32,14 @@ pub use _match::Match;
pub mod config;
pub mod data;
+pub mod error;
pub mod gens;
pub mod io;
pub mod lobby;
+pub mod mailbox;
pub mod map;
pub mod mapstore;
+pub mod net;
pub mod server;
pub mod stats;
pub mod users;
diff --git a/games/rstnode/rst-core/src/lobby.rs b/games/rstnode/rst-core/src/lobby.rs
index 496f98bd7b6f..d58ba7ceb8ee 100644
--- a/games/rstnode/rst-core/src/lobby.rs
+++ b/games/rstnode/rst-core/src/lobby.rs
@@ -2,6 +2,7 @@
use crate::{
data::{Color, ColorPalette},
+ mailbox::Outbox,
users::MetaUser,
wire::{Lobby, LobbyErr, LobbyId, LobbyUpdate, LobbyUser, User, UserId},
};
@@ -68,6 +69,7 @@ impl LobbyList {
pub struct MetaLobby {
pub palette: Vec<Color>,
pub inner: Lobby,
+ pub outbox: Outbox,
}
impl MetaLobby {
@@ -80,6 +82,7 @@ impl MetaLobby {
players: vec![],
settings: vec![],
},
+ outbox: Outbox::new(),
}
}
diff --git a/games/rstnode/rst-core/src/mailbox.rs b/games/rstnode/rst-core/src/mailbox.rs
new file mode 100644
index 000000000000..c7e4512dbeae
--- /dev/null
+++ b/games/rstnode/rst-core/src/mailbox.rs
@@ -0,0 +1,78 @@
+use crate::wire::{
+ game::{Action, Update},
+ Lobby,
+};
+
+use async_std::sync::RwLock;
+use std::collections::VecDeque;
+
+pub enum ClientUpdate {
+ /// Change to the lobby state
+ Lobby(Lobby),
+ /// A game simulation update
+ GameUpdate(Update),
+}
+
+impl<'l> From<&'l Lobby> for ClientUpdate {
+ fn from(l: &'l Lobby) -> Self {
+ ClientUpdate::Lobby(l.clone())
+ }
+}
+
+impl<'l> From<&'l Update> for ClientUpdate {
+ fn from(u: &'l Update) -> Self {
+ ClientUpdate::GameUpdate(u.clone())
+ }
+}
+
+/// A message out buffer that can be attached to any server entity
+pub struct Outbox {
+ queue: RwLock<VecDeque<ClientUpdate>>,
+}
+
+impl Outbox {
+ pub fn new() -> Self {
+ Self {
+ queue: Default::default(),
+ }
+ }
+
+ /// Queue a new item to send out
+ pub async fn queue(&self, update: impl Into<ClientUpdate>) {
+ let mut q = self.queue.write().await;
+ q.push_back(update.into());
+ }
+
+ /// Run a closure for all queued items
+ pub async fn run_for<F: Fn(&ClientUpdate)>(&self, handle: F) {
+ let q = self.queue.read().await;
+ q.iter().for_each(|item| handle(item));
+ }
+
+ /// Clear the outbox for the next update interval
+ pub async fn clear(&self) {
+ self.queue.write().await.clear();
+ }
+}
+
+pub struct Inbox {
+ queue: RwLock<VecDeque<Action>>,
+}
+
+impl Inbox {
+ pub fn new() -> Self {
+ Self {
+ queue: Default::default(),
+ }
+ }
+
+ /// Queue a new item to send out
+ pub async fn queue(&self, update: impl Into<Action>) {
+ let mut q = self.queue.write().await;
+ q.push_back(update.into());
+ }
+
+ pub async fn pop(&self) -> Option<Action> {
+ self.queue.write().await.pop_front()
+ }
+}
diff --git a/games/rstnode/rst-core/src/map.rs b/games/rstnode/rst-core/src/map.rs
index 37f758b4a433..8c6578177e6c 100644
--- a/games/rstnode/rst-core/src/map.rs
+++ b/games/rstnode/rst-core/src/map.rs
@@ -1,17 +1,11 @@
//! Implements a map graph and world logic
use crate::{
- config::{LinkCfg, MapCfg, NodeCfg},
data::{Link, Node, NodeId},
- server::{ServerErr, ServerResult},
wire::Response,
};
use async_std::sync::Arc;
-use quadtree_rs::{
- area::{Area, AreaBuilder},
- point::Point,
- Quadtree,
-};
+use quadtree_rs::{area::AreaBuilder, point::Point, Quadtree};
use std::collections::BTreeMap;
pub struct MapNode {
@@ -29,7 +23,7 @@ pub struct Map {
/// Node IDs mapped to coordinates
nodes: BTreeMap<NodeId, (i64, i64)>,
/// Link IDs mapped to link objects
- links: BTreeMap<u16, Arc<Link>>,
+ _links: BTreeMap<u16, Arc<Link>>,
/// A coordinate map for the network
coord: Quadtree<i64, Arc<MapNode>>,
}
@@ -38,16 +32,14 @@ impl Map {
pub fn new() -> Self {
Self {
nodes: BTreeMap::new(),
- links: BTreeMap::new(),
+ _links: BTreeMap::new(),
coord: Quadtree::new(2),
}
}
- pub fn update<F>(&mut self, cb: F) -> ServerResult<Response>
- where
- F: Fn(&mut Map) -> ServerResult<Response>,
- {
- unimplemented!()
+ /// Get the position of a node by its ID
+ pub fn node_position(&self, id: NodeId) -> Option<(i64, i64)> {
+ self.nodes.get(&id).cloned()
}
/// Get all objects that can be selected by a single point
diff --git a/games/rstnode/rst-core/src/net/endpoint.rs b/games/rstnode/rst-core/src/net/endpoint.rs
new file mode 100644
index 000000000000..0c8e2f912421
--- /dev/null
+++ b/games/rstnode/rst-core/src/net/endpoint.rs
@@ -0,0 +1,49 @@
+use crate::{server::Server, Id};
+use async_std::{
+ net::UdpSocket,
+ sync::{Arc, RwLock},
+ task,
+};
+use std::{
+ collections::BTreeMap,
+ net::SocketAddr,
+ sync::atomic::{AtomicBool, Ordering},
+};
+
+pub struct Endpoint {
+ running: AtomicBool,
+ socket: UdpSocket,
+ bind: String,
+ clients: RwLock<BTreeMap<Id, Client>>,
+}
+
+pub struct Client {}
+
+impl Endpoint {
+ pub async fn new(bind: &str) -> Arc<Self> {
+ let socket = UdpSocket::bind(bind).await.unwrap();
+ Arc::new(Self {
+ running: true.into(),
+ socket,
+ bind: bind.into(),
+ clients: Default::default(),
+ })
+ }
+
+ /// Stop the endpoint
+ pub fn stop(self: &Arc<Self>) {
+ self.running.store(false, Ordering::Relaxed);
+ }
+
+ pub async fn listen(self: &Arc<Self>, serv: Arc<Server>) {
+ let mut buf = vec![0; 1024];
+
+ info!("Listening for connections on {}", self.bind);
+ while self.running.load(Ordering::Relaxed) {
+ let (int, peer) = self.socket.recv_from(&mut buf).await.unwrap();
+ if int > 1024 {
+ warn!("Read a larger chunk than buffer?");
+ }
+ }
+ }
+}
diff --git a/games/rstnode/rst-core/src/net/gen.rs b/games/rstnode/rst-core/src/net/gen.rs
new file mode 100644
index 000000000000..f0a1f58f1905
--- /dev/null
+++ b/games/rstnode/rst-core/src/net/gen.rs
@@ -0,0 +1,52 @@
+use crate::{
+ error::Error,
+ wire::{
+ AuthErr, Lobby, LobbyErr, LobbyId, LobbyUpdate, MatchErr, RegErr, Response, UpdateState,
+ User, UserId,
+ },
+};
+use chrono::{DateTime, Utc};
+
+pub fn register(r: Result<UserId, RegErr>) -> Response {
+ Response::Register(r)
+}
+
+pub fn login(r: Result<User, AuthErr>) -> Response {
+ Response::Login(r)
+}
+
+pub fn logout(r: Result<(), AuthErr>) -> Response {
+ Response::Logout(r)
+}
+
+pub fn rooms(r: Vec<(String, LobbyId)>) -> Response {
+ Response::Rooms(r)
+}
+
+pub fn join(r: Result<Lobby, LobbyErr>) -> Response {
+ Response::Join(r)
+}
+
+pub fn leave(r: Result<(), LobbyErr>) -> Response {
+ Response::Leave(r)
+}
+
+pub fn ready(r: LobbyUpdate) -> Response {
+ Response::Ready(r)
+}
+
+pub fn start_req(r: DateTime<Utc>) -> Response {
+ Response::StartReq(r)
+}
+
+pub fn game_update(r: UpdateState) -> Response {
+ Response::GameUpdate(r)
+}
+
+pub fn leave_game(r: Result<(), MatchErr>) -> Response {
+ Response::LeaveGame(r)
+}
+
+pub fn invalid() -> Response {
+ Response::Invalid
+}
diff --git a/games/rstnode/rst-core/src/net/handler.rs b/games/rstnode/rst-core/src/net/handler.rs
new file mode 100644
index 000000000000..aa0ab6a281c5
--- /dev/null
+++ b/games/rstnode/rst-core/src/net/handler.rs
@@ -0,0 +1,17 @@
+use crate::{
+ net::Client,
+ server::Server,
+ wire::{Request, Response},
+};
+use async_std::sync::{Receiver, Sender};
+
+pub struct Handler {
+ tx: Sender<Response>,
+}
+
+impl Handler {
+ /// Start a message handler with a handle to send a reply back to the clients
+ pub fn start(req: Request) {
+
+ }
+}
diff --git a/games/rstnode/rst-core/src/net/mod.rs b/games/rstnode/rst-core/src/net/mod.rs
new file mode 100644
index 000000000000..f60cb3b97668
--- /dev/null
+++ b/games/rstnode/rst-core/src/net/mod.rs
@@ -0,0 +1,20 @@
+mod endpoint;
+pub use endpoint::*;
+
+mod gen;
+pub use gen::*;
+
+mod handler;
+pub use handler::*;
+
+mod parser;
+pub use parser::*;
+
+// #[async_std::test]
+// async fn user_connection() {
+// let serv = Server::new();
+// let ep = Endpoint::new("localhost:9999").await;
+// task::spawn(async move { ep.listen(serv).await });
+
+// // Create a fake client here
+// }
diff --git a/games/rstnode/rst-core/src/net/parser.rs b/games/rstnode/rst-core/src/net/parser.rs
new file mode 100644
index 000000000000..d7fdf3de964a
--- /dev/null
+++ b/games/rstnode/rst-core/src/net/parser.rs
@@ -0,0 +1,17 @@
+use crate::{
+ error::Error,
+ wire::{Request, Response},
+ GameIf,
+};
+use std::sync::Arc;
+
+/// Parse a request and call a game interface function for it
+pub async fn request(req: Request, game: Arc<impl GameIf>) -> Response {
+ use Request::*;
+ match req {
+ Register(name, pw) => super::register(game.register(name, pw).await),
+ Login(name, pw_hash) => super::login(game.login(name, pw_hash).await),
+ Logout(user) => super::logout(game.logout(user).await),
+ _ => super::invalid(),
+ }
+}
diff --git a/games/rstnode/rst-core/src/server.rs b/games/rstnode/rst-core/src/server.rs
index 3d95c3638c98..68fa2a074e34 100644
--- a/games/rstnode/rst-core/src/server.rs
+++ b/games/rstnode/rst-core/src/server.rs
@@ -4,18 +4,17 @@
//! 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,
+ game::Action, AuthErr, Lobby, LobbyErr, LobbyId, LobbyUpdate, MatchErr, MatchId, RegErr,
Response, UpdateState, User, UserId,
},
+ GameIf, Match,
};
-use async_std::sync::{Arc, Mutex, RwLock};
+use async_std::sync::{Arc, Mutex};
use async_trait::async_trait;
use chrono::{DateTime, Utc};
use std::{collections::BTreeMap, path::Path};
@@ -40,12 +39,12 @@ pub struct Server {
impl Server {
/// Create a new game server
- fn new() -> Self {
- Self {
+ 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
@@ -68,15 +67,15 @@ impl Server {
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_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
@@ -91,31 +90,32 @@ impl Server {
#[async_trait]
impl GameIf for Server {
- async fn register(self: Arc<Self>, name: String, pw: String) -> Result<UserId, RegErr> {
- unimplemented!()
+ 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> {
- unimplemented!()
+ async fn login(self: Arc<Self>, _name: String, _pw: String) -> Result<User, AuthErr> {
+ todo!()
}
- async fn logout(self: Arc<Self>, user: User) -> Result<(), AuthErr> {
- unimplemented!()
+ 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)
+ // 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, |mut l| l.join(&mu)).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, |mut l| l.leave(&mu)).await
+ self.lobbies.get_mut(lobby, |l| l.leave(&mu)).await
}
async fn ready(
@@ -124,9 +124,7 @@ impl GameIf for Server {
lobby: LobbyId,
ready: bool,
) -> Result<LobbyUpdate, LobbyErr> {
- self.lobbies
- .get_mut(lobby, |mut l| l.ready(user, ready))
- .await
+ self.lobbies.get_mut(lobby, |l| l.ready(user, ready)).await
}
/// A start request was received
@@ -135,8 +133,8 @@ impl GameIf for Server {
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?;
+ self.lobbies.get_mut(lobby, |l| l.start(user)).await??;
+ let _lob = self.lobbies.consume(lobby).await?;
Ok(Utc::now())
}
@@ -149,7 +147,7 @@ impl GameIf for Server {
unimplemented!()
}
- async fn leave_match(self: Arc<Self>, user: User, mtch: MatchId) -> Result<(), MatchErr> {
+ async fn leave_match(self: Arc<Self>, _user: User, _mtch: MatchId) -> Result<(), MatchErr> {
unimplemented!()
}
}
diff --git a/games/rstnode/rst-core/src/wire/action.rs b/games/rstnode/rst-core/src/wire/game/action.rs
index 22ab7ce6868e..22ab7ce6868e 100644
--- a/games/rstnode/rst-core/src/wire/action.rs
+++ b/games/rstnode/rst-core/src/wire/game/action.rs
diff --git a/games/rstnode/rst-core/src/wire/game/mod.rs b/games/rstnode/rst-core/src/wire/game/mod.rs
new file mode 100644
index 000000000000..2cb32cbaa79c
--- /dev/null
+++ b/games/rstnode/rst-core/src/wire/game/mod.rs
@@ -0,0 +1,5 @@
+mod action;
+pub use action::*;
+
+mod update;
+pub use update::*;
diff --git a/games/rstnode/rst-core/src/wire/update.rs b/games/rstnode/rst-core/src/wire/game/update.rs
index a1b47ff07e50..44a2e646bd34 100644
--- a/games/rstnode/rst-core/src/wire/update.rs
+++ b/games/rstnode/rst-core/src/wire/game/update.rs
@@ -1,11 +1,13 @@
//! Update to the game state
-use super::UserId;
-use crate::data::{NodeId, PacketId, Player, Upgrade};
+use crate::{
+ data::{NodeId, PacketId, Player, Upgrade},
+ wire::UserId,
+};
use serde::{Deserialize, Serialize};
/// An update provided by the game server
-#[derive(Serialize, Deserialize)]
+#[derive(Clone, Serialize, Deserialize)]
pub enum Update {
/// Update made to a node
Node(NodeUpdate),
@@ -20,7 +22,7 @@ pub enum Update {
}
/// Update made to a node
-#[derive(Serialize, Deserialize)]
+#[derive(Clone, Serialize, Deserialize)]
pub enum NodeUpdate {
/// The node owner changed
Owner(Player),
@@ -35,7 +37,7 @@ pub enum NodeUpdate {
}
/// Update made to a link
-#[derive(Serialize, Deserialize)]
+#[derive(Clone, Serialize, Deserialize)]
pub enum LinkUpdate {
/// Take a packet from a node's buffer
TakePacket(PacketId),
@@ -44,20 +46,21 @@ pub enum LinkUpdate {
}
/// Update made to a packet
-#[derive(Serialize, Deserialize)]
+#[derive(Clone, Serialize, Deserialize)]
pub enum PacketUpdate {
/// Advance a packet along one step along the link
Increment(PacketId),
}
/// Update made to the user set
-#[derive(Serialize, Deserialize)]
+#[derive(Clone, Serialize, Deserialize)]
pub enum UserUpdate {
UserLeft(UserId),
+ UserPaused(UserId),
}
/// An error occured, can be non-fatal
-#[derive(Serialize, Deserialize)]
+#[derive(Clone, Serialize, Deserialize)]
pub enum UpdateError {
/// You are the last user in the match
LastUser,
diff --git a/games/rstnode/rst-core/src/wire/mod.rs b/games/rstnode/rst-core/src/wire/mod.rs
index 493f0bcb6885..1f15bca79028 100644
--- a/games/rstnode/rst-core/src/wire/mod.rs
+++ b/games/rstnode/rst-core/src/wire/mod.rs
@@ -1,20 +1,19 @@
//! Network formats and container messages
-mod action;
-pub use action::*;
-
mod env;
pub use env::*;
+pub mod game;
+
+mod proto;
+pub use proto::*;
+
mod resp;
pub use resp::*;
mod req;
pub use req::*;
-mod update;
-pub use update::*;
-
use crate::{data::Color, Id};
use serde::{Deserialize, Serialize};
diff --git a/games/rstnode/rst-core/src/wire/proto/mod.rs b/games/rstnode/rst-core/src/wire/proto/mod.rs
new file mode 100644
index 000000000000..07598bc85540
--- /dev/null
+++ b/games/rstnode/rst-core/src/wire/proto/mod.rs
@@ -0,0 +1,25 @@
+//! This module implements the client-server game protocol
+
+use super::{Request, Response};
+
+pub enum NetErr {
+ Refused,
+ Dropped,
+ Timeout,
+ BadData,
+}
+
+/// Use this function to send a request to a partical remote
+///
+/// The function makes sure that you get a valid response back, but
+/// does not yet ensure that this response is correct for the request
+/// in question.
+pub fn request_to(r: Request, remote: String) -> Result<Response, NetErr> {
+ todo!()
+}
+
+/// Use this function to send a response to a client
+pub fn response_to(r: Response, client: String) -> Result<(), NetErr> {
+ todo!()
+}
+
diff --git a/games/rstnode/rst-core/src/wire/proto/request.rs b/games/rstnode/rst-core/src/wire/proto/request.rs
new file mode 100644
index 000000000000..a95c240c4a14
--- /dev/null
+++ b/games/rstnode/rst-core/src/wire/proto/request.rs
@@ -0,0 +1,41 @@
+use crate::wire::{Action, LobbyId, MatchId, Request, User};
+
+pub fn register(name: String, pw: String) -> Request {
+ Request::Register(name, pw)
+}
+c
+pub fn login(name: String, pw: String) -> Request {
+ Request::Login(name, pw)
+}
+
+pub fn logout(user: User) -> Request {
+ Request::Logout(user)
+}
+
+pub fn anonymous(name: String) -> Request {
+ Request::Anonymous(name)
+}
+
+pub fn join(user: User, lid: LobbyId) -> Request {
+ Request::Join(user, lid)
+}
+
+pub fn leave(user: User, lid: LobbyId) -> Request {
+ Request::Leave(user, lid)
+}
+
+pub fn ready(user: User, lid: LobbyId, ready: bool) -> Request {
+ Request::Ready(user, lid, ready)
+}
+
+pub fn start_req(user: User, lid: LobbyId) -> Request {
+ Request::StartReq(user, lid)
+}
+
+pub fn game_action(user: User, mid: MatchId, act: Action) -> Request {
+ Request::GameAction(user, mid, act)
+}
+
+pub fn leave_game(user: User, mid: MatchId) -> Request {
+ Request::LeaveGame(user, mid)
+}
diff --git a/games/rstnode/rst-core/src/wire/proto/response.rs b/games/rstnode/rst-core/src/wire/proto/response.rs
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/games/rstnode/rst-core/src/wire/proto/response.rs
diff --git a/games/rstnode/rst-core/src/wire/req.rs b/games/rstnode/rst-core/src/wire/req.rs
index ffefcbdb6ac7..be5c905795a9 100644
--- a/games/rstnode/rst-core/src/wire/req.rs
+++ b/games/rstnode/rst-core/src/wire/req.rs
@@ -1,4 +1,4 @@
-use super::{action::Action, LobbyId, MatchId, User};
+use super::{game::Action, LobbyId, MatchId, User};
use serde::{Deserialize, Serialize};
/// A message sent from the game client to the server
diff --git a/games/rstnode/rst-core/src/wire/resp.rs b/games/rstnode/rst-core/src/wire/resp.rs
index ef2e192a6044..99598cceb9e6 100644
--- a/games/rstnode/rst-core/src/wire/resp.rs
+++ b/games/rstnode/rst-core/src/wire/resp.rs
@@ -27,9 +27,11 @@ pub enum Response {
GameUpdate(UpdateState),
/// Leave the match (forfeit)
LeaveGame(Result<(), MatchErr>),
+ /// The given request was entirely invalid
+ Invalid,
}
-#[derive(Serialize, Deserialize)]
+#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum RegErr {
/// The password is way too bad
BadPassword,
@@ -39,7 +41,7 @@ pub enum RegErr {
OtherError,
}
-#[derive(Serialize, Deserialize)]
+#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum AuthErr {
/// Wrong password for the user
WrongPassword,
@@ -51,7 +53,7 @@ pub enum AuthErr {
OtherError,
}
-#[derive(Serialize, Deserialize)]
+#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum LobbyErr {
/// The requested room is already full
RoomFull,
@@ -85,7 +87,7 @@ pub enum UpdateState {
}
/// An error that can occur in a match
-#[derive(Serialize, Deserialize)]
+#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum MatchErr {
/// The provided player wasn't in the match (anymore?)
NotInMatch,