From e68c912ecbfea0d557463836ca69d4f184938219 Mon Sep 17 00:00:00 2001 From: Resaec Date: Sun, 24 Dec 2023 05:14:27 +0100 Subject: [PATCH] Implement the VoiceHostRequest message --- .../packet/game/VoiceHostRequest.scala | 35 +++++--- .../scala/game/VoiceHostRequestTest.scala | 81 ++++++++++++++++--- 2 files changed, 93 insertions(+), 23 deletions(-) diff --git a/src/main/scala/net/psforever/packet/game/VoiceHostRequest.scala b/src/main/scala/net/psforever/packet/game/VoiceHostRequest.scala index 363cd124..2e143231 100644 --- a/src/main/scala/net/psforever/packet/game/VoiceHostRequest.scala +++ b/src/main/scala/net/psforever/packet/game/VoiceHostRequest.scala @@ -1,31 +1,40 @@ // Copyright (c) 2017 PSForever package net.psforever.packet.game -import net.psforever.packet.{GamePacketOpcode, Marshallable, PlanetSideGamePacket} -import net.psforever.types.PlanetSideGUID +import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket} import scodec.Codec -import scodec.bits.ByteVector import scodec.codecs._ /** * Used by PlanetSide in conjunction with wiredred/pscs.exe to establish local platoon/squad voice chat. * We are not focusing on implementation of this feature. * At the most, we will merely record data about who requested it. - * @param unk na - * @param player_guid the player who sent this request - * @param data everything else + * + * @param remote_host true if the player provides info for a remote host (remote_ip) + * @param port the port to connect to + * @param bandwidth the bandwidth set by the player (valid values are 3, 201, 203) + * @param remote_ip the IP of the remote voice server, only set if remote_host == true */ -final case class VoiceHostRequest(unk: Boolean, player_guid: PlanetSideGUID, data: ByteVector) - extends PlanetSideGamePacket { - type Packet = VoiceHostRequest +final case class VoiceHostRequest( + remote_host: Boolean, + port: Int, + bandwidth: Int, + remote_ip: String +) extends PlanetSideGamePacket { + require(port > 0) + require(port <= 65535) + require(bandwidth == 3 || bandwidth == 201 || bandwidth == 203) + require(remote_host == (remote_ip != "")) + def opcode = GamePacketOpcode.VoiceHostRequest def encode = VoiceHostRequest.encode(this) } object VoiceHostRequest extends Marshallable[VoiceHostRequest] { implicit val codec: Codec[VoiceHostRequest] = ( - ("unk" | bool) :: - ("player_guid" | PlanetSideGUID.codec) :: - ("data" | bytes) - ).as[VoiceHostRequest] + ("remote_host" | bool) :: + ("port" | uint16L) :: + ("bandwidth" | uint8L) :: + ("remote_ip" | PacketHelpers.encodedStringAligned(7)) + ).as[VoiceHostRequest] } diff --git a/src/test/scala/game/VoiceHostRequestTest.scala b/src/test/scala/game/VoiceHostRequestTest.scala index 82ef72a2..51cae071 100644 --- a/src/test/scala/game/VoiceHostRequestTest.scala +++ b/src/test/scala/game/VoiceHostRequestTest.scala @@ -4,26 +4,87 @@ package game import org.specs2.mutable._ import net.psforever.packet._ import net.psforever.packet.game._ -import net.psforever.types.PlanetSideGUID import scodec.bits._ class VoiceHostRequestTest extends Specification { - val string_request = hex"b0 2580 00" + val string_request_local_75_high = hex"b0 25 80 01c000" + val string_request_local_1111_mid = hex"b0 2b 82 64c000" + val string_request_local_1112_mid = hex"b0 2c 02 64c000" + val string_request_remote_12345_high = hex"b0 9c 98 01c780 3131312e3232322e3132332e323334" - "decode" in { - PacketCoding.decodePacket(string_request).require match { - case VoiceHostRequest(unk, player, _) => - unk mustEqual false - player mustEqual PlanetSideGUID(75) + "decode local 75 high" in { + PacketCoding.decodePacket(string_request_local_75_high).require match { + case VoiceHostRequest(remote_host, port, bandwidth, data) => + remote_host mustEqual false + port mustEqual 75 + bandwidth mustEqual 3 + data mustEqual "" case _ => ko } } - "encode" in { - val msg = VoiceHostRequest(false, PlanetSideGUID(75), ByteVector.empty) + "encode local 75 high" in { + val msg = VoiceHostRequest(remote_host = false, 75, 3, "") val pkt = PacketCoding.encodePacket(msg).require.toByteVector - pkt mustEqual string_request + pkt mustEqual string_request_local_75_high + } + + "decode local 1111 mid" in { + PacketCoding.decodePacket(string_request_local_1111_mid).require match { + case VoiceHostRequest(remote_host, port, bandwidth, data) => + remote_host mustEqual false + port mustEqual 1111 + bandwidth mustEqual 201 + data mustEqual "" + case _ => + ko + } + } + + "encode local 1111 mid" in { + val msg = VoiceHostRequest(remote_host = false, 1111, 201, "") + val pkt = PacketCoding.encodePacket(msg).require.toByteVector + + pkt mustEqual string_request_local_1111_mid + } + + "decode local 1112 mid" in { + PacketCoding.decodePacket(string_request_local_1112_mid).require match { + case VoiceHostRequest(remote_host, port, bandwidth, data) => + remote_host mustEqual false + port mustEqual 1112 + bandwidth mustEqual 201 + data mustEqual "" + case _ => + ko + } + } + + "encode local 1112 mid" in { + val msg = VoiceHostRequest(remote_host = false, 1112, 201, "") + val pkt = PacketCoding.encodePacket(msg).require.toByteVector + + pkt mustEqual string_request_local_1112_mid + } + + "decode remote 12345 high" in { + PacketCoding.decodePacket(string_request_remote_12345_high).require match { + case VoiceHostRequest(remote, port, codec, server_ip) => + remote mustEqual true + port mustEqual 12345 + codec mustEqual 3 + server_ip mustEqual "111.222.123.234" + case _ => + ko + } + } + + "encode remote 12345 high" in { + val msg = VoiceHostRequest(remote_host = true, port = 12345, bandwidth = 3, remote_ip = "111.222.123.234") + val pkt = PacketCoding.encodePacket(msg).require.toByteVector + + pkt mustEqual string_request_remote_12345_high } }