Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mintlu8/bevy_serde_lens
Stateful, structural and pretty serialization framework for the bevy engine.
https://github.com/mintlu8/bevy_serde_lens
bevy rust save serde serialization
Last synced: 3 months ago
JSON representation
Stateful, structural and pretty serialization framework for the bevy engine.
- Host: GitHub
- URL: https://github.com/mintlu8/bevy_serde_lens
- Owner: mintlu8
- License: apache-2.0
- Created: 2024-02-28T20:20:33.000Z (11 months ago)
- Default Branch: main
- Last Pushed: 2024-04-25T22:18:02.000Z (9 months ago)
- Last Synced: 2024-04-25T22:32:46.958Z (9 months ago)
- Topics: bevy, rust, save, serde, serialization
- Language: Rust
- Homepage:
- Size: 85 KB
- Stars: 9
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE-APACHE
Awesome Lists containing this project
README
# bevy_serde_lens
[![Crates.io](https://img.shields.io/crates/v/bevy_serde_lens.svg)](https://crates.io/crates/bevy_serde_lens)
[![Docs](https://docs.rs/bevy_serde_lens/badge.svg)](https://docs.rs/bevy_serde_lens/latest/bevy_serde_lens/)
[![Bevy tracking](https://img.shields.io/badge/Bevy%20tracking-released%20version-lightblue)](https://bevyengine.org/learn/book/plugin-development/)Blazingly fast, stateful, structural and human-readable serialization crate for the bevy engine.
## Features
* Stateful serialization and deserialization with world access.
* Blazingly fast (compared to `DynamicScene`).
* Treat an `Entity`, its `Component`s and children as a single serde object.
* Deserialize trait objects like `Box`, as an alternative to `typetag`.
* Extremely lightweight and modular. No systems, no plugins.
* Supports every serde format using familiar syntax.
* Serialize `Handle`s and provide a generalized data interning interface.
* Serialize stored `Entity`s in a safe manner.
* No reflection needed.## Getting Started
Imagine we have a typical `Character` bundle.
First we derive `BevyObject`:
```rust
#[derive(Bundle, BevyObject)]
#[bevy_object(query)]
pub struct Character {
pub transform: Transform,
pub name: Name,
pub position: Position,
pub hp: Hp,
}
```* `#[bevy_object(query)]`
This indicates we are serializing a query instead of a hierarchical tree, which improves performance.
To serialize we simply do:
```rust
serde_json::to_string(&world.serialize_lens::());
```This finds all entities that fits the `QueryFilter` of the bundle and serializes them in an array.
To deserialize we use `deserialize_scope`:
```rust
world.deserialize_scope(|| {
// Returned object doesn't matter, data is stored in the world.
let _ = serde_json::from_str::>(&json_string);
})
```This statement spawns new entities in the world and fills them with deserialized data.
You might want to delete current entities before loading new ones,
to delete all associated entities of a serialization:```rust
// Despawn all character.
world.despawn_bound_objects::()
```To save multiple types of objects in a batch, create a batch serialization type with the `batch!` macro.
```rust
type SaveFile = batch!(
Character, Monster,
// Use `SerializeResource` to serialize a resource.
SerializeResource,
);
world.save::(serializer)
world.load::(deserializer)
world.despawn_bound_objects::()
```This saves each type in a map entry:
```rust
{
"Character": [
{ .. },
{ .. },
..
],
"Monster": [ .. ],
"Terrain": ..
}
```## Advanced Serialization
`BevyObject` is not just a clone of `Bundle`, we support additional types.
* `impl BevyObject`: Components are automatically `BevyObject` and `BevyObject` can contain multiple other `BevyObject`s.
* `Maybe` can be used if an item may or may not exist.
* `DefaultInit` initializes a non-serialize component with `FromWorld`.
* `Child` finds and serializes a single `BevyObject` in children.
* `ChildVec` finds and serializes multiple `BevyObject`s in children.See the `BevyObject` derive macro for more details.
```rust
// Note we cannot derive bundle anymore :(
// #[bevy_object(query)] also cannot be used due to children being serialized.
#[derive(BevyObject)]
#[bevy_object(rename = "character")]
pub struct Character {
pub transform: Transform,
pub name: Name,
pub position: Position,
pub hp: Hp,
#[serde(default)]
pub weapon: Maybe
#[serde(skip)]
pub cache: DefaultInit,
pub potions: ChildVec
}
```## Projection Types
The crate provides various projection types for certain common use cases.
For example, to serialize a `Handle` as its string path,
you can use `#[serde(with = "PathHandle")]` like so```rust
#[derive(Serialize, Deserialize)]
struct MySprite {
#[serde(with = "PathHandle")]
image: Handle
}
```Or use the newtype directly.
```rust
#[derive(Serialize, Deserialize)]
struct MySprite {
image: PathHandle
}
```## EntityId
We provide a framework to serialize `Entity`, `Parent` etc. Before we start keep in mind
this only works with a serializer that can preserve the order of maps.
In `serde_json` for instance, you must enable feature `preserve_order` to use these features.When using `BevyObject`, we can specify the `EntityId` component.
This registers the `Entity` id of this entity for future use in the same batch.**After** the entry, future entities can use `Parented` to parent to this entity,
or use `EntityPtr` to serialize an `Entity` that references this entity.## TypeTag
The `typetag` crate allows you to serialize trait objects like `Box`,
but using `typetag` will always
pull in all implementations linked to your build and does not work on WASM.
To address these limitations this crate allows you to register deserializers manually
in the bevy `World` and use the `TypeTagged` projection type for serialization.```rust
world.register_typetag::, Cat>()
```then
```rust
#[derive(Serialize, Deserialize)]
struct MyComponent {
#[serde(with = "TypeTagged")]
weapon: Box
}
```To have user friendly configuration files,
you can use `register_deserialize_any` and `AnyTagged` to allow `deserialize_any`, i.e.
deserialize `42` instead of `{"int": 42}` in self-describing formats.
Keep in mind using `AnyTagged` in a non-self-describing format like `postcard` will always return an error
as this is a limitation of the serde specification.```rust
world.register_deserialize_any(|s: &str|
Ok(Box::new(s.parse::()
.map_err(|e| e.to_string())?
) as Box)
)
```## For Library Authors
It is more ideal to depend on `bevy_serde_lens_core` since its semver is less likely
to change inside a major bevy release cycle.## Versions
| bevy | bevy-serde-lens-core | bevy-serde-lens |
|------|----------------------|--------------------|
| 0.13 | - | 0.1-0.3 |
| 0.14 | 0.14 | 0.4 |## License
Licensed under either of
* Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or )
* MIT license ([LICENSE-MIT](LICENSE-MIT) or )at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
additional terms or conditions.