added tests for: VoiceHost*, CharacterInfoMessage, CharacterCreateRequestMessage, CharacterRequestMessage, and KeepAliveMessage; modified test for ObjectDetectedMessage

This commit is contained in:
FateJH 2017-05-03 19:48:23 -04:00
parent 461a4f9507
commit 939e0ed688
12 changed files with 257 additions and 39 deletions

View file

@ -26,7 +26,8 @@ object PlanetSideGUID {
* *
* @param finished True when there are no more characters to give info on * @param finished True when there are no more characters to give info on
*/ */
final case class CharacterInfoMessage(zoneId : PlanetSideZoneID, final case class CharacterInfoMessage(unk : Long,
zoneId : PlanetSideZoneID,
charId : Long, charId : Long,
guid : PlanetSideGUID, guid : PlanetSideGUID,
finished : Boolean, finished : Boolean,
@ -39,8 +40,8 @@ final case class CharacterInfoMessage(zoneId : PlanetSideZoneID,
object CharacterInfoMessage extends Marshallable[CharacterInfoMessage] { object CharacterInfoMessage extends Marshallable[CharacterInfoMessage] {
implicit val codec : Codec[CharacterInfoMessage] = ( implicit val codec : Codec[CharacterInfoMessage] = (
("unknown" | uint32L).unit(0) :: // this type is set to unit as we dont know what it is yet ("unk" | uint32L) ::
("zoneId" | PlanetSideZoneID.codec) :: ("zoneId" | PlanetSideZoneID.codec) ::
("charId" | uint32L) :: ("charId" | uint32L) ::
("charGUID" | PlanetSideGUID.codec) :: ("charGUID" | PlanetSideGUID.codec) ::
("finished" | bool) :: ("finished" | bool) ::

View file

@ -1,11 +1,11 @@
// Copyright (c) 2017 PSForever // Copyright (c) 2017 PSForever
package net.psforever.packet.game package net.psforever.packet.game
import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket} import net.psforever.packet.{GamePacketOpcode, Marshallable, PlanetSideGamePacket}
import scodec.Codec import scodec.Codec
import scodec.codecs._ import scodec.codecs._
final case class KeepAliveMessage(code : Int) extends PlanetSideGamePacket { final case class KeepAliveMessage(code : Int = 0) extends PlanetSideGamePacket {
type Packet = KeepAliveMessage type Packet = KeepAliveMessage
def opcode = GamePacketOpcode.KeepAliveMessage def opcode = GamePacketOpcode.KeepAliveMessage
def encode = KeepAliveMessage.encode(this) def encode = KeepAliveMessage.encode(this)

View file

@ -7,18 +7,18 @@ import scodec.{Attempt, Codec, Err}
import shapeless.{::, HNil} import shapeless.{::, HNil}
/** /**
* na * Update a list of (new) objects that have been detected by this client in one way or another.
* @param guid1 na * @param player_guid1 the player
* @param guid2 na; * @param player_guid2 the player(?);
* often matches with `guid1` * often matches with `player_guid1`
* @param unk1 na * @param unk na
* @param unk2 na; * @param list list of detected objects;
* normally contains at least one element * normally contains at least one element
*/ */
final case class ObjectDetectedMessage(guid1 : PlanetSideGUID, final case class ObjectDetectedMessage(player_guid1 : PlanetSideGUID,
guid2 : PlanetSideGUID, player_guid2 : PlanetSideGUID,
unk1 : Int, unk : Int,
unk2 : List[Int]) list : List[PlanetSideGUID])
extends PlanetSideGamePacket { extends PlanetSideGamePacket {
type Packet = ObjectDetectedMessage type Packet = ObjectDetectedMessage
def opcode = GamePacketOpcode.ObjectDetectedMessage def opcode = GamePacketOpcode.ObjectDetectedMessage
@ -27,22 +27,22 @@ final case class ObjectDetectedMessage(guid1 : PlanetSideGUID,
object ObjectDetectedMessage extends Marshallable[ObjectDetectedMessage] { object ObjectDetectedMessage extends Marshallable[ObjectDetectedMessage] {
implicit val codec : Codec[ObjectDetectedMessage] = ( implicit val codec : Codec[ObjectDetectedMessage] = (
("guid1" | PlanetSideGUID.codec) :: ("player_guid1" | PlanetSideGUID.codec) ::
("guid2" | PlanetSideGUID.codec) :: ("player_guid2" | PlanetSideGUID.codec) ::
("unk1" | uint8L) :: ("unk" | uint8L) ::
("unk2" | listOfN(uintL(6), uint16L)) //TODO are these uids? ("list" | listOfN(uintL(6), PlanetSideGUID.codec))
).exmap[ObjectDetectedMessage] ( ).exmap[ObjectDetectedMessage] (
{ {
case g1 :: g2 :: u1 :: u2 :: HNil => case g1 :: g2 :: u :: lst :: HNil =>
Attempt.successful(ObjectDetectedMessage(g1, g2, u1, u2)) Attempt.successful(ObjectDetectedMessage(g1, g2, u, lst))
}, },
{ {
case ObjectDetectedMessage(g1, g2, u1, u2) => case ObjectDetectedMessage(g1, g2, u, lst) =>
if(u2.size > 63) { if(lst.size > 63) {
Attempt.failure(Err(s"too many list elements (max: 63, actual: ${u2.size})")) Attempt.failure(Err(s"too many list elements (max: 63, actual: ${lst.size})"))
} }
else { else {
Attempt.successful(g1 :: g2 :: u1 :: u2 :: HNil) Attempt.successful(g1 :: g2 :: u :: lst :: HNil)
} }
} }
) )

View file

@ -0,0 +1,33 @@
// Copyright (c) 2017 PSForever
package game
import org.specs2.mutable._
import net.psforever.packet._
import net.psforever.packet.game._
import net.psforever.types.{CharacterGender, PlanetSideEmpire}
import scodec.bits._
class CharacterCreateRequestMessageTest extends Specification {
val string = hex"2f 88 54006500730074004300680061007200 320590"
"decode" in {
PacketCoding.DecodePacket(string).require match {
case CharacterCreateRequestMessage(name, head, voice, gender, faction) =>
name mustEqual "TestChar"
head mustEqual 50
voice mustEqual 5
gender mustEqual CharacterGender.Female
faction mustEqual PlanetSideEmpire.NC
case _ =>
ko
}
}
"encode" in {
val msg = CharacterCreateRequestMessage("TestChar", 50, 5, CharacterGender.Female, PlanetSideEmpire.NC)
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string
}
}

View file

@ -0,0 +1,32 @@
// Copyright (c) 2017 PSForever
package game
import org.specs2.mutable._
import net.psforever.packet._
import net.psforever.packet.game._
import scodec.bits._
class CharacterInfoMessageTest extends Specification {
val string = hex"14 0F000000 10270000C1D87A024B00265CB08000"
"decode" in {
PacketCoding.DecodePacket(string).require match {
case CharacterInfoMessage(unk, zone, charId, guid, finished, last) =>
unk mustEqual 15L
zone mustEqual PlanetSideZoneID(10000)
charId mustEqual 41605313L
guid mustEqual PlanetSideGUID(75)
finished mustEqual false
last mustEqual 6404428L
case _ =>
ko
}
}
"encode" in {
val msg = CharacterInfoMessage(15L, PlanetSideZoneID(10000), 41605313L, PlanetSideGUID(75), false, 6404428L)
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string
}
}

View file

@ -0,0 +1,30 @@
// Copyright (c) 2017 PSForever
package game
import org.specs2.mutable._
import net.psforever.packet._
import net.psforever.packet.game._
import net.psforever.types.{CharacterGender, PlanetSideEmpire}
import scodec.bits._
class CharacterRequestMessageTest extends Specification {
val string = hex"30 c1d87a02 00000000"
"decode" in {
PacketCoding.DecodePacket(string).require match {
case CharacterRequestMessage(charId, action) =>
charId mustEqual 41605313L
action mustEqual CharacterRequestAction.Select
case _ =>
ko
}
}
"encode" in {
val msg = CharacterRequestMessage(41605313L, CharacterRequestAction.Select)
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string
}
}

View file

@ -0,0 +1,28 @@
// Copyright (c) 2017 PSForever
package game
import org.specs2.mutable._
import net.psforever.packet._
import net.psforever.packet.game._
import scodec.bits._
class KeepAliveMessageTest extends Specification {
val string = hex"BA 0000"
"decode" in {
PacketCoding.DecodePacket(string).require match {
case KeepAliveMessage(code) =>
code mustEqual 0
case _ =>
ko
}
}
"encode" in {
val msg = KeepAliveMessage()
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string
}
}

View file

@ -11,25 +11,37 @@ class ObjectDetectedMessageTest extends Specification {
"decode" in { "decode" in {
PacketCoding.DecodePacket(string).require match { PacketCoding.DecodePacket(string).require match {
case ObjectDetectedMessage(guid1, guid2, unk1, unk2) => case ObjectDetectedMessage(guid1, guid2, unk1, list) =>
guid1 mustEqual PlanetSideGUID(4070) guid1 mustEqual PlanetSideGUID(4070)
guid2 mustEqual PlanetSideGUID(4070) guid2 mustEqual PlanetSideGUID(4070)
unk1 mustEqual 0 unk1 mustEqual 0
unk2.size mustEqual 7 list.size mustEqual 7
unk2.head mustEqual 3623 list.head mustEqual PlanetSideGUID(3623)
unk2(1) mustEqual 3198 list(1) mustEqual PlanetSideGUID(3198)
unk2(2) mustEqual 3088 list(2) mustEqual PlanetSideGUID(3088)
unk2(3) mustEqual 1579 list(3) mustEqual PlanetSideGUID(1579)
unk2(4) mustEqual 1578 list(4) mustEqual PlanetSideGUID(1578)
unk2(5) mustEqual 3341 list(5) mustEqual PlanetSideGUID(3341)
unk2(6) mustEqual 2997 list(6) mustEqual PlanetSideGUID(2997)
case _ => case _ =>
ko ko
} }
} }
"encode" in { "encode" in {
val msg = ObjectDetectedMessage(PlanetSideGUID(4070), PlanetSideGUID(4070), 0, 3623 :: 3198 :: 3088 :: 1579 :: 1578 :: 3341 :: 2997 :: Nil) val msg = ObjectDetectedMessage(
PlanetSideGUID(4070),
PlanetSideGUID(4070),
0,
PlanetSideGUID(3623) ::
PlanetSideGUID(3198) ::
PlanetSideGUID(3088) ::
PlanetSideGUID(1579) ::
PlanetSideGUID(1578) ::
PlanetSideGUID(3341) ::
PlanetSideGUID(2997) ::
Nil
)
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string pkt mustEqual string

View file

@ -0,0 +1,27 @@
// Copyright (c) 2017 PSForever
package game
import org.specs2.mutable._
import net.psforever.packet._
import net.psforever.packet.game._
import scodec.bits._
class VoiceHostInfoTest extends Specification {
val string_info = hex"b2 4b00"
"decode" in {
PacketCoding.DecodePacket(string_info).require match {
case VoiceHostInfo(player, _) =>
player mustEqual PlanetSideGUID(75)
case _ =>
ko
}
}
"encode" in {
val msg = VoiceHostInfo(PlanetSideGUID(75), ByteVector.empty)
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_info
}
}

View file

@ -0,0 +1,27 @@
// Copyright (c) 2017 PSForever
package game
import org.specs2.mutable._
import net.psforever.packet._
import net.psforever.packet.game._
import scodec.bits._
class VoiceHostKillTest extends Specification {
val string_kill = hex"b1"
"decode" in {
PacketCoding.DecodePacket(string_kill).require match {
case VoiceHostKill() =>
ok
case _ =>
ko
}
}
"encode" in {
val msg = VoiceHostKill()
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_kill
}
}

View file

@ -0,0 +1,28 @@
// Copyright (c) 2017 PSForever
package game
import org.specs2.mutable._
import net.psforever.packet._
import net.psforever.packet.game._
import scodec.bits._
class VoiceHostRequestTest extends Specification {
val string_request = hex"b0 2580 00"
"decode" in {
PacketCoding.DecodePacket(string_request).require match {
case VoiceHostRequest(unk, player, _) =>
unk mustEqual false
player mustEqual PlanetSideGUID(75)
case _ =>
ko
}
}
"encode" in {
val msg = VoiceHostRequest(false, PlanetSideGUID(75), ByteVector.empty)
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_request
}
}

View file

@ -177,7 +177,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
// NOTE: PlanetSideZoneID just chooses the background // NOTE: PlanetSideZoneID just chooses the background
sendResponse(PacketCoding.CreateGamePacket(0, sendResponse(PacketCoding.CreateGamePacket(0,
CharacterInfoMessage(PlanetSideZoneID(1), 0, PlanetSideGUID(0), true, 0))) CharacterInfoMessage(0, PlanetSideZoneID(1), 0, PlanetSideGUID(0), true, 0)))
case msg @ CharacterRequestMessage(charId, action) => case msg @ CharacterRequestMessage(charId, action) =>
log.info("Handling " + msg) log.info("Handling " + msg)
@ -190,7 +190,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
log.debug("Object: " + obj) log.debug("Object: " + obj)
// LoadMapMessage 13714 in mossy .gcap // LoadMapMessage 13714 in mossy .gcap
// XXX: hardcoded shit // XXX: hardcoded shit
sendResponse(PacketCoding.CreateGamePacket(0, LoadMapMessage("map10","z10",40100,25,true,3770441820L))) //VS Sanctuary sendResponse(PacketCoding.CreateGamePacket(0, LoadMapMessage("map13","home3",40100,25,true,3770441820L))) //VS Sanctuary
sendResponse(PacketCoding.CreateGamePacket(0, ZonePopulationUpdateMessage(PlanetSideGUID(13), 414, 138, 0, 138, 0, 138, 0, 138, 0))) sendResponse(PacketCoding.CreateGamePacket(0, ZonePopulationUpdateMessage(PlanetSideGUID(13), 414, 138, 0, 138, 0, 138, 0, 138, 0)))
sendResponse(PacketCoding.CreateGamePacket(0, objectHex)) sendResponse(PacketCoding.CreateGamePacket(0, objectHex))
@ -241,10 +241,10 @@ class WorldSessionActor extends Actor with MDCContextAware {
sendResponse(PacketCoding.CreateGamePacket(0, ActionResultMessage(true, None))) sendResponse(PacketCoding.CreateGamePacket(0, ActionResultMessage(true, None)))
sendResponse(PacketCoding.CreateGamePacket(0, sendResponse(PacketCoding.CreateGamePacket(0,
CharacterInfoMessage(PlanetSideZoneID(0), 0, PlanetSideGUID(0), true, 0))) CharacterInfoMessage(0, PlanetSideZoneID(0), 0, PlanetSideGUID(0), true, 0)))
case KeepAliveMessage(code) => case KeepAliveMessage(code) =>
sendResponse(PacketCoding.CreateGamePacket(0, KeepAliveMessage(0))) sendResponse(PacketCoding.CreateGamePacket(0, KeepAliveMessage()))
case msg @ BeginZoningMessage() => case msg @ BeginZoningMessage() =>
log.info("Reticulating splines ...") log.info("Reticulating splines ...")