1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
use std::fmt::Debug;
use std::hash::Hash;
use bevy::prelude::{App, Component, EntityWorldMut, World};
use serde::de::DeserializeOwned;
use serde::Serialize;
use crate::connection::events::{
IterComponentInsertEvent, IterComponentRemoveEvent, IterComponentUpdateEvent,
};
use crate::prelude::MapEntities;
use crate::protocol::{BitSerializable, EventContext, Protocol};
use crate::shared::replication::components::ShouldBeInterpolated;
use crate::shared::replication::components::ShouldBePredicted;
use crate::shared::replication::ReplicationSend;
// client writes an Enum containing all their message type
// each message must derive message
// that big enum will implement MessageProtocol via a proc macro
// TODO: remove the extra Serialize + DeserializeOwned + Clone bounds
pub trait ComponentProtocol:
BitSerializable
+ Serialize
+ DeserializeOwned
+ MapEntities
+ ComponentBehaviour
+ Debug
+ Send
+ Sync
+ From<ShouldBePredicted>
+ From<ShouldBeInterpolated>
{
type Protocol: Protocol;
/// Add systems to send component inserts/removes/updates
fn add_per_component_replication_send_systems<R: ReplicationSend<Self::Protocol>>(
app: &mut App,
);
/// Adds Component-related events to the app
fn add_events<Ctx: EventContext>(app: &mut App);
// TODO: make this a system that runs after io-receive/recv/read
// maybe a standalone EventsPlugin
/// Takes messages that were written and writes MessageEvents
fn push_component_events<
E: IterComponentInsertEvent<Self::Protocol, Ctx>
+ IterComponentRemoveEvent<Self::Protocol, Ctx>
+ IterComponentUpdateEvent<Self::Protocol, Ctx>,
Ctx: EventContext,
>(
world: &mut World,
events: &mut E,
);
fn add_prediction_systems(app: &mut App);
fn add_interpolation_systems(app: &mut App);
}
// TODO: enum_delegate doesn't work with generics + cannot be used multiple times since it derives a bunch of Into/From traits
/// Trait to delegate a method from the ComponentProtocol enum to the inner Component type
#[enum_delegate::register]
pub trait ComponentBehaviour {
/// Apply a ComponentInsert to an entity
fn insert(self, entity: &mut EntityWorldMut);
/// Apply a ComponentUpdate to an entity
fn update(self, entity: &mut EntityWorldMut);
}
impl<T: Component> ComponentBehaviour for T {
// Apply a ComponentInsert to an entity
fn insert(self, entity: &mut EntityWorldMut) {
// only insert if the entity didn't have the component
// because otherwise the insert could override an component-update that was received later?
// but this could cause some issues if we wanted the component to be updated from the insert
// if entity.get::<T>().is_none() {
entity.insert(self);
// }
}
// Apply a ComponentUpdate to an entity
fn update(self, entity: &mut EntityWorldMut) {
if let Some(mut c) = entity.get_mut::<T>() {
*c = self;
}
// match entity.get_mut::<T>() {
// Some(mut c) => *c = self,
// None => {
// entity.insert(self);
// }
// }
}
}
pub trait ComponentProtocolKind:
BitSerializable
+ Serialize
+ DeserializeOwned
+ MapEntities
+ PartialEq
+ Eq
+ Hash
+ Debug
+ Send
+ Sync
+ for<'a> From<&'a <Self::Protocol as Protocol>::Components>
+ ComponentKindBehaviour
{
type Protocol: Protocol;
}
/// Trait to delegate a method from the ComponentProtocolKind enum to the inner Component type
pub trait ComponentKindBehaviour {
/// Remove the component for an entity
fn remove(self, entity: &mut EntityWorldMut);
}
/// Trait to convert a component type into the corresponding ComponentProtocolKind
pub trait IntoKind<K: ComponentProtocolKind> {
fn into_kind() -> K;
}