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.

218 lines
7.3 KiB

-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local TSM = select(2, ...) ---@type TSM
local Container = TSM.Init("Util.Container") ---@class Util.Container
local Environment = TSM.Include("Environment")
local SlotId = TSM.Include("Util.SlotId")
local private = {
useCTable = nil,
numBagSlots = nil,
}
-- ============================================================================
-- Module Loading
-- ============================================================================
Container:OnModuleLoad(function()
private.useCTable = Environment.HasFeature(Environment.FEATURES.C_CONTAINER)
private.numBagSlots = NUM_BAG_SLOTS + (Environment.HasFeature(Environment.FEATURES.REAGENT_BAG) and NUM_REAGENTBAG_SLOTS or 0)
end)
-- ============================================================================
-- Module Functions
-- ============================================================================
---Iterates over all bag slots
---@return fun(): number, number @An iterator with fields: `index`, `slotId`
function Container.GetBagSlotIterator()
return private.BagSlotIterator, nil, SlotId.Join(0, 0)
end
---Gets the item family for items that can fit in the specified bag.
---@param bag number The bag
---@return number
function Container.GetBagItemFamily(bag)
if bag == BACKPACK_CONTAINER then
return 0
end
local inventoryId = nil
if private.useCTable then
inventoryId = C_Container.ContainerIDToInventoryID(bag)
else
inventoryId = ContainerIDToInventoryID(bag)
end
return GetItemFamily(GetInventoryItemLink("player", inventoryId)) or 0
end
---Gets a list of empty slotIds and their sort values.
---@param bag number The bag to check
---@param itemFamily number The item family to check for
---@param emptySlotIds number[] A table to store the list of empty slotIds in
---@param sortvalue table<number, number> A table to store the sort values in
function Container.GenerateSortedEmptyFamilySlots(bag, itemFamily, emptySlotIds, sortvalue)
local bagFamily = Container.GetBagItemFamily(bag)
if bagFamily == 0 or bit.band(itemFamily, bagFamily) > 0 then
for slot = 1, Container.GetNumSlots(bag) do
if not Container.GetItemInfo(bag, slot) then
local slotId = SlotId.Join(bag, slot)
tinsert(emptySlotIds, slotId)
sortvalue[slotId] = slotId + (bagFamily > 0 and 0 or 100000)
end
end
end
end
---Returns the total number of bag slots.
---@return number
function Container.GetNumBags()
return private.numBagSlots
end
---Returns the indexes for the fist and last bank bag slots.
---@return number @The index of the first bank bag
---@return number @The index of the last bank bag
function Container.GetBankBagIndexes()
return private.numBagSlots + 1, private.numBagSlots + NUM_BANKBAGSLOTS
end
---Returns the total number of slots in the bag specified by the index.
---@param bag number The index of the bag
---@return number
function Container.GetNumSlots(bag)
if private.useCTable then
return C_Container.GetContainerNumSlots(bag)
else
return GetContainerNumSlots(bag)
end
end
---Returns the number of free slots in a bag.
---@param bag number The index of the bag
---@return number
function Container.GetNumFreeSlots(bag)
if private.useCTable then
return C_Container.GetContainerNumFreeSlots(bag)
else
return GetContainerNumFreeSlots(bag)
end
end
---Returns the item ID in a container slot.
---@param bag number The index of the bag
---@param slot number The index of the slot whitin the bag
---@return number
function Container.GetItemId(bag, slot)
if private.useCTable then
return C_Container.GetContainerItemID(bag, slot)
else
return GetContainerItemID(bag, slot)
end
end
---Returns info for an item in a container slot.
---@param bag number The index of the bag
---@param slot number The index of the slot whitin the bag
---@return number iconFileID The icon texture
---@return number stackCount The number of items in the bag slot
---@return boolean isLocked Whether the bag slot is locked or not
---@return number quality The quality of the contained item
---@return boolean isReadable Whether the item in the bag slot is readable
---@return boolean hasLoot Whether the item in the bag slot is lootable
---@return string link The itemLink of the item in the bag slot
---@return boolean isFiltered Whether the item in the bag slot is filtered out
---@return boolean hasNoValue Whether the item has no gold value
---@return number itemId The unique identifier for the item in the bag slot
---@return boolean isBound Whether the item is bound of the character
function Container.GetItemInfo(bag, slot)
if private.useCTable then
local info = C_Container.GetContainerItemInfo(bag, slot)
if not info then
return
end
return info.iconFileID, info.stackCount, info.isLocked, info.quality, info.isReadable, info.hasLoot, info.hyperlink, info.isFiltered, info.hasNoValue, info.itemID, info.isBound
else
return GetContainerItemInfo(bag, slot)
end
end
---Returns a link of the object located in the specified slot of a specified bag.
---@param bag number The index of the bag
---@param slot number The index of the slot whitin the bag
---@return string
function Container.GetItemLink(bag, slot)
if private.useCTable then
return C_Container.GetContainerItemLink(bag, slot)
else
return GetContainerItemLink(bag, slot)
end
end
---Uses an item from given bag slot.
---@param bag number The index of the bag
---@param slot number The index of the slot whitin the bag
function Container.UseItem(bag, slot)
if private.useCTable then
return C_Container.UseContainerItem(bag, slot)
else
return UseContainerItem(bag, slot)
end
end
---Pick up an item from given bag slot.
---@param bag number The index of the bag
---@param slot number The index of the slot whitin the bag
function Container.PickupItem(bag, slot)
if private.useCTable then
return C_Container.PickupContainerItem(bag, slot)
else
return PickupContainerItem(bag, slot)
end
end
---Places part of a stack of items from a container onto the cursor.
---@param bag number The index of the bag
---@param slot number The index of the slot whitin the bag
---@param count number The quantity to split
function Container.SplitItem(bag, slot, count)
if private.useCTable then
return C_Container.SplitContainerItem(bag, slot, count)
else
return SplitContainerItem(bag, slot, count)
end
end
---Register a secure hook function for when a container item is used.
---@param func function
function Container.SecureHookUseItem(func)
if private.useCTable then
hooksecurefunc(C_Container, "UseContainerItem", func)
else
hooksecurefunc("UseContainerItem", func)
end
end
-- ============================================================================
-- Private Helper Functions
-- ============================================================================
function private.BagSlotIterator(_, slotId)
local bag, slot = SlotId.Split(slotId)
while bag <= private.numBagSlots do
slot = slot + 1
if slot <= Container.GetNumSlots(bag) then
return SlotId.Join(bag, slot)
end
bag = bag + 1
slot = 0
end
end