diff --git a/Bagnon/utility/itemEvents.lua b/Bagnon/utility/itemEvents.lua index 6ba4e41..acc1843 100644 --- a/Bagnon/utility/itemEvents.lua +++ b/Bagnon/utility/itemEvents.lua @@ -45,6 +45,7 @@ Bagnon.BagEvents = BagEvents local slots = {} local bagTypes = {} +local pendingBags = {} local function ToIndex(bag, slot) return (bag < 0 and bag*100 - slot) or bag*100 + slot @@ -54,6 +55,29 @@ local function GetBagSize(bag) return (bag == KEYRING_CONTAINER and GetKeyRingSize()) or GetContainerNumSlots(bag) end +-- Defers a re-check of a bag by ~0.25s; used when a previously occupied slot +-- reads back nil (lag race between BAG_UPDATE and item data arriving). +local retryFrame = CreateFrame('Frame') +retryFrame.elapsed = 0 +retryFrame:Hide() +retryFrame:SetScript('OnUpdate', function(self, elapsed) + self.elapsed = self.elapsed + elapsed + if self.elapsed < 0.25 then return end + self.elapsed = 0 + self:Hide() + local bags = pendingBags + pendingBags = {} + for bag in pairs(bags) do + Bagnon.BagEvents:UpdateItems(bag, true) + end +end) + +local function scheduleRetry(bag) + pendingBags[bag] = true + retryFrame.elapsed = 0 + retryFrame:Show() +end + --[[ Startup ]]-- @@ -110,7 +134,7 @@ function BagEvents:RemoveItem(bag, slot) end end -function BagEvents:UpdateItem(bag, slot) +function BagEvents:UpdateItem(bag, slot, isRetry) local data = slots[ToIndex(bag, slot)] if data then @@ -121,6 +145,14 @@ function BagEvents:UpdateItem(bag, slot) local start, duration, enable = GetContainerItemCooldown(bag, slot) local onCooldown = (start > 0 and duration > 0 and enable > 0) + -- A previously occupied slot reading back nil is usually a lag race between + -- BAG_UPDATE and item data arriving from the server. Defer once before drawing + -- the slot as empty; on the second pass we trust whatever we read. + if prevLink and (not link) and (not isRetry) then + scheduleRetry(bag) + return + end + if not(prevLink == link and prevCount == count) then data[1] = link data[2] = count @@ -132,9 +164,9 @@ function BagEvents:UpdateItem(bag, slot) end end -function BagEvents:UpdateItems(bag) +function BagEvents:UpdateItems(bag, isRetry) for slot = 1, GetBagSize(bag) do - self:UpdateItem(bag, slot) + self:UpdateItem(bag, slot, isRetry) end end