working example of object mold (see test for decoding 9mm) but needs work for casting to object type

This commit is contained in:
FateJH 2016-11-26 00:55:21 -05:00
parent 4bbf627770
commit 811bf858f8
3 changed files with 52 additions and 29 deletions

View file

@ -8,42 +8,48 @@ import shapeless._
import scala.annotation.switch import scala.annotation.switch
case class Weapon(unk1 : Int, case class AmmoBox(magazine : Int)
magazine : Int,
unk2 : Int)
object Weapon extends Marshallable[Weapon] { object AmmoBox extends Marshallable[AmmoBox] {
implicit val codec : Codec[Weapon] = ( implicit val codec : Codec[AmmoBox] = (
("unk1" | uintL(23)) :: ("code" | uintL(23)) ::
("magazine" | uint8L) :: ("magazine" | uint16L)
("unk2" | uintL(13)) ).exmap[AmmoBox] (
).as[Weapon] {
case 0xC8 :: mag :: HNil =>
Attempt.successful(AmmoBox(mag))
case x :: _ :: HNil =>
Attempt.failure(Err("code wrong - looking for 200, found "+x))
},
{
case AmmoBox(mag) =>
Attempt.successful(0xC8 :: mag :: HNil)
}
).as[AmmoBox]
} }
case class Mold(objectClass : Int, case class Mold(objectClass : Int,
dataPortion : BitVector) { data : BitVector) {
private val obj : Option[Any] = Mold.selectMold(objectClass, data)
private var obj : Option[Any] = Mold.selectMold(objectClass, dataPortion) def isDefined : Boolean = this.obj.isDefined
def get : T forSome { type T } = this.obj.get
} }
object Mold extends Marshallable[Mold] { object Mold {
def apply(objectClass : Int, def apply(objectClass : Int,
obj : T forSome { type T }) : Mold = obj : T forSome { type T }) : Mold =
new Mold(objectClass, bin"") new Mold(objectClass, bin"")
def selectMold(objClass : Int, data : BitVector) : Option[Any] = { def selectMold(objClass : Int, data : BitVector) : Option[_] = {
(objClass : @switch) match { (objClass : @switch) match {
case 0x4D3 => case 0x1C =>
Weapon.codec.decode(data).toOption Some(AmmoBox.codec.decode(data))
case _ => case _ =>
None None
} }
} }
implicit val codec : Codec[Mold] = (
("objectClass" | uintL(11)) ::
("dataPortion" | bits)
).as[Mold]
} }
/** /**
@ -87,14 +93,14 @@ case class ObjectCreateMessageParent(guid : PlanetSideGUID,
* @param objectClass the code for the type of object being constructed * @param objectClass the code for the type of object being constructed
* @param guid the GUID this object will be assigned * @param guid the GUID this object will be assigned
* @param parentInfo if defined, the relationship between this object and another object (its parent) * @param parentInfo if defined, the relationship between this object and another object (its parent)
* @param data the data used to construct this type of object; * @param mold the data used to construct this type of object;
* requires further object-specific processing * requires further object-specific processing
*/ */
case class ObjectCreateMessage(streamLength : Long, case class ObjectCreateMessage(streamLength : Long,
objectClass : Int, objectClass : Int,
guid : PlanetSideGUID, guid : PlanetSideGUID,
parentInfo : Option[ObjectCreateMessageParent], parentInfo : Option[ObjectCreateMessageParent],
data : BitVector) mold : Mold)
extends PlanetSideGamePacket { extends PlanetSideGamePacket {
def opcode = GamePacketOpcode.ObjectCreateMessage def opcode = GamePacketOpcode.ObjectCreateMessage
def encode = ObjectCreateMessage.encode(this) def encode = ObjectCreateMessage.encode(this)
@ -195,12 +201,12 @@ object ObjectCreateMessage extends Marshallable[ObjectCreateMessage] {
).xmap[ObjectCreateMessage] ( ).xmap[ObjectCreateMessage] (
{ {
case len :: cls :: guid :: info :: data :: HNil => case len :: cls :: guid :: info :: data :: HNil =>
ObjectCreateMessage(len, cls, guid, info, data) ObjectCreateMessage(len, cls, guid, info, Mold(cls, data))
}, },
{ {
//the user should not have to manually supply a proper stream length, that's a restrictive requirement //the user should not have to manually supply a proper stream length, that's a restrictive requirement
case ObjectCreateMessage(_, cls, guid, info, data) => case ObjectCreateMessage(_, cls, guid, info, mold) =>
streamLen(info, data) :: cls :: guid :: info :: data :: HNil streamLen(info, mold.data) :: cls :: guid :: info :: mold.data :: HNil
} }
).as[ObjectCreateMessage] ).as[ObjectCreateMessage]
} }

