mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-02-12 19:31:07 +00:00
Restructure repository
* Move /common/src to /src * Move services to net.psforever package * Move /pslogin to /server
This commit is contained in:
parent
89a30ae6f6
commit
f4fd78fc5d
958 changed files with 527 additions and 725 deletions
11
src/test/resources/logback-test.xml
Normal file
11
src/test/resources/logback-test.xml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>[%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="ERROR">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
223
src/test/scala/CodecTest.scala
Normal file
223
src/test/scala/CodecTest.scala
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.newcodecs._
|
||||
import net.psforever.types._
|
||||
import scodec.bits._
|
||||
|
||||
class CodecTest extends Specification {
|
||||
|
||||
"QuantizedDoubleCodec" should {
|
||||
val string_1 = hex"6E2D70"
|
||||
val string_2 = hex"000000"
|
||||
val string_3 = hex"B616"
|
||||
val string_4 = hex"857C"
|
||||
val string_5 = hex"5380"
|
||||
val string_6 = hex"FFFC"
|
||||
|
||||
"decode" in {
|
||||
newcodecs.q_double(0.0, 8192.0, 20).decode(string_1.bits).require.value mustEqual 3674.859375
|
||||
newcodecs.q_double(0.0, 8192.0, 20).decode(string_2.bits).require.value mustEqual 0.0
|
||||
newcodecs.q_double(0.0, 1024.0, 16).decode(string_3.bits).require.value mustEqual 90.84375
|
||||
newcodecs.q_double(-256.0, 256.0, 14).decode(string_4.bits).require.value mustEqual -3.84375
|
||||
newcodecs.q_double(-256.0, 256.0, 14).decode(string_5.bits).require.value mustEqual 2.59375
|
||||
newcodecs.q_double(-256.0, 256.0, 14).decode(string_6.bits).require.value mustEqual 255.96875
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
newcodecs.q_double(0.0, 8192.0, 20).encode(3674.859375).require.bytes mustEqual string_1
|
||||
newcodecs.q_double(0.0, 8192.0, 20).encode(-1.23).require.bytes mustEqual string_2
|
||||
newcodecs.q_double(0.0, 1024.0, 16).encode(90.84375).require.bytes mustEqual string_3
|
||||
newcodecs.q_double(-256.0, 256.0, 14).encode(-3.84375).require.bytes mustEqual string_4
|
||||
newcodecs.q_double(-256.0, 256.0, 14).encode(2.59375).require.bytes mustEqual string_5
|
||||
newcodecs.q_double(-256.0, 256.0, 14).encode(257.0).require.bytes mustEqual string_6
|
||||
}
|
||||
}
|
||||
|
||||
"Vector3" should {
|
||||
"position" should {
|
||||
val string_pos = hex"6E2D762222B616"
|
||||
|
||||
"decode" in {
|
||||
Vector3.codec_pos.decode(string_pos.bits).require.value mustEqual Vector3(3674.859375f, 1092.7656f, 90.84375f)
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
Vector3.codec_pos.encode(Vector3(3674.859375f, 1092.7656f, 90.84375f)).require.bytes mustEqual string_pos
|
||||
}
|
||||
}
|
||||
|
||||
"velocity" should {
|
||||
val string_vel = hex"857D4E0FFFC0"
|
||||
|
||||
"decode" in {
|
||||
Vector3.codec_vel.decode(string_vel.bits).require.value mustEqual Vector3(-3.84375f, 2.59375f, 255.96875f)
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
Vector3.codec_vel.encode(Vector3(-3.84375f, 2.59375f, 255.96875f)).require.bytes mustEqual string_vel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"Angular" should {
|
||||
"roll" should {
|
||||
val string_roll_0 = hex"00"
|
||||
val string_roll_90 = hex"20"
|
||||
val string_roll_180 = hex"40"
|
||||
val string_roll_270 = hex"60"
|
||||
|
||||
"decode (0)" in {
|
||||
Angular.codec_roll.decode(string_roll_0.bits).require.value mustEqual 0f
|
||||
}
|
||||
|
||||
"decode (90)" in {
|
||||
Angular.codec_roll.decode(string_roll_90.bits).require.value mustEqual 90f
|
||||
}
|
||||
|
||||
"decode (180)" in {
|
||||
Angular.codec_roll.decode(string_roll_180.bits).require.value mustEqual 180f
|
||||
}
|
||||
|
||||
"decode (270)" in {
|
||||
Angular.codec_roll.decode(string_roll_270.bits).require.value mustEqual 270f
|
||||
}
|
||||
|
||||
"encode (0)" in {
|
||||
Angular.codec_roll.encode(0f).require.bytes mustEqual string_roll_0
|
||||
}
|
||||
|
||||
"encode (90)" in {
|
||||
Angular.codec_roll.encode(90f).require.bytes mustEqual string_roll_90
|
||||
}
|
||||
|
||||
"encode (180)" in {
|
||||
Angular.codec_roll.encode(180f).require.bytes mustEqual string_roll_180
|
||||
}
|
||||
|
||||
"encode (270)" in {
|
||||
Angular.codec_roll.encode(270f).require.bytes mustEqual string_roll_270
|
||||
}
|
||||
}
|
||||
|
||||
"pitch" should {
|
||||
val string_pitch_0 = hex"00"
|
||||
val string_pitch_90 = hex"60"
|
||||
val string_pitch_180 = hex"40"
|
||||
val string_pitch_270 = hex"20"
|
||||
|
||||
"decode (0)" in {
|
||||
Angular.codec_pitch.decode(string_pitch_0.bits).require.value mustEqual 0f
|
||||
}
|
||||
|
||||
"decode (90)" in {
|
||||
Angular.codec_pitch.decode(string_pitch_90.bits).require.value mustEqual 90f
|
||||
}
|
||||
|
||||
"decode (180)" in {
|
||||
Angular.codec_pitch.decode(string_pitch_180.bits).require.value mustEqual 180f
|
||||
}
|
||||
|
||||
"decode (270)" in {
|
||||
Angular.codec_pitch.decode(string_pitch_270.bits).require.value mustEqual 270f
|
||||
}
|
||||
|
||||
"encode (0)" in {
|
||||
Angular.codec_pitch.encode(0f).require.bytes mustEqual string_pitch_0
|
||||
}
|
||||
|
||||
"encode (90)" in {
|
||||
Angular.codec_pitch.encode(90f).require.bytes mustEqual string_pitch_90
|
||||
}
|
||||
|
||||
"encode (180)" in {
|
||||
Angular.codec_pitch.encode(180f).require.bytes mustEqual string_pitch_180
|
||||
}
|
||||
|
||||
"encode (270)" in {
|
||||
Angular.codec_pitch.encode(270f).require.bytes mustEqual string_pitch_270
|
||||
}
|
||||
}
|
||||
|
||||
"yaw, normal" should {
|
||||
val string_pitch_0 = hex"00"
|
||||
val string_pitch_90 = hex"60"
|
||||
val string_pitch_180 = hex"40"
|
||||
val string_pitch_270 = hex"20"
|
||||
val string_yaw_0 = hex"20"
|
||||
val string_yaw_90 = hex"00"
|
||||
val string_yaw_180 = hex"60"
|
||||
val string_yaw_270 = hex"40"
|
||||
|
||||
"decode (0)" in {
|
||||
Angular.codec_yaw(0f).decode(string_yaw_0.bits).require.value mustEqual 270f
|
||||
}
|
||||
|
||||
"decode (90)" in {
|
||||
Angular.codec_yaw(0f).decode(string_yaw_90.bits).require.value mustEqual 0f
|
||||
}
|
||||
|
||||
"decode (180)" in {
|
||||
Angular.codec_yaw(0f).decode(string_yaw_180.bits).require.value mustEqual 90f
|
||||
}
|
||||
|
||||
"decode (270)" in {
|
||||
Angular.codec_yaw(0f).decode(string_yaw_270.bits).require.value mustEqual 180f
|
||||
}
|
||||
|
||||
"encode (0)" in {
|
||||
Angular.codec_yaw(0f).encode(0f).require.bytes mustEqual string_pitch_0
|
||||
}
|
||||
|
||||
"encode (90)" in {
|
||||
Angular.codec_yaw(0f).encode(90f).require.bytes mustEqual string_pitch_90
|
||||
}
|
||||
|
||||
"encode (180)" in {
|
||||
Angular.codec_yaw(0f).encode(180f).require.bytes mustEqual string_pitch_180
|
||||
}
|
||||
|
||||
"encode (270)" in {
|
||||
Angular.codec_yaw(0f).encode(270f).require.bytes mustEqual string_pitch_270
|
||||
}
|
||||
}
|
||||
|
||||
"yaw, North-corrected" should {
|
||||
val string_yaw_0 = hex"20"
|
||||
val string_yaw_90 = hex"00"
|
||||
val string_yaw_180 = hex"60"
|
||||
val string_yaw_270 = hex"40"
|
||||
|
||||
"decode (0)" in {
|
||||
Angular.codec_yaw().decode(string_yaw_0.bits).require.value mustEqual 0f
|
||||
}
|
||||
|
||||
"decode (90)" in {
|
||||
Angular.codec_yaw().decode(string_yaw_90.bits).require.value mustEqual 90f
|
||||
}
|
||||
|
||||
"decode (180)" in {
|
||||
Angular.codec_yaw().decode(string_yaw_180.bits).require.value mustEqual 180f
|
||||
}
|
||||
|
||||
"decode (270)" in {
|
||||
Angular.codec_yaw().decode(string_yaw_270.bits).require.value mustEqual 270f
|
||||
}
|
||||
|
||||
"encode (0)" in {
|
||||
Angular.codec_yaw().encode(0f).require.bytes mustEqual string_yaw_0
|
||||
}
|
||||
|
||||
"encode (90)" in {
|
||||
Angular.codec_yaw().encode(90f).require.bytes mustEqual string_yaw_90
|
||||
}
|
||||
|
||||
"encode (180)" in {
|
||||
Angular.codec_yaw().encode(180f).require.bytes mustEqual string_yaw_180
|
||||
}
|
||||
|
||||
"encode (270)" in {
|
||||
Angular.codec_yaw().encode(270f).require.bytes mustEqual string_yaw_270
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
136
src/test/scala/CryptoInterfaceTest.scala
Normal file
136
src/test/scala/CryptoInterfaceTest.scala
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.crypto.CryptoInterface
|
||||
import net.psforever.crypto.CryptoInterface.CryptoDHState
|
||||
import scodec.bits._
|
||||
|
||||
class CryptoInterfaceTest extends Specification {
|
||||
args(stopOnFail = true)
|
||||
"Crypto interface" should {
|
||||
"correctly initialize" in {
|
||||
CryptoInterface.initialize()
|
||||
ok
|
||||
}
|
||||
|
||||
"encrypt and decrypt" in {
|
||||
val key = hex"41414141"
|
||||
val plaintext = ByteVector.fill(16)(0x42)
|
||||
|
||||
val crypto = new CryptoInterface.CryptoState(key, key)
|
||||
|
||||
val ciphertext = crypto.encrypt(plaintext)
|
||||
val decrypted = crypto.decrypt(ciphertext)
|
||||
|
||||
crypto.close
|
||||
decrypted mustEqual plaintext
|
||||
ciphertext mustNotEqual plaintext
|
||||
}
|
||||
|
||||
"encrypt and decrypt must handle no bytes" in {
|
||||
val key = hex"41414141"
|
||||
val empty = ByteVector.empty
|
||||
|
||||
val crypto = new CryptoInterface.CryptoState(key, key)
|
||||
|
||||
val ciphertext = crypto.encrypt(empty)
|
||||
val decrypted = crypto.decrypt(ciphertext)
|
||||
|
||||
crypto.close
|
||||
|
||||
ciphertext mustEqual empty
|
||||
decrypted mustEqual empty
|
||||
}
|
||||
|
||||
"encrypt and decrypt must only accept block aligned inputs" in {
|
||||
val key = hex"41414141"
|
||||
val badPad = ByteVector.fill(CryptoInterface.RC5_BLOCK_SIZE - 1)('a')
|
||||
|
||||
val crypto = new CryptoInterface.CryptoState(key, key)
|
||||
|
||||
crypto.encrypt(badPad) must throwA[IllegalArgumentException]
|
||||
crypto.decrypt(badPad) must throwA[IllegalArgumentException]
|
||||
|
||||
crypto.close
|
||||
ok
|
||||
}
|
||||
|
||||
"arrive at a shared secret" in {
|
||||
val server = new CryptoInterface.CryptoDHState()
|
||||
val client = new CryptoInterface.CryptoDHState()
|
||||
|
||||
// 1. Client generates p, g, and its key pair
|
||||
client.start()
|
||||
|
||||
// 2. Client sends p and g to server who then generates a key pair as well
|
||||
server.start(client.getModulus, client.getGenerator)
|
||||
|
||||
// 3. Both parties come to a shared secret
|
||||
val clientAgreed = client.agree(server.getPublicKey)
|
||||
val serverAgreed = server.agree(client.getPublicKey)
|
||||
|
||||
// Free resources
|
||||
server.close
|
||||
client.close
|
||||
|
||||
clientAgreed mustEqual serverAgreed
|
||||
}
|
||||
|
||||
"must fail to agree on a secret with a bad public key" in {
|
||||
val server = new CryptoInterface.CryptoDHState()
|
||||
val client = new CryptoInterface.CryptoDHState()
|
||||
|
||||
// 1. Client generates p, g, and its key pair
|
||||
client.start()
|
||||
|
||||
// 2. Client sends p and g to server who then generates a key pair as well
|
||||
server.start(client.getModulus, client.getGenerator)
|
||||
|
||||
// 3. Client agrees with a bad public key, so it must fail
|
||||
val clientAgreed = client.agree(client.getPublicKey)
|
||||
val serverAgreed = server.agree(client.getPublicKey)
|
||||
|
||||
// Free resources
|
||||
server.close
|
||||
client.close
|
||||
|
||||
clientAgreed mustNotEqual serverAgreed
|
||||
}
|
||||
|
||||
"MD5MAC correctly" in {
|
||||
val key = hex"377b60f8790f91b35a9da82945743da9"
|
||||
val message = ByteVector(Array[Byte]('m', 'a', 's', 't', 'e', 'r', ' ', 's', 'e', 'c', 'r', 'e', 't')) ++
|
||||
hex"b4aea1559444a20b6112a2892de40eac00000000c8aea155b53d187076b79abab59001b600000000"
|
||||
val expected = hex"5aa15de41f5220cf5cca489155e1438c5aa15de4"
|
||||
|
||||
val output = CryptoInterface.MD5MAC(key, message, expected.length.toInt)
|
||||
|
||||
output mustEqual expected
|
||||
}
|
||||
|
||||
"safely handle multiple starts" in {
|
||||
val dontCare = ByteVector.fill(16)(0x42)
|
||||
val dh = new CryptoDHState()
|
||||
|
||||
dh.start()
|
||||
dh.start() must throwA[IllegalStateException]
|
||||
dh.close
|
||||
|
||||
ok
|
||||
}
|
||||
|
||||
"prevent function calls before initialization" in {
|
||||
val dontCare = ByteVector.fill(16)(0x42)
|
||||
val dh = new CryptoDHState()
|
||||
|
||||
dh.getGenerator must throwA[IllegalStateException]
|
||||
dh.getModulus must throwA[IllegalStateException]
|
||||
dh.getPrivateKey must throwA[IllegalStateException]
|
||||
dh.getPublicKey must throwA[IllegalStateException]
|
||||
dh.agree(dontCare) must throwA[IllegalStateException]
|
||||
dh.close
|
||||
|
||||
ok
|
||||
}
|
||||
}
|
||||
}
|
||||
135
src/test/scala/CryptoPacketTest.scala
Normal file
135
src/test/scala/CryptoPacketTest.scala
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet.control.{ClientStart, ServerStart}
|
||||
import net.psforever.packet.crypto.{ClientChallengeXchg, ClientFinished, ServerChallengeXchg, ServerFinished}
|
||||
import scodec.Codec
|
||||
import scodec.bits._
|
||||
|
||||
class CryptoPacketTest extends Specification {
|
||||
|
||||
"PlanetSide crypto packet" in {
|
||||
val cNonce = 656287232
|
||||
|
||||
"ClientStart" should {
|
||||
val string = hex"0000000200261e27000001f0".bits
|
||||
|
||||
"decode" in {
|
||||
val res = Codec.decode[ClientStart](string)
|
||||
res.isSuccessful mustEqual true
|
||||
res.require.value.clientNonce mustEqual cNonce
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val res = Codec.encode(ClientStart(cNonce))
|
||||
|
||||
res.require mustEqual string
|
||||
}
|
||||
}
|
||||
|
||||
"ServerStart" should {
|
||||
val sNonce = 3468803409L
|
||||
val string = hex"00261e2751bdc1ce000000000001d300000002".bits
|
||||
|
||||
"decode" in {
|
||||
val res = Codec.decode[ServerStart](string)
|
||||
val value = res.require.value
|
||||
|
||||
value.clientNonce mustEqual cNonce
|
||||
value.serverNonce mustEqual sNonce
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val res = Codec.encode(ServerStart(cNonce, sNonce))
|
||||
|
||||
res.require mustEqual string
|
||||
}
|
||||
}
|
||||
|
||||
"ClientChallengeXchg" should {
|
||||
val time = hex"962d8453"
|
||||
val timeDecoded = scodec.codecs.uint32L.decode(time.bits).require.value
|
||||
val challenge = hex"24f5997c c7d16031 d1f567e9"
|
||||
val p = hex"f57511eb 8e5d1efb 8b7f3287 d5a18b17"
|
||||
val g = hex"00000000 00000000 00000000 00000002"
|
||||
val string = (hex"0101" ++ time ++ challenge ++ hex"00 01 0002 ff 2400 00 1000" ++
|
||||
p ++ hex"1000" ++ g ++ hex"0000010307000000").bits
|
||||
|
||||
"decode" in {
|
||||
val res = Codec.decode[ClientChallengeXchg](string)
|
||||
val value = res.require.value
|
||||
|
||||
value.time mustEqual timeDecoded
|
||||
value.challenge mustEqual challenge
|
||||
value.p mustEqual p
|
||||
value.g mustEqual g
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val res = Codec.encode(ClientChallengeXchg(timeDecoded, challenge, p, g))
|
||||
|
||||
res.require mustEqual string
|
||||
}
|
||||
}
|
||||
|
||||
"ServerChallengeXchg" should {
|
||||
val time = hex"962d8453"
|
||||
val timeDecoded = scodec.codecs.uint32L.decode(time.bits).require.value
|
||||
val challenge = hex"1b0e6408 cd935ec2 429aeb58"
|
||||
val pubKey = hex"51f83ce6 45e86c3e 79c8fc70 f6ddf14b"
|
||||
val string = (hex"0201" ++ time ++ challenge ++ hex"00 01 03070000000c00 1000 " ++ pubKey ++ hex"0e").bits
|
||||
|
||||
"decode" in {
|
||||
val res = Codec.decode[ServerChallengeXchg](string)
|
||||
val value = res.require.value
|
||||
|
||||
value.time mustEqual timeDecoded
|
||||
value.challenge mustEqual challenge
|
||||
value.pubKey mustEqual pubKey
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val res = Codec.encode(ServerChallengeXchg(timeDecoded, challenge, pubKey))
|
||||
|
||||
res.require mustEqual string
|
||||
}
|
||||
}
|
||||
|
||||
"ClientFinished" should {
|
||||
val challengeResult = hex"ea3cf05d a5cb4256 8bb91aa7"
|
||||
val pubKey = hex"eddc35f2 52b02d0e 496ba273 54578e73"
|
||||
val string = (hex"10 1000" ++ pubKey ++ hex"0114 " ++ challengeResult).bits
|
||||
|
||||
"decode" in {
|
||||
val res = Codec.decode[ClientFinished](string)
|
||||
val value = res.require.value
|
||||
|
||||
value.challengeResult mustEqual challengeResult
|
||||
value.pubKey mustEqual pubKey
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val res = Codec.encode(ClientFinished(pubKey, challengeResult))
|
||||
|
||||
res.require mustEqual string
|
||||
}
|
||||
}
|
||||
|
||||
"ServerFinished" should {
|
||||
val challengeResult = hex"d64ffb8e 526311b4 af46bece"
|
||||
val string = (hex"0114" ++ challengeResult).bits
|
||||
|
||||
"decode" in {
|
||||
val res = Codec.decode[ServerFinished](string)
|
||||
val value = res.require.value
|
||||
|
||||
value.challengeResult mustEqual challengeResult
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val res = Codec.encode(ServerFinished(challengeResult))
|
||||
|
||||
res.require mustEqual string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
69
src/test/scala/PacketCodingTest.scala
Normal file
69
src/test/scala/PacketCodingTest.scala
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.control.{ClientStart, ServerStart}
|
||||
import scodec.bits._
|
||||
|
||||
class PacketCodingTest extends Specification {
|
||||
/*def roundTrip[Container <: PlanetSidePacketContainer, Packet <: PlanetSidePacket](cont : Container, pkt : Packet) = {
|
||||
|
||||
val filledContainer = cont match {
|
||||
case x : ControlPacket => x.copy(packet = pkt.asInstanceOf[PlanetSideControlPacket])
|
||||
}
|
||||
val pktEncoded = PacketCoding.MarshalPacket(ControlPacket(packetUnderTest.opcode, packetUnderTest)).require
|
||||
val pktDecoded = PacketCoding.UnMarshalPacket(pkt.toByteVector).require.asInstanceOf[ControlPacket]
|
||||
val recvPkt = decoded.packet.asInstanceOf[ServerStart]
|
||||
|
||||
}*/
|
||||
|
||||
"Packet coding" should {
|
||||
"correctly decode control packets" in {
|
||||
val packet = PacketCoding.UnmarshalPacket(hex"0001 00000002 00261e27 000001f0").require
|
||||
|
||||
packet.isInstanceOf[ControlPacket] mustEqual true
|
||||
|
||||
val controlPacket = packet.asInstanceOf[ControlPacket]
|
||||
controlPacket.opcode mustEqual ControlPacketOpcode.ClientStart
|
||||
controlPacket.packet mustEqual ClientStart(656287232)
|
||||
}
|
||||
|
||||
"encode and decode to identical packets" in {
|
||||
val clientNonce = 213129
|
||||
val serverNonce = 848483
|
||||
|
||||
val packetUnderTest = ServerStart(clientNonce, serverNonce)
|
||||
val pkt = PacketCoding.MarshalPacket(ControlPacket(packetUnderTest.opcode, packetUnderTest)).require
|
||||
|
||||
val decoded = PacketCoding.UnmarshalPacket(pkt.toByteVector).require.asInstanceOf[ControlPacket]
|
||||
val recvPkt = decoded.packet.asInstanceOf[ServerStart]
|
||||
|
||||
packetUnderTest mustEqual recvPkt
|
||||
}
|
||||
|
||||
"reject corrupted control packets" in {
|
||||
val packet = PacketCoding.UnmarshalPacket(hex"0001 00001002 00261e27 004101f0")
|
||||
|
||||
packet.isSuccessful mustEqual false
|
||||
}
|
||||
|
||||
"correctly decode crypto packets" in {
|
||||
val packet = PacketCoding.UnmarshalPacket(hex"0001 00000002 00261e27 000001f0").require
|
||||
|
||||
packet.isInstanceOf[ControlPacket] mustEqual true
|
||||
|
||||
val controlPacket = packet.asInstanceOf[ControlPacket]
|
||||
controlPacket.opcode mustEqual ControlPacketOpcode.ClientStart
|
||||
controlPacket.packet mustEqual ClientStart(656287232)
|
||||
}
|
||||
|
||||
"reject bad packet types" in {
|
||||
PacketCoding.UnmarshalPacket(hex"ff414141").isFailure mustEqual true
|
||||
}
|
||||
|
||||
"reject small packets" in {
|
||||
PacketCoding.UnmarshalPacket(hex"00").isFailure mustEqual true
|
||||
PacketCoding.UnmarshalPacket(hex"").isFailure mustEqual true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
244
src/test/scala/Vector3Test.scala
Normal file
244
src/test/scala/Vector3Test.scala
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.types.Vector3
|
||||
|
||||
class Vector3Test extends Specification {
|
||||
val vec = Vector3(1.3f, -2.6f, 3.9f)
|
||||
|
||||
"Vector3" should {
|
||||
"construct" in {
|
||||
vec.x mustEqual 1.3f
|
||||
vec.y mustEqual -2.6f
|
||||
vec.z mustEqual 3.9f
|
||||
}
|
||||
|
||||
"isolate x,y components" in {
|
||||
vec.xy mustEqual Vector3(1.3f, -2.6f, 0)
|
||||
}
|
||||
|
||||
"promote float values into a specific z-format" in {
|
||||
Vector3.z(3.9f) mustEqual Vector3(0, 0, 3.9f)
|
||||
}
|
||||
|
||||
"calculate magnitude (like a vector) 1" in {
|
||||
val obj = Vector3(2.0f, 0.0f, 0.0f)
|
||||
Vector3.Magnitude(obj) mustEqual 2.0f
|
||||
}
|
||||
|
||||
"calculate magnitude (like a vector) 2" in {
|
||||
val obj = Vector3(3.0f, 4.0f, 0.0f)
|
||||
Vector3.Magnitude(obj) mustEqual 5.0f
|
||||
}
|
||||
|
||||
"calculate magnitude (like a vector) 3" in {
|
||||
Vector3.Magnitude(vec) mustEqual 4.864155f
|
||||
}
|
||||
|
||||
"calculate square magnitude (like a vector)" in {
|
||||
Vector3.MagnitudeSquared(vec) mustEqual 23.66f
|
||||
}
|
||||
|
||||
"calculate distance 1" in {
|
||||
val obj1 = Vector3(0.0f, 0.0f, 0.0f)
|
||||
val obj2 = Vector3(2.0f, 0.0f, 0.0f)
|
||||
Vector3.Distance(obj1, obj2) mustEqual 2.0f
|
||||
}
|
||||
|
||||
"calculate distance 2" in {
|
||||
val obj1 = Vector3(0.0f, 0.0f, 0.0f)
|
||||
val obj2 = Vector3(2.0f, 0.0f, 0.0f)
|
||||
Vector3.Distance(obj1, obj2) mustEqual Vector3.Magnitude(obj2)
|
||||
}
|
||||
|
||||
"calculate distance 3" in {
|
||||
val obj1 = Vector3(3.0f, 4.0f, 5.0f)
|
||||
val obj2 = Vector3(3.0f, 4.0f, 5.0f)
|
||||
Vector3.Distance(obj1, obj2) mustEqual 0f
|
||||
}
|
||||
|
||||
"perform addition" in {
|
||||
val obj1 = Vector3(3.0f, 4.0f, 5.0f)
|
||||
val obj2 = Vector3(3.0f, 4.0f, 5.0f)
|
||||
obj1 + obj2 mustEqual Vector3(6f, 8f, 10f)
|
||||
}
|
||||
|
||||
"perform subtraction" in {
|
||||
val obj1 = Vector3(3.0f, 4.0f, 5.0f)
|
||||
val obj2 = Vector3(3.0f, 4.0f, 5.0f)
|
||||
obj1 - obj2 mustEqual Vector3(0f, 0f, 0f)
|
||||
}
|
||||
|
||||
"multiply by a scalar" in {
|
||||
vec * 3f mustEqual Vector3(3.8999999f, -7.7999997f, 11.700001f)
|
||||
}
|
||||
|
||||
"separate into x-component and y-component only" in {
|
||||
val obj = Vector3(1.1f, 2.2f, 3.3f)
|
||||
obj.xy mustEqual Vector3(1.1f, 2.2f, 0f)
|
||||
}
|
||||
|
||||
"calculate the unit vector (zero)" in {
|
||||
Vector3.Unit(Vector3.Zero) mustEqual Vector3(0, 0, 0)
|
||||
}
|
||||
|
||||
"calculate the unit vector (normal)" in {
|
||||
import Vector3._
|
||||
val one_root_two: Float = (1 / math.sqrt(2)).toFloat
|
||||
val one_root_three: Float = (1 / math.sqrt(3)).toFloat
|
||||
val ulp: Float = math.ulp(1) //measure of insignificance
|
||||
|
||||
Unit(Vector3(1, 0, 0)) mustEqual Vector3(1, 0, 0)
|
||||
1 - Magnitude(Vector3(1, 0, 0)) < ulp mustEqual true
|
||||
|
||||
Unit(Vector3(1, 1, 0)) mustEqual Vector3(one_root_two, one_root_two, 0)
|
||||
1 - Magnitude(Vector3(one_root_two, one_root_two, 0)) < ulp mustEqual true
|
||||
|
||||
Unit(Vector3(1, 1, 1)) mustEqual Vector3(one_root_three, one_root_three, one_root_three)
|
||||
1 - Magnitude(Vector3(one_root_three, one_root_three, one_root_three)) < ulp mustEqual true
|
||||
}
|
||||
|
||||
"calculate the dot product (magnitude-squared)" in {
|
||||
Vector3.DotProduct(vec, vec) mustEqual Vector3.MagnitudeSquared(vec)
|
||||
}
|
||||
|
||||
"calculate the dot product (two vectors)" in {
|
||||
Vector3.DotProduct(vec, Vector3(3.4f, -5.6f, 7.8f)) mustEqual 49.4f
|
||||
}
|
||||
|
||||
"calculate the dot product (zero vector)" in {
|
||||
Vector3.DotProduct(vec, Vector3.Zero) mustEqual 0f
|
||||
}
|
||||
|
||||
"calculate the cross product (identity)" in {
|
||||
val Vx: Vector3 = Vector3(1, 0, 0)
|
||||
val Vy: Vector3 = Vector3(0, 1, 0)
|
||||
val Vz: Vector3 = Vector3(0, 0, 1)
|
||||
|
||||
Vector3.CrossProduct(Vx, Vy) mustEqual Vz
|
||||
Vector3.CrossProduct(Vy, Vz) mustEqual Vx
|
||||
Vector3.CrossProduct(Vz, Vx) mustEqual Vy
|
||||
|
||||
Vector3.CrossProduct(Vy, Vx) mustEqual Vector3(0, 0, -1)
|
||||
Vector3.CrossProduct(Vz, Vy) mustEqual Vector3(-1, 0, 0)
|
||||
Vector3.CrossProduct(Vx, Vz) mustEqual Vector3(0, -1, 0)
|
||||
}
|
||||
|
||||
"calculate the cross product (full)" in {
|
||||
val A: Vector3 = Vector3(2, 1, -1)
|
||||
val B: Vector3 = Vector3(-3, 4, 1)
|
||||
|
||||
Vector3.CrossProduct(A, B) mustEqual Vector3(5, 1, 11)
|
||||
Vector3.CrossProduct(B, A) mustEqual Vector3(-5, -1, -11)
|
||||
}
|
||||
|
||||
"find a perpendicular vector with cross product" in {
|
||||
val A: Vector3 = Vector3(2, 1, -1)
|
||||
val B: Vector3 = Vector3(-3, 4, 1)
|
||||
val C: Vector3 = Vector3.CrossProduct(A, B)
|
||||
|
||||
Vector3.DotProduct(A, C) mustEqual 0
|
||||
Vector3.DotProduct(B, C) mustEqual 0
|
||||
}
|
||||
|
||||
"calculate the scalar projection (perpendicular vectors)" in {
|
||||
val Vx: Vector3 = Vector3(1, 0, 0)
|
||||
val Vy: Vector3 = Vector3(0, 1, 0)
|
||||
|
||||
Vector3.ScalarProjection(Vx, Vy) mustEqual 0
|
||||
}
|
||||
|
||||
"calculate the scalar projection (parallel vectors)" in {
|
||||
val A: Vector3 = Vector3(2, 0, 0)
|
||||
val B: Vector3 = Vector3(10, 0, 0)
|
||||
|
||||
Vector3.ScalarProjection(A, B) mustEqual 2
|
||||
Vector3.ScalarProjection(B, A) mustEqual 10
|
||||
}
|
||||
|
||||
"calculate the scalar projection (antiparallel vectors)" in {
|
||||
val A: Vector3 = Vector3(2, 0, 0)
|
||||
val B: Vector3 = Vector3(-10, 0, 0)
|
||||
|
||||
Vector3.ScalarProjection(A, B) mustEqual -2
|
||||
Vector3.ScalarProjection(B, A) mustEqual -10
|
||||
}
|
||||
|
||||
"calculate the scalar projection (normal)" in {
|
||||
val A: Vector3 = Vector3(2, 1, -1)
|
||||
val B: Vector3 = Vector3(3, 4, 1)
|
||||
|
||||
Vector3.ScalarProjection(A, B) mustEqual 1.7650452f
|
||||
Vector3.ScalarProjection(B, A) mustEqual 3.6742344f
|
||||
}
|
||||
|
||||
"calculate the vector projection (perpendicular vectors)" in {
|
||||
val Vx: Vector3 = Vector3(1, 0, 0)
|
||||
val Vy: Vector3 = Vector3(0, 1, 0)
|
||||
|
||||
Vector3.VectorProjection(Vx, Vy) mustEqual Vector3.Zero
|
||||
}
|
||||
|
||||
"calculate the vector projection (parallel vectors)" in {
|
||||
val A: Vector3 = Vector3(2, 0, 0)
|
||||
val B: Vector3 = Vector3(10, 0, 0)
|
||||
|
||||
Vector3.VectorProjection(A, B) mustEqual A
|
||||
Vector3.VectorProjection(B, A) mustEqual B
|
||||
}
|
||||
|
||||
"calculate the vector projection (antiparallel vectors)" in {
|
||||
val A: Vector3 = Vector3(2, 0, 0)
|
||||
val B: Vector3 = Vector3(-10, 0, 0)
|
||||
|
||||
Vector3.VectorProjection(A, B) mustEqual A
|
||||
Vector3.VectorProjection(B, A) mustEqual B
|
||||
}
|
||||
|
||||
"calculate the vector projection (normal)" in {
|
||||
val A: Vector3 = Vector3(2, 1, -1)
|
||||
val B: Vector3 = Vector3(3, 4, 1)
|
||||
|
||||
Vector3.VectorProjection(A, B) mustEqual Vector3(1.0384614f, 1.3846153f, 0.34615383f)
|
||||
Vector3.VectorProjection(B, A) mustEqual Vector3(2.9999998f, 1.4999999f, -1.4999999f)
|
||||
}
|
||||
|
||||
"rotate positive x-axis-vector 90-degrees around the z-axis" in {
|
||||
val A: Vector3 = Vector3(1, 0, 0)
|
||||
A.Rz(0) mustEqual A
|
||||
A.Rz(90) mustEqual Vector3(0, 1, 0)
|
||||
A.Rz(180) mustEqual Vector3(-1, 0, 0)
|
||||
A.Rz(270) mustEqual Vector3(0, -1, 0)
|
||||
A.Rz(360) mustEqual A
|
||||
}
|
||||
|
||||
"rotate positive y-axis-vector 90-degrees around the x-axis" in {
|
||||
val A: Vector3 = Vector3(0, 1, 0)
|
||||
A.Rx(0) mustEqual A
|
||||
A.Rx(90) mustEqual Vector3(0, 0, 1)
|
||||
A.Rx(180) mustEqual Vector3(0, -1, 0)
|
||||
A.Rx(270) mustEqual Vector3(0, 0, -1)
|
||||
A.Rx(360) mustEqual A
|
||||
}
|
||||
|
||||
"rotate positive x-axis-vector 90-degrees around the y-axis" in {
|
||||
val A: Vector3 = Vector3(1, 0, 0)
|
||||
A.Ry(0) mustEqual A
|
||||
A.Ry(90) mustEqual Vector3(0, 0, -1)
|
||||
A.Ry(180) mustEqual Vector3(-1, 0, 0)
|
||||
A.Ry(270) mustEqual Vector3(0, 0, 1)
|
||||
A.Ry(360) mustEqual A
|
||||
}
|
||||
|
||||
"compound rotation" in {
|
||||
val A: Vector3 = Vector3(1, 0, 0)
|
||||
A.Rz(90)
|
||||
.Rx(90)
|
||||
.Ry(90) mustEqual A
|
||||
}
|
||||
|
||||
"45-degree rotation" in {
|
||||
val A: Vector3 = Vector3(1, 0, 0)
|
||||
A.Rz(45) mustEqual Vector3(0.70710677f, 0.70710677f, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
81
src/test/scala/base/ActorTest.scala
Normal file
81
src/test/scala/base/ActorTest.scala
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package base
|
||||
|
||||
import akka.actor.{Actor, ActorRef, ActorSystem, Props}
|
||||
import akka.testkit.{ImplicitSender, TestKit}
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import org.scalatest.BeforeAndAfterAll
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpecLike
|
||||
import org.specs2.specification.Scope
|
||||
|
||||
import scala.collection.mutable
|
||||
import scala.concurrent.duration.FiniteDuration
|
||||
|
||||
abstract class ActorTest(sys: ActorSystem = ActorSystem("system", ConfigFactory.parseMap(ActorTest.LoggingConfig)))
|
||||
extends TestKit(sys)
|
||||
with Scope
|
||||
with ImplicitSender
|
||||
with AnyWordSpecLike
|
||||
with Matchers
|
||||
with BeforeAndAfterAll {
|
||||
override def afterAll(): Unit = {
|
||||
TestKit.shutdownActorSystem(system)
|
||||
}
|
||||
}
|
||||
|
||||
object ActorTest {
|
||||
import scala.jdk.CollectionConverters._
|
||||
private val LoggingConfig = Map(
|
||||
"akka.loggers" -> List("akka.testkit.TestEventListener").asJava,
|
||||
"akka.loglevel" -> "OFF",
|
||||
"akka.stdout-loglevel" -> "OFF",
|
||||
"akka.log-dead-letters" -> "OFF"
|
||||
).asJava
|
||||
|
||||
/**
|
||||
* A (potential) workaround to a Travis CI issue involving polling a series of messages over a period of time.
|
||||
* Running the test in isolation works every time.
|
||||
* Running the test as part of a series produces mixed results.
|
||||
* Travis CI fails the test every time by not getting any messages.
|
||||
* @see TestKit.receiveN
|
||||
* @param n the number of messages to poll
|
||||
* @param timeout how long to wait for each message
|
||||
* @param sys what to poll
|
||||
* @return a list of messages
|
||||
*/
|
||||
def receiveMultiple(n: Int, timeout: FiniteDuration, sys: TestKit): List[Any] = {
|
||||
assert(0 < n, s"number of expected messages must be positive non-zero integer - $n")
|
||||
val out = {
|
||||
val msgs = mutable.ListBuffer[Any]()
|
||||
(0 until n).foreach(_ => {
|
||||
msgs += sys.receiveOne(timeout)
|
||||
})
|
||||
msgs.toList
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
/**
|
||||
* A middleman Actor that accepts a `Props` object to instantiate and accepts messages back from it.
|
||||
* The purpose is to bypass a message receive issue with the `ActorTest` / `TestKit` class
|
||||
* that does not properly queue messages dispatched to it
|
||||
* when messages may be sent to it via a `context.parent` call.
|
||||
* Please do not wrap and parameterize Props objects like this during normal Ops.
|
||||
* @param actorProps the uninitialized `Actor` that uses `context.parent` to direct communication
|
||||
* @param sendTo where to send mesages that have originated from an `actorProps` object;
|
||||
* typically should point back to the test environment constructed by `TestKit`
|
||||
*/
|
||||
class SupportActorInterface(actorProps: Props, sendTo: ActorRef) extends Actor {
|
||||
val test = context.actorOf(actorProps, "support-actor")
|
||||
|
||||
def receive: Receive = {
|
||||
case msg =>
|
||||
(if (sender() == test) {
|
||||
sendTo
|
||||
} else {
|
||||
test
|
||||
}) ! msg
|
||||
}
|
||||
}
|
||||
}
|
||||
54
src/test/scala/base/FreedContextActorTest.scala
Normal file
54
src/test/scala/base/FreedContextActorTest.scala
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright (c) 2020 PSForever
|
||||
package base
|
||||
|
||||
import akka.actor.{Actor, ActorContext, ActorRef, Props}
|
||||
import akka.pattern.ask
|
||||
import akka.util.Timeout
|
||||
|
||||
import scala.concurrent.duration._
|
||||
import scala.concurrent.Await
|
||||
|
||||
/**
|
||||
* Create an `ActorTest` environment that has an `ActorContext` object.
|
||||
*/
|
||||
abstract class FreedContextActorTest extends ActorTest {
|
||||
/*
|
||||
Never do this in actual production code!
|
||||
ActorSystem and ActorContext offer similar mechanisms for instantiating actors.
|
||||
This is a consequence of their shared inheritance of the ActorRefFactory trait.
|
||||
They are not equivalent enough to be able to pass one as the other as a parameter.
|
||||
Because the ActorSystem has no context of its own,
|
||||
various bizarre mechanisms have to be developed to use any methods that would pass in a context object.
|
||||
We create a middleman Actor whose main purpose is to surrender its context object to the test environment directly
|
||||
and then direct all messages sent to that object to the test environment.
|
||||
*/
|
||||
private val _testContextHandler = system.actorOf(Props(classOf[ContextSensitive]), "actor-test-cs")
|
||||
private implicit val timeout = Timeout(5 seconds)
|
||||
private val _testContextHandlerResult = ask(_testContextHandler, message = "", self)
|
||||
implicit val context = Await.result(_testContextHandlerResult, timeout.duration).asInstanceOf[ActorContext]
|
||||
}
|
||||
|
||||
/**
|
||||
* Surrender your `context` object for a greater good!
|
||||
*/
|
||||
private class ContextSensitive extends Actor {
|
||||
var output: ActorRef = ActorRef.noSender
|
||||
|
||||
def receive: Receive = {
|
||||
case _ =>
|
||||
context.become(PassThroughBehavior)
|
||||
output = sender()
|
||||
sender() ! context
|
||||
}
|
||||
|
||||
/**
|
||||
* Once the `context` object has been leased,
|
||||
* this `Actor` becomes transparent.
|
||||
* Calling `context.parent` from whatever `Actor` was spurned by the previously provided `context`,
|
||||
* will now refer to whatever was the contact to gain access to it - the test environment.
|
||||
* @return something to `become`
|
||||
*/
|
||||
def PassThroughBehavior: Receive = {
|
||||
case msg => output forward msg
|
||||
}
|
||||
}
|
||||
27
src/test/scala/control/ClientStartTest.scala
Normal file
27
src/test/scala/control/ClientStartTest.scala
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package control
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.control._
|
||||
import scodec.bits._
|
||||
|
||||
class ClientStartTest extends Specification {
|
||||
val string = hex"0001 00000002 00261e27 000001f0"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case ClientStart(nonce) =>
|
||||
nonce mustEqual 656287232
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = ClientStart(656287232)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
26
src/test/scala/control/ConnectionCloseTest.scala
Normal file
26
src/test/scala/control/ConnectionCloseTest.scala
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package control
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.control._
|
||||
import scodec.bits._
|
||||
|
||||
class ConnectionCloseTest extends Specification {
|
||||
val string = hex"001D"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case ConnectionClose() =>
|
||||
ok
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = ConnectionClose()
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
32
src/test/scala/control/ControlSyncRespTest.scala
Normal file
32
src/test/scala/control/ControlSyncRespTest.scala
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package control
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.control._
|
||||
import scodec.bits._
|
||||
|
||||
class ControlSyncRespTest extends Specification {
|
||||
val string = hex"0008 5268 21392D92 0000000000000276 0000000000000275 0000000000000275 0000000000000276"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case ControlSyncResp(a, b, c, d, e, f) =>
|
||||
a mustEqual 21096
|
||||
|
||||
b mustEqual 0x21392d92
|
||||
c mustEqual 0x276
|
||||
d mustEqual 0x275
|
||||
e mustEqual 0x275
|
||||
f mustEqual 0x276
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val encoded = PacketCoding.EncodePacket(ControlSyncResp(21096, 0x21392d92, 0x276, 0x275, 0x275, 0x276)).require
|
||||
|
||||
encoded.toByteVector mustEqual string
|
||||
}
|
||||
}
|
||||
32
src/test/scala/control/ControlSyncTest.scala
Normal file
32
src/test/scala/control/ControlSyncTest.scala
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package control
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.control._
|
||||
import scodec.bits._
|
||||
|
||||
class ControlSyncTest extends Specification {
|
||||
val string = hex"0007 5268 0000004D 00000052 0000004D 0000007C 0000004D 0000000000000276 0000000000000275"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case ControlSync(a, b, c, d, e, f, g, h) =>
|
||||
a mustEqual 21096
|
||||
b mustEqual 0x4d
|
||||
c mustEqual 0x52
|
||||
d mustEqual 0x4d
|
||||
e mustEqual 0x7c
|
||||
f mustEqual 0x4d
|
||||
g mustEqual 0x276
|
||||
h mustEqual 0x275
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val encoded = PacketCoding.EncodePacket(ControlSync(21096, 0x4d, 0x52, 0x4d, 0x7c, 0x4d, 0x276, 0x275)).require
|
||||
encoded.toByteVector mustEqual string
|
||||
}
|
||||
}
|
||||
31
src/test/scala/control/HandleGamePacketTest.scala
Normal file
31
src/test/scala/control/HandleGamePacketTest.scala
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package control
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.control._
|
||||
import scodec.bits._
|
||||
|
||||
class HandleGamePacketTest extends Specification {
|
||||
//this is the first from a series of SlottedMetaPacket4s; the length field was modified from 12 DC to pass the test
|
||||
val base =
|
||||
hex"18 D5 96 00 00 BC 8E 00 03 A2 16 5D A4 5F B0 80 00 04 30 40 00 08 30 46 00 4A 00 48 00 02 02 F0 62 1E 80 80 00 00 00 00 00 3F FF CC 0D 40 00 20 00 03 00 27 C3 01 C8 00 00 03 08 00 00 03 FF FF FF FC A4 04 00 00 62 00 18 02 00 50 00 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 C8 00 00 00 5D B0 81 40 00 00 00 00 00 00 00 00 00 00 00 00 02 C0 00 40 83 85 46 86 C7 07 8A 4A 80 70 0C 00 01 98 00 00 01 24 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 31 30 90 78 70 65 5F 6A 6F 69 6E 5F 70 6C 61 74 6F 6F 6E 92 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 31 34 8F 78 70 65 5F 6A 6F 69 6E 5F 6F 75 74 66 69 74 92 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 31 31 91 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 39 91 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 38 92 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 31 33 93 78 70 65 5F 77 61 72 70 5F 67 61 74 65 5F 75 73 61 67 65 91 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 32 92 78 70 65 5F 69 6E 73 74 61 6E 74 5F 61 63 74 69 6F 6E 8E 78 70 65 5F 66 6F 72 6D 5F 73 71 75 61 64 91 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 36 91 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 37 8E 78 70 65 5F 6A 6F 69 6E 5F 73 71 75 61 64 8C 78 70 65 5F 62 69 6E 64 5F 61 6D 73 91 78 70 65 5F 62 61 74 74 6C 65 5F 72 61 6E 6B 5F 35 91 78 70 65 5F 62 69 6E 64 5F 66 61 63 69 6C 69 74"
|
||||
val string = hex"00 00 01 CB" ++ base
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case HandleGamePacket(len, data, extra) =>
|
||||
len mustEqual 459
|
||||
data mustEqual base
|
||||
extra mustEqual BitVector.empty
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val pkt = HandleGamePacket(base)
|
||||
val msg = PacketCoding.EncodePacket(pkt).require.toByteVector
|
||||
msg mustEqual string
|
||||
}
|
||||
}
|
||||
199
src/test/scala/control/MultiPacketCollectorTest.scala
Normal file
199
src/test/scala/control/MultiPacketCollectorTest.scala
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package control
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet.control.{ControlSync, MultiPacketBundle, MultiPacketCollector}
|
||||
import net.psforever.packet.crypto.{ClientFinished, ServerFinished}
|
||||
import net.psforever.packet.game.ObjectDeleteMessage
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
|
||||
class MultiPacketCollectorTest extends Specification {
|
||||
val packet1 = ObjectDeleteMessage(PlanetSideGUID(1103), 2)
|
||||
|
||||
"MultiPacketBundle" should {
|
||||
import scodec.bits._
|
||||
val packet2 = ControlSync(21096, 0x4d, 0x52, 0x4d, 0x7c, 0x4d, 0x276, 0x275)
|
||||
|
||||
"construct" in {
|
||||
MultiPacketBundle(List(packet1))
|
||||
ok
|
||||
}
|
||||
|
||||
"fail to construct if not initialized with PlanetSidePackets" in {
|
||||
MultiPacketBundle(Nil) must throwA[IllegalArgumentException]
|
||||
}
|
||||
|
||||
"concatenate bundles into a new bundle" in {
|
||||
val obj1 = MultiPacketBundle(List(packet1))
|
||||
val obj2 = MultiPacketBundle(List(packet2))
|
||||
val obj3 = obj1 + obj2
|
||||
obj3 match {
|
||||
case MultiPacketBundle(list) =>
|
||||
list.size mustEqual 2
|
||||
list.head mustEqual packet1
|
||||
list(1) mustEqual packet2
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"accept PlanetSideGamePackets and PlanetSideControlPackets" in {
|
||||
MultiPacketBundle(List(packet2, packet1)) match {
|
||||
case MultiPacketBundle(list) =>
|
||||
list.size mustEqual 2
|
||||
list.head mustEqual packet2
|
||||
list(1) mustEqual packet1
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"ignore other types of PlanetSideContainerPackets" in {
|
||||
val param = List(packet2, ClientFinished(hex"", hex""), packet1, ServerFinished(hex""))
|
||||
MultiPacketBundle(param) match { //warning message will display in log
|
||||
case MultiPacketBundle(list) =>
|
||||
list.size mustEqual 2
|
||||
list.head mustEqual param.head
|
||||
list(1) mustEqual param(2)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"MultiPacketCollector" should {
|
||||
val packet2 = ObjectDeleteMessage(PlanetSideGUID(1105), 2)
|
||||
val packet3 = ObjectDeleteMessage(PlanetSideGUID(1107), 2)
|
||||
|
||||
"construct" in {
|
||||
new MultiPacketCollector()
|
||||
ok
|
||||
}
|
||||
|
||||
"construct with initial packets" in {
|
||||
MultiPacketCollector(List(packet1, packet2))
|
||||
ok
|
||||
}
|
||||
|
||||
"can retrieve a bundle packets" in {
|
||||
val obj = MultiPacketCollector(List(packet1, packet2))
|
||||
obj.Bundle match {
|
||||
case Some(MultiPacketBundle(list)) =>
|
||||
list.size mustEqual 2
|
||||
list.head mustEqual packet1
|
||||
list(1) mustEqual packet2
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"can retrieve a bundle of potential packets" in {
|
||||
val obj1 = new MultiPacketCollector()
|
||||
obj1.Bundle match {
|
||||
case Some(_) =>
|
||||
ko
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
val obj2 = MultiPacketCollector(List(packet1, packet2))
|
||||
obj2.Bundle match {
|
||||
case None =>
|
||||
ko
|
||||
case Some(MultiPacketBundle(list)) =>
|
||||
list.size mustEqual 2
|
||||
list.head mustEqual packet1
|
||||
list(1) mustEqual packet2
|
||||
}
|
||||
}
|
||||
|
||||
"clear packets after being asked to bundle" in {
|
||||
val list = List(packet1, packet2)
|
||||
val obj = MultiPacketCollector(list)
|
||||
|
||||
obj.Bundle match {
|
||||
case Some(MultiPacketBundle(bundle)) =>
|
||||
bundle mustEqual list
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
|
||||
obj.Bundle match {
|
||||
case Some(MultiPacketBundle(_)) =>
|
||||
ko
|
||||
case _ =>
|
||||
ok
|
||||
}
|
||||
}
|
||||
|
||||
"add a packet" in {
|
||||
val obj = new MultiPacketCollector()
|
||||
obj.Add(packet1)
|
||||
obj.Bundle match {
|
||||
case Some(MultiPacketBundle(list)) =>
|
||||
list.size mustEqual 1
|
||||
list.head mustEqual packet1
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"add packets" in {
|
||||
val obj = new MultiPacketCollector()
|
||||
obj.Add(List(packet1, packet2))
|
||||
obj.Bundle match {
|
||||
case Some(MultiPacketBundle(list)) =>
|
||||
list.size mustEqual 2
|
||||
list.head mustEqual packet1
|
||||
list(1) mustEqual packet2
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"concatenate bundles (1)" in {
|
||||
|
||||
val obj1 = new MultiPacketCollector()
|
||||
obj1.Add(List(packet1, packet2))
|
||||
obj1.Bundle match {
|
||||
case Some(MultiPacketBundle(bundle1)) =>
|
||||
val obj2 = MultiPacketCollector(bundle1)
|
||||
obj2.Add(packet3)
|
||||
obj2.Bundle match {
|
||||
case Some(MultiPacketBundle(list)) =>
|
||||
list.size mustEqual 3
|
||||
list.head mustEqual packet1
|
||||
list(1) mustEqual packet2
|
||||
list(2) mustEqual packet3
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
"concatenate bundles (2)" in {
|
||||
val obj1 = new MultiPacketCollector()
|
||||
obj1.Add(List(packet1, packet2))
|
||||
obj1.Bundle match {
|
||||
case Some(MultiPacketBundle(bundle1)) =>
|
||||
val obj2 = new MultiPacketCollector()
|
||||
obj2.Add(packet3)
|
||||
obj2.Add(bundle1)
|
||||
obj2.Bundle match {
|
||||
case Some(MultiPacketBundle(list)) =>
|
||||
list.size mustEqual 3
|
||||
list.head mustEqual packet3
|
||||
list(1) mustEqual packet1
|
||||
list(2) mustEqual packet2
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
47
src/test/scala/control/MultiPacketExTest.scala
Normal file
47
src/test/scala/control/MultiPacketExTest.scala
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package control
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet.control._
|
||||
import org.specs2.specification.core.Fragment
|
||||
import scodec.bits._
|
||||
|
||||
class MultiPacketExTest extends Specification {
|
||||
val strings = Vector(
|
||||
hex"00",
|
||||
hex"01 41",
|
||||
hex"01 41" ++ hex"02 4142",
|
||||
hex"fe" ++ ByteVector.fill(0xfe)(0x41),
|
||||
hex"ffff00" ++ ByteVector.fill(0xff)(0x41),
|
||||
hex"ff0001" ++ ByteVector.fill(0x100)(0x41),
|
||||
hex"ff ffff ffff 0000" ++ ByteVector.fill(0x0000ffff)(0x41),
|
||||
hex"ff ffff 0000 0100" ++ ByteVector.fill(0x00010000)(0x41)
|
||||
)
|
||||
|
||||
val packets = Vector(
|
||||
MultiPacketEx(Vector(ByteVector.empty)),
|
||||
MultiPacketEx(Vector(hex"41")),
|
||||
MultiPacketEx(Vector(hex"41", hex"4142")),
|
||||
MultiPacketEx(Vector(ByteVector.fill(0xfe)(0x41))),
|
||||
MultiPacketEx(Vector(ByteVector.fill(0xff)(0x41))),
|
||||
MultiPacketEx(Vector(ByteVector.fill(0x100)(0x41))),
|
||||
MultiPacketEx(Vector(ByteVector.fill(0x0000ffff)(0x41))),
|
||||
MultiPacketEx(Vector(ByteVector.fill(0x00010000)(0x41)))
|
||||
)
|
||||
|
||||
"decode" in {
|
||||
Fragment.foreach(strings.indices) { i =>
|
||||
"test " + i ! { MultiPacketEx.decode(strings { i }.bits).require.value mustEqual packets { i } }
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
Fragment.foreach(packets.indices) { i =>
|
||||
"test " + i ! { MultiPacketEx.encode(packets { i }).require.toByteVector mustEqual strings { i } }
|
||||
}
|
||||
}
|
||||
|
||||
"sizeCodec description" in {
|
||||
MultiPacketEx.sizeCodec.toString mustEqual "variable-bit unsigned integer"
|
||||
}
|
||||
}
|
||||
41
src/test/scala/control/MultiPacketTest.scala
Normal file
41
src/test/scala/control/MultiPacketTest.scala
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// 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
|
||||
}
|
||||
}
|
||||
82
src/test/scala/control/RelatedATest.scala
Normal file
82
src/test/scala/control/RelatedATest.scala
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package control
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.control.RelatedA
|
||||
import scodec.bits._
|
||||
|
||||
class RelatedATest extends Specification {
|
||||
val string0 = hex"00 11 01 04"
|
||||
val string1 = hex"00 12 01 04"
|
||||
val string2 = hex"00 13 01 04"
|
||||
val string3 = hex"00 14 01 04"
|
||||
|
||||
"decode (0)" in {
|
||||
PacketCoding.DecodePacket(string0).require match {
|
||||
case RelatedA(slot, subslot) =>
|
||||
slot mustEqual 0
|
||||
subslot mustEqual 260
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (1)" in {
|
||||
PacketCoding.DecodePacket(string1).require match {
|
||||
case RelatedA(slot, subslot) =>
|
||||
slot mustEqual 1
|
||||
subslot mustEqual 260
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (2)" in {
|
||||
PacketCoding.DecodePacket(string2).require match {
|
||||
case RelatedA(slot, subslot) =>
|
||||
slot mustEqual 2
|
||||
subslot mustEqual 260
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (3)" in {
|
||||
PacketCoding.DecodePacket(string3).require match {
|
||||
case RelatedA(slot, subslot) =>
|
||||
slot mustEqual 3
|
||||
subslot mustEqual 260
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (0)" in {
|
||||
val pkt = RelatedA(0, 260)
|
||||
val msg = PacketCoding.EncodePacket(pkt).require.toByteVector
|
||||
msg mustEqual string0
|
||||
}
|
||||
|
||||
"encode (1)" in {
|
||||
val pkt = RelatedA(1, 260)
|
||||
val msg = PacketCoding.EncodePacket(pkt).require.toByteVector
|
||||
msg mustEqual string1
|
||||
}
|
||||
|
||||
"encode (2)" in {
|
||||
val pkt = RelatedA(2, 260)
|
||||
val msg = PacketCoding.EncodePacket(pkt).require.toByteVector
|
||||
msg mustEqual string2
|
||||
}
|
||||
|
||||
"encode (3)" in {
|
||||
val pkt = RelatedA(3, 260)
|
||||
val msg = PacketCoding.EncodePacket(pkt).require.toByteVector
|
||||
msg mustEqual string3
|
||||
}
|
||||
|
||||
"encode (n)" in {
|
||||
RelatedA(4, 260) must throwA[IllegalArgumentException]
|
||||
}
|
||||
}
|
||||
82
src/test/scala/control/RelatedBTest.scala
Normal file
82
src/test/scala/control/RelatedBTest.scala
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package control
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.control.RelatedB
|
||||
import scodec.bits._
|
||||
|
||||
class RelatedBTest extends Specification {
|
||||
val string0 = hex"00 15 01 04"
|
||||
val string1 = hex"00 16 01 04"
|
||||
val string2 = hex"00 17 01 04"
|
||||
val string3 = hex"00 18 01 04"
|
||||
|
||||
"decode (0)" in {
|
||||
PacketCoding.DecodePacket(string0).require match {
|
||||
case RelatedB(slot, subslot) =>
|
||||
slot mustEqual 0
|
||||
subslot mustEqual 260
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (1)" in {
|
||||
PacketCoding.DecodePacket(string1).require match {
|
||||
case RelatedB(slot, subslot) =>
|
||||
slot mustEqual 1
|
||||
subslot mustEqual 260
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (2)" in {
|
||||
PacketCoding.DecodePacket(string2).require match {
|
||||
case RelatedB(slot, subslot) =>
|
||||
slot mustEqual 2
|
||||
subslot mustEqual 260
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (3)" in {
|
||||
PacketCoding.DecodePacket(string3).require match {
|
||||
case RelatedB(slot, subslot) =>
|
||||
slot mustEqual 3
|
||||
subslot mustEqual 260
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (0)" in {
|
||||
val pkt = RelatedB(0, 260)
|
||||
val msg = PacketCoding.EncodePacket(pkt).require.toByteVector
|
||||
msg mustEqual string0
|
||||
}
|
||||
|
||||
"encode (1)" in {
|
||||
val pkt = RelatedB(1, 260)
|
||||
val msg = PacketCoding.EncodePacket(pkt).require.toByteVector
|
||||
msg mustEqual string1
|
||||
}
|
||||
|
||||
"encode (2)" in {
|
||||
val pkt = RelatedB(2, 260)
|
||||
val msg = PacketCoding.EncodePacket(pkt).require.toByteVector
|
||||
msg mustEqual string2
|
||||
}
|
||||
|
||||
"encode (3)" in {
|
||||
val pkt = RelatedB(3, 260)
|
||||
val msg = PacketCoding.EncodePacket(pkt).require.toByteVector
|
||||
msg mustEqual string3
|
||||
}
|
||||
|
||||
"encode (n)" in {
|
||||
RelatedB(4, 260) must throwA[IllegalArgumentException]
|
||||
}
|
||||
}
|
||||
79
src/test/scala/control/SlottedMetaPacketTest.scala
Normal file
79
src/test/scala/control/SlottedMetaPacketTest.scala
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package control
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.control._
|
||||
import org.specs2.specification.core.Fragment
|
||||
import scodec.bits._
|
||||
import scodec.codecs.uint16
|
||||
|
||||
class SlottedMetaPacketTest extends Specification {
|
||||
val string = hex"00 09 00 00 00194302484C36563130433F" ++
|
||||
hex"4C6835316369774A0000000018FABE0C" ++
|
||||
hex"00000000000000000000000001000000" ++
|
||||
hex"020000006B7BD8288C6469666671756F" ++
|
||||
hex"7469656E740000000000440597570065" ++
|
||||
hex"006C0063006F006D006500200074006F" ++
|
||||
hex"00200050006C0061006E006500740053" ++
|
||||
hex"0069006400650021002000018667656D" ++
|
||||
hex"696E690100040001459E2540377540"
|
||||
|
||||
def createMetaPacket(slot: Int, subslot: Int, rest: ByteVector) =
|
||||
hex"00" ++
|
||||
ControlPacketOpcode.codec
|
||||
.encode(
|
||||
ControlPacketOpcode(ControlPacketOpcode.SlottedMetaPacket0.id + slot)
|
||||
)
|
||||
.require
|
||||
.toByteVector ++ uint16.encode(subslot).require.toByteVector ++ rest
|
||||
|
||||
"decode as the base slot and subslot" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case SlottedMetaPacket(slot, subslot, rest) =>
|
||||
slot mustEqual 0
|
||||
subslot mustEqual 0
|
||||
rest mustEqual string.drop(4)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode as an arbitrary slot and subslot" in {
|
||||
val maxSlots = ControlPacketOpcode.SlottedMetaPacket7.id - ControlPacketOpcode.SlottedMetaPacket0.id
|
||||
|
||||
// create all possible SlottedMetaPackets
|
||||
Fragment.foreach(0 to maxSlots) { i =>
|
||||
"slot " + i ! {
|
||||
val subslot = 12323
|
||||
val pkt = createMetaPacket(i, subslot, ByteVector.empty)
|
||||
|
||||
PacketCoding.DecodePacket(pkt).require match {
|
||||
case SlottedMetaPacket(slot, subslotDecoded, rest) =>
|
||||
// XXX: there isn't a simple solution to Slot0 and Slot4 be aliases of each other structurally
|
||||
// This is probably best left to higher layers
|
||||
//slot mustEqual i % 4 // this is seen at 0x00A3FBFA
|
||||
slot mustEqual i
|
||||
subslotDecoded mustEqual subslot
|
||||
rest mustEqual ByteVector.empty // empty in this case
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val encoded = PacketCoding.EncodePacket(SlottedMetaPacket(0, 0x1000, ByteVector.empty)).require
|
||||
val encoded2 = PacketCoding.EncodePacket(SlottedMetaPacket(3, 0xffff, hex"414243")).require
|
||||
val encoded3 = PacketCoding.EncodePacket(SlottedMetaPacket(7, 0, hex"00")).require
|
||||
|
||||
encoded.toByteVector mustEqual createMetaPacket(0, 0x1000, ByteVector.empty)
|
||||
encoded2.toByteVector mustEqual createMetaPacket(3, 0xffff, hex"414243")
|
||||
encoded3.toByteVector mustEqual createMetaPacket(7, 0, hex"00")
|
||||
|
||||
PacketCoding.EncodePacket(SlottedMetaPacket(8, 0, hex"00")).require must throwA[AssertionError]
|
||||
PacketCoding.EncodePacket(SlottedMetaPacket(-1, 0, hex"00")).require must throwA[AssertionError]
|
||||
PacketCoding.EncodePacket(SlottedMetaPacket(0, 0x10000, hex"00")).require must throwA[IllegalArgumentException]
|
||||
}
|
||||
}
|
||||
26
src/test/scala/control/TeardownConnectionTest.scala
Normal file
26
src/test/scala/control/TeardownConnectionTest.scala
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package control
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.control._
|
||||
import scodec.bits._
|
||||
|
||||
class TeardownConnectionTest extends Specification {
|
||||
val string = hex"00 05 02 4F 57 17 00 06"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case TeardownConnection(nonce) =>
|
||||
nonce mustEqual 391597826
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val encoded = PacketCoding.EncodePacket(TeardownConnection(391597826)).require
|
||||
|
||||
encoded.toByteVector mustEqual string
|
||||
}
|
||||
}
|
||||
30
src/test/scala/game/ActionCancelMessageTest.scala
Normal file
30
src/test/scala/game/ActionCancelMessageTest.scala
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class ActionCancelMessageTest extends Specification {
|
||||
val string = hex"22 201ee01a10"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case ActionCancelMessage(player_guid, object_guid, unk) =>
|
||||
player_guid mustEqual PlanetSideGUID(7712)
|
||||
object_guid mustEqual PlanetSideGUID(6880)
|
||||
unk mustEqual 1
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = ActionCancelMessage(PlanetSideGUID(7712), PlanetSideGUID(6880), 1)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
28
src/test/scala/game/ActionProgressMessageTest.scala
Normal file
28
src/test/scala/game/ActionProgressMessageTest.scala
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class ActionProgressMessageTest extends Specification {
|
||||
val string = hex"216000000000"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case ActionProgressMessage(unk1, unk2) =>
|
||||
unk1 mustEqual 6
|
||||
unk2 mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = ActionProgressMessage(6, 0L)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
60
src/test/scala/game/ActionResultMessageTest.scala
Normal file
60
src/test/scala/game/ActionResultMessageTest.scala
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class ActionResultMessageTest extends Specification {
|
||||
val string_pass = hex"1f 80"
|
||||
val string_fail = hex"1f 0080000000"
|
||||
|
||||
"decode (pass)" in {
|
||||
PacketCoding.DecodePacket(string_pass).require match {
|
||||
case ActionResultMessage(okay, code) =>
|
||||
okay mustEqual true
|
||||
code mustEqual None
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (fail)" in {
|
||||
PacketCoding.DecodePacket(string_fail).require match {
|
||||
case ActionResultMessage(okay, code) =>
|
||||
okay mustEqual false
|
||||
code mustEqual Some(1)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (pass, full)" in {
|
||||
val msg = ActionResultMessage(true, None)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_pass
|
||||
}
|
||||
|
||||
"encode (pass, minimal)" in {
|
||||
val msg = ActionResultMessage.Pass
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_pass
|
||||
}
|
||||
|
||||
"encode (fail, full)" in {
|
||||
val msg = ActionResultMessage(false, Some(1))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_fail
|
||||
}
|
||||
|
||||
"encode (fail, minimal)" in {
|
||||
val msg = ActionResultMessage.Fail(1)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_fail
|
||||
}
|
||||
}
|
||||
30
src/test/scala/game/ArmorChangedMessageTest.scala
Normal file
30
src/test/scala/game/ArmorChangedMessageTest.scala
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{ExoSuitType, PlanetSideGUID}
|
||||
import scodec.bits._
|
||||
|
||||
class ArmorChangedMessageTest extends Specification {
|
||||
val string = hex"3E 11 01 4C"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case ArmorChangedMessage(player_guid, armor, subtype) =>
|
||||
player_guid mustEqual PlanetSideGUID(273)
|
||||
armor mustEqual ExoSuitType.MAX
|
||||
subtype mustEqual 3
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = ArmorChangedMessage(PlanetSideGUID(273), ExoSuitType.MAX, 3)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
45
src/test/scala/game/AvatarDeadStateMessageTest.scala
Normal file
45
src/test/scala/game/AvatarDeadStateMessageTest.scala
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||
import scodec.bits._
|
||||
|
||||
class AvatarDeadStateMessageTest extends Specification {
|
||||
val string = hex"ad3c1260801c12608009f99861fb0741e040000010"
|
||||
val string_invalid = hex"ad3c1260801c12608009f99861fb0741e0400000F0"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case AvatarDeadStateMessage(unk1, unk2, unk3, pos, unk4, unk5) =>
|
||||
unk1 mustEqual DeadState.Dead
|
||||
unk2 mustEqual 300000
|
||||
unk3 mustEqual 300000
|
||||
pos mustEqual Vector3(6552.617f, 4602.375f, 60.90625f)
|
||||
unk4 mustEqual PlanetSideEmpire.VS
|
||||
unk5 mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (failure)" in {
|
||||
PacketCoding.DecodePacket(string_invalid).isFailure mustEqual true
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = AvatarDeadStateMessage(
|
||||
DeadState.Dead,
|
||||
300000,
|
||||
300000,
|
||||
Vector3(6552.617f, 4602.375f, 60.90625f),
|
||||
PlanetSideEmpire.VS,
|
||||
true
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
31
src/test/scala/game/AvatarFirstTimeEventMessageTest.scala
Normal file
31
src/test/scala/game/AvatarFirstTimeEventMessageTest.scala
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class AvatarFirstTimeEventMessageTest extends Specification {
|
||||
val string = hex"69 4b00 c000 01000000 9e 766973697465645f63657274696669636174696f6e5f7465726d696e616c"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case AvatarFirstTimeEventMessage(avatar_guid, object_guid, unk1, event_name) =>
|
||||
avatar_guid mustEqual PlanetSideGUID(75)
|
||||
object_guid mustEqual PlanetSideGUID(192)
|
||||
unk1 mustEqual 1
|
||||
event_name mustEqual "visited_certification_terminal"
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = AvatarFirstTimeEventMessage(PlanetSideGUID(75), PlanetSideGUID(192), 1, "visited_certification_terminal")
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
29
src/test/scala/game/AvatarGrenadeStateMessageTest.scala
Normal file
29
src/test/scala/game/AvatarGrenadeStateMessageTest.scala
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{GrenadeState, PlanetSideGUID}
|
||||
import scodec.bits._
|
||||
|
||||
class AvatarGrenadeStateMessageTest extends Specification {
|
||||
val string = hex"A9 DA11 01"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case AvatarGrenadeStateMessage(player_guid, state) =>
|
||||
player_guid mustEqual PlanetSideGUID(4570)
|
||||
state mustEqual GrenadeState.Primed
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = AvatarGrenadeStateMessage(PlanetSideGUID(4570), GrenadeState.Primed)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
31
src/test/scala/game/AvatarImplantMessageTest.scala
Normal file
31
src/test/scala/game/AvatarImplantMessageTest.scala
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class AvatarImplantMessageTest extends Specification {
|
||||
val string = hex"58 630C 68 80"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case AvatarImplantMessage(player_guid, unk1, unk2, implant) =>
|
||||
player_guid mustEqual PlanetSideGUID(3171)
|
||||
unk1 mustEqual ImplantAction.Activation
|
||||
unk2 mustEqual 1
|
||||
implant mustEqual 1
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = AvatarImplantMessage(PlanetSideGUID(3171), ImplantAction.Activation, 1, 1)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
27
src/test/scala/game/AvatarJumpMessageTest.scala
Normal file
27
src/test/scala/game/AvatarJumpMessageTest.scala
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class AvatarJumpMessageTest extends Specification {
|
||||
val string = hex"35 80"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case AvatarJumpMessage(state) =>
|
||||
state mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = AvatarJumpMessage(true)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
50
src/test/scala/game/AvatarSearchCriteriaMessageTest.scala
Normal file
50
src/test/scala/game/AvatarSearchCriteriaMessageTest.scala
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class AvatarSearchCriteriaMessageTest extends Specification {
|
||||
val string = hex"64 C604 00 00 00 00 00 00"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case AvatarSearchCriteriaMessage(unk1, unk2) =>
|
||||
unk1 mustEqual PlanetSideGUID(1222)
|
||||
unk2.length mustEqual 6
|
||||
unk2.head mustEqual 0
|
||||
unk2(1) mustEqual 0
|
||||
unk2(2) mustEqual 0
|
||||
unk2(3) mustEqual 0
|
||||
unk2(4) mustEqual 0
|
||||
unk2(5) mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = AvatarSearchCriteriaMessage(PlanetSideGUID(1222), List(0, 0, 0, 0, 0, 0))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
|
||||
"encode (failure; wrong number of list entries)" in {
|
||||
val msg = AvatarSearchCriteriaMessage(PlanetSideGUID(1222), List(0))
|
||||
PacketCoding.EncodePacket(msg).isSuccessful mustEqual false
|
||||
}
|
||||
|
||||
"encode (failure; list number too big)" in {
|
||||
val msg = AvatarSearchCriteriaMessage(PlanetSideGUID(1222), List(0, 0, 0, 0, 0, 256))
|
||||
PacketCoding.EncodePacket(msg).isSuccessful mustEqual false
|
||||
}
|
||||
|
||||
"encode (failure; list number too small)" in {
|
||||
val msg = AvatarSearchCriteriaMessage(PlanetSideGUID(1222), List(0, 0, 0, -1, 0, 0))
|
||||
PacketCoding.EncodePacket(msg).isSuccessful mustEqual false
|
||||
}
|
||||
}
|
||||
80
src/test/scala/game/AvatarStatisticsMessageTest.scala
Normal file
80
src/test/scala/game/AvatarStatisticsMessageTest.scala
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class AvatarStatisticsMessageTest extends Specification {
|
||||
val string_long = hex"7F 4 00000000 0"
|
||||
val string_complex =
|
||||
hex"7F 01 3C 40 20 00 00 00 C0 00 00 00 00 00 00 00 20 00 00 00 20 00 00 00 40 00 00 00 00 00 00 00 00 00 00 00"
|
||||
|
||||
"decode (long)" in {
|
||||
PacketCoding.DecodePacket(string_long).require match {
|
||||
case AvatarStatisticsMessage(unk, stats) =>
|
||||
unk mustEqual 2
|
||||
stats.unk1 mustEqual None
|
||||
stats.unk2 mustEqual None
|
||||
stats.unk3.length mustEqual 1
|
||||
stats.unk3.head mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (complex)" in {
|
||||
PacketCoding.DecodePacket(string_complex).require match {
|
||||
case AvatarStatisticsMessage(unk, stats) =>
|
||||
unk mustEqual 0
|
||||
stats.unk1 mustEqual Some(1)
|
||||
stats.unk2 mustEqual Some(572)
|
||||
stats.unk3.length mustEqual 8
|
||||
stats.unk3.head mustEqual 1
|
||||
stats.unk3(1) mustEqual 6
|
||||
stats.unk3(2) mustEqual 0
|
||||
stats.unk3(3) mustEqual 1
|
||||
stats.unk3(4) mustEqual 1
|
||||
stats.unk3(5) mustEqual 2
|
||||
stats.unk3(6) mustEqual 0
|
||||
stats.unk3(7) mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (long)" in {
|
||||
val msg = AvatarStatisticsMessage(2, Statistics(0L))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_long
|
||||
}
|
||||
|
||||
"encode (complex)" in {
|
||||
val msg = AvatarStatisticsMessage(0, Statistics(1, 572, List[Long](1, 6, 0, 1, 1, 2, 0, 0)))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_complex
|
||||
}
|
||||
|
||||
"encode (failure; long; missing value)" in {
|
||||
val msg = AvatarStatisticsMessage(0, Statistics(None, None, List(0L)))
|
||||
PacketCoding.EncodePacket(msg).isFailure mustEqual true
|
||||
}
|
||||
|
||||
"encode (failure; complex; missing value (5-bit))" in {
|
||||
val msg = AvatarStatisticsMessage(0, Statistics(None, Some(572), List[Long](1, 6, 0, 1, 1, 2, 0, 0)))
|
||||
PacketCoding.EncodePacket(msg).isFailure mustEqual true
|
||||
}
|
||||
|
||||
"encode (failure; complex; missing value (11-bit))" in {
|
||||
val msg = AvatarStatisticsMessage(0, Statistics(Some(1), None, List[Long](1, 6, 0, 1, 1, 2, 0, 0)))
|
||||
PacketCoding.EncodePacket(msg).isFailure mustEqual true
|
||||
}
|
||||
|
||||
"encode (failure; complex; wrong number of list entries)" in {
|
||||
val msg = AvatarStatisticsMessage(0, Statistics(Some(1), None, List[Long](1, 6, 0, 1)))
|
||||
PacketCoding.EncodePacket(msg).isFailure mustEqual true
|
||||
}
|
||||
}
|
||||
49
src/test/scala/game/AvatarVehicleTimerMessageTest.scala
Normal file
49
src/test/scala/game/AvatarVehicleTimerMessageTest.scala
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class AvatarVehicleTimerMessageTest extends Specification {
|
||||
val string = hex"57bd16866d65646b69740500000000"
|
||||
val string2 = hex"57971b84667572794800000080"
|
||||
|
||||
"decode medkit" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case AvatarVehicleTimerMessage(player_guid, text, time, u1) =>
|
||||
player_guid mustEqual PlanetSideGUID(5821)
|
||||
text mustEqual "medkit"
|
||||
time mustEqual 5
|
||||
u1 mustEqual false
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
"decode fury" in {
|
||||
PacketCoding.DecodePacket(string2).require match {
|
||||
case AvatarVehicleTimerMessage(player_guid, text, time, u1) =>
|
||||
player_guid mustEqual PlanetSideGUID(7063)
|
||||
text mustEqual "fury"
|
||||
time mustEqual 72
|
||||
u1 mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode medkit" in {
|
||||
val msg = AvatarVehicleTimerMessage(PlanetSideGUID(5821), "medkit", 5, false)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
"encode fury" in {
|
||||
val msg = AvatarVehicleTimerMessage(PlanetSideGUID(7063), "fury", 72, true)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string2
|
||||
}
|
||||
}
|
||||
30
src/test/scala/game/BattleExperienceMessageTest.scala
Normal file
30
src/test/scala/game/BattleExperienceMessageTest.scala
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class BattleExperienceMessageTest extends Specification {
|
||||
val string = hex"B4 8A0A E7030000 00"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case BattleExperienceMessage(player_guid, experience, unk) =>
|
||||
player_guid mustEqual PlanetSideGUID(2698)
|
||||
experience mustEqual 999
|
||||
unk mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = BattleExperienceMessage(PlanetSideGUID(2698), 999, 0)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
336
src/test/scala/game/BattleplanMessageTest.scala
Normal file
336
src/test/scala/game/BattleplanMessageTest.scala
Normal file
|
|
@ -0,0 +1,336 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class BattleplanMessageTest extends Specification {
|
||||
val string_start =
|
||||
hex"b3 3a197902 94 59006500740041006e006f0074006800650072004600610069006c0075007200650041006c007400 0000 01 e0"
|
||||
val string_stop =
|
||||
hex"b3 3a197902 94 59006500740041006e006f0074006800650072004600610069006c0075007200650041006c007400 0000 01 f0"
|
||||
val string_line =
|
||||
hex"b3 85647702 8c 4f0075007400730074006100620075006c006f0075007300 0a00 20 2aba2b4aae8bd2aba334aae8dd2aca3b4ab28fd2aca414ab29152aca474ab292d2ada4d4ab69452ada534ab695d2ada594ab696d2ada5d4ab697d2ada614ab698d2ada654ab699d2ada694ab69ad2aea6d4aba9bd2aea714aba9cd2aea754aba9dd2aea794aba9ed"
|
||||
val string_style = hex"b3856477028c4f0075007400730074006100620075006c006f00750073000a00031d22aba2f4aae8cd"
|
||||
val string_message =
|
||||
hex"b3 85647702 8c 4f0075007400730074006100620075006c006f0075007300 0a00 01 6aba2b5011c0480065006c006c006f00200041007500720061007800690073002100"
|
||||
//0xb3856477028c4f0075007400730074006100620075006c006f00750073000a000130
|
||||
|
||||
"decode (start)" in {
|
||||
PacketCoding.DecodePacket(string_start).require match {
|
||||
case BattleplanMessage(char_id, player_name, zone_id, diagrams) =>
|
||||
char_id mustEqual 41490746
|
||||
player_name mustEqual "YetAnotherFailureAlt"
|
||||
zone_id mustEqual 0
|
||||
diagrams.size mustEqual 1
|
||||
//0
|
||||
diagrams.head.action mustEqual DiagramActionCode.StartDrawing
|
||||
diagrams.head.stroke.isDefined mustEqual false
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (end)" in {
|
||||
PacketCoding.DecodePacket(string_stop).require match {
|
||||
case BattleplanMessage(char_id, player_name, zone_id, diagrams) =>
|
||||
char_id mustEqual 41490746
|
||||
player_name mustEqual "YetAnotherFailureAlt"
|
||||
zone_id mustEqual 0
|
||||
diagrams.size mustEqual 1
|
||||
//0
|
||||
diagrams.head.action mustEqual DiagramActionCode.StopDrawing
|
||||
diagrams.head.stroke.isDefined mustEqual false
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (stop)" in {
|
||||
PacketCoding.DecodePacket(string_line).require match {
|
||||
case BattleplanMessage(char_id, player_name, zone_id, diagrams) =>
|
||||
char_id mustEqual 41378949
|
||||
player_name mustEqual "Outstabulous"
|
||||
zone_id mustEqual 10
|
||||
diagrams.size mustEqual 32
|
||||
//0
|
||||
diagrams.head.action mustEqual DiagramActionCode.Vertex
|
||||
diagrams.head.stroke.isDefined mustEqual true
|
||||
diagrams.head.stroke.get.isInstanceOf[Vertex] mustEqual true
|
||||
diagrams.head.stroke.get.asInstanceOf[Vertex].x mustEqual 7512.0f
|
||||
diagrams.head.stroke.get.asInstanceOf[Vertex].y mustEqual 6312.0f
|
||||
//1
|
||||
diagrams(1).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(1).stroke.get.asInstanceOf[Vertex].x mustEqual 7512.0f
|
||||
diagrams(1).stroke.get.asInstanceOf[Vertex].y mustEqual 6328.0f
|
||||
//2
|
||||
diagrams(2).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(2).stroke.get.asInstanceOf[Vertex].x mustEqual 7512.0f
|
||||
diagrams(2).stroke.get.asInstanceOf[Vertex].y mustEqual 6344.0f
|
||||
//3
|
||||
diagrams(3).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(3).stroke.get.asInstanceOf[Vertex].x mustEqual 7512.0f
|
||||
diagrams(3).stroke.get.asInstanceOf[Vertex].y mustEqual 6360.0f
|
||||
//4
|
||||
diagrams(4).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(4).stroke.get.asInstanceOf[Vertex].x mustEqual 7520.0f
|
||||
diagrams(4).stroke.get.asInstanceOf[Vertex].y mustEqual 6376.0f
|
||||
//5
|
||||
diagrams(5).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(5).stroke.get.asInstanceOf[Vertex].x mustEqual 7520.0f
|
||||
diagrams(5).stroke.get.asInstanceOf[Vertex].y mustEqual 6392.0f
|
||||
//6
|
||||
diagrams(6).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(6).stroke.get.asInstanceOf[Vertex].x mustEqual 7520.0f
|
||||
diagrams(6).stroke.get.asInstanceOf[Vertex].y mustEqual 6400.0f
|
||||
//7
|
||||
diagrams(7).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(7).stroke.get.asInstanceOf[Vertex].x mustEqual 7520.0f
|
||||
diagrams(7).stroke.get.asInstanceOf[Vertex].y mustEqual 6416.0f
|
||||
//8
|
||||
diagrams(8).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(8).stroke.get.asInstanceOf[Vertex].x mustEqual 7520.0f
|
||||
diagrams(8).stroke.get.asInstanceOf[Vertex].y mustEqual 6424.0f
|
||||
//9
|
||||
diagrams(9).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(9).stroke.get.asInstanceOf[Vertex].x mustEqual 7520.0f
|
||||
diagrams(9).stroke.get.asInstanceOf[Vertex].y mustEqual 6440.0f
|
||||
//10
|
||||
diagrams(10).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(10).stroke.get.asInstanceOf[Vertex].x mustEqual 7528.0f
|
||||
diagrams(10).stroke.get.asInstanceOf[Vertex].y mustEqual 6448.0f
|
||||
//11
|
||||
diagrams(11).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(11).stroke.get.asInstanceOf[Vertex].x mustEqual 7528.0f
|
||||
diagrams(11).stroke.get.asInstanceOf[Vertex].y mustEqual 6464.0f
|
||||
//12
|
||||
diagrams(12).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(12).stroke.get.asInstanceOf[Vertex].x mustEqual 7528.0f
|
||||
diagrams(12).stroke.get.asInstanceOf[Vertex].y mustEqual 6472.0f
|
||||
//13
|
||||
diagrams(13).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(13).stroke.get.asInstanceOf[Vertex].x mustEqual 7528.0f
|
||||
diagrams(13).stroke.get.asInstanceOf[Vertex].y mustEqual 6488.0f
|
||||
//14
|
||||
diagrams(14).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(14).stroke.get.asInstanceOf[Vertex].x mustEqual 7528.0f
|
||||
diagrams(14).stroke.get.asInstanceOf[Vertex].y mustEqual 6496.0f
|
||||
//15
|
||||
diagrams(15).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(15).stroke.get.asInstanceOf[Vertex].x mustEqual 7528.0f
|
||||
diagrams(15).stroke.get.asInstanceOf[Vertex].y mustEqual 6504.0f
|
||||
//16
|
||||
diagrams(16).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(16).stroke.get.asInstanceOf[Vertex].x mustEqual 7528.0f
|
||||
diagrams(16).stroke.get.asInstanceOf[Vertex].y mustEqual 6512.0f
|
||||
//17
|
||||
diagrams(17).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(17).stroke.get.asInstanceOf[Vertex].x mustEqual 7528.0f
|
||||
diagrams(17).stroke.get.asInstanceOf[Vertex].y mustEqual 6520.0f
|
||||
//18
|
||||
diagrams(18).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(18).stroke.get.asInstanceOf[Vertex].x mustEqual 7528.0f
|
||||
diagrams(18).stroke.get.asInstanceOf[Vertex].y mustEqual 6528.0f
|
||||
//19
|
||||
diagrams(19).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(19).stroke.get.asInstanceOf[Vertex].x mustEqual 7528.0f
|
||||
diagrams(19).stroke.get.asInstanceOf[Vertex].y mustEqual 6536.0f
|
||||
//20
|
||||
diagrams(20).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(20).stroke.get.asInstanceOf[Vertex].x mustEqual 7528.0f
|
||||
diagrams(20).stroke.get.asInstanceOf[Vertex].y mustEqual 6544.0f
|
||||
//21
|
||||
diagrams(21).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(21).stroke.get.asInstanceOf[Vertex].x mustEqual 7528.0f
|
||||
diagrams(21).stroke.get.asInstanceOf[Vertex].y mustEqual 6552.0f
|
||||
//22
|
||||
diagrams(22).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(22).stroke.get.asInstanceOf[Vertex].x mustEqual 7528.0f
|
||||
diagrams(22).stroke.get.asInstanceOf[Vertex].y mustEqual 6560.0f
|
||||
//23
|
||||
diagrams(23).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(23).stroke.get.asInstanceOf[Vertex].x mustEqual 7528.0f
|
||||
diagrams(23).stroke.get.asInstanceOf[Vertex].y mustEqual 6568.0f
|
||||
//24
|
||||
diagrams(24).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(24).stroke.get.asInstanceOf[Vertex].x mustEqual 7536.0f
|
||||
diagrams(24).stroke.get.asInstanceOf[Vertex].y mustEqual 6576.0f
|
||||
//25
|
||||
diagrams(25).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(25).stroke.get.asInstanceOf[Vertex].x mustEqual 7536.0f
|
||||
diagrams(25).stroke.get.asInstanceOf[Vertex].y mustEqual 6584.0f
|
||||
//26
|
||||
diagrams(26).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(26).stroke.get.asInstanceOf[Vertex].x mustEqual 7536.0f
|
||||
diagrams(26).stroke.get.asInstanceOf[Vertex].y mustEqual 6592.0f
|
||||
//27
|
||||
diagrams(27).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(27).stroke.get.asInstanceOf[Vertex].x mustEqual 7536.0f
|
||||
diagrams(27).stroke.get.asInstanceOf[Vertex].y mustEqual 6600.0f
|
||||
//28
|
||||
diagrams(28).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(28).stroke.get.asInstanceOf[Vertex].x mustEqual 7536.0f
|
||||
diagrams(28).stroke.get.asInstanceOf[Vertex].y mustEqual 6608.0f
|
||||
//29
|
||||
diagrams(29).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(29).stroke.get.asInstanceOf[Vertex].x mustEqual 7536.0f
|
||||
diagrams(29).stroke.get.asInstanceOf[Vertex].y mustEqual 6616.0f
|
||||
//30
|
||||
diagrams(30).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(30).stroke.get.asInstanceOf[Vertex].x mustEqual 7536.0f
|
||||
diagrams(30).stroke.get.asInstanceOf[Vertex].y mustEqual 6624.0f
|
||||
//31
|
||||
diagrams(31).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(31).stroke.get.asInstanceOf[Vertex].x mustEqual 7536.0f
|
||||
diagrams(31).stroke.get.asInstanceOf[Vertex].y mustEqual 6632.0f
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (style)" in {
|
||||
PacketCoding.DecodePacket(string_style).require match {
|
||||
case BattleplanMessage(char_id, player_name, zone_id, diagrams) =>
|
||||
char_id mustEqual 41378949
|
||||
player_name mustEqual "Outstabulous"
|
||||
zone_id mustEqual 10
|
||||
diagrams.size mustEqual 3
|
||||
//0
|
||||
diagrams.head.action mustEqual DiagramActionCode.Style
|
||||
diagrams.head.stroke.isDefined mustEqual true
|
||||
diagrams.head.stroke.get.isInstanceOf[Style] mustEqual true
|
||||
diagrams.head.stroke.get.asInstanceOf[Style].thickness mustEqual 3.0f
|
||||
diagrams.head.stroke.get.asInstanceOf[Style].color mustEqual 2
|
||||
//1
|
||||
diagrams(1).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(1).stroke.get.asInstanceOf[Vertex].x mustEqual 7512.0f
|
||||
diagrams(1).stroke.get.asInstanceOf[Vertex].y mustEqual 6328.0f
|
||||
//2
|
||||
diagrams(2).action mustEqual DiagramActionCode.Vertex
|
||||
diagrams(2).stroke.get.asInstanceOf[Vertex].x mustEqual 7512.0f
|
||||
diagrams(2).stroke.get.asInstanceOf[Vertex].y mustEqual 6344.0f
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (message)" in {
|
||||
PacketCoding.DecodePacket(string_message).require match {
|
||||
case BattleplanMessage(char_id, player_name, zone_id, diagrams) =>
|
||||
char_id mustEqual 41378949
|
||||
player_name mustEqual "Outstabulous"
|
||||
zone_id mustEqual 10
|
||||
diagrams.size mustEqual 1
|
||||
//0
|
||||
diagrams.head.action mustEqual DiagramActionCode.DrawString
|
||||
diagrams.head.stroke.isDefined mustEqual true
|
||||
diagrams.head.stroke.get.isInstanceOf[DrawString] mustEqual true
|
||||
diagrams.head.stroke.get.asInstanceOf[DrawString].x mustEqual 7512.0f
|
||||
diagrams.head.stroke.get.asInstanceOf[DrawString].y mustEqual 6312.0f
|
||||
diagrams.head.stroke.get.asInstanceOf[DrawString].color mustEqual 2
|
||||
diagrams.head.stroke.get.asInstanceOf[DrawString].channel mustEqual 0
|
||||
diagrams.head.stroke.get.asInstanceOf[DrawString].message mustEqual "Hello Auraxis!"
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (start)" in {
|
||||
val msg = BattleplanMessage(
|
||||
41490746,
|
||||
"YetAnotherFailureAlt",
|
||||
0,
|
||||
BattleDiagramAction(DiagramActionCode.StartDrawing) ::
|
||||
Nil
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_start
|
||||
}
|
||||
|
||||
"encode (stop)" in {
|
||||
val msg = BattleplanMessage(
|
||||
41490746,
|
||||
"YetAnotherFailureAlt",
|
||||
0,
|
||||
BattleDiagramAction(DiagramActionCode.StopDrawing) ::
|
||||
Nil
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_stop
|
||||
}
|
||||
|
||||
"encode (line)" in {
|
||||
val msg = BattleplanMessage(
|
||||
41378949,
|
||||
"Outstabulous",
|
||||
10,
|
||||
BattleDiagramAction.vertex(7512.0f, 6312.0f) ::
|
||||
BattleDiagramAction.vertex(7512.0f, 6328.0f) ::
|
||||
BattleDiagramAction.vertex(7512.0f, 6344.0f) ::
|
||||
BattleDiagramAction.vertex(7512.0f, 6360.0f) ::
|
||||
BattleDiagramAction.vertex(7520.0f, 6376.0f) ::
|
||||
BattleDiagramAction.vertex(7520.0f, 6392.0f) ::
|
||||
BattleDiagramAction.vertex(7520.0f, 6400.0f) ::
|
||||
BattleDiagramAction.vertex(7520.0f, 6416.0f) ::
|
||||
BattleDiagramAction.vertex(7520.0f, 6424.0f) ::
|
||||
BattleDiagramAction.vertex(7520.0f, 6440.0f) ::
|
||||
BattleDiagramAction.vertex(7528.0f, 6448.0f) ::
|
||||
BattleDiagramAction.vertex(7528.0f, 6464.0f) ::
|
||||
BattleDiagramAction.vertex(7528.0f, 6472.0f) ::
|
||||
BattleDiagramAction.vertex(7528.0f, 6488.0f) ::
|
||||
BattleDiagramAction.vertex(7528.0f, 6496.0f) ::
|
||||
BattleDiagramAction.vertex(7528.0f, 6504.0f) ::
|
||||
BattleDiagramAction.vertex(7528.0f, 6512.0f) ::
|
||||
BattleDiagramAction.vertex(7528.0f, 6520.0f) ::
|
||||
BattleDiagramAction.vertex(7528.0f, 6528.0f) ::
|
||||
BattleDiagramAction.vertex(7528.0f, 6536.0f) ::
|
||||
BattleDiagramAction.vertex(7528.0f, 6544.0f) ::
|
||||
BattleDiagramAction.vertex(7528.0f, 6552.0f) ::
|
||||
BattleDiagramAction.vertex(7528.0f, 6560.0f) ::
|
||||
BattleDiagramAction.vertex(7528.0f, 6568.0f) ::
|
||||
BattleDiagramAction.vertex(7536.0f, 6576.0f) ::
|
||||
BattleDiagramAction.vertex(7536.0f, 6584.0f) ::
|
||||
BattleDiagramAction.vertex(7536.0f, 6592.0f) ::
|
||||
BattleDiagramAction.vertex(7536.0f, 6600.0f) ::
|
||||
BattleDiagramAction.vertex(7536.0f, 6608.0f) ::
|
||||
BattleDiagramAction.vertex(7536.0f, 6616.0f) ::
|
||||
BattleDiagramAction.vertex(7536.0f, 6624.0f) ::
|
||||
BattleDiagramAction.vertex(7536.0f, 6632.0f) ::
|
||||
Nil
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_line
|
||||
}
|
||||
|
||||
"encode (style)" in {
|
||||
val msg = BattleplanMessage(
|
||||
41378949,
|
||||
"Outstabulous",
|
||||
10,
|
||||
BattleDiagramAction.style(3.0f, 2) ::
|
||||
BattleDiagramAction.vertex(7512.0f, 6328.0f) ::
|
||||
BattleDiagramAction.vertex(7512.0f, 6344.0f) ::
|
||||
Nil
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_style
|
||||
}
|
||||
|
||||
"encode (message)" in {
|
||||
val msg = BattleplanMessage(
|
||||
41378949,
|
||||
"Outstabulous",
|
||||
10,
|
||||
BattleDiagramAction.drawString(7512.0f, 6312.0f, 2, 0, "Hello Auraxis!") :: Nil
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_message
|
||||
}
|
||||
}
|
||||
27
src/test/scala/game/BeginZoningMessageTest.scala
Normal file
27
src/test/scala/game/BeginZoningMessageTest.scala
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class BeginZoningMessageTest extends Specification {
|
||||
val string = hex"43" //yes, just the opcode
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case BeginZoningMessage() =>
|
||||
ok
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = BeginZoningMessage()
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
125
src/test/scala/game/BindPlayerMessageTest.scala
Normal file
125
src/test/scala/game/BindPlayerMessageTest.scala
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{SpawnGroup, Vector3}
|
||||
import scodec.bits._
|
||||
|
||||
class BindPlayerMessageTest extends Specification {
|
||||
val string_standard = hex"16028004000000000000000000000000000000"
|
||||
val string_ams = hex"16 05 8440616D73 08 28000000 00000000 00000 00000 0000"
|
||||
val string_tech = hex"16 01 8b40746563685f706c616e74 d4 28000000 38000000 00064 012b1 a044"
|
||||
val string_akkan = hex"16048440616d7388100000001400000214e171a8e33024"
|
||||
|
||||
"decode (standard)" in {
|
||||
PacketCoding.DecodePacket(string_standard).require match {
|
||||
case BindPlayerMessage(action, bindDesc, unk1, logging, unk2, unk3, unk4, pos) =>
|
||||
action mustEqual BindStatus.Unbind
|
||||
bindDesc mustEqual ""
|
||||
unk1 mustEqual false
|
||||
logging mustEqual false
|
||||
unk2 mustEqual SpawnGroup.BoundAMS
|
||||
unk3 mustEqual 0
|
||||
unk4 mustEqual 0
|
||||
pos mustEqual Vector3.Zero
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (ams)" in {
|
||||
PacketCoding.DecodePacket(string_ams).require match {
|
||||
case BindPlayerMessage(action, bindDesc, unk1, logging, unk2, unk3, unk4, pos) =>
|
||||
action mustEqual BindStatus.Unavailable
|
||||
bindDesc mustEqual "@ams"
|
||||
unk1 mustEqual false
|
||||
logging mustEqual false
|
||||
unk2 mustEqual SpawnGroup.AMS
|
||||
unk3 mustEqual 10
|
||||
unk4 mustEqual 0
|
||||
pos mustEqual Vector3.Zero
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (tech)" in {
|
||||
PacketCoding.DecodePacket(string_tech).require match {
|
||||
case BindPlayerMessage(action, bindDesc, unk1, logging, unk2, unk3, unk4, pos) =>
|
||||
action mustEqual BindStatus.Bind
|
||||
bindDesc mustEqual "@tech_plant"
|
||||
unk1 mustEqual true
|
||||
logging mustEqual true
|
||||
unk2 mustEqual SpawnGroup.BoundFacility
|
||||
unk3 mustEqual 10
|
||||
unk4 mustEqual 14
|
||||
pos mustEqual Vector3(4610.0f, 6292, 69.625f)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (akkan)" in {
|
||||
PacketCoding.DecodePacket(string_akkan).require match {
|
||||
case BindPlayerMessage(action, bindDesc, unk1, logging, unk2, unk3, unk4, pos) =>
|
||||
action mustEqual BindStatus.Available
|
||||
bindDesc mustEqual "@ams"
|
||||
unk1 mustEqual true
|
||||
logging mustEqual false
|
||||
unk2 mustEqual SpawnGroup.AMS
|
||||
unk3 mustEqual 4
|
||||
unk4 mustEqual 5
|
||||
pos mustEqual Vector3(2673.039f, 4423.547f, 39.1875f)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (standard)" in {
|
||||
val msg = BindPlayerMessage.Standard
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_standard
|
||||
}
|
||||
|
||||
"encode (ams)" in {
|
||||
val msg = BindPlayerMessage(BindStatus.Unavailable, "@ams", false, false, SpawnGroup.AMS, 10, 0, Vector3.Zero)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_ams
|
||||
}
|
||||
|
||||
"encode (tech)" in {
|
||||
val msg = BindPlayerMessage(
|
||||
BindStatus.Bind,
|
||||
"@tech_plant",
|
||||
true,
|
||||
true,
|
||||
SpawnGroup.BoundFacility,
|
||||
10,
|
||||
14,
|
||||
Vector3(4610.0f, 6292, 69.625f)
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_tech
|
||||
}
|
||||
|
||||
"encode (akkan)" in {
|
||||
val msg = BindPlayerMessage(
|
||||
BindStatus.Available,
|
||||
"@ams",
|
||||
true,
|
||||
false,
|
||||
SpawnGroup.AMS,
|
||||
4,
|
||||
5,
|
||||
Vector3(2673.039f, 4423.547f, 39.1875f)
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_akkan
|
||||
}
|
||||
}
|
||||
31
src/test/scala/game/BroadcastWarpgateUpdateMessageTest.scala
Normal file
31
src/test/scala/game/BroadcastWarpgateUpdateMessageTest.scala
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class BroadcastWarpgateUpdateMessageTest extends Specification {
|
||||
val string = hex"D9 0D 00 01 00 20"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case BroadcastWarpgateUpdateMessage(continent_guid, building_guid, state1, state2, state3) =>
|
||||
continent_guid mustEqual 13
|
||||
building_guid mustEqual 1
|
||||
state1 mustEqual false
|
||||
state2 mustEqual false
|
||||
state3 mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = BroadcastWarpgateUpdateMessage(13, 1, false, false, true)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
50
src/test/scala/game/BugReportMessageTest.scala
Normal file
50
src/test/scala/game/BugReportMessageTest.scala
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.Vector3
|
||||
import scodec.bits._
|
||||
|
||||
class BugReportMessageTest extends Specification {
|
||||
val string =
|
||||
hex"89 03000000 0F000000 8B4465632020322032303039 1 1 0 19 6C511 656B1 7A11 830610062006300 843100320033003400"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case BugReportMessage(major, minor, date, btype, repeat, unk, zone, loc, summary, desc) =>
|
||||
major mustEqual 3
|
||||
minor mustEqual 15
|
||||
date mustEqual "Dec 2 2009"
|
||||
btype mustEqual BugType.GAMEPLAY
|
||||
repeat mustEqual true
|
||||
zone mustEqual 25
|
||||
loc.x mustEqual 674.84375f
|
||||
loc.y mustEqual 726.78906f
|
||||
loc.z mustEqual 69.90625f
|
||||
summary mustEqual "abc"
|
||||
desc mustEqual "1234"
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = BugReportMessage(
|
||||
3,
|
||||
15,
|
||||
"Dec 2 2009",
|
||||
BugType.GAMEPLAY,
|
||||
true,
|
||||
0,
|
||||
25,
|
||||
Vector3(674.84375f, 726.78906f, 69.90625f),
|
||||
"abc",
|
||||
"1234"
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
93
src/test/scala/game/BuildingInfoUpdateMessageTest.scala
Normal file
93
src/test/scala/game/BuildingInfoUpdateMessageTest.scala
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{PlanetSideEmpire, PlanetSideGeneratorState}
|
||||
import scodec.bits._
|
||||
|
||||
class BuildingInfoUpdateMessageTest extends Specification {
|
||||
val string = hex"a0 04 00 09 00 16 00 00 00 00 80 00 00 00 17 00 00 00 00 00 00 40"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case BuildingInfoUpdateMessage(
|
||||
continent_guid,
|
||||
building_guid,
|
||||
ntu_level,
|
||||
is_hacked,
|
||||
empire_hack,
|
||||
hack_time_remaining,
|
||||
empire_own,
|
||||
unk1,
|
||||
unk1x,
|
||||
generator_state,
|
||||
spawn_tubes_normal,
|
||||
force_dome_active,
|
||||
lattice_benefit,
|
||||
unk3,
|
||||
unk4,
|
||||
unk5,
|
||||
unk6,
|
||||
unk7,
|
||||
unk7x,
|
||||
boost_spawn_pain,
|
||||
boost_generator_pain
|
||||
) =>
|
||||
continent_guid mustEqual 4
|
||||
building_guid mustEqual 9
|
||||
ntu_level mustEqual 1
|
||||
is_hacked mustEqual false
|
||||
empire_hack mustEqual PlanetSideEmpire.NEUTRAL
|
||||
hack_time_remaining mustEqual 0
|
||||
empire_own mustEqual PlanetSideEmpire.NC
|
||||
unk1 mustEqual 0
|
||||
unk1x mustEqual None
|
||||
generator_state mustEqual PlanetSideGeneratorState.Normal
|
||||
spawn_tubes_normal mustEqual true
|
||||
force_dome_active mustEqual false
|
||||
lattice_benefit mustEqual 28
|
||||
unk3 mustEqual 0
|
||||
unk4.size mustEqual 0
|
||||
unk4.isEmpty mustEqual true
|
||||
unk5 mustEqual 0
|
||||
unk6 mustEqual false
|
||||
unk7 mustEqual 8
|
||||
unk7x mustEqual None
|
||||
boost_spawn_pain mustEqual false
|
||||
boost_generator_pain mustEqual false
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = BuildingInfoUpdateMessage(
|
||||
4,
|
||||
9,
|
||||
1,
|
||||
false,
|
||||
PlanetSideEmpire.NEUTRAL,
|
||||
0,
|
||||
PlanetSideEmpire.NC,
|
||||
0,
|
||||
None,
|
||||
PlanetSideGeneratorState.Normal,
|
||||
true,
|
||||
false,
|
||||
28,
|
||||
0,
|
||||
Nil,
|
||||
0,
|
||||
false,
|
||||
8,
|
||||
None,
|
||||
false,
|
||||
false
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
64
src/test/scala/game/ChainLashMessageTest.scala
Normal file
64
src/test/scala/game/ChainLashMessageTest.scala
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright (c) 2020 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{PlanetSideGUID, Vector3}
|
||||
import scodec.bits._
|
||||
|
||||
class ChainLashMessageTest extends Specification {
|
||||
val string1 = hex"c5 cafe708880df81e910100000043060"
|
||||
val string2 = hex"c5 5282e910100000093050"
|
||||
|
||||
"decode (1)" in {
|
||||
PacketCoding.DecodePacket(string1).require match {
|
||||
case ChainLashMessage(u1a, u1b, u2, u3) =>
|
||||
u1a.isEmpty mustEqual true
|
||||
u1b.contains(Vector3(7673.164f, 544.1328f, 14.984375f)) mustEqual true
|
||||
u2 mustEqual 466
|
||||
u3 mustEqual List(PlanetSideGUID(1603))
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (2)" in {
|
||||
PacketCoding.DecodePacket(string2).require match {
|
||||
case ChainLashMessage(u1a, u1b, u2, u3) =>
|
||||
u1a.contains(PlanetSideGUID(1445)) mustEqual true
|
||||
u1b.isEmpty mustEqual true
|
||||
u2 mustEqual 466
|
||||
u3 mustEqual List(PlanetSideGUID(1427))
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (1)" in {
|
||||
val msg = ChainLashMessage(Vector3(7673.164f, 544.1328f, 14.984375f), 466, List(PlanetSideGUID(1603)))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string1
|
||||
}
|
||||
|
||||
"encode (2)" in {
|
||||
val msg = ChainLashMessage(PlanetSideGUID(1445), 466, List(PlanetSideGUID(1427)))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string2
|
||||
}
|
||||
|
||||
"encode (fail; 1)" in {
|
||||
ChainLashMessage(
|
||||
Some(PlanetSideGUID(1445)),
|
||||
Some(Vector3(7673.164f, 544.1328f, 14.984375f)),
|
||||
466,
|
||||
List(PlanetSideGUID(1427))
|
||||
) must throwA[AssertionError]
|
||||
}
|
||||
|
||||
"encode (fail; 2)" in {
|
||||
ChainLashMessage(None, None, 466, List(PlanetSideGUID(1427))) must throwA[AssertionError]
|
||||
}
|
||||
}
|
||||
29
src/test/scala/game/ChangeAmmoMessageTest.scala
Normal file
29
src/test/scala/game/ChangeAmmoMessageTest.scala
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class ChangeAmmoMessageTest extends Specification {
|
||||
val string = hex"47 4E00 00000000"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case ChangeAmmoMessage(item_guid, unk1) =>
|
||||
item_guid mustEqual PlanetSideGUID(78)
|
||||
unk1 mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = ChangeAmmoMessage(PlanetSideGUID(78), 0)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
29
src/test/scala/game/ChangeFireModeMessageTest.scala
Normal file
29
src/test/scala/game/ChangeFireModeMessageTest.scala
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class ChangeFireModeMessageTest extends Specification {
|
||||
val string = hex"46 4C0020"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case ChangeFireModeMessage(item_guid, fire_mode) =>
|
||||
item_guid mustEqual PlanetSideGUID(76)
|
||||
fire_mode mustEqual 1
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = ChangeFireModeMessage(PlanetSideGUID(76), 1)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
28
src/test/scala/game/ChangeFireStateMessage_StartTest.scala
Normal file
28
src/test/scala/game/ChangeFireStateMessage_StartTest.scala
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class ChangeFireStateMessage_StartTest extends Specification {
|
||||
val string = hex"39 4C00"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case ChangeFireStateMessage_Start(item_guid) =>
|
||||
item_guid mustEqual PlanetSideGUID(76)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = ChangeFireStateMessage_Start(PlanetSideGUID(76))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
28
src/test/scala/game/ChangeFireStateMessage_StopTest.scala
Normal file
28
src/test/scala/game/ChangeFireStateMessage_StopTest.scala
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class ChangeFireStateMessage_StopTest extends Specification {
|
||||
val string = hex"3A 4C00"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case ChangeFireStateMessage_Stop(item_guid) =>
|
||||
item_guid mustEqual PlanetSideGUID(76)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = ChangeFireStateMessage_Stop(PlanetSideGUID(76))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
29
src/test/scala/game/ChangeShortcutBankMessageTest.scala
Normal file
29
src/test/scala/game/ChangeShortcutBankMessageTest.scala
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class ChangeShortcutBankMessageTest extends Specification {
|
||||
val string = hex"29 4B00 20"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case ChangeShortcutBankMessage(player_guid, bank) =>
|
||||
player_guid mustEqual PlanetSideGUID(75)
|
||||
bank mustEqual 2
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = ChangeShortcutBankMessage(PlanetSideGUID(75), 2)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
33
src/test/scala/game/CharacterCreateRequestMessageTest.scala
Normal file
33
src/test/scala/game/CharacterCreateRequestMessageTest.scala
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire}
|
||||
import scodec.bits._
|
||||
|
||||
class CharacterCreateRequestMessageTest extends Specification {
|
||||
val string = hex"2f 88 54006500730074004300680061007200 320590"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case CharacterCreateRequestMessage(name, head, voice, gender, faction) =>
|
||||
name mustEqual "TestChar"
|
||||
head mustEqual 50
|
||||
voice mustEqual CharacterVoice.Voice5
|
||||
gender mustEqual CharacterGender.Female
|
||||
faction mustEqual PlanetSideEmpire.NC
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg =
|
||||
CharacterCreateRequestMessage("TestChar", 50, CharacterVoice.Voice5, CharacterGender.Female, PlanetSideEmpire.NC)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
33
src/test/scala/game/CharacterInfoMessageTest.scala
Normal file
33
src/test/scala/game/CharacterInfoMessageTest.scala
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class CharacterInfoMessageTest extends Specification {
|
||||
val string = hex"14 0F000000 10270000C1D87A024B00265CB08000"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case CharacterInfoMessage(unk, zone, charId, guid, finished, last) =>
|
||||
unk mustEqual 15L
|
||||
zone mustEqual PlanetSideZoneID(10000)
|
||||
charId mustEqual 41605313L
|
||||
guid mustEqual PlanetSideGUID(75)
|
||||
finished mustEqual false
|
||||
last mustEqual 6404428L
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = CharacterInfoMessage(15L, PlanetSideZoneID(10000), 41605313L, PlanetSideGUID(75), false, 6404428L)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
71
src/test/scala/game/CharacterKnowledgeMessageTest.scala
Normal file
71
src/test/scala/game/CharacterKnowledgeMessageTest.scala
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import net.psforever.objects.avatar.Certification
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class CharacterKnowledgeMessageTest extends Specification {
|
||||
val string = hex"ec cc637a02 45804600720061006e006b0065006e00740061006e006b0003c022dc0008f01800"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case CharacterKnowledgeMessage(char_id, Some(info)) =>
|
||||
char_id mustEqual 41575372L
|
||||
info mustEqual CharacterKnowledgeInfo(
|
||||
"Frankentank",
|
||||
Set(
|
||||
Certification.StandardAssault,
|
||||
Certification.ArmoredAssault1,
|
||||
Certification.MediumAssault,
|
||||
Certification.ReinforcedExoSuit,
|
||||
Certification.Harasser,
|
||||
Certification.Engineering,
|
||||
Certification.GroundSupport,
|
||||
Certification.AgileExoSuit,
|
||||
Certification.AIMAX,
|
||||
Certification.StandardExoSuit,
|
||||
Certification.AAMAX,
|
||||
Certification.ArmoredAssault2
|
||||
),
|
||||
15,
|
||||
0,
|
||||
PlanetSideGUID(12)
|
||||
)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = CharacterKnowledgeMessage(
|
||||
41575372L,
|
||||
CharacterKnowledgeInfo(
|
||||
"Frankentank",
|
||||
Set(
|
||||
Certification.StandardAssault,
|
||||
Certification.ArmoredAssault1,
|
||||
Certification.MediumAssault,
|
||||
Certification.ReinforcedExoSuit,
|
||||
Certification.Harasser,
|
||||
Certification.Engineering,
|
||||
Certification.GroundSupport,
|
||||
Certification.AgileExoSuit,
|
||||
Certification.AIMAX,
|
||||
Certification.StandardExoSuit,
|
||||
Certification.AAMAX,
|
||||
Certification.ArmoredAssault2
|
||||
),
|
||||
15,
|
||||
0,
|
||||
PlanetSideGUID(12)
|
||||
)
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
27
src/test/scala/game/CharacterNoRecordMessageTest.scala
Normal file
27
src/test/scala/game/CharacterNoRecordMessageTest.scala
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class CharacterNoRecordMessageTest extends Specification {
|
||||
val string = hex"13 00400000" //we have no record of this packet, so here's something fake that works
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case CharacterNoRecordMessage(unk) =>
|
||||
unk mustEqual 16384
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = CharacterNoRecordMessage(16384)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
28
src/test/scala/game/CharacterRequestMessageTest.scala
Normal file
28
src/test/scala/game/CharacterRequestMessageTest.scala
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class CharacterRequestMessageTest extends Specification {
|
||||
val string = hex"30 c1d87a02 00000000"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case CharacterRequestMessage(charId, action) =>
|
||||
charId mustEqual 41605313L
|
||||
action mustEqual CharacterRequestAction.Select
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = CharacterRequestMessage(41605313L, CharacterRequestAction.Select)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
56
src/test/scala/game/ChatMsgTest.scala
Normal file
56
src/test/scala/game/ChatMsgTest.scala
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.ChatMessageType
|
||||
import scodec.bits._
|
||||
|
||||
class ChatMsgTest extends Specification {
|
||||
val string_local = hex"12 1A C000 83610062006300"
|
||||
val string_tell = hex"12 20 C180640065006600 83610062006300"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string_local).require match {
|
||||
case ChatMsg(messagetype, has_wide_contents, recipient, contents, note_contents) =>
|
||||
messagetype mustEqual ChatMessageType.CMT_OPEN
|
||||
has_wide_contents mustEqual true
|
||||
recipient mustEqual ""
|
||||
contents mustEqual "abc"
|
||||
note_contents mustEqual None
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
|
||||
PacketCoding.DecodePacket(string_tell).require match {
|
||||
case ChatMsg(messagetype, has_wide_contents, recipient, contents, note_contents) =>
|
||||
messagetype mustEqual ChatMessageType.CMT_TELL
|
||||
has_wide_contents mustEqual true
|
||||
recipient mustEqual "def"
|
||||
contents mustEqual "abc"
|
||||
note_contents mustEqual None
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg_local = ChatMsg(ChatMessageType.CMT_OPEN, true, "", "abc", None)
|
||||
val pkt_local = PacketCoding.EncodePacket(msg_local).require.toByteVector
|
||||
|
||||
pkt_local mustEqual string_local
|
||||
|
||||
val msg_tell = ChatMsg(ChatMessageType.CMT_TELL, true, "def", "abc", None)
|
||||
val pkt_tell = PacketCoding.EncodePacket(msg_tell).require.toByteVector
|
||||
|
||||
pkt_tell mustEqual string_tell
|
||||
}
|
||||
|
||||
"allow and disallow note" in {
|
||||
ChatMsg(ChatMessageType.CMT_ARMOR, false, "DontCare", "DontCare", Some("Should be here")) must throwA[
|
||||
AssertionError
|
||||
]
|
||||
ChatMsg(ChatMessageType.CMT_NOTE, false, "DontCare", "DontCare", None) must throwA[AssertionError]
|
||||
}
|
||||
}
|
||||
30
src/test/scala/game/ChildObjectStateMessageTest.scala
Normal file
30
src/test/scala/game/ChildObjectStateMessageTest.scala
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class ChildObjectStateMessageTest extends Specification {
|
||||
val string = hex"1E 640B 06 47"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case ChildObjectStateMessage(object_guid, pitch, yaw) =>
|
||||
object_guid mustEqual PlanetSideGUID(2916)
|
||||
pitch mustEqual 343.125f
|
||||
yaw mustEqual 160.3125f
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = ChildObjectStateMessage(PlanetSideGUID(2916), 343.125f, 160.3125f)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
28
src/test/scala/game/ConnectToWorldMessageTest.scala
Normal file
28
src/test/scala/game/ConnectToWorldMessageTest.scala
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class ConnectToWorldMessageTest extends Specification {
|
||||
val string = hex"04 8667656D696E69 8C36342E33372E3135382E36393C75"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case ConnectToWorldMessage(serverName, serverIp, serverPort) =>
|
||||
serverName mustEqual "gemini"
|
||||
serverIp mustEqual "64.37.158.69"
|
||||
serverPort mustEqual 30012
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = ConnectToWorldMessage("gemini", "64.37.158.69", 30012)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
34
src/test/scala/game/ConnectToWorldRequestMessageTest.scala
Normal file
34
src/test/scala/game/ConnectToWorldRequestMessageTest.scala
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
class ConnectToWorldRequestMessageTest extends Specification {
|
||||
val string =
|
||||
hex"03 8667656D696E69 0000000000000000 00000000 00000000 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 "
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case ConnectToWorldRequestMessage(serverName, token, majorVersion, minorVersion, revision, buildDate, unk) =>
|
||||
serverName mustEqual "gemini"
|
||||
token mustEqual ""
|
||||
majorVersion mustEqual 0
|
||||
minorVersion mustEqual 0
|
||||
revision mustEqual 0
|
||||
buildDate mustEqual ""
|
||||
unk mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = ConnectToWorldRequestMessage("gemini", "", 0, 0, 0, "", 0)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
29
src/test/scala/game/ContinentalLockUpdateMessageTest.scala
Normal file
29
src/test/scala/game/ContinentalLockUpdateMessageTest.scala
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
import scodec.bits._
|
||||
|
||||
class ContinentalLockUpdateMessageTest extends Specification {
|
||||
val string = hex"A8 16 00 40"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case ContinentalLockUpdateMessage(continent_guid, empire) =>
|
||||
continent_guid mustEqual 22
|
||||
empire mustEqual PlanetSideEmpire.NC
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = ContinentalLockUpdateMessage(22, PlanetSideEmpire.NC)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
122
src/test/scala/game/CreateShortcutMessageTest.scala
Normal file
122
src/test/scala/game/CreateShortcutMessageTest.scala
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{ImplantType, PlanetSideGUID}
|
||||
import scodec.bits._
|
||||
|
||||
class CreateShortcutMessageTest extends Specification {
|
||||
val stringMedkit = hex"28 7210 01 00 90 C0 6D65646B6974 80 80"
|
||||
val stringMacro =
|
||||
hex"28 4C05 08 00 B1 C0 73686F72746375745F6D6163726F 83 4E00 5400 5500 9B 2F00 7000 6C00 6100 7400 6F00 6F00 6E00 2000 4900 6E00 6300 6F00 6D00 6900 6E00 6700 2000 4E00 5400 5500 2000 7300 7000 6100 6D00 2100"
|
||||
val stringRemove = hex"28 4C05 01 00 00"
|
||||
|
||||
"decode (medkit)" in {
|
||||
PacketCoding.DecodePacket(stringMedkit).require match {
|
||||
case CreateShortcutMessage(player_guid, slot, unk, addShortcut, shortcut) =>
|
||||
player_guid mustEqual PlanetSideGUID(4210)
|
||||
slot mustEqual 1
|
||||
unk mustEqual 0
|
||||
addShortcut mustEqual true
|
||||
shortcut.isDefined mustEqual true
|
||||
shortcut.get.purpose mustEqual 0
|
||||
shortcut.get.tile mustEqual "medkit"
|
||||
shortcut.get.effect1 mustEqual ""
|
||||
shortcut.get.effect2 mustEqual ""
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (macro)" in {
|
||||
PacketCoding.DecodePacket(stringMacro).require match {
|
||||
case CreateShortcutMessage(player_guid, slot, unk, addShortcut, shortcut) =>
|
||||
player_guid mustEqual PlanetSideGUID(1356)
|
||||
slot mustEqual 8
|
||||
unk mustEqual 0
|
||||
addShortcut mustEqual true
|
||||
shortcut.isDefined mustEqual true
|
||||
shortcut.get.purpose mustEqual 1
|
||||
shortcut.get.tile mustEqual "shortcut_macro"
|
||||
shortcut.get.effect1 mustEqual "NTU"
|
||||
shortcut.get.effect2 mustEqual "/platoon Incoming NTU spam!"
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (remove)" in {
|
||||
PacketCoding.DecodePacket(stringRemove).require match {
|
||||
case CreateShortcutMessage(player_guid, slot, unk, addShortcut, shortcut) =>
|
||||
player_guid mustEqual PlanetSideGUID(1356)
|
||||
slot mustEqual 1
|
||||
unk mustEqual 0
|
||||
addShortcut mustEqual false
|
||||
shortcut.isDefined mustEqual false
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (medkit)" in {
|
||||
val msg = CreateShortcutMessage(PlanetSideGUID(4210), 1, 0, true, Some(Shortcut(0, "medkit")))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual stringMedkit
|
||||
}
|
||||
|
||||
"encode (macro)" in {
|
||||
val msg = CreateShortcutMessage(
|
||||
PlanetSideGUID(1356),
|
||||
8,
|
||||
0,
|
||||
true,
|
||||
Some(Shortcut(1, "shortcut_macro", "NTU", "/platoon Incoming NTU spam!"))
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual stringMacro
|
||||
}
|
||||
|
||||
"encode (remove)" in {
|
||||
val msg = CreateShortcutMessage(PlanetSideGUID(1356), 1, 0, false)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual stringRemove
|
||||
}
|
||||
|
||||
"macro" in {
|
||||
val MACRO: Some[Shortcut] = Shortcut.MACRO("NTU", "/platoon Incoming NTU spam!")
|
||||
MACRO.get.purpose mustEqual 1
|
||||
MACRO.get.tile mustEqual "shortcut_macro"
|
||||
MACRO.get.effect1 mustEqual "NTU"
|
||||
MACRO.get.effect2 mustEqual "/platoon Incoming NTU spam!"
|
||||
}
|
||||
|
||||
"presets" in {
|
||||
ImplantType.AudioAmplifier.shortcut.purpose mustEqual 2
|
||||
ImplantType.AudioAmplifier.shortcut.tile mustEqual "audio_amplifier"
|
||||
ImplantType.DarklightVision.shortcut.purpose mustEqual 2
|
||||
ImplantType.DarklightVision.shortcut.tile mustEqual "darklight_vision"
|
||||
ImplantType.Targeting.shortcut.purpose mustEqual 2
|
||||
ImplantType.Targeting.shortcut.tile mustEqual "targeting"
|
||||
Shortcut.Medkit.get.purpose mustEqual 0
|
||||
Shortcut.Medkit.get.tile mustEqual "medkit"
|
||||
ImplantType.MeleeBooster.shortcut.purpose mustEqual 2
|
||||
ImplantType.MeleeBooster.shortcut.tile mustEqual "melee_booster"
|
||||
ImplantType.PersonalShield.shortcut.purpose mustEqual 2
|
||||
ImplantType.PersonalShield.shortcut.tile mustEqual "personal_shield"
|
||||
ImplantType.RangeMagnifier.shortcut.purpose mustEqual 2
|
||||
ImplantType.RangeMagnifier.shortcut.tile mustEqual "range_magnifier"
|
||||
ImplantType.AdvancedRegen.shortcut.purpose mustEqual 2
|
||||
ImplantType.AdvancedRegen.shortcut.tile mustEqual "advanced_regen"
|
||||
ImplantType.SecondWind.shortcut.purpose mustEqual 2
|
||||
ImplantType.SecondWind.shortcut.tile mustEqual "second_wind"
|
||||
ImplantType.SilentRun.shortcut.purpose mustEqual 2
|
||||
ImplantType.SilentRun.shortcut.tile mustEqual "silent_run"
|
||||
ImplantType.Surge.shortcut.purpose mustEqual 2
|
||||
ImplantType.Surge.shortcut.tile mustEqual "surge"
|
||||
}
|
||||
}
|
||||
350
src/test/scala/game/DamageFeedbackMessageTest.scala
Normal file
350
src/test/scala/game/DamageFeedbackMessageTest.scala
Normal file
|
|
@ -0,0 +1,350 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class DamageFeedbackMessageTest extends Specification {
|
||||
val string = hex"7b 3d842f610b2040000000"
|
||||
val string_2 = hex"7B 5E5826D8001DC0400000"
|
||||
|
||||
"decode (string 1)" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case DamageFeedbackMessage(unk1, unk2, unk2a, unk2b, unk2c, unk3, unk3a, unk3b, unk3c, unk3d, unk4, unk5, unk6) =>
|
||||
unk1 mustEqual 3
|
||||
unk2 mustEqual true
|
||||
unk2a.contains(PlanetSideGUID(2913)) mustEqual true
|
||||
unk2b.isEmpty mustEqual true
|
||||
unk2c.isEmpty mustEqual true
|
||||
unk3 mustEqual true
|
||||
unk3a.contains(PlanetSideGUID(2913)) mustEqual true
|
||||
unk3b.isEmpty mustEqual true
|
||||
unk3c.isEmpty mustEqual true
|
||||
unk3d.isEmpty mustEqual true
|
||||
unk4 mustEqual 1
|
||||
unk5 mustEqual 2
|
||||
unk6 mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (string 2)" in {
|
||||
PacketCoding.DecodePacket(string_2).require match {
|
||||
case DamageFeedbackMessage(unk1, unk2, unk2a, unk2b, unk2c, unk3, unk3a, unk3b, unk3c, unk3d, unk4, unk5, unk6) =>
|
||||
unk1 mustEqual 5
|
||||
unk2 mustEqual true
|
||||
unk2a.contains(PlanetSideGUID(2454)) mustEqual true
|
||||
unk2b.isEmpty mustEqual true
|
||||
unk2c.isEmpty mustEqual true
|
||||
unk3 mustEqual false
|
||||
unk3a.contains(PlanetSideGUID(216)) mustEqual true
|
||||
unk3b.isEmpty mustEqual true
|
||||
unk3c.isEmpty mustEqual true
|
||||
unk3d.isEmpty mustEqual true
|
||||
unk4 mustEqual 0
|
||||
unk5 mustEqual 750
|
||||
unk6 mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (string 1)" in {
|
||||
val msg = DamageFeedbackMessage(
|
||||
3,
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
None,
|
||||
None,
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
1,
|
||||
2,
|
||||
0
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
|
||||
"encode (string 2)" in {
|
||||
val msg = DamageFeedbackMessage(
|
||||
5,
|
||||
true,
|
||||
Some(PlanetSideGUID(2454)),
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
Some(PlanetSideGUID(216)),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
0,
|
||||
750,
|
||||
0
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_2
|
||||
}
|
||||
|
||||
"assert catches" in {
|
||||
//unk2: no parameters
|
||||
DamageFeedbackMessage(
|
||||
3,
|
||||
true,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
1,
|
||||
2,
|
||||
0
|
||||
) must throwA[AssertionError]
|
||||
//unk2: two exclusive parameters
|
||||
DamageFeedbackMessage(
|
||||
3,
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
Some("error"),
|
||||
None,
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
1,
|
||||
2,
|
||||
0
|
||||
) must throwA[AssertionError]
|
||||
DamageFeedbackMessage(
|
||||
3,
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
None,
|
||||
Some(5),
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
1,
|
||||
2,
|
||||
0
|
||||
) must throwA[AssertionError]
|
||||
DamageFeedbackMessage(
|
||||
3,
|
||||
true,
|
||||
None,
|
||||
Some("error"),
|
||||
Some(5),
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
1,
|
||||
2,
|
||||
0
|
||||
) must throwA[AssertionError]
|
||||
//unk2: all parameters
|
||||
DamageFeedbackMessage(
|
||||
3,
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
Some("error"),
|
||||
Some(5),
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
1,
|
||||
2,
|
||||
0
|
||||
) must throwA[AssertionError]
|
||||
//unk2: mismatched flag for strings
|
||||
DamageFeedbackMessage(
|
||||
3,
|
||||
true,
|
||||
None,
|
||||
None,
|
||||
Some(5),
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
1,
|
||||
2,
|
||||
0
|
||||
) must throwA[AssertionError]
|
||||
DamageFeedbackMessage(
|
||||
3,
|
||||
false,
|
||||
None,
|
||||
Some("error"),
|
||||
None,
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
1,
|
||||
2,
|
||||
0
|
||||
) must throwA[AssertionError]
|
||||
|
||||
//unk3: no parameters
|
||||
DamageFeedbackMessage(
|
||||
3,
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
None,
|
||||
None,
|
||||
true,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
1,
|
||||
2,
|
||||
0
|
||||
) must throwA[AssertionError]
|
||||
//unk3: two exclusive parameters
|
||||
DamageFeedbackMessage(
|
||||
3,
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
None,
|
||||
None,
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
Some("error"),
|
||||
None,
|
||||
None,
|
||||
1,
|
||||
2,
|
||||
0
|
||||
) must throwA[AssertionError]
|
||||
DamageFeedbackMessage(
|
||||
3,
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
None,
|
||||
None,
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
None,
|
||||
Some(5),
|
||||
None,
|
||||
1,
|
||||
2,
|
||||
0
|
||||
) must throwA[AssertionError]
|
||||
DamageFeedbackMessage(
|
||||
3,
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
None,
|
||||
None,
|
||||
true,
|
||||
None,
|
||||
Some("error"),
|
||||
Some(5),
|
||||
Some(1),
|
||||
1,
|
||||
2,
|
||||
0
|
||||
) must throwA[AssertionError]
|
||||
//unk3: all parameters
|
||||
DamageFeedbackMessage(
|
||||
3,
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
None,
|
||||
None,
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
Some("error"),
|
||||
Some(5),
|
||||
None,
|
||||
1,
|
||||
2,
|
||||
0
|
||||
) must throwA[AssertionError]
|
||||
//unk3: mismatched fields
|
||||
DamageFeedbackMessage(
|
||||
3,
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
None,
|
||||
None,
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
None,
|
||||
None,
|
||||
Some(5),
|
||||
1,
|
||||
2,
|
||||
0
|
||||
) must throwA[AssertionError]
|
||||
DamageFeedbackMessage(
|
||||
3,
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
None,
|
||||
None,
|
||||
true,
|
||||
None,
|
||||
Some("Error"),
|
||||
None,
|
||||
None,
|
||||
1,
|
||||
2,
|
||||
0
|
||||
) must throwA[AssertionError]
|
||||
//unk3: mismatched flag for strings
|
||||
DamageFeedbackMessage(
|
||||
3,
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
None,
|
||||
None,
|
||||
true,
|
||||
None,
|
||||
None,
|
||||
Some(5),
|
||||
None,
|
||||
1,
|
||||
2,
|
||||
0
|
||||
) must throwA[AssertionError]
|
||||
DamageFeedbackMessage(
|
||||
3,
|
||||
true,
|
||||
Some(PlanetSideGUID(2913)),
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
Some("error"),
|
||||
None,
|
||||
None,
|
||||
1,
|
||||
2,
|
||||
0
|
||||
) must throwA[AssertionError]
|
||||
}
|
||||
}
|
||||
31
src/test/scala/game/DamageMessageTest.scala
Normal file
31
src/test/scala/game/DamageMessageTest.scala
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) 2019 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class DamageMessageTest extends Specification {
|
||||
val string = hex"0b610b02610b00"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case DamageMessage(guid1, unk1, guid2, unk2) =>
|
||||
guid1 mustEqual PlanetSideGUID(2913)
|
||||
unk1 mustEqual 2
|
||||
guid2 mustEqual PlanetSideGUID(2913)
|
||||
unk2 mustEqual false
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = DamageMessage(PlanetSideGUID(2913), 2, PlanetSideGUID(2913), false)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
31
src/test/scala/game/DamageWithPositionMessageTest.scala
Normal file
31
src/test/scala/game/DamageWithPositionMessageTest.scala
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import net.psforever.types.Vector3
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class DamageWithPositionMessageTest extends Specification {
|
||||
val string = hex"A6 11 6C2D7 65535 CA16"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case DamageWithPositionMessage(unk, pos) =>
|
||||
unk mustEqual 17
|
||||
pos.x mustEqual 3674.8438f
|
||||
pos.y mustEqual 2726.789f
|
||||
pos.z mustEqual 91.15625f
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = DamageWithPositionMessage(17, Vector3(3674.8438f, 2726.789f, 91.15625f))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
28
src/test/scala/game/DataChallengeMessageRespTest.scala
Normal file
28
src/test/scala/game/DataChallengeMessageRespTest.scala
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) 2020 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class DataChallengeMessageRespTest extends Specification {
|
||||
val string = hex"948673616d706c6501000000"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case DataChallengeMessageResp(attribute, value) =>
|
||||
attribute mustEqual "sample"
|
||||
value mustEqual 1L
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = DataChallengeMessageResp("sample", 1L)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
28
src/test/scala/game/DataChallengeMessageTest.scala
Normal file
28
src/test/scala/game/DataChallengeMessageTest.scala
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) 2020 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class DataChallengeMessageTest extends Specification {
|
||||
val string = hex"938673616d706c6501000000"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case DataChallengeMessage(attribute, value) =>
|
||||
attribute mustEqual "sample"
|
||||
value mustEqual 1L
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = DataChallengeMessage("sample", 1L)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
31
src/test/scala/game/DelayedPathMountMsgTest.scala
Normal file
31
src/test/scala/game/DelayedPathMountMsgTest.scala
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class DelayedPathMountMsgTest extends Specification {
|
||||
val string = hex"5a f50583044680"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case DelayedPathMountMsg(player_guid, vehicle_guid, u3, u4) =>
|
||||
player_guid mustEqual PlanetSideGUID(1525)
|
||||
vehicle_guid mustEqual PlanetSideGUID(1155)
|
||||
u3 mustEqual 70
|
||||
u4 mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = DelayedPathMountMsg(PlanetSideGUID(1525), PlanetSideGUID(1155), 70, true)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
52
src/test/scala/game/DensityLevelUpdateMessageTest.scala
Normal file
52
src/test/scala/game/DensityLevelUpdateMessageTest.scala
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class DensityLevelUpdateMessageTest extends Specification {
|
||||
val string = hex"cd 0100 1f4e 000000"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case DensityLevelUpdateMessage(zone_id, building_id, unk) =>
|
||||
zone_id mustEqual 1
|
||||
building_id mustEqual 19999
|
||||
unk.length mustEqual 8
|
||||
unk.head mustEqual 0
|
||||
unk(1) mustEqual 0
|
||||
unk(2) mustEqual 0
|
||||
unk(3) mustEqual 0
|
||||
unk(4) mustEqual 0
|
||||
unk(5) mustEqual 0
|
||||
unk(6) mustEqual 0
|
||||
unk(7) mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = DensityLevelUpdateMessage(1, 19999, List(0, 0, 0, 0, 0, 0, 0, 0))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
|
||||
"encode (failure; wrong number of list entries)" in {
|
||||
val msg = DensityLevelUpdateMessage(1, 19999, List(0))
|
||||
PacketCoding.EncodePacket(msg).isSuccessful mustEqual false
|
||||
}
|
||||
|
||||
"encode (failure; list number too big)" in {
|
||||
val msg = DensityLevelUpdateMessage(1, 19999, List(0, 0, 0, 0, 0, 0, 0, 8))
|
||||
PacketCoding.EncodePacket(msg).isSuccessful mustEqual false
|
||||
}
|
||||
|
||||
"encode (failure; list number too small)" in {
|
||||
val msg = DensityLevelUpdateMessage(1, 19999, List(0, 0, 0, 0, 0, -1, 0, 0))
|
||||
PacketCoding.EncodePacket(msg).isSuccessful mustEqual false
|
||||
}
|
||||
}
|
||||
38
src/test/scala/game/DeployObjectMessageTest.scala
Normal file
38
src/test/scala/game/DeployObjectMessageTest.scala
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{PlanetSideGUID, Vector3}
|
||||
import scodec.bits._
|
||||
|
||||
class DeployObjectMessageTest extends Specification {
|
||||
val string = hex"5d 740b e8030000 a644b 6e3c6 7e18 00 00 3f 01000000"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case DeployObjectMessage(guid, unk1, pos, orient, unk2) =>
|
||||
guid mustEqual PlanetSideGUID(2932)
|
||||
unk1 mustEqual 1000L
|
||||
pos mustEqual Vector3(5769.297f, 3192.8594f, 97.96875f)
|
||||
orient mustEqual Vector3.z(272.8125f)
|
||||
unk2 mustEqual 1L
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = DeployObjectMessage(
|
||||
PlanetSideGUID(2932),
|
||||
1000L,
|
||||
Vector3(5769.297f, 3192.8594f, 97.96875f),
|
||||
Vector3.z(272.8125f),
|
||||
1L
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
42
src/test/scala/game/DeployRequestMessageTest.scala
Normal file
42
src/test/scala/game/DeployRequestMessageTest.scala
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{DriveState, PlanetSideGUID, Vector3}
|
||||
import scodec.bits._
|
||||
|
||||
class DeployRequestMessageTest extends Specification {
|
||||
val string = hex"4b 4b00 7c01 40 0cf73b52aa6a9300"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case DeployRequestMessage(player_guid, vehicle_guid, deploy_state, unk2, unk3, pos) =>
|
||||
player_guid mustEqual PlanetSideGUID(75)
|
||||
vehicle_guid mustEqual PlanetSideGUID(380)
|
||||
deploy_state mustEqual DriveState.Deploying
|
||||
unk2 mustEqual 0
|
||||
unk3 mustEqual false
|
||||
pos.x mustEqual 4060.1953f
|
||||
pos.y mustEqual 2218.8281f
|
||||
pos.z mustEqual 155.32812f
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = DeployRequestMessage(
|
||||
PlanetSideGUID(75),
|
||||
PlanetSideGUID(380),
|
||||
DriveState.Deploying,
|
||||
0,
|
||||
false,
|
||||
Vector3(4060.1953f, 2218.8281f, 155.32812f)
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
44
src/test/scala/game/DeployableObjectsInfoMessageTest.scala
Normal file
44
src/test/scala/game/DeployableObjectsInfoMessageTest.scala
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game.{DeployableIcon, DeployableInfo, DeployableObjectsInfoMessage, DeploymentAction}
|
||||
import net.psforever.types.{PlanetSideGUID, Vector3}
|
||||
import scodec.bits._
|
||||
|
||||
class DeployableObjectsInfoMessageTest extends Specification {
|
||||
val string = hex"76 00 80 00 00 31 85 41 CF D3 7E B3 34 00 E6 30 48" //this was a TRAP @ Ogma, Forseral
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case DeployableObjectsInfoMessage(action, list) =>
|
||||
action mustEqual DeploymentAction.Dismiss
|
||||
list.size mustEqual 1
|
||||
//0
|
||||
list.head.object_guid mustEqual PlanetSideGUID(2659)
|
||||
list.head.icon mustEqual DeployableIcon.TRAP
|
||||
list.head.pos.x mustEqual 3572.4453f
|
||||
list.head.pos.y mustEqual 3277.9766f
|
||||
list.head.pos.z mustEqual 114.0f
|
||||
list.head.player_guid mustEqual PlanetSideGUID(2502)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = DeployableObjectsInfoMessage(
|
||||
DeploymentAction.Dismiss,
|
||||
DeployableInfo(
|
||||
PlanetSideGUID(2659),
|
||||
DeployableIcon.TRAP,
|
||||
Vector3(3572.4453f, 3277.9766f, 114.0f),
|
||||
PlanetSideGUID(2502)
|
||||
)
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
59
src/test/scala/game/DestroyDisplayMessageTest.scala
Normal file
59
src/test/scala/game/DestroyDisplayMessageTest.scala
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
import scodec.bits._
|
||||
|
||||
class DestroyDisplayMessageTest extends Specification {
|
||||
val string =
|
||||
hex"81 87 41006E00670065006C006C006F00 35BCD801 8 F201 9207 0A 0 48004D00460049004300 B18ED901 00" // Angello-VS (???) HMFIC-TR
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case DestroyDisplayMessage(
|
||||
killer,
|
||||
killer_charId,
|
||||
killer_empire,
|
||||
killer_inVehicle,
|
||||
unk,
|
||||
method,
|
||||
victim,
|
||||
victim_charId,
|
||||
victim_empire,
|
||||
victim_inVehicle
|
||||
) =>
|
||||
killer mustEqual "Angello"
|
||||
killer_charId mustEqual 30981173
|
||||
killer_empire mustEqual PlanetSideEmpire.VS
|
||||
killer_inVehicle mustEqual false
|
||||
unk mustEqual 121
|
||||
method mustEqual 969
|
||||
victim mustEqual "HMFIC"
|
||||
victim_charId mustEqual 31035057
|
||||
victim_empire mustEqual PlanetSideEmpire.TR
|
||||
victim_inVehicle mustEqual false
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = DestroyDisplayMessage(
|
||||
"Angello",
|
||||
30981173,
|
||||
PlanetSideEmpire.VS,
|
||||
false,
|
||||
121,
|
||||
969,
|
||||
"HMFIC",
|
||||
31035057,
|
||||
PlanetSideEmpire.TR,
|
||||
false
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
38
src/test/scala/game/DestroyMessageTest.scala
Normal file
38
src/test/scala/game/DestroyMessageTest.scala
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{PlanetSideGUID, Vector3}
|
||||
import scodec.bits._
|
||||
|
||||
class DestroyMessageTest extends Specification {
|
||||
val string = hex"0C 74 09 74 09 00 00 06 35 3C FF D7 26 08"
|
||||
|
||||
"DestroyMessage" should {
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case DestroyMessage(unk1, unk2, unk3, pos) =>
|
||||
unk1 mustEqual PlanetSideGUID(2420)
|
||||
unk2 mustEqual PlanetSideGUID(2420)
|
||||
unk3 mustEqual PlanetSideGUID(0)
|
||||
pos mustEqual Vector3(1642.0469f, 4091.6172f, 32.59375f)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = DestroyMessage(
|
||||
PlanetSideGUID(2420),
|
||||
PlanetSideGUID(2420),
|
||||
PlanetSideGUID(0),
|
||||
Vector3(1642.0469f, 4091.6172f, 32.59375f)
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
}
|
||||
33
src/test/scala/game/DisconnectMessageTest.scala
Normal file
33
src/test/scala/game/DisconnectMessageTest.scala
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class DisconnectMessageTest extends Specification {
|
||||
val string = hex"B7 85 46 69 72 73 74 86 53 65 63 6F 6E 64 8E 46 69 72 73 74 20 26 20 73 65 63 6F 6E 64"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case DisconnectMessage(unk1, unk2, unk3) =>
|
||||
unk1 mustEqual "First"
|
||||
unk2 mustEqual "Second"
|
||||
unk3 mustEqual "First & second"
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = DisconnectMessage("First", "Second", "First & second")
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
|
||||
"comparison" in {
|
||||
DisconnectMessage("First") mustEqual DisconnectMessage("First", "", "")
|
||||
}
|
||||
}
|
||||
29
src/test/scala/game/DismountBuildingMsgTest.scala
Normal file
29
src/test/scala/game/DismountBuildingMsgTest.scala
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class DismountBuildingMsgTest extends Specification {
|
||||
val string = hex"7C 4B00 2E00"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case DismountBuildingMsg(player_guid, building_guid) =>
|
||||
player_guid mustEqual PlanetSideGUID(75)
|
||||
building_guid mustEqual PlanetSideGUID(46)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = DismountBuildingMsg(PlanetSideGUID(75), PlanetSideGUID(46))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
30
src/test/scala/game/DismountVehicleMsgTest.scala
Normal file
30
src/test/scala/game/DismountVehicleMsgTest.scala
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
import net.psforever.types.{BailType, PlanetSideGUID}
|
||||
|
||||
class DismountVehicleMsgTest extends Specification {
|
||||
val string = hex"0F C609 00"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case DismountVehicleMsg(player_guid, bailType, wasKickedByDriver) =>
|
||||
player_guid mustEqual PlanetSideGUID(2502)
|
||||
bailType mustEqual BailType.Normal
|
||||
wasKickedByDriver mustEqual false
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = DismountVehicleMsg(PlanetSideGUID(2502), BailType.Normal, false)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
30
src/test/scala/game/DisplayedAwardMessageTest.scala
Normal file
30
src/test/scala/game/DisplayedAwardMessageTest.scala
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import net.psforever.types.{MeritCommendation, PlanetSideGUID}
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class DisplayedAwardMessageTest extends Specification {
|
||||
val string = hex"D1 9F06 A6010000 3 0"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case DisplayedAwardMessage(player_guid, ribbon, bar) =>
|
||||
player_guid mustEqual PlanetSideGUID(1695)
|
||||
ribbon mustEqual MeritCommendation.TwoYearVS
|
||||
bar mustEqual RibbonBarsSlot.TermOfService
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = DisplayedAwardMessage(PlanetSideGUID(1695), MeritCommendation.TwoYearVS, RibbonBarsSlot.TermOfService)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
28
src/test/scala/game/DropItemMessageTest.scala
Normal file
28
src/test/scala/game/DropItemMessageTest.scala
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class DropItemMessageTest extends Specification {
|
||||
val string = hex"37 4C00"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case DropItemMessage(item_guid) =>
|
||||
item_guid mustEqual PlanetSideGUID(76)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = DropItemMessage(PlanetSideGUID(76))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
43
src/test/scala/game/DroppodFreefallingMessageTest.scala
Normal file
43
src/test/scala/game/DroppodFreefallingMessageTest.scala
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{PlanetSideGUID, Vector3}
|
||||
import scodec.bits._
|
||||
|
||||
class DroppodFreefallingMessageTest extends Specification {
|
||||
val string =
|
||||
hex"68 220e 00e0b245 00c06145 00a08744 00000000 00000000 ffff79c4 0740b245 22c66145 00608144 00 67 3f 00 00 3f"
|
||||
|
||||
"DroppodFreefallingMessage" should {
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case DroppodFreefallingMessage(guid, pos, vel, pos2, orientation1, orientation2) =>
|
||||
guid mustEqual PlanetSideGUID(3618)
|
||||
pos mustEqual Vector3(5724, 3612, 1085)
|
||||
vel mustEqual Vector3(0, 0, -999.99994f)
|
||||
pos2 mustEqual Vector3(5704.0034f, 3612.3833f, 1035.0f)
|
||||
orientation1 mustEqual Vector3(0, 70.3125f, 272.8125f)
|
||||
orientation2 mustEqual Vector3(0, 0, 272.8125f)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = DroppodFreefallingMessage(
|
||||
PlanetSideGUID(3618),
|
||||
Vector3(5724, 3612, 1085),
|
||||
Vector3(0, 0, -999.99994f),
|
||||
Vector3(5704.0034f, 3612.3833f, 1035.0f),
|
||||
Vector3(0, 70.3125f, 272.8125f),
|
||||
Vector3(0, 0, 272.8125f)
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
}
|
||||
29
src/test/scala/game/EmoteMsgTest.scala
Normal file
29
src/test/scala/game/EmoteMsgTest.scala
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{EmoteType, PlanetSideGUID}
|
||||
import scodec.bits._
|
||||
|
||||
class EmoteMsgTest extends Specification {
|
||||
val string = hex"25 4B00 15"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case EmoteMsg(avatar_guid, emote) =>
|
||||
avatar_guid mustEqual PlanetSideGUID(75)
|
||||
emote mustEqual EmoteType.Thumbsdown
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = EmoteMsg(PlanetSideGUID(75), EmoteType.Thumbsdown)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
28
src/test/scala/game/ExperienceAddedMessageTest.scala
Normal file
28
src/test/scala/game/ExperienceAddedMessageTest.scala
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class ExperienceAddedMessageTest extends Specification {
|
||||
val string = hex"B8 04 03"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case ExperienceAddedMessage(exp, unk) =>
|
||||
exp mustEqual 260 //0x104
|
||||
unk mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = ExperienceAddedMessage(260)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class FacilityBenefitShieldChargeRequestMessageTest extends Specification {
|
||||
val string = hex"C2 4C00"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case FacilityBenefitShieldChargeRequestMessage(guid) =>
|
||||
guid mustEqual PlanetSideGUID(76)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = FacilityBenefitShieldChargeRequestMessage(PlanetSideGUID(76))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
54
src/test/scala/game/FavoritesMessageTest.scala
Normal file
54
src/test/scala/game/FavoritesMessageTest.scala
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{LoadoutType, PlanetSideGUID}
|
||||
import scodec.bits._
|
||||
|
||||
class FavoritesMessageTest extends Specification {
|
||||
val stringVehicles = hex"60 5C 84 02 20 5300 6B00 7900 6700 7500 6100 7200 6400"
|
||||
val stringInfantry = hex"60 2C 03 82 34 4100 6700 6900 6C00 6500 2000 2800 6200 6100 7300 6900 6300 2900 20"
|
||||
|
||||
"decode (for infantry)" in {
|
||||
PacketCoding.DecodePacket(stringInfantry).require match {
|
||||
case FavoritesMessage(list, player_guid, line, label, armor) =>
|
||||
list mustEqual LoadoutType.Infantry
|
||||
player_guid mustEqual PlanetSideGUID(3760)
|
||||
line mustEqual 0
|
||||
label mustEqual "Agile (basic)"
|
||||
armor.isDefined mustEqual true
|
||||
armor.get mustEqual 1
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (for infantry)" in {
|
||||
val msg = FavoritesMessage(LoadoutType.Infantry, PlanetSideGUID(3760), 0, "Agile (basic)", 1)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual stringInfantry
|
||||
}
|
||||
|
||||
"decode (for vehicles)" in {
|
||||
PacketCoding.DecodePacket(stringVehicles).require match {
|
||||
case FavoritesMessage(list, player_guid, line, label, armor) =>
|
||||
list mustEqual LoadoutType.Vehicle
|
||||
player_guid mustEqual PlanetSideGUID(4210)
|
||||
line mustEqual 0
|
||||
label mustEqual "Skyguard"
|
||||
armor.isDefined mustEqual false
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (for vehicles)" in {
|
||||
val msg = FavoritesMessage(LoadoutType.Vehicle, PlanetSideGUID(4210), 0, "Skyguard")
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual stringVehicles
|
||||
}
|
||||
}
|
||||
33
src/test/scala/game/FavoritesRequestTest.scala
Normal file
33
src/test/scala/game/FavoritesRequestTest.scala
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{LoadoutType, PlanetSideGUID}
|
||||
import scodec.bits._
|
||||
|
||||
class FavoritesRequestTest extends Specification {
|
||||
val stringInfantry = hex"5E 4B00 1187 4500 7800 6100 6D00 7000 6C00 6500"
|
||||
|
||||
"decode (for infantry)" in {
|
||||
PacketCoding.DecodePacket(stringInfantry).require match {
|
||||
case FavoritesRequest(player_guid, list, action, line, label) =>
|
||||
player_guid mustEqual PlanetSideGUID(75)
|
||||
list mustEqual LoadoutType.Infantry
|
||||
action mustEqual FavoritesAction.Save
|
||||
line mustEqual 1
|
||||
label.isDefined mustEqual true
|
||||
label.get mustEqual "Example"
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (for infantry)" in {
|
||||
val msg = FavoritesRequest(PlanetSideGUID(75), LoadoutType.Infantry, FavoritesAction.Save, 1, Some("Example"))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual stringInfantry
|
||||
}
|
||||
}
|
||||
63
src/test/scala/game/FireHintMessageTest.scala
Normal file
63
src/test/scala/game/FireHintMessageTest.scala
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{PlanetSideGUID, Vector3}
|
||||
import scodec.bits._
|
||||
|
||||
class FireHintMessageTest extends Specification {
|
||||
val string = hex"a1 0117 23cd63f1d7480d 000077ff9d1d00"
|
||||
val string2 = hex"a1 080e 65af5705074411 0000cffee0fc7b08899f5580"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case FireHintMessage(weapon_guid, pos, u1, u2, u3, u4, u5) =>
|
||||
weapon_guid mustEqual PlanetSideGUID(5889)
|
||||
pos mustEqual Vector3(3482.2734f, 3642.4922f, 53.125f)
|
||||
u1 mustEqual 0
|
||||
u2 mustEqual 65399
|
||||
u3 mustEqual 7581
|
||||
u4 mustEqual 0
|
||||
u5 mustEqual None
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
"decode string2" in {
|
||||
PacketCoding.DecodePacket(string2).require match {
|
||||
case FireHintMessage(weapon_guid, pos, u1, u2, u3, u4, u5) =>
|
||||
weapon_guid mustEqual PlanetSideGUID(3592)
|
||||
pos mustEqual Vector3(2910.789f, 3744.875f, 69.0625f)
|
||||
u1 mustEqual 0
|
||||
u2 mustEqual 65231
|
||||
u3 mustEqual 64736
|
||||
u4 mustEqual 3
|
||||
u5 mustEqual Some(Vector3(21.5f, -6.8125f, 2.65625f))
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = FireHintMessage(PlanetSideGUID(5889), Vector3(3482.2734f, 3642.4922f, 53.125f), 0, 65399, 7581, 0)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
"encode string2" in {
|
||||
val msg = FireHintMessage(
|
||||
PlanetSideGUID(3592),
|
||||
Vector3(2910.789f, 3744.875f, 69.0625f),
|
||||
0,
|
||||
65231,
|
||||
64736,
|
||||
3,
|
||||
Some(Vector3(21.5f, -6.8125f, 2.65625f))
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string2
|
||||
}
|
||||
}
|
||||
29
src/test/scala/game/FriendsRequestTest.scala
Normal file
29
src/test/scala/game/FriendsRequestTest.scala
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class FriendsRequestTest extends Specification {
|
||||
val string = hex"72 3 0A0 46004A0048004E004300"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case FriendsRequest(action, friend) =>
|
||||
action mustEqual 1
|
||||
friend.length mustEqual 5
|
||||
friend mustEqual "FJHNC"
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = FriendsRequest(1, "FJHNC")
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
104
src/test/scala/game/FriendsResponseTest.scala
Normal file
104
src/test/scala/game/FriendsResponseTest.scala
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class FriendsResponseTest extends Specification {
|
||||
val stringOneFriend = hex"73 61 8C 60 4B007500720074004800650063007400690063002D004700 00"
|
||||
val stringManyFriends =
|
||||
hex"73 01 AC 48 4100 6E00 6700 6500 6C00 6C00 6F00 2D00 5700 47 00 7400 6800 6500 7000 6800 6100 7400 7400 7000 6800 7200 6F00 6700 6700 46 80 4B00 6900 6D00 7000 6F00 7300 7300 6900 6200 6C00 6500 3100 3200 45 00 5A00 6500 6100 7200 7400 6800 6C00 6900 6E00 6700 46 00 4B00 7500 7200 7400 4800 6500 6300 7400 6900 6300 2D00 4700 00"
|
||||
val stringShort = hex"73 81 80"
|
||||
|
||||
"decode (one friend)" in {
|
||||
PacketCoding.DecodePacket(stringOneFriend).require match {
|
||||
case FriendsResponse(action, unk2, unk3, unk4, list) =>
|
||||
action mustEqual FriendAction.UpdateFriend
|
||||
unk2 mustEqual 0
|
||||
unk3 mustEqual true
|
||||
unk4 mustEqual true
|
||||
list.size mustEqual 1
|
||||
list.head.name mustEqual "KurtHectic-G"
|
||||
list.head.online mustEqual false
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (multiple friends)" in {
|
||||
PacketCoding.DecodePacket(stringManyFriends).require match {
|
||||
case FriendsResponse(action, unk2, unk3, unk4, list) =>
|
||||
action mustEqual FriendAction.InitializeFriendList
|
||||
unk2 mustEqual 0
|
||||
unk3 mustEqual true
|
||||
unk4 mustEqual true
|
||||
list.size mustEqual 5
|
||||
list.head.name mustEqual "Angello-W"
|
||||
list.head.online mustEqual false
|
||||
list(1).name mustEqual "thephattphrogg"
|
||||
list(1).online mustEqual false
|
||||
list(2).name mustEqual "Kimpossible12"
|
||||
list(2).online mustEqual false
|
||||
list(3).name mustEqual "Zearthling"
|
||||
list(3).online mustEqual false
|
||||
list(4).name mustEqual "KurtHectic-G"
|
||||
list(4).online mustEqual false
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (short)" in {
|
||||
PacketCoding.DecodePacket(stringShort).require match {
|
||||
case FriendsResponse(action, unk2, unk3, unk4, list) =>
|
||||
action mustEqual FriendAction.InitializeIgnoreList
|
||||
unk2 mustEqual 0
|
||||
unk3 mustEqual true
|
||||
unk4 mustEqual true
|
||||
list.size mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (one friend)" in {
|
||||
val msg = FriendsResponse(
|
||||
FriendAction.UpdateFriend,
|
||||
0,
|
||||
true,
|
||||
true,
|
||||
Friend("KurtHectic-G", false) ::
|
||||
Nil
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual stringOneFriend
|
||||
}
|
||||
|
||||
"encode (multiple friends)" in {
|
||||
val msg = FriendsResponse(
|
||||
FriendAction.InitializeFriendList,
|
||||
0,
|
||||
true,
|
||||
true,
|
||||
Friend("Angello-W", false) ::
|
||||
Friend("thephattphrogg", false) ::
|
||||
Friend("Kimpossible12", false) ::
|
||||
Friend("Zearthling", false) ::
|
||||
Friend("KurtHectic-G", false) ::
|
||||
Nil
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual stringManyFriends
|
||||
}
|
||||
|
||||
"encode (short)" in {
|
||||
val msg = FriendsResponse(FriendAction.InitializeIgnoreList, 0, true, true)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual stringShort
|
||||
}
|
||||
}
|
||||
27
src/test/scala/game/GenericActionMessageTest.scala
Normal file
27
src/test/scala/game/GenericActionMessageTest.scala
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class GenericActionMessageTest extends Specification {
|
||||
val string = hex"A7 94"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case GenericActionMessage(action) =>
|
||||
action mustEqual 37
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = GenericActionMessage(37)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
59
src/test/scala/game/GenericCollisionMsgTest.scala
Normal file
59
src/test/scala/game/GenericCollisionMsgTest.scala
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{PlanetSideGUID, Vector3}
|
||||
import scodec.bits._
|
||||
|
||||
class GenericCollisionMsgTest extends Specification {
|
||||
//TODO find a better test later
|
||||
val string =
|
||||
hex"3C 92C00000190000001B2A8010932CEF505C70946F00000000000000000000000017725EBC6D6A058000000000000000000000000000003F8FF45140"
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case GenericCollisionMsg(unk1, p, t, php, thp, pv, tv, ppos, tpos, unk2, unk3, unk4) =>
|
||||
unk1 mustEqual 2
|
||||
p mustEqual PlanetSideGUID(75)
|
||||
t mustEqual PlanetSideGUID(0)
|
||||
php mustEqual 100
|
||||
thp mustEqual 0
|
||||
pv.x mustEqual 32.166428f
|
||||
pv.y mustEqual 23.712547f
|
||||
pv.z mustEqual -0.012802706f
|
||||
tv.x mustEqual 0.0f
|
||||
tv.z mustEqual 0.0f
|
||||
tv.x mustEqual 0.0f
|
||||
ppos.x mustEqual 3986.7266f
|
||||
ppos.y mustEqual 2615.3672f
|
||||
ppos.z mustEqual 90.625f
|
||||
tpos.x mustEqual 0.0f
|
||||
tpos.y mustEqual 0.0f
|
||||
tpos.z mustEqual 0.0f
|
||||
unk2 mustEqual 0L
|
||||
unk3 mustEqual 0L
|
||||
unk4 mustEqual 1171341310L
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
"encode" in {
|
||||
val msg = GenericCollisionMsg(
|
||||
2,
|
||||
PlanetSideGUID(75),
|
||||
PlanetSideGUID(0),
|
||||
100,
|
||||
0,
|
||||
Vector3(32.166428f, 23.712547f, -0.012802706f),
|
||||
Vector3(0.0f, 0.0f, 0.0f),
|
||||
Vector3(3986.7266f, 2615.3672f, 90.625f),
|
||||
Vector3(0.0f, 0.0f, 0.0f),
|
||||
0L,
|
||||
0L,
|
||||
1171341310L
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
29
src/test/scala/game/GenericObjectActionMessageTest.scala
Normal file
29
src/test/scala/game/GenericObjectActionMessageTest.scala
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class GenericObjectActionMessageTest extends Specification {
|
||||
val string = hex"56 B501 24"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case GenericObjectActionMessage(object_guid, action) =>
|
||||
object_guid mustEqual PlanetSideGUID(437)
|
||||
action mustEqual 9
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = GenericObjectActionMessage(PlanetSideGUID(437), 9)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
29
src/test/scala/game/GenericObjectStateMsgTest.scala
Normal file
29
src/test/scala/game/GenericObjectStateMsgTest.scala
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class GenericObjectStateMsgTest extends Specification {
|
||||
val string = hex"1D 6401 10000000"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case GenericObjectStateMsg(object_guid, state) =>
|
||||
object_guid mustEqual PlanetSideGUID(356)
|
||||
state mustEqual 16
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = GenericObjectStateMsg(PlanetSideGUID(356), 16)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
34
src/test/scala/game/HackMessageTest.scala
Normal file
34
src/test/scala/game/HackMessageTest.scala
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class HackMessageTest extends Specification {
|
||||
// Record 62 in PSCap-hack-door-tower.gcap
|
||||
val string = hex"54 000105c3800000202fc04200000000"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case HackMessage(unk1, target_guid, player_guid, progress, unk5, hack_state, unk7) =>
|
||||
unk1 mustEqual 0
|
||||
target_guid mustEqual PlanetSideGUID(1024)
|
||||
player_guid mustEqual PlanetSideGUID(3607)
|
||||
progress mustEqual 0
|
||||
unk5 mustEqual 3212836864L
|
||||
hack_state mustEqual HackState.Start
|
||||
unk7 mustEqual 8L
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = HackMessage(0, PlanetSideGUID(1024), PlanetSideGUID(3607), 0, 3212836864L, HackState.Start, 8L)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
29
src/test/scala/game/HitHintTest.scala
Normal file
29
src/test/scala/game/HitHintTest.scala
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class HitHintTest extends Specification {
|
||||
val string = hex"0A 460B 0100"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case HitHint(source, player) =>
|
||||
source mustEqual PlanetSideGUID(2886)
|
||||
player mustEqual PlanetSideGUID(1)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = HitHint(PlanetSideGUID(2886), PlanetSideGUID(1))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
76
src/test/scala/game/HitMessageTest.scala
Normal file
76
src/test/scala/game/HitMessageTest.scala
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{PlanetSideGUID, Vector3}
|
||||
import scodec.bits._
|
||||
|
||||
class HitMessageTest extends Specification {
|
||||
val string_hitgeneric = hex"09 09E9A70200"
|
||||
val string_hitobj = hex"09 99292705F4B1FB9514585F08BDD3D454CC5EE80300"
|
||||
|
||||
"decode (generic)" in {
|
||||
PacketCoding.DecodePacket(string_hitgeneric).require match {
|
||||
case HitMessage(seq_time, projectile_guid, unk1, hit_info, unk2, unk3, unk4) =>
|
||||
seq_time mustEqual 777
|
||||
projectile_guid mustEqual PlanetSideGUID(40102)
|
||||
unk1 mustEqual 0
|
||||
hit_info mustEqual None
|
||||
unk2 mustEqual true
|
||||
unk3 mustEqual false
|
||||
unk4 mustEqual None
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (object)" in {
|
||||
PacketCoding.DecodePacket(string_hitobj).require match {
|
||||
case HitMessage(seq_time, projectile_guid, unk1, hit_info, unk2, unk3, unk4) =>
|
||||
seq_time mustEqual 153
|
||||
projectile_guid mustEqual PlanetSideGUID(40100)
|
||||
unk1 mustEqual 0
|
||||
hit_info mustEqual Some(
|
||||
HitInfo(
|
||||
Vector3(3672.9766f, 2729.8594f, 92.34375f),
|
||||
Vector3(3679.5156f, 2722.6172f, 92.796875f),
|
||||
Some(PlanetSideGUID(372))
|
||||
)
|
||||
)
|
||||
unk2 mustEqual true
|
||||
unk3 mustEqual false
|
||||
unk4 mustEqual None
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (generic)" in {
|
||||
val msg_hitgeneric = HitMessage(777, PlanetSideGUID(40102), 0, None, true, false, None)
|
||||
val pkt_hitgeneric = PacketCoding.EncodePacket(msg_hitgeneric).require.toByteVector
|
||||
pkt_hitgeneric mustEqual string_hitgeneric
|
||||
}
|
||||
|
||||
"encode (object)" in {
|
||||
val msg_hitobj = HitMessage(
|
||||
153,
|
||||
PlanetSideGUID(40100),
|
||||
0,
|
||||
Some(
|
||||
HitInfo(
|
||||
Vector3(3672.9766f, 2729.8594f, 92.34375f),
|
||||
Vector3(3679.5156f, 2722.6172f, 92.796875f),
|
||||
Some(PlanetSideGUID(372))
|
||||
)
|
||||
),
|
||||
true,
|
||||
false,
|
||||
None
|
||||
)
|
||||
val pkt_hitobj = PacketCoding.EncodePacket(msg_hitobj).require.toByteVector
|
||||
|
||||
pkt_hitobj mustEqual string_hitobj
|
||||
}
|
||||
}
|
||||
97
src/test/scala/game/HotSpotUpdateMessageTest.scala
Normal file
97
src/test/scala/game/HotSpotUpdateMessageTest.scala
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class HotSpotUpdateMessageTest extends Specification {
|
||||
val stringClear = hex"9F 0500 1 000"
|
||||
val stringOne = hex"9F 0500 1 010 002E9 00145 80000 0"
|
||||
val stringTwo = hex"9F 0500 5 020 00D07 008CA 80000 00BEA 004C4 80000"
|
||||
val stringThree = hex"9F 0A00 4 030 00FC8 00F0A 80000 002E9 00BEA 80000 00FC8 00BEA 80000 0"
|
||||
|
||||
"decode (clear)" in {
|
||||
PacketCoding.DecodePacket(stringClear).require match {
|
||||
case HotSpotUpdateMessage(continent_id, unk, spots) =>
|
||||
continent_id mustEqual 5
|
||||
unk mustEqual 1
|
||||
spots.size mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (one)" in {
|
||||
PacketCoding.DecodePacket(stringOne).require match {
|
||||
case HotSpotUpdateMessage(continent_id, unk, spots) =>
|
||||
continent_id mustEqual 5
|
||||
unk mustEqual 1
|
||||
spots.size mustEqual 1
|
||||
spots.head mustEqual HotSpotInfo(4700.0f, 2600.0f, 64.0f)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (two)" in {
|
||||
PacketCoding.DecodePacket(stringTwo).require match {
|
||||
case HotSpotUpdateMessage(continent_id, unk, spots) =>
|
||||
continent_id mustEqual 5
|
||||
unk mustEqual 5
|
||||
spots.size mustEqual 2
|
||||
spots.head mustEqual HotSpotInfo(4000.0f, 5400.0f, 64.0f)
|
||||
spots(1) mustEqual HotSpotInfo(5500.0f, 2200.0f, 64.0f)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (three)" in {
|
||||
PacketCoding.DecodePacket(stringThree).require match {
|
||||
case HotSpotUpdateMessage(continent_id, unk, spots) =>
|
||||
continent_id mustEqual 10
|
||||
unk mustEqual 4
|
||||
spots.size mustEqual 3
|
||||
spots.head mustEqual HotSpotInfo(4600.0f, 5600.0f, 64.0f)
|
||||
spots(1) mustEqual HotSpotInfo(4700.0f, 5500.0f, 64.0f)
|
||||
spots(2) mustEqual HotSpotInfo(4600.0f, 5500.0f, 64.0f)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (clear)" in {
|
||||
val msg = HotSpotUpdateMessage(5, 1, Nil)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual stringClear
|
||||
}
|
||||
|
||||
"encode (one)" in {
|
||||
val msg = HotSpotUpdateMessage(5, 1, List(HotSpotInfo(4700.0f, 2600.0f, 64.0f)))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual stringOne
|
||||
}
|
||||
|
||||
"encode (two)" in {
|
||||
val msg =
|
||||
HotSpotUpdateMessage(5, 5, List(HotSpotInfo(4000.0f, 5400.0f, 64.0f), HotSpotInfo(5500.0f, 2200.0f, 64.0f)))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual stringTwo
|
||||
}
|
||||
|
||||
"encode (three)" in {
|
||||
val msg = HotSpotUpdateMessage(
|
||||
10,
|
||||
4,
|
||||
List(
|
||||
HotSpotInfo(4600.0f, 5600.0f, 64.0f),
|
||||
HotSpotInfo(4700.0f, 5500.0f, 64.0f),
|
||||
HotSpotInfo(4600.0f, 5500.0f, 64.0f)
|
||||
)
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual stringThree
|
||||
}
|
||||
}
|
||||
31
src/test/scala/game/InventoryStateMessageTest.scala
Normal file
31
src/test/scala/game/InventoryStateMessageTest.scala
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class InventoryStateMessageTest extends Specification {
|
||||
val string = hex"38 5C0B 00 3C02 B20000000 0"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case InventoryStateMessage(object_guid, unk, inv_guid, value) =>
|
||||
object_guid mustEqual PlanetSideGUID(2908)
|
||||
unk mustEqual 0
|
||||
inv_guid mustEqual PlanetSideGUID(2800)
|
||||
value mustEqual 200
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = InventoryStateMessage(PlanetSideGUID(2908), 0, PlanetSideGUID(2800), 200)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
77
src/test/scala/game/ItemTransactionMessageTest.scala
Normal file
77
src/test/scala/game/ItemTransactionMessageTest.scala
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{PlanetSideGUID, TransactionType}
|
||||
import scodec.bits._
|
||||
|
||||
class ItemTransactionMessageTest extends Specification {
|
||||
val string_buy = hex"44 4C03 4000110070756E6973686572000000"
|
||||
val string_sell = hex"44 5303 60001000004E00"
|
||||
val string_forget = hex"44 BA00 600011006861726173736572000000"
|
||||
|
||||
"decode (buy)" in {
|
||||
PacketCoding.DecodePacket(string_buy).require match {
|
||||
case ItemTransactionMessage(terminal_guid, transaction_type, item_page, item_name, unk1, item_guid) =>
|
||||
terminal_guid mustEqual PlanetSideGUID(844)
|
||||
transaction_type mustEqual TransactionType.Buy
|
||||
item_page mustEqual 0
|
||||
item_name mustEqual "punisher"
|
||||
unk1 mustEqual 0
|
||||
item_guid mustEqual PlanetSideGUID(0)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (sell)" in {
|
||||
PacketCoding.DecodePacket(string_sell).require match {
|
||||
case ItemTransactionMessage(terminal_guid, transaction_type, item_page, item_name, unk1, item_guid) =>
|
||||
terminal_guid mustEqual PlanetSideGUID(851)
|
||||
transaction_type mustEqual TransactionType.Sell
|
||||
item_page mustEqual 0
|
||||
item_name mustEqual ""
|
||||
unk1 mustEqual 0
|
||||
item_guid mustEqual PlanetSideGUID(78)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode (forget)" in {
|
||||
PacketCoding.DecodePacket(string_forget).require match {
|
||||
case ItemTransactionMessage(terminal_guid, transaction_type, item_page, item_name, unk1, item_guid) =>
|
||||
terminal_guid mustEqual PlanetSideGUID(186)
|
||||
transaction_type mustEqual TransactionType.Sell
|
||||
item_page mustEqual 0
|
||||
item_name mustEqual "harasser"
|
||||
unk1 mustEqual 0
|
||||
item_guid mustEqual PlanetSideGUID(0)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (buy)" in {
|
||||
val msg_buy = ItemTransactionMessage(PlanetSideGUID(844), TransactionType.Buy, 0, "punisher", 0, PlanetSideGUID(0))
|
||||
val pkt_buy = PacketCoding.EncodePacket(msg_buy).require.toByteVector
|
||||
pkt_buy mustEqual string_buy
|
||||
}
|
||||
|
||||
"encode (sell)" in {
|
||||
val msg_sell = ItemTransactionMessage(PlanetSideGUID(851), TransactionType.Sell, 0, "", 0, PlanetSideGUID(78))
|
||||
val pkt_sell = PacketCoding.EncodePacket(msg_sell).require.toByteVector
|
||||
|
||||
pkt_sell mustEqual string_sell
|
||||
}
|
||||
|
||||
"encode (forget)" in {
|
||||
val msg_forget =
|
||||
ItemTransactionMessage(PlanetSideGUID(186), TransactionType.Sell, 0, "harasser", 0, PlanetSideGUID(0))
|
||||
val pkt_forget = PacketCoding.EncodePacket(msg_forget).require.toByteVector
|
||||
|
||||
pkt_forget mustEqual string_forget
|
||||
}
|
||||
}
|
||||
44
src/test/scala/game/ItemTransactionResultMessageTest.scala
Normal file
44
src/test/scala/game/ItemTransactionResultMessageTest.scala
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{PlanetSideGUID, TransactionType}
|
||||
import scodec.bits._
|
||||
|
||||
class ItemTransactionResultMessageTest extends Specification {
|
||||
//these are paried packets come from the same capture
|
||||
val string_request = hex"44 DD 03 40 00 11 40 73 75 70 70 72 65 73 73 6F 72 00 00 00"
|
||||
val string_result = hex"45 DD 03 50 00"
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string_result).require match {
|
||||
case ItemTransactionResultMessage(terminal_guid, transaction_type, is_success, error_code) =>
|
||||
terminal_guid mustEqual PlanetSideGUID(989)
|
||||
transaction_type mustEqual TransactionType.Buy
|
||||
is_success mustEqual true
|
||||
error_code mustEqual 0
|
||||
case default =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = ItemTransactionResultMessage(PlanetSideGUID(989), TransactionType.Buy, true, 0)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_result
|
||||
}
|
||||
|
||||
"proper reply" in {
|
||||
try {
|
||||
val request = PacketCoding.DecodePacket(string_request).require.asInstanceOf[ItemTransactionMessage]
|
||||
val result = PacketCoding.DecodePacket(string_result).require.asInstanceOf[ItemTransactionResultMessage]
|
||||
request.terminal_guid mustEqual result.terminal_guid
|
||||
request.transaction_type mustEqual result.transaction_type
|
||||
} catch {
|
||||
case e: Exception =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
27
src/test/scala/game/KeepAliveMessageTest.scala
Normal file
27
src/test/scala/game/KeepAliveMessageTest.scala
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class KeepAliveMessageTest extends Specification {
|
||||
val string = hex"BA 0000"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case KeepAliveMessage(code) =>
|
||||
code mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = KeepAliveMessage()
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
40
src/test/scala/game/LashMessageTest.scala
Normal file
40
src/test/scala/game/LashMessageTest.scala
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{PlanetSideGUID, Vector3}
|
||||
import scodec.bits._
|
||||
|
||||
class LashMessageTest extends Specification {
|
||||
val string = hex"4f644a82e2c297a738a1ed0b01b886c0"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case LashMessage(seq_time, player, victim, bullet, pos, unk1) =>
|
||||
seq_time mustEqual 356
|
||||
player mustEqual PlanetSideGUID(2858)
|
||||
victim mustEqual PlanetSideGUID(2699)
|
||||
bullet mustEqual PlanetSideGUID(40030)
|
||||
pos mustEqual Vector3(5903.7656f, 3456.5156f, 111.53125f)
|
||||
unk1 mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = LashMessage(
|
||||
356,
|
||||
PlanetSideGUID(2858),
|
||||
PlanetSideGUID(2699),
|
||||
PlanetSideGUID(40030),
|
||||
Vector3(5903.7656f, 3456.5156f, 111.53125f),
|
||||
0
|
||||
)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
31
src/test/scala/game/LoadMapMessageTest.scala
Normal file
31
src/test/scala/game/LoadMapMessageTest.scala
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class LoadMapMessageTest extends Specification {
|
||||
val string = hex"31 85 6D61703130 83 7A3130 0FA0 19000000 F6 F1 60 86 80"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case LoadMapMessage(map_name, nav_map_name, unk1, unk2, weapons_unlocked, unk3) =>
|
||||
map_name mustEqual "map10"
|
||||
nav_map_name mustEqual "z10"
|
||||
unk1 mustEqual 40975
|
||||
unk2 mustEqual 25
|
||||
weapons_unlocked mustEqual true
|
||||
unk3 mustEqual 230810349
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = LoadMapMessage("map10", "z10", 40975, 25, true, 230810349)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
123
src/test/scala/game/LoginMessageTest.scala
Normal file
123
src/test/scala/game/LoginMessageTest.scala
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
// 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]
|
||||
}
|
||||
}
|
||||
81
src/test/scala/game/LoginRespMessageTest.scala
Normal file
81
src/test/scala/game/LoginRespMessageTest.scala
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.packet.game.LoginRespMessage._
|
||||
import scodec.bits._
|
||||
|
||||
class LoginRespMessageTest extends Specification {
|
||||
|
||||
/// NOTE: the token is a C-string, meaning that the 18FABE0C junk seems like uninitialized memory due to memcpy, but
|
||||
/// not memset
|
||||
//val original = hex"02 4861484C64597A73305641536A6B73520000000018FABE0C0000000000000000" ++
|
||||
// hex"00000000 01000000 02000000 6B7BD828 8C4169666671756F7469656E74 00000000 00"
|
||||
val string = hex"02 4861484C64597A73305641536A6B735200000000000000000000000000000000" ++
|
||||
hex"00000000 01000000 02000000 6B7BD828 8C4169666671756F7469656E74 00000000 00"
|
||||
|
||||
val string_priv = hex"02 4861484C64597A73305641536A6B735200000000000000000000000000000000" ++
|
||||
hex"00000000 01000000 02000000 6B7BD828 8C4169666671756F7469656E74 11270000 80"
|
||||
|
||||
"encode" in {
|
||||
val msg = LoginRespMessage(
|
||||
"HaHLdYzs0VASjksR",
|
||||
LoginError.Success,
|
||||
StationError.AccountActive,
|
||||
StationSubscriptionStatus.Active,
|
||||
685276011,
|
||||
"Aiffquotient",
|
||||
0
|
||||
)
|
||||
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string
|
||||
}
|
||||
|
||||
"encode with privilege" in {
|
||||
val msg = LoginRespMessage(
|
||||
"HaHLdYzs0VASjksR",
|
||||
LoginError.Success,
|
||||
StationError.AccountActive,
|
||||
StationSubscriptionStatus.Active,
|
||||
685276011,
|
||||
"Aiffquotient",
|
||||
10001
|
||||
)
|
||||
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string_priv
|
||||
}
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case LoginRespMessage(token, error, stationError, subscription, unk, username, priv) =>
|
||||
token mustEqual "HaHLdYzs0VASjksR"
|
||||
error mustEqual LoginError.Success
|
||||
stationError mustEqual StationError.AccountActive
|
||||
subscription mustEqual StationSubscriptionStatus.Active
|
||||
unk mustEqual 685276011
|
||||
username mustEqual "Aiffquotient"
|
||||
priv mustEqual 0
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"decode with privilege" in {
|
||||
PacketCoding.DecodePacket(string_priv).require match {
|
||||
case LoginRespMessage(token, error, stationError, subscription, unk, username, priv) =>
|
||||
token mustEqual "HaHLdYzs0VASjksR"
|
||||
error mustEqual LoginError.Success
|
||||
stationError mustEqual StationError.AccountActive
|
||||
subscription mustEqual StationSubscriptionStatus.Active
|
||||
unk mustEqual 685276011
|
||||
username mustEqual "Aiffquotient"
|
||||
priv mustEqual 10001
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
}
|
||||
28
src/test/scala/game/LootItemMessageTest.scala
Normal file
28
src/test/scala/game/LootItemMessageTest.scala
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import scodec.bits._
|
||||
|
||||
class LootItemMessageTest extends Specification {
|
||||
val string = hex"6C DD0D 5C14"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case LootItemMessage(item_guid, target_guid) =>
|
||||
item_guid mustEqual PlanetSideGUID(3549)
|
||||
target_guid mustEqual PlanetSideGUID(5212)
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = LootItemMessage(PlanetSideGUID(3549), PlanetSideGUID(5212))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
30
src/test/scala/game/MailMessageTest.scala
Normal file
30
src/test/scala/game/MailMessageTest.scala
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package game
|
||||
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import scodec.bits._
|
||||
|
||||
class MailMessageTest extends Specification {
|
||||
//we've never received this packet before so this whole test is faked
|
||||
val string = hex"F1 86466174654A489250726 96F72697479204D61696C2054657374 8E48656C6C6F204175726178697321"
|
||||
|
||||
"decode" in {
|
||||
PacketCoding.DecodePacket(string).require match {
|
||||
case MailMessage(sender, subject, msg) =>
|
||||
sender mustEqual "FateJH"
|
||||
subject mustEqual "Priority Mail Test"
|
||||
msg mustEqual "Hello Auraxis!"
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode" in {
|
||||
val msg = MailMessage("FateJH", "Priority Mail Test", "Hello Auraxis!")
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue