Browse Source

Send lobby status when game finishes

main
ThePerkinrex 4 years ago
parent
commit
4bad9c0b04
No known key found for this signature in database GPG Key ID: FD81DE6D75E20917
  1. 3
      server/src/games/run.rs
  2. 169
      server/src/server/game.rs
  3. 4
      server/src/server/lobby.rs

3
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<String, RunningPile>,
pub player_piles: Vec<HashMap<String, RunningPile>>,
functions: Functions,

169
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<GameStatus> {
pub(super) async fn get_status(data: &mut ServiceData,
socket_mgr: &SocketManager,) -> Result<GameStatus> {
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

4
server/src/server/lobby.rs

@ -24,7 +24,7 @@ pub(super) async fn vote(
Ok(())
}
async fn get_status(data: &mut ServiceData) -> Result<LobbyStatus> {
pub(super) async fn get_status(data: &mut ServiceData) -> Result<LobbyStatus> {
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,

Loading…
Cancel
Save