feat(D.2b): wire ConfirmMove (0x0022 echo) + RollbackMove (0x00A0) for optimistic inventory moves
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6f0012bd14
commit
4aebf444d9
2 changed files with 31 additions and 7 deletions
|
|
@ -246,8 +246,9 @@ public static class GameEventWiring
|
||||||
dispatcher.Register(GameEventType.InventoryPutObjInContainer, e =>
|
dispatcher.Register(GameEventType.InventoryPutObjInContainer, e =>
|
||||||
{
|
{
|
||||||
var p = GameEvents.ParsePutObjInContainer(e.Payload.Span);
|
var p = GameEvents.ParsePutObjInContainer(e.Payload.Span);
|
||||||
if (p is not null) items.MoveItem(p.Value.ItemGuid, p.Value.ContainerGuid,
|
if (p is null) return;
|
||||||
newSlot: (int)p.Value.Placement);
|
items.MoveItem(p.Value.ItemGuid, p.Value.ContainerGuid, newSlot: (int)p.Value.Placement);
|
||||||
|
items.ConfirmMove(p.Value.ItemGuid); // B-Drag: the server confirmed our optimistic move
|
||||||
});
|
});
|
||||||
|
|
||||||
// ViewContents (0x0196) — the server's AUTHORITATIVE full contents list for a container you
|
// ViewContents (0x0196) — the server's AUTHORITATIVE full contents list for a container you
|
||||||
|
|
@ -273,14 +274,16 @@ public static class GameEventWiring
|
||||||
if (guid is not null) items.MoveItem(guid.Value, newContainerId: 0u);
|
if (guid is not null) items.MoveItem(guid.Value, newContainerId: 0u);
|
||||||
});
|
});
|
||||||
|
|
||||||
// B-Wire: InventoryServerSaveFailed (0x00A0) — rollback of a speculative move.
|
// B-Drag: InventoryServerSaveFailed (0x00A0) — server rejected an optimistic move.
|
||||||
// acdream does not do speculative moves yet (read-only inventory); parse + log
|
// Snap the item back to its pre-move slot. Log only when there was no pending move
|
||||||
// so the wire is correct. B-Drag wires the rollback behavior. (Divergence note.)
|
// (a server-initiated failure on a non-optimistic path).
|
||||||
dispatcher.Register(GameEventType.InventoryServerSaveFailed, e =>
|
dispatcher.Register(GameEventType.InventoryServerSaveFailed, e =>
|
||||||
{
|
{
|
||||||
var p = GameEvents.ParseInventoryServerSaveFailed(e.Payload.Span);
|
var p = GameEvents.ParseInventoryServerSaveFailed(e.Payload.Span);
|
||||||
if (p is not null)
|
if (p is null) return;
|
||||||
Console.WriteLine($"[B-Wire] InventoryServerSaveFailed guid=0x{p.Value.ItemGuid:X8} err=0x{p.Value.WeenieError:X}");
|
// B-Drag: the server rejected an optimistic move — snap the item back to its pre-move slot.
|
||||||
|
if (!items.RollbackMove(p.Value.ItemGuid))
|
||||||
|
Console.WriteLine($"[B-Drag] InventoryServerSaveFailed guid=0x{p.Value.ItemGuid:X8} err=0x{p.Value.WeenieError:X} (no pending move)");
|
||||||
});
|
});
|
||||||
|
|
||||||
// B-Wire: CloseGroundContainer (0x0052) — server closed a ground-container
|
// B-Wire: CloseGroundContainer (0x0052) — server closed a ground-container
|
||||||
|
|
|
||||||
|
|
@ -585,6 +585,27 @@ public sealed class GameEventWiringTests
|
||||||
d.Dispatch(env!.Value);
|
d.Dispatch(env!.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireAll_InventoryServerSaveFailed_RollsBackOptimisticMove()
|
||||||
|
{
|
||||||
|
var (d, items, _, _, _) = MakeAll();
|
||||||
|
// An item known to be in container 0xC0 at slot 2, then optimistically moved to 0xC1.
|
||||||
|
items.RecordMembership(0x50000B01u, containerId: 0x500000C0u);
|
||||||
|
items.MoveItem(0x50000B01u, 0x500000C0u, 2);
|
||||||
|
items.MoveItemOptimistic(0x50000B01u, 0x500000C1u, 0);
|
||||||
|
Assert.Equal(0x500000C1u, items.Get(0x50000B01u)!.ContainerId); // moved (optimistic)
|
||||||
|
|
||||||
|
// Server bounces it: InventoryServerSaveFailed (itemGuid, weenieError).
|
||||||
|
byte[] payload = new byte[8];
|
||||||
|
BinaryPrimitives.WriteUInt32LittleEndian(payload.AsSpan(0), 0x50000B01u);
|
||||||
|
BinaryPrimitives.WriteUInt32LittleEndian(payload.AsSpan(4), 0x1Au); // some WeenieError
|
||||||
|
var env = GameEventEnvelope.TryParse(WrapEnvelope(GameEventType.InventoryServerSaveFailed, payload));
|
||||||
|
d.Dispatch(env!.Value);
|
||||||
|
|
||||||
|
Assert.Equal(0x500000C0u, items.Get(0x50000B01u)!.ContainerId); // snapped back
|
||||||
|
Assert.Equal(2, items.Get(0x50000B01u)!.ContainerSlot);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void WireAll_InventoryPutObjectIn3D_UnparentsFromContainer()
|
public void WireAll_InventoryPutObjectIn3D_UnparentsFromContainer()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue