From 684c64679b2c29a40351ce7399adbc704de156bc Mon Sep 17 00:00:00 2001 From: FateJH Date: Sat, 6 May 2017 00:45:42 -0400 Subject: [PATCH] initial work on DisplayedAwardMessage packet and tests --- .../psforever/packet/GamePacketOpcode.scala | 2 +- .../packet/game/DisplayedAwardMessage.scala | 59 +++++++++++++++++++ .../game/DisplayedAwardMessageTest.scala | 29 +++++++++ 3 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 common/src/main/scala/net/psforever/packet/game/DisplayedAwardMessage.scala create mode 100644 common/src/test/scala/game/DisplayedAwardMessageTest.scala diff --git a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala index cad22888..a06b26c0 100644 --- a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala +++ b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala @@ -567,7 +567,7 @@ object GamePacketOpcode extends Enumeration { // OPCODES 0xd0-df case 0xd0 => noDecoder(UnknownMessage208) - case 0xd1 => noDecoder(DisplayedAwardMessage) + case 0xd1 => game.DisplayedAwardMessage.decode case 0xd2 => noDecoder(RespawnAMSInfoMessage) case 0xd3 => noDecoder(ComponentDamageMessage) case 0xd4 => noDecoder(GenericObjectActionAtPositionMessage) diff --git a/common/src/main/scala/net/psforever/packet/game/DisplayedAwardMessage.scala b/common/src/main/scala/net/psforever/packet/game/DisplayedAwardMessage.scala new file mode 100644 index 00000000..fe0e1215 --- /dev/null +++ b/common/src/main/scala/net/psforever/packet/game/DisplayedAwardMessage.scala @@ -0,0 +1,59 @@ +// Copyright (c) 2017 PSForever +package net.psforever.packet.game + +import net.psforever.packet.game.objectcreate.RibbonBars +import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket} +import scodec.Codec +import scodec.codecs._ + +/** + * An `Enumeration` of the slots for award ribbons on a player's `RibbonBars`. + */ +object RibbonBarsSlot extends Enumeration { + type Type = Value + + val Top, + Middle, + Bottom, + TermOfService //technically,the slot above "Top" + = Value + + implicit val codec = PacketHelpers.createEnumerationCodec(this, uint4L) +} + +/** + * Dispatched to configure a player's merit commendation ribbons.
+ *
+ * Normally, this packet is dispatched by the client when managing merit commendations through the "Character Info/Achievements" tab. + * On Gemini Live, this packet was also always dispatched once by the server during character login. + * It set the term of service ribbon explicitly. + * Generally, this was unnecessary, as the encoded character data maintains information about displayed ribbons. + * This behavior was probably a routine that ensured that correct yearly progression was tracked if the player earned it while offline. + * It never set any of the other ribbon slot positions during login.
+ *
+ * A specific ribbon may only be set once to one slot. + * The last set slot is considered the valid position to which that ribbon will be placed/moved. + * @param player_guid the player + * @param ribbon the award to be displayed; + * defaults to `RibbonsBars.noRibbon`; + * use `RibbonsBars.noRibbon` when indicating "no ribbon" + * @param bar any of the four positions where the award ribbon is to be displayed; + * defaults to `TermOfService` + * @see `RibbonBars` + */ +final case class DisplayedAwardMessage(player_guid : PlanetSideGUID, + ribbon : Long = RibbonBars.noRibbon, + bar : RibbonBarsSlot.Value = RibbonBarsSlot.TermOfService) + extends PlanetSideGamePacket { + type Packet = DisplayedAwardMessage + def opcode = GamePacketOpcode.DisplayedAwardMessage + def encode = DisplayedAwardMessage.encode(this) +} + +object DisplayedAwardMessage extends Marshallable[DisplayedAwardMessage] { + implicit val codec : Codec[DisplayedAwardMessage] = ( + ("player_guid" | PlanetSideGUID.codec) :: + ("ribbon" | uint32L) :: + ("bar" | RibbonBarsSlot.codec) + ).as[DisplayedAwardMessage] +} diff --git a/common/src/test/scala/game/DisplayedAwardMessageTest.scala b/common/src/test/scala/game/DisplayedAwardMessageTest.scala new file mode 100644 index 00000000..9ad7c1d6 --- /dev/null +++ b/common/src/test/scala/game/DisplayedAwardMessageTest.scala @@ -0,0 +1,29 @@ +// Copyright (c) 2017 PSForever +package game + +import org.specs2.mutable._ +import net.psforever.packet._ +import net.psforever.packet.game._ +import scodec.bits._ + +class DisplayedAwardMessageTest extends Specification { + val string = hex"D1 9F06 A6010000 3 0" + + "decode" in { + PacketCoding.DecodePacket(string).require match { + case DisplayedAwardMessage(player_guid, ribbon, bar) => + player_guid mustEqual PlanetSideGUID(1695) + ribbon mustEqual 422L + bar mustEqual RibbonBarsSlot.TermOfService + case _ => + ko + } + } + + "encode" in { + val msg = DisplayedAwardMessage(PlanetSideGUID(1695), 422L, RibbonBarsSlot.TermOfService) + val pkt = PacketCoding.EncodePacket(msg).require.toByteVector + + pkt mustEqual string + } +}