Skip to content

Commit c2d4508

Browse files
committed
Add on_client_insert to add_visiblity_filter
1 parent c42ebc1 commit c2d4508

2 files changed

Lines changed: 81 additions & 0 deletions

File tree

src/server/visibility.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ impl AppVisibilityExt for App {
104104

105105
self.add_observer(update_for_new_clients::<F>)
106106
.add_observer(on_insert::<F>)
107+
.add_observer(on_client_insert::<F>)
107108
.add_observer(on_remove::<F>)
108109
.add_observer(on_client_remove::<F>)
109110
}
@@ -158,6 +159,28 @@ fn on_insert<F: VisibilityFilter>(
158159
}
159160
}
160161

162+
fn on_client_insert<F: VisibilityFilter>(
163+
insert: On<Insert, F::ClientComponent>,
164+
registry: Res<FilterRegistry>,
165+
mut clients: Query<(&F::ClientComponent, &mut ClientVisibility)>,
166+
entities: Query<(Entity, &F), Without<ClientVisibility>>,
167+
) {
168+
let Ok((client_component, mut visibility)) = clients.get_mut(insert.entity) else {
169+
return;
170+
};
171+
172+
let bit = registry.bit::<F>();
173+
for (entity, component) in &entities {
174+
let visible = component.is_visible(insert.entity, Some(client_component));
175+
debug!(
176+
"evaluating inserted `{}` to client `{}` for entity `{entity}` to `{visible}`",
177+
ShortName::of::<F>(),
178+
insert.entity
179+
);
180+
visibility.set(entity, bit, visible);
181+
}
182+
}
183+
161184
fn on_remove<F: VisibilityFilter>(
162185
remove: On<Remove, F>,
163186
registry: Res<FilterRegistry>,

tests/spawn.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,47 @@ fn visibility_gain() {
558558
assert_eq!(components.iter(client_app.world()).len(), 1);
559559
}
560560

561+
#[test]
562+
fn visibility_gain_late_client() {
563+
let mut server_app = App::new();
564+
let mut client_app = App::new();
565+
for app in [&mut server_app, &mut client_app] {
566+
app.add_plugins((
567+
MinimalPlugins,
568+
StatesPlugin,
569+
RepliconPlugins.set(ServerPlugin::new(PostUpdate)),
570+
))
571+
.replicate::<A>()
572+
.add_visibility_filter::<DeferredVisibility>()
573+
.finish();
574+
}
575+
576+
server_app.connect_client(&mut client_app);
577+
578+
server_app
579+
.world_mut()
580+
.spawn((Replicated, DeferredVisibility, A));
581+
582+
server_app.update();
583+
server_app.exchange_with_client(&mut client_app);
584+
client_app.update();
585+
586+
let mut components = client_app.world_mut().query::<&A>();
587+
assert_eq!(components.iter(client_app.world()).len(), 0);
588+
589+
let client = **client_app.world().resource::<TestClientEntity>();
590+
server_app
591+
.world_mut()
592+
.entity_mut(client)
593+
.insert(CanSeeDeferred);
594+
595+
server_app.update();
596+
server_app.exchange_with_client(&mut client_app);
597+
client_app.update();
598+
599+
assert_eq!(components.iter(client_app.world()).len(), 1);
600+
}
601+
561602
#[test]
562603
fn visibility_gain_with_signature() {
563604
let mut server_app = App::new();
@@ -616,3 +657,20 @@ impl VisibilityFilter for EntityVisibility {
616657
component.is_some()
617658
}
618659
}
660+
661+
#[derive(Component)]
662+
#[component(immutable)]
663+
struct DeferredVisibility;
664+
665+
#[derive(Component)]
666+
#[component(immutable)]
667+
struct CanSeeDeferred;
668+
669+
impl VisibilityFilter for DeferredVisibility {
670+
type ClientComponent = CanSeeDeferred;
671+
type Scope = Entity;
672+
673+
fn is_visible(&self, _client: Entity, component: Option<&Self::ClientComponent>) -> bool {
674+
component.is_some()
675+
}
676+
}

0 commit comments

Comments
 (0)