From 38a4e128b6bb3212c24eead6c50b32c9aec0ddfa Mon Sep 17 00:00:00 2001 From: FateJH Date: Sun, 11 Sep 2016 00:57:04 -0400 Subject: [PATCH 1/4] initial coding for packet and its tests; includes commented-out extended functionality --- .../psforever/packet/GamePacketOpcode.scala | 2 +- .../packet/game/ObjectAttachMessage.scala | 60 +++++++++++++++++++ common/src/test/scala/GamePacketTest.scala | 23 +++++++ 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 common/src/main/scala/net/psforever/packet/game/ObjectAttachMessage.scala diff --git a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala index 6e9984e5..3fae9098 100644 --- a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala +++ b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala @@ -368,7 +368,7 @@ object GamePacketOpcode extends Enumeration { // 0x28 case 0x28 => noDecoder(CreateShortcutMessage) case 0x29 => noDecoder(ChangeShortcutBankMessage) - case 0x2a => noDecoder(ObjectAttachMessage) + case 0x2a => game.ObjectAttachMessage.decode case 0x2b => noDecoder(UnknownMessage43) case 0x2c => noDecoder(PlanetsideAttributeMessage) case 0x2d => game.RequestDestroyMessage.decode diff --git a/common/src/main/scala/net/psforever/packet/game/ObjectAttachMessage.scala b/common/src/main/scala/net/psforever/packet/game/ObjectAttachMessage.scala new file mode 100644 index 00000000..056900e5 --- /dev/null +++ b/common/src/main/scala/net/psforever/packet/game/ObjectAttachMessage.scala @@ -0,0 +1,60 @@ +// Copyright (c) 2016 PSForever.net to present +package net.psforever.packet.game + +import net.psforever.packet.{GamePacketOpcode, Marshallable, PlanetSideGamePacket} +import scodec.Codec +import scodec.codecs._ + +/** + * Change the location of an item within the game's inventory system.
+ *
+ * The data portion of this packet defines a player, an item, and a destination. + * After the packet is received by the client, the item will be guaranteed to be within the player's inventory in the codified location. + * The "inventory" in this case includes both the player's literal grid inventory and their available equipment slots. + * Where the item was before it was moved is not specified.
+ *
+ * This packet is a complementary packet that simulates a lazy TCP-like approach to coordinating item manipulation. + * In some cases, the client will (appear to) proceed with what it intended to do without waiting for the server to confirm. + * For example, grabbing an item from an inventory position will generate a `MoveItemMessage` that defines "the player's cursor" as a destination. + * The client will "attach to the player's cursor" without waiting for the `ObjectAttachMessage` from the server which echoes the destination. + * The change is observable. + * Inversely, the client is blocked from detaching the item from "the player's cursor" and putting it back into the inventory on its own. + * It waits until it receives an `ObjectAttachMessage` in confirmation.
+ *
+ * Destination codes:
+ * `80` is the first pistol slot
+ * `81` is the second pistol slot
+ * `82` is the first rifle slot
+ * `83` is the second rifle slot
+ * `86` is the first entry in the player's inventory
+ * `00 FA` is a special dest/extra code that "attaches the object to the player's cursor" + * @param player_guid the player GUID + * @param item_guid the item GUID + * @param dest a codified location within the player's inventory see above + * //@param extra optional; a special kind of item manipulation; the common one is `FA` + */ +final case class ObjectAttachMessage(player_guid : PlanetSideGUID, + item_guid : PlanetSideGUID, + dest : Int) + extends PlanetSideGamePacket { + type Packet = ObjectAttachMessage + def opcode = GamePacketOpcode.ObjectAttachMessage + def encode = ObjectAttachMessage.encode(this) +} + +object ObjectAttachMessage extends Marshallable[ObjectAttachMessage] { +// implicit val codec : Codec[ObjectAttachMessage] = ( +// ("player_guid" | PlanetSideGUID.codec) :: +// ("item_guid" | PlanetSideGUID.codec) >>:~ { _ => +// ("dest" | uint8L) >>:~ ( loc => +// conditional(loc == 0, "extra" | uint8L) +// ) +// } +// ).as[ObjectAttachMessage] + + implicit val codec : Codec[ObjectAttachMessage] = ( + ("player_guid" | PlanetSideGUID.codec) :: + ("item_guid" | PlanetSideGUID.codec) :: + ("dest" | uint8L) + ).as[ObjectAttachMessage] +} diff --git a/common/src/test/scala/GamePacketTest.scala b/common/src/test/scala/GamePacketTest.scala index 2f7e8a11..4c0cc329 100644 --- a/common/src/test/scala/GamePacketTest.scala +++ b/common/src/test/scala/GamePacketTest.scala @@ -299,6 +299,29 @@ class GamePacketTest extends Specification { } } + "ObjectAttachMessage" should { + val stringToInventory = hex"2A 9F05 D405 86" + val stringToCursor = hex"2A 9F05 D405 00FA" + + "encode" in { + PacketCoding.DecodePacket(stringToInventory).require match { + case ObjectAttachMessage(player_guid, item_guid, index) => + player_guid mustEqual PlanetSideGUID(1439) + item_guid mustEqual PlanetSideGUID(1492) + index mustEqual 134 + case default => + ko + } + } + + "decode" in { + val msg = ObjectAttachMessage(PlanetSideGUID(1439), PlanetSideGUID(1492), 134) + val pkt = PacketCoding.EncodePacket(msg).require.toByteVector + + pkt mustEqual stringToInventory + } + } + "DropItemMessage" should { val string = hex"37 4C00" From 3cfa08b3cb47cc0e0a9a98b1c77746add43bfe2a Mon Sep 17 00:00:00 2001 From: FateJH Date: Tue, 20 Sep 2016 22:03:21 -0400 Subject: [PATCH 2/4] activating case for extra parameter now that a method is available --- .../packet/game/ObjectAttachMessage.scala | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/common/src/main/scala/net/psforever/packet/game/ObjectAttachMessage.scala b/common/src/main/scala/net/psforever/packet/game/ObjectAttachMessage.scala index 056900e5..2bd404e3 100644 --- a/common/src/main/scala/net/psforever/packet/game/ObjectAttachMessage.scala +++ b/common/src/main/scala/net/psforever/packet/game/ObjectAttachMessage.scala @@ -31,11 +31,14 @@ import scodec.codecs._ * @param player_guid the player GUID * @param item_guid the item GUID * @param dest a codified location within the player's inventory see above - * //@param extra optional; a special kind of item manipulation; the common one is `FA` + * @param extra optional; a special kind of item manipulation; the common one is `FA` + * @see MoveItemMessage + * @see ObjectAttachMessage */ final case class ObjectAttachMessage(player_guid : PlanetSideGUID, item_guid : PlanetSideGUID, - dest : Int) + dest : Int, + extra : Option[Int]) extends PlanetSideGamePacket { type Packet = ObjectAttachMessage def opcode = GamePacketOpcode.ObjectAttachMessage @@ -43,18 +46,11 @@ final case class ObjectAttachMessage(player_guid : PlanetSideGUID, } object ObjectAttachMessage extends Marshallable[ObjectAttachMessage] { -// implicit val codec : Codec[ObjectAttachMessage] = ( -// ("player_guid" | PlanetSideGUID.codec) :: -// ("item_guid" | PlanetSideGUID.codec) >>:~ { _ => -// ("dest" | uint8L) >>:~ ( loc => -// conditional(loc == 0, "extra" | uint8L) -// ) -// } -// ).as[ObjectAttachMessage] - implicit val codec : Codec[ObjectAttachMessage] = ( ("player_guid" | PlanetSideGUID.codec) :: ("item_guid" | PlanetSideGUID.codec) :: - ("dest" | uint8L) + (("dest" | uint8L) >>:~ { loc => + conditional(loc == 0, "extra" | uint8L).hlist + }) ).as[ObjectAttachMessage] } From ccd3fe0adab4aa37105b1baa6919448eed6e673a Mon Sep 17 00:00:00 2001 From: FateJH Date: Tue, 22 Nov 2016 19:28:27 -0500 Subject: [PATCH 3/4] adjusted fields for slot numbering of either 8u or 16u index --- .../packet/game/ObjectAttachMessage.scala | 32 +++++++++---------- common/src/test/scala/GamePacketTest.scala | 26 ++++++++++++--- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/common/src/main/scala/net/psforever/packet/game/ObjectAttachMessage.scala b/common/src/main/scala/net/psforever/packet/game/ObjectAttachMessage.scala index 2bd404e3..3afb5570 100644 --- a/common/src/main/scala/net/psforever/packet/game/ObjectAttachMessage.scala +++ b/common/src/main/scala/net/psforever/packet/game/ObjectAttachMessage.scala @@ -1,7 +1,7 @@ // Copyright (c) 2016 PSForever.net to present package net.psforever.packet.game -import net.psforever.packet.{GamePacketOpcode, Marshallable, PlanetSideGamePacket} +import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket} import scodec.Codec import scodec.codecs._ @@ -16,29 +16,31 @@ import scodec.codecs._ * This packet is a complementary packet that simulates a lazy TCP-like approach to coordinating item manipulation. * In some cases, the client will (appear to) proceed with what it intended to do without waiting for the server to confirm. * For example, grabbing an item from an inventory position will generate a `MoveItemMessage` that defines "the player's cursor" as a destination. - * The client will "attach to the player's cursor" without waiting for the `ObjectAttachMessage` from the server which echoes the destination. + * The client will "attach to the player's cursor" without waiting for an `ObjectAttachMessage` from the server which echoes the destination. * The change is observable. * Inversely, the client is blocked from detaching the item from "the player's cursor" and putting it back into the inventory on its own. * It waits until it receives an `ObjectAttachMessage` in confirmation.
*
* Destination codes:
- * `80` is the first pistol slot
- * `81` is the second pistol slot
- * `82` is the first rifle slot
- * `83` is the second rifle slot
- * `86` is the first entry in the player's inventory
- * `00 FA` is a special dest/extra code that "attaches the object to the player's cursor" + * `0x80` is the first pistol slot
+ * `0x81` is the second pistol slot
+ * `0x82` is the first rifle slot
+ * `0x83` is the second rifle slot
+ * `0x84` is the melee/knife slot
+ * `0x86` is the first entry in the player's grid inventory
+ * `0x00FA` is a special dest/extra code that "attaches the object to the player's cursor"
+ *
+ * Exploration:
+ * What is slot `0x85`? * @param player_guid the player GUID * @param item_guid the item GUID - * @param dest a codified location within the player's inventory see above - * @param extra optional; a special kind of item manipulation; the common one is `FA` + * @param slot a codified location within the player's inventory; + * may be 8u (0 is 0x80, to 127) or 16u (128 is 0x0080) * @see MoveItemMessage - * @see ObjectAttachMessage */ final case class ObjectAttachMessage(player_guid : PlanetSideGUID, item_guid : PlanetSideGUID, - dest : Int, - extra : Option[Int]) + slot : Int) extends PlanetSideGamePacket { type Packet = ObjectAttachMessage def opcode = GamePacketOpcode.ObjectAttachMessage @@ -49,8 +51,6 @@ object ObjectAttachMessage extends Marshallable[ObjectAttachMessage] { implicit val codec : Codec[ObjectAttachMessage] = ( ("player_guid" | PlanetSideGUID.codec) :: ("item_guid" | PlanetSideGUID.codec) :: - (("dest" | uint8L) >>:~ { loc => - conditional(loc == 0, "extra" | uint8L).hlist - }) + ("slot" | PacketHelpers.encodedStringSize) ).as[ObjectAttachMessage] } diff --git a/common/src/test/scala/GamePacketTest.scala b/common/src/test/scala/GamePacketTest.scala index 4c0cc329..6855b810 100644 --- a/common/src/test/scala/GamePacketTest.scala +++ b/common/src/test/scala/GamePacketTest.scala @@ -303,23 +303,41 @@ class GamePacketTest extends Specification { val stringToInventory = hex"2A 9F05 D405 86" val stringToCursor = hex"2A 9F05 D405 00FA" - "encode" in { + "encode (inventory 1,1)" in { PacketCoding.DecodePacket(stringToInventory).require match { case ObjectAttachMessage(player_guid, item_guid, index) => player_guid mustEqual PlanetSideGUID(1439) item_guid mustEqual PlanetSideGUID(1492) - index mustEqual 134 + index mustEqual 6 case default => ko } } - "decode" in { - val msg = ObjectAttachMessage(PlanetSideGUID(1439), PlanetSideGUID(1492), 134) + "encode (cursor)" in { + PacketCoding.DecodePacket(stringToCursor).require match { + case ObjectAttachMessage(player_guid, item_guid, index) => + player_guid mustEqual PlanetSideGUID(1439) + item_guid mustEqual PlanetSideGUID(1492) + index mustEqual 250 + case default => + ko + } + } + + "decode (inventory 1,1)" in { + val msg = ObjectAttachMessage(PlanetSideGUID(1439), PlanetSideGUID(1492), 6) val pkt = PacketCoding.EncodePacket(msg).require.toByteVector pkt mustEqual stringToInventory } + + "decode (cursor)" in { + val msg = ObjectAttachMessage(PlanetSideGUID(1439), PlanetSideGUID(1492), 250) + val pkt = PacketCoding.EncodePacket(msg).require.toByteVector + + pkt mustEqual stringToCursor + } } "DropItemMessage" should { From 763e82fd3511614f21698503d6caaa5d612a7587 Mon Sep 17 00:00:00 2001 From: FateJH Date: Tue, 10 Jan 2017 17:10:35 -0500 Subject: [PATCH 4/4] commentary adjustments --- .../packet/game/ObjectAttachMessage.scala | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/common/src/main/scala/net/psforever/packet/game/ObjectAttachMessage.scala b/common/src/main/scala/net/psforever/packet/game/ObjectAttachMessage.scala index 3afb5570..b8cf2bcc 100644 --- a/common/src/main/scala/net/psforever/packet/game/ObjectAttachMessage.scala +++ b/common/src/main/scala/net/psforever/packet/game/ObjectAttachMessage.scala @@ -22,21 +22,20 @@ import scodec.codecs._ * It waits until it receives an `ObjectAttachMessage` in confirmation.
*
* Destination codes:
- * `0x80` is the first pistol slot
- * `0x81` is the second pistol slot
- * `0x82` is the first rifle slot
- * `0x83` is the second rifle slot
- * `0x84` is the melee/knife slot
- * `0x86` is the first entry in the player's grid inventory
- * `0x00FA` is a special dest/extra code that "attaches the object to the player's cursor"
- *
- * Exploration:
- * What is slot `0x85`? - * @param player_guid the player GUID - * @param item_guid the item GUID - * @param slot a codified location within the player's inventory; - * may be 8u (0 is 0x80, to 127) or 16u (128 is 0x0080) - * @see MoveItemMessage + * `0x80` - pistol slot 1
+ * `0x81` - pistol slot 2
+ * `0x82` - rifle slot 1
+ * `0x83` - rifle slot 2
+ * `0x84` - melee/knife slot
+ * `0x85` - mystery slot
+ * `0x86` - grid inventory (1,1)
+ * `0x00FA` is a special dest/extra code that "attaches the item to the player's cursor" + * @param player_guid the player + * @param item_guid the item + * @param slot a codified location within an inventory, and overlapping the player's holsters if need be; + * 8u (0 - 127 or `0x80 - 0xFF`) or + * 16u (128 - 32767 or `0x0080 - 0x7FFF`) + * @see `MoveItemMessage`, `objectcreate\ObjectClass.SLOT_BLOCKER` */ final case class ObjectAttachMessage(player_guid : PlanetSideGUID, item_guid : PlanetSideGUID,