diff --git a/crates/benilla-app/src/addon_harness/mod.rs b/crates/benilla-app/src/addon_harness/mod.rs index 39f66cc5..4126bc83 100644 --- a/crates/benilla-app/src/addon_harness/mod.rs +++ b/crates/benilla-app/src/addon_harness/mod.rs @@ -1108,6 +1108,11 @@ fn seat_a_session(script: &mut UiScript) { if let Some(names) = area_names() { script.set_area_names(names.clone()); } + // The map rects and the flight-master table, for the reason [`world_map_catalog`] gives. + if let Some((continents, taxi)) = world_map_catalog() { + script.set_world_map_catalog(continents.clone()); + script.set_taxi_map_catalog(taxi.clone()); + } script.set_unit( "player", Some(benilla_ui::script::UnitState { @@ -1417,6 +1422,46 @@ fn area_names() -> Option<&'static std::collections::BTreeMap> { .as_ref() } +/// The world-map catalog — `WorldMapArea`, `WorldMapContinent`, `WorldMapOverlay` and the taxi +/// nodes resolved against them — read once per process; `None` with no install. +/// +/// Seated for the same reason the area-name column above is, and it was the next gap in the same +/// wall: the live client pushes this at every VM build (`ui_world_map::seed_world_map_catalog`), +/// so an in-world session with an empty catalog is a state only the harness reaches — and the +/// faults it hides are silent in exactly the same way. pfQuest's minimap pass gates its whole pin +/// loop on `minimap_sizes[mapID]` (`map.lua:1383`), a table whose `__index` asks +/// `C_Map.GetMapWorldSize` and **caches a `false` for ever** on a miss, so an empty catalog here +/// reads as "this client has no zone sizes" with no raise and no log line. Without this, a probe +/// of that gate measures the shipped fallback table rather than the client — which is a way to +/// conclude a live bug exists when it does not. +fn world_map_catalog() -> Option<&'static ( + Vec, + Vec, +)> { + use std::sync::OnceLock; + #[allow(clippy::type_complexity)] + static CATALOG: OnceLock< + Option<( + Vec, + Vec, + )>, + > = OnceLock::new(); + CATALOG + .get_or_init(|| { + let data = benilla_formats::wow_data()?; + let mut chain = benilla_formats::open_chain(&data).ok()?; + let areas = benilla_formats::load_area_table_catalog(&mut chain).ok()?; + let maps = + benilla_assets::MapCatalogRes(benilla_formats::load_map_catalog(&mut chain).ok()?); + let (views, ui_data) = crate::ui_world_map::build_catalog(&mut chain, &areas, &maps)?; + let nodes = benilla_formats::load_taxi_nodes(&mut chain) + .map(|n| crate::ui_taxi::taxi_map_catalog(&n, &ui_data, &areas)) + .unwrap_or_default(); + Some((views, nodes)) + }) + .as_ref() +} + /// `SpellDuration.dbc`, behind nampower's `GetSpellDuration`; `None` when the chain lacks it. fn spell_durations() -> Option<&'static benilla_formats::SpellDurationCatalog> { use std::sync::OnceLock;