Skip to main content

AppRuleExt

Trait AppRuleExt 

Source
pub trait AppRuleExt {
Show 24 methods // Required methods fn replicate_resource_with<R: Resource<Mutability: MutWrite<R>>>( &mut self, resource_rule: impl IntoResourceRule<R>, ) -> &mut Self; fn replicate_with_priority_filtered<R: IntoComponentRules, F: FilterRules>( &mut self, priority: usize, component_rules: R, ) -> &mut Self; fn replicate_bundle_with_filtered<B: BundleRules, F: FilterRules>( &mut self, priority: usize, ) -> &mut Self; // Provided methods fn replicate<C>(&mut self) -> &mut Self where C: Component<Mutability: MutWrite<C>> + Serialize + DeserializeOwned { ... } fn replicate_once<C>(&mut self) -> &mut Self where C: Component<Mutability: MutWrite<C>> + Serialize + DeserializeOwned { ... } fn replicate_diff<C>(&mut self) -> &mut Self where C: Diffable { ... } fn replicate_diff_filtered<C, F: FilterRules>(&mut self) -> &mut Self where C: Diffable { ... } fn replicate_as<C, T>(&mut self) -> &mut Self where C: Component<Mutability: MutWrite<C>> + Clone + Into<T> + From<T>, T: Serialize + DeserializeOwned { ... } fn replicate_once_as<C, T>(&mut self) -> &mut Self where C: Component<Mutability: MutWrite<C>> + Clone + Into<T> + From<T>, T: Serialize + DeserializeOwned { ... } fn replicate_resource<R>(&mut self) -> &mut Self where R: Resource<Mutability: MutWrite<R>> + Serialize + DeserializeOwned { ... } fn replicate_resource_diff<R>(&mut self) -> &mut Self where R: Resource<Mutability: MutWrite<R>> + Diffable { ... } fn replicate_resource_once<R>(&mut self) -> &mut Self where R: Resource<Mutability: MutWrite<R>> + Serialize + DeserializeOwned { ... } fn replicate_resource_as<R, T>(&mut self) -> &mut Self where R: Resource<Mutability: MutWrite<R>> + Clone + Into<T> + From<T>, T: Serialize + DeserializeOwned { ... } fn replicate_resource_once_as<R, T>(&mut self) -> &mut Self where R: Resource<Mutability: MutWrite<R>> + Clone + Into<T> + From<T>, T: Serialize + DeserializeOwned { ... } fn replicate_filtered<C, F: FilterRules>(&mut self) -> &mut Self where C: Component<Mutability: MutWrite<C>> + Serialize + DeserializeOwned { ... } fn replicate_once_filtered<C, F: FilterRules>(&mut self) -> &mut Self where C: Component<Mutability: MutWrite<C>> + Serialize + DeserializeOwned { ... } fn replicate_filtered_as<C, T, F: FilterRules>(&mut self) -> &mut Self where C: Component<Mutability: MutWrite<C>> + Clone + Into<T> + From<T>, T: Serialize + DeserializeOwned { ... } fn replicate_once_filtered_as<C, T, F: FilterRules>(&mut self) -> &mut Self where C: Component<Mutability: MutWrite<C>> + Clone + Into<T> + From<T>, T: Serialize + DeserializeOwned { ... } fn replicate_with<R: IntoComponentRules>( &mut self, component_rules: R, ) -> &mut Self { ... } fn replicate_with_filtered<R: IntoComponentRules, F: FilterRules>( &mut self, component_rules: R, ) -> &mut Self { ... } fn replicate_with_priority<R: IntoComponentRules>( &mut self, priority: usize, component_rules: R, ) -> &mut Self { ... } fn replicate_bundle<B: BundleRules>(&mut self) -> &mut Self { ... } fn replicate_bundle_filtered<B: BundleRules, F: FilterRules>( &mut self, ) -> &mut Self { ... } fn replicate_bundle_with<B: BundleRules>( &mut self, priority: usize, ) -> &mut Self { ... }
}
Expand description

