From 9d670292387d047296fe6f8c960a17341457f137 Mon Sep 17 00:00:00 2001 From: Mazo Date: Mon, 20 Jan 2020 02:55:55 +0000 Subject: [PATCH] Feature/caverns (#331) * Typo fix * Expand building hack info match to include vanu_control_console * Fix cavern crystal animations by allowing Amenities without an Owner to be ZoneAware, allowing them to direct to the correct Zone's LocalEvents * Add logging for when an invalid object reference gets deleted from a client * Show zipline teleporter animation (locally, at least) Co-authored-by: Fate-JH --- .../serverobject/ServerObjectBuilder.scala | 3 ++ .../pad/VehicleSpawnControl.scala | 16 +++++----- .../pad/process/VehicleSpawnControlBase.scala | 2 +- .../VehicleSpawnControlConcealPlayer.scala | 4 +-- .../VehicleSpawnControlDriverControl.scala | 2 +- .../VehicleSpawnControlFinalClearance.scala | 4 +-- .../VehicleSpawnControlLoadVehicle.scala | 6 ++-- .../process/VehicleSpawnControlRailJack.scala | 2 +- .../VehicleSpawnControlSeatDriver.scala | 4 +-- ...cleSpawnControlServerVehicleOverride.scala | 6 ++-- .../serverobject/painbox/PainboxControl.scala | 2 +- .../serverobject/structures/Amenity.scala | 32 ++++++++++++------- .../serverobject/structures/Building.scala | 16 +++++----- .../terminals/ProximityTerminalControl.scala | 4 +-- .../net/psforever/objects/zones/Zone.scala | 9 +++++- .../src/main/scala/WorldSessionActor.scala | 4 ++- 16 files changed, 69 insertions(+), 47 deletions(-) diff --git a/common/src/main/scala/net/psforever/objects/serverobject/ServerObjectBuilder.scala b/common/src/main/scala/net/psforever/objects/serverobject/ServerObjectBuilder.scala index de9d15c8..f584620c 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/ServerObjectBuilder.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/ServerObjectBuilder.scala @@ -30,6 +30,9 @@ import net.psforever.objects.guid.NumberPoolHub class ServerObjectBuilder[A <: PlanetSideServerObject](private val id : Int, private val constructor : ServerObjectBuilder.ConstructorType[A] ) { + + def Id : Int = id + /** * Instantiate and configure the given server object. * Specific configuration should have been handled by curried parameters into `constructor`, i.e., diff --git a/common/src/main/scala/net/psforever/objects/serverobject/pad/VehicleSpawnControl.scala b/common/src/main/scala/net/psforever/objects/serverobject/pad/VehicleSpawnControl.scala index 2918b7de..200da469 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/pad/VehicleSpawnControl.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/pad/VehicleSpawnControl.scala @@ -65,7 +65,7 @@ class VehicleSpawnControl(pad : VehicleSpawnPad) extends VehicleSpawnControlBase } catch { case _ : AssertionError if vehicle.HasGUID => //same as order being dropped - VehicleSpawnControl.DisposeSpawnedVehicle(vehicle, pad.Owner.Zone) + VehicleSpawnControl.DisposeSpawnedVehicle(vehicle, pad.Zone) case _ : AssertionError => ; //shrug case e : Exception => //something unexpected e.printStackTrace() @@ -140,10 +140,10 @@ class VehicleSpawnControl(pad : VehicleSpawnPad) extends VehicleSpawnControlBase }) && orders.forall { !_.driver.Name.equals(name) }) { //not a second order from an existing order's player orders = orders :+ order - pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.PeriodicReminder(name, VehicleSpawnPad.Reminders.Queue, Some(orders.length + 1)) + pad.Zone.VehicleEvents ! VehicleSpawnPad.PeriodicReminder(name, VehicleSpawnPad.Reminders.Queue, Some(orders.length + 1)) } else { - VehicleSpawnControl.DisposeSpawnedVehicle(order, pad.Owner.Zone) + VehicleSpawnControl.DisposeSpawnedVehicle(order, pad.Zone) } } @@ -201,7 +201,7 @@ class VehicleSpawnControl(pad : VehicleSpawnPad) extends VehicleSpawnControlBase * @param recipients all of the other customers who will be receiving the message */ def BlockedReminder(blockedOrder : VehicleSpawnControl.Order, recipients : Seq[VehicleSpawnControl.Order]) : Unit = { - val relevantRecipients = blockedOrder.vehicle.Seats(0).Occupant.orElse(pad.Owner.Zone.GUID(blockedOrder.vehicle.Owner)) match { + val relevantRecipients = blockedOrder.vehicle.Seats(0).Occupant.orElse(pad.Zone.GUID(blockedOrder.vehicle.Owner)) match { case Some(p : Player) => (VehicleSpawnControl.Order(p, blockedOrder.vehicle) +: recipients).iterator //who took possession of the vehicle case _ => @@ -223,15 +223,15 @@ class VehicleSpawnControl(pad : VehicleSpawnPad) extends VehicleSpawnControlBase def CancelOrder(entry : VehicleSpawnControl.Order)(implicit context : ActorContext) : Unit = { val vehicle = entry.vehicle if(vehicle.Seats.values.count(_.isOccupied) == 0) { - VehicleSpawnControl.DisposeSpawnedVehicle(entry, pad.Owner.Zone) - pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.PeriodicReminder(entry.driver.Name, VehicleSpawnPad.Reminders.Cancelled) + VehicleSpawnControl.DisposeSpawnedVehicle(entry, pad.Zone) + pad.Zone.VehicleEvents ! VehicleSpawnPad.PeriodicReminder(entry.driver.Name, VehicleSpawnPad.Reminders.Cancelled) } } @tailrec private final def recursiveBlockedReminder(iter : Iterator[VehicleSpawnControl.Order], cause : Option[Any]) : Unit = { if(iter.hasNext) { val recipient = iter.next - pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.PeriodicReminder(recipient.driver.Name, VehicleSpawnPad.Reminders.Blocked, cause) + pad.Zone.VehicleEvents ! VehicleSpawnPad.PeriodicReminder(recipient.driver.Name, VehicleSpawnPad.Reminders.Blocked, cause) recursiveBlockedReminder(iter, cause) } } @@ -239,7 +239,7 @@ class VehicleSpawnControl(pad : VehicleSpawnPad) extends VehicleSpawnControlBase @tailrec private final def recursiveOrderReminder(iter : Iterator[VehicleSpawnControl.Order], position : Int = 2) : Unit = { if(iter.hasNext) { val recipient = iter.next - pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.PeriodicReminder(recipient.driver.Name, VehicleSpawnPad.Reminders.Queue, Some(position)) + pad.Zone.VehicleEvents ! VehicleSpawnPad.PeriodicReminder(recipient.driver.Name, VehicleSpawnPad.Reminders.Queue, Some(position)) recursiveOrderReminder(iter, position + 1) } } diff --git a/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlBase.scala b/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlBase.scala index 5494f6ae..cc78e9b6 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlBase.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlBase.scala @@ -25,7 +25,7 @@ abstract class VehicleSpawnControlBase(pad : VehicleSpawnPad) extends Actor { */ private def GetLogger(logid : String) : Logger = baseLogger match { case None => - if(!pad.HasGUID || pad.Owner.Zone == Zone.Nowhere) { + if(!pad.HasGUID || pad.Zone == Zone.Nowhere) { org.log4s.getLogger(s"uninitialized_${pad.Definition.Name}$logid") } else { diff --git a/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlConcealPlayer.scala b/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlConcealPlayer.scala index 3e7188b8..3663d8e6 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlConcealPlayer.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlConcealPlayer.scala @@ -28,12 +28,12 @@ class VehicleSpawnControlConcealPlayer(pad : VehicleSpawnPad) extends VehicleSpa //TODO how far can the driver stray from the Terminal before his order is cancelled? if(driver.Continent == pad.Continent && driver.VehicleSeated.isEmpty) { trace(s"hiding ${driver.Name}") - pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.ConcealPlayer(driver.GUID) + pad.Zone.VehicleEvents ! VehicleSpawnPad.ConcealPlayer(driver.GUID) context.system.scheduler.scheduleOnce(2000 milliseconds, loadVehicle, order) } else { trace(s"integral component lost; abort order fulfillment") - VehicleSpawnControl.DisposeSpawnedVehicle(order.vehicle, pad.Owner.Zone) + VehicleSpawnControl.DisposeSpawnedVehicle(order.vehicle, pad.Zone) context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder } diff --git a/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlDriverControl.scala b/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlDriverControl.scala index 8bf2cc75..edc0ba13 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlDriverControl.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlDriverControl.scala @@ -26,7 +26,7 @@ class VehicleSpawnControlDriverControl(pad : VehicleSpawnPad) extends VehicleSpa } if(vehicle.PassengerInSeat(driver).contains(0)) { trace(s"returning control of ${vehicle.Definition.Name} to ${driver.Name}") - pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.ServerVehicleOverrideEnd(driver.Name, vehicle, pad) + pad.Zone.VehicleEvents ! VehicleSpawnPad.ServerVehicleOverrideEnd(driver.Name, vehicle, pad) } else { trace(s"${driver.Name} is not seated in ${vehicle.Definition.Name}; vehicle controls have been locked") diff --git a/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlFinalClearance.scala b/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlFinalClearance.scala index 52e63fbf..183a4ee7 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlFinalClearance.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlFinalClearance.scala @@ -28,7 +28,7 @@ class VehicleSpawnControlFinalClearance(pad : VehicleSpawnPad) extends VehicleSp //ensure the vacant vehicle is above the trench and doors vehicle.Position = pad.Position + Vector3.z(pad.Definition.VehicleCreationZOffset) val definition = vehicle.Definition - pad.Owner.Zone.VehicleEvents ! VehicleServiceMessage(s"${pad.Continent}", VehicleAction.LoadVehicle(PlanetSideGUID(0), vehicle, definition.ObjectId, vehicle.GUID, definition.Packet.ConstructorData(vehicle).get)) + pad.Zone.VehicleEvents ! VehicleServiceMessage(s"${pad.Continent}", VehicleAction.LoadVehicle(PlanetSideGUID(0), vehicle, definition.ObjectId, vehicle.GUID, definition.Packet.ConstructorData(vehicle).get)) } context.parent ! VehicleSpawnControl.ProcessControl.Reminder self ! VehicleSpawnControlFinalClearance.Test(order) @@ -36,7 +36,7 @@ class VehicleSpawnControlFinalClearance(pad : VehicleSpawnPad) extends VehicleSp case test @ VehicleSpawnControlFinalClearance.Test(entry) => if(Vector3.DistanceSquared(entry.vehicle.Position, pad.Position) > 100.0f) { //10m away from pad trace("pad cleared") - pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.ResetSpawnPad(pad) + pad.Zone.VehicleEvents ! VehicleSpawnPad.ResetSpawnPad(pad) context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder } else { diff --git a/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlLoadVehicle.scala b/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlLoadVehicle.scala index b548bd71..df8a5505 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlLoadVehicle.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlLoadVehicle.scala @@ -16,7 +16,7 @@ import scala.concurrent.duration._ *
* This object introduces the vehicle into the game environment. * The vehicle must be added to the `Zone` object, loaded onto other players' clients, and given an initial timed deconstruction event. - * For actual details on this process, please refer to the external source represented by `pad.Owner.Zone.VehicleEvents`. + * For actual details on this process, please refer to the external source represented by `pad.Zone.VehicleEvents`. * It has failure cases should the driver be in an incorrect state. * @param pad the `VehicleSpawnPad` object being governed */ @@ -31,12 +31,12 @@ class VehicleSpawnControlLoadVehicle(pad : VehicleSpawnPad) extends VehicleSpawn trace(s"loading the ${vehicle.Definition.Name}") vehicle.Position = vehicle.Position - Vector3.z(if(GlobalDefinitions.isFlightVehicle(vehicle.Definition)) 9 else 5) //appear below the trench and doors vehicle.Cloaked = vehicle.Definition.CanCloak && driver.Cloaked - pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.LoadVehicle(vehicle) + pad.Zone.VehicleEvents ! VehicleSpawnPad.LoadVehicle(vehicle) context.system.scheduler.scheduleOnce(100 milliseconds, railJack, order) } else { trace("owner lost or vehicle in poor condition; abort order fulfillment") - VehicleSpawnControl.DisposeSpawnedVehicle(order, pad.Owner.Zone) + VehicleSpawnControl.DisposeSpawnedVehicle(order, pad.Zone) context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder } diff --git a/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlRailJack.scala b/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlRailJack.scala index e5789fd5..0621905e 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlRailJack.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlRailJack.scala @@ -26,7 +26,7 @@ class VehicleSpawnControlRailJack(pad : VehicleSpawnPad) extends VehicleSpawnCon def receive : Receive = { case order @ VehicleSpawnControl.Order(_, vehicle) => - pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.AttachToRails(vehicle, pad) + pad.Zone.VehicleEvents ! VehicleSpawnPad.AttachToRails(vehicle, pad) context.system.scheduler.scheduleOnce(10 milliseconds, seatDriver, order) case msg @ (VehicleSpawnControl.ProcessControl.Reminder | VehicleSpawnControl.ProcessControl.GetNewOrder) => diff --git a/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlSeatDriver.scala b/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlSeatDriver.scala index 8253dd92..7a0e58d0 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlSeatDriver.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlSeatDriver.scala @@ -40,7 +40,7 @@ class VehicleSpawnControlSeatDriver(pad : VehicleSpawnPad) extends VehicleSpawnC val driver = entry.driver if(entry.vehicle.Health > 0 && driver.isAlive && driver.Continent == pad.Continent && driver.VehicleSeated.isEmpty) { trace("driver to be made seated in vehicle") - pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.StartPlayerSeatedInVehicle(entry.driver.Name, entry.vehicle, pad) + pad.Zone.VehicleEvents ! VehicleSpawnPad.StartPlayerSeatedInVehicle(entry.driver.Name, entry.vehicle, pad) } else{ trace("driver lost; vehicle stranded on pad") @@ -50,7 +50,7 @@ class VehicleSpawnControlSeatDriver(pad : VehicleSpawnPad) extends VehicleSpawnC case VehicleSpawnControlSeatDriver.DriverInSeat(entry) => if(entry.driver.isAlive && entry.vehicle.PassengerInSeat(entry.driver).contains(0)) { trace(s"driver ${entry.driver.Name} has taken the wheel") - pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.PlayerSeatedInVehicle(entry.driver.Name, entry.vehicle, pad) + pad.Zone.VehicleEvents ! VehicleSpawnPad.PlayerSeatedInVehicle(entry.driver.Name, entry.vehicle, pad) } else { trace("driver lost, but operations can continue") diff --git a/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlServerVehicleOverride.scala b/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlServerVehicleOverride.scala index f77cb4ce..781a9a98 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlServerVehicleOverride.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlServerVehicleOverride.scala @@ -28,7 +28,7 @@ class VehicleSpawnControlServerVehicleOverride(pad : VehicleSpawnPad) extends Ve case order @ VehicleSpawnControl.Order(driver, vehicle) => val vehicleFailState = vehicle.Health == 0 || vehicle.Position == Vector3.Zero val driverFailState = !driver.isAlive || driver.Continent != pad.Continent || !vehicle.PassengerInSeat(driver).contains(0) - pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.DetachFromRails(vehicle, pad) + pad.Zone.VehicleEvents ! VehicleSpawnPad.DetachFromRails(vehicle, pad) if(vehicleFailState || driverFailState) { if(vehicleFailState) { trace(s"vehicle was already destroyed") @@ -36,12 +36,12 @@ class VehicleSpawnControlServerVehicleOverride(pad : VehicleSpawnPad) extends Ve else { trace(s"driver is not ready") } - pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.RevealPlayer(order.DriverGUID) + pad.Zone.VehicleEvents ! VehicleSpawnPad.RevealPlayer(order.DriverGUID) driverControl ! order } else { trace(s"telling ${driver.Name} that the server is assuming control of the ${vehicle.Definition.Name}") - pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.ServerVehicleOverrideStart(driver.Name, vehicle, pad) + pad.Zone.VehicleEvents ! VehicleSpawnPad.ServerVehicleOverrideStart(driver.Name, vehicle, pad) context.system.scheduler.scheduleOnce(4000 milliseconds, driverControl, order) } diff --git a/common/src/main/scala/net/psforever/objects/serverobject/painbox/PainboxControl.scala b/common/src/main/scala/net/psforever/objects/serverobject/painbox/PainboxControl.scala index 36230615..830cbd84 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/painbox/PainboxControl.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/painbox/PainboxControl.scala @@ -55,7 +55,7 @@ class PainboxControl(painbox: Painbox) extends Actor { val owner = painbox.Owner.asInstanceOf[Building] val faction = owner.Faction if(faction != PlanetSideEmpire.NEUTRAL && (nearestDoor match { case Some(door) => door.Open.nonEmpty; case _ => true })) { - val events = owner.Zone.AvatarEvents + val events = painbox.Zone.AvatarEvents val damage = painbox.Definition.Damage val radius = painbox.Definition.Radius * painbox.Definition.Radius val position = painbox.Position diff --git a/common/src/main/scala/net/psforever/objects/serverobject/structures/Amenity.scala b/common/src/main/scala/net/psforever/objects/serverobject/structures/Amenity.scala index 22ba8371..e6b6ea6f 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/structures/Amenity.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/structures/Amenity.scala @@ -2,8 +2,9 @@ package net.psforever.objects.serverobject.structures import net.psforever.objects.serverobject.PlanetSideServerObject -import net.psforever.objects.zones.Zone +import net.psforever.objects.zones.{Zone, ZoneAware} import net.psforever.types.{PlanetSideEmpire, Vector3} +import net.psforever.objects.zones.{ Zone => World } /** * Amenities are elements of the game that belong to other elements of the game.
@@ -15,7 +16,8 @@ import net.psforever.types.{PlanetSideEmpire, Vector3} * the `Amenity` objects look to its `Owner` object for some of its properties. * @see `FactionAffinity` */ -abstract class Amenity extends PlanetSideServerObject { +abstract class Amenity extends PlanetSideServerObject with ZoneAware { + private[this] val log = org.log4s.getLogger("Amenity") /** what other entity has authority over this amenity; usually either a building or a vehicle */ private var owner : AmenityOwner = Building.NoBuilding /** if the entity exists at a specific position relative to the owner's position */ @@ -27,7 +29,12 @@ abstract class Amenity extends PlanetSideServerObject { * Reference the object that is in direct association with (is superior to) this one. * @return the object associated as this object's "owner" */ - def Owner : AmenityOwner = owner + def Owner : AmenityOwner = { + if(owner == Building.NoBuilding) { + log.warn(s"Amenity $GUID in zone $Zone tried to access owner, but doesn't have one.") + } + owner + } /** * Set an object to have a direct association with (be superior to) this one. @@ -40,6 +47,17 @@ abstract class Amenity extends PlanetSideServerObject { Owner } + override def Zone : Zone = { + if(super.Zone != World.Nowhere) { + super.Zone + } else if(Owner.Zone != World.Nowhere) { + Owner.Zone + } else { + log.warn(s"Amenity $GUID tried to access it's Zone, but doesn't have one.") + World.Nowhere + } + } + def LocationOffset : Vector3 = offset.getOrElse(Vector3.Zero) def LocationOffset_=(off : Vector3) : Vector3 = LocationOffset_=(Some(off)) @@ -53,12 +71,4 @@ abstract class Amenity extends PlanetSideServerObject { } LocationOffset } - - override def Zone : Zone = Owner.Zone - - override def Zone_=(zone : Zone) = Owner.Zone - - override def Continent : String = Owner.Continent - - override def Continent_=(str : String) : String = Owner.Continent } 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 e7c75084..bdfb1e7a 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 @@ -174,7 +174,7 @@ class Building(private val name: String, ) = { val ntuLevel : Int = NtuLevel //if we have a capture terminal, get the hack status & time (in milliseconds) from control console if it exists - val (hacking, hackingFaction, hackTime) : (Boolean, PlanetSideEmpire.Value, Long) = Amenities.find(_.Definition == GlobalDefinitions.capture_terminal) match { + val (hacking, hackingFaction, hackTime) : (Boolean, PlanetSideEmpire.Value, Long) = Amenities.find(x => x.Definition == GlobalDefinitions.capture_terminal || x.Definition == GlobalDefinitions.vanu_control_console) match { case Some(obj: CaptureTerminal with Hackable) => obj.HackedBy match { case Some(Hackable.HackInfo(_, _, hfaction, _, start, length)) => @@ -187,7 +187,7 @@ class Building(private val name: String, (false, PlanetSideEmpire.NEUTRAL, 0L) } //TODO if we have a generator, get the current repair state - val (generatorState, bootGeneratorPain) = (PlanetSideGeneratorState.Normal, false) + val (generatorState, boostGeneratorPain) = (PlanetSideGeneratorState.Normal, false) // todo: poll pain field strength //if we have spawn tubes, determine if any of them are active val (spawnTubesNormal, boostSpawnPain) : (Boolean, Boolean) = { val o = Amenities.collect({ case _ : SpawnTube => true }) ///TODO obj.Health > 0 @@ -252,13 +252,13 @@ class Building(private val name: String, ForceDomeActive, latticeBenefit, 0, //cavern_benefit; !! Field > 0 will cause malformed packet. See class def. - Nil, - 0, - false, - 8, //!! Field != 8 will cause malformed packet. See class def. - None, + Nil, //unk4 + 0, //unk5 + false, //unk6 + 8, //!! unk7 Field != 8 will cause malformed packet. See class def. + None, //unk7x boostSpawnPain, //boost_spawn_pain - bootGeneratorPain //boost_generator_pain + boostGeneratorPain //boost_generator_pain ) } diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTerminalControl.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTerminalControl.scala index 34c4df24..385ec627 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTerminalControl.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTerminalControl.scala @@ -84,7 +84,7 @@ class ProximityTerminalControl(term : Terminal with ProximityUnit) extends Actor import scala.concurrent.ExecutionContext.Implicits.global terminalAction.cancel terminalAction = context.system.scheduler.schedule(500 milliseconds, medDef.Interval, self, ProximityTerminalControl.TerminalAction()) - TerminalObject.Owner.Zone.LocalEvents ! Terminal.StartProximityEffect(term) + TerminalObject.Zone.LocalEvents ! Terminal.StartProximityEffect(term) } } else { @@ -103,7 +103,7 @@ class ProximityTerminalControl(term : Terminal with ProximityUnit) extends Actor //de-activation (global / local) if(term.NumberUsers == 0 && hadUsers) { terminalAction.cancel - TerminalObject.Owner.Zone.LocalEvents ! Terminal.StopProximityEffect(term) + TerminalObject.Zone.LocalEvents ! Terminal.StopProximityEffect(term) } } else { diff --git a/common/src/main/scala/net/psforever/objects/zones/Zone.scala b/common/src/main/scala/net/psforever/objects/zones/Zone.scala index 17642ec3..ac980f06 100644 --- a/common/src/main/scala/net/psforever/objects/zones/Zone.scala +++ b/common/src/main/scala/net/psforever/objects/zones/Zone.scala @@ -362,7 +362,14 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) { } private def BuildLocalObjects(implicit context : ActorContext, guid : NumberPoolHub) : Unit = { - Map.LocalObjects.foreach({ builderObject => builderObject.Build }) + Map.LocalObjects.foreach({ builderObject => + builderObject.Build + + val obj = guid(builderObject.Id) + obj collect { + case el : ZoneAware => el.Zone = this + } + }) } private def BuildSupportObjects() : Unit = { diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index 7f8e0cb6..6de5f18a 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -339,7 +339,8 @@ class WorldSessionActor extends Actor case out @ Some(obj) if obj.HasGUID => out case None if id.nonEmpty => - //delete stale entity reference from client (deferred until later) + //delete stale entity reference from client + log.warn(s"Player ${player.Name} has an invalid reference to GUID ${id.get} in zone ${continent.Id}. Delete object on client.") //sendResponse(ObjectDeleteMessage(id.get, 0)) None case _ => @@ -4554,6 +4555,7 @@ class WorldSessionActor extends Actor if(isTeleporter) { val endPoint = path.get.ZipLinePoints.last + sendResponse(ZipLineMessage(PlanetSideGUID(0), forwards, 0, path_id, pos)) // todo: send to zone to show teleport animation to all clients sendResponse(PlayerStateShiftMessage(ShiftState(0, endPoint, player.Orientation.z, None))) } else { action match {