diff --git a/Cargo.toml b/Cargo.toml index e24544d..0b972b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,11 @@ categories = ["network-programming", "game-development"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] +default = ["serde", "ron", "bincode"] wasm-bindgen = ["instant/wasm-bindgen", "ggrs/wasm-bindgen"] +serde = ["dep:serde"] +ron = ["serde", "dep:ron"] +bincode = ["serde", "dep:bincode"] [dependencies] bevy = { version = "0.12", default-features = false } @@ -22,13 +26,16 @@ instant = { version = "0.1", optional = true } log = "0.4" #ggrs = { version= "0.9.4", features=["sync-send"]} ggrs = { git = "https://github.com/gschup/ggrs", features=["sync-send"]} +serde = { version = "1", optional = true } +ron = { version = "0.8", optional = true } +bincode = { version = "1.3", optional = true } [dev-dependencies] bevy = { version = "0.12", default-features = true } clap = { version = "4.4", features = ["derive"] } rand = "0.8.4" rand_xoshiro = "0.6" -serde = "1.0.130" +serde = "1" serde_json = "1.0" serial_test = "2.0" diff --git a/src/lib.rs b/src/lib.rs index 5f3f4fb..a33c258 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -228,6 +228,34 @@ impl Plugin for GgrsPlugin { /// Extension trait to add the GGRS plugin idiomatically to Bevy Apps pub trait GgrsApp { + /// Registers a component type for saving and loading from the world. This + /// uses [Serde](`serde`) and [RON](`ron`). + #[cfg(feature = "ron")] + fn rollback_component_with_ron(&mut self) -> &mut Self + where + Type: Component + serde::Serialize + serde::de::DeserializeOwned; + + /// Registers a resource type for saving and loading from the world. This + /// uses [Serde](`serde`) and [RON](`ron`). + #[cfg(feature = "ron")] + fn rollback_resource_with_ron(&mut self) -> &mut Self + where + Type: Resource + serde::Serialize + serde::de::DeserializeOwned; + + /// Registers a component type for saving and loading from the world. This + /// uses [Serde](`serde`) and [bincode](`bincode`). + #[cfg(feature = "bincode")] + fn rollback_component_with_bincode(&mut self) -> &mut Self + where + Type: Component + serde::Serialize + serde::de::DeserializeOwned; + + /// Registers a resource type for saving and loading from the world. This + /// uses [Serde](`serde`) and [bincode](`bincode`). + #[cfg(feature = "bincode")] + fn rollback_resource_with_bincode(&mut self) -> &mut Self + where + Type: Resource + serde::Serialize + serde::de::DeserializeOwned; + /// Registers a component type for saving and loading from the world. This /// uses [`Copy`] based snapshots for rollback. fn rollback_component_with_copy(&mut self) -> &mut Self @@ -396,4 +424,35 @@ impl GgrsApp for App { { self.add_plugins(ResourceChecksumPlugin::(hasher)) } + #[cfg(feature = "ron")] + fn rollback_component_with_ron(&mut self) -> &mut Self + where + Type: Component + serde::Serialize + serde::de::DeserializeOwned, + { + self.add_plugins(ComponentSnapshotPlugin::>::default()) + } + + #[cfg(feature = "ron")] + fn rollback_resource_with_ron(&mut self) -> &mut Self + where + Type: Resource + serde::Serialize + serde::de::DeserializeOwned, + { + self.add_plugins(ResourceSnapshotPlugin::>::default()) + } + + #[cfg(feature = "bincode")] + fn rollback_component_with_bincode(&mut self) -> &mut Self + where + Type: Component + serde::Serialize + serde::de::DeserializeOwned, + { + self.add_plugins(ComponentSnapshotPlugin::>::default()) + } + + #[cfg(feature = "bincode")] + fn rollback_resource_with_bincode(&mut self) -> &mut Self + where + Type: Resource + serde::Serialize + serde::de::DeserializeOwned, + { + self.add_plugins(ResourceSnapshotPlugin::>::default()) + } } diff --git a/src/snapshot/strategy.rs b/src/snapshot/strategy.rs index 0fb6f27..6e6b029 100644 --- a/src/snapshot/strategy.rs +++ b/src/snapshot/strategy.rs @@ -92,3 +92,65 @@ impl Strategy for ReflectStrategy { target } } + +#[cfg(feature = "ron")] +mod ron_strategy { + use std::marker::PhantomData; + + use serde::{de::DeserializeOwned, Serialize}; + + use crate::Strategy; + + /// A [`Strategy`] based on [`serde`] and [`ron`] + pub struct RonStrategy(PhantomData); + + impl Strategy for RonStrategy { + type Target = T; + + type Stored = String; + + #[inline(always)] + fn store(target: &Self::Target) -> Self::Stored { + ron::to_string(target).unwrap() + } + + #[inline(always)] + fn load(stored: &Self::Stored) -> Self::Target { + ron::from_str(stored).unwrap() + } + } +} + +#[cfg(feature = "ron")] +pub use ron_strategy::*; + +#[cfg(feature = "bincode")] +mod bincode_strategy { + use std::marker::PhantomData; + + use serde::{de::DeserializeOwned, Serialize}; + + use crate::Strategy; + + /// A [`Strategy`] based on [`serde`] and [`bincode`] + pub struct BincodeStrategy(PhantomData); + + impl Strategy for BincodeStrategy { + type Target = T; + + type Stored = Vec; + + #[inline(always)] + fn store(target: &Self::Target) -> Self::Stored { + bincode::serialize(target).unwrap() + } + + #[inline(always)] + fn load(stored: &Self::Stored) -> Self::Target { + bincode::deserialize(stored).unwrap() + } + } +} + +#[cfg(feature = "bincode")] +pub use bincode_strategy::*;