mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-02-21 07:33:39 +00:00
Restructure repository
* Move /common/src to /src * Move services to net.psforever package * Move /pslogin to /server
This commit is contained in:
parent
89a30ae6f6
commit
f4fd78fc5d
958 changed files with 527 additions and 725 deletions
110
src/test/scala/objects/AvatarTest.scala
Normal file
110
src/test/scala/objects/AvatarTest.scala
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects.GlobalDefinitions._
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.avatar.{Avatar, BattleRank, Implant}
|
||||
import net.psforever.objects.definition.ImplantDefinition
|
||||
import net.psforever.types.{CharacterGender, CharacterVoice, ImplantType, PlanetSideEmpire}
|
||||
import org.specs2.mutable._
|
||||
|
||||
class AvatarTest extends Specification {
|
||||
def CreatePlayer(): (Player, Avatar) = {
|
||||
val avatar = Avatar(0, "TestCharacter", PlanetSideEmpire.VS, CharacterGender.Female, 41, CharacterVoice.Voice1)
|
||||
val player = Player(avatar)
|
||||
player.Slot(0).Equipment = Tool(beamer)
|
||||
player.Slot(2).Equipment = Tool(suppressor)
|
||||
player.Slot(4).Equipment = Tool(forceblade)
|
||||
player.Slot(6).Equipment = AmmoBox(bullet_9mm)
|
||||
player.Slot(9).Equipment = AmmoBox(bullet_9mm)
|
||||
player.Slot(12).Equipment = AmmoBox(bullet_9mm)
|
||||
player.Slot(33).Equipment = AmmoBox(bullet_9mm_AP)
|
||||
player.Slot(36).Equipment = AmmoBox(energy_cell)
|
||||
player.Slot(39).Equipment = SimpleItem(remote_electronics_kit)
|
||||
(player, avatar)
|
||||
}
|
||||
|
||||
"construct" in {
|
||||
val av = Avatar(0, "Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
av.name mustEqual "Chord"
|
||||
av.faction mustEqual PlanetSideEmpire.TR
|
||||
av.sex mustEqual CharacterGender.Male
|
||||
av.head mustEqual 0
|
||||
av.voice mustEqual CharacterVoice.Voice5
|
||||
av.bep mustEqual 0
|
||||
av.cep mustEqual 0
|
||||
av.certifications mustEqual Set.empty
|
||||
av.definition.ObjectId mustEqual 121
|
||||
}
|
||||
|
||||
"can not maintain experience point values below zero" in {
|
||||
val av = Avatar(0, "Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
av.bep mustEqual 0
|
||||
av.copy(bep = -1) must throwA[AssertionError]
|
||||
av.copy(cep = -1) must throwA[AssertionError]
|
||||
}
|
||||
|
||||
//refer to ImplantTest.scala for more tests
|
||||
"maximum of three implant slots" in {
|
||||
val obj = Avatar(0, "Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.implants.length mustEqual 3
|
||||
obj.implants(0) must beNone
|
||||
obj.implants(1) must beNone
|
||||
obj.implants(2) must beNone
|
||||
obj.implants.lift(3) must beNone
|
||||
}
|
||||
|
||||
"can install an implant" in {
|
||||
val testplant = Implant(new ImplantDefinition(ImplantType.AdvancedRegen))
|
||||
var obj = Avatar(
|
||||
0,
|
||||
"Chord",
|
||||
PlanetSideEmpire.TR,
|
||||
CharacterGender.Male,
|
||||
0,
|
||||
CharacterVoice.Voice5,
|
||||
bep = BattleRank.BR6.experience
|
||||
)
|
||||
obj.implants.nonEmpty must beTrue
|
||||
obj.implants.length mustEqual 3
|
||||
obj = obj.copy(implants = obj.implants.updated(0, Some(testplant)))
|
||||
obj.implants.flatten.find(_.definition.implantType == ImplantType.AdvancedRegen) match {
|
||||
case Some(slot) =>
|
||||
slot.definition mustEqual testplant.definition
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
ok
|
||||
}
|
||||
|
||||
"can not install the same type of implant twice" in {
|
||||
val testplant1 = Implant(new ImplantDefinition(ImplantType.AdvancedRegen))
|
||||
val testplant2 = Implant(new ImplantDefinition(ImplantType.AdvancedRegen))
|
||||
val obj = Avatar(0, "Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.copy(implants = obj.implants.updated(0, Some(testplant1)).updated(1, Some(testplant2))) must throwA[
|
||||
AssertionError
|
||||
]
|
||||
}
|
||||
|
||||
"can not install more implants than slots available" in {
|
||||
val testplant1 = Implant(new ImplantDefinition(ImplantType.AdvancedRegen))
|
||||
val testplant2 = Implant(new ImplantDefinition(ImplantType.Surge))
|
||||
val testplant3 = Implant(new ImplantDefinition(ImplantType.DarklightVision))
|
||||
val obj = Avatar(0, "Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.copy(
|
||||
bep = BattleRank.BR12.value,
|
||||
implants = Seq(Some(testplant1), Some(testplant2), Some(testplant3))
|
||||
) must throwA[
|
||||
AssertionError
|
||||
]
|
||||
}
|
||||
|
||||
"the fifth slot is the locker wrapped in an EquipmentSlot" in {
|
||||
val (_, avatar) = CreatePlayer()
|
||||
avatar.fifthSlot().Equipment match {
|
||||
case Some(slot: LockerEquipment) => slot.Inventory mustEqual avatar.locker.Inventory
|
||||
case _ => ko
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
122
src/test/scala/objects/BuildingTest.scala
Normal file
122
src/test/scala/objects/BuildingTest.scala
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import base.ActorTest
|
||||
import net.psforever.actors.zone.BuildingActor
|
||||
import net.psforever.objects.{Default, GlobalDefinitions}
|
||||
import net.psforever.objects.serverobject.doors.Door
|
||||
import net.psforever.objects.serverobject.structures._
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
import org.specs2.mutable.Specification
|
||||
import akka.actor.typed.scaladsl.adapter._
|
||||
|
||||
class AmenityTest extends Specification {
|
||||
val definition = new AmenityDefinition(0) {
|
||||
//intentionally blank
|
||||
}
|
||||
class AmenityObject extends Amenity {
|
||||
def Definition: AmenityDefinition = definition
|
||||
}
|
||||
|
||||
"Amenity" should {
|
||||
"construct" in {
|
||||
val ao = new AmenityObject()
|
||||
ao.Owner mustEqual Building.NoBuilding
|
||||
}
|
||||
|
||||
"can be owned by a building" in {
|
||||
val ao = new AmenityObject()
|
||||
val bldg = Building("Building", 0, 10, Zone.Nowhere, StructureType.Building)
|
||||
|
||||
ao.Owner = bldg
|
||||
ao.Owner mustEqual bldg
|
||||
}
|
||||
|
||||
"be owned by a vehicle" in {
|
||||
import net.psforever.objects.Vehicle
|
||||
val ao = new AmenityObject()
|
||||
val veh = Vehicle(GlobalDefinitions.quadstealth)
|
||||
|
||||
ao.Owner = veh
|
||||
ao.Owner mustEqual veh
|
||||
}
|
||||
|
||||
"not be owned by an unexpected object" in {
|
||||
val ao = new AmenityObject()
|
||||
//ao.Owner = net.psforever.objects.serverobject.mblocker.Locker() //will not compile
|
||||
ok
|
||||
}
|
||||
|
||||
"confer faction allegiance through ownership" in {
|
||||
//see FactionAffinityTest
|
||||
val ao = new AmenityObject()
|
||||
val bldg = Building("Building", 0, 10, Zone.Nowhere, StructureType.Building)
|
||||
ao.Owner = bldg
|
||||
bldg.Faction mustEqual PlanetSideEmpire.NEUTRAL
|
||||
ao.Faction mustEqual PlanetSideEmpire.NEUTRAL
|
||||
|
||||
bldg.Faction = PlanetSideEmpire.TR
|
||||
bldg.Faction mustEqual PlanetSideEmpire.TR
|
||||
ao.Faction mustEqual PlanetSideEmpire.TR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BuildingTest extends Specification {
|
||||
"Building" should {
|
||||
"construct" in {
|
||||
val bldg = Building("Building", 0, 10, Zone.Nowhere, StructureType.Building)
|
||||
bldg.MapId mustEqual 10
|
||||
bldg.Actor mustEqual Default.Actor
|
||||
bldg.Amenities mustEqual Nil
|
||||
bldg.Zone mustEqual Zone.Nowhere
|
||||
bldg.Faction mustEqual PlanetSideEmpire.NEUTRAL
|
||||
}
|
||||
|
||||
"change faction affinity" in {
|
||||
val bldg = Building("Building", 0, 10, Zone.Nowhere, StructureType.Building)
|
||||
bldg.Faction mustEqual PlanetSideEmpire.NEUTRAL
|
||||
|
||||
bldg.Faction = PlanetSideEmpire.TR
|
||||
bldg.Faction mustEqual PlanetSideEmpire.TR
|
||||
}
|
||||
|
||||
"keep track of amenities" in {
|
||||
val bldg = Building("Building", 0, 10, Zone.Nowhere, StructureType.Building)
|
||||
val door1 = Door(GlobalDefinitions.door)
|
||||
val door2 = Door(GlobalDefinitions.door)
|
||||
|
||||
bldg.Amenities mustEqual Nil
|
||||
bldg.Amenities = door2
|
||||
bldg.Amenities mustEqual List(door2)
|
||||
bldg.Amenities = door1
|
||||
bldg.Amenities mustEqual List(door2, door1)
|
||||
door1.Owner mustEqual bldg
|
||||
door2.Owner mustEqual bldg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class WarpGateTest extends Specification {
|
||||
"WarpGate" should {
|
||||
"construct" in {
|
||||
val bldg = WarpGate("WarpGate", 0, 10, Zone.Nowhere, GlobalDefinitions.warpgate)
|
||||
bldg.MapId mustEqual 10
|
||||
bldg.Actor mustEqual Default.Actor
|
||||
bldg.Amenities mustEqual Nil
|
||||
bldg.Zone mustEqual Zone.Nowhere
|
||||
bldg.Faction mustEqual PlanetSideEmpire.NEUTRAL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BuildingActor1Test extends ActorTest {
|
||||
"Building Control" should {
|
||||
"construct" in {
|
||||
val bldg = Building("Building", 0, 10, Zone.Nowhere, StructureType.Building)
|
||||
bldg.Actor = system.spawn(BuildingActor(Zone.Nowhere, bldg), "test").toClassic
|
||||
assert(bldg.Actor != Default.Actor)
|
||||
}
|
||||
}
|
||||
}
|
||||
59
src/test/scala/objects/ContainerTest.scala
Normal file
59
src/test/scala/objects/ContainerTest.scala
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects.equipment.{EquipmentSize, EquipmentSlot}
|
||||
import net.psforever.objects.inventory.{Container, GridInventory, InventoryEquipmentSlot}
|
||||
import net.psforever.objects.{GlobalDefinitions, OffhandEquipmentSlot, Tool}
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import org.specs2.mutable._
|
||||
|
||||
import scala.util.Success
|
||||
|
||||
class ContainerTest extends Specification {
|
||||
"Container" should {
|
||||
"construct" in {
|
||||
val obj = new ContainerTest.CObject
|
||||
obj.VisibleSlots mustEqual (0 until 9).toSet
|
||||
obj.Inventory.Size mustEqual 0
|
||||
obj.Inventory.Capacity mustEqual 9
|
||||
obj.Find(PlanetSideGUID(0)) mustEqual None
|
||||
obj.Slot(0).isInstanceOf[OffhandEquipmentSlot] mustEqual true
|
||||
obj.Slot(0).isInstanceOf[InventoryEquipmentSlot] mustEqual true
|
||||
obj.Slot(0).isInstanceOf[EquipmentSlot] mustEqual true
|
||||
obj.Slot(0).Size mustEqual EquipmentSize.Inventory
|
||||
obj.Slot(0).Equipment mustEqual None
|
||||
obj.Collisions(0, 2, 2) mustEqual Success(List())
|
||||
}
|
||||
|
||||
"Collisions can Find items in Inventory (default behavior)" in {
|
||||
val obj = new ContainerTest.CObject
|
||||
val weapon = Tool(GlobalDefinitions.beamer)
|
||||
weapon.GUID = PlanetSideGUID(1)
|
||||
|
||||
obj.Inventory += 0 -> weapon
|
||||
obj.Find(PlanetSideGUID(1)) match {
|
||||
case Some(index) =>
|
||||
obj.Inventory.Items(index).obj mustEqual weapon
|
||||
case None =>
|
||||
ko
|
||||
}
|
||||
obj.Collisions(1, 1, 1) match {
|
||||
case Success(items) =>
|
||||
items.length mustEqual 1
|
||||
items.head.obj mustEqual weapon
|
||||
case _ => ;
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object ContainerTest {
|
||||
class CObject extends Container {
|
||||
private val inv = GridInventory(3, 3)
|
||||
|
||||
def Inventory: GridInventory = inv
|
||||
|
||||
def VisibleSlots: Set[Int] = Set[Int](0, 1, 2, 3, 4, 5, 6, 7, 8)
|
||||
}
|
||||
}
|
||||
949
src/test/scala/objects/ConverterTest.scala
Normal file
949
src/test/scala/objects/ConverterTest.scala
Normal file
|
|
@ -0,0 +1,949 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects.definition.converter.{CharacterSelectConverter, DestroyedVehicleConverter, REKConverter}
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
import net.psforever.objects.definition._
|
||||
import net.psforever.objects.equipment._
|
||||
import net.psforever.objects.inventory.InventoryTile
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
import net.psforever.objects.serverobject.tube.SpawnTube
|
||||
import net.psforever.objects.vehicles.UtilityType
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types._
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
import scala.util.{Failure, Success}
|
||||
|
||||
class ConverterTest extends Specification {
|
||||
"AmmoBox" should {
|
||||
val bullet_9mm = AmmoBoxDefinition(28)
|
||||
bullet_9mm.Capacity = 50
|
||||
|
||||
"convert to packet" in {
|
||||
val obj = AmmoBox(bullet_9mm)
|
||||
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual DetailedAmmoBoxData(
|
||||
CommonFieldData(
|
||||
PlanetSideEmpire.NEUTRAL,
|
||||
bops = false,
|
||||
alternate = false,
|
||||
true,
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
None,
|
||||
PlanetSideGUID(0)
|
||||
),
|
||||
obj.Capacity
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual CommonFieldData(
|
||||
PlanetSideEmpire.NEUTRAL,
|
||||
bops = false,
|
||||
alternate = false,
|
||||
false,
|
||||
None,
|
||||
false,
|
||||
Some(false),
|
||||
None,
|
||||
PlanetSideGUID(0)
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"Tool" should {
|
||||
"convert to packet (1 fire mode slot)" in {
|
||||
val obj: Tool = Tool(GlobalDefinitions.flechette)
|
||||
obj.AmmoSlot.Box.GUID = PlanetSideGUID(90)
|
||||
|
||||
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual DetailedWeaponData(
|
||||
CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0)),
|
||||
0,
|
||||
List(InternalSlot(Ammo.shotgun_shell.id, PlanetSideGUID(90), 0, DetailedAmmoBoxData(8, 12)))
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual WeaponData(
|
||||
CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0)),
|
||||
0,
|
||||
List(
|
||||
InternalSlot(
|
||||
Ammo.shotgun_shell.id,
|
||||
PlanetSideGUID(90),
|
||||
0,
|
||||
CommonFieldData(
|
||||
PlanetSideEmpire.NEUTRAL,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
None,
|
||||
false,
|
||||
Some(false),
|
||||
None,
|
||||
PlanetSideGUID(0)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"convert to packet (2 fire mode slots)" in {
|
||||
val obj: Tool = Tool(GlobalDefinitions.punisher)
|
||||
obj.AmmoSlots.head.Box.GUID = PlanetSideGUID(90)
|
||||
obj.AmmoSlots(1).Box.GUID = PlanetSideGUID(91)
|
||||
|
||||
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual DetailedWeaponData(
|
||||
CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0)),
|
||||
0,
|
||||
List(
|
||||
InternalSlot(Ammo.bullet_9mm.id, PlanetSideGUID(90), 0, DetailedAmmoBoxData(8, 30)),
|
||||
InternalSlot(Ammo.rocket.id, PlanetSideGUID(91), 1, DetailedAmmoBoxData(8, 1))
|
||||
)
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual WeaponData(
|
||||
CommonFieldData(
|
||||
PlanetSideEmpire.NEUTRAL, //TODO need faction affinity
|
||||
bops = false,
|
||||
alternate = false,
|
||||
true,
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
None,
|
||||
PlanetSideGUID(0)
|
||||
),
|
||||
0,
|
||||
List(
|
||||
InternalSlot(Ammo.bullet_9mm.id, PlanetSideGUID(90), 0, CommonFieldData()(false)),
|
||||
InternalSlot(Ammo.rocket.id, PlanetSideGUID(91), 1, CommonFieldData()(false))
|
||||
)
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"Kit" should {
|
||||
"convert to packet" in {
|
||||
val kdef = KitDefinition(Kits.medkit)
|
||||
val obj = Kit(kdef)
|
||||
obj.GUID = PlanetSideGUID(90)
|
||||
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual DetailedAmmoBoxData(0, 1)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual CommonFieldData()(false)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"ConstructionItem" should {
|
||||
"convert to packet" in {
|
||||
val obj = ConstructionItem(GlobalDefinitions.ace)
|
||||
obj.GUID = PlanetSideGUID(90)
|
||||
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual DetailedConstructionToolData(
|
||||
CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0))
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual HandheldData(
|
||||
CommonFieldData(
|
||||
PlanetSideEmpire.NEUTRAL,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
None,
|
||||
PlanetSideGUID(0)
|
||||
)
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"SimpleItem" should {
|
||||
"convert to packet" in {
|
||||
val sdef = SimpleItemDefinition(SItem.remote_electronics_kit)
|
||||
sdef.Packet = new REKConverter()
|
||||
val obj = SimpleItem(sdef)
|
||||
obj.GUID = PlanetSideGUID(90)
|
||||
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual DetailedREKData(
|
||||
CommonFieldData(
|
||||
PlanetSideEmpire.NEUTRAL, //TODO faction affinity
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
None,
|
||||
false,
|
||||
Some(false),
|
||||
None,
|
||||
PlanetSideGUID(0)
|
||||
)
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual REKData(
|
||||
CommonFieldData(
|
||||
PlanetSideEmpire.NEUTRAL,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
None,
|
||||
false,
|
||||
Some(false),
|
||||
None,
|
||||
PlanetSideGUID(0)
|
||||
)
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"BoomerTrigger" should {
|
||||
"convert" in {
|
||||
val obj = new BoomerTrigger
|
||||
obj.GUID = PlanetSideGUID(90)
|
||||
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual DetailedConstructionToolData(
|
||||
CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0))
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual HandheldData(
|
||||
CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, false, None, false, None, None, PlanetSideGUID(0))
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"Telepad" should {
|
||||
"convert (success)" in {
|
||||
val obj = new Telepad(GlobalDefinitions.router_telepad)
|
||||
obj.Router = PlanetSideGUID(1001)
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual HandheldData(
|
||||
CommonFieldData(
|
||||
PlanetSideEmpire.NEUTRAL,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
Some(1001),
|
||||
PlanetSideGUID(0)
|
||||
)
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
|
||||
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual DetailedConstructionToolData(
|
||||
CommonFieldData(
|
||||
PlanetSideEmpire.NEUTRAL,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
Some(1001),
|
||||
PlanetSideGUID(0)
|
||||
)
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"convert (failure; no router)" in {
|
||||
val obj = new Telepad(GlobalDefinitions.router_telepad)
|
||||
//obj.Router = PlanetSideGUID(1001)
|
||||
obj.Definition.Packet.ConstructorData(obj).isFailure mustEqual true
|
||||
|
||||
obj.Definition.Packet.DetailedConstructorData(obj).isFailure mustEqual true
|
||||
}
|
||||
}
|
||||
|
||||
"SmallDeployable" should {
|
||||
"convert" in {
|
||||
val obj = new SensorDeployable(GlobalDefinitions.motionalarmsensor)
|
||||
obj.Faction = PlanetSideEmpire.TR
|
||||
obj.Definition.Packet.DetailedConstructorData(obj).isFailure mustEqual true
|
||||
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual CommonFieldDataWithPlacement(
|
||||
PlacementData(Vector3.Zero, Vector3.Zero),
|
||||
CommonFieldData(
|
||||
PlanetSideEmpire.TR,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
None,
|
||||
false,
|
||||
Some(false),
|
||||
None,
|
||||
PlanetSideGUID(0)
|
||||
)
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"SmallTurret" should {
|
||||
"convert" in {
|
||||
val obj = new TurretDeployable(GlobalDefinitions.spitfire_turret)
|
||||
obj.Faction = PlanetSideEmpire.TR
|
||||
obj.GUID = PlanetSideGUID(90)
|
||||
obj.Weapons(1).Equipment.get.GUID = PlanetSideGUID(91)
|
||||
obj.Weapons(1).Equipment.get.asInstanceOf[Tool].AmmoSlot.Box.GUID = PlanetSideGUID(92)
|
||||
obj.Definition.Packet.DetailedConstructorData(obj).isFailure mustEqual true
|
||||
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual SmallTurretData(
|
||||
CommonFieldDataWithPlacement(
|
||||
PlacementData(Vector3.Zero, Vector3.Zero),
|
||||
CommonFieldData(
|
||||
PlanetSideEmpire.TR,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
None,
|
||||
false,
|
||||
Some(true),
|
||||
None,
|
||||
PlanetSideGUID(0)
|
||||
)
|
||||
),
|
||||
255,
|
||||
InventoryData(
|
||||
List(
|
||||
InternalSlot(
|
||||
ObjectClass.spitfire_weapon,
|
||||
PlanetSideGUID(91),
|
||||
1,
|
||||
WeaponData(
|
||||
CommonFieldData(
|
||||
PlanetSideEmpire.NEUTRAL,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
None,
|
||||
PlanetSideGUID(0)
|
||||
),
|
||||
0,
|
||||
List(
|
||||
InternalSlot(
|
||||
Ammo.spitfire_ammo.id,
|
||||
PlanetSideGUID(92),
|
||||
0,
|
||||
CommonFieldData(
|
||||
PlanetSideEmpire.NEUTRAL,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
None,
|
||||
false,
|
||||
Some(false),
|
||||
None,
|
||||
PlanetSideGUID(0)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"FieldTurret" should {
|
||||
"convert" in {
|
||||
val obj = new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr)
|
||||
obj.Faction = PlanetSideEmpire.TR
|
||||
obj.GUID = PlanetSideGUID(90)
|
||||
obj.Weapons(1).Equipment.get.GUID = PlanetSideGUID(91)
|
||||
obj.Weapons(1).Equipment.get.asInstanceOf[Tool].AmmoSlot.Box.GUID = PlanetSideGUID(92)
|
||||
obj.Definition.Packet.DetailedConstructorData(obj).isFailure mustEqual true
|
||||
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual OneMannedFieldTurretData(
|
||||
CommonFieldDataWithPlacement(
|
||||
PlacementData(Vector3.Zero, Vector3.Zero),
|
||||
CommonFieldData(
|
||||
PlanetSideEmpire.TR,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
None,
|
||||
false,
|
||||
Some(false),
|
||||
None,
|
||||
PlanetSideGUID(0)
|
||||
)
|
||||
),
|
||||
255,
|
||||
InventoryData(
|
||||
List(
|
||||
InternalSlot(
|
||||
ObjectClass.energy_gun_tr,
|
||||
PlanetSideGUID(91),
|
||||
1,
|
||||
WeaponData(
|
||||
CommonFieldData(
|
||||
PlanetSideEmpire.NEUTRAL,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
None,
|
||||
PlanetSideGUID(0)
|
||||
),
|
||||
0,
|
||||
List(
|
||||
InternalSlot(
|
||||
Ammo.energy_gun_ammo.id,
|
||||
PlanetSideGUID(92),
|
||||
0,
|
||||
CommonFieldData(
|
||||
PlanetSideEmpire.NEUTRAL,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
None,
|
||||
false,
|
||||
Some(false),
|
||||
None,
|
||||
PlanetSideGUID(0)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"TRAP" should {
|
||||
"convert" in {
|
||||
val obj = new TrapDeployable(GlobalDefinitions.tank_traps)
|
||||
obj.Faction = PlanetSideEmpire.TR
|
||||
obj.GUID = PlanetSideGUID(90)
|
||||
obj.Definition.Packet.DetailedConstructorData(obj).isFailure mustEqual true
|
||||
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual TRAPData(
|
||||
CommonFieldDataWithPlacement(
|
||||
PlacementData(Vector3.Zero, Vector3.Zero),
|
||||
CommonFieldData(
|
||||
PlanetSideEmpire.TR,
|
||||
bops = false,
|
||||
alternate = false,
|
||||
true,
|
||||
None,
|
||||
false,
|
||||
Some(true),
|
||||
None,
|
||||
PlanetSideGUID(0)
|
||||
)
|
||||
),
|
||||
255
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"ShieldGenerator" should {
|
||||
"convert" in {
|
||||
val obj = new ShieldGeneratorDeployable(GlobalDefinitions.deployable_shield_generator)
|
||||
obj.Faction = PlanetSideEmpire.TR
|
||||
obj.GUID = PlanetSideGUID(90)
|
||||
obj.Definition.Packet.DetailedConstructorData(obj).isFailure mustEqual true
|
||||
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual AegisShieldGeneratorData(
|
||||
CommonFieldDataWithPlacement(
|
||||
PlacementData(Vector3.Zero, Vector3.Zero),
|
||||
PlanetSideEmpire.TR,
|
||||
0
|
||||
),
|
||||
255
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"TelepadDeployable" should {
|
||||
"convert (success)" in {
|
||||
val obj = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||
obj.Faction = PlanetSideEmpire.TR
|
||||
obj.GUID = PlanetSideGUID(90)
|
||||
obj.Router = PlanetSideGUID(1001)
|
||||
obj.Owner = PlanetSideGUID(5001)
|
||||
obj.Health = 1
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual DroppedItemData(
|
||||
PlacementData(Vector3.Zero, Vector3.Zero),
|
||||
TelepadDeployableData(
|
||||
CommonFieldData(
|
||||
PlanetSideEmpire.TR,
|
||||
bops = false,
|
||||
alternate = false,
|
||||
true,
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
Some(1001),
|
||||
PlanetSideGUID(5001)
|
||||
),
|
||||
unk1 = 87,
|
||||
unk2 = 12
|
||||
)
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"convert (success; destroyed)" in {
|
||||
val obj = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||
obj.Faction = PlanetSideEmpire.TR
|
||||
obj.GUID = PlanetSideGUID(90)
|
||||
obj.Router = PlanetSideGUID(1001)
|
||||
obj.Owner = PlanetSideGUID(5001)
|
||||
obj.Health = 0
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual DroppedItemData(
|
||||
PlacementData(Vector3.Zero, Vector3.Zero),
|
||||
TelepadDeployableData(
|
||||
CommonFieldData(
|
||||
PlanetSideEmpire.TR,
|
||||
bops = false,
|
||||
alternate = true,
|
||||
true,
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
Some(1001),
|
||||
PlanetSideGUID(0)
|
||||
),
|
||||
unk1 = 0,
|
||||
unk2 = 6
|
||||
)
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"convert (failure; no router)" in {
|
||||
val obj = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||
obj.Faction = PlanetSideEmpire.TR
|
||||
obj.GUID = PlanetSideGUID(90)
|
||||
//obj.Router = PlanetSideGUID(1001)
|
||||
obj.Owner = PlanetSideGUID(5001)
|
||||
obj.Health = 1
|
||||
obj.Definition.Packet.ConstructorData(obj).isFailure mustEqual true
|
||||
|
||||
obj.Router = PlanetSideGUID(0)
|
||||
obj.Definition.Packet.ConstructorData(obj).isFailure mustEqual true
|
||||
}
|
||||
|
||||
"convert (failure; detailed)" in {
|
||||
val obj = new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||
obj.Faction = PlanetSideEmpire.TR
|
||||
obj.GUID = PlanetSideGUID(90)
|
||||
obj.Router = PlanetSideGUID(1001)
|
||||
obj.Owner = PlanetSideGUID(5001)
|
||||
obj.Health = 1
|
||||
obj.Definition.Packet.DetailedConstructorData(obj).isFailure mustEqual true
|
||||
}
|
||||
}
|
||||
|
||||
"Player" should {
|
||||
var avatar = Avatar(0, "Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
val obj: Player = {
|
||||
/*
|
||||
Create an AmmoBoxDefinition with which to build two AmmoBoxes
|
||||
Create a ToolDefinition with which to create a Tool
|
||||
Load one of the AmmoBoxes into that Tool
|
||||
Create a Player
|
||||
Give the Player's Holster (2) the Tool
|
||||
Place the remaining AmmoBox into the Player's inventory in the third slot (8)
|
||||
*/
|
||||
val tdef = ToolDefinition(1076)
|
||||
tdef.Name = "sample_weapon"
|
||||
tdef.Size = EquipmentSize.Rifle
|
||||
tdef.AmmoTypes += GlobalDefinitions.bullet_9mm
|
||||
tdef.FireModes += new FireModeDefinition
|
||||
tdef.FireModes.head.AmmoTypeIndices += 0
|
||||
tdef.FireModes.head.AmmoSlotIndex = 0
|
||||
tdef.FireModes.head.Magazine = 18
|
||||
val tool = Tool(tdef)
|
||||
tool.GUID = PlanetSideGUID(92)
|
||||
tool.AmmoSlot.Box.GUID = PlanetSideGUID(90)
|
||||
val obj = Player(avatar)
|
||||
obj.GUID = PlanetSideGUID(93)
|
||||
obj.Slot(2).Equipment = tool
|
||||
obj.Slot(5).Equipment.get.GUID = PlanetSideGUID(94)
|
||||
obj.Inventory += 8 -> AmmoBox(GlobalDefinitions.bullet_9mm)
|
||||
obj.Slot(8).Equipment.get.GUID = PlanetSideGUID(91)
|
||||
obj
|
||||
}
|
||||
val converter = new CharacterSelectConverter
|
||||
|
||||
"convert to packet (BR < 24)" in {
|
||||
avatar = avatar.copy(bep = 0)
|
||||
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
||||
case Success(_) =>
|
||||
ok
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(_) =>
|
||||
ok
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"convert to packet (BR >= 24)" in {
|
||||
avatar = avatar.copy(bep = 10000000)
|
||||
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
||||
case Success(_) =>
|
||||
ok
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(_) =>
|
||||
ok
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"convert to simple packet (BR < 24)" in {
|
||||
avatar = avatar.copy(bep = 0)
|
||||
converter.DetailedConstructorData(obj) match {
|
||||
case Success(_) =>
|
||||
ok
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
converter.ConstructorData(obj).isFailure mustEqual true
|
||||
converter.ConstructorData(obj).get must throwA[Exception]
|
||||
}
|
||||
|
||||
"convert to simple packet (BR >= 24)" in {
|
||||
avatar = avatar.copy(bep = 10000000)
|
||||
converter.DetailedConstructorData(obj) match {
|
||||
case Success(_) =>
|
||||
ok
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
converter.ConstructorData(obj).isFailure mustEqual true
|
||||
converter.ConstructorData(obj).get must throwA[Exception]
|
||||
}
|
||||
}
|
||||
|
||||
"LockerContainer" should {
|
||||
"convert to packet (empty)" in {
|
||||
val obj = new LockerEquipment(LockerContainer())
|
||||
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual DetailedLockerContainerData(
|
||||
CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0)),
|
||||
None
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual LockerContainerData(None)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"convert to packet (occupied)" in {
|
||||
import GlobalDefinitions._
|
||||
val obj = new LockerEquipment(LockerContainer())
|
||||
val rek = SimpleItem(remote_electronics_kit)
|
||||
rek.GUID = PlanetSideGUID(1)
|
||||
obj.Inventory += 0 -> rek
|
||||
|
||||
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual DetailedLockerContainerData(
|
||||
8,
|
||||
InternalSlot(
|
||||
remote_electronics_kit.ObjectId,
|
||||
PlanetSideGUID(1),
|
||||
0,
|
||||
DetailedREKData(
|
||||
CommonFieldData(
|
||||
PlanetSideEmpire.NEUTRAL,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
None,
|
||||
false,
|
||||
Some(false),
|
||||
None,
|
||||
PlanetSideGUID(0)
|
||||
)
|
||||
)
|
||||
) :: Nil
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual LockerContainerData(
|
||||
InventoryData(
|
||||
InternalSlot(
|
||||
remote_electronics_kit.ObjectId,
|
||||
PlanetSideGUID(1),
|
||||
0,
|
||||
REKData(
|
||||
CommonFieldData(
|
||||
PlanetSideEmpire.NEUTRAL,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
None,
|
||||
false,
|
||||
Some(false),
|
||||
None,
|
||||
PlanetSideGUID(0)
|
||||
)
|
||||
)
|
||||
) :: Nil
|
||||
)
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"Terminal" should {
|
||||
"convert to packet" in {
|
||||
val obj = Terminal(GlobalDefinitions.order_terminala)
|
||||
|
||||
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
||||
case Failure(err) =>
|
||||
err.isInstanceOf[NoSuchMethodException] mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual CommonFieldData(PlanetSideEmpire.NEUTRAL)(false)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"Spawn Tube" should {
|
||||
"convert to packet" in {
|
||||
val obj = SpawnTube(GlobalDefinitions.ams_respawn_tube)
|
||||
|
||||
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
||||
case Failure(err) =>
|
||||
err.isInstanceOf[NoSuchMethodException] mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual CommonFieldData(PlanetSideEmpire.NEUTRAL)(false)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"Vehicle" should {
|
||||
"convert to packet (1)" in {
|
||||
val hellfire_ammo = AmmoBoxDefinition(Ammo.hellfire_ammo.id)
|
||||
|
||||
val fury_weapon_systema_def = ToolDefinition(ObjectClass.fury_weapon_systema)
|
||||
fury_weapon_systema_def.Size = EquipmentSize.VehicleWeapon
|
||||
fury_weapon_systema_def.AmmoTypes += GlobalDefinitions.hellfire_ammo
|
||||
fury_weapon_systema_def.FireModes += new FireModeDefinition
|
||||
fury_weapon_systema_def.FireModes.head.AmmoTypeIndices += 0
|
||||
fury_weapon_systema_def.FireModes.head.AmmoSlotIndex = 0
|
||||
fury_weapon_systema_def.FireModes.head.Magazine = 2
|
||||
|
||||
val fury_def = VehicleDefinition(ObjectClass.fury)
|
||||
fury_def.Seats += 0 -> new SeatDefinition()
|
||||
fury_def.Seats(0).Bailable = true
|
||||
fury_def.Seats(0).ControlledWeapon = Some(1)
|
||||
fury_def.MountPoints += 0 -> 0
|
||||
fury_def.MountPoints += 2 -> 0
|
||||
fury_def.Weapons += 1 -> fury_weapon_systema_def
|
||||
fury_def.TrunkSize = InventoryTile(11, 11)
|
||||
fury_def.TrunkOffset = 30
|
||||
|
||||
val hellfire_ammo_box = AmmoBox(hellfire_ammo)
|
||||
hellfire_ammo_box.GUID = PlanetSideGUID(432)
|
||||
|
||||
val fury = Vehicle(fury_def)
|
||||
fury.GUID = PlanetSideGUID(413)
|
||||
fury.Faction = PlanetSideEmpire.VS
|
||||
fury.Position = Vector3(3674.8438f, 2732f, 91.15625f)
|
||||
fury.Orientation = Vector3(0.0f, 0.0f, 90.0f)
|
||||
fury.WeaponControlledFromSeat(0).get.GUID = PlanetSideGUID(400)
|
||||
fury.WeaponControlledFromSeat(0).get.asInstanceOf[Tool].AmmoSlots.head.Box = hellfire_ammo_box
|
||||
|
||||
fury.Definition.Packet.ConstructorData(fury).isSuccess mustEqual true
|
||||
ok //TODO write more of this test
|
||||
}
|
||||
|
||||
"convert to packet (2)" in {
|
||||
val ams = Vehicle(GlobalDefinitions.ams)
|
||||
ams.GUID = PlanetSideGUID(413)
|
||||
ams.Utilities(1)().GUID = PlanetSideGUID(414)
|
||||
ams.Utilities(2)().GUID = PlanetSideGUID(415)
|
||||
ams.Utilities(3)().GUID = PlanetSideGUID(416)
|
||||
ams.Utilities(4)().GUID = PlanetSideGUID(417)
|
||||
|
||||
ams.Definition.Packet.ConstructorData(ams).isSuccess mustEqual true
|
||||
}
|
||||
|
||||
"convert to packet (3)" in {
|
||||
val ams = Vehicle(GlobalDefinitions.ams)
|
||||
ams.GUID = PlanetSideGUID(413)
|
||||
ams.Health = 0 //destroyed vehicle
|
||||
|
||||
ams.Definition.Packet.ConstructorData(ams).isSuccess mustEqual true
|
||||
//did not initialize the utilities, but the converter did not fail
|
||||
}
|
||||
|
||||
"convert to packet (4)" in {
|
||||
val router = Vehicle(GlobalDefinitions.router)
|
||||
router.GUID = PlanetSideGUID(413)
|
||||
router.Utility(UtilityType.teleportpad_terminal).get.GUID = PlanetSideGUID(1413)
|
||||
router.Utility(UtilityType.internal_router_telepad_deployable).get.GUID = PlanetSideGUID(2413)
|
||||
router.Definition.Packet.ConstructorData(router).isSuccess mustEqual true
|
||||
}
|
||||
}
|
||||
|
||||
"DestroyedVehicle" should {
|
||||
"not convert a working vehicle" in {
|
||||
val ams = Vehicle(GlobalDefinitions.ams)
|
||||
ams.GUID = PlanetSideGUID(413)
|
||||
(ams.Health > 0) mustEqual true //not destroyed vehicle
|
||||
DestroyedVehicleConverter.converter.ConstructorData(ams).isFailure mustEqual true
|
||||
}
|
||||
|
||||
"convert to packet" in {
|
||||
val ams = Vehicle(GlobalDefinitions.ams)
|
||||
ams.GUID = PlanetSideGUID(413)
|
||||
ams.Health = 0
|
||||
DestroyedVehicleConverter.converter.ConstructorData(ams).isSuccess mustEqual true
|
||||
//did not initialize the utilities, but the converter did not fail
|
||||
}
|
||||
|
||||
"not convert into a detailed packet" in {
|
||||
val ams = Vehicle(GlobalDefinitions.ams)
|
||||
ams.GUID = PlanetSideGUID(413)
|
||||
ams.Health = 0
|
||||
DestroyedVehicleConverter.converter.DetailedConstructorData(ams).isFailure mustEqual true
|
||||
}
|
||||
}
|
||||
}
|
||||
608
src/test/scala/objects/DamageModelTests.scala
Normal file
608
src/test/scala/objects/DamageModelTests.scala
Normal file
|
|
@ -0,0 +1,608 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.vital.damage.{DamageCalculations, DamageModifiers, DamageProfile}
|
||||
import DamageCalculations._
|
||||
import net.psforever.objects.vital.resistance.ResistanceCalculations
|
||||
import ResistanceCalculations._
|
||||
import net.psforever.objects.vital.resolution.ResolutionCalculations
|
||||
import ResolutionCalculations._
|
||||
import net.psforever.objects.ballistics._
|
||||
import net.psforever.objects.definition.{ProjectileDefinition, VehicleDefinition}
|
||||
import net.psforever.objects.vital.{DamageType, Vitality}
|
||||
import net.psforever.packet.game.objectcreate.ObjectClass
|
||||
import net.psforever.types._
|
||||
import org.specs2.mutable.Specification
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
|
||||
class DamageCalculationsTests extends Specification {
|
||||
"DamageCalculations" should {
|
||||
val wep = GlobalDefinitions.galaxy_gunship_cannon
|
||||
val wep_fmode = Tool(wep).FireMode
|
||||
val wep_prof = wep_fmode.Add
|
||||
val proj = DamageModelTests.projectile
|
||||
val proj_prof = proj.asInstanceOf[DamageProfile]
|
||||
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
val projectile = Projectile(proj, wep, wep_fmode, player, Vector3(2, 2, 0), Vector3.Zero)
|
||||
val target = Vehicle(GlobalDefinitions.fury)
|
||||
target.Position = Vector3(10, 0, 0)
|
||||
val resprojectile = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
projectile,
|
||||
SourceEntry(target),
|
||||
target.DamageModel,
|
||||
Vector3(15, 0, 0)
|
||||
)
|
||||
|
||||
"extract no damage numbers" in {
|
||||
AgainstNothing(proj_prof) mustEqual 0
|
||||
}
|
||||
|
||||
"extract damage against exosuit target" in {
|
||||
AgainstExoSuit(proj_prof) == proj_prof.Damage0 mustEqual true
|
||||
}
|
||||
|
||||
"extract damage against MAX target" in {
|
||||
AgainstMaxSuit(proj_prof) == proj_prof.Damage3 mustEqual true
|
||||
}
|
||||
|
||||
"extract damage against vehicle target" in {
|
||||
AgainstVehicle(proj_prof) == proj_prof.Damage1 mustEqual true
|
||||
}
|
||||
|
||||
"extract damage against aircraft target" in {
|
||||
AgainstAircraft(proj_prof) == proj_prof.Damage2 mustEqual true
|
||||
}
|
||||
|
||||
"extract damage against battleframe robotics" in {
|
||||
AgainstBFR(proj_prof) == proj_prof.Damage4 mustEqual true
|
||||
}
|
||||
|
||||
"no degrade damage modifier" in {
|
||||
DamageModifiers.SameHit.Calculate(100, resprojectile) mustEqual 100
|
||||
}
|
||||
|
||||
"degrade over distance damage modifier (no degrade)" in {
|
||||
val resprojectile2 = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
projectile,
|
||||
SourceEntry(target),
|
||||
target.DamageModel,
|
||||
Vector3(10, 0, 0)
|
||||
)
|
||||
DamageModifiers.DistanceDegrade.Calculate(100, resprojectile2) == 100 mustEqual true
|
||||
}
|
||||
|
||||
"degrade over distance damage modifier (some degrade)" in {
|
||||
val resprojectile2 = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
projectile,
|
||||
SourceEntry(target),
|
||||
target.DamageModel,
|
||||
Vector3(100, 0, 0)
|
||||
)
|
||||
val damage = DamageModifiers.DistanceDegrade.Calculate(100, resprojectile2)
|
||||
damage < 100 && damage > 0 mustEqual true
|
||||
}
|
||||
|
||||
"degrade over distance damage modifier (zero'd)" in {
|
||||
val resprojectile2 = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
projectile,
|
||||
SourceEntry(target),
|
||||
target.DamageModel,
|
||||
Vector3(1000, 0, 0)
|
||||
)
|
||||
DamageModifiers.DistanceDegrade.Calculate(100, resprojectile2) == 0 mustEqual true
|
||||
}
|
||||
|
||||
"degrade at radial distance damage modifier (no degrade)" in {
|
||||
val resprojectile2 = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
projectile,
|
||||
SourceEntry(target),
|
||||
target.DamageModel,
|
||||
Vector3(10, 0, 0)
|
||||
)
|
||||
DamageModifiers.RadialDegrade.Calculate(100, resprojectile2) == 100 mustEqual true
|
||||
}
|
||||
|
||||
"degrade at radial distance damage modifier (some degrade)" in {
|
||||
val damage = DamageModifiers.RadialDegrade.Calculate(100, resprojectile)
|
||||
damage < 100 && damage > 0 mustEqual true
|
||||
}
|
||||
|
||||
"degrade at radial distance damage modifier (zero'd)" in {
|
||||
val resprojectile2 = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
projectile,
|
||||
SourceEntry(target),
|
||||
target.DamageModel,
|
||||
Vector3(1000, 0, 0)
|
||||
)
|
||||
DamageModifiers.RadialDegrade.Calculate(100, resprojectile2) == 0 mustEqual true
|
||||
}
|
||||
|
||||
"lash degrade (no lash; too close)" in {
|
||||
val resprojectile2 = ResolvedProjectile(
|
||||
ProjectileResolution.Lash,
|
||||
projectile,
|
||||
SourceEntry(target),
|
||||
target.DamageModel,
|
||||
Vector3(5, 0, 0) //compared to Vector3(2, 2, 0)
|
||||
)
|
||||
DamageModifiers.Lash.Calculate(100, resprojectile2) == 0 mustEqual true
|
||||
}
|
||||
|
||||
"lash degrade (lash)" in {
|
||||
val resprojectile2 = ResolvedProjectile(
|
||||
ProjectileResolution.Lash,
|
||||
projectile,
|
||||
SourceEntry(target),
|
||||
target.DamageModel,
|
||||
Vector3(20, 0, 0)
|
||||
)
|
||||
val damage = DamageModifiers.Lash.Calculate(100, resprojectile2)
|
||||
damage < 100 && damage > 0 mustEqual true
|
||||
}
|
||||
|
||||
"lash degrade (no lash; too far)" in {
|
||||
val resprojectile2 = ResolvedProjectile(
|
||||
ProjectileResolution.Lash,
|
||||
projectile,
|
||||
SourceEntry(target),
|
||||
target.DamageModel,
|
||||
Vector3(1000, 0, 0)
|
||||
)
|
||||
DamageModifiers.Lash.Calculate(100, resprojectile2) == 0 mustEqual true
|
||||
}
|
||||
|
||||
"extract a complete damage profile" in {
|
||||
val result1 = DamageModifiers.RadialDegrade.Calculate(
|
||||
AgainstVehicle(proj_prof) + AgainstVehicle(wep_prof),
|
||||
resprojectile
|
||||
)
|
||||
val result2 = DamageCalculations.DamageWithModifiers(AgainstVehicle, resprojectile)
|
||||
result1 mustEqual result2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ResistanceCalculationsTests extends Specification {
|
||||
val wep = GlobalDefinitions.galaxy_gunship_cannon
|
||||
val wep_fmode = Tool(wep).FireMode
|
||||
val proj = DamageModelTests.projectile
|
||||
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
val projectile = Projectile(proj, wep, wep_fmode, player, Vector3(2, 2, 0), Vector3.Zero)
|
||||
|
||||
"ResistanceCalculations" should {
|
||||
"ignore all targets" in {
|
||||
val target = Vehicle(GlobalDefinitions.fury)
|
||||
val resprojectile = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
projectile,
|
||||
SourceEntry(target),
|
||||
target.DamageModel,
|
||||
Vector3.Zero
|
||||
)
|
||||
InvalidTarget(resprojectile).isFailure mustEqual true
|
||||
}
|
||||
|
||||
"discern standard infantry targets" in {
|
||||
val target = player
|
||||
val resprojectile = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
projectile,
|
||||
SourceEntry(target),
|
||||
target.DamageModel,
|
||||
Vector3.Zero
|
||||
)
|
||||
ValidInfantryTarget(resprojectile).isSuccess mustEqual true
|
||||
ValidMaxTarget(resprojectile).isSuccess mustEqual false
|
||||
ValidVehicleTarget(resprojectile).isSuccess mustEqual false
|
||||
ValidAircraftTarget(resprojectile).isSuccess mustEqual false
|
||||
}
|
||||
|
||||
"discern mechanized infantry targets" in {
|
||||
val target = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
target.ExoSuit = ExoSuitType.MAX
|
||||
val resprojectile = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
projectile,
|
||||
SourceEntry(target),
|
||||
target.DamageModel,
|
||||
Vector3.Zero
|
||||
)
|
||||
ValidInfantryTarget(resprojectile).isSuccess mustEqual false
|
||||
ValidMaxTarget(resprojectile).isSuccess mustEqual true
|
||||
ValidVehicleTarget(resprojectile).isSuccess mustEqual false
|
||||
ValidAircraftTarget(resprojectile).isSuccess mustEqual false
|
||||
}
|
||||
|
||||
"discern ground vehicle targets" in {
|
||||
val target = Vehicle(GlobalDefinitions.fury)
|
||||
val resprojectile = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
projectile,
|
||||
SourceEntry(target),
|
||||
target.DamageModel,
|
||||
Vector3.Zero
|
||||
)
|
||||
ValidInfantryTarget(resprojectile).isSuccess mustEqual false
|
||||
ValidMaxTarget(resprojectile).isSuccess mustEqual false
|
||||
ValidVehicleTarget(resprojectile).isSuccess mustEqual true
|
||||
ValidAircraftTarget(resprojectile).isSuccess mustEqual false
|
||||
}
|
||||
|
||||
"discern flying vehicle targets" in {
|
||||
val target = Vehicle(GlobalDefinitions.mosquito)
|
||||
val resprojectile = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
projectile,
|
||||
SourceEntry(target),
|
||||
target.DamageModel,
|
||||
Vector3.Zero
|
||||
)
|
||||
ValidInfantryTarget(resprojectile).isSuccess mustEqual false
|
||||
ValidMaxTarget(resprojectile).isSuccess mustEqual false
|
||||
ValidVehicleTarget(resprojectile).isSuccess mustEqual false
|
||||
ValidAircraftTarget(resprojectile).isSuccess mustEqual true
|
||||
}
|
||||
|
||||
"extract no resistance values" in {
|
||||
NoResistExtractor(SourceEntry(player)) mustEqual 0
|
||||
}
|
||||
|
||||
"extract resistance values from exo-suit" in {
|
||||
val pSource = PlayerSource(player)
|
||||
ExoSuitDirectExtractor(pSource) mustEqual 4
|
||||
ExoSuitSplashExtractor(pSource) mustEqual 15
|
||||
ExoSuitAggravatedExtractor(pSource) mustEqual 8
|
||||
ExoSuitRadiationExtractor(pSource) mustEqual 0
|
||||
}
|
||||
|
||||
"extract resistance values from vehicle" in {
|
||||
val vSource = VehicleSource(Vehicle(GlobalDefinitions.fury))
|
||||
VehicleDirectExtractor(vSource) mustEqual 0
|
||||
VehicleSplashExtractor(vSource) mustEqual 0
|
||||
VehicleAggravatedExtractor(vSource) mustEqual 0
|
||||
VehicleRadiationExtractor(vSource) mustEqual 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ResolutionCalculationsTests extends Specification {
|
||||
val wep = GlobalDefinitions.galaxy_gunship_cannon
|
||||
val wep_fmode = Tool(wep).FireMode
|
||||
val proj = DamageModelTests.projectile
|
||||
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
player.Spawn()
|
||||
val projectile = Projectile(proj, wep, wep_fmode, player, Vector3(2, 2, 0), Vector3.Zero)
|
||||
|
||||
"ResolutionCalculations" should {
|
||||
"calculate no damage" in {
|
||||
val target = player
|
||||
val resprojectile = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
projectile,
|
||||
SourceEntry(target),
|
||||
target.DamageModel,
|
||||
Vector3.Zero
|
||||
)
|
||||
ResolutionCalculations.NoDamage(resprojectile)(50, 50) mustEqual 0
|
||||
}
|
||||
|
||||
"calculate no infantry damage for vehicles" in {
|
||||
val target1 = Vehicle(GlobalDefinitions.fury) //!
|
||||
val resprojectile1 = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
projectile,
|
||||
SourceEntry(target1),
|
||||
target1.DamageModel,
|
||||
Vector3.Zero
|
||||
)
|
||||
InfantryDamageAfterResist(resprojectile1)(50, 10) mustEqual (0, 0)
|
||||
|
||||
val target2 = player
|
||||
val resprojectile2 = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
projectile,
|
||||
SourceEntry(target2),
|
||||
target2.DamageModel,
|
||||
Vector3.Zero
|
||||
)
|
||||
InfantryDamageAfterResist(resprojectile2)(50, 10) mustEqual (40, 10)
|
||||
}
|
||||
|
||||
"calculate health and armor damage for infantry target" in {
|
||||
InfantryDamageAfterResist(100, 100)(50, 10) mustEqual (40, 10)
|
||||
}
|
||||
|
||||
"calculate health and armor damage, with bleed through damage, for infantry target" in {
|
||||
//health = 100, armor = 5 -> resist 10 but only have 5, so rollover extra -> damages (40+5, 5)
|
||||
InfantryDamageAfterResist(100, 5)(50, 10) mustEqual (45, 5)
|
||||
}
|
||||
|
||||
"calculate health damage for infantry target" in {
|
||||
//health = 100, armor = 0
|
||||
InfantryDamageAfterResist(100, 0)(50, 10) mustEqual (50, 0)
|
||||
}
|
||||
|
||||
"calculate armor damage for infantry target" in {
|
||||
//resistance > damage
|
||||
InfantryDamageAfterResist(100, 100)(50, 60) mustEqual (0, 50)
|
||||
}
|
||||
|
||||
val player2 = Player(Avatar(0, "TestCharacter2", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
player2.ExoSuit = ExoSuitType.MAX
|
||||
player2.Spawn()
|
||||
"calculate no max damage for vehicles" in {
|
||||
val target1 = Vehicle(GlobalDefinitions.fury) //!
|
||||
val resprojectile1 = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
projectile,
|
||||
SourceEntry(target1),
|
||||
target1.DamageModel,
|
||||
Vector3.Zero
|
||||
)
|
||||
MaxDamageAfterResist(resprojectile1)(50, 10) mustEqual (0, 0)
|
||||
|
||||
val target2 = player2
|
||||
val resprojectile2 = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
projectile,
|
||||
SourceEntry(target2),
|
||||
target2.DamageModel,
|
||||
Vector3.Zero
|
||||
)
|
||||
MaxDamageAfterResist(resprojectile2)(50, 10) mustEqual (0, 40)
|
||||
}
|
||||
|
||||
"calculate health and armor damage for max target" in {
|
||||
MaxDamageAfterResist(100, 5)(50, 10) mustEqual (35, 5)
|
||||
}
|
||||
|
||||
"calculate health damage for max target" in {
|
||||
//health = 100, armor = 0
|
||||
MaxDamageAfterResist(100, 0)(50, 10) mustEqual (40, 0)
|
||||
}
|
||||
|
||||
"calculate armor damage for max target" in {
|
||||
//resistance > damage
|
||||
MaxDamageAfterResist(100, 100)(50, 10) mustEqual (0, 40)
|
||||
}
|
||||
|
||||
"do not care if target is infantry for vehicle calculations" in {
|
||||
val target1 = player
|
||||
val resprojectile1 = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
projectile,
|
||||
SourceEntry(target1),
|
||||
target1.DamageModel,
|
||||
Vector3.Zero
|
||||
)
|
||||
VehicleDamageAfterResist(resprojectile1)(50, 10) mustEqual 40
|
||||
|
||||
val target2 = Vehicle(GlobalDefinitions.fury) //!
|
||||
val resprojectile2 = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
projectile,
|
||||
SourceEntry(target2),
|
||||
target2.DamageModel,
|
||||
Vector3.Zero
|
||||
)
|
||||
VehicleDamageAfterResist(resprojectile2)(50, 10) mustEqual 40
|
||||
}
|
||||
|
||||
"calculate resisted damage for vehicle target" in {
|
||||
VehicleDamageAfterResist(50, 10) mustEqual 40
|
||||
}
|
||||
|
||||
"calculate un-resisted damage for vehicle target" in {
|
||||
VehicleDamageAfterResist(50, 0) mustEqual 50
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DamageModelTests extends Specification {
|
||||
val wep = GlobalDefinitions.galaxy_gunship_cannon
|
||||
val wep_tool = Tool(wep)
|
||||
val wep_fmode = wep_tool.FireMode
|
||||
val proj = DamageModelTests.projectile
|
||||
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
player.Spawn()
|
||||
val projectile = Projectile(proj, wep, wep_fmode, player, Vector3(2, 2, 0), Vector3.Zero)
|
||||
|
||||
"DamageModel" should {
|
||||
"be a part of vitality" in {
|
||||
player.isInstanceOf[Vitality] mustEqual true
|
||||
try {
|
||||
player.getClass.getDeclaredMethod("DamageModel").hashCode()
|
||||
} catch {
|
||||
case _: Exception =>
|
||||
ko //the method doesn't exist
|
||||
}
|
||||
|
||||
wep_tool.isInstanceOf[Vitality] mustEqual false
|
||||
try {
|
||||
wep_tool.getClass.getDeclaredMethod("DamageModel").hashCode()
|
||||
ko
|
||||
} catch {
|
||||
case _: Exception =>
|
||||
ok //the method doesn't exist
|
||||
}
|
||||
ok
|
||||
}
|
||||
|
||||
"resolve infantry targets" in {
|
||||
val tplayer =
|
||||
Player(Avatar(0, "TestCharacter2", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
tplayer.Spawn()
|
||||
tplayer.Health mustEqual 100
|
||||
tplayer.Armor mustEqual 50
|
||||
|
||||
val resprojectile = ResolvedProjectile(
|
||||
ProjectileResolution.Hit,
|
||||
projectile,
|
||||
SourceEntry(tplayer),
|
||||
tplayer.DamageModel,
|
||||
Vector3.Zero
|
||||
)
|
||||
val func: Any => ResolvedProjectile = resprojectile.damage_model.Calculate(resprojectile)
|
||||
|
||||
func(tplayer)
|
||||
tplayer.Health mustEqual 54
|
||||
tplayer.Armor mustEqual 46
|
||||
}
|
||||
|
||||
"resolve infantry targets in a specific way" in {
|
||||
val tplayer =
|
||||
Player(Avatar(0, "TestCharacter2", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
tplayer.Spawn()
|
||||
tplayer.Health mustEqual 100
|
||||
tplayer.Armor mustEqual 50
|
||||
|
||||
val resprojectile = ResolvedProjectile(
|
||||
ProjectileResolution.Hit,
|
||||
projectile,
|
||||
SourceEntry(tplayer),
|
||||
tplayer.DamageModel,
|
||||
Vector3.Zero
|
||||
)
|
||||
val func: Any => ResolvedProjectile =
|
||||
resprojectile.damage_model.Calculate(resprojectile, ProjectileResolution.Splash)
|
||||
|
||||
func(tplayer)
|
||||
tplayer.Health mustEqual 65
|
||||
tplayer.Armor mustEqual 35
|
||||
}
|
||||
|
||||
"resolve infantry targets, with damage overflow" in {
|
||||
val tplayer =
|
||||
Player(Avatar(0, "TestCharacter2", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
tplayer.Spawn()
|
||||
tplayer.Health mustEqual 100
|
||||
tplayer.Armor mustEqual 50
|
||||
|
||||
val resprojectile = ResolvedProjectile(
|
||||
ProjectileResolution.Hit,
|
||||
projectile,
|
||||
SourceEntry(tplayer),
|
||||
tplayer.DamageModel,
|
||||
Vector3.Zero
|
||||
)
|
||||
val func: Any => ResolvedProjectile = resprojectile.damage_model.Calculate(resprojectile)
|
||||
tplayer.Armor = 0
|
||||
|
||||
func(tplayer)
|
||||
tplayer.Health mustEqual 50
|
||||
tplayer.Armor mustEqual 0
|
||||
}
|
||||
|
||||
"resolve vehicle targets" in {
|
||||
val vehicle = Vehicle(DamageModelTests.vehicle)
|
||||
vehicle.Health mustEqual 650
|
||||
|
||||
val resprojectile = ResolvedProjectile(
|
||||
ProjectileResolution.Hit,
|
||||
projectile,
|
||||
SourceEntry(vehicle),
|
||||
vehicle.DamageModel,
|
||||
Vector3.Zero
|
||||
)
|
||||
val func: Any => ResolvedProjectile = resprojectile.damage_model.Calculate(resprojectile)
|
||||
|
||||
func(vehicle)
|
||||
vehicle.Health mustEqual 518
|
||||
}
|
||||
|
||||
"resolve vehicle targets (with shields)" in {
|
||||
val vehicle = Vehicle(DamageModelTests.vehicle)
|
||||
vehicle.Shields = 10
|
||||
vehicle.Health mustEqual 650
|
||||
vehicle.Shields mustEqual 10
|
||||
|
||||
val resprojectile = ResolvedProjectile(
|
||||
ProjectileResolution.Hit,
|
||||
projectile,
|
||||
SourceEntry(vehicle),
|
||||
vehicle.DamageModel,
|
||||
Vector3.Zero
|
||||
)
|
||||
val func: Any => ResolvedProjectile = resprojectile.damage_model.Calculate(resprojectile)
|
||||
|
||||
func(vehicle)
|
||||
vehicle.Health mustEqual 528
|
||||
vehicle.Shields mustEqual 0
|
||||
}
|
||||
|
||||
"resolve vehicle targets (losing shields)" in {
|
||||
val vehicle = Vehicle(DamageModelTests.vehicle)
|
||||
vehicle.Shields = 10
|
||||
vehicle.Health mustEqual 650
|
||||
vehicle.Shields mustEqual 10
|
||||
|
||||
val resprojectile = ResolvedProjectile(
|
||||
ProjectileResolution.Hit,
|
||||
projectile,
|
||||
SourceEntry(vehicle),
|
||||
vehicle.DamageModel,
|
||||
Vector3.Zero
|
||||
)
|
||||
val func: Any => ResolvedProjectile = resprojectile.damage_model.Calculate(resprojectile)
|
||||
|
||||
func(vehicle)
|
||||
vehicle.Health mustEqual 528
|
||||
vehicle.Shields mustEqual 0
|
||||
func(vehicle)
|
||||
vehicle.Health mustEqual 396
|
||||
vehicle.Shields mustEqual 0
|
||||
}
|
||||
|
||||
"resolve vehicle targets in a specific way" in {
|
||||
val vehicle = Vehicle(DamageModelTests.vehicle)
|
||||
vehicle.Health mustEqual 650
|
||||
|
||||
val resprojectile = ResolvedProjectile(
|
||||
ProjectileResolution.Hit,
|
||||
projectile,
|
||||
SourceEntry(vehicle),
|
||||
vehicle.DamageModel,
|
||||
Vector3.Zero
|
||||
)
|
||||
val func: Any => ResolvedProjectile =
|
||||
resprojectile.damage_model.Calculate(resprojectile, ProjectileResolution.Splash)
|
||||
|
||||
func(vehicle)
|
||||
vehicle.Health mustEqual 518
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object DamageModelTests {
|
||||
final val projectile = new ProjectileDefinition(Projectiles.heavy_grenade_projectile.id) {
|
||||
Damage0 = 50
|
||||
Damage1 = 82
|
||||
Damage2 = 82
|
||||
Damage3 = 75
|
||||
Damage4 = 66
|
||||
DamageAtEdge = 0.1f
|
||||
DamageRadius = 5f
|
||||
DegradeMultiplier = 0.5f
|
||||
LashRadius = 5f
|
||||
ProjectileDamageType = DamageType.Splash
|
||||
InitialVelocity = 75
|
||||
Lifespan = 5f
|
||||
ProjectileDefinition.CalculateDerivedFields(pdef = this)
|
||||
Modifiers = DamageModifiers.RadialDegrade
|
||||
}
|
||||
|
||||
final val vehicle = new VehicleDefinition(ObjectClass.fury) {
|
||||
MaxHealth = 650
|
||||
Damageable = true
|
||||
Repairable = true
|
||||
RepairIfDestroyed = false
|
||||
MaxShields = 130 + 1
|
||||
}
|
||||
}
|
||||
1747
src/test/scala/objects/DamageableTest.scala
Normal file
1747
src/test/scala/objects/DamageableTest.scala
Normal file
File diff suppressed because it is too large
Load diff
49
src/test/scala/objects/DefaultTest.scala
Normal file
49
src/test/scala/objects/DefaultTest.scala
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// Copyright (c) 2020 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.DeadLetter
|
||||
import akka.testkit.TestProbe
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.Default
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
class DefaultTest extends Specification {
|
||||
"Default.Cancellable" should {
|
||||
"always act like it can be cancelled successfully" in {
|
||||
Default.Cancellable.cancel() mustEqual true
|
||||
}
|
||||
|
||||
"always act like it was cancelled successfully" in {
|
||||
Default.Cancellable.isCancelled mustEqual true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DefaultActorStartedTest extends ActorTest {
|
||||
"Default.Actor" should {
|
||||
"send messages to deadLetters" in {
|
||||
//after being started
|
||||
Default(system)
|
||||
val probe = new TestProbe(system)
|
||||
system.eventStream.subscribe(probe.ref, classOf[DeadLetter])
|
||||
Default.Actor ! "hello world"
|
||||
val msg1 = probe.receiveOne(250 milliseconds)
|
||||
assert(msg1.isInstanceOf[DeadLetter])
|
||||
assert(msg1.asInstanceOf[DeadLetter].message equals "hello world")
|
||||
|
||||
//if it was stopped
|
||||
system.stop(Default.Actor)
|
||||
Default.Actor ! "hello world"
|
||||
val msg2 = probe.receiveOne(250 milliseconds)
|
||||
assert(msg2.isInstanceOf[DeadLetter])
|
||||
assert(msg2.asInstanceOf[DeadLetter].message equals "hello world")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object DefaultActorTest {
|
||||
//due to being a singleton, the original original value of the Default.Actor is cached here
|
||||
val Original = Default.Actor
|
||||
}
|
||||
817
src/test/scala/objects/DeployableTest.scala
Normal file
817
src/test/scala/objects/DeployableTest.scala
Normal file
|
|
@ -0,0 +1,817 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.{Actor, Props}
|
||||
import akka.testkit.TestProbe
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.ballistics._
|
||||
import net.psforever.objects.ce.DeployedItem
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
import net.psforever.objects.guid.source.LimitedNumberSource
|
||||
import net.psforever.objects.serverobject.mount.Mountable
|
||||
import net.psforever.objects.vital.Vitality
|
||||
import net.psforever.objects.zones.{Zone, ZoneMap}
|
||||
import net.psforever.objects.{TurretDeployable, _}
|
||||
import net.psforever.packet.game.{DeployableIcon, DeployableInfo, DeploymentAction}
|
||||
import net.psforever.types._
|
||||
import org.specs2.mutable.Specification
|
||||
import net.psforever.services.{RemoverActor, Service}
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||
import net.psforever.services.support.SupportActor
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
class DeployableTest extends Specification {
|
||||
"Deployable" should {
|
||||
"know its owner by GUID" in {
|
||||
val obj = new ExplosiveDeployable(GlobalDefinitions.he_mine)
|
||||
obj.Owner.isEmpty mustEqual true
|
||||
obj.Owner = PlanetSideGUID(10)
|
||||
obj.Owner.contains(PlanetSideGUID(10)) mustEqual true
|
||||
}
|
||||
|
||||
"know its owner by GUID" in {
|
||||
val obj = new ExplosiveDeployable(GlobalDefinitions.he_mine)
|
||||
obj.OwnerName.isEmpty mustEqual true
|
||||
obj.OwnerName = "TestCharacter"
|
||||
obj.OwnerName.contains("TestCharacter") mustEqual true
|
||||
}
|
||||
|
||||
"know its faction allegiance" in {
|
||||
val obj = new ExplosiveDeployable(GlobalDefinitions.he_mine)
|
||||
obj.Faction mustEqual PlanetSideEmpire.NEUTRAL
|
||||
obj.Faction = PlanetSideEmpire.TR
|
||||
obj.Faction mustEqual PlanetSideEmpire.TR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SensorDeployableTest extends Specification {
|
||||
"SensorDeployable" should {
|
||||
"construct" in {
|
||||
new SensorDeployable(GlobalDefinitions.motionalarmsensor)
|
||||
ok
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ExplosiveDeployableTest extends Specification {
|
||||
"ExplosiveDeployable" should {
|
||||
"construct" in {
|
||||
val obj = new ExplosiveDeployable(GlobalDefinitions.he_mine)
|
||||
obj.Destroyed mustEqual false
|
||||
}
|
||||
|
||||
"explode" in {
|
||||
val obj = new ExplosiveDeployable(GlobalDefinitions.he_mine)
|
||||
obj.Destroyed mustEqual false
|
||||
obj.Destroyed = true
|
||||
obj.Destroyed mustEqual true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BoomerDeployableTest extends Specification {
|
||||
"BoomerDeployable" should {
|
||||
"construct" in {
|
||||
val obj = new BoomerDeployable(GlobalDefinitions.boomer)
|
||||
obj.Destroyed mustEqual false
|
||||
obj.Trigger.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"explode" in {
|
||||
val obj = new BoomerDeployable(GlobalDefinitions.boomer)
|
||||
obj.Destroyed mustEqual false
|
||||
obj.Destroyed = true
|
||||
obj.Destroyed mustEqual true
|
||||
}
|
||||
|
||||
"manage its trigger" in {
|
||||
val obj = new BoomerDeployable(GlobalDefinitions.boomer)
|
||||
obj.Trigger.isEmpty mustEqual true
|
||||
|
||||
val trigger = new BoomerTrigger
|
||||
obj.Trigger = trigger
|
||||
obj.Trigger.contains(trigger) mustEqual true
|
||||
|
||||
obj.Trigger = None
|
||||
obj.Trigger.isEmpty mustEqual true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TrapDeployableTest extends Specification {
|
||||
"SensorDeployable" should {
|
||||
"construct" in {
|
||||
val obj = new TrapDeployable(GlobalDefinitions.tank_traps)
|
||||
obj.Health mustEqual GlobalDefinitions.tank_traps.MaxHealth
|
||||
}
|
||||
|
||||
"update health values" in {
|
||||
val obj = new TrapDeployable(GlobalDefinitions.tank_traps)
|
||||
obj.Health mustEqual GlobalDefinitions.tank_traps.MaxHealth
|
||||
obj.Health = 0
|
||||
obj.Health mustEqual 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TurretDeployableTest extends Specification {
|
||||
"TurretDeployable" should {
|
||||
"define (valid turret objects)" in {
|
||||
List(
|
||||
DeployedItem.spitfire_turret.id,
|
||||
DeployedItem.spitfire_cloaked.id,
|
||||
DeployedItem.spitfire_aa.id,
|
||||
DeployedItem.portable_manned_turret.id,
|
||||
DeployedItem.portable_manned_turret_tr.id,
|
||||
DeployedItem.portable_manned_turret_nc.id,
|
||||
DeployedItem.portable_manned_turret_vs.id
|
||||
).foreach(id => {
|
||||
try { new TurretDeployableDefinition(id) }
|
||||
catch { case _: Exception => ko }
|
||||
})
|
||||
ok
|
||||
}
|
||||
|
||||
"define (invalid object)" in {
|
||||
new TurretDeployableDefinition(5) must throwA[NoSuchElementException] //wrong object id altogether
|
||||
}
|
||||
|
||||
"construct" in {
|
||||
val obj = new TurretDeployable(GlobalDefinitions.spitfire_turret)
|
||||
obj.Health mustEqual obj.MaxHealth
|
||||
}
|
||||
|
||||
"update health values" in {
|
||||
val obj = new TurretDeployable(GlobalDefinitions.spitfire_turret)
|
||||
obj.Health mustEqual GlobalDefinitions.spitfire_turret.MaxHealth
|
||||
obj.Health = 0
|
||||
obj.Health mustEqual 0
|
||||
}
|
||||
|
||||
"may have mount point" in {
|
||||
new TurretDeployable(GlobalDefinitions.spitfire_turret).MountPoints mustEqual Map()
|
||||
new TurretDeployable(GlobalDefinitions.portable_manned_turret_vs).MountPoints mustEqual Map(1 -> 0, 2 -> 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DeployableMake extends Specification {
|
||||
"Deployables.Make" should {
|
||||
"construct a boomer" in {
|
||||
val func = Deployables.Make(DeployedItem.boomer)
|
||||
func() match {
|
||||
case _: BoomerDeployable => ok
|
||||
case _ => ko
|
||||
}
|
||||
}
|
||||
|
||||
"construct an he mine" in {
|
||||
val func = Deployables.Make(DeployedItem.he_mine)
|
||||
func() match {
|
||||
case obj: ExplosiveDeployable if obj.Definition == GlobalDefinitions.he_mine => ok
|
||||
case _ => ko
|
||||
}
|
||||
}
|
||||
|
||||
"construct a disruptor mine" in {
|
||||
val func = Deployables.Make(DeployedItem.jammer_mine)
|
||||
func() match {
|
||||
case obj: ExplosiveDeployable if obj.Definition == GlobalDefinitions.jammer_mine => ok
|
||||
case _ => ko
|
||||
}
|
||||
}
|
||||
|
||||
"construct a spitfire turret" in {
|
||||
val func = Deployables.Make(DeployedItem.spitfire_turret)
|
||||
func() match {
|
||||
case obj: TurretDeployable if obj.Definition == GlobalDefinitions.spitfire_turret => ok
|
||||
case _ => ko
|
||||
}
|
||||
}
|
||||
|
||||
"construct a shadow turret" in {
|
||||
val func = Deployables.Make(DeployedItem.spitfire_cloaked)
|
||||
func() match {
|
||||
case obj: TurretDeployable if obj.Definition == GlobalDefinitions.spitfire_cloaked => ok
|
||||
case _ => ko
|
||||
}
|
||||
}
|
||||
|
||||
"construct a cerebus turret" in {
|
||||
val func = Deployables.Make(DeployedItem.spitfire_aa)
|
||||
func() match {
|
||||
case obj: TurretDeployable if obj.Definition == GlobalDefinitions.spitfire_aa => ok
|
||||
case _ => ko
|
||||
}
|
||||
}
|
||||
|
||||
"construct a motion sensor" in {
|
||||
val func = Deployables.Make(DeployedItem.motionalarmsensor)
|
||||
func() match {
|
||||
case obj: SensorDeployable if obj.Definition == GlobalDefinitions.motionalarmsensor => ok
|
||||
case _ => ko
|
||||
}
|
||||
}
|
||||
|
||||
"construct a sensor disruptor" in {
|
||||
val func = Deployables.Make(DeployedItem.sensor_shield)
|
||||
func() match {
|
||||
case obj: SensorDeployable if obj.Definition == GlobalDefinitions.sensor_shield => ok
|
||||
case _ => ko
|
||||
}
|
||||
}
|
||||
|
||||
"construct three metal i-beams so huge that a driver must be blind to drive into them but does anyway" in {
|
||||
val func = Deployables.Make(DeployedItem.tank_traps)
|
||||
func() match {
|
||||
case obj: TrapDeployable if obj.Definition == GlobalDefinitions.tank_traps => ok
|
||||
case _ => ko
|
||||
}
|
||||
}
|
||||
|
||||
"construct a generic field turret" in {
|
||||
val func = Deployables.Make(DeployedItem.portable_manned_turret)
|
||||
func() match {
|
||||
case obj: TurretDeployable if obj.Definition == GlobalDefinitions.portable_manned_turret => ok
|
||||
case _ => ko
|
||||
}
|
||||
}
|
||||
|
||||
"construct an avenger turret" in {
|
||||
val func = Deployables.Make(DeployedItem.portable_manned_turret_tr)
|
||||
func() match {
|
||||
case obj: TurretDeployable if obj.Definition == GlobalDefinitions.portable_manned_turret_tr => ok
|
||||
case _ => ko
|
||||
}
|
||||
}
|
||||
|
||||
"construct an aegis shield generator" in {
|
||||
val func = Deployables.Make(DeployedItem.deployable_shield_generator)
|
||||
func() match {
|
||||
case obj: ShieldGeneratorDeployable if obj.Definition == GlobalDefinitions.deployable_shield_generator => ok
|
||||
case _ => ko
|
||||
}
|
||||
}
|
||||
|
||||
"construct a telepad" in {
|
||||
val func = Deployables.Make(DeployedItem.router_telepad_deployable)
|
||||
func() match {
|
||||
case obj: TelepadDeployable if obj.Definition == GlobalDefinitions.router_telepad_deployable => ok
|
||||
case _ => ko
|
||||
}
|
||||
}
|
||||
|
||||
"construct an osprey turret" in {
|
||||
val func = Deployables.Make(DeployedItem.portable_manned_turret_nc)
|
||||
func() match {
|
||||
case obj: TurretDeployable if obj.Definition == GlobalDefinitions.portable_manned_turret_nc => ok
|
||||
case _ => ko
|
||||
}
|
||||
}
|
||||
|
||||
"construct an orion turret" in {
|
||||
val func = Deployables.Make(DeployedItem.portable_manned_turret_vs)
|
||||
func() match {
|
||||
case obj: TurretDeployable if obj.Definition == GlobalDefinitions.portable_manned_turret_vs => ok
|
||||
case _ => ko
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ShieldGeneratorDeployableTest extends Specification {
|
||||
"ShieldGeneratorDeployable" should {
|
||||
"construct" in {
|
||||
val obj = new ShieldGeneratorDeployable(GlobalDefinitions.deployable_shield_generator)
|
||||
obj.Health mustEqual obj.MaxHealth
|
||||
}
|
||||
|
||||
"update health values" in {
|
||||
val obj = new ShieldGeneratorDeployable(GlobalDefinitions.deployable_shield_generator)
|
||||
obj.Health mustEqual GlobalDefinitions.deployable_shield_generator.MaxHealth
|
||||
obj.Health = 0
|
||||
obj.Health mustEqual 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ExplosiveDeployableJammerTest extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(10))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
val activityProbe = TestProbe()
|
||||
val avatarProbe = TestProbe()
|
||||
val localProbe = TestProbe()
|
||||
zone.Activity = activityProbe.ref
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
zone.LocalEvents = localProbe.ref
|
||||
|
||||
val j_mine = Deployables.Make(DeployedItem.jammer_mine)().asInstanceOf[ExplosiveDeployable] //guid=1
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=3
|
||||
player1.Spawn()
|
||||
val player2 =
|
||||
Player(Avatar(0, "TestCharacter2", PlanetSideEmpire.NC, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=4
|
||||
player2.Spawn()
|
||||
val weapon = Tool(GlobalDefinitions.jammer_grenade) //guid=5
|
||||
guid.register(j_mine, 1)
|
||||
guid.register(player1, 3)
|
||||
guid.register(player2, 4)
|
||||
guid.register(weapon, 5)
|
||||
j_mine.Zone = zone
|
||||
j_mine.Owner = player2
|
||||
j_mine.OwnerName = player2.Name
|
||||
j_mine.Faction = PlanetSideEmpire.NC
|
||||
j_mine.Actor = system.actorOf(Props(classOf[ExplosiveDeployableControl], j_mine), "j-mine-control")
|
||||
|
||||
val jMineSource = SourceEntry(j_mine)
|
||||
val pSource = PlayerSource(player1)
|
||||
val projectile = weapon.Projectile
|
||||
val resolved = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
Projectile(projectile, weapon.Definition, weapon.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
|
||||
jMineSource,
|
||||
j_mine.DamageModel,
|
||||
Vector3(1, 0, 0)
|
||||
)
|
||||
val applyDamageToJ = resolved.damage_model.Calculate(resolved)
|
||||
|
||||
"ExplosiveDeployable" should {
|
||||
"handle being jammered appropriately (no detonation)" in {
|
||||
assert(!j_mine.Destroyed)
|
||||
|
||||
j_mine.Actor ! Vitality.Damage(applyDamageToJ)
|
||||
val msg_local = localProbe.receiveN(4, 200 milliseconds)
|
||||
val msg_avatar = avatarProbe.receiveOne(200 milliseconds)
|
||||
activityProbe.expectNoMessage(200 milliseconds)
|
||||
assert(
|
||||
msg_local.head match {
|
||||
case LocalServiceMessage("TestCharacter2", LocalAction.AlertDestroyDeployable(PlanetSideGUID(0), target)) =>
|
||||
target eq j_mine
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_local(1) match {
|
||||
case LocalServiceMessage(
|
||||
"NC",
|
||||
LocalAction.DeployableMapIcon(
|
||||
PlanetSideGUID(0),
|
||||
DeploymentAction.Dismiss,
|
||||
DeployableInfo(PlanetSideGUID(1), DeployableIcon.DisruptorMine, _, PlanetSideGUID(0))
|
||||
)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_local(2) match {
|
||||
case LocalServiceMessage.Deployables(SupportActor.ClearSpecific(List(target), _zone)) =>
|
||||
(target eq j_mine) && (_zone eq zone)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_local(3) match {
|
||||
case LocalServiceMessage.Deployables(RemoverActor.AddTask(target, _zone, _)) =>
|
||||
(target eq j_mine) && (_zone eq zone)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar match {
|
||||
case AvatarServiceMessage("test", AvatarAction.Destroy(PlanetSideGUID(1), _, Service.defaultPlayerGUID, _)) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(j_mine.Destroyed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ExplosiveDeployableJammerExplodeTest extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(10))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
val activityProbe = TestProbe()
|
||||
val avatarProbe = TestProbe()
|
||||
val localProbe = TestProbe()
|
||||
zone.Activity = activityProbe.ref
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
zone.LocalEvents = localProbe.ref
|
||||
|
||||
val h_mine = Deployables.Make(DeployedItem.he_mine)().asInstanceOf[ExplosiveDeployable] //guid=2
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=3
|
||||
player1.Spawn()
|
||||
val player2 =
|
||||
Player(Avatar(0, "TestCharacter2", PlanetSideEmpire.NC, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=4
|
||||
player2.Spawn()
|
||||
val weapon = Tool(GlobalDefinitions.jammer_grenade) //guid=5
|
||||
guid.register(h_mine, 2)
|
||||
guid.register(player1, 3)
|
||||
guid.register(player2, 4)
|
||||
guid.register(weapon, 5)
|
||||
h_mine.Zone = zone
|
||||
h_mine.Owner = player2
|
||||
h_mine.OwnerName = player2.Name
|
||||
h_mine.Faction = PlanetSideEmpire.NC
|
||||
h_mine.Actor = system.actorOf(Props(classOf[ExplosiveDeployableControl], h_mine), "h-mine-control")
|
||||
|
||||
val hMineSource = SourceEntry(h_mine)
|
||||
val pSource = PlayerSource(player1)
|
||||
val projectile = weapon.Projectile
|
||||
val resolved = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
Projectile(projectile, weapon.Definition, weapon.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
|
||||
hMineSource,
|
||||
h_mine.DamageModel,
|
||||
Vector3(1, 0, 0)
|
||||
)
|
||||
val applyDamageToH = resolved.damage_model.Calculate(resolved)
|
||||
|
||||
"ExplosiveDeployable" should {
|
||||
"handle being jammered appropriately (detonation)" in {
|
||||
assert(!h_mine.Destroyed)
|
||||
|
||||
h_mine.Actor ! Vitality.Damage(applyDamageToH)
|
||||
val msg_local = localProbe.receiveN(5, 200 milliseconds)
|
||||
val msg_avatar = avatarProbe.receiveOne(200 milliseconds)
|
||||
val msg_activity = activityProbe.receiveOne(200 milliseconds)
|
||||
assert(
|
||||
msg_local.head match {
|
||||
case LocalServiceMessage("test", LocalAction.Detonate(PlanetSideGUID(2), target)) => target eq h_mine
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_local(1) match {
|
||||
case LocalServiceMessage("TestCharacter2", LocalAction.AlertDestroyDeployable(PlanetSideGUID(0), target)) =>
|
||||
target eq h_mine
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_local(2) match {
|
||||
case LocalServiceMessage(
|
||||
"NC",
|
||||
LocalAction.DeployableMapIcon(
|
||||
PlanetSideGUID(0),
|
||||
DeploymentAction.Dismiss,
|
||||
DeployableInfo(PlanetSideGUID(2), DeployableIcon.HEMine, _, PlanetSideGUID(0))
|
||||
)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_local(3) match {
|
||||
case LocalServiceMessage.Deployables(SupportActor.ClearSpecific(List(target), _zone)) =>
|
||||
(target eq h_mine) && (_zone eq zone)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_local(4) match {
|
||||
case LocalServiceMessage.Deployables(RemoverActor.AddTask(target, _zone, _)) =>
|
||||
(target eq h_mine) && (_zone eq zone)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar match {
|
||||
case AvatarServiceMessage("test", AvatarAction.Destroy(PlanetSideGUID(2), _, Service.defaultPlayerGUID, _)) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_activity match {
|
||||
case Zone.HotSpot.Activity(target, attacker, _) => (target eq hMineSource) && (attacker eq pSource)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(h_mine.Destroyed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ExplosiveDeployableDestructionTest extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(10))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
val activityProbe = TestProbe()
|
||||
val avatarProbe = TestProbe()
|
||||
val localProbe = TestProbe()
|
||||
zone.Activity = activityProbe.ref
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
zone.LocalEvents = localProbe.ref
|
||||
|
||||
val h_mine = Deployables.Make(DeployedItem.he_mine)().asInstanceOf[ExplosiveDeployable] //guid=2
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=3
|
||||
player1.Spawn()
|
||||
val player2 =
|
||||
Player(Avatar(0, "TestCharacter2", PlanetSideEmpire.NC, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=4
|
||||
player2.Spawn()
|
||||
val weapon = Tool(GlobalDefinitions.suppressor) //guid=5
|
||||
guid.register(h_mine, 2)
|
||||
guid.register(player1, 3)
|
||||
guid.register(player2, 4)
|
||||
guid.register(weapon, 5)
|
||||
h_mine.Zone = zone
|
||||
h_mine.Owner = player2
|
||||
h_mine.OwnerName = player2.Name
|
||||
h_mine.Faction = PlanetSideEmpire.NC
|
||||
h_mine.Actor = system.actorOf(Props(classOf[ExplosiveDeployableControl], h_mine), "h-mine-control")
|
||||
|
||||
val hMineSource = SourceEntry(h_mine)
|
||||
val pSource = PlayerSource(player1)
|
||||
val projectile = weapon.Projectile
|
||||
val resolved = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
Projectile(projectile, weapon.Definition, weapon.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
|
||||
hMineSource,
|
||||
h_mine.DamageModel,
|
||||
Vector3(1, 0, 0)
|
||||
)
|
||||
val applyDamageTo = resolved.damage_model.Calculate(resolved)
|
||||
|
||||
"ExplosiveDeployable" should {
|
||||
"handle being destroyed" in {
|
||||
h_mine.Health = h_mine.Definition.DamageDestroysAt + 1
|
||||
assert(h_mine.Health > h_mine.Definition.DamageDestroysAt)
|
||||
assert(!h_mine.Destroyed)
|
||||
|
||||
h_mine.Actor ! Vitality.Damage(applyDamageTo)
|
||||
val msg_local = localProbe.receiveN(5, 200 milliseconds)
|
||||
val msg_avatar = avatarProbe.receiveOne(200 milliseconds)
|
||||
activityProbe.expectNoMessage(200 milliseconds)
|
||||
assert(
|
||||
msg_local.head match {
|
||||
case LocalServiceMessage("TestCharacter2", LocalAction.AlertDestroyDeployable(PlanetSideGUID(0), target)) =>
|
||||
target eq h_mine
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_local(1) match {
|
||||
case LocalServiceMessage(
|
||||
"NC",
|
||||
LocalAction.DeployableMapIcon(
|
||||
PlanetSideGUID(0),
|
||||
DeploymentAction.Dismiss,
|
||||
DeployableInfo(PlanetSideGUID(2), DeployableIcon.HEMine, _, PlanetSideGUID(0))
|
||||
)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_local(2) match {
|
||||
case LocalServiceMessage.Deployables(SupportActor.ClearSpecific(List(target), _zone)) =>
|
||||
(target eq h_mine) && (_zone eq zone)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_local(3) match {
|
||||
case LocalServiceMessage.Deployables(RemoverActor.AddTask(target, _zone, _)) =>
|
||||
(target eq h_mine) && (_zone eq zone)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_local(4) match {
|
||||
case LocalServiceMessage("test", LocalAction.TriggerEffect(_, "detonate_damaged_mine", PlanetSideGUID(2))) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar match {
|
||||
case AvatarServiceMessage("test", AvatarAction.Destroy(PlanetSideGUID(2), _, Service.defaultPlayerGUID, _)) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(h_mine.Health <= h_mine.Definition.DamageDestroysAt)
|
||||
assert(h_mine.Destroyed)
|
||||
}
|
||||
}
|
||||
}
|
||||
class TurretControlConstructTest extends ActorTest {
|
||||
"TurretControl" should {
|
||||
"construct" in {
|
||||
val obj = new TurretDeployable(GlobalDefinitions.spitfire_turret)
|
||||
system.actorOf(Props(classOf[TurretControl], obj), s"${obj.Definition.Name}_test")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TurretControlInitializeTest extends ActorTest {
|
||||
"TurretControl" should {
|
||||
"initialize" in {
|
||||
val obj = new TurretDeployable(GlobalDefinitions.spitfire_turret)
|
||||
obj.GUID = PlanetSideGUID(1)
|
||||
assert(obj.Actor == Default.Actor)
|
||||
val init = system.actorOf(Props(classOf[DeployableTest.TurretInitializer], obj), "init_turret_test")
|
||||
init ! "initialize"
|
||||
expectNoMessage(200 milliseconds)
|
||||
assert(obj.Actor != Default.Actor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TurretControlUninitializeTest extends ActorTest {
|
||||
"TurretControl" should {
|
||||
"uninitialize" in {
|
||||
val obj = new TurretDeployable(GlobalDefinitions.spitfire_turret)
|
||||
val init = system.actorOf(Props(classOf[DeployableTest.TurretInitializer], obj), "init_turret_test")
|
||||
obj.GUID = PlanetSideGUID(1)
|
||||
init ! "initialize"
|
||||
expectNoMessage(200 milliseconds)
|
||||
assert(obj.Actor != Default.Actor)
|
||||
|
||||
init ! "uninitialize"
|
||||
expectNoMessage(200 milliseconds)
|
||||
assert(obj.Actor == Default.Actor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TurretControlMountTest extends ActorTest {
|
||||
"TurretControl" should {
|
||||
"control mounting" in {
|
||||
val obj = new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) { GUID = PlanetSideGUID(1) }
|
||||
obj.Faction = PlanetSideEmpire.TR
|
||||
obj.Actor = system.actorOf(Props(classOf[TurretControl], obj), s"${obj.Definition.Name}_test")
|
||||
|
||||
assert(obj.Seats(0).Occupant.isEmpty)
|
||||
val player1 = Player(Avatar(0, "test1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
obj.Actor ! Mountable.TryMount(player1, 0)
|
||||
val reply1a = receiveOne(200 milliseconds)
|
||||
assert(reply1a.isInstanceOf[Mountable.MountMessages])
|
||||
val reply1b = reply1a.asInstanceOf[Mountable.MountMessages]
|
||||
assert(reply1b.player == player1)
|
||||
assert(reply1b.response.isInstanceOf[Mountable.CanMount])
|
||||
assert(obj.Seats(0).Occupant.contains(player1))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TurretControlBlockMountTest extends ActorTest {
|
||||
"TurretControl" should {
|
||||
"block mounting by others if already mounted by someone" in {
|
||||
val obj = new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) { GUID = PlanetSideGUID(1) }
|
||||
obj.Faction = PlanetSideEmpire.TR
|
||||
obj.Actor = system.actorOf(Props(classOf[TurretControl], obj), s"${obj.Definition.Name}_test")
|
||||
|
||||
assert(obj.Seats(0).Occupant.isEmpty)
|
||||
val player1 = Player(Avatar(0, "test1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
obj.Actor ! Mountable.TryMount(player1, 0)
|
||||
val reply1a = receiveOne(200 milliseconds)
|
||||
assert(reply1a.isInstanceOf[Mountable.MountMessages])
|
||||
val reply1b = reply1a.asInstanceOf[Mountable.MountMessages]
|
||||
assert(reply1b.player == player1)
|
||||
assert(reply1b.response.isInstanceOf[Mountable.CanMount])
|
||||
assert(obj.Seats(0).Occupant.contains(player1))
|
||||
|
||||
val player2 = Player(Avatar(1, "test2", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
obj.Actor ! Mountable.TryMount(player2, 0)
|
||||
val reply2a = receiveOne(200 milliseconds)
|
||||
assert(reply2a.isInstanceOf[Mountable.MountMessages])
|
||||
val reply2b = reply2a.asInstanceOf[Mountable.MountMessages]
|
||||
assert(reply2b.player == player2)
|
||||
assert(reply2b.response.isInstanceOf[Mountable.CanNotMount])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TurretControlBlockBetrayalMountTest extends ActorTest {
|
||||
"TurretControl" should {
|
||||
"block mounting by players of another faction" in {
|
||||
val obj = new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) { GUID = PlanetSideGUID(1) }
|
||||
obj.Faction = PlanetSideEmpire.TR
|
||||
obj.Actor = system.actorOf(Props(classOf[TurretControl], obj), s"${obj.Definition.Name}_test")
|
||||
|
||||
assert(obj.Seats(0).Occupant.isEmpty)
|
||||
val player = Player(Avatar(0, "test", PlanetSideEmpire.VS, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
obj.Actor ! Mountable.TryMount(player, 0)
|
||||
val reply1a = receiveOne(200 milliseconds)
|
||||
assert(reply1a.isInstanceOf[Mountable.MountMessages])
|
||||
val reply1b = reply1a.asInstanceOf[Mountable.MountMessages]
|
||||
assert(reply1b.player == player)
|
||||
assert(reply1b.response.isInstanceOf[Mountable.CanNotMount])
|
||||
assert(obj.Seats(0).Occupant.isEmpty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TurretControlDismountTest extends ActorTest {
|
||||
"TurretControl" should {
|
||||
"control dismounting" in {
|
||||
val obj = new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) { GUID = PlanetSideGUID(1) }
|
||||
obj.Faction = PlanetSideEmpire.TR
|
||||
obj.Actor = system.actorOf(Props(classOf[TurretControl], obj), s"${obj.Definition.Name}_test")
|
||||
|
||||
assert(obj.Seats(0).Occupant.isEmpty)
|
||||
val player = Player(Avatar(0, "test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
obj.Actor ! Mountable.TryMount(player, 0)
|
||||
val reply1a = receiveOne(200 milliseconds)
|
||||
assert(reply1a.isInstanceOf[Mountable.MountMessages])
|
||||
val reply1b = reply1a.asInstanceOf[Mountable.MountMessages]
|
||||
assert(reply1b.player == player)
|
||||
assert(reply1b.response.isInstanceOf[Mountable.CanMount])
|
||||
assert(obj.Seats(0).Occupant.contains(player))
|
||||
|
||||
obj.Actor ! Mountable.TryDismount(player, 0)
|
||||
val reply2a = receiveOne(200 milliseconds)
|
||||
assert(reply2a.isInstanceOf[Mountable.MountMessages])
|
||||
val reply2b = reply2a.asInstanceOf[Mountable.MountMessages]
|
||||
assert(reply2b.player == player)
|
||||
assert(reply2b.response.isInstanceOf[Mountable.CanDismount])
|
||||
assert(obj.Seats(0).Occupant.isEmpty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TurretControlBetrayalMountTest extends ActorTest {
|
||||
"TurretControl" should {
|
||||
"allow all allegiances" in {
|
||||
val obj = new TurretDeployable(
|
||||
new TurretDeployableDefinition(685) { FactionLocked = false } //required (defaults to true)
|
||||
) { GUID = PlanetSideGUID(1) }
|
||||
obj.Faction = PlanetSideEmpire.TR
|
||||
obj.Actor = system.actorOf(Props(classOf[TurretControl], obj), s"${obj.Definition.Name}_test")
|
||||
|
||||
assert(obj.Seats(0).Occupant.isEmpty)
|
||||
val player = Player(Avatar(0, "test", PlanetSideEmpire.NC, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
assert(player.Faction != obj.Faction)
|
||||
obj.Actor ! Mountable.TryMount(player, 0)
|
||||
val reply1a = receiveOne(200 milliseconds)
|
||||
assert(reply1a.isInstanceOf[Mountable.MountMessages])
|
||||
val reply1b = reply1a.asInstanceOf[Mountable.MountMessages]
|
||||
assert(reply1b.player == player)
|
||||
assert(reply1b.response.isInstanceOf[Mountable.CanMount])
|
||||
assert(obj.Seats(0).Occupant.contains(player))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TelepadDeployableTest extends Specification {
|
||||
"Telepad" should {
|
||||
"construct" in {
|
||||
val obj = new Telepad(GlobalDefinitions.router_telepad)
|
||||
obj.Active mustEqual false
|
||||
obj.Router.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"activate and deactivate" in {
|
||||
val obj = new Telepad(GlobalDefinitions.router_telepad)
|
||||
obj.Active mustEqual false
|
||||
obj.Active = true
|
||||
obj.Active mustEqual true
|
||||
obj.Active = false
|
||||
obj.Active mustEqual false
|
||||
}
|
||||
|
||||
"keep track of a Router" in {
|
||||
val obj = new Telepad(GlobalDefinitions.router_telepad)
|
||||
obj.Router.isEmpty mustEqual true
|
||||
obj.Router = PlanetSideGUID(1)
|
||||
obj.Router.contains(PlanetSideGUID(1)) mustEqual true
|
||||
obj.Router = None
|
||||
obj.Router.isEmpty mustEqual true
|
||||
obj.Router = PlanetSideGUID(1)
|
||||
obj.Router.contains(PlanetSideGUID(1)) mustEqual true
|
||||
obj.Router = PlanetSideGUID(0)
|
||||
obj.Router.isEmpty mustEqual true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object DeployableTest {
|
||||
class TurretInitializer(obj: TurretDeployable) extends Actor {
|
||||
def receive: Receive = {
|
||||
case "initialize" =>
|
||||
obj.Definition.Initialize(obj, context)
|
||||
case "uninitialize" =>
|
||||
obj.Definition.Uninitialize(obj, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
1064
src/test/scala/objects/DeployableToolboxTest.scala
Normal file
1064
src/test/scala/objects/DeployableToolboxTest.scala
Normal file
File diff suppressed because it is too large
Load diff
268
src/test/scala/objects/DeploymentTest.scala
Normal file
268
src/test/scala/objects/DeploymentTest.scala
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.{Actor, ActorRef, ActorSystem, Props}
|
||||
import akka.testkit.TestProbe
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
import net.psforever.objects.{GlobalDefinitions, Vehicle}
|
||||
import net.psforever.objects.serverobject.deploy.{Deployment, DeploymentBehavior}
|
||||
import net.psforever.objects.zones.{Zone, ZoneMap}
|
||||
import net.psforever.types.{DriveState, PlanetSideEmpire, PlanetSideGUID, Vector3}
|
||||
import org.specs2.mutable.Specification
|
||||
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||
|
||||
import scala.concurrent.duration.Duration
|
||||
|
||||
class DeploymentTest extends Specification {
|
||||
"Deployment" should {
|
||||
"construct" in {
|
||||
val obj = new DeploymentTest.DeploymentObject()
|
||||
obj.DeploymentState mustEqual DriveState.Mobile
|
||||
obj.DeployTime mustEqual 0
|
||||
obj.UndeployTime mustEqual 0
|
||||
}
|
||||
|
||||
"change deployment state" in {
|
||||
val obj = new DeploymentTest.DeploymentObject()
|
||||
obj.DeploymentState mustEqual DriveState.Mobile
|
||||
|
||||
obj.DeploymentState = DriveState.Deployed
|
||||
obj.DeploymentState mustEqual DriveState.Deployed
|
||||
obj.DeploymentState = DriveState.Deploying
|
||||
obj.DeploymentState mustEqual DriveState.Deploying
|
||||
obj.DeploymentState = DriveState.Undeploying
|
||||
obj.DeploymentState mustEqual DriveState.Undeploying
|
||||
obj.DeploymentState = DriveState.State7
|
||||
obj.DeploymentState mustEqual DriveState.State7
|
||||
}
|
||||
|
||||
"have custom deployment time by object" in {
|
||||
val ams = Vehicle(GlobalDefinitions.ams)
|
||||
(ams.DeployTime == 0) mustEqual false //not default
|
||||
(ams.UndeployTime == 0) mustEqual false //not default
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DeploymentBehavior1Test extends ActorTest {
|
||||
"Deployment" should {
|
||||
"construct" in {
|
||||
val obj = DeploymentTest.SetUpAgent
|
||||
assert(obj.Actor != ActorRef.noSender)
|
||||
assert(obj.DeploymentState == DriveState.Mobile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DeploymentBehavior2Test extends ActorTest {
|
||||
"Deployment" should {
|
||||
"change following a deployment cycle using TryDeploymentChange" in {
|
||||
val obj = DeploymentTest.SetUpAgent
|
||||
val probe = new TestProbe(system)
|
||||
val eventsProbe = new TestProbe(system)
|
||||
obj.Zone.VehicleEvents = eventsProbe.ref
|
||||
assert(obj.DeploymentState == DriveState.Mobile)
|
||||
//to Deploying
|
||||
obj.Actor.tell(Deployment.TryDeploymentChange(DriveState.Deploying), probe.ref)
|
||||
val reply1a = probe.receiveOne(Duration.create(500, "ms"))
|
||||
assert(reply1a match {
|
||||
case Deployment.CanDeploy(_, DriveState.Deploying) => true
|
||||
case _ => false
|
||||
})
|
||||
val reply1b = eventsProbe.receiveOne(Duration.create(500, "ms"))
|
||||
assert(reply1b match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.DeployRequest(_, PlanetSideGUID(1), DriveState.Deploying, 0, false, Vector3.Zero)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
})
|
||||
//to Deployed
|
||||
val reply2 = eventsProbe.receiveOne(Duration.create(500, "ms"))
|
||||
assert(reply2 match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.DeployRequest(_, PlanetSideGUID(1), DriveState.Deployed, 0, false, Vector3.Zero)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
})
|
||||
assert(obj.DeploymentState == DriveState.Deployed)
|
||||
//to Undeploying
|
||||
obj.Actor.tell(Deployment.TryDeploymentChange(DriveState.Undeploying), probe.ref)
|
||||
val reply3a = probe.receiveOne(Duration.create(500, "ms"))
|
||||
assert(reply3a match {
|
||||
case Deployment.CanUndeploy(_, DriveState.Undeploying) => true
|
||||
case _ => false
|
||||
})
|
||||
val reply3b = eventsProbe.receiveOne(Duration.create(500, "ms"))
|
||||
assert(reply3b match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.DeployRequest(_, PlanetSideGUID(1), DriveState.Undeploying, 0, false, Vector3.Zero)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
})
|
||||
//to Mobile
|
||||
val reply4 = eventsProbe.receiveOne(Duration.create(500, "ms"))
|
||||
assert(reply4 match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.DeployRequest(_, PlanetSideGUID(1), DriveState.Mobile, 0, false, Vector3.Zero)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
})
|
||||
assert(obj.DeploymentState == DriveState.Mobile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DeploymentBehavior3Test extends ActorTest {
|
||||
"Deployment" should {
|
||||
"change following a deployment cycle using TryDeploy and TryUndeploy" in {
|
||||
val obj = DeploymentTest.SetUpAgent
|
||||
val probe = new TestProbe(system)
|
||||
val eventsProbe = new TestProbe(system)
|
||||
obj.Zone.VehicleEvents = eventsProbe.ref
|
||||
assert(obj.DeploymentState == DriveState.Mobile)
|
||||
//to Deploying
|
||||
obj.Actor.tell(Deployment.TryDeploy(DriveState.Deploying), probe.ref)
|
||||
val reply1a = probe.receiveOne(Duration.create(500, "ms"))
|
||||
assert(reply1a match {
|
||||
case Deployment.CanDeploy(_, DriveState.Deploying) => true
|
||||
case _ => false
|
||||
})
|
||||
val reply1b = eventsProbe.receiveOne(Duration.create(500, "ms"))
|
||||
assert(reply1b match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.DeployRequest(_, PlanetSideGUID(1), DriveState.Deploying, 0, false, Vector3.Zero)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
})
|
||||
//to Deployed
|
||||
val reply2 = eventsProbe.receiveOne(Duration.create(500, "ms"))
|
||||
assert(reply2 match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.DeployRequest(_, PlanetSideGUID(1), DriveState.Deployed, 0, false, Vector3.Zero)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
})
|
||||
assert(obj.DeploymentState == DriveState.Deployed)
|
||||
//to Undeploying
|
||||
obj.Actor.tell(Deployment.TryUndeploy(DriveState.Undeploying), probe.ref)
|
||||
val reply3a = probe.receiveOne(Duration.create(500, "ms"))
|
||||
assert(reply3a match {
|
||||
case Deployment.CanUndeploy(_, DriveState.Undeploying) => true
|
||||
case _ => false
|
||||
})
|
||||
val reply3b = eventsProbe.receiveOne(Duration.create(500, "ms"))
|
||||
assert(reply3b match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.DeployRequest(_, PlanetSideGUID(1), DriveState.Undeploying, 0, false, Vector3.Zero)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
})
|
||||
//to Mobile
|
||||
val reply4 = eventsProbe.receiveOne(Duration.create(500, "ms"))
|
||||
assert(reply4 match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.DeployRequest(_, PlanetSideGUID(1), DriveState.Mobile, 0, false, Vector3.Zero)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
})
|
||||
assert(obj.DeploymentState == DriveState.Mobile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DeploymentBehavior4Test extends ActorTest {
|
||||
"Deployment" should {
|
||||
"not deploy to an out of order state" in {
|
||||
val obj = DeploymentTest.SetUpAgent
|
||||
assert(obj.DeploymentState == DriveState.Mobile)
|
||||
|
||||
obj.Actor ! Deployment.TryDeploymentChange(DriveState.Deployed)
|
||||
val reply1 = receiveOne(Duration.create(100, "ms"))
|
||||
assert(reply1.isInstanceOf[Deployment.CanNotChangeDeployment])
|
||||
assert(reply1.asInstanceOf[Deployment.CanNotChangeDeployment].obj == obj)
|
||||
assert(reply1.asInstanceOf[Deployment.CanNotChangeDeployment].to_state == DriveState.Deployed)
|
||||
assert(obj.DeploymentState == DriveState.Mobile)
|
||||
|
||||
obj.Actor ! Deployment.TryDeploy(DriveState.Deployed)
|
||||
val reply2 = receiveOne(Duration.create(100, "ms"))
|
||||
assert(reply2.isInstanceOf[Deployment.CanNotChangeDeployment])
|
||||
assert(reply2.asInstanceOf[Deployment.CanNotChangeDeployment].obj == obj)
|
||||
assert(reply2.asInstanceOf[Deployment.CanNotChangeDeployment].to_state == DriveState.Deployed)
|
||||
assert(obj.DeploymentState == DriveState.Mobile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DeploymentBehavior5Test extends ActorTest {
|
||||
"Deployment" should {
|
||||
"not deploy to an undeploy state" in {
|
||||
val obj = DeploymentTest.SetUpAgent
|
||||
assert(obj.DeploymentState == DriveState.Mobile)
|
||||
obj.Actor ! Deployment.TryDeploymentChange(DriveState.Deploying)
|
||||
receiveOne(Duration.create(100, "ms")) //consume
|
||||
obj.Actor ! Deployment.TryDeploymentChange(DriveState.Deployed)
|
||||
receiveOne(Duration.create(100, "ms")) //consume
|
||||
assert(obj.DeploymentState == DriveState.Deployed)
|
||||
|
||||
obj.Actor ! Deployment.TryDeploy(DriveState.Undeploying)
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
assert(reply.isInstanceOf[Deployment.CanNotChangeDeployment])
|
||||
assert(reply.asInstanceOf[Deployment.CanNotChangeDeployment].obj == obj)
|
||||
assert(reply.asInstanceOf[Deployment.CanNotChangeDeployment].to_state == DriveState.Undeploying)
|
||||
assert(obj.DeploymentState == DriveState.Deployed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DeploymentBehavior6Test extends ActorTest {
|
||||
"Deployment" should {
|
||||
"not undeploy to a deploy state" in {
|
||||
val obj = DeploymentTest.SetUpAgent
|
||||
assert(obj.DeploymentState == DriveState.Mobile)
|
||||
|
||||
obj.Actor ! Deployment.TryUndeploy(DriveState.Deploying)
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
assert(reply.isInstanceOf[Deployment.CanNotChangeDeployment])
|
||||
assert(reply.asInstanceOf[Deployment.CanNotChangeDeployment].obj == obj)
|
||||
assert(reply.asInstanceOf[Deployment.CanNotChangeDeployment].to_state == DriveState.Deploying)
|
||||
assert(obj.DeploymentState == DriveState.Mobile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object DeploymentTest {
|
||||
class DeploymentObject extends PlanetSideServerObject with Deployment {
|
||||
def Faction: PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||
def Definition = null
|
||||
}
|
||||
|
||||
private class DeploymentControl(obj: Deployment.DeploymentObject) extends Actor with DeploymentBehavior {
|
||||
override def DeploymentObject = obj
|
||||
def receive = deployBehavior.orElse { case _ => }
|
||||
}
|
||||
|
||||
def SetUpAgent(implicit system: ActorSystem) = {
|
||||
val obj = new DeploymentObject()
|
||||
obj.GUID = PlanetSideGUID(1)
|
||||
obj.Zone = Zone("test", new ZoneMap("test"), 1)
|
||||
obj.Actor = system.actorOf(Props(classOf[DeploymentControl], obj), "test")
|
||||
obj
|
||||
}
|
||||
}
|
||||
140
src/test/scala/objects/DoorTest.scala
Normal file
140
src/test/scala/objects/DoorTest.scala
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.{ActorSystem, Props}
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
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.packet.game.UseItemMessage
|
||||
import net.psforever.types._
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
import scala.concurrent.duration.Duration
|
||||
|
||||
class DoorTest extends Specification {
|
||||
val player = Player(Avatar(0, "test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
|
||||
"Door" should {
|
||||
"construct" in {
|
||||
Door(GlobalDefinitions.door)
|
||||
ok
|
||||
}
|
||||
|
||||
"starts as closed (false)" in {
|
||||
val door = Door(GlobalDefinitions.door)
|
||||
door.Open mustEqual None
|
||||
door.isOpen mustEqual false
|
||||
}
|
||||
|
||||
"be opened and closed (1; manual)" in {
|
||||
val door = Door(GlobalDefinitions.door)
|
||||
door.isOpen mustEqual false
|
||||
door.Open mustEqual None
|
||||
|
||||
door.Open = Some(player)
|
||||
door.isOpen mustEqual true
|
||||
door.Open mustEqual Some(player)
|
||||
|
||||
door.Open = None
|
||||
door.isOpen mustEqual false
|
||||
door.Open mustEqual None
|
||||
}
|
||||
|
||||
"be opened and closed (2; toggle)" in {
|
||||
val msg = UseItemMessage(
|
||||
PlanetSideGUID(6585),
|
||||
PlanetSideGUID(0),
|
||||
PlanetSideGUID(372),
|
||||
4294967295L,
|
||||
false,
|
||||
Vector3(5.0f, 0.0f, 0.0f),
|
||||
Vector3(0.0f, 0.0f, 0.0f),
|
||||
11,
|
||||
25,
|
||||
0,
|
||||
364
|
||||
)
|
||||
val door = Door(GlobalDefinitions.door)
|
||||
door.Open mustEqual None
|
||||
door.Use(player, msg)
|
||||
door.Open mustEqual Some(player)
|
||||
door.Use(player, msg)
|
||||
door.Open mustEqual None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DoorControl1Test extends ActorTest {
|
||||
"DoorControl" should {
|
||||
"construct" in {
|
||||
val door = Door(GlobalDefinitions.door)
|
||||
door.Actor = system.actorOf(Props(classOf[DoorControl], door), "door")
|
||||
assert(door.Actor != Default.Actor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DoorControl2Test extends ActorTest {
|
||||
"DoorControl" should {
|
||||
"open on use" in {
|
||||
val (player, door) = DoorControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
val msg = UseItemMessage(
|
||||
PlanetSideGUID(1),
|
||||
PlanetSideGUID(0),
|
||||
PlanetSideGUID(2),
|
||||
0L,
|
||||
false,
|
||||
Vector3(0f, 0f, 0f),
|
||||
Vector3(0f, 0f, 0f),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0L
|
||||
) //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())
|
||||
assert(door.Open.isDefined)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DoorControl3Test extends ActorTest {
|
||||
"DoorControl" should {
|
||||
"do nothing if given garbage" in {
|
||||
val (_, door) = DoorControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
assert(door.Open.isEmpty)
|
||||
|
||||
door.Actor ! "trash"
|
||||
val reply = receiveOne(Duration.create(500, "ms"))
|
||||
assert(reply.isInstanceOf[Door.NoEvent])
|
||||
assert(door.Open.isEmpty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object DoorControlTest {
|
||||
def SetUpAgents(faction: PlanetSideEmpire.Value)(implicit system: ActorSystem): (Player, Door) = {
|
||||
val door = Door(GlobalDefinitions.door)
|
||||
door.Actor = system.actorOf(Props(classOf[DoorControl], door), "door")
|
||||
door.Owner = new Building(
|
||||
"Building",
|
||||
building_guid = 0,
|
||||
map_id = 0,
|
||||
Zone.Nowhere,
|
||||
StructureType.Building,
|
||||
GlobalDefinitions.building
|
||||
)
|
||||
door.Owner.Faction = faction
|
||||
(Player(Avatar(0, "test", faction, CharacterGender.Male, 0, CharacterVoice.Mute)), door)
|
||||
}
|
||||
}
|
||||
288
src/test/scala/objects/EntityTest.scala
Normal file
288
src/test/scala/objects/EntityTest.scala
Normal file
|
|
@ -0,0 +1,288 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects.PlanetSideGameObject
|
||||
import net.psforever.objects.definition.ObjectDefinition
|
||||
import net.psforever.objects.entity.{AssigningGUIDException, NoGUIDException}
|
||||
import net.psforever.types.{PlanetSideGUID, StalePlanetSideGUID, ValidPlanetSideGUID, Vector3}
|
||||
import org.specs2.mutable._
|
||||
|
||||
class EntityTest extends Specification {
|
||||
//both WorldEntity and IdentifiableEntity are components of PlanetSideGameObject
|
||||
private class EntityTestClass extends PlanetSideGameObject {
|
||||
def Definition: ObjectDefinition = new ObjectDefinition(0) {}
|
||||
}
|
||||
|
||||
"PlanetSideGUID" should {
|
||||
"construct as valid" in {
|
||||
ValidPlanetSideGUID(1).isInstanceOf[PlanetSideGUID] mustEqual true
|
||||
}
|
||||
|
||||
"construct as stale" in {
|
||||
StalePlanetSideGUID(1).isInstanceOf[PlanetSideGUID] mustEqual true
|
||||
}
|
||||
|
||||
"apply construct (as valid)" in {
|
||||
val guid = PlanetSideGUID(1)
|
||||
guid.isInstanceOf[PlanetSideGUID] mustEqual true
|
||||
guid.isInstanceOf[ValidPlanetSideGUID] mustEqual true
|
||||
guid.isInstanceOf[StalePlanetSideGUID] mustEqual false
|
||||
}
|
||||
|
||||
"valid and stale are equal by guid" in {
|
||||
//your linter will complain; let it
|
||||
ValidPlanetSideGUID(1) == StalePlanetSideGUID(1) mustEqual true
|
||||
ValidPlanetSideGUID(1) == StalePlanetSideGUID(2) mustEqual false
|
||||
}
|
||||
|
||||
"valid and stale are pattern-matchable" in {
|
||||
val guid1: PlanetSideGUID = ValidPlanetSideGUID(1)
|
||||
val guid2: PlanetSideGUID = StalePlanetSideGUID(1)
|
||||
def getGuid(o: PlanetSideGUID): PlanetSideGUID = o //distancing the proper type
|
||||
|
||||
getGuid(guid1) match {
|
||||
case ValidPlanetSideGUID(1) => ok
|
||||
case _ => ko
|
||||
}
|
||||
getGuid(guid2) match {
|
||||
case StalePlanetSideGUID(1) => ok
|
||||
case _ => ko
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"SimpleWorldEntity" should {
|
||||
"construct" in {
|
||||
new EntityTestClass()
|
||||
ok
|
||||
}
|
||||
|
||||
"initialize" in {
|
||||
val obj: EntityTestClass = new EntityTestClass()
|
||||
obj.Position mustEqual Vector3(0f, 0f, 0f)
|
||||
obj.Orientation mustEqual Vector3(0f, 0f, 0f)
|
||||
obj.Velocity.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"mutate and access" in {
|
||||
val obj: EntityTestClass = new EntityTestClass
|
||||
obj.Position = Vector3(1f, 1f, 1f)
|
||||
obj.Orientation = Vector3(2f, 2f, 2f)
|
||||
obj.Velocity = Vector3(3f, 3f, 3f)
|
||||
|
||||
obj.Position mustEqual Vector3(1f, 1f, 1f)
|
||||
obj.Orientation mustEqual Vector3(2f, 2f, 2f)
|
||||
obj.Velocity.contains(Vector3(3f, 3f, 3f)) mustEqual true
|
||||
}
|
||||
|
||||
"clamp Orientation" in {
|
||||
val obj: EntityTestClass = new EntityTestClass
|
||||
obj.Orientation = Vector3(-1f, 361f, -0f)
|
||||
obj.Orientation mustEqual Vector3(359f, 1f, 0f)
|
||||
}
|
||||
|
||||
"is moving (at all)" in {
|
||||
val obj: EntityTestClass = new EntityTestClass
|
||||
obj.Velocity.isEmpty mustEqual true
|
||||
obj.isMoving mustEqual false
|
||||
|
||||
obj.Velocity = Vector3.Zero
|
||||
obj.isMoving mustEqual false
|
||||
obj.Velocity = Vector3(1, 0, 0)
|
||||
obj.isMoving mustEqual true
|
||||
obj.Velocity = None
|
||||
obj.isMoving mustEqual false
|
||||
}
|
||||
|
||||
"is moving (Vector3 comparison)" in {
|
||||
val obj: EntityTestClass = new EntityTestClass
|
||||
val test1 = Vector3(1, 0, 0)
|
||||
val test2 = Vector3(2, 0, 0)
|
||||
obj.Velocity.isEmpty mustEqual true
|
||||
obj.isMoving mustEqual false
|
||||
obj.isMoving(test1) mustEqual false
|
||||
obj.isMoving(test2) mustEqual false
|
||||
|
||||
obj.Velocity = Vector3(1, 0, 0)
|
||||
obj.isMoving(test1) mustEqual true
|
||||
obj.isMoving(test2) mustEqual false
|
||||
obj.Velocity = Vector3(3, 0, 0)
|
||||
obj.isMoving(test1) mustEqual true
|
||||
obj.isMoving(test2) mustEqual true
|
||||
obj.Velocity = Vector3(1, 1, 0)
|
||||
obj.isMoving(test1) mustEqual true
|
||||
obj.isMoving(test2) mustEqual false
|
||||
}
|
||||
|
||||
"is moving (Float comparison)" in {
|
||||
val obj: EntityTestClass = new EntityTestClass
|
||||
obj.Velocity.isEmpty mustEqual true
|
||||
obj.isMoving mustEqual false
|
||||
obj.isMoving(1) mustEqual false
|
||||
obj.isMoving(2) mustEqual false
|
||||
obj.isMoving(4) mustEqual false
|
||||
|
||||
obj.Velocity = Vector3(1, 0, 0)
|
||||
obj.isMoving(1) mustEqual true
|
||||
obj.isMoving(2) mustEqual false
|
||||
obj.isMoving(4) mustEqual false
|
||||
obj.Velocity = Vector3(3, 0, 0)
|
||||
obj.isMoving(1) mustEqual true
|
||||
obj.isMoving(2) mustEqual true
|
||||
obj.isMoving(4) mustEqual true
|
||||
obj.Velocity = Vector3(1, 1, 1)
|
||||
obj.isMoving(1) mustEqual true
|
||||
obj.isMoving(2) mustEqual true
|
||||
obj.isMoving(4) mustEqual false
|
||||
}
|
||||
}
|
||||
|
||||
"IdentifiableEntity" should {
|
||||
"construct" in {
|
||||
new EntityTestClass()
|
||||
ok
|
||||
}
|
||||
|
||||
"error while not set" in {
|
||||
val obj: EntityTestClass = new EntityTestClass
|
||||
obj.GUID must throwA[NoGUIDException]
|
||||
}
|
||||
|
||||
"error if set to an invalid GUID before being set to a valid GUID" in {
|
||||
val obj: EntityTestClass = new EntityTestClass
|
||||
obj.GUID must throwA[NoGUIDException]
|
||||
try {
|
||||
obj.GUID = StalePlanetSideGUID(1)
|
||||
ko
|
||||
} catch {
|
||||
case AssigningGUIDException(_, _, _, _: StalePlanetSideGUID) => ok
|
||||
case _: Throwable => ko
|
||||
}
|
||||
}
|
||||
|
||||
"work after valid mutation" in {
|
||||
val obj: EntityTestClass = new EntityTestClass
|
||||
obj.GUID = PlanetSideGUID(1051)
|
||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||
}
|
||||
|
||||
"raise complaint about subsequent mutations using a valid GUID" in {
|
||||
val obj: EntityTestClass = new EntityTestClass
|
||||
obj.GUID = PlanetSideGUID(1051)
|
||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||
try {
|
||||
obj.GUID = ValidPlanetSideGUID(1)
|
||||
ko
|
||||
} catch {
|
||||
case AssigningGUIDException(_, _, _, ValidPlanetSideGUID(1)) => ok
|
||||
case _: Throwable => ko
|
||||
}
|
||||
}
|
||||
|
||||
"ignore subsequent mutations using an invalid GUID" in {
|
||||
val obj: EntityTestClass = new EntityTestClass
|
||||
obj.GUID = PlanetSideGUID(1051)
|
||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||
try {
|
||||
obj.GUID = StalePlanetSideGUID(1)
|
||||
ko
|
||||
} catch {
|
||||
case AssigningGUIDException(_, _, _, _: StalePlanetSideGUID) => ok
|
||||
case _: Throwable => ko
|
||||
}
|
||||
}
|
||||
|
||||
"invalidate does nothing by default" in {
|
||||
val obj: EntityTestClass = new EntityTestClass
|
||||
obj.Invalidate()
|
||||
obj.GUID must throwA[NoGUIDException]
|
||||
}
|
||||
|
||||
"invalidate changes the nature of the previous valid mutation" in {
|
||||
val obj: EntityTestClass = new EntityTestClass
|
||||
obj.GUID = PlanetSideGUID(1051)
|
||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||
obj.GUID.isInstanceOf[ValidPlanetSideGUID] mustEqual true
|
||||
obj.Invalidate()
|
||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||
obj.GUID.isInstanceOf[StalePlanetSideGUID] mustEqual true
|
||||
}
|
||||
|
||||
"setting an invalid GUID after invalidating the previous valid mutation still raises complaint" in {
|
||||
val obj: EntityTestClass = new EntityTestClass
|
||||
obj.GUID = PlanetSideGUID(1051)
|
||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||
obj.GUID.isInstanceOf[ValidPlanetSideGUID] mustEqual true
|
||||
obj.Invalidate()
|
||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||
obj.GUID.isInstanceOf[StalePlanetSideGUID] mustEqual true
|
||||
(obj.GUID = StalePlanetSideGUID(2)) must throwA[AssigningGUIDException]
|
||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||
}
|
||||
|
||||
"setting a valid GUID after invalidating correctly sets the new valid GUID" in {
|
||||
val obj: EntityTestClass = new EntityTestClass
|
||||
obj.GUID = PlanetSideGUID(1051)
|
||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||
obj.GUID.isInstanceOf[ValidPlanetSideGUID] mustEqual true
|
||||
obj.Invalidate()
|
||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||
obj.GUID.isInstanceOf[StalePlanetSideGUID] mustEqual true
|
||||
obj.GUID = PlanetSideGUID(2)
|
||||
obj.GUID mustEqual PlanetSideGUID(2)
|
||||
obj.GUID.isInstanceOf[ValidPlanetSideGUID] mustEqual true
|
||||
}
|
||||
|
||||
"setting the same valid GUID after invalidating correctly resets the valid GUID" in {
|
||||
val obj: EntityTestClass = new EntityTestClass
|
||||
obj.GUID = PlanetSideGUID(1051)
|
||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||
obj.GUID.isInstanceOf[ValidPlanetSideGUID] mustEqual true
|
||||
obj.Invalidate()
|
||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||
obj.GUID.isInstanceOf[StalePlanetSideGUID] mustEqual true
|
||||
obj.GUID = PlanetSideGUID(1051)
|
||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||
obj.GUID.isInstanceOf[ValidPlanetSideGUID] mustEqual true
|
||||
}
|
||||
|
||||
"report not having a GUID when not set" in {
|
||||
val obj: EntityTestClass = new EntityTestClass
|
||||
obj.HasGUID mustEqual false
|
||||
}
|
||||
|
||||
"report having a GUID when a valid GUID is set" in {
|
||||
val obj: EntityTestClass = new EntityTestClass
|
||||
obj.HasGUID mustEqual false
|
||||
obj.GUID = PlanetSideGUID(1051)
|
||||
obj.HasGUID mustEqual true
|
||||
}
|
||||
|
||||
"report not having a GUID after invalidating (staleness)" in {
|
||||
val obj: EntityTestClass = new EntityTestClass
|
||||
obj.HasGUID mustEqual false
|
||||
obj.GUID = PlanetSideGUID(1051)
|
||||
obj.HasGUID mustEqual true
|
||||
obj.Invalidate()
|
||||
obj.HasGUID mustEqual false
|
||||
//remember that we will still return a GUID in this case
|
||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||
}
|
||||
|
||||
"report having a GUID after setting a valid GUID, after invalidating" in {
|
||||
val obj: EntityTestClass = new EntityTestClass
|
||||
obj.HasGUID mustEqual false
|
||||
obj.GUID = PlanetSideGUID(1051)
|
||||
obj.HasGUID mustEqual true
|
||||
obj.Invalidate()
|
||||
obj.HasGUID mustEqual false
|
||||
obj.GUID = PlanetSideGUID(2)
|
||||
obj.HasGUID mustEqual true
|
||||
}
|
||||
}
|
||||
|
||||
"hachCode test" in {
|
||||
ValidPlanetSideGUID(1051).hashCode mustEqual ValidPlanetSideGUID(1051).hashCode
|
||||
ValidPlanetSideGUID(1051).hashCode mustEqual StalePlanetSideGUID(1051).hashCode
|
||||
}
|
||||
}
|
||||
148
src/test/scala/objects/EquipmentSlotTest.scala
Normal file
148
src/test/scala/objects/EquipmentSlotTest.scala
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects.{OffhandEquipmentSlot, Tool}
|
||||
import net.psforever.objects.equipment.{EquipmentSize, EquipmentSlot}
|
||||
import net.psforever.objects.GlobalDefinitions.{beamer, repeater, suppressor}
|
||||
import org.specs2.mutable._
|
||||
|
||||
class EquipmentSlotTest extends Specification {
|
||||
"EquipmentSlot" should {
|
||||
"construct" in {
|
||||
val obj = new EquipmentSlot()
|
||||
obj.Size mustEqual EquipmentSize.Blocked
|
||||
obj.Equipment mustEqual None
|
||||
}
|
||||
|
||||
"construct with a default size" in {
|
||||
val obj = EquipmentSlot(EquipmentSize.Pistol)
|
||||
obj.Size mustEqual EquipmentSize.Pistol
|
||||
}
|
||||
|
||||
"change size" in {
|
||||
val obj = new EquipmentSlot()
|
||||
obj.Size mustEqual EquipmentSize.Blocked
|
||||
obj.Size = EquipmentSize.Pistol
|
||||
obj.Size mustEqual EquipmentSize.Pistol
|
||||
}
|
||||
|
||||
"hold equipment" in {
|
||||
val obj = new EquipmentSlot()
|
||||
val equipment = Tool(beamer)
|
||||
obj.Equipment = None
|
||||
|
||||
beamer.Size mustEqual EquipmentSize.Pistol
|
||||
obj.Size = EquipmentSize.Pistol
|
||||
obj.Equipment = equipment
|
||||
obj.Equipment match {
|
||||
case Some(item) =>
|
||||
item.Definition mustEqual beamer
|
||||
case None =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"put down previously held equipment" in {
|
||||
val obj = EquipmentSlot(EquipmentSize.Pistol)
|
||||
obj.Equipment = Tool(beamer)
|
||||
|
||||
obj.Equipment match {
|
||||
case Some(item) =>
|
||||
item.Definition mustEqual beamer
|
||||
case None =>
|
||||
ko
|
||||
}
|
||||
obj.Equipment = None
|
||||
obj.Equipment match {
|
||||
case Some(_) =>
|
||||
ko
|
||||
case None =>
|
||||
ok
|
||||
}
|
||||
}
|
||||
|
||||
"not change size when holding equipment" in {
|
||||
val obj = new EquipmentSlot()
|
||||
obj.Size mustEqual EquipmentSize.Blocked
|
||||
obj.Size = EquipmentSize.Pistol
|
||||
obj.Equipment = Tool(beamer)
|
||||
obj.Equipment match {
|
||||
case Some(_) => ;
|
||||
case None => ko
|
||||
}
|
||||
|
||||
obj.Size mustEqual EquipmentSize.Pistol
|
||||
obj.Size = EquipmentSize.Rifle
|
||||
obj.Size mustEqual EquipmentSize.Pistol
|
||||
}
|
||||
|
||||
"not hold wrong-sized equipment" in {
|
||||
val obj = new EquipmentSlot()
|
||||
val equipment = Tool(suppressor)
|
||||
obj.Equipment = None
|
||||
|
||||
beamer.Size mustEqual EquipmentSize.Pistol
|
||||
obj.Size = EquipmentSize.Pistol
|
||||
obj.Equipment = equipment
|
||||
obj.Equipment mustEqual None
|
||||
}
|
||||
|
||||
"not switch to holding a second item in place of a first one" in {
|
||||
val obj = EquipmentSlot(EquipmentSize.Pistol)
|
||||
obj.Equipment = Tool(beamer)
|
||||
|
||||
obj.Equipment match {
|
||||
case Some(item) =>
|
||||
item.Definition mustEqual beamer
|
||||
case None =>
|
||||
ko
|
||||
}
|
||||
repeater.Size mustEqual EquipmentSize.Pistol
|
||||
obj.Equipment = Tool(repeater) //also a pistol
|
||||
obj.Equipment match {
|
||||
case Some(item) =>
|
||||
item.Definition mustEqual beamer
|
||||
case None =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"OffhandEquipmentSLot" should {
|
||||
"construct" in {
|
||||
val obj = new OffhandEquipmentSlot(EquipmentSize.Pistol)
|
||||
obj.Size mustEqual EquipmentSize.Pistol
|
||||
obj.Equipment mustEqual None
|
||||
}
|
||||
|
||||
"hold equipment" in {
|
||||
val obj = new OffhandEquipmentSlot(EquipmentSize.Pistol)
|
||||
val equipment = Tool(beamer)
|
||||
obj.Equipment = None
|
||||
|
||||
beamer.Size mustEqual EquipmentSize.Pistol
|
||||
obj.Equipment = equipment
|
||||
obj.Equipment match {
|
||||
case Some(item) =>
|
||||
item.Definition mustEqual beamer
|
||||
case None =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"not change size after being constructed" in {
|
||||
//see above test "EquipmentSlot should/not change size when holding equipment"
|
||||
val obj = new OffhandEquipmentSlot(EquipmentSize.Pistol)
|
||||
obj.Equipment mustEqual None
|
||||
|
||||
obj.Size mustEqual EquipmentSize.Pistol
|
||||
obj.Size = EquipmentSize.Rifle
|
||||
obj.Size mustEqual EquipmentSize.Pistol
|
||||
}
|
||||
|
||||
"special Blocked size default" in {
|
||||
OffhandEquipmentSlot.BlockedSlot.Size mustEqual EquipmentSize.Blocked
|
||||
OffhandEquipmentSlot.BlockedSlot.Equipment mustEqual None
|
||||
}
|
||||
}
|
||||
}
|
||||
440
src/test/scala/objects/EquipmentTest.scala
Normal file
440
src/test/scala/objects/EquipmentTest.scala
Normal file
|
|
@ -0,0 +1,440 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.equipment._
|
||||
import net.psforever.objects.inventory.InventoryTile
|
||||
import net.psforever.objects.GlobalDefinitions._
|
||||
import net.psforever.objects.avatar.Certification
|
||||
import net.psforever.objects.ce.DeployedItem
|
||||
import net.psforever.objects.definition._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import org.specs2.mutable._
|
||||
|
||||
class EquipmentTest extends Specification {
|
||||
"EquipmentSize" should {
|
||||
"equal" in {
|
||||
//basic equality
|
||||
EquipmentSize.isEqual(EquipmentSize.Pistol, EquipmentSize.Pistol) mustEqual true
|
||||
EquipmentSize.isEqual(EquipmentSize.Pistol, EquipmentSize.Rifle) mustEqual false
|
||||
//Inventory is always allowed
|
||||
EquipmentSize.isEqual(EquipmentSize.Inventory, EquipmentSize.Rifle) mustEqual true
|
||||
EquipmentSize.isEqual(EquipmentSize.Pistol, EquipmentSize.Inventory) mustEqual true
|
||||
//Blocked is never allowed
|
||||
EquipmentSize.isEqual(EquipmentSize.Blocked, EquipmentSize.Rifle) mustEqual false
|
||||
EquipmentSize.isEqual(EquipmentSize.Pistol, EquipmentSize.Blocked) mustEqual false
|
||||
EquipmentSize.isEqual(EquipmentSize.Blocked, EquipmentSize.Inventory) mustEqual false
|
||||
}
|
||||
}
|
||||
|
||||
"AmmoBox" should {
|
||||
"define" in {
|
||||
val obj = AmmoBoxDefinition(86)
|
||||
obj.Capacity = 300
|
||||
obj.Tile = InventoryTile.Tile44
|
||||
|
||||
obj.AmmoType mustEqual Ammo.aphelion_immolation_cannon_ammo
|
||||
obj.Capacity mustEqual 300
|
||||
obj.Tile.Width mustEqual InventoryTile.Tile44.Width
|
||||
obj.Tile.Height mustEqual InventoryTile.Tile44.Height
|
||||
obj.ObjectId mustEqual 86
|
||||
}
|
||||
|
||||
"construct" in {
|
||||
val obj = AmmoBox(bullet_9mm)
|
||||
obj.AmmoType mustEqual Ammo.bullet_9mm
|
||||
obj.Capacity mustEqual 50
|
||||
}
|
||||
|
||||
"construct (2)" in {
|
||||
val obj = AmmoBox(bullet_9mm, 150)
|
||||
obj.AmmoType mustEqual Ammo.bullet_9mm
|
||||
obj.Capacity mustEqual 150
|
||||
}
|
||||
|
||||
"vary capacity" in {
|
||||
val obj = AmmoBox(bullet_9mm, 0)
|
||||
obj.Capacity mustEqual 1 //can not be initialized to 0
|
||||
obj.Capacity = 75
|
||||
obj.Capacity mustEqual 75
|
||||
}
|
||||
|
||||
"limit capacity" in {
|
||||
val obj = AmmoBox(bullet_9mm)
|
||||
obj.Capacity mustEqual 50
|
||||
obj.Capacity = -1
|
||||
obj.Capacity mustEqual 0
|
||||
obj.Capacity = 65536
|
||||
obj.Capacity mustEqual 65535
|
||||
}
|
||||
|
||||
"split (0)" in {
|
||||
val obj = AmmoBox(bullet_9mm)
|
||||
obj.Capacity = 0
|
||||
val list = AmmoBox.Split(obj)
|
||||
list.size mustEqual 0
|
||||
}
|
||||
|
||||
"split (1)" in {
|
||||
val obj = AmmoBox(bullet_9mm)
|
||||
obj.Capacity = 50
|
||||
val list = AmmoBox.Split(obj)
|
||||
list.size mustEqual 1
|
||||
list.head.Capacity mustEqual 50
|
||||
}
|
||||
|
||||
"split (2)" in {
|
||||
val obj = AmmoBox(bullet_9mm)
|
||||
obj.Capacity = 75
|
||||
val list = AmmoBox.Split(obj)
|
||||
list.size mustEqual 2
|
||||
list.head.Capacity mustEqual 50
|
||||
list(1).Capacity mustEqual 25
|
||||
}
|
||||
|
||||
"split (4)" in {
|
||||
val obj = AmmoBox(bullet_9mm)
|
||||
obj.Capacity = 165
|
||||
val list = AmmoBox.Split(obj)
|
||||
list.size mustEqual 4
|
||||
list.head.Capacity mustEqual 50
|
||||
list(1).Capacity mustEqual 50
|
||||
list(2).Capacity mustEqual 50
|
||||
list(3).Capacity mustEqual 15
|
||||
}
|
||||
}
|
||||
|
||||
"Tool" should {
|
||||
"define" in {
|
||||
val obj = ToolDefinition(1076)
|
||||
obj.Name = "sample_weapon"
|
||||
obj.Size = EquipmentSize.Rifle
|
||||
obj.AmmoTypes += GlobalDefinitions.shotgun_shell
|
||||
obj.AmmoTypes += GlobalDefinitions.shotgun_shell_AP
|
||||
obj.AmmoTypes += GlobalDefinitions.shotgun_shell_AP
|
||||
obj.FireModes += new FireModeDefinition
|
||||
obj.FireModes.head.AmmoTypeIndices += 0
|
||||
obj.FireModes.head.AmmoTypeIndices += 1
|
||||
obj.FireModes.head.AmmoSlotIndex = 0
|
||||
obj.FireModes.head.Magazine = 18
|
||||
obj.FireModes += new FireModeDefinition
|
||||
obj.FireModes(1).AmmoTypeIndices += 0
|
||||
obj.FireModes(1).AmmoTypeIndices += 1
|
||||
obj.FireModes(1).AmmoSlotIndex = 1
|
||||
obj.FireModes(1).Chamber = 3
|
||||
obj.FireModes(1).Magazine = 18
|
||||
obj.Tile = InventoryTile.Tile93
|
||||
obj.ObjectId mustEqual 1076
|
||||
|
||||
obj.Name mustEqual "sample_weapon"
|
||||
obj.AmmoTypes.head mustEqual GlobalDefinitions.shotgun_shell
|
||||
obj.AmmoTypes(1) mustEqual GlobalDefinitions.shotgun_shell_AP
|
||||
obj.FireModes.head.AmmoTypeIndices.head mustEqual 0
|
||||
obj.FireModes.head.AmmoTypeIndices(1) mustEqual 1
|
||||
obj.FireModes.head.AmmoSlotIndex mustEqual 0
|
||||
obj.FireModes.head.Chamber mustEqual 1
|
||||
obj.FireModes.head.Magazine mustEqual 18
|
||||
obj.FireModes(1).AmmoTypeIndices.head mustEqual 0
|
||||
obj.FireModes(1).AmmoTypeIndices(1) mustEqual 1
|
||||
obj.FireModes(1).AmmoSlotIndex mustEqual 1
|
||||
obj.FireModes(1).Chamber mustEqual 3
|
||||
obj.FireModes(1).Magazine mustEqual 18
|
||||
obj.Tile.Width mustEqual InventoryTile.Tile93.Width
|
||||
obj.Tile.Height mustEqual InventoryTile.Tile93.Height
|
||||
}
|
||||
|
||||
"construct" in {
|
||||
val obj: Tool = Tool(fury_weapon_systema)
|
||||
obj.Definition.ObjectId mustEqual fury_weapon_systema.ObjectId
|
||||
}
|
||||
|
||||
"fire mode" in {
|
||||
//explanation: fury_weapon_systema has one fire mode and that fire mode is our only option
|
||||
val obj: Tool = Tool(fury_weapon_systema)
|
||||
obj.Magazine = obj.MaxMagazine
|
||||
obj.Magazine mustEqual obj.Definition.FireModes.head.Magazine
|
||||
//fmode = 0
|
||||
obj.FireModeIndex mustEqual 0
|
||||
obj.FireMode.Magazine mustEqual 2
|
||||
obj.AmmoType mustEqual Ammo.hellfire_ammo
|
||||
//fmode -> 1 (0)
|
||||
obj.FireModeIndex = 1
|
||||
obj.FireModeIndex mustEqual 0
|
||||
obj.FireMode.Magazine mustEqual 2
|
||||
obj.AmmoType mustEqual Ammo.hellfire_ammo
|
||||
}
|
||||
|
||||
"default fire mode (dual magazine feed)" in {
|
||||
val obj = ToolDefinition(1076)
|
||||
obj.AmmoTypes += GlobalDefinitions.shotgun_shell
|
||||
obj.AmmoTypes += GlobalDefinitions.shotgun_shell_AP
|
||||
obj.ProjectileTypes += GlobalDefinitions.shotgun_shell_projectile
|
||||
obj.ProjectileTypes += GlobalDefinitions.shotgun_shell_AP_projectile
|
||||
obj.FireModes += new FireModeDefinition
|
||||
obj.FireModes.head.AmmoTypeIndices += 0
|
||||
obj.FireModes.head.AmmoSlotIndex = 0
|
||||
obj.FireModes += new FireModeDefinition
|
||||
obj.FireModes(1).AmmoTypeIndices += 1
|
||||
obj.FireModes(1).AmmoSlotIndex = 1
|
||||
|
||||
val tool0 = Tool(obj)
|
||||
tool0.FireModeIndex mustEqual 0
|
||||
tool0.ProjectileType mustEqual GlobalDefinitions.shotgun_shell_projectile.ProjectileType
|
||||
|
||||
obj.DefaultFireModeIndex = 1
|
||||
val tool1 = Tool(obj)
|
||||
tool1.FireModeIndex mustEqual 1
|
||||
tool1.ProjectileType mustEqual GlobalDefinitions.shotgun_shell_AP_projectile.ProjectileType
|
||||
}
|
||||
|
||||
"multiple fire modes" in {
|
||||
//explanation: sample_weapon has two fire modes; each fire mode has a different ammunition type
|
||||
val obj: Tool = Tool(punisher)
|
||||
//fmode = 0
|
||||
obj.FireModeIndex mustEqual 0
|
||||
obj.FireMode.Magazine mustEqual 30
|
||||
obj.AmmoType mustEqual Ammo.bullet_9mm
|
||||
//fmode -> 1
|
||||
obj.NextFireMode
|
||||
obj.FireModeIndex mustEqual 1
|
||||
obj.FireMode.Magazine mustEqual 1
|
||||
obj.AmmoType mustEqual Ammo.rocket
|
||||
//fmode -> 0
|
||||
obj.NextFireMode
|
||||
obj.FireModeIndex mustEqual 0
|
||||
obj.FireMode.Magazine mustEqual 30
|
||||
obj.AmmoType mustEqual Ammo.bullet_9mm
|
||||
}
|
||||
|
||||
"multiple types of ammunition" in {
|
||||
//explanation: obj has one fire mode and two ammunitions; adjusting the AmmoType changes between them
|
||||
val obj: Tool = Tool(flechette)
|
||||
//ammo = 0
|
||||
obj.AmmoTypeIndex mustEqual 0
|
||||
obj.AmmoType mustEqual Ammo.shotgun_shell
|
||||
//ammo -> 1
|
||||
obj.NextAmmoType
|
||||
obj.AmmoTypeIndex mustEqual 1
|
||||
obj.AmmoType mustEqual Ammo.shotgun_shell_AP
|
||||
//ammo -> 2 (0)
|
||||
obj.NextAmmoType
|
||||
obj.AmmoTypeIndex mustEqual 0
|
||||
obj.AmmoType mustEqual Ammo.shotgun_shell
|
||||
}
|
||||
|
||||
"multiple ammo types and multiple fire modes, split (Punisher)" in {
|
||||
val obj = Tool(GlobalDefinitions.punisher)
|
||||
//ammo = 0, fmode = 0
|
||||
obj.FireModeIndex mustEqual 0
|
||||
obj.AmmoTypeIndex mustEqual 0
|
||||
obj.AmmoType mustEqual Ammo.bullet_9mm
|
||||
//ammo = 2, fmode = 1
|
||||
obj.NextFireMode
|
||||
obj.FireModeIndex mustEqual 1
|
||||
obj.AmmoTypeIndex mustEqual 2
|
||||
obj.AmmoType mustEqual Ammo.rocket
|
||||
//ammo = 3, fmode = 1
|
||||
obj.NextAmmoType
|
||||
obj.AmmoTypeIndex mustEqual 3
|
||||
obj.AmmoType mustEqual Ammo.frag_cartridge
|
||||
//ammo = 4, fmode = 1
|
||||
obj.NextAmmoType
|
||||
obj.AmmoTypeIndex mustEqual 4
|
||||
obj.AmmoType mustEqual Ammo.jammer_cartridge
|
||||
//ammo = 0, fmode = 0
|
||||
obj.NextFireMode
|
||||
obj.FireModeIndex mustEqual 0
|
||||
obj.AmmoTypeIndex mustEqual 0
|
||||
obj.AmmoType mustEqual Ammo.bullet_9mm
|
||||
//ammo = 1, fmode = 0
|
||||
obj.NextAmmoType
|
||||
obj.AmmoTypeIndex mustEqual 1
|
||||
obj.AmmoType mustEqual Ammo.bullet_9mm_AP
|
||||
//ammo = 5, fmode = 1
|
||||
obj.NextFireMode
|
||||
obj.NextAmmoType
|
||||
obj.FireModeIndex mustEqual 1
|
||||
obj.AmmoTypeIndex mustEqual 5
|
||||
obj.AmmoType mustEqual Ammo.plasma_cartridge
|
||||
//ammo = 2, fmode = 1
|
||||
obj.NextAmmoType
|
||||
obj.AmmoTypeIndex mustEqual 2
|
||||
obj.AmmoType mustEqual Ammo.rocket
|
||||
}
|
||||
|
||||
"projectile types and ammo types" in {
|
||||
val suppressor_wep = Tool(suppressor)
|
||||
suppressor_wep.ProjectileType mustEqual bullet_9mm_projectile.ProjectileType
|
||||
suppressor_wep.NextAmmoType
|
||||
suppressor_wep.ProjectileType mustEqual bullet_9mm_AP_projectile.ProjectileType
|
||||
suppressor_wep.NextAmmoType
|
||||
suppressor_wep.ProjectileType mustEqual bullet_9mm_projectile.ProjectileType
|
||||
}
|
||||
|
||||
"projectile types and fire modes" in {
|
||||
val pulsar_wep = Tool(pulsar)
|
||||
pulsar_wep.ProjectileType mustEqual pulsar_projectile.ProjectileType
|
||||
pulsar_wep.NextFireMode
|
||||
pulsar_wep.ProjectileType mustEqual pulsar_ap_projectile.ProjectileType
|
||||
pulsar_wep.NextFireMode
|
||||
pulsar_wep.ProjectileType mustEqual pulsar_projectile.ProjectileType
|
||||
}
|
||||
|
||||
"projectile types and fire modes / ammo types" in {
|
||||
val punisher_wep = Tool(punisher)
|
||||
punisher_wep.ProjectileType mustEqual bullet_9mm_projectile.ProjectileType
|
||||
punisher_wep.NextAmmoType
|
||||
punisher_wep.ProjectileType mustEqual bullet_9mm_AP_projectile.ProjectileType
|
||||
|
||||
punisher_wep.NextFireMode
|
||||
punisher_wep.ProjectileType mustEqual rocket_projectile.ProjectileType
|
||||
punisher_wep.NextAmmoType
|
||||
punisher_wep.ProjectileType mustEqual frag_cartridge_projectile.ProjectileType
|
||||
punisher_wep.NextAmmoType
|
||||
punisher_wep.ProjectileType mustEqual jammer_cartridge_projectile.ProjectileType
|
||||
|
||||
punisher_wep.NextFireMode
|
||||
punisher_wep.ProjectileType mustEqual bullet_9mm_AP_projectile.ProjectileType
|
||||
punisher_wep.NextAmmoType
|
||||
punisher_wep.ProjectileType mustEqual bullet_9mm_projectile.ProjectileType
|
||||
|
||||
punisher_wep.NextFireMode
|
||||
punisher_wep.ProjectileType mustEqual jammer_cartridge_projectile.ProjectileType
|
||||
punisher_wep.NextAmmoType
|
||||
punisher_wep.ProjectileType mustEqual plasma_cartridge_projectile.ProjectileType
|
||||
punisher_wep.NextAmmoType
|
||||
punisher_wep.ProjectileType mustEqual rocket_projectile.ProjectileType
|
||||
}
|
||||
|
||||
"discharge (1)" in {
|
||||
val obj = Tool(GlobalDefinitions.punisher)
|
||||
obj.Magazine mustEqual 30
|
||||
obj.Discharge()
|
||||
obj.Magazine mustEqual 29
|
||||
obj.Discharge()
|
||||
obj.Discharge()
|
||||
obj.Magazine mustEqual 27
|
||||
}
|
||||
|
||||
"chamber" in {
|
||||
val obj = Tool(GlobalDefinitions.flechette)
|
||||
obj.Magazine mustEqual 12
|
||||
obj.AmmoSlot.Chamber mustEqual 8
|
||||
|
||||
obj.Discharge()
|
||||
obj.Magazine mustEqual 12
|
||||
obj.AmmoSlot.Chamber mustEqual 7
|
||||
obj.Discharge()
|
||||
obj.Discharge()
|
||||
obj.Magazine mustEqual 12
|
||||
obj.AmmoSlot.Chamber mustEqual 5
|
||||
obj.Discharge()
|
||||
obj.Discharge()
|
||||
obj.Discharge()
|
||||
obj.Discharge()
|
||||
obj.Magazine mustEqual 12
|
||||
obj.AmmoSlot.Chamber mustEqual 1
|
||||
obj.Discharge()
|
||||
obj.Magazine mustEqual 11
|
||||
obj.AmmoSlot.Chamber mustEqual 8
|
||||
}
|
||||
}
|
||||
|
||||
"Kit" should {
|
||||
"define" in {
|
||||
val sample = KitDefinition(Kits.medkit)
|
||||
sample.ObjectId mustEqual medkit.ObjectId
|
||||
sample.Tile.Width mustEqual medkit.Tile.Width
|
||||
sample.Tile.Height mustEqual medkit.Tile.Height
|
||||
}
|
||||
|
||||
"construct" in {
|
||||
val obj: Kit = Kit(medkit)
|
||||
obj.Definition.ObjectId mustEqual medkit.ObjectId
|
||||
}
|
||||
}
|
||||
|
||||
"ConstructionItem" should {
|
||||
"construct" in {
|
||||
val obj: ConstructionItem = ConstructionItem(GlobalDefinitions.ace)
|
||||
obj.Definition.ObjectId mustEqual GlobalDefinitions.ace.ObjectId
|
||||
}
|
||||
|
||||
"fire modes" in {
|
||||
val obj: ConstructionItem = ConstructionItem(GlobalDefinitions.ace)
|
||||
obj.AmmoType mustEqual DeployedItem.boomer
|
||||
obj.NextFireMode
|
||||
obj.AmmoType mustEqual DeployedItem.he_mine
|
||||
obj.NextFireMode
|
||||
obj.AmmoType mustEqual DeployedItem.spitfire_turret
|
||||
obj.NextFireMode
|
||||
obj.AmmoType mustEqual DeployedItem.motionalarmsensor
|
||||
obj.NextFireMode
|
||||
obj.AmmoType mustEqual DeployedItem.boomer
|
||||
}
|
||||
|
||||
"ammo types" in {
|
||||
val obj: ConstructionItem = ConstructionItem(GlobalDefinitions.ace)
|
||||
obj.NextFireMode
|
||||
obj.AmmoType mustEqual DeployedItem.he_mine
|
||||
obj.NextAmmoType
|
||||
obj.AmmoType mustEqual DeployedItem.jammer_mine
|
||||
obj.NextAmmoType
|
||||
obj.AmmoType mustEqual DeployedItem.he_mine
|
||||
}
|
||||
|
||||
"when switching fire modes, ammo mode resets to the first entry" in {
|
||||
val obj: ConstructionItem = ConstructionItem(GlobalDefinitions.ace)
|
||||
obj.NextFireMode
|
||||
obj.AmmoType mustEqual DeployedItem.he_mine
|
||||
obj.NextAmmoType
|
||||
obj.AmmoType mustEqual DeployedItem.jammer_mine
|
||||
obj.NextFireMode //spitfire_turret
|
||||
obj.NextFireMode //motionalarmsensor
|
||||
obj.NextFireMode //boomer
|
||||
obj.NextFireMode
|
||||
obj.AmmoType mustEqual DeployedItem.he_mine
|
||||
}
|
||||
|
||||
"qualify certifications that must be met before ammo types may be used" in {
|
||||
val obj: ConstructionItem = ConstructionItem(GlobalDefinitions.ace)
|
||||
obj.AmmoType mustEqual DeployedItem.boomer
|
||||
obj.ModePermissions mustEqual Set(Certification.CombatEngineering)
|
||||
obj.NextFireMode
|
||||
obj.AmmoType mustEqual DeployedItem.he_mine
|
||||
obj.ModePermissions mustEqual Set(Certification.CombatEngineering)
|
||||
obj.NextAmmoType
|
||||
obj.AmmoType mustEqual DeployedItem.jammer_mine
|
||||
obj.ModePermissions mustEqual Set(Certification.AssaultEngineering)
|
||||
}
|
||||
}
|
||||
|
||||
"SimpleItem" should {
|
||||
"define" in {
|
||||
val sample = SimpleItemDefinition(SItem.remote_electronics_kit)
|
||||
sample.ObjectId mustEqual remote_electronics_kit.ObjectId
|
||||
}
|
||||
|
||||
"construct" in {
|
||||
val obj: SimpleItem = SimpleItem(remote_electronics_kit)
|
||||
obj.Definition.ObjectId mustEqual remote_electronics_kit.ObjectId
|
||||
}
|
||||
}
|
||||
|
||||
"BoomerTrigger" should {
|
||||
"construct" in {
|
||||
val obj: BoomerTrigger = new BoomerTrigger
|
||||
obj.Definition.ObjectId mustEqual boomer_trigger.ObjectId
|
||||
obj.Companion mustEqual None
|
||||
}
|
||||
|
||||
"boomer trigger has a companion object referenced by GUID" in {
|
||||
val obj: BoomerTrigger = new BoomerTrigger
|
||||
obj.Companion mustEqual None
|
||||
obj.Companion = PlanetSideGUID(1)
|
||||
obj.Companion.contains(PlanetSideGUID(1)) mustEqual true
|
||||
obj.Companion = None
|
||||
obj.Companion mustEqual None
|
||||
}
|
||||
}
|
||||
}
|
||||
210
src/test/scala/objects/ExoSuitTest.scala
Normal file
210
src/test/scala/objects/ExoSuitTest.scala
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects.definition.{ExoSuitDefinition, SpecialExoSuitDefinition}
|
||||
import net.psforever.objects.equipment._
|
||||
import net.psforever.objects.inventory.InventoryTile
|
||||
import net.psforever.types.{ExoSuitType, PlanetSideEmpire}
|
||||
import org.specs2.mutable._
|
||||
|
||||
class ExoSuitTest extends Specification {
|
||||
"ExoSuitDefinition" should {
|
||||
"construct" in {
|
||||
val obj = ExoSuitDefinition(ExoSuitType.Standard)
|
||||
obj.MaxArmor mustEqual 0
|
||||
obj.InventoryScale mustEqual InventoryTile.Tile11
|
||||
obj.InventoryOffset mustEqual 0
|
||||
obj.SuitType mustEqual ExoSuitType.Standard
|
||||
obj.Holsters.length mustEqual 5
|
||||
obj.Holsters.foreach(slot => { if (slot != EquipmentSize.Blocked) { ko } })
|
||||
ok
|
||||
}
|
||||
|
||||
"produce the type of exo-suit that was provided as a clarified type" in {
|
||||
ExoSuitDefinition(ExoSuitType.Standard).SuitType mustEqual ExoSuitType.Standard
|
||||
ExoSuitDefinition(ExoSuitType.Agile).SuitType mustEqual ExoSuitType.Agile
|
||||
}
|
||||
|
||||
"change the maximum armor value" in {
|
||||
val obj = ExoSuitDefinition(ExoSuitType.Standard)
|
||||
obj.MaxArmor mustEqual 0
|
||||
obj.MaxArmor = 1
|
||||
obj.MaxArmor mustEqual 1
|
||||
}
|
||||
|
||||
"not change the maximum armor to an invalid value" in {
|
||||
val obj = ExoSuitDefinition(ExoSuitType.Standard)
|
||||
obj.MaxArmor mustEqual 0
|
||||
obj.MaxArmor = -1
|
||||
obj.MaxArmor mustEqual 0
|
||||
obj.MaxArmor = 65536
|
||||
obj.MaxArmor mustEqual 65535
|
||||
}
|
||||
|
||||
"change the size of the inventory" in {
|
||||
val obj = ExoSuitDefinition(ExoSuitType.Standard)
|
||||
obj.InventoryScale mustEqual InventoryTile.Tile11
|
||||
obj.InventoryScale = InventoryTile.Tile42
|
||||
obj.InventoryScale mustEqual InventoryTile.Tile42
|
||||
}
|
||||
|
||||
"change the start index of the inventory" in {
|
||||
val obj = ExoSuitDefinition(ExoSuitType.Standard)
|
||||
obj.InventoryOffset mustEqual 0
|
||||
obj.InventoryOffset = 1
|
||||
obj.InventoryOffset mustEqual 1
|
||||
}
|
||||
|
||||
"not change the start index of the inventory to an invalid value" in {
|
||||
val obj = ExoSuitDefinition(ExoSuitType.Standard)
|
||||
obj.InventoryOffset mustEqual 0
|
||||
obj.InventoryOffset = -1
|
||||
obj.InventoryOffset mustEqual 0
|
||||
obj.InventoryOffset = 65536
|
||||
obj.InventoryOffset mustEqual 65535
|
||||
}
|
||||
|
||||
"change specific holsters to specific values" in {
|
||||
val obj = ExoSuitDefinition(ExoSuitType.Standard)
|
||||
obj.Holster(0) mustEqual EquipmentSize.Blocked
|
||||
obj.Holster(0, EquipmentSize.Pistol)
|
||||
obj.Holster(0) mustEqual EquipmentSize.Pistol
|
||||
obj.Holster(4) mustEqual EquipmentSize.Blocked
|
||||
obj.Holster(4, EquipmentSize.Rifle)
|
||||
obj.Holster(4) mustEqual EquipmentSize.Rifle
|
||||
(0 to 4).foreach {
|
||||
case 0 => obj.Holsters(0) mustEqual EquipmentSize.Pistol
|
||||
case 4 => obj.Holsters(4) mustEqual EquipmentSize.Rifle
|
||||
case x => obj.Holsters(x) mustEqual EquipmentSize.Blocked
|
||||
}
|
||||
ok
|
||||
}
|
||||
|
||||
"can not change any slot that does not exist" in {
|
||||
val obj = ExoSuitDefinition(ExoSuitType.Standard)
|
||||
obj.Holster(9) mustEqual EquipmentSize.Blocked
|
||||
obj.Holster(9, EquipmentSize.Pistol)
|
||||
obj.Holster(9) mustEqual EquipmentSize.Blocked
|
||||
}
|
||||
|
||||
"produce a copy of the definition" in {
|
||||
val obj = ExoSuitDefinition(ExoSuitType.Standard)
|
||||
val obj2 = obj.Use
|
||||
obj eq obj2
|
||||
}
|
||||
}
|
||||
|
||||
"SpecialExoSuitDefinition" should {
|
||||
"construct" in {
|
||||
val obj = SpecialExoSuitDefinition(ExoSuitType.Standard)
|
||||
obj.MaxArmor mustEqual 0
|
||||
obj.InventoryScale mustEqual InventoryTile.Tile11
|
||||
obj.InventoryOffset mustEqual 0
|
||||
obj.SuitType mustEqual ExoSuitType.Standard
|
||||
obj.Holsters.length mustEqual 5
|
||||
obj.Holsters.foreach(slot => { if (slot != EquipmentSize.Blocked) { ko } })
|
||||
obj.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Normal
|
||||
}
|
||||
|
||||
"configure UsingSpecial to various values" in {
|
||||
val obj = SpecialExoSuitDefinition(ExoSuitType.Standard)
|
||||
obj.UsingSpecial = SpecialExoSuitDefinition.Mode.Anchored
|
||||
obj.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Anchored
|
||||
obj.UsingSpecial = SpecialExoSuitDefinition.Mode.Overdrive
|
||||
obj.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Overdrive
|
||||
obj.UsingSpecial = SpecialExoSuitDefinition.Mode.Shielded
|
||||
obj.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Shielded
|
||||
obj.UsingSpecial = SpecialExoSuitDefinition.Mode.Normal
|
||||
obj.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Normal
|
||||
}
|
||||
|
||||
"produce a separate copy of the definition" in {
|
||||
val obj = SpecialExoSuitDefinition(ExoSuitType.Standard)
|
||||
val obj2 = obj.Use
|
||||
obj ne obj2
|
||||
}
|
||||
}
|
||||
|
||||
"ExoSuitDefinition.Select" should {
|
||||
"produce common, shared instances of exo suits" in {
|
||||
ExoSuitDefinition.Select(ExoSuitType.Standard, PlanetSideEmpire.VS) eq ExoSuitDefinition.Select(
|
||||
ExoSuitType.Standard,
|
||||
PlanetSideEmpire.VS
|
||||
)
|
||||
ExoSuitDefinition.Select(ExoSuitType.Agile, PlanetSideEmpire.VS) eq ExoSuitDefinition.Select(
|
||||
ExoSuitType.Agile,
|
||||
PlanetSideEmpire.VS
|
||||
)
|
||||
ExoSuitDefinition.Select(ExoSuitType.Reinforced, PlanetSideEmpire.VS) eq ExoSuitDefinition.Select(
|
||||
ExoSuitType.Reinforced,
|
||||
PlanetSideEmpire.VS
|
||||
)
|
||||
ExoSuitDefinition.Select(ExoSuitType.Infiltration, PlanetSideEmpire.VS) eq ExoSuitDefinition.Select(
|
||||
ExoSuitType.Infiltration,
|
||||
PlanetSideEmpire.VS
|
||||
)
|
||||
}
|
||||
|
||||
"produce common, shared instances of exo suits across factions" in {
|
||||
ExoSuitDefinition.Select(ExoSuitType.Standard, PlanetSideEmpire.VS) eq ExoSuitDefinition.Select(
|
||||
ExoSuitType.Standard,
|
||||
PlanetSideEmpire.TR
|
||||
)
|
||||
ExoSuitDefinition.Select(ExoSuitType.Standard, PlanetSideEmpire.VS) eq ExoSuitDefinition.Select(
|
||||
ExoSuitType.Standard,
|
||||
PlanetSideEmpire.NC
|
||||
)
|
||||
|
||||
ExoSuitDefinition.Select(ExoSuitType.Agile, PlanetSideEmpire.VS) eq ExoSuitDefinition.Select(
|
||||
ExoSuitType.Agile,
|
||||
PlanetSideEmpire.TR
|
||||
)
|
||||
ExoSuitDefinition.Select(ExoSuitType.Agile, PlanetSideEmpire.VS) eq ExoSuitDefinition.Select(
|
||||
ExoSuitType.Agile,
|
||||
PlanetSideEmpire.NC
|
||||
)
|
||||
|
||||
ExoSuitDefinition.Select(ExoSuitType.Reinforced, PlanetSideEmpire.VS) eq ExoSuitDefinition.Select(
|
||||
ExoSuitType.Reinforced,
|
||||
PlanetSideEmpire.TR
|
||||
)
|
||||
ExoSuitDefinition.Select(ExoSuitType.Reinforced, PlanetSideEmpire.VS) eq ExoSuitDefinition.Select(
|
||||
ExoSuitType.Reinforced,
|
||||
PlanetSideEmpire.NC
|
||||
)
|
||||
|
||||
ExoSuitDefinition.Select(ExoSuitType.Infiltration, PlanetSideEmpire.VS) eq ExoSuitDefinition.Select(
|
||||
ExoSuitType.Infiltration,
|
||||
PlanetSideEmpire.TR
|
||||
)
|
||||
ExoSuitDefinition.Select(ExoSuitType.Infiltration, PlanetSideEmpire.VS) eq ExoSuitDefinition.Select(
|
||||
ExoSuitType.Infiltration,
|
||||
PlanetSideEmpire.NC
|
||||
)
|
||||
}
|
||||
|
||||
"can select max for TR" in {
|
||||
val obj = ExoSuitDefinition.Select(ExoSuitType.MAX, PlanetSideEmpire.TR)
|
||||
obj.isInstanceOf[SpecialExoSuitDefinition] mustEqual true
|
||||
obj.MaxCapacitor mustEqual 300
|
||||
}
|
||||
|
||||
"can select max for VS" in {
|
||||
val obj = ExoSuitDefinition.Select(ExoSuitType.MAX, PlanetSideEmpire.VS)
|
||||
obj.isInstanceOf[SpecialExoSuitDefinition] mustEqual true
|
||||
obj.MaxCapacitor mustEqual 50
|
||||
}
|
||||
|
||||
"can select max for NC" in {
|
||||
val obj = ExoSuitDefinition.Select(ExoSuitType.MAX, PlanetSideEmpire.NC)
|
||||
obj.isInstanceOf[SpecialExoSuitDefinition] mustEqual true
|
||||
obj.MaxCapacitor mustEqual 400
|
||||
}
|
||||
|
||||
"produces unique instances of the mechanized assault exo suit" in {
|
||||
val obj = ExoSuitDefinition.Select(ExoSuitType.MAX, PlanetSideEmpire.VS)
|
||||
obj ne ExoSuitDefinition.Select(ExoSuitType.MAX, PlanetSideEmpire.VS)
|
||||
obj.isInstanceOf[SpecialExoSuitDefinition] mustEqual true
|
||||
}
|
||||
}
|
||||
}
|
||||
287
src/test/scala/objects/FacilityTurretTest.scala
Normal file
287
src/test/scala/objects/FacilityTurretTest.scala
Normal file
|
|
@ -0,0 +1,287 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.Props
|
||||
import akka.testkit.TestProbe
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
import net.psforever.objects.{Default, GlobalDefinitions, Player, Tool}
|
||||
import net.psforever.objects.definition.ToolDefinition
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
import net.psforever.objects.guid.source.LimitedNumberSource
|
||||
import net.psforever.objects.serverobject.CommonMessages
|
||||
import net.psforever.objects.serverobject.mount.Mountable
|
||||
import net.psforever.objects.serverobject.structures.{Building, StructureType}
|
||||
import net.psforever.objects.serverobject.turret._
|
||||
import net.psforever.objects.zones.{Zone, ZoneMap}
|
||||
import net.psforever.packet.game.{InventoryStateMessage, RepairMessage}
|
||||
import net.psforever.types._
|
||||
import org.specs2.mutable.Specification
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||
|
||||
import scala.collection.mutable
|
||||
import scala.concurrent.duration._
|
||||
|
||||
class FacilityTurretTest extends Specification {
|
||||
"FacilityTurretTest" should {
|
||||
"define" in {
|
||||
val obj = new FacilityTurretDefinition(480)
|
||||
obj.Weapons mustEqual mutable.HashMap.empty[TurretUpgrade.Value, ToolDefinition]
|
||||
obj.ReserveAmmunition mustEqual false
|
||||
obj.FactionLocked mustEqual true
|
||||
obj.MaxHealth mustEqual 0
|
||||
obj.MountPoints mustEqual mutable.HashMap.empty[Int, Int]
|
||||
}
|
||||
|
||||
"construct" in {
|
||||
val obj = FacilityTurret(GlobalDefinitions.manned_turret)
|
||||
obj.Weapons.size mustEqual 1
|
||||
obj.Weapons(1).Equipment match {
|
||||
case Some(tool: Tool) =>
|
||||
tool.Definition mustEqual GlobalDefinitions.phalanx_sgl_hevgatcan
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
obj.Seats.size mustEqual 1
|
||||
obj.Seats(0).ControlledWeapon.contains(1) mustEqual true
|
||||
obj.MountPoints.size mustEqual 1
|
||||
obj.MountPoints(1) mustEqual 0
|
||||
obj.Health mustEqual 3600
|
||||
obj.Upgrade mustEqual TurretUpgrade.None
|
||||
obj.Health = 360
|
||||
obj.Health mustEqual 360
|
||||
}
|
||||
|
||||
"upgrade to a different weapon" in {
|
||||
val obj = FacilityTurret(GlobalDefinitions.manned_turret)
|
||||
obj.Upgrade = TurretUpgrade.None
|
||||
obj.Weapons(1).Equipment match {
|
||||
case Some(tool: Tool) =>
|
||||
tool.Definition mustEqual GlobalDefinitions.phalanx_sgl_hevgatcan
|
||||
tool.FireModeIndex mustEqual 0
|
||||
tool.NextFireMode
|
||||
tool.FireModeIndex mustEqual 0 //one fire mode
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
//upgrade
|
||||
obj.Upgrade = TurretUpgrade.AVCombo
|
||||
obj.Weapons(1).Equipment match {
|
||||
case Some(tool: Tool) =>
|
||||
tool.Definition mustEqual GlobalDefinitions.phalanx_avcombo
|
||||
tool.FireModeIndex mustEqual 0
|
||||
tool.ProjectileType mustEqual GlobalDefinitions.phalanx_projectile.ProjectileType
|
||||
tool.NextFireMode
|
||||
tool.FireModeIndex mustEqual 1
|
||||
tool.ProjectileType mustEqual GlobalDefinitions.phalanx_av_projectile.ProjectileType
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
//revert
|
||||
obj.Upgrade = TurretUpgrade.None
|
||||
obj.Weapons(1).Equipment match {
|
||||
case Some(tool: Tool) =>
|
||||
tool.Definition mustEqual GlobalDefinitions.phalanx_sgl_hevgatcan
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FacilityTurretControl1Test extends ActorTest {
|
||||
"FacilityTurretControl" should {
|
||||
"construct" in {
|
||||
val obj = FacilityTurret(GlobalDefinitions.manned_turret)
|
||||
obj.Actor = system.actorOf(Props(classOf[FacilityTurretControl], obj), "turret-control")
|
||||
assert(obj.Actor != Default.Actor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FacilityTurretControl2Test extends ActorTest {
|
||||
val player = Player(Avatar(0, "", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
val obj = FacilityTurret(GlobalDefinitions.manned_turret)
|
||||
obj.GUID = PlanetSideGUID(1)
|
||||
obj.Actor = system.actorOf(Props(classOf[FacilityTurretControl], obj), "turret-control")
|
||||
val bldg = Building("Building", guid = 0, map_id = 0, Zone.Nowhere, StructureType.Building)
|
||||
bldg.Amenities = obj
|
||||
bldg.Faction = PlanetSideEmpire.TR
|
||||
|
||||
"FacilityTurretControl" should {
|
||||
"seat on faction affiliation when FactionLock is true" in {
|
||||
assert(player.Faction == PlanetSideEmpire.TR)
|
||||
assert(obj.Faction == PlanetSideEmpire.TR)
|
||||
assert(obj.Definition.FactionLocked)
|
||||
|
||||
obj.Actor ! Mountable.TryMount(player, 0)
|
||||
val reply = receiveOne(300 milliseconds)
|
||||
reply match {
|
||||
case msg: Mountable.MountMessages =>
|
||||
assert(msg.response.isInstanceOf[Mountable.CanMount])
|
||||
case _ =>
|
||||
assert(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FacilityTurretControl3Test extends ActorTest {
|
||||
val player = Player(Avatar(0, "", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
val obj = FacilityTurret(GlobalDefinitions.manned_turret)
|
||||
obj.GUID = PlanetSideGUID(1)
|
||||
obj.Actor = system.actorOf(Props(classOf[FacilityTurretControl], obj), "turret-control")
|
||||
val bldg = Building("Building", guid = 0, map_id = 0, Zone.Nowhere, StructureType.Building)
|
||||
bldg.Amenities = obj
|
||||
|
||||
"FacilityTurretControl" should {
|
||||
"block seating on mismatched faction affiliation when FactionLock is true" in {
|
||||
assert(player.Faction == PlanetSideEmpire.TR)
|
||||
assert(obj.Faction == PlanetSideEmpire.NEUTRAL)
|
||||
assert(obj.Definition.FactionLocked)
|
||||
|
||||
obj.Actor ! Mountable.TryMount(player, 0)
|
||||
val reply = receiveOne(300 milliseconds)
|
||||
reply match {
|
||||
case msg: Mountable.MountMessages =>
|
||||
assert(msg.response.isInstanceOf[Mountable.CanNotMount])
|
||||
case _ =>
|
||||
assert(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FacilityTurretControl4Test extends ActorTest {
|
||||
val player = Player(Avatar(0, "", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
val objDef = new FacilityTurretDefinition(480)
|
||||
objDef.FactionLocked = false
|
||||
val obj = FacilityTurret(objDef)
|
||||
obj.GUID = PlanetSideGUID(1)
|
||||
obj.Actor = system.actorOf(Props(classOf[FacilityTurretControl], obj), "turret-control")
|
||||
val bldg = Building("Building", guid = 0, map_id = 0, Zone.Nowhere, StructureType.Building)
|
||||
bldg.Amenities = obj
|
||||
|
||||
"FacilityTurretControl" should {
|
||||
"seating even with mismatched faction affiliation when FactionLock is false" in {
|
||||
assert(player.Faction == PlanetSideEmpire.TR)
|
||||
assert(obj.Faction == PlanetSideEmpire.NEUTRAL)
|
||||
assert(!obj.Definition.FactionLocked)
|
||||
|
||||
obj.Actor ! Mountable.TryMount(player, 0)
|
||||
val reply = receiveOne(300 milliseconds)
|
||||
reply match {
|
||||
case msg: Mountable.MountMessages =>
|
||||
assert(msg.response.isInstanceOf[Mountable.CanMount])
|
||||
case _ =>
|
||||
assert(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FacilityTurretControlRestorationTest extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(10))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
val building = Building("test-building", 1, 1, zone, StructureType.Facility) //guid=1
|
||||
val activityProbe = TestProbe()
|
||||
val avatarProbe = TestProbe()
|
||||
val vehicleProbe = TestProbe()
|
||||
val buildingProbe = TestProbe()
|
||||
zone.Activity = activityProbe.ref
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
zone.VehicleEvents = vehicleProbe.ref
|
||||
building.Actor = buildingProbe.ref
|
||||
|
||||
val turret = new FacilityTurret(GlobalDefinitions.manned_turret) //2, 5, 6
|
||||
turret.Actor = system.actorOf(Props(classOf[FacilityTurretControl], turret), "turret-control")
|
||||
turret.Zone = zone
|
||||
turret.Position = Vector3(1, 0, 0)
|
||||
val turretWeapon = turret.Weapons.values.head.Equipment.get.asInstanceOf[Tool]
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=3
|
||||
player1.Spawn()
|
||||
player1.Position = Vector3(2, 2, 2)
|
||||
val player1Probe = TestProbe()
|
||||
player1.Actor = player1Probe.ref
|
||||
|
||||
guid.register(building, 1)
|
||||
guid.register(turret, 2)
|
||||
guid.register(player1, 3)
|
||||
guid.register(turretWeapon, 5)
|
||||
guid.register(turretWeapon.AmmoSlot.Box, 6)
|
||||
building.Position = Vector3(1, 0, 0)
|
||||
building.Zone = zone
|
||||
building.Amenities = turret
|
||||
|
||||
val tool = Tool(GlobalDefinitions.nano_dispenser) //7 & 8
|
||||
guid.register(tool, 7)
|
||||
guid.register(tool.AmmoSlot.Box, 8)
|
||||
|
||||
"RepairableTurretWeapon" should {
|
||||
"handle repairs and restoration" in {
|
||||
turret.Health = turret.Definition.RepairRestoresAt - 1 //initial state manip
|
||||
turret.Destroyed = true //initial state manip
|
||||
assert(turret.Health < turret.Definition.RepairRestoresAt)
|
||||
assert(turret.Destroyed)
|
||||
|
||||
turret.Actor ! CommonMessages.Use(player1, Some(tool))
|
||||
val msg12345 = avatarProbe.receiveN(5, 500 milliseconds)
|
||||
val msg4 = vehicleProbe.receiveOne(500 milliseconds)
|
||||
assert(
|
||||
msg12345.head match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction
|
||||
.SendResponse(PlanetSideGUID(0), InventoryStateMessage(PlanetSideGUID(8), _, PlanetSideGUID(7), _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg12345(1) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg12345(2) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 50, 0)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg12345(3) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 51, 0)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg12345(4) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction.SendResponse(PlanetSideGUID(0), RepairMessage(PlanetSideGUID(2), _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg4 match {
|
||||
case VehicleServiceMessage("test", VehicleAction.EquipmentInSlot(_, PlanetSideGUID(2), 1, t))
|
||||
if t eq turretWeapon =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(turret.Health > turret.Definition.RepairRestoresAt)
|
||||
assert(!turret.Destroyed)
|
||||
}
|
||||
}
|
||||
}
|
||||
141
src/test/scala/objects/FactionAffinityTest.scala
Normal file
141
src/test/scala/objects/FactionAffinityTest.scala
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.{Actor, ActorSystem, Props}
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.{GlobalDefinitions, Vehicle}
|
||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||
import net.psforever.objects.serverobject.doors.Door
|
||||
import net.psforever.objects.serverobject.structures.{Building, StructureType}
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
import scala.concurrent.duration.Duration
|
||||
|
||||
class FactionAffinityTest extends Specification {
|
||||
"FactionAffinity" should {
|
||||
"construct (basic)" in {
|
||||
val obj = new FactionAffinity { def Faction = PlanetSideEmpire.TR }
|
||||
obj.Faction mustEqual PlanetSideEmpire.TR
|
||||
}
|
||||
|
||||
"construct (part of)" in {
|
||||
val obj = new Door(GlobalDefinitions.door)
|
||||
obj.Faction mustEqual PlanetSideEmpire.NEUTRAL
|
||||
}
|
||||
|
||||
"can not change affinity directly (basic)" in {
|
||||
val obj = new FactionAffinity { def Faction = PlanetSideEmpire.TR }
|
||||
(obj.Faction = PlanetSideEmpire.NC) mustEqual PlanetSideEmpire.TR
|
||||
}
|
||||
|
||||
"can not change affinity directly (part of)" in {
|
||||
val obj = new Door(GlobalDefinitions.door)
|
||||
(obj.Faction = PlanetSideEmpire.TR) mustEqual PlanetSideEmpire.NEUTRAL
|
||||
}
|
||||
|
||||
"inherits affinity from owner 1" in {
|
||||
val obj = new Door(GlobalDefinitions.door)
|
||||
obj.Owner.Faction mustEqual PlanetSideEmpire.NEUTRAL
|
||||
(obj.Faction = PlanetSideEmpire.TR) mustEqual PlanetSideEmpire.NEUTRAL
|
||||
}
|
||||
|
||||
"inherits affinity from owner 2" in {
|
||||
val obj = new Door(GlobalDefinitions.door)
|
||||
val bldg = new Building(
|
||||
"Building",
|
||||
building_guid = 0,
|
||||
map_id = 1,
|
||||
Zone.Nowhere,
|
||||
StructureType.Building,
|
||||
GlobalDefinitions.building
|
||||
)
|
||||
obj.Owner = bldg
|
||||
obj.Faction mustEqual PlanetSideEmpire.NEUTRAL
|
||||
|
||||
bldg.Faction = PlanetSideEmpire.TR
|
||||
obj.Faction mustEqual PlanetSideEmpire.TR
|
||||
|
||||
bldg.Faction = PlanetSideEmpire.NC
|
||||
obj.Faction mustEqual PlanetSideEmpire.NC
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FactionAffinity1Test extends ActorTest {
|
||||
"FactionAffinity" should {
|
||||
"assert affinity on confirm request" in {
|
||||
val obj = FactionAffinityTest.SetUpAgent
|
||||
obj.Faction = PlanetSideEmpire.VS //object is a type that can be changed directly
|
||||
assert(obj.Faction == PlanetSideEmpire.VS)
|
||||
|
||||
obj.Actor ! FactionAffinity.ConfirmFactionAffinity()
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
assert(reply.isInstanceOf[FactionAffinity.AssertFactionAffinity])
|
||||
assert(reply.asInstanceOf[FactionAffinity.AssertFactionAffinity].obj == obj)
|
||||
assert(reply.asInstanceOf[FactionAffinity.AssertFactionAffinity].faction == PlanetSideEmpire.VS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FactionAffinity2Test extends ActorTest {
|
||||
"FactionAffinity" should {
|
||||
"assert affinity on assert request" in {
|
||||
val obj = FactionAffinityTest.SetUpAgent
|
||||
obj.Faction = PlanetSideEmpire.VS //object is a type that can be changed directly
|
||||
assert(obj.Faction == PlanetSideEmpire.VS)
|
||||
|
||||
obj.Actor ! FactionAffinity.AssertFactionAffinity(obj, PlanetSideEmpire.NEUTRAL)
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
assert(reply.isInstanceOf[FactionAffinity.AssertFactionAffinity])
|
||||
assert(reply.asInstanceOf[FactionAffinity.AssertFactionAffinity].obj == obj)
|
||||
assert(reply.asInstanceOf[FactionAffinity.AssertFactionAffinity].faction == PlanetSideEmpire.VS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FactionAffinity3Test extends ActorTest {
|
||||
"FactionAffinity" should {
|
||||
"convert and assert affinity on convert request" in {
|
||||
val obj = FactionAffinityTest.SetUpAgent
|
||||
obj.Faction = PlanetSideEmpire.VS //object is a type that can be changed directly
|
||||
assert(obj.Faction == PlanetSideEmpire.VS)
|
||||
|
||||
obj.Actor ! FactionAffinity.ConvertFactionAffinity(PlanetSideEmpire.TR)
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
assert(reply.isInstanceOf[FactionAffinity.AssertFactionAffinity])
|
||||
assert(reply.asInstanceOf[FactionAffinity.AssertFactionAffinity].obj == obj)
|
||||
assert(reply.asInstanceOf[FactionAffinity.AssertFactionAffinity].faction == PlanetSideEmpire.TR)
|
||||
assert(obj.Faction == PlanetSideEmpire.TR)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object FactionAffinityTest {
|
||||
import net.psforever.objects.serverobject.affinity.FactionAffinityBehavior
|
||||
|
||||
private class AffinityControl(obj: FactionAffinity)
|
||||
extends Actor
|
||||
with FactionAffinityBehavior.Check
|
||||
with FactionAffinityBehavior.Convert {
|
||||
override def FactionObject = obj
|
||||
def receive = checkBehavior.orElse(convertBehavior).orElse { case _ => }
|
||||
}
|
||||
|
||||
def SetUpAgent(implicit system: ActorSystem) = {
|
||||
val obj = new Vehicle(GlobalDefinitions.quadstealth)
|
||||
obj.Actor = system.actorOf(Props(classOf[FactionAffinityTest.AffinityControl], obj), "test")
|
||||
obj
|
||||
}
|
||||
|
||||
def FreeFactionObject: FactionAffinity =
|
||||
new FactionAffinity() {
|
||||
private var faction: PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||
def Faction: PlanetSideEmpire.Value = faction
|
||||
override def Faction_=(fac: PlanetSideEmpire.Value): PlanetSideEmpire.Value = {
|
||||
faction = fac
|
||||
faction
|
||||
}
|
||||
}
|
||||
}
|
||||
132
src/test/scala/objects/FireModeTest.scala
Normal file
132
src/test/scala/objects/FireModeTest.scala
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects.definition.ToolDefinition
|
||||
import net.psforever.objects.{GlobalDefinitions, Tool}
|
||||
import net.psforever.objects.equipment.{
|
||||
EquipmentSize,
|
||||
FireModeDefinition,
|
||||
InfiniteFireModeDefinition,
|
||||
PelletFireModeDefinition
|
||||
}
|
||||
import org.specs2.mutable._
|
||||
|
||||
class FireModeTest extends Specification {
|
||||
"FireModeDefinition" should {
|
||||
"construct" in {
|
||||
val obj = new FireModeDefinition
|
||||
obj.AmmoTypeIndices mustEqual Nil
|
||||
obj.AmmoSlotIndex mustEqual 0
|
||||
obj.Magazine mustEqual 1
|
||||
obj.RoundsPerShot mustEqual 1
|
||||
obj.Chamber mustEqual 1
|
||||
}
|
||||
|
||||
"test configurations" in {
|
||||
val tdef = ToolDefinition(1076) //fake object id
|
||||
tdef.Size = EquipmentSize.Rifle
|
||||
tdef.AmmoTypes += GlobalDefinitions.bullet_9mm
|
||||
tdef.AmmoTypes += GlobalDefinitions.shotgun_shell
|
||||
tdef.FireModes += new FireModeDefinition
|
||||
tdef.FireModes.head.AmmoTypeIndices += 0
|
||||
tdef.FireModes.head.AmmoSlotIndex = 0
|
||||
tdef.FireModes.head.Magazine = 18
|
||||
tdef.FireModes.head.RoundsPerShot = 18
|
||||
tdef.FireModes.head.Chamber = 2
|
||||
tdef.FireModes += new FireModeDefinition
|
||||
tdef.FireModes(1).AmmoTypeIndices += 1
|
||||
tdef.FireModes(1).AmmoTypeIndices += 2
|
||||
tdef.FireModes(1).AmmoSlotIndex = 1
|
||||
tdef.FireModes(1).Magazine = 9
|
||||
tdef.FireModes(1).RoundsPerShot = 2
|
||||
tdef.FireModes(1).Chamber = 8
|
||||
|
||||
tdef.AmmoTypes.toList mustEqual List(GlobalDefinitions.bullet_9mm, GlobalDefinitions.shotgun_shell)
|
||||
tdef.FireModes.size mustEqual 2
|
||||
tdef.FireModes.head.AmmoTypeIndices.toList mustEqual List(0)
|
||||
tdef.FireModes.head.AmmoSlotIndex mustEqual 0
|
||||
tdef.FireModes.head.Magazine mustEqual 18
|
||||
tdef.FireModes.head.RoundsPerShot mustEqual 18
|
||||
tdef.FireModes.head.Chamber mustEqual 2
|
||||
tdef.FireModes(1).AmmoTypeIndices.toList mustEqual List(1, 2)
|
||||
tdef.FireModes(1).AmmoSlotIndex mustEqual 1
|
||||
tdef.FireModes(1).Magazine mustEqual 9
|
||||
tdef.FireModes(1).RoundsPerShot mustEqual 2
|
||||
tdef.FireModes(1).Chamber mustEqual 8
|
||||
}
|
||||
|
||||
"discharge" in {
|
||||
val obj = Tool(GlobalDefinitions.beamer) //see EquipmentTest
|
||||
obj.FireMode.isInstanceOf[FireModeDefinition] mustEqual true
|
||||
obj.Magazine mustEqual 16
|
||||
obj.FireMode.RoundsPerShot mustEqual 1
|
||||
obj.FireMode.Chamber mustEqual 1
|
||||
|
||||
obj.Magazine mustEqual 16
|
||||
obj.Discharge()
|
||||
obj.Magazine mustEqual 15
|
||||
obj.Discharge()
|
||||
obj.Discharge()
|
||||
obj.Magazine mustEqual 13
|
||||
}
|
||||
}
|
||||
|
||||
"PelletFireModeDefinition" should {
|
||||
"construct" in {
|
||||
val obj = new PelletFireModeDefinition
|
||||
obj.AmmoTypeIndices mustEqual Nil
|
||||
obj.AmmoSlotIndex mustEqual 0
|
||||
obj.Magazine mustEqual 1
|
||||
obj.RoundsPerShot mustEqual 1
|
||||
obj.Chamber mustEqual 1
|
||||
}
|
||||
|
||||
"discharge" in {
|
||||
val obj = Tool(GlobalDefinitions.flechette) //see EquipmentTest
|
||||
obj.FireMode.isInstanceOf[PelletFireModeDefinition] mustEqual true
|
||||
obj.Magazine mustEqual 12
|
||||
obj.FireMode.RoundsPerShot mustEqual 1
|
||||
obj.FireMode.Chamber mustEqual 8
|
||||
|
||||
obj.Magazine mustEqual 12
|
||||
obj.Discharge() //1
|
||||
obj.Magazine mustEqual 12
|
||||
obj.Discharge() //2
|
||||
obj.Discharge() //3
|
||||
obj.Magazine mustEqual 12
|
||||
obj.Discharge() //4
|
||||
obj.Discharge() //5
|
||||
obj.Discharge() //6
|
||||
obj.Discharge() //7
|
||||
obj.Magazine mustEqual 12
|
||||
obj.Discharge() //8
|
||||
obj.Magazine mustEqual 11
|
||||
}
|
||||
}
|
||||
|
||||
"InfiniteFireModeDefinition" should {
|
||||
"construct" in {
|
||||
val obj = new InfiniteFireModeDefinition
|
||||
obj.AmmoTypeIndices mustEqual Nil
|
||||
obj.AmmoSlotIndex mustEqual 0
|
||||
obj.Magazine mustEqual 1
|
||||
obj.RoundsPerShot mustEqual 1
|
||||
obj.Chamber mustEqual 1
|
||||
}
|
||||
|
||||
"discharge" in {
|
||||
val obj = Tool(GlobalDefinitions.magcutter) //see EquipmentTest
|
||||
obj.FireMode.isInstanceOf[InfiniteFireModeDefinition] mustEqual true
|
||||
obj.Magazine mustEqual 1
|
||||
obj.FireMode.RoundsPerShot mustEqual 1
|
||||
obj.FireMode.Chamber mustEqual 1
|
||||
|
||||
obj.Magazine mustEqual 1
|
||||
obj.Discharge()
|
||||
obj.Magazine mustEqual 1
|
||||
obj.Discharge()
|
||||
obj.Discharge()
|
||||
obj.Magazine mustEqual 1
|
||||
}
|
||||
}
|
||||
}
|
||||
852
src/test/scala/objects/GeneratorTest.scala
Normal file
852
src/test/scala/objects/GeneratorTest.scala
Normal file
|
|
@ -0,0 +1,852 @@
|
|||
// Copyright (c) 2020 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.{ActorRef, Props}
|
||||
import akka.testkit.TestProbe
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
import net.psforever.objects.ballistics._
|
||||
import net.psforever.objects.{GlobalDefinitions, Player, Tool}
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
import net.psforever.objects.guid.source.LimitedNumberSource
|
||||
import net.psforever.objects.serverobject.CommonMessages
|
||||
import net.psforever.objects.serverobject.generator.{Generator, GeneratorControl}
|
||||
import net.psforever.objects.serverobject.structures.{Building, StructureType}
|
||||
import net.psforever.objects.vital.Vitality
|
||||
import net.psforever.objects.zones.{Zone, ZoneMap}
|
||||
import net.psforever.packet.game.{InventoryStateMessage, RepairMessage, TriggerEffectMessage}
|
||||
import net.psforever.types._
|
||||
import org.specs2.mutable.Specification
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
class GeneratorTest extends Specification {
|
||||
"Generator" should {
|
||||
"construct" in {
|
||||
Generator(GlobalDefinitions.generator)
|
||||
ok
|
||||
}
|
||||
|
||||
"start in 'Normal' condition" in {
|
||||
val obj = Generator(GlobalDefinitions.generator)
|
||||
obj.Condition mustEqual PlanetSideGeneratorState.Normal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GeneratorControlConstructTest extends ActorTest {
|
||||
"GeneratorControl" should {
|
||||
"construct" in {
|
||||
val gen = Generator(GlobalDefinitions.generator)
|
||||
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "gen-control")
|
||||
assert(gen.Actor != ActorRef.noSender)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GeneratorControlDamageTest extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(5))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
val avatarProbe = TestProbe()
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
val activityProbe = TestProbe()
|
||||
zone.Activity = activityProbe.ref
|
||||
|
||||
val gen = Generator(GlobalDefinitions.generator) //guid=2
|
||||
gen.Position = Vector3(1, 0, 0)
|
||||
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=3
|
||||
player1.Position = Vector3(14, 0, 0) //<14m from generator; dies
|
||||
player1.Spawn()
|
||||
|
||||
val building = Building("test-building", 1, 1, zone, StructureType.Facility) //guid=1
|
||||
building.Position = Vector3(1, 0, 0)
|
||||
building.Zone = zone
|
||||
building.Amenities = gen
|
||||
building.PlayersInSOI = List(player1)
|
||||
val buildingProbe = TestProbe()
|
||||
building.Actor = buildingProbe.ref
|
||||
|
||||
guid.register(building, 1)
|
||||
guid.register(gen, 2)
|
||||
guid.register(player1, 3)
|
||||
|
||||
val weapon = Tool(GlobalDefinitions.phoenix) //decimator
|
||||
val projectile = weapon.Projectile
|
||||
val resolved = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
Projectile(
|
||||
projectile,
|
||||
weapon.Definition,
|
||||
weapon.FireMode,
|
||||
PlayerSource(player1),
|
||||
0,
|
||||
Vector3(2, 0, 0),
|
||||
Vector3(-1, 0, 0)
|
||||
),
|
||||
SourceEntry(gen),
|
||||
gen.DamageModel,
|
||||
Vector3(1, 0, 0)
|
||||
)
|
||||
val applyDamageTo = resolved.damage_model.Calculate(resolved)
|
||||
expectNoMessage(200 milliseconds)
|
||||
//we're not testing that the math is correct
|
||||
|
||||
"GeneratorControl" should {
|
||||
"handle damage" in {
|
||||
assert(gen.Health == gen.Definition.MaxHealth)
|
||||
assert(!gen.Destroyed)
|
||||
assert(gen.Condition == PlanetSideGeneratorState.Normal)
|
||||
|
||||
gen.Actor ! Vitality.Damage(applyDamageTo)
|
||||
val msg_avatar = avatarProbe.receiveN(2, 500 milliseconds)
|
||||
buildingProbe.expectNoMessage(200 milliseconds)
|
||||
assert(
|
||||
msg_avatar.head 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(gen.Health < gen.Definition.MaxHealth)
|
||||
assert(!gen.Destroyed)
|
||||
assert(gen.Condition == PlanetSideGeneratorState.Normal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GeneratorControlCriticalTest extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(5))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
val avatarProbe = TestProbe()
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
val activityProbe = TestProbe()
|
||||
zone.Activity = activityProbe.ref
|
||||
|
||||
val gen = Generator(GlobalDefinitions.generator) //guid=2
|
||||
gen.Position = Vector3(1, 0, 0)
|
||||
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=3
|
||||
player1.Position = Vector3(14, 0, 0) //<14m from generator; dies
|
||||
player1.Spawn()
|
||||
|
||||
val building = Building("test-building", 1, 1, zone, StructureType.Facility) //guid=1
|
||||
building.Position = Vector3(1, 0, 0)
|
||||
building.Zone = zone
|
||||
building.Amenities = gen
|
||||
building.PlayersInSOI = List(player1)
|
||||
val buildingProbe = TestProbe()
|
||||
building.Actor = buildingProbe.ref
|
||||
|
||||
guid.register(building, 1)
|
||||
guid.register(gen, 2)
|
||||
guid.register(player1, 3)
|
||||
|
||||
val weapon = Tool(GlobalDefinitions.phoenix) //decimator
|
||||
val projectile = weapon.Projectile
|
||||
val resolved = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
Projectile(
|
||||
projectile,
|
||||
weapon.Definition,
|
||||
weapon.FireMode,
|
||||
PlayerSource(player1),
|
||||
0,
|
||||
Vector3(2, 0, 0),
|
||||
Vector3(-1, 0, 0)
|
||||
),
|
||||
SourceEntry(gen),
|
||||
gen.DamageModel,
|
||||
Vector3(1, 0, 0)
|
||||
)
|
||||
val applyDamageTo = resolved.damage_model.Calculate(resolved)
|
||||
val halfHealth = gen.Definition.MaxHealth / 2
|
||||
expectNoMessage(200 milliseconds)
|
||||
//we're not testing that the math is correct
|
||||
|
||||
"GeneratorControl" should {
|
||||
"handle damage through the generator's critical state" in {
|
||||
gen.Health = halfHealth + 1 //no matter what, the next shot pushes it to critical status
|
||||
assert(gen.Health > halfHealth)
|
||||
assert(!gen.Destroyed)
|
||||
assert(gen.Condition == PlanetSideGeneratorState.Normal)
|
||||
|
||||
gen.Actor ! Vitality.Damage(applyDamageTo)
|
||||
val msg_avatar = avatarProbe.receiveN(2, 500 milliseconds)
|
||||
val msg_building = buildingProbe.receiveOne(500 milliseconds)
|
||||
assert(
|
||||
msg_avatar.head 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 Building.AmenityStateChange(o) => o eq gen
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(gen.Health < halfHealth)
|
||||
assert(!gen.Destroyed)
|
||||
assert(gen.Condition == PlanetSideGeneratorState.Critical)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GeneratorControlDestroyedTest extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(5))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
val avatarProbe = TestProbe()
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
val activityProbe = TestProbe()
|
||||
zone.Activity = activityProbe.ref
|
||||
|
||||
val gen = Generator(GlobalDefinitions.generator) //guid=2
|
||||
gen.Position = Vector3(1, 0, 0)
|
||||
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=3
|
||||
player1.Position = Vector3(14, 0, 0) //<14m from generator; dies
|
||||
player1.Spawn()
|
||||
player1.Actor = TestProbe().ref
|
||||
|
||||
val building = Building("test-building", 1, 1, zone, StructureType.Facility) //guid=1
|
||||
building.Position = Vector3(1, 0, 0)
|
||||
building.Zone = zone
|
||||
building.Amenities = gen
|
||||
building.PlayersInSOI = List(player1)
|
||||
val buildingProbe = TestProbe()
|
||||
building.Actor = buildingProbe.ref
|
||||
|
||||
guid.register(building, 1)
|
||||
guid.register(gen, 2)
|
||||
guid.register(player1, 3)
|
||||
|
||||
val weapon = Tool(GlobalDefinitions.phoenix) //decimator
|
||||
val projectile = weapon.Projectile
|
||||
val resolved = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
Projectile(
|
||||
projectile,
|
||||
weapon.Definition,
|
||||
weapon.FireMode,
|
||||
PlayerSource(player1),
|
||||
0,
|
||||
Vector3(2, 0, 0),
|
||||
Vector3(-1, 0, 0)
|
||||
),
|
||||
SourceEntry(gen),
|
||||
gen.DamageModel,
|
||||
Vector3(1, 0, 0)
|
||||
)
|
||||
val applyDamageTo = resolved.damage_model.Calculate(resolved)
|
||||
expectNoMessage(200 milliseconds)
|
||||
//we're not testing that the math is correct
|
||||
|
||||
"GeneratorControl" should {
|
||||
"handle damage until destroyed" in {
|
||||
gen.Health = 1 //no matter what, the next shot destroys the generator
|
||||
assert(gen.Health == 1)
|
||||
assert(!gen.Destroyed)
|
||||
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)
|
||||
assert(
|
||||
msg_avatar1 match {
|
||||
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 16)) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(gen.Health == 1)
|
||||
assert(!gen.Destroyed)
|
||||
assert(gen.Condition == PlanetSideGeneratorState.Normal)
|
||||
|
||||
avatarProbe.expectNoMessage(9 seconds)
|
||||
buildingProbe.expectNoMessage(50 milliseconds) //no prior messages
|
||||
val msg_avatar2 = avatarProbe.receiveN(3, 1000 milliseconds) //see DamageableEntity test file
|
||||
val msg_building = buildingProbe.receiveOne(200 milliseconds)
|
||||
assert(
|
||||
msg_building match {
|
||||
case Building.AmenityStateChange(o) => o eq gen
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar2.head match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar2(1) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.Destroy(PlanetSideGUID(2), _, _, Vector3(1, 0, 0))) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar2(2) match {
|
||||
case AvatarServiceMessage(
|
||||
"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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GeneratorControlKillsTest extends ActorTest {
|
||||
/*
|
||||
to perform this test, players need to be added to the SOI organization of the test base in proximity of the generator
|
||||
under normal player scenario, this is an automatic process
|
||||
extending from the act of players being in a zone
|
||||
and players being within the SOI radius from the center of a facility on a periodic check
|
||||
the test base being used has no established SOI region or automatic SOI check refresh,
|
||||
but its SOI information can be loaded with the players manually
|
||||
the players need something to catch the die message
|
||||
*/
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(5))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
val avatarProbe = TestProbe()
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
val activityProbe = TestProbe()
|
||||
zone.Activity = activityProbe.ref
|
||||
|
||||
val gen = Generator(GlobalDefinitions.generator) //guid=2
|
||||
gen.Position = Vector3(1, 0, 0)
|
||||
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=3
|
||||
player1.Position = Vector3(14, 0, 0) //<14m from generator; dies
|
||||
player1.Spawn()
|
||||
val player1Probe = TestProbe()
|
||||
player1.Actor = player1Probe.ref
|
||||
val player2 =
|
||||
Player(Avatar(0, "TestCharacter2", PlanetSideEmpire.TR, CharacterGender.Female, 1, CharacterVoice.Mute)) //guid=4
|
||||
player2.Position = Vector3(15, 0, 0) //>14m from generator; lives
|
||||
player2.Spawn()
|
||||
val player2Probe = TestProbe()
|
||||
player2.Actor = player2Probe.ref
|
||||
|
||||
val building = Building("test-building", 1, 1, zone, StructureType.Facility) //guid=1
|
||||
building.Position = Vector3(1, 0, 0)
|
||||
building.Zone = zone
|
||||
building.Amenities = gen
|
||||
building.PlayersInSOI = List(player1, player2)
|
||||
val buildingProbe = TestProbe()
|
||||
building.Actor = buildingProbe.ref
|
||||
|
||||
guid.register(building, 1)
|
||||
guid.register(gen, 2)
|
||||
guid.register(player1, 3)
|
||||
guid.register(player2, 4)
|
||||
|
||||
val weapon = Tool(GlobalDefinitions.phoenix) //decimator
|
||||
val projectile = weapon.Projectile
|
||||
val resolved = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
Projectile(
|
||||
projectile,
|
||||
weapon.Definition,
|
||||
weapon.FireMode,
|
||||
PlayerSource(player1),
|
||||
0,
|
||||
Vector3(2, 0, 0),
|
||||
Vector3(-1, 0, 0)
|
||||
),
|
||||
SourceEntry(gen),
|
||||
gen.DamageModel,
|
||||
Vector3(1, 0, 0)
|
||||
)
|
||||
val applyDamageTo = resolved.damage_model.Calculate(resolved)
|
||||
expectNoMessage(200 milliseconds)
|
||||
//we're not testing that the math is correct
|
||||
|
||||
"GeneratorControl" should {
|
||||
"kill players when the generator is destroyed" in {
|
||||
gen.Health = 1 //no matter what, the next shot destroys the generator
|
||||
assert(gen.Health == 1)
|
||||
assert(!gen.Destroyed)
|
||||
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)
|
||||
assert(
|
||||
msg_avatar1.head match {
|
||||
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 16)) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar1(1) match {
|
||||
case AvatarServiceMessage("TestCharacter2", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 16)) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(gen.Health == 1)
|
||||
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)
|
||||
assert(
|
||||
msg_building match {
|
||||
case Building.AmenityStateChange(o) => o eq gen
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar2.head match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar2(1) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.Destroy(PlanetSideGUID(2), _, _, Vector3(1, 0, 0))) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar2(2) match {
|
||||
case AvatarServiceMessage(
|
||||
"test",
|
||||
AvatarAction.SendResponse(_, TriggerEffectMessage(PlanetSideGUID(2), "explosion_generator", None, None))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_player1 match {
|
||||
case _ @Player.Die() => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(gen.Health == 0)
|
||||
assert(gen.Destroyed)
|
||||
assert(gen.Condition == PlanetSideGeneratorState.Destroyed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GeneratorControlNotDestroyTwice extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(10))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
|
||||
GUID(guid)
|
||||
}
|
||||
val building = Building("test-building", 1, 1, zone, StructureType.Facility) //guid=1
|
||||
val gen = Generator(GlobalDefinitions.generator) //guid=2
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=3
|
||||
player1.Spawn()
|
||||
guid.register(building, 1)
|
||||
guid.register(gen, 2)
|
||||
guid.register(player1, 3)
|
||||
building.Position = Vector3(1, 0, 0)
|
||||
building.Zone = zone
|
||||
building.Amenities = gen
|
||||
gen.Position = Vector3(1, 0, 0)
|
||||
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
||||
val activityProbe = TestProbe()
|
||||
val avatarProbe = TestProbe()
|
||||
val buildingProbe = TestProbe()
|
||||
zone.Activity = activityProbe.ref
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
building.Actor = buildingProbe.ref
|
||||
|
||||
val weapon = Tool(GlobalDefinitions.phoenix) //decimator
|
||||
val projectile = weapon.Projectile
|
||||
val resolved = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
Projectile(
|
||||
projectile,
|
||||
weapon.Definition,
|
||||
weapon.FireMode,
|
||||
PlayerSource(player1),
|
||||
0,
|
||||
Vector3(2, 0, 0),
|
||||
Vector3(-1, 0, 0)
|
||||
),
|
||||
SourceEntry(gen),
|
||||
gen.DamageModel,
|
||||
Vector3(1, 0, 0)
|
||||
)
|
||||
val applyDamageTo = resolved.damage_model.Calculate(resolved)
|
||||
expectNoMessage(200 milliseconds)
|
||||
//we're not testing that the math is correct
|
||||
|
||||
"GeneratorControl" should {
|
||||
"not send a status update if destroyed and partially repaired, but destroyed again" in {
|
||||
//damaged, not yet restored, but will not be destroyed again within one shot
|
||||
val originalHealth = gen.Health = gen.Definition.DamageDestroysAt + 1
|
||||
gen.Condition = PlanetSideGeneratorState.Destroyed //initial state manip
|
||||
gen.Destroyed = true
|
||||
assert(gen.Destroyed)
|
||||
assert(originalHealth < gen.Definition.DefaultHealth)
|
||||
assert(originalHealth < gen.Definition.RepairRestoresAt)
|
||||
assert(originalHealth > gen.Definition.DamageDestroysAt)
|
||||
|
||||
gen.Actor ! Vitality.Damage(applyDamageTo)
|
||||
avatarProbe.expectNoMessage(500 milliseconds)
|
||||
activityProbe.receiveOne(500 milliseconds)
|
||||
buildingProbe.expectNoMessage(1000 milliseconds)
|
||||
assert(gen.Health < originalHealth)
|
||||
assert(gen.Destroyed)
|
||||
assert(originalHealth < gen.Definition.DefaultHealth)
|
||||
assert(originalHealth < gen.Definition.RepairRestoresAt)
|
||||
assert(gen.Health <= gen.Definition.DamageDestroysAt)
|
||||
|
||||
//damaged, not yet restored, and would have been destroyed with next shot
|
||||
gen.Health = 1
|
||||
assert(gen.Health == 1)
|
||||
assert(gen.Destroyed)
|
||||
gen.Actor ! Vitality.Damage(applyDamageTo)
|
||||
avatarProbe.expectNoMessage(500 milliseconds)
|
||||
activityProbe.receiveOne(500 milliseconds) //activity alert occurs because this was not a kill shot
|
||||
buildingProbe.expectNoMessage(1000 milliseconds)
|
||||
assert(gen.Health == 0)
|
||||
assert(gen.Destroyed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GeneratorControlNotDamageIfExplodingTest extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(5))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
val avatarProbe = TestProbe()
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
val activityProbe = TestProbe()
|
||||
zone.Activity = activityProbe.ref
|
||||
|
||||
val gen = Generator(GlobalDefinitions.generator) //guid=2
|
||||
gen.Position = Vector3(1, 0, 0)
|
||||
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=3
|
||||
player1.Position = Vector3(14, 0, 0) //<14m from generator; dies
|
||||
player1.Spawn()
|
||||
val player1Probe = TestProbe()
|
||||
player1.Actor = player1Probe.ref
|
||||
|
||||
val building = Building("test-building", 1, 1, zone, StructureType.Facility) //guid=1
|
||||
building.Position = Vector3(1, 0, 0)
|
||||
building.Zone = zone
|
||||
building.Amenities = gen
|
||||
building.PlayersInSOI = List(player1)
|
||||
val buildingProbe = TestProbe()
|
||||
building.Actor = buildingProbe.ref
|
||||
|
||||
guid.register(building, 1)
|
||||
guid.register(gen, 2)
|
||||
guid.register(player1, 3)
|
||||
|
||||
val weapon = Tool(GlobalDefinitions.phoenix) //decimator
|
||||
val projectile = weapon.Projectile
|
||||
val resolved = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
Projectile(
|
||||
projectile,
|
||||
weapon.Definition,
|
||||
weapon.FireMode,
|
||||
PlayerSource(player1),
|
||||
0,
|
||||
Vector3(2, 0, 0),
|
||||
Vector3(-1, 0, 0)
|
||||
),
|
||||
SourceEntry(gen),
|
||||
gen.DamageModel,
|
||||
Vector3(1, 0, 0)
|
||||
)
|
||||
val applyDamageTo = resolved.damage_model.Calculate(resolved)
|
||||
expectNoMessage(200 milliseconds)
|
||||
//we're not testing that the math is correct
|
||||
|
||||
"GeneratorControl" should {
|
||||
"not damage if the generator is going to explode" in {
|
||||
gen.Health = 1 //no matter what, the next shot destroys the generator
|
||||
assert(gen.Health == 1)
|
||||
assert(!gen.Destroyed)
|
||||
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)
|
||||
assert(
|
||||
msg_avatar match {
|
||||
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 16)) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(gen.Health == 1)
|
||||
assert(!gen.Destroyed)
|
||||
assert(gen.Condition == PlanetSideGeneratorState.Normal)
|
||||
//going to explode state
|
||||
|
||||
//once
|
||||
gen.Actor ! Vitality.Damage(applyDamageTo)
|
||||
avatarProbe.expectNoMessage(500 milliseconds)
|
||||
buildingProbe.expectNoMessage(200 milliseconds)
|
||||
player1Probe.expectNoMessage(200 milliseconds)
|
||||
assert(gen.Health == 1)
|
||||
//twice
|
||||
gen.Actor ! Vitality.Damage(applyDamageTo)
|
||||
avatarProbe.expectNoMessage(500 milliseconds)
|
||||
buildingProbe.expectNoMessage(200 milliseconds)
|
||||
player1Probe.expectNoMessage(200 milliseconds)
|
||||
assert(gen.Health == 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GeneratorControlNotRepairIfExplodingTest extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(5))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
val avatarProbe = TestProbe()
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
val activityProbe = TestProbe()
|
||||
zone.Activity = activityProbe.ref
|
||||
|
||||
val gen = Generator(GlobalDefinitions.generator) //guid=2
|
||||
gen.Position = Vector3(1, 0, 0)
|
||||
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=3
|
||||
player1.Position = Vector3(14, 0, 0) //<14m from generator; dies
|
||||
player1.Spawn()
|
||||
val player1Probe = TestProbe()
|
||||
player1.Actor = player1Probe.ref
|
||||
|
||||
val building = Building("test-building", 1, 1, zone, StructureType.Facility) //guid=1
|
||||
building.Position = Vector3(1, 0, 0)
|
||||
building.Zone = zone
|
||||
building.Amenities = gen
|
||||
building.PlayersInSOI = List(player1)
|
||||
val buildingProbe = TestProbe()
|
||||
building.Actor = buildingProbe.ref
|
||||
|
||||
guid.register(building, 1)
|
||||
guid.register(gen, 2)
|
||||
guid.register(player1, 3)
|
||||
|
||||
val weapon = Tool(GlobalDefinitions.phoenix) //decimator
|
||||
val projectile = weapon.Projectile
|
||||
val resolved = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
Projectile(
|
||||
projectile,
|
||||
weapon.Definition,
|
||||
weapon.FireMode,
|
||||
PlayerSource(player1),
|
||||
0,
|
||||
Vector3(2, 0, 0),
|
||||
Vector3(-1, 0, 0)
|
||||
),
|
||||
SourceEntry(gen),
|
||||
gen.DamageModel,
|
||||
Vector3(1, 0, 0)
|
||||
)
|
||||
val applyDamageTo = resolved.damage_model.Calculate(resolved)
|
||||
|
||||
val tool = Tool(GlobalDefinitions.nano_dispenser) //4 & 5
|
||||
guid.register(tool, 4)
|
||||
guid.register(tool.AmmoSlot.Box, 5)
|
||||
expectNoMessage(200 milliseconds)
|
||||
//we're not testing that the math is correct
|
||||
|
||||
"GeneratorControl" should {
|
||||
"not repair if the generator is going to explode" in {
|
||||
gen.Health = 1 //no matter what, the next shot destroys the generator
|
||||
assert(gen.Health == 1)
|
||||
assert(!gen.Destroyed)
|
||||
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)
|
||||
assert(
|
||||
msg_avatar1 match {
|
||||
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 16)) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(gen.Health == 1)
|
||||
assert(!gen.Destroyed)
|
||||
assert(gen.Condition == PlanetSideGeneratorState.Normal)
|
||||
//going to explode state
|
||||
|
||||
//once
|
||||
gen.Actor ! CommonMessages.Use(player1, Some(tool)) //repair?
|
||||
avatarProbe.expectNoMessage(1000 milliseconds) //no messages
|
||||
buildingProbe.expectNoMessage(200 milliseconds)
|
||||
player1Probe.expectNoMessage(200 milliseconds)
|
||||
assert(gen.Health == 1)
|
||||
//twice
|
||||
gen.Actor ! CommonMessages.Use(player1, Some(tool)) //repair?
|
||||
avatarProbe.expectNoMessage(1000 milliseconds) //no messages
|
||||
buildingProbe.expectNoMessage(200 milliseconds)
|
||||
player1Probe.expectNoMessage(200 milliseconds)
|
||||
assert(gen.Health == 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GeneratorControlRepairPastRestorePoint extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(5))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
val avatarProbe = TestProbe()
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
val activityProbe = TestProbe()
|
||||
zone.Activity = activityProbe.ref
|
||||
|
||||
val gen = Generator(GlobalDefinitions.generator) //guid=2
|
||||
gen.Position = Vector3(1, 0, 0)
|
||||
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=3
|
||||
player1.Position = Vector3(14, 0, 0) //<14m from generator; dies
|
||||
player1.Spawn()
|
||||
val player1Probe = TestProbe()
|
||||
player1.Actor = player1Probe.ref
|
||||
|
||||
val building = Building("test-building", 1, 1, zone, StructureType.Facility) //guid=1
|
||||
building.Position = Vector3(1, 0, 0)
|
||||
building.Zone = zone
|
||||
building.Amenities = gen
|
||||
building.PlayersInSOI = List(player1)
|
||||
val buildingProbe = TestProbe()
|
||||
building.Actor = buildingProbe.ref
|
||||
|
||||
val tool = Tool(GlobalDefinitions.nano_dispenser) //4 & 5
|
||||
|
||||
guid.register(building, 1)
|
||||
guid.register(gen, 2)
|
||||
guid.register(player1, 3)
|
||||
guid.register(tool, 4)
|
||||
guid.register(tool.AmmoSlot.Box, 5)
|
||||
expectNoMessage(200 milliseconds)
|
||||
//we're not testing that the math is correct
|
||||
|
||||
"GeneratorControl" should {
|
||||
"send a status update if destroyed and repairing past the restoration point" in {
|
||||
val originalHealth = gen.Health = gen.Definition.RepairRestoresAt - 1 //damage
|
||||
gen.Condition = PlanetSideGeneratorState.Destroyed //initial state manip
|
||||
gen.Destroyed = true
|
||||
assert(originalHealth < gen.Definition.DefaultHealth)
|
||||
assert(originalHealth < gen.Definition.RepairRestoresAt)
|
||||
assert(gen.Destroyed)
|
||||
|
||||
gen.Actor ! CommonMessages.Use(player1, Some(tool)) //repair
|
||||
val msg_avatar = avatarProbe.receiveN(4, 500 milliseconds) //expected
|
||||
val msg_building = buildingProbe.receiveOne(200 milliseconds)
|
||||
assert(
|
||||
msg_avatar.head match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction
|
||||
.SendResponse(_, InventoryStateMessage(ValidPlanetSideGUID(5), _, ValidPlanetSideGUID(4), _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(1) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
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), _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_building match {
|
||||
case Building.AmenityStateChange(o) => o eq gen
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(gen.Condition == PlanetSideGeneratorState.Normal)
|
||||
assert(gen.Health > gen.Definition.RepairRestoresAt)
|
||||
assert(!gen.Destroyed)
|
||||
}
|
||||
}
|
||||
}
|
||||
103
src/test/scala/objects/IFFLockTest.scala
Normal file
103
src/test/scala/objects/IFFLockTest.scala
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.{ActorSystem, Props}
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
import net.psforever.objects.{Default, GlobalDefinitions, Player}
|
||||
import net.psforever.objects.serverobject.CommonMessages
|
||||
import net.psforever.objects.serverobject.locks.{IFFLock, IFFLockControl}
|
||||
import net.psforever.objects.serverobject.structures.{Building, StructureType}
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.types._
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
class IFFLockTest extends Specification {
|
||||
"IFFLock" should {
|
||||
"construct" in {
|
||||
IFFLock(GlobalDefinitions.lock_external)
|
||||
ok
|
||||
}
|
||||
|
||||
//TODO internal hacking logic will be re-written later
|
||||
|
||||
"keep track of its orientation as a North-corrected vector" in {
|
||||
val ulp = math.ulp(1)
|
||||
val lock = IFFLock(GlobalDefinitions.lock_external)
|
||||
|
||||
lock.Orientation = Vector3(0, 0, 0) //face North
|
||||
lock.Outwards.x < ulp mustEqual true
|
||||
lock.Outwards.y mustEqual 1
|
||||
|
||||
lock.Orientation = Vector3(0, 0, 90) //face East
|
||||
lock.Outwards.x mustEqual 1
|
||||
lock.Outwards.y < ulp mustEqual true
|
||||
|
||||
lock.Orientation = Vector3(0, 0, 180) //face South
|
||||
lock.Outwards.x < ulp mustEqual true
|
||||
lock.Outwards.y mustEqual -1
|
||||
|
||||
lock.Orientation = Vector3(0, 0, 270) //face West
|
||||
lock.Outwards.x mustEqual -1
|
||||
lock.Outwards.y < ulp mustEqual true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class IFFLockControl1Test extends ActorTest {
|
||||
"IFFLockControl" should {
|
||||
"construct" in {
|
||||
val lock = IFFLock(GlobalDefinitions.lock_external)
|
||||
lock.Actor = system.actorOf(Props(classOf[IFFLockControl], lock), "lock-control")
|
||||
assert(lock.Actor != Default.Actor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class IFFLockControl2Test extends ActorTest {
|
||||
"IFFLockControl" should {
|
||||
"can hack" in {
|
||||
val (player, lock) = IFFLockControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
player.GUID = PlanetSideGUID(1)
|
||||
assert(lock.HackedBy.isEmpty)
|
||||
|
||||
lock.Actor ! CommonMessages.Hack(player, lock)
|
||||
Thread.sleep(500L) //blocking
|
||||
assert(lock.HackedBy.nonEmpty) //TODO rewrite later
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class IFFLockControl3Test extends ActorTest {
|
||||
"IFFLockControl" should {
|
||||
"can clear hack" in {
|
||||
val (player, lock) = IFFLockControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
player.GUID = PlanetSideGUID(1)
|
||||
assert(lock.HackedBy.isEmpty)
|
||||
|
||||
lock.Actor ! CommonMessages.Hack(player, lock)
|
||||
Thread.sleep(500L) //blocking
|
||||
assert(lock.HackedBy.nonEmpty) //TODO rewrite later
|
||||
lock.Actor ! CommonMessages.ClearHack()
|
||||
Thread.sleep(500L) //blocking
|
||||
assert(lock.HackedBy.isEmpty) //TODO rewrite
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object IFFLockControlTest {
|
||||
def SetUpAgents(faction: PlanetSideEmpire.Value)(implicit system: ActorSystem): (Player, IFFLock) = {
|
||||
val lock = IFFLock(GlobalDefinitions.lock_external)
|
||||
lock.Actor = system.actorOf(Props(classOf[IFFLockControl], lock), "lock-control")
|
||||
lock.Owner = new Building(
|
||||
"Building",
|
||||
building_guid = 0,
|
||||
map_id = 0,
|
||||
Zone.Nowhere,
|
||||
StructureType.Building,
|
||||
GlobalDefinitions.building
|
||||
)
|
||||
lock.Owner.Faction = faction
|
||||
(Player(Avatar(0, "test", faction, CharacterGender.Male, 0, CharacterVoice.Mute)), lock)
|
||||
}
|
||||
}
|
||||
656
src/test/scala/objects/InventoryTest.scala
Normal file
656
src/test/scala/objects/InventoryTest.scala
Normal file
|
|
@ -0,0 +1,656 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects.{AmmoBox, SimpleItem, Tool}
|
||||
import net.psforever.objects.definition.SimpleItemDefinition
|
||||
import net.psforever.objects.inventory.{GridInventory, InventoryDisarrayException, InventoryItem, InventoryTile}
|
||||
import net.psforever.objects.GlobalDefinitions.{bullet_9mm, suppressor}
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import org.specs2.mutable._
|
||||
|
||||
import scala.collection.mutable.ListBuffer
|
||||
import scala.util.{Success, Failure}
|
||||
|
||||
class InventoryTest extends Specification {
|
||||
val bullet9mmBox1 = AmmoBox(bullet_9mm)
|
||||
bullet9mmBox1.GUID = PlanetSideGUID(1)
|
||||
val bullet9mmBox2 = AmmoBox(bullet_9mm)
|
||||
bullet9mmBox2.GUID = PlanetSideGUID(2)
|
||||
|
||||
"InventoryDisarrayException" should {
|
||||
"construct" in {
|
||||
InventoryDisarrayException("slot out of bounds")
|
||||
ok
|
||||
}
|
||||
|
||||
"construct (with Throwable)" in {
|
||||
InventoryDisarrayException("slot out of bounds", new Throwable())
|
||||
ok
|
||||
}
|
||||
}
|
||||
|
||||
"GridInventory" should {
|
||||
"construct" in {
|
||||
val obj: GridInventory = GridInventory()
|
||||
obj.TotalCapacity mustEqual 1
|
||||
obj.Capacity mustEqual 1
|
||||
}
|
||||
|
||||
"resize" in {
|
||||
val obj: GridInventory = GridInventory(9, 6)
|
||||
obj.TotalCapacity mustEqual 54
|
||||
obj.Capacity mustEqual 54
|
||||
obj.Size mustEqual 0
|
||||
}
|
||||
|
||||
"check for collision with inventory border" in {
|
||||
val obj: GridInventory = GridInventory(3, 3)
|
||||
//safe
|
||||
obj.CheckCollisionsAsList(0, 3, 3) mustEqual Success(Nil)
|
||||
//right
|
||||
obj.CheckCollisionsAsList(-1, 3, 3) match {
|
||||
case Failure(fail) =>
|
||||
fail.isInstanceOf[IndexOutOfBoundsException] mustEqual true
|
||||
case _ => ko
|
||||
}
|
||||
//left
|
||||
obj.CheckCollisionsAsList(1, 3, 3) match {
|
||||
case Failure(fail) =>
|
||||
fail.isInstanceOf[IndexOutOfBoundsException] mustEqual true
|
||||
case _ => ko
|
||||
}
|
||||
//bottom
|
||||
obj.CheckCollisionsAsList(3, 3, 3) match {
|
||||
case Failure(fail) =>
|
||||
fail.isInstanceOf[IndexOutOfBoundsException] mustEqual true
|
||||
case _ => ko
|
||||
}
|
||||
}
|
||||
|
||||
"check for item collision (right insert)" in {
|
||||
val obj: GridInventory = GridInventory(9, 6)
|
||||
obj += 0 -> bullet9mmBox1
|
||||
obj.Capacity mustEqual 45
|
||||
val w = bullet9mmBox2.Tile.Width
|
||||
val h = bullet9mmBox2.Tile.Height
|
||||
val list0 = obj.CheckCollisionsAsList(0, w, h)
|
||||
obj.CheckCollisionsAsList(0, w, h) match {
|
||||
case Success(list) => list.length mustEqual 1
|
||||
case Failure(_) => ko
|
||||
}
|
||||
val list1 = obj.CheckCollisionsAsList(1, w, h)
|
||||
list1 match {
|
||||
case Success(list) => list.length mustEqual 1
|
||||
case Failure(_) => ko
|
||||
}
|
||||
val list2 = obj.CheckCollisionsAsList(2, w, h)
|
||||
list2 match {
|
||||
case Success(list) => list.length mustEqual 1
|
||||
case Failure(_) => ko
|
||||
}
|
||||
val list3 = obj.CheckCollisionsAsList(3, w, h)
|
||||
list3 match {
|
||||
case Success(list) => list.isEmpty mustEqual true
|
||||
case Failure(_) => ko
|
||||
}
|
||||
obj.CheckCollisionsAsGrid(0, w, h) mustEqual list0
|
||||
obj.CheckCollisionsAsGrid(1, w, h) mustEqual list1
|
||||
obj.CheckCollisionsAsGrid(2, w, h) mustEqual list2
|
||||
obj.CheckCollisionsAsGrid(3, w, h) mustEqual list3
|
||||
obj.Clear()
|
||||
ok
|
||||
}
|
||||
|
||||
"check for item collision (left insert)" in {
|
||||
val obj: GridInventory = GridInventory(9, 6)
|
||||
obj += 3 -> bullet9mmBox1
|
||||
obj.Capacity mustEqual 45
|
||||
val w = bullet9mmBox2.Tile.Width
|
||||
val h = bullet9mmBox2.Tile.Height
|
||||
val list0 = obj.CheckCollisionsAsList(3, w, h)
|
||||
list0 match {
|
||||
case Success(list) => list.length mustEqual 1
|
||||
case Failure(_) => ko
|
||||
}
|
||||
val list1 = obj.CheckCollisionsAsList(2, w, h)
|
||||
list1 match {
|
||||
case Success(list) => list.length mustEqual 1
|
||||
case Failure(_) => ko
|
||||
}
|
||||
val list2 = obj.CheckCollisionsAsList(1, w, h)
|
||||
list2 match {
|
||||
case Success(list) => list.length mustEqual 1
|
||||
case Failure(_) => ko
|
||||
}
|
||||
val list3 = obj.CheckCollisionsAsList(0, w, h)
|
||||
list3 match {
|
||||
case Success(list) => list.isEmpty mustEqual true
|
||||
case Failure(_) => ko
|
||||
}
|
||||
obj.CheckCollisionsAsGrid(3, w, h) mustEqual list0
|
||||
obj.CheckCollisionsAsGrid(2, w, h) mustEqual list1
|
||||
obj.CheckCollisionsAsGrid(1, w, h) mustEqual list2
|
||||
obj.CheckCollisionsAsGrid(0, w, h) mustEqual list3
|
||||
obj.Clear()
|
||||
ok
|
||||
}
|
||||
|
||||
"check for item collision (below insert)" in {
|
||||
val obj: GridInventory = GridInventory(9, 6)
|
||||
obj += 0 -> bullet9mmBox1
|
||||
obj.Capacity mustEqual 45
|
||||
val w = bullet9mmBox2.Tile.Width
|
||||
val h = bullet9mmBox2.Tile.Height
|
||||
val list0 = obj.CheckCollisionsAsList(0, w, h)
|
||||
list0 match {
|
||||
case Success(list) => list.length mustEqual 1
|
||||
case Failure(_) => ko
|
||||
}
|
||||
val list1 = obj.CheckCollisionsAsList(9, w, h)
|
||||
list1 match {
|
||||
case Success(list) => list.length mustEqual 1
|
||||
case Failure(_) => ko
|
||||
}
|
||||
val list2 = obj.CheckCollisionsAsList(18, w, h)
|
||||
list2 match {
|
||||
case Success(list) => list.length mustEqual 1
|
||||
case Failure(_) => ko
|
||||
}
|
||||
val list3 = obj.CheckCollisionsAsList(27, w, h)
|
||||
list3 match {
|
||||
case Success(list) => list.isEmpty mustEqual true
|
||||
case Failure(_) => ko
|
||||
}
|
||||
obj.CheckCollisionsAsGrid(0, w, h) mustEqual list0
|
||||
obj.CheckCollisionsAsGrid(9, w, h) mustEqual list1
|
||||
obj.CheckCollisionsAsGrid(18, w, h) mustEqual list2
|
||||
obj.CheckCollisionsAsGrid(27, w, h) mustEqual list3
|
||||
obj.Clear()
|
||||
ok
|
||||
}
|
||||
|
||||
"check for item collision (above insert)" in {
|
||||
val obj: GridInventory = GridInventory(9, 6)
|
||||
obj += 27 -> bullet9mmBox1
|
||||
obj.Capacity mustEqual 45
|
||||
val w = bullet9mmBox2.Tile.Width
|
||||
val h = bullet9mmBox2.Tile.Height
|
||||
val list0 = obj.CheckCollisionsAsList(27, w, h)
|
||||
list0 match {
|
||||
case Success(list) => list.length mustEqual 1
|
||||
case Failure(_) => ko
|
||||
}
|
||||
val list1 = obj.CheckCollisionsAsList(18, w, h)
|
||||
list1 match {
|
||||
case Success(list) => list.length mustEqual 1
|
||||
case Failure(_) => ko
|
||||
}
|
||||
val list2 = obj.CheckCollisionsAsList(9, w, h)
|
||||
list2 match {
|
||||
case Success(list) => list.length mustEqual 1
|
||||
case Failure(_) => ko
|
||||
}
|
||||
val list3 = obj.CheckCollisionsAsList(0, w, h)
|
||||
list3 match {
|
||||
case Success(list) => list.isEmpty mustEqual true
|
||||
case Failure(_) => ko
|
||||
}
|
||||
obj.CheckCollisionsAsGrid(27, w, h) mustEqual list0
|
||||
obj.CheckCollisionsAsGrid(18, w, h) mustEqual list1
|
||||
obj.CheckCollisionsAsGrid(9, w, h) mustEqual list2
|
||||
obj.CheckCollisionsAsGrid(0, w, h) mustEqual list3
|
||||
obj.Clear()
|
||||
ok
|
||||
}
|
||||
|
||||
"check for item collision (diagonal insert)" in {
|
||||
/*
|
||||
Number indicates upper-left corner of attempted 3x3 insertion by list#
|
||||
0 - - - - - 2 - - - - -
|
||||
- 1 - - - 3 - - - - - -
|
||||
- - - - - - - - - - - -
|
||||
- - - X X X - - - - - -
|
||||
- - - X X X - - - - - -
|
||||
- 5 - X X 7 - - - - - -
|
||||
4 - - - - - 6 - - - - -
|
||||
- - - - - - - - - - - -
|
||||
- - - - - - - - - - - -
|
||||
*/
|
||||
val obj: GridInventory = GridInventory(12, 9)
|
||||
obj += 39 -> bullet9mmBox1
|
||||
obj.Capacity mustEqual 99 //108 - 9
|
||||
val w = bullet9mmBox2.Tile.Width
|
||||
val h = bullet9mmBox2.Tile.Height
|
||||
val list0 = obj.CheckCollisionsAsList(0, w, h)
|
||||
list0 match {
|
||||
case Success(list) => list.isEmpty mustEqual true
|
||||
case Failure(_) => ko
|
||||
}
|
||||
val list1 = obj.CheckCollisionsAsList(13, w, h)
|
||||
list1 match {
|
||||
case Success(list) => list.length mustEqual 1
|
||||
case Failure(_) => ko
|
||||
}
|
||||
val list2 = obj.CheckCollisionsAsList(6, w, h)
|
||||
list2 match {
|
||||
case Success(list) => list.isEmpty mustEqual true
|
||||
case Failure(_) => ko
|
||||
}
|
||||
val list3 = obj.CheckCollisionsAsList(17, w, h)
|
||||
list3 match {
|
||||
case Success(list) => list.length mustEqual 1
|
||||
case Failure(_) => ko
|
||||
}
|
||||
val list4 = obj.CheckCollisionsAsList(72, w, h)
|
||||
list4 match {
|
||||
case Success(list) => list.isEmpty mustEqual true
|
||||
case Failure(_) => ko
|
||||
}
|
||||
val list5 = obj.CheckCollisionsAsList(61, w, h)
|
||||
list5 match {
|
||||
case Success(list) => list.length mustEqual 1
|
||||
case Failure(_) => ko
|
||||
}
|
||||
val list6 = obj.CheckCollisionsAsList(78, w, h)
|
||||
list6 match {
|
||||
case Success(list) => list.isEmpty mustEqual true
|
||||
case Failure(_) => ko
|
||||
}
|
||||
val list7 = obj.CheckCollisionsAsList(65, w, h)
|
||||
list7 match {
|
||||
case Success(list) => list.length mustEqual 1
|
||||
case Failure(_) => ko
|
||||
}
|
||||
obj.CheckCollisionsAsGrid(0, w, h) mustEqual list0
|
||||
obj.CheckCollisionsAsGrid(13, w, h) mustEqual list1
|
||||
obj.CheckCollisionsAsGrid(6, w, h) mustEqual list2
|
||||
obj.CheckCollisionsAsGrid(17, w, h) mustEqual list3
|
||||
obj.CheckCollisionsAsGrid(72, w, h) mustEqual list4
|
||||
obj.CheckCollisionsAsGrid(61, w, h) mustEqual list5
|
||||
obj.CheckCollisionsAsGrid(78, w, h) mustEqual list6
|
||||
obj.CheckCollisionsAsGrid(65, w, h) mustEqual list7
|
||||
obj.Clear()
|
||||
ok
|
||||
}
|
||||
|
||||
"insert item" in {
|
||||
val obj: GridInventory = GridInventory(9, 6)
|
||||
obj.CheckCollisions(23, bullet9mmBox1) mustEqual Success(Nil)
|
||||
obj += 2 -> bullet9mmBox1
|
||||
obj.TotalCapacity mustEqual 54
|
||||
obj.Capacity mustEqual 45
|
||||
obj.Size mustEqual 1
|
||||
obj.hasItem(PlanetSideGUID(1)).contains(bullet9mmBox1) mustEqual true
|
||||
obj.Clear()
|
||||
obj.Size mustEqual 0
|
||||
}
|
||||
|
||||
"not insert into an invalid slot (n < 0)" in {
|
||||
val obj: GridInventory = GridInventory(9, 6)
|
||||
obj.Capacity mustEqual 54
|
||||
obj.Size mustEqual 0
|
||||
obj.Insert(-1, bullet9mmBox1) must throwA[IndexOutOfBoundsException]
|
||||
obj.Capacity mustEqual 54
|
||||
obj.Size mustEqual 0
|
||||
}
|
||||
|
||||
"not insert into an invalid slot (n > capacity)" in {
|
||||
val obj: GridInventory = GridInventory(9, 6)
|
||||
obj.Capacity mustEqual 54
|
||||
obj.Size mustEqual 0
|
||||
obj.Insert(55, bullet9mmBox1) must throwA[IndexOutOfBoundsException]
|
||||
obj.Capacity mustEqual 54
|
||||
obj.Size mustEqual 0
|
||||
}
|
||||
|
||||
"block insertion if item collision" in {
|
||||
val obj: GridInventory = GridInventory(9, 6)
|
||||
obj += 0 -> bullet9mmBox1
|
||||
obj.Capacity mustEqual 45
|
||||
obj.hasItem(PlanetSideGUID(1)).contains(bullet9mmBox1) mustEqual true
|
||||
obj += 2 -> bullet9mmBox2
|
||||
obj.hasItem(PlanetSideGUID(2)).isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"insert items quickly (risk overwriting entries)" in {
|
||||
val obj: GridInventory = GridInventory(6, 6)
|
||||
(obj += 0 -> bullet9mmBox1) mustEqual true
|
||||
val collision1 = obj.CheckCollisions(0, 1, 1)
|
||||
obj.CheckCollisions(1, 1, 1) mustEqual collision1
|
||||
obj.CheckCollisions(2, 1, 1) mustEqual collision1
|
||||
obj.CheckCollisions(6, 1, 1) mustEqual collision1
|
||||
obj.CheckCollisions(7, 1, 1) mustEqual collision1
|
||||
obj.CheckCollisions(8, 1, 1) mustEqual collision1
|
||||
obj.CheckCollisions(12, 1, 1) mustEqual collision1
|
||||
obj.CheckCollisions(13, 1, 1) mustEqual collision1
|
||||
obj.CheckCollisions(14, 1, 1) mustEqual collision1
|
||||
|
||||
(obj += 7 -> bullet9mmBox2) mustEqual false //can not insert overlapping object
|
||||
obj.CheckCollisions(0, 1, 1) mustEqual collision1
|
||||
obj.CheckCollisions(1, 1, 1) mustEqual collision1
|
||||
obj.CheckCollisions(2, 1, 1) mustEqual collision1
|
||||
obj.CheckCollisions(6, 1, 1) mustEqual collision1
|
||||
obj.CheckCollisions(7, 1, 1) mustEqual collision1
|
||||
obj.CheckCollisions(8, 1, 1) mustEqual collision1
|
||||
obj.CheckCollisions(12, 1, 1) mustEqual collision1
|
||||
obj.CheckCollisions(13, 1, 1) mustEqual collision1
|
||||
obj.CheckCollisions(14, 1, 1) mustEqual collision1
|
||||
|
||||
obj.InsertQuickly(7, bullet9mmBox2) mustEqual true //overwrite
|
||||
val collision2 = obj.CheckCollisions(7, 1, 1)
|
||||
obj.CheckCollisions(0, 1, 1) mustEqual collision1
|
||||
obj.CheckCollisions(1, 1, 1) mustEqual collision1
|
||||
obj.CheckCollisions(2, 1, 1) mustEqual collision1
|
||||
obj.CheckCollisions(6, 1, 1) mustEqual collision1
|
||||
obj.CheckCollisions(7, 1, 1) mustEqual collision2
|
||||
obj.CheckCollisions(8, 1, 1) mustEqual collision2
|
||||
obj.CheckCollisions(12, 1, 1) mustEqual collision1
|
||||
obj.CheckCollisions(13, 1, 1) mustEqual collision2
|
||||
obj.CheckCollisions(14, 1, 1) mustEqual collision2
|
||||
}
|
||||
|
||||
"clear all items" in {
|
||||
val obj: GridInventory = GridInventory(9, 6)
|
||||
obj += 2 -> bullet9mmBox1
|
||||
obj.Size mustEqual 1
|
||||
obj.hasItem(PlanetSideGUID(1)).contains(bullet9mmBox1) mustEqual true
|
||||
obj.Clear()
|
||||
obj.Size mustEqual 0
|
||||
obj.hasItem(PlanetSideGUID(1)).isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"remove item" in {
|
||||
val obj: GridInventory = GridInventory(9, 6)
|
||||
obj += 0 -> bullet9mmBox1
|
||||
obj.hasItem(PlanetSideGUID(1)).contains(bullet9mmBox1) mustEqual true
|
||||
obj -= PlanetSideGUID(1)
|
||||
obj.hasItem(PlanetSideGUID(1)).isEmpty mustEqual true
|
||||
obj.Clear()
|
||||
ok
|
||||
}
|
||||
|
||||
"fail to remove from an invalid slot (n < 0)" in {
|
||||
val obj: GridInventory = GridInventory(9, 6)
|
||||
(obj -= -1) mustEqual false
|
||||
}
|
||||
|
||||
"fail to remove from an invalid slot (n > capacity)" in {
|
||||
val obj: GridInventory = GridInventory(9, 6)
|
||||
(obj -= 55) mustEqual false
|
||||
}
|
||||
|
||||
"unblock insertion on item removal" in {
|
||||
val obj: GridInventory = GridInventory(9, 6)
|
||||
obj.CheckCollisions(23, bullet9mmBox1) mustEqual Success(Nil)
|
||||
obj += 23 -> bullet9mmBox1
|
||||
obj.hasItem(PlanetSideGUID(1)).contains(bullet9mmBox1) mustEqual true
|
||||
obj.CheckCollisions(23, bullet9mmBox1) mustEqual Success(1 :: Nil)
|
||||
obj -= PlanetSideGUID(1)
|
||||
obj.hasItem(PlanetSideGUID(1)).isEmpty mustEqual true
|
||||
obj.CheckCollisions(23, bullet9mmBox1) mustEqual Success(Nil)
|
||||
obj.Clear()
|
||||
ok
|
||||
}
|
||||
|
||||
"attempt to fit an item" in {
|
||||
val sampleDef22 = new SimpleItemDefinition(149)
|
||||
sampleDef22.Tile = InventoryTile.Tile22
|
||||
val sampleDef33 = new SimpleItemDefinition(149)
|
||||
sampleDef33.Tile = InventoryTile.Tile33
|
||||
val sampleDef63 = new SimpleItemDefinition(149)
|
||||
sampleDef63.Tile = InventoryTile.Tile63
|
||||
|
||||
val obj: GridInventory = GridInventory(9, 9)
|
||||
obj += 0 -> SimpleItem(sampleDef22)
|
||||
obj += 20 -> SimpleItem(sampleDef63)
|
||||
obj += 56 -> SimpleItem(sampleDef33)
|
||||
obj.Fit(InventoryTile.Tile33) match {
|
||||
case Some(x) =>
|
||||
x mustEqual 50
|
||||
case None =>
|
||||
ko
|
||||
}
|
||||
ok
|
||||
}
|
||||
|
||||
"attempt to fit all the items" in {
|
||||
val sampleDef1 = new SimpleItemDefinition(149)
|
||||
sampleDef1.Tile = InventoryTile.Tile22
|
||||
val sampleDef2 = new SimpleItemDefinition(149)
|
||||
sampleDef2.Tile = InventoryTile.Tile33
|
||||
val sampleDef3 = new SimpleItemDefinition(149)
|
||||
sampleDef3.Tile = InventoryTile.Tile42
|
||||
val sampleDef4 = new SimpleItemDefinition(149)
|
||||
sampleDef4.Tile = InventoryTile.Tile63
|
||||
|
||||
val list: ListBuffer[InventoryItem] = ListBuffer()
|
||||
list += new InventoryItem(SimpleItem(sampleDef2), -1)
|
||||
list += new InventoryItem(SimpleItem(sampleDef3), -1)
|
||||
list += new InventoryItem(SimpleItem(sampleDef1), -1)
|
||||
list += new InventoryItem(SimpleItem(sampleDef4), -1)
|
||||
list += new InventoryItem(SimpleItem(sampleDef1), -1)
|
||||
list += new InventoryItem(SimpleItem(sampleDef4), -1)
|
||||
list += new InventoryItem(SimpleItem(sampleDef2), -1)
|
||||
list += new InventoryItem(SimpleItem(sampleDef3), -1)
|
||||
val obj: GridInventory = GridInventory(9, 9)
|
||||
|
||||
val (elements, out) = GridInventory.recoverInventory(list.toList, obj)
|
||||
elements.length mustEqual 6
|
||||
out.length mustEqual 2
|
||||
elements.foreach(item => {
|
||||
obj.Insert(item.start, item.obj) mustEqual true
|
||||
})
|
||||
out.head.Definition.Tile mustEqual InventoryTile.Tile22 //did not fit
|
||||
out(1).Definition.Tile mustEqual InventoryTile.Tile22 //did not fit
|
||||
ok
|
||||
}
|
||||
|
||||
"confirm integrity of inventory as a grid" in {
|
||||
val obj: GridInventory = GridInventory(6, 6)
|
||||
(obj += 0 -> bullet9mmBox1) mustEqual true
|
||||
(obj += 21 -> bullet9mmBox2) mustEqual true
|
||||
//artificially pollute the inventory grid-space
|
||||
obj.SetCells(10, 1, 1, 3)
|
||||
obj.SetCells(19, 2, 2, 4)
|
||||
obj.ElementsOnGridMatchList() mustEqual 5 //number of misses repaired
|
||||
}
|
||||
|
||||
"confirm integrity of inventory as a list (no overlap)" in {
|
||||
val obj: GridInventory = GridInventory(9, 9)
|
||||
val gun = Tool(suppressor)
|
||||
obj.InsertQuickly(0, gun)
|
||||
obj.InsertQuickly(33, bullet9mmBox1)
|
||||
//nothing should overlap
|
||||
val lists = obj.ElementsInListCollideInGrid()
|
||||
lists.size mustEqual 0
|
||||
}
|
||||
|
||||
"confirm integrity of inventory as a list (normal overlap)" in {
|
||||
val obj: GridInventory = GridInventory(9, 9)
|
||||
val gun = Tool(suppressor)
|
||||
val bullet9mmBox3 = AmmoBox(bullet_9mm)
|
||||
obj.InsertQuickly(0, gun)
|
||||
obj.InsertQuickly(18, bullet9mmBox1)
|
||||
obj.InsertQuickly(38, bullet9mmBox2)
|
||||
obj.InsertQuickly(33, bullet9mmBox3)
|
||||
//gun and box1 should overlap
|
||||
//box1 and box2 should overlap
|
||||
//box3 should not overlap with anything
|
||||
val lists = obj.ElementsInListCollideInGrid()
|
||||
lists.size mustEqual 2
|
||||
lists.foreach { list =>
|
||||
val out = list.map { _.obj }
|
||||
if (out.size == 2 && out.contains(gun) && out.contains(bullet9mmBox1)) {
|
||||
ok
|
||||
} else if (out.size == 2 && out.contains(bullet9mmBox1) && out.contains(bullet9mmBox2)) {
|
||||
ok
|
||||
} else {
|
||||
ko
|
||||
}
|
||||
}
|
||||
ok
|
||||
}
|
||||
|
||||
"confirm integrity of inventory as a list (triple overlap)" in {
|
||||
val obj: GridInventory = GridInventory(9, 9)
|
||||
val gun = Tool(suppressor)
|
||||
val bullet9mmBox3 = AmmoBox(bullet_9mm)
|
||||
val bullet9mmBox4 = AmmoBox(bullet_9mm)
|
||||
obj.InsertQuickly(0, gun)
|
||||
obj.InsertQuickly(18, bullet9mmBox1)
|
||||
obj.InsertQuickly(36, bullet9mmBox2)
|
||||
obj.InsertQuickly(38, bullet9mmBox3)
|
||||
obj.InsertQuickly(33, bullet9mmBox4)
|
||||
//gun and box1 should overlap
|
||||
//box1, box2, and box3 should overlap
|
||||
//box4 should not overlap with anything
|
||||
val lists = obj.ElementsInListCollideInGrid()
|
||||
lists.size mustEqual 2
|
||||
lists.foreach { list =>
|
||||
val out = list.map { _.obj }
|
||||
if (out.size == 2 && out.contains(gun) && out.contains(bullet9mmBox1)) {
|
||||
ok
|
||||
} else if (
|
||||
out.size == 3 && out.contains(bullet9mmBox1) && out.contains(bullet9mmBox2) && out.contains(bullet9mmBox3)
|
||||
) {
|
||||
ok
|
||||
} else {
|
||||
ko
|
||||
}
|
||||
}
|
||||
ok
|
||||
}
|
||||
}
|
||||
|
||||
"InventoryEquiupmentSlot" should {
|
||||
"insert, collide, insert" in {
|
||||
val obj: GridInventory = GridInventory(7, 7)
|
||||
obj.Slot(16).Equipment = bullet9mmBox1
|
||||
//confirm all squares
|
||||
obj.Slot(8).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(9).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(10).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(11).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(12).Equipment.nonEmpty mustEqual false
|
||||
//
|
||||
obj.Slot(15).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(16).Equipment.nonEmpty mustEqual true
|
||||
obj.Slot(17).Equipment.nonEmpty mustEqual true
|
||||
obj.Slot(18).Equipment.nonEmpty mustEqual true
|
||||
obj.Slot(19).Equipment.nonEmpty mustEqual false
|
||||
//
|
||||
obj.Slot(22).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(23).Equipment.nonEmpty mustEqual true
|
||||
obj.Slot(24).Equipment.nonEmpty mustEqual true
|
||||
obj.Slot(25).Equipment.nonEmpty mustEqual true
|
||||
obj.Slot(26).Equipment.nonEmpty mustEqual false
|
||||
//
|
||||
obj.Slot(29).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(30).Equipment.nonEmpty mustEqual true
|
||||
obj.Slot(31).Equipment.nonEmpty mustEqual true
|
||||
obj.Slot(32).Equipment.nonEmpty mustEqual true
|
||||
obj.Slot(33).Equipment.nonEmpty mustEqual false
|
||||
//
|
||||
obj.Slot(36).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(37).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(38).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(39).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(40).Equipment.nonEmpty mustEqual false
|
||||
//
|
||||
//remove
|
||||
obj.Slot(16).Equipment = None
|
||||
obj.Slot(8).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(9).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(10).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(11).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(12).Equipment.nonEmpty mustEqual false
|
||||
//
|
||||
obj.Slot(15).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(16).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(17).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(18).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(19).Equipment.nonEmpty mustEqual false
|
||||
//
|
||||
obj.Slot(22).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(23).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(24).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(25).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(26).Equipment.nonEmpty mustEqual false
|
||||
//
|
||||
obj.Slot(29).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(30).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(31).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(32).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(33).Equipment.nonEmpty mustEqual false
|
||||
//
|
||||
obj.Slot(36).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(37).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(38).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(39).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(40).Equipment.nonEmpty mustEqual false
|
||||
//insert again
|
||||
obj.Slot(16).Equipment = bullet9mmBox2
|
||||
obj.Slot(8).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(9).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(10).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(11).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(12).Equipment.nonEmpty mustEqual false
|
||||
//
|
||||
obj.Slot(15).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(16).Equipment.nonEmpty mustEqual true
|
||||
obj.Slot(17).Equipment.nonEmpty mustEqual true
|
||||
obj.Slot(18).Equipment.nonEmpty mustEqual true
|
||||
obj.Slot(19).Equipment.nonEmpty mustEqual false
|
||||
//
|
||||
obj.Slot(22).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(23).Equipment.nonEmpty mustEqual true
|
||||
obj.Slot(24).Equipment.nonEmpty mustEqual true
|
||||
obj.Slot(25).Equipment.nonEmpty mustEqual true
|
||||
obj.Slot(26).Equipment.nonEmpty mustEqual false
|
||||
//
|
||||
obj.Slot(29).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(30).Equipment.nonEmpty mustEqual true
|
||||
obj.Slot(31).Equipment.nonEmpty mustEqual true
|
||||
obj.Slot(32).Equipment.nonEmpty mustEqual true
|
||||
obj.Slot(33).Equipment.nonEmpty mustEqual false
|
||||
//
|
||||
obj.Slot(36).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(37).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(38).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(39).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(40).Equipment.nonEmpty mustEqual false
|
||||
//
|
||||
//remove
|
||||
obj.Slot(16).Equipment = None
|
||||
obj.Slot(8).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(9).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(10).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(11).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(12).Equipment.nonEmpty mustEqual false
|
||||
//
|
||||
obj.Slot(15).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(16).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(17).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(18).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(19).Equipment.nonEmpty mustEqual false
|
||||
//
|
||||
obj.Slot(22).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(23).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(24).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(25).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(26).Equipment.nonEmpty mustEqual false
|
||||
//
|
||||
obj.Slot(29).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(30).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(31).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(32).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(33).Equipment.nonEmpty mustEqual false
|
||||
//
|
||||
obj.Slot(36).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(37).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(38).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(39).Equipment.nonEmpty mustEqual false
|
||||
obj.Slot(40).Equipment.nonEmpty mustEqual false
|
||||
}
|
||||
}
|
||||
}
|
||||
152
src/test/scala/objects/LoadoutTest.scala
Normal file
152
src/test/scala/objects/LoadoutTest.scala
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.loadouts._
|
||||
import net.psforever.types.{CharacterGender, CharacterVoice, ExoSuitType, PlanetSideEmpire}
|
||||
import net.psforever.objects.GlobalDefinitions._
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
import org.specs2.mutable._
|
||||
|
||||
class LoadoutTest extends Specification {
|
||||
val avatar = Avatar(0, "TestCharacter", PlanetSideEmpire.VS, CharacterGender.Female, 41, CharacterVoice.Voice1)
|
||||
|
||||
def CreatePlayer(): Player = {
|
||||
new Player(avatar) {
|
||||
Slot(0).Equipment = Tool(beamer)
|
||||
Slot(2).Equipment = Tool(suppressor)
|
||||
Slot(4).Equipment = Tool(forceblade)
|
||||
Slot(6).Equipment = ConstructionItem(ace)
|
||||
Slot(9).Equipment = AmmoBox(bullet_9mm)
|
||||
Slot(12).Equipment = AmmoBox(bullet_9mm)
|
||||
Slot(33).Equipment = Kit(medkit)
|
||||
Slot(39).Equipment = SimpleItem(remote_electronics_kit)
|
||||
}
|
||||
}
|
||||
|
||||
"test sample player" in {
|
||||
val player = CreatePlayer()
|
||||
player.Holsters()(0).Equipment.get.Definition mustEqual beamer
|
||||
player.Holsters()(2).Equipment.get.Definition mustEqual suppressor
|
||||
player.Holsters()(4).Equipment.get.Definition mustEqual forceblade
|
||||
player.Slot(6).Equipment.get.Definition mustEqual ace
|
||||
player.Slot(9).Equipment.get.Definition mustEqual bullet_9mm
|
||||
player.Slot(12).Equipment.get.Definition mustEqual bullet_9mm
|
||||
player.Slot(33).Equipment.get.Definition mustEqual medkit
|
||||
player.Slot(39).Equipment.get.Definition mustEqual remote_electronics_kit
|
||||
}
|
||||
|
||||
"create a loadout that contains a player's inventory" in {
|
||||
val player = CreatePlayer()
|
||||
val obj = Loadout.Create(player, "test").asInstanceOf[InfantryLoadout]
|
||||
|
||||
obj.label mustEqual "test"
|
||||
obj.exosuit mustEqual ExoSuitType.Standard
|
||||
obj.subtype mustEqual 0
|
||||
|
||||
obj.visible_slots.length mustEqual 3
|
||||
val holsters = obj.visible_slots.sortBy(_.index)
|
||||
holsters.head.index mustEqual 0
|
||||
holsters.head.item.asInstanceOf[Loadout.ShorthandTool].definition mustEqual beamer
|
||||
holsters(1).index mustEqual 2
|
||||
holsters(1).item.asInstanceOf[Loadout.ShorthandTool].definition mustEqual suppressor
|
||||
holsters(2).index mustEqual 4
|
||||
holsters(2).item.asInstanceOf[Loadout.ShorthandTool].definition mustEqual forceblade
|
||||
|
||||
obj.inventory.length mustEqual 5
|
||||
val inventory = obj.inventory.sortBy(_.index)
|
||||
inventory.head.index mustEqual 6
|
||||
inventory.head.item.asInstanceOf[Loadout.ShorthandConstructionItem].definition mustEqual ace
|
||||
inventory(1).index mustEqual 9
|
||||
inventory(1).item.asInstanceOf[Loadout.ShorthandAmmoBox].definition mustEqual bullet_9mm
|
||||
inventory(2).index mustEqual 12
|
||||
inventory(2).item.asInstanceOf[Loadout.ShorthandAmmoBox].definition mustEqual bullet_9mm
|
||||
inventory(3).index mustEqual 33
|
||||
inventory(3).item.asInstanceOf[Loadout.ShorthandKit].definition mustEqual medkit
|
||||
inventory(4).index mustEqual 39
|
||||
inventory(4).item.asInstanceOf[Loadout.ShorthandSimpleItem].definition mustEqual remote_electronics_kit
|
||||
}
|
||||
|
||||
"create a loadout that contains a vehicle's inventory" in {
|
||||
val vehicle = Vehicle(mediumtransport)
|
||||
vehicle.Inventory += 30 -> AmmoBox(bullet_9mm)
|
||||
vehicle.Inventory += 33 -> AmmoBox(bullet_9mm_AP)
|
||||
val obj = Loadout.Create(vehicle, "test").asInstanceOf[VehicleLoadout]
|
||||
|
||||
obj.label mustEqual "test"
|
||||
obj.vehicle_definition mustEqual mediumtransport
|
||||
|
||||
obj.visible_slots.length mustEqual 2
|
||||
val holsters = obj.visible_slots.sortBy(_.index)
|
||||
holsters.head.index mustEqual 5
|
||||
holsters.head.item.asInstanceOf[Loadout.ShorthandTool].definition mustEqual mediumtransport_weapon_systemA
|
||||
holsters(1).index mustEqual 6
|
||||
holsters(1).item.asInstanceOf[Loadout.ShorthandTool].definition mustEqual mediumtransport_weapon_systemB
|
||||
|
||||
obj.inventory.length mustEqual 2
|
||||
val inventory = obj.inventory.sortBy(_.index)
|
||||
inventory.head.index mustEqual 30
|
||||
inventory.head.item.asInstanceOf[Loadout.ShorthandAmmoBox].definition mustEqual bullet_9mm
|
||||
inventory(1).index mustEqual 33
|
||||
inventory(1).item.asInstanceOf[Loadout.ShorthandAmmoBox].definition mustEqual bullet_9mm_AP
|
||||
}
|
||||
|
||||
"distinguish MAX subtype information" in {
|
||||
val player = CreatePlayer()
|
||||
val slot = player.Slot(0)
|
||||
slot.Equipment = None //only an unequipped slot can have its Equipment Size changed (Rifle -> Max)
|
||||
player.ExoSuit = ExoSuitType.MAX
|
||||
|
||||
val ldout1 = Loadout.Create(player, "weaponless").asInstanceOf[InfantryLoadout]
|
||||
slot.Equipment = None
|
||||
slot.Equipment = Tool(trhev_dualcycler)
|
||||
val ldout2 = Loadout.Create(player, "cycler").asInstanceOf[InfantryLoadout]
|
||||
slot.Equipment = None
|
||||
slot.Equipment = Tool(trhev_pounder)
|
||||
val ldout3 = Loadout.Create(player, "pounder").asInstanceOf[InfantryLoadout]
|
||||
slot.Equipment = None
|
||||
slot.Equipment = Tool(trhev_burster)
|
||||
val ldout4 = Loadout.Create(player, "burster").asInstanceOf[InfantryLoadout]
|
||||
|
||||
ldout1.subtype mustEqual 0
|
||||
ldout2.subtype mustEqual 1
|
||||
ldout3.subtype mustEqual 2
|
||||
ldout4.subtype mustEqual InfantryLoadout.DetermineSubtype(player) //example
|
||||
}
|
||||
|
||||
"players have additional uniform subtype" in {
|
||||
val player = CreatePlayer()
|
||||
val slot = player.Slot(0)
|
||||
slot.Equipment = None //only an unequipped slot can have its Equipment Size changed (Rifle -> Max)
|
||||
|
||||
player.ExoSuit = ExoSuitType.Standard
|
||||
val ldout0 = Loadout.Create(player, "standard").asInstanceOf[InfantryLoadout]
|
||||
player.ExoSuit = ExoSuitType.Agile
|
||||
val ldout1 = Loadout.Create(player, "agile").asInstanceOf[InfantryLoadout]
|
||||
player.ExoSuit = ExoSuitType.Reinforced
|
||||
val ldout2 = Loadout.Create(player, "rein").asInstanceOf[InfantryLoadout]
|
||||
player.ExoSuit = ExoSuitType.Infiltration
|
||||
val ldout7 = Loadout.Create(player, "inf").asInstanceOf[InfantryLoadout]
|
||||
|
||||
player.ExoSuit = ExoSuitType.MAX
|
||||
val ldout3 = Loadout.Create(player, "weaponless").asInstanceOf[InfantryLoadout]
|
||||
slot.Equipment = None
|
||||
slot.Equipment = Tool(trhev_dualcycler)
|
||||
val ldout4 = Loadout.Create(player, "cycler").asInstanceOf[InfantryLoadout]
|
||||
slot.Equipment = None
|
||||
slot.Equipment = Tool(trhev_pounder)
|
||||
val ldout5 = Loadout.Create(player, "pounder").asInstanceOf[InfantryLoadout]
|
||||
slot.Equipment = None
|
||||
slot.Equipment = Tool(trhev_burster)
|
||||
val ldout6 = Loadout.Create(player, "burster").asInstanceOf[InfantryLoadout]
|
||||
|
||||
InfantryLoadout.DetermineSubtypeB(ldout0.exosuit, ldout0.subtype) mustEqual 0
|
||||
InfantryLoadout.DetermineSubtypeB(ldout1.exosuit, ldout1.subtype) mustEqual 1
|
||||
InfantryLoadout.DetermineSubtypeB(ldout2.exosuit, ldout2.subtype) mustEqual 2
|
||||
InfantryLoadout.DetermineSubtypeB(ldout3.exosuit, ldout3.subtype) mustEqual 3
|
||||
InfantryLoadout.DetermineSubtypeB(ldout4.exosuit, ldout4.subtype) mustEqual 4
|
||||
InfantryLoadout.DetermineSubtypeB(ldout5.exosuit, ldout5.subtype) mustEqual 5
|
||||
InfantryLoadout.DetermineSubtypeB(ldout6.exosuit, ldout6.subtype) mustEqual 6
|
||||
InfantryLoadout.DetermineSubtypeB(ldout7.exosuit, ldout7.subtype) mustEqual 7
|
||||
}
|
||||
}
|
||||
37
src/test/scala/objects/LockerTest.scala
Normal file
37
src/test/scala/objects/LockerTest.scala
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.Props
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.GlobalDefinitions
|
||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||
import net.psforever.objects.serverobject.mblocker.{Locker, LockerControl}
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
import org.specs2.mutable._
|
||||
|
||||
class LockerTest extends Specification {
|
||||
"LockerDefinition" should {
|
||||
"define" in {
|
||||
GlobalDefinitions.mb_locker.ObjectId mustEqual 524
|
||||
GlobalDefinitions.mb_locker.Name mustEqual "mb_locker"
|
||||
}
|
||||
}
|
||||
|
||||
"Locker" should {
|
||||
"construct" in {
|
||||
new Locker()
|
||||
ok
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LockerControlTest extends ActorTest {
|
||||
"LockerControl" should {
|
||||
"construct" in {
|
||||
val locker = new Locker()
|
||||
locker.Actor = system.actorOf(Props(classOf[LockerControl], locker), "test")
|
||||
locker.Actor ! FactionAffinity.ConfirmFactionAffinity()
|
||||
expectMsg(FactionAffinity.AssertFactionAffinity(locker, PlanetSideEmpire.NEUTRAL))
|
||||
}
|
||||
}
|
||||
}
|
||||
98
src/test/scala/objects/MountableTest.scala
Normal file
98
src/test/scala/objects/MountableTest.scala
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.{Actor, ActorRef, Props}
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.Player
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
import net.psforever.objects.definition.{ObjectDefinition, SeatDefinition}
|
||||
import net.psforever.objects.serverobject.mount.{Mountable, MountableBehavior}
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
import net.psforever.objects.vehicles.Seat
|
||||
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire, PlanetSideGUID}
|
||||
|
||||
import scala.concurrent.duration.Duration
|
||||
|
||||
class MountableControl1Test extends ActorTest {
|
||||
"MountableControl" should {
|
||||
"construct" in {
|
||||
val obj = new MountableTest.MountableTestObject
|
||||
obj.Actor = system.actorOf(Props(classOf[MountableTest.MountableTestControl], obj), "mech")
|
||||
assert(obj.Actor != ActorRef.noSender)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MountableControl2Test extends ActorTest {
|
||||
"MountableControl" should {
|
||||
"let a player mount" in {
|
||||
val player = Player(Avatar(0, "test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
val obj = new MountableTest.MountableTestObject
|
||||
obj.Actor = system.actorOf(Props(classOf[MountableTest.MountableTestControl], obj), "mountable")
|
||||
val msg = Mountable.TryMount(player, 0)
|
||||
|
||||
obj.Actor ! msg
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
assert(reply.isInstanceOf[Mountable.MountMessages])
|
||||
val reply2 = reply.asInstanceOf[Mountable.MountMessages]
|
||||
assert(reply2.player == player)
|
||||
assert(reply2.response.isInstanceOf[Mountable.CanMount])
|
||||
val reply3 = reply2.response.asInstanceOf[Mountable.CanMount]
|
||||
assert(reply3.obj == obj)
|
||||
assert(reply3.seat_num == 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MountableControl3Test extends ActorTest {
|
||||
"MountableControl" should {
|
||||
"block a player from mounting" in {
|
||||
val player1 = Player(Avatar(0, "test1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
val player2 = Player(Avatar(1, "test2", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
val obj = new MountableTest.MountableTestObject
|
||||
obj.Actor = system.actorOf(Props(classOf[MountableTest.MountableTestControl], obj), "mountable")
|
||||
obj.Actor ! Mountable.TryMount(player1, 0)
|
||||
receiveOne(Duration.create(100, "ms")) //consume reply
|
||||
|
||||
obj.Actor ! Mountable.TryMount(player2, 0)
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
assert(reply.isInstanceOf[Mountable.MountMessages])
|
||||
val reply2 = reply.asInstanceOf[Mountable.MountMessages]
|
||||
assert(reply2.player == player2)
|
||||
assert(reply2.response.isInstanceOf[Mountable.CanNotMount])
|
||||
val reply3 = reply2.response.asInstanceOf[Mountable.CanNotMount]
|
||||
assert(reply3.obj == obj)
|
||||
assert(reply3.seat_num == 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object MountableTest {
|
||||
class MountableTestObject extends PlanetSideServerObject with Mountable {
|
||||
private val seats: Map[Int, Seat] = Map(0 -> new Seat(new SeatDefinition()))
|
||||
def Seats: Map[Int, Seat] = seats
|
||||
def Seat(seatNum: Int): Option[Seat] = seats.get(seatNum)
|
||||
def MountPoints: Map[Int, Int] = Map(1 -> 0)
|
||||
def GetSeatFromMountPoint(mount: Int): Option[Int] = MountPoints.get(mount)
|
||||
def PassengerInSeat(user: Player): Option[Int] = {
|
||||
if (seats(0).Occupant.contains(user)) {
|
||||
Some(0)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
GUID = PlanetSideGUID(1)
|
||||
//eh whatever
|
||||
def Faction = PlanetSideEmpire.TR
|
||||
def Definition: ObjectDefinition = null
|
||||
}
|
||||
|
||||
class MountableTestControl(obj: PlanetSideServerObject with Mountable)
|
||||
extends Actor
|
||||
with MountableBehavior.Mount
|
||||
with MountableBehavior.Dismount {
|
||||
override def MountableObject = obj
|
||||
|
||||
def receive: Receive = mountBehavior.orElse(dismountBehavior)
|
||||
}
|
||||
}
|
||||
725
src/test/scala/objects/PlayerControlTest.scala
Normal file
725
src/test/scala/objects/PlayerControlTest.scala
Normal file
|
|
@ -0,0 +1,725 @@
|
|||
// Copyright (c) 2020 PSForever
|
||||
package objects
|
||||
/*
|
||||
import akka.actor.Props
|
||||
import akka.testkit.TestProbe
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.avatar.{Avatar, PlayerControl}
|
||||
import net.psforever.objects.ballistics._
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
import net.psforever.objects.guid.source.LimitedNumberSource
|
||||
import net.psforever.objects.vital.Vitality
|
||||
import net.psforever.objects.zones.{Zone, ZoneMap}
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.serverobject.CommonMessages
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types._
|
||||
import net.psforever.services.Service
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
class PlayerControlHealTest extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(15))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
val avatarProbe = TestProbe()
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
player1.Position = Vector3(2, 0, 0)
|
||||
guid.register(player1.avatar.locker, 5)
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1), "player1-control")
|
||||
val player2 =
|
||||
Player(Avatar(0, "TestCharacter2", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=2
|
||||
player2.Zone = zone
|
||||
player2.Spawn()
|
||||
guid.register(player2.avatar.locker, 6)
|
||||
player2.Actor = system.actorOf(Props(classOf[PlayerControl], player2), "player2-control")
|
||||
|
||||
val tool = Tool(GlobalDefinitions.medicalapplicator) //guid=3 & 4
|
||||
|
||||
guid.register(player1, 1)
|
||||
guid.register(player2, 2)
|
||||
guid.register(tool, 3)
|
||||
guid.register(tool.AmmoSlot.Box, 4)
|
||||
|
||||
"PlayerControl" should {
|
||||
"handle being healed by another player" in {
|
||||
val originalHealth = player2.Health = 0 //initial state manip
|
||||
val originalMagazine = tool.Magazine
|
||||
assert(originalHealth < player2.MaxHealth)
|
||||
|
||||
player2.Actor ! CommonMessages.Use(player1, Some(tool))
|
||||
val msg_avatar = avatarProbe.receiveN(4, 500 milliseconds)
|
||||
assert(
|
||||
msg_avatar.head match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction.SendResponse(_, InventoryStateMessage(PlanetSideGUID(4), _, PlanetSideGUID(3), _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(1) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(2) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter2",
|
||||
AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 55, 1)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(3) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction.SendResponse(_, RepairMessage(PlanetSideGUID(2), _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
val raisedHealth = player2.Health
|
||||
assert(raisedHealth > originalHealth)
|
||||
assert(tool.Magazine < originalMagazine)
|
||||
|
||||
player1.Position = Vector3(10, 0, 0) //moved more than 5m away
|
||||
player2.Actor ! CommonMessages.Use(player1, Some(tool))
|
||||
avatarProbe.expectNoMessage(500 milliseconds)
|
||||
assert(raisedHealth == player2.Health)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PlayerControlHealSelfTest extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(15))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
val avatarProbe = TestProbe()
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
player1.Position = Vector3(2, 0, 0)
|
||||
guid.register(player1.avatar.locker, 5)
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1), "player1-control")
|
||||
|
||||
val tool = Tool(GlobalDefinitions.medicalapplicator) //guid=3 & 4
|
||||
|
||||
guid.register(player1, 1)
|
||||
guid.register(tool, 3)
|
||||
guid.register(tool.AmmoSlot.Box, 4)
|
||||
|
||||
"PlayerControl" should {
|
||||
"handle healing own self" in {
|
||||
val originalHealth = player1.Health = 1 //initial state manip
|
||||
val originalMagazine = tool.Magazine
|
||||
assert(originalHealth < player1.MaxHealth)
|
||||
|
||||
player1.Actor ! CommonMessages.Use(player1, Some(tool))
|
||||
val msg_avatar1 = avatarProbe.receiveN(2, 500 milliseconds)
|
||||
assert(
|
||||
msg_avatar1.head match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction.SendResponse(_, InventoryStateMessage(PlanetSideGUID(4), _, PlanetSideGUID(3), _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar1(1) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(1), 0, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
val raisedHealth = player1.Health
|
||||
assert(raisedHealth > originalHealth)
|
||||
assert(tool.Magazine < originalMagazine)
|
||||
|
||||
player1.Position = Vector3(10, 0, 0) //trying to move away from oneself doesn't work
|
||||
player1.Actor ! CommonMessages.Use(player1, Some(tool))
|
||||
val msg_avatar2 = avatarProbe.receiveN(2, 500 milliseconds)
|
||||
assert(
|
||||
msg_avatar2.head match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction.SendResponse(_, InventoryStateMessage(PlanetSideGUID(4), _, PlanetSideGUID(3), _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar2(1) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(1), 0, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(player1.Health > raisedHealth)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PlayerControlRepairTest extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(15))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
val avatarProbe = TestProbe()
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
player1.Position = Vector3(2, 0, 0)
|
||||
guid.register(player1.avatar.locker, 5)
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1), "player1-control")
|
||||
val player2 =
|
||||
Player(Avatar(0, "TestCharacter2", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=2
|
||||
player2.Zone = zone
|
||||
player2.Spawn()
|
||||
guid.register(player2.avatar.locker, 6)
|
||||
player2.Actor = system.actorOf(Props(classOf[PlayerControl], player2), "player2-control")
|
||||
|
||||
val tool = Tool(GlobalDefinitions.bank) //guid=3 & 4
|
||||
|
||||
guid.register(player1, 1)
|
||||
guid.register(player2, 2)
|
||||
guid.register(tool, 3)
|
||||
guid.register(tool.AmmoSlot.Box, 4)
|
||||
|
||||
"PlayerControl" should {
|
||||
"handle being repaired by another player" in {
|
||||
val originalArmor = player2.Armor = 0 //initial state manip
|
||||
val originalMagazine = tool.Magazine
|
||||
assert(originalArmor < player2.MaxArmor)
|
||||
|
||||
player2.Actor ! CommonMessages.Use(player1, Some(tool))
|
||||
val msg_avatar = avatarProbe.receiveN(5, 1000 milliseconds)
|
||||
assert(
|
||||
msg_avatar.head match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction.SendResponse(_, InventoryStateMessage(PlanetSideGUID(4), _, PlanetSideGUID(3), _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(1) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 4, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(2) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter2",
|
||||
AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 56, 1)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(3) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction.SendResponse(_, RepairMessage(PlanetSideGUID(2), _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(4) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter2",
|
||||
AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 56, 1)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(player2.Armor > originalArmor)
|
||||
assert(tool.Magazine < originalMagazine)
|
||||
|
||||
val fixedArmor = player2.Armor
|
||||
player1.Position = Vector3(10, 0, 0) //moved more than 5m away
|
||||
player2.Actor ! CommonMessages.Use(player1, Some(tool))
|
||||
avatarProbe.expectNoMessage(500 milliseconds)
|
||||
assert(fixedArmor == player2.Armor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PlayerControlRepairSelfTest extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(15))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
val avatarProbe = TestProbe()
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
player1.Position = Vector3(2, 0, 0)
|
||||
guid.register(player1.avatar.locker, 5)
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1), "player1-control")
|
||||
|
||||
val tool = Tool(GlobalDefinitions.bank) //guid=3 & 4
|
||||
|
||||
guid.register(player1, 1)
|
||||
guid.register(tool, 3)
|
||||
guid.register(tool.AmmoSlot.Box, 4)
|
||||
|
||||
"PlayerControl" should {
|
||||
"handle repairing own self" in {
|
||||
val originalArmor = player1.Armor = 0 //initial state manip
|
||||
val originalMagazine = tool.Magazine
|
||||
assert(originalArmor < player1.MaxArmor)
|
||||
|
||||
player1.Actor ! CommonMessages.Use(player1, Some(tool))
|
||||
val msg_avatar1 = avatarProbe.receiveN(2, 500 milliseconds)
|
||||
assert(
|
||||
msg_avatar1.head match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction.SendResponse(_, InventoryStateMessage(PlanetSideGUID(4), _, PlanetSideGUID(3), _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar1(1) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(1), 4, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
val fixedArmor = player1.Armor
|
||||
assert(fixedArmor > originalArmor)
|
||||
assert(tool.Magazine < originalMagazine)
|
||||
|
||||
player1.Position = Vector3(10, 0, 0) //trying to move away from oneself doesn't work
|
||||
player1.Actor ! CommonMessages.Use(player1, Some(tool))
|
||||
val msg_avatar2 = avatarProbe.receiveN(2, 500 milliseconds)
|
||||
assert(
|
||||
msg_avatar2.head match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction.SendResponse(_, InventoryStateMessage(PlanetSideGUID(4), _, PlanetSideGUID(3), _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar2(1) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(1), 4, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(player1.Armor > fixedArmor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PlayerControlDamageTest extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(15))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
val activityProbe = TestProbe()
|
||||
val avatarProbe = TestProbe()
|
||||
zone.Activity = activityProbe.ref
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
player1.Position = Vector3(2, 0, 0)
|
||||
guid.register(player1.avatar.locker, 5)
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1), "player1-control")
|
||||
val player2 =
|
||||
Player(Avatar(0, "TestCharacter2", PlanetSideEmpire.NC, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=2
|
||||
player2.Zone = zone
|
||||
player2.Spawn()
|
||||
guid.register(player2.avatar.locker, 6)
|
||||
player2.Actor = system.actorOf(Props(classOf[PlayerControl], player2), "player2-control")
|
||||
val tool = Tool(GlobalDefinitions.suppressor) //guid 3 & 4
|
||||
val projectile = tool.Projectile
|
||||
val playerSource = SourceEntry(player2)
|
||||
val resolved = ResolvedProjectile(
|
||||
ProjectileResolution.Hit,
|
||||
Projectile(
|
||||
projectile,
|
||||
tool.Definition,
|
||||
tool.FireMode,
|
||||
PlayerSource(player1),
|
||||
0,
|
||||
Vector3(2, 0, 0),
|
||||
Vector3(-1, 0, 0)
|
||||
),
|
||||
playerSource,
|
||||
player1.DamageModel,
|
||||
Vector3(1, 0, 0)
|
||||
)
|
||||
val applyDamageTo = resolved.damage_model.Calculate(resolved)
|
||||
guid.register(player1, 1)
|
||||
guid.register(player2, 2)
|
||||
guid.register(tool, 3)
|
||||
guid.register(tool.AmmoSlot.Box, 4)
|
||||
expectNoMessage(200 milliseconds)
|
||||
"PlayerControl" should {
|
||||
"handle damage" in {
|
||||
assert(player2.Health == player2.Definition.DefaultHealth)
|
||||
assert(player2.Armor == player2.MaxArmor)
|
||||
player2.Actor ! Vitality.Damage(applyDamageTo)
|
||||
val msg_avatar = avatarProbe.receiveN(4, 500 milliseconds)
|
||||
val msg_activity = activityProbe.receiveOne(200 milliseconds)
|
||||
assert(
|
||||
msg_avatar.head match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 4, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(1) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(2) match {
|
||||
case AvatarServiceMessage("TestCharacter2", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 2, _)) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_activity match {
|
||||
case activity: Zone.HotSpot.Activity =>
|
||||
activity.attacker == PlayerSource(player1) &&
|
||||
activity.defender == playerSource &&
|
||||
activity.location == Vector3(1, 0, 0)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(3) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter2",
|
||||
AvatarAction.SendResponse(Service.defaultPlayerGUID, DamageWithPositionMessage(10, Vector3(2, 0, 0)))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(player2.Health < player2.Definition.DefaultHealth)
|
||||
assert(player2.Armor < player2.MaxArmor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PlayerControlDeathStandingTest extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(15))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
val avatarProbe = TestProbe()
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
val activityProbe = TestProbe()
|
||||
zone.Activity = activityProbe.ref
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
player1.Position = Vector3(2, 0, 0)
|
||||
guid.register(player1.avatar.locker, 5)
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1), "player1-control")
|
||||
val player2 =
|
||||
Player(Avatar(0, "TestCharacter2", PlanetSideEmpire.NC, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=2
|
||||
player2.Zone = zone
|
||||
player2.Spawn()
|
||||
guid.register(player2.avatar.locker, 6)
|
||||
player2.Actor = system.actorOf(Props(classOf[PlayerControl], player2), "player2-control")
|
||||
|
||||
val tool = Tool(GlobalDefinitions.suppressor) //guid 3 & 4
|
||||
val projectile = tool.Projectile
|
||||
val player1Source = SourceEntry(player1)
|
||||
val resolved = ResolvedProjectile(
|
||||
ProjectileResolution.Hit,
|
||||
Projectile(projectile, tool.Definition, tool.FireMode, player1Source, 0, Vector3(2, 0, 0), Vector3(-1, 0, 0)),
|
||||
SourceEntry(player2),
|
||||
player2.DamageModel,
|
||||
Vector3(1, 0, 0)
|
||||
)
|
||||
val applyDamageTo = resolved.damage_model.Calculate(resolved)
|
||||
guid.register(player1, 1)
|
||||
guid.register(player2, 2)
|
||||
guid.register(tool, 3)
|
||||
guid.register(tool.AmmoSlot.Box, 4)
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
"PlayerControl" should {
|
||||
"handle death" in {
|
||||
player2.Health = player2.Definition.DamageDestroysAt + 1 //initial state manip
|
||||
player2.ExoSuit = ExoSuitType.MAX
|
||||
player2.Armor = 1 //initial state manip
|
||||
player2.Capacitor = 1 //initial state manip
|
||||
assert(player2.Health > player2.Definition.DamageDestroysAt)
|
||||
assert(player2.Armor == 1)
|
||||
assert(player2.Capacitor == 1)
|
||||
assert(player2.isAlive)
|
||||
|
||||
player2.Actor ! Vitality.Damage(applyDamageTo)
|
||||
val msg_avatar = avatarProbe.receiveN(8, 500 milliseconds)
|
||||
activityProbe.expectNoMessage(200 milliseconds)
|
||||
assert(
|
||||
msg_avatar.head match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 4, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(1) match {
|
||||
case AvatarServiceMessage("TestCharacter2", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 2, _)) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(2) match {
|
||||
case AvatarServiceMessage("TestCharacter2", AvatarAction.Killed(PlanetSideGUID(2), None)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(3) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(4) match {
|
||||
case AvatarServiceMessage("TestCharacter2", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 7, _)) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(5) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter2",
|
||||
AvatarAction.SendResponse(_, DestroyMessage(PlanetSideGUID(2), PlanetSideGUID(2), _, Vector3.Zero))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(6) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter2",
|
||||
AvatarAction.SendResponse(
|
||||
_,
|
||||
AvatarDeadStateMessage(DeadState.Dead, 300000, 300000, Vector3.Zero, PlanetSideEmpire.NC, true)
|
||||
)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(7) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.DestroyDisplay(killer, victim, _, _))
|
||||
if killer.Name.equals(player1.Name) && victim.Name.equals(player2.Name) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(player2.Health <= player2.Definition.DamageDestroysAt)
|
||||
assert(player2.Armor == 0)
|
||||
assert(!player2.isAlive)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PlayerControlDeathSeatedTest extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(15))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
val avatarProbe = TestProbe()
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
val activityProbe = TestProbe()
|
||||
zone.Activity = activityProbe.ref
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
player1.Position = Vector3(2, 0, 0)
|
||||
guid.register(player1.avatar.locker, 6)
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1), "player1-control")
|
||||
val player2 =
|
||||
Player(Avatar(0, "TestCharacter2", PlanetSideEmpire.NC, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=2
|
||||
player2.Zone = zone
|
||||
player2.Spawn()
|
||||
guid.register(player2.avatar.locker, 7)
|
||||
player2.Actor = system.actorOf(Props(classOf[PlayerControl], player2), "player2-control")
|
||||
|
||||
val vehicle = Vehicle(GlobalDefinitions.quadstealth) //guid=5
|
||||
vehicle.Faction = player2.Faction
|
||||
|
||||
val tool = Tool(GlobalDefinitions.suppressor) //guid 3 & 4
|
||||
val projectile = tool.Projectile
|
||||
val player1Source = SourceEntry(player1)
|
||||
val resolved = ResolvedProjectile(
|
||||
ProjectileResolution.Hit,
|
||||
Projectile(projectile, tool.Definition, tool.FireMode, player1Source, 0, Vector3(2, 0, 0), Vector3(-1, 0, 0)),
|
||||
SourceEntry(player2),
|
||||
player2.DamageModel,
|
||||
Vector3(1, 0, 0)
|
||||
)
|
||||
val applyDamageTo = resolved.damage_model.Calculate(resolved)
|
||||
guid.register(player1, 1)
|
||||
guid.register(player2, 2)
|
||||
guid.register(tool, 3)
|
||||
guid.register(tool.AmmoSlot.Box, 4)
|
||||
guid.register(vehicle, 5)
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
"PlayerControl" should {
|
||||
"handle death when seated (in something)" in {
|
||||
player2.Health = player2.Definition.DamageDestroysAt + 1 //initial state manip
|
||||
player2.VehicleSeated = vehicle.GUID //initial state manip, anything
|
||||
vehicle.Seats(0).Occupant = player2
|
||||
player2.Armor = 0 //initial state manip
|
||||
assert(player2.Health > player2.Definition.DamageDestroysAt)
|
||||
assert(player2.isAlive)
|
||||
|
||||
player2.Actor ! Vitality.Damage(applyDamageTo)
|
||||
val msg_avatar = avatarProbe.receiveN(9, 500 milliseconds)
|
||||
activityProbe.expectNoMessage(200 milliseconds)
|
||||
assert(
|
||||
msg_avatar.head match {
|
||||
case AvatarServiceMessage("TestCharacter2", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 2, _)) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(1) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter2",
|
||||
AvatarAction.Killed(PlanetSideGUID(2), Some(PlanetSideGUID(5)))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(2) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter2",
|
||||
AvatarAction.SendResponse(_, ObjectDetachMessage(PlanetSideGUID(5), PlanetSideGUID(2), _, _, _, _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(3) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter2",
|
||||
AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 29, 1)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(4) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.ObjectDelete(PlanetSideGUID(2), PlanetSideGUID(2), _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(5) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(6) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter2",
|
||||
AvatarAction.SendResponse(_, DestroyMessage(PlanetSideGUID(2), PlanetSideGUID(2), _, Vector3.Zero))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(7) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter2",
|
||||
AvatarAction.SendResponse(
|
||||
_,
|
||||
AvatarDeadStateMessage(DeadState.Dead, 300000, 300000, Vector3.Zero, PlanetSideEmpire.NC, true)
|
||||
)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(8) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.DestroyDisplay(killer, victim, _, _))
|
||||
if killer.Name.equals(player1.Name) && victim.Name.equals(player2.Name) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(player2.Health <= player2.Definition.DamageDestroysAt)
|
||||
assert(!player2.isAlive)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object PlayerControlTest {}
|
||||
|
||||
|
||||
*/
|
||||
425
src/test/scala/objects/PlayerTest.scala
Normal file
425
src/test/scala/objects/PlayerTest.scala
Normal file
|
|
@ -0,0 +1,425 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects.GlobalDefinitions._
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
import net.psforever.objects.definition.{SimpleItemDefinition, SpecialExoSuitDefinition}
|
||||
import net.psforever.objects.equipment.EquipmentSize
|
||||
import net.psforever.types.{PlanetSideGUID, _}
|
||||
import org.specs2.mutable._
|
||||
|
||||
import scala.util.Success
|
||||
|
||||
class PlayerTest extends Specification {
|
||||
def TestPlayer(
|
||||
name: String,
|
||||
faction: PlanetSideEmpire.Value,
|
||||
sex: CharacterGender.Value,
|
||||
head: Int,
|
||||
voice: CharacterVoice.Value
|
||||
): Player = {
|
||||
new Player(Avatar(0, name, faction, sex, head, voice))
|
||||
}
|
||||
|
||||
"Player" should {
|
||||
"construct" in {
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.isAlive mustEqual false
|
||||
obj.FacingYawUpper mustEqual 0
|
||||
obj.Jumping mustEqual false
|
||||
obj.Crouching mustEqual false
|
||||
obj.Cloaked mustEqual false
|
||||
|
||||
obj.FacingYawUpper = 1.3f
|
||||
obj.Jumping = true
|
||||
obj.Crouching = true
|
||||
obj.Cloaked = true
|
||||
obj.FacingYawUpper mustEqual 1.3f
|
||||
obj.Jumping mustEqual true
|
||||
obj.Crouching mustEqual true
|
||||
obj.Cloaked mustEqual true
|
||||
}
|
||||
|
||||
"(re)spawn" in {
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.isAlive mustEqual false
|
||||
obj.Health mustEqual 0
|
||||
obj.Armor mustEqual 0
|
||||
obj.MaxHealth mustEqual 100
|
||||
obj.MaxArmor mustEqual 50
|
||||
obj.Spawn()
|
||||
obj.isAlive mustEqual true
|
||||
obj.Health mustEqual 100
|
||||
obj.Armor mustEqual 50
|
||||
}
|
||||
|
||||
"will not (re)spawn if not dead" in {
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.Spawn()
|
||||
obj.Health mustEqual 100
|
||||
obj.Armor mustEqual 50
|
||||
obj.isAlive mustEqual true
|
||||
|
||||
obj.Health = 10
|
||||
obj.Armor = 10
|
||||
obj.Health mustEqual 10
|
||||
obj.Armor mustEqual 10
|
||||
obj.Spawn()
|
||||
obj.Health mustEqual 10
|
||||
obj.Armor mustEqual 10
|
||||
}
|
||||
|
||||
"can die" in {
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.Spawn()
|
||||
obj.Armor = 35 //50 -> 35
|
||||
obj.isAlive mustEqual true
|
||||
obj.Health mustEqual obj.MaxHealth
|
||||
obj.Armor mustEqual 35
|
||||
obj.Die
|
||||
obj.isAlive mustEqual false
|
||||
obj.Health mustEqual 0
|
||||
obj.Armor mustEqual 35
|
||||
}
|
||||
|
||||
"can not become a backpack if alive" in {
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.Spawn()
|
||||
obj.isAlive mustEqual true
|
||||
obj.isBackpack mustEqual false
|
||||
obj.Release
|
||||
obj.isAlive mustEqual true
|
||||
obj.isBackpack mustEqual false
|
||||
}
|
||||
|
||||
"can become a backpack" in {
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.isAlive mustEqual false
|
||||
obj.isBackpack mustEqual false
|
||||
obj.Release
|
||||
obj.isAlive mustEqual false
|
||||
obj.isBackpack mustEqual true
|
||||
}
|
||||
|
||||
"set new maximum values (health, stamina)" in {
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.MaxHealth mustEqual 100
|
||||
obj.MaxHealth = 123
|
||||
obj.MaxHealth mustEqual 123
|
||||
obj.MaxHealth = None
|
||||
//MaxStamina has no equivalent
|
||||
obj.MaxHealth mustEqual 100
|
||||
}
|
||||
|
||||
// "set new values (health, armor, stamina) but only when alive" in {
|
||||
// val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
// obj.Health = 23
|
||||
// obj.Armor = 34
|
||||
// obj.Stamina = 45
|
||||
// obj.Health mustEqual 0
|
||||
// obj.Armor mustEqual 0
|
||||
// obj.Stamina mustEqual 0
|
||||
//
|
||||
// obj.Spawn()
|
||||
// obj.Health mustEqual obj.MaxHealth
|
||||
// obj.Armor mustEqual obj.MaxArmor
|
||||
// obj.Stamina mustEqual obj.MaxStamina
|
||||
// obj.Health = 23
|
||||
// obj.Armor = 34
|
||||
// obj.Stamina = 45
|
||||
// obj.Health mustEqual 23
|
||||
// obj.Armor mustEqual 34
|
||||
// obj.Stamina mustEqual 45
|
||||
// }
|
||||
|
||||
"has visible slots" in {
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.VisibleSlots mustEqual Set(0, 2, 4) //Standard
|
||||
obj.ExoSuit = ExoSuitType.Agile
|
||||
obj.VisibleSlots mustEqual Set(0, 1, 2, 4)
|
||||
obj.ExoSuit = ExoSuitType.Reinforced
|
||||
obj.VisibleSlots mustEqual Set(0, 1, 2, 3, 4)
|
||||
obj.ExoSuit = ExoSuitType.Infiltration
|
||||
obj.VisibleSlots mustEqual Set(0, 4)
|
||||
obj.ExoSuit = ExoSuitType.MAX
|
||||
obj.VisibleSlots mustEqual Set(0)
|
||||
}
|
||||
|
||||
"init (Standard Exo-Suit)" in {
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.ExoSuit mustEqual ExoSuitType.Standard
|
||||
obj.Slot(0).Size mustEqual EquipmentSize.Pistol
|
||||
obj.Slot(1).Size mustEqual EquipmentSize.Blocked
|
||||
obj.Slot(2).Size mustEqual EquipmentSize.Rifle
|
||||
obj.Slot(3).Size mustEqual EquipmentSize.Blocked
|
||||
obj.Slot(4).Size mustEqual EquipmentSize.Melee
|
||||
obj.Inventory.Width mustEqual 9
|
||||
obj.Inventory.Height mustEqual 6
|
||||
obj.Inventory.Offset mustEqual 6
|
||||
}
|
||||
|
||||
"draw equipped holsters only" in {
|
||||
val wep = SimpleItem(SimpleItemDefinition(149))
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.Slot(1).Size = EquipmentSize.Pistol
|
||||
obj.Slot(1).Equipment = wep
|
||||
obj.DrawnSlot mustEqual Player.HandsDownSlot
|
||||
obj.DrawnSlot = 0
|
||||
obj.DrawnSlot mustEqual Player.HandsDownSlot
|
||||
obj.DrawnSlot = 1
|
||||
obj.DrawnSlot mustEqual 1
|
||||
}
|
||||
|
||||
"remember the last drawn holster" in {
|
||||
val wep1 = SimpleItem(SimpleItemDefinition(149))
|
||||
val wep2 = SimpleItem(SimpleItemDefinition(149))
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.Slot(0).Size = EquipmentSize.Pistol
|
||||
obj.Slot(0).Equipment = wep1
|
||||
obj.Slot(1).Size = EquipmentSize.Pistol
|
||||
obj.Slot(1).Equipment = wep2
|
||||
obj.DrawnSlot mustEqual Player.HandsDownSlot //default value
|
||||
obj.LastDrawnSlot mustEqual Player.HandsDownSlot //default value
|
||||
|
||||
obj.DrawnSlot = 1
|
||||
obj.DrawnSlot mustEqual 1
|
||||
obj.LastDrawnSlot mustEqual 1
|
||||
|
||||
obj.DrawnSlot = 0
|
||||
obj.DrawnSlot mustEqual 0
|
||||
obj.LastDrawnSlot mustEqual 0
|
||||
|
||||
obj.DrawnSlot = Player.HandsDownSlot
|
||||
obj.DrawnSlot mustEqual Player.HandsDownSlot
|
||||
obj.LastDrawnSlot mustEqual 0
|
||||
|
||||
obj.DrawnSlot = 1
|
||||
obj.DrawnSlot mustEqual 1
|
||||
obj.LastDrawnSlot mustEqual 1
|
||||
|
||||
obj.DrawnSlot = 0
|
||||
obj.DrawnSlot mustEqual 0
|
||||
obj.LastDrawnSlot mustEqual 0
|
||||
|
||||
obj.DrawnSlot = 1
|
||||
obj.DrawnSlot mustEqual 1
|
||||
obj.LastDrawnSlot mustEqual 1
|
||||
|
||||
obj.DrawnSlot = Player.HandsDownSlot
|
||||
obj.DrawnSlot mustEqual Player.HandsDownSlot
|
||||
obj.LastDrawnSlot mustEqual 1
|
||||
}
|
||||
|
||||
"hold something in their free hand" in {
|
||||
val wep = SimpleItem(SimpleItemDefinition(149))
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.Slot(Player.FreeHandSlot).Equipment = wep
|
||||
|
||||
obj.Slot(Player.FreeHandSlot).Equipment.get.Definition.ObjectId mustEqual 149
|
||||
}
|
||||
|
||||
"provide an invalid hand that can not hold anything" in {
|
||||
val wep = SimpleItem(SimpleItemDefinition(149))
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.Slot(-1).Equipment = wep
|
||||
|
||||
obj.Slot(-1).Equipment.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"search for the smallest available slot in which to store equipment" in {
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.Inventory.Resize(3, 3) //fits one item
|
||||
|
||||
obj.Fit(Tool(GlobalDefinitions.beamer)).contains(0) mustEqual true
|
||||
|
||||
obj.Fit(Tool(GlobalDefinitions.suppressor)).contains(2) mustEqual true
|
||||
|
||||
val ammo = AmmoBox(GlobalDefinitions.bullet_9mm)
|
||||
val ammo2 = AmmoBox(GlobalDefinitions.bullet_9mm)
|
||||
val ammo3 = AmmoBox(GlobalDefinitions.bullet_9mm)
|
||||
obj.Fit(ammo).contains(6) mustEqual true
|
||||
obj.Slot(6).Equipment = ammo
|
||||
obj.Fit(ammo2).contains(Player.FreeHandSlot) mustEqual true
|
||||
obj.Slot(Player.FreeHandSlot).Equipment = ammo2
|
||||
obj.Fit(ammo3).isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"can use their free hand to hold things" in {
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
val ammo = AmmoBox(GlobalDefinitions.bullet_9mm)
|
||||
obj.FreeHand.Equipment.isEmpty mustEqual true
|
||||
|
||||
obj.FreeHand.Equipment = ammo
|
||||
obj.FreeHand.Equipment.contains(ammo) mustEqual true
|
||||
}
|
||||
|
||||
"can access the player's locker-space" in {
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.Slot(5).Equipment.get.isInstanceOf[LockerEquipment] mustEqual true
|
||||
}
|
||||
|
||||
"can find equipment" in {
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.Slot(0).Equipment = {
|
||||
val item = Tool(beamer)
|
||||
item.GUID = PlanetSideGUID(1)
|
||||
item
|
||||
}
|
||||
obj.Slot(4).Equipment = {
|
||||
val item = Tool(forceblade)
|
||||
item.GUID = PlanetSideGUID(2)
|
||||
item
|
||||
}
|
||||
obj.Slot(6).Equipment = {
|
||||
val item = ConstructionItem(ace)
|
||||
item.GUID = PlanetSideGUID(3)
|
||||
item
|
||||
}
|
||||
obj.avatar.locker.Slot(6).Equipment = {
|
||||
val item = Kit(medkit)
|
||||
item.GUID = PlanetSideGUID(4)
|
||||
item
|
||||
}
|
||||
obj.FreeHand.Equipment = {
|
||||
val item = SimpleItem(remote_electronics_kit)
|
||||
item.GUID = PlanetSideGUID(5)
|
||||
item
|
||||
}
|
||||
|
||||
obj.Find(PlanetSideGUID(1)).contains(0) mustEqual true //holsters
|
||||
obj.Find(PlanetSideGUID(2)).contains(4) mustEqual true //holsters, melee
|
||||
obj.Find(PlanetSideGUID(3)).contains(6) mustEqual true //inventory
|
||||
obj.Find(PlanetSideGUID(4)).isEmpty mustEqual true //can not find in locker-space
|
||||
obj.Find(PlanetSideGUID(5)).contains(Player.FreeHandSlot) mustEqual true //free hand
|
||||
obj.Find(PlanetSideGUID(6)).isEmpty mustEqual true //not here
|
||||
}
|
||||
|
||||
"does equipment collision checking (are we already holding something there?)" in {
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
val item1 = Tool(beamer)
|
||||
val item2 = Kit(medkit)
|
||||
val item3 = AmmoBox(GlobalDefinitions.bullet_9mm)
|
||||
obj.Slot(0).Equipment = item1
|
||||
obj.Slot(6).Equipment = item2
|
||||
obj.FreeHand.Equipment = item3
|
||||
|
||||
obj.Collisions(0, 1, 1) match {
|
||||
case Success(List(item)) =>
|
||||
item.obj mustEqual item1
|
||||
item.start mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
} //holsters
|
||||
|
||||
obj.Collisions(1, 1, 1) match {
|
||||
case Success(List()) => ;
|
||||
case _ =>
|
||||
ko
|
||||
} //holsters, nothing
|
||||
|
||||
obj.Collisions(6, 1, 1) match {
|
||||
case Success(List(item)) =>
|
||||
item.obj mustEqual item2
|
||||
item.start mustEqual 6
|
||||
case _ =>
|
||||
ko
|
||||
} //inventory
|
||||
|
||||
obj.Collisions(Player.FreeHandSlot, 1, 1) match {
|
||||
case Success(List(item)) =>
|
||||
item.obj mustEqual item3
|
||||
item.start mustEqual Player.FreeHandSlot
|
||||
case _ =>
|
||||
ko
|
||||
} //free hand
|
||||
}
|
||||
|
||||
"seat in a vehicle" in {
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.VehicleSeated.isEmpty mustEqual true
|
||||
obj.VehicleSeated = PlanetSideGUID(65)
|
||||
obj.VehicleSeated.contains(PlanetSideGUID(65)) mustEqual true
|
||||
obj.VehicleSeated = None
|
||||
obj.VehicleSeated.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"own in a vehicle" in {
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.avatar.vehicle.isEmpty mustEqual true
|
||||
obj.avatar.vehicle = Some(PlanetSideGUID(65))
|
||||
obj.avatar.vehicle.contains(PlanetSideGUID(65)) mustEqual true
|
||||
obj.avatar.vehicle = None
|
||||
obj.avatar.vehicle.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"remember what zone he is in" in {
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.Continent mustEqual "home2"
|
||||
obj.Continent = "ugd01"
|
||||
obj.Continent mustEqual "ugd01"
|
||||
}
|
||||
|
||||
"special is typically normal and can not be changed from normal" in {
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Normal
|
||||
obj.UsingSpecial = SpecialExoSuitDefinition.Mode.Shielded
|
||||
obj.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Normal
|
||||
}
|
||||
|
||||
"a TR MAX can change its special to Overdrive or Anchored" in {
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.ExoSuit = ExoSuitType.MAX
|
||||
obj.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Normal
|
||||
obj.UsingSpecial = SpecialExoSuitDefinition.Mode.Anchored
|
||||
obj.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Anchored
|
||||
obj.UsingSpecial = SpecialExoSuitDefinition.Mode.Normal
|
||||
obj.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Normal
|
||||
obj.UsingSpecial = SpecialExoSuitDefinition.Mode.Overdrive
|
||||
obj.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Overdrive
|
||||
//note
|
||||
obj.UsingSpecial = SpecialExoSuitDefinition.Mode.Anchored
|
||||
obj.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Overdrive
|
||||
}
|
||||
|
||||
"an NC MAX can change its special to Shielded" in {
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.NC, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.ExoSuit = ExoSuitType.MAX
|
||||
obj.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Normal
|
||||
obj.UsingSpecial = SpecialExoSuitDefinition.Mode.Shielded
|
||||
obj.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Shielded
|
||||
obj.UsingSpecial = SpecialExoSuitDefinition.Mode.Normal
|
||||
obj.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Normal
|
||||
}
|
||||
|
||||
"one faction can not use the other's specials" in {
|
||||
val objtr = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
objtr.ExoSuit = ExoSuitType.MAX
|
||||
objtr.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Normal
|
||||
objtr.UsingSpecial = SpecialExoSuitDefinition.Mode.Shielded
|
||||
objtr.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Normal
|
||||
|
||||
val objnc = TestPlayer("Chord", PlanetSideEmpire.NC, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
objnc.ExoSuit = ExoSuitType.MAX
|
||||
objnc.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Normal
|
||||
objnc.UsingSpecial = SpecialExoSuitDefinition.Mode.Overdrive
|
||||
objnc.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Normal
|
||||
objnc.UsingSpecial = SpecialExoSuitDefinition.Mode.Anchored
|
||||
objnc.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Normal
|
||||
}
|
||||
|
||||
"changing exo-suit type resets the special to Normal (and changing back does not revert it again)" in {
|
||||
val obj = TestPlayer("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
obj.ExoSuit = ExoSuitType.MAX
|
||||
obj.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Normal
|
||||
obj.UsingSpecial = SpecialExoSuitDefinition.Mode.Anchored
|
||||
obj.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Anchored
|
||||
|
||||
val test = obj.UsingSpecial
|
||||
obj.ExoSuit = ExoSuitType.Standard
|
||||
obj.UsingSpecial mustEqual SpecialExoSuitDefinition.Mode.Normal
|
||||
obj.ExoSuit = ExoSuitType.MAX
|
||||
obj.UsingSpecial != test mustEqual true
|
||||
}
|
||||
}
|
||||
}
|
||||
368
src/test/scala/objects/ProjectileTest.scala
Normal file
368
src/test/scala/objects/ProjectileTest.scala
Normal file
|
|
@ -0,0 +1,368 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
import net.psforever.objects.ballistics._
|
||||
import net.psforever.objects.definition.ProjectileDefinition
|
||||
import net.psforever.objects.serverobject.mblocker.Locker
|
||||
import net.psforever.objects.vital.DamageType
|
||||
import net.psforever.types.{PlanetSideGUID, _}
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
class ProjectileTest extends Specification {
|
||||
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
val fury = Vehicle(GlobalDefinitions.fury)
|
||||
|
||||
"LocalProjectile" should {
|
||||
"construct" in {
|
||||
val obj = new LocalProjectile() //since they're just placeholders, they only need to construct
|
||||
obj.Definition.ObjectId mustEqual 0
|
||||
obj.Definition.Name mustEqual "projectile"
|
||||
}
|
||||
|
||||
"local projectile range" in {
|
||||
Projectile.baseUID < Projectile.rangeUID mustEqual true
|
||||
}
|
||||
}
|
||||
|
||||
"ProjectileDefinition" should {
|
||||
"define (default)" in {
|
||||
val obj = new ProjectileDefinition(31) //9mmbullet_projectile
|
||||
|
||||
obj.ProjectileType mustEqual Projectiles.bullet_9mm_projectile
|
||||
obj.ObjectId mustEqual 31
|
||||
obj.Damage0 mustEqual 0
|
||||
obj.Damage1 mustEqual 0
|
||||
obj.Damage2 mustEqual 0
|
||||
obj.Damage3 mustEqual 0
|
||||
obj.Damage4 mustEqual 0
|
||||
obj.Acceleration mustEqual 0
|
||||
obj.AccelerationUntil mustEqual 0f
|
||||
obj.ProjectileDamageType mustEqual DamageType.None
|
||||
obj.ProjectileDamageTypeSecondary mustEqual DamageType.None
|
||||
obj.DegradeDelay mustEqual 1f
|
||||
obj.DegradeMultiplier mustEqual 1f
|
||||
obj.InitialVelocity mustEqual 1
|
||||
obj.Lifespan mustEqual 1f
|
||||
obj.DamageAtEdge mustEqual 1f
|
||||
obj.DamageRadius mustEqual 1f
|
||||
obj.UseDamage1Subtract mustEqual false
|
||||
}
|
||||
|
||||
"define (custom)" in {
|
||||
val obj = new ProjectileDefinition(31) //9mmbullet_projectile
|
||||
obj.Damage0 = 2
|
||||
obj.Damage1 = 4
|
||||
obj.Damage2 = 8
|
||||
obj.Damage3 = 16
|
||||
obj.Damage4 = 32
|
||||
obj.Acceleration = 5
|
||||
obj.AccelerationUntil = 5.5f
|
||||
obj.ProjectileDamageType = DamageType.Splash
|
||||
obj.ProjectileDamageTypeSecondary = DamageType.Radiation
|
||||
obj.DegradeDelay = 11.1f
|
||||
obj.DegradeMultiplier = 22.2f
|
||||
obj.InitialVelocity = 50
|
||||
obj.Lifespan = 11.2f
|
||||
obj.DamageAtEdge = 3f
|
||||
obj.DamageRadius = 3f
|
||||
obj.UseDamage1Subtract = true
|
||||
|
||||
obj.Damage0 mustEqual 2
|
||||
obj.Damage1 mustEqual 4
|
||||
obj.Damage2 mustEqual 8
|
||||
obj.Damage3 mustEqual 16
|
||||
obj.Damage4 mustEqual 32
|
||||
obj.Acceleration mustEqual 5
|
||||
obj.AccelerationUntil mustEqual 5.5f
|
||||
obj.ProjectileDamageType mustEqual DamageType.Splash
|
||||
obj.ProjectileDamageTypeSecondary mustEqual DamageType.Radiation
|
||||
obj.DegradeDelay mustEqual 11.1f
|
||||
obj.DegradeMultiplier mustEqual 22.2f
|
||||
obj.InitialVelocity mustEqual 50
|
||||
obj.Lifespan mustEqual 11.2f
|
||||
obj.DamageAtEdge mustEqual 3f
|
||||
obj.DamageRadius mustEqual 3f
|
||||
obj.UseDamage1Subtract mustEqual true
|
||||
}
|
||||
|
||||
"define (failure)" in {
|
||||
Projectiles(31) mustEqual Projectiles.bullet_9mm_projectile
|
||||
try {
|
||||
ProjectileDefinition(Projectiles.bullet_9mm_projectile) //passes
|
||||
} catch {
|
||||
case _: NoSuchElementException =>
|
||||
ko
|
||||
}
|
||||
|
||||
Projectiles(2) must throwA[NoSuchElementException]
|
||||
new ProjectileDefinition(2) must throwA[NoSuchElementException]
|
||||
}
|
||||
|
||||
"cascade damage values" in {
|
||||
val obj = new ProjectileDefinition(31) //9mmbullet_projectile
|
||||
obj.Damage4 = 32
|
||||
obj.Damage3 = 16
|
||||
obj.Damage2 = 8
|
||||
obj.Damage1 = 4
|
||||
obj.Damage0 = 2
|
||||
|
||||
//initial
|
||||
obj.Damage4 mustEqual 32
|
||||
obj.Damage3 mustEqual 16
|
||||
obj.Damage2 mustEqual 8
|
||||
obj.Damage1 mustEqual 4
|
||||
obj.Damage0 mustEqual 2
|
||||
//negate Damage4
|
||||
obj.Damage4 = None
|
||||
obj.Damage4 mustEqual 16
|
||||
obj.Damage3 mustEqual 16
|
||||
obj.Damage2 mustEqual 8
|
||||
obj.Damage1 mustEqual 4
|
||||
obj.Damage0 mustEqual 2
|
||||
//negate Damage3
|
||||
obj.Damage3 = None
|
||||
obj.Damage4 mustEqual 8
|
||||
obj.Damage3 mustEqual 8
|
||||
obj.Damage2 mustEqual 8
|
||||
obj.Damage1 mustEqual 4
|
||||
obj.Damage0 mustEqual 2
|
||||
//negate Damage2
|
||||
obj.Damage2 = None
|
||||
obj.Damage4 mustEqual 4
|
||||
obj.Damage3 mustEqual 4
|
||||
obj.Damage2 mustEqual 4
|
||||
obj.Damage1 mustEqual 4
|
||||
obj.Damage0 mustEqual 2
|
||||
//negate Damage1
|
||||
obj.Damage1 = None
|
||||
obj.Damage4 mustEqual 2
|
||||
obj.Damage3 mustEqual 2
|
||||
obj.Damage2 mustEqual 2
|
||||
obj.Damage1 mustEqual 2
|
||||
obj.Damage0 mustEqual 2
|
||||
//negate Damage0
|
||||
obj.Damage0 = None
|
||||
obj.Damage4 mustEqual 0
|
||||
obj.Damage3 mustEqual 0
|
||||
obj.Damage2 mustEqual 0
|
||||
obj.Damage1 mustEqual 0
|
||||
obj.Damage0 mustEqual 0
|
||||
//set Damage3, set Damage0
|
||||
obj.Damage3 = 13
|
||||
obj.Damage0 = 7
|
||||
obj.Damage4 mustEqual 13
|
||||
obj.Damage3 mustEqual 13
|
||||
obj.Damage2 mustEqual 7
|
||||
obj.Damage1 mustEqual 7
|
||||
obj.Damage0 mustEqual 7
|
||||
}
|
||||
}
|
||||
|
||||
"SourceEntry" should {
|
||||
"construct for players" in {
|
||||
SourceEntry(player) match {
|
||||
case o: PlayerSource =>
|
||||
o.Name mustEqual "TestCharacter"
|
||||
o.Faction mustEqual PlanetSideEmpire.TR
|
||||
o.Seated mustEqual false
|
||||
o.ExoSuit mustEqual ExoSuitType.Standard
|
||||
o.Health mustEqual 0
|
||||
o.Armor mustEqual 0
|
||||
o.Definition mustEqual GlobalDefinitions.avatar
|
||||
o.Position mustEqual Vector3.Zero
|
||||
o.Orientation mustEqual Vector3.Zero
|
||||
o.Velocity mustEqual None
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"construct for vehicles" in {
|
||||
SourceEntry(fury) match {
|
||||
case o: VehicleSource =>
|
||||
o.Name mustEqual "Fury"
|
||||
o.Faction mustEqual PlanetSideEmpire.NEUTRAL
|
||||
o.Definition mustEqual GlobalDefinitions.fury
|
||||
o.Health mustEqual 650
|
||||
o.Shields mustEqual 0
|
||||
o.Position mustEqual Vector3.Zero
|
||||
o.Orientation mustEqual Vector3.Zero
|
||||
o.Velocity mustEqual None
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"construct for generic object" in {
|
||||
val obj = Locker()
|
||||
SourceEntry(obj) match {
|
||||
case o: ObjectSource =>
|
||||
o.obj mustEqual obj
|
||||
o.Name mustEqual "Mb Locker"
|
||||
o.Faction mustEqual PlanetSideEmpire.NEUTRAL
|
||||
o.Definition mustEqual GlobalDefinitions.mb_locker
|
||||
o.Position mustEqual Vector3.Zero
|
||||
o.Orientation mustEqual Vector3.Zero
|
||||
o.Velocity mustEqual None
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"contain timely information" in {
|
||||
val obj =
|
||||
Player(Avatar(0, "TestCharacter-alt", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
obj.VehicleSeated = Some(PlanetSideGUID(1))
|
||||
obj.Position = Vector3(1.2f, 3.4f, 5.6f)
|
||||
obj.Orientation = Vector3(2.1f, 4.3f, 6.5f)
|
||||
obj.Velocity = Some(Vector3(1.1f, 2.2f, 3.3f))
|
||||
val sobj = SourceEntry(obj)
|
||||
obj.VehicleSeated = None
|
||||
obj.Position = Vector3.Zero
|
||||
obj.Orientation = Vector3.Zero
|
||||
obj.Velocity = None
|
||||
obj.ExoSuit = ExoSuitType.Agile
|
||||
|
||||
sobj match {
|
||||
case o: PlayerSource =>
|
||||
o.Name mustEqual "TestCharacter-alt"
|
||||
o.Faction mustEqual PlanetSideEmpire.TR
|
||||
o.Seated mustEqual true
|
||||
o.ExoSuit mustEqual ExoSuitType.Standard
|
||||
o.Definition mustEqual GlobalDefinitions.avatar
|
||||
o.Position mustEqual Vector3(1.2f, 3.4f, 5.6f)
|
||||
o.Orientation mustEqual Vector3(2.1f, 4.3f, 6.5f)
|
||||
o.Velocity mustEqual Some(Vector3(1.1f, 2.2f, 3.3f))
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"Projectile" should {
|
||||
val beamer_def = GlobalDefinitions.beamer
|
||||
val beamer_wep = Tool(beamer_def)
|
||||
val firemode = beamer_wep.FireMode
|
||||
val projectile = beamer_wep.Projectile
|
||||
|
||||
"construct" in {
|
||||
val obj = Projectile(
|
||||
beamer_wep.Projectile,
|
||||
beamer_wep.Definition,
|
||||
beamer_wep.FireMode,
|
||||
PlayerSource(player),
|
||||
beamer_def.ObjectId,
|
||||
Vector3(1.2f, 3.4f, 5.6f),
|
||||
Vector3(0.2f, 0.4f, 0.6f)
|
||||
)
|
||||
obj.profile mustEqual projectile
|
||||
obj.tool_def mustEqual beamer_def
|
||||
obj.fire_mode mustEqual firemode
|
||||
obj.owner match {
|
||||
case _: PlayerSource =>
|
||||
ok
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
obj.attribute_to mustEqual obj.tool_def.ObjectId
|
||||
obj.shot_origin mustEqual Vector3(1.2f, 3.4f, 5.6f)
|
||||
obj.shot_angle mustEqual Vector3(0.2f, 0.4f, 0.6f)
|
||||
obj.fire_time <= System.nanoTime mustEqual true
|
||||
obj.isResolved mustEqual false
|
||||
}
|
||||
|
||||
"construct (different attribute)" in {
|
||||
val obj1 = Projectile(
|
||||
beamer_wep.Projectile,
|
||||
beamer_wep.Definition,
|
||||
beamer_wep.FireMode,
|
||||
player,
|
||||
Vector3(1.2f, 3.4f, 5.6f),
|
||||
Vector3(0.2f, 0.4f, 0.6f)
|
||||
)
|
||||
obj1.attribute_to mustEqual obj1.tool_def.ObjectId
|
||||
|
||||
val obj2 = Projectile(
|
||||
beamer_wep.Projectile,
|
||||
beamer_wep.Definition,
|
||||
beamer_wep.FireMode,
|
||||
PlayerSource(player),
|
||||
65,
|
||||
Vector3(1.2f, 3.4f, 5.6f),
|
||||
Vector3(0.2f, 0.4f, 0.6f)
|
||||
)
|
||||
obj2.attribute_to == obj2.tool_def.ObjectId mustEqual false
|
||||
obj2.attribute_to mustEqual 65
|
||||
}
|
||||
|
||||
"resolve" in {
|
||||
val obj = Projectile(
|
||||
projectile,
|
||||
beamer_def,
|
||||
firemode,
|
||||
PlayerSource(player),
|
||||
beamer_def.ObjectId,
|
||||
Vector3.Zero,
|
||||
Vector3.Zero
|
||||
)
|
||||
obj.isResolved mustEqual false
|
||||
obj.isMiss mustEqual false
|
||||
|
||||
obj.Resolve()
|
||||
obj.isResolved mustEqual true
|
||||
obj.isMiss mustEqual false
|
||||
}
|
||||
|
||||
"missed" in {
|
||||
val obj = Projectile(
|
||||
projectile,
|
||||
beamer_def,
|
||||
firemode,
|
||||
PlayerSource(player),
|
||||
beamer_def.ObjectId,
|
||||
Vector3.Zero,
|
||||
Vector3.Zero
|
||||
)
|
||||
obj.isResolved mustEqual false
|
||||
obj.isMiss mustEqual false
|
||||
|
||||
obj.Miss()
|
||||
obj.isResolved mustEqual true
|
||||
obj.isMiss mustEqual true
|
||||
}
|
||||
}
|
||||
|
||||
"ResolvedProjectile" should {
|
||||
val beamer_wep = Tool(GlobalDefinitions.beamer)
|
||||
val p_source = PlayerSource(player)
|
||||
val player2 = Player(Avatar(0, "TestTarget", PlanetSideEmpire.NC, CharacterGender.Female, 1, CharacterVoice.Mute))
|
||||
val p2_source = PlayerSource(player2)
|
||||
val projectile = Projectile(
|
||||
beamer_wep.Projectile,
|
||||
GlobalDefinitions.beamer,
|
||||
beamer_wep.FireMode,
|
||||
p_source,
|
||||
GlobalDefinitions.beamer.ObjectId,
|
||||
Vector3.Zero,
|
||||
Vector3.Zero
|
||||
)
|
||||
val fury_dm = fury.DamageModel
|
||||
|
||||
"construct" in {
|
||||
val obj = ResolvedProjectile(
|
||||
ProjectileResolution.Hit,
|
||||
projectile,
|
||||
PlayerSource(player2),
|
||||
fury_dm,
|
||||
Vector3(1.2f, 3.4f, 5.6f)
|
||||
)
|
||||
obj.resolution mustEqual ProjectileResolution.Hit
|
||||
obj.projectile mustEqual projectile
|
||||
obj.target mustEqual p2_source
|
||||
obj.damage_model mustEqual fury.DamageModel
|
||||
obj.hit_pos mustEqual Vector3(1.2f, 3.4f, 5.6f)
|
||||
}
|
||||
}
|
||||
}
|
||||
444
src/test/scala/objects/RepairableTest.scala
Normal file
444
src/test/scala/objects/RepairableTest.scala
Normal file
|
|
@ -0,0 +1,444 @@
|
|||
// Copyright (c) 2020 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.Props
|
||||
import akka.testkit.TestProbe
|
||||
import base.ActorTest
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
import net.psforever.objects.guid.source.LimitedNumberSource
|
||||
import net.psforever.objects.serverobject.CommonMessages
|
||||
import net.psforever.objects.serverobject.generator.{Generator, GeneratorControl}
|
||||
import net.psforever.objects.serverobject.structures.{Building, StructureType}
|
||||
import net.psforever.objects.serverobject.terminals.{Terminal, TerminalControl}
|
||||
import net.psforever.objects.serverobject.turret.{FacilityTurret, FacilityTurretControl}
|
||||
import net.psforever.objects.vehicles.VehicleControl
|
||||
import net.psforever.objects.zones.{Zone, ZoneMap}
|
||||
import net.psforever.packet.game.{InventoryStateMessage, RepairMessage}
|
||||
import net.psforever.types._
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
/*
|
||||
the generator is used to test basic entity repair
|
||||
essentially, treat it more as a generic entity whose object type is repairable
|
||||
see GeneratorTest in relation to what the generator does above and beyond that during repair
|
||||
*/
|
||||
class RepairableEntityRepairTest extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(10))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
|
||||
GUID(guid)
|
||||
}
|
||||
val building = Building("test-building", 1, 1, zone, StructureType.Facility) //guid=1
|
||||
val gen = Generator(GlobalDefinitions.generator) //guid=2
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=3
|
||||
player1.Spawn()
|
||||
guid.register(building, 1)
|
||||
guid.register(gen, 2)
|
||||
guid.register(player1, 3)
|
||||
building.Position = Vector3(1, 0, 0)
|
||||
building.Zone = zone
|
||||
building.Amenities = gen
|
||||
gen.Position = Vector3(1, 0, 0)
|
||||
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
||||
val activityProbe = TestProbe()
|
||||
val avatarProbe = TestProbe()
|
||||
val buildingProbe = TestProbe()
|
||||
zone.Activity = activityProbe.ref
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
building.Actor = buildingProbe.ref
|
||||
val tool = Tool(GlobalDefinitions.nano_dispenser) //4 & 5
|
||||
guid.register(tool, 4)
|
||||
guid.register(tool.AmmoSlot.Box, 5)
|
||||
expectNoMessage(200 milliseconds)
|
||||
//we're not testing that the math is correct
|
||||
|
||||
"RepairableEntity" should {
|
||||
"handle repairs" in {
|
||||
assert(gen.Health == gen.Definition.DefaultHealth) //ideal
|
||||
val originalHealth = gen.Health -= 50
|
||||
assert(gen.Health < gen.Definition.DefaultHealth) //damage
|
||||
gen.Actor ! CommonMessages.Use(player1, Some(tool)) //repair
|
||||
|
||||
val msg123 = avatarProbe.receiveN(3, 500 milliseconds)
|
||||
assert(
|
||||
msg123.head match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction
|
||||
.SendResponse(PlanetSideGUID(0), InventoryStateMessage(PlanetSideGUID(5), _, PlanetSideGUID(4), _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg123(1) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg123(2) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction.SendResponse(PlanetSideGUID(0), RepairMessage(PlanetSideGUID(2), _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(originalHealth < gen.Health) //generator repaired a bit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RepairableEntityNotRepairTest extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(10))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
|
||||
GUID(guid)
|
||||
}
|
||||
val building = Building("test-building", 1, 1, zone, StructureType.Facility) //guid=1
|
||||
val gen = Generator(GlobalDefinitions.generator) //guid=2
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=3
|
||||
player1.Spawn()
|
||||
guid.register(building, 1)
|
||||
guid.register(gen, 2)
|
||||
guid.register(player1, 3)
|
||||
building.Position = Vector3(1, 0, 0)
|
||||
building.Zone = zone
|
||||
building.Amenities = gen
|
||||
gen.Position = Vector3(1, 0, 0)
|
||||
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
||||
val activityProbe = TestProbe()
|
||||
val avatarProbe = TestProbe()
|
||||
val buildingProbe = TestProbe()
|
||||
zone.Activity = activityProbe.ref
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
building.Actor = buildingProbe.ref
|
||||
val tool = Tool(GlobalDefinitions.nano_dispenser) //4 & 5
|
||||
guid.register(tool, 4)
|
||||
guid.register(tool.AmmoSlot.Box, 5)
|
||||
expectNoMessage(200 milliseconds)
|
||||
//we're not testing that the math is correct
|
||||
|
||||
"RepairableEntity" should {
|
||||
"not repair if health is already full" in {
|
||||
assert(gen.Health == gen.Definition.DefaultHealth) //ideal
|
||||
gen.Actor ! CommonMessages.Use(player1, Some(tool)) //repair?
|
||||
avatarProbe.expectNoMessage(1000 milliseconds) //no messages
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RepairableAmenityTest extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(10))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
|
||||
GUID(guid)
|
||||
}
|
||||
val building = Building("test-building", 1, 1, zone, StructureType.Facility) //guid=1
|
||||
val term = Terminal(GlobalDefinitions.order_terminal) //guid=2
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=3
|
||||
player1.Spawn()
|
||||
guid.register(building, 1)
|
||||
guid.register(term, 2)
|
||||
guid.register(player1, 3)
|
||||
building.Position = Vector3(1, 0, 0)
|
||||
building.Zone = zone
|
||||
building.Amenities = term
|
||||
term.Position = Vector3(1, 0, 0)
|
||||
term.Actor = system.actorOf(Props(classOf[TerminalControl], term), "terminal-control")
|
||||
val activityProbe = TestProbe()
|
||||
val avatarProbe = TestProbe()
|
||||
val buildingProbe = TestProbe()
|
||||
zone.Activity = activityProbe.ref
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
building.Actor = buildingProbe.ref
|
||||
|
||||
val tool = Tool(GlobalDefinitions.nano_dispenser) //4 & 5
|
||||
guid.register(tool, 4)
|
||||
guid.register(tool.AmmoSlot.Box, 5)
|
||||
expectNoMessage(200 milliseconds)
|
||||
//we're not testing that the math is correct
|
||||
|
||||
"RepairableAmenity" should {
|
||||
"send initialization messages upon restoration" in {
|
||||
//the decimator does enough damage to one-shot this terminal from any initial health
|
||||
val originalHealth = term.Health = term.Definition.RepairRestoresAt - 1 //initial state manip
|
||||
term.Destroyed = true
|
||||
assert(originalHealth < term.Definition.RepairRestoresAt)
|
||||
assert(term.Destroyed)
|
||||
|
||||
term.Actor ! CommonMessages.Use(player1, Some(tool))
|
||||
val msg12345 = avatarProbe.receiveN(5, 500 milliseconds)
|
||||
assert(
|
||||
msg12345.head match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction
|
||||
.SendResponse(PlanetSideGUID(0), InventoryStateMessage(PlanetSideGUID(5), _, PlanetSideGUID(4), _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg12345(1) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg12345(2) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 50, 0)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg12345(3) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 51, 0)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg12345(4) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction.SendResponse(PlanetSideGUID(0), RepairMessage(PlanetSideGUID(2), _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(term.Health > term.Definition.RepairRestoresAt)
|
||||
assert(!term.Destroyed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RepairableTurretWeapon extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(10))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
val building = Building("test-building", 1, 1, zone, StructureType.Facility) //guid=1
|
||||
val activityProbe = TestProbe()
|
||||
val avatarProbe = TestProbe()
|
||||
val vehicleProbe = TestProbe()
|
||||
val buildingProbe = TestProbe()
|
||||
zone.Activity = activityProbe.ref
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
zone.VehicleEvents = vehicleProbe.ref
|
||||
building.Actor = buildingProbe.ref
|
||||
|
||||
val turret = new FacilityTurret(GlobalDefinitions.manned_turret) //2, 5, 6
|
||||
turret.Actor = system.actorOf(Props(classOf[FacilityTurretControl], turret), "turret-control")
|
||||
turret.Zone = zone
|
||||
turret.Position = Vector3(1, 0, 0)
|
||||
val turretWeapon = turret.Weapons.values.head.Equipment.get.asInstanceOf[Tool]
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=3
|
||||
player1.Spawn()
|
||||
player1.Position = Vector3(2, 2, 2)
|
||||
val player1Probe = TestProbe()
|
||||
player1.Actor = player1Probe.ref
|
||||
|
||||
guid.register(building, 1)
|
||||
guid.register(turret, 2)
|
||||
guid.register(player1, 3)
|
||||
guid.register(turretWeapon, 5)
|
||||
guid.register(turretWeapon.AmmoSlot.Box, 6)
|
||||
building.Position = Vector3(1, 0, 0)
|
||||
building.Zone = zone
|
||||
building.Amenities = turret
|
||||
|
||||
val tool = Tool(GlobalDefinitions.nano_dispenser) //7 & 8
|
||||
guid.register(tool, 7)
|
||||
guid.register(tool.AmmoSlot.Box, 8)
|
||||
|
||||
"RepairableTurretWeapon" should {
|
||||
"handle repairs and restoration" in {
|
||||
turret.Health = turret.Definition.RepairRestoresAt - 1 //initial state manip
|
||||
turret.Destroyed = true //initial state manip
|
||||
assert(turret.Health < turret.Definition.RepairRestoresAt)
|
||||
assert(turret.Destroyed)
|
||||
|
||||
turret.Actor ! CommonMessages.Use(player1, Some(tool))
|
||||
val msg12345 = avatarProbe.receiveN(5, 500 milliseconds)
|
||||
val msg4 = vehicleProbe.receiveOne(500 milliseconds)
|
||||
assert(
|
||||
msg12345.head match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction
|
||||
.SendResponse(PlanetSideGUID(0), InventoryStateMessage(PlanetSideGUID(8), _, PlanetSideGUID(7), _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg12345(1) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
//msg12345(2) and msg12345(3) are related to RepairableAmenity
|
||||
assert(
|
||||
msg12345(4) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction.SendResponse(PlanetSideGUID(0), RepairMessage(PlanetSideGUID(2), _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg4 match {
|
||||
case VehicleServiceMessage("test", VehicleAction.EquipmentInSlot(_, PlanetSideGUID(2), 1, t))
|
||||
if t eq turretWeapon =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(turret.Health > turret.Definition.RepairRestoresAt)
|
||||
assert(!turret.Destroyed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RepairableVehicleRepair extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(10))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
val avatarProbe = TestProbe()
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
|
||||
val atv = Vehicle(GlobalDefinitions.quadassault) //guid=1, 2, 3
|
||||
atv.Actor = system.actorOf(Props(classOf[VehicleControl], atv), "vehicle-control")
|
||||
atv.Position = Vector3(1, 0, 0)
|
||||
val atvWeapon = atv.Weapons(1).Equipment.get.asInstanceOf[Tool]
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=4
|
||||
player1.Spawn()
|
||||
player1.Position = Vector3(2, 2, 2)
|
||||
val player1Probe = TestProbe()
|
||||
player1.Actor = player1Probe.ref
|
||||
|
||||
guid.register(atv, 1)
|
||||
guid.register(atvWeapon, 2)
|
||||
guid.register(atvWeapon.AmmoSlot.Box, 3)
|
||||
guid.register(player1, 4)
|
||||
atv.Zone = zone
|
||||
|
||||
val tool = Tool(GlobalDefinitions.nano_dispenser) //5 & 6
|
||||
guid.register(tool, 5)
|
||||
guid.register(tool.AmmoSlot.Box, 6)
|
||||
|
||||
"RepairableVehicle" should {
|
||||
"handle repairs" in {
|
||||
val originalHealth = atv.Health = atv.Definition.DamageDestroysAt + 1 //initial state manip
|
||||
assert(atv.Health == originalHealth)
|
||||
|
||||
atv.Actor ! CommonMessages.Use(player1, Some(tool))
|
||||
val msg123 = avatarProbe.receiveN(3, 500 milliseconds)
|
||||
assert(
|
||||
msg123.head match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction
|
||||
.SendResponse(PlanetSideGUID(0), InventoryStateMessage(PlanetSideGUID(6), _, PlanetSideGUID(5), _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg123(1) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(1), 0, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg123(2) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction.SendResponse(PlanetSideGUID(0), RepairMessage(PlanetSideGUID(1), _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(atv.Health > originalHealth)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RepairableVehicleRestoration extends ActorTest {
|
||||
/*
|
||||
no messages are dispatched, in this case, because most vehicles are flagged to not be repairable if destroyed
|
||||
*/
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(10))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
val avatarProbe = TestProbe()
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
|
||||
val atv = Vehicle(GlobalDefinitions.quadassault) //guid=1, 2, 3
|
||||
atv.Actor = system.actorOf(Props(classOf[VehicleControl], atv), "vehicle-control")
|
||||
atv.Position = Vector3(1, 0, 0)
|
||||
val atvWeapon = atv.Weapons(1).Equipment.get.asInstanceOf[Tool]
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=4
|
||||
player1.Spawn()
|
||||
player1.Position = Vector3(2, 2, 2)
|
||||
val player1Probe = TestProbe()
|
||||
player1.Actor = player1Probe.ref
|
||||
|
||||
guid.register(atv, 1)
|
||||
guid.register(atvWeapon, 2)
|
||||
guid.register(atvWeapon.AmmoSlot.Box, 3)
|
||||
guid.register(player1, 4)
|
||||
atv.Zone = zone
|
||||
|
||||
val tool = Tool(GlobalDefinitions.nano_dispenser) //5 & 6
|
||||
guid.register(tool, 5)
|
||||
guid.register(tool.AmmoSlot.Box, 6)
|
||||
|
||||
"RepairableVehicle" should {
|
||||
"will not restore a destroyed vehicle to working order" in {
|
||||
atv.Health = atv.Definition.DamageDestroysAt - 1 //initial state manip
|
||||
atv.Destroyed = true //initial state manip
|
||||
assert(atv.Health <= atv.Definition.DamageDestroysAt)
|
||||
assert(atv.Destroyed)
|
||||
|
||||
atv.Actor ! CommonMessages.Use(player1, Some(tool))
|
||||
avatarProbe.expectNoMessage(500 milliseconds)
|
||||
assert(atv.Health == 0) //set to zero explicitly
|
||||
assert(atv.Destroyed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object RepairableTest {}
|
||||
395
src/test/scala/objects/ResourceSiloTest.scala
Normal file
395
src/test/scala/objects/ResourceSiloTest.scala
Normal file
|
|
@ -0,0 +1,395 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.{Actor, Props}
|
||||
import akka.routing.RandomPool
|
||||
import akka.testkit.TestProbe
|
||||
import base.ActorTest
|
||||
import net.psforever.actors.zone.{BuildingActor, ZoneActor}
|
||||
import net.psforever.objects.guid.{NumberPoolHub, TaskResolver}
|
||||
import net.psforever.objects.guid.source.LimitedNumberSource
|
||||
import net.psforever.objects.serverobject.CommonMessages
|
||||
import net.psforever.objects.{GlobalDefinitions, Ntu, Player, Vehicle}
|
||||
import net.psforever.objects.serverobject.resourcesilo.{ResourceSilo, ResourceSiloControl, ResourceSiloDefinition}
|
||||
import net.psforever.objects.serverobject.structures.{Building, StructureType}
|
||||
import net.psforever.objects.serverobject.transfer.TransferBehavior
|
||||
import net.psforever.objects.zones.{Zone, ZoneMap}
|
||||
import net.psforever.packet.game.UseItemMessage
|
||||
import net.psforever.types._
|
||||
import org.specs2.mutable.Specification
|
||||
import net.psforever.services.ServiceManager
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
import akka.actor.typed.scaladsl.adapter._
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
class ResourceSiloTest extends Specification {
|
||||
"Resource Silo" should {
|
||||
"define" in {
|
||||
val obj = new ResourceSiloDefinition
|
||||
obj.ObjectId mustEqual 731
|
||||
}
|
||||
|
||||
"construct" in {
|
||||
val obj = ResourceSilo()
|
||||
obj.Definition mustEqual GlobalDefinitions.resource_silo
|
||||
obj.MaxNtuCapacitor mustEqual 1000
|
||||
obj.NtuCapacitor mustEqual 0
|
||||
obj.LowNtuWarningOn mustEqual true
|
||||
obj.CapacitorDisplay mustEqual 0
|
||||
//
|
||||
obj.NtuCapacitor = 50
|
||||
obj.LowNtuWarningOn = false
|
||||
obj.NtuCapacitor mustEqual 50
|
||||
obj.LowNtuWarningOn mustEqual false
|
||||
obj.CapacitorDisplay mustEqual 1
|
||||
}
|
||||
|
||||
"charge level can not exceed limits(0 to maximum)" in {
|
||||
val obj = ResourceSilo()
|
||||
obj.NtuCapacitor mustEqual 0
|
||||
obj.NtuCapacitor = -5
|
||||
obj.NtuCapacitor mustEqual 0
|
||||
|
||||
obj.NtuCapacitor = obj.MaxNtuCapacitor + 100
|
||||
obj.NtuCapacitor mustEqual 1000
|
||||
obj.NtuCapacitor mustEqual obj.MaxNtuCapacitor
|
||||
}
|
||||
|
||||
"using the silo generates a charge event" in {
|
||||
val msg = UseItemMessage(
|
||||
PlanetSideGUID(1),
|
||||
PlanetSideGUID(0),
|
||||
PlanetSideGUID(2),
|
||||
0L,
|
||||
false,
|
||||
Vector3(0f, 0f, 0f),
|
||||
Vector3(0f, 0f, 0f),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0L
|
||||
) //faked
|
||||
ResourceSilo().Use(ResourceSiloTest.player, msg) mustEqual ResourceSilo.ChargeEvent()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ResourceSiloControlStartupTest extends ActorTest {
|
||||
val serviceManager = ServiceManager.boot(system)
|
||||
serviceManager ! ServiceManager.Register(RandomPool(1).props(Props[TaskResolver]()), "taskResolver")
|
||||
val obj = ResourceSilo()
|
||||
obj.GUID = PlanetSideGUID(1)
|
||||
val probe = TestProbe()
|
||||
serviceManager ! ServiceManager.Register(Props(classOf[ResourceSiloTest.ProbedAvatarService], probe), "avatar")
|
||||
|
||||
"Resource silo" should {
|
||||
"startup properly" in {
|
||||
expectNoMessage(500 milliseconds)
|
||||
system.actorOf(Props(classOf[ResourceSiloControl], obj), "test-silo")
|
||||
expectNoMessage(1 seconds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ResourceSiloControlUseTest extends ActorTest {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(10))
|
||||
val map = new ZoneMap("test")
|
||||
val zone = new Zone("test", map, 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
zone.actor = system.spawnAnonymous(ZoneActor(zone))
|
||||
val building = new Building(
|
||||
"Building",
|
||||
building_guid = 0,
|
||||
map_id = 0,
|
||||
zone,
|
||||
StructureType.Building,
|
||||
GlobalDefinitions.building
|
||||
) //guid=1
|
||||
|
||||
val obj = ResourceSilo() //guid=2
|
||||
obj.Actor = system.actorOf(Props(classOf[ResourceSiloControl], obj), "test-silo")
|
||||
obj.Owner = building
|
||||
obj.Actor ! "startup"
|
||||
|
||||
val player = Player(
|
||||
new Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)
|
||||
) //guid=3
|
||||
val vehicle = Vehicle(GlobalDefinitions.ant) //guid=4
|
||||
val probe = new TestProbe(system)
|
||||
|
||||
guid.register(building, 1)
|
||||
guid.register(obj, 2)
|
||||
guid.register(player, 3)
|
||||
guid.register(vehicle, 4)
|
||||
expectNoMessage(200 milliseconds)
|
||||
zone.Transport ! Zone.Vehicle.Spawn(vehicle)
|
||||
vehicle.Seats(0).Occupant = player
|
||||
player.VehicleSeated = vehicle.GUID
|
||||
expectNoMessage(200 milliseconds)
|
||||
system.stop(vehicle.Actor)
|
||||
vehicle.Actor = probe.ref
|
||||
|
||||
"Resource silo" should {
|
||||
"respond when being used" in {
|
||||
expectNoMessage(1 seconds)
|
||||
obj.Actor ! CommonMessages.Use(ResourceSiloTest.player)
|
||||
|
||||
val reply = probe.receiveOne(2000 milliseconds)
|
||||
assert(reply match {
|
||||
case TransferBehavior.Discharging(Ntu.Nanites) => true
|
||||
case _ => false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ResourceSiloControlNtuWarningTest extends ActorTest {
|
||||
val obj = ResourceSilo()
|
||||
obj.GUID = PlanetSideGUID(1)
|
||||
obj.Actor = system.actorOf(Props(classOf[ResourceSiloControl], obj), "test-silo")
|
||||
obj.Actor ! "startup"
|
||||
val zone = new Zone("nowhere", new ZoneMap("nowhere-map"), 0)
|
||||
obj.Owner =
|
||||
new Building("Building", building_guid = 6, map_id = 0, zone, StructureType.Building, GlobalDefinitions.building)
|
||||
obj.Owner.GUID = PlanetSideGUID(6)
|
||||
val zoneEvents = TestProbe("zone-events")
|
||||
|
||||
"Resource silo" should {
|
||||
"announce high ntu" in {
|
||||
zone.AvatarEvents = zoneEvents.ref
|
||||
assert(obj.LowNtuWarningOn)
|
||||
obj.Actor ! ResourceSilo.LowNtuWarning(false)
|
||||
|
||||
val reply = zoneEvents.receiveOne(500 milliseconds)
|
||||
assert(!obj.LowNtuWarningOn)
|
||||
assert(reply.isInstanceOf[AvatarServiceMessage])
|
||||
assert(reply.asInstanceOf[AvatarServiceMessage].forChannel == "nowhere")
|
||||
assert(reply.asInstanceOf[AvatarServiceMessage].actionMessage.isInstanceOf[AvatarAction.PlanetsideAttribute])
|
||||
assert(
|
||||
reply
|
||||
.asInstanceOf[AvatarServiceMessage]
|
||||
.actionMessage
|
||||
.asInstanceOf[AvatarAction.PlanetsideAttribute]
|
||||
.player_guid == PlanetSideGUID(6)
|
||||
)
|
||||
assert(
|
||||
reply
|
||||
.asInstanceOf[AvatarServiceMessage]
|
||||
.actionMessage
|
||||
.asInstanceOf[AvatarAction.PlanetsideAttribute]
|
||||
.attribute_type == 47
|
||||
)
|
||||
assert(
|
||||
reply
|
||||
.asInstanceOf[AvatarServiceMessage]
|
||||
.actionMessage
|
||||
.asInstanceOf[AvatarAction.PlanetsideAttribute]
|
||||
.attribute_value == 0
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ResourceSiloControlUpdate1Test extends ActorTest {
|
||||
val obj = ResourceSilo()
|
||||
obj.GUID = PlanetSideGUID(1)
|
||||
obj.Actor = system.actorOf(Props(classOf[ResourceSiloControl], obj), "test-silo")
|
||||
obj.Actor ! "startup"
|
||||
val zone = new Zone("nowhere", new ZoneMap("nowhere-map"), 0)
|
||||
val bldg =
|
||||
new Building("Building", building_guid = 6, map_id = 0, zone, StructureType.Building, GlobalDefinitions.building)
|
||||
bldg.GUID = PlanetSideGUID(6)
|
||||
obj.Owner = bldg
|
||||
val zoneEvents = TestProbe("zone-events")
|
||||
val buildingEvents = TestProbe("building-events")
|
||||
|
||||
"Resource silo" should {
|
||||
"update the charge level and capacitor display (report high ntu, power restored)" in {
|
||||
zone.AvatarEvents = zoneEvents.ref
|
||||
bldg.Actor = buildingEvents.ref
|
||||
|
||||
assert(obj.NtuCapacitor == 0)
|
||||
assert(obj.CapacitorDisplay == 0)
|
||||
assert(obj.LowNtuWarningOn)
|
||||
obj.Actor ! ResourceSilo.UpdateChargeLevel(305)
|
||||
|
||||
val reply1 = zoneEvents.receiveOne(500 milliseconds)
|
||||
val reply2 = buildingEvents.receiveOne(500 milliseconds)
|
||||
assert(obj.NtuCapacitor == 305)
|
||||
assert(obj.CapacitorDisplay == 4)
|
||||
assert(reply1 match {
|
||||
case AvatarServiceMessage("nowhere", AvatarAction.PlanetsideAttribute(PlanetSideGUID(1), 45, 4)) => true
|
||||
case _ => false
|
||||
})
|
||||
assert(reply2.isInstanceOf[BuildingActor.MapUpdate])
|
||||
|
||||
val reply3 = zoneEvents.receiveOne(500 milliseconds)
|
||||
assert(!obj.LowNtuWarningOn)
|
||||
assert(reply3 match {
|
||||
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
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ResourceSiloControlUpdate2Test extends ActorTest {
|
||||
val obj = ResourceSilo()
|
||||
obj.GUID = PlanetSideGUID(1)
|
||||
obj.Actor = system.actorOf(Props(classOf[ResourceSiloControl], obj), "test-silo")
|
||||
obj.Actor ! "startup"
|
||||
val zone = new Zone("nowhere", new ZoneMap("nowhere-map"), 0)
|
||||
val bldg =
|
||||
new Building("Building", building_guid = 6, map_id = 0, zone, StructureType.Building, GlobalDefinitions.building)
|
||||
bldg.GUID = PlanetSideGUID(6)
|
||||
obj.Owner = bldg
|
||||
val zoneEvents = TestProbe("zone-events")
|
||||
val buildingEvents = TestProbe("building-events")
|
||||
|
||||
"Resource silo" should {
|
||||
"update the charge level and capacitor display (report good ntu)" in {
|
||||
zone.AvatarEvents = zoneEvents.ref
|
||||
bldg.Actor = buildingEvents.ref
|
||||
|
||||
obj.NtuCapacitor = 100
|
||||
obj.LowNtuWarningOn = true
|
||||
assert(obj.NtuCapacitor == 100)
|
||||
assert(obj.CapacitorDisplay == 1)
|
||||
assert(obj.LowNtuWarningOn)
|
||||
obj.Actor ! ResourceSilo.UpdateChargeLevel(105)
|
||||
|
||||
val reply1 = zoneEvents.receiveOne(1000 milliseconds)
|
||||
val reply2 = buildingEvents.receiveOne(1000 milliseconds)
|
||||
assert(obj.NtuCapacitor == 205)
|
||||
assert(obj.CapacitorDisplay == 3)
|
||||
assert(reply1.isInstanceOf[AvatarServiceMessage])
|
||||
assert(reply1.asInstanceOf[AvatarServiceMessage].forChannel == "nowhere")
|
||||
assert(reply1.asInstanceOf[AvatarServiceMessage].actionMessage.isInstanceOf[AvatarAction.PlanetsideAttribute])
|
||||
assert(
|
||||
reply1
|
||||
.asInstanceOf[AvatarServiceMessage]
|
||||
.actionMessage
|
||||
.asInstanceOf[AvatarAction.PlanetsideAttribute]
|
||||
.player_guid == PlanetSideGUID(1)
|
||||
)
|
||||
assert(
|
||||
reply1
|
||||
.asInstanceOf[AvatarServiceMessage]
|
||||
.actionMessage
|
||||
.asInstanceOf[AvatarAction.PlanetsideAttribute]
|
||||
.attribute_type == 45
|
||||
)
|
||||
assert(
|
||||
reply1
|
||||
.asInstanceOf[AvatarServiceMessage]
|
||||
.actionMessage
|
||||
.asInstanceOf[AvatarAction.PlanetsideAttribute]
|
||||
.attribute_value == 3
|
||||
)
|
||||
|
||||
assert(reply2.isInstanceOf[BuildingActor.MapUpdate])
|
||||
|
||||
val reply3 = zoneEvents.receiveOne(500 milliseconds)
|
||||
assert(!obj.LowNtuWarningOn)
|
||||
assert(reply3.isInstanceOf[AvatarServiceMessage])
|
||||
assert(reply3.asInstanceOf[AvatarServiceMessage].forChannel == "nowhere")
|
||||
assert(reply3.asInstanceOf[AvatarServiceMessage].actionMessage.isInstanceOf[AvatarAction.PlanetsideAttribute])
|
||||
assert(
|
||||
reply3
|
||||
.asInstanceOf[AvatarServiceMessage]
|
||||
.actionMessage
|
||||
.asInstanceOf[AvatarAction.PlanetsideAttribute]
|
||||
.player_guid == PlanetSideGUID(6)
|
||||
)
|
||||
assert(
|
||||
reply3
|
||||
.asInstanceOf[AvatarServiceMessage]
|
||||
.actionMessage
|
||||
.asInstanceOf[AvatarAction.PlanetsideAttribute]
|
||||
.attribute_type == 47
|
||||
)
|
||||
assert(
|
||||
reply3
|
||||
.asInstanceOf[AvatarServiceMessage]
|
||||
.actionMessage
|
||||
.asInstanceOf[AvatarAction.PlanetsideAttribute]
|
||||
.attribute_value == 0
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ResourceSiloControlNoUpdateTest extends ActorTest {
|
||||
val obj = ResourceSilo()
|
||||
obj.GUID = PlanetSideGUID(1)
|
||||
obj.Actor = system.actorOf(Props(classOf[ResourceSiloControl], obj), "test-silo")
|
||||
obj.Actor ! "startup"
|
||||
val zone = new Zone("nowhere", new ZoneMap("nowhere-map"), 0)
|
||||
val bldg =
|
||||
new Building("Building", building_guid = 6, map_id = 0, zone, StructureType.Building, GlobalDefinitions.building)
|
||||
bldg.GUID = PlanetSideGUID(6)
|
||||
obj.Owner = bldg
|
||||
val zoneEvents = TestProbe("zone-events")
|
||||
val buildingEvents = TestProbe("building-events")
|
||||
|
||||
"Resource silo" should {
|
||||
"update, but not sufficiently to change the capacitor display" in {
|
||||
zone.AvatarEvents = zoneEvents.ref
|
||||
bldg.Actor = buildingEvents.ref
|
||||
|
||||
obj.NtuCapacitor = 250
|
||||
obj.LowNtuWarningOn = false
|
||||
assert(obj.NtuCapacitor == 250)
|
||||
assert(obj.CapacitorDisplay == 3)
|
||||
assert(!obj.LowNtuWarningOn)
|
||||
obj.Actor ! ResourceSilo.UpdateChargeLevel(50)
|
||||
|
||||
expectNoMessage(500 milliseconds)
|
||||
zoneEvents.expectNoMessage(500 milliseconds)
|
||||
buildingEvents.expectNoMessage(500 milliseconds)
|
||||
assert(
|
||||
obj.NtuCapacitor == 299 || obj.NtuCapacitor == 300
|
||||
) // Just in case the capacitor level drops while waiting for the message check 299 & 300
|
||||
assert(obj.CapacitorDisplay == 3)
|
||||
assert(!obj.LowNtuWarningOn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object ResourceSiloTest {
|
||||
val player = Player(
|
||||
new Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)
|
||||
)
|
||||
|
||||
class ProbedAvatarService(probe: TestProbe) extends Actor {
|
||||
override def receive: Receive = {
|
||||
case msg =>
|
||||
probe.ref ! msg
|
||||
}
|
||||
}
|
||||
|
||||
class ProbedBuildingControl(probe: TestProbe) extends Actor {
|
||||
override def receive: Receive = {
|
||||
case msg =>
|
||||
probe.ref ! msg
|
||||
}
|
||||
}
|
||||
|
||||
class ProbedResourceSiloControl(silo: ResourceSilo, probe: TestProbe) extends ResourceSiloControl(silo) {
|
||||
override def receive: Receive = {
|
||||
case msg =>
|
||||
super.receive.apply(msg)
|
||||
probe.ref ! msg
|
||||
}
|
||||
}
|
||||
}
|
||||
371
src/test/scala/objects/ServerObjectBuilderTest.scala
Normal file
371
src/test/scala/objects/ServerObjectBuilderTest.scala
Normal file
|
|
@ -0,0 +1,371 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.{Actor, ActorContext, Props}
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.GlobalDefinitions
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
import net.psforever.objects.serverobject.ServerObjectBuilder
|
||||
import net.psforever.objects.serverobject.structures.{Building, FoundationBuilder, StructureType, WarpGate}
|
||||
import net.psforever.objects.serverobject.terminals.ProximityTerminal
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.types.{PlanetSideGUID, Vector3}
|
||||
|
||||
import scala.concurrent.duration.Duration
|
||||
|
||||
class BuildingBuilderTest extends ActorTest {
|
||||
"Building object" should {
|
||||
"build" in {
|
||||
val structure: (String, Int, Int, Zone, ActorContext) => Building = Building.Structure(StructureType.Building)
|
||||
val actor = system.actorOf(
|
||||
Props(classOf[ServerObjectBuilderTest.BuildingTestActor], structure, "Building", 10, 10, Zone.Nowhere),
|
||||
"building"
|
||||
)
|
||||
actor ! "!"
|
||||
|
||||
val reply = receiveOne(Duration.create(1000, "ms"))
|
||||
assert(reply.isInstanceOf[Building])
|
||||
assert(reply.asInstanceOf[Building].MapId == 10)
|
||||
assert(reply.asInstanceOf[Building].Zone == Zone.Nowhere)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class WarpGateBuilderTest extends ActorTest {
|
||||
"WarpGate object" should {
|
||||
"build" in {
|
||||
val structure: (String, Int, Int, Zone, ActorContext) => Building = WarpGate.Structure
|
||||
val actor = system.actorOf(
|
||||
Props(classOf[ServerObjectBuilderTest.BuildingTestActor], structure, "wgate", 10, 10, Zone.Nowhere),
|
||||
"wgate"
|
||||
)
|
||||
actor ! "!"
|
||||
|
||||
val reply = receiveOne(Duration.create(1000, "ms"))
|
||||
assert(reply.isInstanceOf[Building])
|
||||
assert(reply.asInstanceOf[Building].MapId == 10)
|
||||
assert(reply.asInstanceOf[Building].Zone == Zone.Nowhere)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DoorObjectBuilderTest1 extends ActorTest {
|
||||
import net.psforever.objects.serverobject.doors.Door
|
||||
"Door object" should {
|
||||
"build" in {
|
||||
val hub = ServerObjectBuilderTest.NumberPoolHub
|
||||
val actor = system.actorOf(
|
||||
Props(classOf[ServerObjectBuilderTest.BuilderTestActor], ServerObjectBuilder(1, Door.Constructor), hub),
|
||||
"door"
|
||||
)
|
||||
actor ! "!"
|
||||
|
||||
val reply = receiveOne(Duration.create(1000, "ms"))
|
||||
assert(reply.isInstanceOf[Door])
|
||||
assert(reply.asInstanceOf[Door].HasGUID)
|
||||
assert(reply.asInstanceOf[Door].GUID == PlanetSideGUID(1))
|
||||
assert(reply == hub(1).get)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DoorObjectBuilderTest2 extends ActorTest {
|
||||
import net.psforever.objects.serverobject.doors.Door
|
||||
"Door object" should {
|
||||
"build" in {
|
||||
val hub = ServerObjectBuilderTest.NumberPoolHub
|
||||
val actor = system.actorOf(
|
||||
Props(
|
||||
classOf[ServerObjectBuilderTest.BuilderTestActor],
|
||||
ServerObjectBuilder(1, Door.Constructor(Vector3(1, 2, 3))),
|
||||
hub
|
||||
),
|
||||
"door"
|
||||
)
|
||||
actor ! "!"
|
||||
|
||||
val reply = receiveOne(Duration.create(1000, "ms"))
|
||||
assert(reply.isInstanceOf[Door])
|
||||
assert(reply.asInstanceOf[Door].Position == Vector3(1, 2, 3))
|
||||
assert(reply.asInstanceOf[Door].HasGUID)
|
||||
assert(reply.asInstanceOf[Door].GUID == PlanetSideGUID(1))
|
||||
assert(reply == hub(1).get)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class IFFLockObjectBuilderTest extends ActorTest {
|
||||
import net.psforever.objects.serverobject.locks.IFFLock
|
||||
"IFFLock object" should {
|
||||
"build" in {
|
||||
val hub = ServerObjectBuilderTest.NumberPoolHub
|
||||
val actor = system.actorOf(
|
||||
Props(
|
||||
classOf[ServerObjectBuilderTest.BuilderTestActor],
|
||||
ServerObjectBuilder(1, IFFLock.Constructor(Vector3(0f, 0f, 0f), Vector3(0f, 0f, 0f))),
|
||||
hub
|
||||
),
|
||||
"lock"
|
||||
)
|
||||
actor ! "!"
|
||||
|
||||
val reply = receiveOne(Duration.create(1000, "ms"))
|
||||
assert(reply.isInstanceOf[IFFLock])
|
||||
assert(reply.asInstanceOf[IFFLock].HasGUID)
|
||||
assert(reply.asInstanceOf[IFFLock].GUID == PlanetSideGUID(1))
|
||||
assert(reply == hub(1).get)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ImplantTerminalMechObjectBuilderTest extends ActorTest {
|
||||
import net.psforever.objects.serverobject.implantmech.ImplantTerminalMech
|
||||
"Implant terminal mech object" should {
|
||||
"build" in {
|
||||
val hub = ServerObjectBuilderTest.NumberPoolHub
|
||||
val actor = system.actorOf(
|
||||
Props(
|
||||
classOf[ServerObjectBuilderTest.BuilderTestActor],
|
||||
ServerObjectBuilder(1, ImplantTerminalMech.Constructor(Vector3.Zero)),
|
||||
hub
|
||||
),
|
||||
"mech"
|
||||
)
|
||||
actor ! "!"
|
||||
|
||||
val reply = receiveOne(Duration.create(1000, "ms"))
|
||||
assert(reply.isInstanceOf[ImplantTerminalMech])
|
||||
assert(reply.asInstanceOf[ImplantTerminalMech].HasGUID)
|
||||
assert(reply.asInstanceOf[ImplantTerminalMech].GUID == PlanetSideGUID(1))
|
||||
assert(reply == hub(1).get)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TerminalObjectBuilderTest extends ActorTest {
|
||||
import net.psforever.objects.GlobalDefinitions.order_terminal
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
"Terminal object" should {
|
||||
"build" in {
|
||||
val hub = ServerObjectBuilderTest.NumberPoolHub
|
||||
val actor = system.actorOf(
|
||||
Props(
|
||||
classOf[ServerObjectBuilderTest.BuilderTestActor],
|
||||
ServerObjectBuilder(1, Terminal.Constructor(Vector3(1.1f, 2.2f, 3.3f), order_terminal)),
|
||||
hub
|
||||
),
|
||||
"term"
|
||||
)
|
||||
actor ! "!"
|
||||
|
||||
val reply = receiveOne(Duration.create(1000, "ms"))
|
||||
assert(reply.isInstanceOf[Terminal])
|
||||
assert(reply.asInstanceOf[Terminal].HasGUID)
|
||||
assert(reply.asInstanceOf[Terminal].GUID == PlanetSideGUID(1))
|
||||
assert(reply.asInstanceOf[Terminal].Position == Vector3(1.1f, 2.2f, 3.3f))
|
||||
assert(reply == hub(1).get)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ProximityTerminalObjectBuilderTest extends ActorTest {
|
||||
import net.psforever.objects.GlobalDefinitions.medical_terminal
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
"Terminal object" should {
|
||||
"build" in {
|
||||
val hub = ServerObjectBuilderTest.NumberPoolHub
|
||||
val actor = system.actorOf(
|
||||
Props(
|
||||
classOf[ServerObjectBuilderTest.BuilderTestActor],
|
||||
ServerObjectBuilder(1, ProximityTerminal.Constructor(medical_terminal)),
|
||||
hub
|
||||
),
|
||||
"term"
|
||||
)
|
||||
actor ! "!"
|
||||
|
||||
val reply = receiveOne(Duration.create(1000, "ms"))
|
||||
assert(reply.isInstanceOf[Terminal])
|
||||
assert(reply.asInstanceOf[Terminal].HasGUID)
|
||||
assert(reply.asInstanceOf[Terminal].GUID == PlanetSideGUID(1))
|
||||
assert(reply == hub(1).get)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleSpawnPadObjectBuilderTest extends ActorTest {
|
||||
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
|
||||
"Vehicle spawn pad object" should {
|
||||
"build" in {
|
||||
val hub = ServerObjectBuilderTest.NumberPoolHub
|
||||
val actor = system.actorOf(
|
||||
Props(
|
||||
classOf[ServerObjectBuilderTest.BuilderTestActor],
|
||||
ServerObjectBuilder(
|
||||
1,
|
||||
VehicleSpawnPad
|
||||
.Constructor(Vector3(1.1f, 2.2f, 3.3f), GlobalDefinitions.mb_pad_creation, Vector3(4.4f, 5.5f, 6.6f))
|
||||
),
|
||||
hub
|
||||
),
|
||||
"pad"
|
||||
)
|
||||
actor ! "!"
|
||||
|
||||
val reply = receiveOne(Duration.create(1000, "ms"))
|
||||
assert(reply.isInstanceOf[VehicleSpawnPad])
|
||||
assert(reply.asInstanceOf[VehicleSpawnPad].HasGUID)
|
||||
assert(reply.asInstanceOf[VehicleSpawnPad].GUID == PlanetSideGUID(1))
|
||||
assert(reply.asInstanceOf[VehicleSpawnPad].Position == Vector3(1.1f, 2.2f, 3.3f))
|
||||
assert(reply.asInstanceOf[VehicleSpawnPad].Orientation == Vector3(4.4f, 5.5f, 6.6f))
|
||||
assert(reply == hub(1).get)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LocalProjectileBuilderTest extends ActorTest {
|
||||
import net.psforever.objects.LocalProjectile
|
||||
"Local projectile object" 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
|
||||
"Locker object" should {
|
||||
"build" in {
|
||||
val hub = ServerObjectBuilderTest.NumberPoolHub
|
||||
val actor = system.actorOf(
|
||||
Props(classOf[ServerObjectBuilderTest.BuilderTestActor], ServerObjectBuilder(1, Locker.Constructor), hub),
|
||||
"locker"
|
||||
)
|
||||
actor ! "!"
|
||||
|
||||
val reply = receiveOne(Duration.create(1000, "ms"))
|
||||
assert(reply.isInstanceOf[Locker])
|
||||
assert(reply.asInstanceOf[Locker].HasGUID)
|
||||
assert(reply.asInstanceOf[Locker].GUID == PlanetSideGUID(1))
|
||||
assert(reply == hub(1).get)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ResourceSiloObjectBuilderTest extends ActorTest {
|
||||
import net.psforever.objects.serverobject.resourcesilo.ResourceSilo
|
||||
"Resource silo object" should {
|
||||
"build" in {
|
||||
val hub = ServerObjectBuilderTest.NumberPoolHub
|
||||
val actor = system.actorOf(
|
||||
Props(
|
||||
classOf[ServerObjectBuilderTest.BuilderTestActor],
|
||||
ServerObjectBuilder(1, ResourceSilo.Constructor(Vector3(0f, 0f, 0f))),
|
||||
hub
|
||||
),
|
||||
"resource-silo"
|
||||
)
|
||||
actor ! "startup"
|
||||
|
||||
val reply = receiveOne(Duration.create(1000, "ms"))
|
||||
assert(reply.isInstanceOf[ResourceSilo])
|
||||
assert(reply.asInstanceOf[ResourceSilo].HasGUID)
|
||||
assert(reply.asInstanceOf[ResourceSilo].GUID == PlanetSideGUID(1))
|
||||
assert(reply == hub(1).get)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SpawnTubeObjectBuilderTest extends ActorTest {
|
||||
import net.psforever.objects.serverobject.tube.SpawnTube
|
||||
"Spawn tube object" should {
|
||||
"build" in {
|
||||
val hub = ServerObjectBuilderTest.NumberPoolHub
|
||||
val actor = system.actorOf(
|
||||
Props(
|
||||
classOf[ServerObjectBuilderTest.BuilderTestActor],
|
||||
ServerObjectBuilder(1, SpawnTube.Constructor(Vector3(3980.4062f, 4267.3047f, 257.5625f), Vector3(0, 0, 90))),
|
||||
hub
|
||||
),
|
||||
"spawn-tube"
|
||||
)
|
||||
actor ! "!"
|
||||
|
||||
val reply = receiveOne(Duration.create(1000, "ms"))
|
||||
assert(reply.isInstanceOf[SpawnTube])
|
||||
assert(reply.asInstanceOf[SpawnTube].HasGUID)
|
||||
assert(reply.asInstanceOf[SpawnTube].GUID == PlanetSideGUID(1))
|
||||
assert(reply.asInstanceOf[SpawnTube].Position == Vector3(3980.4062f, 4267.3047f, 257.5625f))
|
||||
assert(reply.asInstanceOf[SpawnTube].Orientation == Vector3(0, 0, 90))
|
||||
assert(reply == hub(1).get)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FacilityTurretObjectBuilderTest extends ActorTest {
|
||||
import net.psforever.objects.GlobalDefinitions.manned_turret
|
||||
import net.psforever.objects.serverobject.turret.FacilityTurret
|
||||
"FacilityTurretObjectBuilder" should {
|
||||
"build" in {
|
||||
val hub = ServerObjectBuilderTest.NumberPoolHub
|
||||
val actor = system.actorOf(
|
||||
Props(
|
||||
classOf[ServerObjectBuilderTest.BuilderTestActor],
|
||||
ServerObjectBuilder(1, FacilityTurret.Constructor(manned_turret)),
|
||||
hub
|
||||
),
|
||||
"manned-turret"
|
||||
)
|
||||
actor ! "!"
|
||||
|
||||
val reply = receiveOne(Duration.create(1000, "ms"))
|
||||
assert(reply.isInstanceOf[FacilityTurret])
|
||||
assert(reply.asInstanceOf[FacilityTurret].HasGUID)
|
||||
assert(reply.asInstanceOf[FacilityTurret].GUID == PlanetSideGUID(1))
|
||||
assert(reply == hub(1).get)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object ServerObjectBuilderTest {
|
||||
import net.psforever.objects.guid.source.LimitedNumberSource
|
||||
def NumberPoolHub: NumberPoolHub = {
|
||||
val obj = new NumberPoolHub(new LimitedNumberSource(2))
|
||||
obj
|
||||
}
|
||||
|
||||
class BuilderTestActor(builder: ServerObjectBuilder[_], hub: NumberPoolHub) extends Actor {
|
||||
def receive: Receive = {
|
||||
case _ =>
|
||||
sender() ! builder.Build(context, hub)
|
||||
}
|
||||
}
|
||||
|
||||
class BuildingTestActor(
|
||||
structure_con: (String, Int, Int, Zone, ActorContext) => Building,
|
||||
name: String,
|
||||
building_guid: Int,
|
||||
map_id: Int,
|
||||
zone: Zone
|
||||
) extends Actor {
|
||||
def receive: Receive = {
|
||||
case _ =>
|
||||
sender() ! FoundationBuilder(structure_con).Build(name, building_guid, map_id, zone)(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
35
src/test/scala/objects/SpawnTubeTest.scala
Normal file
35
src/test/scala/objects/SpawnTubeTest.scala
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.Props
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.{Default, GlobalDefinitions}
|
||||
import net.psforever.objects.serverobject.tube.{SpawnTube, SpawnTubeControl, SpawnTubeDefinition}
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
class SpawnTubeTest extends Specification {
|
||||
"SpawnTubeDefinition" should {
|
||||
"define" in {
|
||||
val obj = new SpawnTubeDefinition(49)
|
||||
obj.ObjectId mustEqual 49
|
||||
}
|
||||
}
|
||||
|
||||
"SpawnTube" should {
|
||||
"construct" in {
|
||||
val obj = SpawnTube(GlobalDefinitions.ams_respawn_tube)
|
||||
obj.Actor mustEqual Default.Actor
|
||||
obj.Definition mustEqual GlobalDefinitions.ams_respawn_tube
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SpawnTubeControlTest extends ActorTest {
|
||||
"SpawnTubeControl" should {
|
||||
"construct" in {
|
||||
val obj = SpawnTube(GlobalDefinitions.ams_respawn_tube)
|
||||
obj.Actor = system.actorOf(Props(classOf[SpawnTubeControl], obj), "spawn-tube")
|
||||
assert(obj.Actor != Default.Actor)
|
||||
}
|
||||
}
|
||||
}
|
||||
238
src/test/scala/objects/UtilityTest.scala
Normal file
238
src/test/scala/objects/UtilityTest.scala
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.{Actor, Props}
|
||||
import base.ActorTest
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
import net.psforever.objects.serverobject.tube.SpawnTube
|
||||
import net.psforever.objects.vehicles._
|
||||
import net.psforever.packet.game.ItemTransactionMessage
|
||||
import net.psforever.types._
|
||||
import org.specs2.mutable._
|
||||
|
||||
import scala.concurrent.duration.Duration
|
||||
|
||||
class UtilityTest extends Specification {
|
||||
"Utility" should {
|
||||
"create an order_terminala object" in {
|
||||
val obj = Utility(UtilityType.order_terminala, UtilityTest.vehicle)
|
||||
obj.UtilType mustEqual UtilityType.order_terminala
|
||||
obj().isInstanceOf[Terminal] mustEqual true
|
||||
obj().asInstanceOf[Terminal].Definition.ObjectId mustEqual 613
|
||||
obj().asInstanceOf[Terminal].Actor mustEqual Default.Actor
|
||||
}
|
||||
|
||||
"create an order_terminalb object" in {
|
||||
val obj = Utility(UtilityType.order_terminalb, UtilityTest.vehicle)
|
||||
obj.UtilType mustEqual UtilityType.order_terminalb
|
||||
obj().isInstanceOf[Terminal] mustEqual true
|
||||
obj().asInstanceOf[Terminal].Definition.ObjectId mustEqual 614
|
||||
obj().asInstanceOf[Terminal].Actor mustEqual Default.Actor
|
||||
}
|
||||
|
||||
"create a matrix_terminalc object" in {
|
||||
val obj = Utility(UtilityType.matrix_terminalc, UtilityTest.vehicle)
|
||||
obj.UtilType mustEqual UtilityType.matrix_terminalc
|
||||
obj().isInstanceOf[Terminal] mustEqual true
|
||||
obj().asInstanceOf[Terminal].Definition.ObjectId mustEqual 519
|
||||
obj().asInstanceOf[Terminal].Actor mustEqual Default.Actor
|
||||
}
|
||||
|
||||
"create an ams_respawn_tube object" in {
|
||||
val obj = Utility(UtilityType.ams_respawn_tube, UtilityTest.vehicle)
|
||||
obj.UtilType mustEqual UtilityType.ams_respawn_tube
|
||||
obj().isInstanceOf[SpawnTube] mustEqual true
|
||||
obj().asInstanceOf[SpawnTube].Definition.ObjectId mustEqual 49
|
||||
obj().asInstanceOf[SpawnTube].Actor mustEqual Default.Actor
|
||||
}
|
||||
|
||||
"create a teleportpad_terminal object" in {
|
||||
val obj = Utility(UtilityType.teleportpad_terminal, UtilityTest.vehicle)
|
||||
obj.UtilType mustEqual UtilityType.teleportpad_terminal
|
||||
obj().isInstanceOf[Terminal] mustEqual true
|
||||
obj().asInstanceOf[Terminal].Definition.ObjectId mustEqual 853
|
||||
obj().asInstanceOf[Terminal].Actor mustEqual Default.Actor
|
||||
}
|
||||
|
||||
"produce a telepad object through the teleportpad_terminal" in {
|
||||
val veh = Vehicle(GlobalDefinitions.quadstealth)
|
||||
veh.Faction = PlanetSideEmpire.TR
|
||||
val obj = Utility(UtilityType.teleportpad_terminal, UtilityTest.vehicle)
|
||||
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
veh.GUID = PlanetSideGUID(101)
|
||||
obj().Owner = veh //hack
|
||||
obj().GUID = PlanetSideGUID(1)
|
||||
player.GUID = PlanetSideGUID(2)
|
||||
|
||||
val msg = obj()
|
||||
.asInstanceOf[Terminal]
|
||||
.Request(
|
||||
player,
|
||||
ItemTransactionMessage(PlanetSideGUID(853), TransactionType.Buy, 0, "router_telepad", 0, PlanetSideGUID(0))
|
||||
)
|
||||
msg.isInstanceOf[Terminal.BuyEquipment] mustEqual true
|
||||
msg.asInstanceOf[Terminal.BuyEquipment].item.isInstanceOf[Telepad] mustEqual true
|
||||
}
|
||||
|
||||
"create an internal_router_telepad_deployable object" in {
|
||||
val obj = Utility(UtilityType.internal_router_telepad_deployable, UtilityTest.vehicle)
|
||||
obj.UtilType mustEqual UtilityType.internal_router_telepad_deployable
|
||||
obj().isInstanceOf[Utility.InternalTelepad] mustEqual true
|
||||
obj().asInstanceOf[Utility.InternalTelepad].Definition.ObjectId mustEqual 744
|
||||
obj().asInstanceOf[Utility.InternalTelepad].Actor mustEqual Default.Actor
|
||||
}
|
||||
|
||||
"internal_router_telepad_deployable can keep track of an object's GUID (presumedly, it's a Telepad)" in {
|
||||
val obj = Utility(UtilityType.internal_router_telepad_deployable, UtilityTest.vehicle)
|
||||
val inpad = obj().asInstanceOf[Utility.InternalTelepad]
|
||||
|
||||
inpad.Telepad.isEmpty mustEqual true
|
||||
inpad.Telepad = PlanetSideGUID(5)
|
||||
inpad.Telepad.contains(PlanetSideGUID(5)) mustEqual true
|
||||
inpad.Telepad = PlanetSideGUID(6)
|
||||
inpad.Telepad.contains(PlanetSideGUID(6)) mustEqual true
|
||||
inpad.Telepad = None
|
||||
inpad.Telepad.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"be located with their owner (terminal)" in {
|
||||
val veh = Vehicle(GlobalDefinitions.quadstealth)
|
||||
val obj = Utility(UtilityType.order_terminala, veh)
|
||||
obj().Position mustEqual veh.Position
|
||||
obj().Orientation mustEqual veh.Orientation
|
||||
|
||||
veh.Position = Vector3(1, 2, 3)
|
||||
veh.Orientation = Vector3(4, 5, 6)
|
||||
obj().Position mustEqual veh.Position
|
||||
obj().Orientation mustEqual veh.Orientation
|
||||
}
|
||||
|
||||
"be located with their owner (spawn tube)" in {
|
||||
val veh = Vehicle(GlobalDefinitions.quadstealth)
|
||||
val obj = Utility(UtilityType.ams_respawn_tube, veh)
|
||||
obj().Position mustEqual veh.Position
|
||||
obj().Orientation mustEqual veh.Orientation
|
||||
|
||||
veh.Position = Vector3(1, 2, 3)
|
||||
veh.Orientation = Vector3(4, 5, 6)
|
||||
obj().Position mustEqual veh.Position
|
||||
obj().Orientation mustEqual veh.Orientation
|
||||
}
|
||||
|
||||
"be located with their owner (internal telepad)" in {
|
||||
val veh = Vehicle(GlobalDefinitions.quadstealth)
|
||||
val obj = Utility(UtilityType.internal_router_telepad_deployable, veh)
|
||||
obj().Position mustEqual veh.Position
|
||||
obj().Orientation mustEqual veh.Orientation
|
||||
|
||||
veh.Position = Vector3(1, 2, 3)
|
||||
veh.Orientation = Vector3(4, 5, 6)
|
||||
veh.GUID = PlanetSideGUID(101)
|
||||
obj().Position mustEqual veh.Position
|
||||
obj().Orientation mustEqual veh.Orientation
|
||||
obj().asInstanceOf[Utility.InternalTelepad].Router.contains(veh.GUID) mustEqual true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UtilityTerminalATest extends ActorTest {
|
||||
"Utility" should {
|
||||
"wire an order_terminala Actor" in {
|
||||
val obj = Utility(UtilityType.order_terminala, UtilityTest.vehicle)
|
||||
obj().GUID = PlanetSideGUID(1)
|
||||
assert(obj().Actor == Default.Actor)
|
||||
|
||||
system.actorOf(Props(classOf[UtilityTest.SetupControl], obj), "test") ! ""
|
||||
receiveOne(Duration.create(500, "ms")) //consume and discard
|
||||
assert(obj().Actor != Default.Actor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UtilityTerminalBTest extends ActorTest {
|
||||
"Utility" should {
|
||||
"wire an order_terminalb Actor" in {
|
||||
val obj = Utility(UtilityType.order_terminalb, UtilityTest.vehicle)
|
||||
obj().GUID = PlanetSideGUID(1)
|
||||
assert(obj().Actor == Default.Actor)
|
||||
|
||||
system.actorOf(Props(classOf[UtilityTest.SetupControl], obj), "test") ! ""
|
||||
receiveOne(Duration.create(500, "ms")) //consume and discard
|
||||
assert(obj().Actor != Default.Actor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UtilityTerminalCTest extends ActorTest {
|
||||
"Utility" should {
|
||||
"wire a matrix_terminalc Actor" in {
|
||||
val obj = Utility(UtilityType.matrix_terminalc, UtilityTest.vehicle)
|
||||
obj().GUID = PlanetSideGUID(1)
|
||||
assert(obj().Actor == Default.Actor)
|
||||
|
||||
system.actorOf(Props(classOf[UtilityTest.SetupControl], obj), "test") ! ""
|
||||
receiveOne(Duration.create(500, "ms")) //consume and discard
|
||||
assert(obj().Actor != Default.Actor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UtilityRespawnTubeTest extends ActorTest {
|
||||
"Utility" should {
|
||||
"wire an ams_respawn_tube Actor" in {
|
||||
val obj = Utility(UtilityType.ams_respawn_tube, UtilityTest.vehicle)
|
||||
obj().GUID = PlanetSideGUID(1)
|
||||
assert(obj().Actor == Default.Actor)
|
||||
|
||||
system.actorOf(Props(classOf[UtilityTest.SetupControl], obj), "test") ! ""
|
||||
receiveOne(Duration.create(500, "ms")) //consume and discard
|
||||
assert(obj().Actor != Default.Actor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UtilityTelepadTerminalTest extends ActorTest {
|
||||
"Utility" should {
|
||||
"wire a teleportpad_terminal Actor" in {
|
||||
val obj = Utility(UtilityType.teleportpad_terminal, UtilityTest.vehicle)
|
||||
obj().GUID = PlanetSideGUID(1)
|
||||
assert(obj().Actor == Default.Actor)
|
||||
|
||||
system.actorOf(Props(classOf[UtilityTest.SetupControl], obj), "test") ! ""
|
||||
receiveOne(Duration.create(500, "ms")) //consume and discard
|
||||
assert(obj().Actor != Default.Actor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UtilityInternalTelepadTest extends ActorTest {
|
||||
"Utility" should {
|
||||
"wire a teleportpad_terminal Actor" in {
|
||||
val veh = Vehicle(GlobalDefinitions.quadstealth)
|
||||
veh.GUID = PlanetSideGUID(101)
|
||||
val obj = Utility(UtilityType.internal_router_telepad_deployable, veh)
|
||||
obj().GUID = PlanetSideGUID(1)
|
||||
assert(obj().Actor == Default.Actor)
|
||||
assert(obj().asInstanceOf[Utility.InternalTelepad].Router.contains(veh.GUID))
|
||||
|
||||
system.actorOf(Props(classOf[UtilityTest.SetupControl], obj), "test") ! ""
|
||||
receiveOne(Duration.create(500, "ms")) //consume and discard
|
||||
assert(obj().Actor != Default.Actor)
|
||||
assert(obj().asInstanceOf[Utility.InternalTelepad].Router.contains(veh.GUID))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object UtilityTest {
|
||||
val vehicle = Vehicle(GlobalDefinitions.quadstealth)
|
||||
|
||||
class SetupControl(obj: Utility) extends Actor {
|
||||
def receive: Receive = {
|
||||
case _ =>
|
||||
obj.Setup(context)
|
||||
sender() ! ""
|
||||
}
|
||||
}
|
||||
}
|
||||
22
src/test/scala/objects/VehicleSpawnPadTest.scala
Normal file
22
src/test/scala/objects/VehicleSpawnPadTest.scala
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects.{Default, GlobalDefinitions}
|
||||
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
class VehicleSpawnPadTest extends Specification {
|
||||
"VehicleSpawnPadDefinition" should {
|
||||
"define" in {
|
||||
GlobalDefinitions.mb_pad_creation.ObjectId mustEqual 525
|
||||
}
|
||||
}
|
||||
|
||||
"VehicleSpawnPad" should {
|
||||
"construct" in {
|
||||
val obj = VehicleSpawnPad(GlobalDefinitions.mb_pad_creation)
|
||||
obj.Actor mustEqual Default.Actor
|
||||
obj.Definition mustEqual GlobalDefinitions.mb_pad_creation
|
||||
}
|
||||
}
|
||||
}
|
||||
1023
src/test/scala/objects/VehicleTest.scala
Normal file
1023
src/test/scala/objects/VehicleTest.scala
Normal file
File diff suppressed because it is too large
Load diff
96
src/test/scala/objects/VitalityTest.scala
Normal file
96
src/test/scala/objects/VitalityTest.scala
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects.ballistics._
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
import net.psforever.objects.vital._
|
||||
import net.psforever.types._
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
class VitalityTest extends Specification {
|
||||
"Vitality" should {
|
||||
val wep = GlobalDefinitions.galaxy_gunship_cannon
|
||||
val wep_fmode = Tool(wep).FireMode
|
||||
val proj = wep.ProjectileTypes.head
|
||||
val vehicle = Vehicle(GlobalDefinitions.fury)
|
||||
val vSource = VehicleSource(vehicle)
|
||||
|
||||
"accept a variety of events" in {
|
||||
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
val pSource = PlayerSource(player)
|
||||
val projectile = Projectile(proj, wep, wep_fmode, player, Vector3(2, 2, 0), Vector3.Zero)
|
||||
val resprojectile = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
projectile,
|
||||
SourceEntry(player),
|
||||
player.DamageModel,
|
||||
Vector3(50, 50, 0)
|
||||
)
|
||||
|
||||
player.History(resprojectile) //ResolvedProjectile, straight-up
|
||||
player.History(DamageFromProjectile(resprojectile))
|
||||
player.History(HealFromKit(pSource, 10, GlobalDefinitions.medkit))
|
||||
player.History(HealFromTerm(pSource, 10, 0, GlobalDefinitions.order_terminal))
|
||||
player.History(HealFromImplant(pSource, 10, ImplantType.AdvancedRegen))
|
||||
player.History(HealFromExoSuitChange(pSource, ExoSuitType.Standard))
|
||||
player.History(RepairFromTerm(vSource, 10, GlobalDefinitions.order_terminal))
|
||||
player.History(VehicleShieldCharge(vSource, 10))
|
||||
player.History(PlayerSuicide(pSource))
|
||||
ok
|
||||
}
|
||||
|
||||
"return and clear the former list of vital activities" in {
|
||||
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
val pSource = PlayerSource(player)
|
||||
|
||||
player.History(HealFromKit(pSource, 10, GlobalDefinitions.medkit))
|
||||
player.History(HealFromTerm(pSource, 10, 0, GlobalDefinitions.order_terminal))
|
||||
player.History(HealFromImplant(pSource, 10, ImplantType.AdvancedRegen))
|
||||
player.History(HealFromExoSuitChange(pSource, ExoSuitType.Standard))
|
||||
player.History(RepairFromTerm(vSource, 10, GlobalDefinitions.order_terminal))
|
||||
player.History(VehicleShieldCharge(vSource, 10))
|
||||
player.History(PlayerSuicide(pSource))
|
||||
player.History.size mustEqual 7
|
||||
|
||||
val list = player.ClearHistory()
|
||||
player.History.size mustEqual 0
|
||||
list.head.isInstanceOf[PlayerSuicide] mustEqual true
|
||||
list(1).isInstanceOf[VehicleShieldCharge] mustEqual true
|
||||
list(2).isInstanceOf[RepairFromTerm] mustEqual true
|
||||
list(3).isInstanceOf[HealFromExoSuitChange] mustEqual true
|
||||
list(4).isInstanceOf[HealFromImplant] mustEqual true
|
||||
list(5).isInstanceOf[HealFromTerm] mustEqual true
|
||||
list(6).isInstanceOf[HealFromKit] mustEqual true
|
||||
}
|
||||
|
||||
"get exactly one entry that was caused by projectile damage" in {
|
||||
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
val pSource = PlayerSource(player)
|
||||
val projectile = Projectile(proj, wep, wep_fmode, player, Vector3(2, 2, 0), Vector3.Zero)
|
||||
val resprojectile = ResolvedProjectile(
|
||||
ProjectileResolution.Splash,
|
||||
projectile,
|
||||
SourceEntry(player),
|
||||
player.DamageModel,
|
||||
Vector3(50, 50, 0)
|
||||
)
|
||||
|
||||
player.History(DamageFromProjectile(resprojectile))
|
||||
player.History(HealFromKit(pSource, 10, GlobalDefinitions.medkit))
|
||||
player.History(HealFromTerm(pSource, 10, 0, GlobalDefinitions.order_terminal))
|
||||
player.History(HealFromImplant(pSource, 10, ImplantType.AdvancedRegen))
|
||||
player.History(HealFromExoSuitChange(pSource, ExoSuitType.Standard))
|
||||
player.History(RepairFromTerm(vSource, 10, GlobalDefinitions.order_terminal))
|
||||
player.History(VehicleShieldCharge(vSource, 10))
|
||||
player.History(PlayerSuicide(pSource))
|
||||
|
||||
player.LastShot match {
|
||||
case Some(resolved_projectile) =>
|
||||
resolved_projectile.projectile mustEqual projectile
|
||||
case None =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
656
src/test/scala/objects/ZoneTest.scala
Normal file
656
src/test/scala/objects/ZoneTest.scala
Normal file
|
|
@ -0,0 +1,656 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import akka.actor.ActorContext
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.entity.IdentifiableEntity
|
||||
import net.psforever.objects.equipment.Equipment
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
import net.psforever.objects.guid.source.LimitedNumberSource
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
import net.psforever.objects.serverobject.tube.SpawnTube
|
||||
import net.psforever.objects._
|
||||
import net.psforever.types._
|
||||
import net.psforever.objects.serverobject.structures.{Building, FoundationBuilder, StructureType}
|
||||
import net.psforever.objects.zones.{Zone, ZoneMap}
|
||||
import net.psforever.objects.Vehicle
|
||||
import org.specs2.mutable.Specification
|
||||
import akka.actor.typed.scaladsl.adapter._
|
||||
import net.psforever.actors.zone.ZoneActor
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
class ZoneTest extends Specification {
|
||||
def test(a: String, b: Int, c: Int, d: Zone, e: ActorContext): Building = {
|
||||
Building.NoBuilding
|
||||
}
|
||||
|
||||
"ZoneMap" should {
|
||||
"construct" in {
|
||||
new ZoneMap("map13")
|
||||
ok
|
||||
}
|
||||
|
||||
"references bases by a positive building id (defaults to 0)" in {
|
||||
val map = new ZoneMap("map13")
|
||||
map.localBuildings mustEqual Map.empty
|
||||
map.addLocalBuilding("Building", buildingGuid = 10, mapId = 0, FoundationBuilder(test))
|
||||
map.localBuildings.keySet.contains(("Building", 10, 0)) mustEqual true
|
||||
map.addLocalBuilding("Building", buildingGuid = -1, mapId = 0, FoundationBuilder(test))
|
||||
map.localBuildings.keySet.contains(("Building", 10, 0)) mustEqual true
|
||||
map.localBuildings.keySet.contains(("Building", -1, 0)) mustEqual false
|
||||
}
|
||||
|
||||
"associates objects to bases (doesn't check numbers)" in {
|
||||
val map = new ZoneMap("map13")
|
||||
map.objectToBuilding mustEqual Map.empty
|
||||
map.linkObjectToBuilding(1, 2)
|
||||
map.objectToBuilding mustEqual Map(1 -> 2)
|
||||
map.linkObjectToBuilding(3, 4)
|
||||
map.objectToBuilding mustEqual Map(1 -> 2, 3 -> 4)
|
||||
}
|
||||
|
||||
"associates doors to door locks (doesn't check numbers)" in {
|
||||
val map = new ZoneMap("map13")
|
||||
map.doorToLock mustEqual Map.empty
|
||||
map.linkDoorToLock(1, 2)
|
||||
map.doorToLock mustEqual Map(1 -> 2)
|
||||
map.linkDoorToLock(3, 4)
|
||||
map.doorToLock mustEqual Map(1 -> 2, 3 -> 4)
|
||||
}
|
||||
|
||||
"associates terminals to spawn pads (doesn't check numbers)" in {
|
||||
val map = new ZoneMap("map13")
|
||||
map.terminalToSpawnPad mustEqual Map.empty
|
||||
map.linkTerminalToSpawnPad(1, 2)
|
||||
map.terminalToSpawnPad mustEqual Map(1 -> 2)
|
||||
map.linkTerminalToSpawnPad(3, 4)
|
||||
map.terminalToSpawnPad mustEqual Map(1 -> 2, 3 -> 4)
|
||||
}
|
||||
|
||||
"associates mechanical components to implant terminals (doesn't check numbers)" in {
|
||||
val map = new ZoneMap("map13")
|
||||
map.terminalToInterface mustEqual Map.empty
|
||||
map.linkTerminalToInterface(1, 2)
|
||||
map.terminalToInterface mustEqual Map(1 -> 2)
|
||||
map.linkTerminalToInterface(3, 4)
|
||||
map.terminalToInterface mustEqual Map(1 -> 2, 3 -> 4)
|
||||
}
|
||||
|
||||
"associate turrets to weapons" in {
|
||||
val map = new ZoneMap("map13")
|
||||
map.turretToWeapon mustEqual Map.empty
|
||||
map.linkTurretToWeapon(1, 2)
|
||||
map.turretToWeapon mustEqual Map(1 -> 2)
|
||||
map.linkTurretToWeapon(3, 4)
|
||||
map.turretToWeapon mustEqual Map(1 -> 2, 3 -> 4)
|
||||
}
|
||||
}
|
||||
|
||||
val map13 = new ZoneMap("map13")
|
||||
map13.addLocalBuilding("Building", buildingGuid = 0, mapId = 10, FoundationBuilder(test))
|
||||
class TestObject extends IdentifiableEntity
|
||||
|
||||
"Zone" should {
|
||||
"construct" in {
|
||||
val zone = new Zone("home3", map13, 13)
|
||||
zone.EquipmentOnGround mustEqual List.empty[Equipment]
|
||||
zone.Vehicles mustEqual List.empty[Vehicle]
|
||||
zone.Players mustEqual List.empty[Player]
|
||||
zone.Corpses mustEqual List.empty[Player]
|
||||
}
|
||||
|
||||
"can have its unique identifier system changed if no objects were added to it" in {
|
||||
val zone = new Zone("home3", map13, 13)
|
||||
val guid1: NumberPoolHub = new NumberPoolHub(new LimitedNumberSource(100))
|
||||
zone.GUID(guid1) mustEqual true
|
||||
zone.AddPool("pool1", (0 to 50).toList)
|
||||
zone.AddPool("pool2", (51 to 75).toList)
|
||||
|
||||
val obj = new TestObject()
|
||||
guid1.register(obj, "pool2").isSuccess mustEqual true
|
||||
guid1.WhichPool(obj).contains("pool2") mustEqual true
|
||||
|
||||
zone.GUID(new NumberPoolHub(new LimitedNumberSource(150))) mustEqual false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ZoneActorTest extends ActorTest {
|
||||
"Zone" should {
|
||||
"refuse new number pools after the Actor is started" in {
|
||||
val zone = new Zone("test", new ZoneMap("map6"), 1) { override def SetupNumberPools() = {} }
|
||||
zone.GUID(new NumberPoolHub(new LimitedNumberSource(40150)))
|
||||
zone.actor = system.spawn(ZoneActor(zone), "test-add-pool-actor-init")
|
||||
expectNoMessage(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) { override def SetupNumberPools() = {} }
|
||||
|
||||
zone.GUID(new NumberPoolHub(new LimitedNumberSource(10)))
|
||||
zone.AddPool("test", 1 to 2)
|
||||
zone.actor = system.spawn(ZoneActor(zone), "test-remove-pool-actor-init")
|
||||
expectNoMessage(Duration.create(300, "ms"))
|
||||
|
||||
assert(!zone.RemovePool("test"))
|
||||
}
|
||||
|
||||
"set up spawn groups based on buildings" in {
|
||||
val map6 = new ZoneMap("map6") {
|
||||
addLocalBuilding(
|
||||
"Building",
|
||||
buildingGuid = 1,
|
||||
mapId = 1,
|
||||
FoundationBuilder(Building.Structure(StructureType.Building, Vector3(1, 1, 1)))
|
||||
)
|
||||
addLocalObject(2, SpawnTube.Constructor(Vector3(1, 0, 0), Vector3.Zero))
|
||||
addLocalObject(3, Terminal.Constructor(Vector3.Zero, GlobalDefinitions.dropship_vehicle_terminal))
|
||||
addLocalObject(4, SpawnTube.Constructor(Vector3(1, 0, 0), Vector3.Zero))
|
||||
linkObjectToBuilding(2, 1)
|
||||
linkObjectToBuilding(3, 1)
|
||||
linkObjectToBuilding(4, 1)
|
||||
|
||||
addLocalBuilding(
|
||||
"Building",
|
||||
buildingGuid = 5,
|
||||
mapId = 2,
|
||||
FoundationBuilder(Building.Structure(StructureType.Building))
|
||||
)
|
||||
addLocalObject(6, SpawnTube.Constructor(Vector3.Zero, Vector3.Zero))
|
||||
linkObjectToBuilding(6, 5)
|
||||
|
||||
addLocalBuilding(
|
||||
"Building",
|
||||
buildingGuid = 7,
|
||||
mapId = 3,
|
||||
FoundationBuilder(Building.Structure(StructureType.Building, Vector3(1, 1, 1)))
|
||||
)
|
||||
addLocalObject(8, Terminal.Constructor(Vector3.Zero, GlobalDefinitions.dropship_vehicle_terminal))
|
||||
addLocalObject(9, SpawnTube.Constructor(Vector3(1, 0, 0), Vector3.Zero))
|
||||
addLocalObject(10, Terminal.Constructor(Vector3.Zero, GlobalDefinitions.dropship_vehicle_terminal))
|
||||
linkObjectToBuilding(8, 7)
|
||||
linkObjectToBuilding(9, 7)
|
||||
linkObjectToBuilding(10, 7)
|
||||
}
|
||||
val zone = new Zone("test", map6, 1) { override def SetupNumberPools() = {} }
|
||||
zone.actor = system.spawn(ZoneActor(zone), "test-init")
|
||||
expectNoMessage(Duration.create(1, "seconds"))
|
||||
|
||||
val groups = zone.SpawnGroups()
|
||||
assert(groups.size == 2)
|
||||
zone
|
||||
.SpawnGroups()
|
||||
.foreach({
|
||||
case (building, tubes) =>
|
||||
if (building.MapId == 1) {
|
||||
val building1 = zone.SpawnGroups(building)
|
||||
assert(tubes.length == 2)
|
||||
assert(tubes.head == building1.head)
|
||||
assert(tubes.head.GUID == PlanetSideGUID(2))
|
||||
assert(tubes(1) == building1(1))
|
||||
assert(tubes(1).GUID == PlanetSideGUID(4))
|
||||
} else if (building.MapId == 3) {
|
||||
val building2 = zone.SpawnGroups(building)
|
||||
assert(tubes.length == 1)
|
||||
assert(tubes.head == building2.head)
|
||||
assert(tubes.head.GUID == PlanetSideGUID(9))
|
||||
} else {
|
||||
assert(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ZonePopulationTest extends ActorTest {
|
||||
"ZonePopulationActor" should {
|
||||
"add new user to zones" in {
|
||||
val zone = new Zone("test", new ZoneMap(""), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
}
|
||||
val avatar = Avatar(0, "Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
assert(zone.Players.isEmpty)
|
||||
assert(zone.LivePlayers.isEmpty)
|
||||
zone.Population ! Zone.Population.Join(avatar)
|
||||
zone.Population ! Zone.Population.Spawn(avatar, Player(avatar), null)
|
||||
expectNoMessage(Duration.create(200, "ms"))
|
||||
assert(zone.Players.size == 1)
|
||||
assert(zone.Players.head == avatar)
|
||||
// assert(zone.LivePlayers.isEmpty)
|
||||
}
|
||||
|
||||
"remove user from zones" in {
|
||||
val zone = new Zone("test", new ZoneMap(""), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
}
|
||||
val avatar = Avatar(1, "Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||
receiveOne(Duration.create(200, "ms")) //consume
|
||||
zone.Population ! Zone.Population.Join(avatar)
|
||||
zone.Population ! Zone.Population.Spawn(avatar, Player(avatar), null)
|
||||
expectNoMessage(Duration.create(100, "ms"))
|
||||
|
||||
assert(zone.Players.size == 1)
|
||||
assert(zone.Players.head == avatar)
|
||||
zone.Population ! Zone.Population.Leave(avatar)
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
assert(reply.isInstanceOf[Zone.Population.PlayerHasLeft])
|
||||
assert(zone.Players.isEmpty)
|
||||
}
|
||||
|
||||
/* TODO they need AvatarActor, which has further dependencies
|
||||
"associate user with a character" in {
|
||||
val zone = new Zone("test", new ZoneMap(""), 0) { override def SetupNumberPools() = {} }
|
||||
val avatar = Avatar(0, "Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
val player = Player(avatar)
|
||||
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||
expectNoMessage(200 milliseconds)
|
||||
zone.Population ! Zone.Population.Join(avatar)
|
||||
expectNoMessage(Duration.create(100, "ms"))
|
||||
|
||||
assert(zone.Players.size == 1)
|
||||
assert(zone.Players.head == avatar)
|
||||
assert(zone.LivePlayers.isEmpty)
|
||||
zone.Population ! Zone.Population.Spawn(avatar, player)
|
||||
expectNoMessage(Duration.create(100, "ms"))
|
||||
assert(zone.Players.size == 1)
|
||||
assert(zone.Players.head == avatar)
|
||||
assert(zone.LivePlayers.size == 1)
|
||||
assert(zone.LivePlayers.head == player)
|
||||
}
|
||||
|
||||
"disassociate character from a user" in {
|
||||
val zone = new Zone("test", new ZoneMap(""), 0) { override def SetupNumberPools() = {} }
|
||||
val avatar = Avatar(0, "Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
val player = Player(avatar)
|
||||
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||
expectNoMessage(200 milliseconds)
|
||||
zone.Population ! Zone.Population.Join(avatar)
|
||||
expectNoMessage(Duration.create(100, "ms"))
|
||||
zone.Population ! Zone.Population.Spawn(avatar, player)
|
||||
expectNoMessage(Duration.create(100, "ms"))
|
||||
|
||||
assert(zone.Players.size == 1)
|
||||
assert(zone.Players.head == avatar)
|
||||
assert(zone.LivePlayers.size == 1)
|
||||
assert(zone.LivePlayers.head == player)
|
||||
zone.Population ! Zone.Population.Release(avatar)
|
||||
expectNoMessage(Duration.create(100, "ms"))
|
||||
assert(zone.Players.size == 1)
|
||||
assert(zone.Players.head == avatar)
|
||||
assert(zone.LivePlayers.isEmpty)
|
||||
}
|
||||
|
||||
"user tries to Leave, but still has an associated character" in {
|
||||
val zone = new Zone("test", new ZoneMap(""), 0) { override def SetupNumberPools() = {} }
|
||||
val avatar = Avatar(0, "Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
val player = Player(avatar)
|
||||
player.GUID = PlanetSideGUID(1)
|
||||
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||
expectNoMessage(200 milliseconds)
|
||||
zone.Population ! Zone.Population.Join(avatar)
|
||||
expectNoMessage(Duration.create(100, "ms"))
|
||||
zone.Population ! Zone.Population.Spawn(avatar, player)
|
||||
expectNoMessage(Duration.create(100, "ms"))
|
||||
|
||||
assert(zone.Players.size == 1)
|
||||
assert(zone.Players.head == avatar)
|
||||
assert(zone.LivePlayers.size == 1)
|
||||
assert(zone.LivePlayers.head == player)
|
||||
zone.Population ! Zone.Population.Leave(avatar)
|
||||
val reply = receiveOne(Duration.create(500, "ms"))
|
||||
assert(zone.Players.isEmpty)
|
||||
assert(zone.LivePlayers.isEmpty)
|
||||
assert(reply.isInstanceOf[Zone.Population.PlayerHasLeft])
|
||||
assert(reply.asInstanceOf[Zone.Population.PlayerHasLeft].zone == zone)
|
||||
assert(reply.asInstanceOf[Zone.Population.PlayerHasLeft].player.contains(player))
|
||||
}
|
||||
|
||||
"user tries to Spawn a character, but an associated character already exists" in {
|
||||
val zone = new Zone("test", new ZoneMap(""), 0) { override def SetupNumberPools() = {} }
|
||||
val avatar = Avatar(0, "Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
val player1 = Player(avatar)
|
||||
val player2 = Player(avatar)
|
||||
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||
expectNoMessage(200 milliseconds)
|
||||
zone.Population ! Zone.Population.Join(avatar)
|
||||
expectNoMessage(Duration.create(100, "ms"))
|
||||
zone.Population ! Zone.Population.Spawn(avatar, player1)
|
||||
expectNoMessage(Duration.create(100, "ms"))
|
||||
|
||||
assert(zone.Players.size == 1)
|
||||
assert(zone.Players.head == avatar)
|
||||
assert(zone.LivePlayers.size == 1)
|
||||
assert(zone.LivePlayers.head == player1)
|
||||
zone.Population ! Zone.Population.Spawn(avatar, player2)
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
assert(zone.Players.size == 1)
|
||||
assert(zone.Players.head == avatar)
|
||||
assert(zone.LivePlayers.size == 1)
|
||||
assert(zone.LivePlayers.head == player1)
|
||||
assert(reply.isInstanceOf[Zone.Population.PlayerAlreadySpawned])
|
||||
assert(reply.asInstanceOf[Zone.Population.PlayerAlreadySpawned].player == player1)
|
||||
}
|
||||
|
||||
"user tries to Spawn a character, but did not Join first" in {
|
||||
val zone = new Zone("test", new ZoneMap(""), 0) { override def SetupNumberPools() = {} }
|
||||
val avatar = Avatar(0, "Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
val player = Player(avatar)
|
||||
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
assert(zone.Players.isEmpty)
|
||||
assert(zone.LivePlayers.isEmpty)
|
||||
zone.Population ! Zone.Population.Spawn(avatar, player)
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
assert(zone.Players.isEmpty)
|
||||
assert(zone.LivePlayers.isEmpty)
|
||||
assert(reply.isInstanceOf[Zone.Population.PlayerCanNotSpawn])
|
||||
assert(reply.asInstanceOf[Zone.Population.PlayerCanNotSpawn].zone == zone)
|
||||
assert(reply.asInstanceOf[Zone.Population.PlayerCanNotSpawn].player == player)
|
||||
}
|
||||
*/
|
||||
|
||||
"user tries to Release a character, but did not Spawn a character first" in {
|
||||
val zone = new Zone("test", new ZoneMap(""), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
}
|
||||
val avatar = Avatar(2, "Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
|
||||
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||
expectNoMessage(200 milliseconds)
|
||||
zone.Population ! Zone.Population.Join(avatar)
|
||||
zone.Population ! Zone.Population.Spawn(avatar, Player(avatar), null)
|
||||
expectNoMessage(Duration.create(100, "ms"))
|
||||
|
||||
assert(zone.Players.size == 1)
|
||||
assert(zone.Players.head == avatar)
|
||||
// assert(zone.LivePlayers.isEmpty)
|
||||
zone.Population ! Zone.Population.Release(avatar)
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
// assert(zone.Players.size == 1)
|
||||
// assert(zone.Players.head == avatar)
|
||||
// assert(zone.LivePlayers.isEmpty)
|
||||
assert(reply.isInstanceOf[Zone.Population.PlayerHasLeft])
|
||||
assert(reply.asInstanceOf[Zone.Population.PlayerHasLeft].zone == zone)
|
||||
// assert(reply.asInstanceOf[Zone.Population.PlayerHasLeft].player.isEmpty)
|
||||
}
|
||||
|
||||
"user adds character to list of retired characters" in {
|
||||
val zone = new Zone("test", new ZoneMap(""), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
}
|
||||
val player = Player(Avatar(3, "Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5))
|
||||
player.Release
|
||||
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
assert(zone.Corpses.isEmpty)
|
||||
zone.Population ! Zone.Corpse.Add(player)
|
||||
expectNoMessage(Duration.create(500, "ms"))
|
||||
assert(zone.Corpses.size == 1)
|
||||
assert(zone.Corpses.head == player)
|
||||
}
|
||||
|
||||
"user removes character from the list of retired characters" in {
|
||||
val zone = new Zone("test", new ZoneMap(""), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
}
|
||||
val player = Player(Avatar(4, "Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5))
|
||||
player.Release
|
||||
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||
expectNoMessage(200 milliseconds)
|
||||
zone.Population ! Zone.Corpse.Add(player)
|
||||
expectNoMessage(Duration.create(500, "ms"))
|
||||
|
||||
assert(zone.Corpses.size == 1)
|
||||
assert(zone.Corpses.head == player)
|
||||
zone.Population ! Zone.Corpse.Remove(player)
|
||||
expectNoMessage(Duration.create(200, "ms"))
|
||||
assert(zone.Corpses.isEmpty)
|
||||
}
|
||||
|
||||
"user removes THE CORRECT character from the list of retired characters" in {
|
||||
val zone = new Zone("test", new ZoneMap(""), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
}
|
||||
val player1 = Player(Avatar(5, "Chord1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5))
|
||||
player1.Release
|
||||
val player2 = Player(Avatar(6, "Chord2", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5))
|
||||
player2.Release
|
||||
val player3 = Player(Avatar(7, "Chord3", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5))
|
||||
player3.Release
|
||||
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||
expectNoMessage(200 milliseconds)
|
||||
zone.Population ! Zone.Corpse.Add(player1)
|
||||
zone.Population ! Zone.Corpse.Add(player2)
|
||||
zone.Population ! Zone.Corpse.Add(player3)
|
||||
expectNoMessage(Duration.create(500, "ms"))
|
||||
|
||||
assert(zone.Corpses.size == 3)
|
||||
assert(zone.Corpses.head == player1)
|
||||
assert(zone.Corpses(1) == player2)
|
||||
assert(zone.Corpses(2) == player3)
|
||||
zone.Population ! Zone.Corpse.Remove(player2)
|
||||
expectNoMessage(Duration.create(200, "ms"))
|
||||
assert(zone.Corpses.size == 2)
|
||||
assert(zone.Corpses.head == player1)
|
||||
assert(zone.Corpses(1) == player3)
|
||||
}
|
||||
|
||||
"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) {
|
||||
override def SetupNumberPools() = {}
|
||||
}
|
||||
val player = Player(Avatar(8, "Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5))
|
||||
//player.Release !!important
|
||||
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
assert(zone.Corpses.isEmpty)
|
||||
zone.Population ! Zone.Corpse.Add(player)
|
||||
expectNoMessage(Duration.create(200, "ms"))
|
||||
assert(zone.Corpses.isEmpty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ZoneGroundDropItemTest extends ActorTest {
|
||||
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
|
||||
val hub = new NumberPoolHub(new LimitedNumberSource(20))
|
||||
hub.register(item, 10)
|
||||
val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = {} }
|
||||
zone.GUID(hub)
|
||||
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
"DropItem" should {
|
||||
"drop item on ground" in {
|
||||
receiveOne(1 second) //consume
|
||||
assert(!zone.EquipmentOnGround.contains(item))
|
||||
zone.Ground ! Zone.Ground.DropItem(item, Vector3(1.1f, 2.2f, 3.3f), Vector3(4.4f, 5.5f, 6.6f))
|
||||
|
||||
val reply = receiveOne(200 milliseconds)
|
||||
assert(reply.isInstanceOf[Zone.Ground.ItemOnGround])
|
||||
assert(reply.asInstanceOf[Zone.Ground.ItemOnGround].item == item)
|
||||
assert(reply.asInstanceOf[Zone.Ground.ItemOnGround].pos == Vector3(1.1f, 2.2f, 3.3f))
|
||||
assert(reply.asInstanceOf[Zone.Ground.ItemOnGround].orient == Vector3(4.4f, 5.5f, 6.6f))
|
||||
assert(zone.EquipmentOnGround.contains(item))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ZoneGroundCanNotDropItem1Test 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) { override def SetupNumberPools() = {} }
|
||||
zone.GUID(hub)
|
||||
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
"DropItem" should {
|
||||
"not drop an item that is not registered" in {
|
||||
receiveOne(1 second) //consume
|
||||
assert(!zone.EquipmentOnGround.contains(item))
|
||||
zone.Ground ! Zone.Ground.DropItem(item, Vector3.Zero, Vector3.Zero)
|
||||
|
||||
val reply = receiveOne(300 milliseconds)
|
||||
assert(reply.isInstanceOf[Zone.Ground.CanNotDropItem])
|
||||
assert(reply.asInstanceOf[Zone.Ground.CanNotDropItem].item == item)
|
||||
assert(reply.asInstanceOf[Zone.Ground.CanNotDropItem].zone == zone)
|
||||
assert(reply.asInstanceOf[Zone.Ground.CanNotDropItem].reason == "not registered yet")
|
||||
assert(!zone.EquipmentOnGround.contains(item))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) { override def SetupNumberPools() = {} }
|
||||
//zone.GUID(hub) //!important
|
||||
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
"DropItem" should {
|
||||
"not drop an item that is not registered to the zone" in {
|
||||
receiveOne(1 second) //consume
|
||||
assert(!zone.EquipmentOnGround.contains(item))
|
||||
zone.Ground ! Zone.Ground.DropItem(item, Vector3.Zero, Vector3.Zero)
|
||||
|
||||
val reply = receiveOne(300 milliseconds)
|
||||
assert(reply.isInstanceOf[Zone.Ground.CanNotDropItem])
|
||||
assert(reply.asInstanceOf[Zone.Ground.CanNotDropItem].item == item)
|
||||
assert(reply.asInstanceOf[Zone.Ground.CanNotDropItem].zone == zone)
|
||||
assert(reply.asInstanceOf[Zone.Ground.CanNotDropItem].reason == "registered to some other zone")
|
||||
assert(!zone.EquipmentOnGround.contains(item))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ZoneGroundCanNotDropItem3Test 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) { override def SetupNumberPools() = {} }
|
||||
zone.GUID(hub) //!important
|
||||
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
"DropItem" should {
|
||||
"not drop an item that has already been dropped" in {
|
||||
receiveOne(1 second) //consume
|
||||
assert(!zone.EquipmentOnGround.contains(item))
|
||||
assert(zone.EquipmentOnGround.isEmpty)
|
||||
zone.Ground ! Zone.Ground.DropItem(item, Vector3.Zero, Vector3.Zero)
|
||||
|
||||
val reply1 = receiveOne(300 milliseconds)
|
||||
assert(reply1.isInstanceOf[Zone.Ground.ItemOnGround])
|
||||
assert(reply1.asInstanceOf[Zone.Ground.ItemOnGround].item == item)
|
||||
assert(zone.EquipmentOnGround.contains(item))
|
||||
assert(zone.EquipmentOnGround.size == 1)
|
||||
zone.Ground ! Zone.Ground.DropItem(item, Vector3.Zero, Vector3.Zero)
|
||||
|
||||
val reply2 = receiveOne(300 milliseconds)
|
||||
assert(reply2.isInstanceOf[Zone.Ground.CanNotDropItem])
|
||||
assert(reply2.asInstanceOf[Zone.Ground.CanNotDropItem].item == item)
|
||||
assert(reply2.asInstanceOf[Zone.Ground.CanNotDropItem].zone == zone)
|
||||
assert(reply2.asInstanceOf[Zone.Ground.CanNotDropItem].reason == "already dropped")
|
||||
assert(zone.EquipmentOnGround.size == 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ZoneGroundPickupItemTest extends ActorTest {
|
||||
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
|
||||
val hub = new NumberPoolHub(new LimitedNumberSource(20))
|
||||
hub.register(item, 10)
|
||||
val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = {} }
|
||||
zone.GUID(hub)
|
||||
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
"PickupItem" should {
|
||||
"pickup an item from ground" in {
|
||||
receiveOne(1 second) //consume
|
||||
assert(!zone.EquipmentOnGround.contains(item))
|
||||
zone.Ground ! Zone.Ground.DropItem(item, Vector3.Zero, Vector3.Zero)
|
||||
|
||||
val reply1 = receiveOne(200 milliseconds)
|
||||
assert(reply1.isInstanceOf[Zone.Ground.ItemOnGround])
|
||||
assert(zone.EquipmentOnGround.contains(item))
|
||||
zone.Ground ! Zone.Ground.PickupItem(item.GUID)
|
||||
|
||||
val reply2 = receiveOne(200 milliseconds)
|
||||
assert(reply2.isInstanceOf[Zone.Ground.ItemInHand])
|
||||
assert(reply2.asInstanceOf[Zone.Ground.ItemInHand].item == item)
|
||||
assert(!zone.EquipmentOnGround.contains(item))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ZoneGroundCanNotPickupItemTest extends ActorTest {
|
||||
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
|
||||
val hub = new NumberPoolHub(new LimitedNumberSource(20))
|
||||
hub.register(item, 10)
|
||||
val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = {} }
|
||||
zone.GUID(hub) //still registered to this zone
|
||||
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
"PickupItem" should {
|
||||
"not pickup an item if it can not be found" in {
|
||||
receiveOne(1 second) //consume
|
||||
assert(!zone.EquipmentOnGround.contains(item))
|
||||
zone.Ground ! Zone.Ground.PickupItem(item.GUID)
|
||||
|
||||
val reply2 = receiveOne(200 milliseconds)
|
||||
assert(reply2.isInstanceOf[Zone.Ground.CanNotPickupItem])
|
||||
assert(reply2.asInstanceOf[Zone.Ground.CanNotPickupItem].item_guid == item.GUID)
|
||||
assert(reply2.asInstanceOf[Zone.Ground.CanNotPickupItem].zone == zone)
|
||||
assert(reply2.asInstanceOf[Zone.Ground.CanNotPickupItem].reason == "can not find")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ZoneGroundRemoveItemTest extends ActorTest {
|
||||
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
|
||||
val hub = new NumberPoolHub(new LimitedNumberSource(20))
|
||||
hub.register(item, 10)
|
||||
val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = {} }
|
||||
zone.GUID(hub) //still registered to this zone
|
||||
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
"RemoveItem" should {
|
||||
"remove an item from the ground without callback (even if the item is not found)" in {
|
||||
receiveOne(1 second)
|
||||
assert(!zone.EquipmentOnGround.contains(item))
|
||||
zone.Ground ! Zone.Ground.DropItem(item, Vector3.Zero, Vector3.Zero)
|
||||
receiveOne(200 milliseconds)
|
||||
assert(zone.EquipmentOnGround.contains(item)) //dropped
|
||||
|
||||
zone.Ground ! Zone.Ground.RemoveItem(item.GUID)
|
||||
expectNoMessage(500 milliseconds)
|
||||
assert(!zone.EquipmentOnGround.contains(item))
|
||||
|
||||
zone.Ground ! Zone.Ground.RemoveItem(item.GUID) //repeat
|
||||
expectNoMessage(500 milliseconds)
|
||||
assert(!zone.EquipmentOnGround.contains(item))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object ZoneTest {
|
||||
val testNum = new AtomicInteger(1)
|
||||
def TestName: String = s"test${testNum.getAndIncrement()}"
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.guidtask
|
||||
|
||||
import base.ActorTest
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
|
||||
|
||||
class GUIDTaskRegisterAmmoTest extends ActorTest {
|
||||
"RegisterEquipment -> RegisterObjectTask" in {
|
||||
val (_, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
|
||||
val obj = AmmoBox(GlobalDefinitions.energy_cell)
|
||||
|
||||
assert(!obj.HasGUID)
|
||||
taskResolver ! TaskResolver.GiveTask(
|
||||
new GUIDTaskTest.RegisterTestTask(probe.ref),
|
||||
List(GUIDTask.RegisterEquipment(obj)(uns))
|
||||
)
|
||||
probe.expectMsg(scala.util.Success)
|
||||
assert(obj.HasGUID)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.guidtask
|
||||
|
||||
import base.ActorTest
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
|
||||
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire}
|
||||
|
||||
class GUIDTaskRegisterAvatarTest extends ActorTest {
|
||||
"RegisterAvatar" in {
|
||||
val (_, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
|
||||
val obj = Player(Avatar(0, "test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
val obj_wep = Tool(GlobalDefinitions.beamer)
|
||||
obj.Slot(0).Equipment = obj_wep
|
||||
val obj_wep_ammo = AmmoBox(GlobalDefinitions.energy_cell)
|
||||
obj_wep.AmmoSlots.head.Box = obj_wep_ammo
|
||||
val obj_inv_ammo = AmmoBox(GlobalDefinitions.energy_cell)
|
||||
obj.Slot(6).Equipment = obj_inv_ammo
|
||||
val obj_locker = obj.Slot(5).Equipment.get
|
||||
val obj_locker_ammo = AmmoBox(GlobalDefinitions.energy_cell)
|
||||
obj_locker.asInstanceOf[LockerEquipment].Inventory += 0 -> obj_locker_ammo
|
||||
|
||||
assert(!obj.HasGUID)
|
||||
assert(!obj_wep.HasGUID)
|
||||
assert(!obj_wep_ammo.HasGUID)
|
||||
assert(!obj_inv_ammo.HasGUID)
|
||||
assert(!obj_locker.HasGUID)
|
||||
assert(!obj_locker_ammo.HasGUID)
|
||||
taskResolver ! TaskResolver.GiveTask(
|
||||
new GUIDTaskTest.RegisterTestTask(probe.ref),
|
||||
List(GUIDTask.RegisterAvatar(obj)(uns))
|
||||
)
|
||||
probe.expectMsg(scala.util.Success)
|
||||
assert(obj.HasGUID)
|
||||
assert(obj_wep.HasGUID)
|
||||
assert(obj_wep_ammo.HasGUID)
|
||||
assert(obj_inv_ammo.HasGUID)
|
||||
assert(obj_locker.HasGUID)
|
||||
assert(obj_locker_ammo.HasGUID)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.guidtask
|
||||
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
|
||||
|
||||
class GUIDTaskRegisterObjectTest 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)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.guidtask
|
||||
|
||||
import base.ActorTest
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
|
||||
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire}
|
||||
|
||||
class GUIDTaskRegisterPlayerTest extends ActorTest {
|
||||
"RegisterPlayer" in {
|
||||
val (_, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
|
||||
val obj = Player(Avatar(0, "test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
val obj_wep = Tool(GlobalDefinitions.beamer)
|
||||
obj.Slot(0).Equipment = obj_wep
|
||||
val obj_wep_ammo = AmmoBox(GlobalDefinitions.energy_cell)
|
||||
obj_wep.AmmoSlots.head.Box = obj_wep_ammo
|
||||
val obj_inv_ammo = AmmoBox(GlobalDefinitions.energy_cell)
|
||||
obj.Slot(6).Equipment = obj_inv_ammo
|
||||
val obj_locker = obj.Slot(5).Equipment.get
|
||||
val obj_locker_ammo = AmmoBox(GlobalDefinitions.energy_cell)
|
||||
obj_locker.asInstanceOf[LockerEquipment].Inventory += 0 -> obj_locker_ammo
|
||||
|
||||
assert(!obj.HasGUID)
|
||||
assert(!obj_wep.HasGUID)
|
||||
assert(!obj_wep_ammo.HasGUID)
|
||||
assert(!obj_inv_ammo.HasGUID)
|
||||
assert(!obj_locker.HasGUID)
|
||||
assert(!obj_locker_ammo.HasGUID)
|
||||
taskResolver ! TaskResolver.GiveTask(
|
||||
new GUIDTaskTest.RegisterTestTask(probe.ref),
|
||||
List(GUIDTask.RegisterPlayer(obj)(uns))
|
||||
)
|
||||
probe.expectMsg(scala.util.Success)
|
||||
assert(obj.HasGUID)
|
||||
assert(obj_wep.HasGUID)
|
||||
assert(obj_wep_ammo.HasGUID)
|
||||
assert(obj_inv_ammo.HasGUID)
|
||||
assert(!obj_locker.HasGUID)
|
||||
assert(!obj_locker_ammo.HasGUID)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.guidtask
|
||||
|
||||
import base.ActorTest
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
|
||||
|
||||
class GUIDTaskRegisterToolTest extends ActorTest {
|
||||
"RegisterEquipment -> RegisterTool" in {
|
||||
val (_, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
|
||||
val obj = Tool(GlobalDefinitions.beamer)
|
||||
obj.AmmoSlots.head.Box = AmmoBox(GlobalDefinitions.energy_cell)
|
||||
|
||||
assert(!obj.HasGUID)
|
||||
assert(!obj.AmmoSlots.head.Box.HasGUID)
|
||||
taskResolver ! TaskResolver.GiveTask(
|
||||
new GUIDTaskTest.RegisterTestTask(probe.ref),
|
||||
List(GUIDTask.RegisterEquipment(obj)(uns))
|
||||
)
|
||||
probe.expectMsg(scala.util.Success)
|
||||
assert(obj.HasGUID)
|
||||
assert(obj.AmmoSlots.head.Box.HasGUID)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.guidtask
|
||||
|
||||
import base.ActorTest
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
|
||||
|
||||
class GUIDTaskRegisterTurretTest extends ActorTest {
|
||||
"RegisterDeployableTurret" in {
|
||||
val (_, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
|
||||
val obj = new TurretDeployable(GlobalDefinitions.portable_manned_turret_vs)
|
||||
val obj_wep = obj.Weapons(1).Equipment.get
|
||||
val obj_ammo = obj_wep.asInstanceOf[Tool].AmmoSlot.Box
|
||||
val obj_res = obj.Inventory.Items.map(_.obj)
|
||||
|
||||
assert(!obj.HasGUID)
|
||||
assert(!obj_wep.HasGUID)
|
||||
assert(!obj_ammo.HasGUID)
|
||||
obj_res.foreach(box => !box.HasGUID)
|
||||
taskResolver ! TaskResolver.GiveTask(
|
||||
new GUIDTaskTest.RegisterTestTask(probe.ref),
|
||||
List(GUIDTask.RegisterDeployableTurret(obj)(uns))
|
||||
)
|
||||
probe.expectMsg(scala.util.Success)
|
||||
assert(obj.HasGUID)
|
||||
assert(obj_wep.HasGUID)
|
||||
assert(obj_ammo.HasGUID)
|
||||
obj_res.foreach(box => box.HasGUID)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.guidtask
|
||||
|
||||
import base.ActorTest
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
|
||||
|
||||
class GUIDTaskRegisterVehicleTest extends ActorTest {
|
||||
"RegisterVehicle" in {
|
||||
val (_, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
|
||||
val obj = Vehicle(GlobalDefinitions.fury)
|
||||
val obj_wep = obj.WeaponControlledFromSeat(0).get
|
||||
val obj_wep_ammo = (obj.WeaponControlledFromSeat(0).get.asInstanceOf[Tool].AmmoSlots.head.Box =
|
||||
AmmoBox(GlobalDefinitions.hellfire_ammo)).get
|
||||
obj.Trunk += 30 -> AmmoBox(GlobalDefinitions.hellfire_ammo)
|
||||
val obj_trunk_ammo = obj.Trunk.Items(0).obj
|
||||
|
||||
assert(!obj.HasGUID)
|
||||
assert(!obj_wep.HasGUID)
|
||||
assert(!obj_wep_ammo.HasGUID)
|
||||
assert(!obj_trunk_ammo.HasGUID)
|
||||
taskResolver ! TaskResolver.GiveTask(
|
||||
new GUIDTaskTest.RegisterTestTask(probe.ref),
|
||||
List(GUIDTask.RegisterVehicle(obj)(uns))
|
||||
)
|
||||
probe.expectMsg(scala.util.Success)
|
||||
assert(obj.HasGUID)
|
||||
assert(obj_wep.HasGUID)
|
||||
assert(obj_wep_ammo.HasGUID)
|
||||
assert(obj_trunk_ammo.HasGUID)
|
||||
}
|
||||
}
|
||||
51
src/test/scala/objects/guidtask/GUIDTaskTest.scala
Normal file
51
src/test/scala/objects/guidtask/GUIDTaskTest.scala
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.guidtask
|
||||
|
||||
import java.util.logging.LogManager
|
||||
import scala.util.Success
|
||||
import akka.actor.{ActorRef, ActorSystem, Props}
|
||||
import akka.testkit.TestProbe
|
||||
import net.psforever.objects.entity.IdentifiableEntity
|
||||
import net.psforever.objects.guid.actor.{NumberPoolActor, UniqueNumberSystem}
|
||||
import net.psforever.objects.guid.selector.RandomSelector
|
||||
import net.psforever.objects.guid.source.LimitedNumberSource
|
||||
import net.psforever.objects.guid.{NumberPoolHub, Task, TaskResolver}
|
||||
|
||||
object GUIDTaskTest {
|
||||
class TestObject extends IdentifiableEntity
|
||||
|
||||
class RegisterTestTask(probe: ActorRef) extends Task {
|
||||
def Execute(resolver: ActorRef): Unit = {
|
||||
probe ! Success
|
||||
resolver ! Success(this)
|
||||
}
|
||||
}
|
||||
|
||||
def CommonTestSetup(implicit system: ActorSystem): (NumberPoolHub, ActorRef, ActorRef, TestProbe) = {
|
||||
import akka.actor.Props
|
||||
import akka.routing.RandomPool
|
||||
import akka.testkit.TestProbe
|
||||
|
||||
val guid: NumberPoolHub = new NumberPoolHub(new LimitedNumberSource(110))
|
||||
guid.AddPool("dynamic", (1 to 100).toList).Selector = new RandomSelector //TODO name is hardcoded for now
|
||||
val uns = system.actorOf(
|
||||
RandomPool(25).props(Props(classOf[UniqueNumberSystem], guid, GUIDTaskTest.AllocateNumberPoolActors(guid))),
|
||||
"uns"
|
||||
)
|
||||
val taskResolver = system.actorOf(RandomPool(15).props(Props[TaskResolver]()), "resolver")
|
||||
LogManager.getLogManager.reset() //suppresses any internal loggers created by the above elements
|
||||
(guid, uns, taskResolver, TestProbe())
|
||||
}
|
||||
|
||||
/**
|
||||
* @see `UniqueNumberSystem.AllocateNumberPoolActors(NumberPoolHub)(implicit ActorContext)`
|
||||
*/
|
||||
def AllocateNumberPoolActors(poolSource: NumberPoolHub)(implicit system: ActorSystem): Map[String, ActorRef] = {
|
||||
poolSource.Pools
|
||||
.map({
|
||||
case ((pname, pool)) =>
|
||||
pname -> system.actorOf(Props(classOf[NumberPoolActor], pool), pname)
|
||||
})
|
||||
.toMap
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.guidtask
|
||||
|
||||
import base.ActorTest
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
|
||||
|
||||
class GUIDTaskUnregisterAmmoTest extends ActorTest {
|
||||
"UnregisterEquipment -> UnregisterObjectTask" in {
|
||||
val (guid, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
|
||||
val obj = AmmoBox(GlobalDefinitions.energy_cell)
|
||||
guid.register(obj, "dynamic")
|
||||
|
||||
assert(obj.HasGUID)
|
||||
taskResolver ! TaskResolver.GiveTask(
|
||||
new GUIDTaskTest.RegisterTestTask(probe.ref),
|
||||
List(GUIDTask.UnregisterEquipment(obj)(uns))
|
||||
)
|
||||
probe.expectMsg(scala.util.Success)
|
||||
assert(!obj.HasGUID)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.guidtask
|
||||
|
||||
import base.ActorTest
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
|
||||
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire}
|
||||
|
||||
class GUIDTaskUnregisterAvatarTest extends ActorTest {
|
||||
"UnregisterAvatar" in {
|
||||
val (guid, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
|
||||
val obj = Player(Avatar(0, "test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
val obj_wep = Tool(GlobalDefinitions.beamer)
|
||||
obj.Slot(0).Equipment = obj_wep
|
||||
val obj_wep_ammo = AmmoBox(GlobalDefinitions.energy_cell)
|
||||
obj_wep.AmmoSlots.head.Box = obj_wep_ammo
|
||||
val obj_inv_ammo = AmmoBox(GlobalDefinitions.energy_cell)
|
||||
obj.Slot(6).Equipment = obj_inv_ammo
|
||||
val obj_locker = obj.Slot(5).Equipment.get
|
||||
val obj_locker_ammo = AmmoBox(GlobalDefinitions.energy_cell)
|
||||
obj_locker.asInstanceOf[LockerEquipment].Inventory += 0 -> obj_locker_ammo
|
||||
guid.register(obj, "dynamic")
|
||||
guid.register(obj_wep, "dynamic")
|
||||
guid.register(obj_wep_ammo, "dynamic")
|
||||
guid.register(obj_inv_ammo, "dynamic")
|
||||
guid.register(obj_locker, "dynamic")
|
||||
guid.register(obj_locker_ammo, "dynamic")
|
||||
|
||||
assert(obj.HasGUID)
|
||||
assert(obj_wep.HasGUID)
|
||||
assert(obj_wep_ammo.HasGUID)
|
||||
assert(obj_inv_ammo.HasGUID)
|
||||
assert(obj_locker.HasGUID)
|
||||
assert(obj_locker_ammo.HasGUID)
|
||||
taskResolver ! TaskResolver.GiveTask(
|
||||
new GUIDTaskTest.RegisterTestTask(probe.ref),
|
||||
List(GUIDTask.UnregisterAvatar(obj)(uns))
|
||||
)
|
||||
probe.expectMsg(scala.util.Success)
|
||||
assert(!obj.HasGUID)
|
||||
assert(!obj_wep.HasGUID)
|
||||
assert(!obj_wep_ammo.HasGUID)
|
||||
assert(!obj_inv_ammo.HasGUID)
|
||||
assert(!obj_locker.HasGUID)
|
||||
assert(!obj_locker_ammo.HasGUID)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.guidtask
|
||||
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
|
||||
|
||||
class GUIDTaskUnregisterObjectTest extends ActorTest {
|
||||
"UnregisterObjectTask" in {
|
||||
val (guid, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
|
||||
val obj = new GUIDTaskTest.TestObject
|
||||
guid.register(obj, "dynamic")
|
||||
|
||||
assert(obj.HasGUID)
|
||||
taskResolver ! TaskResolver.GiveTask(
|
||||
new GUIDTaskTest.RegisterTestTask(probe.ref),
|
||||
List(GUIDTask.UnregisterObjectTask(obj)(uns))
|
||||
)
|
||||
probe.expectMsg(scala.util.Success)
|
||||
assert(!obj.HasGUID)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.guidtask
|
||||
|
||||
import base.ActorTest
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
|
||||
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire}
|
||||
|
||||
class GUIDTaskUnregisterPlayerTest extends ActorTest {
|
||||
"UnregisterPlayer" in {
|
||||
val (guid, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
|
||||
val obj = Player(Avatar(0, "test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
val obj_wep = Tool(GlobalDefinitions.beamer)
|
||||
obj.Slot(0).Equipment = obj_wep
|
||||
val obj_wep_ammo = AmmoBox(GlobalDefinitions.energy_cell)
|
||||
obj_wep.AmmoSlots.head.Box = obj_wep_ammo
|
||||
val obj_inv_ammo = AmmoBox(GlobalDefinitions.energy_cell)
|
||||
obj.Slot(6).Equipment = obj_inv_ammo
|
||||
val obj_locker = obj.Slot(5).Equipment.get
|
||||
val obj_locker_ammo = AmmoBox(GlobalDefinitions.energy_cell)
|
||||
obj_locker.asInstanceOf[LockerEquipment].Inventory += 0 -> obj_locker_ammo
|
||||
guid.register(obj, "dynamic")
|
||||
guid.register(obj_wep, "dynamic")
|
||||
guid.register(obj_wep_ammo, "dynamic")
|
||||
guid.register(obj_inv_ammo, "dynamic")
|
||||
guid.register(obj_locker, "dynamic")
|
||||
guid.register(obj_locker_ammo, "dynamic")
|
||||
|
||||
assert(obj.HasGUID)
|
||||
assert(obj_wep.HasGUID)
|
||||
assert(obj_wep_ammo.HasGUID)
|
||||
assert(obj_inv_ammo.HasGUID)
|
||||
assert(obj_locker.HasGUID)
|
||||
assert(obj_locker_ammo.HasGUID)
|
||||
taskResolver ! TaskResolver.GiveTask(
|
||||
new GUIDTaskTest.RegisterTestTask(probe.ref),
|
||||
List(GUIDTask.UnregisterPlayer(obj)(uns))
|
||||
)
|
||||
probe.expectMsg(scala.util.Success)
|
||||
assert(!obj.HasGUID)
|
||||
assert(!obj_wep.HasGUID)
|
||||
assert(!obj_wep_ammo.HasGUID)
|
||||
assert(!obj_inv_ammo.HasGUID)
|
||||
assert(obj_locker.HasGUID)
|
||||
assert(obj_locker_ammo.HasGUID)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.guidtask
|
||||
|
||||
import base.ActorTest
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
|
||||
|
||||
class GUIDTaskUnregisterToolTest extends ActorTest {
|
||||
"UnregisterEquipment -> UnregisterTool" in {
|
||||
val (guid, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
|
||||
val obj = Tool(GlobalDefinitions.beamer)
|
||||
obj.AmmoSlots.head.Box = AmmoBox(GlobalDefinitions.energy_cell)
|
||||
guid.register(obj, "dynamic")
|
||||
guid.register(obj.AmmoSlots.head.Box, "dynamic")
|
||||
|
||||
assert(obj.HasGUID)
|
||||
assert(obj.AmmoSlots.head.Box.HasGUID)
|
||||
taskResolver ! TaskResolver.GiveTask(
|
||||
new GUIDTaskTest.RegisterTestTask(probe.ref),
|
||||
List(GUIDTask.UnregisterEquipment(obj)(uns))
|
||||
)
|
||||
probe.expectMsg(scala.util.Success)
|
||||
assert(!obj.HasGUID)
|
||||
assert(!obj.AmmoSlots.head.Box.HasGUID)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.guidtask
|
||||
|
||||
import base.ActorTest
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
|
||||
|
||||
class GUIDTaskUnregisterTurretTest extends ActorTest {
|
||||
"UnregisterDeployableTurret" in {
|
||||
val (guid, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
|
||||
val obj = new TurretDeployable(GlobalDefinitions.portable_manned_turret_vs)
|
||||
val obj_wep = obj.Weapons(1).Equipment.get
|
||||
val obj_ammo = obj_wep.asInstanceOf[Tool].AmmoSlot.Box
|
||||
val obj_res = obj.Inventory.Items.map(_.obj)
|
||||
guid.register(obj, "dynamic")
|
||||
guid.register(obj_wep, "dynamic")
|
||||
guid.register(obj_ammo, "dynamic")
|
||||
obj_res.foreach(box => guid.register(box, "dynamic"))
|
||||
|
||||
assert(obj.HasGUID)
|
||||
assert(obj_wep.HasGUID)
|
||||
assert(obj_ammo.HasGUID)
|
||||
obj_res.foreach(box => box.HasGUID)
|
||||
taskResolver ! TaskResolver.GiveTask(
|
||||
new GUIDTaskTest.RegisterTestTask(probe.ref),
|
||||
List(GUIDTask.UnregisterDeployableTurret(obj)(uns))
|
||||
)
|
||||
probe.expectMsg(scala.util.Success)
|
||||
assert(!obj.HasGUID)
|
||||
assert(!obj_wep.HasGUID)
|
||||
assert(!obj_ammo.HasGUID)
|
||||
obj_res.foreach(box => !box.HasGUID)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.guidtask
|
||||
|
||||
import base.ActorTest
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
|
||||
|
||||
class GUIDTaskUnregisterVehicleTest extends ActorTest {
|
||||
"RegisterVehicle" in {
|
||||
val (guid, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
|
||||
val obj = Vehicle(GlobalDefinitions.fury)
|
||||
val obj_wep = obj.WeaponControlledFromSeat(0).get
|
||||
val obj_wep_ammo = (obj.WeaponControlledFromSeat(0).get.asInstanceOf[Tool].AmmoSlots.head.Box =
|
||||
AmmoBox(GlobalDefinitions.hellfire_ammo)).get
|
||||
obj.Trunk += 30 -> AmmoBox(GlobalDefinitions.hellfire_ammo)
|
||||
val obj_trunk_ammo = obj.Trunk.Items(0).obj
|
||||
guid.register(obj, "dynamic")
|
||||
guid.register(obj_wep, "dynamic")
|
||||
guid.register(obj_wep_ammo, "dynamic")
|
||||
guid.register(obj_trunk_ammo, "dynamic")
|
||||
|
||||
assert(obj.HasGUID)
|
||||
assert(obj_wep.HasGUID)
|
||||
assert(obj_wep_ammo.HasGUID)
|
||||
assert(obj_trunk_ammo.HasGUID)
|
||||
taskResolver ! TaskResolver.GiveTask(
|
||||
new GUIDTaskTest.RegisterTestTask(probe.ref),
|
||||
List(GUIDTask.UnregisterVehicle(obj)(uns))
|
||||
)
|
||||
probe.expectMsg(scala.util.Success)
|
||||
assert(!obj.HasGUID)
|
||||
assert(!obj_wep.HasGUID)
|
||||
assert(!obj_wep_ammo.HasGUID)
|
||||
assert(!obj_trunk_ammo.HasGUID)
|
||||
}
|
||||
}
|
||||
51
src/test/scala/objects/number/NumberPoolActorTest.scala
Normal file
51
src/test/scala/objects/number/NumberPoolActorTest.scala
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.number
|
||||
|
||||
import akka.actor.Props
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.guid.actor.NumberPoolActor
|
||||
import net.psforever.objects.guid.pool.ExclusivePool
|
||||
import net.psforever.objects.guid.selector.RandomSelector
|
||||
|
||||
import scala.concurrent.duration.Duration
|
||||
|
||||
class NumberPoolActorTest extends ActorTest {
|
||||
"NumberPoolActor" should {
|
||||
"GetAnyNumber" in {
|
||||
val pool = new ExclusivePool((25 to 50).toList)
|
||||
pool.Selector = new RandomSelector
|
||||
val poolActor = system.actorOf(Props(classOf[NumberPoolActor], pool), name = "poolActor1")
|
||||
poolActor ! NumberPoolActor.GetAnyNumber()
|
||||
val msg = receiveOne(Duration.create(500, "ms"))
|
||||
assert(msg.isInstanceOf[NumberPoolActor.GiveNumber])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class NumberPoolActorTest1 extends ActorTest {
|
||||
"NumberPoolActor" should {
|
||||
"GetSpecificNumber" in {
|
||||
val pool = new ExclusivePool((25 to 50).toList)
|
||||
pool.Selector = new RandomSelector
|
||||
val poolActor = system.actorOf(Props(classOf[NumberPoolActor], pool), name = "poolActor2")
|
||||
poolActor ! NumberPoolActor.GetSpecificNumber(37)
|
||||
expectMsg(NumberPoolActor.GiveNumber(37, None))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class NumberPoolActorTest2 extends ActorTest {
|
||||
"NumberPoolActor" should {
|
||||
"NoNumber" in {
|
||||
val pool = new ExclusivePool((25 to 25).toList) //pool only has one number - 25
|
||||
pool.Selector = new RandomSelector
|
||||
val poolActor = system.actorOf(Props(classOf[NumberPoolActor], pool), name = "poolActor3")
|
||||
poolActor ! NumberPoolActor.GetAnyNumber()
|
||||
expectMsg(NumberPoolActor.GiveNumber(25, None))
|
||||
|
||||
poolActor ! NumberPoolActor.GetAnyNumber()
|
||||
val msg = receiveOne(Duration.create(500, "ms"))
|
||||
assert(msg.isInstanceOf[NumberPoolActor.NoNumber])
|
||||
}
|
||||
}
|
||||
}
|
||||
343
src/test/scala/objects/number/NumberPoolHubTest.scala
Normal file
343
src/test/scala/objects/number/NumberPoolHubTest.scala
Normal file
|
|
@ -0,0 +1,343 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.number
|
||||
|
||||
import net.psforever.objects.entity.IdentifiableEntity
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
import net.psforever.objects.guid.selector.RandomSelector
|
||||
import net.psforever.objects.guid.source.LimitedNumberSource
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
import scala.util.Success
|
||||
|
||||
class NumberPoolHubTest extends Specification {
|
||||
val numberList = 0 :: 1 :: 2 :: 3 :: 5 :: 8 :: 13 :: 21 :: Nil
|
||||
val numberList1 = 0 :: 1 :: 2 :: 3 :: 5 :: Nil
|
||||
val numberList2 = 8 :: 13 :: 21 :: 34 :: Nil
|
||||
val numberSet1 = numberList1.toSet
|
||||
val numberSet2 = numberList2.toSet
|
||||
class EntityTestClass extends IdentifiableEntity
|
||||
|
||||
"NumberPoolHub" should {
|
||||
"construct" in {
|
||||
new NumberPoolHub(new LimitedNumberSource(51))
|
||||
ok
|
||||
}
|
||||
|
||||
"get a pool" in {
|
||||
val obj = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
obj.GetPool("generic").isDefined mustEqual true //default pool
|
||||
}
|
||||
|
||||
"add a pool" in {
|
||||
val obj = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
obj.Numbers.isEmpty mustEqual true
|
||||
obj.AddPool("fibonacci", numberList)
|
||||
obj.Numbers.toSet.equals(numberList.toSet) mustEqual true
|
||||
val pool = obj.GetPool("fibonacci")
|
||||
pool.isDefined mustEqual true
|
||||
pool.get.Numbers.equals(numberList)
|
||||
}
|
||||
|
||||
"enumerate the content of all pools" in {
|
||||
val obj = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
obj.AddPool("fibonacci1", numberList1)
|
||||
obj.AddPool("fibonacci2", numberList2)
|
||||
numberSet1.intersect(obj.Numbers.toSet) mustEqual numberSet1
|
||||
numberSet2.intersect(obj.Numbers.toSet) mustEqual numberSet2
|
||||
obj.Numbers.toSet.diff(numberSet1) mustEqual numberSet2
|
||||
}
|
||||
|
||||
"remove a pool" in {
|
||||
val obj = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
obj.Numbers.isEmpty mustEqual true
|
||||
obj.AddPool("fibonacci", numberList)
|
||||
obj.Numbers.toSet.equals(numberList.toSet) mustEqual true
|
||||
obj.RemovePool("fibonacci").toSet.equals(numberList.toSet) mustEqual true
|
||||
obj.Numbers.isEmpty mustEqual true
|
||||
obj.GetPool("fibonacci").isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"block removing the default 'generic' pool" in {
|
||||
val obj = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
obj.RemovePool("generic") must throwA[IllegalArgumentException]
|
||||
}
|
||||
|
||||
"block adding pools that use already-included numbers" in {
|
||||
val obj = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
obj.AddPool("fibonacci1", numberList)
|
||||
val numberList4 = 3 :: 7 :: 21 :: 34 :: 45 :: Nil
|
||||
obj.AddPool("fibonacci2", numberList4) must throwA[IllegalArgumentException]
|
||||
}
|
||||
|
||||
"enumerate only the content of all current pools" in {
|
||||
val obj = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
obj.AddPool("fibonacci1", numberList1)
|
||||
obj.AddPool("fibonacci2", numberList2)
|
||||
numberSet1.intersect(obj.Numbers.toSet) mustEqual numberSet1
|
||||
numberSet2.intersect(obj.Numbers.toSet) mustEqual numberSet2
|
||||
obj.RemovePool("fibonacci1")
|
||||
numberSet1.intersect(obj.Numbers.toSet) mustEqual Set() //no intersect
|
||||
numberSet2.intersect(obj.Numbers.toSet) mustEqual numberSet2
|
||||
}
|
||||
|
||||
"register an object to a pool" in {
|
||||
val hub = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
hub.AddPool("fibonacci", numberList)
|
||||
val obj = new EntityTestClass()
|
||||
obj.GUID must throwA[Exception]
|
||||
hub.register(obj, "fibonacci") match {
|
||||
case Success(number) =>
|
||||
obj.GUID mustEqual PlanetSideGUID(number)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"lookup a registered object" in {
|
||||
val hub = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
hub.AddPool("fibonacci", numberList)
|
||||
val obj = new EntityTestClass()
|
||||
hub.register(obj, "fibonacci") match {
|
||||
case Success(number) =>
|
||||
val objFromNumber = hub(number)
|
||||
objFromNumber.contains(obj) mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"lookup the pool of a(n unassigned) number" in {
|
||||
val hub = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
hub.AddPool("fibonacci1", numberList1)
|
||||
hub.AddPool("fibonacci2", numberList2)
|
||||
hub.WhichPool(13).contains("fibonacci2") mustEqual true
|
||||
}
|
||||
|
||||
"lookup the pool of a registered object" in {
|
||||
val hub = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
hub.AddPool("fibonacci", numberList1)
|
||||
val obj = new EntityTestClass()
|
||||
hub.register(obj, "fibonacci")
|
||||
hub.WhichPool(obj).contains("fibonacci") mustEqual true
|
||||
}
|
||||
|
||||
"register an object to a specific, unused number; it is assigned to pool 'generic'" in {
|
||||
val hub = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
hub.AddPool("fibonacci", numberList1)
|
||||
val obj = new EntityTestClass()
|
||||
obj.GUID must throwA[Exception]
|
||||
hub.register(obj, 44) match {
|
||||
case Success(number) =>
|
||||
obj.GUID mustEqual PlanetSideGUID(number)
|
||||
hub.WhichPool(obj).contains("generic") mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"register an object to a specific, pooled number (list 1)" in {
|
||||
val src = new LimitedNumberSource(51)
|
||||
val hub = new NumberPoolHub(src)
|
||||
hub.AddPool("fibonacci", numberList)
|
||||
val obj = new EntityTestClass()
|
||||
obj.GUID must throwA[Exception]
|
||||
hub.register(obj, 5) match {
|
||||
case Success(number) =>
|
||||
obj.GUID mustEqual PlanetSideGUID(number)
|
||||
hub.WhichPool(obj).contains("fibonacci") mustEqual true
|
||||
src.Available(5).isEmpty mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"register an object to a specific, pooled number (list 2)" in {
|
||||
val src = new LimitedNumberSource(51)
|
||||
val hub = new NumberPoolHub(src)
|
||||
hub.AddPool("fibonacci", numberList2)
|
||||
val obj = new EntityTestClass()
|
||||
obj.GUID must throwA[Exception]
|
||||
hub.register(obj, 13) match {
|
||||
case Success(number) =>
|
||||
obj.GUID mustEqual PlanetSideGUID(number)
|
||||
hub.WhichPool(obj).contains("fibonacci") mustEqual true
|
||||
src.Available(13).isEmpty mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"register an object without extra specifications; it is assigned to pool 'generic'" in {
|
||||
val hub = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
val obj = new EntityTestClass()
|
||||
hub.register(obj)
|
||||
hub.WhichPool(obj).contains("generic") mustEqual true
|
||||
}
|
||||
|
||||
"unregister an object" in {
|
||||
val hub = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
hub.AddPool("fibonacci", numberList)
|
||||
val obj = new EntityTestClass()
|
||||
obj.HasGUID mustEqual false
|
||||
hub.register(obj, "fibonacci")
|
||||
hub.WhichPool(obj).contains("fibonacci") mustEqual true
|
||||
obj.HasGUID mustEqual true
|
||||
|
||||
hub.unregister(obj)
|
||||
obj.HasGUID mustEqual false
|
||||
hub.WhichPool(obj).isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"not register an object to a different pool" in {
|
||||
val hub = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
hub.AddPool("fibonacci1", numberList1)
|
||||
hub.AddPool("fibonacci2", numberList2)
|
||||
val obj = new EntityTestClass()
|
||||
hub.register(obj, "fibonacci1")
|
||||
hub.register(obj, "fibonacci2")
|
||||
hub.WhichPool(obj).contains("fibonacci1") mustEqual true
|
||||
}
|
||||
|
||||
"fail to unregister an object that is not registered to this hub" in {
|
||||
val hub1 = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
val hub2 = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
hub1.AddPool("fibonacci", numberList)
|
||||
hub2.AddPool("fibonacci", numberList)
|
||||
val obj = new EntityTestClass()
|
||||
hub1.register(obj, "fibonacci")
|
||||
hub2.unregister(obj) must throwA[Exception]
|
||||
}
|
||||
|
||||
"pre-register a specific, unused number" in {
|
||||
val hub = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
hub.register(13) match {
|
||||
case Success(_) =>
|
||||
ok
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"pre-register a specific, pooled number" in {
|
||||
val hub = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
hub.AddPool("fibonacci", numberList)
|
||||
hub.register(13) match {
|
||||
case Success(key) =>
|
||||
key.GUID mustEqual 13
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"pre-register a number from a known pool" in {
|
||||
val hub = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
hub.AddPool("fibonacci", numberList).Selector = new RandomSelector
|
||||
hub.register("fibonacci") match {
|
||||
case Success(key) =>
|
||||
numberList.contains(key.GUID) mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"unregister a number" in {
|
||||
val hub = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
hub.AddPool("fibonacci", numberList).Selector = new RandomSelector //leave this tagged on
|
||||
val obj = new EntityTestClass()
|
||||
hub.register(13) match {
|
||||
case Success(key) =>
|
||||
key.Object = obj
|
||||
obj.HasGUID mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
hub.WhichPool(obj).contains("fibonacci") mustEqual true
|
||||
hub.unregister(13) match {
|
||||
case Success(thing) =>
|
||||
thing.contains(obj) mustEqual true
|
||||
thing.get.HasGUID mustEqual false
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"not affect the hidden restricted pool by adding a new pool" in {
|
||||
val src = new LimitedNumberSource(51)
|
||||
src.Restrict(4)
|
||||
src.Restrict(8) //in fibonacci
|
||||
src.Restrict(10)
|
||||
src.Restrict(12)
|
||||
val hub = new NumberPoolHub(src)
|
||||
hub.AddPool("fibonacci", numberList) must throwA[IllegalArgumentException]
|
||||
}
|
||||
|
||||
"not register an object to a number belonging to the restricted pool" in {
|
||||
val src = new LimitedNumberSource(51)
|
||||
src.Restrict(4)
|
||||
val hub = new NumberPoolHub(src)
|
||||
val obj = new EntityTestClass()
|
||||
hub.register(obj, 4).isFailure mustEqual true
|
||||
}
|
||||
|
||||
"not register an object to the restricted pool directly" in {
|
||||
val src = new LimitedNumberSource(51)
|
||||
// src.Restrict(4)
|
||||
val hub = new NumberPoolHub(src)
|
||||
val obj = new EntityTestClass()
|
||||
hub.register(obj, "").isFailure mustEqual true //the empty string represents the restricted pool
|
||||
}
|
||||
|
||||
"not register a number belonging to the restricted pool" in {
|
||||
val src = new LimitedNumberSource(51)
|
||||
src.Restrict(4)
|
||||
val hub = new NumberPoolHub(src)
|
||||
hub.register(4).isFailure mustEqual true
|
||||
}
|
||||
|
||||
"not unregister a number belonging to the restricted pool" in {
|
||||
val src = new LimitedNumberSource(51)
|
||||
src.Restrict(4)
|
||||
val hub = new NumberPoolHub(src)
|
||||
hub.unregister(4).isFailure mustEqual true
|
||||
}
|
||||
|
||||
"identity an object that is registered to it" in {
|
||||
val hub1 = new NumberPoolHub(new LimitedNumberSource(10))
|
||||
val hub2 = new NumberPoolHub(new LimitedNumberSource(10))
|
||||
val obj1 = new EntityTestClass()
|
||||
val obj2 = new EntityTestClass()
|
||||
hub1.register(obj1)
|
||||
hub2.register(obj2)
|
||||
|
||||
hub1.isRegistered(obj1) mustEqual true
|
||||
hub2.isRegistered(obj2) mustEqual true
|
||||
hub1.isRegistered(obj2) mustEqual false
|
||||
hub2.isRegistered(obj1) mustEqual false
|
||||
}
|
||||
|
||||
"identity a number that is registered to it" in {
|
||||
val src1 = new LimitedNumberSource(5)
|
||||
val hub1 = new NumberPoolHub(src1)
|
||||
val src2 = new LimitedNumberSource(10)
|
||||
src2.Restrict(0)
|
||||
src2.Restrict(1)
|
||||
src2.Restrict(2)
|
||||
src2.Restrict(3)
|
||||
src2.Restrict(4)
|
||||
src2.Restrict(5)
|
||||
val hub2 = new NumberPoolHub(src2)
|
||||
val obj1 = new EntityTestClass()
|
||||
val obj2 = new EntityTestClass()
|
||||
hub1.register(obj1)
|
||||
hub2.register(obj2)
|
||||
val num1 = obj1.GUID.guid
|
||||
val num2 = obj2.GUID.guid
|
||||
|
||||
hub1.isRegistered(num1) mustEqual true
|
||||
hub2.isRegistered(num2) mustEqual true
|
||||
hub1.isRegistered(num2) mustEqual false
|
||||
hub2.isRegistered(num1) mustEqual false
|
||||
}
|
||||
}
|
||||
}
|
||||
220
src/test/scala/objects/number/NumberPoolTest.scala
Normal file
220
src/test/scala/objects/number/NumberPoolTest.scala
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.number
|
||||
|
||||
import net.psforever.objects.guid.pool.{ExclusivePool, GenericPool, SimplePool}
|
||||
import net.psforever.objects.guid.selector.SpecificSelector
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
import scala.collection.mutable
|
||||
import scala.collection.mutable.ListBuffer
|
||||
import scala.util.Success
|
||||
|
||||
class NumberPoolTest extends Specification {
|
||||
"SimplePool" should {
|
||||
"construct" in {
|
||||
new SimplePool(0 :: 1 :: 2 :: Nil)
|
||||
ok
|
||||
}
|
||||
|
||||
"fail to construct 1 (number less than zero)" in {
|
||||
new SimplePool(-1 :: Nil) must throwA[IllegalArgumentException]
|
||||
}
|
||||
|
||||
"fail to construct 2 (duplicate numbers)" in {
|
||||
new SimplePool(1 :: 1 :: Nil) must throwA[IllegalArgumentException]
|
||||
}
|
||||
|
||||
"get a number" in {
|
||||
val min = 10
|
||||
val max = 20
|
||||
val domain = (min to max).toList
|
||||
val obj = new SimplePool(domain)
|
||||
obj.Get() match {
|
||||
case Success(number) =>
|
||||
(min <= number && number <= max) mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
ok
|
||||
}
|
||||
|
||||
"used number count is always zero" in {
|
||||
val obj = new SimplePool((0 to 10).toList)
|
||||
obj.Count mustEqual 0
|
||||
obj.Get()
|
||||
obj.Count mustEqual 0
|
||||
}
|
||||
|
||||
"return a number" in {
|
||||
//returning a number for a SimplePool is actually just a way of checking that the number is in the "pool" at all
|
||||
val obj = new SimplePool((0 to 10).toList)
|
||||
obj.Get() match {
|
||||
case Success(number) =>
|
||||
obj.Return(number) mustEqual true
|
||||
obj.Return(11) mustEqual false
|
||||
obj.Return(number) mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"numbers remain available" in {
|
||||
val obj = new SimplePool((0 to 10).toList)
|
||||
obj.Selector = new SpecificSelector
|
||||
obj.Selector.asInstanceOf[SpecificSelector].SelectionIndex = 8
|
||||
obj.Get() mustEqual Success(8)
|
||||
obj.Get() mustEqual Success(8) //compare to how SpecificSelector works otherwise - it would be an invalid return
|
||||
}
|
||||
}
|
||||
|
||||
"ExclusivePool" should {
|
||||
"construct" in {
|
||||
new ExclusivePool(0 :: 1 :: 2 :: Nil)
|
||||
ok
|
||||
}
|
||||
|
||||
"get a number" in {
|
||||
val min = 10
|
||||
val max = 20
|
||||
val domain = (min to max).toList
|
||||
val obj = new ExclusivePool(domain)
|
||||
obj.Get() match {
|
||||
case Success(number) =>
|
||||
(min <= number && number <= max) mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
ok
|
||||
}
|
||||
|
||||
"get all the numbers" in {
|
||||
val min = 10
|
||||
val max = 20
|
||||
val domain = (min to max).toList
|
||||
val obj = new ExclusivePool(domain)
|
||||
domain.foreach(_ => {
|
||||
obj.Get() match {
|
||||
case Success(number) =>
|
||||
(min <= number && number <= max) mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
})
|
||||
ok
|
||||
}
|
||||
|
||||
"return a number" in {
|
||||
val obj = new ExclusivePool((0 to 10).toList)
|
||||
obj.Get() match {
|
||||
case Success(number) =>
|
||||
try { obj.Return(number) mustEqual true }
|
||||
catch { case _: Exception => ko }
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"return all the numbers" in {
|
||||
val range = 0 to 10
|
||||
val obj = new ExclusivePool((0 to 10).toList)
|
||||
val list: ListBuffer[Int] = ListBuffer[Int]()
|
||||
range.foreach(_ => {
|
||||
obj.Get() match {
|
||||
case Success(number) =>
|
||||
list += number
|
||||
case _ =>
|
||||
}
|
||||
})
|
||||
list.foreach(number => {
|
||||
try { obj.Return(number) mustEqual true }
|
||||
catch { case _: Exception => ko }
|
||||
})
|
||||
ok
|
||||
}
|
||||
}
|
||||
|
||||
"GenericPool" should {
|
||||
"construct" in {
|
||||
new GenericPool(mutable.LongMap[String](), 11)
|
||||
ok
|
||||
}
|
||||
|
||||
"get a provided number" in {
|
||||
val map = mutable.LongMap[String]()
|
||||
val obj = new GenericPool(map, 11)
|
||||
obj.Numbers.isEmpty mustEqual true
|
||||
obj.Selector.asInstanceOf[SpecificSelector].SelectionIndex = 5
|
||||
obj.Get() match {
|
||||
case Success(number) =>
|
||||
number mustEqual 5
|
||||
map.contains(5) mustEqual true
|
||||
map(5) mustEqual "generic"
|
||||
obj.Numbers.contains(5) mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"return a number" in {
|
||||
val map = mutable.LongMap[String]()
|
||||
val obj = new GenericPool(map, 11)
|
||||
obj.Selector.asInstanceOf[SpecificSelector].SelectionIndex = 5
|
||||
obj.Get()
|
||||
map.get(5).contains("generic") mustEqual true
|
||||
obj.Numbers.contains(5) mustEqual true
|
||||
obj.Return(5) mustEqual true
|
||||
map.get(5).isEmpty mustEqual true
|
||||
obj.Numbers.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"block on numbers that are already defined" in {
|
||||
val map = mutable.LongMap[String]()
|
||||
map += 5L -> "test" //5 is defined
|
||||
val obj = new GenericPool(map, 11)
|
||||
obj.Numbers.isEmpty mustEqual true
|
||||
obj.Selector.asInstanceOf[SpecificSelector].SelectionIndex = 5 //5 is requested
|
||||
obj.Get() match {
|
||||
case Success(_) =>
|
||||
ko
|
||||
case _ =>
|
||||
obj.Numbers.isEmpty mustEqual true
|
||||
}
|
||||
}
|
||||
|
||||
"get a free number on own if none provided" in {
|
||||
val map = mutable.LongMap[String]()
|
||||
val obj = new GenericPool(map, 11)
|
||||
obj.Get() match {
|
||||
case Success(number) =>
|
||||
number mustEqual 5
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"get a free number that is not already defined" in {
|
||||
val map = mutable.LongMap[String]()
|
||||
map += 5L -> "test" //5 is defined; think, -1 :: 5 :: 11
|
||||
val obj = new GenericPool(map, 11)
|
||||
obj.Get() match {
|
||||
case Success(number) =>
|
||||
number mustEqual 2 // think, -1 :: 2 :: 5 :: 11
|
||||
case _ => ko
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
"get a free number that represents half of the largest delta" in {
|
||||
val map = mutable.LongMap[String]()
|
||||
map += 5L -> "test" //5 is defined; think, -1 :: 5 :: 11
|
||||
map += 4L -> "test" //4 is defined; think, -1 :: 4 :: 5 :: 11
|
||||
val obj = new GenericPool(map, 11)
|
||||
obj.Get() match {
|
||||
case Success(number) =>
|
||||
number mustEqual 8 // think, -1 :: 4 :: 5 :: 8 :: 11
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
329
src/test/scala/objects/number/NumberSelectorTest.scala
Normal file
329
src/test/scala/objects/number/NumberSelectorTest.scala
Normal file
|
|
@ -0,0 +1,329 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.number
|
||||
|
||||
import net.psforever.objects.guid.selector.{RandomSequenceSelector, _}
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
class NumberSelectorTest extends Specification {
|
||||
def randArrayGen(n: Int = 26, dx: Int = 0): Array[Int] = {
|
||||
val obj = Array.ofDim[Int](n)
|
||||
(0 to 25).foreach(x => { obj(x) = x + dx })
|
||||
obj
|
||||
}
|
||||
|
||||
"RandomSequenceSelector (0, default)" should {
|
||||
"construct" in {
|
||||
new RandomSequenceSelector
|
||||
ok
|
||||
}
|
||||
|
||||
"get a number" in {
|
||||
val n: Int = 26
|
||||
val obj = new RandomSequenceSelector
|
||||
obj.Get(randArrayGen(n)) mustNotEqual -1
|
||||
}
|
||||
|
||||
"return a number" in {
|
||||
val n: Int = 26
|
||||
val obj = new RandomSequenceSelector
|
||||
val ary = randArrayGen(n)
|
||||
val number = obj.Get(ary)
|
||||
number mustNotEqual -1
|
||||
ary.head mustEqual -1 //regardless of which number we actually got, the head of the array is now -1
|
||||
obj.Return(number, ary)
|
||||
ary.head mustEqual number //the returned number is at the head of the array
|
||||
}
|
||||
|
||||
"get all numbers" in {
|
||||
val n = 26
|
||||
val obj = new RandomSequenceSelector
|
||||
val ary = randArrayGen(n)
|
||||
(0 until n).foreach(_ => { obj.Get(ary) mustNotEqual -1 })
|
||||
ok
|
||||
}
|
||||
|
||||
"return all numbers" in {
|
||||
val n = 26
|
||||
val obj = new RandomSequenceSelector
|
||||
val ary1 = randArrayGen(n)
|
||||
val ary2 = randArrayGen(n)
|
||||
(0 until n).foreach(index => { ary2(index) = obj.Get(ary1) }) //move numbers from ary1 to ary2
|
||||
ary2.toSet.diff(ary1.toSet).size mustEqual n //no numbers between ary2 and ary1 match
|
||||
(0 until n).foreach(index => { obj.Return(ary2(index), ary1) mustEqual true }) //return numbers from ary2 to ary1
|
||||
ary2.toSet.diff(ary1.toSet).size mustEqual 0 //no difference in the content between ary2 and ary1
|
||||
}
|
||||
|
||||
"gets invalid index when exhausted" in {
|
||||
val n = 26
|
||||
val obj = new RandomSequenceSelector
|
||||
val ary = randArrayGen(n)
|
||||
(0 until n).foreach(_ => { obj.Get(ary) mustNotEqual -1 })
|
||||
obj.Get(ary) mustEqual -1
|
||||
}
|
||||
|
||||
"format an array" in {
|
||||
val ary = Array[Int](1, -1, 5, 3, -1, 2)
|
||||
(new RandomSequenceSelector).Format(ary)
|
||||
ary mustEqual Array[Int](-1, -1, 1, 5, 3, 2)
|
||||
}
|
||||
}
|
||||
|
||||
"RandomSelector" should {
|
||||
"construct" in {
|
||||
new RandomSelector
|
||||
ok
|
||||
}
|
||||
|
||||
"get a number" in {
|
||||
val obj = new RandomSelector
|
||||
obj.Get(randArrayGen()) mustNotEqual -1
|
||||
}
|
||||
|
||||
"return a number" in {
|
||||
val obj = new RandomSelector
|
||||
val ary = randArrayGen()
|
||||
val number = obj.Get(ary)
|
||||
number mustNotEqual -1
|
||||
ary.head mustEqual -1 //regardless of which number we actually got, the head of the array is now -1
|
||||
obj.Return(number, ary)
|
||||
ary.head mustEqual number //the returned number is at the head of the array
|
||||
}
|
||||
|
||||
"get all numbers" in {
|
||||
val n = 26
|
||||
val obj = new RandomSelector
|
||||
val ary = randArrayGen(n)
|
||||
(0 until n).foreach(_ => { obj.Get(ary) mustNotEqual -1 })
|
||||
ok
|
||||
}
|
||||
|
||||
"return all numbers" in {
|
||||
val n = 26
|
||||
val obj = new RandomSelector
|
||||
val ary1 = randArrayGen(n)
|
||||
val ary2 = randArrayGen(n)
|
||||
(0 until n).foreach(index => { ary2(index) = obj.Get(ary1) }) //move numbers from ary1 to ary2
|
||||
ary2.toSet.diff(ary1.toSet).size mustEqual n //no numbers between ary2 and ary1 match
|
||||
(0 until n).foreach(index => { obj.Return(ary2(index), ary1) mustEqual true }) //return numbers from ary2 to ary1
|
||||
ary2.toSet.diff(ary1.toSet).size mustEqual 0 //no difference in the content between ary2 and ary1
|
||||
}
|
||||
|
||||
"gets invalid index when exhausted" in {
|
||||
val n = 26
|
||||
val obj = new RandomSelector
|
||||
val ary = randArrayGen(n)
|
||||
(0 until n).foreach(_ => { obj.Get(ary) mustNotEqual -1 })
|
||||
obj.Get(ary) mustEqual -1
|
||||
}
|
||||
|
||||
"format an array" in {
|
||||
val ary = Array[Int](1, -1, 5, 3, -1, 2)
|
||||
(new RandomSelector).Format(ary)
|
||||
ary mustEqual Array[Int](-1, -1, 1, 5, 3, 2)
|
||||
}
|
||||
}
|
||||
|
||||
"StrictInOrderSelector" should {
|
||||
"construct" in {
|
||||
new StrictInOrderSelector
|
||||
ok
|
||||
}
|
||||
|
||||
"get a number" in {
|
||||
val obj = new StrictInOrderSelector
|
||||
obj.Get(randArrayGen()) mustNotEqual -1
|
||||
}
|
||||
|
||||
"return a number" in {
|
||||
val obj = new StrictInOrderSelector
|
||||
val ary = randArrayGen()
|
||||
val number = obj.Get(ary)
|
||||
number mustNotEqual -1
|
||||
ary.head mustEqual -1 //regardless of which number we actually got, the head of the array is now -1
|
||||
obj.Return(number, ary)
|
||||
ary.head mustEqual number //the returned number is at the head of the array
|
||||
}
|
||||
|
||||
"get all numbers" in {
|
||||
val n = 26
|
||||
val obj = new StrictInOrderSelector
|
||||
val ary = randArrayGen()
|
||||
(0 until n).foreach(_ => { obj.Get(ary) mustNotEqual -1 })
|
||||
ok
|
||||
}
|
||||
|
||||
"return all numbers" in {
|
||||
val n = 26
|
||||
val obj = new StrictInOrderSelector
|
||||
val ary1 = randArrayGen(n)
|
||||
val ary2 = randArrayGen(n)
|
||||
(0 until n).foreach(index => { ary2(index) = obj.Get(ary1) }) //move numbers from ary1 to ary2
|
||||
ary2.toSet.diff(ary1.toSet).size mustEqual n //no numbers between ary2 and ary1 match
|
||||
(0 until n).foreach(index => { obj.Return(ary2(index), ary1) mustEqual true }) //return numbers from ary2 to ary1
|
||||
ary2.toSet.diff(ary1.toSet).size mustEqual 0 //no difference in the content between ary2 and ary1
|
||||
}
|
||||
|
||||
"gets invalid index when exhausted" in {
|
||||
val n = 26
|
||||
val obj = new StrictInOrderSelector
|
||||
val ary = randArrayGen(n)
|
||||
(0 until n).foreach(_ => { obj.Get(ary) mustNotEqual -1 })
|
||||
obj.Get(ary) mustEqual -1
|
||||
}
|
||||
|
||||
"wait until number is available" in {
|
||||
val n = 26
|
||||
val obj = new StrictInOrderSelector
|
||||
val ary = randArrayGen(n)
|
||||
(0 until n).foreach(_ => { obj.Get(ary) mustNotEqual -1 })
|
||||
obj.Get(ary) mustEqual -1
|
||||
obj.Return(1, ary) //return a number that isn't the one StrictOrder is waiting on
|
||||
obj.Get(ary) mustEqual -1
|
||||
obj.Return(0, ary) //return the number StrictOrder wants
|
||||
obj.Get(ary) mustEqual 0
|
||||
obj.Get(ary) mustEqual 1
|
||||
}
|
||||
|
||||
"format an array" in {
|
||||
val ary = Array[Int](1, -1, 5, 3, -1, 2)
|
||||
(new StrictInOrderSelector).Format(ary)
|
||||
ary mustEqual Array[Int](-1, 1, 2, 3, -1, 5)
|
||||
}
|
||||
}
|
||||
|
||||
"OpportunisticSelector" should {
|
||||
"construct" in {
|
||||
new OpportunisticSelector
|
||||
ok
|
||||
}
|
||||
|
||||
"get a number" in {
|
||||
val obj = new OpportunisticSelector
|
||||
obj.Get(randArrayGen()) mustNotEqual -1
|
||||
}
|
||||
|
||||
"return a number" in {
|
||||
val obj = new OpportunisticSelector
|
||||
val ary = randArrayGen()
|
||||
val number = obj.Get(ary)
|
||||
number mustNotEqual -1
|
||||
ary.head mustEqual -1 //regardless of which number we actually got, the head of the array is now -1
|
||||
obj.Return(number, ary)
|
||||
ary.head mustEqual number //the returned number is at the head of the array
|
||||
}
|
||||
|
||||
"get all numbers" in {
|
||||
val obj = new OpportunisticSelector
|
||||
val ary = randArrayGen()
|
||||
(0 to 25).foreach(_ => { obj.Get(ary) mustNotEqual -1 })
|
||||
ok
|
||||
}
|
||||
|
||||
"return all numbers" in {
|
||||
val n = 26
|
||||
val obj = new OpportunisticSelector
|
||||
val ary1 = randArrayGen(n)
|
||||
val ary2 = randArrayGen(n)
|
||||
(0 until n).foreach(index => { ary2(index) = obj.Get(ary1) }) //move numbers from ary1 to ary2
|
||||
ary2.toSet.diff(ary1.toSet).size mustEqual n //no numbers between ary2 and ary1 match
|
||||
(0 until n).foreach(index => { obj.Return(ary2(index), ary1) mustEqual true }) //return numbers from ary2 to ary1
|
||||
ary2.toSet.diff(ary1.toSet).size mustEqual 0 //no difference in the content between ary2 and ary1
|
||||
}
|
||||
|
||||
"gets invalid index when exhausted" in {
|
||||
val n = 26
|
||||
val obj = new OpportunisticSelector
|
||||
val ary = randArrayGen(n)
|
||||
(0 until n).foreach(_ => { obj.Get(ary) mustNotEqual -1 })
|
||||
obj.Get(ary) mustEqual -1
|
||||
}
|
||||
|
||||
"format an array" in {
|
||||
val ary = Array[Int](1, -1, 5, 3, -1, 2)
|
||||
(new OpportunisticSelector).Format(ary)
|
||||
ary mustEqual Array[Int](-1, -1, 1, 5, 3, 2)
|
||||
}
|
||||
}
|
||||
|
||||
"SpecificSelector" should {
|
||||
"construct" in {
|
||||
new SpecificSelector
|
||||
ok
|
||||
}
|
||||
|
||||
"get a number" in {
|
||||
val obj = new SpecificSelector
|
||||
val ary = randArrayGen()
|
||||
obj.SelectionIndex = 5
|
||||
obj.Get(ary) mustEqual 5
|
||||
obj.Get(ary) mustEqual -1 //now that 5 has been selected, the selector will only get a -1 from that position
|
||||
}
|
||||
|
||||
"return a number" in {
|
||||
val obj = new SpecificSelector
|
||||
val ary = randArrayGen()
|
||||
obj.SelectionIndex = 5
|
||||
val number = obj.Get(ary)
|
||||
number mustEqual 5
|
||||
obj.Get(ary) mustEqual -1
|
||||
obj.Return(number, ary)
|
||||
obj.Get(ary) mustEqual number //the returned number is at the head of the array
|
||||
}
|
||||
|
||||
"return a number (2)" in {
|
||||
val obj = new SpecificSelector
|
||||
val ary = randArrayGen()
|
||||
obj.SelectionIndex = 5
|
||||
val number = obj.Get(ary)
|
||||
number mustEqual 5
|
||||
obj.Get(ary) mustEqual -1
|
||||
ary(number) mustEqual -1
|
||||
|
||||
obj.SelectionIndex = 10 //even if we move the selection index, the number will return to its last position
|
||||
obj.Return(number, ary)
|
||||
ary(number) mustEqual number //the returned number at the original index
|
||||
obj.Get(
|
||||
ary
|
||||
) mustEqual 10 //of course, with the selection index changed, we will not get the same position next time
|
||||
}
|
||||
|
||||
"get all numbers" in {
|
||||
val n = 26
|
||||
val obj = new SpecificSelector
|
||||
val ary = randArrayGen(n)
|
||||
(0 until n).foreach(i => {
|
||||
obj.SelectionIndex = i
|
||||
obj.Get(ary) mustEqual i
|
||||
})
|
||||
ok
|
||||
}
|
||||
|
||||
"return all numbers" in {
|
||||
val n = 26
|
||||
val obj = new SpecificSelector
|
||||
val ary1 = randArrayGen(n)
|
||||
val ary2 = randArrayGen(n)
|
||||
(0 until n).foreach(index => {
|
||||
obj.SelectionIndex = index
|
||||
ary2(index) = obj.Get(ary1)
|
||||
}) //move numbers from ary1 to ary2
|
||||
ary2.toSet.diff(ary1.toSet).size mustEqual n //no numbers between ary2 and ary1 match
|
||||
(0 until n).foreach(index => { obj.Return(ary2(index), ary1) mustEqual true }) //return numbers from ary2 to ary1
|
||||
ary2.toSet.diff(ary1.toSet).size mustEqual 0 //no difference in the content between ary2 and ary1
|
||||
}
|
||||
|
||||
"gets invalid index when exhausted" in {
|
||||
val obj = new SpecificSelector
|
||||
val ary = randArrayGen()
|
||||
obj.SelectionIndex = 5
|
||||
obj.Get(ary) mustEqual 5
|
||||
obj.Get(ary) mustEqual -1 //yes, it really is that simple
|
||||
}
|
||||
|
||||
"format an array" in {
|
||||
val ary = Array[Int](1, -1, 5, 3, -1, 2)
|
||||
(new SpecificSelector).Format(ary)
|
||||
ary mustEqual Array[Int](-1, 1, 2, 3, -1, 5)
|
||||
}
|
||||
}
|
||||
}
|
||||
200
src/test/scala/objects/number/NumberSourceTest.scala
Normal file
200
src/test/scala/objects/number/NumberSourceTest.scala
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.number
|
||||
|
||||
import net.psforever.objects.guid.AvailabilityPolicy
|
||||
import net.psforever.objects.guid.key.{LoanedKey, SecureKey}
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
class NumberSourceTest extends Specification {
|
||||
import net.psforever.objects.entity.IdentifiableEntity
|
||||
private class TestClass extends IdentifiableEntity
|
||||
|
||||
"LimitedNumberSource" should {
|
||||
import net.psforever.objects.guid.source.LimitedNumberSource
|
||||
"construct" in {
|
||||
val obj = LimitedNumberSource(25)
|
||||
obj.Size mustEqual 26
|
||||
obj.CountAvailable mustEqual 26
|
||||
obj.CountUsed mustEqual 0
|
||||
}
|
||||
|
||||
"get a number" in {
|
||||
val obj = LimitedNumberSource(25)
|
||||
val result: Option[LoanedKey] = obj.Available(5)
|
||||
result.isDefined mustEqual true
|
||||
result.get.GUID mustEqual 5
|
||||
result.get.Policy mustEqual AvailabilityPolicy.Leased
|
||||
result.get.Object.isEmpty mustEqual true
|
||||
obj.Size mustEqual 26
|
||||
obj.CountAvailable mustEqual 25
|
||||
obj.CountUsed mustEqual 1
|
||||
}
|
||||
|
||||
"assign the number" in {
|
||||
val obj = LimitedNumberSource(25)
|
||||
val result: Option[LoanedKey] = obj.Available(5)
|
||||
result.isDefined mustEqual true
|
||||
result.get.Object = new TestClass()
|
||||
ok
|
||||
}
|
||||
|
||||
"return a number (unused)" in {
|
||||
val obj = LimitedNumberSource(25)
|
||||
val result: Option[LoanedKey] = obj.Available(5)
|
||||
result.isDefined mustEqual true
|
||||
result.get.GUID mustEqual 5
|
||||
obj.CountUsed mustEqual 1
|
||||
val ret = obj.Return(result.get)
|
||||
ret.isEmpty mustEqual true
|
||||
obj.CountUsed mustEqual 0
|
||||
}
|
||||
|
||||
"return a number (assigned)" in {
|
||||
val obj = LimitedNumberSource(25)
|
||||
val test = new TestClass()
|
||||
val result: Option[LoanedKey] = obj.Available(5)
|
||||
result.isDefined mustEqual true
|
||||
result.get.GUID mustEqual 5
|
||||
result.get.Object = test
|
||||
obj.CountUsed mustEqual 1
|
||||
val ret = obj.Return(result.get)
|
||||
ret.contains(test) mustEqual true
|
||||
obj.CountUsed mustEqual 0
|
||||
}
|
||||
|
||||
"restrict a number (unassigned)" in {
|
||||
val obj = LimitedNumberSource(25)
|
||||
val result: Option[LoanedKey] = obj.Restrict(5)
|
||||
result.isDefined mustEqual true
|
||||
result.get.GUID mustEqual 5
|
||||
result.get.Policy mustEqual AvailabilityPolicy.Restricted
|
||||
result.get.Object.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"restrict a number (assigned + multiple assignments)" in {
|
||||
val obj = LimitedNumberSource(25)
|
||||
val test1 = new TestClass()
|
||||
val test2 = new TestClass()
|
||||
val result: Option[LoanedKey] = obj.Restrict(5)
|
||||
result.get.GUID mustEqual 5
|
||||
result.get.Policy mustEqual AvailabilityPolicy.Restricted
|
||||
result.get.Object.isEmpty mustEqual true
|
||||
result.get.Object = None //assignment 1
|
||||
result.get.Object.isEmpty mustEqual true //still unassigned
|
||||
result.get.Object = test1 //assignment 2
|
||||
result.get.Object.contains(test1) mustEqual true
|
||||
result.get.Object = test2 //assignment 3
|
||||
result.get.Object.contains(test1) mustEqual true //same as above
|
||||
}
|
||||
|
||||
"return a restricted number (correctly fail)" in {
|
||||
val obj = LimitedNumberSource(25)
|
||||
val test = new TestClass()
|
||||
val result: Option[LoanedKey] = obj.Restrict(5)
|
||||
result.get.GUID mustEqual 5
|
||||
result.get.Policy mustEqual AvailabilityPolicy.Restricted
|
||||
result.get.Object = test
|
||||
|
||||
obj.Return(5)
|
||||
val result2: Option[SecureKey] = obj.Get(5)
|
||||
result2.get.GUID mustEqual 5
|
||||
result2.get.Policy mustEqual AvailabilityPolicy.Restricted
|
||||
result2.get.Object.contains(test) mustEqual true
|
||||
}
|
||||
|
||||
"return a secure key" in {
|
||||
val obj = LimitedNumberSource(25)
|
||||
val test = new TestClass()
|
||||
|
||||
val result1: Option[LoanedKey] = obj.Available(5)
|
||||
result1.get.Object = test
|
||||
test.GUID mustEqual PlanetSideGUID(5)
|
||||
|
||||
val result2: Option[SecureKey] = obj.Get(5)
|
||||
obj.Return(result2.get).contains(test) mustEqual true
|
||||
}
|
||||
|
||||
"restrict a previously-assigned number" in {
|
||||
val obj = LimitedNumberSource(25)
|
||||
val test = new TestClass()
|
||||
val result1: Option[LoanedKey] = obj.Available(5)
|
||||
result1.isDefined mustEqual true
|
||||
result1.get.Policy mustEqual AvailabilityPolicy.Leased
|
||||
result1.get.Object = test
|
||||
val result2: Option[LoanedKey] = obj.Restrict(5)
|
||||
result2.isDefined mustEqual true
|
||||
result2.get.Policy mustEqual AvailabilityPolicy.Restricted
|
||||
result2.get.Object.contains(test) mustEqual true
|
||||
}
|
||||
|
||||
"check a number (not previously gotten)" in {
|
||||
val obj = LimitedNumberSource(25)
|
||||
val result2: Option[SecureKey] = obj.Get(5)
|
||||
result2.get.GUID mustEqual 5
|
||||
result2.get.Policy mustEqual AvailabilityPolicy.Available
|
||||
result2.get.Object.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"check a number (previously gotten)" in {
|
||||
val obj = LimitedNumberSource(25)
|
||||
val result: Option[LoanedKey] = obj.Available(5)
|
||||
result.isDefined mustEqual true
|
||||
result.get.GUID mustEqual 5
|
||||
result.get.Policy mustEqual AvailabilityPolicy.Leased
|
||||
result.get.Object.isEmpty mustEqual true
|
||||
val result2: Option[SecureKey] = obj.Get(5)
|
||||
result2.get.GUID mustEqual 5
|
||||
result2.get.Policy mustEqual AvailabilityPolicy.Leased
|
||||
result2.get.Object.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"check a number (assigned)" in {
|
||||
val obj = LimitedNumberSource(25)
|
||||
val result: Option[LoanedKey] = obj.Available(5)
|
||||
result.isDefined mustEqual true
|
||||
result.get.GUID mustEqual 5
|
||||
result.get.Policy mustEqual AvailabilityPolicy.Leased
|
||||
result.get.Object = new TestClass()
|
||||
val result2: Option[SecureKey] = obj.Get(5)
|
||||
result2.get.GUID mustEqual 5
|
||||
result2.get.Policy mustEqual AvailabilityPolicy.Leased
|
||||
result2.get.Object mustEqual result.get.Object
|
||||
}
|
||||
|
||||
"check a number (assigned and returned)" in {
|
||||
val obj = LimitedNumberSource(25)
|
||||
val test = new TestClass()
|
||||
val result: Option[LoanedKey] = obj.Available(5)
|
||||
result.get.Policy mustEqual AvailabilityPolicy.Leased
|
||||
result.get.Object = test
|
||||
val result2: Option[SecureKey] = obj.Get(5)
|
||||
result2.get.Policy mustEqual AvailabilityPolicy.Leased
|
||||
result2.get.Object.get mustEqual test
|
||||
obj.Return(5).contains(test) mustEqual true
|
||||
val result3: Option[SecureKey] = obj.Get(5)
|
||||
result3.get.Policy mustEqual AvailabilityPolicy.Available
|
||||
result3.get.Object.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"clear" in {
|
||||
val obj = LimitedNumberSource(25)
|
||||
val test1 = new TestClass()
|
||||
val test2 = new TestClass()
|
||||
val test3 = new TestClass()
|
||||
obj.Available(5) //no assignment
|
||||
obj.Available(10).get.Object = test1
|
||||
obj.Available(15).get.Object = test2
|
||||
obj.Restrict(15)
|
||||
obj.Restrict(20).get.Object = test3
|
||||
obj.CountUsed mustEqual 4
|
||||
|
||||
val list: List[IdentifiableEntity] = obj.Clear()
|
||||
obj.CountUsed mustEqual 0
|
||||
list.size mustEqual 3
|
||||
list.count(obj => obj == test1) mustEqual 1
|
||||
list.count(obj => obj == test2) mustEqual 1
|
||||
list.count(obj => obj == test3) mustEqual 1
|
||||
}
|
||||
}
|
||||
}
|
||||
60
src/test/scala/objects/number/RegisterTest.scala
Normal file
60
src/test/scala/objects/number/RegisterTest.scala
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.number
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import net.psforever.objects.guid.actor.Register
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
class RegisterTest extends Specification {
|
||||
val obj = new net.psforever.objects.entity.IdentifiableEntity() {}
|
||||
|
||||
"Register" should {
|
||||
"construct (object)" in {
|
||||
val reg = Register(obj)
|
||||
reg.obj mustEqual obj
|
||||
reg.number.isEmpty mustEqual true
|
||||
reg.name.isEmpty mustEqual true
|
||||
reg.callback.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"construct (object, callback)" in {
|
||||
val reg = Register(obj, ActorRef.noSender)
|
||||
reg.obj mustEqual obj
|
||||
reg.number.isEmpty mustEqual true
|
||||
reg.name.isEmpty mustEqual true
|
||||
reg.callback.contains(ActorRef.noSender) mustEqual true
|
||||
}
|
||||
|
||||
"construct (object, suggested number)" in {
|
||||
val reg = Register(obj, 5)
|
||||
reg.obj mustEqual obj
|
||||
reg.number.contains(5) mustEqual true
|
||||
reg.name.isEmpty mustEqual true
|
||||
reg.callback.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"construct (object, suggested number, callback)" in {
|
||||
val reg = Register(obj, 5, ActorRef.noSender)
|
||||
reg.obj mustEqual obj
|
||||
reg.number.contains(5) mustEqual true
|
||||
reg.name.isEmpty mustEqual true
|
||||
reg.callback.contains(ActorRef.noSender) mustEqual true
|
||||
}
|
||||
|
||||
"construct (object, pool name)" in {
|
||||
val reg = Register(obj, "pool")
|
||||
reg.obj mustEqual obj
|
||||
reg.number.isEmpty mustEqual true
|
||||
reg.name.contains("pool") mustEqual true
|
||||
reg.callback.isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"construct (object, pool name, callback)" in {
|
||||
val reg = Register(obj, "pool", ActorRef.noSender)
|
||||
reg.obj mustEqual obj
|
||||
reg.number.isEmpty mustEqual true
|
||||
reg.name.contains("pool") mustEqual true
|
||||
reg.callback.contains(ActorRef.noSender) mustEqual true
|
||||
}
|
||||
}
|
||||
}
|
||||
386
src/test/scala/objects/number/UniqueNumberSystemTest.scala
Normal file
386
src/test/scala/objects/number/UniqueNumberSystemTest.scala
Normal file
|
|
@ -0,0 +1,386 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.number
|
||||
|
||||
import akka.actor.{ActorRef, ActorSystem, Props}
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.entity.IdentifiableEntity
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
import net.psforever.objects.guid.actor.{NumberPoolActor, Register, UniqueNumberSystem, Unregister}
|
||||
import net.psforever.objects.guid.selector.RandomSelector
|
||||
import net.psforever.objects.guid.source.LimitedNumberSource
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
|
||||
import scala.concurrent.duration._
|
||||
import scala.util.{Failure, Success}
|
||||
|
||||
class AllocateNumberPoolActors extends ActorTest {
|
||||
"AllocateNumberPoolActors" in {
|
||||
val src: LimitedNumberSource = LimitedNumberSource(6000)
|
||||
val guid: NumberPoolHub = new NumberPoolHub(src)
|
||||
guid.AddPool("pool1", (1001 to 2000).toList)
|
||||
guid.AddPool("pool2", (3001 to 4000).toList)
|
||||
guid.AddPool("pool3", (5001 to 6000).toList)
|
||||
val actorMap = UniqueNumberSystemTest.AllocateNumberPoolActors(guid)
|
||||
assert(actorMap.size == 4)
|
||||
assert(actorMap.get("generic").isDefined) //automatically generated
|
||||
assert(actorMap.get("pool1").isDefined)
|
||||
assert(actorMap.get("pool2").isDefined)
|
||||
assert(actorMap.get("pool3").isDefined)
|
||||
}
|
||||
}
|
||||
|
||||
class UniqueNumberSystemTest extends ActorTest() {
|
||||
"UniqueNumberSystem" should {
|
||||
"constructor" in {
|
||||
val src: LimitedNumberSource = LimitedNumberSource(6000)
|
||||
val guid: NumberPoolHub = new NumberPoolHub(src)
|
||||
guid.AddPool("pool1", (1001 to 2000).toList)
|
||||
guid.AddPool("pool2", (3001 to 4000).toList)
|
||||
guid.AddPool("pool3", (5001 to 6000).toList)
|
||||
system.actorOf(
|
||||
Props(classOf[UniqueNumberSystem], guid, UniqueNumberSystemTest.AllocateNumberPoolActors(guid)),
|
||||
"uns"
|
||||
)
|
||||
//as long as it constructs ...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UniqueNumberSystemTest1 extends ActorTest() {
|
||||
class EntityTestClass extends IdentifiableEntity
|
||||
|
||||
"UniqueNumberSystem" should {
|
||||
"Register (success)" in {
|
||||
val src: LimitedNumberSource = LimitedNumberSource(6000)
|
||||
val guid: NumberPoolHub = new NumberPoolHub(src)
|
||||
val pool1 = (1001 to 2000).toList
|
||||
val pool2 = (3001 to 4000).toList
|
||||
val pool3 = (5001 to 6000).toList
|
||||
guid.AddPool("pool1", pool1).Selector = new RandomSelector
|
||||
guid.AddPool("pool2", pool2).Selector = new RandomSelector
|
||||
guid.AddPool("pool3", pool3).Selector = new RandomSelector
|
||||
val uns = system.actorOf(
|
||||
Props(classOf[UniqueNumberSystem], guid, UniqueNumberSystemTest.AllocateNumberPoolActors(guid)),
|
||||
"uns"
|
||||
)
|
||||
assert(src.CountUsed == 0)
|
||||
//pool1
|
||||
for (_ <- 1 to 100) {
|
||||
val testObj = new EntityTestClass()
|
||||
uns ! Register(testObj, "pool1")
|
||||
val msg = receiveOne(Duration.create(500, "ms"))
|
||||
assert(msg.isInstanceOf[Success[_]])
|
||||
assert(pool1.contains(testObj.GUID.guid))
|
||||
}
|
||||
//pool2
|
||||
for (_ <- 1 to 100) {
|
||||
val testObj = new EntityTestClass()
|
||||
uns ! Register(testObj, "pool2")
|
||||
val msg = receiveOne(Duration.create(500, "ms"))
|
||||
assert(msg.isInstanceOf[Success[_]])
|
||||
assert(pool2.contains(testObj.GUID.guid))
|
||||
}
|
||||
//pool3
|
||||
for (_ <- 1 to 100) {
|
||||
val testObj = new EntityTestClass()
|
||||
uns ! Register(testObj, "pool3")
|
||||
val msg = receiveOne(Duration.create(500, "ms"))
|
||||
assert(msg.isInstanceOf[Success[_]])
|
||||
assert(pool3.contains(testObj.GUID.guid))
|
||||
}
|
||||
assert(src.CountUsed == 300)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UniqueNumberSystemTest2 extends ActorTest() {
|
||||
class EntityTestClass extends IdentifiableEntity
|
||||
|
||||
"UniqueNumberSystem" should {
|
||||
"Register (success; already registered)" in {
|
||||
val src: LimitedNumberSource = LimitedNumberSource(6000)
|
||||
val guid: NumberPoolHub = new NumberPoolHub(src)
|
||||
guid.AddPool("pool1", (1001 to 2000).toList).Selector = new RandomSelector
|
||||
guid.AddPool("pool2", (3001 to 4000).toList).Selector = new RandomSelector
|
||||
guid.AddPool("pool3", (5001 to 6000).toList).Selector = new RandomSelector
|
||||
val uns = system.actorOf(
|
||||
Props(classOf[UniqueNumberSystem], guid, UniqueNumberSystemTest.AllocateNumberPoolActors(guid)),
|
||||
"uns"
|
||||
)
|
||||
val testObj = new EntityTestClass()
|
||||
assert(!testObj.HasGUID)
|
||||
assert(src.CountUsed == 0)
|
||||
|
||||
uns ! Register(testObj, "pool1")
|
||||
val msg1 = receiveOne(Duration.create(500, "ms"))
|
||||
assert(msg1.isInstanceOf[Success[_]])
|
||||
assert(testObj.HasGUID)
|
||||
assert(src.CountUsed == 1)
|
||||
|
||||
val id = testObj.GUID.guid
|
||||
uns ! Register(testObj, "pool2") //different pool; makes no difference
|
||||
val msg2 = receiveOne(Duration.create(500, "ms"))
|
||||
assert(msg2.isInstanceOf[Success[_]])
|
||||
assert(testObj.HasGUID)
|
||||
assert(src.CountUsed == 1)
|
||||
assert(testObj.GUID.guid == id) //unchanged
|
||||
}
|
||||
}
|
||||
//a log.warn should have been generated during this test
|
||||
}
|
||||
|
||||
class UniqueNumberSystemTest3 extends ActorTest() {
|
||||
class EntityTestClass extends IdentifiableEntity
|
||||
|
||||
"UniqueNumberSystem" should {
|
||||
"Register (failure; no pool)" in {
|
||||
val src: LimitedNumberSource = LimitedNumberSource(6000)
|
||||
val guid: NumberPoolHub = new NumberPoolHub(src)
|
||||
guid.AddPool("pool1", (1001 to 2000).toList).Selector = new RandomSelector
|
||||
guid.AddPool("pool2", (3001 to 4000).toList).Selector = new RandomSelector
|
||||
guid.AddPool("pool3", (5001 to 6000).toList).Selector = new RandomSelector
|
||||
val uns = system.actorOf(
|
||||
Props(classOf[UniqueNumberSystem], guid, UniqueNumberSystemTest.AllocateNumberPoolActors(guid)),
|
||||
"uns"
|
||||
)
|
||||
val testObj = new EntityTestClass()
|
||||
assert(!testObj.HasGUID)
|
||||
assert(src.CountUsed == 0)
|
||||
|
||||
uns ! Register(testObj, "pool4")
|
||||
val msg1 = receiveOne(Duration.create(500, "ms"))
|
||||
assert(msg1.isInstanceOf[Failure[_]])
|
||||
assert(!testObj.HasGUID)
|
||||
assert(src.CountUsed == 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UniqueNumberSystemTest4 extends ActorTest() {
|
||||
class EntityTestClass extends IdentifiableEntity
|
||||
|
||||
"UniqueNumberSystem" should {
|
||||
"Register (failure; empty pool)" in {
|
||||
val src: LimitedNumberSource = LimitedNumberSource(6000)
|
||||
val guid: NumberPoolHub = new NumberPoolHub(src)
|
||||
guid.AddPool("pool1", (1001 to 2000).toList).Selector = new RandomSelector
|
||||
guid.AddPool("pool2", (3001 to 4000).toList).Selector = new RandomSelector
|
||||
guid.AddPool("pool3", (5001 to 6000).toList).Selector = new RandomSelector
|
||||
guid.AddPool("pool4", 50 :: Nil).Selector = new RandomSelector //list of one element; can not add an empty list
|
||||
val uns = system.actorOf(
|
||||
Props(classOf[UniqueNumberSystem], guid, UniqueNumberSystemTest.AllocateNumberPoolActors(guid)),
|
||||
"uns"
|
||||
)
|
||||
|
||||
val testObj1 = new EntityTestClass()
|
||||
uns ! Register(testObj1, "pool4")
|
||||
val msg1 = receiveOne(Duration.create(500, "ms"))
|
||||
assert(msg1.isInstanceOf[Success[_]]) //pool4 is now empty
|
||||
|
||||
val testObj2 = new EntityTestClass()
|
||||
uns ! Register(testObj2, "pool4")
|
||||
val msg2 = receiveOne(Duration.create(500, "ms"))
|
||||
assert(msg2.isInstanceOf[Failure[_]])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UniqueNumberSystemTest5 extends ActorTest() {
|
||||
class EntityTestClass extends IdentifiableEntity
|
||||
|
||||
"UniqueNumberSystem" should {
|
||||
"Unregister (success)" in {
|
||||
val src: LimitedNumberSource = LimitedNumberSource(6000)
|
||||
val guid: NumberPoolHub = new NumberPoolHub(src)
|
||||
val pool2 = (3001 to 4000).toList
|
||||
guid.AddPool("pool1", (1001 to 2000).toList).Selector = new RandomSelector
|
||||
guid.AddPool("pool2", pool2).Selector = new RandomSelector
|
||||
guid.AddPool("pool3", (5001 to 6000).toList).Selector = new RandomSelector
|
||||
val uns = system.actorOf(
|
||||
Props(classOf[UniqueNumberSystem], guid, UniqueNumberSystemTest.AllocateNumberPoolActors(guid)),
|
||||
"uns"
|
||||
)
|
||||
val testObj = new EntityTestClass()
|
||||
assert(!testObj.HasGUID)
|
||||
assert(src.CountUsed == 0)
|
||||
|
||||
uns ! Register(testObj, "pool2")
|
||||
val msg1 = receiveOne(Duration.create(2000, "ms"))
|
||||
assert(msg1.isInstanceOf[Success[_]])
|
||||
assert(testObj.HasGUID)
|
||||
assert(pool2.contains(testObj.GUID.guid))
|
||||
assert(src.CountUsed == 1)
|
||||
|
||||
uns ! Unregister(testObj)
|
||||
val msg2 = receiveOne(Duration.create(2000, "ms"))
|
||||
assert(msg2.isInstanceOf[Success[_]])
|
||||
assert(!testObj.HasGUID)
|
||||
assert(src.CountUsed == 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UniqueNumberSystemTest6 extends ActorTest() {
|
||||
class EntityTestClass extends IdentifiableEntity
|
||||
|
||||
"UniqueNumberSystem" should {
|
||||
"Unregister (success; object not registered at all)" in {
|
||||
val src: LimitedNumberSource = LimitedNumberSource(6000)
|
||||
val guid: NumberPoolHub = new NumberPoolHub(src)
|
||||
guid.AddPool("pool1", (1001 to 2000).toList).Selector = new RandomSelector
|
||||
guid.AddPool("pool2", (3001 to 4000).toList).Selector = new RandomSelector
|
||||
guid.AddPool("pool3", (5001 to 6000).toList).Selector = new RandomSelector
|
||||
val uns = system.actorOf(
|
||||
Props(classOf[UniqueNumberSystem], guid, UniqueNumberSystemTest.AllocateNumberPoolActors(guid)),
|
||||
"uns"
|
||||
)
|
||||
val testObj = new EntityTestClass()
|
||||
assert(!testObj.HasGUID)
|
||||
assert(src.CountUsed == 0)
|
||||
|
||||
uns ! Unregister(testObj)
|
||||
val msg1 = receiveOne(Duration.create(500, "ms"))
|
||||
assert(msg1.isInstanceOf[Success[_]])
|
||||
assert(!testObj.HasGUID)
|
||||
assert(src.CountUsed == 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UniqueNumberSystemTest7 extends ActorTest() {
|
||||
class EntityTestClass extends IdentifiableEntity
|
||||
|
||||
"UniqueNumberSystem" should {
|
||||
"Unregister (failure; number not in system)" in {
|
||||
val src: LimitedNumberSource = LimitedNumberSource(6000)
|
||||
val guid: NumberPoolHub = new NumberPoolHub(src)
|
||||
guid.AddPool("pool1", (1001 to 2000).toList).Selector = new RandomSelector
|
||||
guid.AddPool("pool2", (3001 to 4000).toList).Selector = new RandomSelector
|
||||
guid.AddPool("pool3", (5001 to 6000).toList).Selector = new RandomSelector
|
||||
val uns = system.actorOf(
|
||||
Props(classOf[UniqueNumberSystem], guid, UniqueNumberSystemTest.AllocateNumberPoolActors(guid)),
|
||||
"uns"
|
||||
)
|
||||
val testObj = new EntityTestClass()
|
||||
testObj.GUID = PlanetSideGUID(6001) //fake registering; number too high
|
||||
assert(testObj.HasGUID)
|
||||
assert(src.CountUsed == 0)
|
||||
|
||||
uns ! Unregister(testObj)
|
||||
val msg1 = receiveOne(Duration.create(500, "ms"))
|
||||
assert(msg1.isInstanceOf[Failure[_]])
|
||||
assert(testObj.HasGUID)
|
||||
assert(src.CountUsed == 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UniqueNumberSystemTest8 extends ActorTest() {
|
||||
class EntityTestClass extends IdentifiableEntity
|
||||
|
||||
"UniqueNumberSystem" should {
|
||||
"Unregister (failure; object is not registered to that number)" in {
|
||||
val src: LimitedNumberSource = LimitedNumberSource(6000)
|
||||
val guid: NumberPoolHub = new NumberPoolHub(src)
|
||||
guid.AddPool("pool1", (1001 to 2000).toList).Selector = new RandomSelector
|
||||
guid.AddPool("pool2", (3001 to 4000).toList).Selector = new RandomSelector
|
||||
guid.AddPool("pool3", (5001 to 6000).toList).Selector = new RandomSelector
|
||||
val uns = system.actorOf(
|
||||
Props(classOf[UniqueNumberSystem], guid, UniqueNumberSystemTest.AllocateNumberPoolActors(guid)),
|
||||
"uns"
|
||||
)
|
||||
val testObj = new EntityTestClass()
|
||||
testObj.GUID = PlanetSideGUID(3500) //fake registering
|
||||
assert(testObj.HasGUID)
|
||||
assert(src.CountUsed == 0)
|
||||
|
||||
uns ! Unregister(testObj)
|
||||
val msg1 = receiveOne(Duration.create(500, "ms"))
|
||||
assert(msg1.isInstanceOf[Failure[_]])
|
||||
assert(testObj.HasGUID)
|
||||
assert(src.CountUsed == 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UniqueNumberSystemTest9 extends ActorTest() {
|
||||
class EntityTestClass extends IdentifiableEntity
|
||||
|
||||
"UniqueNumberSystem" should {
|
||||
"Failures (manually walking the failure cases)" in {
|
||||
val src: LimitedNumberSource = LimitedNumberSource(6000)
|
||||
val guid: NumberPoolHub = new NumberPoolHub(src)
|
||||
guid.AddPool("pool1", (1001 to 2000).toList).Selector = new RandomSelector
|
||||
guid.AddPool("pool2", (3001 to 4000).toList).Selector = new RandomSelector
|
||||
guid.AddPool("pool3", (5001 to 6000).toList).Selector = new RandomSelector
|
||||
val uns = system.actorOf(
|
||||
Props(classOf[UniqueNumberSystem], guid, UniqueNumberSystemTest.AllocateNumberPoolActors(guid)),
|
||||
"uns"
|
||||
)
|
||||
val excp = new Exception("EXCEPTION MESSAGE")
|
||||
expectNoMessage(Duration.create(200, "ms"))
|
||||
|
||||
//GiveNumber
|
||||
uns ! NumberPoolActor.GiveNumber(1001, Some("test")) //no task associated with id="test"
|
||||
uns ! NumberPoolActor.GiveNumber(1000, Some("test")) //no task associated with id="test" and number is not pooled
|
||||
uns ! NumberPoolActor.GiveNumber(1000, Some(1)) //the task could theoretically exist, but does not
|
||||
//NoNumber
|
||||
uns ! NumberPoolActor.NoNumber(excp, Some(1))
|
||||
uns ! NumberPoolActor.NoNumber(excp, None)
|
||||
uns ! NumberPoolActor.NoNumber(excp, Some("test"))
|
||||
//ReturnNumberResult A
|
||||
uns ! NumberPoolActor.ReturnNumberResult(1001, None, Some("test"))
|
||||
uns ! NumberPoolActor.ReturnNumberResult(1000, None, Some("test"))
|
||||
uns ! NumberPoolActor.ReturnNumberResult(1001, None, Some(1))
|
||||
uns ! NumberPoolActor.ReturnNumberResult(1000, None, Some(1))
|
||||
//ReturnNumberResult B
|
||||
uns ! NumberPoolActor.ReturnNumberResult(1001, Some(excp), Some("test"))
|
||||
uns ! NumberPoolActor.ReturnNumberResult(1001, Some(excp), Some(1))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UniqueNumberSystemTestA extends ActorTest {
|
||||
class EntityTestClass extends IdentifiableEntity
|
||||
|
||||
"UniqueNumberSystem" should {
|
||||
"remain consistent between registrations" in {
|
||||
val src: LimitedNumberSource = LimitedNumberSource(10)
|
||||
val guid: NumberPoolHub = new NumberPoolHub(src)
|
||||
guid.AddPool("pool1", (0 until 10).toList).Selector = new RandomSelector
|
||||
val uns = system.actorOf(
|
||||
Props(classOf[UniqueNumberSystem], guid, UniqueNumberSystemTest.AllocateNumberPoolActors(guid)),
|
||||
"uns"
|
||||
)
|
||||
expectNoMessage(Duration.create(200, "ms"))
|
||||
|
||||
assert(src.CountUsed == 0)
|
||||
(0 to 4).foreach(i => { assert(guid.register(new EntityTestClass(), i).isSuccess) })
|
||||
assert(src.CountUsed == 5)
|
||||
|
||||
(0 to 5).foreach(_ => { uns ! Register(new EntityTestClass(), "pool1") })
|
||||
assert(receiveOne(200 milliseconds).isInstanceOf[Success[_]]) //6th
|
||||
assert(receiveOne(200 milliseconds).isInstanceOf[Success[_]]) //7th
|
||||
assert(receiveOne(200 milliseconds).isInstanceOf[Success[_]]) //8th
|
||||
assert(receiveOne(200 milliseconds).isInstanceOf[Success[_]]) //9th
|
||||
assert(receiveOne(200 milliseconds).isInstanceOf[Success[_]]) //10th
|
||||
assert(receiveOne(200 milliseconds).isInstanceOf[Failure[_]]) //no more
|
||||
assert(src.CountUsed == 10)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object UniqueNumberSystemTest {
|
||||
|
||||
/**
|
||||
* @see `UniqueNumberSystem.AllocateNumberPoolActors(NumberPoolHub)(implicit ActorContext)`
|
||||
*/
|
||||
def AllocateNumberPoolActors(poolSource: NumberPoolHub)(implicit system: ActorSystem): Map[String, ActorRef] = {
|
||||
poolSource.Pools
|
||||
.map({
|
||||
case (pname, pool) =>
|
||||
pname -> system.actorOf(Props(classOf[NumberPoolActor], pool), pname)
|
||||
})
|
||||
.toMap
|
||||
}
|
||||
}
|
||||
194
src/test/scala/objects/terminal/ImplantTerminalMechTest.scala
Normal file
194
src/test/scala/objects/terminal/ImplantTerminalMechTest.scala
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.terminal
|
||||
|
||||
import akka.actor.{ActorSystem, Props}
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
import net.psforever.objects.{Default, GlobalDefinitions, Player}
|
||||
import net.psforever.objects.definition.SeatDefinition
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
import net.psforever.objects.guid.source.LimitedNumberSource
|
||||
import net.psforever.objects.serverobject.mount.Mountable
|
||||
import net.psforever.objects.serverobject.implantmech.{ImplantTerminalMech, ImplantTerminalMechControl}
|
||||
import net.psforever.objects.serverobject.structures.{Building, StructureType}
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
import net.psforever.objects.vehicles.Seat
|
||||
import net.psforever.objects.zones.{Zone, ZoneMap}
|
||||
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire, Vector3}
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
import scala.concurrent.duration.Duration
|
||||
|
||||
class ImplantTerminalMechTest extends Specification {
|
||||
"Implant_Terminal_Mech" should {
|
||||
"define" in {
|
||||
val implant_terminal_mech = GlobalDefinitions.implant_terminal_mech
|
||||
implant_terminal_mech.ObjectId mustEqual 410
|
||||
implant_terminal_mech.MountPoints mustEqual Map(1 -> 0)
|
||||
implant_terminal_mech.Seats.keySet mustEqual Set(0)
|
||||
implant_terminal_mech.Seats(0).isInstanceOf[SeatDefinition] mustEqual true
|
||||
implant_terminal_mech
|
||||
.Seats(0)
|
||||
.ArmorRestriction mustEqual net.psforever.objects.vehicles.SeatArmorRestriction.NoMax
|
||||
implant_terminal_mech.Seats(0).Bailable mustEqual false
|
||||
implant_terminal_mech.Seats(0).ControlledWeapon.isEmpty mustEqual true
|
||||
}
|
||||
}
|
||||
|
||||
"Implant_Terminal_Mech" should {
|
||||
"construct" in {
|
||||
val obj = ImplantTerminalMech(GlobalDefinitions.implant_terminal_mech)
|
||||
obj.Actor mustEqual Default.Actor
|
||||
obj.Definition mustEqual GlobalDefinitions.implant_terminal_mech
|
||||
obj.Seats.keySet mustEqual Set(0)
|
||||
obj.Seats(0).isInstanceOf[Seat] mustEqual true
|
||||
}
|
||||
|
||||
"get seat from mount points" in {
|
||||
val obj = ImplantTerminalMech(GlobalDefinitions.implant_terminal_mech)
|
||||
obj.GetSeatFromMountPoint(0).isEmpty mustEqual true
|
||||
obj.GetSeatFromMountPoint(1).contains(0) mustEqual true
|
||||
obj.GetSeatFromMountPoint(2).isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"get passenger in a seat" in {
|
||||
val player = Player(Avatar(0, "test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
val obj = ImplantTerminalMech(GlobalDefinitions.implant_terminal_mech)
|
||||
obj.PassengerInSeat(player).isEmpty mustEqual true
|
||||
obj.Seats(0).Occupant = player
|
||||
obj.PassengerInSeat(player).contains(0) mustEqual true
|
||||
obj.Seats(0).Occupant = None
|
||||
obj.PassengerInSeat(player).isEmpty mustEqual true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ImplantTerminalMechControl1Test extends ActorTest {
|
||||
"ImplantTerminalMechControl" should {
|
||||
"construct" in {
|
||||
val obj = ImplantTerminalMech(GlobalDefinitions.implant_terminal_mech)
|
||||
obj.Actor = system.actorOf(Props(classOf[ImplantTerminalMechControl], obj), "mech")
|
||||
assert(obj.Actor != Default.Actor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ImplantTerminalMechControl2Test extends ActorTest {
|
||||
"ImplantTerminalMechControl" should {
|
||||
"let a player mount" in {
|
||||
val (player, mech) = ImplantTerminalMechTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
val msg = Mountable.TryMount(player, 0)
|
||||
|
||||
mech.Actor ! msg
|
||||
val reply = receiveOne(Duration.create(200, "ms"))
|
||||
assert(reply.isInstanceOf[Mountable.MountMessages])
|
||||
val reply2 = reply.asInstanceOf[Mountable.MountMessages]
|
||||
assert(reply2.player == player)
|
||||
assert(reply2.response.isInstanceOf[Mountable.CanMount])
|
||||
val reply3 = reply2.response.asInstanceOf[Mountable.CanMount]
|
||||
assert(reply3.obj == mech)
|
||||
assert(reply3.seat_num == 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ImplantTerminalMechControl3Test extends ActorTest {
|
||||
import net.psforever.types.CharacterGender
|
||||
"ImplantTerminalMechControl" should {
|
||||
"block a player from mounting" in {
|
||||
val (player1, mech) = ImplantTerminalMechTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
val player2 = Player(Avatar(1, "test2", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
|
||||
mech.Actor ! Mountable.TryMount(player1, 0)
|
||||
receiveOne(Duration.create(100, "ms")) //consume reply
|
||||
|
||||
mech.Actor ! Mountable.TryMount(player2, 0)
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
assert(reply.isInstanceOf[Mountable.MountMessages])
|
||||
val reply2 = reply.asInstanceOf[Mountable.MountMessages]
|
||||
assert(reply2.player == player2)
|
||||
assert(reply2.response.isInstanceOf[Mountable.CanNotMount])
|
||||
val reply3 = reply2.response.asInstanceOf[Mountable.CanNotMount]
|
||||
assert(reply3.obj == mech)
|
||||
assert(reply3.seat_num == 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ImplantTerminalMechControl4Test extends ActorTest {
|
||||
"ImplantTerminalMechControl" should {
|
||||
"dismount player after mounting" in {
|
||||
val (player, mech) = ImplantTerminalMechTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
mech.Actor ! Mountable.TryMount(player, 0)
|
||||
receiveOne(Duration.create(200, "ms")) //consume reply
|
||||
assert(mech.Seat(0).get.isOccupied)
|
||||
|
||||
mech.Actor ! Mountable.TryDismount(player, 0)
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
assert(reply.isInstanceOf[Mountable.MountMessages])
|
||||
val reply2 = reply.asInstanceOf[Mountable.MountMessages]
|
||||
assert(reply2.player == player)
|
||||
assert(reply2.response.isInstanceOf[Mountable.CanDismount])
|
||||
val reply3 = reply2.response.asInstanceOf[Mountable.CanDismount]
|
||||
assert(reply3.obj == mech)
|
||||
assert(reply3.seat_num == 0)
|
||||
assert(!mech.Seat(0).get.isOccupied)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ImplantTerminalMechControl5Test extends ActorTest {
|
||||
"ImplantTerminalMechControl" should {
|
||||
"block a player from dismounting" in {
|
||||
val (player, mech) = ImplantTerminalMechTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
mech.Actor ! Mountable.TryMount(player, 0)
|
||||
receiveOne(Duration.create(100, "ms")) //consume reply
|
||||
assert(mech.Seat(0).get.isOccupied)
|
||||
|
||||
mech.Velocity = Vector3(1, 0, 0) //makes no sense, but it works as the "seat" is not bailable
|
||||
mech.Actor ! Mountable.TryDismount(player, 0)
|
||||
val reply = receiveOne(Duration.create(100, "ms"))
|
||||
assert(reply.isInstanceOf[Mountable.MountMessages])
|
||||
val reply2 = reply.asInstanceOf[Mountable.MountMessages]
|
||||
assert(reply2.player == player)
|
||||
assert(reply2.response.isInstanceOf[Mountable.CanNotDismount])
|
||||
val reply3 = reply2.response.asInstanceOf[Mountable.CanNotDismount]
|
||||
assert(reply3.obj == mech)
|
||||
assert(reply3.seat_num == 0)
|
||||
assert(mech.Seat(0).get.isOccupied)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object ImplantTerminalMechTest {
|
||||
def SetUpAgents(faction: PlanetSideEmpire.Value)(implicit system: ActorSystem): (Player, ImplantTerminalMech) = {
|
||||
val guid = new NumberPoolHub(new LimitedNumberSource(10))
|
||||
val map = new ZoneMap("test")
|
||||
val zone = new Zone("test", map, 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
}
|
||||
val building = new Building(
|
||||
"Building",
|
||||
building_guid = 0,
|
||||
map_id = 0,
|
||||
zone,
|
||||
StructureType.Building,
|
||||
GlobalDefinitions.building
|
||||
) //guid=3
|
||||
building.Faction = faction
|
||||
|
||||
val interface = Terminal(GlobalDefinitions.implant_terminal_interface) //guid=2
|
||||
interface.Owner = building
|
||||
val terminal = ImplantTerminalMech(GlobalDefinitions.implant_terminal_mech) //guid=1
|
||||
terminal.Owner = building
|
||||
|
||||
guid.register(terminal, 1)
|
||||
guid.register(interface, 2)
|
||||
guid.register(building, 3)
|
||||
map.linkTerminalToInterface(1, 2)
|
||||
terminal.Actor = system.actorOf(Props(classOf[ImplantTerminalMechControl], terminal), "terminal-control")
|
||||
|
||||
(Player(Avatar(0, "test", faction, CharacterGender.Male, 0, CharacterVoice.Mute)), terminal)
|
||||
}
|
||||
}
|
||||
32
src/test/scala/objects/terminal/MatrixTerminalTest.scala
Normal file
32
src/test/scala/objects/terminal/MatrixTerminalTest.scala
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.terminal
|
||||
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
import net.psforever.objects.serverobject.terminals.{MatrixTerminalDefinition, Terminal}
|
||||
import net.psforever.objects.{GlobalDefinitions, Player, Vehicle}
|
||||
import net.psforever.packet.game.ItemTransactionMessage
|
||||
import net.psforever.types._
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
class MatrixTerminalTest extends Specification {
|
||||
"MatrixTerminal" should {
|
||||
"define" in {
|
||||
val a = new MatrixTerminalDefinition(517)
|
||||
a.ObjectId mustEqual 517
|
||||
}
|
||||
|
||||
"creation" in {
|
||||
Terminal(new MatrixTerminalDefinition(518))
|
||||
ok
|
||||
}
|
||||
|
||||
"invalid message" in {
|
||||
val player = Player(Avatar(0, "test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 1, "lite_armor", 0, PlanetSideGUID(0))
|
||||
val terminal = Terminal(new MatrixTerminalDefinition(519))
|
||||
terminal.Owner = Vehicle(GlobalDefinitions.quadstealth)
|
||||
terminal.Owner.Faction = PlanetSideEmpire.TR
|
||||
terminal.Request(player, msg) mustEqual Terminal.NoDeal()
|
||||
}
|
||||
}
|
||||
}
|
||||
197
src/test/scala/objects/terminal/OrderTerminalTest.scala
Normal file
197
src/test/scala/objects/terminal/OrderTerminalTest.scala
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.terminal
|
||||
|
||||
import net.psforever.objects.serverobject.structures.{Building, StructureType}
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.avatar.{Avatar, Certification}
|
||||
import net.psforever.packet.game.ItemTransactionMessage
|
||||
import net.psforever.types._
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
class OrderTerminalTest extends Specification {
|
||||
val avatar = Avatar(0, "test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)
|
||||
val player = Player(avatar)
|
||||
|
||||
val building = new Building(
|
||||
"Building",
|
||||
building_guid = 0,
|
||||
map_id = 0,
|
||||
Zone.Nowhere,
|
||||
StructureType.Building,
|
||||
GlobalDefinitions.building
|
||||
)
|
||||
building.Faction = PlanetSideEmpire.TR
|
||||
val infantryTerminal = Terminal(GlobalDefinitions.order_terminal)
|
||||
infantryTerminal.Owner = building
|
||||
|
||||
"General terminal behavior" should {
|
||||
"player can not buy equipment from the wrong page ('9mmbullet_AP', page 10)" in {
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 1, "9mmbullet_AP", 0, PlanetSideGUID(0))
|
||||
|
||||
infantryTerminal.Request(player, msg) mustEqual Terminal.NoDeal()
|
||||
}
|
||||
}
|
||||
|
||||
"Infantry Order Terminal" should {
|
||||
"player can buy a box of ammunition ('9mmbullet_AP')" in {
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "9mmbullet_AP", 0, PlanetSideGUID(0))
|
||||
val reply = infantryTerminal.Request(player, msg)
|
||||
reply.isInstanceOf[Terminal.BuyEquipment] mustEqual true
|
||||
val reply2 = reply.asInstanceOf[Terminal.BuyEquipment]
|
||||
reply2.item.isInstanceOf[AmmoBox] mustEqual true
|
||||
reply2.item.asInstanceOf[AmmoBox].Definition mustEqual GlobalDefinitions.bullet_9mm_AP
|
||||
}
|
||||
|
||||
"player can buy a weapon ('suppressor')" in {
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "suppressor", 0, PlanetSideGUID(0))
|
||||
val reply = infantryTerminal.Request(player, msg)
|
||||
reply.isInstanceOf[Terminal.BuyEquipment] mustEqual true
|
||||
val reply2 = reply.asInstanceOf[Terminal.BuyEquipment]
|
||||
reply2.item.isInstanceOf[Tool] mustEqual true
|
||||
reply2.item.asInstanceOf[Tool].Definition mustEqual GlobalDefinitions.suppressor
|
||||
}
|
||||
|
||||
"player can buy different armor ('lite_armor')" in {
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 1, "lite_armor", 0, PlanetSideGUID(0))
|
||||
|
||||
infantryTerminal.Request(player, msg) mustEqual Terminal.BuyExosuit(ExoSuitType.Agile)
|
||||
}
|
||||
|
||||
"player can buy a box of ammunition belonging to a special armor type ('dualcycler_ammo')" in {
|
||||
val msg =
|
||||
ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 1, "dualcycler_ammo", 0, PlanetSideGUID(0))
|
||||
val reply = infantryTerminal.Request(player, msg)
|
||||
reply.isInstanceOf[Terminal.BuyEquipment] mustEqual true
|
||||
val reply2 = reply.asInstanceOf[Terminal.BuyEquipment]
|
||||
reply2.item.isInstanceOf[AmmoBox] mustEqual true
|
||||
reply2.item.asInstanceOf[AmmoBox].Definition mustEqual GlobalDefinitions.dualcycler_ammo
|
||||
}
|
||||
|
||||
"player can buy a support tool ('bank')" in {
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 2, "bank", 0, PlanetSideGUID(0))
|
||||
val reply = infantryTerminal.Request(player, msg)
|
||||
reply.isInstanceOf[Terminal.BuyEquipment] mustEqual true
|
||||
val reply2 = reply.asInstanceOf[Terminal.BuyEquipment]
|
||||
reply2.item.isInstanceOf[Tool] mustEqual true
|
||||
reply2.item.asInstanceOf[Tool].Definition mustEqual GlobalDefinitions.bank
|
||||
}
|
||||
|
||||
"player can buy a box of vehicle ammunition ('105mmbullet')" in {
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 3, "105mmbullet", 0, PlanetSideGUID(0))
|
||||
val reply = infantryTerminal.Request(player, msg)
|
||||
reply.isInstanceOf[Terminal.BuyEquipment] mustEqual true
|
||||
val reply2 = reply.asInstanceOf[Terminal.BuyEquipment]
|
||||
reply2.item.isInstanceOf[AmmoBox] mustEqual true
|
||||
reply2.item.asInstanceOf[AmmoBox].Definition mustEqual GlobalDefinitions.bullet_105mm
|
||||
}
|
||||
|
||||
"player can not buy fake equipment ('sabot')" in {
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "sabot", 0, PlanetSideGUID(0))
|
||||
infantryTerminal.Request(player, msg) mustEqual Terminal.NoDeal()
|
||||
}
|
||||
|
||||
"player can not retrieve an infantry loadout from the wrong line" in {
|
||||
val msg = infantryTerminal.Request(
|
||||
player,
|
||||
ItemTransactionMessage(PlanetSideGUID(10), TransactionType.Loadout, 4, "", 1, PlanetSideGUID(0))
|
||||
)
|
||||
msg.isInstanceOf[Terminal.NoDeal] mustEqual true
|
||||
}
|
||||
}
|
||||
|
||||
"Vehicle Terminal" should {
|
||||
val terminal = Terminal(GlobalDefinitions.ground_vehicle_terminal)
|
||||
terminal.Owner = building
|
||||
|
||||
"player can spawn a vehicle and its default trunk contents" in {
|
||||
val msg =
|
||||
ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 46769, "quadassault", 0, PlanetSideGUID(0))
|
||||
terminal.Request(player, msg) match {
|
||||
case Terminal.BuyVehicle(vehicle, weapons, trunk) =>
|
||||
vehicle.Definition mustEqual GlobalDefinitions.quadassault
|
||||
|
||||
weapons.size mustEqual 0 //note: vehicles never have custom weapons using the default loadout
|
||||
|
||||
trunk.size mustEqual 4
|
||||
trunk.head.obj.Definition mustEqual GlobalDefinitions.bullet_12mm
|
||||
trunk(1).obj.Definition mustEqual GlobalDefinitions.bullet_12mm
|
||||
trunk(2).obj.Definition mustEqual GlobalDefinitions.bullet_12mm
|
||||
trunk(3).obj.Definition mustEqual GlobalDefinitions.bullet_12mm
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"player can not spawn a fake vehicle ('harasser')" in {
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 46769, "harasser", 0, PlanetSideGUID(0))
|
||||
terminal.Request(player, msg) mustEqual Terminal.NoDeal()
|
||||
}
|
||||
}
|
||||
|
||||
"Certification Terminal" should {
|
||||
val terminal = Terminal(GlobalDefinitions.cert_terminal)
|
||||
terminal.Owner = building
|
||||
|
||||
"player can learn a certification ('medium_assault')" in {
|
||||
val msg =
|
||||
ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Learn, 0, "medium_assault", 0, PlanetSideGUID(0))
|
||||
terminal.Request(player, msg) mustEqual Terminal.LearnCertification(Certification.MediumAssault)
|
||||
}
|
||||
|
||||
"player can not learn a fake certification ('juggling')" in {
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Learn, 0, "juggling", 0, PlanetSideGUID(0))
|
||||
terminal.Request(player, msg) mustEqual Terminal.NoDeal()
|
||||
}
|
||||
|
||||
"player can forget a certification ('medium_assault')" in {
|
||||
val msg =
|
||||
ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Sell, 0, "medium_assault", 0, PlanetSideGUID(0))
|
||||
terminal.Request(player, msg) mustEqual Terminal.SellCertification(Certification.MediumAssault)
|
||||
}
|
||||
|
||||
"player can not forget a fake certification ('juggling')" in {
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Sell, 0, "juggling", 0, PlanetSideGUID(0))
|
||||
terminal.Request(player, msg) mustEqual Terminal.NoDeal()
|
||||
}
|
||||
}
|
||||
|
||||
"Implant_Terminal_Interface" should {
|
||||
val terminal = Terminal(GlobalDefinitions.implant_terminal_interface)
|
||||
terminal.Owner = building
|
||||
|
||||
"player can learn an implant ('darklight_vision')" in {
|
||||
val msg =
|
||||
ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "darklight_vision", 0, PlanetSideGUID(0))
|
||||
|
||||
val reply = terminal.Request(player, msg)
|
||||
reply.isInstanceOf[Terminal.LearnImplant] mustEqual true
|
||||
val reply2 = reply.asInstanceOf[Terminal.LearnImplant]
|
||||
reply2.implant mustEqual GlobalDefinitions.darklight_vision
|
||||
}
|
||||
|
||||
"player can not learn a fake implant ('aimbot')" in {
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "aimbot", 0, PlanetSideGUID(0))
|
||||
|
||||
terminal.Request(player, msg) mustEqual Terminal.NoDeal()
|
||||
}
|
||||
|
||||
"player can un-learn an implant ('darklight_vision')" in {
|
||||
val msg =
|
||||
ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Sell, 0, "darklight_vision", 0, PlanetSideGUID(0))
|
||||
|
||||
val reply = terminal.Request(player, msg)
|
||||
reply.isInstanceOf[Terminal.SellImplant] mustEqual true
|
||||
val reply2 = reply.asInstanceOf[Terminal.SellImplant]
|
||||
reply2.implant mustEqual GlobalDefinitions.darklight_vision
|
||||
}
|
||||
|
||||
"player can not un-learn a fake implant ('aimbot')" in {
|
||||
val terminal = Terminal(GlobalDefinitions.implant_terminal_interface)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Sell, 0, "aimbot", 0, PlanetSideGUID(0))
|
||||
|
||||
terminal.Request(player, msg) mustEqual Terminal.NoDeal()
|
||||
}
|
||||
}
|
||||
}
|
||||
429
src/test/scala/objects/terminal/ProximityTest.scala
Normal file
429
src/test/scala/objects/terminal/ProximityTest.scala
Normal file
|
|
@ -0,0 +1,429 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.terminal
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
import akka.actor.Props
|
||||
import akka.testkit.TestProbe
|
||||
import base.ActorTest
|
||||
import net.psforever.actors.zone.ZoneActor
|
||||
import net.psforever.objects.serverobject.CommonMessages
|
||||
import net.psforever.objects.serverobject.structures.{Building, StructureType}
|
||||
import net.psforever.objects.serverobject.terminals.{
|
||||
ProximityTerminal,
|
||||
ProximityTerminalControl,
|
||||
ProximityUnit,
|
||||
Terminal
|
||||
}
|
||||
import net.psforever.objects.zones.{Zone, ZoneMap}
|
||||
import net.psforever.objects.{GlobalDefinitions, Player}
|
||||
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire, PlanetSideGUID}
|
||||
import org.specs2.mutable.Specification
|
||||
import net.psforever.services.Service
|
||||
import net.psforever.services.local.LocalService
|
||||
|
||||
import scala.concurrent.duration._
|
||||
import akka.actor.typed.scaladsl.adapter._
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
|
||||
class ProximityTest extends Specification {
|
||||
|
||||
"ProximityUnit" should {
|
||||
"construct (with a Terminal object)" in {
|
||||
val obj = new ProximityTest.SampleTerminal()
|
||||
obj.NumberUsers mustEqual 0
|
||||
}
|
||||
|
||||
"keep track of users (add)" in {
|
||||
val avatar1 =
|
||||
Player(
|
||||
Avatar(
|
||||
ProximityTest.avatarId.getAndIncrement(),
|
||||
"TestCharacter1",
|
||||
PlanetSideEmpire.VS,
|
||||
CharacterGender.Female,
|
||||
1,
|
||||
CharacterVoice.Voice1
|
||||
)
|
||||
)
|
||||
avatar1.Spawn()
|
||||
avatar1.Health = 50
|
||||
val avatar2 =
|
||||
Player(
|
||||
Avatar(
|
||||
ProximityTest.avatarId.getAndIncrement(),
|
||||
"TestCharacter2",
|
||||
PlanetSideEmpire.VS,
|
||||
CharacterGender.Female,
|
||||
1,
|
||||
CharacterVoice.Voice1
|
||||
)
|
||||
)
|
||||
avatar2.Spawn()
|
||||
avatar2.Health = 50
|
||||
|
||||
val obj = new ProximityTerminal(GlobalDefinitions.medical_terminal)
|
||||
obj.NumberUsers mustEqual 0
|
||||
obj.AddUser(avatar1) mustEqual true
|
||||
obj.NumberUsers mustEqual 1
|
||||
obj.AddUser(avatar2) mustEqual true
|
||||
obj.NumberUsers mustEqual 2
|
||||
}
|
||||
|
||||
"keep track of users (remove)" in {
|
||||
val avatar1 =
|
||||
Player(
|
||||
Avatar(
|
||||
ProximityTest.avatarId.getAndIncrement(),
|
||||
"TestCharacter1",
|
||||
PlanetSideEmpire.VS,
|
||||
CharacterGender.Female,
|
||||
1,
|
||||
CharacterVoice.Voice1
|
||||
)
|
||||
)
|
||||
avatar1.Spawn()
|
||||
avatar1.Health = 50
|
||||
val avatar2 =
|
||||
Player(
|
||||
Avatar(
|
||||
ProximityTest.avatarId.getAndIncrement(),
|
||||
"TestCharacter2",
|
||||
PlanetSideEmpire.VS,
|
||||
CharacterGender.Female,
|
||||
1,
|
||||
CharacterVoice.Voice1
|
||||
)
|
||||
)
|
||||
avatar2.Spawn()
|
||||
avatar2.Health = 50
|
||||
|
||||
val obj = new ProximityTerminal(GlobalDefinitions.medical_terminal)
|
||||
obj.NumberUsers mustEqual 0
|
||||
obj.AddUser(avatar1) mustEqual true
|
||||
obj.NumberUsers mustEqual 1
|
||||
obj.AddUser(avatar2) mustEqual true
|
||||
obj.NumberUsers mustEqual 2
|
||||
|
||||
obj.RemoveUser(avatar1) mustEqual true
|
||||
obj.NumberUsers mustEqual 1
|
||||
obj.RemoveUser(avatar2) mustEqual true
|
||||
obj.NumberUsers mustEqual 0
|
||||
}
|
||||
|
||||
"can not add a user twice" in {
|
||||
val avatar =
|
||||
Player(
|
||||
Avatar(
|
||||
ProximityTest.avatarId.getAndIncrement(),
|
||||
"TestCharacter1",
|
||||
PlanetSideEmpire.VS,
|
||||
CharacterGender.Female,
|
||||
1,
|
||||
CharacterVoice.Voice1
|
||||
)
|
||||
)
|
||||
avatar.Spawn()
|
||||
avatar.Health = 50
|
||||
|
||||
val obj = new ProximityTerminal(GlobalDefinitions.medical_terminal)
|
||||
obj.AddUser(avatar) mustEqual true
|
||||
obj.NumberUsers mustEqual 1
|
||||
obj.AddUser(avatar) // mustEqual false
|
||||
obj.NumberUsers mustEqual 1
|
||||
}
|
||||
|
||||
"can not remove a user that was not added" in {
|
||||
val avatar =
|
||||
Player(
|
||||
Avatar(
|
||||
ProximityTest.avatarId.getAndIncrement(),
|
||||
"TestCharacter1",
|
||||
PlanetSideEmpire.VS,
|
||||
CharacterGender.Female,
|
||||
1,
|
||||
CharacterVoice.Voice1
|
||||
)
|
||||
)
|
||||
avatar.Spawn()
|
||||
avatar.Health = 50
|
||||
|
||||
val obj = new ProximityTest.SampleTerminal()
|
||||
obj.RemoveUser(avatar) mustEqual false
|
||||
obj.NumberUsers mustEqual 0
|
||||
}
|
||||
}
|
||||
|
||||
"ProximityTerminal" should {
|
||||
"construct" in {
|
||||
ProximityTerminal(GlobalDefinitions.medical_terminal)
|
||||
ok
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ProximityTerminalControlStartTest extends ActorTest {
|
||||
"ProximityTerminalControl" should {
|
||||
//setup
|
||||
val zone: Zone = new Zone("test", new ZoneMap("test-map"), 0) {
|
||||
actor = system.spawn(ZoneActor(this), "test-zone")
|
||||
|
||||
override def SetupNumberPools() = {
|
||||
AddPool("dynamic", 1 to 10)
|
||||
}
|
||||
}
|
||||
val terminal = new ProximityTerminal(GlobalDefinitions.medical_terminal)
|
||||
terminal.Actor = system.actorOf(Props(classOf[ProximityTerminalControl], terminal), "test-prox")
|
||||
new Building("Building", building_guid = 0, map_id = 0, zone, StructureType.Facility, GlobalDefinitions.building) {
|
||||
Amenities = terminal
|
||||
Faction = PlanetSideEmpire.VS
|
||||
}
|
||||
val avatar =
|
||||
Player(
|
||||
Avatar(
|
||||
ProximityTest.avatarId.getAndIncrement(),
|
||||
"TestCharacter1",
|
||||
PlanetSideEmpire.VS,
|
||||
CharacterGender.Female,
|
||||
1,
|
||||
CharacterVoice.Voice1
|
||||
)
|
||||
)
|
||||
avatar.Continent = "test"
|
||||
avatar.Spawn()
|
||||
avatar.Health = 50
|
||||
|
||||
avatar.GUID = PlanetSideGUID(1)
|
||||
terminal.GUID = PlanetSideGUID(2)
|
||||
terminal.Actor ! Service.Startup()
|
||||
expectNoMessage(500 milliseconds) //spacer
|
||||
val probe1 = new TestProbe(system, "local-events")
|
||||
val probe2 = new TestProbe(system, "target-callback")
|
||||
zone.LocalEvents = probe1.ref
|
||||
|
||||
"send out a start message" in {
|
||||
assert(terminal.NumberUsers == 0)
|
||||
assert(terminal.Owner.Continent.equals("test"))
|
||||
|
||||
terminal.Actor.tell(CommonMessages.Use(avatar, Some(avatar)), probe2.ref)
|
||||
probe1.expectMsgClass(1 second, classOf[Terminal.StartProximityEffect])
|
||||
probe2.expectMsgClass(1 second, classOf[ProximityUnit.Action])
|
||||
assert(terminal.NumberUsers == 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ProximityTerminalControlTwoUsersTest extends ActorTest {
|
||||
"ProximityTerminalControl" should {
|
||||
//setup
|
||||
val zone: Zone = new Zone("test", new ZoneMap("test-map"), 0) {
|
||||
actor = system.spawn(ZoneActor(this), "test-zone")
|
||||
override def SetupNumberPools() = {
|
||||
AddPool("dynamic", 1 to 10)
|
||||
}
|
||||
}
|
||||
val terminal = new ProximityTerminal(GlobalDefinitions.medical_terminal)
|
||||
terminal.Actor = system.actorOf(Props(classOf[ProximityTerminalControl], terminal), "test-prox")
|
||||
new Building("Building", building_guid = 0, map_id = 0, zone, StructureType.Facility, GlobalDefinitions.building) {
|
||||
Amenities = terminal
|
||||
Faction = PlanetSideEmpire.VS
|
||||
}
|
||||
|
||||
val avatar =
|
||||
Player(
|
||||
Avatar(
|
||||
ProximityTest.avatarId.getAndIncrement(),
|
||||
"TestCharacter1",
|
||||
PlanetSideEmpire.VS,
|
||||
CharacterGender.Female,
|
||||
1,
|
||||
CharacterVoice.Voice1
|
||||
)
|
||||
)
|
||||
avatar.Continent = "test"
|
||||
avatar.Spawn()
|
||||
avatar.Health = 50
|
||||
val avatar2 =
|
||||
Player(
|
||||
Avatar(
|
||||
ProximityTest.avatarId.getAndIncrement(),
|
||||
"TestCharacter2",
|
||||
PlanetSideEmpire.VS,
|
||||
CharacterGender.Female,
|
||||
1,
|
||||
CharacterVoice.Voice1
|
||||
)
|
||||
)
|
||||
avatar2.Continent = "test"
|
||||
avatar2.Spawn()
|
||||
avatar2.Health = 50
|
||||
|
||||
avatar.GUID = PlanetSideGUID(1)
|
||||
avatar2.GUID = PlanetSideGUID(2)
|
||||
terminal.GUID = PlanetSideGUID(3)
|
||||
terminal.Actor ! Service.Startup()
|
||||
expectNoMessage(500 milliseconds) //spacer
|
||||
val probe1 = new TestProbe(system, "local-events")
|
||||
val probe2 = new TestProbe(system, "target-callback-1")
|
||||
val probe3 = new TestProbe(system, "target-callback-2")
|
||||
zone.LocalEvents = probe1.ref
|
||||
|
||||
"not send out a start message if not the first user" in {
|
||||
assert(terminal.NumberUsers == 0)
|
||||
assert(terminal.Owner.Continent.equals("test"))
|
||||
|
||||
terminal.Actor.tell(CommonMessages.Use(avatar, Some(avatar)), probe2.ref)
|
||||
probe1.expectMsgClass(1 second, classOf[Terminal.StartProximityEffect])
|
||||
probe2.expectMsgClass(1 second, classOf[ProximityUnit.Action])
|
||||
|
||||
terminal.Actor.tell(CommonMessages.Use(avatar2, Some(avatar2)), probe3.ref)
|
||||
probe1.expectNoMessage(1 second)
|
||||
probe2.expectMsgClass(1 second, classOf[ProximityUnit.Action])
|
||||
probe3.expectMsgClass(1 second, classOf[ProximityUnit.Action])
|
||||
assert(terminal.NumberUsers == 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ProximityTerminalControlStopTest extends ActorTest {
|
||||
"ProximityTerminalControl" should {
|
||||
//setup
|
||||
val zone: Zone = new Zone("test", new ZoneMap("test-map"), 0) {
|
||||
actor = system.spawn(ZoneActor(this), "test-zone")
|
||||
|
||||
override def SetupNumberPools() = {
|
||||
AddPool("dynamic", 1 to 10)
|
||||
}
|
||||
}
|
||||
val terminal = new ProximityTerminal(GlobalDefinitions.medical_terminal)
|
||||
terminal.Actor = system.actorOf(Props(classOf[ProximityTerminalControl], terminal), "test-prox")
|
||||
new Building("Building", building_guid = 0, map_id = 0, zone, StructureType.Facility, GlobalDefinitions.building) {
|
||||
Amenities = terminal
|
||||
Faction = PlanetSideEmpire.VS
|
||||
}
|
||||
val avatar =
|
||||
Player(
|
||||
Avatar(
|
||||
ProximityTest.avatarId.getAndIncrement(),
|
||||
"TestCharacter1",
|
||||
PlanetSideEmpire.VS,
|
||||
CharacterGender.Female,
|
||||
1,
|
||||
CharacterVoice.Voice1
|
||||
)
|
||||
)
|
||||
avatar.Continent = "test"
|
||||
avatar.Spawn()
|
||||
avatar.Health = 50
|
||||
|
||||
avatar.GUID = PlanetSideGUID(1)
|
||||
terminal.GUID = PlanetSideGUID(2)
|
||||
terminal.Actor ! Service.Startup()
|
||||
expectNoMessage(500 milliseconds) //spacer
|
||||
val probe1 = new TestProbe(system, "local-events")
|
||||
val probe2 = new TestProbe(system, "target-callback-1")
|
||||
zone.LocalEvents = probe1.ref
|
||||
|
||||
"send out a stop message" in {
|
||||
assert(terminal.NumberUsers == 0)
|
||||
assert(terminal.Owner.Continent.equals("test"))
|
||||
|
||||
terminal.Actor.tell(CommonMessages.Use(avatar, Some(avatar)), probe2.ref)
|
||||
probe1.expectMsgClass(1 second, classOf[Terminal.StartProximityEffect])
|
||||
probe2.expectMsgClass(1 second, classOf[ProximityUnit.Action])
|
||||
|
||||
terminal.Actor ! CommonMessages.Unuse(avatar, Some(avatar))
|
||||
probe1.expectMsgClass(1 second, classOf[Terminal.StopProximityEffect])
|
||||
assert(terminal.NumberUsers == 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ProximityTerminalControlNotStopTest extends ActorTest {
|
||||
"ProximityTerminalControl" should {
|
||||
//setup
|
||||
val zone: Zone = new Zone("test", new ZoneMap("test-map"), 0) {
|
||||
actor = system.spawn(ZoneActor(this), "test-zone")
|
||||
override def SetupNumberPools() = {
|
||||
AddPool("dynamic", 1 to 10)
|
||||
}
|
||||
}
|
||||
val terminal = new ProximityTerminal(GlobalDefinitions.medical_terminal)
|
||||
terminal.Actor = system.actorOf(Props(classOf[ProximityTerminalControl], terminal), "test-prox")
|
||||
new Building("Building", building_guid = 0, map_id = 0, zone, StructureType.Facility, GlobalDefinitions.building) {
|
||||
Amenities = terminal
|
||||
Faction = PlanetSideEmpire.VS
|
||||
}
|
||||
|
||||
val avatar =
|
||||
Player(
|
||||
Avatar(
|
||||
ProximityTest.avatarId.getAndIncrement(),
|
||||
"TestCharacter1",
|
||||
PlanetSideEmpire.VS,
|
||||
CharacterGender.Female,
|
||||
1,
|
||||
CharacterVoice.Voice1
|
||||
)
|
||||
)
|
||||
avatar.Continent = "test"
|
||||
avatar.Spawn()
|
||||
avatar.Health = 50
|
||||
val avatar2 =
|
||||
Player(
|
||||
Avatar(
|
||||
ProximityTest.avatarId.getAndIncrement(),
|
||||
"TestCharacter2",
|
||||
PlanetSideEmpire.VS,
|
||||
CharacterGender.Female,
|
||||
1,
|
||||
CharacterVoice.Voice1
|
||||
)
|
||||
)
|
||||
avatar2.Continent = "test"
|
||||
avatar2.Spawn()
|
||||
avatar2.Health = 50
|
||||
|
||||
avatar.GUID = PlanetSideGUID(1)
|
||||
avatar2.GUID = PlanetSideGUID(2)
|
||||
terminal.GUID = PlanetSideGUID(3)
|
||||
terminal.Actor ! Service.Startup()
|
||||
expectNoMessage(500 milliseconds) //spacer
|
||||
val probe1 = new TestProbe(system, "local-events")
|
||||
val probe2 = new TestProbe(system, "target-callback-1")
|
||||
val probe3 = new TestProbe(system, "target-callback-2")
|
||||
zone.LocalEvents = probe1.ref
|
||||
|
||||
"will not send out one stop message until last user" in {
|
||||
assert(terminal.NumberUsers == 0)
|
||||
assert(terminal.Owner.Continent.equals("test"))
|
||||
|
||||
terminal.Actor.tell(CommonMessages.Use(avatar, Some(avatar)), probe2.ref)
|
||||
probe1.expectMsgClass(100 millisecond, classOf[Terminal.StartProximityEffect])
|
||||
assert(terminal.NumberUsers == 1)
|
||||
|
||||
terminal.Actor.tell(CommonMessages.Use(avatar2, Some(avatar2)), probe3.ref)
|
||||
probe1.expectNoMessage(100 millisecond)
|
||||
assert(terminal.NumberUsers == 2)
|
||||
|
||||
terminal.Actor ! CommonMessages.Unuse(avatar, Some(avatar))
|
||||
probe1.expectNoMessage(100 millisecond)
|
||||
assert(terminal.NumberUsers == 1)
|
||||
|
||||
terminal.Actor ! CommonMessages.Unuse(avatar2, Some(avatar2))
|
||||
probe1.expectMsgClass(100 millisecond, classOf[Terminal.StopProximityEffect])
|
||||
assert(terminal.NumberUsers == 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object ProximityTest {
|
||||
val avatarId = new AtomicInteger(0)
|
||||
|
||||
class SampleTerminal extends Terminal(GlobalDefinitions.dropship_vehicle_terminal) with ProximityUnit
|
||||
|
||||
class ProbedLocalService(probe: TestProbe, zone: Zone) extends LocalService(zone) {
|
||||
self.tell(Service.Join("test"), probe.ref)
|
||||
}
|
||||
|
||||
}
|
||||
148
src/test/scala/objects/terminal/TerminalControlTest.scala
Normal file
148
src/test/scala/objects/terminal/TerminalControlTest.scala
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.terminal
|
||||
|
||||
import akka.actor.{ActorSystem, Props}
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.avatar.{Avatar, Certification}
|
||||
import net.psforever.objects.serverobject.structures.{Building, StructureType}
|
||||
import net.psforever.objects.serverobject.terminals.{Terminal, TerminalControl, TerminalDefinition}
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.objects.{GlobalDefinitions, Player}
|
||||
import net.psforever.packet.game.ItemTransactionMessage
|
||||
import net.psforever.types._
|
||||
|
||||
import scala.concurrent.duration.Duration
|
||||
|
||||
class TerminalControl1Test extends ActorTest {
|
||||
"TerminalControl" should {
|
||||
"construct (cert terminal)" in {
|
||||
val terminal = Terminal(GlobalDefinitions.cert_terminal)
|
||||
terminal.Actor = system.actorOf(Props(classOf[TerminalControl], terminal), "test-cert-term")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TerminalControl2Test extends ActorTest {
|
||||
"TerminalControl can not process wrong messages" in {
|
||||
val (_, terminal) = TerminalControlTest.SetUpAgents(GlobalDefinitions.cert_terminal, PlanetSideEmpire.TR)
|
||||
|
||||
terminal.Actor ! "hello"
|
||||
expectNoMessage(Duration.create(500, "ms"))
|
||||
}
|
||||
}
|
||||
|
||||
//terminal control is mostly a pass-through actor for Terminal.Exchange messages, wrapped in Terminal.TerminalMessage protocol
|
||||
//test for Cert_Terminal messages (see CertTerminalTest)
|
||||
class CertTerminalControl1Test extends ActorTest {
|
||||
"TerminalControl can be used to learn a certification ('medium_assault')" in {
|
||||
val (player, terminal) = TerminalControlTest.SetUpAgents(GlobalDefinitions.cert_terminal, PlanetSideEmpire.TR)
|
||||
val msg =
|
||||
ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Learn, 0, "medium_assault", 0, PlanetSideGUID(0))
|
||||
|
||||
terminal.Actor ! Terminal.Request(player, msg)
|
||||
val reply = receiveOne(Duration.create(500, "ms"))
|
||||
assert(reply.isInstanceOf[Terminal.TerminalMessage])
|
||||
val reply2 = reply.asInstanceOf[Terminal.TerminalMessage]
|
||||
assert(reply2.player == player)
|
||||
assert(reply2.msg == msg)
|
||||
assert(reply2.response == Terminal.LearnCertification(Certification.MediumAssault))
|
||||
}
|
||||
}
|
||||
|
||||
class CertTerminalControl2Test extends ActorTest {
|
||||
"TerminalControl can be used to warn about not learning a fake certification ('juggling')" in {
|
||||
val (player, terminal) = TerminalControlTest.SetUpAgents(GlobalDefinitions.cert_terminal, PlanetSideEmpire.TR)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Learn, 0, "juggling", 0, PlanetSideGUID(0))
|
||||
|
||||
terminal.Actor ! Terminal.Request(player, msg)
|
||||
val reply = receiveOne(Duration.create(500, "ms"))
|
||||
assert(reply.isInstanceOf[Terminal.TerminalMessage])
|
||||
val reply2 = reply.asInstanceOf[Terminal.TerminalMessage]
|
||||
assert(reply2.player == player)
|
||||
assert(reply2.msg == msg)
|
||||
assert(reply2.response == Terminal.NoDeal())
|
||||
}
|
||||
}
|
||||
|
||||
class CertTerminalControl3Test extends ActorTest {
|
||||
"TerminalControl can be used to forget a certification ('medium_assault')" in {
|
||||
val (player, terminal) = TerminalControlTest.SetUpAgents(GlobalDefinitions.cert_terminal, PlanetSideEmpire.TR)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Sell, 0, "medium_assault", 0, PlanetSideGUID(0))
|
||||
|
||||
terminal.Actor ! Terminal.Request(player, msg)
|
||||
val reply = receiveOne(Duration.create(500, "ms"))
|
||||
assert(reply.isInstanceOf[Terminal.TerminalMessage])
|
||||
val reply2 = reply.asInstanceOf[Terminal.TerminalMessage]
|
||||
assert(reply2.player == player)
|
||||
assert(reply2.msg == msg)
|
||||
assert(reply2.response == Terminal.SellCertification(Certification.MediumAssault))
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleTerminalControl1Test extends ActorTest {
|
||||
"TerminalControl can be used to buy a vehicle ('two_man_assault_buggy')" in {
|
||||
val (player, terminal) =
|
||||
TerminalControlTest.SetUpAgents(GlobalDefinitions.ground_vehicle_terminal, PlanetSideEmpire.TR)
|
||||
val msg = ItemTransactionMessage(
|
||||
PlanetSideGUID(1),
|
||||
TransactionType.Buy,
|
||||
46769,
|
||||
"two_man_assault_buggy",
|
||||
0,
|
||||
PlanetSideGUID(0)
|
||||
)
|
||||
|
||||
terminal.Actor ! Terminal.Request(player, msg)
|
||||
val reply = receiveOne(Duration.create(500, "ms"))
|
||||
assert(reply.isInstanceOf[Terminal.TerminalMessage])
|
||||
val reply2 = reply.asInstanceOf[Terminal.TerminalMessage]
|
||||
assert(reply2.player == player)
|
||||
assert(reply2.msg == msg)
|
||||
assert(reply2.response.isInstanceOf[Terminal.BuyVehicle])
|
||||
val reply3 = reply2.response.asInstanceOf[Terminal.BuyVehicle]
|
||||
assert(reply3.vehicle.Definition == GlobalDefinitions.two_man_assault_buggy)
|
||||
assert(reply3.weapons == Nil)
|
||||
assert(reply3.inventory.length == 6) //TODO
|
||||
assert(reply3.inventory.head.obj.Definition == GlobalDefinitions.bullet_12mm)
|
||||
assert(reply3.inventory(1).obj.Definition == GlobalDefinitions.bullet_12mm)
|
||||
assert(reply3.inventory(2).obj.Definition == GlobalDefinitions.bullet_12mm)
|
||||
assert(reply3.inventory(3).obj.Definition == GlobalDefinitions.bullet_12mm)
|
||||
assert(reply3.inventory(4).obj.Definition == GlobalDefinitions.bullet_12mm)
|
||||
assert(reply3.inventory(5).obj.Definition == GlobalDefinitions.bullet_12mm)
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleTerminalControl2Test extends ActorTest {
|
||||
"TerminalControl can be used to warn about not buy a vehicle ('harasser')" in {
|
||||
val (player, terminal) =
|
||||
TerminalControlTest.SetUpAgents(GlobalDefinitions.ground_vehicle_terminal, PlanetSideEmpire.TR)
|
||||
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "harasser", 0, PlanetSideGUID(0))
|
||||
|
||||
terminal.Actor ! Terminal.Request(player, msg)
|
||||
val reply = receiveOne(Duration.create(500, "ms"))
|
||||
assert(reply.isInstanceOf[Terminal.TerminalMessage])
|
||||
val reply2 = reply.asInstanceOf[Terminal.TerminalMessage]
|
||||
assert(reply2.player == player)
|
||||
assert(reply2.msg == msg)
|
||||
assert(reply2.response == Terminal.NoDeal())
|
||||
}
|
||||
}
|
||||
|
||||
object TerminalControlTest {
|
||||
def SetUpAgents(tdef: TerminalDefinition, faction: PlanetSideEmpire.Value)(implicit
|
||||
system: ActorSystem
|
||||
): (Player, Terminal) = {
|
||||
val terminal = Terminal(tdef)
|
||||
terminal.Actor = system.actorOf(Props(classOf[TerminalControl], terminal), "test-term")
|
||||
terminal.Owner = new Building(
|
||||
"Building",
|
||||
building_guid = 0,
|
||||
map_id = 0,
|
||||
Zone.Nowhere,
|
||||
StructureType.Building,
|
||||
GlobalDefinitions.building
|
||||
)
|
||||
terminal.Owner.Faction = faction
|
||||
(Player(Avatar(0, "test", faction, CharacterGender.Male, 0, CharacterVoice.Mute)), terminal)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue