use super::SysTimer; use crate::client::Client; use common::{ comp::{Player, Pos, Waypoint, WaypointArea}, resources::Time, vsystem::{Origin, Phase, VJob, VSystem}, }; use common_net::msg::{Notification, ServerGeneral}; use specs::{Entities, Join, Read, ReadStorage, Write, WriteStorage}; /// Cooldown time (in seconds) for "Waypoint Saved" notifications const NOTIFY_TIME: f64 = 10.0; /// This system updates player waypoints /// TODO: Make this faster by only considering local waypoints #[derive(Default)] pub struct Sys; impl<'a> VSystem<'a> for Sys { #[allow(clippy::type_complexity)] // TODO: Pending review in #587 type SystemData = ( Entities<'a>, ReadStorage<'a, Pos>, ReadStorage<'a, Player>, ReadStorage<'a, WaypointArea>, WriteStorage<'a, Waypoint>, ReadStorage<'a, Client>, Read<'a, Time>, Write<'a, SysTimer>, ); const NAME: &'static str = "waypoint"; const ORIGIN: Origin = Origin::Server; const PHASE: Phase = Phase::Create; fn run( _job: &mut VJob, ( entities, positions, players, waypoint_areas, mut waypoints, clients, time, mut timer, ): Self::SystemData, ) { timer.start(); for (entity, player_pos, _, client) in (&entities, &positions, &players, &clients).join() { for (waypoint_pos, waypoint_area) in (&positions, &waypoint_areas).join() { if player_pos.0.distance_squared(waypoint_pos.0) < waypoint_area.radius().powi(2) { if let Ok(wp_old) = waypoints.insert(entity, Waypoint::new(player_pos.0, *time)) { if wp_old.map_or(true, |w| w.elapsed(*time) > NOTIFY_TIME) { client.send_fallible(ServerGeneral::Notification( Notification::WaypointSaved, )); } } } } } timer.end(); } }