diff --git a/server/src/games/run.rs b/server/src/games/run.rs index 9009f51..af9f3e7 100644 --- a/server/src/games/run.rs +++ b/server/src/games/run.rs @@ -16,8 +16,7 @@ pub use types::{CardId, CardIdx, PileKind, RunningPile}; use types::{Data, Player, RhaiResult}; pub struct RunningGame { - #[allow(unused)] // TODO Remove - name: String, + pub name: String, pub piles: HashMap, pub player_piles: Vec>, functions: Functions, diff --git a/server/src/server/game.rs b/server/src/server/game.rs index 35a2304..6b4bd0f 100644 --- a/server/src/server/game.rs +++ b/server/src/server/game.rs @@ -3,100 +3,112 @@ use super::{ socket_manager::SocketManager, ServiceData, }; -use crate::{games::{CardId, CardIdx, PileKind, RunningPile}, server::protos::{game::game_status::CustomInfoMessage, protocol::server_client_packet::Data}}; +use crate::{games::{CardId, CardIdx, PileKind, RunningPile}, server::protos::{game::game_status::CustomInfoMessage, protocol::server_client_packet::{self, Data}}}; use anyhow::{anyhow, Result}; -pub(super) async fn get_status(data: &mut ServiceData) -> Result { +pub(super) async fn get_status(data: &mut ServiceData, + socket_mgr: &SocketManager,) -> Result { let uuid = data.user_id.get()?; log::info!("Creating a new status for {}", uuid); let lobby: u32 = match data.db.get_lobby_for_user(uuid).await { Some(l) => l, None => return Err(anyhow!("User isn't in a lobby")), }; - let games_lock = data.running_games.read().await; // This encounters a deadlock + let (status, name) = { + let games_lock = data.running_games.read().await; // This encounters a deadlock // log::info!("Locked games"); - let game_lock = match games_lock.get(&lobby) { - Some(x) => x.read().await, - None => return Err(anyhow!("User isn't in a lobby with a running game",)), - }; - // log::info!("Locked game"); - let game = &game_lock.1; - let mut names = vec![]; - for (uuid, id) in &game.players { - names.push((data.db.get_name_for_uuid(*uuid).await, *id)) - } - names.sort_by(|(_, a), (_, b)| a.cmp(b)); - let names = names - .into_iter() - .map(|(x, _)| super::protos::common::Name { name: x }) - .collect(); - let status = GameStatus { - current_turn: game.get_current_player(), - common_piles: Some(Piles { - piles: game - .piles - .iter() - .map(|(k, v)| (k.clone(), v.clone())) - .map(|(k, v): (String, RunningPile)| { - ( - k, - super::protos::game::game_status::Pile { - cards: v - .cards - .into_iter() - .map(|c| super::protos::game::game_status::Card { - kind: Some(CardKind { kind: c.kind }), - visible: true, - uuid: c.uuid.to_string(), - }) - .collect(), - face_down: v.face_down, - visible: v.visible, - name: v.name, - }, - ) - }) - .collect(), - }), - player_piles: game - .player_piles - .clone() + let game_lock = match games_lock.get(&lobby) { + Some(x) => x.read().await, + None => return Err(anyhow!("User isn't in a lobby with a running game",)), + }; + // log::info!("Locked game"); + let game = &game_lock.1; + let mut names = vec![]; + for (uuid, id) in &game.players { + names.push((data.db.get_name_for_uuid(*uuid).await, *id)) + } + names.sort_by(|(_, a), (_, b)| a.cmp(b)); + let names = names .into_iter() - .map(|piles| Piles { - piles: piles + .map(|(x, _)| super::protos::common::Name { name: x }) + .collect(); + ( + GameStatus { + current_turn: game.get_current_player(), + common_piles: Some(Piles { + piles: game + .piles + .iter() + .map(|(k, v)| (k.clone(), v.clone())) + .map(|(k, v): (String, RunningPile)| { + ( + k, + super::protos::game::game_status::Pile { + cards: v + .cards + .into_iter() + .map(|c| super::protos::game::game_status::Card { + kind: Some(CardKind { kind: c.kind }), + visible: true, + uuid: c.uuid.to_string(), + }) + .collect(), + face_down: v.face_down, + visible: v.visible, + name: v.name, + }, + ) + }) + .collect(), + }), + player_piles: game + .player_piles + .clone() .into_iter() - .map(|(k, v)| { - ( - k, - super::protos::game::game_status::Pile { - cards: v - .cards - .into_iter() - .map(|x| super::protos::game::game_status::Card { - kind: Some(CardKind { kind: x.kind }), - visible: true, - uuid: x.uuid.to_string(), - }) - .collect(), - face_down: v.face_down, - visible: v.visible, - name: v.name, - }, - ) + .map(|piles| Piles { + piles: piles + .into_iter() + .map(|(k, v)| { + ( + k, + super::protos::game::game_status::Pile { + cards: v + .cards + .into_iter() + .map(|x| super::protos::game::game_status::Card { + kind: Some(CardKind { kind: x.kind }), + visible: true, + uuid: x.uuid.to_string(), + }) + .collect(), + face_down: v.face_down, + visible: v.visible, + name: v.name, + }, + ) + }) + .collect(), }) .collect(), - }) - .collect(), - names, - has_finished: game.has_finished, - info: None, + names, + has_finished: game.has_finished, + info: None, + }, + game.name.clone(), + ) }; log::info!("Created a new status for {}", uuid); + if status.has_finished { + log::info!("Game has finished: {}", name); + data.running_games.write().await.remove(&lobby); + let s = super::lobby::get_status(data).await.expect("Unexpected error getting lobby status"); + socket_mgr.broadcast_to_lobby(&mut data.db, data.user_id.0.unwrap(), server_client_packet::Data::LobbyStatus(s)).await.expect("Error sending finished game "); + } Ok(status) } pub(super) async fn query_status(data: &mut ServiceData, socket_mgr: &SocketManager) -> Result<()> { - let status = get_status(data).await?; + let status = get_status(data, socket_mgr).await?; socket_mgr .write(data.user_id.get_ref()?, Data::GameStatus(status)) .await @@ -177,10 +189,13 @@ pub(super) async fn on_click( pile_name: card.pile_name, }; if let Err(e) = game.on_click(card, game.get_player_for_uuid(&uuid).unwrap()) { - message = Some(CustomInfoMessage { title: "Error in game execution".to_string(), m: e.to_string() }); + message = Some(CustomInfoMessage { + title: "Error in game execution".to_string(), + m: e.to_string(), + }); } } // drop the connection so that the lock is released - let mut status = get_status(data).await?; + let mut status = get_status(data, socket_mgr).await?; status.info = message; socket_mgr diff --git a/server/src/server/lobby.rs b/server/src/server/lobby.rs index cb2887b..7de3d6e 100644 --- a/server/src/server/lobby.rs +++ b/server/src/server/lobby.rs @@ -24,7 +24,7 @@ pub(super) async fn vote( Ok(()) } -async fn get_status(data: &mut ServiceData) -> Result { +pub(super) async fn get_status(data: &mut ServiceData) -> Result { let uuid = data.user_id.get()?; if let Some(l) = data.db.get_lobby_for_user(uuid).await { let (votes, is_starting) = data.voting.status(&l).await.unwrap_or_default(); @@ -67,7 +67,7 @@ pub(super) async fn ready(data: &mut ServiceData, socket_mgr: &SocketManager) -> .await?; log::info!("Player {} is ready", uuid); if is_starting { - let game_status = super::game::get_status(data).await?; + let game_status = super::game::get_status(data, socket_mgr).await?; socket_mgr .broadcast_to_lobby( &mut data.db,