From 7b35f14043fe0a1f1c891c7af194729c666e1571 Mon Sep 17 00:00:00 2001 From: Imbris Date: Tue, 12 Oct 2021 22:03:18 -0400 Subject: [PATCH] Remove per entity VecDeque's of events from character StateUpdate and instead pass in external Vecs that can be pushed to (saves significant time not allocating for VecDeque::new) --- common/src/comp/character_state.rs | 168 +++++++++++++---------- common/src/comp/mod.rs | 2 +- common/src/event.rs | 3 + common/src/lib.rs | 3 +- common/src/states/basic_aura.rs | 9 +- common/src/states/basic_beam.rs | 11 +- common/src/states/basic_block.rs | 4 +- common/src/states/basic_melee.rs | 22 ++- common/src/states/basic_ranged.rs | 27 +++- common/src/states/basic_summon.rs | 7 +- common/src/states/behavior.rs | 85 ++++++++---- common/src/states/blink.rs | 6 +- common/src/states/boost.rs | 20 ++- common/src/states/charged_melee.rs | 18 ++- common/src/states/charged_ranged.rs | 9 +- common/src/states/climb.rs | 5 +- common/src/states/combo_melee.rs | 19 ++- common/src/states/dance.rs | 21 +-- common/src/states/dash_melee.rs | 4 +- common/src/states/equipping.rs | 6 +- common/src/states/glide.rs | 8 +- common/src/states/glide_wield.rs | 26 ++-- common/src/states/idle.rs | 29 ++-- common/src/states/leap_melee.rs | 6 +- common/src/states/repeater_ranged.rs | 11 +- common/src/states/roll.rs | 9 +- common/src/states/self_buff.rs | 7 +- common/src/states/shockwave.rs | 6 +- common/src/states/sit.rs | 21 +-- common/src/states/sneak.rs | 27 ++-- common/src/states/spin_melee.rs | 4 +- common/src/states/sprite_interact.rs | 8 +- common/src/states/sprite_summon.rs | 6 +- common/src/states/stunned.rs | 4 +- common/src/states/talk.rs | 21 +-- common/src/states/use_item.rs | 17 ++- common/src/states/utils.rs | 38 +++-- common/src/states/wielding.rs | 26 ++-- common/systems/src/character_behavior.rs | 42 +++--- 39 files changed, 464 insertions(+), 301 deletions(-) diff --git a/common/src/comp/character_state.rs b/common/src/comp/character_state.rs index 9d27425d39..8c312489d9 100644 --- a/common/src/comp/character_state.rs +++ b/common/src/comp/character_state.rs @@ -15,7 +15,7 @@ use crate::{ use serde::{Deserialize, Serialize}; use specs::{Component, DerefFlaggedStorage, VecStorage}; use specs_idvs::IdvStorage; -use std::collections::{BTreeMap, VecDeque}; +use std::collections::BTreeMap; use strum_macros::Display; use vek::*; @@ -31,8 +31,21 @@ pub struct StateUpdate { pub should_strafe: bool, pub queued_inputs: BTreeMap, pub removed_inputs: Vec, - pub local_events: VecDeque, - pub server_events: VecDeque, +} + +pub struct OutputEvents<'a> { + local: &'a mut Vec, + server: &'a mut Vec, +} + +impl<'a> OutputEvents<'a> { + pub fn new(local: &'a mut Vec, server: &'a mut Vec) -> Self { + Self { local, server } + } + + pub fn emit_local(&mut self, event: LocalEvent) { self.local.push(event); } + + pub fn emit_server(&mut self, event: ServerEvent) { self.server.push(event); } } impl From<&JoinData<'_>> for StateUpdate { @@ -49,8 +62,6 @@ impl From<&JoinData<'_>> for StateUpdate { character: data.character.clone(), queued_inputs: BTreeMap::new(), removed_inputs: Vec::new(), - local_events: VecDeque::new(), - server_events: VecDeque::new(), } } } @@ -246,81 +257,96 @@ impl CharacterState { std::mem::discriminant(self) == std::mem::discriminant(other) } - pub fn behavior(&self, j: &JoinData) -> StateUpdate { + pub fn behavior(&self, j: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { match &self { - CharacterState::Idle => states::idle::Data.behavior(j), - CharacterState::Talk => states::talk::Data.behavior(j), - CharacterState::Climb(data) => data.behavior(j), - CharacterState::Glide(data) => data.behavior(j), - CharacterState::GlideWield(data) => data.behavior(j), - CharacterState::Stunned(data) => data.behavior(j), - CharacterState::Sit => states::sit::Data::behavior(&states::sit::Data, j), - CharacterState::Dance => states::dance::Data::behavior(&states::dance::Data, j), - CharacterState::Sneak => states::sneak::Data::behavior(&states::sneak::Data, j), - CharacterState::BasicBlock(data) => data.behavior(j), - CharacterState::Roll(data) => data.behavior(j), - CharacterState::Wielding => states::wielding::Data.behavior(j), - CharacterState::Equipping(data) => data.behavior(j), - CharacterState::ComboMelee(data) => data.behavior(j), - CharacterState::BasicMelee(data) => data.behavior(j), - CharacterState::BasicRanged(data) => data.behavior(j), - CharacterState::Boost(data) => data.behavior(j), - CharacterState::DashMelee(data) => data.behavior(j), - CharacterState::LeapMelee(data) => data.behavior(j), - CharacterState::SpinMelee(data) => data.behavior(j), - CharacterState::ChargedMelee(data) => data.behavior(j), - CharacterState::ChargedRanged(data) => data.behavior(j), - CharacterState::RepeaterRanged(data) => data.behavior(j), - CharacterState::Shockwave(data) => data.behavior(j), - CharacterState::BasicBeam(data) => data.behavior(j), - CharacterState::BasicAura(data) => data.behavior(j), - CharacterState::Blink(data) => data.behavior(j), - CharacterState::BasicSummon(data) => data.behavior(j), - CharacterState::SelfBuff(data) => data.behavior(j), - CharacterState::SpriteSummon(data) => data.behavior(j), - CharacterState::UseItem(data) => data.behavior(j), - CharacterState::SpriteInteract(data) => data.behavior(j), + CharacterState::Idle => states::idle::Data.behavior(j, output_events), + CharacterState::Talk => states::talk::Data.behavior(j, output_events), + CharacterState::Climb(data) => data.behavior(j, output_events), + CharacterState::Glide(data) => data.behavior(j, output_events), + CharacterState::GlideWield(data) => data.behavior(j, output_events), + CharacterState::Stunned(data) => data.behavior(j, output_events), + CharacterState::Sit => { + states::sit::Data::behavior(&states::sit::Data, j, output_events) + }, + CharacterState::Dance => { + states::dance::Data::behavior(&states::dance::Data, j, output_events) + }, + CharacterState::Sneak => { + states::sneak::Data::behavior(&states::sneak::Data, j, output_events) + }, + CharacterState::BasicBlock(data) => data.behavior(j, output_events), + CharacterState::Roll(data) => data.behavior(j, output_events), + CharacterState::Wielding => states::wielding::Data.behavior(j, output_events), + CharacterState::Equipping(data) => data.behavior(j, output_events), + CharacterState::ComboMelee(data) => data.behavior(j, output_events), + CharacterState::BasicMelee(data) => data.behavior(j, output_events), + CharacterState::BasicRanged(data) => data.behavior(j, output_events), + CharacterState::Boost(data) => data.behavior(j, output_events), + CharacterState::DashMelee(data) => data.behavior(j, output_events), + CharacterState::LeapMelee(data) => data.behavior(j, output_events), + CharacterState::SpinMelee(data) => data.behavior(j, output_events), + CharacterState::ChargedMelee(data) => data.behavior(j, output_events), + CharacterState::ChargedRanged(data) => data.behavior(j, output_events), + CharacterState::RepeaterRanged(data) => data.behavior(j, output_events), + CharacterState::Shockwave(data) => data.behavior(j, output_events), + CharacterState::BasicBeam(data) => data.behavior(j, output_events), + CharacterState::BasicAura(data) => data.behavior(j, output_events), + CharacterState::Blink(data) => data.behavior(j, output_events), + CharacterState::BasicSummon(data) => data.behavior(j, output_events), + CharacterState::SelfBuff(data) => data.behavior(j, output_events), + CharacterState::SpriteSummon(data) => data.behavior(j, output_events), + CharacterState::UseItem(data) => data.behavior(j, output_events), + CharacterState::SpriteInteract(data) => data.behavior(j, output_events), } } - pub fn handle_event(&self, j: &JoinData, action: ControlAction) -> StateUpdate { + pub fn handle_event( + &self, + j: &JoinData, + output_events: &mut OutputEvents, + action: ControlAction, + ) -> StateUpdate { match &self { - CharacterState::Idle => states::idle::Data.handle_event(j, action), - CharacterState::Talk => states::talk::Data.handle_event(j, action), - CharacterState::Climb(data) => data.handle_event(j, action), - CharacterState::Glide(data) => data.handle_event(j, action), - CharacterState::GlideWield(data) => data.handle_event(j, action), - CharacterState::Stunned(data) => data.handle_event(j, action), - CharacterState::Sit => states::sit::Data::handle_event(&states::sit::Data, j, action), + CharacterState::Idle => states::idle::Data.handle_event(j, output_events, action), + CharacterState::Talk => states::talk::Data.handle_event(j, output_events, action), + CharacterState::Climb(data) => data.handle_event(j, output_events, action), + CharacterState::Glide(data) => data.handle_event(j, output_events, action), + CharacterState::GlideWield(data) => data.handle_event(j, output_events, action), + CharacterState::Stunned(data) => data.handle_event(j, output_events, action), + CharacterState::Sit => { + states::sit::Data::handle_event(&states::sit::Data, j, output_events, action) + }, CharacterState::Dance => { - states::dance::Data::handle_event(&states::dance::Data, j, action) + states::dance::Data::handle_event(&states::dance::Data, j, output_events, action) }, CharacterState::Sneak => { - states::sneak::Data::handle_event(&states::sneak::Data, j, action) + states::sneak::Data::handle_event(&states::sneak::Data, j, output_events, action) }, - CharacterState::BasicBlock(data) => data.handle_event(j, action), - CharacterState::Roll(data) => data.handle_event(j, action), - CharacterState::Wielding => states::wielding::Data.handle_event(j, action), - CharacterState::Equipping(data) => data.handle_event(j, action), - CharacterState::ComboMelee(data) => data.handle_event(j, action), - CharacterState::BasicMelee(data) => data.handle_event(j, action), - CharacterState::BasicRanged(data) => data.handle_event(j, action), - CharacterState::Boost(data) => data.handle_event(j, action), - CharacterState::DashMelee(data) => data.handle_event(j, action), - CharacterState::LeapMelee(data) => data.handle_event(j, action), - CharacterState::SpinMelee(data) => data.handle_event(j, action), - CharacterState::ChargedMelee(data) => data.handle_event(j, action), - CharacterState::ChargedRanged(data) => data.handle_event(j, action), - CharacterState::RepeaterRanged(data) => data.handle_event(j, action), - CharacterState::Shockwave(data) => data.handle_event(j, action), - CharacterState::BasicBeam(data) => data.handle_event(j, action), - CharacterState::BasicAura(data) => data.handle_event(j, action), - CharacterState::Blink(data) => data.handle_event(j, action), - CharacterState::BasicSummon(data) => data.handle_event(j, action), - CharacterState::SelfBuff(data) => data.handle_event(j, action), - CharacterState::SpriteSummon(data) => data.handle_event(j, action), - CharacterState::UseItem(data) => data.handle_event(j, action), - CharacterState::SpriteInteract(data) => data.handle_event(j, action), + CharacterState::BasicBlock(data) => data.handle_event(j, output_events, action), + CharacterState::Roll(data) => data.handle_event(j, output_events, action), + CharacterState::Wielding => { + states::wielding::Data.handle_event(j, output_events, action) + }, + CharacterState::Equipping(data) => data.handle_event(j, output_events, action), + CharacterState::ComboMelee(data) => data.handle_event(j, output_events, action), + CharacterState::BasicMelee(data) => data.handle_event(j, output_events, action), + CharacterState::BasicRanged(data) => data.handle_event(j, output_events, action), + CharacterState::Boost(data) => data.handle_event(j, output_events, action), + CharacterState::DashMelee(data) => data.handle_event(j, output_events, action), + CharacterState::LeapMelee(data) => data.handle_event(j, output_events, action), + CharacterState::SpinMelee(data) => data.handle_event(j, output_events, action), + CharacterState::ChargedMelee(data) => data.handle_event(j, output_events, action), + CharacterState::ChargedRanged(data) => data.handle_event(j, output_events, action), + CharacterState::RepeaterRanged(data) => data.handle_event(j, output_events, action), + CharacterState::Shockwave(data) => data.handle_event(j, output_events, action), + CharacterState::BasicBeam(data) => data.handle_event(j, output_events, action), + CharacterState::BasicAura(data) => data.handle_event(j, output_events, action), + CharacterState::Blink(data) => data.handle_event(j, output_events, action), + CharacterState::BasicSummon(data) => data.handle_event(j, output_events, action), + CharacterState::SelfBuff(data) => data.handle_event(j, output_events, action), + CharacterState::SpriteSummon(data) => data.handle_event(j, output_events, action), + CharacterState::UseItem(data) => data.handle_event(j, output_events, action), + CharacterState::SpriteInteract(data) => data.handle_event(j, output_events, action), } } } diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index 12575c6d71..677b5c17e2 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -8,7 +8,7 @@ pub mod anchor; #[cfg(not(target_arch = "wasm32"))] pub mod body; pub mod buff; #[cfg(not(target_arch = "wasm32"))] -mod character_state; +pub mod character_state; #[cfg(not(target_arch = "wasm32"))] pub mod chat; #[cfg(not(target_arch = "wasm32"))] pub mod combo; pub mod compass; diff --git a/common/src/event.rs b/common/src/event.rs index 4c7d1bc896..0c551ed39d 100644 --- a/common/src/event.rs +++ b/common/src/event.rs @@ -242,6 +242,9 @@ impl<'a, E> Emitter<'a, E> { pub fn emit(&mut self, event: E) { self.events.push_back(event); } pub fn append(&mut self, other: &mut VecDeque) { self.events.append(other) } + + // TODO: allow just emitting the whole vec of events at once? without copying + pub fn append_vec(&mut self, vec: Vec) { self.events.extend(vec) } } impl<'a, E> Drop for Emitter<'a, E> { diff --git a/common/src/lib.rs b/common/src/lib.rs index a337c57b88..01cd3e8dde 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -10,7 +10,8 @@ label_break_value, option_zip, trait_alias, - type_alias_impl_trait + type_alias_impl_trait, + extend_one )] /// Re-exported crates diff --git a/common/src/states/basic_aura.rs b/common/src/states/basic_aura.rs index 0c2f084c67..2ee79957b7 100644 --- a/common/src/states/basic_aura.rs +++ b/common/src/states/basic_aura.rs @@ -2,6 +2,7 @@ use crate::{ combat::GroupTarget, comp::{ aura::{AuraBuffConstructor, AuraChange, AuraKind, AuraTarget, Specifier}, + character_state::OutputEvents, CharacterState, StateUpdate, }, event::ServerEvent, @@ -52,12 +53,12 @@ pub struct Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_orientation(data, &mut update, 1.0, None); handle_move(data, &mut update, 0.8); - handle_jump(data, &mut update, 1.0); + handle_jump(data, output_events, &mut update, 1.0); match self.stage_section { StageSection::Buildup => { @@ -89,12 +90,12 @@ impl CharacterBehavior for Data { 1.0 + (self.static_data.combo_at_cast.max(1) as f32).log(2.0); }, } - update.server_events.push_front(ServerEvent::ComboChange { + output_events.emit_server(ServerEvent::ComboChange { entity: data.entity, change: -(self.static_data.combo_at_cast as i32), }); } - update.server_events.push_front(ServerEvent::Aura { + output_events.emit_server(ServerEvent::Aura { entity: data.entity, aura_change: AuraChange::Add(aura), }); diff --git a/common/src/states/basic_beam.rs b/common/src/states/basic_beam.rs index deda921aa3..ffc7b4ad2e 100644 --- a/common/src/states/basic_beam.rs +++ b/common/src/states/basic_beam.rs @@ -3,7 +3,10 @@ use crate::{ Attack, AttackDamage, AttackEffect, CombatEffect, CombatRequirement, Damage, DamageKind, DamageSource, GroupTarget, }, - comp::{beam, body::biped_large, Body, CharacterState, Ori, Pos, StateUpdate}, + comp::{ + beam, body::biped_large, character_state::OutputEvents, Body, CharacterState, Ori, Pos, + StateUpdate, + }, event::ServerEvent, states::{ behavior::{CharacterBehavior, JoinData}, @@ -60,14 +63,14 @@ pub struct Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); let ori_rate = self.static_data.ori_rate; handle_orientation(data, &mut update, ori_rate, None); handle_move(data, &mut update, 0.4); - handle_jump(data, &mut update, 1.0); + handle_jump(data, output_events, &mut update, 1.0); match self.stage_section { StageSection::Buildup => { @@ -171,7 +174,7 @@ impl CharacterBehavior for Data { let pos = Pos(data.pos.0 + body_offsets); // Create beam segment - update.server_events.push_front(ServerEvent::BeamSegment { + output_events.emit_server(ServerEvent::BeamSegment { properties, pos, ori: beam_ori, diff --git a/common/src/states/basic_block.rs b/common/src/states/basic_block.rs index 273f9d8ab3..f0719ba15e 100644 --- a/common/src/states/basic_block.rs +++ b/common/src/states/basic_block.rs @@ -1,6 +1,6 @@ use super::utils::*; use crate::{ - comp::{CharacterState, InputKind, StateUpdate}, + comp::{character_state::OutputEvents, CharacterState, InputKind, StateUpdate}, states::behavior::{CharacterBehavior, JoinData}, }; use serde::{Deserialize, Serialize}; @@ -35,7 +35,7 @@ pub struct Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_orientation(data, &mut update, 1.0, None); diff --git a/common/src/states/basic_melee.rs b/common/src/states/basic_melee.rs index 982a93f5d4..314bd4e1f7 100644 --- a/common/src/states/basic_melee.rs +++ b/common/src/states/basic_melee.rs @@ -3,7 +3,7 @@ use crate::{ Attack, AttackDamage, AttackEffect, CombatEffect, CombatRequirement, Damage, DamageKind, DamageSource, GroupTarget, Knockback, }, - comp::{tool::ToolKind, CharacterState, Melee, StateUpdate}, + comp::{character_state::OutputEvents, tool::ToolKind, CharacterState, Melee, StateUpdate}, states::{ behavior::{CharacterBehavior, JoinData}, utils::*, @@ -53,12 +53,12 @@ pub struct Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_orientation(data, &mut update, 1.0, None); handle_move(data, &mut update, 0.7); - handle_jump(data, &mut update, 1.0); + handle_jump(data, output_events, &mut update, 1.0); match self.stage_section { StageSection::Buildup => { @@ -161,7 +161,7 @@ impl CharacterBehavior for Data { } else { // Done if input_is_pressed(data, self.static_data.ability_info.input) { - reset_state(self, data, &mut update); + reset_state(self, data, output_events, &mut update); } else { update.character = CharacterState::Wielding; } @@ -184,6 +184,16 @@ impl CharacterBehavior for Data { } } -fn reset_state(data: &Data, join: &JoinData, update: &mut StateUpdate) { - handle_input(join, update, data.static_data.ability_info.input); +fn reset_state( + data: &Data, + join: &JoinData, + output_events: &mut OutputEvents, + update: &mut StateUpdate, +) { + handle_input( + join, + output_events, + update, + data.static_data.ability_info.input, + ); } diff --git a/common/src/states/basic_ranged.rs b/common/src/states/basic_ranged.rs index 2b487ba2ef..2e936d74f3 100644 --- a/common/src/states/basic_ranged.rs +++ b/common/src/states/basic_ranged.rs @@ -1,5 +1,8 @@ use crate::{ - comp::{Body, CharacterState, LightEmitter, Pos, ProjectileConstructor, StateUpdate}, + comp::{ + character_state::OutputEvents, Body, CharacterState, LightEmitter, Pos, + ProjectileConstructor, StateUpdate, + }, event::ServerEvent, states::{ behavior::{CharacterBehavior, JoinData}, @@ -45,12 +48,12 @@ pub struct Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_orientation(data, &mut update, 1.0, None); handle_move(data, &mut update, 0.3); - handle_jump(data, &mut update, 1.0); + handle_jump(data, output_events, &mut update, 1.0); match self.stage_section { StageSection::Buildup => { @@ -96,7 +99,7 @@ impl CharacterBehavior for Data { })) .unwrap_or(data.inputs.look_dir); // Tells server to create and shoot the projectile - update.server_events.push_front(ServerEvent::Shoot { + output_events.emit_server(ServerEvent::Shoot { entity: data.entity, pos, dir, @@ -121,7 +124,7 @@ impl CharacterBehavior for Data { } else { // Done if input_is_pressed(data, self.static_data.ability_info.input) { - reset_state(self, data, &mut update); + reset_state(self, data, output_events, &mut update); } else { update.character = CharacterState::Wielding; } @@ -142,6 +145,16 @@ impl CharacterBehavior for Data { } } -fn reset_state(data: &Data, join: &JoinData, update: &mut StateUpdate) { - handle_input(join, update, data.static_data.ability_info.input); +fn reset_state( + data: &Data, + join: &JoinData, + output_events: &mut OutputEvents, + update: &mut StateUpdate, +) { + handle_input( + join, + output_events, + update, + data.static_data.ability_info.input, + ); } diff --git a/common/src/states/basic_summon.rs b/common/src/states/basic_summon.rs index 9ad22acf23..cec7765b68 100644 --- a/common/src/states/basic_summon.rs +++ b/common/src/states/basic_summon.rs @@ -1,6 +1,7 @@ use crate::{ comp::{ self, + character_state::OutputEvents, inventory::loadout_builder::{self, LoadoutBuilder}, Behavior, BehaviorCapability, CharacterState, Projectile, StateUpdate, }, @@ -54,7 +55,7 @@ pub struct Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); match self.stage_section { @@ -167,7 +168,7 @@ impl CharacterBehavior for Data { }); // Send server event to create npc - update.server_events.push_front(ServerEvent::CreateNpc { + output_events.emit_server(ServerEvent::CreateNpc { pos: comp::Pos(collision_vector - Vec3::unit_z() * obstacle_z), stats, skill_set, @@ -193,7 +194,7 @@ impl CharacterBehavior for Data { }); // Send local event used for frontend shenanigans - update.local_events.push_front(LocalEvent::CreateOutcome( + output_events.emit_local(LocalEvent::CreateOutcome( Outcome::SummonedCreature { pos: data.pos.0, body, diff --git a/common/src/states/behavior.rs b/common/src/states/behavior.rs index b54ff433e6..d98f1a0b84 100644 --- a/common/src/states/behavior.rs +++ b/common/src/states/behavior.rs @@ -1,8 +1,9 @@ use crate::{ comp::{ - self, item::MaterialStatManifest, Beam, Body, CharacterState, Combo, ControlAction, - Controller, ControllerInputs, Density, Energy, Health, InputAttr, InputKind, Inventory, - InventoryAction, Mass, Melee, Ori, PhysicsState, Pos, SkillSet, StateUpdate, Stats, Vel, + self, character_state::OutputEvents, item::MaterialStatManifest, Beam, Body, + CharacterState, Combo, ControlAction, Controller, ControllerInputs, Density, Energy, + Health, InputAttr, InputKind, Inventory, InventoryAction, Mass, Melee, Ori, PhysicsState, + Pos, SkillSet, StateUpdate, Stats, Vel, }, resources::DeltaTime, terrain::TerrainGrid, @@ -12,20 +13,47 @@ use specs::{storage::FlaggedAccessMut, Entity, LazyUpdate}; use vek::*; pub trait CharacterBehavior { - fn behavior(&self, data: &JoinData) -> StateUpdate; + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate; // Impl these to provide behavior for these inputs - fn swap_equipped_weapons(&self, data: &JoinData) -> StateUpdate { StateUpdate::from(data) } - fn manipulate_loadout(&self, data: &JoinData, _inv_action: InventoryAction) -> StateUpdate { + fn swap_equipped_weapons( + &self, + data: &JoinData, + _output_events: &mut OutputEvents, + ) -> StateUpdate { + StateUpdate::from(data) + } + fn manipulate_loadout( + &self, + data: &JoinData, + _output_events: &mut OutputEvents, + _inv_action: InventoryAction, + ) -> StateUpdate { + StateUpdate::from(data) + } + fn wield(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate { + StateUpdate::from(data) + } + fn glide_wield(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate { + StateUpdate::from(data) + } + fn unwield(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate { + StateUpdate::from(data) + } + fn sit(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate { + StateUpdate::from(data) + } + fn dance(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate { + StateUpdate::from(data) + } + fn sneak(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate { + StateUpdate::from(data) + } + fn stand(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate { + StateUpdate::from(data) + } + fn talk(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate { StateUpdate::from(data) } - fn wield(&self, data: &JoinData) -> StateUpdate { StateUpdate::from(data) } - fn glide_wield(&self, data: &JoinData) -> StateUpdate { StateUpdate::from(data) } - fn unwield(&self, data: &JoinData) -> StateUpdate { StateUpdate::from(data) } - fn sit(&self, data: &JoinData) -> StateUpdate { StateUpdate::from(data) } - fn dance(&self, data: &JoinData) -> StateUpdate { StateUpdate::from(data) } - fn sneak(&self, data: &JoinData) -> StateUpdate { StateUpdate::from(data) } - fn stand(&self, data: &JoinData) -> StateUpdate { StateUpdate::from(data) } - fn talk(&self, data: &JoinData) -> StateUpdate { StateUpdate::from(data) } fn start_input( &self, data: &JoinData, @@ -45,18 +73,25 @@ pub trait CharacterBehavior { update.removed_inputs.push(input); update } - fn handle_event(&self, data: &JoinData, event: ControlAction) -> StateUpdate { + fn handle_event( + &self, + data: &JoinData, + output_events: &mut OutputEvents, + event: ControlAction, + ) -> StateUpdate { match event { - ControlAction::SwapEquippedWeapons => self.swap_equipped_weapons(data), - ControlAction::InventoryAction(inv_action) => self.manipulate_loadout(data, inv_action), - ControlAction::Wield => self.wield(data), - ControlAction::GlideWield => self.glide_wield(data), - ControlAction::Unwield => self.unwield(data), - ControlAction::Sit => self.sit(data), - ControlAction::Dance => self.dance(data), - ControlAction::Sneak => self.sneak(data), - ControlAction::Stand => self.stand(data), - ControlAction::Talk => self.talk(data), + ControlAction::SwapEquippedWeapons => self.swap_equipped_weapons(data, output_events), + ControlAction::InventoryAction(inv_action) => { + self.manipulate_loadout(data, output_events, inv_action) + }, + ControlAction::Wield => self.wield(data, output_events), + ControlAction::GlideWield => self.glide_wield(data, output_events), + ControlAction::Unwield => self.unwield(data, output_events), + ControlAction::Sit => self.sit(data, output_events), + ControlAction::Dance => self.dance(data, output_events), + ControlAction::Sneak => self.sneak(data, output_events), + ControlAction::Stand => self.stand(data, output_events), + ControlAction::Talk => self.talk(data, output_events), ControlAction::StartInput { input, target_entity, diff --git a/common/src/states/blink.rs b/common/src/states/blink.rs index fae3bbef76..24623e0673 100644 --- a/common/src/states/blink.rs +++ b/common/src/states/blink.rs @@ -1,5 +1,5 @@ use crate::{ - comp::{CharacterState, StateUpdate}, + comp::{character_state::OutputEvents, CharacterState, StateUpdate}, event::ServerEvent, states::{ behavior::{CharacterBehavior, JoinData}, @@ -34,7 +34,7 @@ pub struct Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_orientation(data, &mut update, 1.0, None); @@ -52,7 +52,7 @@ impl CharacterBehavior for Data { // provided if let Some(input_attr) = self.static_data.ability_info.input_attr { if let Some(target) = input_attr.target_entity { - update.server_events.push_front(ServerEvent::TeleportTo { + output_events.emit_server(ServerEvent::TeleportTo { entity: data.entity, target, max_range: Some(self.static_data.max_range), diff --git a/common/src/states/boost.rs b/common/src/states/boost.rs index 9323cc2f3a..4e1ca96fac 100644 --- a/common/src/states/boost.rs +++ b/common/src/states/boost.rs @@ -1,5 +1,5 @@ use crate::{ - comp::{CharacterState, StateUpdate}, + comp::{character_state::OutputEvents, CharacterState, StateUpdate}, states::{ behavior::{CharacterBehavior, JoinData}, utils::*, @@ -28,7 +28,7 @@ pub struct Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_move(data, &mut update, 1.0); @@ -47,7 +47,7 @@ impl CharacterBehavior for Data { } else { // Done if input_is_pressed(data, self.static_data.ability_info.input) { - reset_state(self, data, &mut update); + reset_state(self, data, output_events, &mut update); } else { update.vel.0 = update.vel.0.try_normalized().unwrap_or_default() * update @@ -63,6 +63,16 @@ impl CharacterBehavior for Data { } } -fn reset_state(data: &Data, join: &JoinData, update: &mut StateUpdate) { - handle_input(join, update, data.static_data.ability_info.input); +fn reset_state( + data: &Data, + join: &JoinData, + output_events: &mut OutputEvents, + update: &mut StateUpdate, +) { + handle_input( + join, + output_events, + update, + data.static_data.ability_info.input, + ); } diff --git a/common/src/states/charged_melee.rs b/common/src/states/charged_melee.rs index 5d3ca259e4..e4bc23107f 100644 --- a/common/src/states/charged_melee.rs +++ b/common/src/states/charged_melee.rs @@ -1,6 +1,6 @@ use crate::{ combat::{Attack, AttackDamage, AttackEffect, CombatEffect, CombatRequirement}, - comp::{tool::ToolKind, CharacterState, Melee, StateUpdate}, + comp::{character_state::OutputEvents, tool::ToolKind, CharacterState, Melee, StateUpdate}, event::LocalEvent, outcome::Outcome, states::{ @@ -69,12 +69,12 @@ pub struct Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_orientation(data, &mut update, 1.0, None); handle_move(data, &mut update, 0.7); - handle_jump(data, &mut update, 1.0); + handle_jump(data, output_events, &mut update, 1.0); match self.stage_section { StageSection::Charge => { @@ -190,13 +190,11 @@ impl CharacterBehavior for Data { if let Some(FrontendSpecifier::GroundCleave) = self.static_data.specifier { // Send local event used for frontend shenanigans - update.local_events.push_front(LocalEvent::CreateOutcome( - Outcome::GroundSlam { - pos: data.pos.0 - + *data.ori.look_dir() - * (data.body.max_radius() + self.static_data.range), - }, - )); + output_events.emit_local(LocalEvent::CreateOutcome(Outcome::GroundSlam { + pos: data.pos.0 + + *data.ori.look_dir() + * (data.body.max_radius() + self.static_data.range), + })); } } else if self.timer < self.static_data.swing_duration { // Swings diff --git a/common/src/states/charged_ranged.rs b/common/src/states/charged_ranged.rs index cbe3dfc482..9f5ca30b82 100644 --- a/common/src/states/charged_ranged.rs +++ b/common/src/states/charged_ranged.rs @@ -1,6 +1,7 @@ use crate::{ comp::{ - projectile::ProjectileConstructor, Body, CharacterState, LightEmitter, Pos, StateUpdate, + character_state::OutputEvents, projectile::ProjectileConstructor, Body, CharacterState, + LightEmitter, Pos, StateUpdate, }, event::ServerEvent, states::{ @@ -70,12 +71,12 @@ impl Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_orientation(data, &mut update, 1.0, None); handle_move(data, &mut update, self.static_data.move_speed); - handle_jump(data, &mut update, 1.0); + handle_jump(data, output_events, &mut update, 1.0); match self.stage_section { StageSection::Buildup => { @@ -118,7 +119,7 @@ impl CharacterBehavior for Data { crit_mult, buff_strength, ); - update.server_events.push_front(ServerEvent::Shoot { + output_events.emit_server(ServerEvent::Shoot { entity: data.entity, pos, dir: data.inputs.look_dir, diff --git a/common/src/states/climb.rs b/common/src/states/climb.rs index 0ccd3bd106..4857e40242 100644 --- a/common/src/states/climb.rs +++ b/common/src/states/climb.rs @@ -1,5 +1,6 @@ use crate::{ comp::{ + character_state::OutputEvents, skills::{ClimbSkill::*, Skill, SKILL_MODIFIERS}, CharacterState, Climb, InputKind, Ori, StateUpdate, }, @@ -54,7 +55,7 @@ impl Default for Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); // If no wall is in front of character or we stopped climbing; @@ -72,7 +73,7 @@ impl CharacterBehavior for Data { // How strong the climb boost is relative to a normal jump const CLIMB_BOOST_JUMP_FACTOR: f32 = 0.5; // They've climbed atop something, give them a boost - update.local_events.push_front(LocalEvent::Jump( + output_events.emit_local(LocalEvent::Jump( data.entity, CLIMB_BOOST_JUMP_FACTOR * impulse / data.mass.0, )); diff --git a/common/src/states/combo_melee.rs b/common/src/states/combo_melee.rs index df55b12d89..17efb030b6 100644 --- a/common/src/states/combo_melee.rs +++ b/common/src/states/combo_melee.rs @@ -1,6 +1,7 @@ use crate::{ combat::{Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement}, comp::{ + character_state::OutputEvents, tool::{Stats, ToolKind}, CharacterState, Melee, StateUpdate, }, @@ -151,7 +152,7 @@ pub struct Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_move(data, &mut update, 0.4); @@ -340,7 +341,7 @@ impl CharacterBehavior for Data { } else { // Done if input_is_pressed(data, self.static_data.ability_info.input) { - reset_state(self, data, &mut update); + reset_state(self, data, output_events, &mut update); } else { update.character = CharacterState::Wielding; } @@ -363,8 +364,18 @@ impl CharacterBehavior for Data { } } -fn reset_state(data: &Data, join: &JoinData, update: &mut StateUpdate) { - handle_input(join, update, data.static_data.ability_info.input); +fn reset_state( + data: &Data, + join: &JoinData, + output_events: &mut OutputEvents, + update: &mut StateUpdate, +) { + handle_input( + join, + output_events, + update, + data.static_data.ability_info.input, + ); if let CharacterState::ComboMelee(c) = &mut update.character { c.stage = (data.stage % data.static_data.num_stages) + 1; diff --git a/common/src/states/dance.rs b/common/src/states/dance.rs index 8a13b84d10..ccaf6a4c39 100644 --- a/common/src/states/dance.rs +++ b/common/src/states/dance.rs @@ -1,6 +1,6 @@ use super::utils::*; use crate::{ - comp::{CharacterState, InventoryAction, StateUpdate}, + comp::{character_state::OutputEvents, CharacterState, InventoryAction, StateUpdate}, states::behavior::{CharacterBehavior, JoinData}, }; use serde::{Deserialize, Serialize}; @@ -9,11 +9,11 @@ use serde::{Deserialize, Serialize}; pub struct Data; impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_wield(data, &mut update); - handle_jump(data, &mut update, 1.0); + handle_jump(data, output_events, &mut update, 1.0); // Try to Fall/Stand up/Move if data.physics.on_ground.is_none() || data.inputs.move_dir.magnitude_squared() > 0.0 { @@ -23,25 +23,30 @@ impl CharacterBehavior for Data { update } - fn manipulate_loadout(&self, data: &JoinData, inv_action: InventoryAction) -> StateUpdate { + fn manipulate_loadout( + &self, + data: &JoinData, + output_events: &mut OutputEvents, + inv_action: InventoryAction, + ) -> StateUpdate { let mut update = StateUpdate::from(data); - handle_manipulate_loadout(data, &mut update, inv_action); + handle_manipulate_loadout(data, output_events, &mut update, inv_action); update } - fn wield(&self, data: &JoinData) -> StateUpdate { + fn wield(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_wield(data, &mut update); update } - fn sit(&self, data: &JoinData) -> StateUpdate { + fn sit(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_sit(data, &mut update); update } - fn stand(&self, data: &JoinData) -> StateUpdate { + fn stand(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); // Try to Fall/Stand up/Move update.character = CharacterState::Idle; diff --git a/common/src/states/dash_melee.rs b/common/src/states/dash_melee.rs index efe2ddcfdc..d009305cb8 100644 --- a/common/src/states/dash_melee.rs +++ b/common/src/states/dash_melee.rs @@ -1,6 +1,6 @@ use crate::{ combat::{Attack, AttackDamage, AttackEffect, CombatEffect, CombatRequirement}, - comp::{tool::ToolKind, CharacterState, Melee, StateUpdate}, + comp::{character_state::OutputEvents, tool::ToolKind, CharacterState, Melee, StateUpdate}, states::{ behavior::{CharacterBehavior, JoinData}, utils::*, @@ -74,7 +74,7 @@ pub struct Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_move(data, &mut update, 0.1); diff --git a/common/src/states/equipping.rs b/common/src/states/equipping.rs index 609acf48ae..78061755c6 100644 --- a/common/src/states/equipping.rs +++ b/common/src/states/equipping.rs @@ -1,6 +1,6 @@ use super::utils::*; use crate::{ - comp::{CharacterState, StateUpdate}, + comp::{character_state::OutputEvents, CharacterState, StateUpdate}, states::behavior::{CharacterBehavior, JoinData}, }; use serde::{Deserialize, Serialize}; @@ -23,12 +23,12 @@ pub struct Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_orientation(data, &mut update, 1.0, None); handle_move(data, &mut update, 1.0); - handle_jump(data, &mut update, 1.0); + handle_jump(data, output_events, &mut update, 1.0); if self.timer < self.static_data.buildup_duration { // Draw weapon diff --git a/common/src/states/glide.rs b/common/src/states/glide.rs index 399110dc3c..1c66e519cf 100644 --- a/common/src/states/glide.rs +++ b/common/src/states/glide.rs @@ -1,8 +1,8 @@ use super::utils::handle_climb; use crate::{ comp::{ - fluid_dynamics::angle_of_attack, inventory::slot::EquipSlot, CharacterState, Ori, - StateUpdate, Vel, + character_state::OutputEvents, fluid_dynamics::angle_of_attack, inventory::slot::EquipSlot, + CharacterState, Ori, StateUpdate, Vel, }, states::{ behavior::{CharacterBehavior, JoinData}, @@ -73,7 +73,7 @@ impl Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); // If player is on ground, end glide @@ -199,7 +199,7 @@ impl CharacterBehavior for Data { update } - fn unwield(&self, data: &JoinData) -> StateUpdate { + fn unwield(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); update.character = CharacterState::Idle; update diff --git a/common/src/states/glide_wield.rs b/common/src/states/glide_wield.rs index 88da23275b..961c9bb2aa 100644 --- a/common/src/states/glide_wield.rs +++ b/common/src/states/glide_wield.rs @@ -1,6 +1,9 @@ use super::utils::*; use crate::{ - comp::{slot::EquipSlot, CharacterState, InventoryAction, Ori, StateUpdate}, + comp::{ + character_state::OutputEvents, slot::EquipSlot, CharacterState, InventoryAction, Ori, + StateUpdate, + }, states::{ behavior::{CharacterBehavior, JoinData}, glide, @@ -32,12 +35,12 @@ impl From<&JoinData<'_>> for Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_orientation(data, &mut update, 1.0, None); handle_move(data, &mut update, 1.0); - handle_jump(data, &mut update, 1.0); + handle_jump(data, output_events, &mut update, 1.0); handle_dodge_input(data, &mut update); handle_wield(data, &mut update); @@ -76,31 +79,36 @@ impl CharacterBehavior for Data { update } - fn manipulate_loadout(&self, data: &JoinData, inv_action: InventoryAction) -> StateUpdate { + fn manipulate_loadout( + &self, + data: &JoinData, + output_events: &mut OutputEvents, + inv_action: InventoryAction, + ) -> StateUpdate { let mut update = StateUpdate::from(data); - handle_manipulate_loadout(data, &mut update, inv_action); + handle_manipulate_loadout(data, output_events, &mut update, inv_action); update } - fn unwield(&self, data: &JoinData) -> StateUpdate { + fn unwield(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); update.character = CharacterState::Idle; update } - fn sit(&self, data: &JoinData) -> StateUpdate { + fn sit(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_sit(data, &mut update); update } - fn dance(&self, data: &JoinData) -> StateUpdate { + fn dance(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_dance(data, &mut update); update } - fn sneak(&self, data: &JoinData) -> StateUpdate { + fn sneak(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_sneak(data, &mut update); update diff --git a/common/src/states/idle.rs b/common/src/states/idle.rs index d1f02390b1..43b95c996c 100644 --- a/common/src/states/idle.rs +++ b/common/src/states/idle.rs @@ -1,18 +1,18 @@ use super::utils::*; use crate::{ - comp::{InventoryAction, StateUpdate}, + comp::{character_state::OutputEvents, InventoryAction, StateUpdate}, states::behavior::{CharacterBehavior, JoinData}, }; pub struct Data; impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_orientation(data, &mut update, 1.0, None); handle_move(data, &mut update, 1.0); - handle_jump(data, &mut update, 1.0); + handle_jump(data, output_events, &mut update, 1.0); handle_wield(data, &mut update); handle_climb(data, &mut update); handle_dodge_input(data, &mut update); @@ -20,49 +20,54 @@ impl CharacterBehavior for Data { update } - fn swap_equipped_weapons(&self, data: &JoinData) -> StateUpdate { + fn swap_equipped_weapons(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_swap_equipped_weapons(data, &mut update); update } - fn manipulate_loadout(&self, data: &JoinData, inv_action: InventoryAction) -> StateUpdate { + fn manipulate_loadout( + &self, + data: &JoinData, + output_events: &mut OutputEvents, + inv_action: InventoryAction, + ) -> StateUpdate { let mut update = StateUpdate::from(data); - handle_manipulate_loadout(data, &mut update, inv_action); + handle_manipulate_loadout(data, output_events, &mut update, inv_action); update } - fn wield(&self, data: &JoinData) -> StateUpdate { + fn wield(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_wield(data, &mut update); update } - fn glide_wield(&self, data: &JoinData) -> StateUpdate { + fn glide_wield(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_glide_wield(data, &mut update); update } - fn sit(&self, data: &JoinData) -> StateUpdate { + fn sit(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_sit(data, &mut update); update } - fn dance(&self, data: &JoinData) -> StateUpdate { + fn dance(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_dance(data, &mut update); update } - fn sneak(&self, data: &JoinData) -> StateUpdate { + fn sneak(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_sneak(data, &mut update); update } - fn talk(&self, data: &JoinData) -> StateUpdate { + fn talk(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_talk(data, &mut update); update diff --git a/common/src/states/leap_melee.rs b/common/src/states/leap_melee.rs index bc9f09be6b..2c0b773cb2 100644 --- a/common/src/states/leap_melee.rs +++ b/common/src/states/leap_melee.rs @@ -1,6 +1,6 @@ use crate::{ combat::{Attack, AttackDamage, AttackEffect, CombatEffect, CombatRequirement}, - comp::{tool::ToolKind, CharacterState, Melee, StateUpdate}, + comp::{character_state::OutputEvents, tool::ToolKind, CharacterState, Melee, StateUpdate}, states::{ behavior::{CharacterBehavior, JoinData}, utils::{StageSection, *}, @@ -57,12 +57,12 @@ pub struct Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_orientation(data, &mut update, 1.0, None); handle_move(data, &mut update, 0.3); - handle_jump(data, &mut update, 1.0); + handle_jump(data, output_events, &mut update, 1.0); match self.stage_section { // Delay before leaping into the air diff --git a/common/src/states/repeater_ranged.rs b/common/src/states/repeater_ranged.rs index 8e498d3ecb..180599a00f 100644 --- a/common/src/states/repeater_ranged.rs +++ b/common/src/states/repeater_ranged.rs @@ -1,5 +1,8 @@ use crate::{ - comp::{Body, CharacterState, LightEmitter, Pos, ProjectileConstructor, StateUpdate}, + comp::{ + character_state::OutputEvents, Body, CharacterState, LightEmitter, Pos, + ProjectileConstructor, StateUpdate, + }, event::ServerEvent, states::{ behavior::{CharacterBehavior, JoinData}, @@ -49,7 +52,7 @@ pub struct Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_orientation(data, &mut update, 1.0, None); handle_move(data, &mut update, 0.3); @@ -97,7 +100,7 @@ impl CharacterBehavior for Data { crit_mult, buff_strength, ); - update.server_events.push_front(ServerEvent::Shoot { + output_events.emit_server(ServerEvent::Shoot { entity: data.entity, pos, dir: data.inputs.look_dir, @@ -109,7 +112,7 @@ impl CharacterBehavior for Data { }); // Removes energy from character when arrow is fired - update.server_events.push_front(ServerEvent::EnergyChange { + output_events.emit_server(ServerEvent::EnergyChange { entity: data.entity, change: -self.static_data.energy_cost, }); diff --git a/common/src/states/roll.rs b/common/src/states/roll.rs index d91e0526f9..d87d599a41 100644 --- a/common/src/states/roll.rs +++ b/common/src/states/roll.rs @@ -1,6 +1,7 @@ use crate::{ comp::{ buff::{BuffChange, BuffKind}, + character_state::OutputEvents, CharacterState, InputKind, StateUpdate, }, event::ServerEvent, @@ -47,7 +48,7 @@ pub struct Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); // You should not be able to strafe while rolling @@ -67,7 +68,7 @@ impl CharacterBehavior for Data { }); } else { // Remove burning effect if active - update.server_events.push_front(ServerEvent::Buff { + output_events.emit_server(ServerEvent::Buff { entity: data.entity, buff_change: BuffChange::RemoveByKind(BuffKind::Burning), }); @@ -109,7 +110,7 @@ impl CharacterBehavior for Data { handle_move(data, &mut update, 1.0); // Allows for jumps to interrupt recovery in roll if self.timer < self.static_data.recover_duration - && !handle_jump(data, &mut update, 1.5) + && !handle_jump(data, output_events, &mut update, 1.5) { // Recover update.character = CharacterState::Roll(Data { @@ -120,7 +121,7 @@ impl CharacterBehavior for Data { // Done if let Some((input, stage)) = self.was_combo { if input_is_pressed(data, input) { - handle_input(data, &mut update, input); + handle_input(data, output_events, &mut update, input); // If other states are introduced that progress through stages, add them // here if let CharacterState::ComboMelee(c) = &mut update.character { diff --git a/common/src/states/self_buff.rs b/common/src/states/self_buff.rs index 6f60e283d7..b8a3bd1d4a 100644 --- a/common/src/states/self_buff.rs +++ b/common/src/states/self_buff.rs @@ -1,6 +1,7 @@ use crate::{ comp::{ buff::{Buff, BuffChange, BuffData, BuffKind, BuffSource}, + character_state::OutputEvents, CharacterState, StateUpdate, }, event::ServerEvent, @@ -43,11 +44,11 @@ pub struct Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_move(data, &mut update, 0.8); - handle_jump(data, &mut update, 1.0); + handle_jump(data, output_events, &mut update, 1.0); match self.stage_section { StageSection::Buildup => { @@ -68,7 +69,7 @@ impl CharacterBehavior for Data { Vec::new(), BuffSource::Character { by: *data.uid }, ); - update.server_events.push_front(ServerEvent::Buff { + output_events.emit_server(ServerEvent::Buff { entity: data.entity, buff_change: BuffChange::Add(buff), }); diff --git a/common/src/states/shockwave.rs b/common/src/states/shockwave.rs index 70d3eee546..d7ba8a66b2 100644 --- a/common/src/states/shockwave.rs +++ b/common/src/states/shockwave.rs @@ -3,7 +3,7 @@ use crate::{ Attack, AttackDamage, AttackEffect, CombatEffect, CombatRequirement, Damage, DamageKind, DamageSource, GroupTarget, Knockback, }, - comp::{shockwave, CharacterState, StateUpdate}, + comp::{character_state::OutputEvents, shockwave, CharacterState, StateUpdate}, event::ServerEvent, states::{ behavior::{CharacterBehavior, JoinData}, @@ -62,7 +62,7 @@ pub struct Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_orientation(data, &mut update, 1.0, None); @@ -117,7 +117,7 @@ impl CharacterBehavior for Data { owner: Some(*data.uid), specifier: self.static_data.specifier, }; - update.server_events.push_front(ServerEvent::Shockwave { + output_events.emit_server(ServerEvent::Shockwave { properties, pos: *data.pos, ori: *data.ori, diff --git a/common/src/states/sit.rs b/common/src/states/sit.rs index afafb3e743..cb8183f196 100644 --- a/common/src/states/sit.rs +++ b/common/src/states/sit.rs @@ -1,6 +1,6 @@ use super::utils::*; use crate::{ - comp::{CharacterState, InventoryAction, StateUpdate}, + comp::{character_state::OutputEvents, CharacterState, InventoryAction, StateUpdate}, states::behavior::{CharacterBehavior, JoinData}, }; use serde::{Deserialize, Serialize}; @@ -9,11 +9,11 @@ use serde::{Deserialize, Serialize}; pub struct Data; impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_wield(data, &mut update); - handle_jump(data, &mut update, 1.0); + handle_jump(data, output_events, &mut update, 1.0); // Try to Fall/Stand up/Move if data.physics.on_ground.is_none() || data.inputs.move_dir.magnitude_squared() > 0.0 { @@ -23,25 +23,30 @@ impl CharacterBehavior for Data { update } - fn manipulate_loadout(&self, data: &JoinData, inv_action: InventoryAction) -> StateUpdate { + fn manipulate_loadout( + &self, + data: &JoinData, + output_events: &mut OutputEvents, + inv_action: InventoryAction, + ) -> StateUpdate { let mut update = StateUpdate::from(data); - handle_manipulate_loadout(data, &mut update, inv_action); + handle_manipulate_loadout(data, output_events, &mut update, inv_action); update } - fn wield(&self, data: &JoinData) -> StateUpdate { + fn wield(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_wield(data, &mut update); update } - fn dance(&self, data: &JoinData) -> StateUpdate { + fn dance(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_dance(data, &mut update); update } - fn stand(&self, data: &JoinData) -> StateUpdate { + fn stand(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); // Try to Fall/Stand up/Move update.character = CharacterState::Idle; diff --git a/common/src/states/sneak.rs b/common/src/states/sneak.rs index 537c7a9836..d92f40f9fa 100644 --- a/common/src/states/sneak.rs +++ b/common/src/states/sneak.rs @@ -1,18 +1,18 @@ use super::utils::*; use crate::{ - comp::{CharacterState, InventoryAction, StateUpdate}, + comp::{character_state::OutputEvents, CharacterState, InventoryAction, StateUpdate}, states::behavior::{CharacterBehavior, JoinData}, }; pub struct Data; impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_orientation(data, &mut update, 1.0, None); handle_move(data, &mut update, 0.4); - handle_jump(data, &mut update, 1.0); + handle_jump(data, output_events, &mut update, 1.0); handle_wield(data, &mut update); handle_climb(data, &mut update); handle_dodge_input(data, &mut update); @@ -25,43 +25,48 @@ impl CharacterBehavior for Data { update } - fn swap_equipped_weapons(&self, data: &JoinData) -> StateUpdate { + fn swap_equipped_weapons(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_swap_equipped_weapons(data, &mut update); update } - fn manipulate_loadout(&self, data: &JoinData, inv_action: InventoryAction) -> StateUpdate { + fn manipulate_loadout( + &self, + data: &JoinData, + output_events: &mut OutputEvents, + inv_action: InventoryAction, + ) -> StateUpdate { let mut update = StateUpdate::from(data); - handle_manipulate_loadout(data, &mut update, inv_action); + handle_manipulate_loadout(data, output_events, &mut update, inv_action); update } - fn wield(&self, data: &JoinData) -> StateUpdate { + fn wield(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_wield(data, &mut update); update } - fn glide_wield(&self, data: &JoinData) -> StateUpdate { + fn glide_wield(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_glide_wield(data, &mut update); update } - fn sit(&self, data: &JoinData) -> StateUpdate { + fn sit(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_sit(data, &mut update); update } - fn dance(&self, data: &JoinData) -> StateUpdate { + fn dance(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_dance(data, &mut update); update } - fn stand(&self, data: &JoinData) -> StateUpdate { + fn stand(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); update.character = CharacterState::Idle; update diff --git a/common/src/states/spin_melee.rs b/common/src/states/spin_melee.rs index 5baf929409..5ec0e2c88d 100644 --- a/common/src/states/spin_melee.rs +++ b/common/src/states/spin_melee.rs @@ -3,7 +3,7 @@ use crate::{ Attack, AttackDamage, AttackEffect, CombatEffect, CombatRequirement, Damage, DamageKind, DamageSource, GroupTarget, Knockback, }, - comp::{tool::ToolKind, CharacterState, Melee, StateUpdate}, + comp::{character_state::OutputEvents, tool::ToolKind, CharacterState, Melee, StateUpdate}, consts::GRAVITY, states::{ behavior::{CharacterBehavior, JoinData}, @@ -71,7 +71,7 @@ pub struct Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); match self.static_data.movement_behavior { diff --git a/common/src/states/sprite_interact.rs b/common/src/states/sprite_interact.rs index e34b34cb04..e825d519b8 100644 --- a/common/src/states/sprite_interact.rs +++ b/common/src/states/sprite_interact.rs @@ -1,6 +1,6 @@ use super::utils::*; use crate::{ - comp::{CharacterState, InventoryManip, StateUpdate}, + comp::{character_state::OutputEvents, CharacterState, InventoryManip, StateUpdate}, event::ServerEvent, states::behavior::{CharacterBehavior, JoinData}, terrain::SpriteKind, @@ -41,7 +41,7 @@ pub struct Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); let ori_dir = Dir::from_unnormalized(Vec3::from( @@ -93,9 +93,7 @@ impl CharacterBehavior for Data { } else { // Create inventory manipulation event let inv_manip = InventoryManip::Collect(self.static_data.sprite_pos); - update - .server_events - .push_front(ServerEvent::InventoryManip(data.entity, inv_manip)); + output_events.emit_server(ServerEvent::InventoryManip(data.entity, inv_manip)); // Done if self.static_data.was_wielded { update.character = CharacterState::Wielding; diff --git a/common/src/states/sprite_summon.rs b/common/src/states/sprite_summon.rs index df354f1013..2a81fe8f44 100644 --- a/common/src/states/sprite_summon.rs +++ b/common/src/states/sprite_summon.rs @@ -1,5 +1,5 @@ use crate::{ - comp::{CharacterState, StateUpdate}, + comp::{character_state::OutputEvents, CharacterState, StateUpdate}, event::ServerEvent, spiral::Spiral2d, states::{ @@ -47,7 +47,7 @@ pub struct Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); match self.stage_section { @@ -119,7 +119,7 @@ impl CharacterBehavior for Data { Vec3::new(sprite_pos.x as i32, sprite_pos.y as i32, z); // Send server event to create sprite - update.server_events.push_front(ServerEvent::CreateSprite { + output_events.emit_server(ServerEvent::CreateSprite { pos: sprite_pos, sprite: self.static_data.sprite, }); diff --git a/common/src/states/stunned.rs b/common/src/states/stunned.rs index 97bd5e7937..0641ce0ad4 100644 --- a/common/src/states/stunned.rs +++ b/common/src/states/stunned.rs @@ -1,6 +1,6 @@ use super::utils::*; use crate::{ - comp::{CharacterState, PoiseState, StateUpdate}, + comp::{character_state::OutputEvents, CharacterState, PoiseState, StateUpdate}, states::behavior::{CharacterBehavior, JoinData}, }; use serde::{Deserialize, Serialize}; @@ -33,7 +33,7 @@ pub struct Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_orientation(data, &mut update, 1.0, None); diff --git a/common/src/states/talk.rs b/common/src/states/talk.rs index 59abfc8e69..b069e2dfd8 100644 --- a/common/src/states/talk.rs +++ b/common/src/states/talk.rs @@ -1,6 +1,6 @@ use super::utils::*; use crate::{ - comp::{CharacterState, InventoryAction, StateUpdate}, + comp::{character_state::OutputEvents, CharacterState, InventoryAction, StateUpdate}, states::behavior::{CharacterBehavior, JoinData}, }; use serde::{Deserialize, Serialize}; @@ -11,7 +11,7 @@ const TURN_RATE: f32 = 40.0; pub struct Data; impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_wield(data, &mut update); @@ -20,33 +20,38 @@ impl CharacterBehavior for Data { update } - fn manipulate_loadout(&self, data: &JoinData, inv_action: InventoryAction) -> StateUpdate { + fn manipulate_loadout( + &self, + data: &JoinData, + output_events: &mut OutputEvents, + inv_action: InventoryAction, + ) -> StateUpdate { let mut update = StateUpdate::from(data); - handle_manipulate_loadout(data, &mut update, inv_action); + handle_manipulate_loadout(data, output_events, &mut update, inv_action); update } - fn wield(&self, data: &JoinData) -> StateUpdate { + fn wield(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_wield(data, &mut update); update } - fn sit(&self, data: &JoinData) -> StateUpdate { + fn sit(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); update.character = CharacterState::Idle; attempt_sit(data, &mut update); update } - fn dance(&self, data: &JoinData) -> StateUpdate { + fn dance(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); update.character = CharacterState::Idle; attempt_dance(data, &mut update); update } - fn stand(&self, data: &JoinData) -> StateUpdate { + fn stand(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); // Try to Fall/Stand up/Move update.character = CharacterState::Idle; diff --git a/common/src/states/use_item.rs b/common/src/states/use_item.rs index 10d490eec2..db56d7f6a5 100644 --- a/common/src/states/use_item.rs +++ b/common/src/states/use_item.rs @@ -2,6 +2,7 @@ use super::utils::*; use crate::{ comp::{ buff::{BuffChange, BuffKind}, + character_state::OutputEvents, inventory::{ item::{ConsumableKind, ItemKind}, slot::{InvSlotId, Slot}, @@ -47,7 +48,7 @@ pub struct Data { } impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); match self.static_data.item_kind { @@ -86,7 +87,7 @@ impl CharacterBehavior for Data { }); if let UsePoint::BuildupUse = use_point { // Create inventory manipulation event - use_item(data, &mut update, self); + use_item(data, output_events, self); } } }, @@ -107,7 +108,7 @@ impl CharacterBehavior for Data { }); if let UsePoint::UseRecover = use_point { // Create inventory manipulation event - use_item(data, &mut update, self); + use_item(data, output_events, self); } } }, @@ -141,11 +142,11 @@ impl CharacterBehavior for Data { if matches!(update.character, CharacterState::Roll(_)) { // Remove potion/saturation effect if left the use item state early by rolling - update.server_events.push_front(ServerEvent::Buff { + output_events.emit_server(ServerEvent::Buff { entity: data.entity, buff_change: BuffChange::RemoveByKind(BuffKind::Potion), }); - update.server_events.push_front(ServerEvent::Buff { + output_events.emit_server(ServerEvent::Buff { entity: data.entity, buff_change: BuffChange::RemoveByKind(BuffKind::Saturation), }); @@ -201,7 +202,7 @@ enum UsePoint { UseRecover, } -fn use_item(data: &JoinData, update: &mut StateUpdate, state: &Data) { +fn use_item(data: &JoinData, output_events: &mut OutputEvents, state: &Data) { // Check if the same item is in the slot let item_is_same = data .inventory @@ -212,8 +213,6 @@ fn use_item(data: &JoinData, update: &mut StateUpdate, state: &Data) { if item_is_same { // Create inventory manipulation event let inv_manip = InventoryManip::Use(Slot::Inventory(state.static_data.inv_slot)); - update - .server_events - .push_front(ServerEvent::InventoryManip(data.entity, inv_manip)); + output_events.emit_server(ServerEvent::InventoryManip(data.entity, inv_manip)); } } diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index 0a4f599120..5e35f043a5 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -3,6 +3,7 @@ use crate::{ combat, comp::{ biped_large, biped_small, + character_state::OutputEvents, inventory::slot::{EquipSlot, Slot}, item::{Hands, ItemKind, Tool, ToolKind}, quadruped_low, quadruped_medium, quadruped_small, @@ -632,6 +633,7 @@ pub fn attempt_swap_equipped_weapons(data: &JoinData<'_>, update: &mut StateUpda /// Handles inventory manipulations that affect the loadout pub fn handle_manipulate_loadout( data: &JoinData<'_>, + output_events: &mut OutputEvents, update: &mut StateUpdate, inv_action: InventoryAction, ) { @@ -664,9 +666,8 @@ pub fn handle_manipulate_loadout( }); } else { // Else emit inventory action instantnaneously - update - .server_events - .push_front(ServerEvent::InventoryManip(data.entity, inv_action.into())); + output_events + .emit_server(ServerEvent::InventoryManip(data.entity, inv_action.into())); } }, InventoryAction::Collect(sprite_pos) => { @@ -773,9 +774,7 @@ pub fn handle_manipulate_loadout( }, _ => { // Else just do event instantaneously - update - .server_events - .push_front(ServerEvent::InventoryManip(data.entity, inv_action.into())); + output_events.emit_server(ServerEvent::InventoryManip(data.entity, inv_action.into())); }, } } @@ -798,12 +797,18 @@ pub fn attempt_glide_wield(data: &JoinData<'_>, update: &mut StateUpdate) { } /// Checks that player can jump and sends jump event if so -pub fn handle_jump(data: &JoinData<'_>, update: &mut StateUpdate, strength: f32) -> bool { +pub fn handle_jump( + data: &JoinData<'_>, + output_events: &mut OutputEvents, + // TODO: remove? + _update: &mut StateUpdate, + strength: f32, +) -> bool { (input_is_pressed(data, InputKind::Jump) && data.physics.on_ground.is_some()) .then(|| data.body.jump_impulse()) .flatten() .map(|impulse| { - update.local_events.push_front(LocalEvent::Jump( + output_events.emit_local(LocalEvent::Jump( data.entity, strength * impulse / data.mass.0 * data.stats.move_speed_modifier, )); @@ -881,24 +886,33 @@ pub fn handle_ability_input(data: &JoinData<'_>, update: &mut StateUpdate) { } } -pub fn handle_input(data: &JoinData<'_>, update: &mut StateUpdate, input: InputKind) { +pub fn handle_input( + data: &JoinData<'_>, + output_events: &mut OutputEvents, + update: &mut StateUpdate, + input: InputKind, +) { match input { InputKind::Primary | InputKind::Secondary | InputKind::Ability(_) => { handle_ability(data, update, input) }, InputKind::Roll => handle_dodge_input(data, update), InputKind::Jump => { - handle_jump(data, update, 1.0); + handle_jump(data, output_events, update, 1.0); }, InputKind::Block => handle_block_input(data, update), InputKind::Fly => {}, } } -pub fn attempt_input(data: &JoinData<'_>, update: &mut StateUpdate) { +pub fn attempt_input( + data: &JoinData<'_>, + output_events: &mut OutputEvents, + update: &mut StateUpdate, +) { // TODO: look into using first() when it becomes stable if let Some(input) = data.controller.queued_inputs.keys().next() { - handle_input(data, update, *input); + handle_input(data, output_events, update, *input); } } diff --git a/common/src/states/wielding.rs b/common/src/states/wielding.rs index 68c90aa4fd..7c7fd20993 100644 --- a/common/src/states/wielding.rs +++ b/common/src/states/wielding.rs @@ -1,6 +1,7 @@ use super::utils::*; use crate::{ comp::{ + character_state::OutputEvents, slot::{EquipSlot, Slot}, CharacterState, InventoryAction, StateUpdate, }, @@ -10,24 +11,29 @@ use crate::{ pub struct Data; impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData) -> StateUpdate { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); handle_orientation(data, &mut update, 1.0, None); handle_move(data, &mut update, 1.0); handle_climb(data, &mut update); - attempt_input(data, &mut update); + attempt_input(data, output_events, &mut update); update } - fn swap_equipped_weapons(&self, data: &JoinData) -> StateUpdate { + fn swap_equipped_weapons(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_swap_equipped_weapons(data, &mut update); update } - fn manipulate_loadout(&self, data: &JoinData, inv_action: InventoryAction) -> StateUpdate { + fn manipulate_loadout( + &self, + data: &JoinData, + output_events: &mut OutputEvents, + inv_action: InventoryAction, + ) -> StateUpdate { let mut update = StateUpdate::from(data); match inv_action { InventoryAction::Drop(EquipSlot::ActiveMainhand | EquipSlot::ActiveOffhand) @@ -40,35 +46,35 @@ impl CharacterBehavior for Data { }, _ => (), } - handle_manipulate_loadout(data, &mut update, inv_action); + handle_manipulate_loadout(data, output_events, &mut update, inv_action); update } - fn glide_wield(&self, data: &JoinData) -> StateUpdate { + fn glide_wield(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_glide_wield(data, &mut update); update } - fn unwield(&self, data: &JoinData) -> StateUpdate { + fn unwield(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); update.character = CharacterState::Idle; update } - fn sit(&self, data: &JoinData) -> StateUpdate { + fn sit(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_sit(data, &mut update); update } - fn dance(&self, data: &JoinData) -> StateUpdate { + fn dance(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_dance(data, &mut update); update } - fn sneak(&self, data: &JoinData) -> StateUpdate { + fn sneak(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); attempt_sneak(data, &mut update); update diff --git a/common/systems/src/character_behavior.rs b/common/systems/src/character_behavior.rs index d3ee92c2ba..2cdc3b602f 100644 --- a/common/systems/src/character_behavior.rs +++ b/common/systems/src/character_behavior.rs @@ -5,11 +5,12 @@ use specs::{ use common::{ comp::{ - self, inventory::item::MaterialStatManifest, Beam, Body, CharacterState, Combo, Controller, - Density, Energy, Health, Inventory, InventoryManip, Mass, Melee, Mounting, Ori, - PhysicsState, Poise, PoiseState, Pos, SkillSet, StateUpdate, Stats, Vel, + self, character_state::OutputEvents, inventory::item::MaterialStatManifest, Beam, Body, + CharacterState, Combo, Controller, Density, Energy, Health, Inventory, InventoryManip, + Mass, Melee, Mounting, Ori, PhysicsState, Poise, PoiseState, Pos, SkillSet, StateUpdate, + Stats, Vel, }, - event::{Emitter, EventBus, LocalEvent, ServerEvent}, + event::{EventBus, LocalEvent, ServerEvent}, outcome::Outcome, resources::DeltaTime, states::behavior::{JoinData, JoinStruct}, @@ -87,6 +88,10 @@ impl<'a> System<'a> for Sys { let mut server_emitter = read_data.server_bus.emitter(); let mut local_emitter = read_data.local_bus.emitter(); + let mut local_events = Vec::new(); + let mut server_events = Vec::new(); + let mut output_events = OutputEvents::new(&mut local_events, &mut server_events); + for ( entity, uid, @@ -259,13 +264,8 @@ impl<'a> System<'a> for Sys { &read_data.dt, &read_data.msm, ); - let state_update = j.character.handle_event(&j, action); - Self::publish_state_update( - &mut join_struct, - state_update, - &mut local_emitter, - &mut server_emitter, - ); + let state_update = j.character.handle_event(&j, &mut output_events, action); + Self::publish_state_update(&mut join_struct, state_update, &mut output_events); } // Mounted occurs after control actions have been handled @@ -285,14 +285,12 @@ impl<'a> System<'a> for Sys { &read_data.msm, ); - let state_update = j.character.behavior(&j); - Self::publish_state_update( - &mut join_struct, - state_update, - &mut local_emitter, - &mut server_emitter, - ); + let state_update = j.character.behavior(&j, &mut output_events); + Self::publish_state_update(&mut join_struct, state_update, &mut output_events); } + + local_emitter.append_vec(local_events); + server_emitter.append_vec(server_events); } } @@ -300,12 +298,8 @@ impl Sys { fn publish_state_update( join: &mut JoinStruct, mut state_update: StateUpdate, - local_emitter: &mut Emitter, - server_emitter: &mut Emitter, + output_events: &mut OutputEvents, ) { - local_emitter.append(&mut state_update.local_events); - server_emitter.append(&mut state_update.server_events); - // TODO: if checking equality is expensive use optional field in StateUpdate if *join.char_state != state_update.character { *join.char_state = state_update.character @@ -322,7 +316,7 @@ impl Sys { join.controller.queued_inputs.remove(&input); } if state_update.swap_equipped_weapons { - server_emitter.emit(ServerEvent::InventoryManip( + output_events.emit_server(ServerEvent::InventoryManip( join.entity, InventoryManip::SwapEquippedWeapons, ));