fix: migrate CLEU to unit events on retail 12.0+ (#22)#24
Conversation
Retail 12.0 (Midnight) marks COMBAT_LOG_EVENT_UNFILTERED with HasRestrictions = true, raising ADDON_ACTION_FORBIDDEN on insecure registration. This breaks DragonShout on retail 12.0+: interrupts, CC announcements, and dispels all stop working. The capability flag ns.capabilities.combatLog (set in Lifecycle.Initialize) now selects between two source modules instead of toggling features off: - CombatLogListener (existing, Classic + pre-12.0 retail) registers COMBAT_LOG_EVENT_UNFILTERED and dispatches by subevent. - UnitEventListener (new, retail 12.0+) registers UNIT_SPELLCAST_INTERRUPTED, UNIT_AURA, and UNIT_SPELLCAST_SUCCEEDED against tracked unit tokens (player + pet + party + raid). Both source modules feed identical payload tables into the existing handlers (OnInterrupt, OnAuraApplied, OnDispel). Handler signatures refactored from positional CLEU args to a single payload table. Aura cache (owned by AuraListener) supports dispel correlation: UNIT_SPELLCAST_SUCCEEDED for player dispel casts is bound to a target only when UNIT_AURA fires removedAuraInstanceIDs on a friendly unit within 600 ms. Capability gaps accepted on retail 12.0+: - Loss of ~50 yd CLEU global scope (unit-token scoped only). - Interrupter's spell name no longer available (default interrupts template adjusted to read sensibly without it). - Hostile-source aura data may be redacted in instances. - No UNIT_DISPEL event - dispel detection is correlation-based. Closes #22 # Conflicts: # DragonShout/Core/Init.lua # DragonShout/Listeners/AuraListener.lua # DragonShout/Locales/enUS.lua
|
Warning Rate limit exceeded
To continue reviewing without waiting, purchase usage credits in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Repository YAML (base), Organization UI (inherited) Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (13)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Cleanup leftover design notes from abandoned PR #24 that documented a ns.capabilities.combatLog gate and UnitEventListener module which were never merged. PR #26 fixes #22 via a private CreateFrame frame to escape shared AceEvent30Frame taint; the prior Midnight/HasRestrictions diagnosis was incorrect.
…) (#26) * fix: avoid AceEvent shared-frame taint for combat log registration (#22) Replace addon:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED", ...) with a private, unnamed CreateFrame("Frame") + OnEvent script. The shared AceEvent30Frame can be tainted by upstream addons via CallbackHandler's OnUsed lazy-registration path, which then blocks any first-time event registration from clean addons with ADDON_ACTION_FORBIDDEN. Using a private unnamed frame for CLEU isolates DragonShout from this class of cross-addon taint. The one-shot PLAYER_LOGIN registration in Core/Lifecycle.lua remains on AceEvent - it's rarely the first registrant and degrades gracefully. See .deliverables/tech-lead/ADR-0001-dragonshout-aceevent-taint.md * docs: remove stale UnitEventListener/capabilities prose (#22) Cleanup leftover design notes from abandoned PR #24 that documented a ns.capabilities.combatLog gate and UnitEventListener module which were never merged. PR #26 fixes #22 via a private CreateFrame frame to escape shared AceEvent30Frame taint; the prior Midnight/HasRestrictions diagnosis was incorrect. * feat: add UnitEventListener for retail Midnight CLEU restrictions (#28) (#29) Retail patch 12.0 (Midnight, Interface 120000+) suppresses COMBAT_LOG_EVENT_UNFILTERED for addons - the event registers but never fires. Route interrupt and CC-on-player detection through UNIT_* events on affected clients while leaving Classic (MoP, TBC Anniversary) on the identical CLEU code path. Per ADR-0002: - New Core/Capabilities.lua exposes ns.capabilities.cleuRestricted, set at file scope from (C_RestrictedActions ~= nil) AND mainline build >= 120000. - New Listeners/UnitEventListener.lua: private unnamed CreateFrame (mirrors PR #26 anti-taint pattern), registers UNIT_SPELLCAST_INTERRUPTED and UNIT_AURA. Translates payloads into the CLEU-shaped positional tuple the existing handlers consume, plus a trailing 'extras' table for spell info (CombatLogGetCurrentEventInfo is not the source of truth on Midnight). - CombatLogListener.Initialize/Shutdown self-gate on cleuRestricted - no CLEU registration on retail Midnight. - InterruptListener.OnInterrupt and AuraListener.OnAuraApplied gain an optional trailing 'extras' parameter. When nil (Classic forwarding via CombatLogListener), behavior is unchanged. - Both dispatchers are always in LISTENER_MODULES; each self-gates on ns.capabilities inside its own Initialize. Dropped on retail Midnight (no clean attribution event): - dispels: DispelListener stays on disk but is never invoked. - ccApplied (CC the player lands on others): sourceUnit on AuraData is unreliable. Files added: Core/Capabilities.lua, Listeners/UnitEventListener.lua. Files modified: Core/Init.lua, DragonShout.toc, .luacheckrc, Listeners/{CombatLogListener,InterruptListener,AuraListener}.lua. Refs: #28, ADR-0002
Type of change
Description
Retail 12.0 (Midnight) marks
COMBAT_LOG_EVENT_UNFILTEREDwithHasRestrictions = true(verified against Blizzard's publishedBlizzardInterfaceCode/Interface/AddOns/Blizzard_APIDocumentationGenerated/CombatLogDocumentation.lualines 119-128), causingADDON_ACTION_FORBIDDENon insecure registration. This breaks DragonShout on retail 12.0+: interrupts, CC announcements, and dispels all stop working.This is a one-PR full migration (not gate-only). The capability flag
ns.capabilities.combatLog(set inLifecycle.Initialize) now selects between two source modules:CombatLogListener(existing, Classic + pre-12.0 retail) registersCOMBAT_LOG_EVENT_UNFILTEREDand dispatches by subevent.UnitEventListener(new, retail 12.0+) registersUNIT_SPELLCAST_INTERRUPTED,UNIT_AURA, andUNIT_SPELLCAST_SUCCEEDEDagainst tracked unit tokens (player + pet + party + raid).Both source modules feed identical payload tables into the existing handlers (
OnInterrupt,OnAuraApplied,OnDispel). Handler signatures refactored from positional CLEU args to a single payload table.The aura cache (owned by
AuraListener) supports dispel correlation:UNIT_SPELLCAST_SUCCEEDEDfor player dispel casts is bound to a target only whenUNIT_AURAfiresremovedAuraInstanceIDson a friendly unit within 600 ms.Capability gaps disclosed (retail 12.0+)
UNIT_SPELLCAST_INTERRUPTEDpayload (defaultinterrupts.templateadjusted to read sensibly without it).AuraData.sourceUnitnil).UNIT_DISPELevent - dispel detection is inferential via cast + aura-removal correlation.Testing
mise exec -- luacheck .passes (0 warnings / 0 errors in 31 files)./ds status: should showCombat-log listener: activeon Classic andUnit-event listener: activeon retail 12.0+.Open questions worth user review
interrupts.templatechanged from"Interrupted {target}'s {extraSpell} with {spell}!"to"Interrupted {target}'s {extraSpell}!". Existing user profiles untouched (no SavedVariables migration); only new profiles get the new default.Checklist
Closes #22