Files
benilla-octo/crates/benilla-app/assets/ui/ContainerFrameAdapters.xml
T
SamandClaude Fable 5 a0d2fc383b the world map blips are the reference's, and particles go untinted
- the world map speaks the reference's names: WorldMapTooltip is declared (six corpus addons index it; pfUI dies on it at file scope), the blackout frame takes the reference's spelling BlackoutWorld, and the four hand-written party blips become the reference's own unit-blip templates — all 44 blips as instances, each with its published $parentIcon, the name pfUI recolours group blips by class through; the 40 raid ones are declared but not positioned yet, named in the OUT list rather than faked
- the templates addons build their own buttons from are published: ItemButtonTemplate, ContainerFrameItemButtonTemplate and the bag-slot chain — most of the handler scripts were live the whole time (this client executes the reference's own container and paper-doll code off the player's patch chain), so what was missing was mostly declarations, not behaviour — the bank arm stays out and is named as the omission it is; OptionsFrameSliders becomes real, with the three Graphics rows reading it and re-reading on show, so an addon's write to a slider's bounds actually moves the slider; and the template census that had ranked these at "zero demand" learns to see a local bound to a literal — its table went from 3 rows to 7
- the bindings answer in 1.12's own shapes: Button:IsEnabled() answers the NUMBER 1 or 0 (0 is truthy in Lua, so the reference's own == 0 tests got false forever, and three of our files had hand-worked around the divergence rather than fixed it); the constructors' string arguments are four shapes, not one rule — pfUI passes a Button where a template name goes and the reference constructs the FontString and ignores it; SetInventoryItem returns THREE values, the reference's own paper doll destructuring repairCost; UnitIsVisible is object presence and nothing else (57 bytes, one branch, no distance — an out-of-range party member is exists-yes, visible-nil); the tapped pair reads the two dynamic-flags bits, and its repaint wire fires UNIT_FACTION on the tap bit — the half a passing predicate test never sees; UnitIsPartyLeader is two ORed legs covering disjoint failures (a held stranger leading their own party, and an out-of-range member with no object to read a flag from); and the four nameplate verbs take no argument and return zero values
- the ghost's wisps compose onto its body instead of over it — the four emitters drew at full strength over a body at alpha 0.5, and now inherit the instance alpha down the attachment chain the way the reference recomposes it per frame; the residual we had parked ("the wisps should inherit the tint too") is REFUTED at the bytes: a particle batch commits hardcoded white RGB, and even that never reaches the fragment — particles are never tinted, only the alpha crosses, applied to the alpha byte alone — so the shipped shader split was already right and no code changes

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 20:15:16 +07:00

177 lines
10 KiB
XML

