Skip to content

Commit 58bb7d1

Browse files
ShaturUkoeHB
andauthored
Relationships networking (#473)
Co-authored-by: UkoeHB <37489173+UkoeHB@users.noreply.github.com>
1 parent c21198f commit 58bb7d1

10 files changed

Lines changed: 986 additions & 92 deletions

File tree

CHANGELOG.md

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

1212
- Support for `no_std`.
13+
- Relationships networking. Use `SyncRelatedAppExt::sync_related_entities<C>` to ensure that entities related by `C` are replicated in sync.
1314
- Seamless support for immutable components. For these components, replication is always applied via insertion.
1415

1516
### Changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ members = ["bevy_replicon_example_backend"]
3030
[dependencies]
3131
bevy = { version = "0.16.0-rc.5", default-features = false }
3232
log = "0.4" # Directly depend on `log` like other `no_std` Bevy crates, since `bevy_log` currently requires `std`.
33+
petgraph = { version = "0.8", default-features = false, features = [
34+
"stable_graph",
35+
] }
3336
variadics_please = "1.0"
3437
typeid = "1.0"
3538
bytes = { version = "1.10", default-features = false }

src/lib.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ This behavior is also configurable via [client markers](#client-markers).
209209
Some components depend on each other. For example, [`ChildOf`] and [`Children`]. You can enable
210210
replication only for [`ChildOf`] and [`Children`] will be updated automatically on insertion.
211211
212+
You can also ensure that their mutations arrive in sync by using [`SyncRelatedAppExt::sync_related_entities`].
213+
212214
## Network events and triggers
213215
214216
This replaces RPCs (remote procedure calls) in other engines and,
@@ -549,9 +551,9 @@ All events, inserts, removals and despawns will be applied to clients in the sam
549551
However, if you insert/mutate a component and immediately remove it, the client will only receive the removal because the component value
550552
won't exist in the [`World`] during the replication process. But removal followed by insertion will work as expected since we buffer removals.
551553
552-
Entity component mutations are grouped by entity, and component groupings may be applied to clients in a different order than on the server.
554+
Entity component mutations may be applied to clients in a different order than on the server.
553555
For example, if two entities are spawned in tick 1 on the server and their components are mutated in tick 2,
554-
then the client is guaranteed to see the spawns at the same time, but the component mutations may appear in different client ticks.
556+
then the client is guaranteed to see the spawns at the same tick, but the component mutations may appear later (but not earlier).
555557
556558
If a component is dependent on other data, mutations to the component will only be applied to the client when that data has arrived.
557559
So if your component references another entity, mutations to that component will only be applied when the referenced entity has been spawned on the client.
@@ -612,7 +614,8 @@ pub mod prelude {
612614
server_trigger::{ServerTriggerAppExt, ServerTriggerExt},
613615
},
614616
replication::{
615-
Replicated, command_markers::AppMarkerExt, replication_rules::AppRuleExt,
617+
Replicated, command_markers::AppMarkerExt, related_entities::SyncRelatedAppExt,
618+
replication_rules::AppRuleExt,
616619
},
617620
},
618621
};

src/server.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use crate::shared::{
3030
postcard_utils,
3131
replication::{
3232
client_ticks::{ClientTicks, EntityBuffer},
33+
related_entities::RelatedEntities,
3334
replication_registry::{
3435
ReplicationRegistry, component_fns::ComponentFns, ctx::SerializeCtx,
3536
rule_fns::UntypedRuleFns,
@@ -249,6 +250,7 @@ pub(super) fn send_replication(
249250
&mut ClientTicks,
250251
Option<&mut ClientVisibility>,
251252
)>,
253+
mut related_entities: ResMut<RelatedEntities>,
252254
mut removal_buffer: ResMut<RemovalBuffer>,
253255
mut entity_buffer: ResMut<EntityBuffer>,
254256
mut despawn_buffer: ResMut<DespawnBuffer>,
@@ -259,9 +261,12 @@ pub(super) fn send_replication(
259261
server_tick: Res<ServerTick>,
260262
time: Res<Time>,
261263
) -> Result<()> {
262-
for (_, mut mutations, mut updates, ..) in &mut clients {
264+
related_entities.rebuild_graphs();
265+
266+
for (_, mut updates, mut mutations, ..) in &mut clients {
263267
updates.clear();
264268
mutations.clear();
269+
mutations.resize_related(related_entities.graphs_count());
265270
}
266271

267272
collect_mappings(&mut serialized, &mut clients)?;
@@ -272,6 +277,7 @@ pub(super) fn send_replication(
272277
&mut clients,
273278
&registry,
274279
&type_registry.read(),
280+
&related_entities,
275281
&removal_buffer,
276282
&world,
277283
&change_tick,
@@ -471,6 +477,7 @@ fn collect_changes(
471477
)>,
472478
registry: &ReplicationRegistry,
473479
type_registry: &TypeRegistry,
480+
related_entities: &RelatedEntities,
474481
removal_buffer: &RemovalBuffer,
475482
world: &ServerWorld,
476483
change_tick: &SystemChangeTick,
@@ -535,12 +542,13 @@ fn collect_changes(
535542
{
536543
if ticks.is_changed(tick, change_tick.this_run()) {
537544
if !mutations.entity_added() {
545+
let graph_index = related_entities.graph_index(entity.id());
538546
let entity_range = write_entity_cached(
539547
&mut entity_range,
540548
serialized,
541549
entity.id(),
542550
)?;
543-
mutations.add_entity(entity.id(), entity_range);
551+
mutations.add_entity(entity.id(), graph_index, entity_range);
544552
}
545553
let component_range = write_component_cached(
546554
&mut component_range,

0 commit comments

Comments
 (0)