From 91f76b3836f74f1de67fb5c69e08de50de0975e8 Mon Sep 17 00:00:00 2001 From: Sofia Date: Sun, 26 Jul 2026 20:10:41 +0300 Subject: [PATCH] Implement concept of fast forwarding --- rust/src/game_manager.rs | 21 +++++++++++++-- rust/src/replay.rs | 55 +++++++++++++++++++++++++++------------- 2 files changed, 57 insertions(+), 19 deletions(-) diff --git a/rust/src/game_manager.rs b/rust/src/game_manager.rs index d26ff0d..519b192 100644 --- a/rust/src/game_manager.rs +++ b/rust/src/game_manager.rs @@ -352,6 +352,7 @@ impl Game { playback.bind_mut().replay = recorder.bind().replay.clone(); playback.bind_mut().current_map = self.current_map.clone(); playback.bind_mut().current_time = recorder.bind().time_elapsed + time_delta; + playback.bind_mut().fast_forwarding = true; self.current_replay_playback = Some(playback.clone()); self.base_mut().add_child(&playback); } @@ -789,11 +790,19 @@ impl Game { self.stop_playback(); } - if let Some(player) = self.find_player_mut(id) - && let Some(character) = &mut player.character + if let Some(player) = self.find_player(id) + && let Some(mut character) = player.character.clone() { // This is a respawn, remove old character character.queue_free(); + + if let Some(mut recorder) = self.replay_recorder.clone() + && let Some(state) = player.get_state() + { + recorder + .bind_mut() + .record_event(ReplayEvent::Respawn(id, state)); + } } if let Some(mut map) = self.current_map.clone() { @@ -867,6 +876,14 @@ impl Game { if let Some(character) = &mut player.character { // This is a respawn, delete old character character.queue_free(); + + if let Some(mut recorder) = self.replay_recorder.clone() + && let Some(state) = player.get_state() + { + recorder + .bind_mut() + .record_event(ReplayEvent::Respawn(id, state)); + } } let mut character = map.bind_mut().spawn_player( diff --git a/rust/src/replay.rs b/rust/src/replay.rs index 09c14c0..c88e17f 100644 --- a/rust/src/replay.rs +++ b/rust/src/replay.rs @@ -23,6 +23,8 @@ pub struct ReplayPlayback { pub spectated_player_id: u16, + pub fast_forwarding: bool, + base: Base, } @@ -46,27 +48,43 @@ impl INode for ReplayPlayback { while let Some(frame) = self.replay.frames.get(self.current_frame_idx) && frame.time <= self.current_time { - if let Some(map) = &mut self.current_map { - for (id, data) in &frame.player_data { - if !self.player_characters.contains_key(id) { - if let Some(player) = map.bind_mut().spawn_replay_player(*id, data.clone()) - { - self.player_characters.insert(*id, player); + if !self.fast_forwarding { + if let Some(map) = &mut self.current_map { + for (id, data) in &frame.player_data { + if !self.player_characters.contains_key(id) { + if let Some(player) = + map.bind_mut().spawn_replay_player(*id, data.clone()) + { + self.player_characters.insert(*id, player); + } } } } - } - for event in &frame.events { - match event { - ReplayEvent::Death(damage_source, player_id) => { - if let Some(character) = self.player_characters.get_mut(player_id) { - character.bind_mut().kill(*damage_source); + for event in &frame.events { + match event { + ReplayEvent::Death(damage_source, player_id) => { + if let Some(character) = self.player_characters.get_mut(player_id) { + character.bind_mut().kill(*damage_source); + } } - } - ReplayEvent::Shoot(player_id, to) => { - if let Some(character) = self.player_characters.get_mut(player_id) { - character.bind_mut().try_shoot(*to, false); + ReplayEvent::Shoot(player_id, to) => { + if let Some(character) = self.player_characters.get_mut(player_id) { + character.bind_mut().try_shoot(*to, false); + } + } + ReplayEvent::Respawn(player_id, data) => { + if let Some(mut character) = self.player_characters.remove(player_id) { + character.queue_free(); + } + + if let Some(map) = &mut self.current_map { + if let Some(player) = + map.bind_mut().spawn_replay_player(*player_id, data.clone()) + { + self.player_characters.insert(*player_id, player); + } + } } } } @@ -90,6 +108,8 @@ impl INode for ReplayPlayback { self.current_frame_idx += 1; } + self.fast_forwarding = false; + if self.current_frame_idx >= self.replay.frames.len() { for (id, mut character) in self.player_characters.clone() { character.queue_free(); @@ -203,6 +223,7 @@ pub struct ReplayFrame { pub enum ReplayEvent { Death(DamageSource, u16), Shoot(u16, Vector3), + Respawn(u16, ReplayPlayerState), } #[derive(Debug)] @@ -220,7 +241,7 @@ pub struct ReplayPlayerState { } impl Player { - fn get_state(&self) -> Option { + pub fn get_state(&self) -> Option { if let Some(character) = &self.character { Some(ReplayPlayerState { transform: character.dyn_bind().get_transform(),