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.

130 lines
4.5 KiB

-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local TSM = select(2, ...) ---@type TSM
local InventoryInfo = TSM.Init("Service.InventoryInfo") ---@class Service.InventoryInfo
local Environment = TSM.Include("Environment")
local Container = TSM.Include("Util.Container")
local Event = TSM.Include("Util.Event")
local SlotId = TSM.Include("Util.SlotId")
local Table = TSM.Include("Util.Table")
local ItemInfo = TSM.Include("Service.ItemInfo")
local TooltipScanning = TSM.Include("Service.TooltipScanning")
local private = {
slotIdLocked = {},
slotIdSoulboundCached = {},
slotIdIsBoP = {},
slotIdIsBoA = {},
}
-- ============================================================================
-- Module Loading
-- ============================================================================
InventoryInfo:OnModuleLoad(function()
Event.Register("ITEM_LOCKED", private.ItemLockedHandler)
Event.Register("ITEM_UNLOCKED", private.ItemUnlockedHandler)
Event.Register("BAG_UPDATE", private.BagUpdateHandler)
Event.Register("PLAYERBANKSLOTS_CHANGED", private.BankSlotChangedHandler)
if Environment.HasFeature(Environment.FEATURES.REAGENT_BANK) then
Event.Register("PLAYERREAGENTBANKSLOTS_CHANGED", private.ReagentBankSlotChangedHandler)
end
end)
-- ============================================================================
-- Module Functions
-- ============================================================================
--- Check if an item will go in a bag.
-- @tparam string link The item
-- @tparam number bag The bag index
-- @treturn boolean Whether or not the item will go in the bag
function InventoryInfo.ItemWillGoInBag(link, bag)
if not link or not bag then
return
end
if bag == BACKPACK_CONTAINER or bag == BANK_CONTAINER then
return true
elseif bag == REAGENTBANK_CONTAINER then
return IsReagentBankUnlocked() and ItemInfo.IsCraftingReagent(link)
end
local itemFamily = GetItemFamily(link) or 0
if ItemInfo.GetClassId(link) == Enum.ItemClass.Container then
-- bags report their family as what can go inside them, not what they can go inside
itemFamily = 0
end
local _, bagFamily = Container.GetNumFreeSlots(bag)
if not bagFamily then
return
end
return bagFamily == 0 or bit.band(itemFamily, bagFamily) > 0
end
function InventoryInfo.IsBagSlotLocked(bag, slot)
return private.slotIdLocked[SlotId.Join(bag, slot)]
end
function InventoryInfo.IsSoulbound(bag, slot)
local slotId = SlotId.Join(bag, slot)
if private.slotIdSoulboundCached[slotId] then
return private.slotIdIsBoP[slotId], private.slotIdIsBoA[slotId]
end
local scanned, isBOP, isBOA = TooltipScanning.IsSoulbound(bag, slot)
if scanned then
private.slotIdSoulboundCached[slotId] = true
private.slotIdIsBoP[slotId] = isBOP
private.slotIdIsBoA[slotId] = isBOA
end
return isBOP, isBOA
end
-- ============================================================================
-- Private Helper Functions
-- ============================================================================
function private.ItemLockedHandler(_, bag, slot)
if not slot then
return
end
private.slotIdLocked[SlotId.Join(bag, slot)] = true
end
function private.ItemUnlockedHandler(_, bag, slot)
if not slot then
return
end
private.slotIdLocked[SlotId.Join(bag, slot)] = nil
end
function private.BagUpdateHandler(_, bag)
-- clear the soulbound cache for everything in this bag
Table.Filter(private.slotIdSoulboundCached, private.SlotIdSoulboundCachedFilter, bag)
end
function private.BankSlotChangedHandler(_, slot)
if slot <= NUM_BANKGENERIC_SLOTS then
-- one of the slots of the primary bank container changed, so just clear the cache for this slot
private.slotIdSoulboundCached[SlotId.Join(BANK_CONTAINER, slot)] = nil
else
-- one of the extra bank bags changed, so clear the cache for the entire bag
Table.Filter(private.slotIdSoulboundCached, private.SlotIdSoulboundCachedFilter, slot - NUM_BANKGENERIC_SLOTS)
end
end
function private.SlotIdSoulboundCachedFilter(slotId, _, bag)
return SlotId.Split(slotId) == bag
end
function private.ReagentBankSlotChangedHandler(_, slot)
-- clear the soulbound cache for this slot
private.slotIdSoulboundCached[SlotId.Join(REAGENTBANK_CONTAINER, slot)] = nil
end