Skip to content

Commit ebe7dea

Browse files
authored
Refactor despawns and removal buffering (#475)
* Refactor despawns - Track despawns using observer. - Move to `server` module since it's very tiny. * Move `buffer_removals` to `server` module Place it alongside other systems. We don't need it to be a plugin, users can't toggle it. Also simplifies unit tests. * Update changelog
1 parent 6427893 commit ebe7dea

4 files changed

Lines changed: 88 additions & 168 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1818
- Update to Bevy 0.16.
1919
- All serde methods now use `bevy::ecs::error::Result` instead of `postcard::Result` for more informative errors.
2020
- `AppRuleExt::replicate_mapped`, `RuleFns::default_mapped` and `default_deserialize_mapped` now deprecated. Entities inside components now mapped automatically, use methods without `_mapped` prefixes.
21+
- Use an observer instead of a system to track despawns.
2122

2223
### Removed
2324

src/server.rs

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
pub mod client_entity_map;
22
pub mod client_visibility;
3-
pub(super) mod despawn_buffer;
43
pub mod event;
54
pub(super) mod removal_buffer;
65
pub(super) mod replication_messages;
@@ -10,7 +9,9 @@ mod server_world;
109
use core::{ops::Range, time::Duration};
1110

1211
use bevy::{
13-
ecs::{component::StorageType, system::SystemChangeTick},
12+
ecs::{
13+
archetype::Archetypes, component::StorageType, entity::Entities, system::SystemChangeTick,
14+
},
1415
prelude::*,
1516
ptr::Ptr,
1617
reflect::TypeRegistry,
@@ -29,20 +30,21 @@ use crate::shared::{
2930
event::server_event::BufferedServerEvents,
3031
postcard_utils,
3132
replication::{
33+
Replicated,
3234
client_ticks::{ClientTicks, EntityBuffer},
3335
related_entities::RelatedEntities,
3436
replication_registry::{
3537
ReplicationRegistry, component_fns::ComponentFns, ctx::SerializeCtx,
3638
rule_fns::UntypedRuleFns,
3739
},
40+
replication_rules::ReplicationRules,
3841
track_mutate_messages::TrackMutateMessages,
3942
},
4043
replicon_tick::RepliconTick,
4144
};
4245
use client_entity_map::ClientEntityMap;
4346
use client_visibility::{ClientVisibility, Visibility};
44-
use despawn_buffer::{DespawnBuffer, DespawnBufferPlugin};
45-
use removal_buffer::{RemovalBuffer, RemovalBufferPlugin};
47+
use removal_buffer::{RemovalBuffer, RemovalReader};
4648
use replication_messages::{
4749
mutations::Mutations, serialized_data::SerializedData, updates::Updates,
4850
};
@@ -89,7 +91,8 @@ impl Default for ServerPlugin {
8991
/// Can be disabled for client-only apps.
9092
impl Plugin for ServerPlugin {
9193
fn build(&self, app: &mut App) {
92-
app.add_plugins((DespawnBufferPlugin, RemovalBufferPlugin))
94+
app.init_resource::<DespawnBuffer>()
95+
.init_resource::<RemovalBuffer>()
9396
.init_resource::<RepliconServer>()
9497
.init_resource::<ServerTick>()
9598
.init_resource::<EntityBuffer>()
@@ -104,6 +107,7 @@ impl Plugin for ServerPlugin {
104107
)
105108
.add_observer(handle_connects)
106109
.add_observer(handle_disconnects)
110+
.add_observer(buffer_despawns)
107111
.add_systems(Startup, setup_channels)
108112
.add_systems(
109113
PreUpdate,
@@ -118,11 +122,15 @@ impl Plugin for ServerPlugin {
118122
.add_systems(
119123
PostUpdate,
120124
(
121-
send_replication
122-
.map(Result::unwrap)
125+
(
126+
buffer_removals,
127+
send_replication
128+
.map(Result::unwrap)
129+
.run_if(resource_changed::<ServerTick>),
130+
)
131+
.chain()
123132
.in_set(ServerSet::Send)
124-
.run_if(server_running)
125-
.run_if(resource_changed::<ServerTick>),
133+
.run_if(server_running),
126134
reset.run_if(server_just_stopped),
127135
),
128136
);
@@ -236,6 +244,33 @@ fn receive_acks(
236244
}
237245
}
238246

247+
fn buffer_despawns(
248+
trigger: Trigger<OnRemove, Replicated>,
249+
mut despawn_buffer: ResMut<DespawnBuffer>,
250+
server: Res<RepliconServer>,
251+
) {
252+
if server.is_running() {
253+
despawn_buffer.push(trigger.target());
254+
}
255+
}
256+
257+
fn buffer_removals(
258+
entities: &Entities,
259+
archetypes: &Archetypes,
260+
mut removal_reader: RemovalReader,
261+
mut removal_buffer: ResMut<RemovalBuffer>,
262+
rules: Res<ReplicationRules>,
263+
) {
264+
for (&entity, removed_components) in removal_reader.read() {
265+
let location = entities
266+
.get(entity)
267+
.expect("removals count only existing entities");
268+
let archetype = archetypes.get(location.archetype_id).unwrap();
269+
270+
removal_buffer.update(&rules, archetype, entity, removed_components);
271+
}
272+
}
273+
239274
/// Collects [`ReplicationMessages`] and sends them.
240275
fn send_replication(
241276
mut serialized: Local<SerializedData>,
@@ -737,3 +772,11 @@ pub enum VisibilityPolicy {
737772
/// All entities are hidden by default and should be explicitly registered to be visible.
738773
Whitelist,
739774
}
775+
776+
/// Buffer with all despawned entities.
777+
///
778+
/// We treat removals of [`Replicated`] component as despawns
779+
/// to avoid missing events in case the server's tick policy is
780+
/// not [`TickPolicy::EveryFrame`].
781+
#[derive(Default, Resource, Deref, DerefMut)]
782+
struct DespawnBuffer(Vec<Entity>);

src/server/despawn_buffer.rs

Lines changed: 0 additions & 62 deletions
This file was deleted.

0 commit comments

Comments
 (0)