mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-19 18:44:45 +00:00
evict players from the outfit. no longer shall you spy on our stale info!
update packet types
This commit is contained in:
parent
8dcf678045
commit
c84bf9ae74
|
|
@ -30,7 +30,7 @@ import net.psforever.objects.vehicles.Utility
|
|||
import net.psforever.objects.vital.Vitality
|
||||
import net.psforever.objects.zones.{ZoneProjectile, Zoning}
|
||||
import net.psforever.packet.PlanetSideGamePacket
|
||||
import net.psforever.packet.game.OutfitEventAction.{OutfitInfo, OutfitRankNames, Unk0, Unk1}
|
||||
import net.psforever.packet.game.OutfitEventAction.{OutfitInfo, OutfitRankNames, Initial, Unk1}
|
||||
import net.psforever.packet.game.{ActionCancelMessage, AvatarFirstTimeEventMessage, AvatarImplantMessage, AvatarJumpMessage, BattleplanMessage, BindPlayerMessage, BugReportMessage, ChangeFireModeMessage, ChangeShortcutBankMessage, CharacterCreateRequestMessage, CharacterRequestMessage, ChatMsg, CollisionIs, ConnectToWorldRequestMessage, CreateShortcutMessage, DeadState, DeployObjectMessage, DisplayedAwardMessage, DropItemMessage, EmoteMsg, FacilityBenefitShieldChargeRequestMessage, FriendsRequest, GenericAction, GenericActionMessage, GenericCollisionMsg, GenericObjectActionAtPositionMessage, GenericObjectActionMessage, GenericObjectStateMsg, HitHint, InvalidTerrainMessage, LootItemMessage, MoveItemMessage, ObjectDetectedMessage, ObjectHeldMessage, OutfitEvent, OutfitMemberEvent, OutfitMembershipRequest, OutfitMembershipResponse, OutfitRequest, OutfitRequestAction, PickupItemMessage, PlanetsideAttributeMessage, PlayerStateMessageUpstream, RequestDestroyMessage, TargetingImplantRequest, TerrainCondition, TradeMessage, UnuseItemMessage, UseItemMessage, VoiceHostInfo, VoiceHostRequest, ZipLineMessage}
|
||||
import net.psforever.services.RemoverActor
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
|
|
@ -673,9 +673,9 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
|
|||
|
||||
def handleOutfitRequest(pkt: OutfitRequest): Unit = {
|
||||
pkt match {
|
||||
case OutfitRequest(_, OutfitRequestAction.Unk3(true)) =>
|
||||
case OutfitRequest(_, OutfitRequestAction.OutfitWindowOpen(true)) =>
|
||||
|
||||
case OutfitRequest(_, OutfitRequestAction.Unk3(false)) =>
|
||||
case OutfitRequest(_, OutfitRequestAction.OutfitWindowOpen(false)) =>
|
||||
|
||||
case _ =>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ import net.psforever.objects.vital.etc.SuicideReason
|
|||
import net.psforever.objects.vital.interaction.DamageInteraction
|
||||
import net.psforever.objects.zones.{ZoneProjectile, Zoning}
|
||||
import net.psforever.packet.PlanetSideGamePacket
|
||||
import net.psforever.packet.game.OutfitEventAction.{OutfitInfo, OutfitRankNames, Unk2}
|
||||
import net.psforever.packet.game.OutfitEventAction.{OutfitInfo, OutfitRankNames, Update}
|
||||
import net.psforever.packet.game.{ActionCancelMessage, ActionResultMessage, AvatarFirstTimeEventMessage, AvatarImplantMessage, AvatarJumpMessage, BattleplanMessage, BindPlayerMessage, BugReportMessage, ChangeFireModeMessage, ChangeShortcutBankMessage, CharacterCreateRequestMessage, CharacterRequestAction, CharacterRequestMessage, ChatMsg, CollisionIs, ConnectToWorldRequestMessage, CreateShortcutMessage, DeadState, DeployObjectMessage, DisplayedAwardMessage, DropItemMessage, EmoteMsg, FacilityBenefitShieldChargeRequestMessage, FriendsRequest, GenericAction, GenericActionMessage, GenericCollisionMsg, GenericObjectActionAtPositionMessage, GenericObjectActionMessage, GenericObjectStateMsg, HitHint, InvalidTerrainMessage, LootItemMessage, MoveItemMessage, ObjectDetectedMessage, ObjectHeldMessage, OutfitEvent, OutfitMembershipRequest, OutfitMembershipRequestAction, OutfitMembershipResponse, OutfitRequest, OutfitRequestAction, PickupItemMessage, PlanetsideAttributeMessage, PlayerStateMessageUpstream, RequestDestroyMessage, TargetingImplantRequest, TerrainCondition, TradeMessage, UnuseItemMessage, UseItemMessage, VoiceHostInfo, VoiceHostRequest, ZipLineMessage}
|
||||
import net.psforever.services.account.{AccountPersistenceService, RetrieveAccountData}
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
|
|
@ -836,12 +836,12 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
|
|||
case OutfitRequest(_, OutfitRequestAction.Ranks(List(r1, r2, r3, r4, r5, r6, r7, r8))) =>
|
||||
SessionOutfitHandlers.HandleOutfitRank(zones, List(r1, r2, r3, r4, r5, r6, r7, r8), player)
|
||||
|
||||
case OutfitRequest(_, OutfitRequestAction.Unk3(true)) =>
|
||||
case OutfitRequest(_, OutfitRequestAction.OutfitWindowOpen(true)) =>
|
||||
SessionOutfitHandlers.HandleViewOutfitWindow(zones, player, player.outfit_id)
|
||||
|
||||
case OutfitRequest(_, OutfitRequestAction.Unk3(false)) =>
|
||||
case OutfitRequest(_, OutfitRequestAction.OutfitWindowOpen(false)) =>
|
||||
|
||||
case OutfitRequest(_, OutfitRequestAction.Unk4(true)) =>
|
||||
case OutfitRequest(_, OutfitRequestAction.OutfitListWindowOpen(true)) =>
|
||||
SessionOutfitHandlers.HandleGetOutfitList(player)
|
||||
|
||||
case _ =>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import io.getquill.{ActionReturning, EntityQuery, Insert, PostgresJAsyncContext,
|
|||
import net.psforever.objects.avatar.PlayerControl
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.objects.Player
|
||||
import net.psforever.packet.game.OutfitEventAction.{OutfitInfo, OutfitRankNames, Unk0, Unk1, Unk2}
|
||||
import net.psforever.packet.game.OutfitEventAction.{Leaving, OutfitInfo, OutfitRankNames, Initial, Unk1, Update, UpdateMemberCount}
|
||||
import net.psforever.packet.game.OutfitMembershipResponse.PacketType.CreateResponse
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
|
|
@ -63,7 +63,7 @@ object SessionOutfitHandlers {
|
|||
outfit.created.atZone(java.time.ZoneOffset.UTC).toInstant.toEpochMilli / 1000
|
||||
|
||||
PlayerControl.sendResponse(player.Zone, player.Name,
|
||||
OutfitEvent(outfit.id, Unk2(
|
||||
OutfitEvent(outfit.id, Update(
|
||||
OutfitInfo(
|
||||
outfit.name, 0, 0, 1,
|
||||
OutfitRankNames("", "", "", "", "", "", "", ""),
|
||||
|
|
@ -143,16 +143,16 @@ object SessionOutfitHandlers {
|
|||
invited.CharId, outfitInvite.sentFrom.CharId, invited.Name, outfit.name, flag = true))
|
||||
|
||||
PlayerControl.sendResponse(outfitInvite.sentFrom.Zone, outfitInvite.sentFrom.Name,
|
||||
OutfitEvent(outfitId, OutfitEventAction.Unk5(memberCount)))
|
||||
OutfitEvent(outfitId, UpdateMemberCount(memberCount)))
|
||||
|
||||
PlayerControl.sendResponse(outfitInvite.sentFrom.Zone, outfitInvite.sentFrom.Name,
|
||||
OutfitMemberEvent(outfitId, invited.CharId,
|
||||
OutfitMemberEventAction.Unk0(invited.Name, 0, 0, 0,
|
||||
OutfitMemberEventAction.Update(invited.Name, 0, 0, 0,
|
||||
OutfitMemberEventAction.PacketType.Padding, 0)))
|
||||
|
||||
val seconds: Long = outfit.created.atZone(java.time.ZoneOffset.UTC).toInstant.toEpochMilli / 1000
|
||||
PlayerControl.sendResponse(invited.Zone, invited.Name,
|
||||
OutfitEvent(outfitId, Unk0(OutfitInfo(
|
||||
OutfitEvent(outfitId, Initial(OutfitInfo(
|
||||
outfit.name, points, points, memberCount,
|
||||
OutfitRankNames("", "", "", "", "", "", "", ""),
|
||||
outfit.motd.getOrElse(""),
|
||||
|
|
@ -211,12 +211,12 @@ object SessionOutfitHandlers {
|
|||
case (deleted, _) =>
|
||||
if (deleted > 0) {
|
||||
PlayerControl.sendResponse(kickedBy.Zone, kickedBy.Name,
|
||||
OutfitMemberEvent(kickedBy.outfit_id, kickedId, OutfitMemberEventAction.Unk1()))
|
||||
OutfitMemberEvent(kickedBy.outfit_id, kickedId, OutfitMemberEventAction.Kicked()))
|
||||
|
||||
zones.filter(z => z.AllPlayers.nonEmpty).flatMap(_.AllPlayers)
|
||||
.filter(p => p.outfit_id == kickedBy.outfit_id).foreach(outfitMember =>
|
||||
PlayerControl.sendResponse(outfitMember.Zone, outfitMember.Name,
|
||||
OutfitMemberEvent(kickedBy.outfit_id, kickedId, OutfitMemberEventAction.Unk1()))
|
||||
OutfitMemberEvent(kickedBy.outfit_id, kickedId, OutfitMemberEventAction.Kicked()))
|
||||
)
|
||||
|
||||
session.chat.LeaveChannel(OutfitChannel(kickedBy.outfit_id))
|
||||
|
|
@ -238,8 +238,13 @@ object SessionOutfitHandlers {
|
|||
case (deleted, _) =>
|
||||
if (deleted > 0) {
|
||||
findPlayerByIdForOutfitAction(zones, kickedId, kickedBy).foreach { kicked =>
|
||||
|
||||
PlayerControl.sendResponse(kicked.Zone, kicked.Name,
|
||||
OutfitMembershipResponse(OutfitMembershipResponse.PacketType.Kick, 0, 1,
|
||||
OutfitEvent(kickedBy.outfit_id, Leaving())
|
||||
)
|
||||
|
||||
PlayerControl.sendResponse(kicked.Zone, kicked.Name,
|
||||
OutfitMembershipResponse(OutfitMembershipResponse.PacketType.YouGotKicked, 0, 1,
|
||||
kickedBy.CharId, kicked.CharId, kicked.Name, kickedBy.Name, flag = false))
|
||||
|
||||
kicked.Zone.AvatarEvents ! AvatarServiceMessage(kicked.Zone.id,
|
||||
|
|
@ -251,7 +256,7 @@ object SessionOutfitHandlers {
|
|||
kicked.outfit_id = 0
|
||||
kicked.outfit_name = ""
|
||||
PlayerControl.sendResponse(kicked.Zone, kicked.Name,
|
||||
OutfitMemberEvent(kickedBy.outfit_id, kickedId, OutfitMemberEventAction.Unk1()))
|
||||
OutfitMemberEvent(kickedBy.outfit_id, kickedId, OutfitMemberEventAction.Kicked()))
|
||||
}
|
||||
val avatarName: Future[Option[String]] =
|
||||
ctx.run(
|
||||
|
|
@ -260,15 +265,15 @@ object SessionOutfitHandlers {
|
|||
|
||||
avatarName.foreach {
|
||||
case Some(name) => PlayerControl.sendResponse(kickedBy.Zone, kickedBy.Name,
|
||||
OutfitMembershipResponse(OutfitMembershipResponse.PacketType.Kick, 0, 1, kickedBy.CharId, kickedId, name, "", flag = true))
|
||||
OutfitMembershipResponse(OutfitMembershipResponse.PacketType.YouKicked, 0, 1, kickedBy.CharId, kickedId, name, "", flag = true))
|
||||
|
||||
case None => PlayerControl.sendResponse(kickedBy.Zone, kickedBy.Name,
|
||||
OutfitMembershipResponse(OutfitMembershipResponse.PacketType.Kick, 0, 1, kickedBy.CharId, kickedId, "NameNotFound", "", flag = true))
|
||||
OutfitMembershipResponse(OutfitMembershipResponse.PacketType.YouKicked, 0, 1, kickedBy.CharId, kickedId, "NameNotFound", "", flag = true))
|
||||
}
|
||||
zones.filter(z => z.AllPlayers.nonEmpty).flatMap(_.AllPlayers)
|
||||
.filter(p => p.outfit_id == kickedBy.outfit_id).foreach(outfitMember =>
|
||||
PlayerControl.sendResponse(outfitMember.Zone, outfitMember.Name,
|
||||
OutfitMemberEvent(kickedBy.outfit_id, kickedId, OutfitMemberEventAction.Unk1()))
|
||||
OutfitMemberEvent(kickedBy.outfit_id, kickedId, OutfitMemberEventAction.Kicked()))
|
||||
)
|
||||
// this needs to be the kicked player
|
||||
// session.chat.LeaveChannel(OutfitChannel(kickedBy.outfit_id))
|
||||
|
|
@ -303,7 +308,7 @@ object SessionOutfitHandlers {
|
|||
PlayerControl.sendResponse(
|
||||
zone, outfitMember.Name,
|
||||
OutfitMemberEvent(outfit_id, promoter.avatar.id,
|
||||
OutfitMemberEventAction.Unk0(promoter.Name, 6, owner_points, 0, OutfitMemberEventAction.PacketType.Padding, 0)))
|
||||
OutfitMemberEventAction.Update(promoter.Name, 6, owner_points, 0, OutfitMemberEventAction.PacketType.Padding, 0)))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
@ -327,7 +332,7 @@ object SessionOutfitHandlers {
|
|||
PlayerControl.sendResponse(
|
||||
zone, player.Name,
|
||||
OutfitMemberEvent(outfit_id, promoted.avatar.id,
|
||||
OutfitMemberEventAction.Unk0(promoted.Name, newRank, member_points, 0, OutfitMemberEventAction.PacketType.Padding, 0)))
|
||||
OutfitMemberEventAction.Update(promoted.Name, newRank, member_points, 0, OutfitMemberEventAction.PacketType.Padding, 0)))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
@ -356,7 +361,7 @@ object SessionOutfitHandlers {
|
|||
val seconds: Long = outfit.created.atZone(java.time.ZoneOffset.UTC).toInstant.toEpochMilli / 1000
|
||||
|
||||
PlayerControl.sendResponse(player.Zone, player.Name,
|
||||
OutfitEvent(outfit.id, Unk0(OutfitInfo(
|
||||
OutfitEvent(outfit.id, Initial(OutfitInfo(
|
||||
outfit.name,
|
||||
totalPoints,
|
||||
totalPoints,
|
||||
|
|
@ -382,7 +387,7 @@ object SessionOutfitHandlers {
|
|||
}
|
||||
PlayerControl.sendResponse(player.Zone, player.Name,
|
||||
OutfitMemberEvent(outfit.id, avatarId,
|
||||
OutfitMemberEventAction.Unk0(
|
||||
OutfitMemberEventAction.Update(
|
||||
avatarName,
|
||||
rank,
|
||||
points,
|
||||
|
|
@ -438,7 +443,7 @@ object SessionOutfitHandlers {
|
|||
// send to all online players in outfit
|
||||
val outfit_event = OutfitEvent(
|
||||
outfit_id,
|
||||
Unk2(
|
||||
Update(
|
||||
OutfitInfo(
|
||||
outfit_name = outfit.name,
|
||||
outfit_points1 = totalPoints,
|
||||
|
|
@ -500,7 +505,7 @@ object SessionOutfitHandlers {
|
|||
// send to all online players in outfit
|
||||
val outfit_event = OutfitEvent(
|
||||
outfit_id,
|
||||
Unk2(
|
||||
Update(
|
||||
OutfitInfo(
|
||||
outfit_name = outfit.name,
|
||||
outfit_points1 = totalPoints,
|
||||
|
|
@ -555,7 +560,7 @@ object SessionOutfitHandlers {
|
|||
val seconds: Long = outfit.created.atZone(java.time.ZoneOffset.UTC).toInstant.toEpochMilli / 1000
|
||||
|
||||
PlayerControl.sendResponse(player.Zone, player.Name,
|
||||
OutfitEvent(outfitId, Unk2(OutfitInfo(
|
||||
OutfitEvent(outfitId, Update(OutfitInfo(
|
||||
outfit.name, points, points, memberCount,
|
||||
OutfitRankNames(outfit.rank0.getOrElse(""), outfit.rank1.getOrElse(""), outfit.rank2.getOrElse(""),
|
||||
outfit.rank3.getOrElse(""), outfit.rank4.getOrElse(""), outfit.rank5.getOrElse(""),
|
||||
|
|
@ -744,7 +749,7 @@ object SessionOutfitHandlers {
|
|||
}
|
||||
}
|
||||
|
||||
def updateMemberRankById(outfit_id: Long, avatar_id: Long, rank: Int): Quoted[Update[Outfitmember]] = quote {
|
||||
def updateMemberRankById(outfit_id: Long, avatar_id: Long, rank: Int): Quoted[io.getquill.Update[Outfitmember]] = quote {
|
||||
query[Outfitmember]
|
||||
.filter(_.outfit_id == lift(outfit_id))
|
||||
.filter(_.avatar_id == lift(avatar_id))
|
||||
|
|
@ -759,7 +764,7 @@ object SessionOutfitHandlers {
|
|||
}
|
||||
}
|
||||
|
||||
def updateOutfitOwnerById(outfit_id: Long, owner_id: Long): Quoted[Update[Outfit]] = quote {
|
||||
def updateOutfitOwnerById(outfit_id: Long, owner_id: Long): Quoted[io.getquill.Update[Outfit]] = quote {
|
||||
query[Outfit]
|
||||
.filter(_.id == lift(outfit_id))
|
||||
.update(_.owner_id -> lift(owner_id))
|
||||
|
|
@ -775,7 +780,7 @@ object SessionOutfitHandlers {
|
|||
}
|
||||
}
|
||||
|
||||
def updateOutfitMotdById(outfit_id: Long, motd: Option[String]): Quoted[Update[Outfit]] = quote {
|
||||
def updateOutfitMotdById(outfit_id: Long, motd: Option[String]): Quoted[io.getquill.Update[Outfit]] = quote {
|
||||
query[Outfit]
|
||||
.filter(_.id == lift(outfit_id))
|
||||
.update(_.motd -> lift(motd))
|
||||
|
|
@ -789,7 +794,7 @@ object SessionOutfitHandlers {
|
|||
}
|
||||
}
|
||||
|
||||
def updateOutfitRanksById(outfit_id: Long, list: List[Option[String]]): Quoted[Update[Outfit]] = {
|
||||
def updateOutfitRanksById(outfit_id: Long, list: List[Option[String]]): Quoted[io.getquill.Update[Outfit]] = {
|
||||
|
||||
// Normalize: turn empty strings into None
|
||||
val normalized = list.map {
|
||||
|
|
|
|||
|
|
@ -50,26 +50,55 @@ object OutfitEventAction {
|
|||
unk25: Long,
|
||||
)
|
||||
|
||||
final case class Unk0(
|
||||
/**
|
||||
* Initial
|
||||
*
|
||||
* Send at the start of an OutfitWindow info dump.
|
||||
*
|
||||
* Not always complete, seen as an initialization after login, join or while outfit is in formation.
|
||||
* @param outfit_info
|
||||
*/
|
||||
final case class Initial(
|
||||
outfit_info: OutfitInfo
|
||||
) extends OutfitEventAction(code = 0)
|
||||
|
||||
final case class Unk1(
|
||||
) extends OutfitEventAction(code = 1)
|
||||
|
||||
final case class Unk2(
|
||||
/**
|
||||
* Update
|
||||
*
|
||||
* Send after changing outfit Ranks, MOTD and other situations.
|
||||
* @param outfit_info
|
||||
*/
|
||||
final case class Update(
|
||||
outfit_info: OutfitInfo,
|
||||
) extends OutfitEventAction(code = 2)
|
||||
|
||||
final case class Unk3(
|
||||
/**
|
||||
* Send to players to tell them they left the outfit.
|
||||
*
|
||||
* Resets them to behave like they have no outfit.
|
||||
* Will have them open the OutfitListWindow instead of the OutfitWindow.
|
||||
*/
|
||||
final case class Leaving(
|
||||
) extends OutfitEventAction(code = 3)
|
||||
|
||||
/**
|
||||
* Used to switch from the temporary "invalid" outfit ID used while formation to a valid ID used from that point on.
|
||||
* @param new_outfit_id the new ID that represents this specific outfit in the DB
|
||||
*/
|
||||
final case class UpdateOutfitId(
|
||||
new_outfit_id: Long,
|
||||
) extends OutfitEventAction(code = 4)
|
||||
|
||||
final case class Unk5(
|
||||
unk1: Long,
|
||||
/**
|
||||
* Used to tell outfit members that the member count changed.
|
||||
* Send after InviteAccept or Kick actions
|
||||
* @param member_count
|
||||
*/
|
||||
final case class UpdateMemberCount(
|
||||
member_count: Long,
|
||||
) extends OutfitEventAction(code = 5)
|
||||
|
||||
final case class Unknown(badCode: Int, data: BitVector) extends OutfitEventAction(badCode)
|
||||
|
|
@ -126,35 +155,35 @@ object OutfitEventAction {
|
|||
}
|
||||
)
|
||||
|
||||
val Unk0Codec: Codec[Unk0] = (
|
||||
val Unk0Codec: Codec[Initial] = (
|
||||
("outfit_info" | InfoCodec)
|
||||
).xmap[Unk0](
|
||||
).xmap[Initial](
|
||||
{
|
||||
case info =>
|
||||
Unk0(info)
|
||||
Initial(info)
|
||||
},
|
||||
{
|
||||
case Unk0(info) =>
|
||||
case Initial(info) =>
|
||||
info
|
||||
}
|
||||
)
|
||||
|
||||
val Unk1Codec: Codec[Unk1] = PacketHelpers.emptyCodec(Unk1())
|
||||
|
||||
val Unk2Codec: Codec[Unk2] = (
|
||||
val Unk2Codec: Codec[Update] = (
|
||||
("outfit_info" | InfoCodec)
|
||||
).xmap[Unk2](
|
||||
).xmap[Update](
|
||||
{
|
||||
case info =>
|
||||
Unk2(info)
|
||||
Update(info)
|
||||
},
|
||||
{
|
||||
case Unk2(info) =>
|
||||
case Update(info) =>
|
||||
info
|
||||
}
|
||||
)
|
||||
|
||||
val Unk3Codec: Codec[Unk3] = PacketHelpers.emptyCodec(Unk3())
|
||||
val Unk3Codec: Codec[Leaving] = PacketHelpers.emptyCodec(Leaving())
|
||||
|
||||
val UpdateOutfitIdCodec: Codec[UpdateOutfitId] = ( // update outfit_id? // 2016.03.18 #10640 // after this packet the referenced id changes to the new one, old is not used again
|
||||
("new_outfit_id" | uint32L)
|
||||
|
|
@ -169,15 +198,15 @@ object OutfitEventAction {
|
|||
}
|
||||
)
|
||||
|
||||
val Unk5Codec: Codec[Unk5] = (
|
||||
val UpdateMemberCountCodec: Codec[UpdateMemberCount] = (
|
||||
("" | uint32L)
|
||||
).xmap[Unk5](
|
||||
).xmap[UpdateMemberCount](
|
||||
{
|
||||
case u1 =>
|
||||
Unk5(u1)
|
||||
UpdateMemberCount(u1)
|
||||
},
|
||||
{
|
||||
case Unk5(u1) =>
|
||||
case UpdateMemberCount(u1) =>
|
||||
u1
|
||||
}
|
||||
)
|
||||
|
|
@ -220,7 +249,7 @@ object OutfitEvent extends Marshallable[OutfitEvent] {
|
|||
val Unk2: PacketType.Value = Value(2) // send after creating an outfit // normal info, same as Unk0
|
||||
val Unk3: PacketType.Value = Value(3) // below
|
||||
val UpdateOutfitId: PacketType.Value = Value(4)
|
||||
val Unk5: PacketType.Value = Value(5)
|
||||
val UpdateMemberCount: PacketType.Value = Value(5)
|
||||
val Unk6: PacketType.Value = Value(6)
|
||||
val Unk7: PacketType.Value = Value(7)
|
||||
|
||||
|
|
@ -237,7 +266,7 @@ object OutfitEvent extends Marshallable[OutfitEvent] {
|
|||
case 2 => Unk2Codec // sent after /outfitcreate and on login if in an outfit
|
||||
case 3 => Unk3Codec
|
||||
case 4 => UpdateOutfitIdCodec
|
||||
case 5 => Unk5Codec
|
||||
case 5 => UpdateMemberCountCodec
|
||||
case 6 => unknownCodec(action = code)
|
||||
case 7 => unknownCodec(action = code)
|
||||
|
||||
|
|
|
|||
|
|
@ -33,20 +33,30 @@ object OutfitMemberEventAction {
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
action is unimplemented! if action == 0 unk2 will contain one additional uint32L
|
||||
padding contains one uint4L of padding. may contain uint32L of unknown data depending on action
|
||||
*/
|
||||
final case class Unk0(
|
||||
/**
|
||||
*
|
||||
* Update
|
||||
*
|
||||
* Update is used to inform outfit members about a new member.
|
||||
* Gets send after an InviteAccept or Rank changes.
|
||||
*
|
||||
* @param member_name
|
||||
* @param rank
|
||||
* @param points client divides this by 100
|
||||
* @param last_online seconds ago from current time, 0 if online
|
||||
* @param action should always be 1, otherwise there will be actual data in padding. not implemented!
|
||||
* @param padding should always be 0, 4 bits of padding // only contains data if action is 0
|
||||
*/
|
||||
final case class Update(
|
||||
member_name: String,
|
||||
rank: Int,
|
||||
points: Long, // client divides this by 100
|
||||
last_online: Long, // seconds ago from current time, 0 if online
|
||||
action: PacketType.Type, // should always be 1, otherwise there will be actual data in padding. not implemented!
|
||||
padding: Int // should always be 0, 4 bits of padding // only contains data if action is 0
|
||||
points: Long,
|
||||
last_online: Long,
|
||||
action: PacketType.Type,
|
||||
padding: Int
|
||||
) extends OutfitMemberEventAction(code = 0)
|
||||
|
||||
final case class Unk1(
|
||||
final case class Kicked(
|
||||
) extends OutfitMemberEventAction(code = 1)
|
||||
|
||||
final case class Unknown(badCode: Int, data: BitVector) extends OutfitMemberEventAction(badCode)
|
||||
|
|
@ -58,25 +68,25 @@ object OutfitMemberEventAction {
|
|||
object Codecs {
|
||||
private val everFailCondition = conditional(included = false, bool)
|
||||
|
||||
val Unk0Codec: Codec[Unk0] = (
|
||||
("member_name" | PacketHelpers.encodedWideStringAligned(6)) :: // from here is packet_type == 0 only
|
||||
val UpdateCodec: Codec[Update] = (
|
||||
("member_name" | PacketHelpers.encodedWideStringAligned(6)) ::
|
||||
("rank" | uint(3)) ::
|
||||
("points" | uint32L) ::
|
||||
("last_login" | uint32L) ::
|
||||
("action" | OutfitMemberEventAction.PacketType.codec) ::
|
||||
("padding" | uint4L)
|
||||
).xmap[Unk0](
|
||||
).xmap[Update](
|
||||
{
|
||||
case member_name :: rank :: points :: last_login :: action :: padding :: HNil =>
|
||||
Unk0(member_name, rank, points, last_login, action, padding)
|
||||
Update(member_name, rank, points, last_login, action, padding)
|
||||
},
|
||||
{
|
||||
case Unk0(member_name, rank, points, last_login, action, padding) =>
|
||||
case Update(member_name, rank, points, last_login, action, padding) =>
|
||||
member_name :: rank :: points :: last_login :: action :: padding :: HNil
|
||||
}
|
||||
)
|
||||
|
||||
val Unk1Codec: Codec[Unk1] = PacketHelpers.emptyCodec(Unk1())
|
||||
val KickedCodec: Codec[Kicked] = PacketHelpers.emptyCodec(Kicked())
|
||||
|
||||
/**
|
||||
* A common form for known action code indexes with an unknown purpose and transformation is an "Unknown" object.
|
||||
|
|
@ -109,8 +119,8 @@ object OutfitMemberEvent extends Marshallable[OutfitMemberEvent] {
|
|||
object PacketType extends Enumeration {
|
||||
type Type = Value
|
||||
|
||||
val Unk0: PacketType.Value = Value(0)
|
||||
val Unk1: PacketType.Value = Value(1) // Info: Player has been invited / response to OutfitMembershipRequest Unk2 for that player
|
||||
val Update: PacketType.Value = Value(0)
|
||||
val Kicked: PacketType.Value = Value(1)
|
||||
val Unk2: PacketType.Value = Value(2)
|
||||
val Unk3: PacketType.Value = Value(3)
|
||||
|
||||
|
|
@ -122,8 +132,8 @@ object OutfitMemberEvent extends Marshallable[OutfitMemberEvent] {
|
|||
import scala.annotation.switch
|
||||
|
||||
((code: @switch) match {
|
||||
case 0 => Unk0Codec
|
||||
case 1 => Unk1Codec
|
||||
case 0 => UpdateCodec
|
||||
case 1 => KickedCodec
|
||||
case 2 => unknownCodec(code)
|
||||
case 3 => unknownCodec(code)
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import scodec.codecs._
|
|||
import shapeless.{::, HNil}
|
||||
|
||||
final case class OutfitMembershipRequest(
|
||||
outfit_id: Long,
|
||||
requester_id: Long,
|
||||
action: OutfitMembershipRequestAction
|
||||
) extends PlanetSideGamePacket {
|
||||
type Packet = OutfitMembershipRequest
|
||||
|
|
@ -37,8 +37,8 @@ object OutfitMembershipRequestAction {
|
|||
) extends OutfitMembershipRequestAction(code = 1)
|
||||
|
||||
final case class Invite(
|
||||
avatar_id: Long,
|
||||
member_name: String,
|
||||
target_id: Long,
|
||||
target_name: String,
|
||||
) extends OutfitMembershipRequestAction(code = 2)
|
||||
|
||||
final case class AcceptInvite(
|
||||
|
|
@ -50,19 +50,19 @@ object OutfitMembershipRequestAction {
|
|||
) extends OutfitMembershipRequestAction(code = 4)
|
||||
|
||||
final case class CancelInvite(
|
||||
avatar_id: Long,
|
||||
member_name: String,
|
||||
target_id: Long,
|
||||
target_name: String,
|
||||
) extends OutfitMembershipRequestAction(code = 5)
|
||||
|
||||
final case class Kick(
|
||||
avatar_id: Long,
|
||||
member_name: String,
|
||||
target_id: Long,
|
||||
target_name: String,
|
||||
) extends OutfitMembershipRequestAction(code = 6)
|
||||
|
||||
final case class SetRank(
|
||||
avatar_id: Long,
|
||||
target_id: Long,
|
||||
rank: Int,
|
||||
member_name: String,
|
||||
target_name: String,
|
||||
) extends OutfitMembershipRequestAction(code = 7)
|
||||
|
||||
final case class Unknown(badCode: Int, data: BitVector) extends OutfitMembershipRequestAction(badCode)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ final case class OutfitMembershipResponse(
|
|||
packet_type: OutfitMembershipResponse.PacketType.Type,
|
||||
unk0: Int,
|
||||
unk1: Int,
|
||||
outfit_id: Long,
|
||||
requester_id: Long,
|
||||
target_id: Long,
|
||||
str1: String,
|
||||
str2: String,
|
||||
|
|
@ -34,8 +34,8 @@ object OutfitMembershipResponse extends Marshallable[OutfitMembershipResponse] {
|
|||
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 YouGotKicked: PacketType.Value = Value(4)
|
||||
val YouKicked: PacketType.Value = Value(5)
|
||||
val Unk6: PacketType.Value = Value(6) // 6 and 7 seen as failed decodes, validity unknown
|
||||
val Unk7: PacketType.Value = Value(7)
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import scodec.codecs._
|
|||
import shapeless.{::, HNil}
|
||||
|
||||
final case class OutfitRequest(
|
||||
outfit_id: Long,
|
||||
requester_id: Long,
|
||||
action: OutfitRequestAction
|
||||
) extends PlanetSideGamePacket {
|
||||
type Packet = OutfitRequest
|
||||
|
|
@ -42,13 +42,13 @@ object OutfitRequestAction {
|
|||
* na
|
||||
* @param unk na
|
||||
*/
|
||||
final case class Unk3(menuOpen: Boolean) extends OutfitRequestAction(code = 3)
|
||||
final case class OutfitWindowOpen(menuOpen: Boolean) extends OutfitRequestAction(code = 3)
|
||||
|
||||
/**
|
||||
* na
|
||||
* @param unk na
|
||||
*/
|
||||
final case class Unk4(menuOpen: Boolean) extends OutfitRequestAction(code = 4)
|
||||
final case class OutfitListWindowOpen(menuOpen: Boolean) extends OutfitRequestAction(code = 4)
|
||||
|
||||
/**
|
||||
* na
|
||||
|
|
@ -116,24 +116,24 @@ object OutfitRequest extends Marshallable[OutfitRequest] {
|
|||
/**
|
||||
* na
|
||||
*/
|
||||
private val unk3Codec: Codec[OutfitRequestAction] = bool.hlist.xmap[OutfitRequestAction] (
|
||||
private val OutfitWindowOpenCodec: Codec[OutfitRequestAction] = bool.hlist.xmap[OutfitRequestAction] (
|
||||
{
|
||||
case value :: HNil => OutfitRequestAction.Unk3(value)
|
||||
case value :: HNil => OutfitRequestAction.OutfitWindowOpen(value)
|
||||
},
|
||||
{
|
||||
case OutfitRequestAction.Unk3(value) => value :: HNil
|
||||
case OutfitRequestAction.OutfitWindowOpen(value) => value :: HNil
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* na
|
||||
*/
|
||||
private val unk4Codec: Codec[OutfitRequestAction] = bool.hlist.xmap[OutfitRequestAction] (
|
||||
private val OutfitListWindowOpenCodec: Codec[OutfitRequestAction] = bool.hlist.xmap[OutfitRequestAction] (
|
||||
{
|
||||
case value :: HNil => OutfitRequestAction.Unk4(value)
|
||||
case value :: HNil => OutfitRequestAction.OutfitListWindowOpen(value)
|
||||
},
|
||||
{
|
||||
case OutfitRequestAction.Unk4(value) => value :: HNil
|
||||
case OutfitRequestAction.OutfitListWindowOpen(value) => value :: HNil
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -151,8 +151,8 @@ object OutfitRequest extends Marshallable[OutfitRequest] {
|
|||
val Motd: PacketType.Value = Value(0)
|
||||
val Rank: PacketType.Value = Value(1)
|
||||
val Unk2: PacketType.Value = Value(2)
|
||||
val Detail: PacketType.Value = Value(3)
|
||||
val List: PacketType.Value = Value(4) // sent by client if menu is either open (true) or closed (false)
|
||||
val OutfitWindowOpen: PacketType.Value = Value(3)
|
||||
val OutfitListWindowOpen: PacketType.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))
|
||||
}
|
||||
|
|
@ -165,8 +165,8 @@ object OutfitRequest extends Marshallable[OutfitRequest] {
|
|||
case 0 => MotdCodec
|
||||
case 1 => RankCodec
|
||||
case 2 => unk2Codec
|
||||
case 3 => unk3Codec
|
||||
case 4 => unk4Codec
|
||||
case 3 => OutfitWindowOpenCodec
|
||||
case 4 => OutfitListWindowOpenCodec
|
||||
case _ => failCodec(code)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ class OutfitEventTest extends Specification {
|
|||
PacketCoding.decodePacket(unk0_ABC).require match {
|
||||
case OutfitEvent(outfit_guid, action) =>
|
||||
outfit_guid mustEqual 25044
|
||||
action mustEqual Unk0(
|
||||
action mustEqual Initial(
|
||||
OutfitInfo(
|
||||
outfit_name = "Black Armored Reapers",
|
||||
outfit_points1 = 223190045,
|
||||
|
|
@ -78,7 +78,7 @@ class OutfitEventTest extends Specification {
|
|||
"encode Unk0 ABC" in {
|
||||
val msg = OutfitEvent(
|
||||
25044,
|
||||
Unk0(
|
||||
Initial(
|
||||
OutfitInfo(
|
||||
outfit_name = "Black Armored Reapers",
|
||||
outfit_points1 = 223190045,
|
||||
|
|
@ -125,7 +125,7 @@ class OutfitEventTest extends Specification {
|
|||
PacketCoding.decodePacket(unk2_ABC).require match {
|
||||
case OutfitEvent(outfit_guid, action) =>
|
||||
outfit_guid mustEqual 2147418113L
|
||||
action mustEqual Unk2(OutfitInfo(
|
||||
action mustEqual Update(OutfitInfo(
|
||||
outfit_name = "PlanetSide_Forever_Vanu",
|
||||
outfit_points1 = 0,
|
||||
outfit_points2 = 0,
|
||||
|
|
@ -148,7 +148,7 @@ class OutfitEventTest extends Specification {
|
|||
"encode Unk2 ABC" in {
|
||||
val msg = OutfitEvent(
|
||||
2147418113L,
|
||||
Unk2(
|
||||
Update(
|
||||
OutfitInfo(
|
||||
outfit_name = "PlanetSide_Forever_Vanu",
|
||||
outfit_points1 = 0,
|
||||
|
|
@ -175,7 +175,7 @@ class OutfitEventTest extends Specification {
|
|||
PacketCoding.decodePacket(unk3_ABC).require match {
|
||||
case OutfitEvent(outfit_guid, action) =>
|
||||
outfit_guid mustEqual 2147418113L
|
||||
action mustEqual Unk3()
|
||||
action mustEqual Leaving()
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
|
|
@ -184,7 +184,7 @@ class OutfitEventTest extends Specification {
|
|||
"encode Unk3 ABC" in {
|
||||
val msg = OutfitEvent(
|
||||
2147418113L,
|
||||
Unk3()
|
||||
Leaving()
|
||||
)
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
|
||||
|
|
@ -219,8 +219,8 @@ class OutfitEventTest extends Specification {
|
|||
PacketCoding.decodePacket(unk5_ABC).require match {
|
||||
case OutfitEvent(outfit_guid, action) =>
|
||||
outfit_guid mustEqual 2147418113L
|
||||
action mustEqual Unk5(
|
||||
unk1 = 2,
|
||||
action mustEqual UpdateMemberCount(
|
||||
member_count = 2,
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
|
|
@ -230,8 +230,8 @@ class OutfitEventTest extends Specification {
|
|||
"encode Unk5 ABC" in {
|
||||
val msg = OutfitEvent(
|
||||
2147418113L,
|
||||
Unk5(
|
||||
unk1 = 2,
|
||||
UpdateMemberCount(
|
||||
member_count = 2,
|
||||
)
|
||||
)
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class OutfitMemberEventTest extends Specification {
|
|||
|
||||
"decode Lazer padding" in {
|
||||
PacketCoding.decodePacket(Lazer).require match {
|
||||
case OutfitMemberEvent(outfit_id, member_id, Unk0(member_name, rank, points, last_login, action, padding)) =>
|
||||
case OutfitMemberEvent(outfit_id, member_id, Update(member_name, rank, points, last_login, action, padding)) =>
|
||||
outfit_id mustEqual 6418
|
||||
member_id mustEqual 705344
|
||||
member_name mustEqual "Lazer1982"
|
||||
|
|
@ -40,7 +40,7 @@ class OutfitMemberEventTest extends Specification {
|
|||
val msg = OutfitMemberEvent(
|
||||
outfit_id = 6418,
|
||||
member_id = 705344,
|
||||
Unk0(
|
||||
Update(
|
||||
member_name = "Lazer1982",
|
||||
rank = 7,
|
||||
points = 3134113,
|
||||
|
|
@ -56,7 +56,7 @@ class OutfitMemberEventTest extends Specification {
|
|||
|
||||
"decode OpolE padding" in {
|
||||
PacketCoding.decodePacket(OpolE).require match {
|
||||
case OutfitMemberEvent(outfit_id, member_id, Unk0(member_name, rank, points, last_login, action, unk0_padding)) =>
|
||||
case OutfitMemberEvent(outfit_id, member_id, Update(member_name, rank, points, last_login, action, unk0_padding)) =>
|
||||
outfit_id mustEqual 6418
|
||||
member_id mustEqual 42644970
|
||||
member_name mustEqual "OpolE"
|
||||
|
|
@ -74,7 +74,7 @@ class OutfitMemberEventTest extends Specification {
|
|||
val msg = OutfitMemberEvent(
|
||||
outfit_id = 6418,
|
||||
member_id = 42644970,
|
||||
Unk0(
|
||||
Update(
|
||||
member_name = "OpolE",
|
||||
rank = 6,
|
||||
points = 461901,
|
||||
|
|
@ -91,7 +91,7 @@ class OutfitMemberEventTest extends Specification {
|
|||
|
||||
"decode Unk1" in {
|
||||
PacketCoding.decodePacket(unk1).require match {
|
||||
case OutfitMemberEvent(outfit_id, member_id, Unk1()) =>
|
||||
case OutfitMemberEvent(outfit_id, member_id, Kicked()) =>
|
||||
outfit_id mustEqual 529744
|
||||
member_id mustEqual 41605263
|
||||
case _ =>
|
||||
|
|
@ -103,7 +103,7 @@ class OutfitMemberEventTest extends Specification {
|
|||
val msg = OutfitMemberEvent(
|
||||
outfit_id = 529744,
|
||||
member_id = 41605263,
|
||||
Unk1()
|
||||
Kicked()
|
||||
)
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ class OutfitMembershipResponseTest extends Specification {
|
|||
"decode unk4" in {
|
||||
PacketCoding.decodePacket(unk4).require match {
|
||||
case OutfitMembershipResponse(packet_type, unk0, unk1, outfit_id, target_id, str1, str2, flag) =>
|
||||
packet_type mustEqual PacketType.Unk4
|
||||
packet_type mustEqual PacketType.YouGotKicked
|
||||
unk0 mustEqual 0
|
||||
unk1 mustEqual 0
|
||||
outfit_id mustEqual 41593365
|
||||
|
|
@ -125,7 +125,7 @@ class OutfitMembershipResponseTest extends Specification {
|
|||
}
|
||||
|
||||
"encode unk4" in {
|
||||
val msg = OutfitMembershipResponse(PacketType.Unk4, 0, 0, 41593365, 0, "", "", flag = true)
|
||||
val msg = OutfitMembershipResponse(PacketType.YouGotKicked, 0, 0, 41593365, 0, "", "", flag = true)
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual unk4
|
||||
|
|
@ -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.Kick
|
||||
packet_type mustEqual PacketType.YouKicked
|
||||
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.Kick, 0, 1, 41593365, 41605263, "PSFoutfittest1", "", flag = true)
|
||||
val msg = OutfitMembershipResponse(PacketType.YouKicked, 0, 1, 41593365, 41605263, "PSFoutfittest1", "", flag = true)
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual unk5
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ class OutfitRequestTest extends Specification {
|
|||
|
||||
"decode Unk3" in {
|
||||
PacketCoding.decodePacket(string6).require match {
|
||||
case OutfitRequest(id, OutfitRequestAction.Unk3(value)) =>
|
||||
case OutfitRequest(id, OutfitRequestAction.OutfitWindowOpen(value)) =>
|
||||
id mustEqual 1176612L
|
||||
value mustEqual true
|
||||
case _ =>
|
||||
|
|
@ -56,7 +56,7 @@ class OutfitRequestTest extends Specification {
|
|||
|
||||
"decode Unk4" in {
|
||||
PacketCoding.decodePacket(string8).require match {
|
||||
case OutfitRequest(id, OutfitRequestAction.Unk4(value)) =>
|
||||
case OutfitRequest(id, OutfitRequestAction.OutfitListWindowOpen(value)) =>
|
||||
id mustEqual 41588237L
|
||||
value mustEqual true
|
||||
case _ =>
|
||||
|
|
@ -88,14 +88,14 @@ class OutfitRequestTest extends Specification {
|
|||
}
|
||||
|
||||
"encode Unk3" in {
|
||||
val msg = OutfitRequest(1176612L, OutfitRequestAction.Unk3(true))
|
||||
val msg = OutfitRequest(1176612L, OutfitRequestAction.OutfitWindowOpen(true))
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string6
|
||||
}
|
||||
|
||||
"encode Unk4" in {
|
||||
val msg = OutfitRequest(41588237L, OutfitRequestAction.Unk4(true))
|
||||
val msg = OutfitRequest(41588237L, OutfitRequestAction.OutfitListWindowOpen(true))
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string8
|
||||
|
|
|
|||
Loading…
Reference in a new issue