Unify SavedVariables into two clean roots with one-time migration

Collapse all legacy/scattered SavedVariables from absorbed standalone
addons (FeedOMatic, ZHunter/zButtons, SmartAmmo, AutoQuest, AntiDaze,
AutoStrip, MinimapButton) into two persisted globals with clean per-module
nesting under .modules.<id>.

Migration engine (api/savedvariables.lua):
- MTH_SV_EnsureSchema() with schemaVersion gate, idempotent + non-destructive
- Per-module migrators map old locations -> canonical nested stores
- Driven by an ADDON_LOADED("MetaHunt") handler so it runs only AFTER WoW
  loads the real SavedVariables (fixes announce-every-session bug that ran
  the migration on empty pre-load defaults)
- One-time player-facing chat announce, gated on real legacy data present

Framework/config:
- core-framework InitSavedVariables no longer runs migration at file-load;
  unconditionally strips account-root module aliases
- config.lua stops re-creating root[module] aliases (was duplicating data
  onto disk); canonical store stays under .modules.<id>

Modules:
- feedomatic: bind FOM_* globals as runtime aliases into nested store,
  drop persisted duplicates and .legacy blob
- zhunter: ZHunterMod_Saved re-pointed at .modules.zhunter
- smartammo/autoquest/antidaze/autostrip/minimapbutton read nested store

TOC trimmed to MTH_SavedVariables + MTH_CharSavedVariables only.
Profiles unchanged (already snapshot/apply the nested .modules structure).

