mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-20 02:54:46 +00:00
communication of the details information for a squad and refactored messaging back to WSA; removed an unused description field from the squad and added two fields that were actually represented
This commit is contained in:
parent
5c433204cf
commit
9cf1cd92cc
|
|
@ -10,18 +10,21 @@ class Squad(squadId : PlanetSideGUID, alignment : PlanetSideEmpire.Value) extend
|
|||
private val faction : PlanetSideEmpire.Value = alignment //does not change
|
||||
private var zoneId : Option[Int] = 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)
|
||||
private var listed : Boolean = false
|
||||
private var leaderPositionIndex : Int = 0
|
||||
private var autoApproveInvitationRequests : Boolean = false
|
||||
private var locationFollowsSquadLead : Boolean = false
|
||||
|
||||
override def GUID_=(d : PlanetSideGUID) : PlanetSideGUID = GUID
|
||||
|
||||
def Faction : PlanetSideEmpire.Value = faction
|
||||
|
||||
def CustomZoneId : Boolean = zoneId.isDefined
|
||||
|
||||
def ZoneId : Int = zoneId.getOrElse({
|
||||
membership.headOption match {
|
||||
membership.lift(leaderPositionIndex) match {
|
||||
case Some(leader) =>
|
||||
leader.ZoneId
|
||||
case _ =>
|
||||
|
|
@ -45,13 +48,6 @@ class Squad(squadId : PlanetSideGUID, alignment : PlanetSideEmpire.Value) extend
|
|||
Task
|
||||
}
|
||||
|
||||
def Description : String = description
|
||||
|
||||
def Description_=(desc : String) : String = {
|
||||
description = desc
|
||||
Description
|
||||
}
|
||||
|
||||
def Listed : Boolean = listed
|
||||
|
||||
def Listed_=(announce : Boolean) : Boolean = {
|
||||
|
|
@ -59,6 +55,20 @@ class Squad(squadId : PlanetSideGUID, alignment : PlanetSideEmpire.Value) extend
|
|||
Listed
|
||||
}
|
||||
|
||||
def LocationFollowsSquadLead : Boolean = locationFollowsSquadLead
|
||||
|
||||
def LocationFollowsSquadLead_=(follow : Boolean) : Boolean = {
|
||||
locationFollowsSquadLead = follow
|
||||
LocationFollowsSquadLead
|
||||
}
|
||||
|
||||
def AutoApproveInvitationRequests : Boolean = autoApproveInvitationRequests
|
||||
|
||||
def AutoApproveInvitationRequests_=(autoApprove : Boolean) : Boolean = {
|
||||
autoApproveInvitationRequests = autoApprove
|
||||
AutoApproveInvitationRequests
|
||||
}
|
||||
|
||||
def Membership : Array[Member] = membership
|
||||
|
||||
def Availability : Array[Boolean] = availability
|
||||
|
|
@ -85,3 +95,16 @@ class Squad(squadId : PlanetSideGUID, alignment : PlanetSideEmpire.Value) extend
|
|||
|
||||
def Capacity : Int = availability.count(open => open)
|
||||
}
|
||||
|
||||
object Squad {
|
||||
final val Blank = new Squad(PlanetSideGUID(0), PlanetSideEmpire.NEUTRAL) {
|
||||
override def ZoneId : Int = 0
|
||||
override def ZoneId_=(id : Int) : Int = 0
|
||||
override def ZoneId_=(id : Option[Int]) : Int = 0
|
||||
override def Task_=(assignment : String) : String = ""
|
||||
override def Listed_=(announce : Boolean) : Boolean = false
|
||||
override def Membership : Array[Member] = Array.empty[Member]
|
||||
override def Availability : Array[Boolean] = Array.fill[Boolean](10)(false)
|
||||
override def LeaderPositionIndex_=(position : Int) : Int = 0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -306,13 +306,13 @@ object SquadAction{
|
|||
* `36` - UNKNOWN<br>
|
||||
* `String :: Long :: Int :: Int`<br>
|
||||
* `34` - Search for Squads with a Particular Role
|
||||
* @param unk1 na
|
||||
* @param unk2 na
|
||||
* @param squad_guid the unique identifier of the squad, if non-zero
|
||||
* @param line the original listing line number, if applicable
|
||||
* @param action the purpose of this packet;
|
||||
* also decides the content of the parameter fields
|
||||
*/
|
||||
final case class SquadDefinitionActionMessage(unk1 : Int,
|
||||
unk2 : Int,
|
||||
final case class SquadDefinitionActionMessage(squad_guid : PlanetSideGUID,
|
||||
line : Int,
|
||||
action : SquadAction)
|
||||
extends PlanetSideGamePacket {
|
||||
type Packet = SquadDefinitionActionMessage
|
||||
|
|
@ -353,28 +353,28 @@ object SquadDefinitionActionMessage extends Marshallable[SquadDefinitionActionMe
|
|||
case 35 => cancelSquadSearchCodec
|
||||
case 40 => findLfsSoldiersForRoleCodec
|
||||
case 41 => cancelFindCodec
|
||||
case 1 | 2 | 6 | 9 |
|
||||
11 | 12 | 13 | 14 | 16 |
|
||||
17 | 18 | 29 | 30 | 33 | 36 |
|
||||
37 | 38 | 42 | 43 => unknownCodec(code)
|
||||
case 1 | 2 | 6 | 9 | 11 |
|
||||
12 | 13 | 14 | 16 | 17 |
|
||||
18 | 29 | 30 | 32 | 33 |
|
||||
36 | 37 | 38 | 42 | 43 => unknownCodec(code)
|
||||
case _ => failureCodec(code)
|
||||
}).asInstanceOf[Codec[SquadAction]]
|
||||
}
|
||||
|
||||
implicit val codec : Codec[SquadDefinitionActionMessage] = (
|
||||
uintL(6) >>:~ { code =>
|
||||
("unk1" | uint16L) ::
|
||||
("unk2" | uint4L) ::
|
||||
("squad_guid" | PlanetSideGUID.codec) ::
|
||||
("line" | uint4L) ::
|
||||
("action" | selectFromActionCode(code))
|
||||
}
|
||||
).xmap[SquadDefinitionActionMessage] (
|
||||
{
|
||||
case _ :: u1 :: u2 :: action :: HNil =>
|
||||
SquadDefinitionActionMessage(u1, u2, action)
|
||||
case _ :: guid :: line :: action :: HNil =>
|
||||
SquadDefinitionActionMessage(guid, line, action)
|
||||
},
|
||||
{
|
||||
case SquadDefinitionActionMessage(u1, u2, action) =>
|
||||
action.code :: u1 :: u2 :: action :: HNil
|
||||
case SquadDefinitionActionMessage(guid, line, action) =>
|
||||
action.code :: guid :: line :: action :: HNil
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ object SquadPositionDetail {
|
|||
def apply(role : String, detailed_orders : String, requirements : Set[CertificationType.Value]) : SquadPositionDetail = SquadPositionDetail(is_closed = false, role, detailed_orders, requirements, 0L, "")
|
||||
|
||||
def apply(role : String, detailed_orders : String, name : String) : SquadPositionDetail = SquadPositionDetail(is_closed = false, role, detailed_orders, Set.empty, reliableNameHash(name), name)
|
||||
|
||||
def apply(role : String, detailed_orders : String, requirements : Set[CertificationType.Value], name : String) : SquadPositionDetail = SquadPositionDetail(is_closed = false, role, detailed_orders, requirements, reliableNameHash(name), name)
|
||||
}
|
||||
|
||||
object SquadDetailDefinitionUpdateMessage extends Marshallable[SquadDetailDefinitionUpdateMessage] {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ final case class SquadMembershipRequest(request_type : SquadRequestType.Value,
|
|||
assert(unk3.nonEmpty, s"a $request_type request requires the unk3 field be defined")
|
||||
}
|
||||
if(request_type == SquadRequestType.Invite) {
|
||||
assert(unk5.nonEmpty, "an Invite request requires the unk5 field be undefined")
|
||||
assert(unk5.nonEmpty, "an Invite request requires the unk5 field be defined")
|
||||
}
|
||||
|
||||
type Packet = SquadMembershipRequest
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) 2019 PSForever
|
||||
package services.teamwork
|
||||
|
||||
import net.psforever.packet.game.SquadInfo
|
||||
import net.psforever.packet.game.{PlanetSideGUID, PlanetSideZoneID, SquadInfo, SquadPositionDetail}
|
||||
|
||||
object SquadResponse {
|
||||
trait Response
|
||||
|
|
@ -9,4 +9,6 @@ object SquadResponse {
|
|||
final case class Init(info : Vector[SquadInfo]) extends Response
|
||||
final case class Update(infos : Iterable[(Int, SquadInfo)]) extends Response
|
||||
final case class Remove(infos : Iterable[Int]) extends Response
|
||||
|
||||
final case class Detail(guid : PlanetSideGUID, leader : String, task : String, zone : PlanetSideZoneID, member_info : List[SquadPositionDetail]) extends Response
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ package services.teamwork
|
|||
|
||||
import akka.actor.Actor
|
||||
import net.psforever.objects.Player
|
||||
import net.psforever.objects.teamwork.Squad
|
||||
import net.psforever.objects.teamwork.{Member, Squad}
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||
import services.{GenericEventBus, Service}
|
||||
|
||||
import scala.collection.concurrent.TrieMap
|
||||
|
|
@ -17,7 +17,7 @@ class SquadService extends Actor {
|
|||
private var memberToSquad : TrieMap[String, Squad] = new TrieMap[String, Squad]()
|
||||
private var idToSquad : TrieMap[PlanetSideGUID, Squad] = new TrieMap[PlanetSideGUID, Squad]()
|
||||
private var i : Int = 1
|
||||
private var publishedLists : TrieMap[PlanetSideEmpire.Value, ListBuffer[SquadInfo]] = TrieMap[PlanetSideEmpire.Value, ListBuffer[SquadInfo]](
|
||||
private val publishedLists : TrieMap[PlanetSideEmpire.Value, ListBuffer[SquadInfo]] = TrieMap[PlanetSideEmpire.Value, ListBuffer[SquadInfo]](
|
||||
PlanetSideEmpire.TR -> ListBuffer.empty,
|
||||
PlanetSideEmpire.NC -> ListBuffer.empty,
|
||||
PlanetSideEmpire.VS -> ListBuffer.empty
|
||||
|
|
@ -41,28 +41,51 @@ class SquadService extends Actor {
|
|||
PlanetSideGUID(out)
|
||||
}
|
||||
|
||||
def GetSquadFromPlayer(player : Player) : Squad = {
|
||||
val name = player.Name
|
||||
val faction = player.Faction
|
||||
memberToSquad.get(name) match {
|
||||
case Some(squad) =>
|
||||
squad
|
||||
def GetParticipatingSquad(player : Player, zone : Int) : Option[Squad] = {
|
||||
memberToSquad.get(player.Name) match {
|
||||
case opt @ Some(squad) =>
|
||||
squad.Membership.find(_.Name == player.Name).get.ZoneId = zone
|
||||
opt
|
||||
case None =>
|
||||
val id = GetNextSquadId()
|
||||
val squad = new Squad(id, faction)
|
||||
val leadPosition = squad.Membership(squad.LeaderPositionIndex)
|
||||
leadPosition.Name = name
|
||||
leadPosition.Health = player.Health
|
||||
leadPosition.Armor = player.Armor
|
||||
leadPosition.Position = player.Position
|
||||
leadPosition.ZoneId = 1 //player.Continent //TODO how to resolve this?
|
||||
log.info(s"$name-$faction has started a new squad")
|
||||
memberToSquad += name -> squad
|
||||
idToSquad += id -> squad
|
||||
squad
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
def GetLeadingSquad(player : Player, zone : Int, opt : Option[Squad]) : Squad = {
|
||||
val name = player.Name
|
||||
val squadOut = opt match {
|
||||
case Some(squad) =>
|
||||
if(squad.Leader.equals(name)) {
|
||||
squad
|
||||
}
|
||||
else {
|
||||
GetLeadingSquad(player, zone, None)
|
||||
}
|
||||
|
||||
case None =>
|
||||
memberToSquad.get(name) match {
|
||||
case Some(squad) if squad.Leader.equals(name) =>
|
||||
squad
|
||||
case _ =>
|
||||
val faction = player.Faction
|
||||
val id = GetNextSquadId()
|
||||
val squad = new Squad(id, faction)
|
||||
val leadPosition = squad.Membership(squad.LeaderPositionIndex)
|
||||
leadPosition.Name = name
|
||||
leadPosition.Health = player.Health
|
||||
leadPosition.Armor = player.Armor
|
||||
leadPosition.Position = player.Position
|
||||
leadPosition.ZoneId = zone
|
||||
log.info(s"$name-$faction has started a new squad")
|
||||
memberToSquad += name -> squad
|
||||
idToSquad += id -> squad
|
||||
squad
|
||||
}
|
||||
}
|
||||
squadOut.Membership(squadOut.LeaderPositionIndex).ZoneId = zone
|
||||
squadOut
|
||||
}
|
||||
|
||||
val SquadEvents = new GenericEventBus[SquadServiceResponse]
|
||||
|
||||
def receive : Receive = {
|
||||
|
|
@ -84,167 +107,306 @@ class SquadService extends Actor {
|
|||
//check for renewable squad information
|
||||
memberToSquad.get(name) match {
|
||||
case None => ;
|
||||
case Some(squad) =>
|
||||
sender ! SquadServiceMessage.RecoverSquadMembership()
|
||||
case Some(_) =>
|
||||
sender ! SquadServiceMessage.RecoverSquadMembership() //TODO?
|
||||
}
|
||||
|
||||
case Service.Leave(Some(name)) => ;
|
||||
SquadEvents.unsubscribe(sender())
|
||||
memberToSquad.get(name) match {
|
||||
case Some(squad) =>
|
||||
if(squad.Leader.equals(name)) {
|
||||
//we were the leader
|
||||
if(squad.Membership.count(p => p.Name.equals("")) > 1) {
|
||||
//other players were in the squad; publicly disband it
|
||||
squad.Membership.foreach(position => {
|
||||
position.Name = ""
|
||||
position.ZoneId = 0
|
||||
position.Position = Vector3.Zero
|
||||
position.Health = 0
|
||||
position.Armor = 0
|
||||
})
|
||||
}
|
||||
memberToSquad.remove(name)
|
||||
idToSquad.remove(squad.GUID)
|
||||
UpdateSquadList(squad, List())
|
||||
}
|
||||
else {
|
||||
//we were just a grunt in the squad
|
||||
val position = squad.Membership.find(_.Name == name).get
|
||||
position.Name = ""
|
||||
position.ZoneId = 0
|
||||
position.Position = Vector3.Zero
|
||||
position.Health = 0
|
||||
position.Armor = 0
|
||||
UpdateSquadDetail(squad)
|
||||
}
|
||||
case None => ;
|
||||
}
|
||||
//TODO leave squad, if joined to one, and perform clean-up
|
||||
|
||||
case Service.Leave(None) | Service.LeaveAll() =>
|
||||
SquadEvents.unsubscribe(sender())
|
||||
//TODO might be better to invalidate these
|
||||
case Service.Leave(None) | Service.LeaveAll() => ;
|
||||
|
||||
case SquadServiceMessage.SquadDefinitionAction(tplayer, zone_ordinal_number, _, _, action) =>
|
||||
case SquadServiceMessage.SquadDefinitionAction(tplayer, zone_ordinal_number, guid, _, action) =>
|
||||
import net.psforever.packet.game.SquadAction._
|
||||
val squad = GetSquadFromPlayer(tplayer)
|
||||
val member = squad.Membership.find(_.Name == tplayer.Name).get //should never fail
|
||||
member.ZoneId = zone_ordinal_number //TODO improve this requirement
|
||||
if(tplayer.Name.equals(squad.Leader)) {
|
||||
var listingChanged : List[Int] = Nil
|
||||
action match {
|
||||
case ChangeSquadPurpose(purpose) =>
|
||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has changed his squad's task to $purpose")
|
||||
squad.Description = purpose
|
||||
listingChanged = List(SquadInfo.Field.Task)
|
||||
val squadOpt = GetParticipatingSquad(tplayer, zone_ordinal_number)
|
||||
action match {
|
||||
case ChangeSquadPurpose(purpose) =>
|
||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has changed his squad's task to $purpose")
|
||||
val squad = GetLeadingSquad(tplayer, zone_ordinal_number, squadOpt)
|
||||
squad.Task = purpose
|
||||
UpdateSquadList(squad, List(SquadInfo.Field.Task))
|
||||
UpdateSquadDetail(squad)
|
||||
|
||||
case ChangeSquadZone(zone) =>
|
||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has changed his squad's ops zone to $zone")
|
||||
squad.ZoneId = zone.zoneId.toInt
|
||||
listingChanged = List(SquadInfo.Field.ZoneId)
|
||||
case ChangeSquadZone(zone) =>
|
||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has changed squad's ops zone to $zone")
|
||||
val squad = GetLeadingSquad(tplayer, zone_ordinal_number, squadOpt)
|
||||
squad.ZoneId = zone.zoneId.toInt
|
||||
UpdateSquadList(squad, List(SquadInfo.Field.ZoneId))
|
||||
UpdateSquadDetail(squad)
|
||||
|
||||
case CloseSquadMemberPosition(position) =>
|
||||
if(position != squad.LeaderPositionIndex) {
|
||||
squad.Availability.lift(position) match {
|
||||
case Some(true) =>
|
||||
squad.Availability.update(position, false)
|
||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has closed the #$position position in his squad")
|
||||
val memberPosition = squad.Membership(position)
|
||||
listingChanged = if(memberPosition.Name.nonEmpty) {
|
||||
List(SquadInfo.Field.Size, SquadInfo.Field.Capacity)
|
||||
case CloseSquadMemberPosition(position) =>
|
||||
val squad = GetLeadingSquad(tplayer, zone_ordinal_number, squadOpt)
|
||||
squad.Availability.lift(position) match {
|
||||
case Some(true) =>
|
||||
squad.Availability.update(position, false)
|
||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has closed the #$position position in squad")
|
||||
val memberPosition = squad.Membership(position)
|
||||
val listingChanged = if(memberPosition.Name.nonEmpty) {
|
||||
List(SquadInfo.Field.Size, SquadInfo.Field.Capacity)
|
||||
}
|
||||
else {
|
||||
List(SquadInfo.Field.Capacity)
|
||||
}
|
||||
memberPosition.Close()
|
||||
UpdateSquadList(squad, listingChanged)
|
||||
UpdateSquadDetail(squad)
|
||||
case Some(false) | None => ;
|
||||
}
|
||||
|
||||
case AddSquadMemberPosition(position) =>
|
||||
val squad = GetLeadingSquad(tplayer, zone_ordinal_number, squadOpt)
|
||||
squad.Availability.lift(position) match {
|
||||
case Some(false) =>
|
||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has opened the #$position position in squad")
|
||||
squad.Availability.update(position, true)
|
||||
UpdateSquadList(squad, List(SquadInfo.Field.Capacity))
|
||||
UpdateSquadDetail(squad)
|
||||
case Some(true) | None => ;
|
||||
}
|
||||
|
||||
case ChangeSquadMemberRequirementsRole(position, role) =>
|
||||
val squad = GetLeadingSquad(tplayer, zone_ordinal_number, squadOpt)
|
||||
squad.Availability.lift(position) match {
|
||||
case Some(true) =>
|
||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has changed the role of squad position #$position")
|
||||
squad.Membership(position).Role = role
|
||||
UpdateSquadDetail(squad)
|
||||
case Some(false) | None => ;
|
||||
}
|
||||
|
||||
case ChangeSquadMemberRequirementsDetailedOrders(position, orders) =>
|
||||
val squad = GetLeadingSquad(tplayer, zone_ordinal_number, squadOpt)
|
||||
squad.Availability.lift(position) match {
|
||||
case Some(true) =>
|
||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has changed the orders for squad position #$position")
|
||||
squad.Membership(position).Orders = orders
|
||||
UpdateSquadDetail(squad)
|
||||
case Some(false) | None => ;
|
||||
}
|
||||
|
||||
case ChangeSquadMemberRequirementsCertifications(position, certs) =>
|
||||
val squad = GetLeadingSquad(tplayer, zone_ordinal_number, squadOpt)
|
||||
squad.Availability.lift(position) match {
|
||||
case Some(true) =>
|
||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has changed the requirements for squad position #$position")
|
||||
squad.Membership(position).Requirements = certs
|
||||
UpdateSquadDetail(squad)
|
||||
case Some(false) | None => ;
|
||||
}
|
||||
|
||||
case LocationFollowsSquadLead(state) =>
|
||||
val squad = GetLeadingSquad(tplayer, zone_ordinal_number, squadOpt)
|
||||
if(state) {
|
||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has moves the rally to the leader's position")
|
||||
}
|
||||
else {
|
||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has let the rally move freely")
|
||||
}
|
||||
squad.LocationFollowsSquadLead = state
|
||||
|
||||
case AutoApproveInvitationRequests(state) =>
|
||||
val squad = GetLeadingSquad(tplayer, zone_ordinal_number, squadOpt)
|
||||
if(state) {
|
||||
log.info(s"${tplayer.Name}-${tplayer.Faction} is allowing all requests to join the squad")
|
||||
}
|
||||
else {
|
||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has started screening invitation requests")
|
||||
}
|
||||
squad.AutoApproveInvitationRequests = state
|
||||
|
||||
case SelectRoleForYourself(line) =>
|
||||
//TODO need to ask permission from the squad leader, unless our character is the squad leader or already currently in the squad
|
||||
val name = tplayer.Name
|
||||
squadOpt match {
|
||||
case Some(squad) =>
|
||||
{
|
||||
if(squad.Availability(line))
|
||||
squad.Membership.lift(line)
|
||||
else
|
||||
None
|
||||
} match {
|
||||
case Some(desiredPosition : Member)
|
||||
if desiredPosition.Requirements.intersect(tplayer.Certifications) == desiredPosition.Requirements =>
|
||||
//our character is qualified for this new position
|
||||
if(squad.Leader.equals(tplayer.Name)) {
|
||||
squad.LeaderPositionIndex = line //update
|
||||
}
|
||||
else {
|
||||
List(SquadInfo.Field.Capacity)
|
||||
val hadPreviousPosition = squad.Membership.find(_.Name == name) match {
|
||||
case Some(currentPosition)=>
|
||||
currentPosition.Name = ""
|
||||
currentPosition.ZoneId = 0
|
||||
currentPosition.Health = 0
|
||||
currentPosition.Armor = 0
|
||||
currentPosition.Position = Vector3.Zero
|
||||
true
|
||||
case None =>
|
||||
false
|
||||
}
|
||||
memberPosition.Close()
|
||||
case Some(false) => ;
|
||||
desiredPosition.Name = name
|
||||
desiredPosition.ZoneId = zone_ordinal_number
|
||||
desiredPosition.Health = tplayer.Health
|
||||
desiredPosition.Armor = tplayer.Armor
|
||||
desiredPosition.Position = tplayer.Position
|
||||
if(!hadPreviousPosition) {
|
||||
UpdateSquadList(squad, List(SquadInfo.Field.Size))
|
||||
}
|
||||
UpdateSquadDetail(squad)
|
||||
case None => ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
log.warn(s"can not close the leader position in squad-${squad.GUID.guid}")
|
||||
}
|
||||
|
||||
case AddSquadMemberPosition(position) =>
|
||||
squad.Availability.lift(position) match {
|
||||
case Some(false) =>
|
||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has opened the #$position position in his squad")
|
||||
squad.Availability.update(position, true)
|
||||
listingChanged = List(SquadInfo.Field.Capacity)
|
||||
case Some(true) => ;
|
||||
case None => ;
|
||||
}
|
||||
|
||||
case ChangeSquadMemberRequirementsRole(position, role) =>
|
||||
squad.Availability.lift(position) match {
|
||||
case Some(true) =>
|
||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has changed the role of squad position #$position")
|
||||
squad.Membership(position).Role = role
|
||||
case Some(false) => ;
|
||||
case None => ;
|
||||
}
|
||||
|
||||
case ChangeSquadMemberRequirementsDetailedOrders(position, orders) =>
|
||||
squad.Availability.lift(position) match {
|
||||
case Some(true) =>
|
||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has changed the orders for squad position #$position")
|
||||
squad.Membership(position).Orders = orders
|
||||
case Some(false) => ;
|
||||
case None => ;
|
||||
}
|
||||
|
||||
case ChangeSquadMemberRequirementsCertifications(position, certs) =>
|
||||
squad.Availability.lift(position) match {
|
||||
case Some(true) =>
|
||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has changed the requirements for squad position #$position")
|
||||
squad.Membership(position).Requirements = certs
|
||||
case Some(false) => ;
|
||||
case None => ;
|
||||
}
|
||||
|
||||
case ListSquad() =>
|
||||
if(!squad.Listed) {
|
||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has opened recruitment for his squad")
|
||||
squad.Listed = true
|
||||
}
|
||||
|
||||
case ResetAll() =>
|
||||
squad.Description = ""
|
||||
squad.ZoneId = None
|
||||
squad.Availability.indices.foreach { i =>
|
||||
squad.Availability.update(i, true)
|
||||
}
|
||||
//TODO squad members?
|
||||
|
||||
case _ => ;
|
||||
}
|
||||
//queue updates
|
||||
if(squad.Listed) {
|
||||
val entry = SquadService.Publish(squad)
|
||||
val faction = squad.Faction
|
||||
val factionListings = publishedLists(faction)
|
||||
factionListings.find(info => {
|
||||
info.squad_guid match {
|
||||
case Some(guid) => guid == squad.GUID
|
||||
case _ => false
|
||||
}
|
||||
}) match {
|
||||
case Some(listedSquad) =>
|
||||
val index = factionListings.indexOf(listedSquad)
|
||||
val changes = if(listingChanged.nonEmpty) {
|
||||
SquadService.Differences(listingChanged, entry)
|
||||
}
|
||||
else {
|
||||
SquadService.Differences(listedSquad, entry)
|
||||
}
|
||||
if(changes != SquadInfo.Blank) {
|
||||
//squad information update
|
||||
log.info(s"Squad will be updated")
|
||||
factionListings(index) = entry
|
||||
SquadEvents.publish(
|
||||
SquadServiceResponse(s"$faction/Squad", SquadResponse.Update(Seq((index, changes))))
|
||||
)
|
||||
}
|
||||
else {
|
||||
//remove squad from listing
|
||||
log.info(s"Squad will be removed")
|
||||
factionListings.remove(index)
|
||||
SquadEvents.publish(
|
||||
SquadServiceResponse(s"$faction/Squad", SquadResponse.Remove(Seq(index)))
|
||||
)
|
||||
}
|
||||
case None =>
|
||||
//first time being published
|
||||
log.info(s"Squad will be introduced")
|
||||
factionListings += SquadService.Publish(squad)
|
||||
SquadEvents.publish(
|
||||
SquadServiceResponse(s"$faction/Squad", SquadResponse.Init(factionListings.toVector))
|
||||
)
|
||||
case None => ;
|
||||
}
|
||||
}
|
||||
|
||||
case ListSquad() =>
|
||||
val squad = GetLeadingSquad(tplayer, zone_ordinal_number, squadOpt)
|
||||
if(!squad.Listed) {
|
||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has opened recruitment for this squad")
|
||||
squad.Listed = true
|
||||
}
|
||||
UpdateSquadList(squad, List())
|
||||
|
||||
case ResetAll() =>
|
||||
val squad = GetLeadingSquad(tplayer, zone_ordinal_number, squadOpt)
|
||||
squad.Task = ""
|
||||
squad.ZoneId = None
|
||||
squad.Availability.indices.foreach { i =>
|
||||
squad.Availability.update(i, true)
|
||||
}
|
||||
squad.Membership.foreach(position => {
|
||||
position.Role = ""
|
||||
position.Orders = ""
|
||||
position.Requirements = Set()
|
||||
})
|
||||
UpdateSquadList(squad, List(SquadInfo.Field.Task, SquadInfo.Field.ZoneId, SquadInfo.Field.Size, SquadInfo.Field.Capacity))
|
||||
UpdateSquadDetail(squad)
|
||||
|
||||
case DisplaySquad() =>
|
||||
idToSquad.get(guid) match {
|
||||
case Some(squad) =>
|
||||
sender ! SquadServiceResponse(s"${tplayer.Name}/Squad", GenSquadDetail(squad))
|
||||
case None => ;
|
||||
}
|
||||
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
case msg =>
|
||||
log.info(s"Unhandled message $msg from $sender")
|
||||
}
|
||||
|
||||
def UpdateSquadList(squad : Squad, listingChanged : List[Int]) : Unit = {
|
||||
//queue updates
|
||||
if(squad.Listed) {
|
||||
val entry = SquadService.Publish(squad)
|
||||
val faction = squad.Faction
|
||||
val factionListings = publishedLists(faction)
|
||||
factionListings.find(info => {
|
||||
info.squad_guid match {
|
||||
case Some(sguid) => sguid == squad.GUID
|
||||
case _ => false
|
||||
}
|
||||
}) match {
|
||||
case Some(listedSquad) =>
|
||||
val index = factionListings.indexOf(listedSquad)
|
||||
val changes = if(listingChanged.nonEmpty) {
|
||||
SquadService.Differences(listingChanged, entry)
|
||||
}
|
||||
else {
|
||||
SquadService.Differences(listedSquad, entry)
|
||||
}
|
||||
if(changes != SquadInfo.Blank) {
|
||||
//squad information update
|
||||
log.info(s"Squad will be updated")
|
||||
factionListings(index) = entry
|
||||
SquadEvents.publish(
|
||||
SquadServiceResponse(s"$faction/Squad", SquadResponse.Update(Seq((index, changes))))
|
||||
)
|
||||
}
|
||||
else {
|
||||
//remove squad from listing
|
||||
log.info(s"Squad will be removed")
|
||||
factionListings.remove(index)
|
||||
SquadEvents.publish(
|
||||
SquadServiceResponse(s"$faction/Squad", SquadResponse.Remove(Seq(index)))
|
||||
)
|
||||
}
|
||||
case None =>
|
||||
//first time being published
|
||||
log.info(s"Squad will be introduced")
|
||||
factionListings += SquadService.Publish(squad)
|
||||
SquadEvents.publish(
|
||||
SquadServiceResponse(s"$faction/Squad", SquadResponse.Init(factionListings.toVector))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def GenSquadDetail(squad : Squad) : SquadResponse.Detail = {
|
||||
SquadResponse.Detail(
|
||||
squad.GUID,
|
||||
squad.Leader,
|
||||
squad.Task,
|
||||
PlanetSideZoneID(squad.ZoneId),
|
||||
squad.Membership.zipWithIndex.map({ case (p, index) =>
|
||||
if(squad.Availability(index)) {
|
||||
SquadPositionDetail(p.Role, p.Orders, p.Requirements, p.Name)
|
||||
}
|
||||
else {
|
||||
SquadPositionDetail.Closed
|
||||
}
|
||||
}).toList
|
||||
)
|
||||
}
|
||||
|
||||
def UpdateSquadDetail(squad : Squad) : Unit = {
|
||||
val detail = GenSquadDetail(squad)
|
||||
squad.Membership.collect {
|
||||
case member if !member.Name.equals("") =>
|
||||
member.Name
|
||||
}.foreach { name =>
|
||||
SquadEvents.publish(
|
||||
SquadServiceResponse(s"$name/Squad", detail)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object SquadService {
|
||||
def Publish(squad : Squad) : SquadInfo = {
|
||||
SquadInfo(
|
||||
squad.Leader,
|
||||
squad.Description,
|
||||
squad.Task,
|
||||
PlanetSideZoneID(squad.ZoneId),
|
||||
squad.Size,
|
||||
squad.Capacity,
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@
|
|||
package services.teamwork
|
||||
|
||||
import net.psforever.objects.Player
|
||||
import net.psforever.packet.game.SquadAction
|
||||
import net.psforever.packet.game.{PlanetSideGUID, SquadAction}
|
||||
|
||||
final case class SquadServiceMessage(forChannel : String, actionMessage : Any)
|
||||
|
||||
object SquadServiceMessage {
|
||||
final case class SquadDefinitionAction(player : Player, zone_ordinal_number : Int, u1 : Int, u2 : Int, action : SquadAction)
|
||||
final case class SquadDefinitionAction(player : Player, zone_ordinal_number : Int, guid : PlanetSideGUID, line : Int, action : SquadAction)
|
||||
|
||||
final case class RecoverSquadMembership()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (00)" in {
|
||||
PacketCoding.DecodePacket(string_00).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 3
|
||||
unk1 mustEqual PlanetSideGUID(3)
|
||||
unk2 mustEqual 0
|
||||
action mustEqual DisplaySquad()
|
||||
case _ =>
|
||||
|
|
@ -52,7 +52,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (03)" in {
|
||||
PacketCoding.DecodePacket(string_03).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 3
|
||||
action mustEqual SaveSquadDefinition()
|
||||
case _ =>
|
||||
|
|
@ -63,7 +63,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (03)" in {
|
||||
PacketCoding.DecodePacket(string_04).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 3
|
||||
action mustEqual LoadSquadDefinition()
|
||||
case _ =>
|
||||
|
|
@ -74,7 +74,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (07)" in {
|
||||
PacketCoding.DecodePacket(string_07).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 3
|
||||
action mustEqual ListSquadDefinition("Cops and Military Officers")
|
||||
case _ =>
|
||||
|
|
@ -85,7 +85,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (08)" in {
|
||||
PacketCoding.DecodePacket(string_08).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 0
|
||||
action mustEqual ListSquad()
|
||||
case _ =>
|
||||
|
|
@ -96,7 +96,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (10)" in {
|
||||
PacketCoding.DecodePacket(string_10).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 0
|
||||
action mustEqual SelectRoleForYourself(1)
|
||||
case _ =>
|
||||
|
|
@ -107,7 +107,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (19)" in {
|
||||
PacketCoding.DecodePacket(string_19).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 0
|
||||
action mustEqual ChangeSquadPurpose("A-Team")
|
||||
case _ =>
|
||||
|
|
@ -118,7 +118,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (20)" in {
|
||||
PacketCoding.DecodePacket(string_20).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 0
|
||||
action mustEqual ChangeSquadZone(PlanetSideZoneID(1))
|
||||
case _ =>
|
||||
|
|
@ -129,7 +129,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (21)" in {
|
||||
PacketCoding.DecodePacket(string_21).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 0
|
||||
action mustEqual CloseSquadMemberPosition(2)
|
||||
case _ =>
|
||||
|
|
@ -140,7 +140,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (22)" in {
|
||||
PacketCoding.DecodePacket(string_22).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 0
|
||||
action mustEqual AddSquadMemberPosition(2)
|
||||
case _ =>
|
||||
|
|
@ -151,7 +151,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (23)" in {
|
||||
PacketCoding.DecodePacket(string_23).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 0
|
||||
action mustEqual ChangeSquadMemberRequirementsRole(1, "BLUFOR")
|
||||
case _ =>
|
||||
|
|
@ -162,7 +162,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (24)" in {
|
||||
PacketCoding.DecodePacket(string_24).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 0
|
||||
action mustEqual ChangeSquadMemberRequirementsDetailedOrders(1, "kill bad dudes")
|
||||
case _ =>
|
||||
|
|
@ -173,7 +173,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (25)" in {
|
||||
PacketCoding.DecodePacket(string_25).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 0
|
||||
action mustEqual ChangeSquadMemberRequirementsCertifications(
|
||||
1,
|
||||
|
|
@ -187,7 +187,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (26)" in {
|
||||
PacketCoding.DecodePacket(string_26).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 0
|
||||
action mustEqual ResetAll()
|
||||
case _ =>
|
||||
|
|
@ -198,7 +198,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (28)" in {
|
||||
PacketCoding.DecodePacket(string_28).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 0
|
||||
action mustEqual AutoApproveInvitationRequests(true)
|
||||
case _ =>
|
||||
|
|
@ -209,7 +209,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (31)" in {
|
||||
PacketCoding.DecodePacket(string_31).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 0
|
||||
action mustEqual LocationFollowsSquadLead(true)
|
||||
case _ =>
|
||||
|
|
@ -220,7 +220,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (34a)" in {
|
||||
PacketCoding.DecodePacket(string_34a).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 0
|
||||
action mustEqual SearchForSquadsWithParticularRole("Badass", 0L, 1, 0)
|
||||
case _ =>
|
||||
|
|
@ -231,7 +231,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (34b)" in {
|
||||
PacketCoding.DecodePacket(string_34b).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 0
|
||||
action mustEqual SearchForSquadsWithParticularRole("Badass", 0L, 2, 0)
|
||||
case _ =>
|
||||
|
|
@ -242,7 +242,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (34c)" in {
|
||||
PacketCoding.DecodePacket(string_34c).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 0
|
||||
action mustEqual SearchForSquadsWithParticularRole("Badass", 0L, 2, 1)
|
||||
case _ =>
|
||||
|
|
@ -253,7 +253,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (34d)" in {
|
||||
PacketCoding.DecodePacket(string_34d).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 0
|
||||
action mustEqual SearchForSquadsWithParticularRole("Badass", 536870928L, 2, 2)
|
||||
case _ =>
|
||||
|
|
@ -264,7 +264,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (34e)" in {
|
||||
PacketCoding.DecodePacket(string_34e).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 0
|
||||
action mustEqual SearchForSquadsWithParticularRole("Badass", 536870928L, 2, 3)
|
||||
case _ =>
|
||||
|
|
@ -275,7 +275,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (35)" in {
|
||||
PacketCoding.DecodePacket(string_35).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 0
|
||||
action mustEqual CancelSquadSearch()
|
||||
case _ =>
|
||||
|
|
@ -286,7 +286,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (40)" in {
|
||||
PacketCoding.DecodePacket(string_40).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 0
|
||||
action mustEqual FindLfsSoldiersForRole(1)
|
||||
case _ =>
|
||||
|
|
@ -297,7 +297,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (41)" in {
|
||||
PacketCoding.DecodePacket(string_41).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 0
|
||||
action mustEqual CancelFind()
|
||||
case _ =>
|
||||
|
|
@ -308,7 +308,7 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
"decode (43, unknown)" in {
|
||||
PacketCoding.DecodePacket(string_43).require match {
|
||||
case SquadDefinitionActionMessage(unk1, unk2, action) =>
|
||||
unk1 mustEqual 0
|
||||
unk1 mustEqual PlanetSideGUID(0)
|
||||
unk2 mustEqual 0
|
||||
action mustEqual Unknown(43, hex"00".toBitVector.take(6))
|
||||
case _ =>
|
||||
|
|
@ -321,91 +321,91 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
}
|
||||
|
||||
"encode (00)" in {
|
||||
val msg = SquadDefinitionActionMessage(3, 0, DisplaySquad())
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(3), 0, DisplaySquad())
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_00
|
||||
}
|
||||
|
||||
"encode (03)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 3, SaveSquadDefinition())
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 3, SaveSquadDefinition())
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_03
|
||||
}
|
||||
|
||||
"encode (03)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 3, LoadSquadDefinition())
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 3, LoadSquadDefinition())
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_04
|
||||
}
|
||||
|
||||
"encode (07)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 3, ListSquadDefinition("Cops and Military Officers"))
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 3, ListSquadDefinition("Cops and Military Officers"))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_07
|
||||
}
|
||||
|
||||
"encode (08)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 0, ListSquad())
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 0, ListSquad())
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_08
|
||||
}
|
||||
|
||||
"encode (10)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 0, SelectRoleForYourself(1))
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 0, SelectRoleForYourself(1))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_10
|
||||
}
|
||||
|
||||
"encode (19)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 0, ChangeSquadPurpose("A-Team"))
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 0, ChangeSquadPurpose("A-Team"))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_19
|
||||
}
|
||||
|
||||
"encode (20)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 0, ChangeSquadZone(PlanetSideZoneID(1)))
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 0, ChangeSquadZone(PlanetSideZoneID(1)))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_20
|
||||
}
|
||||
|
||||
"encode (21)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 0, CloseSquadMemberPosition(2))
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 0, CloseSquadMemberPosition(2))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_21
|
||||
}
|
||||
|
||||
"encode (22)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 0, AddSquadMemberPosition(2))
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 0, AddSquadMemberPosition(2))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_22
|
||||
}
|
||||
|
||||
"encode (23)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 0, ChangeSquadMemberRequirementsRole(1, "BLUFOR"))
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 0, ChangeSquadMemberRequirementsRole(1, "BLUFOR"))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_23
|
||||
}
|
||||
|
||||
"encode (24)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 0, ChangeSquadMemberRequirementsDetailedOrders(1, "kill bad dudes"))
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 0, ChangeSquadMemberRequirementsDetailedOrders(1, "kill bad dudes"))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_24
|
||||
}
|
||||
|
||||
"encode (25)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 0, ChangeSquadMemberRequirementsCertifications(
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 0, ChangeSquadMemberRequirementsCertifications(
|
||||
1,
|
||||
Set(CertificationType.AntiVehicular, CertificationType.InfiltrationSuit)
|
||||
))
|
||||
|
|
@ -415,84 +415,84 @@ class SquadDefinitionActionMessageTest extends Specification {
|
|||
}
|
||||
|
||||
"encode (26)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 0, ResetAll())
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 0, ResetAll())
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_26
|
||||
}
|
||||
|
||||
"encode (28)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 0, AutoApproveInvitationRequests(true))
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 0, AutoApproveInvitationRequests(true))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_28
|
||||
}
|
||||
|
||||
"encode (31)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 0, LocationFollowsSquadLead(true))
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 0, LocationFollowsSquadLead(true))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_31
|
||||
}
|
||||
|
||||
"encode (34a)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 0, SearchForSquadsWithParticularRole("Badass", 0L, 1, 0))
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 0, SearchForSquadsWithParticularRole("Badass", 0L, 1, 0))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_34a
|
||||
}
|
||||
|
||||
"encode (34b)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 0, SearchForSquadsWithParticularRole("Badass", 0L, 2, 0))
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 0, SearchForSquadsWithParticularRole("Badass", 0L, 2, 0))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_34b
|
||||
}
|
||||
|
||||
"encode (34c)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 0, SearchForSquadsWithParticularRole("Badass", 0L, 2, 1))
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 0, SearchForSquadsWithParticularRole("Badass", 0L, 2, 1))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_34c
|
||||
}
|
||||
|
||||
"encode (34d)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 0, SearchForSquadsWithParticularRole("Badass", 536870928L, 2, 2))
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 0, SearchForSquadsWithParticularRole("Badass", 536870928L, 2, 2))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_34d
|
||||
}
|
||||
|
||||
"encode (34e)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 0, SearchForSquadsWithParticularRole("Badass", 536870928L, 2, 3))
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 0, SearchForSquadsWithParticularRole("Badass", 536870928L, 2, 3))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_34e
|
||||
}
|
||||
|
||||
"encode (35)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 0, CancelSquadSearch())
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 0, CancelSquadSearch())
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_35
|
||||
}
|
||||
|
||||
"encode (40)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 0, FindLfsSoldiersForRole(1))
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 0, FindLfsSoldiersForRole(1))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_40
|
||||
}
|
||||
|
||||
"encode (41)" in {
|
||||
val msg = SquadDefinitionActionMessage(0, 0, CancelFind())
|
||||
val msg = SquadDefinitionActionMessage(PlanetSideGUID(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 msg = SquadDefinitionActionMessage(PlanetSideGUID(0), 0, Unknown(43, BitVector.empty))
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_43
|
||||
|
|
|
|||
|
|
@ -370,6 +370,17 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}.toVector
|
||||
)
|
||||
)
|
||||
|
||||
case SquadResponse.Detail(guid, leader, task, zone, member_info) =>
|
||||
sendResponse(
|
||||
SquadDetailDefinitionUpdateMessage(
|
||||
guid,
|
||||
leader,
|
||||
task,
|
||||
zone,
|
||||
member_info
|
||||
)
|
||||
)
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
|
|
@ -2850,7 +2861,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
})
|
||||
//AvatarAwardMessage
|
||||
//DisplayAwardMessage
|
||||
//SquadDefinitionActionMessage and SquadDetailDefinitionUpdateMessage
|
||||
//SquadDefinitionActionMessage and SquadDetailDefinitionUpdateMessage; handled elsewhere
|
||||
//MapObjectStateBlockMessage and ObjectCreateMessage?
|
||||
//TacticsMessage?
|
||||
//change the owner on our deployables (re-draw the icons for our deployables too)
|
||||
|
|
@ -2885,35 +2896,35 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
interstellarFerryTopLevelGUID = None
|
||||
case _ => ;
|
||||
}
|
||||
sendResponse(ReplicationStreamMessage(
|
||||
5,
|
||||
Some(6),
|
||||
Vector(
|
||||
SquadListing(0, SquadInfo(Some("xNick"), Some("FLY,ALL WELCOME!"), Some(PlanetSideZoneID(7)), Some(8), Some(10), Some(PlanetSideGUID(1)))),
|
||||
SquadListing(1, SquadInfo(Some("HofD"), Some("=KOK+SPC+FLY= All Welcome"), Some(PlanetSideZoneID(7)), Some(3), Some(10), Some(PlanetSideGUID(3))))
|
||||
)
|
||||
))
|
||||
//sendRawResponse(hex"e803008484000c800259e8809fda020043004a0069006d006d0079006e009b48006f006d006900630069006400690061006c00200053006d007500720066007300200041006e006f006e0079006d006f007500730004000000981401064580540061006e006b002000440072006900760065007200a05200650063006f006d006d0065006e00640065006400200074006f0020006800610076006500200065006e00670069006e0065006500720069006e0067002e0000000000800180000c00020c8c46007200650065006200690065002000730070006f007400cf44006f002000770068006100740065007600650072002c0020006200750074002000700072006500660065007200610062006c007900200073007400690063006b002000770069007400680020007400680065002000730071007500610064002e00200044006f006e002700740020006e00650065006400200061006e007900200073007000650063006900660069006300200063006500720074002e0096e27a0290540068006500460069006e0061006c005300740072007500670067006c0065000000000000020c8c46007200650065006200690065002000530070006f007400cf44006f002000770068006100740065007600650072002c0020006200750074002000700072006500660065007200610062006c007900200073007400690063006b002000770069007400680020007400680065002000730071007500610064002e00200044006f006e002700740020006e00650065006400200061006e007900200073007000650063006900660069006300200063006500720074002e0000000000800000000000020c8a41004d0053002000440072006900760065007200b34700690076006500200075007300200073007000610077006e00200070006f0069006e00740073002c0020006800610063006b0069006e006700200061006e006400200069006e00660069006c0020006100720065002000750073006500660075006c002e00fb02790287440030004f004d006700750079000100020c00020c8d410076006500720061006700650020004a0069006d006d007900a05200650069006e0066006f0072006300650064002000450078006f007300750069007400200077006f0075006c00640020006200650020006e0069006300650000000000800300000c00020c8b4100760065007200610067006500200042006f006200a05200650069006e0066006f0072006300650064002000450078006f007300750069007400200077006f0075006c00640020006200650020006e0069006300650000000000800300000c00020c8b410076006500720061006700650020004a006f006500a05200650069006e0066006f0072006300650064002000450078006f007300750069007400200077006f0075006c00640020006200650020006e0069006300650000000000800300000c00020c8753007500700070006f0072007400a2520065007300730075007200650063007400200073006f006c00640069006500720073002c0020006b00650065007000200075007300200061006c006900760065002e0000000000800100000c0c0a0c8845006e00670069006e00650065007200a043006f006d00620061007400200045006e00670069006e0065006500720069006e006700200077006f0075006c00640020006200650020006e0069006300650004b3d101864a0069006d006d0079006e000100000c000a0c854d0065006400690063009a4100640076002e0020004d00650064006900630061006c00200077006f0075006c00640020006200650020006e0069006300650000000000800100000c0400")
|
||||
sendResponse(
|
||||
SquadDetailDefinitionUpdateMessage(
|
||||
PlanetSideGUID(3),
|
||||
"HofD",
|
||||
"\\#ffdc00***\\#9640ff=KOK+SPC+FLY=\\#ffdc00***\\#FF4040 All Welcome",
|
||||
PlanetSideZoneID(7),
|
||||
List(
|
||||
SquadPositionDetail("\\#ff0000 |||||||||||||||||||||||", "Just a space filler"),
|
||||
SquadPositionDetail("\\#ffdc00 C", ""),
|
||||
SquadPositionDetail("\\#ffdc00 H", "", "OpoIE"),
|
||||
SquadPositionDetail("\\#ffdc00 I", "", "BobaF3tt907"),
|
||||
SquadPositionDetail("\\#ffdc00 N", ""),
|
||||
SquadPositionDetail("\\#ffdc00 A", ""),
|
||||
SquadPositionDetail("\\#ff0000 |||||||||||||||||||||||", "Another space filler"),
|
||||
SquadPositionDetail("\\#9640ff K", ""),
|
||||
SquadPositionDetail("\\#9640ff O", "", "HofD"),
|
||||
SquadPositionDetail("\\#9640ff K", "")
|
||||
)
|
||||
)
|
||||
)
|
||||
// sendResponse(ReplicationStreamMessage(
|
||||
// 5,
|
||||
// Some(6),
|
||||
// Vector(
|
||||
// SquadListing(0, SquadInfo(Some("xNick"), Some("FLY,ALL WELCOME!"), Some(PlanetSideZoneID(7)), Some(8), Some(10), Some(PlanetSideGUID(1)))),
|
||||
// SquadListing(1, SquadInfo(Some("HofD"), Some("=KOK+SPC+FLY= All Welcome"), Some(PlanetSideZoneID(7)), Some(3), Some(10), Some(PlanetSideGUID(3))))
|
||||
// )
|
||||
// ))
|
||||
// //sendRawResponse(hex"e803008484000c800259e8809fda020043004a0069006d006d0079006e009b48006f006d006900630069006400690061006c00200053006d007500720066007300200041006e006f006e0079006d006f007500730004000000981401064580540061006e006b002000440072006900760065007200a05200650063006f006d006d0065006e00640065006400200074006f0020006800610076006500200065006e00670069006e0065006500720069006e0067002e0000000000800180000c00020c8c46007200650065006200690065002000730070006f007400cf44006f002000770068006100740065007600650072002c0020006200750074002000700072006500660065007200610062006c007900200073007400690063006b002000770069007400680020007400680065002000730071007500610064002e00200044006f006e002700740020006e00650065006400200061006e007900200073007000650063006900660069006300200063006500720074002e0096e27a0290540068006500460069006e0061006c005300740072007500670067006c0065000000000000020c8c46007200650065006200690065002000530070006f007400cf44006f002000770068006100740065007600650072002c0020006200750074002000700072006500660065007200610062006c007900200073007400690063006b002000770069007400680020007400680065002000730071007500610064002e00200044006f006e002700740020006e00650065006400200061006e007900200073007000650063006900660069006300200063006500720074002e0000000000800000000000020c8a41004d0053002000440072006900760065007200b34700690076006500200075007300200073007000610077006e00200070006f0069006e00740073002c0020006800610063006b0069006e006700200061006e006400200069006e00660069006c0020006100720065002000750073006500660075006c002e00fb02790287440030004f004d006700750079000100020c00020c8d410076006500720061006700650020004a0069006d006d007900a05200650069006e0066006f0072006300650064002000450078006f007300750069007400200077006f0075006c00640020006200650020006e0069006300650000000000800300000c00020c8b4100760065007200610067006500200042006f006200a05200650069006e0066006f0072006300650064002000450078006f007300750069007400200077006f0075006c00640020006200650020006e0069006300650000000000800300000c00020c8b410076006500720061006700650020004a006f006500a05200650069006e0066006f0072006300650064002000450078006f007300750069007400200077006f0075006c00640020006200650020006e0069006300650000000000800300000c00020c8753007500700070006f0072007400a2520065007300730075007200650063007400200073006f006c00640069006500720073002c0020006b00650065007000200075007300200061006c006900760065002e0000000000800100000c0c0a0c8845006e00670069006e00650065007200a043006f006d00620061007400200045006e00670069006e0065006500720069006e006700200077006f0075006c00640020006200650020006e0069006300650004b3d101864a0069006d006d0079006e000100000c000a0c854d0065006400690063009a4100640076002e0020004d00650064006900630061006c00200077006f0075006c00640020006200650020006e0069006300650000000000800100000c0400")
|
||||
// sendResponse(
|
||||
// SquadDetailDefinitionUpdateMessage(
|
||||
// PlanetSideGUID(3),
|
||||
// "HofD",
|
||||
// "\\#ffdc00***\\#9640ff=KOK+SPC+FLY=\\#ffdc00***\\#FF4040 All Welcome",
|
||||
// PlanetSideZoneID(7),
|
||||
// List(
|
||||
// SquadPositionDetail("\\#ff0000 |||||||||||||||||||||||", "Just a space filler"),
|
||||
// SquadPositionDetail("\\#ffdc00 C", ""),
|
||||
// SquadPositionDetail("\\#ffdc00 H", "", "OpoIE"),
|
||||
// SquadPositionDetail("\\#ffdc00 I", "", "BobaF3tt907"),
|
||||
// SquadPositionDetail("\\#ffdc00 N", ""),
|
||||
// SquadPositionDetail("\\#ffdc00 A", ""),
|
||||
// SquadPositionDetail("\\#ff0000 |||||||||||||||||||||||", "Another space filler"),
|
||||
// SquadPositionDetail("\\#9640ff K", ""),
|
||||
// SquadPositionDetail("\\#9640ff O", "", "HofD"),
|
||||
// SquadPositionDetail("\\#9640ff K", "")
|
||||
// )
|
||||
// )
|
||||
// )
|
||||
}
|
||||
|
||||
def handleControlPkt(pkt : PlanetSideControlPacket) = {
|
||||
|
|
@ -3325,6 +3336,11 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
|
||||
case msg @ PlayerStateMessageUpstream(avatar_guid, pos, vel, yaw, pitch, yaw_upper, seq_time, unk3, is_crouching, is_jumping, unk4, is_cloaking, unk5, unk6) =>
|
||||
if(deadState == DeadState.Alive) {
|
||||
// if(!player.Crouching && is_crouching) {
|
||||
// sendResponse(
|
||||
// SquadMembershipRequest(SquadRequestType.Unk01, 1L, Some(1L), "FateJH", Some(None))
|
||||
// )
|
||||
// }
|
||||
player.Position = pos
|
||||
player.Velocity = vel
|
||||
player.Orientation = Vector3(player.Orientation.x, pitch, yaw)
|
||||
|
|
|
|||
Loading…
Reference in a new issue