veloren_common_net/msg/
ecs_packet.rs

1use crate::sync::{self, NetSync};
2use common::comp;
3use serde::{Deserialize, Serialize};
4use std::marker::PhantomData;
5
6/// This macro defines [`EcsCompPacke`]
7///
8/// It is meant to be passed to the `synced_components!` macro which will call
9/// it with a list of components.
10macro_rules! comp_packet {
11    ($($component_name:ident: $component_type:ident,)*) => {
12
13        // `sum_type!` will automatically derive From<T> for EcsCompPacket
14        // for each variant EcsCompPacket::T(T).
15        sum_type::sum_type! {
16            #[derive(Clone, Debug, Serialize, Deserialize)]
17            pub enum EcsCompPacket {
18                // Note: also use the component_type identifier
19                // to name the enum variant that contains the component.
20                $($component_type($component_type),)*
21                // These aren't included in the "synced_components" because the way
22                // we determine if they are changed and when to send them is different
23                // from the other components.
24                Pos(comp::Pos),
25                Vel(comp::Vel),
26                Ori(comp::Ori),
27            }
28        }
29
30        // `sum_type!` will automatically derive From<PhantomData<T>> for EcsCompPhantom
31        // for each variant EcsCompPhantom::T(PhantomData<T>).
32        sum_type::sum_type! {
33            #[derive(Clone, Debug, Serialize, Deserialize)]
34            pub enum EcsCompPhantom {
35                $($component_type(PhantomData<$component_type>),)*
36                Pos(PhantomData<comp::Pos>),
37                Vel(PhantomData<comp::Vel>),
38                Ori(PhantomData<comp::Ori>),
39            }
40        }
41
42        impl sync::CompPacket for EcsCompPacket {
43            type Phantom = EcsCompPhantom;
44
45            fn apply_insert(self, entity: specs::Entity, world: &specs::World, force_update: bool) {
46                match self {
47                    $(Self::$component_type(mut comp) => {
48                        comp.pre_insert(world);
49                        sync::handle_insert(comp, entity, world);
50                    },)*
51                    Self::Pos(comp) => {
52                        sync::handle_interp_insert(comp, entity, world, force_update)
53                    },
54                    Self::Vel(comp) => {
55                        sync::handle_interp_insert(comp, entity, world, force_update)
56                    },
57                    Self::Ori(comp) => {
58                        sync::handle_interp_insert(comp, entity, world, force_update)
59                    },
60                }
61            }
62
63            fn apply_modify(self, entity: specs::Entity, world: &specs::World, force_update: bool) {
64                match self {
65                    $(Self::$component_type(mut comp) => {
66                        comp.pre_modify(world);
67                        sync::handle_modify(comp, entity, world);
68                    },)*
69                    Self::Pos(comp) => {
70                        sync::handle_interp_modify(comp, entity, world, force_update)
71                    },
72                    Self::Vel(comp) => {
73                        sync::handle_interp_modify(comp, entity, world, force_update)
74                    },
75                    Self::Ori(comp) => {
76                        sync::handle_interp_modify(comp, entity, world, force_update)
77                    },
78                }
79            }
80
81            fn apply_remove(phantom: Self::Phantom, entity: specs::Entity, world: &specs::World) {
82                match phantom {
83                    $(EcsCompPhantom::$component_type(_) => {
84                        sync::handle_remove::<$component_type>(entity, world);
85                    },)*
86                    EcsCompPhantom::Pos(_) => {
87                        sync::handle_interp_remove::<comp::Pos>(entity, world)
88                    },
89                    EcsCompPhantom::Vel(_) => {
90                        sync::handle_interp_remove::<comp::Vel>(entity, world)
91                    },
92                    EcsCompPhantom::Ori(_) => {
93                        sync::handle_interp_remove::<comp::Ori>(entity, world)
94                    },
95                }
96            }
97        }
98    }
99}
100
101// Import all the component types so they will be available when expanding the
102// macro below.
103use crate::synced_components::*;
104// Pass `comp_packet!` macro to this "x macro" which will invoke it with a list
105// of components. This will declare the types defined in the macro above.
106crate::synced_components!(comp_packet);