the minimap and world map go stock, and the chat loses its white plate
- the minimap cluster and the battleground list are the reference's own `Minimap.xml` and `BattlefieldFrame.xml`, ours deleted, and the sixteen engine names the static probe found unbound are built, not stubbed: the battleground list and queue family (the as-group join refused client-side with no packet when the map's `MaxPlayers` is below the group), the bodyless `CMSG_BATTLEFIELD_STATUS` on world enter — benilla never sent it, so a queue joined before a reconnect was invisible — the 5.5556 yd `BATTLEFIELDS_CLOSED` leash, and the meeting-stone pair over the `0x295` five-way table with both asymmetries; the ping's lifetime is the stock Lua's now (held 5 s, faded 0.5 s), `GetPingPosition` answers two numbers always — our nil was a Lua error on every frame of the stock `Minimap_OnUpdate` — and the map-change drop the reference never had is gone (1974)
- the world map is the reference's own `WorldMapFrame.xml`, our transcription deleted; built for it: the arrow-frame family (an anonymous `Model` child at its 33.6 px footprint, drawn app-side as the minimap's own arrow sprite through one shared constant), the battleground position family over `MSG_BATTLEGROUND_PLAYER_POSITIONS` both ways (the reference's 5000 ms request throttle), and `GetPlayerMapPosition` resolving `raid1..raid40` where it knew only the party (B320); `SetupFullscreenScale` — the engine binding `0x48c270` the map's and the cinematic frame's OnShow call, which our map had stood in for with Lua — is bound to the carved law `min(0.75 · aspect, 1)` off the configured aspect, written through the frame's own `SetScale` (1.0 at 4:3 and wider, 0.9375 at 5:4); a hovered POI writes the map's own area label, not the tooltip; named gap: `WorldMapPing` draws nothing yet (1980, 1981)
- the tutorial frame is the reference's own `TutorialFrame.xml`, over a tutorial system benilla never had: two bit banks filled from `SMSG_TUTORIAL_FLAGS` — the fire-once bank `TriggerTutorial` reads and sets (never a send) and the acknowledged bank `FlagTutorial` writes and sends; there is no tutorial CVar in the binary (210 `CVar::Register` sites censused), so "disable tutorials" is every bit acknowledged; the sites this app can produce are wired (the world-enter Welcome cascade, the level-up arm, item pushes, the loot sparkle, the meeting-stone and battleground arms), the rest named; the loader learned `<TitleRegion>` — the stock frame's drag handle, a region that emits no quad; and the `TabardModel` widget kind arrives ahead of its window, five ints bounded by the `.rdata` table `{170, 17, 6, 17, 51}` and the constant 100 000 tabard cost (1976, 1977)
- the chat window drew as an opaque white plate: the chat-cache loader, gated on `InWorld` alone, restored into the boot VM 130 ms before the deferred entry load filled it, and its per-VM memo then blocked the restore that would have reached the real frames — the plate the stock Lua tints black stayed the XML's white; between the entry edge and the load there is now no VM in the world (the edge parks the boot VM, the load takes it back), so no in-world feed pushes into a VM with no interface; the perf pill reads `59 fps 7.0 ms 17.3 cpu` — the MAIN thread's milliseconds in full text and the process-wide sum dim, because the sum of every thread's CPU time had been read as a frame time (a raid read 17 on it at a solid 60 with the main thread at 7); and `WOW_PROBE_UI_ONE_TEX=1` is a pricing lever, never a look, for the draw-count ceiling a UI atlas would reach before one is built (1978, 1954)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -151,10 +151,30 @@ fn ui_wanted(world: &World) -> bool {
|
||||
#[derive(Resource, Default)]
|
||||
pub(crate) struct PendingEntryUiLoad;
|
||||
|
||||
/// `OnEnter(InWorld)`: arm the deferred entry load. The load itself runs a few frames later —
|
||||
/// see [`PendingEntryUiLoad`].
|
||||
pub(crate) fn arm_entry_ui_load(mut commands: Commands) {
|
||||
commands.insert_resource(PendingEntryUiLoad);
|
||||
/// **The boot VM, parked for the deferral window** (decision 1978). Between the world-entry edge
|
||||
/// and the deferred entry load there is no VM in the world at all: the boot VM waits here, out of
|
||||
/// every feed's reach, and the load takes it back. Every feed takes the VM as an `Option` and
|
||||
/// already returns on `None` — the glue phase's shape — so a feed keyed on a per-VM memo cannot
|
||||
/// push into a VM that has no interface yet and then hold the real push back (the chat plate
|
||||
/// that stayed white, and 1348's whole class). `ingame_ui_pending` stays for the feeds that
|
||||
/// name it; with the VM parked it is belt and braces.
|
||||
pub(crate) struct ParkedBootVm(UiScript);
|
||||
|
||||
/// `OnEnter(InWorld)`: arm the deferred entry load and park the boot VM. The load itself runs a
|
||||
/// few frames later — see [`PendingEntryUiLoad`] and [`ParkedBootVm`].
|
||||
pub(crate) fn arm_entry_ui_load(world: &mut World) {
|
||||
world.insert_resource(PendingEntryUiLoad);
|
||||
if let Some(vm) = world.remove_non_send_resource::<UiScript>() {
|
||||
world.insert_non_send_resource(ParkedBootVm(vm));
|
||||
}
|
||||
}
|
||||
|
||||
/// The parked boot VM back into the world, if one is parked — the session end and the
|
||||
/// left-before-the-load arm both want the VM where the tail expects it.
|
||||
fn unpark_boot_vm(world: &mut World) {
|
||||
if let Some(ParkedBootVm(vm)) = world.remove_non_send_resource::<ParkedBootVm>() {
|
||||
world.insert_non_send_resource(vm);
|
||||
}
|
||||
}
|
||||
|
||||
/// **Is the in-game UI still owed for this world entry?** True from `OnEnter(InWorld)` until
|
||||
@@ -200,6 +220,7 @@ pub(crate) fn run_pending_entry_load(world: &mut World) {
|
||||
if !in_world {
|
||||
// Left the world before the load ran — nothing to build a UI for.
|
||||
world.remove_resource::<PendingEntryUiLoad>();
|
||||
unpark_boot_vm(world);
|
||||
return;
|
||||
}
|
||||
let covering = world
|
||||
@@ -245,6 +266,9 @@ pub(crate) fn run_pending_entry_load(world: &mut World) {
|
||||
/// capture boots straight into `InWorld`, so before that this would have run ahead of
|
||||
/// [`benilla_assets::AssetSet::Open`] and loaded against no patch chain.
|
||||
pub(crate) fn load_ingame_ui_on_world_entry(world: &mut World) {
|
||||
// The VM the entry edge parked (1978); the live slot is the fallback for a caller that did
|
||||
// not go through the arm.
|
||||
unpark_boot_vm(world);
|
||||
if !ui_wanted(world) {
|
||||
return;
|
||||
}
|
||||
@@ -449,6 +473,9 @@ pub(crate) fn shutdown_ui_state(script: &mut UiScript, identity: Option<&(String
|
||||
/// Exclusive rather than a `NonSendMut` system because it both drops and installs a `NonSend`, and
|
||||
/// because the shutdown writes must be ordered against each other — see [`shutdown_ui_state`].
|
||||
pub(crate) fn end_ui_session(world: &mut World) {
|
||||
// A VM still parked (the load never ran) goes back into the world first, so the tail below
|
||||
// runs against the same slot it always did (1978).
|
||||
unpark_boot_vm(world);
|
||||
// An armed-but-unrun entry load ([`PendingEntryUiLoad`]) means this session never built an
|
||||
// in-game UI: there are no globals to save and no addon state to write, and running the
|
||||
// shutdown tail against the boot VM would overwrite the real files with that emptiness.
|
||||
@@ -701,3 +728,32 @@ pub(crate) fn is_emote_token_line(line: &str) -> bool {
|
||||
.bytes()
|
||||
.all(|b| b.is_ascii_uppercase() || b.is_ascii_digit() || b == b'_')
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
/// The entry edge parks the boot VM (1978): between the arm and the load there is no VM in
|
||||
/// the world for any feed to push into, and the session end puts a never-loaded one back.
|
||||
#[test]
|
||||
fn the_entry_edge_parks_the_boot_vm_and_the_session_end_returns_it() {
|
||||
let mut world = World::new();
|
||||
let boot = UiScript::new().unwrap();
|
||||
let session = boot.session();
|
||||
world.insert_non_send_resource(boot);
|
||||
arm_entry_ui_load(&mut world);
|
||||
assert!(
|
||||
world.get_non_send_resource::<UiScript>().is_none(),
|
||||
"no VM in the deferral window"
|
||||
);
|
||||
assert!(world.get_resource::<PendingEntryUiLoad>().is_some());
|
||||
assert!(world.get_non_send_resource::<ParkedBootVm>().is_some());
|
||||
// Left the world before the load ran: the VM comes back, untouched.
|
||||
unpark_boot_vm(&mut world);
|
||||
let vm = world
|
||||
.get_non_send_resource::<UiScript>()
|
||||
.expect("the parked VM is back");
|
||||
assert_eq!(vm.session(), session, "the same VM, no session moved");
|
||||
assert!(world.get_non_send_resource::<ParkedBootVm>().is_none());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user