diff --git a/src/AcDream.Core.Net/Messages/GameEvents.cs b/src/AcDream.Core.Net/Messages/GameEvents.cs
index bd28a283..edb98809 100644
--- a/src/AcDream.Core.Net/Messages/GameEvents.cs
+++ b/src/AcDream.Core.Net/Messages/GameEvents.cs
@@ -343,19 +343,24 @@ public static class GameEvents
BinaryPrimitives.ReadUInt32LittleEndian(payload.Slice(8)));
}
- /// 0x0022 InventoryPutObjInContainer: server puts item into container slot.
+ /// 0x0022 InventoryPutObjInContainer: server puts item into container slot.
+ /// 4 fields (ACE GameEventItemServerSaysContainId.cs): itemGuid, containerGuid,
+ /// placement, containerType. ContainerType (0=item,1=container,2=foci) confirmed
+ /// vs holtburger events.rs fixture (slot=3 type=1).
public readonly record struct InventoryPutObjInContainer(
uint ItemGuid,
uint ContainerGuid,
- uint Placement);
+ uint Placement,
+ uint ContainerType);
public static InventoryPutObjInContainer? ParsePutObjInContainer(ReadOnlySpan payload)
{
- if (payload.Length < 12) return null;
+ if (payload.Length < 16) return null;
return new InventoryPutObjInContainer(
BinaryPrimitives.ReadUInt32LittleEndian(payload),
BinaryPrimitives.ReadUInt32LittleEndian(payload.Slice(4)),
- BinaryPrimitives.ReadUInt32LittleEndian(payload.Slice(8)));
+ BinaryPrimitives.ReadUInt32LittleEndian(payload.Slice(8)),
+ BinaryPrimitives.ReadUInt32LittleEndian(payload.Slice(12)));
}
/// 0x0196 ViewContents: full contents list of a container you opened.
diff --git a/tests/AcDream.Core.Net.Tests/Messages/GameEventsInventoryTests.cs b/tests/AcDream.Core.Net.Tests/Messages/GameEventsInventoryTests.cs
index 5a49b53a..c77f646b 100644
--- a/tests/AcDream.Core.Net.Tests/Messages/GameEventsInventoryTests.cs
+++ b/tests/AcDream.Core.Net.Tests/Messages/GameEventsInventoryTests.cs
@@ -42,4 +42,21 @@ public sealed class GameEventsInventoryTests
[Fact]
public void ParseViewContents_truncated_returnsNull()
=> Assert.Null(GameEvents.ParseViewContents(new byte[4]));
+
+ [Fact]
+ public void ParsePutObjInContainer_readsAllFourFields()
+ {
+ var b = new byte[16];
+ BinaryPrimitives.WriteUInt32LittleEndian(b.AsSpan(0), 0x50000A01u); // itemGuid
+ BinaryPrimitives.WriteUInt32LittleEndian(b.AsSpan(4), 0x500000C9u); // containerGuid
+ BinaryPrimitives.WriteUInt32LittleEndian(b.AsSpan(8), 3u); // placement
+ BinaryPrimitives.WriteUInt32LittleEndian(b.AsSpan(12), 1u); // containerType
+
+ var p = GameEvents.ParsePutObjInContainer(b);
+ Assert.NotNull(p);
+ Assert.Equal(0x50000A01u, p!.Value.ItemGuid);
+ Assert.Equal(0x500000C9u, p.Value.ContainerGuid);
+ Assert.Equal(3u, p.Value.Placement);
+ Assert.Equal(1u, p.Value.ContainerType);
+ }
}