each zone now has access to its own bundle of task resolver objects; primary changes to reflect this has been the simplification of item moving parameters; tests corrected

This commit is contained in:
Jason_DiDonato@yahoo.com 2020-10-10 09:16:56 -04:00
parent 4fc1788e95
commit 69b3a8a4bf
26 changed files with 277 additions and 367 deletions

View file

@ -8,7 +8,6 @@ import java.util.UUID.randomUUID
import akka.actor.ActorSystem
import akka.actor.typed.ActorRef
import akka.actor.typed.scaladsl.Behaviors
import akka.routing.RandomPool
import akka.{actor => classic}
import ch.qos.logback.classic.LoggerContext
import ch.qos.logback.classic.joran.JoranConfigurator
@ -19,7 +18,6 @@ import net.psforever.actors.session.SessionActor
import net.psforever.login.psadmin.PsAdminActor
import net.psforever.login._
import net.psforever.objects.Default
import net.psforever.objects.guid.TaskResolver
import net.psforever.objects.zones._
import net.psforever.services.account.{AccountIntermediaryService, AccountPersistenceService}
import net.psforever.services.chat.ChatService
@ -122,7 +120,6 @@ object Server {
val serviceManager = ServiceManager.boot
serviceManager ! ServiceManager.Register(classic.Props[AccountIntermediaryService](), "accountIntermediary")
serviceManager ! ServiceManager.Register(RandomPool(150).props(classic.Props[TaskResolver]()), "taskResolver")
serviceManager ! ServiceManager.Register(classic.Props[GalaxyService](), "galaxy")
serviceManager ! ServiceManager.Register(classic.Props[SquadService](), "squad")
serviceManager ! ServiceManager.Register(classic.Props[AccountPersistenceService](), "accountPersistence")

View file

@ -0,0 +1,54 @@
// Copyright (c) 2020 PSForever
package actor.base
import akka.actor.{Actor, ActorContext, ActorRef, Props}
import akka.pattern.ask
import akka.util.Timeout
import scala.concurrent.Await
import scala.concurrent.duration._
/**
* Create an `ActorTest` environment that has an `ActorContext` object.
*/
abstract class FreedContextActorTest extends ActorTest {
/*
Never do this in actual production code!
ActorSystem and ActorContext offer similar mechanisms for instantiating actors.
This is a consequence of their shared inheritance of the ActorRefFactory trait.
They are not equivalent enough to be able to pass one as the other as a parameter.
Because the ActorSystem has no context of its own,
various bizarre mechanisms have to be developed to use any methods that would pass in a context object.
We create a middleman Actor whose main purpose is to surrender its context object to the test environment directly
and then direct all messages sent to that object to the test environment.
*/
private val _testContextHandler = system.actorOf(Props(classOf[ContextSensitive]), "actor-test-cs")
private implicit val timeout = Timeout(5 seconds)
private val _testContextHandlerResult = ask(_testContextHandler, message = "", self)
implicit val context = Await.result(_testContextHandlerResult, timeout.duration).asInstanceOf[ActorContext]
}
/**
* Surrender your `context` object for a greater good!
*/
private class ContextSensitive extends Actor {
var output: ActorRef = ActorRef.noSender
def receive: Receive = {
case _ =>
context.become(PassThroughBehavior)
output = sender()
sender() ! context
}
/**
* Once the `context` object has been leased,
* this `Actor` becomes transparent.
* Calling `context.parent` from whatever `Actor` was spurned by the previously provided `context`,
* will now refer to whatever was the contact to gain access to it - the test environment.
* @return something to `become`
*/
def PassThroughBehavior: Receive = {
case msg => output forward msg
}
}

View file

@ -112,12 +112,12 @@ class VehicleSpawnControl4Test extends ActorTest {
pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle) //order
val msg = probe.receiveOne(1 minute)
assert(
msg match {
case VehicleServiceMessage.Decon(RemoverActor.AddTask(v, z, _)) => (v == vehicle) && (z == zone)
case _ => false
}
)
// assert(
// msg match {
// case VehicleServiceMessage.Decon(RemoverActor.AddTask(v, z, _)) => (v == vehicle) && (z == zone)
// case _ => false
// }
// )
probe.expectNoMessage(5 seconds)
}
}

View file

