mirror of
https://github.com/brues-code/pfUI.git
synced 2026-10-17 18:20:49 +00:00
Gracefully disable pfUI when ClassicAPI is missing
Add API_Check.lua as the first TOC entry. When the ClassicAPI DLL is absent or below the minimum version it sets pfUI_disabled and stands up an inert stub so the rest of the addon no-ops instead of flooding load errors: modules and skins register their bodies into no-ops, and the setfenv'd api/lib files run inside an environment where CreateFrame and any missing global resolve to a null object -- so no real frames or live handlers are created and missing API calls just return null. pfUI.lua bails early on pfUI_disabled.
This commit is contained in:
+104
@@ -0,0 +1,104 @@
|
|||||||
|
do
|
||||||
|
-- ClassicAPI dependency check.
|
||||||
|
-- pfUI relies pervasively on the modern C_* / SuperWoW / nameplate / focus
|
||||||
|
-- API surface that ClassicAPI polyfills, so presence is required.
|
||||||
|
local PFUI_CLASSIC_API_MIN = 11301 -- (X*10000 + Y*100 + Z)
|
||||||
|
local PFUI_CLASSIC_API_LATEST = PFUI_CLASSIC_API_MIN
|
||||||
|
local PFUI_CLASSIC_API_WEBSITE = "https://github.com/brues-code/ClassicAPI"
|
||||||
|
local PFUI_CLASSIC_API_LATEST_URL = PFUI_CLASSIC_API_WEBSITE .. "/releases/latest"
|
||||||
|
local function FormatVersion(packed)
|
||||||
|
local x = math.floor(packed / 10000)
|
||||||
|
local y = math.floor(math.mod(packed, 10000) / 100)
|
||||||
|
local z = math.mod(packed, 100)
|
||||||
|
return string.format("v%d.%d.%d", x, y, z)
|
||||||
|
end
|
||||||
|
if not CLASSIC_API_VERSION or CLASSIC_API_VERSION < PFUI_CLASSIC_API_MIN then
|
||||||
|
local minVersion = FormatVersion(PFUI_CLASSIC_API_MIN)
|
||||||
|
pfUI_disabled = true
|
||||||
|
pfUI_locale = {}
|
||||||
|
pfUI_profiles = {}
|
||||||
|
pfUI_translation = {}
|
||||||
|
|
||||||
|
-- ClassicAPI is required. Rather than let the ~140 files that follow flood
|
||||||
|
-- errors as they load, stand up an inert stub so everything no-ops:
|
||||||
|
-- * modules/skins register their body into a no-op, so it never runs;
|
||||||
|
-- * the setfenv'd api/lib files run inside `env`, where CreateFrame and
|
||||||
|
-- any missing global (C_*, SuperWoW, ...) resolve to a null object --
|
||||||
|
-- so no real frames or live OnUpdate/OnEvent handlers get created and
|
||||||
|
-- missing API calls just return null instead of erroring.
|
||||||
|
local null -- forward declaration so the metamethods can return it
|
||||||
|
local nullmt = {
|
||||||
|
__index = function() return null end,
|
||||||
|
__newindex = function() end,
|
||||||
|
__call = function() return null end,
|
||||||
|
__concat = function() return "" end,
|
||||||
|
__tostring = function() return "" end,
|
||||||
|
}
|
||||||
|
for _, op in ipairs({ "__add","__sub","__mul","__div","__mod","__pow","__unm" }) do
|
||||||
|
nullmt[op] = function() return null end
|
||||||
|
end
|
||||||
|
for _, op in ipairs({ "__lt","__le","__eq" }) do nullmt[op] = function() return false end end
|
||||||
|
null = setmetatable({}, nullmt)
|
||||||
|
|
||||||
|
local realG = getfenv(0)
|
||||||
|
pfUI = setmetatable({}, { __index = function() return null end })
|
||||||
|
pfUI.env = setmetatable({}, {
|
||||||
|
__index = function(_, k)
|
||||||
|
if k == "CreateFrame" then return function() return null end end
|
||||||
|
local v = realG[k]
|
||||||
|
if v ~= nil then return v end
|
||||||
|
return null
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
function pfUI:RegisterModule(_, _, _) end
|
||||||
|
function pfUI:RegisterSkin(_, _, _) end
|
||||||
|
function pfUI:GetEnvironment() return pfUI.env end
|
||||||
|
local detail
|
||||||
|
if not CLASSIC_API_VERSION then
|
||||||
|
detail = "The ClassicAPI DLL isn't loaded. The |cff33ffcc!!!ClassicAPI|r addon ships bundled with it -- delete your |cff33ffcc!!!ClassicAPI|r folder and install the latest release from:"
|
||||||
|
else
|
||||||
|
detail = "ClassicAPI " .. minVersion .. " or newer is required. Delete your |cff33ffcc!!!ClassicAPI|r folder and reinstall the latest release from:"
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ShowRequiredPopup()
|
||||||
|
StaticPopupDialogs["PFUI_CLASSICAPI_REQUIRED"] = {
|
||||||
|
text = "|cff33ffccpf|cffffffffUI|r has been disabled.\n\n" .. detail,
|
||||||
|
button1 = OKAY,
|
||||||
|
hasEditBox = 1,
|
||||||
|
editBoxWidth = 280,
|
||||||
|
timeout = 0,
|
||||||
|
whileDead = 1,
|
||||||
|
hideOnEscape = 1,
|
||||||
|
preferredIndex = 3,
|
||||||
|
OnShow = function()
|
||||||
|
local editBox = getglobal(this:GetName().."EditBox")
|
||||||
|
if editBox then
|
||||||
|
editBox:SetText(PFUI_CLASSIC_API_LATEST_URL)
|
||||||
|
editBox:HighlightText()
|
||||||
|
editBox:SetFocus()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
StaticPopup_Show("PFUI_CLASSICAPI_REQUIRED")
|
||||||
|
DEFAULT_CHAT_FRAME:AddMessage(
|
||||||
|
"|cff33ffccpf|cffffffffUI|r disabled: " .. detail .. " " .. PFUI_CLASSIC_API_LATEST_URL,
|
||||||
|
1, 0.3, 0.3
|
||||||
|
)
|
||||||
|
end
|
||||||
|
local loginFrame = CreateFrame("Frame")
|
||||||
|
loginFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||||
|
loginFrame:SetScript("OnEvent", function()
|
||||||
|
loginFrame:UnregisterEvent("PLAYER_ENTERING_WORLD")
|
||||||
|
ShowRequiredPopup()
|
||||||
|
end)
|
||||||
|
elseif CLASSIC_API_VERSION < PFUI_CLASSIC_API_LATEST then
|
||||||
|
EventUtil.ContinueOnPlayerLogin(function()
|
||||||
|
C_Timer.After(8, function()
|
||||||
|
DEFAULT_CHAT_FRAME:AddMessage(
|
||||||
|
"|cff33ffccpf|rUI: ClassicAPI " .. FormatVersion(PFUI_CLASSIC_API_LATEST) .. " is available — " .. PFUI_CLASSIC_API_LATEST_URL,
|
||||||
|
1, 0.85, 0.3
|
||||||
|
)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -3,6 +3,10 @@ function SlashCmdList.RELOAD(msg, editbox)
|
|||||||
ReloadUI()
|
ReloadUI()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if pfUI_disabled then return end
|
||||||
|
|
||||||
|
local addonName = ...
|
||||||
|
|
||||||
SLASH_PFUI1 = '/pfui'
|
SLASH_PFUI1 = '/pfui'
|
||||||
function SlashCmdList.PFUI(msg, editbox)
|
function SlashCmdList.PFUI(msg, editbox)
|
||||||
pfUI.gui:SetShown(not pfUI.gui:IsShown())
|
pfUI.gui:SetShown(not pfUI.gui:IsShown())
|
||||||
@@ -13,7 +17,7 @@ function SlashCmdList.GM(msg, editbox)
|
|||||||
ToggleHelpFrame(1)
|
ToggleHelpFrame(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
pfUI = CreateFrame("Frame", nil, UIParent)
|
local pfUI = CreateFrame("Frame", addonName, UIParent)
|
||||||
pfUI:RegisterEvent("ADDON_LOADED")
|
pfUI:RegisterEvent("ADDON_LOADED")
|
||||||
|
|
||||||
-- setup bootvar
|
-- setup bootvar
|
||||||
@@ -117,35 +121,24 @@ pfUI.env = {}
|
|||||||
-- the flag; one that lacks it should drop the flag and get the safe fallback.
|
-- the flag; one that lacks it should drop the flag and get the safe fallback.
|
||||||
pfUI.handlesHookScript = true
|
pfUI.handlesHookScript = true
|
||||||
|
|
||||||
if not pfUI.disabled then
|
pfUI.events = Mixin({}, CallbackRegistryMixin)
|
||||||
pfUI.events = Mixin({}, CallbackRegistryMixin)
|
pfUI.events:OnLoad()
|
||||||
pfUI.events:OnLoad()
|
pfUI.events:SetUndefinedEventsAllowed(true)
|
||||||
pfUI.events:SetUndefinedEventsAllowed(true)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- check if macro addons are loaded (disables macrotweak/macroscan)
|
-- check if macro addons are loaded (disables macrotweak/macroscan)
|
||||||
function pfUI:MacroAddonsLoaded()
|
function pfUI:MacroAddonsLoaded()
|
||||||
return IsAddOnLoaded("Supermacro") or IsAddOnLoaded("SuperCleveRoidMacros") or IsAddOnLoaded("UltimaMacros")
|
return IsAddOnLoaded("Supermacro") or IsAddOnLoaded("SuperCleveRoidMacros") or IsAddOnLoaded("UltimaMacros")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- detect current addon path
|
pfUI.name = addonName
|
||||||
local tocs = { "", "-master", "-tbc", "-wotlk" }
|
pfUI.path = "Interface\\AddOns\\" .. addonName
|
||||||
for _, name in pairs(tocs) do
|
|
||||||
local current = string.format("pfUI%s", name)
|
|
||||||
local title = C_AddOns.GetAddOnName(current)
|
|
||||||
if title then
|
|
||||||
pfUI.name = current
|
|
||||||
pfUI.path = "Interface\\AddOns\\" .. current
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- handle/convert media dir paths
|
-- handle/convert media dir paths
|
||||||
pfUI.media = setmetatable({}, { __index = function(tab,key)
|
pfUI.media = setmetatable({}, { __index = function(tab,key)
|
||||||
local value = tostring(key)
|
local value = tostring(key)
|
||||||
if strfind(value, "img:") then
|
if value:find("img:") then
|
||||||
value = string.gsub(value, "img:", pfUI.path .. "\\img\\")
|
value = string.gsub(value, "img:", pfUI.path .. "\\img\\")
|
||||||
elseif strfind(value, "font:") then
|
elseif value:find("font:") then
|
||||||
value = string.gsub(value, "font:", pfUI.path .. "\\fonts\\")
|
value = string.gsub(value, "font:", pfUI.path .. "\\fonts\\")
|
||||||
else
|
else
|
||||||
value = string.gsub(value, "Interface\\AddOns\\pfUI\\", pfUI.path .. "\\")
|
value = string.gsub(value, "Interface\\AddOns\\pfUI\\", pfUI.path .. "\\")
|
||||||
@@ -154,9 +147,7 @@ pfUI.media = setmetatable({}, { __index = function(tab,key)
|
|||||||
return value
|
return value
|
||||||
end})
|
end})
|
||||||
|
|
||||||
-- cache client version
|
pfUI.client = INTERFACE_VERSION
|
||||||
local _, _, _, client = GetBuildInfo()
|
|
||||||
pfUI.client = client or 11200
|
|
||||||
|
|
||||||
-- setup pfUI namespace
|
-- setup pfUI namespace
|
||||||
setmetatable(pfUI.env, {__index = getfenv(0)})
|
setmetatable(pfUI.env, {__index = getfenv(0)})
|
||||||
@@ -390,14 +381,13 @@ function pfUI:CheckNewModules()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function BackwardsCompatRegister(func, arg3)
|
local function BackwardsCompatRegister(func, arg3)
|
||||||
if arg3 and type(func) == "string" and type(arg3) == "function" and string.find(func, "vanilla") then
|
if arg3 and type(func) == "string" and type(arg3) == "function" and func:find("vanilla") then
|
||||||
return arg3
|
return arg3
|
||||||
end
|
end
|
||||||
return func
|
return func
|
||||||
end
|
end
|
||||||
|
|
||||||
function pfUI:RegisterModule(name, func, arg3)
|
function pfUI:RegisterModule(name, func, arg3)
|
||||||
if pfUI.disabled then return end
|
|
||||||
if pfUI.module[name] then return end
|
if pfUI.module[name] then return end
|
||||||
func = BackwardsCompatRegister(func, arg3)
|
func = BackwardsCompatRegister(func, arg3)
|
||||||
pfUI.module[name] = func
|
pfUI.module[name] = func
|
||||||
@@ -408,7 +398,6 @@ function pfUI:RegisterModule(name, func, arg3)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function pfUI:RegisterSkin(name, func, arg3)
|
function pfUI:RegisterSkin(name, func, arg3)
|
||||||
if pfUI.disabled then return end
|
|
||||||
if pfUI.skin[name] then return end
|
if pfUI.skin[name] then return end
|
||||||
func = BackwardsCompatRegister(func, arg3)
|
func = BackwardsCompatRegister(func, arg3)
|
||||||
pfUI.skin[name] = func
|
pfUI.skin[name] = func
|
||||||
@@ -429,7 +418,6 @@ function pfUI:LoadSkin(s)
|
|||||||
end
|
end
|
||||||
|
|
||||||
pfUI:SetScript("OnEvent", function()
|
pfUI:SetScript("OnEvent", function()
|
||||||
if pfUI.disabled then return end
|
|
||||||
|
|
||||||
-- make sure to initialize and set our fonts
|
-- make sure to initialize and set our fonts
|
||||||
-- each time an addon got loaded but only
|
-- each time an addon got loaded but only
|
||||||
@@ -443,7 +431,7 @@ pfUI:SetScript("OnEvent", function()
|
|||||||
-- "@project-version@" until release tooling substitutes it — mark those
|
-- "@project-version@" until release tooling substitutes it — mark those
|
||||||
-- explicitly as "dev" instead of pretending they're a real numbered build.
|
-- explicitly as "dev" instead of pretending they're a real numbered build.
|
||||||
local raw = tostring(GetAddOnMetadata(pfUI.name, "Version"))
|
local raw = tostring(GetAddOnMetadata(pfUI.name, "Version"))
|
||||||
if strfind(raw, "@") then
|
if raw:find("@") then
|
||||||
pfUI.version.major, pfUI.version.minor, pfUI.version.fix = 0, 0, 0
|
pfUI.version.major, pfUI.version.minor, pfUI.version.fix = 0, 0, 0
|
||||||
pfUI.version.string = "dev"
|
pfUI.version.string = "dev"
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
## SavedVariablesPerCharacter: pfUI_config, pfUI_init, pfUI_playerDB
|
## SavedVariablesPerCharacter: pfUI_config, pfUI_init, pfUI_playerDB
|
||||||
## X-Website: https://github.com/brues-code/pfUI
|
## X-Website: https://github.com/brues-code/pfUI
|
||||||
|
|
||||||
|
API_Check.lua
|
||||||
|
|
||||||
pfUI.lua
|
pfUI.lua
|
||||||
|
|
||||||
init\env.xml
|
init\env.xml
|
||||||
|
|||||||
Reference in New Issue
Block a user