From c70143f3270dd385d9e1c55b10476876e5ab2fd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Rica=20Pais=20da=20Silva?= Date: Sat, 14 Dec 2024 11:06:06 +0100 Subject: [PATCH] refactor: Rename components/traits to shorter names (#34) --- Cargo.toml | 8 +-- MIGRATIONS.md | 4 ++ README.md | 14 ++-- bevy_prng/src/chacha.rs | 2 +- bevy_prng/src/lib.rs | 10 +-- bevy_prng/src/newtype.rs | 4 +- bevy_prng/src/pcg.rs | 2 +- bevy_prng/src/wyrand.rs | 2 +- bevy_prng/src/xoshiro.rs | 2 +- examples/turn_based_game.rs | 11 ++- src/component.rs | 115 +++++++++++++++--------------- src/observers.rs | 44 ++++++------ src/plugin.rs | 25 +++---- src/prelude.rs | 2 +- src/resource.rs | 43 ++++++----- src/seed.rs | 17 ++--- src/traits.rs | 40 +++++------ tests/integration/determinism.rs | 14 ++-- tests/integration/reseeding.rs | 27 ++++--- tutorial/03-components-forking.md | 34 ++++----- 20 files changed, 209 insertions(+), 211 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f99b90c..ae63b1d 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.8.1" +version = "0.9.0" rust-version = "1.76.0" [workspace.dependencies] @@ -49,7 +49,7 @@ wyrand = ["bevy_prng/wyrand"] bevy_app.workspace = true bevy_ecs.workspace = true bevy_reflect.workspace = true -bevy_prng = { path = "bevy_prng", version = "0.8" } +bevy_prng = { path = "bevy_prng", version = "0.9" } # others getrandom = "0.2" @@ -63,10 +63,10 @@ serde_derive = { workspace = true, optional = true } # cannot be out of step with bevy_rand due to dependencies on traits # and implementations between the two crates. [target.'cfg(any())'.dependencies] -bevy_prng = { path = "bevy_prng", version = "=0.8" } +bevy_prng = { path = "bevy_prng", version = "=0.9" } [dev-dependencies] -bevy_prng = { path = "bevy_prng", version = "0.8", features = ["rand_chacha", "wyrand"] } +bevy_prng = { path = "bevy_prng", version = "0.9", features = ["rand_chacha", "wyrand"] } rand = "0.8" ron = { version = "0.8.0", features = ["integer128"] } diff --git a/MIGRATIONS.md b/MIGRATIONS.md index 4871293..746fda0 100644 --- a/MIGRATIONS.md +++ b/MIGRATIONS.md @@ -27,3 +27,7 @@ As the `wyrand` dependency has been updated and contains a breaking output chang ## Migrating from v0.7 to v0.8 `GlobalRngSeed` has been removed, instead being rolled into `GlobalEntropy`. This will allow better reflection tracking of the global rng source, and will allow for automatic reseeding without any custom system needing to be provided. Use the `reseed` method to reinstantiate the internal RNG source with the new seed, and `get_seed` to return a reference to the initial starting seed for the source. The serialized format of `GlobalEntropy` has changed and previously serialized instances are no longer compatible. + +## Migrating from v0.8 to v0.9 + +`EntropyComponent` has been renamed to `Entropy`, and the trait `SeedableEntropySource` has been renamed to `EntropySource`. The change to `Entropy` also changes the `TypePath` definition, so this will change the serialised format of the component. diff --git a/README.md b/README.md index 032118d..1981fb2 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ DO **NOT** use `bevy_rand` for actual security purposes, as this requires much m ### Registering a PRNG for use with Bevy Rand -Before a PRNG can be used via `GlobalEntropy` or `EntropyComponent`, it must be registered via the plugin. +Before a PRNG can be used via `GlobalEntropy` or `Entropy`, it must be registered via the plugin. ```rust use bevy_ecs::prelude::*; @@ -69,7 +69,7 @@ fn print_random_value(mut rng: ResMut>) { ### Forking RNGs -For seeding `EntropyComponent`s from a global source, it is best to make use of forking instead of generating the seed value directly. `GlobalEntropy` can only exist as a singular instance, so when forking normally, it will always fork as `EntropyComponent` instances. +For seeding `Entropy`s from a global source, it is best to make use of forking instead of generating the seed value directly. `GlobalEntropy` can only exist as a singular instance, so when forking normally, it will always fork as `Entropy` instances. ```rust use bevy_ecs::prelude::*; @@ -88,12 +88,12 @@ fn setup_source(mut commands: Commands, mut global: ResMut } ``` -`EntropyComponent`s can be seeded/forked from other `EntropyComponent`s as well. +`Entropy`s can be seeded/forked from other `Entropy`s as well. ```rust use bevy_ecs::prelude::*; use bevy_prng::WyRand; -use bevy_rand::prelude::{EntropyComponent, ForkableRng}; +use bevy_rand::prelude::{Entropy, ForkableRng}; #[derive(Component)] struct Npc; @@ -103,7 +103,7 @@ struct Source; fn setup_npc_from_source( mut commands: Commands, - mut q_source: Query<&mut EntropyComponent, (With, Without)>, + mut q_source: Query<&mut Entropy, (With, Without)>, ) { let mut source = q_source.single_mut(); for _ in 0..2 { @@ -132,7 +132,7 @@ fn setup_npc_from_source( | `bevy` | `bevy_rand` | | ------ | ------------ | -| v0.15 | v0.8 | +| v0.15 | v0.8 - v0.9 | | v0.14 | v0.7 | | v0.13 | v0.5 - v0.6 | | v0.12 | v0.4 | @@ -143,7 +143,7 @@ The versions of `rand_core`/`rand` that `bevy_rand` is compatible with is as fol | `bevy_rand` | `rand_core` | `rand` | | ------------ | ----------- | ------ | -| v0.1 -> v0.8 | v0.6 | v0.8 | +| v0.1 -> v0.9 | v0.6 | v0.8 | ## Migrations diff --git a/bevy_prng/src/chacha.rs b/bevy_prng/src/chacha.rs index bc008f1..3e8646c 100644 --- a/bevy_prng/src/chacha.rs +++ b/bevy_prng/src/chacha.rs @@ -1,4 +1,4 @@ -use crate::{newtype::newtype_prng, SeedableEntropySource}; +use crate::{newtype::newtype_prng, EntropySource}; use bevy_reflect::{Reflect, ReflectFromReflect}; use rand_core::{RngCore, SeedableRng}; diff --git a/bevy_prng/src/lib.rs b/bevy_prng/src/lib.rs index f220800..62ba6d1 100644 --- a/bevy_prng/src/lib.rs +++ b/bevy_prng/src/lib.rs @@ -38,7 +38,7 @@ pub use xoshiro::*; /// A marker trait to define the required trait bounds for a seedable PRNG to /// integrate into `EntropyComponent` or `GlobalEntropy`. This is a sealed trait. #[cfg(feature = "serialize")] -pub trait SeedableEntropySource: +pub trait EntropySource: RngCore + SeedableRng + Clone @@ -54,7 +54,7 @@ pub trait SeedableEntropySource: { } -/// Marker trait for a suitable seed for [`SeedableEntropySource`]. This is an auto trait which will +/// Marker trait for a suitable seed for [`EntropySource`]. This is an auto trait which will /// apply to all suitable types that meet the trait criteria. #[cfg(feature = "serialize")] pub trait EntropySeed: @@ -92,7 +92,7 @@ impl< /// A marker trait to define the required trait bounds for a seedable PRNG to /// integrate into `EntropyComponent` or `GlobalEntropy`. This is a sealed trait. #[cfg(not(feature = "serialize"))] -pub trait SeedableEntropySource: +pub trait EntropySource: RngCore + SeedableRng + Clone @@ -108,7 +108,7 @@ pub trait SeedableEntropySource: } #[cfg(not(feature = "serialize"))] -/// Marker trait for a suitable seed for [`SeedableEntropySource`]. This is an auto trait which will +/// Marker trait for a suitable seed for [`EntropySource`]. This is an auto trait which will /// apply to all suitable types that meet the trait criteria. pub trait EntropySeed: Debug @@ -145,5 +145,5 @@ impl< mod private { pub trait SealedSeedable {} - impl SealedSeedable for T {} + impl SealedSeedable for T {} } diff --git a/bevy_prng/src/newtype.rs b/bevy_prng/src/newtype.rs index 9665c1d..7d24959 100644 --- a/bevy_prng/src/newtype.rs +++ b/bevy_prng/src/newtype.rs @@ -72,7 +72,7 @@ macro_rules! newtype_prng { } } - impl SeedableEntropySource for $newtype {} + impl EntropySource for $newtype {} }; } @@ -150,7 +150,7 @@ macro_rules! newtype_prng_remote { } } - impl SeedableEntropySource for $newtype {} + impl EntropySource for $newtype {} }; } diff --git a/bevy_prng/src/pcg.rs b/bevy_prng/src/pcg.rs index 9745c76..54567ed 100644 --- a/bevy_prng/src/pcg.rs +++ b/bevy_prng/src/pcg.rs @@ -1,4 +1,4 @@ -use crate::{newtype::newtype_prng, SeedableEntropySource}; +use crate::{newtype::newtype_prng, EntropySource}; use bevy_reflect::{Reflect, ReflectFromReflect}; use rand_core::{RngCore, SeedableRng}; diff --git a/bevy_prng/src/wyrand.rs b/bevy_prng/src/wyrand.rs index 37dab03..ec663ed 100644 --- a/bevy_prng/src/wyrand.rs +++ b/bevy_prng/src/wyrand.rs @@ -1,4 +1,4 @@ -use crate::{newtype::newtype_prng, SeedableEntropySource}; +use crate::{newtype::newtype_prng, EntropySource}; use bevy_reflect::{Reflect, ReflectFromReflect}; use rand_core::{RngCore, SeedableRng}; diff --git a/bevy_prng/src/xoshiro.rs b/bevy_prng/src/xoshiro.rs index fc591e2..6695a0a 100644 --- a/bevy_prng/src/xoshiro.rs +++ b/bevy_prng/src/xoshiro.rs @@ -1,6 +1,6 @@ use crate::{ newtype::{newtype_prng, newtype_prng_remote}, - SeedableEntropySource, + EntropySource, }; use bevy_reflect::{reflect_remote, std_traits::ReflectDefault, Reflect, ReflectFromReflect}; diff --git a/examples/turn_based_game.rs b/examples/turn_based_game.rs index b632ff3..2cc7826 100644 --- a/examples/turn_based_game.rs +++ b/examples/turn_based_game.rs @@ -3,7 +3,7 @@ use bevy_app::prelude::*; use bevy_ecs::prelude::*; use bevy_prng::ChaCha8Rng; -use bevy_rand::prelude::{EntropyComponent, EntropyPlugin, ForkableRng, GlobalEntropy}; +use bevy_rand::prelude::{Entropy, EntropyPlugin, ForkableRng, GlobalEntropy}; use rand::prelude::{IteratorRandom, Rng}; #[derive(Component, PartialEq, Eq)] @@ -97,7 +97,7 @@ fn setup_enemies(mut commands: Commands, mut rng: ResMut), With>, + mut q_entities: Query<(Entity, &mut Entropy), With>, ) -> Vec { // No matter the order of entities in the query, because they have their own RNG instance, // it will always result in a deterministic output due to being seeded from a single global @@ -121,7 +121,7 @@ fn attack_turn( &Defense, &Name, &mut Health, - &mut EntropyComponent, + &mut Entropy, )>, ) { // Establish list of enemy entities for player to attack @@ -173,10 +173,7 @@ fn attack_turn( } fn buff_entities( - mut q_entities: Query< - (&Name, &Buff, &mut Health, &mut EntropyComponent), - With, - >, + mut q_entities: Query<(&Name, &Buff, &mut Health, &mut Entropy), With>, ) { // Query iteration order is not stable, but entities having their own RNG source side-steps this // completely, so the result is always deterministic. diff --git a/src/component.rs b/src/component.rs index 5a8015d..dc945c6 100644 --- a/src/component.rs +++ b/src/component.rs @@ -3,12 +3,12 @@ use std::fmt::Debug; use crate::{ seed::RngSeed, traits::{ - EcsEntropySource, ForkableAsRng, ForkableAsSeed, ForkableInnerRng, ForkableInnerSeed, + EcsEntropy, ForkableAsRng, ForkableAsSeed, ForkableInnerRng, ForkableInnerSeed, ForkableRng, ForkableSeed, }, }; use bevy_ecs::prelude::{Component, ReflectComponent}; -use bevy_prng::SeedableEntropySource; +use bevy_prng::EntropySource; use bevy_reflect::{Reflect, ReflectFromReflect}; use rand_core::{RngCore, SeedableRng}; @@ -21,12 +21,12 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize}; #[cfg(feature = "serialize")] use serde::Deserialize; -/// An [`EntropyComponent`] that wraps a random number generator that implements +/// An [`Entropy`] that wraps a random number generator that implements /// [`RngCore`] & [`SeedableRng`]. /// -/// ## Creating new [`EntropyComponent`]s. +/// ## Creating new [`Entropy`]s. /// -/// You can creates a new [`EntropyComponent`] directly from anything that implements +/// You can creates a new [`Entropy`] directly from anything that implements /// [`RngCore`] or provides a mut reference to [`RngCore`], such as [`ResMut`] or a /// [`Component`], or from a [`RngCore`] source directly. /// @@ -36,7 +36,7 @@ use serde::Deserialize; /// ``` /// use bevy_ecs::prelude::*; /// use bevy_prng::WyRand; -/// use bevy_rand::prelude::EntropyComponent; +/// use bevy_rand::prelude::Entropy; /// /// #[derive(Component)] /// struct Source; @@ -45,7 +45,7 @@ use serde::Deserialize; /// commands /// .spawn(( /// Source, -/// EntropyComponent::::default(), +/// Entropy::::default(), /// )); /// } /// ``` @@ -72,7 +72,7 @@ use serde::Deserialize; /// ``` /// use bevy_ecs::prelude::*; /// use bevy_prng::WyRand; -/// use bevy_rand::prelude::{EntropyComponent, ForkableRng}; +/// use bevy_rand::prelude::{Entropy, ForkableRng}; /// /// #[derive(Component)] /// struct Npc; @@ -81,7 +81,7 @@ use serde::Deserialize; /// /// fn setup_npc_from_source( /// mut commands: Commands, -/// mut q_source: Query<&mut EntropyComponent, (With, Without)>, +/// mut q_source: Query<&mut Entropy, (With, Without)>, /// ) { /// let mut source = q_source.single_mut(); /// @@ -111,9 +111,9 @@ use serde::Deserialize; all(not(feature = "serialize")), reflect(Debug, PartialEq, Component, FromReflect) )] -pub struct EntropyComponent(R); +pub struct Entropy(R); -impl EntropyComponent { +impl Entropy { /// Create a new component from an `RngCore` instance. #[inline] #[must_use] @@ -128,14 +128,14 @@ impl EntropyComponent { } } -impl Default for EntropyComponent { +impl Default for Entropy { #[inline] fn default() -> Self { Self::from_entropy() } } -impl RngCore for EntropyComponent { +impl RngCore for Entropy { #[inline] fn next_u32(&mut self) -> u32 { self.0.next_u32() @@ -157,7 +157,7 @@ impl RngCore for EntropyComponent { } } -impl SeedableRng for EntropyComponent { +impl SeedableRng for Entropy { type Seed = R::Seed; #[inline] @@ -186,47 +186,54 @@ impl SeedableRng for EntropyComponent { } } -impl EcsEntropySource for EntropyComponent {} +impl EcsEntropy for Entropy {} -impl ForkableRng for EntropyComponent +impl ForkableRng for Entropy where - R: SeedableEntropySource + 'static, + R: EntropySource + 'static, { - type Output = EntropyComponent; + type Output = Entropy; } -impl ForkableAsRng for EntropyComponent +impl ForkableAsRng for Entropy where - R: SeedableEntropySource + 'static, + R: EntropySource + 'static, { - type Output = EntropyComponent where T: SeedableEntropySource; + type Output + = Entropy + where + T: EntropySource; } -impl ForkableInnerRng for EntropyComponent +impl ForkableInnerRng for Entropy where - R: SeedableEntropySource + 'static, + R: EntropySource + 'static, { type Output = R; } -impl ForkableSeed for EntropyComponent +impl ForkableSeed for Entropy where - R: SeedableEntropySource + 'static, + R: EntropySource + 'static, R::Seed: Send + Sync + Clone, { type Output = RngSeed; } -impl ForkableAsSeed for EntropyComponent +impl ForkableAsSeed for Entropy where - R: SeedableEntropySource + 'static, + R: EntropySource + 'static, { - type Output = RngSeed where T: SeedableEntropySource, T::Seed: Send + Sync + Clone; + type Output + = RngSeed + where + T: EntropySource, + T::Seed: Send + Sync + Clone; } -impl ForkableInnerSeed for EntropyComponent +impl ForkableInnerSeed for Entropy where - R: SeedableEntropySource + 'static, + R: EntropySource + 'static, R::Seed: Send + Sync + Clone + AsMut<[u8]> + Default, { type Output = R::Seed; @@ -241,34 +248,28 @@ mod tests { #[test] fn forking() { - let mut rng1 = EntropyComponent::::default(); + let mut rng1 = Entropy::::default(); let rng2 = rng1.fork_rng(); - assert_ne!( - rng1, rng2, - "forked EntropyComponents should not match each other" - ); + assert_ne!(rng1, rng2, "forked Entropys should not match each other"); } #[test] fn forking_as() { - let mut rng1 = EntropyComponent::::default(); + let mut rng1 = Entropy::::default(); let rng2 = rng1.fork_as::(); let rng1 = format!("{:?}", rng1); let rng2 = format!("{:?}", rng2); - assert_ne!( - &rng1, &rng2, - "forked EntropyComponents should not match each other" - ); + assert_ne!(&rng1, &rng2, "forked Entropys should not match each other"); } #[test] fn forking_inner() { - let mut rng1 = EntropyComponent::::default(); + let mut rng1 = Entropy::::default(); let rng2 = rng1.fork_inner(); @@ -281,13 +282,13 @@ mod tests { #[test] fn type_paths() { assert_eq!( - "bevy_rand::component::EntropyComponent", - EntropyComponent::::type_path() + "bevy_rand::component::Entropy", + Entropy::::type_path() ); assert_eq!( - "EntropyComponent", - EntropyComponent::::short_type_path() + "Entropy", + Entropy::::short_type_path() ); } @@ -302,9 +303,9 @@ mod tests { use serde::de::DeserializeSeed; let mut registry = TypeRegistry::default(); - registry.register::>(); + registry.register::>(); - let mut val: EntropyComponent = EntropyComponent::from_seed([7; 32]); + let mut val: Entropy = Entropy::from_seed([7; 32]); // Modify the state of the RNG instance val.next_u32(); @@ -315,7 +316,7 @@ mod tests { assert_eq!( &serialized, - "{\"bevy_rand::component::EntropyComponent\":(((seed:(7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7),stream:0,word_pos:1)))}" + "{\"bevy_rand::component::Entropy\":(((seed:(7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7),stream:0,word_pos:1)))}" ); let mut deserializer = ron::Deserializer::from_str(&serialized).unwrap(); @@ -324,18 +325,18 @@ mod tests { let value = de.deserialize(&mut deserializer).unwrap(); - let mut dynamic = EntropyComponent::::take_from_reflect(value).unwrap(); + let mut dynamic = Entropy::::take_from_reflect(value).unwrap(); // The two instances should be the same assert_eq!( val, dynamic, - "The deserialized EntropyComponent should equal the original" + "The deserialized Entropy should equal the original" ); // They should output the same numbers, as no state is lost between serialization and deserialization. assert_eq!( val.next_u32(), dynamic.next_u32(), - "The deserialized EntropyComponent should have the same output as original" + "The deserialized Entropy should have the same output as original" ); } @@ -350,11 +351,11 @@ mod tests { use serde::de::DeserializeSeed; let mut registry = TypeRegistry::default(); - registry.register::>(); + registry.register::>(); - let registered_type = EntropyComponent::::get_type_registration(); + let registered_type = Entropy::::get_type_registration(); - let mut val = EntropyComponent::::from_seed([7; 32]); + let mut val = Entropy::::from_seed([7; 32]); // Modify the state of the RNG instance val.next_u32(); @@ -374,18 +375,18 @@ mod tests { let value = de.deserialize(&mut deserializer).unwrap(); - let mut dynamic = EntropyComponent::::take_from_reflect(value).unwrap(); + let mut dynamic = Entropy::::take_from_reflect(value).unwrap(); // The two instances should be the same assert_eq!( val, dynamic, - "The deserialized EntropyComponent should equal the original" + "The deserialized Entropy should equal the original" ); // They should output the same numbers, as no state is lost between serialization and deserialization. assert_eq!( val.next_u32(), dynamic.next_u32(), - "The deserialized EntropyComponent should have the same output as original" + "The deserialized Entropy should have the same output as original" ); } } diff --git a/src/observers.rs b/src/observers.rs index 3ddc991..a4eb43f 100644 --- a/src/observers.rs +++ b/src/observers.rs @@ -6,19 +6,19 @@ use bevy_ecs::{ system::{Populated, Single}, }; -use bevy_prng::SeedableEntropySource; +use bevy_prng::EntropySource; use crate::{ - prelude::{EntropyComponent, ForkableSeed, GlobalEntropy}, + prelude::{Entropy, ForkableSeed, GlobalEntropy}, seed::RngSeed, traits::SeedSource, }; /// Component to denote a source has linked children entities #[derive(Debug, Component)] -pub struct RngChildren(PhantomData); +pub struct RngChildren(PhantomData); -impl Default for RngChildren { +impl Default for RngChildren { fn default() -> Self { Self(PhantomData) } @@ -26,9 +26,9 @@ impl Default for RngChildren { /// Component to denote has a relation to a parent Rng source entity. #[derive(Debug, Component)] -pub struct RngParent(Entity, PhantomData); +pub struct RngParent(Entity, PhantomData); -impl RngParent { +impl RngParent { /// Initialises the relation component with the parent entity pub fn new(parent: Entity) -> Self { Self(parent, PhantomData) @@ -43,9 +43,9 @@ impl RngParent { /// Observer event for triggering an entity to pull a new seed value from a /// GlobalEntropy source. #[derive(Debug, Event)] -pub struct SeedFromGlobal(PhantomData); +pub struct SeedFromGlobal(PhantomData); -impl Default for SeedFromGlobal { +impl Default for SeedFromGlobal { fn default() -> Self { Self(PhantomData) } @@ -54,9 +54,9 @@ impl Default for SeedFromGlobal { /// Observer event for triggering an entity to pull a new seed value from a /// linked parent entity. #[derive(Debug, Event)] -pub struct SeedFromParent(PhantomData); +pub struct SeedFromParent(PhantomData); -impl Default for SeedFromParent { +impl Default for SeedFromParent { fn default() -> Self { Self(PhantomData) } @@ -65,9 +65,9 @@ impl Default for SeedFromParent { /// Observer event for triggering an entity to use a new seed value from the /// the event. #[derive(Debug, Event)] -pub struct ReseedRng(Rng::Seed); +pub struct ReseedRng(Rng::Seed); -impl ReseedRng +impl ReseedRng where Rng::Seed: Send + Sync + Clone, { @@ -81,13 +81,13 @@ where /// association needed so that when the source Rng's seed is changed, it propagates new seeds to /// all linked Rngs. #[derive(Debug, Event)] -pub struct LinkRngSourceToTarget { +pub struct LinkRngSourceToTarget { rng: PhantomData, source: PhantomData, target: PhantomData, } -impl Default +impl Default for LinkRngSourceToTarget where Rng::Seed: Sync + Send + Clone, @@ -102,7 +102,7 @@ where } /// Observer system for reseeding a target RNG on an entity with a provided seed value. -pub fn reseed(trigger: Trigger>, mut commands: Commands) +pub fn reseed(trigger: Trigger>, mut commands: Commands) where Rng::Seed: Sync + Send + Clone, { @@ -116,7 +116,7 @@ where } /// Observer System for pulling in a new seed from a GlobalEntropy source -pub fn seed_from_global( +pub fn seed_from_global( trigger: Trigger>, mut source: ResMut>, mut commands: Commands, @@ -130,10 +130,10 @@ pub fn seed_from_global( /// Observer System for pulling in a new seed for the current entity from its parent Rng source. This /// observer system will only run if there are parent entities to have seeds pulled from. -pub fn seed_from_parent( +pub fn seed_from_parent( trigger: Trigger>, q_linked: Populated<&RngParent>, - mut q_parents: Populated<&mut EntropyComponent, With>>, + mut q_parents: Populated<&mut Entropy, With>>, mut commands: Commands, ) where Rng::Seed: Send + Sync + Clone, @@ -150,10 +150,10 @@ pub fn seed_from_parent( /// Observer System for handling seed propagation from source Rng to all child entities. This observer /// will only run if there is a single source entity and also if there are target entities to seed. -pub fn seed_children( - trigger: Trigger>, +pub fn seed_children( + trigger: Trigger>, q_source: Single< - (Entity, &mut EntropyComponent), + (Entity, &mut Entropy), (With, With>, Without), >, q_target: Populated, With>, Without)>, @@ -177,7 +177,7 @@ pub fn seed_children( +pub fn link_targets( _trigger: Trigger>, q_source: Single, Without)>, q_target: Populated, Without)>, diff --git a/src/plugin.rs b/src/plugin.rs index 7953bbf..fef08e5 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -1,11 +1,11 @@ #[cfg(feature = "experimental")] use std::marker::PhantomData; -use crate::{component::EntropyComponent, resource::GlobalEntropy, seed::RngSeed}; +use crate::{component::Entropy, resource::GlobalEntropy, seed::RngSeed}; use bevy_app::{App, Plugin}; #[cfg(feature = "experimental")] use bevy_ecs::prelude::Component; -use bevy_prng::{EntropySeed, SeedableEntropySource}; +use bevy_prng::{EntropySeed, EntropySource}; use rand_core::SeedableRng; /// Plugin for integrating a PRNG that implements `RngCore` into @@ -33,11 +33,11 @@ use rand_core::SeedableRng; /// println!("Random value: {}", rng.next_u32()); /// } /// ``` -pub struct EntropyPlugin { +pub struct EntropyPlugin { seed: Option, } -impl EntropyPlugin +impl EntropyPlugin where R::Seed: Send + Sync + Clone, { @@ -57,7 +57,7 @@ where } } -impl Default for EntropyPlugin +impl Default for EntropyPlugin where R::Seed: Send + Sync + Clone, { @@ -66,13 +66,13 @@ where } } -impl Plugin for EntropyPlugin +impl Plugin for EntropyPlugin where R::Seed: EntropySeed, { fn build(&self, app: &mut App) { app.register_type::>() - .register_type::>() + .register_type::>() .register_type::(); if let Some(seed) = self.seed.as_ref() { @@ -89,18 +89,15 @@ where /// Plugin for setting up linked RNG sources #[cfg(feature = "experimental")] -pub struct LinkedEntropySources< - Source: Component, - Target: Component, - Rng: SeedableEntropySource + 'static, -> { +pub struct LinkedEntropySources +{ rng: PhantomData, source: PhantomData, target: PhantomData, } #[cfg(feature = "experimental")] -impl Default +impl Default for LinkedEntropySources { fn default() -> Self { @@ -113,7 +110,7 @@ impl } #[cfg(feature = "experimental")] -impl Plugin +impl Plugin for LinkedEntropySources where Rng::Seed: Send + Sync + Clone, diff --git a/src/prelude.rs b/src/prelude.rs index ab070fe..c048e6d 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,4 +1,4 @@ -pub use crate::component::EntropyComponent; +pub use crate::component::Entropy; pub use crate::plugin::EntropyPlugin; pub use crate::resource::GlobalEntropy; pub use crate::seed::RngSeed; diff --git a/src/resource.rs b/src/resource.rs index b2fa392..9b875b3 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -1,15 +1,15 @@ use std::fmt::Debug; use crate::{ - component::EntropyComponent, + component::Entropy, seed::RngSeed, traits::{ - EcsEntropySource, ForkableAsRng, ForkableAsSeed, ForkableInnerRng, ForkableInnerSeed, + EcsEntropy, ForkableAsRng, ForkableAsSeed, ForkableInnerRng, ForkableInnerSeed, ForkableRng, ForkableSeed, }, }; use bevy_ecs::prelude::{ReflectFromWorld, ReflectResource, Resource}; -use bevy_prng::SeedableEntropySource; +use bevy_prng::EntropySource; use bevy_reflect::{Reflect, ReflectFromReflect}; use rand_core::{RngCore, SeedableRng}; @@ -65,12 +65,12 @@ use serde::{Deserialize, Serialize}; )] #[cfg_attr(feature = "serialize", reflect(where R::Seed: PartialEq + Debug + Sync + Send + Clone + Serialize + for<'a> Deserialize<'a>))] #[cfg_attr(not(feature = "serialize"), reflect(where R::Seed: PartialEq + Debug + Sync + Send + Clone))] -pub struct GlobalEntropy { +pub struct GlobalEntropy { seed: R::Seed, rng: R, } -impl GlobalEntropy +impl GlobalEntropy where R::Seed: Clone, { @@ -97,7 +97,7 @@ where } } -impl Default for GlobalEntropy +impl Default for GlobalEntropy where R::Seed: Clone, { @@ -107,7 +107,7 @@ where } } -impl RngCore for GlobalEntropy { +impl RngCore for GlobalEntropy { #[inline] fn next_u32(&mut self) -> u32 { self.rng.next_u32() @@ -129,7 +129,7 @@ impl RngCore for GlobalEntropy { } } -impl SeedableRng for GlobalEntropy +impl SeedableRng for GlobalEntropy where R::Seed: Clone, { @@ -159,27 +159,30 @@ where } } -impl EcsEntropySource for GlobalEntropy where R::Seed: Clone {} +impl EcsEntropy for GlobalEntropy where R::Seed: Clone {} impl ForkableRng for GlobalEntropy where - R: SeedableEntropySource + 'static, + R: EntropySource + 'static, R::Seed: Clone, { - type Output = EntropyComponent; + type Output = Entropy; } impl ForkableAsRng for GlobalEntropy where - R: SeedableEntropySource + 'static, + R: EntropySource + 'static, R::Seed: Clone, { - type Output = EntropyComponent where T: SeedableEntropySource; + type Output + = Entropy + where + T: EntropySource; } impl ForkableInnerRng for GlobalEntropy where - R: SeedableEntropySource + 'static, + R: EntropySource + 'static, R::Seed: Clone, { type Output = R; @@ -187,7 +190,7 @@ where impl ForkableSeed for GlobalEntropy where - R: SeedableEntropySource + 'static, + R: EntropySource + 'static, R::Seed: Send + Sync + Clone, { type Output = RngSeed; @@ -195,15 +198,19 @@ where impl ForkableAsSeed for GlobalEntropy where - R: SeedableEntropySource + 'static, + R: EntropySource + 'static, R::Seed: Clone, { - type Output = RngSeed where T: SeedableEntropySource, T::Seed: Send + Sync + Clone; + type Output + = RngSeed + where + T: EntropySource, + T::Seed: Send + Sync + Clone; } impl ForkableInnerSeed for GlobalEntropy where - R: SeedableEntropySource + 'static, + R: EntropySource + 'static, R::Seed: Send + Sync + Clone + AsMut<[u8]> + Default, { type Output = R::Seed; diff --git a/src/seed.rs b/src/seed.rs index 0f6fde8..1f7b87e 100644 --- a/src/seed.rs +++ b/src/seed.rs @@ -1,24 +1,24 @@ use std::marker::PhantomData; use bevy_ecs::{component::StorageType, prelude::Component}; -use bevy_prng::SeedableEntropySource; +use bevy_prng::EntropySource; use bevy_reflect::Reflect; use rand_core::SeedableRng; -use crate::{component::EntropyComponent, traits::SeedSource}; +use crate::{component::Entropy, traits::SeedSource}; /// The initial seed/state for an [`EntropyComponent`]. Adding this component to an `Entity` will cause /// an `EntropyComponent` to be initialised as well. To force a reseed, just insert this component to an /// `Entity` to overwrite the old value, and the `EntropyComponent` will be overwritten with the new seed /// in turn. #[derive(Debug, Reflect)] -pub struct RngSeed { +pub struct RngSeed { seed: R::Seed, #[reflect(ignore)] rng: PhantomData, } -impl SeedSource for RngSeed +impl SeedSource for RngSeed where R::Seed: Sync + Send + Clone, { @@ -43,7 +43,7 @@ where } } -impl Component for RngSeed +impl Component for RngSeed where R::Seed: Sync + Send + Clone, { @@ -59,13 +59,10 @@ where world .commands() .entity(entity) - .insert(EntropyComponent::::from_seed(seed)); + .insert(Entropy::::from_seed(seed)); }) .on_remove(|mut world, entity, _| { - world - .commands() - .entity(entity) - .remove::>(); + world.commands().entity(entity).remove::>(); }); } } diff --git a/src/traits.rs b/src/traits.rs index 0c4b359..68b53ea 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,12 +1,12 @@ -use bevy_prng::SeedableEntropySource; +use bevy_prng::EntropySource; use rand_core::{RngCore, SeedableRng}; /// Trait for implementing Forking behaviour for [`crate::component::EntropyComponent`] and [`crate::resource::GlobalEntropy`]. /// Forking creates a new RNG instance using a generated seed from the original source. If the original is seeded with a known /// seed, this process is deterministic. -pub trait ForkableRng: EcsEntropySource { +pub trait ForkableRng: EcsEntropy { /// The type of instance that is to be forked from the original source. - type Output: EcsEntropySource; + type Output: EcsEntropy; /// Fork the original instance to yield a new instance with a generated seed. /// This method preserves the RNG algorithm between original and forked instances. @@ -34,11 +34,11 @@ pub trait ForkableRng: EcsEntropySource { /// Trait for implementing Forking behaviour for [`crate::component::EntropyComponent`] and [`crate::resource::GlobalEntropy`]. /// Forking creates a new RNG instance using a generated seed from the original source. If the original is seeded with a known /// seed, this process is deterministic. This trait enables forking between different PRNG algorithm types. -pub trait ForkableAsRng: EcsEntropySource { +pub trait ForkableAsRng: EcsEntropy { /// The type of instance that is to be forked from the original source. - type Output: EcsEntropySource + type Output: EcsEntropy where - R: SeedableEntropySource; + R: EntropySource; /// Fork the original instance to yield a new instance with a generated seed. /// This method allows one to specify the RNG algorithm to be used for the forked instance. @@ -58,7 +58,7 @@ pub trait ForkableAsRng: EcsEntropySource { /// )); /// } /// ``` - fn fork_as(&mut self) -> Self::Output { + fn fork_as(&mut self) -> Self::Output { Self::Output::<_>::from_rng(self).unwrap() } } @@ -66,9 +66,9 @@ pub trait ForkableAsRng: EcsEntropySource { /// Trait for implementing Forking behaviour for [`crate::component::EntropyComponent`] and [`crate::resource::GlobalEntropy`]. /// Forking creates a new RNG instance using a generated seed from the original source. If the original is seeded with a known /// seed, this process is deterministic. This trait enables forking the inner PRNG instance of the source component/resource. -pub trait ForkableInnerRng: EcsEntropySource { +pub trait ForkableInnerRng: EcsEntropy { /// The type of instance that is to be forked from the original source. - type Output: SeedableEntropySource; + type Output: EntropySource; /// Fork the original instance to yield a new instance with a generated seed. /// This method yields the inner PRNG instance directly as a forked instance. @@ -99,7 +99,7 @@ pub trait ForkableInnerRng: EcsEntropySource { /// Trait for implementing forking behaviour for [`crate::component::EntropyComponent`] and [`crate::resource::GlobalEntropy`]. /// Forking creates a new RNG instance using a generated seed from the original source. If the original is seeded with a known /// seed, this process is deterministic. This trait enables forking from an entropy source to a seed component. -pub trait ForkableSeed: EcsEntropySource +pub trait ForkableSeed: EcsEntropy where S::Seed: Send + Sync + Clone, { @@ -137,11 +137,11 @@ where /// Forking creates a new RNG instance using a generated seed from the original source. If the original is seeded with a known /// seed, this process is deterministic. This trait enables forking from an entropy source to a seed component of a different /// PRNG algorithm. -pub trait ForkableAsSeed: EcsEntropySource { +pub trait ForkableAsSeed: EcsEntropy { /// The type of seed component that is to be forked from the original source. type Output: SeedSource where - T: SeedableEntropySource, + T: EntropySource, T::Seed: Send + Sync + Clone; /// Fork a new seed from the original entropy source. @@ -162,7 +162,7 @@ pub trait ForkableAsSeed: EcsEntropySource { /// )); /// } /// ``` - fn fork_as_seed(&mut self) -> Self::Output + fn fork_as_seed(&mut self) -> Self::Output where T::Seed: Send + Sync + Clone, { @@ -177,7 +177,7 @@ pub trait ForkableAsSeed: EcsEntropySource { /// Trait for implementing forking behaviour for [`crate::component::EntropyComponent`] and [`crate::resource::GlobalEntropy`]. /// Forking creates a new RNG instance using a generated seed from the original source. If the original is seeded with a known /// seed, this process is deterministic. This trait enables forking from an entropy source to the RNG's seed type. -pub trait ForkableInnerSeed: EcsEntropySource +pub trait ForkableInnerSeed: EcsEntropy where S::Seed: Send + Sync + Clone + AsMut<[u8]> + Default, { @@ -213,7 +213,7 @@ where /// A trait for providing [`crate::seed::RngSeed`] with /// common initialization strategies. This trait is not object safe and is also a sealed trait. -pub trait SeedSource: private::SealedSeed +pub trait SeedSource: private::SealedSeed where R::Seed: Send + Sync + Clone, { @@ -253,23 +253,23 @@ where /// A marker trait for [`crate::component::EntropyComponent`] and [`crate::resource::GlobalEntropy`]. /// This is a sealed trait and cannot be consumed by downstream. -pub trait EcsEntropySource: RngCore + SeedableRng + private::SealedSource {} +pub trait EcsEntropy: RngCore + SeedableRng + private::SealedSource {} mod private { - use super::{EcsEntropySource, SeedSource, SeedableEntropySource}; + use super::{EcsEntropy, EntropySource, SeedSource}; pub trait SealedSource {} pub trait SealedSeed where - R: SeedableEntropySource, + R: EntropySource, { } - impl SealedSource for T where T: EcsEntropySource {} + impl SealedSource for T where T: EcsEntropy {} impl SealedSeed for T where T: SeedSource, - R: SeedableEntropySource, + R: EntropySource, R::Seed: Send + Sync + Clone, { } diff --git a/tests/integration/determinism.rs b/tests/integration/determinism.rs index a939f1c..a946950 100644 --- a/tests/integration/determinism.rs +++ b/tests/integration/determinism.rs @@ -1,9 +1,7 @@ use bevy_app::prelude::*; use bevy_ecs::prelude::*; use bevy_prng::{ChaCha12Rng, ChaCha8Rng, WyRand}; -use bevy_rand::prelude::{ - EntropyComponent, EntropyPlugin, ForkableAsRng, ForkableRng, GlobalEntropy, -}; +use bevy_rand::prelude::{Entropy, EntropyPlugin, ForkableAsRng, ForkableRng, GlobalEntropy}; use rand::prelude::Rng; use rand_core::RngCore; @@ -26,7 +24,7 @@ struct SourceD; #[derive(Component)] struct SourceE; -fn random_output_a(mut q_source: Query<&mut EntropyComponent, With>) { +fn random_output_a(mut q_source: Query<&mut Entropy, With>) { let mut rng = q_source.single_mut(); assert_eq!( @@ -36,13 +34,13 @@ fn random_output_a(mut q_source: Query<&mut EntropyComponent, With, With>) { +fn random_output_b(mut q_source: Query<&mut Entropy, With>) { let mut rng = q_source.single_mut(); assert!(rng.gen_bool(0.5), "SourceB does not match expected output"); } -fn random_output_c(mut q_source: Query<&mut EntropyComponent, With>) { +fn random_output_c(mut q_source: Query<&mut Entropy, With>) { let mut rng = q_source.single_mut(); assert_eq!( @@ -52,7 +50,7 @@ fn random_output_c(mut q_source: Query<&mut EntropyComponent, With, With>) { +fn random_output_d(mut q_source: Query<&mut Entropy, With>) { let mut rng = q_source.single_mut(); assert_eq!( @@ -62,7 +60,7 @@ fn random_output_d(mut q_source: Query<&mut EntropyComponent, With< ); } -fn random_output_e(mut q_source: Query<&mut EntropyComponent, With>) { +fn random_output_e(mut q_source: Query<&mut Entropy, With>) { let mut rng = q_source.single_mut(); let mut bytes = [0u8; 8]; diff --git a/tests/integration/reseeding.rs b/tests/integration/reseeding.rs index 501704b..dd62e8a 100644 --- a/tests/integration/reseeding.rs +++ b/tests/integration/reseeding.rs @@ -3,7 +3,7 @@ use bevy_ecs::prelude::*; use bevy_prng::{ChaCha8Rng, WyRand}; use bevy_rand::{ plugin::EntropyPlugin, - prelude::EntropyComponent, + prelude::Entropy, resource::GlobalEntropy, traits::{ForkableAsSeed, ForkableSeed}, }; @@ -71,21 +71,18 @@ fn component_fork_seed() { } }, ) - .add_systems( - Update, - |mut q_rng: Query<&mut EntropyComponent>| { - let rngs = q_rng.iter_mut(); + .add_systems(Update, |mut q_rng: Query<&mut Entropy>| { + 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(); } @@ -106,7 +103,7 @@ fn component_fork_as_seed() { } }, ) - .add_systems(Update, |mut q_rng: Query<&mut EntropyComponent>| { + .add_systems(Update, |mut q_rng: Query<&mut Entropy>| { let rngs = q_rng.iter_mut(); assert_eq!(rngs.size_hint().0, 5); @@ -171,7 +168,7 @@ fn observer_global_reseeding() { .add_systems( Update, |mut commands: Commands, - query: Query>>, + query: Query>>, mut source: ResMut>| { for e in &query { commands.trigger_targets(ReseedRng::::new(source.fork_inner_seed()), e); diff --git a/tutorial/03-components-forking.md b/tutorial/03-components-forking.md index 006499b..9089599 100644 --- a/tutorial/03-components-forking.md +++ b/tutorial/03-components-forking.md @@ -1,11 +1,11 @@ -# Entities as RNG sources with `EntropyComponent` +# Entities as RNG sources with `Entropy` -In order to move beyond the restrictions placed by `GlobalEntropy` and achieve determinism *with parallelism*, where the RNG source lives has to go from a global source to one owned by the entities themselves. `EntropyComponent` enables us to attach a PRNG to any given entity, and thus sidesteps not only forcing systems to run serially to each other, but also avoids the problem of queries not being stable in ordering. In fact, as ordering is no longer an issue, parallel iteration of queries is made possible as we avoid borrowing issues if each entity we queried owns its own RNG source. +In order to move beyond the restrictions placed by `GlobalEntropy` and achieve determinism *with parallelism*, where the RNG source lives has to go from a global source to one owned by the entities themselves. `Entropy` enables us to attach a PRNG to any given entity, and thus sidesteps not only forcing systems to run serially to each other, but also avoids the problem of queries not being stable in ordering. In fact, as ordering is no longer an issue, parallel iteration of queries is made possible as we avoid borrowing issues if each entity we queried owns its own RNG source. ```rust use bevy_ecs::prelude::*; use bevy_prng::WyRand; -use bevy_rand::prelude::EntropyComponent; +use bevy_rand::prelude::Entropy; #[derive(Component)] struct Source; @@ -14,17 +14,17 @@ fn setup_source(mut commands: Commands) { commands .spawn(( Source, - EntropyComponent::::default(), + Entropy::::default(), )); } ``` -In the above example, we are creating an entity with a `Source` marker component and attaching an `EntropyComponent` to it with the `WyRand` algorithm and a randomised seed. To then access this source, we simply query `Query<&mut EntropyComponent, With>`. In this case, we are creating a single entity with an RNG source, but there's no reason why many more can't have an RNG source attached to them. +In the above example, we are creating an entity with a `Source` marker component and attaching an `Entropy` to it with the `WyRand` algorithm and a randomised seed. To then access this source, we simply query `Query<&mut Entropy, With>`. In this case, we are creating a single entity with an RNG source, but there's no reason why many more can't have an RNG source attached to them. ```rust use bevy_ecs::prelude::*; use bevy_prng::WyRand; -use bevy_rand::prelude::EntropyComponent; +use bevy_rand::prelude::Entropy; #[derive(Component)] struct Npc; @@ -34,7 +34,7 @@ fn setup_source(mut commands: Commands) { commands .spawn(( Npc, - EntropyComponent::::default(), + Entropy::::default(), )); } } @@ -46,12 +46,12 @@ We can also instantiate these components with set seeds, but there's then the da Forking is the process of generating a new seed from an RNG source and creating a new RNG instance with it. If cloning creates a new instance with the same state from the old, forking creates a new instance with a new state, advancing the old instance's state in the process (as we used it to generate a new seed). -Because PRNG algorithms are deterministic, forking is a deterministic process, and it allows us to have one seed state create many "random" states while being hard to predict. `bevy_rand` makes it super easy to fork new `EntropyComponent`s, allowing you to source new RNGs from `GlobalEntropy` or even other `EntropyComponent`s! +Because PRNG algorithms are deterministic, forking is a deterministic process, and it allows us to have one seed state create many "random" states while being hard to predict. `bevy_rand` makes it super easy to fork new `Entropy`s, allowing you to source new RNGs from `GlobalEntropy` or even other `Entropy`s! ```rust use bevy_ecs::prelude::*; use bevy_prng::ChaCha8Rng; -use bevy_rand::prelude::{EntropyComponent, GlobalEntropy, ForkableRng}; +use bevy_rand::prelude::{Entropy, GlobalEntropy, ForkableRng}; #[derive(Component)] struct Source; @@ -60,7 +60,7 @@ fn setup_source(mut commands: Commands, mut global: ResMut` + global.fork_rng(), // This will yield an `Entropy` )); } ``` @@ -70,7 +70,7 @@ We can even fork to different PRNG algorithms. ```rust use bevy_ecs::prelude::*; use bevy_prng::{ChaCha8Rng, WyRand}; -use bevy_rand::prelude::{EntropyComponent, GlobalEntropy, ForkableAsRng}; +use bevy_rand::prelude::{Entropy, GlobalEntropy, ForkableAsRng}; #[derive(Component)] struct Source; @@ -79,7 +79,7 @@ fn setup_source(mut commands: Commands, mut global: ResMut(), // This will yield an `EntropyComponent` + global.fork_as::(), // This will yield an `Entropy` )); } ``` @@ -89,7 +89,7 @@ So we created a `Source` entity with an RNG source, let's use it to spawn more e ```rust use bevy_ecs::prelude::*; use bevy_prng::WyRand; -use bevy_rand::prelude::{EntropyComponent, ForkableRng}; +use bevy_rand::prelude::{Entropy, ForkableRng}; #[derive(Component)] struct Npc; @@ -99,14 +99,14 @@ struct Source; fn setup_npc_from_source( mut commands: Commands, - mut q_source: Query<&mut EntropyComponent, (With, Without)>, + mut q_source: Query<&mut Entropy, (With, Without)>, ) { let mut source = q_source.single_mut(); for _ in 0..10 { commands .spawn(( Npc, - source.fork_rng() // This will yield a new `EntropyComponent` + source.fork_rng() // This will yield a new `Entropy` )); } } @@ -115,7 +115,7 @@ fn setup_npc_from_source( Now that we have our `Npc` entities attached with RNG sources, when we query them, we can make use of their own sources when generating new random numbers from them. ```rust ignore -fn randomise_npc_stat(mut q_npc: Query<(&mut Stat, &mut EntropyComponent), With>) { +fn randomise_npc_stat(mut q_npc: Query<(&mut Stat, &mut Entropy), With>) { for (mut stat, mut rng) in q_npc.iter_mut() { stat.0 = rng.next_u32(); } @@ -124,4 +124,4 @@ fn randomise_npc_stat(mut q_npc: Query<(&mut Stat, &mut EntropyComponent This way, no matter what order the query iterates, we can be assured that the resulting output is always deterministic. Other systems that access different entities with RNG sources that don't overlap with `Npc` entity systems will be able to run in parallel, and iterating the queries themselves can also be done in parallel with `.par_iter()`. We've ensured that each *access* is deterministic and owned to the entity itself. -As a final note: for both `GlobalEntropy` and `EntropyComponent`s, one can fork the inner PRNG instance to use directly or pass into methods via `fork_inner()`. +As a final note: for both `GlobalEntropy` and `Entropy`s, one can fork the inner PRNG instance to use directly or pass into methods via `fork_inner()`.