From c8bc4c134d8d0e0d37dee8be166259525d8e807d Mon Sep 17 00:00:00 2001 From: Brues <5278969+brues-code@users.noreply.github.com> Date: Fri, 11 Sep 2026 00:42:42 -0500 Subject: [PATCH] Filter UNIT_AURA by unit token and drop the unit streams in realtime mode Two handlers opened by testing arg1 against a fixed set of unit tokens, so every other unit's copy of UNIT_AURA reached Lua only to be compared away -- in a raid that is the bulk of them. ClassicAPI's RegisterUnitEvent pushes that filter into the client, so the handler only runs for the units named. Filtering is per (frame, event), so the other events sharing the libdebuff frame are unaffected. Utility.lua UNIT_AURA -> "target" (libdebuff seeding) ComboPointTracker UNIT_AURA -> "target", "player" Extensions register through CleveRoids.RegisterEvent, so ExtensionsManager gains a RegisterUnitEvent alongside it. Separately, the main frame's unit state streams (UNIT_AURA / UNIT_HEALTH / UNIT_POWER, or the _GUID variants under Nampower v2.39+) are now registered only in event-driven mode. Their handlers are wholly wrapped in `realtime == 0`, so with realtime on every one of them crossed into Lua and returned immediately while the OnUpdate did the refreshing. Registration is applied at load, again at VARIABLES_LOADED once the saved setting is readable, and whenever /cleveroid realtime flips it. Those three stay plain RegisterEvent calls: their handlers ignore the unit and refresh every macro, and a conditional may name any unit ([@party3,hp:<50], @focus, @mouseover), so narrowing the token set would leave those icons stale. The _GUID variants could not be filtered anyway -- their first argument is a GUID, not a unit token. --- ComboPointTracker.lua | 8 ++++---- Core.lua | 42 +++++++++++++++++++++++++++++++++--------- ExtensionsManager.lua | 18 ++++++++++++++++++ Utility.lua | 4 ++-- 4 files changed, 57 insertions(+), 15 deletions(-) diff --git a/ComboPointTracker.lua b/ComboPointTracker.lua index 23d8e17..11f229d 100644 --- a/ComboPointTracker.lua +++ b/ComboPointTracker.lua @@ -745,7 +745,7 @@ function Extension.OnLoad() Extension.RegisterEvent("SPELLCAST_FAILED", "OnSpellcastFailed") Extension.RegisterEvent("SPELLCAST_INTERRUPTED", "OnSpellcastInterrupted") Extension.RegisterEvent("PLAYER_TARGET_CHANGED", "OnTargetChanged") - Extension.RegisterEvent("UNIT_AURA", "OnUnitAura") + Extension.RegisterUnitEvent("UNIT_AURA", "OnUnitAura", "target", "player") Extension.RegisterEvent("PLAYER_COMBO_POINTS", "OnComboPointsChanged") -- PERFORMANCE OPTIMIZATION: Removed OnUpdate polling for combo points @@ -765,10 +765,10 @@ function Extension.OnTargetChanged() CleveRoids.UpdateComboPoints() end +-- Registered as a unit event for target and player, so arg1 is always one of +-- those two -- no token check needed. function Extension.OnUnitAura() - if arg1 == "target" or arg1 == "player" then - CleveRoids.UpdateComboPoints() - end + CleveRoids.UpdateComboPoints() end function Extension.OnComboPointsChanged() diff --git a/Core.lua b/Core.lua index 97eea0a..91de01d 100644 --- a/Core.lua +++ b/Core.lua @@ -591,6 +591,10 @@ frame:SetScript("OnEvent", function() if type(CleveRoidMacros.macrocheck) ~= "number" then CleveRoidMacros.macrocheck = 1 -- enabled by default end + + -- The saved realtime setting is only readable now; the unit streams were + -- registered at load assuming event-driven mode. + CleveRoids.ApplyUnitStreamEvents() end) -- Queues a full update of all action bars. @@ -4464,18 +4468,36 @@ if type(C_LossOfControl) == "table" then CleveRoids.Frame:RegisterEvent("LOSS_OF_CONTROL_ADDED") CleveRoids.Frame:RegisterEvent("LOSS_OF_CONTROL_UPDATE") end --- Use GUID events when available (v2.39+), fall back to standard per-token events +-- The unit state streams that drive icon refresh: GUID events when Nampower +-- provides them (v2.39+, one event per unit change rather than one per token), +-- else the stock per-token events. These cannot become RegisterUnitEvent calls +-- -- the handlers ignore the unit and refresh every macro, because a conditional +-- may name any unit ([@party3,hp:<50], @focus, @mouseover), so narrowing the +-- token set would leave those icons stale. +local unitStreamEvents if CleveRoids.NampowerAPI.features.hasUnitGuidEvents then - CleveRoids.Frame:RegisterEvent("UNIT_AURA_GUID") - CleveRoids.Frame:RegisterEvent("UNIT_HEALTH_GUID") - CleveRoids.Frame:RegisterEvent("UNIT_MANA_GUID") - CleveRoids.Frame:RegisterEvent("UNIT_RAGE_GUID") - CleveRoids.Frame:RegisterEvent("UNIT_ENERGY_GUID") + unitStreamEvents = { "UNIT_AURA_GUID", "UNIT_HEALTH_GUID", "UNIT_MANA_GUID", "UNIT_RAGE_GUID", "UNIT_ENERGY_GUID" } else - CleveRoids.Frame:RegisterEvent("UNIT_AURA") - CleveRoids.Frame:RegisterEvent("UNIT_HEALTH") - CleveRoids.Frame:RegisterEvent("UNIT_POWER") + unitStreamEvents = { "UNIT_AURA", "UNIT_HEALTH", "UNIT_POWER" } end + +-- They do fire continuously for every unit in range, and in realtime mode their +-- handlers do nothing at all: the OnUpdate refreshes on every throttled tick and +-- QueueActionUpdate no-ops. Rather than pay a Lua dispatch per event to return +-- early, drop the registrations entirely while realtime is on. Re-applied at +-- VARIABLES_LOADED (when the saved value is first known) and whenever +-- `/cleveroid realtime` flips it. +function CleveRoids.ApplyUnitStreamEvents() + local eventDriven = not CleveRoidMacros or CleveRoidMacros.realtime == 0 + for i = 1, table.getn(unitStreamEvents) do + if eventDriven then + CleveRoids.Frame:RegisterEvent(unitStreamEvents[i]) + else + CleveRoids.Frame:UnregisterEvent(unitStreamEvents[i]) + end + end +end +CleveRoids.ApplyUnitStreamEvents() if CleveRoids.hasSuperwow then CleveRoids.Frame:RegisterEvent("UNIT_CASTEVENT") end @@ -5808,6 +5830,8 @@ SlashCmdList["CLEVEROID"] = function(msg) local num = tonumber(val) if num == 0 or num == 1 then CleveRoidMacros.realtime = num + -- The unit streams are only worth receiving in event-driven mode. + CleveRoids.ApplyUnitStreamEvents() CleveRoids.Print("realtime set to " .. num) else CleveRoids.Print("Usage: /cleveroid realtime 0 or 1 - Force realtime updates rather than event based updates (Default: 0. 1 = on, increases CPU load.)") diff --git a/ExtensionsManager.lua b/ExtensionsManager.lua index b0cb84f..ff6a62a 100644 --- a/ExtensionsManager.lua +++ b/ExtensionsManager.lua @@ -66,6 +66,10 @@ function CleveRoids.RegisterExtension(name) CleveRoids.RegisterEvent(name, eventName, callbackName) end + extension.RegisterUnitEvent = function(eventName, callbackName, ...) + CleveRoids.RegisterUnitEvent(name, eventName, callbackName, unpack(arg)) + end + extension.Hook = function(functionName, callbackName, dontCallOriginal) CleveRoids.RegisterHook(name, functionName, callbackName, dontCallOriginal) end @@ -146,6 +150,20 @@ function CleveRoids.RegisterEvent(extensionName, eventName, callbackName) extension.internal.frame:RegisterEvent(eventName) end +-- Registers a callback for a UNIT_* event, filtered to the given unit tokens. +-- The callback then only runs for those units: the client drops every other +-- unit's copy, instead of all of them reaching Lua to be compared away. Use +-- this over RegisterEvent whenever the handler starts by testing arg1. +-- extensionName: The name of the extension trying to register the callback +-- eventName: The UNIT_* event to register +-- callbackName: The name of the callback that gets called when the event fires +-- ...: the unit tokens to accept (e.g. "player", "target") +function CleveRoids.RegisterUnitEvent(extensionName, eventName, callbackName, ...) + local extension = CleveRoids.Extensions[extensionName] + extension.internal.eventHandlers[eventName] = callbackName + extension.internal.frame:RegisterUnitEvent(eventName, unpack(arg)) +end + -- Hooks the given function by it's name -- extensionName: The name of the extension trying to register the callback -- functionName: The name of the function that'll be hooked diff --git a/Utility.lua b/Utility.lua index 72a4297..419a631 100644 --- a/Utility.lua +++ b/Utility.lua @@ -4115,7 +4115,7 @@ end) local ev = CreateFrame("Frame", "CleveRoidsLibDebuffFrame", UIParent) ev:RegisterEvent("PLAYER_TARGET_CHANGED") -ev:RegisterEvent("UNIT_AURA") +ev:RegisterUnitEvent("UNIT_AURA", "target") ev:RegisterEvent("ADDON_LOADED") -- For pfUI integration initialization ev:RegisterEvent("ZONE_CHANGED_NEW_AREA") -- Clear known enemy GUIDs on zone change @@ -4214,7 +4214,7 @@ ev:SetScript("OnEvent", function() end SeedUnit("target") - elseif event == "UNIT_AURA" and arg1 == "target" then + elseif event == "UNIT_AURA" then SeedUnit("target") elseif event == "UNIT_CASTEVENT" then