aboutsummaryrefslogtreecommitdiff
path: root/games
diff options
context:
space:
mode:
authorKatharina Fey <kookie@spacekookie.de>2021-02-19 00:12:38 +0100
committerKatharina Fey <kookie@spacekookie.de>2021-02-19 00:12:38 +0100
commit2f401b176b343cf881f3ac3397ffc66808128950 (patch)
tree6d824dc6ea89329e7e3bb54db8b31d11c0428c5a /games
parent837a0ca6438d1f78a7364c3c7c310dc96e01f31d (diff)
rstnode: add basic map i/o mechanism for server and client
Diffstat (limited to 'games')
-rw-r--r--games/rstnode/rst-client/src/assets.rs23
-rw-r--r--games/rstnode/rst-client/src/graphics/entities/mod.rs2
-rw-r--r--games/rstnode/rst-client/src/state/mod.rs6
-rw-r--r--games/rstnode/rst-core/src/data.rs21
-rw-r--r--games/rstnode/rst-core/src/lib.rs6
-rw-r--r--games/rstnode/rst-core/src/loader.rs82
-rw-r--r--games/rstnode/rst-core/src/mapstore.rs1
-rw-r--r--games/rstnode/rst-core/src/net/endpoint.rs23
-rw-r--r--games/rstnode/rst-core/src/net/handler.rs17
-rw-r--r--games/rstnode/rst-core/src/net/mod.rs2
-rw-r--r--games/rstnode/rst-core/src/server.rs8
-rw-r--r--games/rstnode/rst-core/src/users.rs4
-rw-r--r--games/rstnode/rst-server/src/loader.rs7
-rw-r--r--games/rstnode/rst-server/src/main.rs1
14 files changed, 153 insertions, 50 deletions
diff --git a/games/rstnode/rst-client/src/assets.rs b/games/rstnode/rst-client/src/assets.rs
index 76556213fc70..80f58ee585ce 100644
--- a/games/rstnode/rst-client/src/assets.rs
+++ b/games/rstnode/rst-client/src/assets.rs
@@ -12,29 +12,14 @@ use std::{
};
use tempfile::tempdir;
-pub type Result<T> = std::result::Result<T, LoadError>;
-
-#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
-pub struct URI(String, String);
-
-impl From<&'static str> for URI {
- fn from(s: &'static str) -> Self {
- let mut v: Vec<_> = s.split("/").collect();
- Self(v.remove(0).into(), v.remove(0).into())
- }
-}
+pub use rst_core::loader::Uri;
-impl From<String> for URI {
- fn from(s: String) -> Self {
- let mut v: Vec<_> = s.split("/").collect();
- Self(v.remove(0).into(), v.remove(0).into())
- }
-}
+pub type Result<T> = std::result::Result<T, LoadError>;
/// Asset loader
#[derive(Debug)]
pub struct Assets {
- inner: BTreeMap<URI, Image>,
+ inner: BTreeMap<Uri, Image>,
}
impl Assets {
@@ -44,7 +29,7 @@ impl Assets {
}
}
- pub fn find<U: Into<URI>>(&self, u: U) -> Option<Image> {
+ pub fn find<U: Into<Uri>>(&self, u: U) -> Option<Image> {
self.inner.get(&u.into()).map(|i| i.clone())
}
diff --git a/games/rstnode/rst-client/src/graphics/entities/mod.rs b/games/rstnode/rst-client/src/graphics/entities/mod.rs
index db675f816fbf..bb28fdd808d0 100644
--- a/games/rstnode/rst-client/src/graphics/entities/mod.rs
+++ b/games/rstnode/rst-client/src/graphics/entities/mod.rs
@@ -19,7 +19,6 @@ impl<'a> From<&'a Coordinates> for Point2<f32> {
}
pub struct NodeRndr {
- pub loc: Coordinates,
pub inner: Arc<Node>,
}
@@ -44,7 +43,6 @@ impl Renderer for NodeRndr {
}
pub struct LinkRndr {
- pub loc: Coordinates,
pub inner: Arc<Link>,
}
diff --git a/games/rstnode/rst-client/src/state/mod.rs b/games/rstnode/rst-client/src/state/mod.rs
index 45e69eee10bb..cd030dcd5595 100644
--- a/games/rstnode/rst-client/src/state/mod.rs
+++ b/games/rstnode/rst-client/src/state/mod.rs
@@ -17,7 +17,7 @@ use crate::{
};
use ggez::{event::EventHandler, graphics, Context, GameResult};
use rst_core::{
- data::{Color, Level, Link, Node, Owner, Player, Upgrade},
+ data::{Color, Level, Link, Node, Owner, Player, Position, Upgrade},
io::Io,
};
use std::sync::Arc;
@@ -51,9 +51,9 @@ impl ClientState {
vp: Viewport::new(),
input: InputHandle::new(),
node1: NodeRndr {
- loc: Coordinates(512.0, 512.0),
inner: Arc::new(Node {
id: 0,
+ pos: Position { x: 512.0, y: 512.0 },
health: 100.into(),
max_health: 100.into(),
owner: Owner::Player(Player {
@@ -70,9 +70,9 @@ impl ClientState {
}),
},
node2: NodeRndr {
- loc: Coordinates(128.0, 128.0),
inner: Arc::new(Node {
id: 0,
+ pos: Position { x: 128.0, y: 128.0 },
health: 100.into(),
max_health: 100.into(),
owner: Owner::Neutral,
diff --git a/games/rstnode/rst-core/src/data.rs b/games/rstnode/rst-core/src/data.rs
index 44d4e2a1a456..2b7a13eb6377 100644
--- a/games/rstnode/rst-core/src/data.rs
+++ b/games/rstnode/rst-core/src/data.rs
@@ -14,6 +14,12 @@ use std::{
pub type NodeId = usize;
+#[derive(Serialize, Deserialize)]
+pub struct Position {
+ pub x: f32,
+ pub y: f32,
+}
+
/// A node is a computer on the network graph
///
/// It's owned by a player, and has some upgrade state, as well as
@@ -22,6 +28,8 @@ pub type NodeId = usize;
pub struct Node {
/// Each node has a unique ID by which it's addressed
pub id: NodeId,
+ /// The position of this node on the map
+ pub pos: Position,
/// The current health
pub health: AtomicU32,
/// The max health
@@ -95,18 +103,9 @@ pub struct Player {
// 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(),
+ money: self.money.load(Ordering::Relaxed).into(),
+ ..self.clone()
}
}
}
diff --git a/games/rstnode/rst-core/src/lib.rs b/games/rstnode/rst-core/src/lib.rs
index dc1a84f63b58..bbf0e8e5933d 100644
--- a/games/rstnode/rst-core/src/lib.rs
+++ b/games/rstnode/rst-core/src/lib.rs
@@ -30,6 +30,7 @@ pub use _if::GameIf;
mod _match;
pub use _match::Match;
+pub mod loader;
pub mod config;
pub mod data;
pub mod error;
@@ -46,3 +47,8 @@ pub mod users;
pub mod wire;
pub use identity::Identity as Id;
+
+/// ConvenienceWrapper around RwLock
+pub(crate) type Lock<T> = async_std::sync::RwLock<T>;
+pub(crate) type LockMap<K, V> = async_std::sync::RwLock<std::collections::BTreeMap<K, V>>;
+pub(crate) type LockSet<T> = async_std::sync::RwLock<std::collections::BTreeSet<T>>;
diff --git a/games/rstnode/rst-core/src/loader.rs b/games/rstnode/rst-core/src/loader.rs
new file mode 100644
index 000000000000..13cb3773fbf6
--- /dev/null
+++ b/games/rstnode/rst-core/src/loader.rs
@@ -0,0 +1,82 @@
+//! An adaptation of the assets loader from rst-client, but only for
+//! maps and unit definitions
+
+use crate::config::MapCfg;
+use serde_yaml;
+use std::{
+ collections::BTreeMap,
+ fs::{self, File, OpenOptions},
+ io::{Read, Write},
+ path::PathBuf,
+};
+
+/// A unique resource identifier
+#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
+pub struct Uri(String, String);
+
+impl From<&'static str> for Uri {
+ fn from(s: &'static str) -> Self {
+ let mut v: Vec<_> = s.split("/").collect();
+ Self(v.remove(0).into(), v.remove(0).into())
+ }
+}
+
+impl From<String> for Uri {
+ fn from(s: String) -> Self {
+ let mut v: Vec<_> = s.split("/").collect();
+ Self(v.remove(0).into(), v.remove(0).into())
+ }
+}
+
+/// A loader for maps
+pub struct MapLoader {
+ root: PathBuf,
+ inner: BTreeMap<String, MapCfg>,
+}
+
+impl MapLoader {
+ pub fn load_path(path: PathBuf) -> Self {
+ Self {
+ root: path.clone(),
+ inner: fs::read_dir(&path)
+ .unwrap()
+ .filter_map(|map| {
+ let map = map.unwrap();
+ let name = map.file_name().into_string().unwrap();
+
+ if map.path().is_dir() {
+ warn!("Directories in map path will be ignored: {}!", name);
+ None
+ } else {
+ let np = map.path().with_extension("");
+ let name = np.file_name().unwrap().to_str().unwrap();
+
+ debug!("Loading map {}", name);
+ let mut c = String::new();
+ let mut f = File::open(map.path()).unwrap();
+ f.read_to_string(&mut c).unwrap();
+
+ Some((name.into(), serde_yaml::from_str(&c).unwrap()))
+ }
+ })
+ .collect(),
+ }
+ }
+
+ /// Save all maps that are present currently
+ pub fn save_all(&self) {
+ self.inner.iter().for_each(|(name, map)| {
+ let path = self.root.join(format!("{}.rstmap", name));
+ let mut f = OpenOptions::new()
+ .truncate(true)
+ .create(true)
+ .write(true)
+ .open(path.clone())
+ .unwrap();
+
+ debug!("Writing map configuration {}", path.to_str().unwrap());
+ let buf = serde_yaml::to_string(&map).unwrap();
+ f.write_all(buf.as_bytes()).unwrap();
+ });
+ }
+}
diff --git a/games/rstnode/rst-core/src/mapstore.rs b/games/rstnode/rst-core/src/mapstore.rs
index 85c5e36ef93b..eaacba34f27b 100644
--- a/games/rstnode/rst-core/src/mapstore.rs
+++ b/games/rstnode/rst-core/src/mapstore.rs
@@ -3,6 +3,7 @@
use crate::config::MapCfg;
use std::{collections::BTreeMap, fs, path::Path};
+#[deprecated]
pub struct MapStore {
configs: BTreeMap<String, MapCfg>,
}
diff --git a/games/rstnode/rst-core/src/net/endpoint.rs b/games/rstnode/rst-core/src/net/endpoint.rs
index 0c8e2f912421..63fa1185bcac 100644
--- a/games/rstnode/rst-core/src/net/endpoint.rs
+++ b/games/rstnode/rst-core/src/net/endpoint.rs
@@ -1,7 +1,7 @@
-use crate::{server::Server, Id};
+use crate::{server::Server, wire::Response, Id};
use async_std::{
net::UdpSocket,
- sync::{Arc, RwLock},
+ sync::{Arc, Receiver, RwLock},
task,
};
use std::{
@@ -12,19 +12,33 @@ use std::{
pub struct Endpoint {
running: AtomicBool,
- socket: UdpSocket,
+ socket: Arc<UdpSocket>,
bind: String,
clients: RwLock<BTreeMap<Id, Client>>,
}
pub struct Client {}
+pub struct SendHandle {
+ rx: Receiver<(SocketAddr, Response)>,
+ socket: Arc<UdpSocket>,
+}
+
+impl SendHandle {
+ async fn run(self) {
+ // Loop until
+ while let Some((peer, resp)) = self.rx.recv().await {
+
+ }
+ }
+}
+
impl Endpoint {
pub async fn new(bind: &str) -> Arc<Self> {
let socket = UdpSocket::bind(bind).await.unwrap();
Arc::new(Self {
running: true.into(),
- socket,
+ socket: Arc::new(socket),
bind: bind.into(),
clients: Default::default(),
})
@@ -35,6 +49,7 @@ impl Endpoint {
self.running.store(false, Ordering::Relaxed);
}
+ /// Start listening for incoming packets
pub async fn listen(self: &Arc<Self>, serv: Arc<Server>) {
let mut buf = vec![0; 1024];
diff --git a/games/rstnode/rst-core/src/net/handler.rs b/games/rstnode/rst-core/src/net/handler.rs
index aa0ab6a281c5..007f0c67b063 100644
--- a/games/rstnode/rst-core/src/net/handler.rs
+++ b/games/rstnode/rst-core/src/net/handler.rs
@@ -3,15 +3,24 @@ use crate::{
server::Server,
wire::{Request, Response},
};
-use async_std::sync::{Receiver, Sender};
+use async_std::sync::{Arc, Receiver, Sender};
+use std::net::SocketAddr;
+/// A handler task wrapper to execute
pub struct Handler {
- tx: Sender<Response>,
+ peer: SocketAddr,
+ tx: Sender<(SocketAddr, Response)>,
+ server: Arc<Server>,
}
impl Handler {
+ pub fn new(peer: SocketAddr, tx: Sender<(SocketAddr, Response)>, server: Arc<Server>) -> Self {
+ Self { peer, tx, server }
+ }
+
/// Start a message handler with a handle to send a reply back to the clients
- pub fn start(req: Request) {
-
+ pub async fn run(self, req: Request) {
+ let resp = crate::net::parser::request(req, self.server).await;
+ self.tx.send((self.peer, resp)).await;
}
}
diff --git a/games/rstnode/rst-core/src/net/mod.rs b/games/rstnode/rst-core/src/net/mod.rs
index f60cb3b97668..b9b0a4a3a63b 100644
--- a/games/rstnode/rst-core/src/net/mod.rs
+++ b/games/rstnode/rst-core/src/net/mod.rs
@@ -15,6 +15,6 @@ pub use parser::*;
// 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/server.rs b/games/rstnode/rst-core/src/server.rs
index 68fa2a074e34..a550a8396395 100644
--- a/games/rstnode/rst-core/src/server.rs
+++ b/games/rstnode/rst-core/src/server.rs
@@ -12,7 +12,7 @@ use crate::{
game::Action, AuthErr, Lobby, LobbyErr, LobbyId, LobbyUpdate, MatchErr, MatchId, RegErr,
Response, UpdateState, User, UserId,
},
- GameIf, Match,
+ GameIf, Lock, LockMap, Match,
};
use async_std::sync::{Arc, Mutex};
use async_trait::async_trait;
@@ -32,7 +32,7 @@ pub enum ServerErr {
/// The game's server backend
pub struct Server {
- matches: BTreeMap<MatchId, Mutex<Match>>,
+ matches: LockMap<MatchId, Lock<Match>>,
users: UserStore,
lobbies: LobbyList,
}
@@ -81,8 +81,8 @@ impl Server {
where
F: Fn(&mut Vec<Player>) -> ServerResult<Response>,
{
- match self.matches.get(&id) {
- Some(ref mut m) => cb(&mut m.lock().await.players),
+ match self.matches.read().await.get(&id) {
+ Some(ref mut m) => cb(&mut m.write().await.players),
None => Err(ServerErr::NoSuchMatch),
}
}
diff --git a/games/rstnode/rst-core/src/users.rs b/games/rstnode/rst-core/src/users.rs
index 0c93b83ec1da..ea91b3e6cb16 100644
--- a/games/rstnode/rst-core/src/users.rs
+++ b/games/rstnode/rst-core/src/users.rs
@@ -2,7 +2,7 @@
use crate::{
wire::{LobbyErr, User, UserId},
- Id,
+ Id, LockMap,
};
use async_std::sync::{Arc, RwLock};
use std::{
@@ -19,7 +19,7 @@ pub struct MetaUser {
pub struct UserStore {
max: AtomicUsize,
- users: RwLock<BTreeMap<UserId, Arc<MetaUser>>>,
+ users: LockMap<UserId, Arc<MetaUser>>,
}
impl UserStore {
diff --git a/games/rstnode/rst-server/src/loader.rs b/games/rstnode/rst-server/src/loader.rs
new file mode 100644
index 000000000000..fabc173b6ded
--- /dev/null
+++ b/games/rstnode/rst-server/src/loader.rs
@@ -0,0 +1,7 @@
+use rst_core::loader::MapLoader;
+use std::path::Path;
+
+/// Load a set of maps at launch
+pub(crate) fn load<'p, P: Into<&'p Path>>(path: P) -> MapLoader {
+ MapLoader::load_path(path.into().to_path_buf())
+}
diff --git a/games/rstnode/rst-server/src/main.rs b/games/rstnode/rst-server/src/main.rs
index fbdd33bb864d..2766f1f3c978 100644
--- a/games/rstnode/rst-server/src/main.rs
+++ b/games/rstnode/rst-server/src/main.rs
@@ -6,6 +6,7 @@
#[macro_use]
extern crate tracing;
+pub(crate) mod loader;
pub(crate) mod constants;
pub(crate) mod log;