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:
FateJH 2019-06-06 14:54:53 -04:00
parent 5c433204cf
commit 9cf1cd92cc
9 changed files with 467 additions and 262 deletions

View file

@ -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
}
}

View file

@ -306,13 +306,13 @@ object SquadAction{
* &nbsp;&nbsp;&nbsp;&nbsp;`36` - UNKNOWN<br>
* &nbsp;&nbsp;`String :: Long :: Int :: Int`<br>
* &nbsp;&nbsp;&nbsp;&nbsp;`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
}
)
}

View file

@ -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] {

View file

@ -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

View file

@ -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
}

View file

@ -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,

View file

@ -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()
}

View file

@ -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

View file

@ -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)