diff --git a/Cargo.toml b/Cargo.toml index 29cbad6..132748f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ keywords = ["game", "bevy", "rand", "rng"] categories = ["game-engines", "algorithms"] exclude = ["/.*"] resolver = "2" -rust-version = "1.67.0" +rust-version = "1.70.0" [features] default = ["serialize", "thread_local_entropy"] @@ -19,7 +19,7 @@ serialize = ["dep:serde", "rand_core/serde1", "rand_chacha?/serde1"] [dependencies] # bevy -bevy = { version = "0.10", default-features = false } +bevy = { version = "0.11.1", default-features = false } # others serde = { version = "1.0", features = ["derive"], optional = true } diff --git a/README.md b/README.md index c525f8f..f840a1d 100644 --- a/README.md +++ b/README.md @@ -174,13 +174,20 @@ All recommended crates implement the necessary traits to be compatible with `bev - **`thread_local_entropy`** - Enables `ThreadLocalEntropy`, overriding `SeedableRng::from_entropy` implementations to make use of thread local entropy sources for faster PRNG initialisation. Enabled by default. - **`serialize`** - Enables [`Serialize`] and [`Deserialize`] derives. Enabled by default. +## Note about Reflection & `TypePath` stability. + +All `rand` PRNGs do not implement `TypePath` in any form, even as an optional feature, due to lack of native support for reflection in Rust. As such, while the components/resource in this library are *stable* and implement a stable `TypePath` for themselves, PRNGs rely on `std::any::type_name` for returning the type's name/path, which is NOT guaranteed to be stable for all versions of the compiler. As such, there may be instabilities/compatibilities with different compiler versions and compilations, as this instability infects the overall `TypePath` via the generic portion of the type path. + +If there arises problems with regards to stability for reflection purposes, please make an issue with regards to that in this repository, so I can track such occurrences. Tests are included in the crate anyway to hopefully detect such cases in the future. + ## Supported Versions & MSRV `bevy_rand` uses the same MSRV as `bevy`. -| `bevy_rand` | `bevy` | -| ----------- | ------ | -| v0.1 | v0.10 | +| `bevy_rand` | `bevy` | +| ----------- | ------- | +| v0.2 | v0.11.1 | +| v0.1 | v0.10 | ## License diff --git a/examples/turn_based_game.rs b/examples/turn_based_game.rs index 31ecd22..333975b 100644 --- a/examples/turn_based_game.rs +++ b/examples/turn_based_game.rs @@ -45,9 +45,12 @@ struct Health { fn main() { App::new() - .add_plugin(EntropyPlugin::::with_seed([1; 32])) - .add_startup_systems((setup_player, setup_enemies).chain()) - .add_systems((determine_attack_order.pipe(attack_turn), buff_entities).chain()) + .add_plugins(EntropyPlugin::::with_seed([1; 32])) + .add_systems(Startup, (setup_player, setup_enemies).chain()) + .add_systems( + Update, + (determine_attack_order.pipe(attack_turn), buff_entities).chain(), + ) .run(); } diff --git a/src/component.rs b/src/component.rs index 8e27b24..3c7dbd8 100644 --- a/src/component.rs +++ b/src/component.rs @@ -2,8 +2,8 @@ use std::fmt::Debug; use crate::{resource::GlobalEntropy, traits::SeedableEntropySource}; use bevy::{ - prelude::{Component, FromReflect, Mut, Reflect, ReflectComponent, ResMut}, - reflect::ReflectFromReflect, + prelude::{Component, Mut, Reflect, ReflectComponent, ReflectFromReflect, ResMut}, + reflect::{utility::GenericTypePathCell, TypePath}, }; use rand_core::{RngCore, SeedableRng}; @@ -89,7 +89,8 @@ use serde::{Deserialize, Serialize}; /// } /// } /// ``` -#[derive(Debug, Clone, PartialEq, Eq, Component, Reflect, FromReflect)] +#[derive(Debug, Clone, PartialEq, Eq, Component, Reflect)] +#[reflect_value(type_path = false)] #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serialize", @@ -122,6 +123,35 @@ impl EntropyComponent { } } +impl TypePath for EntropyComponent { + fn type_path() -> &'static str { + static CELL: GenericTypePathCell = GenericTypePathCell::new(); + CELL.get_or_insert::(|| { + format!( + "bevy_rand::component::EntropyComponent<{}>", + std::any::type_name::() + ) + }) + } + + fn short_type_path() -> &'static str { + static CELL: GenericTypePathCell = GenericTypePathCell::new(); + CELL.get_or_insert::(|| bevy::utils::get_short_name(Self::type_path())) + } + + fn type_ident() -> Option<&'static str> { + Some("EntropyComponent") + } + + fn crate_name() -> Option<&'static str> { + Some("bevy_rand") + } + + fn module_path() -> Option<&'static str> { + Some("bevy_rand::component") + } +} + impl Default for EntropyComponent { fn default() -> Self { Self::from_entropy() @@ -225,6 +255,19 @@ mod tests { ); } + #[test] + fn type_paths() { + assert_eq!( + "bevy_rand::component::EntropyComponent", + EntropyComponent::::type_path() + ); + + assert_eq!( + "EntropyComponent", + EntropyComponent::::short_type_path() + ); + } + #[cfg(feature = "serialize")] #[test] fn rng_reflection() { diff --git a/src/resource.rs b/src/resource.rs index 470b252..4de85cc 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -2,8 +2,8 @@ use std::fmt::Debug; use crate::traits::SeedableEntropySource; use bevy::{ - prelude::{FromReflect, Reflect, ReflectResource, Resource}, - reflect::ReflectFromReflect, + prelude::{Reflect, ReflectFromReflect, ReflectResource, Resource}, + reflect::{utility::GenericTypePathCell, TypePath}, }; use rand_core::{RngCore, SeedableRng}; @@ -32,7 +32,8 @@ use serde::{Deserialize, Serialize}; /// println!("Random value: {}", rng.next_u32()); /// } /// ``` -#[derive(Debug, Clone, PartialEq, Eq, Resource, Reflect, FromReflect)] +#[derive(Debug, Clone, PartialEq, Eq, Resource, Reflect)] +#[reflect_value(type_path = false)] #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serialize", @@ -65,6 +66,35 @@ impl GlobalEntropy { } } +impl TypePath for GlobalEntropy { + fn type_path() -> &'static str { + static CELL: GenericTypePathCell = GenericTypePathCell::new(); + CELL.get_or_insert::(|| { + format!( + "bevy_rand::resource::GlobalEntropy<{}>", + std::any::type_name::() + ) + }) + } + + fn short_type_path() -> &'static str { + static CELL: GenericTypePathCell = GenericTypePathCell::new(); + CELL.get_or_insert::(|| bevy::utils::get_short_name(Self::type_path())) + } + + fn type_ident() -> Option<&'static str> { + Some("GlobalEntropy") + } + + fn crate_name() -> Option<&'static str> { + Some("bevy_rand") + } + + fn module_path() -> Option<&'static str> { + Some("bevy_rand::resource") + } +} + impl Default for GlobalEntropy { fn default() -> Self { Self::from_entropy() @@ -136,15 +166,30 @@ impl From<&mut R> for GlobalEntropy { #[cfg(test)] mod tests { + use rand_chacha::ChaCha8Rng; + + use super::*; + + #[test] + fn type_paths() { + assert_eq!( + "bevy_rand::resource::GlobalEntropy", + GlobalEntropy::::type_path() + ); + + assert_eq!( + "GlobalEntropy", + GlobalEntropy::::short_type_path() + ); + } + #[cfg(feature = "serialize")] #[test] fn rng_reflection() { - use super::*; use bevy::reflect::{ serde::{ReflectSerializer, UntypedReflectDeserializer}, TypeRegistryInternal, }; - use rand_chacha::ChaCha8Rng; use ron::ser::to_string; use serde::de::DeserializeSeed; diff --git a/tests/determinism.rs b/tests/determinism.rs index df39a01..99299e1 100644 --- a/tests/determinism.rs +++ b/tests/determinism.rs @@ -82,13 +82,16 @@ fn setup_sources(mut commands: Commands, mut rng: ResMut::with_seed([2; 32])) - .add_startup_system(setup_sources) - .add_systems(( - random_output_a, - random_output_b, - random_output_c, - random_output_d, - )) + .add_plugins(EntropyPlugin::::with_seed([2; 32])) + .add_systems(Startup, setup_sources) + .add_systems( + Update, + ( + random_output_a, + random_output_b, + random_output_c, + random_output_d, + ), + ) .run(); }