mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-13 15:34:42 +00:00
Merge branch 'favorites'
This commit is contained in:
commit
ba5583e583
4 changed files with 130 additions and 2 deletions
|
|
@ -433,7 +433,7 @@ object GamePacketOpcode extends Enumeration {
|
||||||
case 0x5f => noDecoder(FavoritesResponse)
|
case 0x5f => noDecoder(FavoritesResponse)
|
||||||
|
|
||||||
// OPCODES 0x60-6f
|
// OPCODES 0x60-6f
|
||||||
case 0x60 => noDecoder(FavoritesMessage)
|
case 0x60 => game.FavoritesMessage.decode
|
||||||
case 0x61 => noDecoder(ObjectDetectedMessage)
|
case 0x61 => noDecoder(ObjectDetectedMessage)
|
||||||
case 0x62 => noDecoder(SplashHitMessage)
|
case 0x62 => noDecoder(SplashHitMessage)
|
||||||
case 0x63 => noDecoder(SetChatFilterMessage)
|
case 0x63 => noDecoder(SetChatFilterMessage)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
// 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._
|
||||||
|
import shapeless.{::, HNil}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the designator for an entry in the player's favorites list.<br>
|
||||||
|
* <br>
|
||||||
|
* This entry defines a user-defined loadout label that appears on a "Favorites" tab list and can be selected.
|
||||||
|
* A subsequent server request - `ItemTransactionMessage` - must be made to retrieve the said loadout contents.
|
||||||
|
* Multiple separated favorites lists are present in the game.
|
||||||
|
* All entries are prepended with their destination list which indicates how from how that list is viewable.
|
||||||
|
* Different lists also have different numbers of available lines to store loadout entries.<br>
|
||||||
|
* <br>
|
||||||
|
* 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.<br>
|
||||||
|
* <br>
|
||||||
|
* Lists:<br>
|
||||||
|
* `
|
||||||
|
* 0 - Equipment Terminal (infantry)<br>
|
||||||
|
* 1 - Repair/Rearm Silo (standard vehicles)<br>
|
||||||
|
* `
|
||||||
|
* <br>
|
||||||
|
* Armors:<br>
|
||||||
|
* `
|
||||||
|
* 1 - Agile<br>
|
||||||
|
* 2 - Reinforced<br>
|
||||||
|
* 4 - AA MAX<br>
|
||||||
|
* 5 - AI MAX<br>
|
||||||
|
* 6 - AV MAX<br>
|
||||||
|
* `
|
||||||
|
* <br>
|
||||||
|
* Exploration 1:<br>
|
||||||
|
* 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.
|
||||||
|
* These lists also do not include `Squad Defintion...` presets.
|
||||||
|
* What are the unknown lists?<br>
|
||||||
|
* <br>
|
||||||
|
* Exploration 2:<br>
|
||||||
|
* There are three unaccounted exo-suit indices - 0, 3, and 7;
|
||||||
|
* and, there are 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?
|
||||||
|
* @param list the destination list
|
||||||
|
* @param player_guid the player
|
||||||
|
* @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,
|
||||||
|
label : String,
|
||||||
|
armor : Option[Int] = None)
|
||||||
|
extends PlanetSideGamePacket {
|
||||||
|
type Packet = FavoritesMessage
|
||||||
|
def opcode = GamePacketOpcode.FavoritesMessage
|
||||||
|
def encode = FavoritesMessage.encode(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
object FavoritesMessage extends Marshallable[FavoritesMessage] {
|
||||||
|
implicit val codec : Codec[FavoritesMessage] = (
|
||||||
|
("list" | uint2L) >>:~ { value =>
|
||||||
|
("player_guid" | PlanetSideGUID.codec) ::
|
||||||
|
("line" | uint4L) ::
|
||||||
|
("label" | PacketHelpers.encodedWideStringAligned(2)) ::
|
||||||
|
conditional(value == 0, "armor" | uintL(3))
|
||||||
|
}).xmap[FavoritesMessage] (
|
||||||
|
{
|
||||||
|
case lst :: guid :: ln :: str :: arm :: HNil =>
|
||||||
|
FavoritesMessage(lst, guid, ln, str, arm)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
case FavoritesMessage(lst, guid, ln, str, arm) =>
|
||||||
|
val armset : Option[Int] = if(lst == 0 && arm.isEmpty) { Some(0) } else { arm }
|
||||||
|
lst :: guid :: ln :: str :: armset :: HNil
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -12,7 +12,7 @@ object TransactionType extends Enumeration {
|
||||||
Sell,
|
Sell,
|
||||||
Unk4,
|
Unk4,
|
||||||
Unk5,
|
Unk5,
|
||||||
Unk6,
|
Infantry_Loadout,
|
||||||
Unk7
|
Unk7
|
||||||
= Value
|
= Value
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1081,6 +1081,52 @@ class GamePacketTest extends Specification {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"FavoritesMessage" should {
|
||||||
|
val stringVehicles = hex"60 5C 84 02 20 5300 6B00 7900 6700 7500 6100 7200 6400"
|
||||||
|
val stringInfantry = hex"60 2C 03 82 34 4100 6700 6900 6C00 6500 2000 2800 6200 6100 7300 6900 6300 2900 20"
|
||||||
|
|
||||||
|
"decode (for infantry)" in {
|
||||||
|
PacketCoding.DecodePacket(stringInfantry).require match {
|
||||||
|
case FavoritesMessage(list, player_guid, line, label, armor) =>
|
||||||
|
list mustEqual 0
|
||||||
|
player_guid mustEqual PlanetSideGUID(3760)
|
||||||
|
line mustEqual 0
|
||||||
|
label mustEqual "Agile (basic)"
|
||||||
|
armor.isDefined mustEqual true
|
||||||
|
armor.get mustEqual 1
|
||||||
|
case default =>
|
||||||
|
ko
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"encode (for infantry)" in {
|
||||||
|
val msg = FavoritesMessage(0, PlanetSideGUID(3760), 0, "Agile (basic)", Option(1))
|
||||||
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
||||||
|
pkt mustEqual stringInfantry
|
||||||
|
}
|
||||||
|
|
||||||
|
"decode (for vehicles)" in {
|
||||||
|
PacketCoding.DecodePacket(stringVehicles).require match {
|
||||||
|
case FavoritesMessage(list, player_guid, line, label, armor) =>
|
||||||
|
list mustEqual 1
|
||||||
|
player_guid mustEqual PlanetSideGUID(4210)
|
||||||
|
line mustEqual 0
|
||||||
|
label mustEqual "Skyguard"
|
||||||
|
armor.isDefined mustEqual false
|
||||||
|
case default =>
|
||||||
|
ko
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"encode (for vehicles)" in {
|
||||||
|
val msg = FavoritesMessage(1, PlanetSideGUID(4210), 0, "Skyguard")
|
||||||
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
||||||
|
pkt mustEqual stringVehicles
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
"WeaponJammedMessage" should {
|
"WeaponJammedMessage" should {
|
||||||
val string = hex"66 4C00"
|
val string = hex"66 4C00"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue