comments and tests; generator now passes state information to owner, owner composes messaging; can not set faction information if building does not have ntu

This commit is contained in:
Jason_DiDonato@yahoo.com 2020-10-21 12:35:13 -04:00
parent 88684aa1a2
commit 54f6588439
7 changed files with 296 additions and 236 deletions

View file

@ -3646,12 +3646,6 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
if (isMovingPlus) {
CancelZoningProcessWithDescriptiveReason("cancel_motion")
}
if (!player.Crouching && is_crouching) {
continent.Buildings.values.find { b => Vector3.Distance(player.Position, b.Position) <= b.Definition.SOIRadius} match {
case Some(b) => ;
case _ => ;
}
}
player.Position = pos
player.Velocity = vel
player.Orientation = Vector3(player.Orientation.x, pitch, yaw)

View file

@ -7,7 +7,7 @@ import akka.{actor => classic}
import net.psforever.actors.commands.NtuCommand
import net.psforever.objects.{CommonNtuContainer, NtuContainer}
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.serverobject.generator.Generator
import net.psforever.objects.serverobject.generator.{Generator, GeneratorControl}
import net.psforever.objects.serverobject.structures.{Amenity, Building, StructureType, WarpGate}
import net.psforever.objects.zones.Zone
import net.psforever.persistence
@ -16,7 +16,7 @@ import net.psforever.types.PlanetSideEmpire
import net.psforever.util.Database._
import net.psforever.services.galaxy.{GalaxyAction, GalaxyServiceMessage}
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
import net.psforever.services.{InterstellarClusterService, ServiceManager}
import net.psforever.services.{InterstellarClusterService, Service, ServiceManager}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}
@ -73,6 +73,7 @@ class BuildingActor(
private[this] val log = org.log4s.getLogger
var galaxyService: Option[classic.ActorRef] = None
var interstellarCluster: Option[ActorRef[InterstellarClusterService.Command]] = None
var hasNtuSupply: Boolean = true
context.system.receptionist ! Receptionist.Find(
InterstellarClusterService.InterstellarClusterServiceKey,
@ -124,28 +125,11 @@ class BuildingActor(
galaxyService ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage()))
Behaviors.same
case AmenityStateChange(_: Generator, data) =>
//TODO when parameter object is finally immutable, perform analysis on it to determine specific actions
data match {
case Some("overloaded") =>
powerLost()
val zone = building.Zone
val msg = AvatarAction.PlanetsideAttributeToAll(building.GUID, 46, 2)
building.PlayersInSOI.foreach { player =>
zone.AvatarEvents ! AvatarServiceMessage(player.Name, msg)
} //???
case Some("restored") =>
// Power restored. Reactor Online. Sensors Online. Weapons Online. All systems nominal.
powerRestored()
val zone = building.Zone
building.PlayersInSOI.foreach { player =>
val msg = AvatarAction.PlanetsideAttributeToAll(building.GUID, 46, 0)
zone.AvatarEvents ! AvatarServiceMessage(player.Name, msg)
} //reset ???
case _ => ;
case AmenityStateChange(gen: Generator, data) =>
if (generatorStateChange(gen, data)) {
//update the map
galaxyService ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage()))
}
//update the map
galaxyService ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage()))
Behaviors.same
case AmenityStateChange(_, _) =>
@ -163,15 +147,17 @@ class BuildingActor(
Behaviors.same
case msg @ NtuDepleted() =>
// Oops, someone let the base run out of power. Shut it all down.
// Someone let the base run out of nanites. No one gets anything.
building.Amenities.foreach { amenity =>
amenity.Actor ! msg
}
setFactionTo(PlanetSideEmpire.NEUTRAL, galaxyService)
hasNtuSupply = false
Behaviors.same
case msg @ SuppliedWithNtu() =>
// Auto-repair, mainly. If the Generator works, power is restored too.
// Auto-repair restart, mainly. If the Generator works, power should be restored too.
hasNtuSupply = true
building.Amenities.foreach { amenity =>
amenity.Actor ! msg
}
@ -182,49 +168,107 @@ class BuildingActor(
}
}
def generatorStateChange(generator: Generator, event: Any): Boolean = {
event match {
case Some(GeneratorControl.Event.UnderAttack) =>
val events = zone.AvatarEvents
val guid = building.GUID
val msg = AvatarAction.GenericObjectAction(Service.defaultPlayerGUID, guid, 15)
building.PlayersInSOI.foreach { player =>
events ! AvatarServiceMessage(player.Name, msg)
}
false
case Some(GeneratorControl.Event.Critical) =>
val events = zone.AvatarEvents
val guid = building.GUID
val msg = AvatarAction.PlanetsideAttributeToAll(guid, 46, 1)
building.PlayersInSOI.foreach { player =>
events ! AvatarServiceMessage(player.Name, msg)
}
true
case Some(GeneratorControl.Event.Destabilized) =>
val events = zone.AvatarEvents
val guid = building.GUID
val msg = AvatarAction.GenericObjectAction(Service.defaultPlayerGUID, guid, 16)
building.PlayersInSOI.foreach { player =>
events ! AvatarServiceMessage(player.Name, msg)
}
false
case Some(GeneratorControl.Event.Destroyed) =>
true
case Some(GeneratorControl.Event.Offline) =>
powerLost()
val zone = building.Zone
val msg = AvatarAction.PlanetsideAttributeToAll(building.GUID, 46, 2)
building.PlayersInSOI.foreach { player =>
zone.AvatarEvents ! AvatarServiceMessage(player.Name, msg)
} //???
false
case Some(GeneratorControl.Event.Normal) =>
true
case Some(GeneratorControl.Event.Online) =>
// Power restored. Reactor Online. Sensors Online. Weapons Online. All systems nominal.
powerRestored()
val events = zone.AvatarEvents
val guid = building.GUID
val msg1 = AvatarAction.PlanetsideAttributeToAll(guid, 46, 0)
val msg2 = AvatarAction.GenericObjectAction(Service.defaultPlayerGUID, guid, 17)
building.PlayersInSOI.foreach { player =>
val name = player.Name
events ! AvatarServiceMessage(name, msg1) //reset ???; might be global?
events ! AvatarServiceMessage(name, msg2) //This facility's generator is back on line
}
true
case _ =>
false
}
}
def setFactionTo(faction: PlanetSideEmpire.Value, galaxy: classic.ActorRef): Unit = {
import ctx._
ctx
.run(
query[persistence.Building]
.filter(_.localId == lift(building.MapId))
.filter(_.zoneId == lift(zone.Number))
)
.onComplete {
case Success(res) =>
res.headOption match {
case Some(_) =>
ctx
.run(
query[persistence.Building]
.filter(_.localId == lift(building.MapId))
.filter(_.zoneId == lift(zone.Number))
.update(_.factionId -> lift(building.Faction.id))
)
.onComplete {
case Success(_) =>
case Failure(e) => log.error(e.getMessage)
}
case _ =>
ctx
.run(
query[persistence.Building]
.insert(
_.localId -> lift(building.MapId),
_.factionId -> lift(building.Faction.id),
_.zoneId -> lift(zone.Number)
)
)
.onComplete {
case Success(_) =>
case Failure(e) => log.error(e.getMessage)
}
}
case Failure(e) => log.error(e.getMessage)
}
building.Faction = faction
galaxy ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage()))
zone.LocalEvents ! LocalServiceMessage(zone.id, LocalAction.SetEmpire(building.GUID, faction))
if (hasNtuSupply) {
import ctx._
ctx
.run(
query[persistence.Building]
.filter(_.localId == lift(building.MapId))
.filter(_.zoneId == lift(zone.Number))
)
.onComplete {
case Success(res) =>
res.headOption match {
case Some(_) =>
ctx
.run(
query[persistence.Building]
.filter(_.localId == lift(building.MapId))
.filter(_.zoneId == lift(zone.Number))
.update(_.factionId -> lift(building.Faction.id))
)
.onComplete {
case Success(_) =>
case Failure(e) => log.error(e.getMessage)
}
case _ =>
ctx
.run(
query[persistence.Building]
.insert(
_.localId -> lift(building.MapId),
_.factionId -> lift(building.Faction.id),
_.zoneId -> lift(zone.Number)
)
)
.onComplete {
case Success(_) =>
case Failure(e) => log.error(e.getMessage)
}
}
case Failure(e) => log.error(e.getMessage)
}
building.Faction = faction
galaxy ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage()))
zone.LocalEvents ! LocalServiceMessage(zone.id, LocalAction.SetEmpire(building.GUID, faction))
}
}
def powerLost(): Unit = {

View file

@ -34,13 +34,23 @@ class GeneratorControl(gen: Generator)
def DamageableObject = gen
def RepairableObject = gen
def AutoRepairObject = gen
/** flagged to explode after some time */
var imminentExplosion: Boolean = false
/** explode when this timer completes */
var queuedExplosion: Cancellable = Default.Cancellable
var alarmCooldownPeriod: Boolean = false
private[this] val log = org.log4s.getLogger
/** when damaged, announce that damage was dealt on a schedule */
var alarmCooldown: Cancellable = Default.Cancellable
/*
behavior of the generator piggybacks from the logic used in `AmenityAutoRepair`
AAR splits its logic based on whether or not it has detected a source of nanite transfer units (NTU)
this amenity is the bridge between NTU and facility power so it leverages that logic
it is split between when detecting ntu and when starved for ntu
*/
def receive: Receive = withNtu
/** behavior that is valid for both "with-ntu" and "without-ntu" */
val commonBehavior: Receive =
checkBehavior
.orElse(takesDamage)
@ -48,22 +58,29 @@ class GeneratorControl(gen: Generator)
.orElse(autoRepairBehavior)
.orElse {
case GeneratorControl.UnderThreatAlarm() =>
if (!alarmCooldownPeriod) {
alarmCooldownPeriod = true
GeneratorControl.BroadcastGeneratorEvent(gen, GeneratorControl.Event.UnderAttack)
queuedExplosion = context.system.scheduler.scheduleOnce(delay = 5 seconds, self, GeneratorControl.AlarmReset())
//alert to damage and block other damage alerts for a time
if (alarmCooldown.isCancelled) {
GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.UnderAttack))
alarmCooldown.cancel()
alarmCooldown = context.system.scheduler.scheduleOnce(delay = 5 seconds, self, GeneratorControl.AlarmReset())
}
case GeneratorControl.AlarmReset() =>
alarmCooldownPeriod = false
//clear the blocker for alerting to damage
alarmCooldown = Default.Cancellable
}
/*
when NTU is detected,
the generator can be properly destabilized and explode
the generator can be repaired to operational status and power the facility in which it is installed
*/
def withNtu: Receive =
commonBehavior
.orElse {
case GeneratorControl.Destabilized() =>
imminentExplosion = true
GeneratorControl.BroadcastGeneratorEvent(gen, GeneratorControl.Event.Overloaded)
GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.Destabilized))
queuedExplosion.cancel()
queuedExplosion = context.system.scheduler.scheduleOnce(10 seconds, self, GeneratorControl.GeneratorExplodes())
@ -73,7 +90,7 @@ class GeneratorControl(gen: Generator)
gen.Health = 0
super.DestructionAwareness(gen, gen.LastShot.get)
gen.Condition = PlanetSideGeneratorState.Destroyed
GeneratorControl.UpdateOwner(gen, Some("destroyed"))
GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.Destroyed))
//kaboom
zone.AvatarEvents ! AvatarServiceMessage(
zone.id,
@ -99,39 +116,45 @@ class GeneratorControl(gen: Generator)
gen.ClearHistory()
case GeneratorControl.Restored() =>
GeneratorControl.UpdateOwner(gen, Some("restored"))
GeneratorControl.BroadcastGeneratorEvent(gen, GeneratorControl.Event.Online)
GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.Online))
case _ => ;
}
/*
when ntu is not expected,
the generator can still be destroyed but will not explode
handles the possibility that ntu was lost during an ongoing destabilization and cancels the explosion
*/
def withoutNtu: Receive =
commonBehavior
.orElse {
case GeneratorControl.GeneratorExplodes() =>
queuedExplosion.cancel()
queuedExplosion = Default.Cancellable
imminentExplosion = false
commonBehavior
.orElse {
case GeneratorControl.GeneratorExplodes() =>
queuedExplosion.cancel()
queuedExplosion = Default.Cancellable
imminentExplosion = false
case GeneratorControl.Destabilized() =>
//if the generator is destabilized but has no ntu, it will not explode
gen.Health = 0
super.DestructionAwareness(gen, gen.LastShot.get)
queuedExplosion.cancel()
queuedExplosion = Default.Cancellable
imminentExplosion = false
gen.Condition = PlanetSideGeneratorState.Destroyed
GeneratorControl.UpdateOwner(gen, Some("destroyed"))
gen.ClearHistory()
case GeneratorControl.Destabilized() =>
//if the generator is destabilized but has no ntu, it will not explode
gen.Health = 0
super.DestructionAwareness(gen, gen.LastShot.get)
queuedExplosion.cancel()
queuedExplosion = Default.Cancellable
imminentExplosion = false
gen.Condition = PlanetSideGeneratorState.Destroyed
GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.Destroyed))
gen.ClearHistory()
case _ =>
}
case _ =>
}
override protected def CanPerformRepairs(obj: Target, player: Player, item: Tool): Boolean = {
//if an explosion is queued, disallow repairs
!imminentExplosion && super.CanPerformRepairs(obj, player, item)
}
override protected def WillAffectTarget(target: Target, damage: Int, cause: ResolvedProjectile): Boolean = {
//if an explosion is queued, disallow further damage
!imminentExplosion && super.WillAffectTarget(target, damage, cause)
}
@ -147,9 +170,10 @@ class GeneratorControl(gen: Generator)
override protected def DestructionAwareness(target: Target, cause: ResolvedProjectile): Unit = {
tryAutoRepair()
//if the target is already destroyed, do not let it be destroyed again
if (!target.Destroyed) {
target.Health = 1 //temporary
GeneratorControl.UpdateOwner(gen, Some("overloaded"))
GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.Offline))
self ! GeneratorControl.Destabilized()
}
}
@ -165,12 +189,14 @@ class GeneratorControl(gen: Generator)
override def Restoration(obj: Repairable.Target): Unit = {
super.Restoration(obj)
gen.Condition = PlanetSideGeneratorState.Normal
GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.Normal))
self ! GeneratorControl.Restored()
}
override def withNtuSupplyCallback() : Unit = {
context.become(withNtu)
super.withNtuSupplyCallback()
//if not destroyed when a source of ntu is detected, restore facility power
if(!gen.Destroyed) {
self ! GeneratorControl.Restored()
}
@ -180,9 +206,11 @@ class GeneratorControl(gen: Generator)
//auto-repair must stop naturally
context.become(withoutNtu)
super.noNtuSupplyCallback()
//if not destroyed when cutoff from a source of ntu, stop facility power generation
if(!gen.Destroyed) {
GeneratorControl.UpdateOwner(gen, Some("overloaded"))
GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.Offline))
}
//can any explosion (see withoutNtu->GenweratorControl.Destabilized)
if(!queuedExplosion.isCancelled) {
queuedExplosion.cancel()
self ! GeneratorControl.Destabilized()
@ -191,7 +219,6 @@ class GeneratorControl(gen: Generator)
}
object GeneratorControl {
/**
* na
*/
@ -221,41 +248,24 @@ object GeneratorControl {
* na
*/
object Event extends Enumeration {
val UnderAttack = Value(15)
val Critical = Value(0)
val Overloaded = Value(16)
val Online = Value(17)
val
Critical, //PlanetSideGeneratorState.Critical
UnderAttack,
Destabilized,
Destroyed, //PlanetSideGeneratorState.Destroyed
Offline,
Normal, //PlanetSideGeneratorState.Normal
Online
= Value
}
/**
* na
* @param obj na
* Send a message back to the owner for which this `Amenity` entity is installed.
* @param obj the entity doing the self-reporting
* @param data optional information that indicates the nature of the state change
*/
private def UpdateOwner(obj: Generator, data: Option[Any] = None): Unit = {
obj.Owner match {
case b: Building => b.Actor ! BuildingActor.AmenityStateChange(obj, data)
case _ => ;
}
}
/**
* na
* @param target the generator
* @param event the action code for the event
*/
private def BroadcastGeneratorEvent(target: Generator, event: Event.Value): Unit = {
target.Owner match {
case b: Building =>
val events = target.Zone.AvatarEvents
val msg = event match {
case Event.Critical => AvatarAction.PlanetsideAttributeToAll(b.GUID, 46, 1) //critical status warning
case _ => AvatarAction.GenericObjectAction(Service.defaultPlayerGUID, b.GUID, event.id)
}
b.PlayersInSOI.foreach { player =>
events ! AvatarServiceMessage(player.Name, msg)
}
case _ => ;
}
obj.Owner.Actor ! BuildingActor.AmenityStateChange(obj, data)
}
/**
@ -270,7 +280,7 @@ object GeneratorControl {
val max: Float = target.MaxHealth.toFloat
if (target.Condition != PlanetSideGeneratorState.Critical && health / max < 0.51f) { //becoming critical
target.Condition = PlanetSideGeneratorState.Critical
GeneratorControl.UpdateOwner(target, Some("critical"))
GeneratorControl.UpdateOwner(target, Some(GeneratorControl.Event.Critical))
}
//the generator is under attack
target.Actor ! UnderThreatAlarm()

View file

@ -4,6 +4,7 @@ package objects
import akka.actor.Props
import akka.testkit.TestProbe
import base.FreedContextActorTest
import net.psforever.actors.zone.BuildingActor
import net.psforever.objects.avatar.Avatar
import net.psforever.objects.ballistics.{Projectile, ProjectileResolution, ResolvedProjectile, SourceEntry}
import net.psforever.objects.guid.NumberPoolHub
@ -57,6 +58,7 @@ class AutoRepairFacilityIntegrationTest extends FreedContextActorTest {
silo.NtuCapacitor = 1000
silo.Actor = system.actorOf(Props(classOf[ResourceSiloControl], silo), "test-silo")
silo.Actor ! "startup"
building.Actor ! BuildingActor.PowerOn() //artificial
val wep_fmode = weapon.FireMode
val wep_prof = wep_fmode.Add

View file

@ -2,17 +2,22 @@
package objects
import akka.actor.{ActorSystem, Props}
import akka.testkit.TestProbe
import base.ActorTest
import net.psforever.objects.avatar.Avatar
import net.psforever.objects.guid.NumberPoolHub
import net.psforever.objects.guid.source.MaxNumberSource
import net.psforever.objects.serverobject.CommonMessages
import net.psforever.objects.{Default, GlobalDefinitions, Player}
import net.psforever.objects.serverobject.doors.{Door, DoorControl}
import net.psforever.objects.serverobject.structures.{Building, StructureType}
import net.psforever.objects.zones.Zone
import net.psforever.objects.zones.{Zone, ZoneMap}
import net.psforever.packet.game.UseItemMessage
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
import net.psforever.types._
import org.specs2.mutable.Specification
import scala.concurrent.duration.Duration
import scala.concurrent.duration._
class DoorTest extends Specification {
val player = Player(Avatar(0, "test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
@ -83,6 +88,8 @@ class DoorControl2Test extends ActorTest {
"DoorControl" should {
"open on use" in {
val (player, door) = DoorControlTest.SetUpAgents(PlanetSideEmpire.TR)
val probe = new TestProbe(system)
door.Zone.LocalEvents = probe.ref
val msg = UseItemMessage(
PlanetSideGUID(1),
PlanetSideGUID(0),
@ -98,13 +105,12 @@ class DoorControl2Test extends ActorTest {
) //faked
assert(door.Open.isEmpty)
door.Actor ! Door.Use(player, msg)
val reply = receiveOne(Duration.create(500, "ms"))
assert(reply.isInstanceOf[Door.DoorMessage])
val reply2 = reply.asInstanceOf[Door.DoorMessage]
assert(reply2.player == player)
assert(reply2.msg == msg)
assert(reply2.response == Door.OpenEvent())
door.Actor ! CommonMessages.Use(player, Some(msg))
val reply = probe.receiveOne(1000 milliseconds)
assert(reply match {
case LocalServiceMessage("test", LocalAction.DoorOpens(PlanetSideGUID(0), _, d)) => d eq door
case _ => false
})
assert(door.Open.isDefined)
}
}
@ -126,16 +132,24 @@ class DoorControl3Test extends ActorTest {
object DoorControlTest {
def SetUpAgents(faction: PlanetSideEmpire.Value)(implicit system: ActorSystem): (Player, Door) = {
val door = Door(GlobalDefinitions.door)
val guid = new NumberPoolHub(new MaxNumberSource(5))
val zone = new Zone("test", new ZoneMap("test"), 0) {
override def SetupNumberPools() = {}
GUID(guid)
}
guid.register(door, 1)
door.Actor = system.actorOf(Props(classOf[DoorControl], door), "door")
door.Owner = new Building(
"Building",
building_guid = 0,
map_id = 0,
Zone.Nowhere,
zone,
StructureType.Building,
GlobalDefinitions.building
)
door.Owner.Faction = faction
(Player(Avatar(0, "test", faction, CharacterGender.Male, 0, CharacterVoice.Mute)), door)
val player = Player(Avatar(0, "test", faction, CharacterGender.Male, 0, CharacterVoice.Mute))
guid.register(player, 2)
(player, door)
}
}

View file

@ -11,7 +11,7 @@ import net.psforever.objects.{GlobalDefinitions, Player, Tool}
import net.psforever.objects.guid.NumberPoolHub
import net.psforever.objects.guid.source.MaxNumberSource
import net.psforever.objects.serverobject.CommonMessages
import net.psforever.objects.serverobject.generator.{Generator, GeneratorControl}
import net.psforever.objects.serverobject.generator.{Generator, GeneratorControl, GeneratorDefinition}
import net.psforever.objects.serverobject.structures.{Building, StructureType}
import net.psforever.objects.vital.Vitality
import net.psforever.objects.zones.{Zone, ZoneMap}
@ -25,12 +25,12 @@ import scala.concurrent.duration._
class GeneratorTest extends Specification {
"Generator" should {
"construct" in {
Generator(GlobalDefinitions.generator)
Generator(GeneratorTest.generator_definition)
ok
}
"start in 'Normal' condition" in {
val obj = Generator(GlobalDefinitions.generator)
val obj = Generator(GeneratorTest.generator_definition)
obj.Condition mustEqual PlanetSideGeneratorState.Normal
}
}
@ -39,7 +39,7 @@ class GeneratorTest extends Specification {
class GeneratorControlConstructTest extends ActorTest {
"GeneratorControl" should {
"construct" in {
val gen = Generator(GlobalDefinitions.generator)
val gen = Generator(GeneratorTest.generator_definition)
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "gen-control")
assert(gen.Actor != ActorRef.noSender)
}
@ -57,7 +57,7 @@ class GeneratorControlDamageTest extends ActorTest {
val activityProbe = TestProbe()
zone.Activity = activityProbe.ref
val gen = Generator(GlobalDefinitions.generator) //guid=2
val gen = Generator(GeneratorTest.generator_definition) //guid=2
gen.Position = Vector3(1, 0, 0)
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
@ -106,19 +106,18 @@ class GeneratorControlDamageTest extends ActorTest {
assert(gen.Condition == PlanetSideGeneratorState.Normal)
gen.Actor ! Vitality.Damage(applyDamageTo)
val msg_avatar = avatarProbe.receiveN(2, 500 milliseconds)
buildingProbe.expectNoMessage(200 milliseconds)
val msg_avatar = avatarProbe.receiveOne(500 milliseconds)
val msg_building = buildingProbe.receiveOne(500 milliseconds)
assert(
msg_avatar.head match {
msg_avatar match {
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
case _ => false
}
)
assert(
msg_avatar(1) match {
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 15)) =>
true
case _ => false
msg_building match {
case BuildingActor.AmenityStateChange(_, Some(GeneratorControl.Event.UnderAttack)) => true
case _ => false
}
)
assert(gen.Health < gen.Definition.MaxHealth)
@ -139,7 +138,7 @@ class GeneratorControlCriticalTest extends ActorTest {
val activityProbe = TestProbe()
zone.Activity = activityProbe.ref
val gen = Generator(GlobalDefinitions.generator) //guid=2
val gen = Generator(GeneratorTest.generator_definition) //guid=2
gen.Position = Vector3(1, 0, 0)
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
@ -190,25 +189,18 @@ class GeneratorControlCriticalTest extends ActorTest {
assert(gen.Condition == PlanetSideGeneratorState.Normal)
gen.Actor ! Vitality.Damage(applyDamageTo)
val msg_avatar = avatarProbe.receiveN(2, 500 milliseconds)
val msg_avatar = avatarProbe.receiveOne(500 milliseconds)
val msg_building = buildingProbe.receiveOne(500 milliseconds)
assert(
msg_avatar.head match {
msg_avatar match {
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
case _ => false
}
)
assert(
msg_avatar(1) match {
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 15)) =>
true
case _ => false
}
)
assert(
msg_building match {
case BuildingActor.AmenityStateChange(o) => o eq gen
case _ => false
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Critical)) => o eq gen
case _ => false
}
)
assert(gen.Health < halfHealth)
@ -229,7 +221,7 @@ class GeneratorControlDestroyedTest extends ActorTest {
val activityProbe = TestProbe()
zone.Activity = activityProbe.ref
val gen = Generator(GlobalDefinitions.generator) //guid=2
val gen = Generator(GeneratorTest.generator_definition) //guid=2
gen.Position = Vector3(1, 0, 0)
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
@ -269,7 +261,6 @@ class GeneratorControlDestroyedTest extends ActorTest {
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
gen.Actor ! BuildingActor.NtuDepleted() //no auto-repair
expectNoMessage(200 milliseconds)
//we're not testing that the math is correct
@ -281,12 +272,16 @@ class GeneratorControlDestroyedTest extends ActorTest {
assert(gen.Condition == PlanetSideGeneratorState.Normal) //skipped critical state because didn't transition ~50%
gen.Actor ! Vitality.Damage(applyDamageTo)
val msg_avatar1 = avatarProbe.receiveOne(500 milliseconds)
buildingProbe.expectNoMessage(200 milliseconds)
val msg_building12 = buildingProbe.receiveN(2,500 milliseconds)
assert(
msg_avatar1 match {
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 16)) =>
true
msg_building12.head match {
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Offline)) => o eq gen
case _ => false
}
)
assert(
msg_building12(1) match {
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Destabilized)) => o eq gen
case _ => false
}
)
@ -294,13 +289,13 @@ class GeneratorControlDestroyedTest extends ActorTest {
assert(!gen.Destroyed)
assert(gen.Condition == PlanetSideGeneratorState.Normal)
avatarProbe.expectNoMessage(9 seconds)
avatarProbe.expectNoMessage(9500 milliseconds)
val msg_avatar2 = avatarProbe.receiveN(3, 1000 milliseconds) //see DamageableEntity test file
val msg_building = buildingProbe.receiveOne(200 milliseconds)
assert(
msg_building match {
case BuildingActor.AmenityStateChange(o) => o eq gen
case _ => false
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Destroyed)) => o eq gen
case _ => false
}
)
assert(
@ -352,7 +347,7 @@ class GeneratorControlKillsTest extends ActorTest {
val activityProbe = TestProbe()
zone.Activity = activityProbe.ref
val gen = Generator(GlobalDefinitions.generator) //guid=2
val gen = Generator(GeneratorTest.generator_definition) //guid=2
gen.Position = Vector3(1, 0, 0)
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
@ -400,7 +395,6 @@ class GeneratorControlKillsTest extends ActorTest {
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
gen.Actor ! BuildingActor.NtuDepleted() //no auto-repair
expectNoMessage(200 milliseconds)
//we're not testing that the math is correct
@ -412,21 +406,16 @@ class GeneratorControlKillsTest extends ActorTest {
assert(gen.Condition == PlanetSideGeneratorState.Normal) //skipped critical state because didn't transition ~50%
gen.Actor ! Vitality.Damage(applyDamageTo)
val msg_avatar1 = avatarProbe.receiveN(2, 500 milliseconds)
buildingProbe.expectNoMessage(200 milliseconds)
player1Probe.expectNoMessage(200 milliseconds)
player2Probe.expectNoMessage(200 milliseconds)
val msg_building12 = buildingProbe.receiveN(2,500 milliseconds)
assert(
msg_avatar1.head match {
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 16)) =>
true
msg_building12.head match {
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Offline)) => o eq gen
case _ => false
}
)
assert(
msg_avatar1(1) match {
case AvatarServiceMessage("TestCharacter2", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 16)) =>
true
msg_building12(1) match {
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Destabilized)) => o eq gen
case _ => false
}
)
@ -434,14 +423,13 @@ class GeneratorControlKillsTest extends ActorTest {
assert(!gen.Destroyed)
assert(gen.Condition == PlanetSideGeneratorState.Normal)
val msg_building = buildingProbe.receiveOne(10500 milliseconds)
val msg_avatar2 = avatarProbe.receiveN(3, 200 milliseconds)
val msg_player1 = player1Probe.receiveOne(100 milliseconds)
player2Probe.expectNoMessage(200 milliseconds)
avatarProbe.expectNoMessage(9500 milliseconds)
val msg_avatar2 = avatarProbe.receiveN(3, 1000 milliseconds) //see DamageableEntity test file
val msg_building = buildingProbe.receiveOne(200 milliseconds)
assert(
msg_building match {
case BuildingActor.AmenityStateChange(o) => o eq gen
case _ => false
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Destroyed)) => o eq gen
case _ => false
}
)
assert(
@ -459,22 +447,25 @@ class GeneratorControlKillsTest extends ActorTest {
assert(
msg_avatar2(2) match {
case AvatarServiceMessage(
"test",
AvatarAction.SendResponse(_, TriggerEffectMessage(PlanetSideGUID(2), "explosion_generator", None, None))
) =>
"test",
AvatarAction.SendResponse(_, TriggerEffectMessage(PlanetSideGUID(2), "explosion_generator", None, None))
) =>
true
case _ => false
}
)
assert(gen.Health == 0)
assert(gen.Destroyed)
assert(gen.Condition == PlanetSideGeneratorState.Destroyed)
val msg_player1 = player1Probe.receiveOne(100 milliseconds)
player2Probe.expectNoMessage(200 milliseconds)
assert(
msg_player1 match {
case _ @Player.Die() => true
case _ => false
}
)
assert(gen.Health == 0)
assert(gen.Destroyed)
assert(gen.Condition == PlanetSideGeneratorState.Destroyed)
}
}
}
@ -487,7 +478,7 @@ class GeneratorControlNotDestroyTwice extends ActorTest {
GUID(guid)
}
val building = Building("test-building", 1, 1, zone, StructureType.Facility) //guid=1
val gen = Generator(GlobalDefinitions.generator) //guid=2
val gen = Generator(GeneratorTest.generator_definition) //guid=2
val player1 =
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=3
player1.Spawn()
@ -573,7 +564,7 @@ class GeneratorControlNotDamageIfExplodingTest extends ActorTest {
val activityProbe = TestProbe()
zone.Activity = activityProbe.ref
val gen = Generator(GlobalDefinitions.generator) //guid=2
val gen = Generator(GeneratorTest.generator_definition) //guid=2
gen.Position = Vector3(1, 0, 0)
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
@ -625,13 +616,16 @@ class GeneratorControlNotDamageIfExplodingTest extends ActorTest {
assert(gen.Condition == PlanetSideGeneratorState.Normal) //skipped critical state because didn't transition ~50%
gen.Actor ! Vitality.Damage(applyDamageTo)
val msg_avatar = avatarProbe.receiveOne(500 milliseconds)
buildingProbe.expectNoMessage(200 milliseconds)
player1Probe.expectNoMessage(200 milliseconds)
val msg_building12 = buildingProbe.receiveN(2,500 milliseconds)
assert(
msg_avatar match {
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 16)) =>
true
msg_building12.head match {
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Offline)) => o eq gen
case _ => false
}
)
assert(
msg_building12(1) match {
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Destabilized)) => o eq gen
case _ => false
}
)
@ -667,7 +661,7 @@ class GeneratorControlNotRepairIfExplodingTest extends ActorTest {
val activityProbe = TestProbe()
zone.Activity = activityProbe.ref
val gen = Generator(GlobalDefinitions.generator) //guid=2
val gen = Generator(GeneratorTest.generator_definition) //guid=2
gen.Position = Vector3(1, 0, 0)
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
@ -723,13 +717,16 @@ class GeneratorControlNotRepairIfExplodingTest extends ActorTest {
assert(gen.Condition == PlanetSideGeneratorState.Normal) //skipped critical state because didn't transition ~50%
gen.Actor ! Vitality.Damage(applyDamageTo)
val msg_avatar1 = avatarProbe.receiveOne(500 milliseconds)
buildingProbe.expectNoMessage(200 milliseconds)
player1Probe.expectNoMessage(200 milliseconds)
val msg_building12 = buildingProbe.receiveN(2,500 milliseconds)
assert(
msg_avatar1 match {
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 16)) =>
true
msg_building12.head match {
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Offline)) => o eq gen
case _ => false
}
)
assert(
msg_building12(1) match {
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Destabilized)) => o eq gen
case _ => false
}
)
@ -765,7 +762,7 @@ class GeneratorControlRepairPastRestorePoint extends ActorTest {
val activityProbe = TestProbe()
zone.Activity = activityProbe.ref
val gen = Generator(GlobalDefinitions.generator) //guid=2
val gen = Generator(GeneratorTest.generator_definition) //guid=2
gen.Position = Vector3(1, 0, 0)
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
@ -804,7 +801,7 @@ class GeneratorControlRepairPastRestorePoint extends ActorTest {
assert(gen.Destroyed)
gen.Actor ! CommonMessages.Use(player1, Some(tool)) //repair
val msg_avatar = avatarProbe.receiveN(4, 500 milliseconds) //expected
val msg_avatar = avatarProbe.receiveN(3, 500 milliseconds) //expected
val msg_building = buildingProbe.receiveOne(200 milliseconds)
assert(
msg_avatar.head match {
@ -825,13 +822,6 @@ class GeneratorControlRepairPastRestorePoint extends ActorTest {
)
assert(
msg_avatar(2) match {
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 17)) =>
true
case _ => false
}
)
assert(
msg_avatar(3) match {
case AvatarServiceMessage(
"TestCharacter1",
AvatarAction.SendResponse(_, RepairMessage(ValidPlanetSideGUID(2), _))
@ -842,7 +832,7 @@ class GeneratorControlRepairPastRestorePoint extends ActorTest {
)
assert(
msg_building match {
case BuildingActor.AmenityStateChange(o) => o eq gen
case BuildingActor.AmenityStateChange(o, _) => o eq gen
case _ => false
}
)
@ -852,3 +842,15 @@ class GeneratorControlRepairPastRestorePoint extends ActorTest {
}
}
}
object GeneratorTest {
final val generator_definition = new GeneratorDefinition(352) {
MaxHealth = 4000
Damageable = true
DamageableByFriendlyFire = false
Repairable = true
RepairDistance = 13.5f
RepairIfDestroyed = true
//note: no auto-repair
}
}

View file

@ -289,12 +289,6 @@ class ResourceSiloControlUpdate1Test extends ActorTest {
case AvatarServiceMessage("nowhere", AvatarAction.PlanetsideAttribute(PlanetSideGUID(6), 47, 0)) => true
case _ => false
})
val reply4 = zoneEvents.receiveOne(500 milliseconds)
assert(reply4 match {
case AvatarServiceMessage("nowhere", AvatarAction.PlanetsideAttribute(PlanetSideGUID(6), 48, 0)) => true
case _ => false
})
}
}
}