From 5a41a58c0a075af16017ac8c22b648fcd689b1d5 Mon Sep 17 00:00:00 2001 From: timokoesters Date: Sat, 29 Jun 2019 14:10:52 +0200 Subject: [PATCH 1/8] End roll when going too slow --- common/src/sys/animation.rs | 2 +- common/src/sys/controller.rs | 2 +- common/src/sys/phys.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/src/sys/animation.rs b/common/src/sys/animation.rs index 95bb562f90..3412b49943 100644 --- a/common/src/sys/animation.rs +++ b/common/src/sys/animation.rs @@ -57,7 +57,7 @@ impl<'a> System<'a> for Sys { let animation = match ( on_ground.is_some(), - vel.0.magnitude() > 3.0, // Moving + vel.0.magnitude_squared() > 10.0, // Moving attacking.is_some(), gliding.is_some(), rolling.is_some(), diff --git a/common/src/sys/controller.rs b/common/src/sys/controller.rs index 5bd45ac7c7..9dc84325c4 100644 --- a/common/src/sys/controller.rs +++ b/common/src/sys/controller.rs @@ -108,7 +108,7 @@ impl<'a> System<'a> for Sys { && attackings.get(entity).is_none() && glidings.get(entity).is_none() && on_ground.is_some() - && vel.0.magnitude() > 5.0 + && vel.0.magnitude_squared() > 25.0 { rollings.insert(entity, Rolling::start()); } diff --git a/common/src/sys/phys.rs b/common/src/sys/phys.rs index f95d6b839a..4da571fb1b 100644 --- a/common/src/sys/phys.rs +++ b/common/src/sys/phys.rs @@ -124,7 +124,7 @@ impl<'a> System<'a> for Sys { // Roll if let Some(time) = rollings.get_mut(entity).map(|r| &mut r.time) { *time += dt.0; - if *time > 0.55 { + if *time > 0.55 || vel.0.magnitude_squared() < 10.0 { rollings.remove(entity); } } From b0ea959f677eaabe0a2f67f79347d3e03c043a63 Mon Sep 17 00:00:00 2001 From: timokoesters Date: Sat, 29 Jun 2019 17:00:23 +0200 Subject: [PATCH 2/8] Remove animation syncing (does not fix any known bug) --- client/src/lib.rs | 17 +++++++---------- common/src/msg/server.rs | 4 ---- server/src/lib.rs | 36 ------------------------------------ 3 files changed, 7 insertions(+), 50 deletions(-) diff --git a/client/src/lib.rs b/client/src/lib.rs index c043cc0df9..bc6a88b056 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -60,7 +60,7 @@ impl Client { let mut postbox = PostBox::to(addr)?; // Wait for initial sync - let (state, entity, server_info) = match postbox.next_message() { + let (mut state, entity, server_info) = match postbox.next_message() { Some(ServerMsg::InitialSync { ecs_state, entity_uid, @@ -84,6 +84,12 @@ impl Client { // We reduce the thread count by 1 to keep rendering smooth thread_pool.set_num_threads((thread_pool.max_count() - 1).max(1)); + // Set client-only components + state + .ecs_mut() + .write_storage() + .insert(entity, comp::AnimationInfo::default()); + Ok(Self { client_state, thread_pool, @@ -376,15 +382,6 @@ impl Client { } None => {} }, - ServerMsg::EntityAnimation { - entity, - animation_info, - } => match self.state.ecs().entity_from_uid(entity) { - Some(entity) => { - self.state.write_component(entity, animation_info); - } - None => {} - }, ServerMsg::TerrainChunkUpdate { key, chunk } => { self.state.insert_chunk(key, *chunk); self.pending_chunks.remove(&key); diff --git a/common/src/msg/server.rs b/common/src/msg/server.rs index f3604fb839..12898ed72d 100644 --- a/common/src/msg/server.rs +++ b/common/src/msg/server.rs @@ -36,10 +36,6 @@ pub enum ServerMsg { vel: comp::Vel, ori: comp::Ori, }, - EntityAnimation { - entity: u64, - animation_info: comp::AnimationInfo, - }, TerrainChunkUpdate { key: Vec2, chunk: Box, diff --git a/server/src/lib.rs b/server/src/lib.rs index aa331e103b..51c712393a 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -146,7 +146,6 @@ impl Server { .with(comp::Vel(Vec3::zero())) .with(comp::Ori(Vec3::unit_y())) .with(comp::Controller::default()) - .with(comp::AnimationInfo::default()) .with(comp::Actor::Character { name, body }) .with(comp::Stats::default()) .with(comp::ForceUpdate) @@ -163,7 +162,6 @@ impl Server { state.write_component(entity, comp::Actor::Character { name, body }); state.write_component(entity, comp::Stats::default()); - state.write_component(entity, comp::AnimationInfo::default()); state.write_component(entity, comp::Controller::default()); state.write_component(entity, comp::Pos(spawn_point)); state.write_component(entity, comp::Vel(Vec3::zero())); @@ -636,19 +634,6 @@ impl Server { }); } - // Sync animations - for (&uid, &animation_info) in ( - &state.ecs().read_storage::(), - &state.ecs().read_storage::(), - ) - .join() - { - client.notify(ServerMsg::EntityAnimation { - entity: uid.into(), - animation_info: animation_info.clone(), - }); - } - // Tell the client its request was successful. client.allow_state(ClientState::Registered); } @@ -709,27 +694,6 @@ impl Server { } } - // Sync animations - for (entity, &uid, &animation_info, force_update) in ( - &self.state.ecs().entities(), - &self.state.ecs().read_storage::(), - &self.state.ecs().read_storage::(), - self.state.ecs().read_storage::().maybe(), - ) - .join() - { - if animation_info.changed || force_update.is_some() { - let msg = ServerMsg::EntityAnimation { - entity: uid.into(), - animation_info: animation_info.clone(), - }; - match force_update { - Some(_) => self.clients.notify_ingame(msg), - None => self.clients.notify_ingame_except(entity, msg), - } - } - } - // Remove all force flags. self.state .ecs_mut() From c80351f6ca71feeb9b6bad6a7cb7a2679b1a3aff Mon Sep 17 00:00:00 2001 From: timokoesters Date: Sat, 29 Jun 2019 19:49:51 +0200 Subject: [PATCH 3/8] Fix double roll bug --- client/src/lib.rs | 2 + common/src/comp/action_state.rs | 26 ++++++ common/src/comp/mod.rs | 2 + common/src/msg/ecs_packet.rs | 6 -- common/src/msg/server.rs | 1 + common/src/state.rs | 9 +- common/src/sys/action_state.rs | 60 +++++++++++++ common/src/sys/animation.rs | 36 +++----- common/src/sys/mod.rs | 11 ++- server/src/lib.rs | 145 +++++++++++++++++--------------- 10 files changed, 188 insertions(+), 110 deletions(-) create mode 100644 common/src/comp/action_state.rs create mode 100644 common/src/sys/action_state.rs diff --git a/client/src/lib.rs b/client/src/lib.rs index bc6a88b056..94bc446c61 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -374,11 +374,13 @@ impl Client { pos, vel, ori, + action_state, } => match self.state.ecs().entity_from_uid(entity) { Some(entity) => { self.state.write_component(entity, pos); self.state.write_component(entity, vel); self.state.write_component(entity, ori); + self.state.write_component(entity, action_state); } None => {} }, diff --git a/common/src/comp/action_state.rs b/common/src/comp/action_state.rs new file mode 100644 index 0000000000..7296e1031f --- /dev/null +++ b/common/src/comp/action_state.rs @@ -0,0 +1,26 @@ +use specs::{Component, FlaggedStorage, NullStorage, VecStorage}; + +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub struct ActionState { + pub moving: bool, + pub on_ground: bool, + pub attacking: bool, + pub rolling: bool, + pub gliding: bool, +} + +impl Default for ActionState { + fn default() -> Self { + Self { + moving: false, + on_ground: false, + attacking: false, + rolling: false, + gliding: false, + } + } +} + +impl Component for ActionState { + type Storage = FlaggedStorage>; +} diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index 4f0b3a6477..d93cf4c579 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -7,6 +7,7 @@ mod inventory; mod phys; mod player; mod stats; +mod action_state; // Reexports pub use agent::Agent; @@ -18,3 +19,4 @@ pub use inventory::{item, Inventory}; pub use phys::{ForceUpdate, Ori, Pos, Vel}; pub use player::Player; pub use stats::{Dying, HealthSource, Stats}; +pub use action_state::ActionState; diff --git a/common/src/msg/ecs_packet.rs b/common/src/msg/ecs_packet.rs index 841b0d5a8e..1c533cfd0e 100644 --- a/common/src/msg/ecs_packet.rs +++ b/common/src/msg/ecs_packet.rs @@ -23,9 +23,6 @@ sphynx::sum_type! { Actor(comp::Actor), Player(comp::Player), Stats(comp::Stats), - Attacking(comp::Attacking), - Rolling(comp::Rolling), - Gliding(comp::Gliding), } } // Automatically derive From for EcsCompPhantom @@ -39,9 +36,6 @@ sphynx::sum_type! { Actor(PhantomData), Player(PhantomData), Stats(PhantomData), - Attacking(PhantomData), - Rolling(PhantomData), - Gliding(PhantomData), } } impl sphynx::CompPacket for EcsCompPacket { diff --git a/common/src/msg/server.rs b/common/src/msg/server.rs index 12898ed72d..0fadce7afa 100644 --- a/common/src/msg/server.rs +++ b/common/src/msg/server.rs @@ -35,6 +35,7 @@ pub enum ServerMsg { pos: comp::Pos, vel: comp::Vel, ori: comp::Ori, + action_state: comp::ActionState, }, TerrainChunkUpdate { key: Vec2, diff --git a/common/src/state.rs b/common/src/state.rs index 919c9009f8..fa25027980 100644 --- a/common/src/state.rs +++ b/common/src/state.rs @@ -102,9 +102,6 @@ impl State { ecs.register_synced::(); ecs.register_synced::(); ecs.register_synced::(); - ecs.register_synced::(); - ecs.register_synced::(); - ecs.register_synced::(); // Register components synced by other means ecs.register::(); @@ -112,10 +109,14 @@ impl State { ecs.register::(); ecs.register::(); ecs.register::(); - ecs.register::(); ecs.register::(); + ecs.register::(); + ecs.register::(); + ecs.register::(); + ecs.register::(); // Register client-local components + ecs.register::(); ecs.register::(); // Register server-local components diff --git a/common/src/sys/action_state.rs b/common/src/sys/action_state.rs new file mode 100644 index 0000000000..b3c97a1b15 --- /dev/null +++ b/common/src/sys/action_state.rs @@ -0,0 +1,60 @@ +use crate::{ + comp::{ + Animation, AnimationInfo, Attacking, ForceUpdate, Gliding, Jumping, OnGround, Ori, Pos, + Rolling, Vel, ActionState, + }, + state::DeltaTime, +}; +use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage}; + +/// This system will set the ActionState component as specified by other components +pub struct Sys; +impl<'a> System<'a> for Sys { + type SystemData = ( + Entities<'a>, + Read<'a, DeltaTime>, + ReadStorage<'a, Vel>, + ReadStorage<'a, OnGround>, + ReadStorage<'a, Jumping>, + ReadStorage<'a, Gliding>, + ReadStorage<'a, Attacking>, + ReadStorage<'a, Rolling>, + WriteStorage<'a, ActionState>, + ); + + fn run( + &mut self, + ( + entities, + dt, + velocities, + on_grounds, + jumpings, + glidings, + attackings, + rollings, + mut action_states, + ): Self::SystemData, + ) { + for (entity, vel, on_ground, jumping, gliding, attacking, rolling, mut action_state) in ( + &entities, + &velocities, + on_grounds.maybe(), + jumpings.maybe(), + glidings.maybe(), + attackings.maybe(), + rollings.maybe(), + &mut action_states, + ) + .join() + { + *action_state = ActionState { + on_ground: on_ground.is_some(), + moving: vel.0.magnitude_squared() > 10.0, + attacking: attacking.is_some(), + rolling: rolling.is_some(), + gliding: gliding.is_some(), + }; + } + } +} diff --git a/common/src/sys/animation.rs b/common/src/sys/animation.rs index 3412b49943..7af4953117 100644 --- a/common/src/sys/animation.rs +++ b/common/src/sys/animation.rs @@ -1,7 +1,6 @@ use crate::{ comp::{ - Animation, AnimationInfo, Attacking, ForceUpdate, Gliding, Jumping, OnGround, Ori, Pos, - Rolling, Vel, + Animation, AnimationInfo, ForceUpdate, ActionState }, state::DeltaTime, }; @@ -13,12 +12,7 @@ impl<'a> System<'a> for Sys { type SystemData = ( Entities<'a>, Read<'a, DeltaTime>, - ReadStorage<'a, Vel>, - ReadStorage<'a, OnGround>, - ReadStorage<'a, Jumping>, - ReadStorage<'a, Gliding>, - ReadStorage<'a, Attacking>, - ReadStorage<'a, Rolling>, + ReadStorage<'a, ActionState>, WriteStorage<'a, AnimationInfo>, ); @@ -27,23 +21,13 @@ impl<'a> System<'a> for Sys { ( entities, dt, - velocities, - on_grounds, - jumpings, - glidings, - attackings, - rollings, + action_states, mut animation_infos, ): Self::SystemData, ) { - for (entity, vel, on_ground, jumping, gliding, attacking, rolling, mut animation_info) in ( + for (entity, a, mut animation_info) in ( &entities, - &velocities, - on_grounds.maybe(), - jumpings.maybe(), - glidings.maybe(), - attackings.maybe(), - rollings.maybe(), + &action_states, &mut animation_infos, ) .join() @@ -56,11 +40,11 @@ impl<'a> System<'a> for Sys { } let animation = match ( - on_ground.is_some(), - vel.0.magnitude_squared() > 10.0, // Moving - attacking.is_some(), - gliding.is_some(), - rolling.is_some(), + a.on_ground, + a.moving, + a.attacking, + a.gliding, + a.rolling, ) { (_, _, true, true, _) => impossible_animation("Attack while gliding"), (_, _, true, _, true) => impossible_animation("Roll while attacking"), diff --git a/common/src/sys/mod.rs b/common/src/sys/mod.rs index 65b24f12fa..6bf0ddb162 100644 --- a/common/src/sys/mod.rs +++ b/common/src/sys/mod.rs @@ -4,6 +4,7 @@ pub mod combat; pub mod controller; pub mod phys; mod stats; +mod action_state; // External use specs::DispatcherBuilder; @@ -11,6 +12,7 @@ use specs::DispatcherBuilder; // System names const AGENT_SYS: &str = "agent_sys"; const CONTROLLER_SYS: &str = "controller_sys"; +const ACTION_STATE_SYS: &str = "action_state_sys"; const PHYS_SYS: &str = "phys_sys"; const COMBAT_SYS: &str = "combat_sys"; const ANIMATION_SYS: &str = "animation_sys"; @@ -18,9 +20,10 @@ const STATS_SYS: &str = "stats_sys"; pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) { dispatch_builder.add(agent::Sys, AGENT_SYS, &[]); - dispatch_builder.add(controller::Sys, CONTROLLER_SYS, &[]); - dispatch_builder.add(phys::Sys, PHYS_SYS, &[]); - dispatch_builder.add(combat::Sys, COMBAT_SYS, &[]); - dispatch_builder.add(animation::Sys, ANIMATION_SYS, &[]); + dispatch_builder.add(controller::Sys, CONTROLLER_SYS, &[AGENT_SYS]); + dispatch_builder.add(phys::Sys, PHYS_SYS, &[CONTROLLER_SYS]); + dispatch_builder.add(action_state::Sys, ACTION_STATE_SYS, &[CONTROLLER_SYS, PHYS_SYS]); + 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]); } diff --git a/server/src/lib.rs b/server/src/lib.rs index 51c712393a..4e46303d5d 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -166,6 +166,7 @@ impl Server { state.write_component(entity, comp::Pos(spawn_point)); state.write_component(entity, comp::Vel(Vec3::zero())); state.write_component(entity, comp::Ori(Vec3::unit_y())); + state.write_component(entity, comp::ActionState::default()); // Make sure physics are accepted. state.write_component(entity, comp::ForceUpdate); @@ -210,74 +211,6 @@ impl Server { // Tick the world self.world.tick(dt); - // Sync deaths. - let ecs = &self.state.ecs(); - let clients = &mut self.clients; - let todo_kill = (&ecs.entities(), &ecs.read_storage::()) - .join() - .map(|(entity, dying)| { - // Chat message - if let Some(player) = ecs.read_storage::().get(entity) { - let msg = if let comp::HealthSource::Attack { by } = dying.cause { - ecs.entity_from_uid(by.into()).and_then(|attacker| { - ecs.read_storage::() - .get(attacker) - .map(|attacker_alias| { - format!( - "{} was killed by {}", - &player.alias, &attacker_alias.alias - ) - }) - }) - } else { - None - } - .unwrap_or(format!("{} died", &player.alias)); - - clients.notify_registered(ServerMsg::Chat(msg)); - } - - entity - }) - .collect::>(); - - // Actually kill them - for entity in todo_kill { - if let Some(client) = self.clients.get_mut(&entity) { - self.state.write_component(entity, comp::Vel(Vec3::zero())); - self.state.write_component(entity, comp::ForceUpdate); - client.force_state(ClientState::Dead); - } else { - if let Err(err) = self.state.ecs_mut().delete_entity_synced(entity) { - warn!("Failed to delete client not found in kill list: {:?}", err); - } - continue; - } - } - - // Handle respawns - let todo_respawn = ( - &self.state.ecs().entities(), - &self.state.ecs().read_storage::(), - ) - .join() - .map(|(entity, _)| entity) - .collect::>(); - - for entity in todo_respawn { - if let Some(client) = self.clients.get_mut(&entity) { - client.allow_state(ClientState::Character); - self.state.write_component(entity, comp::Stats::default()); - self.state - .ecs_mut() - .write_storage::() - .get_mut(entity) - .map(|pos| pos.0.z += 100.0); - self.state.write_component(entity, comp::Vel(Vec3::zero())); - self.state.write_component(entity, comp::ForceUpdate); - } - } - // 5) Fetch any generated `TerrainChunk`s and insert them into the terrain. // Also, send the chunk data to anybody that is close by. if let Ok((key, chunk)) = self.chunk_rx.try_recv() { @@ -618,11 +551,12 @@ impl Server { state.write_component(entity, player); // Sync physics - for (&uid, &pos, &vel, &ori) in ( + for (&uid, &pos, &vel, &ori, &action_state) in ( &state.ecs().read_storage::(), &state.ecs().read_storage::(), &state.ecs().read_storage::(), &state.ecs().read_storage::(), + &state.ecs().read_storage::(), ) .join() { @@ -631,6 +565,7 @@ impl Server { pos, vel, ori, + action_state, }); } @@ -645,12 +580,13 @@ impl Server { .notify_registered(ServerMsg::EcsSync(self.state.ecs_mut().next_sync_package())); // Sync physics - for (entity, &uid, &pos, &vel, &ori, force_update) in ( + for (entity, &uid, &pos, &vel, &ori, &action_state, force_update) in ( &self.state.ecs().entities(), &self.state.ecs().read_storage::(), &self.state.ecs().read_storage::(), &self.state.ecs().read_storage::(), &self.state.ecs().read_storage::(), + &self.state.ecs().read_storage::(), self.state.ecs().read_storage::().maybe(), ) .join() @@ -660,6 +596,7 @@ impl Server { pos, vel, ori, + action_state, }; let state = &self.state; @@ -694,6 +631,74 @@ impl Server { } } + // Sync deaths. + let ecs = &self.state.ecs(); + let clients = &mut self.clients; + let todo_kill = (&ecs.entities(), &ecs.read_storage::()) + .join() + .map(|(entity, dying)| { + // Chat message + if let Some(player) = ecs.read_storage::().get(entity) { + let msg = if let comp::HealthSource::Attack { by } = dying.cause { + ecs.entity_from_uid(by.into()).and_then(|attacker| { + ecs.read_storage::() + .get(attacker) + .map(|attacker_alias| { + format!( + "{} was killed by {}", + &player.alias, &attacker_alias.alias + ) + }) + }) + } else { + None + } + .unwrap_or(format!("{} died", &player.alias)); + + clients.notify_registered(ServerMsg::Chat(msg)); + } + + entity + }) + .collect::>(); + + // Actually kill them + for entity in todo_kill { + if let Some(client) = self.clients.get_mut(&entity) { + self.state.write_component(entity, comp::Vel(Vec3::zero())); + self.state.write_component(entity, comp::ForceUpdate); + client.force_state(ClientState::Dead); + } else { + if let Err(err) = self.state.ecs_mut().delete_entity_synced(entity) { + warn!("Failed to delete client not found in kill list: {:?}", err); + } + continue; + } + } + + // Handle respawns + let todo_respawn = ( + &self.state.ecs().entities(), + &self.state.ecs().read_storage::(), + ) + .join() + .map(|(entity, _)| entity) + .collect::>(); + + for entity in todo_respawn { + if let Some(client) = self.clients.get_mut(&entity) { + client.allow_state(ClientState::Character); + self.state.write_component(entity, comp::Stats::default()); + self.state + .ecs_mut() + .write_storage::() + .get_mut(entity) + .map(|pos| pos.0.z += 100.0); + self.state.write_component(entity, comp::Vel(Vec3::zero())); + self.state.write_component(entity, comp::ForceUpdate); + } + } + // Remove all force flags. self.state .ecs_mut() From 9f835337413d2ec6fdd141eb53d72f941319ec6e Mon Sep 17 00:00:00 2001 From: timokoesters Date: Sat, 29 Jun 2019 20:23:18 +0200 Subject: [PATCH 4/8] Fix invisible characters --- common/src/comp/animation.rs | 2 -- common/src/sys/animation.rs | 15 +++++---------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/common/src/comp/animation.rs b/common/src/comp/animation.rs index d3e89dc18c..e59a506148 100644 --- a/common/src/comp/animation.rs +++ b/common/src/comp/animation.rs @@ -16,7 +16,6 @@ pub enum Animation { pub struct AnimationInfo { pub animation: Animation, pub time: f64, - pub changed: bool, } impl Default for AnimationInfo { @@ -24,7 +23,6 @@ impl Default for AnimationInfo { Self { animation: Animation::Idle, time: 0.0, - changed: true, } } } diff --git a/common/src/sys/animation.rs b/common/src/sys/animation.rs index 7af4953117..6b251a0311 100644 --- a/common/src/sys/animation.rs +++ b/common/src/sys/animation.rs @@ -25,15 +25,12 @@ impl<'a> System<'a> for Sys { mut animation_infos, ): Self::SystemData, ) { - for (entity, a, mut animation_info) in ( + for (entity, a) in ( &entities, &action_states, - &mut animation_infos, ) .join() { - animation_info.time += dt.0 as f64; - fn impossible_animation(message: &str) -> Animation { warn!("{}", message); Animation::Idle @@ -58,14 +55,12 @@ impl<'a> System<'a> for Sys { (_, _, true, false, false) => Animation::Attack, }; - let last = animation_info.clone(); - let changed = last.animation != animation; + let new_time = animation_infos.get(entity).filter(|i| i.animation == animation).map(|i| i.time + dt.0 as f64); - *animation_info = AnimationInfo { + animation_infos.insert(entity, AnimationInfo { animation, - time: if changed { 0.0 } else { last.time }, - changed, - }; + time: new_time.unwrap_or(0.0), + }); } } } From 610c86a3b99dacd248beec2e882d0ab9747b3c26 Mon Sep 17 00:00:00 2001 From: timokoesters Date: Sat, 29 Jun 2019 20:52:20 +0200 Subject: [PATCH 5/8] Animation fixes --- common/src/comp/mod.rs | 4 +-- common/src/sys/action_state.rs | 19 +++++++++++--- common/src/sys/animation.rs | 45 ++++++++++++---------------------- common/src/sys/mod.rs | 8 ++++-- 4 files changed, 39 insertions(+), 37 deletions(-) diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index d93cf4c579..fee0d63f16 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -1,3 +1,4 @@ +mod action_state; mod agent; mod animation; mod body; @@ -7,9 +8,9 @@ mod inventory; mod phys; mod player; mod stats; -mod action_state; // Reexports +pub use action_state::ActionState; pub use agent::Agent; pub use animation::{Animation, AnimationInfo}; pub use body::{humanoid, quadruped, quadruped_medium, Actor, Body}; @@ -19,4 +20,3 @@ pub use inventory::{item, Inventory}; pub use phys::{ForceUpdate, Ori, Pos, Vel}; pub use player::Player; pub use stats::{Dying, HealthSource, Stats}; -pub use action_state::ActionState; diff --git a/common/src/sys/action_state.rs b/common/src/sys/action_state.rs index b3c97a1b15..93dc4607e5 100644 --- a/common/src/sys/action_state.rs +++ b/common/src/sys/action_state.rs @@ -1,7 +1,7 @@ use crate::{ comp::{ - Animation, AnimationInfo, Attacking, ForceUpdate, Gliding, Jumping, OnGround, Ori, Pos, - Rolling, Vel, ActionState, + ActionState, Animation, AnimationInfo, Attacking, Controller, ForceUpdate, Gliding, + Jumping, OnGround, Ori, Pos, Rolling, Vel, }, state::DeltaTime, }; @@ -13,6 +13,7 @@ impl<'a> System<'a> for Sys { type SystemData = ( Entities<'a>, Read<'a, DeltaTime>, + ReadStorage<'a, Controller>, ReadStorage<'a, Vel>, ReadStorage<'a, OnGround>, ReadStorage<'a, Jumping>, @@ -27,6 +28,7 @@ impl<'a> System<'a> for Sys { ( entities, dt, + controllers, // To make sure it only runs on the single client and the server velocities, on_grounds, jumpings, @@ -36,9 +38,20 @@ impl<'a> System<'a> for Sys { mut action_states, ): Self::SystemData, ) { - for (entity, vel, on_ground, jumping, gliding, attacking, rolling, mut action_state) in ( + for ( + entity, + vel, + _controller, + on_ground, + jumping, + gliding, + attacking, + rolling, + mut action_state, + ) in ( &entities, &velocities, + &controllers, on_grounds.maybe(), jumpings.maybe(), glidings.maybe(), diff --git a/common/src/sys/animation.rs b/common/src/sys/animation.rs index 6b251a0311..cebb5dde07 100644 --- a/common/src/sys/animation.rs +++ b/common/src/sys/animation.rs @@ -1,7 +1,5 @@ use crate::{ - comp::{ - Animation, AnimationInfo, ForceUpdate, ActionState - }, + comp::{ActionState, Animation, AnimationInfo, ForceUpdate}, state::DeltaTime, }; use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage}; @@ -16,33 +14,14 @@ impl<'a> System<'a> for Sys { WriteStorage<'a, AnimationInfo>, ); - fn run( - &mut self, - ( - entities, - dt, - action_states, - mut animation_infos, - ): Self::SystemData, - ) { - for (entity, a) in ( - &entities, - &action_states, - ) - .join() - { + fn run(&mut self, (entities, dt, action_states, mut animation_infos): Self::SystemData) { + for (entity, a) in (&entities, &action_states).join() { fn impossible_animation(message: &str) -> Animation { warn!("{}", message); Animation::Idle } - let animation = match ( - a.on_ground, - a.moving, - a.attacking, - a.gliding, - a.rolling, - ) { + let animation = match (a.on_ground, a.moving, a.attacking, a.gliding, a.rolling) { (_, _, true, true, _) => impossible_animation("Attack while gliding"), (_, _, true, _, true) => impossible_animation("Roll while attacking"), (_, _, _, true, true) => impossible_animation("Roll while gliding"), @@ -55,12 +34,18 @@ impl<'a> System<'a> for Sys { (_, _, true, false, false) => Animation::Attack, }; - let new_time = animation_infos.get(entity).filter(|i| i.animation == animation).map(|i| i.time + dt.0 as f64); + let new_time = animation_infos + .get(entity) + .filter(|i| i.animation == animation) + .map(|i| i.time + dt.0 as f64); - animation_infos.insert(entity, AnimationInfo { - animation, - time: new_time.unwrap_or(0.0), - }); + animation_infos.insert( + entity, + AnimationInfo { + animation, + time: new_time.unwrap_or(0.0), + }, + ); } } } diff --git a/common/src/sys/mod.rs b/common/src/sys/mod.rs index 6bf0ddb162..6507c09f7e 100644 --- a/common/src/sys/mod.rs +++ b/common/src/sys/mod.rs @@ -1,10 +1,10 @@ +mod action_state; pub mod agent; pub mod animation; pub mod combat; pub mod controller; pub mod phys; mod stats; -mod action_state; // External use specs::DispatcherBuilder; @@ -22,7 +22,11 @@ pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) { dispatch_builder.add(agent::Sys, AGENT_SYS, &[]); dispatch_builder.add(controller::Sys, CONTROLLER_SYS, &[AGENT_SYS]); dispatch_builder.add(phys::Sys, PHYS_SYS, &[CONTROLLER_SYS]); - dispatch_builder.add(action_state::Sys, ACTION_STATE_SYS, &[CONTROLLER_SYS, PHYS_SYS]); + dispatch_builder.add( + action_state::Sys, + ACTION_STATE_SYS, + &[CONTROLLER_SYS, PHYS_SYS], + ); 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]); From 5fcf6ededa4313760334d72056e47df3886e0a58 Mon Sep 17 00:00:00 2001 From: timokoesters Date: Sat, 29 Jun 2019 22:11:21 +0200 Subject: [PATCH 6/8] magnitude_squared everywhere, actionstate everywhere, constant for moving --- common/src/sys/action_state.rs | 3 +- common/src/sys/controller.rs | 38 ++++++++------------------ common/src/sys/phys.rs | 50 ++++++++++++++++++++-------------- 3 files changed, 43 insertions(+), 48 deletions(-) diff --git a/common/src/sys/action_state.rs b/common/src/sys/action_state.rs index 93dc4607e5..08c1a3d514 100644 --- a/common/src/sys/action_state.rs +++ b/common/src/sys/action_state.rs @@ -4,6 +4,7 @@ use crate::{ Jumping, OnGround, Ori, Pos, Rolling, Vel, }, state::DeltaTime, + sys::phys::MOVEMENT_THRESHOLD_VEL, }; use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage}; @@ -63,7 +64,7 @@ impl<'a> System<'a> for Sys { { *action_state = ActionState { on_ground: on_ground.is_some(), - moving: vel.0.magnitude_squared() > 10.0, + moving: vel.0.magnitude_squared() > MOVEMENT_THRESHOLD_VEL.powf(2.0), attacking: attacking.is_some(), rolling: rolling.is_some(), gliding: gliding.is_some(), diff --git a/common/src/sys/controller.rs b/common/src/sys/controller.rs index 9dc84325c4..58edf00140 100644 --- a/common/src/sys/controller.rs +++ b/common/src/sys/controller.rs @@ -1,7 +1,7 @@ use crate::{ comp::{ - Animation, AnimationInfo, Attacking, Controller, Gliding, HealthSource, Jumping, MoveDir, - OnGround, Respawning, Rolling, Stats, {ForceUpdate, Ori, Pos, Vel}, + ActionState, Animation, AnimationInfo, Attacking, Controller, Gliding, HealthSource, + Jumping, MoveDir, OnGround, Respawning, Rolling, Stats, {ForceUpdate, Ori, Pos, Vel}, }, state::DeltaTime, }; @@ -18,7 +18,7 @@ impl<'a> System<'a> for Sys { ReadStorage<'a, Pos>, ReadStorage<'a, Vel>, ReadStorage<'a, Ori>, - ReadStorage<'a, OnGround>, + ReadStorage<'a, ActionState>, WriteStorage<'a, MoveDir>, WriteStorage<'a, Jumping>, WriteStorage<'a, Attacking>, @@ -37,7 +37,7 @@ impl<'a> System<'a> for Sys { positions, velocities, orientations, - on_grounds, + action_states, mut move_dirs, mut jumpings, mut attackings, @@ -46,14 +46,14 @@ impl<'a> System<'a> for Sys { mut glidings, ): Self::SystemData, ) { - for (entity, controller, stats, pos, vel, ori, on_ground) in ( + for (entity, controller, stats, pos, vel, ori, a) in ( &entities, &controllers, &stats, &positions, &velocities, &orientations, - on_grounds.maybe(), + &action_states, ) .join() { @@ -66,10 +66,10 @@ impl<'a> System<'a> for Sys { } // Move dir - if rollings.get(entity).is_none() { + if !a.rolling { move_dirs.insert( entity, - MoveDir(if controller.move_dir.magnitude() > 1.0 { + MoveDir(if controller.move_dir.magnitude_squared() > 1.0 { controller.move_dir.normalized() } else { controller.move_dir @@ -78,38 +78,24 @@ impl<'a> System<'a> for Sys { } // Glide - if controller.glide - && on_ground.is_none() - && attackings.get(entity).is_none() - && rollings.get(entity).is_none() - { + if controller.glide && !a.on_ground && !a.attacking && !a.rolling { glidings.insert(entity, Gliding); } else { glidings.remove(entity); } // Attack - if controller.attack - && attackings.get(entity).is_none() - && glidings.get(entity).is_none() - && rollings.get(entity).is_none() - { + if controller.attack && !a.attacking && !a.gliding && !a.rolling { attackings.insert(entity, Attacking::start()); } // Jump - if controller.jump && on_ground.is_some() && vel.0.z <= 0.0 { + if controller.jump && a.on_ground && vel.0.z <= 0.0 { jumpings.insert(entity, Jumping); } // Roll - if controller.roll - && rollings.get(entity).is_none() - && attackings.get(entity).is_none() - && glidings.get(entity).is_none() - && on_ground.is_some() - && vel.0.magnitude_squared() > 25.0 - { + if controller.roll && !a.rolling && a.on_ground && a.moving && !a.attacking && !a.gliding { rollings.insert(entity, Rolling::start()); } } diff --git a/common/src/sys/phys.rs b/common/src/sys/phys.rs index 4da571fb1b..bf41fc2775 100644 --- a/common/src/sys/phys.rs +++ b/common/src/sys/phys.rs @@ -1,5 +1,5 @@ use crate::{ - comp::{Gliding, Jumping, MoveDir, OnGround, Ori, Pos, Rolling, Stats, Vel}, + comp::{ActionState, Gliding, Jumping, MoveDir, OnGround, Ori, Pos, Rolling, Stats, Vel}, state::DeltaTime, terrain::TerrainMap, vol::{ReadVol, Vox}, @@ -22,6 +22,8 @@ const GLIDE_SPEED: f32 = 45.0; // Gravity is 9.81 * 4, so this makes gravity equal to .15 const GLIDE_ANTIGRAV: f32 = 9.81 * 3.95; +pub const MOVEMENT_THRESHOLD_VEL: f32 = 3.0; + // Integrates forces, calculates the new velocity based off of the old velocity // dt = delta time // lv = linear velocity @@ -45,6 +47,7 @@ impl<'a> System<'a> for Sys { ReadStorage<'a, MoveDir>, ReadStorage<'a, Gliding>, ReadStorage<'a, Stats>, + ReadStorage<'a, ActionState>, WriteStorage<'a, Jumping>, WriteStorage<'a, Rolling>, WriteStorage<'a, OnGround>, @@ -62,6 +65,7 @@ impl<'a> System<'a> for Sys { move_dirs, glidings, stats, + action_states, mut jumpings, mut rollings, mut on_grounds, @@ -71,11 +75,11 @@ impl<'a> System<'a> for Sys { ): Self::SystemData, ) { // Apply movement inputs - for (entity, stats, move_dir, gliding, mut pos, mut vel, mut ori) in ( + for (entity, stats, a, move_dir, mut pos, mut vel, mut ori) in ( &entities, &stats, + &action_states, move_dirs.maybe(), - glidings.maybe(), &mut positions, &mut velocities, &mut orientations, @@ -91,19 +95,25 @@ impl<'a> System<'a> for Sys { if let Some(move_dir) = move_dir { vel.0 += Vec2::broadcast(dt.0) * move_dir.0 - * match ( - on_grounds.get(entity).is_some(), - glidings.get(entity).is_some(), - rollings.get(entity).is_some(), - ) { - (true, false, false) if vel.0.magnitude() < HUMANOID_SPEED => { + * match (a.on_ground, a.gliding, a.rolling) { + (true, false, false) + if vel.0.magnitude_squared() < HUMANOID_SPEED.powf(2.0) => + { HUMANOID_ACCEL } - (false, true, false) if vel.0.magnitude() < GLIDE_SPEED => GLIDE_ACCEL, - (false, false, false) if vel.0.magnitude() < HUMANOID_AIR_SPEED => { + (false, true, false) + if vel.0.magnitude_squared() < GLIDE_SPEED.powf(2.0) => + { + GLIDE_ACCEL + } + (false, false, false) + if vel.0.magnitude_squared() < HUMANOID_AIR_SPEED.powf(2.0) => + { HUMANOID_AIR_ACCEL } - (true, false, true) if vel.0.magnitude() < ROLL_SPEED => ROLL_ACCEL, + (true, false, true) if vel.0.magnitude_squared() < ROLL_SPEED.powf(2.0) => { + ROLL_ACCEL + } _ => 0.0, }; @@ -116,7 +126,10 @@ impl<'a> System<'a> for Sys { } // Glide - if gliding.is_some() && vel.0.magnitude() < GLIDE_SPEED && vel.0.z < 0.0 { + if a.gliding + && vel.0.magnitude_squared() < GLIDE_SPEED.powf(2.0) + && vel.0.z < 0.0 + { let lift = GLIDE_ANTIGRAV + vel.0.z.powf(2.0) * 0.2; vel.0.z += dt.0 * lift * Vec2::::from(vel.0 * 0.15).magnitude().min(1.0); } @@ -124,7 +137,7 @@ impl<'a> System<'a> for Sys { // Roll if let Some(time) = rollings.get_mut(entity).map(|r| &mut r.time) { *time += dt.0; - if *time > 0.55 || vel.0.magnitude_squared() < 10.0 { + if *time > 0.55 || !a.moving { rollings.remove(entity); } } @@ -136,12 +149,7 @@ impl<'a> System<'a> for Sys { // Integrate forces // Friction is assumed to be a constant dependent on location - let friction = 50.0 - * if on_grounds.get(entity).is_some() { - FRIC_GROUND - } else { - FRIC_AIR - }; + let friction = 50.0 * if a.on_ground { FRIC_GROUND } else { FRIC_AIR }; vel.0 = integrate_forces(dt.0, vel.0, friction); // Basic collision with terrain @@ -184,7 +192,7 @@ impl<'a> System<'a> for Sys { false }; - let was_on_ground = on_grounds.get(entity).is_some(); + let was_on_ground = a.on_ground; on_grounds.remove(entity); // Assume we're in the air - unless we can prove otherwise pos.0.z -= 0.0001; // To force collision with the floor From d235374d8e724d50394dbe7881dd61fde873fe61 Mon Sep 17 00:00:00 2001 From: timokoesters Date: Sat, 29 Jun 2019 22:40:40 +0200 Subject: [PATCH 7/8] Fix npc and death bug --- client/src/lib.rs | 22 ++++++++++++---------- common/src/sys/controller.rs | 8 +++++++- common/src/sys/phys.rs | 5 +---- server/src/lib.rs | 5 +++-- voxygen/src/scene/figure.rs | 2 +- 5 files changed, 24 insertions(+), 18 deletions(-) diff --git a/client/src/lib.rs b/client/src/lib.rs index 94bc446c61..01abe759ef 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -310,16 +310,18 @@ impl Client { } // 6) Update the server about the player's physics attributes. - match ( - self.state.read_storage().get(self.entity).cloned(), - self.state.read_storage().get(self.entity).cloned(), - self.state.read_storage().get(self.entity).cloned(), - ) { - (Some(pos), Some(vel), Some(ori)) => { - self.postbox - .send_message(ClientMsg::PlayerPhysics { pos, vel, ori }); + if let ClientState::Character = self.client_state { + match ( + self.state.read_storage().get(self.entity).cloned(), + self.state.read_storage().get(self.entity).cloned(), + self.state.read_storage().get(self.entity).cloned(), + ) { + (Some(pos), Some(vel), Some(ori)) => { + self.postbox + .send_message(ClientMsg::PlayerPhysics { pos, vel, ori }); + } + _ => {} } - _ => {} } // Output debug metrics @@ -392,7 +394,7 @@ impl Client { self.client_state = state; } ServerMsg::StateAnswer(Err((error, state))) => { - warn!("{:?}", error); + warn!("StateAnswer: {:?}", error); } ServerMsg::ForceState(state) => { self.client_state = state; diff --git a/common/src/sys/controller.rs b/common/src/sys/controller.rs index 58edf00140..f78a912251 100644 --- a/common/src/sys/controller.rs +++ b/common/src/sys/controller.rs @@ -95,7 +95,13 @@ impl<'a> System<'a> for Sys { } // Roll - if controller.roll && !a.rolling && a.on_ground && a.moving && !a.attacking && !a.gliding { + if controller.roll + && !a.rolling + && a.on_ground + && a.moving + && !a.attacking + && !a.gliding + { rollings.insert(entity, Rolling::start()); } } diff --git a/common/src/sys/phys.rs b/common/src/sys/phys.rs index bf41fc2775..a7cffc3859 100644 --- a/common/src/sys/phys.rs +++ b/common/src/sys/phys.rs @@ -126,10 +126,7 @@ impl<'a> System<'a> for Sys { } // Glide - if a.gliding - && vel.0.magnitude_squared() < GLIDE_SPEED.powf(2.0) - && vel.0.z < 0.0 - { + if a.gliding && vel.0.magnitude_squared() < GLIDE_SPEED.powf(2.0) && vel.0.z < 0.0 { let lift = GLIDE_ANTIGRAV + vel.0.z.powf(2.0) * 0.2; vel.0.z += dt.0 * lift * Vec2::::from(vel.0 * 0.15).magnitude().min(1.0); } diff --git a/server/src/lib.rs b/server/src/lib.rs index 4e46303d5d..1b03bfb266 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -20,7 +20,7 @@ use common::{ terrain::{TerrainChunk, TerrainChunkSize}, vol::VolSize, }; -use log::warn; +use log::{debug, warn}; use specs::{join::Join, world::EntityBuilder as EcsEntityBuilder, Builder, Entity as EcsEntity}; use std::{ collections::HashSet, @@ -148,6 +148,7 @@ impl Server { .with(comp::Controller::default()) .with(comp::Actor::Character { name, body }) .with(comp::Stats::default()) + .with(comp::ActionState::default()) .with(comp::ForceUpdate) } @@ -526,7 +527,7 @@ impl Server { // Handle client disconnects. for entity in disconnected_clients { if let Err(err) = self.state.ecs_mut().delete_entity_synced(entity) { - warn!("Failed to delete disconnected client: {:?}", err); + debug!("Failed to delete disconnected client: {:?}", err); } frontend_events.push(Event::ClientDisconnected { entity }); diff --git a/voxygen/src/scene/figure.rs b/voxygen/src/scene/figure.rs index 5c7ee582f7..8b42334535 100644 --- a/voxygen/src/scene/figure.rs +++ b/voxygen/src/scene/figure.rs @@ -439,7 +439,7 @@ impl FigureModelCache { fn load_wolf_head_lower(head_lower: quadruped_medium::HeadLower) -> Mesh { Self::load_mesh( match head_lower { - quadruped_medium::HeadLower::Default => "npc/wolf/head_lower.vox", + quadruped_medium::HeadLower::Default => "npc/wolf/wolf_head_lower.vox", }, Vec3::new(-7.0, -6.0, -5.5), ) From ccbacabd2f0de97acee50ddc71ec4c3250188592 Mon Sep 17 00:00:00 2001 From: timokoesters Date: Sat, 29 Jun 2019 22:51:22 +0200 Subject: [PATCH 8/8] Make agents use controller correctly --- common/src/sys/agent.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/common/src/sys/agent.rs b/common/src/sys/agent.rs index 3ff07be4ab..7ecd5fec42 100644 --- a/common/src/sys/agent.rs +++ b/common/src/sys/agent.rs @@ -41,9 +41,7 @@ impl<'a> System<'a> for Sys { let tgt_pos = tgt_pos.0 + *offset; if tgt_pos.z > pos.0.z + 1.0 { - if let Err(err) = jumps.insert(entity, Jumping) { - warn!("Inserting Jumping for an entity failed: {:?}", err,); - } + controller.jump = true; } // Move towards the target. @@ -74,9 +72,7 @@ impl<'a> System<'a> for Sys { controller.move_dir = Vec2::zero(); if rand::random::() < 0.2 { - attacks - .insert(entity, Attacking::start()) - .expect("Inserting attacking for an entity failed!"); + controller.attack = true; } false