Crate bevy_bundlication

Source
Expand description

§bevy_bundlication

Network replication for bevy based on a bundle pattern. Replication group rules for bevy_replicon using a bundle-like API.

§Goals

  • Simplify the definition of replication groups
  • Simplify bandwidth optimization

§Getting started

bevy_bundlication works with a pattern similar to a Bundle from bevy. Anything matching the bundle gets networked. Each field needs to implement NetworkedComponent, this can be done manually or trough a blanket impl on types that have Component, Serialze and Deserialize. For types where the blanket impl causes conflicts, the #[bundlication(as = Wrapper)] attribute can be used where Wrapper is a type that impletements NetworkedWrapper<YourType>.

Bundles can be registered to bevy_replicon using replicate_bundle::<Bundle>().

use bevy::prelude::*;
use bevy_replicon::prelude::*;

#[derive(NetworkedBundle)]
pub struct PlayerPositionBundle {
    // The content of this field doesn't get sent, and it will be received as the default value,
    // it therefor requires neither Serialize/Deserialize nor NetworkedComponent
    #[bundlication(no_send, rate=Once)]
    pub player: Player,
    // This component is sent and spawned as is
    pub speed: Speed,
    // We replicate Transform, but it is serialized/deserialized using the logic of JustTranslation
    #[bundlication(as = JustTranslation)]
    pub translation: Transform,
    // If we also use this as a bundle and have fields we don't want replicon to consider, we can
    // add the skip attribute
    #[bundlication(skip)]
    pub skipped: GlobalTransform,
}

pub struct MovementPlugin;

impl Plugin for MovementPlugin {
    fn build(&self, app: &mut App) {
        // To replicate the bundle, we register our bundle to bevy_replicon
        app.replicate_bundle::<PlayerPositionBundle>();
    }
}

use bevy_bundlication::prelude::*;
use serde::{Serialize, Deserialize};

// We need Default on Player because we use the no_send attribute
#[derive(Component, Default)]
pub struct Player(u128);

// Speed derives all required traits for the NetworkedBundle blanket impl
#[derive(Component, Serialize, Deserialize)]
pub struct Speed(f32);

// We define a type to network a type we don't own in a different way than its default behavior.
// This can also be used to network components without Serialize/Deserialize
// In this case we only network the translation part of Transform
#[derive(Serialize, Deserialize)]
pub struct JustTranslation(Vec3);

impl NetworkedWrapper<Transform> for JustTranslation {
    fn write_data(from: &Transform, w: impl std::io::Write, _: &SerializeCtx) -> Result<()> {
        serialize(w, &from.translation)?;
        Ok(())
    }

    fn read_new(r: impl std::io::Read, _: &mut DeserializeCtx) -> Result<Transform> {
        let translation: Vec3 = deserialize(r)?;
        Ok(Transform::from_translation(translation))
    }
}

§License

All code in this repository is dual-licensed under either:

at your option.

Modules§

macro_export
A module with exports used by the macro
prelude
The prelude of the crate, contains everything necessary to get started with this crate

Traits§

NetworkedComponent
A trait needed to network components, provided by a blanket impl if the component has Serialize+Deserialize
NetworkedWrapper
A trait that allows wrapping a component as another type for bevy_bundlication. Useful when working with components from bevy itself or 3rd party plugins

Functions§

deserialize
Deserialize an instance of the specified type from the provided reader
serialize
Serialize the provided value into the writer

Type Aliases§

BevyResult
An alias for postcard’s Result type