From b1615aa4d97d9a55056c48f799c221a2062631ce Mon Sep 17 00:00:00 2001 From: FateJH Date: Thu, 22 Sep 2016 16:28:09 -0400 Subject: [PATCH] alternate constructor for HotSpotInfo; testing; updated commentary --- .../packet/game/HotSpotUpdateMessage.scala | 41 +++++++++++++------ common/src/test/scala/GamePacketTest.scala | 29 +++++++++++++ 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/common/src/main/scala/net/psforever/packet/game/HotSpotUpdateMessage.scala b/common/src/main/scala/net/psforever/packet/game/HotSpotUpdateMessage.scala index ec0f4f45..4c520e53 100644 --- a/common/src/main/scala/net/psforever/packet/game/HotSpotUpdateMessage.scala +++ b/common/src/main/scala/net/psforever/packet/game/HotSpotUpdateMessage.scala @@ -10,11 +10,14 @@ import scodec.codecs._ *
* The origin point is the lowest left corner of the map grid. * The coordinates of the hotspot do not match up to the map's internal coordinate system - what you learn using the `/loc` command. - * Hotspot coordinates ranges across from 0 (`000`) to 4096 (`FFF`) on both axes. - * The scale is typically set as 128 (`80000`) but can also be made smaller or even made absurdly big. - * @param unk1 na + * Hotspot coordinates range across from 0 (`000`) to 4096 (`FFF`) on both axes. + * The scale is typically set as 128 (`80000`) but can also be made smaller or even made absurdly big.
+ *
+ * Exploration:
+ * Are those really unknown values or are they just extraneous spacers between the components of the coordinates? + * @param unk1 na; always zero? * @param x the x-coord of the center of the hotspot - * @param unk2 na + * @param unk2 na; always zero? * @param y the y-coord of the center of the hotspot * @param scale how big the hotspot explosion icon appears */ @@ -25,23 +28,24 @@ final case class HotSpotInfo(unk1 : Int, scale : Int) /** - * A list of data for creating hotspots on a continental map.
+ * A list of data for creating hotspots on a continental map. + * Hotspots indicate player activity, almost always some form of combat or aggressive encounter.
*
- * The hotspot system is a forgetful all-or-nothing affair. - * The packet that is always initially sent during server login clears any would-be hotspots from the map. - * Each time a hotspot packet is received for a zone, all of the previous hotspots for that zone are forgotten. - * To simply add a hotspot, the next packet has to contain information that re-explains the packets that were originally rendered.
+ * The hotspot system is an all-or-nothing affair. + * The received packet indicates the hotspots to display and the map will display only those hotspots. + * Inversely, if the received packet indicates no hotspots, the map will display no hotspots at all. + * This "no hotspots" packet is always initially sent during zone setup during server login. + * To clear away only some hotspots, but retains others, a continental `List` would have to be pruned selectively for the client.
*
- * Exploration 1:
+ * Exploration:
* The unknown parameter has been observed with various non-zero values such as 1, 2, and 5. * Visually, however, `unk` does not affect anything. + * (Originally, I thought it might be a layering index but that is incorrect.) * Does it do something internally? * @param continent_guid the zone (continent) * @param unk na - * @param spots a List of HotSpotInfo, or `Nil` if empty + * @param spots a List of HotSpotInfo */ -// TODO need aligned/padded list support -// TODO test with sendRawResponse(hex"9F 0D00 5 02 0 00 D07 00 8CA 00020 00 BEA 00 4C4 40000") final case class HotSpotUpdateMessage(continent_guid : PlanetSideGUID, unk : Int, spots : List[HotSpotInfo] = Nil) @@ -59,6 +63,17 @@ object HotSpotInfo extends Marshallable[HotSpotInfo] { ("y" | uintL(12)) :: ("scale" | uintL(20)) }.as[HotSpotInfo] + + /** + * This alternate constructor ignores the unknown values. + * @param x the x-coord of the center of the hotspot + * @param y the y-coord of the center of the hotspot + * @param scale how big the hotspot explosion icon appears + * @return valid HotSpotInfo + */ + def apply(x : Int, y : Int, scale : Int) : HotSpotInfo = { + HotSpotInfo(0, x, 0 ,y, scale) + } } object HotSpotUpdateMessage extends Marshallable[HotSpotUpdateMessage] { diff --git a/common/src/test/scala/GamePacketTest.scala b/common/src/test/scala/GamePacketTest.scala index 457791c5..1490b5b2 100644 --- a/common/src/test/scala/GamePacketTest.scala +++ b/common/src/test/scala/GamePacketTest.scala @@ -5,6 +5,7 @@ import org.specs2.mutable._ import net.psforever.packet._ import net.psforever.packet.game._ import net.psforever.types._ +import scodec.Attempt import scodec.Attempt.Successful import scodec.bits._ @@ -915,6 +916,34 @@ class GamePacketTest extends Specification { } } + "HotSpotInfo" should { + val string = hex"00 D0 70 08 CA 80 00 00" // note: completing that last byte is required to avoid it being placed at the start of the vector + "decode" in { + HotSpotInfo.codec.decode(string.toBitVector) match { + case Attempt.Successful(decoded) => + decoded.value.x mustEqual 2000 + decoded.value.y mustEqual 2700 + decoded.value.scale mustEqual 128 + case _ => + ko + } + } + + "encode (long-hand)" in { + val msg = HotSpotInfo(0, 2000, 0, 2700, 128) + val pkt = HotSpotInfo.codec.encode(msg).require.toByteVector + + pkt mustEqual string + } + + "encode (short-hand)" in { + val msg = HotSpotInfo(2000, 2700, 128) + val pkt = HotSpotInfo.codec.encode(msg).require.toByteVector + + pkt mustEqual string + } + } + "HotSpotUpdateMessage" should { val stringClear = hex"9F 0500 1 00 0" val stringOne = hex"9F 0500 1 01 0 00 2E9 00 145 80000 0"