mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-15 16:34:39 +00:00
Router and Telepad (#232)
* added short and detailed codecs for Telepad, and converter for switching between Telepad and packets; modified Utility to construct a formal TeleportPadTerminal that associates the Telepad with a Router; can now pull telepad Equipment from Router terminal utilities * this code supports operation of the deployable-side telepad * basic teleportation between the Router and the remote telepad is functional; an ever-present internal telepad utility was added to the Router to facilitate this teleportation * breakdown of Router teleportation code for the purposes of client synchronization; supports Router being set up first or Telepad being set up first, either order; background timer for eventual activation of Router * refactored the router telepad system to remove unecessary function diversions; telepads now are properly linked where appropriate and links are properly broken in appropriate situations; message passing has been simplified * fixed inventory size of the telepad; transferred router telepad activation systems from VehicleService to LocalService, and from the Ruoter to the TelepadDeployable; cleaned up code that handled the TelepadDeployable the Router relationship in WSA * tests, mostly; no-router conditions for certain telepad-related converters * adjusted (made constant) quantities for owned telepads * resolved issue with router and telepad crashes; properly handles deployment states of AMS and Router upon zone entry; changed ownership/decon requirements to ownerless only
This commit is contained in:
parent
3270ec87b8
commit
9340777c00
46 changed files with 2057 additions and 251 deletions
|
|
@ -22,7 +22,8 @@ object Deployables {
|
||||||
DeployedItem.portable_manned_turret_nc -> { ()=> new TurretDeployable(GlobalDefinitions.portable_manned_turret_nc) },
|
DeployedItem.portable_manned_turret_nc -> { ()=> new TurretDeployable(GlobalDefinitions.portable_manned_turret_nc) },
|
||||||
DeployedItem.portable_manned_turret_tr -> { ()=> new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) },
|
DeployedItem.portable_manned_turret_tr -> { ()=> new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) },
|
||||||
DeployedItem.portable_manned_turret_vs -> { ()=> new TurretDeployable(GlobalDefinitions.portable_manned_turret_vs) },
|
DeployedItem.portable_manned_turret_vs -> { ()=> new TurretDeployable(GlobalDefinitions.portable_manned_turret_vs) },
|
||||||
DeployedItem.deployable_shield_generator -> { ()=> new ShieldGeneratorDeployable(GlobalDefinitions.deployable_shield_generator) }
|
DeployedItem.deployable_shield_generator -> { ()=> new ShieldGeneratorDeployable(GlobalDefinitions.deployable_shield_generator) },
|
||||||
|
DeployedItem.router_telepad_deployable -> { () => new TelepadDeployable(GlobalDefinitions.router_telepad_deployable) }
|
||||||
).withDefaultValue( { ()=> new ExplosiveDeployable(GlobalDefinitions.boomer) } )
|
).withDefaultValue( { ()=> new ExplosiveDeployable(GlobalDefinitions.boomer) } )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -642,6 +642,8 @@ object GlobalDefinitions {
|
||||||
|
|
||||||
val advanced_ace = ConstructionItemDefinition(CItem.advanced_ace)
|
val advanced_ace = ConstructionItemDefinition(CItem.advanced_ace)
|
||||||
|
|
||||||
|
val router_telepad = ConstructionItemDefinition(CItem.router_telepad)
|
||||||
|
|
||||||
val fury_weapon_systema = ToolDefinition(ObjectClass.fury_weapon_systema)
|
val fury_weapon_systema = ToolDefinition(ObjectClass.fury_weapon_systema)
|
||||||
|
|
||||||
val quadassault_weapon_system = ToolDefinition(ObjectClass.quadassault_weapon_system)
|
val quadassault_weapon_system = ToolDefinition(ObjectClass.quadassault_weapon_system)
|
||||||
|
|
@ -859,6 +861,10 @@ object GlobalDefinitions {
|
||||||
val portable_manned_turret_vs = TurretDeployableDefinition(DeployedItem.portable_manned_turret_vs)
|
val portable_manned_turret_vs = TurretDeployableDefinition(DeployedItem.portable_manned_turret_vs)
|
||||||
|
|
||||||
val deployable_shield_generator = new ShieldGeneratorDefinition
|
val deployable_shield_generator = new ShieldGeneratorDefinition
|
||||||
|
|
||||||
|
val router_telepad_deployable = DeployableDefinition(DeployedItem.router_telepad_deployable)
|
||||||
|
|
||||||
|
val internal_router_telepad_deployable = DeployableDefinition(DeployedItem.router_telepad_deployable)
|
||||||
init_deployables()
|
init_deployables()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -894,6 +900,8 @@ object GlobalDefinitions {
|
||||||
|
|
||||||
val respawn_tube_tower = new SpawnTubeDefinition(733)
|
val respawn_tube_tower = new SpawnTubeDefinition(733)
|
||||||
|
|
||||||
|
val teleportpad_terminal = new TeleportPadTerminalDefinition
|
||||||
|
|
||||||
val adv_med_terminal = new MedicalTerminalDefinition(38)
|
val adv_med_terminal = new MedicalTerminalDefinition(38)
|
||||||
|
|
||||||
val crystals_health_a = new MedicalTerminalDefinition(225)
|
val crystals_health_a = new MedicalTerminalDefinition(225)
|
||||||
|
|
@ -4059,6 +4067,13 @@ object GlobalDefinitions {
|
||||||
advanced_ace.Modes(2).Item(DeployedItem.deployable_shield_generator -> Set(CertificationType.AssaultEngineering))
|
advanced_ace.Modes(2).Item(DeployedItem.deployable_shield_generator -> Set(CertificationType.AssaultEngineering))
|
||||||
advanced_ace.Tile = InventoryTile.Tile93
|
advanced_ace.Tile = InventoryTile.Tile93
|
||||||
|
|
||||||
|
router_telepad.Name = "router_telepad"
|
||||||
|
router_telepad.Size = EquipmentSize.Pistol
|
||||||
|
router_telepad.Modes += new ConstructionFireMode
|
||||||
|
router_telepad.Modes.head.Item(DeployedItem.router_telepad_deployable -> Set(CertificationType.GroundSupport))
|
||||||
|
router_telepad.Tile = InventoryTile.Tile33
|
||||||
|
router_telepad.Packet = new TelepadConverter
|
||||||
|
|
||||||
fury_weapon_systema.Name = "fury_weapon_systema"
|
fury_weapon_systema.Name = "fury_weapon_systema"
|
||||||
fury_weapon_systema.Size = EquipmentSize.VehicleWeapon
|
fury_weapon_systema.Size = EquipmentSize.VehicleWeapon
|
||||||
fury_weapon_systema.AmmoTypes += hellfire_ammo
|
fury_weapon_systema.AmmoTypes += hellfire_ammo
|
||||||
|
|
@ -5121,6 +5136,8 @@ object GlobalDefinitions {
|
||||||
router.MaxShields = 800 + 1
|
router.MaxShields = 800 + 1
|
||||||
router.Seats += 0 -> new SeatDefinition()
|
router.Seats += 0 -> new SeatDefinition()
|
||||||
router.MountPoints += 1 -> 0
|
router.MountPoints += 1 -> 0
|
||||||
|
router.Utilities += 1 -> UtilityType.teleportpad_terminal
|
||||||
|
router.Utilities += 2 -> UtilityType.internal_router_telepad_deployable
|
||||||
router.TrunkSize = InventoryTile.Tile1511
|
router.TrunkSize = InventoryTile.Tile1511
|
||||||
router.TrunkOffset = 30
|
router.TrunkOffset = 30
|
||||||
router.Deployment = true
|
router.Deployment = true
|
||||||
|
|
@ -5515,5 +5532,16 @@ object GlobalDefinitions {
|
||||||
deployable_shield_generator.MaxHealth = 1700
|
deployable_shield_generator.MaxHealth = 1700
|
||||||
deployable_shield_generator.DeployTime = Duration.create(6000, "ms")
|
deployable_shield_generator.DeployTime = Duration.create(6000, "ms")
|
||||||
deployable_shield_generator.Model = StandardResolutions.ComplexDeployables
|
deployable_shield_generator.Model = StandardResolutions.ComplexDeployables
|
||||||
|
|
||||||
|
router_telepad_deployable.Name = "router_telepad_deployable"
|
||||||
|
router_telepad_deployable.MaxHealth = 100
|
||||||
|
router_telepad_deployable.DeployTime = Duration.create(1, "ms")
|
||||||
|
router_telepad_deployable.Packet = new TelepadDeployableConverter
|
||||||
|
router_telepad_deployable.Model = StandardResolutions.SimpleDeployables
|
||||||
|
|
||||||
|
internal_router_telepad_deployable.Name = "router_telepad_deployable"
|
||||||
|
internal_router_telepad_deployable.MaxHealth = 1
|
||||||
|
internal_router_telepad_deployable.DeployTime = Duration.create(1, "ms")
|
||||||
|
internal_router_telepad_deployable.Packet = new InternalTelepadDeployableConverter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
14
common/src/main/scala/net/psforever/objects/Telepad.scala
Normal file
14
common/src/main/scala/net/psforever/objects/Telepad.scala
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.objects
|
||||||
|
|
||||||
|
import net.psforever.objects.ce.TelepadLike
|
||||||
|
import net.psforever.objects.definition.ConstructionItemDefinition
|
||||||
|
|
||||||
|
class Telepad(private val cdef : ConstructionItemDefinition) extends ConstructionItem(cdef)
|
||||||
|
with TelepadLike
|
||||||
|
|
||||||
|
object Telepad {
|
||||||
|
def apply(cdef : ConstructionItemDefinition) : Telepad = {
|
||||||
|
new Telepad(cdef)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.objects
|
||||||
|
|
||||||
|
import net.psforever.objects.ce.{SimpleDeployable, TelepadLike}
|
||||||
|
import net.psforever.objects.definition.DeployableDefinition
|
||||||
|
|
||||||
|
class TelepadDeployable(ddef : DeployableDefinition) extends SimpleDeployable(ddef)
|
||||||
|
with TelepadLike
|
||||||
|
|
@ -378,7 +378,7 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends PlanetSideServ
|
||||||
def Utilities : Map[Int, Utility] = utilities
|
def Utilities : Map[Int, Utility] = utilities
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a referenece ot a certain `Utility` attached to this `Vehicle`.
|
* Get a reference to a certain `Utility` attached to this `Vehicle`.
|
||||||
* @param utilNumber the attachment number of the `Utility`
|
* @param utilNumber the attachment number of the `Utility`
|
||||||
* @return the `Utility` or `None` (if invalid)
|
* @return the `Utility` or `None` (if invalid)
|
||||||
*/
|
*/
|
||||||
|
|
@ -396,6 +396,15 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends PlanetSideServ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def Utility(utilType : UtilityType.Value) : Option[PlanetSideServerObject] = {
|
||||||
|
utilities.values.find(_.UtilType == utilType) match {
|
||||||
|
case Some(util) =>
|
||||||
|
Some(util())
|
||||||
|
case None =>
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override def DeployTime = Definition.DeployTime
|
override def DeployTime = Definition.DeployTime
|
||||||
|
|
||||||
override def UndeployTime = Definition.UndeployTime
|
override def UndeployTime = Definition.UndeployTime
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,13 @@ class DeployableToolbox {
|
||||||
* keys: categories, values: quantity storage object
|
* keys: categories, values: quantity storage object
|
||||||
*/
|
*/
|
||||||
private val categoryCounts = DeployableCategory.values.toSeq.map(value => { value -> new DeployableToolbox.Bin }).toMap
|
private val categoryCounts = DeployableCategory.values.toSeq.map(value => { value -> new DeployableToolbox.Bin }).toMap
|
||||||
//)
|
categoryCounts(DeployableCategory.Telepads).Max = 1024
|
||||||
/**
|
/**
|
||||||
* a map of bins for keeping track of the quantities of individual deployables
|
* a map of bins for keeping track of the quantities of individual deployables
|
||||||
* keys: deployable types, values: quantity storage object
|
* keys: deployable types, values: quantity storage object
|
||||||
*/
|
*/
|
||||||
private val deployableCounts = DeployedItem.values.toSeq.map(value => { value -> new DeployableToolbox.Bin }).toMap
|
private val deployableCounts = DeployedItem.values.toSeq.map(value => { value -> new DeployableToolbox.Bin }).toMap
|
||||||
|
deployableCounts(DeployedItem.router_telepad_deployable).Max = 1024
|
||||||
/**
|
/**
|
||||||
* a map of tracked/owned individual deployables
|
* a map of tracked/owned individual deployables
|
||||||
* keys: categories, values: deployable objects
|
* keys: categories, values: deployable objects
|
||||||
|
|
@ -523,8 +524,8 @@ object DeployableToolbox {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(certifications.contains(CertificationType.GroundSupport)) {
|
if(certifications.contains(CertificationType.GroundSupport)) {
|
||||||
counts(DeployedItem.router_telepad_deployable).Max = 1
|
counts(DeployedItem.router_telepad_deployable).Max = 1024
|
||||||
categories(DeployableCategory.Telepads).Max = 1
|
categories(DeployableCategory.Telepads).Max = 1024
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -589,9 +590,9 @@ object DeployableToolbox {
|
||||||
AddToDeployableQuantities(counts, categories, FortificationEngineering, certificationSet ++ Set(FortificationEngineering))
|
AddToDeployableQuantities(counts, categories, FortificationEngineering, certificationSet ++ Set(FortificationEngineering))
|
||||||
}
|
}
|
||||||
|
|
||||||
case GroundSupport =>
|
// case GroundSupport =>
|
||||||
counts(DeployedItem.router_telepad_deployable).Max = 1024
|
// counts(DeployedItem.router_telepad_deployable).Max = 1024
|
||||||
categories(DeployableCategory.Telepads).Max = 1024
|
// categories(DeployableCategory.Telepads).Max = 1024
|
||||||
|
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
@ -657,9 +658,9 @@ object DeployableToolbox {
|
||||||
RemoveFromDeployablesQuantities(counts, categories, FortificationEngineering, certificationSet)
|
RemoveFromDeployablesQuantities(counts, categories, FortificationEngineering, certificationSet)
|
||||||
}
|
}
|
||||||
|
|
||||||
case GroundSupport =>
|
// case GroundSupport =>
|
||||||
counts(DeployedItem.router_telepad_deployable).Max = 0
|
// counts(DeployedItem.router_telepad_deployable).Max = 0
|
||||||
categories(DeployableCategory.Telepads).Max = 0
|
// categories(DeployableCategory.Telepads).Max = 0
|
||||||
|
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,8 @@ object Deployable {
|
||||||
DeployedItem.portable_manned_turret_tr.id -> DeployableIcon.FieldTurret,
|
DeployedItem.portable_manned_turret_tr.id -> DeployableIcon.FieldTurret,
|
||||||
DeployedItem.portable_manned_turret_nc.id -> DeployableIcon.FieldTurret,
|
DeployedItem.portable_manned_turret_nc.id -> DeployableIcon.FieldTurret,
|
||||||
DeployedItem.portable_manned_turret_vs.id -> DeployableIcon.FieldTurret,
|
DeployedItem.portable_manned_turret_vs.id -> DeployableIcon.FieldTurret,
|
||||||
DeployedItem.deployable_shield_generator.id -> DeployableIcon.AegisShieldGenerator
|
DeployedItem.deployable_shield_generator.id -> DeployableIcon.AegisShieldGenerator,
|
||||||
|
DeployedItem.router_telepad_deployable.id -> DeployableIcon.RouterTelepad
|
||||||
).withDefaultValue(DeployableIcon.Boomer)
|
).withDefaultValue(DeployableIcon.Boomer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.objects.ce
|
||||||
|
|
||||||
|
import akka.actor.ActorContext
|
||||||
|
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
|
||||||
|
import net.psforever.packet.game.PlanetSideGUID
|
||||||
|
|
||||||
|
trait TelepadLike {
|
||||||
|
private var router : Option[PlanetSideGUID] = None
|
||||||
|
private var activated : Boolean = false
|
||||||
|
|
||||||
|
def Router : Option[PlanetSideGUID] = router
|
||||||
|
|
||||||
|
def Router_=(rguid : PlanetSideGUID) : Option[PlanetSideGUID] = Router_=(Some(rguid))
|
||||||
|
|
||||||
|
def Router_=(rguid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = {
|
||||||
|
router match {
|
||||||
|
case None =>
|
||||||
|
router = rguid
|
||||||
|
case Some(_) =>
|
||||||
|
if(rguid.isEmpty || rguid.contains(PlanetSideGUID(0))) {
|
||||||
|
router = None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Router
|
||||||
|
}
|
||||||
|
|
||||||
|
def Active : Boolean = activated
|
||||||
|
|
||||||
|
def Active_=(state : Boolean) : Boolean = {
|
||||||
|
activated = state
|
||||||
|
Active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object TelepadLike {
|
||||||
|
final case class Activate(obj : PlanetSideGameObject with TelepadLike)
|
||||||
|
|
||||||
|
final case class Deactivate(obj : PlanetSideGameObject with TelepadLike)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assemble some logic for a provided object.
|
||||||
|
* @param obj an `Amenity` object;
|
||||||
|
* anticipating a `Terminal` object using this same definition
|
||||||
|
* @param context hook to the local `Actor` system
|
||||||
|
*/
|
||||||
|
def Setup(obj : Amenity, context : ActorContext) : Unit = {
|
||||||
|
obj.asInstanceOf[TelepadLike].Router = obj.Owner.GUID
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An analysis of the active system of teleportation utilized by Router vehicles.
|
||||||
|
* Information about the two endpoints - an internal telepad and a remote telepad - are collected, if they are applicable.
|
||||||
|
* The vehicle "Router" itself must be in the drive state of `Deployed`.
|
||||||
|
* @param router the vehicle that serves as the container of an internal telepad unit
|
||||||
|
* @param zone where the router is located
|
||||||
|
* @return the pair of units that compose the teleportation system
|
||||||
|
*/
|
||||||
|
def AppraiseTeleportationSystem(router : Vehicle, zone : Zone) : Option[(Utility.InternalTelepad, TelepadDeployable)] = {
|
||||||
|
import net.psforever.objects.vehicles.UtilityType
|
||||||
|
import net.psforever.types.DriveState
|
||||||
|
router.Utility(UtilityType.internal_router_telepad_deployable) match {
|
||||||
|
//if the vehicle has an internal telepad, it is allowed to be a Router (that's a weird way of saying it)
|
||||||
|
case Some(util : Utility.InternalTelepad) =>
|
||||||
|
//check for a readied remote telepad
|
||||||
|
zone.GUID(util.Telepad) match {
|
||||||
|
case Some(telepad : TelepadDeployable) =>
|
||||||
|
//determine whether to activate both the Router's internal telepad and the deployed remote telepad
|
||||||
|
if(router.DeploymentState == DriveState.Deployed && util.Active && telepad.Active) {
|
||||||
|
Some((util, telepad))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
case _ =>
|
||||||
|
None
|
||||||
|
}
|
||||||
|
case _ =>
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.objects.definition.converter
|
||||||
|
|
||||||
|
import net.psforever.objects.PlanetSideGameObject
|
||||||
|
import net.psforever.objects.ce.TelepadLike
|
||||||
|
import net.psforever.packet.game.objectcreate._
|
||||||
|
|
||||||
|
import scala.util.{Success, Try}
|
||||||
|
|
||||||
|
class InternalTelepadDeployableConverter extends ObjectCreateConverter[PlanetSideGameObject with TelepadLike]() {
|
||||||
|
override def ConstructorData(obj : PlanetSideGameObject with TelepadLike) : Try[ContainedTelepadDeployableData] = {
|
||||||
|
Success(ContainedTelepadDeployableData(101, obj.Router.get))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.objects.definition.converter
|
||||||
|
|
||||||
|
import net.psforever.objects.Telepad
|
||||||
|
import net.psforever.packet.game.objectcreate._
|
||||||
|
|
||||||
|
import scala.util.{Failure, Success, Try}
|
||||||
|
|
||||||
|
class TelepadConverter extends ObjectCreateConverter[Telepad]() {
|
||||||
|
override def ConstructorData(obj : Telepad) : Try[TelepadData] = {
|
||||||
|
obj.Router match {
|
||||||
|
case Some(_) =>
|
||||||
|
Success(TelepadData (0, obj.Router))
|
||||||
|
case None =>
|
||||||
|
Failure(new IllegalStateException("TelepadConverter: telepad needs to know id of its router"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override def DetailedConstructorData(obj : Telepad) : Try[DetailedTelepadData] = {
|
||||||
|
obj.Router match {
|
||||||
|
case Some(_) =>
|
||||||
|
Success(DetailedTelepadData (0, obj.Router))
|
||||||
|
case None =>
|
||||||
|
Failure(new IllegalStateException("TelepadConverter: telepad needs to know id of its router"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.objects.definition.converter
|
||||||
|
|
||||||
|
import net.psforever.objects.TelepadDeployable
|
||||||
|
import net.psforever.packet.game.PlanetSideGUID
|
||||||
|
import net.psforever.packet.game.objectcreate._
|
||||||
|
|
||||||
|
import scala.util.{Failure, Success, Try}
|
||||||
|
|
||||||
|
class TelepadDeployableConverter extends ObjectCreateConverter[TelepadDeployable]() {
|
||||||
|
override def ConstructorData(obj : TelepadDeployable) : Try[TelepadDeployableData] = {
|
||||||
|
if(obj.Router.isEmpty || obj.Router.contains(PlanetSideGUID(0))) {
|
||||||
|
Failure(new IllegalStateException("TelepadDeployableConverter: telepad deployable needs to know id of its router"))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(obj.Health > 0) {
|
||||||
|
Success(TelepadDeployableData(
|
||||||
|
PlacementData(obj.Position, obj.Orientation),
|
||||||
|
obj.Faction,
|
||||||
|
bops = false,
|
||||||
|
destroyed = false,
|
||||||
|
unk1 = 2,
|
||||||
|
unk2 = true,
|
||||||
|
obj.Router.get,
|
||||||
|
obj.Owner.getOrElse(PlanetSideGUID(0)),
|
||||||
|
unk3 = 87,
|
||||||
|
unk4 = 12
|
||||||
|
))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Success(TelepadDeployableData(
|
||||||
|
PlacementData(obj.Position, obj.Orientation),
|
||||||
|
obj.Faction,
|
||||||
|
bops = false,
|
||||||
|
destroyed = true,
|
||||||
|
unk1 = 2,
|
||||||
|
unk2 = true,
|
||||||
|
obj.Router.get,
|
||||||
|
owner_guid = PlanetSideGUID(0),
|
||||||
|
unk3 = 0,
|
||||||
|
unk4 = 6
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -212,6 +212,10 @@ object EquipmentTerminalDefinition {
|
||||||
"command_detonater" -> MakeSimpleItem(command_detonater),
|
"command_detonater" -> MakeSimpleItem(command_detonater),
|
||||||
"flail_targeting_laser" -> MakeSimpleItem(flail_targeting_laser)
|
"flail_targeting_laser" -> MakeSimpleItem(flail_targeting_laser)
|
||||||
)
|
)
|
||||||
|
/**
|
||||||
|
* A single-element `Map` of the one piece of `Equipment` specific to the Router.
|
||||||
|
*/
|
||||||
|
val routerTerminal : Map[String, () => Equipment] = Map("router_telepad" -> MakeTelepad(router_telepad))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new `Tool` from provided `EquipmentDefinition` objects.
|
* Create a new `Tool` from provided `EquipmentDefinition` objects.
|
||||||
|
|
@ -334,6 +338,13 @@ object EquipmentTerminalDefinition {
|
||||||
*/
|
*/
|
||||||
private def MakeConstructionItem(cdef : ConstructionItemDefinition)() : ConstructionItem = ConstructionItem(cdef)
|
private def MakeConstructionItem(cdef : ConstructionItemDefinition)() : ConstructionItem = ConstructionItem(cdef)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* na
|
||||||
|
* @param cdef na
|
||||||
|
* @return na
|
||||||
|
*/
|
||||||
|
private def MakeTelepad(cdef : ConstructionItemDefinition)() : Telepad = Telepad(cdef)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Accept a simplified blueprint for some piece of `Equipment` and create an actual piece of `Equipment` based on it.
|
* Accept a simplified blueprint for some piece of `Equipment` and create an actual piece of `Equipment` based on it.
|
||||||
* Used specifically for the reconstruction of `Equipment` via an `Loadout`.
|
* Used specifically for the reconstruction of `Equipment` via an `Loadout`.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.objects.serverobject.terminals
|
||||||
|
|
||||||
|
import akka.actor.ActorContext
|
||||||
|
import net.psforever.objects.Player
|
||||||
|
import net.psforever.objects.serverobject.structures.Amenity
|
||||||
|
import net.psforever.packet.game.ItemTransactionMessage
|
||||||
|
|
||||||
|
class TeleportPadTerminalDefinition extends EquipmentTerminalDefinition(853) {
|
||||||
|
Name = "teleport_pad_terminal"
|
||||||
|
|
||||||
|
def Buy(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = {
|
||||||
|
Terminal.BuyEquipment(EquipmentTerminalDefinition.routerTerminal("router_telepad")())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object TeleportPadTerminalDefinition {
|
||||||
|
/**
|
||||||
|
* Assemble some logic for a provided object.
|
||||||
|
* @param obj an `Amenity` object;
|
||||||
|
* anticipating a `Terminal` object using this same definition
|
||||||
|
* @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) {
|
||||||
|
obj.Actor = context.actorOf(Props(classOf[TerminalControl], obj), s"${obj.Definition.Name}_${obj.GUID.guid}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -40,13 +40,13 @@ class Terminal(tdef : TerminalDefinition) extends Amenity with Hackable {
|
||||||
if(Faction == player.Faction || HackedBy.isDefined) {
|
if(Faction == player.Faction || HackedBy.isDefined) {
|
||||||
msg.transaction_type match {
|
msg.transaction_type match {
|
||||||
case TransactionType.Buy | TransactionType.Learn =>
|
case TransactionType.Buy | TransactionType.Learn =>
|
||||||
tdef.Buy(player, msg)
|
Buy(player, msg)
|
||||||
|
|
||||||
case TransactionType.Sell =>
|
case TransactionType.Sell =>
|
||||||
tdef.Sell(player, msg)
|
Sell(player, msg)
|
||||||
|
|
||||||
case TransactionType.Loadout =>
|
case TransactionType.Loadout =>
|
||||||
tdef.Loadout(player, msg)
|
Loadout(player, msg)
|
||||||
|
|
||||||
case _ =>
|
case _ =>
|
||||||
Terminal.NoDeal()
|
Terminal.NoDeal()
|
||||||
|
|
@ -57,6 +57,18 @@ class Terminal(tdef : TerminalDefinition) extends Amenity with Hackable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def Buy(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = {
|
||||||
|
tdef.Buy(player, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
def Sell(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = {
|
||||||
|
tdef.Sell(player, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
def Loadout(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = {
|
||||||
|
tdef.Loadout(player, msg)
|
||||||
|
}
|
||||||
|
|
||||||
def Definition : TerminalDefinition = tdef
|
def Definition : TerminalDefinition = tdef
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,13 @@
|
||||||
package net.psforever.objects.vehicles
|
package net.psforever.objects.vehicles
|
||||||
|
|
||||||
import akka.actor.ActorContext
|
import akka.actor.ActorContext
|
||||||
import net.psforever.objects.{GlobalDefinitions, Vehicle}
|
import net.psforever.objects.definition.DeployableDefinition
|
||||||
|
import net.psforever.objects._
|
||||||
|
import net.psforever.objects.ce.TelepadLike
|
||||||
import net.psforever.objects.serverobject.structures.Amenity
|
import net.psforever.objects.serverobject.structures.Amenity
|
||||||
import net.psforever.objects.serverobject.terminals.{MatrixTerminalDefinition, OrderTerminalABDefinition, Terminal, TerminalDefinition}
|
import net.psforever.objects.serverobject.terminals._
|
||||||
import net.psforever.objects.serverobject.tube.{SpawnTube, SpawnTubeDefinition}
|
import net.psforever.objects.serverobject.tube.{SpawnTube, SpawnTubeDefinition}
|
||||||
|
import net.psforever.packet.game.{ItemTransactionMessage, PlanetSideGUID}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An `Enumeration` of the available vehicular utilities.<br>
|
* An `Enumeration` of the available vehicular utilities.<br>
|
||||||
|
|
@ -21,7 +24,9 @@ object UtilityType extends Enumeration {
|
||||||
ams_respawn_tube,
|
ams_respawn_tube,
|
||||||
matrix_terminalc,
|
matrix_terminalc,
|
||||||
order_terminala,
|
order_terminala,
|
||||||
order_terminalb
|
order_terminalb,
|
||||||
|
teleportpad_terminal,
|
||||||
|
internal_router_telepad_deployable
|
||||||
= Value
|
= Value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -94,13 +99,17 @@ object Utility {
|
||||||
new TerminalUtility(GlobalDefinitions.order_terminala)
|
new TerminalUtility(GlobalDefinitions.order_terminala)
|
||||||
case UtilityType.order_terminalb =>
|
case UtilityType.order_terminalb =>
|
||||||
new TerminalUtility(GlobalDefinitions.order_terminalb)
|
new TerminalUtility(GlobalDefinitions.order_terminalb)
|
||||||
|
case UtilityType.teleportpad_terminal =>
|
||||||
|
new TeleportPadTerminalUtility(GlobalDefinitions.teleportpad_terminal)
|
||||||
|
case UtilityType.internal_router_telepad_deployable =>
|
||||||
|
new InternalTelepad(GlobalDefinitions.internal_router_telepad_deployable)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override for `SpawnTube` objects so that they inherit the spatial characteristics of their `Owner`.
|
* Override for `SpawnTube` objects so that they inherit the spatial characteristics of their `Owner`.
|
||||||
* @param tubeDef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
|
* @param tubeDef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
|
||||||
*/
|
*/
|
||||||
private class SpawnTubeUtility(tubeDef : SpawnTubeDefinition) extends SpawnTube(tubeDef) {
|
class SpawnTubeUtility(tubeDef : SpawnTubeDefinition) extends SpawnTube(tubeDef) {
|
||||||
override def Position = Owner.Position
|
override def Position = Owner.Position
|
||||||
override def Orientation = Owner.Orientation
|
override def Orientation = Owner.Orientation
|
||||||
}
|
}
|
||||||
|
|
@ -109,11 +118,60 @@ object Utility {
|
||||||
* Override for `Terminal` objects so that they inherit the spatial characteristics of their `Owner`.
|
* Override for `Terminal` objects so that they inherit the spatial characteristics of their `Owner`.
|
||||||
* @param tdef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
|
* @param tdef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
|
||||||
*/
|
*/
|
||||||
private class TerminalUtility(tdef : TerminalDefinition) extends Terminal(tdef) {
|
class TerminalUtility(tdef : TerminalDefinition) extends Terminal(tdef) {
|
||||||
override def Position = Owner.Position
|
override def Position = Owner.Position
|
||||||
override def Orientation = Owner.Orientation
|
override def Orientation = Owner.Orientation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* na
|
||||||
|
* @param tdef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
|
||||||
|
*/
|
||||||
|
class TeleportPadTerminalUtility(tdef : TerminalDefinition) extends TerminalUtility(tdef) {
|
||||||
|
/**
|
||||||
|
* na
|
||||||
|
* @param player na
|
||||||
|
* @param msg na
|
||||||
|
* @return na
|
||||||
|
*/
|
||||||
|
override def Buy(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = {
|
||||||
|
val reply = super.Buy(player, msg)
|
||||||
|
reply match {
|
||||||
|
case Terminal.BuyEquipment(obj : Telepad) =>
|
||||||
|
obj.Router = Owner.GUID
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
reply
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The internal telepad is a component that is contained by the Router when it deploys
|
||||||
|
* and allows it to serve as one of the terminal points of a Router-telepad teleportation system.
|
||||||
|
* @param ddef na
|
||||||
|
*/
|
||||||
|
class InternalTelepad(ddef : DeployableDefinition) extends Amenity
|
||||||
|
with TelepadLike {
|
||||||
|
/** a link to the telepad that serves as the other endpoint of this teleportation system */
|
||||||
|
private var activeTelepad : Option[PlanetSideGUID] = None
|
||||||
|
|
||||||
|
def Telepad : Option[PlanetSideGUID] = activeTelepad
|
||||||
|
|
||||||
|
def Telepad_=(rguid : PlanetSideGUID) : Option[PlanetSideGUID] = Telepad_=(Some(rguid))
|
||||||
|
|
||||||
|
def Telepad_=(rguid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = {
|
||||||
|
activeTelepad = rguid
|
||||||
|
Telepad
|
||||||
|
}
|
||||||
|
|
||||||
|
override def Position = Owner.Position
|
||||||
|
override def Orientation = Owner.Orientation
|
||||||
|
/** the router is the owner */
|
||||||
|
override def Router : Option[PlanetSideGUID] = Some(Owner.GUID)
|
||||||
|
|
||||||
|
def Definition = ddef
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide the called-out object's logic.
|
* Provide the called-out object's logic.
|
||||||
* @param util the type of the `Amenity` object
|
* @param util the type of the `Amenity` object
|
||||||
|
|
@ -128,5 +186,11 @@ object Utility {
|
||||||
OrderTerminalABDefinition.Setup
|
OrderTerminalABDefinition.Setup
|
||||||
case UtilityType.order_terminalb =>
|
case UtilityType.order_terminalb =>
|
||||||
OrderTerminalABDefinition.Setup
|
OrderTerminalABDefinition.Setup
|
||||||
|
case UtilityType.teleportpad_terminal =>
|
||||||
|
TeleportPadTerminalDefinition.Setup
|
||||||
|
case UtilityType.internal_router_telepad_deployable =>
|
||||||
|
TelepadLike.Setup
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//private def defaultSetup(o1 : Amenity, o2 : ActorContext) : Unit = { }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -232,6 +232,21 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recover an object from the globally unique identifier system by the number that was assigned previously.
|
||||||
|
* @param object_guid the globally unique identifier requested
|
||||||
|
* @return the associated object, if it exists
|
||||||
|
* @see `GUID(Int)`
|
||||||
|
*/
|
||||||
|
def GUID(object_guid : Option[PlanetSideGUID]) : Option[PlanetSideGameObject] = {
|
||||||
|
object_guid match {
|
||||||
|
case Some(oguid) =>
|
||||||
|
GUID(oguid.guid)
|
||||||
|
case None =>
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recover an object from the globally unique identifier system by the number that was assigned previously.
|
* Recover an object from the globally unique identifier system by the number that was assigned previously.
|
||||||
* @param object_guid the globally unique identifier requested
|
* @param object_guid the globally unique identifier requested
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.packet.game.objectcreate
|
||||||
|
|
||||||
|
import net.psforever.packet.Marshallable
|
||||||
|
import net.psforever.packet.game.PlanetSideGUID
|
||||||
|
import scodec.{Attempt, Codec, Err}
|
||||||
|
import scodec.codecs._
|
||||||
|
import shapeless.{::, HNil}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* na
|
||||||
|
*/
|
||||||
|
final case class ContainedTelepadDeployableData(unk : Int,
|
||||||
|
router_guid : PlanetSideGUID) extends ConstructorData {
|
||||||
|
override def bitsize : Long = 59L
|
||||||
|
}
|
||||||
|
|
||||||
|
object ContainedTelepadDeployableData extends Marshallable[ContainedTelepadDeployableData] {
|
||||||
|
implicit val codec : Codec[ContainedTelepadDeployableData] = (
|
||||||
|
("unk" | uint(7)) ::
|
||||||
|
("router_guid" | PlanetSideGUID.codec) ::
|
||||||
|
uint16 ::
|
||||||
|
uint4 ::
|
||||||
|
uint16
|
||||||
|
).exmap[ContainedTelepadDeployableData] (
|
||||||
|
{
|
||||||
|
case unk :: rguid :: 0 :: 8 :: 0 :: HNil =>
|
||||||
|
Attempt.successful(ContainedTelepadDeployableData(unk, rguid))
|
||||||
|
case _ :: _ :: _ :: _ :: _ :: HNil =>
|
||||||
|
Attempt.failure(Err("invalid rek data format"))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
case ContainedTelepadDeployableData(unk, rguid) =>
|
||||||
|
Attempt.successful(unk :: rguid :: 0 :: 8 :: 0 :: HNil)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.packet.game.objectcreate
|
||||||
|
|
||||||
|
import net.psforever.packet.Marshallable
|
||||||
|
import net.psforever.packet.game.PlanetSideGUID
|
||||||
|
import scodec.{Attempt, Codec, Err}
|
||||||
|
import scodec.codecs._
|
||||||
|
import shapeless.{::, HNil}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A representation of the telepad portion of `ObjectCreateDetailedMessage` packet data.
|
||||||
|
* This data will help construct the "cosntruction tool"
|
||||||
|
* that can be obtained from the Router vehicle - the Router telepad.
|
||||||
|
* It issued to construct a bidirectional teleportation point associated with a Router if that Router is deployed.
|
||||||
|
* @param unk na
|
||||||
|
* @param router_guid the Router
|
||||||
|
*/
|
||||||
|
final case class DetailedTelepadData(unk : Int, router_guid : Option[PlanetSideGUID]) extends ConstructorData {
|
||||||
|
override def bitsize : Long = {
|
||||||
|
val rguidSize = if(router_guid.nonEmpty) 16 else 0
|
||||||
|
51L + rguidSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object DetailedTelepadData extends Marshallable[DetailedTelepadData] {
|
||||||
|
def apply(unk : Int) : DetailedTelepadData = DetailedTelepadData(unk, None)
|
||||||
|
|
||||||
|
def apply(unk : Int, router_guid : PlanetSideGUID) : DetailedTelepadData = DetailedTelepadData(unk, Some(router_guid))
|
||||||
|
|
||||||
|
implicit val codec : Codec[DetailedTelepadData] = (
|
||||||
|
("unk" | uint(6)) ::
|
||||||
|
optional(bool, "router_guid" | PlanetSideGUID.codec) ::
|
||||||
|
uint(24) ::
|
||||||
|
uint(18) ::
|
||||||
|
uint2
|
||||||
|
).exmap[DetailedTelepadData] (
|
||||||
|
{
|
||||||
|
case unk :: rguid :: 1 :: 1 :: 0 :: HNil =>
|
||||||
|
Attempt.successful(DetailedTelepadData(unk, rguid))
|
||||||
|
case _ =>
|
||||||
|
Attempt.failure(Err("invalid detailed telepad format"))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
case DetailedTelepadData(unk, rguid) =>
|
||||||
|
Attempt.successful(unk :: rguid :: 1 :: 1 :: 0 :: HNil)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -230,8 +230,6 @@ object ObjectClass {
|
||||||
final val repeater = 730
|
final val repeater = 730
|
||||||
final val rocklet = 737
|
final val rocklet = 737
|
||||||
final val rotarychaingun_mosquito = 740
|
final val rotarychaingun_mosquito = 740
|
||||||
final val router_telepad = 743
|
|
||||||
final val router_telepad_deployable = 744
|
|
||||||
final val scythe = 747
|
final val scythe = 747
|
||||||
final val six_shooter = 761
|
final val six_shooter = 761
|
||||||
final val skyguard_weapon_system = 788
|
final val skyguard_weapon_system = 788
|
||||||
|
|
@ -276,7 +274,7 @@ object ObjectClass {
|
||||||
final val nano_dispenser = 577
|
final val nano_dispenser = 577
|
||||||
final val command_detonater = 213
|
final val command_detonater = 213
|
||||||
final val flail_targeting_laser = 297
|
final val flail_targeting_laser = 297
|
||||||
//ace deployables
|
//deployables
|
||||||
final val ace = 32
|
final val ace = 32
|
||||||
final val advanced_ace = 39
|
final val advanced_ace = 39
|
||||||
final val boomer = 148
|
final val boomer = 148
|
||||||
|
|
@ -284,6 +282,8 @@ object ObjectClass {
|
||||||
final val he_mine = 388
|
final val he_mine = 388
|
||||||
final val jammer_mine = 420
|
final val jammer_mine = 420
|
||||||
final val motionalarmsensor = 575
|
final val motionalarmsensor = 575
|
||||||
|
final val router_telepad = 743
|
||||||
|
final val router_telepad_deployable = 744
|
||||||
final val sensor_shield = 752
|
final val sensor_shield = 752
|
||||||
final val spitfire_aa = 819
|
final val spitfire_aa = 819
|
||||||
final val spitfire_cloaked = 825
|
final val spitfire_cloaked = 825
|
||||||
|
|
@ -602,7 +602,6 @@ object ObjectClass {
|
||||||
case ObjectClass.repeater => ConstructorData.genericCodec(DetailedWeaponData.codec, "weapon")
|
case ObjectClass.repeater => ConstructorData.genericCodec(DetailedWeaponData.codec, "weapon")
|
||||||
case ObjectClass.rocklet => ConstructorData.genericCodec(DetailedWeaponData.codec, "weapon")
|
case ObjectClass.rocklet => ConstructorData.genericCodec(DetailedWeaponData.codec, "weapon")
|
||||||
// case ObjectClass.rotarychaingun_mosquito => ConstructorData.genericCodec(DetailedWeaponData.codec, "weapon")
|
// case ObjectClass.rotarychaingun_mosquito => ConstructorData.genericCodec(DetailedWeaponData.codec, "weapon")
|
||||||
case ObjectClass.router_telepad => ConstructorData.genericCodec(DetailedWeaponData.codec, "weapon") //TODO belongs here?
|
|
||||||
case ObjectClass.scythe => ConstructorData.genericCodec(DetailedWeaponData.codec, "weapon")
|
case ObjectClass.scythe => ConstructorData.genericCodec(DetailedWeaponData.codec, "weapon")
|
||||||
// case ObjectClass.skyguard_weapon_system => ConstructorData.genericCodec(DetailedWeaponData.codec, "weapon")
|
// case ObjectClass.skyguard_weapon_system => ConstructorData.genericCodec(DetailedWeaponData.codec, "weapon")
|
||||||
case ObjectClass.spiker => ConstructorData.genericCodec(DetailedWeaponData.codec, "weapon")
|
case ObjectClass.spiker => ConstructorData.genericCodec(DetailedWeaponData.codec, "weapon")
|
||||||
|
|
@ -660,11 +659,11 @@ object ObjectClass {
|
||||||
case ObjectClass.medicalapplicator => ConstructorData.genericCodec(DetailedWeaponData.codec, "tool")
|
case ObjectClass.medicalapplicator => ConstructorData.genericCodec(DetailedWeaponData.codec, "tool")
|
||||||
case ObjectClass.nano_dispenser => ConstructorData.genericCodec(DetailedWeaponData.codec, "tool")
|
case ObjectClass.nano_dispenser => ConstructorData.genericCodec(DetailedWeaponData.codec, "tool")
|
||||||
case ObjectClass.remote_electronics_kit => ConstructorData.genericCodec(DetailedREKData.codec, "tool")
|
case ObjectClass.remote_electronics_kit => ConstructorData.genericCodec(DetailedREKData.codec, "tool")
|
||||||
//case ObjectClass.router_telepad => ConstructorData.genericCodec(*.codec, "tool") //TODO
|
|
||||||
case ObjectClass.trek => ConstructorData.genericCodec(DetailedWeaponData.codec, "tool")
|
case ObjectClass.trek => ConstructorData.genericCodec(DetailedWeaponData.codec, "tool")
|
||||||
//ace deployable
|
//ace deployable
|
||||||
case ObjectClass.ace => ConstructorData.genericCodec(DetailedACEData.codec, "ace")
|
case ObjectClass.ace => ConstructorData.genericCodec(DetailedACEData.codec, "ace")
|
||||||
case ObjectClass.advanced_ace => ConstructorData.genericCodec(DetailedACEData.codec, "advanced ace")
|
case ObjectClass.advanced_ace => ConstructorData.genericCodec(DetailedACEData.codec, "advanced ace")
|
||||||
|
case ObjectClass.router_telepad => ConstructorData.genericCodec(DetailedTelepadData.codec, "router telepad")
|
||||||
case ObjectClass.boomer_trigger => ConstructorData.genericCodec(DetailedBoomerTriggerData.codec, "boomer trigger")
|
case ObjectClass.boomer_trigger => ConstructorData.genericCodec(DetailedBoomerTriggerData.codec, "boomer trigger")
|
||||||
//other
|
//other
|
||||||
case ObjectClass.avatar => ConstructorData.genericCodec(DetailedPlayerData.codec(false), "avatar")
|
case ObjectClass.avatar => ConstructorData.genericCodec(DetailedPlayerData.codec(false), "avatar")
|
||||||
|
|
@ -951,11 +950,12 @@ object ObjectClass {
|
||||||
case ObjectClass.medicalapplicator => ConstructorData.genericCodec(WeaponData.codec, "tool")
|
case ObjectClass.medicalapplicator => ConstructorData.genericCodec(WeaponData.codec, "tool")
|
||||||
case ObjectClass.nano_dispenser => ConstructorData.genericCodec(WeaponData.codec, "tool")
|
case ObjectClass.nano_dispenser => ConstructorData.genericCodec(WeaponData.codec, "tool")
|
||||||
case ObjectClass.remote_electronics_kit => ConstructorData.genericCodec(REKData.codec, "tool")
|
case ObjectClass.remote_electronics_kit => ConstructorData.genericCodec(REKData.codec, "tool")
|
||||||
//case ObjectClass.router_telepad => ConstructorData.genericCodec(WeaponData.codec, "tool") //TODO
|
|
||||||
case ObjectClass.trek => ConstructorData.genericCodec(WeaponData.codec, "tool")
|
case ObjectClass.trek => ConstructorData.genericCodec(WeaponData.codec, "tool")
|
||||||
//ace deployables
|
//deployables
|
||||||
case ObjectClass.ace => ConstructorData.genericCodec(ACEData.codec, "ace")
|
case ObjectClass.ace => ConstructorData.genericCodec(ACEData.codec, "ace")
|
||||||
case ObjectClass.advanced_ace => ConstructorData.genericCodec(ACEData.codec, "advanced ace")
|
case ObjectClass.advanced_ace => ConstructorData.genericCodec(ACEData.codec, "advanced ace")
|
||||||
|
case ObjectClass.router_telepad => ConstructorData.genericCodec(TelepadData.codec, "router telepad")
|
||||||
|
case ObjectClass.router_telepad_deployable => ConstructorData.genericCodec(ContainedTelepadDeployableData.codec, "router telepad")
|
||||||
case ObjectClass.boomer_trigger => ConstructorData.genericCodec(BoomerTriggerData.codec, "boomer trigger")
|
case ObjectClass.boomer_trigger => ConstructorData.genericCodec(BoomerTriggerData.codec, "boomer trigger")
|
||||||
//vehicles?
|
//vehicles?
|
||||||
case ObjectClass.orbital_shuttle => ConstructorData.genericCodec(OrbitalShuttleData.codec, "HART")
|
case ObjectClass.orbital_shuttle => ConstructorData.genericCodec(OrbitalShuttleData.codec, "HART")
|
||||||
|
|
@ -1182,11 +1182,11 @@ object ObjectClass {
|
||||||
case ObjectClass.medicalapplicator => DroppedItemData.genericCodec(WeaponData.codec, "tool")
|
case ObjectClass.medicalapplicator => DroppedItemData.genericCodec(WeaponData.codec, "tool")
|
||||||
case ObjectClass.nano_dispenser => DroppedItemData.genericCodec(WeaponData.codec, "tool")
|
case ObjectClass.nano_dispenser => DroppedItemData.genericCodec(WeaponData.codec, "tool")
|
||||||
case ObjectClass.remote_electronics_kit => DroppedItemData.genericCodec(REKData.codec, " tool")
|
case ObjectClass.remote_electronics_kit => DroppedItemData.genericCodec(REKData.codec, " tool")
|
||||||
//case ObjectClass.router_telepad => DroppedItemData.genericCodec(WeaponData.codec, "tool") //TODO
|
|
||||||
case ObjectClass.trek => DroppedItemData.genericCodec(WeaponData.codec, "tool")
|
case ObjectClass.trek => DroppedItemData.genericCodec(WeaponData.codec, "tool")
|
||||||
//ace deployables
|
//deployables
|
||||||
case ObjectClass.ace => DroppedItemData.genericCodec(ACEData.codec, "ace")
|
case ObjectClass.ace => DroppedItemData.genericCodec(ACEData.codec, "ace")
|
||||||
case ObjectClass.advanced_ace => DroppedItemData.genericCodec(ACEData.codec, "advanced ace") //todo temporary?
|
case ObjectClass.advanced_ace => DroppedItemData.genericCodec(ACEData.codec, "advanced ace")
|
||||||
|
case ObjectClass.router_telepad => DroppedItemData.genericCodec(TelepadData.codec, "router telepad") //TODO not correct
|
||||||
case ObjectClass.boomer_trigger => DroppedItemData.genericCodec(BoomerTriggerData.codec, "boomer trigger")
|
case ObjectClass.boomer_trigger => DroppedItemData.genericCodec(BoomerTriggerData.codec, "boomer trigger")
|
||||||
case ObjectClass.boomer => ConstructorData.genericCodec(SmallDeployableData.codec, "ace deployable")
|
case ObjectClass.boomer => ConstructorData.genericCodec(SmallDeployableData.codec, "ace deployable")
|
||||||
case ObjectClass.he_mine => ConstructorData.genericCodec(SmallDeployableData.codec, "ace deployable")
|
case ObjectClass.he_mine => ConstructorData.genericCodec(SmallDeployableData.codec, "ace deployable")
|
||||||
|
|
@ -1202,6 +1202,7 @@ object ObjectClass {
|
||||||
case ObjectClass.portable_manned_turret_nc => ConstructorData.genericCodec(OneMannedFieldTurretData.codec, "field turret")
|
case ObjectClass.portable_manned_turret_nc => ConstructorData.genericCodec(OneMannedFieldTurretData.codec, "field turret")
|
||||||
case ObjectClass.portable_manned_turret_tr => ConstructorData.genericCodec(OneMannedFieldTurretData.codec, "field turret")
|
case ObjectClass.portable_manned_turret_tr => ConstructorData.genericCodec(OneMannedFieldTurretData.codec, "field turret")
|
||||||
case ObjectClass.portable_manned_turret_vs => ConstructorData.genericCodec(OneMannedFieldTurretData.codec, "field turret")
|
case ObjectClass.portable_manned_turret_vs => ConstructorData.genericCodec(OneMannedFieldTurretData.codec, "field turret")
|
||||||
|
case ObjectClass.router_telepad_deployable => ConstructorData.genericCodec(TelepadDeployableData.codec, "telepad deployable")
|
||||||
//projectiles
|
//projectiles
|
||||||
case ObjectClass.hunter_seeker_missile_projectile => ConstructorData.genericCodec(TrackedProjectileData.codec, "projectile")
|
case ObjectClass.hunter_seeker_missile_projectile => ConstructorData.genericCodec(TrackedProjectileData.codec, "projectile")
|
||||||
case ObjectClass.oicw_projectile => ConstructorData.genericCodec(TrackedProjectileData.codec, "projectile")
|
case ObjectClass.oicw_projectile => ConstructorData.genericCodec(TrackedProjectileData.codec, "projectile")
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.packet.game.objectcreate
|
||||||
|
|
||||||
|
import net.psforever.packet.Marshallable
|
||||||
|
import net.psforever.packet.game.PlanetSideGUID
|
||||||
|
import scodec.{Attempt, Codec, Err}
|
||||||
|
import scodec.codecs._
|
||||||
|
import shapeless.{::, HNil}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A representation of the telepad portion of `ObjectCreateMessage` packet data.
|
||||||
|
* This data will help construct the "cosntruction tool"
|
||||||
|
* that can be obtained from the Router vehicle - the Router telepad.
|
||||||
|
* It issued to construct a bidirectional teleportation point associated with a Router if that Router is deployed.
|
||||||
|
* @param unk na
|
||||||
|
* @param router_guid the Router
|
||||||
|
*/
|
||||||
|
final case class TelepadData(unk : Int, router_guid : Option[PlanetSideGUID]) extends ConstructorData {
|
||||||
|
override def bitsize : Long = {
|
||||||
|
val rguidSize = if(router_guid.nonEmpty) 16 else 0
|
||||||
|
34L + rguidSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object TelepadData extends Marshallable[TelepadData] {
|
||||||
|
def apply(unk : Int) : TelepadData = TelepadData(unk, None)
|
||||||
|
|
||||||
|
def apply(unk : Int, router_guid : PlanetSideGUID) : TelepadData = TelepadData(unk, Some(router_guid))
|
||||||
|
|
||||||
|
implicit val codec : Codec[TelepadData] = (
|
||||||
|
("unk" | uint(6)) ::
|
||||||
|
optional(bool, "router_guid" | PlanetSideGUID.codec) ::
|
||||||
|
uint(27)
|
||||||
|
).exmap[TelepadData] (
|
||||||
|
{
|
||||||
|
case unk :: rguid :: 0 :: HNil =>
|
||||||
|
Attempt.successful(TelepadData(unk, rguid))
|
||||||
|
case _ =>
|
||||||
|
Attempt.failure(Err("invalid telepad format"))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
case TelepadData(unk, rguid) =>
|
||||||
|
Attempt.successful(unk :: rguid :: 0 :: HNil)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.packet.game.objectcreate
|
||||||
|
|
||||||
|
import net.psforever.packet.Marshallable
|
||||||
|
import net.psforever.packet.game.PlanetSideGUID
|
||||||
|
import net.psforever.types.PlanetSideEmpire
|
||||||
|
import scodec.Codec
|
||||||
|
import scodec.codecs._
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A representation of simple objects that are spawned by the adaptive construction engine.
|
||||||
|
* @param pos na
|
||||||
|
* @param faction na
|
||||||
|
* @param bops na
|
||||||
|
* @param destroyed na
|
||||||
|
* @param unk1 na
|
||||||
|
* @param unk2 na
|
||||||
|
* @param router_guid the associated Router vehicle;
|
||||||
|
* this is an essential non-blank (16u 0x0) field;
|
||||||
|
* a blanked field will cause the client to crash
|
||||||
|
* @param owner_guid the owner of this telepad
|
||||||
|
* @param unk3 na
|
||||||
|
* @param unk4 na
|
||||||
|
*/
|
||||||
|
//TODO might be CommonFieldData
|
||||||
|
final case class TelepadDeployableData(pos : PlacementData,
|
||||||
|
faction : PlanetSideEmpire.Value,
|
||||||
|
bops : Boolean,
|
||||||
|
destroyed : Boolean,
|
||||||
|
unk1 : Int,
|
||||||
|
unk2 : Boolean,
|
||||||
|
router_guid : PlanetSideGUID,
|
||||||
|
owner_guid : PlanetSideGUID,
|
||||||
|
unk3 : Int,
|
||||||
|
unk4 : Int) extends ConstructorData {
|
||||||
|
override def bitsize : Long = {
|
||||||
|
val posSize = pos.bitsize
|
||||||
|
59 + posSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object TelepadDeployableData extends Marshallable[TelepadDeployableData] {
|
||||||
|
implicit val codec : Codec[TelepadDeployableData] = (
|
||||||
|
("pos" | PlacementData.codec) ::
|
||||||
|
("faction" | PlanetSideEmpire.codec) ::
|
||||||
|
("bops" | bool) ::
|
||||||
|
("destroyed" | bool) ::
|
||||||
|
("unk1" | uint2L) :: //3 - na, 2 - common, 1 - na, 0 - common?
|
||||||
|
("unk2" | bool) ::
|
||||||
|
("router_guid" | PlanetSideGUID.codec) ::
|
||||||
|
("owner_guid" | PlanetSideGUID.codec) ::
|
||||||
|
("unk3" | uint16L) ::
|
||||||
|
("unk4" | uint4)
|
||||||
|
).as[TelepadDeployableData]
|
||||||
|
}
|
||||||
|
|
@ -226,6 +226,7 @@ abstract class RemoverActor extends SupportActor[RemoverActor.Entry] {
|
||||||
* No entries in the first pool.
|
* No entries in the first pool.
|
||||||
*/
|
*/
|
||||||
def ClearAll() : Unit = {
|
def ClearAll() : Unit = {
|
||||||
|
trace("all tasks have been cleared")
|
||||||
firstTask.cancel
|
firstTask.cancel
|
||||||
firstHeap = Nil
|
firstHeap = Nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
// Copyright (c) 2017 PSForever
|
// Copyright (c) 2017 PSForever
|
||||||
package services.local
|
package services.local
|
||||||
|
|
||||||
import net.psforever.objects.PlanetSideGameObject
|
import net.psforever.objects.{PlanetSideGameObject, TelepadDeployable, Vehicle}
|
||||||
import net.psforever.objects.ce.Deployable
|
import net.psforever.objects.ce.Deployable
|
||||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||||
import net.psforever.objects.serverobject.doors.Door
|
import net.psforever.objects.serverobject.doors.Door
|
||||||
import net.psforever.objects.serverobject.hackable.Hackable
|
import net.psforever.objects.serverobject.hackable.Hackable
|
||||||
import net.psforever.objects.serverobject.terminals.CaptureTerminal
|
import net.psforever.objects.serverobject.terminals.CaptureTerminal
|
||||||
|
import net.psforever.objects.vehicles.Utility
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.Zone
|
||||||
import net.psforever.packet.game._
|
import net.psforever.packet.game._
|
||||||
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||||
|
|
@ -23,9 +24,11 @@ object LocalAction {
|
||||||
final case class ClearTemporaryHack(player_guid: PlanetSideGUID, target: PlanetSideServerObject with Hackable) extends Action
|
final case class ClearTemporaryHack(player_guid: PlanetSideGUID, target: PlanetSideServerObject with Hackable) extends Action
|
||||||
final case class HackCaptureTerminal(player_guid : PlanetSideGUID, continent : Zone, target : CaptureTerminal, unk1 : Long, unk2 : Long = 8L, isResecured : Boolean) extends Action
|
final case class HackCaptureTerminal(player_guid : PlanetSideGUID, continent : Zone, target : CaptureTerminal, unk1 : Long, unk2 : Long = 8L, isResecured : Boolean) extends Action
|
||||||
final case class ProximityTerminalEffect(player_guid : PlanetSideGUID, object_guid : PlanetSideGUID, effectState : Boolean) extends Action
|
final case class ProximityTerminalEffect(player_guid : PlanetSideGUID, object_guid : PlanetSideGUID, effectState : Boolean) extends Action
|
||||||
|
final case class RouterTelepadTransport(player_guid : PlanetSideGUID, passenger_guid : PlanetSideGUID, src_guid : PlanetSideGUID, dest_guid : PlanetSideGUID) extends Action
|
||||||
|
final case class SetEmpire(object_guid: PlanetSideGUID, empire: PlanetSideEmpire.Value) extends Action
|
||||||
|
final case class ToggleTeleportSystem(player_guid : PlanetSideGUID, router : Vehicle, systemPlan : Option[(Utility.InternalTelepad, TelepadDeployable)]) extends Action
|
||||||
final case class TriggerEffect(player_guid : PlanetSideGUID, effect : String, target : PlanetSideGUID) extends Action
|
final case class TriggerEffect(player_guid : PlanetSideGUID, effect : String, target : PlanetSideGUID) extends Action
|
||||||
final case class TriggerEffectInfo(player_guid : PlanetSideGUID, effect : String, target : PlanetSideGUID, unk1 : Boolean, unk2 : Long) extends Action
|
final case class TriggerEffectInfo(player_guid : PlanetSideGUID, effect : String, target : PlanetSideGUID, unk1 : Boolean, unk2 : Long) extends Action
|
||||||
final case class TriggerEffectLocation(player_guid : PlanetSideGUID, effect : String, pos : Vector3, orient : Vector3) extends Action
|
final case class TriggerEffectLocation(player_guid : PlanetSideGUID, effect : String, pos : Vector3, orient : Vector3) extends Action
|
||||||
final case class TriggerSound(player_guid : PlanetSideGUID, sound : TriggeredSound.Value, pos : Vector3, unk : Int, volume : Float) extends Action
|
final case class TriggerSound(player_guid : PlanetSideGUID, sound : TriggeredSound.Value, pos : Vector3, unk : Int, volume : Float) extends Action
|
||||||
final case class SetEmpire(object_guid: PlanetSideGUID, empire: PlanetSideEmpire.Value) extends Action
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
package services.local
|
package services.local
|
||||||
|
|
||||||
import net.psforever.objects.ce.Deployable
|
import net.psforever.objects.ce.Deployable
|
||||||
import net.psforever.objects.PlanetSideGameObject
|
import net.psforever.objects.vehicles.Utility
|
||||||
|
import net.psforever.objects.{PlanetSideGameObject, TelepadDeployable, Vehicle}
|
||||||
import net.psforever.packet.game._
|
import net.psforever.packet.game._
|
||||||
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||||
|
|
||||||
|
|
@ -19,7 +20,10 @@ object LocalResponse {
|
||||||
final case class HackCaptureTerminal(target_guid : PlanetSideGUID, unk1 : Long, unk2 : Long, isResecured: Boolean) extends Response
|
final case class HackCaptureTerminal(target_guid : PlanetSideGUID, unk1 : Long, unk2 : Long, isResecured: Boolean) extends Response
|
||||||
final case class ObjectDelete(item_guid : PlanetSideGUID, unk : Int) extends Response
|
final case class ObjectDelete(item_guid : PlanetSideGUID, unk : Int) extends Response
|
||||||
final case class ProximityTerminalEffect(object_guid : PlanetSideGUID, effectState : Boolean) extends Response
|
final case class ProximityTerminalEffect(object_guid : PlanetSideGUID, effectState : Boolean) extends Response
|
||||||
|
final case class RouterTelepadMessage(msg : String) extends Response
|
||||||
|
final case class RouterTelepadTransport(passenger_guid : PlanetSideGUID, src_guid : PlanetSideGUID, dest_guid : PlanetSideGUID) extends Response
|
||||||
|
final case class SetEmpire(object_guid: PlanetSideGUID, empire: PlanetSideEmpire.Value) extends Response
|
||||||
|
final case class ToggleTeleportSystem(router : Vehicle, systemPlan : Option[(Utility.InternalTelepad, TelepadDeployable)]) extends Response
|
||||||
final case class TriggerEffect(target: PlanetSideGUID, effect: String, effectInfo: Option[TriggeredEffect] = None, triggeredLocation: Option[TriggeredEffectLocation] = None) extends Response
|
final case class TriggerEffect(target: PlanetSideGUID, effect: String, effectInfo: Option[TriggeredEffect] = None, triggeredLocation: Option[TriggeredEffectLocation] = None) extends Response
|
||||||
final case class TriggerSound(sound : TriggeredSound.Value, pos : Vector3, unk : Int, volume : Float) extends Response
|
final case class TriggerSound(sound : TriggeredSound.Value, pos : Vector3, unk : Int, volume : Float) extends Response
|
||||||
final case class SetEmpire(object_guid: PlanetSideGUID, empire: PlanetSideEmpire.Value) extends Response
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,18 +7,21 @@ import net.psforever.objects.serverobject.resourcesilo.ResourceSilo
|
||||||
import net.psforever.objects.serverobject.structures.Building
|
import net.psforever.objects.serverobject.structures.Building
|
||||||
import net.psforever.objects.serverobject.terminals.CaptureTerminal
|
import net.psforever.objects.serverobject.terminals.CaptureTerminal
|
||||||
import net.psforever.objects.zones.{InterstellarCluster, Zone}
|
import net.psforever.objects.zones.{InterstellarCluster, Zone}
|
||||||
import net.psforever.objects.{BoomerDeployable, GlobalDefinitions, PlanetSideGameObject, TurretDeployable}
|
import net.psforever.objects._
|
||||||
import net.psforever.packet.game.{PlanetSideGUID, TriggeredEffect, TriggeredEffectLocation}
|
import net.psforever.packet.game.{PlanetSideGUID, TriggeredEffect, TriggeredEffectLocation}
|
||||||
import net.psforever.objects.vital.Vitality
|
import net.psforever.objects.vital.Vitality
|
||||||
import net.psforever.types.Vector3
|
import net.psforever.types.Vector3
|
||||||
import services.local.support.{DeployableRemover, DoorCloseActor, HackClearActor, HackCaptureActor}
|
import services.local.support._
|
||||||
import services.vehicle.{VehicleAction, VehicleServiceMessage}
|
import services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||||
import services.{GenericEventBus, Service, ServiceManager}
|
import services.{GenericEventBus, RemoverActor, Service, ServiceManager}
|
||||||
|
|
||||||
import scala.util.Success
|
import scala.util.Success
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
import akka.pattern.ask
|
import akka.pattern.ask
|
||||||
|
import net.psforever.objects.vehicles.{Utility, UtilityType}
|
||||||
import services.ServiceManager.Lookup
|
import services.ServiceManager.Lookup
|
||||||
|
import services.support.SupportActor
|
||||||
|
|
||||||
import scala.concurrent.duration.Duration
|
import scala.concurrent.duration.Duration
|
||||||
|
|
||||||
class LocalService extends Actor {
|
class LocalService extends Actor {
|
||||||
|
|
@ -26,6 +29,7 @@ class LocalService extends Actor {
|
||||||
private val hackClearer = context.actorOf(Props[HackClearActor], "local-hack-clearer")
|
private val hackClearer = context.actorOf(Props[HackClearActor], "local-hack-clearer")
|
||||||
private val hackCapturer = context.actorOf(Props[HackCaptureActor], "local-hack-capturer")
|
private val hackCapturer = context.actorOf(Props[HackCaptureActor], "local-hack-capturer")
|
||||||
private val engineer = context.actorOf(Props[DeployableRemover], "deployable-remover-agent")
|
private val engineer = context.actorOf(Props[DeployableRemover], "deployable-remover-agent")
|
||||||
|
private val teleportDeployment : ActorRef = context.actorOf(Props[RouterTelepadActivation], "telepad-activate-agent")
|
||||||
private [this] val log = org.log4s.getLogger
|
private [this] val log = org.log4s.getLogger
|
||||||
var cluster : ActorRef = Actor.noSender
|
var cluster : ActorRef = Actor.noSender
|
||||||
|
|
||||||
|
|
@ -111,10 +115,18 @@ class LocalService extends Actor {
|
||||||
LocalEvents.publish(
|
LocalEvents.publish(
|
||||||
LocalServiceResponse(s"/$forChannel/Local", player_guid, LocalResponse.ProximityTerminalEffect(object_guid, effectState))
|
LocalServiceResponse(s"/$forChannel/Local", player_guid, LocalResponse.ProximityTerminalEffect(object_guid, effectState))
|
||||||
)
|
)
|
||||||
|
case LocalAction.RouterTelepadTransport(player_guid, passenger_guid, src_guid, dest_guid) =>
|
||||||
|
LocalEvents.publish(
|
||||||
|
LocalServiceResponse(s"/$forChannel/Local", player_guid, LocalResponse.RouterTelepadTransport(passenger_guid, src_guid, dest_guid))
|
||||||
|
)
|
||||||
case LocalAction.SetEmpire(object_guid, empire) =>
|
case LocalAction.SetEmpire(object_guid, empire) =>
|
||||||
LocalEvents.publish(
|
LocalEvents.publish(
|
||||||
LocalServiceResponse(s"/$forChannel/Local", Service.defaultPlayerGUID, LocalResponse.SetEmpire(object_guid, empire))
|
LocalServiceResponse(s"/$forChannel/Local", Service.defaultPlayerGUID, LocalResponse.SetEmpire(object_guid, empire))
|
||||||
)
|
)
|
||||||
|
case LocalAction.ToggleTeleportSystem(player_guid, router, system_plan) =>
|
||||||
|
LocalEvents.publish(
|
||||||
|
LocalServiceResponse(s"/$forChannel/Local", player_guid, LocalResponse.ToggleTeleportSystem(router, system_plan))
|
||||||
|
)
|
||||||
case LocalAction.TriggerEffect(player_guid, effect, target) =>
|
case LocalAction.TriggerEffect(player_guid, effect, target) =>
|
||||||
LocalEvents.publish(
|
LocalEvents.publish(
|
||||||
LocalServiceResponse(s"/$forChannel/Local", player_guid, LocalResponse.TriggerEffect(target, effect))
|
LocalServiceResponse(s"/$forChannel/Local", player_guid, LocalResponse.TriggerEffect(target, effect))
|
||||||
|
|
@ -219,6 +231,12 @@ class LocalService extends Actor {
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case DeployableRemover.EliminateDeployable(obj : TelepadDeployable, guid, pos, zone) =>
|
||||||
|
obj.Active = false
|
||||||
|
//ClearSpecific will also remove objects that do not have GUID's; we may not have a GUID at this time
|
||||||
|
teleportDeployment ! SupportActor.ClearSpecific(List(obj), zone)
|
||||||
|
EliminateDeployable(obj, guid, pos, zone.Id)
|
||||||
|
|
||||||
case DeployableRemover.EliminateDeployable(obj, guid, pos, zone) =>
|
case DeployableRemover.EliminateDeployable(obj, guid, pos, zone) =>
|
||||||
EliminateDeployable(obj, guid, pos, zone.Id)
|
EliminateDeployable(obj, guid, pos, zone.Id)
|
||||||
|
|
||||||
|
|
@ -227,6 +245,54 @@ class LocalService extends Actor {
|
||||||
LocalServiceResponse(s"/${zone.Id}/Local", Service.defaultPlayerGUID, LocalResponse.ObjectDelete(trigger_guid, 0))
|
LocalServiceResponse(s"/${zone.Id}/Local", Service.defaultPlayerGUID, LocalResponse.ObjectDelete(trigger_guid, 0))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//message to RouterTelepadActivation
|
||||||
|
case LocalServiceMessage.Telepads(msg) =>
|
||||||
|
teleportDeployment forward msg
|
||||||
|
|
||||||
|
//from RouterTelepadActivation
|
||||||
|
case RouterTelepadActivation.ActivateTeleportSystem(telepad, zone) =>
|
||||||
|
val remoteTelepad = telepad.asInstanceOf[TelepadDeployable]
|
||||||
|
remoteTelepad.Active = true
|
||||||
|
zone.GUID(remoteTelepad.Router) match {
|
||||||
|
case Some(router : Vehicle) =>
|
||||||
|
router.Utility(UtilityType.internal_router_telepad_deployable) match {
|
||||||
|
case Some(internalTelepad : Utility.InternalTelepad) =>
|
||||||
|
//get rid of previous linked remote telepad (if any)
|
||||||
|
zone.GUID(internalTelepad.Telepad) match {
|
||||||
|
case Some(old : TelepadDeployable) =>
|
||||||
|
log.info(s"ActivateTeleportSystem: old remote telepad@${old.GUID.guid} linked to internal@${internalTelepad.GUID.guid} will be deconstructed")
|
||||||
|
old.Active = false
|
||||||
|
engineer ! SupportActor.ClearSpecific(List(old), zone)
|
||||||
|
engineer ! RemoverActor.AddTask(old, zone, Some(0 seconds))
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
internalTelepad.Telepad = remoteTelepad.GUID
|
||||||
|
if(internalTelepad.Active) {
|
||||||
|
log.info(s"ActivateTeleportSystem: fully deployed router@${router.GUID.guid} in ${zone.Id} will link internal@${internalTelepad.GUID.guid} and remote@${remoteTelepad.GUID.guid}")
|
||||||
|
LocalEvents.publish(
|
||||||
|
LocalServiceResponse(s"/${zone.Id}/Local", Service.defaultPlayerGUID, LocalResponse.ToggleTeleportSystem(router, Some((internalTelepad, remoteTelepad))))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
remoteTelepad.OwnerName match {
|
||||||
|
case Some(name) =>
|
||||||
|
LocalEvents.publish(
|
||||||
|
LocalServiceResponse(s"/$name/Local", Service.defaultPlayerGUID, LocalResponse.RouterTelepadMessage("@Teleport_NotDeployed"))
|
||||||
|
)
|
||||||
|
case None => ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case _ =>
|
||||||
|
log.error(s"ActivateTeleportSystem: vehicle@${router.GUID.guid} in ${zone.Id} is not a router?")
|
||||||
|
RouterTelepadError(remoteTelepad, zone, "@Telepad_NoDeploy_RouterLost")
|
||||||
|
}
|
||||||
|
case Some(o) =>
|
||||||
|
log.error(s"ActivateTeleportSystem: ${o.Definition.Name}@${o.GUID.guid} in ${zone.Id} is not a router")
|
||||||
|
RouterTelepadError(remoteTelepad, zone, "@Telepad_NoDeploy_RouterLost")
|
||||||
|
case None =>
|
||||||
|
RouterTelepadError(remoteTelepad, zone, "@Telepad_NoDeploy_RouterLost")
|
||||||
|
}
|
||||||
|
|
||||||
//synchronized damage calculations
|
//synchronized damage calculations
|
||||||
case Vitality.DamageOn(target : Deployable, func) =>
|
case Vitality.DamageOn(target : Deployable, func) =>
|
||||||
func(target)
|
func(target)
|
||||||
|
|
@ -236,6 +302,24 @@ class LocalService extends Actor {
|
||||||
log.warn(s"Unhandled message $msg from $sender")
|
log.warn(s"Unhandled message $msg from $sender")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* na
|
||||||
|
* @param telepad na
|
||||||
|
* @param zone na
|
||||||
|
* @param msg na
|
||||||
|
*/
|
||||||
|
def RouterTelepadError(telepad : TelepadDeployable, zone : Zone, msg : String) : Unit = {
|
||||||
|
telepad.OwnerName match {
|
||||||
|
case Some(name) =>
|
||||||
|
LocalEvents.publish(
|
||||||
|
LocalServiceResponse(s"/$name/Local", Service.defaultPlayerGUID, LocalResponse.RouterTelepadMessage(msg))
|
||||||
|
)
|
||||||
|
case None => ;
|
||||||
|
}
|
||||||
|
engineer ! SupportActor.ClearSpecific(List(telepad), zone)
|
||||||
|
engineer ! RemoverActor.AddTask(telepad, zone, Some(0 seconds))
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common behavior for distributing information about a deployable's destruction or deconstruction.<br>
|
* Common behavior for distributing information about a deployable's destruction or deconstruction.<br>
|
||||||
* <br>
|
* <br>
|
||||||
|
|
|
||||||
|
|
@ -5,4 +5,6 @@ final case class LocalServiceMessage(forChannel : String, actionMessage : LocalA
|
||||||
|
|
||||||
object LocalServiceMessage {
|
object LocalServiceMessage {
|
||||||
final case class Deployables(msg : Any)
|
final case class Deployables(msg : Any)
|
||||||
|
|
||||||
|
final case class Telepads(msg : Any)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,142 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package services.local.support
|
||||||
|
|
||||||
|
import akka.actor.Cancellable
|
||||||
|
import net.psforever.objects.zones.Zone
|
||||||
|
import net.psforever.objects._
|
||||||
|
import services.support.{SimilarityComparator, SupportActor}
|
||||||
|
|
||||||
|
import scala.concurrent.duration._
|
||||||
|
|
||||||
|
class RouterTelepadActivation extends SupportActor[RouterTelepadActivation.Entry] {
|
||||||
|
var activationTask : Cancellable = DefaultCancellable.obj
|
||||||
|
var telepadList : List[RouterTelepadActivation.Entry] = List()
|
||||||
|
val sameEntryComparator = new SimilarityComparator[RouterTelepadActivation.Entry]() {
|
||||||
|
def Test(entry1 : RouterTelepadActivation.Entry, entry2 : RouterTelepadActivation.Entry) : Boolean = {
|
||||||
|
(entry1.obj eq entry2.obj) && (entry1.zone eq entry2.zone) && entry1.obj.GUID == entry2.obj.GUID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val firstStandardTime : FiniteDuration = 60 seconds
|
||||||
|
|
||||||
|
def InclusionTest(entry : RouterTelepadActivation.Entry) : Boolean = {
|
||||||
|
val obj = entry.obj
|
||||||
|
obj.isInstanceOf[TelepadDeployable] && !obj.asInstanceOf[TelepadDeployable].Active
|
||||||
|
}
|
||||||
|
|
||||||
|
def receive : Receive = entryManagementBehaviors
|
||||||
|
.orElse {
|
||||||
|
case RouterTelepadActivation.AddTask(obj, zone, duration) =>
|
||||||
|
val entry = RouterTelepadActivation.Entry(obj, zone, duration.getOrElse(firstStandardTime).toNanos)
|
||||||
|
if(InclusionTest(entry) && !telepadList.exists(test => sameEntryComparator.Test(test, entry))) {
|
||||||
|
if(entry.duration == 0) {
|
||||||
|
//skip the queue altogether
|
||||||
|
ActivationTask(entry)
|
||||||
|
}
|
||||||
|
else if(telepadList.isEmpty) {
|
||||||
|
//we were the only entry so the event must be started from scratch
|
||||||
|
telepadList = List(entry)
|
||||||
|
trace(s"an activation task has been added: $entry")
|
||||||
|
RetimeFirstTask()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//unknown number of entries; append, sort, then re-time tasking
|
||||||
|
val oldHead = telepadList.head
|
||||||
|
if(!telepadList.exists(test => sameEntryComparator.Test(test, entry))) {
|
||||||
|
telepadList = (telepadList :+ entry).sortBy(entry => entry.time + entry.duration)
|
||||||
|
trace(s"an activation task has been added: $entry")
|
||||||
|
if(oldHead != telepadList.head) {
|
||||||
|
RetimeFirstTask()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
trace(s"$obj is already queued")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
trace(s"$obj either does not qualify for this behavior or is already queued")
|
||||||
|
}
|
||||||
|
|
||||||
|
//private messages from self to self
|
||||||
|
case RouterTelepadActivation.TryActivate() =>
|
||||||
|
activationTask.cancel
|
||||||
|
val now : Long = System.nanoTime
|
||||||
|
val (in, out) = telepadList.partition(entry => { now - entry.time >= entry.duration })
|
||||||
|
telepadList = out
|
||||||
|
in.foreach { ActivationTask }
|
||||||
|
RetimeFirstTask()
|
||||||
|
trace(s"router activation task has found ${in.size} items to process")
|
||||||
|
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common function to reset the first task's delayed execution.
|
||||||
|
* Cancels the scheduled timer and will only restart the timer if there is at least one entry in the first pool.
|
||||||
|
* @param now the time (in nanoseconds);
|
||||||
|
* defaults to the current time (in nanoseconds)
|
||||||
|
*/
|
||||||
|
def RetimeFirstTask(now : Long = System.nanoTime) : Unit = {
|
||||||
|
activationTask.cancel
|
||||||
|
if(telepadList.nonEmpty) {
|
||||||
|
val short_timeout : FiniteDuration = math.max(1, telepadList.head.duration - (now - telepadList.head.time)) nanoseconds
|
||||||
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
|
activationTask = context.system.scheduler.scheduleOnce(short_timeout, self, RouterTelepadActivation.TryActivate())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def HurrySpecific(targets : List[PlanetSideGameObject], zone : Zone) : Unit = {
|
||||||
|
PartitionTargetsFromList(telepadList, targets.map { RouterTelepadActivation.Entry(_, zone, 0) }, zone) match {
|
||||||
|
case (Nil, _) =>
|
||||||
|
debug(s"no tasks matching the targets $targets have been hurried")
|
||||||
|
case (in, out) =>
|
||||||
|
debug(s"the following tasks have been hurried: $in")
|
||||||
|
telepadList = out
|
||||||
|
if(out.nonEmpty) {
|
||||||
|
RetimeFirstTask()
|
||||||
|
}
|
||||||
|
in.foreach { ActivationTask }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def HurryAll() : Unit = {
|
||||||
|
trace("all tasks have been hurried")
|
||||||
|
activationTask.cancel
|
||||||
|
telepadList.foreach { ActivationTask }
|
||||||
|
telepadList = Nil
|
||||||
|
}
|
||||||
|
|
||||||
|
def ClearSpecific(targets : List[PlanetSideGameObject], zone : Zone) : Unit = {
|
||||||
|
PartitionTargetsFromList(telepadList, targets.map { RouterTelepadActivation.Entry(_, zone, 0) }, zone) match {
|
||||||
|
case (Nil, _) =>
|
||||||
|
debug(s"no tasks matching the targets $targets have been cleared")
|
||||||
|
case (in, out) =>
|
||||||
|
debug(s"the following tasks have been cleared: $in")
|
||||||
|
telepadList = out //.sortBy(entry => entry.time + entry.duration)
|
||||||
|
if(out.nonEmpty) {
|
||||||
|
RetimeFirstTask()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def ClearAll() : Unit = {
|
||||||
|
trace("all tasks have been cleared")
|
||||||
|
activationTask.cancel
|
||||||
|
telepadList = Nil
|
||||||
|
}
|
||||||
|
|
||||||
|
def ActivationTask(entry : SupportActor.Entry) : Unit = {
|
||||||
|
entry.obj.asInstanceOf[TelepadDeployable].Active = true
|
||||||
|
context.parent ! RouterTelepadActivation.ActivateTeleportSystem(entry.obj, entry.zone)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object RouterTelepadActivation {
|
||||||
|
final case class Entry(_obj : PlanetSideGameObject, _zone : Zone, _duration : Long) extends SupportActor.Entry(_obj, _zone, _duration)
|
||||||
|
|
||||||
|
final case class AddTask(obj : PlanetSideGameObject, zone : Zone, duration : Option[FiniteDuration] = None)
|
||||||
|
|
||||||
|
final case class TryActivate()
|
||||||
|
|
||||||
|
final case class ActivateTeleportSystem(telepad : PlanetSideGameObject, zone : Zone)
|
||||||
|
}
|
||||||
|
|
@ -73,17 +73,12 @@ abstract class SupportActor[A <: SupportActor.Entry] extends Actor {
|
||||||
//a - find targets from entries
|
//a - find targets from entries
|
||||||
val locatedTargets = for {
|
val locatedTargets = for {
|
||||||
a <- targets
|
a <- targets
|
||||||
b <- list//.filter(entry => entry.zone == zone)
|
b <- list
|
||||||
if b.obj.HasGUID && a.obj.HasGUID && comparator.Test(b, a)
|
if b.obj.HasGUID && a.obj.HasGUID && comparator.Test(b, a)
|
||||||
} yield b
|
} yield b
|
||||||
if(locatedTargets.nonEmpty) {
|
if(locatedTargets.nonEmpty) {
|
||||||
//b - entries, after the found targets are removed (cull any non-GUID entries while at it)
|
//b - entries, after the found targets are removed (cull any non-GUID entries while at it)
|
||||||
val retained = for {
|
(locatedTargets, list filterNot locatedTargets.toSet)
|
||||||
a <- locatedTargets
|
|
||||||
b <- list
|
|
||||||
if b.obj.HasGUID && a.obj.HasGUID && !comparator.Test(b, a)
|
|
||||||
} yield b
|
|
||||||
(locatedTargets, retained)
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
(Nil, list)
|
(Nil, list)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
// Copyright (c) 2017 PSForever
|
// Copyright (c) 2017 PSForever
|
||||||
package services.vehicle
|
package services.vehicle
|
||||||
|
|
||||||
import net.psforever.objects.{PlanetSideGameObject, Vehicle}
|
import net.psforever.objects.{PlanetSideGameObject, TelepadDeployable, Vehicle}
|
||||||
import net.psforever.objects.equipment.Equipment
|
import net.psforever.objects.equipment.Equipment
|
||||||
|
import net.psforever.objects.vehicles.Utility
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.Zone
|
||||||
import net.psforever.packet.PlanetSideGamePacket
|
import net.psforever.packet.PlanetSideGamePacket
|
||||||
import net.psforever.packet.game.PlanetSideGUID
|
import net.psforever.packet.game.PlanetSideGUID
|
||||||
|
|
@ -26,7 +27,7 @@ object VehicleAction {
|
||||||
final case class PlanetsideAttribute(player_guid : PlanetSideGUID, target_guid : PlanetSideGUID, attribute_type : Int, attribute_value : Long) extends Action
|
final case class PlanetsideAttribute(player_guid : PlanetSideGUID, target_guid : PlanetSideGUID, attribute_type : Int, attribute_value : Long) extends Action
|
||||||
final case class SeatPermissions(player_guid : PlanetSideGUID, vehicle_guid : PlanetSideGUID, seat_group : Int, permission : Long) extends Action
|
final case class SeatPermissions(player_guid : PlanetSideGUID, vehicle_guid : PlanetSideGUID, seat_group : Int, permission : Long) extends Action
|
||||||
final case class StowEquipment(player_guid : PlanetSideGUID, vehicle_guid : PlanetSideGUID, slot : Int, item : Equipment) extends Action
|
final case class StowEquipment(player_guid : PlanetSideGUID, vehicle_guid : PlanetSideGUID, slot : Int, item : Equipment) extends Action
|
||||||
final case class UnloadVehicle(player_guid : PlanetSideGUID, continent : Zone, vehicle : Vehicle) extends Action
|
final case class UnloadVehicle(player_guid : PlanetSideGUID, continent : Zone, vehicle : Vehicle, vehicle_guid : PlanetSideGUID) extends Action
|
||||||
final case class UnstowEquipment(player_guid : PlanetSideGUID, item_guid : PlanetSideGUID) extends Action
|
final case class UnstowEquipment(player_guid : PlanetSideGUID, item_guid : PlanetSideGUID) extends Action
|
||||||
final case class VehicleState(player_guid : PlanetSideGUID, vehicle_guid : PlanetSideGUID, unk1 : Int, pos : Vector3, ang : Vector3, vel : Option[Vector3], unk2 : Option[Int], unk3 : Int, unk4 : Int, wheel_direction : Int, unk5 : Boolean, unk6 : Boolean) extends Action
|
final case class VehicleState(player_guid : PlanetSideGUID, vehicle_guid : PlanetSideGUID, unk1 : Int, pos : Vector3, ang : Vector3, vel : Option[Vector3], unk2 : Option[Int], unk3 : Int, unk4 : Int, wheel_direction : Int, unk5 : Boolean, unk6 : Boolean) extends Action
|
||||||
final case class SendResponse(player_guid: PlanetSideGUID, msg : PlanetSideGamePacket) extends Action
|
final case class SendResponse(player_guid: PlanetSideGUID, msg : PlanetSideGamePacket) extends Action
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
package services.vehicle
|
package services.vehicle
|
||||||
|
|
||||||
import net.psforever.objects.serverobject.tube.SpawnTube
|
import net.psforever.objects.serverobject.tube.SpawnTube
|
||||||
import net.psforever.objects.{PlanetSideGameObject, Vehicle}
|
import net.psforever.objects.vehicles.Utility
|
||||||
|
import net.psforever.objects.{PlanetSideGameObject, TelepadDeployable, Vehicle}
|
||||||
import net.psforever.packet.PlanetSideGamePacket
|
import net.psforever.packet.PlanetSideGamePacket
|
||||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||||
import net.psforever.packet.game.objectcreate.ConstructorData
|
import net.psforever.packet.game.objectcreate.ConstructorData
|
||||||
|
|
@ -30,7 +31,7 @@ object VehicleResponse {
|
||||||
final case class RevealPlayer(player_guid : PlanetSideGUID) extends Response
|
final case class RevealPlayer(player_guid : PlanetSideGUID) extends Response
|
||||||
final case class SeatPermissions(vehicle_guid : PlanetSideGUID, seat_group : Int, permission : Long) extends Response
|
final case class SeatPermissions(vehicle_guid : PlanetSideGUID, seat_group : Int, permission : Long) extends Response
|
||||||
final case class StowEquipment(vehicle_guid : PlanetSideGUID, slot : Int, itype : Int, iguid : PlanetSideGUID, idata : ConstructorData) extends Response
|
final case class StowEquipment(vehicle_guid : PlanetSideGUID, slot : Int, itype : Int, iguid : PlanetSideGUID, idata : ConstructorData) extends Response
|
||||||
final case class UnloadVehicle(vehicle_guid : PlanetSideGUID) extends Response
|
final case class UnloadVehicle(vehicle : Vehicle, vehicle_guid : PlanetSideGUID) extends Response
|
||||||
final case class UnstowEquipment(item_guid : PlanetSideGUID) extends Response
|
final case class UnstowEquipment(item_guid : PlanetSideGUID) extends Response
|
||||||
final case class VehicleState(vehicle_guid : PlanetSideGUID, unk1 : Int, pos : Vector3, ang : Vector3, vel : Option[Vector3], unk2 : Option[Int], unk3 : Int, unk4 : Int, wheel_direction : Int, unk5 : Boolean, unk6 : Boolean) extends Response
|
final case class VehicleState(vehicle_guid : PlanetSideGUID, unk1 : Int, pos : Vector3, ang : Vector3, vel : Option[Vector3], unk2 : Option[Int], unk3 : Int, unk4 : Int, wheel_direction : Int, unk5 : Boolean, unk6 : Boolean) extends Response
|
||||||
final case class SendResponse(msg: PlanetSideGamePacket) extends Response
|
final case class SendResponse(msg: PlanetSideGamePacket) extends Response
|
||||||
|
|
|
||||||
|
|
@ -105,10 +105,10 @@ class VehicleService extends Actor {
|
||||||
VehicleEvents.publish(
|
VehicleEvents.publish(
|
||||||
VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.StowEquipment(vehicle_guid, slot, definition.ObjectId, item.GUID, definition.Packet.DetailedConstructorData(item).get))
|
VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.StowEquipment(vehicle_guid, slot, definition.ObjectId, item.GUID, definition.Packet.DetailedConstructorData(item).get))
|
||||||
)
|
)
|
||||||
case VehicleAction.UnloadVehicle(player_guid, continent, vehicle) =>
|
case VehicleAction.UnloadVehicle(player_guid, continent, vehicle, vehicle_guid) =>
|
||||||
vehicleDecon ! RemoverActor.ClearSpecific(List(vehicle), continent) //precaution
|
vehicleDecon ! RemoverActor.ClearSpecific(List(vehicle), continent) //precaution
|
||||||
VehicleEvents.publish(
|
VehicleEvents.publish(
|
||||||
VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.UnloadVehicle(vehicle.GUID))
|
VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.UnloadVehicle(vehicle, vehicle_guid))
|
||||||
)
|
)
|
||||||
case VehicleAction.UnstowEquipment(player_guid, item_guid) =>
|
case VehicleAction.UnstowEquipment(player_guid, item_guid) =>
|
||||||
VehicleEvents.publish(
|
VehicleEvents.publish(
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ package services.vehicle.support
|
||||||
import net.psforever.objects.Vehicle
|
import net.psforever.objects.Vehicle
|
||||||
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
|
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.Zone
|
||||||
|
import net.psforever.types.DriveState
|
||||||
import services.{RemoverActor, Service}
|
import services.{RemoverActor, Service}
|
||||||
import services.vehicle.{VehicleAction, VehicleServiceMessage}
|
import services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||||
|
|
||||||
|
|
@ -43,8 +44,9 @@ class VehicleRemover extends RemoverActor {
|
||||||
override def SecondJob(entry : RemoverActor.Entry) : Unit = {
|
override def SecondJob(entry : RemoverActor.Entry) : Unit = {
|
||||||
val vehicle = entry.obj.asInstanceOf[Vehicle]
|
val vehicle = entry.obj.asInstanceOf[Vehicle]
|
||||||
val zone = entry.zone
|
val zone = entry.zone
|
||||||
|
vehicle.DeploymentState = DriveState.Mobile
|
||||||
zone.Transport ! Zone.Vehicle.Despawn(vehicle)
|
zone.Transport ! Zone.Vehicle.Despawn(vehicle)
|
||||||
context.parent ! VehicleServiceMessage(zone.Id, VehicleAction.UnloadVehicle(Service.defaultPlayerGUID, zone, vehicle))
|
context.parent ! VehicleServiceMessage(zone.Id, VehicleAction.UnloadVehicle(Service.defaultPlayerGUID, zone, vehicle, vehicle.GUID))
|
||||||
super.SecondJob(entry)
|
super.SecondJob(entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
package base
|
package base
|
||||||
|
|
||||||
// Copyright (c) 2017 PSForever
|
import akka.actor.{Actor, ActorRef, ActorSystem, Props}
|
||||||
import akka.actor.ActorSystem
|
|
||||||
import akka.testkit.{ImplicitSender, TestKit}
|
import akka.testkit.{ImplicitSender, TestKit}
|
||||||
import com.typesafe.config.ConfigFactory
|
import com.typesafe.config.ConfigFactory
|
||||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||||
|
|
@ -48,4 +48,28 @@ object ActorTest {
|
||||||
}
|
}
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A middleman Actor that accepts a `Props` object to instantiate and accepts messages back from it.
|
||||||
|
* The purpose is to bypass a message receive issue with the `ActorTest` / `TestKit` class
|
||||||
|
* that does not properly queue messages dispatched to it
|
||||||
|
* when messages may be sent to it via a `context.parent` call.
|
||||||
|
* Please do not wrap and parameterize Props objects like this during normal Ops.
|
||||||
|
* @param actorProps the uninitialized `Actor` that uses `context.parent` to direct communication
|
||||||
|
* @param sendTo where to send mesages that have originated from an `actorProps` object;
|
||||||
|
* typically should point back to the test environment constructed by `TestKit`
|
||||||
|
*/
|
||||||
|
class SupportActorInterface(actorProps : Props, sendTo : ActorRef) extends Actor {
|
||||||
|
val test = context.actorOf(actorProps, "support-actor")
|
||||||
|
|
||||||
|
def receive : Receive = {
|
||||||
|
case msg =>
|
||||||
|
(if(sender == test) {
|
||||||
|
sendTo
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
test
|
||||||
|
}) ! msg
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package game.objectcreate
|
||||||
|
|
||||||
|
import net.psforever.packet.PacketCoding
|
||||||
|
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||||
|
import net.psforever.packet.game.objectcreate._
|
||||||
|
import org.specs2.mutable._
|
||||||
|
import scodec.bits._
|
||||||
|
|
||||||
|
class ContainedTelepadDeployableDataTest extends Specification {
|
||||||
|
val string = hex"178f0000004080f42b00182cb0202000100000"
|
||||||
|
|
||||||
|
"ContainedTelepadDeployableData" should {
|
||||||
|
"decode" in {
|
||||||
|
PacketCoding.DecodePacket(string).require match {
|
||||||
|
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||||
|
len mustEqual 143
|
||||||
|
cls mustEqual 744
|
||||||
|
guid mustEqual PlanetSideGUID(432)
|
||||||
|
parent.isDefined mustEqual true
|
||||||
|
parent.get.guid mustEqual PlanetSideGUID(385)
|
||||||
|
parent.get.slot mustEqual 2
|
||||||
|
data.isDefined mustEqual true
|
||||||
|
data.get.isInstanceOf[ContainedTelepadDeployableData] mustEqual true
|
||||||
|
data.get.asInstanceOf[ContainedTelepadDeployableData].unk mustEqual 101
|
||||||
|
data.get.asInstanceOf[ContainedTelepadDeployableData].router_guid mustEqual PlanetSideGUID(385)
|
||||||
|
case _ =>
|
||||||
|
ko
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"encode" in {
|
||||||
|
val obj = ContainedTelepadDeployableData(101, PlanetSideGUID(385))
|
||||||
|
val msg = ObjectCreateMessage(744, PlanetSideGUID(432), ObjectCreateMessageParent(PlanetSideGUID(385), 2), obj)
|
||||||
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
pkt mustEqual string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package game.objectcreate
|
||||||
|
|
||||||
|
import net.psforever.packet._
|
||||||
|
import net.psforever.packet.game._
|
||||||
|
import net.psforever.packet.game.objectcreate._
|
||||||
|
import org.specs2.mutable._
|
||||||
|
import scodec.bits._
|
||||||
|
|
||||||
|
class TelepadDataTest extends Specification {
|
||||||
|
val string = hex"17 86000000 5700 f3a a201 80 0302020000000"
|
||||||
|
//TODO validate the unknown fields before router_guid for testing
|
||||||
|
|
||||||
|
"TelepadData" should {
|
||||||
|
"decode" in {
|
||||||
|
PacketCoding.DecodePacket(string).require match {
|
||||||
|
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||||
|
len mustEqual 134
|
||||||
|
cls mustEqual ObjectClass.router_telepad
|
||||||
|
guid mustEqual PlanetSideGUID(418)
|
||||||
|
parent.isDefined mustEqual true
|
||||||
|
parent.get.guid mustEqual PlanetSideGUID(430)
|
||||||
|
parent.get.slot mustEqual 0
|
||||||
|
data.isDefined mustEqual true
|
||||||
|
data.get.isInstanceOf[TelepadData] mustEqual true
|
||||||
|
data.get.asInstanceOf[TelepadData].router_guid mustEqual Some(PlanetSideGUID(385))
|
||||||
|
case _ =>
|
||||||
|
ko
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"encode" in {
|
||||||
|
val obj = TelepadData(0, PlanetSideGUID(385))
|
||||||
|
val msg = ObjectCreateMessage(ObjectClass.router_telepad, PlanetSideGUID(418), ObjectCreateMessageParent(PlanetSideGUID(430), 0), obj)
|
||||||
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
||||||
|
pkt mustEqual string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package game.objectcreate
|
||||||
|
|
||||||
|
import net.psforever.packet._
|
||||||
|
import net.psforever.packet.game._
|
||||||
|
import net.psforever.packet.game.objectcreate._
|
||||||
|
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||||
|
import org.specs2.mutable._
|
||||||
|
import scodec.bits._
|
||||||
|
|
||||||
|
class TelepadDeployableDataTest extends Specification {
|
||||||
|
val string = hex"17 c8000000 f42 6101 fbcfc 0fd43 6903 00 00 79 05 8101 ae01 5700c"
|
||||||
|
//TODO validate the unknown fields before router_guid for testing
|
||||||
|
|
||||||
|
"TelepadData" should {
|
||||||
|
"decode" in {
|
||||||
|
PacketCoding.DecodePacket(string).require match {
|
||||||
|
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||||
|
len mustEqual 200
|
||||||
|
cls mustEqual ObjectClass.router_telepad_deployable
|
||||||
|
guid mustEqual PlanetSideGUID(353)
|
||||||
|
parent.isDefined mustEqual false
|
||||||
|
data.isDefined mustEqual true
|
||||||
|
data.get.isInstanceOf[TelepadDeployableData] mustEqual true
|
||||||
|
val teledata = data.get.asInstanceOf[TelepadDeployableData]
|
||||||
|
teledata.pos.coord mustEqual Vector3(6559.961f, 1960.1172f, 13.640625f)
|
||||||
|
teledata.pos.orient mustEqual Vector3.z(109.6875f)
|
||||||
|
teledata.pos.vel.isDefined mustEqual false
|
||||||
|
teledata.faction mustEqual PlanetSideEmpire.TR
|
||||||
|
teledata.bops mustEqual false
|
||||||
|
teledata.destroyed mustEqual false
|
||||||
|
teledata.unk1 mustEqual 2
|
||||||
|
teledata.unk2 mustEqual true
|
||||||
|
teledata.router_guid mustEqual PlanetSideGUID(385)
|
||||||
|
teledata.owner_guid mustEqual PlanetSideGUID(430)
|
||||||
|
teledata.unk3 mustEqual 87
|
||||||
|
teledata.unk4 mustEqual 12
|
||||||
|
case _ =>
|
||||||
|
ko
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"encode" in {
|
||||||
|
val obj = TelepadDeployableData(
|
||||||
|
PlacementData(
|
||||||
|
Vector3(6559.961f, 1960.1172f, 13.640625f),
|
||||||
|
Vector3.z(109.6875f)
|
||||||
|
),
|
||||||
|
PlanetSideEmpire.TR,
|
||||||
|
false, false, 2, true,
|
||||||
|
PlanetSideGUID(385),
|
||||||
|
PlanetSideGUID(430),
|
||||||
|
87, 12
|
||||||
|
)
|
||||||
|
val msg = ObjectCreateMessage(ObjectClass.router_telepad_deployable, PlanetSideGUID(353), obj)
|
||||||
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
||||||
|
pkt mustEqual string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package game.objectcreatedetailed
|
||||||
|
|
||||||
|
import net.psforever.packet._
|
||||||
|
import net.psforever.packet.game._
|
||||||
|
import net.psforever.packet.game.objectcreate._
|
||||||
|
import org.specs2.mutable._
|
||||||
|
import scodec.bits._
|
||||||
|
|
||||||
|
class DetailedTelepadDataTest extends Specification {
|
||||||
|
val string = hex"18 97000000 4f00 f3a e301 80 4a680400000200008"
|
||||||
|
val string_short = hex"18 87000000 2a00 f3a 5d01 89 8000000200008"
|
||||||
|
//TODO validate the unknown fields before router_guid for testing
|
||||||
|
|
||||||
|
"DetailedTelepadData" should {
|
||||||
|
"decode" in {
|
||||||
|
PacketCoding.DecodePacket(string).require match {
|
||||||
|
case ObjectCreateDetailedMessage(len, cls, guid, parent, data) =>
|
||||||
|
len mustEqual 151
|
||||||
|
cls mustEqual ObjectClass.router_telepad
|
||||||
|
guid mustEqual PlanetSideGUID(483)
|
||||||
|
parent.isDefined mustEqual true
|
||||||
|
parent.get.guid mustEqual PlanetSideGUID(414)
|
||||||
|
parent.get.slot mustEqual 0
|
||||||
|
data.isDefined mustEqual true
|
||||||
|
data.get.isInstanceOf[DetailedTelepadData] mustEqual true
|
||||||
|
data.get.asInstanceOf[DetailedTelepadData].router_guid mustEqual Some(PlanetSideGUID(564))
|
||||||
|
case _ =>
|
||||||
|
ko
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"decode (short)" in {
|
||||||
|
PacketCoding.DecodePacket(string_short).require match {
|
||||||
|
case ObjectCreateDetailedMessage(len, cls, guid, parent, data) =>
|
||||||
|
len mustEqual 135
|
||||||
|
cls mustEqual ObjectClass.router_telepad
|
||||||
|
guid mustEqual PlanetSideGUID(349)
|
||||||
|
parent.isDefined mustEqual true
|
||||||
|
parent.get.guid mustEqual PlanetSideGUID(340)
|
||||||
|
parent.get.slot mustEqual 9
|
||||||
|
data.isDefined mustEqual true
|
||||||
|
data.get.isInstanceOf[DetailedTelepadData] mustEqual true
|
||||||
|
data.get.asInstanceOf[DetailedTelepadData].router_guid mustEqual None
|
||||||
|
case _ =>
|
||||||
|
ko
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"encode" in {
|
||||||
|
val obj = DetailedTelepadData(18, PlanetSideGUID(564))
|
||||||
|
val msg = ObjectCreateDetailedMessage(ObjectClass.router_telepad, PlanetSideGUID(483), ObjectCreateMessageParent(PlanetSideGUID(414), 0), obj)
|
||||||
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
||||||
|
pkt mustEqual string
|
||||||
|
}
|
||||||
|
|
||||||
|
"encode (short)" in {
|
||||||
|
val obj = DetailedTelepadData(32)
|
||||||
|
val msg = ObjectCreateDetailedMessage(ObjectClass.router_telepad, PlanetSideGUID(349), ObjectCreateMessageParent(PlanetSideGUID(340), 9), obj)
|
||||||
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
||||||
|
pkt mustEqual string_short
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,7 @@ import net.psforever.objects.equipment._
|
||||||
import net.psforever.objects.inventory.InventoryTile
|
import net.psforever.objects.inventory.InventoryTile
|
||||||
import net.psforever.objects.serverobject.terminals.Terminal
|
import net.psforever.objects.serverobject.terminals.Terminal
|
||||||
import net.psforever.objects.serverobject.tube.SpawnTube
|
import net.psforever.objects.serverobject.tube.SpawnTube
|
||||||
|
import net.psforever.objects.vehicles.UtilityType
|
||||||
import net.psforever.packet.game.PlanetSideGUID
|
import net.psforever.packet.game.PlanetSideGUID
|
||||||
import net.psforever.packet.game.objectcreate._
|
import net.psforever.packet.game.objectcreate._
|
||||||
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire, Vector3}
|
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire, Vector3}
|
||||||
|
|
@ -166,6 +167,35 @@ class ConverterTest extends Specification {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"Telepad" should {
|
||||||
|
"convert (success)" in {
|
||||||
|
val obj = new Telepad(GlobalDefinitions.router_telepad)
|
||||||
|
obj.Router = PlanetSideGUID(1001)
|
||||||
|
obj.Definition.Packet.ConstructorData(obj) match {
|
||||||
|
case Success(pkt) =>
|
||||||
|
pkt mustEqual TelepadData(0, PlanetSideGUID(1001))
|
||||||
|
case _ =>
|
||||||
|
ko
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
||||||
|
case Success(pkt) =>
|
||||||
|
pkt mustEqual DetailedTelepadData(0, PlanetSideGUID(1001))
|
||||||
|
case _ =>
|
||||||
|
ko
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"convert (failure; no router)" in {
|
||||||
|
val obj = new Telepad(GlobalDefinitions.router_telepad)
|
||||||
|
//obj.Router = PlanetSideGUID(1001)
|
||||||
|
obj.Definition.Packet.ConstructorData(obj).isFailure mustEqual true
|
||||||
|
|
||||||
|
|
||||||
|
obj.Definition.Packet.DetailedConstructorData(obj).isFailure mustEqual true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
"SmallDeployable" should {
|
"SmallDeployable" should {
|
||||||
"convert" in {
|
"convert" in {
|
||||||
val obj = new SensorDeployable(GlobalDefinitions.motionalarmsensor)
|
val obj = new SensorDeployable(GlobalDefinitions.motionalarmsensor)
|
||||||
|
|
@ -299,6 +329,79 @@ class ConverterTest extends Specification {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"TelepadDeployable" should {
|
||||||
|
"convert (success)" in {
|
||||||
|
val obj = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||||
|
obj.Faction = PlanetSideEmpire.TR
|
||||||
|
obj.GUID = PlanetSideGUID(90)
|
||||||
|
obj.Router = PlanetSideGUID(1001)
|
||||||
|
obj.Owner = PlanetSideGUID(5001)
|
||||||
|
obj.Health = 1
|
||||||
|
obj.Definition.Packet.ConstructorData(obj) match {
|
||||||
|
case Success(pkt) =>
|
||||||
|
pkt mustEqual TelepadDeployableData(
|
||||||
|
PlacementData(Vector3.Zero, Vector3.Zero),
|
||||||
|
PlanetSideEmpire.TR,
|
||||||
|
bops = false,
|
||||||
|
destroyed = false,
|
||||||
|
unk1 = 2, unk2 = true,
|
||||||
|
router_guid = PlanetSideGUID(1001),
|
||||||
|
owner_guid = PlanetSideGUID(5001),
|
||||||
|
unk3 = 87, unk4 = 12
|
||||||
|
)
|
||||||
|
case _ =>
|
||||||
|
ko
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"convert (success; destroyed)" in {
|
||||||
|
val obj = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||||
|
obj.Faction = PlanetSideEmpire.TR
|
||||||
|
obj.GUID = PlanetSideGUID(90)
|
||||||
|
obj.Router = PlanetSideGUID(1001)
|
||||||
|
obj.Owner = PlanetSideGUID(5001)
|
||||||
|
obj.Health = 0
|
||||||
|
obj.Definition.Packet.ConstructorData(obj) match {
|
||||||
|
case Success(pkt) =>
|
||||||
|
pkt mustEqual TelepadDeployableData(
|
||||||
|
PlacementData(Vector3.Zero, Vector3.Zero),
|
||||||
|
PlanetSideEmpire.TR,
|
||||||
|
bops = false,
|
||||||
|
destroyed = true,
|
||||||
|
unk1 = 2, unk2 = true,
|
||||||
|
router_guid = PlanetSideGUID(1001),
|
||||||
|
owner_guid = PlanetSideGUID(0),
|
||||||
|
unk3 = 0, unk4 = 6
|
||||||
|
)
|
||||||
|
case _ =>
|
||||||
|
ko
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"convert (failure; no router)" in {
|
||||||
|
val obj = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||||
|
obj.Faction = PlanetSideEmpire.TR
|
||||||
|
obj.GUID = PlanetSideGUID(90)
|
||||||
|
//obj.Router = PlanetSideGUID(1001)
|
||||||
|
obj.Owner = PlanetSideGUID(5001)
|
||||||
|
obj.Health = 1
|
||||||
|
obj.Definition.Packet.ConstructorData(obj).isFailure mustEqual true
|
||||||
|
|
||||||
|
obj.Router = PlanetSideGUID(0)
|
||||||
|
obj.Definition.Packet.ConstructorData(obj).isFailure mustEqual true
|
||||||
|
}
|
||||||
|
|
||||||
|
"convert (failure; detailed)" in {
|
||||||
|
val obj = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||||
|
obj.Faction = PlanetSideEmpire.TR
|
||||||
|
obj.GUID = PlanetSideGUID(90)
|
||||||
|
obj.Router = PlanetSideGUID(1001)
|
||||||
|
obj.Owner = PlanetSideGUID(5001)
|
||||||
|
obj.Health = 1
|
||||||
|
obj.Definition.Packet.DetailedConstructorData(obj).isFailure mustEqual true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
"Player" should {
|
"Player" should {
|
||||||
val avatar = Avatar("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
val avatar = Avatar("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||||
val obj : Player = {
|
val obj : Player = {
|
||||||
|
|
@ -525,6 +628,15 @@ class ConverterTest extends Specification {
|
||||||
ams.Definition.Packet.ConstructorData(ams).isSuccess mustEqual true
|
ams.Definition.Packet.ConstructorData(ams).isSuccess mustEqual true
|
||||||
//did not initialize the utilities, but the converter did not fail
|
//did not initialize the utilities, but the converter did not fail
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"convert to packet (4)" in {
|
||||||
|
val
|
||||||
|
router = Vehicle(GlobalDefinitions.router)
|
||||||
|
router.GUID = PlanetSideGUID(413)
|
||||||
|
router.Utility(UtilityType.teleportpad_terminal).get.GUID = PlanetSideGUID(1413)
|
||||||
|
router.Utility(UtilityType.internal_router_telepad_deployable).get.GUID = PlanetSideGUID(2413)
|
||||||
|
router.Definition.Packet.ConstructorData(router).isSuccess mustEqual true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"DestroyedVehicle" should {
|
"DestroyedVehicle" should {
|
||||||
|
|
|
||||||
|
|
@ -318,6 +318,38 @@ class TurretControlBetrayalMountTest extends ActorTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TelepadDeployableTest extends Specification {
|
||||||
|
"Telepad" should {
|
||||||
|
"construct" in {
|
||||||
|
val obj = new Telepad(GlobalDefinitions.router_telepad)
|
||||||
|
obj.Active mustEqual false
|
||||||
|
obj.Router mustEqual None
|
||||||
|
}
|
||||||
|
|
||||||
|
"activate and deactivate" in {
|
||||||
|
val obj = new Telepad(GlobalDefinitions.router_telepad)
|
||||||
|
obj.Active mustEqual false
|
||||||
|
obj.Active = true
|
||||||
|
obj.Active mustEqual true
|
||||||
|
obj.Active = false
|
||||||
|
obj.Active mustEqual false
|
||||||
|
}
|
||||||
|
|
||||||
|
"keep track of a Router" in {
|
||||||
|
val obj = new Telepad(GlobalDefinitions.router_telepad)
|
||||||
|
obj.Router mustEqual None
|
||||||
|
obj.Router = PlanetSideGUID(1)
|
||||||
|
obj.Router mustEqual Some(PlanetSideGUID(1))
|
||||||
|
obj.Router = None
|
||||||
|
obj.Router mustEqual None
|
||||||
|
obj.Router = PlanetSideGUID(1)
|
||||||
|
obj.Router mustEqual Some(PlanetSideGUID(1))
|
||||||
|
obj.Router = PlanetSideGUID(0)
|
||||||
|
obj.Router mustEqual None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object DeployableTest {
|
object DeployableTest {
|
||||||
class TurretInitializer(obj : TurretDeployable) extends Actor {
|
class TurretInitializer(obj : TurretDeployable) extends Actor {
|
||||||
def receive : Receive = {
|
def receive : Receive = {
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,12 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.Initialize(Set())
|
obj.Initialize(Set())
|
||||||
val list = obj.UpdateUI()
|
val list = obj.UpdateUI()
|
||||||
list.size mustEqual DeployedItem.values.size - 3 //extra field turrets
|
list.size mustEqual DeployedItem.values.size - 3 //extra field turrets
|
||||||
list.foreach({case(_,curr,_,max) =>
|
val (routers, allOthers) = list.partition({ case((_,_,_,max)) => max == 1024 })
|
||||||
|
allOthers.foreach({case(_,curr,_,max) =>
|
||||||
curr mustEqual 0
|
curr mustEqual 0
|
||||||
max mustEqual 0
|
max mustEqual 0
|
||||||
})
|
})
|
||||||
|
routers.length mustEqual 1
|
||||||
ok
|
ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,7 +46,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
}
|
}
|
||||||
|
|
||||||
"initialization (AssaultEngineering)" in {
|
"initialization (AssaultEngineering)" in {
|
||||||
|
|
@ -64,7 +66,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
}
|
}
|
||||||
|
|
||||||
"initialization (FortificationEngineering)" in {
|
"initialization (FortificationEngineering)" in {
|
||||||
|
|
@ -84,7 +86,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
}
|
}
|
||||||
|
|
||||||
"initialization (AdvancedEngineering)" in {
|
"initialization (AdvancedEngineering)" in {
|
||||||
|
|
@ -104,7 +106,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
}
|
}
|
||||||
|
|
||||||
"initialization (AdvancedHacking)" in {
|
"initialization (AdvancedHacking)" in {
|
||||||
|
|
@ -124,7 +126,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
}
|
}
|
||||||
|
|
||||||
"initialization (without CombatEngineering)" in {
|
"initialization (without CombatEngineering)" in {
|
||||||
|
|
@ -144,7 +146,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
}
|
}
|
||||||
|
|
||||||
"initialization (GroundSupport)" in {
|
"initialization (GroundSupport)" in {
|
||||||
|
|
@ -164,6 +166,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
||||||
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
}
|
}
|
||||||
|
|
||||||
"can not initialize twice" in {
|
"can not initialize twice" in {
|
||||||
|
|
@ -183,7 +186,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
|
|
||||||
obj.Initialize(Set(AdvancedEngineering)) mustEqual false
|
obj.Initialize(Set(AdvancedEngineering)) mustEqual false
|
||||||
obj.CountDeployable(DeployedItem.boomer)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.boomer)._2 mustEqual 0
|
||||||
|
|
@ -200,7 +203,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
}
|
}
|
||||||
|
|
||||||
"uninitialized fields can not accept deployables" in {
|
"uninitialized fields can not accept deployables" in {
|
||||||
|
|
@ -240,7 +243,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
|
|
||||||
obj.AddToDeployableQuantities(
|
obj.AddToDeployableQuantities(
|
||||||
CombatEngineering,
|
CombatEngineering,
|
||||||
|
|
@ -260,7 +263,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
|
|
||||||
obj.AddToDeployableQuantities(
|
obj.AddToDeployableQuantities(
|
||||||
FortificationEngineering,
|
FortificationEngineering,
|
||||||
|
|
@ -280,7 +283,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
|
|
||||||
obj.AddToDeployableQuantities(
|
obj.AddToDeployableQuantities(
|
||||||
AssaultEngineering,
|
AssaultEngineering,
|
||||||
|
|
@ -300,7 +303,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
|
|
||||||
obj.AddToDeployableQuantities(
|
obj.AddToDeployableQuantities(
|
||||||
AssaultEngineering,
|
AssaultEngineering,
|
||||||
|
|
@ -320,7 +323,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
|
|
||||||
obj.AddToDeployableQuantities(
|
obj.AddToDeployableQuantities(
|
||||||
AdvancedHacking,
|
AdvancedHacking,
|
||||||
|
|
@ -340,7 +343,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
}
|
}
|
||||||
|
|
||||||
"change accessible fields by adding by certification type (GroundSupport)" in {
|
"change accessible fields by adding by certification type (GroundSupport)" in {
|
||||||
|
|
@ -360,7 +363,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
|
|
||||||
obj.AddToDeployableQuantities(
|
obj.AddToDeployableQuantities(
|
||||||
GroundSupport,
|
GroundSupport,
|
||||||
|
|
@ -400,7 +403,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
|
|
||||||
obj.AddToDeployableQuantities(
|
obj.AddToDeployableQuantities(
|
||||||
AdvancedEngineering,
|
AdvancedEngineering,
|
||||||
|
|
@ -420,7 +423,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
}
|
}
|
||||||
|
|
||||||
"change accessible fields by removing by certification types (all)" in {
|
"change accessible fields by removing by certification types (all)" in {
|
||||||
|
|
@ -440,7 +443,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
|
|
||||||
obj.RemoveFromDeployableQuantities(
|
obj.RemoveFromDeployableQuantities(
|
||||||
GroundSupport,
|
GroundSupport,
|
||||||
|
|
@ -460,7 +463,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
|
|
||||||
obj.RemoveFromDeployableQuantities(
|
obj.RemoveFromDeployableQuantities(
|
||||||
AdvancedHacking,
|
AdvancedHacking,
|
||||||
|
|
@ -480,7 +483,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
|
|
||||||
obj.RemoveFromDeployableQuantities(
|
obj.RemoveFromDeployableQuantities(
|
||||||
FortificationEngineering,
|
FortificationEngineering,
|
||||||
|
|
@ -500,7 +503,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
|
|
||||||
obj.RemoveFromDeployableQuantities(
|
obj.RemoveFromDeployableQuantities(
|
||||||
AssaultEngineering,
|
AssaultEngineering,
|
||||||
|
|
@ -520,7 +523,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
|
|
||||||
obj.RemoveFromDeployableQuantities(
|
obj.RemoveFromDeployableQuantities(
|
||||||
CombatEngineering,
|
CombatEngineering,
|
||||||
|
|
@ -540,7 +543,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
}
|
}
|
||||||
|
|
||||||
"change accessible fields by removing by certification type (AdvancedEngineering)" in {
|
"change accessible fields by removing by certification type (AdvancedEngineering)" in {
|
||||||
|
|
@ -560,7 +563,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 1
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 1
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
|
|
||||||
obj.RemoveFromDeployableQuantities(
|
obj.RemoveFromDeployableQuantities(
|
||||||
AdvancedEngineering,
|
AdvancedEngineering,
|
||||||
|
|
@ -580,7 +583,7 @@ class DeployableToolboxTest extends Specification {
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.portable_manned_turret_vs)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.deployable_shield_generator)._2 mustEqual 0
|
||||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 0
|
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||||
}
|
}
|
||||||
|
|
||||||
"can not remove deployables from an unpopulated field" in {
|
"can not remove deployables from an unpopulated field" in {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import net.psforever.objects._
|
||||||
import net.psforever.objects.equipment._
|
import net.psforever.objects.equipment._
|
||||||
import net.psforever.objects.inventory.InventoryTile
|
import net.psforever.objects.inventory.InventoryTile
|
||||||
import net.psforever.objects.GlobalDefinitions._
|
import net.psforever.objects.GlobalDefinitions._
|
||||||
import net.psforever.objects.ce.DeployedItem
|
import net.psforever.objects.ce.{DeployedItem, TelepadLike}
|
||||||
import net.psforever.objects.definition._
|
import net.psforever.objects.definition._
|
||||||
import net.psforever.packet.game.PlanetSideGUID
|
import net.psforever.packet.game.PlanetSideGUID
|
||||||
import net.psforever.types.CertificationType
|
import net.psforever.types.CertificationType
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package objects
|
||||||
|
|
||||||
import akka.actor.{Actor, ActorRef, Props}
|
import akka.actor.{Actor, ActorRef, Props}
|
||||||
import base.ActorTest
|
import base.ActorTest
|
||||||
import net.psforever.objects.{GlobalDefinitions, Vehicle}
|
import net.psforever.objects._
|
||||||
import net.psforever.objects.serverobject.terminals.Terminal
|
import net.psforever.objects.serverobject.terminals.Terminal
|
||||||
import net.psforever.objects.vehicles._
|
import net.psforever.objects.vehicles._
|
||||||
import net.psforever.packet.game.PlanetSideGUID
|
import net.psforever.packet.game.PlanetSideGUID
|
||||||
|
|
@ -18,7 +18,7 @@ class UtilityTest extends Specification {
|
||||||
obj.UtilType mustEqual UtilityType.order_terminala
|
obj.UtilType mustEqual UtilityType.order_terminala
|
||||||
obj().isInstanceOf[Terminal] mustEqual true
|
obj().isInstanceOf[Terminal] mustEqual true
|
||||||
obj().asInstanceOf[Terminal].Definition.ObjectId mustEqual 613
|
obj().asInstanceOf[Terminal].Definition.ObjectId mustEqual 613
|
||||||
obj().asInstanceOf[Terminal].Actor == ActorRef.noSender
|
obj().asInstanceOf[Terminal].Actor mustEqual ActorRef.noSender
|
||||||
}
|
}
|
||||||
|
|
||||||
"create an order_terminalb object" in {
|
"create an order_terminalb object" in {
|
||||||
|
|
@ -26,7 +26,7 @@ class UtilityTest extends Specification {
|
||||||
obj.UtilType mustEqual UtilityType.order_terminalb
|
obj.UtilType mustEqual UtilityType.order_terminalb
|
||||||
obj().isInstanceOf[Terminal] mustEqual true
|
obj().isInstanceOf[Terminal] mustEqual true
|
||||||
obj().asInstanceOf[Terminal].Definition.ObjectId mustEqual 614
|
obj().asInstanceOf[Terminal].Definition.ObjectId mustEqual 614
|
||||||
obj().asInstanceOf[Terminal].Actor == ActorRef.noSender
|
obj().asInstanceOf[Terminal].Actor mustEqual ActorRef.noSender
|
||||||
}
|
}
|
||||||
|
|
||||||
"create a matrix_terminalc object" in {
|
"create a matrix_terminalc object" in {
|
||||||
|
|
@ -34,7 +34,7 @@ class UtilityTest extends Specification {
|
||||||
obj.UtilType mustEqual UtilityType.matrix_terminalc
|
obj.UtilType mustEqual UtilityType.matrix_terminalc
|
||||||
obj().isInstanceOf[Terminal] mustEqual true
|
obj().isInstanceOf[Terminal] mustEqual true
|
||||||
obj().asInstanceOf[Terminal].Definition.ObjectId mustEqual 519
|
obj().asInstanceOf[Terminal].Definition.ObjectId mustEqual 519
|
||||||
obj().asInstanceOf[Terminal].Actor == ActorRef.noSender
|
obj().asInstanceOf[Terminal].Actor mustEqual ActorRef.noSender
|
||||||
}
|
}
|
||||||
|
|
||||||
"create an ams_respawn_tube object" in {
|
"create an ams_respawn_tube object" in {
|
||||||
|
|
@ -43,7 +43,53 @@ class UtilityTest extends Specification {
|
||||||
obj.UtilType mustEqual UtilityType.ams_respawn_tube
|
obj.UtilType mustEqual UtilityType.ams_respawn_tube
|
||||||
obj().isInstanceOf[SpawnTube] mustEqual true
|
obj().isInstanceOf[SpawnTube] mustEqual true
|
||||||
obj().asInstanceOf[SpawnTube].Definition.ObjectId mustEqual 49
|
obj().asInstanceOf[SpawnTube].Definition.ObjectId mustEqual 49
|
||||||
obj().asInstanceOf[SpawnTube].Actor == ActorRef.noSender
|
obj().asInstanceOf[SpawnTube].Actor mustEqual ActorRef.noSender
|
||||||
|
}
|
||||||
|
|
||||||
|
"create a teleportpad_terminal object" in {
|
||||||
|
val obj = Utility(UtilityType.teleportpad_terminal, UtilityTest.vehicle)
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
"teleportpad_terminal produces a telepad object (router_telepad)" in {
|
||||||
|
import net.psforever.packet.game.ItemTransactionMessage
|
||||||
|
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire, TransactionType}
|
||||||
|
val veh = Vehicle(GlobalDefinitions.quadstealth)
|
||||||
|
val obj = Utility(UtilityType.teleportpad_terminal, UtilityTest.vehicle)
|
||||||
|
veh.GUID = PlanetSideGUID(101)
|
||||||
|
obj().Owner = veh //hack
|
||||||
|
obj().GUID = PlanetSideGUID(1)
|
||||||
|
|
||||||
|
val msg = obj().asInstanceOf[Terminal].Buy(
|
||||||
|
Player(Avatar("TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)),
|
||||||
|
ItemTransactionMessage(PlanetSideGUID(853), TransactionType.Buy, 0, "router_telepad", 0, PlanetSideGUID(0))
|
||||||
|
)
|
||||||
|
msg.isInstanceOf[Terminal.BuyEquipment] mustEqual true
|
||||||
|
msg.asInstanceOf[Terminal.BuyEquipment].item.isInstanceOf[Telepad] mustEqual true
|
||||||
|
}
|
||||||
|
|
||||||
|
"create an internal_router_telepad_deployable object" in {
|
||||||
|
val obj = Utility(UtilityType.internal_router_telepad_deployable, UtilityTest.vehicle)
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
"internal_router_telepad_deployable can keep track of an object's GUID (presumedly, it's a Telepad)" in {
|
||||||
|
val obj = Utility(UtilityType.internal_router_telepad_deployable, UtilityTest.vehicle)
|
||||||
|
val inpad = obj().asInstanceOf[Utility.InternalTelepad]
|
||||||
|
|
||||||
|
inpad.Telepad mustEqual None
|
||||||
|
inpad.Telepad = PlanetSideGUID(5)
|
||||||
|
inpad.Telepad mustEqual Some(PlanetSideGUID(5))
|
||||||
|
inpad.Telepad = PlanetSideGUID(6)
|
||||||
|
inpad.Telepad mustEqual Some(PlanetSideGUID(6))
|
||||||
|
inpad.Telepad = None
|
||||||
|
inpad.Telepad mustEqual None
|
||||||
}
|
}
|
||||||
|
|
||||||
"be located with their owner (terminal)" in {
|
"be located with their owner (terminal)" in {
|
||||||
|
|
@ -71,10 +117,25 @@ class UtilityTest extends Specification {
|
||||||
obj().Position mustEqual veh.Position
|
obj().Position mustEqual veh.Position
|
||||||
obj().Orientation mustEqual veh.Orientation
|
obj().Orientation mustEqual veh.Orientation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"be located with their owner (internal telepad)" in {
|
||||||
|
val veh = Vehicle(GlobalDefinitions.quadstealth)
|
||||||
|
val obj = Utility(UtilityType.internal_router_telepad_deployable, veh)
|
||||||
|
obj().Position mustEqual veh.Position
|
||||||
|
obj().Orientation mustEqual veh.Orientation
|
||||||
|
|
||||||
|
import net.psforever.types.Vector3
|
||||||
|
veh.Position = Vector3(1, 2, 3)
|
||||||
|
veh.Orientation = Vector3(4, 5, 6)
|
||||||
|
veh.GUID = PlanetSideGUID(101)
|
||||||
|
obj().Position mustEqual veh.Position
|
||||||
|
obj().Orientation mustEqual veh.Orientation
|
||||||
|
obj().asInstanceOf[Utility.InternalTelepad].Router mustEqual Some(veh.GUID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Utility1Test extends ActorTest {
|
class UtilityTerminalATest extends ActorTest {
|
||||||
"Utility" should {
|
"Utility" should {
|
||||||
"wire an order_terminala Actor" in {
|
"wire an order_terminala Actor" in {
|
||||||
val obj = Utility(UtilityType.order_terminala, UtilityTest.vehicle)
|
val obj = Utility(UtilityType.order_terminala, UtilityTest.vehicle)
|
||||||
|
|
@ -88,7 +149,7 @@ class Utility1Test extends ActorTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Utility2Test extends ActorTest {
|
class UtilityTerminalBTest extends ActorTest {
|
||||||
"Utility" should {
|
"Utility" should {
|
||||||
"wire an order_terminalb Actor" in {
|
"wire an order_terminalb Actor" in {
|
||||||
val obj = Utility(UtilityType.order_terminalb, UtilityTest.vehicle)
|
val obj = Utility(UtilityType.order_terminalb, UtilityTest.vehicle)
|
||||||
|
|
@ -102,7 +163,7 @@ class Utility2Test extends ActorTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Utility3Test extends ActorTest {
|
class UtilityTerminalCTest extends ActorTest {
|
||||||
"Utility" should {
|
"Utility" should {
|
||||||
"wire a matrix_terminalc Actor" in {
|
"wire a matrix_terminalc Actor" in {
|
||||||
val obj = Utility(UtilityType.matrix_terminalc, UtilityTest.vehicle)
|
val obj = Utility(UtilityType.matrix_terminalc, UtilityTest.vehicle)
|
||||||
|
|
@ -116,7 +177,7 @@ class Utility3Test extends ActorTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Utility4Test extends ActorTest {
|
class UtilityRespawnTubeTest extends ActorTest {
|
||||||
"Utility" should {
|
"Utility" should {
|
||||||
"wire an ams_respawn_tube Actor" in {
|
"wire an ams_respawn_tube Actor" in {
|
||||||
val obj = Utility(UtilityType.ams_respawn_tube, UtilityTest.vehicle)
|
val obj = Utility(UtilityType.ams_respawn_tube, UtilityTest.vehicle)
|
||||||
|
|
@ -130,6 +191,38 @@ class Utility4Test extends ActorTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class UtilityTelepadTerminalTest extends ActorTest {
|
||||||
|
"Utility" should {
|
||||||
|
"wire a teleportpad_terminal Actor" in {
|
||||||
|
val obj = Utility(UtilityType.teleportpad_terminal, UtilityTest.vehicle)
|
||||||
|
obj().GUID = PlanetSideGUID(1)
|
||||||
|
assert(obj().Actor == ActorRef.noSender)
|
||||||
|
|
||||||
|
system.actorOf(Props(classOf[UtilityTest.SetupControl], obj), "test") ! ""
|
||||||
|
receiveOne(Duration.create(100, "ms")) //consume and discard
|
||||||
|
assert(obj().Actor != ActorRef.noSender)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UtilityInternalTelepadTest extends ActorTest {
|
||||||
|
"Utility" should {
|
||||||
|
"wire a teleportpad_terminal Actor" in {
|
||||||
|
val veh = Vehicle(GlobalDefinitions.quadstealth)
|
||||||
|
veh.GUID = PlanetSideGUID(101)
|
||||||
|
val obj = Utility(UtilityType.internal_router_telepad_deployable, veh)
|
||||||
|
obj().GUID = PlanetSideGUID(1)
|
||||||
|
assert(obj().Actor == ActorRef.noSender)
|
||||||
|
assert(obj().asInstanceOf[Utility.InternalTelepad].Router.contains(veh.GUID))
|
||||||
|
|
||||||
|
system.actorOf(Props(classOf[UtilityTest.SetupControl], obj), "test") ! ""
|
||||||
|
receiveOne(Duration.create(100, "ms")) //consume and discard
|
||||||
|
assert(obj().Actor == ActorRef.noSender)
|
||||||
|
assert(obj().asInstanceOf[Utility.InternalTelepad].Router.contains(veh.GUID))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object UtilityTest {
|
object UtilityTest {
|
||||||
val vehicle = Vehicle(GlobalDefinitions.quadstealth)
|
val vehicle = Vehicle(GlobalDefinitions.quadstealth)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package service
|
||||||
|
|
||||||
import akka.actor.Props
|
import akka.actor.Props
|
||||||
import base.ActorTest
|
import base.ActorTest
|
||||||
import net.psforever.objects.{GlobalDefinitions, SensorDeployable}
|
import net.psforever.objects.{GlobalDefinitions, SensorDeployable, Vehicle}
|
||||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||||
import net.psforever.packet.game._
|
import net.psforever.packet.game._
|
||||||
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||||
|
|
@ -154,6 +154,19 @@ class ProximityTerminalEffectTest extends ActorTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class RouterTelepadTransportTest extends ActorTest {
|
||||||
|
ServiceManager.boot(system)
|
||||||
|
|
||||||
|
"LocalService" should {
|
||||||
|
"pass RouterTelepadTransport" in {
|
||||||
|
val service = system.actorOf(Props[LocalService], "l_service")
|
||||||
|
service ! Service.Join("test")
|
||||||
|
service ! LocalServiceMessage("test", LocalAction.RouterTelepadTransport(PlanetSideGUID(10), PlanetSideGUID(11), PlanetSideGUID(12), PlanetSideGUID(13)))
|
||||||
|
expectMsg(LocalServiceResponse("/test/Local", PlanetSideGUID(10), LocalResponse.RouterTelepadTransport(PlanetSideGUID(11), PlanetSideGUID(12), PlanetSideGUID(13))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class SetEmpireTest extends ActorTest {
|
class SetEmpireTest extends ActorTest {
|
||||||
ServiceManager.boot(system)
|
ServiceManager.boot(system)
|
||||||
val obj = new SensorDeployable(GlobalDefinitions.motionalarmsensor)
|
val obj = new SensorDeployable(GlobalDefinitions.motionalarmsensor)
|
||||||
|
|
@ -168,6 +181,20 @@ class SetEmpireTest extends ActorTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ToggleTeleportSystemTest extends ActorTest {
|
||||||
|
ServiceManager.boot(system)
|
||||||
|
|
||||||
|
"LocalService" should {
|
||||||
|
"pass ToggleTeleportSystem" in {
|
||||||
|
val router = Vehicle(GlobalDefinitions.router)
|
||||||
|
val service = system.actorOf(Props[LocalService], "l_service")
|
||||||
|
service ! Service.Join("test")
|
||||||
|
service ! LocalServiceMessage("test", LocalAction.ToggleTeleportSystem(PlanetSideGUID(10), router, None))
|
||||||
|
expectMsg(LocalServiceResponse("/test/Local", PlanetSideGUID(10), LocalResponse.ToggleTeleportSystem(router, None)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class TriggerEffectTest extends ActorTest {
|
class TriggerEffectTest extends ActorTest {
|
||||||
ServiceManager.boot(system)
|
ServiceManager.boot(system)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import akka.actor.{ActorRef, Props}
|
||||||
import akka.routing.RandomPool
|
import akka.routing.RandomPool
|
||||||
import akka.testkit.TestProbe
|
import akka.testkit.TestProbe
|
||||||
import base.ActorTest
|
import base.ActorTest
|
||||||
import net.psforever.objects.PlanetSideGameObject
|
import net.psforever.objects.{GlobalDefinitions, PlanetSideGameObject, Tool}
|
||||||
import net.psforever.objects.definition.{EquipmentDefinition, ObjectDefinition}
|
import net.psforever.objects.definition.{EquipmentDefinition, ObjectDefinition}
|
||||||
import net.psforever.objects.equipment.Equipment
|
import net.psforever.objects.equipment.Equipment
|
||||||
import net.psforever.objects.guid.TaskResolver
|
import net.psforever.objects.guid.TaskResolver
|
||||||
|
|
@ -21,24 +21,26 @@ import scala.concurrent.duration._
|
||||||
// "RemoverActor" should {
|
// "RemoverActor" should {
|
||||||
// "handle a simple task" in {
|
// "handle a simple task" in {
|
||||||
// expectNoMsg(500 milliseconds)
|
// expectNoMsg(500 milliseconds)
|
||||||
// val probe = TestProbe()
|
// val remover = system.actorOf(
|
||||||
// val remover = system.actorOf(Props(classOf[RemoverActorTest.TestRemover], probe), "test-remover")
|
// Props(classOf[ActorTest.SupportActorInterface], Props[RemoverActorTest.TestRemover], self),
|
||||||
|
// "test-remover"
|
||||||
|
// )
|
||||||
// remover ! RemoverActor.AddTask(RemoverActorTest.TestObject, Zone.Nowhere)
|
// remover ! RemoverActor.AddTask(RemoverActorTest.TestObject, Zone.Nowhere)
|
||||||
//
|
//
|
||||||
// val reply1 = probe.receiveOne(200 milliseconds)
|
// val reply1 = receiveOne(500 milliseconds)
|
||||||
// assert(reply1.isInstanceOf[RemoverActorTest.InclusionTestAlert])
|
// assert(reply1.isInstanceOf[RemoverActorTest.InclusionTestAlert])
|
||||||
// val reply2 = probe.receiveOne(200 milliseconds)
|
// val reply2 = receiveOne(500 milliseconds)
|
||||||
// assert(reply2.isInstanceOf[RemoverActorTest.InitialJobAlert])
|
// assert(reply2.isInstanceOf[RemoverActorTest.InitialJobAlert])
|
||||||
// probe.expectNoMsg(1 seconds) //delay
|
// expectNoMsg(1 seconds) //delay
|
||||||
// val reply3 = probe.receiveOne(300 milliseconds)
|
// val reply3 = receiveOne(500 milliseconds)
|
||||||
// assert(reply3.isInstanceOf[RemoverActorTest.FirstJobAlert])
|
// assert(reply3.isInstanceOf[RemoverActorTest.FirstJobAlert])
|
||||||
// val reply4 = probe.receiveOne(300 milliseconds)
|
// val reply4 = receiveOne(500 milliseconds)
|
||||||
// assert(reply4.isInstanceOf[RemoverActorTest.ClearanceTestAlert])
|
// assert(reply4.isInstanceOf[RemoverActorTest.ClearanceTestAlert])
|
||||||
// val reply5 = probe.receiveOne(300 milliseconds)
|
// val reply5 = receiveOne(500 milliseconds)
|
||||||
// assert(reply5.isInstanceOf[RemoverActorTest.SecondJobAlert])
|
// assert(reply5.isInstanceOf[RemoverActorTest.SecondJobAlert])
|
||||||
// val reply6 = probe.receiveOne(500 milliseconds)
|
// val reply6 = receiveOne(500 milliseconds)
|
||||||
// assert(reply6.isInstanceOf[RemoverActorTest.DeletionTaskAlert])
|
// assert(reply6.isInstanceOf[RemoverActorTest.DeletionTaskAlert])
|
||||||
// val reply7 = probe.receiveOne(500 milliseconds)
|
// val reply7 = receiveOne(500 milliseconds)
|
||||||
// assert(reply7.isInstanceOf[RemoverActorTest.DeletionTaskRunAlert])
|
// assert(reply7.isInstanceOf[RemoverActorTest.DeletionTaskRunAlert])
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
@ -50,29 +52,31 @@ import scala.concurrent.duration._
|
||||||
// "RemoverActor" should {
|
// "RemoverActor" should {
|
||||||
// "handle a simple task (timed)" in {
|
// "handle a simple task (timed)" in {
|
||||||
// expectNoMsg(500 milliseconds)
|
// expectNoMsg(500 milliseconds)
|
||||||
// val probe = TestProbe()
|
// val remover = system.actorOf(
|
||||||
// val remover = system.actorOf(Props(classOf[RemoverActorTest.TestRemover], probe), "test-remover")
|
// Props(classOf[ActorTest.SupportActorInterface], Props[RemoverActorTest.TestRemover], self),
|
||||||
|
// "test-remover"
|
||||||
|
// )
|
||||||
// remover ! RemoverActor.AddTask(RemoverActorTest.TestObject, Zone.Nowhere, Some(100 milliseconds))
|
// remover ! RemoverActor.AddTask(RemoverActorTest.TestObject, Zone.Nowhere, Some(100 milliseconds))
|
||||||
//
|
//
|
||||||
// val reply1 = probe.receiveOne(200 milliseconds)
|
// val reply1 = receiveOne(500 milliseconds)
|
||||||
// assert(reply1.isInstanceOf[RemoverActorTest.InclusionTestAlert])
|
// assert(reply1.isInstanceOf[RemoverActorTest.InclusionTestAlert])
|
||||||
// val reply2 = probe.receiveOne(200 milliseconds)
|
// val reply2 = receiveOne(500 milliseconds)
|
||||||
// assert(reply2.isInstanceOf[RemoverActorTest.InitialJobAlert])
|
// assert(reply2.isInstanceOf[RemoverActorTest.InitialJobAlert])
|
||||||
// //no delay
|
// //no delay
|
||||||
// val reply3 = probe.receiveOne(300 milliseconds)
|
// val reply3 = receiveOne(500 milliseconds)
|
||||||
// assert(reply3.isInstanceOf[RemoverActorTest.FirstJobAlert])
|
// assert(reply3.isInstanceOf[RemoverActorTest.FirstJobAlert])
|
||||||
// val reply4 = probe.receiveOne(300 milliseconds)
|
// val reply4 = receiveOne(500 milliseconds)
|
||||||
// assert(reply4.isInstanceOf[RemoverActorTest.ClearanceTestAlert])
|
// assert(reply4.isInstanceOf[RemoverActorTest.ClearanceTestAlert])
|
||||||
// val reply5 = probe.receiveOne(300 milliseconds)
|
// val reply5 = receiveOne(500 milliseconds)
|
||||||
// assert(reply5.isInstanceOf[RemoverActorTest.SecondJobAlert])
|
// assert(reply5.isInstanceOf[RemoverActorTest.SecondJobAlert])
|
||||||
// val reply6 = probe.receiveOne(300 milliseconds)
|
// val reply6 = receiveOne(500 milliseconds)
|
||||||
// assert(reply6.isInstanceOf[RemoverActorTest.DeletionTaskAlert])
|
// assert(reply6.isInstanceOf[RemoverActorTest.DeletionTaskAlert])
|
||||||
// val reply7 = probe.receiveOne(300 milliseconds)
|
// val reply7 = receiveOne(500 milliseconds)
|
||||||
// assert(reply7.isInstanceOf[RemoverActorTest.DeletionTaskRunAlert])
|
// assert(reply7.isInstanceOf[RemoverActorTest.DeletionTaskRunAlert])
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
//
|
|
||||||
//class ExcludedRemoverActorTest extends ActorTest {
|
//class ExcludedRemoverActorTest extends ActorTest {
|
||||||
// ServiceManager.boot ! ServiceManager.Register(RandomPool(2).props(Props[TaskResolver]), "taskResolver")
|
// ServiceManager.boot ! ServiceManager.Register(RandomPool(2).props(Props[TaskResolver]), "taskResolver")
|
||||||
// val AlternateTestObject = new PlanetSideGameObject() { def Definition = new ObjectDefinition(0) { } }
|
// val AlternateTestObject = new PlanetSideGameObject() { def Definition = new ObjectDefinition(0) { } }
|
||||||
|
|
@ -81,7 +85,10 @@ import scala.concurrent.duration._
|
||||||
// "allow only specific objects" in {
|
// "allow only specific objects" in {
|
||||||
// expectNoMsg(500 milliseconds)
|
// expectNoMsg(500 milliseconds)
|
||||||
// val probe = TestProbe()
|
// val probe = TestProbe()
|
||||||
// val remover = system.actorOf(Props(classOf[RemoverActorTest.TestRemover], probe), "test-remover")
|
// val remover = system.actorOf(
|
||||||
|
// Props(classOf[ActorTest.SupportActorInterface], Props[RemoverActorTest.TestRemover], self),
|
||||||
|
// "test-remover"
|
||||||
|
// )
|
||||||
// remover ! RemoverActor.AddTask(AlternateTestObject, Zone.Nowhere)
|
// remover ! RemoverActor.AddTask(AlternateTestObject, Zone.Nowhere)
|
||||||
//
|
//
|
||||||
// val reply1 = probe.receiveOne(200 milliseconds)
|
// val reply1 = probe.receiveOne(200 milliseconds)
|
||||||
|
|
@ -91,7 +98,7 @@ import scala.concurrent.duration._
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
//
|
|
||||||
//class MultipleRemoverActorTest extends ActorTest {
|
//class MultipleRemoverActorTest extends ActorTest {
|
||||||
// ServiceManager.boot ! ServiceManager.Register(RandomPool(2).props(Props[TaskResolver]), "taskResolver")
|
// ServiceManager.boot ! ServiceManager.Register(RandomPool(2).props(Props[TaskResolver]), "taskResolver")
|
||||||
// final val TestObject2 = new Equipment() { def Definition = new EquipmentDefinition(0) { GUID = PlanetSideGUID(2) } }
|
// final val TestObject2 = new Equipment() { def Definition = new EquipmentDefinition(0) { GUID = PlanetSideGUID(2) } }
|
||||||
|
|
@ -494,44 +501,44 @@ object RemoverActorTest {
|
||||||
|
|
||||||
final case class DeletionTaskRunAlert()
|
final case class DeletionTaskRunAlert()
|
||||||
|
|
||||||
class TestRemover(probe : TestProbe) extends RemoverActor {
|
class TestRemover extends RemoverActor {
|
||||||
import net.psforever.objects.guid.{Task, TaskResolver}
|
import net.psforever.objects.guid.{Task, TaskResolver}
|
||||||
val FirstStandardDuration = 1 seconds
|
val FirstStandardDuration = 1 seconds
|
||||||
|
|
||||||
val SecondStandardDuration = 100 milliseconds
|
val SecondStandardDuration = 100 milliseconds
|
||||||
|
|
||||||
def InclusionTest(entry : RemoverActor.Entry) : Boolean = {
|
def InclusionTest(entry : RemoverActor.Entry) : Boolean = {
|
||||||
probe.ref ! InclusionTestAlert()
|
context.parent ! InclusionTestAlert()
|
||||||
entry.obj.isInstanceOf[Equipment]
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
def InitialJob(entry : RemoverActor.Entry) : Unit = {
|
def InitialJob(entry : RemoverActor.Entry) : Unit = {
|
||||||
probe.ref ! InitialJobAlert()
|
context.parent ! InitialJobAlert()
|
||||||
}
|
}
|
||||||
|
|
||||||
def FirstJob(entry : RemoverActor.Entry) : Unit = {
|
def FirstJob(entry : RemoverActor.Entry) : Unit = {
|
||||||
probe.ref ! FirstJobAlert()
|
context.parent ! FirstJobAlert()
|
||||||
}
|
}
|
||||||
|
|
||||||
override def SecondJob(entry : RemoverActor.Entry) : Unit = {
|
override def SecondJob(entry : RemoverActor.Entry) : Unit = {
|
||||||
probe.ref ! SecondJobAlert()
|
context.parent ! SecondJobAlert()
|
||||||
super.SecondJob(entry)
|
super.SecondJob(entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
def ClearanceTest(entry : RemoverActor.Entry) : Boolean = {
|
def ClearanceTest(entry : RemoverActor.Entry) : Boolean = {
|
||||||
probe.ref ! ClearanceTestAlert()
|
context.parent ! ClearanceTestAlert()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
def DeletionTask(entry : RemoverActor.Entry) : TaskResolver.GiveTask = {
|
def DeletionTask(entry : RemoverActor.Entry) : TaskResolver.GiveTask = {
|
||||||
probe.ref ! DeletionTaskAlert()
|
context.parent ! DeletionTaskAlert()
|
||||||
TaskResolver.GiveTask(new Task() {
|
TaskResolver.GiveTask(new Task() {
|
||||||
private val localProbe = probe
|
private val localProbe = context.parent
|
||||||
|
|
||||||
override def isComplete = Task.Resolution.Success
|
override def isComplete = Task.Resolution.Success
|
||||||
|
|
||||||
def Execute(resolver : ActorRef) : Unit = {
|
def Execute(resolver : ActorRef) : Unit = {
|
||||||
localProbe.ref ! DeletionTaskRunAlert()
|
context.parent ! DeletionTaskRunAlert()
|
||||||
resolver ! scala.util.Success(this)
|
resolver ! scala.util.Success(this)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
171
common/src/test/scala/service/RouterTelepadActivationTest.scala
Normal file
171
common/src/test/scala/service/RouterTelepadActivationTest.scala
Normal file
|
|
@ -0,0 +1,171 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package service
|
||||||
|
|
||||||
|
import akka.actor.Props
|
||||||
|
import base.ActorTest
|
||||||
|
import net.psforever.objects._
|
||||||
|
import net.psforever.objects.zones.Zone
|
||||||
|
import net.psforever.packet.game.PlanetSideGUID
|
||||||
|
import services.local.support.RouterTelepadActivation
|
||||||
|
import services.support.SupportActor
|
||||||
|
|
||||||
|
import scala.concurrent.duration._
|
||||||
|
|
||||||
|
class RouterTelepadActivationTest extends ActorTest {
|
||||||
|
"RouterTelepadActivation" should {
|
||||||
|
"construct" in {
|
||||||
|
system.actorOf(Props[RouterTelepadActivation], "activation-test-actor")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RouterTelepadActivationSimpleTest extends ActorTest {
|
||||||
|
"RouterTelepadActivation" should {
|
||||||
|
"handle a task" in {
|
||||||
|
val telepad = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||||
|
telepad.GUID = PlanetSideGUID(1)
|
||||||
|
val obj = system.actorOf(
|
||||||
|
Props(classOf[ActorTest.SupportActorInterface], Props[RouterTelepadActivation], self),
|
||||||
|
"activation-test-actor"
|
||||||
|
)
|
||||||
|
|
||||||
|
obj ! RouterTelepadActivation.AddTask(telepad, Zone.Nowhere, Some(2 seconds))
|
||||||
|
expectMsg(3 seconds, RouterTelepadActivation.ActivateTeleportSystem(telepad, Zone.Nowhere))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RouterTelepadActivationComplexTest extends ActorTest {
|
||||||
|
"RouterTelepadActivation" should {
|
||||||
|
"handle multiple tasks" in {
|
||||||
|
val telepad1 = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||||
|
telepad1.GUID = PlanetSideGUID(1)
|
||||||
|
val telepad2 = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||||
|
telepad2.GUID = PlanetSideGUID(2)
|
||||||
|
val telepad3 = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||||
|
telepad3.GUID = PlanetSideGUID(3)
|
||||||
|
val obj = system.actorOf(
|
||||||
|
Props(classOf[ActorTest.SupportActorInterface], Props[RouterTelepadActivation], self),
|
||||||
|
"activation-test-actor"
|
||||||
|
)
|
||||||
|
|
||||||
|
obj ! RouterTelepadActivation.AddTask(telepad1, Zone.Nowhere, Some(2 seconds))
|
||||||
|
obj ! RouterTelepadActivation.AddTask(telepad2, Zone.Nowhere, Some(3 seconds))
|
||||||
|
obj ! RouterTelepadActivation.AddTask(telepad3, Zone.Nowhere, Some(1 seconds))
|
||||||
|
val msgs = receiveN(3, 5 seconds) //organized by duration
|
||||||
|
assert(msgs.head.isInstanceOf[RouterTelepadActivation.ActivateTeleportSystem])
|
||||||
|
assert(msgs.head.asInstanceOf[RouterTelepadActivation.ActivateTeleportSystem].telepad == telepad3)
|
||||||
|
assert(msgs(1).isInstanceOf[RouterTelepadActivation.ActivateTeleportSystem])
|
||||||
|
assert(msgs(1).asInstanceOf[RouterTelepadActivation.ActivateTeleportSystem].telepad == telepad1)
|
||||||
|
assert(msgs(2).isInstanceOf[RouterTelepadActivation.ActivateTeleportSystem])
|
||||||
|
assert(msgs(2).asInstanceOf[RouterTelepadActivation.ActivateTeleportSystem].telepad == telepad2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RouterTelepadActivationHurryTest extends ActorTest {
|
||||||
|
"RouterTelepadActivation" should {
|
||||||
|
"hurry specific tasks" in {
|
||||||
|
val telepad1 = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||||
|
telepad1.GUID = PlanetSideGUID(1)
|
||||||
|
val telepad2 = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||||
|
telepad2.GUID = PlanetSideGUID(2)
|
||||||
|
val telepad3 = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||||
|
telepad3.GUID = PlanetSideGUID(3)
|
||||||
|
val obj = system.actorOf(
|
||||||
|
Props(classOf[ActorTest.SupportActorInterface], Props[RouterTelepadActivation], self),
|
||||||
|
"activation-test-actor"
|
||||||
|
)
|
||||||
|
|
||||||
|
obj ! RouterTelepadActivation.AddTask(telepad1, Zone.Nowhere, Some(2 seconds))
|
||||||
|
obj ! RouterTelepadActivation.AddTask(telepad2, Zone.Nowhere, Some(2 seconds))
|
||||||
|
obj ! RouterTelepadActivation.AddTask(telepad3, Zone.Nowhere, Some(2 seconds))
|
||||||
|
obj ! SupportActor.HurrySpecific(List(telepad1, telepad2), Zone.Nowhere)
|
||||||
|
val msgs = receiveN(2, 1 seconds)
|
||||||
|
assert(msgs.head.isInstanceOf[RouterTelepadActivation.ActivateTeleportSystem])
|
||||||
|
assert(msgs.head.asInstanceOf[RouterTelepadActivation.ActivateTeleportSystem].telepad == telepad1)
|
||||||
|
assert(msgs(1).isInstanceOf[RouterTelepadActivation.ActivateTeleportSystem])
|
||||||
|
assert(msgs(1).asInstanceOf[RouterTelepadActivation.ActivateTeleportSystem].telepad == telepad2)
|
||||||
|
val last = receiveOne(3 seconds)
|
||||||
|
assert(last.isInstanceOf[RouterTelepadActivation.ActivateTeleportSystem])
|
||||||
|
assert(last.asInstanceOf[RouterTelepadActivation.ActivateTeleportSystem].telepad == telepad3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RouterTelepadActivationHurryAllTest extends ActorTest {
|
||||||
|
"RouterTelepadActivation" should {
|
||||||
|
"hurry all tasks" in {
|
||||||
|
val telepad1 = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||||
|
telepad1.GUID = PlanetSideGUID(1)
|
||||||
|
val telepad2 = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||||
|
telepad2.GUID = PlanetSideGUID(2)
|
||||||
|
val telepad3 = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||||
|
telepad3.GUID = PlanetSideGUID(3)
|
||||||
|
val obj = system.actorOf(
|
||||||
|
Props(classOf[ActorTest.SupportActorInterface], Props[RouterTelepadActivation], self),
|
||||||
|
"activation-test-actor"
|
||||||
|
)
|
||||||
|
|
||||||
|
obj ! RouterTelepadActivation.AddTask(telepad1, Zone.Nowhere, Some(7 seconds))
|
||||||
|
obj ! RouterTelepadActivation.AddTask(telepad2, Zone.Nowhere, Some(5 seconds))
|
||||||
|
obj ! RouterTelepadActivation.AddTask(telepad3, Zone.Nowhere, Some(6 seconds))
|
||||||
|
obj ! SupportActor.HurryAll()
|
||||||
|
val msgs = receiveN(3, 4 seconds) //organized by duration; note: all messages received before the earliest task should be performed
|
||||||
|
assert(msgs.head.isInstanceOf[RouterTelepadActivation.ActivateTeleportSystem])
|
||||||
|
assert(msgs.head.asInstanceOf[RouterTelepadActivation.ActivateTeleportSystem].telepad == telepad2)
|
||||||
|
assert(msgs(1).isInstanceOf[RouterTelepadActivation.ActivateTeleportSystem])
|
||||||
|
assert(msgs(1).asInstanceOf[RouterTelepadActivation.ActivateTeleportSystem].telepad == telepad3)
|
||||||
|
assert(msgs(2).isInstanceOf[RouterTelepadActivation.ActivateTeleportSystem])
|
||||||
|
assert(msgs(2).asInstanceOf[RouterTelepadActivation.ActivateTeleportSystem].telepad == telepad1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RouterTelepadActivationClearTest extends ActorTest {
|
||||||
|
"RouterTelepadActivation" should {
|
||||||
|
"clear specific tasks" in {
|
||||||
|
val telepad1 = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||||
|
telepad1.GUID = PlanetSideGUID(1)
|
||||||
|
val telepad2 = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||||
|
telepad2.GUID = PlanetSideGUID(2)
|
||||||
|
val telepad3 = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||||
|
telepad3.GUID = PlanetSideGUID(3)
|
||||||
|
val obj = system.actorOf(
|
||||||
|
Props(classOf[ActorTest.SupportActorInterface], Props[RouterTelepadActivation], self),
|
||||||
|
"activation-test-actor"
|
||||||
|
)
|
||||||
|
|
||||||
|
obj ! RouterTelepadActivation.AddTask(telepad1, Zone.Nowhere, Some(2 seconds))
|
||||||
|
obj ! RouterTelepadActivation.AddTask(telepad2, Zone.Nowhere, Some(2 seconds))
|
||||||
|
obj ! RouterTelepadActivation.AddTask(telepad3, Zone.Nowhere, Some(2 seconds))
|
||||||
|
obj ! SupportActor.ClearSpecific(List(telepad1, telepad2), Zone.Nowhere)
|
||||||
|
val msgs = receiveN(1, 3 seconds) //should only receive telepad3
|
||||||
|
assert(msgs.head.isInstanceOf[RouterTelepadActivation.ActivateTeleportSystem])
|
||||||
|
assert(msgs.head.asInstanceOf[RouterTelepadActivation.ActivateTeleportSystem].telepad == telepad3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RouterTelepadActivationClearAllTest extends ActorTest {
|
||||||
|
"RouterTelepadActivation" should {
|
||||||
|
"clear all tasks" in {
|
||||||
|
val telepad1 = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||||
|
telepad1.GUID = PlanetSideGUID(1)
|
||||||
|
val telepad2 = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||||
|
telepad2.GUID = PlanetSideGUID(2)
|
||||||
|
val telepad3 = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||||
|
telepad3.GUID = PlanetSideGUID(3)
|
||||||
|
val obj = system.actorOf(
|
||||||
|
Props(classOf[ActorTest.SupportActorInterface], Props[RouterTelepadActivation], self),
|
||||||
|
"activation-test-actor"
|
||||||
|
)
|
||||||
|
|
||||||
|
obj ! RouterTelepadActivation.AddTask(telepad1, Zone.Nowhere, Some(2 seconds))
|
||||||
|
obj ! RouterTelepadActivation.AddTask(telepad2, Zone.Nowhere, Some(2 seconds))
|
||||||
|
obj ! RouterTelepadActivation.AddTask(telepad3, Zone.Nowhere, Some(2 seconds))
|
||||||
|
obj ! SupportActor.ClearAll()
|
||||||
|
expectNoMsg(4 seconds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,7 +16,7 @@ import services.ServiceManager.Lookup
|
||||||
import net.psforever.objects._
|
import net.psforever.objects._
|
||||||
import net.psforever.objects.avatar.{Certification, DeployableToolbox}
|
import net.psforever.objects.avatar.{Certification, DeployableToolbox}
|
||||||
import net.psforever.objects.ballistics._
|
import net.psforever.objects.ballistics._
|
||||||
import net.psforever.objects.ce.{ComplexDeployable, Deployable, DeployedItem, SimpleDeployable}
|
import net.psforever.objects.ce._
|
||||||
import net.psforever.objects.definition.{ConstructionFireMode, DeployableDefinition, ObjectDefinition, ToolDefinition}
|
import net.psforever.objects.definition.{ConstructionFireMode, DeployableDefinition, ObjectDefinition, ToolDefinition}
|
||||||
import net.psforever.objects.definition.converter.{CorpseConverter, DestroyedVehicleConverter}
|
import net.psforever.objects.definition.converter.{CorpseConverter, DestroyedVehicleConverter}
|
||||||
import net.psforever.objects.equipment.{CItem, _}
|
import net.psforever.objects.equipment.{CItem, _}
|
||||||
|
|
@ -35,7 +35,7 @@ import net.psforever.objects.serverobject.mblocker.Locker
|
||||||
import net.psforever.objects.serverobject.pad.{VehicleSpawnControl, VehicleSpawnPad}
|
import net.psforever.objects.serverobject.pad.{VehicleSpawnControl, VehicleSpawnPad}
|
||||||
import net.psforever.objects.serverobject.pad.process.{AutoDriveControls, VehicleSpawnControlGuided}
|
import net.psforever.objects.serverobject.pad.process.{AutoDriveControls, VehicleSpawnControlGuided}
|
||||||
import net.psforever.objects.serverobject.resourcesilo.ResourceSilo
|
import net.psforever.objects.serverobject.resourcesilo.ResourceSilo
|
||||||
import net.psforever.objects.serverobject.structures.{Building, StructureType, WarpGate}
|
import net.psforever.objects.serverobject.structures.{Amenity, Building, StructureType, WarpGate}
|
||||||
import net.psforever.objects.serverobject.terminals._
|
import net.psforever.objects.serverobject.terminals._
|
||||||
import net.psforever.objects.serverobject.terminals.Terminal.TerminalMessage
|
import net.psforever.objects.serverobject.terminals.Terminal.TerminalMessage
|
||||||
import net.psforever.objects.serverobject.tube.SpawnTube
|
import net.psforever.objects.serverobject.tube.SpawnTube
|
||||||
|
|
@ -45,7 +45,7 @@ import net.psforever.objects.vital._
|
||||||
import net.psforever.objects.zones.{InterstellarCluster, Zone}
|
import net.psforever.objects.zones.{InterstellarCluster, Zone}
|
||||||
import net.psforever.packet.game.objectcreate._
|
import net.psforever.packet.game.objectcreate._
|
||||||
import net.psforever.types._
|
import net.psforever.types._
|
||||||
import services.{RemoverActor, _}
|
import services.{RemoverActor, vehicle, _}
|
||||||
import services.avatar.{AvatarAction, AvatarResponse, AvatarServiceMessage, AvatarServiceResponse}
|
import services.avatar.{AvatarAction, AvatarResponse, AvatarServiceMessage, AvatarServiceResponse}
|
||||||
import services.galaxy.{GalaxyResponse, GalaxyServiceResponse}
|
import services.galaxy.{GalaxyResponse, GalaxyServiceResponse}
|
||||||
import services.local.{LocalAction, LocalResponse, LocalServiceMessage, LocalServiceResponse}
|
import services.local.{LocalAction, LocalResponse, LocalServiceMessage, LocalServiceResponse}
|
||||||
|
|
@ -59,7 +59,9 @@ import scala.concurrent.{Await, Future}
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
import scala.util.Success
|
import scala.util.Success
|
||||||
import akka.pattern.ask
|
import akka.pattern.ask
|
||||||
import services.local.support.HackCaptureActor
|
import net.psforever.objects.vehicles.Utility.InternalTelepad
|
||||||
|
import services.local.support.{HackCaptureActor, RouterTelepadActivation}
|
||||||
|
import services.support.SupportActor
|
||||||
|
|
||||||
class WorldSessionActor extends Actor with MDCContextAware {
|
class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
|
|
||||||
|
|
@ -95,6 +97,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
var whenUsedLastKit : Long = 0
|
var whenUsedLastKit : Long = 0
|
||||||
val projectiles : Array[Option[Projectile]] = Array.fill[Option[Projectile]](Projectile.RangeUID - Projectile.BaseUID)(None)
|
val projectiles : Array[Option[Projectile]] = Array.fill[Option[Projectile]](Projectile.RangeUID - Projectile.BaseUID)(None)
|
||||||
var drawDeloyableIcon : PlanetSideGameObject with Deployable => Unit = RedrawDeployableIcons
|
var drawDeloyableIcon : PlanetSideGameObject with Deployable => Unit = RedrawDeployableIcons
|
||||||
|
var recentTeleportAttempt : Long = 0
|
||||||
|
|
||||||
var amsSpawnPoint : Option[SpawnTube] = None
|
var amsSpawnPoint : Option[SpawnTube] = None
|
||||||
var clientKeepAlive : Cancellable = DefaultCancellable.obj
|
var clientKeepAlive : Cancellable = DefaultCancellable.obj
|
||||||
var progressBarUpdate : Cancellable = DefaultCancellable.obj
|
var progressBarUpdate : Cancellable = DefaultCancellable.obj
|
||||||
|
|
@ -124,6 +128,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
vehicleService ! Service.Leave()
|
vehicleService ! Service.Leave()
|
||||||
avatarService ! Service.Leave()
|
avatarService ! Service.Leave()
|
||||||
galaxyService ! Service.Leave()
|
galaxyService ! Service.Leave()
|
||||||
|
cluster ! Service.Leave()
|
||||||
LivePlayerList.Remove(sessionId)
|
LivePlayerList.Remove(sessionId)
|
||||||
if(player != null && player.HasGUID) {
|
if(player != null && player.HasGUID) {
|
||||||
val player_guid = player.GUID
|
val player_guid = player.GUID
|
||||||
|
|
@ -141,15 +146,15 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
})
|
})
|
||||||
//handle orphaned deployables
|
//handle orphaned deployables
|
||||||
DisownDeployables()
|
DisownDeployables()
|
||||||
//clean up boomer triggers
|
//clean up boomer triggers and telepads
|
||||||
val equipment = (
|
val equipment = (
|
||||||
(player.Holsters()
|
(player.Holsters()
|
||||||
.zipWithIndex
|
.zipWithIndex
|
||||||
.map({ case ((slot, index)) => (index, slot.Equipment) })
|
.map({ case ((slot, index)) => (index, slot.Equipment) })
|
||||||
.collect { case ((index, Some(obj))) => InventoryItem(obj, index) }
|
.collect { case ((index, Some(obj))) => InventoryItem(obj, index) }
|
||||||
) ++ player.Inventory.Items)
|
) ++ player.Inventory.Items)
|
||||||
.filterNot({ case InventoryItem(obj, _) => obj.isInstanceOf[BoomerTrigger] })
|
.filterNot({ case InventoryItem(obj, _) => obj.isInstanceOf[BoomerTrigger] || obj.isInstanceOf[Telepad] })
|
||||||
//TODO final character save before doing any of this
|
//TODO final character save before doing any of this (use equipment)
|
||||||
continent.Population ! Zone.Population.Release(avatar)
|
continent.Population ! Zone.Population.Release(avatar)
|
||||||
if(player.isAlive) {
|
if(player.isAlive) {
|
||||||
//actually being alive or manually deconstructing
|
//actually being alive or manually deconstructing
|
||||||
|
|
@ -206,13 +211,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
case None =>
|
case None =>
|
||||||
None
|
None
|
||||||
}) match {
|
}) match {
|
||||||
case Some(vehicle : Vehicle) =>
|
|
||||||
vehicle.Seat(vehicle.PassengerInSeat(player).get).get.Occupant = None
|
|
||||||
if(vehicle.Seats.values.count(_.isOccupied) == 0) {
|
|
||||||
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.AddTask(vehicle, continent, vehicle.Definition.DeconstructionTime)) //start vehicle decay
|
|
||||||
}
|
|
||||||
vehicleService ! Service.Leave(Some(s"${vehicle.Actor}"))
|
|
||||||
|
|
||||||
case Some(mobj : Mountable) =>
|
case Some(mobj : Mountable) =>
|
||||||
mobj.Seat(mobj.PassengerInSeat(player).get).get.Occupant = None
|
mobj.Seat(mobj.PassengerInSeat(player).get).get.Occupant = None
|
||||||
|
|
||||||
|
|
@ -496,10 +494,11 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
case building : Building =>
|
case building : Building =>
|
||||||
log.info(s"Zone.Lattice.SpawnPoint: spawn point on $zone_id in building ${building.Id} selected")
|
log.info(s"Zone.Lattice.SpawnPoint: spawn point on $zone_id in building ${building.Id} selected")
|
||||||
case vehicle : Vehicle =>
|
case vehicle : Vehicle =>
|
||||||
|
// vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(vehicle), continent))
|
||||||
|
// vehicleService ! VehicleServiceMessage.Decon(RemoverActor.AddTask(vehicle, continent, vehicle.Definition.DeconstructionTime))
|
||||||
//TODO replace this bad math with good math or no math
|
//TODO replace this bad math with good math or no math
|
||||||
//position the player alongside either of the AMS's terminals, facing away from it
|
//position the player alongside either of the AMS's terminals, facing away from it
|
||||||
val side = if(System.currentTimeMillis() % 2 == 0) 1
|
val side = if(System.currentTimeMillis() % 2 == 0) 1 else -1
|
||||||
else -1
|
|
||||||
//right | left
|
//right | left
|
||||||
val z = spawn_tube.Orientation.z
|
val z = spawn_tube.Orientation.z
|
||||||
val zrot = (z + 90) % 360
|
val zrot = (z + 90) % 360
|
||||||
|
|
@ -547,7 +546,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
case Zone.Ground.ItemOnGround(item : BoomerTrigger, pos, orient) =>
|
case Zone.Ground.ItemOnGround(item : BoomerTrigger, pos, orient) =>
|
||||||
//dropped the trigger, no longer own the boomer; make certain whole faction is aware of that
|
//dropped the trigger, no longer own the boomer; make certain whole faction is aware of that
|
||||||
val playerGUID = player.GUID
|
val playerGUID = player.GUID
|
||||||
continent.GUID(item.Companion.getOrElse(PlanetSideGUID(0))) match {
|
continent.GUID(item.Companion) match {
|
||||||
case Some(obj : BoomerDeployable) =>
|
case Some(obj : BoomerDeployable) =>
|
||||||
val guid = obj.GUID
|
val guid = obj.GUID
|
||||||
val factionOnContinentChannel = s"${continent.Id}/${player.Faction}"
|
val factionOnContinentChannel = s"${continent.Id}/${player.Faction}"
|
||||||
|
|
@ -586,7 +585,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
case Zone.Ground.ItemInHand(item : BoomerTrigger) =>
|
case Zone.Ground.ItemInHand(item : BoomerTrigger) =>
|
||||||
if(PutItemInHand(item)) {
|
if(PutItemInHand(item)) {
|
||||||
//pick up the trigger, own the boomer; make certain whole faction is aware of that
|
//pick up the trigger, own the boomer; make certain whole faction is aware of that
|
||||||
continent.GUID(item.Companion.getOrElse(PlanetSideGUID(0))) match {
|
continent.GUID(item.Companion) match {
|
||||||
case Some(obj : BoomerDeployable) =>
|
case Some(obj : BoomerDeployable) =>
|
||||||
val guid = obj.GUID
|
val guid = obj.GUID
|
||||||
val playerGUID = player.GUID
|
val playerGUID = player.GUID
|
||||||
|
|
@ -632,6 +631,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
case GlobalDefinitions.advanced_ace =>
|
case GlobalDefinitions.advanced_ace =>
|
||||||
sendResponse(GenericObjectActionMessage(player.GUID, 212)) //put fdu down; it will be removed from the client's holster
|
sendResponse(GenericObjectActionMessage(player.GUID, 212)) //put fdu down; it will be removed from the client's holster
|
||||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PutDownFDU(player.GUID))
|
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PutDownFDU(player.GUID))
|
||||||
|
case GlobalDefinitions.router_telepad => ;
|
||||||
case _ =>
|
case _ =>
|
||||||
log.warn(s"Zone.Deployable.DeployableIsBuilt: not sure what kind of construction item to animate - ${tool.Definition}")
|
log.warn(s"Zone.Deployable.DeployableIsBuilt: not sure what kind of construction item to animate - ${tool.Definition}")
|
||||||
}
|
}
|
||||||
|
|
@ -706,6 +706,39 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
FindReplacementConstructionItem(tool, index)
|
FindReplacementConstructionItem(tool, index)
|
||||||
StopBundlingPackets()
|
StopBundlingPackets()
|
||||||
|
|
||||||
|
case WorldSessionActor.FinalizeDeployable(obj : TelepadDeployable, tool, index) =>
|
||||||
|
StartBundlingPackets()
|
||||||
|
if(obj.Health > 0) {
|
||||||
|
val guid = obj.GUID
|
||||||
|
//router telepad deployable
|
||||||
|
val router = tool.asInstanceOf[Telepad].Router
|
||||||
|
//router must exist and be deployed
|
||||||
|
continent.GUID(router) match {
|
||||||
|
case Some(vehicle : Vehicle) =>
|
||||||
|
val routerGUID = router.get
|
||||||
|
if(vehicle.Health == 0) {
|
||||||
|
//the Telepad was successfully deployed; but, before it could configure, its Router was destroyed
|
||||||
|
sendResponse(ChatMsg(ChatMessageType.UNK_229, false, "", "@Telepad_NoDeploy_RouterLost", None))
|
||||||
|
localService ! LocalServiceMessage.Deployables(RemoverActor.AddTask(obj, continent, Some(0 seconds)))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log.info(s"FinalizeDeployable: setup for telepad #${guid.guid} in zone ${continent.Id}")
|
||||||
|
obj.Router = routerGUID //necessary; forwards link to the router
|
||||||
|
DeployableBuildActivity(obj)
|
||||||
|
CommonDestroyConstructionItem(tool, index)
|
||||||
|
StopBundlingPackets()
|
||||||
|
//it takes 60s for the telepad to become properly active
|
||||||
|
localService ! LocalServiceMessage.Telepads(RouterTelepadActivation.AddTask(obj, continent))
|
||||||
|
}
|
||||||
|
|
||||||
|
case _ =>
|
||||||
|
//the Telepad was successfully deployed; but, before it could configure, its Router was deconstructed
|
||||||
|
sendResponse(ChatMsg(ChatMessageType.UNK_229, false, "", "@Telepad_NoDeploy_RouterLost", None))
|
||||||
|
localService ! LocalServiceMessage.Deployables(RemoverActor.AddTask(obj, continent, Some(0 seconds)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StopBundlingPackets()
|
||||||
|
|
||||||
case WorldSessionActor.FinalizeDeployable(obj : SimpleDeployable, tool, index) =>
|
case WorldSessionActor.FinalizeDeployable(obj : SimpleDeployable, tool, index) =>
|
||||||
//tank_trap
|
//tank_trap
|
||||||
StartBundlingPackets()
|
StartBundlingPackets()
|
||||||
|
|
@ -1132,8 +1165,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
DeconstructDeployable(obj, guid, pos)
|
DeconstructDeployable(obj, guid, pos)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DeconstructDeployable(obj, guid, pos, obj.Orientation, if(obj.MountPoints.isEmpty) 2
|
DeconstructDeployable(obj, guid, pos, obj.Orientation, if(obj.MountPoints.isEmpty) 2 else 1)
|
||||||
else 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case LocalResponse.EliminateDeployable(obj : ComplexDeployable, guid, pos) =>
|
case LocalResponse.EliminateDeployable(obj : ComplexDeployable, guid, pos) =>
|
||||||
|
|
@ -1152,6 +1184,34 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
DeconstructDeployable(obj, guid, pos, obj.Orientation, 2)
|
DeconstructDeployable(obj, guid, pos, obj.Orientation, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case LocalResponse.EliminateDeployable(obj : TelepadDeployable, guid, pos) =>
|
||||||
|
//if active, deactivate
|
||||||
|
if(obj.Active) {
|
||||||
|
obj.Active = false
|
||||||
|
sendResponse(GenericObjectActionMessage(guid, 116))
|
||||||
|
sendResponse(GenericObjectActionMessage(guid, 120))
|
||||||
|
}
|
||||||
|
//determine if no replacement teleport system exists
|
||||||
|
continent.GUID(obj.Router) match {
|
||||||
|
case Some(router : Vehicle) =>
|
||||||
|
//if the telepad was replaced, the new system is physically in place but not yet functional
|
||||||
|
if(router.Utility(UtilityType.internal_router_telepad_deployable) match {
|
||||||
|
case Some(internalTelepad : Utility.InternalTelepad) => internalTelepad.Telepad.contains(guid) //same telepad
|
||||||
|
case _ => true
|
||||||
|
}) {
|
||||||
|
//there is no replacement telepad; shut down the system
|
||||||
|
ToggleTeleportSystem(router, None)
|
||||||
|
}
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
//standard deployable elimination behavior
|
||||||
|
if(obj.Health == 0) {
|
||||||
|
DeconstructDeployable(obj, guid, pos)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DeconstructDeployable(obj, guid, pos, obj.Orientation, 2)
|
||||||
|
}
|
||||||
|
|
||||||
case LocalResponse.EliminateDeployable(obj, guid, pos) =>
|
case LocalResponse.EliminateDeployable(obj, guid, pos) =>
|
||||||
if(obj.Health == 0) {
|
if(obj.Health == 0) {
|
||||||
DeconstructDeployable(obj, guid, pos)
|
DeconstructDeployable(obj, guid, pos)
|
||||||
|
|
@ -1215,9 +1275,20 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
sendResponse(ProximityTerminalUseMessage(PlanetSideGUID(0), object_guid, effectState))
|
sendResponse(ProximityTerminalUseMessage(PlanetSideGUID(0), object_guid, effectState))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case LocalResponse.RouterTelepadMessage(msg) =>
|
||||||
|
sendResponse(ChatMsg(ChatMessageType.UNK_229, false, "", msg, None))
|
||||||
|
|
||||||
|
case LocalResponse.RouterTelepadTransport(passenger_guid, src_guid, dest_guid) =>
|
||||||
|
StartBundlingPackets()
|
||||||
|
UseRouterTelepadEffect(passenger_guid, src_guid, dest_guid)
|
||||||
|
StopBundlingPackets()
|
||||||
|
|
||||||
case LocalResponse.SetEmpire(object_guid, empire) =>
|
case LocalResponse.SetEmpire(object_guid, empire) =>
|
||||||
sendResponse(SetEmpireMessage(object_guid, empire))
|
sendResponse(SetEmpireMessage(object_guid, empire))
|
||||||
|
|
||||||
|
case LocalResponse.ToggleTeleportSystem(router, system_plan) =>
|
||||||
|
ToggleTeleportSystem(router, system_plan)
|
||||||
|
|
||||||
case LocalResponse.TriggerEffect(target_guid, effect, effectInfo, triggerLocation) =>
|
case LocalResponse.TriggerEffect(target_guid, effect, effectInfo, triggerLocation) =>
|
||||||
sendResponse(TriggerEffectMessage(target_guid, effect, effectInfo, triggerLocation))
|
sendResponse(TriggerEffectMessage(target_guid, effect, effectInfo, triggerLocation))
|
||||||
|
|
||||||
|
|
@ -1257,12 +1328,12 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
val obj_guid : PlanetSideGUID = obj.GUID
|
val obj_guid : PlanetSideGUID = obj.GUID
|
||||||
val player_guid : PlanetSideGUID = tplayer.GUID
|
val player_guid : PlanetSideGUID = tplayer.GUID
|
||||||
log.info(s"MountVehicleMsg: $player_guid mounts $obj_guid @ $seat_num")
|
log.info(s"MountVehicleMsg: $player_guid mounts $obj_guid @ $seat_num")
|
||||||
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(obj), continent)) //clear timer
|
|
||||||
PlayerActionsToCancel()
|
PlayerActionsToCancel()
|
||||||
sendResponse(PlanetsideAttributeMessage(obj_guid, 0, obj.Health))
|
sendResponse(PlanetsideAttributeMessage(obj_guid, 0, obj.Health))
|
||||||
sendResponse(PlanetsideAttributeMessage(obj_guid, 68, 0)) //shield health
|
sendResponse(PlanetsideAttributeMessage(obj_guid, 68, 0)) //shield health
|
||||||
sendResponse(PlanetsideAttributeMessage(obj_guid, 113, 0)) //capacitor
|
sendResponse(PlanetsideAttributeMessage(obj_guid, 113, 0)) //capacitor
|
||||||
if(seat_num == 0) {
|
if(seat_num == 0) {
|
||||||
|
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(obj), continent)) //clear timer
|
||||||
//simplistic vehicle ownership management
|
//simplistic vehicle ownership management
|
||||||
obj.Owner match {
|
obj.Owner match {
|
||||||
case Some(owner_guid) =>
|
case Some(owner_guid) =>
|
||||||
|
|
@ -1288,8 +1359,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
})
|
})
|
||||||
case _ => ; //no weapons to update
|
case _ => ; //no weapons to update
|
||||||
}
|
}
|
||||||
//sendResponse(PlanetsideAttributeMessage(obj.GUID, 0, obj.Health)) //TODO vehicle max health in definition
|
|
||||||
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(obj), continent)) //clear timer
|
|
||||||
AccessContents(obj)
|
AccessContents(obj)
|
||||||
MountingAction(tplayer, obj, seat_num)
|
MountingAction(tplayer, obj, seat_num)
|
||||||
|
|
||||||
|
|
@ -1313,9 +1382,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
else {
|
else {
|
||||||
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.KickPassenger(player_guid, seat_num, true, obj.GUID))
|
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.KickPassenger(player_guid, seat_num, true, obj.GUID))
|
||||||
}
|
}
|
||||||
if(obj.Seats.values.count(_.isOccupied) == 0) {
|
|
||||||
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.AddTask(obj, continent, obj.Definition.DeconstructionTime)) //start vehicle decay
|
|
||||||
}
|
|
||||||
|
|
||||||
case Mountable.CanDismount(obj : Mountable, _) =>
|
case Mountable.CanDismount(obj : Mountable, _) =>
|
||||||
log.warn(s"DismountVehicleMsg: $obj is some generic mountable object and nothing will happen")
|
log.warn(s"DismountVehicleMsg: $obj is some generic mountable object and nothing will happen")
|
||||||
|
|
@ -1468,7 +1534,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Buy, true))
|
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Buy, true))
|
||||||
}
|
}
|
||||||
|
|
||||||
case Terminal.BuyEquipment(item) => ;
|
case Terminal.BuyEquipment(item) =>
|
||||||
tplayer.Fit(item) match {
|
tplayer.Fit(item) match {
|
||||||
case Some(index) =>
|
case Some(index) =>
|
||||||
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Buy, true))
|
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Buy, true))
|
||||||
|
|
@ -1797,12 +1863,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
* @param reply na
|
* @param reply na
|
||||||
*/
|
*/
|
||||||
def HandleVehicleServiceResponse(toChannel : String, guid : PlanetSideGUID, reply : VehicleResponse.Response) : Unit = {
|
def HandleVehicleServiceResponse(toChannel : String, guid : PlanetSideGUID, reply : VehicleResponse.Response) : Unit = {
|
||||||
val tplayer_guid = if(player.HasGUID) player.GUID
|
val tplayer_guid = if(player.HasGUID) player.GUID else PlanetSideGUID(0)
|
||||||
else PlanetSideGUID(0)
|
|
||||||
reply match {
|
|
||||||
case VehicleResponse.Ownership(vehicle_guid) =>
|
|
||||||
sendResponse(PlanetsideAttributeMessage(guid, 21, vehicle_guid.guid))
|
|
||||||
|
|
||||||
|
reply match {
|
||||||
case VehicleResponse.AttachToRails(vehicle_guid, pad_guid) =>
|
case VehicleResponse.AttachToRails(vehicle_guid, pad_guid) =>
|
||||||
sendResponse(ObjectAttachMessage(pad_guid, vehicle_guid, 3))
|
sendResponse(ObjectAttachMessage(pad_guid, vehicle_guid, 3))
|
||||||
|
|
||||||
|
|
@ -1881,6 +1944,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
sendResponse(ObjectAttachMessage(vehicle_guid, guid, seat))
|
sendResponse(ObjectAttachMessage(vehicle_guid, guid, seat))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case VehicleResponse.Ownership(vehicle_guid) =>
|
||||||
|
sendResponse(PlanetsideAttributeMessage(guid, 21, vehicle_guid.guid))
|
||||||
|
|
||||||
case VehicleResponse.PlanetsideAttribute(vehicle_guid, attribute_type, attribute_value) =>
|
case VehicleResponse.PlanetsideAttribute(vehicle_guid, attribute_type, attribute_value) =>
|
||||||
if(tplayer_guid != guid) {
|
if(tplayer_guid != guid) {
|
||||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, attribute_type, attribute_value))
|
sendResponse(PlanetsideAttributeMessage(vehicle_guid, attribute_type, attribute_value))
|
||||||
|
|
@ -1906,7 +1972,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
case VehicleResponse.UnloadVehicle(vehicle_guid) =>
|
case VehicleResponse.UnloadVehicle(vehicle, vehicle_guid) =>
|
||||||
|
BeforeUnloadVehicle(vehicle)
|
||||||
sendResponse(ObjectDeleteMessage(vehicle_guid, 0))
|
sendResponse(ObjectDeleteMessage(vehicle_guid, 0))
|
||||||
|
|
||||||
case VehicleResponse.UnstowEquipment(item_guid) =>
|
case VehicleResponse.UnstowEquipment(item_guid) =>
|
||||||
|
|
@ -2079,9 +2146,15 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
val wep = slot.Equipment.get
|
val wep = slot.Equipment.get
|
||||||
avatarService ! AvatarServiceMessage(continentId, AvatarAction.ObjectDelete(Service.defaultPlayerGUID, wep.GUID))
|
avatarService ! AvatarServiceMessage(continentId, AvatarAction.ObjectDelete(Service.defaultPlayerGUID, wep.GUID))
|
||||||
})
|
})
|
||||||
if(target.Definition == GlobalDefinitions.ams) {
|
target.Definition match {
|
||||||
target.Actor ! Deployment.TryDeploymentChange(DriveState.Undeploying)
|
case GlobalDefinitions.ams =>
|
||||||
ClearCurrentAmsSpawnPoint()
|
target.Actor ! Deployment.TryDeploymentChange(DriveState.Undeploying)
|
||||||
|
ClearCurrentAmsSpawnPoint()
|
||||||
|
case GlobalDefinitions.router =>
|
||||||
|
target.Actor ! Deployment.TryDeploymentChange(DriveState.Undeploying)
|
||||||
|
BeforeUnloadVehicle(target)
|
||||||
|
localService ! LocalServiceMessage(continent.Id, LocalAction.ToggleTeleportSystem(PlanetSideGUID(0), target, None))
|
||||||
|
case _ => ;
|
||||||
}
|
}
|
||||||
avatarService ! AvatarServiceMessage(continentId, AvatarAction.Destroy(targetGUID, playerGUID, playerGUID, target.Position))
|
avatarService ! AvatarServiceMessage(continentId, AvatarAction.Destroy(targetGUID, playerGUID, playerGUID, target.Position))
|
||||||
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(target), continent))
|
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(target), continent))
|
||||||
|
|
@ -2590,6 +2663,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
normal
|
||||||
|
.filter(_.Definition.DeployCategory == DeployableCategory.Sensors)
|
||||||
|
.foreach(obj => { sendResponse(TriggerEffectMessage(obj.GUID, "on", true, 1000)) })
|
||||||
//draw our faction's deployables on the map
|
//draw our faction's deployables on the map
|
||||||
continent.DeployableList
|
continent.DeployableList
|
||||||
.filter(obj => obj.Faction == faction && obj.Health > 0)
|
.filter(obj => obj.Faction == faction && obj.Health > 0)
|
||||||
|
|
@ -2624,7 +2700,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
}
|
}
|
||||||
//load vehicles in zone
|
//load vehicles in zone
|
||||||
val (wreckages, vehicles) = continent.Vehicles.partition(vehicle => { vehicle.Health == 0 && vehicle.Definition.DestroyedModel.nonEmpty })
|
val (wreckages, vehicles) = continent.Vehicles.partition(vehicle => { vehicle.Health == 0 && vehicle.Definition.DestroyedModel.nonEmpty })
|
||||||
//active vehicles
|
//active vehicles (and some wreckage)
|
||||||
vehicles.foreach(vehicle => {
|
vehicles.foreach(vehicle => {
|
||||||
val vehicle_guid = vehicle.GUID
|
val vehicle_guid = vehicle.GUID
|
||||||
val vdefinition = vehicle.Definition
|
val vdefinition = vehicle.Definition
|
||||||
|
|
@ -2646,22 +2722,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
})
|
})
|
||||||
ReloadVehicleAccessPermissions(vehicle)
|
ReloadVehicleAccessPermissions(vehicle)
|
||||||
})
|
})
|
||||||
//Loop over vehicles again to add cargohold occupants after all vehicles have been created on the local client
|
|
||||||
vehicles.foreach(vehicle => {
|
|
||||||
vehicle.CargoHolds.foreach({ case (cargo_num, cargo) => {
|
|
||||||
cargo.Occupant match {
|
|
||||||
case Some(cargo_vehicle) =>
|
|
||||||
if(cargo_vehicle.HasGUID) {
|
|
||||||
StartBundlingPackets()
|
|
||||||
sendResponse(ObjectAttachMessage(cargo_vehicle.GUID, vehicle.GUID, cargo_num))
|
|
||||||
//todo: attaching the vehicle seems to work, but setting the mount point status doesn't?
|
|
||||||
sendResponse(CargoMountPointStatusMessage(cargo_vehicle.GUID, vehicle.GUID, vehicle.GUID, PlanetSideGUID(0), cargo_num, CargoStatus.Occupied, 0))
|
|
||||||
StopBundlingPackets()
|
|
||||||
}
|
|
||||||
case None => ; // No vehicle in cargo
|
|
||||||
}
|
|
||||||
}})
|
|
||||||
})
|
|
||||||
//vehicle wreckages
|
//vehicle wreckages
|
||||||
wreckages.foreach(vehicle => {
|
wreckages.foreach(vehicle => {
|
||||||
sendResponse(
|
sendResponse(
|
||||||
|
|
@ -2672,6 +2732,30 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
//Loop over vehicles again to add cargohold occupants after all vehicles have been created on the local client
|
||||||
|
vehicles.filter(_.CargoHolds.nonEmpty).foreach(vehicle => {
|
||||||
|
vehicle.CargoHolds.foreach({ case (cargo_num, cargo) => {
|
||||||
|
cargo.Occupant match {
|
||||||
|
case Some(cargo_vehicle) =>
|
||||||
|
if(cargo_vehicle.HasGUID) {
|
||||||
|
sendResponse(ObjectAttachMessage(cargo_vehicle.GUID, vehicle.GUID, cargo_num))
|
||||||
|
//todo: attaching the vehicle seems to work, but setting the mount point status doesn't?
|
||||||
|
sendResponse(CargoMountPointStatusMessage(cargo_vehicle.GUID, vehicle.GUID, vehicle.GUID, PlanetSideGUID(0), cargo_num, CargoStatus.Occupied, 0))
|
||||||
|
}
|
||||||
|
case None => ; // No vehicle in cargo
|
||||||
|
}
|
||||||
|
}})
|
||||||
|
})
|
||||||
|
//special deploy states
|
||||||
|
val deployedVehicles = vehicles.filter(_.DeploymentState == DriveState.Deployed)
|
||||||
|
deployedVehicles.filter(_.Definition == GlobalDefinitions.ams).foreach(obj => {
|
||||||
|
sendResponse(PlanetsideAttributeMessage(obj.GUID, 81, 1))
|
||||||
|
})
|
||||||
|
deployedVehicles.filter(_.Definition == GlobalDefinitions.router).foreach(obj => {
|
||||||
|
sendResponse(DeployRequestMessage(player.GUID, obj.GUID, DriveState.Deploying, 0, false, Vector3.Zero))
|
||||||
|
sendResponse(DeployRequestMessage(player.GUID, obj.GUID, DriveState.Deployed, 0, false, Vector3.Zero))
|
||||||
|
ToggleTeleportSystem(obj, TelepadLike.AppraiseTeleportationSystem(obj, continent))
|
||||||
|
})
|
||||||
|
|
||||||
//implant terminals
|
//implant terminals
|
||||||
continent.Map.TerminalToInterface.foreach({ case ((terminal_guid, interface_guid)) =>
|
continent.Map.TerminalToInterface.foreach({ case ((terminal_guid, interface_guid)) =>
|
||||||
|
|
@ -3054,7 +3138,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
case Some(trigger : BoomerTrigger) =>
|
case Some(trigger : BoomerTrigger) =>
|
||||||
val playerGUID = player.GUID
|
val playerGUID = player.GUID
|
||||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ChangeFireState_Start(playerGUID, item_guid))
|
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ChangeFireState_Start(playerGUID, item_guid))
|
||||||
continent.GUID(trigger.Companion.getOrElse(PlanetSideGUID(0))) match {
|
continent.GUID(trigger.Companion) match {
|
||||||
case Some(boomer : BoomerDeployable) =>
|
case Some(boomer : BoomerDeployable) =>
|
||||||
val boomerGUID = boomer.GUID
|
val boomerGUID = boomer.GUID
|
||||||
boomer.Exploded = true
|
boomer.Exploded = true
|
||||||
|
|
@ -3231,7 +3315,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
|
|
||||||
case Some(obj : BoomerTrigger) =>
|
case Some(obj : BoomerTrigger) =>
|
||||||
if(FindEquipmentToDelete(object_guid, obj)) {
|
if(FindEquipmentToDelete(object_guid, obj)) {
|
||||||
continent.GUID(obj.Companion.getOrElse(PlanetSideGUID(0))) match {
|
continent.GUID(obj.Companion) match {
|
||||||
case Some(boomer : BoomerDeployable) =>
|
case Some(boomer : BoomerDeployable) =>
|
||||||
boomer.Trigger = None
|
boomer.Trigger = None
|
||||||
localService ! LocalServiceMessage.Deployables(RemoverActor.AddTask(boomer, continent, Some(0 seconds)))
|
localService ! LocalServiceMessage.Deployables(RemoverActor.AddTask(boomer, continent, Some(0 seconds)))
|
||||||
|
|
@ -3279,7 +3363,13 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
case None => ;
|
case None => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Some(obj : TelepadDeployable) =>
|
||||||
|
localService ! LocalServiceMessage.Telepads(SupportActor.ClearSpecific(List(obj), continent))
|
||||||
|
localService ! LocalServiceMessage.Deployables(RemoverActor.ClearSpecific(List(obj), continent))
|
||||||
|
localService ! LocalServiceMessage.Deployables(RemoverActor.AddTask(obj, continent, Some(0 seconds)))
|
||||||
|
|
||||||
case Some(obj : PlanetSideGameObject with Deployable) =>
|
case Some(obj : PlanetSideGameObject with Deployable) =>
|
||||||
|
localService ! LocalServiceMessage.Deployables(RemoverActor.ClearSpecific(List(obj), continent))
|
||||||
localService ! LocalServiceMessage.Deployables(RemoverActor.AddTask(obj, continent, Some(0 seconds)))
|
localService ! LocalServiceMessage.Deployables(RemoverActor.AddTask(obj, continent, Some(0 seconds)))
|
||||||
|
|
||||||
case Some(thing) =>
|
case Some(thing) =>
|
||||||
|
|
@ -3618,38 +3708,50 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
}
|
}
|
||||||
|
|
||||||
case Some(terminal : Terminal) =>
|
case Some(terminal : Terminal) =>
|
||||||
if(terminal.Definition.isInstanceOf[MatrixTerminalDefinition]) {
|
val tdef = terminal.Definition
|
||||||
//TODO matrix spawn point; for now, just blindly bind to show work (and hope nothing breaks)
|
val owned = terminal.Faction == player.Faction
|
||||||
sendResponse(BindPlayerMessage(1, "@ams", true, true, 0, 0, 0, terminal.Position))
|
val hacked = terminal.HackedBy.nonEmpty
|
||||||
}
|
if(owned) {
|
||||||
else if(terminal.Definition.isInstanceOf[RepairRearmSiloDefinition]) {
|
if(tdef.isInstanceOf[MatrixTerminalDefinition]) {
|
||||||
FindLocalVehicle match {
|
//TODO matrix spawn point; for now, just blindly bind to show work (and hope nothing breaks)
|
||||||
case Some(vehicle) =>
|
sendResponse(BindPlayerMessage(1, "@ams", true, true, 0, 0, 0, terminal.Position))
|
||||||
sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType))
|
}
|
||||||
sendResponse(UseItemMessage(avatar_guid, item_used_guid, vehicle.GUID, unk2, unk3, unk4, unk5, unk6, unk7, unk8, vehicle.Definition.ObjectId))
|
else if(tdef.isInstanceOf[RepairRearmSiloDefinition]) {
|
||||||
case None =>
|
FindLocalVehicle match {
|
||||||
log.error("UseItem: expected seated vehicle, but found none")
|
case Some(vehicle) =>
|
||||||
|
sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType))
|
||||||
|
sendResponse(UseItemMessage(avatar_guid, item_used_guid, vehicle.GUID, unk2, unk3, unk4, unk5, unk6, unk7, unk8, vehicle.Definition.ObjectId))
|
||||||
|
case None =>
|
||||||
|
log.error("UseItem: expected seated vehicle, but found none")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(tdef.isInstanceOf[TeleportPadTerminalDefinition]) {
|
||||||
|
//explicit request
|
||||||
|
terminal.Actor ! Terminal.Request(
|
||||||
|
player,
|
||||||
|
ItemTransactionMessage(object_guid, TransactionType.Buy, 0, "router_telepad", 0, PlanetSideGUID(0))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(hacked) {
|
||||||
|
sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType))
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if(terminal.Faction != player.Faction && terminal.HackedBy.isEmpty) {
|
player.Slot(player.DrawnSlot).Equipment match {
|
||||||
player.Slot(player.DrawnSlot).Equipment match {
|
case Some(tool: SimpleItem) =>
|
||||||
case Some(tool: SimpleItem) =>
|
if (tool.Definition == GlobalDefinitions.remote_electronics_kit) {
|
||||||
if (tool.Definition == GlobalDefinitions.remote_electronics_kit) {
|
val hackSpeed = GetPlayerHackSpeed(terminal)
|
||||||
val hackSpeed = GetPlayerHackSpeed(terminal)
|
|
||||||
|
|
||||||
if(hackSpeed > 0) {
|
if(hackSpeed > 0) {
|
||||||
progressBarValue = Some(-hackSpeed)
|
progressBarValue = Some(-hackSpeed)
|
||||||
self ! WorldSessionActor.HackingProgress(progressType = 1, player, terminal, tool.GUID, hackSpeed, FinishHacking(terminal, 3212836864L))
|
self ! WorldSessionActor.HackingProgress(progressType = 1, player, terminal, tool.GUID, hackSpeed, FinishHacking(terminal, 3212836864L))
|
||||||
log.info("Hacking a terminal")
|
log.info("Hacking a terminal")
|
||||||
}
|
|
||||||
}
|
}
|
||||||
case _ => ;
|
}
|
||||||
}
|
case _ => ;
|
||||||
} else if (terminal.Faction == player.Faction || !terminal.HackedBy.isEmpty) {
|
|
||||||
// If hacked only allow access to the faction that hacked it
|
|
||||||
// Otherwise allow the faction that owns the terminal to use it
|
|
||||||
sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3662,6 +3764,29 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
sendResponse(AvatarDeadStateMessage(DeadState.Release, 0, 0, player.Position, player.Faction, true))
|
sendResponse(AvatarDeadStateMessage(DeadState.Release, 0, 0, player.Position, player.Faction, true))
|
||||||
continent.Population ! Zone.Population.Release(avatar)
|
continent.Population ! Zone.Population.Release(avatar)
|
||||||
|
|
||||||
|
case Some(obj : TelepadDeployable) =>
|
||||||
|
continent.GUID(obj.Router) match {
|
||||||
|
case Some(vehicle : Vehicle) =>
|
||||||
|
vehicle.Utility(UtilityType.internal_router_telepad_deployable) match {
|
||||||
|
case Some(util : Utility.InternalTelepad) =>
|
||||||
|
UseRouterTelepadSystem(router = vehicle, internalTelepad = util, remoteTelepad = obj, src = obj, dest = util)
|
||||||
|
case _ =>
|
||||||
|
log.error(s"telepad@${object_guid.guid} is not linked to a router - ${vehicle.Definition.Name}@${obj.Router.get.guid}")
|
||||||
|
}
|
||||||
|
case Some(o) =>
|
||||||
|
log.error(s"telepad@${object_guid.guid} is linked to wrong kind of object - ${o.Definition.Name}@${obj.Router.get.guid}")
|
||||||
|
case None => ;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Some(obj : Utility.InternalTelepad) =>
|
||||||
|
continent.GUID(obj.Telepad) match {
|
||||||
|
case Some(pad : TelepadDeployable) =>
|
||||||
|
UseRouterTelepadSystem(router = obj.Owner.asInstanceOf[Vehicle], internalTelepad = obj, remoteTelepad = pad, src = obj, dest = pad)
|
||||||
|
case Some(o) =>
|
||||||
|
log.error(s"internal telepad@${object_guid.guid} is not linked to a remote telepad - ${o.Definition.Name}@${o.GUID.guid}")
|
||||||
|
case None => ;
|
||||||
|
}
|
||||||
|
|
||||||
case Some(obj) =>
|
case Some(obj) =>
|
||||||
log.warn(s"UseItem: don't know how to handle $obj; taking a shot in the dark")
|
log.warn(s"UseItem: don't know how to handle $obj; taking a shot in the dark")
|
||||||
sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType))
|
sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType))
|
||||||
|
|
@ -3719,7 +3844,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
case turret =>
|
case turret =>
|
||||||
turret
|
turret
|
||||||
}
|
}
|
||||||
log.info(s"Constructing a ${ammoType}")
|
log.info(s"DeployObject: Constructing a ${ammoType}")
|
||||||
val dObj : PlanetSideGameObject with Deployable = Deployables.Make(ammoType)()
|
val dObj : PlanetSideGameObject with Deployable = Deployables.Make(ammoType)()
|
||||||
dObj.Position = pos
|
dObj.Position = pos
|
||||||
dObj.Orientation = orient
|
dObj.Orientation = orient
|
||||||
|
|
@ -3735,9 +3860,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
taskResolver ! CallBackForTask(tasking, continent.Deployables, Zone.Deployable.Build(dObj, obj))
|
taskResolver ! CallBackForTask(tasking, continent.Deployables, Zone.Deployable.Build(dObj, obj))
|
||||||
|
|
||||||
case Some(obj) =>
|
case Some(obj) =>
|
||||||
log.warn(s"$obj is something?")
|
log.warn(s"DeployObject: $obj is something?")
|
||||||
case None =>
|
case None =>
|
||||||
log.warn("nothing?")
|
log.warn("DeployObject: nothing?")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3896,7 +4021,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
log.info(s"Hit: $msg")
|
log.info(s"Hit: $msg")
|
||||||
(hit_info match {
|
(hit_info match {
|
||||||
case Some(hitInfo) =>
|
case Some(hitInfo) =>
|
||||||
continent.GUID(hitInfo.hitobject_guid.get) match {
|
continent.GUID(hitInfo.hitobject_guid) match {
|
||||||
case Some(obj : Player) =>
|
case Some(obj : Player) =>
|
||||||
Some((obj, hitInfo.shot_origin, hitInfo.hit_pos))
|
Some((obj, hitInfo.shot_origin, hitInfo.hit_pos))
|
||||||
case Some(obj : Vehicle) =>
|
case Some(obj : Vehicle) =>
|
||||||
|
|
@ -3995,6 +4120,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
//todo: continue flight path until aircraft crashes if no passengers present (or no passenger seats), then deconstruct.
|
//todo: continue flight path until aircraft crashes if no passengers present (or no passenger seats), then deconstruct.
|
||||||
//todo: kick cargo passengers out. To be added after PR #216 is merged
|
//todo: kick cargo passengers out. To be added after PR #216 is merged
|
||||||
if(bailType == BailType.Bailed && seat_num == 0 && GlobalDefinitions.isFlightVehicle(obj.asInstanceOf[Vehicle].Definition)) {
|
if(bailType == BailType.Bailed && seat_num == 0 && GlobalDefinitions.isFlightVehicle(obj.asInstanceOf[Vehicle].Definition)) {
|
||||||
|
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(obj), continent))
|
||||||
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.AddTask(obj, continent, Some(0 seconds))) // Immediately deconstruct vehicle
|
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.AddTask(obj, continent, Some(0 seconds))) // Immediately deconstruct vehicle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4153,7 +4279,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
case msg @ TargetingImplantRequest(list) =>
|
case msg @ TargetingImplantRequest(list) =>
|
||||||
log.info("TargetingImplantRequest: "+msg)
|
log.info("TargetingImplantRequest: "+msg)
|
||||||
|
|
||||||
|
|
@ -4730,7 +4855,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
/**
|
/**
|
||||||
* Disassociate this client's player (oneself) from a vehicle that he owns.
|
* Disassociate this client's player (oneself) from a vehicle that he owns.
|
||||||
*/
|
*/
|
||||||
def DisownVehicle() : Unit = DisownVehicle(player)
|
def DisownVehicle() : Option[Vehicle] = DisownVehicle(player)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disassociate a player from a vehicle that he owns.
|
* Disassociate a player from a vehicle that he owns.
|
||||||
|
|
@ -4740,30 +4865,38 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
* @see `DisownVehicle(Player, Vehicle)`
|
* @see `DisownVehicle(Player, Vehicle)`
|
||||||
* @param tplayer the player
|
* @param tplayer the player
|
||||||
*/
|
*/
|
||||||
def DisownVehicle(tplayer : Player) : Unit = {
|
def DisownVehicle(tplayer : Player) : Option[Vehicle] = {
|
||||||
tplayer.VehicleOwned match {
|
tplayer.VehicleOwned match {
|
||||||
case Some(vehicle_guid) =>
|
case Some(vehicle_guid) =>
|
||||||
|
tplayer.VehicleOwned = None
|
||||||
continent.GUID(vehicle_guid) match {
|
continent.GUID(vehicle_guid) match {
|
||||||
case Some(vehicle : Vehicle) =>
|
case Some(vehicle : Vehicle) =>
|
||||||
DisownVehicle(tplayer, vehicle)
|
DisownVehicle(tplayer, vehicle)
|
||||||
case _ => ;
|
case _ =>
|
||||||
|
None
|
||||||
}
|
}
|
||||||
tplayer.VehicleOwned = None
|
case None =>
|
||||||
case None => ;
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disassociate a vehicle from the player that owns it.
|
* Disassociate a vehicle from the player that owns it, if that player really was the previous owner.
|
||||||
* When a vehicle is disowned
|
|
||||||
* This is the vehicle side of vehicle ownership removal.
|
* This is the vehicle side of vehicle ownership removal.
|
||||||
|
* Additionally, start the vehicle deconstruction timer.
|
||||||
* @see `DisownVehicle(Player)`
|
* @see `DisownVehicle(Player)`
|
||||||
* @param tplayer the player
|
* @param tplayer the player
|
||||||
* @param vehicle the discovered vehicle
|
* @param vehicle the discovered vehicle
|
||||||
*/
|
*/
|
||||||
private def DisownVehicle(tplayer : Player, vehicle : Vehicle) : Unit = {
|
private def DisownVehicle(tplayer : Player, vehicle : Vehicle) : Option[Vehicle] = {
|
||||||
if(vehicle.Owner.contains(tplayer.GUID)) {
|
if(vehicle.Owner.contains(tplayer.GUID)) {
|
||||||
vehicle.Owner = None
|
vehicle.Owner = None
|
||||||
|
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(vehicle), continent))
|
||||||
|
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.AddTask(vehicle, continent, vehicle.Definition.DeconstructionTime)) //start vehicle decay
|
||||||
|
Some(vehicle)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5299,13 +5432,18 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
*/
|
*/
|
||||||
def PermitEquipmentStow(equipment : Equipment, obj : PlanetSideGameObject with Container) : Boolean = {
|
def PermitEquipmentStow(equipment : Equipment, obj : PlanetSideGameObject with Container) : Boolean = {
|
||||||
equipment match {
|
equipment match {
|
||||||
case item : BoomerTrigger =>
|
case _ : BoomerTrigger =>
|
||||||
obj.isInstanceOf[Player] //a BoomerTrigger can only be stowed in a player's holsters or inventory
|
obj.isInstanceOf[Player] //a BoomerTrigger can only be stowed in a player's holsters or inventory
|
||||||
case _ =>
|
case _ =>
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* na
|
||||||
|
* @param tool na
|
||||||
|
* @param obj na
|
||||||
|
*/
|
||||||
def PerformToolAmmoChange(tool : Tool, obj : PlanetSideGameObject with Container) : Unit = {
|
def PerformToolAmmoChange(tool : Tool, obj : PlanetSideGameObject with Container) : Unit = {
|
||||||
val originalAmmoType = tool.AmmoType
|
val originalAmmoType = tool.AmmoType
|
||||||
do {
|
do {
|
||||||
|
|
@ -5514,6 +5652,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
* Drop the item if:<br>
|
* Drop the item if:<br>
|
||||||
* - the item is cavern equipment<br>
|
* - the item is cavern equipment<br>
|
||||||
* - the item is a `BoomerTrigger` type object<br>
|
* - the item is a `BoomerTrigger` type object<br>
|
||||||
|
* - the item is a `router_telepad` type object<br>
|
||||||
* - the item is another faction's exclusive equipment
|
* - the item is another faction's exclusive equipment
|
||||||
* @param tplayer the player
|
* @param tplayer the player
|
||||||
* @return true if the item is to be dropped; false, otherwise
|
* @return true if the item is to be dropped; false, otherwise
|
||||||
|
|
@ -5522,6 +5661,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
val objDef = entry.obj.Definition
|
val objDef = entry.obj.Definition
|
||||||
val faction = GlobalDefinitions.isFactionEquipment(objDef)
|
val faction = GlobalDefinitions.isFactionEquipment(objDef)
|
||||||
GlobalDefinitions.isCavernEquipment(objDef) ||
|
GlobalDefinitions.isCavernEquipment(objDef) ||
|
||||||
|
objDef == GlobalDefinitions.router_telepad ||
|
||||||
entry.obj.isInstanceOf[BoomerTrigger] ||
|
entry.obj.isInstanceOf[BoomerTrigger] ||
|
||||||
(faction != tplayer.Faction && faction != PlanetSideEmpire.NEUTRAL)
|
(faction != tplayer.Faction && faction != PlanetSideEmpire.NEUTRAL)
|
||||||
}
|
}
|
||||||
|
|
@ -5546,46 +5686,88 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform specific operations depending on the target of deployment.
|
* Perform specific operations depending on the target of deployment.
|
||||||
* @param obj the object that has deployed
|
* @param obj the object that has had its deployment state changed
|
||||||
*/
|
*/
|
||||||
def DeploymentActivities(obj : Deployment.DeploymentObject) : Unit = {
|
def DeploymentActivities(obj : Deployment.DeploymentObject) : Unit = {
|
||||||
|
DeploymentActivities(obj, obj.DeploymentState)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform specific operations depending on the target of deployment.
|
||||||
|
* @param obj the object that has had its deployment state changed
|
||||||
|
* @param state the new deployment state
|
||||||
|
*/
|
||||||
|
def DeploymentActivities(obj : Deployment.DeploymentObject, state : DriveState.Value) : Unit = {
|
||||||
obj match {
|
obj match {
|
||||||
case vehicle : Vehicle =>
|
case vehicle : Vehicle =>
|
||||||
ReloadVehicleAccessPermissions(vehicle) //TODO we should not have to do this imho
|
ReloadVehicleAccessPermissions(vehicle) //TODO we should not have to do this imho
|
||||||
|
//ams
|
||||||
if(obj.Definition == GlobalDefinitions.ams) {
|
if(vehicle.Definition == GlobalDefinitions.ams) {
|
||||||
obj.DeploymentState match {
|
state match {
|
||||||
case DriveState.Deployed =>
|
case DriveState.Deployed =>
|
||||||
vehicleService ! VehicleServiceMessage.AMSDeploymentChange(continent)
|
vehicleService ! VehicleServiceMessage.AMSDeploymentChange(continent)
|
||||||
sendResponse(PlanetsideAttributeMessage(obj.GUID, 81, 1))
|
sendResponse(PlanetsideAttributeMessage(vehicle.GUID, 81, 1))
|
||||||
case DriveState.Undeploying =>
|
case DriveState.Undeploying =>
|
||||||
vehicleService ! VehicleServiceMessage.AMSDeploymentChange(continent)
|
vehicleService ! VehicleServiceMessage.AMSDeploymentChange(continent)
|
||||||
sendResponse(PlanetsideAttributeMessage(obj.GUID, 81, 0))
|
sendResponse(PlanetsideAttributeMessage(vehicle.GUID, 81, 0))
|
||||||
case DriveState.Mobile | DriveState.State7 =>
|
case DriveState.Mobile | DriveState.State7 =>
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(obj.Definition == GlobalDefinitions.ant) {
|
//ant
|
||||||
obj.DeploymentState match {
|
else if(vehicle.Definition == GlobalDefinitions.ant) {
|
||||||
case DriveState.Deployed =>
|
state match {
|
||||||
// We only want this WSA (not other player's WSA) to manage timers
|
case DriveState.Deployed =>
|
||||||
if(vehicle.Seat(0).get.Occupant.contains(player)){
|
// We only want this WSA (not other player's WSA) to manage timers
|
||||||
// Start ntu regeneration
|
if(vehicle.Seat(0).get.Occupant.contains(player)){
|
||||||
// If vehicle sends UseItemMessage with silo as target NTU regeneration will be disabled and orb particles will be disabled
|
// Start ntu regeneration
|
||||||
antChargingTick = context.system.scheduler.scheduleOnce(1000 milliseconds, self, NtuCharging(player, vehicle))
|
// If vehicle sends UseItemMessage with silo as target NTU regeneration will be disabled and orb particles will be disabled
|
||||||
}
|
antChargingTick = context.system.scheduler.scheduleOnce(1000 milliseconds, self, NtuCharging(player, vehicle))
|
||||||
case DriveState.Undeploying =>
|
}
|
||||||
// We only want this WSA (not other player's WSA) to manage timers
|
case DriveState.Undeploying =>
|
||||||
if(vehicle.Seat(0).get.Occupant.contains(player)){
|
// We only want this WSA (not other player's WSA) to manage timers
|
||||||
antChargingTick.cancel() // Stop charging NTU if charging
|
if(vehicle.Seat(0).get.Occupant.contains(player)){
|
||||||
}
|
antChargingTick.cancel() // Stop charging NTU if charging
|
||||||
|
}
|
||||||
|
|
||||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(obj.GUID, 52, 0L)) // panel glow off
|
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(vehicle.GUID, 52, 0L)) // panel glow off
|
||||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(obj.GUID, 49, 0L)) // orb particles off
|
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(vehicle.GUID, 49, 0L)) // orb particles off
|
||||||
case DriveState.Mobile | DriveState.State7 | DriveState.Deploying =>
|
case DriveState.Mobile | DriveState.State7 | DriveState.Deploying =>
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
//router
|
||||||
|
else if(vehicle.Definition == GlobalDefinitions.router) {
|
||||||
|
state match {
|
||||||
|
case DriveState.Deploying =>
|
||||||
|
vehicle.Utility(UtilityType.internal_router_telepad_deployable) match {
|
||||||
|
case Some(util : Utility.InternalTelepad) =>
|
||||||
|
util.Active = true
|
||||||
|
case _ =>
|
||||||
|
log.warn(s"DeploymentActivities: could not find internal telepad in router@${vehicle.GUID.guid} while $state")
|
||||||
|
}
|
||||||
|
case DriveState.Deployed =>
|
||||||
|
//let the timer do all the work
|
||||||
|
localService ! LocalServiceMessage(continent.Id, LocalAction.ToggleTeleportSystem(PlanetSideGUID(0), vehicle, TelepadLike.AppraiseTeleportationSystem(vehicle, continent)))
|
||||||
|
case DriveState.Undeploying =>
|
||||||
|
//deactivate internal router before trying to reset the system
|
||||||
|
vehicle.Utility(UtilityType.internal_router_telepad_deployable) match {
|
||||||
|
case Some(util : Utility.InternalTelepad) =>
|
||||||
|
//any telepads linked with internal mechanism must be deconstructed
|
||||||
|
continent.GUID(util.Telepad) match {
|
||||||
|
case Some(telepad : TelepadDeployable) =>
|
||||||
|
localService ! LocalServiceMessage.Deployables(RemoverActor.ClearSpecific(List(telepad), continent))
|
||||||
|
localService ! LocalServiceMessage.Deployables(RemoverActor.AddTask(telepad, continent, Some(0 milliseconds)))
|
||||||
|
case Some(_) | None => ;
|
||||||
|
}
|
||||||
|
util.Active = false
|
||||||
|
localService ! LocalServiceMessage(continent.Id, LocalAction.ToggleTeleportSystem(PlanetSideGUID(0), vehicle, None))
|
||||||
|
case _ =>
|
||||||
|
log.warn(s"DeploymentActivities: could not find internal telepad in router@${vehicle.GUID.guid} while $state")
|
||||||
|
}
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
}
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5934,7 +6116,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
val triggers = RemoveBoomerTriggersFromInventory()
|
val triggers = RemoveBoomerTriggersFromInventory()
|
||||||
triggers.foreach(trigger =>{ NormalItemDrop(obj, continent, avatarService)(trigger) })
|
triggers.foreach(trigger => { NormalItemDrop(obj, continent, avatarService)(trigger) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -6628,7 +6810,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
val item = definition.Item
|
val item = definition.Item
|
||||||
val deployables = avatar.Deployables
|
val deployables = avatar.Deployables
|
||||||
val (curr, max) = deployables.CountDeployable(item)
|
val (curr, max) = deployables.CountDeployable(item)
|
||||||
log.info(s"FinalizeDeployable: ${definition.Name}")
|
log.info(s"DeployableBuildActivity: ${definition.Name}")
|
||||||
//two potential messages related to numerical limitations of deployables
|
//two potential messages related to numerical limitations of deployables
|
||||||
if(!avatar.Deployables.Available(obj)) {
|
if(!avatar.Deployables.Available(obj)) {
|
||||||
val (removed, msg) = {
|
val (removed, msg) = {
|
||||||
|
|
@ -6640,9 +6822,15 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
removed match {
|
removed match {
|
||||||
|
case Some(telepad : TelepadDeployable) =>
|
||||||
|
telepad.Owner = None
|
||||||
|
telepad.OwnerName = None
|
||||||
|
localService ! LocalServiceMessage.Deployables(RemoverActor.ClearSpecific(List(telepad), continent))
|
||||||
|
localService ! LocalServiceMessage.Deployables(RemoverActor.AddTask(telepad, continent, Some(0 seconds))) //normal decay
|
||||||
case Some(old) =>
|
case Some(old) =>
|
||||||
old.Position = Vector3.Zero
|
|
||||||
old.Owner = None
|
old.Owner = None
|
||||||
|
old.OwnerName = None
|
||||||
|
localService ! LocalServiceMessage.Deployables(RemoverActor.ClearSpecific(List(old), continent))
|
||||||
localService ! LocalServiceMessage.Deployables(RemoverActor.AddTask(old, continent, Some(0 seconds)))
|
localService ! LocalServiceMessage.Deployables(RemoverActor.AddTask(old, continent, Some(0 seconds)))
|
||||||
if(msg) { //max test
|
if(msg) { //max test
|
||||||
sendResponse(ChatMsg(ChatMessageType.UNK_229, false, "", s"@${definition.Descriptor}OldestDestroyed", None))
|
sendResponse(ChatMsg(ChatMessageType.UNK_229, false, "", s"@${definition.Descriptor}OldestDestroyed", None))
|
||||||
|
|
@ -6651,6 +6839,10 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
log.warn(s"DeployableBuildActivity: how awkward: we probably shouldn't be allowed to build this deployable right now")
|
log.warn(s"DeployableBuildActivity: how awkward: we probably shouldn't be allowed to build this deployable right now")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(obj.isInstanceOf[TelepadDeployable]) {
|
||||||
|
//always treat the telepad we are putting down as the first and only one
|
||||||
|
sendResponse(ObjectDeployedMessage.Success(definition.Name, 1, 1))
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
sendResponse(ObjectDeployedMessage.Success(definition.Name, curr + 1, max))
|
sendResponse(ObjectDeployedMessage.Success(definition.Name, curr + 1, max))
|
||||||
val (catCurr, catMax) = deployables.CountCategory(item)
|
val (catCurr, catMax) = deployables.CountCategory(item)
|
||||||
|
|
@ -6940,9 +7132,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
*/
|
*/
|
||||||
def RemoveBoomerTriggersFromInventory() : List[BoomerTrigger] = {
|
def RemoveBoomerTriggersFromInventory() : List[BoomerTrigger] = {
|
||||||
val player_guid = player.GUID
|
val player_guid = player.GUID
|
||||||
((player.Inventory.Items.collect({ case entry @ InventoryItem(obj : BoomerTrigger, index) => (obj, index) })) ++
|
val holstersWithIndex = player.Holsters().zipWithIndex
|
||||||
(player.Holsters()
|
((player.Inventory.Items.collect({ case InventoryItem(obj : BoomerTrigger, index) => (obj, index) })) ++
|
||||||
.zipWithIndex
|
(holstersWithIndex
|
||||||
.map({ case ((slot, index)) => (slot.Equipment, index) })
|
.map({ case ((slot, index)) => (slot.Equipment, index) })
|
||||||
.collect { case ((Some(obj : BoomerTrigger), index)) => (obj, index) }
|
.collect { case ((Some(obj : BoomerTrigger), index)) => (obj, index) }
|
||||||
)
|
)
|
||||||
|
|
@ -7128,6 +7320,158 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to link the router teleport system using the provided terminal information.
|
||||||
|
* Although additional states are necessary to properly use the teleportation system,
|
||||||
|
* e.g., deployment state, active state of the endpoints, etc.,
|
||||||
|
* this decision is not made factoring those other conditions.
|
||||||
|
* @param router the vehicle that houses one end of the teleportation system (the `InternalTelepad` object)
|
||||||
|
* @param systemPlan specific object identification of the two endpoints of the teleportation system;
|
||||||
|
* if absent, the knowable endpoint is deleted from the client reflexively
|
||||||
|
*/
|
||||||
|
def ToggleTeleportSystem(router : Vehicle, systemPlan : Option[(Utility.InternalTelepad, TelepadDeployable)]) : Unit = {
|
||||||
|
StartBundlingPackets()
|
||||||
|
systemPlan match {
|
||||||
|
case Some((internalTelepad, remoteTelepad)) =>
|
||||||
|
LinkRouterToRemoteTelepad(router, internalTelepad, remoteTelepad)
|
||||||
|
case _ =>
|
||||||
|
router.Utility(UtilityType.internal_router_telepad_deployable) match {
|
||||||
|
case Some(util : Utility.InternalTelepad) =>
|
||||||
|
sendResponse(ObjectDeleteMessage(util.GUID, 0))
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StopBundlingPackets()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link the router teleport system using the provided terminal information.
|
||||||
|
* The internal telepad is made known of the remote telepad, creating the link.
|
||||||
|
* @param router the vehicle that houses one end of the teleportation system (the `internalTelepad`)
|
||||||
|
* @param internalTelepad the endpoint of the teleportation system housed by the router
|
||||||
|
* @param remoteTelepad the endpoint of the teleportation system that exists in the environment
|
||||||
|
*/
|
||||||
|
def LinkRouterToRemoteTelepad(router : Vehicle, internalTelepad : Utility.InternalTelepad, remoteTelepad : TelepadDeployable) : Unit = {
|
||||||
|
internalTelepad.Telepad = remoteTelepad.GUID //necessary; backwards link to the (new) telepad
|
||||||
|
CreateRouterInternalTelepad(router, internalTelepad)
|
||||||
|
LinkRemoteTelepad(remoteTelepad.GUID)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the mechanism that serves as one endpoint of the linked router teleportation system.<br>
|
||||||
|
* <br>
|
||||||
|
* Technically, the mechanism - an `InternalTelepad` object - is always made to exist
|
||||||
|
* due to how the Router vehicle object is encoded into an `ObjectCreateMessage` packet.
|
||||||
|
* Regardless, that internal mechanism is created anew each time the system links a new remote telepad.
|
||||||
|
* @param router the vehicle that houses one end of the teleportation system (the `internalTelepad`)
|
||||||
|
* @param internalTelepad the endpoint of the teleportation system housed by the router
|
||||||
|
*/
|
||||||
|
def CreateRouterInternalTelepad(router : Vehicle, internalTelepad : PlanetSideGameObject with TelepadLike) : Unit = {
|
||||||
|
//create the interal telepad each time the link is made
|
||||||
|
val rguid = router.GUID
|
||||||
|
val uguid = internalTelepad.GUID
|
||||||
|
val udef = internalTelepad.Definition
|
||||||
|
/*
|
||||||
|
the following instantiation and configuration creates the internal Router component
|
||||||
|
normally dispatched while the Router is transitioned into its Deploying state
|
||||||
|
it is safe, however, to perform these actions at any time during and after the Deploying state
|
||||||
|
*/
|
||||||
|
sendResponse(
|
||||||
|
ObjectCreateMessage(
|
||||||
|
udef.ObjectId,
|
||||||
|
uguid,
|
||||||
|
ObjectCreateMessageParent(rguid, 2), //TODO stop assuming slot number
|
||||||
|
udef.Packet.ConstructorData(internalTelepad).get
|
||||||
|
)
|
||||||
|
)
|
||||||
|
sendResponse(GenericObjectActionMessage(uguid, 108))
|
||||||
|
sendResponse(GenericObjectActionMessage(uguid, 120))
|
||||||
|
/*
|
||||||
|
the following configurations create the interactive beam underneath the Deployed Router
|
||||||
|
normally dispatched after the warm-up timer has completed
|
||||||
|
*/
|
||||||
|
sendResponse(GenericObjectActionMessage(uguid, 108))
|
||||||
|
sendResponse(GenericObjectActionMessage(uguid, 112))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* na
|
||||||
|
* @param telepadGUID na
|
||||||
|
*/
|
||||||
|
def LinkRemoteTelepad(telepadGUID: PlanetSideGUID) : Unit = {
|
||||||
|
sendResponse(GenericObjectActionMessage(telepadGUID, 108))
|
||||||
|
sendResponse(GenericObjectActionMessage(telepadGUID, 112))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A player uses a fully-linked Router teleportation system.
|
||||||
|
* @param router the Router vehicle
|
||||||
|
* @param internalTelepad the internal telepad within the Router vehicle
|
||||||
|
* @param remoteTelepad the remote telepad that is currently associated with this Router
|
||||||
|
* @param src the origin of the teleportation (where the player starts)
|
||||||
|
* @param dest the destination of the teleportation (where the player is going)
|
||||||
|
*/
|
||||||
|
def UseRouterTelepadSystem(router: Vehicle, internalTelepad: InternalTelepad, remoteTelepad: TelepadDeployable, src: PlanetSideGameObject with TelepadLike, dest: PlanetSideGameObject with TelepadLike) = {
|
||||||
|
val time = System.nanoTime
|
||||||
|
if(time - recentTeleportAttempt > (2 seconds).toNanos && router.DeploymentState == DriveState.Deployed && internalTelepad.Active && remoteTelepad.Active) {
|
||||||
|
val pguid = player.GUID
|
||||||
|
val sguid = src.GUID
|
||||||
|
val dguid = dest.GUID
|
||||||
|
StartBundlingPackets()
|
||||||
|
sendResponse(PlayerStateShiftMessage(ShiftState(0, dest.Position, player.Orientation.z, player.Velocity)))
|
||||||
|
UseRouterTelepadEffect(pguid, sguid, dguid)
|
||||||
|
StopBundlingPackets()
|
||||||
|
// vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(router), continent))
|
||||||
|
// vehicleService ! VehicleServiceMessage.Decon(RemoverActor.AddTask(router, continent, router.Definition.DeconstructionTime))
|
||||||
|
localService ! LocalServiceMessage(continent.Id, LocalAction.RouterTelepadTransport(pguid, pguid, sguid, dguid))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log.warn(s"UseRouterTelepadSystem: can not teleport")
|
||||||
|
}
|
||||||
|
recentTeleportAttempt = time
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Animate(?) a player using a fully-linked Router teleportation system.
|
||||||
|
* In reality, this seems to do nothing visually?
|
||||||
|
* @param playerGUID the player being teleported
|
||||||
|
* @param srcGUID the origin of the teleportation
|
||||||
|
* @param destGUID the destination of the teleportation
|
||||||
|
*/
|
||||||
|
def UseRouterTelepadEffect(playerGUID : PlanetSideGUID, srcGUID : PlanetSideGUID, destGUID : PlanetSideGUID) : Unit = {
|
||||||
|
sendResponse(PlanetsideAttributeMessage(playerGUID, 64, 1)) //what does this do?
|
||||||
|
sendResponse(GenericObjectActionMessage(srcGUID, 124))
|
||||||
|
sendResponse(GenericObjectActionMessage(destGUID, 128))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Before a vehicle is removed from the game world, the following actions must be performed.
|
||||||
|
* @param vehicle the vehicle
|
||||||
|
*/
|
||||||
|
def BeforeUnloadVehicle(vehicle : Vehicle) : Unit = {
|
||||||
|
vehicle.Definition match {
|
||||||
|
case GlobalDefinitions.router =>
|
||||||
|
log.info("BeforeUnload: cleaning up after a router ...")
|
||||||
|
(vehicle.Utility(UtilityType.internal_router_telepad_deployable) match {
|
||||||
|
case Some(util : Utility.InternalTelepad) =>
|
||||||
|
val telepad = util.Telepad
|
||||||
|
util.Active = false
|
||||||
|
util.Telepad = None
|
||||||
|
continent.GUID(telepad)
|
||||||
|
case _ =>
|
||||||
|
None
|
||||||
|
}) match {
|
||||||
|
case Some(telepad : TelepadDeployable) =>
|
||||||
|
log.info(s"BeforeUnload: deconstructing telepad $telepad that was linked to router $vehicle ...")
|
||||||
|
telepad.Active = false
|
||||||
|
localService ! LocalServiceMessage.Deployables(RemoverActor.ClearSpecific(List(telepad), continent))
|
||||||
|
localService ! LocalServiceMessage.Deployables(RemoverActor.AddTask(telepad, continent, Some(0 seconds)))
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def failWithError(error : String) = {
|
def failWithError(error : String) = {
|
||||||
log.error(error)
|
log.error(error)
|
||||||
sendResponse(ConnectionClose())
|
sendResponse(ConnectionClose())
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue