From cd3e6d2f636d171a9baa22ec2e717706144d3261 Mon Sep 17 00:00:00 2001 From: Mazo Date: Sat, 26 May 2018 07:51:18 +0100 Subject: [PATCH 01/17] Add missing deployment time to ANT definition --- .../main/scala/net/psforever/objects/GlobalDefinitions.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala index d3b9c05f..b147716f 100644 --- a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala +++ b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala @@ -2701,6 +2701,9 @@ object GlobalDefinitions { ant.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax ant.MountPoints += 1 -> 0 ant.MountPoints += 2 -> 0 + ant.Deployment = true + ant.DeployTime = 1500 + ant.UndeployTime = 1500 ant.AutoPilotSpeeds = (18, 6) ant.Packet = utilityConverter From 1b0b84e53ed6a9ff860c93eef17f3b21e93e7463 Mon Sep 17 00:00:00 2001 From: Mazo Date: Sat, 26 May 2018 07:57:51 +0100 Subject: [PATCH 02/17] Improvements/fixes to some javadoc / comments --- .../serverobject/structures/Building.scala | 2 +- .../structures/BuildingControl.scala | 1 - .../net/psforever/objects/vehicles/Seat.scala | 4 ++-- .../game/PlanetsideAttributeMessage.scala | 14 ++++++++++--- .../packet/game/WeaponFireMessage.scala | 21 ++++++++++++++++--- .../game/objectcreate/VehicleData.scala | 2 +- .../src/main/scala/WorldSessionActor.scala | 14 ++++++------- 7 files changed, 40 insertions(+), 18 deletions(-) diff --git a/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala b/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala index 844da483..ae928688 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala @@ -11,7 +11,7 @@ import net.psforever.types.{PlanetSideEmpire, Vector3} class Building(private val mapId : Int, private val zone : Zone, private val buildingType : StructureType.Value) extends PlanetSideServerObject { /** * The mapId is the identifier number used in BuildingInfoUpdateMessage. - * The modelId is the identifier number used in SetEmpireMessage. + * The modelId is the identifier number used in SetEmpireMessage / Facility hacking / PlanetSideAttributeMessage. */ private var modelId : Option[Int] = None private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL diff --git a/common/src/main/scala/net/psforever/objects/serverobject/structures/BuildingControl.scala b/common/src/main/scala/net/psforever/objects/serverobject/structures/BuildingControl.scala index 2f7b7b7c..87ac9a1b 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/structures/BuildingControl.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/structures/BuildingControl.scala @@ -14,7 +14,6 @@ class BuildingControl(building : Building) extends Actor with FactionAffinityBeh building.Amenities.foreach(_.Actor forward FactionAffinity.ConfirmFactionAffinity()) } sender ! FactionAffinity.AssertFactionAffinity(building, faction) - case _ => ; } } diff --git a/common/src/main/scala/net/psforever/objects/vehicles/Seat.scala b/common/src/main/scala/net/psforever/objects/vehicles/Seat.scala index f69f927d..bf907740 100644 --- a/common/src/main/scala/net/psforever/objects/vehicles/Seat.scala +++ b/common/src/main/scala/net/psforever/objects/vehicles/Seat.scala @@ -15,7 +15,7 @@ class Seat(private val seatDef : SeatDefinition) { /** * Is this seat occupied? - * @return the GUID of the player sitting in this seat, or `None` if it is left vacant + * @return the Player object of the player sitting in this seat, or `None` if it is left vacant */ def Occupant : Option[Player] = { this.occupant @@ -25,7 +25,7 @@ class Seat(private val seatDef : SeatDefinition) { * The player is trying to sit down. * Seats are exclusive positions that can only hold one occupant at a time. * @param player the player who wants to sit, or `None` if the occupant is getting up - * @return the GUID of the player sitting in this seat, or `None` if it is left vacant + * @return the Player object of the player sitting in this seat, or `None` if it is left vacant */ def Occupant_=(player : Player) : Option[Player] = Occupant_=(Some(player)) diff --git a/common/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala b/common/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala index 5d0dc875..60bc85ba 100644 --- a/common/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala +++ b/common/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala @@ -39,7 +39,7 @@ import scodec.codecs._ *
* Players/General:
* Server to client :
- * `0 - health`
+ * `0 - health (setting to zero on vehicles/terminals will destroy them)`
* `1 - healthMax`
* `2 - stamina`
* `3 - staminaMax`
@@ -104,6 +104,11 @@ import scodec.codecs._ * `35 - BR. Value is the BR`
* `36 - CR. Value is the CR`
* `43 - Info on avatar name : 0 = Nothing, 1 = "(LD)" message`
+ * `45 - NTU charge bar 0-10, 5 = 50% full. Seems to apply to both ANT and NTU Silo (possibly siphons?)`
+ * 47 - Sets base NTU level to CRITICAL. MUST use base modelId not base GUID + * 48 - Send base power loss message & turns on red warning lights throughout base. MUST use base modelId not base GUID + * 49 - Vehicle texture effects state? (>0 turns on ANT panel glow or ntu silo panel glow + orbs) (bit?) + * `52 - Vehicle particle effects? (>0 turns on orbs going towards ANT. Doesn't affect silo) (bit?) * `53 - LFS. Value is 1 to flag LFS`
* `54 - Player "Aura". Values can be expressed in the first byte's lower nibble:`
* - 0 is nothing
@@ -114,6 +119,7 @@ import scodec.codecs._ * -- e.g., 13 = 8 + 4 + 1 = fire and LLU and plasma
* `55 - "Someone is attempting to Heal you". Value is 1`
* `56 - "Someone is attempting to Repair you". Value is 1`
+ * `67 - Enables base shields (from cavern module/lock). MUST use base modelId not GUID`
* `73 - "You are locked into the Core Beam. Charging your Module now.". Value is 1 to active`
* `77 - Cavern Facility Captures. Value is the number of captures`
* `78 - Cavern Kills. Value is the number of kills`
@@ -128,10 +134,12 @@ import scodec.codecs._ * `13 - Trunk permissions (same)`
* `21 - Asserts first time event eligibility / makes owner if no owner is assigned`
* `22 - Toggles gunner and passenger mount points (1 = hides, 0 = reveals; this also locks their permissions)`
- * `68 - ???`
+ * `54 - Vehicle EMP? Plays sound as if vehicle had been hit by EMP`
+ * `68 - Vehicle shield health`
* `80 - Damage vehicle (unknown value)`
* `81 - ???`
- * `113 - ???` + * `113 - `Vehicle capacitor - e.g. Leviathan EMP charge` + * * @param player_guid the player * @param attribute_type na * @param attribute_value na diff --git a/common/src/main/scala/net/psforever/packet/game/WeaponFireMessage.scala b/common/src/main/scala/net/psforever/packet/game/WeaponFireMessage.scala index d3a87bdf..eb3dc21f 100644 --- a/common/src/main/scala/net/psforever/packet/game/WeaponFireMessage.scala +++ b/common/src/main/scala/net/psforever/packet/game/WeaponFireMessage.scala @@ -6,10 +6,25 @@ import net.psforever.types.Vector3 import scodec.Codec import scodec.codecs._ -/** WeaponFireMessage seems to be sent each time a weapon actually shoots. +/** + * WeaponFireMessage seems to be sent each time a weapon actually shoots. * - * See [[PlayerStateMessageUpstream]] for explanation of seq_time. - */ + * + * @param seq_time See [[PlayerStateMessageUpstream]] for explanation of seq_time. + * @param weapon_guid + * @param projectile_guid + * @param shot_origin + * @param unk1 Always zero from testing so far + * @param unk2 Seems semi-random + * @param unk3 Seems semi-random + * @param unk4 Maximum travel distance in meters - seems to be zero for decimator rockets + * @param unk5 Possibly always 255 from testing + * @param unk6 0 for bullet + * 1 for possibly delayed explosion (thumper alt fire) or thresher/leviathan flux cannon + * 2 for vs starfire (lockon type?) + * 3 for thrown (e.g. grenades) + * @param unk7 Seems to be thrown weapon velocity/direction +*/ final case class WeaponFireMessage(seq_time : Int, weapon_guid : PlanetSideGUID, projectile_guid : PlanetSideGUID, diff --git a/common/src/main/scala/net/psforever/packet/game/objectcreate/VehicleData.scala b/common/src/main/scala/net/psforever/packet/game/objectcreate/VehicleData.scala index 34eac81d..0f0898d7 100644 --- a/common/src/main/scala/net/psforever/packet/game/objectcreate/VehicleData.scala +++ b/common/src/main/scala/net/psforever/packet/game/objectcreate/VehicleData.scala @@ -57,7 +57,7 @@ final case class VariantVehicleData(unk : Int) extends SpecificVehicleData { * For very complicated vehicles, the packets `FrameVehicleStateMessage` and `VehicleSubStateMessage` will also be employed. * The tasks that these packets perform are different based on the vehicle that responds or generates them. * @param basic data common to objects - * @param unk1 na + * @param unk1 na. Valid values seem to be 0-3. Anything higher spawns a completely broken NC vehicle with no guns that can't move * @param health the amount of health the vehicle has, as a percentage of a filled bar (255) * @param unk2 na * @param no_mount_points do not display entry points for the seats diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index 8ec79f16..0a70c289 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -1169,8 +1169,8 @@ class WorldSessionActor extends Actor with MDCContextAware { } sendResponse(PlanetsideAttributeMessage(vehicle_guid, 22, 0L)) //mount points on? //sendResponse(PlanetsideAttributeMessage(vehicle_guid, 0, 10))//vehicle.Definition.MaxHealth)) - sendResponse(PlanetsideAttributeMessage(vehicle_guid, 68, 0L)) //??? - sendResponse(PlanetsideAttributeMessage(vehicle_guid, 113, 0L)) //??? + sendResponse(PlanetsideAttributeMessage(vehicle_guid, 68, 0L)) // Shield health + sendResponse(PlanetsideAttributeMessage(vehicle_guid, 113, 0L)) // Capacitor (EMP) ReloadVehicleAccessPermissions(vehicle) ServerVehicleLock(vehicle) @@ -3417,7 +3417,7 @@ class WorldSessionActor extends Actor with MDCContextAware { /** * Gives a target player positive battle experience points only. * If the player has access to more implant slots as a result of changing battle experience points, unlock those slots. - * @param tplayer the player + * @param avatar the player * @param bep the change in experience points, positive by assertion * @return the player's current battle experience points */ @@ -4069,7 +4069,7 @@ class WorldSessionActor extends Actor with MDCContextAware { obj match { case vehicle : Vehicle => ReloadVehicleAccessPermissions(vehicle) //TODO we should not have to do this imho - // + if(obj.Definition == GlobalDefinitions.ams) { obj.DeploymentState match { case DriveState.Deployed => @@ -4241,7 +4241,7 @@ class WorldSessionActor extends Actor with MDCContextAware { *
* A maximum revive waiting timer is started. * When this timer reaches zero, the avatar will attempt to spawn back on its faction-specific sanctuary continent. - * @pararm tplayer the player to be killed + * @param tplayer the player to be killed */ def KillPlayer(tplayer : Player) : Unit = { val player_guid = tplayer.GUID @@ -4495,7 +4495,7 @@ class WorldSessionActor extends Actor with MDCContextAware { /** * For pure proximity-based units and services, disable any manual attempt at cutting off the functionality. * If an existing timer can be found, cancel it. - * @param terminal the proximity-based unit + * @param terminal_guid the proximity-based unit */ def ClearDelayedProximityUnitReset(terminal_guid : PlanetSideGUID) : Unit = { delayedProximityTerminalResets.get(terminal_guid) match { @@ -4592,7 +4592,7 @@ class WorldSessionActor extends Actor with MDCContextAware { * Restore, at most, a specific amount of health points on a player. * Send messages to connected client and to events system. * @param tplayer the player - * @param repairValue the amount to heal; + * @param healValue the amount to heal; * 10 by default * @return whether the player can be repaired for any more health points */ From 8a2896f434a8d93a1a96f838d55763e9251b5207 Mon Sep 17 00:00:00 2001 From: Mazo Date: Sat, 26 May 2018 09:06:51 +0100 Subject: [PATCH 03/17] Move services to common to allow server objects to send messages --- {pslogin => common}/src/main/scala/services/Service.scala | 0 .../src/main/scala/services/ServiceManager.scala | 0 .../src/main/scala/services/avatar/AvatarAction.scala | 0 .../src/main/scala/services/avatar/AvatarResponse.scala | 0 .../src/main/scala/services/avatar/AvatarService.scala | 2 +- .../src/main/scala/services/avatar/AvatarServiceMessage.scala | 0 .../src/main/scala/services/avatar/AvatarServiceResponse.scala | 0 .../scala/services/avatar/support/CorpseRemovalActor.scala | 0 .../src/main/scala/services/local/LocalAction.scala | 0 .../src/main/scala/services/local/LocalResponse.scala | 0 .../src/main/scala/services/local/LocalService.scala | 2 +- .../src/main/scala/services/local/LocalServiceMessage.scala | 0 .../src/main/scala/services/local/LocalServiceResponse.scala | 0 .../src/main/scala/services/local/support/DoorCloseActor.scala | 0 .../src/main/scala/services/local/support/HackClearActor.scala | 0 .../src/main/scala/services/vehicle/VehicleAction.scala | 0 .../src/main/scala/services/vehicle/VehicleResponse.scala | 0 .../src/main/scala/services/vehicle/VehicleService.scala | 3 +-- .../main/scala/services/vehicle/VehicleServiceMessage.scala | 0 .../main/scala/services/vehicle/VehicleServiceResponse.scala | 0 .../scala/services/vehicle/support/DeconstructionActor.scala | 0 .../services/vehicle/support/DelayedDeconstructionActor.scala | 0 22 files changed, 3 insertions(+), 4 deletions(-) rename {pslogin => common}/src/main/scala/services/Service.scala (100%) rename {pslogin => common}/src/main/scala/services/ServiceManager.scala (100%) rename {pslogin => common}/src/main/scala/services/avatar/AvatarAction.scala (100%) rename {pslogin => common}/src/main/scala/services/avatar/AvatarResponse.scala (100%) rename {pslogin => common}/src/main/scala/services/avatar/AvatarService.scala (100%) rename {pslogin => common}/src/main/scala/services/avatar/AvatarServiceMessage.scala (100%) rename {pslogin => common}/src/main/scala/services/avatar/AvatarServiceResponse.scala (100%) rename {pslogin => common}/src/main/scala/services/avatar/support/CorpseRemovalActor.scala (100%) rename {pslogin => common}/src/main/scala/services/local/LocalAction.scala (100%) rename {pslogin => common}/src/main/scala/services/local/LocalResponse.scala (100%) rename {pslogin => common}/src/main/scala/services/local/LocalService.scala (100%) rename {pslogin => common}/src/main/scala/services/local/LocalServiceMessage.scala (100%) rename {pslogin => common}/src/main/scala/services/local/LocalServiceResponse.scala (100%) rename {pslogin => common}/src/main/scala/services/local/support/DoorCloseActor.scala (100%) rename {pslogin => common}/src/main/scala/services/local/support/HackClearActor.scala (100%) rename {pslogin => common}/src/main/scala/services/vehicle/VehicleAction.scala (100%) rename {pslogin => common}/src/main/scala/services/vehicle/VehicleResponse.scala (100%) rename {pslogin => common}/src/main/scala/services/vehicle/VehicleService.scala (99%) rename {pslogin => common}/src/main/scala/services/vehicle/VehicleServiceMessage.scala (100%) rename {pslogin => common}/src/main/scala/services/vehicle/VehicleServiceResponse.scala (100%) rename {pslogin => common}/src/main/scala/services/vehicle/support/DeconstructionActor.scala (100%) rename {pslogin => common}/src/main/scala/services/vehicle/support/DelayedDeconstructionActor.scala (100%) diff --git a/pslogin/src/main/scala/services/Service.scala b/common/src/main/scala/services/Service.scala similarity index 100% rename from pslogin/src/main/scala/services/Service.scala rename to common/src/main/scala/services/Service.scala diff --git a/pslogin/src/main/scala/services/ServiceManager.scala b/common/src/main/scala/services/ServiceManager.scala similarity index 100% rename from pslogin/src/main/scala/services/ServiceManager.scala rename to common/src/main/scala/services/ServiceManager.scala diff --git a/pslogin/src/main/scala/services/avatar/AvatarAction.scala b/common/src/main/scala/services/avatar/AvatarAction.scala similarity index 100% rename from pslogin/src/main/scala/services/avatar/AvatarAction.scala rename to common/src/main/scala/services/avatar/AvatarAction.scala diff --git a/pslogin/src/main/scala/services/avatar/AvatarResponse.scala b/common/src/main/scala/services/avatar/AvatarResponse.scala similarity index 100% rename from pslogin/src/main/scala/services/avatar/AvatarResponse.scala rename to common/src/main/scala/services/avatar/AvatarResponse.scala diff --git a/pslogin/src/main/scala/services/avatar/AvatarService.scala b/common/src/main/scala/services/avatar/AvatarService.scala similarity index 100% rename from pslogin/src/main/scala/services/avatar/AvatarService.scala rename to common/src/main/scala/services/avatar/AvatarService.scala index 17cec7ae..9bd793a2 100644 --- a/pslogin/src/main/scala/services/avatar/AvatarService.scala +++ b/common/src/main/scala/services/avatar/AvatarService.scala @@ -2,8 +2,8 @@ package services.avatar import akka.actor.{Actor, ActorRef, Props} -import services.avatar.support.CorpseRemovalActor import services.{GenericEventBus, Service} +import services.avatar.support.CorpseRemovalActor class AvatarService extends Actor { private val undertaker : ActorRef = context.actorOf(Props[CorpseRemovalActor], "corpse-removal-agent") diff --git a/pslogin/src/main/scala/services/avatar/AvatarServiceMessage.scala b/common/src/main/scala/services/avatar/AvatarServiceMessage.scala similarity index 100% rename from pslogin/src/main/scala/services/avatar/AvatarServiceMessage.scala rename to common/src/main/scala/services/avatar/AvatarServiceMessage.scala diff --git a/pslogin/src/main/scala/services/avatar/AvatarServiceResponse.scala b/common/src/main/scala/services/avatar/AvatarServiceResponse.scala similarity index 100% rename from pslogin/src/main/scala/services/avatar/AvatarServiceResponse.scala rename to common/src/main/scala/services/avatar/AvatarServiceResponse.scala diff --git a/pslogin/src/main/scala/services/avatar/support/CorpseRemovalActor.scala b/common/src/main/scala/services/avatar/support/CorpseRemovalActor.scala similarity index 100% rename from pslogin/src/main/scala/services/avatar/support/CorpseRemovalActor.scala rename to common/src/main/scala/services/avatar/support/CorpseRemovalActor.scala diff --git a/pslogin/src/main/scala/services/local/LocalAction.scala b/common/src/main/scala/services/local/LocalAction.scala similarity index 100% rename from pslogin/src/main/scala/services/local/LocalAction.scala rename to common/src/main/scala/services/local/LocalAction.scala diff --git a/pslogin/src/main/scala/services/local/LocalResponse.scala b/common/src/main/scala/services/local/LocalResponse.scala similarity index 100% rename from pslogin/src/main/scala/services/local/LocalResponse.scala rename to common/src/main/scala/services/local/LocalResponse.scala diff --git a/pslogin/src/main/scala/services/local/LocalService.scala b/common/src/main/scala/services/local/LocalService.scala similarity index 100% rename from pslogin/src/main/scala/services/local/LocalService.scala rename to common/src/main/scala/services/local/LocalService.scala index 5c01ee1a..2d2570ce 100644 --- a/pslogin/src/main/scala/services/local/LocalService.scala +++ b/common/src/main/scala/services/local/LocalService.scala @@ -2,8 +2,8 @@ package services.local import akka.actor.{Actor, Props} -import services.local.support.{DoorCloseActor, HackClearActor} import services.{GenericEventBus, Service} +import services.local.support.{DoorCloseActor, HackClearActor} class LocalService extends Actor { private val doorCloser = context.actorOf(Props[DoorCloseActor], "local-door-closer") diff --git a/pslogin/src/main/scala/services/local/LocalServiceMessage.scala b/common/src/main/scala/services/local/LocalServiceMessage.scala similarity index 100% rename from pslogin/src/main/scala/services/local/LocalServiceMessage.scala rename to common/src/main/scala/services/local/LocalServiceMessage.scala diff --git a/pslogin/src/main/scala/services/local/LocalServiceResponse.scala b/common/src/main/scala/services/local/LocalServiceResponse.scala similarity index 100% rename from pslogin/src/main/scala/services/local/LocalServiceResponse.scala rename to common/src/main/scala/services/local/LocalServiceResponse.scala diff --git a/pslogin/src/main/scala/services/local/support/DoorCloseActor.scala b/common/src/main/scala/services/local/support/DoorCloseActor.scala similarity index 100% rename from pslogin/src/main/scala/services/local/support/DoorCloseActor.scala rename to common/src/main/scala/services/local/support/DoorCloseActor.scala diff --git a/pslogin/src/main/scala/services/local/support/HackClearActor.scala b/common/src/main/scala/services/local/support/HackClearActor.scala similarity index 100% rename from pslogin/src/main/scala/services/local/support/HackClearActor.scala rename to common/src/main/scala/services/local/support/HackClearActor.scala diff --git a/pslogin/src/main/scala/services/vehicle/VehicleAction.scala b/common/src/main/scala/services/vehicle/VehicleAction.scala similarity index 100% rename from pslogin/src/main/scala/services/vehicle/VehicleAction.scala rename to common/src/main/scala/services/vehicle/VehicleAction.scala diff --git a/pslogin/src/main/scala/services/vehicle/VehicleResponse.scala b/common/src/main/scala/services/vehicle/VehicleResponse.scala similarity index 100% rename from pslogin/src/main/scala/services/vehicle/VehicleResponse.scala rename to common/src/main/scala/services/vehicle/VehicleResponse.scala diff --git a/pslogin/src/main/scala/services/vehicle/VehicleService.scala b/common/src/main/scala/services/vehicle/VehicleService.scala similarity index 99% rename from pslogin/src/main/scala/services/vehicle/VehicleService.scala rename to common/src/main/scala/services/vehicle/VehicleService.scala index 6b16ec2b..51ae1aeb 100644 --- a/pslogin/src/main/scala/services/vehicle/VehicleService.scala +++ b/common/src/main/scala/services/vehicle/VehicleService.scala @@ -4,10 +4,9 @@ package services.vehicle import akka.actor.{Actor, ActorRef, Props} import net.psforever.objects.serverobject.pad.VehicleSpawnPad import net.psforever.objects.zones.Zone -import services.vehicle.support.{DeconstructionActor, DelayedDeconstructionActor} import net.psforever.types.DriveState - import services.{GenericEventBus, Service} +import services.vehicle.support.{DeconstructionActor, DelayedDeconstructionActor} class VehicleService extends Actor { private val vehicleDecon : ActorRef = context.actorOf(Props[DeconstructionActor], "vehicle-decon-agent") diff --git a/pslogin/src/main/scala/services/vehicle/VehicleServiceMessage.scala b/common/src/main/scala/services/vehicle/VehicleServiceMessage.scala similarity index 100% rename from pslogin/src/main/scala/services/vehicle/VehicleServiceMessage.scala rename to common/src/main/scala/services/vehicle/VehicleServiceMessage.scala diff --git a/pslogin/src/main/scala/services/vehicle/VehicleServiceResponse.scala b/common/src/main/scala/services/vehicle/VehicleServiceResponse.scala similarity index 100% rename from pslogin/src/main/scala/services/vehicle/VehicleServiceResponse.scala rename to common/src/main/scala/services/vehicle/VehicleServiceResponse.scala diff --git a/pslogin/src/main/scala/services/vehicle/support/DeconstructionActor.scala b/common/src/main/scala/services/vehicle/support/DeconstructionActor.scala similarity index 100% rename from pslogin/src/main/scala/services/vehicle/support/DeconstructionActor.scala rename to common/src/main/scala/services/vehicle/support/DeconstructionActor.scala diff --git a/pslogin/src/main/scala/services/vehicle/support/DelayedDeconstructionActor.scala b/common/src/main/scala/services/vehicle/support/DelayedDeconstructionActor.scala similarity index 100% rename from pslogin/src/main/scala/services/vehicle/support/DelayedDeconstructionActor.scala rename to common/src/main/scala/services/vehicle/support/DelayedDeconstructionActor.scala From 2d2788383c9878dc92bc7dc7f6ccca324fab9c67 Mon Sep 17 00:00:00 2001 From: Mazo Date: Sat, 26 May 2018 12:49:50 +0100 Subject: [PATCH 04/17] Add capacitor / max capacitor values to vehicles --- .../net/psforever/objects/GlobalDefinitions.scala | 1 + .../main/scala/net/psforever/objects/Vehicle.scala | 14 ++++++++++++++ .../objects/definition/VehicleDefinition.scala | 8 ++++++++ .../objects/serverobject/structures/Building.scala | 2 +- 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala index b147716f..52843e78 100644 --- a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala +++ b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala @@ -2705,6 +2705,7 @@ object GlobalDefinitions { ant.DeployTime = 1500 ant.UndeployTime = 1500 ant.AutoPilotSpeeds = (18, 6) + ant.MaximumCapacitor = 1500 ant.Packet = utilityConverter ams.Name = "ams" diff --git a/common/src/main/scala/net/psforever/objects/Vehicle.scala b/common/src/main/scala/net/psforever/objects/Vehicle.scala index 6dabd99a..dcea094c 100644 --- a/common/src/main/scala/net/psforever/objects/Vehicle.scala +++ b/common/src/main/scala/net/psforever/objects/Vehicle.scala @@ -47,6 +47,7 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends PlanetSideServ private var trunkAccess : Option[PlanetSideGUID] = None private var jammered : Boolean = false private var cloaked : Boolean = false + private var capacitor : Int = 0 /** * Permissions control who gets to access different parts of the vehicle; @@ -147,6 +148,19 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends PlanetSideServ Cloaked } + def Capacitor : Int = capacitor + + def Capacitor_=(value: Int) : Int = { + if(value > Definition.MaximumCapacitor) { + capacitor = Definition.MaximumCapacitor + } else if (value < 0) { + capacitor = 0 + } else { + capacitor = value + } + Capacitor + } + /** * Given the index of an entry mounting point, return the infantry-accessible `Seat` associated with it. * @param mountPoint an index representing the seat position / mounting point diff --git a/common/src/main/scala/net/psforever/objects/definition/VehicleDefinition.scala b/common/src/main/scala/net/psforever/objects/definition/VehicleDefinition.scala index 5bb11e89..2d17e170 100644 --- a/common/src/main/scala/net/psforever/objects/definition/VehicleDefinition.scala +++ b/common/src/main/scala/net/psforever/objects/definition/VehicleDefinition.scala @@ -29,6 +29,7 @@ class VehicleDefinition(objectId : Int) extends ObjectDefinition(objectId) { private var canCloak : Boolean = false private var canBeOwned : Boolean = true private var serverVehicleOverrideSpeeds : (Int, Int) = (0, 0) + private var maximumCapacitor : Int = 0 Name = "vehicle" Packet = VehicleDefinition.converter @@ -114,6 +115,13 @@ class VehicleDefinition(objectId : Int) extends ObjectDefinition(objectId) { def AutoPilotSpeed1 : Int = serverVehicleOverrideSpeeds._1 def AutoPilotSpeed2 : Int = serverVehicleOverrideSpeeds._2 + + def MaximumCapacitor : Int = maximumCapacitor + + def MaximumCapacitor_=(maxCapacitor: Int) : Int = { + maximumCapacitor = maxCapacitor + MaximumCapacitor + } } object VehicleDefinition { diff --git a/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala b/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala index ae928688..3ebb145a 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala @@ -12,7 +12,7 @@ class Building(private val mapId : Int, private val zone : Zone, private val bui /** * The mapId is the identifier number used in BuildingInfoUpdateMessage. * The modelId is the identifier number used in SetEmpireMessage / Facility hacking / PlanetSideAttributeMessage. - */ + */ private var modelId : Option[Int] = None private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL private var amenities : List[Amenity] = List.empty From 2933811ac6a7b320f2086bb41db18575cf811087 Mon Sep 17 00:00:00 2001 From: Mazo Date: Sat, 26 May 2018 12:52:03 +0100 Subject: [PATCH 05/17] Add ResourceSilo definition with basic functionality for charging/discharging --- .../psforever/objects/GlobalDefinitions.scala | 3 + .../resourcesilo/ResourceSilo.scala | 86 +++++++++++++++++++ .../resourcesilo/ResourceSiloControl.scala | 80 +++++++++++++++++ .../resourcesilo/ResourceSiloDefinition.scala | 12 +++ 4 files changed, 181 insertions(+) create mode 100644 common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSilo.scala create mode 100644 common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala create mode 100644 common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloDefinition.scala diff --git a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala index 52843e78..1595fb78 100644 --- a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala +++ b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala @@ -13,6 +13,7 @@ import net.psforever.objects.serverobject.mblocker.LockerDefinition import net.psforever.objects.serverobject.pad.VehicleSpawnPadDefinition import net.psforever.objects.serverobject.terminals._ import net.psforever.objects.serverobject.tube.SpawnTubeDefinition +import net.psforever.objects.serverobject.resourcesilo.ResourceSiloDefinition import net.psforever.objects.vehicles.{SeatArmorRestriction, UtilityType} import net.psforever.types.PlanetSideEmpire @@ -563,6 +564,8 @@ object GlobalDefinitions { val door = new DoorDefinition + val resource_silo = new ResourceSiloDefinition + /** * Given a faction, provide the standard assault melee weapon. * @param faction the faction diff --git a/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSilo.scala b/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSilo.scala new file mode 100644 index 00000000..9e653c31 --- /dev/null +++ b/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSilo.scala @@ -0,0 +1,86 @@ +// Copyright (c) 2017 PSForever +package net.psforever.objects.serverobject.resourcesilo + +import akka.actor.{ActorContext, Props} +import net.psforever.objects.{GlobalDefinitions, Player, Vehicle} +import net.psforever.objects.serverobject.structures.Amenity +import net.psforever.packet.game.UseItemMessage + +class ResourceSilo extends Amenity { + private var chargeLevel : Int = 0 + private val maximumCharge : Int = 1000 + // For the flashing red light on top of the NTU silo on + private var lowNtuWarningOn : Int = 0 + + // For the NTU display bar + private var capacitorDisplay : Long = 0 + + def ChargeLevel : Int = chargeLevel + + // Do not call directly. Use ResourceSilo.UpdateChargeLevel message to handle logic such as low ntu warnings + def ChargeLevel_=(charge: Int) : Int = { + if(charge < 0 ) { + chargeLevel = 0 + } else if (charge > maximumCharge) { + chargeLevel = maximumCharge + } else { + chargeLevel = charge + } + ChargeLevel + } + + def MaximumCharge : Int = maximumCharge + + def LowNtuWarningOn : Int = lowNtuWarningOn + def LowNtuWarningOn_=(enabled: Int) : Int = { + lowNtuWarningOn = enabled + LowNtuWarningOn + } + + def CapacitorDisplay : Long = capacitorDisplay + def CapacitorDisplay_=(value: Long) : Long = { + capacitorDisplay = value + CapacitorDisplay + } + + def Definition : ResourceSiloDefinition = GlobalDefinitions.resource_silo + + def Use(player: Player, msg : UseItemMessage) : ResourceSilo.Exchange = { + ResourceSilo.ChargeEvent() + } +} + + +object ResourceSilo { + + final case class Use(player: Player, msg : UseItemMessage) + final case class UpdateChargeLevel(amount: Int) + final case class LowNtuWarning(enabled: Int) + final case class SyncStateWithClient() + sealed trait Exchange + final case class ChargeEvent() extends Exchange + final case class ResourceSiloMessage(player: Player, msg : UseItemMessage, response : Exchange) + + + /** + * Overloaded constructor. + * @return the `Resource Silo` object + */ + def apply() : ResourceSilo = { + new ResourceSilo() + } + + /** + * Instantiate an configure a `Resource Silo` object + * @param id the unique id that will be assigned to this entity + * @param context a context to allow the object to properly set up `ActorSystem` functionality; + * not necessary for this object, but required by signature + * @return the `Locker` object + */ + def Constructor(id : Int, context : ActorContext) : ResourceSilo = { + val obj = ResourceSilo() + obj.Actor = context.actorOf(Props(classOf[ResourceSiloControl], obj), s"${obj.Definition.Name}_$id") + obj.Actor ! "startup" + obj + } +} \ No newline at end of file diff --git a/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala b/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala new file mode 100644 index 00000000..18e38fde --- /dev/null +++ b/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala @@ -0,0 +1,80 @@ +// Copyright (c) 2017 PSForever +package net.psforever.objects.serverobject.resourcesilo + +import akka.actor.{Actor, ActorRef} +import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior} +import net.psforever.objects.serverobject.structures.Building +import net.psforever.packet.game.PlanetSideGUID +import services.ServiceManager.Lookup +import services._ +import services.avatar.{AvatarAction, AvatarServiceMessage} + +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.duration._ + + +/** + * An `Actor` that handles messages being dispatched to a specific `Resource Silo`. + * @param resourceSilo the `Resource Silo` object being governed + */ +class ResourceSiloControl(resourceSilo : ResourceSilo) extends Actor with FactionAffinityBehavior.Check { + def FactionObject : FactionAffinity = resourceSilo + var avatarService : ActorRef = Actor.noSender + private[this] val log = org.log4s.getLogger + + def receive : Receive = { + case "startup" => + ServiceManager.serviceManager ! Lookup("avatar") //ask for a resolver to deal with the GUID system + + case ServiceManager.LookupResult("avatar", endpoint) => + avatarService = endpoint + log.info("ResourceSiloControl: Silo " + resourceSilo.GUID + " Got avatar service " + endpoint) + + // todo: This is just a temporary solution to drain NTU over time. When base object destruction is properly implemented NTU should be deducted when base objects repair themselves + context.system.scheduler.schedule(5 second, 5 second, self, ResourceSilo.UpdateChargeLevel(-1)) + context.become(Processing) + + case _ => ; + } + + def Processing : Receive = checkBehavior.orElse { + case ResourceSilo.Use(player, msg) => + sender ! ResourceSilo.ResourceSiloMessage(player, msg, resourceSilo.Use(player, msg)) + case ResourceSilo.LowNtuWarning(enabled: Int) => + resourceSilo.LowNtuWarningOn = enabled + log.trace(s"LowNtuWarning: Silo ${resourceSilo.GUID} low ntu warning set to ${enabled}") + avatarService ! AvatarServiceMessage(resourceSilo.Owner.asInstanceOf[Building].Zone.Id, AvatarAction.PlanetsideAttribute(PlanetSideGUID(resourceSilo.Owner.asInstanceOf[Building].ModelId), 47, resourceSilo.LowNtuWarningOn)) + + case ResourceSilo.UpdateChargeLevel(amount: Int) => + // Increase if positive passed in or decrease charge level if negative number is passed in + resourceSilo.ChargeLevel += amount + if(resourceSilo.ChargeLevel > 0) { + log.trace(s"UpdateChargeLevel: Silo ${resourceSilo.GUID} set to ${resourceSilo.ChargeLevel}") + } + + val ntuIsLow = resourceSilo.ChargeLevel.toFloat / resourceSilo.MaximumCharge.toFloat < 0.2f + + val ntuBarLevel = scala.math.round((resourceSilo.ChargeLevel.toFloat / resourceSilo.MaximumCharge.toFloat) * 10).toInt + // Only send updated capacitor display value to all clients if it has actually changed + if(resourceSilo.CapacitorDisplay != ntuBarLevel) { + log.trace(s"Silo ${resourceSilo.GUID} NTU bar level has changed from ${resourceSilo.CapacitorDisplay} to ${ntuBarLevel}") + resourceSilo.CapacitorDisplay = ntuBarLevel + avatarService ! AvatarServiceMessage(resourceSilo.Owner.asInstanceOf[Building].Zone.Id, AvatarAction.PlanetsideAttribute(resourceSilo.GUID, 45, resourceSilo.CapacitorDisplay)) + } + + if(resourceSilo.LowNtuWarningOn == 1 && !ntuIsLow){ + self ! ResourceSilo.LowNtuWarning(0) + } else if (resourceSilo.LowNtuWarningOn == 0 && ntuIsLow) { + self ! ResourceSilo.LowNtuWarning(1) + } + + //todo: Shut down base power and make base neutral if silo hits zero NTU + case ResourceSilo.SyncStateWithClient() => + avatarService ! AvatarServiceMessage(resourceSilo.Owner.asInstanceOf[Building].Zone.Id, AvatarAction.PlanetsideAttribute(PlanetSideGUID(resourceSilo.Owner.asInstanceOf[Building].ModelId), 47, resourceSilo.LowNtuWarningOn)) + avatarService ! AvatarServiceMessage(resourceSilo.Owner.asInstanceOf[Building].Zone.Id, AvatarAction.PlanetsideAttribute(resourceSilo.GUID, 45, resourceSilo.CapacitorDisplay)) + + case _ => ; + } + + +} diff --git a/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloDefinition.scala b/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloDefinition.scala new file mode 100644 index 00000000..1f557062 --- /dev/null +++ b/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloDefinition.scala @@ -0,0 +1,12 @@ +// Copyright (c) 2017 PSForever +package net.psforever.objects.serverobject.resourcesilo + +import net.psforever.objects.definition.ObjectDefinition + +/** + * The definition for any `Resource Silo`. + * Object Id 731. + */ +class ResourceSiloDefinition extends ObjectDefinition(731) { + Name = "resource_silo" +} From bd7647177b3176ad98229acd1dff89571be5a373 Mon Sep 17 00:00:00 2001 From: Mazo Date: Sat, 26 May 2018 12:52:17 +0100 Subject: [PATCH 06/17] Add resource silo to Anguta --- pslogin/src/main/scala/Maps.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pslogin/src/main/scala/Maps.scala b/pslogin/src/main/scala/Maps.scala index 64f8e22f..038068d7 100644 --- a/pslogin/src/main/scala/Maps.scala +++ b/pslogin/src/main/scala/Maps.scala @@ -9,6 +9,7 @@ import net.psforever.objects.serverobject.pad.VehicleSpawnPad import net.psforever.objects.serverobject.structures.{Building, FoundationBuilder, StructureType, WarpGate} import net.psforever.objects.serverobject.terminals.{ProximityTerminal, Terminal} import net.psforever.objects.serverobject.tube.SpawnTube +import net.psforever.objects.serverobject.resourcesilo.ResourceSilo import net.psforever.types.Vector3 object Maps { @@ -125,6 +126,7 @@ object Maps { LocalObject(2050, Terminal.Constructor(repair_silo)) //rearm terminal A LocalObject(2061, ProximityTerminal.Constructor(repair_silo)) //repair terminal B LocalObject(2062, Terminal.Constructor(repair_silo)) //rearm terminal B + LocalObject(2094, ResourceSilo.Constructor) // NTU Silo LocalObject(2239, Terminal.Constructor(spawn_terminal)) LocalObject(2244, Terminal.Constructor(spawn_terminal)) LocalObject(2245, Terminal.Constructor(spawn_terminal)) @@ -238,6 +240,7 @@ object Maps { ObjectToBuilding(2050, 2) ObjectToBuilding(2061, 2) ObjectToBuilding(2062, 2) + ObjectToBuilding(2094, 2) ObjectToBuilding(2145, 2) ObjectToBuilding(2146, 2) ObjectToBuilding(2147, 2) From 519e56e27c5abd5c838dee01098f219b5a0aa747 Mon Sep 17 00:00:00 2001 From: Mazo Date: Sat, 26 May 2018 12:54:02 +0100 Subject: [PATCH 07/17] Add basic functionality to deploy ANT & charge at warpgate --- .../src/main/scala/WorldSessionActor.scala | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index 0a70c289..fbf3d203 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -43,6 +43,8 @@ import services.local.{LocalAction, LocalResponse, LocalServiceMessage, LocalSer import services.vehicle.VehicleAction.UnstowEquipment import services.vehicle.{VehicleAction, VehicleResponse, VehicleServiceMessage, VehicleServiceResponse} +import scala.concurrent.duration._ +import scala.concurrent.ExecutionContext.Implicits.global import scala.annotation.tailrec import scala.util.Success @@ -82,6 +84,7 @@ class WorldSessionActor extends Actor with MDCContextAware { var progressBarUpdate : Cancellable = DefaultCancellable.obj var reviveTimer : Cancellable = DefaultCancellable.obj var respawnTimer : Cancellable = DefaultCancellable.obj + var antChargingTick : Cancellable = DefaultCancellable.obj /** * Convert a boolean value into an integer value. @@ -1492,6 +1495,26 @@ class WorldSessionActor extends Actor with MDCContextAware { continent.Ground ! Zone.DropItemOnGround(item, item.Position, item.Orientation) //restore } + case NtuCharging(tplayer, vehicle) => + log.trace(s"NtuCharging: Vehicle ${vehicle.GUID} is charging NTU capacitor.") + + if(vehicle.Capacitor < vehicle.Definition.MaximumCapacitor) { + // Charging + vehicle.Capacitor += 100 + + sendResponse(PlanetsideAttributeMessage(vehicle.GUID, 45, scala.math.round((vehicle.Capacitor.toFloat / vehicle.Definition.MaximumCapacitor.toFloat) * 10) )) // set ntu on vehicle UI + avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(vehicle.GUID, 52, 1L)) // panel glow on + avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(vehicle.GUID, 49, 1L)) // orb particle effect on + + antChargingTick = context.system.scheduler.scheduleOnce(1000 milliseconds, self, NtuCharging(player, vehicle)) // Repeat until fully charged + } else { + // Fully charged + sendResponse(PlanetsideAttributeMessage(vehicle.GUID, 45, scala.math.round((vehicle.Capacitor.toFloat / vehicle.Definition.MaximumCapacitor.toFloat) * 10).toInt)) // set ntu on vehicle UI + + // Turning off glow/orb effects on ANT doesn't seem to work when deployed. Try to undeploy ANT from server side + context.system.scheduler.scheduleOnce(vehicle.UndeployTime milliseconds, vehicle.Actor, Deployment.TryUndeploy(DriveState.Undeploying)) + } + case ItemHacking(tplayer, target, tool_guid, delta, completeAction, tickAction) => progressBarUpdate.cancel if(progressBarValue.isDefined) { @@ -4082,6 +4105,27 @@ class WorldSessionActor extends Actor with MDCContextAware { case _ => ; } } + if(obj.Definition == GlobalDefinitions.ant) { + obj.DeploymentState match { + case DriveState.Deployed => + // We only want this WSA (not other player's WSA) to manage timers + if(vehicle.Seat(0).get.Occupant.contains(player)){ + // Start ntu regeneration + // If vehicle sends UseItemMessage with silo as target NTU regeneration will be disabled and orb particles will be disabled + antChargingTick = context.system.scheduler.scheduleOnce(1000 milliseconds, self, NtuCharging(player, vehicle)) + } + case DriveState.Undeploying => + // We only want this WSA (not other player's WSA) to manage timers + if(vehicle.Seat(0).get.Occupant.contains(player)){ + antChargingTick.cancel() // Stop charging NTU if charging + } + + avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(obj.GUID, 52, 0L)) // panel glow off + avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(obj.GUID, 49, 0L)) // orb particles off + case DriveState.Mobile | DriveState.State7 | DriveState.Deploying => + case _ => ; + } + } case _ => ; } } @@ -4817,4 +4861,7 @@ object WorldSessionActor { delta : Float, completeAction : () => Unit, tickAction : Option[() => Unit] = None) + + private final case class NtuCharging(tplayer: Player, + vehicle: Vehicle) } From d55cd6ef9f86a8b56422345619b4f62790337451 Mon Sep 17 00:00:00 2001 From: Mazo Date: Sat, 26 May 2018 12:54:47 +0100 Subject: [PATCH 08/17] Functionality for discharging ANT into resource silo --- .../src/main/scala/WorldSessionActor.scala | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index fbf3d203..18d62cf9 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -29,6 +29,7 @@ import net.psforever.objects.serverobject.locks.IFFLock import net.psforever.objects.serverobject.mblocker.Locker import net.psforever.objects.serverobject.pad.{VehicleSpawnControl, VehicleSpawnPad} import net.psforever.objects.serverobject.pad.process.{AutoDriveControls, VehicleSpawnControlGuided} +import net.psforever.objects.serverobject.resourcesilo.ResourceSilo import net.psforever.objects.serverobject.structures.{Building, StructureType, WarpGate} import net.psforever.objects.serverobject.terminals._ import net.psforever.objects.serverobject.terminals.Terminal.TerminalMessage @@ -85,6 +86,7 @@ class WorldSessionActor extends Actor with MDCContextAware { var reviveTimer : Cancellable = DefaultCancellable.obj var respawnTimer : Cancellable = DefaultCancellable.obj var antChargingTick : Cancellable = DefaultCancellable.obj + var antDischargingTick : Cancellable = DefaultCancellable.obj /** * Convert a boolean value into an integer value. @@ -628,6 +630,17 @@ class WorldSessionActor extends Actor with MDCContextAware { case Deployment.CanNotChangeDeployment(obj, state, reason) => CanNotChangeDeployment(obj, state, reason) + case ResourceSilo.ResourceSiloMessage(tplayer, msg, order) => + val vehicle_guid = msg.avatar_guid + val silo_guid = msg.object_guid + order match { + case ResourceSilo.ChargeEvent() => + antChargingTick.cancel() // If an ANT is refilling a NTU silo it isn't in a warpgate, so disable NTU regeneration + antDischargingTick.cancel() + + antDischargingTick = context.system.scheduler.scheduleOnce(1000 milliseconds, self, NtuDischarging(player, continent.GUID(vehicle_guid).get.asInstanceOf[Vehicle], silo_guid)) + } + case Door.DoorMessage(tplayer, msg, order) => val door_guid = msg.object_guid order match { @@ -1515,6 +1528,70 @@ class WorldSessionActor extends Actor with MDCContextAware { context.system.scheduler.scheduleOnce(vehicle.UndeployTime milliseconds, vehicle.Actor, Deployment.TryUndeploy(DriveState.Undeploying)) } + case NtuDischarging(tplayer, vehicle, silo_guid) => + log.trace(s"NtuDischarging: Vehicle ${vehicle.GUID} is discharging NTU into silo $silo_guid") + avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(vehicle.GUID, 49, 0L)) // orb particle effect off + avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(vehicle.GUID, 52, 1L)) // panel glow on + + var silo = continent.GUID(silo_guid).get.asInstanceOf[ResourceSilo] + + // Check vehicle is still deployed before continuing. User can undeploy manually or vehicle may not longer be present. + if(vehicle.DeploymentState == DriveState.Deployed) { + if(vehicle.Capacitor > 0 && silo.ChargeLevel < silo.MaximumCharge) { + + // Make sure we don't exceed the silo maximum charge or remove much NTU from ANT if maximum is reached, or try to make ANT go below 0 NTU + var chargeToDeposit = Math.min(Math.min(vehicle.Capacitor, 100), (silo.MaximumCharge - silo.ChargeLevel)) + vehicle.Capacitor -= chargeToDeposit + silo.Actor ! ResourceSilo.UpdateChargeLevel(chargeToDeposit) + + log.warn(AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(silo_guid, 45, 1L)).toString) +// avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(silo_guid, 45, 1L)) // set silo ntu level + avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(silo_guid, 49, 1L)) // panel glow on & orb particles on + + sendResponse(PlanetsideAttributeMessage(vehicle.GUID, 45, scala.math.round((vehicle.Capacitor.toFloat / vehicle.Definition.MaximumCapacitor.toFloat) * 10))) // set ntu on vehicle UI +// avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(silo_guid, 45, scala.math.round((silo.ChargeLevel.toFloat / silo.MaximumCharge.toFloat) * 10))) // set ntu on silo bar + + //todo: grant BEP to user + //todo: grant BEP to squad in range + //todo: notify map service to update ntu % on map for all users + + //todo: handle silo orb / panel glow properly if more than one person is refilling silo and one player stops. effects should stay on until all players stop + + if(vehicle.Capacitor > 0 && silo.ChargeLevel < silo.MaximumCharge) { + log.trace(s"NtuDischarging: ANT not empty and Silo not full. Scheduling another discharge") + // Silo still not full and ant still has charge left - keep rescheduling ticks + antDischargingTick = context.system.scheduler.scheduleOnce(1000 milliseconds, self, NtuDischarging(player, vehicle, silo_guid)) + } else { + log.trace(s"NtuDischarging: ANT NTU empty or Silo NTU full.") + + // Turning off glow/orb effects on ANT doesn't seem to work when deployed. Try to undeploy ANT from server side + context.system.scheduler.scheduleOnce(vehicle.UndeployTime milliseconds, vehicle.Actor, Deployment.TryUndeploy(DriveState.Undeploying)) + + avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(silo_guid, 49, 0L)) // panel glow off & orb particles off + antDischargingTick.cancel() + } + } else { + // This shouldn't normally be run, only if the client thinks the ANT has capacitor charge when it doesn't, or thinks the silo isn't full when it is. + log.warn(s"NtuDischarging: Invalid discharge state. ANT Capacitor: ${vehicle.Capacitor} Silo Capacitor: ${silo.ChargeLevel}") + + // Turning off glow/orb effects on ANT doesn't seem to work when deployed. Try to undeploy ANT from server side + context.system.scheduler.scheduleOnce(vehicle.UndeployTime milliseconds, vehicle.Actor, Deployment.TryUndeploy(DriveState.Undeploying)) + + avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(silo_guid, 49, 0L)) // panel glow off & orb particles off + antDischargingTick.cancel() + } + } else { + log.trace(s"NtuDischarging: Vehicle is no longer deployed. Removing effects") + // Vehicle has changed from deployed and this should be the last timer tick sent + avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(vehicle.GUID, 52, 0L)) // panel glow off + avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(silo_guid, 49, 0L)) // panel glow off & orb particles off + antDischargingTick.cancel() + } + + + + + case ItemHacking(tplayer, target, tool_guid, delta, completeAction, tickAction) => progressBarUpdate.cancel if(progressBarValue.isDefined) { @@ -2450,6 +2527,20 @@ class WorldSessionActor extends Actor with MDCContextAware { sendResponse(GenericObjectStateMsg(object_guid, 16)) } + case Some(resourceSilo : ResourceSilo) => + log.info(s"UseItem: Vehicle $avatar_guid is refilling resource silo $object_guid") + val vehicle = continent.GUID(avatar_guid).get.asInstanceOf[Vehicle] + + if(resourceSilo.Faction == PlanetSideEmpire.NEUTRAL || player.Faction == resourceSilo.Faction) { + if(vehicle.Seat(0).get.Occupant.contains(player)) { + log.trace("UseItem: Player matches vehicle driver. Calling ResourceSilo.Use") + resourceSilo.Actor ! ResourceSilo.Use(player, msg) + } + } else { + log.warn(s"Player ${player.GUID} - ${player.Faction} tried to refill silo ${resourceSilo.GUID} - ${resourceSilo.Faction} belonging to another empire") + } + + case Some(panel : IFFLock) => if(panel.Faction != player.Faction && panel.HackedBy.isEmpty) { player.Slot(player.DrawnSlot).Equipment match { @@ -4864,4 +4955,5 @@ object WorldSessionActor { private final case class NtuCharging(tplayer: Player, vehicle: Vehicle) + private final case class NtuDischarging(tplayer: Player, vehicle: Vehicle, silo_guid: PlanetSideGUID) } From aa81116260714bf19ff8e8a4f95fb246aacae1e2 Mon Sep 17 00:00:00 2001 From: Mazo Date: Sat, 26 May 2018 12:55:57 +0100 Subject: [PATCH 09/17] Sync resource silo charge level on continent map with clients on zone entry --- .../src/main/scala/WorldSessionActor.scala | 46 +++++++++++-------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index 18d62cf9..b7c1ac86 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -4276,29 +4276,35 @@ class WorldSessionActor extends Actor with MDCContextAware { * @param building the building object */ def initFacility(continentNumber : Int, buildingNumber : Int, building : Building) : Unit = { + var ntuLevel = 0 + building.Amenities.filter(x => (x.Definition == GlobalDefinitions.resource_silo)).headOption.asInstanceOf[Option[ResourceSilo]] match { + case Some(obj: ResourceSilo) => ntuLevel = obj.CapacitorDisplay.toInt + case _ => ; + } + sendResponse( BuildingInfoUpdateMessage( - continentNumber, //Zone - buildingNumber, //Facility - 8, //NTU% - false, //Hacked + continent_id = continentNumber, //Zone + building_id = buildingNumber, //Facility + ntu_level = ntuLevel, + is_hacked = false, //Hacked PlanetSideEmpire.NEUTRAL, //Base hacked by - 0, //Time remaining for hack (ms) - building.Faction, //Base owned by - 0, //!! Field != 0 will cause malformed packet. See class def. - None, - PlanetSideGeneratorState.Normal, //Generator state - true, //Respawn tubes operating state - false, //Force dome state - 0, //Lattice benefits - 0, //!! Field > 0 will cause malformed packet. See class def. - Nil, - 0, - false, - 8, //!! Field != 8 will cause malformed packet. See class def. - None, - false, //Boosted spawn room pain field - false //Boosted generator room pain field + hack_time_remaining = 0, //Time remaining for hack (ms) + empire_own = building.Faction, //Base owned by + unk1 = 0, //!! Field != 0 will cause malformed packet. See class def. + unk1x = None, + generator_state = PlanetSideGeneratorState.Normal, //Generator state + spawn_tubes_normal = true, //Respawn tubes operating state + force_dome_active = false, //Force dome state + lattice_benefit = 0, //Lattice benefits + cavern_benefit = 0, //!! Field > 0 will cause malformed packet. See class def. + unk4 = Nil, + unk5 = 0, + unk6 = false, + unk7 = 8, //!! Field != 8 will cause malformed packet. See class def. + unk7x = None, + boost_spawn_pain = false, //Boosted spawn room pain field + boost_generator_pain = false //Boosted generator room pain field ) ) sendResponse(DensityLevelUpdateMessage(continentNumber, buildingNumber, List(0,0, 0,0, 0,0, 0,0))) From 86bb83dc096b478bd1dda708793b95feeb54531b Mon Sep 17 00:00:00 2001 From: Mazo Date: Sat, 26 May 2018 16:37:42 +0100 Subject: [PATCH 10/17] Rename existing galaxy service to cluster and add GalaxyService to send map updates to all connected clients --- .../resourcesilo/ResourceSilo.scala | 1 - .../resourcesilo/ResourceSiloControl.scala | 6 +-- .../scala/services/galaxy/GalaxyAction.scala | 10 ++++ .../services/galaxy/GalaxyResponse.scala | 10 ++++ .../scala/services/galaxy/GalaxyService.scala | 50 +++++++++++++++++++ .../galaxy/GalaxyServiceMessage.scala | 4 ++ .../galaxy/GalaxyServiceResponse.scala | 9 ++++ pslogin/src/main/scala/PsLogin.scala | 4 +- .../src/main/scala/WorldSessionActor.scala | 42 ++++++++++------ 9 files changed, 114 insertions(+), 22 deletions(-) create mode 100644 common/src/main/scala/services/galaxy/GalaxyAction.scala create mode 100644 common/src/main/scala/services/galaxy/GalaxyResponse.scala create mode 100644 common/src/main/scala/services/galaxy/GalaxyService.scala create mode 100644 common/src/main/scala/services/galaxy/GalaxyServiceMessage.scala create mode 100644 common/src/main/scala/services/galaxy/GalaxyServiceResponse.scala diff --git a/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSilo.scala b/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSilo.scala index 9e653c31..d62dccb0 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSilo.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSilo.scala @@ -56,7 +56,6 @@ object ResourceSilo { final case class Use(player: Player, msg : UseItemMessage) final case class UpdateChargeLevel(amount: Int) final case class LowNtuWarning(enabled: Int) - final case class SyncStateWithClient() sealed trait Exchange final case class ChargeEvent() extends Exchange final case class ResourceSiloMessage(player: Player, msg : UseItemMessage, response : Exchange) diff --git a/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala b/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala index 18e38fde..9e711958 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala @@ -24,7 +24,7 @@ class ResourceSiloControl(resourceSilo : ResourceSilo) extends Actor with Factio def receive : Receive = { case "startup" => - ServiceManager.serviceManager ! Lookup("avatar") //ask for a resolver to deal with the GUID system + ServiceManager.serviceManager ! Lookup("avatar") case ServiceManager.LookupResult("avatar", endpoint) => avatarService = endpoint @@ -69,10 +69,6 @@ class ResourceSiloControl(resourceSilo : ResourceSilo) extends Actor with Factio } //todo: Shut down base power and make base neutral if silo hits zero NTU - case ResourceSilo.SyncStateWithClient() => - avatarService ! AvatarServiceMessage(resourceSilo.Owner.asInstanceOf[Building].Zone.Id, AvatarAction.PlanetsideAttribute(PlanetSideGUID(resourceSilo.Owner.asInstanceOf[Building].ModelId), 47, resourceSilo.LowNtuWarningOn)) - avatarService ! AvatarServiceMessage(resourceSilo.Owner.asInstanceOf[Building].Zone.Id, AvatarAction.PlanetsideAttribute(resourceSilo.GUID, 45, resourceSilo.CapacitorDisplay)) - case _ => ; } diff --git a/common/src/main/scala/services/galaxy/GalaxyAction.scala b/common/src/main/scala/services/galaxy/GalaxyAction.scala new file mode 100644 index 00000000..7bb9c794 --- /dev/null +++ b/common/src/main/scala/services/galaxy/GalaxyAction.scala @@ -0,0 +1,10 @@ +// Copyright (c) 2017 PSForever +package services.galaxy + +import net.psforever.packet.game.{BuildingInfoUpdateMessage} + +object GalaxyAction { + trait Action + + final case class MapUpdate(msg: BuildingInfoUpdateMessage) extends Action +} diff --git a/common/src/main/scala/services/galaxy/GalaxyResponse.scala b/common/src/main/scala/services/galaxy/GalaxyResponse.scala new file mode 100644 index 00000000..8026085f --- /dev/null +++ b/common/src/main/scala/services/galaxy/GalaxyResponse.scala @@ -0,0 +1,10 @@ +// Copyright (c) 2017 PSForever +package services.galaxy + +import net.psforever.packet.game.{BuildingInfoUpdateMessage} + +object GalaxyResponse { + trait Response + + final case class MapUpdate(msg: BuildingInfoUpdateMessage) extends Response +} diff --git a/common/src/main/scala/services/galaxy/GalaxyService.scala b/common/src/main/scala/services/galaxy/GalaxyService.scala new file mode 100644 index 00000000..2e83802e --- /dev/null +++ b/common/src/main/scala/services/galaxy/GalaxyService.scala @@ -0,0 +1,50 @@ +// Copyright (c) 2017 PSForever +package services.galaxy + +import akka.actor.{Actor, Props} +import net.psforever.packet.game.BuildingInfoUpdateMessage +import services.local.support.{DoorCloseActor, HackClearActor} +import services.{GenericEventBus, Service} + +class GalaxyService extends Actor { + private [this] val log = org.log4s.getLogger + + override def preStart = { + log.info("Starting...") + } + + val GalaxyEvents = new GenericEventBus[GalaxyServiceResponse] + + def receive = { + // Service.Join requires a channel to be passed in normally but GalaxyService is an exception in that messages go to ALL connected players + case Service.Join(_) => + val path = s"/Galaxy" + val who = sender() + log.info(s"$who has joined $path") + GalaxyEvents.subscribe(who, path) + + case Service.Leave(None) => + GalaxyEvents.unsubscribe(sender()) + + case Service.Leave(_) => + val path = s"/Galaxy" + val who = sender() + log.info(s"$who has left $path") + GalaxyEvents.unsubscribe(who, path) + + case Service.LeaveAll() => + GalaxyEvents.unsubscribe(sender()) + + case GalaxyServiceMessage(action) => + action match { + case GalaxyAction.MapUpdate(msg: BuildingInfoUpdateMessage) => + log.warn(s"Publishing msg ${msg}") + GalaxyEvents.publish( + GalaxyServiceResponse(s"/Galaxy", GalaxyResponse.MapUpdate(msg)) + ) + case _ => ; + } + case msg => + log.info(s"Unhandled message $msg from $sender") + } +} diff --git a/common/src/main/scala/services/galaxy/GalaxyServiceMessage.scala b/common/src/main/scala/services/galaxy/GalaxyServiceMessage.scala new file mode 100644 index 00000000..a013af5e --- /dev/null +++ b/common/src/main/scala/services/galaxy/GalaxyServiceMessage.scala @@ -0,0 +1,4 @@ +// Copyright (c) 2017 PSForever +package services.galaxy + +final case class GalaxyServiceMessage(actionMessage : GalaxyAction.Action) diff --git a/common/src/main/scala/services/galaxy/GalaxyServiceResponse.scala b/common/src/main/scala/services/galaxy/GalaxyServiceResponse.scala new file mode 100644 index 00000000..28125a89 --- /dev/null +++ b/common/src/main/scala/services/galaxy/GalaxyServiceResponse.scala @@ -0,0 +1,9 @@ +// Copyright (c) 2017 PSForever +package services.galaxy + +import net.psforever.packet.game.PlanetSideGUID +import services.GenericEventBusMsg + +final case class GalaxyServiceResponse(toChannel : String, + replyMessage : GalaxyResponse.Response + ) extends GenericEventBusMsg diff --git a/pslogin/src/main/scala/PsLogin.scala b/pslogin/src/main/scala/PsLogin.scala index e689aa9e..469ed631 100644 --- a/pslogin/src/main/scala/PsLogin.scala +++ b/pslogin/src/main/scala/PsLogin.scala @@ -19,6 +19,7 @@ import org.fusesource.jansi.Ansi._ import org.fusesource.jansi.Ansi.Color._ import services.ServiceManager import services.avatar._ +import services.galaxy.GalaxyService import services.local._ import services.vehicle.VehicleService @@ -209,7 +210,8 @@ object PsLogin { serviceManager ! ServiceManager.Register(Props[AvatarService], "avatar") serviceManager ! ServiceManager.Register(Props[LocalService], "local") serviceManager ! ServiceManager.Register(Props[VehicleService], "vehicle") - serviceManager ! ServiceManager.Register(Props(classOf[InterstellarCluster], continentList), "galaxy") + serviceManager ! ServiceManager.Register(Props[GalaxyService], "galaxy") + serviceManager ! ServiceManager.Register(Props(classOf[InterstellarCluster], continentList), "cluster") //attach event bus entry point to each zone import akka.pattern.ask diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index b7c1ac86..c0d5dde0 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -40,6 +40,7 @@ import net.psforever.packet.game.objectcreate._ import net.psforever.types._ import services._ import services.avatar.{AvatarAction, AvatarResponse, AvatarServiceMessage, AvatarServiceResponse} +import services.galaxy.{GalaxyResponse, GalaxyServiceResponse} import services.local.{LocalAction, LocalResponse, LocalServiceMessage, LocalServiceResponse} import services.vehicle.VehicleAction.UnstowEquipment import services.vehicle.{VehicleAction, VehicleResponse, VehicleServiceMessage, VehicleServiceResponse} @@ -59,8 +60,9 @@ class WorldSessionActor extends Actor with MDCContextAware { var avatarService : ActorRef = ActorRef.noSender var localService : ActorRef = ActorRef.noSender var vehicleService : ActorRef = ActorRef.noSender + var galaxyService : ActorRef = ActorRef.noSender var taskResolver : ActorRef = Actor.noSender - var galaxy : ActorRef = Actor.noSender + var cluster : ActorRef = Actor.noSender var continent : Zone = Zone.Nowhere var player : Player = null var avatar : Avatar = null @@ -104,6 +106,7 @@ class WorldSessionActor extends Actor with MDCContextAware { localService ! Service.Leave() vehicleService ! Service.Leave() avatarService ! Service.Leave() + galaxyService ! Service.Leave() LivePlayerList.Remove(sessionId) if(player != null && player.HasGUID) { @@ -217,6 +220,7 @@ class WorldSessionActor extends Actor with MDCContextAware { ServiceManager.serviceManager ! Lookup("local") ServiceManager.serviceManager ! Lookup("vehicle") ServiceManager.serviceManager ! Lookup("taskResolver") + ServiceManager.serviceManager ! Lookup("cluster") ServiceManager.serviceManager ! Lookup("galaxy") case _ => @@ -238,8 +242,11 @@ class WorldSessionActor extends Actor with MDCContextAware { taskResolver = endpoint log.info("ID: " + sessionId + " Got task resolver service " + endpoint) case ServiceManager.LookupResult("galaxy", endpoint) => - galaxy = endpoint + galaxyService = endpoint log.info("ID: " + sessionId + " Got galaxy service " + endpoint) + case ServiceManager.LookupResult("cluster", endpoint) => + cluster = endpoint + log.info("ID: " + sessionId + " Got cluster service " + endpoint) case ControlPacket(_, ctrl) => handleControlPkt(ctrl) @@ -409,6 +416,13 @@ class WorldSessionActor extends Actor with MDCContextAware { case _ => ; } + case GalaxyServiceResponse(_, reply) => + reply match { + case GalaxyResponse.MapUpdate(msg) => + log.warn(s"Client ${player.GUID} Updating map ${msg}") + sendResponse(msg) + } + case LocalServiceResponse(_, guid, reply) => val tplayer_guid = if(player.HasGUID) { player.GUID} else { PlanetSideGUID(0) } reply match { @@ -1385,7 +1399,7 @@ class WorldSessionActor extends Actor with MDCContextAware { reviveTimer.cancel if(spawn_group == 2) { sendResponse(ChatMsg(ChatMessageType.CMT_OPEN, false, "", "No friendly AMS is deployed in this region.", None)) - galaxy ! Zone.Lattice.RequestSpawnPoint(zone_number, player, 0) + cluster ! Zone.Lattice.RequestSpawnPoint(zone_number, player, 0) } else { RequestSanctuaryZoneSpawn(player, zone_number) @@ -1401,7 +1415,7 @@ class WorldSessionActor extends Actor with MDCContextAware { sendResponse(ReplicationStreamMessage(5, Some(6), Vector(SquadListing()))) //clear squad list sendResponse(FriendsResponse(FriendAction.InitializeFriendList, 0, true, true, Nil)) sendResponse(FriendsResponse(FriendAction.InitializeIgnoreList, 0, true, true, Nil)) - galaxy ! InterstellarCluster.GetWorld("z6") + cluster ! InterstellarCluster.GetWorld("z6") case InterstellarCluster.GiveWorld(zoneId, zone) => log.info(s"Zone $zoneId will now load") @@ -1544,12 +1558,8 @@ class WorldSessionActor extends Actor with MDCContextAware { vehicle.Capacitor -= chargeToDeposit silo.Actor ! ResourceSilo.UpdateChargeLevel(chargeToDeposit) - log.warn(AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(silo_guid, 45, 1L)).toString) -// avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(silo_guid, 45, 1L)) // set silo ntu level avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(silo_guid, 49, 1L)) // panel glow on & orb particles on - sendResponse(PlanetsideAttributeMessage(vehicle.GUID, 45, scala.math.round((vehicle.Capacitor.toFloat / vehicle.Definition.MaximumCapacitor.toFloat) * 10))) // set ntu on vehicle UI -// avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(silo_guid, 45, scala.math.round((silo.ChargeLevel.toFloat / silo.MaximumCharge.toFloat) * 10))) // set ntu on silo bar //todo: grant BEP to user //todo: grant BEP to squad in range @@ -1723,7 +1733,7 @@ class WorldSessionActor extends Actor with MDCContextAware { //TODO check if can spawn on last continent/location from player? //TODO if yes, get continent guid accessors //TODO if no, get sanctuary guid accessors and reset the player's expectations - galaxy ! InterstellarCluster.RequestClientInitialization() + cluster ! InterstellarCluster.RequestClientInitialization() case default => log.error("Unsupported " + default + " in " + msg) } @@ -1738,6 +1748,7 @@ class WorldSessionActor extends Actor with MDCContextAware { avatarService ! Service.Join(continent.Id) localService ! Service.Join(continent.Id) vehicleService ! Service.Join(continent.Id) + galaxyService ! Service.Join("galaxy") configZone(continent) sendResponse(TimeOfDayMessage(1191182336)) //custom @@ -1935,7 +1946,7 @@ class WorldSessionActor extends Actor with MDCContextAware { case msg @ SpawnRequestMessage(u1, u2, u3, u4, u5) => log.info(s"SpawnRequestMessage: $msg") //TODO just focus on u5 and u2 for now - galaxy ! Zone.Lattice.RequestSpawnPoint(u5.toInt, player, u2.toInt) + cluster ! Zone.Lattice.RequestSpawnPoint(u5.toInt, player, u2.toInt) case msg @ SetChatFilterMessage(send_channel, origin, whitelist) => log.info("SetChatFilters: " + msg) @@ -2038,7 +2049,7 @@ class WorldSessionActor extends Actor with MDCContextAware { else if(trimContents.equals("!ams")) { makeReply = false if(player.isBackpack) { //player is on deployment screen (either dead or deconstructed) - galaxy ! Zone.Lattice.RequestSpawnPoint(continent.Number, player, 2) + cluster ! Zone.Lattice.RequestSpawnPoint(continent.Number, player, 2) } } // TODO: Depending on messagetype, may need to prepend sender's name to contents with proper spacing @@ -3410,7 +3421,7 @@ class WorldSessionActor extends Actor with MDCContextAware { def TaskBeforeZoneChange(priorTask : TaskResolver.GiveTask, zoneId : String) : TaskResolver.GiveTask = { TaskResolver.GiveTask( new Task() { - private val localService = galaxy + private val localService = cluster private val localMsg = InterstellarCluster.GetWorld(zoneId) override def isComplete : Task.Resolution.Value = priorTask.task.isComplete @@ -4278,7 +4289,8 @@ class WorldSessionActor extends Actor with MDCContextAware { def initFacility(continentNumber : Int, buildingNumber : Int, building : Building) : Unit = { var ntuLevel = 0 building.Amenities.filter(x => (x.Definition == GlobalDefinitions.resource_silo)).headOption.asInstanceOf[Option[ResourceSilo]] match { - case Some(obj: ResourceSilo) => ntuLevel = obj.CapacitorDisplay.toInt + case Some(obj: ResourceSilo) => + ntuLevel = obj.CapacitorDisplay.toInt case _ => ; } @@ -4410,7 +4422,7 @@ class WorldSessionActor extends Actor with MDCContextAware { import scala.concurrent.duration._ import scala.concurrent.ExecutionContext.Implicits.global - reviveTimer = context.system.scheduler.scheduleOnce(respawnTimer milliseconds, galaxy, Zone.Lattice.RequestSpawnPoint(Zones.SanctuaryZoneNumber(tplayer.Faction), tplayer, 7)) + reviveTimer = context.system.scheduler.scheduleOnce(respawnTimer milliseconds, cluster, Zone.Lattice.RequestSpawnPoint(Zones.SanctuaryZoneNumber(tplayer.Faction), tplayer, 7)) } /** @@ -4575,7 +4587,7 @@ class WorldSessionActor extends Actor with MDCContextAware { sendResponse(DisconnectMessage("Player failed to load on faction's sanctuary continent. Please relog.")) } else { - galaxy ! Zone.Lattice.RequestSpawnPoint(sanctNumber, tplayer, 7) + cluster ! Zone.Lattice.RequestSpawnPoint(sanctNumber, tplayer, 7) } } From d72e1adf0455eb52940abbc77c58a00e597f8b95 Mon Sep 17 00:00:00 2001 From: Mazo Date: Sat, 26 May 2018 16:38:02 +0100 Subject: [PATCH 11/17] Sync resource silo display & warning light with newly connected clients --- pslogin/src/main/scala/WorldSessionActor.scala | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index c0d5dde0..950176ab 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -4377,6 +4377,14 @@ class WorldSessionActor extends Actor with MDCContextAware { val amenityId = amenity.GUID sendResponse(PlanetsideAttributeMessage(amenityId, 50, 0)) sendResponse(PlanetsideAttributeMessage(amenityId, 51, 0)) + + amenity.Definition match { + case GlobalDefinitions.resource_silo => + // Synchronise warning light & silo capacity + sendResponse(PlanetsideAttributeMessage(amenityId, 45, amenity.asInstanceOf[ResourceSilo].CapacitorDisplay)) + sendResponse(PlanetsideAttributeMessage(amenityId, 47, amenity.asInstanceOf[ResourceSilo].LowNtuWarningOn)) + case _ => ; + } }) sendResponse(HackMessage(3, PlanetSideGUID(building.ModelId), PlanetSideGUID(0), 0, 3212836864L, HackState.HackCleared, 8)) }) From b326cdf53067ef63095268bd1774b31050e86658 Mon Sep 17 00:00:00 2001 From: Mazo Date: Sat, 26 May 2018 16:38:49 +0100 Subject: [PATCH 12/17] Add functionality for BuildingControl to send map updates to all clients via GalaxyService --- .../serverobject/structures/Building.scala | 4 ++ .../structures/BuildingControl.scala | 66 ++++++++++++++++++- 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala b/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala index 3ebb145a..416b8662 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala @@ -68,6 +68,7 @@ object Building { val obj = new Building(id, zone, buildingType) obj.Position = location obj.Actor = context.actorOf(Props(classOf[BuildingControl], obj), s"$id-$buildingType-building") + obj.Actor ! "startup" obj } @@ -75,6 +76,9 @@ object Building { import akka.actor.Props val obj = new Building(id, zone, buildingType) obj.Actor = context.actorOf(Props(classOf[BuildingControl], obj), s"$id-$buildingType-building") + obj.Actor ! "startup" obj } + + final case class SendMapUpdateToAllClients() } diff --git a/common/src/main/scala/net/psforever/objects/serverobject/structures/BuildingControl.scala b/common/src/main/scala/net/psforever/objects/serverobject/structures/BuildingControl.scala index 87ac9a1b..ab6926f1 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/structures/BuildingControl.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/structures/BuildingControl.scala @@ -1,19 +1,79 @@ // Copyright (c) 2017 PSForever package net.psforever.objects.serverobject.structures -import akka.actor.Actor +import akka.actor.{Actor, ActorRef} +import net.psforever.objects.GlobalDefinitions import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior} +import net.psforever.objects.serverobject.resourcesilo.ResourceSilo +import net.psforever.packet.game.{BuildingInfoUpdateMessage, PlanetSideGeneratorState} +import net.psforever.types.PlanetSideEmpire +import services.ServiceManager +import services.ServiceManager.Lookup +import services.galaxy.{GalaxyAction, GalaxyServiceMessage} class BuildingControl(building : Building) extends Actor with FactionAffinityBehavior.Check { def FactionObject : FactionAffinity = building + var galaxyService : ActorRef = Actor.noSender + private[this] val log = org.log4s.getLogger - def receive : Receive = checkBehavior.orElse { + def receive : Receive = { + case "startup" => + log.warn(s"Building ${building.GUID} / ${building.ModelId} / ${building.Id} in startup") + ServiceManager.serviceManager ! Lookup("galaxy") //ask for a resolver to deal with the GUID system + + case ServiceManager.LookupResult("galaxy", endpoint) => + galaxyService = endpoint + log.info("BuildingControl: Building " + building.ModelId + " Got galaxy service " + endpoint) + + // todo: This is just a temporary solution to drain NTU over time. When base object destruction is properly implemented NTU should be deducted when base objects repair themselves + context.become(Processing) + + case _ => log.warn("Message received before startup called"); + } + + def Processing : Receive = checkBehavior.orElse { case FactionAffinity.ConvertFactionAffinity(faction) => val originalAffinity = building.Faction if(originalAffinity != (building.Faction = faction)) { building.Amenities.foreach(_.Actor forward FactionAffinity.ConfirmFactionAffinity()) } sender ! FactionAffinity.AssertFactionAffinity(building, faction) - case _ => ; + case Building.SendMapUpdateToAllClients() => + log.info(s"Sending facility map update to all clients. Zone: ${building.Zone.Number} - Building: ${building.ModelId}") + var ntuLevel = 0 + building.Amenities.filter(x => (x.Definition == GlobalDefinitions.resource_silo)).headOption.asInstanceOf[Option[ResourceSilo]] match { + case Some(obj: ResourceSilo) => + ntuLevel = obj.CapacitorDisplay.toInt + case _ => ; + } + galaxyService ! GalaxyServiceMessage(GalaxyAction.MapUpdate( + BuildingInfoUpdateMessage( + continent_id = building.Zone.Number, //Zone + building_id = building.Id, //Facility + ntu_level = ntuLevel, + is_hacked = false, //Hacked + PlanetSideEmpire.NEUTRAL, //Base hacked by + hack_time_remaining = 0, //Time remaining for hack (ms) + empire_own = building.Faction, //Base owned by + unk1 = 0, //!! Field != 0 will cause malformed packet. See class def. + unk1x = None, + generator_state = PlanetSideGeneratorState.Normal, //Generator state + spawn_tubes_normal = true, //Respawn tubes operating state + force_dome_active = false, //Force dome state + lattice_benefit = 0, //Lattice benefits + cavern_benefit = 0, //!! Field > 0 will cause malformed packet. See class def. + unk4 = Nil, + unk5 = 0, + unk6 = false, + unk7 = 8, //!! Field != 8 will cause malformed packet. See class def. + unk7x = None, + boost_spawn_pain = false, //Boosted spawn room pain field + boost_generator_pain = false //Boosted generator room pain field + ))) + case _ => + log.warn(s"BuildingControl: Unknown message received from ${sender().path}") +// case default => +// log.warn(s"BuildingControl: Unknown message ${default} received from ${sender().path}") + } } From a4c2085fb7d461b50a5202a93b54a826b0321c44 Mon Sep 17 00:00:00 2001 From: Mazo Date: Sat, 26 May 2018 16:39:12 +0100 Subject: [PATCH 13/17] Sync silo NTU level on map with all clients when it changes --- .../objects/serverobject/resourcesilo/ResourceSiloControl.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala b/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala index 9e711958..20d9b5e4 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala @@ -59,6 +59,7 @@ class ResourceSiloControl(resourceSilo : ResourceSilo) extends Actor with Factio if(resourceSilo.CapacitorDisplay != ntuBarLevel) { log.trace(s"Silo ${resourceSilo.GUID} NTU bar level has changed from ${resourceSilo.CapacitorDisplay} to ${ntuBarLevel}") resourceSilo.CapacitorDisplay = ntuBarLevel + resourceSilo.Owner.Actor ! Building.SendMapUpdateToAllClients() avatarService ! AvatarServiceMessage(resourceSilo.Owner.asInstanceOf[Building].Zone.Id, AvatarAction.PlanetsideAttribute(resourceSilo.GUID, 45, resourceSilo.CapacitorDisplay)) } From 0ecceebf34c63130abef700860d23752df096fad Mon Sep 17 00:00:00 2001 From: Mazo Date: Sat, 26 May 2018 16:41:53 +0100 Subject: [PATCH 14/17] Change/remove debug logging --- .../serverobject/structures/BuildingControl.scala | 12 ++++-------- pslogin/src/main/scala/WorldSessionActor.scala | 1 - 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/common/src/main/scala/net/psforever/objects/serverobject/structures/BuildingControl.scala b/common/src/main/scala/net/psforever/objects/serverobject/structures/BuildingControl.scala index ab6926f1..f2daedba 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/structures/BuildingControl.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/structures/BuildingControl.scala @@ -18,12 +18,11 @@ class BuildingControl(building : Building) extends Actor with FactionAffinityBeh def receive : Receive = { case "startup" => - log.warn(s"Building ${building.GUID} / ${building.ModelId} / ${building.Id} in startup") ServiceManager.serviceManager ! Lookup("galaxy") //ask for a resolver to deal with the GUID system case ServiceManager.LookupResult("galaxy", endpoint) => galaxyService = endpoint - log.info("BuildingControl: Building " + building.ModelId + " Got galaxy service " + endpoint) + log.trace("BuildingControl: Building " + building.ModelId + " Got galaxy service " + endpoint) // todo: This is just a temporary solution to drain NTU over time. When base object destruction is properly implemented NTU should be deducted when base objects repair themselves context.become(Processing) @@ -39,7 +38,7 @@ class BuildingControl(building : Building) extends Actor with FactionAffinityBeh } sender ! FactionAffinity.AssertFactionAffinity(building, faction) case Building.SendMapUpdateToAllClients() => - log.info(s"Sending facility map update to all clients. Zone: ${building.Zone.Number} - Building: ${building.ModelId}") + log.info(s"Sending BuildingInfoUpdateMessage update to all clients. Zone: ${building.Zone.Number} - Building: ${building.ModelId}") var ntuLevel = 0 building.Amenities.filter(x => (x.Definition == GlobalDefinitions.resource_silo)).headOption.asInstanceOf[Option[ResourceSilo]] match { case Some(obj: ResourceSilo) => @@ -70,10 +69,7 @@ class BuildingControl(building : Building) extends Actor with FactionAffinityBeh boost_spawn_pain = false, //Boosted spawn room pain field boost_generator_pain = false //Boosted generator room pain field ))) - case _ => - log.warn(s"BuildingControl: Unknown message received from ${sender().path}") -// case default => -// log.warn(s"BuildingControl: Unknown message ${default} received from ${sender().path}") - + case default => + log.warn(s"BuildingControl: Unknown message ${default} received from ${sender().path}") } } diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index 950176ab..0e02bb44 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -419,7 +419,6 @@ class WorldSessionActor extends Actor with MDCContextAware { case GalaxyServiceResponse(_, reply) => reply match { case GalaxyResponse.MapUpdate(msg) => - log.warn(s"Client ${player.GUID} Updating map ${msg}") sendResponse(msg) } From fc71bbfd2aebb8bea8b4df7853136fce340d4991 Mon Sep 17 00:00:00 2001 From: Mazo Date: Sat, 26 May 2018 17:13:24 +0100 Subject: [PATCH 15/17] Shut down base power if NTU runs out, and restore it once refilled. --- .../resourcesilo/ResourceSiloControl.scala | 15 +++++++++++++-- .../packet/game/PlanetsideAttributeMessage.scala | 2 +- .../scala/services/galaxy/GalaxyService.scala | 1 - pslogin/src/main/scala/WorldSessionActor.scala | 9 +++++++-- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala b/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala index 20d9b5e4..a92713a0 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala @@ -46,13 +46,14 @@ class ResourceSiloControl(resourceSilo : ResourceSilo) extends Actor with Factio avatarService ! AvatarServiceMessage(resourceSilo.Owner.asInstanceOf[Building].Zone.Id, AvatarAction.PlanetsideAttribute(PlanetSideGUID(resourceSilo.Owner.asInstanceOf[Building].ModelId), 47, resourceSilo.LowNtuWarningOn)) case ResourceSilo.UpdateChargeLevel(amount: Int) => + val siloChargeBeforeChange = resourceSilo.ChargeLevel + // Increase if positive passed in or decrease charge level if negative number is passed in resourceSilo.ChargeLevel += amount if(resourceSilo.ChargeLevel > 0) { log.trace(s"UpdateChargeLevel: Silo ${resourceSilo.GUID} set to ${resourceSilo.ChargeLevel}") } - val ntuIsLow = resourceSilo.ChargeLevel.toFloat / resourceSilo.MaximumCharge.toFloat < 0.2f val ntuBarLevel = scala.math.round((resourceSilo.ChargeLevel.toFloat / resourceSilo.MaximumCharge.toFloat) * 10).toInt // Only send updated capacitor display value to all clients if it has actually changed @@ -63,13 +64,23 @@ class ResourceSiloControl(resourceSilo : ResourceSilo) extends Actor with Factio avatarService ! AvatarServiceMessage(resourceSilo.Owner.asInstanceOf[Building].Zone.Id, AvatarAction.PlanetsideAttribute(resourceSilo.GUID, 45, resourceSilo.CapacitorDisplay)) } + val ntuIsLow = resourceSilo.ChargeLevel.toFloat / resourceSilo.MaximumCharge.toFloat < 0.2f if(resourceSilo.LowNtuWarningOn == 1 && !ntuIsLow){ self ! ResourceSilo.LowNtuWarning(0) } else if (resourceSilo.LowNtuWarningOn == 0 && ntuIsLow) { self ! ResourceSilo.LowNtuWarning(1) } - //todo: Shut down base power and make base neutral if silo hits zero NTU + + if(resourceSilo.ChargeLevel == 0 && siloChargeBeforeChange > 0) { + // Oops, someone let the base run out of power. Shut it all down. + //todo: Make base neutral if silo hits zero NTU + avatarService ! AvatarServiceMessage(resourceSilo.Owner.asInstanceOf[Building].Zone.Id, AvatarAction.PlanetsideAttribute(PlanetSideGUID(resourceSilo.Owner.asInstanceOf[Building].ModelId), 48, 1)) + } else if (siloChargeBeforeChange == 0 && resourceSilo.ChargeLevel > 0) { + // Power restored. Reactor Online. Sensors Online. Weapons Online. All systems nominal. + //todo: Check generator is online before starting up + avatarService ! AvatarServiceMessage(resourceSilo.Owner.asInstanceOf[Building].Zone.Id, AvatarAction.PlanetsideAttribute(PlanetSideGUID(resourceSilo.Owner.asInstanceOf[Building].ModelId), 48, 0)) + } case _ => ; } diff --git a/common/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala b/common/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala index 60bc85ba..3f6705a5 100644 --- a/common/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala +++ b/common/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala @@ -106,7 +106,7 @@ import scodec.codecs._ * `43 - Info on avatar name : 0 = Nothing, 1 = "(LD)" message`
* `45 - NTU charge bar 0-10, 5 = 50% full. Seems to apply to both ANT and NTU Silo (possibly siphons?)`
* 47 - Sets base NTU level to CRITICAL. MUST use base modelId not base GUID - * 48 - Send base power loss message & turns on red warning lights throughout base. MUST use base modelId not base GUID + * 48 - Set to 1 to send base power loss message & turns on red warning lights throughout base. MUST use base modelId not base GUID * 49 - Vehicle texture effects state? (>0 turns on ANT panel glow or ntu silo panel glow + orbs) (bit?) * `52 - Vehicle particle effects? (>0 turns on orbs going towards ANT. Doesn't affect silo) (bit?) * `53 - LFS. Value is 1 to flag LFS`
diff --git a/common/src/main/scala/services/galaxy/GalaxyService.scala b/common/src/main/scala/services/galaxy/GalaxyService.scala index 2e83802e..262d64b4 100644 --- a/common/src/main/scala/services/galaxy/GalaxyService.scala +++ b/common/src/main/scala/services/galaxy/GalaxyService.scala @@ -38,7 +38,6 @@ class GalaxyService extends Actor { case GalaxyServiceMessage(action) => action match { case GalaxyAction.MapUpdate(msg: BuildingInfoUpdateMessage) => - log.warn(s"Publishing msg ${msg}") GalaxyEvents.publish( GalaxyServiceResponse(s"/Galaxy", GalaxyResponse.MapUpdate(msg)) ) diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index 0e02bb44..82aa40c2 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -4380,8 +4380,13 @@ class WorldSessionActor extends Actor with MDCContextAware { amenity.Definition match { case GlobalDefinitions.resource_silo => // Synchronise warning light & silo capacity - sendResponse(PlanetsideAttributeMessage(amenityId, 45, amenity.asInstanceOf[ResourceSilo].CapacitorDisplay)) - sendResponse(PlanetsideAttributeMessage(amenityId, 47, amenity.asInstanceOf[ResourceSilo].LowNtuWarningOn)) + var silo = amenity.asInstanceOf[ResourceSilo] + sendResponse(PlanetsideAttributeMessage(amenityId, 45, silo.CapacitorDisplay)) + sendResponse(PlanetsideAttributeMessage(amenityId, 47, silo.LowNtuWarningOn)) + + if(silo.ChargeLevel == 0) { + sendResponse(PlanetsideAttributeMessage(PlanetSideGUID(silo.Owner.asInstanceOf[Building].ModelId), 48, 1)) + } case _ => ; } }) From 52357415c6aa81b742fb8d7f2c4df602bfec2f91 Mon Sep 17 00:00:00 2001 From: Mazo Date: Sat, 26 May 2018 19:37:34 +0100 Subject: [PATCH 16/17] Temporarily disable base offlining when NTU hits zero, otherwise there's no way to get an ANT onto the continent to refill it until warp gates are functional --- .../serverobject/resourcesilo/ResourceSiloControl.scala | 4 +++- pslogin/src/main/scala/WorldSessionActor.scala | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala b/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala index a92713a0..ae1a5db9 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala @@ -75,7 +75,9 @@ class ResourceSiloControl(resourceSilo : ResourceSilo) extends Actor with Factio if(resourceSilo.ChargeLevel == 0 && siloChargeBeforeChange > 0) { // Oops, someone let the base run out of power. Shut it all down. //todo: Make base neutral if silo hits zero NTU - avatarService ! AvatarServiceMessage(resourceSilo.Owner.asInstanceOf[Building].Zone.Id, AvatarAction.PlanetsideAttribute(PlanetSideGUID(resourceSilo.Owner.asInstanceOf[Building].ModelId), 48, 1)) + + // temporarily disabled until warpgates can bring ANTs from sanctuary, otherwise we'd be stuck in a situation with an unpowered base and no way to get an ANT to refill it. +// avatarService ! AvatarServiceMessage(resourceSilo.Owner.asInstanceOf[Building].Zone.Id, AvatarAction.PlanetsideAttribute(PlanetSideGUID(resourceSilo.Owner.asInstanceOf[Building].ModelId), 48, 1)) } else if (siloChargeBeforeChange == 0 && resourceSilo.ChargeLevel > 0) { // Power restored. Reactor Online. Sensors Online. Weapons Online. All systems nominal. //todo: Check generator is online before starting up diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index 82aa40c2..b1438bff 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -4385,7 +4385,8 @@ class WorldSessionActor extends Actor with MDCContextAware { sendResponse(PlanetsideAttributeMessage(amenityId, 47, silo.LowNtuWarningOn)) if(silo.ChargeLevel == 0) { - sendResponse(PlanetsideAttributeMessage(PlanetSideGUID(silo.Owner.asInstanceOf[Building].ModelId), 48, 1)) + // temporarily disabled until warpgates can bring ANTs from sanctuary, otherwise we'd be stuck in a situation with an unpowered base and no way to get an ANT to refill it. + // sendResponse(PlanetsideAttributeMessage(PlanetSideGUID(silo.Owner.asInstanceOf[Building].ModelId), 48, 1)) } case _ => ; } From 77468013719b9a81cb87ed861198702df563d0ff Mon Sep 17 00:00:00 2001 From: Mazo Date: Tue, 12 Jun 2018 17:38:31 +0100 Subject: [PATCH 17/17] Move new services from master merge to common --- {pslogin => common}/src/main/scala/services/RemoverActor.scala | 0 .../main/scala/services/avatar/support/DroppedItemRemover.scala | 2 +- .../main/scala/services/vehicle/support/VehicleRemover.scala | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename {pslogin => common}/src/main/scala/services/RemoverActor.scala (100%) rename {pslogin => common}/src/main/scala/services/avatar/support/DroppedItemRemover.scala (100%) rename {pslogin => common}/src/main/scala/services/vehicle/support/VehicleRemover.scala (100%) diff --git a/pslogin/src/main/scala/services/RemoverActor.scala b/common/src/main/scala/services/RemoverActor.scala similarity index 100% rename from pslogin/src/main/scala/services/RemoverActor.scala rename to common/src/main/scala/services/RemoverActor.scala diff --git a/pslogin/src/main/scala/services/avatar/support/DroppedItemRemover.scala b/common/src/main/scala/services/avatar/support/DroppedItemRemover.scala similarity index 100% rename from pslogin/src/main/scala/services/avatar/support/DroppedItemRemover.scala rename to common/src/main/scala/services/avatar/support/DroppedItemRemover.scala index 01bc9d47..ce91fdf8 100644 --- a/pslogin/src/main/scala/services/avatar/support/DroppedItemRemover.scala +++ b/common/src/main/scala/services/avatar/support/DroppedItemRemover.scala @@ -3,8 +3,8 @@ package services.avatar.support import net.psforever.objects.equipment.Equipment import net.psforever.objects.guid.{GUIDTask, TaskResolver} -import services.avatar.{AvatarAction, AvatarServiceMessage} import services.{RemoverActor, Service} +import services.avatar.{AvatarAction, AvatarServiceMessage} import scala.concurrent.duration._ diff --git a/pslogin/src/main/scala/services/vehicle/support/VehicleRemover.scala b/common/src/main/scala/services/vehicle/support/VehicleRemover.scala similarity index 100% rename from pslogin/src/main/scala/services/vehicle/support/VehicleRemover.scala rename to common/src/main/scala/services/vehicle/support/VehicleRemover.scala index cec2e65e..b60c9356 100644 --- a/pslogin/src/main/scala/services/vehicle/support/VehicleRemover.scala +++ b/common/src/main/scala/services/vehicle/support/VehicleRemover.scala @@ -4,8 +4,8 @@ package services.vehicle.support import net.psforever.objects.Vehicle import net.psforever.objects.guid.{GUIDTask, TaskResolver} import net.psforever.objects.zones.Zone -import services.vehicle.{VehicleAction, VehicleServiceMessage} import services.{RemoverActor, Service} +import services.vehicle.{VehicleAction, VehicleServiceMessage} import scala.concurrent.duration._