diff --git a/common/src/main/scala/net/psforever/objects/Default.scala b/common/src/main/scala/net/psforever/objects/Default.scala
new file mode 100644
index 00000000..33787813
--- /dev/null
+++ b/common/src/main/scala/net/psforever/objects/Default.scala
@@ -0,0 +1,47 @@
+// Copyright (c) 2017 PSForever
+package net.psforever.objects
+
+object Default {
+ //cancellable
+ import akka.actor.Cancellable
+ protected class InternalCancellable extends Cancellable {
+ override def cancel : Boolean = true
+ override def isCancelled : Boolean = true
+ }
+ private val cancellable : Cancellable = new InternalCancellable
+
+ /**
+ * Used to initialize the value of a re-usable `Cancellable` object.
+ * By convention, it always acts like it has been cancelled before and can be cancelled.
+ * Should be replaced with pertinent `Cancellable` logic through the initialization of an executor.
+ */
+ final def Cancellable : Cancellable = cancellable
+
+ //actor
+ import akka.actor.{Actor => AkkaActor, ActorRef, ActorSystem, DeadLetter, Props}
+ /**
+ * An actor designed to wrap around `deadLetters` and redirect all normal messages to it.
+ * This measure is more to "protect" `deadLetters` than anything else.
+ * Even if it is stopped, it still fulfills exactly the same purpose!
+ * The original target to which the actor is assigned will not be implicitly accredited.
+ */
+ private class DefaultActor extends AkkaActor {
+ def receive : Receive = {
+ case msg => context.system.deadLetters ! DeadLetter(msg, sender, self)
+ }
+ }
+ private var defaultRef : ActorRef = ActorRef.noSender
+ /**
+ * Instigate the default actor.
+ * @param sys the actor universe under which this default actor will exist
+ * @return the new default actor
+ */
+ def apply(sys : ActorSystem) : ActorRef = {
+ if(defaultRef == ActorRef.noSender) {
+ defaultRef = sys.actorOf(Props[DefaultActor], name = s"system-default-actor")
+ }
+ defaultRef
+ }
+
+ final def Actor : ActorRef = defaultRef
+}
diff --git a/common/src/main/scala/net/psforever/objects/DefaultCancellable.scala b/common/src/main/scala/net/psforever/objects/DefaultCancellable.scala
deleted file mode 100644
index 394ba9c9..00000000
--- a/common/src/main/scala/net/psforever/objects/DefaultCancellable.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2017 PSForever
-package net.psforever.objects
-
-/**
- * Used to initialize the value of a re-usable `Cancellable` object.
- * By convention, it always acts like it has been cancelled before and can be cancelled.
- * Should be replaced with pertinent `Cancellable` logic through the initialization of an executor.
- */
-object DefaultCancellable {
- import akka.actor.Cancellable
-
- protected class InternalCancellable extends Cancellable {
- override def cancel : Boolean = true
- override def isCancelled : Boolean = true
- }
-
- final val obj : Cancellable = new InternalCancellable
-}
diff --git a/common/src/main/scala/net/psforever/objects/ImplantSlot.scala b/common/src/main/scala/net/psforever/objects/ImplantSlot.scala
index 5fed4a50..5cc624ea 100644
--- a/common/src/main/scala/net/psforever/objects/ImplantSlot.scala
+++ b/common/src/main/scala/net/psforever/objects/ImplantSlot.scala
@@ -20,7 +20,7 @@ class ImplantSlot {
/** whether this implant is ready for use */
private var initialized : Boolean = false
/** a cancellable timer that can be used to set an implant as initialized once complete */
- private var initializeTimer: Cancellable = DefaultCancellable.obj
+ private var initializeTimer: Cancellable = Default.Cancellable
/** is this implant active */
private var active : Boolean = false
diff --git a/common/src/main/scala/net/psforever/objects/Player.scala b/common/src/main/scala/net/psforever/objects/Player.scala
index 87b1da3d..4144415d 100644
--- a/common/src/main/scala/net/psforever/objects/Player.scala
+++ b/common/src/main/scala/net/psforever/objects/Player.scala
@@ -125,7 +125,7 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
def Stamina_=(assignStamina : Int) : Int = {
stamina = if(isAlive) { math.min(math.max(0, assignStamina), MaxStamina) } else { 0 }
- if(Actor != ActorRef.noSender) {
+ if(Actor != Default.Actor) {
Actor ! Player.StaminaChanged(Stamina)
}
diff --git a/common/src/main/scala/net/psforever/objects/Vehicle.scala b/common/src/main/scala/net/psforever/objects/Vehicle.scala
index 6db09377..00356be4 100644
--- a/common/src/main/scala/net/psforever/objects/Vehicle.scala
+++ b/common/src/main/scala/net/psforever/objects/Vehicle.scala
@@ -1,7 +1,6 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects
-import akka.actor.ActorRef
import net.psforever.objects.definition.VehicleDefinition
import net.psforever.objects.equipment.{Equipment, EquipmentSize, EquipmentSlot, JammableUnit}
import net.psforever.objects.inventory.{Container, GridInventory, InventoryTile}
@@ -546,14 +545,7 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
false
}
- override def hashCode() : Int = {
- Actor match {
- case ActorRef.noSender =>
- super.hashCode()
- case actor =>
- actor.hashCode()
- }
- }
+ override def hashCode() : Int = Actor.hashCode()
/**
* Override the string representation to provide additional information.
diff --git a/common/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala b/common/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala
index 552dd021..fa455aa3 100644
--- a/common/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala
+++ b/common/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala
@@ -2,7 +2,7 @@
package net.psforever.objects.avatar
import akka.actor.Actor
-import net.psforever.objects.{DefaultCancellable, GlobalDefinitions, ImplantSlot, Player, Players, Tool}
+import net.psforever.objects.{Default, GlobalDefinitions, ImplantSlot, Player, Players, Tool}
import net.psforever.objects.ballistics.{PlayerSource, ResolvedProjectile, SourceEntry}
import net.psforever.objects.definition.ImplantDefinition
import net.psforever.objects.equipment.{Ammo, JammableBehavior, JammableUnit}
@@ -33,7 +33,7 @@ class PlayerControl(player : Player) extends Actor
private [this] val damageLog = org.log4s.getLogger(Damageable.LogChannel)
// A collection of timers for each slot to trigger stamina drain on an interval
- val implantSlotStaminaDrainTimers = mutable.HashMap(0 -> DefaultCancellable.obj, 1 -> DefaultCancellable.obj, 2 -> DefaultCancellable.obj)
+ val implantSlotStaminaDrainTimers = mutable.HashMap(0 -> Default.Cancellable, 1 -> Default.Cancellable, 2 -> Default.Cancellable)
def receive : Receive = jammableBehavior
.orElse(takesDamage)
@@ -46,7 +46,7 @@ class PlayerControl(player : Player) extends Actor
if(status == 0 && (implantSlot.Active || !implantSlot.Initialized)) {
// Cancel stamina drain timer
implantSlotStaminaDrainTimers(slot).cancel()
- implantSlotStaminaDrainTimers(slot) = DefaultCancellable.obj
+ implantSlotStaminaDrainTimers(slot) = Default.Cancellable
implantSlot.Active = false
player.Zone.AvatarEvents ! AvatarServiceMessage(player.Zone.Id, AvatarAction.PlanetsideAttribute(player.GUID, 28, player.Implant(slot).id * 2)) // Deactivation sound / effect
@@ -60,7 +60,7 @@ class PlayerControl(player : Player) extends Actor
// todo: Deactivate implants server side when actions like zoning happen. (Other actions?)
log.warn(s"Implant ${slot} is already active, but activating again")
implantSlotStaminaDrainTimers(slot).cancel()
- implantSlotStaminaDrainTimers(slot) = DefaultCancellable.obj
+ implantSlotStaminaDrainTimers(slot) = Default.Cancellable
}
implantSlot.Active = true
@@ -104,9 +104,9 @@ class PlayerControl(player : Player) extends Actor
if(implantSlot.Installed.isDefined) {
player.Zone.AvatarEvents ! AvatarServiceMessage(player.Name, AvatarAction.SendResponse(player.GUID, AvatarImplantMessage(player.GUID, ImplantAction.Initialization, slot, 1)))
implantSlot.Initialized = true
- if(implantSlot.InitializeTimer != DefaultCancellable.obj) {
+ if(implantSlot.InitializeTimer != Default.Cancellable) {
implantSlot.InitializeTimer.cancel()
- implantSlot.InitializeTimer = DefaultCancellable.obj
+ implantSlot.InitializeTimer = Default.Cancellable
}
}
@@ -463,9 +463,9 @@ object PlayerControl {
val implantSlot = player.ImplantSlot(slot)
implantSlot.Initialized = false
- if(implantSlot.InitializeTimer != DefaultCancellable.obj) {
+ if(implantSlot.InitializeTimer != Default.Cancellable) {
implantSlot.InitializeTimer.cancel()
- implantSlot.InitializeTimer = DefaultCancellable.obj
+ implantSlot.InitializeTimer = Default.Cancellable
}
player.Zone.AvatarEvents ! AvatarServiceMessage(player.Zone.Id, AvatarAction.SendResponse(player.GUID, AvatarImplantMessage(player.GUID, ImplantAction.Initialization, slot, 0)))
}
diff --git a/common/src/main/scala/net/psforever/objects/ce/TelepadLike.scala b/common/src/main/scala/net/psforever/objects/ce/TelepadLike.scala
index f0566a12..aa701983 100644
--- a/common/src/main/scala/net/psforever/objects/ce/TelepadLike.scala
+++ b/common/src/main/scala/net/psforever/objects/ce/TelepadLike.scala
@@ -2,8 +2,8 @@
package net.psforever.objects.ce
import akka.actor.ActorContext
+import net.psforever.objects.{Default, PlanetSideGameObject, TelepadDeployable, Vehicle}
import net.psforever.objects.serverobject.PlanetSideServerObject
-import net.psforever.objects.{PlanetSideGameObject, TelepadDeployable, Vehicle}
import net.psforever.objects.serverobject.structures.Amenity
import net.psforever.objects.vehicles.Utility
import net.psforever.objects.zones.Zone
@@ -50,8 +50,8 @@ object TelepadLike {
*/
def Setup(obj : Amenity, context : ActorContext) : Unit = {
obj.asInstanceOf[TelepadLike].Router = obj.Owner.GUID
- import akka.actor.{ActorRef, Props}
- if(obj.Actor == ActorRef.noSender) {
+ import akka.actor.Props
+ if(obj.Actor == Default.Actor) {
obj.Actor = context.actorOf(Props(classOf[TelepadControl], obj), PlanetSideServerObject.UniqueActorName(obj))
}
}
diff --git a/common/src/main/scala/net/psforever/objects/definition/SimpleDeployableDefinition.scala b/common/src/main/scala/net/psforever/objects/definition/SimpleDeployableDefinition.scala
index 07b9c430..277481a5 100644
--- a/common/src/main/scala/net/psforever/objects/definition/SimpleDeployableDefinition.scala
+++ b/common/src/main/scala/net/psforever/objects/definition/SimpleDeployableDefinition.scala
@@ -1,8 +1,8 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.definition
-import akka.actor.{ActorContext, ActorRef}
-import net.psforever.objects.PlanetSideGameObject
+import akka.actor.ActorContext
+import net.psforever.objects.{Default, PlanetSideGameObject}
import net.psforever.objects.ce.{Deployable, DeployableCategory, DeployedItem}
import net.psforever.objects.definition.converter.SmallDeployableConverter
import net.psforever.objects.serverobject.PlanetSideServerObject
@@ -68,6 +68,6 @@ object SimpleDeployableDefinition {
def SimpleUninitialize(obj : PlanetSideServerObject, context : ActorContext) : Unit = {
context.stop(obj.Actor)
- obj.Actor = ActorRef.noSender
+ obj.Actor = Default.Actor
}
}
diff --git a/common/src/main/scala/net/psforever/objects/equipment/JammingUnit.scala b/common/src/main/scala/net/psforever/objects/equipment/JammingUnit.scala
index aeb045d1..95433213 100644
--- a/common/src/main/scala/net/psforever/objects/equipment/JammingUnit.scala
+++ b/common/src/main/scala/net/psforever/objects/equipment/JammingUnit.scala
@@ -2,7 +2,7 @@
package net.psforever.objects.equipment
import akka.actor.{Actor, Cancellable}
-import net.psforever.objects.{DefaultCancellable, PlanetSideGameObject, Tool}
+import net.psforever.objects.{Default, PlanetSideGameObject, Tool}
import net.psforever.objects.ballistics.ResolvedProjectile
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.vehicles.MountedWeapons
@@ -111,9 +111,9 @@ trait JammableBehavior {
/** flag for jammed sound */
protected var jammedSound : Boolean = false
/** the sound timer */
- protected var jammeredSoundTimer : Cancellable = DefaultCancellable.obj
+ protected var jammeredSoundTimer : Cancellable = Default.Cancellable
/** the effect timer */
- protected var jammeredStatusTimer : Cancellable = DefaultCancellable.obj
+ protected var jammeredStatusTimer : Cancellable = Default.Cancellable
/** `ZoneAware` is used for callback to the event systems */
def JammableObject : PlanetSideServerObject with JammableUnit with ZoneAware
diff --git a/common/src/main/scala/net/psforever/objects/guid/TaskResolver.scala b/common/src/main/scala/net/psforever/objects/guid/TaskResolver.scala
index 0a905d06..557bfece 100644
--- a/common/src/main/scala/net/psforever/objects/guid/TaskResolver.scala
+++ b/common/src/main/scala/net/psforever/objects/guid/TaskResolver.scala
@@ -5,6 +5,7 @@ import java.util.concurrent.TimeoutException
import akka.actor.{Actor, ActorRef, Cancellable}
import akka.routing.Broadcast
+import net.psforever.objects.Default
import scala.annotation.tailrec
import scala.collection.mutable.ListBuffer
@@ -16,7 +17,7 @@ class TaskResolver() extends Actor {
/** list of all work currently managed by this resolver */
private val tasks : ListBuffer[TaskResolver.TaskEntry] = new ListBuffer[TaskResolver.TaskEntry]
/** scheduled termination of tardy managed work */
- private var timeoutCleanup : Cancellable = TaskResolver.DefaultCancellable
+ private var timeoutCleanup : Cancellable = Default.Cancellable
/** logging utilities; default to tracing */
private[this] val log = org.log4s.getLogger
private def trace(msg : String) = log.trace(msg)
@@ -109,7 +110,7 @@ class TaskResolver() extends Actor {
* @param resolver the `TaskResolver` that distributed this work, thus determining that this work is a sub-task;
* by default, no one, as the work is identified as a main task
*/
- private def QueueSubtasks(task : Task, subtasks : List[TaskResolver.GiveTask], resolver : ActorRef = Actor.noSender) : Unit = {
+ private def QueueSubtasks(task : Task, subtasks : List[TaskResolver.GiveTask], resolver : ActorRef = ActorRef.noSender) : Unit = {
val entry : TaskResolver.TaskEntry = TaskResolver.TaskEntry(task, subtasks.map(task => task.task), resolver)
tasks += entry
trace(s"enqueue task $task")
@@ -347,7 +348,7 @@ object TaskResolver {
* //@param isASubtask whether this work is intermediary or the last in a dependency chain
* @param supertaskRef the `TaskResolver` that will handle work that depends on the outcome of this work
*/
- private final case class TaskEntry(task : Task, subtasks : List[Task] = Nil, supertaskRef : ActorRef = Actor.noSender) {
+ private final case class TaskEntry(task : Task, subtasks : List[Task] = Nil, supertaskRef : ActorRef = ActorRef.noSender) {
private var start : Long = 0L
private var isExecuting : Boolean = false
@@ -368,14 +369,6 @@ object TaskResolver {
}
}
- /**
- * A placeholder `Cancellable` object for the time-out checking functionality.
- */
- private final val DefaultCancellable = new Cancellable() {
- def cancel : Boolean = true
- def isCancelled() : Boolean = true
- }
-
/**
* Scan across a group of tasks to determine which ones match the target completion status.
* @param iter an `Iterator` of enqueued `TaskEntry` indices
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/PlanetSideServerObject.scala b/common/src/main/scala/net/psforever/objects/serverobject/PlanetSideServerObject.scala
index 01085a38..05b7a102 100644
--- a/common/src/main/scala/net/psforever/objects/serverobject/PlanetSideServerObject.scala
+++ b/common/src/main/scala/net/psforever/objects/serverobject/PlanetSideServerObject.scala
@@ -2,41 +2,67 @@
package net.psforever.objects.serverobject
import akka.actor.ActorRef
-import net.psforever.objects.PlanetSideGameObject
+import net.psforever.objects.{Default, PlanetSideGameObject}
import net.psforever.objects.entity.NoGUIDException
import net.psforever.objects.serverobject.affinity.FactionAffinity
import net.psforever.objects.zones.ZoneAware
/**
* An object layered on top of the standard game object class that maintains an internal `ActorRef`.
- * A measure of synchronization can be managed using this `Actor`.
+ * A measure of synchronization can be managed using this `Actor` as a "controlling agent."
*/
abstract class PlanetSideServerObject extends PlanetSideGameObject
with FactionAffinity
with ZoneAware {
- private var actor = ActorRef.noSender
+ private var actor : ActorRef = ActorRef.noSender
+ private var getActorFunc : ()=>ActorRef = PlanetSideServerObject.getDefaultActor
/**
* Retrieve a reference to the internal `Actor`.
* @return the internal `ActorRef`
*/
- def Actor : ActorRef = actor
+ def Actor : ActorRef = getActorFunc()
/**
* Assign an `Actor` to act for this server object.
- * This reference is only set once, that is, as long as the internal `ActorRef` directs to `Actor.noSender` (`null`).
+ * This reference is only set once, that is, as long as the internal `ActorRef` directs to `ActorRef.noSender` (`null`).
* @param control the `Actor` whose functionality will govern this server object
* @return the current internal `ActorRef`
*/
def Actor_=(control : ActorRef) : ActorRef = {
- if(actor == ActorRef.noSender || control == ActorRef.noSender) {
- actor = control
+ if(control == Default.Actor) {
+ ResetControl()
}
- actor
+ else {
+ actor = control
+ getActorFunc = PlanetSideServerObject.doGetLocalActor(this)
+ actor
+ }
+ }
+
+ def ResetControl() : ActorRef = {
+ getActorFunc = PlanetSideServerObject.getDefaultActor
+ val out = actor
+ actor = ActorRef.noSender
+ out
}
}
object PlanetSideServerObject {
+ /**
+ * Before the internal control agency of a respective server object is ever set,
+ * a default control agency will be produced.
+ * @return the value pointed to by `Default.Actor`
+ */
+ private def getDefaultActor() : ActorRef = { Default.Actor }
+
+ /**
+ * Allow retrieving a reference to the internal `Actor`.
+ * @see o the server object
+ * @return the internal `ActorRef`
+ */
+ private def doGetLocalActor(o : PlanetSideServerObject)() : ActorRef = o.actor
+
/**
* `Actor` entities require unique names over the course of the lifetime of the `ActorSystem` object.
* To produce this name, a composition of three strings separated by underscores is assembled.
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 ab6d4f2d..86df17b1 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
@@ -5,7 +5,7 @@ import akka.actor.{ActorContext, Cancellable, Props}
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
import net.psforever.objects.serverobject.pad.process.{VehicleSpawnControlBase, VehicleSpawnControlConcealPlayer}
import net.psforever.objects.zones.Zone
-import net.psforever.objects.{DefaultCancellable, Player, Vehicle}
+import net.psforever.objects.{Default, Player, Vehicle}
import services.RemoverActor
import services.vehicle.VehicleServiceMessage
@@ -32,7 +32,7 @@ import scala.concurrent.duration._
*/
class VehicleSpawnControl(pad : VehicleSpawnPad) extends VehicleSpawnControlBase(pad) with FactionAffinityBehavior.Check {
/** a reminder sent to future customers */
- var periodicReminder : Cancellable = DefaultCancellable.obj
+ var periodicReminder : Cancellable = Default.Cancellable
/** a list of vehicle orders that have been submitted for this spawn pad */
var orders : List[VehicleSpawnControl.Order] = List.empty[VehicleSpawnControl.Order]
/** the current vehicle order being acted upon;
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 b58243ea..e0fed464 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
@@ -1,8 +1,8 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.pad.process
-import akka.actor.{ActorRef, Props}
-import net.psforever.objects.Vehicle
+import akka.actor.Props
+import net.psforever.objects.{Default, Vehicle}
import net.psforever.objects.serverobject.pad.{VehicleSpawnControl, VehicleSpawnPad}
import scala.concurrent.ExecutionContext.Implicits.global
@@ -29,7 +29,7 @@ class VehicleSpawnControlSeatDriver(pad : VehicleSpawnPad) extends VehicleSpawnC
def receive : Receive = {
case order @ VehicleSpawnControl.Order(_, vehicle) =>
- if(vehicle.Actor == ActorRef.noSender) { //wait for a necessary vehicle component to be loaded
+ if(vehicle.Actor == Default.Actor) { //wait for a necessary vehicle component to be loaded
context.system.scheduler.scheduleOnce(50 milliseconds, self, order)
}
else {
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 5f0b5266..4cd63ebc 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
@@ -3,7 +3,7 @@ package net.psforever.objects.serverobject.painbox
import akka.actor.{Actor, Cancellable}
import net.psforever.objects.serverobject.doors.Door
import net.psforever.objects.serverobject.structures.Building
-import net.psforever.objects.{DefaultCancellable, GlobalDefinitions}
+import net.psforever.objects.{Default, GlobalDefinitions}
import net.psforever.types.{PlanetSideEmpire, Vector3}
import services.avatar.{AvatarAction, AvatarServiceMessage}
@@ -12,7 +12,7 @@ import scala.concurrent.duration._
class PainboxControl(painbox: Painbox) extends Actor {
private[this] val log = org.log4s.getLogger(s"Painbox")
- var painboxTick: Cancellable = DefaultCancellable.obj
+ var painboxTick: Cancellable = Default.Cancellable
var nearestDoor: Option[Door] = None
var bBoxMinCorner = Vector3.Zero
var bBoxMaxCorner = Vector3.Zero
@@ -97,7 +97,7 @@ class PainboxControl(painbox: Painbox) extends Actor {
case Painbox.Stop() =>
context.become(Stopped)
painboxTick.cancel
- painboxTick = DefaultCancellable.obj
+ painboxTick = Default.Cancellable
case Painbox.Tick() =>
//todo: Account for overlapping pain fields
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 06878023..180293ee 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
@@ -3,8 +3,8 @@ package net.psforever.objects.serverobject.structures
import java.util.concurrent.TimeUnit
-import akka.actor.{ActorContext, ActorRef}
-import net.psforever.objects.{GlobalDefinitions, Player}
+import akka.actor.ActorContext
+import net.psforever.objects.{Default, GlobalDefinitions, Player}
import net.psforever.objects.definition.ObjectDefinition
import net.psforever.objects.serverobject.generator.Generator
import net.psforever.objects.serverobject.hackable.Hackable
@@ -118,7 +118,7 @@ class Building(private val name: String,
}
def TriggerZoneMapUpdate(): Unit = {
- if(Actor != ActorRef.noSender) Actor ! Building.TriggerZoneMapUpdate(Zone.Number)
+ if(Actor != Default.Actor) Actor ! Building.TriggerZoneMapUpdate(Zone.Number)
}
def UpdateForceDomeStatus() : Unit = {
@@ -141,7 +141,7 @@ class Building(private val name: String,
}
if(originalStatus != ForceDomeActive) {
- if(Actor != ActorRef.noSender) {
+ if(Actor != Default.Actor) {
Zone.LocalEvents ! LocalServiceMessage(Zone.Id, LocalAction.UpdateForceDomeStatus(Service.defaultPlayerGUID, GUID, ForceDomeActive))
Actor ! Building.SendMapUpdate(all_clients = true)
}
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 7f06e1b0..4818f9c0 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
@@ -13,8 +13,8 @@ import services.galaxy.{GalaxyAction, GalaxyResponse, GalaxyServiceMessage, Gala
class BuildingControl(building : Building) extends Actor with FactionAffinityBehavior.Check {
def FactionObject : FactionAffinity = building
- var galaxyService : ActorRef = Actor.noSender
- var interstellarCluster : ActorRef = Actor.noSender
+ var galaxyService : ActorRef = ActorRef.noSender
+ var interstellarCluster : ActorRef = ActorRef.noSender
private[this] val log = org.log4s.getLogger
override def preStart = {
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/MatrixTerminalDefinition.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/MatrixTerminalDefinition.scala
index b815ce2a..3ceb4fdd 100644
--- a/common/src/main/scala/net/psforever/objects/serverobject/terminals/MatrixTerminalDefinition.scala
+++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/MatrixTerminalDefinition.scala
@@ -2,7 +2,7 @@
package net.psforever.objects.serverobject.terminals
import akka.actor.ActorContext
-import net.psforever.objects.Player
+import net.psforever.objects.{Default, Player}
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.serverobject.structures.Amenity
@@ -28,8 +28,8 @@ object MatrixTerminalDefinition {
* @param context hook to the local `Actor` system
*/
def Setup(obj : Amenity, context : ActorContext) : Unit = {
- import akka.actor.{ActorRef, Props}
- if(obj.Actor == ActorRef.noSender) {
+ import akka.actor.Props
+ if(obj.Actor == Default.Actor) {
obj.Actor = context.actorOf(Props(classOf[TerminalControl], obj), PlanetSideServerObject.UniqueActorName(obj))
}
}
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/OrderTerminalDefinition.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/OrderTerminalDefinition.scala
index 5ab86e44..a4bb0e78 100644
--- a/common/src/main/scala/net/psforever/objects/serverobject/terminals/OrderTerminalDefinition.scala
+++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/OrderTerminalDefinition.scala
@@ -3,7 +3,7 @@ package net.psforever.objects.serverobject.terminals
import akka.actor.ActorContext
import net.psforever.objects.definition.ImplantDefinition
-import net.psforever.objects.{Player, Vehicle}
+import net.psforever.objects.{Default, Player, Vehicle}
import net.psforever.objects.equipment.Equipment
import net.psforever.objects.loadouts.{InfantryLoadout, VehicleLoadout}
import net.psforever.objects.inventory.InventoryItem
@@ -340,8 +340,8 @@ object OrderTerminalDefinition {
* @param context hook to the local `Actor` system
*/
def Setup(obj : Amenity, context : ActorContext) : Unit = {
- import akka.actor.{ActorRef, Props}
- if(obj.Actor == ActorRef.noSender) {
+ import akka.actor.Props
+ if(obj.Actor == Default.Actor) {
obj.Actor = context.actorOf(Props(classOf[TerminalControl], obj), PlanetSideServerObject.UniqueActorName(obj))
}
}
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTerminal.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTerminal.scala
index 65ba0fd0..63aa9479 100644
--- a/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTerminal.scala
+++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTerminal.scala
@@ -1,7 +1,7 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.terminals
-import net.psforever.objects.Player
+import net.psforever.objects.{Default, Player}
import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject}
import net.psforever.objects.serverobject.structures.Amenity
import net.psforever.types.Vector3
@@ -74,8 +74,8 @@ object ProximityTerminal {
* @param context hook to the local `Actor` system
*/
def Setup(obj : Amenity, context : ActorContext) : Unit = {
- import akka.actor.{ActorRef, Props}
- if(obj.Actor == ActorRef.noSender) {
+ import akka.actor.Props
+ if(obj.Actor == Default.Actor) {
obj.Actor = context.actorOf(Props(classOf[ProximityTerminalControl], obj), PlanetSideServerObject.UniqueActorName(obj))
obj.Actor ! Service.Startup()
}
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 6c9de987..4cbe945b 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
@@ -30,7 +30,7 @@ class ProximityTerminalControl(term : Terminal with ProximityUnit) extends Actor
def DamageableObject = term
def RepairableObject = term
- var terminalAction : Cancellable = DefaultCancellable.obj
+ var terminalAction : Cancellable = Default.Cancellable
val callbacks : mutable.ListBuffer[ActorRef] = new mutable.ListBuffer[ActorRef]()
val log = org.log4s.getLogger
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/tube/SpawnTubeDefinition.scala b/common/src/main/scala/net/psforever/objects/serverobject/tube/SpawnTubeDefinition.scala
index d96011b9..0ad4e09f 100644
--- a/common/src/main/scala/net/psforever/objects/serverobject/tube/SpawnTubeDefinition.scala
+++ b/common/src/main/scala/net/psforever/objects/serverobject/tube/SpawnTubeDefinition.scala
@@ -2,7 +2,7 @@
package net.psforever.objects.serverobject.tube
import akka.actor.ActorContext
-import net.psforever.objects.SpawnPointDefinition
+import net.psforever.objects.{Default, SpawnPointDefinition}
import net.psforever.objects.definition.converter.SpawnTubeConverter
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.serverobject.structures.{Amenity, AmenityDefinition}
@@ -23,8 +23,8 @@ object SpawnTubeDefinition {
* @param context hook to the local `Actor` system
*/
def Setup(obj : Amenity, context : ActorContext) : Unit = {
- import akka.actor.{ActorRef, Props}
- if(obj.Actor == ActorRef.noSender) {
+ import akka.actor.Props
+ if(obj.Actor == Default.Actor) {
obj.Actor = context.actorOf(Props(classOf[SpawnTubeControl], obj), PlanetSideServerObject.UniqueActorName(obj))
}
}
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/turret/FacilityTurretControl.scala b/common/src/main/scala/net/psforever/objects/serverobject/turret/FacilityTurretControl.scala
index ee273448..5127f7cb 100644
--- a/common/src/main/scala/net/psforever/objects/serverobject/turret/FacilityTurretControl.scala
+++ b/common/src/main/scala/net/psforever/objects/serverobject/turret/FacilityTurretControl.scala
@@ -3,7 +3,7 @@ package net.psforever.objects.serverobject.turret
import akka.actor.Actor
import net.psforever.objects.ballistics.ResolvedProjectile
-import net.psforever.objects.{DefaultCancellable, GlobalDefinitions, Player, Tool}
+import net.psforever.objects.{Default, GlobalDefinitions, Player, Tool}
import net.psforever.objects.equipment.{Ammo, JammableMountedWeapons}
import net.psforever.objects.serverobject.CommonMessages
import net.psforever.objects.serverobject.mount.MountableBehavior
@@ -41,7 +41,7 @@ class FacilityTurretControl(turret : FacilityTurret) extends Actor
def RepairableObject = turret
// Used for timing ammo recharge for vanu turrets in caves
- var weaponAmmoRechargeTimer = DefaultCancellable.obj
+ var weaponAmmoRechargeTimer = Default.Cancellable
def receive : Receive = checkBehavior
.orElse(jammableBehavior)
@@ -65,7 +65,7 @@ class FacilityTurretControl(turret : FacilityTurret) extends Actor
}
case FacilityTurret.WeaponDischarged() =>
- if(weaponAmmoRechargeTimer != DefaultCancellable.obj) {
+ if(weaponAmmoRechargeTimer != Default.Cancellable) {
weaponAmmoRechargeTimer.cancel()
}
@@ -83,9 +83,9 @@ class FacilityTurretControl(turret : FacilityTurret) extends Actor
}
}
- if(weapon.Magazine == weapon.MaxMagazine && weaponAmmoRechargeTimer != DefaultCancellable.obj) {
+ if(weapon.Magazine == weapon.MaxMagazine && weaponAmmoRechargeTimer != Default.Cancellable) {
weaponAmmoRechargeTimer.cancel()
- weaponAmmoRechargeTimer = DefaultCancellable.obj
+ weaponAmmoRechargeTimer = Default.Cancellable
}
case _ => ;
diff --git a/common/src/main/scala/net/psforever/objects/teamwork/SquadFeatures.scala b/common/src/main/scala/net/psforever/objects/teamwork/SquadFeatures.scala
index aa6c05be..da071ea1 100644
--- a/common/src/main/scala/net/psforever/objects/teamwork/SquadFeatures.scala
+++ b/common/src/main/scala/net/psforever/objects/teamwork/SquadFeatures.scala
@@ -1,7 +1,7 @@
// Copyright (c) 2019 PSForever
package net.psforever.objects.teamwork
-import akka.actor.{Actor, ActorContext, ActorRef, Props}
+import akka.actor.{ActorContext, ActorRef, Props}
import net.psforever.types.SquadWaypoints
import services.teamwork.SquadService.WaypointData
import services.teamwork.SquadSwitchboard
@@ -74,7 +74,7 @@ class SquadFeatures(val Squad : Squad) {
def Stop : SquadFeatures = {
switchboard ! akka.actor.PoisonPill
- switchboard = Actor.noSender
+ switchboard = ActorRef.noSender
waypoints = Array.empty
this
}
diff --git a/common/src/main/scala/net/psforever/objects/vehicles/CargoBehavior.scala b/common/src/main/scala/net/psforever/objects/vehicles/CargoBehavior.scala
index 5f7c9795..ed5d25e8 100644
--- a/common/src/main/scala/net/psforever/objects/vehicles/CargoBehavior.scala
+++ b/common/src/main/scala/net/psforever/objects/vehicles/CargoBehavior.scala
@@ -15,8 +15,8 @@ import scala.concurrent.duration._
trait CargoBehavior {
_ : Actor =>
- private var cargoMountTimer : Cancellable = DefaultCancellable.obj
- private var cargoDismountTimer : Cancellable = DefaultCancellable.obj
+ private var cargoMountTimer : Cancellable = Default.Cancellable
+ private var cargoDismountTimer : Cancellable = Default.Cancellable
/* gate-keep mounting behavior so that unit does not try to dismount as cargo, or mount different vehicle */
private var isMounting : Option[PlanetSideGUID] = None
diff --git a/common/src/main/scala/net/psforever/objects/vehicles/Utility.scala b/common/src/main/scala/net/psforever/objects/vehicles/Utility.scala
index 11829053..039c3cc0 100644
--- a/common/src/main/scala/net/psforever/objects/vehicles/Utility.scala
+++ b/common/src/main/scala/net/psforever/objects/vehicles/Utility.scala
@@ -269,6 +269,6 @@ object InternalTelepadDefinition {
def SimpleUninitialize(obj : PlanetSideServerObject, context : ActorContext) : Unit = {
context.stop(obj.Actor)
- obj.Actor = ActorRef.noSender
+ obj.Actor = Default.Actor
}
}
diff --git a/common/src/main/scala/net/psforever/objects/vehicles/VehicleControl.scala b/common/src/main/scala/net/psforever/objects/vehicles/VehicleControl.scala
index 6a62b822..2d4d7e6f 100644
--- a/common/src/main/scala/net/psforever/objects/vehicles/VehicleControl.scala
+++ b/common/src/main/scala/net/psforever/objects/vehicles/VehicleControl.scala
@@ -52,7 +52,7 @@ class VehicleControl(vehicle : Vehicle) extends Actor
/** cheap flag for whether the vehicle is decaying */
var decaying : Boolean = false
/** primary vehicle decay timer */
- var decayTimer : Cancellable = DefaultCancellable.obj
+ var decayTimer : Cancellable = Default.Cancellable
def receive : Receive = Enabled
@@ -62,7 +62,7 @@ class VehicleControl(vehicle : Vehicle) extends Actor
decayTimer.cancel
vehicle.Utilities.values.foreach { util =>
context.stop(util().Actor)
- util().Actor = ActorRef.noSender
+ util().Actor = Default.Actor
}
}
diff --git a/common/src/main/scala/net/psforever/objects/zones/SphereOfInfluenceActor.scala b/common/src/main/scala/net/psforever/objects/zones/SphereOfInfluenceActor.scala
index f08082ed..b07a45f1 100644
--- a/common/src/main/scala/net/psforever/objects/zones/SphereOfInfluenceActor.scala
+++ b/common/src/main/scala/net/psforever/objects/zones/SphereOfInfluenceActor.scala
@@ -1,7 +1,7 @@
package net.psforever.objects.zones
import akka.actor.{Actor, Cancellable}
-import net.psforever.objects.{DefaultCancellable, Player}
+import net.psforever.objects.{Default, Player}
import net.psforever.objects.definition.ObjectDefinition
import net.psforever.objects.serverobject.structures.{Building, SphereOfInfluence}
import net.psforever.types.Vector3
@@ -12,7 +12,7 @@ import scala.concurrent.duration._
class SphereOfInfluenceActor(zone: Zone) extends Actor {
var sois : Iterable[(Building, Int)] = Nil
- var populateTick : Cancellable = DefaultCancellable.obj
+ var populateTick : Cancellable = Default.Cancellable
//private[this] val log = org.log4s.getLogger(s"${zone.Id.capitalize}-SphereOfInfluenceActor")
def receive : Receive = Stopped
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 4e2b49b2..08c29e87 100644
--- a/common/src/main/scala/net/psforever/objects/zones/Zone.scala
+++ b/common/src/main/scala/net/psforever/objects/zones/Zone.scala
@@ -55,13 +55,13 @@ import scala.util.Try
*/
class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
/** Governs general synchronized external requests. */
- private var actor = ActorRef.noSender
+ private var actor = Default.Actor
/** Actor that handles SOI related functionality, for example if a player is in a SOI **/
- private var soi = ActorRef.noSender
+ private var soi = Default.Actor
/** Used by the globally unique identifier system to coordinate requests. */
- private var accessor : ActorRef = ActorRef.noSender
+ private var accessor : ActorRef = Default.Actor
/** The basic support structure for the globally unique number system used by this `Zone`. */
private var guid : NumberPoolHub = new NumberPoolHub(new LimitedNumberSource(65536))
/** A synchronized `List` of items (`Equipment`) dropped by players on the ground and can be collected again. */
@@ -69,19 +69,19 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
/** */
private val vehicles : ListBuffer[Vehicle] = ListBuffer[Vehicle]()
/** Used by the `Zone` to coordinate `Equipment` dropping and collection requests. */
- private var ground : ActorRef = ActorRef.noSender
+ private var ground : ActorRef = Default.Actor
/** */
private val constructions : ListBuffer[PlanetSideGameObject with Deployable] = ListBuffer[PlanetSideGameObject with Deployable]()
/** */
- private var deployables : ActorRef = ActorRef.noSender
+ private var deployables : ActorRef = Default.Actor
/** */
- private var transport : ActorRef = ActorRef.noSender
+ private var transport : ActorRef = Default.Actor
/** */
private val players : TrieMap[Avatar, Option[Player]] = TrieMap[Avatar, Option[Player]]()
/** */
private val corpses : ListBuffer[Player] = ListBuffer[Player]()
/** */
- private var population : ActorRef = ActorRef.noSender
+ private var population : ActorRef = Default.Actor
private var buildings : PairMap[Int, Building] = PairMap.empty[Int, Building]
@@ -92,7 +92,7 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
/** key - spawn zone id, value - buildings belonging to spawn zone */
private var spawnGroups : Map[Building, List[SpawnPoint]] = PairMap[Building, List[SpawnPoint]]()
/** */
- private var projector : ActorRef = ActorRef.noSender
+ private var projector : ActorRef = Default.Actor
/** */
private var hotspots : ListBuffer[HotSpotInfo] = ListBuffer[HotSpotInfo]()
/** */
@@ -102,11 +102,11 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
/** calculate a duration from a given interaction's participants */
private var hotspotTimeFunc : (SourceEntry, SourceEntry)=>FiniteDuration = Zone.HotSpot.Rules.NoTime
/** */
- private var avatarEvents : ActorRef = ActorRef.noSender
+ private var avatarEvents : ActorRef = Default.Actor
/** */
- private var localEvents : ActorRef = ActorRef.noSender
+ private var localEvents : ActorRef = Default.Actor
/** */
- private var vehicleEvents : ActorRef = ActorRef.noSender
+ private var vehicleEvents : ActorRef = Default.Actor
/**
* Establish the basic accessible conditions necessary for a functional `Zone`.
@@ -126,7 +126,7 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
* @param context a reference to an `ActorContext` necessary for `Props`
*/
def Init(implicit context : ActorContext) : Unit = {
- if(accessor == ActorRef.noSender) {
+ if(accessor == Default.Actor) {
SetupNumberPools()
accessor = context.actorOf(RandomPool(25).props(Props(classOf[UniqueNumberSystem], this.guid, UniqueNumberSystem.AllocateNumberPoolActors(this.guid))), s"$Id-uns")
ground = context.actorOf(Props(classOf[ZoneGroundActor], this, equipmentOnGround), s"$Id-ground")
@@ -187,7 +187,7 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
* @see `ZoneActor`
*/
def Actor_=(zoneActor : ActorRef) : ActorRef = {
- if(actor == ActorRef.noSender) {
+ if(actor == Default.Actor) {
actor = zoneActor
}
Actor
@@ -226,7 +226,7 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
* @return synchronized reference to the globally unique identifier system
*/
def GUID(hub : NumberPoolHub) : Boolean = {
- if(actor == ActorRef.noSender && guid.Pools.values.foldLeft(0)(_ + _.Count) == 0) {
+ if(actor == Default.Actor && guid.Pools.values.foldLeft(0)(_ + _.Count) == 0) {
import org.fusesource.jansi.Ansi.Color.RED
import org.fusesource.jansi.Ansi.ansi
println(ansi().fgBright(RED).a(s"""Caution: replacement of the number pool system for zone $Id; function is for testing purposes only""").reset())
@@ -248,7 +248,7 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
* `false`, if the new pool can not be created because the system has already been started
*/
def AddPool(name : String, pool : Seq[Int]) : Boolean = {
- if(accessor == ActorRef.noSender) {
+ if(accessor == Default.Actor) {
guid.AddPool(name, pool.toList)
true
}
@@ -266,7 +266,7 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
* `false`, if the new pool can not be removed because the system has already been started
*/
def RemovePool(name : String) : Boolean = {
- if(accessor == ActorRef.noSender) {
+ if(accessor == Default.Actor) {
guid.RemovePool(name)
true
}
diff --git a/common/src/main/scala/net/psforever/objects/zones/ZoneHotSpotProjector.scala b/common/src/main/scala/net/psforever/objects/zones/ZoneHotSpotProjector.scala
index be4fd1a0..9aed54e7 100644
--- a/common/src/main/scala/net/psforever/objects/zones/ZoneHotSpotProjector.scala
+++ b/common/src/main/scala/net/psforever/objects/zones/ZoneHotSpotProjector.scala
@@ -2,7 +2,7 @@
package net.psforever.objects.zones
import akka.actor.{Actor, ActorRef, Cancellable, Props}
-import net.psforever.objects.DefaultCancellable
+import net.psforever.objects.Default
import net.psforever.types.{PlanetSideEmpire, Vector3}
import services.ServiceManager
@@ -59,7 +59,7 @@ class ZoneHotSpotProjector(zone : Zone, hotspots : ListBuffer[HotSpotInfo], blan
/** a hook for the `GalaxyService` used to broadcast messages */
var galaxy : ActorRef = ActorRef.noSender
/** the timer for the blanking process */
- var blanking : Cancellable = DefaultCancellable.obj
+ var blanking : Cancellable = Default.Cancellable
/** how long to wait in between blanking periods while hotspots decay */
var blankingDelay : FiniteDuration = blankingTime
diff --git a/common/src/main/scala/net/psforever/objects/zones/ZonePopulationActor.scala b/common/src/main/scala/net/psforever/objects/zones/ZonePopulationActor.scala
index 1f7bdf0a..f6bae4bb 100644
--- a/common/src/main/scala/net/psforever/objects/zones/ZonePopulationActor.scala
+++ b/common/src/main/scala/net/psforever/objects/zones/ZonePopulationActor.scala
@@ -3,7 +3,7 @@ package net.psforever.objects.zones
import akka.actor.{Actor, ActorRef, Props}
import net.psforever.objects.avatar.PlayerControl
-import net.psforever.objects.{Avatar, Player}
+import net.psforever.objects.{Avatar, Default, Player}
import scala.annotation.tailrec
import scala.collection.concurrent.TrieMap
@@ -47,7 +47,7 @@ class ZonePopulationActor(zone : Zone, playerMap : TrieMap[Avatar, Option[Player
sender ! Zone.Population.PlayerAlreadySpawned(zone, player)
}
else if(newToZone) {
- player.Actor = context.actorOf(Props(classOf[PlayerControl], player), s"${player.CharId}_${player.GUID.guid}_${System.currentTimeMillis}")
+ player.Actor = context.actorOf(Props(classOf[PlayerControl], player), name = GetPlayerControlName(player, None))
player.Zone = zone
}
case None =>
@@ -63,10 +63,15 @@ class ZonePopulationActor(zone : Zone, playerMap : TrieMap[Avatar, Option[Player
}
case Zone.Corpse.Add(player) =>
- CorpseAdd(player, corpseList)
+ if(CorpseAdd(player, corpseList)) {
+ player.Actor = context.actorOf(Props(classOf[PlayerControl], player), name = s"corpse_of_${GetPlayerControlName(player, None)}")
+ player.Zone = zone
+ }
case Zone.Corpse.Remove(player) =>
- CorpseRemove(player, corpseList)
+ if(CorpseRemove(player, corpseList)) {
+ PlayerLeave(player)
+ }
case _ => ;
}
@@ -168,17 +173,19 @@ object ZonePopulationActor {
* @param player a `Player` object
* @param corpseList a list of `Player` objects
*/
- def CorpseRemove(player : Player, corpseList : ListBuffer[Player]) : Unit = {
+ def CorpseRemove(player : Player, corpseList : ListBuffer[Player]) : Boolean = {
recursiveFindCorpse(corpseList.iterator, player) match {
- case None => ;
+ case None =>
+ false
case Some(index) =>
corpseList.remove(index)
+ true
}
}
def PlayerLeave(player : Player) : Unit = {
player.Actor ! akka.actor.PoisonPill
- player.Actor = ActorRef.noSender
+ player.Actor = Default.Actor
}
/**
@@ -202,4 +209,14 @@ object ZonePopulationActor {
}
}
}
+
+ def GetPlayerControlName(player : Player, old : Option[ActorRef]) : String = {
+ old match {
+ case Some(control) =>
+ val nameNumber = control.toString.split("/").last //split on '/'
+ nameNumber.split("#").head //split on '#'
+ case None => ;
+ s"${player.CharId}_${player.GUID.guid}_${System.currentTimeMillis}" //new
+ }
+ }
}
diff --git a/common/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala b/common/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala
index 4fd31757..be4bdbce 100644
--- a/common/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala
+++ b/common/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala
@@ -1,8 +1,8 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.zones
-import akka.actor.{Actor, ActorRef, Props}
-import net.psforever.objects.Vehicle
+import akka.actor.{Actor, Props}
+import net.psforever.objects.{Default, Vehicle}
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.vehicles.VehicleControl
@@ -38,7 +38,7 @@ class ZoneVehicleActor(zone : Zone, vehicleList : ListBuffer[Vehicle]) extends A
else if(vehicleList.contains(vehicle)) {
sender ! Zone.Vehicle.CanNotSpawn(zone, vehicle, "already in zone")
}
- else if(vehicle.Actor != ActorRef.noSender) {
+ else if(vehicle.Actor != Default.Actor) {
sender ! Zone.Vehicle.CanNotSpawn(zone, vehicle, "already in another zone")
}
else {
@@ -52,7 +52,7 @@ class ZoneVehicleActor(zone : Zone, vehicleList : ListBuffer[Vehicle]) extends A
case Some(index) =>
vehicleList.remove(index)
context.stop(vehicle.Actor)
- vehicle.Actor = ActorRef.noSender
+ vehicle.Actor = Default.Actor
case None => ;
sender ! Zone.Vehicle.CanNotDespawn(zone, vehicle, "can not find")
}
diff --git a/common/src/main/scala/services/RemoverActor.scala b/common/src/main/scala/services/RemoverActor.scala
index 58415aa5..7e200c76 100644
--- a/common/src/main/scala/services/RemoverActor.scala
+++ b/common/src/main/scala/services/RemoverActor.scala
@@ -1,10 +1,10 @@
// Copyright (c) 2017 PSForever
package services
-import akka.actor.{Actor, ActorRef, Cancellable}
+import akka.actor.{ActorRef, Cancellable}
import net.psforever.objects.guid.TaskResolver
import net.psforever.objects.zones.Zone
-import net.psforever.objects.{DefaultCancellable, PlanetSideGameObject}
+import net.psforever.objects.{Default, PlanetSideGameObject}
import net.psforever.types.Vector3
import services.support.{SimilarityComparator, SupportActor, SupportActorCaseConversions}
@@ -33,7 +33,7 @@ abstract class RemoverActor extends SupportActor[RemoverActor.Entry] {
/**
* The timer that checks whether entries in the first pool are still eligible for that pool.
*/
- var firstTask : Cancellable = DefaultCancellable.obj
+ var firstTask : Cancellable = Default.Cancellable
/**
* The first pool of objects waiting to be processed for removal.
*/
@@ -42,13 +42,13 @@ abstract class RemoverActor extends SupportActor[RemoverActor.Entry] {
/**
* The timer that checks whether entries in the second pool are still eligible for that pool.
*/
- var secondTask : Cancellable = DefaultCancellable.obj
+ var secondTask : Cancellable = Default.Cancellable
/**
* The second pool of objects waiting to be processed for removal.
*/
var secondHeap : List[RemoverActor.Entry] = List()
- protected var taskResolver : ActorRef = Actor.noSender
+ protected var taskResolver : ActorRef = ActorRef.noSender
val sameEntryComparator = new SimilarityComparator[RemoverActor.Entry]() {
def Test(entry1 : RemoverActor.Entry, entry2 : RemoverActor.Entry) : Boolean = {
diff --git a/common/src/main/scala/services/ServiceManager.scala b/common/src/main/scala/services/ServiceManager.scala
index 91dcb449..bf2628e1 100644
--- a/common/src/main/scala/services/ServiceManager.scala
+++ b/common/src/main/scala/services/ServiceManager.scala
@@ -1,12 +1,12 @@
+// Copyright (c) 2017 PSForever
package services
-// Copyright (c) 2017 PSForever
import akka.actor.{Actor, ActorIdentity, ActorRef, ActorSystem, Identify, Props}
import scala.collection.mutable
object ServiceManager {
- var serviceManager = Actor.noSender
+ var serviceManager = ActorRef.noSender
def boot(implicit system : ActorSystem) = {
serviceManager = system.actorOf(Props[ServiceManager], "service")
diff --git a/common/src/main/scala/services/account/AccountPersistenceService.scala b/common/src/main/scala/services/account/AccountPersistenceService.scala
index e0bdf217..3c7f290d 100644
--- a/common/src/main/scala/services/account/AccountPersistenceService.scala
+++ b/common/src/main/scala/services/account/AccountPersistenceService.scala
@@ -190,7 +190,7 @@ class PersistenceMonitor(name : String, squadService : ActorRef, taskResolver :
/** the last-reported game coordinate position of this player */
var lastPosition : Vector3 = Vector3.Zero
/** the ongoing amount of permissible inactivity */
- var timer : Cancellable = DefaultCancellable.obj
+ var timer : Cancellable = Default.Cancellable
/** the sparingly-used log */
val log = org.log4s.getLogger
@@ -309,7 +309,7 @@ class PersistenceMonitor(name : String, squadService : ActorRef, taskResolver :
player.Position = Vector3.Zero
player.Health = 0
inZone.GUID(player.VehicleOwned) match {
- case Some(vehicle : Vehicle) if vehicle.OwnerName.contains(player.Name) && vehicle.Actor != ActorRef.noSender =>
+ case Some(vehicle : Vehicle) if vehicle.OwnerName.contains(player.Name) && vehicle.Actor != Default.Actor =>
vehicle.Actor ! Vehicle.Ownership(None)
case _ => ;
}
diff --git a/common/src/main/scala/services/local/support/DoorCloseActor.scala b/common/src/main/scala/services/local/support/DoorCloseActor.scala
index 771e47a8..2b497751 100644
--- a/common/src/main/scala/services/local/support/DoorCloseActor.scala
+++ b/common/src/main/scala/services/local/support/DoorCloseActor.scala
@@ -2,7 +2,7 @@
package services.local.support
import akka.actor.{Actor, Cancellable}
-import net.psforever.objects.{DefaultCancellable, Player}
+import net.psforever.objects.{Default, Player}
import net.psforever.objects.serverobject.doors.Door
import net.psforever.objects.serverobject.structures.Building
import net.psforever.objects.zones.Zone
@@ -18,7 +18,7 @@ import scala.concurrent.duration._
*/
class DoorCloseActor() extends Actor {
/** The periodic `Executor` that checks for doors to be closed */
- private var doorCloserTrigger : Cancellable = DefaultCancellable.obj
+ private var doorCloserTrigger : Cancellable = Default.Cancellable
/** A `List` of currently open doors */
private var openDoors : List[DoorCloseActor.DoorEntry] = Nil
//private[this] val log = org.log4s.getLogger
diff --git a/common/src/main/scala/services/local/support/HackCaptureActor.scala b/common/src/main/scala/services/local/support/HackCaptureActor.scala
index 18387e8f..e01d13cf 100644
--- a/common/src/main/scala/services/local/support/HackCaptureActor.scala
+++ b/common/src/main/scala/services/local/support/HackCaptureActor.scala
@@ -1,7 +1,7 @@
package services.local.support
import akka.actor.{Actor, Cancellable}
-import net.psforever.objects.DefaultCancellable
+import net.psforever.objects.Default
import net.psforever.objects.serverobject.hackable.Hackable
import net.psforever.objects.serverobject.structures.Building
import net.psforever.objects.serverobject.terminals.CaptureTerminal
@@ -14,7 +14,7 @@ import scala.concurrent.duration.{FiniteDuration, _}
class HackCaptureActor extends Actor {
private [this] val log = org.log4s.getLogger
- private var clearTrigger : Cancellable = DefaultCancellable.obj
+ private var clearTrigger : Cancellable = Default.Cancellable
/** A `List` of currently hacked server objects */
private var hackedObjects : List[HackCaptureActor.HackEntry] = Nil
diff --git a/common/src/main/scala/services/local/support/HackClearActor.scala b/common/src/main/scala/services/local/support/HackClearActor.scala
index a53becd8..53fcfae2 100644
--- a/common/src/main/scala/services/local/support/HackClearActor.scala
+++ b/common/src/main/scala/services/local/support/HackClearActor.scala
@@ -4,7 +4,7 @@ package services.local.support
import java.util.concurrent.TimeUnit
import akka.actor.{Actor, Cancellable}
-import net.psforever.objects.DefaultCancellable
+import net.psforever.objects.Default
import net.psforever.objects.serverobject.hackable.Hackable
import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject}
import net.psforever.objects.zones.Zone
@@ -20,7 +20,7 @@ import scala.concurrent.duration._
*/
class HackClearActor() extends Actor {
/** The periodic `Executor` that checks for server objects to be unhacked */
- private var clearTrigger : Cancellable = DefaultCancellable.obj
+ private var clearTrigger : Cancellable = Default.Cancellable
/** A `List` of currently hacked server objects */
private var hackedObjects : List[HackClearActor.HackEntry] = Nil
private[this] val log = org.log4s.getLogger
diff --git a/common/src/main/scala/services/local/support/RouterTelepadActivation.scala b/common/src/main/scala/services/local/support/RouterTelepadActivation.scala
index 25f54881..f471e573 100644
--- a/common/src/main/scala/services/local/support/RouterTelepadActivation.scala
+++ b/common/src/main/scala/services/local/support/RouterTelepadActivation.scala
@@ -9,7 +9,7 @@ import services.support.{SimilarityComparator, SupportActor}
import scala.concurrent.duration._
class RouterTelepadActivation extends SupportActor[RouterTelepadActivation.Entry] {
- var activationTask : Cancellable = DefaultCancellable.obj
+ var activationTask : Cancellable = Default.Cancellable
var telepadList : List[RouterTelepadActivation.Entry] = List()
val sameEntryComparator = new SimilarityComparator[RouterTelepadActivation.Entry]() {
def Test(entry1 : RouterTelepadActivation.Entry, entry2 : RouterTelepadActivation.Entry) : Boolean = {
diff --git a/common/src/main/scala/services/vehicle/support/TurretUpgrader.scala b/common/src/main/scala/services/vehicle/support/TurretUpgrader.scala
index 0d09607b..d0e27daf 100644
--- a/common/src/main/scala/services/vehicle/support/TurretUpgrader.scala
+++ b/common/src/main/scala/services/vehicle/support/TurretUpgrader.scala
@@ -1,8 +1,8 @@
// Copyright (c) 2017 PSForever
package services.vehicle.support
-import akka.actor.{Actor, ActorRef, Cancellable}
-import net.psforever.objects.{AmmoBox, DefaultCancellable, PlanetSideGameObject, Tool}
+import akka.actor.{ActorRef, Cancellable}
+import net.psforever.objects.{AmmoBox, Default, PlanetSideGameObject, Tool}
import net.psforever.objects.guid.{GUIDTask, Task, TaskResolver}
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.serverobject.turret.{FacilityTurret, TurretUpgrade, WeaponTurret}
@@ -16,11 +16,11 @@ import services.{Service, ServiceManager}
import scala.concurrent.duration._
class TurretUpgrader extends SupportActor[TurretUpgrader.Entry] {
- var task : Cancellable = DefaultCancellable.obj
+ var task : Cancellable = Default.Cancellable
var list : List[TurretUpgrader.Entry] = List()
- private var taskResolver : ActorRef = Actor.noSender
+ private var taskResolver : ActorRef = ActorRef.noSender
val sameEntryComparator = new SimilarityComparator[TurretUpgrader.Entry]() {
def Test(entry1 : TurretUpgrader.Entry, entry2 : TurretUpgrader.Entry) : Boolean = {
diff --git a/common/src/main/scala/services/vehicle/support/VehicleRemover.scala b/common/src/main/scala/services/vehicle/support/VehicleRemover.scala
index 1f57e85f..7ddab7a2 100644
--- a/common/src/main/scala/services/vehicle/support/VehicleRemover.scala
+++ b/common/src/main/scala/services/vehicle/support/VehicleRemover.scala
@@ -7,7 +7,7 @@ import net.psforever.objects.guid.GUIDTask.UnregisterVehicle
import services.{RemoverActor, ServiceManager}
class VehicleRemover extends Actor {
- var taskResolver : ActorRef = Actor.noSender
+ var taskResolver : ActorRef = ActorRef.noSender
override def preStart() : Unit = {
super.preStart()
diff --git a/common/src/test/scala/objects/BuildingTest.scala b/common/src/test/scala/objects/BuildingTest.scala
index cec8b518..c605ffda 100644
--- a/common/src/test/scala/objects/BuildingTest.scala
+++ b/common/src/test/scala/objects/BuildingTest.scala
@@ -1,9 +1,9 @@
// Copyright (c) 2017 PSForever
package objects
-import akka.actor.{ActorRef, Props}
+import akka.actor.Props
import base.ActorTest
-import net.psforever.objects.GlobalDefinitions
+import net.psforever.objects.{Default, GlobalDefinitions}
import net.psforever.objects.serverobject.affinity.FactionAffinity
import net.psforever.objects.serverobject.doors.{Door, DoorControl}
import net.psforever.objects.serverobject.structures._
@@ -72,7 +72,7 @@ class BuildingTest extends Specification {
"construct" in {
val bldg = Building("Building", 0, 10, Zone.Nowhere, StructureType.Building)
bldg.MapId mustEqual 10
- bldg.Actor mustEqual ActorRef.noSender
+ bldg.Actor mustEqual Default.Actor
bldg.Amenities mustEqual Nil
bldg.Zone mustEqual Zone.Nowhere
bldg.Faction mustEqual PlanetSideEmpire.NEUTRAL
@@ -107,7 +107,7 @@ class WarpGateTest extends Specification {
"construct" in {
val bldg = WarpGate("WarpGate", 0, 10, Zone.Nowhere, GlobalDefinitions.warpgate)
bldg.MapId mustEqual 10
- bldg.Actor mustEqual ActorRef.noSender
+ bldg.Actor mustEqual Default.Actor
bldg.Amenities mustEqual Nil
bldg.Zone mustEqual Zone.Nowhere
bldg.Faction mustEqual PlanetSideEmpire.NEUTRAL
@@ -120,7 +120,7 @@ class BuildingControl1Test extends ActorTest {
"construct" in {
val bldg = Building("Building", 0, 10, Zone.Nowhere, StructureType.Building)
bldg.Actor = system.actorOf(Props(classOf[BuildingControl], bldg), "test")
- assert(bldg.Actor != ActorRef.noSender)
+ assert(bldg.Actor != Default.Actor)
}
}
}
diff --git a/common/src/test/scala/objects/DefaultTest.scala b/common/src/test/scala/objects/DefaultTest.scala
new file mode 100644
index 00000000..224a5e08
--- /dev/null
+++ b/common/src/test/scala/objects/DefaultTest.scala
@@ -0,0 +1,49 @@
+// Copyright (c) 2020 PSForever
+package objects
+
+import akka.actor.DeadLetter
+import akka.testkit.TestProbe
+import base.ActorTest
+import net.psforever.objects.Default
+import org.specs2.mutable.Specification
+
+import scala.concurrent.duration._
+
+class DefaultTest extends Specification {
+ "Default.Cancellable" should {
+ "always act like it can be cancelled successfully" in {
+ Default.Cancellable.cancel mustEqual true
+ }
+
+ "always act like it was cancelled successfully" in {
+ Default.Cancellable.isCancelled mustEqual true
+ }
+ }
+}
+
+class DefaultActorStartedTest extends ActorTest {
+ "Default.Actor" should {
+ "send messages to deadLetters" in {
+ //after being started
+ Default(system)
+ val probe = new TestProbe(system)
+ system.eventStream.subscribe(probe.ref, classOf[DeadLetter])
+ Default.Actor ! "hello world"
+ val msg1 = probe.receiveOne(250 milliseconds)
+ assert(msg1.isInstanceOf[DeadLetter])
+ assert(msg1.asInstanceOf[DeadLetter].message equals "hello world")
+
+ //if it was stopped
+ system.stop(Default.Actor)
+ Default.Actor ! "hello world"
+ val msg2 = probe.receiveOne(250 milliseconds)
+ assert(msg2.isInstanceOf[DeadLetter])
+ assert(msg2.asInstanceOf[DeadLetter].message equals "hello world")
+ }
+ }
+}
+
+object DefaultActorTest {
+ //due to being a singleton, the original original value of the Default.Actor is cached here
+ val Original = Default.Actor
+}
diff --git a/common/src/test/scala/objects/DeployableTest.scala b/common/src/test/scala/objects/DeployableTest.scala
index a60456c1..cc318f97 100644
--- a/common/src/test/scala/objects/DeployableTest.scala
+++ b/common/src/test/scala/objects/DeployableTest.scala
@@ -592,11 +592,11 @@ class TurretControlInitializeTest extends ActorTest {
"initialize" in {
val obj = new TurretDeployable(GlobalDefinitions.spitfire_turret)
obj.GUID = PlanetSideGUID(1)
- assert(obj.Actor == ActorRef.noSender)
+ assert(obj.Actor == Default.Actor)
val init = system.actorOf(Props(classOf[DeployableTest.TurretInitializer], obj), "init_turret_test")
init ! "initialize"
expectNoMessage(200 milliseconds)
- assert(obj.Actor != ActorRef.noSender)
+ assert(obj.Actor != Default.Actor)
}
}
}
@@ -609,11 +609,11 @@ class TurretControlUninitializeTest extends ActorTest {
obj.GUID = PlanetSideGUID(1)
init ! "initialize"
expectNoMessage(200 milliseconds)
- assert(obj.Actor != ActorRef.noSender)
+ assert(obj.Actor != Default.Actor)
init ! "uninitialize"
expectNoMessage(200 milliseconds)
- assert(obj.Actor == ActorRef.noSender)
+ assert(obj.Actor == Default.Actor)
}
}
}
diff --git a/common/src/test/scala/objects/DeploymentTest.scala b/common/src/test/scala/objects/DeploymentTest.scala
index ef11da72..c0bf4bf2 100644
--- a/common/src/test/scala/objects/DeploymentTest.scala
+++ b/common/src/test/scala/objects/DeploymentTest.scala
@@ -1,7 +1,7 @@
// Copyright (c) 2017 PSForever
package objects
-import akka.actor.{Actor, ActorSystem, Props}
+import akka.actor.{Actor, ActorRef, ActorSystem, Props}
import base.ActorTest
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.{GlobalDefinitions, Vehicle}
@@ -46,7 +46,7 @@ class DeploymentBehavior1Test extends ActorTest {
"Deployment" should {
"construct" in {
val obj = DeploymentTest.SetUpAgent
- assert(obj.Actor != Actor.noSender)
+ assert(obj.Actor != ActorRef.noSender)
assert(obj.DeploymentState == DriveState.Mobile)
}
}
diff --git a/common/src/test/scala/objects/DoorTest.scala b/common/src/test/scala/objects/DoorTest.scala
index 2a5bc597..b488aa48 100644
--- a/common/src/test/scala/objects/DoorTest.scala
+++ b/common/src/test/scala/objects/DoorTest.scala
@@ -1,9 +1,9 @@
// Copyright (c) 2017 PSForever
package objects
-import akka.actor.{ActorRef, ActorSystem, Props}
+import akka.actor.{ActorSystem, Props}
import base.ActorTest
-import net.psforever.objects.{Avatar, GlobalDefinitions, Player}
+import net.psforever.objects.{Avatar, Default, GlobalDefinitions, Player}
import net.psforever.objects.serverobject.doors.{Door, DoorControl}
import net.psforever.objects.serverobject.structures.{Building, StructureType}
import net.psforever.objects.zones.Zone
@@ -59,7 +59,7 @@ class DoorControl1Test extends ActorTest {
"construct" in {
val door = Door(GlobalDefinitions.door)
door.Actor = system.actorOf(Props(classOf[DoorControl], door), "door")
- assert(door.Actor != ActorRef.noSender)
+ assert(door.Actor != Default.Actor)
}
}
}
diff --git a/common/src/test/scala/objects/FacilityTurretTest.scala b/common/src/test/scala/objects/FacilityTurretTest.scala
index 72d9664d..23f6ab9b 100644
--- a/common/src/test/scala/objects/FacilityTurretTest.scala
+++ b/common/src/test/scala/objects/FacilityTurretTest.scala
@@ -1,10 +1,10 @@
// Copyright (c) 2017 PSForever
package objects
-import akka.actor.{ActorRef, Props}
+import akka.actor.Props
import akka.testkit.TestProbe
import base.ActorTest
-import net.psforever.objects.{Avatar, GlobalDefinitions, Player, Tool}
+import net.psforever.objects.{Avatar, Default, GlobalDefinitions, Player, Tool}
import net.psforever.objects.definition.ToolDefinition
import net.psforever.objects.guid.NumberPoolHub
import net.psforever.objects.guid.source.LimitedNumberSource
@@ -94,7 +94,7 @@ class FacilityTurretControl1Test extends ActorTest {
"construct" in {
val obj = FacilityTurret(GlobalDefinitions.manned_turret)
obj.Actor = system.actorOf(Props(classOf[FacilityTurretControl], obj), "turret-control")
- assert(obj.Actor != ActorRef.noSender)
+ assert(obj.Actor != Default.Actor)
}
}
}
diff --git a/common/src/test/scala/objects/IFFLockTest.scala b/common/src/test/scala/objects/IFFLockTest.scala
index fe60a530..a82973ad 100644
--- a/common/src/test/scala/objects/IFFLockTest.scala
+++ b/common/src/test/scala/objects/IFFLockTest.scala
@@ -1,10 +1,10 @@
// Copyright (c) 2017 PSForever
package objects
-import akka.actor.{ActorRef, ActorSystem, Props}
+import akka.actor.{ActorSystem, Props}
import base.ActorTest
+import net.psforever.objects.{Avatar, Default, GlobalDefinitions, Player}
import net.psforever.objects.serverobject.CommonMessages
-import net.psforever.objects.{Avatar, GlobalDefinitions, Player}
import net.psforever.objects.serverobject.locks.{IFFLock, IFFLockControl}
import net.psforever.objects.serverobject.structures.{Building, StructureType}
import net.psforever.objects.zones.Zone
@@ -48,7 +48,7 @@ class IFFLockControl1Test extends ActorTest {
"construct" in {
val lock = IFFLock(GlobalDefinitions.lock_external)
lock.Actor = system.actorOf(Props(classOf[IFFLockControl], lock), "lock-control")
- assert(lock.Actor != ActorRef.noSender)
+ assert(lock.Actor != Default.Actor)
}
}
}
diff --git a/common/src/test/scala/objects/LockerTest.scala b/common/src/test/scala/objects/LockerTest.scala
index b1f9d017..82f0b12c 100644
--- a/common/src/test/scala/objects/LockerTest.scala
+++ b/common/src/test/scala/objects/LockerTest.scala
@@ -1,7 +1,7 @@
// Copyright (c) 2017 PSForever
package objects
-import akka.actor.{ActorRef, Props}
+import akka.actor.Props
import base.ActorTest
import net.psforever.objects.GlobalDefinitions
import net.psforever.objects.serverobject.affinity.FactionAffinity
@@ -19,8 +19,8 @@ class LockerTest extends Specification {
"Locker" should {
"construct" in {
- val locker = new Locker()
- locker.Actor mustEqual ActorRef.noSender
+ new Locker()
+ ok
}
}
}
diff --git a/common/src/test/scala/objects/PlayerControlTest.scala b/common/src/test/scala/objects/PlayerControlTest.scala
index 7a2a4667..90338965 100644
--- a/common/src/test/scala/objects/PlayerControlTest.scala
+++ b/common/src/test/scala/objects/PlayerControlTest.scala
@@ -187,7 +187,7 @@ class PlayerControlRepairTest extends ActorTest {
assert(originalArmor < player2.MaxArmor)
player2.Actor ! CommonMessages.Use(player1, Some(tool))
- val msg_avatar = avatarProbe.receiveN(5, 500 milliseconds)
+ val msg_avatar = avatarProbe.receiveN(5, 1000 milliseconds)
assert(
msg_avatar.head match {
case AvatarServiceMessage("TestCharacter1", AvatarAction.SendResponse(_, InventoryStateMessage(PlanetSideGUID(4), _, PlanetSideGUID(3), _))) => true
diff --git a/common/src/test/scala/objects/SpawnTubeTest.scala b/common/src/test/scala/objects/SpawnTubeTest.scala
index 96b37921..89cf686f 100644
--- a/common/src/test/scala/objects/SpawnTubeTest.scala
+++ b/common/src/test/scala/objects/SpawnTubeTest.scala
@@ -1,9 +1,9 @@
// Copyright (c) 2017 PSForever
package objects
-import akka.actor.{ActorRef, Props}
+import akka.actor.Props
import base.ActorTest
-import net.psforever.objects.GlobalDefinitions
+import net.psforever.objects.{Default, GlobalDefinitions}
import net.psforever.objects.serverobject.tube.{SpawnTube, SpawnTubeControl, SpawnTubeDefinition}
import org.specs2.mutable.Specification
@@ -18,7 +18,7 @@ class SpawnTubeTest extends Specification {
"SpawnTube" should {
"construct" in {
val obj = SpawnTube(GlobalDefinitions.ams_respawn_tube)
- obj.Actor mustEqual ActorRef.noSender
+ obj.Actor mustEqual Default.Actor
obj.Definition mustEqual GlobalDefinitions.ams_respawn_tube
}
}
@@ -29,7 +29,7 @@ class SpawnTubeControlTest extends ActorTest {
"construct" in {
val obj = SpawnTube(GlobalDefinitions.ams_respawn_tube)
obj.Actor = system.actorOf(Props(classOf[SpawnTubeControl], obj), "spawn-tube")
- assert(obj.Actor != ActorRef.noSender)
+ assert(obj.Actor != Default.Actor)
}
}
}
diff --git a/common/src/test/scala/objects/UtilityTest.scala b/common/src/test/scala/objects/UtilityTest.scala
index c7f200ab..afd88a43 100644
--- a/common/src/test/scala/objects/UtilityTest.scala
+++ b/common/src/test/scala/objects/UtilityTest.scala
@@ -20,7 +20,7 @@ class UtilityTest extends Specification {
obj.UtilType mustEqual UtilityType.order_terminala
obj().isInstanceOf[Terminal] mustEqual true
obj().asInstanceOf[Terminal].Definition.ObjectId mustEqual 613
- obj().asInstanceOf[Terminal].Actor mustEqual ActorRef.noSender
+ obj().asInstanceOf[Terminal].Actor mustEqual Default.Actor
}
"create an order_terminalb object" in {
@@ -28,7 +28,7 @@ class UtilityTest extends Specification {
obj.UtilType mustEqual UtilityType.order_terminalb
obj().isInstanceOf[Terminal] mustEqual true
obj().asInstanceOf[Terminal].Definition.ObjectId mustEqual 614
- obj().asInstanceOf[Terminal].Actor mustEqual ActorRef.noSender
+ obj().asInstanceOf[Terminal].Actor mustEqual Default.Actor
}
"create a matrix_terminalc object" in {
@@ -36,7 +36,7 @@ class UtilityTest extends Specification {
obj.UtilType mustEqual UtilityType.matrix_terminalc
obj().isInstanceOf[Terminal] mustEqual true
obj().asInstanceOf[Terminal].Definition.ObjectId mustEqual 519
- obj().asInstanceOf[Terminal].Actor mustEqual ActorRef.noSender
+ obj().asInstanceOf[Terminal].Actor mustEqual Default.Actor
}
"create an ams_respawn_tube object" in {
@@ -44,7 +44,7 @@ class UtilityTest extends Specification {
obj.UtilType mustEqual UtilityType.ams_respawn_tube
obj().isInstanceOf[SpawnTube] mustEqual true
obj().asInstanceOf[SpawnTube].Definition.ObjectId mustEqual 49
- obj().asInstanceOf[SpawnTube].Actor mustEqual ActorRef.noSender
+ obj().asInstanceOf[SpawnTube].Actor mustEqual Default.Actor
}
"create a teleportpad_terminal object" in {
@@ -52,7 +52,7 @@ class UtilityTest extends Specification {
obj.UtilType mustEqual UtilityType.teleportpad_terminal
obj().isInstanceOf[Terminal] mustEqual true
obj().asInstanceOf[Terminal].Definition.ObjectId mustEqual 853
- obj().asInstanceOf[Terminal].Actor mustEqual ActorRef.noSender
+ obj().asInstanceOf[Terminal].Actor mustEqual Default.Actor
}
"produce a telepad object through the teleportpad_terminal" in {
@@ -78,7 +78,7 @@ class UtilityTest extends Specification {
obj.UtilType mustEqual UtilityType.internal_router_telepad_deployable
obj().isInstanceOf[Utility.InternalTelepad] mustEqual true
obj().asInstanceOf[Utility.InternalTelepad].Definition.ObjectId mustEqual 744
- obj().asInstanceOf[Utility.InternalTelepad].Actor mustEqual ActorRef.noSender
+ obj().asInstanceOf[Utility.InternalTelepad].Actor mustEqual Default.Actor
}
"internal_router_telepad_deployable can keep track of an object's GUID (presumedly, it's a Telepad)" in {
@@ -139,11 +139,11 @@ class UtilityTerminalATest extends ActorTest {
"wire an order_terminala Actor" in {
val obj = Utility(UtilityType.order_terminala, UtilityTest.vehicle)
obj().GUID = PlanetSideGUID(1)
- assert(obj().Actor == ActorRef.noSender)
+ assert(obj().Actor == Default.Actor)
system.actorOf(Props(classOf[UtilityTest.SetupControl], obj), "test") ! ""
receiveOne(Duration.create(500, "ms")) //consume and discard
- assert(obj().Actor != ActorRef.noSender)
+ assert(obj().Actor != Default.Actor)
}
}
}
@@ -153,11 +153,11 @@ class UtilityTerminalBTest extends ActorTest {
"wire an order_terminalb Actor" in {
val obj = Utility(UtilityType.order_terminalb, UtilityTest.vehicle)
obj().GUID = PlanetSideGUID(1)
- assert(obj().Actor == ActorRef.noSender)
+ assert(obj().Actor == Default.Actor)
system.actorOf(Props(classOf[UtilityTest.SetupControl], obj), "test") ! ""
receiveOne(Duration.create(500, "ms")) //consume and discard
- assert(obj().Actor != ActorRef.noSender)
+ assert(obj().Actor != Default.Actor)
}
}
}
@@ -167,11 +167,11 @@ class UtilityTerminalCTest extends ActorTest {
"wire a matrix_terminalc Actor" in {
val obj = Utility(UtilityType.matrix_terminalc, UtilityTest.vehicle)
obj().GUID = PlanetSideGUID(1)
- assert(obj().Actor == ActorRef.noSender)
+ assert(obj().Actor == Default.Actor)
system.actorOf(Props(classOf[UtilityTest.SetupControl], obj), "test") ! ""
receiveOne(Duration.create(500, "ms")) //consume and discard
- assert(obj().Actor != ActorRef.noSender)
+ assert(obj().Actor != Default.Actor)
}
}
}
@@ -181,11 +181,11 @@ class UtilityRespawnTubeTest extends ActorTest {
"wire an ams_respawn_tube Actor" in {
val obj = Utility(UtilityType.ams_respawn_tube, UtilityTest.vehicle)
obj().GUID = PlanetSideGUID(1)
- assert(obj().Actor == ActorRef.noSender)
+ assert(obj().Actor == Default.Actor)
system.actorOf(Props(classOf[UtilityTest.SetupControl], obj), "test") ! ""
receiveOne(Duration.create(500, "ms")) //consume and discard
- assert(obj().Actor != ActorRef.noSender)
+ assert(obj().Actor != Default.Actor)
}
}
}
@@ -195,11 +195,11 @@ class UtilityTelepadTerminalTest extends ActorTest {
"wire a teleportpad_terminal Actor" in {
val obj = Utility(UtilityType.teleportpad_terminal, UtilityTest.vehicle)
obj().GUID = PlanetSideGUID(1)
- assert(obj().Actor == ActorRef.noSender)
+ assert(obj().Actor == Default.Actor)
system.actorOf(Props(classOf[UtilityTest.SetupControl], obj), "test") ! ""
receiveOne(Duration.create(500, "ms")) //consume and discard
- assert(obj().Actor != ActorRef.noSender)
+ assert(obj().Actor != Default.Actor)
}
}
}
@@ -211,12 +211,12 @@ class UtilityInternalTelepadTest extends ActorTest {
veh.GUID = PlanetSideGUID(101)
val obj = Utility(UtilityType.internal_router_telepad_deployable, veh)
obj().GUID = PlanetSideGUID(1)
- assert(obj().Actor == ActorRef.noSender)
+ assert(obj().Actor == Default.Actor)
assert(obj().asInstanceOf[Utility.InternalTelepad].Router.contains(veh.GUID))
system.actorOf(Props(classOf[UtilityTest.SetupControl], obj), "test") ! ""
receiveOne(Duration.create(500, "ms")) //consume and discard
- assert(obj().Actor != ActorRef.noSender)
+ assert(obj().Actor != Default.Actor)
assert(obj().asInstanceOf[Utility.InternalTelepad].Router.contains(veh.GUID))
}
}
diff --git a/common/src/test/scala/objects/VehicleSpawnPadTest.scala b/common/src/test/scala/objects/VehicleSpawnPadTest.scala
index 3d56e304..469fcba1 100644
--- a/common/src/test/scala/objects/VehicleSpawnPadTest.scala
+++ b/common/src/test/scala/objects/VehicleSpawnPadTest.scala
@@ -1,9 +1,8 @@
// Copyright (c) 2017 PSForever
package objects
-import akka.actor.ActorRef
+import net.psforever.objects.{Default, GlobalDefinitions}
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
-import net.psforever.objects.GlobalDefinitions
import org.specs2.mutable.Specification
class VehicleSpawnPadTest extends Specification {
@@ -16,7 +15,7 @@ class VehicleSpawnPadTest extends Specification {
"VehicleSpawnPad" should {
"construct" in {
val obj = VehicleSpawnPad(GlobalDefinitions.mb_pad_creation)
- obj.Actor mustEqual ActorRef.noSender
+ obj.Actor mustEqual Default.Actor
obj.Definition mustEqual GlobalDefinitions.mb_pad_creation
}
}
diff --git a/common/src/test/scala/objects/ZoneTest.scala b/common/src/test/scala/objects/ZoneTest.scala
index 1b814178..533c5c6e 100644
--- a/common/src/test/scala/objects/ZoneTest.scala
+++ b/common/src/test/scala/objects/ZoneTest.scala
@@ -92,10 +92,6 @@ class ZoneTest extends Specification {
"Zone" should {
"construct" in {
val zone = new Zone("home3", map13, 13)
- zone.GUID mustEqual ActorRef.noSender
- zone.Ground mustEqual ActorRef.noSender
- zone.Transport mustEqual ActorRef.noSender
- //zone also has a unique identifier system but it can't be accessed without its the Actor GUID being initialized
zone.EquipmentOnGround mustEqual List.empty[Equipment]
zone.Vehicles mustEqual List.empty[Vehicle]
zone.Players mustEqual List.empty[Player]
diff --git a/common/src/test/scala/objects/number/RegisterTest.scala b/common/src/test/scala/objects/number/RegisterTest.scala
index ef9314cb..fbce828e 100644
--- a/common/src/test/scala/objects/number/RegisterTest.scala
+++ b/common/src/test/scala/objects/number/RegisterTest.scala
@@ -1,7 +1,7 @@
// Copyright (c) 2017 PSForever
package objects.number
-import akka.actor.Actor
+import akka.actor.ActorRef
import net.psforever.objects.guid.actor.Register
import org.specs2.mutable.Specification
@@ -18,11 +18,11 @@ class RegisterTest extends Specification {
}
"construct (object, callback)" in {
- val reg = Register(obj, Actor.noSender)
+ val reg = Register(obj, ActorRef.noSender)
reg.obj mustEqual obj
reg.number.isEmpty mustEqual true
reg.name.isEmpty mustEqual true
- reg.callback.contains(Actor.noSender) mustEqual true
+ reg.callback.contains(ActorRef.noSender) mustEqual true
}
"construct (object, suggested number)" in {
@@ -34,11 +34,11 @@ class RegisterTest extends Specification {
}
"construct (object, suggested number, callback)" in {
- val reg = Register(obj, 5, Actor.noSender)
+ val reg = Register(obj, 5, ActorRef.noSender)
reg.obj mustEqual obj
reg.number.contains(5) mustEqual true
reg.name.isEmpty mustEqual true
- reg.callback.contains(Actor.noSender) mustEqual true
+ reg.callback.contains(ActorRef.noSender) mustEqual true
}
"construct (object, pool name)" in {
@@ -50,11 +50,11 @@ class RegisterTest extends Specification {
}
"construct (object, pool name, callback)" in {
- val reg = Register(obj, "pool", Actor.noSender)
+ val reg = Register(obj, "pool", ActorRef.noSender)
reg.obj mustEqual obj
reg.number.isEmpty mustEqual true
reg.name.contains("pool") mustEqual true
- reg.callback.contains(Actor.noSender) mustEqual true
+ reg.callback.contains(ActorRef.noSender) mustEqual true
}
}
}
diff --git a/common/src/test/scala/objects/terminal/ImplantTerminalMechTest.scala b/common/src/test/scala/objects/terminal/ImplantTerminalMechTest.scala
index 387728d1..d9193af9 100644
--- a/common/src/test/scala/objects/terminal/ImplantTerminalMechTest.scala
+++ b/common/src/test/scala/objects/terminal/ImplantTerminalMechTest.scala
@@ -1,8 +1,9 @@
// Copyright (c) 2017 PSForever
package objects.terminal
-import akka.actor.{ActorRef, ActorSystem, Props}
+import akka.actor.{ActorSystem, Props}
import base.ActorTest
+import net.psforever.objects.{Avatar, Default, GlobalDefinitions, Player}
import net.psforever.objects.definition.SeatDefinition
import net.psforever.objects.guid.NumberPoolHub
import net.psforever.objects.guid.source.LimitedNumberSource
@@ -12,7 +13,6 @@ import net.psforever.objects.serverobject.structures.{Building, StructureType}
import net.psforever.objects.serverobject.terminals.Terminal
import net.psforever.objects.vehicles.Seat
import net.psforever.objects.zones.{Zone, ZoneMap}
-import net.psforever.objects.{Avatar, GlobalDefinitions, Player}
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire, Vector3}
import org.specs2.mutable.Specification
@@ -35,7 +35,7 @@ class ImplantTerminalMechTest extends Specification {
"Implant_Terminal_Mech" should {
"construct" in {
val obj = ImplantTerminalMech(GlobalDefinitions.implant_terminal_mech)
- obj.Actor mustEqual ActorRef.noSender
+ obj.Actor mustEqual Default.Actor
obj.Definition mustEqual GlobalDefinitions.implant_terminal_mech
obj.Seats.keySet mustEqual Set(0)
obj.Seats(0).isInstanceOf[Seat] mustEqual true
@@ -65,7 +65,7 @@ class ImplantTerminalMechControl1Test extends ActorTest {
"construct" in {
val obj = ImplantTerminalMech(GlobalDefinitions.implant_terminal_mech)
obj.Actor = system.actorOf(Props(classOf[ImplantTerminalMechControl], obj), "mech")
- assert(obj.Actor != ActorRef.noSender)
+ assert(obj.Actor != Default.Actor)
}
}
}
diff --git a/common/src/test/scala/service/LocalServiceTest.scala b/common/src/test/scala/service/LocalServiceTest.scala
index cd4dafad..3ef697c2 100644
--- a/common/src/test/scala/service/LocalServiceTest.scala
+++ b/common/src/test/scala/service/LocalServiceTest.scala
@@ -6,6 +6,7 @@ import base.ActorTest
import net.psforever.objects.{GlobalDefinitions, SensorDeployable, Vehicle}
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.serverobject.terminals.{ProximityTerminal, Terminal}
+import net.psforever.objects.vehicles.VehicleControl
import net.psforever.objects.zones.Zone
import net.psforever.packet.game._
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID, Vector3}
@@ -206,6 +207,7 @@ class ToggleTeleportSystemTest extends ActorTest {
"LocalService" should {
"pass ToggleTeleportSystem" in {
val router = Vehicle(GlobalDefinitions.router)
+ router.Actor = system.actorOf(Props(classOf[VehicleControl], router), "test-router")
val service = system.actorOf(Props(classOf[LocalService], Zone.Nowhere), "l_service")
service ! Service.Join("test")
service ! LocalServiceMessage("test", LocalAction.ToggleTeleportSystem(PlanetSideGUID(10), router, None))
diff --git a/common/src/test/scala/service/VehicleServiceTest.scala b/common/src/test/scala/service/VehicleServiceTest.scala
index 9a5ffce7..e59343f3 100644
--- a/common/src/test/scala/service/VehicleServiceTest.scala
+++ b/common/src/test/scala/service/VehicleServiceTest.scala
@@ -4,6 +4,7 @@ package service
import akka.actor.Props
import base.ActorTest
import net.psforever.objects._
+import net.psforever.objects.vehicles.VehicleControl
import net.psforever.objects.zones.Zone
import net.psforever.types.{PlanetSideGUID, _}
import services.{Service, ServiceManager}
@@ -171,6 +172,7 @@ class KickPassengerTest extends ActorTest {
class LoadVehicleTest extends ActorTest {
ServiceManager.boot(system)
val vehicle = Vehicle(GlobalDefinitions.quadstealth)
+ vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "test-vehicle")
val cdata = vehicle.Definition.Packet.ConstructorData(vehicle).get
"VehicleService" should {
@@ -260,6 +262,7 @@ class TransferPassengerChannelTest extends ActorTest {
"pass TransferPassengerChannel" in {
val service = system.actorOf(Props(classOf[VehicleService], Zone.Nowhere), "v-service")
val fury = Vehicle(GlobalDefinitions.fury)
+ fury.Actor = system.actorOf(Props(classOf[VehicleControl], fury), "test-fury")
service ! Service.Join("test")
service ! VehicleServiceMessage("test", VehicleAction.TransferPassengerChannel(PlanetSideGUID(10), "old_channel", "new_channel", fury, PlanetSideGUID(11)))
expectMsg(VehicleServiceResponse("/test/Vehicle", PlanetSideGUID(10), VehicleResponse.TransferPassengerChannel("old_channel", "new_channel", fury, PlanetSideGUID(11))))
diff --git a/pslogin/src/main/scala/LoginSessionActor.scala b/pslogin/src/main/scala/LoginSessionActor.scala
index c279082f..1e667374 100644
--- a/pslogin/src/main/scala/LoginSessionActor.scala
+++ b/pslogin/src/main/scala/LoginSessionActor.scala
@@ -12,7 +12,7 @@ import MDCContextAware.Implicits._
import com.github.mauricio.async.db.general.ArrayRowData
import com.github.mauricio.async.db.{Connection, QueryResult}
import net.psforever.objects.Account
-import net.psforever.objects.DefaultCancellable
+import net.psforever.objects.Default
import net.psforever.types.PlanetSideEmpire
import net.psforever.WorldConfig
import services.ServiceManager
@@ -40,9 +40,9 @@ class LoginSessionActor extends Actor with MDCContextAware {
var sessionId : Long = 0
var leftRef : ActorRef = ActorRef.noSender
var rightRef : ActorRef = ActorRef.noSender
- var accountIntermediary : ActorRef = Actor.noSender
+ var accountIntermediary : ActorRef = ActorRef.noSender
- var updateServerListTask : Cancellable = DefaultCancellable.obj
+ var updateServerListTask : Cancellable = Default.Cancellable
var ipAddress : String = ""
var hostName : String = ""
diff --git a/pslogin/src/main/scala/PacketCodingActor.scala b/pslogin/src/main/scala/PacketCodingActor.scala
index 310e3c7b..42559447 100644
--- a/pslogin/src/main/scala/PacketCodingActor.scala
+++ b/pslogin/src/main/scala/PacketCodingActor.scala
@@ -5,7 +5,7 @@ import scodec.Attempt.{Failure, Successful}
import scodec.bits._
import org.log4s.MDC
import MDCContextAware.Implicits._
-import net.psforever.objects.DefaultCancellable
+import net.psforever.objects.Default
import net.psforever.packet.control.{HandleGamePacket, _}
import scala.annotation.tailrec
@@ -52,7 +52,7 @@ class PacketCodingActor extends Actor with MDCContextAware {
// Due to the fact the client can send `RelatedA` packets out of order, we need to keep a buffer of which subslots arrived correctly, order them
// and then act accordingly to send the missing subslot packet after a specified timeout
private var relatedALog : ArrayBuffer[Int] = ArrayBuffer()
- private var relatedABufferTimeout : Cancellable = DefaultCancellable.obj
+ private var relatedABufferTimeout : Cancellable = Default.Cancellable
def AddSlottedPacketToLog(subslot: Int, packet : ByteVector): Unit = {
val log_limit = 500 // Number of SlottedMetaPackets to keep in history
@@ -386,7 +386,7 @@ class PacketCodingActor extends Actor with MDCContextAware {
// The client has indicated it's received up to a certain subslot, that means we can purge the log of any subslots prior to and including the confirmed subslot
// Find where this subslot is stored in the packet log (if at all) and drop anything to the left of it, including itself
- if(relatedABufferTimeout.isCancelled || relatedABufferTimeout == DefaultCancellable.obj) {
+ if(relatedABufferTimeout.isCancelled || relatedABufferTimeout == Default.Cancellable) {
val pos = slottedPacketLog.keySet.toArray.indexOf(subslot)
if(pos != -1) {
slottedPacketLog = slottedPacketLog.drop(pos+1)
diff --git a/pslogin/src/main/scala/PsLogin.scala b/pslogin/src/main/scala/PsLogin.scala
index f68d4535..1978b2ad 100644
--- a/pslogin/src/main/scala/PsLogin.scala
+++ b/pslogin/src/main/scala/PsLogin.scala
@@ -13,6 +13,7 @@ import ch.qos.logback.core.util.StatusPrinter
import com.typesafe.config.ConfigFactory
import net.psforever.config.{Invalid, Valid}
import net.psforever.crypto.CryptoInterface
+import net.psforever.objects.Default
import net.psforever.objects.zones._
import net.psforever.objects.guid.TaskResolver
import net.psforever.psadmin.PsAdminActor
@@ -225,6 +226,7 @@ object PsLogin {
/** Start up the main actor system. This "system" is the home for all actors running on this server */
system = ActorSystem("PsLogin")
+ Default(system)
logger.info("Starting actor pipelines")
/** Create pipelines for the login and world servers
diff --git a/pslogin/src/main/scala/SessionRouter.scala b/pslogin/src/main/scala/SessionRouter.scala
index 8b7fc805..f911e31d 100644
--- a/pslogin/src/main/scala/SessionRouter.scala
+++ b/pslogin/src/main/scala/SessionRouter.scala
@@ -48,7 +48,7 @@ class SessionRouter(role : String, pipeline : List[SessionPipeline]) extends Act
val sessionById = mutable.Map[Long, Session]()
val sessionByActor = mutable.Map[ActorRef, Session]()
val closePacket = PacketCoding.EncodePacket(ConnectionClose()).require.bytes
- var accountIntermediary : ActorRef = Actor.noSender
+ var accountIntermediary : ActorRef = ActorRef.noSender
var sessionId = 0L // this is a connection session, not an actual logged in session ID
var inputRef : ActorRef = ActorRef.noSender
diff --git a/pslogin/src/main/scala/TcpListener.scala b/pslogin/src/main/scala/TcpListener.scala
index 92fa8260..39280caf 100644
--- a/pslogin/src/main/scala/TcpListener.scala
+++ b/pslogin/src/main/scala/TcpListener.scala
@@ -25,7 +25,7 @@ class TcpListener[T <: Actor](actorClass : Class[T],
var sessionId = 0L
var bytesRecevied = 0L
var bytesSent = 0L
- var nextActor : ActorRef = Actor.noSender
+ var nextActor : ActorRef = ActorRef.noSender
def receive = {
case Tcp.Bound(local) =>
diff --git a/pslogin/src/main/scala/UdpListener.scala b/pslogin/src/main/scala/UdpListener.scala
index dffc15f1..73a145e3 100644
--- a/pslogin/src/main/scala/UdpListener.scala
+++ b/pslogin/src/main/scala/UdpListener.scala
@@ -38,7 +38,7 @@ class UdpListener(nextActorProps : Props,
var bytesRecevied = 0L
var bytesSent = 0L
- var nextActor : ActorRef = Actor.noSender
+ var nextActor : ActorRef = ActorRef.noSender
def receive = {
case Udp.Bound(local) =>
diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala
index 2cea782e..e180a64f 100644
--- a/pslogin/src/main/scala/WorldSessionActor.scala
+++ b/pslogin/src/main/scala/WorldSessionActor.scala
@@ -5,10 +5,7 @@ import com.github.mauricio.async.db.general.ArrayRowData
import com.github.mauricio.async.db.{Connection, QueryResult}
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
-
-import net.psforever.WorldConfig
import org.log4s.{Logger, MDC}
-
import scala.annotation.{switch, tailrec}
import scala.collection.mutable.LongMap
import scala.concurrent.{Await, Future, Promise}
@@ -62,6 +59,7 @@ import net.psforever.packet.game._
import net.psforever.packet.game.objectcreate.{ConstructorData, DetailedCharacterData, DroppedItemData, ObjectClass, ObjectCreateMessageParent, PlacementData}
import net.psforever.packet.game.{HotSpotInfo => PacketHotSpotInfo}
import net.psforever.types._
+import net.psforever.WorldConfig
import services.{RemoverActor, Service, ServiceManager}
import services.account.{AccountPersistenceService, PlayerToken, ReceiveAccountData, RetrieveAccountData}
import services.avatar.{AvatarAction, AvatarResponse, AvatarServiceMessage, AvatarServiceResponse}
@@ -89,8 +87,8 @@ class WorldSessionActor extends Actor
var chatService : ActorRef = ActorRef.noSender
var galaxyService : ActorRef = ActorRef.noSender
var squadService : ActorRef = ActorRef.noSender
- var taskResolver : ActorRef = Actor.noSender
- var cluster : ActorRef = Actor.noSender
+ var taskResolver : ActorRef = ActorRef.noSender
+ var cluster : ActorRef = ActorRef.noSender
var continent : Zone = Zone.Nowhere
var account : Account = null
var player : Player = null
@@ -163,9 +161,13 @@ class WorldSessionActor extends Actor
var squadSetup : () => Unit = FirstTimeSquadSetup
var squadUpdateCounter : Int = 0
val queuedSquadActions : Seq[() => Unit] = Seq(SquadUpdates, NoSquadUpdates, NoSquadUpdates, NoSquadUpdates)
- /** Keeps track of the number of PlayerStateMessageUpstream messages received by the client
+ /** Upstream message counter
+ * Checks for server acknowledgement of the following messages:
+ * `PlayerStateMessageUpstream`
+ * `VehicleStateMessage` (driver seat only)
+ * `ChildObjectStateMessage` (any seat but driver)
* As they should arrive roughly every 250 milliseconds this allows for a very crude method of scheduling tasks up to four times per second */
- private var playerStateMessageUpstreamCount = 0
+ private var upstreamMessageCount : Int = 0
var zoningType : Zoning.Method.Value = Zoning.Method.None
var zoningChatMessageType : ChatMessageType.Value = ChatMessageType.CMT_QUIT
var zoningStatus : Zoning.Status.Value = Zoning.Status.None
@@ -174,17 +176,26 @@ class WorldSessionActor extends Actor
lazy val unsignedIntMaxValue : Long = Int.MaxValue.toLong * 2L + 1L
var serverTime : Long = 0
var amsSpawnPoints : List[SpawnPoint] = Nil
+ /** a flag for the zone having finished loading during zoning
+ * `None` when no zone is loaded
+ * `Some(true)` when a zone has successfully loaded
+ * `Some(false)` when the loading process has failed or was executed but did not complete for some reason
+ * */
+ var zoneLoaded : Option[Boolean] = None
+ /** a flag that forces the current zone to reload itself during a zoning operation */
+ var zoneReload : Boolean = false
+ var turnCounter : PlanetSideGUID=>Unit = TurnCounterDuringInterim
- var clientKeepAlive : Cancellable = DefaultCancellable.obj
- var progressBarUpdate : Cancellable = DefaultCancellable.obj
- var reviveTimer : Cancellable = DefaultCancellable.obj
- var respawnTimer : Cancellable = DefaultCancellable.obj
- var cargoMountTimer : Cancellable = DefaultCancellable.obj
- var cargoDismountTimer : Cancellable = DefaultCancellable.obj
- var antChargingTick : Cancellable = DefaultCancellable.obj
- var antDischargingTick : Cancellable = DefaultCancellable.obj
- var zoningTimer : Cancellable = DefaultCancellable.obj
- var zoningReset : Cancellable = DefaultCancellable.obj
+ var clientKeepAlive : Cancellable = Default.Cancellable
+ var progressBarUpdate : Cancellable = Default.Cancellable
+ var reviveTimer : Cancellable = Default.Cancellable
+ var respawnTimer : Cancellable = Default.Cancellable
+ var cargoMountTimer : Cancellable = Default.Cancellable
+ var cargoDismountTimer : Cancellable = Default.Cancellable
+ var antChargingTick : Cancellable = Default.Cancellable
+ var antDischargingTick : Cancellable = Default.Cancellable
+ var zoningTimer : Cancellable = Default.Cancellable
+ var zoningReset : Cancellable = Default.Cancellable
/**
* Convert a boolean value into an integer value.
* Use: `true:Int` or `false:Int`
@@ -832,14 +843,14 @@ class WorldSessionActor extends Actor
case Zone.Population.PlayerHasLeft(zone, Some(tplayer)) =>
if(tplayer.isAlive) {
- log.info(s"$tplayer has left zone ${zone.Id}")
+ log.info(s"${tplayer.Name} has left zone ${zone.Id}")
}
case Zone.Population.PlayerCanNotSpawn(zone, tplayer) =>
- log.warn(s"$tplayer can not spawn in zone ${zone.Id}; why?")
+ log.warn(s"${tplayer.Name} can not spawn in zone ${zone.Id}; why?")
case Zone.Population.PlayerAlreadySpawned(zone, tplayer) =>
- log.warn(s"$tplayer is already spawned on zone ${zone.Id}; a clerical error?")
+ log.warn(s"${tplayer.Name} is already spawned on zone ${zone.Id}; a clerical error?")
case Zone.Lattice.SpawnPoint(zone_id, spawn_tube) =>
CancelZoningProcess()
@@ -917,7 +928,7 @@ class WorldSessionActor extends Actor
PutItemOnGround(item, pos, orient)
case Zone.Ground.CanNotDropItem(zone, item, reason) =>
- log.warn(s"DropItem: $player tried to drop a $item on the ground, but $reason")
+ log.warn(s"DropItem: ${player.Name} tried to drop a $item on the ground, but $reason")
if(!item.HasGUID) {
log.warn(s"DropItem: zone ${continent.Id} contents may be in disarray")
}
@@ -951,9 +962,9 @@ class WorldSessionActor extends Actor
case Zone.Ground.CanNotPickupItem(zone, item_guid, _) =>
zone.GUID(item_guid) match {
case Some(item) =>
- log.warn(s"DropItem: finding a $item on the ground was suggested, but $player can not reach it")
+ log.warn(s"DropItem: finding a $item on the ground was suggested, but ${player.Name} can not reach it")
case None =>
- log.warn(s"DropItem: finding an item ($item_guid) on the ground was suggested, but $player can not see it")
+ log.warn(s"DropItem: finding an item ($item_guid) on the ground was suggested, but ${player.Name} can not see it")
sendResponse(ObjectDeleteMessage(item_guid, 0))
}
@@ -1504,6 +1515,9 @@ class WorldSessionActor extends Actor
val weaponsEnabled = (continent.Map.Name != "map11" && continent.Map.Name != "map12" && continent.Map.Name != "map13")
sendResponse(LoadMapMessage(continent.Map.Name, continent.Id, 40100, 25, weaponsEnabled, continent.Map.Checksum))
setupAvatarFunc() //important! the LoadMapMessage must be processed by the client before the avatar is created
+ turnCounter = TurnCounterDuringInterim
+ context.system.scheduler.scheduleOnce(delay = 2000 millisecond, self, SetCurrentAvatar(tplayer, 200))
+ upstreamMessageCount = 0
persist()
case PlayerLoaded(tplayer) =>
@@ -1511,8 +1525,9 @@ class WorldSessionActor extends Actor
log.info(s"Player ${tplayer.Name} will respawn")
player = tplayer
setupAvatarFunc()
+ upstreamMessageCount = 0
persist()
- self ! SetCurrentAvatar(tplayer)
+ self ! SetCurrentAvatar(tplayer, 200)
case PlayerFailedToLoad(tplayer) =>
player.Continent match {
@@ -1520,12 +1535,66 @@ class WorldSessionActor extends Actor
failWithError(s"${tplayer.Name} failed to load anywhere")
}
- case SetCurrentAvatar(tplayer) =>
- if(tplayer.Actor == ActorRef.noSender) {
- respawnTimer = context.system.scheduler.scheduleOnce(100 milliseconds, self, SetCurrentAvatar(tplayer))
+ /*
+ The user is either already in the current zone and merely transporting himself from one location to another,
+ also called "dying", or occasionally "deconstructing,"
+ or is completely switching in between zones.
+ These correspond to the message NewPlayerLoaded for the case of "dying" or the latter zone switching case,
+ and PlayerLoaded for "deconstruction."
+ In the latter case, the user must wait for the zone to be recognized as loaded for the server
+ and this is performed through the send LoadMapMessage, receive BeginZoningMessage exchange
+ The user's player should have already been registered into the new zone
+ and is at some stage of being added to the zone in which they will have control agency in that zone.
+ Whether or not the zone is loaded in the earlier case depends on the destination with respect to the current location.
+ Once all of the following is (assumed) accomplished,
+ the servwer will attempt to declare that user's player the avatar of the user's client.
+ Reception of certain packets that represent "reported user activity" after that marks the end of avatar loading.
+ If the maximum number of unsuccessful attempts is reached, some course of action is taken.
+ If the player dies, the process does not need to continue.
+ He may or may not be accompanied by a vehicle at any stage of this process.
+ */
+ case SetCurrentAvatar(tplayer, max_attempts, attempt) =>
+ respawnTimer.cancel
+ val waitingOnUpstream = upstreamMessageCount == 0
+ if(attempt >= max_attempts && waitingOnUpstream) {
+ zoneLoaded match {
+ case None | Some(false) =>
+ log.warn("SetCurrentAvatar: failed to load intended destination zone; routing to faction sanctuary")
+ RequestSanctuaryZoneSpawn(tplayer, continent.Number)
+ case _ =>
+ log.warn("SetCurrentAvatar: the zone loaded but elements remain unready; restarting the process ...")
+ val pos = shiftPosition.getOrElse(player.Position)
+ val orient = shiftOrientation.getOrElse(player.Orientation)
+ sendResponse(AvatarDeadStateMessage(DeadState.Release, 0, 0, pos, player.Faction, true))
+ val toZoneId = continent.Id
+ tplayer.Die
+ continent.Population ! Zone.Population.Leave(avatar) //does not matter if it doesn't work
+ zoneLoaded = None
+ zoneReload = true
+ LoadZonePhysicalSpawnPoint(toZoneId, pos, orient, respawnTime = 0L)
+ }
}
- else {
- HandleSetCurrentAvatar(tplayer)
+ else if(tplayer.isAlive) {
+ if(
+ zoneLoaded.contains(true) &&
+ tplayer.HasGUID && tplayer.Actor != Default.Actor && (continent.GUID(tplayer.VehicleSeated) match {
+ case Some(o : Vehicle) => o.HasGUID && o.Actor != Default.Actor && !o.Destroyed
+ case _ => true
+ })
+ ) {
+ if(waitingOnUpstream) {
+ beginZoningSetCurrentAvatarFunc(tplayer)
+ respawnTimer = context.system.scheduler.scheduleOnce(
+ delay = (if(attempt <= max_attempts / 2) 10 else 5) seconds,
+ self,
+ SetCurrentAvatar(tplayer, max_attempts, attempt + max_attempts / 3)
+ )
+ }
+ //if not the condition above, player has started playing normally
+ }
+ else {
+ respawnTimer = context.system.scheduler.scheduleOnce(500 milliseconds, self, SetCurrentAvatar(tplayer, max_attempts, attempt + 1))
+ }
}
case NtuCharging(tplayer, vehicle) =>
@@ -1737,7 +1806,7 @@ class WorldSessionActor extends Actor
case _ =>
//fall back to sanctuary/prior?
- log.error(s"LoginInfo: player $playerName could not be found in game world")
+ log.error(s"LoginInfo: player ${player.Name}Name could not be found in game world")
self ! PlayerToken.LoginInfo(playerName, Zone.Nowhere, pos)
}
@@ -1898,7 +1967,7 @@ class WorldSessionActor extends Actor
/**
* Use the zoning process using some spawnable entity in the destination zone.
- * @param zone the destination zone
+ * @param zone the destination zone
* @param spawnPosition the destination spawn position
* @param spawnOrientation the destination spawn orientation
*/
@@ -2586,7 +2655,7 @@ class WorldSessionActor extends Actor
CancelZoningProcessWithDescriptiveReason("cancel_mount")
val obj_guid : PlanetSideGUID = obj.GUID
val player_guid : PlanetSideGUID = tplayer.GUID
- log.info(s"MountVehicleMsg: $player_guid mounts $obj_guid @ $seat_num")
+ log.info(s"MountVehicleMsg: ${player.Name}_guid mounts $obj_guid @ $seat_num")
CancelAllProximityUnits()
sendResponse(PlanetsideAttributeMessage(obj_guid, 0, obj.Health))
sendResponse(PlanetsideAttributeMessage(obj_guid, 68, obj.Shields)) //shield health
@@ -2658,16 +2727,16 @@ class WorldSessionActor extends Actor
log.warn(s"DismountVehicleMsg: $obj is some generic mountable object and nothing will happen")
case Mountable.CanNotMount(obj : Vehicle, seat_num) =>
- log.warn(s"MountVehicleMsg: $tplayer attempted to mount $obj's seat $seat_num, but was not allowed")
+ log.warn(s"MountVehicleMsg: ${tplayer.Name} attempted to mount $obj's seat $seat_num, but was not allowed")
if(obj.SeatPermissionGroup(seat_num).contains(AccessPermissionGroup.Driver)) {
sendResponse(ChatMsg(ChatMessageType.CMT_OPEN, false, "", "You are not the driver of this vehicle.", None))
}
case Mountable.CanNotMount(obj : Mountable, seat_num) =>
- log.warn(s"MountVehicleMsg: $tplayer attempted to mount $obj's seat $seat_num, but was not allowed")
+ log.warn(s"MountVehicleMsg: ${tplayer.Name} attempted to mount $obj's seat $seat_num, but was not allowed")
case Mountable.CanNotDismount(obj, seat_num) =>
- log.warn(s"DismountVehicleMsg: $tplayer attempted to dismount $obj's seat $seat_num, but was not allowed")
+ log.warn(s"DismountVehicleMsg: ${tplayer.Name} attempted to dismount $obj's seat $seat_num, but was not allowed")
}
}
@@ -2866,7 +2935,7 @@ class WorldSessionActor extends Actor
lastTerminalOrderFulfillment = true
case Terminal.InfantryLoadout(exosuit, subtype, holsters, inventory) =>
- log.info(s"$tplayer wants to change equipment loadout to their option #${msg.unk1 + 1}")
+ log.info(s"${tplayer.Name} wants to change equipment loadout to their option #${msg.unk1 + 1}")
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Loadout, true))
//sanitize exo-suit for change
val originalSuit = player.ExoSuit
@@ -2906,7 +2975,7 @@ class WorldSessionActor extends Actor
}
}
else {
- log.warn(s"$tplayer no longer has permission to wear the exo-suit type $exosuit; will wear $fallbackSuit instead")
+ log.warn(s"${tplayer.Name} no longer has permission to wear the exo-suit type $exosuit; will wear $fallbackSuit instead")
(fallbackSuit, fallbackSubtype)
}
//update suit interally (holsters must be empty before this point)
@@ -3014,7 +3083,7 @@ class WorldSessionActor extends Actor
lastTerminalOrderFulfillment = true
case Terminal.VehicleLoadout(definition, weapons, inventory) =>
- log.info(s"$tplayer wants to change their vehicle equipment loadout to their option #${msg.unk1 + 1}")
+ log.info(s"${tplayer.Name} wants to change their vehicle equipment loadout to their option #${msg.unk1 + 1}")
FindLocalVehicle match {
case Some(vehicle) =>
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Loadout, true))
@@ -3112,7 +3181,7 @@ class WorldSessionActor extends Actor
case Terminal.LearnImplant(implant) =>
val terminal_guid = msg.terminal_guid
val implant_type = implant.Type
- val message = s"Implants: $tplayer wants to learn $implant_type"
+ val message = s"Implants: ${tplayer.Name} wants to learn $implant_type"
val (interface, slotNumber) = tplayer.VehicleSeated match {
case Some(mech_guid) =>
(
@@ -3166,13 +3235,13 @@ class WorldSessionActor extends Actor
}
if(interface.contains(terminal_guid.guid) && slotNumber.isDefined) {
val slot = slotNumber.get
- log.info(s"$tplayer is selling $implant_type - take from slot $slot")
+ log.info(s"${tplayer.Name} is selling $implant_type - take from slot $slot")
player.Actor ! Player.UninitializeImplant(slot)
sendResponse(AvatarImplantMessage(tplayer.GUID, ImplantAction.Remove, slot, 0))
sendResponse(ItemTransactionResultMessage(terminal_guid, TransactionType.Sell, true))
}
else {
- val message = s"$tplayer can not sell $implant_type"
+ val message = s"${tplayer.Name} can not sell $implant_type"
if(interface.isEmpty) {
log.warn(s"$message - not interacting with a terminal")
}
@@ -3230,7 +3299,7 @@ class WorldSessionActor extends Actor
}
case None =>
- log.error(s"$tplayer wanted to spawn a vehicle, but there was no spawn pad associated with terminal ${msg.terminal_guid} to accept it")
+ log.error(s"${tplayer.Name} wanted to spawn a vehicle, but there was no spawn pad associated with terminal ${msg.terminal_guid} to accept it")
}
lastTerminalOrderFulfillment = true
@@ -3764,6 +3833,7 @@ class WorldSessionActor extends Actor
//player died during setup; probably a relog
player.Actor ! Player.Die()
}
+ upstreamMessageCount = 0
}
/**
@@ -3772,7 +3842,7 @@ class WorldSessionActor extends Actor
* @param tplayer the target player
*/
def SetCurrentAvatarNormally(tplayer : Player) : Unit = {
- self ! SetCurrentAvatar(tplayer)
+ HandleSetCurrentAvatar(tplayer)
}
/**
@@ -3787,6 +3857,7 @@ class WorldSessionActor extends Actor
*/
def SetCurrentAvatarUponDeployment(tplayer : Player) : Unit = {
beginZoningSetCurrentAvatarFunc = SetCurrentAvatarNormally
+ upstreamMessageCount = 0
continent.Actor ! Zone.Lattice.RequestSpawnPoint(continent.Number, tplayer, 0)
}
@@ -4061,6 +4132,7 @@ class WorldSessionActor extends Actor
case msg@BeginZoningMessage() =>
log.info("Reticulating splines ...")
+ zoneLoaded = None
val continentId = continent.Id
traveler.zone = continentId
val faction = player.Faction
@@ -4358,7 +4430,8 @@ class WorldSessionActor extends Actor
}
}
continent.VehicleEvents ! VehicleServiceMessage(continent.Id, VehicleAction.UpdateAmsSpawnPoint(continent))
- beginZoningSetCurrentAvatarFunc(player)
+ upstreamMessageCount = 0
+ zoneLoaded = Some(true)
case msg @ PlayerStateMessageUpstream(avatar_guid, pos, vel, yaw, pitch, yaw_upper, seq_time, unk3, is_crouching, is_jumping, jump_thrust, is_cloaking, unk5, unk6) =>
if (player.death_by == -1) {
@@ -4366,14 +4439,14 @@ class WorldSessionActor extends Actor
Thread.sleep(300)
sendResponse(DropSession(sessionId, "kick by GM"))
}
- playerStateMessageUpstreamCount += 1
+ turnCounter(avatar_guid)
val isMoving = WorldEntity.isMoving(vel)
val isMovingPlus = isMoving || is_jumping || jump_thrust
if(isMovingPlus) {
CancelZoningProcessWithDescriptiveReason("cancel_motion")
}
- if(deadState == DeadState.Alive && playerStateMessageUpstreamCount % 2 == 0) { // Regen stamina roughly every 500ms
+ if(deadState == DeadState.Alive && upstreamMessageCount % 2 == 0) { // Regen stamina roughly every 500ms
if(player.skipStaminaRegenForTurns > 0) {
//do not renew stamina for a while
player.skipStaminaRegenForTurns -= 1
@@ -4432,7 +4505,15 @@ class WorldSessionActor extends Actor
case msg@ChildObjectStateMessage(object_guid, pitch, yaw) =>
//the majority of the following check retrieves information to determine if we are in control of the child
FindContainedWeapon match {
- case (Some(_), Some(tool)) =>
+ case (Some(o), Some(tool)) =>
+ (o match {
+ case mount : Mountable => mount.PassengerInSeat(player)
+ case _ => None
+ }) match {
+ case None | Some(0) => ;
+ case Some(_) =>
+ turnCounter(player.GUID)
+ }
if(tool.GUID == object_guid) {
//TODO set tool orientation?
player.Orientation = Vector3(0f, pitch, yaw)
@@ -4445,7 +4526,7 @@ class WorldSessionActor extends Actor
log.warn(s"ChildObjectState: ${player.Name} can not find any controllable agent, let alone #${object_guid.guid}")
case (None, _) => ;
//TODO status condition of "playing getting out of vehicle to allow for late packets without warning
- //log.warn(s"ChildObjectState: player $player not related to anything with a controllable agent")
+ //log.warn(s"ChildObjectState: player ${player.Name} not related to anything with a controllable agent")
}
if (player.death_by == -1) {
sendResponse(ChatMsg(ChatMessageType.UNK_71, true, "", "Your account has been logged out by a Customer Service Representative.", None))
@@ -4457,8 +4538,9 @@ class WorldSessionActor extends Actor
if(deadState == DeadState.Alive) {
GetVehicleAndSeat() match {
case (Some(obj), Some(0)) =>
- val seat = obj.Seats(0)
//we're driving the vehicle
+ turnCounter(player.GUID)
+ val seat = obj.Seats(0)
player.Position = pos //convenient
if(seat.ControlledWeapon.isEmpty) {
player.Orientation = Vector3.z(ang.z) //convenient
@@ -4503,7 +4585,7 @@ class WorldSessionActor extends Actor
}
case msg@VehicleSubStateMessage(vehicle_guid, player_guid, vehicle_pos, vehicle_ang, vel, unk1, unk2) =>
- //log.info(s"VehicleSubState: $vehicle_guid, $player_guid, $vehicle_pos, $vehicle_ang, $vel, $unk1, $unk2")
+ //log.info(s"VehicleSubState: $vehicle_guid, ${player.Name}_guid, $vehicle_pos, $vehicle_ang, $vel, $unk1, $unk2")
case msg@ProjectileStateMessage(projectile_guid, shot_pos, shot_vel, shot_orient, seq, end, target_guid) =>
//log.trace(s"ProjectileState: $msg")
@@ -5207,13 +5289,13 @@ class WorldSessionActor extends Actor
continent.Ground ! Zone.Ground.DropItem(item, player.Position, player.Orientation)
}
case None =>
- log.warn(s"DropItem: $player wanted to drop a $anItem, but it wasn't at hand")
+ log.warn(s"DropItem: ${player.Name} wanted to drop a $anItem, but it wasn't at hand")
}
case Some(obj) => //TODO LLU
- log.warn(s"DropItem: $player wanted to drop a $obj, but that isn't possible")
+ log.warn(s"DropItem: ${player.Name} wanted to drop a $obj, but that isn't possible")
case None =>
sendResponse(ObjectDeleteMessage(item_guid, 0)) //this is fine; item doesn't exist to the server anyway
- log.warn(s"DropItem: $player wanted to drop an item ($item_guid), but it was nowhere to be found")
+ log.warn(s"DropItem: ${player.Name} wanted to drop an item ($item_guid), but it was nowhere to be found")
}
case msg@PickupItemMessage(item_guid, player_guid, unk1, unk2) =>
@@ -5227,7 +5309,7 @@ class WorldSessionActor extends Actor
sendResponse(ActionResultMessage.Fail(16)) //error code?
}
case _ =>
- log.warn(s"PickupItem: $player requested an item that doesn't exist in this zone; assume client-side garbage data")
+ log.warn(s"PickupItem: ${player.Name} requested an item that doesn't exist in this zone; assume client-side garbage data")
sendResponse(ObjectDeleteMessage(item_guid, 0))
}
@@ -5288,7 +5370,7 @@ class WorldSessionActor extends Actor
val before = player.DrawnSlot
if(before != held_holsters) {
if(player.ExoSuit == ExoSuitType.MAX && held_holsters != 0) {
- log.info(s"ObjectHeld: $player is denied changing hands to $held_holsters as a MAX")
+ log.info(s"ObjectHeld: ${player.Name} is denied changing hands to $held_holsters as a MAX")
player.DrawnSlot = 0
sendResponse(ObjectHeldMessage(avatar_guid, 0, true))
}
@@ -5603,7 +5685,7 @@ class WorldSessionActor extends Actor
CancelZoningProcessWithDescriptiveReason("cancel_use")
if(obj.isBackpack) {
if(equipment.isEmpty) {
- log.info(s"UseItem: $player looting the corpse of $obj")
+ log.info(s"UseItem: ${player.Name} looting the corpse of $obj")
sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType))
accessedContainer = Some(obj)
}
@@ -5716,7 +5798,7 @@ class WorldSessionActor extends Actor
CancelZoningProcessWithDescriptiveReason("cancel_use")
locker.Actor ! CommonMessages.Use(player, Some(item))
case None if locker.Faction == player.Faction || !locker.HackedBy.isEmpty =>
- log.trace(s"UseItem: $player accessing a locker")
+ log.trace(s"UseItem: ${player.Name} accessing a locker")
CancelZoningProcessWithDescriptiveReason("cancel_use")
val container = player.Locker
accessedContainer = Some(container)
@@ -6208,7 +6290,7 @@ class WorldSessionActor extends Actor
}
}
else {
- log.warn(s"WeaponFireMessage: $player's ${tool.Definition.Name} projectile is too far from owner position at time of discharge ($distanceToOwner > $acceptableDistanceToOwner); suspect")
+ log.warn(s"WeaponFireMessage: ${player.Name}'s ${tool.Definition.Name} projectile is too far from owner position at time of discharge ($distanceToOwner > $acceptableDistanceToOwner); suspect")
}
}
case _ => ;
@@ -6370,7 +6452,7 @@ class WorldSessionActor extends Actor
case out @ Some(_ : Mountable) =>
out
case _ =>
- dismountWarning(s"DismountVehicleMsg: player $player_guid not considered seated in a mountable entity")
+ dismountWarning(s"DismountVehicleMsg: player ${player.Name}_guid not considered seated in a mountable entity")
None
}) match {
case Some(obj : Mountable) =>
@@ -6395,7 +6477,7 @@ class WorldSessionActor extends Actor
}
case None =>
- dismountWarning(s"DismountVehicleMsg: can not find where player $player_guid is seated in mountable ${player.VehicleSeated}")
+ dismountWarning(s"DismountVehicleMsg: can not find where player ${player.Name}_guid is seated in mountable ${player.VehicleSeated}")
}
case _ =>
dismountWarning(s"DismountVehicleMsg: can not find mountable entity ${player.VehicleSeated}")
@@ -6418,17 +6500,17 @@ class WorldSessionActor extends Actor
case Some(seat_num : Int) =>
obj.Actor ! Mountable.TryDismount(tplayer, seat_num)
case None =>
- dismountWarning(s"DismountVehicleMsg: can not find where other player $player_guid is seated in mountable $obj_guid")
+ dismountWarning(s"DismountVehicleMsg: can not find where other player ${player.Name}_guid is seated in mountable $obj_guid")
}
case (None, _) => ;
- log.warn(s"DismountVehicleMsg: $player can not find his vehicle")
+ log.warn(s"DismountVehicleMsg: ${player.Name} can not find his vehicle")
case (_, None) => ;
- log.warn(s"DismountVehicleMsg: player $player_guid could not be found to kick")
+ log.warn(s"DismountVehicleMsg: player ${player.Name}_guid could not be found to kick")
case _ =>
log.warn(s"DismountVehicleMsg: object is either not a Mountable or not a Player")
}
case None =>
- log.warn(s"DismountVehicleMsg: $player does not own a vehicle")
+ log.warn(s"DismountVehicleMsg: ${player.Name} does not own a vehicle")
}
}
@@ -6445,7 +6527,7 @@ class WorldSessionActor extends Actor
}
}
else {
- log.warn(s"DeployRequest: $player does not own the deploying $vehicle_guid object")
+ log.warn(s"DeployRequest: ${player.Name} does not own the deploying $vehicle_guid object")
}
case msg @ AvatarGrenadeStateMessage(player_guid, state) =>
@@ -6523,7 +6605,7 @@ class WorldSessionActor extends Actor
}
}
else {
- log.warn(s"Vehicle attributes: $player does not own vehicle ${vehicle.GUID} and can not change it")
+ log.warn(s"Vehicle attributes: ${player.Name} does not own vehicle ${vehicle.GUID} and can not change it")
}
case _ =>
log.warn(s"echo unknown attributes behavior")
@@ -9320,7 +9402,7 @@ class WorldSessionActor extends Actor
val player_guid : PlanetSideGUID = tplayer.GUID
val obj_guid : PlanetSideGUID = obj.GUID
PlayerActionsToCancel()
- log.info(s"MountVehicleMsg: $player_guid mounts $obj @ $seatNum")
+ log.info(s"MountVehicleMsg: ${player.Name}_guid mounts $obj @ $seatNum")
sendResponse(ObjectAttachMessage(obj_guid, player_guid, seatNum))
continent.VehicleEvents ! VehicleServiceMessage(continent.Id, VehicleAction.MountVehicle(player_guid, obj_guid, seatNum))
}
@@ -9353,7 +9435,7 @@ class WorldSessionActor extends Actor
def HandleDealingDamage(target : PlanetSideGameObject with Vitality, data : ResolvedProjectile) : Unit = {
val func = data.damage_model.Calculate(data)
target match {
- case obj : Player if obj.CanDamage && obj.Actor != ActorRef.noSender =>
+ case obj : Player if obj.CanDamage && obj.Actor != Default.Actor =>
if(obj.spectator) {
player.death_by = -1 // little thing for auto kick
}
@@ -10006,7 +10088,7 @@ class WorldSessionActor extends Actor
* @return a tuple composed of an `ActorRef` destination and a message to send to that destination
*/
def LoadZoneAsPlayer(tplayer : Player, zone_id : String) : (ActorRef, Any) = {
- if(zone_id == continent.Id) {
+ if(!zoneReload && zone_id == continent.Id) {
if(player.isBackpack) { //important! test the actor-wide player ref, not the parameter
//respawning from unregistered player
(taskResolver, RegisterAvatar(tplayer))
@@ -10115,7 +10197,7 @@ class WorldSessionActor extends Actor
continent.VehicleEvents ! VehicleServiceMessage(name, VehicleAction.TransferPassengerChannel(pguid, s"${cargo.Actor}", toChannel, cargo, topLevel))
}
//
- if(zone_id == continent.Id) {
+ if(!zoneReload && zone_id == continent.Id) {
if(vehicle.Definition == GlobalDefinitions.droppod) {
//instant action droppod in the same zone
(taskResolver, RegisterDroppod(vehicle, player))
@@ -10175,7 +10257,7 @@ class WorldSessionActor extends Actor
**/
def LoadZoneInVehicleAsPassenger(vehicle : Vehicle, zone_id : String) : (ActorRef, Any) = {
log.info(s"LoadZoneInVehicleAsPassenger: ${player.Name} is the passenger of a ${vehicle.Definition.Name}")
- if(zone_id == continent.Id) {
+ if(!zoneReload && zone_id == continent.Id) {
//transferring a vehicle between spawn points (warp gates) in the same zone
(self, PlayerLoaded(player))
}
@@ -10226,9 +10308,11 @@ class WorldSessionActor extends Actor
* It also sets up actions for the new zone loading process.
*/
def LoadZoneCommonTransferActivity() : Unit = {
+ zoneLoaded = None
+ zoneReload = false
if(player.VehicleOwned.nonEmpty && player.VehicleSeated != player.VehicleOwned) {
continent.GUID(player.VehicleOwned) match {
- case Some(vehicle : Vehicle) if vehicle.Actor != ActorRef.noSender =>
+ case Some(vehicle : Vehicle) if vehicle.Actor != Default.Actor =>
vehicle.Actor ! Vehicle.Ownership(None)
case _ => ;
}
@@ -11427,6 +11511,35 @@ class WorldSessionActor extends Actor
}
}
+ /**
+ * The upstream counter accumulates when the server receives sp[ecific messages from the client.
+ * It counts upwards until it reach maximum value, and then starts over.
+ * When it starts over, which should take an exceptionally long time to achieve,
+ * it starts counting at one rather than zero.
+ * @param p the player's globally unique identifier number
+ */
+ def NormalTurnCounter(p : PlanetSideGUID) : Unit = {
+ upstreamMessageCount = 1 + upstreamMessageCount % Int.MaxValue
+ }
+
+ /**
+ * During the interim period between the avatar being in one place/zone
+ * and completing the process of transitioning to another place/zone,
+ * the upstream message counter is zero'd
+ * awaiting new activity from the client.
+ * Until new upstream messages that pass some tests against their data start being reported,
+ * the counter does not accumulate properly.
+ * @param guid the player's globally unique identifier number
+ */
+ def TurnCounterDuringInterim(guid : PlanetSideGUID) : Unit = {
+ if(player.GUID == guid && player.Zone == continent) {
+ turnCounter = NormalTurnCounter
+ }
+ else {
+ upstreamMessageCount = 0
+ }
+ }
+
def failWithError(error : String) = {
log.error(error)
sendResponse(ConnectionClose())
@@ -11553,7 +11666,7 @@ object WorldSessionActor {
private final case class PlayerFailedToLoad(tplayer : Player)
private final case class CreateCharacter(name : String, head : Int, voice : CharacterVoice.Value, gender : CharacterGender.Value, empire : PlanetSideEmpire.Value)
private final case class ListAccountCharacters()
- private final case class SetCurrentAvatar(tplayer : Player)
+ private final case class SetCurrentAvatar(tplayer : Player, max_attempts : Int, attempt : Int = 0)
private final case class ZoningReset()
final val ftes = (