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_path: String, pub pkey_path: String, pub page_path: 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: u32, 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, 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) } } pub type CmdTx = tokio::sync::mpsc::UnboundedSender; pub type PlayerMapData = Arc>>; #[derive(Debug)] pub struct PlayerMap { inner: PlayerMapData, uid_counter: AtomicUsize, } impl Deref for PlayerMap { type Target = Arc>>; 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 } }