diff --git a/src/main/scala/net/psforever/actors/net/LoginActor.scala b/src/main/scala/net/psforever/actors/net/LoginActor.scala index 6fd5d7bd5..f58fce6d1 100644 --- a/src/main/scala/net/psforever/actors/net/LoginActor.scala +++ b/src/main/scala/net/psforever/actors/net/LoginActor.scala @@ -106,7 +106,7 @@ class LoginActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], conne accountLogin(username, password.getOrElse("")) - case ConnectToWorldRequestMessage(name, _, _, _, _, _, _) => + case ConnectToWorldRequestMessage(name, _, _, _, _, _, _, _) => log.info(s"Connect to world request for '$name'") val response = ConnectToWorldMessage(serverName, publicAddress.getAddress.getHostAddress, publicAddress.getPort) middlewareActor ! MiddlewareActor.Send(response) diff --git a/src/main/scala/net/psforever/actors/session/support/SessionData.scala b/src/main/scala/net/psforever/actors/session/support/SessionData.scala index aa89066b7..196bb8a15 100644 --- a/src/main/scala/net/psforever/actors/session/support/SessionData.scala +++ b/src/main/scala/net/psforever/actors/session/support/SessionData.scala @@ -156,7 +156,7 @@ class SessionData( /* packets */ def handleConnectToWorldRequest(pkt: ConnectToWorldRequestMessage)(implicit context: ActorContext): Unit = { - val ConnectToWorldRequestMessage(_, token, majorVersion, minorVersion, revision, buildDate, _) = pkt + val ConnectToWorldRequestMessage(_, token, majorVersion, minorVersion, revision, buildDate, _, _) = pkt log.trace( s"ConnectToWorldRequestMessage: client with versioning $majorVersion.$minorVersion.$revision, $buildDate has sent a token to the server" ) @@ -217,12 +217,9 @@ class SessionData( } } fallHeightTracker(pos.z) - if (isCrouching && !player.Crouching) { - import scodec.bits._ - // 17 B8010000 970 3D10 002D765535CA16000000 402285BB0037E 4100749E1D03000000620D83A0A00000195798741C00000332E40D84800000 - middlewareActor ! MiddlewareActor.Raw(hex"17 ec060000 970 fe0f 6C2D765535CA16000013 f9c1f2f80c000 1e18ff0000 105 1e4078640000000 8c50004c0041006d0069006e00670079007500650054005200 7c00000304217c859e8080000000000000002503420022c02a002a002a002a0050004c0041002a002a002a002a00010027e300940000016c0400023c040002285a086c2f00c80000000000300210288740800000004046f17423018000002c4d6190400000001010704a86406000002bc770842000000004041c5f21d01800000e075821902000000623e84208000001950588c1800000332ea0f840000000") - //dev stuff goes here - } +// if (isCrouching && !player.Crouching) { +// //dev stuff goes here +// } player.Position = pos player.Velocity = vel player.Orientation = Vector3(player.Orientation.x, pitch, yaw) diff --git a/src/main/scala/net/psforever/packet/game/ConnectToWorldRequestMessage.scala b/src/main/scala/net/psforever/packet/game/ConnectToWorldRequestMessage.scala index 63b0aadd5..36193896b 100644 --- a/src/main/scala/net/psforever/packet/game/ConnectToWorldRequestMessage.scala +++ b/src/main/scala/net/psforever/packet/game/ConnectToWorldRequestMessage.scala @@ -14,7 +14,8 @@ final case class ConnectToWorldRequestMessage( minorVersion: Long, revision: Long, buildDate: String, - unknown: Int + unk1: Int, + unk2: Int ) extends PlanetSideGamePacket { type Packet = ConnectToWorldRequestMessage def opcode = GamePacketOpcode.ConnectToWorldRequestMessage @@ -29,6 +30,7 @@ object ConnectToWorldRequestMessage extends Marshallable[ConnectToWorldRequestMe ("minor_version" | uint32L) :: ("revision" | uint32L) :: ("build_date" | PacketHelpers.encodedString) :: - ("unknown_short" | uint16L) + ("unk1" | uint8) :: + ("unk2" | uint8) ).as[ConnectToWorldRequestMessage] } diff --git a/src/main/scala/net/psforever/packet/game/objectcreate/CharacterAppearanceData.scala b/src/main/scala/net/psforever/packet/game/objectcreate/CharacterAppearanceData.scala index 71ea09be2..3e8b820e1 100644 --- a/src/main/scala/net/psforever/packet/game/objectcreate/CharacterAppearanceData.scala +++ b/src/main/scala/net/psforever/packet/game/objectcreate/CharacterAppearanceData.scala @@ -171,9 +171,9 @@ object CharacterAppearanceData extends Marshallable[CharacterAppearanceData] { app.faction, black_ops, altModel, - false, + v1 = false, None, - false, + jammered=false, None, if (jammered) { Some(0) @@ -194,20 +194,20 @@ object CharacterAppearanceData extends Marshallable[CharacterAppearanceData] { outfit_name.length, outfit_name: String, outfit_logo: Int, - false, + unk1 = false, backpack, - false, - false, - false, + unk2 = false, + unk3 = false, + unk4 = false, facingPitch: Float, facingYawUpper: Float, lfs: Boolean, grenade_state: GrenadeState.Value, is_cloaking: Boolean, - false, - false, + unk5 = false, + unk6 = false, charging_pose: Boolean, - false, + unk7 = false, on_zipline )(altModel, name_padding) new CharacterAppearanceData( @@ -283,11 +283,6 @@ object CharacterAppearanceData extends Marshallable[CharacterAppearanceData] { 6 } - private val extra_codec: Codec[ExtraData] = ( - ("unk1" | bool) :: - ("unk2" | bool) - ).as[ExtraData] - private val zipline_codec: Codec[ZiplineData] = ( ("unk1" | uint32L) :: ("unk2" | bool) @@ -301,9 +296,9 @@ object CharacterAppearanceData extends Marshallable[CharacterAppearanceData] { def a_codec(name_padding: Int): Codec[CharacterAppearanceA] = ( ("data" | CommonFieldData.codec) >>:~ { data => - ("name" | PacketHelpers.encodedWideStringAligned(namePadding(name_padding, data.v2))) >>:~ { name => + ("name" | PacketHelpers.encodedWideStringAligned(namePadding(name_padding, data.v2))) :: ("exosuit" | ExoSuitType.codec) :: - ("unk5" | uint2) :: //unknown + ("unk5" | uint2) :: ("sex" | CharacterSex.codec) :: ("head" | uint8L) :: ("voice" | CharacterVoice.codec) :: @@ -312,7 +307,7 @@ object CharacterAppearanceData extends Marshallable[CharacterAppearanceData] { ("unk8" | uint16L) :: ("unk9" | uint16L) :: ("unkA" | uint16L) //usually either 0 or 65535 - }} + } ).exmap[CharacterAppearanceA]( { case data :: name :: suit :: u5 :: sex :: head :: v1 :: u6 :: u7 :: u8 :: u9 :: uA :: HNil => @@ -398,14 +393,14 @@ object CharacterAppearanceData extends Marshallable[CharacterAppearanceData] { ("outfit_name" | PacketHelpers.encodedWideStringAligned(outfitNamePadding)) :: ("outfit_logo" | uint8L) :: ("unk1" | bool) :: //unknown - conditional(alt_model, "backpack" | bool) :: //alt_model flag adds this bit; see ps.c:line#1069587 + ("backpack" | conditional(alt_model, bool)) :: //alt_model flag adds this bit; see ps.c:line#1069587 ("unk2" | bool) :: //requires alt_model flag (does NOT require health == 0) ("unk3" | bool) :: //stream misalignment when set ("unk4" | bool) :: //unknown ("facingPitch" | Angular.codec_zero_centered) :: ("facingYawUpper" | Angular.codec_zero_centered) :: ("lfs" | uint2) :: - ("grenade_state" | GrenadeState.codec_2u) :: //note: bin10 and bin11 are neutral (bin00 is not defined) + ("grenade_state" | GrenadeState.codec_2u) :: ("is_cloaking" | bool) :: ("unk5" | bool) :: //unknown ("unk6" | bool) :: //stream misalignment when set diff --git a/src/main/scala/net/psforever/packet/game/objectcreate/CharacterData.scala b/src/main/scala/net/psforever/packet/game/objectcreate/CharacterData.scala index 014c46bd9..d224f62d5 100644 --- a/src/main/scala/net/psforever/packet/game/objectcreate/CharacterData.scala +++ b/src/main/scala/net/psforever/packet/game/objectcreate/CharacterData.scala @@ -119,7 +119,7 @@ object CharacterData extends Marshallable[CharacterData] { ("health" | uint8L) :: //dead state when health == 0 ("armor" | uint8L) :: (("uniform_upgrade" | UniformStyle.codec) >>:~ { style => - uint(3) :: //uniform_upgrade is actually interpreted as a 6u field, but the lower 3u seems to be discarded + uint(bits = 3) :: //uniform_upgrade is actually interpreted as a 6u field, but the lower 3u seems to be discarded ("command_rank" | uintL(3)) :: listOfN(uint2, "implant_effects" | ImplantEffects.codec) :: ("cosmetics" | conditional(BattleRank.showCosmetics(style), Cosmetic.codec)) diff --git a/src/main/scala/net/psforever/types/CharacterVoice.scala b/src/main/scala/net/psforever/types/CharacterVoice.scala index a6e287d44..eefc6baa2 100644 --- a/src/main/scala/net/psforever/types/CharacterVoice.scala +++ b/src/main/scala/net/psforever/types/CharacterVoice.scala @@ -22,5 +22,5 @@ object CharacterVoice extends Enumeration { Voice5 //daredevil, calculating = Value - implicit val codec = PacketHelpers.createEnumerationCodec(this, uint(3)) + implicit val codec = PacketHelpers.createEnumerationCodec(this, uint(bits = 3)) } diff --git a/src/main/scala/net/psforever/types/ExoSuitType.scala b/src/main/scala/net/psforever/types/ExoSuitType.scala index fee36b081..439d1e023 100644 --- a/src/main/scala/net/psforever/types/ExoSuitType.scala +++ b/src/main/scala/net/psforever/types/ExoSuitType.scala @@ -12,5 +12,5 @@ object ExoSuitType extends Enumeration { type Type = Value val Agile, Reinforced, MAX, Infiltration, Standard = Value - implicit val codec: Codec[ExoSuitType.Value] = PacketHelpers.createEnumerationCodec(this, uint(3)) + implicit val codec: Codec[ExoSuitType.Value] = PacketHelpers.createEnumerationCodec(this, uint(bits = 3)) } diff --git a/src/test/scala/game/ConnectToWorldRequestMessageTest.scala b/src/test/scala/game/ConnectToWorldRequestMessageTest.scala index 770bb3aca..05f1dba0e 100644 --- a/src/test/scala/game/ConnectToWorldRequestMessageTest.scala +++ b/src/test/scala/game/ConnectToWorldRequestMessageTest.scala @@ -12,21 +12,22 @@ class ConnectToWorldRequestMessageTest extends Specification { "decode" in { PacketCoding.decodePacket(string).require match { - case ConnectToWorldRequestMessage(serverName, token, majorVersion, minorVersion, revision, buildDate, unk) => + case ConnectToWorldRequestMessage(serverName, token, majorVersion, minorVersion, revision, buildDate, unk1, unk2) => serverName mustEqual "gemini" token mustEqual "" majorVersion mustEqual 0 minorVersion mustEqual 0 revision mustEqual 0 buildDate mustEqual "" - unk mustEqual 0 + unk1 mustEqual 0 + unk2 mustEqual 0 case _ => ko } } "encode" in { - val msg = ConnectToWorldRequestMessage("gemini", "", 0, 0, 0, "", 0) + val msg = ConnectToWorldRequestMessage("gemini", "", 0, 0, 0, "", 0, 0) val pkt = PacketCoding.encodePacket(msg).require.toByteVector pkt mustEqual string diff --git a/src/test/scala/game/objectcreatevehicle/UtilityVehiclesTest.scala b/src/test/scala/game/objectcreatevehicle/UtilityVehiclesTest.scala index a5eadf0d6..57dedbdb0 100644 --- a/src/test/scala/game/objectcreatevehicle/UtilityVehiclesTest.scala +++ b/src/test/scala/game/objectcreatevehicle/UtilityVehiclesTest.scala @@ -2,7 +2,7 @@ package game.objectcreatevehicle import net.psforever.packet._ -import net.psforever.packet.game.objectcreate._ +import net.psforever.packet.game.objectcreate.{CharacterAppearanceA, _} import net.psforever.packet.game.ObjectCreateMessage import net.psforever.types._ import org.specs2.mutable._ @@ -13,7 +13,7 @@ class UtilityVehiclesTest extends Specification { val string_ams = hex"17 B8010000 970 3D10 002D765535CA16000000 402285BB0037E4100749E1D03000000620D83A0A00000195798741C00000332E40D84800000" val string_ams_seated = - hex"17ec060000970fe0f030898abda28127f007ff9c1f2f80c0001e18ff00001051e40786400000008c50004c0041006d0069006e006700790075006500540052007c00000304217c859e8080000000000000002503420022c02a002a002a002a0050004c0041002a002a002a002a00010027e300940000016c0400023c040002285a086c2f00c80000000000300210288740800000004046f17423018000002c4d6190400000001010704a86406000002bc770842000000004041c5f21d01800000e075821902000000623e84208000001950588c1800000332ea0f840000000" + hex"17 ec060000 970 fe0f 6C2D765535CA16000013 f9c1f2f80c000 1e18ff0000 105 1e4078640000000 8c50004c0041006d0069006e00670079007500650054005200 04217c859e808000000000000000250342002 2c02a002a002a002a0050004c0041002a002a002a002a00 010027e3007c000003940000016c0400023c040002285a086c2f00c80000000000300210288740800000004046f17423018000002c4d6190400000001010704a86406000002bc770842000000004041c5f21d01800000e0 75821902000000 623e8420800000 1950588c1800000 332ea0f840000000" "Utility vehicles" should { "decode (ant)" in { @@ -98,12 +98,141 @@ class UtilityVehiclesTest extends Specification { "decode (ams, seated)" in { PacketCoding.decodePacket(string_ams_seated).require match { case ObjectCreateMessage(len, cls, guid, None, data) => - len mustEqual 440L + len mustEqual 1772 cls mustEqual ObjectClass.ams - guid mustEqual PlanetSideGUID(4157) + guid mustEqual PlanetSideGUID(4094) data match { case ams: VehicleData => - ok + ams.pos.coord mustEqual Vector3(3674.8438f, 2726.789f, 91.15625f) + ams.pos.orient mustEqual Vector3(0f, 0f, 36.5625f) + ams.pos.vel.contains(Vector3(27.3375f, -0.78749996f, 0.1125f)) mustEqual true //contains does not work + ams.data match { + case data: CommonFieldData => + data.faction mustEqual PlanetSideEmpire.TR + data.bops mustEqual false + data.alternate mustEqual false + data.v1 mustEqual false + data.v2.isEmpty mustEqual true + data.jammered mustEqual false + data.v4.contains(false) mustEqual true + data.v5.isEmpty mustEqual true + data.guid mustEqual ValidPlanetSideGUID(3087) + case _ => + ko + } + ams.unk3 mustEqual false + ams.health mustEqual 255 + ams.unk4 mustEqual false + ams.no_mount_points mustEqual false + ams.driveState mustEqual DriveState.Mobile + ams.unk5 mustEqual false + ams.unk6 mustEqual false + ams.cloak mustEqual false + ams.vehicle_format_data.contains(UtilityVehicleData(0)) mustEqual true + val inv = ams.inventory match { + case Some(inv: InventoryData) => inv.contents + case _ => Nil + } + //0 + val inv0 = inv.head + inv0.objectClass mustEqual ObjectClass.avatar + inv0.guid mustEqual PlanetSideGUID(3087) + inv0.parentSlot mustEqual 0 + inv0.obj match { + case PlayerData(None, CharacterAppearanceData(a, b, r), char, Some(InventoryData(pinv)), DrawnSlot.None) => + a.app.name mustEqual "PLAmingyueTR" + a.app.faction mustEqual PlanetSideEmpire.TR + a.app.sex mustEqual CharacterSex.Female + a.app.voice mustEqual CharacterVoice.Voice5 + a.app.head mustEqual 16 + a.data match { + case data: CommonFieldData => + data.faction mustEqual PlanetSideEmpire.TR + data.bops mustEqual false + data.alternate mustEqual false + data.v1 mustEqual false + data.v2.isEmpty mustEqual true + data.jammered mustEqual false + data.v4.isEmpty mustEqual true + data.v5.isEmpty mustEqual true + data.guid mustEqual ValidPlanetSideGUID(0) + case _ => + ko + } + a.char_id mustEqual 41555698L + a.exosuit mustEqual ExoSuitType.Agile + a.unk5 mustEqual 0 + a.unk7 mustEqual 0 + a.unk8 mustEqual 0 + a.unk9 mustEqual 0 + a.unkA mustEqual 0 + b.outfit_id mustEqual 527764 + b.outfit_name mustEqual "****PLA****" + b.outfit_logo mustEqual 1 + b.lfs mustEqual false + b.backpack mustEqual false + b.charging_pose mustEqual false + b.grenade_state mustEqual GrenadeState.None + b.on_zipline.isEmpty mustEqual true + b.facingPitch mustEqual -5.625f + b.facingYawUpper mustEqual 5.625f + b.unk1 mustEqual false + b.unk2 mustEqual false + b.unk3 mustEqual false + b.unk4 mustEqual false + b.unk5 mustEqual false + b.unk6 mustEqual false + b.unk7 mustEqual false + r mustEqual RibbonBars( + MeritCommendation.AMSSupport2, + MeritCommendation.HeavyAssault1, + MeritCommendation.ScavengerTR1, + MeritCommendation.ThreeYearTR + ) + char.health mustEqual 100 + char.armor mustEqual 0 + char.uniform_upgrade mustEqual UniformStyle.ThirdUpgrade + char.command_rank mustEqual 4 + char.implant_effects mustEqual Nil + char.unk mustEqual 2 + char.cosmetics.contains(Set(Cosmetic.Earpiece, Cosmetic.Sunglasses, Cosmetic.NoHelmet)) mustEqual true + pinv mustEqual List( + InternalSlot(728, ValidPlanetSideGUID(3312), 0, REKData(CommonFieldData(PlanetSideEmpire.TR,false,false,false,None,false,Some(false),None,ValidPlanetSideGUID(0)),3,0)), + InternalSlot(132, ValidPlanetSideGUID(3665), 1, WeaponData(CommonFieldData(PlanetSideEmpire.TR,false,false,false,None,false,None,None,ValidPlanetSideGUID(0)),0,List( + InternalSlot(111,ValidPlanetSideGUID(4538),0,CommonFieldData(PlanetSideEmpire.NEUTRAL,false,false,false,None,false,Some(false),None,ValidPlanetSideGUID(0)))),false) + ), + InternalSlot(556, ValidPlanetSideGUID(3179), 2, WeaponData(CommonFieldData(PlanetSideEmpire.TR,false,false,false,None,false,None,None,ValidPlanetSideGUID(0)),0,List( + InternalSlot(28,ValidPlanetSideGUID(3221),0,CommonFieldData(PlanetSideEmpire.NEUTRAL,false,false,false,None,false,Some(false),None,ValidPlanetSideGUID(0)))),false) + ), + InternalSlot(175,ValidPlanetSideGUID(4334),4,WeaponData(CommonFieldData(PlanetSideEmpire.TR,false,false,false,None,false,None,None,ValidPlanetSideGUID(0)),0,List(InternalSlot(540,ValidPlanetSideGUID(3833),0,CommonFieldData(PlanetSideEmpire.NEUTRAL,false,false,false,None,false,Some(false),None,ValidPlanetSideGUID(0)))),false)) + ) + case _ => + ko + } + //1 + val inv1 = inv(1) + inv1.objectClass mustEqual ObjectClass.matrix_terminalc + inv1.guid mustEqual PlanetSideGUID(3265) + inv1.parentSlot mustEqual 1 + inv1.obj.isInstanceOf[CommonFieldData] mustEqual true + //2 + val inv2 = inv(2) + inv2.objectClass mustEqual ObjectClass.ams_respawn_tube + inv2.guid mustEqual PlanetSideGUID(4346) + inv2.parentSlot mustEqual 2 + inv2.obj.isInstanceOf[CommonFieldData] mustEqual true + //3 + val inv3 = inv(3) + inv3.objectClass mustEqual ObjectClass.order_terminala + inv3.guid mustEqual PlanetSideGUID(4363) + inv3.parentSlot mustEqual 3 + inv3.obj.isInstanceOf[CommonFieldData] mustEqual true + //4 + val inv4 = inv(4) + inv4.objectClass mustEqual ObjectClass.order_terminalb + inv4.guid mustEqual PlanetSideGUID(4074) + inv4.parentSlot mustEqual 4 + inv4.obj.isInstanceOf[CommonFieldData] mustEqual true case _ => ko } @@ -182,5 +311,124 @@ class UtilityVehiclesTest extends Specification { pkt mustEqual string_ams } + + "encode (ams, seated)" in { + val obj = VehicleData( + PlacementData( + Vector3(3674.8438f, 2726.789f, 91.15625f), + Vector3(0f, 0f, 36.5625f), + Some(Vector3(27.3375f, -0.78749996f, 0.1125f)) + ), + CommonFieldData(PlanetSideEmpire.TR, false, false, false, None, false, Some(false), None, PlanetSideGUID(3087)), + unk3 = false, + health = 255, + unk4 = false, + no_mount_points = false, + DriveState.Mobile, + unk5 = false, + unk6 = false, + cloak = false, + Some(UtilityVehicleData(0)), + Some(InventoryData( + List( + InternalSlot( + ObjectClass.avatar, PlanetSideGUID(3087), 0, { + val a: Int => CharacterAppearanceA = CharacterAppearanceA( + BasicCharacterData( + "PLAmingyueTR", + PlanetSideEmpire.TR, + CharacterSex.Female, + head = 16, + CharacterVoice.Voice5 + ), + CommonFieldData(PlanetSideEmpire.TR, false, false, false, None, false, None, None, PlanetSideGUID(0)), + ExoSuitType.Agile, + unk5 = 0, + char_id = 41555698L, + unk7 = 0, + unk8 = 0, + unk9 = 0, + unkA = 0 + ) + val b: (Boolean, Int) => CharacterAppearanceB = CharacterAppearanceB( + outfit_id = 527764L, + outfit_name = "****PLA****", + outfit_logo = 1, + unk1 = false, + backpack = false, + unk2 = false, + unk3 = false, + unk4 = false, + facingPitch = -5.625f, + facingYawUpper = 5.625f, + lfs = false, + GrenadeState.None, + is_cloaking = false, + unk5 = false, + unk6 = false, + charging_pose = false, + unk7 = false, + on_zipline = None + ) + val app: Int => CharacterAppearanceData = CharacterAppearanceData( + a, + b, + RibbonBars( + MeritCommendation.AMSSupport2, + MeritCommendation.HeavyAssault1, + MeritCommendation.ScavengerTR1, + MeritCommendation.ThreeYearTR + ) + ) + val char: (Boolean, Boolean) => CharacterData = CharacterData( + health = 100, + armor = 0, + UniformStyle.ThirdUpgrade, + unk = 2, + command_rank = 4, + implant_effects = List(), + Some(Set(Cosmetic.Earpiece, Cosmetic.Sunglasses, Cosmetic.NoHelmet)) + ) + val inv = InventoryData( + List( + InternalSlot(728, ValidPlanetSideGUID(3312), 0, REKData(CommonFieldData(PlanetSideEmpire.TR,false,false,false,None,false,Some(false),None,ValidPlanetSideGUID(0)),3,0)), + InternalSlot(132, ValidPlanetSideGUID(3665), 1, WeaponData(CommonFieldData(PlanetSideEmpire.TR,false,false,false,None,false,None,None,ValidPlanetSideGUID(0)),0,List( + InternalSlot(111, ValidPlanetSideGUID(4538), 0, CommonFieldData(PlanetSideEmpire.NEUTRAL,false,false,false,None,false,Some(false),None,ValidPlanetSideGUID(0)))),false) + ), + InternalSlot(556, ValidPlanetSideGUID(3179), 2, WeaponData(CommonFieldData(PlanetSideEmpire.TR,false,false,false,None,false,None,None,ValidPlanetSideGUID(0)),0,List( + InternalSlot(28, ValidPlanetSideGUID(3221), 0, CommonFieldData(PlanetSideEmpire.NEUTRAL,false,false,false,None,false,Some(false),None,ValidPlanetSideGUID(0)))),false) + ), + InternalSlot(175, ValidPlanetSideGUID(4334), 4, WeaponData(CommonFieldData(PlanetSideEmpire.TR,false,false,false,None,false,None,None,ValidPlanetSideGUID(0)),0,List(InternalSlot(540,ValidPlanetSideGUID(3833),0,CommonFieldData(PlanetSideEmpire.NEUTRAL,false,false,false,None,false,Some(false),None,ValidPlanetSideGUID(0)))),false)) + ) + ) + MountableInventory.PlayerData( + app, + char, + inv, + DrawnSlot.None, + MountableInventory.InitialStreamLengthToSeatEntries(hasVelocity=true, VehicleFormat.Utility) + ) + } + ), + InternalSlot( + ObjectClass.matrix_terminalc, PlanetSideGUID(3265), 1, CommonFieldData(PlanetSideEmpire.TR)(flag = false) + ), + InternalSlot( + ObjectClass.ams_respawn_tube, PlanetSideGUID(4346), 2, CommonFieldData(PlanetSideEmpire.TR)(flag = false) + ), + InternalSlot( + ObjectClass.order_terminala, PlanetSideGUID(4363), 3, CommonFieldData(PlanetSideEmpire.TR)(flag = false) + ), + InternalSlot( + ObjectClass.order_terminalb, PlanetSideGUID(4074), 4, CommonFieldData(PlanetSideEmpire.TR)(flag = false) + ) + ) + )) + )(VehicleFormat.Utility) + val msg = ObjectCreateMessage(ObjectClass.ams, PlanetSideGUID(4094), obj) + val pkt = PacketCoding.encodePacket(msg).require.toByteVector + + pkt mustEqual string_ams_seated + } } } diff --git a/tools/client/src/main/scala/net/psforever/tools/client/Client.scala b/tools/client/src/main/scala/net/psforever/tools/client/Client.scala index a8f44128d..d7f231efe 100644 --- a/tools/client/src/main/scala/net/psforever/tools/client/Client.scala +++ b/tools/client/src/main/scala/net/psforever/tools/client/Client.scala @@ -209,7 +209,7 @@ class Client(username: String, password: String) { case _ => ??? } setupConnection() - send(ConnectToWorldRequestMessage("", state.token.get, 0, 0, 0, "", 0)).require + send(ConnectToWorldRequestMessage("", state.token.get, 0, 0, 0, "", 0, 0)).require while (true) { val r = waitFor[CharacterInfoMessage]().require if (r.finished) {