mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-20 02:24:45 +00:00
correct packet fields to support and added tests for 'no entry' packet; added commentary
This commit is contained in:
parent
3e84e999fb
commit
7050027235
|
|
@ -209,8 +209,8 @@ object PacketHelpers {
|
|||
* Codec that encodes/decodes a list of `n` elements, where `n` is known at compile time.<br>
|
||||
* <br>
|
||||
* This function is copied almost verbatim from its source, with exception of swapping the parameter that is normally a `Nat` `literal`.
|
||||
* The modified function takes a normal unsigned `Integer` and assures that the parameter is a non-negative before further processing.
|
||||
* @param size the fixed size of the `List`
|
||||
* The modified function takes a normal unsigned `Integer` and assures that the parameter is non-negative before further processing.
|
||||
* @param size the known size of the `List`
|
||||
* @param codec a codec that describes each of the contents of the `List`
|
||||
* @tparam A the type of the `List` contents
|
||||
* @see codec\package.scala, sizedList
|
||||
|
|
|
|||
|
|
@ -5,15 +5,45 @@ import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, Plan
|
|||
import scodec.Codec
|
||||
import scodec.codecs._
|
||||
|
||||
final case class Friend(name : String = "",
|
||||
/**
|
||||
* An entry in the list of players known to and tracked by this player.
|
||||
* They're called "friends" even though they can be used for a list of ignored players as well.
|
||||
* @param name the name of the player
|
||||
* @param online the player's current state of activity; defaults to `false`, or offline
|
||||
*/
|
||||
final case class Friend(name : String,
|
||||
online : Boolean = false)
|
||||
|
||||
final case class FriendsResponse(unk1 : Int,
|
||||
unk2 : Int,
|
||||
/**
|
||||
* Manage the lists of other players whose names are retained by the given player.<br>
|
||||
* <br>
|
||||
* Friends can be remembered and their current playing status can be reported.
|
||||
* Ignored players will have their comments stifled in the given player's chat window.
|
||||
* This does not handle outfit member lists.<br>
|
||||
* <br>
|
||||
* Actions:<br>
|
||||
* 0 - initialize friends list (no logging)<br>
|
||||
* 1 - add entry to friends list<br>
|
||||
* 2 - remove entry from friends list<br>
|
||||
* 3 - update status of player in friends list;
|
||||
* if player is not listed, he is not added<br>
|
||||
* 4 - initialize ignored players list (no logging)<br>
|
||||
* 5 - add entry to ignored players list<br>
|
||||
* 6 - remove entry from ignored players list<br>
|
||||
* @param action the purpose of the entry(s) in this packet
|
||||
* @param unk1 na; always 0?
|
||||
* @param unk2 na; always `true`?
|
||||
* @param unk3 na; always `true`?
|
||||
* @param number_of_friends the number of `Friend` entries handled by this packet; max is 15 per packet
|
||||
* @param friend the first `Friend` entry
|
||||
* @param friends all the other `Friend` entries
|
||||
*/
|
||||
final case class FriendsResponse(action : Int,
|
||||
unk1 : Int,
|
||||
unk2 : Boolean,
|
||||
unk3 : Boolean,
|
||||
unk4 : Boolean,
|
||||
number_of_friends : Int,
|
||||
friend : Friend,
|
||||
friend : Option[Friend] = None,
|
||||
friends : List[Friend] = Nil)
|
||||
extends PlanetSideGamePacket {
|
||||
type Packet = FriendsResponse
|
||||
|
|
@ -27,6 +57,10 @@ object Friend extends Marshallable[Friend] {
|
|||
("online" | bool)
|
||||
).as[Friend]
|
||||
|
||||
/**
|
||||
* This codec is used for the "`List` of other `Friends`."
|
||||
* Initial byte-alignment creates padding differences which requires a second `Codec`.
|
||||
*/
|
||||
implicit val codec_list : Codec[Friend] = (
|
||||
("name" | PacketHelpers.encodedWideStringAligned(7)) ::
|
||||
("online" | bool)
|
||||
|
|
@ -35,13 +69,13 @@ object Friend extends Marshallable[Friend] {
|
|||
|
||||
object FriendsReponse extends Marshallable[FriendsResponse] {
|
||||
implicit val codec : Codec[FriendsResponse] = (
|
||||
("unk1" | uintL(3)) ::
|
||||
("unk2" | uintL(4)) ::
|
||||
("action" | uintL(3)) ::
|
||||
("unk1" | uint4L) ::
|
||||
("unk2" | bool) ::
|
||||
("unk3" | bool) ::
|
||||
("unk4" | bool) ::
|
||||
(("number_of_friends" | uintL(4)) >>:~ { len =>
|
||||
("friend" | Friend.codec) ::
|
||||
("friends" | PacketHelpers.sizedList(len-1, Friend.codec_list))
|
||||
(("number_of_friends" | uint4L) >>:~ { len =>
|
||||
conditional(len > 0, "friend" | Friend.codec) ::
|
||||
("friends" | PacketHelpers.sizedList(len-1, Friend.codec_list)) //List of 'Friend(String, Boolean)'s without a size field when encoded
|
||||
})
|
||||
).as[FriendsResponse]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -833,6 +833,7 @@ class GamePacketTest extends Specification {
|
|||
"FriendsResponse" should {
|
||||
val stringOneFriend = hex"73 61 8C 60 4B007500720074004800650063007400690063002D004700 00"
|
||||
val stringManyFriends = hex"73 01 AC 48 4100 6E00 6700 6500 6C00 6C00 6F00 2D00 5700 47 00 7400 6800 6500 7000 6800 6100 7400 7400 7000 6800 7200 6F00 6700 6700 46 80 4B00 6900 6D00 7000 6F00 7300 7300 6900 6200 6C00 6500 3100 3200 45 00 5A00 6500 6100 7200 7400 6800 6C00 6900 6E00 6700 46 00 4B00 7500 7200 7400 4800 6500 6300 7400 6900 6300 2D00 4700 00"
|
||||
val stringShort = hex"73 81 80"
|
||||
|
||||
"decode (one friend)" in {
|
||||
PacketCoding.DecodePacket(stringOneFriend).require match {
|
||||
|
|
@ -842,8 +843,9 @@ class GamePacketTest extends Specification {
|
|||
unk3 mustEqual true
|
||||
unk4 mustEqual true
|
||||
number_of_friends mustEqual 1
|
||||
friend.name mustEqual "KurtHectic-G"
|
||||
friend.online mustEqual false
|
||||
friend.isDefined mustEqual true
|
||||
friend.get.name mustEqual "KurtHectic-G"
|
||||
friend.get.online mustEqual false
|
||||
list.size mustEqual 0
|
||||
case default =>
|
||||
ko
|
||||
|
|
@ -858,8 +860,9 @@ class GamePacketTest extends Specification {
|
|||
unk3 mustEqual true
|
||||
unk4 mustEqual true
|
||||
number_of_friends mustEqual 5
|
||||
friend.name mustEqual "Angello-W"
|
||||
friend.online mustEqual false
|
||||
friend.isDefined mustEqual true
|
||||
friend.get.name mustEqual "Angello-W"
|
||||
friend.get.online mustEqual false
|
||||
list.size mustEqual 4
|
||||
list.head.name mustEqual "thephattphrogg"
|
||||
list.head.online mustEqual false
|
||||
|
|
@ -874,22 +877,44 @@ class GamePacketTest extends Specification {
|
|||
}
|
||||
}
|
||||
|
||||
"decode (short)" in {
|
||||
PacketCoding.DecodePacket(stringShort).require match {
|
||||
case FriendsResponse(unk1, unk2, unk3, unk4, number_of_friends, friend, list) =>
|
||||
unk1 mustEqual 4
|
||||
unk2 mustEqual 0
|
||||
unk3 mustEqual true
|
||||
unk4 mustEqual true
|
||||
number_of_friends mustEqual 0
|
||||
friend.isDefined mustEqual false
|
||||
list.size mustEqual 0
|
||||
case default =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (one friend)" in {
|
||||
val msg = FriendsResponse(3, 0, true, true, 1, Friend("KurtHectic-G", false))
|
||||
val msg = FriendsResponse(3, 0, true, true, 1, Option(Friend("KurtHectic-G", false)))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual stringOneFriend
|
||||
}
|
||||
|
||||
"encode (multiple friends)" in {
|
||||
val msg = FriendsResponse(0, 0, true, true, 5, Friend("Angello-W", false), Friend("thephattphrogg", false) ::
|
||||
Friend("Kimpossible12", false) ::
|
||||
Friend("Zearthling", false) ::
|
||||
Friend("KurtHectic-G", false) :: Nil)
|
||||
val msg = FriendsResponse(0, 0, true, true, 5, Option(Friend("Angello-W", false)), Friend("thephattphrogg", false) ::
|
||||
Friend("Kimpossible12", false) ::
|
||||
Friend("Zearthling", false) ::
|
||||
Friend("KurtHectic-G", false) :: Nil)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual stringManyFriends
|
||||
}
|
||||
|
||||
"encode (short)" in {
|
||||
val msg = FriendsResponse(4, 0, true, true, 0)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual stringShort
|
||||
}
|
||||
}
|
||||
|
||||
"WeaponDryFireMessage" should {
|
||||
|
|
|
|||
Loading…
Reference in a new issue