diff --git a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala index 9a6e9c74..f984eb78 100644 --- a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala +++ b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala @@ -444,7 +444,7 @@ object GamePacketOpcode extends Enumeration { case WeaponJammedMessage => noDecoder(opcode) case LinkDeadAwarenessMsg => noDecoder(opcode) case DroppodFreefallingMessage => noDecoder(opcode) - case AvatarFirstTimeEventMessage => noDecoder(opcode) + case AvatarFirstTimeEventMessage => game.AvatarFirstTimeEventMessage.decode case AggravatedDamageMessage => noDecoder(opcode) case TriggerSoundMessage => noDecoder(opcode) case LootItemMessage => noDecoder(opcode) diff --git a/common/src/main/scala/net/psforever/packet/game/AvatarFirstTimeEventMessage.scala b/common/src/main/scala/net/psforever/packet/game/AvatarFirstTimeEventMessage.scala new file mode 100644 index 00000000..0fd5bc10 --- /dev/null +++ b/common/src/main/scala/net/psforever/packet/game/AvatarFirstTimeEventMessage.scala @@ -0,0 +1,25 @@ +// Copyright (c) 2016 PSForever.net to present +package net.psforever.packet.game + +import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket} +import scodec.Codec +import scodec.codecs._ + +final case class AvatarFirstTimeEventMessage(avatar_guid : PlanetSideGUID, + object_guid : PlanetSideGUID, + unk1 : Long, + event_name : String) + extends PlanetSideGamePacket { + type Packet = AvatarFirstTimeEventMessage + def opcode = GamePacketOpcode.AvatarFirstTimeEventMessage + def encode = AvatarFirstTimeEventMessage.encode(this) +} + +object AvatarFirstTimeEventMessage extends Marshallable[AvatarFirstTimeEventMessage] { + implicit val codec : Codec[AvatarFirstTimeEventMessage] = ( + ("avatar_guid" | PlanetSideGUID.codec) :: + ("object_guid" | PlanetSideGUID.codec) :: + ("unk1" | uint32L ) :: + ("event_name" | PacketHelpers.encodedString) + ).as[AvatarFirstTimeEventMessage] +} diff --git a/common/src/test/scala/GamePacketTest.scala b/common/src/test/scala/GamePacketTest.scala index 8d35c76b..3f351b20 100644 --- a/common/src/test/scala/GamePacketTest.scala +++ b/common/src/test/scala/GamePacketTest.scala @@ -753,6 +753,29 @@ class GamePacketTest extends Specification { } } + "AvatarFirstTimeEventMessage" should { + val string = hex"69 4b00 c000 01000000 9e 766973697465645f63657274696669636174696f6e5f7465726d696e616c" + + "decode" in { + PacketCoding.DecodePacket(string).require match { + case AvatarFirstTimeEventMessage(avatar_guid, object_guid, unk1, event_name) => + avatar_guid mustEqual PlanetSideGUID(75) + object_guid mustEqual PlanetSideGUID(192) + unk1 mustEqual 1 + event_name mustEqual "visited_certification_terminal" + case default => + ko + } + } + + "encode" in { + val msg = AvatarFirstTimeEventMessage(PlanetSideGUID(75), PlanetSideGUID(192), 1, "visited_certification_terminal") + val pkt = PacketCoding.EncodePacket(msg).require.toByteVector + + pkt mustEqual string + } + } + "PingMsg" should { val packet = hex"1a 00000000 b0360000" diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index c8b08c19..a3a531cd 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -244,6 +244,9 @@ class WorldSessionActor extends Actor with MDCContextAware { case msg @ HitMessage(seq_time, projectile_guid, unk1, hit_info, unk2, unk3, unk4) => log.info("Hit: " + msg) + case msg @ AvatarFirstTimeEventMessage(avatar_guid, object_guid, unk1, event_name) => + log.info("AvatarFirstTimeEvent: " + msg) + case default => log.debug(s"Unhandled GamePacket ${pkt}") }