Files
coa-tsm/TradeSkillMaster/Util/Inventory.lua
T
Andrew6810 f3e579cb57 init
2022-11-05 21:19:42 -07:00

214 lines
6.3 KiB
Lua

-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- http://www.curse.com/addons/wow/tradeskillmaster_warehousing --
-- --
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
-- All Rights Reserved* - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
-- This file contains APIs related to inventory information (bags/bank)
local TSM = select(2, ...)
local private = {}
TSMAPI:RegisterForTracing(private, "TradeSkillMaster.Util_private")
private.bagUpdateCallbacks = {}
private.bankUpdateCallbacks = {}
private.bagState = {}
private.bankState = {}
function private:OnBagUpdate()
local newState = {}
local didChange
for bag, slot, itemString, quantity in TSMAPI:GetBagIterator() do
newState[itemString] = (newState[itemString] or 0) + quantity
if not private.bagState[itemString] then
didChange = true
elseif private.bagState[itemString] then
if private.bagState[itemString] ~= quantity then
didChange = true
end
private.bagState[itemString] = nil
end
end
didChange = didChange or (next(private.bagState) and true)
private.bagState = newState
if didChange then
for _, callback in ipairs(private.bagUpdateCallbacks) do
callback(private.bagState)
end
end
end
function private:OnBankUpdate()
if not private.bankOpened then return end
local newState = {}
local didChange
for bag, slot, itemString, quantity in TSMAPI:GetBankIterator() do
newState[itemString] = (newState[itemString] or 0) + quantity
if not private.bankState[itemString] then
didChange = true
elseif private.bankState[itemString] then
if private.bankState[itemString] ~= quantity then
didChange = true
end
private.bankState[itemString] = nil
end
end
didChange = didChange or (next(private.bankState) and true)
private.bankState = newState
if didChange then
for _, callback in ipairs(private.bankUpdateCallbacks) do
callback(private.bankState)
end
end
end
function TSMAPI:RegisterForBagChange(callback)
assert(type(callback) == "function", format("Expected function, got %s.", type(callback)))
tinsert(private.bagUpdateCallbacks, callback)
end
function TSMAPI:RegisterForBankChange(callback)
assert(type(callback) == "function", format("Expected function, got %s.", type(callback)))
tinsert(private.bankUpdateCallbacks, callback)
end
-- Makes sure this bag is an actual bag and not an ammo, soul shard, etc bag
function private:IsValidBag(bag)
if bag == 0 then return true end
-- family 0 = bag with no type, family 1/2/4 are special bags that can only hold certain types of items
local itemFamily = GetItemFamily(GetInventoryItemLink("player", ContainerIDToInventoryID(bag)))
return itemFamily and (itemFamily == 0 or itemFamily > 4)
end
function TSMAPI:GetBagIterator(autoBaseItems, includeSoulbound)
local bags, b, s = {}, 1, 0
for bag=0, NUM_BAG_SLOTS do
if private:IsValidBag(bag) then
tinsert(bags, bag)
end
end
local iter
iter = function()
if bags[b] then
if s < GetContainerNumSlots(bags[b]) then
s = s + 1
else
s = 1
b = b + 1
if not bags[b] then return end
end
local link = GetContainerItemLink(bags[b], s)
if not link then
-- no item here, try the next slot
return iter()
end
local itemString
if autoBaseItems then
itemString = TSMAPI:GetBaseItemString(link, true)
else
itemString = TSMAPI:GetItemString(link)
end
if not itemString then
-- ignore invalid item
return iter()
end
if not includeSoulbound and TSMAPI:IsSoulbound(bags[b], s) then
-- ignore soulbound item
return iter()
end
local _, quantity, locked = GetContainerItemInfo(bags[b], s)
return bags[b], s, itemString, quantity, locked
end
end
return iter
end
function TSMAPI:GetBankIterator(autoBaseItems, includeSoulbound)
local bags, b, s = {}, 1, 0
tinsert(bags, -1)
for bag=NUM_BAG_SLOTS+1, NUM_BAG_SLOTS+NUM_BANKBAGSLOTS do
if private:IsValidBag(bag) then
tinsert(bags, bag)
end
end
local iter
iter = function()
if bags[b] then
if s < GetContainerNumSlots(bags[b]) then
s = s + 1
else
s = 1
b = b + 1
if not bags[b] then return end
end
local link = GetContainerItemLink(bags[b], s)
local itemString
if autoBaseItems then
itemString = TSMAPI:GetBaseItemString(link, true)
else
itemString = TSMAPI:GetItemString(link)
end
if not itemString or (not includeSoulbound and TSMAPI:IsSoulbound(bags[b], s)) then
return iter()
else
local _, quantity, locked = GetContainerItemInfo(bags[b], s)
return bags[b], s, itemString, quantity, locked
end
end
end
return iter
end
function TSMAPI:ItemWillGoInBag(link, bag)
if not link or not bag then return end
if bag == 0 then return true end
local itemFamily = GetItemFamily(link)
local bagFamily = GetItemFamily(GetBagName(bag))
if not bagFamily then return end
return bagFamily == 0 or bit.band(itemFamily, bagFamily) > 0
end
do
local BUCKET_TIME = 0.5
local function EventHandler(event, bag)
if event == "BANKFRAME_OPENED" then
private.bankOpened = true
elseif event == "BANKFRAME_CLOSED" then
private.bankOpened = nil
end
if event == "BAG_UPDATE" then
if bag > NUM_BAG_SLOTS then
TSMAPI:CreateTimeDelay("bankStateUpdate", BUCKET_TIME, private.OnBankUpdate)
else
TSMAPI:CreateTimeDelay("bagStateUpdate", BUCKET_TIME, private.OnBagUpdate)
end
elseif event == "PLAYER_ENTERING_WORLD" then
TSMAPI:CreateTimeDelay("bagStateUpdate", BUCKET_TIME, private.OnBagUpdate)
TSMAPI:CreateTimeDelay("bankStateUpdate", BUCKET_TIME, private.OnBankUpdate)
elseif event == "BANKFRAME_OPENED" or event == "PLAYERBANKSLOTS_CHANGED" then
TSMAPI:CreateTimeDelay("bankStateUpdate", BUCKET_TIME, private.OnBankUpdate)
end
end
TSM.RegisterEvent(private, "BAG_UPDATE", EventHandler)
TSM.RegisterEvent(private, "BANKFRAME_OPENED", EventHandler)
TSM.RegisterEvent(private, "BANKFRAME_CLOSED", EventHandler)
TSM.RegisterEvent(private, "PLAYER_ENTERING_WORLD", EventHandler)
TSM.RegisterEvent(private, "PLAYERBANKSLOTS_CHANGED", EventHandler)
end