Also includes pet-scan refinements: canonical pet key derivation and
level-independent pet signature (schema v3).
This commit is contained in:
DuvelCorp
2026-09-09 22:52:48 +02:00
parent de6621f41f
commit 060fc555fe
22 changed files with 854 additions and 502 deletions
+35 -60
View File
@@ -1,7 +1,3 @@
local function MTHSmartAmmo_GetSaved()
return MTH_SA_GetSavedTable("MTHSmartAmmo")
end
local function MTHSmartAmmo_GetModuleStore()
if MTH and MTH.GetModuleCharSavedVariables then
return MTH:GetModuleCharSavedVariables("smartammo")
@@ -9,40 +5,43 @@ local function MTHSmartAmmo_GetModuleStore()
return nil
end
local function MTHSmartAmmo_IsSmartEnabled()
-- Single source of truth: moduleStore.settings.{smartEnabled,reloadEnabled,weaponSwapEnabled}
local function MTHSmartAmmo_GetSettings()
local moduleStore = MTHSmartAmmo_GetModuleStore()
if type(moduleStore) == "table" and moduleStore.smartEnabled ~= nil then
return moduleStore.smartEnabled and true or false
if type(moduleStore) ~= "table" then
return nil
end
local saved = MTHSmartAmmo_GetSaved()
if saved["enabled"] == nil then
return true
if type(moduleStore.settings) ~= "table" then
moduleStore.settings = {}
end
return saved["enabled"] and true or false
return moduleStore.settings
end
local function MTHSmartAmmo_ReadFlag(key)
local settings = MTHSmartAmmo_GetSettings()
if settings and settings[key] ~= nil then
return settings[key] and true or false
end
return true -- default enabled
end
local function MTHSmartAmmo_WriteFlag(key, enabled)
local settings = MTHSmartAmmo_GetSettings()
if settings then
settings[key] = enabled and true or false
end
end
local function MTHSmartAmmo_IsSmartEnabled()
return MTHSmartAmmo_ReadFlag("smartEnabled")
end
local function MTHSmartAmmo_IsReloadEnabled()
local moduleStore = MTHSmartAmmo_GetModuleStore()
if type(moduleStore) == "table" and moduleStore.reloadEnabled ~= nil then
return moduleStore.reloadEnabled and true or false
end
local saved = MTHSmartAmmo_GetSaved()
if saved["reload"] == nil then
return true
end
return saved["reload"] and true or false
return MTHSmartAmmo_ReadFlag("reloadEnabled")
end
local function MTHSmartAmmo_IsWeaponSwapEnabled()
local moduleStore = MTHSmartAmmo_GetModuleStore()
if type(moduleStore) == "table" and moduleStore.weaponSwapEnabled ~= nil then
return moduleStore.weaponSwapEnabled and true or false
end
local saved = MTHSmartAmmo_GetSaved()
if saved["weaponSwap"] == nil then
return true
end
return saved["weaponSwap"] and true or false
return MTHSmartAmmo_ReadFlag("weaponSwapEnabled")
end
local MTHSmartAmmo_InitializeHooks
@@ -58,9 +57,7 @@ local MTH_SA_SPELL_EVENTS = {
}
function MTHSmartAmmo_SetSmartEnabled(enabled, silent)
local saved = MTHSmartAmmo_GetSaved()
if enabled then
saved["enabled"] = 1
local evFrame = getglobal("MTH_SA_EventFrame")
if evFrame then
for _, ev in ipairs(MTH_SA_SPELL_EVENTS) do
@@ -77,7 +74,6 @@ function MTHSmartAmmo_SetSmartEnabled(enabled, silent)
MTH_SA_Print("Smart Ammo Enabled.")
end
else
saved["enabled"] = false
local evFrame = getglobal("MTH_SA_EventFrame")
if evFrame then
for _, ev in ipairs(MTH_SA_SPELL_EVENTS) do
@@ -89,10 +85,7 @@ function MTHSmartAmmo_SetSmartEnabled(enabled, silent)
end
end
local moduleStore = MTHSmartAmmo_GetModuleStore()
if type(moduleStore) == "table" then
moduleStore.smartEnabled = enabled and true or false
end
MTHSmartAmmo_WriteFlag("smartEnabled", enabled and true or false)
end
function MTHSmartAmmo_GetSmartEnabled()
@@ -100,16 +93,7 @@ function MTHSmartAmmo_GetSmartEnabled()
end
function MTHSmartAmmo_SetReloadEnabled(enabled, silent)
local saved = MTHSmartAmmo_GetSaved()
if enabled then
saved["reload"] = 1
else
saved["reload"] = false
end
local moduleStore = MTHSmartAmmo_GetModuleStore()
if type(moduleStore) == "table" then
moduleStore.reloadEnabled = enabled and true or false
end
MTHSmartAmmo_WriteFlag("reloadEnabled", enabled and true or false)
if not silent and DEFAULT_CHAT_FRAME then
MTH_SA_Print("Smart Ammo reload fallback " .. (enabled and "Enabled." or "Disabled."))
end
@@ -120,16 +104,7 @@ function MTHSmartAmmo_GetReloadEnabled()
end
function MTHSmartAmmo_SetWeaponSwapEnabled(enabled, silent)
local saved = MTHSmartAmmo_GetSaved()
if enabled then
saved["weaponSwap"] = 1
else
saved["weaponSwap"] = false
end
local moduleStore = MTHSmartAmmo_GetModuleStore()
if type(moduleStore) == "table" then
moduleStore.weaponSwapEnabled = enabled and true or false
end
MTHSmartAmmo_WriteFlag("weaponSwapEnabled", enabled and true or false)
if not silent and DEFAULT_CHAT_FRAME then
MTH_SA_Print("Smart Ammo weapon-swap auto-equip " .. (enabled and "Enabled." or "Disabled."))
end
@@ -807,15 +782,15 @@ SlashCmdList["MTHSmartAmmo"] = function(msg)
return
end
local saved = MTHSmartAmmo_GetSaved()
local smartEnabled = MTHSmartAmmo_GetSmartEnabled()
if msg == "status" then
local castHook, actionHook, byNameHook = MTHSmartAmmo_AreHooksInstalled()
MTH_SA_Print("Smart Ammo status: smart=" .. tostring(saved["enabled"] and true or false) .. ", module=" .. tostring(MTH_SA_IsModuleEnabled()) .. ", hooks=" .. tostring(castHook) .. "/" .. tostring(actionHook) .. "/" .. tostring(byNameHook))
MTH_SA_Print("Smart Ammo status: smart=" .. tostring(smartEnabled) .. ", module=" .. tostring(MTH_SA_IsModuleEnabled()) .. ", hooks=" .. tostring(castHook) .. "/" .. tostring(actionHook) .. "/" .. tostring(byNameHook))
return
end
if saved["enabled"] then
if smartEnabled then
MTHSmartAmmo_SetSmartEnabled(nil)
else
MTHSmartAmmo_SetSmartEnabled(1)
+11 -66
View File
@@ -15,39 +15,6 @@ local MTH_SmartAmmo = {
local MTH_SA_BOUNDARY_KEY = "smartammo.core"
function MTH_SA_GetSavedTable(tableName)
if not MTH or not MTH.GetModuleCharSavedVariables then
if type(_G[tableName]) ~= "table" then
_G[tableName] = {}
end
return _G[tableName]
end
local moduleStore = MTH:GetModuleCharSavedVariables("smartammo")
if type(moduleStore) ~= "table" then
moduleStore = {}
end
if not moduleStore.legacy then
moduleStore.legacy = {}
end
if type(moduleStore.legacy[tableName]) ~= "table" then
moduleStore.legacy[tableName] = {}
end
if type(_G[tableName]) == "table" then
local legacyTable = moduleStore.legacy[tableName]
if not next(legacyTable) then
for key, value in pairs(_G[tableName]) do
legacyTable[key] = value
end
end
end
_G[tableName] = moduleStore.legacy[tableName]
return moduleStore.legacy[tableName]
end
function MTH_SA_IsModuleEnabled()
if MTH and MTH.IsModuleEnabled then
return MTH:IsModuleEnabled("smartammo", true) and true or false
@@ -70,43 +37,22 @@ local function MTH_SA_ApplySavedState()
return
end
local saved = MTH_SA_GetSavedTable("MTHSmartAmmo")
local moduleStore = MTH and MTH.GetModuleCharSavedVariables and MTH:GetModuleCharSavedVariables("smartammo") or nil
if type(moduleStore) == "table" then
if moduleStore.smartEnabled ~= nil then
saved["enabled"] = moduleStore.smartEnabled and 1 or false
end
if moduleStore.reloadEnabled ~= nil then
saved["reload"] = moduleStore.reloadEnabled and 1 or false
end
if moduleStore.weaponSwapEnabled ~= nil then
saved["weaponSwap"] = moduleStore.weaponSwapEnabled and 1 or false
end
end
if saved["enabled"] == nil then
saved["enabled"] = 1
if type(moduleStore) == "table" then
moduleStore.smartEnabled = true
end
end
if saved["reload"] == nil and type(moduleStore) == "table" then
moduleStore.reloadEnabled = saved["reload"] ~= false
end
if saved["weaponSwap"] == nil then
saved["weaponSwap"] = 1
if type(moduleStore) == "table" then
moduleStore.weaponSwapEnabled = true
end
elseif type(moduleStore) == "table" and moduleStore.weaponSwapEnabled == nil then
moduleStore.weaponSwapEnabled = saved["weaponSwap"] ~= false
end
local settings = (type(moduleStore) == "table" and type(moduleStore.settings) == "table") and moduleStore.settings or {}
MTHSmartAmmo_SetSmartEnabled(saved["enabled"] and 1 or nil, 1)
local smart = settings.smartEnabled
if smart == nil then smart = true end
local reload = settings.reloadEnabled
if reload == nil then reload = true end
local swap = settings.weaponSwapEnabled
if swap == nil then swap = true end
MTHSmartAmmo_SetSmartEnabled(smart and 1 or nil, 1)
if type(MTHSmartAmmo_SetReloadEnabled) == "function" then
MTHSmartAmmo_SetReloadEnabled(saved["reload"] ~= false and 1 or nil, 1)
MTHSmartAmmo_SetReloadEnabled(reload and 1 or nil, 1)
end
if type(MTHSmartAmmo_SetWeaponSwapEnabled) == "function" then
MTHSmartAmmo_SetWeaponSwapEnabled(saved["weaponSwap"] ~= false and 1 or nil, 1)
MTHSmartAmmo_SetWeaponSwapEnabled(swap and 1 or nil, 1)
end
if type(MTHSmartAmmo_EnsureHooks) == "function" then
MTHSmartAmmo_EnsureHooks("module-apply")
@@ -154,7 +100,6 @@ local function MTH_SA_RestoreHooks()
end
function MTH_SmartAmmo:init()
MTH_SA_GetSavedTable("MTHSmartAmmo")
if self.enabled then
MTH_SA_ApplySavedState()
end