diff --git a/ClassicAPI.lua b/ClassicAPI.lua index b0897b6..a2cf514 100644 --- a/ClassicAPI.lua +++ b/ClassicAPI.lua @@ -3,11 +3,16 @@ ClassicAPI is a client mod (sibling to Nampower/SuperWoW) that backports the modern C_* API into the 1.12.1 Lua environment. It is a HARD REQUIREMENT of - this addon (ClassicAPI v1.12.1+, which added the positional - C_UnitAuras.UnitAura), so the wrappers below call the API directly — no - fallbacks. The load-time requirement check (Core.lua) uses IsAvailable() to - warn when the DLL is missing and HasMinimumVersion() when it's too old; users - who don't want ClassicAPI should run the upstream addon. + this addon (ClassicAPI v1.15.0+, which added frame:RegisterUnitEvent), so the + wrappers below call the API directly — no fallbacks. The load-time requirement + check (Core.lua) uses IsAvailable() to warn when the DLL is missing and + HasMinimumVersion() when it's too old; users who don't want ClassicAPI should + run the upstream addon. + + The minimum is not advisory: Utility.lua calls frame:RegisterUnitEvent at file + scope, so an older ClassicAPI aborts that chunk and leaves most of the addon + undefined. Raise the Core.lua minimum in step with any new API adopted at file + scope. Detection: the global CLASSIC_API_VERSION is defined once the client has booted, encoded as X*10000 + Y*100 + Z for a vX.Y.Z tag (untagged dev builds @@ -37,6 +42,14 @@ function API.GetVersionNumber() return CLASSIC_API_VERSION or 0 end +-- Returns the loaded version as major, minor, patch (0, 0, 0 if absent). +function API.GetVersion() + local v = CLASSIC_API_VERSION or 0 + local major = math.floor(v / 10000) + local minor = math.floor(v / 100) - major * 100 + return major, minor, v - math.floor(v / 100) * 100 +end + -- True if the ClassicAPI client mod is loaded at all. function API.IsAvailable() return CLASSIC_API_VERSION ~= nil @@ -56,7 +69,7 @@ end -- Scan one aura range of `unit` (filter = "HELPFUL" or "HARMFUL") for an aura -- matching the dispel type. Uses the positional C_UnitAuras.UnitAura (added in --- ClassicAPI v1.12.1, this addon's minimum) -- no table allocated per slot, with +-- ClassicAPI v1.12.1, below this addon's minimum) -- no table allocated per slot, with -- dispelName as the 4th return. The filtered index self-terminates at the end of -- the range (nil name); 48 is a backstop over vanilla's 32 helpful / 16 harmful slots. local function scanDispel(unit, filter, dispelType, wantAny) diff --git a/Core.lua b/Core.lua index 91de01d..27251b6 100644 --- a/Core.lua +++ b/Core.lua @@ -198,10 +198,12 @@ requirementCheckFrame:SetScript("OnEvent", function() local hasNampower30 = hasNampower and CleveRoids.NampowerAPI and CleveRoids.NampowerAPI.HasMinimumVersion(3, 0, 0) local hasClassicAPI = CleveRoids.ClassicAPI and CleveRoids.ClassicAPI.IsAvailable() - -- v1.12.1 added the positional C_UnitAuras.UnitAura the dispel conditionals use. - local hasClassicAPI1121 = hasClassicAPI and CleveRoids.ClassicAPI.HasMinimumVersion(1, 12, 1) + -- v1.15.0 added frame:RegisterUnitEvent, which Utility.lua calls at file scope. + -- On an older build that call raises, aborting the rest of the chunk -- so this + -- is not a degraded-features warning, it's "the addon did not finish loading". + local hasClassicAPI1150 = hasClassicAPI and CleveRoids.ClassicAPI.HasMinimumVersion(1, 15, 0) - if not hasNampower30 or not hasUnitXP or not hasClassicAPI or not hasClassicAPI1121 then + if not hasNampower30 or not hasUnitXP or not hasClassicAPI or not hasClassicAPI1150 then -- Show warnings (don't disable — tearing down a partially-initialized addon causes hangs) if not hasNampower then CleveRoids.Print("|cFFFF9900WARNING:|r |cFF00FFFFAvitasia's Nampower v3.0.0+|r is required:") @@ -221,10 +223,11 @@ requirementCheckFrame:SetScript("OnEvent", function() CleveRoids.Print("|cFFFF9900WARNING:|r |cFF00FFFFClassicAPI|r is required:") CleveRoids.Print("https://github.com/brues-code/ClassicAPI") CleveRoids.Print("Dispel-type and movement conditionals will be unavailable without it.") - elseif not hasClassicAPI1121 then - CleveRoids.Print("|cFFFF9900WARNING:|r |cFF00FFFFClassicAPI v1.12.1+|r is required:") + elseif not hasClassicAPI1150 then + local major, minor, patch = CleveRoids.ClassicAPI.GetVersion() + CleveRoids.Print(format("|cFFFF9900WARNING:|r |cFF00FFFFClassicAPI v1.15.0+|r is required (you have v%d.%d.%d):", major, minor, patch)) CleveRoids.Print("https://github.com/brues-code/ClassicAPI") - CleveRoids.Print("Dispel-type conditionals will be unavailable with this older version.") + CleveRoids.Print("The addon cannot finish loading on this version -- update ClassicAPI.") end end @@ -1139,7 +1142,7 @@ local publishedDisplay = {} -- nothing matched" and shows the question mark. Skipping the call instead would hand -- the macro back to ClassicAPI's own #showtooltip parser. function CleveRoids.PublishDisplay(actions) - if not CleveRoids.useClassicAPIDisplay then return end + if not CleveRoids.ClassicAPIMacroDisplay then return end local macroID = actions and actions.macroID if not macroID then return end -- SuperMacro macros have no Blizzard index @@ -1154,7 +1157,7 @@ end -- ClassicAPI re-evaluates nothing for us. Covers macros that aren't on a bar too, -- which is what keeps the macro window grid's icons correct. function CleveRoids.PublishAllDisplays() - if not CleveRoids.useClassicAPIDisplay then return end + if not CleveRoids.ClassicAPIMacroDisplay then return end -- Forget what we published so every macro republishes once. Callers reach here -- after login and after a re-parse, where a cached value could otherwise -- suppress the publish a freshly rebuilt macro still needs. @@ -1169,13 +1172,12 @@ end -- Hand every macro back to ClassicAPI's own parser and stop claiming ownership. function CleveRoids.ReleaseDisplays() - if not CleveRoids.useClassicAPIDisplay then return end + if not CleveRoids.ClassicAPIMacroDisplay then return end for i = 1, 36 do C_Macro.SetMacroDisplay(i, nil) end publishedDisplay = {} CleveRoids.ClassicAPIMacroDisplay = false - CleveRoids.useClassicAPIDisplay = false end -- PERFORMANCE: Static buffer references for hot path @@ -1221,17 +1223,10 @@ function CleveRoids.TestForAllActiveActions() local slots = actionsToSlots[actions] local stateChanged = CleveRoids.TestForActiveAction(actions) if stateChanged then - if CleveRoids.useClassicAPIDisplay then - -- Publishing repaints every slot holding this macro through the - -- client's own notifier, so the per-slot fan-out below is redundant. - CleveRoids.PublishDisplay(actions) - else - -- Send event to ALL slots that use this macro - local count = slots._count - for j = 1, count do - CleveRoids.SendEventForAction(slots[j], "ACTIONBAR_SLOT_CHANGED", slots[j]) - end - end + -- Publishing repaints every slot holding this macro through the client's + -- own notifier, so there is no per-slot fan-out to do here. It no-ops once + -- ReleaseDisplays has handed the macros back. + CleveRoids.PublishDisplay(actions) end -- Clear for reuse (reset count and clear buffer reference) for j = 1, slots._count do diff --git a/Init.lua b/Init.lua index e716c27..72e250e 100644 --- a/Init.lua +++ b/Init.lua @@ -29,14 +29,17 @@ CleveRoids.supported = CleveRoids.hasTurtle -- tooltip, cooldown sweep, range and usable state all come from the client -- including -- the drag cursor and the macro window grid, which Lua cannot reach. -- --- Feature-detect rather than version-check: the API is unreleased, so --- CLASSIC_API_VERSION reports the dev sentinel. ClassicAPI stands down from macro --- display entirely when it sees this addon loaded; ClassicAPIMacroDisplay is what --- tells it we drive it instead. A fork that leaves the flag unset keeps the old --- behavior -- both must never drive the same buttons. -CleveRoids.useClassicAPIDisplay = +-- ClassicAPI stands down from macro display entirely when it sees this addon loaded; +-- ClassicAPIMacroDisplay is what tells it we drive it instead, and ReleaseDisplays +-- clears it to hand every macro back. A fork that leaves the flag unset keeps the old +-- behavior -- both must never drive the same buttons. It doubles as the internal +-- "may we call C_Macro.SetMacroDisplay" guard, so the two can never disagree. +-- +-- Feature-detect rather than version-check: SetMacroDisplay ships in ClassicAPI +-- v1.15.0, this addon's minimum, so a nil here means the client mod is missing +-- outright -- the case Core.lua's requirement check warns about but keeps running. +CleveRoids.ClassicAPIMacroDisplay = (type(C_Macro) == "table" and C_Macro.SetMacroDisplay ~= nil) and true or false -CleveRoids.ClassicAPIMacroDisplay = CleveRoids.useClassicAPIDisplay CleveRoids.ParsedMsg = {} CleveRoids.ExpandedGroups = {} diff --git a/README.md b/README.md index dbd54b6..686f836 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Enhanced macro addon for World of Warcraft 1.12.1 (Vanilla/Turtle WoW) with dyna |-----|:--------:|---------| | [Nampower](https://github.com/brues-code/nampower/releases) (v3.0.0+) | ✅ | Spell queueing, DBC data, auto-attack events | | [UnitXP_SP3](https://codeberg.org/konaka/UnitXP_SP3/releases) | ✅ | Distance checks, `[multiscan]` enemy scanning | -| [ClassicAPI](https://github.com/brues-code/ClassicAPI/releases) | ✅ | Modern `C_*` API: dispel-type conditionals (`[magic]`, `[curse]`, …), `[moving]` speed | +| [ClassicAPI](https://github.com/brues-code/ClassicAPI/releases) (v1.15.0+) | ✅ | Modern `C_*` API: dispel-type conditionals (`[magic]`, `[curse]`, …), `[moving]` speed, unit-filtered events | ## Installation