diff --git a/common/src/main/scala/net/psforever/objects/teamwork/Member.scala b/common/src/main/scala/net/psforever/objects/teamwork/Member.scala
new file mode 100644
index 00000000..fc1988e3
--- /dev/null
+++ b/common/src/main/scala/net/psforever/objects/teamwork/Member.scala
@@ -0,0 +1,65 @@
+// Copyright (c) 2019 PSForever
+package net.psforever.objects.teamwork
+
+import net.psforever.types.{CertificationType, Vector3}
+
+class Member {
+ //about the position to be filled
+ private var role : String = ""
+ private var restrictions : Set[CertificationType.Value] = Set()
+ //about the individual filling the position
+ private var name : String = ""
+ private var health : Int = 0
+ private var armor : Int = 0
+ private var zoneId : String = "Nowhere"
+ private var position : Vector3 = Vector3.Zero
+
+ def Role : String = role
+
+ def Role_=(title : String) : String = {
+ role = title
+ Role
+ }
+
+ def Restrictions : Set[CertificationType.Value] = restrictions
+
+ def Restrictions_=(requirements : Set[CertificationType.Value]) = {
+ restrictions = requirements
+ Restrictions
+ }
+
+ def Name : String = name
+
+ def Name_=(moniker : String) : String = {
+ name = moniker
+ Name
+ }
+
+ def Health : Int = health
+
+ def Health_=(red : Int) : Int = {
+ health = red
+ Health
+ }
+
+ def Armor : Int = armor
+
+ def Armor_=(blue : Int) : Int = {
+ armor = blue
+ Armor
+ }
+
+ def ZoneId : String = zoneId
+
+ def ZoneId_=(id : String) : String = {
+ zoneId = id
+ ZoneId
+ }
+
+ def Position : Vector3 = position
+
+ def Position_=(pos : Vector3) : Vector3 = {
+ position = pos
+ Position
+ }
+}
diff --git a/common/src/main/scala/net/psforever/objects/teamwork/Squad.scala b/common/src/main/scala/net/psforever/objects/teamwork/Squad.scala
new file mode 100644
index 00000000..23a96a7a
--- /dev/null
+++ b/common/src/main/scala/net/psforever/objects/teamwork/Squad.scala
@@ -0,0 +1,51 @@
+// Copyright (c) 2019 PSForever
+package net.psforever.objects.teamwork
+
+import net.psforever.objects.entity.IdentifiableEntity
+import net.psforever.packet.game.PlanetSideGUID
+import net.psforever.types.PlanetSideEmpire
+
+class Squad(squadId : PlanetSideGUID, alignment : PlanetSideEmpire.Value) extends IdentifiableEntity {
+ super.GUID_=(squadId)
+ private val faction : PlanetSideEmpire.Value = alignment //does not change
+ private val zoneId : Option[String] = None
+ private var task : String = ""
+ private var description : String = ""
+ private val membership : Array[Member] = Array.fill[Member](10)(new Member)
+ private val availability : Array[Boolean] = Array.fill[Boolean](10)(true)
+
+ override def GUID_=(d : PlanetSideGUID) : PlanetSideGUID = GUID
+
+ def Faction : PlanetSideEmpire.Value = faction
+
+ def ZoneId : String = zoneId.getOrElse({
+ membership.headOption match {
+ case Some(leader) =>
+ leader.ZoneId
+ case _ =>
+ "Nowhere"
+ }
+ })
+
+ def Task : String = task
+
+ def Task_=(assignment : String) : String = {
+ task = assignment
+ Task
+ }
+
+ def Description : String = description
+
+ def Description_=(desc : String) : String = {
+ description = desc
+ Description
+ }
+
+ def Membership : Array[Member] = membership
+
+ def Availability : Array[Boolean] = availability
+
+ def Size : Int = membership.count(member => !member.Name.equals(""))
+
+ def Capacity : Int = availability.count(open => open)
+}
diff --git a/common/src/main/scala/net/psforever/packet/game/SquadDefinitionActionMessage.scala b/common/src/main/scala/net/psforever/packet/game/SquadDefinitionActionMessage.scala
index 052c0e55..0baf8518 100644
--- a/common/src/main/scala/net/psforever/packet/game/SquadDefinitionActionMessage.scala
+++ b/common/src/main/scala/net/psforever/packet/game/SquadDefinitionActionMessage.scala
@@ -2,21 +2,239 @@
package net.psforever.packet.game
import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket}
+import scodec.bits.BitVector
import scodec.{Attempt, Codec, Err}
import scodec.codecs._
import shapeless.{::, HNil}
+/**
+ * The generic superclass of a specific behavior for this type of squad definition action.
+ * All behaviors have a "code" that indicates how the rest of the data is parsed.
+ * @param code the action behavior code
+ */
+protected abstract class SquadAction(val code : Int)
+
+object SquadAction{
+ final case class SaveSquadDefinition() extends SquadAction(3)
+
+ final case class ListSquad() extends SquadAction(8)
+
+ final case class SelectRoleForYourself(state : Int) extends SquadAction(10)
+
+ final case class ChangeSquadPurpose(purpose : String) extends SquadAction(19)
+
+ final case class ChangeSquadZone(zone : PlanetSideZoneID) extends SquadAction(20)
+
+ final case class CloseSquadMemberPosition(position : Int) extends SquadAction(21)
+
+ final case class AddSquadMemberPosition(position : Int) extends SquadAction(22)
+
+ final case class ChangeSquadMemberRequirementsRole(u1 : Int, role : String) extends SquadAction(23)
+
+ final case class ChangeSquadMemberRequirementsDetailedOrders(u1 : Int, orders : String) extends SquadAction(24)
+
+ final case class ChangeSquadMemberRequirementsWeapons(u1 : Int, u2 : Long) extends SquadAction(25)
+
+ final case class ResetAll() extends SquadAction(26)
+
+ final case class AutoApproveInvitationRequests(state : Boolean) extends SquadAction(28)
+
+ final case class LocationFollowsSquadLead(state : Boolean) extends SquadAction(31)
+
+ final case class SearchForSquadsWithParticularRole(u1: String, u2 : Long, u3: Int, u4 : Int) extends SquadAction(34)
+
+ final case class CancelSquadSearch() extends SquadAction(35)
+
+ final case class FindLfsSoldiersForRole(state : Int) extends SquadAction(40)
+
+ final case class CancelFind() extends SquadAction(41)
+
+ final case class Unknown(badCode : Int, data : BitVector) extends SquadAction(badCode)
+
+ /**
+ * The `Codec`s used to transform the input stream into the context of a specific action
+ * and extract the field data from that stream.
+ */
+ object Codecs {
+ private val everFailCondition = conditional(included = false, bool)
+
+ val saveSquadDefinitionCodec = everFailCondition.xmap[SaveSquadDefinition] (
+ _ => SaveSquadDefinition(),
+ {
+ case SaveSquadDefinition() => None
+ }
+ )
+
+ val listSquadCodec = everFailCondition.xmap[ListSquad] (
+ _ => ListSquad(),
+ {
+ case ListSquad() => None
+ }
+ )
+
+ val selectRoleForYourselfCodec = uint4.xmap[SelectRoleForYourself] (
+ value => SelectRoleForYourself(value),
+ {
+ case SelectRoleForYourself(value) => value
+ }
+ )
+
+ val changeSquadPurposeCodec = PacketHelpers.encodedWideStringAligned(6).xmap[ChangeSquadPurpose] (
+ purpose => ChangeSquadPurpose(purpose),
+ {
+ case ChangeSquadPurpose(purpose) => purpose
+ }
+ )
+
+ val changeSquadZoneCodec = uint16L.xmap[ChangeSquadZone] (
+ value => ChangeSquadZone(PlanetSideZoneID(value)),
+ {
+ case ChangeSquadZone(value) => value.zoneId.toInt
+ }
+ )
+
+ val closeSquadMemberPositionCodec = uint4.xmap[CloseSquadMemberPosition] (
+ position => CloseSquadMemberPosition(position),
+ {
+ case CloseSquadMemberPosition(position) => position
+ }
+ )
+
+ val addSquadMemberPositionCodec = uint4.xmap[AddSquadMemberPosition] (
+ position => AddSquadMemberPosition(position),
+ {
+ case AddSquadMemberPosition(position) => position
+ }
+ )
+
+ val changeSquadMemberRequirementsRoleCodec = (uint4L :: PacketHelpers.encodedWideStringAligned(2)).xmap[ChangeSquadMemberRequirementsRole] (
+ {
+ case u1 :: role :: HNil => ChangeSquadMemberRequirementsRole(u1, role)
+ },
+ {
+ case ChangeSquadMemberRequirementsRole(u1, role) => u1 :: role :: HNil
+ }
+ )
+
+ val changeSquadMemberRequirementsDetailedOrdersCodec = (uint4L :: PacketHelpers.encodedWideStringAligned(2)).xmap[ChangeSquadMemberRequirementsDetailedOrders] (
+ {
+ case u1 :: role :: HNil => ChangeSquadMemberRequirementsDetailedOrders(u1, role)
+ },
+ {
+ case ChangeSquadMemberRequirementsDetailedOrders(u1, role) => u1 :: role :: HNil
+ }
+ )
+
+ val changeSquadMemberRequirementsWeaponsCodec = (uint4 :: ulongL(46)).xmap[ChangeSquadMemberRequirementsWeapons] (
+ {
+ case u1 :: u2 :: HNil => ChangeSquadMemberRequirementsWeapons(u1, u2)
+ },
+ {
+ case ChangeSquadMemberRequirementsWeapons(u1, u2) => u1 :: u2 :: HNil
+ }
+ )
+
+ val resetAllCodec = everFailCondition.xmap[ResetAll] (
+ _ => ResetAll(),
+ {
+ case ResetAll() => None
+ }
+ )
+
+ val autoApproveInvitationRequestsCodec = bool.xmap[AutoApproveInvitationRequests] (
+ state => AutoApproveInvitationRequests(state),
+ {
+ case AutoApproveInvitationRequests(state) => state
+ }
+ )
+
+ val locationFollowsSquadLeadCodec = bool.xmap[LocationFollowsSquadLead] (
+ state => LocationFollowsSquadLead(state),
+ {
+ case LocationFollowsSquadLead(state) => state
+ }
+ )
+
+ val searchForSquadsWithParticularRoleCodec = (
+ PacketHelpers.encodedWideStringAligned(6) ::
+ ulongL(46) ::
+ uint16L ::
+ uintL(3)).xmap[SearchForSquadsWithParticularRole] (
+ {
+ case u1 :: u2 :: u3 :: u4 :: HNil => SearchForSquadsWithParticularRole(u1, u2, u3, u4)
+ },
+ {
+ case SearchForSquadsWithParticularRole(u1, u2, u3, u4) => u1 :: u2 :: u3 :: u4 :: HNil
+ }
+ )
+
+ val cancelSquadSearchCodec = everFailCondition.xmap[CancelSquadSearch] (
+ _ => CancelSquadSearch(),
+ {
+ case CancelSquadSearch() => None
+ }
+ )
+
+ val findLfsSoldiersForRoleCodec = uint4.xmap[FindLfsSoldiersForRole] (
+ state => FindLfsSoldiersForRole(state),
+ {
+ case FindLfsSoldiersForRole(state) => state
+ }
+ )
+
+ val cancelFindCodec = everFailCondition.xmap[CancelFind] (
+ _ => CancelFind(),
+ {
+ case CancelFind() => None
+ }
+ )
+
+ /**
+ * A common form for known action code indexes with an unknown purpose and transformation is an "Unknown" object.
+ * @param action the action behavior code
+ * @return a transformation between the action code and the unknown bit data
+ */
+ def unknownCodec(action : Int) = bits.xmap[Unknown] (
+ data => Unknown(action, data),
+ {
+ case Unknown(_, data) => data
+ }
+ )
+
+ /**
+ * The action code was completely unanticipated!
+ * @param action the action behavior code
+ * @return nothing; always fail
+ */
+ def failureCodec(action : Int)= everFailCondition.exmap[SquadAction] (
+ _ => Attempt.failure(Err(s"can not match a codec pattern for decoding $action")),
+ _ => Attempt.failure(Err(s"can not match a codec pattern for encoding $action"))
+ )
+ }
+}
+
/**
* Manage composition and details of a player's current squad, or the currently-viewed squad.
*
* The `action` code indicates the format of the remainder data in the packet.
* The following formats are translated; their purposes are listed:
* `(None)`
- * `3 ` - Save Squad Definition
- * `8 ` - List Squad
- * `26` - Reset All
- * `35` - Cancel Squad Search
- * `41` - Cancel Find
+ * `0 ` - UNKNOWN
+ * `1 ` - UNKNOWN
+ * `2 ` - UNKNOWN
+ * `3 ` - Save Squad Definition
+ * `4 ` - UNKNOWN
+ * `6 ` - UNKNOWN
+ * `8 ` - List Squad
+ * `9 ` - UNKNOWN
+ * `16` - UNKNOWN
+ * `17` - UNKNOWN
+ * `18` - UNKNOWN
+ * `26` - Reset All
+ * `35` - Cancel Squad Search
+ * `41` - Cancel Find
+ * `42` - UNKNOWN
+ * `43` - UNKNOWN
* `Boolean`
* `28` - Auto-approve Requests for Invitation
* `29` - UNKNOWN
@@ -48,34 +266,15 @@ import shapeless.{::, HNil}
* `Long :: Long`
* `36` - UNKNOWN
* `String :: Long :: Int :: Int`
- * `34` - Search for Squads with a Particular Role
- *
- * Exploration:
- * Some notes regarding the full list of action codes follows after this packet.
- * Asides from codes whose behaviors are unknown, some codes also have unknown data format.
- * No information for codes 1, 5, 9, 27, or 35 has been found yet.
- * @param action the purpose of this packet;
- * also decides the content of the parameter fields
+ * `34` - Search for Squads with a Particular Role
* @param unk1 na
* @param unk2 na
- * @param string_opt the optional `String` parameter
- * @param int1_opt the first optional `Int` parameter;
- * will not necessarily conform to a single bit length
- * @param int2_opt the second optional `Int` parameter
- * @param long1_opt the first optional `Long` parameter;
- * will not necessarily conform to a single bit length
- * @param long2_opt the second optional `Long` parameter
- * @param bool_opt the optional `Boolean` parameter
+ * @param action the purpose of this packet;
+ * also decides the content of the parameter fields
*/
-final case class SquadDefinitionActionMessage(action : Int,
- unk1 : Int,
+final case class SquadDefinitionActionMessage(unk1 : Int,
unk2 : Int,
- string_opt : Option[String],
- int1_opt : Option[Int],
- int2_opt : Option[Int],
- long1_opt : Option[Long],
- long2_opt : Option[Long],
- bool_opt : Option[Boolean])
+ action : SquadAction)
extends PlanetSideGamePacket {
type Packet = SquadDefinitionActionMessage
def opcode = GamePacketOpcode.SquadDefinitionActionMessage
@@ -84,266 +283,57 @@ final case class SquadDefinitionActionMessage(action : Int,
object SquadDefinitionActionMessage extends Marshallable[SquadDefinitionActionMessage] {
/**
- * Common pattern for the parameters, with enough fields to support all possible outputs.
- * All fields are `Option`al purposefully.
+ * Use the action code to transform between
+ * the specific action object and its field data
+ * and the stream of bits of the original packet.
+ * @param code the action behavior code
+ * @return the `SquadAction` `Codec` to use for the given `code`
*/
- private type allPattern = Option[String] :: Option[Int] :: Option[Int] :: Option[Long] :: Option[Long] :: Option[Boolean] :: HNil
-
- /**
- * `Codec` for reading nothing from the remainder of the stream data.
- * @return a filled-out `allPattern` if successful
- */
- def noneCodec : Codec[allPattern] = ignore(0).xmap[allPattern] (
- {
- case () =>
- None :: None :: None :: None :: None :: None :: HNil
- },
- {
- case _ :: _ :: _ :: _ :: _ :: _ :: HNil =>
- ()
- }
- )
-
- /**
- * `Codec` for reading a single `Boolean` from remaining stream data.
- * @return a filled-out `allPattern` if successful
- */
- def boolCodec : Codec[allPattern] = bool.hlist.exmap[allPattern] (
- {
- case n :: HNil =>
- Attempt.successful(None :: None :: None :: None :: None :: Some(n) :: HNil)
- },
- {
- case _ :: _ :: _ :: _ :: _ :: None :: HNil =>
- Attempt.failure(Err("expected a boolean value but found nothing"))
- case _ :: _ :: _ :: _ :: _ :: Some(n) :: HNil =>
- Attempt.successful(n :: HNil)
- }
- )
-
- /**
- * `Codec` for reading a single `Int` from remaining stream data.
- * Multiple bit lengths can be processed from this reading.
- * @param icodec the `Codec[Int]` read by this method
- * @return a filled-out `allPattern` if successful
- */
- def intCodec(icodec : Codec[Int]) : Codec[allPattern] = icodec.hlist.exmap[allPattern] (
- {
- case n :: HNil =>
- Attempt.successful(None :: Some(n) :: None :: None :: None :: None :: HNil)
- },
- {
- case _ :: None :: _ :: _ :: _ :: _ :: HNil =>
- Attempt.failure(Err("expected an integer value but found nothing"))
- case _ :: Some(n) :: _ :: _ :: _ :: _ :: HNil =>
- Attempt.successful(n :: HNil)
- }
- )
-
- /**
- * `Codec` for reading a single `Long` from remaining stream data.
- * @return a filled-out `allPattern` if successful
- */
- def longCodec : Codec[allPattern] = uint32L.hlist.exmap[allPattern] (
- {
- case n :: HNil =>
- Attempt.successful(None :: None :: None :: Some(n) :: None :: None :: HNil)
- },
- {
- case _ :: _ :: _ :: None :: _ :: _ :: HNil =>
- Attempt.failure(Err("expected a long value but found nothing"))
- case _ :: _ :: _ :: Some(n) :: _ :: _ :: HNil =>
- Attempt.successful(n :: HNil)
- }
- )
-
- /**
- * `Codec` for reading a `String` from remaining stream data.
- * All `String`s processed by this reading are wide character and are padded by six.
- * @return a filled-out `allPattern` if successful
- */
- def stringCodec : Codec[allPattern] = PacketHelpers.encodedWideStringAligned(6).hlist.exmap[allPattern] (
- {
- case a :: HNil =>
- Attempt.successful(Some(a) :: None :: None :: None :: None :: None :: HNil)
- },
- {
- case None:: _ :: _ :: _ :: _ :: _ :: HNil =>
- Attempt.failure(Err("expected a string value but found nothing"))
- case Some(a) :: _ :: _ :: _ :: _ :: _ :: HNil =>
- Attempt.successful(a :: HNil)
- }
- )
-
- /**
- * `Codec` for reading an `Int` followed by a `Long` from remaining stream data.
- * Multiple bit lengths can be processed for the `Long1` value from this reading.
- * @param lcodec the `Codec[Long]` read by this method
- * @return a filled-out `allPattern` if successful
- */
- def intLongCodec(lcodec : Codec[Long]) : Codec[allPattern] = (
- uint4L ::
- lcodec
- ).exmap[allPattern] (
- {
- case a :: b :: HNil =>
- Attempt.successful(None :: Some(a) :: None :: Some(b) :: None :: None :: HNil)
- },
- {
- case _ :: None :: _ :: _ :: _ :: _ :: HNil =>
- Attempt.failure(Err("expected a integer value but found nothing"))
- case _ :: _ :: _ :: None :: _ :: _ :: HNil =>
- Attempt.failure(Err("expected a long value but found nothing"))
- case _ :: Some(a) :: _ :: Some(b) :: _ :: _ :: HNil =>
- Attempt.successful(a :: b :: HNil)
- }
- )
-
- /**
- * `Codec` for reading an `Int` followed by a `String` from remaining stream data.
- * All `String`s processed by this reading are wide character and are padded by two.
- * @return a filled-out `allPattern` if successful
- */
- def intStringCodec : Codec[allPattern] = (
- uint4L ::
- PacketHelpers.encodedWideStringAligned(2)
- ).exmap[allPattern] (
- {
- case a :: b :: HNil =>
- Attempt.successful(Some(b) :: Some(a) :: None :: None :: None :: None :: HNil)
- },
- {
- case None:: _ :: _ :: _ :: _ :: _ :: HNil =>
- Attempt.failure(Err("expected a string value but found nothing"))
- case _ :: None :: _ :: _ :: _ :: _ :: HNil =>
- Attempt.failure(Err("expected an integer value but found nothing"))
- case Some(b) :: Some(a) :: _ :: _ :: _ :: _ :: HNil =>
- Attempt.successful(a :: b :: HNil)
- }
- )
-
- /**
- * `Codec` for reading two `Long`s from remaining stream data.
- * @return a filled-out `allPattern` if successful
- */
- def longLongCodec : Codec[allPattern] = (
- ulongL(46) ::
- uint32L
- ).exmap[allPattern] (
- {
- case a :: b :: HNil =>
- Attempt.successful(None :: None :: None :: Some(a) :: Some(b) :: None :: HNil)
- },
- {
- case (_ :: _ :: _ :: None :: _ :: _ :: HNil) | (_ :: _ :: _ :: _ :: None :: _ :: HNil) =>
- Attempt.failure(Err("expected two long values but found one"))
- case _ :: _ :: _ :: Some(a) :: Some(b) :: _ :: HNil =>
- Attempt.successful(a :: b :: HNil)
- }
- )
-
- /**
- * `Codec` for reading a `String`, a `Long`, and two `Int`s from remaining stream data.
- * All `String`s processed by this reading are wide character and are padded by six.
- * @return a filled-out `allPattern` if successful
- */
- def complexCodec : Codec[allPattern] = (
- PacketHelpers.encodedWideStringAligned(6) ::
- ulongL(46) ::
- uint16L ::
- uintL(3)
- ).exmap[allPattern] (
- {
- case a :: b :: c :: d :: HNil =>
- Attempt.successful(Some(a) :: Some(c) :: Some(d) :: Some(b) :: None :: None :: HNil)
- },
- {
- case None:: _ :: _ :: _ :: _ :: _ :: HNil =>
- Attempt.failure(Err("expected a string value but found nothing"))
- case _ :: _ :: _ :: None :: _ :: _ :: HNil =>
- Attempt.failure(Err("expected a long value but found nothing"))
- case (_ :: None :: _ :: _ :: _ :: _ :: HNil) | (_ :: _ :: None :: _ :: _ :: _ :: HNil) =>
- Attempt.failure(Err("expected two integer values but found one"))
- case Some(a) :: Some(c) :: Some(d) :: Some(b) :: _ :: _ :: HNil =>
- Attempt.successful(a :: b :: c :: d :: HNil)
- }
- )
-
- import scala.annotation.switch
-
- /**
- * Select the `Codec` to translate bit data in this packet with an `allPattern` format.
- * @param action the purpose of this packet;
- * also decides the content of the parameter fields
- * @return an `allPattern` `Codec` that parses the appropriate data
- */
- def selectCodec(action : Int) : Codec[allPattern] = (action : @switch) match {
- case 3 | 8 | 26 | 35 | 41 => //TODO double check these
- noneCodec
-
- case 28 | 29 | 30 | 31 =>
- boolCodec
-
- case 33 =>
- intCodec(uintL(3))
- case 10 | 11 | 21 | 22 | 40 =>
- intCodec(uint4L)
- case 20 =>
- intCodec(uint16L)
-
- case 13 | 14 | 15 | 37 =>
- longCodec
-
- case 7 | 19 =>
- stringCodec
-
- case 12 | 38 =>
- intLongCodec(uint32L)
- case 25 =>
- intLongCodec(ulongL(46))
-
- case 23 | 24 =>
- intStringCodec
-
- case 36 =>
- longLongCodec
-
- case 34 =>
- complexCodec
-
- case _ =>
- //TODO for debugging purposes only; normal failure condition below
- bits.hlist.exmap[allPattern] (
- {
- case x :: HNil =>
- org.log4s.getLogger.warn(s"can not match a codec pattern for decoding $action")
- Attempt.successful(Some(x.toString) :: None :: None :: None :: None :: None :: HNil)
- },
- {
- case Some(x) :: None :: None :: None :: None :: None :: HNil =>
- org.log4s.getLogger.warn(s"can not match a codec pattern for encoding $action")
- Attempt.successful(scodec.bits.BitVector.fromValidBin(x) :: HNil)
- }
- )
-// ignore(0).exmap[allPattern] (
-// {
-// case () =>
-// Attempt.failure(Err(s"can not match a codec pattern for decoding $action"))
-// },
-// {
-// case _ :: _ :: _ :: _ :: _ :: _ :: HNil =>
-// Attempt.failure(Err(s"can not match a codec pattern for encoding $action"))
-// }
-// )
+ def selectFromActionCode(code : Int) : Codec[SquadAction] = {
+ import SquadAction.Codecs._
+ import scala.annotation.switch
+ ((code : @switch) match {
+ case 3 => saveSquadDefinitionCodec
+ case 8 => listSquadCodec
+ case 10 => selectRoleForYourselfCodec
+ case 19 => changeSquadPurposeCodec
+ case 20 => changeSquadZoneCodec
+ case 21 => closeSquadMemberPositionCodec
+ case 22 => addSquadMemberPositionCodec
+ case 23 => changeSquadMemberRequirementsRoleCodec
+ case 24 => changeSquadMemberRequirementsDetailedOrdersCodec
+ case 25 => changeSquadMemberRequirementsWeaponsCodec
+ case 26 => resetAllCodec
+ case 28 => autoApproveInvitationRequestsCodec
+ case 31 => locationFollowsSquadLeadCodec
+ case 34 => searchForSquadsWithParticularRoleCodec
+ case 35 => cancelSquadSearchCodec
+ case 40 => findLfsSoldiersForRoleCodec
+ case 41 => cancelFindCodec
+ case 0 | 1 | 2 | 4 | 6 | 7 | 9 |
+ 11 | 12 | 13 | 14 | 15 | 16 |
+ 17 | 18 | 29 | 30 | 33 | 36 |
+ 37 | 38 | 42 | 43 => unknownCodec(code)
+ case _ => failureCodec(code)
+ }).asInstanceOf[Codec[SquadAction]]
}
implicit val codec : Codec[SquadDefinitionActionMessage] = (
- ("action" | uintL(6)) >>:~ { action =>
+ uintL(6) >>:~ { code =>
("unk1" | uint16L) ::
("unk2" | uint4L) ::
- selectCodec(action)
+ ("action" | selectFromActionCode(code))
}
- ).as[SquadDefinitionActionMessage]
+ ).xmap[SquadDefinitionActionMessage] (
+ {
+ case _ :: u1 :: u2 :: action :: HNil =>
+ SquadDefinitionActionMessage(u1, u2, action)
+ },
+ {
+ case SquadDefinitionActionMessage(u1, u2, action) =>
+ action.code :: u1 :: u2 :: action :: HNil
+ }
+ )
}
/*
diff --git a/common/src/test/scala/game/SquadDefinitionActionMessageTest.scala b/common/src/test/scala/game/SquadDefinitionActionMessageTest.scala
index a9657dec..934422a7 100644
--- a/common/src/test/scala/game/SquadDefinitionActionMessageTest.scala
+++ b/common/src/test/scala/game/SquadDefinitionActionMessageTest.scala
@@ -3,6 +3,7 @@ package game
import org.specs2.mutable._
import net.psforever.packet._
+import net.psforever.packet.game.SquadAction._
import net.psforever.packet.game._
import scodec.bits._
@@ -30,18 +31,15 @@ class SquadDefinitionActionMessageTest extends Specification {
val string_40 = hex"E7 a0 000004" //index: 1
val string_41 = hex"E7 a4 000000"
+ val string_43 = hex"e7 ac 000000"
+ val string_failure = hex"E7 ff"
+
"decode (03)" in {
PacketCoding.DecodePacket(string_03).require match {
- case SquadDefinitionActionMessage(action, unk1, unk2, str, int1, int2, long1, long2, bool) =>
- action mustEqual 3
+ case SquadDefinitionActionMessage(unk1, unk2, action) =>
unk1 mustEqual 0
unk2 mustEqual 3
- str.isDefined mustEqual false
- int1.isDefined mustEqual false
- int2.isDefined mustEqual false
- long1.isDefined mustEqual false
- long2.isDefined mustEqual false
- bool.isDefined mustEqual false
+ action mustEqual SaveSquadDefinition()
case _ =>
ko
}
@@ -49,16 +47,10 @@ class SquadDefinitionActionMessageTest extends Specification {
"decode (08)" in {
PacketCoding.DecodePacket(string_08).require match {
- case SquadDefinitionActionMessage(action, unk1, unk2, str, int1, int2, long1, long2, bool) =>
- action mustEqual 8
+ case SquadDefinitionActionMessage(unk1, unk2, action) =>
unk1 mustEqual 0
unk2 mustEqual 0
- str.isDefined mustEqual false
- int1.isDefined mustEqual false
- int2.isDefined mustEqual false
- long1.isDefined mustEqual false
- long2.isDefined mustEqual false
- bool.isDefined mustEqual false
+ action mustEqual ListSquad()
case _ =>
ko
}
@@ -66,17 +58,10 @@ class SquadDefinitionActionMessageTest extends Specification {
"decode (10)" in {
PacketCoding.DecodePacket(string_10).require match {
- case SquadDefinitionActionMessage(action, unk1, unk2, str, int1, int2, long1, long2, bool) =>
- action mustEqual 10
+ case SquadDefinitionActionMessage(unk1, unk2, action) =>
unk1 mustEqual 0
unk2 mustEqual 0
- str.isDefined mustEqual false
- int1.isDefined mustEqual true
- int1.get mustEqual 1
- int2.isDefined mustEqual false
- long1.isDefined mustEqual false
- long2.isDefined mustEqual false
- bool.isDefined mustEqual false
+ action mustEqual SelectRoleForYourself(1)
case _ =>
ko
}
@@ -84,17 +69,10 @@ class SquadDefinitionActionMessageTest extends Specification {
"decode (19)" in {
PacketCoding.DecodePacket(string_19).require match {
- case SquadDefinitionActionMessage(action, unk1, unk2, str, int1, int2, long1, long2, bool) =>
- action mustEqual 19
+ case SquadDefinitionActionMessage(unk1, unk2, action) =>
unk1 mustEqual 0
unk2 mustEqual 0
- str.isDefined mustEqual true
- str.get mustEqual "A-Team"
- int1.isDefined mustEqual false
- int2.isDefined mustEqual false
- long1.isDefined mustEqual false
- long2.isDefined mustEqual false
- bool.isDefined mustEqual false
+ action mustEqual ChangeSquadPurpose("A-Team")
case _ =>
ko
}
@@ -102,17 +80,10 @@ class SquadDefinitionActionMessageTest extends Specification {
"decode (20)" in {
PacketCoding.DecodePacket(string_20).require match {
- case SquadDefinitionActionMessage(action, unk1, unk2, str, int1, int2, long1, long2, bool) =>
- action mustEqual 20
+ case SquadDefinitionActionMessage(unk1, unk2, action) =>
unk1 mustEqual 0
unk2 mustEqual 0
- str.isDefined mustEqual false
- int1.isDefined mustEqual true
- int1.get mustEqual 1
- int2.isDefined mustEqual false
- long1.isDefined mustEqual false
- long2.isDefined mustEqual false
- bool.isDefined mustEqual false
+ action mustEqual ChangeSquadZone(PlanetSideZoneID(1))
case _ =>
ko
}
@@ -120,17 +91,10 @@ class SquadDefinitionActionMessageTest extends Specification {
"decode (21)" in {
PacketCoding.DecodePacket(string_21).require match {
- case SquadDefinitionActionMessage(action, unk1, unk2, str, int1, int2, long1, long2, bool) =>
- action mustEqual 21
+ case SquadDefinitionActionMessage(unk1, unk2, action) =>
unk1 mustEqual 0
unk2 mustEqual 0
- str.isDefined mustEqual false
- int1.isDefined mustEqual true
- int1.get mustEqual 2
- int2.isDefined mustEqual false
- long1.isDefined mustEqual false
- long2.isDefined mustEqual false
- bool.isDefined mustEqual false
+ action mustEqual CloseSquadMemberPosition(2)
case _ =>
ko
}
@@ -138,17 +102,10 @@ class SquadDefinitionActionMessageTest extends Specification {
"decode (22)" in {
PacketCoding.DecodePacket(string_22).require match {
- case SquadDefinitionActionMessage(action, unk1, unk2, str, int1, int2, long1, long2, bool) =>
- action mustEqual 22
+ case SquadDefinitionActionMessage(unk1, unk2, action) =>
unk1 mustEqual 0
unk2 mustEqual 0
- str.isDefined mustEqual false
- int1.isDefined mustEqual true
- int1.get mustEqual 2
- int2.isDefined mustEqual false
- long1.isDefined mustEqual false
- long2.isDefined mustEqual false
- bool.isDefined mustEqual false
+ action mustEqual AddSquadMemberPosition(2)
case _ =>
ko
}
@@ -156,18 +113,10 @@ class SquadDefinitionActionMessageTest extends Specification {
"decode (23)" in {
PacketCoding.DecodePacket(string_23).require match {
- case SquadDefinitionActionMessage(action, unk1, unk2, str, int1, int2, long1, long2, bool) =>
- action mustEqual 23
+ case SquadDefinitionActionMessage(unk1, unk2, action) =>
unk1 mustEqual 0
unk2 mustEqual 0
- str.isDefined mustEqual true
- str.get mustEqual "BLUFOR"
- int1.isDefined mustEqual true
- int1.get mustEqual 1
- int2.isDefined mustEqual false
- long1.isDefined mustEqual false
- long2.isDefined mustEqual false
- bool.isDefined mustEqual false
+ action mustEqual ChangeSquadMemberRequirementsRole(1, "BLUFOR")
case _ =>
ko
}
@@ -175,18 +124,10 @@ class SquadDefinitionActionMessageTest extends Specification {
"decode (24)" in {
PacketCoding.DecodePacket(string_24).require match {
- case SquadDefinitionActionMessage(action, unk1, unk2, str, int1, int2, long1, long2, bool) =>
- action mustEqual 24
+ case SquadDefinitionActionMessage(unk1, unk2, action) =>
unk1 mustEqual 0
unk2 mustEqual 0
- str.isDefined mustEqual true
- str.get mustEqual "kill bad dudes"
- int1.isDefined mustEqual true
- int1.get mustEqual 1
- int2.isDefined mustEqual false
- long1.isDefined mustEqual false
- long2.isDefined mustEqual false
- bool.isDefined mustEqual false
+ action mustEqual ChangeSquadMemberRequirementsDetailedOrders(1, "kill bad dudes")
case _ =>
ko
}
@@ -194,18 +135,10 @@ class SquadDefinitionActionMessageTest extends Specification {
"decode (25)" in {
PacketCoding.DecodePacket(string_25).require match {
- case SquadDefinitionActionMessage(action, unk1, unk2, str, int1, int2, long1, long2, bool) =>
- action mustEqual 25
+ case SquadDefinitionActionMessage(unk1, unk2, action) =>
unk1 mustEqual 0
unk2 mustEqual 0
- str.isDefined mustEqual false
- int1.isDefined mustEqual true
- int1.get mustEqual 1
- int2.isDefined mustEqual false
- long1.isDefined mustEqual true
- long1.get mustEqual 536870928L
- long2.isDefined mustEqual false
- bool.isDefined mustEqual false
+ action mustEqual ChangeSquadMemberRequirementsWeapons(1, 536870928L)
case _ =>
ko
}
@@ -213,16 +146,10 @@ class SquadDefinitionActionMessageTest extends Specification {
"decode (26)" in {
PacketCoding.DecodePacket(string_26).require match {
- case SquadDefinitionActionMessage(action, unk1, unk2, str, int1, int2, long1, long2, bool) =>
- action mustEqual 26
+ case SquadDefinitionActionMessage(unk1, unk2, action) =>
unk1 mustEqual 0
unk2 mustEqual 0
- str.isDefined mustEqual false
- int1.isDefined mustEqual false
- int2.isDefined mustEqual false
- long1.isDefined mustEqual false
- long2.isDefined mustEqual false
- bool.isDefined mustEqual false
+ action mustEqual ResetAll()
case _ =>
ko
}
@@ -230,17 +157,10 @@ class SquadDefinitionActionMessageTest extends Specification {
"decode (28)" in {
PacketCoding.DecodePacket(string_28).require match {
- case SquadDefinitionActionMessage(action, unk1, unk2, str, int1, int2, long1, long2, bool) =>
- action mustEqual 28
+ case SquadDefinitionActionMessage(unk1, unk2, action) =>
unk1 mustEqual 0
unk2 mustEqual 0
- str.isDefined mustEqual false
- int1.isDefined mustEqual false
- int2.isDefined mustEqual false
- long1.isDefined mustEqual false
- long2.isDefined mustEqual false
- bool.isDefined mustEqual true
- bool.get mustEqual true
+ action mustEqual AutoApproveInvitationRequests(true)
case _ =>
ko
}
@@ -248,17 +168,10 @@ class SquadDefinitionActionMessageTest extends Specification {
"decode (31)" in {
PacketCoding.DecodePacket(string_31).require match {
- case SquadDefinitionActionMessage(action, unk1, unk2, str, int1, int2, long1, long2, bool) =>
- action mustEqual 31
+ case SquadDefinitionActionMessage(unk1, unk2, action) =>
unk1 mustEqual 0
unk2 mustEqual 0
- str.isDefined mustEqual false
- int1.isDefined mustEqual false
- int2.isDefined mustEqual false
- long1.isDefined mustEqual false
- long2.isDefined mustEqual false
- bool.isDefined mustEqual true
- bool.get mustEqual true
+ action mustEqual LocationFollowsSquadLead(true)
case _ =>
ko
}
@@ -266,20 +179,10 @@ class SquadDefinitionActionMessageTest extends Specification {
"decode (34a)" in {
PacketCoding.DecodePacket(string_34a).require match {
- case SquadDefinitionActionMessage(action, unk1, unk2, str, int1, int2, long1, long2, bool) =>
- action mustEqual 34
+ case SquadDefinitionActionMessage(unk1, unk2, action) =>
unk1 mustEqual 0
unk2 mustEqual 0
- str.isDefined mustEqual true
- str.get mustEqual "Badass"
- int1.isDefined mustEqual true
- int1.get mustEqual 1
- int2.isDefined mustEqual true
- int2.get mustEqual 0
- long1.isDefined mustEqual true
- long1.get mustEqual 0
- long2.isDefined mustEqual false
- bool.isDefined mustEqual false
+ action mustEqual SearchForSquadsWithParticularRole("Badass", 0L, 1, 0)
case _ =>
ko
}
@@ -287,20 +190,10 @@ class SquadDefinitionActionMessageTest extends Specification {
"decode (34b)" in {
PacketCoding.DecodePacket(string_34b).require match {
- case SquadDefinitionActionMessage(action, unk1, unk2, str, int1, int2, long1, long2, bool) =>
- action mustEqual 34
+ case SquadDefinitionActionMessage(unk1, unk2, action) =>
unk1 mustEqual 0
unk2 mustEqual 0
- str.isDefined mustEqual true
- str.get mustEqual "Badass"
- int1.isDefined mustEqual true
- int1.get mustEqual 2
- int2.isDefined mustEqual true
- int2.get mustEqual 0
- long1.isDefined mustEqual true
- long1.get mustEqual 0
- long2.isDefined mustEqual false
- bool.isDefined mustEqual false
+ action mustEqual SearchForSquadsWithParticularRole("Badass", 0L, 2, 0)
case _ =>
ko
}
@@ -308,20 +201,10 @@ class SquadDefinitionActionMessageTest extends Specification {
"decode (34c)" in {
PacketCoding.DecodePacket(string_34c).require match {
- case SquadDefinitionActionMessage(action, unk1, unk2, str, int1, int2, long1, long2, bool) =>
- action mustEqual 34
+ case SquadDefinitionActionMessage(unk1, unk2, action) =>
unk1 mustEqual 0
unk2 mustEqual 0
- str.isDefined mustEqual true
- str.get mustEqual "Badass"
- int1.isDefined mustEqual true
- int1.get mustEqual 2
- int2.isDefined mustEqual true
- int2.get mustEqual 1
- long1.isDefined mustEqual true
- long1.get mustEqual 0
- long2.isDefined mustEqual false
- bool.isDefined mustEqual false
+ action mustEqual SearchForSquadsWithParticularRole("Badass", 0L, 2, 1)
case _ =>
ko
}
@@ -329,20 +212,10 @@ class SquadDefinitionActionMessageTest extends Specification {
"decode (34d)" in {
PacketCoding.DecodePacket(string_34d).require match {
- case SquadDefinitionActionMessage(action, unk1, unk2, str, int1, int2, long1, long2, bool) =>
- action mustEqual 34
+ case SquadDefinitionActionMessage(unk1, unk2, action) =>
unk1 mustEqual 0
unk2 mustEqual 0
- str.isDefined mustEqual true
- str.get mustEqual "Badass"
- int1.isDefined mustEqual true
- int1.get mustEqual 2
- int2.isDefined mustEqual true
- int2.get mustEqual 2
- long1.isDefined mustEqual true
- long1.get mustEqual 536870928L
- long2.isDefined mustEqual false
- bool.isDefined mustEqual false
+ action mustEqual SearchForSquadsWithParticularRole("Badass", 536870928L, 2, 2)
case _ =>
ko
}
@@ -350,20 +223,10 @@ class SquadDefinitionActionMessageTest extends Specification {
"decode (34e)" in {
PacketCoding.DecodePacket(string_34e).require match {
- case SquadDefinitionActionMessage(action, unk1, unk2, str, int1, int2, long1, long2, bool) =>
- action mustEqual 34
+ case SquadDefinitionActionMessage(unk1, unk2, action) =>
unk1 mustEqual 0
unk2 mustEqual 0
- str.isDefined mustEqual true
- str.get mustEqual "Badass"
- int1.isDefined mustEqual true
- int1.get mustEqual 2
- int2.isDefined mustEqual true
- int2.get mustEqual 3
- long1.isDefined mustEqual true
- long1.get mustEqual 536870928L
- long2.isDefined mustEqual false
- bool.isDefined mustEqual false
+ action mustEqual SearchForSquadsWithParticularRole("Badass", 536870928L, 2, 3)
case _ =>
ko
}
@@ -371,16 +234,10 @@ class SquadDefinitionActionMessageTest extends Specification {
"decode (35)" in {
PacketCoding.DecodePacket(string_35).require match {
- case SquadDefinitionActionMessage(action, unk1, unk2, str, int1, int2, long1, long2, bool) =>
- action mustEqual 35
+ case SquadDefinitionActionMessage(unk1, unk2, action) =>
unk1 mustEqual 0
unk2 mustEqual 0
- str.isDefined mustEqual false
- int1.isDefined mustEqual false
- int2.isDefined mustEqual false
- long1.isDefined mustEqual false
- long2.isDefined mustEqual false
- bool.isDefined mustEqual false
+ action mustEqual CancelSquadSearch()
case _ =>
ko
}
@@ -388,17 +245,10 @@ class SquadDefinitionActionMessageTest extends Specification {
"decode (40)" in {
PacketCoding.DecodePacket(string_40).require match {
- case SquadDefinitionActionMessage(action, unk1, unk2, str, int1, int2, long1, long2, bool) =>
- action mustEqual 40
+ case SquadDefinitionActionMessage(unk1, unk2, action) =>
unk1 mustEqual 0
unk2 mustEqual 0
- str.isDefined mustEqual false
- int1.isDefined mustEqual true
- int1.get mustEqual 1
- int2.isDefined mustEqual false
- long1.isDefined mustEqual false
- long2.isDefined mustEqual false
- bool.isDefined mustEqual false
+ action mustEqual FindLfsSoldiersForRole(1)
case _ =>
ko
}
@@ -406,165 +256,181 @@ class SquadDefinitionActionMessageTest extends Specification {
"decode (41)" in {
PacketCoding.DecodePacket(string_41).require match {
- case SquadDefinitionActionMessage(action, unk1, unk2, str, int1, int2, long1, long2, bool) =>
- action mustEqual 41
+ case SquadDefinitionActionMessage(unk1, unk2, action) =>
unk1 mustEqual 0
unk2 mustEqual 0
- str.isDefined mustEqual false
- int1.isDefined mustEqual false
- int2.isDefined mustEqual false
- long1.isDefined mustEqual false
- long2.isDefined mustEqual false
- bool.isDefined mustEqual false
+ action mustEqual CancelFind()
case _ =>
ko
}
}
+ "decode (43, unknown)" in {
+ PacketCoding.DecodePacket(string_43).require match {
+ case SquadDefinitionActionMessage(unk1, unk2, action) =>
+ unk1 mustEqual 0
+ unk2 mustEqual 0
+ action mustEqual Unknown(43, hex"00".toBitVector.take(6))
+ case _ =>
+ ko
+ }
+ }
+
+ "decode (failure)" in {
+ PacketCoding.DecodePacket(string_failure).isFailure mustEqual true
+ }
+
"encode (03)" in {
- val msg = SquadDefinitionActionMessage(3, 0, 3, None, None, None, None, None, None)
+ val msg = SquadDefinitionActionMessage(0, 3, SaveSquadDefinition())
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_03
}
"encode (08)" in {
- val msg = SquadDefinitionActionMessage(8, 0, 0, None, None, None, None, None, None)
+ val msg = SquadDefinitionActionMessage(0, 0, ListSquad())
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_08
}
"encode (10)" in {
- val msg = SquadDefinitionActionMessage(10, 0, 0, None, Some(1), None, None, None, None)
+ val msg = SquadDefinitionActionMessage(0, 0, SelectRoleForYourself(1))
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_10
}
"encode (19)" in {
- val msg = SquadDefinitionActionMessage(19, 0, 0, Some("A-Team"), None, None, None, None, None)
+ val msg = SquadDefinitionActionMessage(0, 0, ChangeSquadPurpose("A-Team"))
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_19
}
"encode (20)" in {
- val msg = SquadDefinitionActionMessage(20, 0, 0, None, Some(1), None, None, None, None)
+ val msg = SquadDefinitionActionMessage(0, 0, ChangeSquadZone(PlanetSideZoneID(1)))
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_20
}
"encode (21)" in {
- val msg = SquadDefinitionActionMessage(21, 0, 0, None, Some(2), None, None, None, None)
+ val msg = SquadDefinitionActionMessage(0, 0, CloseSquadMemberPosition(2))
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_21
}
"encode (22)" in {
- val msg = SquadDefinitionActionMessage(22, 0, 0, None, Some(2), None, None, None, None)
+ val msg = SquadDefinitionActionMessage(0, 0, AddSquadMemberPosition(2))
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_22
}
"encode (23)" in {
- val msg = SquadDefinitionActionMessage(23, 0, 0, Some("BLUFOR"), Some(1), None, None, None, None)
+ val msg = SquadDefinitionActionMessage(0, 0, ChangeSquadMemberRequirementsRole(1, "BLUFOR"))
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_23
}
"encode (24)" in {
- val msg = SquadDefinitionActionMessage(24, 0, 0, Some("kill bad dudes"), Some(1), None, None, None, None)
+ val msg = SquadDefinitionActionMessage(0, 0, ChangeSquadMemberRequirementsDetailedOrders(1, "kill bad dudes"))
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_24
}
"encode (25)" in {
- val msg = SquadDefinitionActionMessage(25, 0, 0, None, Some(1), None, Some(536870928L), None, None)
+ val msg = SquadDefinitionActionMessage(0, 0, ChangeSquadMemberRequirementsWeapons(1, 536870928L))
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_25
}
"encode (26)" in {
- val msg = SquadDefinitionActionMessage(26, 0, 0, None, None, None, None, None, None)
+ val msg = SquadDefinitionActionMessage(0, 0, ResetAll())
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_26
}
"encode (28)" in {
- val msg = SquadDefinitionActionMessage(28, 0, 0, None, None, None, None, None, Some(true))
+ val msg = SquadDefinitionActionMessage(0, 0, AutoApproveInvitationRequests(true))
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_28
}
"encode (31)" in {
- val msg = SquadDefinitionActionMessage(31, 0, 0, None, None, None, None, None, Some(true))
+ val msg = SquadDefinitionActionMessage(0, 0, LocationFollowsSquadLead(true))
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_31
}
"encode (34a)" in {
- val msg = SquadDefinitionActionMessage(34, 0, 0, Some("Badass"), Some(1), Some(0), Some(0L), None, None)
+ val msg = SquadDefinitionActionMessage(0, 0, SearchForSquadsWithParticularRole("Badass", 0L, 1, 0))
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_34a
}
"encode (34b)" in {
- val msg = SquadDefinitionActionMessage(34, 0, 0, Some("Badass"), Some(2), Some(0), Some(0L), None, None)
+ val msg = SquadDefinitionActionMessage(0, 0, SearchForSquadsWithParticularRole("Badass", 0L, 2, 0))
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_34b
}
"encode (34c)" in {
- val msg = SquadDefinitionActionMessage(34, 0, 0, Some("Badass"), Some(2), Some(1), Some(0L), None, None)
+ val msg = SquadDefinitionActionMessage(0, 0, SearchForSquadsWithParticularRole("Badass", 0L, 2, 1))
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_34c
}
"encode (34d)" in {
- val msg = SquadDefinitionActionMessage(34, 0, 0, Some("Badass"), Some(2), Some(2), Some(536870928L), None, None)
+ val msg = SquadDefinitionActionMessage(0, 0, SearchForSquadsWithParticularRole("Badass", 536870928L, 2, 2))
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_34d
}
"encode (34e)" in {
- val msg = SquadDefinitionActionMessage(34, 0, 0, Some("Badass"), Some(2), Some(3), Some(536870928L), None, None)
+ val msg = SquadDefinitionActionMessage(0, 0, SearchForSquadsWithParticularRole("Badass", 536870928L, 2, 3))
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_34e
}
"encode (35)" in {
- val msg = SquadDefinitionActionMessage(35, 0, 0, None, None, None, None, None, None)
+ val msg = SquadDefinitionActionMessage(0, 0, CancelSquadSearch())
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_35
}
"encode (40)" in {
- val msg = SquadDefinitionActionMessage(40, 0, 0, None, Some(1), None, None, None, None)
+ val msg = SquadDefinitionActionMessage(0, 0, FindLfsSoldiersForRole(1))
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_40
}
"encode (41)" in {
- val msg = SquadDefinitionActionMessage(41, 0, 0, None, None, None, None, None, None)
+ val msg = SquadDefinitionActionMessage(0, 0, CancelFind())
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_41
}
+
+ "encode (43, unknown)" in {
+ val msg = SquadDefinitionActionMessage(0, 0, Unknown(43, BitVector.empty))
+ val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
+
+ pkt mustEqual string_43
+ }
}