Replication functions for App.

Required Methods§

Source

fn replicate_resource_with<R: Resource<Mutability: MutWrite<R>>>( &mut self, resource_rule: impl IntoResourceRule<R>, ) -> &mut Self

Like Self::replicate_with, but for a single Resource.

See also Self::replicate_resource.

Source

fn replicate_with_priority_filtered<R: IntoComponentRules, F: FilterRules>( &mut self, priority: usize, component_rules: R, ) -> &mut Self

Like Self::replicate_filtered, but for Self::replicate_with_priority.

The default priority equals the total number of components and filters in the rule

Source

fn replicate_bundle_with_filtered<B: BundleRules, F: FilterRules>( &mut self, priority: usize, ) -> &mut Self

Provided Methods§

Source

fn replicate<C>(&mut self) -> &mut Self
where C: Component<Mutability: MutWrite<C>> + Serialize + DeserializeOwned,

Defines a ReplicationRule for a single component.

If present on an entity with Replicated component, it will be serialized and deserialized as-is using postcard and sent at ReplicationMode::OnChange. To customize this, use Self::replicate_with.

See also the components section from the quick start guide.

Source

fn replicate_once<C>(&mut self) -> &mut Self
where C: Component<Mutability: MutWrite<C>> + Serialize + DeserializeOwned,

Source

fn replicate_diff<C>(&mut self) -> &mut Self
where C: Diffable,

Like Self::replicate, but sends recorded diffs instead of re-sending the entire component when it changes.

Mutations should be performed through EntityCommandsDiffExt::apply_diff or EntityDiffExt::apply_diff.

See Diffable for more details.

Source

fn replicate_diff_filtered<C, F: FilterRules>(&mut self) -> &mut Self
where C: Diffable,

Like Self::replicate_diff, but also adds filters like Self::replicate_filtered.

Source

fn replicate_as<C, T>(&mut self) -> &mut Self
where C: Component<Mutability: MutWrite<C>> + Clone + Into<T> + From<T>, T: Serialize + DeserializeOwned,

Like Self::replicate, but converts the component into T before serialization and back into C after deserialization.

Useful for customizing how the component is sent over the network. In some cases, this is more convenient than passing custom ser/de functions with Self::replicate_with, because you only need to implement From<C> for T and From<T> for C.

§Examples

Quantize position:

use bevy::{math::I16Vec2, prelude::*};
use bevy_replicon::prelude::*;
use serde::{Deserialize, Serialize};

app.replicate_as::<Position, QuantizedPosition>();

#[derive(Component, Deref, Clone, Copy)]
struct Position(Vec2);

/// Quantized representation of [`Position`] sent over the network.
#[derive(Deref, Serialize, Deserialize)]
struct QuantizedPosition(I16Vec2);

/// Scale factor for quantizing.
///
/// Each unit in world space is multiplied by this factor before rounding.
/// With this scale we keep two decimal places of precision (0.01 units).
/// The representable range is from [`i16::MIN`] to [`i16::MAX`] divided by this value,
/// which is `-327.68..=327.67` per axis. Values outside this range will overflow,
/// so world positions should stay within it.
const SCALE: f32 = 100.0;

impl From<Position> for QuantizedPosition {
    fn from(position: Position) -> Self {
        Self((*position * SCALE).round().as_i16vec2())
    }
}

impl From<QuantizedPosition> for Position {
    fn from(position: QuantizedPosition) -> Self {
        Position(position.as_vec2() / SCALE)
    }
}

Ignore scale.

This will overwrite the scale value with the default. If you want to preserve it, use Self::replicate_with to provide in-place deserialization.

use bevy::prelude::*;
use bevy_replicon::prelude::*;
use serde::{Deserialize, Serialize};

app.replicate_as::<Transform, TransformWithoutScale>();

#[derive(Serialize, Deserialize, Clone, Copy)]
struct TransformWithoutScale {
    translation: Vec3,
    rotation: Quat,
}

