diff --git a/server/Cargo.toml b/server/Cargo.toml new file mode 100644 index 0000000..9731046 --- /dev/null +++ b/server/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "server" +version = "0.1.0" +edition = "2021" + +[dependencies] +itertools = "0.13.0" +rocket = { version = "0.5.1", features = ["json"] } +#word_grid = { path="../wordgrid" } +serde_json = { workspace = true } +serde = { workspace = true } +uuid = { version = "1.11.0", features = ["v4"] } +ws = { package = "rocket_ws", version = "0.1.1" } +#futures = "0.3.30" diff --git a/server/src/main.rs b/server/src/main.rs new file mode 100644 index 0000000..d3b6292 --- /dev/null +++ b/server/src/main.rs @@ -0,0 +1,87 @@ + +#[macro_use] +extern crate rocket; + +use std::collections::HashMap; +use rocket::futures::{pin_mut, FutureExt, StreamExt, SinkExt}; +use rocket::futures::stream::FusedStream; +use rocket::State; +use std::time::Duration; +use rocket::tokio::select; +use rocket::tokio::sync::broadcast::{channel, Sender}; +use rocket::tokio::sync::Mutex; +use rocket::tokio::time::interval; +use ws::Message; + +type RoomMap = HashMap::>; + +#[get("/room/")] +async fn chat(id: &str, ws: ws::WebSocket, rooms: &State>) -> ws::Channel<'static> { + let mut rooms = rooms.lock().await; + let (sender, mut receiver) = if rooms.contains_key(id) { + let sender = rooms.get(id).unwrap(); + (sender.clone(), sender.subscribe()) + + } else { + let (sender, receiver) = channel::(1024); + rooms.insert(id.to_string(), sender.clone()); + + (sender, receiver) + }; + + ws.channel(move |mut stream| Box::pin(async move { + let mut interval = interval(Duration::from_secs(10)); + while !stream.is_terminated(){ // always seems to return true? + let ws_incoming = stream.next(); + let other_incoming = receiver.recv(); + let ping_tick = interval.tick(); + + // pin_mut!(ws_incoming, other_incoming); // no clue what this does + + select! { + message = ws_incoming => { + if message.is_none() { + println!("Websocket closed"); + return Ok(()) + } + + println!("websocket received a websocket message"); + let message = message.unwrap()?; + + if let ws::Message::Close(close_frame) = &message { + println!("Received close message"); + println!("{close_frame:?}") + } else if let ws::Message::Text(text) = &message { + println!("Received text {text:?}"); + sender.send(text.to_string()).unwrap(); + } else { + println!("Received non-text message: {message:?}") + } + }, + message = other_incoming => { + let message = message.unwrap(); + println!("Sending message \"{message}\" via websocket"); + + + + let _ = stream.send(message.into()).await; // always seems to return Ok(()), even after a disconnection + //println!("Message sent: {blat:?}"); + } + _ = ping_tick => { + println!("ping_tick"); + let message = Message::Ping(Vec::new()); + let _ = stream.send(message.into()).await; + } + } + } + Ok(()) + + })) + +} + +#[launch] +fn rocket() -> _ { + rocket::build().manage(Mutex::new(RoomMap::new())) + .mount("/", routes![chat]) +} \ No newline at end of file diff --git a/server/src/test.http b/server/src/test.http new file mode 100644 index 0000000..2aca275 --- /dev/null +++ b/server/src/test.http @@ -0,0 +1,5 @@ +WEBSOCKET ws://localhost:8000/echo + +Some message + +### diff --git a/wordgrid/src/player_interaction/ai.rs b/wordgrid/src/player_interaction/ai.rs index 4cd4f26..c5da6d6 100644 --- a/wordgrid/src/player_interaction/ai.rs +++ b/wordgrid/src/player_interaction/ai.rs @@ -26,7 +26,7 @@ impl CoordinateLineMapper { } } -#[derive(Copy, Clone, Serialize, Deserialize)] +#[derive(Copy, Clone, Serialize, Deserialize, Debug)] pub struct Difficulty { pub proportion: f64, pub randomness: f64,