use bevy::ecs::entity::EntityMap;
use bevy::scene::serde::SceneDeserializer;
use bevy::utils::HashMap;
use ron::Deserializer;
use serde::de::DeserializeSeed;
use super::*;
#[derive(Component, Default, Clone)]
pub struct Unload;
#[derive(Resource)]
pub struct Loaded(HashMap<u32, Entity>);
impl Loaded {
pub fn entity(&self, entity: Entity) -> Option<Entity> {
self.0.get(&entity.index()).copied()
}
}
pub fn should_load(request: Option<Res<Request>>) -> ShouldRun {
match request.map(|request| request.should_load()) {
Some(true) => ShouldRun::Yes,
_ => ShouldRun::No,
}
}
pub fn load(world: &mut World) {
if let Request::Load { path } = world.resource::<Request>() {
match File::open(path) {
Ok(mut file) => {
let mut serialized_scene = Vec::new();
if let Err(why) = file.read_to_end(&mut serialized_scene) {
error!("file read failed: {why:?}");
}
match Deserializer::from_bytes(&serialized_scene) {
Ok(mut deserializer) => {
let result = SceneDeserializer {
type_registry: &world.resource::<AppTypeRegistry>().read(),
}
.deserialize(&mut deserializer);
match result {
Ok(scene) => {
load_world(world, scene);
}
Err(why) => {
error!("deserialization failed: {why:?}");
}
}
}
Err(why) => {
error!("deserializer creation failed: {why:?}");
}
}
}
Err(why) => {
error!("load failed: {why:?}");
}
}
}
}
pub fn load_world(world: &mut World, scene: DynamicScene) {
unload_world(world);
let mut entity_map = EntityMap::default();
if let Err(why) = scene.write_to_world(world, &mut entity_map) {
error!("world write failed: {why:?}");
}
let mut loaded = HashMap::new();
for old_entity in entity_map.keys() {
let entity = entity_map.get(old_entity).unwrap();
debug!("entity update required: {old_entity:?} -> {entity:?}");
loaded.insert(old_entity.index(), entity);
world.entity_mut(entity).insert(Save);
}
world.insert_resource(Loaded(loaded));
}
pub(crate) fn finish_load(mut commands: Commands) {
commands.remove_resource::<Request>();
commands.remove_resource::<Loaded>();
}
fn unload_world(world: &mut World) {
let entities: Vec<Entity> = world
.query_filtered::<Entity, Or<(With<Save>, With<Unload>)>>()
.iter(world)
.collect();
for entity in entities {
if let Some(entity) = world.get_entity_mut(entity) {
entity.despawn_recursive();
}
}
}
pub trait FromLoaded {
fn from_loaded(&mut self, loaded: &Loaded);
}
impl FromLoaded for Entity {
fn from_loaded(&mut self, loaded: &Loaded) {
*self = loaded.entity(*self).expect("loaded entity is not valid");
}
}
impl<T: FromLoaded> FromLoaded for Option<T> {
fn from_loaded(&mut self, loaded: &Loaded) {
if let Some(entity) = self {
entity.from_loaded(loaded);
}
}
}
pub fn loaded<T: Component + FromLoaded>(loaded: Res<Loaded>, mut query: Query<&mut T>) {
for mut component in &mut query {
component.from_loaded(&loaded);
}
}
pub trait RegisterLoaded {
fn register_loaded<T: FromLoaded + Component>(self) -> Self;
}
impl RegisterLoaded for &mut App {
fn register_loaded<T: FromLoaded + Component>(self) -> Self {
self.add_system_to_stage(SaveStage::PostLoad, loaded::<T>)
}
}