mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-19 18:44:45 +00:00
Building:
Replaces class object/serverobject/door/Base.scala. It performs nearly the exact same purpose but now has a list of owned objects called Amenities. Buildings are now a PlanetSideServerObject (PSSO), which allows them to have accept a *Control Actor and possess FactionAffinity. FoundationBuilder: FoundationBuilder : Building :: ServerObjectBuilder : [T <: PlanetSideServerObject] Amenity: Most PSSO's now accept Amenity as their parent in class hierarchy. Flagged PSSO's like Building and Vehicle are, on the other hand, capable of becoming the owner for these Amenity PSSOs, which allows them to inherit the same FactionAffinity. FactionAffinity: A trait that connects objects that are intended to communicate PlanetSideEmpire values. MountableBhevaior: Split between Mount and Dismount behavior. Passes appropriate messages to ensure coherent workflows. Control Actors: FactionAffinityBehavior and MountableBehavior are PartialFunctions that get processed in series. VehicleControl: Distinguished behavior allowed between an operational vehicle and a deactivated one. WSA: Tightened up DismountVehicleMsg handling code, since MountableBehavior has been enhanced. Minor: Shotgun shell stacking goes from 32 to 16. Various PSSO classes now have reliable Definition objects. Tests: We now have 1012 tests, some of them useful.
This commit is contained in:
parent
8c02f8d519
commit
eefe4d2e20
|
|
@ -9,6 +9,8 @@ import net.psforever.objects.equipment._
|
|||
import net.psforever.objects.inventory.InventoryTile
|
||||
import net.psforever.objects.serverobject.implantmech.ImplantTerminalMechDefinition
|
||||
import net.psforever.objects.serverobject.locks.IFFLockDefinition
|
||||
import net.psforever.objects.serverobject.mblocker.LockerDefinition
|
||||
import net.psforever.objects.serverobject.pad.VehicleSpawnPadDefinition
|
||||
import net.psforever.objects.serverobject.terminals._
|
||||
import net.psforever.objects.vehicles.SeatArmorRestriction
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
|
|
@ -498,9 +500,9 @@ object GlobalDefinitions {
|
|||
|
||||
val vehicle_terminal_combined = new VehicleTerminalCombinedDefinition
|
||||
|
||||
val spawn_pad = new ObjectDefinition(800) { Name = "spawn_pad" }
|
||||
val spawn_pad = new VehicleSpawnPadDefinition
|
||||
|
||||
val mb_locker = new ObjectDefinition(524) { Name = "mb_locker" }
|
||||
val mb_locker = new LockerDefinition
|
||||
|
||||
val lock_external = new IFFLockDefinition
|
||||
|
||||
|
|
@ -827,10 +829,10 @@ object GlobalDefinitions {
|
|||
bullet_9mm_AP.Capacity = 50
|
||||
bullet_9mm_AP.Tile = InventoryTile.Tile33
|
||||
|
||||
shotgun_shell.Capacity = 32
|
||||
shotgun_shell.Capacity = 16
|
||||
shotgun_shell.Tile = InventoryTile.Tile33
|
||||
|
||||
shotgun_shell_AP.Capacity = 32
|
||||
shotgun_shell_AP.Capacity = 16
|
||||
shotgun_shell_AP.Tile = InventoryTile.Tile33
|
||||
|
||||
energy_cell.Capacity = 50
|
||||
|
|
|
|||
|
|
@ -8,6 +8,12 @@ import net.psforever.packet.game.PlanetSideGUID
|
|||
|
||||
import scala.annotation.tailrec
|
||||
|
||||
/**
|
||||
* The companion of a `Locker` that is carried with a player
|
||||
* masquerading as their sixth `EquipmentSlot` object and a sub-inventory item.
|
||||
* The `Player` class refers to it as the "fifth slot" as its permanent slot number is encoded as `0x85`.
|
||||
* The inventory of this object is accessed using a game world `Locker` object (`mb_locker`).
|
||||
*/
|
||||
class LockerContainer extends Equipment with Container {
|
||||
private val inventory = GridInventory(30, 20)
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ package net.psforever.objects
|
|||
import net.psforever.objects.definition.{AvatarDefinition, ImplantDefinition}
|
||||
import net.psforever.objects.equipment.{Equipment, EquipmentSize}
|
||||
import net.psforever.objects.inventory.{Container, GridInventory, InventoryItem}
|
||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.types._
|
||||
|
||||
|
|
@ -16,7 +17,7 @@ class Player(private val name : String,
|
|||
private val sex : CharacterGender.Value,
|
||||
private val head : Int,
|
||||
private val voice : Int
|
||||
) extends PlanetSideGameObject with Container {
|
||||
) extends PlanetSideGameObject with FactionAffinity with Container {
|
||||
private var alive : Boolean = false
|
||||
private var backpack : Boolean = false
|
||||
private var health : Int = 0
|
||||
|
|
|
|||
|
|
@ -4,8 +4,9 @@ package net.psforever.objects
|
|||
import net.psforever.objects.definition.VehicleDefinition
|
||||
import net.psforever.objects.equipment.{Equipment, EquipmentSize}
|
||||
import net.psforever.objects.inventory.{Container, GridInventory, InventoryItem, InventoryTile}
|
||||
import net.psforever.objects.mount.Mountable
|
||||
import net.psforever.objects.serverobject.mount.Mountable
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||
import net.psforever.objects.vehicles.{AccessPermissionGroup, Seat, Utility, VehicleLockState}
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.packet.game.objectcreate.DriveState
|
||||
|
|
@ -27,7 +28,10 @@ import scala.collection.mutable
|
|||
* stores and unloads pertinent information about the `Vehicle`'s configuration;
|
||||
* used in the initialization process (`loadVehicleDefinition`)
|
||||
*/
|
||||
class Vehicle(private val vehicleDef : VehicleDefinition) extends PlanetSideServerObject with Mountable with Container {
|
||||
class Vehicle(private val vehicleDef : VehicleDefinition) extends PlanetSideServerObject
|
||||
with FactionAffinity
|
||||
with Mountable
|
||||
with Container {
|
||||
private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.TR
|
||||
private var owner : Option[PlanetSideGUID] = None
|
||||
private var health : Int = 1
|
||||
|
|
@ -63,7 +67,7 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends PlanetSideServ
|
|||
this.faction
|
||||
}
|
||||
|
||||
def Faction_=(faction : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = {
|
||||
override def Faction_=(faction : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = {
|
||||
this.faction = faction
|
||||
faction
|
||||
}
|
||||
|
|
@ -465,11 +469,17 @@ object Vehicle {
|
|||
|
||||
/**
|
||||
* The `Vehicle` will become unresponsive to player activity.
|
||||
* Usually, it does this to await deconstruction and clean-up
|
||||
* Usually, it does this to await deconstruction and clean-up.
|
||||
* @see `VehicleControl`
|
||||
*/
|
||||
final case class PrepareForDeletion()
|
||||
|
||||
/**
|
||||
* The `Vehicle` will resume previous unresponsiveness to player activity.
|
||||
* @see `VehicleControl`
|
||||
*/
|
||||
final case class Reactivate()
|
||||
|
||||
/**
|
||||
* Overloaded constructor.
|
||||
* @param vehicleDef the vehicle's definition entry
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.mount
|
||||
|
||||
import akka.actor.Actor
|
||||
|
||||
/**
|
||||
* The logic governing `Mountable` objects that use the `TryMount` message.
|
||||
* This is a mix-in trait for combining the `Receive` logic.
|
||||
* @see `Seat`
|
||||
* @see `Mountable`
|
||||
*/
|
||||
trait MountableBehavior {
|
||||
this : Actor =>
|
||||
|
||||
def MountableObject : Mountable
|
||||
|
||||
val mountableBehavior : Receive = {
|
||||
case Mountable.TryMount(user, seat_num) =>
|
||||
MountableObject.Seat(seat_num) match {
|
||||
case Some(seat) =>
|
||||
if((seat.Occupant = user).contains(user)) {
|
||||
sender ! Mountable.MountMessages(user, Mountable.CanMount(MountableObject, seat_num))
|
||||
}
|
||||
else {
|
||||
sender ! Mountable.MountMessages(user, Mountable.CanNotMount(MountableObject, seat_num))
|
||||
}
|
||||
case None =>
|
||||
sender ! Mountable.MountMessages(user, Mountable.CanNotMount(MountableObject, seat_num))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,12 +3,13 @@ package net.psforever.objects.serverobject
|
|||
|
||||
import akka.actor.ActorRef
|
||||
import net.psforever.objects.PlanetSideGameObject
|
||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||
|
||||
/**
|
||||
* An object layered on top of the standard game object class that maintains an internal `ActorRef`.
|
||||
* A measure of synchronization can be managed using this `Actor`.
|
||||
*/
|
||||
abstract class PlanetSideServerObject extends PlanetSideGameObject {
|
||||
abstract class PlanetSideServerObject extends PlanetSideGameObject with FactionAffinity {
|
||||
private var actor = ActorRef.noSender
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.serverobject.affinity
|
||||
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
|
||||
/**
|
||||
* Keep track of the allegiance of the object in terms of its association to a `PlanetSideEmpire` value.
|
||||
*/
|
||||
trait FactionAffinity {
|
||||
def Faction : PlanetSideEmpire.Value
|
||||
|
||||
def Faction_=(fac : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = Faction
|
||||
}
|
||||
|
||||
object FactionAffinity {
|
||||
/**
|
||||
* Message that makes the server object transmit IFF feedback.
|
||||
* @see AssertFactionAffinity
|
||||
*/
|
||||
final case class ConfirmFactionAffinity()
|
||||
/**
|
||||
* Message that makes the server object change allegiance to the specified faction value.
|
||||
* Transmit IFF feedback when done.
|
||||
* @param faction the allegiance to which to change
|
||||
*/
|
||||
final case class ConvertFactionAffinity(faction : PlanetSideEmpire.Value)
|
||||
/**
|
||||
* Message that responds to an IFF feedback request.
|
||||
* Transmit IFF feedback when done.
|
||||
* @see ConfirmFactionAffinity
|
||||
* @param obj the governed object
|
||||
* @param faction the allegiance to which the object belongs
|
||||
*/
|
||||
final case class AssertFactionAffinity(obj : FactionAffinity, faction : PlanetSideEmpire.Value)
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.serverobject.affinity
|
||||
|
||||
import akka.actor.Actor
|
||||
|
||||
object FactionAffinityBehavior {
|
||||
|
||||
/**
|
||||
* A `trait` for inheritance of common implementable methods.
|
||||
*/
|
||||
sealed trait BasicAffinity {
|
||||
def FactionObject : FactionAffinity
|
||||
}
|
||||
|
||||
/**
|
||||
* The logic governing `FactionAffinity` objects that use the `ConvertFactionAffinity` message.
|
||||
* This is a mix-in trait for combining with existing `Receive` logic.
|
||||
*/
|
||||
trait Convert extends BasicAffinity {
|
||||
this : Actor =>
|
||||
|
||||
val convertBehavior : Receive = {
|
||||
case FactionAffinity.ConvertFactionAffinity(faction) =>
|
||||
FactionObject.Faction = faction
|
||||
sender ! FactionAffinity.AssertFactionAffinity(FactionObject, faction)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The logic governing `FactionAffinity` objects that use the `ConfirmFactionAffinity` message.
|
||||
* A case exists to catch `AssertFactionAffinity` messages for the same ends though they should not be used this way.
|
||||
* This is a mix-in trait for combining with existing `Receive` logic.
|
||||
*/
|
||||
trait Check extends BasicAffinity {
|
||||
this : Actor =>
|
||||
|
||||
val checkBehavior : Receive = {
|
||||
case FactionAffinity.ConfirmFactionAffinity() | FactionAffinity.AssertFactionAffinity(_, _) =>
|
||||
sender ! FactionAffinity.AssertFactionAffinity(FactionObject, FactionObject.Faction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.serverobject.doors
|
||||
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
|
||||
/**
|
||||
* A temporary class to represent "facilities" and "structures."
|
||||
* @param id the map id of the base
|
||||
*/
|
||||
class Base(private val id : Int) {
|
||||
private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||
|
||||
def Id : Int = id
|
||||
|
||||
def Faction : PlanetSideEmpire.Value = faction
|
||||
|
||||
def Faction_=(emp : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = {
|
||||
faction = emp
|
||||
Faction
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.serverobject.doors
|
||||
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
import net.psforever.objects.Player
|
||||
import net.psforever.objects.serverobject.structures.Amenity
|
||||
import net.psforever.packet.game.UseItemMessage
|
||||
import net.psforever.types.Vector3
|
||||
|
||||
|
|
@ -10,7 +10,7 @@ import net.psforever.types.Vector3
|
|||
* A structure-owned server object that is a "door" that can open and can close.
|
||||
* @param ddef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
|
||||
*/
|
||||
class Door(private val ddef : DoorDefinition) extends PlanetSideServerObject {
|
||||
class Door(private val ddef : DoorDefinition) extends Amenity {
|
||||
private var openState : Option[Player] = None
|
||||
/** a vector in the direction of the "outside" of a room;
|
||||
* typically, any locking utility is on that same "outside" */
|
||||
|
|
|
|||
|
|
@ -2,13 +2,16 @@
|
|||
package net.psforever.objects.serverobject.doors
|
||||
|
||||
import akka.actor.Actor
|
||||
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
|
||||
|
||||
/**
|
||||
* An `Actor` that handles messages being dispatched to a specific `Door`.
|
||||
* @param door the `Door` object being governed
|
||||
*/
|
||||
class DoorControl(door : Door) extends Actor {
|
||||
def receive : Receive = {
|
||||
class DoorControl(door : Door) extends Actor with FactionAffinityBehavior.Check {
|
||||
def FactionObject : FactionAffinity = door
|
||||
|
||||
def receive : Receive = checkBehavior.orElse {
|
||||
case Door.Use(player, msg) =>
|
||||
sender ! Door.DoorMessage(player, msg, door.Use(player, msg))
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ package net.psforever.objects.serverobject.implantmech
|
|||
|
||||
import net.psforever.objects.Player
|
||||
import net.psforever.objects.definition.ObjectDefinition
|
||||
import net.psforever.objects.mount.Mountable
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
import net.psforever.objects.serverobject.mount.Mountable
|
||||
import net.psforever.objects.serverobject.structures.Amenity
|
||||
import net.psforever.objects.vehicles.Seat
|
||||
|
||||
/**
|
||||
|
|
@ -12,7 +12,7 @@ import net.psforever.objects.vehicles.Seat
|
|||
* For the most part, it merely implements the support data structures indicated by `Mountable`.
|
||||
* @param idef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
|
||||
*/
|
||||
class ImplantTerminalMech(private val idef : ImplantTerminalMechDefinition) extends PlanetSideServerObject with Mountable {
|
||||
class ImplantTerminalMech(private val idef : ImplantTerminalMechDefinition) extends Amenity with Mountable {
|
||||
private val seats : Map[Int, Seat] = Map( 0 -> new Seat(idef.Seats(0)) )
|
||||
|
||||
def Seats : Map[Int, Seat] = seats
|
||||
|
|
|
|||
|
|
@ -2,16 +2,23 @@
|
|||
package net.psforever.objects.serverobject.implantmech
|
||||
|
||||
import akka.actor.Actor
|
||||
import net.psforever.objects.mount.MountableBehavior
|
||||
import net.psforever.objects.serverobject.mount.MountableBehavior
|
||||
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
|
||||
|
||||
/**
|
||||
* An `Actor` that handles messages being dispatched to a specific `ImplantTerminalMech`.
|
||||
* @param mech the "mech" object being governed
|
||||
*/
|
||||
class ImplantTerminalMechControl(mech : ImplantTerminalMech) extends Actor with MountableBehavior {
|
||||
override def MountableObject = mech
|
||||
class ImplantTerminalMechControl(mech : ImplantTerminalMech) extends Actor with FactionAffinityBehavior.Check
|
||||
with MountableBehavior.Mount with MountableBehavior.Dismount {
|
||||
def MountableObject = mech //do not add type!
|
||||
|
||||
def receive : Receive = mountableBehavior.orElse {
|
||||
case _ => ;
|
||||
}
|
||||
def FactionObject : FactionAffinity = mech
|
||||
|
||||
def receive : Receive = checkBehavior
|
||||
.orElse(mountBehavior)
|
||||
.orElse(dismountBehavior)
|
||||
.orElse {
|
||||
case _ => ;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
package net.psforever.objects.serverobject.locks
|
||||
|
||||
import net.psforever.objects.Player
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
import net.psforever.objects.serverobject.structures.Amenity
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.types.Vector3
|
||||
|
||||
|
|
@ -15,7 +15,7 @@ import net.psforever.types.Vector3
|
|||
* The `IFFLock` is ideally associated with a server map object - a `Door` - to which it acts as a gatekeeper.
|
||||
* @param idef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
|
||||
*/
|
||||
class IFFLock(private val idef : IFFLockDefinition) extends PlanetSideServerObject {
|
||||
class IFFLock(private val idef : IFFLockDefinition) extends Amenity {
|
||||
/**
|
||||
* An entry that maintains a reference to the `Player`, and the player's GUID and location when the message was received.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -3,14 +3,17 @@ package net.psforever.objects.serverobject.locks
|
|||
|
||||
import akka.actor.Actor
|
||||
import net.psforever.objects.serverobject.CommonMessages
|
||||
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
|
||||
|
||||
/**
|
||||
* An `Actor` that handles messages being dispatched to a specific `IFFLock`.
|
||||
* @param lock the `IFFLock` object being governed
|
||||
* @see `CommonMessages`
|
||||
*/
|
||||
class IFFLockControl(lock : IFFLock) extends Actor {
|
||||
def receive : Receive = {
|
||||
class IFFLockControl(lock : IFFLock) extends Actor with FactionAffinityBehavior.Check {
|
||||
def FactionObject : FactionAffinity = lock
|
||||
|
||||
def receive : Receive = checkBehavior.orElse {
|
||||
case CommonMessages.Hack(player) =>
|
||||
lock.HackedBy = player
|
||||
|
||||
|
|
|
|||
|
|
@ -1,19 +1,18 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.serverobject.mblocker
|
||||
|
||||
import akka.actor.ActorContext
|
||||
import akka.actor.{ActorContext, Props}
|
||||
import net.psforever.objects.GlobalDefinitions
|
||||
import net.psforever.objects.definition.ObjectDefinition
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
import net.psforever.objects.serverobject.structures.Amenity
|
||||
|
||||
class Locker extends PlanetSideServerObject {
|
||||
def Definition : ObjectDefinition = GlobalDefinitions.mb_locker
|
||||
class Locker extends Amenity {
|
||||
def Definition : LockerDefinition = GlobalDefinitions.mb_locker
|
||||
}
|
||||
|
||||
object Locker {
|
||||
/**
|
||||
* Overloaded constructor.
|
||||
* @return a `VehicleSpawnPad` object
|
||||
* @return the `Locker` object
|
||||
*/
|
||||
def apply() : Locker = {
|
||||
new Locker()
|
||||
|
|
@ -28,6 +27,7 @@ object Locker {
|
|||
*/
|
||||
def Constructor(id : Int, context : ActorContext) : Locker = {
|
||||
val obj = Locker()
|
||||
obj.Actor = context.actorOf(Props(classOf[LockerControl], obj), s"${obj.Definition.Name}_$id")
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.serverobject.mblocker
|
||||
|
||||
import akka.actor.Actor
|
||||
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
|
||||
|
||||
/**
|
||||
* An `Actor` that handles messages being dispatched to a specific `Locker`.
|
||||
* @param locker the `Locker` object being governed
|
||||
*/
|
||||
class LockerControl(locker : Locker) extends Actor with FactionAffinityBehavior.Check {
|
||||
def FactionObject : FactionAffinity = locker
|
||||
|
||||
def receive : Receive = checkBehavior.orElse {
|
||||
case _ => ;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.serverobject.mblocker
|
||||
|
||||
import net.psforever.objects.definition.ObjectDefinition
|
||||
|
||||
/**
|
||||
* The definition for any `Locker`.
|
||||
* Object Id 524.
|
||||
*/
|
||||
class LockerDefinition extends ObjectDefinition(524) {
|
||||
Name = "mb_locker"
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.mount
|
||||
package net.psforever.objects.serverobject.mount
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import net.psforever.objects.Player
|
||||
|
|
@ -62,6 +62,8 @@ object Mountable {
|
|||
*/
|
||||
final case class TryMount(player : Player, seat_num : Int)
|
||||
|
||||
final case class TryDismount(player : Player, seat_num : Int)
|
||||
|
||||
/**
|
||||
* A basic `Trait` connecting all of the actionable `Mountable` response messages.
|
||||
*/
|
||||
|
|
@ -89,4 +91,19 @@ object Mountable {
|
|||
* @param seat_num the seat index
|
||||
*/
|
||||
final case class CanNotMount(obj : Mountable, seat_num : Int) extends Exchange
|
||||
|
||||
/**
|
||||
* Message sent in response to the player succeeding to disembark a `Mountable` object.
|
||||
* The player was previously seated at the given index.
|
||||
* @param obj the `Mountable` object
|
||||
* @param seat_num the seat index
|
||||
*/
|
||||
final case class CanDismount(obj : Mountable, seat_num : Int) extends Exchange
|
||||
/**
|
||||
* Message sent in response to the player failing to disembark a `Mountable` object.
|
||||
* The player is still seated at the given index.
|
||||
* @param obj the `Mountable` object
|
||||
* @param seat_num the seat index
|
||||
*/
|
||||
final case class CanNotDismount(obj : Mountable, seat_num : Int) extends Exchange
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.serverobject.mount
|
||||
|
||||
import akka.actor.Actor
|
||||
import net.psforever.objects.entity.{Identifiable, WorldEntity}
|
||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||
import net.psforever.types.Vector3
|
||||
|
||||
object MountableBehavior {
|
||||
/**
|
||||
* The logic governing `Mountable` objects that use the `TryMount` message.
|
||||
* This is a mix-in trait for combining with existing `Receive` logic.
|
||||
* @see `Seat`
|
||||
* @see `Mountable`
|
||||
*/
|
||||
trait Mount {
|
||||
this : Actor =>
|
||||
|
||||
def MountableObject : Mountable with Identifiable with WorldEntity with FactionAffinity
|
||||
|
||||
val mountBehavior : Receive = {
|
||||
case Mountable.TryMount(user, seat_num) =>
|
||||
val obj = MountableObject
|
||||
obj.Seat(seat_num) match {
|
||||
case Some(seat) =>
|
||||
if(user.Faction == obj.Faction && (seat.Occupant = user).contains(user)) {
|
||||
user.VehicleSeated = obj.GUID
|
||||
sender ! Mountable.MountMessages(user, Mountable.CanMount(obj, seat_num))
|
||||
}
|
||||
else {
|
||||
sender ! Mountable.MountMessages(user, Mountable.CanNotMount(obj, seat_num))
|
||||
}
|
||||
case None =>
|
||||
sender ! Mountable.MountMessages(user, Mountable.CanNotMount(obj, seat_num))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The logic governing `Mountable` objects that use the `TryDismount` message.
|
||||
* This is a mix-in trait for combining with existing `Receive` logic.
|
||||
* @see `Seat`
|
||||
* @see `Mountable`
|
||||
*/
|
||||
trait Dismount {
|
||||
this : Actor =>
|
||||
|
||||
def MountableObject : Mountable with Identifiable with WorldEntity with FactionAffinity
|
||||
|
||||
val dismountBehavior : Receive = {
|
||||
case Mountable.TryDismount(user, seat_num) =>
|
||||
val obj = MountableObject
|
||||
obj.Seat(seat_num) match {
|
||||
case Some(seat) =>
|
||||
if(seat.Bailable || obj.Velocity.isEmpty || Vector3.MagnitudeSquared(obj.Velocity.get).toInt == 0) {
|
||||
seat.Occupant = None
|
||||
user.VehicleSeated = None
|
||||
sender ! Mountable.MountMessages(user, Mountable.CanDismount(obj, seat_num))
|
||||
}
|
||||
else {
|
||||
sender ! Mountable.MountMessages(user, Mountable.CanNotDismount(obj, seat_num))
|
||||
}
|
||||
case None =>
|
||||
sender ! Mountable.MountMessages(user, Mountable.CanNotDismount(obj, seat_num))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
package net.psforever.objects.serverobject.pad
|
||||
|
||||
import akka.actor.{Actor, ActorRef, Cancellable}
|
||||
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
|
||||
import net.psforever.objects.{DefaultCancellable, Player, Vehicle}
|
||||
import net.psforever.types.Vector3
|
||||
|
||||
|
|
@ -29,7 +30,7 @@ import scala.concurrent.duration._
|
|||
* 3. a callback location for sending messages.
|
||||
* @param pad the `VehicleSpawnPad` object being governed
|
||||
*/
|
||||
class VehicleSpawnControl(pad : VehicleSpawnPad) extends Actor {
|
||||
class VehicleSpawnControl(pad : VehicleSpawnPad) extends Actor with FactionAffinityBehavior.Check {
|
||||
/** an executor for progressing a vehicle order through the normal spawning logic */
|
||||
private var process : Cancellable = DefaultCancellable.obj
|
||||
/** a list of vehicle orders that have been submitted for this spawn pad */
|
||||
|
|
@ -41,8 +42,9 @@ class VehicleSpawnControl(pad : VehicleSpawnPad) extends Actor {
|
|||
private[this] val log = org.log4s.getLogger
|
||||
private[this] def trace(msg : String) : Unit = log.trace(msg)
|
||||
|
||||
def FactionObject : FactionAffinity = pad
|
||||
|
||||
def receive : Receive = {
|
||||
def receive : Receive = checkBehavior.orElse {
|
||||
case VehicleSpawnPad.VehicleOrder(player, vehicle) =>
|
||||
trace(s"order from $player for $vehicle received")
|
||||
orders = orders :+ VehicleSpawnControl.OrderEntry(player, vehicle, sender)
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@
|
|||
package net.psforever.objects.serverobject.pad
|
||||
|
||||
import net.psforever.objects.{Player, Vehicle}
|
||||
import net.psforever.objects.definition.ObjectDefinition
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
import net.psforever.objects.serverobject.structures.Amenity
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
|
||||
/**
|
||||
|
|
@ -16,8 +15,8 @@ import net.psforever.packet.game.PlanetSideGUID
|
|||
* @param spDef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
|
||||
* @see `VehicleSpawnControl`
|
||||
*/
|
||||
class VehicleSpawnPad(spDef : ObjectDefinition) extends PlanetSideServerObject {
|
||||
def Definition : ObjectDefinition = spDef
|
||||
class VehicleSpawnPad(spDef : VehicleSpawnPadDefinition) extends Amenity {
|
||||
def Definition : VehicleSpawnPadDefinition = spDef
|
||||
}
|
||||
|
||||
object VehicleSpawnPad {
|
||||
|
|
@ -83,7 +82,7 @@ object VehicleSpawnPad {
|
|||
* @param spDef the spawn pad's definition entry
|
||||
* @return a `VehicleSpawnPad` object
|
||||
*/
|
||||
def apply(spDef : ObjectDefinition) : VehicleSpawnPad = {
|
||||
def apply(spDef : VehicleSpawnPadDefinition) : VehicleSpawnPad = {
|
||||
new VehicleSpawnPad(spDef)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.serverobject.pad
|
||||
|
||||
import net.psforever.objects.definition.ObjectDefinition
|
||||
|
||||
/**
|
||||
* The definition for any `VehicleSpawnPad`.
|
||||
* Object Id 800.
|
||||
*/
|
||||
class VehicleSpawnPadDefinition extends ObjectDefinition(800) {
|
||||
Name = "spawn_pad"
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.serverobject.structures
|
||||
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
|
||||
/**
|
||||
* Amenities are elements of the game that belong to other elements of the game.<br>
|
||||
* <br>
|
||||
* Normal `PlanetSideServerObject` entities (server objects) tend to have properties that are completely internalized.
|
||||
* An `Amenity` is a server object that maintains a fixed association with another server object.
|
||||
* This association strips away at the internalization and redirects a reference to some properties somewhere else.
|
||||
* An `Amenity` object belongs to its `Owner` object;
|
||||
* the `Amenity` objects looks to its `Owner` object for some of its properties.
|
||||
* @see `FactionAffinity`
|
||||
*/
|
||||
abstract class Amenity extends PlanetSideServerObject {
|
||||
private var owner : PlanetSideServerObject = Building.NoBuilding
|
||||
|
||||
def Faction : PlanetSideEmpire.Value = Owner.Faction
|
||||
|
||||
/**
|
||||
* Reference the object that is in direct association with (is superior to) this one.
|
||||
* @return the object associated as this object's "owner"
|
||||
*/
|
||||
def Owner : PlanetSideServerObject = owner
|
||||
|
||||
/**
|
||||
* Set an object to have a direct association with (be superior to) this one.
|
||||
* @see `Amenity.AmenityTarget`
|
||||
* @param obj the object trying to become associated as this object's "owner"
|
||||
* @tparam T a validation of the type of object that can be an owner
|
||||
* @return the object associated as this object's "owner"
|
||||
*/
|
||||
def Owner_=[T : Amenity.AmenityTarget](obj : T) : PlanetSideServerObject = {
|
||||
owner = obj.asInstanceOf[PlanetSideServerObject]
|
||||
Owner
|
||||
}
|
||||
}
|
||||
|
||||
object Amenity {
|
||||
/**
|
||||
* A `trait` for validating the type of object that can be allowed to become an `Amenity` object's `Owner`.<br>
|
||||
* <br>
|
||||
* The `Owner` defaults to a type of `PlanetSideServerObject` in reference type;
|
||||
* but, that distinction is mainly to allow for a common ancestor with appropriate methods.
|
||||
* Only certain types of `PlanetSideServerObject` are formally allowed to be owners.
|
||||
* In execution, the `T` is the type of object that implicitly converts into an acceptable type of sub-object.
|
||||
* The companion object maintains the hardcoded conversions.
|
||||
* If such an implicit conversion does not exist, the assignment is unacceptable at compile time.
|
||||
* @tparam T the permitted type of object
|
||||
*/
|
||||
sealed trait AmenityTarget[T]
|
||||
|
||||
object AmenityTarget {
|
||||
import net.psforever.objects.Vehicle
|
||||
implicit object BuildingTarget extends AmenityTarget[Building] { }
|
||||
implicit object VehicleTarget extends AmenityTarget[Vehicle] { }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.serverobject.structures
|
||||
|
||||
import akka.actor.ActorContext
|
||||
import net.psforever.objects.definition.ObjectDefinition
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
|
||||
class Building(private val id : Int, private val zone : Zone) extends PlanetSideServerObject {
|
||||
private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||
private var amenities : List[Amenity] = List.empty
|
||||
GUID = PlanetSideGUID(0)
|
||||
|
||||
def Id : Int = id
|
||||
|
||||
def Faction : PlanetSideEmpire.Value = faction
|
||||
|
||||
override def Faction_=(fac : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = {
|
||||
faction = fac
|
||||
Faction
|
||||
}
|
||||
|
||||
def Amenities : List[Amenity] = amenities
|
||||
|
||||
def Amenities_=(obj : Amenity) : List[Amenity] = {
|
||||
amenities = amenities :+ obj
|
||||
obj.Owner = this
|
||||
amenities
|
||||
}
|
||||
|
||||
def Zone : Zone = zone
|
||||
|
||||
def Definition: ObjectDefinition = Building.BuildingDefinition
|
||||
}
|
||||
|
||||
object Building {
|
||||
final val NoBuilding : Building = new Building(0, Zone.Nowhere) {
|
||||
override def Faction_=(faction : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||
override def Amenities_=(obj : Amenity) : List[Amenity] = Nil
|
||||
}
|
||||
|
||||
final val BuildingDefinition : ObjectDefinition = new ObjectDefinition(0) { Name = "building" }
|
||||
|
||||
def apply(id : Int, zone : Zone) : Building = {
|
||||
new Building(id, zone)
|
||||
}
|
||||
|
||||
def Structure(id : Int, zone : Zone, context : ActorContext) : Building = {
|
||||
import akka.actor.Props
|
||||
val obj = new Building(id, zone)
|
||||
obj.Actor = context.actorOf(Props(classOf[BuildingControl], obj), s"$id-building")
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.serverobject.structures
|
||||
|
||||
import akka.actor.Actor
|
||||
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
|
||||
|
||||
class BuildingControl(building : Building) extends Actor with FactionAffinityBehavior.Check {
|
||||
def FactionObject : FactionAffinity = building
|
||||
|
||||
def receive : Receive = checkBehavior.orElse {
|
||||
case FactionAffinity.ConvertFactionAffinity(faction) =>
|
||||
val originalAffinity = building.Faction
|
||||
if(originalAffinity != (building.Faction = faction)) {
|
||||
building.Amenities.foreach(_.Actor forward FactionAffinity.ConfirmFactionAffinity())
|
||||
}
|
||||
sender ! FactionAffinity.AssertFactionAffinity(building, faction)
|
||||
|
||||
case _ => ;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.serverobject.structures
|
||||
|
||||
import akka.actor.ActorContext
|
||||
import net.psforever.objects.zones.Zone
|
||||
|
||||
/**
|
||||
* Defer establishment of a `Building` object until the location for the object is correct (in the correct zone)
|
||||
* and a `context` in the proper `Actor` hierarchy of that zone exists in scope.
|
||||
* @see `ServerObjectBuilder`
|
||||
* @see `Building`
|
||||
* @param constructor a curried function that eventually constructs a `Building` object
|
||||
*/
|
||||
class FoundationBuilder(private val constructor : (Int, Zone, ActorContext)=>Building) {
|
||||
def Build(id : Int, zone : Zone)(implicit context : ActorContext = null) : Building = {
|
||||
val obj : Building = constructor(id, zone, context)
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
||||
object FoundationBuilder {
|
||||
/**
|
||||
* Overloaded constructor.
|
||||
* @param constructor a curried function that eventually constructs a `Building` object
|
||||
* @return a `FoundationBuilder` object
|
||||
*/
|
||||
def apply(constructor : (Int, Zone, ActorContext)=>Building) : FoundationBuilder = {
|
||||
new FoundationBuilder(constructor)
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
package net.psforever.objects.serverobject.terminals
|
||||
|
||||
import net.psforever.objects.Player
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
import net.psforever.objects.serverobject.structures.Amenity
|
||||
import net.psforever.packet.game.{ItemTransactionMessage, PlanetSideGUID}
|
||||
import net.psforever.types.{TransactionType, Vector3}
|
||||
|
||||
|
|
@ -10,7 +10,7 @@ import net.psforever.types.{TransactionType, Vector3}
|
|||
* A structure-owned server object that is a "terminal" that can be accessed for amenities and services.
|
||||
* @param tdef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
|
||||
*/
|
||||
class Terminal(tdef : TerminalDefinition) extends PlanetSideServerObject {
|
||||
class Terminal(tdef : TerminalDefinition) extends Amenity {
|
||||
/** An entry that maintains a reference to the `Player`, and the player's GUID and location when the message was received. */
|
||||
private var hackedBy : Option[(Player, PlanetSideGUID, Vector3)] = None
|
||||
|
||||
|
|
@ -65,18 +65,23 @@ class Terminal(tdef : TerminalDefinition) extends PlanetSideServerObject {
|
|||
* @return an actionable message that explains what resulted from interacting with this `Terminal`
|
||||
*/
|
||||
def Request(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = {
|
||||
msg.transaction_type match {
|
||||
case TransactionType.Buy | TransactionType.Learn =>
|
||||
tdef.Buy(player, msg)
|
||||
if(Faction == player.Faction || HackedBy.isDefined) {
|
||||
msg.transaction_type match {
|
||||
case TransactionType.Buy | TransactionType.Learn =>
|
||||
tdef.Buy(player, msg)
|
||||
|
||||
case TransactionType.Sell =>
|
||||
tdef.Sell(player, msg)
|
||||
case TransactionType.Sell =>
|
||||
tdef.Sell(player, msg)
|
||||
|
||||
case TransactionType.InfantryLoadout =>
|
||||
tdef.Loadout(player, msg)
|
||||
case TransactionType.InfantryLoadout =>
|
||||
tdef.Loadout(player, msg)
|
||||
|
||||
case _ =>
|
||||
Terminal.NoDeal()
|
||||
case _ =>
|
||||
Terminal.NoDeal()
|
||||
}
|
||||
}
|
||||
else {
|
||||
Terminal.NoDeal()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,13 +2,16 @@
|
|||
package net.psforever.objects.serverobject.terminals
|
||||
|
||||
import akka.actor.Actor
|
||||
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
|
||||
|
||||
/**
|
||||
* An `Actor` that handles messages being dispatched to a specific `Terminal`.
|
||||
* @param term the `Terminal` object being governed
|
||||
*/
|
||||
class TerminalControl(term : Terminal) extends Actor {
|
||||
def receive : Receive = {
|
||||
class TerminalControl(term : Terminal) extends Actor with FactionAffinityBehavior.Check {
|
||||
def FactionObject : FactionAffinity = term
|
||||
|
||||
def receive : Receive = checkBehavior.orElse {
|
||||
case Terminal.Request(player, msg) =>
|
||||
sender ! Terminal.TerminalMessage(player, msg, term.Request(player, msg))
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ package net.psforever.objects.vehicles
|
|||
|
||||
import akka.actor.Actor
|
||||
import net.psforever.objects.Vehicle
|
||||
import net.psforever.objects.mount.MountableBehavior
|
||||
import net.psforever.objects.serverobject.mount.{Mountable, MountableBehavior}
|
||||
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
|
||||
|
||||
/**
|
||||
* An `Actor` that handles messages being dispatched to a specific `Vehicle`.<br>
|
||||
|
|
@ -12,17 +13,32 @@ import net.psforever.objects.mount.MountableBehavior
|
|||
* The latter is applicable only when the specific vehicle is being deconstructed.
|
||||
* @param vehicle the `Vehicle` object being governed
|
||||
*/
|
||||
class VehicleControl(private val vehicle : Vehicle) extends Actor with MountableBehavior {
|
||||
override def MountableObject = vehicle
|
||||
class VehicleControl(private val vehicle : Vehicle) extends Actor
|
||||
with FactionAffinityBehavior.Check
|
||||
with MountableBehavior.Mount
|
||||
with MountableBehavior.Dismount {
|
||||
def MountableObject = vehicle //do not add type!
|
||||
|
||||
def receive : Receive = mountableBehavior.orElse {
|
||||
case Vehicle.PrepareForDeletion =>
|
||||
context.become(Disabled)
|
||||
def FactionObject : FactionAffinity = vehicle
|
||||
|
||||
case _ => ;
|
||||
}
|
||||
def receive : Receive = Enabled
|
||||
|
||||
def Disabled : Receive = {
|
||||
case _ => ;
|
||||
}
|
||||
def Enabled : Receive = checkBehavior
|
||||
.orElse(mountBehavior)
|
||||
.orElse(dismountBehavior)
|
||||
.orElse {
|
||||
case Vehicle.PrepareForDeletion =>
|
||||
context.become(Disabled)
|
||||
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
def Disabled : Receive = checkBehavior
|
||||
.orElse(dismountBehavior)
|
||||
.orElse {
|
||||
case Vehicle.Reactivate =>
|
||||
context.become(Enabled)
|
||||
|
||||
case _ => ;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,19 +3,20 @@ package net.psforever.objects.zones
|
|||
|
||||
import akka.actor.{ActorContext, ActorRef, Props}
|
||||
import akka.routing.RandomPool
|
||||
import net.psforever.objects.serverobject.doors.Base
|
||||
import net.psforever.objects.{PlanetSideGameObject, Player, Vehicle}
|
||||
import net.psforever.objects.equipment.Equipment
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
import net.psforever.objects.guid.actor.UniqueNumberSystem
|
||||
import net.psforever.objects.guid.selector.RandomSelector
|
||||
import net.psforever.objects.guid.source.LimitedNumberSource
|
||||
import net.psforever.objects.serverobject.structures.{Amenity, Building}
|
||||
import net.psforever.packet.GamePacket
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.types.Vector3
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import scala.collection.mutable.ListBuffer
|
||||
import scala.collection.immutable.{Map => PairMap}
|
||||
|
||||
/**
|
||||
* A server object representing the one-landmass planets as well as the individual subterranean caverns.<br>
|
||||
|
|
@ -55,7 +56,7 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
|
|||
/** */
|
||||
private var transport : ActorRef = ActorRef.noSender
|
||||
|
||||
private var bases : List[Base] = List()
|
||||
private var buildings : PairMap[Int, Building] = PairMap.empty[Int, Building]
|
||||
|
||||
/**
|
||||
* Establish the basic accessible conditions necessary for a functional `Zone`.<br>
|
||||
|
|
@ -79,8 +80,8 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
|
|||
Map.LocalObjects.foreach({ builderObject =>
|
||||
builderObject.Build
|
||||
})
|
||||
|
||||
MakeBases(Map.LocalBases)
|
||||
MakeBuildings(context)
|
||||
AssignAmenities()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -217,13 +218,20 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
|
|||
|
||||
def Transport : ActorRef = transport
|
||||
|
||||
def MakeBases(num : Int) : List[Base] = {
|
||||
bases = (1 to num).map(id => new Base(id)).toList
|
||||
bases
|
||||
def Building(id : Int) : Option[Building] = {
|
||||
buildings.get(id)
|
||||
}
|
||||
|
||||
def Base(id : Int) : Option[Base] = {
|
||||
bases.lift(id)
|
||||
private def MakeBuildings(implicit context : ActorContext) : PairMap[Int, Building] = {
|
||||
val buildingList = Map.LocalBuildings
|
||||
buildings = buildingList.map({case(building_id, constructor) => building_id -> constructor.Build(building_id, this) })
|
||||
buildings
|
||||
}
|
||||
|
||||
private def AssignAmenities() : Unit = {
|
||||
Map.ObjectToBuilding.foreach({ case(object_guid, building_id) =>
|
||||
buildings(building_id).Amenities = guid(object_guid).get.asInstanceOf[Amenity]
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -264,6 +272,8 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
|
|||
}
|
||||
|
||||
object Zone {
|
||||
final val Nowhere : Zone = new Zone("nowhere", new ZoneMap("nowhere"), 99)
|
||||
|
||||
/**
|
||||
* Message to initialize the `Zone`.
|
||||
* @see `Zone.Init(implicit ActorContext)`
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
package net.psforever.objects.zones
|
||||
|
||||
import akka.actor.Actor
|
||||
import net.psforever.objects.PlanetSideGameObject
|
||||
import org.log4s.Logger
|
||||
|
||||
/**
|
||||
* na
|
||||
|
|
@ -20,14 +22,16 @@ class ZoneActor(zone : Zone) extends Actor {
|
|||
}
|
||||
|
||||
def ZoneSetupCheck(): Unit = {
|
||||
import ZoneActor._
|
||||
def guid(id : Int) = zone.GUID(id)
|
||||
val map = zone.Map
|
||||
val slog = org.log4s.getLogger(s"zone/${zone.Id}/sanity")
|
||||
val validateObject : (Int, (PlanetSideGameObject)=>Boolean, String) => Boolean = ValidateObject(guid, slog)
|
||||
|
||||
//check base to object associations
|
||||
map.ObjectToBase.foreach({ case((object_guid, base_id)) =>
|
||||
if(zone.Base(base_id).isEmpty) {
|
||||
slog.error(s"expected a base #$base_id")
|
||||
map.ObjectToBuilding.foreach({ case((object_guid, base_id)) =>
|
||||
if(zone.Building(base_id).isEmpty) {
|
||||
slog.error(s"expected a building at id #$base_id")
|
||||
}
|
||||
if(guid(object_guid).isEmpty) {
|
||||
slog.error(s"expected object id $object_guid to exist, but it did not")
|
||||
|
|
@ -35,74 +39,80 @@ class ZoneActor(zone : Zone) extends Actor {
|
|||
})
|
||||
|
||||
//check door to lock association
|
||||
import net.psforever.objects.serverobject.doors.Door
|
||||
import net.psforever.objects.serverobject.locks.IFFLock
|
||||
map.DoorToLock.foreach({ case((door_guid, lock_guid)) =>
|
||||
try {
|
||||
if(!guid(door_guid).get.isInstanceOf[Door]) {
|
||||
slog.error(s"expected id $door_guid to be a door, but it was not")
|
||||
}
|
||||
}
|
||||
catch {
|
||||
case _ : Exception =>
|
||||
slog.error(s"expected a door at id $door_guid but no object is initialized")
|
||||
}
|
||||
try {
|
||||
if(!guid(lock_guid).get.isInstanceOf[IFFLock]) {
|
||||
slog.error(s"expected id $lock_guid to be an IFF locks but it was not")
|
||||
}
|
||||
}
|
||||
catch {
|
||||
case _ : Exception =>
|
||||
slog.error(s"expected an IFF locks at id $lock_guid but no object is initialized")
|
||||
}
|
||||
validateObject(door_guid, DoorCheck, "door")
|
||||
validateObject(lock_guid, LockCheck, "IFF lock")
|
||||
})
|
||||
|
||||
//check vehicle terminal to spawn pad association
|
||||
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
map.TerminalToSpawnPad.foreach({ case ((term_guid, pad_guid)) =>
|
||||
try {
|
||||
if(!guid(term_guid).get.isInstanceOf[Terminal]) { //TODO check is vehicle terminal
|
||||
slog.error(s"expected id $term_guid to be a terminal, but it was not")
|
||||
}
|
||||
}
|
||||
catch {
|
||||
case _ : Exception =>
|
||||
slog.error(s"expected a terminal at id $term_guid but no object is initialized")
|
||||
}
|
||||
try {
|
||||
if(!guid(pad_guid).get.isInstanceOf[VehicleSpawnPad]) {
|
||||
slog.error(s"expected id $pad_guid to be a spawn pad, but it was not")
|
||||
}
|
||||
}
|
||||
catch {
|
||||
case _ : Exception =>
|
||||
slog.error(s"expected a spawn pad at id $pad_guid but no object is initialized")
|
||||
}
|
||||
validateObject(term_guid, TerminalCheck, "vehicle terminal")
|
||||
validateObject(pad_guid, VehicleSpawnPadCheck, "vehicle spawn pad")
|
||||
})
|
||||
|
||||
//check implant terminal mech to implant terminal interface association
|
||||
import net.psforever.objects.serverobject.implantmech.ImplantTerminalMech
|
||||
map.TerminalToInterface.foreach({case ((mech_guid, interface_guid)) =>
|
||||
try {
|
||||
if(!guid(mech_guid).get.isInstanceOf[ImplantTerminalMech]) {
|
||||
slog.error(s"expected id $mech_guid to be an implant terminal mech, but it was not")
|
||||
}
|
||||
}
|
||||
catch {
|
||||
case _ : Exception =>
|
||||
slog.error(s"expected a implant terminal mech at id $mech_guid but no object is initialized")
|
||||
}
|
||||
try {
|
||||
if(!guid(interface_guid).get.isInstanceOf[Terminal]) { //TODO check is implant terminal
|
||||
slog.error(s"expected id $interface_guid to be an implant terminal interface, but it was not")
|
||||
}
|
||||
}
|
||||
catch {
|
||||
case _ : Exception =>
|
||||
slog.error(s"expected a implant terminal interface at id $interface_guid but no object is initialized")
|
||||
}
|
||||
validateObject(mech_guid, ImplantMechCheck, "implant terminal mech")
|
||||
validateObject(interface_guid, TerminalCheck, "implant terminal interface")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
object ZoneActor {
|
||||
|
||||
/**
|
||||
* Recover an object from a collection and perform any number of validating tests upon it.
|
||||
* If the object fails any tests, log an error.
|
||||
* @param guid access to an association between unique numbers and objects using some of those unique numbers
|
||||
* @param elog a contraction of "error log;"
|
||||
* accepts `String` data
|
||||
* @param object_guid the unique indentifier being checked against the `guid` access point
|
||||
* @param test a test for the discovered object;
|
||||
* expects at least `Type` checking
|
||||
* @param description an explanation of how the object, if not discovered, should be identified
|
||||
* @return `true` if the object was discovered and validates correctly;
|
||||
* `false` if the object failed any tests
|
||||
*/
|
||||
def ValidateObject(guid : (Int)=>Option[PlanetSideGameObject], elog : Logger)
|
||||
(object_guid : Int, test : (PlanetSideGameObject)=>Boolean, description : String) : Boolean = {
|
||||
try {
|
||||
if(!test(guid(object_guid).get)) {
|
||||
elog.error(s"expected id $object_guid to be a $description, but it was not")
|
||||
false
|
||||
}
|
||||
else {
|
||||
true
|
||||
}
|
||||
}
|
||||
catch {
|
||||
case _ : Exception =>
|
||||
elog.error(s"expected a $description at id $object_guid but no object is initialized")
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
def LockCheck(obj : PlanetSideGameObject) : Boolean = {
|
||||
import net.psforever.objects.serverobject.locks.IFFLock
|
||||
obj.isInstanceOf[IFFLock]
|
||||
}
|
||||
|
||||
def DoorCheck(obj : PlanetSideGameObject) : Boolean = {
|
||||
import net.psforever.objects.serverobject.doors.Door
|
||||
obj.isInstanceOf[Door]
|
||||
}
|
||||
|
||||
def TerminalCheck(obj : PlanetSideGameObject) : Boolean = {
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
obj.isInstanceOf[Terminal]
|
||||
}
|
||||
|
||||
def ImplantMechCheck(obj : PlanetSideGameObject) : Boolean = {
|
||||
import net.psforever.objects.serverobject.implantmech.ImplantTerminalMech
|
||||
obj.isInstanceOf[ImplantTerminalMech]
|
||||
}
|
||||
|
||||
def VehicleSpawnPadCheck(obj : PlanetSideGameObject) : Boolean = {
|
||||
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
|
||||
obj.isInstanceOf[VehicleSpawnPad]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.zones
|
||||
|
||||
import net.psforever.objects.serverobject.structures.FoundationBuilder
|
||||
import net.psforever.objects.serverobject.ServerObjectBuilder
|
||||
|
||||
/**
|
||||
|
|
@ -29,7 +30,7 @@ class ZoneMap(private val name : String) {
|
|||
private var linkTerminalInterface : Map[Int, Int] = Map()
|
||||
private var linkDoorLock : Map[Int, Int] = Map()
|
||||
private var linkObjectBase : Map[Int, Int] = Map()
|
||||
private var numBases : Int = 0
|
||||
private var buildings : Map[Int, FoundationBuilder] = Map()
|
||||
|
||||
def Name : String = name
|
||||
|
||||
|
|
@ -49,19 +50,19 @@ class ZoneMap(private val name : String) {
|
|||
localObjects = localObjects :+ obj
|
||||
}
|
||||
|
||||
def LocalBases : Int = numBases
|
||||
def LocalBuildings : Map[Int, FoundationBuilder] = buildings
|
||||
|
||||
def LocalBases_=(num : Int) : Int = {
|
||||
if(num > 0) {
|
||||
numBases = num
|
||||
def LocalBuilding(building_id : Int, constructor : FoundationBuilder) : Int = {
|
||||
if(building_id > 0) {
|
||||
buildings = buildings ++ Map(building_id -> constructor)
|
||||
}
|
||||
LocalBases
|
||||
buildings.size
|
||||
}
|
||||
|
||||
def ObjectToBase : Map[Int, Int] = linkObjectBase
|
||||
def ObjectToBuilding : Map[Int, Int] = linkObjectBase
|
||||
|
||||
def ObjectToBase(object_guid : Int, base_id : Int) : Unit = {
|
||||
linkObjectBase = linkObjectBase ++ Map(object_guid -> base_id)
|
||||
def ObjectToBuilding(object_guid : Int, building_id : Int) : Unit = {
|
||||
linkObjectBase = linkObjectBase ++ Map(object_guid -> building_id)
|
||||
}
|
||||
|
||||
def DoorToLock : Map[Int, Int] = linkDoorLock
|
||||
|
|
|
|||
169
common/src/test/scala/objects/BuildingTest.scala
Normal file
169
common/src/test/scala/objects/BuildingTest.scala
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.{ActorRef, Props}
|
||||
import net.psforever.objects.GlobalDefinitions
|
||||
import net.psforever.objects.definition.ObjectDefinition
|
||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||
import net.psforever.objects.serverobject.doors.{Door, DoorControl}
|
||||
import net.psforever.objects.serverobject.structures.{Amenity, Building, BuildingControl}
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
import scala.concurrent.duration.Duration
|
||||
|
||||
class AmenityTest extends Specification {
|
||||
class AmenityObject extends Amenity {
|
||||
def Definition : ObjectDefinition = null
|
||||
}
|
||||
|
||||
"Amenity" should {
|
||||
"construct" in {
|
||||
val ao = new AmenityObject()
|
||||
ao.Owner mustEqual Building.NoBuilding
|
||||
}
|
||||
|
||||
"can be owned by a building" in {
|
||||
val ao = new AmenityObject()
|
||||
val bldg = Building(10, Zone.Nowhere)
|
||||
|
||||
ao.Owner = bldg
|
||||
ao.Owner mustEqual bldg
|
||||
}
|
||||
|
||||
"be owned by a vehicle" in {
|
||||
import net.psforever.objects.Vehicle
|
||||
val ao = new AmenityObject()
|
||||
val veh = Vehicle(GlobalDefinitions.quadstealth)
|
||||
|
||||
ao.Owner = veh
|
||||
ao.Owner mustEqual veh
|
||||
}
|
||||
|
||||
"not be owned by an unexpected object" in {
|
||||
val ao = new AmenityObject()
|
||||
//ao.Owner = net.psforever.objects.serverobject.mblocker.Locker() //will not compile
|
||||
ok
|
||||
}
|
||||
|
||||
"confer faction allegiance through ownership" in {
|
||||
//see FactionAffinityTest
|
||||
val ao = new AmenityObject()
|
||||
val bldg = Building(10, Zone.Nowhere)
|
||||
ao.Owner = bldg
|
||||
bldg.Faction mustEqual PlanetSideEmpire.NEUTRAL
|
||||
ao.Faction mustEqual PlanetSideEmpire.NEUTRAL
|
||||
|
||||
bldg.Faction = PlanetSideEmpire.TR
|
||||
bldg.Faction mustEqual PlanetSideEmpire.TR
|
||||
ao.Faction mustEqual PlanetSideEmpire.TR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BuildingTest extends Specification {
|
||||
"Building" should {
|
||||
"construct" in {
|
||||
val bldg = Building(10, Zone.Nowhere)
|
||||
bldg.Id mustEqual 10
|
||||
bldg.Actor mustEqual ActorRef.noSender
|
||||
bldg.Amenities mustEqual Nil
|
||||
bldg.Zone mustEqual Zone.Nowhere
|
||||
bldg.Faction mustEqual PlanetSideEmpire.NEUTRAL
|
||||
}
|
||||
|
||||
"change faction affinity" in {
|
||||
val bldg = Building(10, Zone.Nowhere)
|
||||
bldg.Faction mustEqual PlanetSideEmpire.NEUTRAL
|
||||
|
||||
bldg.Faction = PlanetSideEmpire.TR
|
||||
bldg.Faction mustEqual PlanetSideEmpire.TR
|
||||
}
|
||||
|
||||
"keep track of amenities" in {
|
||||
val bldg = Building(10, Zone.Nowhere)
|
||||
val door1 = Door(GlobalDefinitions.door)
|
||||
val door2 = Door(GlobalDefinitions.door)
|
||||
|
||||
bldg.Amenities mustEqual Nil
|
||||
bldg.Amenities = door2
|
||||
bldg.Amenities mustEqual List(door2)
|
||||
bldg.Amenities = door1
|
||||
bldg.Amenities mustEqual List(door2, door1)
|
||||
door1.Owner mustEqual bldg
|
||||
door2.Owner mustEqual bldg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BuildingControl1Test extends ActorTest {
|
||||
"Building Control" should {
|
||||
"construct" in {
|
||||
val bldg = Building(10, Zone.Nowhere)
|
||||
bldg.Actor = system.actorOf(Props(classOf[BuildingControl], bldg), "test")
|
||||
assert(bldg.Actor != ActorRef.noSender)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BuildingControl2Test extends ActorTest {
|
||||
"Building Control" should {
|
||||
"convert and assert faction affinity on convert request" in {
|
||||
val bldg = Building(10, Zone.Nowhere)
|
||||
bldg.Faction = PlanetSideEmpire.TR
|
||||
bldg.Actor = system.actorOf(Props(classOf[BuildingControl], bldg), "test")
|
||||
assert(bldg.Faction == PlanetSideEmpire.TR)
|
||||
|
||||
bldg.Actor ! FactionAffinity.ConvertFactionAffinity(PlanetSideEmpire.VS)
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
assert(reply.isInstanceOf[FactionAffinity.AssertFactionAffinity])
|
||||
assert(reply.asInstanceOf[FactionAffinity.AssertFactionAffinity].obj == bldg)
|
||||
assert(reply.asInstanceOf[FactionAffinity.AssertFactionAffinity].faction == PlanetSideEmpire.VS)
|
||||
assert(bldg.Faction == PlanetSideEmpire.VS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BuildingControl3Test extends ActorTest {
|
||||
"Building Control" should {
|
||||
"convert and assert faction affinity on convert request, and for each of its amenities" in {
|
||||
val bldg = Building(10, Zone.Nowhere)
|
||||
bldg.Faction = PlanetSideEmpire.TR
|
||||
bldg.Actor = system.actorOf(Props(classOf[BuildingControl], bldg), "building-test")
|
||||
val door1 = Door(GlobalDefinitions.door)
|
||||
door1.GUID = PlanetSideGUID(1)
|
||||
door1.Actor = system.actorOf(Props(classOf[DoorControl], door1), "door1-test")
|
||||
val door2 = Door(GlobalDefinitions.door)
|
||||
door2.GUID = PlanetSideGUID(2)
|
||||
door2.Actor = system.actorOf(Props(classOf[DoorControl], door2), "door2-test")
|
||||
bldg.Amenities = door2
|
||||
bldg.Amenities = door1
|
||||
assert(bldg.Faction == PlanetSideEmpire.TR)
|
||||
assert(bldg.Amenities.length == 2)
|
||||
assert(bldg.Amenities.head == door2)
|
||||
assert(bldg.Amenities(1) == door1)
|
||||
|
||||
bldg.Actor ! FactionAffinity.ConvertFactionAffinity(PlanetSideEmpire.VS)
|
||||
val reply = receiveN(3, Duration.create(500, "ms"))
|
||||
assert(reply.length == 3)
|
||||
var building_count = 0
|
||||
var door_count = 0
|
||||
reply.foreach(item => {
|
||||
assert(item.isInstanceOf[FactionAffinity.AssertFactionAffinity])
|
||||
val item2 = item.asInstanceOf[FactionAffinity.AssertFactionAffinity]
|
||||
item2.obj match {
|
||||
case _ : Building =>
|
||||
building_count += 1
|
||||
case _ : Door =>
|
||||
door_count += 1
|
||||
case _ =>
|
||||
assert(false)
|
||||
}
|
||||
assert(item2.faction == PlanetSideEmpire.VS)
|
||||
})
|
||||
assert(building_count == 1 && door_count == 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,11 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.{ActorRef, Props}
|
||||
import akka.actor.{ActorRef, ActorSystem, Props}
|
||||
import net.psforever.objects.{GlobalDefinitions, Player}
|
||||
import net.psforever.objects.serverobject.doors.{Door, DoorControl}
|
||||
import net.psforever.objects.serverobject.structures.Building
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.game.{PlanetSideGUID, UseItemMessage}
|
||||
import net.psforever.types.{CharacterGender, PlanetSideEmpire, Vector3}
|
||||
import org.specs2.mutable.Specification
|
||||
|
|
@ -11,6 +13,8 @@ import org.specs2.mutable.Specification
|
|||
import scala.concurrent.duration.Duration
|
||||
|
||||
class DoorTest extends Specification {
|
||||
val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
|
||||
"Door" should {
|
||||
"construct" in {
|
||||
Door(GlobalDefinitions.door)
|
||||
|
|
@ -24,7 +28,6 @@ class DoorTest extends Specification {
|
|||
}
|
||||
|
||||
"be opened and closed (1; manual)" in {
|
||||
val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val door = Door(GlobalDefinitions.door)
|
||||
door.isOpen mustEqual false
|
||||
door.Open mustEqual None
|
||||
|
|
@ -39,7 +42,6 @@ class DoorTest extends Specification {
|
|||
}
|
||||
|
||||
"be opened and closed (2; toggle)" in {
|
||||
val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val msg = UseItemMessage(PlanetSideGUID(6585), 0, PlanetSideGUID(372), 4294967295L, false, Vector3(5.0f,0.0f,0.0f), Vector3(0.0f,0.0f,0.0f), 11, 25, 0, 364)
|
||||
val door = Door(GlobalDefinitions.door)
|
||||
door.Open mustEqual None
|
||||
|
|
@ -85,9 +87,7 @@ class DoorControl1Test extends ActorTest() {
|
|||
class DoorControl2Test extends ActorTest() {
|
||||
"DoorControl" should {
|
||||
"open on use" in {
|
||||
val door = Door(GlobalDefinitions.door)
|
||||
door.Actor = system.actorOf(Props(classOf[DoorControl], door), "door")
|
||||
val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val (player, door) = DoorControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
val msg = UseItemMessage(PlanetSideGUID(1), 0, PlanetSideGUID(2), 0L, false, Vector3(0f,0f,0f),Vector3(0f,0f,0f),0,0,0,0L) //faked
|
||||
assert(door.Open.isEmpty)
|
||||
|
||||
|
|
@ -106,8 +106,7 @@ class DoorControl2Test extends ActorTest() {
|
|||
class DoorControl3Test extends ActorTest() {
|
||||
"DoorControl" should {
|
||||
"do nothing if given garbage" in {
|
||||
val door = Door(GlobalDefinitions.door)
|
||||
door.Actor = system.actorOf(Props(classOf[DoorControl], door), "door")
|
||||
val (_, door) = DoorControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
assert(door.Open.isEmpty)
|
||||
|
||||
door.Actor ! "trash"
|
||||
|
|
@ -117,3 +116,13 @@ class DoorControl3Test extends ActorTest() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
object DoorControlTest {
|
||||
def SetUpAgents(faction : PlanetSideEmpire.Value)(implicit system : ActorSystem) : (Player, Door) = {
|
||||
val door = Door(GlobalDefinitions.door)
|
||||
door.Actor = system.actorOf(Props(classOf[DoorControl], door), "door")
|
||||
door.Owner = new Building(0, Zone.Nowhere)
|
||||
door.Owner.Faction = faction
|
||||
(Player("test", faction, CharacterGender.Male, 0, 0), door)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
131
common/src/test/scala/objects/FactionAffinityTest.scala
Normal file
131
common/src/test/scala/objects/FactionAffinityTest.scala
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.{Actor, ActorSystem, Props}
|
||||
import net.psforever.objects.{GlobalDefinitions, Vehicle}
|
||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||
import net.psforever.objects.serverobject.doors.Door
|
||||
import net.psforever.objects.serverobject.structures.Building
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
import scala.concurrent.duration.Duration
|
||||
|
||||
class FactionAffinityTest extends Specification {
|
||||
"FactionAffinity" should {
|
||||
"construct (basic)" in {
|
||||
val obj = new FactionAffinity { def Faction = PlanetSideEmpire.TR }
|
||||
obj.Faction mustEqual PlanetSideEmpire.TR
|
||||
}
|
||||
|
||||
"construct (part of)" in {
|
||||
val obj = new Door(GlobalDefinitions.door)
|
||||
obj.Faction mustEqual PlanetSideEmpire.NEUTRAL
|
||||
}
|
||||
|
||||
"can not change affinity directly (basic)" in {
|
||||
val obj = new FactionAffinity { def Faction = PlanetSideEmpire.TR }
|
||||
(obj.Faction = PlanetSideEmpire.NC) mustEqual PlanetSideEmpire.TR
|
||||
}
|
||||
|
||||
"can not change affinity directly (part of)" in {
|
||||
val obj = new Door(GlobalDefinitions.door)
|
||||
(obj.Faction = PlanetSideEmpire.TR) mustEqual PlanetSideEmpire.NEUTRAL
|
||||
}
|
||||
|
||||
"inherits affinity from owner 1" in {
|
||||
val obj = new Door(GlobalDefinitions.door)
|
||||
obj.Owner.Faction mustEqual PlanetSideEmpire.NEUTRAL
|
||||
(obj.Faction = PlanetSideEmpire.TR) mustEqual PlanetSideEmpire.NEUTRAL
|
||||
}
|
||||
|
||||
"inherits affinity from owner 2" in {
|
||||
val obj = new Door(GlobalDefinitions.door)
|
||||
val bldg = new Building(1, Zone.Nowhere)
|
||||
obj.Owner = bldg
|
||||
obj.Faction mustEqual PlanetSideEmpire.NEUTRAL
|
||||
|
||||
bldg.Faction = PlanetSideEmpire.TR
|
||||
obj.Faction mustEqual PlanetSideEmpire.TR
|
||||
|
||||
bldg.Faction = PlanetSideEmpire.NC
|
||||
obj.Faction mustEqual PlanetSideEmpire.NC
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FactionAffinity1Test extends ActorTest() {
|
||||
"FactionAffinity" should {
|
||||
"assert affinity on confirm request" in {
|
||||
val obj = FactionAffinityTest.SetUpAgent
|
||||
obj.Faction = PlanetSideEmpire.VS //object is a type that can be changed directly
|
||||
assert(obj.Faction == PlanetSideEmpire.VS)
|
||||
|
||||
obj.Actor ! FactionAffinity.ConfirmFactionAffinity()
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
assert(reply.isInstanceOf[FactionAffinity.AssertFactionAffinity])
|
||||
assert(reply.asInstanceOf[FactionAffinity.AssertFactionAffinity].obj == obj)
|
||||
assert(reply.asInstanceOf[FactionAffinity.AssertFactionAffinity].faction == PlanetSideEmpire.VS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FactionAffinity2Test extends ActorTest() {
|
||||
"FactionAffinity" should {
|
||||
"assert affinity on assert request" in {
|
||||
val obj = FactionAffinityTest.SetUpAgent
|
||||
obj.Faction = PlanetSideEmpire.VS //object is a type that can be changed directly
|
||||
assert(obj.Faction == PlanetSideEmpire.VS)
|
||||
|
||||
obj.Actor ! FactionAffinity.AssertFactionAffinity(obj, PlanetSideEmpire.NEUTRAL)
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
assert(reply.isInstanceOf[FactionAffinity.AssertFactionAffinity])
|
||||
assert(reply.asInstanceOf[FactionAffinity.AssertFactionAffinity].obj == obj)
|
||||
assert(reply.asInstanceOf[FactionAffinity.AssertFactionAffinity].faction == PlanetSideEmpire.VS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FactionAffinity3Test extends ActorTest() {
|
||||
"FactionAffinity" should {
|
||||
"convert and assert affinity on convert request" in {
|
||||
val obj = FactionAffinityTest.SetUpAgent
|
||||
obj.Faction = PlanetSideEmpire.VS //object is a type that can be changed directly
|
||||
assert(obj.Faction == PlanetSideEmpire.VS)
|
||||
|
||||
obj.Actor ! FactionAffinity.ConvertFactionAffinity(PlanetSideEmpire.TR)
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
assert(reply.isInstanceOf[FactionAffinity.AssertFactionAffinity])
|
||||
assert(reply.asInstanceOf[FactionAffinity.AssertFactionAffinity].obj == obj)
|
||||
assert(reply.asInstanceOf[FactionAffinity.AssertFactionAffinity].faction == PlanetSideEmpire.TR)
|
||||
assert(obj.Faction == PlanetSideEmpire.TR)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object FactionAffinityTest {
|
||||
import net.psforever.objects.serverobject.affinity.FactionAffinityBehavior
|
||||
|
||||
private class AffinityControl(obj : FactionAffinity) extends Actor
|
||||
with FactionAffinityBehavior.Check
|
||||
with FactionAffinityBehavior.Convert {
|
||||
override def FactionObject = obj
|
||||
def receive = checkBehavior.orElse(convertBehavior).orElse { case _ => }
|
||||
}
|
||||
|
||||
def SetUpAgent(implicit system : ActorSystem) = {
|
||||
val obj = new Vehicle(GlobalDefinitions.quadstealth)
|
||||
obj.Actor = system.actorOf(Props(classOf[FactionAffinityTest.AffinityControl], obj), "test")
|
||||
obj
|
||||
}
|
||||
|
||||
def FreeFactionObject : FactionAffinity = new FactionAffinity() {
|
||||
private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||
def Faction : PlanetSideEmpire.Value = faction
|
||||
override def Faction_=(fac : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = {
|
||||
faction = fac
|
||||
faction
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,13 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.{ActorRef, Props}
|
||||
import akka.actor.{ActorRef, ActorSystem, Props}
|
||||
import net.psforever.objects.serverobject.CommonMessages
|
||||
import net.psforever.objects.{GlobalDefinitions, Player}
|
||||
import net.psforever.objects.serverobject.locks.{IFFLock, IFFLockControl}
|
||||
import net.psforever.objects.serverobject.structures.Building
|
||||
import net.psforever.objects.serverobject.terminals.{Terminal, TerminalControl, TerminalDefinition}
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.types.{CharacterGender, PlanetSideEmpire}
|
||||
import org.specs2.mutable.Specification
|
||||
|
|
@ -33,9 +36,7 @@ class IFFLockControl1Test extends ActorTest() {
|
|||
class IFFLockControl2Test extends ActorTest() {
|
||||
"IFFLockControl" should {
|
||||
"can hack" in {
|
||||
val lock = IFFLock(GlobalDefinitions.lock_external)
|
||||
lock.Actor = system.actorOf(Props(classOf[IFFLockControl], lock), "lock-control")
|
||||
val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val (player, lock) = IFFLockControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
player.GUID = PlanetSideGUID(1)
|
||||
assert(lock.HackedBy.isEmpty)
|
||||
|
||||
|
|
@ -49,9 +50,7 @@ class IFFLockControl2Test extends ActorTest() {
|
|||
class IFFLockControl3Test extends ActorTest() {
|
||||
"IFFLockControl" should {
|
||||
"can hack" in {
|
||||
val lock = IFFLock(GlobalDefinitions.lock_external)
|
||||
lock.Actor = system.actorOf(Props(classOf[IFFLockControl], lock), "lock-control")
|
||||
val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val (player, lock) = IFFLockControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
player.GUID = PlanetSideGUID(1)
|
||||
assert(lock.HackedBy.isEmpty)
|
||||
|
||||
|
|
@ -64,3 +63,13 @@ class IFFLockControl3Test extends ActorTest() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
object IFFLockControlTest {
|
||||
def SetUpAgents(faction : PlanetSideEmpire.Value)(implicit system : ActorSystem) : (Player, IFFLock) = {
|
||||
val lock = IFFLock(GlobalDefinitions.lock_external)
|
||||
lock.Actor = system.actorOf(Props(classOf[IFFLockControl], lock), "lock-control")
|
||||
lock.Owner = new Building(0, Zone.Nowhere)
|
||||
lock.Owner.Faction = faction
|
||||
(Player("test", faction, CharacterGender.Male, 0, 0), lock)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
36
common/src/test/scala/objects/LockerTest.scala
Normal file
36
common/src/test/scala/objects/LockerTest.scala
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.{ActorRef, Props}
|
||||
import net.psforever.objects.GlobalDefinitions
|
||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||
import net.psforever.objects.serverobject.mblocker.{Locker, LockerControl}
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
import org.specs2.mutable._
|
||||
|
||||
class LockerTest extends Specification {
|
||||
"LockerDefinition" should {
|
||||
"define" in {
|
||||
GlobalDefinitions.mb_locker.ObjectId mustEqual 524
|
||||
GlobalDefinitions.mb_locker.Name mustEqual "mb_locker"
|
||||
}
|
||||
}
|
||||
|
||||
"Locker" should {
|
||||
"construct" in {
|
||||
val locker = new Locker()
|
||||
locker.Actor mustEqual ActorRef.noSender
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LockerControlTest extends ActorTest {
|
||||
"LockerControl" should {
|
||||
"construct" in {
|
||||
val locker = new Locker()
|
||||
locker.Actor = system.actorOf(Props(classOf[LockerControl], locker), "test")
|
||||
locker.Actor ! FactionAffinity.ConfirmFactionAffinity()
|
||||
expectMsg(FactionAffinity.AssertFactionAffinity(locker, PlanetSideEmpire.NEUTRAL))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,9 +4,10 @@ package objects
|
|||
import akka.actor.{Actor, ActorRef, Props}
|
||||
import net.psforever.objects.Player
|
||||
import net.psforever.objects.definition.{ObjectDefinition, SeatDefinition}
|
||||
import net.psforever.objects.mount.{Mountable, MountableBehavior}
|
||||
import net.psforever.objects.serverobject.mount.{Mountable, MountableBehavior}
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
import net.psforever.objects.vehicles.Seat
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.types.{CharacterGender, PlanetSideEmpire}
|
||||
|
||||
import scala.concurrent.duration.Duration
|
||||
|
|
@ -80,12 +81,15 @@ object MountableTest {
|
|||
None
|
||||
}
|
||||
}
|
||||
def Definition : ObjectDefinition = null //eh whatever
|
||||
GUID = PlanetSideGUID(1)
|
||||
//eh whatever
|
||||
def Faction = PlanetSideEmpire.TR
|
||||
def Definition : ObjectDefinition = null
|
||||
}
|
||||
|
||||
class MountableTestControl(obj : Mountable) extends Actor with MountableBehavior {
|
||||
class MountableTestControl(obj : PlanetSideServerObject with Mountable) extends Actor with MountableBehavior.Mount with MountableBehavior.Dismount {
|
||||
override def MountableObject = obj
|
||||
|
||||
def receive : Receive = mountableBehavior
|
||||
def receive : Receive = mountBehavior.orElse(dismountBehavior)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,10 +5,26 @@ import akka.actor.{Actor, Props}
|
|||
import net.psforever.objects.guid.NumberPoolHub
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.objects.serverobject.ServerObjectBuilder
|
||||
import net.psforever.objects.serverobject.structures.{Building, FoundationBuilder}
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.types.Vector3
|
||||
|
||||
import scala.concurrent.duration.Duration
|
||||
|
||||
class BuildingBuilderTest extends ActorTest {
|
||||
"Building object" should {
|
||||
"build" in {
|
||||
val actor = system.actorOf(Props(classOf[ServerObjectBuilderTest.BuildingTestActor], 10, Zone.Nowhere), "building")
|
||||
actor ! "!"
|
||||
|
||||
val reply = receiveOne(Duration.create(1000, "ms"))
|
||||
assert(reply.isInstanceOf[Building])
|
||||
assert(reply.asInstanceOf[Building].Id == 10)
|
||||
assert(reply.asInstanceOf[Building].Zone == Zone.Nowhere)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DoorObjectBuilderTest1 extends ActorTest {
|
||||
import net.psforever.objects.serverobject.doors.Door
|
||||
"Door object" should {
|
||||
|
|
@ -150,4 +166,11 @@ object ServerObjectBuilderTest {
|
|||
sender ! builder.Build(context, hub)
|
||||
}
|
||||
}
|
||||
|
||||
class BuildingTestActor(building_id : Int, zone : Zone) extends Actor {
|
||||
def receive : Receive = {
|
||||
case _ =>
|
||||
sender ! FoundationBuilder(Building.Structure).Build(building_id, zone)(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.{ActorRef, Props}
|
||||
import akka.actor.{ActorRef, ActorSystem, Props}
|
||||
import net.psforever.objects.serverobject.pad.{VehicleSpawnControl, VehicleSpawnPad}
|
||||
import net.psforever.objects.serverobject.structures.Building
|
||||
import net.psforever.objects.vehicles.VehicleControl
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.objects.{GlobalDefinitions, Player, Vehicle}
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.types.{CharacterGender, PlanetSideEmpire, Vector3}
|
||||
|
|
@ -40,22 +42,20 @@ class VehicleSpawnControl1Test extends ActorTest() {
|
|||
class VehicleSpawnControl2Test extends ActorTest() {
|
||||
"VehicleSpawnControl" should {
|
||||
"spawn a vehicle" in {
|
||||
val obj = VehicleSpawnPad(GlobalDefinitions.spawn_pad)
|
||||
obj.Actor = system.actorOf(Props(classOf[VehicleSpawnControl], obj), "door")
|
||||
val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val (player, pad) = VehicleSpawnPadControl.SetUpAgents(PlanetSideEmpire.TR)
|
||||
player.Spawn
|
||||
val vehicle = Vehicle(GlobalDefinitions.two_man_assault_buggy)
|
||||
vehicle.GUID = PlanetSideGUID(1)
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle")
|
||||
|
||||
obj.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle)
|
||||
pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle)
|
||||
val reply = receiveOne(Duration.create(10000, "ms"))
|
||||
assert(reply == VehicleSpawnPad.ConcealPlayer) //explicit: isInstanceOf does not work
|
||||
|
||||
val reply2 = receiveOne(Duration.create(10000, "ms"))
|
||||
assert(reply2.isInstanceOf[VehicleSpawnPad.LoadVehicle])
|
||||
assert(reply2.asInstanceOf[VehicleSpawnPad.LoadVehicle].vehicle == vehicle)
|
||||
assert(reply2.asInstanceOf[VehicleSpawnPad.LoadVehicle].pad == obj)
|
||||
assert(reply2.asInstanceOf[VehicleSpawnPad.LoadVehicle].pad == pad)
|
||||
|
||||
player.VehicleOwned = Some(vehicle.GUID)
|
||||
val reply3 = receiveOne(Duration.create(10000, "ms"))
|
||||
|
|
@ -78,14 +78,12 @@ class VehicleSpawnControl2Test extends ActorTest() {
|
|||
class VehicleSpawnControl3Test extends ActorTest() {
|
||||
"VehicleSpawnControl" should {
|
||||
"not spawn a vehicle if player is dead" in {
|
||||
val obj = VehicleSpawnPad(GlobalDefinitions.spawn_pad)
|
||||
obj.Actor = system.actorOf(Props(classOf[VehicleSpawnControl], obj), "door")
|
||||
val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val (player, pad) = VehicleSpawnPadControl.SetUpAgents(PlanetSideEmpire.TR)
|
||||
val vehicle = Vehicle(GlobalDefinitions.two_man_assault_buggy)
|
||||
vehicle.GUID = PlanetSideGUID(1)
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle")
|
||||
|
||||
obj.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle)
|
||||
pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle)
|
||||
val reply = receiveOne(Duration.create(5000, "ms"))
|
||||
assert(reply == null)
|
||||
}
|
||||
|
|
@ -95,16 +93,24 @@ class VehicleSpawnControl3Test extends ActorTest() {
|
|||
class VehicleSpawnControl4Test extends ActorTest() {
|
||||
"VehicleSpawnControl" should {
|
||||
"not spawn a vehicle if vehicle Actor is missing" in {
|
||||
val obj = VehicleSpawnPad(GlobalDefinitions.spawn_pad)
|
||||
obj.Actor = system.actorOf(Props(classOf[VehicleSpawnControl], obj), "door")
|
||||
val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val (player, pad) = VehicleSpawnPadControl.SetUpAgents(PlanetSideEmpire.TR)
|
||||
player.Spawn
|
||||
val vehicle = Vehicle(GlobalDefinitions.two_man_assault_buggy)
|
||||
vehicle.GUID = PlanetSideGUID(1)
|
||||
|
||||
obj.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle)
|
||||
pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle)
|
||||
val reply = receiveOne(Duration.create(5000, "ms"))
|
||||
assert(reply == null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object VehicleSpawnPadControl {
|
||||
def SetUpAgents(faction : PlanetSideEmpire.Value)(implicit system : ActorSystem) : (Player, VehicleSpawnPad) = {
|
||||
val pad = VehicleSpawnPad(GlobalDefinitions.spawn_pad)
|
||||
pad.Actor = system.actorOf(Props(classOf[VehicleSpawnControl], pad), "test-pad")
|
||||
pad.Owner = new Building(0, Zone.Nowhere)
|
||||
pad.Owner.Faction = faction
|
||||
(Player("test", faction, CharacterGender.Male, 0, 0), pad)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.Props
|
||||
import net.psforever.objects.{GlobalDefinitions, Player, Vehicle}
|
||||
import net.psforever.objects.definition.SeatDefinition
|
||||
import net.psforever.objects.vehicles.{AccessPermissionGroup, Seat, SeatArmorRestriction, VehicleLockState}
|
||||
import net.psforever.objects.serverobject.mount.Mountable
|
||||
import net.psforever.objects.vehicles._
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.types.{CharacterGender, ExoSuitType, PlanetSideEmpire}
|
||||
import org.specs2.mutable._
|
||||
|
||||
import scala.concurrent.duration.Duration
|
||||
|
||||
class VehicleTest extends Specification {
|
||||
|
||||
"SeatDefinition" should {
|
||||
|
|
@ -254,3 +258,49 @@ class VehicleTest extends Specification {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControl1Test extends ActorTest {
|
||||
"Vehicle Control" should {
|
||||
"deactivate and stop handling mount messages" in {
|
||||
val player1 = Player("test1", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
player1.GUID = PlanetSideGUID(1)
|
||||
val player2 = Player("test2", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val vehicle = Vehicle(GlobalDefinitions.two_man_assault_buggy)
|
||||
vehicle.GUID = PlanetSideGUID(3)
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
|
||||
vehicle.Actor ! Mountable.TryMount(player1, 0)
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
assert(reply.isInstanceOf[Mountable.MountMessages])
|
||||
|
||||
vehicle.Actor ! Vehicle.PrepareForDeletion
|
||||
vehicle.Actor ! Mountable.TryMount(player2, 1)
|
||||
expectNoMsg(Duration.create(200, "ms"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControl2Test extends ActorTest {
|
||||
"Vehicle Control" should {
|
||||
"reactivate and resume handling mount messages" in {
|
||||
val player1 = Player("test1", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
player1.GUID = PlanetSideGUID(1)
|
||||
val player2 = Player("test2", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
player2.GUID = PlanetSideGUID(2)
|
||||
val vehicle = Vehicle(GlobalDefinitions.two_man_assault_buggy)
|
||||
vehicle.GUID = PlanetSideGUID(3)
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
|
||||
vehicle.Actor ! Mountable.TryMount(player1, 0)
|
||||
receiveOne(Duration.create(100, "ms")) //discard
|
||||
vehicle.Actor ! Vehicle.PrepareForDeletion
|
||||
vehicle.Actor ! Mountable.TryMount(player2, 1)
|
||||
expectNoMsg(Duration.create(200, "ms"))
|
||||
|
||||
vehicle.Actor ! Vehicle.Reactivate
|
||||
vehicle.Actor ! Mountable.TryMount(player2, 1)
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
assert(reply.isInstanceOf[Mountable.MountMessages])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,39 +1,44 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.{ActorContext, ActorRef}
|
||||
import net.psforever.objects.entity.IdentifiableEntity
|
||||
import net.psforever.objects.equipment.Equipment
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
import net.psforever.objects.guid.source.LimitedNumberSource
|
||||
import net.psforever.objects.serverobject.structures.{Building, FoundationBuilder}
|
||||
import net.psforever.objects.zones.{Zone, ZoneMap}
|
||||
import net.psforever.objects.{GlobalDefinitions, Vehicle}
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
class ZoneTest extends Specification {
|
||||
def test(a: Int, b : Zone, c : ActorContext) : Building = { Building.NoBuilding }
|
||||
|
||||
"ZoneMap" should {
|
||||
//TODO these are temporary tests as the current ZoneMap is a kludge
|
||||
"construct" in {
|
||||
new ZoneMap("map13")
|
||||
ok
|
||||
}
|
||||
|
||||
"references bases by a positive building id (defaults to 0)" in {
|
||||
def test(a: Int, b : Zone, c : ActorContext) : Building = { Building.NoBuilding }
|
||||
|
||||
val map = new ZoneMap("map13")
|
||||
map.LocalBases mustEqual 0
|
||||
map.LocalBases = 10
|
||||
map.LocalBases mustEqual 10
|
||||
map.LocalBases = -1
|
||||
map.LocalBases mustEqual 10
|
||||
map.LocalBuildings mustEqual Map.empty
|
||||
map.LocalBuilding(10, FoundationBuilder(test))
|
||||
map.LocalBuildings.keySet.contains(10) mustEqual true
|
||||
map.LocalBuilding(-1, FoundationBuilder(test))
|
||||
map.LocalBuildings.keySet.contains(10) mustEqual true
|
||||
map.LocalBuildings.keySet.contains(-1) mustEqual false
|
||||
}
|
||||
|
||||
"associates objects to bases (doesn't check numbers)" in {
|
||||
val map = new ZoneMap("map13")
|
||||
map.ObjectToBase mustEqual Nil
|
||||
map.ObjectToBase(1, 2)
|
||||
map.ObjectToBase mustEqual List((1, 2))
|
||||
map.ObjectToBase(3, 4)
|
||||
map.ObjectToBase mustEqual List((1, 2), (3, 4))
|
||||
map.ObjectToBuilding mustEqual Nil
|
||||
map.ObjectToBuilding(1, 2)
|
||||
map.ObjectToBuilding mustEqual Map(1 -> 2)
|
||||
map.ObjectToBuilding(3, 4)
|
||||
map.ObjectToBuilding mustEqual Map(1 -> 2, 3 -> 4)
|
||||
}
|
||||
|
||||
"associates doors to door locks (doesn't check numbers)" in {
|
||||
|
|
@ -65,11 +70,10 @@ class ZoneTest extends Specification {
|
|||
}
|
||||
|
||||
val map13 = new ZoneMap("map13")
|
||||
map13.LocalBases = 10
|
||||
map13.LocalBuilding(10, FoundationBuilder(test))
|
||||
class TestObject extends IdentifiableEntity
|
||||
|
||||
"Zone" should {
|
||||
//TODO these are temporary tests as the current Zone is a kludge
|
||||
"construct" in {
|
||||
val zone = new Zone("home3", map13, 13)
|
||||
zone.GUID mustEqual ActorRef.noSender
|
||||
|
|
|
|||
|
|
@ -2,8 +2,10 @@
|
|||
package objects.terminal
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import net.psforever.objects.serverobject.structures.Building
|
||||
import net.psforever.objects.{GlobalDefinitions, Player}
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.game.{ItemTransactionMessage, PlanetSideGUID}
|
||||
import net.psforever.types.{CharacterGender, PlanetSideEmpire, TransactionType}
|
||||
import org.specs2.mutable.Specification
|
||||
|
|
@ -11,6 +13,9 @@ import org.specs2.mutable.Specification
|
|||
class AirVehicleTerminalTest extends Specification {
|
||||
"Air_Vehicle_Terminal" should {
|
||||
val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val terminal = Terminal(GlobalDefinitions.air_vehicle_terminal)
|
||||
terminal.Owner = new Building(0, Zone.Nowhere)
|
||||
terminal.Owner.Faction = PlanetSideEmpire.TR
|
||||
|
||||
"construct" in {
|
||||
val terminal = Terminal(GlobalDefinitions.air_vehicle_terminal)
|
||||
|
|
@ -18,8 +23,8 @@ class AirVehicleTerminalTest extends Specification {
|
|||
}
|
||||
|
||||
"player can buy a reaver ('lightgunship')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.air_vehicle_terminal)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "lightgunship", 0, PlanetSideGUID(0))
|
||||
|
||||
val reply = terminal.Request(player, msg)
|
||||
reply.isInstanceOf[Terminal.BuyVehicle] mustEqual true
|
||||
val reply2 = reply.asInstanceOf[Terminal.BuyVehicle]
|
||||
|
|
@ -35,7 +40,6 @@ class AirVehicleTerminalTest extends Specification {
|
|||
}
|
||||
|
||||
"player can not buy a fake vehicle ('reaver')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.ground_vehicle_terminal)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "reaver", 0, PlanetSideGUID(0))
|
||||
|
||||
terminal.Request(player, msg) mustEqual Terminal.NoDeal()
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
package objects.terminal
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import net.psforever.objects.serverobject.structures.Building
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.objects.{GlobalDefinitions, Player}
|
||||
import net.psforever.packet.game.{ItemTransactionMessage, PlanetSideGUID}
|
||||
import net.psforever.types._
|
||||
|
|
@ -11,6 +13,9 @@ import org.specs2.mutable.Specification
|
|||
class CertTerminalTest extends Specification {
|
||||
"Cert_Terminal" should {
|
||||
val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val terminal = Terminal(GlobalDefinitions.cert_terminal)
|
||||
terminal.Owner = new Building(0, Zone.Nowhere)
|
||||
terminal.Owner.Faction = PlanetSideEmpire.TR
|
||||
|
||||
"construct" in {
|
||||
val terminal = Terminal(GlobalDefinitions.cert_terminal)
|
||||
|
|
@ -18,27 +23,23 @@ class CertTerminalTest extends Specification {
|
|||
}
|
||||
|
||||
"player can learn a certification ('medium_assault')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.cert_terminal)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Learn, 0, "medium_assault", 0, PlanetSideGUID(0))
|
||||
terminal.Request(player, msg) mustEqual Terminal.LearnCertification(CertificationType.MediumAssault, 2)
|
||||
}
|
||||
|
||||
"player can not learn a fake certification ('juggling')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.cert_terminal)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Learn, 0, "juggling", 0, PlanetSideGUID(0))
|
||||
|
||||
terminal.Request(player, msg) mustEqual Terminal.NoDeal()
|
||||
}
|
||||
|
||||
"player can forget a certification ('medium_assault')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.cert_terminal)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Sell, 0, "medium_assault", 0, PlanetSideGUID(0))
|
||||
|
||||
terminal.Request(player, msg) mustEqual Terminal.SellCertification(CertificationType.MediumAssault, 2)
|
||||
}
|
||||
|
||||
"player can not forget a fake certification ('juggling')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.cert_terminal)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Sell, 0, "juggling", 0, PlanetSideGUID(0))
|
||||
|
||||
terminal.Request(player, msg) mustEqual Terminal.NoDeal()
|
||||
|
|
|
|||
|
|
@ -2,8 +2,10 @@
|
|||
package objects.terminal
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import net.psforever.objects.serverobject.structures.Building
|
||||
import net.psforever.objects.{GlobalDefinitions, Player}
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.game.{ItemTransactionMessage, PlanetSideGUID}
|
||||
import net.psforever.types.{CharacterGender, PlanetSideEmpire, TransactionType}
|
||||
import org.specs2.mutable.Specification
|
||||
|
|
@ -11,6 +13,9 @@ import org.specs2.mutable.Specification
|
|||
class DropshipVehicleTerminalTest extends Specification {
|
||||
"Dropship_Vehicle_Terminal" should {
|
||||
val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val terminal = Terminal(GlobalDefinitions.dropship_vehicle_terminal)
|
||||
terminal.Owner = new Building(0, Zone.Nowhere)
|
||||
terminal.Owner.Faction = PlanetSideEmpire.TR
|
||||
|
||||
"construct" in {
|
||||
val terminal = Terminal(GlobalDefinitions.dropship_vehicle_terminal)
|
||||
|
|
@ -18,8 +23,8 @@ class DropshipVehicleTerminalTest extends Specification {
|
|||
}
|
||||
|
||||
"player can buy a galaxy ('dropship')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.dropship_vehicle_terminal)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "dropship", 0, PlanetSideGUID(0))
|
||||
|
||||
val reply = terminal.Request(player, msg)
|
||||
reply.isInstanceOf[Terminal.BuyVehicle] mustEqual true
|
||||
val reply2 = reply.asInstanceOf[Terminal.BuyVehicle]
|
||||
|
|
@ -41,7 +46,6 @@ class DropshipVehicleTerminalTest extends Specification {
|
|||
}
|
||||
|
||||
"player can not buy a fake vehicle ('galaxy')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.dropship_vehicle_terminal)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "galaxy", 0, PlanetSideGUID(0))
|
||||
|
||||
terminal.Request(player, msg) mustEqual Terminal.NoDeal()
|
||||
|
|
|
|||
|
|
@ -2,8 +2,10 @@
|
|||
package objects.terminal
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import net.psforever.objects.serverobject.structures.Building
|
||||
import net.psforever.objects.{GlobalDefinitions, Player}
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.game.{ItemTransactionMessage, PlanetSideGUID}
|
||||
import net.psforever.types.{CharacterGender, PlanetSideEmpire, TransactionType}
|
||||
import org.specs2.mutable.Specification
|
||||
|
|
@ -11,6 +13,9 @@ import org.specs2.mutable.Specification
|
|||
class GroundVehicleTerminalTest extends Specification {
|
||||
"Ground_Vehicle_Terminal" should {
|
||||
val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val terminal = Terminal(GlobalDefinitions.ground_vehicle_terminal)
|
||||
terminal.Owner = new Building(0, Zone.Nowhere)
|
||||
terminal.Owner.Faction = PlanetSideEmpire.TR
|
||||
|
||||
"construct" in {
|
||||
val terminal = Terminal(GlobalDefinitions.ground_vehicle_terminal)
|
||||
|
|
@ -18,8 +23,8 @@ class GroundVehicleTerminalTest extends Specification {
|
|||
}
|
||||
|
||||
"player can buy a harasser ('two_man_assault_buggy')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.ground_vehicle_terminal)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "two_man_assault_buggy", 0, PlanetSideGUID(0))
|
||||
|
||||
val reply = terminal.Request(player, msg)
|
||||
reply.isInstanceOf[Terminal.BuyVehicle] mustEqual true
|
||||
val reply2 = reply.asInstanceOf[Terminal.BuyVehicle]
|
||||
|
|
@ -35,7 +40,6 @@ class GroundVehicleTerminalTest extends Specification {
|
|||
}
|
||||
|
||||
"player can not buy a fake vehicle ('harasser')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.ground_vehicle_terminal)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "harasser", 0, PlanetSideGUID(0))
|
||||
|
||||
terminal.Request(player, msg) mustEqual Terminal.NoDeal()
|
||||
|
|
|
|||
|
|
@ -2,8 +2,10 @@
|
|||
package objects.terminal
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import net.psforever.objects.serverobject.structures.Building
|
||||
import net.psforever.objects.{GlobalDefinitions, Player}
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.game.{ItemTransactionMessage, PlanetSideGUID}
|
||||
import net.psforever.types.{CharacterGender, PlanetSideEmpire, TransactionType}
|
||||
import org.specs2.mutable.Specification
|
||||
|
|
@ -11,6 +13,9 @@ import org.specs2.mutable.Specification
|
|||
class ImplantTerminalInterfaceTest extends Specification {
|
||||
"Implant_Terminal_Interface" should {
|
||||
val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val terminal = Terminal(GlobalDefinitions.implant_terminal_interface)
|
||||
terminal.Owner = new Building(0, Zone.Nowhere)
|
||||
terminal.Owner.Faction = PlanetSideEmpire.TR
|
||||
|
||||
"construct" in {
|
||||
val terminal = Terminal(GlobalDefinitions.implant_terminal_interface)
|
||||
|
|
@ -18,8 +23,8 @@ class ImplantTerminalInterfaceTest extends Specification {
|
|||
}
|
||||
|
||||
"player can learn an implant ('darklight_vision')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.implant_terminal_interface)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "darklight_vision", 0, PlanetSideGUID(0))
|
||||
|
||||
val reply = terminal.Request(player, msg)
|
||||
reply.isInstanceOf[Terminal.LearnImplant] mustEqual true
|
||||
val reply2 = reply.asInstanceOf[Terminal.LearnImplant]
|
||||
|
|
@ -27,15 +32,14 @@ class ImplantTerminalInterfaceTest extends Specification {
|
|||
}
|
||||
|
||||
"player can not learn a fake implant ('aimbot')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.implant_terminal_interface)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "aimbot", 0, PlanetSideGUID(0))
|
||||
|
||||
terminal.Request(player, msg) mustEqual Terminal.NoDeal()
|
||||
}
|
||||
|
||||
"player can surrender an implant ('darklight_vision')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.implant_terminal_interface)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Sell, 0, "darklight_vision", 0, PlanetSideGUID(0))
|
||||
|
||||
val reply = terminal.Request(player, msg)
|
||||
reply.isInstanceOf[Terminal.SellImplant] mustEqual true
|
||||
val reply2 = reply.asInstanceOf[Terminal.SellImplant]
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.terminal
|
||||
|
||||
import akka.actor.{ActorRef, Props}
|
||||
import akka.actor.{ActorRef, ActorSystem, Props}
|
||||
import net.psforever.objects.definition.SeatDefinition
|
||||
import net.psforever.objects.mount.Mountable
|
||||
import net.psforever.objects.serverobject.mount.Mountable
|
||||
import net.psforever.objects.serverobject.implantmech.{ImplantTerminalMech, ImplantTerminalMechControl}
|
||||
import net.psforever.objects.vehicles.Seat
|
||||
import net.psforever.objects.{GlobalDefinitions, Player}
|
||||
import net.psforever.types.{CharacterGender, PlanetSideEmpire}
|
||||
import net.psforever.types.{CharacterGender, PlanetSideEmpire, Vector3}
|
||||
import objects.ActorTest
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
|
|
@ -68,43 +68,101 @@ class ImplantTerminalMechControl1Test extends ActorTest() {
|
|||
class ImplantTerminalMechControl2Test extends ActorTest() {
|
||||
"ImplantTerminalMechControl" should {
|
||||
"let a player mount" in {
|
||||
val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val obj = ImplantTerminalMech(GlobalDefinitions.implant_terminal_mech)
|
||||
obj.Actor = system.actorOf(Props(classOf[ImplantTerminalMechControl], obj), "mech")
|
||||
val (player, mech) = ImplantTerminalMechTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
val msg = Mountable.TryMount(player, 0)
|
||||
|
||||
obj.Actor ! msg
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
mech.Actor ! msg
|
||||
val reply = receiveOne(Duration.create(200, "ms"))
|
||||
assert(reply.isInstanceOf[Mountable.MountMessages])
|
||||
val reply2 = reply.asInstanceOf[Mountable.MountMessages]
|
||||
assert(reply2.player == player)
|
||||
assert(reply2.response.isInstanceOf[Mountable.CanMount])
|
||||
val reply3 = reply2.response.asInstanceOf[Mountable.CanMount]
|
||||
assert(reply3.obj == obj)
|
||||
assert(reply3.obj == mech)
|
||||
assert(reply3.seat_num == 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ImplantTerminalMechControl3Test extends ActorTest() {
|
||||
import net.psforever.types.CharacterGender
|
||||
"ImplantTerminalMechControl" should {
|
||||
"block a player from mounting" in {
|
||||
val player1 = Player("test1", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val (player1, mech) = ImplantTerminalMechTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
val player2 = Player("test2", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val obj = ImplantTerminalMech(GlobalDefinitions.implant_terminal_mech)
|
||||
obj.Actor = system.actorOf(Props(classOf[ImplantTerminalMechControl], obj), "mech")
|
||||
obj.Actor ! Mountable.TryMount(player1, 0)
|
||||
|
||||
mech.Actor ! Mountable.TryMount(player1, 0)
|
||||
receiveOne(Duration.create(100, "ms")) //consume reply
|
||||
|
||||
obj.Actor ! Mountable.TryMount(player2, 0)
|
||||
mech.Actor ! Mountable.TryMount(player2, 0)
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
assert(reply.isInstanceOf[Mountable.MountMessages])
|
||||
val reply2 = reply.asInstanceOf[Mountable.MountMessages]
|
||||
assert(reply2.player == player2)
|
||||
assert(reply2.response.isInstanceOf[Mountable.CanNotMount])
|
||||
val reply3 = reply2.response.asInstanceOf[Mountable.CanNotMount]
|
||||
assert(reply3.obj == obj)
|
||||
assert(reply3.obj == mech)
|
||||
assert(reply3.seat_num == 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ImplantTerminalMechControl4Test extends ActorTest() {
|
||||
"ImplantTerminalMechControl" should {
|
||||
"dismount player after mounting" in {
|
||||
val (player, mech) = ImplantTerminalMechTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
mech.Actor ! Mountable.TryMount(player, 0)
|
||||
receiveOne(Duration.create(100, "ms")) //consume reply
|
||||
assert(mech.Seat(0).get.isOccupied)
|
||||
|
||||
mech.Actor ! Mountable.TryDismount(player, 0)
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
assert(reply.isInstanceOf[Mountable.MountMessages])
|
||||
val reply2 = reply.asInstanceOf[Mountable.MountMessages]
|
||||
assert(reply2.player == player)
|
||||
assert(reply2.response.isInstanceOf[Mountable.CanDismount])
|
||||
val reply3 = reply2.response.asInstanceOf[Mountable.CanDismount]
|
||||
assert(reply3.obj == mech)
|
||||
assert(reply3.seat_num == 0)
|
||||
assert(!mech.Seat(0).get.isOccupied)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ImplantTerminalMechControl5Test extends ActorTest() {
|
||||
"ImplantTerminalMechControl" should {
|
||||
"block a player from dismounting" in {
|
||||
val (player, mech) = ImplantTerminalMechTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
mech.Actor ! Mountable.TryMount(player, 0)
|
||||
receiveOne(Duration.create(100, "ms")) //consume reply
|
||||
assert(mech.Seat(0).get.isOccupied)
|
||||
|
||||
mech.Velocity = Vector3(1,0,0) //makes no sense, but it works as the "seat" is not bailable
|
||||
mech.Actor ! Mountable.TryDismount(player, 0)
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
assert(reply.isInstanceOf[Mountable.MountMessages])
|
||||
val reply2 = reply.asInstanceOf[Mountable.MountMessages]
|
||||
assert(reply2.player == player)
|
||||
assert(reply2.response.isInstanceOf[Mountable.CanNotDismount])
|
||||
val reply3 = reply2.response.asInstanceOf[Mountable.CanNotDismount]
|
||||
assert(reply3.obj == mech)
|
||||
assert(reply3.seat_num == 0)
|
||||
assert(mech.Seat(0).get.isOccupied)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object ImplantTerminalMechTest {
|
||||
def SetUpAgents(faction : PlanetSideEmpire.Value)(implicit system : ActorSystem) : (Player, ImplantTerminalMech) = {
|
||||
import net.psforever.objects.serverobject.structures.Building
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
|
||||
val terminal = ImplantTerminalMech(GlobalDefinitions.implant_terminal_mech)
|
||||
terminal.Actor = system.actorOf(Props(classOf[ImplantTerminalMechControl], terminal), "mech")
|
||||
terminal.Owner = new Building(0, Zone.Nowhere)
|
||||
terminal.Owner.Faction = faction
|
||||
terminal.GUID = PlanetSideGUID(1)
|
||||
(Player("test", faction, CharacterGender.Male, 0, 0), terminal)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
package objects.terminal
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import net.psforever.objects.serverobject.structures.Building
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.objects.{AmmoBox, GlobalDefinitions, Player, Tool}
|
||||
import net.psforever.packet.game.{ItemTransactionMessage, PlanetSideGUID}
|
||||
import net.psforever.types._
|
||||
|
|
@ -11,6 +13,9 @@ import org.specs2.mutable.Specification
|
|||
class OrderTerminalTest extends Specification {
|
||||
"Order_Terminal" should {
|
||||
val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val terminal = Terminal(GlobalDefinitions.order_terminal)
|
||||
terminal.Owner = new Building(0, Zone.Nowhere)
|
||||
terminal.Owner.Faction = PlanetSideEmpire.TR
|
||||
|
||||
"construct" in {
|
||||
val terminal = Terminal(GlobalDefinitions.order_terminal)
|
||||
|
|
@ -18,7 +23,6 @@ class OrderTerminalTest extends Specification {
|
|||
}
|
||||
|
||||
"player can buy a box of ammunition ('9mmbullet_AP')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.order_terminal)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "9mmbullet_AP", 0, PlanetSideGUID(0))
|
||||
val reply = terminal.Request(player, msg)
|
||||
reply.isInstanceOf[Terminal.BuyEquipment] mustEqual true
|
||||
|
|
@ -29,7 +33,6 @@ class OrderTerminalTest extends Specification {
|
|||
}
|
||||
|
||||
"player can buy a weapon ('suppressor')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.order_terminal)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "suppressor", 0, PlanetSideGUID(0))
|
||||
val reply = terminal.Request(player, msg)
|
||||
reply.isInstanceOf[Terminal.BuyEquipment] mustEqual true
|
||||
|
|
@ -39,7 +42,6 @@ class OrderTerminalTest extends Specification {
|
|||
}
|
||||
|
||||
"player can buy a box of vehicle ammunition ('105mmbullet')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.order_terminal)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 3, "105mmbullet", 0, PlanetSideGUID(0))
|
||||
val reply = terminal.Request(player, msg)
|
||||
reply.isInstanceOf[Terminal.BuyEquipment] mustEqual true
|
||||
|
|
@ -50,7 +52,6 @@ class OrderTerminalTest extends Specification {
|
|||
}
|
||||
|
||||
"player can buy a support tool ('bank')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.order_terminal)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 2, "bank", 0, PlanetSideGUID(0))
|
||||
val reply = terminal.Request(player, msg)
|
||||
reply.isInstanceOf[Terminal.BuyEquipment] mustEqual true
|
||||
|
|
@ -60,14 +61,12 @@ class OrderTerminalTest extends Specification {
|
|||
}
|
||||
|
||||
"player can buy different armor ('lite_armor')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.order_terminal)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 1, "lite_armor", 0, PlanetSideGUID(0))
|
||||
|
||||
terminal.Request(player, msg) mustEqual Terminal.BuyExosuit(ExoSuitType.Agile)
|
||||
}
|
||||
|
||||
"player can not buy fake equipment ('sabot')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.order_terminal)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "sabot", 0, PlanetSideGUID(0))
|
||||
|
||||
terminal.Request(player, msg) mustEqual Terminal.NoDeal()
|
||||
|
|
@ -76,7 +75,6 @@ class OrderTerminalTest extends Specification {
|
|||
//TODO loudout tests
|
||||
|
||||
"player can not buy equipment from the wrong page ('9mmbullet_AP', page 1)" in {
|
||||
val terminal = Terminal(GlobalDefinitions.order_terminal)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 1, "9mmbullet_AP", 0, PlanetSideGUID(0))
|
||||
|
||||
terminal.Request(player, msg) mustEqual Terminal.NoDeal()
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.terminal
|
||||
|
||||
import akka.actor.Props
|
||||
import net.psforever.objects.serverobject.terminals.{Terminal, TerminalControl}
|
||||
import akka.actor.{ActorSystem, Props}
|
||||
import net.psforever.objects.serverobject.structures.Building
|
||||
import net.psforever.objects.serverobject.terminals.{Terminal, TerminalControl, TerminalDefinition}
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.objects.{GlobalDefinitions, Player}
|
||||
import net.psforever.packet.game.{ItemTransactionMessage, PlanetSideGUID}
|
||||
import net.psforever.types._
|
||||
|
|
@ -21,8 +23,7 @@ class TerminalControl1Test extends ActorTest() {
|
|||
|
||||
class TerminalControl2Test extends ActorTest() {
|
||||
"TerminalControl can not process wrong messages" in {
|
||||
val terminal = Terminal(GlobalDefinitions.cert_terminal)
|
||||
terminal.Actor = system.actorOf(Props(classOf[TerminalControl], terminal), "test-cert-term")
|
||||
val (_, terminal) = TerminalControlTest.SetUpAgents(GlobalDefinitions.cert_terminal, PlanetSideEmpire.TR)
|
||||
|
||||
terminal.Actor !"hello"
|
||||
val reply = receiveOne(Duration.create(500, "ms"))
|
||||
|
|
@ -34,9 +35,7 @@ class TerminalControl2Test extends ActorTest() {
|
|||
//test for Cert_Terminal messages (see CertTerminalTest)
|
||||
class CertTerminalControl1Test extends ActorTest() {
|
||||
"TerminalControl can be used to learn a certification ('medium_assault')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.cert_terminal)
|
||||
terminal.Actor = system.actorOf(Props(classOf[TerminalControl], terminal), "test-cert-term")
|
||||
val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val (player, terminal) = TerminalControlTest.SetUpAgents(GlobalDefinitions.cert_terminal, PlanetSideEmpire.TR)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Learn, 0, "medium_assault", 0, PlanetSideGUID(0))
|
||||
|
||||
terminal.Actor ! Terminal.Request(player, msg)
|
||||
|
|
@ -51,9 +50,7 @@ class CertTerminalControl1Test extends ActorTest() {
|
|||
|
||||
class CertTerminalControl2Test extends ActorTest() {
|
||||
"TerminalControl can be used to warn about not learning a fake certification ('juggling')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.cert_terminal)
|
||||
terminal.Actor = system.actorOf(Props(classOf[TerminalControl], terminal), "test-cert-term")
|
||||
val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val (player, terminal) = TerminalControlTest.SetUpAgents(GlobalDefinitions.cert_terminal, PlanetSideEmpire.TR)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Learn, 0, "juggling", 0, PlanetSideGUID(0))
|
||||
|
||||
terminal.Actor ! Terminal.Request(player, msg)
|
||||
|
|
@ -68,9 +65,7 @@ class CertTerminalControl2Test extends ActorTest() {
|
|||
|
||||
class CertTerminalControl3Test extends ActorTest() {
|
||||
"TerminalControl can be used to forget a certification ('medium_assault')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.cert_terminal)
|
||||
terminal.Actor = system.actorOf(Props(classOf[TerminalControl], terminal), "test-cert-term")
|
||||
val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val (player, terminal) = TerminalControlTest.SetUpAgents(GlobalDefinitions.cert_terminal, PlanetSideEmpire.TR)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Sell, 0, "medium_assault", 0, PlanetSideGUID(0))
|
||||
|
||||
terminal.Actor ! Terminal.Request(player, msg)
|
||||
|
|
@ -85,9 +80,7 @@ class CertTerminalControl3Test extends ActorTest() {
|
|||
|
||||
class VehicleTerminalControl1Test extends ActorTest() {
|
||||
"TerminalControl can be used to buy a vehicle ('two_man_assault_buggy')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.ground_vehicle_terminal)
|
||||
terminal.Actor = system.actorOf(Props(classOf[TerminalControl], terminal), "test-cert-term")
|
||||
val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val (player, terminal) = TerminalControlTest.SetUpAgents(GlobalDefinitions.ground_vehicle_terminal, PlanetSideEmpire.TR)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "two_man_assault_buggy", 0, PlanetSideGUID(0))
|
||||
|
||||
terminal.Actor ! Terminal.Request(player, msg)
|
||||
|
|
@ -112,9 +105,7 @@ class VehicleTerminalControl1Test extends ActorTest() {
|
|||
|
||||
class VehicleTerminalControl2Test extends ActorTest() {
|
||||
"TerminalControl can be used to warn about not buy a vehicle ('harasser')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.ground_vehicle_terminal)
|
||||
terminal.Actor = system.actorOf(Props(classOf[TerminalControl], terminal), "test-cert-term")
|
||||
val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val (player, terminal) = TerminalControlTest.SetUpAgents(GlobalDefinitions.ground_vehicle_terminal, PlanetSideEmpire.TR)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "harasser", 0, PlanetSideGUID(0))
|
||||
|
||||
terminal.Actor ! Terminal.Request(player, msg)
|
||||
|
|
@ -126,3 +117,13 @@ class VehicleTerminalControl2Test extends ActorTest() {
|
|||
assert(reply2.response == Terminal.NoDeal())
|
||||
}
|
||||
}
|
||||
|
||||
object TerminalControlTest {
|
||||
def SetUpAgents(tdef : TerminalDefinition, faction : PlanetSideEmpire.Value)(implicit system : ActorSystem) : (Player, Terminal) = {
|
||||
val terminal = Terminal(tdef)
|
||||
terminal.Actor = system.actorOf(Props(classOf[TerminalControl], terminal), "test-term")
|
||||
terminal.Owner = new Building(0, Zone.Nowhere)
|
||||
terminal.Owner.Faction = faction
|
||||
(Player("test", faction, CharacterGender.Male, 0, 0), terminal)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,10 @@
|
|||
package objects.terminal
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import net.psforever.objects.serverobject.structures.Building
|
||||
import net.psforever.objects.{GlobalDefinitions, Player}
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.game.{ItemTransactionMessage, PlanetSideGUID}
|
||||
import net.psforever.types.{CharacterGender, PlanetSideEmpire, TransactionType}
|
||||
import org.specs2.mutable.Specification
|
||||
|
|
@ -11,6 +13,9 @@ import org.specs2.mutable.Specification
|
|||
class VehicleTerminalCombinedTest extends Specification {
|
||||
"Ground_Vehicle_Terminal" should {
|
||||
val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
|
||||
val terminal = Terminal(GlobalDefinitions.vehicle_terminal_combined)
|
||||
terminal.Owner = new Building(0, Zone.Nowhere)
|
||||
terminal.Owner.Faction = PlanetSideEmpire.TR
|
||||
|
||||
"construct" in {
|
||||
val terminal = Terminal(GlobalDefinitions.vehicle_terminal_combined)
|
||||
|
|
@ -18,8 +23,8 @@ class VehicleTerminalCombinedTest extends Specification {
|
|||
}
|
||||
|
||||
"player can buy a ground vehicle, the harasser ('two_man_assault_buggy')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.vehicle_terminal_combined)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "two_man_assault_buggy", 0, PlanetSideGUID(0))
|
||||
|
||||
val reply = terminal.Request(player, msg)
|
||||
reply.isInstanceOf[Terminal.BuyVehicle] mustEqual true
|
||||
val reply2 = reply.asInstanceOf[Terminal.BuyVehicle]
|
||||
|
|
@ -35,8 +40,8 @@ class VehicleTerminalCombinedTest extends Specification {
|
|||
}
|
||||
|
||||
"player can buy a flying vehicle, the reaver ('lightgunship')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.vehicle_terminal_combined)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "lightgunship", 0, PlanetSideGUID(0))
|
||||
|
||||
val reply = terminal.Request(player, msg)
|
||||
reply.isInstanceOf[Terminal.BuyVehicle] mustEqual true
|
||||
val reply2 = reply.asInstanceOf[Terminal.BuyVehicle]
|
||||
|
|
@ -52,7 +57,6 @@ class VehicleTerminalCombinedTest extends Specification {
|
|||
}
|
||||
|
||||
"player can not buy a fake vehicle ('harasser')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.vehicle_terminal_combined)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "harasser", 0, PlanetSideGUID(0))
|
||||
|
||||
terminal.Request(player, msg) mustEqual Terminal.NoDeal()
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import net.psforever.objects.serverobject.implantmech.ImplantTerminalMech
|
|||
import net.psforever.objects.serverobject.locks.IFFLock
|
||||
import net.psforever.objects.serverobject.mblocker.Locker
|
||||
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
|
||||
import net.psforever.objects.serverobject.structures.{Building, FoundationBuilder}
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
import net.psforever.types.Vector3
|
||||
|
||||
|
|
@ -103,30 +104,46 @@ object Maps {
|
|||
VehicleSpawnPad.Constructor(Vector3(3508.9844f, 2895.961f, 92.296875f), Vector3(0f, 0f, 270.0f))
|
||||
)) //TODO guid not correct
|
||||
|
||||
LocalBases = 30
|
||||
LocalBuilding(2, FoundationBuilder(Building.Structure))
|
||||
ObjectToBuilding(186, 2)
|
||||
ObjectToBuilding(187, 2)
|
||||
ObjectToBuilding(188, 2)
|
||||
ObjectToBuilding(522, 2)
|
||||
ObjectToBuilding(523, 2)
|
||||
ObjectToBuilding(524, 2)
|
||||
ObjectToBuilding(525, 2)
|
||||
ObjectToBuilding(526, 2)
|
||||
ObjectToBuilding(527, 2)
|
||||
ObjectToBuilding(528, 2)
|
||||
ObjectToBuilding(529, 2)
|
||||
ObjectToBuilding(686, 2)
|
||||
ObjectToBuilding(687, 2)
|
||||
ObjectToBuilding(688, 2)
|
||||
ObjectToBuilding(689, 2)
|
||||
ObjectToBuilding(690, 2)
|
||||
ObjectToBuilding(691, 2)
|
||||
ObjectToBuilding(692, 2)
|
||||
ObjectToBuilding(693, 2)
|
||||
ObjectToBuilding(842, 2)
|
||||
ObjectToBuilding(843, 2)
|
||||
ObjectToBuilding(844, 2)
|
||||
ObjectToBuilding(845, 2)
|
||||
ObjectToBuilding(853, 2) //TODO check building_id
|
||||
ObjectToBuilding(855, 2) //TODO check building_id
|
||||
ObjectToBuilding(860, 2) //TODO check building_id
|
||||
ObjectToBuilding(1063, 2) //TODO unowned courtyard terminal?
|
||||
ObjectToBuilding(500, 2) //TODO unowned courtyard spawnpad?
|
||||
ObjectToBuilding(304, 2) //TODO unowned courtyard terminal?
|
||||
ObjectToBuilding(501, 2) //TODO unowned courtyard spawnpad?
|
||||
|
||||
ObjectToBase(330, 29)
|
||||
ObjectToBase(331, 29)
|
||||
ObjectToBase(332, 29)
|
||||
ObjectToBase(333, 29)
|
||||
//ObjectToBase(520, 29)
|
||||
ObjectToBase(522, 2)
|
||||
ObjectToBase(523, 2)
|
||||
ObjectToBase(524, 2)
|
||||
ObjectToBase(525, 2)
|
||||
ObjectToBase(526, 2)
|
||||
ObjectToBase(527, 2)
|
||||
ObjectToBase(528, 2)
|
||||
ObjectToBase(529, 2)
|
||||
ObjectToBase(556, 29)
|
||||
ObjectToBase(557, 29)
|
||||
ObjectToBase(558, 29)
|
||||
ObjectToBase(559, 29)
|
||||
ObjectToBase(1081, 2)
|
||||
ObjectToBase(1063, 2) //TODO unowned courtyard terminal?
|
||||
ObjectToBase(500, 2) //TODO unowned courtyard spawnpad?
|
||||
ObjectToBase(304, 2) //TODO unowned courtyard terminal?
|
||||
ObjectToBase(501, 2) //TODO unowned courtyard spawnpad?
|
||||
LocalBuilding(29, FoundationBuilder(Building.Structure))
|
||||
ObjectToBuilding(330, 29)
|
||||
ObjectToBuilding(332, 29)
|
||||
ObjectToBuilding(556, 29)
|
||||
ObjectToBuilding(558, 29)
|
||||
|
||||
//ObjectToBuilding(1081, ?)
|
||||
//ObjectToBuilding(520, ?)
|
||||
|
||||
DoorToLock(330, 558)
|
||||
DoorToLock(331, 559)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ import net.psforever.objects._
|
|||
import net.psforever.objects.equipment._
|
||||
import net.psforever.objects.guid.{GUIDTask, Task, TaskResolver}
|
||||
import net.psforever.objects.inventory.{Container, GridInventory, InventoryItem}
|
||||
import net.psforever.objects.mount.Mountable
|
||||
import net.psforever.objects.serverobject.mount.Mountable
|
||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||
import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject}
|
||||
import net.psforever.objects.serverobject.doors.Door
|
||||
import net.psforever.objects.serverobject.implantmech.ImplantTerminalMech
|
||||
|
|
@ -424,7 +425,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
val player_guid : PlanetSideGUID = tplayer.GUID
|
||||
val obj_guid : PlanetSideGUID = obj.GUID
|
||||
log.info(s"MountVehicleMsg: $player_guid mounts $obj @ $seat_num")
|
||||
tplayer.VehicleSeated = Some(obj_guid)
|
||||
//tplayer.VehicleSeated = Some(obj_guid)
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, PlanetsideAttributeMessage(obj_guid, 0, 1000L))) //health of mech
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ObjectAttachMessage(obj_guid, player_guid, seat_num)))
|
||||
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.MountVehicle(player_guid, obj_guid, seat_num))
|
||||
|
|
@ -434,7 +435,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
val player_guid : PlanetSideGUID = tplayer.GUID
|
||||
log.info(s"MountVehicleMsg: $player_guid mounts $obj_guid @ $seat_num")
|
||||
vehicleService ! VehicleServiceMessage.UnscheduleDeconstruction(obj_guid) //clear all deconstruction timers
|
||||
tplayer.VehicleSeated = Some(obj_guid)
|
||||
//tplayer.VehicleSeated = Some(obj_guid)
|
||||
if(seat_num == 0) { //simplistic vehicle ownership management
|
||||
obj.Owner match {
|
||||
case Some(owner_guid) =>
|
||||
|
|
@ -466,8 +467,37 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case Mountable.CanMount(obj : Mountable, _) =>
|
||||
log.warn(s"MountVehicleMsg: $obj is some generic mountable object and nothing will happen")
|
||||
|
||||
case Mountable.CanDismount(obj : ImplantTerminalMech, seat_num) =>
|
||||
val obj_guid : PlanetSideGUID = obj.GUID
|
||||
val player_guid : PlanetSideGUID = tplayer.GUID
|
||||
log.info(s"DismountVehicleMsg: $player_guid dismounts $obj @ $seat_num")
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, DismountVehicleMsg(player_guid, seat_num, false)))
|
||||
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.DismountVehicle(player_guid, seat_num, false))
|
||||
|
||||
case Mountable.CanDismount(obj : Vehicle, seat_num) =>
|
||||
val player_guid : PlanetSideGUID = tplayer.GUID
|
||||
if(player_guid == player.GUID) {
|
||||
//disembarking self
|
||||
log.info(s"DismountVehicleMsg: $player_guid dismounts $obj @ $seat_num")
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, DismountVehicleMsg(player_guid, seat_num, false)))
|
||||
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.DismountVehicle(player_guid, seat_num, false))
|
||||
UnAccessContents(obj)
|
||||
}
|
||||
else {
|
||||
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.KickPassenger(player_guid, seat_num, true, obj.GUID))
|
||||
}
|
||||
if(obj.Seats.values.count(seat => seat.isOccupied) == 0) {
|
||||
vehicleService ! VehicleServiceMessage.DelayedVehicleDeconstruction(obj, continent, 600L) //start vehicle decay (10m)
|
||||
}
|
||||
|
||||
case Mountable.CanDismount(obj : Mountable, _) =>
|
||||
log.warn(s"DismountVehicleMsg: $obj is some generic mountable object and nothing will happen")
|
||||
|
||||
case Mountable.CanNotMount(obj, seat_num) =>
|
||||
log.warn(s"MountVehicleMsg: $tplayer attempted to mount $obj's seat $seat_num, but was not allowed")
|
||||
|
||||
case Mountable.CanNotDismount(obj, seat_num) =>
|
||||
log.warn(s"DismountVehicleMsg: $tplayer attempted to dismount $obj's seat $seat_num, but was not allowed")
|
||||
}
|
||||
|
||||
case Terminal.TerminalMessage(tplayer, msg, order) =>
|
||||
|
|
@ -961,11 +991,10 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
log.info("Load the now-registered player")
|
||||
//load the now-registered player
|
||||
tplayer.Spawn
|
||||
sendResponse(PacketCoding.CreateGamePacket(0,
|
||||
ObjectCreateDetailedMessage(ObjectClass.avatar, tplayer.GUID, tplayer.Definition.Packet.DetailedConstructorData(tplayer).get)
|
||||
))
|
||||
val dcdata = tplayer.Definition.Packet.DetailedConstructorData(tplayer).get
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ObjectCreateDetailedMessage(ObjectClass.avatar, tplayer.GUID, dcdata)))
|
||||
avatarService ! AvatarServiceMessage(tplayer.Continent, AvatarAction.LoadPlayer(tplayer.GUID, tplayer.Definition.Packet.ConstructorData(tplayer).get))
|
||||
log.debug(s"ObjectCreateDetailedMessage: ${tplayer.Definition.Packet.DetailedConstructorData(tplayer).get}")
|
||||
log.debug(s"ObjectCreateDetailedMessage: $dcdata")
|
||||
|
||||
case SetCurrentAvatar(tplayer) =>
|
||||
val guid = tplayer.GUID
|
||||
|
|
@ -1823,52 +1852,49 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
// TODO: Not all incoming UseItemMessage's respond with another UseItemMessage (i.e. doors only send out GenericObjectStateMsg)
|
||||
continent.GUID(object_guid) match {
|
||||
case Some(door : Door) =>
|
||||
continent.Map.DoorToLock.get(object_guid.guid) match { //check for IFF Lock
|
||||
case Some(lock_guid) =>
|
||||
val lock_hacked = continent.GUID(lock_guid).get.asInstanceOf[IFFLock].HackedBy match {
|
||||
case Some(_) =>
|
||||
true
|
||||
case None =>
|
||||
Vector3.ScalarProjection(door.Outwards, player.Position - door.Position) < 0f
|
||||
}
|
||||
continent.Map.ObjectToBase.get(lock_guid) match { //check for associated base
|
||||
case Some(base_id) =>
|
||||
if(continent.Base(base_id).get.Faction == player.Faction || lock_hacked) { //either base allegiance aligns or locks is hacked
|
||||
door.Actor ! Door.Use(player, msg)
|
||||
}
|
||||
case None =>
|
||||
if(lock_hacked) { //is lock hacked? this may be a weird case
|
||||
door.Actor ! Door.Use(player, msg)
|
||||
}
|
||||
}
|
||||
case None =>
|
||||
door.Actor ! Door.Use(player, msg) //let door open freely
|
||||
if(player.Faction == door.Faction || ((continent.Map.DoorToLock.get(object_guid.guid) match {
|
||||
case Some(lock_guid) => continent.GUID(lock_guid).get.asInstanceOf[IFFLock].HackedBy.isDefined
|
||||
case None => !door.isOpen
|
||||
}) || Vector3.ScalarProjection(door.Outwards, player.Position - door.Position) < 0f)) {
|
||||
door.Actor ! Door.Use(player, msg)
|
||||
}
|
||||
else if(door.isOpen) {
|
||||
//the door is open globally ... except on our screen
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, GenericObjectStateMsg(object_guid, 16)))
|
||||
}
|
||||
|
||||
case Some(panel : IFFLock) =>
|
||||
player.Slot(player.DrawnSlot).Equipment match {
|
||||
case Some(tool : SimpleItem) =>
|
||||
if(tool.Definition == GlobalDefinitions.remote_electronics_kit) {
|
||||
//TODO get player hack level (for now, presume 15s in intervals of 4/s)
|
||||
progressBarValue = Some(-2.66f)
|
||||
self ! WorldSessionActor.ItemHacking(player, panel, tool.GUID, 2.66f, FinishHackingDoor(panel, 1114636288L))
|
||||
log.info("Hacking a door~")
|
||||
}
|
||||
case _ => ;
|
||||
if(panel.Faction != player.Faction && panel.HackedBy.isEmpty) {
|
||||
player.Slot(player.DrawnSlot).Equipment match {
|
||||
case Some(tool : SimpleItem) =>
|
||||
if(tool.Definition == GlobalDefinitions.remote_electronics_kit) {
|
||||
//TODO get player hack level (for now, presume 15s in intervals of 4/s)
|
||||
progressBarValue = Some(-2.66f)
|
||||
self ! WorldSessionActor.ItemHacking(player, panel, tool.GUID, 2.66f, FinishHackingDoor(panel, 1114636288L))
|
||||
log.info("Hacking a door~")
|
||||
}
|
||||
case _ => ;
|
||||
}
|
||||
}
|
||||
|
||||
case Some(obj : Locker) =>
|
||||
val container = player.Locker
|
||||
accessedContainer = Some(container)
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, UseItemMessage(avatar_guid, unk1, container.GUID, unk2, unk3, unk4, unk5, unk6, unk7, unk8, 456)))
|
||||
if(player.Faction == obj.Faction) {
|
||||
log.info(s"UseItem: $player accessing a locker")
|
||||
val container = player.Locker
|
||||
accessedContainer = Some(container)
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, UseItemMessage(avatar_guid, unk1, container.GUID, unk2, unk3, unk4, unk5, unk6, unk7, unk8, 456)))
|
||||
}
|
||||
else {
|
||||
log.info(s"UseItem: not $player's locker")
|
||||
}
|
||||
|
||||
case Some(obj : Vehicle) =>
|
||||
if(obj.Faction == player.Faction) {
|
||||
val equipment = player.Slot(player.DrawnSlot).Equipment
|
||||
val equipment = player.Slot(player.DrawnSlot).Equipment
|
||||
if(player.Faction == obj.Faction) {
|
||||
if(equipment match {
|
||||
case Some(tool : Tool) =>
|
||||
tool.Definition match {
|
||||
case GlobalDefinitions.nano_dispenser | GlobalDefinitions.remote_electronics_kit => false
|
||||
case GlobalDefinitions.nano_dispenser => false
|
||||
case _ => true
|
||||
}
|
||||
case _ => true
|
||||
|
|
@ -1889,13 +1915,19 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case GlobalDefinitions.nano_dispenser =>
|
||||
//TODO repairing behavior
|
||||
|
||||
case GlobalDefinitions.remote_electronics_kit =>
|
||||
//TODO hacking behavior
|
||||
|
||||
case _ => ;
|
||||
}
|
||||
}
|
||||
}
|
||||
//enemy player interactions
|
||||
else if(equipment.isDefined) {
|
||||
equipment.get.Definition match {
|
||||
case GlobalDefinitions.remote_electronics_kit =>
|
||||
//TODO hacking behavior
|
||||
|
||||
case _ => ;
|
||||
}
|
||||
}
|
||||
|
||||
case Some(obj : PlanetSideGameObject) =>
|
||||
if(itemType != 121) {
|
||||
|
|
@ -1933,7 +1965,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
log.info("ItemTransaction: " + msg)
|
||||
continent.GUID(terminal_guid) match {
|
||||
case Some(term : Terminal) =>
|
||||
term.Actor ! Terminal.Request(player, msg)
|
||||
if(player.Faction == term.Faction) {
|
||||
term.Actor ! Terminal.Request(player, msg)
|
||||
}
|
||||
case Some(obj : PlanetSideGameObject) => ;
|
||||
case None => ;
|
||||
}
|
||||
|
|
@ -2015,36 +2049,19 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case msg @ DismountVehicleMsg(player_guid, unk1, unk2) =>
|
||||
//TODO optimize this later
|
||||
log.info(s"DismountVehicleMsg: $msg")
|
||||
//common warning for this section
|
||||
def dismountWarning(msg : String) : Unit = {
|
||||
log.warn(s"$msg; some vehicle might not know that a player is no longer sitting in it")
|
||||
}
|
||||
if(player.GUID == player_guid) {
|
||||
//normally disembarking from a seat
|
||||
val previouslySeated = player.VehicleSeated
|
||||
player.VehicleSeated = None
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, DismountVehicleMsg(player_guid, unk1, unk2)))
|
||||
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.DismountVehicle(player_guid, unk1, unk2))
|
||||
//common warning for this section
|
||||
def dismountWarning(msg : String) : Unit = {
|
||||
log.warn(s"$msg; some vehicle might not know that a player is no longer sitting in it")
|
||||
}
|
||||
//find vehicle seat and disembark it
|
||||
previouslySeated match {
|
||||
player.VehicleSeated match {
|
||||
case Some(obj_guid) =>
|
||||
continent.GUID(obj_guid) match {
|
||||
case Some(obj : Mountable) =>
|
||||
val seats = obj.Seats.values
|
||||
seats.find(seat => seat.Occupant.contains(player)) match {
|
||||
case Some(seat) =>
|
||||
if(seat.Bailable || obj.Velocity.isEmpty || Vector3.MagnitudeSquared(obj.Velocity.get).toInt == 0) { //ugh, float comparison
|
||||
seat.Occupant = None
|
||||
//special actions
|
||||
obj match {
|
||||
case (veh : Vehicle) =>
|
||||
if(seats.count(seat => seat.isOccupied) == 0) {
|
||||
vehicleService ! VehicleServiceMessage.DelayedVehicleDeconstruction(veh, continent, 600L) //start vehicle decay (10m)
|
||||
UnAccessContents(veh)
|
||||
}
|
||||
case _ => ;
|
||||
}
|
||||
}
|
||||
obj.PassengerInSeat(player) match {
|
||||
case Some(seat_num : Int) =>
|
||||
obj.Actor ! Mountable.TryDismount(player, seat_num)
|
||||
case None =>
|
||||
dismountWarning(s"DismountVehicleMsg: can not find where player $player_guid is seated in mountable $obj_guid")
|
||||
}
|
||||
|
|
@ -2056,35 +2073,23 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
}
|
||||
else {
|
||||
//kicking someone else out of a seat; need to own that seat
|
||||
//kicking someone else out of a seat; need to own that seat/mountable
|
||||
player.VehicleOwned match {
|
||||
case Some(vehicle_guid) =>
|
||||
continent.GUID(player_guid) match {
|
||||
case Some(tplayer : Player) =>
|
||||
if(tplayer.VehicleSeated.contains(vehicle_guid)) {
|
||||
continent.GUID(vehicle_guid) match {
|
||||
case Some(obj : Vehicle) =>
|
||||
val seats = obj.Seats.values
|
||||
seats.find(seat => seat.Occupant.contains(tplayer)) match {
|
||||
case Some(seat) =>
|
||||
seat.Occupant = None
|
||||
tplayer.VehicleSeated = None
|
||||
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.KickPassenger(player_guid, unk1, unk2, vehicle_guid))
|
||||
if(seats.count(seat => seat.isOccupied) == 0) {
|
||||
vehicleService ! VehicleServiceMessage.DelayedVehicleDeconstruction(obj, continent, 600L) //start vehicle decay (10m)
|
||||
}
|
||||
case None =>
|
||||
log.warn(s"DismountVehicleMsg: can not find where player $player_guid is seated in vehicle $vehicle_guid")
|
||||
}
|
||||
case _ =>
|
||||
log.warn(s"DismountVehicleMsg: can not find vehicle $vehicle_guid")
|
||||
}
|
||||
case Some(obj_guid) =>
|
||||
(continent.GUID(obj_guid), continent.GUID(player_guid)) match {
|
||||
case (Some(obj : Mountable), Some(tplayer : Player)) =>
|
||||
obj.PassengerInSeat(tplayer) match {
|
||||
case Some(seat_num : Int) =>
|
||||
obj.Actor ! Mountable.TryDismount(tplayer, seat_num)
|
||||
case None =>
|
||||
dismountWarning(s"DismountVehicleMsg: can not find where other player $player_guid is seated in mountable $obj_guid")
|
||||
}
|
||||
else {
|
||||
log.warn(s"DismountVehicleMsg: non-owner player $player trying to kick player $tplayer out of his seat")
|
||||
}
|
||||
case _ =>
|
||||
case (None, _) => ;
|
||||
log.warn(s"DismountVehicleMsg: $player can not find his vehicle")
|
||||
case (_, None) => ;
|
||||
log.warn(s"DismountVehicleMsg: player $player_guid could not be found to kick")
|
||||
case _ =>
|
||||
log.warn(s"DismountVehicleMsg: object is either not a Mountable or not a Player")
|
||||
}
|
||||
case None =>
|
||||
log.warn(s"DismountVehicleMsg: $player does not own a vehicle")
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ object Zones {
|
|||
super.Init(context)
|
||||
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
Base(2).get.Faction = PlanetSideEmpire.VS //HART building C
|
||||
Base(29).get.Faction = PlanetSideEmpire.NC //South Villa Gun Tower
|
||||
Building(2).get.Faction = PlanetSideEmpire.VS //HART building C
|
||||
Building(29).get.Faction = PlanetSideEmpire.NC //South Villa Gun Tower
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ class DeconstructionActor extends Actor {
|
|||
case DeconstructionActor.RequestDeleteVehicle(vehicle, zone, time) =>
|
||||
vehicles = vehicles :+ DeconstructionActor.VehicleEntry(vehicle, zone, time)
|
||||
vehicle.Actor ! Vehicle.PrepareForDeletion
|
||||
//kick everyone out
|
||||
//kick everyone out; this is a no-blocking manual form of MountableBehavior ! Mountable.TryDismount
|
||||
vehicle.Definition.MountPoints.values.foreach(seat_num => {
|
||||
val zone_id : String = zone.Id
|
||||
val seat : Seat = vehicle.Seat(seat_num).get
|
||||
|
|
|
|||
Loading…
Reference in a new issue