diff options
| -rw-r--r-- | Cargo.lock | 37 | ||||
| -rw-r--r-- | Cargo.toml | 2 | ||||
| -rw-r--r-- | assets/index.html | 23 | ||||
| -rw-r--r-- | src/conn.rs | 2 | ||||
| -rw-r--r-- | src/main.rs | 52 | 
5 files changed, 106 insertions, 10 deletions
| @@ -190,6 +190,21 @@ dependencies = [  ]  [[package]] +name = "futures" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]]  name = "futures-channel"  version = "0.3.21"  source = "registry+https://github.com/rust-lang/crates.io-index" @@ -206,6 +221,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"  checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"  [[package]] +name = "futures-executor" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" + +[[package]]  name = "futures-macro"  version = "0.3.21"  source = "registry+https://github.com/rust-lang/crates.io-index" @@ -234,10 +266,13 @@ version = "0.3.21"  source = "registry+https://github.com/rust-lang/crates.io-index"  checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"  dependencies = [ + "futures-channel",   "futures-core", + "futures-io",   "futures-macro",   "futures-sink",   "futures-task", + "memchr",   "pin-project-lite",   "pin-utils",   "slab", @@ -1410,7 +1445,7 @@ version = "1.0.0"  dependencies = [   "ammonia",   "flate2", - "futures-util", + "futures",   "rand",   "serde",   "serde_json", @@ -13,5 +13,5 @@ serde_json = "1.0"  flate2 = "1.0"  warp = { version = "0.3", features = ["tls", "websocket"] }  rand = "0.8" -futures-util = "0.3" +futures = "0.3"  ammonia = "3" diff --git a/assets/index.html b/assets/index.html index 9517529..f85b733 100644 --- a/assets/index.html +++ b/assets/index.html @@ -7,16 +7,23 @@      <link rel="stylesheet" type="text/css" href="./s.css">    </head>    <body> -    <div id="rlist" class="cent"></div> +    <div class="cent"> +      <div id="rlist"></div> +      <span id="rspace"></span> +    </div>      <script>        let rlist = document.getElementById('rlist'); -      fetch('rlist').then(r => r.json()).then(rooms => { +      fetch('rlist').then(r => r.json()).then(info => { +        let rooms = info[0]; +        let pcounts = info[1];          Object.keys(rooms).forEach(x => {            let roominfo = JSON.parse(rooms[x]); +          let pc = Number(pcounts[x]);            let bc = roominfo.board_conf;            let a = document.createElement('a');            let h1 = document.createElement('h1'); -                h1.appendChild(document.createTextNode(`> ${roominfo.name}`)); +          let ptxt = (pc > 0)? ((pc > 1)? `${pc} players`: `${pc} player`) : "no players"; +          h1.appendChild(document.createTextNode(`> ${roominfo.name} — ${ptxt}`));            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); @@ -26,6 +33,16 @@            rlist.append(document.createElement('br'));          });        }); +      fetch("rspace").then(resp => resp.text()).then(roomspace => { +          let roomspacenum = Number(roomspace); +          let e = document.getElementById('rspace'); +          let t = document.createTextNode("room slots filled, if a room empties of active players it can be replaced by a new one"); +          if (roomspacenum == 1) { +            e.appendChild(document.createTextNode(`there is one available room slot`)); +          } else if (roomspacenum > 1) { +                  e.appendChild(document.createTextNode(`there are ${roomspacenum} available room slots`)); +          } +      })      </script>      <form method="post" action="r" class="cent">        <fieldset> diff --git a/src/conn.rs b/src/conn.rs index af7903f..71beb5d 100644 --- a/src/conn.rs +++ b/src/conn.rs @@ -4,7 +4,7 @@ use std::{      net::SocketAddr,  };  use tokio::sync::RwLock; -use futures_util::{SinkExt, StreamExt, TryStreamExt, stream::SplitStream}; +use futures::{SinkExt, StreamExt, TryStreamExt, stream::SplitStream};  use warp::ws::{ WebSocket, Message };  use ammonia; diff --git a/src/main.rs b/src/main.rs index 66b2cfd..36ee5ce 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ use std::{      collections::HashMap,      num::NonZeroUsize,  }; +use futures::stream::StreamExt;  mod types;  mod conn; @@ -15,6 +16,7 @@ use tokio::sync::RwLock;  const FONT_FILE: &[u8] = include_bytes!("../assets/VT323-Regular.ttf");  const AREA_LIMIT: usize = 150*150; +const ROOM_LIMIT: usize = 8;  fn main() -> Result<(), Box<dyn Error>> {      let conf = Config { @@ -41,15 +43,45 @@ async fn tokio_main(conf: Config) -> Result<(), Box<dyn Error>> {      let code = path!("c.js").and(fs::file(conf.client_code.clone()));      let font = path!("f.ttf").map(|| FONT_FILE);      let listing = { +        let rooms = rooms.clone();          let pubs = public_rooms.clone();          path!("rlist").and_then(move || { +            let rooms = rooms.clone();              let pubs = pubs.clone();              async move { -                let map = pubs.read().await; +                let roomsl = rooms.read().await; +                let pubsl = pubs.read().await; +                let rooms_pcount = futures::stream::iter(pubsl.iter()) +                    .then(|(id, _):(&RoomId,_)| { +                        let roomsl = roomsl.clone(); +                        async move { +                            (id.clone(), roomsl.get(id).unwrap().read().await.players.read().await.len()) +                        } +                    }) +                    .collect::<HashMap<RoomId,_>>().await; +                let resp = (&*pubsl, rooms_pcount);                  Ok::<_,std::convert::Infallible>( -                    reply::json(&*map) -            ) -        }}) +                    reply::json(&resp) +                ) +            } +        }) +    }; +    let roomspace = { +        let rooms = rooms.clone(); + +        path!("rspace").and_then(move || { +            let r = rooms.clone(); +            async move { +                let empty_len = empty_rooms(r.clone()).await.len(); +                let space = ROOM_LIMIT - r.read().await.len() + empty_len; +                Ok::<_,std::convert::Infallible>( +                    hyper::Response::builder() +                        .status(hyper::StatusCode::OK) +                        .body(hyper::Body::from(space.to_string())) +                        .unwrap() +                ) +            } +        })      };      let rform_recv = {          let rooms = rooms.clone(); @@ -159,6 +191,7 @@ async fn tokio_main(conf: Config) -> Result<(), Box<dyn Error>> {          .or(code)          .or(font)          .or(listing) +        .or(roomspace)          .or(rform_recv)          .or(room)          .recover(error_handler); @@ -238,3 +271,14 @@ async fn error_handler(err: Rejection) -> Result<impl Reply, std::convert::Infal      }  } +async fn empty_rooms(rooms: RoomMap) -> Vec<RoomId> { +    let rl = rooms.read().await; +    futures::stream::iter(rl.iter()) +        .filter_map(|(id,roomarc)| async move { +            let rrl = roomarc.read().await; +            let rrrl = rrl.players.read().await; +            if rrrl.len() == 0 { Some(id.clone()) } else { None } +        }) +        .collect::<Vec<RoomId>>().await +} + | 
