use bevy::{
prelude::*,
reflect::Typed,
};
use crate::prelude::*;
#[derive(Resource, Clone, Debug, Default, Reflect)]
#[reflect(Resource, Clone, Default)]
#[type_path = "bevy_save"]
pub struct Checkpoints {
pub(crate) snapshots: Vec<Snapshot>,
pub(crate) active: Option<usize>,
}
impl Checkpoints {
pub fn is_empty(&self) -> bool {
self.snapshots.is_empty()
}
pub fn checkpoint(&mut self, mut checkpoint: Snapshot) {
let active = self.active.unwrap_or(0);
let id = Self::type_info().type_id();
checkpoint
.resources
.retain(|r| r.get_represented_type_info().map(|i| i.type_id()) != Some(id));
self.snapshots.truncate(active + 1);
self.snapshots.push(checkpoint);
self.active = Some(self.snapshots.len() - 1);
}
pub fn active(&self) -> Option<&Snapshot> {
self.active.and_then(|i| self.snapshots.get(i))
}
#[allow(clippy::cast_possible_wrap)]
#[allow(clippy::cast_sign_loss)]
pub fn rollback(&mut self, checkpoints: isize) -> Option<&Snapshot> {
if let Some(active) = self.active {
let raw = active as isize - checkpoints;
let new = raw.clamp(0, self.snapshots.len() as isize - 1) as usize;
self.active = Some(new);
Some(&self.snapshots[new])
} else {
None
}
}
}