From 368d6585c4b943aaa8014679c907dac0cfe5cb33 Mon Sep 17 00:00:00 2001 From: Dane Johnson Date: Fri, 14 Oct 2022 11:36:45 -0500 Subject: [PATCH] Refactor so game loop can hold "player" objects --- public/index.html | 2 +- src/client.rs | 17 ++++++++---- src/game.rs | 69 +++++++++++++++++++++++------------------------ src/lib.rs | 2 +- 4 files changed, 48 insertions(+), 42 deletions(-) diff --git a/public/index.html b/public/index.html index 735d468..593b326 100644 --- a/public/index.html +++ b/public/index.html @@ -57,7 +57,7 @@ break; case "CHAT": let text = $("textarea").val(); - text = text += `\n${args[0]}`; + text = text += `${args[0]}\n`; $("textarea").val(text); default: console.log("Unhandled message", msg); diff --git a/src/client.rs b/src/client.rs index 7739f0b..f18db25 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,5 +1,6 @@ use std::sync::Arc; +use tokio::sync::Mutex; use futures::{select, FutureExt}; use crate::{msg, GlobalState}; @@ -44,18 +45,23 @@ impl Client { match msg.command.as_str() { "HOST" => { let room_code = self.global_state.code_generator.lock().await.generate(); - let game_controller = GameController::default(); + let game_controller = Arc::new(Mutex::new(GameController::default())); let (client_channel, server_channel) = channel_pair(); self.channel = Some(client_channel); - game_controller.channels.lock().await.push(server_channel); + game_controller.lock().await.push(server_channel); self.global_state .rooms .lock() .await - .insert(room_code.clone(), game_controller.clone()); - tokio::spawn(async move { game_controller.run_loop().await }); + .insert(room_code.clone(), Arc::clone(&game_controller)); + tokio::spawn(async move { + loop { + game_controller.lock().await.poll().await; + tokio::task::yield_now().await; + } + }); self.ws.send(msg!(ROOM_CODE, room_code)).await.unwrap(); } "JOIN" => { @@ -67,8 +73,9 @@ impl Client { Some(room) => { let (client_channel, server_channel) = channel_pair(); self.channel = Some(client_channel); - room.channels.lock().await.push(server_channel); + room.lock().await.push(server_channel); self.ws.send(msg!(JOIN_OK)).await.unwrap(); + } None => { self.ws.send(msg!(JOIN_INVALID)).await.unwrap(); diff --git a/src/game.rs b/src/game.rs index 6d620f4..e1036c2 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,20 +1,17 @@ -use std::sync::Arc; - -use tokio::sync::{ mpsc, Mutex }; +use tokio::sync::mpsc; use tokio::sync::mpsc::error::TryRecvError; use crate::message::Message; -#[derive(Clone)] -pub struct GameController { - pub channels: Arc>, +struct Player { + name: String, + channel: Option, + seat: Option, } -impl std::default::Default for GameController { - fn default() -> Self { - let channels = Arc::new(Mutex::new(Channels::default())); - GameController { channels } - } +#[derive(Default)] +pub struct GameController { + players: Vec, } pub struct Channel { @@ -22,26 +19,32 @@ pub struct Channel { pub rx: mpsc::Receiver, } -#[derive(Default)] -pub struct Channels(Vec); - -impl Channels { +impl GameController { pub fn try_recv(&mut self) -> Result { - for channel in self.0.iter_mut() { - let res = channel.rx.try_recv(); - if !(res == Err(TryRecvError::Empty)) { - return res + for player in self.players.iter_mut() { + if let Some(channel) = &mut player.channel { + let res = channel.rx.try_recv(); + if !(res == Err(TryRecvError::Empty)) { + return res + } } } Err(TryRecvError::Empty) } pub async fn broadcast(&mut self, msg: Message) { - for channel in self.0.iter_mut() { - channel.tx.send(msg.clone()).await.unwrap(); + for player in self.players.iter() { + if let Some(channel) = &player.channel { + channel.tx.send(msg.clone()).await.unwrap(); + } } } pub fn push(&mut self, channel: Channel) { - self.0.push(channel); + let player = Player { + name: "Guest".to_string(), + channel: Some(channel), + seat: None, // TODO + }; + self.players.push(player); } } @@ -52,19 +55,15 @@ pub fn channel_pair() -> (Channel, Channel) { } impl GameController { - pub async fn run_loop(&self) { - loop { - let mut channels = self.channels.lock().await; - if let Ok(msg) = channels.try_recv() { - dispatch(&mut channels, msg).await; - } + pub async fn poll(&mut self) { + if let Ok(msg) = self.try_recv() { + self.dispatch(msg).await; } } -} - -async fn dispatch(channels: &mut Channels, msg: Message) { - match msg.command.as_str() { - "CHAT" => channels.broadcast(msg).await, - _ => () - }; + async fn dispatch(&mut self, msg: Message) { + match msg.command.as_str() { + "CHAT" => self.broadcast(msg).await, + _ => () + }; + } } diff --git a/src/lib.rs b/src/lib.rs index 9d6f7b4..0fe2878 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,5 +14,5 @@ use code_generator::CodeGenerator; #[derive(Default)] pub struct GlobalState { pub code_generator: Arc>, - pub rooms: Arc>>, + pub rooms: Arc>>>>, }