mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-25 04:54:45 +00:00
Merge branch 'friends-response'
This commit is contained in:
commit
b8f40bd016
|
|
@ -455,7 +455,7 @@ object GamePacketOpcode extends Enumeration {
|
|||
case 0x70 => noDecoder(SquadMemberEvent)
|
||||
case 0x71 => noDecoder(PlatoonEvent)
|
||||
case 0x72 => noDecoder(FriendsRequest)
|
||||
case 0x73 => noDecoder(FriendsResponse)
|
||||
case 0x73 => game.FriendsResponse.decode
|
||||
case 0x74 => noDecoder(TriggerEnvironmentalDamageMessage)
|
||||
case 0x75 => noDecoder(TrainingZoneMessage)
|
||||
case 0x76 => noDecoder(DeployableObjectsInfoMessage)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
// 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}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
|
||||
/**
|
||||
* 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 friends a list of `Friend`s
|
||||
*/
|
||||
final case class FriendsResponse(action : Int,
|
||||
unk1 : Int,
|
||||
unk2 : Boolean,
|
||||
unk3 : Boolean,
|
||||
friends : List[Friend] = Nil)
|
||||
extends PlanetSideGamePacket {
|
||||
type Packet = FriendsResponse
|
||||
def opcode = GamePacketOpcode.FriendsResponse
|
||||
def encode = FriendsResponse.encode(this)
|
||||
}
|
||||
|
||||
object Friend extends Marshallable[Friend] {
|
||||
implicit val codec : Codec[Friend] = (
|
||||
("name" | PacketHelpers.encodedWideStringAligned(3)) ::
|
||||
("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)
|
||||
).as[Friend]
|
||||
}
|
||||
|
||||
object FriendsResponse extends Marshallable[FriendsResponse] {
|
||||
implicit val codec : Codec[FriendsResponse] = (
|
||||
("action" | uintL(3)) ::
|
||||
("unk1" | uint4L) ::
|
||||
("unk2" | bool) ::
|
||||
("unk3" | bool) ::
|
||||
(("number_of_friends" | uint4L) >>:~ { len =>
|
||||
conditional(len > 0, "friend" | Friend.codec) ::
|
||||
("friends" | PacketHelpers.listOfNSized(len-1, Friend.codec_list))
|
||||
})
|
||||
).xmap[FriendsResponse] (
|
||||
{
|
||||
case act :: u1 :: u2 :: u3 :: num :: friend1 :: friends :: HNil =>
|
||||
val friendList : List[Friend] = if(friend1.isDefined) { friend1.get :: friends } else { friends }
|
||||
FriendsResponse(act, u1, u2, u3, friendList)
|
||||
},
|
||||
{
|
||||
case FriendsResponse(act, u1, u2, u3, friends) =>
|
||||
var friend1 : Option[Friend] = None
|
||||
var friendList : List[Friend] = Nil
|
||||
if(friends.nonEmpty) {
|
||||
friend1 = Some(friends.head)
|
||||
friendList = friends.drop(1)
|
||||
}
|
||||
act :: u1 :: u2 :: u3 :: friends.size :: friend1 :: friendList :: HNil
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -831,6 +831,88 @@ 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 {
|
||||
case FriendsResponse(action, unk2, unk3, unk4, list) =>
|
||||
action mustEqual 3
|
||||
unk2 mustEqual 0
|
||||
unk3 mustEqual true
|
||||
unk4 mustEqual true
|
||||
list.size mustEqual 1
|
||||
list.head.name mustEqual "KurtHectic-G"
|
||||
list.head.online mustEqual false
|
||||
case default =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (multiple friends)" in {
|
||||
PacketCoding.DecodePacket(stringManyFriends).require match {
|
||||
case FriendsResponse(action, unk2, unk3, unk4, list) =>
|
||||
action mustEqual 0
|
||||
unk2 mustEqual 0
|
||||
unk3 mustEqual true
|
||||
unk4 mustEqual true
|
||||
list.size mustEqual 5
|
||||
list.head.name mustEqual "Angello-W"
|
||||
list.head.online mustEqual false
|
||||
list(1).name mustEqual "thephattphrogg"
|
||||
list(1).online mustEqual false
|
||||
list(2).name mustEqual "Kimpossible12"
|
||||
list(2).online mustEqual false
|
||||
list(3).name mustEqual "Zearthling"
|
||||
list(3).online mustEqual false
|
||||
list(4).name mustEqual "KurtHectic-G"
|
||||
list(4).online mustEqual false
|
||||
case default =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (short)" in {
|
||||
PacketCoding.DecodePacket(stringShort).require match {
|
||||
case FriendsResponse(action, unk2, unk3, unk4, list) =>
|
||||
action mustEqual 4
|
||||
unk2 mustEqual 0
|
||||
unk3 mustEqual true
|
||||
unk4 mustEqual true
|
||||
list.size mustEqual 0
|
||||
case default =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (one friend)" in {
|
||||
val msg = FriendsResponse(3, 0, true, true, Friend("KurtHectic-G", false) :: Nil)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual stringOneFriend
|
||||
}
|
||||
|
||||
"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)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual stringManyFriends
|
||||
}
|
||||
|
||||
"encode (short)" in {
|
||||
val msg = FriendsResponse(4, 0, true, true)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual stringShort
|
||||
}
|
||||
}
|
||||
|
||||
"WeaponDryFireMessage" should {
|
||||
val string = hex"52 4C00"
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue