veloren_server/sys/
waypoint.rs1use crate::client::Client;
2use common::{
3 comp::{PhysicsState, Player, Pos, Vel, Waypoint, WaypointArea},
4 resources::Time,
5};
6use common_ecs::{Job, Origin, Phase, System};
7use common_net::msg::{Notification, ServerGeneral};
8use specs::{Entities, Join, LendJoin, Read, ReadStorage, WriteStorage};
9
10const NOTIFY_TIME: f64 = 10.0;
12
13#[derive(Default)]
16pub struct Sys;
17impl<'a> System<'a> for Sys {
18 type SystemData = (
19 Entities<'a>,
20 ReadStorage<'a, Pos>,
21 ReadStorage<'a, Player>,
22 ReadStorage<'a, WaypointArea>,
23 WriteStorage<'a, Waypoint>,
24 ReadStorage<'a, Client>,
25 Read<'a, Time>,
26 ReadStorage<'a, PhysicsState>,
27 ReadStorage<'a, Vel>,
28 );
29
30 const NAME: &'static str = "waypoint";
31 const ORIGIN: Origin = Origin::Server;
32 const PHASE: Phase = Phase::Create;
33
34 fn run(
35 _job: &mut Job<Self>,
36 (
37 entities,
38 positions,
39 players,
40 waypoint_areas,
41 mut waypoints,
42 clients,
43 time,
44 physics_states,
45 velocities,
46 ): Self::SystemData,
47 ) {
48 for (entity, player_pos, _, client, physics, velocity) in (
49 &entities,
50 &positions,
51 &players,
52 &clients,
53 physics_states.maybe(),
54 &velocities,
55 )
56 .join()
57 {
58 if physics.is_none_or(|ps| ps.on_ground.is_some()) && velocity.0.z >= 0.0 {
59 for (waypoint_pos, waypoint_area) in (&positions, &waypoint_areas).join() {
60 if player_pos.0.distance_squared(waypoint_pos.0)
61 < waypoint_area.radius().powi(2)
62 {
63 if let Ok(wp_old) =
64 waypoints.insert(entity, Waypoint::new(player_pos.0, *time))
65 {
66 if wp_old.is_none_or(|w| w.elapsed(*time) > NOTIFY_TIME) {
67 client.send_fallible(ServerGeneral::Notification(
68 Notification::WaypointSaved,
69 ));
70 }
71 }
72 }
73 }
74 }
75 }
76 }
77}