Skip to content

Commit

Permalink
feat: Add set_seed method to GlobalRngSeed
Browse files Browse the repository at this point in the history
  • Loading branch information
Bluefinger committed Jul 5, 2024
1 parent dc8581e commit 2cd07d0
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ authors = ["Gonçalo Rica Pais da Silva <[email protected]>"]
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]
Expand Down
5 changes: 5 additions & 0 deletions src/seed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
67 changes: 65 additions & 2 deletions tests/determinism.rs
Original file line number Diff line number Diff line change
@@ -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")]
Expand Down Expand Up @@ -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<R: SeedableEntropySource>(
seed: Res<GlobalRngSeed<R>>,
mut rng: ResMut<GlobalEntropy<R>>,
) 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::<ChaCha8Rng>::from_seed(seed);

app.add_plugins(EntropyPlugin::<ChaCha8Rng>::with_seed(seed))
.add_systems(PreUpdate, reseed_global_rng::<ChaCha8Rng>);

{
let global_rng = app.world().resource_ref::<GlobalEntropy<ChaCha8Rng>>();
let global_seed = app.world().resource_ref::<GlobalRngSeed<ChaCha8Rng>>();

// 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::<GlobalEntropy<ChaCha8Rng>>();

// 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::<GlobalRngSeed<ChaCha8Rng>>();

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::<GlobalEntropy<ChaCha8Rng>>();

// Now our RNG will not be the same, even though we did not use it directly
assert_ne!(global_rng.as_ref(), &rng_eq);
}
}

0 comments on commit 2cd07d0

Please sign in to comment.