Skip to content

Commit 54c4185

Browse files
ShaturUkoeHB
andauthored
Refactor entity serialization (#51)
* Refactor entity serialization Serializes entities in optimal way by writing its index and generation as separate u32 varints and entity generation if it is zero by prepending a bit flag to index. Also update related docs. Looks like in Rust documentation they don't link types that are already in signature and refer to variable names which is make sense. --------- Co-authored-by: koe <[email protected]>
1 parent a42e964 commit 54c4185

File tree

3 files changed

+52
-18
lines changed

3 files changed

+52
-18
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Changed
1111

12+
- Serialize entities in optimal way by writing its index and generation as separate varints.
1213
- Hide `ReplicationId`, `ReplicationInfo` and related methods from `ReplicationRules` from public API.
1314
- Rename `ReplicationRules::replication_id` into `ReplicationRules::replication_marker_id`.
1415
- Use serialization buffer cache per client for replication.

src/client.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ fn deserialize_tick(cursor: &mut Cursor<Bytes>, world: &mut World) -> Result<boo
122122
}
123123
}
124124

125-
/// Deserializes component [`DiffKind`] and applies them to the [`World`].
125+
/// Deserializes component diffs of `diff_kind` and applies them to the `world`.
126126
fn deserialize_component_diffs(
127127
cursor: &mut Cursor<Bytes>,
128128
world: &mut World,
@@ -132,7 +132,7 @@ fn deserialize_component_diffs(
132132
) -> Result<(), bincode::Error> {
133133
let entities_count: u16 = bincode::deserialize_from(&mut *cursor)?;
134134
for _ in 0..entities_count {
135-
let entity = DefaultOptions::new().deserialize_from(&mut *cursor)?;
135+
let entity = deserialize_entity(&mut *cursor)?;
136136
let mut entity = entity_map.get_by_server_or_spawn(world, entity);
137137
let components_count: u8 = bincode::deserialize_from(&mut *cursor)?;
138138
for _ in 0..components_count {
@@ -150,7 +150,7 @@ fn deserialize_component_diffs(
150150
Ok(())
151151
}
152152

153-
/// Deserializes despawns and applies them to the [`World`].
153+
/// Deserializes despawns and applies them to the `world`.
154154
fn deserialize_despawns(
155155
cursor: &mut Cursor<Bytes>,
156156
world: &mut World,
@@ -161,7 +161,7 @@ fn deserialize_despawns(
161161
// The entity might have already been deleted with the last diff,
162162
// but the server might not yet have received confirmation from the
163163
// client and could include the deletion in the latest diff.
164-
let server_entity = DefaultOptions::new().deserialize_from(&mut *cursor)?;
164+
let server_entity = deserialize_entity(&mut *cursor)?;
165165
if let Some(client_entity) = entity_map.remove_by_server(server_entity) {
166166
world.entity_mut(client_entity).despawn_recursive();
167167
}
@@ -170,6 +170,21 @@ fn deserialize_despawns(
170170
Ok(())
171171
}
172172

173+
/// Deserializes `entity` from compressed index and generation, for details see [`ReplicationBuffer::write_entity()`].
174+
fn deserialize_entity(cursor: &mut Cursor<Bytes>) -> Result<Entity, bincode::Error> {
175+
let flagged_index: u64 = DefaultOptions::new().deserialize_from(&mut *cursor)?;
176+
let has_generation = (flagged_index & 1) > 0;
177+
let generation = if has_generation {
178+
DefaultOptions::new().deserialize_from(&mut *cursor)?
179+
} else {
180+
0u32
181+
};
182+
183+
let bits = (generation as u64) << 32 | (flagged_index >> 1);
184+
185+
Ok(Entity::from_bits(bits))
186+
}
187+
173188
/// Type of component change.
174189
///
175190
/// Parameter for [`deserialize_component_diffs`].

src/server.rs

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -446,14 +446,14 @@ struct ReplicationBuffer {
446446
/// The number of empty arrays at the end. Can be removed using [`Self::trim_empty_arrays`]
447447
trailing_empty_arrays: usize,
448448

449-
/// Position of the entity map from last call of [`Self::start_entity_data`] or [`Self::write_current_entity`].
449+
/// Position of entity after [`Self::start_entity_data`] or its data after [`Self::write_data_entity`].
450450
entity_data_pos: u64,
451451

452-
/// Length of the map that updated automatically after writing data.
452+
/// Length of the data for entity that updated automatically after writing data.
453453
entity_data_len: u8,
454454

455455
/// Entity from last call of [`Self::start_entity_data`].
456-
current_entity: Entity,
456+
data_entity: Entity,
457457
}
458458

459459
impl ReplicationBuffer {
@@ -476,7 +476,7 @@ impl ReplicationBuffer {
476476
trailing_empty_arrays: Default::default(),
477477
entity_data_pos: Default::default(),
478478
entity_data_len: Default::default(),
479-
current_entity: Entity::PLACEHOLDER,
479+
data_entity: Entity::PLACEHOLDER,
480480
})
481481
}
482482

@@ -547,7 +547,7 @@ impl ReplicationBuffer {
547547
self.trailing_empty_arrays = 0;
548548
}
549549

550-
/// Starts writing entity and its data by remembering [`Entity`].
550+
/// Starts writing entity and its data by remembering `entity`.
551551
///
552552
/// Arrays can contain component changes or removals inside.
553553
/// Length will be increased automatically after writing data.
@@ -556,14 +556,14 @@ impl ReplicationBuffer {
556556
fn start_entity_data(&mut self, entity: Entity) {
557557
debug_assert_eq!(self.entity_data_len, 0);
558558

559-
self.current_entity = entity;
559+
self.data_entity = entity;
560560
}
561561

562562
/// Writes entity for current data and updates remembered position for it to write length later.
563563
///
564564
/// Should be called only after first data write.
565-
fn write_current_entity(&mut self) -> Result<(), bincode::Error> {
566-
DefaultOptions::new().serialize_into(&mut self.message, &self.current_entity)?;
565+
fn write_data_entity(&mut self) -> Result<(), bincode::Error> {
566+
self.write_entity(self.data_entity)?;
567567
self.entity_data_pos = self.message.position();
568568
self.message
569569
.set_position(self.entity_data_pos + mem::size_of_val(&self.entity_data_len) as u64);
@@ -595,7 +595,7 @@ impl ReplicationBuffer {
595595
Ok(())
596596
}
597597

598-
/// Serializes [`ReplicationId`] and component into the buffer data.
598+
/// Serializes `replication_id` and component from `ptr` into the buffer data.
599599
///
600600
/// Should be called only inside entity data.
601601
/// Increases entity data length by 1.
@@ -607,7 +607,7 @@ impl ReplicationBuffer {
607607
ptr: Ptr,
608608
) -> Result<(), bincode::Error> {
609609
if self.entity_data_len == 0 {
610-
self.write_current_entity()?;
610+
self.write_data_entity()?;
611611
}
612612

613613
DefaultOptions::new().serialize_into(&mut self.message, &replication_id)?;
@@ -617,14 +617,14 @@ impl ReplicationBuffer {
617617
Ok(())
618618
}
619619

620-
/// Serializes [`ReplicationId`] of the removed component into the buffer data.
620+
/// Serializes `replication_id` of the removed component into the buffer data.
621621
///
622622
/// Should be called only inside entity data.
623623
/// Increases entity data length by 1.
624624
/// See also [`Self::start_entity_data`].
625625
fn write_removal(&mut self, replication_id: ReplicationId) -> Result<(), bincode::Error> {
626626
if self.entity_data_len == 0 {
627-
self.write_current_entity()?;
627+
self.write_data_entity()?;
628628
}
629629

630630
DefaultOptions::new().serialize_into(&mut self.message, &replication_id)?;
@@ -633,18 +633,36 @@ impl ReplicationBuffer {
633633
Ok(())
634634
}
635635

636-
/// Serializes despawned [`Entity`].
636+
/// Serializes despawned `entity`.
637637
///
638638
/// Should be called only inside array.
639639
/// Increases array length by 1.
640640
/// See also [`Self::start_array`].
641641
fn write_despawn(&mut self, entity: Entity) -> Result<(), bincode::Error> {
642-
DefaultOptions::new().serialize_into(&mut self.message, &entity)?;
642+
self.write_entity(entity)?;
643643
self.array_len = self
644644
.array_len
645645
.checked_add(1)
646646
.ok_or(bincode::ErrorKind::SizeLimit)?;
647647

648648
Ok(())
649649
}
650+
651+
/// Serializes `entity` by writing its index and generation as separate varints.
652+
///
653+
/// The index is first prepended with a bit flag to indicate if the generation
654+
/// is serialized or not (it is not serialized if equal to zero).
655+
#[inline]
656+
fn write_entity(&mut self, entity: Entity) -> Result<(), bincode::Error> {
657+
let mut flagged_index = (entity.index() as u64) << 1;
658+
let flag = entity.generation() > 0;
659+
flagged_index |= flag as u64;
660+
661+
DefaultOptions::new().serialize_into(&mut self.message, &flagged_index)?;
662+
if flag {
663+
DefaultOptions::new().serialize_into(&mut self.message, &entity.generation())?;
664+
}
665+
666+
Ok(())
667+
}
650668
}

0 commit comments

Comments
 (0)