From 37ad423820b0a069b6e40360c8259196ab88a890 Mon Sep 17 00:00:00 2001 From: Chord Date: Sun, 15 Dec 2019 21:45:14 -0500 Subject: [PATCH] Packet: Fix VNL packet to support multiple servers --- .../packet/game/VNLWorldStatusMessage.scala | 36 ++++++++++++------- .../game/VNLWorldStatusMessageTest.scala | 27 ++++++-------- .../src/main/scala/LoginSessionActor.scala | 7 ++-- 3 files changed, 40 insertions(+), 30 deletions(-) diff --git a/common/src/main/scala/net/psforever/packet/game/VNLWorldStatusMessage.scala b/common/src/main/scala/net/psforever/packet/game/VNLWorldStatusMessage.scala index 75ac8289..f11b9850 100644 --- a/common/src/main/scala/net/psforever/packet/game/VNLWorldStatusMessage.scala +++ b/common/src/main/scala/net/psforever/packet/game/VNLWorldStatusMessage.scala @@ -30,7 +30,8 @@ final case class WorldInformation(name : String, status : WorldStatus.Value, connections : Vector[WorldConnectionInfo], empireNeed : PlanetSideEmpire.Value) -final case class VNLWorldStatusMessage(welcomeMessage : String, worlds : Vector[WorldInformation]) +final case class VNLWorldStatusMessage(welcomeMessage : String, world_count : Int, world : WorldInformation, + other_worlds : Vector[WorldInformation] = Vector()) extends PlanetSideGamePacket { type Packet = VNLWorldStatusMessage def opcode = GamePacketOpcode.VNLWorldStatusMessage @@ -99,17 +100,28 @@ object VNLWorldStatusMessage extends Marshallable[VNLWorldStatusMessage] { (bytes(4) :: uint16L).xmap(decode, encode).as[WorldConnectionInfo] } + implicit val world_codec : Codec[WorldInformation] = ( + ("world_name" | PacketHelpers.encodedString) :: ( + ("status_and_type" | statusCodec) :+ + // TODO: limit the size of this vector to 11 as the client will fail on any more + ("connections" | vectorOfN(uint8L, connectionCodec)) + :+ + ("empire_need" | PlanetSideEmpire.codec) + )).as[WorldInformation] + + implicit val world_codec_aligned : Codec[WorldInformation] = ( + ("world_name" | PacketHelpers.encodedStringAligned(6)) :: ( + ("status_and_type" | statusCodec) :+ + // TODO: limit the size of this vector to 11 as the client will fail on any more + ("connections" | vectorOfN(uint8L, connectionCodec)) + :+ + ("empire_need" | PlanetSideEmpire.codec) + )).as[WorldInformation] + implicit val codec : Codec[VNLWorldStatusMessage] = ( ("welcome_message" | PacketHelpers.encodedWideString) :: - ("worlds" | vectorOfN(uint8L, ( - // XXX: this needs to be limited to 0x20 bytes - // XXX: this needs to be byte aligned, but not sure how to do this - ("world_name" | PacketHelpers.encodedString) :: ( - ("status_and_type" | statusCodec) :+ - // TODO: limit the size of this vector to 11 as the client will fail on any more - ("connections" | vectorOfN(uint8L, connectionCodec)) :+ - ("empire_need" | PlanetSideEmpire.codec) - ) - ).as[WorldInformation] - ))).as[VNLWorldStatusMessage] + (("num_worlds" | uint8L) flatPrepend { num_worlds => + ("primary_world" | world_codec) :: + ("extra_worlds" | vectorOfN(provide(num_worlds-1), world_codec_aligned) + )})).as[VNLWorldStatusMessage] } diff --git a/common/src/test/scala/game/VNLWorldStatusMessageTest.scala b/common/src/test/scala/game/VNLWorldStatusMessageTest.scala index 78f6af4c..23a5a789 100644 --- a/common/src/test/scala/game/VNLWorldStatusMessageTest.scala +++ b/common/src/test/scala/game/VNLWorldStatusMessageTest.scala @@ -16,12 +16,9 @@ class VNLWorldStatusMessageTest extends Specification { "decode" in { PacketCoding.DecodePacket(string).require match { - case VNLWorldStatusMessage(message, worlds) => - worlds.length mustEqual 1 + case VNLWorldStatusMessage(message, _, world, extra_worlds) => + extra_worlds.length mustEqual 0 message mustEqual "Welcome to PlanetSide! " - val world = worlds { - 0 - } world.name mustEqual "gemini" world.empireNeed mustEqual PlanetSideEmpire.NC world.status mustEqual WorldStatus.Up @@ -39,13 +36,11 @@ class VNLWorldStatusMessageTest extends Specification { } "encode" in { - val msg = VNLWorldStatusMessage("Welcome to PlanetSide! ", - Vector( - WorldInformation("gemini", WorldStatus.Up, ServerType.Released, - Vector( - WorldConnectionInfo(new InetSocketAddress(InetAddress.getByName("64.37.158.69"), 30007)) - ), PlanetSideEmpire.NC - ) + val msg = VNLWorldStatusMessage("Welcome to PlanetSide! ", 1, + WorldInformation("gemini", WorldStatus.Up, ServerType.Released, + Vector( + WorldConnectionInfo(new InetSocketAddress(InetAddress.getByName("64.37.158.69"), 30007)) + ), PlanetSideEmpire.NC ) ) //0100 04 00 01459e2540377540 @@ -56,15 +51,15 @@ class VNLWorldStatusMessageTest extends Specification { } "encode and decode multiple worlds" in { - val msg = VNLWorldStatusMessage("Welcome to PlanetSide! ", + val msg = VNLWorldStatusMessage("Welcome to PlanetSide! ", 2, + WorldInformation("ABCDABCD1", WorldStatus.Up, ServerType.Released, Vector(), PlanetSideEmpire.NC), Vector( - WorldInformation("PSForever1", WorldStatus.Up, ServerType.Released, Vector(), PlanetSideEmpire.NC), - WorldInformation("PSForever2", WorldStatus.Down, ServerType.Beta, Vector(), PlanetSideEmpire.TR) + WorldInformation("ABCDABCD2", WorldStatus.Down, ServerType.Beta, Vector(), PlanetSideEmpire.TR) )) val pkt = PacketCoding.EncodePacket(msg).require.toByteVector - //println(pkt) + println(pkt) // TODO: actually test something ok diff --git a/pslogin/src/main/scala/LoginSessionActor.scala b/pslogin/src/main/scala/LoginSessionActor.scala index 55e234d6..e9f49171 100644 --- a/pslogin/src/main/scala/LoginSessionActor.scala +++ b/pslogin/src/main/scala/LoginSessionActor.scala @@ -164,10 +164,13 @@ class LoginSessionActor extends Actor with MDCContextAware { } def updateServerList() = { - val msg = VNLWorldStatusMessage("Welcome to PlanetSide! ", + val msg = VNLWorldStatusMessage("Welcome to PlanetSide! ", 2, + WorldInformation( + serverName, WorldStatus.Up, ServerType.Beta, Vector(WorldConnectionInfo(serverAddress)), PlanetSideEmpire.VS + ), Vector( WorldInformation( - serverName, WorldStatus.Up, ServerType.Beta, Vector(WorldConnectionInfo(serverAddress)), PlanetSideEmpire.VS + serverName + "A", WorldStatus.Up, ServerType.Beta, Vector(WorldConnectionInfo(serverAddress)), PlanetSideEmpire.TR ) ) )