Skip to main content

manabrew_server/
state.rs

1use dashmap::DashMap;
2use std::time::Instant;
3use tokio::sync::mpsc;
4use tokio_tungstenite::tungstenite::Message;
5
6use crate::analytics::AnalyticsHandle;
7use crate::deck_play_events::DeckPlayEventHandle;
8use crate::identity::{IdentityVerifier, SessionIdentity};
9use crate::room::Room;
10
11pub struct ConnectedPlayer {
12    pub player_id: String,
13    pub username: String,
14    pub room_id: Option<String>,
15    pub sender: mpsc::UnboundedSender<Message>,
16    pub connected: bool,
17    pub generation: u64,
18    pub last_seen: Instant,
19    pub disconnected_at: Option<Instant>,
20    pub is_service: bool,
21    pub identity: Vec<SessionIdentity>,
22}
23
24pub struct UsernameSession {
25    pub player_id: String,
26    pub room_id: Option<String>,
27    pub generation: u64,
28    pub connected: bool,
29    pub sender_closed: bool,
30    pub identity: Vec<SessionIdentity>,
31}
32
33impl From<&ConnectedPlayer> for UsernameSession {
34    fn from(player: &ConnectedPlayer) -> Self {
35        UsernameSession {
36            player_id: player.player_id.clone(),
37            room_id: player.room_id.clone(),
38            generation: player.generation,
39            connected: player.connected,
40            sender_closed: player.sender.is_closed(),
41            identity: player.identity.clone(),
42        }
43    }
44}
45
46pub struct ServerState {
47    pub players: DashMap<String, ConnectedPlayer>,
48    pub rooms: DashMap<String, Room>,
49    pub server_key: String,
50    pub max_rooms: usize,
51    pub official_key: Option<String>,
52    pub analytics: AnalyticsHandle,
53    pub deck_play_events: DeckPlayEventHandle,
54    pub identity: IdentityVerifier,
55}
56
57impl ServerState {
58    pub fn new(
59        server_key: String,
60        max_rooms: usize,
61        official_key: Option<String>,
62        analytics: AnalyticsHandle,
63        deck_play_events: DeckPlayEventHandle,
64        hub_jwks_url: Option<String>,
65    ) -> Self {
66        ServerState {
67            players: DashMap::new(),
68            rooms: DashMap::new(),
69            server_key,
70            max_rooms,
71            official_key,
72            analytics,
73            deck_play_events,
74            identity: IdentityVerifier::new(hub_jwks_url),
75        }
76    }
77
78    pub fn session_by_username(&self, username: &str) -> Option<UsernameSession> {
79        let mut connected = None;
80        for entry in self.players.iter() {
81            let player = entry.value();
82            if player.username != username {
83                continue;
84            }
85            if !player.connected {
86                return Some(UsernameSession::from(player));
87            }
88            connected.get_or_insert_with(|| UsernameSession::from(player));
89        }
90        connected
91    }
92}