Add new() to states

This commit is contained in:
Adam Whitehurst 2020-01-05 15:17:22 -08:00
parent 4e5cf63452
commit 542f06eef4
16 changed files with 191 additions and 29 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<StateHandler Implementor>`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<StateHandler Implementor>`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: _ => {},

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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