mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-15 08:24:39 +00:00
Merge pull request #200 from Fate-JH/decon-repair
Deconstruction Repair
This commit is contained in:
commit
7ddd0214fe
4 changed files with 144 additions and 57 deletions
|
|
@ -127,9 +127,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
continent.Population ! Zone.Population.Release(avatar)
|
continent.Population ! Zone.Population.Release(avatar)
|
||||||
player.VehicleSeated match {
|
player.VehicleSeated match {
|
||||||
case None =>
|
case None =>
|
||||||
continent.Population ! Zone.Corpse.Add(player)
|
|
||||||
FriskCorpse(player) //TODO eliminate dead letters
|
FriskCorpse(player) //TODO eliminate dead letters
|
||||||
if(!WellLootedCorpse(player)) {
|
if(!WellLootedCorpse(player)) {
|
||||||
|
continent.Population ! Zone.Corpse.Add(player)
|
||||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.Release(player, continent))
|
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.Release(player, continent))
|
||||||
taskResolver ! GUIDTask.UnregisterLocker(player.Locker)(continent.GUID) //rest of player will be cleaned up with corpses
|
taskResolver ! GUIDTask.UnregisterLocker(player.Locker)(continent.GUID) //rest of player will be cleaned up with corpses
|
||||||
}
|
}
|
||||||
|
|
@ -304,6 +304,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
|
|
||||||
case AvatarResponse.ObjectDelete(item_guid, unk) =>
|
case AvatarResponse.ObjectDelete(item_guid, unk) =>
|
||||||
if(tplayer_guid != guid) {
|
if(tplayer_guid != guid) {
|
||||||
|
log.info(s"Made to delete item $item_guid")
|
||||||
sendResponse(ObjectDeleteMessage(item_guid, unk))
|
sendResponse(ObjectDeleteMessage(item_guid, unk))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1601,10 +1602,10 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
continent.Population ! Zone.Population.Release(avatar)
|
continent.Population ! Zone.Population.Release(avatar)
|
||||||
player.VehicleSeated match {
|
player.VehicleSeated match {
|
||||||
case None =>
|
case None =>
|
||||||
continent.Population ! Zone.Corpse.Add(player) //TODO move back out of this match case when changing below issue
|
|
||||||
FriskCorpse(player)
|
FriskCorpse(player)
|
||||||
if(!WellLootedCorpse(player)) {
|
if(!WellLootedCorpse(player)) {
|
||||||
TurnPlayerIntoCorpse(player)
|
TurnPlayerIntoCorpse(player)
|
||||||
|
continent.Population ! Zone.Corpse.Add(player) //TODO move back out of this match case when changing below issue
|
||||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.Release(player, continent))
|
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.Release(player, continent))
|
||||||
}
|
}
|
||||||
else { //no items in inventory; leave no corpse
|
else { //no items in inventory; leave no corpse
|
||||||
|
|
|
||||||
|
|
@ -15,17 +15,26 @@ import scala.concurrent.duration._
|
||||||
|
|
||||||
class CorpseRemovalActor extends Actor {
|
class CorpseRemovalActor extends Actor {
|
||||||
private var burial : Cancellable = DefaultCancellable.obj
|
private var burial : Cancellable = DefaultCancellable.obj
|
||||||
|
|
||||||
private var corpses : List[CorpseRemovalActor.Entry] = List()
|
private var corpses : List[CorpseRemovalActor.Entry] = List()
|
||||||
|
|
||||||
|
private var decomposition : Cancellable = DefaultCancellable.obj
|
||||||
|
private var buriedCorpses : List[CorpseRemovalActor.Entry] = List()
|
||||||
|
|
||||||
private var taskResolver : ActorRef = Actor.noSender
|
private var taskResolver : ActorRef = Actor.noSender
|
||||||
|
|
||||||
private[this] val log = org.log4s.getLogger
|
private[this] val log = org.log4s.getLogger
|
||||||
|
|
||||||
override def postStop() = {
|
override def postStop() = {
|
||||||
//Cart Master: See you on Thursday.
|
//Cart Master: See you on Thursday.
|
||||||
corpses.foreach { BurialTask }
|
super.postStop()
|
||||||
corpses = Nil
|
burial.cancel
|
||||||
|
decomposition.cancel
|
||||||
|
|
||||||
|
corpses.foreach(corpse => {
|
||||||
|
BurialTask(corpse)
|
||||||
|
LastRitesTask(corpse)
|
||||||
|
})
|
||||||
|
buriedCorpses.foreach { LastRitesTask }
|
||||||
}
|
}
|
||||||
|
|
||||||
def receive : Receive = {
|
def receive : Receive = {
|
||||||
|
|
@ -42,7 +51,7 @@ class CorpseRemovalActor extends Actor {
|
||||||
|
|
||||||
def Processing : Receive = {
|
def Processing : Receive = {
|
||||||
case CorpseRemovalActor.AddCorpse(corpse, zone, time) =>
|
case CorpseRemovalActor.AddCorpse(corpse, zone, time) =>
|
||||||
if(corpse.isBackpack) {
|
if(corpse.isBackpack && !buriedCorpses.exists(_.corpse == corpse)) {
|
||||||
if(corpses.isEmpty) {
|
if(corpses.isEmpty) {
|
||||||
//we were the only entry so the event must be started from scratch
|
//we were the only entry so the event must be started from scratch
|
||||||
corpses = List(CorpseRemovalActor.Entry(corpse, zone, time))
|
corpses = List(CorpseRemovalActor.Entry(corpse, zone, time))
|
||||||
|
|
@ -51,9 +60,11 @@ class CorpseRemovalActor extends Actor {
|
||||||
else {
|
else {
|
||||||
//unknown number of entries; append, sort, then re-time tasking
|
//unknown number of entries; append, sort, then re-time tasking
|
||||||
val oldHead = corpses.head
|
val oldHead = corpses.head
|
||||||
corpses = (corpses :+ CorpseRemovalActor.Entry(corpse, zone, time)).sortBy(_.timeAlive)
|
if(!corpses.exists(_.corpse == corpse)) {
|
||||||
if(oldHead != corpses.head) {
|
corpses = (corpses :+ CorpseRemovalActor.Entry(corpse, zone, time)).sortBy(_.timeAlive)
|
||||||
RetimeFirstTask()
|
if(oldHead != corpses.head) {
|
||||||
|
RetimeFirstTask()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -72,42 +83,66 @@ class CorpseRemovalActor extends Actor {
|
||||||
CorpseRemovalActor.recursiveFindCorpse(corpses.iterator, targets.head) match {
|
CorpseRemovalActor.recursiveFindCorpse(corpses.iterator, targets.head) match {
|
||||||
case None => ;
|
case None => ;
|
||||||
case Some(index) =>
|
case Some(index) =>
|
||||||
|
decomposition.cancel
|
||||||
BurialTask(corpses(index))
|
BurialTask(corpses(index))
|
||||||
|
buriedCorpses = buriedCorpses :+ corpses(index)
|
||||||
corpses = corpses.take(index) ++ corpses.drop(index+1)
|
corpses = corpses.take(index) ++ corpses.drop(index+1)
|
||||||
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
|
decomposition = context.system.scheduler.scheduleOnce(500 milliseconds, self, CorpseRemovalActor.TryDelete())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log.debug(s"multiple target corpses submitted for early cleanup: $targets")
|
log.debug(s"multiple target corpses submitted for early cleanup: $targets")
|
||||||
|
decomposition.cancel
|
||||||
//cumbersome partition
|
//cumbersome partition
|
||||||
//a - find targets from corpses
|
//a - find targets from corpses
|
||||||
(for {
|
val locatedTargets = for {
|
||||||
a <- targets
|
a <- targets
|
||||||
b <- corpses
|
b <- corpses
|
||||||
if b.corpse == a &&
|
if b.corpse == a &&
|
||||||
b.corpse.Continent.equals(a.Continent) &&
|
b.corpse.Continent.equals(a.Continent) &&
|
||||||
b.corpse.HasGUID && a.HasGUID && b.corpse.GUID == a.GUID
|
b.corpse.HasGUID && a.HasGUID && b.corpse.GUID == a.GUID
|
||||||
} yield b).foreach { BurialTask }
|
} yield b
|
||||||
//b - corpses after the found targets are
|
locatedTargets.foreach { BurialTask }
|
||||||
//removed (note: cull any non-GUID entries while at it)
|
buriedCorpses = locatedTargets ++ buriedCorpses
|
||||||
|
//b - corpses, after the found targets are removed (cull any non-GUID entries while at it)
|
||||||
corpses = (for {
|
corpses = (for {
|
||||||
a <- targets
|
a <- locatedTargets.map { _.corpse }
|
||||||
b <- corpses
|
b <- corpses
|
||||||
if b.corpse.HasGUID && a.HasGUID &&
|
if b.corpse.HasGUID && a.HasGUID &&
|
||||||
(b.corpse != a ||
|
(b.corpse != a ||
|
||||||
!b.corpse.Continent.equals(a.Continent) ||
|
!b.corpse.Continent.equals(a.Continent) ||
|
||||||
!b.corpse.HasGUID || !a.HasGUID || b.corpse.GUID != a.GUID)
|
!b.corpse.HasGUID || !a.HasGUID || b.corpse.GUID != a.GUID)
|
||||||
} yield b).sortBy(_.timeAlive)
|
} yield b).sortBy(_.timeAlive)
|
||||||
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
|
decomposition = context.system.scheduler.scheduleOnce(500 milliseconds, self, CorpseRemovalActor.TryDelete())
|
||||||
}
|
}
|
||||||
RetimeFirstTask()
|
RetimeFirstTask()
|
||||||
}
|
}
|
||||||
|
|
||||||
case CorpseRemovalActor.Dispose() =>
|
case CorpseRemovalActor.StartDelete() =>
|
||||||
burial.cancel
|
burial.cancel
|
||||||
|
decomposition.cancel
|
||||||
val now : Long = System.nanoTime
|
val now : Long = System.nanoTime
|
||||||
val (buried, rotting) = corpses.partition(entry => { now - entry.time >= entry.timeAlive })
|
val (buried, rotting) = corpses.partition(entry => { now - entry.time >= entry.timeAlive })
|
||||||
corpses = rotting
|
corpses = rotting
|
||||||
|
buriedCorpses = buriedCorpses ++ buried
|
||||||
buried.foreach { BurialTask }
|
buried.foreach { BurialTask }
|
||||||
RetimeFirstTask()
|
RetimeFirstTask()
|
||||||
|
if(buriedCorpses.nonEmpty) {
|
||||||
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
|
burial = context.system.scheduler.scheduleOnce(500 milliseconds, self, CorpseRemovalActor.TryDelete())
|
||||||
|
}
|
||||||
|
|
||||||
|
case CorpseRemovalActor.TryDelete() =>
|
||||||
|
decomposition.cancel
|
||||||
|
val (decomposed, rotting) = buriedCorpses.partition(entry => { !entry.zone.Corpses.contains(entry.corpse) })
|
||||||
|
buriedCorpses = rotting
|
||||||
|
decomposed.foreach { LastRitesTask }
|
||||||
|
if(rotting.nonEmpty) {
|
||||||
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
|
decomposition = context.system.scheduler.scheduleOnce(500 milliseconds, self, CorpseRemovalActor.TryDelete())
|
||||||
|
}
|
||||||
|
|
||||||
case CorpseRemovalActor.FailureToWork(target, zone, ex) =>
|
case CorpseRemovalActor.FailureToWork(target, zone, ex) =>
|
||||||
//Cart Master: Oh, I can't take him like that. It's against regulations.
|
//Cart Master: Oh, I can't take him like that. It's against regulations.
|
||||||
|
|
@ -122,21 +157,24 @@ class CorpseRemovalActor extends Actor {
|
||||||
if(corpses.nonEmpty) {
|
if(corpses.nonEmpty) {
|
||||||
val short_timeout : FiniteDuration = math.max(1, corpses.head.timeAlive - (now - corpses.head.time)) nanoseconds
|
val short_timeout : FiniteDuration = math.max(1, corpses.head.timeAlive - (now - corpses.head.time)) nanoseconds
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
burial = context.system.scheduler.scheduleOnce(short_timeout, self, CorpseRemovalActor.Dispose())
|
burial = context.system.scheduler.scheduleOnce(short_timeout, self, CorpseRemovalActor.StartDelete())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def BurialTask(entry : CorpseRemovalActor.Entry) : Unit = {
|
def BurialTask(entry : CorpseRemovalActor.Entry) : Unit = {
|
||||||
//Cart master: Nine pence.
|
|
||||||
val target = entry.corpse
|
val target = entry.corpse
|
||||||
val zone = entry.zone
|
|
||||||
target.Position = Vector3.Zero //somewhere it will not disturb anything
|
|
||||||
entry.zone.Population ! Zone.Corpse.Remove(target)
|
entry.zone.Population ! Zone.Corpse.Remove(target)
|
||||||
context.parent ! AvatarServiceMessage(zone.Id, AvatarAction.ObjectDelete(Service.defaultPlayerGUID, target.GUID))
|
context.parent ! AvatarServiceMessage(entry.zone.Id, AvatarAction.ObjectDelete(Service.defaultPlayerGUID, target.GUID))
|
||||||
taskResolver ! BurialTask(target, zone)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def BurialTask(corpse : Player, zone : Zone) : TaskResolver.GiveTask = {
|
def LastRitesTask(entry : CorpseRemovalActor.Entry) : Unit = {
|
||||||
|
//Cart master: Nine pence.
|
||||||
|
val target = entry.corpse
|
||||||
|
target.Position = Vector3.Zero //somewhere it will not disturb anything
|
||||||
|
taskResolver ! LastRitesTask(target, entry.zone)
|
||||||
|
}
|
||||||
|
|
||||||
|
def LastRitesTask(corpse : Player, zone : Zone) : TaskResolver.GiveTask = {
|
||||||
import net.psforever.objects.guid.{GUIDTask, Task}
|
import net.psforever.objects.guid.{GUIDTask, Task}
|
||||||
TaskResolver.GiveTask (
|
TaskResolver.GiveTask (
|
||||||
new Task() {
|
new Task() {
|
||||||
|
|
@ -170,9 +208,11 @@ object CorpseRemovalActor {
|
||||||
|
|
||||||
final case class Entry(corpse : Player, zone : Zone, timeAlive : Long = CorpseRemovalActor.time, time : Long = System.nanoTime())
|
final case class Entry(corpse : Player, zone : Zone, timeAlive : Long = CorpseRemovalActor.time, time : Long = System.nanoTime())
|
||||||
|
|
||||||
final case class FailureToWork(corpse : Player, zone : Zone, ex : Throwable)
|
private final case class FailureToWork(corpse : Player, zone : Zone, ex : Throwable)
|
||||||
|
|
||||||
final case class Dispose()
|
private final case class StartDelete()
|
||||||
|
|
||||||
|
private final case class TryDelete()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A recursive function that finds and removes a specific player from a list of players.
|
* A recursive function that finds and removes a specific player from a list of players.
|
||||||
|
|
|
||||||
|
|
@ -30,10 +30,25 @@ class DeconstructionActor extends Actor {
|
||||||
private var scrappingProcess : Cancellable = DefaultCancellable.obj
|
private var scrappingProcess : Cancellable = DefaultCancellable.obj
|
||||||
/** A `List` of currently doomed vehicles */
|
/** A `List` of currently doomed vehicles */
|
||||||
private var vehicles : List[DeconstructionActor.VehicleEntry] = Nil
|
private var vehicles : List[DeconstructionActor.VehicleEntry] = Nil
|
||||||
|
/** The periodic `Executor` that cleans up the next vehicle on the list */
|
||||||
|
private var heapEmptyProcess : Cancellable = DefaultCancellable.obj
|
||||||
|
/** A `List` of vehicles that have been removed from the game world and are awaiting deconstruction. */
|
||||||
|
private var vehicleScrapHeap : List[DeconstructionActor.VehicleEntry] = Nil
|
||||||
/** The manager that helps unregister the vehicle from its current GUID scope */
|
/** The manager that helps unregister the vehicle from its current GUID scope */
|
||||||
private var taskResolver : ActorRef = Actor.noSender
|
private var taskResolver : ActorRef = Actor.noSender
|
||||||
//private[this] val log = org.log4s.getLogger
|
//private[this] val log = org.log4s.getLogger
|
||||||
|
|
||||||
|
override def postStop() : Unit = {
|
||||||
|
super.postStop()
|
||||||
|
scrappingProcess.cancel
|
||||||
|
heapEmptyProcess.cancel
|
||||||
|
|
||||||
|
vehicles.foreach(entry => {
|
||||||
|
RetirementTask(entry)
|
||||||
|
DestructionTask(entry)
|
||||||
|
})
|
||||||
|
vehicleScrapHeap.foreach { DestructionTask }
|
||||||
|
}
|
||||||
|
|
||||||
def receive : Receive = {
|
def receive : Receive = {
|
||||||
/*
|
/*
|
||||||
|
|
@ -52,45 +67,56 @@ class DeconstructionActor extends Actor {
|
||||||
|
|
||||||
def Processing : Receive = {
|
def Processing : Receive = {
|
||||||
case DeconstructionActor.RequestDeleteVehicle(vehicle, zone, time) =>
|
case DeconstructionActor.RequestDeleteVehicle(vehicle, zone, time) =>
|
||||||
vehicles = vehicles :+ DeconstructionActor.VehicleEntry(vehicle, zone, time)
|
if(!vehicles.exists(_.vehicle == vehicle) && !vehicleScrapHeap.exists(_.vehicle == vehicle)) {
|
||||||
vehicle.Actor ! Vehicle.PrepareForDeletion
|
vehicles = vehicles :+ DeconstructionActor.VehicleEntry(vehicle, zone, time)
|
||||||
//kick everyone out; this is a no-blocking manual form of MountableBehavior ! Mountable.TryDismount
|
vehicle.Actor ! Vehicle.PrepareForDeletion
|
||||||
vehicle.Definition.MountPoints.values.foreach(seat_num => {
|
//kick everyone out; this is a no-blocking manual form of MountableBehavior ! Mountable.TryDismount
|
||||||
val zone_id : String = zone.Id
|
vehicle.Definition.MountPoints.values.foreach(seat_num => {
|
||||||
val seat : Seat = vehicle.Seat(seat_num).get
|
val zone_id : String = zone.Id
|
||||||
seat.Occupant match {
|
val seat : Seat = vehicle.Seat(seat_num).get
|
||||||
case Some(tplayer) =>
|
seat.Occupant match {
|
||||||
seat.Occupant = None
|
case Some(tplayer) =>
|
||||||
tplayer.VehicleSeated = None
|
seat.Occupant = None
|
||||||
if(tplayer.HasGUID) {
|
tplayer.VehicleSeated = None
|
||||||
context.parent ! VehicleServiceMessage(zone_id, VehicleAction.KickPassenger(tplayer.GUID, 4, false, vehicle.GUID))
|
if(tplayer.HasGUID) {
|
||||||
}
|
context.parent ! VehicleServiceMessage(zone_id, VehicleAction.KickPassenger(tplayer.GUID, 4, false, vehicle.GUID))
|
||||||
case None => ;
|
}
|
||||||
|
case None => ;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if(vehicles.size == 1) {
|
||||||
|
//we were the only entry so the event must be started from scratch
|
||||||
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
|
scrappingProcess = context.system.scheduler.scheduleOnce(DeconstructionActor.timeout, self, DeconstructionActor.StartDeleteVehicle())
|
||||||
}
|
}
|
||||||
})
|
|
||||||
if(vehicles.size == 1) { //we were the only entry so the event must be started from scratch
|
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
|
||||||
scrappingProcess = context.system.scheduler.scheduleOnce(DeconstructionActor.timeout, self, DeconstructionActor.TryDeleteVehicle())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case DeconstructionActor.TryDeleteVehicle() =>
|
case DeconstructionActor.StartDeleteVehicle() =>
|
||||||
scrappingProcess.cancel
|
scrappingProcess.cancel
|
||||||
|
heapEmptyProcess.cancel
|
||||||
val now : Long = System.nanoTime
|
val now : Long = System.nanoTime
|
||||||
val (vehiclesToScrap, vehiclesRemain) = PartitionEntries(vehicles, now)
|
val (vehiclesToScrap, vehiclesRemain) = PartitionEntries(vehicles, now)
|
||||||
vehicles = vehiclesRemain
|
vehicles = vehiclesRemain //entries from original list before partition
|
||||||
vehiclesToScrap.foreach(entry => {
|
vehicleScrapHeap = vehicleScrapHeap ++ vehiclesToScrap //may include existing entries
|
||||||
val vehicle = entry.vehicle
|
vehiclesToScrap.foreach { RetirementTask }
|
||||||
val zone = entry.zone
|
|
||||||
vehicle.Position = Vector3.Zero //somewhere it will not disturb anything
|
|
||||||
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)
|
|
||||||
})
|
|
||||||
|
|
||||||
if(vehiclesRemain.nonEmpty) {
|
if(vehiclesRemain.nonEmpty) {
|
||||||
val short_timeout : FiniteDuration = math.max(1, DeconstructionActor.timeout_time - (now - vehiclesRemain.head.time)) nanoseconds
|
val short_timeout : FiniteDuration = math.max(1, DeconstructionActor.timeout_time - (now - vehiclesRemain.head.time)) nanoseconds
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
scrappingProcess = context.system.scheduler.scheduleOnce(short_timeout, self, DeconstructionActor.TryDeleteVehicle())
|
scrappingProcess = context.system.scheduler.scheduleOnce(short_timeout, self, DeconstructionActor.StartDeleteVehicle())
|
||||||
|
}
|
||||||
|
if(vehicleScrapHeap.nonEmpty) {
|
||||||
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
|
heapEmptyProcess = context.system.scheduler.scheduleOnce(500 milliseconds, self, DeconstructionActor.TryDeleteVehicle())
|
||||||
|
}
|
||||||
|
|
||||||
|
case DeconstructionActor.TryDeleteVehicle() =>
|
||||||
|
heapEmptyProcess.cancel
|
||||||
|
val (vehiclesToScrap, vehiclesRemain) = vehicleScrapHeap.partition(entry => !entry.zone.Vehicles.contains(entry.vehicle))
|
||||||
|
vehicleScrapHeap = vehiclesRemain
|
||||||
|
vehiclesToScrap.foreach { DestructionTask }
|
||||||
|
if(vehiclesRemain.nonEmpty) {
|
||||||
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
|
heapEmptyProcess = context.system.scheduler.scheduleOnce(500 milliseconds, self, DeconstructionActor.TryDeleteVehicle())
|
||||||
}
|
}
|
||||||
|
|
||||||
case DeconstructionActor.FailureToDeleteVehicle(localVehicle, localZone, ex) =>
|
case DeconstructionActor.FailureToDeleteVehicle(localVehicle, localZone, ex) =>
|
||||||
|
|
@ -99,6 +125,20 @@ class DeconstructionActor extends Actor {
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def RetirementTask(entry : DeconstructionActor.VehicleEntry) : Unit = {
|
||||||
|
val vehicle = entry.vehicle
|
||||||
|
val zone = entry.zone
|
||||||
|
zone.Transport ! Zone.Vehicle.Despawn(vehicle)
|
||||||
|
context.parent ! DeconstructionActor.DeleteVehicle(vehicle.GUID, zone.Id) //call up to the main event system
|
||||||
|
}
|
||||||
|
|
||||||
|
def DestructionTask(entry : DeconstructionActor.VehicleEntry) : Unit = {
|
||||||
|
val vehicle = entry.vehicle
|
||||||
|
val zone = entry.zone
|
||||||
|
vehicle.Position = Vector3.Zero //somewhere it will not disturb anything
|
||||||
|
taskResolver ! DeconstructionTask(vehicle, zone)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a middleman `Task` intended to return error messages to the `DeconstructionActor`.
|
* Construct a middleman `Task` intended to return error messages to the `DeconstructionActor`.
|
||||||
* @param vehicle the `Vehicle` object
|
* @param vehicle the `Vehicle` object
|
||||||
|
|
@ -195,6 +235,12 @@ object DeconstructionActor {
|
||||||
final case class DeleteVehicle(vehicle_guid : PlanetSideGUID, zone_id : String)
|
final case class DeleteVehicle(vehicle_guid : PlanetSideGUID, zone_id : String)
|
||||||
/**
|
/**
|
||||||
* Internal message used to signal a test of the queued vehicle information.
|
* Internal message used to signal a test of the queued vehicle information.
|
||||||
|
* Remove all deconstructing vehicles from the game world.
|
||||||
|
*/
|
||||||
|
private final case class StartDeleteVehicle()
|
||||||
|
/**
|
||||||
|
* Internal message used to signal a test of the queued vehicle information.
|
||||||
|
* Remove all deconstructing vehicles from the zone's globally unique identifier system.
|
||||||
*/
|
*/
|
||||||
private final case class TryDeleteVehicle()
|
private final case class TryDeleteVehicle()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -329,7 +329,7 @@ class AvatarReleaseTest extends ActorTest {
|
||||||
assert(reply2msg.replyMessage.isInstanceOf[AvatarResponse.ObjectDelete])
|
assert(reply2msg.replyMessage.isInstanceOf[AvatarResponse.ObjectDelete])
|
||||||
assert(reply2msg.replyMessage.asInstanceOf[AvatarResponse.ObjectDelete].item_guid == guid)
|
assert(reply2msg.replyMessage.asInstanceOf[AvatarResponse.ObjectDelete].item_guid == guid)
|
||||||
|
|
||||||
expectNoMsg(200 milliseconds)
|
expectNoMsg(1000 milliseconds)
|
||||||
assert(zone.Corpses.isEmpty)
|
assert(zone.Corpses.isEmpty)
|
||||||
assert(!obj.HasGUID)
|
assert(!obj.HasGUID)
|
||||||
}
|
}
|
||||||
|
|
@ -379,7 +379,7 @@ class AvatarReleaseEarly1Test extends ActorTest {
|
||||||
assert(reply2msg.replyMessage.isInstanceOf[AvatarResponse.ObjectDelete])
|
assert(reply2msg.replyMessage.isInstanceOf[AvatarResponse.ObjectDelete])
|
||||||
assert(reply2msg.replyMessage.asInstanceOf[AvatarResponse.ObjectDelete].item_guid == guid)
|
assert(reply2msg.replyMessage.asInstanceOf[AvatarResponse.ObjectDelete].item_guid == guid)
|
||||||
|
|
||||||
expectNoMsg(200 milliseconds)
|
expectNoMsg(600 milliseconds)
|
||||||
assert(zone.Corpses.isEmpty)
|
assert(zone.Corpses.isEmpty)
|
||||||
assert(!obj.HasGUID)
|
assert(!obj.HasGUID)
|
||||||
}
|
}
|
||||||
|
|
@ -430,7 +430,7 @@ class AvatarReleaseEarly2Test extends ActorTest {
|
||||||
assert(reply2msg.replyMessage.isInstanceOf[AvatarResponse.ObjectDelete])
|
assert(reply2msg.replyMessage.isInstanceOf[AvatarResponse.ObjectDelete])
|
||||||
assert(reply2msg.replyMessage.asInstanceOf[AvatarResponse.ObjectDelete].item_guid == guid)
|
assert(reply2msg.replyMessage.asInstanceOf[AvatarResponse.ObjectDelete].item_guid == guid)
|
||||||
|
|
||||||
expectNoMsg(200 milliseconds)
|
expectNoMsg(600 milliseconds)
|
||||||
assert(zone.Corpses.isEmpty)
|
assert(zone.Corpses.isEmpty)
|
||||||
assert(!obj.HasGUID)
|
assert(!obj.HasGUID)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue