veloren_server/sys/
invite_timeout.rs

1use crate::client::Client;
2use common::{
3    comp::invite::{Invite, PendingInvites},
4    uid::Uid,
5};
6use common_ecs::{Job, Origin, Phase, System};
7use common_net::msg::{InviteAnswer, ServerGeneral};
8use specs::{Entities, Join, ReadStorage, WriteStorage};
9
10/// This system removes timed out invites
11#[derive(Default)]
12pub struct Sys;
13impl<'a> System<'a> for Sys {
14    type SystemData = (
15        Entities<'a>,
16        WriteStorage<'a, Invite>,
17        WriteStorage<'a, PendingInvites>,
18        ReadStorage<'a, Client>,
19        ReadStorage<'a, Uid>,
20    );
21
22    const NAME: &'static str = "invite_timeout";
23    const ORIGIN: Origin = Origin::Server;
24    const PHASE: Phase = Phase::Create;
25
26    fn run(
27        _job: &mut Job<Self>,
28        (entities, mut invites, mut pending_invites, clients, uids): Self::SystemData,
29    ) {
30        let now = std::time::Instant::now();
31        let timed_out_invites = (&entities, &invites)
32            .join()
33            .filter_map(|(invitee, Invite { inviter, kind })| {
34                // Retrieve timeout invite from pending invites
35                let pending = &mut pending_invites.get_mut(*inviter)?.0;
36                let index = pending.iter().position(|p| p.0 == invitee)?;
37
38                // Stop if not timed out
39                if pending[index].2 > now {
40                    return None;
41                }
42
43                // Remove pending entry
44                pending.swap_remove(index);
45
46                // If no pending invites remain remove the component
47                if pending.is_empty() {
48                    pending_invites.remove(*inviter);
49                }
50
51                // Inform inviter of timeout
52                if let (Some(client), Some(target)) =
53                    (clients.get(*inviter), uids.get(invitee).copied())
54                {
55                    client.send_fallible(ServerGeneral::InviteComplete {
56                        target,
57                        answer: InviteAnswer::TimedOut,
58                        kind: *kind,
59                    });
60                }
61
62                Some(invitee)
63            })
64            .collect::<Vec<_>>();
65
66        for entity in timed_out_invites {
67            invites.remove(entity);
68        }
69    }
70}