mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-19 18:44:45 +00:00
Merge pull request #1095 from Fate-JH/outfit-request
Packet: OutfitRequest
This commit is contained in:
commit
006dd201ba
|
|
@ -591,6 +591,8 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
case packet: HitHint =>
|
||||
sessionFuncs.handleHitHint(packet)
|
||||
|
||||
case _: OutfitRequest => ()
|
||||
|
||||
case pkt =>
|
||||
log.warning(s"Unhandled GamePacket $pkt")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -470,7 +470,7 @@ object GamePacketOpcode extends Enumeration {
|
|||
case 0x8b => noDecoder(UnknownMessage139)
|
||||
case 0x8c => noDecoder(OutfitMembershipRequest)
|
||||
case 0x8d => noDecoder(OutfitMembershipResponse)
|
||||
case 0x8e => noDecoder(OutfitRequest)
|
||||
case 0x8e => game.OutfitRequest.decode
|
||||
case 0x8f => noDecoder(OutfitEvent)
|
||||
|
||||
// OPCODES 0x90-9f
|
||||
|
|
|
|||
177
src/main/scala/net/psforever/packet/game/OutfitRequest.scala
Normal file
177
src/main/scala/net/psforever/packet/game/OutfitRequest.scala
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
// Copyright (c) 2023 PSForever
|
||||
package net.psforever.packet.game
|
||||
|
||||
import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket}
|
||||
import scodec.{Attempt, Codec, Err}
|
||||
import scodec.bits.ByteVector
|
||||
import scodec.codecs._
|
||||
import shapeless.{::, HNil}
|
||||
|
||||
/**
|
||||
* na
|
||||
*/
|
||||
abstract class OutfitRequestForm(val code: Int)
|
||||
|
||||
object OutfitRequestForm {
|
||||
/**
|
||||
* na
|
||||
* @param str na
|
||||
*/
|
||||
final case class Unk0(str: String) extends OutfitRequestForm(code = 0)
|
||||
/**
|
||||
* na
|
||||
* @param list na
|
||||
*/
|
||||
final case class Unk1(list: List[Option[String]]) extends OutfitRequestForm(code = 1)
|
||||
/**
|
||||
* na
|
||||
* @param unk na
|
||||
*/
|
||||
final case class Unk2(unk: Int) extends OutfitRequestForm(code = 2)
|
||||
/**
|
||||
* na
|
||||
* @param unk na
|
||||
*/
|
||||
final case class Unk3(unk: Boolean) extends OutfitRequestForm(code = 3)
|
||||
/**
|
||||
* na
|
||||
* @param unk na
|
||||
*/
|
||||
final case class Unk4(unk: Boolean) extends OutfitRequestForm(code = 4)
|
||||
/**
|
||||
* na
|
||||
* @param unk na
|
||||
*/
|
||||
final case class Fail(unk: ByteVector) extends OutfitRequestForm(code = -1)
|
||||
}
|
||||
|
||||
/**
|
||||
* na
|
||||
* @param id na
|
||||
* @param info na
|
||||
*/
|
||||
final case class OutfitRequest(id: Long, info: OutfitRequestForm)
|
||||
extends PlanetSideGamePacket {
|
||||
type Packet = OrbitalStrikeWaypointMessage
|
||||
def opcode = GamePacketOpcode.OutfitRequest
|
||||
def encode = OutfitRequest.encode(this)
|
||||
}
|
||||
|
||||
object OutfitRequest extends Marshallable[OutfitRequest] {
|
||||
/**
|
||||
* na
|
||||
*/
|
||||
private val unk0Codec: Codec[OutfitRequestForm] = PacketHelpers.encodedWideStringAligned(adjustment = 5).hlist
|
||||
.xmap[OutfitRequestForm] (
|
||||
{
|
||||
case value :: HNil => OutfitRequestForm.Unk0(value)
|
||||
},
|
||||
{
|
||||
case OutfitRequestForm.Unk0(value) => value :: HNil
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* na
|
||||
*/
|
||||
private val unk1Codec: Codec[OutfitRequestForm] = unk1PaddedEntryCodec(len = 8, pad = 5).xmap[OutfitRequestForm] (
|
||||
list => OutfitRequestForm.Unk1(list),
|
||||
{
|
||||
case OutfitRequestForm.Unk1(list) => list
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* na
|
||||
*/
|
||||
private def unk1PaddedEntryCodec(len: Int, pad: Int): Codec[List[Option[String]]] =
|
||||
{
|
||||
val nextPad = if (pad == 0) 7 else pad - 1
|
||||
optional(bool, PacketHelpers.encodedWideStringAligned(nextPad)) >>:~ { strOpt =>
|
||||
(strOpt match {
|
||||
case None if len > 1 => unk1PaddedEntryCodec(len - 1, nextPad)
|
||||
case Some(_) if len > 1 => unk1PaddedEntryCodec(len - 1, pad = 8)
|
||||
case _ => PacketHelpers.listOfNSized(size = 0L, optional(bool, PacketHelpers.encodedWideString))
|
||||
}).hlist
|
||||
}
|
||||
}.xmap[List[Option[String]]](
|
||||
{
|
||||
case head :: tail :: HNil => head +: tail
|
||||
},
|
||||
list => list.head :: list.tail :: HNil
|
||||
)
|
||||
|
||||
/**
|
||||
* na
|
||||
*/
|
||||
private val unk2Codec: Codec[OutfitRequestForm] = uint8.hlist.xmap[OutfitRequestForm] (
|
||||
{
|
||||
case value :: HNil => OutfitRequestForm.Unk2(value)
|
||||
},
|
||||
{
|
||||
case OutfitRequestForm.Unk2(value) => value :: HNil
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* na
|
||||
*/
|
||||
private val unk3Codec: Codec[OutfitRequestForm] = bool.hlist.xmap[OutfitRequestForm] (
|
||||
{
|
||||
case value :: HNil => OutfitRequestForm.Unk3(value)
|
||||
},
|
||||
{
|
||||
case OutfitRequestForm.Unk3(value) => value :: HNil
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* na
|
||||
*/
|
||||
private val unk4Codec: Codec[OutfitRequestForm] = bool.hlist.xmap[OutfitRequestForm] (
|
||||
{
|
||||
case value :: HNil => OutfitRequestForm.Unk4(value)
|
||||
},
|
||||
{
|
||||
case OutfitRequestForm.Unk4(value) => value :: HNil
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* na
|
||||
*/
|
||||
private def failCodec(code: Int): Codec[OutfitRequestForm] = conditional(included = false, bool).exmap[OutfitRequestForm](
|
||||
_ => Attempt.Failure(Err(s"can not decode $code-type info - what is this thing?")),
|
||||
_ => Attempt.Failure(Err(s"can not encode $code-type info - no such thing"))
|
||||
)
|
||||
|
||||
/**
|
||||
* na
|
||||
*/
|
||||
private def infoCodec(code: Int): Codec[OutfitRequestForm] = {
|
||||
code match {
|
||||
case 0 => unk0Codec
|
||||
case 1 => unk1Codec
|
||||
case 2 => unk2Codec
|
||||
case 3 => unk3Codec
|
||||
case 4 => unk4Codec
|
||||
case _ => failCodec(code)
|
||||
}
|
||||
}
|
||||
|
||||
implicit val codec: Codec[OutfitRequest] = (
|
||||
uint(bits = 3) >>:~ { code =>
|
||||
("id" | uint32L) ::
|
||||
("info" | infoCodec(code))
|
||||
}
|
||||
).xmap[OutfitRequest](
|
||||
{
|
||||
case _:: id:: info :: HNil =>
|
||||
OutfitRequest(id, info)
|
||||
},
|
||||
{
|
||||
case OutfitRequest(id, info) =>
|
||||
info.code :: id :: info :: HNil
|
||||
}
|
||||
)
|
||||
}
|
||||
103
src/test/scala/game/OutfitRequesTest.scala
Normal file
103
src/test/scala/game/OutfitRequesTest.scala
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
// Copyright (c) 2023 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class OutfitRequestTest extends Specification {
|
||||
val string0 = hex"8e02b54f40401780560061006e00750020006f0075007400660069007400200066006f0072002000740068006500200070006c0061006e00650074007300690064006500200066006f00720065007600650072002000700072006f006a006500630074002100200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002d00660069006e00640020006f007500740020006d006f00720065002000610062006f0075007400200074006800650020005000530045004d0055002000700072006f006a0065006300740020006100740020005000530066006f00720065007600650072002e006e0065007400"
|
||||
val string2 = hex"8e22b54f405800c000c000c000c000c000c000c000"
|
||||
val string4 = hex"8e42b54f404aa0" //faked by modifying the previous example
|
||||
val string6 = hex"8e649e822010"
|
||||
val string8 = hex"8e81b2cf4050"
|
||||
|
||||
"decode 0" in {
|
||||
PacketCoding.decodePacket(string0).require match {
|
||||
case OutfitRequest(id, OutfitRequestForm.Unk0(str)) =>
|
||||
id mustEqual 41593365L
|
||||
str mustEqual "Vanu outfit for the planetside forever project! -find out more about the PSEMU project at PSforever.net"
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode 1" in {
|
||||
PacketCoding.decodePacket(string2).require match {
|
||||
case OutfitRequest(id, OutfitRequestForm.Unk1(list)) =>
|
||||
id mustEqual 41593365L
|
||||
list mustEqual List(Some(""), Some(""), Some(""), Some(""), Some(""), Some(""), Some(""), Some(""))
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode 2 (fake)" in {
|
||||
PacketCoding.decodePacket(string4).require match {
|
||||
case OutfitRequest(id, OutfitRequestForm.Unk2(value)) =>
|
||||
id mustEqual 41593365L
|
||||
value mustEqual 85
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode 3" in {
|
||||
PacketCoding.decodePacket(string6).require match {
|
||||
case OutfitRequest(id, OutfitRequestForm.Unk3(value)) =>
|
||||
id mustEqual 1176612L
|
||||
value mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode 4" in {
|
||||
PacketCoding.decodePacket(string8).require match {
|
||||
case OutfitRequest(id, OutfitRequestForm.Unk4(value)) =>
|
||||
id mustEqual 41588237L
|
||||
value mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode 0" in {
|
||||
val msg = OutfitRequest(41593365L, OutfitRequestForm.Unk0(
|
||||
"Vanu outfit for the planetside forever project! -find out more about the PSEMU project at PSforever.net"
|
||||
))
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string0
|
||||
}
|
||||
|
||||
"encode 1" in {
|
||||
val msg = OutfitRequest(41593365L, OutfitRequestForm.Unk1(List(Some(""), Some(""), Some(""), Some(""), Some(""), Some(""), Some(""), Some(""))))
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string2
|
||||
}
|
||||
|
||||
"encode 2 (fake)" in {
|
||||
val msg = OutfitRequest(41593365L, OutfitRequestForm.Unk2(85))
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string4
|
||||
}
|
||||
|
||||
"encode 3" in {
|
||||
val msg = OutfitRequest(1176612L, OutfitRequestForm.Unk3(true))
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string6
|
||||
}
|
||||
|
||||
"encode 4" in {
|
||||
val msg = OutfitRequest(41588237L, OutfitRequestForm.Unk4(true))
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string8
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue