Add replay ball

This commit is contained in:
Sofia 2026-07-26 20:34:40 +03:00
parent 6badb845b5
commit 8552aeb55d

View File

@ -5,9 +5,10 @@ use godot::prelude::*;
use crate::{ use crate::{
game_manager::{Game, Player}, game_manager::{Game, Player},
map::Map, map::Map,
net::util::NetVector3, net::{network_manager::BallSync, util::NetVector3},
player::{ 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<Gd<Map>>, pub current_map: Option<Gd<Map>>,
current_frame_idx: usize, current_frame_idx: usize,
player_characters: HashMap<u16, Gd<RemotePlayer>>, player_characters: HashMap<u16, Gd<RemotePlayer>>,
ball: Option<Gd<Ball>>,
pub current_time: f64, pub current_time: f64,
@ -48,6 +50,27 @@ impl INode for ReplayPlayback {
while let Some(frame) = self.replay.frames.get(self.current_frame_idx) while let Some(frame) = self.replay.frames.get(self.current_frame_idx)
&& frame.time <= self.current_time && 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 !self.fast_forwarding {
if let Some(map) = &mut self.current_map { if let Some(map) = &mut self.current_map {
for (id, data) in &frame.player_data { for (id, data) in &frame.player_data {
@ -128,6 +151,9 @@ impl INode for ReplayPlayback {
character.queue_free(); character.queue_free();
} }
self.player_characters.clear(); 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 { fn record_frame(&mut self) -> ReplayFrame {
let mut player_data = HashMap::new(); let mut player_data = HashMap::new();
let mut ball_data = ReplayBall::Held;
if let Some(game) = Game::singleton() { if let Some(game) = Game::singleton() {
for player in &game.bind().players { for player in &game.bind().players {
if let Some(state) = player.get_state() { if let Some(state) = player.get_state() {
player_data.insert(player.id(), 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 { ReplayFrame {
time: self.time_elapsed, time: self.time_elapsed,
player_data, player_data,
ball_data,
events: Vec::new(), events: Vec::new(),
} }
} }
@ -221,6 +258,7 @@ pub struct ReplayPlayer {
pub struct ReplayFrame { pub struct ReplayFrame {
time: f64, time: f64,
player_data: HashMap<u16, ReplayPlayerState>, player_data: HashMap<u16, ReplayPlayerState>,
ball_data: ReplayBall,
events: Vec<ReplayEvent>, events: Vec<ReplayEvent>,
} }
@ -231,9 +269,10 @@ pub enum ReplayEvent {
Respawn(u16, ReplayPlayerState), Respawn(u16, ReplayPlayerState),
} }
#[derive(Debug)] #[derive(Debug, Clone, Default)]
pub enum ReplayBall { pub enum ReplayBall {
World(ReplayBallData), World(ReplayBallData),
#[default]
Held, Held,
} }
@ -266,7 +305,7 @@ impl Player {
} }
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct ReplayBallData { pub struct ReplayBallData {
transform: NetTransform, transform: NetTransform,
velocity: NetVector3, velocity: NetVector3,