bevy_sync 0.19.1

Plugin for synchronizing entities and components between server and its clients.
Documentation
use bevy_app::App;
use bevy_asset::{AssetId, Assets};
use bevy_audio::AudioSource;
use bevy_color::Color;
use bevy_ecs::{
    component::Component,
    entity::{ContainsEntity, Entity},
    query::{With, Without},
    world::{EntityRef, World},
};
use bevy_entity_uuid::EntityUuid;
use bevy_image::Image;
use bevy_mesh::Mesh;
use bevy_pbr::StandardMaterial;
use uuid::Uuid;

use crate::setup::{MySynched, TestEnv, sample_audio, sample_image, sample_mesh};

/// # Panics
///
/// on assert failure
pub fn entities_in_sync<T>(env: &mut TestEnv, _: T, entity_count: u32) {
    for c in &mut env.clients {
        let mut count_check = 0;
        for e in c.world_mut().query::<&EntityUuid>().iter(c.world()) {
            for se in env
                .server
                .world_mut()
                .query::<&EntityUuid>()
                .iter(env.server.world())
            {
                if se.uuid == e.uuid {
                    count_check += 1;
                }
            }
        }
        assert_eq!(count_check, entity_count);
    }
}

/// # Panics
///
/// on assert failure
pub fn initial_sync_for_client_happened(s: &mut App, c: &mut App, entity_count: u32) {
    let mut count_check = 0;
    for (e, c) in c
        .world_mut()
        .query::<(&EntityUuid, &MySynched)>()
        .iter(c.world())
    {
        for se in s.world_mut().query::<&EntityUuid>().iter(s.world()) {
            if se.uuid == e.uuid {
                count_check += 1;
                assert_eq!(c.value, 7);
            }
        }
    }
    assert_eq!(count_check, entity_count);
}

pub fn count_entities_with_component<T: Component>(app: &mut App) -> u32 {
    let mut count = 0;
    for _ in app
        .world_mut()
        .query_filtered::<Entity, With<T>>()
        .iter(app.world())
    {
        count += 1;
    }
    count
}

pub fn count_entities_without_component<T: Component>(app: &mut App) -> u32 {
    let mut count = 0;
    for _ in app
        .world_mut()
        .query_filtered::<Entity, Without<T>>()
        .iter(app.world())
    {
        count += 1;
    }
    count
}

pub fn get_first_entity_component<T: Component>(world: &mut World) -> Option<&T> {
    world.query::<&T>().iter(world).next()
}

/// # Panics
///
/// on assert failure
pub fn material_has_color(app: &mut App, id: AssetId<StandardMaterial>, color: Color) {
    let materials = app.world_mut().resource_mut::<Assets<StandardMaterial>>();
    let material = materials.get(id).unwrap();
    assert_eq!(material.base_color, color);
}

/// # Panics
///
/// on assert failure
pub fn assets_has_sample_mesh(app: &mut App, id: AssetId<Mesh>) {
    let meshes = app.world_mut().resource_mut::<Assets<Mesh>>();
    let mesh = meshes
        .get(id)
        .unwrap_or_else(|| panic!("Mesh {id} not found"));
    let sample = sample_mesh();
    assert_eq!(
        mesh.attribute(Mesh::ATTRIBUTE_POSITION)
            .unwrap()
            .get_bytes(),
        sample
            .attribute(Mesh::ATTRIBUTE_POSITION)
            .unwrap()
            .get_bytes()
    );
}

/// # Panics
///
/// on assert failure
pub fn assets_has_sample_image(app: &mut App, id: AssetId<Image>) {
    let images = app.world_mut().resource_mut::<Assets<Image>>();
    let image = images
        .get(id)
        .unwrap_or_else(|| panic!("Image {id:?} not found"));
    let sample = sample_image();
    assert_eq!(image.data, sample.data);
}

pub fn find_entity_with_server_id(app: &mut App, server_entity_id: Uuid) -> Option<Entity> {
    for (entity, sup) in app
        .world_mut()
        .query::<(Entity, &EntityUuid)>()
        .iter(app.world())
    {
        if sup.uuid == server_entity_id {
            return Some(entity);
        }
    }
    None
}

/// # Panics
///
/// on assert failure
pub fn assets_has_sample_audio(app: &mut App, id: AssetId<AudioSource>) {
    let assets = app.world_mut().resource_mut::<Assets<AudioSource>>();
    let asset = assets
        .get(id)
        .unwrap_or_else(|| panic!("Audio {id:?} not found"));
    let sample = sample_audio();
    assert_eq!(asset.as_ref(), sample.as_ref());
}

pub fn print_world_tree(world: &mut World) {
    for e in world.query::<EntityRef>().iter(world) {
        let e = e.entity();
        let uuid = world.entity(e).get::<EntityUuid>();
        if let Some(uuid) = uuid {
            println!("{e}: {}", uuid.uuid);
        } else {
            println!("{e}");
        }
    }
}