veloren_server/sys/
invite_timeout.rs1use 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#[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 let pending = &mut pending_invites.get_mut(*inviter)?.0;
36 let index = pending.iter().position(|p| p.0 == invitee)?;
37
38 if pending[index].2 > now {
40 return None;
41 }
42
43 pending.swap_remove(index);
45
46 if pending.is_empty() {
48 pending_invites.remove(*inviter);
49 }
50
51 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}