<!--
OUR adapters over the reference's own `Interface\FrameXML\ContainerFrame.lua`.
**This client does not transcribe that file — it EXECUTES it, off the player's own patch
chain**, before any of our `assets/ui` files (`ui_script::reference_ui`, whose header carries
the rule and the licensing reason: Blizzard's Lua is never committed here). What is in THIS
file is only benilla's, and only where a reference body reaches for something this client
genuinely does not have.
The rule, restated in one line so it can be applied without re-reading the module: the sourced
file's globals stand unmodified; ours (loading after) win where both define a name; and where a
reference body needs a benilla answer, it is WRAPPED here — never silently stubbed.
── The one adapter, and why it is not a stub ────────────────────────────────────────────────
`ContainerFrameItemButton_OnEnter` opens with a keyring fork (ref l.615-620):
if this:GetParent():GetID() == KEYRING_CONTAINER then
GameTooltip:SetInventoryItem("player", KeyRingButtonIDToInvSlotID(this:GetID()))
CursorUpdate()
return
end
That fork exists because the REAL client's keyring items are inventory slots, not container
slots, so it has to detour out of the container API to describe one. benilla's keyring is an
ordinary container (id -2, decision 0765): its slots come through `GetContainerItemInfo` and
`GameTooltip:SetBagItem` like every other bag's. So the detour is not merely unavailable here
(`KeyRingButtonIDToInvSlotID` is not a binding here; `CursorUpdate` now is, transcribed from
UIParent.lua into UiPanels.xml, so only half the detour is missing) — it is *wrong* here,
and supplying the two verbs would buy an empty tooltip, because our keyring items were never
fed into the inventory-slot space it reads.
So the wrapper below answers the keyring case the way benilla answers every other bag, and
hands EVERY other slot straight to the reference's own body. The path the player is actually
on — hovering an ordinary bag slot — runs the real client's code, unedited.
── Named, not hidden: what still does not work through the sourced file ─────────────────────
· `MerchantItemButton_OnClick`. The reference's `ContainerFrameItemButton_OnClick` closes its
shift-right-click-at-a-vendor arm with a `SplitStack` closure that calls that global, and
benilla's merchant window publishes `BenillaMerchantItem_OnClick` instead. Confirming a stack
split with a vendor open therefore raises. That is the same "a Benilla name shadows the
reference's" class this whole seam exists to close, one window over, and it is left loud
rather than guarded (1203): the fix is to publish the merchant global, not to hide the call.
· `REPAIR_COST` is read by the reference's repair-mode arm. It is a `GlobalStrings.lua` key and
this client sources that file too, so it resolves at runtime — and the arm is unreachable
today regardless, since `GameTooltip:SetBagItem`'s repairCost is an INTERIM 0.
-->
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script><![CDATA[
-- The reference's own body, captured before we shadow the name. Nil on a machine with no
-- client data (nothing was sourced) — which must be LOUD at the call, not a quiet no-op:
-- a bag hover that silently does nothing is precisely the failure mode that let Bagnon
-- ship "working" through four green survey columns.
local refItemButtonOnEnter = ContainerFrameItemButton_OnEnter
function ContainerFrameItemButton_OnEnter(button)
if not button then
button = this
end
if not button then return end
-- benilla's keyring is a CONTAINER (0765), so the reference's inventory-slot detour is
-- both unavailable and wrong here; this is the same pair of calls its general path
-- makes for every other bag, which is all a keyring slot ever needed.
if button:GetParent():GetID() == KEYRING_CONTAINER then
if (button:GetRight() or 0) >= (GetScreenWidth() / 2) then
GameTooltip:SetOwner(button, "ANCHOR_LEFT")
else
GameTooltip:SetOwner(button, "ANCHOR_RIGHT")
end
GameTooltip:SetBagItem(KEYRING_CONTAINER, button:GetID())
ResetCursor()
return
end
if not refItemButtonOnEnter then
message("benilla: Interface\\FrameXML\\ContainerFrame.lua was not sourced from the "
.. "game data, so bag-slot tooltips cannot work. Check the client data path.")
return
end
refItemButtonOnEnter(button)
end
-- ── `updateContainerFrameAnchors` — a no-op here, and that IS the benilla answer ────────
-- The reference's body (l.480-489) opens `while ContainerFrame1.bags[index] do` and walks
-- the twelve `ContainerFrame1..12` windows it owns, positioning each into columns. benilla
-- does not build those windows at all — our bags are `BagFrame.xml`'s own, and they
-- position themselves. `ui_script::manifest` already records the same difference one
-- function over: *"ToggleBackpack walks twelve ContainerFrames we do not build; ours walks
-- our windows."*
--
-- So this is not a stub standing in for something missing: there is nothing here for it to
-- anchor, and the reference body raises `attempt to index global 'ContainerFrame1'` the
-- moment anything calls it. FIVE corpus addons did — Bongos, Bongos_ActionBar and the
-- CT_BarMod family all HOOK it (`BLIZZARD_Original_updateContainerFrameAnchors` in the
-- traceback) and then call through, so the raise landed inside a Blizzard file with our
-- bag layout nowhere in the stack.
--
-- Deliberately silent rather than warned: an addon calling this on every bag update would
-- turn a warn-once into a warn-always, and unlike the cases in the section above nothing is
-- LOST by doing nothing — the windows it would have moved are already where our own layout
-- put them. The header's "never silently stubbed" rule is about absent capability; this is
-- present capability with a different owner.
function updateContainerFrameAnchors()
end
]]></Script>
<!-- ── The reference's item-button TEMPLATE, which the sourced file cannot bring ────────────
`ui_script::reference_ui` sources `ContainerFrame.lua`, so every handler named below is
the reference's own live code, not a transcription. It cannot source `ContainerFrame.xml`
— that file also declares the twelve `ContainerFrame1..12` windows this client does not
build — so the template that BINDS those handlers to a shape was the one missing piece.
Declaring it here is the smallest thing that closes the gap, and it goes in THIS file
because this is where reference container behaviour that needs a benilla answer lives.
Ref ContainerFrame.xml l.4-60, verbatim but for the one deviation named below. Loads after
ItemButtonTemplate.xml (its base, toc l.45) and after Cooldown.xml (CooldownFrameTemplate,
toc l.124) — both are why this cannot simply sit next to the base.
pfUI is the measured caller: `CreateFrame("Button", name, pfUI.bags[bag], tpl)`
(modules/bags.lua l.381) died on "Couldn't find inherited node" and took its whole bag
module with it. It then reads `$parentCooldown`, `$parentCount`, `$parentIconTexture` and
`$parentNormalTexture` straight off what it just built, and installs NO scripts of its own
on the slot — so the handlers below are not decoration, they are what makes a pfUI bag
respond to a click at all.
DEVIATION, named: the reference's OnEnter/OnDragStart/OnReceiveDrag/OnClick each open with
a KeyRing fork keyed on `KEYRING_CONTAINER`. Those bodies are the SOURCED ones and they
keep their fork; what this file's header explains at length is that our keyring is an
ordinary container (0765), so the fork is wrong here rather than merely unavailable, and
the adapter above is what answers it. Nothing new is introduced by this template. -->
<Button name="ContainerFrameItemButtonTemplate" inherits="ItemButtonTemplate" hidden="true" virtual="true">
<Anchors>
<Anchor point="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="0"/></Offset></Anchor>
</Anchors>
<Frames>
<Model name="$parentCooldown" inherits="CooldownFrameTemplate"/>
</Frames>
<Scripts>
<OnLoad>ContainerFrameItemButton_OnLoad();</OnLoad>
<OnClick>
if ( this:GetParent():GetID() == KEYRING_CONTAINER ) then
KeyRingItemButton_OnClick(arg1);
return;
end
ContainerFrameItemButton_OnClick(arg1);
</OnClick>
<OnEnter>ContainerFrameItemButton_OnEnter();</OnEnter>
<OnLeave>
this.updateTooltip = nil;
GameTooltip:Hide();
ResetCursor();
</OnLeave>
<OnHide>
if ( this.hasStackSplit and (this.hasStackSplit == 1) ) then
StackSplitFrame:Hide();
end
</OnHide>
<OnDragStart>
if ( this:GetParent():GetID() == KEYRING_CONTAINER ) then
KeyRingItemButton_OnClick("LeftButton", 1);
return;
end
ContainerFrameItemButton_OnClick("LeftButton", 1);
</OnDragStart>
<OnReceiveDrag>
if ( this:GetParent():GetID() == KEYRING_CONTAINER ) then
KeyRingItemButton_OnClick("LeftButton", 1);
return;
end
ContainerFrameItemButton_OnClick("LeftButton", 1);
</OnReceiveDrag>
<OnUpdate>ContainerFrameItemButton_OnUpdate(arg1);</OnUpdate>
</Scripts>
</Button>
</Ui>