mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-02-25 09:33:33 +00:00
Merge pull request #157 from Fate-JH/player-avatar-2
The Suppressor Update
This commit is contained in:
commit
3e5e8a2573
135 changed files with 13363 additions and 225 deletions
|
|
@ -4,6 +4,7 @@ package game
|
|||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.ImplantType
|
||||
import scodec.bits._
|
||||
|
||||
class AvatarImplantMessageTest extends Specification {
|
||||
|
|
|
|||
33
common/src/test/scala/game/FavoritesRequestTest.scala
Normal file
33
common/src/test/scala/game/FavoritesRequestTest.scala
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class FavoritesRequestTest extends Specification {
|
||||
val stringInfantry = hex"5E 4B00 1187 4500 7800 6100 6D00 7000 6C00 6500"
|
||||
|
||||
"decode (for infantry)" in {
|
||||
PacketCoding.DecodePacket(stringInfantry).require match {
|
||||
case FavoritesRequest(player_guid, unk, action, line, label) =>
|
||||
player_guid mustEqual PlanetSideGUID(75)
|
||||
unk mustEqual 0
|
||||
action mustEqual FavoritesAction.Save
|
||||
line mustEqual 1
|
||||
label.isDefined mustEqual true
|
||||
label.get mustEqual "Example"
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (for infantry)" in {
|
||||
val msg = FavoritesRequest(PlanetSideGUID(75), 0, FavoritesAction.Save, 1, Some("Example"))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual stringInfantry
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -391,16 +391,16 @@ class ObjectCreateDetailedMessageTest extends Specification {
|
|||
false,
|
||||
RibbonBars()
|
||||
)
|
||||
val inv = InventoryItem(ObjectClass.beamer, PlanetSideGUID(76), 0, DetailedWeaponData(4, 8, ObjectClass.energy_cell, PlanetSideGUID(77), 0, DetailedAmmoBoxData(8, 16))) ::
|
||||
InventoryItem(ObjectClass.suppressor, PlanetSideGUID(78), 2, DetailedWeaponData(4, 8, ObjectClass.bullet_9mm, PlanetSideGUID(79), 0, DetailedAmmoBoxData(8, 25))) ::
|
||||
InventoryItem(ObjectClass.forceblade, PlanetSideGUID(80), 4, DetailedWeaponData(4, 8, ObjectClass.melee_ammo, PlanetSideGUID(81), 0, DetailedAmmoBoxData(8, 1))) ::
|
||||
InventoryItem(ObjectClass.locker_container, PlanetSideGUID(82), 5, DetailedAmmoBoxData(8, 1)) ::
|
||||
InventoryItem(ObjectClass.bullet_9mm, PlanetSideGUID(83), 6, DetailedAmmoBoxData(8, 50)) ::
|
||||
InventoryItem(ObjectClass.bullet_9mm, PlanetSideGUID(84), 9, DetailedAmmoBoxData(8, 50)) ::
|
||||
InventoryItem(ObjectClass.bullet_9mm, PlanetSideGUID(85), 12, DetailedAmmoBoxData(8, 50)) ::
|
||||
InventoryItem(ObjectClass.bullet_9mm_AP, PlanetSideGUID(86), 33, DetailedAmmoBoxData(8, 50)) ::
|
||||
InventoryItem(ObjectClass.energy_cell, PlanetSideGUID(87), 36, DetailedAmmoBoxData(8, 50)) ::
|
||||
InventoryItem(ObjectClass.remote_electronics_kit, PlanetSideGUID(88), 39, DetailedREKData(8)) ::
|
||||
val inv = InventoryItemData(ObjectClass.beamer, PlanetSideGUID(76), 0, DetailedWeaponData(4, 8, ObjectClass.energy_cell, PlanetSideGUID(77), 0, DetailedAmmoBoxData(8, 16))) ::
|
||||
InventoryItemData(ObjectClass.suppressor, PlanetSideGUID(78), 2, DetailedWeaponData(4, 8, ObjectClass.bullet_9mm, PlanetSideGUID(79), 0, DetailedAmmoBoxData(8, 25))) ::
|
||||
InventoryItemData(ObjectClass.forceblade, PlanetSideGUID(80), 4, DetailedWeaponData(4, 8, ObjectClass.melee_ammo, PlanetSideGUID(81), 0, DetailedAmmoBoxData(8, 1))) ::
|
||||
InventoryItemData(ObjectClass.locker_container, PlanetSideGUID(82), 5, DetailedAmmoBoxData(8, 1)) ::
|
||||
InventoryItemData(ObjectClass.bullet_9mm, PlanetSideGUID(83), 6, DetailedAmmoBoxData(8, 50)) ::
|
||||
InventoryItemData(ObjectClass.bullet_9mm, PlanetSideGUID(84), 9, DetailedAmmoBoxData(8, 50)) ::
|
||||
InventoryItemData(ObjectClass.bullet_9mm, PlanetSideGUID(85), 12, DetailedAmmoBoxData(8, 50)) ::
|
||||
InventoryItemData(ObjectClass.bullet_9mm_AP, PlanetSideGUID(86), 33, DetailedAmmoBoxData(8, 50)) ::
|
||||
InventoryItemData(ObjectClass.energy_cell, PlanetSideGUID(87), 36, DetailedAmmoBoxData(8, 50)) ::
|
||||
InventoryItemData(ObjectClass.remote_electronics_kit, PlanetSideGUID(88), 39, DetailedREKData(8)) ::
|
||||
Nil
|
||||
val obj = DetailedCharacterData(
|
||||
app,
|
||||
|
|
|
|||
|
|
@ -1076,9 +1076,9 @@ class ObjectCreateMessageTest extends Specification {
|
|||
"encode (locker container)" in {
|
||||
val obj = LockerContainerData(
|
||||
InventoryData(
|
||||
InventoryItem(ObjectClass.nano_dispenser, PlanetSideGUID(2935), 0, WeaponData(0x6, 0x0, ObjectClass.armor_canister, PlanetSideGUID(3426), 0, AmmoBoxData())) ::
|
||||
InventoryItem(ObjectClass.armor_canister, PlanetSideGUID(4090), 45, AmmoBoxData()) ::
|
||||
InventoryItem(ObjectClass.armor_canister, PlanetSideGUID(3326), 78, AmmoBoxData()) ::
|
||||
InventoryItemData(ObjectClass.nano_dispenser, PlanetSideGUID(2935), 0, WeaponData(0x6, 0x0, ObjectClass.armor_canister, PlanetSideGUID(3426), 0, AmmoBoxData())) ::
|
||||
InventoryItemData(ObjectClass.armor_canister, PlanetSideGUID(4090), 45, AmmoBoxData()) ::
|
||||
InventoryItemData(ObjectClass.armor_canister, PlanetSideGUID(3326), 78, AmmoBoxData()) ::
|
||||
Nil
|
||||
)
|
||||
)
|
||||
|
|
@ -1127,11 +1127,11 @@ class ObjectCreateMessageTest extends Specification {
|
|||
Some(ImplantEffects.NoEffects),
|
||||
Some(Cosmetics(true, true, true, true, false)),
|
||||
InventoryData(
|
||||
InventoryItem(ObjectClass.plasma_grenade, PlanetSideGUID(3662), 0, WeaponData(0, 0, ObjectClass.plasma_grenade_ammo, PlanetSideGUID(3751), 0, AmmoBoxData())) ::
|
||||
InventoryItem(ObjectClass.bank, PlanetSideGUID(3908), 1, WeaponData(0, 0, 1, ObjectClass.armor_canister, PlanetSideGUID(4143), 0, AmmoBoxData())) ::
|
||||
InventoryItem(ObjectClass.mini_chaingun, PlanetSideGUID(4164), 2, WeaponData(0, 0, ObjectClass.bullet_9mm, PlanetSideGUID(3728), 0, AmmoBoxData())) ::
|
||||
InventoryItem(ObjectClass.phoenix, PlanetSideGUID(3603), 3, WeaponData(0, 0, ObjectClass.phoenix_missile, PlanetSideGUID(3056), 0, AmmoBoxData())) ::
|
||||
InventoryItem(ObjectClass.chainblade, PlanetSideGUID(4088), 4, WeaponData(0, 0, 1, ObjectClass.melee_ammo, PlanetSideGUID(3279), 0, AmmoBoxData())) ::
|
||||
InventoryItemData(ObjectClass.plasma_grenade, PlanetSideGUID(3662), 0, WeaponData(0, 0, ObjectClass.plasma_grenade_ammo, PlanetSideGUID(3751), 0, AmmoBoxData())) ::
|
||||
InventoryItemData(ObjectClass.bank, PlanetSideGUID(3908), 1, WeaponData(0, 0, 1, ObjectClass.armor_canister, PlanetSideGUID(4143), 0, AmmoBoxData())) ::
|
||||
InventoryItemData(ObjectClass.mini_chaingun, PlanetSideGUID(4164), 2, WeaponData(0, 0, ObjectClass.bullet_9mm, PlanetSideGUID(3728), 0, AmmoBoxData())) ::
|
||||
InventoryItemData(ObjectClass.phoenix, PlanetSideGUID(3603), 3, WeaponData(0, 0, ObjectClass.phoenix_missile, PlanetSideGUID(3056), 0, AmmoBoxData())) ::
|
||||
InventoryItemData(ObjectClass.chainblade, PlanetSideGUID(4088), 4, WeaponData(0, 0, 1, ObjectClass.melee_ammo, PlanetSideGUID(3279), 0, AmmoBoxData())) ::
|
||||
Nil
|
||||
),
|
||||
DrawnSlot.Rifle1
|
||||
|
|
|
|||
200
common/src/test/scala/objects/ConverterTest.scala
Normal file
200
common/src/test/scala/objects/ConverterTest.scala
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects.definition.converter.{ACEConverter, REKConverter}
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.definition._
|
||||
import net.psforever.objects.equipment.CItem.{DeployedItem, Unit}
|
||||
import net.psforever.objects.equipment._
|
||||
import net.psforever.objects.inventory.InventoryTile
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types.{CharacterGender, PlanetSideEmpire, Vector3}
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
import scala.util.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(8, 50)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual AmmoBoxData()
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"Tool" should {
|
||||
"convert to packet" in {
|
||||
val tdef = ToolDefinition(1076)
|
||||
tdef.Size = EquipmentSize.Rifle
|
||||
tdef.AmmoTypes += Ammo.shotgun_shell
|
||||
tdef.AmmoTypes += Ammo.shotgun_shell_AP
|
||||
tdef.FireModes += new FireModeDefinition
|
||||
tdef.FireModes.head.AmmoTypeIndices += 0
|
||||
tdef.FireModes.head.AmmoTypeIndices += 1
|
||||
tdef.FireModes.head.AmmoSlotIndex = 0
|
||||
val obj : Tool = Tool(tdef)
|
||||
val box = AmmoBox(PlanetSideGUID(90), new AmmoBoxDefinition(Ammo.shotgun_shell.id))
|
||||
obj.AmmoSlots.head.Box = box
|
||||
obj.AmmoSlots.head.Magazine = 30
|
||||
|
||||
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual DetailedWeaponData(4,8, Ammo.shotgun_shell.id, PlanetSideGUID(90), 0, DetailedAmmoBoxData(8, 30))
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual WeaponData(4,8, 0, Ammo.shotgun_shell.id, PlanetSideGUID(90), 0, AmmoBoxData())
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"Kit" should {
|
||||
"convert to packet" in {
|
||||
val kdef = KitDefinition(Kits.medkit)
|
||||
val obj = Kit(PlanetSideGUID(90), kdef)
|
||||
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 AmmoBoxData()
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"ConstructionItem" should {
|
||||
"convert to packet" in {
|
||||
val cdef = ConstructionItemDefinition(Unit.advanced_ace)
|
||||
cdef.Modes += DeployedItem.tank_traps
|
||||
cdef.Modes += DeployedItem.portable_manned_turret_tr
|
||||
cdef.Modes += DeployedItem.deployable_shield_generator
|
||||
cdef.Tile = InventoryTile.Tile63
|
||||
cdef.Packet = new ACEConverter()
|
||||
val obj = ConstructionItem(PlanetSideGUID(90), cdef)
|
||||
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual DetailedACEData(0)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual ACEData(0,0)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"SimpleItem" should {
|
||||
"convert to packet" in {
|
||||
val sdef = SimpleItemDefinition(SItem.remote_electronics_kit)
|
||||
sdef.Packet = new REKConverter()
|
||||
val obj = SimpleItem(PlanetSideGUID(90), sdef)
|
||||
obj.Definition.Packet.DetailedConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual DetailedREKData(8)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
obj.Definition.Packet.ConstructorData(obj) match {
|
||||
case Success(pkt) =>
|
||||
pkt mustEqual REKData(8,0)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"Player" should {
|
||||
"convert to packet" in {
|
||||
/*
|
||||
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 bullet_9mm = AmmoBoxDefinition(28)
|
||||
bullet_9mm.Capacity = 50
|
||||
val box1 = AmmoBox(PlanetSideGUID(90), bullet_9mm)
|
||||
val box2 = AmmoBox(PlanetSideGUID(91), bullet_9mm)
|
||||
val tdef = ToolDefinition(1076)
|
||||
tdef.Name = "sample_weapon"
|
||||
tdef.Size = EquipmentSize.Rifle
|
||||
tdef.AmmoTypes += Ammo.bullet_9mm
|
||||
tdef.FireModes += new FireModeDefinition
|
||||
tdef.FireModes.head.AmmoTypeIndices += 0
|
||||
tdef.FireModes.head.AmmoSlotIndex = 0
|
||||
tdef.FireModes.head.Magazine = 18
|
||||
val tool = Tool(PlanetSideGUID(92), tdef)
|
||||
tool.AmmoSlots.head.Box = box1
|
||||
val obj = Player(PlanetSideGUID(93), "Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
obj.Slot(2).Equipment = tool
|
||||
obj.Inventory += 8 -> box2
|
||||
|
||||
obj.Definition.Packet.DetailedConstructorData(obj).isSuccess mustEqual true
|
||||
ok //TODO write more of this test
|
||||
}
|
||||
}
|
||||
|
||||
"Vehicle" should {
|
||||
"convert to packet" 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 += Ammo.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(PlanetSideGUID(432), hellfire_ammo)
|
||||
|
||||
val fury = Vehicle(PlanetSideGUID(413), fury_def)
|
||||
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.AmmoSlots.head.Box = hellfire_ammo_box
|
||||
|
||||
fury.Definition.Packet.ConstructorData(fury).isSuccess mustEqual true
|
||||
ok //TODO write more of this test
|
||||
}
|
||||
}
|
||||
}
|
||||
83
common/src/test/scala/objects/EntityTest.scala
Normal file
83
common/src/test/scala/objects/EntityTest.scala
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects.PlanetSideGameObject
|
||||
import net.psforever.objects.definition.ObjectDefinition
|
||||
import net.psforever.objects.entity.NoGUIDException
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.types.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) { }
|
||||
}
|
||||
|
||||
"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 mustEqual None
|
||||
}
|
||||
|
||||
"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 mustEqual Some(Vector3(3f, 3f, 3f))
|
||||
}
|
||||
|
||||
"clamp Orientation" in {
|
||||
val obj : EntityTestClass = new EntityTestClass
|
||||
obj.Orientation = Vector3(-1f, 361f, -0f)
|
||||
obj.Orientation mustEqual Vector3(359f, 1f, 0f)
|
||||
}
|
||||
}
|
||||
|
||||
"IdentifiableEntity" should {
|
||||
"construct" in {
|
||||
new EntityTestClass()
|
||||
ok
|
||||
}
|
||||
|
||||
"error while unset" in {
|
||||
val obj : EntityTestClass = new EntityTestClass
|
||||
obj.GUID must throwA[NoGUIDException]
|
||||
}
|
||||
|
||||
"work after mutation" in {
|
||||
val obj : EntityTestClass = new EntityTestClass
|
||||
obj.GUID = PlanetSideGUID(1051)
|
||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||
}
|
||||
|
||||
"work after multiple mutations" in {
|
||||
val obj : EntityTestClass = new EntityTestClass
|
||||
obj.GUID = PlanetSideGUID(1051)
|
||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||
obj.GUID = PlanetSideGUID(30052)
|
||||
obj.GUID mustEqual PlanetSideGUID(30052)
|
||||
obj.GUID = PlanetSideGUID(62)
|
||||
obj.GUID mustEqual PlanetSideGUID(62)
|
||||
}
|
||||
|
||||
"invalidate and resume error" in {
|
||||
val obj : EntityTestClass = new EntityTestClass
|
||||
obj.GUID = PlanetSideGUID(1051)
|
||||
obj.GUID mustEqual PlanetSideGUID(1051)
|
||||
obj.Invalidate()
|
||||
obj.GUID must throwA[NoGUIDException]
|
||||
}
|
||||
}
|
||||
}
|
||||
258
common/src/test/scala/objects/EquipmentTest.scala
Normal file
258
common/src/test/scala/objects/EquipmentTest.scala
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.definition._
|
||||
import net.psforever.objects.equipment.CItem.{DeployedItem, Unit}
|
||||
import net.psforever.objects.equipment._
|
||||
import net.psforever.objects.inventory.InventoryTile
|
||||
import net.psforever.objects.GlobalDefinitions._
|
||||
import org.specs2.mutable._
|
||||
|
||||
class EquipmentTest extends Specification {
|
||||
|
||||
"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
|
||||
}
|
||||
}
|
||||
|
||||
"Tool" should {
|
||||
"define" in {
|
||||
val obj = ToolDefinition(1076)
|
||||
obj.Name = "sample_weapon"
|
||||
obj.Size = EquipmentSize.Rifle
|
||||
obj.AmmoTypes += Ammo.shotgun_shell
|
||||
obj.AmmoTypes += Ammo.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.head.ResetAmmoIndexOnSwap = true
|
||||
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 Ammo.shotgun_shell
|
||||
obj.AmmoTypes(1) mustEqual Ammo.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.head.ResetAmmoIndexOnSwap mustEqual true
|
||||
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.FireModes(1).ResetAmmoIndexOnSwap mustEqual false
|
||||
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
|
||||
}
|
||||
|
||||
"multiple fire modes" in {
|
||||
//explanation: sample_weapon has two fire modes; adjusting the FireMode changes between them
|
||||
val tdef = ToolDefinition(1076)
|
||||
tdef.Size = EquipmentSize.Rifle
|
||||
tdef.AmmoTypes += Ammo.shotgun_shell
|
||||
tdef.AmmoTypes += Ammo.shotgun_shell_AP
|
||||
tdef.FireModes += new FireModeDefinition
|
||||
tdef.FireModes.head.AmmoTypeIndices += 0
|
||||
tdef.FireModes.head.AmmoSlotIndex = 0
|
||||
tdef.FireModes.head.Magazine = 9
|
||||
tdef.FireModes += new FireModeDefinition
|
||||
tdef.FireModes(1).AmmoTypeIndices += 1
|
||||
tdef.FireModes(1).AmmoSlotIndex = 1
|
||||
tdef.FireModes(1).Magazine = 18
|
||||
val obj : Tool = Tool(tdef)
|
||||
//fmode = 0
|
||||
obj.FireModeIndex mustEqual 0
|
||||
obj.FireMode.Magazine mustEqual 9
|
||||
obj.AmmoType mustEqual Ammo.shotgun_shell
|
||||
//fmode -> 1
|
||||
obj.NextFireMode
|
||||
obj.FireModeIndex mustEqual 1
|
||||
obj.FireMode.Magazine mustEqual 18
|
||||
obj.AmmoType mustEqual Ammo.shotgun_shell_AP
|
||||
//fmode -> 0
|
||||
obj.NextFireMode
|
||||
obj.FireModeIndex mustEqual 0
|
||||
obj.FireMode.Magazine mustEqual 9
|
||||
obj.AmmoType mustEqual Ammo.shotgun_shell
|
||||
}
|
||||
|
||||
"multiple types of ammunition" in {
|
||||
//explanation: obj has one fire mode and two ammunitions; adjusting the AmmoType changes between them
|
||||
val tdef = ToolDefinition(1076)
|
||||
tdef.Size = EquipmentSize.Rifle
|
||||
tdef.AmmoTypes += Ammo.shotgun_shell
|
||||
tdef.AmmoTypes += Ammo.shotgun_shell_AP
|
||||
tdef.FireModes += new FireModeDefinition
|
||||
tdef.FireModes.head.AmmoTypeIndices += 0
|
||||
tdef.FireModes.head.AmmoTypeIndices += 1
|
||||
tdef.FireModes.head.AmmoSlotIndex = 0
|
||||
val obj : Tool = Tool(tdef)
|
||||
//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
|
||||
}
|
||||
}
|
||||
|
||||
"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 {
|
||||
val advanced_ace_tr = ConstructionItemDefinition(39)
|
||||
advanced_ace_tr.Modes += DeployedItem.tank_traps
|
||||
advanced_ace_tr.Modes += DeployedItem.portable_manned_turret_tr
|
||||
advanced_ace_tr.Modes += DeployedItem.deployable_shield_generator
|
||||
advanced_ace_tr.Tile = InventoryTile.Tile63
|
||||
|
||||
"define" in {
|
||||
val sample = ConstructionItemDefinition(Unit.advanced_ace)
|
||||
sample.Modes += DeployedItem.tank_traps
|
||||
sample.Modes += DeployedItem.portable_manned_turret_tr
|
||||
sample.Modes += DeployedItem.deployable_shield_generator
|
||||
sample.Tile = InventoryTile.Tile63
|
||||
sample.Modes.head mustEqual DeployedItem.tank_traps
|
||||
sample.Modes(1) mustEqual DeployedItem.portable_manned_turret_tr
|
||||
sample.Modes(2) mustEqual DeployedItem.deployable_shield_generator
|
||||
sample.Tile.width mustEqual InventoryTile.Tile63.width
|
||||
sample.Tile.height mustEqual InventoryTile.Tile63.height
|
||||
}
|
||||
|
||||
"construct" in {
|
||||
val obj : ConstructionItem = ConstructionItem(advanced_ace_tr)
|
||||
obj.Definition.ObjectId mustEqual advanced_ace_tr.ObjectId
|
||||
}
|
||||
|
||||
"fire mode" in {
|
||||
//explanation: router_telepad has one fire mode and that fire mode is our only option
|
||||
val router_telepad : ConstructionItemDefinition = ConstructionItemDefinition(Unit.router_telepad)
|
||||
router_telepad.Modes += DeployedItem.router_telepad_deployable
|
||||
val obj : ConstructionItem = ConstructionItem(router_telepad)
|
||||
//fmode = 0
|
||||
obj.FireModeIndex mustEqual 0
|
||||
obj.FireMode mustEqual DeployedItem.router_telepad_deployable
|
||||
//fmode -> 1 (0)
|
||||
obj.FireModeIndex = 1
|
||||
obj.FireModeIndex mustEqual 0
|
||||
obj.FireMode mustEqual DeployedItem.router_telepad_deployable
|
||||
}
|
||||
|
||||
"multiple fire modes" in {
|
||||
//explanation: advanced_ace_tr has three fire modes; adjusting the FireMode changes between them
|
||||
val obj : ConstructionItem = ConstructionItem(advanced_ace_tr)
|
||||
//fmode = 0
|
||||
obj.FireModeIndex mustEqual 0
|
||||
obj.FireMode mustEqual DeployedItem.tank_traps
|
||||
//fmode -> 1
|
||||
obj.NextFireMode
|
||||
obj.FireModeIndex mustEqual 1
|
||||
obj.FireMode mustEqual DeployedItem.portable_manned_turret_tr
|
||||
//fmode -> 2
|
||||
obj.NextFireMode
|
||||
obj.FireModeIndex mustEqual 2
|
||||
obj.FireMode mustEqual DeployedItem.deployable_shield_generator
|
||||
//fmode -> 0
|
||||
obj.NextFireMode
|
||||
obj.FireModeIndex mustEqual 0
|
||||
obj.FireMode mustEqual DeployedItem.tank_traps
|
||||
}
|
||||
}
|
||||
|
||||
"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
|
||||
}
|
||||
}
|
||||
}
|
||||
76
common/src/test/scala/objects/ImplantTest.scala
Normal file
76
common/src/test/scala/objects/ImplantTest.scala
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects.Implant
|
||||
import net.psforever.objects.definition.{ImplantDefinition, Stance}
|
||||
import net.psforever.types.{ExoSuitType, ImplantType}
|
||||
import org.specs2.mutable._
|
||||
|
||||
class ImplantTest extends Specification {
|
||||
val sample = new ImplantDefinition(8) //variant of sensor shield/silent run
|
||||
sample.Initialization = 90000 //1:30
|
||||
sample.ActivationCharge = 3
|
||||
sample.DurationChargeBase = 1
|
||||
sample.DurationChargeByExoSuit += ExoSuitType.Agile -> 2
|
||||
sample.DurationChargeByExoSuit += ExoSuitType.Reinforced -> 2
|
||||
sample.DurationChargeByExoSuit += ExoSuitType.Standard -> 1
|
||||
sample.DurationChargeByStance += Stance.Running -> 1
|
||||
|
||||
"define" in {
|
||||
sample.Initialization mustEqual 90000
|
||||
sample.ActivationCharge mustEqual 3
|
||||
sample.DurationChargeBase mustEqual 1
|
||||
sample.DurationChargeByExoSuit(ExoSuitType.Agile) mustEqual 2
|
||||
sample.DurationChargeByExoSuit(ExoSuitType.Reinforced) mustEqual 2
|
||||
sample.DurationChargeByExoSuit(ExoSuitType.Standard) mustEqual 1
|
||||
sample.DurationChargeByExoSuit(ExoSuitType.Infiltration) mustEqual 0 //default value
|
||||
sample.DurationChargeByStance(Stance.Running) mustEqual 1
|
||||
sample.DurationChargeByStance(Stance.Crouching) mustEqual 0 //default value
|
||||
sample.Type mustEqual ImplantType.SilentRun
|
||||
}
|
||||
|
||||
"construct" in {
|
||||
val obj = new Implant(sample)
|
||||
obj.Definition.Type mustEqual sample.Type
|
||||
obj.Active mustEqual false
|
||||
obj.Ready mustEqual false
|
||||
obj.Timer mustEqual 0
|
||||
}
|
||||
|
||||
"reset/init their timer" in {
|
||||
val obj = new Implant(sample)
|
||||
obj.Timer mustEqual 0
|
||||
obj.Reset()
|
||||
obj.Timer mustEqual 90000
|
||||
}
|
||||
|
||||
"reset/init their readiness condition" in {
|
||||
val obj = new Implant(sample)
|
||||
obj.Ready mustEqual false
|
||||
obj.Timer = 0
|
||||
obj.Ready mustEqual true
|
||||
obj.Reset()
|
||||
obj.Ready mustEqual false
|
||||
}
|
||||
|
||||
"not activate until they are ready" in {
|
||||
val obj = new Implant(sample)
|
||||
obj.Active = true
|
||||
obj.Active mustEqual false
|
||||
obj.Timer = 0
|
||||
obj.Active = true
|
||||
obj.Active mustEqual true
|
||||
}
|
||||
|
||||
"not cost energy while not active" in {
|
||||
val obj = new Implant(sample)
|
||||
obj.Charge(ExoSuitType.Reinforced, Stance.Running) mustEqual 0
|
||||
}
|
||||
|
||||
"cost energy while active" in {
|
||||
val obj = new Implant(sample)
|
||||
obj.Timer = 0
|
||||
obj.Active = true
|
||||
obj.Charge(ExoSuitType.Reinforced, Stance.Running) mustEqual 4
|
||||
}
|
||||
}
|
||||
349
common/src/test/scala/objects/InventoryTest.scala
Normal file
349
common/src/test/scala/objects/InventoryTest.scala
Normal file
|
|
@ -0,0 +1,349 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects.{AmmoBox, SimpleItem}
|
||||
import net.psforever.objects.definition.SimpleItemDefinition
|
||||
import net.psforever.objects.inventory.{GridInventory, InventoryItem, InventoryTile}
|
||||
import net.psforever.objects.GlobalDefinitions._
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import org.specs2.mutable._
|
||||
|
||||
import scala.collection.mutable.ListBuffer
|
||||
import scala.util.Success
|
||||
|
||||
class InventoryTest extends Specification {
|
||||
val bullet9mmBox1 = AmmoBox(PlanetSideGUID(1), bullet_9mm)
|
||||
val bullet9mmBox2 = AmmoBox(PlanetSideGUID(2), bullet_9mm)
|
||||
|
||||
"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
|
||||
}
|
||||
|
||||
"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)) mustEqual Some(bullet9mmBox1)
|
||||
obj.Clear()
|
||||
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).isFailure mustEqual true
|
||||
//left
|
||||
obj.CheckCollisionsAsList(1, 3, 3).isFailure mustEqual true
|
||||
//bottom
|
||||
obj.CheckCollisionsAsList(3, 3, 3).isFailure mustEqual true
|
||||
}
|
||||
|
||||
"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)
|
||||
list0 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list1 = obj.CheckCollisionsAsList(1, w, h)
|
||||
list1 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list2 = obj.CheckCollisionsAsList(2, w, h)
|
||||
list2 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list3 = obj.CheckCollisionsAsList(3, w, h)
|
||||
list3 match {
|
||||
case scala.util.Success(list) => list.isEmpty mustEqual true
|
||||
case scala.util.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 scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list1 = obj.CheckCollisionsAsList(2, w, h)
|
||||
list1 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list2 = obj.CheckCollisionsAsList(1, w, h)
|
||||
list2 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list3 = obj.CheckCollisionsAsList(0, w, h)
|
||||
list3 match {
|
||||
case scala.util.Success(list) => list.isEmpty mustEqual true
|
||||
case scala.util.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 scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list1 = obj.CheckCollisionsAsList(9, w, h)
|
||||
list1 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list2 = obj.CheckCollisionsAsList(18, w, h)
|
||||
list2 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list3 = obj.CheckCollisionsAsList(27, w, h)
|
||||
list3 match {
|
||||
case scala.util.Success(list) => list.isEmpty mustEqual true
|
||||
case scala.util.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 scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list1 = obj.CheckCollisionsAsList(18, w, h)
|
||||
list1 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list2 = obj.CheckCollisionsAsList(9, w, h)
|
||||
list2 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list3 = obj.CheckCollisionsAsList(0, w, h)
|
||||
list3 match {
|
||||
case scala.util.Success(list) => list.isEmpty mustEqual true
|
||||
case scala.util.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 scala.util.Success(list) => list.isEmpty mustEqual true
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list1 = obj.CheckCollisionsAsList(13, w, h)
|
||||
list1 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list2 = obj.CheckCollisionsAsList(6, w, h)
|
||||
list2 match {
|
||||
case scala.util.Success(list) =>list.isEmpty mustEqual true
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list3 = obj.CheckCollisionsAsList(17, w, h)
|
||||
list3 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list4 = obj.CheckCollisionsAsList(72, w, h)
|
||||
list4 match {
|
||||
case scala.util.Success(list) => list.isEmpty mustEqual true
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list5 = obj.CheckCollisionsAsList(61, w, h)
|
||||
list5 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list6 = obj.CheckCollisionsAsList(78, w, h)
|
||||
list6 match {
|
||||
case scala.util.Success(list) => list.isEmpty mustEqual true
|
||||
case scala.util.Failure(_) => ko
|
||||
}
|
||||
val list7 = obj.CheckCollisionsAsList(65, w, h)
|
||||
list7 match {
|
||||
case scala.util.Success(list) => list.length mustEqual 1
|
||||
case scala.util.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
|
||||
}
|
||||
|
||||
"block insertion if item collision" in {
|
||||
val obj : GridInventory = GridInventory(9, 6)
|
||||
obj += 0 -> bullet9mmBox1
|
||||
obj.Capacity mustEqual 45
|
||||
obj.hasItem(PlanetSideGUID(1)) mustEqual Some(bullet9mmBox1)
|
||||
obj += 2 -> bullet9mmBox2
|
||||
obj.hasItem(PlanetSideGUID(2)) mustEqual None
|
||||
obj.Clear()
|
||||
ok
|
||||
}
|
||||
|
||||
"remove item" in {
|
||||
val obj : GridInventory = GridInventory(9, 6)
|
||||
obj += 0 -> bullet9mmBox1
|
||||
obj.hasItem(PlanetSideGUID(1)) mustEqual Some(bullet9mmBox1)
|
||||
obj -= PlanetSideGUID(1)
|
||||
obj.hasItem(PlanetSideGUID(1)) mustEqual None
|
||||
obj.Clear()
|
||||
ok
|
||||
}
|
||||
|
||||
"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)) mustEqual Some(bullet9mmBox1)
|
||||
obj.CheckCollisions(23, bullet9mmBox1) mustEqual Success(1 :: Nil)
|
||||
obj -= PlanetSideGUID(1)
|
||||
obj.hasItem(PlanetSideGUID(1)) mustEqual None
|
||||
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(PlanetSideGUID(0), sampleDef22)
|
||||
obj += 20 -> SimpleItem(PlanetSideGUID(1), sampleDef63)
|
||||
obj += 56 -> SimpleItem(PlanetSideGUID(2), 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(PlanetSideGUID(0), sampleDef2), -1)
|
||||
list += new InventoryItem(SimpleItem(PlanetSideGUID(1), sampleDef3), -1)
|
||||
list += new InventoryItem(SimpleItem(PlanetSideGUID(2), sampleDef1), -1)
|
||||
list += new InventoryItem(SimpleItem(PlanetSideGUID(3), sampleDef4), -1)
|
||||
list += new InventoryItem(SimpleItem(PlanetSideGUID(4), sampleDef1), -1)
|
||||
list += new InventoryItem(SimpleItem(PlanetSideGUID(5), sampleDef4), -1)
|
||||
list += new InventoryItem(SimpleItem(PlanetSideGUID(6), sampleDef2), -1)
|
||||
list += new InventoryItem(SimpleItem(PlanetSideGUID(7), 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
|
||||
}
|
||||
}
|
||||
}
|
||||
83
common/src/test/scala/objects/NumberPoolActorTest.scala
Normal file
83
common/src/test/scala/objects/NumberPoolActorTest.scala
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.{ActorSystem, Props}
|
||||
import akka.testkit.{ImplicitSender, TestKit, TestProbe}
|
||||
import net.psforever.objects.entity.IdentifiableEntity
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||
import net.psforever.objects.guid.actor.{NumberPoolAccessorActor, NumberPoolActor, Register}
|
||||
import net.psforever.objects.guid.pool.ExclusivePool
|
||||
import net.psforever.objects.guid.selector.RandomSelector
|
||||
import net.psforever.objects.guid.source.LimitedNumberSource
|
||||
import org.specs2.specification.Scope
|
||||
|
||||
import scala.concurrent.duration.Duration
|
||||
import scala.util.Success
|
||||
|
||||
abstract class ActorTest(sys : ActorSystem) extends TestKit(sys) with Scope with ImplicitSender with WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
override def afterAll {
|
||||
TestKit.shutdownActorSystem(system)
|
||||
}
|
||||
}
|
||||
|
||||
class NumberPoolActorTest extends ActorTest(ActorSystem("test")) {
|
||||
"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(100, "ms"))
|
||||
assert(msg.isInstanceOf[NumberPoolActor.GiveNumber])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class NumberPoolActorTest1 extends ActorTest(ActorSystem("test")) {
|
||||
"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(ActorSystem("test")) {
|
||||
"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(100, "ms"))
|
||||
assert(msg.isInstanceOf[NumberPoolActor.NoNumber])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class NumberPoolActorTest3 extends ActorTest(ActorSystem("test")) {
|
||||
"NumberPoolAccessorActor" should {
|
||||
class TestEntity extends IdentifiableEntity
|
||||
|
||||
"register" in {
|
||||
val hub = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
val pool = hub.AddPool("test", (25 to 50).toList)
|
||||
pool.Selector = new RandomSelector
|
||||
val poolActor = system.actorOf(Props(classOf[NumberPoolActor], pool), name = "poolActor")
|
||||
val poolAccessor = system.actorOf(Props(classOf[NumberPoolAccessorActor], hub, pool, poolActor), name = "accessor")
|
||||
|
||||
val obj : TestEntity = new TestEntity
|
||||
val probe = new TestProbe(system)
|
||||
poolAccessor ! Register(obj, probe.ref)
|
||||
probe.expectMsg(Success(obj))
|
||||
assert({obj.GUID; true}) //NoGUIDException if failure
|
||||
}
|
||||
}
|
||||
}
|
||||
285
common/src/test/scala/objects/NumberPoolHubTest.scala
Normal file
285
common/src/test/scala/objects/NumberPoolHubTest.scala
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
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.packet.game.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") mustEqual None
|
||||
}
|
||||
|
||||
"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 mustEqual Some(obj)
|
||||
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) mustEqual Some("fibonacci2")
|
||||
}
|
||||
|
||||
"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) mustEqual Some("fibonacci")
|
||||
}
|
||||
|
||||
"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) mustEqual Some("generic")
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"register an object to a specific, pooled number" in {
|
||||
val hub = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
hub.AddPool("fibonacci", numberList)
|
||||
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) mustEqual Some("fibonacci")
|
||||
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) mustEqual Some("generic")
|
||||
}
|
||||
|
||||
"unregister an object" in {
|
||||
val hub = new NumberPoolHub(new LimitedNumberSource(51))
|
||||
hub.AddPool("fibonacci", numberList)
|
||||
val obj = new EntityTestClass()
|
||||
hub.register(obj, "fibonacci")
|
||||
hub.WhichPool(obj) mustEqual Some("fibonacci")
|
||||
try { obj.GUID } catch { case _ : Exception => ko } //passes
|
||||
|
||||
hub.unregister(obj)
|
||||
hub.WhichPool(obj) mustEqual None
|
||||
obj.GUID must throwA[Exception] //fails
|
||||
}
|
||||
|
||||
"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
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
hub.WhichPool(obj) mustEqual Some("fibonacci")
|
||||
hub.unregister(13) match {
|
||||
case Success(thing) =>
|
||||
thing mustEqual Some(obj)
|
||||
thing.get.GUID must throwA[Exception]
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
194
common/src/test/scala/objects/NumberPoolTest.scala
Normal file
194
common/src/test/scala/objects/NumberPoolTest.scala
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
"get a number" in {
|
||||
val obj = new SimplePool((0 to 10).toList)
|
||||
obj.Get() match {
|
||||
case Success(number) =>
|
||||
(-1 < number && number < 11) mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"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 obj = new ExclusivePool((0 to 10).toList)
|
||||
obj.Get() match {
|
||||
case Success(number) =>
|
||||
(-1 < number && number < 11) mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"get all the numbers" in {
|
||||
val range = 0 to 10
|
||||
val obj = new ExclusivePool((0 to 10).toList)
|
||||
range.foreach(_ => {
|
||||
obj.Get() match {
|
||||
case Success(number) =>
|
||||
(-1 < number && number < 11) 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) mustEqual Some("generic")
|
||||
obj.Numbers.contains(5) mustEqual true
|
||||
obj.Return(5) mustEqual true
|
||||
map.get(5) mustEqual None
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
326
common/src/test/scala/objects/NumberSelectorTest.scala
Normal file
326
common/src/test/scala/objects/NumberSelectorTest.scala
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects.guid.selector.{RandomSequenceSelector, _}
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
class NumberSelectorTest extends Specification {
|
||||
def randArrayGen(n : Int = 26) : Array[Int] = {
|
||||
val obj = Array.ofDim[Int](n)
|
||||
(0 to 25).foreach(x => { obj(x) = x } )
|
||||
obj
|
||||
}
|
||||
|
||||
"RandomSequenceSelector" should {
|
||||
"construct" in {
|
||||
new RandomSequenceSelector
|
||||
ok
|
||||
}
|
||||
|
||||
"get a number" in {
|
||||
val obj = new RandomSequenceSelector
|
||||
obj.Get(randArrayGen()) mustNotEqual -1
|
||||
}
|
||||
|
||||
"return a number" in {
|
||||
val obj = new RandomSequenceSelector
|
||||
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 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
359
common/src/test/scala/objects/NumberSourceTest.scala
Normal file
359
common/src/test/scala/objects/NumberSourceTest.scala
Normal file
|
|
@ -0,0 +1,359 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects.guid.key.{LoanedKey, SecureKey}
|
||||
import net.psforever.objects.guid.AvailabilityPolicy
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
class NumberSourceTest extends Specification {
|
||||
import net.psforever.objects.entity.IdentifiableEntity
|
||||
private class TestClass extends IdentifiableEntity
|
||||
|
||||
"MaxNumberSource" should {
|
||||
import net.psforever.objects.guid.source.MaxNumberSource
|
||||
"construct" in {
|
||||
val obj = MaxNumberSource()
|
||||
obj.Size mustEqual Int.MaxValue
|
||||
obj.CountAvailable mustEqual Int.MaxValue
|
||||
obj.CountUsed mustEqual 0
|
||||
}
|
||||
|
||||
"get a number" in {
|
||||
val obj = MaxNumberSource()
|
||||
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 mustEqual None
|
||||
obj.Size mustEqual Int.MaxValue
|
||||
obj.CountAvailable mustEqual Int.MaxValue - 1
|
||||
obj.CountUsed mustEqual 1
|
||||
}
|
||||
|
||||
"assign the number" in {
|
||||
val obj = MaxNumberSource()
|
||||
val result : Option[LoanedKey] = obj.Available(5)
|
||||
result.isDefined mustEqual true
|
||||
result.get.Object = new TestClass()
|
||||
ok
|
||||
}
|
||||
|
||||
"return a number (unused)" in {
|
||||
val obj = MaxNumberSource()
|
||||
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 mustEqual None
|
||||
obj.CountUsed mustEqual 0
|
||||
}
|
||||
|
||||
"return a number (assigned)" in {
|
||||
val obj = MaxNumberSource()
|
||||
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 mustEqual Some(test)
|
||||
obj.CountUsed mustEqual 0
|
||||
}
|
||||
|
||||
"restrict a number (unassigned)" in {
|
||||
val obj = MaxNumberSource()
|
||||
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 mustEqual None
|
||||
}
|
||||
|
||||
"restrict a number (assigned + multiple assignments)" in {
|
||||
val obj = MaxNumberSource()
|
||||
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 mustEqual None
|
||||
result.get.Object = None //assignment 1
|
||||
result.get.Object mustEqual None //still unassigned
|
||||
result.get.Object = test1 //assignment 2
|
||||
result.get.Object mustEqual Some(test1)
|
||||
result.get.Object = test2 //assignment 3
|
||||
result.get.Object mustEqual Some(test1) //same as above
|
||||
}
|
||||
|
||||
"return a restricted number (correctly fail)" in {
|
||||
val obj = MaxNumberSource()
|
||||
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 mustEqual Some(test)
|
||||
}
|
||||
|
||||
"restrict a previously-assigned number" in {
|
||||
val obj = MaxNumberSource()
|
||||
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 mustEqual Some(test)
|
||||
}
|
||||
|
||||
"check a number (not previously gotten)" in {
|
||||
val obj = MaxNumberSource()
|
||||
val result2 : Option[SecureKey] = obj.Get(5)
|
||||
result2.get.GUID mustEqual 5
|
||||
result2.get.Policy mustEqual AvailabilityPolicy.Available
|
||||
result2.get.Object mustEqual None
|
||||
}
|
||||
|
||||
"check a number (previously gotten)" in {
|
||||
val obj = MaxNumberSource()
|
||||
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 mustEqual None
|
||||
val result2 : Option[SecureKey] = obj.Get(5)
|
||||
result2.get.GUID mustEqual 5
|
||||
result2.get.Policy mustEqual AvailabilityPolicy.Leased
|
||||
result2.get.Object mustEqual None
|
||||
}
|
||||
|
||||
"check a number (assigned)" in {
|
||||
val obj = MaxNumberSource()
|
||||
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 = MaxNumberSource()
|
||||
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 === test
|
||||
obj.Return(5) mustEqual Some(test)
|
||||
val result3 : Option[SecureKey] = obj.Get(5)
|
||||
result3.get.Policy mustEqual AvailabilityPolicy.Available
|
||||
result3.get.Object mustEqual None
|
||||
}
|
||||
|
||||
"clear" in {
|
||||
val obj = MaxNumberSource()
|
||||
val test1 = new TestClass()
|
||||
val test2 = 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 = test1
|
||||
obj.CountUsed mustEqual 4
|
||||
|
||||
val list : List[IdentifiableEntity] = obj.Clear()
|
||||
obj.CountUsed mustEqual 0
|
||||
list.size mustEqual 3
|
||||
list.count(obj => { obj == test1 }) mustEqual 2
|
||||
list.count(obj => { obj == test2 }) mustEqual 1
|
||||
}
|
||||
}
|
||||
|
||||
"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 mustEqual None
|
||||
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 mustEqual None
|
||||
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 mustEqual Some(test)
|
||||
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 mustEqual None
|
||||
}
|
||||
|
||||
"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 mustEqual None
|
||||
result.get.Object = None //assignment 1
|
||||
result.get.Object mustEqual None //still unassigned
|
||||
result.get.Object = test1 //assignment 2
|
||||
result.get.Object mustEqual Some(test1)
|
||||
result.get.Object = test2 //assignment 3
|
||||
result.get.Object mustEqual Some(test1) //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 mustEqual Some(test)
|
||||
}
|
||||
|
||||
"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 mustEqual Some(test)
|
||||
}
|
||||
|
||||
"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 mustEqual None
|
||||
}
|
||||
|
||||
"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 mustEqual None
|
||||
val result2 : Option[SecureKey] = obj.Get(5)
|
||||
result2.get.GUID mustEqual 5
|
||||
result2.get.Policy mustEqual AvailabilityPolicy.Leased
|
||||
result2.get.Object mustEqual None
|
||||
}
|
||||
|
||||
"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) mustEqual Some(test)
|
||||
val result3 : Option[SecureKey] = obj.Get(5)
|
||||
result3.get.Policy mustEqual AvailabilityPolicy.Available
|
||||
result3.get.Object mustEqual None
|
||||
}
|
||||
|
||||
"clear" in {
|
||||
val obj = LimitedNumberSource(25)
|
||||
val test1 = new TestClass()
|
||||
val test2 = 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 = test1
|
||||
obj.CountUsed mustEqual 4
|
||||
|
||||
val list : List[IdentifiableEntity] = obj.Clear()
|
||||
obj.CountUsed mustEqual 0
|
||||
list.size mustEqual 3
|
||||
list.count(obj => obj == test1) mustEqual 2
|
||||
list.count(obj => obj == test2) mustEqual 1
|
||||
}
|
||||
}
|
||||
}
|
||||
153
common/src/test/scala/objects/PlayerTest.scala
Normal file
153
common/src/test/scala/objects/PlayerTest.scala
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects.{Implant, Player, SimpleItem}
|
||||
import net.psforever.objects.definition.{ImplantDefinition, SimpleItemDefinition}
|
||||
import net.psforever.objects.equipment.EquipmentSize
|
||||
import net.psforever.types.{CharacterGender, ExoSuitType, ImplantType, PlanetSideEmpire}
|
||||
import org.specs2.mutable._
|
||||
|
||||
class PlayerTest extends Specification {
|
||||
"construct" in {
|
||||
val obj = new Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
obj.isAlive mustEqual false
|
||||
}
|
||||
|
||||
"(re)spawn" in {
|
||||
val obj = new Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
obj.isAlive mustEqual false
|
||||
obj.Health mustEqual 0
|
||||
obj.Stamina mustEqual 0
|
||||
obj.Armor mustEqual 0
|
||||
obj.Spawn
|
||||
obj.isAlive mustEqual true
|
||||
obj.Health mustEqual obj.MaxHealth
|
||||
obj.Stamina mustEqual obj.MaxStamina
|
||||
obj.Armor mustEqual obj.MaxArmor
|
||||
}
|
||||
|
||||
"init (Standard Exo-Suit)" in {
|
||||
val obj = new Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
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
|
||||
}
|
||||
|
||||
"die" in {
|
||||
val obj = new Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
obj.Spawn
|
||||
obj.Armor = 35 //50 -> 35
|
||||
obj.isAlive mustEqual true
|
||||
obj.Health mustEqual obj.MaxHealth
|
||||
obj.Stamina mustEqual obj.MaxStamina
|
||||
obj.Armor mustEqual 35
|
||||
obj.Die
|
||||
obj.isAlive mustEqual false
|
||||
obj.Health mustEqual 0
|
||||
obj.Stamina mustEqual 0
|
||||
obj.Armor mustEqual 35
|
||||
}
|
||||
|
||||
"draw equipped holsters only" in {
|
||||
val wep = SimpleItem(SimpleItemDefinition(149))
|
||||
val obj = new Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
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 = new Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
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 0 //default value
|
||||
|
||||
obj.DrawnSlot = 1
|
||||
obj.DrawnSlot mustEqual 1
|
||||
obj.LastDrawnSlot mustEqual 0 //default value; sorry
|
||||
|
||||
obj.DrawnSlot = 0
|
||||
obj.DrawnSlot mustEqual 0
|
||||
obj.LastDrawnSlot mustEqual 1
|
||||
|
||||
obj.DrawnSlot = Player.HandsDownSlot
|
||||
obj.DrawnSlot mustEqual Player.HandsDownSlot
|
||||
obj.LastDrawnSlot mustEqual 0
|
||||
|
||||
obj.DrawnSlot = 1
|
||||
obj.DrawnSlot mustEqual 1
|
||||
obj.LastDrawnSlot mustEqual 0
|
||||
|
||||
obj.DrawnSlot = 0
|
||||
obj.DrawnSlot mustEqual 0
|
||||
obj.LastDrawnSlot mustEqual 1
|
||||
|
||||
obj.DrawnSlot = 1
|
||||
obj.DrawnSlot mustEqual 1
|
||||
obj.LastDrawnSlot mustEqual 0
|
||||
|
||||
obj.DrawnSlot = Player.HandsDownSlot
|
||||
obj.DrawnSlot mustEqual Player.HandsDownSlot
|
||||
obj.LastDrawnSlot mustEqual 1
|
||||
}
|
||||
|
||||
"install no implants until a slot is unlocked" in {
|
||||
val testplant : Implant = Implant(ImplantDefinition(1))
|
||||
val obj = new Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
obj.Implants(0).Unlocked mustEqual false
|
||||
obj.Implant(0) mustEqual None
|
||||
obj.InstallImplant(testplant)
|
||||
obj.Implant(0) mustEqual None
|
||||
obj.Implant(ImplantType(1)) mustEqual None
|
||||
|
||||
obj.Implants(0).Unlocked = true
|
||||
obj.InstallImplant(testplant)
|
||||
obj.Implant(0) mustEqual Some(testplant.Definition.Type)
|
||||
obj.Implant(ImplantType(1)) mustEqual Some(testplant)
|
||||
}
|
||||
|
||||
"uninstall implants" in {
|
||||
val testplant : Implant = Implant(ImplantDefinition(1))
|
||||
val obj = new Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
obj.Implants(0).Unlocked = true
|
||||
obj.InstallImplant(testplant)
|
||||
obj.Implant(ImplantType(1)) mustEqual Some(testplant)
|
||||
|
||||
obj.UninstallImplant(ImplantType(1))
|
||||
obj.Implant(0) mustEqual None
|
||||
obj.Implant(ImplantType(1)) mustEqual None
|
||||
}
|
||||
|
||||
"administrate" in {
|
||||
val obj = new Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
obj.Admin mustEqual false
|
||||
Player.Administrate(obj, true)
|
||||
obj.Admin mustEqual true
|
||||
Player.Administrate(obj, false)
|
||||
obj.Admin mustEqual false
|
||||
}
|
||||
|
||||
"spectate" in {
|
||||
val obj = new Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
obj.Spectator mustEqual false
|
||||
Player.Spectate(obj, true)
|
||||
obj.Spectator mustEqual true
|
||||
Player.Spectate(obj, false)
|
||||
obj.Spectator mustEqual false
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue