mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-20 02:24:45 +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
|
|
@ -22,7 +22,8 @@ object Deployables {
|
|||
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_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) } )
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -642,6 +642,8 @@ object GlobalDefinitions {
|
|||
|
||||
val advanced_ace = ConstructionItemDefinition(CItem.advanced_ace)
|
||||
|
||||
val router_telepad = ConstructionItemDefinition(CItem.router_telepad)
|
||||
|
||||
val fury_weapon_systema = ToolDefinition(ObjectClass.fury_weapon_systema)
|
||||
|
||||
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 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()
|
||||
|
||||
/*
|
||||
|
|
@ -894,6 +900,8 @@ object GlobalDefinitions {
|
|||
|
||||
val respawn_tube_tower = new SpawnTubeDefinition(733)
|
||||
|
||||
val teleportpad_terminal = new TeleportPadTerminalDefinition
|
||||
|
||||
val adv_med_terminal = new MedicalTerminalDefinition(38)
|
||||
|
||||
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.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.Size = EquipmentSize.VehicleWeapon
|
||||
fury_weapon_systema.AmmoTypes += hellfire_ammo
|
||||
|
|
@ -5121,6 +5136,8 @@ object GlobalDefinitions {
|
|||
router.MaxShields = 800 + 1
|
||||
router.Seats += 0 -> new SeatDefinition()
|
||||
router.MountPoints += 1 -> 0
|
||||
router.Utilities += 1 -> UtilityType.teleportpad_terminal
|
||||
router.Utilities += 2 -> UtilityType.internal_router_telepad_deployable
|
||||
router.TrunkSize = InventoryTile.Tile1511
|
||||
router.TrunkOffset = 30
|
||||
router.Deployment = true
|
||||
|
|
@ -5515,5 +5532,16 @@ object GlobalDefinitions {
|
|||
deployable_shield_generator.MaxHealth = 1700
|
||||
deployable_shield_generator.DeployTime = Duration.create(6000, "ms")
|
||||
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
|
||||
|
||||
/**
|
||||
* 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`
|
||||
* @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 UndeployTime = Definition.UndeployTime
|
||||
|
|
|
|||
|
|
@ -29,12 +29,13 @@ class DeployableToolbox {
|
|||
* keys: categories, values: quantity storage object
|
||||
*/
|
||||
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
|
||||
* keys: deployable types, values: quantity storage object
|
||||
*/
|
||||
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
|
||||
* keys: categories, values: deployable objects
|
||||
|
|
@ -523,8 +524,8 @@ object DeployableToolbox {
|
|||
}
|
||||
}
|
||||
if(certifications.contains(CertificationType.GroundSupport)) {
|
||||
counts(DeployedItem.router_telepad_deployable).Max = 1
|
||||
categories(DeployableCategory.Telepads).Max = 1
|
||||
counts(DeployedItem.router_telepad_deployable).Max = 1024
|
||||
categories(DeployableCategory.Telepads).Max = 1024
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -589,9 +590,9 @@ object DeployableToolbox {
|
|||
AddToDeployableQuantities(counts, categories, FortificationEngineering, certificationSet ++ Set(FortificationEngineering))
|
||||
}
|
||||
|
||||
case GroundSupport =>
|
||||
counts(DeployedItem.router_telepad_deployable).Max = 1024
|
||||
categories(DeployableCategory.Telepads).Max = 1024
|
||||
// case GroundSupport =>
|
||||
// counts(DeployedItem.router_telepad_deployable).Max = 1024
|
||||
// categories(DeployableCategory.Telepads).Max = 1024
|
||||
|
||||
case _ => ;
|
||||
}
|
||||
|
|
@ -657,9 +658,9 @@ object DeployableToolbox {
|
|||
RemoveFromDeployablesQuantities(counts, categories, FortificationEngineering, certificationSet)
|
||||
}
|
||||
|
||||
case GroundSupport =>
|
||||
counts(DeployedItem.router_telepad_deployable).Max = 0
|
||||
categories(DeployableCategory.Telepads).Max = 0
|
||||
// case GroundSupport =>
|
||||
// counts(DeployedItem.router_telepad_deployable).Max = 0
|
||||
// categories(DeployableCategory.Telepads).Max = 0
|
||||
|
||||
case _ => ;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,7 +118,8 @@ object Deployable {
|
|||
DeployedItem.portable_manned_turret_tr.id -> DeployableIcon.FieldTurret,
|
||||
DeployedItem.portable_manned_turret_nc.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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
"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.
|
||||
|
|
@ -334,6 +338,13 @@ object EquipmentTerminalDefinition {
|
|||
*/
|
||||
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.
|
||||
* 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) {
|
||||
msg.transaction_type match {
|
||||
case TransactionType.Buy | TransactionType.Learn =>
|
||||
tdef.Buy(player, msg)
|
||||
Buy(player, msg)
|
||||
|
||||
case TransactionType.Sell =>
|
||||
tdef.Sell(player, msg)
|
||||
Sell(player, msg)
|
||||
|
||||
case TransactionType.Loadout =>
|
||||
tdef.Loadout(player, msg)
|
||||
Loadout(player, msg)
|
||||
|
||||
case _ =>
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,13 @@
|
|||
package net.psforever.objects.vehicles
|
||||
|
||||
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.terminals.{MatrixTerminalDefinition, OrderTerminalABDefinition, Terminal, TerminalDefinition}
|
||||
import net.psforever.objects.serverobject.terminals._
|
||||
import net.psforever.objects.serverobject.tube.{SpawnTube, SpawnTubeDefinition}
|
||||
import net.psforever.packet.game.{ItemTransactionMessage, PlanetSideGUID}
|
||||
|
||||
/**
|
||||
* An `Enumeration` of the available vehicular utilities.<br>
|
||||
|
|
@ -21,7 +24,9 @@ object UtilityType extends Enumeration {
|
|||
ams_respawn_tube,
|
||||
matrix_terminalc,
|
||||
order_terminala,
|
||||
order_terminalb
|
||||
order_terminalb,
|
||||
teleportpad_terminal,
|
||||
internal_router_telepad_deployable
|
||||
= Value
|
||||
}
|
||||
|
||||
|
|
@ -94,13 +99,17 @@ object Utility {
|
|||
new TerminalUtility(GlobalDefinitions.order_terminala)
|
||||
case UtilityType.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`.
|
||||
* @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 Orientation = Owner.Orientation
|
||||
}
|
||||
|
|
@ -109,11 +118,60 @@ object Utility {
|
|||
* 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
|
||||
*/
|
||||
private class TerminalUtility(tdef : TerminalDefinition) extends Terminal(tdef) {
|
||||
class TerminalUtility(tdef : TerminalDefinition) extends Terminal(tdef) {
|
||||
override def Position = Owner.Position
|
||||
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.
|
||||
* @param util the type of the `Amenity` object
|
||||
|
|
@ -128,5 +186,11 @@ object Utility {
|
|||
OrderTerminalABDefinition.Setup
|
||||
case UtilityType.order_terminalb =>
|
||||
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.
|
||||
* @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 rocklet = 737
|
||||
final val rotarychaingun_mosquito = 740
|
||||
final val router_telepad = 743
|
||||
final val router_telepad_deployable = 744
|
||||
final val scythe = 747
|
||||
final val six_shooter = 761
|
||||
final val skyguard_weapon_system = 788
|
||||
|
|
@ -276,7 +274,7 @@ object ObjectClass {
|
|||
final val nano_dispenser = 577
|
||||
final val command_detonater = 213
|
||||
final val flail_targeting_laser = 297
|
||||
//ace deployables
|
||||
//deployables
|
||||
final val ace = 32
|
||||
final val advanced_ace = 39
|
||||
final val boomer = 148
|
||||
|
|
@ -284,6 +282,8 @@ object ObjectClass {
|
|||
final val he_mine = 388
|
||||
final val jammer_mine = 420
|
||||
final val motionalarmsensor = 575
|
||||
final val router_telepad = 743
|
||||
final val router_telepad_deployable = 744
|
||||
final val sensor_shield = 752
|
||||
final val spitfire_aa = 819
|
||||
final val spitfire_cloaked = 825
|
||||
|
|
@ -602,7 +602,6 @@ object ObjectClass {
|
|||
case ObjectClass.repeater => ConstructorData.genericCodec(DetailedWeaponData.codec, "weapon")
|
||||
case ObjectClass.rocklet => 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.skyguard_weapon_system => 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.nano_dispenser => ConstructorData.genericCodec(DetailedWeaponData.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")
|
||||
//ace deployable
|
||||
case ObjectClass.ace => ConstructorData.genericCodec(DetailedACEData.codec, "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")
|
||||
//other
|
||||
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.nano_dispenser => ConstructorData.genericCodec(WeaponData.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")
|
||||
//ace deployables
|
||||
//deployables
|
||||
case ObjectClass.ace => ConstructorData.genericCodec(ACEData.codec, "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")
|
||||
//vehicles?
|
||||
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.nano_dispenser => DroppedItemData.genericCodec(WeaponData.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")
|
||||
//ace deployables
|
||||
//deployables
|
||||
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 => 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_tr => 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
|
||||
case ObjectClass.hunter_seeker_missile_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.
|
||||
*/
|
||||
def ClearAll() : Unit = {
|
||||
trace("all tasks have been cleared")
|
||||
firstTask.cancel
|
||||
firstHeap = Nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
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.serverobject.PlanetSideServerObject
|
||||
import net.psforever.objects.serverobject.doors.Door
|
||||
import net.psforever.objects.serverobject.hackable.Hackable
|
||||
import net.psforever.objects.serverobject.terminals.CaptureTerminal
|
||||
import net.psforever.objects.vehicles.Utility
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.game._
|
||||
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 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 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 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 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
|
||||
|
||||
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.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 ObjectDelete(item_guid : PlanetSideGUID, unk : Int) 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 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.terminals.CaptureTerminal
|
||||
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.objects.vital.Vitality
|
||||
import net.psforever.types.Vector3
|
||||
import services.local.support.{DeployableRemover, DoorCloseActor, HackClearActor, HackCaptureActor}
|
||||
import services.local.support._
|
||||
import services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||
import services.{GenericEventBus, Service, ServiceManager}
|
||||
import services.{GenericEventBus, RemoverActor, Service, ServiceManager}
|
||||
|
||||
import scala.util.Success
|
||||
import scala.concurrent.duration._
|
||||
import akka.pattern.ask
|
||||
import net.psforever.objects.vehicles.{Utility, UtilityType}
|
||||
import services.ServiceManager.Lookup
|
||||
import services.support.SupportActor
|
||||
|
||||
import scala.concurrent.duration.Duration
|
||||
|
||||
class LocalService extends Actor {
|
||||
|
|
@ -26,6 +29,7 @@ class LocalService extends Actor {
|
|||
private val hackClearer = context.actorOf(Props[HackClearActor], "local-hack-clearer")
|
||||
private val hackCapturer = context.actorOf(Props[HackCaptureActor], "local-hack-capturer")
|
||||
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
|
||||
var cluster : ActorRef = Actor.noSender
|
||||
|
||||
|
|
@ -111,10 +115,18 @@ class LocalService extends Actor {
|
|||
LocalEvents.publish(
|
||||
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) =>
|
||||
LocalEvents.publish(
|
||||
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) =>
|
||||
LocalEvents.publish(
|
||||
LocalServiceResponse(s"/$forChannel/Local", player_guid, LocalResponse.TriggerEffect(target, effect))
|
||||
|
|
@ -219,6 +231,12 @@ class LocalService extends Actor {
|
|||
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) =>
|
||||
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))
|
||||
)
|
||||
|
||||
//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
|
||||
case Vitality.DamageOn(target : Deployable, func) =>
|
||||
func(target)
|
||||
|
|
@ -236,6 +302,24 @@ class LocalService extends Actor {
|
|||
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>
|
||||
* <br>
|
||||
|
|
|
|||
|
|
@ -5,4 +5,6 @@ final case class LocalServiceMessage(forChannel : String, actionMessage : LocalA
|
|||
|
||||
object LocalServiceMessage {
|
||||
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
|
||||
val locatedTargets = for {
|
||||
a <- targets
|
||||
b <- list//.filter(entry => entry.zone == zone)
|
||||
b <- list
|
||||
if b.obj.HasGUID && a.obj.HasGUID && comparator.Test(b, a)
|
||||
} yield b
|
||||
if(locatedTargets.nonEmpty) {
|
||||
//b - entries, after the found targets are removed (cull any non-GUID entries while at it)
|
||||
val retained = for {
|
||||
a <- locatedTargets
|
||||
b <- list
|
||||
if b.obj.HasGUID && a.obj.HasGUID && !comparator.Test(b, a)
|
||||
} yield b
|
||||
(locatedTargets, retained)
|
||||
(locatedTargets, list filterNot locatedTargets.toSet)
|
||||
}
|
||||
else {
|
||||
(Nil, list)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
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.vehicles.Utility
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.PlanetSideGamePacket
|
||||
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 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 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 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
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
package services.vehicle
|
||||
|
||||
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.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
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 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 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 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
|
||||
|
|
|
|||
|
|
@ -105,10 +105,10 @@ class VehicleService extends Actor {
|
|||
VehicleEvents.publish(
|
||||
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
|
||||
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) =>
|
||||
VehicleEvents.publish(
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ package services.vehicle.support
|
|||
import net.psforever.objects.Vehicle
|
||||
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.types.DriveState
|
||||
import services.{RemoverActor, Service}
|
||||
import services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||
|
||||
|
|
@ -43,8 +44,9 @@ class VehicleRemover extends RemoverActor {
|
|||
override def SecondJob(entry : RemoverActor.Entry) : Unit = {
|
||||
val vehicle = entry.obj.asInstanceOf[Vehicle]
|
||||
val zone = entry.zone
|
||||
vehicle.DeploymentState = DriveState.Mobile
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package base
|
||||
|
||||
// Copyright (c) 2017 PSForever
|
||||
import akka.actor.ActorSystem
|
||||
import akka.actor.{Actor, ActorRef, ActorSystem, Props}
|
||||
import akka.testkit.{ImplicitSender, TestKit}
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||
|
|
@ -48,4 +48,28 @@ object ActorTest {
|
|||
}
|
||||
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.serverobject.terminals.Terminal
|
||||
import net.psforever.objects.serverobject.tube.SpawnTube
|
||||
import net.psforever.objects.vehicles.UtilityType
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
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 {
|
||||
"convert" in {
|
||||
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 {
|
||||
val avatar = Avatar("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
val obj : Player = {
|
||||
|
|
@ -525,6 +628,15 @@ class ConverterTest extends Specification {
|
|||
ams.Definition.Packet.ConstructorData(ams).isSuccess mustEqual true
|
||||
//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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
class TurretInitializer(obj : TurretDeployable) extends Actor {
|
||||
def receive : Receive = {
|
||||
|
|
|
|||
|
|
@ -20,10 +20,12 @@ class DeployableToolboxTest extends Specification {
|
|||
obj.Initialize(Set())
|
||||
val list = obj.UpdateUI()
|
||||
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
|
||||
max mustEqual 0
|
||||
})
|
||||
routers.length mustEqual 1
|
||||
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_vs)._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 {
|
||||
|
|
@ -64,7 +66,7 @@ class DeployableToolboxTest extends Specification {
|
|||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._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.router_telepad_deployable)._2 mustEqual 0
|
||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||
}
|
||||
|
||||
"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_vs)._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 {
|
||||
|
|
@ -104,7 +106,7 @@ class DeployableToolboxTest extends Specification {
|
|||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._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.router_telepad_deployable)._2 mustEqual 0
|
||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||
}
|
||||
|
||||
"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_vs)._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 {
|
||||
|
|
@ -144,7 +146,7 @@ class DeployableToolboxTest extends Specification {
|
|||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._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.router_telepad_deployable)._2 mustEqual 0
|
||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||
}
|
||||
|
||||
"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_vs)._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 {
|
||||
|
|
@ -183,7 +186,7 @@ class DeployableToolboxTest extends Specification {
|
|||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._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.router_telepad_deployable)._2 mustEqual 0
|
||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||
|
||||
obj.Initialize(Set(AdvancedEngineering)) mustEqual false
|
||||
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_vs)._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 {
|
||||
|
|
@ -240,7 +243,7 @@ class DeployableToolboxTest extends Specification {
|
|||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._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.router_telepad_deployable)._2 mustEqual 0
|
||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||
|
||||
obj.AddToDeployableQuantities(
|
||||
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_vs)._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(
|
||||
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_vs)._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(
|
||||
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_vs)._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(
|
||||
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_vs)._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(
|
||||
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_vs)._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 {
|
||||
|
|
@ -360,7 +363,7 @@ class DeployableToolboxTest extends Specification {
|
|||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._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.router_telepad_deployable)._2 mustEqual 0
|
||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||
|
||||
obj.AddToDeployableQuantities(
|
||||
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_vs)._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(
|
||||
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_vs)._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 {
|
||||
|
|
@ -440,7 +443,7 @@ class DeployableToolboxTest extends Specification {
|
|||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._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.router_telepad_deployable)._2 mustEqual 1
|
||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||
|
||||
obj.RemoveFromDeployableQuantities(
|
||||
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_vs)._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(
|
||||
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_vs)._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(
|
||||
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_vs)._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(
|
||||
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_vs)._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(
|
||||
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_vs)._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 {
|
||||
|
|
@ -560,7 +563,7 @@ class DeployableToolboxTest extends Specification {
|
|||
obj.CountDeployable(DeployedItem.portable_manned_turret_tr)._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.router_telepad_deployable)._2 mustEqual 0
|
||||
obj.CountDeployable(DeployedItem.router_telepad_deployable)._2 mustEqual 1024
|
||||
|
||||
obj.RemoveFromDeployableQuantities(
|
||||
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_vs)._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 {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import net.psforever.objects._
|
|||
import net.psforever.objects.equipment._
|
||||
import net.psforever.objects.inventory.InventoryTile
|
||||
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.packet.game.PlanetSideGUID
|
||||
import net.psforever.types.CertificationType
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package objects
|
|||
|
||||
import akka.actor.{Actor, ActorRef, Props}
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.{GlobalDefinitions, Vehicle}
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
import net.psforever.objects.vehicles._
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
|
|
@ -18,7 +18,7 @@ class UtilityTest extends Specification {
|
|||
obj.UtilType mustEqual UtilityType.order_terminala
|
||||
obj().isInstanceOf[Terminal] mustEqual true
|
||||
obj().asInstanceOf[Terminal].Definition.ObjectId mustEqual 613
|
||||
obj().asInstanceOf[Terminal].Actor == ActorRef.noSender
|
||||
obj().asInstanceOf[Terminal].Actor mustEqual ActorRef.noSender
|
||||
}
|
||||
|
||||
"create an order_terminalb object" in {
|
||||
|
|
@ -26,7 +26,7 @@ class UtilityTest extends Specification {
|
|||
obj.UtilType mustEqual UtilityType.order_terminalb
|
||||
obj().isInstanceOf[Terminal] mustEqual true
|
||||
obj().asInstanceOf[Terminal].Definition.ObjectId mustEqual 614
|
||||
obj().asInstanceOf[Terminal].Actor == ActorRef.noSender
|
||||
obj().asInstanceOf[Terminal].Actor mustEqual ActorRef.noSender
|
||||
}
|
||||
|
||||
"create a matrix_terminalc object" in {
|
||||
|
|
@ -34,7 +34,7 @@ class UtilityTest extends Specification {
|
|||
obj.UtilType mustEqual UtilityType.matrix_terminalc
|
||||
obj().isInstanceOf[Terminal] mustEqual true
|
||||
obj().asInstanceOf[Terminal].Definition.ObjectId mustEqual 519
|
||||
obj().asInstanceOf[Terminal].Actor == ActorRef.noSender
|
||||
obj().asInstanceOf[Terminal].Actor mustEqual ActorRef.noSender
|
||||
}
|
||||
|
||||
"create an ams_respawn_tube object" in {
|
||||
|
|
@ -43,7 +43,53 @@ class UtilityTest extends Specification {
|
|||
obj.UtilType mustEqual UtilityType.ams_respawn_tube
|
||||
obj().isInstanceOf[SpawnTube] mustEqual true
|
||||
obj().asInstanceOf[SpawnTube].Definition.ObjectId mustEqual 49
|
||||
obj().asInstanceOf[SpawnTube].Actor == 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 {
|
||||
|
|
@ -71,10 +117,25 @@ class UtilityTest extends Specification {
|
|||
obj().Position mustEqual veh.Position
|
||||
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 {
|
||||
"wire an order_terminala Actor" in {
|
||||
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 {
|
||||
"wire an order_terminalb Actor" in {
|
||||
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 {
|
||||
"wire a matrix_terminalc Actor" in {
|
||||
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 {
|
||||
"wire an ams_respawn_tube Actor" in {
|
||||
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 {
|
||||
val vehicle = Vehicle(GlobalDefinitions.quadstealth)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package service
|
|||
|
||||
import akka.actor.Props
|
||||
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.packet.game._
|
||||
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 {
|
||||
ServiceManager.boot(system)
|
||||
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 {
|
||||
ServiceManager.boot(system)
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import akka.actor.{ActorRef, Props}
|
|||
import akka.routing.RandomPool
|
||||
import akka.testkit.TestProbe
|
||||
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.equipment.Equipment
|
||||
import net.psforever.objects.guid.TaskResolver
|
||||
|
|
@ -21,24 +21,26 @@ import scala.concurrent.duration._
|
|||
// "RemoverActor" should {
|
||||
// "handle a simple task" in {
|
||||
// expectNoMsg(500 milliseconds)
|
||||
// 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(RemoverActorTest.TestObject, Zone.Nowhere)
|
||||
//
|
||||
// val reply1 = probe.receiveOne(200 milliseconds)
|
||||
// val reply1 = receiveOne(500 milliseconds)
|
||||
// assert(reply1.isInstanceOf[RemoverActorTest.InclusionTestAlert])
|
||||
// val reply2 = probe.receiveOne(200 milliseconds)
|
||||
// val reply2 = receiveOne(500 milliseconds)
|
||||
// assert(reply2.isInstanceOf[RemoverActorTest.InitialJobAlert])
|
||||
// probe.expectNoMsg(1 seconds) //delay
|
||||
// val reply3 = probe.receiveOne(300 milliseconds)
|
||||
// expectNoMsg(1 seconds) //delay
|
||||
// val reply3 = receiveOne(500 milliseconds)
|
||||
// assert(reply3.isInstanceOf[RemoverActorTest.FirstJobAlert])
|
||||
// val reply4 = probe.receiveOne(300 milliseconds)
|
||||
// val reply4 = receiveOne(500 milliseconds)
|
||||
// assert(reply4.isInstanceOf[RemoverActorTest.ClearanceTestAlert])
|
||||
// val reply5 = probe.receiveOne(300 milliseconds)
|
||||
// val reply5 = receiveOne(500 milliseconds)
|
||||
// assert(reply5.isInstanceOf[RemoverActorTest.SecondJobAlert])
|
||||
// val reply6 = probe.receiveOne(500 milliseconds)
|
||||
// val reply6 = receiveOne(500 milliseconds)
|
||||
// assert(reply6.isInstanceOf[RemoverActorTest.DeletionTaskAlert])
|
||||
// val reply7 = probe.receiveOne(500 milliseconds)
|
||||
// val reply7 = receiveOne(500 milliseconds)
|
||||
// assert(reply7.isInstanceOf[RemoverActorTest.DeletionTaskRunAlert])
|
||||
// }
|
||||
// }
|
||||
|
|
@ -50,29 +52,31 @@ import scala.concurrent.duration._
|
|||
// "RemoverActor" should {
|
||||
// "handle a simple task (timed)" in {
|
||||
// expectNoMsg(500 milliseconds)
|
||||
// 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(RemoverActorTest.TestObject, Zone.Nowhere, Some(100 milliseconds))
|
||||
//
|
||||
// val reply1 = probe.receiveOne(200 milliseconds)
|
||||
// val reply1 = receiveOne(500 milliseconds)
|
||||
// assert(reply1.isInstanceOf[RemoverActorTest.InclusionTestAlert])
|
||||
// val reply2 = probe.receiveOne(200 milliseconds)
|
||||
// val reply2 = receiveOne(500 milliseconds)
|
||||
// assert(reply2.isInstanceOf[RemoverActorTest.InitialJobAlert])
|
||||
// //no delay
|
||||
// val reply3 = probe.receiveOne(300 milliseconds)
|
||||
// val reply3 = receiveOne(500 milliseconds)
|
||||
// assert(reply3.isInstanceOf[RemoverActorTest.FirstJobAlert])
|
||||
// val reply4 = probe.receiveOne(300 milliseconds)
|
||||
// val reply4 = receiveOne(500 milliseconds)
|
||||
// assert(reply4.isInstanceOf[RemoverActorTest.ClearanceTestAlert])
|
||||
// val reply5 = probe.receiveOne(300 milliseconds)
|
||||
// val reply5 = receiveOne(500 milliseconds)
|
||||
// assert(reply5.isInstanceOf[RemoverActorTest.SecondJobAlert])
|
||||
// val reply6 = probe.receiveOne(300 milliseconds)
|
||||
// val reply6 = receiveOne(500 milliseconds)
|
||||
// assert(reply6.isInstanceOf[RemoverActorTest.DeletionTaskAlert])
|
||||
// val reply7 = probe.receiveOne(300 milliseconds)
|
||||
// val reply7 = receiveOne(500 milliseconds)
|
||||
// assert(reply7.isInstanceOf[RemoverActorTest.DeletionTaskRunAlert])
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
|
||||
//class ExcludedRemoverActorTest extends ActorTest {
|
||||
// ServiceManager.boot ! ServiceManager.Register(RandomPool(2).props(Props[TaskResolver]), "taskResolver")
|
||||
// val AlternateTestObject = new PlanetSideGameObject() { def Definition = new ObjectDefinition(0) { } }
|
||||
|
|
@ -81,7 +85,10 @@ import scala.concurrent.duration._
|
|||
// "allow only specific objects" in {
|
||||
// expectNoMsg(500 milliseconds)
|
||||
// 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)
|
||||
//
|
||||
// val reply1 = probe.receiveOne(200 milliseconds)
|
||||
|
|
@ -91,7 +98,7 @@ import scala.concurrent.duration._
|
|||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
|
||||
//class MultipleRemoverActorTest extends ActorTest {
|
||||
// ServiceManager.boot ! ServiceManager.Register(RandomPool(2).props(Props[TaskResolver]), "taskResolver")
|
||||
// final val TestObject2 = new Equipment() { def Definition = new EquipmentDefinition(0) { GUID = PlanetSideGUID(2) } }
|
||||
|
|
@ -494,44 +501,44 @@ object RemoverActorTest {
|
|||
|
||||
final case class DeletionTaskRunAlert()
|
||||
|
||||
class TestRemover(probe : TestProbe) extends RemoverActor {
|
||||
class TestRemover extends RemoverActor {
|
||||
import net.psforever.objects.guid.{Task, TaskResolver}
|
||||
val FirstStandardDuration = 1 seconds
|
||||
|
||||
val SecondStandardDuration = 100 milliseconds
|
||||
|
||||
def InclusionTest(entry : RemoverActor.Entry) : Boolean = {
|
||||
probe.ref ! InclusionTestAlert()
|
||||
entry.obj.isInstanceOf[Equipment]
|
||||
context.parent ! InclusionTestAlert()
|
||||
true
|
||||
}
|
||||
|
||||
def InitialJob(entry : RemoverActor.Entry) : Unit = {
|
||||
probe.ref ! InitialJobAlert()
|
||||
context.parent ! InitialJobAlert()
|
||||
}
|
||||
|
||||
def FirstJob(entry : RemoverActor.Entry) : Unit = {
|
||||
probe.ref ! FirstJobAlert()
|
||||
context.parent ! FirstJobAlert()
|
||||
}
|
||||
|
||||
override def SecondJob(entry : RemoverActor.Entry) : Unit = {
|
||||
probe.ref ! SecondJobAlert()
|
||||
context.parent ! SecondJobAlert()
|
||||
super.SecondJob(entry)
|
||||
}
|
||||
|
||||
def ClearanceTest(entry : RemoverActor.Entry) : Boolean = {
|
||||
probe.ref ! ClearanceTestAlert()
|
||||
context.parent ! ClearanceTestAlert()
|
||||
true
|
||||
}
|
||||
|
||||
def DeletionTask(entry : RemoverActor.Entry) : TaskResolver.GiveTask = {
|
||||
probe.ref ! DeletionTaskAlert()
|
||||
context.parent ! DeletionTaskAlert()
|
||||
TaskResolver.GiveTask(new Task() {
|
||||
private val localProbe = probe
|
||||
private val localProbe = context.parent
|
||||
|
||||
override def isComplete = Task.Resolution.Success
|
||||
|
||||
def Execute(resolver : ActorRef) : Unit = {
|
||||
localProbe.ref ! DeletionTaskRunAlert()
|
||||
context.parent ! DeletionTaskRunAlert()
|
||||
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.avatar.{Certification, DeployableToolbox}
|
||||
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.converter.{CorpseConverter, DestroyedVehicleConverter}
|
||||
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.process.{AutoDriveControls, VehicleSpawnControlGuided}
|
||||
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.Terminal.TerminalMessage
|
||||
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.packet.game.objectcreate._
|
||||
import net.psforever.types._
|
||||
import services.{RemoverActor, _}
|
||||
import services.{RemoverActor, vehicle, _}
|
||||
import services.avatar.{AvatarAction, AvatarResponse, AvatarServiceMessage, AvatarServiceResponse}
|
||||
import services.galaxy.{GalaxyResponse, GalaxyServiceResponse}
|
||||
import services.local.{LocalAction, LocalResponse, LocalServiceMessage, LocalServiceResponse}
|
||||
|
|
@ -59,7 +59,9 @@ import scala.concurrent.{Await, Future}
|
|||
import scala.concurrent.duration._
|
||||
import scala.util.Success
|
||||
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 {
|
||||
|
||||
|
|
@ -95,6 +97,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
var whenUsedLastKit : Long = 0
|
||||
val projectiles : Array[Option[Projectile]] = Array.fill[Option[Projectile]](Projectile.RangeUID - Projectile.BaseUID)(None)
|
||||
var drawDeloyableIcon : PlanetSideGameObject with Deployable => Unit = RedrawDeployableIcons
|
||||
var recentTeleportAttempt : Long = 0
|
||||
|
||||
var amsSpawnPoint : Option[SpawnTube] = None
|
||||
var clientKeepAlive : Cancellable = DefaultCancellable.obj
|
||||
var progressBarUpdate : Cancellable = DefaultCancellable.obj
|
||||
|
|
@ -124,6 +128,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
vehicleService ! Service.Leave()
|
||||
avatarService ! Service.Leave()
|
||||
galaxyService ! Service.Leave()
|
||||
cluster ! Service.Leave()
|
||||
LivePlayerList.Remove(sessionId)
|
||||
if(player != null && player.HasGUID) {
|
||||
val player_guid = player.GUID
|
||||
|
|
@ -141,15 +146,15 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
})
|
||||
//handle orphaned deployables
|
||||
DisownDeployables()
|
||||
//clean up boomer triggers
|
||||
//clean up boomer triggers and telepads
|
||||
val equipment = (
|
||||
(player.Holsters()
|
||||
.zipWithIndex
|
||||
.map({ case ((slot, index)) => (index, slot.Equipment) })
|
||||
.collect { case ((index, Some(obj))) => InventoryItem(obj, index) }
|
||||
) ++ player.Inventory.Items)
|
||||
.filterNot({ case InventoryItem(obj, _) => obj.isInstanceOf[BoomerTrigger] })
|
||||
//TODO final character save before doing any of this
|
||||
.filterNot({ case InventoryItem(obj, _) => obj.isInstanceOf[BoomerTrigger] || obj.isInstanceOf[Telepad] })
|
||||
//TODO final character save before doing any of this (use equipment)
|
||||
continent.Population ! Zone.Population.Release(avatar)
|
||||
if(player.isAlive) {
|
||||
//actually being alive or manually deconstructing
|
||||
|
|
@ -206,13 +211,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case None =>
|
||||
None
|
||||
}) 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) =>
|
||||
mobj.Seat(mobj.PassengerInSeat(player).get).get.Occupant = None
|
||||
|
||||
|
|
@ -496,10 +494,11 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case building : Building =>
|
||||
log.info(s"Zone.Lattice.SpawnPoint: spawn point on $zone_id in building ${building.Id} selected")
|
||||
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
|
||||
//position the player alongside either of the AMS's terminals, facing away from it
|
||||
val side = if(System.currentTimeMillis() % 2 == 0) 1
|
||||
else -1
|
||||
val side = if(System.currentTimeMillis() % 2 == 0) 1 else -1
|
||||
//right | left
|
||||
val z = spawn_tube.Orientation.z
|
||||
val zrot = (z + 90) % 360
|
||||
|
|
@ -547,7 +546,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case Zone.Ground.ItemOnGround(item : BoomerTrigger, pos, orient) =>
|
||||
//dropped the trigger, no longer own the boomer; make certain whole faction is aware of that
|
||||
val playerGUID = player.GUID
|
||||
continent.GUID(item.Companion.getOrElse(PlanetSideGUID(0))) match {
|
||||
continent.GUID(item.Companion) match {
|
||||
case Some(obj : BoomerDeployable) =>
|
||||
val guid = obj.GUID
|
||||
val factionOnContinentChannel = s"${continent.Id}/${player.Faction}"
|
||||
|
|
@ -586,7 +585,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case Zone.Ground.ItemInHand(item : BoomerTrigger) =>
|
||||
if(PutItemInHand(item)) {
|
||||
//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) =>
|
||||
val guid = obj.GUID
|
||||
val playerGUID = player.GUID
|
||||
|
|
@ -632,6 +631,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case GlobalDefinitions.advanced_ace =>
|
||||
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))
|
||||
case GlobalDefinitions.router_telepad => ;
|
||||
case _ =>
|
||||
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)
|
||||
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) =>
|
||||
//tank_trap
|
||||
StartBundlingPackets()
|
||||
|
|
@ -1132,8 +1165,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
DeconstructDeployable(obj, guid, pos)
|
||||
}
|
||||
else {
|
||||
DeconstructDeployable(obj, guid, pos, obj.Orientation, if(obj.MountPoints.isEmpty) 2
|
||||
else 1)
|
||||
DeconstructDeployable(obj, guid, pos, obj.Orientation, if(obj.MountPoints.isEmpty) 2 else 1)
|
||||
}
|
||||
|
||||
case LocalResponse.EliminateDeployable(obj : ComplexDeployable, guid, pos) =>
|
||||
|
|
@ -1152,6 +1184,34 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
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) =>
|
||||
if(obj.Health == 0) {
|
||||
DeconstructDeployable(obj, guid, pos)
|
||||
|
|
@ -1215,9 +1275,20 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
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) =>
|
||||
sendResponse(SetEmpireMessage(object_guid, empire))
|
||||
|
||||
case LocalResponse.ToggleTeleportSystem(router, system_plan) =>
|
||||
ToggleTeleportSystem(router, system_plan)
|
||||
|
||||
case LocalResponse.TriggerEffect(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 player_guid : PlanetSideGUID = tplayer.GUID
|
||||
log.info(s"MountVehicleMsg: $player_guid mounts $obj_guid @ $seat_num")
|
||||
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(obj), continent)) //clear timer
|
||||
PlayerActionsToCancel()
|
||||
sendResponse(PlanetsideAttributeMessage(obj_guid, 0, obj.Health))
|
||||
sendResponse(PlanetsideAttributeMessage(obj_guid, 68, 0)) //shield health
|
||||
sendResponse(PlanetsideAttributeMessage(obj_guid, 113, 0)) //capacitor
|
||||
if(seat_num == 0) {
|
||||
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(obj), continent)) //clear timer
|
||||
//simplistic vehicle ownership management
|
||||
obj.Owner match {
|
||||
case Some(owner_guid) =>
|
||||
|
|
@ -1288,8 +1359,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
})
|
||||
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)
|
||||
MountingAction(tplayer, obj, seat_num)
|
||||
|
||||
|
|
@ -1313,9 +1382,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
else {
|
||||
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, _) =>
|
||||
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))
|
||||
}
|
||||
|
||||
case Terminal.BuyEquipment(item) => ;
|
||||
case Terminal.BuyEquipment(item) =>
|
||||
tplayer.Fit(item) match {
|
||||
case Some(index) =>
|
||||
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Buy, true))
|
||||
|
|
@ -1797,12 +1863,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
* @param reply na
|
||||
*/
|
||||
def HandleVehicleServiceResponse(toChannel : String, guid : PlanetSideGUID, reply : VehicleResponse.Response) : Unit = {
|
||||
val tplayer_guid = if(player.HasGUID) player.GUID
|
||||
else PlanetSideGUID(0)
|
||||
reply match {
|
||||
case VehicleResponse.Ownership(vehicle_guid) =>
|
||||
sendResponse(PlanetsideAttributeMessage(guid, 21, vehicle_guid.guid))
|
||||
val tplayer_guid = if(player.HasGUID) player.GUID else PlanetSideGUID(0)
|
||||
|
||||
reply match {
|
||||
case VehicleResponse.AttachToRails(vehicle_guid, pad_guid) =>
|
||||
sendResponse(ObjectAttachMessage(pad_guid, vehicle_guid, 3))
|
||||
|
||||
|
|
@ -1881,6 +1944,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
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) =>
|
||||
if(tplayer_guid != guid) {
|
||||
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))
|
||||
|
||||
case VehicleResponse.UnstowEquipment(item_guid) =>
|
||||
|
|
@ -2079,9 +2146,15 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
val wep = slot.Equipment.get
|
||||
avatarService ! AvatarServiceMessage(continentId, AvatarAction.ObjectDelete(Service.defaultPlayerGUID, wep.GUID))
|
||||
})
|
||||
if(target.Definition == GlobalDefinitions.ams) {
|
||||
target.Actor ! Deployment.TryDeploymentChange(DriveState.Undeploying)
|
||||
ClearCurrentAmsSpawnPoint()
|
||||
target.Definition match {
|
||||
case GlobalDefinitions.ams =>
|
||||
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))
|
||||
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(target), continent))
|
||||
|
|
@ -2574,7 +2647,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
)
|
||||
//seated players
|
||||
obj.asInstanceOf[Mountable].Seats.values
|
||||
.map(_.Occupant)
|
||||
.map(_.Occupant)
|
||||
.collect {
|
||||
case Some(occupant) =>
|
||||
if(occupant.isAlive) {
|
||||
|
|
@ -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
|
||||
continent.DeployableList
|
||||
.filter(obj => obj.Faction == faction && obj.Health > 0)
|
||||
|
|
@ -2624,7 +2700,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
//load vehicles in zone
|
||||
val (wreckages, vehicles) = continent.Vehicles.partition(vehicle => { vehicle.Health == 0 && vehicle.Definition.DestroyedModel.nonEmpty })
|
||||
//active vehicles
|
||||
//active vehicles (and some wreckage)
|
||||
vehicles.foreach(vehicle => {
|
||||
val vehicle_guid = vehicle.GUID
|
||||
val vdefinition = vehicle.Definition
|
||||
|
|
@ -2646,22 +2722,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
})
|
||||
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
|
||||
wreckages.foreach(vehicle => {
|
||||
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
|
||||
continent.Map.TerminalToInterface.foreach({ case ((terminal_guid, interface_guid)) =>
|
||||
|
|
@ -3054,7 +3138,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case Some(trigger : BoomerTrigger) =>
|
||||
val playerGUID = player.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) =>
|
||||
val boomerGUID = boomer.GUID
|
||||
boomer.Exploded = true
|
||||
|
|
@ -3231,7 +3315,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
|
||||
case Some(obj : BoomerTrigger) =>
|
||||
if(FindEquipmentToDelete(object_guid, obj)) {
|
||||
continent.GUID(obj.Companion.getOrElse(PlanetSideGUID(0))) match {
|
||||
continent.GUID(obj.Companion) match {
|
||||
case Some(boomer : BoomerDeployable) =>
|
||||
boomer.Trigger = None
|
||||
localService ! LocalServiceMessage.Deployables(RemoverActor.AddTask(boomer, continent, Some(0 seconds)))
|
||||
|
|
@ -3279,7 +3363,13 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
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) =>
|
||||
localService ! LocalServiceMessage.Deployables(RemoverActor.ClearSpecific(List(obj), continent))
|
||||
localService ! LocalServiceMessage.Deployables(RemoverActor.AddTask(obj, continent, Some(0 seconds)))
|
||||
|
||||
case Some(thing) =>
|
||||
|
|
@ -3618,38 +3708,50 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
|
||||
case Some(terminal : Terminal) =>
|
||||
if(terminal.Definition.isInstanceOf[MatrixTerminalDefinition]) {
|
||||
//TODO matrix spawn point; for now, just blindly bind to show work (and hope nothing breaks)
|
||||
sendResponse(BindPlayerMessage(1, "@ams", true, true, 0, 0, 0, terminal.Position))
|
||||
}
|
||||
else if(terminal.Definition.isInstanceOf[RepairRearmSiloDefinition]) {
|
||||
FindLocalVehicle match {
|
||||
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")
|
||||
val tdef = terminal.Definition
|
||||
val owned = terminal.Faction == player.Faction
|
||||
val hacked = terminal.HackedBy.nonEmpty
|
||||
if(owned) {
|
||||
if(tdef.isInstanceOf[MatrixTerminalDefinition]) {
|
||||
//TODO matrix spawn point; for now, just blindly bind to show work (and hope nothing breaks)
|
||||
sendResponse(BindPlayerMessage(1, "@ams", true, true, 0, 0, 0, terminal.Position))
|
||||
}
|
||||
else if(tdef.isInstanceOf[RepairRearmSiloDefinition]) {
|
||||
FindLocalVehicle match {
|
||||
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 {
|
||||
if(terminal.Faction != player.Faction && terminal.HackedBy.isEmpty) {
|
||||
player.Slot(player.DrawnSlot).Equipment match {
|
||||
case Some(tool: SimpleItem) =>
|
||||
if (tool.Definition == GlobalDefinitions.remote_electronics_kit) {
|
||||
val hackSpeed = GetPlayerHackSpeed(terminal)
|
||||
player.Slot(player.DrawnSlot).Equipment match {
|
||||
case Some(tool: SimpleItem) =>
|
||||
if (tool.Definition == GlobalDefinitions.remote_electronics_kit) {
|
||||
val hackSpeed = GetPlayerHackSpeed(terminal)
|
||||
|
||||
if(hackSpeed > 0) {
|
||||
progressBarValue = Some(-hackSpeed)
|
||||
self ! WorldSessionActor.HackingProgress(progressType = 1, player, terminal, tool.GUID, hackSpeed, FinishHacking(terminal, 3212836864L))
|
||||
log.info("Hacking a terminal")
|
||||
}
|
||||
if(hackSpeed > 0) {
|
||||
progressBarValue = Some(-hackSpeed)
|
||||
self ! WorldSessionActor.HackingProgress(progressType = 1, player, terminal, tool.GUID, hackSpeed, FinishHacking(terminal, 3212836864L))
|
||||
log.info("Hacking a terminal")
|
||||
}
|
||||
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))
|
||||
}
|
||||
case _ => ;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3662,6 +3764,29 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
sendResponse(AvatarDeadStateMessage(DeadState.Release, 0, 0, player.Position, player.Faction, true))
|
||||
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) =>
|
||||
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))
|
||||
|
|
@ -3719,7 +3844,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case turret =>
|
||||
turret
|
||||
}
|
||||
log.info(s"Constructing a ${ammoType}")
|
||||
log.info(s"DeployObject: Constructing a ${ammoType}")
|
||||
val dObj : PlanetSideGameObject with Deployable = Deployables.Make(ammoType)()
|
||||
dObj.Position = pos
|
||||
dObj.Orientation = orient
|
||||
|
|
@ -3735,9 +3860,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
taskResolver ! CallBackForTask(tasking, continent.Deployables, Zone.Deployable.Build(dObj, obj))
|
||||
|
||||
case Some(obj) =>
|
||||
log.warn(s"$obj is something?")
|
||||
log.warn(s"DeployObject: $obj is something?")
|
||||
case None =>
|
||||
log.warn("nothing?")
|
||||
log.warn("DeployObject: nothing?")
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -3896,7 +4021,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
log.info(s"Hit: $msg")
|
||||
(hit_info match {
|
||||
case Some(hitInfo) =>
|
||||
continent.GUID(hitInfo.hitobject_guid.get) match {
|
||||
continent.GUID(hitInfo.hitobject_guid) match {
|
||||
case Some(obj : Player) =>
|
||||
Some((obj, hitInfo.shot_origin, hitInfo.hit_pos))
|
||||
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: 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)) {
|
||||
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(obj), continent))
|
||||
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 msg @ TargetingImplantRequest(list) =>
|
||||
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.
|
||||
*/
|
||||
def DisownVehicle() : Unit = DisownVehicle(player)
|
||||
def DisownVehicle() : Option[Vehicle] = DisownVehicle(player)
|
||||
|
||||
/**
|
||||
* Disassociate a player from a vehicle that he owns.
|
||||
|
|
@ -4740,30 +4865,38 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
* @see `DisownVehicle(Player, Vehicle)`
|
||||
* @param tplayer the player
|
||||
*/
|
||||
def DisownVehicle(tplayer : Player) : Unit = {
|
||||
def DisownVehicle(tplayer : Player) : Option[Vehicle] = {
|
||||
tplayer.VehicleOwned match {
|
||||
case Some(vehicle_guid) =>
|
||||
tplayer.VehicleOwned = None
|
||||
continent.GUID(vehicle_guid) match {
|
||||
case Some(vehicle : Vehicle) =>
|
||||
DisownVehicle(tplayer, vehicle)
|
||||
case _ => ;
|
||||
case _ =>
|
||||
None
|
||||
}
|
||||
tplayer.VehicleOwned = None
|
||||
case None => ;
|
||||
case None =>
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disassociate a vehicle from the player that owns it.
|
||||
* When a vehicle is disowned
|
||||
* Disassociate a vehicle from the player that owns it, if that player really was the previous owner.
|
||||
* This is the vehicle side of vehicle ownership removal.
|
||||
* Additionally, start the vehicle deconstruction timer.
|
||||
* @see `DisownVehicle(Player)`
|
||||
* @param tplayer the player
|
||||
* @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)) {
|
||||
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 = {
|
||||
equipment match {
|
||||
case item : BoomerTrigger =>
|
||||
case _ : BoomerTrigger =>
|
||||
obj.isInstanceOf[Player] //a BoomerTrigger can only be stowed in a player's holsters or inventory
|
||||
case _ =>
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* na
|
||||
* @param tool na
|
||||
* @param obj na
|
||||
*/
|
||||
def PerformToolAmmoChange(tool : Tool, obj : PlanetSideGameObject with Container) : Unit = {
|
||||
val originalAmmoType = tool.AmmoType
|
||||
do {
|
||||
|
|
@ -5514,6 +5652,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
* Drop the item if:<br>
|
||||
* - the item is cavern equipment<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
|
||||
* @param tplayer the player
|
||||
* @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 faction = GlobalDefinitions.isFactionEquipment(objDef)
|
||||
GlobalDefinitions.isCavernEquipment(objDef) ||
|
||||
objDef == GlobalDefinitions.router_telepad ||
|
||||
entry.obj.isInstanceOf[BoomerTrigger] ||
|
||||
(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.
|
||||
* @param obj the object that has deployed
|
||||
* @param obj the object that has had its deployment state changed
|
||||
*/
|
||||
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 {
|
||||
case vehicle : Vehicle =>
|
||||
ReloadVehicleAccessPermissions(vehicle) //TODO we should not have to do this imho
|
||||
|
||||
if(obj.Definition == GlobalDefinitions.ams) {
|
||||
obj.DeploymentState match {
|
||||
//ams
|
||||
if(vehicle.Definition == GlobalDefinitions.ams) {
|
||||
state match {
|
||||
case DriveState.Deployed =>
|
||||
vehicleService ! VehicleServiceMessage.AMSDeploymentChange(continent)
|
||||
sendResponse(PlanetsideAttributeMessage(obj.GUID, 81, 1))
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle.GUID, 81, 1))
|
||||
case DriveState.Undeploying =>
|
||||
vehicleService ! VehicleServiceMessage.AMSDeploymentChange(continent)
|
||||
sendResponse(PlanetsideAttributeMessage(obj.GUID, 81, 0))
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle.GUID, 81, 0))
|
||||
case DriveState.Mobile | DriveState.State7 =>
|
||||
case _ => ;
|
||||
}
|
||||
}
|
||||
if(obj.Definition == GlobalDefinitions.ant) {
|
||||
obj.DeploymentState match {
|
||||
case DriveState.Deployed =>
|
||||
// We only want this WSA (not other player's WSA) to manage timers
|
||||
if(vehicle.Seat(0).get.Occupant.contains(player)){
|
||||
// Start ntu regeneration
|
||||
// If vehicle sends UseItemMessage with silo as target NTU regeneration will be disabled and orb particles will be disabled
|
||||
antChargingTick = context.system.scheduler.scheduleOnce(1000 milliseconds, self, NtuCharging(player, vehicle))
|
||||
}
|
||||
case DriveState.Undeploying =>
|
||||
// We only want this WSA (not other player's WSA) to manage timers
|
||||
if(vehicle.Seat(0).get.Occupant.contains(player)){
|
||||
antChargingTick.cancel() // Stop charging NTU if charging
|
||||
}
|
||||
//ant
|
||||
else if(vehicle.Definition == GlobalDefinitions.ant) {
|
||||
state match {
|
||||
case DriveState.Deployed =>
|
||||
// We only want this WSA (not other player's WSA) to manage timers
|
||||
if(vehicle.Seat(0).get.Occupant.contains(player)){
|
||||
// Start ntu regeneration
|
||||
// If vehicle sends UseItemMessage with silo as target NTU regeneration will be disabled and orb particles will be disabled
|
||||
antChargingTick = context.system.scheduler.scheduleOnce(1000 milliseconds, self, NtuCharging(player, vehicle))
|
||||
}
|
||||
case DriveState.Undeploying =>
|
||||
// We only want this WSA (not other player's WSA) to manage timers
|
||||
if(vehicle.Seat(0).get.Occupant.contains(player)){
|
||||
antChargingTick.cancel() // Stop charging NTU if charging
|
||||
}
|
||||
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(obj.GUID, 52, 0L)) // panel glow off
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(obj.GUID, 49, 0L)) // orb particles off
|
||||
case DriveState.Mobile | DriveState.State7 | DriveState.Deploying =>
|
||||
case _ => ;
|
||||
}
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(vehicle.GUID, 52, 0L)) // panel glow off
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(vehicle.GUID, 49, 0L)) // orb particles off
|
||||
case DriveState.Mobile | DriveState.State7 | DriveState.Deploying =>
|
||||
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 _ => ;
|
||||
}
|
||||
}
|
||||
|
|
@ -5934,7 +6116,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
})
|
||||
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 deployables = avatar.Deployables
|
||||
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
|
||||
if(!avatar.Deployables.Available(obj)) {
|
||||
val (removed, msg) = {
|
||||
|
|
@ -6640,9 +6822,15 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
}
|
||||
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) =>
|
||||
old.Position = Vector3.Zero
|
||||
old.Owner = None
|
||||
old.OwnerName = None
|
||||
localService ! LocalServiceMessage.Deployables(RemoverActor.ClearSpecific(List(old), continent))
|
||||
localService ! LocalServiceMessage.Deployables(RemoverActor.AddTask(old, continent, Some(0 seconds)))
|
||||
if(msg) { //max test
|
||||
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")
|
||||
}
|
||||
}
|
||||
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 {
|
||||
sendResponse(ObjectDeployedMessage.Success(definition.Name, curr + 1, max))
|
||||
val (catCurr, catMax) = deployables.CountCategory(item)
|
||||
|
|
@ -6940,9 +7132,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
*/
|
||||
def RemoveBoomerTriggersFromInventory() : List[BoomerTrigger] = {
|
||||
val player_guid = player.GUID
|
||||
((player.Inventory.Items.collect({ case entry @ InventoryItem(obj : BoomerTrigger, index) => (obj, index) })) ++
|
||||
(player.Holsters()
|
||||
.zipWithIndex
|
||||
val holstersWithIndex = player.Holsters().zipWithIndex
|
||||
((player.Inventory.Items.collect({ case InventoryItem(obj : BoomerTrigger, index) => (obj, index) })) ++
|
||||
(holstersWithIndex
|
||||
.map({ case ((slot, index)) => (slot.Equipment, 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) = {
|
||||
log.error(error)
|
||||
sendResponse(ConnectionClose())
|
||||
|
|
|
|||
Loading…
Reference in a new issue