bevy_entity_uuid 0.18.0

Keep track of entities via uuid
Documentation
use bevy::prelude::*;
use bevy_entity_uuid::CommandsEntityUuid;
use bevy_entity_uuid::EntityLookup;
use bevy_entity_uuid::EntityUuid;
use bevy_entity_uuid::EntityUuidDeleted;
use bevy_entity_uuid::EntityUuidPlugin;
use bevy_entity_uuid::WorldEntityUuid;
use uuid::Uuid;

fn setup_app<T: Fn(Commands) + Send + Sync + 'static>(setup: T) -> App {
    let mut app = App::new();
    let fn_setup = move |cmd: Commands| {
        setup(cmd);
    };
    app.add_plugins(EntityUuidPlugin);
    app.add_systems(Startup, fn_setup);
    app.update();
    app
}

fn setup_app_removal_callback<T: Fn(Commands) + Send + Sync + 'static>(setup: T) -> App {
    let mut app = App::new();
    let fn_setup = move |cmd: Commands| {
        setup(cmd);
    };
    app.add_plugins(EntityUuidPlugin);
    app.add_systems(Startup, fn_setup);
    app.init_resource::<Messages<EntityUuidDeleted>>();
    app.update();
    app
}

#[test]
fn test_component_added_then_removed_component() {
    let uuid = Uuid::new_v4();
    let mut app = setup_app(move |mut cmd: Commands| {
        cmd.spawn_empty_uuid(uuid);
    });

    let map = app.world().resource::<EntityLookup>();
    let id = map.uuid_to_entity(&uuid).unwrap();
    let uuid2 = map.entity_to_uuid(&id).unwrap();
    let mut entity = app.world_mut().entity_mut(id);
    let comp = entity.get::<EntityUuid>().unwrap();
    assert_eq!(comp.uuid, uuid);
    assert_eq!(uuid, uuid2);

    entity.remove::<EntityUuid>();
    let map = app.world().resource::<EntityLookup>();
    assert!(map.uuid_to_entity(&uuid).is_none());
    assert!(map.entity_to_uuid(&id).is_none());
}

#[test]
fn test_component_added_then_removed_entity() {
    let uuid = Uuid::new_v4();
    let mut app = setup_app(move |mut cmd: Commands| {
        cmd.spawn_empty_uuid(uuid);
    });

    let map = app.world().resource::<EntityLookup>();
    let id = map.uuid_to_entity(&uuid).unwrap();
    let uuid2 = map.entity_to_uuid(&id).unwrap();
    let entity = app.world_mut().entity_mut(id);
    let comp = entity.get::<EntityUuid>().unwrap();
    assert_eq!(comp.uuid, uuid);
    assert_eq!(uuid, uuid2);

    entity.despawn();
    let map = app.world().resource::<EntityLookup>();
    assert!(map.uuid_to_entity(&uuid).is_none());
    assert!(map.entity_to_uuid(&id).is_none());
}

#[test]
fn test_component_added_via_bundle() {
    let uuid = Uuid::new_v4();
    let mut app = setup_app(move |mut cmd: Commands| {
        cmd.spawn_uuid(uuid, Transform::default());
    });

    let map = app.world().resource::<EntityLookup>();
    let id = map.uuid_to_entity(&uuid).unwrap();
    let uuid2 = map.entity_to_uuid(&id).unwrap();
    let mut entity = app.world_mut().entity_mut(id);
    let comp = entity.get::<EntityUuid>().unwrap();
    assert_eq!(comp.uuid, uuid);
    assert_eq!(uuid, uuid2);

    entity.remove::<EntityUuid>();
    let map = app.world().resource::<EntityLookup>();
    assert!(map.uuid_to_entity(&uuid).is_none());
    assert!(map.entity_to_uuid(&id).is_none());
}

#[test]
fn test_with_world_sync() {
    let uuid = Uuid::new_v4();
    let mut app = setup_app(|_| {});
    let id1 = app.world_mut().spawn_empty_uuid(uuid).id();
    let id2 = app.world_mut().spawn_empty_uuid(uuid).id();

    // Spawn with same uuid returns the original one
    // only World can do this because it's synchronous
    assert_eq!(id1, id2);
}

#[test]
fn test_with_world_sync_composed() {
    let uuid = Uuid::new_v4();
    let mut app = setup_app(|_| {});
    let id1 = app.world_mut().spawn_uuid(uuid, Transform::default()).id();
    let id2 = app.world_mut().spawn_uuid(uuid, Transform::default()).id();

    // Spawn with same uuid returns the original one
    // only World can do this because it's synchronous
    assert_eq!(id1, id2);
}

#[test]
fn test_removal_callback() {
    let uuid = Uuid::new_v4();
    let mut app = setup_app_removal_callback(move |mut cmd: Commands| {
        cmd.spawn_uuid(uuid, Transform::default());
    });

    let map = app.world().resource::<EntityLookup>();
    let id = map.uuid_to_entity(&uuid).unwrap();
    app.world_mut().entity_mut(id).despawn();

    let events = app.world_mut().resource::<Messages<EntityUuidDeleted>>();
    let mut cursor = events.get_cursor();
    let event = cursor.read(events).next().unwrap();
    assert_eq!(uuid, event.0);
}