GameStory for client on game end

This commit is contained in:
emilis 2025-10-17 22:03:28 +01:00
parent 3602d18039
commit e57d4a3cbf
No known key found for this signature in database
5 changed files with 71 additions and 15 deletions

View File

@ -7,7 +7,11 @@ use core::num::NonZeroU8;
pub use ident::*;
use serde::{Deserialize, Serialize};
use crate::{character::CharacterId, game::GameOver, role::RoleTitle};
use crate::{
character::CharacterId,
game::{GameOver, story::GameStory},
role::RoleTitle,
};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ClientMessage {
@ -46,6 +50,7 @@ pub enum ServerMessage {
InvalidMessageForGameState,
NoSuchTarget,
GameOver(GameOver),
Story(GameStory),
Update(PlayerUpdate),
Sleep,
Reset,

View File

@ -77,6 +77,20 @@ impl JoinedPlayers {
}
}
pub async fn send_to(&self, player_ids: &[PlayerId], message: ServerMessage) {
let players: tokio::sync::MutexGuard<'_, HashMap<PlayerId, JoinedPlayer>> =
self.players.lock().await;
let senders = players
.iter()
.filter(|(pid, _)| player_ids.contains(*pid))
.map(|(pid, p)| (*pid, p.sender.clone()))
.collect::<Box<[_]>>();
core::mem::drop(players);
for (_, send) in senders {
send.send(message.clone()).log_debug();
}
}
pub async fn send_all_lobby(&self, in_lobby: Box<[PublicIdentity]>, in_lobby_ids: &[PlayerId]) {
let players: tokio::sync::MutexGuard<'_, HashMap<PlayerId, JoinedPlayer>> =
self.players.lock().await;

View File

@ -277,11 +277,17 @@ impl GameRunner {
}
}
enum ProcessOutcome {
Lobby(Lobby),
SendPlayer(PlayerId, ServerMessage),
}
pub struct GameEnd {
game: Option<GameRunner>,
page: Option<usize>,
result: GameOver,
last_error_log: Instant,
notified_connected: bool,
}
impl GameEnd {
@ -290,6 +296,7 @@ impl GameEnd {
result,
page: None,
game: Some(game),
notified_connected: false,
last_error_log: Instant::now() - core::time::Duration::from_secs(60),
}
}
@ -302,6 +309,20 @@ impl GameEnd {
}
pub async fn next(&mut self) -> Option<Lobby> {
if !self.notified_connected {
self.notified_connected = true;
let game = self.game().ok()?;
let story = game.game.story();
let player_ids = game
.player_sender
.iter()
.map(|(i, _)| i.player_id)
.collect::<Box<[_]>>();
game.joined_players
.send_to(&player_ids, ServerMessage::Story(story))
.await;
}
let msg = match self.game().unwrap().comms.message().await {
Ok(msg) => msg,
Err(err) => {
@ -313,10 +334,22 @@ impl GameEnd {
}
};
self.process(msg)
match self.process(msg)? {
ProcessOutcome::Lobby(lobby) => Some(lobby),
ProcessOutcome::SendPlayer(player_id, msg) => {
self.game()
.ok()?
.joined_players
.get_sender(player_id)
.await?
.send(msg)
.log_debug();
None
}
}
}
fn process(&mut self, message: Message) -> Option<Lobby> {
fn process(&mut self, message: Message) -> Option<ProcessOutcome> {
match message {
Message::Host(HostMessage::Echo(msg)) => {
self.game().unwrap().comms.host().send(msg).log_debug();
@ -366,7 +399,7 @@ impl GameEnd {
.send(ServerToHostMessage::Lobby(Box::new([])))
.log_debug();
let lobby = self.game.take()?.into_lobby();
return Some(lobby);
return Some(ProcessOutcome::Lobby(lobby));
}
Message::Host(_) => self
@ -378,16 +411,12 @@ impl GameEnd {
GameError::InvalidMessageForGameState,
))
.log_debug(),
Message::Client(IdentifiedClientMessage {
identity,
message: _,
}) => {
let result = self.result;
self.game()
.ok()?
.player_sender
.send_if_present(identity.player_id, ServerMessage::GameOver(result))
.log_debug();
Message::Client(IdentifiedClientMessage { identity, .. }) => {
let story = self.game().ok()?.game.story();
return Some(ProcessOutcome::SendPlayer(
identity.player_id,
ServerMessage::Story(story),
));
}
Message::ConnectedList(_) => {}
}

View File

@ -2,6 +2,7 @@ use std::rc::Rc;
use gloo::storage::errors::StorageError;
use werewolves_proto::{
game::story::GameStory,
message::{ClientMessage, Identification, PublicIdentity},
player::PlayerId,
role::RoleTitle,
@ -11,7 +12,7 @@ use yew::prelude::*;
use crate::{
clients::client::connection::{Connection2, ConnectionError},
components::{
Button, CoverOfDarkness, Identity,
Button, CoverOfDarkness, Identity, Story,
client::{ClientNav, Signin},
},
storage::StorageKey,
@ -29,6 +30,7 @@ pub enum ClientEvent2 {
joined: bool,
players: Rc<[PublicIdentity]>,
},
Story(GameStory),
}
#[derive(Default, Clone, PartialEq)]
@ -79,6 +81,11 @@ pub fn Client2(ClientProps { auto_join }: &ClientProps) -> Html {
let connection = use_mut_ref(|| Connection2::new(client_state.setter(), ident.clone(), recv));
let content = match &*client_state {
ClientEvent2::Story(story) => html! {
<div class="post-game">
<Story story={story.clone()} />
</div>
},
ClientEvent2::Sleep => html! {
<CoverOfDarkness />
},

View File

@ -218,6 +218,7 @@ impl Connection2 {
fn message_to_client_state(&self, msg: ServerMessage) -> Option<ClientEvent2> {
log::debug!("received message: {msg:?}");
Some(match msg {
ServerMessage::Story(story) => ClientEvent2::Story(story),
ServerMessage::Sleep => ClientEvent2::Sleep,
ServerMessage::Disconnect => ClientEvent2::Disconnected,
ServerMessage::LobbyInfo {