app: order the zone events after the world-map feed

`feed_zone_events` fires `ZONE_CHANGED`, `ZONE_CHANGED_NEW_AREA` and
`MINIMAP_ZONE_CHANGED` inline into the VM. pfQuest answers all three by calling
`SetMapToCurrentZone()` whenever the map is closed (`pfQuest/map.lua:1466`), and
that verb reads `worldmap.player_zone` — which `ui_world_map::feed_world_map`
publishes, in a system that was ordered only `.after(UiInput)`, exactly as this
one was. Nothing ordered the two against each other.

Run the wrong way round, `SetMapToCurrentZone()` reselects the zone the player
has just left, because the feed has not published the new one yet. Every
map-derived overlay then stays a zone behind until something else reselects —
opening the world map, say, whose `OnShow` calls the same verb a frame later
when the feed has caught up.

There is nothing to order in the reference: `SetMapToCurrentZone` calls the
resolver `0x4a6650`, which reads the player's current area live. Reading a
per-frame feed instead is ours, so the ordering is ours to state. Stated as a
set rather than a bare `.after`, since the next consumer of the published zone
will owe the same edge.

Found while chasing grom's report that pfQuest's minimap icons do not re-seat on
a zone change until the world map is opened — which is this shape. Not confirmed
as that bug's cause: it is an unpinned order, so which way it fell before this
commit is not something the logs record.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
This commit is contained in:
2026-10-21 21:37:12 -06:00
co-authored by Claude Opus 5
parent cd6731799b
commit 92b2e31577
2 changed files with 19 additions and 2 deletions
+8 -1
View File
@@ -261,7 +261,14 @@ impl Plugin for AreaPlugin {
// spurious splash.
feed_zone_events
.after(crate::ui_script::UiInput)
.after(benilla_world::terrain_stream::AreaAuthoritySet),
.after(benilla_world::terrain_stream::AreaAuthoritySet)
// `ZONE_CHANGED*` is the signal pfQuest answers with `SetMapToCurrentZone()`
// (`pfQuest/map.lua:1466`), and that verb reads the zone
// `ui_world_map::feed_world_map` publishes. Unordered, the two could run
// either way round, and the wrong way reselects the zone the player just
// left — leaving every map-derived overlay a zone behind until something
// else reselects. See `WorldMapFeedSet`.
.after(crate::ui_world_map::WorldMapFeedSet),
);
}
}
+11 -1
View File
@@ -878,6 +878,16 @@ fn dev_map_jump(
});
}
/// The set of [`feed_world_map`], which publishes the player's `(continent, zone)` into the VM.
///
/// Anything that fires a Lua event an addon answers by calling `SetMapToCurrentZone()` must order
/// **after** this set, because that verb reads the zone this feed publishes
/// (`benilla_ui::script::worldmap`'s `player_zone`) and a stale read reselects the zone the player
/// just left. In the reference there is nothing to order: `SetMapToCurrentZone` calls the resolver
/// `0x4a6650`, which reads the player's current area live, where ours reads a per-frame feed.
#[derive(SystemSet, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct WorldMapFeedSet;
/// The world-map data feed.
pub(crate) struct WorldMapUiPlugin;
@@ -887,7 +897,7 @@ impl Plugin for WorldMapUiPlugin {
Update,
(
// After the script tick: a selection changed this tick projects on the next.
feed_world_map.after(UiInput),
feed_world_map.after(UiInput).in_set(WorldMapFeedSet),
// After the script tick, so the jump hit-tests this tick's frame rects.
dev_map_jump.after(UiInput),
),