From 2cd07d0e8977e4a1d41877af5c60f85f5f11f9e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Rica=20Pais=20da=20Silva?= Date: Fri, 5 Jul 2024 15:39:24 +0200 Subject: [PATCH] feat: Add set_seed method to GlobalRngSeed --- Cargo.toml | 2 +- src/seed.rs | 5 ++++ tests/determinism.rs | 67 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 78b3bc1..fa69698 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ authors = ["Gonçalo Rica Pais da Silva "] edition = "2021" repository = "https://github.com/Bluefinger/bevy_rand" license = "MIT OR Apache-2.0" -version = "0.7.0" +version = "0.7.1" rust-version = "1.76.0" [workspace.dependencies] diff --git a/src/seed.rs b/src/seed.rs index aa5131a..f04b1a2 100644 --- a/src/seed.rs +++ b/src/seed.rs @@ -61,6 +61,11 @@ where self.seed.clone() } + /// Set the global seed to a new value + pub fn set_seed(&mut self, seed: R::Seed) { + self.seed = seed; + } + /// Initializes an instance of [`GlobalRngSeed`] with a randomised seed /// value, drawn from thread-local or OS sources. #[inline] diff --git a/tests/determinism.rs b/tests/determinism.rs index cb4584a..9742ab2 100644 --- a/tests/determinism.rs +++ b/tests/determinism.rs @@ -1,11 +1,11 @@ #![allow(clippy::type_complexity)] use bevy::prelude::*; -use bevy_prng::{ChaCha12Rng, ChaCha8Rng, WyRand}; +use bevy_prng::{ChaCha12Rng, ChaCha8Rng, SeedableEntropySource, WyRand}; use bevy_rand::prelude::{ EntropyComponent, EntropyPlugin, ForkableAsRng, ForkableRng, GlobalEntropy, GlobalRngSeed, }; -use rand::prelude::Rng; +use rand::prelude::{Rng, SeedableRng}; use rand_core::RngCore; #[cfg(target_arch = "wasm32")] @@ -132,3 +132,66 @@ fn test_parallel_determinism() { ) .run(); } + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn test_global_reseeding() { + /// Basic Reseeding mechanism by change detection against GlobalRngSeed + fn reseed_global_rng( + seed: Res>, + mut rng: ResMut>, + ) where + R::Seed: Sync + Send + Clone, + { + if seed.is_changed() && !seed.is_added() { + rng.reseed(seed.get_seed()); + } + } + + let mut app = App::new(); + + let seed = [2; 32]; + + let rng_eq = GlobalEntropy::::from_seed(seed); + + app.add_plugins(EntropyPlugin::::with_seed(seed)) + .add_systems(PreUpdate, reseed_global_rng::); + + { + let global_rng = app.world().resource_ref::>(); + let global_seed = app.world().resource_ref::>(); + + // Our RNGs should be the same as each other as they were initialised with the same seed + assert_eq!(global_rng.as_ref(), &rng_eq); + + // The condition here should mean our reseeding system will NOT run + assert!(global_seed.is_changed() && global_seed.is_added()); + } + + app.update(); + + { + let global_rng = app.world().resource_ref::>(); + + // Our RNGs should remain the same as each other as we have not run the update + assert_eq!(global_rng.as_ref(), &rng_eq); + } + + { + let mut global_seed = app.world_mut().resource_mut::>(); + + global_seed.set_seed([3; 32]); + + // The condition here should mean our reseeding system WILL run + assert!(global_seed.is_changed() && !global_seed.is_added()); + } + + app.update(); + + { + let global_rng = app.world().resource_ref::>(); + + // Now our RNG will not be the same, even though we did not use it directly + assert_ne!(global_rng.as_ref(), &rng_eq); + } +}