From 9965351dba6b7cb5820e04aa35f74151014810b3 Mon Sep 17 00:00:00 2001 From: Bluefinger Date: Mon, 17 Jul 2023 09:46:37 +0100 Subject: [PATCH 1/3] feat: Custom TypePath impl for component/resource --- Cargo.toml | 4 ++-- examples/turn_based_game.rs | 9 ++++++--- src/component.rs | 31 ++++++++++++++++++++++++++++--- src/resource.rs | 30 +++++++++++++++++++++++++++--- tests/determinism.rs | 19 +++++++++++-------- 5 files changed, 74 insertions(+), 19 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 29cbad6..d948221 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 = { git = "https://github.com/MrGVSV/bevy/", branch = "reflect-type-path-opt-out", default-features = false } # others serde = { version = "1.0", features = ["derive"], optional = true } 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..c08bc91 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,30 @@ impl EntropyComponent { } } + +impl TypePath for EntropyComponent { + fn type_path() -> &'static str { + std::any::type_name::() + } + + fn short_type_path() -> &'static str { + static CELL: GenericTypePathCell = GenericTypePathCell::new(); + CELL.get_or_insert::(|| bevy::utils::get_short_name(std::any::type_name::())) + } + + 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() diff --git a/src/resource.rs b/src/resource.rs index 470b252..da146f0 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,29 @@ impl GlobalEntropy { } } +impl TypePath for GlobalEntropy { + fn type_path() -> &'static str { + std::any::type_name::() + } + + fn short_type_path() -> &'static str { + static CELL: GenericTypePathCell = GenericTypePathCell::new(); + CELL.get_or_insert::(|| bevy::utils::get_short_name(std::any::type_name::())) + } + + 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() 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(); } From 86e1dfee17279a03ea00b0914c66a1825ee482f5 Mon Sep 17 00:00:00 2001 From: Bluefinger Date: Wed, 16 Aug 2023 09:23:12 +0100 Subject: [PATCH 2/3] chore: update to bevy v0.11.1 --- Cargo.toml | 2 +- README.md | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d948221..132748f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ serialize = ["dep:serde", "rand_core/serde1", "rand_chacha?/serde1"] [dependencies] # bevy -bevy = { git = "https://github.com/MrGVSV/bevy/", branch = "reflect-type-path-opt-out", 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..e43e030 100644 --- a/README.md +++ b/README.md @@ -178,9 +178,10 @@ All recommended crates implement the necessary traits to be compatible with `bev `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 From 772ec20af379d1993b5ead9aa9f19a13809cf8df Mon Sep 17 00:00:00 2001 From: Bluefinger Date: Wed, 16 Aug 2023 10:44:56 +0100 Subject: [PATCH 3/3] chore: Make TypePath more stable, README note --- README.md | 6 ++++++ src/component.rs | 24 +++++++++++++++++++++--- src/resource.rs | 29 +++++++++++++++++++++++++---- 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index e43e030..f840a1d 100644 --- a/README.md +++ b/README.md @@ -174,6 +174,12 @@ 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`. diff --git a/src/component.rs b/src/component.rs index c08bc91..3c7dbd8 100644 --- a/src/component.rs +++ b/src/component.rs @@ -123,15 +123,20 @@ impl EntropyComponent { } } - impl TypePath for EntropyComponent { fn type_path() -> &'static str { - std::any::type_name::() + 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(std::any::type_name::())) + CELL.get_or_insert::(|| bevy::utils::get_short_name(Self::type_path())) } fn type_ident() -> Option<&'static str> { @@ -250,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 da146f0..4de85cc 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -68,12 +68,18 @@ impl GlobalEntropy { impl TypePath for GlobalEntropy { fn type_path() -> &'static str { - std::any::type_name::() + 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(std::any::type_name::())) + CELL.get_or_insert::(|| bevy::utils::get_short_name(Self::type_path())) } fn type_ident() -> Option<&'static str> { @@ -160,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;