From ab401ce65c2a268b1776920faf3c69fc5caf48c6 Mon Sep 17 00:00:00 2001 From: emilis Date: Thu, 4 Dec 2025 00:12:44 +0000 Subject: [PATCH] bugfix: more reliable role reveal --- werewolves-server/src/game.rs | 54 ++++++++++++++++++++++++----------- werewolves/index.scss | 6 ++++ 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/werewolves-server/src/game.rs b/werewolves-server/src/game.rs index 8c0872d..bf17170 100644 --- a/werewolves-server/src/game.rs +++ b/werewolves-server/src/game.rs @@ -12,7 +12,7 @@ // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use core::ops::Not; +use core::{ops::Not, time::Duration}; use std::sync::Arc; use crate::{ @@ -132,23 +132,43 @@ impl GameRunner { .log_err(); }; (update_host)(&acks, &mut self.comms); - let notify_of_role = |player_id: PlayerId, village: &Village, sender: &LobbyPlayers| { - if let Some(char) = village.character_by_player_id(player_id) { - sender - .send_if_present( - player_id, - ServerMessage::GameStart { + let notify_of_role = + async |player_id: PlayerId, village: &Village, sender: &JoinedPlayers| { + if let Some(char) = village.character_by_player_id(player_id) + && let Some(sender) = sender.get_sender(player_id).await + { + sender + .send(ServerMessage::GameStart { role: char.initial_shown_role(), - }, - ) - .log_debug(); - } - }; + }) + .log_debug(); + } + }; + let notify_non_ackd = + async |acks: &[(Character, bool)], village: &Village, sender: &JoinedPlayers| { + for pid in acks + .iter() + .filter_map(|(c, ack)| ack.not().then_some(c.player_id())) + { + (notify_of_role)(pid, village, sender).await; + } + }; let mut last_err_log = tokio::time::Instant::now() - tokio::time::Duration::from_secs(60); let mut connect_list: Arc<[PlayerId]> = Arc::new([]); while acks.iter().any(|(_, ackd)| !*ackd) { - let msg = match self.comms.message().await { + const PING_TIME: Duration = Duration::from_secs(1); + let sleep_fut = tokio::time::sleep(PING_TIME); + let msg = tokio::select! { + _ = sleep_fut => { + (notify_non_ackd)(&acks, self.game.village(), &self.joined_players).await; + continue; + } + msg = self.comms.message() => { + msg + } + }; + let msg = match msg { Ok(msg) => msg, Err(err) => { if (tokio::time::Instant::now() - last_err_log).as_secs() >= 30 { @@ -164,7 +184,8 @@ impl GameRunner { acks.iter_mut().find(|(c, _)| c.character_id() == char_id) { *ackd = true; - (notify_of_role)(c.player_id(), self.game.village(), &self.player_sender); + (notify_of_role)(c.player_id(), self.game.village(), &self.joined_players) + .await; } (update_host)(&acks, &mut self.comms); } @@ -233,11 +254,12 @@ impl GameRunner { public: _, }, message: _, - }) => (notify_of_role)(player_id, self.game.village(), &self.player_sender), + }) => (notify_of_role)(player_id, self.game.village(), &self.joined_players).await, Message::ConnectedList(c) => { let newly_connected = c.iter().filter(|c| connect_list.contains(*c)); for connected in newly_connected { - (notify_of_role)(*connected, self.game.village(), &self.player_sender) + (notify_of_role)(*connected, self.game.village(), &self.joined_players) + .await } connect_list = c; } diff --git a/werewolves/index.scss b/werewolves/index.scss index dda6a8b..5380187 100644 --- a/werewolves/index.scss +++ b/werewolves/index.scss @@ -980,6 +980,12 @@ input { text-align: center; align-items: center; width: 100%; + height: 80vh; + justify-content: center; + + &>p { + font-size: 1.5em; + } &>button { font-size: 1.5rem;