diff --git a/server/src/server/game.rs b/server/src/server/game.rs index c95f1b0..11a2a37 100644 --- a/server/src/server/game.rs +++ b/server/src/server/game.rs @@ -145,6 +145,7 @@ impl GameService { } async fn get_default_status(&self, uuid: uuid::Uuid) -> Result, Status> { + log::info!("Creating a new status for {}", uuid); let lobby = { let mut conn = self.conn.write().await; let lobby: u32 = match conn.get_lobby_for_user(uuid).await { @@ -153,6 +154,7 @@ impl GameService { }; lobby }; + let r = Ok(self .running_games .read() @@ -165,7 +167,9 @@ impl GameService { .await .2 .get() - .clone()) + .clone()); + log::info!("Created a new status for {}", uuid); + r } } @@ -175,6 +179,8 @@ impl game_server::Game for GameService { &self, request: tonic::Request, ) -> Result, Status> { + log::info!("Getting image location"); + let time = std::time::Instant::now(); let uuid = client_id::get(request.metadata()).map_err(|x| match x { client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), @@ -194,16 +200,20 @@ impl game_server::Game for GameService { }; let game = &self.games[game_id as usize]; let (face, back) = game.get_card_paths(&request.into_inner().kind); + log::info!("Loading face image [{:?}]", time.elapsed()); // TODO Create a cache for loaded images, so that they don't have to be parsed and reformatted each time let mut face_buf = Vec::new(); image::open(&face) .expect(&format!("Error loading the image in {:?}", face)) .write_to(&mut face_buf, image::ImageOutputFormat::Png) .unwrap(); + log::info!("Loading back image [{:?}]", time.elapsed()); let mut back_buf = Vec::new(); image::open(&back) .expect(&format!("Error loading the image in {:?}", back)) .write_to(&mut back_buf, image::ImageOutputFormat::Png) .unwrap(); + + log::info!("Loaded images [{:?}]", time.elapsed()); Ok(Response::new(Image { face: face_buf, back: back_buf, @@ -263,9 +273,10 @@ impl game_server::Game for GameService { })?; Ok(Response::new( - self.get_default_status(uuid) - .await? - .ok_or(Status::internal("No status has been set"))?, + self.get_default_status(uuid).await?.unwrap_or({ + self.update_status(uuid).await?; + self.get_default_status(uuid).await?.unwrap() + }), )) } @@ -286,7 +297,8 @@ impl game_server::Game for GameService { lobby }; use std::convert::TryInto; - let has_changed = self.running_games + let has_changed = self + .running_games .read() .await .get(&lobby) @@ -304,6 +316,6 @@ impl game_server::Game for GameService { .try_into() .unwrap(), ); - Ok(Response::new(HasNewStatus {value: has_changed})) + Ok(Response::new(HasNewStatus { value: has_changed })) } } diff --git a/server/src/server/lobby.rs b/server/src/server/lobby.rs index 30748d7..7184b78 100644 --- a/server/src/server/lobby.rs +++ b/server/src/server/lobby.rs @@ -5,9 +5,9 @@ use tokio::sync::{mpsc, RwLock}; use std::{collections::HashMap, convert::TryInto, sync::Arc}; use super::grpc::common::{HasNewStatus, LastStatusTimestamp, Name}; +use super::grpc::game::MessageStatus; use super::grpc::lobby::lobby_server::Lobby; use super::grpc::lobby::{LobbyStatus, SingleVote, Vote}; -use super::grpc::game::MessageStatus; pub use super::grpc::lobby::lobby_server::LobbyServer; @@ -18,137 +18,143 @@ use super::client_id; use crate::{db, games::RunningGame}; pub struct LobbyService { - conn: RwLock, - games: Arc>, - voting: votes::VotingSystem, - running_games: Arc>)>>>>, + conn: RwLock, + games: Arc>, + voting: votes::VotingSystem, + running_games: + Arc>)>>>>, } impl LobbyService { - pub fn new( - conn: db::DbClient, - voting: votes::VotingSystem, - games: Arc>, - running_games: Arc>)>>>>, - ) -> Self { - Self { - conn: RwLock::new(conn), - voting, - running_games, - games, - } - } + pub fn new( + conn: db::DbClient, + voting: votes::VotingSystem, + games: Arc>, + running_games: Arc< + RwLock>)>>>, + >, + ) -> Self { + Self { + conn: RwLock::new(conn), + voting, + running_games, + games, + } + } } #[tonic::async_trait] impl Lobby for LobbyService { - async fn vote(&self, request: Request) -> Result, Status> { - let uuid = client_id::get(request.metadata()).map_err(|x| match x { - client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), - client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), - })?; - let req = request.into_inner(); - self.voting.vote(uuid, req.game).await; - Ok(Response::new(())) - } - - async fn ready(&self, request: Request<()>) -> Result, Status> { - let uuid = client_id::get(request.metadata()).map_err(|x| match x { - client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), - client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), - })?; - if let Some(Some(winner)) = self.voting.ready(uuid).await { - let mut conn = self.conn.write().await; - let lobby = conn.get_lobby_for_user(uuid).await.unwrap(); - log::info!("[{}] Starting a game ({})", lobby, winner); - let user_count = conn.get_uuids_in_lobby_where_user_is(uuid).await; - let game = self.games[winner as usize].run(&user_count); - self.running_games - .write() - .await - .insert(lobby, RwLock::new((winner, game, Modifiable::new(None)))); - } - Ok(Response::new(())) - } - - async fn poll_status( - &self, - request: Request, - ) -> Result, Status> { - // let uuid = client_id::get(request.metadata()).map_err(|x| match x { - // client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), - // client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), - // })?; - // let mut conn = self.conn.acquire().await; - - let inner = request.into_inner(); - let time = inner - .time - .ok_or(Status::failed_precondition("timestamp musn't be null"))? - .try_into() - .unwrap(); - Ok(Response::new(HasNewStatus { - value: self.voting.has_new_status(&inner.lobby, time).await, - })) - } - - async fn get_status(&self, request: Request<()>) -> Result, Status> { - let uuid = client_id::get(request.metadata()).map_err(|x| match x { - client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), - client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), - })?; - let mut conn = self.conn.write().await; - if let Some(l) = conn.get_lobby_for_user(uuid).await { - let (votes, is_starting) = self.voting.status(&l).await.unwrap_or_default(); - let names = conn.get_users_in_lobby_where_user_is(uuid).await; - // log::info!("Users: {:?}", names); - Ok(Response::new(LobbyStatus { - names: names.into_iter().map(|x| Name { name: x }).collect(), - votes: votes - .into_iter() - .map(|(player, game, ready)| Vote { - player, - game, - ready, - }) - .collect(), - is_starting, - })) - } else { - Err(Status::failed_precondition("User isn't in a lobby")) - } - } - - async fn leave( - &self, - request: tonic::Request<()>, - ) -> Result, tonic::Status> { - let uuid = client_id::get(request.metadata()).map_err(|x| match x { - client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), - client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), - })?; - let mut conn = self.conn.write().await; - if let Some(l) = conn.get_lobby_for_user(uuid).await { - // log::info!("Updating lobby status"); - self.voting.updated_users(&l).await; - // log::info!("Updated lobby status"); - } - conn.leave_lobby(uuid).await; - Ok(Response::new(())) - } - - type usersStream = mpsc::UnboundedReceiver>; - - async fn users(&self, request: Request<()>) -> Result, Status> { - let uuid = client_id::get(request.metadata()).map_err(|x| match x { - client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), - client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), - })?; - let (sender, receiver) = mpsc::unbounded_channel(); - let mut conn = self.conn.write().await; - for name in conn.get_users_in_lobby_where_user_is(uuid).await { - sender.send(Ok(Name { name })).unwrap(); - } - Ok(Response::new(receiver)) - } + async fn vote(&self, request: Request) -> Result, Status> { + let uuid = client_id::get(request.metadata()).map_err(|x| match x { + client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), + client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), + })?; + let req = request.into_inner(); + self.voting.vote(uuid, req.game).await; + Ok(Response::new(())) + } + + async fn ready(&self, request: Request<()>) -> Result, Status> { + let uuid = client_id::get(request.metadata()).map_err(|x| match x { + client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), + client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), + })?; + if let Some(Some(winner)) = self.voting.ready(uuid).await { + let mut conn = self.conn.write().await; + let lobby = conn.get_lobby_for_user(uuid).await.unwrap(); + log::info!("[{}] Starting a game ({})", lobby, winner); + let user_count = conn.get_uuids_in_lobby_where_user_is(uuid).await; + let game = self.games[winner as usize].run(&user_count); + self.running_games + .write() + .await + .insert(lobby, RwLock::new((winner, game, Modifiable::new(None)))); + log::info!("[{}] Started a game ({})", lobby, winner); + } + log::info!("Player {} is ready", uuid); + + Ok(Response::new(())) + } + + async fn poll_status( + &self, + request: Request, + ) -> Result, Status> { + // let uuid = client_id::get(request.metadata()).map_err(|x| match x { + // client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), + // client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), + // })?; + // let mut conn = self.conn.acquire().await; + + let inner = request.into_inner(); + let time = inner + .time + .ok_or(Status::failed_precondition("timestamp musn't be null"))? + .try_into() + .unwrap(); + Ok(Response::new(HasNewStatus { + value: self.voting.has_new_status(&inner.lobby, time).await, + })) + } + + async fn get_status(&self, request: Request<()>) -> Result, Status> { + let uuid = client_id::get(request.metadata()).map_err(|x| match x { + client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), + client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), + })?; + let mut conn = self.conn.write().await; + if let Some(l) = conn.get_lobby_for_user(uuid).await { + let (votes, is_starting) = self.voting.status(&l).await.unwrap_or_default(); + let names = conn.get_users_in_lobby_where_user_is(uuid).await; + // log::info!("Users: {:?}", names); + Ok(Response::new(LobbyStatus { + names: names.into_iter().map(|x| Name { name: x }).collect(), + votes: votes + .into_iter() + .map(|(player, game, ready)| Vote { + player, + game, + ready, + }) + .collect(), + is_starting, + })) + } else { + Err(Status::failed_precondition("User isn't in a lobby")) + } + } + + async fn leave( + &self, + request: tonic::Request<()>, + ) -> Result, tonic::Status> { + let uuid = client_id::get(request.metadata()).map_err(|x| match x { + client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), + client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), + })?; + let mut conn = self.conn.write().await; + if let Some(l) = conn.get_lobby_for_user(uuid).await { + // log::info!("Updating lobby status"); + self.voting.updated_users(&l).await; + // log::info!("Updated lobby status"); + } + conn.leave_lobby(uuid).await; + Ok(Response::new(())) + } + + type usersStream = mpsc::UnboundedReceiver>; + + async fn users(&self, request: Request<()>) -> Result, Status> { + let uuid = client_id::get(request.metadata()).map_err(|x| match x { + client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), + client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), + })?; + let (sender, receiver) = mpsc::unbounded_channel(); + let mut conn = self.conn.write().await; + for name in conn.get_users_in_lobby_where_user_is(uuid).await { + sender.send(Ok(Name { name })).unwrap(); + } + Ok(Response::new(receiver)) + } } diff --git a/unity/Assets/Scripts/Client.cs b/unity/Assets/Scripts/Client.cs index 20712eb..f3ac285 100644 --- a/unity/Assets/Scripts/Client.cs +++ b/unity/Assets/Scripts/Client.cs @@ -103,7 +103,7 @@ public static class Client }, new Metadata { new Metadata.Entry("client_id", connId) } ).Value; - // Debug.Log("HasNewStatus: " + hasNew); + Debug.Log("HasNewStatus: " + hasNew); if (hasNew) { lobby_status.Set(lobby_client.getStatus(new Google.Protobuf.WellKnownTypes.Empty(), new Metadata { new Metadata.Entry("client_id", connId) })); hasChanged = true; diff --git a/unity/Assets/Scripts/MainMenuController.cs b/unity/Assets/Scripts/MainMenuController.cs index 73e3c7e..4cc742d 100644 --- a/unity/Assets/Scripts/MainMenuController.cs +++ b/unity/Assets/Scripts/MainMenuController.cs @@ -70,7 +70,7 @@ public class MainMenuController : MonoBehaviour { } } - void FixedUpdate() { + void Update() { var conn = Client.GetConnection(); if (conn != null) { if(SceneManager.GetActiveScene().buildIndex == 0) {