From aeb7beb3f9b154f4aefbaa1c08d822ed572461fb Mon Sep 17 00:00:00 2001
From: stale <redkugelblitzin@gmail.com>
Date: Fri, 3 Jun 2022 22:39:55 -0300
Subject: cleaned up client code, more info in game page

---
 assets/client.js | 173 ++++++++++++++++++++++++++++---------------------------
 assets/room.html |   7 ++-
 assets/style.css |  11 ++++
 src/conn.rs      |   6 +-
 src/types.rs     |   2 +-
 5 files changed, 109 insertions(+), 90 deletions(-)

diff --git a/assets/client.js b/assets/client.js
index 3d6f064..14e95f0 100644
--- a/assets/client.js
+++ b/assets/client.js
@@ -1,35 +1,38 @@
-window.id = NaN;
+window.player = { uid: NaN };
+window.room = {
+  name: undefined,
+  bconf: { w: NaN, h: NaN, tile_w: NaN, tile_h: NaN, mine_ratio: undefined },
+  board: {},
+  cbounds: {},
+  socket: undefined,
+  last_packet: undefined,
+  identity: JSON.parse(localStorage.getItem("identity")),
+  cursors: new Map(),
+};
 window.info_elem = document.getElementById("miscinfo");
 window.identform = document.getElementById("identform");
 window.statusline = document.getElementById("statusline");
+window.bcont_elem = document.getElementById("board-container");
 window.board_elem = document.getElementById("board");
-window.bwidth = NaN;
-window.bheight = NaN;
-window.tile_w = NaN;
-window.tile_h = NaN;
-window.mine_ratio = "unk";
-window.socket = {};
-window.last_packet = {};
-window.cursors = new Map();
-window.board = {};
-window.board_bounds = {}; // init when we actually have the board loaded
-window.identity = JSON.parse(localStorage.getItem("identity"));
+window.cursor_frame = document.getElementById("cursor-frame");
 
