use crate::ZaraController;
use crate::utils::event::Listener;
use crate::body::state::BodyStateContract;
use crate::health::state::HealthStateContract;
use crate::inventory::state::InventoryStateContract;
use std::time::Duration;
use std::fmt;
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
#[derive(Clone, Debug, Default)]
pub struct ZaraControllerStateContract {
pub environment: EnvironmentStateContract,
pub player_status: PlayerStatusContract,
pub body: BodyStateContract,
pub health: HealthStateContract,
pub inventory: InventoryStateContract,
pub update_counter: f32,
pub queue_counter: f32,
pub last_update_game_time: Duration,
pub last_frame_game_time: Duration,
pub is_paused: bool
}
impl fmt::Display for ZaraControllerStateContract {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Zara core state @{} game secs", self.environment.game_time.as_secs_f32())
}
}
impl Ord for ZaraControllerStateContract {
fn cmp(&self, other: &Self) -> Ordering {
self.environment.game_time.cmp(&other.environment.game_time)
}
}
impl Eq for ZaraControllerStateContract { }
impl PartialOrd for ZaraControllerStateContract {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for ZaraControllerStateContract {
fn eq(&self, other: &Self) -> bool {
const EPS: f32 = 0.0001;
self.environment == other.environment &&
self.player_status == other.player_status &&
self.body == other.body &&
self.health == other.health &&
self.inventory == other.inventory &&
self.last_update_game_time == other.last_update_game_time &&
self.last_frame_game_time == other.last_frame_game_time &&
self.is_paused == other.is_paused &&
f32::abs(self.update_counter - other.update_counter) < EPS &&
f32::abs(self.queue_counter - other.queue_counter) < EPS
}
}
impl Hash for ZaraControllerStateContract {
fn hash<H: Hasher>(&self, state: &mut H) {
self.environment.hash(state);
self.player_status.hash(state);
self.body.hash(state);
self.health.hash(state);
self.inventory.hash(state);
self.last_update_game_time.hash(state);
self.last_frame_game_time.hash(state);
self.is_paused.hash(state);
state.write_u32(self.update_counter as u32);
state.write_u32(self.queue_counter as u32);
}
}
#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
pub struct ActiveDiseaseStateContract {
pub needs_treatment: bool,
pub will_self_heal_on: crate::health::StageLevel,
pub total_duration: Duration,
pub initial_data: Vec<crate::health::disease::state::StageDescriptionStateContract>,
pub stages: Vec<crate::health::disease::state::ActiveStageStateContract>,
pub lerp_data: Option<crate::health::disease::state::LerpDataNodeStateContract>,
pub last_deltas: crate::health::disease::state::DiseaseDeltasStateContract,
pub is_inverted: bool,
pub activation_time: Duration,
pub will_end: bool,
pub end_time: Option<Duration>
}
#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
pub struct ActiveInjuryStateContract {
pub needs_treatment: bool,
pub is_fracture: bool,
pub body_part: crate::body::BodyPart,
pub will_self_heal_on: crate::health::StageLevel,
pub total_duration: Duration,
pub initial_data: Vec<crate::health::injury::state::StageDescriptionStateContract>,
pub stages: Vec<crate::health::injury::state::ActiveStageStateContract>,
pub lerp_data: Option<crate::health::injury::state::LerpDataNodeStateContract>,
pub last_deltas: crate::health::injury::state::InjuryDeltasStateContract,
pub is_inverted: bool,
pub activation_time: Duration,
pub will_end: bool,
pub end_time: Option<Duration>
}
#[derive(Clone, Debug, Default)]
pub struct EnvironmentStateContract {
pub game_time: Duration,
pub wind_speed: f32,
pub temperature: f32,
pub rain_intensity: f32
}
impl fmt::Display for EnvironmentStateContract {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} secs, temp {:.1}C, wind {:.1} m/s, rain {:.1}", self.game_time.as_secs_f32(),
self.temperature, self.wind_speed, self.rain_intensity)
}
}
impl Ord for EnvironmentStateContract {
fn cmp(&self, other: &Self) -> Ordering {
self.game_time.cmp(&other.game_time)
}
}
impl Eq for EnvironmentStateContract { }
impl PartialOrd for EnvironmentStateContract {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for EnvironmentStateContract {
fn eq(&self, other: &Self) -> bool {
const EPS: f32 = 0.0001;
self.game_time == other.game_time &&
f32::abs(self.temperature - other.temperature) < EPS &&
f32::abs(self.wind_speed - other.wind_speed) < EPS &&
f32::abs(self.rain_intensity - other.rain_intensity) < EPS
}
}
impl Hash for EnvironmentStateContract {
fn hash<H: Hasher>(&self, state: &mut H) {
self.game_time.hash(state);
state.write_u32(self.temperature as u32);
state.write_u32(self.wind_speed as u32);
state.write_u32(self.rain_intensity as u32);
}
}
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Default)]
pub struct PlayerStatusContract {
pub is_walking: bool,
pub is_running: bool,
pub is_swimming: bool,
pub is_underwater: bool
}
impl<E: Listener + 'static> ZaraController<E> {
pub fn get_state(&self) -> ZaraControllerStateContract {
ZaraControllerStateContract {
environment: EnvironmentStateContract {
game_time: self.environment.game_time.duration.get(),
wind_speed: self.environment.wind_speed.get(),
temperature: self.environment.temperature.get(),
rain_intensity: self.environment.rain_intensity.get()
},
player_status: PlayerStatusContract {
is_walking: self.player_state.is_walking.get(),
is_running: self.player_state.is_running.get(),
is_swimming: self.player_state.is_swimming.get(),
is_underwater: self.player_state.is_underwater.get()
},
body: self.body.get_state(),
health: self.health.get_state(),
inventory: self.inventory.get_state(),
update_counter: self.update_counter.get(),
queue_counter: self.queue_counter.get(),
last_update_game_time: self.last_update_game_time.get(),
last_frame_game_time: self.last_frame_game_time.get(),
is_paused: self.is_paused.get()
}
}
pub fn restore_state(&self, state: &ZaraControllerStateContract) {
self.update_counter.set(state.update_counter);
self.queue_counter.set(state.queue_counter);
self.last_update_game_time.set(state.last_update_game_time);
self.last_frame_game_time.set(state.last_frame_game_time);
self.is_paused.set(state.is_paused);
self.environment.rain_intensity.set(state.environment.rain_intensity);
self.environment.temperature.set(state.environment.temperature);
self.environment.wind_speed.set(state.environment.wind_speed);
self.environment.game_time.update_from_duration(state.environment.game_time);
self.player_state.is_walking.set(state.player_status.is_walking);
self.player_state.is_running.set(state.player_status.is_running);
self.player_state.is_swimming.set(state.player_status.is_swimming);
self.player_state.is_underwater.set(state.player_status.is_underwater);
self.body.restore_state(&state.body);
self.health.restore_state(&state.health);
self.inventory.restore_state(&state.inventory)
}
}