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