diff --git a/common/src/main/scala/net/psforever/packet/game/FavoritesMessage.scala b/common/src/main/scala/net/psforever/packet/game/FavoritesMessage.scala
index e9884672..989699a9 100644
--- a/common/src/main/scala/net/psforever/packet/game/FavoritesMessage.scala
+++ b/common/src/main/scala/net/psforever/packet/game/FavoritesMessage.scala
@@ -6,20 +6,58 @@ import scodec.Codec
import scodec.codecs._
/**
- * na
- * @param list na
+ * Load the designator for an entry in the player's favorites list.
+ *
+ * This entry defines a loadout but does not directly associate itself with the configurations and contents of the loadout.
+ * It is just the user-defined name that appears on a "Favorites" tab list and can be selected.
+ * A subsequent server request - `ItemTransactionMessage` - must be made to retrieve the said configuration and content for loading.
+ * Multiple separated favorites lists are present in the game.
+ * All entries are prepended with their destination list, which determines what kind of terminal or menu allows them to be viewable.
+ *
+ * Infantry equipment favorites are appended with a code for the type of exo-suit that they will load on a player.
+ * This does not match the same two field numbering system as in `ArmorChangedMessage` packets.
+ * Subtypes are not considered separately.
+ *
+ * Lists:
+ * `
+ * 0 - Equipment Terminal (infantry)
+ * 1 - Repair/Rearm (standard vehicles)
+ * `
+ *
+ * Armors:
+ * `
+ * 1 - Agile
+ * 2 - Reinforced
+ * 4 - AA MAX
+ * 5 - AI MAX
+ * 6 - AV MAX
+ * `
+ *
+ * Exploration 1:
+ * The identifier for the list is two bits so four separated lists of Favorites are supportable.
+ * Two of the lists are common enough and we can assume one of the others is related to Battleframe Robotics.
+ * What, if anything, is the fourth indexed list?
+ *
+ * Exploration 2:
+ * There are three unaccounted exo-suit indices - '0', '3', and '7' - and two specific kinds of exo-suit that are not defined - Infiltration and Standard.
+ * It is possible that one of the indices also defines the generic MAX (see `ArmorChangedMessage`).
+ * Which exo-suit is associated with which index?
+ *
+ * Exploration 3:
+ * The `armor` parameter coincides with the type of exo-suit maintained by the loadout.
+ * Does this value help the client judge when a favorite can be selected by checking against certifications for exo-suit permission?
+ * (If so, why isn't it working?)
+ * @param list the destination list
* @param player_guid the player
- * @param line na
- * @param subject na
- * @param armor the type of exo-suit
- * @param subtype the exo-suit subtype, if any
+ * @param line the zero-indexed line number of this entry in its list
+ * @param label the identifier for this entry
+ * @param armor the type of exo-suit, if an Infantry loadout
*/
final case class FavoritesMessage(list : Int,
player_guid : PlanetSideGUID,
line : Int,
- subject : String,
- armor : Option[Int] = None,
- subtype : Option[Int] = None)
+ label : String,
+ armor : Option[Int] = None)
extends PlanetSideGamePacket {
type Packet = FavoritesMessage
def opcode = GamePacketOpcode.FavoritesMessage
@@ -31,8 +69,7 @@ object FavoritesMessage extends Marshallable[FavoritesMessage] {
("list" | uintL(2)) >>:~ { value =>
("player_guid" | PlanetSideGUID.codec) ::
("line" | uintL(4)) ::
- ("subject" | PacketHelpers.encodedWideStringAligned(2)) ::
- conditional(value == 0, "armor" | uintL(3)) ::
- conditional(value == 0, "subtype" | uintL(3))
+ ("label" | PacketHelpers.encodedWideStringAligned(2)) ::
+ conditional(value == 0, "armor" | uintL(3))
}).as[FavoritesMessage]
}
diff --git a/common/src/test/scala/GamePacketTest.scala b/common/src/test/scala/GamePacketTest.scala
index 58760ff4..b79311ec 100644
--- a/common/src/test/scala/GamePacketTest.scala
+++ b/common/src/test/scala/GamePacketTest.scala
@@ -856,22 +856,20 @@ class GamePacketTest extends Specification {
"decode (for infantry)" in {
PacketCoding.DecodePacket(stringInfantry).require match {
- case FavoritesMessage(list, player_guid, line, subject, armor, subtype) =>
+ case FavoritesMessage(list, player_guid, line, label, armor) =>
list mustEqual 0
player_guid mustEqual PlanetSideGUID(3760)
line mustEqual 0
- subject mustEqual "Agile (basic)"
+ label mustEqual "Agile (basic)"
armor.isDefined mustEqual true
armor.get mustEqual 1
- subtype.isDefined mustEqual true
- subtype.get mustEqual 0
case default =>
ko
}
}
"encode (for infantry)" in {
- val msg = FavoritesMessage(0, PlanetSideGUID(3760), 0, "Agile (basic)", Option(1), Option(0))
+ val msg = FavoritesMessage(0, PlanetSideGUID(3760), 0, "Agile (basic)", Option(1))
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual stringInfantry
@@ -879,13 +877,12 @@ class GamePacketTest extends Specification {
"decode (for vehicles)" in {
PacketCoding.DecodePacket(stringVehicles).require match {
- case FavoritesMessage(list, player_guid, line, subject, armor, subtype) =>
+ case FavoritesMessage(list, player_guid, line, label, armor) =>
list mustEqual 1
player_guid mustEqual PlanetSideGUID(4210)
line mustEqual 0
- subject mustEqual "Skyguard"
+ label mustEqual "Skyguard"
armor.isDefined mustEqual false
- subtype.isDefined mustEqual false
case default =>
ko
}