mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-19 18:14:44 +00:00
Packet: MultiPacketEx, CharacterRequestMessage
Rename AggregatePacket -> MultiPacketEx as it makes more sense
This commit is contained in:
parent
9a0ef28723
commit
7b82491d0e
|
|
@ -41,7 +41,7 @@ object ControlPacketOpcode extends Enumeration {
|
|||
RelatedB1,
|
||||
RelatedB2,
|
||||
RelatedB3,
|
||||
AggregatePacket, // same as MultiPacket, but with the ability to send extended length packets
|
||||
MultiPacketEx, // same as MultiPacket, but with the ability to send extended length packets
|
||||
Unknown26,
|
||||
Unknown27,
|
||||
Unknown28,
|
||||
|
|
@ -85,7 +85,7 @@ object ControlPacketOpcode extends Enumeration {
|
|||
case RelatedB1 => noDecoder(opcode)
|
||||
case RelatedB2 => noDecoder(opcode)
|
||||
case RelatedB3 => noDecoder(opcode)
|
||||
case AggregatePacket => noDecoder(opcode)
|
||||
case MultiPacketEx => control.MultiPacketEx.decode
|
||||
case Unknown26 => noDecoder(opcode)
|
||||
case Unknown27 => noDecoder(opcode)
|
||||
case Unknown28 => noDecoder(opcode)
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ object GamePacketOpcode extends Enumeration {
|
|||
UnknownMessage45,
|
||||
UnknownMessage46,
|
||||
UnknownMessage47,
|
||||
UnknownMessage48,
|
||||
CharacterRequestMessage,
|
||||
LoadMapMessage,
|
||||
|
||||
// OPCODE 50
|
||||
|
|
@ -380,7 +380,7 @@ object GamePacketOpcode extends Enumeration {
|
|||
case UnknownMessage45 => noDecoder(opcode)
|
||||
case UnknownMessage46 => noDecoder(opcode)
|
||||
case UnknownMessage47 => noDecoder(opcode)
|
||||
case UnknownMessage48 => noDecoder(opcode)
|
||||
case CharacterRequestMessage => game.CharacterRequestMessage.decode
|
||||
case LoadMapMessage => noDecoder(opcode)
|
||||
|
||||
// OPCODE 50
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
// Copyright (c) 2016 PSForever.net to present
|
||||
package net.psforever.packet.control
|
||||
|
||||
import net.psforever.packet.{ControlPacketOpcode, Marshallable, PlanetSideControlPacket}
|
||||
import scodec.{Attempt, Codec, DecodeResult, SizeBound}
|
||||
import scodec.bits._
|
||||
import scodec.codecs._
|
||||
|
||||
final case class MultiPacketEx(packets : Vector[ByteVector])
|
||||
extends PlanetSideControlPacket {
|
||||
type Packet = MultiPacketEx
|
||||
def opcode = ControlPacketOpcode.MultiPacketEx
|
||||
def encode = MultiPacketEx.encode(this)
|
||||
}
|
||||
|
||||
object MultiPacketEx extends Marshallable[MultiPacketEx] {
|
||||
val ffFound: Codec[Boolean] = new Codec[Boolean] {
|
||||
def sizeBound = SizeBound.exact(0)
|
||||
def encode(b: Boolean) =
|
||||
if(b)
|
||||
Attempt.successful(hex"ff".bits)
|
||||
else
|
||||
Attempt.successful(bin"")
|
||||
def decode(b: BitVector) = {
|
||||
if (b.length >= 8 && b.take(8) == hex"ff".bits)
|
||||
Attempt.successful(DecodeResult(true, b.drop(8)))
|
||||
else
|
||||
Attempt.successful(DecodeResult(false, b))
|
||||
}
|
||||
|
||||
override def toString = "bitsRemaining"
|
||||
}
|
||||
|
||||
val twoffFound: Codec[Boolean] = new Codec[Boolean] {
|
||||
def sizeBound = SizeBound.exact(0)
|
||||
def encode(b: Boolean) =
|
||||
if(b)
|
||||
Attempt.successful(hex"ffff".bits)
|
||||
else
|
||||
Attempt.successful(bin"")
|
||||
def decode(b: BitVector) = {
|
||||
if (b.length >= 16 && b.take(16) == hex"ffff".bits)
|
||||
Attempt.successful(DecodeResult(true, b.drop(16)))
|
||||
else
|
||||
Attempt.successful(DecodeResult(false, b))
|
||||
}
|
||||
|
||||
override def toString = "bitsRemaining"
|
||||
}
|
||||
|
||||
val sizeCodec = either(ffFound, uint8L,
|
||||
either(twoffFound, uint16L, uint32L).xmap[Long](
|
||||
(a : Either[Int, Long]) => a.fold[Long](a => a, a => a),
|
||||
(a : Long) =>
|
||||
if(a < 0xffff) Left(a.toInt) else Right(a)
|
||||
)
|
||||
).xmap[Long](
|
||||
(a : Either[Int, Long]) => a.fold[Long](a => a, a => a),
|
||||
(a : Long) =>
|
||||
if(a < 0xff) Left(a.toInt) else Right(a)
|
||||
)
|
||||
|
||||
implicit val codec : Codec[MultiPacketEx] = (
|
||||
("packets" | vector(variableSizeBytesLong(sizeCodec, bytes)))
|
||||
).as[MultiPacketEx]
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright (c) 2016 PSForever.net to present
|
||||
package net.psforever.packet.game
|
||||
|
||||
import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket}
|
||||
import scodec.Codec
|
||||
import scodec.codecs._
|
||||
|
||||
/**
|
||||
* Is sent by the PlanetSide client when selecting a character to play from the character selection
|
||||
* menu.
|
||||
*/
|
||||
final case class CharacterRequestMessage(unk : Long, unk2 : Long)
|
||||
extends PlanetSideGamePacket {
|
||||
type Packet = CharacterRequestMessage
|
||||
def opcode = GamePacketOpcode.CharacterRequestMessage
|
||||
def encode = CharacterRequestMessage.encode(this)
|
||||
}
|
||||
|
||||
object CharacterRequestMessage extends Marshallable[CharacterRequestMessage] {
|
||||
implicit val codec : Codec[CharacterRequestMessage] = (
|
||||
("unk1" | uint32L) ::
|
||||
("unk2" | uint32L)
|
||||
).as[CharacterRequestMessage]
|
||||
}
|
||||
|
|
@ -129,5 +129,45 @@ class ControlPacketTest extends Specification {
|
|||
PacketCoding.EncodePacket(SlottedMetaPacket(0, 0x10000, hex"00")).require must throwA[IllegalArgumentException]
|
||||
}
|
||||
}
|
||||
|
||||
"MultiPacketEx" should {
|
||||
val strings = Vector(
|
||||
hex"00",
|
||||
hex"01 41",
|
||||
hex"01 41" ++ hex"02 4142",
|
||||
hex"fe" ++ ByteVector.fill(0xfe)(0x41),
|
||||
hex"ffff00" ++ ByteVector.fill(0xff)(0x41),
|
||||
hex"ff0001" ++ ByteVector.fill(0x100)(0x41),
|
||||
hex"ff ffff ffff 0000" ++ ByteVector.fill(0x0000ffff)(0x41),
|
||||
hex"ff ffff 0000 0100" ++ ByteVector.fill(0x00010000)(0x41)
|
||||
)
|
||||
|
||||
val packets = Vector(
|
||||
MultiPacketEx(Vector(ByteVector.empty)),
|
||||
MultiPacketEx(Vector(hex"41")),
|
||||
MultiPacketEx(Vector(hex"41", hex"4142")),
|
||||
MultiPacketEx(Vector(ByteVector.fill(0xfe)(0x41))),
|
||||
MultiPacketEx(Vector(ByteVector.fill(0xff)(0x41))),
|
||||
MultiPacketEx(Vector(ByteVector.fill(0x100)(0x41))),
|
||||
MultiPacketEx(Vector(ByteVector.fill(0x0000ffff)(0x41))),
|
||||
MultiPacketEx(Vector(ByteVector.fill(0x00010000)(0x41)))
|
||||
)
|
||||
|
||||
"decode" in {
|
||||
for(i <- strings.indices) {
|
||||
MultiPacketEx.decode(strings{i}.bits).require.value mustEqual packets{i}
|
||||
}
|
||||
|
||||
true mustEqual true
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
for(i <- packets.indices) {
|
||||
MultiPacketEx.encode(packets{i}).require.toByteVector mustEqual strings{i}
|
||||
}
|
||||
|
||||
true mustEqual true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -78,6 +78,15 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
handlePkt(v)
|
||||
}
|
||||
}
|
||||
case MultiPacketEx(packets) =>
|
||||
packets.foreach { pkt =>
|
||||
PacketCoding.DecodePacket(pkt) match {
|
||||
case Failure(e) =>
|
||||
log.error(s"Failed to decode inner packet of MultiPacketEx: $e")
|
||||
case Successful(v) =>
|
||||
handlePkt(v)
|
||||
}
|
||||
}
|
||||
case default =>
|
||||
log.debug(s"Unhandled ControlPacket $default")
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue