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)

This commit is contained in:
Imbris 2021-10-12 22:03:18 -04:00
parent 43e743c2bc
commit 457ed6ac64
39 changed files with 464 additions and 301 deletions

View File

@ -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<InputKind, InputAttr>,
pub removed_inputs: Vec<InputKind>,
pub local_events: VecDeque<LocalEvent>,
pub server_events: VecDeque<ServerEvent>,
}
pub struct OutputEvents<'a> {
local: &'a mut Vec<LocalEvent>,
server: &'a mut Vec<ServerEvent>,
}
impl<'a> OutputEvents<'a> {
pub fn new(local: &'a mut Vec<LocalEvent>, server: &'a mut Vec<ServerEvent>) -> 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),
}
}
}

View File

@ -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;

View File

@ -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<E>) { 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<E>) { self.events.extend(vec) }
}
impl<'a, E> Drop for Emitter<'a, E> {

View File

@ -10,7 +10,8 @@
label_break_value,
option_zip,
trait_alias,
type_alias_impl_trait
type_alias_impl_trait,
extend_one
)]
/// Re-exported crates

View File

@ -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),
});

View File

@ -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,

View File

@ -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);

View File

@ -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,
);
}

View File

@ -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,
);
}

View File

@ -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,

View File

@ -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,

View File

@ -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),

View File

@ -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,
);
}

View File

@ -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

View File

@ -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,

View File

@ -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,
));

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,
});

View File

@ -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 {

View File

@ -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),
});

View File

@ -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,

View File

@ -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;

View File

@ -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

View File

@ -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 {

View File

@ -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;

View File

@ -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,
});

View File

@ -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);

View File

@ -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;

View File

@ -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));
}
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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<LocalEvent>,
server_emitter: &mut Emitter<ServerEvent>,
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,
));