From 5b5bf28c526a663a425a472d1c8af79bcbfb65bd Mon Sep 17 00:00:00 2001 From: tfarley Date: Mon, 25 Jul 2016 18:30:50 -0700 Subject: [PATCH] Packet: UseItemMessage (#35) * Add UseItemMessage packet * Add UseItemMessage test * Add UseItemMessage handler stub --- .../psforever/packet/GamePacketOpcode.scala | 2 +- .../packet/game/UseItemMessage.scala | 40 +++++++++++++++++++ common/src/test/scala/GamePacketTest.scala | 30 ++++++++++++++ .../src/main/scala/WorldSessionActor.scala | 6 +++ 4 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 common/src/main/scala/net/psforever/packet/game/UseItemMessage.scala diff --git a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala index 4ba34c44..a7a77e6b 100644 --- a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala +++ b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala @@ -337,7 +337,7 @@ object GamePacketOpcode extends Enumeration { case ReloadMessage => game.ReloadMessage.decode case MountVehicleMsg => noDecoder(opcode) case DismountVehicleMsg => noDecoder(opcode) - case UseItemMessage => noDecoder(opcode) + case UseItemMessage => game.UseItemMessage.decode case MoveItemMessage => game.MoveItemMessage.decode case ChatMsg => game.ChatMsg.decode case CharacterNoRecordMessage => noDecoder(opcode) diff --git a/common/src/main/scala/net/psforever/packet/game/UseItemMessage.scala b/common/src/main/scala/net/psforever/packet/game/UseItemMessage.scala new file mode 100644 index 00000000..b9daf9c8 --- /dev/null +++ b/common/src/main/scala/net/psforever/packet/game/UseItemMessage.scala @@ -0,0 +1,40 @@ +// Copyright (c) 2016 PSForever.net to present +package net.psforever.packet.game + +import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket} +import net.psforever.types.Vector3 +import scodec.Codec +import scodec.codecs._ + +final case class UseItemMessage(avatar_guid : PlanetSideGUID, + unk1 : Int, + object_guid : PlanetSideGUID, + unk2 : Long, + unk3 : Boolean, + unk4 : Vector3, + unk5 : Vector3, + unk6 : Int, + unk7 : Int, + unk8 : Int, + unk9 : Long) + extends PlanetSideGamePacket { + type Packet = UseItemMessage + def opcode = GamePacketOpcode.UseItemMessage + def encode = UseItemMessage.encode(this) +} + +object UseItemMessage extends Marshallable[UseItemMessage] { + implicit val codec : Codec[UseItemMessage] = ( + ("avatar_guid" | PlanetSideGUID.codec) :: + ("unk1" | uint16L) :: + ("object_guid" | PlanetSideGUID.codec) :: + ("unk2" | uint32L) :: + ("unk3" | bool) :: + ("unk4" | Vector3.codec_pos) :: + ("unk5" | Vector3.codec_pos) :: + ("unk6" | uint8L) :: + ("unk7" | uint8L) :: + ("unk8" | uint8L) :: + ("unk9" | uint32L) + ).as[UseItemMessage] +} diff --git a/common/src/test/scala/GamePacketTest.scala b/common/src/test/scala/GamePacketTest.scala index 41f2136a..fbad96c7 100644 --- a/common/src/test/scala/GamePacketTest.scala +++ b/common/src/test/scala/GamePacketTest.scala @@ -468,5 +468,35 @@ class GamePacketTest extends Specification { pkt mustEqual string } } + + "UseItemMessage" should { + val string = hex"10 4B00 0000 7401 FFFFFFFF 4001000000000000000000000000058C803600800000" + + "decode" in { + PacketCoding.DecodePacket(string).require match { + case UseItemMessage(avatar_guid, unk1, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, unk9) => + avatar_guid mustEqual PlanetSideGUID(75) + unk1 mustEqual 0 + object_guid mustEqual PlanetSideGUID(372) + unk2 mustEqual 0xFFFFFFFFL + unk3 mustEqual false + unk4 mustEqual Vector3(5.0f, 0.0f, 0.0f) + unk5 mustEqual Vector3(0.0f, 0.0f, 0.0f) + unk6 mustEqual 11 + unk7 mustEqual 25 + unk8 mustEqual 0 + unk9 mustEqual 364 + case default => + ko + } + } + + "encode" in { + val msg = UseItemMessage(PlanetSideGUID(75), 0, PlanetSideGUID(372), 0xFFFFFFFFL, false, Vector3(5.0f, 0.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), 11, 25, 0, 364) + val pkt = PacketCoding.EncodePacket(msg).require.toByteVector + + pkt mustEqual string + } + } } } diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index 12c93320..0b8cb6c4 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -192,6 +192,12 @@ class WorldSessionActor extends Actor with MDCContextAware { case msg @ ChangeAmmoMessage(item_guid, unk1) => log.info("ChangeAmmo: " + msg) + case msg @ UseItemMessage(avatar_guid, unk1, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, unk9) => + log.info("UseItem: " + msg) + // TODO: Not all fields in the response are identical to source in real packet logs (but seems to be ok) + // TODO: Not all incoming UseItemMessage's respond with another UseItemMessage (i.e. doors only send out GenericObjectStateMsg) + sendResponse(PacketCoding.CreateGamePacket(0, UseItemMessage(avatar_guid, unk1, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, unk9))) + case default => log.debug(s"Unhandled GamePacket ${pkt}") }