mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-29 06:41:00 +00:00
Reorganized vehicle spawning process and wrote tests for process.
This commit is contained in:
parent
c87273c351
commit
5d5c609a2f
|
|
@ -49,97 +49,85 @@ class VehicleSpawnControl(pad : VehicleSpawnPad) extends VehicleSpawnControlBase
|
|||
trace(s"order from $player for $vehicle received")
|
||||
orders = orders :+ VehicleSpawnControl.Order(player, vehicle, sender)
|
||||
if(trackedOrder.isEmpty && orders.length == 1) {
|
||||
self ! VehicleSpawnControl.ProcessControl.GetOrder
|
||||
SelectOrder()
|
||||
}
|
||||
else {
|
||||
sender ! VehicleSpawnControl.RenderOrderRemainderMsg(orders.length + 1)
|
||||
}
|
||||
|
||||
case VehicleSpawnControl.ProcessControl.GetOrder =>
|
||||
trackedOrder match {
|
||||
case None =>
|
||||
periodicReminder.cancel
|
||||
val (completeOrder, remainingOrders) : (Option[VehicleSpawnControl.Order], List[VehicleSpawnControl.Order]) = orders match {
|
||||
case x :: Nil =>
|
||||
(Some(x), Nil)
|
||||
case x :: b =>
|
||||
trace(s"order backlog size: ${b.size}")
|
||||
VehicleSpawnControl.recursiveOrderReminder(b.iterator)
|
||||
(Some(x), b)
|
||||
case Nil =>
|
||||
(None, Nil)
|
||||
}
|
||||
orders = remainingOrders
|
||||
completeOrder match {
|
||||
case Some(entry) =>
|
||||
trace(s"processing next order - a ${entry.vehicle.Definition.Name} for ${entry.driver.Name}")
|
||||
trackedOrder = completeOrder //guard on
|
||||
context.system.scheduler.scheduleOnce(2000 milliseconds, concealPlayer, VehicleSpawnControl.Process.ConcealPlayer(entry))
|
||||
case None =>
|
||||
trackedOrder = None
|
||||
}
|
||||
case Some(_) => ; //do not work on new orders
|
||||
}
|
||||
|
||||
case VehicleSpawnControl.ProcessControl.CancelOrder =>
|
||||
VehicleSpawnControl.recursiveFindOrder(orders.iterator, sender) match {
|
||||
case None => ;
|
||||
case Some(index) =>
|
||||
val dequeuedOrder = orders(index)
|
||||
orders = orders.take(index - 1) ++ orders.drop(index + 1)
|
||||
trace(s"${dequeuedOrder.driver}'s vehicle order has been cancelled")
|
||||
}
|
||||
|
||||
case VehicleSpawnControl.ProcessControl.GetNewOrder =>
|
||||
if(sender == concealPlayer) {
|
||||
trackedOrder = None //guard off
|
||||
self ! VehicleSpawnControl.ProcessControl.GetOrder
|
||||
SelectOrder()
|
||||
}
|
||||
|
||||
/*
|
||||
When the vehicle is spawned and added to the pad, it will "occupy" the pad and block it from further action.
|
||||
Normally, the player who wanted to spawn the vehicle will be automatically put into the driver seat.
|
||||
If this is blocked, the vehicle will idle on the pad and must be moved far enough away from the point of origin.
|
||||
During this time, a periodic message about the spawn pad being blocked
|
||||
will be broadcast to all current customers in the order queue.
|
||||
*/
|
||||
case VehicleSpawnControl.ProcessControl.Reminder =>
|
||||
/*
|
||||
When the vehicle is spawned and added to the pad, it will "occupy" the pad and block it from further action.
|
||||
Normally, the player who wanted to spawn the vehicle will be automatically put into the driver seat.
|
||||
If this is blocked, the vehicle will idle on the pad and must be moved far enough away from the point of origin.
|
||||
During this time, a periodic message about the spawn pad being blocked
|
||||
will be broadcast to all current customers in the order queue.
|
||||
*/
|
||||
if(periodicReminder.isCancelled) {
|
||||
trace(s"the pad has become blocked by ${trackedOrder.get.vehicle.Definition.Name}")
|
||||
periodicReminder = context.system.scheduler.schedule(
|
||||
VehicleSpawnControl.initialReminderDelay,
|
||||
VehicleSpawnControl.periodicReminderDelay,
|
||||
self, VehicleSpawnControl.ProcessControl.Reminder
|
||||
)
|
||||
}
|
||||
else {
|
||||
VehicleSpawnControl.BlockedReminder(trackedOrder, trackedOrder.get +: orders)
|
||||
trackedOrder match {
|
||||
case Some(entry) =>
|
||||
if(periodicReminder.isCancelled) {
|
||||
trace (s"the pad has become blocked by ${entry.vehicle.Definition.Name}")
|
||||
periodicReminder = context.system.scheduler.schedule(
|
||||
VehicleSpawnControl.initialReminderDelay,
|
||||
VehicleSpawnControl.periodicReminderDelay,
|
||||
self, VehicleSpawnControl.ProcessControl.Reminder
|
||||
)
|
||||
}
|
||||
else {
|
||||
VehicleSpawnControl.BlockedReminder(entry, entry +: orders)
|
||||
}
|
||||
case None => ;
|
||||
periodicReminder.cancel
|
||||
}
|
||||
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
def SelectOrder() : Unit = {
|
||||
trackedOrder match {
|
||||
case None =>
|
||||
periodicReminder.cancel
|
||||
val (completeOrder, remainingOrders) : (Option[VehicleSpawnControl.Order], List[VehicleSpawnControl.Order]) = orders match {
|
||||
case x :: Nil =>
|
||||
(Some(x), Nil)
|
||||
case x :: b =>
|
||||
trace(s"order backlog size: ${b.size}")
|
||||
VehicleSpawnControl.recursiveOrderReminder(b.iterator)
|
||||
(Some(x), b)
|
||||
case Nil =>
|
||||
(None, Nil)
|
||||
}
|
||||
orders = remainingOrders
|
||||
completeOrder match {
|
||||
case Some(entry) =>
|
||||
trace(s"processing next order - a ${entry.vehicle.Definition.Name} for ${entry.driver.Name}")
|
||||
trackedOrder = completeOrder //guard on
|
||||
context.system.scheduler.scheduleOnce(2000 milliseconds, concealPlayer, VehicleSpawnControl.Process.ConcealPlayer(entry))
|
||||
case None =>
|
||||
trackedOrder = None
|
||||
}
|
||||
case Some(_) => ; //do not work on new orders
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object VehicleSpawnControl {
|
||||
private final val initialReminderDelay : FiniteDuration = 10000 milliseconds
|
||||
private final val periodicReminderDelay : FiniteDuration = 10000 milliseconds
|
||||
|
||||
/**
|
||||
* A `TaskResolver` to assist with the deconstruction of vehicles.
|
||||
* Treated like a `lazy val`, this only gets defined once and then keeps getting reused.
|
||||
* Since the use case is "if something goes wrong," a limited implementation should be fine.
|
||||
*/
|
||||
private var emergencyResolver : Option[ActorRef] = None
|
||||
|
||||
/**
|
||||
* An `Enumeration` of non-data control messages for the vehicle spawn process.
|
||||
*/
|
||||
object ProcessControl extends Enumeration {
|
||||
val
|
||||
Reminder,
|
||||
GetOrder,
|
||||
GetNewOrder,
|
||||
CancelOrder
|
||||
GetNewOrder
|
||||
= Value
|
||||
}
|
||||
/**
|
||||
|
|
@ -170,23 +158,46 @@ object VehicleSpawnControl {
|
|||
final case class Order(driver : Player, vehicle : Vehicle, sendTo : ActorRef)
|
||||
|
||||
/**
|
||||
* Properly clean up a vehicle that has been registered, but not yet been spawned into the game world.
|
||||
* @see `VehicleSpawnControl.emergencyResolver`
|
||||
* Properly clean up a vehicle that has been registered, but not yet been spawned into the game world.<br>
|
||||
* <br>
|
||||
* Constructs a temporary `TaskResolver` to deal with the vehicle's registration status.
|
||||
* This "temporary" router will persist as if it were a `static` variable in some other language
|
||||
* due to the fact that the `ActorSystem` object will remember it existing.
|
||||
* After the primary task is complete, the router that was created is stopped so that it can be garbage collected.
|
||||
* We could re-use it theoretically, but the `context` might be untrustworthy.
|
||||
* @param entry the order being cancelled
|
||||
* @param zone the continent on which the vehicle was registered
|
||||
* @param context an `ActorContext` object for which to create the `TaskResolver` object
|
||||
*/
|
||||
def DisposeVehicle(entry : VehicleSpawnControl.Order, zone: Zone)(implicit context : ActorContext) : Unit = {
|
||||
import net.psforever.objects.guid.GUIDTask
|
||||
emergencyResolver.getOrElse({
|
||||
import akka.routing.SmallestMailboxPool
|
||||
import net.psforever.objects.guid.TaskResolver
|
||||
val resolver = context.actorOf(SmallestMailboxPool(10).props(Props[TaskResolver]), "vehicle-spawn-control-emergency-decon-resolver")
|
||||
emergencyResolver = Some(resolver)
|
||||
resolver
|
||||
}) ! GUIDTask.UnregisterVehicle(entry.vehicle)(zone.GUID)
|
||||
import akka.actor.{ActorRef, PoisonPill}
|
||||
import akka.routing.SmallestMailboxPool
|
||||
import net.psforever.objects.guid.{GUIDTask, Task, TaskResolver}
|
||||
import net.psforever.types.Vector3
|
||||
val vehicle = entry.vehicle
|
||||
vehicle.Position = Vector3.Zero
|
||||
zone.VehicleEvents ! VehicleSpawnPad.RevealPlayer(entry.driver.GUID, zone.Id)
|
||||
|
||||
val router = context.actorOf(
|
||||
SmallestMailboxPool(10).props(Props[TaskResolver]),
|
||||
s"vehicle-spawn-control-emergency-decon-resolver-${System.nanoTime}"
|
||||
)
|
||||
router !
|
||||
TaskResolver.GiveTask(
|
||||
new Task() {
|
||||
private val localRouter = router
|
||||
|
||||
override def isComplete = Task.Resolution.Success
|
||||
|
||||
def Execute(resolver : ActorRef) : Unit = {
|
||||
resolver ! scala.util.Success(this)
|
||||
}
|
||||
|
||||
override def Cleanup() : Unit = { localRouter ! PoisonPill } //where the router is stopped
|
||||
}, List(GUIDTask.UnregisterVehicle(vehicle)(zone.GUID))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Properly clean up a vehicle that has been registered and spawned into the game world.
|
||||
* @param entry the order being cancelled
|
||||
|
|
@ -204,7 +215,7 @@ object VehicleSpawnControl {
|
|||
* @return an index-appropriate `VehicleSpawnPad.PeriodicReminder` object
|
||||
*/
|
||||
def RenderOrderRemainderMsg(position : Int) : VehicleSpawnPad.PeriodicReminder = {
|
||||
VehicleSpawnPad.PeriodicReminder(s"Your position in the vehicle spawn queue is $position.")
|
||||
VehicleSpawnPad.PeriodicReminder(VehicleSpawnPad.Reminders.Queue, Some(s"$position"))
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -212,42 +223,38 @@ object VehicleSpawnControl {
|
|||
* @param blockedOrder the previous order whose vehicle is blocking the spawn pad from operating
|
||||
* @param recipients all of the customers who will be receiving the message
|
||||
*/
|
||||
def BlockedReminder(blockedOrder : Option[VehicleSpawnControl.Order], recipients : Seq[VehicleSpawnControl.Order]) : Unit = {
|
||||
blockedOrder match {
|
||||
case Some(entry) =>
|
||||
val msg : String = if(entry.vehicle.Health == 0) {
|
||||
"The vehicle spawn where you placed your order is blocked by wreckage."
|
||||
}
|
||||
else {
|
||||
"The vehicle spawn where you placed your order is blocked."
|
||||
}
|
||||
VehicleSpawnControl.recursiveBlockedReminder(recipients.iterator, msg)
|
||||
case None => ;
|
||||
}
|
||||
}
|
||||
|
||||
@tailrec private final def recursiveFindOrder(iter : Iterator[VehicleSpawnControl.Order], target : ActorRef, index : Int = 0) : Option[Int] = {
|
||||
if(!iter.hasNext) {
|
||||
None
|
||||
}
|
||||
else {
|
||||
val recipient = iter.next
|
||||
if(recipient.sendTo == target) {
|
||||
Some(index)
|
||||
def BlockedReminder(blockedOrder : VehicleSpawnControl.Order, recipients : Seq[VehicleSpawnControl.Order]) : Unit = {
|
||||
val wrecked : Option[Any] = if(blockedOrder.vehicle.Health == 0) {
|
||||
Option("Clear the wreckage.")
|
||||
}
|
||||
else {
|
||||
recursiveFindOrder(iter, target, index + 1)
|
||||
None
|
||||
}
|
||||
}
|
||||
VehicleSpawnControl.recursiveBlockedReminder(recipients.iterator, wrecked)
|
||||
}
|
||||
|
||||
@tailrec private final def recursiveBlockedReminder(iter : Iterator[VehicleSpawnControl.Order], msg : String) : Unit = {
|
||||
// @tailrec private final def recursiveFindOrder(iter : Iterator[VehicleSpawnControl.Order], target : ActorRef, index : Int = 0) : Option[Int] = {
|
||||
// if(!iter.hasNext) {
|
||||
// None
|
||||
// }
|
||||
// else {
|
||||
// val recipient = iter.next
|
||||
// if(recipient.sendTo == target) {
|
||||
// Some(index)
|
||||
// }
|
||||
// else {
|
||||
// recursiveFindOrder(iter, target, index + 1)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
@tailrec private final def recursiveBlockedReminder(iter : Iterator[VehicleSpawnControl.Order], cause : Option[Any]) : Unit = {
|
||||
if(iter.hasNext) {
|
||||
val recipient = iter.next
|
||||
if(recipient.sendTo != ActorRef.noSender) {
|
||||
recipient.sendTo ! VehicleSpawnPad.PeriodicReminder(msg)
|
||||
recipient.sendTo ! VehicleSpawnPad.PeriodicReminder(VehicleSpawnPad.Reminders.Blocked, cause)
|
||||
}
|
||||
recursiveBlockedReminder(iter, msg)
|
||||
recursiveBlockedReminder(iter, cause)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,13 +18,12 @@ import net.psforever.packet.game.PlanetSideGUID
|
|||
*/
|
||||
class VehicleSpawnPad(spDef : VehicleSpawnPadDefinition) extends Amenity {
|
||||
/**
|
||||
* USE THIS BOOLEAN FOR DEVELOPMENT PURPOSES!<br>
|
||||
* Purpose: use the ingame railed platform to lift the spawned vehicle out of the trench.
|
||||
* When set, the client performs the standard vehicle entry procedure, including rail animations.
|
||||
* Use the in-game railed platform to lift the spawned vehicle out of the trench.
|
||||
* When set, the client performs the standard vehicle entry procedure, including lifting platform animations.
|
||||
* When unset, the client depicts the player manually boarding the new vehicle within the trench area.
|
||||
* Eventually, the vehicle is then hoisted out into the open.
|
||||
* The main reason to disable this feature is to avoid an `ObjectAttachMessage` that may be dispatched for an incorrect object.
|
||||
* Unset if not guaranteed to have the correct ingame globally unique id of the spawn pad.
|
||||
* Eventually, the vehicle is then hoisted out into the open; without this set, that hoisting is abrupt.
|
||||
* The main reason to disable this feature is to avoid an `ObjectAttachMessage` for an incorrect object designation.
|
||||
* Unset if not guaranteed to have the correct globally unique id of the spawn pad.
|
||||
*/
|
||||
private var onRails : Boolean = true
|
||||
|
||||
|
|
@ -41,7 +40,7 @@ class VehicleSpawnPad(spDef : VehicleSpawnPadDefinition) extends Amenity {
|
|||
object VehicleSpawnPad {
|
||||
|
||||
/**
|
||||
* Communicate to the spawn pad that it should enqueue the following vehicle.
|
||||
* Message to the spawn pad to enqueue the following vehicle order.
|
||||
* This is the entry point to vehicle spawn pad functionality.
|
||||
* @param player the player who submitted the order (the "owner")
|
||||
* @param vehicle the vehicle produced from the order
|
||||
|
|
@ -49,53 +48,115 @@ object VehicleSpawnPad {
|
|||
final case class VehicleOrder(player : Player, vehicle : Vehicle)
|
||||
|
||||
/**
|
||||
* The first callback step in spawning the vehicle.
|
||||
* An packet `GenericObjectActionMessage(/player/, 36)`, when used on a player character,
|
||||
* will cause that player character's model to fade into transparency.
|
||||
* Message to indicate that a certain player should be made transparent.
|
||||
* @see `GenericObjectActionMessage`
|
||||
* @param player_guid the player
|
||||
* @param zone_id the zone in which the spawn pad is located
|
||||
*/
|
||||
final case class ConcealPlayer(player_guid : PlanetSideGUID, zone_id : String)
|
||||
|
||||
/**
|
||||
* Undoes the above message.
|
||||
* Message is intended to undo the effects of the above message, `ConcealPlayer`.
|
||||
* @see `ConcealPlayer`
|
||||
* @param player_guid the player
|
||||
* @param zone_id the zone in which the spawn pad is located
|
||||
*/
|
||||
final case class RevealPlayer(player_guid : PlanetSideGUID, zone_id : String)
|
||||
|
||||
/**
|
||||
* A callback step in spawning the vehicle.
|
||||
* The vehicle is properly introduced into the game world.
|
||||
* If information about the vehicle itself that is important to its spawning has not yet been set,
|
||||
* this callback is the last ideal situation to set that properties without having to adjust the vehicle visually.
|
||||
* The primary operation that should occur is a content-appropriate `ObjectCreateMessage` packet and
|
||||
* having the player sit down in the driver's seat (seat 0) of the vehicle.
|
||||
* Message to properly introduce the vehicle into the zone.
|
||||
* @param vehicle the vehicle being spawned
|
||||
* @param zone the zone in which the spawn pad is located
|
||||
*/
|
||||
final case class LoadVehicle(vehicle : Vehicle, zone : Zone)
|
||||
|
||||
/**
|
||||
* Message to attach the vehicle to the spawn pad's lifting platform ("put on rails").
|
||||
* The attachment process (to the third slot) itself begins autonomous operation of the lifting platform.
|
||||
* @see `ObjectAttachMessage`
|
||||
* @param vehicle the vehicle being spawned
|
||||
* @param pad the spawn pad
|
||||
* @param zone_id the zone in which the spawn pad is located
|
||||
*/
|
||||
final case class AttachToRails(vehicle : Vehicle, pad : VehicleSpawnPad, zone_id : String)
|
||||
|
||||
/**
|
||||
* Message to detach the vehicle from the spawn pad's lifting platform ("put on rails").
|
||||
* @see `ObjectDetachMessage`
|
||||
* @param vehicle the vehicle being spawned
|
||||
* @param pad the spawn pad
|
||||
* @param zone_id the zone in which the spawn pad is located
|
||||
*/
|
||||
final case class DetachFromRails(vehicle : Vehicle, pad : VehicleSpawnPad, zone_id : String)
|
||||
|
||||
/**
|
||||
* Message that resets the spawn pad for its next order fulfillment operation by lowering the lifting platform.
|
||||
* @see `GenericObjectActionMessage`
|
||||
* @param pad the spawn pad
|
||||
* @param zone_id the zone in which the spawn pad is located
|
||||
*/
|
||||
final case class ResetSpawnPad(pad : VehicleSpawnPad, zone_id : String)
|
||||
|
||||
/**
|
||||
* Message that acts as callback to the driver that the process of sitting in the driver seat will be initiated soon.
|
||||
* This information should only be communicated to the driver's client only.
|
||||
* @param vehicle the vehicle being spawned
|
||||
* @param pad the spawn pad
|
||||
*/
|
||||
final case class StartPlayerSeatedInVehicle(vehicle : Vehicle, pad : VehicleSpawnPad)
|
||||
|
||||
/**
|
||||
* A TEMPORARY callback step in spawning the vehicle.
|
||||
* From a state of transparency, while the vehicle is attached to the lifting platform of the spawn pad,
|
||||
* the player designated the "owner" by callback is made to sit in the driver's seat (always seat 0).
|
||||
* This message is the next step after that.
|
||||
* Message that acts as callback to the driver that the process of sitting in the driver seat should be finished.
|
||||
* This information should only be communicated to the driver's client only.
|
||||
* @param vehicle the vehicle being spawned
|
||||
* @param pad the spawn pad
|
||||
*/
|
||||
final case class PlayerSeatedInVehicle(vehicle : Vehicle, pad : VehicleSpawnPad) //TODO while using fake rails
|
||||
|
||||
/**
|
||||
* Message that starts the newly-spawned vehicle to begin driving away from the spawn pad.
|
||||
* Information about the driving process is available on the vehicle itself.
|
||||
* This information should only be communicated to the driver's client only.
|
||||
* @see `VehicleDefinition`
|
||||
* @param vehicle the vehicle
|
||||
* @param pad the spawn pad
|
||||
*/
|
||||
final case class ServerVehicleOverrideStart(vehicle : Vehicle, pad : VehicleSpawnPad)
|
||||
|
||||
/**
|
||||
* Message that transitions the newly-spawned vehicle into a cancellable auto-drive state.
|
||||
* Information about the driving process is available on the vehicle itself.
|
||||
* This information should only be communicated to the driver's client only.
|
||||
* @see `VehicleDefinition`
|
||||
* @param vehicle the vehicle
|
||||
* @param pad the spawn pad
|
||||
*/
|
||||
final case class ServerVehicleOverrideEnd(vehicle : Vehicle, pad : VehicleSpawnPad)
|
||||
|
||||
final case class ResetSpawnPad(pad : VehicleSpawnPad, zone_id : String)
|
||||
|
||||
final case class PeriodicReminder(msg : String)
|
||||
|
||||
/**
|
||||
* Message to initiate the process of properly disposing of the vehicle that may have been or was spawned into the game world.
|
||||
* @param vehicle the vehicle
|
||||
* @param zone the zone in which the spawn pad is located
|
||||
*/
|
||||
final case class DisposeVehicle(vehicle : Vehicle, zone : Zone)
|
||||
|
||||
/**
|
||||
* Message to send targeted messages to the clients of specific users.
|
||||
* @param reason the nature of the message
|
||||
* @param data optional information for rendering the message to the client
|
||||
*/
|
||||
final case class PeriodicReminder(reason : Reminders.Value, data : Option[Any] = None)
|
||||
|
||||
/**
|
||||
* An `Enumeration` of reasons for sending a periodic reminder to the user.
|
||||
*/
|
||||
object Reminders extends Enumeration {
|
||||
val
|
||||
Queue, //optional data is the numeric position in the queue
|
||||
Blocked //optional data is a message regarding the blockage
|
||||
= Value
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloaded constructor.
|
||||
* @param spDef the spawn pad's definition entry
|
||||
|
|
@ -109,7 +170,7 @@ object VehicleSpawnPad {
|
|||
import net.psforever.types.Vector3
|
||||
|
||||
/**
|
||||
* Instantiate an configure a `VehicleSpawnPad` object
|
||||
* Instantiate and configure a `VehicleSpawnPad` object
|
||||
* @param pos the position (used to determine spawn point)
|
||||
* @param orient the orientation (used to indicate spawn direction)
|
||||
* @param id the unique id that will be assigned to this entity
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class VehicleSpawnControlConcealPlayer(pad : VehicleSpawnPad) extends VehicleSpa
|
|||
case VehicleSpawnControl.Process.ConcealPlayer(entry) =>
|
||||
val driver = entry.driver
|
||||
//TODO how far can the driver get stray from the Terminal before his order is cancelled?
|
||||
if(entry.sendTo != ActorRef.noSender && driver.isAlive && driver.Continent == Continent.Id && driver.VehicleSeated.isEmpty) {
|
||||
if(entry.sendTo != ActorRef.noSender && driver.Continent == Continent.Id && driver.VehicleSeated.isEmpty) {
|
||||
trace(s"hiding ${driver.Name}")
|
||||
Continent.VehicleEvents ! VehicleSpawnPad.ConcealPlayer(driver.GUID, Continent.Id)
|
||||
context.system.scheduler.scheduleOnce(2000 milliseconds, loadVehicle, VehicleSpawnControl.Process.LoadVehicle(entry))
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import scala.concurrent.duration._
|
|||
class VehicleSpawnControlLoadVehicle(pad : VehicleSpawnPad) extends VehicleSpawnControlBase(pad) {
|
||||
def LogId = "-loader"
|
||||
|
||||
val seatDriver = context.actorOf(Props(classOf[VehicleSpawnControlSeatDriver], pad), s"${context.parent.path.name}-seat")
|
||||
val railJack = context.actorOf(Props(classOf[VehicleSpawnControlRailJack], pad), s"${context.parent.path.name}-rails")
|
||||
|
||||
def receive : Receive = {
|
||||
case VehicleSpawnControl.Process.LoadVehicle(entry) =>
|
||||
|
|
@ -32,12 +32,12 @@ class VehicleSpawnControlLoadVehicle(pad : VehicleSpawnPad) extends VehicleSpawn
|
|||
trace(s"loading the ${vehicle.Definition.Name}")
|
||||
vehicle.Position = vehicle.Position - Vector3(0, 0, if(GlobalDefinitions.isFlightVehicle(vehicle.Definition)) 9 else 5)
|
||||
Continent.VehicleEvents ! VehicleSpawnPad.LoadVehicle(vehicle, Continent)
|
||||
context.system.scheduler.scheduleOnce(100 milliseconds, seatDriver, VehicleSpawnControl.Process.SeatDriver(entry))
|
||||
context.system.scheduler.scheduleOnce(100 milliseconds, railJack, VehicleSpawnControl.Process.RailJackAction(entry))
|
||||
}
|
||||
else {
|
||||
trace("owner lost; abort order fulfillment")
|
||||
VehicleSpawnControl.DisposeVehicle(entry, Continent)
|
||||
context.parent ! VehicleSpawnControl.ProcessControl.GetOrder
|
||||
context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder
|
||||
}
|
||||
|
||||
case VehicleSpawnControl.ProcessControl.Reminder =>
|
||||
|
|
|
|||
|
|
@ -22,20 +22,25 @@ import scala.concurrent.duration._
|
|||
class VehicleSpawnControlRailJack(pad : VehicleSpawnPad) extends VehicleSpawnControlBase(pad) {
|
||||
def LogId = "-lifter"
|
||||
|
||||
val vehicleOverride = context.actorOf(Props(classOf[VehicleSpawnControlServerVehicleOverride], pad), s"${context.parent.path.name}-override")
|
||||
val seatDriver = context.actorOf(Props(classOf[VehicleSpawnControlSeatDriver], pad), s"${context.parent.path.name}-seat")
|
||||
|
||||
def receive : Receive = {
|
||||
case VehicleSpawnControl.Process.RailJackAction(entry) =>
|
||||
if(entry.vehicle.Health == 0) {
|
||||
//TODO detach vehicle from pad rails if necessary
|
||||
trace(s"vehicle was already destroyed")
|
||||
trace("vehicle was already destroyed; clean it up")
|
||||
VehicleSpawnControl.DisposeSpawnedVehicle(entry, Continent)
|
||||
context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder
|
||||
}
|
||||
else {
|
||||
trace(s"extending rails with vehicle attached")
|
||||
if(pad.Railed) {
|
||||
trace(s"attaching vehicle to railed platform")
|
||||
Continent.VehicleEvents ! VehicleSpawnPad.AttachToRails(entry.vehicle, pad, Continent.Id)
|
||||
}
|
||||
else {
|
||||
trace(s"railed platform skipped; vehicle positioned temporarily in pad trench")
|
||||
}
|
||||
context.parent ! VehicleSpawnControl.ProcessControl.Reminder
|
||||
context.system.scheduler.scheduleOnce(10 milliseconds, vehicleOverride, VehicleSpawnControl.Process.ServerVehicleOverride(entry))
|
||||
context.system.scheduler.scheduleOnce(10 milliseconds, seatDriver, VehicleSpawnControl.Process.SeatDriver(entry))
|
||||
}
|
||||
|
||||
case VehicleSpawnControl.ProcessControl.GetNewOrder =>
|
||||
|
|
|
|||
|
|
@ -25,34 +25,32 @@ import scala.concurrent.duration._
|
|||
class VehicleSpawnControlSeatDriver(pad : VehicleSpawnPad) extends VehicleSpawnControlBase(pad) {
|
||||
def LogId = "-usher"
|
||||
|
||||
val railJack = context.actorOf(Props(classOf[VehicleSpawnControlRailJack], pad), s"${context.parent.path.name}-rails")
|
||||
val vehicleOverride = context.actorOf(Props(classOf[VehicleSpawnControlServerVehicleOverride], pad), s"${context.parent.path.name}-override")
|
||||
|
||||
def receive : Receive = {
|
||||
case VehicleSpawnControl.Process.SeatDriver(entry) =>
|
||||
if(entry.vehicle.Actor == ActorRef.noSender) { //wait for the component of the vehicle needed for seating to be loaded
|
||||
context.system.scheduler.scheduleOnce(50 milliseconds, railJack, VehicleSpawnControl.Process.SeatDriver(entry))
|
||||
context.system.scheduler.scheduleOnce(50 milliseconds, self, VehicleSpawnControl.Process.SeatDriver(entry))
|
||||
}
|
||||
else {
|
||||
val driver = entry.driver
|
||||
if(entry.vehicle.Health == 0) {
|
||||
trace("vehicle was already destroyed; clean it up")
|
||||
if(pad.Railed) {
|
||||
Continent.VehicleEvents ! VehicleSpawnPad.ResetSpawnPad(pad, Continent.Id)
|
||||
}
|
||||
VehicleSpawnControl.DisposeSpawnedVehicle(entry, Continent)
|
||||
context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder
|
||||
}
|
||||
else if(entry.sendTo != ActorRef.noSender && driver.isAlive && driver.Continent == Continent.Id && driver.VehicleSeated.isEmpty) {
|
||||
trace("driver to be made seated in vehicle")
|
||||
entry.sendTo ! VehicleSpawnPad.StartPlayerSeatedInVehicle(entry.vehicle, pad)
|
||||
entry.vehicle.Actor.tell(Mountable.TryMount(driver, 0), entry.sendTo) //entry.sendTo should handle replies to TryMount
|
||||
context.system.scheduler.scheduleOnce(1000 milliseconds, self, VehicleSpawnControl.Process.AwaitDriverInSeat(entry))
|
||||
}
|
||||
else {
|
||||
if(entry.sendTo != ActorRef.noSender && driver.isAlive && driver.Continent == Continent.Id && driver.VehicleSeated.isEmpty) {
|
||||
trace("driver to be made seated in vehicle")
|
||||
entry.sendTo ! VehicleSpawnPad.StartPlayerSeatedInVehicle(entry.vehicle, pad)
|
||||
entry.vehicle.Actor.tell(Mountable.TryMount(driver, 0), entry.sendTo) //entry.sendTo should handle replies to TryMount
|
||||
context.system.scheduler.scheduleOnce(1000 milliseconds, self, VehicleSpawnControl.Process.AwaitDriverInSeat(entry))
|
||||
}
|
||||
else {
|
||||
if(pad.Railed) {
|
||||
Continent.VehicleEvents ! VehicleSpawnPad.AttachToRails(entry.vehicle, pad, Continent.Id)
|
||||
}
|
||||
trace("driver lost; vehicle stranded on pad")
|
||||
context.system.scheduler.scheduleOnce(1000 milliseconds, railJack, VehicleSpawnControl.Process.RailJackAction(entry))
|
||||
}
|
||||
trace("driver lost; vehicle stranded on pad")
|
||||
context.system.scheduler.scheduleOnce(1000 milliseconds, vehicleOverride, VehicleSpawnControl.Process.ServerVehicleOverride(entry))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -60,40 +58,42 @@ class VehicleSpawnControlSeatDriver(pad : VehicleSpawnPad) extends VehicleSpawnC
|
|||
val driver = entry.driver
|
||||
if(entry.vehicle.Health == 0) {
|
||||
trace("vehicle was already destroyed; clean it up")
|
||||
if(pad.Railed) {
|
||||
Continent.VehicleEvents ! VehicleSpawnPad.ResetSpawnPad(pad, Continent.Id)
|
||||
}
|
||||
VehicleSpawnControl.DisposeSpawnedVehicle(entry, Continent)
|
||||
context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder
|
||||
}
|
||||
else if(entry.sendTo == ActorRef.noSender) {
|
||||
else if(entry.sendTo == ActorRef.noSender || driver.Continent != Continent.Id) {
|
||||
trace("driver lost, but operations can continue")
|
||||
self ! VehicleSpawnControl.Process.RailJackAction(entry)
|
||||
vehicleOverride ! VehicleSpawnControl.Process.ServerVehicleOverride(entry)
|
||||
}
|
||||
else if(driver.isAlive && driver.Continent == Continent.Id && driver.VehicleSeated.isEmpty) {
|
||||
else if(driver.isAlive && driver.VehicleSeated.isEmpty) {
|
||||
context.system.scheduler.scheduleOnce(100 milliseconds, self, VehicleSpawnControl.Process.AwaitDriverInSeat(entry))
|
||||
}
|
||||
else {
|
||||
trace(s"driver is sitting down")
|
||||
context.system.scheduler.scheduleOnce(
|
||||
VehicleSpawnControlSeatDriver.RaillessSeatAnimationTimes(entry.vehicle.Definition.Name) milliseconds,
|
||||
self,
|
||||
VehicleSpawnControl.Process.DriverInSeat(entry)
|
||||
)
|
||||
val time = if(pad.Railed) 1000 else VehicleSpawnControlSeatDriver.RaillessSeatAnimationTimes(entry.vehicle.Definition.Name)
|
||||
context.system.scheduler.scheduleOnce(time milliseconds, self, VehicleSpawnControl.Process.DriverInSeat(entry))
|
||||
}
|
||||
|
||||
case VehicleSpawnControl.Process.DriverInSeat(entry) =>
|
||||
if(entry.vehicle.Health == 0) {
|
||||
//TODO detach vehicle from pad rails if necessary
|
||||
trace(s"vehicle was already destroyed; clean it up")
|
||||
if(pad.Railed) {
|
||||
Continent.VehicleEvents ! VehicleSpawnPad.ResetSpawnPad(pad, Continent.Id)
|
||||
}
|
||||
VehicleSpawnControl.DisposeSpawnedVehicle(entry, Continent)
|
||||
context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder
|
||||
}
|
||||
else if(entry.sendTo != ActorRef.noSender) {
|
||||
else if(entry.sendTo != ActorRef.noSender || entry.driver.Continent != Continent.Id) {
|
||||
trace(s"driver ${entry.driver.Name} has taken the wheel")
|
||||
entry.sendTo ! VehicleSpawnPad.PlayerSeatedInVehicle(entry.vehicle, pad)
|
||||
context.system.scheduler.scheduleOnce(10 milliseconds, railJack, VehicleSpawnControl.Process.RailJackAction(entry))
|
||||
context.system.scheduler.scheduleOnce(10 milliseconds, vehicleOverride, VehicleSpawnControl.Process.ServerVehicleOverride(entry))
|
||||
}
|
||||
else {
|
||||
trace("driver lost, but operations can continue")
|
||||
context.system.scheduler.scheduleOnce(10 milliseconds, railJack, VehicleSpawnControl.Process.RailJackAction(entry))
|
||||
context.system.scheduler.scheduleOnce(10 milliseconds, vehicleOverride, VehicleSpawnControl.Process.ServerVehicleOverride(entry))
|
||||
}
|
||||
|
||||
case VehicleSpawnControl.ProcessControl.Reminder =>
|
||||
|
|
@ -118,6 +118,7 @@ object VehicleSpawnControlSeatDriver {
|
|||
"fury" -> 600,
|
||||
"quadassault" -> 600,
|
||||
"quadstealth" -> 600,
|
||||
"two_man_assault_buggy" -> 1000,
|
||||
"skyguard" -> 1300,
|
||||
"threemanheavybuggy" -> 1000,
|
||||
"twomanheavybuggy" -> 1800,
|
||||
|
|
|
|||
|
|
@ -26,25 +26,31 @@ class VehicleSpawnControlServerVehicleOverride(pad : VehicleSpawnPad) extends Ve
|
|||
def receive : Receive = {
|
||||
case VehicleSpawnControl.Process.ServerVehicleOverride(entry) =>
|
||||
val vehicle = entry.vehicle
|
||||
//TODO detach vehicle from pad rails
|
||||
Continent.VehicleEvents ! VehicleSpawnPad.DetachFromRails(vehicle, pad, Continent.Id)
|
||||
if(vehicle.Health == 0) {
|
||||
trace(s"vehicle was already destroyed; but, everything is fine")
|
||||
if(pad.Railed) {
|
||||
Continent.VehicleEvents ! VehicleSpawnPad.ResetSpawnPad(pad, Continent.Id)
|
||||
}
|
||||
finalClear ! VehicleSpawnControl.Process.FinalClearance(entry)
|
||||
}
|
||||
else if(entry.sendTo != ActorRef.noSender && entry.driver.VehicleSeated.contains(vehicle.GUID)) {
|
||||
else if(entry.sendTo != ActorRef.noSender && entry.driver.isAlive && entry.driver.Continent == Continent.Id && entry.driver.VehicleSeated.contains(vehicle.GUID)) {
|
||||
trace(s"telling ${entry.driver.Name} that the server is assuming control of the ${vehicle.Definition.Name}")
|
||||
entry.sendTo ! VehicleSpawnPad.ServerVehicleOverrideStart(vehicle, pad)
|
||||
context.system.scheduler.scheduleOnce(3000 milliseconds, self, VehicleSpawnControl.Process.DriverVehicleControl(entry))
|
||||
}
|
||||
else {
|
||||
if(pad.Railed) {
|
||||
Continent.VehicleEvents ! VehicleSpawnPad.DetachFromRails(vehicle, pad, Continent.Id)
|
||||
Continent.VehicleEvents ! VehicleSpawnPad.ResetSpawnPad(pad, Continent.Id)
|
||||
}
|
||||
finalClear ! VehicleSpawnControl.Process.FinalClearance(entry)
|
||||
}
|
||||
|
||||
case VehicleSpawnControl.Process.DriverVehicleControl(entry) =>
|
||||
val vehicle = entry.vehicle
|
||||
if(pad.Railed) {
|
||||
Continent.VehicleEvents ! VehicleSpawnPad.ResetSpawnPad(pad, Continent.Id)
|
||||
}
|
||||
if(vehicle.Health == 0) {
|
||||
trace(s"vehicle was already destroyed; but, everything is fine")
|
||||
}
|
||||
|
|
@ -59,9 +65,6 @@ class VehicleSpawnControlServerVehicleOverride(pad : VehicleSpawnPad) extends Ve
|
|||
}
|
||||
}
|
||||
else {
|
||||
if(pad.Railed) {
|
||||
Continent.VehicleEvents ! VehicleSpawnPad.ResetSpawnPad(pad, Continent.Id)
|
||||
}
|
||||
trace("can not properly return control to driver")
|
||||
}
|
||||
finalClear ! VehicleSpawnControl.Process.FinalClearance(entry)
|
||||
|
|
|
|||
|
|
@ -55,10 +55,10 @@ class ZoneActor(zone : Zone) extends Actor {
|
|||
zone.Ground forward msg
|
||||
|
||||
//frwd to Vehicle Actor
|
||||
case msg @ Zone.SpawnVehicle =>
|
||||
case msg @ Zone.Vehicle.Spawn =>
|
||||
zone.Transport forward msg
|
||||
|
||||
case msg @ Zone.DespawnVehicle =>
|
||||
case msg @ Zone.Vehicle.Despawn =>
|
||||
zone.Transport forward msg
|
||||
|
||||
//own
|
||||
|
|
|
|||
|
|
@ -2,16 +2,17 @@
|
|||
package objects
|
||||
|
||||
import akka.actor.{ActorRef, ActorSystem, Props}
|
||||
import akka.testkit.TestProbe
|
||||
import net.psforever.objects.serverobject.mount.Mountable
|
||||
import net.psforever.objects.serverobject.pad.{VehicleSpawnControl, VehicleSpawnPad}
|
||||
import net.psforever.objects.serverobject.structures.{Building, StructureType}
|
||||
import net.psforever.objects.vehicles.VehicleControl
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.objects.serverobject.structures.StructureType
|
||||
import net.psforever.objects.{Avatar, GlobalDefinitions, Player, Vehicle}
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.types.{CharacterGender, PlanetSideEmpire, Vector3}
|
||||
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
import scala.concurrent.duration.Duration
|
||||
import scala.concurrent.duration._
|
||||
|
||||
class VehicleSpawnPadTest extends Specification {
|
||||
"VehicleSpawnPadDefinition" should {
|
||||
|
|
@ -25,6 +26,14 @@ class VehicleSpawnPadTest extends Specification {
|
|||
val obj = VehicleSpawnPad(GlobalDefinitions.spawn_pad)
|
||||
obj.Actor mustEqual ActorRef.noSender
|
||||
obj.Definition mustEqual GlobalDefinitions.spawn_pad
|
||||
obj.Railed mustEqual true
|
||||
}
|
||||
|
||||
"un-railed" in {
|
||||
val obj = VehicleSpawnPad(GlobalDefinitions.spawn_pad)
|
||||
obj.Railed mustEqual true
|
||||
obj.Railed = false
|
||||
obj.Railed mustEqual false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -39,78 +48,465 @@ class VehicleSpawnControl1Test extends ActorTest() {
|
|||
}
|
||||
}
|
||||
|
||||
class VehicleSpawnControl2Test extends ActorTest() {
|
||||
class VehicleSpawnControl2aTest extends ActorTest() {
|
||||
// This long runs for a long time.
|
||||
"VehicleSpawnControl" should {
|
||||
"spawn a vehicle" in {
|
||||
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")
|
||||
"complete on a vehicle order (block a second one until the first is done and the spawn pad is cleared)" in {
|
||||
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
//we can recycle the vehicle and the player for each order
|
||||
val probe1 = new TestProbe(system, "first-order")
|
||||
val probe2 = new TestProbe(system, "second-order")
|
||||
val probe3 = new TestProbe(system, "zone-events")
|
||||
zone.VehicleEvents = probe3.ref
|
||||
|
||||
pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle)
|
||||
val reply = receiveOne(Duration.create(10000, "ms"))
|
||||
assert(reply == VehicleSpawnPad.ConcealPlayer) //explicit: isInstanceOf does not work
|
||||
pad.Actor.tell(VehicleSpawnPad.VehicleOrder(player, vehicle), probe1.ref) //first order
|
||||
pad.Actor.tell(VehicleSpawnPad.VehicleOrder(player, vehicle), probe2.ref) //second order
|
||||
|
||||
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 == pad)
|
||||
//
|
||||
// player.VehicleOwned = Some(vehicle.GUID)
|
||||
// val reply3 = receiveOne(Duration.create(10000, "ms"))
|
||||
// assert(reply3.isInstanceOf[VehicleSpawnPad.PlayerSeatedInVehicle])
|
||||
// assert(reply3.asInstanceOf[VehicleSpawnPad.PlayerSeatedInVehicle].vehicle == vehicle)
|
||||
//
|
||||
// val reply4 = receiveOne(Duration.create(10000, "ms"))
|
||||
// assert(reply4.isInstanceOf[VehicleSpawnPad.SpawnPadBlockedWarning])
|
||||
// assert(reply4.asInstanceOf[VehicleSpawnPad.SpawnPadBlockedWarning].vehicle == vehicle)
|
||||
// assert(reply4.asInstanceOf[VehicleSpawnPad.SpawnPadBlockedWarning].warning_count > 0)
|
||||
//
|
||||
// vehicle.Position = Vector3(11f, 0f, 0f) //greater than 10m
|
||||
// val reply5 = receiveOne(Duration.create(10000, "ms"))
|
||||
// assert(reply5.isInstanceOf[VehicleSpawnPad.SpawnPadUnblocked])
|
||||
// assert(reply5.asInstanceOf[VehicleSpawnPad.SpawnPadUnblocked].vehicle_guid == vehicle.GUID)
|
||||
val probe2Msg1 = probe2.receiveOne(100 milliseconds)
|
||||
assert(probe2Msg1.isInstanceOf[VehicleSpawnPad.PeriodicReminder])
|
||||
assert(probe2Msg1.asInstanceOf[VehicleSpawnPad.PeriodicReminder].reason == VehicleSpawnPad.Reminders.Queue)
|
||||
assert(probe2Msg1.asInstanceOf[VehicleSpawnPad.PeriodicReminder].data.contains("2"))
|
||||
|
||||
val probe3Msg1 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg1.isInstanceOf[VehicleSpawnPad.ConcealPlayer])
|
||||
|
||||
val probe3Msg2 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg2.isInstanceOf[VehicleSpawnPad.LoadVehicle])
|
||||
|
||||
val probe3Msg3 = probe3.receiveOne(200 milliseconds)
|
||||
assert(probe3Msg3.isInstanceOf[VehicleSpawnPad.AttachToRails])
|
||||
|
||||
val probe1Msg1 = probe1.receiveOne(200 milliseconds)
|
||||
assert(probe1Msg1.isInstanceOf[VehicleSpawnPad.StartPlayerSeatedInVehicle])
|
||||
val probe1Msg2 = probe1.receiveOne(200 milliseconds)
|
||||
assert(probe1Msg2.isInstanceOf[Mountable.MountMessages])
|
||||
val probe1Msg2Contents = probe1Msg2.asInstanceOf[Mountable.MountMessages]
|
||||
assert(probe1Msg2Contents.response.isInstanceOf[Mountable.CanMount])
|
||||
val probe1Msg3 = probe1.receiveOne(3 seconds)
|
||||
assert(probe1Msg3.isInstanceOf[VehicleSpawnPad.PlayerSeatedInVehicle])
|
||||
|
||||
val probe3Msg4 = probe3.receiveOne(200 milliseconds)
|
||||
assert(probe3Msg4.isInstanceOf[VehicleSpawnPad.DetachFromRails])
|
||||
|
||||
val probe1Msg4 = probe1.receiveOne(1 seconds)
|
||||
assert(probe1Msg4.isInstanceOf[VehicleSpawnPad.ServerVehicleOverrideStart])
|
||||
val probe1Msg5 = probe1.receiveOne(4 seconds)
|
||||
assert(probe1Msg5.isInstanceOf[VehicleSpawnPad.ServerVehicleOverrideEnd])
|
||||
|
||||
val probe1Msg6 = probe1.receiveOne(10 seconds)
|
||||
assert(probe1Msg6.isInstanceOf[VehicleSpawnPad.PeriodicReminder])
|
||||
assert(probe1Msg6.asInstanceOf[VehicleSpawnPad.PeriodicReminder].reason == VehicleSpawnPad.Reminders.Blocked)
|
||||
val probe2Msg2 = probe2.receiveOne(100 milliseconds)
|
||||
assert(probe2Msg2.isInstanceOf[VehicleSpawnPad.PeriodicReminder])
|
||||
assert(probe2Msg2.asInstanceOf[VehicleSpawnPad.PeriodicReminder].reason == VehicleSpawnPad.Reminders.Blocked)
|
||||
|
||||
//if we move the vehicle more than 10m away from the pad, we should receive a ResetSpawnPad, and a second ConcealPlayer message
|
||||
//that means that the first order has cleared and the spawn pad is now working on the second order successfully
|
||||
vehicle.Position = Vector3(0,0,11)
|
||||
player.VehicleSeated = None //since shared between orders, is necessary
|
||||
val probe3Msg5 = probe3.receiveOne(4 seconds)
|
||||
assert(probe3Msg5.isInstanceOf[VehicleSpawnPad.ResetSpawnPad])
|
||||
val probe3Msg6 = probe3.receiveOne(4 seconds)
|
||||
assert(probe3Msg6.isInstanceOf[VehicleSpawnPad.ConcealPlayer])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleSpawnControl2bTest extends ActorTest() {
|
||||
// This long runs for a long time.
|
||||
"VehicleSpawnControl" should {
|
||||
"complete on a vehicle order (railless)" in {
|
||||
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
//we can recycle the vehicle and the player for each order
|
||||
val probe1 = new TestProbe(system, "first-order")
|
||||
val probe2 = new TestProbe(system, "second-order")
|
||||
val probe3 = new TestProbe(system, "zone-events")
|
||||
zone.VehicleEvents = probe3.ref
|
||||
pad.Railed = false
|
||||
|
||||
pad.Actor.tell(VehicleSpawnPad.VehicleOrder(player, vehicle), probe1.ref) //first order
|
||||
pad.Actor.tell(VehicleSpawnPad.VehicleOrder(player, vehicle), probe2.ref) //second order
|
||||
|
||||
val probe2Msg1 = probe2.receiveOne(100 milliseconds)
|
||||
assert(probe2Msg1.isInstanceOf[VehicleSpawnPad.PeriodicReminder])
|
||||
assert(probe2Msg1.asInstanceOf[VehicleSpawnPad.PeriodicReminder].reason == VehicleSpawnPad.Reminders.Queue)
|
||||
assert(probe2Msg1.asInstanceOf[VehicleSpawnPad.PeriodicReminder].data.contains("2"))
|
||||
|
||||
val probe3Msg1 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg1.isInstanceOf[VehicleSpawnPad.ConcealPlayer])
|
||||
|
||||
val probe3Msg2 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg2.isInstanceOf[VehicleSpawnPad.LoadVehicle])
|
||||
|
||||
val probe1Msg1 = probe1.receiveOne(200 milliseconds)
|
||||
assert(probe1Msg1.isInstanceOf[VehicleSpawnPad.StartPlayerSeatedInVehicle])
|
||||
val probe1Msg2 = probe1.receiveOne(200 milliseconds)
|
||||
assert(probe1Msg2.isInstanceOf[Mountable.MountMessages])
|
||||
val probe1Msg2Contents = probe1Msg2.asInstanceOf[Mountable.MountMessages]
|
||||
assert(probe1Msg2Contents.response.isInstanceOf[Mountable.CanMount])
|
||||
val probe1Msg3 = probe1.receiveOne(3 seconds)
|
||||
assert(probe1Msg3.isInstanceOf[VehicleSpawnPad.PlayerSeatedInVehicle])
|
||||
|
||||
val probe3Msg4 = probe3.receiveOne(200 milliseconds)
|
||||
assert(probe3Msg4.isInstanceOf[VehicleSpawnPad.DetachFromRails])
|
||||
|
||||
val probe1Msg4 = probe1.receiveOne(1 seconds)
|
||||
assert(probe1Msg4.isInstanceOf[VehicleSpawnPad.ServerVehicleOverrideStart])
|
||||
val probe1Msg5 = probe1.receiveOne(4 seconds)
|
||||
assert(probe1Msg5.isInstanceOf[VehicleSpawnPad.ServerVehicleOverrideEnd])
|
||||
|
||||
val probe1Msg6 = probe1.receiveOne(10 seconds)
|
||||
assert(probe1Msg6.isInstanceOf[VehicleSpawnPad.PeriodicReminder])
|
||||
assert(probe1Msg6.asInstanceOf[VehicleSpawnPad.PeriodicReminder].reason == VehicleSpawnPad.Reminders.Blocked)
|
||||
val probe2Msg2 = probe2.receiveOne(100 milliseconds)
|
||||
assert(probe2Msg2.isInstanceOf[VehicleSpawnPad.PeriodicReminder])
|
||||
assert(probe2Msg2.asInstanceOf[VehicleSpawnPad.PeriodicReminder].reason == VehicleSpawnPad.Reminders.Blocked)
|
||||
|
||||
//if we move the vehicle more than 10m away from the pad, we should receive a second ConcealPlayer message
|
||||
//that means that the first order has cleared and the spawn pad is now working on the second order successfully
|
||||
vehicle.Position = Vector3(0,0,11)
|
||||
player.VehicleSeated = None //since shared between orders, is necessary
|
||||
val probe3Msg6 = probe3.receiveOne(4 seconds)
|
||||
assert(probe3Msg6.isInstanceOf[VehicleSpawnPad.ConcealPlayer])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleSpawnControl3Test extends ActorTest() {
|
||||
"VehicleSpawnControl" should {
|
||||
"not spawn a vehicle if player is dead" in {
|
||||
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")
|
||||
"player is on wrong continent before vehicle can partially load; vehicle is cleaned up" in {
|
||||
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
val probe1 = new TestProbe(system, "first-order")
|
||||
val probe3 = new TestProbe(system, "zone-events")
|
||||
zone.VehicleEvents = probe3.ref
|
||||
player.Continent = "problem" //problem
|
||||
|
||||
pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle)
|
||||
val reply = receiveOne(Duration.create(5000, "ms"))
|
||||
assert(reply == null)
|
||||
assert(vehicle.HasGUID)
|
||||
pad.Actor.tell(VehicleSpawnPad.VehicleOrder(player, vehicle), probe1.ref)
|
||||
|
||||
val probe3Msg1 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg1.isInstanceOf[VehicleSpawnPad.RevealPlayer])
|
||||
probe3.expectNoMsg(5 seconds)
|
||||
assert(!vehicle.HasGUID) //vehicle has been unregistered
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleSpawnControl4Test extends ActorTest() {
|
||||
"VehicleSpawnControl" should {
|
||||
"not spawn a vehicle if vehicle Actor is missing" in {
|
||||
val (player, pad) = VehicleSpawnPadControl.SetUpAgents(PlanetSideEmpire.TR)
|
||||
player.Spawn
|
||||
val vehicle = Vehicle(GlobalDefinitions.two_man_assault_buggy)
|
||||
vehicle.GUID = PlanetSideGUID(1)
|
||||
"the player is on wrong continent when the vehicle tries to load; vehicle is cleaned up" in {
|
||||
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
val probe1 = new TestProbe(system, "first-order")
|
||||
val probe3 = new TestProbe(system, "zone-events")
|
||||
zone.VehicleEvents = probe3.ref
|
||||
|
||||
pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle)
|
||||
val reply = receiveOne(Duration.create(5000, "ms"))
|
||||
assert(reply == null)
|
||||
pad.Actor.tell(VehicleSpawnPad.VehicleOrder(player, vehicle), probe1.ref)
|
||||
|
||||
val probe3Msg1 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg1.isInstanceOf[VehicleSpawnPad.ConcealPlayer])
|
||||
player.Continent = "problem" //problem
|
||||
assert(vehicle.HasGUID)
|
||||
|
||||
val probe3Msg2 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg2.isInstanceOf[VehicleSpawnPad.RevealPlayer])
|
||||
probe3.expectNoMsg(5 seconds)
|
||||
assert(!vehicle.HasGUID) //vehicle has been unregistered
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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, StructureType.Building)
|
||||
pad.Owner.Faction = faction
|
||||
(Player(Avatar("test", faction, CharacterGender.Male, 0, 0)), pad)
|
||||
class VehicleSpawnControl5aTest extends ActorTest() {
|
||||
"VehicleSpawnControl" should {
|
||||
"the vehicle is destroyed before being fully loaded; the vehicle is cleaned up" in {
|
||||
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
//we can recycle the vehicle and the player for each order
|
||||
val probe1 = new TestProbe(system, "first-order")
|
||||
val probe3 = new TestProbe(system, "zone-events")
|
||||
zone.VehicleEvents = probe3.ref
|
||||
|
||||
pad.Actor.tell(VehicleSpawnPad.VehicleOrder(player, vehicle), probe1.ref)
|
||||
|
||||
val probe3Msg1 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg1.isInstanceOf[VehicleSpawnPad.ConcealPlayer])
|
||||
|
||||
val probe3Msg2 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg2.isInstanceOf[VehicleSpawnPad.LoadVehicle])
|
||||
vehicle.Health = 0 //problem
|
||||
|
||||
val probe3Msg3 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg3.isInstanceOf[VehicleSpawnPad.DisposeVehicle])
|
||||
val probe3Msg4 = probe3.receiveOne(100 milliseconds)
|
||||
assert(probe3Msg4.isInstanceOf[VehicleSpawnPad.RevealPlayer])
|
||||
//note: the vehicle will not be unregistered by this logic alone
|
||||
//since LoadVehicle should introduce it into the game world properly, it has to be handled properly
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleSpawnControl5bTest extends ActorTest() {
|
||||
"VehicleSpawnControl" should {
|
||||
"player dies right after vehicle partially loads; the vehicle spawns and blocks the pad" in {
|
||||
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
//we can recycle the vehicle and the player for each order
|
||||
val probe1 = new TestProbe(system, "first-order")
|
||||
val probe3 = new TestProbe(system, "zone-events")
|
||||
zone.VehicleEvents = probe3.ref
|
||||
|
||||
pad.Actor.tell(VehicleSpawnPad.VehicleOrder(player, vehicle), probe1.ref)
|
||||
|
||||
val probe3Msg1 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg1.isInstanceOf[VehicleSpawnPad.ConcealPlayer])
|
||||
|
||||
val probe3Msg2 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg2.isInstanceOf[VehicleSpawnPad.LoadVehicle])
|
||||
player.Die //problem
|
||||
|
||||
val probe3Msg3 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg3.isInstanceOf[VehicleSpawnPad.AttachToRails])
|
||||
val probe3Msg4 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg4.isInstanceOf[VehicleSpawnPad.DetachFromRails])
|
||||
|
||||
val probe1Msg = probe1.receiveOne(10 seconds)
|
||||
assert(probe1Msg.isInstanceOf[VehicleSpawnPad.PeriodicReminder])
|
||||
assert(probe1Msg.asInstanceOf[VehicleSpawnPad.PeriodicReminder].reason == VehicleSpawnPad.Reminders.Blocked)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleSpawnControl6aTest extends ActorTest() {
|
||||
"VehicleSpawnControl" should {
|
||||
"the vehicle is destroyed while the player is sitting down; the vehicle is cleaned up" in {
|
||||
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
//we can recycle the vehicle and the player for each order
|
||||
val probe1 = new TestProbe(system, "first-order")
|
||||
val probe3 = new TestProbe(system, "zone-events")
|
||||
zone.VehicleEvents = probe3.ref
|
||||
|
||||
pad.Actor.tell(VehicleSpawnPad.VehicleOrder(player, vehicle), probe1.ref)
|
||||
|
||||
val probe3Msg1 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg1.isInstanceOf[VehicleSpawnPad.ConcealPlayer])
|
||||
|
||||
val probe3Msg2 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg2.isInstanceOf[VehicleSpawnPad.LoadVehicle])
|
||||
|
||||
val probe3Msg3 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg3.isInstanceOf[VehicleSpawnPad.AttachToRails])
|
||||
|
||||
val probe1Msg1 = probe1.receiveOne(200 milliseconds)
|
||||
assert(probe1Msg1.isInstanceOf[VehicleSpawnPad.StartPlayerSeatedInVehicle])
|
||||
vehicle.Health = 0 //problem
|
||||
|
||||
val probe3Msg5 = probe3.receiveOne(4 seconds)
|
||||
assert(probe3Msg5.isInstanceOf[VehicleSpawnPad.ResetSpawnPad])
|
||||
val probe3Msg6 = probe3.receiveOne(100 milliseconds)
|
||||
assert(probe3Msg6.isInstanceOf[VehicleSpawnPad.DisposeVehicle])
|
||||
val probe3Msg7 = probe3.receiveOne(100 milliseconds)
|
||||
assert(probe3Msg7.isInstanceOf[VehicleSpawnPad.RevealPlayer])
|
||||
//note: the vehicle will not be unregistered by this logic alone
|
||||
//since LoadVehicle should introduce it into the game world properly, it has to be handled properly
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO test was poor; attempting to check the "if(vehicle.Health ..." cases in VehicleSpawnControlSeatDriver
|
||||
//class VehicleSpawnControl6bTest extends ActorTest() {
|
||||
// "VehicleSpawnControl" should {
|
||||
// "player on wrong continent; the vehicle is then destroyed after being partially spawned, but is cleaned up" in {
|
||||
// val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
// //we can recycle the vehicle and the player for each order
|
||||
// val probe1 = new TestProbe(system, "first-order")
|
||||
// val probe3 = new TestProbe(system, "zone-events")
|
||||
// zone.VehicleEvents = probe3.ref
|
||||
//
|
||||
// pad.Actor.tell(VehicleSpawnPad.VehicleOrder(player, vehicle), probe1.ref)
|
||||
//
|
||||
// val probe3Msg1 = probe3.receiveOne(3 seconds)
|
||||
// assert(probe3Msg1.isInstanceOf[VehicleSpawnPad.ConcealPlayer])
|
||||
//
|
||||
// val probe3Msg2 = probe3.receiveOne(3 seconds)
|
||||
// assert(probe3Msg2.isInstanceOf[VehicleSpawnPad.LoadVehicle])
|
||||
//
|
||||
// val probe3Msg3 = probe3.receiveOne(3 seconds)
|
||||
// assert(probe3Msg3.isInstanceOf[VehicleSpawnPad.AttachToRails])
|
||||
//
|
||||
// val probe1Msg1 = probe1.receiveOne(200 milliseconds)
|
||||
// assert(probe1Msg1.isInstanceOf[VehicleSpawnPad.StartPlayerSeatedInVehicle])
|
||||
// player.Continent = "problem" //problem 1
|
||||
//
|
||||
// vehicle.Health = 0 //problem 2
|
||||
// val probe3Msg3b = probe3.receiveOne(3 seconds)
|
||||
// assert(probe3Msg3b.isInstanceOf[VehicleSpawnPad.DetachFromRails])
|
||||
//
|
||||
// val probe3Msg4 = probe3.receiveOne(3 seconds)
|
||||
// assert(probe3Msg4.isInstanceOf[VehicleSpawnPad.ResetSpawnPad])
|
||||
// val probe3Msg5 = probe3.receiveOne(1 seconds)
|
||||
// assert(probe3Msg5.isInstanceOf[VehicleSpawnPad.DisposeVehicle])
|
||||
// val probe3Msg6 = probe3.receiveOne(1 seconds)
|
||||
// assert(probe3Msg6.isInstanceOf[VehicleSpawnPad.RevealPlayer])
|
||||
// //note: the vehicle will not be unregistered by this logic alone
|
||||
// //since LoadVehicle should introduce it into the game world properly, it has to be handled properly
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
class VehicleSpawnControl6cTest extends ActorTest() {
|
||||
"VehicleSpawnControl" should {
|
||||
"the player can not sit in vehicle; vehicle spawns and blocks the pad" in {
|
||||
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
//we can recycle the vehicle and the player for each order
|
||||
val probe1 = new TestProbe(system, "first-order")
|
||||
val probe3 = new TestProbe(system, "zone-events")
|
||||
zone.VehicleEvents = probe3.ref
|
||||
|
||||
pad.Actor.tell(VehicleSpawnPad.VehicleOrder(player, vehicle), probe1.ref)
|
||||
|
||||
val probe3Msg1 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg1.isInstanceOf[VehicleSpawnPad.ConcealPlayer])
|
||||
|
||||
val probe3Msg2 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg2.isInstanceOf[VehicleSpawnPad.LoadVehicle])
|
||||
|
||||
val probe3Msg3 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg3.isInstanceOf[VehicleSpawnPad.AttachToRails])
|
||||
|
||||
val probe1Msg1 = probe1.receiveOne(200 milliseconds)
|
||||
assert(probe1Msg1.isInstanceOf[VehicleSpawnPad.StartPlayerSeatedInVehicle])
|
||||
player.Continent = "problem" //problem 1
|
||||
probe1.receiveOne(200 milliseconds) //Mountable.MountMessage
|
||||
|
||||
val probe3Msg4 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg4.isInstanceOf[VehicleSpawnPad.DetachFromRails])
|
||||
val probe3Msg5 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg5.isInstanceOf[VehicleSpawnPad.ResetSpawnPad])
|
||||
|
||||
val probe1Msg2 = probe1.receiveOne(10 seconds)
|
||||
assert(probe1Msg2.isInstanceOf[VehicleSpawnPad.PeriodicReminder])
|
||||
assert(probe1Msg2.asInstanceOf[VehicleSpawnPad.PeriodicReminder].reason == VehicleSpawnPad.Reminders.Blocked)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleSpawnControl7aTest extends ActorTest() {
|
||||
"VehicleSpawnControl" should {
|
||||
"the vehicle is destroyed while attached to the rails; it is cleaned up" in {
|
||||
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
//we can recycle the vehicle and the player for each order
|
||||
val probe1 = new TestProbe(system, "first-order")
|
||||
val probe3 = new TestProbe(system, "zone-events")
|
||||
zone.VehicleEvents = probe3.ref
|
||||
|
||||
pad.Actor.tell(VehicleSpawnPad.VehicleOrder(player, vehicle), probe1.ref)
|
||||
|
||||
val probe3Msg1 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg1.isInstanceOf[VehicleSpawnPad.ConcealPlayer])
|
||||
|
||||
val probe3Msg2 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg2.isInstanceOf[VehicleSpawnPad.LoadVehicle])
|
||||
|
||||
val probe3Msg3 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg3.isInstanceOf[VehicleSpawnPad.AttachToRails])
|
||||
|
||||
val probe1Msg1 = probe1.receiveOne(200 milliseconds)
|
||||
assert(probe1Msg1.isInstanceOf[VehicleSpawnPad.StartPlayerSeatedInVehicle])
|
||||
val probe1Msg2 = probe1.receiveOne(200 milliseconds)
|
||||
assert(probe1Msg2.isInstanceOf[Mountable.MountMessages])
|
||||
val probe1Msg2Contents = probe1Msg2.asInstanceOf[Mountable.MountMessages]
|
||||
assert(probe1Msg2Contents.response.isInstanceOf[Mountable.CanMount])
|
||||
val probe1Msg3 = probe1.receiveOne(3 seconds)
|
||||
assert(probe1Msg3.isInstanceOf[VehicleSpawnPad.PlayerSeatedInVehicle])
|
||||
vehicle.Health = 0 //problem
|
||||
|
||||
val probe3Msg4 = probe3.receiveOne(200 milliseconds)
|
||||
assert(probe3Msg4.isInstanceOf[VehicleSpawnPad.DetachFromRails])
|
||||
val probe3Msg5 = probe3.receiveOne(200 milliseconds)
|
||||
assert(probe3Msg5.isInstanceOf[VehicleSpawnPad.ResetSpawnPad])
|
||||
|
||||
probe1.receiveOne(200 milliseconds) //Mountable.MountMessage
|
||||
val probe1Msg4 = probe1.receiveOne(10 seconds)
|
||||
assert(probe1Msg4.isInstanceOf[VehicleSpawnPad.PeriodicReminder])
|
||||
assert(probe1Msg4.asInstanceOf[VehicleSpawnPad.PeriodicReminder].reason == VehicleSpawnPad.Reminders.Blocked)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleSpawnControl7bTest extends ActorTest() {
|
||||
"VehicleSpawnControl" should {
|
||||
"player dies after getting in driver seat; the vehicle blocks the pad" in {
|
||||
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
//we can recycle the vehicle and the player for each order
|
||||
val probe1 = new TestProbe(system, "first-order")
|
||||
val probe3 = new TestProbe(system, "zone-events")
|
||||
zone.VehicleEvents = probe3.ref
|
||||
|
||||
pad.Actor.tell(VehicleSpawnPad.VehicleOrder(player, vehicle), probe1.ref)
|
||||
|
||||
val probe3Msg1 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg1.isInstanceOf[VehicleSpawnPad.ConcealPlayer])
|
||||
|
||||
val probe3Msg2 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg2.isInstanceOf[VehicleSpawnPad.LoadVehicle])
|
||||
|
||||
val probe3Msg3 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg3.isInstanceOf[VehicleSpawnPad.AttachToRails])
|
||||
|
||||
val probe1Msg1 = probe1.receiveOne(200 milliseconds)
|
||||
assert(probe1Msg1.isInstanceOf[VehicleSpawnPad.StartPlayerSeatedInVehicle])
|
||||
val probe1Msg2 = probe1.receiveOne(200 milliseconds)
|
||||
assert(probe1Msg2.isInstanceOf[Mountable.MountMessages])
|
||||
val probe1Msg2Contents = probe1Msg2.asInstanceOf[Mountable.MountMessages]
|
||||
assert(probe1Msg2Contents.response.isInstanceOf[Mountable.CanMount])
|
||||
val probe1Msg3 = probe1.receiveOne(3 seconds)
|
||||
assert(probe1Msg3.isInstanceOf[VehicleSpawnPad.PlayerSeatedInVehicle])
|
||||
player.Die //problem
|
||||
|
||||
val probe3Msg4 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg4.isInstanceOf[VehicleSpawnPad.DetachFromRails])
|
||||
val probe3Msg5 = probe3.receiveOne(100 milliseconds)
|
||||
assert(probe3Msg5.isInstanceOf[VehicleSpawnPad.ResetSpawnPad])
|
||||
|
||||
val probe1Msg4 = probe1.receiveOne(10 seconds)
|
||||
assert(probe1Msg4.isInstanceOf[VehicleSpawnPad.PeriodicReminder])
|
||||
assert(probe1Msg4.asInstanceOf[VehicleSpawnPad.PeriodicReminder].reason == VehicleSpawnPad.Reminders.Blocked)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object VehicleSpawnPadControlTest {
|
||||
import net.psforever.objects.zones.ZoneMap
|
||||
private val map = new ZoneMap("test-map")
|
||||
|
||||
def SetUpAgents(faction : PlanetSideEmpire.Value)(implicit system : ActorSystem) : (Vehicle, Player, VehicleSpawnPad, Zone) = {
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
import net.psforever.objects.guid.source.LimitedNumberSource
|
||||
import net.psforever.objects.serverobject.structures.Building
|
||||
import net.psforever.objects.vehicles.VehicleControl
|
||||
import net.psforever.objects.zones.ZoneActor
|
||||
import net.psforever.objects.Tool
|
||||
import net.psforever.types.CharacterGender
|
||||
|
||||
val zone = new Zone("test-zone", map, 0)
|
||||
val vehicle = Vehicle(GlobalDefinitions.two_man_assault_buggy)
|
||||
val weapon = vehicle.WeaponControlledFromSeat(1).get.asInstanceOf[Tool]
|
||||
val guid : NumberPoolHub = new NumberPoolHub(LimitedNumberSource(3))
|
||||
guid.AddPool("test-pool", (0 to 2).toList)
|
||||
guid.register(vehicle, "test-pool")
|
||||
guid.register(weapon, "test-pool")
|
||||
guid.register(weapon.AmmoSlot.Box, "test-pool")
|
||||
zone.GUID(guid)
|
||||
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), s"test-zone-${System.nanoTime()}")
|
||||
zone.Actor ! Zone.Init()
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), s"vehicle-control-${System.nanoTime()}")
|
||||
|
||||
val pad = VehicleSpawnPad(GlobalDefinitions.spawn_pad)
|
||||
pad.Actor = system.actorOf(Props(classOf[VehicleSpawnControl], pad), s"test-pad-${System.nanoTime()}")
|
||||
pad.Owner = new Building(0, zone, StructureType.Building)
|
||||
pad.Owner.Faction = faction
|
||||
val player = Player(Avatar("test", faction, CharacterGender.Male, 0, 0))
|
||||
player.GUID = PlanetSideGUID(10)
|
||||
player.Continent = zone.Id
|
||||
player.Spawn
|
||||
//note: pad and vehicle are both at Vector3(0,0,0) so they count as blocking
|
||||
(vehicle, player, pad, zone)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1025,9 +1025,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
|
||||
case VehicleSpawnPad.StartPlayerSeatedInVehicle(vehicle, pad) =>
|
||||
val vehicle_guid = vehicle.GUID
|
||||
if(pad.Railed) {
|
||||
sendResponse(ObjectAttachMessage(pad.GUID, vehicle_guid, 3))
|
||||
}
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, 22, 1L)) //mount points off?
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, 21, player.GUID.guid)) //fte and ownership?
|
||||
|
||||
|
|
@ -1053,7 +1050,13 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
sendResponse(GenericObjectActionMessage(pad.GUID, 92)) //reset spawn pad
|
||||
sendResponse(ServerVehicleOverrideMsg.Auto(vehicle.Definition.AutoPilotSpeed2))
|
||||
|
||||
case VehicleSpawnPad.PeriodicReminder(msg) =>
|
||||
case VehicleSpawnPad.PeriodicReminder(cause, data) =>
|
||||
val msg : String = (cause match {
|
||||
case VehicleSpawnPad.Reminders.Blocked =>
|
||||
s"The vehicle spawn where you placed your order is blocked. ${data.getOrElse("")}"
|
||||
case VehicleSpawnPad.Reminders.Queue =>
|
||||
s"Your position in the vehicle spawn queue is ${data.get}."
|
||||
})
|
||||
sendResponse(ChatMsg(ChatMessageType.CMT_OPEN, true, "", msg, None))
|
||||
|
||||
case ListAccountCharacters =>
|
||||
|
|
|
|||
|
|
@ -81,11 +81,7 @@ class DeconstructionActor extends Actor {
|
|||
vehiclesToScrap.foreach(entry => {
|
||||
val vehicle = entry.vehicle
|
||||
val zone = entry.zone
|
||||
<<<<<<< 18a068c10272376450c412425118c86612af7397
|
||||
vehicle.Position = Vector3.Zero //somewhere it will not disturb anything
|
||||
=======
|
||||
vehicle.Position = Vector3.Zero
|
||||
>>>>>>> Splitting single vehicle spawn control process into several subtasks with their own control Actor objects. Importing SouNourS copy of ServerVehicleOverrideMessage packet and tests.
|
||||
entry.zone.Transport ! Zone.Vehicle.Despawn(vehicle)
|
||||
context.parent ! DeconstructionActor.DeleteVehicle(vehicle.GUID, zone.Id) //call up to the main event system
|
||||
taskResolver ! DeconstructionTask(vehicle, zone)
|
||||
|
|
|
|||
Loading…
Reference in a new issue