diff --git a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala index e55f68005..6415a36ef 100644 --- a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala +++ b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala @@ -362,7 +362,7 @@ object GamePacketOpcode extends Enumeration { case ActionCancelMessage => noDecoder(opcode) case ActionCancelAcknowledgeMessage => noDecoder(opcode) case SetEmpireMessage => noDecoder(opcode) - case EmoteMsg => noDecoder(opcode) + case EmoteMsg => game.EmoteMsg.decode case UnuseItemMessage => noDecoder(opcode) case ObjectDetachMessage => noDecoder(opcode) diff --git a/common/src/main/scala/net/psforever/packet/game/EmoteMsg.scala b/common/src/main/scala/net/psforever/packet/game/EmoteMsg.scala new file mode 100644 index 000000000..4b457c087 --- /dev/null +++ b/common/src/main/scala/net/psforever/packet/game/EmoteMsg.scala @@ -0,0 +1,21 @@ +// 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 EmoteMsg(avatar_guid : PlanetSideGUID, + emote_id : Int) + extends PlanetSideGamePacket { + type Packet = EmoteMsg + def opcode = GamePacketOpcode.EmoteMsg + def encode = EmoteMsg.encode(this) +} + +object EmoteMsg extends Marshallable[EmoteMsg] { + implicit val codec : Codec[EmoteMsg] = ( + ("avatar_guid" | PlanetSideGUID.codec) :: + ("emote_id" | uint8L) + ).as[EmoteMsg] +} diff --git a/common/src/test/scala/GamePacketTest.scala b/common/src/test/scala/GamePacketTest.scala index b809686f9..dab495c55 100644 --- a/common/src/test/scala/GamePacketTest.scala +++ b/common/src/test/scala/GamePacketTest.scala @@ -264,5 +264,26 @@ class GamePacketTest extends Specification { pkt mustEqual string } } + + "EmoteMsg" should { + val string = hex"25 4B0004" + + "decode" in { + PacketCoding.DecodePacket(string).require match { + case EmoteMsg(avatar_guid, emote_id) => + avatar_guid mustEqual PlanetSideGUID(75) + emote_id mustEqual 4 + case default => + ko + } + } + + "encode" in { + val msg = EmoteMsg(PlanetSideGUID(75), 4) + 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 2ac9f6118..fe6d334ed 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -163,6 +163,10 @@ class WorldSessionActor extends Actor with MDCContextAware { case msg @ ChangeFireStateMessage_Stop(item_guid) => log.info("ChangeFireState_Stop: " + msg) + case msg @ EmoteMsg(avatar_guid, emote_id) => + log.info("Emote: " + msg) + sendResponse(PacketCoding.CreateGamePacket(0, EmoteMsg(avatar_guid, emote_id))) + case default => log.debug(s"Unhandled GamePacket ${pkt}") }