summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorstale <redkugelblitzin@gmail.com>2022-05-29 20:45:03 -0300
committerstale <redkugelblitzin@gmail.com>2022-05-29 20:45:03 -0300
commitbcd5764aa03e128e06c355272b7b81eac8d4501d (patch)
tree44e1076c24680325a02317c29d4838c547a6c49d /src
parent8e8fb7c45e8088843b71cb55fede723b2f9c7ff2 (diff)
improved pubs listing, many minor fixes
Diffstat (limited to 'src')
-rw-r--r--src/conn.rs2
-rw-r--r--src/main.rs40
-rw-r--r--src/minesweeper.rs4
-rw-r--r--src/types.rs15
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(" ", "&nbsp"), room.read().await.board_conf))).expect("couldn't send register ack");
+ tx.send(Message::text(format!("regack {} {uid} {}", name.replace(" ", "&nbsp"), 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)]