use std::hash::{Hash, Hasher};
use bevy::prelude::*;
use crate::{ChecksumFlag, ChecksumPart, RollbackId, SaveWorld, SaveWorldSystems, checksum_hasher};
pub struct ResourceChecksumPlugin<R: Resource>(pub for<'a> fn(&'a R) -> u64);
fn default_hasher<R: Resource + Hash>(resource: &R) -> u64 {
let mut hasher = checksum_hasher();
resource.hash(&mut hasher);
hasher.finish()
}
impl<R> Default for ResourceChecksumPlugin<R>
where
R: Resource + Hash,
{
fn default() -> Self {
Self(default_hasher::<R>)
}
}
impl<R> Plugin for ResourceChecksumPlugin<R>
where
R: Resource,
{
fn build(&self, app: &mut App) {
let custom_hasher = self.0;
let update = move |mut commands: Commands,
resource: Res<R>,
mut checksum: Query<
&mut ChecksumPart,
(Without<RollbackId>, With<ChecksumFlag<R>>),
>| {
let result = ChecksumPart(custom_hasher(resource.as_ref()) as u128);
trace!(
"Resource {} has checksum {:X}",
disqualified::ShortName::of::<R>(),
result.0
);
if let Ok(mut checksum) = checksum.single_mut() {
*checksum = result;
} else {
commands.spawn((result, ChecksumFlag::<R>::default()));
}
};
app.add_systems(SaveWorld, update.in_set(SaveWorldSystems::Checksum));
}
}