diff --git a/src/AcDream.Core.Net/Messages/InteractRequests.cs b/src/AcDream.Core.Net/Messages/InteractRequests.cs index d9cfe7b..68b3b1e 100644 --- a/src/AcDream.Core.Net/Messages/InteractRequests.cs +++ b/src/AcDream.Core.Net/Messages/InteractRequests.cs @@ -29,6 +29,7 @@ public static class InteractRequests public const uint UseOpcode = 0x0036u; public const uint UseWithTargetOpcode = 0x0035u; public const uint TeleToLifestoneOpcode = 0x0063u; + public const uint PutItemInContainerOpcode = 0x0019u; /// /// Use an object: click a door, loot a corpse, talk to an NPC, @@ -73,4 +74,36 @@ public static class InteractRequests BinaryPrimitives.WriteUInt32LittleEndian(body.AsSpan(8), TeleToLifestoneOpcode); return body; } + + /// + /// Pick up a ground item or move an item between containers. The + /// server places the item in at + /// the given slot (pass 0 to let the + /// server choose). For F-key ground-pickup, pass the player's own + /// server guid as . + /// + /// + /// Wire layout (ACE GameActionPutItemInContainer.Handle): + /// + /// u32 0xF7B1 + /// u32 gameActionSequence + /// u32 0x0019 // PutItemInContainer + /// u32 itemGuid // server guid of the item + /// u32 containerGuid // destination container (player or bag) + /// i32 placement // 0 = server picks slot + /// + /// + /// + public static byte[] BuildPickUp( + uint gameActionSequence, uint itemGuid, uint containerGuid, int placement) + { + byte[] body = new byte[24]; + BinaryPrimitives.WriteUInt32LittleEndian(body, GameActionEnvelope); + BinaryPrimitives.WriteUInt32LittleEndian(body.AsSpan(4), gameActionSequence); + BinaryPrimitives.WriteUInt32LittleEndian(body.AsSpan(8), PutItemInContainerOpcode); + BinaryPrimitives.WriteUInt32LittleEndian(body.AsSpan(12), itemGuid); + BinaryPrimitives.WriteUInt32LittleEndian(body.AsSpan(16), containerGuid); + BinaryPrimitives.WriteInt32LittleEndian (body.AsSpan(20), placement); + return body; + } } diff --git a/tests/AcDream.Core.Net.Tests/Messages/InteractRequestsTests.cs b/tests/AcDream.Core.Net.Tests/Messages/InteractRequestsTests.cs index 5e99b5d..f251cf4 100644 --- a/tests/AcDream.Core.Net.Tests/Messages/InteractRequestsTests.cs +++ b/tests/AcDream.Core.Net.Tests/Messages/InteractRequestsTests.cs @@ -42,4 +42,28 @@ public sealed class InteractRequestsTests Assert.Equal(InteractRequests.TeleToLifestoneOpcode, BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(8))); } + + [Fact] + public void BuildPickUp_WritesOpcode0x0019AndPayload() + { + byte[] body = InteractRequests.BuildPickUp( + gameActionSequence: 5, + itemGuid: 0xABCDu, + containerGuid: 0x5000000Au, + placement: 0); + + Assert.Equal(24, body.Length); + Assert.Equal(InteractRequests.GameActionEnvelope, + BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(0))); + Assert.Equal(5u, + BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(4))); + Assert.Equal(InteractRequests.PutItemInContainerOpcode, + BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(8))); + Assert.Equal(0xABCDu, + BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(12))); + Assert.Equal(0x5000000Au, + BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(16))); + Assert.Equal(0, + BinaryPrimitives.ReadInt32LittleEndian(body.AsSpan(20))); + } }