documentation for projectiles; moved LocalProjectile construction intoMaps.scala; extensive test corrections

This commit is contained in:
FateJH 2018-06-16 00:34:29 -04:00
parent 000652c969
commit 20a4fdfe45
16 changed files with 330 additions and 190 deletions

View file

@ -1,6 +1,10 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects
import akka.actor.ActorContext
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.types.PlanetSideEmpire
/**
* A `LocalProjectile` is a server-side object designed to populate a fake shared space.
* It is a placeholder intended to block out the existence of projectiles communicated from clients.
@ -10,11 +14,23 @@ package net.psforever.objects
* `Projectile.BaseUID`<br>
* `Projectile.RangeUID`
*/
class LocalProjectile extends PlanetSideGameObject {
class LocalProjectile extends PlanetSideServerObject {
def Faction = PlanetSideEmpire.NEUTRAL
def Definition = LocalProjectile.local
}
object LocalProjectile {
import net.psforever.objects.definition.ObjectDefinition
def local = new ObjectDefinition(0) { Name = "projectile" }
/**
* Instantiate and configure a `LocalProjectile` object.
* @param id the unique id that will be assigned to this entity
* @param context a context to allow the object to properly set up `ActorSystem` functionality
* @return the `LocalProjectile` object
*/
def Constructor(id : Int, context : ActorContext) : LocalProjectile = {
new LocalProjectile()
}
}

View file

@ -1,6 +1,10 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.ballistics
/**
* The different values for five common types of damage that can be dealt, based on target and application.
* In the same way, the five damage modifiers that are applied to the same kind of damage.
*/
trait DamageProfile {
def Damage0 : Int

View file

@ -3,6 +3,8 @@ package net.psforever.objects.ballistics
/**
* An `Enumeration` of the damage type.
* These types are not necessarily representative of the kind of projectile being used;
* for example, the bolt driver's `bolt` is considered "splash."
*/
object DamageType extends Enumeration(1) {
type Type = Value

View file

@ -5,6 +5,18 @@ import net.psforever.objects.definition.{ProjectileDefinition, ToolDefinition}
import net.psforever.objects.entity.SimpleWorldEntity
import net.psforever.types.Vector3
/**
* A summation of weapon (`Tool`) discharge.
* @param profile an explanation of the damage that can be performed by this discharge
* @param tool_def the weapon that caused this discharge
* @param shot_origin where the projectile started
* @param shot_angle in which direction the projectile was aimed when it was discharged
* @param resolution whether this projectile has encountered a target or wall;
* defaults to `Unresolved`
* @param fire_time when the weapon discharged was recorded;
* defaults to `System.nanoTime`
* @param hit_time when the discharge had its resolution status updated
*/
final case class Projectile(profile : ProjectileDefinition,
tool_def : ToolDefinition,
shot_origin : Vector3,
@ -12,15 +24,29 @@ final case class Projectile(profile : ProjectileDefinition,
resolution : ProjectileResolution.Value,
fire_time : Long = System.nanoTime,
hit_time : Long = 0) {
/** Information about the current world coordinates and orientation of the projectile */
val current : SimpleWorldEntity = new SimpleWorldEntity()
def Resolve(hitPos : Vector3, hitAng : Vector3, resolution : ProjectileResolution.Value) : Projectile = {
/**
* Give the projectile the suggested resolution status.
* Update the world coordinates and orientation.
* @param pos the current position
* @param ang the current orientation
* @param resolution the resolution status
* @return a new projectile with the suggested resolution status, or the original projectile
*/
def Resolve(pos : Vector3, ang : Vector3, resolution : ProjectileResolution.Value) : Projectile = {
val obj = Resolve(resolution)
obj.current.Position = hitPos
obj.current.Orientation = hitAng
obj.current.Position = pos
obj.current.Orientation = ang
obj
}
/**
* Give the projectile the suggested resolution status.
* @param resolution the resolution status
* @return a new projectile with the suggested resolution status, or the original projectile
*/
def Resolve(resolution : ProjectileResolution.Value) : Projectile = {
resolution match {
case ProjectileResolution.Unresolved =>
@ -38,6 +64,14 @@ object Projectile {
* 40125 to 40149 are being reserved as a guard against undetected overflow */
final val RangeUID : Int = 40150
/**
* Overloaded constructor for an `Unresolved` projectile.
* @param profile an explanation of the damage that can be performed by this discharge
* @param tool_def the weapon that caused this discharge
* @param shot_origin where the projectile started
* @param shot_angle in which direction the projectile was aimed when it was discharged
* @return the `Projectile` object
*/
def apply(profile : ProjectileDefinition, tool_def : ToolDefinition, shot_origin : Vector3, shot_angle : Vector3) : Projectile = {
Projectile(profile, tool_def, shot_origin, shot_angle, ProjectileResolution.Unresolved)
}

View file

@ -1,15 +1,18 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.ballistics
/**
* An `Enumeration` of outcomes regarding what actually happened to the projectile.
*/
object ProjectileResolution extends Enumeration {
type Type = Value
val
Unresolved,
Resolved,
MissedShot,
Hit,
Splash,
Lash
Unresolved, //original basic non-resolution
MissedShot, //projectile did not encounter any collision object and was despawned
Resolved, //a general "projectile encountered something" status with a more specific resolution
Hit, //direct hit, one target
Splash, //area of effect damage, potentially multiple targets
Lash //lashing damage, potentially multiple targets
= Value
}

View file

@ -46,9 +46,6 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
private var accessor : ActorRef = ActorRef.noSender
/** The basic support structure for the globally unique number system used by this `Zone`. */
private var guid : NumberPoolHub = new NumberPoolHub(new LimitedNumberSource(65536))
guid.AddPool("environment", (0 to 3000).toList) //TODO tailer ro suit requirements of zone
guid.AddPool("dynamic", (3001 to 10000).toList).Selector = new RandomSelector //TODO unlump pools later; do not make too big
guid.AddPool("projectiles", (Projectile.BaseUID until Projectile.RangeUID).toList) //TODO unlump pools later; do not make too big
/** A synchronized `List` of items (`Equipment`) dropped by players on the ground and can be collected again. */
private val equipmentOnGround : ListBuffer[Equipment] = ListBuffer[Equipment]()
/** */
@ -90,6 +87,7 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
def Init(implicit context : ActorContext) : Unit = {
if(accessor == ActorRef.noSender) {
implicit val guid : NumberPoolHub = this.guid //passed into builderObject.Build implicitly
SetupNumberPools()
accessor = context.actorOf(RandomPool(25).props(Props(classOf[UniqueNumberSystem], guid, UniqueNumberSystem.AllocateNumberPoolActors(guid))), s"$Id-uns")
ground = context.actorOf(Props(classOf[ZoneGroundActor], this, equipmentOnGround), s"$Id-ground")
transport = context.actorOf(Props(classOf[ZoneVehicleActor], this, vehicles), s"$Id-vehicles")
@ -99,10 +97,28 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
MakeBuildings(context)
AssignAmenities()
CreateSpawnGroups()
MakeLocalProjectiles()
}
}
def SetupNumberPools() : Unit = {
guid.AddPool("environment", (0 to 3000).toList) //TODO tailor to suit requirements of zone
//TODO unlump pools later; do not make any single pool too big
guid.AddPool("dynamic", (3001 to 10000).toList).Selector = new RandomSelector //TODO all things will be registered here, for now
guid.AddPool("b", (10001 to 15000).toList).Selector = new RandomSelector
guid.AddPool("c", (15001 to 20000).toList).Selector = new RandomSelector
guid.AddPool("d", (20001 to 25000).toList).Selector = new RandomSelector
guid.AddPool("e", (25001 to 30000).toList).Selector = new RandomSelector
guid.AddPool("f", (30001 to 35000).toList).Selector = new RandomSelector
guid.AddPool("g", (35001 to 40100).toList).Selector = new RandomSelector
guid.AddPool("projectiles", (Projectile.BaseUID until Projectile.RangeUID).toList)
//TODO disabled temporarily to lighten load times
//guid.AddPool("h", (40150 to 45000).toList).Selector = new RandomSelector
//guid.AddPool("i", (45001 to 50000).toList).Selector = new RandomSelector
//guid.AddPool("j", (50001 to 55000).toList).Selector = new RandomSelector
//guid.AddPool("k", (55001 to 60000).toList).Selector = new RandomSelector
//guid.AddPool("l", (60001 to 65535).toList).Selector = new RandomSelector
}
/**
* A reference to the primary `Actor` that governs this `Zone`.
* @return an `ActorRef`
@ -303,10 +319,6 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
entry
}
def MakeLocalProjectiles() : Unit = {
(Projectile.BaseUID until Projectile.RangeUID) foreach { guid.register(new LocalProjectile(), _) }
}
/**
* Provide bulk correspondence on all map entities that can be composed into packet messages and reported to a client.
* These messages are sent in this fashion at the time of joining the server:<br>

View file

@ -17,7 +17,9 @@ abstract class ActorTest(sys : ActorSystem = ActorSystem("system", ConfigFactory
object ActorTest {
import scala.collection.JavaConverters._
private val LoggingConfig = Map(
"akka.loglevel" -> ConfigValueFactory.fromAnyRef("OFF"),
"akka.stdout-loglevel" -> ConfigValueFactory.fromAnyRef("OFF")
"akka.loggers" -> List("akka.testkit.TestEventListener").asJava,
"akka.loglevel" -> "OFF",
"akka.stdout-loglevel" -> "OFF",
"akka.log-dead-letters" -> "OFF"
).asJava
}

View file

@ -170,6 +170,24 @@ class VehicleSpawnPadObjectBuilderTest extends ActorTest {
}
}
class LocalProjectileBuilderTest extends ActorTest {
import net.psforever.objects.LocalProjectile
"Local ProjectileBuilder" should {
"build" in {
val hub = ServerObjectBuilderTest.NumberPoolHub
val actor = system.actorOf(Props(classOf[ServerObjectBuilderTest.BuilderTestActor], ServerObjectBuilder(1,
LocalProjectile.Constructor), hub), "locker")
actor ! "!"
val reply = receiveOne(Duration.create(1000, "ms"))
assert(reply.isInstanceOf[LocalProjectile])
assert(reply.asInstanceOf[LocalProjectile].HasGUID)
assert(reply.asInstanceOf[LocalProjectile].GUID == PlanetSideGUID(1))
assert(reply == hub(1).get)
}
}
}
class LockerObjectBuilderTest extends ActorTest {
import net.psforever.objects.serverobject.mblocker.Locker
"LockerObjectBuilder" should {

View file

@ -324,10 +324,10 @@ object VehicleSpawnPadControlTest {
import net.psforever.objects.Tool
import net.psforever.types.CharacterGender
val zone = new Zone("test-zone", map, 0)
val zone = new Zone("test-zone", map, 0) { override def SetupNumberPools() = { } }
val vehicle = Vehicle(GlobalDefinitions.two_man_assault_buggy)
val weapon = vehicle.WeaponControlledFromSeat(1).get.asInstanceOf[Tool]
val guid : NumberPoolHub = new NumberPoolHub(LimitedNumberSource(40150))
val guid : NumberPoolHub = new NumberPoolHub(LimitedNumberSource(5))
guid.AddPool("test-pool", (0 to 2).toList)
guid.register(vehicle, "test-pool")
guid.register(weapon, "test-pool")

View file

@ -3,7 +3,7 @@ package objects
import java.util.concurrent.atomic.AtomicInteger
import akka.actor.{Actor, ActorContext, ActorRef, Props}
import akka.actor.{ActorContext, ActorRef, Props}
import net.psforever.objects.entity.IdentifiableEntity
import net.psforever.objects.equipment.Equipment
import net.psforever.objects.guid.NumberPoolHub
@ -16,7 +16,6 @@ import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire, V
import net.psforever.objects.serverobject.structures.{Building, FoundationBuilder, StructureType}
import net.psforever.objects.zones.{Zone, ZoneActor, ZoneMap}
import net.psforever.objects.Vehicle
import net.psforever.objects.ballistics.Projectile
import org.specs2.mutable.Specification
import scala.concurrent.duration._
@ -113,14 +112,14 @@ class ZoneTest extends Specification {
class ZoneActorTest extends ActorTest {
"Zone" should {
"have an Actor" in {
val zone = new Zone("test", new ZoneMap("map6"), 1)
val zone = new Zone("test", new ZoneMap("map6"), 1) { override def SetupNumberPools() = { } }
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), "test-actor")
expectNoMsg(Duration.create(100, "ms"))
assert(zone.Actor != ActorRef.noSender)
}
"create new number pools before the Actor is started" in {
val zone = new Zone("test", new ZoneMap("map6"), 1)
val zone = new Zone("test", new ZoneMap("map6"), 1) { override def SetupNumberPools() = { } }
zone.GUID(new NumberPoolHub(new LimitedNumberSource(10)))
assert( zone.AddPool("test1", 1 to 2) )
@ -129,7 +128,7 @@ class ZoneActorTest extends ActorTest {
}
"remove existing number pools before the Actor is started" in {
val zone = new Zone("test", new ZoneMap("map6"), 1)
val zone = new Zone("test", new ZoneMap("map6"), 1) { override def SetupNumberPools() = { } }
zone.GUID(new NumberPoolHub(new LimitedNumberSource(10)))
assert( zone.AddPool("test1", 1 to 2) )
assert( zone.RemovePool("test1") )
@ -140,19 +139,19 @@ class ZoneActorTest extends ActorTest {
}
"refuse new number pools after the Actor is started" in {
val zone = new Zone("test", new ZoneMap("map6"), 1)
val zone = new Zone("test", new ZoneMap("map6"), 1) { override def SetupNumberPools() = { } }
zone.GUID(new NumberPoolHub(new LimitedNumberSource(40150)))
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), "test-add-pool-actor-init")
zone.Actor ! Zone.Init()
expectNoMsg(Duration.create(300, "ms"))
expectNoMsg(Duration.create(500, "ms"))
assert( !zone.AddPool("test1", 1 to 2) )
}
"refuse to remove number pools after the Actor is started" in {
val zone = new Zone("test", new ZoneMap("map6"), 1)
val zone = new Zone("test", new ZoneMap("map6"), 1) { override def SetupNumberPools() = { } }
zone.GUID(new NumberPoolHub(new LimitedNumberSource(40150)))
zone.GUID(new NumberPoolHub(new LimitedNumberSource(10)))
zone.AddPool("test", 1 to 2)
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), "test-remove-pool-actor-init")
zone.Actor ! Zone.Init()
@ -183,7 +182,7 @@ class ZoneActorTest extends ActorTest {
ObjectToBuilding(5, 3)
ObjectToBuilding(6, 3)
}
val zone = new Zone("test", map6, 1)
val zone = new Zone("test", map6, 1) { override def SetupNumberPools() = { } }
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), "test-init")
zone.Actor ! Zone.Init()
expectNoMsg(Duration.create(300, "ms"))
@ -221,7 +220,7 @@ class ZoneActorTest extends ActorTest {
LocalObject(5, SpawnTube.Constructor(Vector3.Zero, Vector3.Zero))
ObjectToBuilding(5, 3)
}
val zone = new Zone("test", map6, 1)
val zone = new Zone("test", map6, 1) { override def SetupNumberPools() = { } }
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), "test-spawn")
zone.Actor ! Zone.Init()
expectNoMsg(Duration.create(300, "ms"))
@ -252,7 +251,7 @@ class ZoneActorTest extends ActorTest {
LocalObject(5, SpawnTube.Constructor(Vector3.Zero, Vector3.Zero))
ObjectToBuilding(5, 3)
}
val zone = new Zone("test", map6, 1)
val zone = new Zone("test", map6, 1) { override def SetupNumberPools() = { } }
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), "test-no-spawn")
zone.Actor ! Zone.Init()
expectNoMsg(Duration.create(300, "ms"))
@ -265,32 +264,16 @@ class ZoneActorTest extends ActorTest {
assert(reply.asInstanceOf[Zone.Lattice.NoValidSpawnPoint].spawn_group.contains(7))
}
}
"populate a series of reference projectiles" in {
val zone = new Zone("test", new ZoneMap("map6"), 1)
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), "test-projectiles")
zone.Actor ! Zone.Init()
expectNoMsg(Duration.create(300, "ms"))
(Projectile.BaseUID until Projectile.RangeUID)
.map { zone.GUID }
.collect {
case Some(_ : LocalProjectile) => ; //pass
case _ => assert(false)
}
}
}
class ZonePopulationTest extends ActorTest {
val testNum = new AtomicInteger(1)
def TestName : String = s"test${testNum.getAndIncrement()}"
"ZonePopulationActor" should {
"add new user to zones" in {
val zone = new Zone("test", new ZoneMap(""), 0)
val zone = new Zone("test", new ZoneMap(""), 0) { override def SetupNumberPools() = { } }
val avatar = Avatar("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), TestName) ! "!"
receiveOne(Duration.create(200, "ms")) //consume
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), ZoneTest.TestName)
zone.Actor ! Zone.Init()
expectNoMsg(200 milliseconds)
assert(zone.Players.isEmpty)
assert(zone.LivePlayers.isEmpty)
@ -302,9 +285,10 @@ class ZonePopulationTest extends ActorTest {
}
"remove user from zones" in {
val zone = new Zone("test", new ZoneMap(""), 0)
val zone = new Zone("test", new ZoneMap(""), 0) { override def SetupNumberPools() = { } }
val avatar = Avatar("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), TestName) ! "!"
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), ZoneTest.TestName)
zone.Actor ! Zone.Init()
receiveOne(Duration.create(200, "ms")) //consume
zone.Population ! Zone.Population.Join(avatar)
expectNoMsg(Duration.create(100, "ms"))
@ -317,11 +301,12 @@ class ZonePopulationTest extends ActorTest {
}
"associate user with a character" in {
val zone = new Zone("test", new ZoneMap(""), 0)
val zone = new Zone("test", new ZoneMap(""), 0) { override def SetupNumberPools() = { } }
val avatar = Avatar("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
val player = Player(avatar)
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), TestName) ! "!"
receiveOne(Duration.create(200, "ms")) //consume
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), ZoneTest.TestName)
zone.Actor ! Zone.Init()
expectNoMsg(200 milliseconds)
zone.Population ! Zone.Population.Join(avatar)
expectNoMsg(Duration.create(100, "ms"))
@ -337,11 +322,12 @@ class ZonePopulationTest extends ActorTest {
}
"disassociate character from a user" in {
val zone = new Zone("test", new ZoneMap(""), 0)
val zone = new Zone("test", new ZoneMap(""), 0) { override def SetupNumberPools() = { } }
val avatar = Avatar("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
val player = Player(avatar)
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), TestName) ! "!"
receiveOne(Duration.create(200, "ms")) //consume
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), ZoneTest.TestName)
zone.Actor ! Zone.Init()
expectNoMsg(200 milliseconds)
zone.Population ! Zone.Population.Join(avatar)
expectNoMsg(Duration.create(100, "ms"))
zone.Population ! Zone.Population.Spawn(avatar, player)
@ -359,11 +345,12 @@ class ZonePopulationTest extends ActorTest {
}
"user tries to Leave, but still has an associated character" in {
val zone = new Zone("test", new ZoneMap(""), 0)
val zone = new Zone("test", new ZoneMap(""), 0) { override def SetupNumberPools() = { } }
val avatar = Avatar("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
val player = Player(avatar)
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), TestName) ! "!"
receiveOne(Duration.create(500, "ms")) //consume
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), ZoneTest.TestName)
zone.Actor ! Zone.Init()
expectNoMsg(200 milliseconds)
zone.Population ! Zone.Population.Join(avatar)
expectNoMsg(Duration.create(100, "ms"))
zone.Population ! Zone.Population.Spawn(avatar, player)
@ -383,12 +370,13 @@ class ZonePopulationTest extends ActorTest {
}
"user tries to Spawn a character, but an associated character already exists" in {
val zone = new Zone("test", new ZoneMap(""), 0)
val zone = new Zone("test", new ZoneMap(""), 0) { override def SetupNumberPools() = { } }
val avatar = Avatar("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
val player1 = Player(avatar)
val player2 = Player(avatar)
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), TestName) ! "!"
receiveOne(Duration.create(200, "ms")) //consume
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), ZoneTest.TestName)
zone.Actor ! Zone.Init()
expectNoMsg(200 milliseconds)
zone.Population ! Zone.Population.Join(avatar)
expectNoMsg(Duration.create(100, "ms"))
zone.Population ! Zone.Population.Spawn(avatar, player1)
@ -409,11 +397,12 @@ class ZonePopulationTest extends ActorTest {
}
"user tries to Spawn a character, but did not Join first" in {
val zone = new Zone("test", new ZoneMap(""), 0)
val zone = new Zone("test", new ZoneMap(""), 0) { override def SetupNumberPools() = { } }
val avatar = Avatar("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
val player = Player(avatar)
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), TestName) ! "!"
receiveOne(Duration.create(200, "ms")) //consume
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), ZoneTest.TestName)
zone.Actor ! Zone.Init()
expectNoMsg(200 milliseconds)
assert(zone.Players.isEmpty)
assert(zone.LivePlayers.isEmpty)
@ -427,10 +416,11 @@ class ZonePopulationTest extends ActorTest {
}
"user tries to Release a character, but did not Spawn a character first" in {
val zone = new Zone("test", new ZoneMap(""), 0)
val zone = new Zone("test", new ZoneMap(""), 0) { override def SetupNumberPools() = { } }
val avatar = Avatar("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), TestName) ! "!"
receiveOne(Duration.create(200, "ms")) //consume
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), ZoneTest.TestName)
zone.Actor ! Zone.Init()
expectNoMsg(200 milliseconds)
zone.Population ! Zone.Population.Join(avatar)
expectNoMsg(Duration.create(100, "ms"))
@ -448,11 +438,12 @@ class ZonePopulationTest extends ActorTest {
}
"user adds character to list of retired characters" in {
val zone = new Zone("test", new ZoneMap(""), 0)
val zone = new Zone("test", new ZoneMap(""), 0) { override def SetupNumberPools() = { } }
val player = Player(Avatar("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5))
player.Release
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), TestName) ! "!"
receiveOne(Duration.create(200, "ms")) //consume
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), ZoneTest.TestName)
zone.Actor ! Zone.Init()
expectNoMsg(200 milliseconds)
assert(zone.Corpses.isEmpty)
zone.Population ! Zone.Corpse.Add(player)
@ -462,11 +453,12 @@ class ZonePopulationTest extends ActorTest {
}
"user removes character from the list of retired characters" in {
val zone = new Zone("test", new ZoneMap(""), 0)
val zone = new Zone("test", new ZoneMap(""), 0) { override def SetupNumberPools() = { } }
val player = Player(Avatar("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5))
player.Release
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), TestName) ! "!"
receiveOne(Duration.create(200, "ms")) //consume
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), ZoneTest.TestName)
zone.Actor ! Zone.Init()
expectNoMsg(200 milliseconds)
zone.Population ! Zone.Corpse.Add(player)
expectNoMsg(Duration.create(100, "ms"))
@ -478,15 +470,16 @@ class ZonePopulationTest extends ActorTest {
}
"user removes THE CORRECT character from the list of retired characters" in {
val zone = new Zone("test", new ZoneMap(""), 0)
val zone = new Zone("test", new ZoneMap(""), 0) { override def SetupNumberPools() = { } }
val player1 = Player(Avatar("Chord1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5))
player1.Release
val player2 = Player(Avatar("Chord2", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5))
player2.Release
val player3 = Player(Avatar("Chord3", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5))
player3.Release
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), TestName) ! "!"
receiveOne(Duration.create(200, "ms")) //consume
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), ZoneTest.TestName)
zone.Actor ! Zone.Init()
expectNoMsg(200 milliseconds)
zone.Population ! Zone.Corpse.Add(player1)
zone.Population ! Zone.Corpse.Add(player2)
zone.Population ! Zone.Corpse.Add(player3)
@ -504,11 +497,12 @@ class ZonePopulationTest extends ActorTest {
}
"user tries to add character to list of retired characters, but is not in correct state" in {
val zone = new Zone("test", new ZoneMap(""), 0)
val zone = new Zone("test", new ZoneMap(""), 0) { override def SetupNumberPools() = { } }
val player = Player(Avatar("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5))
//player.Release !!important
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), "testC") ! "!"
receiveOne(Duration.create(500, "ms")) //consume
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), ZoneTest.TestName)
zone.Actor ! Zone.Init()
expectNoMsg(200 milliseconds)
assert(zone.Corpses.isEmpty)
zone.Population ! Zone.Corpse.Add(player)
@ -520,11 +514,13 @@ class ZonePopulationTest extends ActorTest {
class ZoneGroundDropItemTest extends ActorTest {
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
val hub = new NumberPoolHub(new LimitedNumberSource(40150))
val hub = new NumberPoolHub(new LimitedNumberSource(20))
hub.register(item, 10)
val zone = new Zone("test", new ZoneMap("test-map"), 0)
val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = { } }
zone.GUID(hub)
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), "drop-test-zone") ! "!"
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), ZoneTest.TestName)
zone.Actor ! Zone.Init()
expectNoMsg(200 milliseconds)
"DropItem" should {
"drop item on ground" in {
@ -544,11 +540,13 @@ class ZoneGroundDropItemTest extends ActorTest {
class ZoneGroundCanNotDropItem1Test extends ActorTest {
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
val hub = new NumberPoolHub(new LimitedNumberSource(40150))
val hub = new NumberPoolHub(new LimitedNumberSource(20))
//hub.register(item, 10) //!important
val zone = new Zone("test", new ZoneMap("test-map"), 0)
val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = { } }
zone.GUID(hub)
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), "drop-test-zone") ! "!"
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), ZoneTest.TestName)
zone.Actor ! Zone.Init()
expectNoMsg(200 milliseconds)
"DropItem" should {
"not drop an item that is not registered" in {
@ -570,9 +568,11 @@ class ZoneGroundCanNotDropItem2Test extends ActorTest {
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
val hub = new NumberPoolHub(new LimitedNumberSource(20))
hub.register(item, 10) //!important
val zone = new Zone("test", new ZoneMap("test-map"), 0)
val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = { } }
//zone.GUID(hub) //!important
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), "drop-test-zone") ! "!"
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), ZoneTest.TestName)
zone.Actor ! Zone.Init()
expectNoMsg(200 milliseconds)
"DropItem" should {
"not drop an item that is not registered to the zone" in {
@ -592,11 +592,13 @@ class ZoneGroundCanNotDropItem2Test extends ActorTest {
class ZoneGroundCanNotDropItem3Test extends ActorTest {
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
val hub = new NumberPoolHub(new LimitedNumberSource(40150))
val hub = new NumberPoolHub(new LimitedNumberSource(20))
hub.register(item, 10) //!important
val zone = new Zone("test", new ZoneMap("test-map"), 0)
val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = { } }
zone.GUID(hub) //!important
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), "drop-test-zone") ! "!"
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), ZoneTest.TestName)
zone.Actor ! Zone.Init()
expectNoMsg(200 milliseconds)
"DropItem" should {
"not drop an item that has already been dropped" in {
@ -624,11 +626,13 @@ class ZoneGroundCanNotDropItem3Test extends ActorTest {
class ZoneGroundPickupItemTest extends ActorTest {
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
val hub = new NumberPoolHub(new LimitedNumberSource(40150))
val hub = new NumberPoolHub(new LimitedNumberSource(20))
hub.register(item, 10)
val zone = new Zone("test", new ZoneMap("test-map"), 0)
val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = { } }
zone.GUID(hub)
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), "drop-test-zone") ! "!"
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), ZoneTest.TestName)
zone.Actor ! Zone.Init()
expectNoMsg(200 milliseconds)
"PickupItem" should {
"pickup an item from ground" in {
@ -651,11 +655,13 @@ class ZoneGroundPickupItemTest extends ActorTest {
class ZoneGroundCanNotPickupItemTest extends ActorTest {
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
val hub = new NumberPoolHub(new LimitedNumberSource(40150))
val hub = new NumberPoolHub(new LimitedNumberSource(20))
hub.register(item, 10)
val zone = new Zone("test", new ZoneMap("test-map"), 0)
val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = { } }
zone.GUID(hub) //still registered to this zone
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), "drop-test-zone") ! "!"
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), ZoneTest.TestName)
zone.Actor ! Zone.Init()
expectNoMsg(200 milliseconds)
"PickupItem" should {
"not pickup an item if it can not be found" in {
@ -674,11 +680,13 @@ class ZoneGroundCanNotPickupItemTest extends ActorTest {
class ZoneGroundRemoveItemTest extends ActorTest {
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
val hub = new NumberPoolHub(new LimitedNumberSource(40150))
val hub = new NumberPoolHub(new LimitedNumberSource(20))
hub.register(item, 10)
val zone = new Zone("test", new ZoneMap("test-map"), 0)
val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = { } }
zone.GUID(hub) //still registered to this zone
system.actorOf(Props(classOf[ZoneTest.ZoneInitActor], zone), "drop-test-zone") ! "!"
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), ZoneTest.TestName)
zone.Actor ! Zone.Init()
expectNoMsg(200 milliseconds)
"RemoveItem" should {
"remove an item from the ground without callback (even if the item is not found)" in {
@ -700,12 +708,6 @@ class ZoneGroundRemoveItemTest extends ActorTest {
}
object ZoneTest {
class ZoneInitActor(zone : Zone) extends Actor {
def receive : Receive = {
case "!" =>
zone.Init(context)
sender ! "!"
case _ => ;
}
}
val testNum = new AtomicInteger(1)
def TestName : String = s"test${testNum.getAndIncrement()}"
}

View file

@ -1,52 +1,17 @@
// Copyright (c) 2017 PSForever
package objects.guidtask
import akka.actor.{Actor, ActorSystem, Props}
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
import org.specs2.mutable.Specification
import objects.ActorTest
import scala.concurrent.Await
import akka.pattern.ask
import akka.util.Timeout
import scala.concurrent.duration._
class GUIDTaskRegister1Test extends ActorTest {
"RegisterObjectTask" in {
val (_, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
val obj = new GUIDTaskTest.TestObject
class GUIDTaskRegister1Test extends Specification {
"RegisterObjectTask" should {
"register (1)" in {
val system = ActorSystem("sys")
val test = system.actorOf(Props(classOf[GUIDTaskRegister1TestActor], system), "test")
implicit val timeout = Timeout(5 seconds)
val future = test ? "test"
val result = Await.result(future, timeout.duration).asInstanceOf[String]
result mustEqual "success"
}
assert(!obj.HasGUID)
taskResolver ! TaskResolver.GiveTask(new GUIDTaskTest.RegisterTestTask(probe.ref), List(GUIDTask.RegisterObjectTask(obj)(uns)))
probe.expectMsg(scala.util.Success)
assert(obj.HasGUID)
}
}
private class GUIDTaskRegister1TestActor(implicit system : ActorSystem) extends Actor {
def receive : Receive = {
case "test" =>
val (_, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
val obj = new GUIDTaskTest.TestObject
assert(!obj.HasGUID)
taskResolver ! TaskResolver.GiveTask(new GUIDTaskTest.RegisterTestTask(probe.ref), List(GUIDTask.RegisterObjectTask(obj)(uns)))
probe.expectMsg(scala.util.Success)
assert(obj.HasGUID)
sender ! "success"
case _ => ;
}
}
//class GUIDTaskRegister1Test extends ActorTest() {
// "RegisterObjectTask" in {
// val (_, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
// val obj = new GUIDTaskTest.TestObject
//
// assert(!obj.HasGUID)
// taskResolver ! TaskResolver.GiveTask(new GUIDTaskTest.RegisterTestTask(probe.ref), List(GUIDTask.RegisterObjectTask(obj)(uns)))
// probe.expectMsg(scala.util.Success)
// assert(obj.HasGUID)
// }
//}

View file

@ -9,7 +9,7 @@ import objects.ActorTest
import scala.concurrent.duration.Duration
class NumberPoolActorTest extends ActorTest(ActorSystem("test")) {
class NumberPoolActorTest extends ActorTest() {
"NumberPoolActor" should {
"GetAnyNumber" in {
val pool = new ExclusivePool((25 to 50).toList)
@ -22,7 +22,7 @@ class NumberPoolActorTest extends ActorTest(ActorSystem("test")) {
}
}
class NumberPoolActorTest1 extends ActorTest(ActorSystem("test")) {
class NumberPoolActorTest1 extends ActorTest() {
"NumberPoolActor" should {
"GetSpecificNumber" in {
val pool = new ExclusivePool((25 to 50).toList)
@ -34,7 +34,7 @@ class NumberPoolActorTest1 extends ActorTest(ActorSystem("test")) {
}
}
class NumberPoolActorTest2 extends ActorTest(ActorSystem("test")) {
class NumberPoolActorTest2 extends ActorTest() {
"NumberPoolActor" should {
"NoNumber" in {
val pool = new ExclusivePool((25 to 25).toList) //pool only has one number - 25

View file

@ -1,6 +1,8 @@
// Copyright (c) 2017 PSForever
import net.psforever.objects.zones.ZoneMap
import net.psforever.objects.GlobalDefinitions._
import net.psforever.objects.LocalProjectile
import net.psforever.objects.ballistics.Projectile
import net.psforever.objects.serverobject.doors.Door
import net.psforever.objects.serverobject.implantmech.ImplantTerminalMech
import net.psforever.objects.serverobject.locks.IFFLock
@ -13,15 +15,25 @@ import net.psforever.objects.serverobject.resourcesilo.ResourceSilo
import net.psforever.types.Vector3
object Maps {
val map1 = new ZoneMap("map01")
val map1 = new ZoneMap("map01") {
Projectiles(this)
}
val map2 = new ZoneMap("map02")
val map2 = new ZoneMap("map02") {
Projectiles(this)
}
val map3 = new ZoneMap("map03")
val map3 = new ZoneMap("map03") {
Projectiles(this)
}
val map4 = new ZoneMap("map04")
val map4 = new ZoneMap("map04") {
Projectiles(this)
}
val map5 = new ZoneMap("map05")
val map5 = new ZoneMap("map05") {
Projectiles(this)
}
val map6 = new ZoneMap("map06") {
Building2()
@ -29,6 +41,7 @@ object Maps {
Building42()
Building48()
Building49()
Projectiles(this)
def Building2() : Unit = {
//Anguta
@ -420,17 +433,29 @@ object Maps {
}
}
val map7 = new ZoneMap("map07")
val map7 = new ZoneMap("map07") {
Projectiles(this)
}
val map8 = new ZoneMap("map08")
val map8 = new ZoneMap("map08") {
Projectiles(this)
}
val map9 = new ZoneMap("map09")
val map9 = new ZoneMap("map09") {
Projectiles(this)
}
val map10 = new ZoneMap("map10")
val map10 = new ZoneMap("map10") {
Projectiles(this)
}
val map11 = new ZoneMap("map11")
val map11 = new ZoneMap("map11") {
Projectiles(this)
}
val map12 = new ZoneMap("map12")
val map12 = new ZoneMap("map12") {
Projectiles(this)
}
val map13 = new ZoneMap("map13") {
Building1()
@ -443,6 +468,7 @@ object Maps {
Building77()
Building79()
Building81()
Projectiles(this)
def Building1() : Unit = {
//warpgate?
@ -716,29 +742,59 @@ object Maps {
}
}
val map14 = new ZoneMap("map14")
val map14 = new ZoneMap("map14") {
Projectiles(this)
}
val map15 = new ZoneMap("map15")
val map15 = new ZoneMap("map15") {
Projectiles(this)
}
val map16 = new ZoneMap("map16")
val map16 = new ZoneMap("map16") {
Projectiles(this)
}
val ugd01 = new ZoneMap("ugd01")
val ugd01 = new ZoneMap("ugd01") {
Projectiles(this)
}
val ugd02 = new ZoneMap("ugd02")
val ugd02 = new ZoneMap("ugd02") {
Projectiles(this)
}
val ugd03 = new ZoneMap("ugd03")
val ugd03 = new ZoneMap("ugd03") {
Projectiles(this)
}
val ugd04 = new ZoneMap("ugd04")
val ugd04 = new ZoneMap("ugd04") {
Projectiles(this)
}
val ugd05 = new ZoneMap("ugd05")
val ugd05 = new ZoneMap("ugd05") {
Projectiles(this)
}
val ugd06 = new ZoneMap("ugd06")
val ugd06 = new ZoneMap("ugd06") {
Projectiles(this)
}
val map96 = new ZoneMap("map96")
val map96 = new ZoneMap("map96") {
Projectiles(this)
}
val map97 = new ZoneMap("map97")
val map97 = new ZoneMap("map97") {
Projectiles(this)
}
val map98 = new ZoneMap("map98")
val map98 = new ZoneMap("map98") {
Projectiles(this)
}
val map99 = new ZoneMap("map99")
val map99 = new ZoneMap("map99") {
Projectiles(this)
}
private def Projectiles(zmap : ZoneMap) : Unit = {
(Projectile.BaseUID until Projectile.RangeUID) foreach { zmap.LocalObject(_, LocalProjectile.Constructor) }
}
}

View file

@ -5256,6 +5256,13 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
}
/**
* Given a globally unique identifier in the 40100 to 40124 range
* (with an optional 25 as buffer),
* find a projectile.
* @param projectile_guid the projectile's GUID
* @return the discovered projectile
*/
def FindProjectileEntry(projectile_guid : PlanetSideGUID) : Option[Projectile] = {
val index = projectile_guid.guid - Projectile.BaseUID
if(0 <= index && index < projectiles.length) {
@ -5267,6 +5274,13 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
}
/**
* Find a projectile with the given globally unique identifier and mark it as a resolved shot.
* A `Resolved` shot has either encountered an obstacle or is being cleaned up for not finding an obstacle.
* @param projectile_guid the projectile GUID
* @param resolution the resolution status to promote the projectile
* @return the projectile
*/
def ResolveProjectileEntry(projectile_guid : PlanetSideGUID, resolution : ProjectileResolution.Value) : Option[Projectile] = {
FindProjectileEntry(projectile_guid) match {
case Some(projectile) =>
@ -5278,6 +5292,16 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
}
/**
* Find a projectile with the given globally unique identifier and mark it as a resolved shot.
* A `Resolved` shot has either encountered an obstacle or is being cleaned up for not finding an obstacle.
* The internal copy of the projectile is retained as merely `Resolved`
* while the observed projectile is promoted to the suggested resolution status.
* @param projectile the projectile object
* @param index where the projectile was found
* @param resolution the resolution status to promote the projectile
* @return a copy of the projectile
*/
def ResolveProjectileEntry(projectile : Projectile, index : Int, resolution : ProjectileResolution.Value) : Option[Projectile] = {
if(projectiles(index).contains(projectile)) {
projectiles(index) = Some(projectile.Resolve(ProjectileResolution.Resolved))

View file

@ -17,8 +17,10 @@ abstract class ActorTest(sys : ActorSystem = ActorSystem("system", ConfigFactory
object ActorTest {
import scala.collection.JavaConverters._
private val LoggingConfig = Map(
"akka.loglevel" -> ConfigValueFactory.fromAnyRef("OFF"),
"akka.stdout-loglevel" -> ConfigValueFactory.fromAnyRef("OFF")
"akka.loggers" -> List("akka.testkit.TestEventListener").asJava,
"akka.loglevel" -> "OFF",
"akka.stdout-loglevel" -> "OFF",
"akka.log-dead-letters" -> "OFF"
).asJava
final case class MDCGamePacket(packet : GamePacket)

View file

@ -384,7 +384,7 @@ Even with all this work, the tests have a high chance of failure just due to bei
class AvatarReleaseTest extends ActorTest {
ServiceManager.boot(system) ! ServiceManager.Register(RandomPool(1).props(Props[TaskResolver]), "taskResolver")
val service = system.actorOf(Props[AvatarService], "release-test-service")
val zone = new Zone("test", new ZoneMap("test-map"), 0)
val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = { AddPool("dynamic", 1 to 10) } }
val taskResolver = system.actorOf(Props[TaskResolver], "release-test-resolver")
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), "release-test-zone")
zone.Actor ! Zone.Init()
@ -433,7 +433,7 @@ class AvatarReleaseTest extends ActorTest {
class AvatarReleaseEarly1Test extends ActorTest {
ServiceManager.boot(system) ! ServiceManager.Register(RandomPool(1).props(Props[TaskResolver]), "taskResolver")
val service = system.actorOf(Props[AvatarService], "release-test-service")
val zone = new Zone("test", new ZoneMap("test-map"), 0)
val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = { AddPool("dynamic", 1 to 10) } }
val taskResolver = system.actorOf(Props[TaskResolver], "release-test-resolver")
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), "release-test-zone")
zone.Actor ! Zone.Init()
@ -483,7 +483,7 @@ class AvatarReleaseEarly1Test extends ActorTest {
class AvatarReleaseEarly2Test extends ActorTest {
ServiceManager.boot(system) ! ServiceManager.Register(RandomPool(1).props(Props[TaskResolver]), "taskResolver")
val service = system.actorOf(Props[AvatarService], "release-test-service")
val zone = new Zone("test", new ZoneMap("test-map"), 0)
val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = { AddPool("dynamic", 1 to 10) } }
val taskResolver = system.actorOf(Props[TaskResolver], "release-test-resolver")
zone.Actor = system.actorOf(Props(classOf[ZoneActor], zone), "release-test-zone")
zone.Actor ! Zone.Init()