From 23ff0f532b9b1b16c5e1247ebfb96a1d7e43a33d Mon Sep 17 00:00:00 2001 From: "Jason_DiDonato@yahoo.com" Date: Tue, 25 May 2021 17:08:03 -0400 Subject: [PATCH] packet work for InvalidTerrainMessage packet and tests --- .../actors/session/SessionActor.scala | 19 +++++++ .../psforever/packet/GamePacketOpcode.scala | 2 +- .../packet/game/InvalidTerrainMessage.scala | 53 +++++++++++++++++++ .../game/InvalidTerrainMessageTest.scala | 35 ++++++++++++ 4 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 src/main/scala/net/psforever/packet/game/InvalidTerrainMessage.scala create mode 100644 src/test/scala/game/InvalidTerrainMessageTest.scala diff --git a/src/main/scala/net/psforever/actors/session/SessionActor.scala b/src/main/scala/net/psforever/actors/session/SessionActor.scala index 5fa59aca..cf0299ba 100644 --- a/src/main/scala/net/psforever/actors/session/SessionActor.scala +++ b/src/main/scala/net/psforever/actors/session/SessionActor.scala @@ -5922,6 +5922,25 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con self.toTyped[ICS.DroppodLaunchExchange] ) + case msg @ InvalidTerrainMessage(_, vehicle_guid, alert, _) => + //log.info(s"$msg") + (continent.GUID(vehicle_guid), continent.GUID(player.VehicleSeated)) match { + case (Some(packetVehicle: Vehicle), Some(playerVehicle: Vehicle)) if packetVehicle eq playerVehicle => + if (alert == TerrainCondition.Unsafe) { + log.info(s"${player.Name}'s ${packetVehicle.Definition.Name} is approaching terrain unsuitable for idling") + } + case (Some(packetVehicle: Vehicle), Some(playerVehicle: Vehicle)) => + if (alert == TerrainCondition.Unsafe) { + log.info(s"${packetVehicle.Definition.Name}@${packetVehicle.GUID} is approaching terrain unsuitable for idling, but is not ${player.Name}'s vehicle") + } + case (Some(_: Vehicle), _) => + log.warn(s"InvalidTerrain: ${player.Name} is not seated in a(ny) vehicle near unsuitable terrain") + case (Some(packetThing), _) => + log.warn(s"InvalidTerrain: ${player.Name} thinks that ${packetThing.Definition.Name}@${packetThing.GUID} is near unsuitable terrain") + case _ => + log.error(s"InvalidTerrain: ${player.Name} is complaining about a thing@$vehicle_guid that can not be found") + } + case msg @ ActionCancelMessage(u1, u2, u3) => progressBarUpdate.cancel() progressBarValue = None diff --git a/src/main/scala/net/psforever/packet/GamePacketOpcode.scala b/src/main/scala/net/psforever/packet/GamePacketOpcode.scala index b57cd033..d12593cd 100644 --- a/src/main/scala/net/psforever/packet/GamePacketOpcode.scala +++ b/src/main/scala/net/psforever/packet/GamePacketOpcode.scala @@ -485,7 +485,7 @@ object GamePacketOpcode extends Enumeration { // 0x98 case 0x98 => noDecoder(OutfitListEvent) case 0x99 => noDecoder(EmpireIncentivesMessage) - case 0x9a => noDecoder(InvalidTerrainMessage) + case 0x9a => game.InvalidTerrainMessage.decode case 0x9b => noDecoder(SyncMessage) case 0x9c => noDecoder(DebugDrawMessage) case 0x9d => noDecoder(SoulMarkMessage) diff --git a/src/main/scala/net/psforever/packet/game/InvalidTerrainMessage.scala b/src/main/scala/net/psforever/packet/game/InvalidTerrainMessage.scala new file mode 100644 index 00000000..a252d2ab --- /dev/null +++ b/src/main/scala/net/psforever/packet/game/InvalidTerrainMessage.scala @@ -0,0 +1,53 @@ +// Copyright (c) 2021 PSForever +package net.psforever.packet.game + +import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket} +import net.psforever.types.{PlanetSideGUID, Vector3} +import scodec.Attempt.Successful +import scodec.Codec +import scodec.codecs._ +import shapeless.{::, HNil} + +/** + * An `Enumeration` of the two conditions of the terrain - safe and unsafe. + */ +object TerrainCondition extends Enumeration { + type Type = Value + val Safe, Unsafe = Value + + implicit val codec = PacketHelpers.createEnumerationCodec(enum = this, uint(bits = 1)) +} + +/** + * na + * @param player_guid the player who is driving the vehicle + * @param vehicle_guid the vehicle + * @param proximity_alert whether this position is invalid; + * `true`, for the nearby terrain being unsuitable; + * `false`, when the vehicle has been moved back to a safe distance (place) + * @param pos the vehicle's current position in the game world + */ +final case class InvalidTerrainMessage( + player_guid: PlanetSideGUID, + vehicle_guid: PlanetSideGUID, + proximity_alert: TerrainCondition.Value, + pos: Vector3 + ) extends PlanetSideGamePacket { + type Packet = InvalidTerrainMessage + def opcode = GamePacketOpcode.InvalidTerrainMessage + def encode = InvalidTerrainMessage.encode(this) +} + +object InvalidTerrainMessage extends Marshallable[InvalidTerrainMessage] { + + implicit val codec: Codec[InvalidTerrainMessage] = ( + ("player_guid" | PlanetSideGUID.codec) :: + ("vehicle_guid" | PlanetSideGUID.codec) :: + ("proximity_alert" | TerrainCondition.codec) :: + ("pos" | floatL :: floatL :: floatL).narrow[Vector3]( + { + case x :: y :: z :: HNil => Successful(Vector3(x, y, z)) + }, + v => v.x :: v.y :: v.z :: HNil + )).as[InvalidTerrainMessage] +} diff --git a/src/test/scala/game/InvalidTerrainMessageTest.scala b/src/test/scala/game/InvalidTerrainMessageTest.scala new file mode 100644 index 00000000..ed4795b8 --- /dev/null +++ b/src/test/scala/game/InvalidTerrainMessageTest.scala @@ -0,0 +1,35 @@ +// Copyright (c) 2021 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 InvalidTerrainMessageTest extends Specification { + val string = hex"9a 6c26ce218ddcc922cf8c3c22f0eeaca180" + + "decode" in { + PacketCoding.decodePacket(string).require match { + case InvalidTerrainMessage(player, vehicle, alert, pos) => + player mustEqual PlanetSideGUID(9836) + vehicle mustEqual PlanetSideGUID(8654) + alert mustEqual TerrainCondition.Unsafe + pos mustEqual Vector3(4695.138f, 3969.5388f, 217.86671f) + case _ => + ko + } + } + + "encode" in { + val msg = InvalidTerrainMessage( + PlanetSideGUID(9836), + PlanetSideGUID(8654), + TerrainCondition.Unsafe, + Vector3(4695.138f, 3969.5388f, 217.86671f) + ) + val pkt = PacketCoding.encodePacket(msg).require.toByteVector + pkt mustEqual string + } +}