@ -2,10 +2,14 @@
package actor.service
import akka.actor.Props
import akka.routing.RandomPool
import actor.base.ActorTest
import akka.testkit.TestProbe
import scala.concurrent.duration._
import actor.base.{ActorTest, FreedContextActorTest}
import net.psforever.objects._
import net.psforever.objects.guid.{NumberPoolHub, TaskResolver}
import net.psforever.objects.avatar.Avatar
import net.psforever.objects.guid.NumberPoolHub
import net.psforever.objects.guid.source.MaxNumberSource
import net.psforever.objects.zones.{Zone, ZoneMap}
import net.psforever.packet.game.objectcreate.{DroppedItemData, ObjectClass, ObjectCreateMessageParent, PlacementData}
import net.psforever.packet.game.{ObjectCreateMessage, PlayerStateMessageUpstream}
@ -13,12 +17,6 @@ import net.psforever.types._
import net.psforever.services.{RemoverActor, Service, ServiceManager}
import net.psforever.services.avatar._
import scala.concurrent.duration._
import akka.actor.typed.scaladsl.adapter._
import net.psforever.actors.zone.ZoneActor
import net.psforever.objects.avatar.Avatar
import net.psforever.objects.guid.source.MaxNumberSource
class AvatarService1Test extends ActorTest {
"AvatarService" should {
"construct" in {
@ -507,36 +505,35 @@ Putting Actor startup in the main class, outside of the body of the test, helps.
Frequent pauses to allow everything to sort their messages also helps.
Even with all this work, the tests have a high chance of failure just due to being asynchronous.
*/
class AvatarReleaseTest extends ActorTest {
ServiceManager.boot(system) ! ServiceManager.Register(RandomPool(1).props(Props[TaskResolver]()), "taskResolver")
class AvatarReleaseTest extends FreedContextActorTest {
val guid: NumberPoolHub = new NumberPoolHub(new MaxNumberSource(15))
val zone = new Zone("test", new ZoneMap("test-map"), 0) {
override def SetupNumberPools() = { AddPool("dynamic", 1 to 10) }
override def SetupNumberPools() : Unit = { }
GUID(guid)
}
val guid1: NumberPoolHub = new NumberPoolHub(new MaxNumberSource(100))
zone.GUID(guid1)
val service = system.actorOf(Props(classOf[AvatarService], zone), "release-test-service")
zone.actor = system.spawn(ZoneActor(zone), "release-test-zone")
zone.init(context)
val obj = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1))
guid1.register(obj)
guid1.register(obj.Slot(5).Equipment.get)
obj.Continent = "test"
guid.register(obj)
guid.register(obj.Slot(5).Equipment.get)
obj.Zone = zone
obj.Release
val subscriber = new TestProbe(system)
"AvatarService" should {
"pass Release" in {
expectNoMessage(100 milliseconds) //spacer
service ! Service.Join("test")
zone.AvatarEvents.tell(Service.Join("test"), subscriber.ref)
assert(zone.Corpses.isEmpty)
zone.Population ! Zone.Corpse.Add(obj)
expectNoMessage(200 milliseconds) //spacer
subscriber.expectNoMessage(200 milliseconds) //spacer
assert(zone.Corpses.size == 1)
assert(obj.HasGUID)
val guid = obj.GUID
service ! AvatarServiceMessage("test", AvatarAction.Release(obj, zone, Some(1 second))) //alive for one second
zone.AvatarEvents ! AvatarServiceMessage("test", AvatarAction.Release(obj, zone, Some(1 second))) //alive for one second
val reply1 = receiveOne(200 milliseconds)
val reply1 = subscriber.receiveOne(200 milliseconds)
assert(reply1.isInstanceOf[AvatarServiceResponse])
val reply1msg = reply1.asInstanceOf[AvatarServiceResponse]
assert(reply1msg.channel == "/test/Avatar")
@ -544,7 +541,7 @@ class AvatarReleaseTest extends ActorTest {
assert(reply1msg.replyMessage.isInstanceOf[AvatarResponse.Release])
assert(reply1msg.replyMessage.asInstanceOf[AvatarResponse.Release].player == obj)
val reply2 = receiveOne(2 seconds)
val reply2 = subscriber.receiveOne(2 seconds)
assert(reply2.isInstanceOf[AvatarServiceResponse])
val reply2msg = reply2.asInstanceOf[AvatarServiceResponse]
assert(reply2msg.channel.equals("/test/Avatar"))
@ -552,43 +549,42 @@ class AvatarReleaseTest extends ActorTest {
assert(reply2msg.replyMessage.isInstanceOf[AvatarResponse.ObjectDelete])
assert(reply2msg.replyMessage.asInstanceOf[AvatarResponse.ObjectDelete].item_guid == guid)
expectNoMessage(1 seconds)
subscriber.expectNoMessage(1 seconds)
assert(zone.Corpses.isEmpty)
assert(!obj.HasGUID)
}
}
}
class AvatarReleaseEarly1Test extends ActorTest {
ServiceManager.boot(system) ! ServiceManager.Register(RandomPool(1).props(Props[TaskResolver]()), "taskResolver")
class AvatarReleaseEarly1Test extends FreedContextActorTest {
val guid: NumberPoolHub = new NumberPoolHub(new MaxNumberSource(15))
val zone = new Zone("test", new ZoneMap("test-map"), 0) {
override def SetupNumberPools() = { AddPool("dynamic", 1 to 10) }
override def SetupNumberPools() : Unit = { }
GUID(guid)
}
val guid1: NumberPoolHub = new NumberPoolHub(new MaxNumberSource(100))
zone.GUID(guid1)
val service = system.actorOf(Props(classOf[AvatarService], zone), "release-test-service")
zone.actor = system.spawn(ZoneActor(zone), "release-test-zone")
val obj = Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1))
guid1.register(obj)
guid1.register(obj.Slot(5).Equipment.get)
obj.Continent = "test"
zone.init(context)
val obj = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1))
guid.register(obj)
guid.register(obj.Slot(5).Equipment.get)
obj.Zone = zone
obj.Release
val subscriber = new TestProbe(system)
"AvatarService" should {
"pass Release" in {
expectNoMessage(100 milliseconds) //spacer
service ! Service.Join("test")
zone.AvatarEvents.tell(Service.Join("test"), subscriber.ref)
assert(zone.Corpses.isEmpty)
zone.Population ! Zone.Corpse.Add(obj)
expectNoMessage(200 milliseconds) //spacer
subscriber.expectNoMessage(200 milliseconds) //spacer
assert(zone.Corpses.size == 1)
assert(obj.HasGUID)
val guid = obj.GUID
service ! AvatarServiceMessage("test", AvatarAction.Release(obj, zone)) //3+ minutes!
zone.AvatarEvents ! AvatarServiceMessage("test", AvatarAction.Release(obj, zone)) //3+ minutes!
val reply1 = receiveOne(200 milliseconds)
val reply1 = subscriber.receiveOne(200 milliseconds)
assert(reply1.isInstanceOf[AvatarServiceResponse])
val reply1msg = reply1.asInstanceOf[AvatarServiceResponse]
assert(reply1msg.channel == "/test/Avatar")
@ -596,8 +592,8 @@ class AvatarReleaseEarly1Test extends ActorTest {
assert(reply1msg.replyMessage.isInstanceOf[AvatarResponse.Release])
assert(reply1msg.replyMessage.asInstanceOf[AvatarResponse.Release].player == obj)
service ! AvatarServiceMessage.Corpse(RemoverActor.HurrySpecific(List(obj), zone)) //IMPORTANT: ONE ENTRY
val reply2 = receiveOne(200 milliseconds)
zone.AvatarEvents ! AvatarServiceMessage.Corpse(RemoverActor.HurrySpecific(List(obj), zone)) //IMPORTANT: ONE ENTRY
val reply2 = subscriber.receiveOne(200 milliseconds)
assert(reply2.isInstanceOf[AvatarServiceResponse])
val reply2msg = reply2.asInstanceOf[AvatarServiceResponse]
assert(reply2msg.channel.equals("/test/Avatar"))
@ -605,49 +601,48 @@ class AvatarReleaseEarly1Test extends ActorTest {
assert(reply2msg.replyMessage.isInstanceOf[AvatarResponse.ObjectDelete])
assert(reply2msg.replyMessage.asInstanceOf[AvatarResponse.ObjectDelete].item_guid == guid)
expectNoMessage(1 seconds)
subscriber.expectNoMessage(1 seconds)
assert(zone.Corpses.isEmpty)
assert(!obj.HasGUID)
}
}
}
class AvatarReleaseEarly2Test extends ActorTest {
ServiceManager.boot(system) ! ServiceManager.Register(RandomPool(1).props(Props[TaskResolver]()), "taskResolver")
class AvatarReleaseEarly2Test extends FreedContextActorTest {
val guid: NumberPoolHub = new NumberPoolHub(new MaxNumberSource(15))
val zone = new Zone("test", new ZoneMap("test-map"), 0) {
override def SetupNumberPools() = { AddPool("dynamic", 1 to 10) }
override def SetupNumberPools() : Unit = { }
GUID(guid)
}
val guid1: NumberPoolHub = new NumberPoolHub(new MaxNumberSource(100))
zone.GUID(guid1)
val service = system.actorOf(Props(classOf[AvatarService], zone), "release-test-service")
zone.actor = system.spawn(ZoneActor(zone), "release-test-zone")
val objAlt =
Player(
Avatar(0, "TestCharacter2", PlanetSideEmpire.NC, CharacterGender.Male, 1, CharacterVoice.Voice1)
) //necessary clutter
zone.init(context)
val obj = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1))
guid.register(obj)
guid.register(obj.Slot(5).Equipment.get)
obj.Zone = zone
obj.Release
val objAlt = Player(
Avatar(0, "TestCharacter2", PlanetSideEmpire.NC, CharacterGender.Male, 1, CharacterVoice.Voice1)
) //necessary clutter
objAlt.GUID = PlanetSideGUID(3)
objAlt.Slot(5).Equipment.get.GUID = PlanetSideGUID(4)
val obj = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1))
guid1.register(obj)
guid1.register(obj.Slot(5).Equipment.get)
obj.Continent = "test"
obj.Release
objAlt.Zone = zone
val subscriber = new TestProbe(system)
"AvatarService" should {
"pass Release" in {
expectNoMessage(100 milliseconds) //spacer
service ! Service.Join("test")
zone.AvatarEvents.tell(Service.Join("test"), subscriber.ref)
assert(zone.Corpses.isEmpty)
zone.Population ! Zone.Corpse.Add(obj)
expectNoMessage(200 milliseconds) //spacer
subscriber.expectNoMessage(200 milliseconds) //spacer
assert(zone.Corpses.size == 1)
assert(obj.HasGUID)
val guid = obj.GUID
service ! AvatarServiceMessage("test", AvatarAction.Release(obj, zone)) //3+ minutes!
zone.AvatarEvents ! AvatarServiceMessage("test", AvatarAction.Release(obj, zone)) //3+ minutes!
val reply1 = receiveOne(200 milliseconds)
val reply1 = subscriber.receiveOne(200 milliseconds)
assert(reply1.isInstanceOf[AvatarServiceResponse])
val reply1msg = reply1.asInstanceOf[AvatarServiceResponse]
assert(reply1msg.channel == "/test/Avatar")
@ -655,10 +650,10 @@ class AvatarReleaseEarly2Test extends ActorTest {
assert(reply1msg.replyMessage.isInstanceOf[AvatarResponse.Release])
assert(reply1msg.replyMessage.asInstanceOf[AvatarResponse.Release].player == obj)
service ! AvatarServiceMessage.Corpse(
zone.AvatarEvents ! AvatarServiceMessage.Corpse(
RemoverActor.HurrySpecific(List(objAlt, obj), zone)
) //IMPORTANT: TWO ENTRIES
val reply2 = receiveOne(100 milliseconds)
val reply2 = subscriber.receiveOne(100 milliseconds)
assert(reply2.isInstanceOf[AvatarServiceResponse])
val reply2msg = reply2.asInstanceOf[AvatarServiceResponse]
assert(reply2msg.channel.equals("/test/Avatar"))
@ -666,7 +661,7 @@ class AvatarReleaseEarly2Test extends ActorTest {
assert(reply2msg.replyMessage.isInstanceOf[AvatarResponse.ObjectDelete])
assert(reply2msg.replyMessage.asInstanceOf[AvatarResponse.ObjectDelete].item_guid == guid)
expectNoMessage(1 seconds)
subscriber.expectNoMessage(1 seconds)
assert(zone.Corpses.isEmpty)
assert(!obj.HasGUID)
}

View file

@ -174,7 +174,6 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
var accountPersistence: ActorRef = ActorRef.noSender
var galaxyService: ActorRef = ActorRef.noSender
var squadService: ActorRef = ActorRef.noSender
var taskResolver: ActorRef = Actor.noSender
var propertyOverrideManager: ActorRef = Actor.noSender
var cluster: typed.ActorRef[InterstellarClusterService.Command] = Actor.noSender
var _session: Session = Session()
@ -295,7 +294,6 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
val serviceManager = ServiceManager.serviceManager
serviceManager ! Lookup("accountIntermediary")
serviceManager ! Lookup("accountPersistence")
serviceManager ! Lookup("taskResolver")
serviceManager ! Lookup("galaxy")
serviceManager ! Lookup("squad")
serviceManager ! Lookup("propertyOverrideManager")
@ -376,9 +374,6 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
case LookupResult("accountPersistence", endpoint) =>
accountPersistence = endpoint
log.info("ID: " + session.id + " Got account persistence service " + endpoint)
case LookupResult("taskResolver", endpoint) =>
taskResolver = endpoint
log.info("ID: " + session.id + " Got task resolver service " + endpoint)
case LookupResult("galaxy", endpoint) =>
galaxyService = endpoint
log.info("ID: " + session.id + " Got galaxy service " + endpoint)
@ -1060,17 +1055,17 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
//TODO sufficiently delete the tool
sendResponse(ObjectDeleteMessage(tool.GUID, 0))
continent.AvatarEvents ! AvatarServiceMessage(continent.id, AvatarAction.ObjectDelete(player.GUID, tool.GUID))
taskResolver ! GUIDTask.UnregisterEquipment(tool)(continent.GUID)
continent.tasks ! GUIDTask.UnregisterEquipment(tool)(continent.GUID)
val trigger = new BoomerTrigger
trigger.Companion = obj.GUID
obj.Trigger = trigger
val holster = player.Slot(index)
if (holster.Equipment.contains(tool)) {
holster.Equipment = None
taskResolver ! HoldNewEquipmentUp(player, taskResolver)(trigger, index)
continent.tasks ! HoldNewEquipmentUp(player)(trigger, index)
} else {
//don't know where boomer trigger should go; drop it on the ground
taskResolver ! NewItemDrop(player, continent)(trigger)
continent.tasks ! NewItemDrop(player, continent)(trigger)
}
case SessionActor.FinalizeDeployable(obj: ExplosiveDeployable, tool, index) =>
@ -1104,7 +1099,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
log.info(s"FinalizeDeployable: setup for telepad #${guid.guid} in zone ${continent.id}")
obj.Router = routerGUID //necessary; forwards link to the router
DeployableBuildActivity(obj)
RemoveOldEquipmentFromInventory(player, taskResolver)(tool)
RemoveOldEquipmentFromInventory(player)(tool)
//it takes 60s for the telepad to become properly active
continent.LocalEvents ! LocalServiceMessage.Telepads(RouterTelepadActivation.AddTask(obj, continent))
}
@ -1133,11 +1128,11 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
//!!only dispatch Zone.Deployable.Dismiss from WorldSessionActor as cleanup if the target deployable was never fully introduced
case Zone.Deployable.DeployableIsDismissed(obj: TurretDeployable) =>
taskResolver ! GUIDTask.UnregisterDeployableTurret(obj)(continent.GUID)
continent.tasks ! GUIDTask.UnregisterDeployableTurret(obj)(continent.GUID)
//!!only dispatch Zone.Deployable.Dismiss from WorldSessionActor as cleanup if the target deployable was never fully introduced
case Zone.Deployable.DeployableIsDismissed(obj) =>
taskResolver ! GUIDTask.UnregisterObjectTask(obj)(continent.GUID)
continent.tasks ! GUIDTask.UnregisterObjectTask(obj)(continent.GUID)
case InterstellarClusterService.ZonesResponse(zones) =>
zones.foreach { zone =>
@ -1240,9 +1235,9 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
player.avatar = avatar
interstellarFerry match {
case Some(vehicle) if vehicle.PassengerInSeat(player).contains(0) =>
taskResolver ! RegisterDrivenVehicle(vehicle, player)
continent.tasks ! RegisterDrivenVehicle(vehicle, player)
case _ =>
taskResolver ! RegisterNewAvatar(player)
continent.tasks ! RegisterNewAvatar(player)
}
case NewPlayerLoaded(tplayer) =>
@ -1608,14 +1603,14 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
Zoning.Time.Sanctuary
} else {
val playerPosition = player.Position.xy
(continent.Buildings.values
continent.Buildings.values
.filter { building =>
val radius = building.Definition.SOIRadius
Vector3.DistanceSquared(building.Position.xy, playerPosition) < radius * radius
}) match {
} match {
case Nil =>
Zoning.Time.None
case List(building) =>
case List(building: FactionAffinity) =>
if (building.Faction == player.Faction) Zoning.Time.Friendly
else if (building.Faction == PlanetSideEmpire.NEUTRAL) Zoning.Time.Neutral
else Zoning.Time.Enemy
@ -1652,7 +1647,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
case Nil =>
//no soi interference
targetBuildings = Nil
case List(building) =>
case List(building: Building) =>
//blocked by a single soi; find space just outside of this soi and confirm no new overlap
val radius = Vector3(0, building.Definition.SOIRadius.toFloat + 5f, 0)
whereToDroppod =
@ -2068,10 +2063,10 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
case (_, guid) => sendResponse(ObjectDeleteMessage(guid, 0))
}
//functionally delete
delete.foreach { case (obj, _) => taskResolver ! GUIDTask.UnregisterEquipment(obj)(continent.GUID) }
delete.foreach { case (obj, _) => continent.tasks ! GUIDTask.UnregisterEquipment(obj)(continent.GUID) }
//redraw
if (maxhand) {
taskResolver ! HoldNewEquipmentUp(player, taskResolver)(
continent.tasks ! HoldNewEquipmentUp(player)(
Tool(GlobalDefinitions.MAXArms(subtype, player.Faction)),
0
)
@ -2146,11 +2141,11 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
(old_holsters ++ old_inventory).foreach {
case (obj, guid) =>
sendResponse(ObjectDeleteMessage(guid, 0))
taskResolver ! GUIDTask.UnregisterEquipment(obj)(continent.GUID)
continent.tasks ! GUIDTask.UnregisterEquipment(obj)(continent.GUID)
}
//redraw
if (maxhand) {
taskResolver ! HoldNewEquipmentUp(player, taskResolver)(
continent.tasks ! HoldNewEquipmentUp(player)(
Tool(GlobalDefinitions.MAXArms(subtype, player.Faction)),
0
)
@ -2189,7 +2184,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
if (Avatar.purchaseCooldowns.contains(item.obj.Definition)) {
avatarActor ! AvatarActor.UpdatePurchaseTime(item.obj.Definition)
}
taskResolver ! PutLoadoutEquipmentInInventory(target, taskResolver)(item.obj, item.start)
continent.tasks ! PutLoadoutEquipmentInInventory(target)(item.obj, item.start)
}
}
}
@ -2538,16 +2533,15 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Buy, false))
case None =>
avatarActor ! AvatarActor.UpdatePurchaseTime(item.Definition)
taskResolver ! BuyNewEquipmentPutInInventory(
continent.tasks ! BuyNewEquipmentPutInInventory(
continent.GUID(tplayer.VehicleSeated) match { case Some(v: Vehicle) => v; case _ => player },
taskResolver,
tplayer,
msg.terminal_guid
)(item)
}
case Terminal.SellEquipment() =>
SellEquipmentFromInventory(tplayer, taskResolver, tplayer, msg.terminal_guid)(Player.FreeHandSlot)
SellEquipmentFromInventory(tplayer, tplayer, msg.terminal_guid)(Player.FreeHandSlot)
case Terminal.LearnCertification(cert) =>
avatarActor ! AvatarActor.LearnCertification(msg.terminal_guid, cert)
@ -2605,7 +2599,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
entry.obj.Faction = tplayer.Faction
vTrunk.InsertQuickly(entry.start, entry.obj)
})
taskResolver ! RegisterVehicleFromSpawnPad(vehicle, pad)
continent.tasks ! RegisterVehicleFromSpawnPad(vehicle, pad)
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Buy, true))
}
case None =>
@ -2873,7 +2867,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
(old_weapons ++ old_inventory).foreach {
case (obj, guid) =>
sendResponse(ObjectDeleteMessage(guid, 0))
taskResolver ! GUIDTask.UnregisterEquipment(obj)(continent.GUID)
continent.tasks ! GUIDTask.UnregisterEquipment(obj)(continent.GUID)
}
ApplyPurchaseTimersBeforePackingLoadout(player, vehicle, added_weapons ++ new_inventory)
} else if (accessedContainer.contains(target)) {
@ -3424,7 +3418,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
})
//load active players in zone (excepting players who are seated or players who are us)
val live = continent.LivePlayers
log.info(s"loading players ${live}")
log.info(s"loading players $live")
live
.filterNot(tplayer => {
tplayer.GUID == player.GUID || tplayer.VehicleSeated.nonEmpty
@ -3545,7 +3539,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
allActiveVehicles.collect {
case vehicle if vehicle.CargoHolds.nonEmpty =>
vehicle.CargoHolds.collect({
case (index, hold) if hold.isOccupied => {
case (index, hold: Cargo) if hold.isOccupied => {
CargoBehavior.CargoMountBehaviorForAll(
vehicle,
hold.Occupant.get,
@ -3580,7 +3574,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
//implant terminals
continent.map.terminalToInterface.foreach({
case ((terminal_guid, interface_guid)) =>
case (terminal_guid, interface_guid) =>
val parent_guid = PlanetSideGUID(terminal_guid)
continent.GUID(interface_guid) match {
case Some(obj: Terminal) =>
@ -3617,7 +3611,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
//base turrets
continent.map.turretToWeapon
.map { case ((turret_guid, _)) => continent.GUID(turret_guid) }
.map { case (turret_guid: Int, _) => continent.GUID(turret_guid) }
.collect {
case Some(turret: FacilityTurret) =>
val pguid = turret.GUID
@ -4112,7 +4106,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
CancelZoningProcessWithDescriptiveReason("cancel_use")
continent.GUID(player.VehicleSeated) match {
case Some(_) =>
RemoveOldEquipmentFromInventory(player, taskResolver)(item)
RemoveOldEquipmentFromInventory(player)(item)
case None =>
DropEquipmentFromInventory(player)(item)
}
@ -4159,9 +4153,9 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
case x :: xs =>
val (deleteFunc, modifyFunc): (Equipment => Future[Any], (AmmoBox, Int) => Unit) = obj match {
case veh: Vehicle =>
(RemoveOldEquipmentFromInventory(veh, taskResolver), ModifyAmmunitionInVehicle(veh))
(RemoveOldEquipmentFromInventory(veh), ModifyAmmunitionInVehicle(veh))
case o: PlanetSideServerObject with Container =>
(RemoveOldEquipmentFromInventory(o, taskResolver), ModifyAmmunition(o))
(RemoveOldEquipmentFromInventory(o), ModifyAmmunition(o))
case _ =>
throw new Exception("ReloadMessage: should be a server object, not a regular game object")
}
@ -4329,7 +4323,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
continent.id,
AvatarAction.ProjectileExplodes(player.GUID, obj.GUID, obj)
)
taskResolver ! UnregisterProjectile(obj)
continent.tasks ! UnregisterProjectile(obj)
}
}
@ -4391,7 +4385,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
Some(destination: PlanetSideServerObject with Container),
Some(item: Equipment)
) =>
ContainableMoveItem(taskResolver, player.Name, source, destination, item, dest)
ContainableMoveItem(player.Name, source, destination, item, dest)
case (None, _, _) =>
log.error(s"MoveItem: wanted to move $item_guid from $source_guid, but could not find source object")
case (_, None, _) =>
@ -4428,7 +4422,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
destination.Fit(item)
) match {
case (Some((source, Some(_))), Some(dest)) =>
ContainableMoveItem(taskResolver, player.Name, source, destination, item, dest)
ContainableMoveItem(player.Name, source, destination, item, dest)
case (None, _) =>
log.error(s"LootItem: can not find where $item is put currently")
case (_, None) =>
@ -4659,7 +4653,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
)
)
sendResponse(ObjectDeleteMessage(kit.GUID, 0))
taskResolver ! GUIDTask.UnregisterEquipment(kit)(continent.GUID)
continent.tasks ! GUIDTask.UnregisterEquipment(kit)(continent.GUID)
}
}
@ -5012,7 +5006,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
case _ =>
GUIDTask.RegisterObjectTask(dObj)(continent.GUID)
}
taskResolver ! CallBackForTask(tasking, continent.Deployables, Zone.Deployable.Build(dObj, obj))
continent.tasks ! CallBackForTask(tasking, continent.Deployables, Zone.Deployable.Build(dObj, obj))
case Some(obj) =>
log.warn(s"DeployObject: $obj is something?")
@ -6277,9 +6271,9 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
case x :: xs =>
val (deleteFunc, modifyFunc): (Equipment => Future[Any], (AmmoBox, Int) => Unit) = obj match {
case (veh: Vehicle) =>
(RemoveOldEquipmentFromInventory(veh, taskResolver), ModifyAmmunitionInVehicle(veh))
(RemoveOldEquipmentFromInventory(veh), ModifyAmmunitionInVehicle(veh))
case o: PlanetSideServerObject with Container =>
(RemoveOldEquipmentFromInventory(o, taskResolver), ModifyAmmunition(o))
(RemoveOldEquipmentFromInventory(o), ModifyAmmunition(o))
case _ =>
throw new Exception(
"PerformToolAmmoChange: (remove/modify) should be a server object, not a regular game object"
@ -6340,7 +6334,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
s"ChangeAmmo: taking ${originalBoxCapacity - splitReloadAmmo} from a box of ${originalBoxCapacity} $requestedAmmoType"
)
val boxForInventory = AmmoBox(box.Definition, splitReloadAmmo)
taskResolver ! stowNewFunc(boxForInventory)
continent.tasks ! stowNewFunc(boxForInventory)
fullMagazine
})
sendResponse(
@ -6385,10 +6379,10 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
case Nil | List(_) => ; //done (the former case is technically not possible)
case _ :: xs =>
modifyFunc(previousBox, 0) //update to changed capacity value
xs.foreach(box => { taskResolver ! stowNewFunc(box) })
xs.foreach(box => { continent.tasks ! stowNewFunc(box) })
}
} else {
taskResolver ! GUIDTask.UnregisterObjectTask(previousBox)(continent.GUID)
continent.tasks ! GUIDTask.UnregisterObjectTask(previousBox)(continent.GUID)
}
}
}
@ -6448,29 +6442,29 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
FindEquipmentStock(player, FindToolThatUses(ammoType), 3, CountGrenades).reverse match { //do not search sidearm holsters
case Nil =>
log.info(s"no more $ammoType grenades")
RemoveOldEquipmentFromInventory(player, taskResolver)(tool)
RemoveOldEquipmentFromInventory(player)(tool)
case x :: xs => //this is similar to ReloadMessage
val box = x.obj.asInstanceOf[Tool]
val tailReloadValue: Int = if (xs.isEmpty) { 0 }
else { xs.map(_.obj.asInstanceOf[Tool].Magazine).reduce(_ + _) }
val sumReloadValue: Int = box.Magazine + tailReloadValue
val actualReloadValue = (if (sumReloadValue <= 3) {
RemoveOldEquipmentFromInventory(player, taskResolver)(x.obj)
val actualReloadValue = if (sumReloadValue <= 3) {
RemoveOldEquipmentFromInventory(player)(x.obj)
sumReloadValue
} else {
ModifyAmmunition(player)(box.AmmoSlot.Box, 3 - tailReloadValue)
3
})
}
log.info(s"found $actualReloadValue more $ammoType grenades to throw")
ModifyAmmunition(player)(
tool.AmmoSlot.Box,
-actualReloadValue
) //grenade item already in holster (negative because empty)
xs.foreach(item => { RemoveOldEquipmentFromInventory(player, taskResolver)(item.obj) })
xs.foreach(item => { RemoveOldEquipmentFromInventory(player)(item.obj) })
}
} else if (tdef == GlobalDefinitions.phoenix) {
RemoveOldEquipmentFromInventory(player, taskResolver)(tool)
RemoveOldEquipmentFromInventory(player)(tool)
}
}
@ -6913,7 +6907,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
val zone = vehicle.PreviousGatingManifest().get.origin
zone.VehicleEvents ! VehicleServiceMessage(
zone.id,
VehicleAction.UnloadVehicle(player.GUID, zone, vehicle, vehicleToDelete)
VehicleAction.UnloadVehicle(player.GUID, vehicle, vehicleToDelete)
)
log.info(
s"AvatarCreate: cleaning up ghost of transitioning vehicle ${vehicle.Definition.Name}@${vehicleToDelete.guid} in zone ${zone.id}"
@ -7160,12 +7154,12 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
obj.Slot(4).Equipment match {
case None => ;
case Some(knife) =>
RemoveOldEquipmentFromInventory(obj, taskResolver)(knife)
RemoveOldEquipmentFromInventory(obj)(knife)
}
obj.Slot(0).Equipment match {
case Some(arms: Tool) =>
if (GlobalDefinitions.isMaxArms(arms.Definition)) {
RemoveOldEquipmentFromInventory(obj, taskResolver)(arms)
RemoveOldEquipmentFromInventory(obj)(arms)
}
case _ => ;
}
@ -7210,7 +7204,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
zone.Population ! Zone.Population.Release(avatar)
sendResponse(ObjectDeleteMessage(pguid, 0))
zone.AvatarEvents ! AvatarServiceMessage(zone.id, AvatarAction.ObjectDelete(pguid, pguid, 0))
taskResolver ! GUIDTask.UnregisterPlayer(tplayer)(zone.GUID)
zone.tasks ! GUIDTask.UnregisterPlayer(tplayer)(zone.GUID)
}
}
@ -8077,7 +8071,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
*/
def CommonDestroyConstructionItem(tool: ConstructionItem, index: Int): Unit = {
if (SafelyRemoveConstructionItemFromSlot(tool, index, "CommonDestroyConstructionItem")) {
taskResolver ! GUIDTask.UnregisterEquipment(tool)(continent.GUID)
continent.tasks ! GUIDTask.UnregisterEquipment(tool)(continent.GUID)
}
}
@ -8219,7 +8213,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
}) match {
case Some((parent, Some(slot))) =>
obj.Position = Vector3.Zero
RemoveOldEquipmentFromInventory(parent, taskResolver)(obj)
RemoveOldEquipmentFromInventory(parent)(obj)
log.info(s"RequestDestroy: equipment $obj")
true
@ -8414,7 +8408,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
if (!zoneReload && zoneId == continent.id) {
if (player.isBackpack) { // important! test the actor-wide player ref, not the parameter
// respawning from unregistered player
taskResolver ! RegisterAvatar(targetPlayer)
continent.tasks ! RegisterAvatar(targetPlayer)
} else {
// move existing player; this is the one case where the original GUID is retained by the player
self ! PlayerLoaded(targetPlayer)
@ -8517,7 +8511,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
if (!zoneReload && zoneId == continent.id) {
if (vehicle.Definition == GlobalDefinitions.droppod) {
//instant action droppod in the same zone
taskResolver ! RegisterDroppod(vehicle, player)
continent.tasks ! RegisterDroppod(vehicle, player)
} else {
//transferring a vehicle between spawn points (warp gates) in the same zone
self ! PlayerLoaded(player)
@ -8541,7 +8535,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
//do not delete if vehicle has passengers or cargo
continent.VehicleEvents ! VehicleServiceMessage(
continent.id,
VehicleAction.UnloadVehicle(pguid, continent, vehicle, topLevel)
VehicleAction.UnloadVehicle(pguid, vehicle, topLevel)
)
None
} else {
@ -8640,7 +8634,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
task: TaskResolver.GiveTask,
zoneMessage: InterstellarClusterService.FindZone
): Unit = {
taskResolver ! TaskResolver.GiveTask(
continent.tasks ! TaskResolver.GiveTask(
new Task() {
override def isComplete: Task.Resolution.Value = task.task.isComplete
@ -8671,7 +8665,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
avatarActor ! AvatarActor.SetVehicle(None)
}
RemoveBoomerTriggersFromInventory().foreach(obj => {
taskResolver ! GUIDTask.UnregisterObjectTask(obj)(continent.GUID)
continent.tasks ! GUIDTask.UnregisterObjectTask(obj)(continent.GUID)
})
Deployables.Disown(continent, avatar, self)
drawDeloyableIcon = RedrawDeployableIcons //important for when SetCurrentAvatar initializes the UI next zone
@ -9149,7 +9143,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
continent.id,
AvatarAction.ProjectileExplodes(player.GUID, projectile_guid, projectile)
)
taskResolver ! UnregisterProjectile(projectile)
continent.tasks ! UnregisterProjectile(projectile)
projectiles(local_index) match {
case Some(obj) if !obj.isResolved => obj.Miss()
case _ => ;
@ -9185,7 +9179,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
tplayer.VehicleSeated = None
zone.Population ! Zone.Population.Release(avatar)
sendResponse(ObjectDeleteMessage(tplayer.GUID, 0))
taskResolver ! GUIDTask.UnregisterPlayer(tplayer)(zone.GUID)
zone.tasks ! GUIDTask.UnregisterPlayer(tplayer)(zone.GUID)
}
}
@ -9374,7 +9368,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
log.trace(
s"WeaponFireMessage: ${projectile_info.Name} is a remote projectile"
)
taskResolver ! (if (projectile.HasGUID) {
continent.tasks ! (if (projectile.HasGUID) {
continent.AvatarEvents ! AvatarServiceMessage(
continent.id,
AvatarAction.ProjectileExplodes(

View file

@ -118,22 +118,19 @@ object WorldSession {
* @see `tell`
* @see `Zone.AvatarEvents`
* @param obj the container
* @param taskResolver na
* @param item the item being manipulated
* @param slot na
* @return a `Future` that anticipates the resolution to this manipulation
*/
def PutEquipmentInInventorySlot(
obj: PlanetSideServerObject with Container,
taskResolver: ActorRef
obj: PlanetSideServerObject with Container
)(item: Equipment, slot: Int): Future[Any] = {
val localContainer = obj
val localItem = item
val localResolver = taskResolver
val result = ask(localContainer.Actor, Containable.PutItemInSlotOnly(localItem, slot))
result.onComplete {
case Failure(_) | Success(_: Containable.CanNotPutItemInSlot) =>
localResolver ! GUIDTask.UnregisterEquipment(localItem)(localContainer.Zone.GUID)
localContainer.Zone.tasks ! GUIDTask.UnregisterEquipment(localItem)(localContainer.Zone.GUID)
case _ => ;
}
result
@ -150,14 +147,12 @@ object WorldSession {
* @see `Task`
* @see `TaskResolver.GiveTask`
* @param obj the container
* @param taskResolver na
* @param item the item being manipulated
* @param slot where the item will be placed in the container
* @return a `TaskResolver` object
*/
def PutLoadoutEquipmentInInventory(
obj: PlanetSideServerObject with Container,
taskResolver: ActorRef
obj: PlanetSideServerObject with Container
)(item: Equipment, slot: Int): TaskResolver.GiveTask = {
val localZone = obj.Zone
TaskResolver.GiveTask(
@ -165,7 +160,7 @@ object WorldSession {
private val localContainer = obj
private val localItem = item
private val localSlot = slot
private val localFunc: (Equipment, Int) => Future[Any] = PutEquipmentInInventorySlot(obj, taskResolver)
private val localFunc: (Equipment, Int) => Future[Any] = PutEquipmentInInventorySlot(obj)
override def Timeout: Long = 1000
@ -203,7 +198,6 @@ object WorldSession {
* @see `PutEquipmentInInventorySlot`
* @see `TerminalMessageOnTimeout`
* @param obj the container
* @param taskResolver na
* @param player na
* @param term na
* @param item the item being manipulated
@ -211,7 +205,6 @@ object WorldSession {
*/
def BuyNewEquipmentPutInInventory(
obj: PlanetSideServerObject with Container,
taskResolver: ActorRef,
player: Player,
term: PlanetSideGUID
)(item: Equipment): TaskResolver.GiveTask = {
@ -221,7 +214,6 @@ object WorldSession {
private val localContainer = obj
private val localItem = item
private val localPlayer = player
private val localResolver = taskResolver
private val localTermMsg: Boolean => Unit = TerminalResult(term, localPlayer, TransactionType.Buy)
override def Timeout: Long = 1000
@ -242,7 +234,7 @@ object WorldSession {
case Failure(_) | Success(_: Containable.CanNotPutItemInSlot) =>
if (localContainer != localPlayer) {
TerminalMessageOnTimeout(
PutEquipmentInInventorySlot(localPlayer, localResolver)(localItem, Player.FreeHandSlot),
PutEquipmentInInventorySlot(localPlayer)(localItem, Player.FreeHandSlot),
localTermMsg
)
.onComplete {
@ -252,7 +244,7 @@ object WorldSession {
localTermMsg(true)
}
} else {
localResolver ! GUIDTask.UnregisterEquipment(localItem)(localContainer.Zone.GUID)
localContainer.Zone.tasks ! GUIDTask.UnregisterEquipment(localItem)(localContainer.Zone.GUID)
localTermMsg(false)
}
case _ =>
@ -289,12 +281,11 @@ object WorldSession {
* @see `TaskResolver.GiveTask`
* @see `Zone.AvatarEvents`
* @param player the player whose visible slot will be equipped and drawn
* @param taskResolver na
* @param item the item to equip
* @param slot the slot in which the item will be equipped
* @return a `TaskResolver` object
*/
def HoldNewEquipmentUp(player: Player, taskResolver: ActorRef)(item: Equipment, slot: Int): TaskResolver.GiveTask = {
def HoldNewEquipmentUp(player: Player)(item: Equipment, slot: Int): TaskResolver.GiveTask = {
if (player.VisibleSlots.contains(slot)) {
val localZone = player.Zone
TaskResolver.GiveTask(
@ -303,7 +294,6 @@ object WorldSession {
private val localGUID = player.GUID
private val localItem = item
private val localSlot = slot
private val localResolver = taskResolver
override def Timeout: Long = 1000
@ -318,7 +308,7 @@ object WorldSession {
ask(localPlayer.Actor, Containable.PutItemInSlotOnly(localItem, localSlot))
.onComplete {
case Failure(_) | Success(_: Containable.CanNotPutItemInSlot) =>
localResolver ! GUIDTask.UnregisterEquipment(localItem)(localZone.GUID)
localPlayer.Zone.tasks ! GUIDTask.UnregisterEquipment(localItem)(localZone.GUID)
case _ =>
if (localPlayer.DrawnSlot != Player.HandsDownSlot) {
localPlayer.DrawnSlot = Player.HandsDownSlot
@ -438,20 +428,18 @@ object WorldSession {
* @see `GUIDTask.UnregisterEquipment`
* @see `Zone.AvatarEvents`
* @param obj the container to search
* @param taskResolver na
* @param item the item to find and remove from the container
* @return a `Future` that anticipates the resolution to this manipulation
*/
def RemoveOldEquipmentFromInventory(obj: PlanetSideServerObject with Container, taskResolver: ActorRef)(
def RemoveOldEquipmentFromInventory(obj: PlanetSideServerObject with Container)(
item: Equipment
): Future[Any] = {
val localContainer = obj
val localItem = item
val localResolver = taskResolver
val result = ask(localContainer.Actor, Containable.RemoveItemFromSlot(localItem))
result.onComplete {
case Success(Containable.ItemFromSlot(_, Some(_), Some(_))) =>
localResolver ! GUIDTask.UnregisterEquipment(localItem)(localContainer.Zone.GUID)
localContainer.Zone.tasks ! GUIDTask.UnregisterEquipment(localItem)(localContainer.Zone.GUID)
case _ =>
}
result
@ -474,7 +462,6 @@ object WorldSession {
* @see `TerminalMessageOnTimeout`
* @see `TerminalResult`
* @param obj the container to search
* @param taskResolver na
* @param player the player who used the terminal
* @param term the unique identifier number of the terminal
* @param slot from which slot the equipment is to be removed
@ -482,14 +469,12 @@ object WorldSession {
*/
def SellEquipmentFromInventory(
obj: PlanetSideServerObject with Container,
taskResolver: ActorRef,
player: Player,
term: PlanetSideGUID
)(slot: Int): Future[Any] = {
val localContainer = obj
val localPlayer = player
val localSlot = slot
val localResolver = taskResolver
val localTermMsg: Boolean => Unit = TerminalResult(term, localPlayer, TransactionType.Sell)
val result = TerminalMessageOnTimeout(
ask(localContainer.Actor, Containable.RemoveItemFromSlot(localSlot)),
@ -497,7 +482,7 @@ object WorldSession {
)
result.onComplete {
case Success(Containable.ItemFromSlot(_, Some(item), Some(_))) =>
localResolver ! GUIDTask.UnregisterEquipment(item)(localContainer.Zone.GUID)
localContainer.Zone.tasks ! GUIDTask.UnregisterEquipment(item)(localContainer.Zone.GUID)
localTermMsg(true)
case _ =>
localTermMsg(false)
@ -519,7 +504,6 @@ object WorldSession {
* @see `RemoveEquipmentFromLockerContainer`
* @see `StowEquipmentInLockerContainer`
* @see `TaskResolver`
* @param taskResolver na
* @param toChannel broadcast channel name for a manual packet callback
* @param source the container in which the item is to be removed
* @param destination the container into which the item is to be placed
@ -527,7 +511,6 @@ object WorldSession {
* @param dest where in the destination container the item is being placed
*/
def ContainableMoveItem(
taskResolver: ActorRef,
toChannel: String,
source: PlanetSideServerObject with Container,
destination: PlanetSideServerObject with Container,
@ -536,9 +519,9 @@ object WorldSession {
) : Unit = {
(source, destination) match {
case (locker: LockerContainer, _) if !destination.isInstanceOf[LockerContainer] =>
RemoveEquipmentFromLockerContainer(taskResolver, toChannel, locker, destination, item, dest)
RemoveEquipmentFromLockerContainer(toChannel, locker, destination, item, dest)
case (_, locker: LockerContainer) =>
StowEquipmentInLockerContainer(taskResolver, toChannel, source, locker, item, dest)
StowEquipmentInLockerContainer(toChannel, source, locker, item, dest)
case _ =>
source.Actor ! Containable.MoveItem(destination, item, dest)
}
@ -564,7 +547,6 @@ object WorldSession {
* @see `TaskResolver`
* @see `TaskResolver.GiveTask`
* @see `Zone.AvatarEvents`
* @param taskResolver na
* @param toChannel broadcast channel name for a manual packet callback
* @param source the container in which the item is to be removed
* @param destination the container into which the item is to be placed
@ -572,7 +554,6 @@ object WorldSession {
* @param dest where in the destination container the item is being placed
*/
def StowEquipmentInLockerContainer(
taskResolver: ActorRef,
toChannel: String,
source: PlanetSideServerObject with Container,
destination: PlanetSideServerObject with Container,
@ -605,7 +586,7 @@ object WorldSession {
//too many swap items or other error; this attempt will probably fail
(Nil, None)
}
taskResolver ! TaskResolver.GiveTask(
destination.Zone.tasks ! TaskResolver.GiveTask(
new Task() {
val localGUID = swapItemGUID //the swap item's original GUID, if any swap item
val localChannel = toChannel
@ -659,7 +640,6 @@ object WorldSession {
* @see `TaskResolver`
* @see `TaskResolver.GiveTask`
* @see `Zone.AvatarEvents`
* @param taskResolver na
* @param toChannel broadcast channel name for a manual packet callback
* @param source the container in which the item is to be removed
* @param destination the container into which the item is to be placed
@ -667,14 +647,13 @@ object WorldSession {
* @param dest where in the destination container the item is being placed
*/
def RemoveEquipmentFromLockerContainer(
taskResolver: ActorRef,
toChannel: String,
source: PlanetSideServerObject with Container,
destination: PlanetSideServerObject with Container,
item: Equipment,
dest: Int
): Unit = {
taskResolver ! TaskResolver.GiveTask(
destination.Zone.tasks ! TaskResolver.GiveTask(
new Task() {
val localGUID = item.GUID //original GUID
val localChannel = toChannel

View file

@ -2,12 +2,11 @@
package net.psforever.objects.serverobject.pad
import akka.actor.{ActorContext, Cancellable, Props}
import net.psforever.objects.guid.GUIDTask.UnregisterVehicle
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
import net.psforever.objects.serverobject.pad.process.{VehicleSpawnControlBase, VehicleSpawnControlConcealPlayer}
import net.psforever.objects.zones.Zone
import net.psforever.objects.{Default, Player, Vehicle}
import net.psforever.services.RemoverActor
import net.psforever.services.vehicle.VehicleServiceMessage
import scala.annotation.tailrec
import scala.concurrent.ExecutionContext.Implicits.global
@ -330,7 +329,7 @@ object VehicleSpawnControl {
if (zone.Vehicles.exists(_.GUID == vehicle.GUID)) { //already added to zone
vehicle.Actor ! Vehicle.Deconstruct()
} else { //just registered to zone
zone.VehicleEvents ! VehicleServiceMessage.Decon(RemoverActor.AddTask(vehicle, zone, Some(0 seconds)))
zone.tasks ! UnregisterVehicle(vehicle)(zone.GUID)
}
}
}

View file

@ -6,6 +6,7 @@ import net.psforever.objects._
import net.psforever.objects.ballistics.{ResolvedProjectile, VehicleSource}
import net.psforever.objects.ce.TelepadLike
import net.psforever.objects.equipment.{Equipment, EquipmentSlot, JammableMountedWeapons}
import net.psforever.objects.guid.GUIDTask
import net.psforever.objects.inventory.{GridInventory, InventoryItem}
import net.psforever.objects.serverobject.CommonMessages
import net.psforever.objects.serverobject.mount.{Mountable, MountableBehavior}
@ -20,7 +21,6 @@ import net.psforever.objects.serverobject.repair.RepairableVehicle
import net.psforever.objects.serverobject.terminals.Terminal
import net.psforever.objects.vital.VehicleShieldCharge
import net.psforever.objects.zones.Zone
import net.psforever.services.RemoverActor
import net.psforever.packet.game._
import net.psforever.packet.game.objectcreate.ObjectCreateMessageParent
import net.psforever.types.{DriveState, ExoSuitType, PlanetSideGUID, Vector3}
@ -338,7 +338,7 @@ class VehicleControl(vehicle: Vehicle)
}
})
//unregister
events ! VehicleServiceMessage.Decon(RemoverActor.AddTask(vehicle, zone, Some(0 seconds)))
zone.tasks ! GUIDTask.UnregisterVehicle(vehicle)(zone.GUID)
//banished to the shadow realm
vehicle.Position = Vector3.Zero
//queue final deletion
@ -355,7 +355,7 @@ class VehicleControl(vehicle: Vehicle)
val zone = vehicle.Zone
zone.VehicleEvents ! VehicleServiceMessage(
zone.id,
VehicleAction.UnloadVehicle(Service.defaultPlayerGUID, zone, vehicle, vehicle.GUID)
VehicleAction.UnloadVehicle(Service.defaultPlayerGUID, vehicle, vehicle.GUID)
)
zone.Transport ! Zone.Vehicle.Despawn(vehicle)
case _ =>

View file

@ -8,7 +8,7 @@ import net.psforever.objects._
import net.psforever.objects.ce.Deployable
import net.psforever.objects.entity.IdentifiableEntity
import net.psforever.objects.equipment.Equipment
import net.psforever.objects.guid.NumberPoolHub
import net.psforever.objects.guid.{NumberPoolHub, TaskResolver}
import net.psforever.objects.guid.actor.UniqueNumberSystem
import net.psforever.objects.guid.key.LoanedKey
import net.psforever.objects.guid.selector.RandomSelector
@ -85,6 +85,8 @@ class Zone(val id: String, val map: ZoneMap, zoneNumber: Int) {
/** Used by the `Zone` to coordinate `Equipment` dropping and collection requests. */
private var ground: ActorRef = Default.Actor
private var taskResolver: ActorRef = Default.Actor
/**
*/
private val constructions: ListBuffer[PlanetSideGameObject with Deployable] = ListBuffer()
@ -167,6 +169,7 @@ class Zone(val id: String, val map: ZoneMap, zoneNumber: Int) {
def init(implicit context: ActorContext): Unit = {
if (accessor == ActorRef.noSender) {
SetupNumberPools()
taskResolver = CreateTaskResolvers(context)
accessor = context.actorOf(
RandomPool(25).props(
Props(classOf[UniqueNumberSystem], this.guid, UniqueNumberSystem.AllocateNumberPoolActors(this.guid))
@ -790,6 +793,12 @@ class Zone(val id: String, val map: ZoneMap, zoneNumber: Int) {
vehicleEvents = bus
VehicleEvents
}
def tasks: ActorRef = taskResolver
protected def CreateTaskResolvers(context: ActorContext, numberCreated: Int = 20): ActorRef = {
context.actorOf(RandomPool(numberCreated).props(Props[TaskResolver]()), s"zone-$id-taskResolver")
}
}
object Zone {

View file

@ -30,7 +30,7 @@ import scala.util.Success
* and finally unregistering it.
* Some types of object have (de-)implementation variations which should be made explicit through the overrides.
*/
abstract class RemoverActor extends SupportActor[RemoverActor.Entry] {
abstract class RemoverActor(val taskResolver: ActorRef) extends SupportActor[RemoverActor.Entry] {
/**
* The timer that checks whether entries in the first pool are still eligible for that pool.
@ -52,24 +52,12 @@ abstract class RemoverActor extends SupportActor[RemoverActor.Entry] {
*/
var secondHeap: List[RemoverActor.Entry] = List()
protected var taskResolver: ActorRef = ActorRef.noSender
val sameEntryComparator = new SimilarityComparator[RemoverActor.Entry]() {
def Test(entry1: RemoverActor.Entry, entry2: RemoverActor.Entry): Boolean = {
entry1.obj == entry2.obj && entry1.zone == entry2.zone && entry1.obj.GUID == entry2.obj.GUID
}
}
/**
* Send the initial message that requests a task resolver for assisting in the removal process.
*/
override def preStart(): Unit = {
super.preStart()
ServiceManager.serviceManager ! ServiceManager.Lookup(
"taskResolver"
) //ask for a resolver to deal with the GUID system
}
/**
* Sufficiently clean up the current contents of these waiting removal jobs.
* Cancel all timers, rush all entries in the lists through their individual steps, then empty the lists.
@ -88,19 +76,9 @@ abstract class RemoverActor extends SupportActor[RemoverActor.Entry] {
}
firstHeap = Nil
secondHeap = Nil
taskResolver = ActorRef.noSender
}
def receive: Receive = {
case ServiceManager.LookupResult("taskResolver", endpoint) =>
taskResolver = endpoint
context.become(Processing)
case msg =>
debug(s"received message $msg before being properly initialized")
}
def Processing: Receive =
def receive: Receive =
entryManagementBehaviors
.orElse {
case RemoverActor.AddTask(obj, zone, duration) =>

View file

@ -49,9 +49,6 @@ class AccountPersistenceService extends Actor {
/** squad service event hook */
var squad: ActorRef = ActorRef.noSender
/** task resolver service event hook */
var resolver: ActorRef = ActorRef.noSender
/** log, for trace and warnings only */
val log = org.log4s.getLogger
@ -62,7 +59,6 @@ class AccountPersistenceService extends Actor {
*/
override def preStart(): Unit = {
ServiceManager.serviceManager ! ServiceManager.Lookup("squad")
ServiceManager.serviceManager ! ServiceManager.Lookup("taskResolver")
log.trace("Awaiting system service hooks ...")
}
@ -130,17 +126,9 @@ class AccountPersistenceService extends Actor {
* @see `ServiceManager.LookupResult`
*/
val Setup: Receive = {
case ServiceManager.LookupResult(id, endpoint) =>
id match {
case "squad" =>
squad = endpoint
case "taskResolver" =>
resolver = endpoint
}
if (
squad != ActorRef.noSender &&
resolver != ActorRef.noSender
) {
case ServiceManager.LookupResult("squad", endpoint) =>
squad = endpoint
if (squad != ActorRef.noSender) {
log.trace("Service hooks obtained. Continuing with standard operation.")
context.become(Started)
}
@ -156,7 +144,7 @@ class AccountPersistenceService extends Actor {
*/
def CreateNewPlayerToken(name: String): ActorRef = {
val ref =
context.actorOf(Props(classOf[PersistenceMonitor], name, squad, resolver), s"$name-${NextPlayerIndex(name)}")
context.actorOf(Props(classOf[PersistenceMonitor], name, squad), s"$name-${NextPlayerIndex(name)}")
accounts += name -> ref
ref
}
@ -231,10 +219,8 @@ object AccountPersistenceService {
* and to determine the conditions for end-of-life activity.
* @param name the unique name of the player
* @param squadService a hook into the `SquadService` event system
* @param taskResolver a hook into the `TaskResolver` event system;
* used for object unregistering
*/
class PersistenceMonitor(name: String, squadService: ActorRef, taskResolver: ActorRef) extends Actor {
class PersistenceMonitor(name: String, squadService: ActorRef) extends Actor {
/** the last-reported zone of this player */
var inZone: Zone = Zone.Nowhere
@ -404,7 +390,7 @@ class PersistenceMonitor(name: String, squadService: ActorRef, taskResolver: Act
}
inZone.Population.tell(Zone.Population.Release(avatar), parent)
inZone.AvatarEvents.tell(AvatarServiceMessage(inZone.id, AvatarAction.ObjectDelete(pguid, pguid)), parent)
taskResolver.tell(GUIDTask.UnregisterPlayer(player)(inZone.GUID), parent)
inZone.tasks.tell(GUIDTask.UnregisterPlayer(player)(inZone.GUID), parent)
AvatarLogout(avatar)
}
@ -423,7 +409,7 @@ class PersistenceMonitor(name: String, squadService: ActorRef, taskResolver: Act
squadService.tell(Service.Leave(Some(avatar.id.toString)), context.parent)
Deployables.Disown(inZone, avatar, context.parent)
inZone.Population.tell(Zone.Population.Leave(avatar), context.parent)
taskResolver.tell(GUIDTask.UnregisterObjectTask(avatar.locker)(inZone.GUID), context.parent)
inZone.tasks.tell(GUIDTask.UnregisterObjectTask(avatar.locker)(inZone.GUID), context.parent)
log.info(s"logout of ${avatar.name}")
}
}

View file

@ -10,8 +10,8 @@ import net.psforever.services.avatar.support.{CorpseRemovalActor, DroppedItemRem
import net.psforever.services.{GenericEventBus, RemoverActor, Service}
class AvatarService(zone: Zone) extends Actor {
private val undertaker: ActorRef = context.actorOf(Props[CorpseRemovalActor](), s"${zone.id}-corpse-removal-agent")
private val janitor = context.actorOf(Props[DroppedItemRemover](), s"${zone.id}-item-remover-agent")
private val undertaker: ActorRef = context.actorOf(Props(classOf[CorpseRemovalActor], zone.tasks), s"${zone.id}-corpse-removal-agent")
private val janitor = context.actorOf(Props(classOf[DroppedItemRemover], zone.tasks), s"${zone.id}-item-remover-agent")
private[this] val log = org.log4s.getLogger

View file

@ -1,6 +1,7 @@
// Copyright (c) 2017 PSForever
package net.psforever.services.avatar.support
import akka.actor.ActorRef
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
import net.psforever.objects.Player
import net.psforever.types.ExoSuitType
@ -9,7 +10,7 @@ import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
import scala.concurrent.duration._
class CorpseRemovalActor extends RemoverActor {
class CorpseRemovalActor(taskResolver: ActorRef) extends RemoverActor(taskResolver) {
final val FirstStandardDuration: FiniteDuration = 1 minute
final val SecondStandardDuration: FiniteDuration = 500 milliseconds

View file

@ -1,6 +1,7 @@
// Copyright (c) 2017 PSForever
package net.psforever.services.avatar.support
import akka.actor.ActorRef
import net.psforever.objects.equipment.Equipment
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
import net.psforever.services.{RemoverActor, Service}
@ -8,7 +9,7 @@ import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
import scala.concurrent.duration._
class DroppedItemRemover extends RemoverActor {
class DroppedItemRemover(taskResolver: ActorRef) extends RemoverActor(taskResolver) {
final val FirstStandardDuration: FiniteDuration = 3 minutes
final val SecondStandardDuration: FiniteDuration = 500 milliseconds

View file

@ -26,7 +26,7 @@ class LocalService(zone: Zone) extends Actor {
private val doorCloser = context.actorOf(Props[DoorCloseActor](), s"${zone.id}-local-door-closer")
private val hackClearer = context.actorOf(Props[HackClearActor](), s"${zone.id}-local-hack-clearer")
private val hackCapturer = context.actorOf(Props[HackCaptureActor](), s"${zone.id}-local-hack-capturer")
private val engineer = context.actorOf(Props[DeployableRemover](), s"${zone.id}-deployable-remover-agent")
private val engineer = context.actorOf(Props(classOf[DeployableRemover], zone.tasks), s"${zone.id}-deployable-remover-agent")
private val teleportDeployment: ActorRef =
context.actorOf(Props[RouterTelepadActivation](), s"${zone.id}-telepad-activate-agent")
private[this] val log = org.log4s.getLogger

View file

@ -1,6 +1,7 @@
// Copyright (c) 2017 PSForever
package net.psforever.services.local.support
import akka.actor.ActorRef
import net.psforever.objects.ce.Deployable
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
import net.psforever.objects.zones.Zone
@ -10,7 +11,7 @@ import net.psforever.services.RemoverActor
import scala.concurrent.duration._
class DeployableRemover extends RemoverActor {
class DeployableRemover(taskResolver: ActorRef) extends RemoverActor(taskResolver) {
final val FirstStandardDuration: FiniteDuration = 3 minutes
final val SecondStandardDuration: FiniteDuration = 2 seconds
@ -64,7 +65,7 @@ class DeployableRemover extends RemoverActor {
boomer.Trigger match {
case Some(trigger) =>
boomer.Trigger = None
taskResolver ! GUIDTask.UnregisterObjectTask(trigger)(entry.zone.GUID)
boomer.Zone.tasks ! GUIDTask.UnregisterObjectTask(trigger)(entry.zone.GUID)
case None => ;
}
GUIDTask.UnregisterObjectTask(boomer)(entry.zone.GUID)

View file

@ -10,12 +10,11 @@ import net.psforever.objects.vital.RepairFromTerm
import net.psforever.objects.zones.Zone
import net.psforever.packet.game.ObjectCreateMessage
import net.psforever.packet.game.objectcreate.ObjectCreateMessageParent
import net.psforever.services.vehicle.support.{TurretUpgrader, VehicleRemover}
import net.psforever.services.vehicle.support.TurretUpgrader
import net.psforever.types.{DriveState, PlanetSideGUID}
import net.psforever.services.{GenericEventBus, RemoverActor, Service}
import net.psforever.services.{GenericEventBus, Service}
class VehicleService(zone: Zone) extends Actor {
private val vehicleDecon: ActorRef = context.actorOf(Props[VehicleRemover](), s"${zone.id}-vehicle-decon-agent")
private val turretUpgrade: ActorRef = context.actorOf(Props[TurretUpgrader](), s"${zone.id}-turret-upgrade-agent")
private[this] val log = org.log4s.getLogger
@ -157,8 +156,7 @@ class VehicleService(zone: Zone) extends Actor {
)
)
)
case VehicleAction.UnloadVehicle(player_guid, continent, vehicle, vehicle_guid) =>
vehicleDecon ! RemoverActor.ClearSpecific(List(vehicle), continent) //precaution
case VehicleAction.UnloadVehicle(player_guid, vehicle, vehicle_guid) =>
VehicleEvents.publish(
VehicleServiceResponse(
s"/$forChannel/Vehicle",
@ -246,10 +244,6 @@ class VehicleService(zone: Zone) extends Actor {
case _ => ;
}
//message to VehicleRemover
case VehicleServiceMessage.Decon(msg) =>
vehicleDecon forward msg
//message to TurretUpgrader
case VehicleServiceMessage.TurretUpgrade(msg) =>
turretUpgrade forward msg

View file

@ -15,8 +15,6 @@ object VehicleServiceMessage {
final case class GiveActorControl(vehicle: Vehicle, actorName: String)
final case class RevokeActorControl(vehicle: Vehicle)
final case class Decon(msg: Any)
final case class TurretUpgrade(msg: Any)
final case class AMSDeploymentChange(zone: Zone)
@ -83,7 +81,6 @@ object VehicleAction {
extends Action
final case class UnloadVehicle(
player_guid: PlanetSideGUID,
continent: Zone,
vehicle: Vehicle,
vehicle_guid: PlanetSideGUID
) extends Action

View file

@ -2,6 +2,7 @@
package net.psforever.services.vehicle.support
import akka.actor.{ActorRef, Cancellable}
import net.psforever.objects.equipment.EquipmentSlot
import net.psforever.objects.{AmmoBox, Default, PlanetSideGameObject, Tool}
import net.psforever.objects.guid.{GUIDTask, Task, TaskResolver}
import net.psforever.objects.serverobject.PlanetSideServerObject
@ -11,7 +12,6 @@ import net.psforever.objects.zones.Zone
import net.psforever.types.PlanetSideGUID
import net.psforever.services.support.{SimilarityComparator, SupportActor, SupportActorCaseConversions}
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
import net.psforever.services.{Service, ServiceManager}
import scala.concurrent.duration._
import scala.util.Success
@ -21,22 +21,12 @@ class TurretUpgrader extends SupportActor[TurretUpgrader.Entry] {
var list: List[TurretUpgrader.Entry] = List()
private var taskResolver: ActorRef = ActorRef.noSender
val sameEntryComparator = new SimilarityComparator[TurretUpgrader.Entry]() {
def Test(entry1: TurretUpgrader.Entry, entry2: TurretUpgrader.Entry): Boolean = {
entry1.obj == entry2.obj && entry1.zone == entry2.zone && entry1.obj.GUID == entry2.obj.GUID
}
}
/**
* Send the initial message that requests a task resolver for assisting in the removal process.
*/
override def preStart(): Unit = {
super.preStart()
self ! Service.Startup()
}
/**
* Sufficiently clean up the current contents of these waiting removal jobs.
* Cancel all timers, rush all entries in the lists through their individual steps, then empty the lists.
@ -49,7 +39,6 @@ class TurretUpgrader extends SupportActor[TurretUpgrader.Entry] {
UpgradeTurretAmmo
}
list = Nil
taskResolver = ActorRef.noSender
}
def CreateEntry(obj: PlanetSideGameObject, zone: Zone, upgrade: TurretUpgrade.Value, duration: Long) =
@ -57,21 +46,7 @@ class TurretUpgrader extends SupportActor[TurretUpgrader.Entry] {
def InclusionTest(entry: TurretUpgrader.Entry): Boolean = entry.obj.isInstanceOf[FacilityTurret]
def receive: Receive = {
case Service.Startup() =>
ServiceManager.serviceManager ! ServiceManager.Lookup(
"taskResolver"
) //ask for a resolver to deal with the GUID system
case ServiceManager.LookupResult("taskResolver", endpoint) =>
taskResolver = endpoint
context.become(Processing)
case msg =>
debug(s"received message $msg before being properly initialized")
}
def Processing: Receive =
def receive: Receive =
entryManagementBehaviors
.orElse {
case TurretUpgrader.AddTask(turret, zone, upgrade, duration) =>
@ -219,7 +194,7 @@ class TurretUpgrader extends SupportActor[TurretUpgrader.Entry] {
.map(box => GUIDTask.RegisterEquipment(box)(guid))
.toList
)
taskResolver ! TaskResolver.GiveTask(
target.Zone.tasks ! TaskResolver.GiveTask(
new Task() {
private val tasks = oldBoxesTask
@ -258,7 +233,7 @@ class TurretUpgrader extends SupportActor[TurretUpgrader.Entry] {
val targetGUID = target.GUID
if (target.Health > 0) {
target.Weapons
.map({ case (index, slot) => (index, slot.Equipment) })
.map({ case (index: Int, slot: EquipmentSlot) => (index, slot.Equipment) })
.collect {
case (index, Some(tool: Tool)) =>
context.parent ! VehicleServiceMessage(

View file

@ -1,33 +0,0 @@
// Copyright (c) 2017-2020 PSForever
package net.psforever.services.vehicle.support
import akka.actor.{Actor, ActorRef}
import net.psforever.objects.Vehicle
import net.psforever.objects.guid.GUIDTask.UnregisterVehicle
import net.psforever.services.{RemoverActor, ServiceManager}
class VehicleRemover extends Actor {
var taskResolver: ActorRef = ActorRef.noSender
override def preStart(): Unit = {
super.preStart()
ServiceManager.serviceManager ! ServiceManager.Lookup(
"taskResolver"
) //ask for a resolver to deal with the GUID system
}
def receive: Receive = {
case ServiceManager.LookupResult("taskResolver", endpoint) =>
taskResolver = endpoint
context.become(Processing)
case _ => ;
}
def Processing: Receive = {
case RemoverActor.AddTask(obj: Vehicle, zone, _) =>
taskResolver ! UnregisterVehicle(obj)(zone.GUID)
case _ => ;
}
}

View file

@ -16,11 +16,13 @@ import net.psforever.objects.vital.Vitality
import net.psforever.objects.vital.damage.DamageProfile
import net.psforever.objects.zones.{Zone, ZoneMap}
import net.psforever.objects.{GlobalDefinitions, Player, Tool}
import net.psforever.services.ServiceManager
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire, Vector3}
import scala.concurrent.duration._
class AutoRepairRequestNtuTest extends FreedContextActorTest {
ServiceManager.boot
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player.Spawn()
val weapon = new Tool(GlobalDefinitions.suppressor)
@ -80,6 +82,7 @@ class AutoRepairRequestNtuTest extends FreedContextActorTest {
}
class AutoRepairRequestNtuRepeatTest extends FreedContextActorTest {
ServiceManager.boot
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player.Spawn()
val weapon = new Tool(GlobalDefinitions.suppressor)
@ -141,6 +144,7 @@ class AutoRepairRequestNtuRepeatTest extends FreedContextActorTest {
}
class AutoRepairNoRequestNtuTest extends FreedContextActorTest {
ServiceManager.boot
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player.Spawn()
val weapon = new Tool(GlobalDefinitions.suppressor)
@ -195,6 +199,7 @@ class AutoRepairNoRequestNtuTest extends FreedContextActorTest {
}
class AutoRepairRestoreRequestNtuTest extends FreedContextActorTest {
ServiceManager.boot
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player.Spawn()
val weapon = new Tool(GlobalDefinitions.suppressor)
@ -258,6 +263,7 @@ class AutoRepairRestoreRequestNtuTest extends FreedContextActorTest {
}
class AutoRepairRepairWithNtuTest extends FreedContextActorTest {
ServiceManager.boot
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player.Spawn()
val weapon = new Tool(GlobalDefinitions.suppressor)
@ -316,6 +322,7 @@ class AutoRepairRepairWithNtuTest extends FreedContextActorTest {
}
class AutoRepairRepairWithNtuUntilDoneTest extends FreedContextActorTest {
ServiceManager.boot
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player.Spawn()
val weapon = new Tool(GlobalDefinitions.suppressor)

View file

@ -2,11 +2,10 @@
package objects
import akka.actor.{Actor, Props}
import akka.routing.RandomPool
import akka.testkit.TestProbe
import base.ActorTest
import net.psforever.actors.zone.{BuildingActor, ZoneActor}
import net.psforever.objects.guid.{NumberPoolHub, TaskResolver}
import net.psforever.objects.guid.NumberPoolHub
import net.psforever.objects.guid.source.MaxNumberSource
import net.psforever.objects.serverobject.CommonMessages
import net.psforever.objects.{GlobalDefinitions, Ntu, Player, Vehicle}
@ -17,7 +16,6 @@ import net.psforever.objects.zones.{Zone, ZoneMap}
import net.psforever.packet.game.UseItemMessage
import net.psforever.types._
import org.specs2.mutable.Specification
import net.psforever.services.ServiceManager
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
import akka.actor.typed.scaladsl.adapter._
import net.psforever.objects.avatar.Avatar
@ -77,18 +75,21 @@ class ResourceSiloTest extends Specification {
}
class ResourceSiloControlStartupTest extends ActorTest {
val serviceManager = ServiceManager.boot(system)
serviceManager ! ServiceManager.Register(RandomPool(1).props(Props[TaskResolver]()), "taskResolver")
val obj = ResourceSilo()
obj.GUID = PlanetSideGUID(1)
val probe = TestProbe()
serviceManager ! ServiceManager.Register(Props(classOf[ResourceSiloTest.ProbedAvatarService], probe), "avatar")
obj.Actor = system.actorOf(Props(classOf[ResourceSiloControl], obj), "test-silo")
val zone = new Zone("nowhere", new ZoneMap("nowhere-map"), 0)
val buildingEvents = TestProbe("test-building-events")
obj.Owner =
new Building("Building", building_guid = 6, map_id = 0, zone, StructureType.Building, GlobalDefinitions.building) {
Actor = buildingEvents.ref
}
obj.Owner.GUID = PlanetSideGUID(6)
"Resource silo" should {
"startup properly" in {
expectNoMessage(500 milliseconds)
system.actorOf(Props(classOf[ResourceSiloControl], obj), "test-silo") ! "startup"
expectNoMessage(1 seconds)
obj.Actor ! "startup"
expectNoMessage(max = 1000 milliseconds)
}
}
}

View file

@ -15,7 +15,7 @@ import net.psforever.objects.zones.{Zone, ZoneMap}
import net.psforever.packet.game.{CargoMountPointStatusMessage, ObjectDetachMessage, PlanetsideAttributeMessage}
import net.psforever.types.{PlanetSideGUID, _}
import org.specs2.mutable._
import net.psforever.services.{RemoverActor, ServiceManager}
import net.psforever.services.ServiceManager
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
import scala.concurrent.duration._
@ -342,23 +342,7 @@ class VehicleControlPrepareForDeletionTest extends ActorTest {
"VehicleControl" should {
"submit for unregistering when marked for deconstruction" in {
vehicle.Actor ! Vehicle.Deconstruct()
val vehicle_msg = vehicleProbe.receiveN(1, 500 milliseconds)
assert(
vehicle_msg.head match {
case VehicleServiceMessage.Decon(RemoverActor.AddTask(v, z, _)) => (v eq vehicle) && (z == vehicle.Zone)
case _ => false
}
)
val vehicle_msg_final = vehicleProbe.receiveN(1, 6 seconds)
assert(
vehicle_msg_final.head match {
case VehicleServiceMessage("test", VehicleAction.UnloadVehicle(_, z, v, PlanetSideGUID(1))) =>
(v eq vehicle) && (z == vehicle.Zone)
case _ => false
}
)
vehicleProbe.expectNoMessage(5 seconds)
}
}
}
@ -383,7 +367,7 @@ class VehicleControlPrepareForDeletionPassengerTest extends ActorTest {
"kick all players when marked for deconstruction" in {
vehicle.Actor ! Vehicle.Deconstruct()
val vehicle_msg = vehicleProbe.receiveN(2, 500 milliseconds)
val vehicle_msg = vehicleProbe.receiveN(1, 500 milliseconds)
assert(
vehicle_msg.head match {
case VehicleServiceMessage(
@ -396,12 +380,6 @@ class VehicleControlPrepareForDeletionPassengerTest extends ActorTest {
)
assert(player1.VehicleSeated.isEmpty)
assert(vehicle.Seats(1).Occupant.isEmpty)
assert(
vehicle_msg(1) match {
case VehicleServiceMessage.Decon(RemoverActor.AddTask(v, z, _)) => (v eq vehicle) && (z == vehicle.Zone)
case _ => false
}
)
}
}
}
@ -451,7 +429,7 @@ class VehicleControlPrepareForDeletionMountedInTest extends FreedContextActorTes
"if mounted as cargo, self-eject when marked for deconstruction" in {
vehicle.Actor ! Vehicle.Deconstruct()
val vehicle_msg = vehicleProbe.receiveN(7, 500 milliseconds)
val vehicle_msg = vehicleProbe.receiveN(6, 500 milliseconds)
//dismounting as cargo messages
assert(
vehicle_msg.head match {
@ -523,12 +501,6 @@ class VehicleControlPrepareForDeletionMountedInTest extends FreedContextActorTes
)
assert(player1.VehicleSeated.isEmpty)
assert(vehicle.Seats(1).Occupant.isEmpty)
assert(
vehicle_msg(6) match {
case VehicleServiceMessage.Decon(RemoverActor.AddTask(v, z, _)) => (v eq vehicle) && (z == vehicle.Zone)
case _ => false
}
)
}
}
}
@ -580,7 +552,7 @@ class VehicleControlPrepareForDeletionMountedCargoTest extends FreedContextActor
"if with mounted cargo, eject it when marked for deconstruction" in {
lodestar.Actor ! Vehicle.Deconstruct()
val vehicle_msg = vehicleProbe.receiveN(7, 500 milliseconds)
val vehicle_msg = vehicleProbe.receiveN(6, 500 milliseconds)
assert(
vehicle_msg.head match {
case VehicleServiceMessage(
@ -650,13 +622,6 @@ class VehicleControlPrepareForDeletionMountedCargoTest extends FreedContextActor
case _ => false
}
)
//cargo dismounting messages
assert(
vehicle_msg(6) match {
case VehicleServiceMessage.Decon(RemoverActor.AddTask(v, z, _)) => (v eq lodestar) && (z == vehicle.Zone)
case _ => false
}
)
}
}
}

View file

@ -2,6 +2,7 @@
package objects
import java.util.concurrent.atomic.AtomicInteger
import akka.actor.ActorContext
import base.ActorTest
import net.psforever.objects.entity.IdentifiableEntity
@ -19,6 +20,7 @@ import org.specs2.mutable.Specification
import akka.actor.typed.scaladsl.adapter._
import net.psforever.actors.zone.ZoneActor
import net.psforever.objects.avatar.Avatar
import net.psforever.services.ServiceManager
import scala.concurrent.duration._
@ -120,6 +122,7 @@ class ZoneTest extends Specification {
}
class ZoneActorTest extends ActorTest {
ServiceManager.boot
"Zone" should {
"refuse new number pools after the Actor is started" in {
val zone = new Zone("test", new ZoneMap("map6"), 1) { override def SetupNumberPools() = {} }

View file

@ -2,17 +2,20 @@
package service
import akka.actor.Props
import base.ActorTest
import akka.testkit.TestProbe
import base.{ActorTest, FreedContextActorTest}
import net.psforever.objects.{GlobalDefinitions, SensorDeployable, Vehicle}
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.serverobject.terminals.{ProximityTerminal, Terminal}
import net.psforever.objects.vehicles.VehicleControl
import net.psforever.objects.zones.Zone
import net.psforever.objects.zones.{Zone, ZoneMap}
import net.psforever.packet.game._
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID, Vector3}
import net.psforever.services.{Service, ServiceManager}
import net.psforever.services.local._
import scala.concurrent.duration._
class LocalService1Test extends ActorTest {
ServiceManager.boot(system)
@ -118,15 +121,19 @@ class DeployableMapIconTest extends ActorTest {
}
}
class DoorClosesTest extends ActorTest {
ServiceManager.boot(system)
class DoorClosesTest extends FreedContextActorTest {
val probe = new TestProbe(system)
val zone = new Zone("test", new ZoneMap("test-map"), 0) {
override def SetupNumberPools() : Unit = { }
}
zone.init(context)
expectNoMessage(500 milliseconds)
"LocalService" should {
"pass DoorCloses" in {
val service = system.actorOf(Props(classOf[LocalService], Zone.Nowhere), "l_service")
service ! Service.Join("test")
service ! LocalServiceMessage("test", LocalAction.DoorCloses(PlanetSideGUID(10), PlanetSideGUID(40)))
expectMsg(LocalServiceResponse("/test/Local", PlanetSideGUID(10), LocalResponse.DoorCloses(PlanetSideGUID(40))))
zone.LocalEvents.tell(Service.Join("test"), probe.ref)
zone.LocalEvents ! LocalServiceMessage("test", LocalAction.DoorCloses(PlanetSideGUID(10), PlanetSideGUID(40)))
probe.expectMsg(LocalServiceResponse("/test/Local", PlanetSideGUID(10), LocalResponse.DoorCloses(PlanetSideGUID(40))))
}
}
}

View file

@ -509,7 +509,7 @@ object RemoverActorTest {
final case class DeletionTaskRunAlert()
class TestRemover extends RemoverActor {
class TestRemover(taskResolver: ActorRef) extends RemoverActor(taskResolver) {
import net.psforever.objects.guid.{Task, TaskResolver}
val FirstStandardDuration = 1 seconds