Merge pull request #605 from Fate-JH/zone-resolver

Zone Task Resolver
This commit is contained in:
Fate-JH 2020-10-11 07:51:38 -04:00 committed by GitHub
commit 35b07f897d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
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.ActorSystem
import akka.actor.typed.ActorRef import akka.actor.typed.ActorRef
import akka.actor.typed.scaladsl.Behaviors import akka.actor.typed.scaladsl.Behaviors
import akka.routing.RandomPool
import akka.{actor => classic} import akka.{actor => classic}
import ch.qos.logback.classic.LoggerContext import ch.qos.logback.classic.LoggerContext
import ch.qos.logback.classic.joran.JoranConfigurator 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.psadmin.PsAdminActor
import net.psforever.login._ import net.psforever.login._
import net.psforever.objects.Default import net.psforever.objects.Default
import net.psforever.objects.guid.TaskResolver
import net.psforever.objects.zones._ import net.psforever.objects.zones._
import net.psforever.services.account.{AccountIntermediaryService, AccountPersistenceService} import net.psforever.services.account.{AccountIntermediaryService, AccountPersistenceService}
import net.psforever.services.chat.ChatService import net.psforever.services.chat.ChatService
@ -122,7 +120,6 @@ object Server {
val serviceManager = ServiceManager.boot val serviceManager = ServiceManager.boot
serviceManager ! ServiceManager.Register(classic.Props[AccountIntermediaryService](), "accountIntermediary") 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[GalaxyService](), "galaxy")
serviceManager ! ServiceManager.Register(classic.Props[SquadService](), "squad") serviceManager ! ServiceManager.Register(classic.Props[SquadService](), "squad")
serviceManager ! ServiceManager.Register(classic.Props[AccountPersistenceService](), "accountPersistence") 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 pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle) //order
val msg = probe.receiveOne(1 minute) val msg = probe.receiveOne(1 minute)
assert( // assert(
msg match { // msg match {
case VehicleServiceMessage.Decon(RemoverActor.AddTask(v, z, _)) => (v == vehicle) && (z == zone) // case VehicleServiceMessage.Decon(RemoverActor.AddTask(v, z, _)) => (v == vehicle) && (z == zone)
case _ => false // case _ => false
} // }
) // )
probe.expectNoMessage(5 seconds) probe.expectNoMessage(5 seconds)
} }
} }

View file

