mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-19 18:14:44 +00:00
solved encoding issues, but am not perfectly happy with the solution; tests pass for one friend name and many friend names; check new codec for sizedList
This commit is contained in:
parent
b444b4b503
commit
3e84e999fb
|
|
@ -3,7 +3,8 @@ package net.psforever.packet
|
|||
|
||||
import java.nio.charset.Charset
|
||||
|
||||
import scodec.{DecodeResult, Err, Codec, Attempt}
|
||||
import scodec.Attempt.Successful
|
||||
import scodec.{Attempt, Codec, DecodeResult, Err}
|
||||
import scodec.bits._
|
||||
import scodec.codecs._
|
||||
import scodec._
|
||||
|
|
@ -205,15 +206,17 @@ object PacketHelpers {
|
|||
*/
|
||||
|
||||
/**
|
||||
* Construct a `Codec` for reading `wchar_t` (wide character) `Strings` whose length field are constrained to specific bit size proportions.
|
||||
* Padding may also exist between the length field and the beginning of the contents.
|
||||
* @param lenSize a codec that defines the bit size that encodes the length
|
||||
* @param adjustment the optional alignment for padding; defaults to 0
|
||||
* @return the `String` `Codec`
|
||||
* 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`
|
||||
* @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
|
||||
* @see codec\package.scala, listOfN
|
||||
* @see codec\package.scala, provides
|
||||
* @return a codec that works on a List of A but excludes the size from the encoding
|
||||
*/
|
||||
def specSizeWideStringAligned(lenSize : Codec[Int], adjustment : Int = 0) : Codec[String] =
|
||||
variableSizeBytes((lenSize <~ ignore(adjustment)).xmap(
|
||||
insize => insize*2, // number of symbols -> number of bytes (decode)
|
||||
outSize => outSize/2 // number of bytes -> number of symbols (encode)
|
||||
), utf16)
|
||||
def sizedList[A](size : Int, codec : Codec[A]) : Codec[List[A]] = listOfN(provide(if(size < 0) 0 else size), codec)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,25 +5,43 @@ import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, Plan
|
|||
import scodec.Codec
|
||||
import scodec.codecs._
|
||||
|
||||
/**
|
||||
* na
|
||||
* @param player_guid the player
|
||||
* @param friend the name of the friend
|
||||
* @param unk na
|
||||
*/
|
||||
final case class FriendsResponse(player_guid : PlanetSideGUID,
|
||||
friend : String,
|
||||
unk : Boolean)
|
||||
final case class Friend(name : String = "",
|
||||
online : Boolean = false)
|
||||
|
||||
final case class FriendsResponse(unk1 : Int,
|
||||
unk2 : Int,
|
||||
unk3 : Boolean,
|
||||
unk4 : Boolean,
|
||||
number_of_friends : Int,
|
||||
friend : Friend,
|
||||
friends : List[Friend] = Nil)
|
||||
extends PlanetSideGamePacket {
|
||||
type Packet = FriendsResponse
|
||||
def opcode = GamePacketOpcode.FriendsResponse
|
||||
def encode = FriendsReponse.encode(this)
|
||||
}
|
||||
|
||||
object Friend extends Marshallable[Friend] {
|
||||
implicit val codec : Codec[Friend] = (
|
||||
("name" | PacketHelpers.encodedWideStringAligned(3)) ::
|
||||
("online" | bool)
|
||||
).as[Friend]
|
||||
|
||||
implicit val codec_list : Codec[Friend] = (
|
||||
("name" | PacketHelpers.encodedWideStringAligned(7)) ::
|
||||
("online" | bool)
|
||||
).as[Friend]
|
||||
}
|
||||
|
||||
object FriendsReponse extends Marshallable[FriendsResponse] {
|
||||
implicit val codec : Codec[FriendsResponse] = (
|
||||
("player_guid" | PlanetSideGUID.codec) ::
|
||||
("friend" | PacketHelpers.specSizeWideStringAligned(uint(5), 3)) ::
|
||||
("unk" | bool)
|
||||
("unk1" | uintL(3)) ::
|
||||
("unk2" | uintL(4)) ::
|
||||
("unk3" | bool) ::
|
||||
("unk4" | bool) ::
|
||||
(("number_of_friends" | uintL(4)) >>:~ { len =>
|
||||
("friend" | Friend.codec) ::
|
||||
("friends" | PacketHelpers.sizedList(len-1, Friend.codec_list))
|
||||
})
|
||||
).as[FriendsResponse]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -831,25 +831,64 @@ class GamePacketTest extends Specification {
|
|||
}
|
||||
|
||||
"FriendsResponse" should {
|
||||
val string = hex"73 618C 60 4B007500720074004800650063007400690063002D004700 00"
|
||||
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"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case FriendsResponse(player_guid, friend, unk) =>
|
||||
player_guid mustEqual PlanetSideGUID(35937)
|
||||
friend.length mustEqual 12
|
||||
friend mustEqual "KurtHectic-G"
|
||||
unk mustEqual false
|
||||
"decode (one friend)" in {
|
||||
PacketCoding.DecodePacket(stringOneFriend).require match {
|
||||
case FriendsResponse(unk1, unk2, unk3, unk4, number_of_friends, friend, list) =>
|
||||
unk1 mustEqual 3
|
||||
unk2 mustEqual 0
|
||||
unk3 mustEqual true
|
||||
unk4 mustEqual true
|
||||
number_of_friends mustEqual 1
|
||||
friend.name mustEqual "KurtHectic-G"
|
||||
friend.online mustEqual false
|
||||
list.size mustEqual 0
|
||||
case default =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = FriendsResponse(PlanetSideGUID(35937), "KurtHectic-G", false)
|
||||
"decode (multiple friends)" in {
|
||||
PacketCoding.DecodePacket(stringManyFriends).require match {
|
||||
case FriendsResponse(unk1, unk2, unk3, unk4, number_of_friends, friend, list) =>
|
||||
unk1 mustEqual 0
|
||||
unk2 mustEqual 0
|
||||
unk3 mustEqual true
|
||||
unk4 mustEqual true
|
||||
number_of_friends mustEqual 5
|
||||
friend.name mustEqual "Angello-W"
|
||||
friend.online mustEqual false
|
||||
list.size mustEqual 4
|
||||
list.head.name mustEqual "thephattphrogg"
|
||||
list.head.online mustEqual false
|
||||
list(1).name mustEqual "Kimpossible12"
|
||||
list(1).online mustEqual false
|
||||
list(2).name mustEqual "Zearthling"
|
||||
list(2).online mustEqual false
|
||||
list(3).name mustEqual "KurtHectic-G"
|
||||
list(3).online mustEqual false
|
||||
case default =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (one friend)" in {
|
||||
val msg = FriendsResponse(3, 0, true, true, 1, Friend("KurtHectic-G", false))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
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 pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual stringManyFriends
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue