diff --git a/common/src/comp/inventory/item.rs b/common/src/comp/inventory/item.rs index 98547f2b8e..180cbf8b86 100644 --- a/common/src/comp/inventory/item.rs +++ b/common/src/comp/inventory/item.rs @@ -28,6 +28,12 @@ pub enum ToolKind { Debug(Debug), } +impl Default for ToolKind { + fn default() -> Self { + Self::Axe + } +} + impl ToolData { pub fn equip_time(&self) -> Duration { Duration::from_millis(self.equip_time_millis) @@ -83,7 +89,7 @@ pub enum Ingredient { Grass, } -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct ToolData { pub kind: ToolKind, equip_time_millis: u64, diff --git a/common/src/comp/states/basic_attack.rs b/common/src/comp/states/basic_attack.rs index b8fbb8a09a..e090334823 100644 --- a/common/src/comp/states/basic_attack.rs +++ b/common/src/comp/states/basic_attack.rs @@ -1,6 +1,6 @@ use crate::comp::{ - ActionState::Attack, AttackKind::BasicAttack, EcsStateData, MoveState, StateHandler, - StateUpdate, ToolData, + ActionState::Attack, AttackKind::BasicAttack, EcsStateData, ItemKind::Tool, MoveState, + StateHandler, StateUpdate, ToolData, }; use crate::util::state_utils::*; use std::time::Duration; @@ -12,6 +12,18 @@ pub struct BasicAttackState { } impl StateHandler for BasicAttackState { + fn new(ecs_data: &EcsStateData) -> Self { + let tool_data = + if let Some(Tool(data)) = ecs_data.stats.equipment.main.as_ref().map(|i| &i.kind) { + data + } else { + &ToolData::default() + }; + Self { + remaining_duration: tool_data.attack_duration(), + } + } + fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate { let mut update = StateUpdate { pos: *ecs_data.pos, diff --git a/common/src/comp/states/basic_block.rs b/common/src/comp/states/basic_block.rs index 6d62a55ada..a18e10ffc5 100644 --- a/common/src/comp/states/basic_block.rs +++ b/common/src/comp/states/basic_block.rs @@ -11,6 +11,12 @@ pub struct BasicBlockState { } impl StateHandler for BasicBlockState { + fn new(ecs_data: &EcsStateData) -> Self { + Self { + active_duration: Duration::default(), + } + } + fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate { let mut update = StateUpdate { pos: *ecs_data.pos, diff --git a/common/src/comp/states/charge_attack.rs b/common/src/comp/states/charge_attack.rs index dd6854809d..c13c4853f8 100644 --- a/common/src/comp/states/charge_attack.rs +++ b/common/src/comp/states/charge_attack.rs @@ -1,6 +1,6 @@ use crate::comp::{ ActionState::Attack, AttackKind::Charge, EcsStateData, HealthChange, HealthSource, - MoveState::Run, RunState, StateHandler, StateUpdate, + ItemKind::Tool, MoveState::Run, RunState, StateHandler, StateUpdate, ToolData, }; use crate::event::ServerEvent; use crate::util::state_utils::*; @@ -16,6 +16,18 @@ pub struct ChargeAttackState { } impl StateHandler for ChargeAttackState { + fn new(ecs_data: &EcsStateData) -> Self { + let tool_data = + if let Some(Tool(data)) = ecs_data.stats.equipment.main.as_ref().map(|i| &i.kind) { + data + } else { + &ToolData::default() + }; + Self { + remaining_duration: tool_data.attack_duration(), + } + } + fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate { let mut update = StateUpdate { pos: *ecs_data.pos, diff --git a/common/src/comp/states/climb.rs b/common/src/comp/states/climb.rs index e315e7c5e2..4901084947 100644 --- a/common/src/comp/states/climb.rs +++ b/common/src/comp/states/climb.rs @@ -11,6 +11,10 @@ use vek::Lerp; pub struct ClimbState; impl StateHandler for ClimbState { + fn new(ecs_data: &EcsStateData) -> Self { + Self {} + } + fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate { let mut update = StateUpdate { pos: *ecs_data.pos, diff --git a/common/src/comp/states/fall.rs b/common/src/comp/states/fall.rs index 09619fae0e..252b208153 100644 --- a/common/src/comp/states/fall.rs +++ b/common/src/comp/states/fall.rs @@ -8,6 +8,10 @@ use vek::{Vec2, Vec3}; pub struct FallState; impl StateHandler for FallState { + fn new(ecs_data: &EcsStateData) -> Self { + Self {} + } + fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate { let mut update = StateUpdate { pos: *ecs_data.pos, diff --git a/common/src/comp/states/glide.rs b/common/src/comp/states/glide.rs index 768adbc0b5..77ea626849 100644 --- a/common/src/comp/states/glide.rs +++ b/common/src/comp/states/glide.rs @@ -9,6 +9,10 @@ use vek::{Vec2, Vec3}; pub struct GlideState; impl StateHandler for GlideState { + fn new(ecs_data: &EcsStateData) -> Self { + Self {} + } + fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate { let mut update = StateUpdate { pos: *ecs_data.pos, diff --git a/common/src/comp/states/idle.rs b/common/src/comp/states/idle.rs index 5f41308f34..6acb80357d 100644 --- a/common/src/comp/states/idle.rs +++ b/common/src/comp/states/idle.rs @@ -8,6 +8,10 @@ use std::time::Duration; pub struct IdleState; impl StateHandler for IdleState { + fn new(ecs_data: &EcsStateData) -> Self { + Self {} + } + fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate { let mut update = StateUpdate { character: *ecs_data.character, @@ -22,10 +26,10 @@ impl StateHandler for IdleState { || (ecs_data.inputs.toggle_wield.is_just_pressed() && update.character.action_state.is_equip_finished()) { - if let Some(Tool { .. }) = ecs_data.stats.equipment.main.as_ref().map(|i| &i.kind) { + if let Some(Tool(data)) = ecs_data.stats.equipment.main.as_ref().map(|i| &i.kind) { update.character.action_state = Wield(Some(WieldState { - equip_delay: Duration::from_millis(TEMP_EQUIP_DELAY), - })) + equip_delay: data.equip_time(), + })); } // else unarmed stuff? diff --git a/common/src/comp/states/jump.rs b/common/src/comp/states/jump.rs index 5581c4d796..f2aea7e393 100644 --- a/common/src/comp/states/jump.rs +++ b/common/src/comp/states/jump.rs @@ -5,6 +5,10 @@ use crate::event::LocalEvent; pub struct JumpState; impl StateHandler for JumpState { + fn new(ecs_data: &EcsStateData) -> Self { + Self {} + } + fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate { let mut update = StateUpdate { character: *ecs_data.character, diff --git a/common/src/comp/states/mod.rs b/common/src/comp/states/mod.rs index e53ec28313..4a0cac5477 100644 --- a/common/src/comp/states/mod.rs +++ b/common/src/comp/states/mod.rs @@ -54,7 +54,6 @@ use super::{ ActionState, ActionState::*, AttackKind::*, BlockKind::*, DodgeKind::*, EcsStateData, MoveState, MoveState::*, StateUpdate, }; -use std::time::Duration; /// #### A trait for implementing state `handle()`ing logic. /// _Mimics the typical OOP style state machine pattern where states implement their own behavior, @@ -74,25 +73,54 @@ use std::time::Duration; /// how the update flow occurs and is in charge of updating the ECS components. pub trait StateHandler: Default { fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate; + fn new(ecs_data: &EcsStateData) -> Self; } -// Public interface that passes EcsStateData to `StateHandle`s `handle()` fn +// fn's relating to individual `ActionState`s +// or passing data from system to handlers impl ActionState { - /// Passes handle to variant or subvariant handlers + /// Passes data to variant or subvariant handlers + /// States contain `Option`s, and will be + /// `None` if state data has not been initialized. So we have to + /// check and intialize new state data if so. pub fn update(&self, ecs_data: &EcsStateData) -> StateUpdate { match self { Attack(kind) => match kind { - BasicAttack(Some(state)) => state.handle(&ecs_data), - Charge(Some(state)) => state.handle(&ecs_data), + BasicAttack(opt_state) => opt_state + // If data hasn't been initialized, initialize a new one + .unwrap_or_else(|| BasicAttackState::new(ecs_data)) + // Call handler + .handle(ecs_data), + Charge(opt_state) => opt_state + // If data hasn't been initialized, initialize a new one + .unwrap_or_else(|| ChargeAttackState::new(ecs_data)) + // Call handler + .handle(ecs_data), }, Block(kind) => match kind { - BasicBlock(Some(state)) => state.handle(&ecs_data), + BasicBlock(opt_state) => opt_state + // If data hasn't been initialized, initialize a new one + .unwrap_or_else(|| BasicBlockState::new(ecs_data)) + // Call handler + .handle(ecs_data), }, Dodge(kind) => match kind { - Roll(Some(state)) => state.handle(&ecs_data), + Roll(opt_state) => opt_state + // If data hasn't been initialized, initialize a new one + .unwrap_or_else(|| RollState::new(ecs_data)) + // Call handler + .handle(ecs_data), }, - Wield(Some(state)) => state.handle(&ecs_data), - Idle(Some(state)) => state.handle(&ecs_data), + Wield(opt_state) => opt_state + // If data hasn't been initialized, initialize a new one + .unwrap_or_else(|| WieldState::new(ecs_data)) + // Call handler + .handle(ecs_data), + Idle(opt_state) => opt_state + // If data hasn't been initialized, initialize a new one + .unwrap_or_else(|| IdleState::new(ecs_data)) + // Call handler + .handle(ecs_data), // // All states should be explicitly handled // Do not use default match: _ => {}, @@ -121,9 +149,13 @@ impl ActionState { } } -// Other fn's that relate to individual `MoveState`s +// fn's that relate to individual `MoveState`s +// or passing data from system to handlers impl MoveState { - /// Returns whether a given `ActionState` overrides `MoveState` `handle()`ing + /// Passes data to variant or subvariant handlers + /// States contain `Option`s, and will be + /// `None` if state data has not been initialized. So we have to + /// check and intialize new state data if so. pub fn overrides_action_state(&self) -> bool { match self { Stand(_) => false, @@ -143,14 +175,46 @@ impl MoveState { /// Passes handle to variant handlers pub fn update(&self, ecs_data: &EcsStateData) -> StateUpdate { match self { - Stand(Some(state)) => state.handle(&ecs_data), - Run(Some(state)) => state.handle(&ecs_data), - Jump(Some(state)) => state.handle(&ecs_data), - Climb(Some(state)) => state.handle(&ecs_data), - Glide(Some(state)) => state.handle(&ecs_data), - Swim(Some(state)) => state.handle(&ecs_data), - Fall(Some(state)) => state.handle(&ecs_data), - Sit(Some(state)) => state.handle(&ecs_data), + Stand(opt_state) => opt_state + // If data hasn't been initialized, initialize a new one + .unwrap_or_else(|| StandState::new(ecs_data)) + // Call handler + .handle(ecs_data), + Run(opt_state) => opt_state + // If data hasn't been initialized, initialize a new one + .unwrap_or_else(|| RunState::new(ecs_data)) + // Call handler + .handle(ecs_data), + Jump(opt_state) => opt_state + // If data hasn't been initialized, initialize a new one + .unwrap_or_else(|| JumpState::new(ecs_data)) + // Call handler + .handle(ecs_data), + Climb(opt_state) => opt_state + // If data hasn't been initialized, initialize a new one + .unwrap_or_else(|| ClimbState::new(ecs_data)) + // Call handler + .handle(ecs_data), + Glide(opt_state) => opt_state + // If data hasn't been initialized, initialize a new one + .unwrap_or_else(|| GlideState::new(ecs_data)) + // Call handler + .handle(ecs_data), + Swim(opt_state) => opt_state + // If data hasn't been initialized, initialize a new one + .unwrap_or_else(|| SwimState::new(ecs_data)) + // Call handler + .handle(ecs_data), + Fall(opt_state) => opt_state + // If data hasn't been initialized, initialize a new one + .unwrap_or_else(|| FallState::new(ecs_data)) + // Call handler + .handle(ecs_data), + Sit(opt_state) => opt_state + // If data hasn't been initialized, initialize a new one + .unwrap_or_else(|| SitState::new(ecs_data)) + // Call handler + .handle(ecs_data), // // All states should be explicitly handled // Do not use default match: _ => {}, diff --git a/common/src/comp/states/roll.rs b/common/src/comp/states/roll.rs index d7c62fce95..1d4f01fbcc 100644 --- a/common/src/comp/states/roll.rs +++ b/common/src/comp/states/roll.rs @@ -1,5 +1,7 @@ use super::ROLL_SPEED; -use crate::comp::{ActionState::*, DodgeKind::*, EcsStateData, StateHandler, StateUpdate}; +use crate::comp::{ + ActionState::*, DodgeKind::*, EcsStateData, ItemKind::Tool, StateHandler, StateUpdate, ToolData, +}; use crate::util::state_utils::*; use std::time::Duration; use vek::Vec3; @@ -11,6 +13,18 @@ pub struct RollState { } impl StateHandler for RollState { + fn new(ecs_data: &EcsStateData) -> Self { + let tool_data = + if let Some(Tool(data)) = ecs_data.stats.equipment.main.as_ref().map(|i| &i.kind) { + data + } else { + &ToolData::default() + }; + Self { + remaining_duration: tool_data.attack_duration(), + } + } + fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate { let mut update = StateUpdate { character: *ecs_data.character, diff --git a/common/src/comp/states/run.rs b/common/src/comp/states/run.rs index 755e8b8e56..94bdf7dc85 100644 --- a/common/src/comp/states/run.rs +++ b/common/src/comp/states/run.rs @@ -10,6 +10,10 @@ use vek::vec::{Vec2, Vec3}; pub struct RunState; impl StateHandler for RunState { + fn new(ecs_data: &EcsStateData) -> Self { + Self {} + } + fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate { let mut update = StateUpdate { character: *ecs_data.character, diff --git a/common/src/comp/states/sit.rs b/common/src/comp/states/sit.rs index 58763c9e0d..99f567bdec 100644 --- a/common/src/comp/states/sit.rs +++ b/common/src/comp/states/sit.rs @@ -8,6 +8,10 @@ use crate::util::state_utils::*; pub struct SitState; impl StateHandler for SitState { + fn new(ecs_data: &EcsStateData) -> Self { + Self {} + } + fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate { let mut update = StateUpdate { character: *ecs_data.character, diff --git a/common/src/comp/states/stand.rs b/common/src/comp/states/stand.rs index d1c5a95574..7c81839f2c 100644 --- a/common/src/comp/states/stand.rs +++ b/common/src/comp/states/stand.rs @@ -8,6 +8,10 @@ use crate::util::state_utils::*; pub struct StandState; impl StateHandler for StandState { + fn new(ecs_data: &EcsStateData) -> Self { + Self {} + } + fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate { let mut update = StateUpdate { character: *ecs_data.character, diff --git a/common/src/comp/states/swim.rs b/common/src/comp/states/swim.rs index 87f350cb58..ccb3022e5d 100644 --- a/common/src/comp/states/swim.rs +++ b/common/src/comp/states/swim.rs @@ -7,6 +7,10 @@ use vek::{Vec2, Vec3}; pub struct SwimState; impl StateHandler for SwimState { + fn new(ecs_data: &EcsStateData) -> Self { + Self {} + } + fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate { let mut update = StateUpdate { character: *ecs_data.character, diff --git a/common/src/comp/states/wield.rs b/common/src/comp/states/wield.rs index ddf91961f4..d2217057e4 100644 --- a/common/src/comp/states/wield.rs +++ b/common/src/comp/states/wield.rs @@ -1,6 +1,6 @@ use crate::comp::{ - AbilityAction, AbilityActionKind::*, ActionState::*, EcsStateData, IdleState, StateHandler, - StateUpdate, + AbilityAction, AbilityActionKind::*, ActionState::*, EcsStateData, IdleState, ItemKind::Tool, + StateHandler, StateUpdate, ToolData, }; use crate::util::state_utils::*; use std::time::Duration; @@ -13,6 +13,18 @@ pub struct WieldState { } impl StateHandler for WieldState { + fn new(ecs_data: &EcsStateData) -> Self { + let tool_data = + if let Some(Tool(data)) = ecs_data.stats.equipment.main.as_ref().map(|i| &i.kind) { + data + } else { + &ToolData::default() + }; + Self { + equip_delay: tool_data.equip_time(), + } + } + fn handle(&self, ecs_data: &EcsStateData) -> StateUpdate { let mut update = StateUpdate { character: *ecs_data.character,