diff --git a/common/src/main/scala/net/psforever/packet/game/BuildingInfoUpdateMessage.scala b/common/src/main/scala/net/psforever/packet/game/BuildingInfoUpdateMessage.scala index 6e8b52ab..c60029b2 100644 --- a/common/src/main/scala/net/psforever/packet/game/BuildingInfoUpdateMessage.scala +++ b/common/src/main/scala/net/psforever/packet/game/BuildingInfoUpdateMessage.scala @@ -16,6 +16,13 @@ object PlanetSideGeneratorState extends Enumeration { implicit val codec = PacketHelpers.createEnumerationCodec(this, uintL(2)) } +final case class Additional1(unk1 : String, + unk2 : Int, + unk3 : Long) + +final case class Additional3(unk1 : Boolean, + unk2 : Int) + /** * BuildingInfoUpdateMessage is sent for all bases, towers, and warpgates from all continents upon login. */ @@ -27,6 +34,7 @@ final case class BuildingInfoUpdateMessage(continent_guid : PlanetSideGUID, hack_time_remaining : Long, empire_own : PlanetSideEmpire.Value, unk1 : Long, + unk1x : Option[Additional1], generator_state : PlanetSideGeneratorState.Value, spawn_tubes_normal : Boolean, force_dome_active : Boolean, @@ -36,6 +44,7 @@ final case class BuildingInfoUpdateMessage(continent_guid : PlanetSideGUID, unk5 : Long, unk6 : Boolean, unk7 : Int, + unk7x : Option[Additional3], boost_spawn_pain : Boolean, boost_generator_pain : Boolean) extends PlanetSideGamePacket { @@ -45,6 +54,17 @@ final case class BuildingInfoUpdateMessage(continent_guid : PlanetSideGUID, } object BuildingInfoUpdateMessage extends Marshallable[BuildingInfoUpdateMessage] { + private val additional1_codec : Codec[Additional1] = ( + ("unk1" | PacketHelpers.encodedWideStringAligned(3)) :: + ("unk2" | uint8L) :: + ("unk3" | uint32L) + ).as[Additional1] + + private val additional3_codec : Codec[Additional3] = ( + ("unk1" | bool) :: + ("unk2" | uint2L) + ).as[Additional3] + implicit val codec : Codec[BuildingInfoUpdateMessage] = ( ("continent_guid" | PlanetSideGUID.codec) :: ("building_guid" | PlanetSideGUID.codec) :: @@ -53,19 +73,22 @@ object BuildingInfoUpdateMessage extends Marshallable[BuildingInfoUpdateMessage] ("empire_hack" | PlanetSideEmpire.codec) :: ("hack_time_remaining" | uint32L ) :: //In milliseconds ("empire_own" | PlanetSideEmpire.codec) :: - ("unk1" | uint32L) :: //TODO: string, uint16L, and uint32L follow if unk1 != 0 - - ("generator_state" | PlanetSideGeneratorState.codec) :: - ("spawn_tubes_normal" | bool) :: - ("force_dome_active" | bool) :: - ("lattice_benefit" | uintL(5)) :: //5 possible benefits, bitwise combination. (MSB)5:Tech 4:Inter 3:Bio 2:Drop 1:Amp(LSB) - ("unk3" | uintL(10)) :: //Module related. 0x3FF gives all modules with no timer. Unclear how this works. - ("unk4" | uint4L) :: //TODO: additional fields if unk4 > 0 - - ("unk5" | uint32L) :: - ("unk6" | bool) :: - ("unk7" | uint4L) :: //TODO: bool and uintL(2) follow if unk7 != 8 - ("boost_spawn_pain" | bool) :: - ("boost_generator_pain" | bool) + (("unk1" | uint32L) >>:~ { unk1 => + conditional(unk1 != 0L, "unk1x" | additional1_codec) :: + ("generator_state" | PlanetSideGeneratorState.codec) :: + ("spawn_tubes_normal" | bool) :: + ("force_dome_active" | bool) :: + ("lattice_benefit" | uintL(5)) :: //5 possible benefits, bitwise combination. (MSB)5:Tech 4:Inter 3:Bio 2:Drop 1:Amp(LSB) + ("unk3" | uintL(10)) :: //Module related. 0x3FF gives all modules with no timer. Unclear how this works. + ("unk4" | uint4L) :: + //TODO: additional fields if unk4 > 0 + ("unk5" | uint32L) :: + ("unk6" | bool) :: + (("unk7" | uint4L) >>:~ { unk7 => + conditional(unk7 != 8, "unk7x" | additional3_codec) :: + ("boost_spawn_pain" | bool) :: + ("boost_generator_pain" | bool) + }) + }) ).as[BuildingInfoUpdateMessage] } diff --git a/common/src/test/scala/GamePacketTest.scala b/common/src/test/scala/GamePacketTest.scala index 769c9704..635a9508 100644 --- a/common/src/test/scala/GamePacketTest.scala +++ b/common/src/test/scala/GamePacketTest.scala @@ -1872,6 +1872,7 @@ class GamePacketTest extends Specification { hack_time_remaining : Long, empire_own : PlanetSideEmpire.Value, unk1 : Long, + unk1x : Option[Additional1], generator_state : PlanetSideGeneratorState.Value, spawn_tubes_normal : Boolean, force_dome_active : Boolean, @@ -1881,6 +1882,7 @@ class GamePacketTest extends Specification { unk5 : Long, unk6 : Boolean, unk7 : Int, + unk7x : Option[Additional3], boost_spawn_pain : Boolean, boost_generator_pain : Boolean) => continent_guid mustEqual PlanetSideGUID(4) @@ -1891,6 +1893,7 @@ class GamePacketTest extends Specification { hack_time_remaining mustEqual 0 empire_own mustEqual PlanetSideEmpire.NC unk1 mustEqual 0 + unk1x mustEqual None generator_state mustEqual PlanetSideGeneratorState.Normal spawn_tubes_normal mustEqual true force_dome_active mustEqual false @@ -1900,6 +1903,7 @@ class GamePacketTest extends Specification { unk5 mustEqual 0 unk6 mustEqual false unk7 mustEqual 8 + unk7x mustEqual None boost_spawn_pain mustEqual false boost_generator_pain mustEqual false case default => @@ -1916,6 +1920,7 @@ class GamePacketTest extends Specification { 0, PlanetSideEmpire.NC, 0, + None, PlanetSideGeneratorState.Normal, true, false, @@ -1925,6 +1930,7 @@ class GamePacketTest extends Specification { 0, false, 8, + None, false, false) val pkt = PacketCoding.EncodePacket(msg).require.toByteVector diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index 4a5fd72c..ffd14068 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -200,6 +200,7 @@ class WorldSessionActor extends Actor with MDCContextAware { 600000, //10 minutes remaining for hack PlanetSideEmpire.VS, //Base owned by VS 0, //!! Field != 0 will cause malformed packet. See class def. + None, PlanetSideGeneratorState.Critical, //Generator critical true, //Respawn tubes destroyed true, //Force dome active @@ -209,6 +210,7 @@ class WorldSessionActor extends Actor with MDCContextAware { 0, false, 8, //!! Field != 8 will cause malformed packet. See class def. + None, true, //Boosted spawn room pain field true))) //Boosted generator room pain field