Skip to content

Commit 2af454c

Browse files
committed
Migrate to the new SystemParam changes
- State now initialized separately. - Updating archetype access no longer needed. - `new_archetype` no longer exists and archetype cache needs to be updated in `get_param`. - `ReplicationRules` resource no longer need to be cloned. For details see bevyengine/bevy#16885 bevyengine/bevy#19143
1 parent 7b69a10 commit 2af454c

File tree

1 file changed

+71
-85
lines changed

1 file changed

+71
-85
lines changed

src/server/server_world.rs

Lines changed: 71 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
use core::mem;
2+
13
use bevy::{
24
ecs::{
3-
archetype::{Archetype, ArchetypeEntity, ArchetypeId},
5+
archetype::{Archetype, ArchetypeEntity, ArchetypeGeneration, ArchetypeId},
46
component::{ComponentId, ComponentTicks, StorageType, Tick},
5-
query::{Access, FilteredAccess},
7+
query::{FilteredAccess, FilteredAccessSet},
68
storage::TableId,
79
system::{ReadOnlySystemParam, SystemMeta, SystemParam},
810
world::unsafe_world_cell::UnsafeWorldCell,
@@ -39,7 +41,12 @@ impl<'w> ServerWorld<'w, '_> {
3941
storage: StorageType,
4042
component_id: ComponentId,
4143
) -> (Ptr<'w>, ComponentTicks) {
42-
debug_assert!(self.state.access.has_component_read(component_id));
44+
debug_assert!(
45+
self.state
46+
.component_access
47+
.access()
48+
.has_component_read(component_id)
49+
);
4350

4451
let storages = unsafe { self.world.storages() };
4552
match storage {
@@ -90,90 +97,45 @@ impl<'w> ServerWorld<'w, '_> {
9097

9198
unsafe impl SystemParam for ServerWorld<'_, '_> {
9299
type State = ReplicationReadState;
93-
type Item<'world, 'state> = ServerWorld<'world, 'state>;
100+
type Item<'w, 's> = ServerWorld<'w, 's>;
94101

95-
fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
96-
let mut filtered_access = FilteredAccess::default();
102+
fn init_state(world: &mut World) -> Self::State {
103+
let mut component_access = FilteredAccess::default();
97104

98105
let marker_id = world.register_component::<Replicated>();
99-
filtered_access.add_component_read(marker_id);
106+
component_access.add_component_read(marker_id);
100107

101108
let rules = world.resource::<ReplicationRules>();
102109
debug!("initializing with {} replication rules", rules.len());
103-
let combined_access = system_meta.component_access_set().combined_access();
104110
for rule in rules.iter() {
105111
for component in &rule.components {
106-
filtered_access.add_component_read(component.id);
107-
assert!(
108-
!combined_access.has_component_write(component.id),
109-
"replicated component `{}` in system `{}` shouldn't be in conflict with other system parameters",
110-
world.components().get_name(component.id).unwrap(),
111-
system_meta.name(),
112-
);
112+
component_access.add_component_read(component.id);
113113
}
114114
}
115115

116-
let access = filtered_access.access().clone();
117-
118-
// SAFETY: used only to extend access.
119-
unsafe {
120-
system_meta.component_access_set_mut().add(filtered_access);
121-
}
122-
123-
ReplicationReadState {
124-
access,
125-
marker_id,
116+
Self::State {
117+
component_access,
118+
marker_id: world.register_component::<Replicated>(),
126119
archetypes: Default::default(),
127-
// Needs to be cloned because `new_archetype` only accepts the state.
128-
rules: world.resource::<ReplicationRules>().clone(),
120+
generation: ArchetypeGeneration::initial(),
129121
}
130122
}
131123

132-
unsafe fn new_archetype(
133-
state: &mut Self::State,
134-
archetype: &Archetype,
124+
fn init_access(
125+
state: &Self::State,
135126
system_meta: &mut SystemMeta,
127+
component_access_set: &mut FilteredAccessSet,
128+
_world: &mut World,
136129
) {
137-
if !archetype.contains(state.marker_id) {
138-
return;
130+
let conflicts = component_access_set.get_conflicts_single(&state.component_access);
131+
if !conflicts.is_empty() {
132+
panic!(
133+
"replicated components in system `{}` shouldn't be in conflict with other system parameters",
134+
system_meta.name(),
135+
);
139136
}
140137

141-
trace!("marking `{:?}` as replicated", archetype.id());
142-
let mut replicated_archetype = ReplicatedArchetype::new(archetype.id());
143-
for rule in state.rules.iter().filter(|rule| rule.matches(archetype)) {
144-
for &component in &rule.components {
145-
// Since rules are sorted by priority,
146-
// we are inserting only new components that aren't present.
147-
if replicated_archetype
148-
.components
149-
.iter()
150-
.any(|(existing, _)| existing.id == component.id)
151-
{
152-
continue;
153-
}
154-
155-
// SAFETY: archetype matches the rule, so the component is present.
156-
let storage =
157-
unsafe { archetype.get_storage_type(component.id).unwrap_unchecked() };
158-
replicated_archetype.components.push((component, storage));
159-
}
160-
}
161-
162-
// Update system access for proper parallelization.
163-
for (component, _) in &replicated_archetype.components {
164-
// SAFETY: archetype contains this component and we don't remove access from system meta.
165-
unsafe {
166-
let archetype_id = archetype
167-
.get_archetype_component_id(component.id)
168-
.unwrap_unchecked();
169-
system_meta
170-
.archetype_component_access_mut()
171-
.add_component_read(archetype_id)
172-
}
173-
}
174-
175-
// Store for future iteration.
176-
state.archetypes.push(replicated_archetype);
138+
component_access_set.add(state.component_access.clone());
177139
}
178140

179141
unsafe fn get_param<'world, 'state>(
@@ -182,6 +144,43 @@ unsafe impl SystemParam for ServerWorld<'_, '_> {
182144
world: UnsafeWorldCell<'world>,
183145
_change_tick: Tick,
184146
) -> Self::Item<'world, 'state> {
147+
let archetypes = world.archetypes();
148+
let old_generation = mem::replace(&mut state.generation, archetypes.generation());
149+
150+
// SAFETY: Has access to this resource and the access is unique.
151+
let rules = unsafe {
152+
world
153+
.get_resource::<ReplicationRules>()
154+
.expect("replication rules should've been initialized in the plugin")
155+
};
156+
for archetype in archetypes[old_generation..]
157+
.iter()
158+
.filter(|archetype| archetype.contains(state.marker_id))
159+
{
160+
trace!("marking `{:?}` as replicated", archetype.id());
161+
let mut replicated_archetype = ReplicatedArchetype::new(archetype.id());
162+
for rule in rules.iter().filter(|rule| rule.matches(archetype)) {
163+
for &component in &rule.components {
164+
// Since rules are sorted by priority,
165+
// we are inserting only new components that aren't present.
166+
if replicated_archetype
167+
.components
168+
.iter()
169+
.any(|(existing, _)| existing.id == component.id)
170+
{
171+
continue;
172+
}
173+
174+
// SAFETY: archetype matches the rule, so the component is present.
175+
let storage =
176+
unsafe { archetype.get_storage_type(component.id).unwrap_unchecked() };
177+
replicated_archetype.components.push((component, storage));
178+
}
179+
}
180+
181+
state.archetypes.push(replicated_archetype);
182+
}
183+
185184
ServerWorld { world, state }
186185
}
187186
}
@@ -192,15 +191,16 @@ pub(crate) struct ReplicationReadState {
192191
/// All replicated components.
193192
///
194193
/// Used only in debug to check component access.
195-
access: Access<ComponentId>,
194+
component_access: FilteredAccess,
196195

197196
/// ID of [`Replicated`] component.
198197
marker_id: ComponentId,
199198

199+
/// Highest processed archetype ID.
200+
generation: ArchetypeGeneration,
201+
200202
/// Archetypes marked as replicated.
201203
archetypes: Vec<ReplicatedArchetype>,
202-
203-
rules: ReplicationRules,
204204
}
205205

206206
/// An archetype that can be stored in [`ReplicatedArchetypes`].
@@ -268,20 +268,6 @@ mod tests {
268268
app.update();
269269
}
270270

271-
#[test]
272-
fn replicate_after_system() {
273-
let mut app = App::new();
274-
app.init_resource::<ProtocolHasher>()
275-
.init_resource::<ReplicationRules>()
276-
.init_resource::<ReplicationRegistry>()
277-
.add_systems(Update, |world: ServerWorld| {
278-
assert_eq!(world.state.rules.len(), 1);
279-
})
280-
.replicate::<Transform>();
281-
282-
app.update();
283-
}
284-
285271
#[test]
286272
fn empty() {
287273
let mut app = App::new();

0 commit comments

Comments
 (0)