aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKatharina Fey <kookie@spacekookie.de>2020-03-22 19:44:26 +0100
committerKatharina Fey <kookie@spacekookie.de>2020-03-22 19:44:26 +0100
commit22c18205bcb3702ddf60f41f77f6f06554202f35 (patch)
tree5f402722bbd767354e040179f0b4cd5ccb6b3899
parenta55c5bded047e1e2c54f6e3f25c9b8e36e605110 (diff)
Updating gameplay starting mechanics, adding quadtree to map
-rw-r--r--Cargo.lock110
-rw-r--r--Cargo.toml8
-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
17 files changed, 476 insertions, 122 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e770659226e5..13da0bddb9b1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -536,6 +536,38 @@ dependencies = [
]
[[package]]
+name = "darling"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "darling_core 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "darling_macro 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "darling_core"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "darling_core 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "deflate"
version = "0.7.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -545,6 +577,29 @@ dependencies = [
]
[[package]]
+name = "derive_builder"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "darling 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "derive_builder_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "derive_builder_core"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "darling 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "digest"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1090,6 +1145,11 @@ version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "ident_case"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "image"
version = "0.22.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1476,6 +1536,29 @@ dependencies = [
]
[[package]]
+name = "num"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-bigint 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-complex 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-iter 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-rational 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-bigint"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "num-complex"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1519,6 +1602,7 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-bigint 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1716,6 +1800,15 @@ dependencies = [
]
[[package]]
+name = "quadtree_rs"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "derive_builder 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "quote"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2010,10 +2103,12 @@ dependencies = [
"chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"ggez 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"netmod-mem 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quadtree_rs 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ratman 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ratman-identity 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -2296,6 +2391,11 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "strsim"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "subtle"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2696,7 +2796,12 @@ dependencies = [
"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac"
"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4"
"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5"
+"checksum darling 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fcfbcb0c5961907597a7d1148e3af036268f2b773886b8bb3eeb1e1281d3d3d6"
+"checksum darling_core 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6afc018370c3bff3eb51f89256a6bdb18b4fdcda72d577982a14954a7a0b402c"
+"checksum darling_macro 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6d8dac1c6f1d29a41c4712b4400f878cb4fcc4c7628f298dd75038e024998d1"
"checksum deflate 0.7.20 (registry+https://github.com/rust-lang/crates.io-index)" = "707b6a7b384888a70c8d2e8650b3e60170dfc6a67bb4aa67b6dfca57af4bedb4"
+"checksum derive_builder 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ac53fa6a3cda160df823a9346442525dcaf1e171999a1cf23e67067e4fd64d4"
+"checksum derive_builder_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0288a23da9333c246bb18c143426074a6ae96747995c5819d2947b64cd942b37"
"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
"checksum directories 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "551a778172a450d7fc12e629ca3b0428d00f6afa9a43da1b630d54604e97371c"
"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b"
@@ -2757,6 +2862,7 @@ dependencies = [
"checksum hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772"
"checksum hex 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76cdda6bf525062a0c9e8f14ee2b37935c86b8efb6c8b69b3c83dfb518a914af"
"checksum hound 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a164bb2ceaeff4f42542bdb847c41517c78a60f5649671b2a07312b6e117549"
+"checksum ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
"checksum image 0.22.5 (registry+https://github.com/rust-lang/crates.io-index)" = "08ed2ada878397b045454ac7cfb011d73132c59f31a955d230bd1f1c2e68eb4a"
"checksum inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff"
"checksum io-kit-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f21dcc74995dd4cd090b147e79789f8d65959cbfb5f0b118002db869ea3bd0a0"
@@ -2802,6 +2908,8 @@ dependencies = [
"checksum nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3b2e0b4f3320ed72aaedb9a5ac838690a8047c7b275da22711fddff4f8a14229"
"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
+"checksum num 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36"
+"checksum num-bigint 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
"checksum num-complex 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95"
"checksum num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "eafd0b45c5537c3ba526f79d3e75120036502bebacbb3f3220914067ce39dbf2"
"checksum num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
@@ -2833,6 +2941,7 @@ dependencies = [
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
"checksum proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548"
"checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15"
+"checksum quadtree_rs 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6ec1506903c0f5cff273bd34df6646c7040f2a7c5b0a92a9179d89551bed9ffd"
"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
@@ -2895,6 +3004,7 @@ dependencies = [
"checksum stdweb-derive 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
"checksum stdweb-internal-macros 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
"checksum stdweb-internal-runtime 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
+"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee"
"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
"checksum syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5"
diff --git a/Cargo.toml b/Cargo.toml
index 8e9c96152b5a..c62fd1354e38 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,15 +1,14 @@
-# cargo-features = ["profile-overrides"]
-
[package]
name = "rstnode"
description = "A game about capturing computers on a network"
version = "0.0.0"
edition = "2018"
-license = "GPL-3.0-or-later"
-authors = ["Katharina Fey <kookie@spacekookie.de>"]
+license = "AGPL-3.0-or-later"
+authors = ["Bread Machine", "Katharina Fey <kookie@spacekookie.de>"]
[dependencies]
serde = { version = "1.0", features = ["derive", "rc"] }
+serde_json = "1.0"
async-std = { version = "1.0", features = ["unstable"] }
async-trait = "0.1"
@@ -21,6 +20,7 @@ ggez = "0.5"
cgmath = { version = "*", features = ["mint"] }
chrono = { version = "0.4", features = ["serde"] }
rand = "0.7"
+quadtree_rs = "0.1"
# [profile.release.overrides."*"]
# opt-level = 3 \ No newline at end of file
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>),
}