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::room::Room;
8
9pub struct ConnectedPlayer {
10    pub player_id: String,
11    pub username: String,
12    pub room_id: Option<String>,
13    pub sender: mpsc::UnboundedSender<Message>,
14    pub connected: bool,
15    pub generation: u64,
16    pub last_seen: Instant,
17    pub disconnected_at: Option<Instant>,
18    pub is_service: bool,
19}
20
21pub struct ServerState {
22    pub players: DashMap<String, ConnectedPlayer>,
23    pub rooms: DashMap<String, Room>,
24    pub server_key: String,
25    pub max_rooms: usize,
26    pub official_key: Option<String>,
27    pub analytics: AnalyticsHandle,
28}
29
30impl ServerState {
31    pub fn new(
32        server_key: String,
33        max_rooms: usize,
34        official_key: Option<String>,
35        analytics: AnalyticsHandle,
36    ) -> Self {
37        ServerState {
38            players: DashMap::new(),
39            rooms: DashMap::new(),
40            server_key,
41            max_rooms,
42            official_key,
43            analytics,
44        }
45    }
46
47    pub fn username_taken_by_connected(&self, username: &str) -> bool {
48        self.players
49            .iter()
50            .any(|entry| entry.value().username == username && entry.value().connected)
51    }
52
53    pub fn find_disconnected_by_username(
54        &self,
55        username: &str,
56    ) -> Option<(String, Option<String>, u64)> {
57        self.players
58            .iter()
59            .find(|entry| entry.value().username == username && !entry.value().connected)
60            .map(|entry| {
61                (
62                    entry.value().player_id.clone(),
63                    entry.value().room_id.clone(),
64                    entry.value().generation,
65                )
66            })
67    }
68
69    pub fn find_connected_by_username(&self, username: &str) -> Option<(String, u64, bool)> {
70        self.players
71            .iter()
72            .find(|entry| entry.value().username == username && entry.value().connected)
73            .map(|entry| {
74                (
75                    entry.value().player_id.clone(),
76                    entry.value().generation,
77                    entry.value().sender.is_closed(),
78                )
79            })
80    }
81}