Skip to content

Commit

Permalink
fix: Flush queued spawns in plugin build
Browse files Browse the repository at this point in the history
  • Loading branch information
Bluefinger committed Dec 15, 2024
1 parent 96432fe commit de63822
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 82 deletions.
3 changes: 3 additions & 0 deletions src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ where
{
fn build(&self, app: &mut App) {
app.register_type::<Entropy<R>>()
.register_type::<RngSeed<R>>()
.register_type::<R::Seed>();

app.world_mut().register_component_hooks::<RngSeed<R>>();
Expand All @@ -81,6 +82,8 @@ where
app.world_mut().spawn((RngSeed::<R>::from_entropy(), Global));
}

app.world_mut().flush();

#[cfg(feature = "experimental")]
app.add_observer(crate::observers::seed_from_global::<R>)
.add_observer(crate::observers::reseed::<R>);
Expand Down
6 changes: 5 additions & 1 deletion tests/integration/determinism.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
use bevy_app::prelude::*;
use bevy_ecs::prelude::*;
use bevy_prng::{ChaCha12Rng, ChaCha8Rng, WyRand};
use bevy_rand::{global::GlobalSeed, prelude::{Entropy, EntropyPlugin, ForkableAsRng, ForkableRng, GlobalEntropy}, traits::SeedSource};
use bevy_rand::{
global::GlobalSeed,
prelude::{Entropy, EntropyPlugin, ForkableAsRng, ForkableRng, GlobalEntropy},
traits::SeedSource,
};
use rand::prelude::Rng;

use rand_core::RngCore;
Expand Down
195 changes: 114 additions & 81 deletions tests/integration/reseeding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ use bevy_app::prelude::*;
use bevy_ecs::prelude::*;
use bevy_prng::{ChaCha8Rng, WyRand};
use bevy_rand::{
global::{Global, GlobalEntropy}, plugin::EntropyPlugin, prelude::Entropy, seed::RngSeed, traits::{ForkableAsSeed, ForkableSeed, SeedSource}
global::{Global, GlobalEntropy},
plugin::EntropyPlugin,
prelude::Entropy,
seed::RngSeed,
traits::{ForkableAsSeed, ForkableSeed, SeedSource},
};
use rand_core::{RngCore, SeedableRng};

Expand All @@ -21,7 +25,10 @@ fn test_global_reseeding() {
app.add_plugins(EntropyPlugin::<ChaCha8Rng>::with_seed(seed));

{
let global_rng = app.world_mut().query_filtered::<&Entropy<ChaCha8Rng>, With<Global>>().single(app.world());
let global_rng = app
.world_mut()
.query_filtered::<&Entropy<ChaCha8Rng>, With<Global>>()
.single(app.world());

// Our RNGs should be the same as each other as they were initialised with the same seed
assert_eq!(global_rng, &rng_eq);
Expand All @@ -30,22 +37,33 @@ fn test_global_reseeding() {
app.update();

{
let global_rng = app.world_mut().query_filtered::<&Entropy<ChaCha8Rng>, With<Global>>().single(app.world());
let global_rng = app
.world_mut()
.query_filtered::<&Entropy<ChaCha8Rng>, With<Global>>()
.single(app.world());

// Our RNGs should remain the same as each other as we have not run the update
assert_eq!(global_rng, &rng_eq);
}

{
let global = app.world_mut().query_filtered::<Entity, With<Global>>().single(app.world());

app.world_mut().entity_mut(global).insert(RngSeed::<ChaCha8Rng>::from_seed([3; 32]));
let global = app
.world_mut()
.query_filtered::<Entity, With<Global>>()
.single(app.world());

app.world_mut()
.entity_mut(global)
.insert(RngSeed::<ChaCha8Rng>::from_seed([3; 32]));
}

app.update();

{
let global_rng = app.world_mut().query_filtered::<&Entropy<ChaCha8Rng>, With<Global>>().single(app.world());
let global_rng = app
.world_mut()
.query_filtered::<&Entropy<ChaCha8Rng>, With<Global>>()
.single(app.world());

// Now our RNG will not be the same, even though we did not use it directly
assert_ne!(global_rng, &rng_eq);
Expand All @@ -68,18 +86,21 @@ fn component_fork_seed() {
}
},
)
.add_systems(Update, |mut q_rng: Query<&mut Entropy<ChaCha8Rng>, Without<Global>>| {
let rngs = q_rng.iter_mut();
.add_systems(
Update,
|mut q_rng: Query<&mut Entropy<ChaCha8Rng>, Without<Global>>| {
let rngs = q_rng.iter_mut();

assert_eq!(rngs.size_hint().0, 5);
assert_eq!(rngs.size_hint().0, 5);

let values: Vec<_> = rngs.map(|mut rng| rng.next_u32()).collect();
let values: Vec<_> = rngs.map(|mut rng| rng.next_u32()).collect();

assert_eq!(
&values,
&[3315785188, 1951699392, 911252207, 791343233, 1599472206]
);
});
assert_eq!(
&values,
&[3315785188, 1951699392, 911252207, 791343233, 1599472206]
);
},
);

app.update();
}
Expand All @@ -100,24 +121,27 @@ fn component_fork_as_seed() {
}
},
)
.add_systems(Update, |mut q_rng: Query<&mut Entropy<WyRand>, Without<Global>>| {
let rngs = q_rng.iter_mut();

assert_eq!(rngs.size_hint().0, 5);

let values: Vec<_> = rngs.map(|mut rng| rng.next_u64()).collect();

assert_eq!(
&values,
&[
10032395693880520184,
15375025802368380325,
10863580644061233257,
7067543572507795213,
7996461288508244033
]
);
});
.add_systems(
Update,
|mut q_rng: Query<&mut Entropy<WyRand>, Without<Global>>| {
let rngs = q_rng.iter_mut();

assert_eq!(rngs.size_hint().0, 5);

let values: Vec<_> = rngs.map(|mut rng| rng.next_u64()).collect();

assert_eq!(
&values,
&[
10032395693880520184,
15375025802368380325,
10863580644061233257,
7067543572507795213,
7996461288508244033
]
);
},
);

