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            frontend_marker: FrontendMarker,
57            arcing: Arcing,
58            // TODO: change this to `SyncFrom::ClientEntity` and sync the bare minimum
59            // from other entities (e.g. just keys needed to show appearance
60            // based on their loadout). Also, it looks like this actually has
61            // an alternative sync method implemented in entity_sync via
62            // ServerGeneral::InventoryUpdate so we could use that instead
63            // or remove the part where it clones the inventory.
64            inventory: Inventory,
65            // TODO: this is used in combat rating calculation in voxygen but we can probably
66            // remove it from that and then see if it's used for anything else and try to move
67            // to only being synced like `ActiveAbilities`.
68            skill_set: SkillSet,
69
70            // Synced to the client only for its own entity
71
72            admin: Admin,
73            combo: Combo,
74            active_abilities: ActiveAbilities,
75            can_build: CanBuild,
76            is_interactor: IsInteractor,
77            interactors: Interactors,
78        }
79    };
80}
81
82macro_rules! reexport_comps {
83    ($($name:ident: $type:ident,)*) => {
84        mod inner {
85            pub use common::comp::*;
86            pub use body::parts::Heads;
87            pub use common::{interaction::Interactors, mounting::VolumeRiders};
88            use common::link::Is;
89            use common::{
90                mounting::{Mount, Rider, VolumeRider},
91                tether::{Leader, Follower},
92                interaction::{Interactor},
93            };
94
95            // We alias these because the identifier used for the
96            // component's type is reused as an enum variant name
97            // in the macro's that we pass to `synced_components!`.
98            //
99            // This is also the reason we need this inner module, since
100            // we can't just re-export all the types directly from `common::comp`.
101            pub type IsMount = Is<Mount>;
102            pub type IsRider = Is<Rider>;
103            pub type IsVolumeRider = Is<VolumeRider>;
104            pub type IsLeader = Is<Leader>;
105            pub type IsFollower = Is<Follower>;
106            pub type IsInteractor = Is<Interactor>;
107        }
108
109        // Re-export all the component types. So that uses of `synced_components!` outside this
110        // module can bring them into scope with a single glob import.
111        $(pub use inner::$type;)*
112    }
113}
114// Pass `reexport_comps` macro to the "x macro" which will invoke it with a list
115// of components.
116//
117// Note: this brings all these components into scope for the implementations
118// below.
119synced_components!(reexport_comps);
120
121// ===============================
122// === NetSync implementations ===
123// ===============================
124
125use crate::sync::{NetSync, SyncFrom};
126
127impl NetSync for Body {
128    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
129}
130
131impl NetSync for Hardcore {
132    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
133}
134
135impl NetSync for Stats {
136    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
137}
138
139impl NetSync for Buffs {
140    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
141}
142
143impl NetSync for Auras {
144    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
145}
146
147impl NetSync for Energy {
148    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
149}
150
151impl NetSync for Health {
152    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
153
154    fn pre_insert(&mut self, world: &specs::World) {
155        use common::resources::Time;
156        use specs::WorldExt;
157
158        // Time isn't synced between client and server so replace the Time from the
159        // server with the Client's local Time to enable accurate comparison.
160        self.last_change.time = *world.read_resource::<Time>();
161    }
162
163    fn pre_modify(&mut self, world: &specs::World) {
164        use common::resources::Time;
165        use specs::WorldExt;
166
167        // Time isn't synced between client and server so replace the Time from the
168        // server with the Client's local Time to enable accurate comparison.
169        self.last_change.time = *world.read_resource::<Time>();
170    }
171}
172
173impl NetSync for Heads {
174    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
175}
176
177impl NetSync for Poise {
178    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
179}
180
181impl NetSync for LightEmitter {
182    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
183}
184
185impl NetSync for LootOwner {
186    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
187}
188
189impl NetSync for PickupItem {
190    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
191}
192
193impl NetSync for ThrownItem {
194    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
195}
196
197impl NetSync for Scale {
198    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
199}
200
201impl NetSync for Group {
202    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
203}
204
205impl NetSync for IsMount {
206    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
207}
208
209impl NetSync for IsRider {
210    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
211}
212
213impl NetSync for IsVolumeRider {
214    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
215}
216
217impl NetSync for VolumeRiders {
218    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
219}
220
221impl NetSync for IsLeader {
222    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
223}
224
225impl NetSync for IsFollower {
226    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
227}
228
229impl NetSync for Mass {
230    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
231}
232
233impl NetSync for Density {
234    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
235}
236
237impl NetSync for Collider {
238    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
239}
240
241impl NetSync for Sticky {
242    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
243}
244
245impl NetSync for Immovable {
246    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
247}
248
249impl NetSync for CharacterState {
250    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
251}
252
253impl NetSync for CharacterActivity {
254    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
255}
256
257impl NetSync for Shockwave {
258    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
259}
260
261impl NetSync for Beam {
262    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
263}
264
265impl NetSync for Alignment {
266    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
267}
268
269impl NetSync for Inventory {
270    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
271}
272
273impl NetSync for SkillSet {
274    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
275}
276
277impl NetSync for Stance {
278    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
279}
280
281impl NetSync for Object {
282    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
283}
284
285impl NetSync for FrontendMarker {
286    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
287}
288
289impl NetSync for Arcing {
290    const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
291}
292
293// These are synced only from the client's own entity.
294
295impl NetSync for Admin {
296    const SYNC_FROM: SyncFrom = SyncFrom::ClientEntity;
297}
298
299impl NetSync for Combo {
300    const SYNC_FROM: SyncFrom = SyncFrom::ClientSpectatorEntity;
301}
302
303impl NetSync for ActiveAbilities {
304    const SYNC_FROM: SyncFrom = SyncFrom::ClientSpectatorEntity;
305}
306
307impl NetSync for CanBuild {
308    const SYNC_FROM: SyncFrom = SyncFrom::ClientEntity;
309}
310
311impl NetSync for IsInteractor {
312    const SYNC_FROM: SyncFrom = SyncFrom::ClientSpectatorEntity;
313}
314
315impl NetSync for Interactors {
316    const SYNC_FROM: SyncFrom = SyncFrom::ClientSpectatorEntity;
317}