From b9607ef405b975edb7206ed5039369c43c8133bf Mon Sep 17 00:00:00 2001 From: timokoesters Date: Wed, 17 Apr 2019 19:32:29 +0200 Subject: [PATCH] Fix #21 by checking animation history Former-commit-id: 5272d1d7aee73fc07edeb31d9f29238d19b7d229 --- client/src/lib.rs | 12 ++++++++---- common/src/comp/character.rs | 8 +++++++- common/src/comp/mod.rs | 1 + common/src/msg/client.rs | 2 +- common/src/msg/server.rs | 2 +- common/src/state.rs | 2 +- common/src/sys/control.rs | 24 ++++++++++++++++-------- server/src/lib.rs | 30 +++++++++++++++++++++++------- voxygen/src/scene/figure.rs | 6 +++--- 9 files changed, 61 insertions(+), 26 deletions(-) diff --git a/client/src/lib.rs b/client/src/lib.rs index 3e0eeaa217..291ec29fd8 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -168,8 +168,12 @@ impl Client { } // Update the server about the player's currently playing animation - if let Some(animation) = self.state.read_storage().get(self.player).cloned() { - self.postbox.send_message(ClientMsg::PlayerAnimation(animation)); + if let Some(animationHistory) = self.state.read_storage::().get(self.player).cloned() { + if let Some(last) = animationHistory.last { + if animationHistory.current != last { + self.postbox.send_message(ClientMsg::PlayerAnimation(animationHistory)); + } + } } // Request chunks from the server @@ -228,9 +232,9 @@ impl Client { }, None => {}, }, - ServerMsg::EntityAnimation { entity, animation } => match self.state.ecs().entity_from_uid(entity) { + ServerMsg::EntityAnimation { entity, animationHistory } => match self.state.ecs().entity_from_uid(entity) { Some(entity) => { - self.state.write_component(entity, animation); + self.state.write_component(entity, animationHistory); }, None => {}, }, diff --git a/common/src/comp/character.rs b/common/src/comp/character.rs index e34919236e..2ed29831f6 100644 --- a/common/src/comp/character.rs +++ b/common/src/comp/character.rs @@ -19,6 +19,12 @@ pub enum Gender { } #[derive(Copy, Clone, Debug, Serialize, Deserialize)] +pub struct AnimationHistory { + pub last: Option, + pub current: Animation, +} + +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] pub enum Animation { Idle, Run, @@ -55,6 +61,6 @@ impl Component for Character { type Storage = FlaggedStorage>; } -impl Component for Animation { +impl Component for AnimationHistory { type Storage = FlaggedStorage>; } diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index c67f27cee2..d10012c976 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -7,4 +7,5 @@ pub mod phys; pub use agent::{Agent, Control}; pub use character::Character; pub use player::Player; +pub use character::AnimationHistory; pub use character::Animation; diff --git a/common/src/msg/client.rs b/common/src/msg/client.rs index 01c35a7962..95eaadecbf 100644 --- a/common/src/msg/client.rs +++ b/common/src/msg/client.rs @@ -11,7 +11,7 @@ pub enum ClientMsg { Ping, Pong, Chat(String), - PlayerAnimation(comp::character::Animation), + PlayerAnimation(comp::character::AnimationHistory), PlayerPhysics { pos: comp::phys::Pos, vel: comp::phys::Vel, diff --git a/common/src/msg/server.rs b/common/src/msg/server.rs index 1585c5f32f..4b5a1b5517 100644 --- a/common/src/msg/server.rs +++ b/common/src/msg/server.rs @@ -25,7 +25,7 @@ pub enum ServerMsg { }, EntityAnimation { entity: u64, - animation: comp::Animation, + animationHistory: comp::AnimationHistory, }, TerrainChunkUpdate { key: Vec3, diff --git a/common/src/state.rs b/common/src/state.rs index 84a6736362..6a12cc6d7d 100644 --- a/common/src/state.rs +++ b/common/src/state.rs @@ -100,7 +100,7 @@ impl State { ecs.internal_mut().register::(); ecs.internal_mut().register::(); ecs.internal_mut().register::(); - ecs.internal_mut().register::(); + ecs.internal_mut().register::(); ecs.internal_mut().register::(); ecs.internal_mut().register::(); diff --git a/common/src/sys/control.rs b/common/src/sys/control.rs index a590e13c47..9179ea744a 100644 --- a/common/src/sys/control.rs +++ b/common/src/sys/control.rs @@ -3,7 +3,7 @@ use specs::{Join, Read, ReadStorage, System, WriteStorage, Entities}; use vek::*; // Crate -use crate::comp::{Control, Animation, phys::{Pos, Vel, Dir}}; +use crate::comp::{Control, Animation, AnimationHistory, phys::{Pos, Vel, Dir}}; // Basic ECS AI agent system pub struct Sys; @@ -13,7 +13,7 @@ impl<'a> System<'a> for Sys { Entities<'a>, WriteStorage<'a, Vel>, WriteStorage<'a, Dir>, - WriteStorage<'a, Animation>, + WriteStorage<'a, AnimationHistory>, ReadStorage<'a, Control>, ); @@ -23,12 +23,20 @@ impl<'a> System<'a> for Sys { // Apply physics to the player: acceleration and non-linear decceleration vel.0 += control.move_dir * 2.0 - vel.0.map(|e| e * e.abs() + e) * 0.03; - if control.move_dir.magnitude() > 0.01 { - dir.0 = vel.0.normalized() * Vec3::new(1.0, 1.0, 0.0); - anims.insert(entity, Animation::Run); - } else { - anims.insert(entity, Animation::Idle); - } + let animation = + if control.move_dir.magnitude() > 0.01 { + dir.0 = vel.0.normalized() * Vec3::new(1.0, 1.0, 0.0); + Animation::Run + } else { + Animation::Idle + }; + + let lastAnimation = anims.get_mut(entity).map(|h| h.current); + + anims.insert(entity, AnimationHistory { + last: lastAnimation, + current: animation, + }); } } } diff --git a/server/src/lib.rs b/server/src/lib.rs index 0eb84959b5..ba7dd7ec8e 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -266,7 +266,7 @@ impl Server { ClientMsg::Ping => client.postbox.send_message(ServerMsg::Pong), ClientMsg::Pong => {} ClientMsg::Chat(msg) => new_chat_msgs.push((entity, msg)), - ClientMsg::PlayerAnimation(animation) => state.write_component(entity, animation), + ClientMsg::PlayerAnimation(animationHistory) => state.write_component(entity, animationHistory), ClientMsg::PlayerPhysics { pos, vel, dir } => { state.write_component(entity, pos); state.write_component(entity, vel); @@ -369,15 +369,31 @@ impl Server { } // Sync animation states - for (entity, &uid, &animation) in ( + for (entity, &uid, &animationHistory) in ( &self.state.ecs().internal().entities(), &self.state.ecs().internal().read_storage::(), - &self.state.ecs().internal().read_storage::(), + &self.state.ecs().internal().read_storage::(), ).join() { - self.clients.notify_connected_except(entity, ServerMsg::EntityAnimation { - entity: uid.into(), - animation, - }); + if let Some(last) = animationHistory.last { + if animationHistory.current == last { + continue; + } + + self.clients.notify_connected_except(entity, ServerMsg::EntityAnimation { + entity: uid.into(), + animationHistory, + }); + } + } + + // Update animation last/current state + for (entity, mut animationHistory) in ( + &self.state.ecs().internal().entities(), + &mut self.state.ecs().internal().write_storage::() + ).join() { + animationHistory.last = None; + let mut new = animationHistory.clone(); + new.last = Some(new.current); } // Remove all force flags diff --git a/voxygen/src/scene/figure.rs b/voxygen/src/scene/figure.rs index 75b727b07f..02089eb724 100644 --- a/voxygen/src/scene/figure.rs +++ b/voxygen/src/scene/figure.rs @@ -83,18 +83,18 @@ impl Figures { pub fn maintain(&mut self, renderer: &mut Renderer, client: &mut Client) { let time = client.state().get_time(); let ecs = client.state_mut().ecs_mut().internal_mut(); - for (entity, pos, dir, character, animation) in ( + for (entity, pos, dir, character, animationHistory) in ( &ecs.entities(), &ecs.read_storage::(), &ecs.read_storage::(), &ecs.read_storage::(), - &ecs.read_storage::(), + &ecs.read_storage::(), ).join() { let state = self.states .entry(entity) .or_insert_with(|| FigureState::new(renderer, CharacterSkeleton::new())); - let target_skeleton = match animation { + let target_skeleton = match animationHistory.current { comp::character::Animation::Idle => IdleAnimation::update_skeleton(&mut state.skeleton, time), comp::character::Animation::Run => RunAnimation::update_skeleton(&mut state.skeleton, time), };