Files
Questie-X/Modules/QuestieInit.lua
T

654 lines
25 KiB
Lua

---@class QuestieInit
local QuestieInit = QuestieLoader:CreateModule("QuestieInit")
local _QuestieInit = QuestieInit.private
---@type ThreadLib
local ThreadLib = QuestieLoader:ImportModule("ThreadLib")
---@type QuestEventHandler
local QuestEventHandler = QuestieLoader:ImportModule("QuestEventHandler")
---@type l10n
local l10n = QuestieLoader:ImportModule("l10n")
---@type ZoneDB
local ZoneDB = QuestieLoader:ImportModule("ZoneDB")
---@type Migration
local Migration = QuestieLoader:ImportModule("Migration")
---@type QuestieProfessions
local QuestieProfessions = QuestieLoader:ImportModule("QuestieProfessions")
---@type QuestieTracker
local QuestieTracker = QuestieLoader:ImportModule("QuestieTracker")
---@type QuestieMap
local QuestieMap = QuestieLoader:ImportModule("QuestieMap")
---@type QuestieLib
local QuestieLib = QuestieLoader:ImportModule("QuestieLib")
---@type QuestiePlayer
local QuestiePlayer = QuestieLoader:ImportModule("QuestiePlayer")
---@type QuestieDB
local QuestieDB = QuestieLoader:ImportModule("QuestieDB")
---@type Cleanup
local QuestieCleanup = QuestieLoader:ImportModule("Cleanup")
---@type DBCompiler
local QuestieDBCompiler = QuestieLoader:ImportModule("DBCompiler")
---@type QuestieCorrections
local QuestieCorrections = QuestieLoader:ImportModule("QuestieCorrections")
---@type QuestieMenu
local QuestieMenu = QuestieLoader:ImportModule("QuestieMenu")
---@type Townsfolk
local Townsfolk = QuestieLoader:ImportModule("Townsfolk")
---@type QuestieQuest
local QuestieQuest = QuestieLoader:ImportModule("QuestieQuest")
---@type IsleOfQuelDanas
local IsleOfQuelDanas = QuestieLoader:ImportModule("IsleOfQuelDanas")
---@type QuestieEventHandler
local QuestieEventHandler = QuestieLoader:ImportModule("QuestieEventHandler")
---@type QuestieJourney
local QuestieJourney = QuestieLoader:ImportModule("QuestieJourney")
---@type HBDHooks
local HBDHooks = QuestieLoader:ImportModule("HBDHooks")
---@type ChatFilter
local ChatFilter = QuestieLoader:ImportModule("ChatFilter")
---@type QuestieShutUp
local QuestieShutUp = QuestieLoader:ImportModule("QuestieShutUp")
---@type Hooks
local Hooks = QuestieLoader:ImportModule("Hooks")
---@type QuestieValidateGameCache
local QuestieValidateGameCache = QuestieLoader:ImportModule("QuestieValidateGameCache")
---@type MinimapIcon
local MinimapIcon = QuestieLoader:ImportModule("MinimapIcon")
---@type QuestieComms
local QuestieComms = QuestieLoader:ImportModule("QuestieComms");
---@type QuestieCompat
local QuestieCompat = QuestieLoader:ImportModule("QuestieCompat")
---@type QuestieOptions
local QuestieOptions = QuestieLoader:ImportModule("QuestieOptions");
---@type QuestieCoords
local QuestieCoords = QuestieLoader:ImportModule("QuestieCoords");
---@type QuestieArrow
local QuestieArrow = QuestieLoader:ImportModule("QuestieArrow")
---@type QuestieTooltips
local QuestieTooltips = QuestieLoader:ImportModule("QuestieTooltips");
---@type QuestieDBMIntegration
local QuestieDBMIntegration = QuestieLoader:ImportModule("QuestieDBMIntegration");
---@type TrackerQuestTimers
local TrackerQuestTimers = QuestieLoader:ImportModule("TrackerQuestTimers")
---@type QuestieCombatQueue
local QuestieCombatQueue = QuestieLoader:ImportModule("QuestieCombatQueue")
---@type QuestieSlash
local QuestieSlash = QuestieLoader:ImportModule("QuestieSlash")
---@type QuestXP
local QuestXP = QuestieLoader:ImportModule("QuestXP")
---@type Tutorial
local Tutorial = QuestieLoader:ImportModule("Tutorial")
---@type WorldMapButton
local WorldMapButton = QuestieLoader:ImportModule("WorldMapButton")
---@type AvailableQuests
local AvailableQuests = QuestieLoader:ImportModule("AvailableQuests")
---@type SeasonOfDiscovery
local SeasonOfDiscovery = QuestieLoader:ImportModule("SeasonOfDiscovery")
---@type QuestieLearner
local QuestieLearner = QuestieLoader:ImportModule("QuestieLearner")
---@type QuestieServer
local QuestieServer = QuestieLoader:ImportModule("QuestieServer")
--- COMPATIBILITY ---
local WOW_PROJECT_ID = QuestieCompat.WOW_PROJECT_ID
local C_Timer = QuestieCompat.C_Timer
-- Safe yield: only yields when we are actually inside a running coroutine.
-- Without this check, coroutine.yield() throws "attempt to yield across C-call boundary"
-- when Stage 1 runs synchronously inside AceAddon's pcall (a C stack frame).
local function coYield()
if coroutine.running() then
coroutine.yield()
end
end
local function _dbStats(t)
if type(t) ~= "table" then return "type=" .. type(t) end
local n, minK, maxK = 0, math.huge, 0
for k in pairs(t) do
n = n + 1
if type(k) == "number" then
if k < minK then minK = k end
if k > maxK then maxK = k end
end
end
return "count=" .. n .. " minID=" .. (minK == math.huge and 0 or minK) .. " maxID=" .. maxK
end
local function loadFullDatabase()
print("\124cFF4DDBFF [1/9] " .. l10n("Loading database") .. "...")
QuestieInit:LoadBaseDB()
Questie:Debug(Questie.DEBUG_DEVELOP, "[DBDiag] After LoadBaseDB - quest:" .. _dbStats(QuestieDB.questData) .. " npc:" .. _dbStats(QuestieDB.npcData))
Questie:Debug(Questie.DEBUG_DEVELOP, "[DBDiag] obj:" .. _dbStats(QuestieDB.objectData) .. " item:" .. _dbStats(QuestieDB.itemData))
print("\124cFF4DDBFF [2/9] " .. l10n("Applying database corrections") .. "...")
coYield()
QuestieCorrections:Initialize()
Questie:Debug(Questie.DEBUG_DEVELOP, "[DBDiag] After Corrections - quest:" .. _dbStats(QuestieDB.questData) .. " npc:" .. _dbStats(QuestieDB.npcData))
print("\124cFF4DDBFF [3/9] " .. l10n("Initializing townfolks") .. "...")
coYield()
Townsfolk.Initialize()
print("\124cFF4DDBFF [4/9] " .. l10n("Initializing locale") .. "...")
coYield()
l10n:Initialize()
coYield()
QuestieDB.private:DeleteGatheringNodes()
print("\124cFF4DDBFF [5/9] " .. l10n("Optimizing waypoints") .. "...")
coYield()
QuestieCorrections:PreCompile()
end
function QuestieInit:OnInitialize()
if QuestieInit.initialized then return end
QuestieInit.initialized = true
if QuestieInit.Stages and QuestieInit.Stages[1] and (not QuestieInit.stage1Done) then
QuestieInit.stage1Done = true
-- Run Stage 1 inside a coroutine so that all coroutine.yield() calls
-- in Stage 1 and its callees (Townsfolk, compiler, etc.) have a valid
-- coroutine context. AceAddon calls OnInitialize from a C pcall boundary
-- so calling coroutine.yield() without an enclosing coroutine crashes.
-- We drain the coroutine synchronously (resume until dead) so that
-- QuestieDB.QuestPointers is set before OnInitialize returns.
local co = coroutine.create(QuestieInit.Stages[1])
while coroutine.status(co) == "suspended" do
local ok, err = coroutine.resume(co)
if not ok then
print(debugstack(co))
break
end
end
else
end
end
---Run the validator
local function runValidator()
if type(QuestieDB.questData) == "string" or type(QuestieDB.npcData) == "string" or type(QuestieDB.objectData) == "string" or type(QuestieDB.itemData) == "string" then
Questie:Error("Cannot run the validator on string data, load database first")
return
end
-- Run validator
if Questie.db.profile.debugEnabled then
coYield()
print("Validating NPCs...")
QuestieDBCompiler:ValidateNPCs()
coYield()
print("Validating objects...")
QuestieDBCompiler:ValidateObjects()
coYield()
print("Validating items...")
QuestieDBCompiler:ValidateItems()
coYield()
print("Validating quests...")
QuestieDBCompiler:ValidateQuests()
end
end
-- ********************************************************************************
-- Start of QuestieInit.Stages ******************************************************
-- stage worker functions. Most are coroutines.
QuestieInit.Stages = {}
QuestieInit.Stages[1] = function() -- run as a coroutine
Questie:Debug(Questie.DEBUG_CRITICAL, "[QuestieInit:Stage1] Starting the real init.")
--? This was moved here because the lag that it creates is much less noticable here, while still initalizing correctly.
Questie:Debug(Questie.DEBUG_CRITICAL, "[QuestieInit:Stage1] Starting QuestieOptions.Initialize Thread.")
ThreadLib.ThreadSimple(QuestieOptions.Initialize, 0)
if QuestieServer and QuestieServer.Init then
QuestieServer:Init()
end
MinimapIcon:Init()
if HBDHooks and HBDHooks.Init then
HBDHooks:Init()
end
Questie:SetIcons()
if QUESTIE_LOCALES_OVERRIDE ~= nil then
l10n:InitializeLocaleOverride()
end
-- Set proper locale. Either default to client Locale or override based on user.
if Questie.db.global.questieLocaleDiff then
l10n:SetUILocale(Questie.db.global.questieLocale);
else
if QUESTIE_LOCALES_OVERRIDE ~= nil then
l10n:SetUILocale(QUESTIE_LOCALES_OVERRIDE.locale);
else
l10n:SetUILocale(GetLocale());
end
end
QuestieShutUp:ToggleFilters(Questie.db.profile.questieShutUp)
coYield()
ZoneDB:Initialize()
coYield()
Migration:Migrate()
IsleOfQuelDanas.Initialize() -- This has to happen before option init
QuestieProfessions:Init()
QuestXP.Init()
coYield()
local dbCompiled = false
local dbIsCompiled, dbCompiledOnVersion, dbCompiledLang
if Questie.IsSoD then
dbIsCompiled = Questie.db.global.sod.dbIsCompiled or false
dbCompiledOnVersion = Questie.db.global.sod.dbCompiledOnVersion
dbCompiledLang = Questie.db.global.sod.dbCompiledLang
else
dbIsCompiled = Questie.db.global.dbIsCompiled or false
dbCompiledOnVersion = Questie.db.global.dbCompiledOnVersion
dbCompiledLang = Questie.db.global.dbCompiledLang
end
if Questie.IsSoD then
coYield()
SeasonOfDiscovery.Initialize()
end
-- Check if the DB needs to be recompiled
do
local addonV = QuestieLib:GetAddonVersionString()
local uiLoc = l10n:GetUILocale()
local storedExp = Questie.db.global.dbCompiledExpansion
end
if (not dbIsCompiled) or (QuestieLib:GetAddonVersionString() ~= dbCompiledOnVersion) or (l10n:GetUILocale() ~= dbCompiledLang) or (Questie.db.global.dbCompiledExpansion ~= WOW_PROJECT_ID) then
print("|cFFAAEEFF" ..
l10n("Questie DB has updated!") ..
"|r|cFFFF6F22 " .. l10n("Data is being processed, this may take a few moments and cause some lag..."))
loadFullDatabase()
Questie:Debug(Questie.DEBUG_DEVELOP, "[DBDiag] Before Compile - quest:" .. _dbStats(QuestieDB.questData) .. " npc:" .. _dbStats(QuestieDB.npcData))
QuestieDBCompiler:Compile()
Questie:Debug(Questie.DEBUG_DEVELOP, "[DBDiag] After Compile - quest:type=" .. type(QuestieDB.questData) .. " npc:type=" .. type(QuestieDB.npcData))
dbCompiled = true
else
Questie:Debug(Questie.DEBUG_DEVELOP, "[DBDiag] DB was CACHED (no recompile)")
l10n:Initialize()
coYield()
QuestieCorrections:MinimalInit()
-- DB is cached — LoadBaseDB never runs, so count the WotLKDB globals here
-- and push them onto plugin.stats so the Database panel shows correct numbers.
QuestieInit:UpdateWotLKDBStats()
end
local dbCompiledCount = Questie.IsSoD and Questie.db.global.sod.dbCompiledCount or Questie.db.global.dbCompiledCount
if (not Questie.db.char.townsfolk) or (dbCompiledCount ~= Questie.db.char.townsfolkVersion) or (Questie.db.char.townsfolkClass ~= UnitClass("player")) then
Questie.db.char.townsfolkVersion = dbCompiledCount
coYield()
Townsfolk:BuildCharacterTownsfolk()
end
coYield()
QuestieDB:Initialize()
coYield()
if QuestieLearner and QuestieLearner.Initialize then
QuestieLearner:Initialize()
end
coYield()
Tutorial.Initialize()
--? Only run the validator on recompile if debug is enabled, otherwise it's a waste of time.
if Questie.db.profile.debugEnabled and dbCompiled then
if Questie.db.profile.skipValidation ~= true then
runValidator()
print("\124cFF4DDBFF Load and Validation complete.")
else
print("\124cFF4DDBFF Validation skipped, load complete.")
end
end
QuestieCleanup:Run()
end
QuestieInit.Stages[2] = function()
Questie:Debug(Questie.DEBUG_INFO, "[QuestieInit:Stage2] Stage 2 start.")
-- We do this while we wait for the Quest Cache anyway.
l10n:PostBoot()
QuestiePlayer:Initialize()
coYield()
QuestieJourney:Initialize()
local keepWaiting = true
-- We had users reporting that a quest did not reach a valid state in the game cache.
-- In this case we still need to continue the initialization process, even though a specific quest might be bugged
-- 3-second timeout for cache validation
C_Timer.After(3, function()
if keepWaiting then
Questie:Error("[QuestieInit:Stage2] Quest cache validation timed out! Some data may be missing.")
keepWaiting = false
local ok, err = coroutine.resume(QuestieInit.Thread)
if not ok then
Questie:Debug(Questie.DEBUG_INFO, "[QuestieInit:Stage2] Resume failed (timeout): " .. tostring(err))
end
end
end)
-- Continue to the next Init Stage once Game Cache's Questlog is good
while (not QuestieValidateGameCache:IsCacheGood()) and keepWaiting do
coYield()
end
keepWaiting = false
end
QuestieInit.Stages[3] = function() -- run as a coroutine
Questie:Debug(Questie.DEBUG_INFO, "[QuestieInit:Stage3] Stage 3 start.")
-- register events that rely on questie being initialized
QuestieEventHandler:RegisterLateEvents()
-- ** OLD ** Questie:ContinueInit() ** START **
QuestieTooltips:Initialize()
QuestieCoords:Initialize()
if QuestieArrow and QuestieArrow.Initialize then
QuestieArrow:Initialize()
else
Questie:Error("[QuestieArrow] Module not loaded correctly (missing Initialize).")
end
TrackerQuestTimers:Initialize()
QuestieComms:Initialize()
QuestieSlash.RegisterSlashCommands()
coYield()
if Questie.db.profile.dbmHUDEnable then
QuestieDBMIntegration:EnableHUD()
end
-- ** OLD ** Questie:ContinueInit() ** END **
coYield()
QuestEventHandler:RegisterEvents()
coYield()
ChatFilter:RegisterEvents()
QuestieMap:InitializeQueue()
coYield()
QuestieQuest:Initialize()
coYield()
WorldMapButton.Initialize()
coYield()
QuestieQuest:GetAllQuestIdsNoObjectives()
coYield()
Townsfolk.PostBoot()
coYield()
QuestieQuest:GetAllQuestIds()
-- Initialize the tracker
coYield()
QuestieTracker.Initialize()
Hooks:HookQuestLogTitle()
QuestieCombatQueue.Initialize()
local dateToday = date("%y-%m-%d")
if Questie.db.profile.showAQWarEffortQuests and ((not Questie.db.profile.aqWarningPrintDate) or (Questie.db.profile.aqWarningPrintDate < dateToday)) then
Questie.db.profile.aqWarningPrintDate = dateToday
C_Timer.After(2, function()
Questie:Print("|cffff0000-----------------------------|r")
Questie:Print(
"|cffff0000The AQ War Effort quests are shown for you. If your server is done you can hide those quests in the General settings of Questie!|r");
Questie:Print("|cffff0000-----------------------------|r")
end)
end
if Questie.IsTBC and (not Questie.db.global.isIsleOfQuelDanasPhaseReminderDisabled) then
C_Timer.After(2, function()
Questie:Print(l10n(
"Current active phase of Isle of Quel'Danas is '%s'. Check the General settings to change the phase or disable this message.",
IsleOfQuelDanas.localizedPhaseNames[Questie.db.global.isleOfQuelDanasPhase]))
end)
end
coYield()
QuestieMenu:OnLogin()
coYield()
if Questie.db.profile.debugEnabled then
QuestieLoader:PopulateGlobals()
end
Questie.started = true
if (Questie.IsWotlk or Questie.IsTBC) and QuestiePlayer.IsMaxLevel() then
local lastRequestWasYesterday = Questie.db.global.lastDailyRequestDate ~= date("%d-%m-%y"); -- Yesterday or some day before
local isPastDailyReset = Questie.db.global.lastDailyRequestResetTime < GetQuestResetTime();
if lastRequestWasYesterday or isPastDailyReset then
Questie.db.global.lastDailyRequestDate = date("%d-%m-%y");
Questie.db.global.lastDailyRequestResetTime = GetQuestResetTime();
end
end
-- We do this last because it will run for a while and we don't want to block the rest of the init
coYield()
AvailableQuests.CalculateAndDrawAll()
Questie:Debug(Questie.DEBUG_INFO, "[QuestieInit:Stage3] Questie init done.")
end
-- End of QuestieInit.Stages ******************************************************
-- ********************************************************************************
function QuestieInit:LoadDatabase(key)
if type(QuestieDB[key]) == "string" then
-- Fix #6: `loadstring` at LOAD TIME is safe, but calling it here during
-- event-driven runtime taints any tables produced on WotLK/Era clients.
-- This path is for legacy single-file DB format. If we are on a
-- modern client (WOW_PROJECT_ID is defined natively and not ancient), refuse
-- and direct the user to reinstall the split-file DB instead.
local _, _, _, tocversion = GetBuildInfo()
local isModernClient = false
if tocversion then
if tocversion >= 100000 then isModernClient = true -- Retail
elseif tocversion >= 11300 and tocversion < 12000 then isModernClient = true -- Classic Era
elseif tocversion >= 20500 and tocversion < 30000 then isModernClient = true -- TBC Classic
elseif tocversion >= 30400 and tocversion < 40000 then isModernClient = true -- WotLK Classic
elseif tocversion >= 40400 and tocversion < 50000 then isModernClient = true -- Cata Classic
elseif tocversion >= 50000 and tocversion < 60000 then isModernClient = true -- MoP (e.g. 50400)
end
end
if isModernClient then
Questie:Debug(Questie.DEBUG_DEVELOP,
"[DBDiag] LEGACY DB ('" .. key .. "' is string) on modern client. "
.. "Runtime loadstring() would taint this data. "
.. "Please reinstall the Questie-X-WotLKDB addon in split-file format.")
QuestieDB[key] = {}
return
end
-- Lua 5.0 / ancient custom server: loadstring is the only option.
coYield()
local fn, loadErr = loadstring(QuestieDB[key])
coYield()
if fn then
local ok, result = pcall(fn)
if ok then
QuestieDB[key] = result
else
Questie:Debug(Questie.DEBUG_DEVELOP, "[DBDiag] ERROR executing('" .. key .. "'): " .. tostring(result))
QuestieDB[key] = nil
end
else
Questie:Debug(Questie.DEBUG_DEVELOP, "[DBDiag] ERROR loadstring('" .. key .. "'): " .. tostring(loadErr) .. " | len=" .. string.len(QuestieDB[key] or ""))
QuestieDB[key] = nil
end
elseif type(QuestieDB[key]) == "table" then
Questie:Debug(Questie.DEBUG_DEVELOP, "[LoadDatabase] '" .. key .. "' already a table (split-file format), skipping loadstring")
else
Questie:Debug(Questie.DEBUG_DEVELOP, "Database is missing, this is likely do to era vs tbc: ", key)
end
if not QuestieDB[key] then
QuestieDB[key] = {}
end
end
function QuestieInit:UpdateWotLKDBStats()
local function _countTable(t)
if type(t) ~= "table" then return 0 end
local n = 0
for _ in pairs(t) do n = n + 1 end
return n
end
local counts = {
QUEST = _countTable(_G["QuestieX_WotLKDB_quest"]),
NPC = _countTable(_G["QuestieX_WotLKDB_npc"]),
OBJECT = _countTable(_G["QuestieX_WotLKDB_object"]),
ITEM = _countTable(_G["QuestieX_WotLKDB_item"]),
}
Questie.wotlkStatsCache = counts
local QuestiePluginAPI = QuestieLoader:ImportModule("QuestiePluginAPI")
if QuestiePluginAPI then
local wotlkPlugin = QuestiePluginAPI:GetPlugin("WotLKDB")
if wotlkPlugin then
wotlkPlugin.stats.QUEST = counts.QUEST
wotlkPlugin.stats.NPC = counts.NPC
wotlkPlugin.stats.OBJECT = counts.OBJECT
wotlkPlugin.stats.ITEM = counts.ITEM
end
end
-- Fix #11: When the database is already compiled (cached), LoadBaseDB is never
-- run, so the global cleanup there is skipped. We MUST clean the namespace here
-- to prevent continuous ADDON_ACTION_BLOCKED taint errors during gameplay.
-- (Doing this also frees ~20MB of redundant RAM since the data is cached!)
_G["QuestieX_WotLKDB_quest"] = nil
_G["QuestieX_WotLKDB_npc"] = nil
_G["QuestieX_WotLKDB_object"] = nil
_G["QuestieX_WotLKDB_item"] = nil
end
function QuestieInit:LoadBaseDB()
local function _countTable(t)
if type(t) ~= "table" then return 0 end
local n = 0
for _ in pairs(t) do n = n + 1 end
return n
end
local function _pullGlobal(dbKey, globalName)
if type(_G[globalName]) == "table" then
QuestieDB[dbKey] = _G[globalName]
_G[globalName] = nil -- Remove tainted global from _G; data lives on through QuestieDB[dbKey]
return true
end
return false
end
-- Count BEFORE pulling so we have accurate numbers even after the globals are cleared
local _counts = {
QUEST = _countTable(_G["QuestieX_WotLKDB_quest"]),
NPC = _countTable(_G["QuestieX_WotLKDB_npc"]),
OBJECT = _countTable(_G["QuestieX_WotLKDB_object"]),
ITEM = _countTable(_G["QuestieX_WotLKDB_item"]),
}
local _pulled = {
quest = _pullGlobal("questData", "QuestieX_WotLKDB_quest"),
npc = _pullGlobal("npcData", "QuestieX_WotLKDB_npc"),
object = _pullGlobal("objectData", "QuestieX_WotLKDB_object"),
item = _pullGlobal("itemData", "QuestieX_WotLKDB_item"),
}
Questie:Debug(Questie.DEBUG_DEVELOP, "[DBDiag] WotLKDB pull: quest=" .. tostring(_pulled.quest) .. " npc=" .. tostring(_pulled.npc) .. " obj=" .. tostring(_pulled.object) .. " item=" .. tostring(_pulled.item))
Questie.wotlkStatsCache = _counts
local QuestiePluginAPI = QuestieLoader:ImportModule("QuestiePluginAPI")
if QuestiePluginAPI then
local wotlkPlugin = QuestiePluginAPI:GetPlugin("WotLKDB")
if wotlkPlugin then
wotlkPlugin.stats.QUEST = _counts.QUEST
wotlkPlugin.stats.NPC = _counts.NPC
wotlkPlugin.stats.OBJECT = _counts.OBJECT
wotlkPlugin.stats.ITEM = _counts.ITEM
end
end
QuestieInit:LoadDatabase("npcData")
QuestieInit:LoadDatabase("objectData")
QuestieInit:LoadDatabase("questData")
QuestieInit:LoadDatabase("itemData")
end
function _QuestieInit.StartStageCoroutine()
for i = 1, #QuestieInit.Stages do
if i == 1 and QuestieInit.stage1Done then
Questie:Debug(Questie.DEBUG_INFO, "[QuestieInit:StartStageCoroutine] Stage 1 already done, skipping.")
else
if i == 1 then QuestieInit.stage1Done = true end
QuestieInit.Stages[i]()
Questie:Debug(Questie.DEBUG_INFO, "[QuestieInit:StartStageCoroutine] Stage " .. i .. " done.")
end
end
end
-- called by the PLAYER_LOGIN event handler
function QuestieInit:Init()
QuestieInit.Thread = coroutine.create(_QuestieInit.StartStageCoroutine)
local function resumeInit()
if not QuestieInit.Thread or coroutine.status(QuestieInit.Thread) == "dead" then
return -- coroutine finished or failed
end
local ok, err = coroutine.resume(QuestieInit.Thread)
if not ok then
local stack = debugstack(QuestieInit.Thread)
local msg = "QuestieInit Thread CRASHED: " .. tostring(err) .. "\n" .. tostring(stack)
Questie:Error(msg)
print("|cFFFF0000" .. msg .. "|r")
elseif coroutine.status(QuestieInit.Thread) ~= "dead" then
C_Timer.After(0.02, resumeInit) -- continue yielding using the timer shim
end
end
resumeInit()
if Questie.db.profile.trackerEnabled then
-- This needs to be called ASAP otherwise tracked Achievements in the Blizzard WatchFrame shows upon login
local WatchFrame = QuestTimerFrame or WatchFrame
if Questie.IsWotlk or QuestieCompat.Is335 then
-- Classic WotLK
WatchFrame:Hide()
else
-- Classic WoW: This moves the QuestTimerFrame off screen. A faux Hide().
-- Otherwise, if the frame is hidden then the OnUpdate doesn't work.
WatchFrame:ClearAllPoints()
WatchFrame:SetPoint("TOP", "UIParent", -10000, -10000)
end
if not (Questie.IsWotlk or QuestieCompat.Is335) then
-- Need to hook this ASAP otherwise the scroll bars show up
hooksecurefunc("ScrollFrame_OnScrollRangeChanged", function()
if TrackedQuestsScrollFrame then
TrackedQuestsScrollFrame.ScrollBar:Hide()
end
if QuestieProfilerScrollFrame then
QuestieProfilerScrollFrame.ScrollBar:Hide()
end
end)
end
end
end