mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-19 18:44:45 +00:00
working encode and decode tests
This commit is contained in:
parent
811bf858f8
commit
1f629cf117
|
|
@ -7,48 +7,85 @@ import scodec.codecs._
|
||||||
import shapeless._
|
import shapeless._
|
||||||
|
|
||||||
import scala.annotation.switch
|
import scala.annotation.switch
|
||||||
|
import scala.util.Try
|
||||||
|
|
||||||
case class AmmoBox(magazine : Int)
|
abstract class ConstructorData
|
||||||
|
|
||||||
object AmmoBox extends Marshallable[AmmoBox] {
|
case class AmmoBoxData(magazine : Int) extends ConstructorData
|
||||||
implicit val codec : Codec[AmmoBox] = (
|
|
||||||
|
object AmmoBoxData extends Marshallable[AmmoBoxData] {
|
||||||
|
implicit val codec : Codec[AmmoBoxData] = (
|
||||||
("code" | uintL(23)) ::
|
("code" | uintL(23)) ::
|
||||||
("magazine" | uint16L)
|
("magazine" | uint16L)
|
||||||
).exmap[AmmoBox] (
|
).exmap[AmmoBoxData] (
|
||||||
{
|
{
|
||||||
case 0xC8 :: mag :: HNil =>
|
case 0xC8 :: mag :: HNil =>
|
||||||
Attempt.successful(AmmoBox(mag))
|
Attempt.successful(AmmoBoxData(mag))
|
||||||
case x :: _ :: HNil =>
|
case x :: _ :: HNil =>
|
||||||
Attempt.failure(Err("code wrong - looking for 200, found "+x))
|
Attempt.failure(Err("code wrong - looking for 200, found "+x))
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
case AmmoBox(mag) =>
|
case AmmoBoxData(mag) =>
|
||||||
Attempt.successful(0xC8 :: mag :: HNil)
|
Attempt.successful(0xC8 :: mag :: HNil)
|
||||||
}
|
}
|
||||||
).as[AmmoBox]
|
).as[AmmoBoxData]
|
||||||
}
|
}
|
||||||
|
|
||||||
case class Mold(objectClass : Int,
|
case class Mold(objectClass : Int,
|
||||||
data : BitVector) {
|
data : BitVector) {
|
||||||
private val obj : Option[Any] = Mold.selectMold(objectClass, data)
|
private var obj : Option[ConstructorData] = Mold.selectMold(objectClass, data)
|
||||||
|
|
||||||
def isDefined : Boolean = this.obj.isDefined
|
def isDefined : Boolean = this.obj.isDefined
|
||||||
|
|
||||||
def get : T forSome { type T } = this.obj.get
|
def get : ConstructorData = this.obj.get
|
||||||
|
|
||||||
|
def set(data : ConstructorData) : Boolean = {
|
||||||
|
var ret = false
|
||||||
|
if(Some(data).isDefined) {
|
||||||
|
obj = Some(data)
|
||||||
|
ret = true
|
||||||
|
}
|
||||||
|
ret
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object Mold {
|
object Mold {
|
||||||
def apply(objectClass : Int,
|
def apply(objectClass : Int, obj : ConstructorData) : Mold =
|
||||||
obj : T forSome { type T }) : Mold =
|
new Mold( objectClass, Mold.serialize(objectClass, obj) )
|
||||||
new Mold(objectClass, bin"")
|
|
||||||
|
|
||||||
def selectMold(objClass : Int, data : BitVector) : Option[_] = {
|
private def selectMold(objClass : Int, data : BitVector) : Option[ConstructorData] = {
|
||||||
(objClass : @switch) match {
|
var out : Option[ConstructorData] = None
|
||||||
case 0x1C =>
|
if(!data.isEmpty) {
|
||||||
Some(AmmoBox.codec.decode(data))
|
(objClass : @switch) match {
|
||||||
case _ =>
|
case 0x1C =>
|
||||||
None
|
val opt = AmmoBoxData.codec.decode(data).toOption
|
||||||
|
if(opt.isDefined) {
|
||||||
|
out = Some(opt.get.value)
|
||||||
|
}
|
||||||
|
case _ =>
|
||||||
|
out = None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
private def serialize(objClass : Int, obj : ConstructorData) : BitVector = {
|
||||||
|
var out = BitVector.empty
|
||||||
|
try {
|
||||||
|
(objClass : @switch) match {
|
||||||
|
case 0x1C =>
|
||||||
|
val opt = AmmoBoxData.codec.encode(obj.asInstanceOf[AmmoBoxData]).toOption
|
||||||
|
if(opt.isDefined) {
|
||||||
|
out = opt.get
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
case ex : ClassCastException => {
|
||||||
|
//TODO generate and log wrong class error message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,14 +143,6 @@ case class ObjectCreateMessage(streamLength : Long,
|
||||||
def encode = ObjectCreateMessage.encode(this)
|
def encode = ObjectCreateMessage.encode(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
object ObjectCreateMessageParent extends Marshallable[ObjectCreateMessageParent] {
|
|
||||||
implicit val codec : Codec[ObjectCreateMessageParent] = (
|
|
||||||
("guid" | PlanetSideGUID.codec) ::
|
|
||||||
("slot" | PacketHelpers.encodedStringSize)
|
|
||||||
).as[ObjectCreateMessageParent]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
object ObjectCreateMessage extends Marshallable[ObjectCreateMessage] {
|
object ObjectCreateMessage extends Marshallable[ObjectCreateMessage] {
|
||||||
type Pattern = Int :: PlanetSideGUID :: Option[ObjectCreateMessageParent] :: HNil
|
type Pattern = Int :: PlanetSideGUID :: Option[ObjectCreateMessageParent] :: HNil
|
||||||
/**
|
/**
|
||||||
|
|
@ -167,13 +196,20 @@ object ObjectCreateMessage extends Marshallable[ObjectCreateMessage] {
|
||||||
* @return the total length of the stream in bits
|
* @return the total length of the stream in bits
|
||||||
*/
|
*/
|
||||||
private def streamLen(parentInfo : Option[ObjectCreateMessageParent], data : BitVector) : Long = {
|
private def streamLen(parentInfo : Option[ObjectCreateMessageParent], data : BitVector) : Long = {
|
||||||
(if(parentInfo.isDefined) {
|
//known length
|
||||||
if(parentInfo.get.slot > 127) 92 else 84 //60u + 16u + (8u or 16u)
|
val first : Long = if(parentInfo.isDefined) {
|
||||||
|
if(parentInfo.get.slot > 127) 92L else 84L //60u + 16u + (8u or 16u)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
60
|
60L
|
||||||
}
|
}
|
||||||
+ data.size)
|
//variant length
|
||||||
|
var second : Long = data.size
|
||||||
|
val secondMod4 : Long = second % 4L
|
||||||
|
if(secondMod4 > 0L) { //pad to include last whole nibble
|
||||||
|
second += 4L - secondMod4
|
||||||
|
}
|
||||||
|
first + second
|
||||||
}
|
}
|
||||||
|
|
||||||
implicit val codec : Codec[ObjectCreateMessage] = (
|
implicit val codec : Codec[ObjectCreateMessage] = (
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,7 @@ class GamePacketTest extends Specification {
|
||||||
"decode (2)" in {
|
"decode (2)" in {
|
||||||
PacketCoding.DecodePacket(packet2).require match {
|
PacketCoding.DecodePacket(packet2).require match {
|
||||||
case obj @ ObjectCreateMessage(len, cls, guid, parent, mold) =>
|
case obj @ ObjectCreateMessage(len, cls, guid, parent, mold) =>
|
||||||
len mustEqual 248
|
len mustEqual 248 //60 + 188
|
||||||
cls mustEqual 121
|
cls mustEqual 121
|
||||||
guid mustEqual PlanetSideGUID(2497)
|
guid mustEqual PlanetSideGUID(2497)
|
||||||
parent mustEqual None
|
parent mustEqual None
|
||||||
|
|
@ -174,6 +174,9 @@ class GamePacketTest extends Specification {
|
||||||
parent.get.guid mustEqual PlanetSideGUID(75)
|
parent.get.guid mustEqual PlanetSideGUID(75)
|
||||||
parent.get.slot mustEqual 33
|
parent.get.slot mustEqual 33
|
||||||
mold.isDefined mustEqual true
|
mold.isDefined mustEqual true
|
||||||
|
|
||||||
|
val obj = mold.get.asInstanceOf[AmmoBoxData]
|
||||||
|
obj.magazine mustEqual 50
|
||||||
case default =>
|
case default =>
|
||||||
ko
|
ko
|
||||||
}
|
}
|
||||||
|
|
@ -185,6 +188,14 @@ class GamePacketTest extends Specification {
|
||||||
|
|
||||||
pkt mustEqual packet2
|
pkt mustEqual packet2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"encode (9mm)" in {
|
||||||
|
val obj = Mold(28, AmmoBoxData(50))
|
||||||
|
val msg = ObjectCreateMessage(0, 28, PlanetSideGUID(1280), Some(ObjectCreateMessageParent(PlanetSideGUID(75), 33)), obj)
|
||||||
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
||||||
|
pkt mustEqual string_9mm
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"ChatMsg" should {
|
"ChatMsg" should {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue