diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/conn.rs | 2 | ||||
-rw-r--r-- | src/main.rs | 40 | ||||
-rw-r--r-- | src/minesweeper.rs | 4 | ||||
-rw-r--r-- | src/types.rs | 15 |
4 files changed, 43 insertions, 18 deletions
diff --git a/src/conn.rs b/src/conn.rs index 14777bf..d38b6ef 100644 --- a/src/conn.rs +++ b/src/conn.rs @@ -43,7 +43,7 @@ pub async fn lobby(socket: WebSocket, addr: SocketAddr, room: Arc<RwLock<Room>>) let conn = Conn { addr, tx: tx.clone() }; room.write().await.players.insert_conn(conn, name.clone(), clr).await }; - tx.send(Message::text(format!("regack {} {uid} {}", name.replace(" ", " "), room.read().await.board_conf))).expect("couldn't send register ack"); + tx.send(Message::text(format!("regack {} {uid} {}", name.replace(" ", " "), room.read().await.conf.board_conf))).expect("couldn't send register ack"); if let Err(e) = room.read().await.cmd_stream.send(MetaMove::Dump) { println!("couldn't request game dump in behalf of {addr}: {e}"); } diff --git a/src/main.rs b/src/main.rs index 2f7d52c..3dd7f39 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,6 +14,7 @@ use types::*; use tokio::sync::RwLock; const FONT_FILE: &[u8] = include_bytes!("../assets/VT323-Regular.ttf"); +const AREA_LIMIT: usize = 150*150; fn main() -> Result<(), Box<dyn Error>> { let conf = Config { @@ -32,7 +33,7 @@ fn main() -> Result<(), Box<dyn Error>> { #[tokio::main] async fn tokio_main(conf: Config) -> Result<(), Box<dyn Error>> { let rooms: RoomMap = Arc::new(RwLock::new(HashMap::new())); - let public_rooms = Arc::new(RwLock::new(Vec::new())); + let public_rooms = Arc::new(RwLock::new(HashMap::new())); use warp::*; let index = path::end().and(fs::file(conf.index_pg.clone())); @@ -44,8 +45,9 @@ async fn tokio_main(conf: Config) -> Result<(), Box<dyn Error>> { path!("rlist").and_then(move || { let pubs = pubs.clone(); async move { - Ok::<_,std::convert::Infallible>( - reply::json(&pubs.read().await.as_slice()) + let map = pubs.read().await; + Ok::<_,std::convert::Infallible>( + reply::json(&*map) ) }}) }; @@ -67,26 +69,36 @@ async fn tokio_main(conf: Config) -> Result<(), Box<dyn Error>> { rinfo.get("ralwayssafe1move"), rinfo.get("rlimit").and_then(|l| l.parse::<usize>().ok()), ) { + if w.get()*h.get() > AREA_LIMIT { + return Err(reject::custom(BoardTooBig)) + } let board_conf = minesweeper::BoardConf { w, h, mine_ratio: (num,denom), always_safe_first_move: asfm.is_some() }; - let name = rinfo.get("rname").map(|r| r.to_owned()).unwrap_or(format!("{w}x{h} room")); - let mut rooms = rooms.write().await; let uid = types::RoomId::new_in(&rooms); + let name = { + let n = rinfo.get("rname").map(|r| r.to_owned()).unwrap(); + if n.is_empty() { uid.to_string() } else { n } + }; let players = PlayerMap::default(); let (cmd_tx, cmd_rx) = tokio::sync::mpsc::unbounded_channel(); let handle = tokio::spawn(gameloop(cmd_rx, players.clone(), board_conf)); - rooms.insert(uid.clone(), Arc::new(RwLock::new(Room { + let room_conf = RoomConf { name, - players, - peer_limit: match limit { Some(i) => i, None => usize::MAX }, + player_cap: match limit { Some(i) => i, None => usize::MAX }, public: access.is_some(), + board_conf, + }; + let new_room = Room { + conf: room_conf, + players, driver: handle, cmd_stream: cmd_tx, - board_conf, - }))); + }; if access.is_some() { - pubs.write().await.push(uid.clone()); + pubs.write().await.insert(uid.clone(), serde_json::to_string(&new_room.conf).unwrap()); } + rooms.insert(uid.clone(), Arc::new(RwLock::new(new_room))); + Ok( hyper::Response::builder() .status(hyper::StatusCode::SEE_OTHER) @@ -205,10 +217,16 @@ use warp::{ reject::{ Reject, Rejection }, reply::{ self, Reply }, http::StatusC struct BadFormData; impl Reject for BadFormData {} +#[derive(Debug)] +struct BoardTooBig; +impl Reject for BoardTooBig {} + async fn error_handler(err: Rejection) -> Result<impl Reply, std::convert::Infallible> { if err.is_not_found() { Ok(reply::with_status("No such file", StatusCode::NOT_FOUND)) } else if let Some(_e) = err.find::<BadFormData>() { Ok(reply::with_status("Bad form data", StatusCode::BAD_REQUEST)) + } else if let Some(_e) = err.find::<BoardTooBig>() { + Ok(reply::with_status("Board too big", StatusCode::BAD_REQUEST)) } else { println!("unhandled rejection: {err:?}"); Ok(reply::with_status("Server error", StatusCode::INTERNAL_SERVER_ERROR)) diff --git a/src/minesweeper.rs b/src/minesweeper.rs index c81aa09..a494b94 100644 --- a/src/minesweeper.rs +++ b/src/minesweeper.rs @@ -3,6 +3,8 @@ use std::{ num::NonZeroUsize, }; use rand::{ thread_rng, Rng, distributions::Uniform }; +use serde::Serialize; + const HIDDEN_BIT: u8 = 1 << 7; pub const FLAGGED_BIT: u8 = 1 << 6; const CORRECT_BIT: u8 = 1 << 5; // grading for a rightly flagged mine @@ -29,7 +31,7 @@ pub struct Game { pub board_conf: BoardConf, } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Serialize)] pub struct BoardConf { pub w: NonZeroUsize, pub h: NonZeroUsize, diff --git a/src/types.rs b/src/types.rs index 84e7d46..d467982 100644 --- a/src/types.rs +++ b/src/types.rs @@ -10,6 +10,7 @@ use std::{ }; use warp::ws::Message; use tokio::sync::RwLock; +use serde::Serialize; use crate::minesweeper; #[derive(Debug, Clone)] @@ -23,15 +24,19 @@ pub struct Config { pub socket_addr: SocketAddr, } -#[derive(Debug)] -pub struct Room { +#[derive(Debug, Serialize)] +pub struct RoomConf { pub name: String, - pub players: PlayerMap, - pub peer_limit: usize, + 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, - pub board_conf: minesweeper::BoardConf, } #[derive(Debug)] |