impl From<Transform> for TransformWithoutScale {
    fn from(value: Transform) -> Self {
        Self {
            translation: value.translation,
            rotation: value.rotation,
        }
    }
}

impl From<TransformWithoutScale> for Transform {
    fn from(value: TransformWithoutScale) -> Self {
        Self {
            translation: value.translation,
            rotation: value.rotation,
            ..Default::default()
        }
    }
}
Source

fn replicate_once_as<C, T>(&mut self) -> &mut Self
where C: Component<Mutability: MutWrite<C>> + Clone + Into<T> + From<T>, T: Serialize + DeserializeOwned,

Source

fn replicate_resource<R>(&mut self) -> &mut Self
where R: Resource<Mutability: MutWrite<R>> + Serialize + DeserializeOwned,

Like Self::replicate, but also registers Replicated as a required component for R.

This is just a convenience helper for:

app.replicate::<MyResource>()
    .register_required_components::<MyResource, Replicated>();

This allows the resource to be replicated automatically when it’s inserted via Commands::insert_resource or App::insert_resource.

To replicate the resource conditionally, use Self::replicate and initialize the resource via Commands::spawn with Replicated, or insert the component dynamically by querying the resource entity.

Note: To initialize a resource ahead of the server, use Signature to map the local resource entity to the corresponding server entity. Otherwise, when the server later replicates that resource, Bevy will reject spawning the entity because the resource already exists in the world. Resources are not applied via World::insert_resource because the server may replicate additional components attached to the resource entity, or replicate an entity with multiple resources on it. This is why resources are replicated as components.

Source

fn replicate_resource_diff<R>(&mut self) -> &mut Self
where R: Resource<Mutability: MutWrite<R>> + Diffable,

Like Self::replicate_resource, but sends recorded diffs instead of re-sending the entire resource when it changes.

Mutations should be performed through CommandsDiffExt::apply_resource_diff or WorldDiffExt::apply_resource_diff.

See Diffable for more details.

Source

fn replicate_resource_once<R>(&mut self) -> &mut Self
where R: Resource<Mutability: MutWrite<R>> + Serialize + DeserializeOwned,

Source

fn replicate_resource_as<R, T>(&mut self) -> &mut Self
where R: Resource<Mutability: MutWrite<R>> + Clone + Into<T> + From<T>, T: Serialize + DeserializeOwned,

Like Self::replicate_resource, but converts the resource into T before serialization and back into C after deserialization.

For more details see Self::replicate_as.

Source

fn replicate_resource_once_as<R, T>(&mut self) -> &mut Self
where R: Resource<Mutability: MutWrite<R>> + Clone + Into<T> + From<T>, T: Serialize + DeserializeOwned,

Source

fn replicate_filtered<C, F: FilterRules>(&mut self) -> &mut Self
where C: Component<Mutability: MutWrite<C>> + Serialize + DeserializeOwned,

Like Self::replicate, but lets you specify archetype filters an entity must match to replicate.

Supports With, Without, Or, and tuples of them, similar to the second generic parameter of Query.

§Examples
app.replicate_filtered::<Transform, With<Player>>() // Replicate `Transform` only for players.
    .replicate_filtered::<Health, Or<(With<Player>, With<Enemy>)>>() // Replicate `Health` only for player and enemies.
    .replicate_filtered::<Platform, (With<Active>, Without<Moving>)>(); // Replicate only active and non-moving platforms.
Source

fn replicate_once_filtered<C, F: FilterRules>(&mut self) -> &mut Self
where C: Component<Mutability: MutWrite<C>> + Serialize + DeserializeOwned,

Source

fn replicate_filtered_as<C, T, F: FilterRules>(&mut self) -> &mut Self
where C: Component<Mutability: MutWrite<C>> + Clone + Into<T> + From<T>, T: Serialize + DeserializeOwned,

