diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/Terminal.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/Terminal.scala index 6f806f26..c7c9b5bd 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/terminals/Terminal.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/Terminal.scala @@ -2,8 +2,6 @@ package net.psforever.objects.serverobject.terminals import net.psforever.objects.Player -import net.psforever.objects.definition.ImplantDefinition -import net.psforever.objects.inventory.InventoryItem import net.psforever.objects.serverobject.PlanetSideServerObject import net.psforever.packet.game.{ItemTransactionMessage, PlanetSideGUID} import net.psforever.types.{TransactionType, Vector3} @@ -154,6 +152,7 @@ object Terminal { */ final case class SellCertification(cert : CertificationType.Value, cost : Int) extends Exchange + import net.psforever.objects.definition.ImplantDefinition /** * Provide the implant type unlocked by the player. * @param implant the implant (definition) requested @@ -167,6 +166,7 @@ object Terminal { final case class SellImplant(implant : ImplantDefinition) extends Exchange import net.psforever.objects.Vehicle + import net.psforever.objects.inventory.InventoryItem /** * Provide a vehicle that was constructed for the player. * @param vehicle the vehicle @@ -175,7 +175,6 @@ object Terminal { */ final case class BuyVehicle(vehicle : Vehicle, weapons : List[InventoryItem], inventory : List[InventoryItem]) extends Exchange - import net.psforever.objects.inventory.InventoryItem /** * Recover a former exo-suit and `Equipment` configuration that the `Player` possessed. * A result of a processed request. diff --git a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala index f5814a85..431aca9f 100644 --- a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala +++ b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala @@ -447,7 +447,7 @@ object GamePacketOpcode extends Enumeration { case 0x6a => noDecoder(AggravatedDamageMessage) case 0x6b => game.TriggerSoundMessage.decode case 0x6c => game.LootItemMessage.decode - case 0x6d => noDecoder(VehicleSubStateMessage) + case 0x6d => game.VehicleSubStateMessage.decode case 0x6e => noDecoder(SquadMembershipRequest) case 0x6f => noDecoder(SquadMembershipResponse) diff --git a/common/src/main/scala/net/psforever/packet/game/VehicleStateMessage.scala b/common/src/main/scala/net/psforever/packet/game/VehicleStateMessage.scala index 4f528584..aa71caa2 100644 --- a/common/src/main/scala/net/psforever/packet/game/VehicleStateMessage.scala +++ b/common/src/main/scala/net/psforever/packet/game/VehicleStateMessage.scala @@ -49,7 +49,7 @@ object VehicleStateMessage extends Marshallable[VehicleStateMessage] { * @see `Angular.codec_pitch` * @see `Angular.codec_yaw` */ - private val codec_orient : Codec[Vector3] = ( + val codec_orient : Codec[Vector3] = ( ("roll" | Angular.codec_roll(10)) :: ("pitch" | Angular.codec_pitch(10)) :: ("yaw" | Angular.codec_yaw(10, 90f)) diff --git a/common/src/main/scala/net/psforever/packet/game/VehicleSubStateMessage.scala b/common/src/main/scala/net/psforever/packet/game/VehicleSubStateMessage.scala new file mode 100644 index 00000000..8a190d71 --- /dev/null +++ b/common/src/main/scala/net/psforever/packet/game/VehicleSubStateMessage.scala @@ -0,0 +1,45 @@ +// Copyright (c) 2017 PSForever +package net.psforever.packet.game + +import net.psforever.packet._ +import net.psforever.types.Vector3 +import scodec.Codec +import scodec.codecs._ + +/** + * Dispatched by the client of a driver who is involved in a collision with another vehicle that has no driver. + * May be supplemented with `GenericCollisionMsg` packets that call out both vehicles. + * Multiple packets may be generated for a single event representing either + * entanglement, escalation, or a lack of resolution. + * @param vehicle_guid the vehicle that was collided with + * @param player_guid the player who drove into the vehicle + * @param vehicle_pos the xyz-coordinates of the displaced collision vehicle in reference to the player's client + * @param vehicle_ang the orientation of the displaced collision vehicle in reference to the player's client + * @param vel optional velocity (unknown) + * @param unk1 na + * @param unk2 na + */ +final case class VehicleSubStateMessage(vehicle_guid : PlanetSideGUID, + player_guid : PlanetSideGUID, + vehicle_pos : Vector3, + vehicle_ang : Vector3, + vel : Option[Vector3], + unk1 : Boolean, + unk2 : Option[List[Boolean]]) + extends PlanetSideGamePacket { + type Packet = VehicleSubStateMessage + def opcode = GamePacketOpcode.VehicleSubStateMessage + def encode = VehicleSubStateMessage.encode(this) +} + +object VehicleSubStateMessage extends Marshallable[VehicleSubStateMessage] { + implicit val codec : Codec[VehicleSubStateMessage] = ( + ("vehicle_guid" | PlanetSideGUID.codec) :: + ("player_guid" | PlanetSideGUID.codec) :: + ("vehicle_pos" | Vector3.codec_float) :: + ("vehicle_ang" | VehicleStateMessage.codec_orient) :: + optional(bool, "vel" | Vector3.codec_vel) :: + ("unk1" | bool) :: + optional(bool, "unk2" | PacketHelpers.listOfNSized(4, bool)) + ).as[VehicleSubStateMessage] +} diff --git a/common/src/test/scala/game/VehicleSubStateMessageTest.scala b/common/src/test/scala/game/VehicleSubStateMessageTest.scala new file mode 100644 index 00000000..95b0e948 --- /dev/null +++ b/common/src/test/scala/game/VehicleSubStateMessageTest.scala @@ -0,0 +1,35 @@ +// 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 VehicleSubStateMessageTest extends Specification { + val string = hex"6D D91C 300D 529F5845 D1953345 E51AB642 21000F63E6F80C1CCF80" + + "decode" in { + PacketCoding.DecodePacket(string).require match { + case VehicleSubStateMessage(vehicle_guid, player_guid, vehicle_pos, vehicle_ang, vel, unk1, unk2) => + vehicle_guid mustEqual PlanetSideGUID(7385) + player_guid mustEqual PlanetSideGUID(3376) + vehicle_pos mustEqual Vector3(3465.9575f, 2873.3635f, 91.05253f) + vehicle_ang mustEqual Vector3(11.6015625f, 0.0f, 3.515625f) + vel.isDefined mustEqual true + vel.get mustEqual Vector3(-0.40625f, 0.03125f, -0.8125f) + unk1 mustEqual false + unk2.isDefined mustEqual false + case _ => + ko + } + } + + "encode" in { + val msg = VehicleSubStateMessage(PlanetSideGUID(7385), PlanetSideGUID(3376), Vector3(3465.9575f, 2873.3635f, 91.05253f), Vector3(11.6015625f, 0.0f, 3.515625f), Some(Vector3(-0.40625f, 0.03125f, -0.8125f)), false, None) + val pkt = PacketCoding.EncodePacket(msg).require.toByteVector + + pkt mustEqual string + } +} diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index 62a015b6..9beb218a 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -1268,6 +1268,9 @@ class WorldSessionActor extends Actor with MDCContextAware { } //log.info("VehicleState: " + msg) + case msg @ VehicleSubStateMessage(vehicle_guid, player_guid, vehicle_pos, vehicle_ang, vel, unk1, unk2) => + //log.info(s"VehicleSubState: $vehicle_guid, $player_guid, $vehicle_pos, $vehicle_ang, $vel, $unk1, $unk2") + case msg @ ProjectileStateMessage(projectile_guid, shot_pos, shot_vector, unk1, unk2, unk3, unk4, time_alive) => //log.info("ProjectileState: " + msg)