diff --git a/rust/src/replay.rs b/rust/src/replay.rs index 7b00676..ea2536c 100644 --- a/rust/src/replay.rs +++ b/rust/src/replay.rs @@ -5,9 +5,10 @@ use godot::prelude::*; use crate::{ game_manager::{Game, Player}, map::Map, - net::util::NetVector3, + net::{network_manager::BallSync, util::NetVector3}, player::{ - DamageSource, IPlayer, NetTransform, remote_player::RemotePlayer, weapon::WeaponType, + DamageSource, IPlayer, NetTransform, ball::Ball, remote_player::RemotePlayer, + weapon::WeaponType, }, }; @@ -18,6 +19,7 @@ pub struct ReplayPlayback { pub current_map: Option>, current_frame_idx: usize, player_characters: HashMap>, + ball: Option>, pub current_time: f64, @@ -48,6 +50,27 @@ impl INode for ReplayPlayback { while let Some(frame) = self.replay.frames.get(self.current_frame_idx) && frame.time <= self.current_time { + if let ReplayBall::World(ball_state) = &frame.ball_data { + if let Some(ball) = &mut self.ball { + ball.bind_mut().apply_sync(BallSync { + transform: ball_state.transform, + velocity: ball_state.velocity, + }); + } else if let Some(map) = &mut self.current_map { + if let Some(ball) = map.bind_mut().spawn_ball( + ball_state.transform.into(), + ball_state.velocity.into(), + None, + ) { + self.ball = Some(ball); + } + } + } else { + if let Some(mut ball) = self.ball.take() { + ball.queue_free(); + } + } + if !self.fast_forwarding { if let Some(map) = &mut self.current_map { for (id, data) in &frame.player_data { @@ -128,6 +151,9 @@ impl INode for ReplayPlayback { character.queue_free(); } self.player_characters.clear(); + if let Some(mut ball) = self.ball.take() { + ball.queue_free(); + } } } @@ -180,17 +206,28 @@ impl ReplayRecorder { fn record_frame(&mut self) -> ReplayFrame { let mut player_data = HashMap::new(); + let mut ball_data = ReplayBall::Held; + if let Some(game) = Game::singleton() { for player in &game.bind().players { if let Some(state) = player.get_state() { player_data.insert(player.id(), state); } } + ball_data = if let Some(ball) = &game.bind().world_ball { + ReplayBall::World(ReplayBallData { + transform: ball.bind().get_transform(), + velocity: ball.bind().get_velocity(), + }) + } else { + ReplayBall::Held + }; } ReplayFrame { time: self.time_elapsed, player_data, + ball_data, events: Vec::new(), } } @@ -221,6 +258,7 @@ pub struct ReplayPlayer { pub struct ReplayFrame { time: f64, player_data: HashMap, + ball_data: ReplayBall, events: Vec, } @@ -231,9 +269,10 @@ pub enum ReplayEvent { Respawn(u16, ReplayPlayerState), } -#[derive(Debug)] +#[derive(Debug, Clone, Default)] pub enum ReplayBall { World(ReplayBallData), + #[default] Held, } @@ -266,7 +305,7 @@ impl Player { } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ReplayBallData { transform: NetTransform, velocity: NetVector3,