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
134
135
136
137
|
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 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, Clone, Copy)]
pub struct BoardConf {
pub w: usize,
pub h: usize,
/// tiles to mines, expressed as (numerator, denominator)
pub mine_ratio: (usize,usize),
}
impl Display for BoardConf {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}x{} {}/{}", self.w, self.h, self.mine_ratio.0, self.mine_ratio.1)
}
}
#[derive(Debug)]
pub struct Room {
pub name: String,
pub players: PlayerMap,
pub peer_limit: usize,
pub public: bool,
pub driver: tokio::task::JoinHandle<()>,
pub cmd_stream: CmdTx,
pub board_conf: BoardConf,
}
#[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)]
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 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
}
}
|