mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-19 18:44:45 +00:00
added and expanded tests in hopes of increasing code coverage score
added tests for AvatarService and PacketCodingActor; especially PCA tests
This commit is contained in:
parent
0e5afe6cfd
commit
3aee0ab4e8
43
.codecov.yml
43
.codecov.yml
|
|
@ -1,2 +1,45 @@
|
|||
# Too spammy for us
|
||||
comment: off
|
||||
|
||||
ignore:
|
||||
- "common/src/main/scala/net/psforever/objects/equipment/Ammo.scala"
|
||||
- "common/src/main/scala/net/psforever/objects/equipment/CItem.scala"
|
||||
- "common/src/main/scala/net/psforever/objects/equipment/EquipmentSize.scala"
|
||||
- "common/src/main/scala/net/psforever/objects/equipment/Kits.scala"
|
||||
- "common/src/main/scala/net/psforever/objects/equipment/SItem.scala"
|
||||
- "common/src/main/scala/net/psforever/objects/guid/AvailabilityPolicy.scala"
|
||||
- "common/src/main/scala/net/psforever/objects/vehicles/AccessPermissionGroup.scala"
|
||||
- "common/src/main/scala/net/psforever/objects/vehicles/SeatArmoRestriction.scala"
|
||||
- "common/src/main/scala/net/psforever/objects/vehicles/VehicleLockState.scala"
|
||||
- "common/src/main/scala/net/psforever/objects/Avatars.scala"
|
||||
- "common/src/main/scala/net/psforever/packet/crypto"
|
||||
- "common/src/main/scala/net/psforever/packet/game/objectcreate/DrawnSlot.scala"
|
||||
- "common/src/main/scala/net/psforever/packet/game/objectcreate/DriveState.scala"
|
||||
- "common/src/main/scala/net/psforever/packet/game/objectcreate/MountItem.scala"
|
||||
- "common/src/main/scala/net/psforever/packet/game/objectcreate/ObjectClass.scala"
|
||||
- "common/src/main/scala/net/psforever/packet/game/objectcreate/Prefab.scala"
|
||||
- "common/src/main/scala/net/psforever/packet/ControlPacketOpcode.scala"
|
||||
- "common/src/main/scala/net/psforever/packet/CryptoPacketOpcode.scala"
|
||||
- "common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala"
|
||||
- "common/src/main/scala/net/psforever/objects/ObjectType.scala"
|
||||
- "common/src/main/scala/net/psforever/types/Angular.scala"
|
||||
- "common/src/main/scala/net/psforever/types/CertificationType.scala"
|
||||
- "common/src/main/scala/net/psforever/types/ChatMessageType.scala"
|
||||
- "common/src/main/scala/net/psforever/types/EmoteType.scala"
|
||||
- "common/src/main/scala/net/psforever/types/ExoSuitType.scala"
|
||||
- "common/src/main/scala/net/psforever/types/GrenadeState.scala"
|
||||
- "common/src/main/scala/net/psforever/types/ImplantType.scala"
|
||||
- "common/src/main/scala/net/psforever/types/MeritCommendation.scala"
|
||||
- "common/src/main/scala/net/psforever/types/PlanetSideEmpire.scala"
|
||||
- "common/src/main/scala/net/psforever/types/TransactionType.scala"
|
||||
- "pslogin/src/main/scala/services/avatar/AvatarAction.scala"
|
||||
- "pslogin/src/main/scala/services/avatar/AvatarResponse.scala"
|
||||
- "pslogin/src/main/scala/services/local/LocalAction.scala"
|
||||
- "pslogin/src/main/scala/services/local/LocalResponse.scala"
|
||||
- "pslogin/src/main/scala/services/vehicle/VehicleAction.scala"
|
||||
- "pslogin/src/main/scala/services/vehicle/VehicleResponse.scala"
|
||||
- "pslogin/src/main/scala/CryptoSessionActor.scala"
|
||||
- "pslogin/src/main/scala/DatabaseConnector.scala"
|
||||
- "pslogin/src/main/scala/LoginConfig.scala"
|
||||
- "pslogin/src/main/scala/MDCContextAware.scala"
|
||||
- "pslogin/src/main/scala/MDCPropagatingExecutionContext.scala"
|
||||
|
|
|
|||
|
|
@ -778,6 +778,14 @@ object GlobalDefinitions {
|
|||
* Initialize `AmmoBoxDefinition` globals.
|
||||
*/
|
||||
private def init_ammo() : Unit = {
|
||||
melee_ammo.Size = EquipmentSize.Blocked
|
||||
|
||||
frag_grenade_ammo.Size = EquipmentSize.Blocked
|
||||
|
||||
jammer_grenade_ammo.Size = EquipmentSize.Blocked
|
||||
|
||||
plasma_grenade_ammo.Size = EquipmentSize.Blocked
|
||||
|
||||
bullet_9mm.Capacity = 50
|
||||
bullet_9mm.Tile = InventoryTile.Tile33
|
||||
|
||||
|
|
@ -802,6 +810,8 @@ object GlobalDefinitions {
|
|||
maelstrom_ammo.Capacity = 50
|
||||
maelstrom_ammo.Tile = InventoryTile.Tile33
|
||||
|
||||
phoenix_missile.Size = EquipmentSize.Blocked
|
||||
|
||||
striker_missile_ammo.Capacity = 15
|
||||
striker_missile_ammo.Tile = InventoryTile.Tile44
|
||||
|
||||
|
|
@ -841,6 +851,8 @@ object GlobalDefinitions {
|
|||
upgrade_canister.Capacity = 100
|
||||
upgrade_canister.Tile = InventoryTile.Tile33
|
||||
|
||||
trek_ammo.Size = EquipmentSize.Blocked
|
||||
|
||||
bullet_35mm.Capacity = 100
|
||||
bullet_35mm.Tile = InventoryTile.Tile44
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class Player(private val name : String,
|
|||
private var maxStamina : Int = 100 //does anything affect this?
|
||||
|
||||
private var exosuit : ExoSuitType.Value = ExoSuitType.Standard
|
||||
private val freeHand : EquipmentSlot = new OffhandEquipmentSlot(EquipmentSize.Any)
|
||||
private val freeHand : EquipmentSlot = new OffhandEquipmentSlot(EquipmentSize.Inventory)
|
||||
private val holsters : Array[EquipmentSlot] = Array.fill[EquipmentSlot](5)(new EquipmentSlot)
|
||||
private val fifthSlot : EquipmentSlot = new OffhandEquipmentSlot(EquipmentSize.Inventory)
|
||||
private val inventory : GridInventory = GridInventory()
|
||||
|
|
@ -59,7 +59,6 @@ class Player(private val name : String,
|
|||
private var cloaked : Boolean = false
|
||||
private var backpackAccess : Option[PlanetSideGUID] = None
|
||||
|
||||
private var sessionId : Long = 0
|
||||
private var admin : Boolean = false
|
||||
private var spectator : Boolean = false
|
||||
|
||||
|
|
@ -498,20 +497,13 @@ class Player(private val name : String,
|
|||
isBackpack && (backpackAccess.isEmpty || backpackAccess.contains(player.GUID))
|
||||
}
|
||||
|
||||
def SessionId : Long = sessionId
|
||||
|
||||
def Admin : Boolean = admin
|
||||
|
||||
def Spectator : Boolean = spectator
|
||||
|
||||
def Continent : String = continent
|
||||
|
||||
def VehicleSeated : Option[PlanetSideGUID] = vehicleSeated
|
||||
|
||||
def VehicleSeated_=(vehicle : Vehicle) : Option[PlanetSideGUID] = {
|
||||
vehicleSeated = Some(vehicle.GUID)
|
||||
VehicleSeated
|
||||
}
|
||||
def VehicleSeated_=(guid : PlanetSideGUID) : Option[PlanetSideGUID] = VehicleSeated_=(Some(guid))
|
||||
|
||||
def VehicleSeated_=(guid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = {
|
||||
vehicleSeated = guid
|
||||
|
|
@ -520,16 +512,15 @@ class Player(private val name : String,
|
|||
|
||||
def VehicleOwned : Option[PlanetSideGUID] = vehicleOwned
|
||||
|
||||
def VehicleOwned_=(vehicle : Vehicle) : Option[PlanetSideGUID] = {
|
||||
vehicleOwned = Some(vehicle.GUID)
|
||||
VehicleOwned
|
||||
}
|
||||
def VehicleOwned_=(guid : PlanetSideGUID) : Option[PlanetSideGUID] = VehicleOwned_=(Some(guid))
|
||||
|
||||
def VehicleOwned_=(guid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = {
|
||||
vehicleOwned = guid
|
||||
VehicleOwned
|
||||
}
|
||||
|
||||
def Continent : String = continent
|
||||
|
||||
def Continent_=(zoneId : String) : String = {
|
||||
continent = zoneId
|
||||
Continent
|
||||
|
|
@ -570,27 +561,16 @@ object Player {
|
|||
new Player(name, faction, sex, head, voice)
|
||||
}
|
||||
|
||||
def apply(guid : PlanetSideGUID, name : String, faction : PlanetSideEmpire.Value, sex : CharacterGender.Value, head : Int, voice : Int) : Player = {
|
||||
val obj = new Player(name, faction, sex, voice, head)
|
||||
obj.GUID = guid
|
||||
obj
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the type of `AvatarDefinition` is used to define the player.
|
||||
* @param player the player
|
||||
* @param avatarDef the player's new definition entry
|
||||
* @return the changed player
|
||||
*/
|
||||
def apply(player : Player, avatarDef : AvatarDefinition) : Player = {
|
||||
player.playerDef = avatarDef
|
||||
player
|
||||
}
|
||||
|
||||
def apply(player : Player, sessId : Long) : Player = {
|
||||
player.sessionId = sessId
|
||||
player
|
||||
}
|
||||
// /**
|
||||
// * Change the type of `AvatarDefinition` is used to define the player.
|
||||
// * @param player the player
|
||||
// * @param avatarDef the player's new definition entry
|
||||
// * @return the changed player
|
||||
// */
|
||||
// def apply(player : Player, avatarDef : AvatarDefinition) : Player = {
|
||||
// player.playerDef = avatarDef
|
||||
// player
|
||||
// }
|
||||
|
||||
def SuitSetup(player : Player, eSuit : ExoSuitType.Value) : Unit = {
|
||||
val esuitDef : ExoSuitDefinition = ExoSuitDefinition.Select(eSuit)
|
||||
|
|
@ -604,11 +584,6 @@ object Player {
|
|||
(0 until 5).foreach(index => { player.Slot(index).Size = esuitDef.Holster(index) })
|
||||
}
|
||||
|
||||
def ChangeSessionId(player : Player, session : Long) : Long = {
|
||||
player.sessionId = session
|
||||
player.SessionId
|
||||
}
|
||||
|
||||
def Administrate(player : Player, isAdmin : Boolean) : Player = {
|
||||
player.admin = isAdmin
|
||||
player
|
||||
|
|
|
|||
|
|
@ -1,45 +0,0 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.entity
|
||||
|
||||
import net.psforever.types.Vector3
|
||||
|
||||
import scala.collection.mutable
|
||||
|
||||
class MobileWorldEntity extends WorldEntity {
|
||||
private var coords : mutable.Stack[TimeEntry] = mutable.Stack(TimeEntry.invalid) //history of last #n positional updates
|
||||
private var orient : mutable.Stack[TimeEntry] = mutable.Stack(TimeEntry.invalid) //history of last #n orientation updates
|
||||
private var vel : Option[Vector3] = None
|
||||
|
||||
def Position : Vector3 = coords.head.entry
|
||||
|
||||
def Position_=(vec : Vector3) : Vector3 = {
|
||||
coords = MobileWorldEntity.pushNewStack(coords, vec, SimpleWorldEntity.validatePositionEntry)
|
||||
Position
|
||||
}
|
||||
|
||||
def AllPositions : scala.collection.immutable.List[TimeEntry] = coords.toList
|
||||
|
||||
def Orientation : Vector3 = orient.head.entry
|
||||
|
||||
def Orientation_=(vec : Vector3) : Vector3 = {
|
||||
orient = MobileWorldEntity.pushNewStack(orient, vec, SimpleWorldEntity.validateOrientationEntry)
|
||||
Orientation
|
||||
}
|
||||
|
||||
def AllOrientations : scala.collection.immutable.List[TimeEntry] = orient.toList
|
||||
|
||||
def Velocity : Option[Vector3] = vel
|
||||
|
||||
def Velocity_=(vec : Option[Vector3]) : Option[Vector3] = {
|
||||
vel = vec
|
||||
vel
|
||||
}
|
||||
|
||||
override def toString : String = WorldEntity.toString(this)
|
||||
}
|
||||
|
||||
object MobileWorldEntity {
|
||||
def pushNewStack(lst : mutable.Stack[TimeEntry], newEntry : Vector3, validate : (Vector3) => Vector3) : mutable.Stack[TimeEntry] = {
|
||||
lst.slice(0, 199).push(TimeEntry(validate(newEntry)))
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.entity
|
||||
|
||||
import net.psforever.types.Vector3
|
||||
|
||||
case class TimeEntry(entry : net.psforever.types.Vector3)(implicit time : Long = org.joda.time.DateTime.now.getMillis)
|
||||
|
||||
object TimeEntry {
|
||||
val invalid = TimeEntry(Vector3(0f, 0f, 0f))(0L)
|
||||
|
||||
def apply(x : Float, y : Float, z : Float) : TimeEntry =
|
||||
TimeEntry(Vector3(x, y, z))
|
||||
}
|
||||
|
|
@ -11,8 +11,7 @@ object EquipmentSize extends Enumeration {
|
|||
VehicleWeapon, //vehicle-mounted weapons
|
||||
BFRArmWeapon, //duel arm weapons for bfr
|
||||
BFRGunnerWeapon, //gunner seat for bfr
|
||||
Inventory, //reserved
|
||||
Any
|
||||
Inventory //reserved
|
||||
= Value
|
||||
|
||||
/**
|
||||
|
|
@ -26,13 +25,13 @@ object EquipmentSize extends Enumeration {
|
|||
* @param type2 the second size
|
||||
* @return `true`, if they are equal; `false`, otherwise
|
||||
*/
|
||||
def isEqual(type1 : EquipmentSize.Value, type2 : EquipmentSize.Value) : Boolean = {
|
||||
if(type1 >= Inventory || type2 >= Inventory) {
|
||||
true
|
||||
}
|
||||
else if(type1 == Blocked || type2 == Blocked) {
|
||||
def isEqual(type1 : EquipmentSize.Value, type2 : EquipmentSize.Value) : Boolean = {
|
||||
if(type1 == Blocked || type2 == Blocked) {
|
||||
false
|
||||
}
|
||||
else if(type1 == Inventory || type2 == Inventory) {
|
||||
true
|
||||
}
|
||||
else {
|
||||
type1 == type2
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,22 +4,15 @@ package net.psforever.objects.equipment
|
|||
import scala.collection.mutable
|
||||
|
||||
class FireModeDefinition {
|
||||
// private var ammoTypes : mutable.ListBuffer[Ammo.Value] = mutable.ListBuffer[Ammo.Value]() //ammo types valid for this fire mode
|
||||
private val ammoTypeIndices : mutable.ListBuffer[Int] = mutable.ListBuffer[Int]() //indices pointing to all ammo types used
|
||||
private var ammoSlotIndex : Int = 0 //ammunition slot number this fire mode utilizes
|
||||
private var chamber : Int = 1 //how many rounds are queued to be fired at once, e.g., 3 for the Jackhammer's triple burst
|
||||
private var magazine : Int = 1 //how many rounds are queued for each reload cycle
|
||||
private var target : Any = _ //target designation (self? other?)
|
||||
// private var target : Any = _ //target designation (self? other?)
|
||||
private var resetAmmoIndexOnSwap : Boolean = false //when changing fire modes, do not attempt to match previous mode's ammo type
|
||||
|
||||
//damage modifiers will follow here ...
|
||||
|
||||
// def AmmoTypes : mutable.ListBuffer[Ammo.Value] = ammoTypes
|
||||
//
|
||||
// def AmmoTypes_=(ammo : Ammo.Value) : mutable.ListBuffer[Ammo.Value] = {
|
||||
// ammoTypes += ammo
|
||||
// }
|
||||
|
||||
def AmmoSlotIndex : Int = ammoSlotIndex
|
||||
|
||||
def AmmoSlotIndex_=(index : Int) : Int = {
|
||||
|
|
@ -47,12 +40,12 @@ class FireModeDefinition {
|
|||
Magazine
|
||||
}
|
||||
|
||||
def Target : Any = target
|
||||
|
||||
def Target_+(setAsTarget : Any) : Any = {
|
||||
target = setAsTarget
|
||||
Target
|
||||
}
|
||||
// def Target : Any = target
|
||||
//
|
||||
// def Target_+(setAsTarget : Any) : Any = {
|
||||
// target = setAsTarget
|
||||
// Target
|
||||
// }
|
||||
|
||||
def ResetAmmoIndexOnSwap : Boolean = resetAmmoIndexOnSwap
|
||||
|
||||
|
|
|
|||
|
|
@ -4,48 +4,6 @@ package net.psforever.objects.guid.source
|
|||
import net.psforever.objects.entity.IdentifiableEntity
|
||||
import net.psforever.objects.guid.key.{LoanedKey, SecureKey}
|
||||
|
||||
trait NumberSourceAccessors {
|
||||
/**
|
||||
* Produce an un-modifiable wrapper for the `Monitor` for this number.
|
||||
* @param number the number
|
||||
* @return the wrapped `Monitor`
|
||||
*/
|
||||
def Get(number : Int) : Option[SecureKey]
|
||||
|
||||
/**
|
||||
* Produce a modifiable wrapper for the `Monitor` for this number, only if the number has not been used.
|
||||
* The `Monitor` should be updated before being wrapped, if necessary.
|
||||
* @param number the number
|
||||
* @return the wrapped `Monitor`, or `None`
|
||||
*/
|
||||
def Available(number : Int) : Option[LoanedKey]
|
||||
|
||||
/**
|
||||
* Consume a wrapped `Monitor` and release its number from its previous assignment/use.
|
||||
* @param monitor the `Monitor`
|
||||
* @return any object previously using this `Monitor`
|
||||
*/
|
||||
def Return(monitor : SecureKey) : Option[IdentifiableEntity] = {
|
||||
Return(monitor.GUID)
|
||||
}
|
||||
|
||||
/**
|
||||
* Consume a wrapped `Monitor` and release its number from its previous assignment/use.
|
||||
* @param monitor the `Monitor`
|
||||
* @return any object previously using this `Monitor`
|
||||
*/
|
||||
def Return(monitor : LoanedKey) : Option[IdentifiableEntity] = {
|
||||
Return(monitor.GUID)
|
||||
}
|
||||
|
||||
/**
|
||||
* Consume the number of a `Monitor` and release that number from its previous assignment/use.
|
||||
* @param number the number
|
||||
* @return any object previously using this number
|
||||
*/
|
||||
def Return(number : Int) : Option[IdentifiableEntity]
|
||||
}
|
||||
|
||||
/**
|
||||
* A `NumberSource` is considered a master "pool" of numbers from which all numbers are available to be drawn.
|
||||
* The numbers are considered to be exclusive.<br>
|
||||
|
|
|
|||
|
|
@ -15,4 +15,4 @@ final case class MultiPacket(packets : Vector[ByteVector])
|
|||
|
||||
object MultiPacket extends Marshallable[MultiPacket] {
|
||||
implicit val codec : Codec[MultiPacket] = ("packets" | vector(variableSizeBytes(uint8L, bytes))).as[MultiPacket]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,4 +68,4 @@ object MultiPacketEx extends Marshallable[MultiPacketEx] {
|
|||
}
|
||||
|
||||
implicit val codec : Codec[MultiPacketEx] = ("packets" | vector(variableSizeBytesLong(sizeCodec, bytes))).as[MultiPacketEx]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,14 +3,14 @@ package net.psforever.packet.control
|
|||
|
||||
import net.psforever.packet.{ControlPacketOpcode, Marshallable, PlanetSideControlPacket}
|
||||
import scodec.Codec
|
||||
import scodec.bits.{BitVector, ByteOrdering, ByteVector}
|
||||
import scodec.bits.BitVector
|
||||
import scodec.codecs._
|
||||
|
||||
final case class SlottedMetaAck(slot : Int, subslot : Int)
|
||||
extends PlanetSideControlPacket {
|
||||
type Packet = SlottedMetaAck
|
||||
|
||||
assert(slot >= 0 && slot <= 7, s"Slot number ($slot) is out of range")
|
||||
assert(slot >= 0 && slot <= 7, s"Slot number ($slot) is out of range") //TODO 7 types of SlottedMeta, 4 types of ResultB?
|
||||
|
||||
def opcode = {
|
||||
val base = ControlPacketOpcode.RelatedB0.id
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package net.psforever.packet.control
|
|||
|
||||
import net.psforever.packet.{ControlPacketOpcode, Marshallable, PlanetSideControlPacket}
|
||||
import scodec.Codec
|
||||
import scodec.bits.{BitVector, ByteOrdering, ByteVector}
|
||||
import scodec.bits.{BitVector, ByteVector}
|
||||
import scodec.codecs._
|
||||
|
||||
final case class SlottedMetaPacket(slot : Int, subslot : Int, packet : ByteVector)
|
||||
|
|
|
|||
|
|
@ -71,4 +71,4 @@ object LoginMessage extends Marshallable[LoginMessage] {
|
|||
("revision" | uint32L)
|
||||
)
|
||||
).as[LoginMessage]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
27
common/src/test/scala/control/ClientStartTest.scala
Normal file
27
common/src/test/scala/control/ClientStartTest.scala
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package control
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.control._
|
||||
import scodec.bits._
|
||||
|
||||
class ClientStartTest extends Specification {
|
||||
val string = hex"0001 00000002 00261e27 000001f0"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case ClientStart(nonce) =>
|
||||
nonce mustEqual 656287232
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = ClientStart(656287232)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
26
common/src/test/scala/control/ConnectionCloseTest.scala
Normal file
26
common/src/test/scala/control/ConnectionCloseTest.scala
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package control
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.control._
|
||||
import scodec.bits._
|
||||
|
||||
class ConnectionCloseTest extends Specification {
|
||||
val string = hex"001D"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case ConnectionClose() =>
|
||||
ok
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = ConnectionClose()
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
|
|
@ -40,4 +40,8 @@ class MultiPacketExTest extends Specification {
|
|||
"test "+i ! { MultiPacketEx.encode(packets{i}).require.toByteVector mustEqual strings{i} }
|
||||
}
|
||||
}
|
||||
|
||||
"sizeCodec description" in {
|
||||
MultiPacketEx.sizeCodec.toString mustEqual "variable-bit unsigned integer"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
38
common/src/test/scala/control/MultiPacketTest.scala
Normal file
38
common/src/test/scala/control/MultiPacketTest.scala
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package control
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.control._
|
||||
import scodec.bits._
|
||||
|
||||
class MultiPacketTest extends Specification {
|
||||
val string = hex"00 03 04 00 15 13 23 3A 00 09 03 E3 00 19 16 6D 56 05 68 05 40 A0 EF 45 00 15 0E 44 00 A0 A2 41 00 00 0F 88 00 06 E4 C0 60 00 00 00 15 E4 32 40 74 72 61 69 6E 69 6E 67 5F 77 65 61 70 6F 6E 73 30 31 13 BD 68 05 53 F6 EF 90 D1 6E 03 14 FE 78 8C 20 1C C0 00 00 1F 00 09 03 E4 6D 56 05 68 05 40 A0 EF 45 00 15 0E 44 30 89 A1 41 00 00 0F 8A 01 00 04 18 EF 80"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case MultiPacket(data) =>
|
||||
data.size mustEqual 4
|
||||
data(0) mustEqual hex"00151323"
|
||||
data(1) mustEqual hex"000903e30019166d5605680540a0ef4500150e4400a0a24100000f880006e4c06000000015e43240747261696e696e675f776561706f6e733031"
|
||||
data(2) mustEqual hex"bd680553f6ef90d16e0314fe788c201cc00000"
|
||||
data(3) mustEqual hex"000903e46d5605680540a0ef4500150e443089a14100000f8a01000418ef80"
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = MultiPacket(
|
||||
Vector(
|
||||
hex"00151323",
|
||||
hex"000903e30019166d5605680540a0ef4500150e4400a0a24100000f880006e4c06000000015e43240747261696e696e675f776561706f6e733031",
|
||||
hex"bd680553f6ef90d16e0314fe788c201cc00000",
|
||||
hex"000903e46d5605680540a0ef4500150e443089a14100000f8a01000418ef80"
|
||||
)
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
29
common/src/test/scala/control/SlottedMetaAckTest.scala
Normal file
29
common/src/test/scala/control/SlottedMetaAckTest.scala
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package control
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.control._
|
||||
import scodec.bits._
|
||||
|
||||
class SlottedMetaAckTest extends Specification {
|
||||
val string = hex"00150da4"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case SlottedMetaAck(_, _) =>
|
||||
ko
|
||||
case RelatedB0(subslot) => //important!
|
||||
subslot mustEqual 3492
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val pkt = SlottedMetaAck(0, 3492)
|
||||
val msg = PacketCoding.EncodePacket(pkt).require.toByteVector
|
||||
|
||||
msg mustEqual string
|
||||
}
|
||||
}
|
||||
122
common/src/test/scala/game/LoginMessageTest.scala
Normal file
122
common/src/test/scala/game/LoginMessageTest.scala
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class LoginMessageTest extends Specification {
|
||||
val string_password = hex"0x01030000000f0000008b4465632020322032303039408061816154000000"
|
||||
val string_token = hex"0x01030000000f0000008b4465632020322032303039a0a0a0a0a121212121a1a1a1a222222222a2a2a2a323232323a3a3a3a424240040806154000000"
|
||||
|
||||
"LoginMessage" should {
|
||||
"decode (username)" in {
|
||||
PacketCoding.DecodePacket(string_password).require match {
|
||||
case LoginMessage(majorVersion, minorVersion, buildDate, username, password, token, revision) =>
|
||||
majorVersion mustEqual 3
|
||||
minorVersion mustEqual 15
|
||||
buildDate mustEqual "Dec 2 2009"
|
||||
username mustEqual "a"
|
||||
password mustEqual Some("a")
|
||||
token mustEqual None
|
||||
revision mustEqual 84
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (token)" in {
|
||||
PacketCoding.DecodePacket(string_token).require match {
|
||||
case LoginMessage(majorVersion, minorVersion, buildDate, username, password, token, revision) =>
|
||||
majorVersion mustEqual 3
|
||||
minorVersion mustEqual 15
|
||||
buildDate mustEqual "Dec 2 2009"
|
||||
username mustEqual "a"
|
||||
password mustEqual None
|
||||
token mustEqual Some("AAAABBBBCCCCDDDDEEEEFFFFGGGGHHH")
|
||||
revision mustEqual 84
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (username)" in {
|
||||
val msg = LoginMessage(
|
||||
3,
|
||||
15,
|
||||
"Dec 2 2009",
|
||||
"a",
|
||||
Some("a"),
|
||||
None,
|
||||
84
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_password
|
||||
}
|
||||
}
|
||||
|
||||
"encode (token)" in {
|
||||
val msg = LoginMessage(
|
||||
3,
|
||||
15,
|
||||
"Dec 2 2009",
|
||||
"a",
|
||||
None,
|
||||
Some("AAAABBBBCCCCDDDDEEEEFFFFGGGGHHH"),
|
||||
84
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_token
|
||||
}
|
||||
|
||||
"encode (both?)" in {
|
||||
LoginMessage(
|
||||
3,
|
||||
15,
|
||||
"Dec 2 2009",
|
||||
"a",
|
||||
Some("a"),
|
||||
Some("AAAABBBBCCCCDDDDEEEEFFFFGGGGHHH"),
|
||||
84
|
||||
) must throwA[IllegalArgumentException]
|
||||
}
|
||||
|
||||
"encode (majorVersion == -1)" in {
|
||||
LoginMessage(
|
||||
-1,
|
||||
15,
|
||||
"Dec 2 2009",
|
||||
"a",
|
||||
Some("a"),
|
||||
None,
|
||||
84
|
||||
) must throwA[IllegalArgumentException]
|
||||
}
|
||||
|
||||
"encode (minorVersion == -1)" in {
|
||||
LoginMessage(
|
||||
3,
|
||||
-1,
|
||||
"Dec 2 2009",
|
||||
"a",
|
||||
Some("a"),
|
||||
None,
|
||||
84
|
||||
) must throwA[IllegalArgumentException]
|
||||
}
|
||||
|
||||
"encode (revision == -1)" in {
|
||||
LoginMessage(
|
||||
3,
|
||||
15,
|
||||
"Dec 2 2009",
|
||||
"a",
|
||||
Some("a"),
|
||||
None,
|
||||
-1
|
||||
) must throwA[IllegalArgumentException]
|
||||
}
|
||||
}
|
||||
63
common/src/test/scala/game/ObjectCreateBaseTest.scala
Normal file
63
common/src/test/scala/game/ObjectCreateBaseTest.scala
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game.{ObjectCreateDetailedMessage, _}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import scodec.bits._
|
||||
|
||||
class ObjectCreateBaseTest extends Specification {
|
||||
val packet217 = hex"17 F8 00 00 00 BC 8C 10 90 3B 45 C6 FA 94 00 9F F0 00 00 40 00 08 C0 44 00 69 00 66 00 66 00 45" //fake data
|
||||
val packet218 = hex"18 F8 00 00 00 BC 8C 10 90 3B 45 C6 FA 94 00 9F F0 00 00 40 00 08 C0 44 00 69 00 66 00 66 00 45" //fake data
|
||||
|
||||
"ObjectCreateDetailedMessage" should {
|
||||
"fail to decode" in {
|
||||
//an invalid bit representation will fail to turn into an object
|
||||
PacketCoding.DecodePacket(packet217).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 248
|
||||
cls mustEqual ObjectClass.avatar
|
||||
guid mustEqual PlanetSideGUID(2497)
|
||||
parent mustEqual None
|
||||
data.isDefined mustEqual false
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"fail to encode" in {
|
||||
//the lack of an object will fail to turn into a bad bitstream
|
||||
val msg = ObjectCreateMessage(0L, ObjectClass.avatar, PlanetSideGUID(2497), None, None)
|
||||
PacketCoding.EncodePacket(msg).isFailure mustEqual true
|
||||
}
|
||||
}
|
||||
|
||||
"ObjectCreateDetailedMessage" should {
|
||||
"fail to decode" in {
|
||||
//an invalid bit representation will fail to turn into an object
|
||||
PacketCoding.DecodePacket(packet218).require match {
|
||||
case ObjectCreateDetailedMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 248
|
||||
cls mustEqual ObjectClass.avatar
|
||||
guid mustEqual PlanetSideGUID(2497)
|
||||
parent mustEqual None
|
||||
data.isDefined mustEqual false
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"fail to encode" in {
|
||||
//the lack of an object will fail to turn into a bad bitstream
|
||||
val msg = ObjectCreateDetailedMessage(0L, ObjectClass.avatar, PlanetSideGUID(2497), None, None)
|
||||
PacketCoding.EncodePacket(msg).isFailure mustEqual true
|
||||
}
|
||||
}
|
||||
|
||||
"StreamBitSize" should {
|
||||
"have zero size by default" in {
|
||||
new StreamBitSize() {}.bitsize mustEqual 0L
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
|
|
@ -1,576 +0,0 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, _}
|
||||
import net.psforever.packet.game.objectcreate.{DriveState, _}
|
||||
import net.psforever.types._
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class ObjectCreateMessageVehiclesTest extends Specification {
|
||||
val string_fury = hex"17 50010000 A79 9D01 FBC1C 12A83 2F06 00 00 21 4400003FC00101140C800C0E40000004048F3600301900000"
|
||||
val string_ant = hex"17 C2000000 9E0 7C01 6C2D7 65535 CA16 00 00 00 4400003FC000000"
|
||||
val string_lightning = hex"17 8b010000 df1 5a00 6c2d7 65535 ca16 00 00 00 4400003fc00101300ad8040c4000000408190b801018000002617402070000000"
|
||||
val string_mediumtransport = hex"17 DA010000 8A2 8301 FBC1C 12A83 2F06 00 00 21 2400003FC079020593F80C2E400000040410148030190000017458050D90000001010401F814064000000"
|
||||
val string_ams = hex"17 B8010000 970 3D10 002D765535CA16000000 402285BB0037E4100749E1D03000000620D83A0A00000195798741C00000332E40D84800000"
|
||||
val string_ams_destroyed = hex"17 8D000000 978 3D10 002D765535CA16000000 0"
|
||||
val string_switchblade = hex"17 93010000 A7B A201 FBC1C12A832F06000021 4400003FC00001013AD3180C0E4000000408330DC03019000006620406072000000"
|
||||
val string_droppod = hex"17 C1000000 8110B0E00FA9000ACFFFF000000 4400007F83C0900"
|
||||
val string_orbital_shuttle_1 = hex"17 82000000 0901B026904838000001FE0700"
|
||||
val string_orbital_shuttle_2 = hex"17 C3000000 B02670402F5AA14F88C210000604000007F8FF03C0"
|
||||
|
||||
"decode (fury)" in {
|
||||
PacketCoding.DecodePacket(string_fury).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 336
|
||||
cls mustEqual ObjectClass.fury
|
||||
guid mustEqual PlanetSideGUID(413)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[VehicleData] mustEqual true
|
||||
val fury = data.get.asInstanceOf[VehicleData]
|
||||
fury.basic.pos.coord.x mustEqual 6531.961f
|
||||
fury.basic.pos.coord.y mustEqual 1872.1406f
|
||||
fury.basic.pos.coord.z mustEqual 24.734375f
|
||||
fury.basic.pos.orient.x mustEqual 0f
|
||||
fury.basic.pos.orient.y mustEqual 0f
|
||||
fury.basic.pos.orient.z mustEqual 357.1875f
|
||||
fury.basic.pos.vel.isDefined mustEqual false
|
||||
fury.basic.faction mustEqual PlanetSideEmpire.VS
|
||||
fury.basic.unk mustEqual 2
|
||||
fury.basic.player_guid mustEqual PlanetSideGUID(0)
|
||||
fury.health mustEqual 255
|
||||
//
|
||||
fury.inventory.isDefined mustEqual true
|
||||
fury.inventory.get.contents.size mustEqual 1
|
||||
val mounting = fury.inventory.get.contents.head
|
||||
mounting.objectClass mustEqual ObjectClass.fury_weapon_systema
|
||||
mounting.guid mustEqual PlanetSideGUID(400)
|
||||
mounting.parentSlot mustEqual 1
|
||||
mounting.obj.isInstanceOf[WeaponData] mustEqual true
|
||||
val weapon = mounting.obj.asInstanceOf[WeaponData]
|
||||
weapon.unk1 mustEqual 0x6
|
||||
weapon.unk2 mustEqual 0x8
|
||||
weapon.fire_mode mustEqual 0
|
||||
weapon.ammo.size mustEqual 1
|
||||
val ammo = weapon.ammo.head
|
||||
ammo.objectClass mustEqual ObjectClass.hellfire_ammo
|
||||
ammo.guid mustEqual PlanetSideGUID(432)
|
||||
ammo.parentSlot mustEqual 0
|
||||
ammo.obj.isInstanceOf[AmmoBoxData] mustEqual true
|
||||
ammo.obj.asInstanceOf[AmmoBoxData].unk mustEqual 0x8
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (ant)" in {
|
||||
PacketCoding.DecodePacket(string_ant).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 194L
|
||||
cls mustEqual ObjectClass.ant
|
||||
guid mustEqual PlanetSideGUID(380)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[VehicleData] mustEqual true
|
||||
val ant = data.get.asInstanceOf[VehicleData]
|
||||
ant.basic.pos.coord.x mustEqual 3674.8438f
|
||||
ant.basic.pos.coord.y mustEqual 2726.789f
|
||||
ant.basic.pos.coord.z mustEqual 91.15625f
|
||||
ant.basic.pos.orient.x mustEqual 0f
|
||||
ant.basic.pos.orient.y mustEqual 0f
|
||||
ant.basic.pos.orient.z mustEqual 90.0f
|
||||
ant.basic.faction mustEqual PlanetSideEmpire.VS
|
||||
ant.basic.unk mustEqual 2
|
||||
ant.basic.player_guid mustEqual PlanetSideGUID(0)
|
||||
ant.health mustEqual 255
|
||||
ant.driveState mustEqual DriveState.Mobile
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (lightning)" in {
|
||||
PacketCoding.DecodePacket(string_lightning).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 395L
|
||||
cls mustEqual ObjectClass.lightning
|
||||
guid mustEqual PlanetSideGUID(90)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[VehicleData] mustEqual true
|
||||
val lightning = data.get.asInstanceOf[VehicleData]
|
||||
lightning.basic.pos.coord.x mustEqual 3674.8438f
|
||||
lightning.basic.pos.coord.y mustEqual 2726.789f
|
||||
lightning.basic.pos.coord.z mustEqual 91.15625f
|
||||
lightning.basic.pos.orient.x mustEqual 0f
|
||||
lightning.basic.pos.orient.y mustEqual 0f
|
||||
lightning.basic.pos.orient.z mustEqual 90.0f
|
||||
lightning.basic.faction mustEqual PlanetSideEmpire.VS
|
||||
lightning.basic.unk mustEqual 2
|
||||
lightning.basic.player_guid mustEqual PlanetSideGUID(0)
|
||||
lightning.health mustEqual 255
|
||||
lightning.inventory.isDefined mustEqual true
|
||||
lightning.inventory.get.contents.size mustEqual 1
|
||||
val mounting = lightning.inventory.get.contents.head
|
||||
mounting.objectClass mustEqual ObjectClass.lightning_weapon_system
|
||||
mounting.guid mustEqual PlanetSideGUID(91)
|
||||
mounting.parentSlot mustEqual 1
|
||||
mounting.obj.isInstanceOf[WeaponData] mustEqual true
|
||||
val weapon = mounting.obj.asInstanceOf[WeaponData]
|
||||
weapon.unk1 mustEqual 0x4
|
||||
weapon.unk2 mustEqual 0x8
|
||||
weapon.fire_mode mustEqual 0
|
||||
weapon.ammo.size mustEqual 2
|
||||
//0
|
||||
var ammo = weapon.ammo.head
|
||||
ammo.objectClass mustEqual ObjectClass.bullet_75mm
|
||||
ammo.guid mustEqual PlanetSideGUID(92)
|
||||
ammo.parentSlot mustEqual 0
|
||||
ammo.obj.isInstanceOf[AmmoBoxData] mustEqual true
|
||||
ammo.obj.asInstanceOf[AmmoBoxData].unk mustEqual 0x0
|
||||
//1
|
||||
ammo = weapon.ammo(1)
|
||||
ammo.objectClass mustEqual ObjectClass.bullet_25mm
|
||||
ammo.guid mustEqual PlanetSideGUID(93)
|
||||
ammo.parentSlot mustEqual 1
|
||||
ammo.obj.isInstanceOf[AmmoBoxData] mustEqual true
|
||||
ammo.obj.asInstanceOf[AmmoBoxData].unk mustEqual 0x0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (medium transport)" in {
|
||||
PacketCoding.DecodePacket(string_mediumtransport).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 474L
|
||||
cls mustEqual ObjectClass.mediumtransport
|
||||
guid mustEqual PlanetSideGUID(387)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[VehicleData] mustEqual true
|
||||
val deliverer = data.get.asInstanceOf[VehicleData]
|
||||
deliverer.basic.pos.coord.x mustEqual 6531.961f
|
||||
deliverer.basic.pos.coord.y mustEqual 1872.1406f
|
||||
deliverer.basic.pos.coord.z mustEqual 24.734375f
|
||||
deliverer.basic.pos.orient.x mustEqual 0f
|
||||
deliverer.basic.pos.orient.y mustEqual 0f
|
||||
deliverer.basic.pos.orient.z mustEqual 357.1875f
|
||||
deliverer.basic.faction mustEqual PlanetSideEmpire.NC
|
||||
deliverer.basic.unk mustEqual 2
|
||||
deliverer.basic.player_guid mustEqual PlanetSideGUID(0)
|
||||
deliverer.unk1 mustEqual 0
|
||||
deliverer.health mustEqual 255
|
||||
deliverer.unk2 mustEqual false
|
||||
deliverer.driveState mustEqual DriveState.State7
|
||||
deliverer.unk3 mustEqual true
|
||||
deliverer.unk4 mustEqual None
|
||||
deliverer.unk5 mustEqual false
|
||||
deliverer.inventory.isDefined mustEqual true
|
||||
deliverer.inventory.get.contents.size mustEqual 2
|
||||
//0
|
||||
var mounting = deliverer.inventory.get.contents.head
|
||||
mounting.objectClass mustEqual ObjectClass.mediumtransport_weapon_systemA
|
||||
mounting.guid mustEqual PlanetSideGUID(383)
|
||||
mounting.parentSlot mustEqual 5
|
||||
mounting.obj.isInstanceOf[WeaponData] mustEqual true
|
||||
var weapon = mounting.obj.asInstanceOf[WeaponData]
|
||||
weapon.unk1 mustEqual 0x6
|
||||
weapon.unk2 mustEqual 0x8
|
||||
weapon.fire_mode mustEqual 0
|
||||
weapon.ammo.size mustEqual 1
|
||||
var ammo = weapon.ammo.head
|
||||
ammo.objectClass mustEqual ObjectClass.bullet_20mm
|
||||
ammo.guid mustEqual PlanetSideGUID(420)
|
||||
ammo.parentSlot mustEqual 0
|
||||
ammo.obj.isInstanceOf[AmmoBoxData] mustEqual true
|
||||
ammo.obj.asInstanceOf[AmmoBoxData].unk mustEqual 0x8
|
||||
//1
|
||||
mounting = deliverer.inventory.get.contents(1)
|
||||
mounting.objectClass mustEqual ObjectClass.mediumtransport_weapon_systemB
|
||||
mounting.guid mustEqual PlanetSideGUID(556)
|
||||
mounting.parentSlot mustEqual 6
|
||||
mounting.obj.isInstanceOf[WeaponData] mustEqual true
|
||||
weapon = mounting.obj.asInstanceOf[WeaponData]
|
||||
weapon.unk1 mustEqual 0x6
|
||||
weapon.unk2 mustEqual 0x8
|
||||
weapon.fire_mode mustEqual 0
|
||||
weapon.ammo.size mustEqual 1
|
||||
ammo = weapon.ammo.head
|
||||
ammo.objectClass mustEqual ObjectClass.bullet_20mm
|
||||
ammo.guid mustEqual PlanetSideGUID(575)
|
||||
ammo.parentSlot mustEqual 0
|
||||
ammo.obj.isInstanceOf[AmmoBoxData] mustEqual true
|
||||
ammo.obj.asInstanceOf[AmmoBoxData].unk mustEqual 0x8
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (ams)" in {
|
||||
PacketCoding.DecodePacket(string_ams).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 440L
|
||||
cls mustEqual ObjectClass.ams
|
||||
guid mustEqual PlanetSideGUID(4157)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[VehicleData] mustEqual true
|
||||
val ams = data.get.asInstanceOf[VehicleData]
|
||||
ams.basic.pos.coord.x mustEqual 3674.0f
|
||||
ams.basic.pos.coord.y mustEqual 2726.789f
|
||||
ams.basic.pos.coord.z mustEqual 91.15625f
|
||||
ams.basic.pos.orient.x mustEqual 0f
|
||||
ams.basic.pos.orient.y mustEqual 0f
|
||||
ams.basic.pos.orient.z mustEqual 90.0f
|
||||
ams.basic.faction mustEqual PlanetSideEmpire.VS
|
||||
ams.basic.unk mustEqual 0
|
||||
ams.basic.player_guid mustEqual PlanetSideGUID(34082)
|
||||
ams.unk1 mustEqual 2
|
||||
ams.health mustEqual 236
|
||||
ams.unk2 mustEqual false
|
||||
ams.driveState mustEqual DriveState.Deployed
|
||||
|
||||
ams.inventory.isDefined mustEqual true
|
||||
val inv = ams.inventory.get.contents
|
||||
inv.head.objectClass mustEqual ObjectClass.matrix_terminalc
|
||||
inv.head.guid mustEqual PlanetSideGUID(3663)
|
||||
inv.head.parentSlot mustEqual 1
|
||||
inv.head.obj.isInstanceOf[CommonTerminalData] mustEqual true
|
||||
inv(1).objectClass mustEqual ObjectClass.ams_respawn_tube
|
||||
inv(1).guid mustEqual PlanetSideGUID(3638)
|
||||
inv(1).parentSlot mustEqual 2
|
||||
inv(1).obj.isInstanceOf[CommonTerminalData] mustEqual true
|
||||
inv(2).objectClass mustEqual ObjectClass.order_terminala
|
||||
inv(2).guid mustEqual PlanetSideGUID(3827)
|
||||
inv(2).parentSlot mustEqual 3
|
||||
inv(2).obj.isInstanceOf[CommonTerminalData] mustEqual true
|
||||
inv(3).objectClass mustEqual ObjectClass.order_terminalb
|
||||
inv(3).guid mustEqual PlanetSideGUID(3556)
|
||||
inv(3).parentSlot mustEqual 4
|
||||
inv(3).obj.isInstanceOf[CommonTerminalData] mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (ams, destroyed)" in {
|
||||
PacketCoding.DecodePacket(string_ams_destroyed).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 141L
|
||||
cls mustEqual ObjectClass.ams_destroyed
|
||||
guid mustEqual PlanetSideGUID(4157)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[DestroyedVehicleData] mustEqual true
|
||||
val dams = data.get.asInstanceOf[DestroyedVehicleData]
|
||||
dams.pos.coord.x mustEqual 3674.0f
|
||||
dams.pos.coord.y mustEqual 2726.789f
|
||||
dams.pos.coord.z mustEqual 91.15625f
|
||||
dams.pos.orient.x mustEqual 0f
|
||||
dams.pos.orient.y mustEqual 0f
|
||||
dams.pos.orient.z mustEqual 90.0f
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (switchblade)" in {
|
||||
PacketCoding.DecodePacket(string_switchblade).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 403L
|
||||
cls mustEqual ObjectClass.switchblade
|
||||
guid mustEqual PlanetSideGUID(418)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[VehicleData] mustEqual true
|
||||
val switchblade = data.get.asInstanceOf[VehicleData]
|
||||
switchblade.basic.pos.coord.x mustEqual 6531.961f
|
||||
switchblade.basic.pos.coord.y mustEqual 1872.1406f
|
||||
switchblade.basic.pos.coord.z mustEqual 24.734375f
|
||||
switchblade.basic.pos.orient.x mustEqual 0f
|
||||
switchblade.basic.pos.orient.y mustEqual 0f
|
||||
switchblade.basic.pos.orient.z mustEqual 357.1875f
|
||||
switchblade.basic.faction mustEqual PlanetSideEmpire.VS
|
||||
switchblade.basic.unk mustEqual 2
|
||||
switchblade.health mustEqual 255
|
||||
switchblade.driveState mustEqual DriveState.Mobile
|
||||
switchblade.inventory.isDefined mustEqual true
|
||||
switchblade.inventory.get.contents.size mustEqual 1
|
||||
//0
|
||||
val weapon = switchblade.inventory.get.contents.head
|
||||
weapon.objectClass mustEqual ObjectClass.scythe
|
||||
weapon.guid mustEqual PlanetSideGUID(355)
|
||||
weapon.parentSlot mustEqual 1
|
||||
weapon.obj.asInstanceOf[WeaponData].unk1 mustEqual 0x6
|
||||
weapon.obj.asInstanceOf[WeaponData].unk2 mustEqual 0x8
|
||||
weapon.obj.asInstanceOf[WeaponData].ammo.size mustEqual 2
|
||||
//ammo-0
|
||||
var ammo = weapon.obj.asInstanceOf[WeaponData].ammo.head
|
||||
ammo.objectClass mustEqual ObjectClass.ancient_ammo_vehicle
|
||||
ammo.guid mustEqual PlanetSideGUID(366)
|
||||
ammo.parentSlot mustEqual 0
|
||||
ammo.obj.asInstanceOf[AmmoBoxData].unk mustEqual 0x8
|
||||
//ammo-1
|
||||
ammo = weapon.obj.asInstanceOf[WeaponData].ammo(1)
|
||||
ammo.objectClass mustEqual ObjectClass.ancient_ammo_vehicle
|
||||
ammo.guid mustEqual PlanetSideGUID(385)
|
||||
ammo.parentSlot mustEqual 1
|
||||
ammo.obj.asInstanceOf[AmmoBoxData].unk mustEqual 0x8
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (droppod)" in {
|
||||
PacketCoding.DecodePacket(string_droppod).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 193L
|
||||
cls mustEqual ObjectClass.droppod
|
||||
guid mustEqual PlanetSideGUID(3595)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[DroppodData] mustEqual true
|
||||
val droppod = data.get.asInstanceOf[DroppodData]
|
||||
droppod.basic.pos.coord.x mustEqual 5108.0f
|
||||
droppod.basic.pos.coord.y mustEqual 6164.0f
|
||||
droppod.basic.pos.coord.z mustEqual 1023.9844f
|
||||
droppod.basic.pos.orient.x mustEqual 0f
|
||||
droppod.basic.pos.orient.y mustEqual 0f
|
||||
droppod.basic.pos.orient.z mustEqual 90.0f
|
||||
droppod.basic.unk mustEqual 2
|
||||
droppod.basic.player_guid mustEqual PlanetSideGUID(0)
|
||||
droppod.burn mustEqual false
|
||||
droppod.health mustEqual 255
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (shuttle 1)" in {
|
||||
PacketCoding.DecodePacket(string_orbital_shuttle_1).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 130
|
||||
cls mustEqual ObjectClass.orbital_shuttle
|
||||
guid mustEqual PlanetSideGUID(1129)
|
||||
parent.isDefined mustEqual true
|
||||
parent.get.guid mustEqual PlanetSideGUID(786)
|
||||
parent.get.slot mustEqual 3
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[OrbitalShuttleData] mustEqual true
|
||||
data.get.asInstanceOf[OrbitalShuttleData].faction mustEqual PlanetSideEmpire.VS
|
||||
data.get.asInstanceOf[OrbitalShuttleData].pos.isDefined mustEqual false
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (shuttle 2)" in {
|
||||
PacketCoding.DecodePacket(string_orbital_shuttle_2).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 195
|
||||
cls mustEqual ObjectClass.orbital_shuttle
|
||||
guid mustEqual PlanetSideGUID(1127)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[OrbitalShuttleData] mustEqual true
|
||||
val shuttle = data.get.asInstanceOf[OrbitalShuttleData]
|
||||
shuttle.faction mustEqual PlanetSideEmpire.VS
|
||||
shuttle.pos.isDefined mustEqual true
|
||||
shuttle.pos.get.coord.x mustEqual 5610.0156f
|
||||
shuttle.pos.get.coord.y mustEqual 4255.258f
|
||||
shuttle.pos.get.coord.z mustEqual 134.1875f
|
||||
shuttle.pos.get.orient.x mustEqual 0f
|
||||
shuttle.pos.get.orient.y mustEqual 0f
|
||||
shuttle.pos.get.orient.z mustEqual 180.0f
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (fury)" in {
|
||||
val obj = VehicleData(
|
||||
CommonFieldData(
|
||||
PlacementData(6531.961f, 1872.1406f, 24.734375f, 0f, 0f, 357.1875f),
|
||||
PlanetSideEmpire.VS, 2
|
||||
),
|
||||
0,
|
||||
255,
|
||||
false, false,
|
||||
DriveState.Mobile,
|
||||
false, false, false,
|
||||
None,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.fury_weapon_systema, PlanetSideGUID(400), 1,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.hellfire_ammo, PlanetSideGUID(432), 0, AmmoBoxData(0x8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
val msg = ObjectCreateMessage(ObjectClass.fury, PlanetSideGUID(413), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_fury
|
||||
}
|
||||
|
||||
"encode (ant)" in {
|
||||
val obj = VehicleData(
|
||||
CommonFieldData(
|
||||
PlacementData(3674.8438f, 2726.789f, 91.15625f, 0f, 0f, 90.0f),
|
||||
PlanetSideEmpire.VS, 2
|
||||
),
|
||||
0,
|
||||
255,
|
||||
false, false,
|
||||
DriveState.Mobile,
|
||||
false, false, false,
|
||||
Some(UtilityVehicleData(0)),
|
||||
None
|
||||
)(VehicleFormat.Utility)
|
||||
val msg = ObjectCreateMessage(ObjectClass.ant, PlanetSideGUID(380), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_ant
|
||||
}
|
||||
|
||||
"encode (lightning)" in {
|
||||
val obj = VehicleData(
|
||||
CommonFieldData(
|
||||
PlacementData(3674.8438f, 2726.789f, 91.15625f, 0f, 0f, 90.0f),
|
||||
PlanetSideEmpire.VS, 2
|
||||
),
|
||||
0,
|
||||
255,
|
||||
false, false,
|
||||
DriveState.Mobile,
|
||||
false, false, false,
|
||||
None,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.lightning_weapon_system, PlanetSideGUID(91), 1,
|
||||
WeaponData(4, 8, 0, ObjectClass.bullet_75mm, PlanetSideGUID(92), 0, AmmoBoxData(), ObjectClass.bullet_25mm, PlanetSideGUID(93), 1, AmmoBoxData())
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
val msg = ObjectCreateMessage(ObjectClass.lightning, PlanetSideGUID(90), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_lightning
|
||||
}
|
||||
|
||||
"encode (medium transport)" in {
|
||||
val obj = VehicleData(
|
||||
CommonFieldData(
|
||||
PlacementData(6531.961f, 1872.1406f, 24.734375f, 0f, 0f, 357.1875f),
|
||||
PlanetSideEmpire.NC, 2
|
||||
),
|
||||
0,
|
||||
255,
|
||||
false, false,
|
||||
DriveState.State7,
|
||||
true, false, false,
|
||||
None,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.mediumtransport_weapon_systemA, PlanetSideGUID(383), 5,
|
||||
WeaponData(6, 8, ObjectClass.bullet_20mm, PlanetSideGUID(420), 0, AmmoBoxData(8))
|
||||
) ::
|
||||
InventoryItemData(ObjectClass.mediumtransport_weapon_systemB, PlanetSideGUID(556), 6,
|
||||
WeaponData(6, 8, ObjectClass.bullet_20mm, PlanetSideGUID(575), 0, AmmoBoxData(8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
val msg = ObjectCreateMessage(ObjectClass.mediumtransport, PlanetSideGUID(387), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_mediumtransport
|
||||
}
|
||||
|
||||
"encode (ams)" in {
|
||||
val obj = VehicleData(
|
||||
CommonFieldData(
|
||||
PlacementData(3674.0f, 2726.789f, 91.15625f, 0f, 0f, 90.0f),
|
||||
PlanetSideEmpire.VS, 0,
|
||||
PlanetSideGUID(34082)
|
||||
),
|
||||
2,
|
||||
236,
|
||||
false, false,
|
||||
DriveState.Deployed,
|
||||
false, true, true,
|
||||
Some(UtilityVehicleData(60)), //what does this mean?
|
||||
Some(InventoryData(List(
|
||||
InternalSlot(ObjectClass.matrix_terminalc, PlanetSideGUID(3663), 1, CommonTerminalData(PlanetSideEmpire.VS)),
|
||||
InternalSlot(ObjectClass.ams_respawn_tube, PlanetSideGUID(3638), 2, CommonTerminalData(PlanetSideEmpire.VS)),
|
||||
InternalSlot(ObjectClass.order_terminala, PlanetSideGUID(3827), 3, CommonTerminalData(PlanetSideEmpire.VS)),
|
||||
InternalSlot(ObjectClass.order_terminalb, PlanetSideGUID(3556), 4, CommonTerminalData(PlanetSideEmpire.VS))
|
||||
)))
|
||||
)(VehicleFormat.Utility)
|
||||
val msg = ObjectCreateMessage(ObjectClass.ams, PlanetSideGUID(4157), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_ams
|
||||
}
|
||||
|
||||
"encode (ams, destroyed)" in {
|
||||
val obj = DestroyedVehicleData(PlacementData(3674.0f, 2726.789f, 91.15625f, 0f, 0f, 90.0f))
|
||||
val msg = ObjectCreateMessage(ObjectClass.ams_destroyed, PlanetSideGUID(4157), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_ams_destroyed
|
||||
}
|
||||
|
||||
"encode (switchblade)" in {
|
||||
val obj = VehicleData(
|
||||
CommonFieldData(
|
||||
PlacementData(6531.961f, 1872.1406f, 24.734375f, 0f, 0f, 357.1875f),
|
||||
PlanetSideEmpire.VS,
|
||||
2
|
||||
),
|
||||
0,
|
||||
255,
|
||||
false, false,
|
||||
DriveState.Mobile,
|
||||
false, false, false,
|
||||
Some(VariantVehicleData(0)),
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.scythe, PlanetSideGUID(355), 1,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.ancient_ammo_vehicle, PlanetSideGUID(366), 0, AmmoBoxData(0x8), ObjectClass.ancient_ammo_vehicle, PlanetSideGUID(385), 1, AmmoBoxData(0x8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Variant)
|
||||
val msg = ObjectCreateMessage(ObjectClass.switchblade, PlanetSideGUID(418), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_switchblade
|
||||
}
|
||||
|
||||
"encode (droppod)" in {
|
||||
val obj = DroppodData(
|
||||
CommonFieldData(
|
||||
PlacementData(5108.0f, 6164.0f, 1023.9844f, 0f, 0f, 90.0f),
|
||||
PlanetSideEmpire.VS,
|
||||
2
|
||||
)
|
||||
)
|
||||
val msg = ObjectCreateMessage(ObjectClass.droppod, PlanetSideGUID(3595), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_droppod
|
||||
}
|
||||
|
||||
"encode (shuttle 1)" in {
|
||||
val obj = OrbitalShuttleData(PlanetSideEmpire.VS)
|
||||
val msg = ObjectCreateMessage(ObjectClass.orbital_shuttle, PlanetSideGUID(1129), ObjectCreateMessageParent(PlanetSideGUID(786), 3), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_orbital_shuttle_1
|
||||
}
|
||||
|
||||
"encode (shuttle 2)" in {
|
||||
val obj = OrbitalShuttleData(PlacementData(5610.0156f, 4255.258f, 134.1875f, 0f, 0f, 180.0f), PlanetSideEmpire.VS)
|
||||
val msg = ObjectCreateMessage(ObjectClass.orbital_shuttle, PlanetSideGUID(1127), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_orbital_shuttle_2
|
||||
}
|
||||
}
|
||||
77
common/src/test/scala/game/objectcreate/ACEDataTest.scala
Normal file
77
common/src/test/scala/game/objectcreate/ACEDataTest.scala
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreate
|
||||
|
||||
import net.psforever.packet.PacketCoding
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class ACEDataTest extends Specification {
|
||||
val string_ace_held = hex"17 76000000 0406900650C80480000000"
|
||||
val string_ace_dropped = hex"17 AF000000 90024113B329C5D5A2D1200005B440000000"
|
||||
|
||||
"ACEData" should {
|
||||
"decode (held)" in {
|
||||
PacketCoding.DecodePacket(string_ace_held).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 118
|
||||
cls mustEqual ObjectClass.ace
|
||||
guid mustEqual PlanetSideGUID(3173)
|
||||
parent.isDefined mustEqual true
|
||||
parent.get.guid mustEqual PlanetSideGUID(3336)
|
||||
parent.get.slot mustEqual 0
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[ACEData] mustEqual true
|
||||
val ace = data.get.asInstanceOf[ACEData]
|
||||
ace.unk1 mustEqual 4
|
||||
ace.unk2 mustEqual 8
|
||||
ace.unk3 mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (dropped)" in {
|
||||
PacketCoding.DecodePacket(string_ace_dropped).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 175
|
||||
cls mustEqual ObjectClass.ace
|
||||
guid mustEqual PlanetSideGUID(4388)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[DroppedItemData[_]] mustEqual true
|
||||
val drop = data.get.asInstanceOf[DroppedItemData[_]]
|
||||
drop.pos.coord.x mustEqual 4708.461f
|
||||
drop.pos.coord.y mustEqual 5547.539f
|
||||
drop.pos.coord.z mustEqual 72.703125f
|
||||
drop.pos.orient.x mustEqual 0f
|
||||
drop.pos.orient.y mustEqual 0f
|
||||
drop.pos.orient.z mustEqual 194.0625f
|
||||
drop.obj.isInstanceOf[ACEData] mustEqual true
|
||||
val ace = drop.obj.asInstanceOf[ACEData]
|
||||
ace.unk1 mustEqual 8
|
||||
ace.unk2 mustEqual 8
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (held)" in {
|
||||
val obj = ACEData(4, 8)
|
||||
val msg = ObjectCreateMessage(ObjectClass.ace, PlanetSideGUID(3173), ObjectCreateMessageParent(PlanetSideGUID(3336), 0), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string_ace_held
|
||||
}
|
||||
|
||||
"encode (dropped)" in {
|
||||
val obj = DroppedItemData(
|
||||
PlacementData(4708.461f, 5547.539f, 72.703125f, 0f, 0f, 194.0625f),
|
||||
ACEData(8, 8)
|
||||
)
|
||||
val msg = ObjectCreateMessage(ObjectClass.ace, PlanetSideGUID(4388), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string_ace_dropped
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreate
|
||||
|
||||
import net.psforever.packet.PacketCoding
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class AegisShieldGeneratorDataTest extends Specification {
|
||||
val string_aegis = hex"17 10010000 F80FC09 9DF96 0C676 801C 00 00 00 443E09FF0000000000000000000000000"
|
||||
|
||||
"AegisShieldGeneratorData" should {
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string_aegis).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 272
|
||||
cls mustEqual ObjectClass.deployable_shield_generator
|
||||
guid mustEqual PlanetSideGUID(2556)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[AegisShieldGeneratorData] mustEqual true
|
||||
val aegis = data.get.asInstanceOf[AegisShieldGeneratorData]
|
||||
aegis.deploy.pos.coord.x mustEqual 3571.2266f
|
||||
aegis.deploy.pos.coord.y mustEqual 3278.0938f
|
||||
aegis.deploy.pos.coord.z mustEqual 114.0f
|
||||
aegis.deploy.pos.orient.x mustEqual 0f
|
||||
aegis.deploy.pos.orient.y mustEqual 0f
|
||||
aegis.deploy.pos.orient.z mustEqual 90.0f
|
||||
aegis.deploy.faction mustEqual PlanetSideEmpire.VS
|
||||
aegis.deploy.unk mustEqual 2
|
||||
aegis.health mustEqual 255
|
||||
aegis.deploy.player_guid mustEqual PlanetSideGUID(2366)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val obj = AegisShieldGeneratorData(
|
||||
CommonFieldData(
|
||||
PlacementData(3571.2266f, 3278.0938f, 114.0f, 0f, 0f, 90.0f),
|
||||
PlanetSideEmpire.VS, 2, PlanetSideGUID(2366)
|
||||
),
|
||||
255
|
||||
)
|
||||
val msg = ObjectCreateMessage(ObjectClass.deployable_shield_generator, PlanetSideGUID(2556), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string_aegis
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreate
|
||||
|
||||
import net.psforever.packet.PacketCoding
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class AmmoBoxDataTest extends Specification {
|
||||
val string_shotgunshell_dropped = hex"17 A5000000 F9A7D0D 5E269 BED5A F114 0000596000000"
|
||||
|
||||
"AmmoBoxData" should {
|
||||
"decode (shotgun shells, dropped)" in {
|
||||
PacketCoding.DecodePacket(string_shotgunshell_dropped).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 165
|
||||
cls mustEqual ObjectClass.shotgun_shell
|
||||
guid mustEqual PlanetSideGUID(3453)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[DroppedItemData[_]] mustEqual true
|
||||
val drop = data.get.asInstanceOf[DroppedItemData[_]]
|
||||
drop.pos.coord.x mustEqual 4684.7344f
|
||||
drop.pos.coord.y mustEqual 5547.4844f
|
||||
drop.pos.coord.z mustEqual 83.765625f
|
||||
drop.pos.orient.x mustEqual 0f
|
||||
drop.pos.orient.y mustEqual 0f
|
||||
drop.pos.orient.z mustEqual 199.6875f
|
||||
drop.obj.isInstanceOf[AmmoBoxData] mustEqual true
|
||||
val box = drop.obj.asInstanceOf[AmmoBoxData]
|
||||
box.unk mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (shotgun shells, dropped)" in {
|
||||
val obj = DroppedItemData(
|
||||
PlacementData(4684.7344f, 5547.4844f, 83.765625f, 0f, 0f, 199.6875f),
|
||||
AmmoBoxData()
|
||||
)
|
||||
val msg = ObjectCreateMessage(ObjectClass.shotgun_shell, PlanetSideGUID(3453), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string_shotgunshell_dropped
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreate
|
||||
|
||||
import net.psforever.packet.PacketCoding
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class BoomerTriggerDataTest extends Specification {
|
||||
val string_boomertrigger = hex"17 76000000 58084A8100E80C00000000" //reconstructed from an inventory entry
|
||||
|
||||
"BoomerTriggerData" should {
|
||||
"decode (held)" in {
|
||||
PacketCoding.DecodePacket(string_boomertrigger).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 118
|
||||
cls mustEqual ObjectClass.boomer_trigger
|
||||
guid mustEqual PlanetSideGUID(3600)
|
||||
parent.isDefined mustEqual true
|
||||
parent.get.guid mustEqual PlanetSideGUID(4272)
|
||||
parent.get.slot mustEqual 0
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[BoomerTriggerData] mustEqual true
|
||||
data.get.asInstanceOf[BoomerTriggerData].unk mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (held)" in {
|
||||
val obj = BoomerTriggerData(0)
|
||||
val msg = ObjectCreateMessage(ObjectClass.boomer_trigger, PlanetSideGUID(3600), ObjectCreateMessageParent(PlanetSideGUID(4272), 0), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string_boomertrigger
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreate
|
||||
|
||||
import net.psforever.packet.PacketCoding
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class CaptureFlagDataTest extends Specification {
|
||||
val string_captureflag = hex"17 E5000000 CE8EA10 04A47 B818A FE0E 00 00 0F 24000015000400160B09000" //LLU for Qumu on Amerish
|
||||
|
||||
"CaptureFlagData" in {
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string_captureflag).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 229
|
||||
cls mustEqual ObjectClass.capture_flag
|
||||
guid mustEqual PlanetSideGUID(4330)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[CaptureFlagData] mustEqual true
|
||||
val flag = data.get.asInstanceOf[CaptureFlagData]
|
||||
flag.pos.coord.x mustEqual 3912.0312f
|
||||
flag.pos.coord.y mustEqual 5169.4375f
|
||||
flag.pos.coord.z mustEqual 59.96875f
|
||||
flag.pos.orient.x mustEqual 0f
|
||||
flag.pos.orient.y mustEqual 0f
|
||||
flag.pos.orient.z mustEqual 47.8125f
|
||||
flag.faction mustEqual PlanetSideEmpire.NC
|
||||
flag.unk1 mustEqual 21
|
||||
flag.unk2 mustEqual 4
|
||||
flag.unk3 mustEqual 2838
|
||||
flag.unk4 mustEqual 9
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val obj = CaptureFlagData(PlacementData(3912.0312f, 5169.4375f, 59.96875f, 0f, 0f, 47.8125f), PlanetSideEmpire.NC, 21, 4, 2838, 9)
|
||||
val msg = ObjectCreateMessage(ObjectClass.capture_flag, PlanetSideGUID(4330), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string_captureflag
|
||||
}
|
||||
}
|
||||
}
|
||||
282
common/src/test/scala/game/objectcreate/CharacterDataTest.scala
Normal file
282
common/src/test/scala/game/objectcreate/CharacterDataTest.scala
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreate
|
||||
|
||||
import net.psforever.packet.PacketCoding
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types._
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class CharacterDataTest extends Specification {
|
||||
val string_character = hex"17 73070000 BC8 3E0F 6C2D7 65535 CA16 00 00 09 9741E4F804000000 234530063007200610077006E00790052006F006E006E0069006500 220B7 E67B540404001000000000022B50100 268042006C00610063006B002000420065007200650074002000410072006D006F007500720065006400200043006F00720070007300 1700E0030050040003BC00000234040001A004000 3FFF67A8F A0A5424E0E800000000080952A9C3A03000001081103E040000000A023782F1080C0000016244108200000000808382403A030000014284C3A0C0000000202512F00B80C00000578F80F840000000280838B3C320300000080"
|
||||
val string_character_backpack = hex"17 9C030000 BC8 340D F20A9 3956C AF0D 00 00 73 480000 87041006E00670065006C006C006F00 4A148 0000000000000000000000005C54200 24404F0072006900670069006E0061006C00200044006900730074007200690063007400 1740180181E8000000C202000042000000D202000000010A3C00"
|
||||
|
||||
"CharacterData" should {
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string_character).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 1907
|
||||
cls mustEqual ObjectClass.avatar
|
||||
guid mustEqual PlanetSideGUID(3902)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[CharacterData] mustEqual true
|
||||
val pc = data.get.asInstanceOf[CharacterData]
|
||||
pc.appearance.pos.coord.x mustEqual 3674.8438f
|
||||
pc.appearance.pos.coord.y mustEqual 2726.789f
|
||||
pc.appearance.pos.coord.z mustEqual 91.15625f
|
||||
pc.appearance.pos.orient.x mustEqual 0f
|
||||
pc.appearance.pos.orient.y mustEqual 0f
|
||||
pc.appearance.pos.orient.z mustEqual 64.6875f
|
||||
pc.appearance.pos.vel.isDefined mustEqual true
|
||||
pc.appearance.pos.vel.get.x mustEqual 1.4375f
|
||||
pc.appearance.pos.vel.get.y mustEqual -0.4375f
|
||||
pc.appearance.pos.vel.get.z mustEqual 0f
|
||||
pc.appearance.basic_appearance.name mustEqual "ScrawnyRonnie"
|
||||
pc.appearance.basic_appearance.faction mustEqual PlanetSideEmpire.TR
|
||||
pc.appearance.basic_appearance.sex mustEqual CharacterGender.Male
|
||||
pc.appearance.basic_appearance.head mustEqual 5
|
||||
pc.appearance.basic_appearance.voice mustEqual 5
|
||||
pc.appearance.voice2 mustEqual 3
|
||||
pc.appearance.black_ops mustEqual false
|
||||
pc.appearance.jammered mustEqual false
|
||||
pc.appearance.exosuit mustEqual ExoSuitType.Reinforced
|
||||
pc.appearance.outfit_name mustEqual "Black Beret Armoured Corps"
|
||||
pc.appearance.outfit_logo mustEqual 23
|
||||
pc.appearance.facingPitch mustEqual 340.3125f
|
||||
pc.appearance.facingYawUpper mustEqual 0
|
||||
pc.appearance.lfs mustEqual false
|
||||
pc.appearance.grenade_state mustEqual GrenadeState.None
|
||||
pc.appearance.is_cloaking mustEqual false
|
||||
pc.appearance.charging_pose mustEqual false
|
||||
pc.appearance.on_zipline mustEqual false
|
||||
pc.appearance.ribbons.upper mustEqual MeritCommendation.MarkovVeteran
|
||||
pc.appearance.ribbons.middle mustEqual MeritCommendation.HeavyInfantry4
|
||||
pc.appearance.ribbons.lower mustEqual MeritCommendation.TankBuster7
|
||||
pc.appearance.ribbons.tos mustEqual MeritCommendation.SixYearTR
|
||||
pc.health mustEqual 255
|
||||
pc.armor mustEqual 253
|
||||
pc.uniform_upgrade mustEqual UniformStyle.ThirdUpgrade
|
||||
pc.command_rank mustEqual 5
|
||||
pc.implant_effects.isDefined mustEqual true
|
||||
pc.implant_effects.get mustEqual ImplantEffects.NoEffects
|
||||
pc.cosmetics.isDefined mustEqual true
|
||||
pc.cosmetics.get.no_helmet mustEqual true
|
||||
pc.cosmetics.get.beret mustEqual true
|
||||
pc.cosmetics.get.sunglasses mustEqual true
|
||||
pc.cosmetics.get.earpiece mustEqual true
|
||||
pc.cosmetics.get.brimmed_cap mustEqual false
|
||||
//short test of inventory items
|
||||
pc.inventory.isDefined mustEqual true
|
||||
val contents = pc.inventory.get.contents
|
||||
contents.size mustEqual 5
|
||||
//0
|
||||
contents.head.objectClass mustEqual ObjectClass.plasma_grenade
|
||||
contents.head.guid mustEqual PlanetSideGUID(3662)
|
||||
contents.head.parentSlot mustEqual 0
|
||||
contents.head.obj.asInstanceOf[WeaponData].fire_mode mustEqual 0
|
||||
contents.head.obj.asInstanceOf[WeaponData].ammo.head.objectClass mustEqual ObjectClass.plasma_grenade_ammo
|
||||
contents.head.obj.asInstanceOf[WeaponData].ammo.head.guid mustEqual PlanetSideGUID(3751)
|
||||
//1
|
||||
contents(1).objectClass mustEqual ObjectClass.bank
|
||||
contents(1).guid mustEqual PlanetSideGUID(3908)
|
||||
contents(1).parentSlot mustEqual 1
|
||||
contents(1).obj.asInstanceOf[WeaponData].fire_mode mustEqual 1
|
||||
contents(1).obj.asInstanceOf[WeaponData].ammo.head.objectClass mustEqual ObjectClass.armor_canister
|
||||
contents(1).obj.asInstanceOf[WeaponData].ammo.head.guid mustEqual PlanetSideGUID(4143)
|
||||
//2
|
||||
contents(2).objectClass mustEqual ObjectClass.mini_chaingun
|
||||
contents(2).guid mustEqual PlanetSideGUID(4164)
|
||||
contents(2).parentSlot mustEqual 2
|
||||
contents(2).obj.asInstanceOf[WeaponData].fire_mode mustEqual 0
|
||||
contents(2).obj.asInstanceOf[WeaponData].ammo.head.objectClass mustEqual ObjectClass.bullet_9mm
|
||||
contents(2).obj.asInstanceOf[WeaponData].ammo.head.guid mustEqual PlanetSideGUID(3728)
|
||||
//3
|
||||
contents(3).objectClass mustEqual ObjectClass.phoenix //actually, a decimator
|
||||
contents(3).guid mustEqual PlanetSideGUID(3603)
|
||||
contents(3).parentSlot mustEqual 3
|
||||
contents(3).obj.asInstanceOf[WeaponData].fire_mode mustEqual 0
|
||||
contents(3).obj.asInstanceOf[WeaponData].ammo.head.objectClass mustEqual ObjectClass.phoenix_missile
|
||||
contents(3).obj.asInstanceOf[WeaponData].ammo.head.guid mustEqual PlanetSideGUID(3056)
|
||||
//4
|
||||
contents(4).objectClass mustEqual ObjectClass.chainblade
|
||||
contents(4).guid mustEqual PlanetSideGUID(4088)
|
||||
contents(4).parentSlot mustEqual 4
|
||||
contents(4).obj.asInstanceOf[WeaponData].fire_mode mustEqual 1
|
||||
contents(4).obj.asInstanceOf[WeaponData].ammo.head.objectClass mustEqual ObjectClass.melee_ammo
|
||||
contents(4).obj.asInstanceOf[WeaponData].ammo.head.guid mustEqual PlanetSideGUID(3279)
|
||||
pc.drawn_slot mustEqual DrawnSlot.Rifle1
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (backpack)" in {
|
||||
PacketCoding.DecodePacket(string_character_backpack).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 924L
|
||||
cls mustEqual ObjectClass.avatar
|
||||
guid mustEqual PlanetSideGUID(3380)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[CharacterData] mustEqual true
|
||||
val pc = data.get.asInstanceOf[CharacterData]
|
||||
pc.appearance.pos.coord.x mustEqual 4629.8906f
|
||||
pc.appearance.pos.coord.y mustEqual 6316.4453f
|
||||
pc.appearance.pos.coord.z mustEqual 54.734375f
|
||||
pc.appearance.pos.orient.x mustEqual 0f
|
||||
pc.appearance.pos.orient.y mustEqual 0f
|
||||
pc.appearance.pos.orient.z mustEqual 126.5625f
|
||||
pc.appearance.pos.vel.isDefined mustEqual false
|
||||
pc.appearance.basic_appearance.name mustEqual "Angello"
|
||||
pc.appearance.basic_appearance.faction mustEqual PlanetSideEmpire.VS
|
||||
pc.appearance.basic_appearance.sex mustEqual CharacterGender.Male
|
||||
pc.appearance.basic_appearance.head mustEqual 10
|
||||
pc.appearance.basic_appearance.voice mustEqual 2
|
||||
pc.appearance.voice2 mustEqual 0
|
||||
pc.appearance.black_ops mustEqual false
|
||||
pc.appearance.jammered mustEqual false
|
||||
pc.appearance.exosuit mustEqual ExoSuitType.MAX
|
||||
pc.appearance.outfit_name mustEqual "Original District"
|
||||
pc.appearance.outfit_logo mustEqual 23
|
||||
pc.appearance.facingPitch mustEqual 0
|
||||
pc.appearance.facingYawUpper mustEqual 180.0f
|
||||
pc.appearance.lfs mustEqual false
|
||||
pc.appearance.grenade_state mustEqual GrenadeState.None
|
||||
pc.appearance.is_cloaking mustEqual false
|
||||
pc.appearance.charging_pose mustEqual false
|
||||
pc.appearance.on_zipline mustEqual false
|
||||
pc.appearance.ribbons.upper mustEqual MeritCommendation.Jacking2
|
||||
pc.appearance.ribbons.middle mustEqual MeritCommendation.ScavengerVS1
|
||||
pc.appearance.ribbons.lower mustEqual MeritCommendation.AMSSupport4
|
||||
pc.appearance.ribbons.tos mustEqual MeritCommendation.SixYearVS
|
||||
pc.health mustEqual 0
|
||||
pc.armor mustEqual 0
|
||||
pc.uniform_upgrade mustEqual UniformStyle.ThirdUpgrade
|
||||
pc.command_rank mustEqual 2
|
||||
pc.implant_effects.isDefined mustEqual false
|
||||
pc.cosmetics.isDefined mustEqual true
|
||||
pc.cosmetics.get.no_helmet mustEqual true
|
||||
pc.cosmetics.get.beret mustEqual true
|
||||
pc.cosmetics.get.sunglasses mustEqual true
|
||||
pc.cosmetics.get.earpiece mustEqual true
|
||||
pc.cosmetics.get.brimmed_cap mustEqual false
|
||||
pc.inventory.isDefined mustEqual false
|
||||
pc.drawn_slot mustEqual DrawnSlot.Pistol1
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val obj = CharacterData(
|
||||
CharacterAppearanceData(
|
||||
PlacementData(
|
||||
Vector3(3674.8438f, 2726.789f, 91.15625f),
|
||||
Vector3(0f, 0f, 64.6875f),
|
||||
Some(Vector3(1.4375f, -0.4375f, 0f))
|
||||
),
|
||||
BasicCharacterData(
|
||||
"ScrawnyRonnie",
|
||||
PlanetSideEmpire.TR,
|
||||
CharacterGender.Male,
|
||||
5,
|
||||
5
|
||||
),
|
||||
3,
|
||||
false,
|
||||
false,
|
||||
ExoSuitType.Reinforced,
|
||||
"Black Beret Armoured Corps",
|
||||
23,
|
||||
false,
|
||||
340.3125f, 0f,
|
||||
false,
|
||||
GrenadeState.None,
|
||||
false, false, false,
|
||||
RibbonBars(
|
||||
MeritCommendation.MarkovVeteran,
|
||||
MeritCommendation.HeavyInfantry4,
|
||||
MeritCommendation.TankBuster7,
|
||||
MeritCommendation.SixYearTR
|
||||
)
|
||||
),
|
||||
255, 253,
|
||||
UniformStyle.ThirdUpgrade,
|
||||
5,
|
||||
Some(ImplantEffects.NoEffects),
|
||||
Some(Cosmetics(true, true, true, true, false)),
|
||||
InventoryData(
|
||||
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
|
||||
)
|
||||
val msg = ObjectCreateMessage(ObjectClass.avatar, PlanetSideGUID(3902), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
val pkt_bitv = pkt.toBitVector
|
||||
val ori_bitv = string_character.toBitVector
|
||||
pkt_bitv.take(452) mustEqual ori_bitv.take(452) //skip 126
|
||||
pkt_bitv.drop(578).take(438) mustEqual ori_bitv.drop(578).take(438) //skip 2
|
||||
pkt_bitv.drop(1018).take(17) mustEqual ori_bitv.drop(1018).take(17) //skip 11
|
||||
pkt_bitv.drop(1046).take(147) mustEqual ori_bitv.drop(1046).take(147) //skip 3
|
||||
pkt_bitv.drop(1196) mustEqual ori_bitv.drop(1196)
|
||||
//TODO work on CharacterData to make this pass as a single stream
|
||||
}
|
||||
|
||||
"encode (backpack)" in {
|
||||
val obj = CharacterData(
|
||||
CharacterAppearanceData(
|
||||
PlacementData(4629.8906f, 6316.4453f, 54.734375f, 0f, 0f, 126.5625f),
|
||||
BasicCharacterData(
|
||||
"Angello",
|
||||
PlanetSideEmpire.VS,
|
||||
CharacterGender.Male,
|
||||
10,
|
||||
2
|
||||
),
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
ExoSuitType.MAX,
|
||||
"Original District",
|
||||
23,
|
||||
true, //backpack
|
||||
0f, 180.0f,
|
||||
false,
|
||||
GrenadeState.None,
|
||||
false, false, false,
|
||||
RibbonBars(
|
||||
MeritCommendation.Jacking2,
|
||||
MeritCommendation.ScavengerVS1,
|
||||
MeritCommendation.AMSSupport4,
|
||||
MeritCommendation.SixYearVS
|
||||
)
|
||||
),
|
||||
0, 0,
|
||||
UniformStyle.ThirdUpgrade,
|
||||
2,
|
||||
None,
|
||||
Some(Cosmetics(true, true, true, true, false)),
|
||||
None,
|
||||
DrawnSlot.Pistol1
|
||||
)
|
||||
val msg = ObjectCreateMessage(ObjectClass.avatar, PlanetSideGUID(3380), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
val pkt_bitv = pkt.toBitVector
|
||||
val ori_bitv = string_character_backpack.toBitVector
|
||||
pkt_bitv.take(300) mustEqual ori_bitv.take(300) //skip 2
|
||||
pkt_bitv.drop(302).take(14) mustEqual ori_bitv.drop(302).take(14) //skip 126
|
||||
pkt_bitv.drop(442).take(305) mustEqual ori_bitv.drop(442).take(305) //skip 1
|
||||
pkt_bitv.drop(748).take(9) mustEqual ori_bitv.drop(748).take(9) // skip 2
|
||||
pkt_bitv.drop(759).take(157) mustEqual ori_bitv.drop(759).take(157) //skip 1
|
||||
pkt_bitv.drop(917) mustEqual ori_bitv.drop(917)
|
||||
//TODO work on CharacterData to make this pass as a single stream
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreate
|
||||
|
||||
import net.psforever.packet.PacketCoding
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class CommandDetonaterDataTest extends Specification {
|
||||
val string_detonater_held = hex"17 76000000 1A886A8421080400000000"
|
||||
val string_detonater_dropped = hex"17 AF000000 EA8620ED1549B4B6A741500001B000000000"
|
||||
|
||||
"CommandDetonaterData" should {
|
||||
"decode (held)" in {
|
||||
PacketCoding.DecodePacket(string_detonater_held).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 118
|
||||
cls mustEqual ObjectClass.command_detonater
|
||||
guid mustEqual PlanetSideGUID(4162)
|
||||
parent.isDefined mustEqual true
|
||||
parent.get.guid mustEqual PlanetSideGUID(4149)
|
||||
parent.get.slot mustEqual 0
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[CommandDetonaterData] mustEqual true
|
||||
val cud = data.get.asInstanceOf[CommandDetonaterData]
|
||||
cud.unk1 mustEqual 4
|
||||
cud.unk2 mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (dropped)" in {
|
||||
PacketCoding.DecodePacket(string_detonater_dropped).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 175
|
||||
cls mustEqual ObjectClass.command_detonater
|
||||
guid mustEqual PlanetSideGUID(3682)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[DroppedItemData[_]] mustEqual true
|
||||
val drop = data.get.asInstanceOf[DroppedItemData[_]]
|
||||
drop.pos.coord.x mustEqual 4777.633f
|
||||
drop.pos.coord.y mustEqual 5485.4062f
|
||||
drop.pos.coord.z mustEqual 85.8125f
|
||||
drop.pos.orient.x mustEqual 0f
|
||||
drop.pos.orient.y mustEqual 0f
|
||||
drop.pos.orient.z mustEqual 14.0625f
|
||||
drop.obj.isInstanceOf[CommandDetonaterData] mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (held)" in {
|
||||
val obj = CommandDetonaterData(4)
|
||||
val msg = ObjectCreateMessage(ObjectClass.command_detonater, PlanetSideGUID(4162), ObjectCreateMessageParent(PlanetSideGUID(4149), 0), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string_detonater_held
|
||||
}
|
||||
|
||||
"encode (dropped)" in {
|
||||
val obj = DroppedItemData(
|
||||
PlacementData(4777.633f, 5485.4062f, 85.8125f, 0f, 0f, 14.0625f),
|
||||
CommandDetonaterData()
|
||||
)
|
||||
val msg = ObjectCreateMessage(ObjectClass.command_detonater, PlanetSideGUID(3682), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string_detonater_dropped
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreate
|
||||
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
import org.specs2.mutable._
|
||||
|
||||
class CommonFieldDataTest extends Specification {
|
||||
"CommonFieldData" should {
|
||||
"construct" in {
|
||||
CommonFieldData(PlacementData(0f, 0f, 0f), PlanetSideEmpire.NC, true, 5) mustEqual
|
||||
CommonFieldData(PlacementData(0f, 0f, 0f), PlanetSideEmpire.NC, false, true, 5, false, PlanetSideGUID(0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreate
|
||||
|
||||
import net.psforever.packet.PacketCoding
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class CommonTerminalDataTest extends Specification {
|
||||
val string_implant_interface = hex"17 6C000000 01014C93304818000000"
|
||||
val string_order_terminala = hex"17 A5000000 B2AF30EACF1889F7A3D1200007D2000000"
|
||||
|
||||
"CommonTerminalData" should {
|
||||
"decode (implant interface)" in {
|
||||
PacketCoding.DecodePacket(string_implant_interface).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 108
|
||||
cls mustEqual 0x199
|
||||
guid mustEqual PlanetSideGUID(1075)
|
||||
parent.isDefined mustEqual true
|
||||
parent.get.guid mustEqual PlanetSideGUID(514)
|
||||
parent.get.slot mustEqual 1
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[CommonTerminalData] mustEqual true
|
||||
data.get.asInstanceOf[CommonTerminalData].faction mustEqual PlanetSideEmpire.VS
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (order terminal a)" in {
|
||||
PacketCoding.DecodePacket(string_order_terminala).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 165
|
||||
cls mustEqual ObjectClass.order_terminala
|
||||
guid mustEqual PlanetSideGUID(3827)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[DroppedItemData[_]] mustEqual true
|
||||
val drop = data.get.asInstanceOf[DroppedItemData[_]]
|
||||
drop.pos.coord.x mustEqual 4579.3438f
|
||||
drop.pos.coord.y mustEqual 5615.0703f
|
||||
drop.pos.coord.z mustEqual 72.953125f
|
||||
drop.pos.orient.x mustEqual 0f
|
||||
drop.pos.orient.y mustEqual 0f
|
||||
drop.pos.orient.z mustEqual 98.4375f
|
||||
drop.obj.isInstanceOf[CommonTerminalData] mustEqual true
|
||||
val term = drop.obj.asInstanceOf[CommonTerminalData]
|
||||
term.faction mustEqual PlanetSideEmpire.NC
|
||||
term.unk mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (implant interface)" in {
|
||||
val obj = CommonTerminalData(PlanetSideEmpire.VS)
|
||||
val msg = ObjectCreateMessage(0x199, PlanetSideGUID(1075), ObjectCreateMessageParent(PlanetSideGUID(514), 1), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string_implant_interface
|
||||
}
|
||||
|
||||
"encode (order terminal a)" in {
|
||||
val obj = DroppedItemData(
|
||||
PlacementData(4579.3438f, 5615.0703f, 72.953125f, 0f, 0f, 98.4375f),
|
||||
CommonTerminalData(PlanetSideEmpire.NC)
|
||||
)
|
||||
val msg = ObjectCreateMessage(ObjectClass.order_terminala, PlanetSideGUID(3827), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string_order_terminala
|
||||
}
|
||||
|
||||
"InternalSlot" in {
|
||||
CommonTerminalData(ObjectClass.order_terminala, PlanetSideGUID(1), 1, CommonTerminalData(PlanetSideEmpire.NC)) mustEqual
|
||||
InternalSlot(ObjectClass.order_terminala, PlanetSideGUID(1), 1, CommonTerminalData(PlanetSideEmpire.NC))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreate
|
||||
|
||||
import net.psforever.packet.PacketCoding
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class LockerContainerDataTest extends Specification {
|
||||
val string_locker_container = hex"17 AF010000 E414C0C00000000000000000000600000818829DC2E030000000202378620D80C00000378FA0FADC000006F1FC199D800000"
|
||||
|
||||
"LockerContainerData" should {
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string_locker_container).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 431
|
||||
cls mustEqual ObjectClass.locker_container
|
||||
guid mustEqual PlanetSideGUID(3148)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[LockerContainerData] mustEqual true
|
||||
val locker = data.get.asInstanceOf[LockerContainerData]
|
||||
val contents = locker.inventory.contents
|
||||
contents.size mustEqual 3
|
||||
//0
|
||||
contents.head.objectClass mustEqual ObjectClass.nano_dispenser
|
||||
contents.head.guid mustEqual PlanetSideGUID(2935)
|
||||
contents.head.parentSlot mustEqual 0
|
||||
contents.head.obj.isInstanceOf[WeaponData] mustEqual true
|
||||
val dispenser = contents.head.obj.asInstanceOf[WeaponData]
|
||||
dispenser.unk1 mustEqual 0x6
|
||||
dispenser.unk2 mustEqual 0x0
|
||||
dispenser.ammo.head.objectClass mustEqual ObjectClass.armor_canister
|
||||
dispenser.ammo.head.guid mustEqual PlanetSideGUID(3426)
|
||||
dispenser.ammo.head.parentSlot mustEqual 0
|
||||
dispenser.ammo.head.obj.isInstanceOf[AmmoBoxData] mustEqual true
|
||||
dispenser.ammo.head.obj.asInstanceOf[AmmoBoxData].unk mustEqual 0
|
||||
//1
|
||||
contents(1).objectClass mustEqual ObjectClass.armor_canister
|
||||
contents(1).guid mustEqual PlanetSideGUID(4090)
|
||||
contents(1).parentSlot mustEqual 45
|
||||
contents(1).obj.isInstanceOf[AmmoBoxData] mustEqual true
|
||||
contents(1).obj.asInstanceOf[AmmoBoxData].unk mustEqual 0
|
||||
//2
|
||||
contents(2).objectClass mustEqual ObjectClass.armor_canister
|
||||
contents(2).guid mustEqual PlanetSideGUID(3326)
|
||||
contents(2).parentSlot mustEqual 78
|
||||
contents(2).obj.isInstanceOf[AmmoBoxData] mustEqual true
|
||||
contents(2).obj.asInstanceOf[AmmoBoxData].unk mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val obj = LockerContainerData(
|
||||
InventoryData(
|
||||
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
|
||||
)
|
||||
)
|
||||
val msg = ObjectCreateMessage(ObjectClass.locker_container, PlanetSideGUID(3148), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string_locker_container
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreate
|
||||
|
||||
import net.psforever.packet.PacketCoding
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class OneMannedFieldTurretDataTest extends Specification {
|
||||
val string_orion = hex"17 5E010000 D82640B 92F76 01D65 F611 00 00 5E 4400006304BFC1E4041826E1503900000010104CE704C06400000"
|
||||
|
||||
"OneMannedFieldTurretData" should {
|
||||
"decode (orion)" in {
|
||||
PacketCoding.DecodePacket(string_orion).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 350
|
||||
cls mustEqual ObjectClass.portable_manned_turret_vs
|
||||
guid mustEqual PlanetSideGUID(2916)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[OneMannedFieldTurretData] mustEqual true
|
||||
val omft = data.get.asInstanceOf[OneMannedFieldTurretData]
|
||||
omft.deploy.pos.coord.x mustEqual 3567.1406f
|
||||
omft.deploy.pos.coord.y mustEqual 2988.0078f
|
||||
omft.deploy.pos.coord.z mustEqual 71.84375f
|
||||
omft.deploy.pos.orient.x mustEqual 0f
|
||||
omft.deploy.pos.orient.y mustEqual 0f
|
||||
omft.deploy.pos.orient.z mustEqual 185.625f
|
||||
omft.deploy.faction mustEqual PlanetSideEmpire.VS
|
||||
omft.deploy.unk mustEqual 2
|
||||
omft.deploy.player_guid mustEqual PlanetSideGUID(2502)
|
||||
omft.health mustEqual 255
|
||||
omft.internals.isDefined mustEqual true
|
||||
val internals = omft.internals.get
|
||||
internals.objectClass mustEqual ObjectClass.energy_gun_vs
|
||||
internals.guid mustEqual PlanetSideGUID(2615)
|
||||
internals.parentSlot mustEqual 1
|
||||
internals.obj.isInstanceOf[WeaponData] mustEqual true
|
||||
val wep = internals.obj.asInstanceOf[WeaponData]
|
||||
wep.unk1 mustEqual 0x6
|
||||
wep.unk2 mustEqual 0x8
|
||||
wep.fire_mode mustEqual 0
|
||||
val ammo = wep.ammo.head
|
||||
ammo.objectClass mustEqual ObjectClass.energy_gun_ammo
|
||||
ammo.guid mustEqual PlanetSideGUID(2510)
|
||||
ammo.parentSlot mustEqual 0
|
||||
ammo.obj.isInstanceOf[AmmoBoxData] mustEqual true
|
||||
ammo.obj.asInstanceOf[AmmoBoxData].unk mustEqual 8
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (orion)" in {
|
||||
val obj = OneMannedFieldTurretData(
|
||||
CommonFieldData(
|
||||
PlacementData(3567.1406f, 2988.0078f, 71.84375f, 0f, 0f, 185.625f),
|
||||
PlanetSideEmpire.VS, 2, PlanetSideGUID(2502)
|
||||
),
|
||||
255,
|
||||
OneMannedFieldTurretData.orion(PlanetSideGUID(2615), 0x6, 0x8, PlanetSideGUID(2510), 8)
|
||||
)
|
||||
val msg = ObjectCreateMessage(ObjectClass.portable_manned_turret_vs, PlanetSideGUID(2916), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
val pkt_bitv = pkt.toBitVector
|
||||
val ori_bitv = string_orion.toBitVector
|
||||
pkt_bitv.take(189) mustEqual ori_bitv.take(189)
|
||||
pkt_bitv.drop(200) mustEqual ori_bitv.drop(200)
|
||||
//TODO work on OneMannedFieldTurretData to make this pass as a single stream
|
||||
}
|
||||
|
||||
"avenger" in {
|
||||
OneMannedFieldTurretData.avenger(PlanetSideGUID(1), 2, 3, PlanetSideGUID(4), 5) mustEqual
|
||||
InternalSlot(ObjectClass.energy_gun_tr, PlanetSideGUID(1), 1,
|
||||
WeaponData(2, 3, ObjectClass.energy_gun_ammo, PlanetSideGUID(4), 0,
|
||||
AmmoBoxData(5)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
"generic" in {
|
||||
OneMannedFieldTurretData.generic(PlanetSideGUID(1), 2, 3, PlanetSideGUID(4), 5) mustEqual
|
||||
InternalSlot(ObjectClass.energy_gun, PlanetSideGUID(1), 1,
|
||||
WeaponData(2, 3, ObjectClass.energy_gun_ammo, PlanetSideGUID(4), 0,
|
||||
AmmoBoxData(5)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
"orion" in {
|
||||
OneMannedFieldTurretData.orion(PlanetSideGUID(1), 2, 3, PlanetSideGUID(4), 5) mustEqual
|
||||
InternalSlot(ObjectClass.energy_gun_vs, PlanetSideGUID(1), 1,
|
||||
WeaponData(2, 3, ObjectClass.energy_gun_ammo, PlanetSideGUID(4), 0,
|
||||
AmmoBoxData(5)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
"osprey" in {
|
||||
OneMannedFieldTurretData.osprey(PlanetSideGUID(1), 2, 3, PlanetSideGUID(4), 5) mustEqual
|
||||
InternalSlot(ObjectClass.energy_gun_nc, PlanetSideGUID(1), 1,
|
||||
WeaponData(2, 3, ObjectClass.energy_gun_ammo, PlanetSideGUID(4), 0,
|
||||
AmmoBoxData(5)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
78
common/src/test/scala/game/objectcreate/REKDataTest.scala
Normal file
78
common/src/test/scala/game/objectcreate/REKDataTest.scala
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreate
|
||||
|
||||
import net.psforever.packet.PacketCoding
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class REKDataTest extends Specification {
|
||||
val string_rek_held = hex"17 86000000 27086C2350F800800000000000"
|
||||
val string_rek_dropped = hex"17 BF000000 EC20311 85219 7AC1A 2D12 00 00 4E 4000000001800"
|
||||
|
||||
"REKData" should {
|
||||
"decode (held)" in {
|
||||
PacketCoding.DecodePacket(string_rek_held).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 134
|
||||
cls mustEqual ObjectClass.remote_electronics_kit
|
||||
guid mustEqual PlanetSideGUID(3893)
|
||||
parent.isDefined mustEqual true
|
||||
parent.get.guid mustEqual PlanetSideGUID(4174)
|
||||
parent.get.slot mustEqual 0
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[REKData] mustEqual true
|
||||
val rek = data.get.asInstanceOf[REKData]
|
||||
rek.unk1 mustEqual 0
|
||||
rek.unk2 mustEqual 8
|
||||
rek.unk3 mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (dropped)" in {
|
||||
PacketCoding.DecodePacket(string_rek_dropped).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 191
|
||||
cls mustEqual ObjectClass.remote_electronics_kit
|
||||
guid mustEqual PlanetSideGUID(4355)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[DroppedItemData[_]] mustEqual true
|
||||
val dropped = data.get.asInstanceOf[DroppedItemData[_]]
|
||||
dropped.pos.coord.x mustEqual 4675.039f
|
||||
dropped.pos.coord.y mustEqual 5506.953f
|
||||
dropped.pos.coord.z mustEqual 72.703125f
|
||||
dropped.pos.orient.x mustEqual 0f
|
||||
dropped.pos.orient.y mustEqual 0f
|
||||
dropped.pos.orient.z mustEqual 230.625f
|
||||
dropped.obj.isInstanceOf[REKData] mustEqual true
|
||||
val rek = dropped.obj.asInstanceOf[REKData]
|
||||
rek.unk1 mustEqual 8
|
||||
rek.unk2 mustEqual 0
|
||||
rek.unk3 mustEqual 3
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (held)" in {
|
||||
val obj = REKData(0, 8)
|
||||
val msg = ObjectCreateMessage(ObjectClass.remote_electronics_kit, PlanetSideGUID(3893), ObjectCreateMessageParent(PlanetSideGUID(4174), 0), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string_rek_held
|
||||
}
|
||||
|
||||
"encode (dropped)" in {
|
||||
val obj = DroppedItemData(
|
||||
PlacementData(4675.039f, 5506.953f, 72.703125f, 0f, 0f, 230.625f),
|
||||
REKData(8, 0, 3)
|
||||
)
|
||||
val msg = ObjectCreateMessage(ObjectClass.remote_electronics_kit, PlanetSideGUID(4355), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string_rek_dropped
|
||||
}
|
||||
}
|
||||
}
|
||||
36
common/src/test/scala/game/objectcreate/RibbonBarsTest.scala
Normal file
36
common/src/test/scala/game/objectcreate/RibbonBarsTest.scala
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreate
|
||||
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types.MeritCommendation
|
||||
import org.specs2.mutable._
|
||||
|
||||
class RibbonBarsTest extends Specification {
|
||||
"RibbonBars" should {
|
||||
"construct" in {
|
||||
RibbonBars()
|
||||
ok
|
||||
}
|
||||
|
||||
"construct (custom)" in {
|
||||
RibbonBars(
|
||||
MeritCommendation.MarkovVeteran,
|
||||
MeritCommendation.HeavyInfantry4,
|
||||
MeritCommendation.TankBuster7,
|
||||
MeritCommendation.SixYearTR
|
||||
)
|
||||
ok
|
||||
}
|
||||
|
||||
"size" in {
|
||||
RibbonBars().bitsize mustEqual 128L
|
||||
|
||||
RibbonBars(
|
||||
MeritCommendation.MarkovVeteran,
|
||||
MeritCommendation.HeavyInfantry4,
|
||||
MeritCommendation.TankBuster7,
|
||||
MeritCommendation.SixYearTR
|
||||
).bitsize mustEqual 128L
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreate
|
||||
|
||||
import net.psforever.packet.PacketCoding
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class SmallDeployableDataTest extends Specification {
|
||||
val string_boomer = hex"17 A5000000 CA0000F1630938D5A8F1400003F0031100"
|
||||
|
||||
"SmallDeployableData" should {
|
||||
"decode (boomer)" in {
|
||||
PacketCoding.DecodePacket(string_boomer).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 165
|
||||
cls mustEqual ObjectClass.boomer
|
||||
guid mustEqual PlanetSideGUID(3840)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[SmallDeployableData] mustEqual true
|
||||
val boomer = data.get.asInstanceOf[SmallDeployableData]
|
||||
boomer.deploy.pos.coord.x mustEqual 4704.172f
|
||||
boomer.deploy.pos.coord.y mustEqual 5546.4375f
|
||||
boomer.deploy.pos.coord.z mustEqual 82.234375f
|
||||
boomer.deploy.pos.orient.x mustEqual 0f
|
||||
boomer.deploy.pos.orient.y mustEqual 0f
|
||||
boomer.deploy.pos.orient.z mustEqual 272.8125f
|
||||
boomer.deploy.unk mustEqual 0
|
||||
boomer.deploy.player_guid mustEqual PlanetSideGUID(4145)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (boomer)" in {
|
||||
val obj = SmallDeployableData(
|
||||
CommonFieldData(
|
||||
PlacementData(4704.172f, 5546.4375f, 82.234375f, 0f, 0f, 272.8125f),
|
||||
PlanetSideEmpire.TR, 0, PlanetSideGUID(4145)
|
||||
)
|
||||
)
|
||||
val msg = ObjectCreateMessage(ObjectClass.boomer, PlanetSideGUID(3840), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string_boomer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreate
|
||||
|
||||
import net.psforever.packet.PacketCoding
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class SmallTurretDataTest extends Specification {
|
||||
val string_spitfire_short = hex"17 BB000000 9D37010 E4F08 6AFCA 0312 00 7F 42 2C1F0F0000F00"
|
||||
val string_spitfire = hex"17 4F010000 9D3A910 D1D78 AE3FC 9111 00 00 69 4488107F80F2021DBF80B80C80000008086EDB83A03200000"
|
||||
|
||||
"SmallTurretData" should {
|
||||
"decode (spitfire, short)" in {
|
||||
PacketCoding.DecodePacket(string_spitfire_short).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 187
|
||||
cls mustEqual ObjectClass.spitfire_turret
|
||||
guid mustEqual PlanetSideGUID(4208)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[SmallTurretData] mustEqual true
|
||||
val turret = data.get.asInstanceOf[SmallTurretData]
|
||||
turret.deploy.pos.coord.x mustEqual 4577.7812f
|
||||
turret.deploy.pos.coord.y mustEqual 5624.828f
|
||||
turret.deploy.pos.coord.z mustEqual 72.046875f
|
||||
turret.deploy.pos.orient.x mustEqual 0f
|
||||
turret.deploy.pos.orient.y mustEqual 2.8125f
|
||||
turret.deploy.pos.orient.z mustEqual 264.375f
|
||||
turret.deploy.faction mustEqual PlanetSideEmpire.NC
|
||||
turret.deploy.destroyed mustEqual true
|
||||
turret.deploy.unk mustEqual 2
|
||||
turret.deploy.player_guid mustEqual PlanetSideGUID(3871)
|
||||
turret.health mustEqual 0
|
||||
turret.internals.isDefined mustEqual false
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (spitfire)" in {
|
||||
PacketCoding.DecodePacket(string_spitfire).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 335
|
||||
cls mustEqual ObjectClass.spitfire_turret
|
||||
guid mustEqual PlanetSideGUID(4265)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[SmallTurretData] mustEqual true
|
||||
val turret = data.get.asInstanceOf[SmallTurretData]
|
||||
turret.deploy.pos.coord.x mustEqual 4527.633f
|
||||
turret.deploy.pos.coord.y mustEqual 6271.3594f
|
||||
turret.deploy.pos.coord.z mustEqual 70.265625f
|
||||
turret.deploy.pos.orient.x mustEqual 0f
|
||||
turret.deploy.pos.orient.y mustEqual 0f
|
||||
turret.deploy.pos.orient.z mustEqual 154.6875f
|
||||
turret.deploy.faction mustEqual PlanetSideEmpire.VS
|
||||
turret.deploy.unk mustEqual 2
|
||||
turret.deploy.player_guid mustEqual PlanetSideGUID(4232)
|
||||
turret.health mustEqual 255
|
||||
turret.internals.isDefined mustEqual true
|
||||
val internals = turret.internals.get
|
||||
internals.objectClass mustEqual ObjectClass.spitfire_weapon
|
||||
internals.guid mustEqual PlanetSideGUID(3064)
|
||||
internals.parentSlot mustEqual 0
|
||||
internals.obj.isInstanceOf[WeaponData] mustEqual true
|
||||
val wep = internals.obj.asInstanceOf[WeaponData]
|
||||
wep.unk1 mustEqual 0x6
|
||||
wep.unk2 mustEqual 0x8
|
||||
wep.fire_mode mustEqual 0
|
||||
val ammo = wep.ammo.head
|
||||
ammo.objectClass mustEqual ObjectClass.spitfire_ammo
|
||||
ammo.guid mustEqual PlanetSideGUID(3694)
|
||||
ammo.parentSlot mustEqual 0
|
||||
ammo.obj.isInstanceOf[AmmoBoxData] mustEqual true
|
||||
ammo.obj.asInstanceOf[AmmoBoxData].unk mustEqual 8
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (spitfire, short)" in {
|
||||
val obj = SmallTurretData(
|
||||
CommonFieldData(
|
||||
PlacementData(4577.7812f, 5624.828f, 72.046875f, 0f, 2.8125f, 264.375f),
|
||||
PlanetSideEmpire.NC, true, 2, PlanetSideGUID(3871)
|
||||
),
|
||||
255 //sets to 0
|
||||
)
|
||||
val msg = ObjectCreateMessage(ObjectClass.spitfire_turret, PlanetSideGUID(4208), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
val pkt_bitv = pkt.toBitVector
|
||||
val ori_bitv = string_spitfire_short.toBitVector
|
||||
pkt_bitv.take(173) mustEqual ori_bitv.take(173)
|
||||
pkt_bitv.drop(185) mustEqual ori_bitv.drop(185)
|
||||
//TODO work on SmallTurretData to make this pass as a single stream
|
||||
}
|
||||
|
||||
"encode (spitfire)" in {
|
||||
val obj = SmallTurretData(
|
||||
CommonFieldData(
|
||||
PlacementData(4527.633f, 6271.3594f, 70.265625f, 0f, 0f, 154.6875f),
|
||||
PlanetSideEmpire.VS, 2, PlanetSideGUID(4232)
|
||||
),
|
||||
255,
|
||||
SmallTurretData.spitfire(PlanetSideGUID(3064), 0x6, 0x8, PlanetSideGUID(3694), 8)
|
||||
)
|
||||
val msg = ObjectCreateMessage(ObjectClass.spitfire_turret, PlanetSideGUID(4265), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
val pkt_bitv = pkt.toBitVector
|
||||
val ori_bitv = string_spitfire.toBitVector
|
||||
pkt_bitv.take(173) mustEqual ori_bitv.take(173)
|
||||
pkt_bitv.drop(185) mustEqual ori_bitv.drop(185)
|
||||
//TODO work on SmallTurretData to make this pass as a single stream
|
||||
}
|
||||
}
|
||||
}
|
||||
57
common/src/test/scala/game/objectcreate/TRAPDataTest.scala
Normal file
57
common/src/test/scala/game/objectcreate/TRAPDataTest.scala
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreate
|
||||
|
||||
import net.psforever.packet.PacketCoding
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class TRAPDataTest extends Specification {
|
||||
val string_trap = hex"17 BB000000 A8B630A 39FA6 FD666 801C 00 00 00 44C6097F80F00"
|
||||
|
||||
"TRAPData" should {
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string_trap).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 187
|
||||
cls mustEqual ObjectClass.tank_traps
|
||||
guid mustEqual PlanetSideGUID(2659)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[TRAPData] mustEqual true
|
||||
val trap = data.get.asInstanceOf[TRAPData]
|
||||
trap.deploy.pos.coord.x mustEqual 3572.4453f
|
||||
trap.deploy.pos.coord.y mustEqual 3277.9766f
|
||||
trap.deploy.pos.coord.z mustEqual 114.0f
|
||||
trap.deploy.pos.orient.x mustEqual 0f
|
||||
trap.deploy.pos.orient.y mustEqual 0f
|
||||
trap.deploy.pos.orient.z mustEqual 90.0f
|
||||
trap.deploy.faction mustEqual PlanetSideEmpire.VS
|
||||
trap.deploy.unk mustEqual 2
|
||||
trap.health mustEqual 255
|
||||
trap.deploy.player_guid mustEqual PlanetSideGUID(2502)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val obj = TRAPData(
|
||||
CommonFieldData(
|
||||
PlacementData(3572.4453f, 3277.9766f, 114.0f, 0f, 0f, 90.0f),
|
||||
PlanetSideEmpire.VS, 2, PlanetSideGUID(2502)
|
||||
),
|
||||
255
|
||||
)
|
||||
val msg = ObjectCreateMessage(ObjectClass.tank_traps, PlanetSideGUID(2659), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
val pkt_bitv = pkt.toBitVector
|
||||
val ori_bitv = string_trap.toBitVector
|
||||
pkt_bitv.take(173) mustEqual ori_bitv.take(173)
|
||||
pkt_bitv.drop(185) mustEqual ori_bitv.drop(185)
|
||||
//TODO work on TRAPData to make this pass as a single stream
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreate
|
||||
|
||||
import net.psforever.packet.PacketCoding
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
import net.psforever.packet.game.objectcreate.{ObjectClass, PlacementData, TrackedProjectileData}
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class TrackedProjectileDataTest extends Specification {
|
||||
val string_striker_projectile = hex"17 C5000000 A4B 009D 4C129 0CB0A 9814 00 F5 E3 040000666686400"
|
||||
|
||||
"TrackedProjectileData" should {
|
||||
"decode (striker projectile)" in {
|
||||
PacketCoding.DecodePacket(string_striker_projectile).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 197
|
||||
cls mustEqual ObjectClass.striker_missile_targeting_projectile
|
||||
guid mustEqual PlanetSideGUID(40192)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[TrackedProjectileData] mustEqual true
|
||||
val projectile = data.get.asInstanceOf[TrackedProjectileData]
|
||||
projectile.pos.coord.x mustEqual 4644.5938f
|
||||
projectile.pos.coord.y mustEqual 5472.0938f
|
||||
projectile.pos.coord.z mustEqual 82.375f
|
||||
projectile.pos.orient.x mustEqual 0f
|
||||
projectile.pos.orient.y mustEqual 30.9375f
|
||||
projectile.pos.orient.z mustEqual 171.5625f
|
||||
projectile.unk1 mustEqual 0
|
||||
projectile.unk2 mustEqual TrackedProjectileData.striker_missile_targetting_projectile_data
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (striker projectile)" in {
|
||||
val obj = TrackedProjectileData.striker(
|
||||
PlacementData(4644.5938f, 5472.0938f, 82.375f, 0f, 30.9375f, 171.5625f),
|
||||
0
|
||||
)
|
||||
val msg = ObjectCreateMessage(ObjectClass.striker_missile_targeting_projectile, PlanetSideGUID(40192), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt.toBitVector.take(132) mustEqual string_striker_projectile.toBitVector.take(132)
|
||||
pkt.toBitVector.drop(133).take(7) mustEqual string_striker_projectile.toBitVector.drop(133).take(7)
|
||||
pkt.toBitVector.drop(141) mustEqual string_striker_projectile.toBitVector.drop(141)
|
||||
}
|
||||
|
||||
"hunter_seeker" in {
|
||||
TrackedProjectileData.hunter_seeker(PlacementData(0f, 0f, 0f), 0) mustEqual
|
||||
TrackedProjectileData(PlacementData(0f, 0f, 0f), 0, TrackedProjectileData.hunter_seeker_missile_projectile_data)
|
||||
}
|
||||
|
||||
"oicw" in {
|
||||
TrackedProjectileData.oicw(PlacementData(0f, 0f, 0f), 0) mustEqual
|
||||
TrackedProjectileData(PlacementData(0f, 0f, 0f), 0, TrackedProjectileData.oicw_projectile_data)
|
||||
}
|
||||
|
||||
"starfire" in {
|
||||
TrackedProjectileData.starfire(PlacementData(0f, 0f, 0f), 0) mustEqual
|
||||
TrackedProjectileData(PlacementData(0f, 0f, 0f), 0, TrackedProjectileData.starfire_projectile_data)
|
||||
}
|
||||
|
||||
"striker" in {
|
||||
TrackedProjectileData.striker(PlacementData(0f, 0f, 0f), 0) mustEqual
|
||||
TrackedProjectileData(PlacementData(0f, 0f, 0f), 0, TrackedProjectileData.striker_missile_targetting_projectile_data)
|
||||
}
|
||||
}
|
||||
}
|
||||
192
common/src/test/scala/game/objectcreate/WeaponDataTest.scala
Normal file
192
common/src/test/scala/game/objectcreate/WeaponDataTest.scala
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreate
|
||||
|
||||
import net.psforever.packet.PacketCoding
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class WeaponDataTest extends Specification {
|
||||
val string_lasher_held = hex"17 BB000000 1688569D90B83 880000008082077036032000000"
|
||||
val string_punisher_held = hex"17 F6000000 0A06612331083 88000000810381383E03200003793287C0E400000"
|
||||
val string_lasher_dropped = hex"17 F4000000 D69020C 99299 85D0A 5F10 00 00 20 400000004041038819018000000"
|
||||
val string_punisher_dropped = hex"17 2F010000 E12A20B 915A9 28C9A 1412 00 00 33 200000004081C1901B01800001BCB5C2E07000000"
|
||||
|
||||
"WeaponData" should {
|
||||
"decode (lasher, held)" in {
|
||||
PacketCoding.DecodePacket(string_lasher_held).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 187
|
||||
cls mustEqual ObjectClass.lasher
|
||||
guid mustEqual PlanetSideGUID(3033)
|
||||
parent.isDefined mustEqual true
|
||||
parent.get.guid mustEqual PlanetSideGUID(4141)
|
||||
parent.get.slot mustEqual 3
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[WeaponData] mustEqual true
|
||||
val wep = data.get.asInstanceOf[WeaponData]
|
||||
wep.unk1 mustEqual 4
|
||||
wep.unk2 mustEqual 8
|
||||
wep.fire_mode mustEqual 0
|
||||
wep.ammo.head.objectClass mustEqual ObjectClass.energy_cell
|
||||
wep.ammo.head.guid mustEqual PlanetSideGUID(3548)
|
||||
wep.ammo.head.parentSlot mustEqual 0
|
||||
wep.ammo.head.obj.isInstanceOf[AmmoBoxData] mustEqual true
|
||||
val ammo = wep.ammo.head.obj.asInstanceOf[AmmoBoxData]
|
||||
ammo.unk mustEqual 8
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (punisher, held)" in {
|
||||
PacketCoding.DecodePacket(string_punisher_held).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 246
|
||||
cls mustEqual ObjectClass.punisher
|
||||
guid mustEqual PlanetSideGUID(4147)
|
||||
parent.isDefined mustEqual true
|
||||
parent.get.guid mustEqual PlanetSideGUID(3092)
|
||||
parent.get.slot mustEqual 3
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[WeaponData] mustEqual true
|
||||
val wep = data.get.asInstanceOf[WeaponData]
|
||||
wep.unk1 mustEqual 4
|
||||
wep.unk2 mustEqual 8
|
||||
wep.fire_mode mustEqual 0
|
||||
val ammo = wep.ammo
|
||||
ammo.size mustEqual 2
|
||||
//0
|
||||
ammo.head.objectClass mustEqual ObjectClass.bullet_9mm
|
||||
ammo.head.guid mustEqual PlanetSideGUID(3918)
|
||||
ammo.head.parentSlot mustEqual 0
|
||||
ammo.head.obj.isInstanceOf[AmmoBoxData] mustEqual true
|
||||
ammo.head.obj.asInstanceOf[AmmoBoxData].unk mustEqual 8
|
||||
//1
|
||||
ammo(1).objectClass mustEqual ObjectClass.rocket
|
||||
ammo(1).guid mustEqual PlanetSideGUID(3941)
|
||||
ammo(1).parentSlot mustEqual 1
|
||||
ammo(1).obj.isInstanceOf[AmmoBoxData] mustEqual true
|
||||
ammo(1).obj.asInstanceOf[AmmoBoxData].unk mustEqual 8
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (lasher, dropped)" in {
|
||||
PacketCoding.DecodePacket(string_lasher_dropped).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 244
|
||||
cls mustEqual ObjectClass.lasher
|
||||
guid mustEqual PlanetSideGUID(3074)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[DroppedItemData[_]] mustEqual true
|
||||
val drop = data.get.asInstanceOf[DroppedItemData[_]]
|
||||
drop.pos.coord.x mustEqual 4691.1953f
|
||||
drop.pos.coord.y mustEqual 5537.039f
|
||||
drop.pos.coord.z mustEqual 65.484375f
|
||||
drop.pos.orient.x mustEqual 0f
|
||||
drop.pos.orient.y mustEqual 0f
|
||||
drop.pos.orient.z mustEqual 0f
|
||||
drop.obj.isInstanceOf[WeaponData] mustEqual true
|
||||
val wep = drop.obj.asInstanceOf[WeaponData]
|
||||
wep.unk1 mustEqual 4
|
||||
wep.unk2 mustEqual 0
|
||||
wep.fire_mode mustEqual 0
|
||||
wep.ammo.head.objectClass mustEqual ObjectClass.energy_cell
|
||||
wep.ammo.head.guid mustEqual PlanetSideGUID(3268)
|
||||
wep.ammo.head.parentSlot mustEqual 0
|
||||
wep.ammo.head.obj.isInstanceOf[AmmoBoxData] mustEqual true
|
||||
val ammo = wep.ammo.head.obj.asInstanceOf[AmmoBoxData]
|
||||
ammo.unk mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (punisher, dropped)" in {
|
||||
PacketCoding.DecodePacket(string_punisher_dropped).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 303
|
||||
cls mustEqual ObjectClass.punisher
|
||||
guid mustEqual PlanetSideGUID(2978)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[DroppedItemData[_]] mustEqual true
|
||||
val drop = data.get.asInstanceOf[DroppedItemData[_]]
|
||||
drop.pos.coord.x mustEqual 4789.133f
|
||||
drop.pos.coord.y mustEqual 5522.3125f
|
||||
drop.pos.coord.z mustEqual 72.3125f
|
||||
drop.pos.orient.x mustEqual 0f
|
||||
drop.pos.orient.y mustEqual 0f
|
||||
drop.pos.orient.z mustEqual 306.5625f
|
||||
drop.obj.isInstanceOf[WeaponData] mustEqual true
|
||||
val wep = drop.obj.asInstanceOf[WeaponData]
|
||||
wep.unk1 mustEqual 2
|
||||
wep.unk2 mustEqual 0
|
||||
wep.fire_mode mustEqual 0
|
||||
val ammo = wep.ammo
|
||||
ammo.size mustEqual 2
|
||||
//0
|
||||
ammo.head.objectClass mustEqual ObjectClass.bullet_9mm
|
||||
ammo.head.guid mustEqual PlanetSideGUID(3528)
|
||||
ammo.head.parentSlot mustEqual 0
|
||||
ammo.head.obj.isInstanceOf[AmmoBoxData] mustEqual true
|
||||
ammo.head.obj.asInstanceOf[AmmoBoxData].unk mustEqual 0
|
||||
//1
|
||||
ammo(1).objectClass mustEqual ObjectClass.rocket
|
||||
ammo(1).guid mustEqual PlanetSideGUID(3031)
|
||||
ammo(1).parentSlot mustEqual 1
|
||||
ammo(1).obj.isInstanceOf[AmmoBoxData] mustEqual true
|
||||
ammo(1).obj.asInstanceOf[AmmoBoxData].unk mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (lasher, held)" in {
|
||||
val obj = WeaponData(4, 8, ObjectClass.energy_cell, PlanetSideGUID(3548), 0, AmmoBoxData(8))
|
||||
val msg = ObjectCreateMessage(ObjectClass.lasher, PlanetSideGUID(3033), ObjectCreateMessageParent(PlanetSideGUID(4141), 3), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string_lasher_held
|
||||
}
|
||||
|
||||
"encode (punisher, held)" in {
|
||||
val obj =
|
||||
WeaponData(4, 8, 0,
|
||||
AmmoBoxData(ObjectClass.bullet_9mm, PlanetSideGUID(3918), 0, AmmoBoxData(8)) ::
|
||||
AmmoBoxData(ObjectClass.rocket, PlanetSideGUID(3941), 1, AmmoBoxData(8)) ::
|
||||
Nil
|
||||
)(2)
|
||||
val msg = ObjectCreateMessage(ObjectClass.punisher, PlanetSideGUID(4147), ObjectCreateMessageParent(PlanetSideGUID(3092), 3), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string_punisher_held
|
||||
}
|
||||
|
||||
"encode (lasher, dropped)" in {
|
||||
val obj = DroppedItemData(
|
||||
PlacementData(4691.1953f, 5537.039f, 65.484375f, 0.0f, 0.0f, 0.0f),
|
||||
WeaponData(4, 0, ObjectClass.energy_cell, PlanetSideGUID(3268), 0, AmmoBoxData())
|
||||
)
|
||||
val msg = ObjectCreateMessage(ObjectClass.lasher, PlanetSideGUID(3074), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string_lasher_dropped
|
||||
}
|
||||
|
||||
"encode (punisher, dropped)" in {
|
||||
val obj = DroppedItemData(
|
||||
PlacementData(4789.133f, 5522.3125f, 72.3125f, 0f, 0f, 306.5625f),
|
||||
WeaponData(2, 0, 0,
|
||||
AmmoBoxData(ObjectClass.bullet_9mm, PlanetSideGUID(3528), 0, AmmoBoxData()) ::
|
||||
AmmoBoxData(ObjectClass.rocket, PlanetSideGUID(3031), 1, AmmoBoxData()) ::
|
||||
Nil
|
||||
)(2)
|
||||
)
|
||||
val msg = ObjectCreateMessage(ObjectClass.punisher, PlanetSideGUID(2978), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string_punisher_dropped
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreatedetailed
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game.{ObjectCreateDetailedMessage, _}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import scodec.bits._
|
||||
|
||||
class DetailedACEDataTest extends Specification {
|
||||
val string_ace = hex"18 87000000 1006 100 C70B 80 8800000200008"
|
||||
|
||||
"DetailedACEData" should {
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string_ace).require match {
|
||||
case ObjectCreateDetailedMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 135
|
||||
cls mustEqual ObjectClass.ace
|
||||
guid mustEqual PlanetSideGUID(3015)
|
||||
parent.isDefined mustEqual true
|
||||
parent.get.guid mustEqual PlanetSideGUID(3104)
|
||||
parent.get.slot mustEqual 0
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[DetailedACEData] mustEqual true
|
||||
data.get.asInstanceOf[DetailedACEData].unk mustEqual 8
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val obj = DetailedACEData(8)
|
||||
val msg = ObjectCreateDetailedMessage(ObjectClass.ace, PlanetSideGUID(3015), ObjectCreateMessageParent(PlanetSideGUID(3104), 0), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_ace
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreatedetailed
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game.{ObjectCreateDetailedMessage, _}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import scodec.bits._
|
||||
|
||||
class DetailedAmmoBoxDataTest extends Specification {
|
||||
val string_9mm = hex"18 7C000000 2580 0E0 0005 A1 C8000064000"
|
||||
|
||||
"DetailedAmmoBoxData" should {
|
||||
"decode (9mm)" in {
|
||||
PacketCoding.DecodePacket(string_9mm).require match {
|
||||
case ObjectCreateDetailedMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 124
|
||||
cls mustEqual ObjectClass.bullet_9mm
|
||||
guid mustEqual PlanetSideGUID(1280)
|
||||
parent.isDefined mustEqual true
|
||||
parent.get.guid mustEqual PlanetSideGUID(75)
|
||||
parent.get.slot mustEqual 33
|
||||
data.isDefined mustEqual true
|
||||
data.get.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 50
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (9mm)" in {
|
||||
val obj = DetailedAmmoBoxData(8, 50)
|
||||
val msg = ObjectCreateDetailedMessage(ObjectClass.bullet_9mm, PlanetSideGUID(1280), ObjectCreateMessageParent(PlanetSideGUID(75), 33), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_9mm
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreatedetailed
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game.{ObjectCreateDetailedMessage, _}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import scodec.bits._
|
||||
|
||||
class DetailedBoomerTriggerDataTest extends Specification {
|
||||
val string_boomer_trigger = hex"18 87000000 6304CA8760B 80 C800000200008"
|
||||
|
||||
"DetailedBoomerTriggerData" should {
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string_boomer_trigger).require match {
|
||||
case ObjectCreateDetailedMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 135
|
||||
cls mustEqual ObjectClass.boomer_trigger
|
||||
guid mustEqual PlanetSideGUID(2934)
|
||||
parent.isDefined mustEqual true
|
||||
parent.get.guid mustEqual PlanetSideGUID(2502)
|
||||
parent.get.slot mustEqual 0
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[DetailedBoomerTriggerData] mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val obj = DetailedBoomerTriggerData()
|
||||
val msg = ObjectCreateDetailedMessage(ObjectClass.boomer_trigger, PlanetSideGUID(2934), ObjectCreateMessageParent(PlanetSideGUID(2502), 0), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_boomer_trigger
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreatedetailed
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game.{ObjectCreateDetailedMessage, _}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import scodec.bits._
|
||||
|
||||
class DetailedCommandDetonaterDataTest extends Specification {
|
||||
val string_detonater = hex"18 87000000 6506 EA8 7420 80 8000000200008"
|
||||
|
||||
"DetailedCommandDetonaterData" should {
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string_detonater).require match {
|
||||
case ObjectCreateDetailedMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 135
|
||||
cls mustEqual ObjectClass.command_detonater
|
||||
guid mustEqual PlanetSideGUID(8308)
|
||||
parent.isDefined mustEqual true
|
||||
parent.get.guid mustEqual PlanetSideGUID(3530)
|
||||
parent.get.slot mustEqual 0
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[DetailedCommandDetonaterData] mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val obj = DetailedCommandDetonaterData()
|
||||
val msg = ObjectCreateDetailedMessage(ObjectClass.command_detonater, PlanetSideGUID(8308), ObjectCreateMessageParent(PlanetSideGUID(3530), 0), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string_detonater
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreatedetailed
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game.{ObjectCreateDetailedMessage, _}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import scodec.bits._
|
||||
|
||||
class DetailedREKDataTest extends Specification {
|
||||
val string_rek = hex"18 97000000 2580 6C2 9F05 81 48000002000080000"
|
||||
|
||||
"DetailedREKData" should {
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string_rek).require match {
|
||||
case ObjectCreateDetailedMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 151
|
||||
cls mustEqual ObjectClass.remote_electronics_kit
|
||||
guid mustEqual PlanetSideGUID(1439)
|
||||
parent.isDefined mustEqual true
|
||||
parent.get.guid mustEqual PlanetSideGUID(75)
|
||||
parent.get.slot mustEqual 1
|
||||
data.isDefined mustEqual true
|
||||
data.get.asInstanceOf[DetailedREKData].unk1 mustEqual 4
|
||||
data.get.asInstanceOf[DetailedREKData].unk2 mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val obj = DetailedREKData(4)
|
||||
val msg = ObjectCreateDetailedMessage(ObjectClass.remote_electronics_kit, PlanetSideGUID(1439), ObjectCreateMessageParent(PlanetSideGUID(75), 1), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_rek
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreatedetailed
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game.{ObjectCreateDetailedMessage, _}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import scodec.bits._
|
||||
|
||||
class DetailedWeaponDataTest extends Specification {
|
||||
val string_gauss = hex"18 DC000000 2580 2C9 B905 82 480000020000C04 1C00C0B0190000078000"
|
||||
val string_punisher = hex"18 27010000 2580 612 a706 82 080000020000c08 1c13a0d01900000780 13a4701a072000000800"
|
||||
|
||||
"DetailedWeaponData" should {
|
||||
"decode (gauss)" in {
|
||||
PacketCoding.DecodePacket(string_gauss).require match {
|
||||
case ObjectCreateDetailedMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 220
|
||||
cls mustEqual ObjectClass.gauss
|
||||
guid mustEqual PlanetSideGUID(1465)
|
||||
parent.isDefined mustEqual true
|
||||
parent.get.guid mustEqual PlanetSideGUID(75)
|
||||
parent.get.slot mustEqual 2
|
||||
data.isDefined mustEqual true
|
||||
val obj_wep = data.get.asInstanceOf[DetailedWeaponData]
|
||||
obj_wep.unk1 mustEqual 2
|
||||
obj_wep.unk2 mustEqual 8
|
||||
val obj_ammo = obj_wep.ammo
|
||||
obj_ammo.head.objectClass mustEqual 28
|
||||
obj_ammo.head.guid mustEqual PlanetSideGUID(1286)
|
||||
obj_ammo.head.parentSlot mustEqual 0
|
||||
obj_ammo.head.obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 30
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (punisher)" in {
|
||||
PacketCoding.DecodePacket(string_punisher).require match {
|
||||
case ObjectCreateDetailedMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 295
|
||||
cls mustEqual ObjectClass.punisher
|
||||
guid mustEqual PlanetSideGUID(1703)
|
||||
parent.isDefined mustEqual true
|
||||
parent.get.guid mustEqual PlanetSideGUID(75)
|
||||
parent.get.slot mustEqual 2
|
||||
data.isDefined mustEqual true
|
||||
val obj_wep = data.get.asInstanceOf[DetailedWeaponData]
|
||||
obj_wep.unk1 mustEqual 0
|
||||
obj_wep.unk2 mustEqual 8
|
||||
val obj_ammo = obj_wep.ammo
|
||||
obj_ammo.size mustEqual 2
|
||||
obj_ammo.head.objectClass mustEqual ObjectClass.bullet_9mm
|
||||
obj_ammo.head.guid mustEqual PlanetSideGUID(1693)
|
||||
obj_ammo.head.parentSlot mustEqual 0
|
||||
obj_ammo.head.obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 30
|
||||
obj_ammo(1).objectClass mustEqual ObjectClass.jammer_cartridge
|
||||
obj_ammo(1).guid mustEqual PlanetSideGUID(1564)
|
||||
obj_ammo(1).parentSlot mustEqual 1
|
||||
obj_ammo(1).obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 1
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (gauss)" in {
|
||||
val obj = DetailedWeaponData(2, 8, ObjectClass.bullet_9mm, PlanetSideGUID(1286), 0, DetailedAmmoBoxData(8, 30))
|
||||
val msg = ObjectCreateDetailedMessage(ObjectClass.gauss, PlanetSideGUID(1465), ObjectCreateMessageParent(PlanetSideGUID(75), 2), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_gauss
|
||||
}
|
||||
|
||||
"encode (punisher)" in {
|
||||
val obj = DetailedWeaponData(0, 8,
|
||||
DetailedAmmoBoxData(ObjectClass.bullet_9mm, PlanetSideGUID(1693), 0, DetailedAmmoBoxData(8, 30)) ::
|
||||
DetailedAmmoBoxData(ObjectClass.jammer_cartridge, PlanetSideGUID(1564), 1, DetailedAmmoBoxData(8, 1)) ::
|
||||
Nil
|
||||
)(2)
|
||||
val msg = ObjectCreateDetailedMessage(ObjectClass.punisher, PlanetSideGUID(1703), ObjectCreateMessageParent(PlanetSideGUID(75), 2), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_punisher
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreatevehicle
|
||||
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types._
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class DestroyedVehiclesTest extends Specification {
|
||||
val string_ams_destroyed = hex"17 8D000000 978 3D10 002D765535CA16000000 0"
|
||||
|
||||
"Destroyed vehicles" should {
|
||||
"decode (ams, destroyed)" in {
|
||||
PacketCoding.DecodePacket(string_ams_destroyed).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 141L
|
||||
cls mustEqual ObjectClass.ams_destroyed
|
||||
guid mustEqual PlanetSideGUID(4157)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[DestroyedVehicleData] mustEqual true
|
||||
val dams = data.get.asInstanceOf[DestroyedVehicleData]
|
||||
dams.pos.coord.x mustEqual 3674.0f
|
||||
dams.pos.coord.y mustEqual 2726.789f
|
||||
dams.pos.coord.z mustEqual 91.15625f
|
||||
dams.pos.orient.x mustEqual 0f
|
||||
dams.pos.orient.y mustEqual 0f
|
||||
dams.pos.orient.z mustEqual 90.0f
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (ams, destroyed)" in {
|
||||
val obj = DestroyedVehicleData(PlacementData(3674.0f, 2726.789f, 91.15625f, 0f, 0f, 90.0f))
|
||||
val msg = ObjectCreateMessage(ObjectClass.ams_destroyed, PlanetSideGUID(4157), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_ams_destroyed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreatevehicle
|
||||
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types._
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class NonstandardVehiclesTest extends Specification {
|
||||
val string_droppod = hex"17 C1000000 8110B0E00FA9000ACFFFF000000 4400007F83C0900"
|
||||
val string_orbital_shuttle_1 = hex"17 82000000 0901B026904838000001FE0700"
|
||||
val string_orbital_shuttle_2 = hex"17 C3000000 B02670402F5AA14F88C210000604000007F8FF03C0"
|
||||
|
||||
"Nonstandard vehicles" should {
|
||||
"decode (droppod)" in {
|
||||
PacketCoding.DecodePacket(string_droppod).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 193L
|
||||
cls mustEqual ObjectClass.droppod
|
||||
guid mustEqual PlanetSideGUID(3595)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[DroppodData] mustEqual true
|
||||
val droppod = data.get.asInstanceOf[DroppodData]
|
||||
droppod.basic.pos.coord.x mustEqual 5108.0f
|
||||
droppod.basic.pos.coord.y mustEqual 6164.0f
|
||||
droppod.basic.pos.coord.z mustEqual 1023.9844f
|
||||
droppod.basic.pos.orient.x mustEqual 0f
|
||||
droppod.basic.pos.orient.y mustEqual 0f
|
||||
droppod.basic.pos.orient.z mustEqual 90.0f
|
||||
droppod.basic.unk mustEqual 2
|
||||
droppod.basic.player_guid mustEqual PlanetSideGUID(0)
|
||||
droppod.burn mustEqual false
|
||||
droppod.health mustEqual 255
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (shuttle 1)" in {
|
||||
PacketCoding.DecodePacket(string_orbital_shuttle_1).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 130
|
||||
cls mustEqual ObjectClass.orbital_shuttle
|
||||
guid mustEqual PlanetSideGUID(1129)
|
||||
parent.isDefined mustEqual true
|
||||
parent.get.guid mustEqual PlanetSideGUID(786)
|
||||
parent.get.slot mustEqual 3
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[OrbitalShuttleData] mustEqual true
|
||||
data.get.asInstanceOf[OrbitalShuttleData].faction mustEqual PlanetSideEmpire.VS
|
||||
data.get.asInstanceOf[OrbitalShuttleData].pos.isDefined mustEqual false
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (shuttle 2)" in {
|
||||
PacketCoding.DecodePacket(string_orbital_shuttle_2).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 195
|
||||
cls mustEqual ObjectClass.orbital_shuttle
|
||||
guid mustEqual PlanetSideGUID(1127)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[OrbitalShuttleData] mustEqual true
|
||||
val shuttle = data.get.asInstanceOf[OrbitalShuttleData]
|
||||
shuttle.faction mustEqual PlanetSideEmpire.VS
|
||||
shuttle.pos.isDefined mustEqual true
|
||||
shuttle.pos.get.coord.x mustEqual 5610.0156f
|
||||
shuttle.pos.get.coord.y mustEqual 4255.258f
|
||||
shuttle.pos.get.coord.z mustEqual 134.1875f
|
||||
shuttle.pos.get.orient.x mustEqual 0f
|
||||
shuttle.pos.get.orient.y mustEqual 0f
|
||||
shuttle.pos.get.orient.z mustEqual 180.0f
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (droppod)" in {
|
||||
val obj = DroppodData(
|
||||
CommonFieldData(
|
||||
PlacementData(5108.0f, 6164.0f, 1023.9844f, 0f, 0f, 90.0f),
|
||||
PlanetSideEmpire.VS,
|
||||
2
|
||||
)
|
||||
)
|
||||
val msg = ObjectCreateMessage(ObjectClass.droppod, PlanetSideGUID(3595), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_droppod
|
||||
}
|
||||
|
||||
"encode (shuttle 1)" in {
|
||||
val obj = OrbitalShuttleData(PlanetSideEmpire.VS)
|
||||
val msg = ObjectCreateMessage(ObjectClass.orbital_shuttle, PlanetSideGUID(1129), ObjectCreateMessageParent(PlanetSideGUID(786), 3), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_orbital_shuttle_1
|
||||
}
|
||||
|
||||
"encode (shuttle 2)" in {
|
||||
val obj = OrbitalShuttleData(PlacementData(5610.0156f, 4255.258f, 134.1875f, 0f, 0f, 180.0f), PlanetSideEmpire.VS)
|
||||
val msg = ObjectCreateMessage(ObjectClass.orbital_shuttle, PlanetSideGUID(1127), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_orbital_shuttle_2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,255 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreatevehicle
|
||||
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types._
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class NormalVehiclesTest extends Specification {
|
||||
val string_fury = hex"17 50010000 A79 9D01 FBC1C 12A83 2F06 00 00 21 4400003FC00101140C800C0E40000004048F3600301900000"
|
||||
val string_lightning = hex"17 8b010000 df1 5a00 6c2d7 65535 ca16 00 00 00 4400003fc00101300ad8040c4000000408190b801018000002617402070000000"
|
||||
val string_mediumtransport = hex"17 DA010000 8A2 8301 FBC1C 12A83 2F06 00 00 21 2400003FC079020593F80C2E400000040410148030190000017458050D90000001010401F814064000000"
|
||||
|
||||
"Normal vehicles" should {
|
||||
"decode (fury)" in {
|
||||
PacketCoding.DecodePacket(string_fury).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 336
|
||||
cls mustEqual ObjectClass.fury
|
||||
guid mustEqual PlanetSideGUID(413)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[VehicleData] mustEqual true
|
||||
val fury = data.get.asInstanceOf[VehicleData]
|
||||
fury.basic.pos.coord.x mustEqual 6531.961f
|
||||
fury.basic.pos.coord.y mustEqual 1872.1406f
|
||||
fury.basic.pos.coord.z mustEqual 24.734375f
|
||||
fury.basic.pos.orient.x mustEqual 0f
|
||||
fury.basic.pos.orient.y mustEqual 0f
|
||||
fury.basic.pos.orient.z mustEqual 357.1875f
|
||||
fury.basic.pos.vel.isDefined mustEqual false
|
||||
fury.basic.faction mustEqual PlanetSideEmpire.VS
|
||||
fury.basic.unk mustEqual 2
|
||||
fury.basic.player_guid mustEqual PlanetSideGUID(0)
|
||||
fury.health mustEqual 255
|
||||
//
|
||||
fury.inventory.isDefined mustEqual true
|
||||
fury.inventory.get.contents.size mustEqual 1
|
||||
val mounting = fury.inventory.get.contents.head
|
||||
mounting.objectClass mustEqual ObjectClass.fury_weapon_systema
|
||||
mounting.guid mustEqual PlanetSideGUID(400)
|
||||
mounting.parentSlot mustEqual 1
|
||||
mounting.obj.isInstanceOf[WeaponData] mustEqual true
|
||||
val weapon = mounting.obj.asInstanceOf[WeaponData]
|
||||
weapon.unk1 mustEqual 0x6
|
||||
weapon.unk2 mustEqual 0x8
|
||||
weapon.fire_mode mustEqual 0
|
||||
weapon.ammo.size mustEqual 1
|
||||
val ammo = weapon.ammo.head
|
||||
ammo.objectClass mustEqual ObjectClass.hellfire_ammo
|
||||
ammo.guid mustEqual PlanetSideGUID(432)
|
||||
ammo.parentSlot mustEqual 0
|
||||
ammo.obj.isInstanceOf[AmmoBoxData] mustEqual true
|
||||
ammo.obj.asInstanceOf[AmmoBoxData].unk mustEqual 0x8
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (lightning)" in {
|
||||
PacketCoding.DecodePacket(string_lightning).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 395L
|
||||
cls mustEqual ObjectClass.lightning
|
||||
guid mustEqual PlanetSideGUID(90)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[VehicleData] mustEqual true
|
||||
val lightning = data.get.asInstanceOf[VehicleData]
|
||||
lightning.basic.pos.coord.x mustEqual 3674.8438f
|
||||
lightning.basic.pos.coord.y mustEqual 2726.789f
|
||||
lightning.basic.pos.coord.z mustEqual 91.15625f
|
||||
lightning.basic.pos.orient.x mustEqual 0f
|
||||
lightning.basic.pos.orient.y mustEqual 0f
|
||||
lightning.basic.pos.orient.z mustEqual 90.0f
|
||||
lightning.basic.faction mustEqual PlanetSideEmpire.VS
|
||||
lightning.basic.unk mustEqual 2
|
||||
lightning.basic.player_guid mustEqual PlanetSideGUID(0)
|
||||
lightning.health mustEqual 255
|
||||
lightning.inventory.isDefined mustEqual true
|
||||
lightning.inventory.get.contents.size mustEqual 1
|
||||
val mounting = lightning.inventory.get.contents.head
|
||||
mounting.objectClass mustEqual ObjectClass.lightning_weapon_system
|
||||
mounting.guid mustEqual PlanetSideGUID(91)
|
||||
mounting.parentSlot mustEqual 1
|
||||
mounting.obj.isInstanceOf[WeaponData] mustEqual true
|
||||
val weapon = mounting.obj.asInstanceOf[WeaponData]
|
||||
weapon.unk1 mustEqual 0x4
|
||||
weapon.unk2 mustEqual 0x8
|
||||
weapon.fire_mode mustEqual 0
|
||||
weapon.ammo.size mustEqual 2
|
||||
//0
|
||||
var ammo = weapon.ammo.head
|
||||
ammo.objectClass mustEqual ObjectClass.bullet_75mm
|
||||
ammo.guid mustEqual PlanetSideGUID(92)
|
||||
ammo.parentSlot mustEqual 0
|
||||
ammo.obj.isInstanceOf[AmmoBoxData] mustEqual true
|
||||
ammo.obj.asInstanceOf[AmmoBoxData].unk mustEqual 0x0
|
||||
//1
|
||||
ammo = weapon.ammo(1)
|
||||
ammo.objectClass mustEqual ObjectClass.bullet_25mm
|
||||
ammo.guid mustEqual PlanetSideGUID(93)
|
||||
ammo.parentSlot mustEqual 1
|
||||
ammo.obj.isInstanceOf[AmmoBoxData] mustEqual true
|
||||
ammo.obj.asInstanceOf[AmmoBoxData].unk mustEqual 0x0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (medium transport)" in {
|
||||
PacketCoding.DecodePacket(string_mediumtransport).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 474L
|
||||
cls mustEqual ObjectClass.mediumtransport
|
||||
guid mustEqual PlanetSideGUID(387)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[VehicleData] mustEqual true
|
||||
val deliverer = data.get.asInstanceOf[VehicleData]
|
||||
deliverer.basic.pos.coord.x mustEqual 6531.961f
|
||||
deliverer.basic.pos.coord.y mustEqual 1872.1406f
|
||||
deliverer.basic.pos.coord.z mustEqual 24.734375f
|
||||
deliverer.basic.pos.orient.x mustEqual 0f
|
||||
deliverer.basic.pos.orient.y mustEqual 0f
|
||||
deliverer.basic.pos.orient.z mustEqual 357.1875f
|
||||
deliverer.basic.faction mustEqual PlanetSideEmpire.NC
|
||||
deliverer.basic.unk mustEqual 2
|
||||
deliverer.basic.player_guid mustEqual PlanetSideGUID(0)
|
||||
deliverer.unk1 mustEqual 0
|
||||
deliverer.health mustEqual 255
|
||||
deliverer.unk2 mustEqual false
|
||||
deliverer.driveState mustEqual DriveState.State7
|
||||
deliverer.unk3 mustEqual true
|
||||
deliverer.unk4 mustEqual None
|
||||
deliverer.unk5 mustEqual false
|
||||
deliverer.inventory.isDefined mustEqual true
|
||||
deliverer.inventory.get.contents.size mustEqual 2
|
||||
//0
|
||||
var mounting = deliverer.inventory.get.contents.head
|
||||
mounting.objectClass mustEqual ObjectClass.mediumtransport_weapon_systemA
|
||||
mounting.guid mustEqual PlanetSideGUID(383)
|
||||
mounting.parentSlot mustEqual 5
|
||||
mounting.obj.isInstanceOf[WeaponData] mustEqual true
|
||||
var weapon = mounting.obj.asInstanceOf[WeaponData]
|
||||
weapon.unk1 mustEqual 0x6
|
||||
weapon.unk2 mustEqual 0x8
|
||||
weapon.fire_mode mustEqual 0
|
||||
weapon.ammo.size mustEqual 1
|
||||
var ammo = weapon.ammo.head
|
||||
ammo.objectClass mustEqual ObjectClass.bullet_20mm
|
||||
ammo.guid mustEqual PlanetSideGUID(420)
|
||||
ammo.parentSlot mustEqual 0
|
||||
ammo.obj.isInstanceOf[AmmoBoxData] mustEqual true
|
||||
ammo.obj.asInstanceOf[AmmoBoxData].unk mustEqual 0x8
|
||||
//1
|
||||
mounting = deliverer.inventory.get.contents(1)
|
||||
mounting.objectClass mustEqual ObjectClass.mediumtransport_weapon_systemB
|
||||
mounting.guid mustEqual PlanetSideGUID(556)
|
||||
mounting.parentSlot mustEqual 6
|
||||
mounting.obj.isInstanceOf[WeaponData] mustEqual true
|
||||
weapon = mounting.obj.asInstanceOf[WeaponData]
|
||||
weapon.unk1 mustEqual 0x6
|
||||
weapon.unk2 mustEqual 0x8
|
||||
weapon.fire_mode mustEqual 0
|
||||
weapon.ammo.size mustEqual 1
|
||||
ammo = weapon.ammo.head
|
||||
ammo.objectClass mustEqual ObjectClass.bullet_20mm
|
||||
ammo.guid mustEqual PlanetSideGUID(575)
|
||||
ammo.parentSlot mustEqual 0
|
||||
ammo.obj.isInstanceOf[AmmoBoxData] mustEqual true
|
||||
ammo.obj.asInstanceOf[AmmoBoxData].unk mustEqual 0x8
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (fury)" in {
|
||||
val obj = VehicleData(
|
||||
CommonFieldData(
|
||||
PlacementData(6531.961f, 1872.1406f, 24.734375f, 0f, 0f, 357.1875f),
|
||||
PlanetSideEmpire.VS, 2
|
||||
),
|
||||
0,
|
||||
255,
|
||||
false, false,
|
||||
DriveState.Mobile,
|
||||
false, false, false,
|
||||
None,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.fury_weapon_systema, PlanetSideGUID(400), 1,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.hellfire_ammo, PlanetSideGUID(432), 0, AmmoBoxData(0x8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
val msg = ObjectCreateMessage(ObjectClass.fury, PlanetSideGUID(413), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_fury
|
||||
}
|
||||
|
||||
"encode (lightning)" in {
|
||||
val obj = VehicleData(
|
||||
CommonFieldData(
|
||||
PlacementData(3674.8438f, 2726.789f, 91.15625f, 0f, 0f, 90.0f),
|
||||
PlanetSideEmpire.VS, 2
|
||||
),
|
||||
0,
|
||||
255,
|
||||
false, false,
|
||||
DriveState.Mobile,
|
||||
false, false, false,
|
||||
None,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.lightning_weapon_system, PlanetSideGUID(91), 1,
|
||||
WeaponData(4, 8, 0, ObjectClass.bullet_75mm, PlanetSideGUID(92), 0, AmmoBoxData(), ObjectClass.bullet_25mm, PlanetSideGUID(93), 1, AmmoBoxData())
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
val msg = ObjectCreateMessage(ObjectClass.lightning, PlanetSideGUID(90), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_lightning
|
||||
}
|
||||
|
||||
"encode (medium transport)" in {
|
||||
val obj = VehicleData(
|
||||
CommonFieldData(
|
||||
PlacementData(6531.961f, 1872.1406f, 24.734375f, 0f, 0f, 357.1875f),
|
||||
PlanetSideEmpire.NC, 2
|
||||
),
|
||||
0,
|
||||
255,
|
||||
false, false,
|
||||
DriveState.State7,
|
||||
true, false, false,
|
||||
None,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.mediumtransport_weapon_systemA, PlanetSideGUID(383), 5,
|
||||
WeaponData(6, 8, ObjectClass.bullet_20mm, PlanetSideGUID(420), 0, AmmoBoxData(8))
|
||||
) ::
|
||||
InventoryItemData(ObjectClass.mediumtransport_weapon_systemB, PlanetSideGUID(556), 6,
|
||||
WeaponData(6, 8, ObjectClass.bullet_20mm, PlanetSideGUID(575), 0, AmmoBoxData(8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
val msg = ObjectCreateMessage(ObjectClass.mediumtransport, PlanetSideGUID(387), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_mediumtransport
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreatevehicle
|
||||
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types._
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class UtilityVehiclesTest extends Specification {
|
||||
val string_ant = hex"17 C2000000 9E0 7C01 6C2D7 65535 CA16 00 00 00 4400003FC000000"
|
||||
val string_ams = hex"17 B8010000 970 3D10 002D765535CA16000000 402285BB0037E4100749E1D03000000620D83A0A00000195798741C00000332E40D84800000"
|
||||
|
||||
"Utility vehicles" should {
|
||||
"decode (ant)" in {
|
||||
PacketCoding.DecodePacket(string_ant).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 194L
|
||||
cls mustEqual ObjectClass.ant
|
||||
guid mustEqual PlanetSideGUID(380)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[VehicleData] mustEqual true
|
||||
val ant = data.get.asInstanceOf[VehicleData]
|
||||
ant.basic.pos.coord.x mustEqual 3674.8438f
|
||||
ant.basic.pos.coord.y mustEqual 2726.789f
|
||||
ant.basic.pos.coord.z mustEqual 91.15625f
|
||||
ant.basic.pos.orient.x mustEqual 0f
|
||||
ant.basic.pos.orient.y mustEqual 0f
|
||||
ant.basic.pos.orient.z mustEqual 90.0f
|
||||
ant.basic.faction mustEqual PlanetSideEmpire.VS
|
||||
ant.basic.unk mustEqual 2
|
||||
ant.basic.player_guid mustEqual PlanetSideGUID(0)
|
||||
ant.health mustEqual 255
|
||||
ant.driveState mustEqual DriveState.Mobile
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (ams)" in {
|
||||
PacketCoding.DecodePacket(string_ams).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 440L
|
||||
cls mustEqual ObjectClass.ams
|
||||
guid mustEqual PlanetSideGUID(4157)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[VehicleData] mustEqual true
|
||||
val ams = data.get.asInstanceOf[VehicleData]
|
||||
ams.basic.pos.coord.x mustEqual 3674.0f
|
||||
ams.basic.pos.coord.y mustEqual 2726.789f
|
||||
ams.basic.pos.coord.z mustEqual 91.15625f
|
||||
ams.basic.pos.orient.x mustEqual 0f
|
||||
ams.basic.pos.orient.y mustEqual 0f
|
||||
ams.basic.pos.orient.z mustEqual 90.0f
|
||||
ams.basic.faction mustEqual PlanetSideEmpire.VS
|
||||
ams.basic.unk mustEqual 0
|
||||
ams.basic.player_guid mustEqual PlanetSideGUID(34082)
|
||||
ams.unk1 mustEqual 2
|
||||
ams.health mustEqual 236
|
||||
ams.unk2 mustEqual false
|
||||
ams.driveState mustEqual DriveState.Deployed
|
||||
|
||||
ams.inventory.isDefined mustEqual true
|
||||
val inv = ams.inventory.get.contents
|
||||
inv.head.objectClass mustEqual ObjectClass.matrix_terminalc
|
||||
inv.head.guid mustEqual PlanetSideGUID(3663)
|
||||
inv.head.parentSlot mustEqual 1
|
||||
inv.head.obj.isInstanceOf[CommonTerminalData] mustEqual true
|
||||
inv(1).objectClass mustEqual ObjectClass.ams_respawn_tube
|
||||
inv(1).guid mustEqual PlanetSideGUID(3638)
|
||||
inv(1).parentSlot mustEqual 2
|
||||
inv(1).obj.isInstanceOf[CommonTerminalData] mustEqual true
|
||||
inv(2).objectClass mustEqual ObjectClass.order_terminala
|
||||
inv(2).guid mustEqual PlanetSideGUID(3827)
|
||||
inv(2).parentSlot mustEqual 3
|
||||
inv(2).obj.isInstanceOf[CommonTerminalData] mustEqual true
|
||||
inv(3).objectClass mustEqual ObjectClass.order_terminalb
|
||||
inv(3).guid mustEqual PlanetSideGUID(3556)
|
||||
inv(3).parentSlot mustEqual 4
|
||||
inv(3).obj.isInstanceOf[CommonTerminalData] mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (ant)" in {
|
||||
val obj = VehicleData(
|
||||
CommonFieldData(
|
||||
PlacementData(3674.8438f, 2726.789f, 91.15625f, 0f, 0f, 90.0f),
|
||||
PlanetSideEmpire.VS, 2
|
||||
),
|
||||
0,
|
||||
255,
|
||||
false, false,
|
||||
DriveState.Mobile,
|
||||
false, false, false,
|
||||
Some(UtilityVehicleData(0)),
|
||||
None
|
||||
)(VehicleFormat.Utility)
|
||||
val msg = ObjectCreateMessage(ObjectClass.ant, PlanetSideGUID(380), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_ant
|
||||
}
|
||||
|
||||
"encode (ams)" in {
|
||||
val obj = VehicleData(
|
||||
CommonFieldData(
|
||||
PlacementData(3674.0f, 2726.789f, 91.15625f, 0f, 0f, 90.0f),
|
||||
PlanetSideEmpire.VS, 0,
|
||||
PlanetSideGUID(34082)
|
||||
),
|
||||
2,
|
||||
236,
|
||||
false, false,
|
||||
DriveState.Deployed,
|
||||
false, true, true,
|
||||
Some(UtilityVehicleData(60)), //what does this mean?
|
||||
Some(InventoryData(List(
|
||||
InternalSlot(ObjectClass.matrix_terminalc, PlanetSideGUID(3663), 1, CommonTerminalData(PlanetSideEmpire.VS)),
|
||||
InternalSlot(ObjectClass.ams_respawn_tube, PlanetSideGUID(3638), 2, CommonTerminalData(PlanetSideEmpire.VS)),
|
||||
InternalSlot(ObjectClass.order_terminala, PlanetSideGUID(3827), 3, CommonTerminalData(PlanetSideEmpire.VS)),
|
||||
InternalSlot(ObjectClass.order_terminalb, PlanetSideGUID(3556), 4, CommonTerminalData(PlanetSideEmpire.VS))
|
||||
)))
|
||||
)(VehicleFormat.Utility)
|
||||
val msg = ObjectCreateMessage(ObjectClass.ams, PlanetSideGUID(4157), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_ams
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game.objectcreatevehicle
|
||||
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types._
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class VariantVehiclesTest extends Specification {
|
||||
val string_switchblade = hex"17 93010000 A7B A201 FBC1C12A832F06000021 4400003FC00001013AD3180C0E4000000408330DC03019000006620406072000000"
|
||||
|
||||
"Variant vehicles" should {
|
||||
"decode (switchblade)" in {
|
||||
PacketCoding.DecodePacket(string_switchblade).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 403L
|
||||
cls mustEqual ObjectClass.switchblade
|
||||
guid mustEqual PlanetSideGUID(418)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[VehicleData] mustEqual true
|
||||
val switchblade = data.get.asInstanceOf[VehicleData]
|
||||
switchblade.basic.pos.coord.x mustEqual 6531.961f
|
||||
switchblade.basic.pos.coord.y mustEqual 1872.1406f
|
||||
switchblade.basic.pos.coord.z mustEqual 24.734375f
|
||||
switchblade.basic.pos.orient.x mustEqual 0f
|
||||
switchblade.basic.pos.orient.y mustEqual 0f
|
||||
switchblade.basic.pos.orient.z mustEqual 357.1875f
|
||||
switchblade.basic.faction mustEqual PlanetSideEmpire.VS
|
||||
switchblade.basic.unk mustEqual 2
|
||||
switchblade.health mustEqual 255
|
||||
switchblade.driveState mustEqual DriveState.Mobile
|
||||
switchblade.inventory.isDefined mustEqual true
|
||||
switchblade.inventory.get.contents.size mustEqual 1
|
||||
//0
|
||||
val weapon = switchblade.inventory.get.contents.head
|
||||
weapon.objectClass mustEqual ObjectClass.scythe
|
||||
weapon.guid mustEqual PlanetSideGUID(355)
|
||||
weapon.parentSlot mustEqual 1
|
||||
weapon.obj.asInstanceOf[WeaponData].unk1 mustEqual 0x6
|
||||
weapon.obj.asInstanceOf[WeaponData].unk2 mustEqual 0x8
|
||||
weapon.obj.asInstanceOf[WeaponData].ammo.size mustEqual 2
|
||||
//ammo-0
|
||||
var ammo = weapon.obj.asInstanceOf[WeaponData].ammo.head
|
||||
ammo.objectClass mustEqual ObjectClass.ancient_ammo_vehicle
|
||||
ammo.guid mustEqual PlanetSideGUID(366)
|
||||
ammo.parentSlot mustEqual 0
|
||||
ammo.obj.asInstanceOf[AmmoBoxData].unk mustEqual 0x8
|
||||
//ammo-1
|
||||
ammo = weapon.obj.asInstanceOf[WeaponData].ammo(1)
|
||||
ammo.objectClass mustEqual ObjectClass.ancient_ammo_vehicle
|
||||
ammo.guid mustEqual PlanetSideGUID(385)
|
||||
ammo.parentSlot mustEqual 1
|
||||
ammo.obj.asInstanceOf[AmmoBoxData].unk mustEqual 0x8
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (switchblade)" in {
|
||||
val obj = VehicleData(
|
||||
CommonFieldData(
|
||||
PlacementData(6531.961f, 1872.1406f, 24.734375f, 0f, 0f, 357.1875f),
|
||||
PlanetSideEmpire.VS,
|
||||
2
|
||||
),
|
||||
0,
|
||||
255,
|
||||
false, false,
|
||||
DriveState.Mobile,
|
||||
false, false, false,
|
||||
Some(VariantVehicleData(0)),
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.scythe, PlanetSideGUID(355), 1,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.ancient_ammo_vehicle, PlanetSideGUID(366), 0, AmmoBoxData(0x8), ObjectClass.ancient_ammo_vehicle, PlanetSideGUID(385), 1, AmmoBoxData(0x8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Variant)
|
||||
val msg = ObjectCreateMessage(ObjectClass.switchblade, PlanetSideGUID(418), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_switchblade
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -149,7 +149,8 @@ class ConverterTest extends Specification {
|
|||
val tool = Tool(tdef)
|
||||
tool.GUID = PlanetSideGUID(92)
|
||||
tool.AmmoSlot.Box.GUID = PlanetSideGUID(90)
|
||||
val obj = Player(PlanetSideGUID(93), "Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
val obj = Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
obj.GUID = PlanetSideGUID(93)
|
||||
obj.Slot(2).Equipment = tool
|
||||
obj.Slot(5).Equipment.get.GUID = PlanetSideGUID(94)
|
||||
obj.Inventory += 8 -> AmmoBox(GlobalDefinitions.bullet_9mm)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,21 @@ import net.psforever.objects.GlobalDefinitions._
|
|||
import org.specs2.mutable._
|
||||
|
||||
class EquipmentTest extends Specification {
|
||||
"EquipmentSize" should {
|
||||
"equal" in {
|
||||
//basic equality
|
||||
EquipmentSize.isEqual(EquipmentSize.Pistol, EquipmentSize.Pistol) mustEqual true
|
||||
EquipmentSize.isEqual(EquipmentSize.Pistol, EquipmentSize.Rifle) mustEqual false
|
||||
//Inventory is always allowed
|
||||
EquipmentSize.isEqual(EquipmentSize.Inventory, EquipmentSize.Rifle) mustEqual true
|
||||
EquipmentSize.isEqual(EquipmentSize.Pistol, EquipmentSize.Inventory) mustEqual true
|
||||
//Blocked is never allowed
|
||||
EquipmentSize.isEqual(EquipmentSize.Blocked, EquipmentSize.Rifle) mustEqual false
|
||||
EquipmentSize.isEqual(EquipmentSize.Pistol, EquipmentSize.Blocked) mustEqual false
|
||||
EquipmentSize.isEqual(EquipmentSize.Blocked, EquipmentSize.Inventory) mustEqual false
|
||||
}
|
||||
}
|
||||
|
||||
"AmmoBox" should {
|
||||
"define" in {
|
||||
val obj = AmmoBoxDefinition(86)
|
||||
|
|
@ -59,13 +74,13 @@ class EquipmentTest extends Specification {
|
|||
obj.Size = EquipmentSize.Rifle
|
||||
obj.AmmoTypes += GlobalDefinitions.shotgun_shell
|
||||
obj.AmmoTypes += GlobalDefinitions.shotgun_shell_AP
|
||||
obj.FireModes += new FireModeDefinition
|
||||
obj.FireModes += 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 += FireModeDefinition()
|
||||
obj.FireModes(1).AmmoTypeIndices += 0
|
||||
obj.FireModes(1).AmmoTypeIndices += 1
|
||||
obj.FireModes(1).AmmoSlotIndex = 1
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects.{Player, SimpleItem}
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.definition.{ImplantDefinition, SimpleItemDefinition}
|
||||
import net.psforever.objects.equipment.EquipmentSize
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.types.{CharacterGender, ExoSuitType, ImplantType, PlanetSideEmpire}
|
||||
import org.specs2.mutable._
|
||||
|
||||
|
|
@ -13,17 +14,55 @@ class PlayerTest extends Specification {
|
|||
obj.isAlive mustEqual false
|
||||
}
|
||||
|
||||
"different players" in {
|
||||
(Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5) ==
|
||||
Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)) mustEqual true
|
||||
(Player("Chord1", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5) ==
|
||||
Player("Chord2", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)) mustEqual false
|
||||
(Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5) ==
|
||||
Player("Chord", PlanetSideEmpire.NC, CharacterGender.Male, 0, 5)) mustEqual false
|
||||
(Player("Chord1", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5) ==
|
||||
Player("Chord2", PlanetSideEmpire.TR, CharacterGender.Female, 0, 5)) mustEqual false
|
||||
(Player("Chord1", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5) ==
|
||||
Player("Chord2", PlanetSideEmpire.TR, CharacterGender.Male, 1, 5)) mustEqual false
|
||||
(Player("Chord1", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5) ==
|
||||
Player("Chord2", PlanetSideEmpire.TR, CharacterGender.Male, 0, 6)) mustEqual false
|
||||
}
|
||||
|
||||
"become a backpack" in {
|
||||
val obj = new Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
obj.isAlive mustEqual false
|
||||
obj.isBackpack mustEqual false
|
||||
obj.Release
|
||||
obj.isAlive mustEqual false
|
||||
obj.isBackpack mustEqual true
|
||||
}
|
||||
|
||||
"(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.MaxHealth mustEqual 100
|
||||
obj.MaxStamina mustEqual 100
|
||||
obj.MaxArmor mustEqual 50
|
||||
obj.Spawn
|
||||
obj.isAlive mustEqual true
|
||||
obj.Health mustEqual obj.MaxHealth
|
||||
obj.Stamina mustEqual obj.MaxStamina
|
||||
obj.Armor mustEqual obj.MaxArmor
|
||||
obj.Health mustEqual 100
|
||||
obj.Stamina mustEqual 100
|
||||
obj.Armor mustEqual 50
|
||||
}
|
||||
|
||||
"set new maximum values (health, stamina)" in {
|
||||
val obj = new Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
obj.MaxHealth mustEqual 100
|
||||
obj.MaxStamina mustEqual 100
|
||||
obj.MaxHealth = 123
|
||||
obj.MaxStamina = 456
|
||||
obj.Spawn
|
||||
obj.Health mustEqual 123
|
||||
obj.Stamina mustEqual 456
|
||||
}
|
||||
|
||||
"init (Standard Exo-Suit)" in {
|
||||
|
|
@ -106,6 +145,40 @@ class PlayerTest extends Specification {
|
|||
obj.LastDrawnSlot mustEqual 1
|
||||
}
|
||||
|
||||
"hold something in their free hand" in {
|
||||
val wep = SimpleItem(SimpleItemDefinition(149))
|
||||
val obj = new Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
obj.Slot(Player.FreeHandSlot).Equipment = wep
|
||||
|
||||
obj.Slot(Player.FreeHandSlot).Equipment.get.Definition.ObjectId mustEqual 149
|
||||
}
|
||||
|
||||
"provide an invalid hand that can not hold anything" in {
|
||||
val wep = SimpleItem(SimpleItemDefinition(149))
|
||||
val obj = new Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
obj.Slot(-1).Equipment = wep
|
||||
|
||||
obj.Slot(-1).Equipment mustEqual None
|
||||
}
|
||||
|
||||
"search for the smallest available slot in which to satore equipment" in {
|
||||
val obj = new Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
obj.Inventory.Resize(3,3)
|
||||
|
||||
obj.Fit(Tool(GlobalDefinitions.beamer)) mustEqual Some(0)
|
||||
|
||||
obj.Fit(Tool(GlobalDefinitions.suppressor)) mustEqual Some(2)
|
||||
|
||||
val ammo = AmmoBox(GlobalDefinitions.bullet_9mm)
|
||||
val ammo2 = AmmoBox(GlobalDefinitions.bullet_9mm)
|
||||
val ammo3 = AmmoBox(GlobalDefinitions.bullet_9mm)
|
||||
obj.Fit(ammo) mustEqual Some(6)
|
||||
obj.Slot(6).Equipment = ammo
|
||||
obj.Fit(ammo2) mustEqual Some(Player.FreeHandSlot)
|
||||
obj.Slot(Player.FreeHandSlot).Equipment = ammo2
|
||||
obj.Fit(ammo2) mustEqual None
|
||||
}
|
||||
|
||||
"install an implant" in {
|
||||
val testplant : ImplantDefinition = ImplantDefinition(1)
|
||||
val obj = new Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
|
|
@ -141,6 +214,31 @@ class PlayerTest extends Specification {
|
|||
obj.Implants(0).Installed mustEqual None
|
||||
}
|
||||
|
||||
"seat in a vehicle" in {
|
||||
val obj = new Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
obj.VehicleSeated mustEqual None
|
||||
obj.VehicleSeated = PlanetSideGUID(65)
|
||||
obj.VehicleSeated mustEqual Some(PlanetSideGUID(65))
|
||||
obj.VehicleSeated = None
|
||||
obj.VehicleSeated mustEqual None
|
||||
}
|
||||
|
||||
"own in a vehicle" in {
|
||||
val obj = new Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
obj.VehicleOwned mustEqual None
|
||||
obj.VehicleOwned = PlanetSideGUID(65)
|
||||
obj.VehicleOwned mustEqual Some(PlanetSideGUID(65))
|
||||
obj.VehicleOwned = None
|
||||
obj.VehicleOwned mustEqual None
|
||||
}
|
||||
|
||||
"remember what zone he is in" in {
|
||||
val obj = new Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
obj.Continent mustEqual "home2"
|
||||
obj.Continent = "ugd01"
|
||||
obj.Continent mustEqual "ugd01"
|
||||
}
|
||||
|
||||
"administrate" in {
|
||||
val obj = new Player("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
|
||||
obj.Admin mustEqual false
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class VehicleSpawnControl2Test extends ActorTest() {
|
|||
assert(reply2.asInstanceOf[VehicleSpawnPad.LoadVehicle].vehicle == vehicle)
|
||||
assert(reply2.asInstanceOf[VehicleSpawnPad.LoadVehicle].pad == obj)
|
||||
|
||||
player.VehicleOwned = vehicle
|
||||
player.VehicleOwned = Some(vehicle.GUID)
|
||||
val reply3 = receiveOne(Duration.create(10000, "ms"))
|
||||
assert(reply3.isInstanceOf[VehicleSpawnPad.PlayerSeatedInVehicle])
|
||||
assert(reply3.asInstanceOf[VehicleSpawnPad.PlayerSeatedInVehicle].vehicle == vehicle)
|
||||
|
|
|
|||
|
|
@ -281,5 +281,43 @@ class NumberPoolHubTest extends Specification {
|
|||
val hub = new NumberPoolHub(src)
|
||||
hub.unregister(4).isFailure mustEqual true
|
||||
}
|
||||
|
||||
"identity an object that is registered to it" in {
|
||||
val hub1 = new NumberPoolHub(new LimitedNumberSource(10))
|
||||
val hub2 = new NumberPoolHub(new LimitedNumberSource(10))
|
||||
val obj1 = new EntityTestClass()
|
||||
val obj2 = new EntityTestClass()
|
||||
hub1.register(obj1)
|
||||
hub2.register(obj2)
|
||||
|
||||
hub1.isRegistered(obj1) mustEqual true
|
||||
hub2.isRegistered(obj2) mustEqual true
|
||||
hub1.isRegistered(obj2) mustEqual false
|
||||
hub2.isRegistered(obj1) mustEqual false
|
||||
}
|
||||
|
||||
"identity a number that is registered to it" in {
|
||||
val src1 = new LimitedNumberSource(5)
|
||||
val hub1 = new NumberPoolHub(src1)
|
||||
val src2 = new LimitedNumberSource(10)
|
||||
src2.Restrict(0)
|
||||
src2.Restrict(1)
|
||||
src2.Restrict(2)
|
||||
src2.Restrict(3)
|
||||
src2.Restrict(4)
|
||||
src2.Restrict(5)
|
||||
val hub2 = new NumberPoolHub(src2)
|
||||
val obj1 = new EntityTestClass()
|
||||
val obj2 = new EntityTestClass()
|
||||
hub1.register(obj1)
|
||||
hub2.register(obj2)
|
||||
val num1 = obj1.GUID.guid
|
||||
val num2 = obj2.GUID.guid
|
||||
|
||||
hub1.isRegistered(num1) mustEqual true
|
||||
hub2.isRegistered(num2) mustEqual true
|
||||
hub1.isRegistered(num2) mustEqual false
|
||||
hub2.isRegistered(num1) mustEqual false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,14 @@ class NumberPoolTest extends Specification {
|
|||
ok
|
||||
}
|
||||
|
||||
"fail to construct 1 (number less than zero)" in {
|
||||
new SimplePool(-1 :: Nil) must throwA[IllegalArgumentException]
|
||||
}
|
||||
|
||||
"fail to construct 2 (duplicate numbers)" in {
|
||||
new SimplePool(1 :: 1 :: Nil) must throwA[IllegalArgumentException]
|
||||
}
|
||||
|
||||
"get a number" in {
|
||||
val obj = new SimplePool((0 to 10).toList)
|
||||
obj.Get() match {
|
||||
|
|
@ -26,6 +34,13 @@ class NumberPoolTest extends Specification {
|
|||
}
|
||||
}
|
||||
|
||||
"used number count is always zero" in {
|
||||
val obj = new SimplePool((0 to 10).toList)
|
||||
obj.Count mustEqual 0
|
||||
obj.Get()
|
||||
obj.Count mustEqual 0
|
||||
}
|
||||
|
||||
"return a number" in {
|
||||
//returning a number for a SimplePool is actually just a way of checking that the number is in the "pool" at all
|
||||
val obj = new SimplePool((0 to 10).toList)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package objects.number
|
|||
|
||||
import net.psforever.objects.guid.AvailabilityPolicy
|
||||
import net.psforever.objects.guid.key.{LoanedKey, SecureKey}
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
class NumberSourceTest extends Specification {
|
||||
|
|
@ -102,6 +103,17 @@ class NumberSourceTest extends Specification {
|
|||
result2.get.Object mustEqual Some(test)
|
||||
}
|
||||
|
||||
"return a secure key" in {
|
||||
val obj = LimitedNumberSource(25)
|
||||
val test = new TestClass()
|
||||
val result1 : Option[LoanedKey] = obj.Available(5)
|
||||
result1.get.Object = test
|
||||
test.GUID = PlanetSideGUID(5)
|
||||
val result2 : Option[SecureKey] = obj.Get(5)
|
||||
|
||||
obj.Return(result2.get) mustEqual Some(test)
|
||||
}
|
||||
|
||||
"restrict a previously-assigned number" in {
|
||||
val obj = LimitedNumberSource(25)
|
||||
val test = new TestClass()
|
||||
|
|
|
|||
60
common/src/test/scala/objects/number/RegisterTest.scala
Normal file
60
common/src/test/scala/objects/number/RegisterTest.scala
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects.number
|
||||
|
||||
import akka.actor.Actor
|
||||
import net.psforever.objects.guid.actor.Register
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
class RegisterTest extends Specification {
|
||||
val obj = new net.psforever.objects.entity.IdentifiableEntity() {}
|
||||
|
||||
"Register" should {
|
||||
"construct (object)" in {
|
||||
val reg = Register(obj)
|
||||
reg.obj mustEqual obj
|
||||
reg.number mustEqual None
|
||||
reg.name mustEqual None
|
||||
reg.callback mustEqual None
|
||||
}
|
||||
|
||||
"construct (object, callback)" in {
|
||||
val reg = Register(obj, Actor.noSender)
|
||||
reg.obj mustEqual obj
|
||||
reg.number mustEqual None
|
||||
reg.name mustEqual None
|
||||
reg.callback mustEqual Some(Actor.noSender)
|
||||
}
|
||||
|
||||
"construct (object, suggested number)" in {
|
||||
val reg = Register(obj, 5)
|
||||
reg.obj mustEqual obj
|
||||
reg.number mustEqual Some(5)
|
||||
reg.name mustEqual None
|
||||
reg.callback mustEqual None
|
||||
}
|
||||
|
||||
"construct (object, suggested number, callback)" in {
|
||||
val reg = Register(obj, 5, Actor.noSender)
|
||||
reg.obj mustEqual obj
|
||||
reg.number mustEqual Some(5)
|
||||
reg.name mustEqual None
|
||||
reg.callback mustEqual Some(Actor.noSender)
|
||||
}
|
||||
|
||||
"construct (object, pool name)" in {
|
||||
val reg = Register(obj, "pool")
|
||||
reg.obj mustEqual obj
|
||||
reg.number mustEqual None
|
||||
reg.name mustEqual Some("pool")
|
||||
reg.callback mustEqual None
|
||||
}
|
||||
|
||||
"construct (object, pool name, callback)" in {
|
||||
val reg = Register(obj, "pool", Actor.noSender)
|
||||
reg.obj mustEqual obj
|
||||
reg.number mustEqual None
|
||||
reg.name mustEqual Some("pool")
|
||||
reg.callback mustEqual Some(Actor.noSender)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@ import objects.ActorTest
|
|||
|
||||
import scala.concurrent.duration.Duration
|
||||
|
||||
class TerminalControlTest extends ActorTest() {
|
||||
class TerminalControl1Test extends ActorTest() {
|
||||
"TerminalControl" should {
|
||||
"construct (cert terminal)" in {
|
||||
val terminal = Terminal(GlobalDefinitions.cert_terminal)
|
||||
|
|
@ -19,6 +19,17 @@ class TerminalControlTest extends ActorTest() {
|
|||
}
|
||||
}
|
||||
|
||||
class TerminalControl2Test extends ActorTest() {
|
||||
"TerminalControl can not process wrong messages" in {
|
||||
val terminal = Terminal(GlobalDefinitions.cert_terminal)
|
||||
terminal.Actor = system.actorOf(Props(classOf[TerminalControl], terminal), "test-cert-term")
|
||||
|
||||
terminal.Actor !"hello"
|
||||
val reply = receiveOne(Duration.create(500, "ms"))
|
||||
assert(reply.isInstanceOf[Terminal.NoDeal])
|
||||
}
|
||||
}
|
||||
|
||||
//terminal control is mostly a pass-through actor for Terminal.Exchange messages, wrapped in Terminal.TerminalMessage protocol
|
||||
//test for Cert_Terminal messages (see CertTerminalTest)
|
||||
class CertTerminalControl1Test extends ActorTest() {
|
||||
|
|
|
|||
|
|
@ -120,10 +120,6 @@ class PacketCodingActor extends Actor with MDCContextAware {
|
|||
// failWithError(s"Invalid message '$default' received in state Established")
|
||||
}
|
||||
|
||||
def resetState() : Unit = {
|
||||
context.become(receive)
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the current subslot number.
|
||||
* Increment the `subslot` for the next time it is needed.
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
sendResponse(PacketCoding.CreateGamePacket(0, ObjectHeldMessage(guid, slot, true)))
|
||||
}
|
||||
|
||||
case AvatarResponse.PlanetSideAttribute(attribute_type, attribute_value) =>
|
||||
case AvatarResponse.PlanetsideAttribute(attribute_type, attribute_value) =>
|
||||
if(player.GUID != guid) {
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, PlanetsideAttributeMessage(guid, attribute_type, attribute_value)))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ object AvatarResponse {
|
|||
// final case class LoadMap() extends Response
|
||||
final case class ObjectDelete(item_guid : PlanetSideGUID, unk : Int) extends Response
|
||||
final case class ObjectHeld(slot : Int) extends Response
|
||||
final case class PlanetSideAttribute(attribute_type : Int, attribute_value : Long) extends Response
|
||||
final case class PlanetsideAttribute(attribute_type : Int, attribute_value : Long) extends Response
|
||||
final case class PlayerState(msg : PlayerStateMessageUpstream, spectator : Boolean, weaponInHand : Boolean) extends Response
|
||||
final case class Reload(mag : Int) extends Response
|
||||
// final case class PlayerStateShift(itemID : PlanetSideGUID) extends Response
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ class AvatarService extends Actor {
|
|||
)
|
||||
case AvatarAction.PlanetsideAttribute(guid, attribute_type, attribute_value) =>
|
||||
AvatarEvents.publish(
|
||||
AvatarServiceResponse(s"/$forChannel/Avatar", guid, AvatarResponse.PlanetSideAttribute(attribute_type, attribute_value))
|
||||
AvatarServiceResponse(s"/$forChannel/Avatar", guid, AvatarResponse.PlanetsideAttribute(attribute_type, attribute_value))
|
||||
)
|
||||
case AvatarAction.PlayerState(guid, msg, spectator, weapon) =>
|
||||
AvatarEvents.publish(
|
||||
|
|
|
|||
57
pslogin/src/main/test/scala/ActorTest.scala
Normal file
57
pslogin/src/main/test/scala/ActorTest.scala
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
|
||||
import akka.actor.{ActorRef, ActorSystem, MDCContextAware}
|
||||
import akka.testkit.{ImplicitSender, TestKit, TestProbe}
|
||||
import net.psforever.packet.{ControlPacket, GamePacket}
|
||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||
import org.specs2.specification.Scope
|
||||
|
||||
abstract class ActorTest(sys : ActorSystem = ActorSystem("system")) extends TestKit(sys) with Scope with ImplicitSender with WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
override def afterAll {
|
||||
TestKit.shutdownActorSystem(system)
|
||||
}
|
||||
}
|
||||
|
||||
object ActorTest {
|
||||
final case class MDCGamePacket(packet : GamePacket)
|
||||
|
||||
final case class MDCControlPacket(packet : ControlPacket)
|
||||
|
||||
class MDCTestProbe(probe : TestProbe) extends MDCContextAware {
|
||||
/*
|
||||
The way this test mediator works needs to be explained.
|
||||
|
||||
MDCContextAware objects initialize themselves in a chain of ActorRefs defined in the HelloFriend message.
|
||||
As the iterator is consumed, it produces a right-neighbor (r-neighbor) that is much further along the chain.
|
||||
The HelloFriend is passed to that r-neighbor and that is how subsequent neighbors are initialized and chained.
|
||||
|
||||
MDCContextAware objects consume and produce internal messages called MdcMsg that wrap around the payload.
|
||||
Normally inaccessible from the outside, the payload is unwrapped within the standard receive PartialFunction.
|
||||
By interacting with a TestProbe constructor param, information that would be concealed by MdcMsg can be polled.
|
||||
|
||||
The l-neighbor of the MDCContextAware is the system of the ActorTest TestKit.
|
||||
The r-neighbor of the MDCContextAware is this MDCTestProbe and, indirectly, the TestProbe that was interjected.
|
||||
Pass l-input into the MDCContextAware itself.
|
||||
The r-output is a normal message that can be polled on that TestProbe.
|
||||
Pass r-input into this MDCTestProbe directly.
|
||||
The l-output is an MdcMsg that can be treated just as r-output, sending it to this Actor and polling the TestProbe.
|
||||
*/
|
||||
private var left : ActorRef = ActorRef.noSender
|
||||
|
||||
def receive : Receive = {
|
||||
case msg @ HelloFriend(_, _) =>
|
||||
left = sender()
|
||||
probe.ref ! msg
|
||||
|
||||
case MDCGamePacket(msg) =>
|
||||
left ! msg
|
||||
|
||||
case MDCControlPacket(msg) =>
|
||||
left ! msg
|
||||
|
||||
case msg =>
|
||||
left ! msg
|
||||
probe.ref ! msg
|
||||
}
|
||||
}
|
||||
}
|
||||
187
pslogin/src/main/test/scala/AvatarServiceTest.scala
Normal file
187
pslogin/src/main/test/scala/AvatarServiceTest.scala
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
import akka.actor.Props
|
||||
import net.psforever.objects._
|
||||
import net.psforever.packet.game.{PlanetSideGUID, PlayerStateMessageUpstream}
|
||||
import net.psforever.types.{CharacterGender, ExoSuitType, PlanetSideEmpire, Vector3}
|
||||
import services.Service
|
||||
import services.avatar._
|
||||
|
||||
class AvatarService0Test extends ActorTest {
|
||||
"AvatarService" should {
|
||||
"construct" in {
|
||||
system.actorOf(Props[AvatarService], "service")
|
||||
assert(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AvatarService1ATest extends ActorTest {
|
||||
"AvatarService" should {
|
||||
"subscribe" in {
|
||||
val service = system.actorOf(Props[AvatarService], "service")
|
||||
service ! Service.Join("test")
|
||||
assert(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AvatarService1BTest extends ActorTest {
|
||||
"AvatarService" should {
|
||||
"subscribe" in {
|
||||
val service = system.actorOf(Props[AvatarService], "service")
|
||||
service ! Service.Join("test")
|
||||
service ! Service.Leave()
|
||||
assert(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AvatarService1CTest extends ActorTest {
|
||||
"AvatarService" should {
|
||||
"subscribe" in {
|
||||
val service = system.actorOf(Props[AvatarService], "service")
|
||||
service ! Service.Join("test")
|
||||
service ! Service.LeaveAll()
|
||||
assert(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AvatarService2Test extends ActorTest {
|
||||
"AvatarService" should {
|
||||
"pass an unhandled message" in {
|
||||
val service = system.actorOf(Props[AvatarService], "service")
|
||||
service ! Service.Join("test")
|
||||
service ! "hello"
|
||||
expectNoMsg()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AvatarService3Test extends ActorTest {
|
||||
"AvatarService" should {
|
||||
"pass ArmorChanged" in {
|
||||
val service = system.actorOf(Props[AvatarService], "service")
|
||||
service ! Service.Join("test")
|
||||
service ! AvatarServiceMessage("test", AvatarAction.ArmorChanged(PlanetSideGUID(10), ExoSuitType.Reinforced, 0))
|
||||
expectMsg(AvatarServiceResponse("/test/Avatar", PlanetSideGUID(10), AvatarResponse.ArmorChanged(ExoSuitType.Reinforced, 0)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AvatarService4Test extends ActorTest {
|
||||
"AvatarService" should {
|
||||
"pass ConcealPlayer" in {
|
||||
val service = system.actorOf(Props[AvatarService], "service")
|
||||
service ! Service.Join("test")
|
||||
service ! AvatarServiceMessage("test", AvatarAction.ConcealPlayer(PlanetSideGUID(10)))
|
||||
expectMsg(AvatarServiceResponse("/test/Avatar", PlanetSideGUID(10), AvatarResponse.ConcealPlayer()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AvatarService5Test extends ActorTest {
|
||||
val tool = Tool(GlobalDefinitions.beamer)
|
||||
|
||||
"AvatarService" should {
|
||||
"pass EquipmentInHand" in {
|
||||
val service = system.actorOf(Props[AvatarService], "service")
|
||||
service ! Service.Join("test")
|
||||
service ! AvatarServiceMessage("test", AvatarAction.EquipmentInHand(PlanetSideGUID(10), 2, tool))
|
||||
expectMsg(AvatarServiceResponse("/test/Avatar", PlanetSideGUID(10), AvatarResponse.EquipmentInHand(2, tool)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AvatarService6Test extends ActorTest {
|
||||
val tool = Tool(GlobalDefinitions.beamer)
|
||||
|
||||
"AvatarService" should {
|
||||
"pass EquipmentOnGround" in {
|
||||
val service = system.actorOf(Props[AvatarService], "service")
|
||||
service ! Service.Join("test")
|
||||
service ! AvatarServiceMessage("test", AvatarAction.EquipmentOnGround(PlanetSideGUID(10), Vector3(300f, 200f, 100f), Vector3(450f, 300f, 150f), tool))
|
||||
expectMsg(AvatarServiceResponse("/test/Avatar", PlanetSideGUID(10), AvatarResponse.EquipmentOnGround(Vector3(300f, 200f, 100f), Vector3(450f, 300f, 150f), tool)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AvatarService7Test extends ActorTest {
|
||||
val obj = Player("TestCharacter1", PlanetSideEmpire.VS, CharacterGender.Female, 1, 1)
|
||||
obj.GUID = PlanetSideGUID(10)
|
||||
obj.Slot(5).Equipment.get.GUID = PlanetSideGUID(11)
|
||||
val pdata = obj.Definition.Packet.DetailedConstructorData(obj).get
|
||||
|
||||
"AvatarService" should {
|
||||
"pass LoadPlayer" in {
|
||||
val service = system.actorOf(Props[AvatarService], "service")
|
||||
service ! Service.Join("test")
|
||||
service ! AvatarServiceMessage("test", AvatarAction.LoadPlayer(PlanetSideGUID(10), pdata))
|
||||
expectMsg(AvatarServiceResponse("/test/Avatar", PlanetSideGUID(10), AvatarResponse.LoadPlayer(pdata)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AvatarService8Test extends ActorTest {
|
||||
"AvatarService" should {
|
||||
"pass ObjectDelete" in {
|
||||
val service = system.actorOf(Props[AvatarService], "service")
|
||||
service ! Service.Join("test")
|
||||
service ! AvatarServiceMessage("test", AvatarAction.ObjectDelete(PlanetSideGUID(10), PlanetSideGUID(11)))
|
||||
expectMsg(AvatarServiceResponse("/test/Avatar", PlanetSideGUID(10), AvatarResponse.ObjectDelete(PlanetSideGUID(11), 0)))
|
||||
|
||||
service ! AvatarServiceMessage("test", AvatarAction.ObjectDelete(PlanetSideGUID(10), PlanetSideGUID(11), 55))
|
||||
expectMsg(AvatarServiceResponse("/test/Avatar", PlanetSideGUID(10), AvatarResponse.ObjectDelete(PlanetSideGUID(11), 55)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AvatarService9Test extends ActorTest {
|
||||
"AvatarService" should {
|
||||
"pass ObjectHeld" in {
|
||||
val service = system.actorOf(Props[AvatarService], "service")
|
||||
service ! Service.Join("test")
|
||||
service ! AvatarServiceMessage("test", AvatarAction.ObjectHeld(PlanetSideGUID(10), 1))
|
||||
expectMsg(AvatarServiceResponse("/test/Avatar", PlanetSideGUID(10), AvatarResponse.ObjectHeld(1)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AvatarServiceATest extends ActorTest {
|
||||
"AvatarService" should {
|
||||
"pass PlanetsideAttribute" in {
|
||||
val service = system.actorOf(Props[AvatarService], "service")
|
||||
service ! Service.Join("test")
|
||||
service ! AvatarServiceMessage("test", AvatarAction.PlanetsideAttribute(PlanetSideGUID(10), 5, 1200L))
|
||||
expectMsg(AvatarServiceResponse("/test/Avatar", PlanetSideGUID(10), AvatarResponse.PlanetsideAttribute(5, 1200L)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AvatarServiceBTest extends ActorTest {
|
||||
val msg = PlayerStateMessageUpstream(PlanetSideGUID(75), Vector3(3694.1094f, 2735.4531f, 90.84375f), Some(Vector3(4.375f, 2.59375f, 0.0f)), 61.875f, 351.5625f, 0.0f, 136, 0, false, false, false, false, 112, 0)
|
||||
|
||||
"AvatarService" should {
|
||||
"pass PlayerState" in {
|
||||
val service = system.actorOf(Props[AvatarService], "service")
|
||||
service ! Service.Join("test")
|
||||
service ! AvatarServiceMessage("test", AvatarAction.PlayerState(PlanetSideGUID(10), msg, false, false))
|
||||
expectMsg(AvatarServiceResponse("/test/Avatar", PlanetSideGUID(10), AvatarResponse.PlayerState(msg, false, false)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AvatarServiceCTest extends ActorTest {
|
||||
"AvatarService" should {
|
||||
"pass Reload" in {
|
||||
val service = system.actorOf(Props[AvatarService], "service")
|
||||
service ! Service.Join("test")
|
||||
service ! AvatarServiceMessage("test", AvatarAction.Reload(PlanetSideGUID(10), 35))
|
||||
expectMsg(AvatarServiceResponse("/test/Avatar", PlanetSideGUID(10), AvatarResponse.Reload(35)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object AvatarServiceTest {
|
||||
//decoy
|
||||
}
|
||||
369
pslogin/src/main/test/scala/PacketCodingActorTest.scala
Normal file
369
pslogin/src/main/test/scala/PacketCodingActorTest.scala
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue