You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
212 lines
6.2 KiB
212 lines
6.2 KiB
|
2 years ago
|
local Addon = LibStub('AceAddon-3.0'):GetAddon('WoWthing_Collector')
|
||
|
|
local Module = Addon:NewModule('Bags')
|
||
|
|
|
||
|
|
|
||
|
|
local C_Container_ContainerIDToInventoryID = C_Container.ContainerIDToInventoryID
|
||
|
|
local C_Container_GetContainerItemID = C_Container.GetContainerItemID
|
||
|
|
local C_Container_GetContainerItemInfo = C_Container.GetContainerItemInfo
|
||
|
|
local C_Container_GetContainerNumSlots = C_Container.GetContainerNumSlots
|
||
|
|
local C_Item_IsItemDataCachedByID = C_Item.IsItemDataCachedByID
|
||
|
|
local C_Item_RequestLoadItemDataByID = C_Item.RequestLoadItemDataByID
|
||
|
|
|
||
|
|
function Module:OnEnable()
|
||
|
|
Addon.charData.bags = Addon.charData.bags or {}
|
||
|
|
Addon.charData.items = Addon.charData.items or {}
|
||
|
|
|
||
|
|
self.isBankOpen = false
|
||
|
|
self.isRequesting = false
|
||
|
|
self.isScanning = false
|
||
|
|
self.wasReagentBankChanged = false
|
||
|
|
self.dirtyBags = {}
|
||
|
|
self.requested = {}
|
||
|
|
|
||
|
|
self:RegisterEvent('BAG_UPDATE')
|
||
|
|
self:RegisterEvent('BANKFRAME_CLOSED')
|
||
|
|
self:RegisterEvent('BANKFRAME_OPENED')
|
||
|
|
self:RegisterEvent('ITEM_LOCKED')
|
||
|
|
self:RegisterEvent('ITEM_UNLOCKED')
|
||
|
|
self:RegisterEvent('PLAYERREAGENTBANKSLOTS_CHANGED')
|
||
|
|
|
||
|
|
self:RegisterBucketEvent({ 'BAG_UPDATE_DELAYED' }, 1, 'UpdateBags')
|
||
|
|
self:RegisterBucketEvent({ 'ITEM_DATA_LOAD_RESULT' }, 2, 'UpdateRequested')
|
||
|
|
self:RegisterBucketEvent(
|
||
|
|
{
|
||
|
|
'ITEM_LOCKED',
|
||
|
|
'ITEM_UNLOCKED',
|
||
|
|
},
|
||
|
|
2,
|
||
|
|
'StartUpdateBagsTimer'
|
||
|
|
)
|
||
|
|
end
|
||
|
|
|
||
|
|
function Module:OnEnteringWorld()
|
||
|
|
C_Timer.After(5, function() self:SetPlayerBagsDirty() end)
|
||
|
|
end
|
||
|
|
|
||
|
|
function Module:BAG_UPDATE(_, bagId)
|
||
|
|
self.dirtyBags[bagId] = true
|
||
|
|
end
|
||
|
|
|
||
|
|
function Module:BANKFRAME_CLOSED()
|
||
|
|
self.isBankOpen = false
|
||
|
|
end
|
||
|
|
|
||
|
|
-- Mark bank and bank bags for scanning
|
||
|
|
function Module:BANKFRAME_OPENED()
|
||
|
|
self.isBankOpen = true
|
||
|
|
self.dirtyBags[Enum.BagIndex.Bank] = true
|
||
|
|
self.dirtyBags[Enum.BagIndex.Reagentbank] = true
|
||
|
|
for i = Enum.BagIndex.BankBag_1, Enum.BagIndex.BankBag_7 do
|
||
|
|
self.dirtyBags[i] = true
|
||
|
|
end
|
||
|
|
|
||
|
|
self:StartUpdateBagsTimer()
|
||
|
|
end
|
||
|
|
|
||
|
|
function Module:ITEM_LOCKED(_, bag, slot)
|
||
|
|
if slot ~= nil then
|
||
|
|
self.dirtyBags[bag] = true
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function Module:ITEM_UNLOCKED(_, bag, slot)
|
||
|
|
if slot ~= nil then
|
||
|
|
self.dirtyBags[bag] = true
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function Module:PLAYERREAGENTBANKSLOTS_CHANGED()
|
||
|
|
self.wasReagentBankChanged = true
|
||
|
|
self.dirtyBags[Enum.BagIndex.Reagentbank] = true
|
||
|
|
|
||
|
|
self:StartUpdateBagsTimer()
|
||
|
|
end
|
||
|
|
|
||
|
|
function Module:SetPlayerBagsDirty()
|
||
|
|
for i = 0, NUM_TOTAL_BAG_FRAMES do
|
||
|
|
self.dirtyBags[i] = true
|
||
|
|
end
|
||
|
|
|
||
|
|
self:StartUpdateBagsTimer()
|
||
|
|
end
|
||
|
|
|
||
|
|
function Module:StartUpdateBagsTimer()
|
||
|
|
self:UniqueTimer('UpdateBags', 2, 'UpdateBags')
|
||
|
|
end
|
||
|
|
|
||
|
|
function Module:UpdateRequested(items)
|
||
|
|
if not self.isRequesting then return end
|
||
|
|
|
||
|
|
for itemId, _ in pairs(items) do
|
||
|
|
self.requested[itemId] = nil
|
||
|
|
end
|
||
|
|
|
||
|
|
local keys = Addon:TableKeys(self.requested)
|
||
|
|
if #keys == 0 then
|
||
|
|
self.isRequesting = false
|
||
|
|
self:StartUpdateBagsTimer()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function Module:UpdateBags()
|
||
|
|
if self.isRequesting or self.isScanning then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
self.isScanning = true
|
||
|
|
self.scanQueue = {}
|
||
|
|
for bagId, _ in pairs(self.dirtyBags) do
|
||
|
|
tinsert(self.scanQueue, bagId)
|
||
|
|
self.dirtyBags[bagId] = nil
|
||
|
|
end
|
||
|
|
|
||
|
|
C_Timer.After(0, function() self:ScanBagQueue() end)
|
||
|
|
end
|
||
|
|
|
||
|
|
function Module:ScanBagQueue()
|
||
|
|
local bagId = tremove(self.scanQueue)
|
||
|
|
if bagId == nil then
|
||
|
|
self.isScanning = false
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
-- Short circuit if bank isn't open
|
||
|
|
local isBank = (
|
||
|
|
bagId == Enum.BagIndex.Bank or
|
||
|
|
bagId == Enum.BagIndex.Reagentbank or
|
||
|
|
(bagId >= Enum.BagIndex.BankBag_1 and bagId <= Enum.BagIndex.BankBag_7)
|
||
|
|
)
|
||
|
|
local scan = true
|
||
|
|
|
||
|
|
if isBank and not self.isBankOpen then
|
||
|
|
scan = false
|
||
|
|
end
|
||
|
|
-- Reagent bank is weird, make sure that the bank is open or it was actually updated
|
||
|
|
if bagId == Enum.BagIndex.Reagentbank then
|
||
|
|
if not (self.isBankOpen or self.wasReagentBankChanged) then
|
||
|
|
scan = false
|
||
|
|
end
|
||
|
|
self.wasReagentBankChanged = false
|
||
|
|
end
|
||
|
|
|
||
|
|
local requestedData = false
|
||
|
|
if scan then
|
||
|
|
local now = time()
|
||
|
|
|
||
|
|
if isBank then
|
||
|
|
Addon.charData.scanTimes["bank"] = now
|
||
|
|
else
|
||
|
|
Addon.charData.scanTimes["bags"] = now
|
||
|
|
end
|
||
|
|
|
||
|
|
Addon.charData.items["b"..bagId] = {}
|
||
|
|
local bag = Addon.charData.items["b"..bagId]
|
||
|
|
|
||
|
|
-- Update bag ID
|
||
|
|
if bagId >= 1 then
|
||
|
|
local bagItemID, _ = GetInventoryItemID('player', C_Container_ContainerIDToInventoryID(bagId))
|
||
|
|
Addon.charData.bags["b"..bagId] = bagItemID
|
||
|
|
end
|
||
|
|
|
||
|
|
local numSlots = C_Container_GetContainerNumSlots(bagId)
|
||
|
|
if numSlots > 0 then
|
||
|
|
for slot = 1, numSlots do
|
||
|
|
-- This always works, even if the full item data isn't cached
|
||
|
|
local itemId = C_Container_GetContainerItemID(bagId, slot)
|
||
|
|
if itemId then
|
||
|
|
if C_Item_IsItemDataCachedByID(itemId) then
|
||
|
|
local itemInfo = C_Container_GetContainerItemInfo(bagId, slot)
|
||
|
|
if itemInfo ~= nil and itemInfo.hyperlink ~= nil then
|
||
|
|
local parsed = Addon:ParseItemLink(itemInfo.hyperlink, itemInfo.quality or -1, itemInfo.stackCount or 1)
|
||
|
|
bag["s"..slot] = parsed
|
||
|
|
end
|
||
|
|
elseif self.requested[itemId] == nil then
|
||
|
|
requestedData = true
|
||
|
|
self.requested[itemId] = true
|
||
|
|
C_Item_RequestLoadItemDataByID(itemId)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
-- If we requested item data, come back and scan this bag again later
|
||
|
|
if requestedData then
|
||
|
|
self.dirtyBags[bagId] = true
|
||
|
|
self.isRequesting = true
|
||
|
|
end
|
||
|
|
|
||
|
|
-- If the scan queue still has bags, add a timer for the next one
|
||
|
|
if #self.scanQueue > 0 then
|
||
|
|
C_Timer.After(0, function() self:ScanBagQueue() end)
|
||
|
|
else
|
||
|
|
self.isScanning = false
|
||
|
|
|
||
|
|
-- Queue another scan if any bags are dirty
|
||
|
|
local bagKeys = Addon:TableKeys(self.dirtyBags)
|
||
|
|
if #bagKeys > 0 then
|
||
|
|
self:StartUpdateBagsTimer()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|