app.update();
}
Expand Down Expand Up @@ -147,21 +171,24 @@ fn observer_global_reseeding() {
}
},
)
.add_systems(PreUpdate, |query: Query<&RngSeed<WyRand>, Without<Global>>| {
let expected = [
2484862625678185386u64,
10323237495534242118,
14704548354072994214,
14638519449267265798,
11723565746675474547,
];
let seeds = query.iter().map(RngSeed::<WyRand>::clone_seed);

expected
.into_iter()
.zip(seeds.map(u64::from_ne_bytes))
.for_each(|(expected, actual)| assert_eq!(expected, actual));
})
.add_systems(
PreUpdate,
|query: Query<&RngSeed<WyRand>, Without<Global>>| {
let expected = [
2484862625678185386u64,
10323237495534242118,
14704548354072994214,
14638519449267265798,
11723565746675474547,
];
let seeds = query.iter().map(RngSeed::<WyRand>::clone_seed);

expected
.into_iter()
.zip(seeds.map(u64::from_ne_bytes))
.for_each(|(expected, actual)| assert_eq!(expected, actual));
},
)
.add_systems(
Update,
|mut commands: Commands,
Expand All @@ -172,21 +199,24 @@ fn observer_global_reseeding() {
}
},
)
.add_systems(PostUpdate, |query: Query<&RngSeed<WyRand>, Without<Global>>| {
let prev_expected = [
2484862625678185386u64,
10323237495534242118,
14704548354072994214,
14638519449267265798,
11723565746675474547,
];
let seeds = query.iter().map(RngSeed::<WyRand>::clone_seed);

prev_expected
.into_iter()
.zip(seeds.map(u64::from_ne_bytes))
.for_each(|(expected, actual)| assert_ne!(expected, actual));
});
.add_systems(
PostUpdate,
|query: Query<&RngSeed<WyRand>, Without<Global>>| {
let prev_expected = [
2484862625678185386u64,
10323237495534242118,
14704548354072994214,
14638519449267265798,
11723565746675474547,
];
let seeds = query.iter().map(RngSeed::<WyRand>::clone_seed);

prev_expected
.into_iter()
.zip(seeds.map(u64::from_ne_bytes))
.for_each(|(expected, actual)| assert_ne!(expected, actual));
},
);

app.run();
}
Expand Down Expand Up @@ -290,23 +320,26 @@ fn generic_observer_reseeding_children() {
commands.trigger(LinkRngSourceToTarget::<Source, Target, WyRand>::default());
commands.trigger_targets(SeedFromGlobal::<WyRand>::default(), source);
})
.add_systems(PreUpdate, |query: Query<&RngSeed<WyRand>, (With<Target>, Without<Global>)>| {
let expected = [
6445550333322662121u64,
14968821102299026759,
12617564484450995185,
908888629357954483,
6128439264405451235,
];
let seeds = query.iter().map(RngSeed::<WyRand>::clone_seed);

assert_eq!(seeds.size_hint().0, 5);

expected
.into_iter()
.zip(seeds.map(u64::from_ne_bytes))
.for_each(|(expected, actual)| assert_eq!(expected, actual));
})
.add_systems(
PreUpdate,
|query: Query<&RngSeed<WyRand>, (With<Target>, Without<Global>)>| {
let expected = [
6445550333322662121u64,
14968821102299026759,
12617564484450995185,
908888629357954483,
6128439264405451235,
];
let seeds = query.iter().map(RngSeed::<WyRand>::clone_seed);

assert_eq!(seeds.size_hint().0, 5);

expected
.into_iter()
.zip(seeds.map(u64::from_ne_bytes))
.for_each(|(expected, actual)| assert_eq!(expected, actual));
},
)
.add_systems(PreUpdate, |query: Query<&RngSeed<WyRand>, With<Source>>| {
let expected = 2484862625678185386u64;
let seeds = u64::from_ne_bytes(query.single().clone_seed());
Expand Down

0 comments on commit de63822

Please sign in to comment.