Like Self::replicate_as, but also adds filters like Self::replicate_filtered.

Source

fn replicate_once_filtered_as<C, T, F: FilterRules>(&mut self) -> &mut Self
where C: Component<Mutability: MutWrite<C>> + Clone + Into<T> + From<T>, T: Serialize + DeserializeOwned,

Source

fn replicate_with<R: IntoComponentRules>( &mut self, component_rules: R, ) -> &mut Self

Defines a customizable ReplicationRule.

Can be used to customize how a component is passed over the network, or for components that don’t implement Serialize or DeserializeOwned.

You can also pass a tuple of RuleFns to define a rule for multiple components. These components will only be replicated if all of them are present on the entity. To assign a ReplicationMode to a component, wrap its RuleFns in a tuple with the desired rate.

If an entity matches multiple rules, the functions from the rule with higher priority will take precedence for overlapping components. For example, a rule for Health and a Player marker will take precedence over a rule for Health alone. This can be used to specialize serialization for a specific set of components.

If you remove a single component from such a rule from an entity, only one removal will be sent to clients. The other components in the rule will remain present on both the server and the clients. Replication for them will be stopped, unless they match another rule.

If your component contains an Entity inside, don’t forget to call Component::map_entities in your deserialization function.

You can also override how the component will be written, see AppMarkerExt.

See also postcard_utils for serialization helpers.

§Examples

Skip scale serialization.

Unlike with the example from Self::replicate_as, this will preserve the original scale value on deserialiation.

use bevy::prelude::*;
use bevy_replicon::{
    bytes::Bytes,
    prelude::*,
    shared::replication::registry::{ctx::WriteCtx, rule_fns::DeserializeFn},
};
use serde::{Deserialize, Serialize};

app.replicate_with(
    RuleFns::<Transform>::new_as::<TransformWithoutScale>()
        .with_in_place(deserialize_in_place_without_scale),
);

#[derive(Serialize, Deserialize, Clone, Copy)]
struct TransformWithoutScale {
    translation: Vec3,
    rotation: Quat,
}

impl From<Transform> for TransformWithoutScale {
    fn from(value: Transform) -> Self {
        Self {
            translation: value.translation,
            rotation: value.rotation,
        }
    }
}

impl From<TransformWithoutScale> for Transform {
    fn from(value: TransformWithoutScale) -> Self {
        Self {
            translation: value.translation,
            rotation: value.rotation,
            ..Default::default()
        }
    }
}

/// Applies the assigned deserialization function and assigns only translation and rotation.
///
/// Called by Replicon on component mutations.
fn deserialize_in_place_without_scale(
    deserialize: DeserializeFn<Transform>,
    ctx: &mut WriteCtx,
    component: &mut Transform,
    message: &mut Bytes,
) -> Result<()> {
    let transform = (deserialize)(ctx, message)?;
    component.translation = transform.translation;
    component.rotation = transform.rotation;
    Ok(())
}

A rule with multiple components:

use bevy::prelude::*;
use bevy_replicon::prelude::*;
use serde::{Deserialize, Serialize};

app.replicate_with((
    // You can also use `replicate_bundle` if you don't want
    // to tweak functions or send rate.
    RuleFns::<Player>::default(),
    RuleFns::<Position>::default(),
))
.replicate_with((
    RuleFns::<MovingPlatform>::default(),
    // Send position only once.
    (RuleFns::<Position>::default(), ReplicationMode::Once),
));

#[derive(Component, Deserialize, Serialize)]
struct Player;

#[derive(Component, Deserialize, Serialize)]
struct MovingPlatform;

#[derive(Component, Deserialize, Serialize)]
struct Position(Vec2);

Ser/de with compression:

use bevy::prelude::*;
use bevy_replicon::{
    bytes::Bytes,
    postcard_utils,
    shared::replication::registry::{
        ctx::{SerializeCtx, WriteCtx},
        rule_fns::RuleFns,
    },
    postcard,
    prelude::*,
};
use bytes::Buf;
use serde::{Deserialize, Serialize};

