feat(web client): take & replay game snapshot
This commit is contained in:
parent
a82169fbe5
commit
fbc6a3c432
5 changed files with 239 additions and 3 deletions
|
|
@ -50,6 +50,44 @@ pub async fn run_local_bot_game(
|
|||
suppress_dice_anim: false,
|
||||
}));
|
||||
|
||||
run_local_bot_game_loop(screen, cmd_rx, pending, player_name, backend, vs).await
|
||||
}
|
||||
|
||||
/// Runs a bot game from a pre-built backend and initial ViewState (used for snapshot replay).
|
||||
/// Returns `true` if the player wants to play again.
|
||||
pub async fn run_local_bot_game_with_backend(
|
||||
screen: RwSignal<Screen>,
|
||||
cmd_rx: &mut mpsc::UnboundedReceiver<NetCommand>,
|
||||
pending: RwSignal<VecDeque<GameUiState>>,
|
||||
player_name: String,
|
||||
backend: TrictracBackend,
|
||||
) -> bool {
|
||||
let mut vs = backend.get_view_state().clone();
|
||||
patch_bot_names(&mut vs, &player_name);
|
||||
screen.set(Screen::Playing(GameUiState {
|
||||
view_state: vs.clone(),
|
||||
player_id: 0,
|
||||
room_id: String::new(),
|
||||
is_bot_game: true,
|
||||
waiting_for_confirm: false,
|
||||
pause_reason: None,
|
||||
my_scored_event: None,
|
||||
opp_scored_event: None,
|
||||
last_moves: None,
|
||||
suppress_dice_anim: false,
|
||||
}));
|
||||
|
||||
run_local_bot_game_loop(screen, cmd_rx, pending, player_name, backend, vs).await
|
||||
}
|
||||
|
||||
async fn run_local_bot_game_loop(
|
||||
screen: RwSignal<Screen>,
|
||||
cmd_rx: &mut mpsc::UnboundedReceiver<NetCommand>,
|
||||
pending: RwSignal<VecDeque<GameUiState>>,
|
||||
player_name: String,
|
||||
mut backend: TrictracBackend,
|
||||
mut vs: ViewState,
|
||||
) -> bool {
|
||||
use futures::StreamExt;
|
||||
loop {
|
||||
match cmd_rx.next().await {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use backbone_lib::traits::{BackEndArchitecture, BackendCommand};
|
||||
use trictrac_store::{Dice, DiceRoller, GameEvent, GameState, TurnStage};
|
||||
use trictrac_store::{Color, Dice, DiceRoller, GameEvent, GameState, Player, Stage, TurnStage};
|
||||
|
||||
use super::types::{GameDelta, PlayerAction, PreGameRollState, SerStage, SerTurnStage, ViewState};
|
||||
|
||||
|
|
@ -130,6 +130,65 @@ impl TrictracBackend {
|
|||
pub fn get_game(&self) -> &GameState {
|
||||
&self.game
|
||||
}
|
||||
|
||||
/// Build a backend pre-loaded with the given `ViewState` snapshot so a bot
|
||||
/// game can resume from an arbitrary position (debug feature).
|
||||
pub fn from_view_state(vs: ViewState, player_name: &str) -> Self {
|
||||
let mut game = GameState::new(false);
|
||||
|
||||
game.board.set_positions(&Color::White, vs.board);
|
||||
|
||||
game.stage = match vs.stage {
|
||||
SerStage::InGame => Stage::InGame,
|
||||
SerStage::Ended => Stage::Ended,
|
||||
_ => Stage::InGame,
|
||||
};
|
||||
|
||||
game.turn_stage = match vs.turn_stage {
|
||||
SerTurnStage::RollDice => TurnStage::RollDice,
|
||||
SerTurnStage::RollWaiting => TurnStage::RollWaiting,
|
||||
SerTurnStage::MarkPoints => TurnStage::MarkPoints,
|
||||
SerTurnStage::HoldOrGoChoice => TurnStage::HoldOrGoChoice,
|
||||
SerTurnStage::Move => TurnStage::Move,
|
||||
SerTurnStage::MarkAdvPoints => TurnStage::MarkAdvPoints,
|
||||
};
|
||||
|
||||
game.dice = Dice { values: vs.dice };
|
||||
|
||||
game.active_player_id = match vs.active_mp_player {
|
||||
Some(0) => HOST_PLAYER_ID,
|
||||
Some(1) => GUEST_PLAYER_ID,
|
||||
_ => HOST_PLAYER_ID,
|
||||
};
|
||||
|
||||
let build_player = |score: &crate::game::trictrac::types::PlayerScore,
|
||||
color: Color|
|
||||
-> Player {
|
||||
let mut p = Player::new(score.name.clone(), color);
|
||||
p.points = score.points;
|
||||
p.holes = score.holes;
|
||||
p.can_bredouille = score.can_bredouille;
|
||||
p
|
||||
};
|
||||
|
||||
game.players.insert(HOST_PLAYER_ID, build_player(&vs.scores[0], Color::White));
|
||||
game.players.insert(GUEST_PLAYER_ID, build_player(&vs.scores[1], Color::Black));
|
||||
|
||||
let mut view_state = ViewState::from_game_state(&game, HOST_PLAYER_ID, GUEST_PLAYER_ID);
|
||||
view_state.scores[0].name = player_name.to_string();
|
||||
view_state.scores[1].name = "Bot".to_string();
|
||||
|
||||
TrictracBackend {
|
||||
game,
|
||||
dice_roller: DiceRoller::default(),
|
||||
commands: Vec::new(),
|
||||
view_state,
|
||||
arrived: [true, true],
|
||||
pre_game_dice: [None; 2],
|
||||
tie_count: 0,
|
||||
ceremony_started: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BackEndArchitecture<PlayerAction, GameDelta, ViewState> for TrictracBackend {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue