From c6860bc7187bd4a005c4fe2728aa043b2b5e5a3d Mon Sep 17 00:00:00 2001 From: Fate-JH Date: Tue, 6 Aug 2024 15:09:34 -0400 Subject: [PATCH] converted DeployItem from AvatarService to LocalService; attempt at resolving missing overwhip yellow ring is complicated; vehicle ownership packet wqorks on deployables that are mountable, but is less successful on normal simple deployables --- .../actor/service/AvatarServiceTest.scala | 23 ------- .../session/support/GeneralOperations.scala | 2 +- .../objects/avatar/PlayerControl.scala | 30 ++++++--- .../objects/ce/DeployableBehavior.scala | 64 +++++++++---------- .../game/PlanetsideAttributeMessage.scala | 19 +++--- .../services/avatar/AvatarService.scala | 11 ---- .../avatar/AvatarServiceMessage.scala | 2 - .../services/local/LocalService.scala | 12 +++- .../services/local/LocalServiceMessage.scala | 1 + .../objects/DeployableBehaviorTest.scala | 4 +- .../scala/objects/TelepadRouterTest.scala | 8 +-- src/test/scala/service/LocalServiceTest.scala | 25 ++++++++ 12 files changed, 109 insertions(+), 92 deletions(-) diff --git a/server/src/test/scala/actor/service/AvatarServiceTest.scala b/server/src/test/scala/actor/service/AvatarServiceTest.scala index 665c7ec7d..6e0eab30d 100644 --- a/server/src/test/scala/actor/service/AvatarServiceTest.scala +++ b/server/src/test/scala/actor/service/AvatarServiceTest.scala @@ -130,29 +130,6 @@ class EquipmentInHandTest extends ActorTest { } } -class DeployItemTest extends ActorTest { - ServiceManager.boot(system) - val service = system.actorOf(Props(classOf[AvatarService], Zone.Nowhere), "deploy-item-test-service") - val objDef = GlobalDefinitions.motionalarmsensor - val obj = new SensorDeployable(objDef) - obj.Position = Vector3(1, 2, 3) - obj.Orientation = Vector3(4, 5, 6) - obj.GUID = PlanetSideGUID(40) - val pkt = ObjectCreateMessage( - objDef.ObjectId, - obj.GUID, - objDef.Packet.ConstructorData(obj).get - ) - - "AvatarService" should { - "pass DeployItem" in { - service ! Service.Join("test") - service ! AvatarServiceMessage("test", AvatarAction.DeployItem(PlanetSideGUID(10), obj)) - expectMsg(AvatarServiceResponse("/test/Avatar", PlanetSideGUID(10), AvatarResponse.DropItem(pkt))) - } - } -} - class DroptItemTest extends ActorTest { ServiceManager.boot(system) val service = system.actorOf(Props(classOf[AvatarService], Zone.Nowhere), "release-test-service") diff --git a/src/main/scala/net/psforever/actors/session/support/GeneralOperations.scala b/src/main/scala/net/psforever/actors/session/support/GeneralOperations.scala index 9f3961911..deea975f9 100644 --- a/src/main/scala/net/psforever/actors/session/support/GeneralOperations.scala +++ b/src/main/scala/net/psforever/actors/session/support/GeneralOperations.scala @@ -563,7 +563,7 @@ class GeneralOperations( * @param unk2 na */ def hackObject(targetGuid: PlanetSideGUID, unk1: Long, unk2: HackState7): Unit = { - sendResponse(HackMessage(HackState1.Unk0, targetGuid, player_guid=Service.defaultPlayerGUID, progress=100, unk1, HackState.Hacked, unk2)) + sendResponse(HackMessage(HackState1.Unk0, targetGuid, player_guid=Service.defaultPlayerGUID, progress=100, unk1.toFloat, HackState.Hacked, unk2)) } /** diff --git a/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala b/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala index 4245c7688..b9cdf30cd 100644 --- a/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala +++ b/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala @@ -531,6 +531,7 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm setupDeployable(obj, tool) case Zone.Deployable.IsBuilt(obj: BoomerDeployable) => + obj.Actor ! Deployable.Ownership(player) deployablePair match { case Some((deployable, tool)) if deployable eq obj => val zone = player.Zone @@ -552,11 +553,12 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm TaskWorkflow.execute(PutNewEquipmentInInventoryOrDrop(player)(trigger)) } Players.buildCooldownReset(zone, player.Name, obj) - case _ => ; + case _ => () } deployablePair = None case Zone.Deployable.IsBuilt(obj: TelepadDeployable) => + obj.Actor ! Deployable.Ownership(player) deployablePair match { case Some((deployable, tool: Telepad)) if deployable eq obj => RemoveOldEquipmentFromInventory(player)(tool) @@ -569,11 +571,12 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm TelepadControl.TelepadError(zone, player.Name, msg = "@Telepad_NoDeploy_RouterLost") } Players.buildCooldownReset(zone, player.Name, obj) - case _ => ; + case _ => () } deployablePair = None case Zone.Deployable.IsBuilt(obj) => + obj.Actor ! Deployable.Ownership(player) deployablePair match { case Some((deployable, tool)) if deployable eq obj => Players.buildCooldownReset(player.Zone, player.Name, obj) @@ -584,7 +587,7 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm case None => log.warn(s"${player.Name} should have destroyed a ${tool.Definition.Name} here, but could not find it") } - case _ => ; + case _ => () } deployablePair = None @@ -701,16 +704,27 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm if (deployables.Valid(obj) && !deployables.Contains(obj) && Players.deployableWithinBuildLimits(player, obj)) { + //deployables, upon construction, may display an animation effect tool.Definition match { - case GlobalDefinitions.ace | /* animation handled in deployable lifecycle */ - GlobalDefinitions.router_telepad => ; /* no special animation */ + case GlobalDefinitions.router_telepad => () /* no special animation */ + case GlobalDefinitions.ace + if obj.Definition.deployAnimation == DeployAnimation.Standard => + zone.LocalEvents ! LocalServiceMessage( + zone.id, + LocalAction.TriggerEffectLocation( + obj.OwnerGuid.getOrElse(Service.defaultPlayerGUID), + "spawn_object_effect", + obj.Position, + obj.Orientation + ) + ) case GlobalDefinitions.advanced_ace if obj.Definition.deployAnimation == DeployAnimation.Fdu => zone.AvatarEvents ! AvatarServiceMessage(zone.id, AvatarAction.PutDownFDU(player.GUID)) case _ => - org.log4s.getLogger(name = "Deployables").warn( - s"not sure what kind of construction item to animate - ${tool.Definition.Name}" - ) + org.log4s + .getLogger(name = "Deployables") + .warn(s"not sure what kind of construction item to animate - ${tool.Definition.Name}") } deployablePair = Some((obj, tool)) obj.Faction = player.Faction diff --git a/src/main/scala/net/psforever/objects/ce/DeployableBehavior.scala b/src/main/scala/net/psforever/objects/ce/DeployableBehavior.scala index 21e17818e..bbc052b5a 100644 --- a/src/main/scala/net/psforever/objects/ce/DeployableBehavior.scala +++ b/src/main/scala/net/psforever/objects/ce/DeployableBehavior.scala @@ -4,7 +4,6 @@ package net.psforever.objects.ce import akka.actor.{Actor, ActorRef, Cancellable} import net.psforever.objects.guid.{GUIDTask, TaskWorkflow} import net.psforever.objects._ -import net.psforever.objects.definition.DeployAnimation import net.psforever.objects.zones.Zone import net.psforever.packet.game._ import net.psforever.services.Service @@ -105,6 +104,7 @@ trait DeployableBehavior { def loseOwnership(obj: Deployable, toFaction: PlanetSideEmpire.Value): Unit = { DeployableBehavior.changeOwnership( obj, + toOwner = "", toFaction, DeployableInfo(obj.GUID, Deployable.Icon.apply(obj.Definition.Item), obj.Position, Service.defaultPlayerGUID) ) @@ -138,18 +138,18 @@ trait DeployableBehavior { */ def gainOwnership(player: Player, toFaction: PlanetSideEmpire.Value): Unit = { val obj = DeployableObject - obj.AssignOwnership(player) decay.cancel() DeployableBehavior.changeOwnership( obj, + player.Name, toFaction, DeployableInfo(obj.GUID, Deployable.Icon.apply(obj.Definition.Item), obj.Position, player.GUID) ) + obj.AssignOwnership(player) } /** * The first stage of the deployable build process, to put the formal process in motion. - * Deployables, upon construction, may display an animation effect. * Parameters are required to be passed onto the next stage of the build process and are not used here. * @see `DeployableDefinition.deployAnimation` * @see `DeployableDefinition.DeployTime` @@ -157,21 +157,9 @@ trait DeployableBehavior { * @param callback an `ActorRef` used for confirming the deployable's completion of the process */ def setupDeployable(callback: ActorRef): Unit = { + import scala.concurrent.ExecutionContext.Implicits.global val obj = DeployableObject constructed = Some(false) - if (obj.Definition.deployAnimation == DeployAnimation.Standard) { - val zone = obj.Zone - zone.LocalEvents ! LocalServiceMessage( - zone.id, - LocalAction.TriggerEffectLocation( - obj.OwnerGuid.getOrElse(Service.defaultPlayerGUID), - "spawn_object_effect", - obj.Position, - obj.Orientation - ) - ) - } - import scala.concurrent.ExecutionContext.Implicits.global setup = context.system.scheduler.scheduleOnce( obj.Definition.DeployTime milliseconds, self, @@ -185,7 +173,7 @@ trait DeployableBehavior { * Nothing dangerous happens if it does not begin to decay, but, because it is not under a player's management, * the deployable will not properly transition to a decay state for another reason * and can linger in the zone ownerless for as long as it is not destroyed. - * @see `AvatarAction.DeployItem` + * @see `LocalAction.DeployItem` * @see `DeploymentAction` * @see `DeployableInfo` * @see `LocalAction.DeployableMapIcon` @@ -197,27 +185,22 @@ trait DeployableBehavior { setup = Default.Cancellable constructed = Some(true) val obj = DeployableObject - val zone = obj.Zone + val zone = obj.Zone val localEvents = zone.LocalEvents - val owner = obj.OwnerGuid.getOrElse(Service.defaultPlayerGUID) - obj.OwnerName match { - case Some(_) => - case None => - import scala.concurrent.ExecutionContext.Implicits.global - decay = context.system.scheduler.scheduleOnce( - Deployable.decay, - self, - Deployable.Deconstruct() - ) + obj.OwnerName.orElse { + import scala.concurrent.ExecutionContext.Implicits.global + decay = context.system.scheduler.scheduleOnce(Deployable.decay, self, Deployable.Deconstruct()) + None } //zone build - zone.AvatarEvents ! AvatarServiceMessage(zone.id, AvatarAction.DeployItem(Service.defaultPlayerGUID, obj)) + localEvents ! LocalServiceMessage(zone.id, LocalAction.DeployItem(obj)) //zone map icon localEvents ! LocalServiceMessage( obj.Faction.toString, LocalAction.DeployableMapIcon( Service.defaultPlayerGUID, - DeploymentAction.Build, DeployableInfo(obj.GUID, Deployable.Icon(obj.Definition.Item), obj.Position, owner) + DeploymentAction.Build, + DeployableInfo(obj.GUID, Deployable.Icon(obj.Definition.Item), obj.Position, obj.OwnerGuid.getOrElse(Service.defaultPlayerGUID)) ) ) //local build management @@ -290,27 +273,44 @@ object DeployableBehavior { * @param toFaction na * @param info na */ - def changeOwnership(obj: Deployable, toFaction: PlanetSideEmpire.Value, info: DeployableInfo): Unit = { + def changeOwnership(obj: Deployable, toOwner: String, toFaction: PlanetSideEmpire.Value, info: DeployableInfo): Unit = { + val dGuid = obj.GUID val originalFaction = obj.Faction val zone = obj.Zone val localEvents = zone.LocalEvents + val ownershipAction = { + val owner = info.player_guid + LocalAction.SendPlanetsideAttributeMessage( + owner, + owner, + PlanetsideAttributeEnum.OwnershipAssignment, + dGuid.guid.toLong + ) + } if (originalFaction != toFaction) { obj.Faction = toFaction //visual tells in regards to ownership by faction zone.AvatarEvents ! AvatarServiceMessage( zone.id, - AvatarAction.SetEmpire(Service.defaultPlayerGUID, obj.GUID, toFaction) + AvatarAction.SetEmpire(Service.defaultPlayerGUID, dGuid, toFaction) ) //remove knowledge by the previous owner's faction localEvents ! LocalServiceMessage( originalFaction.toString, LocalAction.DeployableMapIcon(Service.defaultPlayerGUID, DeploymentAction.Dismiss, info) ) + } else { + //old owner no longer owner + obj.OwnerName.collect { case fromOwner if !fromOwner.equals(toOwner) => + localEvents ! LocalServiceMessage(fromOwner, ownershipAction) + } } //display to the given faction localEvents ! LocalServiceMessage( toFaction.toString, LocalAction.DeployableMapIcon(Service.defaultPlayerGUID, DeploymentAction.Build, info) ) + //new owner is owner + localEvents ! LocalServiceMessage(toOwner, ownershipAction) } } diff --git a/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala b/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala index a6fb90707..aaf908d14 100644 --- a/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala +++ b/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala @@ -1,10 +1,12 @@ // Copyright (c) 2016 PSForever.net to present package net.psforever.packet.game +import net.psforever.packet.GamePacketOpcode.Type import net.psforever.packet.game.PlanetsideAttributeEnum.PlanetsideAttributeEnum import net.psforever.packet.{GamePacketOpcode, Marshallable, PlanetSideGamePacket} import net.psforever.types.PlanetSideGUID -import scodec.Codec +import scodec.bits.BitVector +import scodec.{Attempt, Codec} import scodec.codecs._ /** @@ -68,8 +70,8 @@ import scodec.codecs._ * `17 - BEP. Value seems to be the same as BattleExperienceMessage`
* `18 - CEP.`
* `19 - Anchors. Value is 0 to disengage, 1 to engage.`
- * `20 - Control console hacking, affects CC timer, yellow base warning lights and message "The FactionName has hacked into BaseName". - * Format is: Time left - 2 bytes, faction - 1 byte (1-4), isResecured - 1 byte (0-1)`
+ * `20 - Control console hacking, affects CC timer, yellow base warning lights and message "The FactionName has hacked into BaseName".` + * Format is: Time left - 2 bytes, faction - 1 byte (1-4), isResecured - 1 byte (0-1)
*