diff --git a/server/src/main/java/net/psforever/filters/ApplyCooldownToDuplicateLoggingFilter.java b/server/src/main/java/net/psforever/filters/ApplyCooldownToDuplicateLoggingFilter.java index 733b504b7..e13f324a5 100644 --- a/server/src/main/java/net/psforever/filters/ApplyCooldownToDuplicateLoggingFilter.java +++ b/server/src/main/java/net/psforever/filters/ApplyCooldownToDuplicateLoggingFilter.java @@ -43,8 +43,8 @@ public class ApplyCooldownToDuplicateLoggingFilter extends Filter } public void setCleaning(Long duration) { + housecleaningTime = housecleaningTime - cleaning + duration; cleaning = duration; - housecleaningTime = System.currentTimeMillis() + cleaning; } private void runCleaning() { @@ -58,6 +58,14 @@ public class ApplyCooldownToDuplicateLoggingFilter extends Filter } } + @Override + public void start() { + if (this.cooldown != 0L) { + messageMap = new ConcurrentHashMap<>(1000); + super.start(); + } + } + @Override public void stop() { messageMap.clear(); diff --git a/src/main/scala/net/psforever/actors/session/SessionActor.scala b/src/main/scala/net/psforever/actors/session/SessionActor.scala index 32e1345a0..786a48cbb 100644 --- a/src/main/scala/net/psforever/actors/session/SessionActor.scala +++ b/src/main/scala/net/psforever/actors/session/SessionActor.scala @@ -2463,6 +2463,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con reply match { case Mountable.CanMount(obj: ImplantTerminalMech, seat_number, _) => CancelZoningProcessWithDescriptiveReason("cancel_use") + log.info(s"${player.Name} mounts an implant terminal") CancelAllProximityUnits() MountingAction(tplayer, obj, seat_number) keepAliveFunc = KeepAlivePersistence @@ -2470,14 +2471,21 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con case Mountable.CanMount(obj: Vehicle, seat_number, _) if obj.Definition == GlobalDefinitions.orbital_shuttle => CancelZoningProcessWithDescriptiveReason("cancel_mount") + log.info(s"${player.Name} mounts the orbital shuttle") CancelAllProximityUnits() MountingAction(tplayer, obj, seat_number) keepAliveFunc = KeepAlivePersistence case Mountable.CanMount(obj: Vehicle, seat_number, _) => CancelZoningProcessWithDescriptiveReason("cancel_mount") + log.info(s"${player.Name} mounts ${obj.Definition.Name} in ${ + obj.SeatPermissionGroup(seat_number) match { + case Some(AccessPermissionGroup.Driver) => "the driver seat" + case Some(seatType) => s"a $seatType seat, #$seat_number" + case None => "a seat" + } + }") val obj_guid: PlanetSideGUID = obj.GUID - log.info(s"${player.Name} mounts ${obj.Definition.Name} in seat $seat_number") CancelAllProximityUnits() sendResponse(PlanetsideAttributeMessage(obj_guid, 0, obj.Health)) sendResponse(PlanetsideAttributeMessage(obj_guid, 68, obj.Shields)) //shield health @@ -2504,7 +2512,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con case Mountable.CanMount(obj: FacilityTurret, seat_number, _) => CancelZoningProcessWithDescriptiveReason("cancel_mount") if (!obj.isUpgrading) { - log.info(s"${player.Name} mounts ${obj.Definition.Name}") + log.info(s"${player.Name} mounts the ${obj.Definition.Name}") if (obj.Definition == GlobalDefinitions.vanu_sentry_turret) { obj.Zone.LocalEvents ! LocalServiceMessage(obj.Zone.id, LocalAction.SetEmpire(obj.GUID, player.Faction)) } @@ -2519,6 +2527,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con case Mountable.CanMount(obj: PlanetSideGameObject with WeaponTurret, seat_number, _) => CancelZoningProcessWithDescriptiveReason("cancel_mount") + log.info(s"${player.Name} mounts the ${obj.Definition.asInstanceOf[BasicDefinition].Name}") sendResponse(PlanetsideAttributeMessage(obj.GUID, 0, obj.Health)) UpdateWeaponAtSeatPosition(obj, seat_number) MountingAction(tplayer, obj, seat_number) @@ -2528,6 +2537,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con log.warn(s"MountVehicleMsg: $obj is some mountable object and nothing will happen for ${player.Name}") case Mountable.CanDismount(obj: ImplantTerminalMech, seat_num, _) => + log.info(s"${tplayer.Name} dismounts the implant terminal") DismountAction(tplayer, obj, seat_num) case Mountable.CanDismount(obj: Vehicle, seat_num, mount_point) @@ -2535,6 +2545,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con val pguid = player.GUID if (obj.MountedIn.nonEmpty) { //dismount to hart lobby + log.info(s"${tplayer.Name} dismounts the orbital shuttle into the lobby") val sguid = obj.GUID val (pos, zang) = Vehicles.dismountShuttle(obj, mount_point) tplayer.Position = pos @@ -2573,11 +2584,15 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con case Mountable.CanDismount(obj: Vehicle, seat_num, _) if obj.Definition == GlobalDefinitions.droppod => + log.info(s"${tplayer.Name} has landed on ${continent.id}") UnaccessContainer(obj) DismountAction(tplayer, obj, seat_num) obj.Actor ! Vehicle.Deconstruct() case Mountable.CanDismount(obj: Vehicle, seat_num, _) => + log.info( + s"${tplayer.Name} dismounts a ${obj.Definition.asInstanceOf[ObjectDefinition].Name} from seat #$seat_num" + ) val player_guid: PlanetSideGUID = tplayer.GUID if (player_guid == player.GUID) { //disembarking self @@ -2592,6 +2607,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con } case Mountable.CanDismount(obj: PlanetSideGameObject with WeaponTurret, seat_num, _) => + log.info(s"${tplayer.Name} dismounts a ${obj.Definition.asInstanceOf[ObjectDefinition].Name}") DismountAction(tplayer, obj, seat_num) case Mountable.CanDismount(obj: Mountable, _, _) => @@ -7883,9 +7899,6 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con */ def DismountAction(tplayer: Player, obj: PlanetSideGameObject with Mountable, seatNum: Int): Unit = { val player_guid: PlanetSideGUID = tplayer.GUID - log.info( - s"${tplayer.Name} dismounts a ${obj.Definition.asInstanceOf[ObjectDefinition].Name} from seat #$seatNum" - ) keepAliveFunc = NormalKeepAlive sendResponse(DismountVehicleMsg(player_guid, BailType.Normal, wasKickedByDriver = false)) continent.VehicleEvents ! VehicleServiceMessage( diff --git a/src/main/scala/net/psforever/services/teamwork/SquadService.scala b/src/main/scala/net/psforever/services/teamwork/SquadService.scala index 6136ec6d8..c9254789b 100644 --- a/src/main/scala/net/psforever/services/teamwork/SquadService.scala +++ b/src/main/scala/net/psforever/services/teamwork/SquadService.scala @@ -1,17 +1,27 @@ // Copyright (c) 2019 PSForever package net.psforever.services.teamwork -import akka.actor.{Actor, ActorRef, Terminated} import net.psforever.objects.avatar.{Avatar, Certification} import net.psforever.objects.definition.converter.StatConverter import net.psforever.objects.loadouts.SquadLoadout import net.psforever.objects.teamwork.{Member, Squad, SquadFeatures} import net.psforever.objects.zones.Zone import net.psforever.objects.{LivePlayerList, Player} -import net.psforever.packet.game.{PlanetSideZoneID, SquadDetail, SquadInfo, SquadPositionDetail, SquadPositionEntry, WaypointEventAction, WaypointInfo, SquadAction => SquadRequestAction} -import net.psforever.types._ +import net.psforever.packet.game.{ + PlanetSideZoneID, + SquadDetail, + SquadInfo, + SquadPositionDetail, + SquadPositionEntry, + WaypointEventAction, + WaypointInfo, + SquadAction => SquadRequestAction +} import net.psforever.services.{GenericEventBus, Service} +import net.psforever.types._ +import akka.actor.{Actor, ActorRef, Terminated} +import java.io.{PrintWriter, StringWriter} import scala.collection.concurrent.TrieMap import scala.collection.mutable import scala.collection.mutable.ListBuffer @@ -116,7 +126,7 @@ class SquadService extends Actor { private[this] val log = org.log4s.getLogger private def debug(msg: String): Unit = { - log.trace(msg) + log.debug(msg) } override def postStop(): Unit = { @@ -432,16 +442,16 @@ class SquadService extends Actor { SquadActionUpdate(char_id, health, max_health, armor, max_armor, pos, zone_number, sender()) case msg => - debug(s"Unhandled message $msg from ${sender()}") + log.warn(s"Unhandled action $msg from ${sender()}") } case msg => - debug(s"Unhandled message $msg from ${sender()}") + log.warn(s"Unhandled message $msg from ${sender()}") } def JoinByFaction(faction: String, sender: ActorRef): Unit = { val path = s"/$faction/Squad" - debug(s"$sender has joined $path") + log.trace(s"$sender has joined $path") SquadEvents.subscribe(sender, path) } @@ -449,7 +459,7 @@ class SquadService extends Actor { try { val longCharId = charId.toLong val path = s"/$charId/Squad" - debug(s"$sender has joined $path") + log.trace(s"$sender has joined $path") context.watch(sender) UserEvents += longCharId -> sender refused(longCharId) = Nil @@ -458,13 +468,15 @@ class SquadService extends Actor { log.warn(s"Service.Join: tried $charId as a unique character identifier, but it could not be casted") case e: Exception => log.error(s"Service.Join: unexpected exception using $charId as data - ${e.getLocalizedMessage}") - e.printStackTrace() + val sw = new StringWriter + e.printStackTrace(new PrintWriter(sw)) + log.error(sw.toString) } } def LeaveByFaction(faction: String, sender: ActorRef): Unit = { val path = s"/$faction/Squad" - debug(s"$sender has left $path") + log.trace(s"$sender has left $path") SquadEvents.unsubscribe(sender, path) } @@ -476,7 +488,9 @@ class SquadService extends Actor { log.warn(s"Service.Leave: tried $charId as a unique character identifier, but it could not be casted") case e: Exception => log.error(s"Service.Leave: unexpected exception using $charId as data - ${e.getLocalizedMessage}") - e.printStackTrace() + val sw = new StringWriter + e.printStackTrace(new PrintWriter(sw)) + log.error(sw.toString) } } @@ -2481,16 +2495,11 @@ class SquadService extends Actor { def RemoveAllInvitesToSquad(sguid: PlanetSideGUID): Unit = { //clean up invites invites.collect { - case (id, VacancyInvite(_, _, guid)) if sguid == guid => - RemoveInvite(id) - case (id, IndirectInvite(_, guid)) if sguid == guid => - RemoveInvite(id) - case (id, LookingForSquadRoleInvite(_, _, guid, _)) if sguid == guid => - RemoveInvite(id) - case (id, RequestRole(_, guid, _)) if sguid == guid => - RemoveInvite(id) - case (id, ProximityInvite(_, _, guid)) if sguid == guid => - RemoveInvite(id) + case (id, VacancyInvite(_, _, guid)) if sguid == guid => RemoveInvite(id) + case (id, IndirectInvite(_, guid)) if sguid == guid => RemoveInvite(id) + case (id, LookingForSquadRoleInvite(_, _, guid, _)) if sguid == guid => RemoveInvite(id) + case (id, RequestRole(_, guid, _)) if sguid == guid => RemoveInvite(id) + case (id, ProximityInvite(_, _, guid)) if sguid == guid => RemoveInvite(id) } //tidy the queued invitations queuedInvites.foreach { @@ -2536,16 +2545,11 @@ class SquadService extends Actor { def RemoveAllInvitesWithPlayer(charId: Long): Unit = { RemoveInvite(charId) invites.collect { - case (id, SpontaneousInvite(player)) if player.CharId == charId => - RemoveInvite(id) - case (id, VacancyInvite(_charId, _, _)) if _charId == charId => - RemoveInvite(id) - case (id, IndirectInvite(player, _)) if player.CharId == charId => - RemoveInvite(id) - case (id, LookingForSquadRoleInvite(_charId, _, _, _)) if _charId == charId => - RemoveInvite(id) - case (id, RequestRole(player, _, _)) if player.CharId == charId => - RemoveInvite(id) + case (id, SpontaneousInvite(player)) if player.CharId == charId => RemoveInvite(id) + case (id, VacancyInvite(_charId, _, _)) if _charId == charId => RemoveInvite(id) + case (id, IndirectInvite(player, _)) if player.CharId == charId => RemoveInvite(id) + case (id, LookingForSquadRoleInvite(_charId, _, _, _)) if _charId == charId => RemoveInvite(id) + case (id, RequestRole(player, _, _)) if player.CharId == charId => RemoveInvite(id) } //tidy the queued invitations queuedInvites.remove(charId) @@ -3051,14 +3055,18 @@ class SquadService extends Actor { member.Name = "" member.CharId = 0 //other squad members see the member leaving - Publish(squadFeatures(squad.GUID).ToChannel, SquadResponse.Leave(squad, List(entry)), Seq(charId)) - UpdateSquadListWhenListed(squadFeatures(squad.GUID), SquadInfo().Size(squad.Size)) + squadFeatures.get(squad.GUID) match { + case Some(features) => + Publish(features.ToChannel, SquadResponse.Leave(squad, List(entry)), Seq(charId)) + UpdateSquadListWhenListed(features, SquadInfo().Size(squad.Size)) + case None => ; + } UpdateSquadDetail( squad.GUID, SquadDetail().Members(List(SquadPositionEntry(index, SquadPositionDetail().Player(char_id = 0, name = "")))) ) true - case None => + case _ => false } } @@ -3298,14 +3306,16 @@ class SquadService extends Actor { continueToMonitorDetails.remove(charId) RemoveAllInvitesWithPlayer(charId) val pSquadOpt = GetParticipatingSquad(charId) - val lSquadOpt = GetLeadingSquad(charId, pSquadOpt) pSquadOpt match { //member of the squad; leave the squad case Some(squad) => val size = squad.Size - SquadEvents.unsubscribe(UserEvents(charId), s"/${squadFeatures(squad.GUID).ToChannel}/Squad") - UserEvents.remove(charId) - lSquadOpt match { + UserEvents.remove(charId) match { + case Some(events) => + SquadEvents.unsubscribe(events, s"/${squadFeatures(squad.GUID).ToChannel}/Squad") + case _ => ; + } + GetLeadingSquad(charId, pSquadOpt) match { case Some(_) => //leader of a squad; the squad will be disbanded PanicDisbandSquad(