werewolves/werewolves-server/src/runner.rs

97 lines
3.5 KiB
Rust
Raw Normal View History

2025-10-09 22:27:21 +01:00
use core::{num::NonZeroU8, time::Duration};
2025-10-04 09:26:37 +01:00
use std::sync::Arc;
use werewolves_proto::{
message::{ClientMessage, Identification, host::HostMessage},
player::PlayerId,
};
use crate::{
LogError,
communication::lobby::LobbyComms,
connection::JoinedPlayers,
game::{GameEnd, GameRunner},
2025-10-09 22:27:21 +01:00
lobby::{Lobby, LobbyPlayers},
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) {
2025-10-09 22:27:21 +01:00
let mut lobby = Lobby::new(joined_players, comms);
if let Some(dummies) = option_env!("DUMMY_PLAYERS").and_then(|p| p.parse::<NonZeroU8>().ok()) {
log::info!("creating {dummies} dummy players");
lobby.set_players_in_lobby(LobbyPlayers::with_dummies(dummies));
lobby.send_lobby_info_to_host().await.log_debug();
}
let mut state = RunningState::Lobby(lobby);
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),
2025-10-04 09:26:37 +01:00
ConnectedList(Arc<[PlayerId]>),
}
pub enum RunningState {
Lobby(Lobby),
Game(GameRunner),
GameOver(GameEnd),
}