bevy_sync 0.19.1

Plugin for synchronizing entities and components between server and its clients.
Documentation
//! `bevy_sync`
//!
//! Plugin for synchronizing entities and components between server and its clients.

use bevy_connect::ClientId;
use bevy_ecs::message::Message;
use bevy_ecs::prelude::Component;
use bevy_ecs::prelude::ReflectComponent;
use bevy_ecs::prelude::Resource;
use bevy_reflect::{DynamicTypePath, FromReflect, GetTypeRegistration, Reflect, TypePath};
use bevy_state::state::States;
use serde::{Deserialize, Serialize};
/// Use this event to promote one of the clients as host
pub use uuid::Uuid;
pub mod prelude {
    pub use super::{
        ClientState, ConnectCommand, DisconnectCommand, PromoteToHostCommand, ServerState,
        SyncComponent, SyncConnectionParameters, SyncEntity, SyncExclude, SyncMark, SyncPlugin,
    };
}

mod metrics;
mod binreflect;
mod bundle_fix;
mod client;
mod commands;
mod full_sync;
mod handle_uuid_fix;
mod lib_priv;
mod logging;
mod networking;
mod proto;
mod server;
mod track;

use std::{collections::HashSet, marker::PhantomData, net::IpAddr};

/// Use this component to mark which entities to be synched.
/// This component will be replaced with [`SyncEntity`] once the system engages on it.
#[derive(Component, Reflect, Default)]
#[reflect(Component)]
pub struct SyncMark;

/// Keeps track of the entity uuid used by `bevy_sync` across clients.
/// This is automatically created on entities marked with [`SyncMark`].
/// You don't need to add this one, it's only a marker.
#[derive(Component)]
pub struct SyncEntity;

/// Use this component to mark which component in the entity to exclude from sync.
/// This will skip synchronization only for the specific entity that is marked by this
/// component, and onlt for the component T inside that entity.
/// To skip more components into an entity, add more variations of this for more types.
#[derive(Component, Default)]
pub struct SyncExclude<T: Component> {
    marker: PhantomData<T>,
}

/// Specify networking options to create a session. This will also be available as a resource.
#[derive(Serialize, Deserialize, Debug, Resource, Clone)]
pub enum SyncConnectionParameters {
    Direct {
        ip: IpAddr,
        port: u16,
        asset_port: u16,
    },
}

/// Main `bevy_sync` plugin to setup for sync
pub struct SyncPlugin;

/// Published state for server connectivity.
#[derive(Debug, Clone, Eq, PartialEq, Hash, Default, States)]
pub enum ServerState {
    Connected,
    #[default]
    Disconnected,
}

/// Published state for client connectivity.
#[derive(Debug, Clone, Eq, PartialEq, Hash, Default, States)]
pub enum ClientState {
    ConnectedInitialSync,
    Connected,
    #[default]
    Disconnected,
}

#[derive(Message)]
pub struct InitialSyncFinished;

/// Use this trait extension to configure sync details for your app.
/// Every component that needs to be synched must be called with [`SyncComponent::sync_component`].
/// To enable assets synching, use the other sync_* methods.
/// By default nothing is being synched, so you'll need to additively call all these.
pub trait SyncComponent {
    fn sync_component<
        T: Component
            + TypePath
            + DynamicTypePath
            + Reflect
            + FromReflect
            + GetTypeRegistration
            + Clone,
    >(
        &mut self,
    ) -> &mut Self;
    fn sync_materials(&mut self, enable: bool);
    fn sync_meshes(&mut self, enable: bool);
    fn sync_audios(&mut self, enable: bool);
}

/// Use this command to initiate a connection.
pub struct ConnectCommand {
    /// Set this to true for hosting otherwise it's the client connecting to a
    /// host
    pub is_host: bool,
    /// The more detailed connection parameters, including which mechanism
    /// of networking is being used.
    pub config: SyncConnectionParameters,
}

/// Use this command to disconnect from the network.
pub struct DisconnectCommand;

/// Use this command to promote one of the clients to become the new host.
/// The list of client ids are obtainable through when the join event happens.
///
/// First param is the uuid of the new host.
/// Second param is the port that the new server will use, or [None] to reuse
/// the already defined port.
pub struct PromoteToHostCommand(pub ClientId, pub Option<u16>);

/// Utility funcions to discover clients uuids.
pub trait SyncWorld {
    /// Return the uuid of the host, regardless if this is the host or not.
    fn sync_host_uuid(&self) -> Option<ClientId>;
    /// Return the uuid of this connection
    fn sync_self_uuid(&self) -> ClientId;
    /// Returns the list of all client uuids, including the host one.
    fn sync_all_client_uuids(&self) -> HashSet<ClientId>;
    /// Measures how many event message are left in the queue, useful for
    /// metrics and testing.
    fn events_queue_count(&self) -> usize;
}

#[derive(Clone, Debug, Default, Resource)]
pub struct SyncStats {
    total_sync_net_sent_prev: usize,
    total_sync_net_read_prev: usize,
    pub total_sync_net_sent: usize,
    pub total_sync_net_read: usize,
    total_asset_net_sent_prev: usize,
    total_asset_net_read_prev: usize,
    pub total_asset_net_sent: usize,
    pub total_asset_net_read: usize,
}