View file

@ -148,22 +148,39 @@ class GamePacketTest extends Specification {
val packet = hex"18 CF 13 00 00 BC 87 00 0A F0 16 C3 43 A1 30 90 00 02 C0 40 00 08 70 43 00 68 00 6F 00 72 00 64 00 54 00 52 00 82 65 1F F5 9E 80 80 00 00 00 00 00 3F FF C0 00 00 00 20 00 00 00 20 27 03 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FC CC 10 00 03 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 90 01 90 00 00 00 00 01 00 7E C8 00 C8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 C0 00 42 C5 46 86 C7 00 00 02 A0 00 00 12 60 78 70 65 5F 77 61 72 70 5F 67 61 74 65 5F 75 73 61 67 65 92 78 70 65 5F 69 6E 73 74 61 6E 74 5F 61 63 74 69 6F 6E 92 78 70 65 5F 73 61 6E 63 74 75 61 72 79 5F 68 65 6C 70 91 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 32 8E 78 70 65 5F 66 6F 72 6D 5F 73 71 75 61 64 8E 78 70 65 5F 74 68 5F 6E 6F 6E 73 61 6E 63 8B 78 70 65 5F 74 68 5F 61 6D 6D 6F 90 78 70 65 5F 74 68 5F 66 69 72 65 6D 6F 64 65 73 8F 75 73 65 64 5F 63 68 61 69 6E 62 6C 61 64 65 9A 76 69 73 69 74 65 64 5F 62 72 6F 61 64 63 61 73 74 5F 77 61 72 70 67 61 74 65 8E 76 69 73 69 74 65 64 5F 6C 6F 63 6B 65 72 8D 75 73 65 64 5F 70 75 6E 69 73 68 65 72 88 75 73 65 64 5F 72 65 6B 8D 75 73 65 64 5F 72 65 70 65 61 74 65 72 9F 76 69 73 69 74 65 64 5F 64 65 63 6F 6E 73 74 72 75 63 74 69 6F 6E 5F 74 65 72 6D 69 6E 61 6C 8F 75 73 65 64 5F 73 75 70 70 72 65 73 73 6F 72 96 76 69 73 69 74 65 64 5F 6F 72 64 65 72 5F 74 65 72 6D 69 6E 61 6C 85 6D 61 70 31 35 85 6D 61 70 31 34 85 6D 61 70 31 32 85 6D 61 70 30 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 0A 36 13 88 04 00 40 00 00 10 00 04 00 00 4D 6E 40 10 41 00 00 00 40 00 18 08 38 1C C0 20 32 00 00 07 80 15 E1 D0 02 10 20 00 00 08 00 03 01 07 13 A8 04 06 40 00 00 10 03 20 BB 00 42 E4 00 00 01 00 0E 07 70 08 6C 80 00 06 40 01 C0 F0 01 13 90 00 00 C8 00 38 1E 40 23 32 00 00 19 00 07 03 D0 05 0E 40 00 03 20 00 E8 7B 00 A4 C8 00 00 64 00 DA 4F 80 14 E1 00 00 00 40 00 18 08 38 1F 40 20 32 00 00 0A 00 08 " val packet = hex"18 CF 13 00 00 BC 87 00 0A F0 16 C3 43 A1 30 90 00 02 C0 40 00 08 70 43 00 68 00 6F 00 72 00 64 00 54 00 52 00 82 65 1F F5 9E 80 80 00 00 00 00 00 3F FF C0 00 00 00 20 00 00 00 20 27 03 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FC CC 10 00 03 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 90 01 90 00 00 00 00 01 00 7E C8 00 C8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 C0 00 42 C5 46 86 C7 00 00 02 A0 00 00 12 60 78 70 65 5F 77 61 72 70 5F 67 61 74 65 5F 75 73 61 67 65 92 78 70 65 5F 69 6E 73 74 61 6E 74 5F 61 63 74 69 6F 6E 92 78 70 65 5F 73 61 6E 63 74 75 61 72 79 5F 68 65 6C 70 91 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 32 8E 78 70 65 5F 66 6F 72 6D 5F 73 71 75 61 64 8E 78 70 65 5F 74 68 5F 6E 6F 6E 73 61 6E 63 8B 78 70 65 5F 74 68 5F 61 6D 6D 6F 90 78 70 65 5F 74 68 5F 66 69 72 65 6D 6F 64 65 73 8F 75 73 65 64 5F 63 68 61 69 6E 62 6C 61 64 65 9A 76 69 73 69 74 65 64 5F 62 72 6F 61 64 63 61 73 74 5F 77 61 72 70 67 61 74 65 8E 76 69 73 69 74 65 64 5F 6C 6F 63 6B 65 72 8D 75 73 65 64 5F 70 75 6E 69 73 68 65 72 88 75 73 65 64 5F 72 65 6B 8D 75 73 65 64 5F 72 65 70 65 61 74 65 72 9F 76 69 73 69 74 65 64 5F 64 65 63 6F 6E 73 74 72 75 63 74 69 6F 6E 5F 74 65 72 6D 69 6E 61 6C 8F 75 73 65 64 5F 73 75 70 70 72 65 73 73 6F 72 96 76 69 73 69 74 65 64 5F 6F 72 64 65 72 5F 74 65 72 6D 69 6E 61 6C 85 6D 61 70 31 35 85 6D 61 70 31 34 85 6D 61 70 31 32 85 6D 61 70 30 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 0A 36 13 88 04 00 40 00 00 10 00 04 00 00 4D 6E 40 10 41 00 00 00 40 00 18 08 38 1C C0 20 32 00 00 07 80 15 E1 D0 02 10 20 00 00 08 00 03 01 07 13 A8 04 06 40 00 00 10 03 20 BB 00 42 E4 00 00 01 00 0E 07 70 08 6C 80 00 06 40 01 C0 F0 01 13 90 00 00 C8 00 38 1E 40 23 32 00 00 19 00 07 03 D0 05 0E 40 00 03 20 00 E8 7B 00 A4 C8 00 00 64 00 DA 4F 80 14 E1 00 00 00 40 00 18 08 38 1F 40 20 32 00 00 0A 00 08 "
val packet2 = hex"18 F8 00 00 00 BC 8C 10 90 3B 45 C6 FA 94 00 9F F0 00 00 40 00 08 C0 44 00 69 00 66 00 66 00 45" //faked data? val packet2 = hex"18 F8 00 00 00 BC 8C 10 90 3B 45 C6 FA 94 00 9F F0 00 00 40 00 08 C0 44 00 69 00 66 00 66 00 45" //faked data?
val packet2Rest = packet2.bits.drop(8 + 32 + 1 + 11 + 16) val packet2Rest = packet2.bits.drop(8 + 32 + 1 + 11 + 16)
val string_9mm = hex"18 7C000000 2580 0E0 0005 A1 C8000064000"
"decode (2)" in { "decode (2)" in {
PacketCoding.DecodePacket(packet2).require match { PacketCoding.DecodePacket(packet2).require match {
case obj @ ObjectCreateMessage(len, cls, guid, parent, rest) => case obj @ ObjectCreateMessage(len, cls, guid, parent, mold) =>
len mustEqual 248 len mustEqual 248
cls mustEqual 121 cls mustEqual 121
guid mustEqual PlanetSideGUID(2497) guid mustEqual PlanetSideGUID(2497)
parent mustEqual None parent mustEqual None
rest mustEqual packet2Rest mold.data mustEqual packet2Rest
mold.isDefined mustEqual false
case default =>
ko
}
}
"decode (9mm)" in {
PacketCoding.DecodePacket(string_9mm).require match {
case obj @ ObjectCreateMessage(len, cls, guid, parent, mold) =>
len mustEqual 124
cls mustEqual 28
guid mustEqual PlanetSideGUID(1280)
parent.isDefined mustEqual true
parent.get.guid mustEqual PlanetSideGUID(75)
parent.get.slot mustEqual 33
mold.isDefined mustEqual true
case default => case default =>
ko ko
} }
} }
"encode (2)" in { "encode (2)" in {
val msg = ObjectCreateMessage(0, 121, PlanetSideGUID(2497), None, packet2Rest) val msg = ObjectCreateMessage(0, 121, PlanetSideGUID(2497), None, Mold(121, packet2Rest))
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual packet2 pkt mustEqual packet2

View file

@ -170,7 +170,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
true, //Boosted spawn room pain field true, //Boosted spawn room pain field
true))) //Boosted generator room pain field true))) //Boosted generator room pain field
sendResponse(PacketCoding.CreateGamePacket(0, SetCurrentAvatarMessage(PlanetSideGUID(guid),0,0))) sendResponse(PacketCoding.CreateGamePacket(0, SetCurrentAvatarMessage(guid,0,0)))
import scala.concurrent.duration._ import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.ExecutionContext.Implicits.global