Merge branch 'friends-response'

This commit is contained in:
FateJH 2017-01-09 23:40:05 -05:00
commit b8f40bd016
3 changed files with 177 additions and 1 deletions

View file

@ -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)

View file

@ -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
}
)
}