Network replication for bevy based on a bundle pattern. Replication group rules for bevy_replicon using a bundle-like API.
- Simplify the definition of replication groups
- Simplify bandwidth optimization
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_group::<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)]
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_group::<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) -> BincodeResult<()> {
serialize(w, &from.translation)?;
Ok(())
}
fn read_new(r: impl std::io::Read, _: &mut DeserializeCtx) -> BincodeResult<Transform> {
let translation: Vec3 = deserialize(r)?;
Ok(Transform::from_translation(translation))
}
}
All code in this repository is dual-licensed under either:
- MIT License (LICENSE-MIT or http://opensource.org/licenses/MIT)
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
at your option.