mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-19 18:44:45 +00:00
fix outfit rank names not representing DB values
add MOTD handling renaming OMR packet types with known uses handling outfit promotions (setrank) handle outfit owner changes changing the migration to change to unique index. allows concurrent refresh of MV
This commit is contained in:
parent
ad52c8076c
commit
18dd426d13
|
|
@ -104,4 +104,4 @@ CREATE MATERIALIZED VIEW outfitpoint_mv AS
|
|||
"outfitpoint"
|
||||
GROUP BY "outfit_id";
|
||||
|
||||
CREATE INDEX "outfitpoint_mv_outfit_id_idx" ON "outfitpoint_mv" ("outfit_id");
|
||||
CREATE UNIQUE INDEX "outfitpoint_mv_outfit_id_unique" ON "outfitpoint_mv" ("outfit_id");
|
||||
|
|
|
|||
|
|
@ -830,14 +830,13 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
|
|||
def handleOutfitRequest(pkt: OutfitRequest): Unit = {
|
||||
pkt match {
|
||||
|
||||
case OutfitRequest(_, OutfitRequestAction.Motd(message)) =>
|
||||
SessionOutfitHandlers.HandleOutfitMotd(zones, message, player)
|
||||
|
||||
case OutfitRequest(_, OutfitRequestAction.Ranks(List(r1, r2, r3, r4, r5, r6, r7, r8))) =>
|
||||
// update db
|
||||
//sendResponse(OutfitEvent(6418, Unk2(OutfitInfo(player.outfit_name, 0, 0, 1, OutfitRankNames(r1.getOrElse(""), r2.getOrElse(""), r3.getOrElse(""), r4.getOrElse(""), r5.getOrElse(""), r6.getOrElse(""), r7.getOrElse(""), r8.getOrElse("")), "Welcome to the first PSForever Outfit!", 0, unk11=true, 0, 8888888, 0, 0, 0))))
|
||||
|
||||
case OutfitRequest(_, OutfitRequestAction.Motd(message)) =>
|
||||
// update db
|
||||
//sendResponse(OutfitEvent(6418, Unk2(OutfitInfo(player.outfit_name, 0, 0, 1, OutfitRankNames("", "", "", "", "", "", "", ""), message, 0, unk11=true, 0, 8888888, 0, 0, 0))))
|
||||
|
||||
case OutfitRequest(_, OutfitRequestAction.Unk3(true)) =>
|
||||
SessionOutfitHandlers.HandleViewOutfitWindow(zones, player, player.outfit_id)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) 2025 PSForever
|
||||
package net.psforever.actors.session.support
|
||||
|
||||
import io.getquill.{ActionReturning, EntityQuery, Insert, PostgresJAsyncContext, Query, Quoted, SnakeCase}
|
||||
import io.getquill.{ActionReturning, EntityQuery, Insert, PostgresJAsyncContext, Query, Quoted, SnakeCase, Update}
|
||||
import net.psforever.objects.avatar.PlayerControl
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.objects.Player
|
||||
|
|
@ -19,15 +19,23 @@ import scala.util.{Failure, Success}
|
|||
object SessionOutfitHandlers {
|
||||
|
||||
case class Avatar(id: Long, name: String, faction_id: Int, last_login: java.time.LocalDateTime)
|
||||
case class Outfit(id: Long, name: String, faction: Int, owner_id: Long, motd: Option[String], created: java.time.LocalDateTime,
|
||||
rank0: Option[String],
|
||||
rank1: Option[String],
|
||||
rank2: Option[String],
|
||||
rank3: Option[String],
|
||||
rank4: Option[String],
|
||||
rank5: Option[String],
|
||||
rank6: Option[String],
|
||||
rank7: Option[String])
|
||||
case class Outfit(
|
||||
id: Long,
|
||||
name: String,
|
||||
faction: Int,
|
||||
owner_id: Long,
|
||||
motd: Option[String],
|
||||
created: java.time.LocalDateTime,
|
||||
deleted: Boolean,
|
||||
rank0: Option[String],
|
||||
rank1: Option[String],
|
||||
rank2: Option[String],
|
||||
rank3: Option[String],
|
||||
rank4: Option[String],
|
||||
rank5: Option[String],
|
||||
rank6: Option[String],
|
||||
rank7: Option[String]
|
||||
)
|
||||
case class Outfitmember(id: Long, outfit_id: Long, avatar_id: Long, rank: Int)
|
||||
case class Outfitpoint(id: Long, outfit_id: Long, avatar_id: Option[Long], points: Long)
|
||||
case class OutfitpointMv(outfit_id: Long, points: Long)
|
||||
|
|
@ -126,12 +134,12 @@ object SessionOutfitHandlers {
|
|||
|
||||
PlayerControl.sendResponse(outfitInvite.sentFrom.Zone, outfitInvite.sentFrom.Name,
|
||||
OutfitMembershipResponse(
|
||||
OutfitMembershipResponse.PacketType.Unk2, 0, 0,
|
||||
OutfitMembershipResponse.PacketType.InviteAccepted, 0, 0,
|
||||
invited.CharId, outfitInvite.sentFrom.CharId, invited.Name, outfit.name, flag = false))
|
||||
|
||||
PlayerControl.sendResponse(invited.Zone, invited.Name,
|
||||
OutfitMembershipResponse(
|
||||
OutfitMembershipResponse.PacketType.Unk2, 0, 0,
|
||||
OutfitMembershipResponse.PacketType.InviteAccepted, 0, 0,
|
||||
invited.CharId, outfitInvite.sentFrom.CharId, invited.Name, outfit.name, flag = true))
|
||||
|
||||
PlayerControl.sendResponse(outfitInvite.sentFrom.Zone, outfitInvite.sentFrom.Name,
|
||||
|
|
@ -183,12 +191,12 @@ object SessionOutfitHandlers {
|
|||
|
||||
PlayerControl.sendResponse(outfitInvite.sentFrom.Zone, outfitInvite.sentFrom.Name,
|
||||
OutfitMembershipResponse(
|
||||
OutfitMembershipResponse.PacketType.Unk3, 0, 0,
|
||||
OutfitMembershipResponse.PacketType.InviteRejected, 0, 0,
|
||||
invited.CharId, outfitInvite.sentFrom.CharId, invited.Name, "", flag = false))
|
||||
|
||||
PlayerControl.sendResponse(invited.Zone, invited.Name,
|
||||
OutfitMembershipResponse(
|
||||
OutfitMembershipResponse.PacketType.Unk3, 0, 0,
|
||||
OutfitMembershipResponse.PacketType.InviteRejected, 0, 0,
|
||||
invited.CharId, outfitInvite.sentFrom.CharId, invited.Name, "", flag = true))
|
||||
|
||||
OutfitInviteManager.removeOutfitInvite(invited.CharId)
|
||||
|
|
@ -277,10 +285,60 @@ object SessionOutfitHandlers {
|
|||
}
|
||||
|
||||
def HandleOutfitPromote(zones: Seq[Zone], promotedId: Long, newRank: Int, promoter: Player): Unit = {
|
||||
// send to all online players in outfit
|
||||
|
||||
val outfit_id = promoter.outfit_id
|
||||
|
||||
findPlayerByIdForOutfitAction(zones, promotedId, promoter).foreach { promoted =>
|
||||
PlayerControl.sendResponse(promoted.Zone, promoted.Name, OutfitMemberEvent(6418, promotedId, OutfitMemberEventAction.Unk0(promoted.Name, newRank, 1032432, 0, OutfitMemberEventAction.PacketType.Padding, 0)))
|
||||
PlayerControl.sendResponse(promoter.Zone, promoter.Name, OutfitMemberEvent(6418, promotedId, OutfitMemberEventAction.Unk0(promoted.Name, newRank, 1032432, 0, OutfitMemberEventAction.PacketType.Padding, 0)))
|
||||
|
||||
if (newRank == 7) {
|
||||
|
||||
// demote owner to rank 6
|
||||
// promote promoted to rank 7
|
||||
// update outfit
|
||||
updateOutfitOwner(outfit_id, promoter.avatar.id, promoted.avatar.id)
|
||||
|
||||
// TODO: does every member get the notification like this?
|
||||
getOutfitMemberPoints(outfit_id, promoter.avatar.id).map {
|
||||
owner_points =>
|
||||
// announce owner rank change
|
||||
zones.foreach(zone => {
|
||||
zone.AllPlayers.filter(_.outfit_id == outfit_id).foreach(outfitMember => {
|
||||
PlayerControl.sendResponse(
|
||||
zone, outfitMember.Name,
|
||||
OutfitMemberEvent(outfit_id, promoter.avatar.id,
|
||||
OutfitMemberEventAction.Unk0(promoter.Name, 6, owner_points, 0, OutfitMemberEventAction.PacketType.Padding, 0)))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// update promoter rank
|
||||
PlayerControl.sendResponse(
|
||||
promoter.Zone, promoter.Name,
|
||||
OutfitMemberUpdate(outfit_id, promoter.avatar.id, rank = 6, flag = true))
|
||||
}
|
||||
else {
|
||||
// promote promoted
|
||||
updateOutfitMemberRank(outfit_id, promoted.avatar.id, rank = newRank)
|
||||
}
|
||||
|
||||
// TODO: does every member get the notification like this?
|
||||
getOutfitMemberPoints(outfit_id, promoted.avatar.id).map {
|
||||
member_points =>
|
||||
// tell everyone about the new rank of the promoted member
|
||||
zones.foreach(zone => {
|
||||
zone.AllPlayers.filter(_.outfit_id == outfit_id).foreach(player => {
|
||||
PlayerControl.sendResponse(
|
||||
zone, player.Name,
|
||||
OutfitMemberEvent(outfit_id, promoted.avatar.id,
|
||||
OutfitMemberEventAction.Unk0(promoted.Name, newRank, member_points, 0, OutfitMemberEventAction.PacketType.Padding, 0)))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// update promoted rank
|
||||
PlayerControl.sendResponse(
|
||||
promoted.Zone, promoted.Name,
|
||||
OutfitMemberUpdate(outfit_id, promoted.avatar.id, rank = newRank, flag = true))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -306,7 +364,16 @@ object SessionOutfitHandlers {
|
|||
totalPoints,
|
||||
totalPoints,
|
||||
memberCount,
|
||||
OutfitRankNames("", "", "", "", "", "", "", ""),
|
||||
OutfitRankNames(
|
||||
outfit.rank0.getOrElse(""),
|
||||
outfit.rank1.getOrElse(""),
|
||||
outfit.rank2.getOrElse(""),
|
||||
outfit.rank3.getOrElse(""),
|
||||
outfit.rank4.getOrElse(""),
|
||||
outfit.rank5.getOrElse(""),
|
||||
outfit.rank6.getOrElse(""),
|
||||
outfit.rank7.getOrElse(""),
|
||||
),
|
||||
outfit.motd.getOrElse(""),
|
||||
14, unk11 = true, 0, seconds, 0, 0, 0))))
|
||||
|
||||
|
|
@ -355,6 +422,71 @@ object SessionOutfitHandlers {
|
|||
}
|
||||
}
|
||||
|
||||
def HandleOutfitMotd(zones: Seq[Zone], message: String, player: Player): Unit = {
|
||||
|
||||
val outfit_id = player.outfit_id
|
||||
|
||||
// update MOTD
|
||||
updateOutfitMotd(outfit_id, message)
|
||||
|
||||
// TODO this does not notify clients with open windows. Do they update in the first place?
|
||||
val outfitDetails = for {
|
||||
outfitOpt <- ctx.run(getOutfitById(outfit_id)).map(_.headOption)
|
||||
memberCount <- ctx.run(query[Outfitmember].filter(_.outfit_id == lift(outfit_id)).size)
|
||||
pointsTotal <- ctx.run(querySchema[OutfitpointMv]("outfitpoint_mv").filter(_.outfit_id == lift(outfit_id)))
|
||||
} yield (outfitOpt, memberCount, pointsTotal.headOption.map(_.points).getOrElse(0L))
|
||||
|
||||
for {
|
||||
(outfitOpt, memberCount, totalPoints) <- outfitDetails
|
||||
} yield {
|
||||
outfitOpt.foreach { outfit =>
|
||||
|
||||
// send to all online players in outfit
|
||||
val outfit_event = OutfitEvent(
|
||||
outfit_id,
|
||||
Unk2(
|
||||
OutfitInfo(
|
||||
outfit_name = outfit.name,
|
||||
outfit_points1 = totalPoints,
|
||||
outfit_points2 = totalPoints,
|
||||
member_count = memberCount,
|
||||
outfit_rank_names = OutfitRankNames(
|
||||
outfit.rank0.getOrElse(""),
|
||||
outfit.rank1.getOrElse(""),
|
||||
outfit.rank2.getOrElse(""),
|
||||
outfit.rank3.getOrElse(""),
|
||||
outfit.rank4.getOrElse(""),
|
||||
outfit.rank5.getOrElse(""),
|
||||
outfit.rank6.getOrElse(""),
|
||||
outfit.rank7.getOrElse(""),
|
||||
),
|
||||
motd = outfit.motd.getOrElse(""),
|
||||
unk10 = 0,
|
||||
unk11 = true,
|
||||
unk12 = 0,
|
||||
created_timestamp = outfit.created.atZone(java.time.ZoneOffset.UTC).toInstant.toEpochMilli / 1000,
|
||||
unk23 = 0,
|
||||
unk24 = 0,
|
||||
unk25 = 0
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
zones.foreach(zone => {
|
||||
zone.AllPlayers.filter(_.outfit_id == outfit_id).foreach(player => {
|
||||
PlayerControl.sendResponse(
|
||||
zone, player.Name,
|
||||
outfit_event
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// C >> S OutfitRequest(41593365, Motd(Vanu outfit for the planetside forever project! -find out more about the PSEMU project at PSforever.net))
|
||||
// S >> C OutfitEvent(Unk2, 529744, Unk2(OutfitInfo(PlanetSide_Forever_Vanu, 0, 0, 3, OutfitRankNames(, , , , , , , ), Vanu outfit for the planetside forever project! -find out more about the PSEMU project at PSforever.net, 0, 1, 0, 1458331641, 0, 0, 0)))
|
||||
}
|
||||
|
||||
/* supporting functions */
|
||||
|
||||
def sanitizeOutfitName(name: String): Option[String] = {
|
||||
|
|
@ -435,12 +567,14 @@ object SessionOutfitHandlers {
|
|||
for {
|
||||
deleted <- ctx.run(
|
||||
query[Outfitmember]
|
||||
.filter(m => m.outfit_id == lift(outfit_id) && m.avatar_id == lift(avatar_id))
|
||||
.filter(_.outfit_id == lift(outfit_id))
|
||||
.filter(_.avatar_id == lift(avatar_id))
|
||||
.delete
|
||||
)
|
||||
updated <- ctx.run(
|
||||
query[Outfitpoint]
|
||||
.filter(p => p.outfit_id == lift(outfit_id) && p.avatar_id == lift(avatarOpt))
|
||||
.filter(_.outfit_id == lift(outfit_id))
|
||||
.filter(_.avatar_id == lift(avatarOpt))
|
||||
.update(_.avatar_id -> None)
|
||||
)
|
||||
} yield (deleted, updated)
|
||||
|
|
@ -455,6 +589,18 @@ object SessionOutfitHandlers {
|
|||
query[Outfitmember].filter(_.outfit_id == lift(id)).size
|
||||
}
|
||||
|
||||
def getOutfitMemberPoints(outfit_id: Long, avatar_id: Long): Future[Long] = {
|
||||
val avatarOpt: Option[Long] = Some(avatar_id)
|
||||
for {
|
||||
points <- ctx.run(
|
||||
query[Outfitpoint]
|
||||
.filter(_.outfit_id == lift(outfit_id))
|
||||
.filter(_.avatar_id == lift(avatarOpt))
|
||||
.map(_.points)
|
||||
)
|
||||
} yield (points.headOption.getOrElse(0))
|
||||
}
|
||||
|
||||
def getOutfitPoints(id: Long): Quoted[EntityQuery[OutfitpointMv]] = quote {
|
||||
querySchema[OutfitpointMv]("outfitpoint_mv").filter(_.outfit_id == lift(id))
|
||||
}
|
||||
|
|
@ -490,4 +636,49 @@ object SessionOutfitHandlers {
|
|||
(outfit.id, points.map(_.points).getOrElse(0L), outfit.name, leader.name, memberCounts.map(_._2).getOrElse(0L))
|
||||
}
|
||||
}
|
||||
|
||||
def updateMemberRankById(outfit_id: Long, avatar_id: Long, rank: Int): Quoted[Update[Outfitmember]] = quote {
|
||||
query[Outfitmember]
|
||||
.filter(_.outfit_id == lift(outfit_id))
|
||||
.filter(_.avatar_id == lift(avatar_id))
|
||||
.update(_.rank -> lift(rank))
|
||||
}
|
||||
|
||||
def updateOutfitMemberRank(outfit_id: Long, avatar_id: Long, rank: Int): Future[Unit] = {
|
||||
ctx.transaction { implicit ec =>
|
||||
for {
|
||||
_ <- ctx.run(updateMemberRankById(outfit_id, avatar_id, rank))
|
||||
} yield ()
|
||||
}
|
||||
}
|
||||
|
||||
def updateOutfitOwnerById(outfit_id: Long, owner_id: Long): Quoted[Update[Outfit]] = quote {
|
||||
query[Outfit]
|
||||
.filter(_.id == lift(outfit_id))
|
||||
.update(_.owner_id -> lift(owner_id))
|
||||
}
|
||||
|
||||
def updateOutfitOwner(outfit_id: Long, owner_id: Long, new_owner_id: Long): Future[Unit] = {
|
||||
ctx.transaction { implicit ec =>
|
||||
for {
|
||||
_ <- ctx.run(updateMemberRankById(outfit_id, owner_id, 6))
|
||||
_ <- ctx.run(updateMemberRankById(outfit_id, new_owner_id, 7))
|
||||
_ <- ctx.run(updateOutfitOwnerById(outfit_id, new_owner_id))
|
||||
} yield ()
|
||||
}
|
||||
}
|
||||
|
||||
def updateOutfitMotdById(outfit_id: Long, motd: Option[String]): Quoted[Update[Outfit]] = quote {
|
||||
query[Outfit]
|
||||
.filter(_.id == lift(outfit_id))
|
||||
.update(_.motd -> lift(motd))
|
||||
}
|
||||
|
||||
def updateOutfitMotd(outfit_id: Long, motd: String): Future[Unit] = {
|
||||
ctx.transaction { implicit ec =>
|
||||
for {
|
||||
_ <- ctx.run(updateOutfitMotdById(outfit_id, Some(motd)))
|
||||
} yield ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@ object OutfitMembershipResponse extends Marshallable[OutfitMembershipResponse] {
|
|||
type Type = Value
|
||||
|
||||
val CreateResponse: PacketType.Value = Value(0)
|
||||
val Invite: PacketType.Value = Value(1) // Info: Player has been invited / response to OutfitMembershipRequest Unk2 for that player
|
||||
val Unk2: PacketType.Value = Value(2) // Invited / Accepted / Added
|
||||
val Unk3: PacketType.Value = Value(3)
|
||||
val Invite: PacketType.Value = Value(1) // response to OutfitMembershipRequest Unk2 for that player
|
||||
val InviteAccepted: PacketType.Value = Value(2)
|
||||
val InviteRejected: PacketType.Value = Value(3)
|
||||
val Unk4: PacketType.Value = Value(4)
|
||||
val Kick: PacketType.Value = Value(5)
|
||||
val Unk6: PacketType.Value = Value(6) // 6 and 7 seen as failed decodes, validity unknown
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import scodec.codecs._
|
|||
import shapeless.{::, HNil}
|
||||
|
||||
final case class OutfitRequest(
|
||||
id: Long,
|
||||
outfit_id: Long,
|
||||
action: OutfitRequestAction
|
||||
) extends PlanetSideGamePacket {
|
||||
type Packet = OutfitRequest
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class OutfitMembershipResponseTest extends Specification {
|
|||
"decode unk1" in {
|
||||
PacketCoding.decodePacket(unk1).require match {
|
||||
case OutfitMembershipResponse(packet_type, unk0, unk1, outfit_id, target_id, str1, str2, flag) =>
|
||||
packet_type mustEqual PacketType.Unk1
|
||||
packet_type mustEqual PacketType.Invite
|
||||
unk0 mustEqual 0
|
||||
unk1 mustEqual 0
|
||||
outfit_id mustEqual 30383325
|
||||
|
|
@ -56,7 +56,7 @@ class OutfitMembershipResponseTest extends Specification {
|
|||
}
|
||||
|
||||
"encode unk1" in {
|
||||
val msg = OutfitMembershipResponse(PacketType.Unk1, 0, 0, 30383325, 41605870, "xNick", "PlanetSide_Forever_TR", flag = false)
|
||||
val msg = OutfitMembershipResponse(PacketType.Invite, 0, 0, 30383325, 41605870, "xNick", "PlanetSide_Forever_TR", flag = false)
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual unk1
|
||||
|
|
@ -65,7 +65,7 @@ class OutfitMembershipResponseTest extends Specification {
|
|||
"decode unk2" in {
|
||||
PacketCoding.decodePacket(unk2).require match {
|
||||
case OutfitMembershipResponse(packet_type, unk0, unk1, outfit_id, target_id, str1, str2, flag) =>
|
||||
packet_type mustEqual PacketType.Unk2
|
||||
packet_type mustEqual PacketType.InviteAccepted
|
||||
unk0 mustEqual 0
|
||||
unk1 mustEqual 0
|
||||
outfit_id mustEqual 41605156
|
||||
|
|
@ -79,7 +79,7 @@ class OutfitMembershipResponseTest extends Specification {
|
|||
}
|
||||
|
||||
"encode unk2" in {
|
||||
val msg = OutfitMembershipResponse(PacketType.Unk2, 0, 0, 41605156, 41593365, "Zergling92", "PlanetSide_Forever_Vanu", flag = false)
|
||||
val msg = OutfitMembershipResponse(PacketType.InviteAccepted, 0, 0, 41605156, 41593365, "Zergling92", "PlanetSide_Forever_Vanu", flag = false)
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual unk2
|
||||
|
|
@ -88,7 +88,7 @@ class OutfitMembershipResponseTest extends Specification {
|
|||
"decode unk3" in {
|
||||
PacketCoding.decodePacket(unk3).require match {
|
||||
case OutfitMembershipResponse(packet_type, unk0, unk1, outfit_id, target_id, str1, str2, flag) =>
|
||||
packet_type mustEqual PacketType.Unk3
|
||||
packet_type mustEqual PacketType.InviteRejected
|
||||
unk0 mustEqual 0
|
||||
unk1 mustEqual 0
|
||||
outfit_id mustEqual 41574772
|
||||
|
|
@ -102,7 +102,7 @@ class OutfitMembershipResponseTest extends Specification {
|
|||
}
|
||||
|
||||
"encode unk3" in {
|
||||
val msg = OutfitMembershipResponse(PacketType.Unk3, 0, 0, 41574772, 31156616, "", "", flag = true)
|
||||
val msg = OutfitMembershipResponse(PacketType.InviteRejected, 0, 0, 41574772, 31156616, "", "", flag = true)
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual unk3
|
||||
|
|
@ -134,7 +134,7 @@ class OutfitMembershipResponseTest extends Specification {
|
|||
"decode unk5" in {
|
||||
PacketCoding.decodePacket(unk5).require match {
|
||||
case OutfitMembershipResponse(packet_type, unk0, unk1, outfit_id, target_id, str1, str2, flag) =>
|
||||
packet_type mustEqual PacketType.Unk5
|
||||
packet_type mustEqual PacketType.Kick
|
||||
unk0 mustEqual 0
|
||||
unk1 mustEqual 1
|
||||
outfit_id mustEqual 41593365
|
||||
|
|
@ -148,7 +148,7 @@ class OutfitMembershipResponseTest extends Specification {
|
|||
}
|
||||
|
||||
"encode unk5" in {
|
||||
val msg = OutfitMembershipResponse(PacketType.Unk5, 0, 1, 41593365, 41605263, "PSFoutfittest1", "", flag = true)
|
||||
val msg = OutfitMembershipResponse(PacketType.Kick, 0, 1, 41593365, 41605263, "PSFoutfittest1", "", flag = true)
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual unk5
|
||||
|
|
|
|||
Loading…
Reference in a new issue