diff --git a/src/main/scala/net/psforever/packet/game/OutfitMembershipRequest.scala b/src/main/scala/net/psforever/packet/game/OutfitMembershipRequest.scala index adeaca488..6d3c17ea0 100644 --- a/src/main/scala/net/psforever/packet/game/OutfitMembershipRequest.scala +++ b/src/main/scala/net/psforever/packet/game/OutfitMembershipRequest.scala @@ -24,15 +24,38 @@ abstract class OutfitMembershipRequestAction(val code: Int) object OutfitMembershipRequestAction { - final case class CreateOutfit(unk2: String, unk3: Int, unk4: Boolean, outfit_name: String) extends OutfitMembershipRequestAction(code = 0) + final case class CreateOutfit( + unk2: String, + unk3: Int, + unk4: Boolean, + outfit_name: String + ) extends OutfitMembershipRequestAction(code = 0) - final case class FormOutfit(unk2: String, unk3: Int, unk4: Boolean, outfit_name: String) extends OutfitMembershipRequestAction(code = 1) + final case class FormOutfit( + unk2: String, + unk3: Int, + unk4: Boolean, + outfit_name: String + ) extends OutfitMembershipRequestAction(code = 1) - final case class AcceptOutfitInvite(unk2: String) extends OutfitMembershipRequestAction(code = 3) + final case class Unk2( + unk2: Int, + unk3: Int, + member_name: String, + ) extends OutfitMembershipRequestAction(code = 2) + final case class AcceptOutfitInvite( + unk2: String + ) extends OutfitMembershipRequestAction(code = 3) - final case class RejectOutfitInvite(unk2: String) extends OutfitMembershipRequestAction(code = 4) + final case class RejectOutfitInvite( + unk2: String + ) extends OutfitMembershipRequestAction(code = 4) - final case class CancelOutfitInvite(unk5: Int, unk6: Int, outfit_name: String) extends OutfitMembershipRequestAction(code = 5) + final case class CancelOutfitInvite( + unk5: Int, + unk6: Int, + outfit_name: String + ) extends OutfitMembershipRequestAction(code = 5) final case class Unknown(badCode: Int, data: BitVector) extends OutfitMembershipRequestAction(badCode) @@ -44,7 +67,12 @@ object OutfitMembershipRequestAction { private val everFailCondition = conditional(included = false, bool) val CreateOutfitCodec: Codec[CreateOutfit] = - (PacketHelpers.encodedWideString :: uint4L :: bool :: PacketHelpers.encodedWideString).xmap[CreateOutfit]( + ( + PacketHelpers.encodedWideString :: + uint4L :: + bool :: + PacketHelpers.encodedWideString + ).xmap[CreateOutfit]( { case unk2 :: unk3 :: unk4 :: outfit_name :: HNil => CreateOutfit(unk2, unk3, unk4, outfit_name) @@ -56,7 +84,12 @@ object OutfitMembershipRequestAction { ) val FormOutfitCodec: Codec[FormOutfit] = - (PacketHelpers.encodedWideString :: uint4L :: bool :: PacketHelpers.encodedWideString).xmap[FormOutfit]( + ( + PacketHelpers.encodedWideString :: + uint4L :: + bool :: + PacketHelpers.encodedWideString + ).xmap[FormOutfit]( { case unk2 :: unk3 :: unk4 :: outfit_name :: HNil => FormOutfit(unk2, unk3, unk4, outfit_name) @@ -67,6 +100,22 @@ object OutfitMembershipRequestAction { } ) + val Unk2Codec: Codec[Unk2] = + ( + uint16L :: + uint16L :: + PacketHelpers.encodedWideStringAligned(5) + ).xmap[Unk2]( + { + case unk2 :: unk3 :: member_name :: HNil => + Unk2(unk2, unk3, member_name) + }, + { + case Unk2(unk2, unk3, member_name) => + unk2 :: unk3 :: member_name :: HNil + } + ) + val AcceptOutfitCodec: Codec[AcceptOutfitInvite] = PacketHelpers.encodedWideString.xmap[AcceptOutfitInvite]( { @@ -92,7 +141,11 @@ object OutfitMembershipRequestAction { ) val CancelOutfitCodec: Codec[CancelOutfitInvite] = - (uint16L :: uint16L :: PacketHelpers.encodedWideStringAligned(5)).xmap[CancelOutfitInvite]( + ( + uint16L :: + uint16L :: + PacketHelpers.encodedWideStringAligned(5) + ).xmap[CancelOutfitInvite]( { case unk5 :: unk6 :: outfit_name :: HNil => CancelOutfitInvite(unk5, unk6, outfit_name) @@ -155,7 +208,7 @@ object OutfitMembershipRequest extends Marshallable[OutfitMembershipRequest] { ((code: @switch) match { case 0 => CreateOutfitCodec case 1 => FormOutfitCodec // so far same as Create - case 2 => unknownCodec(action = code) + case 2 => Unk2Codec case 3 => AcceptOutfitCodec case 4 => RejectOutfitCodec // so far same as Accept case 5 => CancelOutfitCodec diff --git a/src/test/scala/game/OutfitMemberEventTest.scala b/src/test/scala/game/OutfitMemberEventTest.scala index 9b07ec9dc..4fe48a805 100644 --- a/src/test/scala/game/OutfitMemberEventTest.scala +++ b/src/test/scala/game/OutfitMemberEventTest.scala @@ -31,7 +31,7 @@ val unk0_ABC_Lazer: ByteVector = hex"90 048640001030c28022404c0061007a00650 "decode Unk0 ABC" in { PacketCoding.decodePacket(unk0_ABC_Lazer).require match { - case OutfitMemberEvent(unk00, outfit_guid, unk3, unk4, unk5, unk6, member_name, unk7, unk8, unk9, unk10, unk11) => + case OutfitMemberEvent(unk00, outfit_guid, unk3, unk4, unk5, unk6, member_name, unk8, unk9, unk10, unk11, unk12, unk13,unk14,unk15,unk16) => unk00 mustEqual 0 outfit_guid mustEqual 6418L unk3 mustEqual 64 @@ -39,11 +39,15 @@ val unk0_ABC_Lazer: ByteVector = hex"90 048640001030c28022404c0061007a00650 unk5 mustEqual 10 unk6 mustEqual 0 member_name mustEqual "Lazer1982" - unk7 mustEqual 15092 - unk8 mustEqual 57413 - unk9 mustEqual 19467 - unk10 mustEqual 16480 - unk11 mustEqual 16 + unk8 mustEqual 244 + unk9 mustEqual 58 + unk10 mustEqual 69 + unk11 mustEqual 224 + unk12 mustEqual 11 + unk13 mustEqual 76 + unk14 mustEqual 96 + unk15 mustEqual 64 + unk16 mustEqual 16 case _ => ko } @@ -58,11 +62,15 @@ val unk0_ABC_Lazer: ByteVector = hex"90 048640001030c28022404c0061007a00650 unk5 = 10, unk6 = 0, member_name = "Lazer1982", - unk7 = 15092, - unk8 = 57413, - unk9 = 19467, - unk10 = 16480, - unk11 = 16, + unk8 = 244, + unk9 = 58, + unk10 = 69, + unk11 = 224, + unk12 = 11, + unk13 = 76, + unk14 = 96, + unk15 = 64, + unk16 = 16, ) val pkt = PacketCoding.encodePacket(msg).require.toByteVector diff --git a/src/test/scala/game/OutfitMembershipRequestTest.scala b/src/test/scala/game/OutfitMembershipRequestTest.scala index 163e4c45a..bef384a5b 100644 --- a/src/test/scala/game/OutfitMembershipRequestTest.scala +++ b/src/test/scala/game/OutfitMembershipRequestTest.scala @@ -13,7 +13,8 @@ class OutfitMembershipRequestTest extends Specification { val create_2222 = hex"8c 0 1000 000 1000 84 3200320032003200" val form_abc = hex"8c 2 0200 000 1000 83 610062006300" val form_1 = hex"8c 2 1000 000 1000 81 3100" - val unk3 = hex"8c 5 bb39 9e0 2000 0000 1080 750072006f006200" // -- "urob" -- could be false positive -- seems to gets an OMSResp -> 0x8d271bb399e025af8f405080550072006f0062008080 + val unk2 = hex"8c 5 bb399e0 2000 0000 1140 7600690072007500730067006900760065007200" // -- virusgiver + val unk3 = hex"8c 5 bb399e0 2000 0000 1080 750072006f006200" // -- "urob" -- could be false positive -- seems to gets an OMSResp -> 0x8d271bb399e025af8f405080550072006f0062008080 val accept_1 = hex"8c 6 0200 000 1000" val accept_2 = hex"8c 6 0400 000 1000" val reject_1 = hex"8c 8 0200 000 1000" @@ -94,6 +95,24 @@ class OutfitMembershipRequestTest extends Specification { pkt mustEqual form_1 } + "decode Unk2" in { + PacketCoding.decodePacket(unk2).require match { + case OutfitMembershipRequest(request_type, outfit_id, action) => + request_type mustEqual RequestType.Unk2 + outfit_id mustEqual 30383325L + action mustEqual Unk2(0, 0, "virusgiver") + case _ => + ko + } + } + + "encode Unk2" in { + val msg = OutfitMembershipRequest(RequestType.Unk2, 30383325L, Unk2(0, 0, "virusgiver")) + val pkt = PacketCoding.encodePacket(msg).require.toByteVector + + pkt mustEqual unk2 + } + "decode AcceptOutfitInvite 1" in { PacketCoding.decodePacket(accept_1).require match { case OutfitMembershipRequest(request_type, avatar_id, action) =>