@ -2,10 +2,14 @@
package actor.service package actor.service
import akka.actor.Props import akka.actor.Props
import akka.routing.RandomPool import akka.testkit.TestProbe
import actor.base.ActorTest import scala.concurrent.duration._
import actor.base.{ActorTest, FreedContextActorTest}
import net.psforever.objects._ 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.objects.zones.{Zone, ZoneMap}
import net.psforever.packet.game.objectcreate.{DroppedItemData, ObjectClass, ObjectCreateMessageParent, PlacementData} import net.psforever.packet.game.objectcreate.{DroppedItemData, ObjectClass, ObjectCreateMessageParent, PlacementData}
import net.psforever.packet.game.{ObjectCreateMessage, PlayerStateMessageUpstream} 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.{RemoverActor, Service, ServiceManager}
import net.psforever.services.avatar._ 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 { class AvatarService1Test extends ActorTest {
"AvatarService" should { "AvatarService" should {
"construct" in { "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. 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. Even with all this work, the tests have a high chance of failure just due to being asynchronous.
*/ */
class AvatarReleaseTest extends ActorTest { class AvatarReleaseTest extends FreedContextActorTest {
ServiceManager.boot(system) ! ServiceManager.Register(RandomPool(1).props(Props[TaskResolver]()), "taskResolver") val guid: NumberPoolHub = new NumberPoolHub(new MaxNumberSource(15))
val zone = new Zone("test", new ZoneMap("test-map"), 0) { 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.init(context)
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, "TestCharacter", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1)) val obj = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1))
guid1.register(obj) guid.register(obj)
guid1.register(obj.Slot(5).Equipment.get) guid.register(obj.Slot(5).Equipment.get)
obj.Continent = "test" obj.Zone = zone
obj.Release obj.Release
val subscriber = new TestProbe(system)
"AvatarService" should { "AvatarService" should {
"pass Release" in { "pass Release" in {
expectNoMessage(100 milliseconds) //spacer expectNoMessage(100 milliseconds) //spacer
service ! Service.Join("test") zone.AvatarEvents.tell(Service.Join("test"), subscriber.ref)
assert(zone.Corpses.isEmpty) assert(zone.Corpses.isEmpty)
zone.Population ! Zone.Corpse.Add(obj) zone.Population ! Zone.Corpse.Add(obj)
expectNoMessage(200 milliseconds) //spacer subscriber.expectNoMessage(200 milliseconds) //spacer
assert(zone.Corpses.size == 1) assert(zone.Corpses.size == 1)
assert(obj.HasGUID) assert(obj.HasGUID)
val guid = obj.GUID 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]) assert(reply1.isInstanceOf[AvatarServiceResponse])
val reply1msg = reply1.asInstanceOf[AvatarServiceResponse] val reply1msg = reply1.asInstanceOf[AvatarServiceResponse]
assert(reply1msg.channel == "/test/Avatar") assert(reply1msg.channel == "/test/Avatar")
@ -544,7 +541,7 @@ class AvatarReleaseTest extends ActorTest {
assert(reply1msg.replyMessage.isInstanceOf[AvatarResponse.Release]) assert(reply1msg.replyMessage.isInstanceOf[AvatarResponse.Release])
assert(reply1msg.replyMessage.asInstanceOf[AvatarResponse.Release].player == obj) assert(reply1msg.replyMessage.asInstanceOf[AvatarResponse.Release].player == obj)
val reply2 = receiveOne(2 seconds) val reply2 = subscriber.receiveOne(2 seconds)
assert(reply2.isInstanceOf[AvatarServiceResponse]) assert(reply2.isInstanceOf[AvatarServiceResponse])
val reply2msg = reply2.asInstanceOf[AvatarServiceResponse] val reply2msg = reply2.asInstanceOf[AvatarServiceResponse]
assert(reply2msg.channel.equals("/test/Avatar")) assert(reply2msg.channel.equals("/test/Avatar"))
@ -552,43 +549,42 @@ 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)
expectNoMessage(1 seconds) subscriber.expectNoMessage(1 seconds)
assert(zone.Corpses.isEmpty) assert(zone.Corpses.isEmpty)
assert(!obj.HasGUID) assert(!obj.HasGUID)
} }
} }
} }
class AvatarReleaseEarly1Test extends ActorTest { class AvatarReleaseEarly1Test extends FreedContextActorTest {
ServiceManager.boot(system) ! ServiceManager.Register(RandomPool(1).props(Props[TaskResolver]()), "taskResolver") val guid: NumberPoolHub = new NumberPoolHub(new MaxNumberSource(15))
val zone = new Zone("test", new ZoneMap("test-map"), 0) { 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.init(context)
zone.GUID(guid1) val obj = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1))
val service = system.actorOf(Props(classOf[AvatarService], zone), "release-test-service") guid.register(obj)
zone.actor = system.spawn(ZoneActor(zone), "release-test-zone") guid.register(obj.Slot(5).Equipment.get)
val obj = Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1)) obj.Zone = zone
guid1.register(obj)
guid1.register(obj.Slot(5).Equipment.get)
obj.Continent = "test"
obj.Release obj.Release
val subscriber = new TestProbe(system)
"AvatarService" should { "AvatarService" should {
"pass Release" in { "pass Release" in {
expectNoMessage(100 milliseconds) //spacer expectNoMessage(100 milliseconds) //spacer
service ! Service.Join("test") zone.AvatarEvents.tell(Service.Join("test"), subscriber.ref)
assert(zone.Corpses.isEmpty) assert(zone.Corpses.isEmpty)
zone.Population ! Zone.Corpse.Add(obj) zone.Population ! Zone.Corpse.Add(obj)
expectNoMessage(200 milliseconds) //spacer subscriber.expectNoMessage(200 milliseconds) //spacer
assert(zone.Corpses.size == 1) assert(zone.Corpses.size == 1)
assert(obj.HasGUID) assert(obj.HasGUID)
val guid = obj.GUID 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]) assert(reply1.isInstanceOf[AvatarServiceResponse])
val reply1msg = reply1.asInstanceOf[AvatarServiceResponse] val reply1msg = reply1.asInstanceOf[AvatarServiceResponse]
assert(reply1msg.channel == "/test/Avatar") assert(reply1msg.channel == "/test/Avatar")
@ -596,8 +592,8 @@ class AvatarReleaseEarly1Test extends ActorTest {
assert(reply1msg.replyMessage.isInstanceOf[AvatarResponse.Release]) assert(reply1msg.replyMessage.isInstanceOf[AvatarResponse.Release])
assert(reply1msg.replyMessage.asInstanceOf[AvatarResponse.Release].player == obj) assert(reply1msg.replyMessage.asInstanceOf[AvatarResponse.Release].player == obj)
service ! AvatarServiceMessage.Corpse(RemoverActor.HurrySpecific(List(obj), zone)) //IMPORTANT: ONE ENTRY zone.AvatarEvents ! AvatarServiceMessage.Corpse(RemoverActor.HurrySpecific(List(obj), zone)) //IMPORTANT: ONE ENTRY
val reply2 = receiveOne(200 milliseconds) val reply2 = subscriber.receiveOne(200 milliseconds)
assert(reply2.isInstanceOf[AvatarServiceResponse]) assert(reply2.isInstanceOf[AvatarServiceResponse])
val reply2msg = reply2.asInstanceOf[AvatarServiceResponse] val reply2msg = reply2.asInstanceOf[AvatarServiceResponse]
assert(reply2msg.channel.equals("/test/Avatar")) assert(reply2msg.channel.equals("/test/Avatar"))
@ -605,49 +601,48 @@ 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)
expectNoMessage(1 seconds) subscriber.expectNoMessage(1 seconds)
assert(zone.Corpses.isEmpty) assert(zone.Corpses.isEmpty)
assert(!obj.HasGUID) assert(!obj.HasGUID)
} }
} }
} }
class AvatarReleaseEarly2Test extends ActorTest { class AvatarReleaseEarly2Test extends FreedContextActorTest {
ServiceManager.boot(system) ! ServiceManager.Register(RandomPool(1).props(Props[TaskResolver]()), "taskResolver") val guid: NumberPoolHub = new NumberPoolHub(new MaxNumberSource(15))
val zone = new Zone("test", new ZoneMap("test-map"), 0) { 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.init(context)
zone.GUID(guid1) val obj = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1))
val service = system.actorOf(Props(classOf[AvatarService], zone), "release-test-service") guid.register(obj)
zone.actor = system.spawn(ZoneActor(zone), "release-test-zone") guid.register(obj.Slot(5).Equipment.get)
val objAlt = obj.Zone = zone
Player( obj.Release
Avatar(0, "TestCharacter2", PlanetSideEmpire.NC, CharacterGender.Male, 1, CharacterVoice.Voice1) val objAlt = Player(
) //necessary clutter Avatar(0, "TestCharacter2", PlanetSideEmpire.NC, CharacterGender.Male, 1, CharacterVoice.Voice1)
) //necessary clutter
objAlt.GUID = PlanetSideGUID(3) objAlt.GUID = PlanetSideGUID(3)
objAlt.Slot(5).Equipment.get.GUID = PlanetSideGUID(4) objAlt.Slot(5).Equipment.get.GUID = PlanetSideGUID(4)
val obj = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1)) objAlt.Zone = zone
guid1.register(obj) val subscriber = new TestProbe(system)
guid1.register(obj.Slot(5).Equipment.get)
obj.Continent = "test"
obj.Release
"AvatarService" should { "AvatarService" should {
"pass Release" in { "pass Release" in {
expectNoMessage(100 milliseconds) //spacer expectNoMessage(100 milliseconds) //spacer
service ! Service.Join("test") zone.AvatarEvents.tell(Service.Join("test"), subscriber.ref)
assert(zone.Corpses.isEmpty) assert(zone.Corpses.isEmpty)
zone.Population ! Zone.Corpse.Add(obj) zone.Population ! Zone.Corpse.Add(obj)
expectNoMessage(200 milliseconds) //spacer subscriber.expectNoMessage(200 milliseconds) //spacer
assert(zone.Corpses.size == 1) assert(zone.Corpses.size == 1)
assert(obj.HasGUID) assert(obj.HasGUID)
val guid = obj.GUID 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]) assert(reply1.isInstanceOf[AvatarServiceResponse])
val reply1msg = reply1.asInstanceOf[AvatarServiceResponse] val reply1msg = reply1.asInstanceOf[AvatarServiceResponse]
assert(reply1msg.channel == "/test/Avatar") assert(reply1msg.channel == "/test/Avatar")
@ -655,10 +650,10 @@ class AvatarReleaseEarly2Test extends ActorTest {
assert(reply1msg.replyMessage.isInstanceOf[AvatarResponse.Release]) assert(reply1msg.replyMessage.isInstanceOf[AvatarResponse.Release])
assert(reply1msg.replyMessage.asInstanceOf[AvatarResponse.Release].player == obj) assert(reply1msg.replyMessage.asInstanceOf[AvatarResponse.Release].player == obj)
service ! AvatarServiceMessage.Corpse( zone.AvatarEvents ! AvatarServiceMessage.Corpse(
RemoverActor.HurrySpecific(List(objAlt, obj), zone) RemoverActor.HurrySpecific(List(objAlt, obj), zone)
) //IMPORTANT: TWO ENTRIES ) //IMPORTANT: TWO ENTRIES
val reply2 = receiveOne(100 milliseconds) val reply2 = subscriber.receiveOne(100 milliseconds)
assert(reply2.isInstanceOf[AvatarServiceResponse]) assert(reply2.isInstanceOf[AvatarServiceResponse])
val reply2msg = reply2.asInstanceOf[AvatarServiceResponse] val reply2msg = reply2.asInstanceOf[AvatarServiceResponse]
assert(reply2msg.channel.equals("/test/Avatar")) assert(reply2msg.channel.equals("/test/Avatar"))
@ -666,7 +661,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)
expectNoMessage(1 seconds) subscriber.expectNoMessage(1 seconds)
assert(zone.Corpses.isEmpty) assert(zone.Corpses.isEmpty)
assert(!obj.HasGUID) assert(!obj.HasGUID)
} }

View file

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

View file

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

View file

@ -2,12 +2,11 @@
package net.psforever.objects.serverobject.pad package net.psforever.objects.serverobject.pad
import akka.actor.{ActorContext, Cancellable, Props} 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.affinity.{FactionAffinity, FactionAffinityBehavior}
import net.psforever.objects.serverobject.pad.process.{VehicleSpawnControlBase, VehicleSpawnControlConcealPlayer} import net.psforever.objects.serverobject.pad.process.{VehicleSpawnControlBase, VehicleSpawnControlConcealPlayer}
import net.psforever.objects.zones.Zone import net.psforever.objects.zones.Zone
import net.psforever.objects.{Default, Player, Vehicle} import net.psforever.objects.{Default, Player, Vehicle}
import net.psforever.services.RemoverActor
import net.psforever.services.vehicle.VehicleServiceMessage
import scala.annotation.tailrec import scala.annotation.tailrec
import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.ExecutionContext.Implicits.global
@ -330,7 +329,7 @@ object VehicleSpawnControl {
if (zone.Vehicles.exists(_.GUID == vehicle.GUID)) { //already added to zone if (zone.Vehicles.exists(_.GUID == vehicle.GUID)) { //already added to zone
vehicle.Actor ! Vehicle.Deconstruct() vehicle.Actor ! Vehicle.Deconstruct()
} else { //just registered to zone } 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.ballistics.{ResolvedProjectile, VehicleSource}
import net.psforever.objects.ce.TelepadLike import net.psforever.objects.ce.TelepadLike
import net.psforever.objects.equipment.{Equipment, EquipmentSlot, JammableMountedWeapons} 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.inventory.{GridInventory, InventoryItem}
import net.psforever.objects.serverobject.CommonMessages import net.psforever.objects.serverobject.CommonMessages
import net.psforever.objects.serverobject.mount.{Mountable, MountableBehavior} 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.serverobject.terminals.Terminal
import net.psforever.objects.vital.VehicleShieldCharge import net.psforever.objects.vital.VehicleShieldCharge
import net.psforever.objects.zones.Zone import net.psforever.objects.zones.Zone
import net.psforever.services.RemoverActor
import net.psforever.packet.game._ import net.psforever.packet.game._
import net.psforever.packet.game.objectcreate.ObjectCreateMessageParent import net.psforever.packet.game.objectcreate.ObjectCreateMessageParent
import net.psforever.types.{DriveState, ExoSuitType, PlanetSideGUID, Vector3} import net.psforever.types.{DriveState, ExoSuitType, PlanetSideGUID, Vector3}
@ -338,7 +338,7 @@ class VehicleControl(vehicle: Vehicle)
} }
}) })
//unregister //unregister
events ! VehicleServiceMessage.Decon(RemoverActor.AddTask(vehicle, zone, Some(0 seconds))) zone.tasks ! GUIDTask.UnregisterVehicle(vehicle)(zone.GUID)
//banished to the shadow realm //banished to the shadow realm
vehicle.Position = Vector3.Zero vehicle.Position = Vector3.Zero
//queue final deletion //queue final deletion
@ -355,7 +355,7 @@ class VehicleControl(vehicle: Vehicle)
val zone = vehicle.Zone val zone = vehicle.Zone
zone.VehicleEvents ! VehicleServiceMessage( zone.VehicleEvents ! VehicleServiceMessage(
zone.id, zone.id,
VehicleAction.UnloadVehicle(Service.defaultPlayerGUID, zone, vehicle, vehicle.GUID) VehicleAction.UnloadVehicle(Service.defaultPlayerGUID, vehicle, vehicle.GUID)
) )
zone.Transport ! Zone.Vehicle.Despawn(vehicle) zone.Transport ! Zone.Vehicle.Despawn(vehicle)
case _ => case _ =>

