From f37ea0022689c27472fded423952f9c533f15957 Mon Sep 17 00:00:00 2001 From: Brues <5278969+brues-code@users.noreply.github.com> Date: Fri, 30 Oct 2026 12:37:56 -0500 Subject: [PATCH] Give pfUI its own EventRegistry and move event-only frames onto it pfUI.events was a bare CallbackRegistry for pfUI's custom events. Build it from ClassicAPI's EventRegistry instead, so the same object also takes game events through RegisterFrameEventAndCallback, sharing one frame for all of them. Move the frames that existed only to listen for a few events onto it: libspell, focus, pixelperfect, innervatecall, loothistory, unusable, equipmentmanager (bank + window refresh), the actionbar grid, updatenotify, turtle-wow's steady shot, nampower's spell queue, superwow's group tracking and unitxp's notifications, plus newitem and mapreveal, which used the global EventRegistry. Handlers take their payload as arguments instead of the event/arg globals, and the per-frame PLAYER_LOGOUT teardown goes away, since the registry unregisters its frame on logout. --- libs/libspell.lua | 4 +-- modules/actionbar.lua | 21 +++-------- modules/equipmentmanager.lua | 40 ++++++++++----------- modules/focus.lua | 4 +-- modules/innervatecall.lua | 19 ++++------ modules/loothistory.lua | 18 +++++----- modules/mapreveal.lua | 2 +- modules/nampower.lua | 14 +------- modules/newitem.lua | 2 +- modules/pixelperfect.lua | 4 +-- modules/superwow.lua | 21 ++++------- modules/turtle-wow.lua | 6 +--- modules/unitxp.lua | 22 ++++-------- modules/unusable.lua | 15 ++++---- modules/updatenotify.lua | 69 +++++++++++++++++------------------- pfUI.lua | 6 ++-- 16 files changed, 101 insertions(+), 166 deletions(-) diff --git a/libs/libspell.lua b/libs/libspell.lua index c02724e3..9077144b 100644 --- a/libs/libspell.lua +++ b/libs/libspell.lua @@ -116,9 +116,7 @@ function libspell.GetSpellInfo(index, bookType) end -- Reset all spell caches whenever new spells are learned/unlearned -local resetcache = CreateFrame("Frame") -resetcache:RegisterEvent("LEARNED_SPELL_IN_TAB") -resetcache:SetScript("OnEvent", function() +pfUI.events:RegisterFrameEventAndCallback("LEARNED_SPELL_IN_TAB", function() table.wipe(spellmaxrank) table.wipe(spellindex) table.wipe(spellinfo) diff --git a/modules/actionbar.lua b/modules/actionbar.lua index bd12bbc3..13089716 100644 --- a/modules/actionbar.lua +++ b/modules/actionbar.lua @@ -1502,23 +1502,10 @@ pfUI:RegisterModule("actionbar", function () _G.ShapeshiftBar_ChangeForm = function(slot) pfActionButton(slot, nil, "ShapeShiftBar") end -- handle drag-drop grid - local grid = CreateFrame("Frame") - grid:RegisterEvent("ACTIONBAR_SHOWGRID") - grid:RegisterEvent("ACTIONBAR_HIDEGRID") - grid:RegisterEvent("PET_BAR_SHOWGRID") - grid:RegisterEvent("PET_BAR_HIDEGRID") - - grid:SetScript("OnEvent", function() - if event == "ACTIONBAR_SHOWGRID" then - pfUI.bars:UpdateGrid(1) - elseif event == "ACTIONBAR_HIDEGRID" then - pfUI.bars:UpdateGrid(0) - elseif event == "PET_BAR_SHOWGRID" then - pfUI.bars:UpdateGrid(1, "PET") - elseif event == "PET_BAR_HIDEGRID" then - pfUI.bars:UpdateGrid(0, "PET") - end - end) + pfUI.events:RegisterFrameEventAndCallback("ACTIONBAR_SHOWGRID", function() pfUI.bars:UpdateGrid(1) end) + pfUI.events:RegisterFrameEventAndCallback("ACTIONBAR_HIDEGRID", function() pfUI.bars:UpdateGrid(0) end) + pfUI.events:RegisterFrameEventAndCallback("PET_BAR_SHOWGRID", function() pfUI.bars:UpdateGrid(1, "PET") end) + pfUI.events:RegisterFrameEventAndCallback("PET_BAR_HIDEGRID", function() pfUI.bars:UpdateGrid(0, "PET") end) -- reagent counter if C.bars.reagents == "1" then diff --git a/modules/equipmentmanager.lua b/modules/equipmentmanager.lua index b1847fa2..b32e8ad0 100644 --- a/modules/equipmentmanager.lua +++ b/modules/equipmentmanager.lua @@ -1243,23 +1243,22 @@ pfUI:RegisterModule("equipmentmanager", function() UpdateBagHighlights() end) - local bankEvents = CreateFrame("Frame") - bankEvents:RegisterEvent("BANKFRAME_OPENED") - bankEvents:RegisterEvent("BANKFRAME_CLOSED") - bankEvents:RegisterEvent("PLAYERBANKSLOTS_CHANGED") - bankEvents:RegisterEvent("BAG_UPDATE_DELAYED") - bankEvents:RegisterEvent("EQUIPMENT_SETS_CHANGED") - bankEvents:SetScript("OnEvent", function() - if event == "BANKFRAME_OPENED" then - bankOpen = true - elseif event == "BANKFRAME_CLOSED" then - bankOpen = false - return - end + local function RescanBank() if not bankOpen then return end ScanBank() if frame:IsShown() then pfUI.equipmentmanager.Refresh() end + end + + pfUI.events:RegisterFrameEventAndCallback("BANKFRAME_OPENED", function() + bankOpen = true + RescanBank() end) + pfUI.events:RegisterFrameEventAndCallback("BANKFRAME_CLOSED", function() + bankOpen = false + end) + for _, event in ipairs({ "PLAYERBANKSLOTS_CHANGED", "BAG_UPDATE_DELAYED", "EQUIPMENT_SETS_CHANGED" }) do + pfUI.events:RegisterFrameEventAndCallback(event, RescanBank) + end -- ============================================================ -- Automatic set switching (triggers) @@ -2084,15 +2083,14 @@ pfUI:RegisterModule("equipmentmanager", function() -- Events -- ============================================================ - local events = CreateFrame("Frame") - events:RegisterEvent("EQUIPMENT_SETS_CHANGED") - events:RegisterEvent("EQUIPMENT_SWAP_FINISHED") - events:RegisterEvent("EQUIPMENT_SWAP_PENDING") - events:RegisterEvent("BAG_UPDATE_DELAYED") - events:RegisterEvent("PLAYER_EQUIPMENT_CHANGED") - events:SetScript("OnEvent", function() + local function RefreshShown() if not frame:IsShown() then return end pfUI.equipmentmanager.Refresh() - end) + end + + for _, event in ipairs({ "EQUIPMENT_SETS_CHANGED", "EQUIPMENT_SWAP_FINISHED", "EQUIPMENT_SWAP_PENDING", + "BAG_UPDATE_DELAYED", "PLAYER_EQUIPMENT_CHANGED" }) do + pfUI.events:RegisterFrameEventAndCallback(event, RefreshShown) + end end) diff --git a/modules/focus.lua b/modules/focus.lua index 9cb51504..dbb17e75 100644 --- a/modules/focus.lua +++ b/modules/focus.lua @@ -18,9 +18,7 @@ pfUI:RegisterModule("focus", function () -- Between events, ClassicAPI fires UNIT_* (health/mana/aura/...) with -- arg1 == "focus" and arg1 == "focustarget", so both frames update -- event-driven like target and need no polling tick. - local refresher = CreateFrame("Frame") - refresher:RegisterEvent("PLAYER_FOCUS_CHANGED") - refresher:SetScript("OnEvent", function() + pfUI.events:RegisterFrameEventAndCallback("PLAYER_FOCUS_CHANGED", function() pfUI.uf.focus.instantRefresh = true pfUI.uf:RefreshUnit(pfUI.uf.focus, "all") pfUI.uf.focustarget.instantRefresh = true diff --git a/modules/innervatecall.lua b/modules/innervatecall.lua index 118c0a20..902c020d 100644 --- a/modules/innervatecall.lua +++ b/modules/innervatecall.lua @@ -46,22 +46,17 @@ pfUI:RegisterModule("innervatecall", function () end) end - local frame = CreateFrame("Frame") - frame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") - frame:RegisterEvent("SPELL_UPDATE_COOLDOWN") - frame:SetScript("OnEvent", function() - if event == "SPELL_UPDATE_COOLDOWN" then - if pending then ScheduleReady() end - return - end + pfUI.events:RegisterFrameEventAndCallback("SPELL_UPDATE_COOLDOWN", function() + if pending then ScheduleReady() end + end) + pfUI.events:RegisterFrameEventAndCallback("COMBAT_LOG_EVENT_UNFILTERED", function() -- Innervate is instant, so it logs SPELL_CAST_SUCCESS with its target - -- arg2=subevent, arg4=sourceGUID, arg9=destName, arg12=spellId - if arg2 ~= "SPELL_CAST_SUCCESS" or arg12 ~= INNERVATE_SPELLID then return end + local _, subevent, _, sourceGUID, _, _, _, _, destName, _, _, spellId = CombatLogGetCurrentEventInfo() + if subevent ~= "SPELL_CAST_SUCCESS" or spellId ~= INNERVATE_SPELLID then return end -- Only announce our own casts - if not IsPlayerGuid(arg4) then return end - local destName = arg9 + if not IsPlayerGuid(sourceGUID) then return end -- Determine channel local channel = GetAnnounceChannel() diff --git a/modules/loothistory.lua b/modules/loothistory.lua index 0ab168a7..f471339d 100644 --- a/modules/loothistory.lua +++ b/modules/loothistory.lua @@ -318,20 +318,18 @@ pfUI:RegisterModule("loothistory", function () -- ========================================================================== -- Events -- ========================================================================== - local events = CreateFrame("Frame") - events:RegisterEvent("LOOT_HISTORY_FULL_UPDATE") - events:RegisterEvent("LOOT_HISTORY_ROLL_CHANGED") - events:RegisterEvent("LOOT_HISTORY_ROLL_COMPLETE") - events:SetScript("OnEvent", function() - -- auto-show on a new roll opening / completing, if enabled - if C.loothistory.autoshow == "1" - and (event == "LOOT_HISTORY_FULL_UPDATE" or event == "LOOT_HISTORY_ROLL_COMPLETE") - and not pfUI.loothistory:IsShown() then + -- auto-show on a new roll opening / completing, if enabled + local function AutoShow() + if C.loothistory.autoshow == "1" and not pfUI.loothistory:IsShown() then pfUI.loothistory:Show() -- OnShow runs FullUpdate return end FullUpdate() -- no-op while hidden - end) + end + + pfUI.events:RegisterFrameEventAndCallback("LOOT_HISTORY_FULL_UPDATE", AutoShow) + pfUI.events:RegisterFrameEventAndCallback("LOOT_HISTORY_ROLL_COMPLETE", AutoShow) + pfUI.events:RegisterFrameEventAndCallback("LOOT_HISTORY_ROLL_CHANGED", FullUpdate) -- ========================================================================== -- Slash command diff --git a/modules/mapreveal.lua b/modules/mapreveal.lua index da777af8..cb2361bd 100644 --- a/modules/mapreveal.lua +++ b/modules/mapreveal.lua @@ -180,7 +180,7 @@ pfUI:RegisterModule("mapreveal", function () -- above, so nothing is redrawn while the map is closed — the next open -- rebuilds from the current state. - EventRegistry:RegisterFrameEventAndCallback("MAP_EXPLORATION_UPDATED", function() + pfUI.events:RegisterFrameEventAndCallback("MAP_EXPLORATION_UPDATED", function() if WorldMapFrame and WorldMapFrame:IsShown() then pfWorldMapFrame_Update() end diff --git a/modules/nampower.lua b/modules/nampower.lua index 040db1a4..f5c30558 100644 --- a/modules/nampower.lua +++ b/modules/nampower.lua @@ -41,19 +41,7 @@ pfUI:RegisterModule("nampower", function () local NON_GCD_QUEUED = 4 local NON_GCD_QUEUE_POPPED = 5 - local queue = CreateFrame("Frame") - queue:RegisterEvent("SPELL_QUEUE_EVENT") - queue:RegisterEvent("PLAYER_LOGOUT") - queue:SetScript("OnEvent", function() - -- Handle shutdown to prevent crash 132 - if event == "PLAYER_LOGOUT" then - this:UnregisterAllEvents() - this:SetScript("OnEvent", nil) - return - end - - local eventCode, spellId = arg1, arg2 - + pfUI.events:RegisterFrameEventAndCallback("SPELL_QUEUE_EVENT", function(_, eventCode, spellId) if eventCode == NORMAL_QUEUED or eventCode == NON_GCD_QUEUED or eventCode == ON_SWING_QUEUED then local texture = C_Spell.GetSpellTexture(spellId) if texture then diff --git a/modules/newitem.lua b/modules/newitem.lua index 5024db5b..76724981 100644 --- a/modules/newitem.lua +++ b/modules/newitem.lua @@ -57,7 +57,7 @@ pfUI:RegisterModule("newitem", function () pfUI.newitem:UpdateSlot(bag, slot) end) - EventRegistry:RegisterFrameEventAndCallback("BAG_NEW_ITEMS_UPDATED", function() + pfUI.events:RegisterFrameEventAndCallback("BAG_NEW_ITEMS_UPDATED", function() pfUI.newitem:RefreshAll() end) diff --git a/modules/pixelperfect.lua b/modules/pixelperfect.lua index 337f970c..872b5d37 100644 --- a/modules/pixelperfect.lua +++ b/modules/pixelperfect.lua @@ -33,9 +33,7 @@ pfUI:RegisterModule("pixelperfect", function () -- pixelperfect: native UIScale listener if tonumber(C.global.pixelperfect) > 0 then - local f = CreateFrame("Frame") - f:RegisterEvent("PLAYER_ENTERING_WORLD") - f:SetScript("OnEvent", pixelperfect) + pfUI.events:RegisterFrameEventAndCallback("PLAYER_ENTERING_WORLD", pixelperfect) pixelperfect() end diff --git a/modules/superwow.lua b/modules/superwow.lua index cbc4a136..a3eb69e6 100644 --- a/modules/superwow.lua +++ b/modules/superwow.lua @@ -95,20 +95,7 @@ pfUI:RegisterModule("superwow", function () -- TrackUnit API for adding group members to minimap -- Tracks friendly units on the minimap for easier group coordination if TrackUnit and C.unitframes.track_group == "1" then - local trackFrame = CreateFrame("Frame") - trackFrame:RegisterEvent("PARTY_MEMBERS_CHANGED") - trackFrame:RegisterEvent("RAID_ROSTER_UPDATE") - trackFrame:RegisterEvent("PLAYER_ENTERING_WORLD") - trackFrame:RegisterEvent("PLAYER_LOGOUT") - - trackFrame:SetScript("OnEvent", function() - -- Handle shutdown to prevent crash 132 - if event == "PLAYER_LOGOUT" then - this:UnregisterAllEvents() - this:SetScript("OnEvent", nil) - return - end - + local function TrackGroup() -- Track party members for i = 1, 4 do local unit = "party" .. i @@ -124,7 +111,11 @@ pfUI:RegisterModule("superwow", function () pcall(TrackUnit, unit) end end - end) + end + + pfUI.events:RegisterFrameEventAndCallback("PARTY_MEMBERS_CHANGED", TrackGroup) + pfUI.events:RegisterFrameEventAndCallback("RAID_ROSTER_UPDATE", TrackGroup) + pfUI.events:RegisterFrameEventAndCallback("PLAYER_ENTERING_WORLD", TrackGroup) end -- Raid Marker Targeting API diff --git a/modules/turtle-wow.lua b/modules/turtle-wow.lua index e2b1dded..28a66d6f 100644 --- a/modules/turtle-wow.lua +++ b/modules/turtle-wow.lua @@ -247,11 +247,7 @@ pfUI:RegisterModule("turtle-wow", function () local STEADY_SHOT_DURATION_MS = 1400 -- not haste-scaled; close enough for the visual cue local ON_SWING_QUEUED, ON_SWING_QUEUE_POPPED = 0, 1 - local steadyShot = CreateFrame("Frame") - steadyShot:RegisterEvent("SPELL_QUEUE_EVENT") - steadyShot:SetScript("OnEvent", function() - if event ~= "SPELL_QUEUE_EVENT" then return end - local eventCode, spellId = arg1, arg2 + pfUI.events:RegisterFrameEventAndCallback("SPELL_QUEUE_EVENT", function(_, eventCode, spellId) if eventCode ~= ON_SWING_QUEUED and eventCode ~= ON_SWING_QUEUE_POPPED then return end if C_Spell.GetSpellName(spellId) ~= steadyShotName then return end if eventCode == ON_SWING_QUEUED then diff --git a/modules/unitxp.lua b/modules/unitxp.lua index ecfbc76e..f6682778 100644 --- a/modules/unitxp.lua +++ b/modules/unitxp.lua @@ -253,24 +253,14 @@ pfUI:RegisterModule("unitxp", function () -- OS Notification Support if C.unitframes.unitxp_notify == "1" then - local notifyFrame = CreateFrame("Frame") - notifyFrame:RegisterEvent("CHAT_MSG_WHISPER") - notifyFrame:RegisterEvent("CHAT_MSG_BN_WHISPER") - notifyFrame:RegisterEvent("READY_CHECK") - notifyFrame:RegisterEvent("RAID_INSTANCE_WELCOME") - notifyFrame:RegisterEvent("PLAYER_LOGOUT") - - notifyFrame:SetScript("OnEvent", function() - -- Handle shutdown to prevent crash 132 - if event == "PLAYER_LOGOUT" then - this:UnregisterAllEvents() - this:SetScript("OnEvent", nil) - return - end - + local function Notify() pcall(UnitXP, "notify", "taskbarIcon") pcall(UnitXP, "notify", "systemSound") - end) + end + + for _, event in ipairs({ "CHAT_MSG_WHISPER", "CHAT_MSG_BN_WHISPER", "READY_CHECK", "RAID_INSTANCE_WELCOME" }) do + pfUI.events:RegisterFrameEventAndCallback(event, Notify) + end -- Also notify on BG queue pop local origBattlefieldPortShow = BattlefieldFrame_Show diff --git a/modules/unusable.lua b/modules/unusable.lua index b17ca3ef..930f60b7 100644 --- a/modules/unusable.lua +++ b/modules/unusable.lua @@ -38,13 +38,7 @@ pfUI:RegisterModule("unusable", function () -- requirement changes (level, proficiency/skill, required spell, reputation, -- honor rank) don't touch the bags; queue a full rebag through pfUI.bag's -- coalesced delay, whose UpdateSlot resets the tint before we reapply it - local refresh = CreateFrame("Frame") - refresh:RegisterEvent("PLAYER_LEVEL_UP") - refresh:RegisterEvent("SKILL_LINES_CHANGED") - refresh:RegisterEvent("SPELLS_CHANGED") - refresh:RegisterEvent("FACTION_STANDING_CHANGED") - refresh:RegisterEvent("PLAYER_PVP_RANK_CHANGED") - refresh:SetScript("OnEvent", function() + local function Refresh() for _, bag in pairs(pfUI.BACKPACK) do pfUI.bag.delay.UpdateBag[bag] = true end @@ -54,5 +48,10 @@ pfUI:RegisterModule("unusable", function () pfUI.bag.delay.UpdateBag[bag] = true end end - end) + end + + for _, event in ipairs({ "PLAYER_LEVEL_UP", "SKILL_LINES_CHANGED", "SPELLS_CHANGED", + "FACTION_STANDING_CHANGED", "PLAYER_PVP_RANK_CHANGED" }) do + pfUI.events:RegisterFrameEventAndCallback(event, Refresh) + end end) diff --git a/modules/updatenotify.lua b/modules/updatenotify.lua index aefe5997..a53bd9e2 100644 --- a/modules/updatenotify.lua +++ b/modules/updatenotify.lua @@ -12,44 +12,41 @@ pfUI:RegisterModule("updatenotify", function () local localbranch = "main" local versionmsg = "VERSION:" .. localversion .. ":" .. localbranch - pfUI.updater = CreateFrame("Frame") - pfUI.updater:RegisterEvent("CHAT_MSG_ADDON") - pfUI.updater:RegisterEvent("PLAYER_ENTERING_WORLD") - pfUI.updater:RegisterEvent("PARTY_MEMBERS_CHANGED") - pfUI.updater:SetScript("OnEvent", function() - if event == "CHAT_MSG_ADDON" and arg1 == ADDON_PREFIX then - local v, rv, branch = pfUI.api.strsplit(":", arg2) - rv = tonumber(rv) - -- only process VERSION messages from the same branch - -- messages without a branch tag (old versions) are ignored - if v == "VERSION" and rv and branch == localbranch then - if rv > localversion then - pfUI_init.updateavailable = rv - end - end - end + pfUI.events:RegisterFrameEventAndCallback("CHAT_MSG_ADDON", function(_, prefix, message) + if prefix ~= ADDON_PREFIX then return end - if event == "PARTY_MEMBERS_CHANGED" then - local groupsize = IsInRaid() and GetNumRaidMembers() or IsInGroup() and GetNumPartyMembers() or 0 - if ( this.group or 0 ) < groupsize then - for _, chan in pairs(groupchannels) do - SendAddonMessage(ADDON_PREFIX, versionmsg, chan) - end - end - this.group = groupsize - end - - if event == "PLAYER_ENTERING_WORLD" then - if not alreadyshown and localversion < remoteversion then - DEFAULT_CHAT_FRAME:AddMessage(string.format(T["|cff33ffccpf|rUI: New version available! Get it at %s"], GetAddOnMetadata(pfUI.name, "X-Website") .. "/releases")) - DEFAULT_CHAT_FRAME:AddMessage(T["|cffddddddIt's always safe to upgrade |cff33ffccpf|rUI. |cffddddddYou won't lose any of your configuration."]) - pfUI_init.updateavailable = localversion - alreadyshown = true - end - - for _, chan in pairs(loginchannels) do - SendAddonMessage(ADDON_PREFIX, versionmsg, chan) + local v, rv, branch = pfUI.api.strsplit(":", message) + rv = tonumber(rv) + -- only process VERSION messages from the same branch + -- messages without a branch tag (old versions) are ignored + if v == "VERSION" and rv and branch == localbranch then + if rv > localversion then + pfUI_init.updateavailable = rv end end end) + + local group = 0 + pfUI.events:RegisterFrameEventAndCallback("PARTY_MEMBERS_CHANGED", function() + local groupsize = IsInRaid() and GetNumRaidMembers() or IsInGroup() and GetNumPartyMembers() or 0 + if group < groupsize then + for _, chan in pairs(groupchannels) do + SendAddonMessage(ADDON_PREFIX, versionmsg, chan) + end + end + group = groupsize + end) + + pfUI.events:RegisterFrameEventAndCallback("PLAYER_ENTERING_WORLD", function() + if not alreadyshown and localversion < remoteversion then + DEFAULT_CHAT_FRAME:AddMessage(string.format(T["|cff33ffccpf|rUI: New version available! Get it at %s"], GetAddOnMetadata(pfUI.name, "X-Website") .. "/releases")) + DEFAULT_CHAT_FRAME:AddMessage(T["|cffddddddIt's always safe to upgrade |cff33ffccpf|rUI. |cffddddddYou won't lose any of your configuration."]) + pfUI_init.updateavailable = localversion + alreadyshown = true + end + + for _, chan in pairs(loginchannels) do + SendAddonMessage(ADDON_PREFIX, versionmsg, chan) + end + end) end) diff --git a/pfUI.lua b/pfUI.lua index 2edd8564..f7122474 100644 --- a/pfUI.lua +++ b/pfUI.lua @@ -52,9 +52,11 @@ pfUI.env = {} -- the flag; one that lacks it should drop the flag and get the safe fallback. pfUI.handlesHookScript = true -pfUI.events = Mixin({}, CallbackRegistryMixin) +-- pfUI's own EventRegistry: carries pfUI's custom events ("bag:closed", +-- "config:changed", ...) and game events alike. Register game events with +-- RegisterFrameEventAndCallback instead of creating a frame per listener. +pfUI.events = CreateFromMixins(EventRegistry) pfUI.events:OnLoad() -pfUI.events:SetUndefinedEventsAllowed(true) -- check if macro addons are loaded (disables macrotweak/macroscan) function pfUI:MacroAddonsLoaded()