diff --git a/common/src/main/scala/net/psforever/packet/game/BattleplanMessage.scala b/common/src/main/scala/net/psforever/packet/game/BattleplanMessage.scala
index 277eb103..fbcbc4da 100644
--- a/common/src/main/scala/net/psforever/packet/game/BattleplanMessage.scala
+++ b/common/src/main/scala/net/psforever/packet/game/BattleplanMessage.scala
@@ -8,25 +8,53 @@ import scodec.codecs._
import shapeless.{::, HNil}
/**
- * A common ancestor of all the different "sheets" used to keep track of the data.
+ * A `Codec` for the actions that each layer of the diagram performs.
+ * `Action1`, `Action2`, `Action5`, `Action6`, and `Action7` have additional `DiagramStroke` input data.
*/
-sealed trait DiagramSheet
+object DiagramActionCode extends Enumeration {
+ type Type = Value
+
+ val Action0,
+ Action1,
+ Action2,
+ Action3,
+ Action4,
+ Action5,
+ Action6,
+ Action7,
+ Action8,
+ Action9,
+ ActionA,
+ ActionB,
+ ActionC,
+ ActionD,
+ ActionE,
+ ActionF
+ = Value //TODO replace these with descriptive wording
+
+ implicit val codec = PacketHelpers.createEnumerationCodec(this, uint4L)
+}
+
+/**
+ * A common ancestor of all the different "strokes" used to keep track of the data.
+ */
+sealed trait DiagramStroke
/**
* na
* @param unk1 na
* @param unk2 na
*/
-final case class SheetOne(unk1 : Float,
- unk2 : Int) extends DiagramSheet
+final case class StrokeOne(unk1 : Float,
+ unk2 : Int) extends DiagramStroke
/**
* na
* @param unk1 na
* @param unk2 na
*/
-final case class SheetTwo(unk1 : Float,
- unk2 : Float) extends DiagramSheet
+final case class StrokeTwo(unk1 : Float,
+ unk2 : Float) extends DiagramStroke
/**
* na
@@ -35,10 +63,10 @@ final case class SheetTwo(unk1 : Float,
* @param unk3 na
* @param unk4 na
*/
-final case class SheetFive(unk1 : Float,
- unk2 : Float,
- unk3 : Float,
- unk4 : Int) extends DiagramSheet
+final case class StrokeFive(unk1 : Float,
+ unk2 : Float,
+ unk3 : Float,
+ unk4 : Int) extends DiagramStroke
/**
* na
@@ -48,37 +76,39 @@ final case class SheetFive(unk1 : Float,
* @param unk4 na
* @param unk5 na
*/
-final case class SheetSix(unk1 : Float,
- unk2 : Float,
- unk3 : Int,
- unk4 : Int,
- unk5 : String) extends DiagramSheet
+final case class StrokeSix(unk1 : Float,
+ unk2 : Float,
+ unk3 : Int,
+ unk4 : Int,
+ unk5 : String) extends DiagramStroke
/**
* na
* @param unk na
*/
-final case class SheetSeven(unk : Int) extends DiagramSheet
+final case class StrokeSeven(unk : Int) extends DiagramStroke
/**
* na
- * @param pageNum a hint to kind of data stored
- * @param sheet the data
+ * @param action the behavior of this stroke;
+ * a hint to kind of stroke data stored, if at all, and how to use it or incorporate prior data
+ * @param stroke the data
*/
-final case class BattleDiagram(pageNum : Int,
- sheet : Option[DiagramSheet] = None)
+final case class BattleDiagramAction(action : DiagramActionCode.Value,
+ stroke : Option[DiagramStroke] = None)
/**
* na
- * @param unk1 na
- * @param mastermind the player who contributed this battle plan
- * @param unk2 na
- * @param diagrams a list of the individual `BattleDiagram`s that compose this plan
+ * @param char_id na;
+ * same as in `CharacterInfoMessage`
+ * @param player_name the player who contributed this battle plan
+ * @param zone_id on which continent the battle plan will be overlaid
+ * @param diagrams a list of the individual actions that compose this plan
*/
-final case class BattleplanMessage(unk1 : Long,
- mastermind : String,
- unk2 : Int,
- diagrams : List[BattleDiagram])
+final case class BattleplanMessage(char_id : Long,
+ player_name : String,
+ zone_id : Int,
+ diagrams : List[BattleDiagramAction])
extends PlanetSideGamePacket {
type Packet = BattleplanMessage
def opcode = GamePacketOpcode.BattleplanMessage
@@ -87,170 +117,170 @@ final case class BattleplanMessage(unk1 : Long,
object BattelplanDiagram {
/**
- * Create a `BattleDiagram` object containing `SheetOne` data.
+ * Create a `BattleDiagramAction` object containing `StrokeOne` data.
* @param unk1 na
* @param unk2 na
- * @return a `BattleDiagram` object
+ * @return a `BattleDiagramAction` object
*/
- def sheet1(unk1 : Float, unk2 : Int) : BattleDiagram =
- BattleDiagram(1, Some(SheetOne(unk1, unk2)))
+ def stroke1(unk1 : Float, unk2 : Int) : BattleDiagramAction =
+ BattleDiagramAction(DiagramActionCode.Action1, Some(StrokeOne(unk1, unk2)))
/**
- * Create a `BattleDiagram` object containing `SheetTwo` data.
+ * Create a `BattleDiagramAction` object containing `StrokeTwo` data.
* @param unk1 na
* @param unk2 na
- * @return a `BattleDiagram` object
+ * @return a `BattleDiagramAction` object
*/
- def sheet2(unk1 : Float, unk2 : Float) : BattleDiagram =
- BattleDiagram(2, Some(SheetTwo(unk1, unk2)))
+ def stroke2(unk1 : Float, unk2 : Float) : BattleDiagramAction =
+ BattleDiagramAction(DiagramActionCode.Action2, Some(StrokeTwo(unk1, unk2)))
/**
- * Create a `BattleDiagram` object containing `SheetFive` data.
+ * Create a `BattleDiagramAction` object containing `StrokeFive` data.
* @param unk1 na
* @param unk2 na
* @param unk3 na
* @param unk4 na
- * @return a `BattleDiagram` object
+ * @return a `BattleDiagramAction` object
*/
- def sheet5(unk1 : Float, unk2 : Float, unk3 : Float, unk4 : Int) : BattleDiagram =
- BattleDiagram(5, Some(SheetFive(unk1, unk2, unk3, unk4)))
+ def stroke5(unk1 : Float, unk2 : Float, unk3 : Float, unk4 : Int) : BattleDiagramAction =
+ BattleDiagramAction(DiagramActionCode.Action5, Some(StrokeFive(unk1, unk2, unk3, unk4)))
/**
- * Create a `BattleDiagram` object containing `SheetSix` data.
+ * Create a `BattleDiagramAction` object containing `StrokeSix` data.
* @param unk1 na
* @param unk2 na
* @param unk3 na
* @param unk4 na
* @param unk5 na
- * @return a `BattleDiagram` object
+ * @return a `BattleDiagramAction` object
*/
- def sheet6(unk1 : Float, unk2 : Float, unk3 : Int, unk4 : Int, unk5 : String) : BattleDiagram =
- BattleDiagram(6, Some(SheetSix(unk1, unk2, unk3, unk4, unk5)))
+ def stroke6(unk1 : Float, unk2 : Float, unk3 : Int, unk4 : Int, unk5 : String) : BattleDiagramAction =
+ BattleDiagramAction(DiagramActionCode.Action6, Some(StrokeSix(unk1, unk2, unk3, unk4, unk5)))
/**
- * Create a `BattleDiagram` object containing `SheetSeven` data.
+ * Create a `BattleDiagramAction` object containing `StrokeSeven` data.
* @param unk na
- * @return a `BattleDiagram` object
+ * @return a `BattleDiagramAction` object
*/
- def sheet7(unk : Int) : BattleDiagram =
- BattleDiagram(7, Some(SheetSeven(unk)))
+ def stroke7(unk : Int) : BattleDiagramAction =
+ BattleDiagramAction(DiagramActionCode.Action7, Some(StrokeSeven(unk)))
}
object BattleplanMessage extends Marshallable[BattleplanMessage] {
/**
- * An intermediary object intended to temporarily store `BattleDiagram` objects.
+ * An intermediary object intended to temporarily store `BattleDiagramAction` objects.
*
* This hidden object is arranged like a linked list;
- * but, later, it is converted into an accessible formal `List` of `BattleDiagram` objects during decoding;
+ * but, later, it is converted into an accessible formal `List` during decoding;
* likewise, during the encoding process, the `List` is transformed back into a linked list structure.
* `Scala`'s own linked list `Collection` is deprecated, without substitution, so this custom one must be used.
- * @param diagram the contained `BattleDiagram` with the sheet that maintains the data
- * @param next the next `BattleDiagramLayer`, if any, arranging into a linked list
+ * @param diagram the contained object that maintains the data
+ * @param next the next `BattleDiagramChain`, if any
*/
- private final case class BattleDiagramLayer(diagram : BattleDiagram,
- next : Option[BattleDiagramLayer])
+ private final case class BattleDiagramChain(diagram : BattleDiagramAction,
+ next : Option[BattleDiagramChain])
/**
- * Parse data into a `SheetOne` object.
+ * Parse data into a `StrokeOne` object.
*/
- private val plan1_codec : Codec[SheetOne] = ( //size: 8; pad: +0
+ private val plan1_codec : Codec[StrokeOne] = ( //size: 8; pad: +0
("unk1" | newcodecs.q_float(0.0, 16.0, 5)) ::
("unk2" | uintL(3))
- ).as[SheetOne]
+ ).as[StrokeOne]
/**
- * Parse data into a `SheetTwo` object.
+ * Parse data into a `StrokeTwo` object.
*/
- private val plan2_codec : Codec[SheetTwo] = ( //size: 22; pad: +2
+ private val plan2_codec : Codec[StrokeTwo] = ( //size: 22; pad: +2
("unk1" | newcodecs.q_float(-4096.0, 12288.0, 11)) ::
("unk2" | newcodecs.q_float(-4096.0, 12288.0, 11))
- ).as[SheetTwo]
+ ).as[StrokeTwo]
/**
- * Parse data into a `SheetFive` object.
+ * Parse data into a `StrokeFive` object.
*/
- private val plan5_codec : Codec[SheetFive] = ( //size: 44; pad: +4
+ private val plan5_codec : Codec[StrokeFive] = ( //size: 44; pad: +4
("unk1" | newcodecs.q_float(-4096.0, 12288.0, 11)) ::
("unk2" | newcodecs.q_float(-4096.0, 12288.0, 11)) ::
("unk3" | newcodecs.q_float(1024.0, 0.0, 11)) ::
("unk4" | uintL(11))
- ).as[SheetFive]
+ ).as[StrokeFive]
/**
- * Parse data into a `SheetSix` object.
+ * Parse data into a `StrokeSix` object.
* @param pad the current padding for the `String` entry
*/
- private def plan6_codec(pad : Int) : Codec[SheetSix] = ( //size: 31 + string.length.field + string.length * 16 + padding; pad: value resets
+ private def plan6_codec(pad : Int) : Codec[StrokeSix] = ( //size: 31 + string.length.field + string.length * 16 + padding; pad: value resets
("unk1" | newcodecs.q_float(-4096.0, 12288.0, 11)) ::
("unk2" | newcodecs.q_float(-4096.0, 12288.0, 11)) ::
("unk3" | uintL(3)) ::
("unk4" | uintL(6)) ::
("unk5" | PacketHelpers.encodedWideStringAligned( (pad + 1) % 8 ))
- ).as[SheetSix]
+ ).as[StrokeSix]
/**
- * Parse data into a `SheetSeven` object.
+ * Parse data into a `StrokeSeven` object.
*/
- private val plan7_codec : Codec[SheetSeven] = ("unk" | uintL(6)).as[SheetSeven] // size: 6; pad: +2
+ private val plan7_codec : Codec[StrokeSeven] = ("unk" | uintL(6)).as[StrokeSeven] // size: 6; pad: +2
/**
- * Switch between different patterns to create a `BattleDiagram` for the following data.
+ * Switch between different patterns to create a `BattleDiagramAction` for the following data.
* @param plan a hint to help parse the following data
* @param pad the current padding for any `String` entry stored within the parsed elements;
* when `plan == 6`, `plan6_codec` utilizes this value
- * @return a `BattleDiagram` object
+ * @return a `BattleDiagramAction` object
*/
- private def diagram_codec(plan : Int, pad : Int) : Codec[BattleDiagram] = (
- conditional(plan == 1, plan1_codec) ::
- conditional(plan == 2, plan2_codec) ::
- conditional(plan == 5, plan5_codec) ::
- conditional(plan == 6, plan6_codec(pad)) ::
- conditional(plan == 7, plan7_codec)
- ).exmap[BattleDiagram] (
+ private def diagram_codec(plan : DiagramActionCode.Value, pad : Int) : Codec[BattleDiagramAction] = (
+ conditional(plan == DiagramActionCode.Action1, plan1_codec) ::
+ conditional(plan == DiagramActionCode.Action2, plan2_codec) ::
+ conditional(plan == DiagramActionCode.Action5, plan5_codec) ::
+ conditional(plan == DiagramActionCode.Action6, plan6_codec(pad)) ::
+ conditional(plan == DiagramActionCode.Action7, plan7_codec)
+ ).exmap[BattleDiagramAction] (
{
- case Some(sheet) :: None :: None :: None :: None :: HNil =>
- Attempt.successful(BattleDiagram(plan, Some(sheet)))
+ case Some(stroke) :: None :: None :: None :: None :: HNil =>
+ Attempt.successful(BattleDiagramAction(plan, Some(stroke)))
- case None :: Some(sheet) :: None :: None :: None :: HNil =>
- Attempt.successful(BattleDiagram(plan, Some(sheet)))
+ case None :: Some(stroke) :: None :: None :: None :: HNil =>
+ Attempt.successful(BattleDiagramAction(plan, Some(stroke)))
- case None :: None :: Some(sheet) :: None :: None :: HNil =>
- Attempt.successful(BattleDiagram(plan, Some(sheet)))
+ case None :: None :: Some(stroke) :: None :: None :: HNil =>
+ Attempt.successful(BattleDiagramAction(plan, Some(stroke)))
- case None :: None :: None :: Some(sheet) :: None :: HNil =>
- Attempt.successful(BattleDiagram(plan, Some(sheet)))
+ case None :: None :: None :: Some(stroke) :: None :: HNil =>
+ Attempt.successful(BattleDiagramAction(plan, Some(stroke)))
- case None :: None :: None :: None :: Some(sheet) :: HNil =>
- Attempt.successful(BattleDiagram(plan, Some(sheet)))
+ case None :: None :: None :: None :: Some(stroke) :: HNil =>
+ Attempt.successful(BattleDiagramAction(plan, Some(stroke)))
case None :: None :: None :: None :: None :: HNil =>
- Attempt.successful(BattleDiagram(plan, None))
+ Attempt.successful(BattleDiagramAction(plan, None))
case _:: _ :: _ :: _ :: _ :: HNil =>
- Attempt.failure(Err(s"too many sheets at once for $plan"))
+ Attempt.failure(Err(s"too many strokes for action $plan"))
},
{
- case BattleDiagram(1, Some(sheet)) =>
- Attempt.successful(Some(sheet.asInstanceOf[SheetOne]) :: None :: None :: None :: None :: HNil)
+ case BattleDiagramAction(DiagramActionCode.Action1, Some(stroke)) =>
+ Attempt.successful(Some(stroke.asInstanceOf[StrokeOne]) :: None :: None :: None :: None :: HNil)
- case BattleDiagram(2, Some(sheet)) =>
- Attempt.successful(None :: Some(sheet.asInstanceOf[SheetTwo]) :: None :: None :: None :: HNil)
+ case BattleDiagramAction(DiagramActionCode.Action2, Some(stroke)) =>
+ Attempt.successful(None :: Some(stroke.asInstanceOf[StrokeTwo]) :: None :: None :: None :: HNil)
- case BattleDiagram(5, Some(sheet)) =>
- Attempt.successful(None :: None :: Some(sheet.asInstanceOf[SheetFive]) :: None :: None :: HNil)
+ case BattleDiagramAction(DiagramActionCode.Action5, Some(stroke)) =>
+ Attempt.successful(None :: None :: Some(stroke.asInstanceOf[StrokeFive]) :: None :: None :: HNil)
- case BattleDiagram(6, Some(sheet)) =>
- Attempt.successful(None :: None :: None :: Some(sheet.asInstanceOf[SheetSix]) :: None :: HNil)
+ case BattleDiagramAction(DiagramActionCode.Action6, Some(stroke)) =>
+ Attempt.successful(None :: None :: None :: Some(stroke.asInstanceOf[StrokeSix]) :: None :: HNil)
- case BattleDiagram(7, Some(sheet)) =>
- Attempt.successful(None :: None :: None :: None :: Some(sheet.asInstanceOf[SheetSeven]) :: HNil)
+ case BattleDiagramAction(DiagramActionCode.Action7, Some(stroke)) =>
+ Attempt.successful(None :: None :: None :: None :: Some(stroke.asInstanceOf[StrokeSeven]) :: HNil)
- case BattleDiagram(_, None) =>
+ case BattleDiagramAction(_, None) =>
Attempt.successful(None :: None :: None :: None :: None :: HNil)
- case BattleDiagram(n, _) =>
- Attempt.failure(Err(s"unhandled sheet number $n"))
+ case BattleDiagramAction(n, _) =>
+ Attempt.failure(Err(s"unhandled stroke action number $n"))
}
)
@@ -260,74 +290,74 @@ object BattleplanMessage extends Marshallable[BattleplanMessage] {
* @param remaining the number of elements remaining to parse
* @param pad the current padding for any `String` entry stored within the parsed elements;
* different elements add different padding offset to this field on subsequent passes
- * @return a `Codec` for `BattleDiagramLayer` objects
+ * @return a `Codec` for `BattleDiagramChain` segments
*/
- private def parse_diagrams_codec(remaining : Int, pad : Int = 0) : Codec[BattleDiagramLayer] = (
- uint4L >>:~ { plan =>
+ private def parse_diagrams_codec(remaining : Int, pad : Int = 0) : Codec[BattleDiagramChain] = (
+ DiagramActionCode.codec >>:~ { plan =>
("diagram" | diagram_codec(plan, pad)) ::
conditional(remaining > 1,
"next" | parse_diagrams_codec(
remaining - 1,
- pad + (if(plan == 2 || plan == 7) { 2 } else if(plan == 5) { 4 } else if(plan == 6) { -pad } else { 0 })
+ pad + (if(plan == DiagramActionCode.Action2 || plan == DiagramActionCode.Action7) { 2 } else if(plan == DiagramActionCode.Action5) { 4 } else if(plan == DiagramActionCode.Action6) { -pad } else { 0 })
)
)
- }).exmap[BattleDiagramLayer] (
+ }).exmap[BattleDiagramChain] (
{
case _ :: diagram :: next :: HNil =>
- Attempt.successful(BattleDiagramLayer(diagram, next))
+ Attempt.successful(BattleDiagramChain(diagram, next))
},
{
- case BattleDiagramLayer(BattleDiagram(num, sheet), next) =>
- Attempt.successful(num :: BattleDiagram(num, sheet) :: next :: HNil)
+ case BattleDiagramChain(BattleDiagramAction(num, stroke), next) =>
+ Attempt.successful(num :: BattleDiagramAction(num, stroke) :: next :: HNil)
}
)
import scala.collection.mutable.ListBuffer
/**
- * Transform a linked list of `BattleDiagramLayer` into a `List` of `BattleDiagram` objects.
- * @param element the current link in a chain of `BattleDiagramLayer` objects
+ * Transform a linked list of `BattleDiagramChain` into a `List` of `BattleDiagramAction` objects.
+ * @param element the current link in a chain of `BattleDiagramChain` objects
* @param list a `List` of extracted `BattleDiagrams`;
* technically, the output
*/
- private def rollDiagramLayers(element : BattleDiagramLayer, list : ListBuffer[BattleDiagram]) : Unit = {
+ private def rollDiagramLayers(element : BattleDiagramChain, list : ListBuffer[BattleDiagramAction]) : Unit = {
list += element.diagram
if(element.next.isDefined)
rollDiagramLayers(element.next.get, list) //tail call optimization
}
/**
- * Transform a `List` of `BattleDiagram` objects into a linked list of `BattleDiagramLayer` objects.
+ * Transform a `List` of `BattleDiagramAction` objects into a linked list of `BattleDiagramChain` objects.
* @param revIter a reverse `List` `Iterator` for a `List` of `BattleDiagrams`
- * @param layers the current head of a chain of `BattleDiagramLayer` objects;
+ * @param layers the current head of a chain of `BattleDiagramChain` objects;
* technically, the output
- * @return a linked list of `BattleDiagramLayer` objects
+ * @return a linked list of `BattleDiagramChain` objects
*/
- private def unrollDiagramLayers(revIter : Iterator[BattleDiagram], layers : Option[BattleDiagramLayer] = None) : Option[BattleDiagramLayer] = {
+ private def unrollDiagramLayers(revIter : Iterator[BattleDiagramAction], layers : Option[BattleDiagramChain] = None) : Option[BattleDiagramChain] = {
if(!revIter.hasNext)
return layers
- val elem : BattleDiagram = revIter.next
- unrollDiagramLayers(revIter, Some(BattleDiagramLayer(elem, layers))) //tail call optimization
+ val elem : BattleDiagramAction = revIter.next
+ unrollDiagramLayers(revIter, Some(BattleDiagramChain(elem, layers))) //tail call optimization
}
implicit val codec : Codec[BattleplanMessage] = (
- ("unk1" | uint32L) ::
- ("mastermind" | PacketHelpers.encodedWideString) ::
- ("unk2" | uint16L) ::
+ ("char_id" | uint32L) ::
+ ("player_name" | PacketHelpers.encodedWideString) ::
+ ("zone_id" | uint16L) ::
(uint8L >>:~ { count =>
conditional(count > 0, "diagrams" | parse_diagrams_codec(count)).hlist
})
).exmap[BattleplanMessage] (
{
- case unk1 :: unk2 :: unk3 :: _ :: diagramLayers :: HNil =>
- val list : ListBuffer[BattleDiagram] = new ListBuffer()
+ case char_id :: player :: zone_id :: _ :: diagramLayers :: HNil =>
+ val list : ListBuffer[BattleDiagramAction] = new ListBuffer()
if(diagramLayers.isDefined)
rollDiagramLayers(diagramLayers.get, list)
- Attempt.successful(BattleplanMessage(unk1, unk2, unk3, list.toList))
+ Attempt.successful(BattleplanMessage(char_id, player, zone_id, list.toList))
},
{
- case BattleplanMessage(unk1, unk2, unk3, diagrams) =>
- val layersOpt = unrollDiagramLayers(diagrams.reverseIterator)
- Attempt.successful(unk1 :: unk2 :: unk3 :: diagrams.size :: layersOpt :: HNil)
+ case BattleplanMessage(char_id, player_name, zone_id, diagrams) =>
+ val layersOpt : Option[BattleDiagramChain] = unrollDiagramLayers(diagrams.reverseIterator)
+ Attempt.successful(char_id :: player_name :: zone_id :: diagrams.size :: layersOpt :: HNil)
}
)
}
diff --git a/common/src/test/scala/game/BattleplanMessageTest.scala b/common/src/test/scala/game/BattleplanMessageTest.scala
index 2eb171bd..860ee0dd 100644
--- a/common/src/test/scala/game/BattleplanMessageTest.scala
+++ b/common/src/test/scala/game/BattleplanMessageTest.scala
@@ -8,17 +8,34 @@ import scodec.bits._
class BattleplanMessageTest extends Specification {
val string = hex"b3 3a197902 94 59006500740041006e006f0074006800650072004600610069006c0075007200650041006c007400 0000 01 e0"
+ //0xb3856477028c4f0075007400730074006100620075006c006f00750073000a00202aba2b4aae8bd2aba334aae8dd2aca3b4ab28fd2aca414ab29152aca474ab292d2ada4d4ab69452ada534ab695d2ada594ab696d2ada5d4ab697d2ada614ab698d2ada654ab699d2ada694ab69ad2aea6d4aba9bd2aea714aba9cd2aea754aba9dd2aea794aba9ed
+ //0xb3856477028c4f0075007400730074006100620075006c006f00750073000a002025ca4d497292525ca47497291525ca4149728f525ca3b49728dd25ca3549728cd25ca3149728bd25ca2d49728ad25ca29497289d25ca25497288d25ca21497287d25ca1d497286d25ca19497285d25ca15497284d25da11497683d25da0d497682d25da09497681d
+ //0xb3856477028c4f0075007400730074006100620075006c006f00750073000a002025da05497680d25da014976ffc25dbfd0976fec25dbf90976fdc25dbf50976fcc25dbf10976fbc25dbed0976fac25dbe90976f9425dbe30972f8425cbdd0972f6425cbd70972f4c25bbcf096ef2c25bbc9096ef1c25bbc5096ef0425bbbf096eef425bbbb096eee4
+ //0xb3856477028c4f0075007400730074006100620075006c006f00750073000a002027aa4349ea90527aa3f49ea8f527aa3b49ea8e527ba3749ee8d527ba3349ee8bd27ba2d49ee8ad27ca2949f289d27ca2549f288d27ca2149f287d27da1d49f686d27da1749fa85527ea1349fa84527ea0f49fe83527fa0b49fe82527fa0749fe81527fa0349fe805
+ //0xb3856477028c4f0075007400730074006100620075006c006f00750073000a00202a8bbb0aa6eec2a9bbd0aa6efc2a9bc10aa6f0c2a9bc50aa6f1c2a9bc90aa6f2c2a9bcf0aa6f442a9bd30aa6f542a9bd70aa6f642a9bdb0aa6f742a9bdf0aa6f842a9be30aa6f942a9be70aa6fa42a9beb0aa6fb42a9bef0aa6fcc2a9bf50aa6fdc2a9bf90aa6ff4
+ //0xb3856477028c4f0075007400730074006100620075006c006f00750073000a00201b127ba8949eea1d27ba8549eea0527aa7f49ea9f527aa7b49ea9e527aa7749ea9d527aa7349ea9c527aa6f49ea9ad27aa6949ea99d27aa6349ea98527aa5f49ea97527aa5b49ea96527aa5549ea94d27aa5149ea93d27aa4d49ea92d27aa4949ea91d27aa4540
+ //0xb3856477028c4f0075007400730074006100620075006c006f00750073000a001e27fbff09feff427fbfb09fafe427ebf709fafd427ebf309f6fcc27dbf109f6fbc27dbed09f2fac27cbe909f2f9c27cbe509eef8c27bbe109eef7c27abdd09eaf6c27abd909eaf5c27abd509e6f54279bd309e6f44279bcf09e6f34279bcb09e6f240
+ //0xb3856477028c4f0075007400730074006100620075006c006f00750073000a0020891b1260a8b4982a25260a874982a15260a834982a0525fa7f497e9f525fa7b497e9e525ea77497a9d525ea73497a9c525ea6f497a9b525ea6b497a9a525da67497699525da63497698525da5f497697525da5b497696525ca57497295525ca534
+ //0xb3856477028c4f0075007400730074006100620075006c006f00750073000a001a25abad096aeac25aba9096ae9c25aba5096ae8c25aba1096ae7c25ab9d096ae6c25ab99096ae5c25ab95096ae4c25ab91096ae3c25ab8d096ae2c25ab89096ae1c25ab85096ae0c25ab81096adfc25bb7d096edec0
+ //0xb3856477028c4f0075007400730074006100620075006c006f00750073000a0018241c8149071fd241c7d49071ed241c7949071dd241c7549031cd240c7149031bd240c6d49031ad240c69490319d240c65490318d240c61490317d240c5d490316d240c59490315d240c55490314d
+ //0xb3856477028c4f0075007400730074006100620075006c006f00750073000a000a2a9bff0aaa8052aaa074aaa82d2aaa0f4aaa85d2aaa1b4aaa87d2aaa234aae89d0
+ //0xb3856477028c4f0075007400730074006100620075006c006f00750073000a000a279bc709e6f14279bc309e6f04279bbf09e6ef4279bbb09e2eec278bb90c
+ //0xb3856477028c4f0075007400730074006100620075006c006f00750073000a000829ebb90a7eee42a0bb90a86eec2a2bbb0a96eec2a6bbb0a9eeec
+ //0xb3856477028c4f0075007400730074006100620075006c006f00750073000a00072aea7d4aba9fd2aea814abaa0d2aea854abaa1d2aea894
+ //0xb3856477028c4f0075007400730074006100620075006c006f00750073000a000625bbb7096eed425bbb3096eec425bbaf096aebc0
+ //0xb3856477028c4f0075007400730074006100620075006c006f00750073000a000225ca51497293d0
+ //0xb3856477028c4f0075007400730074006100620075006c006f00750073000a000130
"decode" in {
PacketCoding.DecodePacket(string).require match {
- case BattleplanMessage(unk1, mastermind, unk2, diagrams) =>
- unk1 mustEqual 41490746
- mastermind mustEqual "YetAnotherFailureAlt"
- unk2 mustEqual 0
+ case BattleplanMessage(char_id, player_name, zone_id, diagrams) =>
+ char_id mustEqual 41490746
+ player_name mustEqual "YetAnotherFailureAlt"
+ zone_id mustEqual 0
diagrams.size mustEqual 1
//h0
- diagrams.head.pageNum mustEqual 14
- diagrams.head.sheet.isDefined mustEqual false
+ diagrams.head.action mustEqual DiagramActionCode.ActionE
+ diagrams.head.stroke.isDefined mustEqual false
case _ =>
ko
}
@@ -29,7 +46,7 @@ class BattleplanMessageTest extends Specification {
41490746,
"YetAnotherFailureAlt",
0,
- BattleDiagram(14) ::
+ BattleDiagramAction(DiagramActionCode.ActionE) ::
Nil
)
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala
index 56b00e01..cf620c3d 100644
--- a/pslogin/src/main/scala/WorldSessionActor.scala
+++ b/pslogin/src/main/scala/WorldSessionActor.scala
@@ -179,7 +179,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
log.debug("Object: " + obj)
// LoadMapMessage 13714 in mossy .gcap
// XXX: hardcoded shit
- sendResponse(PacketCoding.CreateGamePacket(0, LoadMapMessage("map13","home3",40100,25,true,3770441820L))) //VS Sanctuary
+ sendResponse(PacketCoding.CreateGamePacket(0, LoadMapMessage("map10","z10",40100,25,true,3770441820L))) //VS Sanctuary
sendResponse(PacketCoding.CreateGamePacket(0, ZonePopulationUpdateMessage(PlanetSideGUID(13), 414, 138, 0, 138, 0, 138, 0, 138, 0)))
sendResponse(PacketCoding.CreateGamePacket(0, objectHex))
@@ -217,7 +217,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
sendResponse(PacketCoding.CreateGamePacket(0, SetCurrentAvatarMessage(guid,0,0)))
sendResponse(PacketCoding.CreateGamePacket(0, CreateShortcutMessage(guid, 1, 0, true, Shortcut.MEDKIT)))
sendResponse(PacketCoding.CreateGamePacket(0, ReplicationStreamMessage(5, Some(6), Vector(SquadListing(255))))) //clear squad list
-
+sendRawResponse(hex"b3 3a197902 94 59006500740041006e006f0074006800650072004600610069006c0075007200650041006c007400 0000 01 e0")
+sendRawResponse(hex"b3 3a197902 8c 4f0075007400730074006100620075006c006f0075007300 0a00202aba2b4aae8bd2aba334aae8dd2aca3b4ab28fd2aca414ab29152aca474ab292d2ada4d4ab69452ada534ab695d2ada594ab696d2ada5d4ab697d2ada614ab698d2ada654ab699d2ada694ab69ad2aea6d4aba9bd2aea714aba9cd2aea754aba9dd2aea794aba9ed")
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
clientKeepAlive = context.system.scheduler.schedule(0 seconds, 500 milliseconds, self, PokeClient())