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
use crate::sync::{self, NetSync};
use common::comp;
use serde::{Deserialize, Serialize};
use std::marker::PhantomData;
/// This macro defines [`EcsCompPacke`]
///
/// It is meant to be passed to the `synced_components!` macro which will call
/// it with a list of components.
macro_rules! comp_packet {
($($component_name:ident: $component_type:ident,)*) => {
// `sum_type!` will automatically derive From<T> for EcsCompPacket
// for each variant EcsCompPacket::T(T).
sum_type::sum_type! {
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum EcsCompPacket {
// Note: also use the component_type identifier
// to name the enum variant that contains the component.
$($component_type($component_type),)*
// These aren't included in the "synced_components" because the way
// we determine if they are changed and when to send them is different
// from the other components.
Pos(comp::Pos),
Vel(comp::Vel),
Ori(comp::Ori),
}
}
// `sum_type!` will automatically derive From<PhantomData<T>> for EcsCompPhantom
// for each variant EcsCompPhantom::T(PhantomData<T>).
sum_type::sum_type! {
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum EcsCompPhantom {
$($component_type(PhantomData<$component_type>),)*
Pos(PhantomData<comp::Pos>),
Vel(PhantomData<comp::Vel>),
Ori(PhantomData<comp::Ori>),
}
}
impl sync::CompPacket for EcsCompPacket {
type Phantom = EcsCompPhantom;
fn apply_insert(self, entity: specs::Entity, world: &specs::World, force_update: bool) {
match self {
$(Self::$component_type(mut comp) => {
comp.pre_insert(world);
sync::handle_insert(comp, entity, world);
},)*
Self::Pos(comp) => {
sync::handle_interp_insert(comp, entity, world, force_update)
},
Self::Vel(comp) => {
sync::handle_interp_insert(comp, entity, world, force_update)
},
Self::Ori(comp) => {
sync::handle_interp_insert(comp, entity, world, force_update)
},
}
}
fn apply_modify(self, entity: specs::Entity, world: &specs::World, force_update: bool) {
match self {
$(Self::$component_type(mut comp) => {
comp.pre_modify(world);
sync::handle_modify(comp, entity, world);
},)*
Self::Pos(comp) => {
sync::handle_interp_modify(comp, entity, world, force_update)
},
Self::Vel(comp) => {
sync::handle_interp_modify(comp, entity, world, force_update)
},
Self::Ori(comp) => {
sync::handle_interp_modify(comp, entity, world, force_update)
},
}
}
fn apply_remove(phantom: Self::Phantom, entity: specs::Entity, world: &specs::World) {
match phantom {
$(EcsCompPhantom::$component_type(_) => {
sync::handle_remove::<$component_type>(entity, world);
},)*
EcsCompPhantom::Pos(_) => {
sync::handle_interp_remove::<comp::Pos>(entity, world)
},
EcsCompPhantom::Vel(_) => {
sync::handle_interp_remove::<comp::Vel>(entity, world)
},
EcsCompPhantom::Ori(_) => {
sync::handle_interp_remove::<comp::Ori>(entity, world)
},
}
}
}
}
}
// Import all the component types so they will be available when expanding the
// macro below.
use crate::synced_components::*;
// Pass `comp_packet!` macro to this "x macro" which will invoke it with a list
// of components. This will declare the types defined in the macro above.
crate::synced_components!(comp_packet);