View file

@ -8,7 +8,7 @@ import net.psforever.objects._
import net.psforever.objects.ce.Deployable import net.psforever.objects.ce.Deployable
import net.psforever.objects.entity.IdentifiableEntity import net.psforever.objects.entity.IdentifiableEntity
import net.psforever.objects.equipment.Equipment 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.actor.UniqueNumberSystem
import net.psforever.objects.guid.key.LoanedKey import net.psforever.objects.guid.key.LoanedKey
import net.psforever.objects.guid.selector.RandomSelector 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. */ /** Used by the `Zone` to coordinate `Equipment` dropping and collection requests. */
private var ground: ActorRef = Default.Actor private var ground: ActorRef = Default.Actor
private var taskResolver: ActorRef = Default.Actor
/** /**
*/ */
private val constructions: ListBuffer[PlanetSideGameObject with Deployable] = ListBuffer() 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 = { def init(implicit context: ActorContext): Unit = {
if (accessor == ActorRef.noSender) { if (accessor == ActorRef.noSender) {
SetupNumberPools() SetupNumberPools()
taskResolver = CreateTaskResolvers(context)
accessor = context.actorOf( accessor = context.actorOf(
RandomPool(25).props( RandomPool(25).props(
Props(classOf[UniqueNumberSystem], this.guid, UniqueNumberSystem.AllocateNumberPoolActors(this.guid)) 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 = bus
VehicleEvents 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 { object Zone {

View file

@ -30,7 +30,7 @@ import scala.util.Success
* and finally unregistering it. * and finally unregistering it.
* Some types of object have (de-)implementation variations which should be made explicit through the overrides. * 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. * 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() var secondHeap: List[RemoverActor.Entry] = List()
protected var taskResolver: ActorRef = ActorRef.noSender
val sameEntryComparator = new SimilarityComparator[RemoverActor.Entry]() { val sameEntryComparator = new SimilarityComparator[RemoverActor.Entry]() {
def Test(entry1: RemoverActor.Entry, entry2: RemoverActor.Entry): Boolean = { def Test(entry1: RemoverActor.Entry, entry2: RemoverActor.Entry): Boolean = {
entry1.obj == entry2.obj && entry1.zone == entry2.zone && entry1.obj.GUID == entry2.obj.GUID 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. * 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. * 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 firstHeap = Nil
secondHeap = Nil secondHeap = Nil
taskResolver = ActorRef.noSender
} }
def receive: Receive = { 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 =
entryManagementBehaviors entryManagementBehaviors
.orElse { .orElse {
case RemoverActor.AddTask(obj, zone, duration) => case RemoverActor.AddTask(obj, zone, duration) =>

View file

@ -49,9 +49,6 @@ class AccountPersistenceService extends Actor {
/** squad service event hook */ /** squad service event hook */
var squad: ActorRef = ActorRef.noSender var squad: ActorRef = ActorRef.noSender
/** task resolver service event hook */
var resolver: ActorRef = ActorRef.noSender
/** log, for trace and warnings only */ /** log, for trace and warnings only */
val log = org.log4s.getLogger val log = org.log4s.getLogger
@ -62,7 +59,6 @@ class AccountPersistenceService extends Actor {
*/ */
override def preStart(): Unit = { override def preStart(): Unit = {
ServiceManager.serviceManager ! ServiceManager.Lookup("squad") ServiceManager.serviceManager ! ServiceManager.Lookup("squad")
ServiceManager.serviceManager ! ServiceManager.Lookup("taskResolver")
log.trace("Awaiting system service hooks ...") log.trace("Awaiting system service hooks ...")
} }
@ -130,17 +126,9 @@ class AccountPersistenceService extends Actor {
* @see `ServiceManager.LookupResult` * @see `ServiceManager.LookupResult`
*/ */
val Setup: Receive = { val Setup: Receive = {
case ServiceManager.LookupResult(id, endpoint) => case ServiceManager.LookupResult("squad", endpoint) =>
id match { squad = endpoint
case "squad" => if (squad != ActorRef.noSender) {
squad = endpoint
case "taskResolver" =>
resolver = endpoint
}
if (
squad != ActorRef.noSender &&
resolver != ActorRef.noSender
) {
log.trace("Service hooks obtained. Continuing with standard operation.") log.trace("Service hooks obtained. Continuing with standard operation.")
context.become(Started) context.become(Started)
} }
@ -156,7 +144,7 @@ class AccountPersistenceService extends Actor {
*/ */
def CreateNewPlayerToken(name: String): ActorRef = { def CreateNewPlayerToken(name: String): ActorRef = {
val ref = 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 accounts += name -> ref
ref ref
} }
@ -231,10 +219,8 @@ object AccountPersistenceService {
* and to determine the conditions for end-of-life activity. * and to determine the conditions for end-of-life activity.
* @param name the unique name of the player * @param name the unique name of the player
* @param squadService a hook into the `SquadService` event system * @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 */ /** the last-reported zone of this player */
var inZone: Zone = Zone.Nowhere 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.Population.tell(Zone.Population.Release(avatar), parent)
inZone.AvatarEvents.tell(AvatarServiceMessage(inZone.id, AvatarAction.ObjectDelete(pguid, pguid)), 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) AvatarLogout(avatar)
} }
@ -423,7 +409,7 @@ class PersistenceMonitor(name: String, squadService: ActorRef, taskResolver: Act
squadService.tell(Service.Leave(Some(avatar.id.toString)), context.parent) squadService.tell(Service.Leave(Some(avatar.id.toString)), context.parent)
Deployables.Disown(inZone, avatar, context.parent) Deployables.Disown(inZone, avatar, context.parent)
inZone.Population.tell(Zone.Population.Leave(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}") 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} import net.psforever.services.{GenericEventBus, RemoverActor, Service}
class AvatarService(zone: Zone) extends Actor { class AvatarService(zone: Zone) extends Actor {
private val undertaker: ActorRef = context.actorOf(Props[CorpseRemovalActor](), s"${zone.id}-corpse-removal-agent") private val undertaker: ActorRef = context.actorOf(Props(classOf[CorpseRemovalActor], zone.tasks), s"${zone.id}-corpse-removal-agent")
private val janitor = context.actorOf(Props[DroppedItemRemover](), s"${zone.id}-item-remover-agent") private val janitor = context.actorOf(Props(classOf[DroppedItemRemover], zone.tasks), s"${zone.id}-item-remover-agent")
private[this] val log = org.log4s.getLogger private[this] val log = org.log4s.getLogger

View file

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

View file

@ -1,6 +1,7 @@
// Copyright (c) 2017 PSForever // Copyright (c) 2017 PSForever
package net.psforever.services.avatar.support package net.psforever.services.avatar.support
import akka.actor.ActorRef
import net.psforever.objects.equipment.Equipment import net.psforever.objects.equipment.Equipment
import net.psforever.objects.guid.{GUIDTask, TaskResolver} import net.psforever.objects.guid.{GUIDTask, TaskResolver}
import net.psforever.services.{RemoverActor, Service} import net.psforever.services.{RemoverActor, Service}
@ -8,7 +9,7 @@ import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
import scala.concurrent.duration._ import scala.concurrent.duration._
class DroppedItemRemover extends RemoverActor { class DroppedItemRemover(taskResolver: ActorRef) extends RemoverActor(taskResolver) {
final val FirstStandardDuration: FiniteDuration = 3 minutes final val FirstStandardDuration: FiniteDuration = 3 minutes
final val SecondStandardDuration: FiniteDuration = 500 milliseconds 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 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 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 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 = private val teleportDeployment: ActorRef =
context.actorOf(Props[RouterTelepadActivation](), s"${zone.id}-telepad-activate-agent") context.actorOf(Props[RouterTelepadActivation](), s"${zone.id}-telepad-activate-agent")
private[this] val log = org.log4s.getLogger private[this] val log = org.log4s.getLogger

View file

@ -1,6 +1,7 @@
// Copyright (c) 2017 PSForever // Copyright (c) 2017 PSForever
package net.psforever.services.local.support package net.psforever.services.local.support
import akka.actor.ActorRef
import net.psforever.objects.ce.Deployable import net.psforever.objects.ce.Deployable
import net.psforever.objects.guid.{GUIDTask, TaskResolver} import net.psforever.objects.guid.{GUIDTask, TaskResolver}
import net.psforever.objects.zones.Zone import net.psforever.objects.zones.Zone
@ -10,7 +11,7 @@ import net.psforever.services.RemoverActor
import scala.concurrent.duration._ import scala.concurrent.duration._
class DeployableRemover extends RemoverActor { class DeployableRemover(taskResolver: ActorRef) extends RemoverActor(taskResolver) {
final val FirstStandardDuration: FiniteDuration = 3 minutes final val FirstStandardDuration: FiniteDuration = 3 minutes
final val SecondStandardDuration: FiniteDuration = 2 seconds final val SecondStandardDuration: FiniteDuration = 2 seconds
@ -64,7 +65,7 @@ class DeployableRemover extends RemoverActor {
boomer.Trigger match { boomer.Trigger match {
case Some(trigger) => case Some(trigger) =>
boomer.Trigger = None boomer.Trigger = None
taskResolver ! GUIDTask.UnregisterObjectTask(trigger)(entry.zone.GUID) boomer.Zone.tasks ! GUIDTask.UnregisterObjectTask(trigger)(entry.zone.GUID)
case None => ; case None => ;
} }
GUIDTask.UnregisterObjectTask(boomer)(entry.zone.GUID) 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.objects.zones.Zone
import net.psforever.packet.game.ObjectCreateMessage import net.psforever.packet.game.ObjectCreateMessage
import net.psforever.packet.game.objectcreate.ObjectCreateMessageParent 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.types.{DriveState, PlanetSideGUID}
import net.psforever.services.{GenericEventBus, RemoverActor, Service} import net.psforever.services.{GenericEventBus, Service}
class VehicleService(zone: Zone) extends Actor { 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 val turretUpgrade: ActorRef = context.actorOf(Props[TurretUpgrader](), s"${zone.id}-turret-upgrade-agent")
private[this] val log = org.log4s.getLogger 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) => case VehicleAction.UnloadVehicle(player_guid, vehicle, vehicle_guid) =>
vehicleDecon ! RemoverActor.ClearSpecific(List(vehicle), continent) //precaution
VehicleEvents.publish( VehicleEvents.publish(
VehicleServiceResponse( VehicleServiceResponse(
s"/$forChannel/Vehicle", s"/$forChannel/Vehicle",
@ -246,10 +244,6 @@ class VehicleService(zone: Zone) extends Actor {
case _ => ; case _ => ;
} }
//message to VehicleRemover
case VehicleServiceMessage.Decon(msg) =>
vehicleDecon forward msg
//message to TurretUpgrader //message to TurretUpgrader
case VehicleServiceMessage.TurretUpgrade(msg) => case VehicleServiceMessage.TurretUpgrade(msg) =>
turretUpgrade forward msg turretUpgrade forward msg

View file

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

View file

@ -2,6 +2,7 @@
package net.psforever.services.vehicle.support package net.psforever.services.vehicle.support
import akka.actor.{ActorRef, Cancellable} import akka.actor.{ActorRef, Cancellable}
import net.psforever.objects.equipment.EquipmentSlot
import net.psforever.objects.{AmmoBox, Default, PlanetSideGameObject, Tool} import net.psforever.objects.{AmmoBox, Default, PlanetSideGameObject, Tool}
import net.psforever.objects.guid.{GUIDTask, Task, TaskResolver} import net.psforever.objects.guid.{GUIDTask, Task, TaskResolver}
import net.psforever.objects.serverobject.PlanetSideServerObject import net.psforever.objects.serverobject.PlanetSideServerObject
@ -11,7 +12,6 @@ import net.psforever.objects.zones.Zone
import net.psforever.types.PlanetSideGUID import net.psforever.types.PlanetSideGUID
import net.psforever.services.support.{SimilarityComparator, SupportActor, SupportActorCaseConversions} import net.psforever.services.support.{SimilarityComparator, SupportActor, SupportActorCaseConversions}
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage} import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
import net.psforever.services.{Service, ServiceManager}
import scala.concurrent.duration._ import scala.concurrent.duration._
import scala.util.Success import scala.util.Success
@ -21,22 +21,12 @@ class TurretUpgrader extends SupportActor[TurretUpgrader.Entry] {
var list: List[TurretUpgrader.Entry] = List() var list: List[TurretUpgrader.Entry] = List()
private var taskResolver: ActorRef = ActorRef.noSender
val sameEntryComparator = new SimilarityComparator[TurretUpgrader.Entry]() { val sameEntryComparator = new SimilarityComparator[TurretUpgrader.Entry]() {
def Test(entry1: TurretUpgrader.Entry, entry2: TurretUpgrader.Entry): Boolean = { def Test(entry1: TurretUpgrader.Entry, entry2: TurretUpgrader.Entry): Boolean = {
entry1.obj == entry2.obj && entry1.zone == entry2.zone && entry1.obj.GUID == entry2.obj.GUID 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. * 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. * 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 UpgradeTurretAmmo
} }
list = Nil list = Nil
taskResolver = ActorRef.noSender
} }
def CreateEntry(obj: PlanetSideGameObject, zone: Zone, upgrade: TurretUpgrade.Value, duration: Long) = 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 InclusionTest(entry: TurretUpgrader.Entry): Boolean = entry.obj.isInstanceOf[FacilityTurret]
def receive: Receive = { 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 =
entryManagementBehaviors entryManagementBehaviors
.orElse { .orElse {
case TurretUpgrader.AddTask(turret, zone, upgrade, duration) => case TurretUpgrader.AddTask(turret, zone, upgrade, duration) =>
@ -219,7 +194,7 @@ class TurretUpgrader extends SupportActor[TurretUpgrader.Entry] {
.map(box => GUIDTask.RegisterEquipment(box)(guid)) .map(box => GUIDTask.RegisterEquipment(box)(guid))
.toList .toList
) )
taskResolver ! TaskResolver.GiveTask( target.Zone.tasks ! TaskResolver.GiveTask(
new Task() { new Task() {
private val tasks = oldBoxesTask private val tasks = oldBoxesTask
@ -258,7 +233,7 @@ class TurretUpgrader extends SupportActor[TurretUpgrader.Entry] {
val targetGUID = target.GUID val targetGUID = target.GUID
if (target.Health > 0) { if (target.Health > 0) {
target.Weapons target.Weapons
.map({ case (index, slot) => (index, slot.Equipment) }) .map({ case (index: Int, slot: EquipmentSlot) => (index, slot.Equipment) })
.collect { .collect {
case (index, Some(tool: Tool)) => case (index, Some(tool: Tool)) =>
context.parent ! VehicleServiceMessage( 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.vital.damage.DamageProfile
import net.psforever.objects.zones.{Zone, ZoneMap} import net.psforever.objects.zones.{Zone, ZoneMap}
import net.psforever.objects.{GlobalDefinitions, Player, Tool} import net.psforever.objects.{GlobalDefinitions, Player, Tool}
import net.psforever.services.ServiceManager
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire, Vector3} import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire, Vector3}
import scala.concurrent.duration._ import scala.concurrent.duration._
class AutoRepairRequestNtuTest extends FreedContextActorTest { class AutoRepairRequestNtuTest extends FreedContextActorTest {
ServiceManager.boot
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player.Spawn() player.Spawn()
val weapon = new Tool(GlobalDefinitions.suppressor) val weapon = new Tool(GlobalDefinitions.suppressor)
@ -80,6 +82,7 @@ class AutoRepairRequestNtuTest extends FreedContextActorTest {
} }
class AutoRepairRequestNtuRepeatTest extends FreedContextActorTest { class AutoRepairRequestNtuRepeatTest extends FreedContextActorTest {
ServiceManager.boot
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player.Spawn() player.Spawn()
val weapon = new Tool(GlobalDefinitions.suppressor) val weapon = new Tool(GlobalDefinitions.suppressor)
@ -141,6 +144,7 @@ class AutoRepairRequestNtuRepeatTest extends FreedContextActorTest {
} }
class AutoRepairNoRequestNtuTest extends FreedContextActorTest { class AutoRepairNoRequestNtuTest extends FreedContextActorTest {
ServiceManager.boot
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player.Spawn() player.Spawn()
val weapon = new Tool(GlobalDefinitions.suppressor) val weapon = new Tool(GlobalDefinitions.suppressor)
@ -195,6 +199,7 @@ class AutoRepairNoRequestNtuTest extends FreedContextActorTest {
} }
class AutoRepairRestoreRequestNtuTest extends FreedContextActorTest { class AutoRepairRestoreRequestNtuTest extends FreedContextActorTest {
ServiceManager.boot
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player.Spawn() player.Spawn()
val weapon = new Tool(GlobalDefinitions.suppressor) val weapon = new Tool(GlobalDefinitions.suppressor)
@ -258,6 +263,7 @@ class AutoRepairRestoreRequestNtuTest extends FreedContextActorTest {
} }
class AutoRepairRepairWithNtuTest extends FreedContextActorTest { class AutoRepairRepairWithNtuTest extends FreedContextActorTest {
ServiceManager.boot
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player.Spawn() player.Spawn()
val weapon = new Tool(GlobalDefinitions.suppressor) val weapon = new Tool(GlobalDefinitions.suppressor)
@ -316,6 +322,7 @@ class AutoRepairRepairWithNtuTest extends FreedContextActorTest {
} }
class AutoRepairRepairWithNtuUntilDoneTest extends FreedContextActorTest { class AutoRepairRepairWithNtuUntilDoneTest extends FreedContextActorTest {
ServiceManager.boot
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player.Spawn() player.Spawn()
val weapon = new Tool(GlobalDefinitions.suppressor) val weapon = new Tool(GlobalDefinitions.suppressor)

View file

@ -2,11 +2,10 @@
package objects package objects
import akka.actor.{Actor, Props} import akka.actor.{Actor, Props}
import akka.routing.RandomPool
import akka.testkit.TestProbe import akka.testkit.TestProbe
import base.ActorTest import base.ActorTest
import net.psforever.actors.zone.{BuildingActor, ZoneActor} 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.guid.source.MaxNumberSource
import net.psforever.objects.serverobject.CommonMessages import net.psforever.objects.serverobject.CommonMessages
import net.psforever.objects.{GlobalDefinitions, Ntu, Player, Vehicle} 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.packet.game.UseItemMessage
import net.psforever.types._ import net.psforever.types._
import org.specs2.mutable.Specification import org.specs2.mutable.Specification
import net.psforever.services.ServiceManager
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage} import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
import akka.actor.typed.scaladsl.adapter._ import akka.actor.typed.scaladsl.adapter._
import net.psforever.objects.avatar.Avatar import net.psforever.objects.avatar.Avatar
@ -77,18 +75,21 @@ class ResourceSiloTest extends Specification {
} }
class ResourceSiloControlStartupTest extends ActorTest { class ResourceSiloControlStartupTest extends ActorTest {
val serviceManager = ServiceManager.boot(system)
serviceManager ! ServiceManager.Register(RandomPool(1).props(Props[TaskResolver]()), "taskResolver")
val obj = ResourceSilo() val obj = ResourceSilo()
obj.GUID = PlanetSideGUID(1) obj.GUID = PlanetSideGUID(1)
val probe = TestProbe() obj.Actor = system.actorOf(Props(classOf[ResourceSiloControl], obj), "test-silo")
serviceManager ! ServiceManager.Register(Props(classOf[ResourceSiloTest.ProbedAvatarService], probe), "avatar") 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 { "Resource silo" should {
"startup properly" in { "startup properly" in {
expectNoMessage(500 milliseconds) obj.Actor ! "startup"
system.actorOf(Props(classOf[ResourceSiloControl], obj), "test-silo") ! "startup" expectNoMessage(max = 1000 milliseconds)
expectNoMessage(1 seconds)
} }
} }
} }

View file

@ -15,7 +15,7 @@ import net.psforever.objects.zones.{Zone, ZoneMap}
import net.psforever.packet.game.{CargoMountPointStatusMessage, ObjectDetachMessage, PlanetsideAttributeMessage} import net.psforever.packet.game.{CargoMountPointStatusMessage, ObjectDetachMessage, PlanetsideAttributeMessage}
import net.psforever.types.{PlanetSideGUID, _} import net.psforever.types.{PlanetSideGUID, _}
import org.specs2.mutable._ import org.specs2.mutable._
import net.psforever.services.{RemoverActor, ServiceManager} import net.psforever.services.ServiceManager
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage} import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
import scala.concurrent.duration._ import scala.concurrent.duration._
@ -342,23 +342,7 @@ class VehicleControlPrepareForDeletionTest extends ActorTest {
"VehicleControl" should { "VehicleControl" should {
"submit for unregistering when marked for deconstruction" in { "submit for unregistering when marked for deconstruction" in {
vehicle.Actor ! Vehicle.Deconstruct() vehicle.Actor ! Vehicle.Deconstruct()
vehicleProbe.expectNoMessage(5 seconds)
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
}
)
} }
} }
} }
@ -383,7 +367,7 @@ class VehicleControlPrepareForDeletionPassengerTest extends ActorTest {
"kick all players when marked for deconstruction" in { "kick all players when marked for deconstruction" in {
vehicle.Actor ! Vehicle.Deconstruct() vehicle.Actor ! Vehicle.Deconstruct()
val vehicle_msg = vehicleProbe.receiveN(2, 500 milliseconds) val vehicle_msg = vehicleProbe.receiveN(1, 500 milliseconds)
assert( assert(
vehicle_msg.head match { vehicle_msg.head match {
case VehicleServiceMessage( case VehicleServiceMessage(
@ -396,12 +380,6 @@ class VehicleControlPrepareForDeletionPassengerTest extends ActorTest {
) )
assert(player1.VehicleSeated.isEmpty) assert(player1.VehicleSeated.isEmpty)
assert(vehicle.Seats(1).Occupant.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 { "if mounted as cargo, self-eject when marked for deconstruction" in {
vehicle.Actor ! Vehicle.Deconstruct() vehicle.Actor ! Vehicle.Deconstruct()
val vehicle_msg = vehicleProbe.receiveN(7, 500 milliseconds) val vehicle_msg = vehicleProbe.receiveN(6, 500 milliseconds)
//dismounting as cargo messages //dismounting as cargo messages
assert( assert(
vehicle_msg.head match { vehicle_msg.head match {
@ -523,12 +501,6 @@ class VehicleControlPrepareForDeletionMountedInTest extends FreedContextActorTes
) )
assert(player1.VehicleSeated.isEmpty) assert(player1.VehicleSeated.isEmpty)
assert(vehicle.Seats(1).Occupant.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 { "if with mounted cargo, eject it when marked for deconstruction" in {
lodestar.Actor ! Vehicle.Deconstruct() lodestar.Actor ! Vehicle.Deconstruct()
val vehicle_msg = vehicleProbe.receiveN(7, 500 milliseconds) val vehicle_msg = vehicleProbe.receiveN(6, 500 milliseconds)
assert( assert(
vehicle_msg.head match { vehicle_msg.head match {
case VehicleServiceMessage( case VehicleServiceMessage(
@ -650,13 +622,6 @@ class VehicleControlPrepareForDeletionMountedCargoTest extends FreedContextActor
case _ => false 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 package objects
import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger
import akka.actor.ActorContext import akka.actor.ActorContext
import base.ActorTest import base.ActorTest
import net.psforever.objects.entity.IdentifiableEntity import net.psforever.objects.entity.IdentifiableEntity
@ -19,6 +20,7 @@ import org.specs2.mutable.Specification
import akka.actor.typed.scaladsl.adapter._ import akka.actor.typed.scaladsl.adapter._
import net.psforever.actors.zone.ZoneActor import net.psforever.actors.zone.ZoneActor
import net.psforever.objects.avatar.Avatar import net.psforever.objects.avatar.Avatar
import net.psforever.services.ServiceManager
import scala.concurrent.duration._ import scala.concurrent.duration._
@ -120,6 +122,7 @@ class ZoneTest extends Specification {
} }
class ZoneActorTest extends ActorTest { class ZoneActorTest extends ActorTest {
ServiceManager.boot
"Zone" should { "Zone" should {
"refuse new number pools after the Actor is started" in { "refuse new number pools after the Actor is started" in {
val zone = new Zone("test", new ZoneMap("map6"), 1) { override def SetupNumberPools() = {} } val zone = new Zone("test", new ZoneMap("map6"), 1) { override def SetupNumberPools() = {} }

View file

@ -2,17 +2,20 @@
package service package service
import akka.actor.Props 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.{GlobalDefinitions, SensorDeployable, Vehicle}
import net.psforever.objects.serverobject.PlanetSideServerObject import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.serverobject.terminals.{ProximityTerminal, Terminal} import net.psforever.objects.serverobject.terminals.{ProximityTerminal, Terminal}
import net.psforever.objects.vehicles.VehicleControl 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.packet.game._
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID, Vector3} import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID, Vector3}
import net.psforever.services.{Service, ServiceManager} import net.psforever.services.{Service, ServiceManager}
import net.psforever.services.local._ import net.psforever.services.local._
import scala.concurrent.duration._
class LocalService1Test extends ActorTest { class LocalService1Test extends ActorTest {
ServiceManager.boot(system) ServiceManager.boot(system)
@ -118,15 +121,19 @@ class DeployableMapIconTest extends ActorTest {
} }
} }
class DoorClosesTest extends ActorTest { class DoorClosesTest extends FreedContextActorTest {
ServiceManager.boot(system) 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 { "LocalService" should {
"pass DoorCloses" in { "pass DoorCloses" in {
val service = system.actorOf(Props(classOf[LocalService], Zone.Nowhere), "l_service") zone.LocalEvents.tell(Service.Join("test"), probe.ref)
service ! Service.Join("test") zone.LocalEvents ! LocalServiceMessage("test", LocalAction.DoorCloses(PlanetSideGUID(10), PlanetSideGUID(40)))
service ! LocalServiceMessage("test", LocalAction.DoorCloses(PlanetSideGUID(10), PlanetSideGUID(40))) probe.expectMsg(LocalServiceResponse("/test/Local", PlanetSideGUID(10), LocalResponse.DoorCloses(PlanetSideGUID(40))))
expectMsg(LocalServiceResponse("/test/Local", PlanetSideGUID(10), LocalResponse.DoorCloses(PlanetSideGUID(40))))
} }
} }
} }

View file

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