From 31864a467e2e3ca4e68db40f57ecbdc081d928f9 Mon Sep 17 00:00:00 2001 From: Xurkon Date: Wed, 3 Jun 2026 06:41:23 -0500 Subject: [PATCH] fix: harden learner spawn suppression --- Database/QuestieDB.lua | 68 +++++++++++++++++++++++++++++++++++--- Modules/QuestieLearner.lua | 20 +++++++++++ 2 files changed, 84 insertions(+), 4 deletions(-) diff --git a/Database/QuestieDB.lua b/Database/QuestieDB.lua index 97c2e09..0e6fa78 100644 --- a/Database/QuestieDB.lua +++ b/Database/QuestieDB.lua @@ -68,6 +68,68 @@ local function MergeSpawnTables(baseSpawns, overrideSpawns) return merged end +local function GetSpawnTable(entry, primaryKey, legacyKey) + if type(entry) ~= "table" then + return nil + end + + local spawns = entry[primaryKey] + if type(spawns) == "table" then + return spawns + end + + spawns = entry[legacyKey] + if type(spawns) == "table" then + return spawns + end + + return nil +end + +local function NormalizeLearnerSpawnEntry(entry, primaryKey, legacyKey) + if type(entry) ~= "table" then + return false + end + + local changed = false + local currentSpawns = entry[primaryKey] + local legacySpawns = entry[legacyKey] + + if currentSpawns ~= nil and type(currentSpawns) ~= "table" then + entry[primaryKey] = nil + currentSpawns = nil + changed = true + end + + if legacySpawns ~= nil and type(legacySpawns) ~= "table" then + entry[legacyKey] = nil + legacySpawns = nil + changed = true + end + + if type(currentSpawns) ~= "table" and type(legacySpawns) == "table" then + entry[primaryKey] = CopySpawnTable(legacySpawns) + entry[legacyKey] = nil + return true + end + + if type(currentSpawns) == "table" and type(legacySpawns) == "table" then + entry[primaryKey] = MergeSpawnTables(currentSpawns, legacySpawns) + entry[legacyKey] = nil + return true + end + + if type(currentSpawns) == "table" and legacySpawns ~= nil then + entry[legacyKey] = nil + changed = true + end + + return changed +end + +QuestieDB.private.GetLearnerSpawnTable = GetSpawnTable +QuestieDB.private.NormalizeLearnerSpawnEntry = NormalizeLearnerSpawnEntry + local function _MergeOverride(result, override, rawdata, keyMap) for stringKey, intKey in pairs(keyMap) do local overrideValue = override[stringKey] @@ -749,8 +811,7 @@ function QuestieDB.GetSuppressedNPCs(zoneId) local threshold = ld.settings.minConfidencePins or 2 local npcId, entry = next(ld.npcs) while npcId do - -- Support both old format ([4]=spawns) and new format ([7]=spawns) - local spawns = entry[7] or entry[4] + local spawns = GetSpawnTable(entry, 7, 4) if entry.mc and entry.mc >= threshold and spawns and spawns[zoneId] then suppressed[npcId] = true end @@ -771,8 +832,7 @@ function QuestieDB.GetSuppressedObjects(zoneId) local threshold = ld.settings.minConfidencePins or 2 local objId, entry = next(ld.objects) while objId do - -- Support both old format ([4]=spawns) and new format ([7]=spawns) - local spawns = entry[4] or entry[7] + local spawns = GetSpawnTable(entry, 4, 7) if entry.mc and entry.mc >= threshold and spawns and spawns[zoneId] then suppressed[objId] = true end diff --git a/Modules/QuestieLearner.lua b/Modules/QuestieLearner.lua index df5e421..16a1a27 100644 --- a/Modules/QuestieLearner.lua +++ b/Modules/QuestieLearner.lua @@ -1690,6 +1690,26 @@ function QuestieLearner:InjectLearnedData() end local learned = Questie.dbLearner.global + -- Normalize malformed saved variables before any migration or injection. + -- This prevents old learner rows from carrying numeric spawn fields + -- into the suppression path and crashing the quest objective filter. + local sanitizedEntries = 0 + if QuestieDB and QuestieDB.private and QuestieDB.private.NormalizeLearnerSpawnEntry then + for _, data in pairs(learned.npcs) do + if QuestieDB.private.NormalizeLearnerSpawnEntry(data, 7, 4) then + sanitizedEntries = sanitizedEntries + 1 + end + end + for _, data in pairs(learned.objects) do + if QuestieDB.private.NormalizeLearnerSpawnEntry(data, 4, 7) then + sanitizedEntries = sanitizedEntries + 1 + end + end + if sanitizedEntries > 0 then + Questie:Debug(Questie.DEBUG_INFO, "[QuestieLearner] Sanitized", sanitizedEntries, "malformed learned spawn entries") + end + end + -- Migrate old-format NPC data ([4]=spawns, [5]=zoneId) to new format ([7]=spawns, [9]=zoneId) -- Always merge [4] into [7], even when [7] already has partial data from a recent session. for npcId, data in pairs(learned.npcs) do