app.replicate_with(RuleFns::new(
    serialize_big_component,
    deserialize_big_component,
));

fn serialize_big_component(
    _ctx: &mut SerializeCtx,
    component: &BigComponent,
    message: &mut Vec<u8>,
) -> Result<()> {
    // Serialize as usual, but track size.
    let start = message.len();
    postcard_utils::to_extend_mut(component, message)?;
    let end = message.len();

    // Compress serialized slice.
    // Could be zstd, for example.
    let compressed = compress(&mut message[start..end]);

    // Replace serialized slice with compressed data prepended by its size.
    message.truncate(start);
    postcard_utils::to_extend_mut(&compressed.len(), message)?;
    message.extend(compressed);

    Ok(())
}

fn deserialize_big_component(
    _ctx: &mut WriteCtx,
    message: &mut Bytes,
) -> Result<BigComponent> {
    // Read size to know how much data is encoded.
    let size = postcard_utils::from_buf(message)?;

    // Apply decompression and advance the reading cursor.
    let decompressed = decompress(&message[..size]);
    message.advance(size);

    let component = postcard::from_bytes(&decompressed)?;
    Ok(component)
}

#[derive(Component, Deserialize, Serialize)]
struct BigComponent(Vec<u64>);

Custom ser/de with entity mapping:

use bevy::prelude::*;
use bevy_replicon::{
    bytes::Bytes,
    postcard_utils,
    shared::replication::registry::{
        ctx::{SerializeCtx, WriteCtx},
        rule_fns::RuleFns,
    },
    postcard,
    prelude::*,
};
use serde::{Deserialize, Serialize};

app.replicate_with(RuleFns::new(
    serialize_mapped_component,
    deserialize_mapped_component,
));

/// Serializes [`MappedComponent`], but skips [`MappedComponent::unused_field`].
fn serialize_mapped_component(
    _ctx: &mut SerializeCtx,
    component: &MappedComponent,
    message: &mut Vec<u8>,
) -> Result<()> {
    postcard_utils::to_extend_mut(&component.entity, message)?;
    Ok(())
}

/// Deserializes an entity and creates [`MappedComponent`] from it.
fn deserialize_mapped_component(
    ctx: &mut WriteCtx,
    message: &mut Bytes,
) -> Result<MappedComponent> {
    let entity = postcard_utils::from_buf(message)?;
    let mut component = MappedComponent {
        entity,
        unused_field: Default::default(),
    };
    MappedComponent::map_entities(&mut component, ctx); // Important to call!
    Ok(component)
}

#[derive(Component, Deserialize, Serialize)]
struct MappedComponent {
    #[entities]
    entity: Entity,
    unused_field: Vec<bool>,
}

Component with Box<dyn PartialReflect>:

use bevy::{
    prelude::*,
    reflect::serde::{ReflectDeserializer, ReflectSerializer},
};
use bevy_replicon::{
    bytes::Bytes,
    postcard_utils::{BufFlavor, ExtendMutFlavor},
    shared::replication::registry::{
        ctx::{SerializeCtx, WriteCtx},
        rule_fns::RuleFns,
    },
    postcard,
    prelude::*,
};
use serde::{de::DeserializeSeed, Serialize};

app.replicate_with(RuleFns::new(serialize_reflect, deserialize_reflect));

fn serialize_reflect(
    ctx: &mut SerializeCtx,
    component: &ReflectedComponent,
    message: &mut Vec<u8>,
) -> Result<()> {
    let mut serializer = postcard::Serializer {
        output: ExtendMutFlavor::new(message),
    };
    let registry = ctx.type_registry.read();
    ReflectSerializer::new(&*component.0, &registry).serialize(&mut serializer)?;
    Ok(())
}

