From cd2a99bd02bc03703c80b96425e14ef27f092bb8 Mon Sep 17 00:00:00 2001 From: Florian Berthold Date: Mon, 25 May 2026 12:04:14 +0200 Subject: [PATCH] fix(CoAAuraConditionals): stop refreshing on PLAYER_ENTERING_WORLD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calling bar:UpdateStates() on every zone load was the most likely path to the "AddOn 'Bartender4' prevented the call of the secure function 'SecureStateDriverManager:SetAttribute()'" warning — RegisterStateDriver runs internally and every zone fired it across all bars, sometimes while Bartender's own init was still resolving secure state. - Drop PLAYER_ENTERING_WORLD as a trigger. Bartender's own init handles the initial state; UPDATE_SHAPESHIFT_FORMS fires when forms become resolvable on login, so the original intent still holds. - Cache the shapeshift-form signature and skip the refresh if it hasn't actually changed since last run. Avoids redundant secure attribute churn from routine UPDATE_SHAPESHIFT_FORMS spam. - Combat-lockdown guard + PLAYER_REGEN_ENABLED queue-drain unchanged. --- Bartender4/CoAAuraConditionals.lua | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/Bartender4/CoAAuraConditionals.lua b/Bartender4/CoAAuraConditionals.lua index 646fc60..a6fec89 100644 --- a/Bartender4/CoAAuraConditionals.lua +++ b/Bartender4/CoAAuraConditionals.lua @@ -91,11 +91,31 @@ end -- spec respec, etc.) so freshly-resolvable names take effect without -- a /reload. Skipped during combat lockdown — RegisterStateDriver is -- secure and the SetAttribute calls inside UpdateStates would taint. +-- +-- Triggers: UPDATE_SHAPESHIFT_FORMS (the form set actually changed) +-- and PLAYER_REGEN_ENABLED (drain a refresh queued during combat). +-- PLAYER_ENTERING_WORLD is deliberately NOT a trigger — Bartender's +-- own init handles the initial state, and firing UpdateStates on every +-- zone risked re-entering secure paths while Bartender was mid-flux, +-- producing "prevented the call of SecureStateDriverManager:SetAttribute". local refresh = CreateFrame("Frame") refresh:RegisterEvent("UPDATE_SHAPESHIFT_FORMS") -refresh:RegisterEvent("PLAYER_ENTERING_WORLD") refresh:RegisterEvent("PLAYER_REGEN_ENABLED") + +local lastFormSignature local pendingRefresh = false + +local function currentFormSignature() + if type(GetNumShapeshiftForms) ~= "function" then return "" end + local n = GetNumShapeshiftForms() or 0 + local parts = {} + for i = 1, n do + local _, fname = GetShapeshiftFormInfo(i) + parts[#parts + 1] = fname or "" + end + return table.concat(parts, "|") +end + refresh:SetScript("OnEvent", function(self, event) if InCombatLockdown and InCombatLockdown() then pendingRefresh = true @@ -103,6 +123,14 @@ refresh:SetScript("OnEvent", function(self, event) end if event == "PLAYER_REGEN_ENABLED" and not pendingRefresh then return end pendingRefresh = false + + -- Skip the refresh entirely if the form set hasn't changed since + -- last run. Avoids redundant RegisterStateDriver churn on routine + -- UPDATE_SHAPESHIFT_FORMS spam. + local sig = currentFormSignature() + if sig == lastFormSignature then return end + lastFormSignature = sig + local mod = Bartender4 and Bartender4.GetModule and Bartender4:GetModule("ActionBars", true) if not mod or not mod.actionbars then return end for _, bar in pairs(mod.actionbars) do