fix(D.2b): gapless insert on optimistic move — stop the inventory reshuffle

Visual gate: moving an item within a bag reshuffled every item ("the order is
not set"). Root cause: insert-before set ONLY the dragged item's ContainerSlot
to N, colliding with the item already at N; the sort-by-slot tie then reordered
the whole grid on every repaint. Fix: MoveItemOptimistic now does a proper
index-based INSERT (shift the others, renumber 0..N-1 gapless) like retail's
ItemList_InsertItem, and HandleDropRelease uses the target's GRID INDEX
(SlotIndex) as the placement rather than its raw ContainerSlot. Regression test
pins the shifted, gapless order. Full suite green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-06-22 20:29:22 +02:00
parent 975f89c870
commit 82ab0e045a
3 changed files with 52 additions and 2 deletions

View file

@ -422,6 +422,23 @@ public sealed class ClientObjectTableTests
Assert.Equal(0xC5u, table.Get(0x911u)!.ContainerId);
}
[Fact]
public void MoveItemOptimistic_insertBefore_shiftsOthers_keepsGaplessOrder() // the "items change position" bug
{
var table = new ClientObjectTable();
table.Ingest(FullWeenie(0x920u, container: 0xC0u)); table.MoveItem(0x920u, 0xC0u, 0);
table.Ingest(FullWeenie(0x921u, container: 0xC0u)); table.MoveItem(0x921u, 0xC0u, 1);
table.Ingest(FullWeenie(0x922u, container: 0xC0u)); table.MoveItem(0x922u, 0xC0u, 2);
// Move 0x922 (index 2) to index 0 → order [0x922, 0x920, 0x921], slots renumbered 0,1,2 (no ties,
// no reshuffle). A raw slot-set would leave 0x922 + 0x920 both at slot 0 → unstable sort.
table.MoveItemOptimistic(0x922u, 0xC0u, 0);
Assert.Equal(new[] { 0x922u, 0x920u, 0x921u }, table.GetContents(0xC0u));
Assert.Equal(0, table.Get(0x922u)!.ContainerSlot);
Assert.Equal(1, table.Get(0x920u)!.ContainerSlot);
Assert.Equal(2, table.Get(0x921u)!.ContainerSlot);
}
[Fact]
public void ContainerIndex_SlotChange_ResortsInPlace() // guards the Reindex same-container early-out
{