From c0428bd3f631d9d3fa7a6b14e13c840732c5dd8a Mon Sep 17 00:00:00 2001 From: Resaec Date: Sun, 31 Aug 2025 23:37:30 +0200 Subject: [PATCH] add outfit (list) window event subscription handling fix Kicked action send instead of Leaving action when players leave on their own --- .../actors/session/normal/GeneralLogic.scala | 6 ++ .../support/SessionOutfitHandlers.scala | 72 ++++++++++++------- .../scala/net/psforever/objects/Player.scala | 2 + 3 files changed, 54 insertions(+), 26 deletions(-) diff --git a/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala b/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala index a2f87cd16..6be7ec0eb 100644 --- a/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala +++ b/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala @@ -837,13 +837,19 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex SessionOutfitHandlers.HandleOutfitRank(zones, List(r1, r2, r3, r4, r5, r6, r7, r8), player) case OutfitRequest(_, OutfitRequestAction.OutfitWindowOpen(true)) => + player.outfit_window_open = true SessionOutfitHandlers.HandleViewOutfitWindow(zones, player, player.outfit_id) case OutfitRequest(_, OutfitRequestAction.OutfitWindowOpen(false)) => + player.outfit_window_open = false case OutfitRequest(_, OutfitRequestAction.OutfitListWindowOpen(true)) => + player.outfit_list_open = true SessionOutfitHandlers.HandleGetOutfitList(player) + case OutfitRequest(_, OutfitRequestAction.OutfitListWindowOpen(false)) => + player.outfit_list_open = false + case _ => } } diff --git a/src/main/scala/net/psforever/actors/session/support/SessionOutfitHandlers.scala b/src/main/scala/net/psforever/actors/session/support/SessionOutfitHandlers.scala index bafd60be9..be3530ae9 100644 --- a/src/main/scala/net/psforever/actors/session/support/SessionOutfitHandlers.scala +++ b/src/main/scala/net/psforever/actors/session/support/SessionOutfitHandlers.scala @@ -1,11 +1,11 @@ // Copyright (c) 2025 PSForever package net.psforever.actors.session.support -import io.getquill.{ActionReturning, EntityQuery, Insert, PostgresJAsyncContext, Query, Quoted, SnakeCase, Update} +import io.getquill.{Action, ActionReturning, EntityQuery, Insert, PostgresJAsyncContext, Query, Quoted, SnakeCase} import net.psforever.objects.avatar.PlayerControl import net.psforever.objects.zones.Zone import net.psforever.objects.Player -import net.psforever.packet.game.OutfitEventAction.{Leaving, OutfitInfo, OutfitRankNames, Initial, Unk1, Update, UpdateMemberCount} +import net.psforever.packet.game.OutfitEventAction.{Initial, Leaving, OutfitInfo, OutfitRankNames, Unk1, Update, UpdateMemberCount} import net.psforever.packet.game.OutfitMembershipResponse.PacketType.CreateResponse import net.psforever.packet.game._ import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage} @@ -207,22 +207,28 @@ object SessionOutfitHandlers { def HandleOutfitKick(zones: Seq[Zone], kickedId: Long, kickedBy: Player, session: SessionData): Unit = { // if same id, player has left the outfit by their own choice if (kickedId == kickedBy.CharId) { - removeMemberFromOutfit(kickedBy.outfit_id, kickedId).map { + + // store outfit_id since it will be nulled soon + val outfit_id = kickedBy.outfit_id + + removeMemberFromOutfit(outfit_id, kickedId).map { case (deleted, _) => if (deleted > 0) { - PlayerControl.sendResponse(kickedBy.Zone, kickedBy.Name, - 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.Kicked())) + PlayerControl.sendResponse(kickedBy.Zone, kickedBy.Name, + OutfitEvent(outfit_id, Leaving()) ) - session.chat.LeaveChannel(OutfitChannel(kickedBy.outfit_id)) + session.chat.LeaveChannel(OutfitChannel(outfit_id)) kickedBy.outfit_name = "" kickedBy.outfit_id = 0 + zones.filter(z => z.AllPlayers.nonEmpty).flatMap(_.AllPlayers) + .filter(p => p.outfit_id == outfit_id).foreach(outfitMember => + PlayerControl.sendResponse(outfitMember.Zone, outfitMember.Name, + OutfitMemberEvent(outfit_id, kickedId, OutfitMemberEventAction.Kicked())) + ) + kickedBy.Zone.AvatarEvents ! AvatarServiceMessage(kickedBy.Zone.id, AvatarAction.PlanetsideAttributeToAll(kickedBy.GUID, 39, 0)) @@ -304,13 +310,15 @@ object SessionOutfitHandlers { 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.Update(promoter.Name, 6, owner_points, 0, OutfitMemberEventAction.PacketType.Padding, 0))) - }) - }) + zone.AllPlayers + .filter(_.outfit_id == outfit_id) + .foreach(outfitMember => { + PlayerControl.sendResponse( + zone, outfitMember.Name, + OutfitMemberEvent(outfit_id, promoter.avatar.id, + OutfitMemberEventAction.Update(promoter.Name, 6, owner_points, 0, OutfitMemberEventAction.PacketType.Padding, 0))) + }) + }) } // update promoter rank @@ -328,12 +336,14 @@ object SessionOutfitHandlers { 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.Update(promoted.Name, newRank, member_points, 0, OutfitMemberEventAction.PacketType.Padding, 0))) - }) + zone.AllPlayers + .filter(_.outfit_id == outfit_id) + .foreach(player => { + PlayerControl.sendResponse( + zone, player.Name, + OutfitMemberEvent(outfit_id, promoted.avatar.id, + OutfitMemberEventAction.Update(promoted.Name, newRank, member_points, 0, OutfitMemberEventAction.PacketType.Padding, 0))) + }) }) } @@ -472,7 +482,10 @@ object SessionOutfitHandlers { ) zones.foreach(zone => { - zone.AllPlayers.filter(_.outfit_id == outfit_id).foreach(player => { + zone.AllPlayers + .filter(_.outfit_id == outfit_id) + .filter(_.outfit_window_open) + .foreach(player => { PlayerControl.sendResponse( zone, player.Name, outfit_event @@ -502,7 +515,7 @@ object SessionOutfitHandlers { } yield { outfitOpt.foreach { outfit => - // send to all online players in outfit + // send to all online players in outfit with window open val outfit_event = OutfitEvent( outfit_id, Update( @@ -534,7 +547,10 @@ object SessionOutfitHandlers { ) zones.foreach(zone => { - zone.AllPlayers.filter(_.outfit_id == outfit_id).foreach(player => { + zone.AllPlayers + .filter(_.outfit_id == outfit_id) + .filter(_.outfit_window_open) + .foreach(player => { PlayerControl.sendResponse( zone, player.Name, outfit_event @@ -823,4 +839,8 @@ object SessionOutfitHandlers { } yield () } } + + def updateOutfitPointMV(): Quoted[Action[Unit]] = quote( + infix"REFRESH MATERIALIZED VIEW outfitpoint_mv".as[Action[Unit]] + ) } diff --git a/src/main/scala/net/psforever/objects/Player.scala b/src/main/scala/net/psforever/objects/Player.scala index 074937edd..3cdb1b47f 100644 --- a/src/main/scala/net/psforever/objects/Player.scala +++ b/src/main/scala/net/psforever/objects/Player.scala @@ -87,6 +87,8 @@ class Player(var avatar: Avatar) var lastShotSeq_time: Int = -1 var outfit_name: String = "" var outfit_id: Long = 0 + var outfit_window_open: Boolean = false + var outfit_list_open: Boolean = false /** From PlanetsideAttributeMessage */ var PlanetsideAttribute: Array[Long] = Array.ofDim(120)