-if (identity != null) {
-  window.socket = connect();
-  window.identform.style.display = "none";
+if (room.identity == null) {
+  statusline.style.display = "none";
+  identform.style.display = "initial";
 } else {
-  window.identform.style.display = "auto";
-  window.statusline.style.display = "none";
+  join();
 }
-function new_ident() {
-  window.identity = Object();
-  window.identity.name = document.getElementById("name-in").value;
-  window.identity.clr = document.getElementById("clr-in").value;
-  localStorage.setItem("identity", JSON.stringify(window.identity));
-  window.socket = connect();
-  window.identform.style.display = "none";
-  window.statusline.style.display = "flex";
+
+function join() {
+  if (room.identity == null) {
+    room.identity = {};
+    room.identity.name = document.getElementById("name-in").value;
+    room.identity.clr = document.getElementById("clr-in").value;
+    localStorage.setItem("identity", JSON.stringify(room.identity));
+  }
+  identform.style.display = "none";
+  room.socket = connect();
+  statusline.style.display = "flex";
 }
 function new_ident_btn() {
   localStorage.removeItem("identity");
@@ -40,15 +43,15 @@ function connect() {
   let wsproto = (window.location.protocol == "https:")? "wss:": "ws:";
   let s = new WebSocket(`${wsproto}//${location.hostname}:${location.port}${location.pathname}/ws`);
   s.onopen = function() {
-    s.send(`register ${window.identity.name} ${window.identity.clr}`);
+    s.send(`register ${room.identity.name} ${room.identity.clr}`);
   }
   s.onmessage = function(e) {
-    last_packet = e;
+    room.last_packet = e;
     let d = e.data;
     if (typeof d == "object") {
       d.arrayBuffer().then(acceptBoard);
       info_elem.onclick = undefined;
-      info_elem.innerHTML = `Running, ${mine_ratio} tiles are mines`;
+      info_elem.innerHTML = `${room.name} (${room.bconf.w}x${room.bconf.h}) >> Running, ${room.bconf.mine_ratio} tiles are mines`;
     } else if (typeof e.data == "string") {
       let fields = d.split(" ");
       switch (fields[0]) {
@@ -58,22 +61,23 @@ function connect() {
           let clr = fields[3];
           let x = fields[4];
           let y = fields[5];
-          if (!cursors.has(oid)) {
+          if (!room.cursors.has(oid)) {
             createCursor(oid, name, clr);
           }
-          let celem = cursors.get(oid).elem;
+          let celem = room.cursors.get(oid).elem;
           celem.style.left = x + 'px';
           celem.style.top = y + 'px';
-          movSelWin(cursors.get(oid).selwin, x, y);
+          movSelWin(room.cursors.get(oid).selwin, x, y);
         } break;
         case "regack": {
-          name = fields[1];
-          id = Number(fields[2]);
-          let dims = fields[3].split("x");
-          bwidth = Number(dims[0]);
-          bheight = Number(dims[1]);
-          mine_ratio = fields[4];
-          createCursor(id, name, identity.clr);
+          room.name = fields[1];
+          name = fields[2];
+          player.uid = Number(fields[3]);
+          let dims = fields[4].split("x");
+          room.bconf.w = Number(dims[0]);
+          room.bconf.h = Number(dims[1]);
+          room.bconf.mine_ratio = fields[5];
+          createCursor(player.uid, name, room.identity.clr);
         } break;
         case "win": {
           info_elem.innerHTML = "You win! Click here to play again.";
@@ -86,22 +90,22 @@ function connect() {
         } break;
         case "logoff": {
           let oid = Number(fields[1]);
-          cursors.get(oid).elem.remove();
-          cursors.get(oid).selwin.remove();
-          cursors.delete(oid);
+          room.cursors.get(oid).elem.remove();
+          room.cursors.get(oid).selwin.remove();
+          room.cursors.delete(oid);
         } break;
       }
     }
   }
-  s.onerror = function(e) { info_elem.innerHTML += `<br>Error ${e}`; }
-  s.onclose = function(e) { info_elem.innerHTML = "Closed"; }
+  s.onerror = function(e) { info_elem.innerHTML += `<br>Connection error: ${e}`; }
+  s.onclose = function(e) { info_elem.innerHTML = "Connection closed"; }
   return s;
 }
 
 function acceptBoard(data) {
   let dataarr = new Uint8Array(data);
   let vals = fflate.inflateSync(dataarr);
-  board = vals.reduce((s,c) => {
+  room.board = vals.reduce((s,c) => {
     let v = String.fromCodePoint(c);
     if (v == ' ') {
       s = s + "&nbsp";
@@ -110,14 +114,14 @@ function acceptBoard(data) {
     }
     return s;
   }, "");
-  let last = board[0];
+  let last = room.board[0];
   let last_idx = 0;
   let split_board = [];
-  for (let i = 1; i < board.length+1; i++) {
-    let cur = board[i];
+  for (let i = 1; i < room.board.length+1; i++) {
+    let cur = room.board[i];
     let gamechars = /^[CFO# 1-8]+$/;
     if ((cur != last && gamechars.test(cur)) || cur == undefined) {
-      let txt = board.substr(last_idx, i-last_idx);
+      let txt = room.board.substr(last_idx, i-last_idx);
       switch(txt[0]) {
         case 'O':
           txt = `<span style="color:red;">${txt}</span>`;
@@ -141,7 +145,7 @@ function acceptBoard(data) {
       split_board.push(txt);
       last_idx = i;
     }
-    last = board[i];
+    last = room.board[i];
   }
   board_elem.innerHTML = split_board.join("");
 }
@@ -160,66 +164,67 @@ function createCursor(id, name, clr) {
   cursor.appendChild(nametag);
   cursor.classList.add('cursor');
   cursor.style.color = clr;
-  document.getElementById('board-container').append(cursor);
-  document.getElementById('board-container').append(selection_window);
-  if (id == window.id) {
+  document.getElementById('cursor-frame').append(cursor);
+  document.getElementById('cursor-frame').append(selection_window);
+  if (id == window.player.uid) {
     document.addEventListener('mousemove', e => {
-      cursor.style.left = (e.pageX + 15) + 'px';
-      cursor.style.top = (e.pageY + 15) + 'px';
-      movSelWin(selection_window, e.clientX, e.clientY);
-      let tpos = tilepos(e.clientX, e.clientY);
-      socket.send(`pos ${e.pageX} ${e.pageY}`);
+      cursor.style.left = e.pageX + 'px';
+      cursor.style.top = e.pageY + 'px';
+      movSelWin(selection_window, e.pageX, e.pageY);
+      room.socket.send(`pos ${e.pageX} ${e.pageY}`);
     },
       false);
   }
-  cursors.set(id, {name: name, elem: cursor, selwin: selection_window});
+  room.cursors.set(id, {name: name, elem: cursor, selwin: selection_window});
   return cursor;
 }
 function movSelWin(win, x, y) {
-  let anch = board_elem.getBoundingClientRect();
-  let tpos = tilepos(x, y);
-  if (tpos.x > (bwidth - 1) || tpos.x < 0 || tpos.y > (bheight - 1) || tpos.y < 0) {
+  let tpos = tilepos(x,y);
+  if (tpos.x > (room.bconf.w - 1) || tpos.x < 0 || tpos.y > (room.bconf.h - 1) || tpos.y < 0) {
     win.style.display = "none";
   } else {
     win.style.display = "";
   }
-  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';
+  win.style.left = (tpos.x * room.bconf.tile_w) + 'px';
+  win.style.top  = (tpos.y * room.bconf.tile_h) + 'px';
+  win.style.width = room.bconf.tile_w + 'px';
+  win.style.height = room.bconf.tile_h + 'px';
 }
 function getBoardBounds() {
-  let boardb = board_elem.getBoundingClientRect();
-  tile_w = boardb.width / bwidth;
-  tile_h = 48;
+  let a = bcont_elem.getBoundingClientRect();
+  let b = board_elem.getBoundingClientRect();
+  room.bconf.tile_w = b.width / room.bconf.w;
+  room.bconf.tile_h = 48;
   return {
-    ox: boardb.x,
-    oy: boardb.y,
-    w: boardb.width,
-    h: boardb.height
+    ox: b.x + window.scrollX,
+    oy: a.y + window.scrollY,
+    w: b.width,
+    h: a.height
   };
 }
 
-board_elem.onclick = function(e) {
-  let tpos = tilepos(e.clientX, e.clientY);
+bcont_elem.onclick = function(e) {
+  let tpos = tilepos(e.pageX, e.pageY);
   let cmd = `reveal ${tpos.x} ${tpos.y}`;
   //console.log(cmd);
-  socket.send(cmd);
+  room.socket.send(cmd);
 }
-board_elem.oncontextmenu = function(e) {
-  let tpos = tilepos(e.clientX, e.clientY);
+bcont_elem.oncontextmenu = function(e) {
+  let tpos = tilepos(e.pageX, e.pageY);
   let cmd = `flag ${tpos.x} ${tpos.y}`;
   //console.log(cmd);
-  socket.send(cmd);
+  room.socket.send(cmd);
   return false;
 }
 function tilepos(x,y) {
-  board_bounds = getBoardBounds();
-  let b = board_bounds;
-  let relx = (x - b.ox);
-  let rely = (y - b.oy);
-  let tilex = Math.floor(bwidth * relx/b.w);
-  let tiley = Math.floor(bheight * rely/b.h);
+  let b = getBoardBounds();
+  room.cbounds = b;
+  let cx = x - b.ox;
+  let cy = y - b.oy;
+  //let cx = x;
+  //let cy = y;
+  let tilex = Math.floor(room.bconf.w * cx/b.w);
+  let tiley = Math.floor(room.bconf.h * cy/b.h);
   return { x: tilex, y: tiley };
 }
 function sleep(ms) {
diff --git a/assets/room.html b/assets/room.html
index 281afce..b669757 100644
--- a/assets/room.html
+++ b/assets/room.html
@@ -10,15 +10,18 @@
     <div>
       <div id="board-container">
       <span id="board"></span>
+      <div id="cursor-frame"></div>
       </div>
-      <form id="identform" action="javascript:;" onsubmit="new_ident()">
+      <form id="identform" style="display: none" action="javascript:;" onsubmit="join()">
         <input id="name-in" type="text" value="anon">
         <input id="clr-in" type="color" value="#33c033"></input>
         <button>Join</button>
       </form>
       <div id="statusline">
         <p id="miscinfo"></p>
-        <p onclick="new_ident_btn()">new identity</p>
+        <a href="javascript:navigator.clipboard.writeText(window.location.href);alert('copied link to clipboard');">đŸ”—share</p>
+        <a href="javascript:new_ident_btn();">new identity</p>
+        <a href="../..">back to lobby</a>
       </div>
     </div>
   </body>
diff --git a/assets/style.css b/assets/style.css
index 4127817..16ca7f0 100644
--- a/assets/style.css
+++ b/assets/style.css
@@ -6,6 +6,14 @@
   font-size: 80px;
   line-height: 48px;
   margin: 2vw;
+  position: relative;
+  top: 0px;
+  left 0px;
+}
+#cursor-frame {
+  position: absolute;
+  top: 0px;
+  left: 0px;
 }
 .cent {
   width: 80vw;
@@ -61,6 +69,9 @@ body {
   bottom: 0px;
   left: 0px;
 }
+#statusline * {
+  margin: 0.5em 2em 0 0;
+}
 
 span, h1, h4 {
   margin: 0 auto;
diff --git a/src/conn.rs b/src/conn.rs
index dfd6623..764c573 100644
--- a/src/conn.rs
+++ b/src/conn.rs
@@ -60,9 +60,9 @@ pub async fn lobby(socket: WebSocket, addr: SocketAddr, rinfo: (RoomId,Arc<RwLoc
 pub async fn handle_room(streams: (SplitStream<WebSocket>,tokio::sync::mpsc::UnboundedSender<Message>), addr: SocketAddr, rinfo: (RoomId, Arc<RwLock<Room>>)) {
     let (mut incoming, tx) = streams;
     let (room_id, room) = rinfo;
-    let (players, cmd_tx) = {
+    let (players, cmd_tx, room_conf) = {
         let room = room.read().await;
-        (room.players.clone(), room.cmd_stream.clone())
+        (room.players.clone(), room.cmd_stream.clone(), room.conf.clone())
     };
     while let Ok(cmd) = incoming.try_next().await {
         if let Some(cmd) = cmd {
@@ -154,7 +154,7 @@ pub async fn handle_room(streams: (SplitStream<WebSocket>,tokio::sync::mpsc::Unb
                                 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.conf.board_conf))).expect("couldn't send register ack");
+                            tx.send(Message::text(format!("regack {} {} {} {}", room_conf.name, name.replace(" ", "&nbsp"), uid, room_conf.board_conf))).expect("couldn't send register ack");
                             if let Err(e) = room.read().await.cmd_stream.send(MetaMove::Dump) {
                                 println!("{room_id} E: couldn't request game dump in behalf of {addr}: {e}");
                             }
diff --git a/src/types.rs b/src/types.rs
index d467982..2d6ae22 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -24,7 +24,7 @@ pub struct Config {
     pub socket_addr: SocketAddr,
 }
 
-#[derive(Debug, Serialize)]
+#[derive(Debug, Serialize, Clone)]
 pub struct RoomConf {
     pub name: String,
     pub player_cap: usize,
-- 
cgit v1.2.3