fn deserialize_reflect(
    ctx: &mut WriteCtx,
    message: &mut Bytes,
) -> Result<ReflectedComponent> {
    let mut deserializer = postcard::Deserializer::from_flavor(BufFlavor::new(message));
    let registry = ctx.type_registry.read();
    let reflect = ReflectDeserializer::new(&registry).deserialize(&mut deserializer)?;
    Ok(ReflectedComponent(reflect))
}

#[derive(Component)]
struct ReflectedComponent(Box<dyn PartialReflect>);

Component with regular fields and Box<dyn PartialReflect>. Requires writing manual serde implementations. See serde book for more details.

use std::{
    any,
    fmt::{self, Formatter},
};

use bevy::{
    prelude::*,
    reflect::{
        TypeRegistry,
        serde::{ReflectDeserializer, ReflectSerializer},
    },
};
use bevy_replicon::{
    bytes::Bytes,
    postcard,
    postcard_utils::{BufFlavor, ExtendMutFlavor},
    prelude::*,
    shared::replication::registry::{
        ctx::{SerializeCtx, WriteCtx},
        rule_fns::RuleFns,
    },
};
use serde::{
    Deserialize, Serialize,
    de::{self, DeserializeSeed, MapAccess, Visitor},
    ser::SerializeStruct,
};

app.replicate_with(RuleFns::new(serialize_reflect, deserialize_reflect));

fn serialize_reflect(
    ctx: &mut SerializeCtx,
    component: &WithReflectComponent,
    message: &mut Vec<u8>,
) -> Result<()> {
    let mut serializer = postcard::Serializer {
        output: ExtendMutFlavor::new(message),
    };
    let reflect_serializer = WithReflectSerializer {
        component,
        registry: &ctx.type_registry.read(),
    };
    reflect_serializer.serialize(&mut serializer)?;
    Ok(())
}

fn deserialize_reflect(
    ctx: &mut WriteCtx,
    message: &mut Bytes,
) -> Result<WithReflectComponent> {
    let mut deserializer = postcard::Deserializer::from_flavor(BufFlavor::new(message));
    let reflect_deserializer = WithReflectDeserializer {
        registry: &ctx.type_registry.read(),
    };
    let component = reflect_deserializer.deserialize(&mut deserializer)?;
    Ok(component)
}

#[derive(Component)]
struct WithReflectComponent {
    regular: String,
    reflect: Box<dyn PartialReflect>,
}
#[derive(Deserialize)]
#[serde(field_identifier, rename_all = "lowercase")]
enum WithReflectField {
    Regular,
    Reflect,
}

struct WithReflectSerializer<'a> {
    component: &'a WithReflectComponent,
    registry: &'a TypeRegistry,
}

impl serde::Serialize for WithReflectSerializer<'_> {
    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut state =
            serializer.serialize_struct(any::type_name::<WithReflectComponent>(), 3)?;
        state.serialize_field("regular", &self.component.regular)?;
        state.serialize_field(
            "reflect",
            &ReflectSerializer::new(&*self.component.reflect, self.registry),
        )?;

        state.end()
    }
}

struct WithReflectDeserializer<'a> {
    registry: &'a TypeRegistry,
}

impl<'de> DeserializeSeed<'de> for WithReflectDeserializer<'_> {
    type Value = WithReflectComponent;

    fn deserialize<D: serde::Deserializer<'de>>(
        self,
        deserializer: D,
    ) -> Result<Self::Value, D::Error> {
        deserializer.deserialize_struct(
            any::type_name::<WithReflectComponent>(),
            &["regular", "reflect"],
            self,
        )
    }
}

