mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-20 02:24:45 +00:00
restored SquadDefinitionActionMessage to the past upgrade form that was lost; preliminary objects for squad infromation and squad member position information
This commit is contained in:
parent
6fdc617a87
commit
afb10f57c3
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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.<br>
|
||||
* <br>
|
||||
* The `action` code indicates the format of the remainder data in the packet.
|
||||
* The following formats are translated; their purposes are listed:<br>
|
||||
* `(None)`<br>
|
||||
* `3 ` - Save Squad Definition
|
||||
* `8 ` - List Squad
|
||||
* `26` - Reset All
|
||||
* `35` - Cancel Squad Search
|
||||
* `41` - Cancel Find
|
||||
* `0 ` - UNKNOWN<br>
|
||||
* `1 ` - UNKNOWN<br>
|
||||
* `2 ` - UNKNOWN<br>
|
||||
* `3 ` - Save Squad Definition<br>
|
||||
* `4 ` - UNKNOWN<br>
|
||||
* `6 ` - UNKNOWN<br>
|
||||
* `8 ` - List Squad<br>
|
||||
* `9 ` - UNKNOWN<br>
|
||||
* `16` - UNKNOWN<br>
|
||||
* `17` - UNKNOWN<br>
|
||||
* `18` - UNKNOWN<br>
|
||||
* `26` - Reset All<br>
|
||||
* `35` - Cancel Squad Search<br>
|
||||
* `41` - Cancel Find<br>
|
||||
* `42` - UNKNOWN<br>
|
||||
* `43` - UNKNOWN<br>
|
||||
* `Boolean`<br>
|
||||
* `28` - Auto-approve Requests for Invitation<br>
|
||||
* `29` - UNKNOWN<br>
|
||||
|
|
@ -48,34 +266,15 @@ import shapeless.{::, HNil}
|
|||
* `Long :: Long`<br>
|
||||
* `36` - UNKNOWN<br>
|
||||
* `String :: Long :: Int :: Int`<br>
|
||||
* `34` - Search for Squads with a Particular Role<br>
|
||||
* <br>
|
||||
* Exploration:<br>
|
||||
* 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
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue