aboutsummaryrefslogtreecommitdiff
path: root/games
diff options
context:
space:
mode:
authorKatharina Fey <kookie@spacekookie.de>2021-02-26 23:08:23 +0100
committerKatharina Fey <kookie@spacekookie.de>2021-02-26 23:08:23 +0100
commit3bfc345e559dbbb7d2d58db03dd2c1f1b58f9759 (patch)
tree3488666e8d1bfe098e4bf470c6a4cc9cb04f325d /games
parentc6e4921512f576b06c411823c5d88e0dca5b556d (diff)
rstnode: basic event loop usage (prototype)
Diffstat (limited to 'games')
-rw-r--r--games/rstnode/Cargo.lock1
-rw-r--r--games/rstnode/rst-client/src/cli.rs2
-rw-r--r--games/rstnode/rst-client/src/editor/mod.rs28
-rw-r--r--games/rstnode/rst-client/src/event.rs101
-rw-r--r--games/rstnode/rst-client/src/main.rs38
-rw-r--r--games/rstnode/rst-client/src/ui/button.rs20
-rw-r--r--games/rstnode/rst-core/src/lib.rs3
-rw-r--r--games/rstnode/rst-core/src/loader.rs46
-rw-r--r--games/rstnode/rst-core/src/mapstore.rs18
-rw-r--r--games/rstnode/rst-server/Cargo.toml1
-rw-r--r--games/rstnode/rst-server/src/main.rs8
11 files changed, 174 insertions, 92 deletions
diff --git a/games/rstnode/Cargo.lock b/games/rstnode/Cargo.lock
index 33713c4b0971..a222eccc771e 100644
--- a/games/rstnode/Cargo.lock
+++ b/games/rstnode/Cargo.lock
@@ -3878,6 +3878,7 @@ dependencies = [
"async-std",
"async-trait",
"chrono",
+ "clap",
"num_cpus",
"rst-core",
"systemstat",
diff --git a/games/rstnode/rst-client/src/cli.rs b/games/rstnode/rst-client/src/cli.rs
index dcc40b76726b..72d598962b8e 100644
--- a/games/rstnode/rst-client/src/cli.rs
+++ b/games/rstnode/rst-client/src/cli.rs
@@ -21,8 +21,8 @@ pub fn parse(settings: &mut GameSettings) {
)
.arg(
Arg::with_name("assets")
- .required(true)
.takes_value(true)
+ .default_value("./assets/raw")
.help("Specify the path to load assets from"),
)
.arg(
diff --git a/games/rstnode/rst-client/src/editor/mod.rs b/games/rstnode/rst-client/src/editor/mod.rs
index 969ac27088ae..6f5f0c67b3a1 100644
--- a/games/rstnode/rst-client/src/editor/mod.rs
+++ b/games/rstnode/rst-client/src/editor/mod.rs
@@ -1,4 +1,6 @@
-use crate::{assets::Assets, input::InputArbiter, ui::Button, viewport::Viewport, GameSettings};
+use crate::{
+ assets::Assets, input::InputArbiter, ui::Button, viewport::Viewport, EventId, GameSettings,
+};
use ggez::{
event::{EventHandler, MouseButton},
graphics::{self, Color},
@@ -10,12 +12,14 @@ pub struct EditorState {
settings: GameSettings,
input: InputArbiter,
vp: Viewport,
- btn: Button,
+ btn: EventId,
+ btn2: EventId,
}
impl EditorState {
pub fn new(settings: GameSettings, assets: Assets) -> Self {
info!("Initialising map editor state");
+
Self {
assets,
settings,
@@ -26,7 +30,15 @@ impl EditorState {
(250.0, 125.0).into(),
Some("Create Node".into()),
Color::from_rgb(50, 50, 50),
- ),
+ )
+ .register(),
+ btn2: Button::new(
+ (300.0, 25.0).into(),
+ (250.0, 125.0).into(),
+ Some("Destroy Node".into()),
+ Color::from_rgb(50, 50, 50),
+ )
+ .register(),
}
}
}
@@ -36,15 +48,7 @@ impl EventHandler for EditorState {
Ok(())
}
- fn mouse_button_down_event(&mut self, ctx: &mut Context, btn: MouseButton, x: f32, y: f32) {
- self.btn.mouse_button_down_event(ctx, btn, x, y)
- }
-
fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
- graphics::clear(ctx, graphics::Color::from_rgb(15, 15, 15));
-
- self.btn.draw(ctx)?;
-
- graphics::present(ctx)
+ Ok(())
}
}
diff --git a/games/rstnode/rst-client/src/event.rs b/games/rstnode/rst-client/src/event.rs
index 54388bb8c438..88a85ed0fce2 100644
--- a/games/rstnode/rst-client/src/event.rs
+++ b/games/rstnode/rst-client/src/event.rs
@@ -1,17 +1,73 @@
use ggez::{
event::{EventHandler, KeyCode, KeyMods, MouseButton},
- Context, GameResult,
+ graphics, Context, GameResult,
};
+use std::collections::BTreeMap;
+use std::sync::{
+ atomic::{AtomicUsize, Ordering},
+ mpsc::{channel, Receiver, Sender},
+};
+
+static ID_CTR: AtomicUsize = AtomicUsize::new(0);
+
+static mut tx: Option<Sender<HandlerDiff>> = None;
+static mut rx: Option<Receiver<HandlerDiff>> = None;
+
+#[inline(always)]
+pub fn get_tx() -> Sender<HandlerDiff> {
+ unsafe { tx.as_ref() }.expect("Call event::setup() first!").clone()
+}
+
+/// Must absolutely call this function before using the event system!
+pub fn setup() {
+ let (tx_, rx_) = channel();
+ unsafe { tx = Some(tx_) };
+ unsafe { rx = Some(rx_) };
+}
-pub struct EventLayer<L: EventHandler> {
- layers: Vec<Box<dyn EventHandler>>,
+pub type EventId = usize;
+
+pub fn new_id() -> EventId {
+ ID_CTR.fetch_add(1, Ordering::Relaxed)
+}
+
+pub type BoxedHandler = Box<dyn EventHandler + 'static>;
+
+pub enum HandlerDiff {
+ Add { id: usize, inner: BoxedHandler },
+ Remove(usize),
+}
+
+impl HandlerDiff {
+ pub fn add(inner: impl EventHandler + 'static) -> (usize, Self) {
+ let id = new_id();
+ (
+ id,
+ Self::Add {
+ id,
+ inner: Box::new(inner),
+ },
+ )
+ }
+
+ pub fn remove(id: usize) -> Self {
+ Self::Remove(id)
+ }
+}
+
+pub struct EventLayer<L> {
+ layers: BTreeMap<usize, BoxedHandler>,
+ layer_rx: Receiver<HandlerDiff>,
render: L,
}
impl<L: EventHandler> EventLayer<L> {
pub fn new(render: L) -> Self {
+ let layer_rx = unsafe { rx.take().expect("Call event::setup() first!") };
+
Self {
- layers: vec![],
+ layers: BTreeMap::new(),
+ layer_rx,
render,
}
}
@@ -19,38 +75,59 @@ impl<L: EventHandler> EventLayer<L> {
impl<L: EventHandler> EventHandler for EventLayer<L> {
fn update(&mut self, ctx: &mut Context) -> GameResult<()> {
+ // Add all new layers to the update stack
+ while let Ok(l) = self.layer_rx.try_recv() {
+ match l {
+ HandlerDiff::Add { id, inner } => {
+ self.layers.insert(id, inner);
+ }
+ HandlerDiff::Remove(ref id) => {
+ self.layers.remove(id);
+ }
+ }
+ }
+
+ // Then update all the layers
self.layers
.iter_mut()
- .map(|l| l.update(ctx))
+ .map(|(_, l)| l.update(ctx))
.collect::<GameResult<Vec<()>>>()?;
+ // Update the renderer last
self.render.update(ctx)?;
Ok(())
}
fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
+ graphics::clear(ctx, graphics::Color::from_rgb(15, 15, 15));
self.render.draw(ctx)?;
- Ok(())
+
+ self.layers
+ .iter_mut()
+ .map(|(_, l)| l.draw(ctx))
+ .collect::<Vec<_>>();
+
+ graphics::present(ctx)
}
fn mouse_button_down_event(&mut self, ctx: &mut Context, button: MouseButton, x: f32, y: f32) {
self.layers
.iter_mut()
- .map(|l| l.mouse_button_down_event(ctx, button, x, y))
+ .map(|(_, l)| l.mouse_button_down_event(ctx, button, x, y))
.collect::<Vec<_>>();
}
fn mouse_button_up_event(&mut self, ctx: &mut Context, button: MouseButton, x: f32, y: f32) {
self.layers
.iter_mut()
- .map(|l| l.mouse_button_up_event(ctx, button, x, y))
+ .map(|(_, l)| l.mouse_button_up_event(ctx, button, x, y))
.collect::<Vec<_>>();
}
fn mouse_motion_event(&mut self, ctx: &mut Context, x: f32, y: f32, dx: f32, dy: f32) {
self.layers
.iter_mut()
- .map(|l| l.mouse_motion_event(ctx, x, y, dx, dy))
+ .map(|(_, l)| l.mouse_motion_event(ctx, x, y, dx, dy))
.collect::<Vec<_>>();
}
@@ -69,7 +146,7 @@ impl<L: EventHandler> EventHandler for EventLayer<L> {
) {
self.layers
.iter_mut()
- .map(|l| l.key_down_event(ctx, keycode, keymods, repeat))
+ .map(|(_, l)| l.key_down_event(ctx, keycode, keymods, repeat))
.collect::<Vec<_>>();
}
@@ -77,7 +154,7 @@ impl<L: EventHandler> EventHandler for EventLayer<L> {
fn key_up_event(&mut self, ctx: &mut Context, keycode: KeyCode, keymods: KeyMods) {
self.layers
.iter_mut()
- .map(|l| l.key_up_event(ctx, keycode, keymods))
+ .map(|(_, l)| l.key_up_event(ctx, keycode, keymods))
.collect::<Vec<_>>();
}
@@ -86,7 +163,7 @@ impl<L: EventHandler> EventHandler for EventLayer<L> {
fn text_input_event(&mut self, ctx: &mut Context, character: char) {
self.layers
.iter_mut()
- .map(|l| l.text_input_event(ctx, character))
+ .map(|(_, l)| l.text_input_event(ctx, character))
.collect::<Vec<_>>();
}
}
diff --git a/games/rstnode/rst-client/src/main.rs b/games/rstnode/rst-client/src/main.rs
index b0acb22e26d2..3dd93012f47e 100644
--- a/games/rstnode/rst-client/src/main.rs
+++ b/games/rstnode/rst-client/src/main.rs
@@ -23,9 +23,9 @@ mod ui;
mod viewport;
mod window;
+use crate::{assets::Assets, window::Window};
pub(crate) use editor::*;
pub(crate) use event::*;
-#[allow(unused)]
pub(crate) use settings::{GameSettings, GraphicsSettings, WindowSettings};
pub(crate) use state::*;
@@ -41,28 +41,30 @@ async fn main() {
log::initialise();
// Initialise window context
- let mut window = window::create(&settings);
+ let mut win = window::create(&settings);
// Load assets tree
- let assets =
- assets::load_tree(window.ctx(), &settings).unwrap_or_else(|e| fatal!("LoadError: {}!", e));
+ let assets = assets::load_tree(win.ctx(), &settings)
+ .unwrap_or_else(|e| fatal!("Asset tree failed to load: {}!", e));
- // Either create client state or editor state
- if settings.editor {
- let state = EditorState::new(settings, assets);
+ // Event system setup
+ event::setup();
- // Initialise the viewport first!
- // state.viewport().init(window.ctx());
+ match settings.editor {
+ true => run_editor(win, settings, assets),
+ false => run_game(win, settings, assets),
+ }
+}
- // Window goes brrrr
- window.run(state)
- } else {
- let mut state = ClientState::new(settings, assets);
+fn run_editor(win: Window, settings: GameSettings, assets: Assets) {
+ let state = EventLayer::new(EditorState::new(settings, assets));
+ win.run(state);
+}
- // Initialise the viewport first!
- state.viewport().init(window.ctx());
+fn run_game(mut win: Window, settings: GameSettings, assets: Assets) {
+ let mut state = ClientState::new(settings, assets);
+ state.viewport().init(win.ctx());
- // Window goes brrrr
- window.run(state)
- }
+ let mut layer = EventLayer::new(state);
+ win.run(layer)
}
diff --git a/games/rstnode/rst-client/src/ui/button.rs b/games/rstnode/rst-client/src/ui/button.rs
index 9d51b0271cbc..c39f905360d6 100644
--- a/games/rstnode/rst-client/src/ui/button.rs
+++ b/games/rstnode/rst-client/src/ui/button.rs
@@ -1,4 +1,4 @@
-use crate::color::ColorUtils;
+use crate::{color::ColorUtils, get_tx, EventId, HandlerDiff};
use ggez::graphics::{self, Align, Color, DrawMode, DrawParam, Drawable, MeshBuilder, Rect, Text};
use ggez::{
event::{EventHandler, MouseButton},
@@ -38,13 +38,16 @@ impl Button {
}
/// Register an on-click listening closure
- pub fn on_click<C: FnMut() -> () + 'static>(&mut self, btn: MouseButton, cb: C) {
+ pub fn on_click<C: FnMut() -> () + 'static>(mut self, btn: MouseButton, cb: C) -> Self {
self.cbs.insert(btn, Box::new(cb));
+ self
}
- /// Create a button with text which auto-infers its required size
- pub fn auto(pos: Pos, text: String, color: impl Into<Color>) -> Self {
- todo!()
+ /// Register the button with the event handler
+ pub fn register(self) -> EventId {
+ let (btn_id, diff) = HandlerDiff::add(self);
+ get_tx().send(diff).unwrap();
+ btn_id
}
fn boundry_check(&self, x: f32, y: f32) -> bool {
@@ -70,6 +73,13 @@ impl EventHandler for Button {
}
}
+ fn mouse_button_up_event(&mut self, _ctx: &mut Context, btn: MouseButton, x: f32, y: f32) {
+ if self.boundry_check(x, y) {
+ trace!("Releasing button state");
+ std::mem::swap(&mut self.color_base, &mut self.color_trim);
+ }
+ }
+
fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
let mut mb = MeshBuilder::new();
let bounds = Rect {
diff --git a/games/rstnode/rst-core/src/lib.rs b/games/rstnode/rst-core/src/lib.rs
index bbf0e8e5933d..6e35d1937869 100644
--- a/games/rstnode/rst-core/src/lib.rs
+++ b/games/rstnode/rst-core/src/lib.rs
@@ -30,16 +30,15 @@ pub use _if::GameIf;
mod _match;
pub use _match::Match;
-pub mod loader;
pub mod config;
pub mod data;
pub mod error;
pub mod gens;
pub mod io;
+pub mod loader;
pub mod lobby;
pub mod mailbox;
pub mod map;
-pub mod mapstore;
pub mod net;
pub mod server;
pub mod stats;
diff --git a/games/rstnode/rst-core/src/loader.rs b/games/rstnode/rst-core/src/loader.rs
index 13cb3773fbf6..4bfbccfff652 100644
--- a/games/rstnode/rst-core/src/loader.rs
+++ b/games/rstnode/rst-core/src/loader.rs
@@ -36,31 +36,33 @@ pub struct MapLoader {
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();
+ info!("Loading map path: {}", path.to_str().unwrap());
+ let root = path.clone();
+ let 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();
+ 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();
+ 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(),
- }
+ Some((name.into(), serde_yaml::from_str(&c).unwrap()))
+ }
+ })
+ .collect();
+
+ info!("Loading complete!");
+ Self { root, inner }
}
/// Save all maps that are present currently
diff --git a/games/rstnode/rst-core/src/mapstore.rs b/games/rstnode/rst-core/src/mapstore.rs
deleted file mode 100644
index eaacba34f27b..000000000000
--- a/games/rstnode/rst-core/src/mapstore.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-//! Map store
-
-use crate::config::MapCfg;
-use std::{collections::BTreeMap, fs, path::Path};
-
-#[deprecated]
-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/games/rstnode/rst-server/Cargo.toml b/games/rstnode/rst-server/Cargo.toml
index 8903e637fc3f..b6822fff019d 100644
--- a/games/rstnode/rst-server/Cargo.toml
+++ b/games/rstnode/rst-server/Cargo.toml
@@ -11,6 +11,7 @@ rst-core = { path = "../rst-core" }
async-std = { version = "1.0", features = ["unstable", "attributes"] }
async-trait = "0.1"
+clap = "2.0"
chrono = { version = "0.4", features = ["serde"] }
tracing = "0.1"
tracing-subscriber = "0.2"
diff --git a/games/rstnode/rst-server/src/main.rs b/games/rstnode/rst-server/src/main.rs
index 2766f1f3c978..593c12dc7f7a 100644
--- a/games/rstnode/rst-server/src/main.rs
+++ b/games/rstnode/rst-server/src/main.rs
@@ -6,16 +6,20 @@
#[macro_use]
extern crate tracing;
-pub(crate) mod loader;
+pub(crate) mod cli;
pub(crate) mod constants;
+pub(crate) mod loader;
pub(crate) mod log;
-use rst_core::net::Endpoint;
+use rst_core::{loader::MapLoader, net::Endpoint};
#[async_std::main]
async fn main() {
log::initialise();
+ let map_path = cli::parse();
+ let maps = MapLoader::load_path(map_path);
+
let addr = format!("{}:{}", constants::DEFAULT_BIND, constants::DEFAULT_PORT);
let serv = Endpoint::new(addr.as_str()).await;
// serv.listen().await;