impl<'de> Visitor<'de> for WithReflectDeserializer<'_> {
    type Value = WithReflectComponent;

    fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
        formatter.write_str(any::type_name::<Self::Value>())
    }

    fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
        let mut regular = None;
        let mut reflect = None;
        while let Some(key) = map.next_key()? {
            match key {
                WithReflectField::Regular => {
                    if regular.is_some() {
                        return Err(de::Error::duplicate_field("regular"));
                    }
                    regular = Some(map.next_value()?);
                }
                WithReflectField::Reflect => {
                    if reflect.is_some() {
                        return Err(de::Error::duplicate_field("reflect"));
                    }
                    reflect =
                        Some(map.next_value_seed(ReflectDeserializer::new(self.registry))?);
                }
            }
        }
        let regular = regular.ok_or_else(|| de::Error::missing_field("regular"))?;
        let reflect = reflect.ok_or_else(|| de::Error::missing_field("reflect"))?;
        Ok(WithReflectComponent { regular, reflect })
    }
}
Source

fn replicate_with_filtered<R: IntoComponentRules, F: FilterRules>( &mut self, component_rules: R, ) -> &mut Self

Like Self::replicate_filtered, but for Self::replicate_with.

It’s recommended to omit the first parameter and let the compiler infer it from the arguments.

§Examples
app.replicate_with_filtered::<_, With<StaticBox>>((
    RuleFns::<Health>::default(),
    (RuleFns::<Transform>::default(), ReplicationMode::Once),
));
Source

fn replicate_with_priority<R: IntoComponentRules>( &mut self, priority: usize, component_rules: R, ) -> &mut Self

Same as Self::replicate_with, but uses the specified priority instead of the default one.

The default priority equals the total number of components in the rule

Source

fn replicate_bundle<B: BundleRules>(&mut self) -> &mut Self

Defines a ReplicationRule for a bundle.

Implemented for tuples of components. Use it to conveniently create a rule with default ser/de functions and ReplicationMode::OnChange for all components. To customize this, use Self::replicate_with.

Can also be implemented manually for user-defined bundles.

§Examples
use bevy::prelude::*;
use bevy_replicon::{
    bytes::Bytes,
    shared::replication::{
        registry::{
            ctx::{SerializeCtx, WriteCtx},
            ReplicationRegistry,
        },
        rules::component::{BundleRules, ComponentRule},
    },
    prelude::*,
};
use serde::{Deserialize, Serialize};

app.replicate_bundle::<(Name, City)>() // Tuple of components is also a bundle!
    .replicate_bundle::<PlayerBundle>();

#[derive(Component, Deserialize, Serialize)]
struct City;

#[derive(Bundle)]
struct PlayerBundle {
    transform: Transform,
    player: Player,
}

#[derive(Component, Deserialize, Serialize)]
struct Player;

impl BundleRules for PlayerBundle {
    const DEFAULT_PRIORITY: usize = 2; // Usually equals to the number of components, but can be customized.

    fn component_rules(world: &mut World, registry: &mut ReplicationRegistry) -> Vec<ComponentRule> {
        // Customize serlialization to serialize only `translation`.
        let (transform_id, transform_fns_id) = registry.register_rule_fns(
            world,
            RuleFns::new(serialize_translation, deserialize_translation),
        );
        let transform = ComponentRule::new(transform_id, transform_fns_id);

        // Serialize `player` as usual.
        let (player_id, player_fns_id) = registry.register_rule_fns(world, RuleFns::<Player>::default());
        let player = ComponentRule::new(player_id, player_fns_id);

        vec![transform, player]
    }
}
Source

fn replicate_bundle_filtered<B: BundleRules, F: FilterRules>( &mut self, ) -> &mut Self

Source

fn replicate_bundle_with<B: BundleRules>( &mut self, priority: usize, ) -> &mut Self

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementations on Foreign Types§

Source§

impl AppRuleExt for App

Source§

fn replicate_resource_with<R: Resource<Mutability: MutWrite<R>>>( &mut self, resource_rule: impl IntoResourceRule<R>, ) -> &mut Self

Source§

fn replicate_with_priority_filtered<R: IntoComponentRules, F: FilterRules>( &mut self, priority: usize, component_rules: R, ) -> &mut Self

Source§

fn replicate_bundle_with_filtered<B: BundleRules, F: FilterRules>( &mut self, priority: usize, ) -> &mut Self

Implementors§