use std::collections::HashSet; use super::messages::{ClientMessage, ServerMessage}; // send a ServerMessage::Connections to all sockets pub async fn send_connections(v: &mut super::Clients, added: Option, removed: Option, frame: u64) { // get the list of connection IDs let connections: Vec = v.iter() .enumerate() .filter(|(_, n)| n.is_some()) .map(|(id, _)| id) .collect(); super::send(v, |id, _c| { Some(ServerMessage::Connections { connections: connections.clone(), added, removed, id, frame, }) }).await; } // handle incoming websocket messages pub async fn handle( v: &mut super::Clients, requests: &mut HashSet<(u64, Option, usize)>, // frame, connection, client id pending: &mut Vec<(Option, Option)>, id: usize, msg: ClientMessage, ) { match msg { // broadcast inputs to every other connection ClientMessage::Input { data, frame } => { super::broadcast(v, ServerMessage::Input { data, frame, connection: id }, Some(id)).await; }, // a client needs the current game state, grab it from another client ClientMessage::RequestState { frame, connection } => { let count = super::conn_count(v); if count < 2 { // nobody to request state *from* if let Some(Some(client)) = v.get(id) { client.send(ServerMessage::State { state: serde_json::Value::Null, frame: 0, connection: None, }).await.ok(); } return; } // request state from other clients requests.insert((frame, connection, id)); match connection { None => { super::broadcast(v, ServerMessage::RequestState { frame }, Some(id)).await; }, Some(id) => { // it's to a specific connection let Some(Some(client)) = v.get(id) else { return; }; client.send(ServerMessage::RequestState { frame }).await.ok(); }, } }, // a client responded to a request for game state, tell all the requestees ClientMessage::State { state, frame } => { let mut new_requests = HashSet::new(); for (fr, conn, cid) in requests.drain() { if fr != frame || // this isn't the requested frame (conn.is_some() && Some(id) != conn) // this isn't the requested connection { new_requests.insert((fr, conn, cid)); continue; } if let Some(Some(client)) = v.get(cid) { client.send(ServerMessage::State { state: state.clone(), frame, connection: Some(id), }).await.ok(); } } *requests = new_requests; }, // a client said what frame they're on, actually send the connections message ClientMessage::Frame { frame } => { for (added, removed) in pending.into_iter() { send_connections(v, *added, *removed, frame).await; } *pending = Vec::new(); }, ClientMessage::Ping { frame } => { if let Some(Some(client)) = v.get(id) { client.send(ServerMessage::Pong { frame }).await.ok(); } } } }