mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Switched to EventBus system
This commit is contained in:
parent
98a913195b
commit
192f5d355f
@ -1,30 +0,0 @@
|
||||
use specs::Component;
|
||||
use specs_idvs::IDVStorage;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use vek::*;
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Events(pub Vec<EntityEvent>);
|
||||
|
||||
impl Deref for Events {
|
||||
type Target = Vec<EntityEvent>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Events {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Events {
|
||||
type Storage = IDVStorage<Self>;
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum EntityEvent {
|
||||
HitGround { vel: Vec3<f32> },
|
||||
}
|
@ -3,7 +3,6 @@ mod agent;
|
||||
mod animation;
|
||||
mod body;
|
||||
mod controller;
|
||||
mod event;
|
||||
mod inputs;
|
||||
mod inventory;
|
||||
mod last;
|
||||
@ -18,7 +17,6 @@ pub use agent::Agent;
|
||||
pub use animation::{Animation, AnimationInfo};
|
||||
pub use body::{humanoid, object, quadruped, quadruped_medium, Body};
|
||||
pub use controller::Controller;
|
||||
pub use event::{EntityEvent, Events};
|
||||
pub use inputs::{
|
||||
Attacking, CanBuild, Gliding, Jumping, MoveDir, OnGround, Respawning, Rolling, Wielding,
|
||||
};
|
||||
|
42
common/src/event.rs
Normal file
42
common/src/event.rs
Normal file
@ -0,0 +1,42 @@
|
||||
use specs::Entity as EcsEntity;
|
||||
use std::{collections::VecDeque, ops::DerefMut, sync::Mutex};
|
||||
use vek::*;
|
||||
|
||||
pub enum Event {
|
||||
LandOnGround { entity: EcsEntity, vel: Vec3<f32> },
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct EventBus {
|
||||
queue: Mutex<VecDeque<Event>>,
|
||||
}
|
||||
|
||||
impl EventBus {
|
||||
pub fn emitter(&self) -> Emitter {
|
||||
Emitter {
|
||||
bus: self,
|
||||
events: VecDeque::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn recv_all(&self) -> impl ExactSizeIterator<Item = Event> {
|
||||
std::mem::replace(self.queue.lock().unwrap().deref_mut(), VecDeque::new()).into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Emitter<'a> {
|
||||
bus: &'a EventBus,
|
||||
events: VecDeque<Event>,
|
||||
}
|
||||
|
||||
impl<'a> Emitter<'a> {
|
||||
pub fn emit(&mut self, event: Event) {
|
||||
self.events.push_front(event);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for Emitter<'a> {
|
||||
fn drop(&mut self) {
|
||||
self.bus.queue.lock().unwrap().append(&mut self.events);
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ extern crate log;
|
||||
pub mod assets;
|
||||
pub mod clock;
|
||||
pub mod comp;
|
||||
pub mod event;
|
||||
pub mod figure;
|
||||
pub mod msg;
|
||||
pub mod npc;
|
||||
|
@ -3,6 +3,7 @@ pub use sphynx::Uid;
|
||||
|
||||
use crate::{
|
||||
comp,
|
||||
event::EventBus,
|
||||
msg::{EcsCompPacket, EcsResPacket},
|
||||
sys,
|
||||
terrain::{Block, TerrainChunk, TerrainMap},
|
||||
@ -42,18 +43,11 @@ pub struct DeltaTime(pub f32);
|
||||
/// lag. Ideally, we'd avoid such a situation.
|
||||
const MAX_DELTA_TIME: f32 = 1.0;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct BlockChange {
|
||||
blocks: FxHashMap<Vec3<i32>, Block>,
|
||||
}
|
||||
|
||||
impl Default for BlockChange {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
blocks: FxHashMap::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockChange {
|
||||
pub fn set(&mut self, pos: Vec3<i32>, block: Block) {
|
||||
self.blocks.insert(pos, block);
|
||||
@ -64,6 +58,7 @@ impl BlockChange {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct TerrainChanges {
|
||||
pub new_chunks: FxHashSet<Vec2<i32>>,
|
||||
pub modified_chunks: FxHashSet<Vec2<i32>>,
|
||||
@ -71,17 +66,6 @@ pub struct TerrainChanges {
|
||||
pub modified_blocks: FxHashMap<Vec3<i32>, Block>,
|
||||
}
|
||||
|
||||
impl Default for TerrainChanges {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
new_chunks: FxHashSet::default(),
|
||||
modified_chunks: FxHashSet::default(),
|
||||
removed_chunks: FxHashSet::default(),
|
||||
modified_blocks: FxHashMap::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TerrainChanges {
|
||||
pub fn clear(&mut self) {
|
||||
self.new_chunks.clear();
|
||||
@ -161,7 +145,6 @@ impl State {
|
||||
ecs.register::<comp::ForceUpdate>();
|
||||
ecs.register::<comp::InventoryUpdate>();
|
||||
ecs.register::<comp::Inventory>();
|
||||
ecs.register::<comp::Events>();
|
||||
// Controller effects
|
||||
ecs.register::<comp::MoveDir>();
|
||||
ecs.register::<comp::OnGround>();
|
||||
@ -179,6 +162,7 @@ impl State {
|
||||
ecs.add_resource(TerrainMap::new().unwrap());
|
||||
ecs.add_resource(BlockChange::default());
|
||||
ecs.add_resource(TerrainChanges::default());
|
||||
ecs.add_resource(EventBus::default());
|
||||
}
|
||||
|
||||
/// Register a component with the state's ECS.
|
||||
|
@ -1,33 +0,0 @@
|
||||
use crate::{
|
||||
comp::{EntityEvent, Events, HealthSource, Stats},
|
||||
state::DeltaTime,
|
||||
};
|
||||
use log::warn;
|
||||
use specs::{Entities, Join, Read, System, WriteStorage};
|
||||
|
||||
/// This system kills players
|
||||
pub struct Sys;
|
||||
impl<'a> System<'a> for Sys {
|
||||
type SystemData = (
|
||||
Entities<'a>,
|
||||
WriteStorage<'a, Events>,
|
||||
WriteStorage<'a, Stats>,
|
||||
);
|
||||
|
||||
fn run(&mut self, (entities, mut events, mut stats): Self::SystemData) {
|
||||
for (entity, mut events) in (&entities, &mut events).join() {
|
||||
for event in events.drain(..) {
|
||||
match event {
|
||||
EntityEvent::HitGround { vel } => {
|
||||
if let Some(stat) = stats.get_mut(entity) {
|
||||
let falldmg = (vel.z / 1.5 + 6.0) as i32;
|
||||
if falldmg < 0 {
|
||||
stat.health.change_by(falldmg, HealthSource::World);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -3,7 +3,6 @@ pub mod agent;
|
||||
pub mod animation;
|
||||
pub mod combat;
|
||||
pub mod controller;
|
||||
mod event_handler;
|
||||
pub mod movement;
|
||||
pub mod phys;
|
||||
mod stats;
|
||||
@ -20,7 +19,6 @@ const MOVEMENT_SYS: &str = "movement_sys";
|
||||
const COMBAT_SYS: &str = "combat_sys";
|
||||
const ANIMATION_SYS: &str = "animation_sys";
|
||||
const STATS_SYS: &str = "stats_sys";
|
||||
const EVENT_HANDLER_SYS: &str = "event_handler_sys";
|
||||
|
||||
pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) {
|
||||
dispatch_builder.add(agent::Sys, AGENT_SYS, &[]);
|
||||
@ -35,9 +33,4 @@ pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) {
|
||||
dispatch_builder.add(combat::Sys, COMBAT_SYS, &[ACTION_STATE_SYS]);
|
||||
dispatch_builder.add(animation::Sys, ANIMATION_SYS, &[ACTION_STATE_SYS]);
|
||||
dispatch_builder.add(stats::Sys, STATS_SYS, &[COMBAT_SYS]);
|
||||
dispatch_builder.add(
|
||||
event_handler::Sys,
|
||||
EVENT_HANDLER_SYS,
|
||||
&[AGENT_SYS, PHYS_SYS, ACTION_STATE_SYS, COMBAT_SYS],
|
||||
);
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
use crate::{
|
||||
comp::HealthSource,
|
||||
comp::{
|
||||
ActionState, Body, EntityEvent, Events, Jumping, MoveDir, OnGround, Ori, Pos, Rolling,
|
||||
Scale, Stats, Vel, Wielding,
|
||||
ActionState, Body, Jumping, MoveDir, OnGround, Ori, Pos, Rolling, Scale, Stats, Vel,
|
||||
Wielding,
|
||||
},
|
||||
event::{Event, EventBus},
|
||||
state::DeltaTime,
|
||||
terrain::TerrainMap,
|
||||
vol::{ReadVol, Vox},
|
||||
@ -35,6 +36,7 @@ impl<'a> System<'a> for Sys {
|
||||
Entities<'a>,
|
||||
ReadExpect<'a, TerrainMap>,
|
||||
Read<'a, DeltaTime>,
|
||||
Read<'a, EventBus>,
|
||||
ReadStorage<'a, ActionState>,
|
||||
ReadStorage<'a, Scale>,
|
||||
ReadStorage<'a, Body>,
|
||||
@ -42,7 +44,6 @@ impl<'a> System<'a> for Sys {
|
||||
WriteStorage<'a, Pos>,
|
||||
WriteStorage<'a, Vel>,
|
||||
WriteStorage<'a, Ori>,
|
||||
WriteStorage<'a, Events>,
|
||||
);
|
||||
|
||||
fn run(
|
||||
@ -51,6 +52,7 @@ impl<'a> System<'a> for Sys {
|
||||
entities,
|
||||
terrain,
|
||||
dt,
|
||||
event_bus,
|
||||
action_states,
|
||||
scales,
|
||||
bodies,
|
||||
@ -58,9 +60,10 @@ impl<'a> System<'a> for Sys {
|
||||
mut positions,
|
||||
mut velocities,
|
||||
mut orientations,
|
||||
mut events,
|
||||
): Self::SystemData,
|
||||
) {
|
||||
let mut event_emitter = event_bus.emitter();
|
||||
|
||||
// Apply movement inputs
|
||||
for (entity, a, scale, b, mut pos, mut vel, mut ori) in (
|
||||
&entities,
|
||||
@ -211,15 +214,8 @@ impl<'a> System<'a> for Sys {
|
||||
if resolve_dir.z > 0.0 && vel.0.z <= 0.0 {
|
||||
on_ground = true;
|
||||
|
||||
// Hitting the ground
|
||||
const COLLISION_VEL: f32 = GRAVITY * 0.75; // Falling for 0.75 seconds
|
||||
if vel.0.z < -COLLISION_VEL {
|
||||
if events.get(entity).is_none() {
|
||||
events.insert(entity, Events::default());
|
||||
}
|
||||
events
|
||||
.get_mut(entity) // TODO: Use get_mut_or_default when updating to SPECS 15
|
||||
.map(|e| e.push(EntityEvent::HitGround { vel: vel.0 }));
|
||||
if !was_on_ground {
|
||||
event_emitter.emit(Event::LandOnGround { entity, vel: vel.0 });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@ use crate::{
|
||||
};
|
||||
use common::{
|
||||
comp,
|
||||
event::{Event as GameEvent, EventBus},
|
||||
msg::{ClientMsg, ClientState, RequestStateError, ServerError, ServerInfo, ServerMsg},
|
||||
net::PostOffice,
|
||||
state::{State, TimeOfDay, Uid},
|
||||
@ -84,6 +85,7 @@ impl Server {
|
||||
state
|
||||
.ecs_mut()
|
||||
.add_resource(SpawnPoint(Vec3::new(16_384.0, 16_384.0, 380.0)));
|
||||
state.ecs_mut().add_resource(EventBus::default());
|
||||
|
||||
// Set starting time for the server.
|
||||
state.ecs_mut().write_resource::<TimeOfDay>().0 = settings.start_time;
|
||||
@ -199,6 +201,24 @@ impl Server {
|
||||
client.allow_state(ClientState::Character);
|
||||
}
|
||||
|
||||
/// Handle events coming through via the event bus
|
||||
fn handle_events(&mut self) {
|
||||
let mut stats = self.state.ecs().write_storage::<comp::Stats>();
|
||||
|
||||
for event in self.state.ecs().read_resource::<EventBus>().recv_all() {
|
||||
match event {
|
||||
GameEvent::LandOnGround { entity, vel } => {
|
||||
if let Some(stats) = stats.get_mut(entity) {
|
||||
let falldmg = (vel.z / 1.5 + 10.0) as i32;
|
||||
if falldmg < 0 {
|
||||
stats.health.change_by(falldmg, comp::HealthSource::World);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Execute a single server tick, handle input and update the game state by the given duration.
|
||||
pub fn tick(&mut self, _input: Input, dt: Duration) -> Result<Vec<Event>, Error> {
|
||||
// This tick function is the centre of the Veloren universe. Most server-side things are
|
||||
@ -351,6 +371,9 @@ impl Server {
|
||||
self.state.remove_chunk(key);
|
||||
}
|
||||
|
||||
// Handle events
|
||||
self.handle_events();
|
||||
|
||||
// 6) Synchronise clients with the new state of the world.
|
||||
self.sync_clients();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user