diff --git a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala index 21ae82f69..d66750f7b 100644 --- a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala +++ b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala @@ -561,7 +561,7 @@ object GamePacketOpcode extends Enumeration { case 0xca => noDecoder(OutfitBenefitMessage) case 0xcb => noDecoder(EmpireChangeTimeMessage) case 0xcc => noDecoder(ClockCalibrationMessage) - case 0xcd => noDecoder(DensityLevelUpdateMessage) + case 0xcd => game.DensityLevelUpdateMessage.decode case 0xce => noDecoder(ActOfGodMessage) case 0xcf => noDecoder(AvatarAwardMessage) diff --git a/common/src/main/scala/net/psforever/packet/game/DelayedPathMountMsg.scala b/common/src/main/scala/net/psforever/packet/game/DelayedPathMountMsg.scala index 4c713e096..643898e6e 100644 --- a/common/src/main/scala/net/psforever/packet/game/DelayedPathMountMsg.scala +++ b/common/src/main/scala/net/psforever/packet/game/DelayedPathMountMsg.scala @@ -1,4 +1,4 @@ -// Copyright (c) 2016 PSForever.net to present +// Copyright (c) 2017 PSForever package net.psforever.packet.game import net.psforever.packet.{GamePacketOpcode, Marshallable, PlanetSideGamePacket} diff --git a/common/src/main/scala/net/psforever/packet/game/DensityLevelUpdateMessage.scala b/common/src/main/scala/net/psforever/packet/game/DensityLevelUpdateMessage.scala new file mode 100644 index 000000000..6ad1bfe65 --- /dev/null +++ b/common/src/main/scala/net/psforever/packet/game/DensityLevelUpdateMessage.scala @@ -0,0 +1,47 @@ +// Copyright (c) 2017 PSForever +package net.psforever.packet.game + +import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket} +import scodec.{Attempt, Codec, Err} +import scodec.codecs._ +import shapeless.{::, HNil} + +/** + * na + * @param zone_id the continent + * @param building_id the building + * @param density na + */ +final case class DensityLevelUpdateMessage(zone_id : PlanetSideGUID, + building_id : PlanetSideGUID, + density : List[Int]) + extends PlanetSideGamePacket { + type Packet = DensityLevelUpdateMessage + def opcode = GamePacketOpcode.DensityLevelUpdateMessage + def encode = DensityLevelUpdateMessage.encode(this) +} + +object DensityLevelUpdateMessage extends Marshallable[DensityLevelUpdateMessage] { + implicit val codec : Codec[DensityLevelUpdateMessage] = ( + ("zone_id" | PlanetSideGUID.codec) :: + ("building_id" | PlanetSideGUID.codec) :: + ("density" | PacketHelpers.listOfNSized(8, uint(3))) + ).exmap[DensityLevelUpdateMessage] ( + { + case a :: b :: c :: HNil => + Attempt.Successful(DensityLevelUpdateMessage(a, b, c)) + }, + { + case DensityLevelUpdateMessage(a, b, c) => + if(c.length != 8) { + Attempt.Failure(Err("list must have 8 entries")) + } + else if(c.count(i => { i < 0 || i > 7 }) > 0) { + Attempt.Failure(Err("list entries must be 0-7 inclusive")) + } + else { + Attempt.Successful(a :: b :: c :: HNil) + } + } + ) +} diff --git a/common/src/test/scala/game/DensityLevelUpdateMessageTest.scala b/common/src/test/scala/game/DensityLevelUpdateMessageTest.scala new file mode 100644 index 000000000..e6775ae10 --- /dev/null +++ b/common/src/test/scala/game/DensityLevelUpdateMessageTest.scala @@ -0,0 +1,52 @@ +// Copyright (c) 2017 PSForever +package game + +import org.specs2.mutable._ +import net.psforever.packet._ +import net.psforever.packet.game._ +import scodec.bits._ + +class DensityLevelUpdateMessageTest extends Specification { + val string = hex"cd 0100 1f4e 000000" + + "decode" in { + PacketCoding.DecodePacket(string).require match { + case DensityLevelUpdateMessage(zone_id, building_id, unk) => + zone_id mustEqual PlanetSideGUID(1) + building_id mustEqual PlanetSideGUID(19999) + unk.length mustEqual 8 + unk.head mustEqual 0 + unk(1) mustEqual 0 + unk(2) mustEqual 0 + unk(3) mustEqual 0 + unk(4) mustEqual 0 + unk(5) mustEqual 0 + unk(6) mustEqual 0 + unk(7) mustEqual 0 + case _ => + ko + } + } + + "encode" in { + val msg = DensityLevelUpdateMessage(PlanetSideGUID(1), PlanetSideGUID(19999), List(0,0, 0,0, 0,0, 0,0)) + val pkt = PacketCoding.EncodePacket(msg).require.toByteVector + + pkt mustEqual string + } + + "encode (failure; wrong number of list entries)" in { + val msg = DensityLevelUpdateMessage(PlanetSideGUID(1), PlanetSideGUID(19999), List(0)) + PacketCoding.EncodePacket(msg).isSuccessful mustEqual false + } + + "encode (failure; list number too big)" in { + val msg1 = DensityLevelUpdateMessage(PlanetSideGUID(1), PlanetSideGUID(19999), List(0,0, 0,0, 0,0, 0,8)) + PacketCoding.EncodePacket(msg1).isSuccessful mustEqual false + } + + "encode (failure; list number too small)" in { + val msg1 = DensityLevelUpdateMessage(PlanetSideGUID(1), PlanetSideGUID(19999), List(0,0, 0,0, 0,-1, 0,0)) + PacketCoding.EncodePacket(msg1).isSuccessful mustEqual false + } +} \ No newline at end of file diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index 1fef2f1f1..4910357cb 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -3059,6 +3059,8 @@ class WorldSessionActor extends Actor with MDCContextAware { false ) ) + sendResponse(DensityLevelUpdateMessage(continentNumber, buildingNumber, List(0,0, 0,0, 0,0, 0,0))) //TODO what is density? + //TODO BroadcastWarpgateUpdateMessage() for warp gates // sendResponse( // BuildingInfoUpdateMessage( // PlanetSideGUID(6), //Ceryshen @@ -3084,8 +3086,6 @@ class WorldSessionActor extends Actor with MDCContextAware { // true //Boosted generator room pain field // ) // ) - //TODO DensityLevelUpdateMessage() - //TODO BroadcastWarpgateUpdateMessage() for warp gates } def configZone(zone : Zone) : Unit = {