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:
@@ -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),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user