summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--Cargo.toml1
-rw-r--r--assets/client.js4
-rw-r--r--assets/index.html13
-rw-r--r--assets/room.html2
-rw-r--r--assets/style.css10
-rw-r--r--src/conn.rs2
-rw-r--r--src/main.rs40
-rw-r--r--src/minesweeper.rs4
-rw-r--r--src/types.rs15
10 files changed, 68 insertions, 24 deletions
diff --git a/Cargo.lock b/Cargo.lock
index ca41240..1853a85 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1378,6 +1378,7 @@ dependencies = [
"futures-util",
"rand",
"serde",
+ "serde_json",
"tokio",
"warp",
]
diff --git a/Cargo.toml b/Cargo.toml
index c825273..6356860 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,6 +9,7 @@ edition = "2018"
[dependencies]
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
+serde_json = "1.0"
warp = { version = "0.3", features = ["tls", "websocket"] }
rand = "0.8"
futures-util = "0.3"
diff --git a/assets/client.js b/assets/client.js
index b23222c..a6a2a73 100644
--- a/assets/client.js
+++ b/assets/client.js
@@ -163,8 +163,8 @@ function movSelWin(win, x, y) {
} else {
win.style.display = "";
}
- win.style.left = (anch.x + (tpos.x * tile_w)) + 'px';
- win.style.top = (anch.y + ((tpos.y + 0.35) * tile_h)) + 'px';
+ win.style.left = (window.scrollX + anch.x + (tpos.x * tile_w)) + 'px';
+ win.style.top = (window.scrollY + anch.y + ((tpos.y + 0.35) * tile_h)) + 'px';
win.style.width = tile_w + 'px';
win.style.height = tile_h + 'px';
}
diff --git a/assets/index.html b/assets/index.html
index 6fc9c46..763b9ef 100644
--- a/assets/index.html
+++ b/assets/index.html
@@ -11,9 +11,16 @@
<script>
let rlist = document.getElementById('rlist');
fetch('rlist').then(r => r.json()).then(rooms => {
- rooms.forEach(x => {
+ Object.keys(rooms).forEach(x => {
+ let roominfo = JSON.parse(rooms[x]);
+ let bc = roominfo.board_conf;
let a = document.createElement('a');
- a.appendChild(document.createTextNode(x));
+ let h1 = document.createElement('h1');
+ h1.appendChild(document.createTextNode(`> ${roominfo.name}`));
+ let h4 = document.createElement('h4');
+ h4.appendChild(document.createTextNode(`${bc.w} by ${bc.h} with ${bc.mine_ratio[0]} in every ${bc.mine_ratio[1]} tiles mined`));
+ a.append(h1);
+ a.append(h4);
a.href = 'room/' + x;
rlist.append(a);
rlist.append(document.createElement('br'));
@@ -33,7 +40,7 @@
tiles are mines
</label><br>
<label>public, ie. shown in the lobby <input name="raccess" type="checkbox" checked></label><br>
- <label>always safe first move <input name="ralwayssafe1move" type="checkbox" checked></label><br>
+ <label>safe first move (if possible)<input name="ralwayssafe1move" type="checkbox" checked></label><br>
<label>player limit<input name="rlimit" type="number" value="32"></label><br>
<button>create</button>
</fieldset>
diff --git a/assets/room.html b/assets/room.html
index 27f9ae1..e3e6ff9 100644
--- a/assets/room.html
+++ b/assets/room.html
@@ -7,7 +7,7 @@
<link rel="stylesheet" type="text/css" href="/s.css">
</head>
<body>
- <div class="cent">
+ <div>
<div id="board-container">
<span id="board"></span>
</div>
diff --git a/assets/style.css b/assets/style.css
index d217b8d..52a2021 100644
--- a/assets/style.css
+++ b/assets/style.css
@@ -36,3 +36,13 @@ body {
padding: 0.1em 0.1em;
}
+#rlist a {
+ text-decoration: none;
+ line-height: 0.4;
+ color: #dfdfff;
+ background-color: #3c3c3c;
+}
+
+a :visited {
+ color: inherit;
+}
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)]