- an addon error shows the red script-error dialog the reference shows, and a runaway load loop can no longer freeze world entry - food and drink show stack counts from the first login, and a paladin's aura bar lights the aura that is actually on - logging out no longer erases the character from saved-bag addons: the player's absence is no data - MPQ patches are discovered the way the client discovers them, and a slow arrival holds in place instead of falling through the world Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
164 lines
9.6 KiB
XML
164 lines
9.6 KiB
XML
<Ui>
|
|
<!--
|
|
Interface\FrameXML\BasicControls.xml, re-expressed — the reference's second file, right
|
|
after Fonts.xml, and one of the smallest in FrameXML. It carries four things an addon can
|
|
reach and we had none of:
|
|
|
|
TEXT(text) the identity function 1.12 wraps every displayed string in. **26 corpus
|
|
addons call it**, because half the shipped FrameXML does and they copied
|
|
the idiom. Missing, it is `attempt to call global 'TEXT'`.
|
|
message(text) the client's "show the player this" dialog. Its own popup, not a chat
|
|
line. Present in 64 corpus files — but read the line before ranking it
|
|
(1207): 55 of those are copies of `Dewdrop-2.0.lua`, and the genuine
|
|
callers are about ten addons.
|
|
_ERRORMESSAGE what `message` is implemented in terms of, and the reference's default
|
|
error handler. Two corpus addons replace it outright (ImprovedErrorFrame
|
|
is one), which they cannot do to a name that does not exist.
|
|
ScriptErrors the dialog both of the above put text into, plus DialogBoxFrame and the
|
|
DialogButton*Texture trio it is built from — three of which the corpus
|
|
also inherits from directly (`inherits_demand`, 2 addons each).
|
|
|
|
The three fonts this needs — GameFontRedLarge, DialogButtonNormalText,
|
|
DialogButtonHighlightText — are already in Fonts.xml, so this file is self-contained
|
|
against the one that loads before it, exactly as it is in the reference's own toc order.
|
|
-->
|
|
<Script><![CDATA[
|
|
-- ── _ERRORMESSAGE / message (ref BasicControls.xml l.5-15) ─────────────────────────────
|
|
--
|
|
-- COMPLETE, including `debuginfo()`. That line was guarded here when this file landed,
|
|
-- because `debuginfo` was an engine global we lacked and whose behaviour was uncarved —
|
|
-- and declaring a no-op under a real 1.12 name is exactly the "capability absent without a
|
|
-- failure" class 1203 named. wow-re has since carved it (2026-08-11): `0x7027f0` is
|
|
-- `33 c0 c3` — `xor eax,eax; ret`, three bytes, no call, no memory write. It genuinely
|
|
-- does nothing and returns nothing, and five of its `debug*` siblings are byte-identical.
|
|
-- So the no-op in `stdlib.rs` is the REFERENCE's no-op, the guard was measuring our own
|
|
-- ignorance rather than a real branch, and it is gone.
|
|
function _ERRORMESSAGE(msg)
|
|
debuginfo()
|
|
if not ScriptErrors:IsVisible() then
|
|
ScriptErrors_Message:SetText(msg)
|
|
ScriptErrors:Show()
|
|
end
|
|
return msg
|
|
end
|
|
|
|
function message(text)
|
|
_ERRORMESSAGE(text)
|
|
end
|
|
|
|
-- ── seterrorhandler(_ERRORMESSAGE): the reference's closing line, now transcribed ──────
|
|
-- This file withheld exactly this line from when it landed until decision 1305, because
|
|
-- the engine's error channel (`UiScript::errors()`) was the only place a Lua fault was
|
|
-- visible to any instrument and a modal would have blinded it. That trade is dissolved,
|
|
-- not decided differently: the engine now records every caught script error on the host
|
|
-- channel FIRST and then dispatches it to whatever `geterrorhandler()` answers
|
|
-- (`dispatch_script_errors_to_handler`, 1305) — so the harness's blocker tables read
|
|
-- exactly what they always read, and the player gets what the reference always gave them:
|
|
-- an addon that errors puts the red ScriptErrors dialog on screen instead of failing
|
|
-- somewhere only a terminal can see (B271's report was debugged entirely off WARN lines).
|
|
-- An addon that installs its OWN handler still wins outright, exactly as in 1195.
|
|
seterrorhandler(_ERRORMESSAGE)
|
|
|
|
-- ── TEXT (ref l.22-26, verbatim) ──────────────────────────────────────────────────────
|
|
-- "This function is used to translate text (actually it's already translated as-is)" is
|
|
-- the reference's own comment. It really is the identity function: 1.12 shipped one
|
|
-- localisation per client and the hook was never used.
|
|
function TEXT(text)
|
|
return text
|
|
end
|
|
|
|
-- ── UIParentLoadAddOn (ref UIParent.lua l.638-647) ────────────────────────────────────
|
|
-- The on-demand loader every "open the auction house / tradeskill / talent panel" path
|
|
-- goes through, and the one 5 corpus addons name — FuBar_MCPFu, Fubar_RareTrackerFu, MCP,
|
|
-- MikScrollingBattleText, SpecialTalent: five separate addons, not one library replicated
|
|
-- (1207/1240).
|
|
--
|
|
-- Every piece was already here and only the join was missing: `LoadAddOn` answers the
|
|
-- reference's own `(1, nil)` / `(nil, reason)` pair, `message` and `TEXT` are directly
|
|
-- above, and the `ADDON_*` reason words come from the real `GlobalStrings.lua` we RUN off
|
|
-- the patch chain rather than copy (1234).
|
|
--
|
|
-- **`FailedAddOnLoad` is the reference's own latch, and it is not decoration.** Without it
|
|
-- an addon that retries the load from a handler raises a modal on every attempt; with it
|
|
-- the failure shows once per addon name per session. It is exactly the detail this would
|
|
-- have lacked had it been reconstructed from the name instead of read.
|
|
--
|
|
-- Every reason our `LoadAddOn` can answer resolves to a string: MISSING, DISABLED,
|
|
-- NOT_DEMAND_LOADED, DEP_MISSING and DEP_DISABLED all have an `ADDON_..reason` word
|
|
-- (GlobalStrings l.16-31), the same reason set wow-re's `ui.md` l.2396 carves off
|
|
-- `0x51e780`. So the `getglobal` below cannot hand `format` a nil.
|
|
FailedAddOnLoad = {};
|
|
|
|
function UIParentLoadAddOn(name)
|
|
local loaded, reason = LoadAddOn(name)
|
|
if not loaded then
|
|
if not FailedAddOnLoad[name] then
|
|
message(format(TEXT(ADDON_LOAD_FAILED), name, TEXT(getglobal("ADDON_" .. reason))))
|
|
FailedAddOnLoad[name] = true
|
|
end
|
|
end
|
|
return loaded
|
|
end
|
|
]]></Script>
|
|
|
|
<!-- The dialog button faces (ref l.28-37). Same three-piece art as UIPanelButtonTemplate's,
|
|
with their own names because the reference's dialogs inherit these directly. -->
|
|
<Texture name="DialogButtonNormalTexture" file="Interface\Buttons\UI-Panel-Button-Up" virtual="true">
|
|
<TexCoords left="0" right="0.625" top="0" bottom="0.6875"/>
|
|
</Texture>
|
|
<Texture name="DialogButtonPushedTexture" file="Interface\Buttons\UI-Panel-Button-Down" virtual="true">
|
|
<TexCoords left="0" right="0.625" top="0" bottom="0.6875"/>
|
|
</Texture>
|
|
<Texture name="DialogButtonHighlightTexture" file="Interface\Buttons\UI-Panel-Button-Highlight" alphaMode="ADD" virtual="true">
|
|
<TexCoords left="0" right="0.625" top="0" bottom="0.6875"/>
|
|
</Texture>
|
|
|
|
<!-- DialogBoxFrame (ref l.38-77): a centered tooltip-bordered box with one OKAY button that
|
|
hides its parent. Virtual — ScriptErrors below is the only thing in shipped FrameXML that
|
|
inherits it, but two corpus addons inherit it too. -->
|
|
<Frame name="DialogBoxFrame" virtual="true" toplevel="true" frameStrata="DIALOG" hidden="true">
|
|
<Anchors>
|
|
<Anchor point="CENTER"/>
|
|
</Anchors>
|
|
<Backdrop bgFile="Interface\DialogFrame\UI-DialogBox-Background" edgeFile="Interface\DialogFrame\UI-DialogBox-Border" tile="true">
|
|
<EdgeSize><AbsValue val="32"/></EdgeSize>
|
|
<TileSize><AbsValue val="32"/></TileSize>
|
|
<BackgroundInsets><AbsInset left="11" right="12" top="12" bottom="11"/></BackgroundInsets>
|
|
</Backdrop>
|
|
<Frames>
|
|
<Button name="$parentButton">
|
|
<Size><AbsDimension x="128" y="32"/></Size>
|
|
<Anchors>
|
|
<Anchor point="BOTTOM"><Offset><AbsDimension x="0" y="16"/></Offset></Anchor>
|
|
</Anchors>
|
|
<Scripts>
|
|
<OnClick>
|
|
this:GetParent():Hide()
|
|
</OnClick>
|
|
</Scripts>
|
|
<NormalTexture inherits="DialogButtonNormalTexture"/>
|
|
<PushedTexture inherits="DialogButtonPushedTexture"/>
|
|
<HighlightTexture inherits="DialogButtonHighlightTexture"/>
|
|
<ButtonText text="OKAY"/>
|
|
<NormalFont inherits="DialogButtonNormalText"/>
|
|
<HighlightFont inherits="DialogButtonHighlightText"/>
|
|
</Button>
|
|
</Frames>
|
|
</Frame>
|
|
|
|
<!-- "This is the general scripting error dialog" (ref l.79-100), verbatim. -->
|
|
<Frame name="ScriptErrors" inherits="DialogBoxFrame">
|
|
<Size><AbsDimension x="384" y="128"/></Size>
|
|
<Layers>
|
|
<Layer level="ARTWORK">
|
|
<FontString name="ScriptErrors_Message" inherits="GameFontRedLarge" justifyH="CENTER" justifyV="TOP" nonspacewrap="true">
|
|
<Size><AbsDimension x="360" y="0"/></Size>
|
|
<Anchors>
|
|
<Anchor point="TOP"><Offset><AbsDimension x="0" y="-16"/></Offset></Anchor>
|
|
</Anchors>
|
|
</FontString>
|
|
</Layer>
|
|
</Layers>
|
|
</Frame>
|
|
</Ui>
|