Interim 2 (#477)

* changed DefaultCancellable.obj with Default.Cancellable and deleted the former (as unnecessary)

* changed ActorRef.noSender with Default.Actor for PlanetSideServerObject entities

* Actor.noSender -> ActorRef.noSender, for consistency

* player name in log messages; zoneLoaded and zoneReload flags; upstream message count

* Default object tests; expanded the set current avatar loop

* fallback cases for unsuccessful zone/avatar load process

* completing the trials of the god Travis

* forgot to reactivate kamon
This commit is contained in:
Fate-JH 2020-05-30 12:28:10 -04:00 committed by GitHub
parent 765816a4d2
commit d6397d54a1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
64 changed files with 523 additions and 302 deletions

View file

@ -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
}

View file

@ -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
}

View file

@ -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

View file

@ -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)
}

View file

@ -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.

View file

@ -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)))
}

View file

@ -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))
}
}

View file

@ -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
}
}

View file

@ -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

View file

@ -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

View file

@ -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.<br>

View file

@ -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;

View file

@ -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 {

View file

@ -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

View file

@ -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)
}

View file

@ -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 = {

View file

@ -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))
}
}

View file

@ -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))
}
}

View file

@ -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()
}

View file

@ -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

View file

@ -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))
}
}

View file

@ -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 _ => ;

View file

@ -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
}

View file

@ -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

View file

@ -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
}
}

View file

@ -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
}
}

View file

@ -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

View file

@ -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`.<br>
@ -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
}

View file

@ -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

View file

@ -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
}
}
}

View file

@ -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")
}

View file

@ -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 = {

View file

@ -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")

View file

@ -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 _ => ;
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 = {

View file

@ -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 = {

View file

@ -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()

View file

@ -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)
}
}
}

View file

@ -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
}

View file

@ -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)
}
}
}

View file

@ -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)
}
}

View file

@ -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)
}
}
}

View file

@ -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)
}
}
}

View file

@ -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)
}
}
}

View file

@ -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
}
}
}

View file

@ -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

View file

@ -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)
}
}
}

View file

@ -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))
}
}

View file

@ -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
}
}

View file

@ -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]

View file

@ -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
}
}
}

View file

@ -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)
}
}
}

View file

@ -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))

View file

@ -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))))

View file

@ -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 = ""

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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) =>

View file

@ -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) =>

View file

@ -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<br>
* Checks for server acknowledgement of the following messages:<br>
* `PlayerStateMessageUpstream`<br>
* `VehicleStateMessage` (driver seat only)<br>
* `ChildObjectStateMessage` (any seat but driver)<br>
* 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 = (