From fbe671e577e66943fcfb00dabc08be447bef3fcb Mon Sep 17 00:00:00 2001 From: FateJH Date: Sat, 22 Apr 2017 14:59:46 -0400 Subject: [PATCH 1/3] initial work on InventoryStateMessage packet --- .../psforever/packet/GamePacketOpcode.scala | 2 +- .../packet/game/InventoryStateMessage.scala | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 common/src/main/scala/net/psforever/packet/game/InventoryStateMessage.scala diff --git a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala index 69629b548..35a4cd105 100644 --- a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala +++ b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala @@ -385,7 +385,7 @@ object GamePacketOpcode extends Enumeration { case 0x36 => game.PickupItemMessage.decode case 0x37 => game.DropItemMessage.decode // 0x38 - case 0x38 => noDecoder(InventoryStateMessage) + case 0x38 => game.InventoryStateMessage.decode case 0x39 => game.ChangeFireStateMessage_Start.decode case 0x3a => game.ChangeFireStateMessage_Stop.decode case 0x3b => noDecoder(UnknownMessage59) diff --git a/common/src/main/scala/net/psforever/packet/game/InventoryStateMessage.scala b/common/src/main/scala/net/psforever/packet/game/InventoryStateMessage.scala new file mode 100644 index 000000000..60817688c --- /dev/null +++ b/common/src/main/scala/net/psforever/packet/game/InventoryStateMessage.scala @@ -0,0 +1,25 @@ +// Copyright (c) 2017 PSForever +package net.psforever.packet.game + +import net.psforever.packet.{GamePacketOpcode, Marshallable, PlanetSideGamePacket} +import scodec.Codec +import scodec.codecs._ + +final case class InventoryStateMessage(player_guid : PlanetSideGUID, + unk1 : Int, + unk2 : Int, + unk3 : Long) + extends PlanetSideGamePacket { + type Packet = InventoryStateMessage + def opcode = GamePacketOpcode.InventoryStateMessage + def encode = InventoryStateMessage.encode(this) +} + +object InventoryStateMessage extends Marshallable[InventoryStateMessage] { + implicit val codec : Codec[InventoryStateMessage] = ( + ("player_guid" | PlanetSideGUID.codec) :: + ("unk1" | uintL(10)) :: + ("unk2" | uint16L) :: + ("unk3" | uint32L) + ).as[InventoryStateMessage] +} From 92c126759a90aefc4d99e23ed8766588dca3134c Mon Sep 17 00:00:00 2001 From: FateJH Date: Wed, 17 May 2017 20:45:06 -0400 Subject: [PATCH 2/3] clarified fields and purpose; updated comments; working tests --- .../packet/game/InventoryStateMessage.scala | 32 ++++++++++++++----- .../game/InventoryStateMessageTest.scala | 31 ++++++++++++++++++ 2 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 common/src/test/scala/game/InventoryStateMessageTest.scala diff --git a/common/src/main/scala/net/psforever/packet/game/InventoryStateMessage.scala b/common/src/main/scala/net/psforever/packet/game/InventoryStateMessage.scala index 60817688c..fcafe13c9 100644 --- a/common/src/main/scala/net/psforever/packet/game/InventoryStateMessage.scala +++ b/common/src/main/scala/net/psforever/packet/game/InventoryStateMessage.scala @@ -5,10 +5,26 @@ import net.psforever.packet.{GamePacketOpcode, Marshallable, PlanetSideGamePacke import scodec.Codec import scodec.codecs._ -final case class InventoryStateMessage(player_guid : PlanetSideGUID, - unk1 : Int, - unk2 : Int, - unk3 : Long) +/** + * Dispatched by the server to update the value associated with an object in a specific container object.
+ *
+ * The object indicated by `object_guid` must be associated with the inventory (`container_guid`) at the time. + * A common use for this packet is to update weapon data when gaining control over that weapon. + * For example, before boarding any kind of turret for the first time, it's ammunition component will have exactly one shot. + * This shot was established when the turret was first created. + * This information would be displayed in the holster icon across the bottom of the GUI while it is mounted. + * Furthermore, the mounted player will only fire the turret exactly one time. + * This packet can provide the turret with its correct and current amount of ammunition before the player mounts it. + * @param object_guid the object being affected + * @param unk na; + * usually 0 + * @param container_guid the object in which `object_guid` is contained + * @param value an amount with which to update `object_guid` + */ +final case class InventoryStateMessage(object_guid : PlanetSideGUID, + unk : Int, + container_guid : PlanetSideGUID, + value : Long) extends PlanetSideGamePacket { type Packet = InventoryStateMessage def opcode = GamePacketOpcode.InventoryStateMessage @@ -17,9 +33,9 @@ final case class InventoryStateMessage(player_guid : PlanetSideGUID, object InventoryStateMessage extends Marshallable[InventoryStateMessage] { implicit val codec : Codec[InventoryStateMessage] = ( - ("player_guid" | PlanetSideGUID.codec) :: - ("unk1" | uintL(10)) :: - ("unk2" | uint16L) :: - ("unk3" | uint32L) + ("object_guid" | PlanetSideGUID.codec) :: + ("unk" | uintL(10)) :: + ("container_guid" | PlanetSideGUID.codec) :: + ("value" | uint32L) ).as[InventoryStateMessage] } diff --git a/common/src/test/scala/game/InventoryStateMessageTest.scala b/common/src/test/scala/game/InventoryStateMessageTest.scala new file mode 100644 index 000000000..9b0cddfae --- /dev/null +++ b/common/src/test/scala/game/InventoryStateMessageTest.scala @@ -0,0 +1,31 @@ +// Copyright (c) 2017 PSForever +package game + +import org.specs2.mutable._ +import net.psforever.packet._ +import net.psforever.packet.game._ +import scodec.bits._ + +class InventoryStateMessageTest extends Specification { + val string = hex"38 5C0B 00 3C02 B20000000 0" + + "decode" in { + PacketCoding.DecodePacket(string).require match { + case InventoryStateMessage(object_guid, unk, inv_guid, value) => + object_guid mustEqual PlanetSideGUID(2908) + unk mustEqual 0 + inv_guid mustEqual PlanetSideGUID(2800) + value mustEqual 200 + case _ => + ko + } + } + + "encode" in { + val msg = InventoryStateMessage(PlanetSideGUID(2908), 0, PlanetSideGUID(2800), 200) + val pkt = PacketCoding.EncodePacket(msg).require.toByteVector + + pkt mustEqual string + } +} + From 71e729cf2b52319fb243492ac78bee2e3b2cceaf Mon Sep 17 00:00:00 2001 From: FateJH Date: Wed, 17 May 2017 21:10:21 -0400 Subject: [PATCH 3/3] overloaded constructor --- .../psforever/packet/game/InventoryStateMessage.scala | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/common/src/main/scala/net/psforever/packet/game/InventoryStateMessage.scala b/common/src/main/scala/net/psforever/packet/game/InventoryStateMessage.scala index fcafe13c9..1cf24392c 100644 --- a/common/src/main/scala/net/psforever/packet/game/InventoryStateMessage.scala +++ b/common/src/main/scala/net/psforever/packet/game/InventoryStateMessage.scala @@ -32,6 +32,16 @@ final case class InventoryStateMessage(object_guid : PlanetSideGUID, } object InventoryStateMessage extends Marshallable[InventoryStateMessage] { + /** + * Overloaded constructor that ignores the unknown field. + * @param object_guid the object being affected + * @param container_guid the object in which `object_guid` is contained + * @param value an amount with which to update `object_guid` + * @return an `InventoryStateMessage` object + */ + def apply(object_guid : PlanetSideGUID, container_guid : PlanetSideGUID, value : Long) : InventoryStateMessage = + InventoryStateMessage(object_guid, 0, container_guid, value) + implicit val codec : Codec[InventoryStateMessage] = ( ("object_guid" | PlanetSideGUID.codec) :: ("unk" | uintL(10)) ::