perf: add caching and transfer limiting for bag/bank operations
This commit is contained in:
+112
-20
@@ -1,12 +1,100 @@
|
||||
-- Guda Bag Scanner
|
||||
-- Scans and stores bag contents
|
||||
-- Scans and stores bag contents with caching and event pending tracking
|
||||
|
||||
local addon = Guda
|
||||
|
||||
local BagScanner = {}
|
||||
addon.Modules.BagScanner = BagScanner
|
||||
|
||||
-- Scan all bags and return data
|
||||
-- Cache for bag data to avoid re-scanning all slots on every update
|
||||
local bagCache = nil
|
||||
local cacheValid = false
|
||||
|
||||
-- Event pending tracking (like Baganator's IsBagEventPending)
|
||||
local eventPending = false
|
||||
local dirtySlots = {} -- Track specific slots that changed: dirtySlots[bagID][slotID] = true
|
||||
|
||||
-- Clear the bag cache
|
||||
function BagScanner:ClearCache()
|
||||
bagCache = nil
|
||||
cacheValid = false
|
||||
dirtySlots = {}
|
||||
end
|
||||
|
||||
-- Check if a bag event is pending (use before transfers)
|
||||
function BagScanner:IsEventPending()
|
||||
return eventPending
|
||||
end
|
||||
|
||||
-- Clear the pending flag (call after processing)
|
||||
function BagScanner:ClearEventPending()
|
||||
eventPending = false
|
||||
end
|
||||
|
||||
-- Mark a specific slot as dirty (incremental tracking)
|
||||
function BagScanner:MarkSlotDirty(bagID, slotID)
|
||||
if not dirtySlots[bagID] then
|
||||
dirtySlots[bagID] = {}
|
||||
end
|
||||
dirtySlots[bagID][slotID] = true
|
||||
eventPending = true
|
||||
end
|
||||
|
||||
-- Get dirty slots and clear them
|
||||
function BagScanner:GetAndClearDirtySlots()
|
||||
local dirty = dirtySlots
|
||||
dirtySlots = {}
|
||||
return dirty
|
||||
end
|
||||
|
||||
-- Get cached bag data, or scan if cache is invalid
|
||||
function BagScanner:GetBagData()
|
||||
if cacheValid and bagCache then
|
||||
-- Process any dirty slots incrementally
|
||||
for bagID, slots in pairs(dirtySlots) do
|
||||
if bagCache[bagID] then
|
||||
for slotID in pairs(slots) do
|
||||
local oldData = bagCache[bagID].slots[slotID]
|
||||
local newData = self:ScanSlot(bagID, slotID)
|
||||
bagCache[bagID].slots[slotID] = newData
|
||||
|
||||
-- Update free slot count
|
||||
local wasEmpty = (oldData == nil)
|
||||
local isEmpty = (newData == nil)
|
||||
if wasEmpty and not isEmpty then
|
||||
bagCache[bagID].freeSlots = bagCache[bagID].freeSlots - 1
|
||||
elseif not wasEmpty and isEmpty then
|
||||
bagCache[bagID].freeSlots = bagCache[bagID].freeSlots + 1
|
||||
end
|
||||
end
|
||||
else
|
||||
-- Bag not in cache, scan it
|
||||
bagCache[bagID] = self:ScanBag(bagID)
|
||||
end
|
||||
end
|
||||
dirtySlots = {}
|
||||
return bagCache
|
||||
end
|
||||
|
||||
-- Cache miss - do full scan
|
||||
bagCache = self:ScanBags()
|
||||
cacheValid = true
|
||||
dirtySlots = {}
|
||||
return bagCache
|
||||
end
|
||||
|
||||
-- Invalidate cache (force full re-scan on next update)
|
||||
function BagScanner:InvalidateCache()
|
||||
cacheValid = false
|
||||
end
|
||||
|
||||
-- Invalidate a specific bag in the cache
|
||||
function BagScanner:InvalidateBag(bagID)
|
||||
if not bagCache then return end
|
||||
bagCache[bagID] = nil
|
||||
end
|
||||
|
||||
-- Scan all bags and return data (full scan)
|
||||
function BagScanner:ScanBags()
|
||||
local bagData = {}
|
||||
|
||||
@@ -61,8 +149,6 @@ function BagScanner:ScanSlot(bagID, slot)
|
||||
local itemLink = GetContainerItemLink(bagID, slot)
|
||||
|
||||
-- Get item info
|
||||
-- Correct order: itemName, itemLink, itemRarity, itemLevel, itemCategory, itemType,
|
||||
-- itemStackCount, itemSubType, itemTexture, itemEquipLoc, itemSellPrice
|
||||
local name, link, itemQuality, iLevel, itemCategory, itemType, itemStackCount, itemSubType, itemTexture, itemEquipLoc, itemSellPrice
|
||||
if itemLink then
|
||||
name, link, itemQuality, iLevel, itemCategory, itemType, itemStackCount, itemSubType, itemTexture, itemEquipLoc, itemSellPrice = addon.Modules.Utils:GetItemInfo(itemLink)
|
||||
@@ -76,9 +162,9 @@ function BagScanner:ScanSlot(bagID, slot)
|
||||
name = name,
|
||||
iLevel = iLevel,
|
||||
type = itemType,
|
||||
class = itemCategory, -- Category (e.g., "Consumable", "Armor")
|
||||
subclass = itemSubType, -- SubType (e.g., "Potion", "Cloth")
|
||||
equipSlot = itemEquipLoc, -- Equipment slot (e.g., "INVTYPE_HEAD") - correct now!
|
||||
class = itemCategory,
|
||||
subclass = itemSubType,
|
||||
equipSlot = itemEquipLoc,
|
||||
locked = locked,
|
||||
}
|
||||
end
|
||||
@@ -88,29 +174,35 @@ function BagScanner:SaveToDatabase()
|
||||
local bagData = self:ScanBags()
|
||||
addon.Modules.DB:SaveBags(bagData)
|
||||
addon:Debug("Bag data saved to database")
|
||||
|
||||
|
||||
-- Clear tooltip cache so counts update immediately
|
||||
if addon.Modules.Tooltip and addon.Modules.Tooltip.ClearCache then
|
||||
addon.Modules.Tooltip:ClearCache()
|
||||
end
|
||||
end
|
||||
|
||||
-- Initialize with auto-save on bag changes
|
||||
-- Initialize with event pending tracking
|
||||
function BagScanner:Initialize()
|
||||
-- Create event frame for bag updates
|
||||
local eventFrame = CreateFrame("Frame")
|
||||
self.eventFrame = eventFrame
|
||||
|
||||
-- Register bag update events
|
||||
-- Register bag update events for pending tracking
|
||||
eventFrame:RegisterEvent("BAG_UPDATE")
|
||||
eventFrame:RegisterEvent("BAG_UPDATE_DELAYED")
|
||||
--
|
||||
--eventFrame:SetScript("OnEvent", function()
|
||||
-- if event == "BAG_UPDATE" or event == "BAG_UPDATE_DELAYED" then
|
||||
-- addon:Debug("Bag update detected, saving data...")
|
||||
-- self:SaveToDatabase()
|
||||
-- end
|
||||
--end)
|
||||
eventFrame:SetScript("OnEvent", function()
|
||||
eventPending = true
|
||||
-- Mark the specific bag as having changes
|
||||
if arg1 then
|
||||
if not dirtySlots[arg1] then
|
||||
dirtySlots[arg1] = {}
|
||||
end
|
||||
-- We don't know which slot, so mark entire bag for rescan
|
||||
-- by invalidating it
|
||||
if bagCache and bagCache[arg1] then
|
||||
bagCache[arg1] = nil
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
addon:Debug("Bag scanner initialized with auto-save")
|
||||
end
|
||||
addon:Debug("Bag scanner initialized with event pending tracking")
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user