diff --git a/Database/compiler.lua b/Database/compiler.lua index bcb0c1c..5ab2553 100644 --- a/Database/compiler.lua +++ b/Database/compiler.lua @@ -9,6 +9,8 @@ local QuestieDB = QuestieLoader:ImportModule("QuestieDB") local QuestieLib = QuestieLoader:ImportModule("QuestieLib") ---@type l10n local l10n = QuestieLoader:ImportModule("l10n") +---@type QuestiePluginAPI +local QuestiePluginAPI = QuestieLoader:ImportModule("QuestiePluginAPI") --- COMPATIBILITY --- local WOW_PROJECT_ID = QuestieCompat.WOW_PROJECT_ID @@ -1095,6 +1097,7 @@ function QuestieDBCompiler:Compile() print("\124cFFAAEEFF"..l10n("Questie DB update complete!")) Questie.db.global.dbCompiledExpansion = WOW_PROJECT_ID + Questie.db.global.dbCompiledPluginSignature = QuestiePluginAPI:GetLoadedSignature() if Questie.IsSoD then Questie.db.global.sod.dbCompiledOnVersion = QuestieLib:GetAddonVersionString() @@ -1107,6 +1110,8 @@ function QuestieDBCompiler:Compile() Questie.db.global.dbIsCompiled = true Questie.db.global.dbCompiledCount = (Questie.db.global.dbCompiledCount or 0) + 1 end + + QuestieDBCompiler._isCompiling = false end function QuestieDBCompiler:ValidateNPCs() diff --git a/Modules/Libs/QuestiePluginAPI.lua b/Modules/Libs/QuestiePluginAPI.lua index a152996..6867e61 100644 --- a/Modules/Libs/QuestiePluginAPI.lua +++ b/Modules/Libs/QuestiePluginAPI.lua @@ -4,6 +4,28 @@ local QuestiePluginAPI = QuestieLoader:CreateModule("QuestiePluginAPI") QuestiePluginAPI.registeredPlugins = {} QuestiePluginAPI.loadedDBFlavor = nil -- set by the first DB plugin that calls FinishLoading QuestiePluginAPI.pendingPluginsCount = 0 -- count of plugins that have registered but not yet FinishedLoading +QuestiePluginAPI.loadedDBVersions = {} + +local KNOWN_PLUGIN_ADDONS = { + WotLKDB = "Questie-X-WotLKDB", + ClassicDB = "Questie-X-ClassicDB", + TBCDB = "Questie-X-TBCDB", + Ascension = "Questie-X-AscensionDB", + AscensionDB = "Questie-X-AscensionDB", + Ebonhold = "Questie-X-EbonholdDB", + EbonholdDB = "Questie-X-EbonholdDB", + Valanior = "Questie-X-ValaniorDB", + ValaniorDB = "Questie-X-ValaniorDB", + RetailDB = "Questie-X-RetailDB", +} + +local function GetPluginAddonVersion(pluginName, flavorKey) + local addonName = KNOWN_PLUGIN_ADDONS[flavorKey] or KNOWN_PLUGIN_ADDONS[pluginName] or pluginName + if GetAddOnMetadata then + return GetAddOnMetadata(addonName, "Version") or "unknown" + end + return "unknown" +end --- Returns true if at least one DB plugin has fully loaded. ---@return boolean @@ -27,6 +49,27 @@ function QuestiePluginAPI:GetLoadedFlavor() return self.loadedDBFlavor end +--- Returns a stable signature for loaded DB plugin data. +---@return string +function QuestiePluginAPI:GetLoadedSignature() + local parts = {} + local pluginName, plugin = next(self.registeredPlugins) + while pluginName do + local version = self.loadedDBVersions[pluginName] or plugin.version or "pending" + local flavor = plugin.flavorKey or pluginName + local stats = plugin.stats or {} + parts[#parts + 1] = pluginName .. ":" .. flavor .. ":" .. version + .. ":Q" .. tostring(stats.QUEST or 0) + .. ":N" .. tostring(stats.NPC or 0) + .. ":O" .. tostring(stats.OBJECT or 0) + .. ":I" .. tostring(stats.ITEM or 0) + pluginName, plugin = next(self.registeredPlugins, pluginName) + end + + table.sort(parts) + return table.concat(parts, "|") +end + ---@class QuestiePlugin local QuestiePlugin = {} QuestiePlugin.__index = QuestiePlugin @@ -298,6 +341,10 @@ function QuestiePlugin:FinishLoading(flavorKey) QuestiePluginAPI.loadedDBFlavor = self.name end + self.flavorKey = flavorKey or self.name + self.version = GetPluginAddonVersion(self.name, self.flavorKey) + QuestiePluginAPI.loadedDBVersions[self.name] = self.version + if not self.isFinished then self.isFinished = true QuestiePluginAPI.pendingPluginsCount = math.max(0, QuestiePluginAPI.pendingPluginsCount - 1) diff --git a/Modules/QuestieInit.lua b/Modules/QuestieInit.lua index 41f2a29..f06607f 100644 --- a/Modules/QuestieInit.lua +++ b/Modules/QuestieInit.lua @@ -383,9 +383,13 @@ QuestieInit.Stages[3] = function() -- run as a coroutine local waitStart = GetTime() Questie:Debug(Questie.DEBUG_CRITICAL, "[QuestieInit:Stage3] Waiting for plugins to register/finish. Initial pending: " .. QuestiePluginAPI.pendingPluginsCount) - -- Give other addons/scripts a moment to fire and register if they were waiting for PLAYER_LOGIN - while (GetTime() - waitStart < 1.0) do - coYield() + -- Give DB plugins a short grace period only when a plugin addon is enabled + -- but none has registered yet. Avoid adding a fixed one-second delay to + -- every login after plugins are already registered. + if QuestieServer:IsAnyDBPluginEnabled() and (not QuestiePluginAPI:IsAnyPluginLoaded()) then + while (GetTime() - waitStart < 1.0) do + coYield() + end end local timeout = 10 @@ -395,16 +399,26 @@ QuestieInit.Stages[3] = function() -- run as a coroutine elapsed = GetTime() - waitStart end - -- Always re-compile on custom servers to pick up QuestieLearner changes from SavedVariables, - -- or if compilation was explicitly deferred/needed. + -- Recompile custom-server/plugin data only when the compiled cache no longer + -- matches the loaded plugin set. Learner data is applied as live overrides and + -- does not require rebuilding the binary DB cache on every login. local isCustomServer = Questie.IsAscension or Questie.IsEbonhold or Questie.IsValanior or QuestieServer:IsAnyDBPluginEnabled() - if isCustomServer or needsCompilation or (not Questie.db.global.dbIsCompiled) then + local pluginSignature = QuestiePluginAPI:GetLoadedSignature() + local cacheMatchesPlugins = Questie.db.global.dbCompiledPluginSignature == pluginSignature + local cacheMatchesCore = Questie.db.global.dbIsCompiled + and (QuestieLib:GetAddonVersionString() == Questie.db.global.dbCompiledOnVersion) + and (l10n:GetUILocale() == Questie.db.global.dbCompiledLang) + and (Questie.db.global.dbCompiledExpansion == WOW_PROJECT_ID) + + if needsCompilation or (not cacheMatchesCore) or (isCustomServer and (not cacheMatchesPlugins)) then Questie:Debug(Questie.DEBUG_CRITICAL, "[QuestieInit:Stage3] Starting compilation (Server=" .. tostring(isCustomServer) .. ", Needed=" .. tostring(needsCompilation) .. ")") if not QuestieDB.questData then loadFullDatabase() end QuestieDBCompiler:Compile() QuestieDB:Initialize() + else + Questie:Debug(Questie.DEBUG_INFO, "[QuestieInit:Stage3] DB cache is current; skipping compilation.") end -- register events that rely on questie being initialized