bugfix: more reliable role reveal

This commit is contained in:
emilis 2025-12-04 00:12:44 +00:00
parent 391e4ea6d7
commit ab401ce65c
No known key found for this signature in database
2 changed files with 44 additions and 16 deletions

View File

@ -12,7 +12,7 @@
// //
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
use core::ops::Not; use core::{ops::Not, time::Duration};
use std::sync::Arc; use std::sync::Arc;
use crate::{ use crate::{
@ -132,23 +132,43 @@ impl GameRunner {
.log_err(); .log_err();
}; };
(update_host)(&acks, &mut self.comms); (update_host)(&acks, &mut self.comms);
let notify_of_role = |player_id: PlayerId, village: &Village, sender: &LobbyPlayers| { let notify_of_role =
if let Some(char) = village.character_by_player_id(player_id) { 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 sender
.send_if_present( .send(ServerMessage::GameStart {
player_id,
ServerMessage::GameStart {
role: char.initial_shown_role(), 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 last_err_log = tokio::time::Instant::now() - tokio::time::Duration::from_secs(60);
let mut connect_list: Arc<[PlayerId]> = Arc::new([]); let mut connect_list: Arc<[PlayerId]> = Arc::new([]);
while acks.iter().any(|(_, ackd)| !*ackd) { 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, Ok(msg) => msg,
Err(err) => { Err(err) => {
if (tokio::time::Instant::now() - last_err_log).as_secs() >= 30 { 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) acks.iter_mut().find(|(c, _)| c.character_id() == char_id)
{ {
*ackd = true; *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); (update_host)(&acks, &mut self.comms);
} }
@ -233,11 +254,12 @@ impl GameRunner {
public: _, public: _,
}, },
message: _, 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) => { Message::ConnectedList(c) => {
let newly_connected = c.iter().filter(|c| connect_list.contains(*c)); let newly_connected = c.iter().filter(|c| connect_list.contains(*c));
for connected in newly_connected { 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; connect_list = c;
} }

View File

@ -980,6 +980,12 @@ input {
text-align: center; text-align: center;
align-items: center; align-items: center;
width: 100%; width: 100%;
height: 80vh;
justify-content: center;
&>p {
font-size: 1.5em;
}
&>button { &>button {
font-size: 1.5rem; font-size: 1.5rem;