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 {