fix(sort): refuse to sort inventory when read is inconsistent with server

Post-sort holes were caused by the planning phase, not the execution
phase. When GetContainerItemInfo/Link transiently returns nil for an
occupied slot during server lag, CreateBagFromID marks it <EMPTY>, the
sort algorithm moves real items into that "destination", and we end up
with literal gaps where the misclassified items used to be.

Validate the read against GetContainerNumFreeSlots before sorting; if
counts disagree, print a chat warning and abort instead of corrupting
the layout. User retries after a moment.
This commit is contained in:
2026-05-16 10:36:16 +02:00
parent 844f9c8a4e
commit da2d323018
+29
View File
@@ -257,6 +257,23 @@ local function SortBag(bag)
end
end
-- Returns true iff every slot in `bagID` whose GetContainerItemLink is nil
-- is also reported empty by GetContainerNumFreeSlots. When the server is
-- laggy GetContainerItemInfo/Link can transiently return nil for slots that
-- actually contain items; sorting on that snapshot generates moves that
-- treat occupied slots as empty destinations, leaving holes in the result.
local function IsBagReadConsistent(bagID)
local slots = GetContainerNumSlots(bagID) or 0
local reportedFree = select(1, GetContainerNumFreeSlots(bagID)) or 0
local actualEmpty = 0
for s = 1, slots do
if not GetContainerItemLink(bagID, s) then
actualEmpty = actualEmpty + 1
end
end
return actualEmpty == reportedFree, actualEmpty, reportedFree
end
local function CreateBagFromID(bagID)
local items = GetContainerNumSlots(bagID);
local bag = {};
@@ -349,6 +366,18 @@ function SortBtn:OnClick()
local bags = {};
if self.frameID == "inventory" then
-- Refuse to sort if any bag's read is inconsistent with the server's
-- reported free-slot count — sorting on that snapshot is what causes
-- the post-sort holes on a laggy server.
for i = 0, NUM_BAG_FRAMES, 1 do
local ok, empty, reported = IsBagReadConsistent(i)
if not ok then
DEFAULT_CHAT_FRAME:AddMessage(format(
"|cFFFFAA00Bagnon: bag %d not fully loaded (read %d empty, server says %d) — try sort again in a moment.|r",
i, empty, reported))
return
end
end
isGuildBankSort = false;
for i = 0, NUM_BAG_FRAMES, 1 do
local bag = CreateBagFromID(i);