summaryrefslogtreecommitdiff
path: root/src/types.rs
blob: 2d6ae223baf28c645c8c22f2c8bec39f695424fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use std::{
    collections::HashMap,
    net::SocketAddr,
    sync::{
        Arc,
        atomic::{ AtomicUsize, Ordering },
    },
    fmt::Display,
    ops::{ Deref, DerefMut },
};
use warp::ws::Message;
use tokio::sync::RwLock;
use serde::Serialize;
use crate::minesweeper;

#[derive(Debug, Clone)]
pub struct Config {
    pub cert: String,
    pub pkey: String,
    pub index_pg: String,
    pub room_pg: String,
    pub client_code: String,
    pub stylesheet: String,
    pub socket_addr: SocketAddr,
}

#[derive(Debug, Serialize, Clone)]
pub struct RoomConf {
    pub name: String,
    pub player_cap: usize,
    pub public: bool,
    pub board_conf: minesweeper::BoardConf,
}

pub struct Room {
    pub conf: RoomConf,
    pub players: PlayerMap,
    pub driver: tokio::task::JoinHandle<()>,
    pub cmd_stream: CmdTx,
}

#[derive(Debug)]
pub enum MetaMove {
    Move(minesweeper::Move,SocketAddr),
    Dump,
    Reset,
}

#[derive(Debug)]
pub struct Conn {
    pub tx: tokio::sync::mpsc::UnboundedSender<Message>,
    pub addr: SocketAddr,
}

#[derive(Debug)]
pub struct Player {
    pub conn: Conn,
    pub uid: usize,
    pub name: String,
    pub clr: String,
    pub position: (usize, usize),
}

impl Display for Player {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "\"{}\"@{}", self.name, self.conn.addr)
    }
}

#[derive(Eq, PartialEq, Hash, Debug, Clone, serde::Serialize)]
pub struct RoomId(pub String);
impl Display for RoomId {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}
impl std::borrow::Borrow<str> for RoomId {
    fn borrow(&self) -> &str {
        self.0.borrow()
    }
}

impl RoomId {
    pub fn new_in<T>(map: &HashMap<RoomId, T>) -> Self {
        use rand::{ thread_rng, Rng, distributions::Alphanumeric };
        let id = RoomId { 0: thread_rng()
            .sample_iter(&Alphanumeric)
            .take(16)
            .map(char::from)
            .collect::<String>() };
        if map.contains_key(&id) { RoomId::new_in(map) }
        else { id }
    }
}

pub type CmdTx = tokio::sync::mpsc::UnboundedSender<MetaMove>;
pub type RoomMap = Arc<RwLock<HashMap<RoomId, Arc<RwLock<Room>>>>>;
pub type PlayerMapData = Arc<RwLock<HashMap<SocketAddr, Player>>>;
#[derive(Debug)]
pub struct PlayerMap {
    inner: PlayerMapData,
    uid_counter: AtomicUsize,
}

impl Deref for PlayerMap {
    type Target = Arc<RwLock<HashMap<SocketAddr, Player>>>;
    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}
impl DerefMut for PlayerMap {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.inner
    }
}
impl Default for PlayerMap {
    fn default() -> Self {
        Self { inner: Arc::new(RwLock::new(HashMap::new())), uid_counter: 0.into() }
    }
}

impl PlayerMap {
    pub async fn insert_conn(&mut self, conn: Conn, name: String, clr: String) -> usize {
        let mut map = self.write().await;
        let uid = self.uid_counter.fetch_add(1, Ordering::Relaxed);
        map.insert(
            conn.addr,
            Player { conn, uid, name, clr, position: (0,0) },
        );
        uid
    }
}