From 44c5f65796a552283742421c03acff3b0bad628c Mon Sep 17 00:00:00 2001 From: tfarley Date: Thu, 28 Jul 2016 23:35:50 -0700 Subject: [PATCH] Packet: HitMessage (#45) * Add HitMessage packet * Add HitMessage test * Add HitMessage handler stub --- .../psforever/packet/GamePacketOpcode.scala | 2 +- .../psforever/packet/game/HitMessage.scala | 42 +++++++++++++++++ common/src/test/scala/GamePacketTest.scala | 45 +++++++++++++++++++ .../src/main/scala/WorldSessionActor.scala | 3 ++ 4 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 common/src/main/scala/net/psforever/packet/game/HitMessage.scala diff --git a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala index 2c076ed3c..20fbcf6ed 100644 --- a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala +++ b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala @@ -328,7 +328,7 @@ object GamePacketOpcode extends Enumeration { case UnknownMessage6 => noDecoder(opcode) case UnknownMessage7 => noDecoder(opcode) case PlayerStateMessage => noDecoder(opcode) - case HitMessage => noDecoder(opcode) + case HitMessage => game.HitMessage.decode // OPCODE 10 case HitHint => noDecoder(opcode) diff --git a/common/src/main/scala/net/psforever/packet/game/HitMessage.scala b/common/src/main/scala/net/psforever/packet/game/HitMessage.scala new file mode 100644 index 000000000..00a6f7c66 --- /dev/null +++ b/common/src/main/scala/net/psforever/packet/game/HitMessage.scala @@ -0,0 +1,42 @@ +// 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 HitInfo(shot_origin : Vector3, + hit_pos : Vector3, + hitobject_guid : Option[PlanetSideGUID]) + +final case class HitMessage(seq_time : Int, + projectile_guid : PlanetSideGUID, + unk1 : Int, + hit_info : Option[HitInfo], + unk2 : Boolean, + unk3 : Boolean, + unk4 : Option[Int]) + extends PlanetSideGamePacket { + type Packet = HitMessage + def opcode = GamePacketOpcode.HitMessage + def encode = HitMessage.encode(this) +} + +object HitMessage extends Marshallable[HitMessage] { + implicit val codec_hitinfo : Codec[HitInfo] = ( + ("shot_origin" | Vector3.codec_pos) :: + ("hit_pos" | Vector3.codec_pos) :: + ("hitobject_guid" | optional(bool, PlanetSideGUID.codec)) + ).as[HitInfo] + + implicit val codec : Codec[HitMessage] = ( + ("seq_time" | uintL(10)) :: + ("projectile_guid" | PlanetSideGUID.codec) :: + ("unk1" | uintL(3)) :: + ("hit_info" | optional(bool, codec_hitinfo)) :: + ("unk2" | bool) :: + ("unk3" | bool) :: + ("unk4" | optional(bool, uint16L)) + ).as[HitMessage] +} diff --git a/common/src/test/scala/GamePacketTest.scala b/common/src/test/scala/GamePacketTest.scala index a377c3480..006e8302f 100644 --- a/common/src/test/scala/GamePacketTest.scala +++ b/common/src/test/scala/GamePacketTest.scala @@ -674,5 +674,50 @@ class GamePacketTest extends Specification { pkt mustEqual string } } + + "HitMessage" should { + val string_hitgeneric = hex"09 09E9A70200" + val string_hitobj = hex"09 99292705F4B1FB9514585F08BDD3D454CC5EE80300" + + "decode" in { + PacketCoding.DecodePacket(string_hitgeneric).require match { + case HitMessage(seq_time, projectile_guid, unk1, hit_info, unk2, unk3, unk4) => + seq_time mustEqual 777 + projectile_guid mustEqual PlanetSideGUID(40102) + unk1 mustEqual 0 + hit_info mustEqual None + unk2 mustEqual true + unk3 mustEqual false + unk4 mustEqual None + case default => + ko + } + + PacketCoding.DecodePacket(string_hitobj).require match { + case HitMessage(seq_time, projectile_guid, unk1, hit_info, unk2, unk3, unk4) => + seq_time mustEqual 153 + projectile_guid mustEqual PlanetSideGUID(40100) + unk1 mustEqual 0 + hit_info mustEqual Some(HitInfo(Vector3(3672.9766f, 2729.8594f, 92.34375f), Vector3(3679.5156f, 2722.6172f, 92.796875f), Some(PlanetSideGUID(372)))) + unk2 mustEqual true + unk3 mustEqual false + unk4 mustEqual None + case default => + ko + } + } + + "encode" in { + val msg_hitgeneric = HitMessage(777, PlanetSideGUID(40102), 0, None, true, false, None) + val pkt_hitgeneric = PacketCoding.EncodePacket(msg_hitgeneric).require.toByteVector + + pkt_hitgeneric mustEqual string_hitgeneric + + val msg_hitobj = HitMessage(153, PlanetSideGUID(40100), 0, Some(HitInfo(Vector3(3672.9766f, 2729.8594f, 92.34375f), Vector3(3679.5156f, 2722.6172f, 92.796875f), Some(PlanetSideGUID(372)))), true, false, None) + val pkt_hitobj = PacketCoding.EncodePacket(msg_hitobj).require.toByteVector + + pkt_hitobj mustEqual string_hitobj + } + } } } diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index d05a7b57b..464354487 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -218,6 +218,9 @@ class WorldSessionActor extends Actor with MDCContextAware { case msg @ WeaponFireMessage(seq_time, weapon_guid, projectile_guid, shot_origin, unk1, unk2, unk3, unk4, unk5, unk6, unk7) => log.info("WeaponFire: " + msg) + case msg @ HitMessage(seq_time, projectile_guid, unk1, hit_info, unk2, unk3, unk4) => + log.info("Hit: " + msg) + case default => log.debug(s"Unhandled GamePacket ${pkt}") }