veloren_common_net/
synced_components.rs

1//! Contains an "x macro" for all synced components as well as [NetSync]
2//! implementations for those components.
3//!
4//!
5//! An x macro accepts another macro as input and calls it with a list of
6//! inputs. This allows adding components to the list in the x macro declaration
7//! and then writing macros that will accept this list and generate code that
8//! handles every synced component without further repitition of the component
9//! set.
10//!
11//! This module also re-exports all the component types that are synced.
12//!
13//! A glob import from this can be used so that the component types are in scope
14//! when using the x macro defined here which requires this.
15
16/// This provides a lowercase name and the component type.
17///
18/// See [module](self) level docs for more details.
19#[macro_export]
20macro_rules! synced_components {
21    ($macro:ident) => {
22        $macro! {
23            body: Body,
24            hardcore: Hardcore,
25            stats: Stats,
26            buffs: Buffs,
27            auras: Auras,
28            energy: Energy,
29            health: Health,
30            heads: Heads,
31            poise: Poise,
32            light_emitter: LightEmitter,
33            loot_owner: LootOwner,
34            item: PickupItem,
35            thrown_item: ThrownItem,
36            scale: Scale,
37            group: Group,
38            is_mount: IsMount,
39            is_rider: IsRider,
40            is_volume_rider: IsVolumeRider,
41            volume_riders: VolumeRiders,
42            is_leader: IsLeader,
43            is_follower: IsFollower,
44            mass: Mass,
45            density: Density,
46            collider: Collider,
47            sticky: Sticky,
48            immovable: Immovable,
49            character_state: CharacterState,
50            character_activity: CharacterActivity,
51            shockwave: Shockwave,
52            beam: Beam,
53            alignment: Alignment,
54            stance: Stance,
55            object: Object,
56            // TODO: change this to `SyncFrom::ClientEntity` and sync the bare minimum
57            // from other entities (e.g. just keys needed to show appearance
58            // based on their loadout). Also, it looks like this actually has
59            // an alternative sync method implemented in entity_sync via
60            // ServerGeneral::InventoryUpdate so we could use that instead
61            // or remove the part where it clones the inventory.
62            inventory: Inventory,
63            // TODO: this is used in combat rating calculation in voxygen but we can probably
64            // remove it from that and then see if it's used for anything else and try to move
65            // to only being synced for the client's entity.
66            skill_set: SkillSet,
67
68            // Synced to the client only for its own entity
69
70            admin: Admin,
71            combo: Combo,
72            active_abilities: ActiveAbilities,
73            can_build: CanBuild,
74            is_interactor: IsInteractor,
75            interactors: Interactors,
76        }
77    };
78}
79
80macro_rules! reexport_comps {
81    ($($name:ident: $type:ident,)*) => {
82        mod inner {
83            pub use common::comp::*;
84            pub use body::parts::Heads;
85            pub use common::{interaction::Interactors, mounting::VolumeRiders};
86            use common::link::Is;
87            use common::{
88                mounting::{Mount, Rider, VolumeRider},
89                tether::{Leader, Follower},
90                interaction::{Interactor},
91            };
92
93            // We alias these because the identifier used for the
94            // component's type is reused as an enum variant name
95            // in the macro's that we pass to `synced_components!`.
96            //
97            // This is also the reason we need this inner module, since
98            // we can't just re-export all the types directly from `common::comp`.
99            pub type IsMount = Is<Mount>;
100            pub type IsRider = Is<Rider>;
101            pub type IsVolumeRider = Is<VolumeRider>;
102            pub type IsLeader = Is<Leader>;
103            pub type IsFollower = Is<Follower>;
104            pub type IsInteractor = Is<Interactor>;
105        }
106
107        // Re-export all the component types. So that uses of `synced_components!` outside this
108        // module can bring them into scope with a single glob import.
109        $(pub use inner::$type;)*
110    }
111}
112// Pass `reexport_comps` macro to the "x macro" which will invoke it with a list
113// of components.
114//
115// Note: this brings all these components into scope for the implementations
116// below.
117synced_components!(reexport_comps);
118
119// ===============================
120// === NetSync implementations ===
121// ===============================
122
123use crate::sync::{NetSync, SyncFrom};
124
125impl NetSync for Body {
126    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
127}
128
129impl NetSync for Hardcore {
130    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
131}
132
133impl NetSync for Stats {
134    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
135}
136
137impl NetSync for Buffs {
138    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
139}
140
141impl NetSync for Auras {
142    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
143}
144
145impl NetSync for Energy {
146    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
147}
148
149impl NetSync for Health {
150    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
151
152    fn pre_insert(&mut self, world: &specs::World) {
153        use common::resources::Time;
154        use specs::WorldExt;
155
156        // Time isn't synced between client and server so replace the Time from the
157        // server with the Client's local Time to enable accurate comparison.
158        self.last_change.time = *world.read_resource::<Time>();
159    }
160
161    fn pre_modify(&mut self, world: &specs::World) {
162        use common::resources::Time;
163        use specs::WorldExt;
164
165        // Time isn't synced between client and server so replace the Time from the
166        // server with the Client's local Time to enable accurate comparison.
167        self.last_change.time = *world.read_resource::<Time>();
168    }
169}
170
171impl NetSync for Heads {
172    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
173}
174
175impl NetSync for Poise {
176    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
177}
178
179impl NetSync for LightEmitter {
180    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
181}
182
183impl NetSync for LootOwner {
184    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
185}
186
187impl NetSync for PickupItem {
188    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
189}
190
191impl NetSync for ThrownItem {
192    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
193}
194
195impl NetSync for Scale {
196    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
197}
198
199impl NetSync for Group {
200    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
201}
202
203impl NetSync for IsMount {
204    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
205}
206
207impl NetSync for IsRider {
208    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
209}
210
211impl NetSync for IsVolumeRider {
212    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
213}
214
215impl NetSync for VolumeRiders {
216    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
217}
218
219impl NetSync for IsLeader {
220    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
221}
222
223impl NetSync for IsFollower {
224    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
225}
226
227impl NetSync for Mass {
228    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
229}
230
231impl NetSync for Density {
232    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
233}
234
235impl NetSync for Collider {
236    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
237}
238
239impl NetSync for Sticky {
240    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
241}
242
243impl NetSync for Immovable {
244    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
245}
246
247impl NetSync for CharacterState {
248    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
249}
250
251impl NetSync for CharacterActivity {
252    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
253}
254
255impl NetSync for Shockwave {
256    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
257}
258
259impl NetSync for Beam {
260    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
261}
262
263impl NetSync for Alignment {
264    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
265}
266
267impl NetSync for Inventory {
268    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
269}
270
271impl NetSync for SkillSet {
272    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
273}
274
275impl NetSync for Stance {
276    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
277}
278
279impl NetSync for Object {
280    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
281}
282
283// These are synced only from the client's own entity.
284
285impl NetSync for Admin {
286    const SYNC_FROM: SyncFrom = SyncFrom::ClientEntity;
287}
288
289impl NetSync for Combo {
290    const SYNC_FROM: SyncFrom = SyncFrom::ClientEntity;
291}
292
293impl NetSync for ActiveAbilities {
294    const SYNC_FROM: SyncFrom = SyncFrom::ClientEntity;
295}
296
297impl NetSync for CanBuild {
298    const SYNC_FROM: SyncFrom = SyncFrom::ClientEntity;
299}
300
301impl NetSync for IsInteractor {
302    const SYNC_FROM: SyncFrom = SyncFrom::ClientEntity;
303}
304
305impl NetSync for Interactors {
306    const SYNC_FROM: SyncFrom = SyncFrom::ClientEntity;
307}