From 814e8587205fccaea896399f3abfc8a151f1d293 Mon Sep 17 00:00:00 2001 From: Songtronix Date: Sun, 25 Aug 2019 16:49:54 +0200 Subject: [PATCH] Split Events in ServerEvent and LocalEvent --- common/src/event.rs | 40 ++++++++++++++++++++++-------------- common/src/state.rs | 27 +++++++++++++++++++++--- common/src/sys/controller.rs | 17 ++++++++------- common/src/sys/phys.rs | 6 +++--- common/src/sys/stats.rs | 6 +++--- server/src/cmd.rs | 6 +++--- server/src/lib.rs | 21 +++++++------------ 7 files changed, 75 insertions(+), 48 deletions(-) diff --git a/common/src/event.rs b/common/src/event.rs index acaac6cf48..a5ed0840fb 100644 --- a/common/src/event.rs +++ b/common/src/event.rs @@ -4,7 +4,11 @@ use specs::Entity as EcsEntity; use std::{collections::VecDeque, ops::DerefMut}; use vek::*; -pub enum Event { +pub enum LocalEvent { + Jump(EcsEntity), +} + +pub enum ServerEvent { LandOnGround { entity: EcsEntity, vel: Vec3, @@ -17,44 +21,50 @@ pub enum Event { entity: EcsEntity, cause: comp::HealthSource, }, - Jump(EcsEntity), Respawn(EcsEntity), } -#[derive(Default)] -pub struct EventBus { - queue: Mutex>, +pub struct EventBus { + queue: Mutex>, } -impl EventBus { - pub fn emitter(&self) -> Emitter { +impl Default for EventBus { + fn default() -> Self { + Self { + queue: Mutex::new(VecDeque::new()), + } + } +} + +impl EventBus { + pub fn emitter(&self) -> Emitter { Emitter { bus: self, events: VecDeque::new(), } } - pub fn emit(&self, event: Event) { + pub fn emit(&self, event: E) { self.queue.lock().push_front(event); } - pub fn recv_all(&self) -> impl ExactSizeIterator { + pub fn recv_all(&self) -> impl ExactSizeIterator { std::mem::replace(self.queue.lock().deref_mut(), VecDeque::new()).into_iter() } } -pub struct Emitter<'a> { - bus: &'a EventBus, - events: VecDeque, +pub struct Emitter<'a, E> { + bus: &'a EventBus, + events: VecDeque, } -impl<'a> Emitter<'a> { - pub fn emit(&mut self, event: Event) { +impl<'a, E> Emitter<'a, E> { + pub fn emit(&mut self, event: E) { self.events.push_front(event); } } -impl<'a> Drop for Emitter<'a> { +impl<'a, E> Drop for Emitter<'a, E> { fn drop(&mut self) { self.bus.queue.lock().append(&mut self.events); } diff --git a/common/src/state.rs b/common/src/state.rs index cb89aff217..179f6ee360 100644 --- a/common/src/state.rs +++ b/common/src/state.rs @@ -3,7 +3,7 @@ pub use sphynx::Uid; use crate::{ comp, - event::EventBus, + event::{EventBus, LocalEvent, ServerEvent}, msg::{EcsCompPacket, EcsResPacket}, sys, terrain::{Block, TerrainChunk, TerrainMap}, @@ -42,6 +42,7 @@ pub struct DeltaTime(pub f32); /// upper limit. If delta time exceeds this value, the game's physics will begin to produce time /// lag. Ideally, we'd avoid such a situation. const MAX_DELTA_TIME: f32 = 1.0; +const HUMANOID_JUMP_ACCEL: f32 = 18.0; #[derive(Default)] pub struct BlockChange { @@ -108,6 +109,7 @@ impl State { } // Create a new Sphynx ECS world. + // TODO: Split up registering into server and client (e.g. move EventBus to the server) fn setup_sphynx_world(ecs: &mut sphynx::World) { // Register server -> all clients synced components. ecs.register_synced::(); @@ -154,7 +156,8 @@ impl State { ecs.add_resource(TerrainMap::new().unwrap()); ecs.add_resource(BlockChange::default()); ecs.add_resource(TerrainChanges::default()); - ecs.add_resource(EventBus::default()); + ecs.add_resource(EventBus::::default()); + ecs.add_resource(EventBus::::default()); } /// Register a component with the state's ECS. @@ -311,8 +314,26 @@ impl State { &mut self.ecs.write_resource::().blocks, Default::default(), ); + + // Process local events + let events = self.ecs.read_resource::>().recv_all(); + for event in events { + { + let mut velocities = self.ecs.write_storage::(); + let mut force_updates = self.ecs.write_storage::(); + + match event { + LocalEvent::Jump(entity) => { + if let Some(vel) = velocities.get_mut(entity) { + vel.0.z = HUMANOID_JUMP_ACCEL; + let _ = force_updates.insert(entity, comp::ForceUpdate); + } + } + } + } + } } - + /// Clean up the state after a tick. pub fn cleanup(&mut self) { // Clean up data structures from the last tick. diff --git a/common/src/sys/controller.rs b/common/src/sys/controller.rs index 304e60c86c..79a12d7a17 100644 --- a/common/src/sys/controller.rs +++ b/common/src/sys/controller.rs @@ -3,7 +3,7 @@ use crate::{ ActionState::*, Body, CharacterState, Controller, MovementState::*, PhysicsState, Stats, Vel, }, - event::{Event, EventBus}, + event::{EventBus, ServerEvent, LocalEvent}, }; use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage}; use std::time::Duration; @@ -13,7 +13,8 @@ pub struct Sys; impl<'a> System<'a> for Sys { type SystemData = ( Entities<'a>, - Read<'a, EventBus>, + Read<'a, EventBus>, + Read<'a, EventBus>, WriteStorage<'a, Controller>, ReadStorage<'a, Stats>, ReadStorage<'a, Body>, @@ -26,7 +27,8 @@ impl<'a> System<'a> for Sys { &mut self, ( entities, - event_bus, + server_bus, + local_bus, mut controllers, stats, bodies, @@ -35,7 +37,8 @@ impl<'a> System<'a> for Sys { mut character_states, ): Self::SystemData, ) { - let mut event_emitter = event_bus.emitter(); + let mut server_emitter = server_bus.emitter(); + let mut local_emitter = local_bus.emitter(); for (entity, controller, stats, body, vel, physics, mut character) in ( &entities, @@ -51,7 +54,7 @@ impl<'a> System<'a> for Sys { if stats.is_dead { // Respawn if controller.respawn { - event_emitter.emit(Event::Respawn(entity)); + server_emitter.emit(ServerEvent::Respawn(entity)); } continue; } @@ -140,10 +143,10 @@ impl<'a> System<'a> for Sys { time_left: Duration::from_millis(600), }; } - + // Jump if controller.jump && physics.on_ground && vel.0.z <= 0.0 { - event_emitter.emit(Event::Jump(entity)); + local_emitter.emit(LocalEvent::Jump(entity)); } } } diff --git a/common/src/sys/phys.rs b/common/src/sys/phys.rs index b8bfd11cce..ad31ff7188 100644 --- a/common/src/sys/phys.rs +++ b/common/src/sys/phys.rs @@ -1,7 +1,7 @@ use { crate::{ comp::{Body, MovementState::*, Ori, PhysicsState, Pos, Scale, Stats, Vel}, - event::{Event, EventBus}, + event::{ServerEvent, EventBus}, state::DeltaTime, terrain::TerrainMap, vol::{ReadVol, Vox}, @@ -34,7 +34,7 @@ impl<'a> System<'a> for Sys { Entities<'a>, ReadExpect<'a, TerrainMap>, Read<'a, DeltaTime>, - Read<'a, EventBus>, + Read<'a, EventBus>, ReadStorage<'a, Scale>, ReadStorage<'a, Body>, WriteStorage<'a, PhysicsState>, @@ -211,7 +211,7 @@ impl<'a> System<'a> for Sys { on_ground = true; if !was_on_ground { - event_emitter.emit(Event::LandOnGround { entity, vel: vel.0 }); + event_emitter.emit(ServerEvent::LandOnGround { entity, vel: vel.0 }); } } diff --git a/common/src/sys/stats.rs b/common/src/sys/stats.rs index 1ebd322a2c..e461a1fad7 100644 --- a/common/src/sys/stats.rs +++ b/common/src/sys/stats.rs @@ -1,6 +1,6 @@ use crate::{ comp::{HealthSource, Stats}, - event::{Event, EventBus}, + event::{ServerEvent, EventBus}, state::DeltaTime, }; use log::warn; @@ -12,7 +12,7 @@ impl<'a> System<'a> for Sys { type SystemData = ( Entities<'a>, Read<'a, DeltaTime>, - Read<'a, EventBus>, + Read<'a, EventBus>, WriteStorage<'a, Stats>, ); @@ -21,7 +21,7 @@ impl<'a> System<'a> for Sys { for (entity, mut stat) in (&entities, &mut stats).join() { if stat.should_die() && !stat.is_dead { - event_emitter.emit(Event::Die { + event_emitter.emit(ServerEvent::Die { entity, cause: match stat.health.last_change { Some(change) => change.2, diff --git a/server/src/cmd.rs b/server/src/cmd.rs index e03e28bdc1..675cee77b4 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -6,7 +6,7 @@ use crate::Server; use chrono::{NaiveTime, Timelike}; use common::{ comp, - event::{Event as GameEvent, EventBus}, + event::{ServerEvent, EventBus}, msg::ServerMsg, npc::{get_npc_name, NpcKind}, state::TimeOfDay, @@ -741,8 +741,8 @@ fn handle_explosion(server: &mut Server, entity: EcsEntity, args: String, action Some(pos) => server .state .ecs() - .read_resource::() - .emit(GameEvent::Explosion { pos: pos.0, radius }), + .read_resource::>() + .emit(ServerEvent::Explosion { pos: pos.0, radius }), None => server.clients.notify( entity, ServerMsg::private(String::from("You have no position!")), diff --git a/server/src/lib.rs b/server/src/lib.rs index 8eb3cbd0e1..0eba3c5ff5 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -18,7 +18,7 @@ use crate::{ }; use common::{ comp, - event::{Event as GameEvent, EventBus}, + event::{EventBus, ServerEvent}, msg::{ClientMsg, ClientState, RequestStateError, ServerError, ServerInfo, ServerMsg}, net::PostOffice, state::{BlockChange, State, TimeOfDay, Uid}, @@ -37,7 +37,6 @@ use vek::*; use world::{ChunkSupplement, World}; const CLIENT_TIMEOUT: f64 = 20.0; // Seconds -const HUMANOID_JUMP_ACCEL: f32 = 18.0; pub enum Event { ClientConnected { @@ -88,7 +87,7 @@ impl Server { state .ecs_mut() .add_resource(SpawnPoint(Vec3::new(16_384.0, 16_384.0, 512.0))); - state.ecs_mut().add_resource(EventBus::default()); + state.ecs_mut().add_resource(EventBus::::default()); // Set starting time for the server. state.ecs_mut().write_resource::().0 = settings.start_time; @@ -218,7 +217,7 @@ impl Server { fn handle_events(&mut self) { let clients = &mut self.clients; - let events = self.state.ecs().read_resource::().recv_all(); + let events = self.state.ecs().read_resource::>().recv_all(); for event in events { let ecs = self.state.ecs_mut(); let mut todo_remove = None; @@ -231,7 +230,7 @@ impl Server { let mut force_updates = ecs.write_storage::(); match event { - GameEvent::LandOnGround { entity, vel } => { + ServerEvent::LandOnGround { entity, vel } => { if let Some(stats) = stats.get_mut(entity) { let falldmg = (vel.z / 1.5 + 10.0) as i32; if falldmg < 0 { @@ -239,7 +238,7 @@ impl Server { } } } - GameEvent::Explosion { pos, radius } => { + ServerEvent::Explosion { pos, radius } => { const RAYS: usize = 500; for _ in 0..RAYS { @@ -257,13 +256,7 @@ impl Server { .cast(); } } - GameEvent::Jump(entity) => { - if let Some(vel) = velocities.get_mut(entity) { - vel.0.z = HUMANOID_JUMP_ACCEL; - let _ = force_updates.insert(entity, comp::ForceUpdate); - } - } - GameEvent::Die { entity, cause } => { + ServerEvent::Die { entity, cause } => { // Chat message if let Some(player) = ecs.read_storage::().get(entity) { let msg = if let comp::HealthSource::Attack { by } = cause { @@ -308,7 +301,7 @@ impl Server { todo_remove = Some(entity.clone()); } } - GameEvent::Respawn(entity) => { + ServerEvent::Respawn(entity) => { // Only clients can respawn if let Some(client) = clients.get_mut(&entity) { client.allow_state(ClientState::Character);