diff --git a/.codecov.yml b/.codecov.yml index ed4904dbe..67d23fb7a 100644 --- a/.codecov.yml +++ b/.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" diff --git a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala index 7299d1828..6b9e2d49f 100644 --- a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala +++ b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.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 diff --git a/common/src/main/scala/net/psforever/objects/Player.scala b/common/src/main/scala/net/psforever/objects/Player.scala index 4b718f13a..ba1a9581e 100644 --- a/common/src/main/scala/net/psforever/objects/Player.scala +++ b/common/src/main/scala/net/psforever/objects/Player.scala @@ -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 diff --git a/common/src/main/scala/net/psforever/objects/entity/MobileWorldEntity.scala b/common/src/main/scala/net/psforever/objects/entity/MobileWorldEntity.scala deleted file mode 100644 index 33de4798f..000000000 --- a/common/src/main/scala/net/psforever/objects/entity/MobileWorldEntity.scala +++ /dev/null @@ -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))) - } -} diff --git a/common/src/main/scala/net/psforever/objects/entity/TimeEntry.scala b/common/src/main/scala/net/psforever/objects/entity/TimeEntry.scala deleted file mode 100644 index f6fcc417d..000000000 --- a/common/src/main/scala/net/psforever/objects/entity/TimeEntry.scala +++ /dev/null @@ -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)) -} diff --git a/common/src/main/scala/net/psforever/objects/equipment/EquipmentSize.scala b/common/src/main/scala/net/psforever/objects/equipment/EquipmentSize.scala index 16ffebb99..bcae0146c 100644 --- a/common/src/main/scala/net/psforever/objects/equipment/EquipmentSize.scala +++ b/common/src/main/scala/net/psforever/objects/equipment/EquipmentSize.scala @@ -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 } diff --git a/common/src/main/scala/net/psforever/objects/equipment/FireModeDefinition.scala b/common/src/main/scala/net/psforever/objects/equipment/FireModeDefinition.scala index 2c02a54c8..e1f7862b0 100644 --- a/common/src/main/scala/net/psforever/objects/equipment/FireModeDefinition.scala +++ b/common/src/main/scala/net/psforever/objects/equipment/FireModeDefinition.scala @@ -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 diff --git a/common/src/main/scala/net/psforever/objects/guid/source/NumberSource.scala b/common/src/main/scala/net/psforever/objects/guid/source/NumberSource.scala index f169eabe9..8e1fec4e5 100644 --- a/common/src/main/scala/net/psforever/objects/guid/source/NumberSource.scala +++ b/common/src/main/scala/net/psforever/objects/guid/source/NumberSource.scala @@ -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.
diff --git a/common/src/main/scala/net/psforever/packet/control/MultiPacket.scala b/common/src/main/scala/net/psforever/packet/control/MultiPacket.scala index 61e237908..260ccd622 100644 --- a/common/src/main/scala/net/psforever/packet/control/MultiPacket.scala +++ b/common/src/main/scala/net/psforever/packet/control/MultiPacket.scala @@ -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] -} \ No newline at end of file +} diff --git a/common/src/main/scala/net/psforever/packet/control/MultiPacketEx.scala b/common/src/main/scala/net/psforever/packet/control/MultiPacketEx.scala index a52fb26da..89fe73320 100644 --- a/common/src/main/scala/net/psforever/packet/control/MultiPacketEx.scala +++ b/common/src/main/scala/net/psforever/packet/control/MultiPacketEx.scala @@ -68,4 +68,4 @@ object MultiPacketEx extends Marshallable[MultiPacketEx] { } implicit val codec : Codec[MultiPacketEx] = ("packets" | vector(variableSizeBytesLong(sizeCodec, bytes))).as[MultiPacketEx] -} \ No newline at end of file +} diff --git a/common/src/main/scala/net/psforever/packet/control/SlottedMetaAck.scala b/common/src/main/scala/net/psforever/packet/control/SlottedMetaAck.scala index dbf24bb74..31c940e91 100644 --- a/common/src/main/scala/net/psforever/packet/control/SlottedMetaAck.scala +++ b/common/src/main/scala/net/psforever/packet/control/SlottedMetaAck.scala @@ -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 diff --git a/common/src/main/scala/net/psforever/packet/control/SlottedMetaPacket.scala b/common/src/main/scala/net/psforever/packet/control/SlottedMetaPacket.scala index dcbe43d25..2c4637401 100644 --- a/common/src/main/scala/net/psforever/packet/control/SlottedMetaPacket.scala +++ b/common/src/main/scala/net/psforever/packet/control/SlottedMetaPacket.scala @@ -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) diff --git a/common/src/main/scala/net/psforever/packet/game/LoginMessage.scala b/common/src/main/scala/net/psforever/packet/game/LoginMessage.scala index 685431ee9..ec0a3c839 100644 --- a/common/src/main/scala/net/psforever/packet/game/LoginMessage.scala +++ b/common/src/main/scala/net/psforever/packet/game/LoginMessage.scala @@ -71,4 +71,4 @@ object LoginMessage extends Marshallable[LoginMessage] { ("revision" | uint32L) ) ).as[LoginMessage] -} \ No newline at end of file +} diff --git a/common/src/test/scala/control/ClientStartTest.scala b/common/src/test/scala/control/ClientStartTest.scala new file mode 100644 index 000000000..aecf0822e --- /dev/null +++ b/common/src/test/scala/control/ClientStartTest.scala @@ -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 + } +} diff --git a/common/src/test/scala/control/ConnectionCloseTest.scala b/common/src/test/scala/control/ConnectionCloseTest.scala new file mode 100644 index 000000000..46231304f --- /dev/null +++ b/common/src/test/scala/control/ConnectionCloseTest.scala @@ -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 + } +} diff --git a/common/src/test/scala/control/MultiPacketExTest.scala b/common/src/test/scala/control/MultiPacketExTest.scala index e537bf81e..3909f6c18 100644 --- a/common/src/test/scala/control/MultiPacketExTest.scala +++ b/common/src/test/scala/control/MultiPacketExTest.scala @@ -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" + } } diff --git a/common/src/test/scala/control/MultiPacketTest.scala b/common/src/test/scala/control/MultiPacketTest.scala new file mode 100644 index 000000000..35a7489d3 --- /dev/null +++ b/common/src/test/scala/control/MultiPacketTest.scala @@ -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 + } +} diff --git a/common/src/test/scala/control/SlottedMetaAckTest.scala b/common/src/test/scala/control/SlottedMetaAckTest.scala new file mode 100644 index 000000000..161ba5261 --- /dev/null +++ b/common/src/test/scala/control/SlottedMetaAckTest.scala @@ -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 + } +} diff --git a/common/src/test/scala/game/LoginMessageTest.scala b/common/src/test/scala/game/LoginMessageTest.scala new file mode 100644 index 000000000..098109fd0 --- /dev/null +++ b/common/src/test/scala/game/LoginMessageTest.scala @@ -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] + } +} diff --git a/common/src/test/scala/game/ObjectCreateBaseTest.scala b/common/src/test/scala/game/ObjectCreateBaseTest.scala new file mode 100644 index 000000000..c3ebe1bdd --- /dev/null +++ b/common/src/test/scala/game/ObjectCreateBaseTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/ObjectCreateDetailedMessageTest.scala b/common/src/test/scala/game/ObjectCreateDetailedMessageTest.scala deleted file mode 100644 index 545a5fdb1..000000000 --- a/common/src/test/scala/game/ObjectCreateDetailedMessageTest.scala +++ /dev/null @@ -1,1075 +0,0 @@ -// 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 net.psforever.types._ -import scodec.bits._ - -class ObjectCreateDetailedMessageTest extends Specification { - val packet = hex"18 CF 13 00 00 BC 87 00 0A F0 16 C3 43 A1 30 90 00 02 C0 40 00 08 70 43 00 68 00 6F 00 72 00 64 00 54 00 52 00 82 65 1F F5 9E 80 80 00 00 00 00 00 3F FF C0 00 00 00 20 00 00 00 20 27 03 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FC CC 10 00 03 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 90 01 90 00 00 00 00 01 00 7E C8 00 C8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 C0 00 42 C5 46 86 C7 00 00 02 A0 00 00 12 60 78 70 65 5F 77 61 72 70 5F 67 61 74 65 5F 75 73 61 67 65 92 78 70 65 5F 69 6E 73 74 61 6E 74 5F 61 63 74 69 6F 6E 92 78 70 65 5F 73 61 6E 63 74 75 61 72 79 5F 68 65 6C 70 91 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 32 8E 78 70 65 5F 66 6F 72 6D 5F 73 71 75 61 64 8E 78 70 65 5F 74 68 5F 6E 6F 6E 73 61 6E 63 8B 78 70 65 5F 74 68 5F 61 6D 6D 6F 90 78 70 65 5F 74 68 5F 66 69 72 65 6D 6F 64 65 73 8F 75 73 65 64 5F 63 68 61 69 6E 62 6C 61 64 65 9A 76 69 73 69 74 65 64 5F 62 72 6F 61 64 63 61 73 74 5F 77 61 72 70 67 61 74 65 8E 76 69 73 69 74 65 64 5F 6C 6F 63 6B 65 72 8D 75 73 65 64 5F 70 75 6E 69 73 68 65 72 88 75 73 65 64 5F 72 65 6B 8D 75 73 65 64 5F 72 65 70 65 61 74 65 72 9F 76 69 73 69 74 65 64 5F 64 65 63 6F 6E 73 74 72 75 63 74 69 6F 6E 5F 74 65 72 6D 69 6E 61 6C 8F 75 73 65 64 5F 73 75 70 70 72 65 73 73 6F 72 96 76 69 73 69 74 65 64 5F 6F 72 64 65 72 5F 74 65 72 6D 69 6E 61 6C 85 6D 61 70 31 35 85 6D 61 70 31 34 85 6D 61 70 31 32 85 6D 61 70 30 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 0A 36 13 88 04 00 40 00 00 10 00 04 00 00 4D 6E 40 10 41 00 00 00 40 00 18 08 38 1C C0 20 32 00 00 07 80 15 E1 D0 02 10 20 00 00 08 00 03 01 07 13 A8 04 06 40 00 00 10 03 20 BB 00 42 E4 00 00 01 00 0E 07 70 08 6C 80 00 06 40 01 C0 F0 01 13 90 00 00 C8 00 38 1E 40 23 32 00 00 19 00 07 03 D0 05 0E 40 00 03 20 00 E8 7B 00 A4 C8 00 00 64 00 DA 4F 80 14 E1 00 00 00 40 00 18 08 38 1F 40 20 32 00 00 0A 00 08 " //fake data? - val packet2 = 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 - //val packet2Rest = packet2.bits.drop(8 + 32 + 1 + 11 + 16) - var string_inventoryItem = hex"46 04 C0 08 08 80 00 00 20 00 0C 04 10 29 A0 10 19 00 00 04 00 00" - val string_detonater = hex"18 87000000 6506 EA8 7420 80 8000000200008" - val string_ace = hex"18 87000000 1006 100 C70B 80 8800000200008" - val string_9mm = hex"18 7C000000 2580 0E0 0005 A1 C8000064000" - 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" - val string_rek = hex"18 97000000 2580 6C2 9F05 81 48000002000080000" - val string_boomer_trigger = hex"18 87000000 6304CA8760B 80 C800000200008" - val string_testchar = hex"18 570C0000 BC8 4B00 6C2D7 65535 CA16 0 00 01 34 40 00 0970 49006C006C006C004900490049006C006C006C0049006C0049006C006C0049006C006C006C0049006C006C004900 84 52 70 76 1E 80 80 00 00 00 00 00 3FFFC 0 00 00 00 20 00 00 0F F6 A7 03 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 90 01 90 00 64 00 00 01 00 7E C8 00 C8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 C0 00 42 C5 46 86 C7 00 00 00 80 00 00 12 40 78 70 65 5F 73 61 6E 63 74 75 61 72 79 5F 68 65 6C 70 90 78 70 65 5F 74 68 5F 66 69 72 65 6D 6F 64 65 73 8B 75 73 65 64 5F 62 65 61 6D 65 72 85 6D 61 70 31 33 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 0A 23 02 60 04 04 40 00 00 10 00 06 02 08 14 D0 08 0C 80 00 02 00 02 6B 4E 00 82 88 00 00 02 00 00 C0 41 C0 9E 01 01 90 00 00 64 00 44 2A 00 10 91 00 00 00 40 00 18 08 38 94 40 20 32 00 00 00 80 19 05 48 02 17 20 00 00 08 00 70 29 80 43 64 00 00 32 00 0E 05 40 08 9C 80 00 06 40 01 C0 AA 01 19 90 00 00 C8 00 3A 15 80 28 72 00 00 19 00 04 0A B8 05 26 40 00 03 20 06 C2 58 00 A7 88 00 00 02 00 00 80 00 00" - val string_testchar_br32 = hex"18 2c e0 00 00 bc 84 B0 00 0b ea 00 6c 7d f1 10 00 00 02 40 00 08 60 4b 00 69 00 43 00 6b 00 4a 00 72 00 02 31 3a cc 82 c0 00 00 00 00 00 00 00 00 3e df 42 00 20 00 0e 00 40 43 40 4c 04 00 02 e8 00 00 03 a8 00 00 01 9c 04 00 00 b8 99 84 00 0e 68 28 00 00 00 00 00 00 00 00 00 00 00 00 01 90 01 90 00 c8 00 00 01 00 7e c8 00 5c 00 00 01 29 c1 cc 80 00 00 00 00 00 00 00 00 00 00 00 00 03 c0 00 40 81 01 c4 45 46 86 c8 88 c9 09 4a 4a 80 50 0c 13 00 00 15 00 80 00 48 00 7870655f6f766572686561645f6d6170 8d7870655f776172705f676174658f7870655f666f726d5f6f75746669748c7870655f626c61636b6f7073927870655f636f6d6d616e645f72616e6b5f35927870655f636f6d6d616e645f72616e6b5f33927870655f73616e6374756172795f68656c70927870655f626174746c655f72616e6b5f3133927870655f626174746c655f72616e6b5f3132927870655f626174746c655f72616e6b5f3130927870655f626174746c655f72616e6b5f3134927870655f626174746c655f72616e6b5f3135937870655f6f72626974616c5f73687574746c658c7870655f64726f705f706f64917870655f62696e645f666163696c697479917870655f626174746c655f72616e6b5f33917870655f626174746c655f72616e6b5f35917870655f626174746c655f72616e6b5f348e7870655f6a6f696e5f73717561648e7870655f666f726d5f7371756164927870655f696e7374616e745f616374696f6e917870655f626174746c655f72616e6b5f32937870655f776172705f676174655f7573616765917870655f626174746c655f72616e6b5f38927870655f626174746c655f72616e6b5f3131917870655f626174746c655f72616e6b5f368e7870655f6d61696c5f616c657274927870655f636f6d6d616e645f72616e6b5f31927870655f626174746c655f72616e6b5f3230927870655f626174746c655f72616e6b5f3138927870655f626174746c655f72616e6b5f3139907870655f6a6f696e5f706c61746f6f6e927870655f626174746c655f72616e6b5f3137927870655f626174746c655f72616e6b5f31368f7870655f6a6f696e5f6f7574666974927870655f626174746c655f72616e6b5f3235927870655f626174746c655f72616e6b5f3234927870655f636f6d6d616e645f72616e6b5f34907870655f666f726d5f706c61746f6f6e8c7870655f62696e645f616d73917870655f626174746c655f72616e6b5f39917870655f626174746c655f72616e6b5f378d7870655f74685f726f757465728c7870655f74685f666c61696c8a7870655f74685f616e748a7870655f74685f616d738f7870655f74685f67726f756e645f708c7870655f74685f6169725f708c7870655f74685f686f7665728d7870655f74685f67726f756e648a7870655f74685f626672927870655f74685f61667465726275726e65728a7870655f74685f6169728c7870655f74685f636c6f616b89757365645f6f69637791757365645f616476616e6365645f61636597766973697465645f73706974666972655f74757272657498766973697465645f73706974666972655f636c6f616b656493766973697465645f73706974666972655f616192766973697465645f74616e6b5f7472617073a1766973697465645f706f727461626c655f6d616e6e65645f7475727265745f6e63a1766973697465645f706f727461626c655f6d616e6e65645f7475727265745f74728e757365645f6d61676375747465728f757365645f636861696e626c6164658f757365645f666f726365626c61646593766973697465645f77616c6c5f74757272657498766973697465645f616e6369656e745f7465726d696e616c8b766973697465645f616d738b766973697465645f616e7490766973697465645f64726f707368697091766973697465645f6c6962657261746f7294766973697465645f6c6967687467756e7368697091766973697465645f6c696768746e696e6790766973697465645f6d616772696465728f766973697465645f70726f776c657293766973697465645f71756164737465616c746890766973697465645f736b7967756172649a766973697465645f74687265656d616e686561767962756767799d766973697465645f74776f5f6d616e5f61737361756c745f627567677998766973697465645f74776f6d616e6865617679627567677998766973697465645f74776f6d616e686f766572627567677990766973697465645f76616e67756172648d766973697465645f666c61696c8e766973697465645f726f7574657293766973697465645f737769746368626c6164658e766973697465645f6175726f726193766973697465645f626174746c657761676f6e8c766973697465645f6675727993766973697465645f7175616461737361756c7496766973697465645f67616c6178795f67756e736869708e766973697465645f6170635f74728e766973697465645f6170635f767390766973697465645f6c6f64657374617290766973697465645f7068616e7461736d91766973697465645f7468756e64657265728e766973697465645f6170635f6e638f766973697465645f76756c747572658c766973697465645f7761737090766973697465645f6d6f73717569746f97766973697465645f617068656c696f6e5f666c6967687497766973697465645f617068656c696f6e5f67756e6e657297766973697465645f636f6c6f737375735f666c6967687497766973697465645f636f6c6f737375735f67756e6e657298766973697465645f706572656772696e655f666c6967687498766973697465645f706572656772696e655f67756e6e657289757365645f62616e6b95766973697465645f7265736f757263655f73696c6f9e766973697465645f63657274696669636174696f6e5f7465726d696e616c94766973697465645f6d65645f7465726d696e616c93757365645f6e616e6f5f64697370656e73657295766973697465645f73656e736f725f736869656c649a766973697465645f62726f6164636173745f77617270676174658c757365645f7068616c616e7894757365645f7068616c616e785f6176636f6d626f96757365645f7068616c616e785f666c616b636f6d626f96766973697465645f77617270676174655f736d616c6c91757365645f666c616d657468726f7765729a757365645f616e6369656e745f7475727265745f776561706f6e92766973697465645f4c4c555f736f636b657492757365645f656e657267795f67756e5f6e6397766973697465645f6d656469756d7472616e73706f72749f757365645f617068656c696f6e5f696d6d6f6c6174696f6e5f63616e6e6f6e93757365645f6772656e6164655f706c61736d6193757365645f6772656e6164655f6a616d6d657298766973697465645f736869656c645f67656e657261746f7295766973697465645f6d6f74696f6e5f73656e736f7296766973697465645f6865616c74685f6372797374616c96766973697465645f7265706169725f6372797374616c97766973697465645f76656869636c655f6372797374616c91757365645f6772656e6164655f6672616788757365645f61636598766973697465645f6164765f6d65645f7465726d696e616c8b757365645f6265616d657290757365645f626f6c745f6472697665728b757365645f6379636c65728a757365645f676175737391757365645f68756e7465727365656b657288757365645f6973708b757365645f6c616e6365728b757365645f6c61736865728e757365645f6d61656c7374726f6d8c757365645f70686f656e69788b757365645f70756c7361728d757365645f70756e69736865728e757365645f725f73686f7467756e8d757365645f7261646961746f7288757365645f72656b8d757365645f72657065617465728c757365645f726f636b6c65748c757365645f737472696b65728f757365645f73757070726573736f728c757365645f7468756d7065729c766973697465645f76616e755f636f6e74726f6c5f636f6e736f6c6598766973697465645f636170747572655f7465726d696e616c92757365645f6d696e695f636861696e67756e91757365645f6c617a655f706f696e7465728c757365645f74656c657061648b757365645f7370696b657291757365645f68656176795f736e6970657293757365645f636f6d6d616e645f75706c696e6b8d757365645f66697265626972648e757365645f666c6563686574746594757365645f68656176795f7261696c5f6265616d89757365645f696c63399a766973697465645f67656e657261746f725f7465726d696e616c8e766973697465645f6c6f636b65729a766973697465645f65787465726e616c5f646f6f725f6c6f636b9c766973697465645f6169725f76656869636c655f7465726d696e616c97766973697465645f67616c6178795f7465726d696e616c98766973697465645f696d706c616e745f7465726d696e616c99766973697465645f7365636f6e646172795f6361707475726590757365645f32356d6d5f63616e6e6f6e99757365645f6c6962657261746f725f626f6d6261726469657293766973697465645f7265706169725f73696c6f93766973697465645f76616e755f6d6f64756c6591757365645f666c61696c5f776561706f6e8b757365645f73637974686598766973697465645f7265737061776e5f7465726d696e616c8c757365645f62616c6c67756e92757365645f656e657267795f67756e5f747295757365645f616e6e69766572736172795f67756e6195757365645f616e6e69766572736172795f67756e6294757365645f616e6e69766572736172795f67756e90757365645f37356d6d5f63616e6e6f6e92757365645f6170635f6e635f776561706f6e92757365645f6170635f74725f776561706f6e92757365645f6170635f76735f776561706f6e90757365645f666c75785f63616e6e6f6e9f757365645f617068656c696f6e5f706c61736d615f726f636b65745f706f6491757365645f617068656c696f6e5f7070618c757365645f666c7578706f6494766973697465645f6266725f7465726d696e616c9e757365645f636f6c6f737375735f636c75737465725f626f6d625f706f64a0757365645f636f6c6f737375735f6475616c5f3130306d6d5f63616e6e6f6e7399757365645f636f6c6f737375735f74616e6b5f63616e6e6f6e96766973697465645f656e657267795f6372797374616c9b757365645f68656176795f6772656e6164655f6c61756e6368657298757365645f33356d6d5f726f74617279636861696e67756e8b757365645f6b6174616e6190757365645f33356d6d5f63616e6e6f6e93757365645f7265617665725f776561706f6e7396757365645f6c696768746e696e675f776561706f6e738c757365645f6d65645f61707090757365645f32306d6d5f63616e6e6f6e98766973697465645f6d6f6e6f6c6974685f616d657269736899766973697465645f6d6f6e6f6c6974685f636572797368656e97766973697465645f6d6f6e6f6c6974685f637973736f7297766973697465645f6d6f6e6f6c6974685f6573616d697299766973697465645f6d6f6e6f6c6974685f666f72736572616c99766973697465645f6d6f6e6f6c6974685f697368756e64617298766973697465645f6d6f6e6f6c6974685f7365617268757397766973697465645f6d6f6e6f6c6974685f736f6c73617292757365645f6e635f6865765f66616c636f6e99757365645f6e635f6865765f7363617474657263616e6e6f6e93757365645f6e635f6865765f73706172726f7791757365645f61726d6f725f736970686f6e9f757365645f706572656772696e655f6475616c5f6d616368696e655f67756e9f757365645f706572656772696e655f6475616c5f726f636b65745f706f647399757365645f706572656772696e655f6d65636868616d6d65729e757365645f706572656772696e655f7061727469636c655f63616e6e6f6e96757365645f706572656772696e655f73706172726f7791757365645f3130356d6d5f63616e6e6f6e92757365645f31356d6d5f636861696e67756ea0757365645f70756c7365645f7061727469636c655f616363656c657261746f7293757365645f726f74617279636861696e67756e9f766973697465645f6465636f6e737472756374696f6e5f7465726d696e616c95757365645f736b7967756172645f776561706f6e7391766973697465645f67656e657261746f7291757365645f67617573735f63616e6e6f6e89757365645f7472656b95757365645f76616e67756172645f776561706f6e73a4766973697465645f616e6369656e745f6169725f76656869636c655f7465726d696e616ca2766973697465645f616e6369656e745f65717569706d656e745f7465726d696e616c96766973697465645f6f726465725f7465726d696e616ca7766973697465645f616e6369656e745f67726f756e645f76656869636c655f7465726d696e616c9f766973697465645f67726f756e645f76656869636c655f7465726d696e616c97757365645f76756c747572655f626f6d6261726469657298757365645f76756c747572655f6e6f73655f63616e6e6f6e98757365645f76756c747572655f7461696c5f63616e6e6f6e97757365645f776173705f776561706f6e5f73797374656d91766973697465645f636861726c6965303191766973697465645f636861726c6965303291766973697465645f636861726c6965303391766973697465645f636861726c6965303491766973697465645f636861726c6965303591766973697465645f636861726c6965303691766973697465645f636861726c6965303791766973697465645f636861726c6965303891766973697465645f636861726c6965303996766973697465645f67696e6765726d616e5f6174617298766973697465645f67696e6765726d616e5f646168616b6196766973697465645f67696e6765726d616e5f6876617296766973697465645f67696e6765726d616e5f697a686199766973697465645f67696e6765726d616e5f6a616d7368696498766973697465645f67696e6765726d616e5f6d697468726198766973697465645f67696e6765726d616e5f726173686e7599766973697465645f67696e6765726d616e5f7372616f73686198766973697465645f67696e6765726d616e5f79617a61746195766973697465645f67696e6765726d616e5f7a616c8e766973697465645f736c656430318e766973697465645f736c656430328e766973697465645f736c656430348e766973697465645f736c656430358e766973697465645f736c656430368e766973697465645f736c656430378e766973697465645f736c6564303897766973697465645f736e6f776d616e5f616d657269736898766973697465645f736e6f776d616e5f636572797368656e96766973697465645f736e6f776d616e5f637973736f7296766973697465645f736e6f776d616e5f6573616d697298766973697465645f736e6f776d616e5f666f72736572616c96766973697465645f736e6f776d616e5f686f7373696e98766973697465645f736e6f776d616e5f697368756e64617297766973697465645f736e6f776d616e5f7365617268757396766973697465645f736e6f776d616e5f736f6c736172857567643036857567643035857567643034857567643033857567643032857567643031856d61703939856d61703938856d61703937856d61703936856d61703135856d61703134856d61703131856d61703038856d61703034856d61703035856d61703033856d61703031856d61703036856d61703032856d61703039856d61703037856d617031300300000091747261696e696e675f73746172745f6e638b747261696e696e675f75698c747261696e696e675f6d61700000000000000000000000000000000000000000800000003d0c04d350840240000010000602429660f80c80000c8004200c1b81480000020000c046f18a47019000019000ca4644304900000040001809e6bb052032000008001a84787211200000080003010714889c06400000100320ff0a42e4000001009e95a7342e03200000080003010408c914064000000001198990c4e4000001000060223b9b2180c800000a00081c20c92c800003600414ec172d900000040001808de1284a0320000320008ef1c336b20000078011d830e6f6400000600569c417e2c80000020000c04102502f019000008c00ce31027d99000000400018099e6146203200004b0015a7d44002f720000008000301040c18dc064000023000b1240800636400000100006020e0e92280c80000c800081650c00cfc800006400ce32a1801a59000000400018099e6fc3e03200004b00058b14680463200000080003010742610c064000043000b16c8880916400000100006020e0d01580c80000c8006714e24012cc80000020000c04cf25c190190000258001032e240307900000c8019c74470061b2000000800030133ced8fc0640000960012d9a8d00f0640000010025b9c1401e4c8000002004b6b23c03d1900000040098f585007b3200000080131a58c00f864000001002536f1c01f4c8000002004a64e2a03f190000004015e1b4580873200000080003010711f8a406400000100110a00c010ee400000100006020e2a51380c8000002002218d21021ec80000020000c041c40249019000000400af18a44043f90000004000180838b44760320000008015e38c80088320000008000301071490cc064000001002bc35890110e400000100006020e2052180c800000200221f90d0222c80000020000c041c5e447019000000400442e62e044790000004000180838af032032000000800886d08c089320000008000301071738740640000010011098898112e400000100006020e2361c80c8000002002212a1b0226c80000020000c041c512170190000004004420a32044f900000040001808389104a0320000008008874c8808a3200000080003010715907c06400000100110c0898114e400000100006020e2771a80c800000200578bd13022ac80000020000c041c424330190000004004423848045790000004000180838bfc32032000000801a86506008b320000008000301071030dc06400000100129f68a0117640000010026353110232c8000002004b69438046d90000004015e2887008eb200000080003010715909406400000100350fb8e011de400000100006020e2881980c8000002005786d0f023cc80000020000c041c4cc3b019000000400af1ba1c047b90000004000180838af872032000000800886344408fb20000008000301071620d406400000100110c10b011fe400000100006020e2870d80c800000200578f30c0240c80000020000c041c5863b019000000400442ee300483900000040001808388605e032000000801a86f03c090b200000080003010712a8fc064000001002bc0d858121e400000100006020e2521c80c800000200578b7230244c80000020000c041c49629019000000400d434026048b90000004000180838afc42032000000801a86d864091b200000080003010711989c064000001003508c8c8123e400000100006020e2a82280c8000002006a14f110248c80000020000c041c4be21019000000400af12640049390000004000180838a54720320000008015e33430092b20000008000301071228cc064000001003546e8d432400000100004f34a631139000004001b0834723120000008000204000c2ed0fa1c800000200a8432234a90000004000180952b248a0320000018004024c569d20000008000250a4d0ebc480000020000c04a24bc43019000000c00e0" - - "decode (2)" in { - //an invalid bit representation will fail to turn into an object - PacketCoding.DecodePacket(packet2).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 - } - } - - "decode (detonater)" 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 - } - } - - "decode (ace)" 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 - } - } - - "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 - } - } - - "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 - } - } - - "decode (rek)" 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 - } - } - - "decode (boomer trigger)" 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 - } - } - - "decode (character)" in { - PacketCoding.DecodePacket(string_testchar).require match { - case ObjectCreateDetailedMessage(len, cls, guid, parent, data) => - len mustEqual 3159 - cls mustEqual ObjectClass.avatar - guid mustEqual PlanetSideGUID(75) - parent.isDefined mustEqual false - data.isDefined mustEqual true - val char = data.get.asInstanceOf[DetailedCharacterData] - char.appearance.pos.coord.x mustEqual 3674.8438f - char.appearance.pos.coord.y mustEqual 2726.789f - char.appearance.pos.coord.z mustEqual 91.15625f - char.appearance.pos.orient.x mustEqual 0 - char.appearance.pos.orient.y mustEqual 0f - char.appearance.pos.orient.z mustEqual 36.5625f - char.appearance.basic_appearance.name mustEqual "IlllIIIlllIlIllIlllIllI" - char.appearance.basic_appearance.faction mustEqual PlanetSideEmpire.VS - char.appearance.basic_appearance.sex mustEqual CharacterGender.Female - char.appearance.basic_appearance.head mustEqual 41 - char.appearance.basic_appearance.voice mustEqual 1 //female 1 - char.appearance.voice2 mustEqual 3 - char.appearance.black_ops mustEqual false - char.appearance.jammered mustEqual false - char.appearance.exosuit mustEqual ExoSuitType.Standard - char.appearance.outfit_name mustEqual "" - char.appearance.outfit_logo mustEqual 0 - char.appearance.backpack mustEqual false - char.appearance.facingPitch mustEqual 2.8125f - char.appearance.facingYawUpper mustEqual 210.9375f - char.appearance.lfs mustEqual true - char.appearance.grenade_state mustEqual GrenadeState.None - char.appearance.is_cloaking mustEqual false - char.appearance.charging_pose mustEqual false - char.appearance.on_zipline mustEqual false - char.appearance.ribbons.upper mustEqual MeritCommendation.None - char.appearance.ribbons.middle mustEqual MeritCommendation.None - char.appearance.ribbons.lower mustEqual MeritCommendation.None - char.appearance.ribbons.tos mustEqual MeritCommendation.None - char.bep mustEqual 0 - char.cep mustEqual 0 - char.healthMax mustEqual 100 - char.health mustEqual 100 - char.armor mustEqual 50 //standard exosuit value - char.unk1 mustEqual 1 - char.unk2 mustEqual 7 - char.unk3 mustEqual 7 - char.staminaMax mustEqual 100 - char.stamina mustEqual 100 - char.certs.length mustEqual 7 - char.certs.head mustEqual CertificationType.StandardAssault - char.certs(1) mustEqual CertificationType.MediumAssault - char.certs(2) mustEqual CertificationType.ATV - char.certs(3) mustEqual CertificationType.Harasser - char.certs(4) mustEqual CertificationType.StandardExoSuit - char.certs(5) mustEqual CertificationType.AgileExoSuit - char.certs(6) mustEqual CertificationType.ReinforcedExoSuit - char.implants.length mustEqual 0 - char.firstTimeEvents.size mustEqual 4 - char.firstTimeEvents.head mustEqual "xpe_sanctuary_help" - char.firstTimeEvents(1) mustEqual "xpe_th_firemodes" - char.firstTimeEvents(2) mustEqual "used_beamer" - char.firstTimeEvents(3) mustEqual "map13" - char.tutorials.size mustEqual 0 - char.cosmetics.isDefined mustEqual false - char.inventory.isDefined mustEqual true - val inventory = char.inventory.get.contents - inventory.size mustEqual 10 - //0 - inventory.head.objectClass mustEqual ObjectClass.beamer - inventory.head.guid mustEqual PlanetSideGUID(76) - inventory.head.parentSlot mustEqual 0 - var wep = inventory.head.obj.asInstanceOf[DetailedWeaponData] - wep.ammo.head.objectClass mustEqual ObjectClass.energy_cell - wep.ammo.head.guid mustEqual PlanetSideGUID(77) - wep.ammo.head.parentSlot mustEqual 0 - wep.ammo.head.obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 16 - //1 - inventory(1).objectClass mustEqual ObjectClass.suppressor - inventory(1).guid mustEqual PlanetSideGUID(78) - inventory(1).parentSlot mustEqual 2 - wep = inventory(1).obj.asInstanceOf[DetailedWeaponData] - wep.ammo.head.objectClass mustEqual ObjectClass.bullet_9mm - wep.ammo.head.guid mustEqual PlanetSideGUID(79) - wep.ammo.head.parentSlot mustEqual 0 - wep.ammo.head.obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 25 - //2 - inventory(2).objectClass mustEqual ObjectClass.forceblade - inventory(2).guid mustEqual PlanetSideGUID(80) - inventory(2).parentSlot mustEqual 4 - wep = inventory(2).obj.asInstanceOf[DetailedWeaponData] - wep.ammo.head.objectClass mustEqual ObjectClass.melee_ammo - wep.ammo.head.guid mustEqual PlanetSideGUID(81) - wep.ammo.head.parentSlot mustEqual 0 - wep.ammo.head.obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 1 - //3 - inventory(3).objectClass mustEqual ObjectClass.locker_container - inventory(3).guid mustEqual PlanetSideGUID(82) - inventory(3).parentSlot mustEqual 5 - inventory(3).obj.isInstanceOf[DetailedLockerContainerData] mustEqual true - inventory(3).obj.asInstanceOf[DetailedLockerContainerData].inventory.isDefined mustEqual false - //4 - inventory(4).objectClass mustEqual ObjectClass.bullet_9mm - inventory(4).guid mustEqual PlanetSideGUID(83) - inventory(4).parentSlot mustEqual 6 - inventory(4).obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 50 - //5 - inventory(5).objectClass mustEqual ObjectClass.bullet_9mm - inventory(5).guid mustEqual PlanetSideGUID(84) - inventory(5).parentSlot mustEqual 9 - inventory(5).obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 50 - //6 - inventory(6).objectClass mustEqual ObjectClass.bullet_9mm - inventory(6).guid mustEqual PlanetSideGUID(85) - inventory(6).parentSlot mustEqual 12 - inventory(6).obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 50 - //7 - inventory(7).objectClass mustEqual ObjectClass.bullet_9mm_AP - inventory(7).guid mustEqual PlanetSideGUID(86) - inventory(7).parentSlot mustEqual 33 - inventory(7).obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 50 - //8 - inventory(8).objectClass mustEqual ObjectClass.energy_cell - inventory(8).guid mustEqual PlanetSideGUID(87) - inventory(8).parentSlot mustEqual 36 - inventory(8).obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 50 - //9 - inventory(9).objectClass mustEqual ObjectClass.remote_electronics_kit - inventory(9).guid mustEqual PlanetSideGUID(88) - inventory(9).parentSlot mustEqual 39 - //the rek has data but none worth testing here - char.drawn_slot mustEqual DrawnSlot.Pistol1 - case _ => - ko - } - } - - "decode (character, BR32)" in { - PacketCoding.DecodePacket(string_testchar_br32).require match { - case ObjectCreateDetailedMessage(len, cls, guid, parent, data) => - //this test is mainly for an alternate bitstream parsing order - //the object produced is massive and most of it is already covered in other tests - //only certain details towards the end of the stream will be checked - data.isDefined mustEqual true - val char = data.get.asInstanceOf[DetailedCharacterData] - DetailedCharacterData.isBR24(char.bep) mustEqual true - char.certs.size mustEqual 15 - char.certs.head mustEqual CertificationType.StandardAssault - char.certs(14) mustEqual CertificationType.CombatEngineering - char.implants.size mustEqual 3 - char.implants.head.implant mustEqual ImplantType.AudioAmplifier - char.implants.head.activation mustEqual None - char.implants(1).implant mustEqual ImplantType.Targeting - char.implants(1).activation mustEqual None - char.implants(2).implant mustEqual ImplantType.Surge - char.implants(2).activation mustEqual None - char.firstTimeEvents.size mustEqual 298 - char.firstTimeEvents.head mustEqual "xpe_overhead_map" - char.firstTimeEvents(297) mustEqual "map10" - char.tutorials.size mustEqual 3 - char.tutorials.head mustEqual "training_start_nc" - char.tutorials(1) mustEqual "training_ui" - char.tutorials(2) mustEqual "training_map" - char.cosmetics.isDefined mustEqual true - char.cosmetics.get.no_helmet mustEqual true - char.cosmetics.get.beret mustEqual true - char.cosmetics.get.earpiece mustEqual true - char.cosmetics.get.sunglasses mustEqual true - char.cosmetics.get.brimmed_cap mustEqual false - //inventory - char.inventory.isDefined mustEqual true - char.inventory.get.contents.size mustEqual 12 - //0 - char.inventory.get.contents.head.objectClass mustEqual 531 - char.inventory.get.contents.head.guid mustEqual PlanetSideGUID(4202) - char.inventory.get.contents.head.parentSlot mustEqual 0 - val wep1 = char.inventory.get.contents.head.obj.asInstanceOf[DetailedWeaponData] - wep1.unk1 mustEqual 2 - wep1.unk2 mustEqual 8 - wep1.ammo.head.objectClass mustEqual 389 - wep1.ammo.head.guid mustEqual PlanetSideGUID(3942) - wep1.ammo.head.parentSlot mustEqual 0 - wep1.ammo.head.obj.asInstanceOf[DetailedAmmoBoxData].unk mustEqual 8 - wep1.ammo.head.obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 100 - //4 - char.inventory.get.contents(4).objectClass mustEqual 456 - char.inventory.get.contents(4).guid mustEqual PlanetSideGUID(5374) - char.inventory.get.contents(4).parentSlot mustEqual 5 - char.inventory.get.contents(4).obj.asInstanceOf[DetailedLockerContainerData].inventory.get.contents.size mustEqual 61 - //11 - char.inventory.get.contents(11).objectClass mustEqual 673 - char.inventory.get.contents(11).guid mustEqual PlanetSideGUID(3661) - char.inventory.get.contents(11).parentSlot mustEqual 60 - val wep2 = char.inventory.get.contents(11).obj.asInstanceOf[DetailedWeaponData] - wep2.unk1 mustEqual 2 - wep2.unk2 mustEqual 8 - wep2.ammo.head.objectClass mustEqual 674 - wep2.ammo.head.guid mustEqual PlanetSideGUID(8542) - wep2.ammo.head.parentSlot mustEqual 0 - wep2.ammo.head.obj.asInstanceOf[DetailedAmmoBoxData].unk mustEqual 8 - wep2.ammo.head.obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 3 - char.drawn_slot mustEqual DrawnSlot.None - case _ => - ko - } - } - - "encode (2)" 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 - } - - "encode (detonater)" 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 - } - - "encode (ace)" 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 - } - - "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 - } - - "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 - } - - "encode (rek)" 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 - } - - "encode (boomer trigger)" 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 - } - - "encode (character)" in { - val app = CharacterAppearanceData( - PlacementData( - Vector3(3674.8438f, 2726.789f, 91.15625f), - Vector3(0f, 0f, 36.5625f) - ), - BasicCharacterData( - "IlllIIIlllIlIllIlllIllI", - PlanetSideEmpire.VS, - CharacterGender.Female, - 41, - 1 - ), - 3, - false, - false, - ExoSuitType.Standard, - "", - 0, - false, - 2.8125f, 210.9375f, - true, - GrenadeState.None, - false, - false, - false, - RibbonBars() - ) - val inv = InventoryItemData(ObjectClass.beamer, PlanetSideGUID(76), 0, DetailedWeaponData(4, 8, ObjectClass.energy_cell, PlanetSideGUID(77), 0, DetailedAmmoBoxData(8, 16))) :: - InventoryItemData(ObjectClass.suppressor, PlanetSideGUID(78), 2, DetailedWeaponData(4, 8, ObjectClass.bullet_9mm, PlanetSideGUID(79), 0, DetailedAmmoBoxData(8, 25))) :: - InventoryItemData(ObjectClass.forceblade, PlanetSideGUID(80), 4, DetailedWeaponData(4, 8, ObjectClass.melee_ammo, PlanetSideGUID(81), 0, DetailedAmmoBoxData(8, 1))) :: - InventoryItemData(ObjectClass.locker_container, PlanetSideGUID(82), 5, DetailedLockerContainerData(8)) :: - InventoryItemData(ObjectClass.bullet_9mm, PlanetSideGUID(83), 6, DetailedAmmoBoxData(8, 50)) :: - InventoryItemData(ObjectClass.bullet_9mm, PlanetSideGUID(84), 9, DetailedAmmoBoxData(8, 50)) :: - InventoryItemData(ObjectClass.bullet_9mm, PlanetSideGUID(85), 12, DetailedAmmoBoxData(8, 50)) :: - InventoryItemData(ObjectClass.bullet_9mm_AP, PlanetSideGUID(86), 33, DetailedAmmoBoxData(8, 50)) :: - InventoryItemData(ObjectClass.energy_cell, PlanetSideGUID(87), 36, DetailedAmmoBoxData(8, 50)) :: - InventoryItemData(ObjectClass.remote_electronics_kit, PlanetSideGUID(88), 39, DetailedREKData(8)) :: - Nil - val obj = DetailedCharacterData( - app, - 0, - 0, - 100, 100, - 50, - 1, 7, 7, - 100, 100, - List( - CertificationType.StandardAssault, - CertificationType.MediumAssault, - CertificationType.ATV, - CertificationType.Harasser, - CertificationType.StandardExoSuit, - CertificationType.AgileExoSuit, - CertificationType.ReinforcedExoSuit - ), - List(), - "xpe_sanctuary_help" :: "xpe_th_firemodes" :: "used_beamer" :: "map13" :: Nil, - List.empty, - None, - Some(InventoryData(inv)), - DrawnSlot.Pistol1 - ) - val msg = ObjectCreateDetailedMessage(0x79, PlanetSideGUID(75), obj) - val pkt = PacketCoding.EncodePacket(msg).require.toByteVector - - val pkt_bitv = pkt.toBitVector - val ori_bitv = string_testchar.toBitVector - pkt_bitv.take(153) mustEqual ori_bitv.take(153) //skip 1 - pkt_bitv.drop(154).take(422) mustEqual ori_bitv.drop(154).take(422) //skip 126 - pkt_bitv.drop(702).take(29) mustEqual ori_bitv.drop(702).take(29) //skip 1 - pkt_bitv.drop(732) mustEqual ori_bitv.drop(732) - //TODO work on DetailedCharacterData to make this pass as a single stream - } - - "encode (character, br32)" in { - val obj = DetailedCharacterData( - CharacterAppearanceData( - PlacementData( - Vector3(5500.0f, 3800.0f, 71.484375f), - Vector3(0.0f, 0.0f, 90.0f), - None - ), - BasicCharacterData("KiCkJr", PlanetSideEmpire.NC, CharacterGender.Male, 24, 4), - 3, - false, false, - ExoSuitType.Agile, - "", - 14, - false, - 354.375f, 354.375f, - false, - GrenadeState.None, - false, false, false, - RibbonBars(MeritCommendation.Loser4, MeritCommendation.EventNCElite, MeritCommendation.HeavyAssault6, MeritCommendation.SixYearNC) - ), - 6366766, - 694787, - 100, 100, 100, - 1, 7, 7, - 100, 46, - List( - CertificationType.StandardAssault, - CertificationType.MediumAssault, - CertificationType.HeavyAssault, - CertificationType.AntiVehicular, - CertificationType.AirCavalryScout, - CertificationType.GroundSupport, - CertificationType.Harasser, - CertificationType.StandardExoSuit, - CertificationType.AgileExoSuit, - CertificationType.Medical, - CertificationType.AdvancedMedical, - CertificationType.Hacking, - CertificationType.AdvancedHacking, - CertificationType.Engineering, - CertificationType.CombatEngineering - ), - List( - ImplantEntry(ImplantType.AudioAmplifier, None), - ImplantEntry(ImplantType.Targeting, None), - ImplantEntry(ImplantType.Surge, None) - ), - List( - "xpe_overhead_map", - "xpe_warp_gate", - "xpe_form_outfit", - "xpe_blackops", - "xpe_command_rank_5", - "xpe_command_rank_3", - "xpe_sanctuary_help", - "xpe_battle_rank_13", - "xpe_battle_rank_12", - "xpe_battle_rank_10", - "xpe_battle_rank_14", - "xpe_battle_rank_15", - "xpe_orbital_shuttle", - "xpe_drop_pod", - "xpe_bind_facility", - "xpe_battle_rank_3", - "xpe_battle_rank_5", - "xpe_battle_rank_4", - "xpe_join_squad", - "xpe_form_squad", - "xpe_instant_action", - "xpe_battle_rank_2", - "xpe_warp_gate_usage", - "xpe_battle_rank_8", - "xpe_battle_rank_11", - "xpe_battle_rank_6", - "xpe_mail_alert", - "xpe_command_rank_1", - "xpe_battle_rank_20", - "xpe_battle_rank_18", - "xpe_battle_rank_19", - "xpe_join_platoon", - "xpe_battle_rank_17", - "xpe_battle_rank_16", - "xpe_join_outfit", - "xpe_battle_rank_25", - "xpe_battle_rank_24", - "xpe_command_rank_4", - "xpe_form_platoon", - "xpe_bind_ams", - "xpe_battle_rank_9", - "xpe_battle_rank_7", - "xpe_th_router", - "xpe_th_flail", - "xpe_th_ant", - "xpe_th_ams", - "xpe_th_ground_p", - "xpe_th_air_p", - "xpe_th_hover", - "xpe_th_ground", - "xpe_th_bfr", - "xpe_th_afterburner", - "xpe_th_air", - "xpe_th_cloak", - "used_oicw", - "used_advanced_ace", - "visited_spitfire_turret", - "visited_spitfire_cloaked", - "visited_spitfire_aa", - "visited_tank_traps", - "visited_portable_manned_turret_nc", - "visited_portable_manned_turret_tr", - "used_magcutter", - "used_chainblade", - "used_forceblade", - "visited_wall_turret", - "visited_ancient_terminal", - "visited_ams", - "visited_ant", - "visited_dropship", - "visited_liberator", - "visited_lightgunship", - "visited_lightning", - "visited_magrider", - "visited_prowler", - "visited_quadstealth", - "visited_skyguard", - "visited_threemanheavybuggy", - "visited_two_man_assault_buggy", - "visited_twomanheavybuggy", - "visited_twomanhoverbuggy", - "visited_vanguard", - "visited_flail", - "visited_router", - "visited_switchblade", - "visited_aurora", - "visited_battlewagon", - "visited_fury", - "visited_quadassault", - "visited_galaxy_gunship", - "visited_apc_tr", - "visited_apc_vs", - "visited_lodestar", - "visited_phantasm", - "visited_thunderer", - "visited_apc_nc", - "visited_vulture", - "visited_wasp", - "visited_mosquito", - "visited_aphelion_flight", - "visited_aphelion_gunner", - "visited_colossus_flight", - "visited_colossus_gunner", - "visited_peregrine_flight", - "visited_peregrine_gunner", - "used_bank", - "visited_resource_silo", - "visited_certification_terminal", - "visited_med_terminal", - "used_nano_dispenser", - "visited_sensor_shield", - "visited_broadcast_warpgate", - "used_phalanx", - "used_phalanx_avcombo", - "used_phalanx_flakcombo", - "visited_warpgate_small", - "used_flamethrower", - "used_ancient_turret_weapon", - "visited_LLU_socket", - "used_energy_gun_nc", - "visited_mediumtransport", - "used_aphelion_immolation_cannon", - "used_grenade_plasma", - "used_grenade_jammer", - "visited_shield_generator", - "visited_motion_sensor", - "visited_health_crystal", - "visited_repair_crystal", - "visited_vehicle_crystal", - "used_grenade_frag", - "used_ace", - "visited_adv_med_terminal", - "used_beamer", - "used_bolt_driver", - "used_cycler", - "used_gauss", - "used_hunterseeker", - "used_isp", - "used_lancer", - "used_lasher", - "used_maelstrom", - "used_phoenix", - "used_pulsar", - "used_punisher", - "used_r_shotgun", - "used_radiator", - "used_rek", - "used_repeater", - "used_rocklet", - "used_striker", - "used_suppressor", - "used_thumper", - "visited_vanu_control_console", - "visited_capture_terminal", - "used_mini_chaingun", - "used_laze_pointer", - "used_telepad", - "used_spiker", - "used_heavy_sniper", - "used_command_uplink", - "used_firebird", - "used_flechette", - "used_heavy_rail_beam", - "used_ilc9", - "visited_generator_terminal", - "visited_locker", - "visited_external_door_lock", - "visited_air_vehicle_terminal", - "visited_galaxy_terminal", - "visited_implant_terminal", - "visited_secondary_capture", - "used_25mm_cannon", - "used_liberator_bombardier", - "visited_repair_silo", - "visited_vanu_module", - "used_flail_weapon", - "used_scythe", - "visited_respawn_terminal", - "used_ballgun", - "used_energy_gun_tr", - "used_anniversary_guna", - "used_anniversary_gunb", - "used_anniversary_gun", - "used_75mm_cannon", - "used_apc_nc_weapon", - "used_apc_tr_weapon", - "used_apc_vs_weapon", - "used_flux_cannon", - "used_aphelion_plasma_rocket_pod", - "used_aphelion_ppa", - "used_fluxpod", - "visited_bfr_terminal", - "used_colossus_cluster_bomb_pod", - "used_colossus_dual_100mm_cannons", - "used_colossus_tank_cannon", - "visited_energy_crystal", - "used_heavy_grenade_launcher", - "used_35mm_rotarychaingun", - "used_katana", - "used_35mm_cannon", - "used_reaver_weapons", - "used_lightning_weapons", - "used_med_app", - "used_20mm_cannon", - "visited_monolith_amerish", - "visited_monolith_ceryshen", - "visited_monolith_cyssor", - "visited_monolith_esamir", - "visited_monolith_forseral", - "visited_monolith_ishundar", - "visited_monolith_searhus", - "visited_monolith_solsar", - "used_nc_hev_falcon", - "used_nc_hev_scattercannon", - "used_nc_hev_sparrow", - "used_armor_siphon", - "used_peregrine_dual_machine_gun", - "used_peregrine_dual_rocket_pods", - "used_peregrine_mechhammer", - "used_peregrine_particle_cannon", - "used_peregrine_sparrow", - "used_105mm_cannon", - "used_15mm_chaingun", - "used_pulsed_particle_accelerator", - "used_rotarychaingun", - "visited_deconstruction_terminal", - "used_skyguard_weapons", - "visited_generator", - "used_gauss_cannon", - "used_trek", - "used_vanguard_weapons", - "visited_ancient_air_vehicle_terminal", - "visited_ancient_equipment_terminal", - "visited_order_terminal", - "visited_ancient_ground_vehicle_terminal", - "visited_ground_vehicle_terminal", - "used_vulture_bombardier", - "used_vulture_nose_cannon", - "used_vulture_tail_cannon", - "used_wasp_weapon_system", - "visited_charlie01", - "visited_charlie02", - "visited_charlie03", - "visited_charlie04", - "visited_charlie05", - "visited_charlie06", - "visited_charlie07", - "visited_charlie08", - "visited_charlie09", - "visited_gingerman_atar", - "visited_gingerman_dahaka", - "visited_gingerman_hvar", - "visited_gingerman_izha", - "visited_gingerman_jamshid", - "visited_gingerman_mithra", - "visited_gingerman_rashnu", - "visited_gingerman_sraosha", - "visited_gingerman_yazata", - "visited_gingerman_zal", - "visited_sled01", - "visited_sled02", - "visited_sled04", - "visited_sled05", - "visited_sled06", - "visited_sled07", - "visited_sled08", - "visited_snowman_amerish", - "visited_snowman_ceryshen", - "visited_snowman_cyssor", - "visited_snowman_esamir", - "visited_snowman_forseral", - "visited_snowman_hossin", - "visited_snowman_ishundar", - "visited_snowman_searhus", - "visited_snowman_solsar", - "ugd06", - "ugd05", - "ugd04", - "ugd03", - "ugd02", - "ugd01", - "map99", - "map98", - "map97", - "map96", - "map15", - "map14", - "map11", - "map08", - "map04", - "map05", - "map03", - "map01", - "map06", - "map02", - "map09", - "map07", - "map10" - ), - List( - "training_start_nc", - "training_ui", - "training_map" - ), - Some(Cosmetics(true, true, true, true, false)), - Some( - InventoryData( - List( - InternalSlot(531, PlanetSideGUID(4202), 0, - DetailedWeaponData(2, 8, List(InternalSlot(389, PlanetSideGUID(3942), 0,DetailedAmmoBoxData(8, 100)))) - ), - InternalSlot(132, PlanetSideGUID(6924), 1, - DetailedWeaponData(2, 8, List(InternalSlot(111, PlanetSideGUID(9157), 0, DetailedAmmoBoxData(8, 100)))) - ), - InternalSlot(714, PlanetSideGUID(8498), 2, - DetailedWeaponData(2, 8, List(InternalSlot(755, PlanetSideGUID(5356), 0, DetailedAmmoBoxData(8, 16)))) - ), - InternalSlot(468, PlanetSideGUID(7198), 4, - DetailedWeaponData(2, 8, List(InternalSlot(540, PlanetSideGUID(5009), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(456, PlanetSideGUID(5374), 5, - DetailedLockerContainerData(8, Some(InventoryData(List( - InternalSlot(429, PlanetSideGUID(3021), 0, - DetailedWeaponData(6, 8, List(InternalSlot(272, PlanetSideGUID(8729), 0, DetailedAmmoBoxData(8, 0)))) - ), - InternalSlot(838, PlanetSideGUID(8467), 9, - DetailedWeaponData(6, 8, List(InternalSlot(839, PlanetSideGUID(8603), 0, DetailedAmmoBoxData(8, 5)))) - ), - InternalSlot(272, PlanetSideGUID(3266), 18, DetailedAmmoBoxData(8, 27)), - InternalSlot(577, PlanetSideGUID(2934), 22, - DetailedWeaponData(6, 8, List(InternalSlot(111, PlanetSideGUID(4682), 0, DetailedAmmoBoxData(8, 100)))) - ), - InternalSlot(839, PlanetSideGUID(3271), 90, DetailedAmmoBoxData(8, 15)), - InternalSlot(839, PlanetSideGUID(7174), 94, DetailedAmmoBoxData(8, 6)), - InternalSlot(429, PlanetSideGUID(6084), 98, - DetailedWeaponData(6, 8, List(InternalSlot(272, PlanetSideGUID(5928), 0, DetailedAmmoBoxData(8, 35)))) - ), - InternalSlot(462, PlanetSideGUID(5000), 108, - DetailedWeaponData(6, 8, List(InternalSlot(463, PlanetSideGUID(6277), 0, DetailedAmmoBoxData(8, 150)))) - ), - InternalSlot(429, PlanetSideGUID(4341), 189, - DetailedWeaponData(6, 8, List(InternalSlot(272, PlanetSideGUID(7043), 0, DetailedAmmoBoxData(8, 35)))) - ), - InternalSlot(556, PlanetSideGUID(4168), 198, - DetailedWeaponData(6, 8, List(InternalSlot(28, PlanetSideGUID(8937), 0, DetailedAmmoBoxData(8, 100)))) - ), - InternalSlot(272, PlanetSideGUID(3173), 207, DetailedAmmoBoxData(8, 50)), - InternalSlot(462, PlanetSideGUID(3221), 210, - DetailedWeaponData(6, 8, List(InternalSlot(463, PlanetSideGUID(4031), 0, DetailedAmmoBoxData(8, 150)))) - ), - InternalSlot(556, PlanetSideGUID(6853), 280, - DetailedWeaponData(6, 8, List(InternalSlot(29, PlanetSideGUID(8524), 0, DetailedAmmoBoxData(8, 67)))) - ), - InternalSlot(556, PlanetSideGUID(4569), 290, - DetailedWeaponData(6, 8, List(InternalSlot(28, PlanetSideGUID(5584), 0, DetailedAmmoBoxData(8, 100)))) - ), - InternalSlot(462, PlanetSideGUID(9294), 300, - DetailedWeaponData(6, 8, List(InternalSlot(463, PlanetSideGUID(3118), 0, DetailedAmmoBoxData(8, 150)))) - ), - InternalSlot(272, PlanetSideGUID(4759), 387, DetailedAmmoBoxData(8, 50)), - InternalSlot(462, PlanetSideGUID(7377), 390, - DetailedWeaponData(6, 8, List(InternalSlot(463, PlanetSideGUID(8155), 0, DetailedAmmoBoxData(8, 150)))) - ), - InternalSlot(843, PlanetSideGUID(6709), 480, DetailedAmmoBoxData(8, 1)), - InternalSlot(843, PlanetSideGUID(5276), 484, DetailedAmmoBoxData(8, 1)), - InternalSlot(843, PlanetSideGUID(7769), 488, DetailedAmmoBoxData(8, 1)), - InternalSlot(844, PlanetSideGUID(5334), 492, DetailedAmmoBoxData(8, 1)), - InternalSlot(844, PlanetSideGUID(6219), 496, DetailedAmmoBoxData(8, 1)), - InternalSlot(842, PlanetSideGUID(7279), 500, DetailedAmmoBoxData(8, 1)), - InternalSlot(842, PlanetSideGUID(5415), 504, DetailedAmmoBoxData(8, 1)), - InternalSlot(175, PlanetSideGUID(5741), 540, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(5183), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(324, PlanetSideGUID(6208), 541, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(5029), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(324, PlanetSideGUID(8589), 542, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(9217), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(175, PlanetSideGUID(8901), 543, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(7633), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(175, PlanetSideGUID(8419), 544, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(6546), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(175, PlanetSideGUID(4715), 545, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(8453), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(324, PlanetSideGUID(3577), 546, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(9202), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(324, PlanetSideGUID(6003), 547, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(3260), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(324, PlanetSideGUID(9140), 548, - DetailedWeaponData(6, 8, List(InternalSlot(540,PlanetSideGUID(3815),0,DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(324, PlanetSideGUID(4913), 549, - DetailedWeaponData(6, 8, List(InternalSlot(540,PlanetSideGUID(7222),0,DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(324, PlanetSideGUID(6954), 550, - DetailedWeaponData(6, 8, List(InternalSlot(540,PlanetSideGUID(2953),0,DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(324, PlanetSideGUID(6405), 551, - DetailedWeaponData(6, 8, List(InternalSlot(540,PlanetSideGUID(4676),0,DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(324, PlanetSideGUID(8915), 552, - DetailedWeaponData(6, 8, List(InternalSlot(540,PlanetSideGUID(4018),0,DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(324, PlanetSideGUID(4993), 553, - DetailedWeaponData(6, 8, List(InternalSlot(540,PlanetSideGUID(6775),0,DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(175, PlanetSideGUID(5053), 554, - DetailedWeaponData(6, 8, List(InternalSlot(540,PlanetSideGUID(6418),0,DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(324, PlanetSideGUID(9244), 555, - DetailedWeaponData(6, 8, List(InternalSlot(540,PlanetSideGUID(3327),0,DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(468, PlanetSideGUID(6292), 556, - DetailedWeaponData(6, 8, List(InternalSlot(540,PlanetSideGUID(6918),0,DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(842, PlanetSideGUID(5357), 558, DetailedAmmoBoxData(8, 1)), - InternalSlot(844, PlanetSideGUID(4435), 562, DetailedAmmoBoxData(8, 1)), - InternalSlot(843, PlanetSideGUID(7242), 566, DetailedAmmoBoxData(8, 1)), - InternalSlot(175, PlanetSideGUID(7330), 570, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(4786), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(468, PlanetSideGUID(7415), 571, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(6536), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(175, PlanetSideGUID(3949), 572, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(7526), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(175, PlanetSideGUID(3805), 573, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(7358), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(324, PlanetSideGUID(4493), 574, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(6852), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(324, PlanetSideGUID(5762), 575, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(3463), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(175, PlanetSideGUID(3315), 576, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(7619), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(324, PlanetSideGUID(6263), 577, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(5912), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(468, PlanetSideGUID(4028), 578, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(8021), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(175, PlanetSideGUID(2843), 579, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(7250), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(175, PlanetSideGUID(9143), 580, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(5195), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(468, PlanetSideGUID(5024), 581, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(4287), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(468, PlanetSideGUID(6582), 582, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(4915), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(468, PlanetSideGUID(6425), 583, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(8872), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(468, PlanetSideGUID(4431), 584, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(4191), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(175, PlanetSideGUID(8339), 585, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(7317), 0, DetailedAmmoBoxData(8, 1)))) - ), - InternalSlot(175, PlanetSideGUID(3277), 586, - DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(6469), 0, DetailedAmmoBoxData(8, 1)))) - ) - )))) - ), - InternalSlot(213, PlanetSideGUID(6877), 6, DetailedCommandDetonaterData(4, 8)), - InternalSlot(755, PlanetSideGUID(6227), 9, DetailedAmmoBoxData(8, 16)), - InternalSlot(728, PlanetSideGUID(7181), 12, DetailedREKData(4, 16)), - InternalSlot(536, PlanetSideGUID(4077), 33, DetailedAmmoBoxData(8, 1)), - InternalSlot(680, PlanetSideGUID(4377), 37, - DetailedWeaponData(2, 8, List(InternalSlot(681, PlanetSideGUID(8905), 0, DetailedAmmoBoxData(8, 3)))) - ), - InternalSlot(32, PlanetSideGUID(5523), 39, DetailedACEData(4)), - InternalSlot(673, PlanetSideGUID(3661), 60, - DetailedWeaponData(2, 8, List(InternalSlot(674, PlanetSideGUID(8542), 0, DetailedAmmoBoxData(8, 3)))) - ) - ) - ) - ), - DrawnSlot.None - ) - val msg = ObjectCreateDetailedMessage(ObjectClass.avatar, PlanetSideGUID(75), obj) - val pkt = PacketCoding.EncodePacket(msg).require.toByteVector - - val pkt_bitv = pkt.toBitVector - val ori_bitv = string_testchar_br32.toBitVector - pkt_bitv.take(153) mustEqual ori_bitv.take(153) //skip 1 - pkt_bitv.drop(154).take(144) mustEqual ori_bitv.drop(154).take(144) //skip 24 - pkt_bitv.drop(322).take(72) mustEqual ori_bitv.drop(322).take(72) //skip 24 - pkt_bitv.drop(418).take(55) mustEqual ori_bitv.drop(418).take(55) //skip 1 - pkt_bitv.drop(474).take(102) mustEqual ori_bitv.drop(474).take(102) //skip 126 - pkt_bitv.drop(702).take(192) mustEqual ori_bitv.drop(702).take(192) //skip 36 - pkt_bitv.drop(930) mustEqual ori_bitv.drop(930) //to end - } -} diff --git a/common/src/test/scala/game/ObjectCreateMessageTest.scala b/common/src/test/scala/game/ObjectCreateMessageTest.scala deleted file mode 100644 index b7795746e..000000000 --- a/common/src/test/scala/game/ObjectCreateMessageTest.scala +++ /dev/null @@ -1,1203 +0,0 @@ -// Copyright (c) 2017 PSForever -package game - -import net.psforever.packet._ -import net.psforever.packet.game.{ObjectCreateMessage, _} -import net.psforever.packet.game.objectcreate._ -import net.psforever.types._ -import org.specs2.mutable._ -import scodec.bits._ - -class ObjectCreateMessageTest extends Specification { - val string_striker_projectile = hex"17 C5000000 A4B 009D 4C129 0CB0A 9814 00 F5 E3 040000666686400" - val string_implant_interface = hex"17 6C000000 01014C93304818000000" - val string_order_terminala = hex"17 A5000000 B2AF30EACF1889F7A3D1200007D2000000" - val string_ace_held = hex"17 76000000 0406900650C80480000000" - val string_boomertrigger = hex"17 76000000 58084A8100E80C00000000" //reconstructed from an inventory entry - val string_detonater_held = hex"17 76000000 1A886A8421080400000000" - val string_lasher_held = hex"17 BB000000 1688569D90B83 880000008082077036032000000" - val string_punisher_held = hex"17 F6000000 0A06612331083 88000000810381383E03200003793287C0E400000" - val string_rek_held = hex"17 86000000 27086C2350F800800000000000" - val string_captureflag = hex"17 E5000000 CE8EA10 04A47 B818A FE0E 00 00 0F 24000015000400160B09000" //LLU for Qumu on Amerish - val string_ace_dropped = hex"17 AF000000 90024113B329C5D5A2D1200005B440000000" - val string_detonater_dropped = hex"17 AF000000 EA8620ED1549B4B6A741500001B000000000" - val string_shotgunshell_dropped = hex"17 A5000000 F9A7D0D 5E269 BED5A F114 0000596000000" - 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" - val string_rek_dropped = hex"17 BF000000 EC20311 85219 7AC1A 2D12 00 00 4E 4000000001800" - val string_boomer = hex"17 A5000000 CA0000F1630938D5A8F1400003F0031100" - 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" - val string_trap = hex"17 BB000000 A8B630A 39FA6 FD666 801C 00 00 00 44C6097F80F00" - val string_aegis = hex"17 10010000 F80FC09 9DF96 0C676 801C 00 00 00 443E09FF0000000000000000000000000" - val string_orion = hex"17 5E010000 D82640B 92F76 01D65 F611 00 00 5E 4400006304BFC1E4041826E1503900000010104CE704C06400000" - val string_locker_container = hex"17 AF010000 E414C0C00000000000000000000600000818829DC2E030000000202378620D80C00000378FA0FADC000006F1FC199D800000" - 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" - - "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 - } - } - - "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 - } - } - - "decode (ace, 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 (boomer trigger, 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 - } - } - - "decode (detonator, 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 (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 (REK, 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 (capture flag)" 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 - } - } - "decode (ace, 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 - } - } - - "decode (detonator, 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 - } - } - - "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 - } - } - - "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 - } - } - - "decode (REK, 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 - } - } - - "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 - } - } - - "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 - } - } - - "decode (trap)" 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 - } - } - - "decode (aegis)" 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 - } - } - - "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 - } - } - - "decode (locker container)" 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 - } - } - - "decode (character, alive)" 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 (character, 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 (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) - } - - "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 - } - - "encode (ace, 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 (boomer trigger, 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 - } - - "encode (detonater, 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 (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 (REK, 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 (capture flag)" 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 - } - - "encode (ace, 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 - } - - "encode (detonator, 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 - } - - "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 - } - - "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 - } - - "encode (REK, 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 - } - - "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 - } - - "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 - } - - "encode (trap)" 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 - } - - "encode (aegis)" 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 - } - - "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 - } - - "encode (locker container)" 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 - } - - "encode (character, alive)" 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 (character, 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 - } -} diff --git a/common/src/test/scala/game/ObjectCreateMessageVehiclesTest.scala b/common/src/test/scala/game/ObjectCreateMessageVehiclesTest.scala deleted file mode 100644 index 11cca6b25..000000000 --- a/common/src/test/scala/game/ObjectCreateMessageVehiclesTest.scala +++ /dev/null @@ -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 - } -} diff --git a/common/src/test/scala/game/objectcreate/ACEDataTest.scala b/common/src/test/scala/game/objectcreate/ACEDataTest.scala new file mode 100644 index 000000000..980e4d564 --- /dev/null +++ b/common/src/test/scala/game/objectcreate/ACEDataTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreate/AegisShieldGeneratorDataTest.scala b/common/src/test/scala/game/objectcreate/AegisShieldGeneratorDataTest.scala new file mode 100644 index 000000000..8b2bae091 --- /dev/null +++ b/common/src/test/scala/game/objectcreate/AegisShieldGeneratorDataTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreate/AmmoBoxDataTest.scala b/common/src/test/scala/game/objectcreate/AmmoBoxDataTest.scala new file mode 100644 index 000000000..a3da94405 --- /dev/null +++ b/common/src/test/scala/game/objectcreate/AmmoBoxDataTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreate/BoomerTriggerDataTest.scala b/common/src/test/scala/game/objectcreate/BoomerTriggerDataTest.scala new file mode 100644 index 000000000..db5c61d2f --- /dev/null +++ b/common/src/test/scala/game/objectcreate/BoomerTriggerDataTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreate/CaptureFlagDataTest.scala b/common/src/test/scala/game/objectcreate/CaptureFlagDataTest.scala new file mode 100644 index 000000000..ee78c7ef4 --- /dev/null +++ b/common/src/test/scala/game/objectcreate/CaptureFlagDataTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreate/CharacterDataTest.scala b/common/src/test/scala/game/objectcreate/CharacterDataTest.scala new file mode 100644 index 000000000..21d1cee08 --- /dev/null +++ b/common/src/test/scala/game/objectcreate/CharacterDataTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreate/CommandDetonaterDataTest.scala b/common/src/test/scala/game/objectcreate/CommandDetonaterDataTest.scala new file mode 100644 index 000000000..c01dece32 --- /dev/null +++ b/common/src/test/scala/game/objectcreate/CommandDetonaterDataTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreate/CommonFieldDataTest.scala b/common/src/test/scala/game/objectcreate/CommonFieldDataTest.scala new file mode 100644 index 000000000..3ce92333a --- /dev/null +++ b/common/src/test/scala/game/objectcreate/CommonFieldDataTest.scala @@ -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)) + } + } +} diff --git a/common/src/test/scala/game/objectcreate/CommonTerminalDataTest.scala b/common/src/test/scala/game/objectcreate/CommonTerminalDataTest.scala new file mode 100644 index 000000000..2e4a4d701 --- /dev/null +++ b/common/src/test/scala/game/objectcreate/CommonTerminalDataTest.scala @@ -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)) + } + } +} diff --git a/common/src/test/scala/game/objectcreate/LockerContainerDataTest.scala b/common/src/test/scala/game/objectcreate/LockerContainerDataTest.scala new file mode 100644 index 000000000..2c81aea97 --- /dev/null +++ b/common/src/test/scala/game/objectcreate/LockerContainerDataTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreate/OneMannedFieldTurretDataTest.scala b/common/src/test/scala/game/objectcreate/OneMannedFieldTurretDataTest.scala new file mode 100644 index 000000000..4847bb15d --- /dev/null +++ b/common/src/test/scala/game/objectcreate/OneMannedFieldTurretDataTest.scala @@ -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) + ) + ) + } + } +} diff --git a/common/src/test/scala/game/objectcreate/REKDataTest.scala b/common/src/test/scala/game/objectcreate/REKDataTest.scala new file mode 100644 index 000000000..3de8dc638 --- /dev/null +++ b/common/src/test/scala/game/objectcreate/REKDataTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreate/RibbonBarsTest.scala b/common/src/test/scala/game/objectcreate/RibbonBarsTest.scala new file mode 100644 index 000000000..3b059e836 --- /dev/null +++ b/common/src/test/scala/game/objectcreate/RibbonBarsTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreate/SmallDeployableDataTest.scala b/common/src/test/scala/game/objectcreate/SmallDeployableDataTest.scala new file mode 100644 index 000000000..eb3ce947f --- /dev/null +++ b/common/src/test/scala/game/objectcreate/SmallDeployableDataTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreate/SmallTurretDataTest.scala b/common/src/test/scala/game/objectcreate/SmallTurretDataTest.scala new file mode 100644 index 000000000..a9ecdbac7 --- /dev/null +++ b/common/src/test/scala/game/objectcreate/SmallTurretDataTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreate/TRAPDataTest.scala b/common/src/test/scala/game/objectcreate/TRAPDataTest.scala new file mode 100644 index 000000000..88fdf57a4 --- /dev/null +++ b/common/src/test/scala/game/objectcreate/TRAPDataTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreate/TrackedProjectileDataTest.scala b/common/src/test/scala/game/objectcreate/TrackedProjectileDataTest.scala new file mode 100644 index 000000000..480c33be2 --- /dev/null +++ b/common/src/test/scala/game/objectcreate/TrackedProjectileDataTest.scala @@ -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) + } + } +} diff --git a/common/src/test/scala/game/objectcreate/WeaponDataTest.scala b/common/src/test/scala/game/objectcreate/WeaponDataTest.scala new file mode 100644 index 000000000..b4b87b0c1 --- /dev/null +++ b/common/src/test/scala/game/objectcreate/WeaponDataTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreatedetailed/DetailedACEDataTest.scala b/common/src/test/scala/game/objectcreatedetailed/DetailedACEDataTest.scala new file mode 100644 index 000000000..24214f09b --- /dev/null +++ b/common/src/test/scala/game/objectcreatedetailed/DetailedACEDataTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreatedetailed/DetailedAmmoBoxDataTest.scala b/common/src/test/scala/game/objectcreatedetailed/DetailedAmmoBoxDataTest.scala new file mode 100644 index 000000000..0b9ae180d --- /dev/null +++ b/common/src/test/scala/game/objectcreatedetailed/DetailedAmmoBoxDataTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreatedetailed/DetailedBoomerTriggerDataTest.scala b/common/src/test/scala/game/objectcreatedetailed/DetailedBoomerTriggerDataTest.scala new file mode 100644 index 000000000..e67d5de69 --- /dev/null +++ b/common/src/test/scala/game/objectcreatedetailed/DetailedBoomerTriggerDataTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreatedetailed/DetailedCharacterDataTest.scala b/common/src/test/scala/game/objectcreatedetailed/DetailedCharacterDataTest.scala new file mode 100644 index 000000000..89f690195 --- /dev/null +++ b/common/src/test/scala/game/objectcreatedetailed/DetailedCharacterDataTest.scala @@ -0,0 +1,853 @@ +// 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 net.psforever.types._ +import scodec.bits._ + +class DetailedCharacterDataTest extends Specification { + val string_testchar = hex"18 570C0000 BC8 4B00 6C2D7 65535 CA16 0 00 01 34 40 00 0970 49006C006C006C004900490049006C006C006C0049006C0049006C006C0049006C006C006C0049006C006C004900 84 52 70 76 1E 80 80 00 00 00 00 00 3FFFC 0 00 00 00 20 00 00 0F F6 A7 03 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 90 01 90 00 64 00 00 01 00 7E C8 00 C8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 C0 00 42 C5 46 86 C7 00 00 00 80 00 00 12 40 78 70 65 5F 73 61 6E 63 74 75 61 72 79 5F 68 65 6C 70 90 78 70 65 5F 74 68 5F 66 69 72 65 6D 6F 64 65 73 8B 75 73 65 64 5F 62 65 61 6D 65 72 85 6D 61 70 31 33 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 0A 23 02 60 04 04 40 00 00 10 00 06 02 08 14 D0 08 0C 80 00 02 00 02 6B 4E 00 82 88 00 00 02 00 00 C0 41 C0 9E 01 01 90 00 00 64 00 44 2A 00 10 91 00 00 00 40 00 18 08 38 94 40 20 32 00 00 00 80 19 05 48 02 17 20 00 00 08 00 70 29 80 43 64 00 00 32 00 0E 05 40 08 9C 80 00 06 40 01 C0 AA 01 19 90 00 00 C8 00 3A 15 80 28 72 00 00 19 00 04 0A B8 05 26 40 00 03 20 06 C2 58 00 A7 88 00 00 02 00 00 80 00 00" + val string_testchar_br32 = hex"18 2c e0 00 00 bc 84 B0 00 0b ea 00 6c 7d f1 10 00 00 02 40 00 08 60 4b 00 69 00 43 00 6b 00 4a 00 72 00 02 31 3a cc 82 c0 00 00 00 00 00 00 00 00 3e df 42 00 20 00 0e 00 40 43 40 4c 04 00 02 e8 00 00 03 a8 00 00 01 9c 04 00 00 b8 99 84 00 0e 68 28 00 00 00 00 00 00 00 00 00 00 00 00 01 90 01 90 00 c8 00 00 01 00 7e c8 00 5c 00 00 01 29 c1 cc 80 00 00 00 00 00 00 00 00 00 00 00 00 03 c0 00 40 81 01 c4 45 46 86 c8 88 c9 09 4a 4a 80 50 0c 13 00 00 15 00 80 00 48 00 7870655f6f766572686561645f6d6170 8d7870655f776172705f676174658f7870655f666f726d5f6f75746669748c7870655f626c61636b6f7073927870655f636f6d6d616e645f72616e6b5f35927870655f636f6d6d616e645f72616e6b5f33927870655f73616e6374756172795f68656c70927870655f626174746c655f72616e6b5f3133927870655f626174746c655f72616e6b5f3132927870655f626174746c655f72616e6b5f3130927870655f626174746c655f72616e6b5f3134927870655f626174746c655f72616e6b5f3135937870655f6f72626974616c5f73687574746c658c7870655f64726f705f706f64917870655f62696e645f666163696c697479917870655f626174746c655f72616e6b5f33917870655f626174746c655f72616e6b5f35917870655f626174746c655f72616e6b5f348e7870655f6a6f696e5f73717561648e7870655f666f726d5f7371756164927870655f696e7374616e745f616374696f6e917870655f626174746c655f72616e6b5f32937870655f776172705f676174655f7573616765917870655f626174746c655f72616e6b5f38927870655f626174746c655f72616e6b5f3131917870655f626174746c655f72616e6b5f368e7870655f6d61696c5f616c657274927870655f636f6d6d616e645f72616e6b5f31927870655f626174746c655f72616e6b5f3230927870655f626174746c655f72616e6b5f3138927870655f626174746c655f72616e6b5f3139907870655f6a6f696e5f706c61746f6f6e927870655f626174746c655f72616e6b5f3137927870655f626174746c655f72616e6b5f31368f7870655f6a6f696e5f6f7574666974927870655f626174746c655f72616e6b5f3235927870655f626174746c655f72616e6b5f3234927870655f636f6d6d616e645f72616e6b5f34907870655f666f726d5f706c61746f6f6e8c7870655f62696e645f616d73917870655f626174746c655f72616e6b5f39917870655f626174746c655f72616e6b5f378d7870655f74685f726f757465728c7870655f74685f666c61696c8a7870655f74685f616e748a7870655f74685f616d738f7870655f74685f67726f756e645f708c7870655f74685f6169725f708c7870655f74685f686f7665728d7870655f74685f67726f756e648a7870655f74685f626672927870655f74685f61667465726275726e65728a7870655f74685f6169728c7870655f74685f636c6f616b89757365645f6f69637791757365645f616476616e6365645f61636597766973697465645f73706974666972655f74757272657498766973697465645f73706974666972655f636c6f616b656493766973697465645f73706974666972655f616192766973697465645f74616e6b5f7472617073a1766973697465645f706f727461626c655f6d616e6e65645f7475727265745f6e63a1766973697465645f706f727461626c655f6d616e6e65645f7475727265745f74728e757365645f6d61676375747465728f757365645f636861696e626c6164658f757365645f666f726365626c61646593766973697465645f77616c6c5f74757272657498766973697465645f616e6369656e745f7465726d696e616c8b766973697465645f616d738b766973697465645f616e7490766973697465645f64726f707368697091766973697465645f6c6962657261746f7294766973697465645f6c6967687467756e7368697091766973697465645f6c696768746e696e6790766973697465645f6d616772696465728f766973697465645f70726f776c657293766973697465645f71756164737465616c746890766973697465645f736b7967756172649a766973697465645f74687265656d616e686561767962756767799d766973697465645f74776f5f6d616e5f61737361756c745f627567677998766973697465645f74776f6d616e6865617679627567677998766973697465645f74776f6d616e686f766572627567677990766973697465645f76616e67756172648d766973697465645f666c61696c8e766973697465645f726f7574657293766973697465645f737769746368626c6164658e766973697465645f6175726f726193766973697465645f626174746c657761676f6e8c766973697465645f6675727993766973697465645f7175616461737361756c7496766973697465645f67616c6178795f67756e736869708e766973697465645f6170635f74728e766973697465645f6170635f767390766973697465645f6c6f64657374617290766973697465645f7068616e7461736d91766973697465645f7468756e64657265728e766973697465645f6170635f6e638f766973697465645f76756c747572658c766973697465645f7761737090766973697465645f6d6f73717569746f97766973697465645f617068656c696f6e5f666c6967687497766973697465645f617068656c696f6e5f67756e6e657297766973697465645f636f6c6f737375735f666c6967687497766973697465645f636f6c6f737375735f67756e6e657298766973697465645f706572656772696e655f666c6967687498766973697465645f706572656772696e655f67756e6e657289757365645f62616e6b95766973697465645f7265736f757263655f73696c6f9e766973697465645f63657274696669636174696f6e5f7465726d696e616c94766973697465645f6d65645f7465726d696e616c93757365645f6e616e6f5f64697370656e73657295766973697465645f73656e736f725f736869656c649a766973697465645f62726f6164636173745f77617270676174658c757365645f7068616c616e7894757365645f7068616c616e785f6176636f6d626f96757365645f7068616c616e785f666c616b636f6d626f96766973697465645f77617270676174655f736d616c6c91757365645f666c616d657468726f7765729a757365645f616e6369656e745f7475727265745f776561706f6e92766973697465645f4c4c555f736f636b657492757365645f656e657267795f67756e5f6e6397766973697465645f6d656469756d7472616e73706f72749f757365645f617068656c696f6e5f696d6d6f6c6174696f6e5f63616e6e6f6e93757365645f6772656e6164655f706c61736d6193757365645f6772656e6164655f6a616d6d657298766973697465645f736869656c645f67656e657261746f7295766973697465645f6d6f74696f6e5f73656e736f7296766973697465645f6865616c74685f6372797374616c96766973697465645f7265706169725f6372797374616c97766973697465645f76656869636c655f6372797374616c91757365645f6772656e6164655f6672616788757365645f61636598766973697465645f6164765f6d65645f7465726d696e616c8b757365645f6265616d657290757365645f626f6c745f6472697665728b757365645f6379636c65728a757365645f676175737391757365645f68756e7465727365656b657288757365645f6973708b757365645f6c616e6365728b757365645f6c61736865728e757365645f6d61656c7374726f6d8c757365645f70686f656e69788b757365645f70756c7361728d757365645f70756e69736865728e757365645f725f73686f7467756e8d757365645f7261646961746f7288757365645f72656b8d757365645f72657065617465728c757365645f726f636b6c65748c757365645f737472696b65728f757365645f73757070726573736f728c757365645f7468756d7065729c766973697465645f76616e755f636f6e74726f6c5f636f6e736f6c6598766973697465645f636170747572655f7465726d696e616c92757365645f6d696e695f636861696e67756e91757365645f6c617a655f706f696e7465728c757365645f74656c657061648b757365645f7370696b657291757365645f68656176795f736e6970657293757365645f636f6d6d616e645f75706c696e6b8d757365645f66697265626972648e757365645f666c6563686574746594757365645f68656176795f7261696c5f6265616d89757365645f696c63399a766973697465645f67656e657261746f725f7465726d696e616c8e766973697465645f6c6f636b65729a766973697465645f65787465726e616c5f646f6f725f6c6f636b9c766973697465645f6169725f76656869636c655f7465726d696e616c97766973697465645f67616c6178795f7465726d696e616c98766973697465645f696d706c616e745f7465726d696e616c99766973697465645f7365636f6e646172795f6361707475726590757365645f32356d6d5f63616e6e6f6e99757365645f6c6962657261746f725f626f6d6261726469657293766973697465645f7265706169725f73696c6f93766973697465645f76616e755f6d6f64756c6591757365645f666c61696c5f776561706f6e8b757365645f73637974686598766973697465645f7265737061776e5f7465726d696e616c8c757365645f62616c6c67756e92757365645f656e657267795f67756e5f747295757365645f616e6e69766572736172795f67756e6195757365645f616e6e69766572736172795f67756e6294757365645f616e6e69766572736172795f67756e90757365645f37356d6d5f63616e6e6f6e92757365645f6170635f6e635f776561706f6e92757365645f6170635f74725f776561706f6e92757365645f6170635f76735f776561706f6e90757365645f666c75785f63616e6e6f6e9f757365645f617068656c696f6e5f706c61736d615f726f636b65745f706f6491757365645f617068656c696f6e5f7070618c757365645f666c7578706f6494766973697465645f6266725f7465726d696e616c9e757365645f636f6c6f737375735f636c75737465725f626f6d625f706f64a0757365645f636f6c6f737375735f6475616c5f3130306d6d5f63616e6e6f6e7399757365645f636f6c6f737375735f74616e6b5f63616e6e6f6e96766973697465645f656e657267795f6372797374616c9b757365645f68656176795f6772656e6164655f6c61756e6368657298757365645f33356d6d5f726f74617279636861696e67756e8b757365645f6b6174616e6190757365645f33356d6d5f63616e6e6f6e93757365645f7265617665725f776561706f6e7396757365645f6c696768746e696e675f776561706f6e738c757365645f6d65645f61707090757365645f32306d6d5f63616e6e6f6e98766973697465645f6d6f6e6f6c6974685f616d657269736899766973697465645f6d6f6e6f6c6974685f636572797368656e97766973697465645f6d6f6e6f6c6974685f637973736f7297766973697465645f6d6f6e6f6c6974685f6573616d697299766973697465645f6d6f6e6f6c6974685f666f72736572616c99766973697465645f6d6f6e6f6c6974685f697368756e64617298766973697465645f6d6f6e6f6c6974685f7365617268757397766973697465645f6d6f6e6f6c6974685f736f6c73617292757365645f6e635f6865765f66616c636f6e99757365645f6e635f6865765f7363617474657263616e6e6f6e93757365645f6e635f6865765f73706172726f7791757365645f61726d6f725f736970686f6e9f757365645f706572656772696e655f6475616c5f6d616368696e655f67756e9f757365645f706572656772696e655f6475616c5f726f636b65745f706f647399757365645f706572656772696e655f6d65636868616d6d65729e757365645f706572656772696e655f7061727469636c655f63616e6e6f6e96757365645f706572656772696e655f73706172726f7791757365645f3130356d6d5f63616e6e6f6e92757365645f31356d6d5f636861696e67756ea0757365645f70756c7365645f7061727469636c655f616363656c657261746f7293757365645f726f74617279636861696e67756e9f766973697465645f6465636f6e737472756374696f6e5f7465726d696e616c95757365645f736b7967756172645f776561706f6e7391766973697465645f67656e657261746f7291757365645f67617573735f63616e6e6f6e89757365645f7472656b95757365645f76616e67756172645f776561706f6e73a4766973697465645f616e6369656e745f6169725f76656869636c655f7465726d696e616ca2766973697465645f616e6369656e745f65717569706d656e745f7465726d696e616c96766973697465645f6f726465725f7465726d696e616ca7766973697465645f616e6369656e745f67726f756e645f76656869636c655f7465726d696e616c9f766973697465645f67726f756e645f76656869636c655f7465726d696e616c97757365645f76756c747572655f626f6d6261726469657298757365645f76756c747572655f6e6f73655f63616e6e6f6e98757365645f76756c747572655f7461696c5f63616e6e6f6e97757365645f776173705f776561706f6e5f73797374656d91766973697465645f636861726c6965303191766973697465645f636861726c6965303291766973697465645f636861726c6965303391766973697465645f636861726c6965303491766973697465645f636861726c6965303591766973697465645f636861726c6965303691766973697465645f636861726c6965303791766973697465645f636861726c6965303891766973697465645f636861726c6965303996766973697465645f67696e6765726d616e5f6174617298766973697465645f67696e6765726d616e5f646168616b6196766973697465645f67696e6765726d616e5f6876617296766973697465645f67696e6765726d616e5f697a686199766973697465645f67696e6765726d616e5f6a616d7368696498766973697465645f67696e6765726d616e5f6d697468726198766973697465645f67696e6765726d616e5f726173686e7599766973697465645f67696e6765726d616e5f7372616f73686198766973697465645f67696e6765726d616e5f79617a61746195766973697465645f67696e6765726d616e5f7a616c8e766973697465645f736c656430318e766973697465645f736c656430328e766973697465645f736c656430348e766973697465645f736c656430358e766973697465645f736c656430368e766973697465645f736c656430378e766973697465645f736c6564303897766973697465645f736e6f776d616e5f616d657269736898766973697465645f736e6f776d616e5f636572797368656e96766973697465645f736e6f776d616e5f637973736f7296766973697465645f736e6f776d616e5f6573616d697298766973697465645f736e6f776d616e5f666f72736572616c96766973697465645f736e6f776d616e5f686f7373696e98766973697465645f736e6f776d616e5f697368756e64617297766973697465645f736e6f776d616e5f7365617268757396766973697465645f736e6f776d616e5f736f6c736172857567643036857567643035857567643034857567643033857567643032857567643031856d61703939856d61703938856d61703937856d61703936856d61703135856d61703134856d61703131856d61703038856d61703034856d61703035856d61703033856d61703031856d61703036856d61703032856d61703039856d61703037856d617031300300000091747261696e696e675f73746172745f6e638b747261696e696e675f75698c747261696e696e675f6d61700000000000000000000000000000000000000000800000003d0c04d350840240000010000602429660f80c80000c8004200c1b81480000020000c046f18a47019000019000ca4644304900000040001809e6bb052032000008001a84787211200000080003010714889c06400000100320ff0a42e4000001009e95a7342e03200000080003010408c914064000000001198990c4e4000001000060223b9b2180c800000a00081c20c92c800003600414ec172d900000040001808de1284a0320000320008ef1c336b20000078011d830e6f6400000600569c417e2c80000020000c04102502f019000008c00ce31027d99000000400018099e6146203200004b0015a7d44002f720000008000301040c18dc064000023000b1240800636400000100006020e0e92280c80000c800081650c00cfc800006400ce32a1801a59000000400018099e6fc3e03200004b00058b14680463200000080003010742610c064000043000b16c8880916400000100006020e0d01580c80000c8006714e24012cc80000020000c04cf25c190190000258001032e240307900000c8019c74470061b2000000800030133ced8fc0640000960012d9a8d00f0640000010025b9c1401e4c8000002004b6b23c03d1900000040098f585007b3200000080131a58c00f864000001002536f1c01f4c8000002004a64e2a03f190000004015e1b4580873200000080003010711f8a406400000100110a00c010ee400000100006020e2a51380c8000002002218d21021ec80000020000c041c40249019000000400af18a44043f90000004000180838b44760320000008015e38c80088320000008000301071490cc064000001002bc35890110e400000100006020e2052180c800000200221f90d0222c80000020000c041c5e447019000000400442e62e044790000004000180838af032032000000800886d08c089320000008000301071738740640000010011098898112e400000100006020e2361c80c8000002002212a1b0226c80000020000c041c512170190000004004420a32044f900000040001808389104a0320000008008874c8808a3200000080003010715907c06400000100110c0898114e400000100006020e2771a80c800000200578bd13022ac80000020000c041c424330190000004004423848045790000004000180838bfc32032000000801a86506008b320000008000301071030dc06400000100129f68a0117640000010026353110232c8000002004b69438046d90000004015e2887008eb200000080003010715909406400000100350fb8e011de400000100006020e2881980c8000002005786d0f023cc80000020000c041c4cc3b019000000400af1ba1c047b90000004000180838af872032000000800886344408fb20000008000301071620d406400000100110c10b011fe400000100006020e2870d80c800000200578f30c0240c80000020000c041c5863b019000000400442ee300483900000040001808388605e032000000801a86f03c090b200000080003010712a8fc064000001002bc0d858121e400000100006020e2521c80c800000200578b7230244c80000020000c041c49629019000000400d434026048b90000004000180838afc42032000000801a86d864091b200000080003010711989c064000001003508c8c8123e400000100006020e2a82280c8000002006a14f110248c80000020000c041c4be21019000000400af12640049390000004000180838a54720320000008015e33430092b20000008000301071228cc064000001003546e8d432400000100004f34a631139000004001b0834723120000008000204000c2ed0fa1c800000200a8432234a90000004000180952b248a0320000018004024c569d20000008000250a4d0ebc480000020000c04a24bc43019000000c00e0" + + "DetailedCharacterData" should { + "decode" in { + PacketCoding.DecodePacket(string_testchar).require match { + case ObjectCreateDetailedMessage(len, cls, guid, parent, data) => + len mustEqual 3159 + cls mustEqual ObjectClass.avatar + guid mustEqual PlanetSideGUID(75) + parent.isDefined mustEqual false + data.isDefined mustEqual true + val char = data.get.asInstanceOf[DetailedCharacterData] + char.appearance.pos.coord.x mustEqual 3674.8438f + char.appearance.pos.coord.y mustEqual 2726.789f + char.appearance.pos.coord.z mustEqual 91.15625f + char.appearance.pos.orient.x mustEqual 0 + char.appearance.pos.orient.y mustEqual 0f + char.appearance.pos.orient.z mustEqual 36.5625f + char.appearance.basic_appearance.name mustEqual "IlllIIIlllIlIllIlllIllI" + char.appearance.basic_appearance.faction mustEqual PlanetSideEmpire.VS + char.appearance.basic_appearance.sex mustEqual CharacterGender.Female + char.appearance.basic_appearance.head mustEqual 41 + char.appearance.basic_appearance.voice mustEqual 1 //female 1 + char.appearance.voice2 mustEqual 3 + char.appearance.black_ops mustEqual false + char.appearance.jammered mustEqual false + char.appearance.exosuit mustEqual ExoSuitType.Standard + char.appearance.outfit_name mustEqual "" + char.appearance.outfit_logo mustEqual 0 + char.appearance.backpack mustEqual false + char.appearance.facingPitch mustEqual 2.8125f + char.appearance.facingYawUpper mustEqual 210.9375f + char.appearance.lfs mustEqual true + char.appearance.grenade_state mustEqual GrenadeState.None + char.appearance.is_cloaking mustEqual false + char.appearance.charging_pose mustEqual false + char.appearance.on_zipline mustEqual false + char.appearance.ribbons.upper mustEqual MeritCommendation.None + char.appearance.ribbons.middle mustEqual MeritCommendation.None + char.appearance.ribbons.lower mustEqual MeritCommendation.None + char.appearance.ribbons.tos mustEqual MeritCommendation.None + char.bep mustEqual 0 + char.cep mustEqual 0 + char.healthMax mustEqual 100 + char.health mustEqual 100 + char.armor mustEqual 50 //standard exosuit value + char.unk1 mustEqual 1 + char.unk2 mustEqual 7 + char.unk3 mustEqual 7 + char.staminaMax mustEqual 100 + char.stamina mustEqual 100 + char.certs.length mustEqual 7 + char.certs.head mustEqual CertificationType.StandardAssault + char.certs(1) mustEqual CertificationType.MediumAssault + char.certs(2) mustEqual CertificationType.ATV + char.certs(3) mustEqual CertificationType.Harasser + char.certs(4) mustEqual CertificationType.StandardExoSuit + char.certs(5) mustEqual CertificationType.AgileExoSuit + char.certs(6) mustEqual CertificationType.ReinforcedExoSuit + char.implants.length mustEqual 0 + char.firstTimeEvents.size mustEqual 4 + char.firstTimeEvents.head mustEqual "xpe_sanctuary_help" + char.firstTimeEvents(1) mustEqual "xpe_th_firemodes" + char.firstTimeEvents(2) mustEqual "used_beamer" + char.firstTimeEvents(3) mustEqual "map13" + char.tutorials.size mustEqual 0 + char.cosmetics.isDefined mustEqual false + char.inventory.isDefined mustEqual true + val inventory = char.inventory.get.contents + inventory.size mustEqual 10 + //0 + inventory.head.objectClass mustEqual ObjectClass.beamer + inventory.head.guid mustEqual PlanetSideGUID(76) + inventory.head.parentSlot mustEqual 0 + var wep = inventory.head.obj.asInstanceOf[DetailedWeaponData] + wep.ammo.head.objectClass mustEqual ObjectClass.energy_cell + wep.ammo.head.guid mustEqual PlanetSideGUID(77) + wep.ammo.head.parentSlot mustEqual 0 + wep.ammo.head.obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 16 + //1 + inventory(1).objectClass mustEqual ObjectClass.suppressor + inventory(1).guid mustEqual PlanetSideGUID(78) + inventory(1).parentSlot mustEqual 2 + wep = inventory(1).obj.asInstanceOf[DetailedWeaponData] + wep.ammo.head.objectClass mustEqual ObjectClass.bullet_9mm + wep.ammo.head.guid mustEqual PlanetSideGUID(79) + wep.ammo.head.parentSlot mustEqual 0 + wep.ammo.head.obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 25 + //2 + inventory(2).objectClass mustEqual ObjectClass.forceblade + inventory(2).guid mustEqual PlanetSideGUID(80) + inventory(2).parentSlot mustEqual 4 + wep = inventory(2).obj.asInstanceOf[DetailedWeaponData] + wep.ammo.head.objectClass mustEqual ObjectClass.melee_ammo + wep.ammo.head.guid mustEqual PlanetSideGUID(81) + wep.ammo.head.parentSlot mustEqual 0 + wep.ammo.head.obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 1 + //3 + inventory(3).objectClass mustEqual ObjectClass.locker_container + inventory(3).guid mustEqual PlanetSideGUID(82) + inventory(3).parentSlot mustEqual 5 + inventory(3).obj.isInstanceOf[DetailedLockerContainerData] mustEqual true + inventory(3).obj.asInstanceOf[DetailedLockerContainerData].inventory.isDefined mustEqual false + //4 + inventory(4).objectClass mustEqual ObjectClass.bullet_9mm + inventory(4).guid mustEqual PlanetSideGUID(83) + inventory(4).parentSlot mustEqual 6 + inventory(4).obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 50 + //5 + inventory(5).objectClass mustEqual ObjectClass.bullet_9mm + inventory(5).guid mustEqual PlanetSideGUID(84) + inventory(5).parentSlot mustEqual 9 + inventory(5).obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 50 + //6 + inventory(6).objectClass mustEqual ObjectClass.bullet_9mm + inventory(6).guid mustEqual PlanetSideGUID(85) + inventory(6).parentSlot mustEqual 12 + inventory(6).obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 50 + //7 + inventory(7).objectClass mustEqual ObjectClass.bullet_9mm_AP + inventory(7).guid mustEqual PlanetSideGUID(86) + inventory(7).parentSlot mustEqual 33 + inventory(7).obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 50 + //8 + inventory(8).objectClass mustEqual ObjectClass.energy_cell + inventory(8).guid mustEqual PlanetSideGUID(87) + inventory(8).parentSlot mustEqual 36 + inventory(8).obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 50 + //9 + inventory(9).objectClass mustEqual ObjectClass.remote_electronics_kit + inventory(9).guid mustEqual PlanetSideGUID(88) + inventory(9).parentSlot mustEqual 39 + //the rek has data but none worth testing here + char.drawn_slot mustEqual DrawnSlot.Pistol1 + case _ => + ko + } + } + + "decode (BR32)" in { + PacketCoding.DecodePacket(string_testchar_br32).require match { + case ObjectCreateDetailedMessage(len, cls, guid, parent, data) => + //this test is mainly for an alternate bitstream parsing order + //the object produced is massive and most of it is already covered in other tests + //only certain details towards the end of the stream will be checked + data.isDefined mustEqual true + val char = data.get.asInstanceOf[DetailedCharacterData] + DetailedCharacterData.isBR24(char.bep) mustEqual true + char.certs.size mustEqual 15 + char.certs.head mustEqual CertificationType.StandardAssault + char.certs(14) mustEqual CertificationType.CombatEngineering + char.implants.size mustEqual 3 + char.implants.head.implant mustEqual ImplantType.AudioAmplifier + char.implants.head.activation mustEqual None + char.implants(1).implant mustEqual ImplantType.Targeting + char.implants(1).activation mustEqual None + char.implants(2).implant mustEqual ImplantType.Surge + char.implants(2).activation mustEqual None + char.firstTimeEvents.size mustEqual 298 + char.firstTimeEvents.head mustEqual "xpe_overhead_map" + char.firstTimeEvents(297) mustEqual "map10" + char.tutorials.size mustEqual 3 + char.tutorials.head mustEqual "training_start_nc" + char.tutorials(1) mustEqual "training_ui" + char.tutorials(2) mustEqual "training_map" + char.cosmetics.isDefined mustEqual true + char.cosmetics.get.no_helmet mustEqual true + char.cosmetics.get.beret mustEqual true + char.cosmetics.get.earpiece mustEqual true + char.cosmetics.get.sunglasses mustEqual true + char.cosmetics.get.brimmed_cap mustEqual false + //inventory + char.inventory.isDefined mustEqual true + char.inventory.get.contents.size mustEqual 12 + //0 + char.inventory.get.contents.head.objectClass mustEqual 531 + char.inventory.get.contents.head.guid mustEqual PlanetSideGUID(4202) + char.inventory.get.contents.head.parentSlot mustEqual 0 + val wep1 = char.inventory.get.contents.head.obj.asInstanceOf[DetailedWeaponData] + wep1.unk1 mustEqual 2 + wep1.unk2 mustEqual 8 + wep1.ammo.head.objectClass mustEqual 389 + wep1.ammo.head.guid mustEqual PlanetSideGUID(3942) + wep1.ammo.head.parentSlot mustEqual 0 + wep1.ammo.head.obj.asInstanceOf[DetailedAmmoBoxData].unk mustEqual 8 + wep1.ammo.head.obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 100 + //4 + char.inventory.get.contents(4).objectClass mustEqual 456 + char.inventory.get.contents(4).guid mustEqual PlanetSideGUID(5374) + char.inventory.get.contents(4).parentSlot mustEqual 5 + char.inventory.get.contents(4).obj.asInstanceOf[DetailedLockerContainerData].inventory.get.contents.size mustEqual 61 + //11 + char.inventory.get.contents(11).objectClass mustEqual 673 + char.inventory.get.contents(11).guid mustEqual PlanetSideGUID(3661) + char.inventory.get.contents(11).parentSlot mustEqual 60 + val wep2 = char.inventory.get.contents(11).obj.asInstanceOf[DetailedWeaponData] + wep2.unk1 mustEqual 2 + wep2.unk2 mustEqual 8 + wep2.ammo.head.objectClass mustEqual 674 + wep2.ammo.head.guid mustEqual PlanetSideGUID(8542) + wep2.ammo.head.parentSlot mustEqual 0 + wep2.ammo.head.obj.asInstanceOf[DetailedAmmoBoxData].unk mustEqual 8 + wep2.ammo.head.obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 3 + char.drawn_slot mustEqual DrawnSlot.None + case _ => + ko + } + } + + "encode (character)" in { + val app = CharacterAppearanceData( + PlacementData( + Vector3(3674.8438f, 2726.789f, 91.15625f), + Vector3(0f, 0f, 36.5625f) + ), + BasicCharacterData( + "IlllIIIlllIlIllIlllIllI", + PlanetSideEmpire.VS, + CharacterGender.Female, + 41, + 1 + ), + 3, + false, + false, + ExoSuitType.Standard, + "", + 0, + false, + 2.8125f, 210.9375f, + true, + GrenadeState.None, + false, + false, + false, + RibbonBars() + ) + val inv = InventoryItemData(ObjectClass.beamer, PlanetSideGUID(76), 0, DetailedWeaponData(4, 8, ObjectClass.energy_cell, PlanetSideGUID(77), 0, DetailedAmmoBoxData(8, 16))) :: + InventoryItemData(ObjectClass.suppressor, PlanetSideGUID(78), 2, DetailedWeaponData(4, 8, ObjectClass.bullet_9mm, PlanetSideGUID(79), 0, DetailedAmmoBoxData(8, 25))) :: + InventoryItemData(ObjectClass.forceblade, PlanetSideGUID(80), 4, DetailedWeaponData(4, 8, ObjectClass.melee_ammo, PlanetSideGUID(81), 0, DetailedAmmoBoxData(8, 1))) :: + InventoryItemData(ObjectClass.locker_container, PlanetSideGUID(82), 5, DetailedLockerContainerData(8)) :: + InventoryItemData(ObjectClass.bullet_9mm, PlanetSideGUID(83), 6, DetailedAmmoBoxData(8, 50)) :: + InventoryItemData(ObjectClass.bullet_9mm, PlanetSideGUID(84), 9, DetailedAmmoBoxData(8, 50)) :: + InventoryItemData(ObjectClass.bullet_9mm, PlanetSideGUID(85), 12, DetailedAmmoBoxData(8, 50)) :: + InventoryItemData(ObjectClass.bullet_9mm_AP, PlanetSideGUID(86), 33, DetailedAmmoBoxData(8, 50)) :: + InventoryItemData(ObjectClass.energy_cell, PlanetSideGUID(87), 36, DetailedAmmoBoxData(8, 50)) :: + InventoryItemData(ObjectClass.remote_electronics_kit, PlanetSideGUID(88), 39, DetailedREKData(8)) :: + Nil + val obj = DetailedCharacterData( + app, + 0, + 0, + 100, 100, + 50, + 1, 7, 7, + 100, 100, + List( + CertificationType.StandardAssault, + CertificationType.MediumAssault, + CertificationType.ATV, + CertificationType.Harasser, + CertificationType.StandardExoSuit, + CertificationType.AgileExoSuit, + CertificationType.ReinforcedExoSuit + ), + List(), + "xpe_sanctuary_help" :: "xpe_th_firemodes" :: "used_beamer" :: "map13" :: Nil, + List.empty, + None, + Some(InventoryData(inv)), + DrawnSlot.Pistol1 + ) + val msg = ObjectCreateDetailedMessage(0x79, PlanetSideGUID(75), obj) + val pkt = PacketCoding.EncodePacket(msg).require.toByteVector + + val pkt_bitv = pkt.toBitVector + val ori_bitv = string_testchar.toBitVector + pkt_bitv.take(153) mustEqual ori_bitv.take(153) //skip 1 + pkt_bitv.drop(154).take(422) mustEqual ori_bitv.drop(154).take(422) //skip 126 + pkt_bitv.drop(702).take(29) mustEqual ori_bitv.drop(702).take(29) //skip 1 + pkt_bitv.drop(732) mustEqual ori_bitv.drop(732) + //TODO work on DetailedCharacterData to make this pass as a single stream + } + + "encode (character, br32)" in { + val obj = DetailedCharacterData( + CharacterAppearanceData( + PlacementData( + Vector3(5500.0f, 3800.0f, 71.484375f), + Vector3(0.0f, 0.0f, 90.0f), + None + ), + BasicCharacterData("KiCkJr", PlanetSideEmpire.NC, CharacterGender.Male, 24, 4), + 3, + false, false, + ExoSuitType.Agile, + "", + 14, + false, + 354.375f, 354.375f, + false, + GrenadeState.None, + false, false, false, + RibbonBars(MeritCommendation.Loser4, MeritCommendation.EventNCElite, MeritCommendation.HeavyAssault6, MeritCommendation.SixYearNC) + ), + 6366766, + 694787, + 100, 100, 100, + 1, 7, 7, + 100, 46, + List( + CertificationType.StandardAssault, + CertificationType.MediumAssault, + CertificationType.HeavyAssault, + CertificationType.AntiVehicular, + CertificationType.AirCavalryScout, + CertificationType.GroundSupport, + CertificationType.Harasser, + CertificationType.StandardExoSuit, + CertificationType.AgileExoSuit, + CertificationType.Medical, + CertificationType.AdvancedMedical, + CertificationType.Hacking, + CertificationType.AdvancedHacking, + CertificationType.Engineering, + CertificationType.CombatEngineering + ), + List( + ImplantEntry(ImplantType.AudioAmplifier, None), + ImplantEntry(ImplantType.Targeting, None), + ImplantEntry(ImplantType.Surge, None) + ), + List( + "xpe_overhead_map", + "xpe_warp_gate", + "xpe_form_outfit", + "xpe_blackops", + "xpe_command_rank_5", + "xpe_command_rank_3", + "xpe_sanctuary_help", + "xpe_battle_rank_13", + "xpe_battle_rank_12", + "xpe_battle_rank_10", + "xpe_battle_rank_14", + "xpe_battle_rank_15", + "xpe_orbital_shuttle", + "xpe_drop_pod", + "xpe_bind_facility", + "xpe_battle_rank_3", + "xpe_battle_rank_5", + "xpe_battle_rank_4", + "xpe_join_squad", + "xpe_form_squad", + "xpe_instant_action", + "xpe_battle_rank_2", + "xpe_warp_gate_usage", + "xpe_battle_rank_8", + "xpe_battle_rank_11", + "xpe_battle_rank_6", + "xpe_mail_alert", + "xpe_command_rank_1", + "xpe_battle_rank_20", + "xpe_battle_rank_18", + "xpe_battle_rank_19", + "xpe_join_platoon", + "xpe_battle_rank_17", + "xpe_battle_rank_16", + "xpe_join_outfit", + "xpe_battle_rank_25", + "xpe_battle_rank_24", + "xpe_command_rank_4", + "xpe_form_platoon", + "xpe_bind_ams", + "xpe_battle_rank_9", + "xpe_battle_rank_7", + "xpe_th_router", + "xpe_th_flail", + "xpe_th_ant", + "xpe_th_ams", + "xpe_th_ground_p", + "xpe_th_air_p", + "xpe_th_hover", + "xpe_th_ground", + "xpe_th_bfr", + "xpe_th_afterburner", + "xpe_th_air", + "xpe_th_cloak", + "used_oicw", + "used_advanced_ace", + "visited_spitfire_turret", + "visited_spitfire_cloaked", + "visited_spitfire_aa", + "visited_tank_traps", + "visited_portable_manned_turret_nc", + "visited_portable_manned_turret_tr", + "used_magcutter", + "used_chainblade", + "used_forceblade", + "visited_wall_turret", + "visited_ancient_terminal", + "visited_ams", + "visited_ant", + "visited_dropship", + "visited_liberator", + "visited_lightgunship", + "visited_lightning", + "visited_magrider", + "visited_prowler", + "visited_quadstealth", + "visited_skyguard", + "visited_threemanheavybuggy", + "visited_two_man_assault_buggy", + "visited_twomanheavybuggy", + "visited_twomanhoverbuggy", + "visited_vanguard", + "visited_flail", + "visited_router", + "visited_switchblade", + "visited_aurora", + "visited_battlewagon", + "visited_fury", + "visited_quadassault", + "visited_galaxy_gunship", + "visited_apc_tr", + "visited_apc_vs", + "visited_lodestar", + "visited_phantasm", + "visited_thunderer", + "visited_apc_nc", + "visited_vulture", + "visited_wasp", + "visited_mosquito", + "visited_aphelion_flight", + "visited_aphelion_gunner", + "visited_colossus_flight", + "visited_colossus_gunner", + "visited_peregrine_flight", + "visited_peregrine_gunner", + "used_bank", + "visited_resource_silo", + "visited_certification_terminal", + "visited_med_terminal", + "used_nano_dispenser", + "visited_sensor_shield", + "visited_broadcast_warpgate", + "used_phalanx", + "used_phalanx_avcombo", + "used_phalanx_flakcombo", + "visited_warpgate_small", + "used_flamethrower", + "used_ancient_turret_weapon", + "visited_LLU_socket", + "used_energy_gun_nc", + "visited_mediumtransport", + "used_aphelion_immolation_cannon", + "used_grenade_plasma", + "used_grenade_jammer", + "visited_shield_generator", + "visited_motion_sensor", + "visited_health_crystal", + "visited_repair_crystal", + "visited_vehicle_crystal", + "used_grenade_frag", + "used_ace", + "visited_adv_med_terminal", + "used_beamer", + "used_bolt_driver", + "used_cycler", + "used_gauss", + "used_hunterseeker", + "used_isp", + "used_lancer", + "used_lasher", + "used_maelstrom", + "used_phoenix", + "used_pulsar", + "used_punisher", + "used_r_shotgun", + "used_radiator", + "used_rek", + "used_repeater", + "used_rocklet", + "used_striker", + "used_suppressor", + "used_thumper", + "visited_vanu_control_console", + "visited_capture_terminal", + "used_mini_chaingun", + "used_laze_pointer", + "used_telepad", + "used_spiker", + "used_heavy_sniper", + "used_command_uplink", + "used_firebird", + "used_flechette", + "used_heavy_rail_beam", + "used_ilc9", + "visited_generator_terminal", + "visited_locker", + "visited_external_door_lock", + "visited_air_vehicle_terminal", + "visited_galaxy_terminal", + "visited_implant_terminal", + "visited_secondary_capture", + "used_25mm_cannon", + "used_liberator_bombardier", + "visited_repair_silo", + "visited_vanu_module", + "used_flail_weapon", + "used_scythe", + "visited_respawn_terminal", + "used_ballgun", + "used_energy_gun_tr", + "used_anniversary_guna", + "used_anniversary_gunb", + "used_anniversary_gun", + "used_75mm_cannon", + "used_apc_nc_weapon", + "used_apc_tr_weapon", + "used_apc_vs_weapon", + "used_flux_cannon", + "used_aphelion_plasma_rocket_pod", + "used_aphelion_ppa", + "used_fluxpod", + "visited_bfr_terminal", + "used_colossus_cluster_bomb_pod", + "used_colossus_dual_100mm_cannons", + "used_colossus_tank_cannon", + "visited_energy_crystal", + "used_heavy_grenade_launcher", + "used_35mm_rotarychaingun", + "used_katana", + "used_35mm_cannon", + "used_reaver_weapons", + "used_lightning_weapons", + "used_med_app", + "used_20mm_cannon", + "visited_monolith_amerish", + "visited_monolith_ceryshen", + "visited_monolith_cyssor", + "visited_monolith_esamir", + "visited_monolith_forseral", + "visited_monolith_ishundar", + "visited_monolith_searhus", + "visited_monolith_solsar", + "used_nc_hev_falcon", + "used_nc_hev_scattercannon", + "used_nc_hev_sparrow", + "used_armor_siphon", + "used_peregrine_dual_machine_gun", + "used_peregrine_dual_rocket_pods", + "used_peregrine_mechhammer", + "used_peregrine_particle_cannon", + "used_peregrine_sparrow", + "used_105mm_cannon", + "used_15mm_chaingun", + "used_pulsed_particle_accelerator", + "used_rotarychaingun", + "visited_deconstruction_terminal", + "used_skyguard_weapons", + "visited_generator", + "used_gauss_cannon", + "used_trek", + "used_vanguard_weapons", + "visited_ancient_air_vehicle_terminal", + "visited_ancient_equipment_terminal", + "visited_order_terminal", + "visited_ancient_ground_vehicle_terminal", + "visited_ground_vehicle_terminal", + "used_vulture_bombardier", + "used_vulture_nose_cannon", + "used_vulture_tail_cannon", + "used_wasp_weapon_system", + "visited_charlie01", + "visited_charlie02", + "visited_charlie03", + "visited_charlie04", + "visited_charlie05", + "visited_charlie06", + "visited_charlie07", + "visited_charlie08", + "visited_charlie09", + "visited_gingerman_atar", + "visited_gingerman_dahaka", + "visited_gingerman_hvar", + "visited_gingerman_izha", + "visited_gingerman_jamshid", + "visited_gingerman_mithra", + "visited_gingerman_rashnu", + "visited_gingerman_sraosha", + "visited_gingerman_yazata", + "visited_gingerman_zal", + "visited_sled01", + "visited_sled02", + "visited_sled04", + "visited_sled05", + "visited_sled06", + "visited_sled07", + "visited_sled08", + "visited_snowman_amerish", + "visited_snowman_ceryshen", + "visited_snowman_cyssor", + "visited_snowman_esamir", + "visited_snowman_forseral", + "visited_snowman_hossin", + "visited_snowman_ishundar", + "visited_snowman_searhus", + "visited_snowman_solsar", + "ugd06", + "ugd05", + "ugd04", + "ugd03", + "ugd02", + "ugd01", + "map99", + "map98", + "map97", + "map96", + "map15", + "map14", + "map11", + "map08", + "map04", + "map05", + "map03", + "map01", + "map06", + "map02", + "map09", + "map07", + "map10" + ), + List( + "training_start_nc", + "training_ui", + "training_map" + ), + Some(Cosmetics(true, true, true, true, false)), + Some( + InventoryData( + List( + InternalSlot(531, PlanetSideGUID(4202), 0, + DetailedWeaponData(2, 8, List(InternalSlot(389, PlanetSideGUID(3942), 0,DetailedAmmoBoxData(8, 100)))) + ), + InternalSlot(132, PlanetSideGUID(6924), 1, + DetailedWeaponData(2, 8, List(InternalSlot(111, PlanetSideGUID(9157), 0, DetailedAmmoBoxData(8, 100)))) + ), + InternalSlot(714, PlanetSideGUID(8498), 2, + DetailedWeaponData(2, 8, List(InternalSlot(755, PlanetSideGUID(5356), 0, DetailedAmmoBoxData(8, 16)))) + ), + InternalSlot(468, PlanetSideGUID(7198), 4, + DetailedWeaponData(2, 8, List(InternalSlot(540, PlanetSideGUID(5009), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(456, PlanetSideGUID(5374), 5, + DetailedLockerContainerData(8, Some(InventoryData(List( + InternalSlot(429, PlanetSideGUID(3021), 0, + DetailedWeaponData(6, 8, List(InternalSlot(272, PlanetSideGUID(8729), 0, DetailedAmmoBoxData(8, 0)))) + ), + InternalSlot(838, PlanetSideGUID(8467), 9, + DetailedWeaponData(6, 8, List(InternalSlot(839, PlanetSideGUID(8603), 0, DetailedAmmoBoxData(8, 5)))) + ), + InternalSlot(272, PlanetSideGUID(3266), 18, DetailedAmmoBoxData(8, 27)), + InternalSlot(577, PlanetSideGUID(2934), 22, + DetailedWeaponData(6, 8, List(InternalSlot(111, PlanetSideGUID(4682), 0, DetailedAmmoBoxData(8, 100)))) + ), + InternalSlot(839, PlanetSideGUID(3271), 90, DetailedAmmoBoxData(8, 15)), + InternalSlot(839, PlanetSideGUID(7174), 94, DetailedAmmoBoxData(8, 6)), + InternalSlot(429, PlanetSideGUID(6084), 98, + DetailedWeaponData(6, 8, List(InternalSlot(272, PlanetSideGUID(5928), 0, DetailedAmmoBoxData(8, 35)))) + ), + InternalSlot(462, PlanetSideGUID(5000), 108, + DetailedWeaponData(6, 8, List(InternalSlot(463, PlanetSideGUID(6277), 0, DetailedAmmoBoxData(8, 150)))) + ), + InternalSlot(429, PlanetSideGUID(4341), 189, + DetailedWeaponData(6, 8, List(InternalSlot(272, PlanetSideGUID(7043), 0, DetailedAmmoBoxData(8, 35)))) + ), + InternalSlot(556, PlanetSideGUID(4168), 198, + DetailedWeaponData(6, 8, List(InternalSlot(28, PlanetSideGUID(8937), 0, DetailedAmmoBoxData(8, 100)))) + ), + InternalSlot(272, PlanetSideGUID(3173), 207, DetailedAmmoBoxData(8, 50)), + InternalSlot(462, PlanetSideGUID(3221), 210, + DetailedWeaponData(6, 8, List(InternalSlot(463, PlanetSideGUID(4031), 0, DetailedAmmoBoxData(8, 150)))) + ), + InternalSlot(556, PlanetSideGUID(6853), 280, + DetailedWeaponData(6, 8, List(InternalSlot(29, PlanetSideGUID(8524), 0, DetailedAmmoBoxData(8, 67)))) + ), + InternalSlot(556, PlanetSideGUID(4569), 290, + DetailedWeaponData(6, 8, List(InternalSlot(28, PlanetSideGUID(5584), 0, DetailedAmmoBoxData(8, 100)))) + ), + InternalSlot(462, PlanetSideGUID(9294), 300, + DetailedWeaponData(6, 8, List(InternalSlot(463, PlanetSideGUID(3118), 0, DetailedAmmoBoxData(8, 150)))) + ), + InternalSlot(272, PlanetSideGUID(4759), 387, DetailedAmmoBoxData(8, 50)), + InternalSlot(462, PlanetSideGUID(7377), 390, + DetailedWeaponData(6, 8, List(InternalSlot(463, PlanetSideGUID(8155), 0, DetailedAmmoBoxData(8, 150)))) + ), + InternalSlot(843, PlanetSideGUID(6709), 480, DetailedAmmoBoxData(8, 1)), + InternalSlot(843, PlanetSideGUID(5276), 484, DetailedAmmoBoxData(8, 1)), + InternalSlot(843, PlanetSideGUID(7769), 488, DetailedAmmoBoxData(8, 1)), + InternalSlot(844, PlanetSideGUID(5334), 492, DetailedAmmoBoxData(8, 1)), + InternalSlot(844, PlanetSideGUID(6219), 496, DetailedAmmoBoxData(8, 1)), + InternalSlot(842, PlanetSideGUID(7279), 500, DetailedAmmoBoxData(8, 1)), + InternalSlot(842, PlanetSideGUID(5415), 504, DetailedAmmoBoxData(8, 1)), + InternalSlot(175, PlanetSideGUID(5741), 540, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(5183), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(324, PlanetSideGUID(6208), 541, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(5029), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(324, PlanetSideGUID(8589), 542, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(9217), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(175, PlanetSideGUID(8901), 543, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(7633), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(175, PlanetSideGUID(8419), 544, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(6546), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(175, PlanetSideGUID(4715), 545, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(8453), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(324, PlanetSideGUID(3577), 546, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(9202), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(324, PlanetSideGUID(6003), 547, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(3260), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(324, PlanetSideGUID(9140), 548, + DetailedWeaponData(6, 8, List(InternalSlot(540,PlanetSideGUID(3815),0,DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(324, PlanetSideGUID(4913), 549, + DetailedWeaponData(6, 8, List(InternalSlot(540,PlanetSideGUID(7222),0,DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(324, PlanetSideGUID(6954), 550, + DetailedWeaponData(6, 8, List(InternalSlot(540,PlanetSideGUID(2953),0,DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(324, PlanetSideGUID(6405), 551, + DetailedWeaponData(6, 8, List(InternalSlot(540,PlanetSideGUID(4676),0,DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(324, PlanetSideGUID(8915), 552, + DetailedWeaponData(6, 8, List(InternalSlot(540,PlanetSideGUID(4018),0,DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(324, PlanetSideGUID(4993), 553, + DetailedWeaponData(6, 8, List(InternalSlot(540,PlanetSideGUID(6775),0,DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(175, PlanetSideGUID(5053), 554, + DetailedWeaponData(6, 8, List(InternalSlot(540,PlanetSideGUID(6418),0,DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(324, PlanetSideGUID(9244), 555, + DetailedWeaponData(6, 8, List(InternalSlot(540,PlanetSideGUID(3327),0,DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(468, PlanetSideGUID(6292), 556, + DetailedWeaponData(6, 8, List(InternalSlot(540,PlanetSideGUID(6918),0,DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(842, PlanetSideGUID(5357), 558, DetailedAmmoBoxData(8, 1)), + InternalSlot(844, PlanetSideGUID(4435), 562, DetailedAmmoBoxData(8, 1)), + InternalSlot(843, PlanetSideGUID(7242), 566, DetailedAmmoBoxData(8, 1)), + InternalSlot(175, PlanetSideGUID(7330), 570, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(4786), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(468, PlanetSideGUID(7415), 571, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(6536), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(175, PlanetSideGUID(3949), 572, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(7526), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(175, PlanetSideGUID(3805), 573, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(7358), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(324, PlanetSideGUID(4493), 574, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(6852), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(324, PlanetSideGUID(5762), 575, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(3463), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(175, PlanetSideGUID(3315), 576, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(7619), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(324, PlanetSideGUID(6263), 577, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(5912), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(468, PlanetSideGUID(4028), 578, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(8021), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(175, PlanetSideGUID(2843), 579, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(7250), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(175, PlanetSideGUID(9143), 580, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(5195), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(468, PlanetSideGUID(5024), 581, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(4287), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(468, PlanetSideGUID(6582), 582, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(4915), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(468, PlanetSideGUID(6425), 583, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(8872), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(468, PlanetSideGUID(4431), 584, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(4191), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(175, PlanetSideGUID(8339), 585, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(7317), 0, DetailedAmmoBoxData(8, 1)))) + ), + InternalSlot(175, PlanetSideGUID(3277), 586, + DetailedWeaponData(6, 8, List(InternalSlot(540, PlanetSideGUID(6469), 0, DetailedAmmoBoxData(8, 1)))) + ) + )))) + ), + InternalSlot(213, PlanetSideGUID(6877), 6, DetailedCommandDetonaterData(4, 8)), + InternalSlot(755, PlanetSideGUID(6227), 9, DetailedAmmoBoxData(8, 16)), + InternalSlot(728, PlanetSideGUID(7181), 12, DetailedREKData(4, 16)), + InternalSlot(536, PlanetSideGUID(4077), 33, DetailedAmmoBoxData(8, 1)), + InternalSlot(680, PlanetSideGUID(4377), 37, + DetailedWeaponData(2, 8, List(InternalSlot(681, PlanetSideGUID(8905), 0, DetailedAmmoBoxData(8, 3)))) + ), + InternalSlot(32, PlanetSideGUID(5523), 39, DetailedACEData(4)), + InternalSlot(673, PlanetSideGUID(3661), 60, + DetailedWeaponData(2, 8, List(InternalSlot(674, PlanetSideGUID(8542), 0, DetailedAmmoBoxData(8, 3)))) + ) + ) + ) + ), + DrawnSlot.None + ) + val msg = ObjectCreateDetailedMessage(ObjectClass.avatar, PlanetSideGUID(75), obj) + val pkt = PacketCoding.EncodePacket(msg).require.toByteVector + + val pkt_bitv = pkt.toBitVector + val ori_bitv = string_testchar_br32.toBitVector + pkt_bitv.take(153) mustEqual ori_bitv.take(153) //skip 1 + pkt_bitv.drop(154).take(144) mustEqual ori_bitv.drop(154).take(144) //skip 24 + pkt_bitv.drop(322).take(72) mustEqual ori_bitv.drop(322).take(72) //skip 24 + pkt_bitv.drop(418).take(55) mustEqual ori_bitv.drop(418).take(55) //skip 1 + pkt_bitv.drop(474).take(102) mustEqual ori_bitv.drop(474).take(102) //skip 126 + pkt_bitv.drop(702).take(192) mustEqual ori_bitv.drop(702).take(192) //skip 36 + pkt_bitv.drop(930) mustEqual ori_bitv.drop(930) //to end + } + } +} diff --git a/common/src/test/scala/game/objectcreatedetailed/DetailedCommandDetonaterDataTest.scala b/common/src/test/scala/game/objectcreatedetailed/DetailedCommandDetonaterDataTest.scala new file mode 100644 index 000000000..b1cebb955 --- /dev/null +++ b/common/src/test/scala/game/objectcreatedetailed/DetailedCommandDetonaterDataTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreatedetailed/DetailedREKDataTest.scala b/common/src/test/scala/game/objectcreatedetailed/DetailedREKDataTest.scala new file mode 100644 index 000000000..5b1ead2da --- /dev/null +++ b/common/src/test/scala/game/objectcreatedetailed/DetailedREKDataTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreatedetailed/DetailedWeaponDataTest.scala b/common/src/test/scala/game/objectcreatedetailed/DetailedWeaponDataTest.scala new file mode 100644 index 000000000..90c92a2a0 --- /dev/null +++ b/common/src/test/scala/game/objectcreatedetailed/DetailedWeaponDataTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreatevehicle/DestroyedVehiclesTest.scala b/common/src/test/scala/game/objectcreatevehicle/DestroyedVehiclesTest.scala new file mode 100644 index 000000000..fe51669fe --- /dev/null +++ b/common/src/test/scala/game/objectcreatevehicle/DestroyedVehiclesTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreatevehicle/NonstandardVehiclesTest.scala b/common/src/test/scala/game/objectcreatevehicle/NonstandardVehiclesTest.scala new file mode 100644 index 000000000..aec38af8a --- /dev/null +++ b/common/src/test/scala/game/objectcreatevehicle/NonstandardVehiclesTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreatevehicle/NormalVehiclesTest.scala b/common/src/test/scala/game/objectcreatevehicle/NormalVehiclesTest.scala new file mode 100644 index 000000000..9dd75b48c --- /dev/null +++ b/common/src/test/scala/game/objectcreatevehicle/NormalVehiclesTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreatevehicle/UtilityVehiclesTest.scala b/common/src/test/scala/game/objectcreatevehicle/UtilityVehiclesTest.scala new file mode 100644 index 000000000..930c7e3a6 --- /dev/null +++ b/common/src/test/scala/game/objectcreatevehicle/UtilityVehiclesTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/game/objectcreatevehicle/VariantVehiclesTest.scala b/common/src/test/scala/game/objectcreatevehicle/VariantVehiclesTest.scala new file mode 100644 index 000000000..c1203d6ce --- /dev/null +++ b/common/src/test/scala/game/objectcreatevehicle/VariantVehiclesTest.scala @@ -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 + } + } +} diff --git a/common/src/test/scala/objects/ConverterTest.scala b/common/src/test/scala/objects/ConverterTest.scala index b4e5ec24a..fe4f8d585 100644 --- a/common/src/test/scala/objects/ConverterTest.scala +++ b/common/src/test/scala/objects/ConverterTest.scala @@ -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) diff --git a/common/src/test/scala/objects/EquipmentTest.scala b/common/src/test/scala/objects/EquipmentTest.scala index 02847c63c..db2de872e 100644 --- a/common/src/test/scala/objects/EquipmentTest.scala +++ b/common/src/test/scala/objects/EquipmentTest.scala @@ -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 diff --git a/common/src/test/scala/objects/PlayerTest.scala b/common/src/test/scala/objects/PlayerTest.scala index 8f7980703..2e737e96d 100644 --- a/common/src/test/scala/objects/PlayerTest.scala +++ b/common/src/test/scala/objects/PlayerTest.scala @@ -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 diff --git a/common/src/test/scala/objects/VehicleSpawnPadTest.scala b/common/src/test/scala/objects/VehicleSpawnPadTest.scala index 5005661f5..61f1deeb9 100644 --- a/common/src/test/scala/objects/VehicleSpawnPadTest.scala +++ b/common/src/test/scala/objects/VehicleSpawnPadTest.scala @@ -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) diff --git a/common/src/test/scala/objects/number/NumberPoolHubTest.scala b/common/src/test/scala/objects/number/NumberPoolHubTest.scala index 551d09098..6e614c095 100644 --- a/common/src/test/scala/objects/number/NumberPoolHubTest.scala +++ b/common/src/test/scala/objects/number/NumberPoolHubTest.scala @@ -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 + } } } diff --git a/common/src/test/scala/objects/number/NumberPoolTest.scala b/common/src/test/scala/objects/number/NumberPoolTest.scala index f29bbc0a9..e448e7322 100644 --- a/common/src/test/scala/objects/number/NumberPoolTest.scala +++ b/common/src/test/scala/objects/number/NumberPoolTest.scala @@ -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) diff --git a/common/src/test/scala/objects/number/NumberSourceTest.scala b/common/src/test/scala/objects/number/NumberSourceTest.scala index dac0df170..f60e6ec9d 100644 --- a/common/src/test/scala/objects/number/NumberSourceTest.scala +++ b/common/src/test/scala/objects/number/NumberSourceTest.scala @@ -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() diff --git a/common/src/test/scala/objects/number/RegisterTest.scala b/common/src/test/scala/objects/number/RegisterTest.scala new file mode 100644 index 000000000..5bde0af03 --- /dev/null +++ b/common/src/test/scala/objects/number/RegisterTest.scala @@ -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) + } + } +} diff --git a/common/src/test/scala/objects/terminal/TerminalControlTest.scala b/common/src/test/scala/objects/terminal/TerminalControlTest.scala index 4d587292e..ddb6ad521 100644 --- a/common/src/test/scala/objects/terminal/TerminalControlTest.scala +++ b/common/src/test/scala/objects/terminal/TerminalControlTest.scala @@ -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() { diff --git a/pslogin/src/main/scala/PacketCodingActor.scala b/pslogin/src/main/scala/PacketCodingActor.scala index 7fc39476e..9d597ba67 100644 --- a/pslogin/src/main/scala/PacketCodingActor.scala +++ b/pslogin/src/main/scala/PacketCodingActor.scala @@ -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. diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index 4b8ca23d9..f60c694ee 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -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))) } diff --git a/pslogin/src/main/scala/services/avatar/AvatarResponse.scala b/pslogin/src/main/scala/services/avatar/AvatarResponse.scala index 75763c8c8..abcf6246b 100644 --- a/pslogin/src/main/scala/services/avatar/AvatarResponse.scala +++ b/pslogin/src/main/scala/services/avatar/AvatarResponse.scala @@ -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 diff --git a/pslogin/src/main/scala/services/avatar/AvatarService.scala b/pslogin/src/main/scala/services/avatar/AvatarService.scala index 5148b2733..5093c98d8 100644 --- a/pslogin/src/main/scala/services/avatar/AvatarService.scala +++ b/pslogin/src/main/scala/services/avatar/AvatarService.scala @@ -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( diff --git a/pslogin/src/main/test/scala/ActorTest.scala b/pslogin/src/main/test/scala/ActorTest.scala new file mode 100644 index 000000000..116f6b212 --- /dev/null +++ b/pslogin/src/main/test/scala/ActorTest.scala @@ -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 + } + } +} diff --git a/pslogin/src/main/test/scala/AvatarServiceTest.scala b/pslogin/src/main/test/scala/AvatarServiceTest.scala new file mode 100644 index 000000000..a89748005 --- /dev/null +++ b/pslogin/src/main/test/scala/AvatarServiceTest.scala @@ -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 +} diff --git a/pslogin/src/main/test/scala/PacketCodingActorTest.scala b/pslogin/src/main/test/scala/PacketCodingActorTest.scala new file mode 100644 index 000000000..1e7325d63 --- /dev/null +++ b/pslogin/src/main/test/scala/PacketCodingActorTest.scala @@ -0,0 +1,369 @@ +// Copyright (c) 2017 PSForever + +import akka.actor.{ActorRef, Props} +import akka.testkit.TestProbe +import net.psforever.packet.control.ControlSync +import net.psforever.packet.game.objectcreate.ObjectClass +import net.psforever.packet.{ControlPacket, GamePacket, PacketCoding} +import net.psforever.packet.game._ +import scodec.bits._ + +import scala.concurrent.duration._ + +class PacketCodingActor1Test extends ActorTest { + "PacketCodingActor" should { + "construct" in { + system.actorOf(Props[PacketCodingActor], "pca") + //just construct without failing + } + } +} + +class PacketCodingActor2Test extends ActorTest { + "PacketCodingActor" should { + "initialize (no r-neighbor)" in { + val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca") + within(200 millis) { + pca ! HelloFriend(135, List.empty[ActorRef].iterator) + expectNoMsg + } + } + } +} + +class PacketCodingActor3Test extends ActorTest { + "PacketCodingActor" should { + "initialize (an r-neighbor)" in { + val probe1 = TestProbe() + val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe") + val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca") + val iter = List(probe2).iterator + val msg = HelloFriend(135, iter) + + assert(iter.hasNext) + pca ! msg + probe1.expectMsg(msg) //pca will pass message directly; a new HelloFriend would be an unequal different object + assert(!iter.hasNext) + } + } +} + +class PacketCodingActor4Test extends ActorTest { + val string_hex = RawPacket(hex"2A 9F05 D405 86") + val string_obj = ObjectAttachMessage(PlanetSideGUID(1439), PlanetSideGUID(1492), 6) + + "PacketCodingActor" should { + "translate r-originating game packet into l-facing hexadecimal data" in { + val probe1 = TestProbe() + val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe") + val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca") + pca ! HelloFriend(135, List(probe2).iterator) + probe1.receiveOne(100 milli) //consume + + val msg = ActorTest.MDCGamePacket(PacketCoding.CreateGamePacket(0, string_obj)) + probe2 ! msg + val reply1 = receiveOne(100 milli) //we get a MdcMsg message back + probe2 ! reply1 //by feeding the MdcMsg into the actor, we get normal output on the probe + probe1.expectMsg(string_hex) + } + } +} + +class PacketCodingActor5Test extends ActorTest { + val string_hex = RawPacket(hex"2A 9F05 D405 86") + val string_obj = ObjectAttachMessage(PlanetSideGUID(1439), PlanetSideGUID(1492), 6) + + "PacketCodingActor" should { + "translate l-originating hexadecimal data into r-facing game packet" in { + val probe1 = TestProbe() + val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe") + val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca") + pca ! HelloFriend(135, List(probe2).iterator) + probe1.receiveOne(100 milli) //consume + + pca ! string_hex + val reply = probe1.receiveOne(100 milli) + reply match { + case GamePacket(_, _, msg) => ; + assert(msg == string_obj) + case _ => + assert(false) + } + } + } +} + +class PacketCodingActor6Test extends ActorTest { + val string_obj = ObjectAttachMessage(PlanetSideGUID(1439), PlanetSideGUID(1492), 6) + + "PacketCodingActor" should { + "permit l-originating game packet to pass through as an r-facing game packet" in { + val probe1 = TestProbe() + val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe") + val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca") + pca ! HelloFriend(135, List(probe2).iterator) + probe1.receiveOne(100 milli) //consume + + val msg = PacketCoding.CreateGamePacket(0, string_obj) + pca ! msg + probe1.expectMsg(msg) + } + } +} + +class PacketCodingActor7Test extends ActorTest { + val string_hex = RawPacket(hex"0007 5268 0000004D 00000052 0000004D 0000007C 0000004D 0000000000000276 0000000000000275") + val string_obj = ControlSync(21096, 0x4d, 0x52, 0x4d, 0x7c, 0x4d, 0x276, 0x275) + + "PacketCodingActor" should { + "translate r-originating control packet into l-facing hexadecimal data" in { + val probe1 = TestProbe() + val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe") + val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca") + pca ! HelloFriend(135, List(probe2).iterator) + probe1.receiveOne(100 milli) //consume + + val msg = ActorTest.MDCControlPacket(PacketCoding.CreateControlPacket(string_obj)) + probe2 ! msg + val reply1 = receiveOne(100 milli) //we get a MdcMsg message back + probe2 ! reply1 //by feeding the MdcMsg into the actor, we get normal output on the probe + probe1.expectMsg(string_hex) + } + } +} + +class PacketCodingActor8Test extends ActorTest { + val string_hex = RawPacket(hex"0007 5268 0000004D 00000052 0000004D 0000007C 0000004D 0000000000000276 0000000000000275") + val string_obj = ControlSync(21096, 0x4d, 0x52, 0x4d, 0x7c, 0x4d, 0x276, 0x275) + + "PacketCodingActor" should { + "translate l-originating hexadecimal data into r-facing control packet" in { + val probe1 = TestProbe() + val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe") + val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca") + pca ! HelloFriend(135, List(probe2).iterator) + probe1.receiveOne(100 milli) //consume + + pca ! string_hex + val reply = probe1.receiveOne(100 milli) + reply match { + case ControlPacket(_, msg) => ; + assert(msg == string_obj) + case _ => + assert(false) + } + } + } +} + +class PacketCodingActor9Test extends ActorTest { + val string_obj = ControlSync(21096, 0x4d, 0x52, 0x4d, 0x7c, 0x4d, 0x276, 0x275) + + "PacketCodingActor" should { + "permit l-originating control packet to pass through as an r-facing control packet" in { + val probe1 = TestProbe() + val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe") + val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca") + pca ! HelloFriend(135, List(probe2).iterator) + probe1.receiveOne(100 milli) //consume + + val msg = PacketCoding.CreateControlPacket(string_obj) + pca ! msg + probe1.expectMsg(msg) + } + } +} + +class PacketCodingActorATest extends ActorTest { + "PacketCodingActor" should { + "permit l-originating unhandled message to pass through as an r-facing unhandled message" in { + val probe1 = TestProbe() + val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe") + val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca") + pca ! HelloFriend(135, List(probe2).iterator) + probe1.receiveOne(100 milli) //consume + + pca ! "unhandled message" + probe1.expectMsg("unhandled message") + } + } +} + +class PacketCodingActorBTest extends ActorTest { + "PacketCodingActor" should { + "permit r-originating unhandled message to pass through as an l-facing unhandled message" in { + val probe1 = TestProbe() + val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe") + val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca") + pca ! HelloFriend(135, List(probe2).iterator) + probe1.receiveOne(100 milli) //consume + + probe2 ! "unhandled message" + val reply1 = receiveOne(100 milli) //we get a MdcMsg message back + probe2 ! reply1 //by feeding the MdcMsg into the actor, we get normal output on the probe + probe1.expectMsg("unhandled message") + } + } +} + +class PacketCodingActorCTest extends ActorTest { + val string_hex = hex"D5 0B 00 00 00 01 0A E4 0C 02 48 70 75 72 63 68 61 73 65 5F 65 78 65 6D 70 74 5F 76 73 80 92 70 75 72 63 68 61 73 65 5F 65 78 65 6D 70 74 5F 74 72 80 92 70 75 72 63 68 61 73 65 5F 65 78 65 6D 70 74 5F 6E 63 80 11 00 01 14 A4 04 02 1C 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 12 00 01 14 A4 04 02 1C 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 13 00 01 14 A4 04 02 1C 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 14 00 01 14 A4 04 02 1C 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 15 00 01 14 A4 04 02 1C 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 16 00 01 14 A4 04 02 1C 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 1D 00 15 0A 60 04 02 1C 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 54 00 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 76 00 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 87 00 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 C7 00 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 C8 00 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 26 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 52 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 AD 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 B0 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 B9 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 CE 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 D6 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 2C 40 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 82 40 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 83 40 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 B9 40 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 CA 40 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 61 60 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 9B 60 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 DA 60 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 1E 00 15 0A 60 04 02 1C 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 54 00 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 76 00 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 87 00 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 C7 00 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 C8 00 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 26 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 52 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 AD 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 B0 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 B9 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 CE 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 D6 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 2C 40 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 82 40 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 83 40 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 B9 40 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 CA 40 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 61 60 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 9B 60 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 DA 60 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 1F 00 15 0A 60 04 02 1C 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 54 00 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 76 00 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 87 00 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 C7 00 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 C8 00 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 26 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 52 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 AD 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 B0 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 B9 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 CE 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 D6 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 2C 40 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 82 40 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 83 40 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 B9 40 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 CA 40 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 61 60 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 9B 60 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 DA 60 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 20 00 15 0A 60 04 02 1C 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 54 00 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 76 00 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 87 00 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 C7 00 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 C8 00 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 26 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 52 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 AD 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 B0 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 B9 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 CE 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 D6 20 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 2C 40 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 82 40 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 83 40 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 B9 40 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 CA 40 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 61 60 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 9B 60 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65 DA 60 20 10 E0 61 6C 6C 6F 77 65 64 85 66 61 6C 73 65" + + "PacketCodingActor" should { + "should split r-originating hexadecimal data if it is larger than the MTU limit" in { + val probe1 = TestProbe() + val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe") + val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca") + pca ! HelloFriend(135, List(probe2).iterator) + probe1.receiveOne(100 milli) //consume + + val msg = RawPacket(string_hex) + probe2 ! msg + receiveN(4) + //msg4.foreach(str => { probe2 ! str }) + //probe1.receiveN(4) + } + } +} + +class PacketCodingActorDTest extends ActorTest { + val string_obj = PropertyOverrideMessage( + List( + GamePropertyScope(0, + GamePropertyTarget(GamePropertyTarget.game_properties, List( + "purchase_exempt_vs" -> "", + "purchase_exempt_tr" -> "", + "purchase_exempt_nc" -> "" + ) + )), + GamePropertyScope(17, + GamePropertyTarget(ObjectClass.katana, "allowed" -> "false") + ), + GamePropertyScope(18, + GamePropertyTarget(ObjectClass.katana, "allowed" -> "false") + ), + GamePropertyScope(19, + GamePropertyTarget(ObjectClass.katana, "allowed" -> "false") + ), + GamePropertyScope(20, + GamePropertyTarget(ObjectClass.katana, "allowed" -> "false") + ), + GamePropertyScope(21, + GamePropertyTarget(ObjectClass.katana, "allowed" -> "false") + ), + GamePropertyScope(22, + GamePropertyTarget(ObjectClass.katana, "allowed" -> "false") + ), + GamePropertyScope(29, List( + GamePropertyTarget(ObjectClass.aphelion_flight, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.aphelion_gunner, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.aurora, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.battlewagon, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.colossus_flight, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.colossus_gunner, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.flail, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.galaxy_gunship, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.lasher, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.liberator, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.lightgunship, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.maelstrom, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.magrider, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.mini_chaingun, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.peregrine_flight, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.peregrine_gunner, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.prowler, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.r_shotgun, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.thunderer, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.vanguard, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.vulture, "allowed" -> "false") + )), + GamePropertyScope(30, List( + GamePropertyTarget(ObjectClass.aphelion_flight, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.aphelion_gunner, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.aurora, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.battlewagon, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.colossus_flight, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.colossus_gunner, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.flail, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.galaxy_gunship, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.lasher, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.liberator, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.lightgunship, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.maelstrom, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.magrider, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.mini_chaingun, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.peregrine_flight, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.peregrine_gunner, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.prowler, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.r_shotgun, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.thunderer, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.vanguard, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.vulture, "allowed" -> "false") + )), + GamePropertyScope(31, List( + GamePropertyTarget(ObjectClass.aphelion_flight, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.aphelion_gunner, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.aurora, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.battlewagon, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.colossus_flight, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.colossus_gunner, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.flail, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.galaxy_gunship, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.lasher, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.liberator, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.lightgunship, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.maelstrom, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.magrider, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.mini_chaingun, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.peregrine_flight, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.peregrine_gunner, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.prowler, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.r_shotgun, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.thunderer, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.vanguard, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.vulture, "allowed" -> "false") + )), + GamePropertyScope(32, List( + GamePropertyTarget(ObjectClass.aphelion_flight, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.aphelion_gunner, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.aurora, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.battlewagon, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.colossus_flight, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.colossus_gunner, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.flail, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.galaxy_gunship, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.lasher, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.liberator, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.lightgunship, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.maelstrom, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.magrider, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.mini_chaingun, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.peregrine_flight, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.peregrine_gunner, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.prowler, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.r_shotgun, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.thunderer, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.vanguard, "allowed" -> "false"), + GamePropertyTarget(ObjectClass.vulture, "allowed" -> "false") + )) + ) + ) + + "PacketCodingActor" should { + "should split r-originating game packet if it is larger than the MTU limit" in { + val probe1 = TestProbe() + val probe2 = system.actorOf(Props(classOf[ActorTest.MDCTestProbe], probe1), "mdc-probe") + val pca : ActorRef = system.actorOf(Props[PacketCodingActor], "pca") + pca ! HelloFriend(135, List(probe2).iterator) + probe1.receiveOne(100 milli) //consume + + val msg = ActorTest.MDCGamePacket(PacketCoding.CreateGamePacket(0, string_obj)) + probe2 ! msg + receiveN(4) + } + } +} + +object PacketCodingActorTest { + //decoy +}