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) { if (isMovingPlus) {
CancelZoningProcessWithDescriptiveReason("cancel_motion") 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.Position = pos
player.Velocity = vel player.Velocity = vel
player.Orientation = Vector3(player.Orientation.x, pitch, yaw) 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.actors.commands.NtuCommand
import net.psforever.objects.{CommonNtuContainer, NtuContainer} import net.psforever.objects.{CommonNtuContainer, NtuContainer}
import net.psforever.objects.serverobject.PlanetSideServerObject 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.serverobject.structures.{Amenity, Building, StructureType, WarpGate}
import net.psforever.objects.zones.Zone import net.psforever.objects.zones.Zone
import net.psforever.persistence import net.psforever.persistence
@ -16,7 +16,7 @@ import net.psforever.types.PlanetSideEmpire
import net.psforever.util.Database._ import net.psforever.util.Database._
import net.psforever.services.galaxy.{GalaxyAction, GalaxyServiceMessage} import net.psforever.services.galaxy.{GalaxyAction, GalaxyServiceMessage}
import net.psforever.services.local.{LocalAction, LocalServiceMessage} 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.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success} import scala.util.{Failure, Success}
@ -73,6 +73,7 @@ class BuildingActor(
private[this] val log = org.log4s.getLogger private[this] val log = org.log4s.getLogger
var galaxyService: Option[classic.ActorRef] = None var galaxyService: Option[classic.ActorRef] = None
var interstellarCluster: Option[ActorRef[InterstellarClusterService.Command]] = None var interstellarCluster: Option[ActorRef[InterstellarClusterService.Command]] = None
var hasNtuSupply: Boolean = true
context.system.receptionist ! Receptionist.Find( context.system.receptionist ! Receptionist.Find(
InterstellarClusterService.InterstellarClusterServiceKey, InterstellarClusterService.InterstellarClusterServiceKey,
@ -124,28 +125,11 @@ class BuildingActor(
galaxyService ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage())) galaxyService ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage()))
Behaviors.same Behaviors.same
case AmenityStateChange(_: Generator, data) => case AmenityStateChange(gen: Generator, data) =>
//TODO when parameter object is finally immutable, perform analysis on it to determine specific actions if (generatorStateChange(gen, data)) {
data match { //update the map
case Some("overloaded") => galaxyService ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage()))
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 _ => ;
} }
//update the map
galaxyService ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage()))
Behaviors.same Behaviors.same
case AmenityStateChange(_, _) => case AmenityStateChange(_, _) =>
@ -163,15 +147,17 @@ class BuildingActor(
Behaviors.same Behaviors.same
case msg @ NtuDepleted() => 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 => building.Amenities.foreach { amenity =>
amenity.Actor ! msg amenity.Actor ! msg
} }
setFactionTo(PlanetSideEmpire.NEUTRAL, galaxyService) setFactionTo(PlanetSideEmpire.NEUTRAL, galaxyService)
hasNtuSupply = false
Behaviors.same Behaviors.same
case msg @ SuppliedWithNtu() => 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 => building.Amenities.foreach { amenity =>
amenity.Actor ! msg 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 = { def setFactionTo(faction: PlanetSideEmpire.Value, galaxy: classic.ActorRef): Unit = {
import ctx._ if (hasNtuSupply) {
ctx import ctx._
.run( ctx
query[persistence.Building] .run(
.filter(_.localId == lift(building.MapId)) query[persistence.Building]
.filter(_.zoneId == lift(zone.Number)) .filter(_.localId == lift(building.MapId))
) .filter(_.zoneId == lift(zone.Number))
.onComplete { )
case Success(res) => .onComplete {
res.headOption match { case Success(res) =>
case Some(_) => res.headOption match {
ctx case Some(_) =>
.run( ctx
query[persistence.Building] .run(
.filter(_.localId == lift(building.MapId)) query[persistence.Building]
.filter(_.zoneId == lift(zone.Number)) .filter(_.localId == lift(building.MapId))
.update(_.factionId -> lift(building.Faction.id)) .filter(_.zoneId == lift(zone.Number))
) .update(_.factionId -> lift(building.Faction.id))
.onComplete { )
case Success(_) => .onComplete {
case Failure(e) => log.error(e.getMessage) case Success(_) =>
} case Failure(e) => log.error(e.getMessage)
case _ => }
ctx case _ =>
.run( ctx
query[persistence.Building] .run(
.insert( query[persistence.Building]
_.localId -> lift(building.MapId), .insert(
_.factionId -> lift(building.Faction.id), _.localId -> lift(building.MapId),
_.zoneId -> lift(zone.Number) _.factionId -> lift(building.Faction.id),
) _.zoneId -> lift(zone.Number)
) )
.onComplete { )
case Success(_) => .onComplete {
case Failure(e) => log.error(e.getMessage) case Success(_) =>
} case Failure(e) => log.error(e.getMessage)
} }
case Failure(e) => log.error(e.getMessage) }
} case Failure(e) => log.error(e.getMessage)
building.Faction = faction }
galaxy ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage())) building.Faction = faction
zone.LocalEvents ! LocalServiceMessage(zone.id, LocalAction.SetEmpire(building.GUID, faction)) galaxy ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage()))
zone.LocalEvents ! LocalServiceMessage(zone.id, LocalAction.SetEmpire(building.GUID, faction))
}
} }
def powerLost(): Unit = { def powerLost(): Unit = {

View file

@ -34,13 +34,23 @@ class GeneratorControl(gen: Generator)
def DamageableObject = gen def DamageableObject = gen
def RepairableObject = gen def RepairableObject = gen
def AutoRepairObject = gen def AutoRepairObject = gen
/** flagged to explode after some time */
var imminentExplosion: Boolean = false var imminentExplosion: Boolean = false
/** explode when this timer completes */
var queuedExplosion: Cancellable = Default.Cancellable var queuedExplosion: Cancellable = Default.Cancellable
var alarmCooldownPeriod: Boolean = false /** when damaged, announce that damage was dealt on a schedule */
private[this] val log = org.log4s.getLogger 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 def receive: Receive = withNtu
/** behavior that is valid for both "with-ntu" and "without-ntu" */
val commonBehavior: Receive = val commonBehavior: Receive =
checkBehavior checkBehavior
.orElse(takesDamage) .orElse(takesDamage)
@ -48,22 +58,29 @@ class GeneratorControl(gen: Generator)
.orElse(autoRepairBehavior) .orElse(autoRepairBehavior)
.orElse { .orElse {
case GeneratorControl.UnderThreatAlarm() => case GeneratorControl.UnderThreatAlarm() =>
if (!alarmCooldownPeriod) { //alert to damage and block other damage alerts for a time
alarmCooldownPeriod = true if (alarmCooldown.isCancelled) {
GeneratorControl.BroadcastGeneratorEvent(gen, GeneratorControl.Event.UnderAttack) GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.UnderAttack))
queuedExplosion = context.system.scheduler.scheduleOnce(delay = 5 seconds, self, GeneratorControl.AlarmReset()) alarmCooldown.cancel()
alarmCooldown = context.system.scheduler.scheduleOnce(delay = 5 seconds, self, GeneratorControl.AlarmReset())
} }
case 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 = def withNtu: Receive =
commonBehavior commonBehavior
.orElse { .orElse {
case GeneratorControl.Destabilized() => case GeneratorControl.Destabilized() =>
imminentExplosion = true imminentExplosion = true
GeneratorControl.BroadcastGeneratorEvent(gen, GeneratorControl.Event.Overloaded) GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.Destabilized))
queuedExplosion.cancel() queuedExplosion.cancel()
queuedExplosion = context.system.scheduler.scheduleOnce(10 seconds, self, GeneratorControl.GeneratorExplodes()) queuedExplosion = context.system.scheduler.scheduleOnce(10 seconds, self, GeneratorControl.GeneratorExplodes())
@ -73,7 +90,7 @@ class GeneratorControl(gen: Generator)
gen.Health = 0 gen.Health = 0
super.DestructionAwareness(gen, gen.LastShot.get) super.DestructionAwareness(gen, gen.LastShot.get)
gen.Condition = PlanetSideGeneratorState.Destroyed gen.Condition = PlanetSideGeneratorState.Destroyed
GeneratorControl.UpdateOwner(gen, Some("destroyed")) GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.Destroyed))
//kaboom //kaboom
zone.AvatarEvents ! AvatarServiceMessage( zone.AvatarEvents ! AvatarServiceMessage(
zone.id, zone.id,
@ -99,39 +116,45 @@ class GeneratorControl(gen: Generator)
gen.ClearHistory() gen.ClearHistory()
case GeneratorControl.Restored() => case GeneratorControl.Restored() =>
GeneratorControl.UpdateOwner(gen, Some("restored")) GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.Online))
GeneratorControl.BroadcastGeneratorEvent(gen, GeneratorControl.Event.Online)
case _ => ; 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 = def withoutNtu: Receive =
commonBehavior commonBehavior
.orElse { .orElse {
case GeneratorControl.GeneratorExplodes() => case GeneratorControl.GeneratorExplodes() =>
queuedExplosion.cancel() queuedExplosion.cancel()
queuedExplosion = Default.Cancellable queuedExplosion = Default.Cancellable
imminentExplosion = false imminentExplosion = false
case GeneratorControl.Destabilized() => case GeneratorControl.Destabilized() =>
//if the generator is destabilized but has no ntu, it will not explode //if the generator is destabilized but has no ntu, it will not explode
gen.Health = 0 gen.Health = 0
super.DestructionAwareness(gen, gen.LastShot.get) super.DestructionAwareness(gen, gen.LastShot.get)
queuedExplosion.cancel() queuedExplosion.cancel()
queuedExplosion = Default.Cancellable queuedExplosion = Default.Cancellable
imminentExplosion = false imminentExplosion = false
gen.Condition = PlanetSideGeneratorState.Destroyed gen.Condition = PlanetSideGeneratorState.Destroyed
GeneratorControl.UpdateOwner(gen, Some("destroyed")) GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.Destroyed))
gen.ClearHistory() gen.ClearHistory()
case _ => case _ =>
} }
override protected def CanPerformRepairs(obj: Target, player: Player, item: Tool): Boolean = { override protected def CanPerformRepairs(obj: Target, player: Player, item: Tool): Boolean = {
//if an explosion is queued, disallow repairs
!imminentExplosion && super.CanPerformRepairs(obj, player, item) !imminentExplosion && super.CanPerformRepairs(obj, player, item)
} }
override protected def WillAffectTarget(target: Target, damage: Int, cause: ResolvedProjectile): Boolean = { 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) !imminentExplosion && super.WillAffectTarget(target, damage, cause)
} }
@ -147,9 +170,10 @@ class GeneratorControl(gen: Generator)
override protected def DestructionAwareness(target: Target, cause: ResolvedProjectile): Unit = { override protected def DestructionAwareness(target: Target, cause: ResolvedProjectile): Unit = {
tryAutoRepair() tryAutoRepair()
//if the target is already destroyed, do not let it be destroyed again
if (!target.Destroyed) { if (!target.Destroyed) {
target.Health = 1 //temporary target.Health = 1 //temporary
GeneratorControl.UpdateOwner(gen, Some("overloaded")) GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.Offline))
self ! GeneratorControl.Destabilized() self ! GeneratorControl.Destabilized()
} }
} }
@ -165,12 +189,14 @@ class GeneratorControl(gen: Generator)
override def Restoration(obj: Repairable.Target): Unit = { override def Restoration(obj: Repairable.Target): Unit = {
super.Restoration(obj) super.Restoration(obj)
gen.Condition = PlanetSideGeneratorState.Normal gen.Condition = PlanetSideGeneratorState.Normal
GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.Normal))
self ! GeneratorControl.Restored() self ! GeneratorControl.Restored()
} }
override def withNtuSupplyCallback() : Unit = { override def withNtuSupplyCallback() : Unit = {
context.become(withNtu) context.become(withNtu)
super.withNtuSupplyCallback() super.withNtuSupplyCallback()
//if not destroyed when a source of ntu is detected, restore facility power
if(!gen.Destroyed) { if(!gen.Destroyed) {
self ! GeneratorControl.Restored() self ! GeneratorControl.Restored()
} }
@ -180,9 +206,11 @@ class GeneratorControl(gen: Generator)
//auto-repair must stop naturally //auto-repair must stop naturally
context.become(withoutNtu) context.become(withoutNtu)
super.noNtuSupplyCallback() super.noNtuSupplyCallback()
//if not destroyed when cutoff from a source of ntu, stop facility power generation
if(!gen.Destroyed) { 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) { if(!queuedExplosion.isCancelled) {
queuedExplosion.cancel() queuedExplosion.cancel()
self ! GeneratorControl.Destabilized() self ! GeneratorControl.Destabilized()
@ -191,7 +219,6 @@ class GeneratorControl(gen: Generator)
} }
object GeneratorControl { object GeneratorControl {
/** /**
* na * na
*/ */
@ -221,41 +248,24 @@ object GeneratorControl {
* na * na
*/ */
object Event extends Enumeration { object Event extends Enumeration {
val UnderAttack = Value(15) val
val Critical = Value(0) Critical, //PlanetSideGeneratorState.Critical
val Overloaded = Value(16) UnderAttack,
val Online = Value(17) Destabilized,
Destroyed, //PlanetSideGeneratorState.Destroyed
Offline,
Normal, //PlanetSideGeneratorState.Normal
Online
= Value
} }
/** /**
* na * Send a message back to the owner for which this `Amenity` entity is installed.
* @param obj na * @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 = { private def UpdateOwner(obj: Generator, data: Option[Any] = None): Unit = {
obj.Owner match { obj.Owner.Actor ! BuildingActor.AmenityStateChange(obj, data)
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 _ => ;
}
} }
/** /**
@ -270,7 +280,7 @@ object GeneratorControl {
val max: Float = target.MaxHealth.toFloat val max: Float = target.MaxHealth.toFloat
if (target.Condition != PlanetSideGeneratorState.Critical && health / max < 0.51f) { //becoming critical if (target.Condition != PlanetSideGeneratorState.Critical && health / max < 0.51f) { //becoming critical
target.Condition = PlanetSideGeneratorState.Critical target.Condition = PlanetSideGeneratorState.Critical
GeneratorControl.UpdateOwner(target, Some("critical")) GeneratorControl.UpdateOwner(target, Some(GeneratorControl.Event.Critical))
} }
//the generator is under attack //the generator is under attack
target.Actor ! UnderThreatAlarm() target.Actor ! UnderThreatAlarm()

View file

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

View file

@ -2,17 +2,22 @@
package objects package objects
import akka.actor.{ActorSystem, Props} import akka.actor.{ActorSystem, Props}
import akka.testkit.TestProbe
import base.ActorTest import base.ActorTest
import net.psforever.objects.avatar.Avatar 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.{Default, GlobalDefinitions, Player}
import net.psforever.objects.serverobject.doors.{Door, DoorControl} import net.psforever.objects.serverobject.doors.{Door, DoorControl}
import net.psforever.objects.serverobject.structures.{Building, StructureType} 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.packet.game.UseItemMessage
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
import net.psforever.types._ import net.psforever.types._
import org.specs2.mutable.Specification import org.specs2.mutable.Specification
import scala.concurrent.duration.Duration import scala.concurrent.duration._
class DoorTest extends Specification { class DoorTest extends Specification {
val player = Player(Avatar(0, "test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) val player = Player(Avatar(0, "test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
@ -83,6 +88,8 @@ class DoorControl2Test extends ActorTest {
"DoorControl" should { "DoorControl" should {
"open on use" in { "open on use" in {
val (player, door) = DoorControlTest.SetUpAgents(PlanetSideEmpire.TR) val (player, door) = DoorControlTest.SetUpAgents(PlanetSideEmpire.TR)
val probe = new TestProbe(system)
door.Zone.LocalEvents = probe.ref
val msg = UseItemMessage( val msg = UseItemMessage(
PlanetSideGUID(1), PlanetSideGUID(1),
PlanetSideGUID(0), PlanetSideGUID(0),
@ -98,13 +105,12 @@ class DoorControl2Test extends ActorTest {
) //faked ) //faked
assert(door.Open.isEmpty) assert(door.Open.isEmpty)
door.Actor ! Door.Use(player, msg) door.Actor ! CommonMessages.Use(player, Some(msg))
val reply = receiveOne(Duration.create(500, "ms")) val reply = probe.receiveOne(1000 milliseconds)
assert(reply.isInstanceOf[Door.DoorMessage]) assert(reply match {
val reply2 = reply.asInstanceOf[Door.DoorMessage] case LocalServiceMessage("test", LocalAction.DoorOpens(PlanetSideGUID(0), _, d)) => d eq door
assert(reply2.player == player) case _ => false
assert(reply2.msg == msg) })
assert(reply2.response == Door.OpenEvent())
assert(door.Open.isDefined) assert(door.Open.isDefined)
} }
} }
@ -126,16 +132,24 @@ class DoorControl3Test extends ActorTest {
object DoorControlTest { object DoorControlTest {
def SetUpAgents(faction: PlanetSideEmpire.Value)(implicit system: ActorSystem): (Player, Door) = { def SetUpAgents(faction: PlanetSideEmpire.Value)(implicit system: ActorSystem): (Player, Door) = {
val door = Door(GlobalDefinitions.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.Actor = system.actorOf(Props(classOf[DoorControl], door), "door")
door.Owner = new Building( door.Owner = new Building(
"Building", "Building",
building_guid = 0, building_guid = 0,
map_id = 0, map_id = 0,
Zone.Nowhere, zone,
StructureType.Building, StructureType.Building,
GlobalDefinitions.building GlobalDefinitions.building
) )
door.Owner.Faction = faction 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.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.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.serverobject.structures.{Building, StructureType}
import net.psforever.objects.vital.Vitality import net.psforever.objects.vital.Vitality
import net.psforever.objects.zones.{Zone, ZoneMap} import net.psforever.objects.zones.{Zone, ZoneMap}
@ -25,12 +25,12 @@ import scala.concurrent.duration._
class GeneratorTest extends Specification { class GeneratorTest extends Specification {
"Generator" should { "Generator" should {
"construct" in { "construct" in {
Generator(GlobalDefinitions.generator) Generator(GeneratorTest.generator_definition)
ok ok
} }
"start in 'Normal' condition" in { "start in 'Normal' condition" in {
val obj = Generator(GlobalDefinitions.generator) val obj = Generator(GeneratorTest.generator_definition)
obj.Condition mustEqual PlanetSideGeneratorState.Normal obj.Condition mustEqual PlanetSideGeneratorState.Normal
} }
} }
@ -39,7 +39,7 @@ class GeneratorTest extends Specification {
class GeneratorControlConstructTest extends ActorTest { class GeneratorControlConstructTest extends ActorTest {
"GeneratorControl" should { "GeneratorControl" should {
"construct" in { "construct" in {
val gen = Generator(GlobalDefinitions.generator) val gen = Generator(GeneratorTest.generator_definition)
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "gen-control") gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "gen-control")
assert(gen.Actor != ActorRef.noSender) assert(gen.Actor != ActorRef.noSender)
} }
@ -57,7 +57,7 @@ class GeneratorControlDamageTest extends ActorTest {
val activityProbe = TestProbe() val activityProbe = TestProbe()
zone.Activity = activityProbe.ref 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.Position = Vector3(1, 0, 0)
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control") gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
@ -106,19 +106,18 @@ class GeneratorControlDamageTest extends ActorTest {
assert(gen.Condition == PlanetSideGeneratorState.Normal) assert(gen.Condition == PlanetSideGeneratorState.Normal)
gen.Actor ! Vitality.Damage(applyDamageTo) gen.Actor ! Vitality.Damage(applyDamageTo)
val msg_avatar = avatarProbe.receiveN(2, 500 milliseconds) val msg_avatar = avatarProbe.receiveOne(500 milliseconds)
buildingProbe.expectNoMessage(200 milliseconds) val msg_building = buildingProbe.receiveOne(500 milliseconds)
assert( assert(
msg_avatar.head match { msg_avatar match {
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
case _ => false case _ => false
} }
) )
assert( assert(
msg_avatar(1) match { msg_building match {
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 15)) => case BuildingActor.AmenityStateChange(_, Some(GeneratorControl.Event.UnderAttack)) => true
true case _ => false
case _ => false
} }
) )
assert(gen.Health < gen.Definition.MaxHealth) assert(gen.Health < gen.Definition.MaxHealth)
@ -139,7 +138,7 @@ class GeneratorControlCriticalTest extends ActorTest {
val activityProbe = TestProbe() val activityProbe = TestProbe()
zone.Activity = activityProbe.ref 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.Position = Vector3(1, 0, 0)
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control") gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
@ -190,25 +189,18 @@ class GeneratorControlCriticalTest extends ActorTest {
assert(gen.Condition == PlanetSideGeneratorState.Normal) assert(gen.Condition == PlanetSideGeneratorState.Normal)
gen.Actor ! Vitality.Damage(applyDamageTo) 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) val msg_building = buildingProbe.receiveOne(500 milliseconds)
assert( assert(
msg_avatar.head match { msg_avatar match {
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
case _ => false case _ => false
} }
) )
assert(
msg_avatar(1) match {
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 15)) =>
true
case _ => false
}
)
assert( assert(
msg_building match { msg_building match {
case BuildingActor.AmenityStateChange(o) => o eq gen case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Critical)) => o eq gen
case _ => false case _ => false
} }
) )
assert(gen.Health < halfHealth) assert(gen.Health < halfHealth)
@ -229,7 +221,7 @@ class GeneratorControlDestroyedTest extends ActorTest {
val activityProbe = TestProbe() val activityProbe = TestProbe()
zone.Activity = activityProbe.ref 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.Position = Vector3(1, 0, 0)
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control") gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
@ -269,7 +261,6 @@ class GeneratorControlDestroyedTest extends ActorTest {
Vector3(1, 0, 0) Vector3(1, 0, 0)
) )
val applyDamageTo = resolved.damage_model.Calculate(resolved) val applyDamageTo = resolved.damage_model.Calculate(resolved)
gen.Actor ! BuildingActor.NtuDepleted() //no auto-repair
expectNoMessage(200 milliseconds) expectNoMessage(200 milliseconds)
//we're not testing that the math is correct //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% assert(gen.Condition == PlanetSideGeneratorState.Normal) //skipped critical state because didn't transition ~50%
gen.Actor ! Vitality.Damage(applyDamageTo) gen.Actor ! Vitality.Damage(applyDamageTo)
val msg_avatar1 = avatarProbe.receiveOne(500 milliseconds) val msg_building12 = buildingProbe.receiveN(2,500 milliseconds)
buildingProbe.expectNoMessage(200 milliseconds)
assert( assert(
msg_avatar1 match { msg_building12.head match {
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 16)) => case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Offline)) => o eq gen
true case _ => false
}
)
assert(
msg_building12(1) match {
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Destabilized)) => o eq gen
case _ => false case _ => false
} }
) )
@ -294,13 +289,13 @@ class GeneratorControlDestroyedTest extends ActorTest {
assert(!gen.Destroyed) assert(!gen.Destroyed)
assert(gen.Condition == PlanetSideGeneratorState.Normal) 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_avatar2 = avatarProbe.receiveN(3, 1000 milliseconds) //see DamageableEntity test file
val msg_building = buildingProbe.receiveOne(200 milliseconds) val msg_building = buildingProbe.receiveOne(200 milliseconds)
assert( assert(
msg_building match { msg_building match {
case BuildingActor.AmenityStateChange(o) => o eq gen case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Destroyed)) => o eq gen
case _ => false case _ => false
} }
) )
assert( assert(
@ -352,7 +347,7 @@ class GeneratorControlKillsTest extends ActorTest {
val activityProbe = TestProbe() val activityProbe = TestProbe()
zone.Activity = activityProbe.ref 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.Position = Vector3(1, 0, 0)
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control") gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
@ -400,7 +395,6 @@ class GeneratorControlKillsTest extends ActorTest {
Vector3(1, 0, 0) Vector3(1, 0, 0)
) )
val applyDamageTo = resolved.damage_model.Calculate(resolved) val applyDamageTo = resolved.damage_model.Calculate(resolved)
gen.Actor ! BuildingActor.NtuDepleted() //no auto-repair
expectNoMessage(200 milliseconds) expectNoMessage(200 milliseconds)
//we're not testing that the math is correct //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% assert(gen.Condition == PlanetSideGeneratorState.Normal) //skipped critical state because didn't transition ~50%
gen.Actor ! Vitality.Damage(applyDamageTo) gen.Actor ! Vitality.Damage(applyDamageTo)
val msg_avatar1 = avatarProbe.receiveN(2, 500 milliseconds) val msg_building12 = buildingProbe.receiveN(2,500 milliseconds)
buildingProbe.expectNoMessage(200 milliseconds)
player1Probe.expectNoMessage(200 milliseconds)
player2Probe.expectNoMessage(200 milliseconds)
assert( assert(
msg_avatar1.head match { msg_building12.head match {
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 16)) => case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Offline)) => o eq gen
true
case _ => false case _ => false
} }
) )
assert( assert(
msg_avatar1(1) match { msg_building12(1) match {
case AvatarServiceMessage("TestCharacter2", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 16)) => case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Destabilized)) => o eq gen
true
case _ => false case _ => false
} }
) )
@ -434,14 +423,13 @@ class GeneratorControlKillsTest extends ActorTest {
assert(!gen.Destroyed) assert(!gen.Destroyed)
assert(gen.Condition == PlanetSideGeneratorState.Normal) assert(gen.Condition == PlanetSideGeneratorState.Normal)
val msg_building = buildingProbe.receiveOne(10500 milliseconds) avatarProbe.expectNoMessage(9500 milliseconds)
val msg_avatar2 = avatarProbe.receiveN(3, 200 milliseconds) val msg_avatar2 = avatarProbe.receiveN(3, 1000 milliseconds) //see DamageableEntity test file
val msg_player1 = player1Probe.receiveOne(100 milliseconds) val msg_building = buildingProbe.receiveOne(200 milliseconds)
player2Probe.expectNoMessage(200 milliseconds)
assert( assert(
msg_building match { msg_building match {
case BuildingActor.AmenityStateChange(o) => o eq gen case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Destroyed)) => o eq gen
case _ => false case _ => false
} }
) )
assert( assert(
@ -459,22 +447,25 @@ class GeneratorControlKillsTest extends ActorTest {
assert( assert(
msg_avatar2(2) match { msg_avatar2(2) match {
case AvatarServiceMessage( case AvatarServiceMessage(
"test", "test",
AvatarAction.SendResponse(_, TriggerEffectMessage(PlanetSideGUID(2), "explosion_generator", None, None)) AvatarAction.SendResponse(_, TriggerEffectMessage(PlanetSideGUID(2), "explosion_generator", None, None))
) => ) =>
true true
case _ => false 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( assert(
msg_player1 match { msg_player1 match {
case _ @Player.Die() => true case _ @Player.Die() => true
case _ => false case _ => false
} }
) )
assert(gen.Health == 0)
assert(gen.Destroyed)
assert(gen.Condition == PlanetSideGeneratorState.Destroyed)
} }
} }
} }
@ -487,7 +478,7 @@ class GeneratorControlNotDestroyTwice extends ActorTest {
GUID(guid) GUID(guid)
} }
val building = Building("test-building", 1, 1, zone, StructureType.Facility) //guid=1 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 = val player1 =
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=3 Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=3
player1.Spawn() player1.Spawn()
@ -573,7 +564,7 @@ class GeneratorControlNotDamageIfExplodingTest extends ActorTest {
val activityProbe = TestProbe() val activityProbe = TestProbe()
zone.Activity = activityProbe.ref 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.Position = Vector3(1, 0, 0)
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control") 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% assert(gen.Condition == PlanetSideGeneratorState.Normal) //skipped critical state because didn't transition ~50%
gen.Actor ! Vitality.Damage(applyDamageTo) gen.Actor ! Vitality.Damage(applyDamageTo)
val msg_avatar = avatarProbe.receiveOne(500 milliseconds) val msg_building12 = buildingProbe.receiveN(2,500 milliseconds)
buildingProbe.expectNoMessage(200 milliseconds)
player1Probe.expectNoMessage(200 milliseconds)
assert( assert(
msg_avatar match { msg_building12.head match {
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 16)) => case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Offline)) => o eq gen
true case _ => false
}
)
assert(
msg_building12(1) match {
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Destabilized)) => o eq gen
case _ => false case _ => false
} }
) )
@ -667,7 +661,7 @@ class GeneratorControlNotRepairIfExplodingTest extends ActorTest {
val activityProbe = TestProbe() val activityProbe = TestProbe()
zone.Activity = activityProbe.ref 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.Position = Vector3(1, 0, 0)
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control") 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% assert(gen.Condition == PlanetSideGeneratorState.Normal) //skipped critical state because didn't transition ~50%
gen.Actor ! Vitality.Damage(applyDamageTo) gen.Actor ! Vitality.Damage(applyDamageTo)
val msg_avatar1 = avatarProbe.receiveOne(500 milliseconds) val msg_building12 = buildingProbe.receiveN(2,500 milliseconds)
buildingProbe.expectNoMessage(200 milliseconds)
player1Probe.expectNoMessage(200 milliseconds)
assert( assert(
msg_avatar1 match { msg_building12.head match {
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 16)) => case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Offline)) => o eq gen
true case _ => false
}
)
assert(
msg_building12(1) match {
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Destabilized)) => o eq gen
case _ => false case _ => false
} }
) )
@ -765,7 +762,7 @@ class GeneratorControlRepairPastRestorePoint extends ActorTest {
val activityProbe = TestProbe() val activityProbe = TestProbe()
zone.Activity = activityProbe.ref 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.Position = Vector3(1, 0, 0)
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control") gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
@ -804,7 +801,7 @@ class GeneratorControlRepairPastRestorePoint extends ActorTest {
assert(gen.Destroyed) assert(gen.Destroyed)
gen.Actor ! CommonMessages.Use(player1, Some(tool)) //repair 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) val msg_building = buildingProbe.receiveOne(200 milliseconds)
assert( assert(
msg_avatar.head match { msg_avatar.head match {
@ -825,13 +822,6 @@ class GeneratorControlRepairPastRestorePoint extends ActorTest {
) )
assert( assert(
msg_avatar(2) match { msg_avatar(2) match {
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 17)) =>
true
case _ => false
}
)
assert(
msg_avatar(3) match {
case AvatarServiceMessage( case AvatarServiceMessage(
"TestCharacter1", "TestCharacter1",
AvatarAction.SendResponse(_, RepairMessage(ValidPlanetSideGUID(2), _)) AvatarAction.SendResponse(_, RepairMessage(ValidPlanetSideGUID(2), _))
@ -842,7 +832,7 @@ class GeneratorControlRepairPastRestorePoint extends ActorTest {
) )
assert( assert(
msg_building match { msg_building match {
case BuildingActor.AmenityStateChange(o) => o eq gen case BuildingActor.AmenityStateChange(o, _) => o eq gen
case _ => false 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 AvatarServiceMessage("nowhere", AvatarAction.PlanetsideAttribute(PlanetSideGUID(6), 47, 0)) => true
case _ => false case _ => false
}) })
val reply4 = zoneEvents.receiveOne(500 milliseconds)
assert(reply4 match {
case AvatarServiceMessage("nowhere", AvatarAction.PlanetsideAttribute(PlanetSideGUID(6), 48, 0)) => true
case _ => false
})
} }
} }
} }