pub mod entity_sync; pub mod message; pub mod persistence; pub mod sentinel; pub mod subscription; pub mod terrain; pub mod terrain_sync; pub mod waypoint; use specs::DispatcherBuilder; use std::{ marker::PhantomData, time::{Duration, Instant}, }; pub type EntitySyncTimer = SysTimer; pub type MessageTimer = SysTimer; pub type SentinelTimer = SysTimer; pub type SubscriptionTimer = SysTimer; pub type TerrainTimer = SysTimer; pub type TerrainSyncTimer = SysTimer; pub type WaypointTimer = SysTimer; pub type StatsPersistenceTimer = SysTimer; pub type StatsPersistenceScheduler = SysScheduler; // System names // Note: commented names may be useful in the future //const ENTITY_SYNC_SYS: &str = "server_entity_sync_sys"; //const SENTINEL_SYS: &str = "sentinel_sys"; //const SUBSCRIPTION_SYS: &str = "server_subscription_sys"; //const TERRAIN_SYNC_SYS: &str = "server_terrain_sync_sys"; const TERRAIN_SYS: &str = "server_terrain_sys"; const WAYPOINT_SYS: &str = "waypoint_sys"; const STATS_PERSISTENCE_SYS: &str = "stats_persistence_sys"; pub fn add_server_systems(dispatch_builder: &mut DispatcherBuilder) { dispatch_builder.add(terrain::Sys, TERRAIN_SYS, &[]); dispatch_builder.add(waypoint::Sys, WAYPOINT_SYS, &[]); dispatch_builder.add(persistence::stats::Sys, STATS_PERSISTENCE_SYS, &[]); } pub fn run_sync_systems(ecs: &mut specs::World) { use specs::RunNow; // Setup for entity sync // If I'm not mistaken, these two could be ran in parallel sentinel::Sys.run_now(ecs); subscription::Sys.run_now(ecs); // Sync terrain_sync::Sys.run_now(ecs); entity_sync::Sys.run_now(ecs); } /// Used to schedule systems to run at an interval pub struct SysScheduler { interval: Duration, last_run: Instant, _phantom: PhantomData, } impl SysScheduler { pub fn every(interval: Duration) -> Self { Self { interval, last_run: Instant::now(), _phantom: PhantomData, } } pub fn should_run(&mut self) -> bool { if self.last_run.elapsed() > self.interval { self.last_run = Instant::now(); true } else { false } } } impl Default for SysScheduler { fn default() -> Self { Self { interval: Duration::from_secs(30), last_run: Instant::now(), _phantom: PhantomData, } } } /// Used to keep track of how much time each system takes pub struct SysTimer { pub nanos: u64, start: Option, _phantom: PhantomData, } impl SysTimer { pub fn start(&mut self) { if self.start.is_some() { panic!("Timer already started"); } self.start = Some(Instant::now()); } pub fn end(&mut self) { self.nanos = self .start .take() .expect("Timer ended without starting it") .elapsed() .as_nanos() as u64; } } impl Default for SysTimer { fn default() -> Self { Self { nanos: 0, start: None, _phantom: PhantomData, } } }