PSF-LoginServer/src/test/scala/objects/DeployableBehaviorTest.scala

354 lines
16 KiB
Scala
Raw Normal View History

Deployable Behaviors (#840) * unifying the split code pathways that separated telepads from other deloyables; in other words, no more SimpleDeployables and ComplexDeployables, just Deployables * moved some aspects of the build logic into a deployable control mixin; aspects governing the deplpoyable toolbox have been transferred into the player control agency * moving aspects of teleportation system establishment and decomposition into specialized Telepad control agencies * retiring deployable disposal code path that required a dedicated remover; each deployable now handles its own removal, and some do special things when being removed; process still has some rough edges and tests are probably thoroughly broken * additional modifications to support boomers and telepads; consolidation of code for deployable acknowledgement by owner and during failure conditions; tests for behavior * retooled a significant portion of the build sequence and deconstruct sequence to: eliminate duplicate messages, give the player more input to and control over the process, remove undue responsibility thrust on SessionActor * messaging issue where player did not re-raise hand after exchanging a used construction tool for a new construction tool * modification to deconstruct path to make certain deplayble is unregistered last; ridding requirement of AlertDestroyDeployable; fixing test * create paths for unowned deployable building and (standard) owned deployable building; corrected activation and connection between telepad deployable and internal roouter telepad; wrote tests for connection between telepad deployable and internal telepad * modifiying the conditions of a deployable construction item being moved into a visible player slot such that the construction item's initial output is valid given the player's current certifications * by forcing the fire mode to revert briefly before the ammo type updates, the construction item can be made to remain consistent between fire mode shifts * construction tools now keep track of fire mode ammo types for a period of time, allowing one mode's last setting to be retained * greatly delayed rebase with master * minor changes; test correction (?) * router is go?
2021-06-02 15:51:38 +00:00
// Copyright (c) 2021 PSForever
package objects
import akka.actor.{ActorRef, Props}
import akka.testkit.TestProbe
import base.{ActorTest, FreedContextActorTest}
import net.psforever.objects.avatar.{Avatar, Certification, PlayerControl}
import net.psforever.objects.{ConstructionItem, Deployables, GlobalDefinitions, Player}
import net.psforever.objects.ce.{Deployable, DeployedItem}
import net.psforever.objects.guid.{NumberPoolHub, TaskResolver}
import net.psforever.objects.guid.source.MaxNumberSource
import net.psforever.objects.zones.{Zone, ZoneDeployableActor, ZoneMap}
import net.psforever.packet.game._
import net.psforever.services.Service
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
import net.psforever.types._
import scala.collection.mutable.ListBuffer
import scala.concurrent.duration._
class DeployableBehaviorSetupTest extends ActorTest {
val eventsProbe = new TestProbe(system)
val jmine = Deployables.Make(DeployedItem.jammer_mine)() //guid=1
val deployableList = new ListBuffer()
val guid = new NumberPoolHub(new MaxNumberSource(max = 5))
val zone = new Zone(id = "test", new ZoneMap(name = "test"), zoneNumber = 0) {
private val deployables = system.actorOf(Props(classOf[ZoneDeployableActor], this, deployableList), name = "test-zone-deployables")
override def SetupNumberPools(): Unit = {}
GUID(guid)
override def AvatarEvents: ActorRef = eventsProbe.ref
override def LocalEvents: ActorRef = eventsProbe.ref
override def Deployables: ActorRef = deployables
}
guid.register(jmine, number = 1)
jmine.Faction = PlanetSideEmpire.TR
jmine.Position = Vector3(1,2,3)
jmine.Orientation = Vector3(4,5,6)
"DeployableBehavior" should {
"perform self-setup" in {
assert(deployableList.isEmpty, "self-setup test - deployable list is not empty")
zone.Deployables ! Zone.Deployable.Build(jmine)
val eventsMsgs = eventsProbe.receiveN(3, 10.seconds)
eventsMsgs.head match {
case LocalServiceMessage(
"test",
LocalAction.TriggerEffectLocation(PlanetSideGUID(0), "spawn_object_effect", Vector3(1,2,3), Vector3(4,5,6))
) => ;
case _ => assert(false, "self-setup test - no spawn fx")
}
eventsMsgs(1) match {
case AvatarServiceMessage("test", AvatarAction.DeployItem(PlanetSideGUID(0), obj)) =>
assert(obj eq jmine, "self-setup test - not same mine")
case _ =>
assert( false, "self-setup test - wrong deploy message")
}
eventsMsgs(2) match {
case LocalServiceMessage(
"TR",
LocalAction.DeployableMapIcon(
PlanetSideGUID(0),
DeploymentAction.Build,
DeployableInfo(PlanetSideGUID(1), DeployableIcon.DisruptorMine, Vector3(1,2,3), PlanetSideGUID(0))
)
) => ;
case _ => assert(false, "self-setup test - no icon or wrong icon")
}
assert(deployableList.contains(jmine), "self-setup test - deployable not appended to list")
}
}
}
class DeployableBehaviorSetupOwnedP1Test extends ActorTest {
val eventsProbe = new TestProbe(system)
val avatar = Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterSex.Male, 0, CharacterVoice.Mute)
val player = Player(avatar) //guid=3
val jmine = Deployables.Make(DeployedItem.jammer_mine)() //guid=1
val citem = new ConstructionItem(GlobalDefinitions.ace) //guid = 2
val deployableList = new ListBuffer()
val guid = new NumberPoolHub(new MaxNumberSource(max = 5))
val zone = new Zone(id = "test", new ZoneMap(name = "test"), zoneNumber = 0) {
private val deployables = system.actorOf(Props(classOf[ZoneDeployableActor], this, deployableList), name = "test-zone-deployables")
override def SetupNumberPools(): Unit = {}
GUID(guid)
override def AvatarEvents: ActorRef = eventsProbe.ref
override def LocalEvents: ActorRef = eventsProbe.ref
override def Deployables: ActorRef = deployables
override def Players = List(avatar)
override def LivePlayers = List(player)
}
guid.register(jmine, number = 1)
guid.register(citem, number = 2)
guid.register(player, number = 3)
jmine.Faction = PlanetSideEmpire.TR
jmine.Position = Vector3(1,2,3)
jmine.Orientation = Vector3(4,5,6)
jmine.AssignOwnership(player)
"DeployableBehavior" should {
"receive setup functions after asking owner" in {
val playerProbe = new TestProbe(system)
player.Actor = playerProbe.ref
assert(deployableList.isEmpty, "owned setup test, 1 - deployable list is not empty")
zone.Deployables ! Zone.Deployable.BuildByOwner(jmine, player, citem)
playerProbe.receiveOne(200.milliseconds) match {
case Player.BuildDeployable(a, b) =>
assert((a eq jmine) && (b eq citem), "owned setup test, 1 - process echoing wrong mine or wrong construction item")
case _ =>
assert(false, "owned setup test, 1 - not echoing messages to owner")
}
}
}
}
class DeployableBehaviorSetupOwnedP2Test extends FreedContextActorTest {
val eventsProbe = new TestProbe(system)
val avatar = Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterSex.Male, 0, CharacterVoice.Mute)
val player = Player(avatar) //guid=3
val jmine = Deployables.Make(DeployedItem.jammer_mine)() //guid=1
val citem = new ConstructionItem(GlobalDefinitions.ace) //guid = 2
val deployableList = new ListBuffer()
val guid = new NumberPoolHub(new MaxNumberSource(max = 5))
val zone = new Zone(id = "test", new ZoneMap(name = "test"), zoneNumber = 0) {
private val deployables = system.actorOf(Props(classOf[ZoneDeployableActor], this, deployableList), name = "test-zone-deployables")
override def SetupNumberPools(): Unit = {}
GUID(guid)
override def AvatarEvents: ActorRef = eventsProbe.ref
override def LocalEvents: ActorRef = eventsProbe.ref
override def Deployables: ActorRef = deployables
override def Players = List(avatar)
override def LivePlayers = List(player)
override def tasks: ActorRef = eventsProbe.ref
}
guid.register(jmine, number = 1)
guid.register(citem, number = 2)
guid.register(player, number = 3)
guid.register(avatar.locker, number = 4)
jmine.Faction = PlanetSideEmpire.TR
jmine.Position = Vector3(1,2,3)
jmine.Orientation = Vector3(4,5,6)
jmine.AssignOwnership(player)
avatar.deployables.UpdateMaxCounts(Set(Certification.CombatEngineering, Certification.AssaultEngineering))
player.Zone = zone
player.Slot(slot = 0).Equipment = citem
player.Actor = system.actorOf(Props(classOf[PlayerControl], player, null), name = "deployable-test-player-control")
"DeployableBehavior" should {
"perform setup functions after asking owner" in {
assert(player.Slot(slot = 0).Equipment.contains(citem), "owned setup test, 2 - player hand is empty")
assert(deployableList.isEmpty, "owned setup test, 2 - deployable list is not empty")
assert(!avatar.deployables.Contains(jmine), "owned setup test, 2 - avatar already owns deployable")
zone.Deployables ! Zone.Deployable.BuildByOwner(jmine, player, citem)
//assert(false, "test needs to be fixed")
val eventsMsgs = eventsProbe.receiveN(8, 10.seconds)
eventsMsgs.head match {
case AvatarServiceMessage(
"TestCharacter1",
AvatarAction.SendResponse(
Service.defaultPlayerGUID,
ObjectDeployedMessage(0, "jammer_mine", DeployOutcome.Success, 1, 20)
)
) => ;
case _ =>
assert(false, "owned setup test, 2 - did not receive build confirmation")
}
eventsMsgs(1) match {
case LocalServiceMessage("TestCharacter1", LocalAction.DeployableUIFor(DeployedItem.jammer_mine)) => ;
case _ => assert(false, "owned setup test, 2 - did not receive ui update")
}
eventsMsgs(2) match {
case LocalServiceMessage(
"test",
LocalAction.TriggerEffectLocation(PlanetSideGUID(3), "spawn_object_effect", Vector3(1,2,3), Vector3(4,5,6))
) => ;
case _ => assert(false, "owned setup test, 2 - no spawn fx")
}
eventsMsgs(3) match {
case AvatarServiceMessage("test", AvatarAction.DeployItem(PlanetSideGUID(0), obj)) =>
assert(obj eq jmine, "owned setup test, 2 - not same mine")
case _ =>
assert( false, "owned setup test, 2 - wrong deploy message")
}
//the message order can be jumbled from here-on
eventsMsgs(4) match {
case LocalServiceMessage(
"TR",
LocalAction.DeployableMapIcon(
PlanetSideGUID(0),
DeploymentAction.Build,
DeployableInfo(PlanetSideGUID(1), DeployableIcon.DisruptorMine, Vector3(1,2,3), PlanetSideGUID(3))
)
) => ;
case _ =>
assert(false, "owned setup test, 2 - no icon or wrong icon")
}
eventsMsgs(5) match {
case AvatarServiceMessage(
"TestCharacter1",
AvatarAction.SendResponse(Service.defaultPlayerGUID, GenericObjectActionMessage(PlanetSideGUID(1), 21))
) => ;
case _ =>
assert(false, "owned setup test, 2 - build action not reset (GOAM21)")
}
eventsMsgs(6) match {
case AvatarServiceMessage("test", AvatarAction.ObjectDelete(Service.defaultPlayerGUID, PlanetSideGUID(2), 0)) => ;
case _ =>
assert(false, "owned setup test, 2 - construction tool not deleted")
}
eventsMsgs(7) match {
case TaskResolver.GiveTask(_, _) => ;
case _ =>
assert(false, "owned setup test, 2 - construction tool not unregistered")
}
assert(player.Slot(slot = 0).Equipment.isEmpty, "owned setup test, 2 - player hand should be empty")
assert(deployableList.contains(jmine), "owned setup test, 2 - deployable not appended to list")
assert(avatar.deployables.Contains(jmine), "owned setup test, 2 - avatar does not own deployable")
}
}
}
class DeployableBehaviorDeconstructTest extends ActorTest {
val eventsProbe = new TestProbe(system)
val jmine = Deployables.Make(DeployedItem.jammer_mine)() //guid = 1
val deployableList = new ListBuffer()
val guid = new NumberPoolHub(new MaxNumberSource(max = 5))
val zone = new Zone(id = "test", new ZoneMap(name = "test"), zoneNumber = 0) {
private val deployables = system.actorOf(Props(classOf[ZoneDeployableActor], this, deployableList), name = "test-zone-deployables")
override def SetupNumberPools(): Unit = {}
GUID(guid)
override def AvatarEvents: ActorRef = eventsProbe.ref
override def LocalEvents: ActorRef = eventsProbe.ref
override def tasks: ActorRef = eventsProbe.ref
override def Deployables: ActorRef = deployables
}
guid.register(jmine, number = 1)
jmine.Faction = PlanetSideEmpire.TR
jmine.Position = Vector3(1,2,3)
jmine.Orientation = Vector3(4,5,6)
"DeployableBehavior" should {
"deconstruct, by self" in {
zone.Deployables ! Zone.Deployable.Build(jmine)
eventsProbe.receiveN(3, 10.seconds) //all of the messages from the construction (see other testing)
assert(deployableList.contains(jmine), "deconstruct test - deployable not appended to list")
jmine.Actor ! Deployable.Deconstruct()
val eventsMsgs = eventsProbe.receiveN(3, 10.seconds)
eventsMsgs.head match {
case LocalServiceMessage("test", LocalAction.EliminateDeployable(`jmine`, PlanetSideGUID(1), Vector3(1,2,3), 2)) => ;
case _ => assert(false, "deconstruct test - not eliminating deployable")
}
eventsMsgs(1) match {
case LocalServiceMessage(
"TR",
LocalAction.DeployableMapIcon(
PlanetSideGUID(0),
DeploymentAction.Dismiss,
DeployableInfo(PlanetSideGUID(1), DeployableIcon.DisruptorMine, Vector3(1, 2, 3), PlanetSideGUID(0))
)
) => ;
case _ => assert(false, "owned deconstruct test - not removing icon")
}
eventsMsgs(2) match {
case TaskResolver.GiveTask(_, _) => ;
case _ => assert(false, "deconstruct test - not unregistering deployable")
}
assert(!deployableList.contains(jmine), "deconstruct test - deployable not removed from list")
}
}
}
class DeployableBehaviorDeconstructOwnedTest extends FreedContextActorTest {
val eventsProbe = new TestProbe(system)
val avatar = Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterSex.Male, 0, CharacterVoice.Mute)
val player = Player(avatar) //guid=3
val jmine = Deployables.Make(DeployedItem.jammer_mine)() //guid=1
val citem = new ConstructionItem(GlobalDefinitions.ace) //guid = 2
val deployableList = new ListBuffer()
val guid = new NumberPoolHub(new MaxNumberSource(max = 5))
val zone = new Zone(id = "test", new ZoneMap(name = "test"), zoneNumber = 0) {
private val deployables = system.actorOf(Props(classOf[ZoneDeployableActor], this, deployableList), name = "test-zone-deployables")
override def SetupNumberPools(): Unit = {}
GUID(guid)
override def AvatarEvents: ActorRef = eventsProbe.ref
override def LocalEvents: ActorRef = eventsProbe.ref
override def Deployables: ActorRef = deployables
override def Players = List(avatar)
override def LivePlayers = List(player)
override def tasks: ActorRef = eventsProbe.ref
}
guid.register(jmine, number = 1)
guid.register(citem, number = 2)
guid.register(player, number = 3)
guid.register(avatar.locker, number = 4)
jmine.Faction = PlanetSideEmpire.TR
jmine.Position = Vector3(1,2,3)
jmine.Orientation = Vector3(4,5,6)
jmine.AssignOwnership(player)
avatar.deployables.UpdateMaxCounts(Set(Certification.CombatEngineering, Certification.AssaultEngineering))
player.Zone = zone
player.Slot(slot = 0).Equipment = citem
player.Actor = system.actorOf(Props(classOf[PlayerControl], player, null), name = "deployable-test-player-control")
"DeployableBehavior" should {
"deconstruct and alert owner" in {
zone.Deployables ! Zone.Deployable.BuildByOwner(jmine, player, citem)
eventsProbe.receiveN(8, 10.seconds)
assert(deployableList.contains(jmine), "owned deconstruct test - deployable not appended to list")
assert(avatar.deployables.Contains(jmine), "owned deconstruct test - avatar does not own deployable")
jmine.Actor ! Deployable.Deconstruct()
val eventsMsgs = eventsProbe.receiveN(4, 10.seconds)
eventsMsgs.head match {
case LocalServiceMessage("test", LocalAction.EliminateDeployable(`jmine`, PlanetSideGUID(1), Vector3(1,2,3), 2)) => ;
case _ => assert(false, "owned deconstruct test - not eliminating deployable")
}
eventsMsgs(1) match {
case LocalServiceMessage("TestCharacter1", LocalAction.DeployableUIFor(DeployedItem.jammer_mine)) => ;
case _ => assert(false, "")
}
eventsMsgs(2) match {
case LocalServiceMessage(
"TR",
LocalAction.DeployableMapIcon(
PlanetSideGUID(0),
DeploymentAction.Dismiss,
DeployableInfo(PlanetSideGUID(1), DeployableIcon.DisruptorMine, Vector3(1, 2, 3), PlanetSideGUID(0))
)
) => ;
case _ => assert(false, "owned deconstruct test - not removing icon")
}
eventsMsgs(3) match {
case TaskResolver.GiveTask(_, _) => ;
case _ => assert(false, "owned deconstruct test - not unregistering deployable")
}
assert(deployableList.isEmpty, "owned deconstruct test - deployable still in list")
assert(!avatar.deployables.Contains(jmine), "owned deconstruct test - avatar still owns deployable")
}
}
}
object DeployableBehaviorTest {
//...
}