mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-19 18:44:45 +00:00
OutfitListEvent ListElementOutfit decoded
This commit is contained in:
parent
308ea20dee
commit
d450a1b6e5
|
|
@ -38,8 +38,8 @@ object OutfitEventAction {
|
|||
|
||||
final case class OutfitInfo(
|
||||
outfit_name: String,
|
||||
unk6: Long,
|
||||
unk7: Long,
|
||||
outfit_points1: Long,
|
||||
outfit_points2: Long, // same as outfit_points1
|
||||
member_count: Int,
|
||||
unk9: Int,
|
||||
outfit_rank_names: OutfitRankNames,
|
||||
|
|
@ -276,31 +276,6 @@ object OutfitEvent extends Marshallable[OutfitEvent] {
|
|||
val unk6: RequestType.Value = Value(6)
|
||||
val unk7: RequestType.Value = Value(7)
|
||||
|
||||
/*
|
||||
|
||||
OutfitEvent(Unk0, ValidPlanetSideGUID(18361), Unk0(OutfitInfo(0, 0, The Black Ravens, 338420223, 338420223, 433, 0, OutfitRankNames(Corporal (No Ventrilo), Sergeant - SGT, Advance Medical, , Master Sgt - MSG, Captain, Trusted Officer, OutFit Leader), TBR website..... http://trravens.darkbb.com ventrilo info: evolve.typefrag.com port: 45694 (vent pw dotaftw) Channel PW: zeroenigma : if you guys wants to contact me, my email is zero_overkill99@yahoo.com, ValidPlanetSideGUID(32787), 0, 0, 0, 1133571390, 0, 0, 0, 0)))
|
||||
OutfitEvent(Unk2, ValidPlanetSideGUID(18361), Unk2(OutfitInfo(0, 0, The Black Ravens, 338420486, 338420486, 433, 0, OutfitRankNames(Corporal (No Ventrilo), Sergeant - SGT, Advance Medical, , Master Sgt - MSG, Captain, Trusted Officer, OutFit Leader), TBR website..... http://trravens.darkbb.com ventrilo info: evolve.typefrag.com port: 45694 (vent pw dotaftw) Channel PW: zeroenigma : if you guys wants to contact me, my email is zero_overkill99@yahoo.com, ValidPlanetSideGUID(32787), 0, 0, 0, 1133571390, 0, 0, 0, 0)))
|
||||
|
||||
|
||||
unk3 -- #66162 PSCap-2016-02-28_02-58-10-PM.txt
|
||||
|
||||
MP(
|
||||
SMP(
|
||||
MPEx(
|
||||
OutfitMembershipResponse,
|
||||
OutfitEvent,
|
||||
SquadMemberEvent
|
||||
)
|
||||
),
|
||||
SMP(
|
||||
MPEx(
|
||||
PlanetsideAttributeMessage x 3 + PlanetsideStringAttributeMessage
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
*/
|
||||
|
||||
implicit val codec: Codec[Type] = PacketHelpers.createEnumerationCodec(this, uintL(3))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,19 +3,14 @@ package net.psforever.packet.game
|
|||
|
||||
import net.psforever.packet.GamePacketOpcode.Type
|
||||
import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket}
|
||||
import scodec.bits.BitVector
|
||||
import scodec.{Attempt, Codec, Err}
|
||||
import scodec.bits.{BitVector, ByteVector}
|
||||
import scodec.codecs._
|
||||
import scodec.{Attempt, Codec}
|
||||
|
||||
// 98 5ec300000d01a020004000001 12056002e0053002e0053002e0055002e004400 845400680069006f009 85ee300001e2b 858000800000110041002e0027002e0041002e0027002e00 8448006900720075009 84003200005a540000060000011a0530065006300720065007400200043006800690065006600730085530069006c00610073009840a32000001953476fe0c00011c041007a0075007200650020005400770069006c006900670068007400874600720061006e0063006b006f009840c3200000d3a4c000c00000106030002e006f0085410074006c0061007300984183200011d9296000c0000011e0570061007200720069006f007200270073002000430072006500650064008653006500760061006b00690098442320001bf40e000080000013203100330033003700740068002000410072006d006f0072006500640020004400690076006900730069006f006e002d004b008548006f0073002d004b009844c320001b3d2c200060000012a03300330031007300740020004d0069006e006e00650073006f0074006100200054007200690062006500864d006100670069002d0045009846c3200009e206c00040000010c04100720065006100350031008942006c00610063
|
||||
import shapeless.{::, HNil}
|
||||
|
||||
final case class OutfitListEvent(
|
||||
outfit_score: Long,
|
||||
unk1: Long,
|
||||
unk2: Long,
|
||||
unk3: Int,
|
||||
outfit_name: String,
|
||||
outfit_leader: String,
|
||||
request_type: OutfitListEvent.RequestType.Type,
|
||||
action: OutfitListEventAction
|
||||
) extends PlanetSideGamePacket {
|
||||
type Packet = OutfitListEvent
|
||||
|
||||
|
|
@ -23,13 +18,144 @@ final case class OutfitListEvent(
|
|||
|
||||
def encode: Attempt[BitVector] = OutfitListEvent.encode(this)
|
||||
}
|
||||
object OutfitListEvent extends Marshallable[OutfitListEvent] {
|
||||
implicit val codec: Codec[OutfitListEvent] = (
|
||||
("outfit_score" | uint32) ::
|
||||
|
||||
abstract class OutfitListEventAction(val code: Int)
|
||||
|
||||
object OutfitListEventAction {
|
||||
|
||||
final case class ListElementOutfit(
|
||||
outfit_id: Long,
|
||||
points: Long,
|
||||
members: Long,
|
||||
outfit_name: String,
|
||||
outfit_leader: String,
|
||||
) extends OutfitListEventAction(code = 2)
|
||||
|
||||
/*
|
||||
TODO: Check packet when bundle packet has been implemented (packet containing OutfitListEvent packets back to back)
|
||||
For now it seems like there is no valid packet captured
|
||||
*/
|
||||
final case class Unk3(
|
||||
unk1: Long,
|
||||
data: ByteVector
|
||||
) extends OutfitListEventAction(code = 3)
|
||||
|
||||
final case class Unknown(badCode: Int, data: BitVector) extends OutfitListEventAction(badCode)
|
||||
|
||||
/**
|
||||
* The `Codec`s used to transform the input stream into the context of a specific action
|
||||
* and extract the field data from that stream.
|
||||
*/
|
||||
object Codecs {
|
||||
private val everFailCondition = conditional(included = false, bool)
|
||||
|
||||
val ListElementOutfitCodec: Codec[ListElementOutfit] = (
|
||||
("unk1" | uint32L) ::
|
||||
("unk2" | uint32L) ::
|
||||
("unk3" | uint(3)) ::
|
||||
("outfit_name" | PacketHelpers.encodedWideStringAligned(5)) ::
|
||||
("outfit_leader" | PacketHelpers.encodedWideString)
|
||||
).as[OutfitListEvent]
|
||||
("points" | uint32L) ::
|
||||
("members" | uint32L) ::
|
||||
("outfit_name" | PacketHelpers.encodedWideStringAligned(5)) ::
|
||||
("outfit_leader" | PacketHelpers.encodedWideString)
|
||||
).xmap[ListElementOutfit](
|
||||
{
|
||||
case u1 :: points :: members :: outfit_name :: outfit_leader :: HNil =>
|
||||
ListElementOutfit(u1, points, members, outfit_name, outfit_leader)
|
||||
},
|
||||
{
|
||||
case ListElementOutfit(u1, points, members, outfit_name, outfit_leader) =>
|
||||
u1 :: points :: members :: outfit_name :: outfit_leader :: HNil
|
||||
}
|
||||
)
|
||||
|
||||
val Unk3Codec: Codec[Unk3] = (
|
||||
("unk1" | uint32L) ::
|
||||
("data" | bytes)
|
||||
).xmap[Unk3](
|
||||
{
|
||||
case u1 :: data :: HNil =>
|
||||
Unk3(u1, data)
|
||||
},
|
||||
{
|
||||
case Unk3(u1, data) =>
|
||||
u1 :: data :: HNil
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* A common form for known action code indexes with an unknown purpose and transformation is an "Unknown" object.
|
||||
*
|
||||
* @param action the action behavior code
|
||||
* @return a transformation between the action code and the unknown bit data
|
||||
*/
|
||||
def unknownCodec(action: Int): Codec[Unknown] =
|
||||
bits.xmap[Unknown](
|
||||
data => Unknown(action, data),
|
||||
{
|
||||
case Unknown(_, data) => data
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* The action code was completely unanticipated!
|
||||
*
|
||||
* @param action the action behavior code
|
||||
* @return nothing; always fail
|
||||
*/
|
||||
def failureCodec(action: Int): Codec[OutfitListEventAction] =
|
||||
everFailCondition.exmap[OutfitListEventAction](
|
||||
_ => Attempt.failure(Err(s"can not match a codec pattern for decoding $action")),
|
||||
_ => Attempt.failure(Err(s"can not match a codec pattern for encoding $action"))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object OutfitListEvent extends Marshallable[OutfitListEvent] {
|
||||
import shapeless.{::, HNil}
|
||||
|
||||
object RequestType extends Enumeration {
|
||||
type Type = Value
|
||||
|
||||
val Unk0: RequestType.Value = Value(0)
|
||||
val Unk1: RequestType.Value = Value(1)
|
||||
val ListElementOutfit: RequestType.Value = Value(2)
|
||||
val Unk3: RequestType.Value = Value(3)
|
||||
val Unk4: RequestType.Value = Value(4)
|
||||
val Unk5: RequestType.Value = Value(5)
|
||||
val unk6: RequestType.Value = Value(6)
|
||||
val unk7: RequestType.Value = Value(7)
|
||||
|
||||
implicit val codec: Codec[Type] = PacketHelpers.createEnumerationCodec(this, uintL(3))
|
||||
}
|
||||
|
||||
private def selectFromType(code: Int): Codec[OutfitListEventAction] = {
|
||||
import OutfitListEventAction.Codecs._
|
||||
import scala.annotation.switch
|
||||
|
||||
((code: @switch) match {
|
||||
case 0 => unknownCodec(action = code)
|
||||
case 1 => unknownCodec(action = code)
|
||||
case 2 => ListElementOutfitCodec
|
||||
case 3 => Unk3Codec // indicated in code
|
||||
case 4 => unknownCodec(action = code)
|
||||
case 5 => unknownCodec(action = code)
|
||||
case 6 => unknownCodec(action = code)
|
||||
case 7 => unknownCodec(action = code)
|
||||
|
||||
case _ => failureCodec(code)
|
||||
}).asInstanceOf[Codec[OutfitListEventAction]]
|
||||
}
|
||||
|
||||
implicit val codec: Codec[OutfitListEvent] = (
|
||||
("request_type" | RequestType.codec) >>:~ { request_type =>
|
||||
("action" | selectFromType(request_type.id)).hlist
|
||||
}
|
||||
).xmap[OutfitListEvent](
|
||||
{
|
||||
case request_type :: action :: HNil =>
|
||||
OutfitListEvent(request_type, action)
|
||||
},
|
||||
{
|
||||
case OutfitListEvent(request_type, action) =>
|
||||
request_type :: action :: HNil
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ object OutfitRequest extends Marshallable[OutfitRequest] {
|
|||
val Rank: RequestType.Value = Value(1)
|
||||
val Unk2: RequestType.Value = Value(2)
|
||||
val Detail: RequestType.Value = Value(3)
|
||||
val List: RequestType.Value = Value(4)
|
||||
val List: RequestType.Value = Value(4) // sent by client if menu is either open (true) or closed (false)
|
||||
|
||||
implicit val codec: Codec[Type] = PacketHelpers.createEnumerationCodec(this, uintL(3))
|
||||
}
|
||||
|
|
@ -175,7 +175,7 @@ object OutfitRequest extends Marshallable[OutfitRequest] {
|
|||
}
|
||||
).xmap[OutfitRequest](
|
||||
{
|
||||
case _:: id:: action :: HNil =>
|
||||
case _ :: id:: action :: HNil =>
|
||||
OutfitRequest(id, action)
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -58,8 +58,8 @@ class OutfitEventTest extends Specification {
|
|||
action mustEqual Unk0(
|
||||
OutfitInfo(
|
||||
outfit_name = "Black Armored Reapers",
|
||||
unk6 = 223190045,
|
||||
unk7 = 223190045,
|
||||
outfit_points1 = 223190045,
|
||||
outfit_points2 = 223190045,
|
||||
member_count = 171,
|
||||
unk9 = 0,
|
||||
OutfitRankNames("Dog Meat","Russian","","","Squad Leaders","Acting Commanders","Reapers",""),
|
||||
|
|
@ -87,8 +87,8 @@ class OutfitEventTest extends Specification {
|
|||
Unk0(
|
||||
OutfitInfo(
|
||||
outfit_name = "Black Armored Reapers",
|
||||
unk6 = 223190045,
|
||||
unk7 = 223190045,
|
||||
outfit_points1 = 223190045,
|
||||
outfit_points2 = 223190045,
|
||||
member_count = 171,
|
||||
unk9 = 0,
|
||||
OutfitRankNames("Dog Meat","Russian","","","Squad Leaders","Acting Commanders","Reapers",""),
|
||||
|
|
@ -145,8 +145,8 @@ class OutfitEventTest extends Specification {
|
|||
outfit_guid mustEqual 2147418113L
|
||||
action mustEqual Unk2(OutfitInfo(
|
||||
outfit_name = "PlanetSide_Forever_Vanu",
|
||||
unk6 = 0,
|
||||
unk7 = 0,
|
||||
outfit_points1 = 0,
|
||||
outfit_points2 = 0,
|
||||
member_count = 1,
|
||||
unk9 = 0,
|
||||
OutfitRankNames("","","","","","","",""),
|
||||
|
|
@ -173,8 +173,8 @@ class OutfitEventTest extends Specification {
|
|||
Unk2(
|
||||
OutfitInfo(
|
||||
outfit_name = "PlanetSide_Forever_Vanu",
|
||||
unk6 = 0,
|
||||
unk7 = 0,
|
||||
outfit_points1 = 0,
|
||||
outfit_points2 = 0,
|
||||
member_count = 1,
|
||||
unk9 = 0,
|
||||
OutfitRankNames("","","","","","","",""),
|
||||
|
|
|
|||
|
|
@ -2,29 +2,30 @@
|
|||
package game
|
||||
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.packet.game.OutfitListEvent
|
||||
import net.psforever.packet.game.OutfitListEvent.RequestType
|
||||
import net.psforever.packet.game.OutfitListEventAction.ListElementOutfit
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits.ByteVector
|
||||
|
||||
class OutfitListEventTest extends Specification {
|
||||
val unk0_ABC: ByteVector = ByteVector.fromValidHex("98 5e83a000 0000 e180 0080 0000 11404e0069006700680074004c006f00720064007300 854e005900430061007400")
|
||||
val unk0_DEF: ByteVector = ByteVector.fromValidHex("98 4ec28100 151a 6280 0340 0000 11a0490052004f004e004600490053005400200043006c0061006e00 8654006f006c006a00")
|
||||
val unk1_ABC: ByteVector = ByteVector.fromValidHex("98 4723c000 02aa 81e0 0220 0000 11006900470061006d00650073002d004500 906900670061006d006500730043005400460057006800610063006b002d004500")
|
||||
val unk2_ABC: ByteVector = ByteVector.fromValidHex("98 49a3c000 116d a4e0 0040 0000 11a042006c006f006f00640020006f0066002000560061006e007500 864b00610072006e002d004500")
|
||||
val unk3_ABC: ByteVector = ByteVector.fromValidHex("98 49c3c000 0df5 87c0 0140 0000 11a054006800650020004e00650076006500720068006f006f006400 8e6f00460058006f00530074006f006e0065004d0061006e002d004700")
|
||||
val unk4_ABC: ByteVector = ByteVector.fromValidHex("98 4c03c000 0240 6040 0060 0000 1220540068006500200042006c00610063006b0020004b006e0069006700680074007300 874400720061007a00760065006e00")
|
||||
val unk5_ABC: ByteVector = ByteVector.fromValidHex("98 5383c000 14b7 09a0 00c0 0000 10a03e005400760053003c00 89430061007000650062006f00610074007300")
|
||||
val unk6_ABC: ByteVector = ByteVector.fromValidHex("98 5b03c000 035d 6700 0040 0000 11404c006f0073007400200043006100750073006500 895a00650072006f004b00650077006c006c00")
|
||||
val unk7_ABC: ByteVector = ByteVector.fromValidHex("98 4043e000 19fb 8261 6140 0000 11e0540068006500200042006c00610063006b00200054006f00770065007200 874b00720075007000680065007800")
|
||||
val unk8_ABC: ByteVector = ByteVector.fromValidHex("98 4a03e000 17e2") // broken, limit of SMP
|
||||
val unk0_ABC: ByteVector = ByteVector.fromValidHex("98 5 e83a0000 000e1800 0800000 11404e0069006700680074004c006f00720064007300 854e005900430061007400")
|
||||
val unk0_DEF: ByteVector = ByteVector.fromValidHex("98 4 ec281001 51a62800 3400000 11a0490052004f004e004600490053005400200043006c0061006e00 8654006f006c006a00")
|
||||
val unk1_ABC: ByteVector = ByteVector.fromValidHex("98 4 723c0000 2aa81e00 2200000 11006900470061006d00650073002d004500 906900670061006d006500730043005400460057006800610063006b002d004500")
|
||||
val unk2_ABC: ByteVector = ByteVector.fromValidHex("98 4 9a3c0001 16da4e00 0400000 11a042006c006f006f00640020006f0066002000560061006e007500 864b00610072006e002d004500")
|
||||
val unk3_ABC: ByteVector = ByteVector.fromValidHex("98 4 9c3c0000 df587c00 1400000 11a054006800650020004e00650076006500720068006f006f006400 8e6f00460058006f00530074006f006e0065004d0061006e002d004700")
|
||||
val unk4_ABC: ByteVector = ByteVector.fromValidHex("98 4 c03c0000 24060400 0600000 1220540068006500200042006c00610063006b0020004b006e0069006700680074007300 874400720061007a00760065006e00")
|
||||
val unk5_ABC: ByteVector = ByteVector.fromValidHex("98 5 383c0001 4b709a00 0c00000 10a03e005400760053003c00 89430061007000650062006f00610074007300")
|
||||
val unk6_ABC: ByteVector = ByteVector.fromValidHex("98 5 b03c0000 35d67000 0400000 11404c006f0073007400200043006100750073006500 895a00650072006f004b00650077006c006c00")
|
||||
val unk7_ABC: ByteVector = ByteVector.fromValidHex("98 4 043e0001 9fb82616 1400000 11e0540068006500200042006c00610063006b00200054006f00770065007200 874b00720075007000680065007800")
|
||||
|
||||
"decode unk0_ABC" in {
|
||||
PacketCoding.decodePacket(unk0_ABC).require match {
|
||||
case OutfitListEvent(outfit_score, unk1, unk2, unk3, outfit_name, outfit_leader) =>
|
||||
outfit_score mustEqual 1585684480L
|
||||
unk1 mustEqual 2162229248L
|
||||
unk2 mustEqual 32768
|
||||
unk3 mustEqual 0
|
||||
case OutfitListEvent(code, ListElementOutfit(unk1, points, members, outfit_name, outfit_leader)) =>
|
||||
code mustEqual OutfitListEvent.RequestType.ListElementOutfit
|
||||
unk1 mustEqual 7668
|
||||
points mustEqual 788224
|
||||
members mustEqual 4
|
||||
outfit_name mustEqual "NightLords"
|
||||
outfit_leader mustEqual "NYCat"
|
||||
case _ =>
|
||||
|
|
@ -33,7 +34,7 @@ class OutfitListEventTest extends Specification {
|
|||
}
|
||||
|
||||
"encode unk0_ABC" in {
|
||||
val msg = OutfitListEvent(1585684480L, 2162229248L, 32768, 0, "NightLords", "NYCat")
|
||||
val msg = OutfitListEvent(RequestType.ListElementOutfit, ListElementOutfit(7668, 788224, 4, "NightLords", "NYCat"))
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual unk0_ABC
|
||||
|
|
|
|||
Loading…
Reference in a new issue