use core::time::Duration; use werewolves_proto::{ message::{ClientMessage, Identification, host::HostMessage}, player::PlayerId, }; use crate::{ LogError, communication::lobby::LobbyComms, connection::JoinedPlayers, game::{GameEnd, GameRunner}, lobby::Lobby, saver::Saver, }; #[derive(Debug, Clone, PartialEq)] pub struct IdentifiedClientMessage { pub identity: Identification, pub message: ClientMessage, } pub async fn run_game(joined_players: JoinedPlayers, comms: LobbyComms, mut saver: impl Saver) { let mut state = RunningState::Lobby(Lobby::new(joined_players, comms)); loop { match &mut state { RunningState::Lobby(lobby) => { if let Some(game) = lobby.next().await { state = RunningState::Game(game) } } RunningState::Game(game) => { if let Some(result) = game.next().await { match saver.save(game.proto_game()) { Ok(path) => { log::info!("saved game to {path}"); } Err(err) => { log::error!("saving game: {err}"); let game_clone = game.proto_game().clone(); let mut saver_clone = saver.clone(); tokio::spawn(async move { let started = chrono::Utc::now(); loop { tokio::time::sleep(Duration::from_secs(30)).await; match saver_clone.save(&game_clone) { Ok(path) => { log::info!("saved game from {started} to {path}"); return; } Err(err) => { log::error!("saving game from {started}: {err}") } } } }); } } state = match state { RunningState::Game(game) => { RunningState::GameOver(GameEnd::new(game, result)) } _ => unsafe { core::hint::unreachable_unchecked() }, }; } } RunningState::GameOver(end) => { if let Some(mut new_lobby) = end.next().await { new_lobby.send_lobby_info_to_clients().await; new_lobby.send_lobby_info_to_host().await.log_debug(); state = RunningState::Lobby(new_lobby) } } } } } #[derive(Debug, Clone, PartialEq)] pub enum Message { Host(HostMessage), Client(IdentifiedClientMessage), Connect(PlayerId), Disconnect(PlayerId), } pub enum RunningState { Lobby(Lobby), Game(GameRunner), GameOver(GameEnd), }