Packet: ObjectCreateMessage

Still tons of decoding to due (it a streaming type). More hardcore RE
required.
This commit is contained in:
Chord 2016-06-04 19:14:05 -04:00
parent c83132f21b
commit 78ace06516
2 changed files with 56 additions and 1 deletions

View file

@ -113,7 +113,7 @@ object PacketHelpers {
// when the first bit of the byte is set, the size can be between [0, 127].
// otherwise, it is between [128, 32767] and two bytes are used for encoding
// The magic in this is next level
private def encodedStringSize : Codec[Int] = either(bool, uint(15), uint(7)).
def encodedStringSize : Codec[Int] = either(bool, uint(15), uint(7)).
xmap[Int](
(a : Either[Int, Int]) => a.fold[Int](a => a, a => a),
(a : Int) =>

View file

@ -0,0 +1,55 @@
package net.psforever.packet.game
import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket}
import scodec.bits._
import scodec.{Attempt, Codec, Err}
import scodec.codecs._
import shapeless._
case class ObjectCreateMessageParent(guid : Int, slot : Int)
case class ObjectCreateMessage(streamLength : Long,
objectClass : Int,
guid : Int,
parentInfo : Option[ObjectCreateMessageParent])
extends PlanetSideGamePacket {
def opcode = GamePacketOpcode.ObjectCreateMessage
def encode = ObjectCreateMessage.encode(this)
}
object ObjectCreateMessage extends Marshallable[ObjectCreateMessage] {
type Pattern = Int :: Int :: Option[ObjectCreateMessageParent] :: HNil
type ChoicePattern = Either[Pattern, Pattern]
val noParent : Codec[Pattern] = (("object_class" | uintL(0xb)) ::
("guid" | uint16L)).xmap[Pattern]( {
case cls :: guid :: HNil => cls :: guid :: None :: HNil
}, {
case cls :: guid :: None :: HNil => cls :: guid :: HNil
})
val parent : Codec[Pattern] = (("parent_guid" | uint16L) ::
("object_class" | uintL(0xb)) ::
("guid" | uint16L) ::
("parent_slot_index" | PacketHelpers.encodedStringSize)).xmap[Pattern]( {
case pguid :: cls :: guid :: slot :: HNil =>
cls :: guid :: Some(ObjectCreateMessageParent(pguid, slot)) :: HNil
}, {
case cls :: guid :: Some(ObjectCreateMessageParent(pguid, slot)) :: HNil =>
pguid :: cls :: guid :: slot :: HNil
})
implicit val codec : Codec[ObjectCreateMessage] = (
("stream_length" | uint32L) :: either(bool, parent, noParent).exmap[Pattern]( {
case Left(a :: b :: Some(c) :: HNil) => Attempt.successful(a :: b :: Some(c) :: HNil)
case Right(a :: b :: None :: HNil) => Attempt.successful(a :: b :: None :: HNil)
// failure cases
case Left(a :: b :: None :: HNil) => Attempt.failure(Err("expected parent structure"))
case Right(a :: b :: Some(c) :: HNil) => Attempt.failure(Err("got unexpected parent structure"))
}, {
case a :: b :: Some(c) :: HNil => Attempt.successful(Left(a :: b :: Some(c) :: HNil))
case a :: b :: None :: HNil => Attempt.successful(Right(a :: b :: None :: HNil))
})
).as[ObjectCreateMessage]
}