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