use bevy_archive::archetype_archive::WorldArchSnapshot;
use bevy_archive::flecs_archsnaphot::*;
use bevy_archive::flecs_registry::*;
use bevy_archive::prelude::AuroraWorldManifest;
use bevy_archive::prelude::WorldWithAurora;
use bevy_ecs::name::Name;
use bevy_ecs::prelude::Component as BevyComponent;
use flecs_ecs::prelude::*;
use serde::{Deserialize, Serialize};
use std::fs;
#[derive(Component, BevyComponent, Serialize, Deserialize, Debug, Clone, PartialEq)]
struct Position {
x: f32,
y: f32,
}
#[derive(Component, BevyComponent, Serialize, Deserialize, Debug, Clone, PartialEq)]
struct Velocity {
dx: f32,
dy: f32,
}
#[derive(Component, BevyComponent, Serialize, Deserialize, Debug, Clone, PartialEq)]
struct Inventory(Vec<String>);
#[derive(Component, BevyComponent, Serialize, Deserialize, Debug, Clone)]
struct NestedComponent {
inner: Vector2,
name: String,
}
#[derive(Clone, BevyComponent, Serialize, Deserialize, Debug, Component)]
pub struct Vector2([f32; 2]);
#[derive(Clone, BevyComponent, Serialize, Deserialize, Debug)]
pub struct Vector2Wrapper {
pub x: f32,
pub y: f32,
}
impl From<&Vector2> for Vector2Wrapper {
fn from(p: &Vector2) -> Self {
Self {
x: p.0[0],
y: p.0[1],
}
}
}
impl From<Vector2Wrapper> for Vector2 {
fn from(p: Vector2Wrapper) -> Self {
Self([p.x, p.y])
}
}
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct ChildOfWrapper(pub u32);
#[derive(Component, Serialize, Deserialize, Default)]
pub struct NameID(pub String);
fn setup_registry() -> SnapshotRegistry {
let mut registry = SnapshotRegistry::default();
registry.register::<Position>();
registry.register::<Velocity>();
registry.register::<Inventory>();
registry.register::<NestedComponent>();
registry.register::<NameID>();
registry.register_with::<Vector2, Vector2Wrapper>();
registry
}
impl From<&Name> for NameID {
fn from(value: &Name) -> Self {
Self(value.to_string())
}
}
impl From<NameID> for Name {
fn from(value: NameID) -> Self {
Self::new(value.0)
}
}
fn setup_registry_bevy() -> bevy_archive::prelude::SnapshotRegistry {
let mut registry = bevy_archive::prelude::SnapshotRegistry::default();
registry.register::<Position>();
registry.register::<Velocity>();
registry.register::<Inventory>();
registry.register::<NestedComponent>();
registry.register_with::<Vector2, Vector2Wrapper>();
registry.register_with_name::<Name, NameID>("NameID");
registry
}
fn build_sample_world(world: &mut World) -> Entity {
println!("Snapshot:\n");
for e in 0..50 {
let ent = world.entity();
match e % 7 {
0 => {
ent.set(Position {
x: 1.0 * e as f32,
y: -1.0 * e as f32,
});
ent.set_name(format!("entity_{}", e).as_str());
}
1 => {
ent.set(Velocity {
dx: e as f32,
dy: -e as f32,
});
ent.set(Vector2([e as f32, 2.0 * e as f32]));
}
2 => {
ent.set(Inventory(vec!["sword".into(), "apple".into()]));
ent.set_name(format!("hero_{}", e).as_str());
}
3 => {
ent.set(NestedComponent {
inner: Vector2([0.5 * e as f32, 0.25 * e as f32]),
name: "omega".into(),
});
ent.set_name(format!("boss_{}", e).as_str());
}
4 => {
ent.set(Position {
x: 1.1 * e as f32,
y: -1.1 * e as f32,
});
ent.set(Velocity {
dx: -0.5 * e as f32,
dy: 0.5 * e as f32,
});
ent.set_name(format!("combo_{}", e).as_str());
}
5 => {
ent.set_name(format!("flagged_{}", e).as_str());
}
6 => {
ent.set(Vector2([42.0, -42.0]));
ent.set_name(format!("vec_{}", e).as_str());
}
_ => {}
}
}
world.lookup("boss_3").id()
}
pub fn save_world_manifest(
world: &World,
registry: &SnapshotRegistry,
) -> Result<AuroraWorldManifest, String> {
let snapshot = save_world_arch_snapshot(world, registry);
let world_with_aurora = WorldWithAurora::from(&snapshot);
Ok(AuroraWorldManifest {
metadata: None,
world: world_with_aurora,
})
}
pub fn load_world_manifest(
world: &mut World,
manifest: &AuroraWorldManifest,
registry: &SnapshotRegistry,
) -> Result<(), String> {
let snapshot: WorldArchSnapshot = (&manifest.world).into();
load_world_arch_snapshot(world, &snapshot, registry);
Ok(())
}
fn test_roundtrip_with_children() {
let mut world = World::new();
let registry = setup_registry();
let _boss_id = build_sample_world(&mut world);
let snapshot = save_world_manifest(&world, ®istry).unwrap();
println!(
"\n\u{1F4C8} Snapshot: {}",
toml::to_string_pretty(&snapshot).unwrap()
);
let path = "example_output.toml";
snapshot.to_file(path, None).unwrap();
println!("\u{1F4BE} Snapshot saved to `{}`", path);
let mut new_world = bevy_ecs::prelude::World::new();
let registry = setup_registry_bevy();
let loaded = AuroraWorldManifest::from_file(path, None).unwrap();
bevy_archive::prelude::load_world_manifest(&mut new_world, &loaded, ®istry).unwrap();
let snapshot = bevy_archive::prelude::save_world_manifest(&new_world, ®istry).unwrap();
println!(
"\n\u{1F4C8} Reloaded Snapshot: {}",
toml::to_string_pretty(&snapshot).unwrap()
);
let _ = fs::remove_file(path);
}
fn main() {
test_roundtrip_with_children();
}