use std::time::Duration;
use bevy::prelude::*;
use crate::{
AdvanceWorld, AdvanceWorldSystems, CloneStrategy, DEFAULT_FPS, ResourceSnapshotPlugin,
RollbackFrameCount,
};
#[derive(Resource, Clone, Copy, Debug, Hash, Deref)]
pub struct RollbackFrameRate(pub usize);
impl Default for RollbackFrameRate {
fn default() -> Self {
Self(DEFAULT_FPS)
}
}
#[derive(Default, Clone, Copy, Debug)]
pub struct GgrsTime;
pub struct GgrsTimePlugin;
impl GgrsTimePlugin {
pub fn update(
mut time: ResMut<Time<GgrsTime>>,
framerate: Res<RollbackFrameRate>,
frame: Res<RollbackFrameCount>,
) {
let this_frame = frame.0 as u64;
let framerate = framerate.0 as u64;
let runtime = Duration::from_nanos(this_frame * 1_000_000_000 / framerate);
let time_moved_backwards = runtime < time.elapsed();
if time_moved_backwards {
*time = Time::new_with(GgrsTime);
time.advance_by(runtime);
} else {
time.advance_to(runtime);
}
}
pub fn replace_default_with_ggrs(
mut default_time: ResMut<Time<()>>,
ggrs_time: Res<Time<GgrsTime>>,
) {
*default_time = ggrs_time.as_generic();
}
pub fn replace_default_with_virtual(
mut default_time: ResMut<Time<()>>,
virtual_time: Res<Time<Virtual>>,
) {
*default_time = virtual_time.as_generic();
}
}
impl Plugin for GgrsTimePlugin {
fn build(&self, app: &mut App) {
app.insert_resource(Time::new_with(GgrsTime))
.add_plugins(ResourceSnapshotPlugin::<CloneStrategy<Time<GgrsTime>>>::default())
.add_systems(
AdvanceWorld,
(Self::update, Self::replace_default_with_ggrs)
.chain()
.in_set(AdvanceWorldSystems::First),
)
.add_systems(
AdvanceWorld,
Self::replace_default_with_virtual.in_set(AdvanceWorldSystems::Last),
);
}
}