diff --git a/Bagnon/components/item.lua b/Bagnon/components/item.lua index e5c8324..ac871b8 100644 --- a/Bagnon/components/item.lua +++ b/Bagnon/components/item.lua @@ -248,6 +248,37 @@ end --[[ Update Methods ]] -- +-- Shared retry queue for slots whose live read returned nil for a previously +-- occupied slot — almost always a server lag race where item data hasn't +-- arrived yet. Retrying renders the correct texture instead of flashing empty. +local RENDER_RETRY_INTERVAL = 0.1 +local RENDER_RETRY_MAX = 30 -- ~3s cap so a genuine empty still resolves +local pendingSlots = {} +local slotRetryFrame = CreateFrame('Frame') +slotRetryFrame.elapsed = 0 +slotRetryFrame:Hide() +slotRetryFrame:SetScript('OnUpdate', function(self, elapsed) + self.elapsed = self.elapsed + elapsed + if self.elapsed < RENDER_RETRY_INTERVAL then return end + self.elapsed = 0 + local q = pendingSlots + pendingSlots = {} + for slot in pairs(q) do + if slot:IsVisible() then + slot:Update() + end + end + if not next(pendingSlots) then + self:Hide() + end +end) + +local function scheduleSlotRetry(slot) + pendingSlots[slot] = true + slotRetryFrame.elapsed = 0 + slotRetryFrame:Show() +end + -- Update the texture, lock status, and other information about an item function ItemSlot:Update() @@ -255,6 +286,17 @@ function ItemSlot:Update() local texture, count, locked, quality, readable, lootable, link = self:GetItemSlotInfo() + -- Lag race: the slot was occupied a moment ago but the server hasn't + -- delivered item data yet. Defer rendering so the slot doesn't flash empty. + if self.hasItem and (not link) then + self.renderRetries = (self.renderRetries or 0) + 1 + if self.renderRetries < RENDER_RETRY_MAX then + scheduleSlotRetry(self) + return + end + end + self.renderRetries = nil + self:SetItem(link) self:SetTexture(texture) self:SetCount(count)