diff --git a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala
index 44c742f0..ad04c26d 100644
--- a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala
+++ b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala
@@ -454,7 +454,7 @@ object GamePacketOpcode extends Enumeration {
// OPCODES 0x70-7f
case 0x70 => noDecoder(SquadMemberEvent)
case 0x71 => noDecoder(PlatoonEvent)
- case 0x72 => noDecoder(FriendsRequest)
+ case 0x72 => game.FriendsRequest.decode
case 0x73 => game.FriendsResponse.decode
case 0x74 => noDecoder(TriggerEnvironmentalDamageMessage)
case 0x75 => noDecoder(TrainingZoneMessage)
diff --git a/common/src/main/scala/net/psforever/packet/game/FriendsRequest.scala b/common/src/main/scala/net/psforever/packet/game/FriendsRequest.scala
new file mode 100644
index 00000000..d0ded324
--- /dev/null
+++ b/common/src/main/scala/net/psforever/packet/game/FriendsRequest.scala
@@ -0,0 +1,48 @@
+// 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._
+
+/**
+ * Manage the lists of other players whose names are retained by the given player.
+ *
+ * Players can be remembered by their names and added to a list of remembered names - the "friends list."
+ * They can also be dropped from the list.
+ * A list of "ignored" player names can also be retained.
+ * Ignored players will have their comments stifled in the given player's chat window.
+ * No name will be appended or removed from any list until the response to this packet is received.
+ *
+ * Actions that involve the "remove" functionality will locate the entered name in the local list before dispatching this packet.
+ * A complaint will be logged to the event window if the name is not found.
+ *
+ * Actions:
+ * 0 - display friends list
+ * 1 - add player to friends list
+ * 2 - remove player from friends list
+ * 4 - display ignored player list
+ * 5 - add player to ignored player list
+ * 6 - remove player from ignored player list
+ *
+ * Exploration:
+ * Are action = 3 and action = 7 supposed to do anything?
+ * @param action the purpose of this packet
+ * @param friend the player name that was entered;
+ * blank in certain situations
+ */
+final case class FriendsRequest(action : Int,
+ friend : String)
+ extends PlanetSideGamePacket {
+ type Packet = FriendsRequest
+ def opcode = GamePacketOpcode.FriendsRequest
+ def encode = FriendsRequest.encode(this)
+}
+
+object FriendsRequest extends Marshallable[FriendsRequest] {
+ implicit val codec : Codec[FriendsRequest] = (
+ ("action" | uintL(3)) ::
+ ("friend" | PacketHelpers.encodedWideStringAligned(5))
+ ).as[FriendsRequest]
+}
+
diff --git a/common/src/test/scala/GamePacketTest.scala b/common/src/test/scala/GamePacketTest.scala
index 3a913ca5..a5f47f3b 100644
--- a/common/src/test/scala/GamePacketTest.scala
+++ b/common/src/test/scala/GamePacketTest.scala
@@ -869,8 +869,6 @@ class GamePacketTest extends Specification {
list(3).online mustEqual false
list(4).name mustEqual "KurtHectic-G"
list(4).online mustEqual false
- case default =>
- ko
}
}
@@ -896,10 +894,10 @@ class GamePacketTest extends Specification {
"encode (multiple friends)" in {
val msg = FriendsResponse(0, 0, true, true, Friend("Angello-W", false) ::
- Friend("thephattphrogg", false) ::
- Friend("Kimpossible12", false) ::
- Friend("Zearthling", false) ::
- Friend("KurtHectic-G", false) :: Nil)
+ Friend("thephattphrogg", false) ::
+ Friend("Kimpossible12", false) ::
+ Friend("Zearthling", false) ::
+ Friend("KurtHectic-G", false) :: Nil)
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual stringManyFriends
@@ -913,6 +911,28 @@ class GamePacketTest extends Specification {
}
}
+ "FriendsRequest" should {
+ val string = hex"72 3 0A0 46004A0048004E004300"
+
+ "decode" in {
+ PacketCoding.DecodePacket(string).require match {
+ case FriendsRequest(action, friend) =>
+ action mustEqual 1
+ friend.length mustEqual 5
+ friend mustEqual "FJHNC"
+ case default =>
+ ko
+ }
+ }
+
+ "encode" in {
+ val msg = FriendsRequest(1, "FJHNC")
+ val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
+
+ pkt mustEqual string
+ }
+ }
+
"WeaponDryFireMessage" should {
val string = hex"52 4C00"