mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-13 07:24:53 +00:00
sufficient functionality that allows the UI for squads to display properly on squad joining and on squad leaving; clarification for SquadMemberEvent fields; QoL support functionality intergrated into SDDUM streams
This commit is contained in:
parent
2a1b051710
commit
60a11b8c52
9 changed files with 456 additions and 309 deletions
|
|
@ -82,12 +82,12 @@ class Squad(squadId : PlanetSideGUID, alignment : PlanetSideEmpire.Value) extend
|
||||||
LeaderPositionIndex
|
LeaderPositionIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
def Leader : String = {
|
def Leader : Member = {
|
||||||
membership.lift(leaderPositionIndex) match {
|
membership(leaderPositionIndex) match {
|
||||||
case Some(member) =>
|
case member if !member.Name.equals("") =>
|
||||||
member.Name
|
member
|
||||||
case None =>
|
case _ =>
|
||||||
""
|
throw new Exception("can not find squad leader!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -198,17 +198,16 @@ final case class SquadDetail(unk1 : Option[Int],
|
||||||
leader_name.orElse(Some("")),
|
leader_name.orElse(Some("")),
|
||||||
task.orElse(Some("")),
|
task.orElse(Some("")),
|
||||||
zone_id.orElse(Some(PlanetSideZoneID(0))),
|
zone_id.orElse(Some(PlanetSideZoneID(0))),
|
||||||
unk7.orElse(Some(0)),
|
unk7.orElse(Some(4983296)), //FullSquad value
|
||||||
{
|
{
|
||||||
val complete = SquadPositionDetail().Complete
|
val complete = SquadPositionDetail().Complete
|
||||||
Some(member_info match {
|
Some(member_info match {
|
||||||
case Some(info) =>
|
case Some(info) =>
|
||||||
//create one list that ensures all existing positions are "complete" then add a list of the missing indices
|
//create one list that ensures all existing positions are "complete" then add a list of the missing indices
|
||||||
val fields = info.collect {
|
val (indices, fields) = info.collect {
|
||||||
case SquadPositionEntry(a, Some(b)) => SquadPositionEntry(a, b.Complete)
|
case SquadPositionEntry(a, Some(b)) => (a, SquadPositionEntry(a, b.Complete))
|
||||||
case out @ SquadPositionEntry(_, None) => out
|
case out @ SquadPositionEntry(a, None) => (a, out)
|
||||||
}
|
}.unzip
|
||||||
val indices = info.map { case SquadPositionEntry(a, _) => a }
|
|
||||||
((0 to 9).toSet.diff(indices.toSet).map { SquadPositionEntry(_, complete) } ++ fields).toList.sortBy(_.index)
|
((0 to 9).toSet.diff(indices.toSet).map { SquadPositionEntry(_, complete) } ++ fields).toList.sortBy(_.index)
|
||||||
case None =>
|
case None =>
|
||||||
//original list
|
//original list
|
||||||
|
|
@ -585,7 +584,6 @@ object SquadDetailDefinitionUpdateMessage extends Marshallable[SquadDetailDefini
|
||||||
private def membersCodec(bitsOverByte : StreamLengthToken) : Codec[SquadDetail] = {
|
private def membersCodec(bitsOverByte : StreamLengthToken) : Codec[SquadDetail] = {
|
||||||
import shapeless.::
|
import shapeless.::
|
||||||
(
|
(
|
||||||
//TODO you can replace this outer structure with an either Codec
|
|
||||||
bool >>:~ { flag =>
|
bool >>:~ { flag =>
|
||||||
conditional(flag, {
|
conditional(flag, {
|
||||||
bitsOverByte.Add(4)
|
bitsOverByte.Add(4)
|
||||||
|
|
@ -593,15 +591,15 @@ object SquadDetailDefinitionUpdateMessage extends Marshallable[SquadDetailDefini
|
||||||
}) ::
|
}) ::
|
||||||
conditional(!flag, {
|
conditional(!flag, {
|
||||||
bitsOverByte.Add(3)
|
bitsOverByte.Add(3)
|
||||||
uint(2) :: FullyPopulatedPositions.codec(bitsOverByte)
|
uint2 :: FullyPopulatedPositions.codec(bitsOverByte)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
).exmap[SquadDetail] (
|
).exmap[SquadDetail] (
|
||||||
{
|
{
|
||||||
case true :: Some(_ :: member_list :: HNil) :: _ :: HNil =>
|
case true :: Some(_ :: member_list :: HNil) :: _ :: HNil =>
|
||||||
Attempt.successful(SquadDetail(None, None, None, None, None, None, None, None, Some(member_list.toList)))
|
Attempt.successful(SquadDetail(None, None, None, None, None, None, None, None, Some(ignoreTerminatingEntry(member_list.toList))))
|
||||||
case false :: None :: Some(_ :: member_list :: HNil) :: HNil =>
|
case false :: None :: Some(_ :: member_list :: HNil) :: HNil =>
|
||||||
Attempt.successful(SquadDetail(None, None, None, None, None, None, None, None, Some(member_list.toList)))
|
Attempt.successful(SquadDetail(None, None, None, None, None, None, None, None, Some(ignoreTerminatingEntry(member_list.toList))))
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
case SquadDetail(_, _, _, _, _, _, _, _, Some(member_list)) =>
|
case SquadDetail(_, _, _, _, _, _, _, _, Some(member_list)) =>
|
||||||
|
|
@ -612,16 +610,54 @@ object SquadDetailDefinitionUpdateMessage extends Marshallable[SquadDetailDefini
|
||||||
}
|
}
|
||||||
.flatten
|
.flatten
|
||||||
.count(_.isEmpty) == 0) {
|
.count(_.isEmpty) == 0) {
|
||||||
Attempt.successful(false :: None :: Some(2 :: member_list.toVector :: HNil) :: HNil)
|
Attempt.successful(false :: None :: Some(2 :: ensureTerminatingEntry(member_list).toVector :: HNil) :: HNil)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Attempt.successful(true :: Some(4 :: member_list.toVector :: HNil) :: None :: HNil)
|
Attempt.successful(true :: Some(4 :: ensureTerminatingEntry(member_list).toVector :: HNil) :: None :: HNil)
|
||||||
}
|
}
|
||||||
case _ =>
|
case _ =>
|
||||||
Attempt.failure(Err("failed to encode squad data for members"))
|
Attempt.failure(Err("failed to encode squad data for members"))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
//TODO while this pattern looks elegant, bitsOverByte does not accumulate properly with the either(bool, L, R); why?
|
||||||
|
// private def membersCodec(bitsOverByte : StreamLengthToken) : Codec[SquadDetail] = {
|
||||||
|
// import shapeless.::
|
||||||
|
// either(bool,
|
||||||
|
// { //false
|
||||||
|
// bitsOverByte.Add(3)
|
||||||
|
// uint2 :: FullyPopulatedPositions.codec(bitsOverByte)
|
||||||
|
// },
|
||||||
|
// { //true
|
||||||
|
// bitsOverByte.Add(4)
|
||||||
|
// uint(3) :: vector(ItemizedPositions.codec(bitsOverByte))
|
||||||
|
// }
|
||||||
|
// ).exmap[SquadDetail] (
|
||||||
|
// {
|
||||||
|
// case Left(_ :: member_list :: HNil) =>
|
||||||
|
// Attempt.successful(SquadDetail(None, None, None, None, None, None, None, None, Some(ignoreTerminatingEntry(member_list.toList))))
|
||||||
|
// case Right(_ :: member_list :: HNil) =>
|
||||||
|
// Attempt.successful(SquadDetail(None, None, None, None, None, None, None, None, Some(ignoreTerminatingEntry(member_list.toList))))
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// case SquadDetail(_, _, _, _, _, _, _, _, Some(member_list)) =>
|
||||||
|
// if(member_list
|
||||||
|
// .collect { case position if position.info.nonEmpty =>
|
||||||
|
// val info = position.info.get
|
||||||
|
// List(info.is_closed, info.role, info.detailed_orders, info.requirements, info.char_id, info.name)
|
||||||
|
// }
|
||||||
|
// .flatten
|
||||||
|
// .count(_.isEmpty) == 0) {
|
||||||
|
// Attempt.successful(Left(2 :: ensureTerminatingEntry(member_list).toVector :: HNil))
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// Attempt.successful(Right(4 :: ensureTerminatingEntry(member_list).toVector :: HNil))
|
||||||
|
// }
|
||||||
|
// case _ =>
|
||||||
|
// Attempt.failure(Err("failed to encode squad data for members"))
|
||||||
|
// }
|
||||||
|
// )
|
||||||
|
// }
|
||||||
/**
|
/**
|
||||||
* A failing pattern for when the coded value is not tied to a known field pattern.
|
* A failing pattern for when the coded value is not tied to a known field pattern.
|
||||||
* This pattern does not read or write any bit data.
|
* This pattern does not read or write any bit data.
|
||||||
|
|
@ -1245,10 +1281,9 @@ object SquadDetailDefinitionUpdateMessage extends Marshallable[SquadDetailDefini
|
||||||
}).xmap[Vector[SquadPositionEntry]] (
|
}).xmap[Vector[SquadPositionEntry]] (
|
||||||
{
|
{
|
||||||
case _ :: _ :: linkedMembers :: HNil =>
|
case _ :: _ :: linkedMembers :: HNil =>
|
||||||
unlinkFields(linkedMembers).toVector
|
ignoreTerminatingEntry(unlinkFields(linkedMembers)).toVector
|
||||||
},
|
},
|
||||||
//TODO "memberList.size - 1"? the only two examples are "10" anyway
|
memberList => 10 :: 12 :: linkFields(ensureTerminatingEntry(memberList.toList).reverse) :: HNil
|
||||||
memberList => memberList.size - 1 :: 12 :: linkFields(memberList.reverse.toList) :: HNil
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1320,6 +1355,32 @@ object SquadDetailDefinitionUpdateMessage extends Marshallable[SquadDetailDefini
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The last entry in the sequence of squad information listings should be a dummied listing with an index of 255.
|
||||||
|
* Ensure that this terminal entry is located at the end.
|
||||||
|
* @param list the listing of squad information
|
||||||
|
* @return the listing of squad information, with a specific final entry
|
||||||
|
*/
|
||||||
|
private def ensureTerminatingEntry(list : List[SquadPositionEntry]) : List[SquadPositionEntry] = {
|
||||||
|
list.lastOption match {
|
||||||
|
case Some(SquadPositionEntry(255, _)) => list
|
||||||
|
case Some(_) | None => list :+ SquadPositionEntry(255, None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The last entry in the sequence of squad information listings should be a dummied listing with an index of 255.
|
||||||
|
* Remove this terminal entry from the end of the list so as not to hassle with it.
|
||||||
|
* @param list the listing of squad information
|
||||||
|
* @return the listing of squad information, with a specific final entry truncated
|
||||||
|
*/
|
||||||
|
private def ignoreTerminatingEntry(list : List[SquadPositionEntry]) : List[SquadPositionEntry] = {
|
||||||
|
list.lastOption match {
|
||||||
|
case Some(SquadPositionEntry(255, _)) => list.init
|
||||||
|
case Some(_) | None => list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
implicit val codec : Codec[SquadDetailDefinitionUpdateMessage] = {
|
implicit val codec : Codec[SquadDetailDefinitionUpdateMessage] = {
|
||||||
import shapeless.::
|
import shapeless.::
|
||||||
import net.psforever.newcodecs.newcodecs
|
import net.psforever.newcodecs.newcodecs
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,10 @@ import shapeless.{::, HNil}
|
||||||
|
|
||||||
final case class SquadMemberEvent(unk1 : Int,
|
final case class SquadMemberEvent(unk1 : Int,
|
||||||
unk2 : Int,
|
unk2 : Int,
|
||||||
unk3 : Long,
|
char_id : Long,
|
||||||
unk4 : Int,
|
member_position : Int,
|
||||||
unk5 : Option[String],
|
player_name : Option[String],
|
||||||
unk6 : Option[Int],
|
zone_number : Option[Int],
|
||||||
unk7 : Option[Long])
|
unk7 : Option[Long])
|
||||||
extends PlanetSideGamePacket {
|
extends PlanetSideGamePacket {
|
||||||
type Packet = SquadMemberEvent
|
type Packet = SquadMemberEvent
|
||||||
|
|
@ -20,40 +20,40 @@ final case class SquadMemberEvent(unk1 : Int,
|
||||||
}
|
}
|
||||||
|
|
||||||
object SquadMemberEvent extends Marshallable[SquadMemberEvent] {
|
object SquadMemberEvent extends Marshallable[SquadMemberEvent] {
|
||||||
def apply(unk1 : Int, unk2 : Int, unk3 : Long, unk4 : Int) : SquadMemberEvent =
|
def apply(unk1 : Int, unk2 : Int, char_id : Long, member_position : Int) : SquadMemberEvent =
|
||||||
SquadMemberEvent(unk1, unk2, unk3, unk4, None, None, None)
|
SquadMemberEvent(unk1, unk2, char_id, member_position, None, None, None)
|
||||||
|
|
||||||
def apply(unk2 : Int, unk3 : Long, unk4 : Int, unk5 : String, unk6 : Int, unk7 : Long) : SquadMemberEvent =
|
def apply(unk2 : Int, char_id : Long, member_position : Int, player_name : String, zone_number : Int, unk7 : Long) : SquadMemberEvent =
|
||||||
SquadMemberEvent(0, unk2, unk3, unk4, Some(unk5), Some(unk6), Some(unk7))
|
SquadMemberEvent(0, unk2, char_id, member_position, Some(player_name), Some(zone_number), Some(unk7))
|
||||||
|
|
||||||
def apply(unk2 : Int, unk3 : Long, unk4 : Int, unk6 : Int) : SquadMemberEvent =
|
def apply(unk2 : Int, char_id : Long, member_position : Int, zone_number : Int) : SquadMemberEvent =
|
||||||
SquadMemberEvent(3, unk2, unk3, unk4, None, Some(unk6), None)
|
SquadMemberEvent(3, unk2, char_id, member_position, None, Some(zone_number), None)
|
||||||
|
|
||||||
def apply(unk2 : Int, unk3 : Long, unk4 : Int, unk7 : Long) : SquadMemberEvent =
|
def apply(unk2 : Int, char_id : Long, member_position : Int, unk7 : Long) : SquadMemberEvent =
|
||||||
SquadMemberEvent(4, unk2, unk3, unk4, None, None, Some(unk7))
|
SquadMemberEvent(4, unk2, char_id, member_position, None, None, Some(unk7))
|
||||||
|
|
||||||
implicit val codec : Codec[SquadMemberEvent] = (
|
implicit val codec : Codec[SquadMemberEvent] = (
|
||||||
("unk1" | uintL(3)) >>:~ { unk1 =>
|
("unk1" | uint(3)) >>:~ { unk1 =>
|
||||||
("unk2" | uint16L) ::
|
("unk2" | uint16L) ::
|
||||||
("unk3" | uint32L) ::
|
("char_id" | uint32L) ::
|
||||||
("unk4" | uintL(4)) ::
|
("member_position" | uint4) ::
|
||||||
conditional(unk1 == 0, "unk5" | PacketHelpers.encodedWideStringAligned(1)) ::
|
conditional(unk1 == 0, "player_name" | PacketHelpers.encodedWideStringAligned(1)) ::
|
||||||
conditional(unk1 == 0 || unk1 == 3, "unk6" | uint16L) ::
|
conditional(unk1 == 0 || unk1 == 3, "zone_number" | uint16L) ::
|
||||||
conditional(unk1 == 0 || unk1 == 4, "unk7" | uint32L)
|
conditional(unk1 == 0 || unk1 == 4, "unk7" | uint32L)
|
||||||
}).exmap[SquadMemberEvent] (
|
}).exmap[SquadMemberEvent] (
|
||||||
{
|
{
|
||||||
case unk1 :: unk2 :: unk3 :: unk4 :: unk5 :: unk6 :: unk7 :: HNil =>
|
case unk1 :: unk2 :: char_id :: member_position :: player_name :: zone_number :: unk7 :: HNil =>
|
||||||
Attempt.Successful(SquadMemberEvent(unk1, unk2, unk3, unk4, unk5, unk6, unk7))
|
Attempt.Successful(SquadMemberEvent(unk1, unk2, char_id, member_position, player_name, zone_number, unk7))
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
case data @ SquadMemberEvent(0, unk2, unk3, unk4, Some(unk5), Some(unk6), Some(unk7)) =>
|
case data @ SquadMemberEvent(0, unk2, char_id, member_position, Some(player_name), Some(zone_number), Some(unk7)) =>
|
||||||
Attempt.Successful(0 :: unk2 :: unk3 :: unk4 :: Some(unk5) :: Some(unk6) :: Some(unk7) :: HNil)
|
Attempt.Successful(0 :: unk2 :: char_id :: member_position :: Some(player_name) :: Some(zone_number) :: Some(unk7) :: HNil)
|
||||||
case data @ SquadMemberEvent(3, unk2, unk3, unk4, None, Some(unk6), None) =>
|
case data @ SquadMemberEvent(3, unk2, char_id, member_position, None, Some(zone_number), None) =>
|
||||||
Attempt.Successful(3 :: unk2 :: unk3 :: unk4 :: None :: Some(unk6) :: None :: HNil)
|
Attempt.Successful(3 :: unk2 :: char_id :: member_position :: None :: Some(zone_number) :: None :: HNil)
|
||||||
case data @ SquadMemberEvent(4, unk2, unk3, unk4, None, None, Some(unk7)) =>
|
case data @ SquadMemberEvent(4, unk2, char_id, member_position, None, None, Some(unk7)) =>
|
||||||
Attempt.Successful(4 :: unk2 :: unk3 :: unk4 :: None :: None :: Some(unk7) :: HNil)
|
Attempt.Successful(4 :: unk2 :: char_id :: member_position :: None :: None :: Some(unk7) :: HNil)
|
||||||
case data @ SquadMemberEvent(unk1, unk2, unk3, unk4, None, None, None) =>
|
case data @ SquadMemberEvent(unk1, unk2, char_id, member_position, None, None, None) =>
|
||||||
Attempt.Successful(unk1 :: unk2 :: unk3 :: unk4 :: None :: None :: None :: HNil)
|
Attempt.Successful(unk1 :: unk2 :: char_id :: member_position :: None :: None :: None :: HNil)
|
||||||
case data =>
|
case data =>
|
||||||
Attempt.Failure(Err(s"SquadMemberEvent can not encode with this pattern - $data"))
|
Attempt.Failure(Err(s"SquadMemberEvent can not encode with this pattern - $data"))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
13
common/src/main/scala/services/teamwork/SquadAction.scala
Normal file
13
common/src/main/scala/services/teamwork/SquadAction.scala
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright (c) 2019 PSForever
|
||||||
|
package services.teamwork
|
||||||
|
|
||||||
|
import net.psforever.objects.Player
|
||||||
|
import net.psforever.packet.game._
|
||||||
|
import net.psforever.types.SquadRequestType
|
||||||
|
|
||||||
|
object SquadAction {
|
||||||
|
trait Action
|
||||||
|
|
||||||
|
final case class Membership(request_type : SquadRequestType.Value, unk2 : Long, unk3 : Option[Long], player_name : String, unk5 : Option[Option[String]]) extends Action
|
||||||
|
final case class Definition(player : Player, zone_ordinal_number : Int, guid : PlanetSideGUID, line : Int, action : SquadAction)
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
// Copyright (c) 2019 PSForever
|
// Copyright (c) 2019 PSForever
|
||||||
package services.teamwork
|
package services.teamwork
|
||||||
|
|
||||||
|
import net.psforever.objects.teamwork.{Member, Squad}
|
||||||
import net.psforever.packet.game._
|
import net.psforever.packet.game._
|
||||||
|
import net.psforever.types.SquadRequestType
|
||||||
|
|
||||||
object SquadResponse {
|
object SquadResponse {
|
||||||
trait Response
|
trait Response
|
||||||
|
|
@ -10,5 +12,9 @@ object SquadResponse {
|
||||||
final case class Update(infos : Iterable[(Int, 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 Remove(infos : Iterable[Int]) extends Response
|
||||||
|
|
||||||
|
final case class Membership(request_type : SquadRequestType.Value, unk1 : Int, unk2 : Int, unk3 : Long, unk4 : Option[Long], player_name : String, unk5 : Boolean, unk6 : Option[Option[String]]) extends Response //see SquadMembershipResponse
|
||||||
|
final case class Join(squad : Squad, positionsToUpdate : List[Int]) extends Response
|
||||||
|
final case class Leave(squad : Squad, positionsToUpdate : List[(Long, Int)]) extends Response
|
||||||
|
|
||||||
final case class Detail(guid : PlanetSideGUID, leader : String, task : String, zone : PlanetSideZoneID, member_info : List[SquadPositionDetail]) extends Response
|
final case class Detail(guid : PlanetSideGUID, leader : String, task : String, zone : PlanetSideZoneID, member_info : List[SquadPositionDetail]) extends Response
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,13 @@ package services.teamwork
|
||||||
|
|
||||||
import akka.actor.Actor
|
import akka.actor.Actor
|
||||||
import net.psforever.objects.Player
|
import net.psforever.objects.Player
|
||||||
import net.psforever.objects.teamwork.{Member, Squad}
|
import net.psforever.objects.teamwork.Squad
|
||||||
import net.psforever.packet.game._
|
import net.psforever.packet.game._
|
||||||
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
import net.psforever.types.{PlanetSideEmpire, SquadRequestType, Vector3}
|
||||||
import services.{GenericEventBus, Service}
|
import services.{GenericEventBus, Service}
|
||||||
|
|
||||||
import scala.collection.concurrent.TrieMap
|
import scala.collection.concurrent.TrieMap
|
||||||
|
import scala.collection.mutable
|
||||||
import scala.collection.mutable.ListBuffer
|
import scala.collection.mutable.ListBuffer
|
||||||
|
|
||||||
//import scala.concurrent.duration._
|
//import scala.concurrent.duration._
|
||||||
|
|
@ -22,11 +23,35 @@ class SquadService extends Actor {
|
||||||
PlanetSideEmpire.NC -> ListBuffer.empty,
|
PlanetSideEmpire.NC -> ListBuffer.empty,
|
||||||
PlanetSideEmpire.VS -> ListBuffer.empty
|
PlanetSideEmpire.VS -> ListBuffer.empty
|
||||||
)
|
)
|
||||||
|
private val bids : mutable.LongMap[(PlanetSideGUID, Int)] = mutable.LongMap[(PlanetSideGUID, Int)]()
|
||||||
|
|
||||||
private [this] val log = org.log4s.getLogger
|
private [this] val log = org.log4s.getLogger
|
||||||
|
|
||||||
override def preStart = {
|
override def preStart = {
|
||||||
log.info("Starting...")
|
log.info("Starting...")
|
||||||
|
|
||||||
|
val testSquad = new Squad(PlanetSideGUID(3), PlanetSideEmpire.VS)
|
||||||
|
testSquad.Task = "\\#66CCFF Sentinels of Auraxis\\#FFFFFF ... \\#40FF40 Squad Up!!"
|
||||||
|
testSquad.ZoneId = 5
|
||||||
|
testSquad.Membership(0).Name = "Wizkid45"
|
||||||
|
testSquad.Membership(0).CharId = 30910985L
|
||||||
|
testSquad.Membership(0).ZoneId = 5
|
||||||
|
testSquad.Membership(0).Position = Vector3(5526.5234f, 3818.7344f, 54.59375f)
|
||||||
|
testSquad.Membership(1).Name = "xoBLADEox"
|
||||||
|
testSquad.Membership(1).CharId = 42781919L
|
||||||
|
testSquad.Membership(1).ZoneId = 5
|
||||||
|
testSquad.Membership(1).Position = Vector3(4673.5312f, 2604.8047f, 40.015625f)
|
||||||
|
testSquad.Membership(3).Name = "cabal0428"
|
||||||
|
testSquad.Membership(3).CharId = 353380L
|
||||||
|
testSquad.Membership(3).ZoneId = 5
|
||||||
|
testSquad.Membership(3).Position = Vector3(4727.492f, 2613.5312f, 51.390625f)
|
||||||
|
testSquad.Membership(4).Name = "xSkiku"
|
||||||
|
testSquad.Membership(4).CharId = 41588340L
|
||||||
|
testSquad.Membership(4).ZoneId = 5
|
||||||
|
testSquad.Membership(4).Position = Vector3(3675.0f, 4789.8047f, 63.21875f)
|
||||||
|
idToSquad(PlanetSideGUID(3)) = testSquad
|
||||||
|
testSquad.Listed = true
|
||||||
|
UpdateSquadList(testSquad, List())
|
||||||
}
|
}
|
||||||
|
|
||||||
def GetNextSquadId() : PlanetSideGUID = {
|
def GetNextSquadId() : PlanetSideGUID = {
|
||||||
|
|
@ -55,7 +80,7 @@ class SquadService extends Actor {
|
||||||
val name = player.Name
|
val name = player.Name
|
||||||
val squadOut = opt match {
|
val squadOut = opt match {
|
||||||
case Some(squad) =>
|
case Some(squad) =>
|
||||||
if(squad.Leader.equals(name)) {
|
if(squad.Leader.Name.equals(name)) {
|
||||||
squad
|
squad
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -64,7 +89,7 @@ class SquadService extends Actor {
|
||||||
|
|
||||||
case None =>
|
case None =>
|
||||||
memberToSquad.get(name) match {
|
memberToSquad.get(name) match {
|
||||||
case Some(squad) if squad.Leader.equals(name) =>
|
case Some(squad) if squad.Leader.Name.equals(name) =>
|
||||||
squad
|
squad
|
||||||
case _ =>
|
case _ =>
|
||||||
val faction = player.Faction
|
val faction = player.Faction
|
||||||
|
|
@ -115,7 +140,7 @@ class SquadService extends Actor {
|
||||||
SquadEvents.unsubscribe(sender())
|
SquadEvents.unsubscribe(sender())
|
||||||
memberToSquad.get(name) match {
|
memberToSquad.get(name) match {
|
||||||
case Some(squad) =>
|
case Some(squad) =>
|
||||||
if(squad.Leader.equals(name)) {
|
if(squad.Leader.Name.equals(name)) {
|
||||||
//we were the leader
|
//we were the leader
|
||||||
if(squad.Membership.count(p => p.Name.equals("")) > 1) {
|
if(squad.Membership.count(p => p.Name.equals("")) > 1) {
|
||||||
//other players were in the squad; publicly disband it
|
//other players were in the squad; publicly disband it
|
||||||
|
|
@ -144,190 +169,218 @@ class SquadService extends Actor {
|
||||||
}
|
}
|
||||||
case None => ;
|
case None => ;
|
||||||
}
|
}
|
||||||
//TODO leave squad, if joined to one, and perform clean-up
|
//TODO leave squad, if joined to one, and perform clean-up
|
||||||
|
|
||||||
case Service.Leave(None) | Service.LeaveAll() => ;
|
case Service.Leave(None) | Service.LeaveAll() => ;
|
||||||
|
|
||||||
case SquadServiceMessage.SquadDefinitionAction(tplayer, zone_ordinal_number, guid, _, action) =>
|
case SquadServiceMessage(tplayer, squad_action) => squad_action match {
|
||||||
import net.psforever.packet.game.SquadAction._
|
case SquadAction.Membership(request_type, char_id, optional_char_id, name, unk5) => request_type match {
|
||||||
val squadOpt = GetParticipatingSquad(tplayer, zone_ordinal_number)
|
case SquadRequestType.Accept =>
|
||||||
action match {
|
bids.get(char_id) match {
|
||||||
case SaveSquadDefinition() =>
|
case Some((squadGUID, line)) if idToSquad.get(squadGUID).nonEmpty =>
|
||||||
|
//join squad
|
||||||
case ChangeSquadPurpose(purpose) =>
|
val squad = idToSquad(squadGUID)
|
||||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has changed his squad's task to $purpose")
|
val position = squad.Membership(line)
|
||||||
val squad = GetLeadingSquad(tplayer, zone_ordinal_number, squadOpt)
|
if(squad.Availability(line) && position.CharId == 0 &&
|
||||||
squad.Task = purpose
|
tplayer.Certifications.intersect(position.Requirements) == position.Requirements) {
|
||||||
UpdateSquadList(squad, List(SquadInfo.Field.Task))
|
position.Name = tplayer.Name
|
||||||
UpdateSquadDetail(squad)
|
position.CharId = char_id
|
||||||
|
position.Health = tplayer.Health
|
||||||
case ChangeSquadZone(zone) =>
|
position.Armor = tplayer.Armor
|
||||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has changed squad's ops zone to $zone")
|
position.Position = tplayer.Position
|
||||||
val squad = GetLeadingSquad(tplayer, zone_ordinal_number, squadOpt)
|
position.ZoneId = 13
|
||||||
squad.ZoneId = zone.zoneId.toInt
|
memberToSquad(tplayer.Name) = squad
|
||||||
UpdateSquadList(squad, List(SquadInfo.Field.ZoneId))
|
sender ! SquadServiceResponse("", SquadResponse.Join(
|
||||||
UpdateSquadDetail(squad)
|
squad,
|
||||||
|
squad.Membership.zipWithIndex.collect({ case (member, index) if member.CharId != 0 => index }).toList
|
||||||
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 {
|
bids.remove(char_id)
|
||||||
List(SquadInfo.Field.Capacity)
|
case _ => ;
|
||||||
}
|
|
||||||
memberPosition.Close()
|
|
||||||
UpdateSquadList(squad, listingChanged)
|
|
||||||
UpdateSquadDetail(squad)
|
|
||||||
case Some(false) | None => ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case AddSquadMemberPosition(position) =>
|
case SquadRequestType.Leave =>
|
||||||
val squad = GetLeadingSquad(tplayer, zone_ordinal_number, squadOpt)
|
if(optional_char_id.contains(char_id)) {
|
||||||
squad.Availability.lift(position) match {
|
//we're leaving the squad on our own
|
||||||
case Some(false) =>
|
val name = tplayer.Name
|
||||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has opened the #$position position in squad")
|
val squad = memberToSquad(name)
|
||||||
squad.Availability.update(position, true)
|
val membership = squad.Membership.zipWithIndex
|
||||||
UpdateSquadList(squad, List(SquadInfo.Field.Capacity))
|
val (member, index) = membership
|
||||||
UpdateSquadDetail(squad)
|
.find { case (_member, _) => _member.Name == name }
|
||||||
case Some(true) | None => ;
|
.get
|
||||||
}
|
val updateList = membership.collect({ case (_member, _) if _member.CharId > 0 => (_member.CharId, index) }).toList
|
||||||
|
memberToSquad.remove(name)
|
||||||
case ChangeSquadMemberRequirementsRole(position, role) =>
|
member.Name = ""
|
||||||
val squad = GetLeadingSquad(tplayer, zone_ordinal_number, squadOpt)
|
member.CharId = 0
|
||||||
squad.Availability.lift(position) match {
|
sender ! SquadServiceResponse("", SquadResponse.Leave(squad, updateList))
|
||||||
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
|
|
||||||
}
|
|
||||||
val hadPreviousPosition = squad.Membership.find(_.Name == name) match {
|
|
||||||
case Some(currentPosition)=>
|
|
||||||
currentPosition.Name = ""
|
|
||||||
currentPosition.CharId = 0L
|
|
||||||
currentPosition.ZoneId = 0
|
|
||||||
currentPosition.Health = 0
|
|
||||||
currentPosition.Armor = 0
|
|
||||||
currentPosition.Position = Vector3.Zero
|
|
||||||
true
|
|
||||||
case None =>
|
|
||||||
false
|
|
||||||
}
|
|
||||||
desiredPosition.Name = name
|
|
||||||
desiredPosition.CharId = tplayer.CharId
|
|
||||||
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 => ;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 _ => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
case msg =>
|
case SquadAction.Definition(tplayer : Player, zone_ordinal_number : Int, guid : PlanetSideGUID, line : Int, action : SquadAction) =>
|
||||||
log.info(s"Unhandled message $msg from $sender")
|
import net.psforever.packet.game.SquadAction._
|
||||||
|
val squadOpt = GetParticipatingSquad(tplayer, zone_ordinal_number)
|
||||||
|
action match {
|
||||||
|
case SaveSquadDefinition() =>
|
||||||
|
|
||||||
|
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 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) =>
|
||||||
|
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(position) =>
|
||||||
|
//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.GUID == guid =>
|
||||||
|
//already a member of this squad; swap positions freely
|
||||||
|
case Some(squad) =>
|
||||||
|
//not a member of the requesting squad; do nothing
|
||||||
|
case None =>
|
||||||
|
//not a member of any squad; consider request of joining the target squad
|
||||||
|
idToSquad.get(guid) match {
|
||||||
|
case Some(squad) =>
|
||||||
|
val member = squad.Membership(position)
|
||||||
|
if(squad.Availability(position) && member.CharId == 0 &&
|
||||||
|
tplayer.Certifications.intersect(member.Requirements) == member.Requirements) {
|
||||||
|
bids(tplayer.CharId) = (guid, position)
|
||||||
|
val leader = squad.Leader
|
||||||
|
//TODO need to ask permission from the squad leader, unless auto-approve is in effect
|
||||||
|
sender ! SquadServiceResponse("", SquadResponse.Membership(SquadRequestType.Invite, 0, 0, leader.CharId, Some(tplayer.CharId), leader.Name, false, None))
|
||||||
|
}
|
||||||
|
|
||||||
|
case None =>
|
||||||
|
//squad does not exist!? assume old data
|
||||||
|
//reload squad list data and blank the squad definition the user is looking at
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = {
|
def UpdateSquadList(squad : Squad, listingChanged : List[Int]) : Unit = {
|
||||||
|
|
@ -380,7 +433,7 @@ class SquadService extends Actor {
|
||||||
def GenSquadDetail(squad : Squad) : SquadResponse.Detail = {
|
def GenSquadDetail(squad : Squad) : SquadResponse.Detail = {
|
||||||
SquadResponse.Detail(
|
SquadResponse.Detail(
|
||||||
squad.GUID,
|
squad.GUID,
|
||||||
squad.Leader,
|
squad.Leader.Name,
|
||||||
squad.Task,
|
squad.Task,
|
||||||
PlanetSideZoneID(squad.ZoneId),
|
PlanetSideZoneID(squad.ZoneId),
|
||||||
squad.Membership.zipWithIndex.map({ case (p, index) =>
|
squad.Membership.zipWithIndex.map({ case (p, index) =>
|
||||||
|
|
@ -410,7 +463,7 @@ class SquadService extends Actor {
|
||||||
object SquadService {
|
object SquadService {
|
||||||
def Publish(squad : Squad) : SquadInfo = {
|
def Publish(squad : Squad) : SquadInfo = {
|
||||||
SquadInfo(
|
SquadInfo(
|
||||||
squad.Leader,
|
squad.Leader.Name,
|
||||||
squad.Task,
|
squad.Task,
|
||||||
PlanetSideZoneID(squad.ZoneId),
|
PlanetSideZoneID(squad.ZoneId),
|
||||||
squad.Size,
|
squad.Size,
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,9 @@
|
||||||
package services.teamwork
|
package services.teamwork
|
||||||
|
|
||||||
import net.psforever.objects.Player
|
import net.psforever.objects.Player
|
||||||
import net.psforever.packet.game.{PlanetSideGUID, SquadAction}
|
|
||||||
|
|
||||||
final case class SquadServiceMessage(forChannel : String, actionMessage : Any)
|
final case class SquadServiceMessage(tplayer : Player, actionMessage : Any)
|
||||||
|
|
||||||
object SquadServiceMessage {
|
object SquadServiceMessage {
|
||||||
final case class SquadDefinitionAction(player : Player, zone_ordinal_number : Int, guid : PlanetSideGUID, line : Int, action : SquadAction)
|
|
||||||
|
|
||||||
final case class RecoverSquadMembership()
|
final case class RecoverSquadMembership()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,7 @@ class SquadDetailDefinitionUpdateMessageTest extends Specification {
|
||||||
guid mustEqual PlanetSideGUID(3)
|
guid mustEqual PlanetSideGUID(3)
|
||||||
detail match {
|
detail match {
|
||||||
case SquadDetail(None, None, None, None, None, None, None, None, Some(members)) =>
|
case SquadDetail(None, None, None, None, None, None, None, None, Some(members)) =>
|
||||||
members.size mustEqual 2
|
members.size mustEqual 1
|
||||||
members.head.index mustEqual 5
|
members.head.index mustEqual 5
|
||||||
members.head.info match {
|
members.head.info match {
|
||||||
case Some(SquadPositionDetail(Some(is_closed), None, None, None, None, None)) =>
|
case Some(SquadPositionDetail(Some(is_closed), None, None, None, None, None)) =>
|
||||||
|
|
@ -169,7 +169,7 @@ class SquadDetailDefinitionUpdateMessageTest extends Specification {
|
||||||
guid mustEqual PlanetSideGUID(7)
|
guid mustEqual PlanetSideGUID(7)
|
||||||
detail match {
|
detail match {
|
||||||
case SquadDetail(None, None, None, None, None, None, None, None, Some(members)) =>
|
case SquadDetail(None, None, None, None, None, None, None, None, Some(members)) =>
|
||||||
members.size mustEqual 2
|
members.size mustEqual 1
|
||||||
members.head.index mustEqual 0
|
members.head.index mustEqual 0
|
||||||
members.head.info match {
|
members.head.info match {
|
||||||
case Some(SquadPositionDetail(None, Some(role), None, None, None, None)) =>
|
case Some(SquadPositionDetail(None, Some(role), None, None, None, None)) =>
|
||||||
|
|
@ -192,7 +192,7 @@ class SquadDetailDefinitionUpdateMessageTest extends Specification {
|
||||||
guid mustEqual PlanetSideGUID(1)
|
guid mustEqual PlanetSideGUID(1)
|
||||||
detail match {
|
detail match {
|
||||||
case SquadDetail(None, None, None, None, None, None, None, None, Some(members)) =>
|
case SquadDetail(None, None, None, None, None, None, None, None, Some(members)) =>
|
||||||
members.size mustEqual 2
|
members.size mustEqual 1
|
||||||
members.head.index mustEqual 6
|
members.head.index mustEqual 6
|
||||||
members.head.info match {
|
members.head.info match {
|
||||||
case Some(SquadPositionDetail(None, Some(role), None, Some(req), None, None)) =>
|
case Some(SquadPositionDetail(None, Some(role), None, Some(req), None, None)) =>
|
||||||
|
|
@ -217,7 +217,7 @@ class SquadDetailDefinitionUpdateMessageTest extends Specification {
|
||||||
guid mustEqual PlanetSideGUID(3)
|
guid mustEqual PlanetSideGUID(3)
|
||||||
detail match {
|
detail match {
|
||||||
case SquadDetail(None, None, None, None, None, None, None, None, Some(members)) =>
|
case SquadDetail(None, None, None, None, None, None, None, None, Some(members)) =>
|
||||||
members.size mustEqual 2
|
members.size mustEqual 1
|
||||||
members.head.index mustEqual 5
|
members.head.index mustEqual 5
|
||||||
members.head.info match {
|
members.head.info match {
|
||||||
case Some(SquadPositionDetail(None, None, None, None, Some(char_id), Some(name))) =>
|
case Some(SquadPositionDetail(None, None, None, None, Some(char_id), Some(name))) =>
|
||||||
|
|
@ -242,7 +242,7 @@ class SquadDetailDefinitionUpdateMessageTest extends Specification {
|
||||||
detail match {
|
detail match {
|
||||||
case SquadDetail(None, None, None, None, None, Some(task), None, None, Some(members)) =>
|
case SquadDetail(None, None, None, None, None, Some(task), None, None, Some(members)) =>
|
||||||
task mustEqual "\\#FF0000 The \\#ffffff Blades"
|
task mustEqual "\\#FF0000 The \\#ffffff Blades"
|
||||||
members.size mustEqual 11
|
members.size mustEqual 10
|
||||||
//
|
//
|
||||||
members.head.index mustEqual 9
|
members.head.index mustEqual 9
|
||||||
members.head.info match {
|
members.head.info match {
|
||||||
|
|
@ -399,7 +399,7 @@ class SquadDetailDefinitionUpdateMessageTest extends Specification {
|
||||||
detail match {
|
detail match {
|
||||||
case SquadDetail(None, None, None, None, None, Some(task), None, None, Some(member_list)) =>
|
case SquadDetail(None, None, None, None, None, Some(task), None, None, Some(member_list)) =>
|
||||||
task mustEqual "PSForever Packet Collection"
|
task mustEqual "PSForever Packet Collection"
|
||||||
member_list.size mustEqual 11
|
member_list.size mustEqual 10
|
||||||
member_list.head mustEqual SquadPositionEntry(9,Some(
|
member_list.head mustEqual SquadPositionEntry(9,Some(
|
||||||
SquadPositionDetail(
|
SquadPositionDetail(
|
||||||
Some(false),
|
Some(false),
|
||||||
|
|
@ -516,8 +516,7 @@ class SquadDetailDefinitionUpdateMessageTest extends Specification {
|
||||||
.Field1(0)
|
.Field1(0)
|
||||||
.LeaderCharId(1221560L)
|
.LeaderCharId(1221560L)
|
||||||
.Members(List(
|
.Members(List(
|
||||||
SquadPositionEntry(6, SquadPositionDetail().Player(0L, "")),
|
SquadPositionEntry(6, SquadPositionDetail().Player(0L, ""))
|
||||||
SquadPositionEntry(255, None)
|
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
@ -540,8 +539,7 @@ class SquadDetailDefinitionUpdateMessageTest extends Specification {
|
||||||
.Leader(42631712L, "Jaako")
|
.Leader(42631712L, "Jaako")
|
||||||
.Field3(556403L)
|
.Field3(556403L)
|
||||||
.Members(List(
|
.Members(List(
|
||||||
SquadPositionEntry(0, SquadPositionDetail().Player(0L, "")),
|
SquadPositionEntry(0, SquadPositionDetail().Player(0L, ""))
|
||||||
SquadPositionEntry(255, None)
|
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
@ -593,8 +591,7 @@ class SquadDetailDefinitionUpdateMessageTest extends Specification {
|
||||||
SquadPositionEntry(3, SquadPositionDetail().Role("The Princess")),
|
SquadPositionEntry(3, SquadPositionDetail().Role("The Princess")),
|
||||||
SquadPositionEntry(2, SquadPositionDetail().Role("The Prince")),
|
SquadPositionEntry(2, SquadPositionDetail().Role("The Prince")),
|
||||||
SquadPositionEntry(1, SquadPositionDetail().Role("The Queen")),
|
SquadPositionEntry(1, SquadPositionDetail().Role("The Queen")),
|
||||||
SquadPositionEntry(0, SquadPositionDetail().Role("The King")),
|
SquadPositionEntry(0, SquadPositionDetail().Role("The King"))
|
||||||
SquadPositionEntry(255, None)
|
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
@ -606,8 +603,7 @@ class SquadDetailDefinitionUpdateMessageTest extends Specification {
|
||||||
PlanetSideGUID(3),
|
PlanetSideGUID(3),
|
||||||
SquadDetail()
|
SquadDetail()
|
||||||
.Members(List(
|
.Members(List(
|
||||||
SquadPositionEntry(5, SquadPositionDetail.Closed),
|
SquadPositionEntry(5, SquadPositionDetail.Closed)
|
||||||
SquadPositionEntry(255, None)
|
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
@ -620,8 +616,7 @@ class SquadDetailDefinitionUpdateMessageTest extends Specification {
|
||||||
PlanetSideGUID(7),
|
PlanetSideGUID(7),
|
||||||
SquadDetail()
|
SquadDetail()
|
||||||
.Members(List(
|
.Members(List(
|
||||||
SquadPositionEntry(0, SquadPositionDetail().Role("Commander")),
|
SquadPositionEntry(0, SquadPositionDetail().Role("Commander"))
|
||||||
SquadPositionEntry(255, None)
|
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
@ -635,8 +630,7 @@ class SquadDetailDefinitionUpdateMessageTest extends Specification {
|
||||||
.Members(List(
|
.Members(List(
|
||||||
SquadPositionEntry(6, SquadPositionDetail()
|
SquadPositionEntry(6, SquadPositionDetail()
|
||||||
.Role("ADV Hacker")
|
.Role("ADV Hacker")
|
||||||
.Requirements(Set(CertificationType.AdvancedHacking))),
|
.Requirements(Set(CertificationType.AdvancedHacking)))
|
||||||
SquadPositionEntry(255, None)
|
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
@ -648,8 +642,7 @@ class SquadDetailDefinitionUpdateMessageTest extends Specification {
|
||||||
PlanetSideGUID(3),
|
PlanetSideGUID(3),
|
||||||
SquadDetail()
|
SquadDetail()
|
||||||
.Members(List(
|
.Members(List(
|
||||||
SquadPositionEntry(5, SquadPositionDetail().Player(1218249L, "Duckmaster43")),
|
SquadPositionEntry(5, SquadPositionDetail().Player(1218249L, "Duckmaster43"))
|
||||||
SquadPositionEntry(255, None)
|
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
@ -671,8 +664,7 @@ class SquadDetailDefinitionUpdateMessageTest extends Specification {
|
||||||
SquadPositionEntry(3, SquadPositionDetail().Role("")),
|
SquadPositionEntry(3, SquadPositionDetail().Role("")),
|
||||||
SquadPositionEntry(2, SquadPositionDetail().Role("")),
|
SquadPositionEntry(2, SquadPositionDetail().Role("")),
|
||||||
SquadPositionEntry(1, SquadPositionDetail().Role("")),
|
SquadPositionEntry(1, SquadPositionDetail().Role("")),
|
||||||
SquadPositionEntry(0, SquadPositionDetail().Role("")),
|
SquadPositionEntry(0, SquadPositionDetail().Role(""))
|
||||||
SquadPositionEntry(255, None)
|
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
@ -715,7 +707,7 @@ class SquadDetailDefinitionUpdateMessageTest extends Specification {
|
||||||
PlanetSideGUID(3),
|
PlanetSideGUID(3),
|
||||||
SquadDetail
|
SquadDetail
|
||||||
.Task("PSForever Packet Collection")
|
.Task("PSForever Packet Collection")
|
||||||
.Members((0 to 9).map { index => SquadPositionEntry(index, position) }.reverse.toList :+ SquadPositionEntry(255, None))
|
.Members((0 to 9).map { index => SquadPositionEntry(index, position) }.reverse.toList)
|
||||||
)
|
)
|
||||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
pkt mustEqual string_mixed
|
pkt mustEqual string_mixed
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ import services.galaxy.{GalaxyResponse, GalaxyServiceResponse}
|
||||||
import services.local.{LocalAction, LocalResponse, LocalServiceMessage, LocalServiceResponse}
|
import services.local.{LocalAction, LocalResponse, LocalServiceMessage, LocalServiceResponse}
|
||||||
import services.vehicle.support.TurretUpgrader
|
import services.vehicle.support.TurretUpgrader
|
||||||
import services.vehicle.{VehicleAction, VehicleResponse, VehicleServiceMessage, VehicleServiceResponse}
|
import services.vehicle.{VehicleAction, VehicleResponse, VehicleServiceMessage, VehicleServiceResponse}
|
||||||
import services.teamwork._
|
import services.teamwork.{SquadAction => SquadServiceAction, SquadServiceMessage, SquadServiceResponse, SquadResponse, SquadService}
|
||||||
|
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
|
|
@ -376,16 +376,65 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
SquadDetailDefinitionUpdateMessage(
|
SquadDetailDefinitionUpdateMessage(
|
||||||
guid,
|
guid,
|
||||||
SquadDetail()
|
SquadDetail()
|
||||||
.LeaderCharId(member_info.find(_.name == leader).get.char_id.get)
|
.LeaderCharId(member_info.find(_.name.contains(leader)).get.char_id.get)
|
||||||
.LeaderName(leader)
|
.LeaderName(leader)
|
||||||
.Task(task)
|
.Task(task)
|
||||||
.ZoneId(zone)
|
.ZoneId(zone)
|
||||||
.Members(
|
.Members(member_info.zipWithIndex.map { case (a, b) => SquadPositionEntry(b, a) })
|
||||||
member_info.zipWithIndex.map { case (a, b) => SquadPositionEntry(b, a) }
|
|
||||||
)
|
|
||||||
.Complete
|
.Complete
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
case SquadResponse.Membership(request_type, unk1, unk2, unk3, unk4, player_name, unk5, unk6) =>
|
||||||
|
sendResponse(SquadMembershipResponse(request_type, unk1, unk2, unk3, unk4, player_name, unk5, unk6))
|
||||||
|
|
||||||
|
case SquadResponse.Join(squad, positionsToUpdate) =>
|
||||||
|
val leader = squad.Leader
|
||||||
|
val id = 11
|
||||||
|
val membershipPositions = squad.Membership
|
||||||
|
.zipWithIndex
|
||||||
|
.filter { case (_, index ) => positionsToUpdate.contains(index) }
|
||||||
|
sendResponse(SquadMembershipResponse(SquadRequestType.Accept, 0, 0, player.CharId, Some(leader.CharId), player.Name, true, Some(None)))
|
||||||
|
//load each member's entry
|
||||||
|
membershipPositions.foreach { case(member, index) =>
|
||||||
|
sendResponse(SquadMemberEvent(0, id, member.CharId, index, Some(member.Name), Some(member.ZoneId), Some(0)))
|
||||||
|
}
|
||||||
|
//repeat own entry and initialize connection to squad
|
||||||
|
membershipPositions.find({ case(member, _) => member.CharId == avatar.CharId }) match {
|
||||||
|
case Some((member, index)) =>
|
||||||
|
sendResponse(SquadMemberEvent(0, id, member.CharId, index, Some(member.Name), Some(member.ZoneId), Some(0)))
|
||||||
|
sendResponse(PlanetsideAttributeMessage(player.GUID, 31, id)) //associate with squad?
|
||||||
|
sendResponse(PlanetsideAttributeMessage(player.GUID, 32, index)) //associate with member position in squad?
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
//send first update for map icons
|
||||||
|
sendResponse(SquadState(PlanetSideGUID(id),
|
||||||
|
membershipPositions
|
||||||
|
.filterNot { case (member, _) => member.CharId == avatar.CharId }
|
||||||
|
.map{ case (member, _) => SquadStateInfo(member.CharId, 64,64, member.Position, 2,2, false, 429, None,None) }
|
||||||
|
.toList
|
||||||
|
))
|
||||||
|
//a finalization? what does this do?
|
||||||
|
sendResponse(SquadDefinitionActionMessage(squad.GUID, 0, SquadAction.Unknown(18, hex"00".toBitVector.take(6))))
|
||||||
|
|
||||||
|
case SquadResponse.Leave(_, positionsToUpdate) =>
|
||||||
|
val id = 11
|
||||||
|
sendResponse(SquadMembershipResponse(SquadRequestType.Leave, 0,1, avatar.CharId, Some(avatar.CharId), avatar.name, true, Some(None)))
|
||||||
|
//remove each member's entry (our own too)
|
||||||
|
positionsToUpdate.foreach { case(member, index) =>
|
||||||
|
sendResponse(SquadMemberEvent(1, id, member, index, None, None, None))
|
||||||
|
}
|
||||||
|
//repeat own entry and rescind connection to squad
|
||||||
|
positionsToUpdate.find({ case(member, _) => member == avatar.CharId }) match {
|
||||||
|
case Some((member, index)) =>
|
||||||
|
sendResponse(SquadMemberEvent(1, id, member, index, None, None, None))
|
||||||
|
sendResponse(PlanetsideAttributeMessage(player.GUID, 31, 0)) //disassociate with squad?
|
||||||
|
sendResponse(PlanetsideAttributeMessage(player.GUID, 32, 0)) //disassociate with member position in squad?
|
||||||
|
sendResponse(PlanetsideAttributeMessage(player.GUID, 34, 4294967295L)) //unknown
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
//a finalization? what does this do?
|
||||||
|
sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(0), 0, SquadAction.Unknown(18, hex"00".toBitVector.take(6))))
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2911,42 +2960,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
interstellarFerryTopLevelGUID = None
|
interstellarFerryTopLevelGUID = None
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
//SQUAD TESTING CODE
|
squadService ! Service.Join(s"${avatar.faction}") //channel will be player.Faction
|
||||||
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))))
|
|
||||||
)
|
|
||||||
))
|
|
||||||
sendResponse(
|
|
||||||
SquadDetailDefinitionUpdateMessage(
|
|
||||||
PlanetSideGUID(3),
|
|
||||||
SquadDetail(
|
|
||||||
3,
|
|
||||||
1792,
|
|
||||||
42771010L,
|
|
||||||
529745L,
|
|
||||||
"HofD",
|
|
||||||
"\\#ffdc00***\\#9640ff=KOK+SPC+FLY=\\#ffdc00***\\#FF4040 All Welcome",
|
|
||||||
PlanetSideZoneID(7),
|
|
||||||
4983296,
|
|
||||||
List(
|
|
||||||
SquadPositionEntry(0, SquadPositionDetail("\\#ff0000 |||||||||||||||||||||||", "", Set(), 0, "")),
|
|
||||||
SquadPositionEntry(1, SquadPositionDetail("\\#ffdc00 C", "", Set(), 0, "")),
|
|
||||||
SquadPositionEntry(2, SquadPositionDetail("\\#ffdc00 H", "", Set(), 42644970L, "OpolE")),
|
|
||||||
SquadPositionEntry(3, SquadPositionDetail("\\#ffdc00 I", "", Set(), 41604210L, "BobaF3tt907")),
|
|
||||||
SquadPositionEntry(4, SquadPositionDetail("\\#ffdc00 N", "", Set(), 0, "")),
|
|
||||||
SquadPositionEntry(5, SquadPositionDetail("\\#ffdc00 A", "", Set(), 0, "")),
|
|
||||||
SquadPositionEntry(6, SquadPositionDetail("\\#ff0000 |||||||||||||||||||||||", "", Set(), 0, "")),
|
|
||||||
SquadPositionEntry(7, SquadPositionDetail("\\#9640ff K", "", Set(), 0, "")),
|
|
||||||
SquadPositionEntry(8, SquadPositionDetail("\\#9640ff O", "", Set(), 42771010L ,"HofD")),
|
|
||||||
SquadPositionEntry(9, SquadPositionDetail("\\#9640ff K", "", Set(), 0, ""))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def handleControlPkt(pkt : PlanetSideControlPacket) = {
|
def handleControlPkt(pkt : PlanetSideControlPacket) = {
|
||||||
|
|
@ -3359,18 +3373,7 @@ 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) =>
|
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(deadState == DeadState.Alive) {
|
||||||
if(!player.Crouching && is_crouching) { //SQUAD TESTING CODE
|
if(!player.Crouching && is_crouching) { //SQUAD TESTING CODE
|
||||||
sendRawResponse(hex"e80300818800015c5189004603408c000000012000ff")
|
//...
|
||||||
// sendResponse(SquadMembershipResponse(SquadRequestType.Invite,0,0,42771010,Some(avatar.CharId),"HofD",false,None))
|
|
||||||
// sendResponse(SquadMembershipResponse(SquadRequestType.Accept,0,0,avatar.CharId,Some(42771010),"VirusGiver",true,Some(None)))
|
|
||||||
// sendResponse(SquadMemberEvent(0,7,42771010,0,Some("HofD"),Some(7),Some(529745)))
|
|
||||||
// sendResponse(SquadMemberEvent(0,7,42644970,1,Some("OpolE"),Some(7),Some(6418)))
|
|
||||||
// sendResponse(SquadMemberEvent(0,7,41604210,8,Some("BobaF3tt907"),Some(12),Some(8097)))
|
|
||||||
// sendResponse(PlanetsideAttributeMessage(player.GUID, 49, 7))
|
|
||||||
// sendResponse(PlanetsideAttributeMessage(player.GUID, 50, 2))
|
|
||||||
// sendResponse(PlanetsideAttributeMessage(player.GUID, 51, 8))
|
|
||||||
// sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(3), 0, SquadAction.Unknown(18, hex"".toBitVector)))
|
|
||||||
// sendResponse(PlanetsideAttributeMessage(player.GUID, 83, 0))
|
|
||||||
// sendResponse(SquadState(PlanetSideGUID(7),List(SquadStateInfo(avatar.CharId,64,64,Vector3(3464.0469f,4065.5703f,20.015625f),2,2,false,0,None,None))))
|
|
||||||
}
|
}
|
||||||
player.Position = pos
|
player.Position = pos
|
||||||
player.Velocity = vel
|
player.Velocity = vel
|
||||||
|
|
@ -4850,7 +4853,29 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
|
|
||||||
case msg @ SquadDefinitionActionMessage(u1, u2, action) =>
|
case msg @ SquadDefinitionActionMessage(u1, u2, action) =>
|
||||||
log.info(s"SquadDefinitionAction: $msg")
|
log.info(s"SquadDefinitionAction: $msg")
|
||||||
squadService ! SquadServiceMessage.SquadDefinitionAction(player, continent.Number, u1, u2, action)
|
squadService ! SquadServiceMessage(player, SquadServiceAction.Definition(player, continent.Number, u1, u2, action))
|
||||||
|
|
||||||
|
case msg @ SquadMembershipRequest(request_type, unk2, unk3, player_name, unk5) =>
|
||||||
|
log.info(s"$msg")
|
||||||
|
squadService ! SquadServiceMessage(player, SquadServiceAction.Membership(request_type, unk2, unk3, player_name, unk5))
|
||||||
|
// if(request_type == SquadRequestType.Accept) {
|
||||||
|
// sendResponse(SquadMembershipResponse(SquadRequestType.Accept, 0, 0, unk2, Some(30910985L), player.Name, true, Some(None)))
|
||||||
|
// sendResponse(SquadMemberEvent(0, 11, 30910985L, 0, Some("Wizkid45"), Some(5), Some(320036)))
|
||||||
|
// sendResponse(SquadMemberEvent(0, 11, 42781919L, 1, Some("xoBLADEox"), Some(5), Some(528805)))
|
||||||
|
// sendResponse(SquadMemberEvent(0, 11, avatar.CharId, 2, Some(player.Name), Some(13), Some(320036)))
|
||||||
|
// sendResponse(SquadMemberEvent(0, 11, 353380L, 3, Some("cabal0428") ,Some(5), Some(8156)))
|
||||||
|
// sendResponse(SquadMemberEvent(0, 11, 41588340L, 4 ,Some("xSkiku"), Some(5), Some(0)))
|
||||||
|
// sendResponse(SquadMemberEvent(0, 11, avatar.CharId, 2, Some(player.Name), Some(13), Some(320036)))
|
||||||
|
// sendResponse(PlanetsideAttributeMessage(player.GUID, 31, 11)) //associate with squad?
|
||||||
|
// sendResponse(PlanetsideAttributeMessage(player.GUID, 32, 2)) //associate with member position in squad?
|
||||||
|
// sendResponse(SquadState(PlanetSideGUID(11),List(
|
||||||
|
// SquadStateInfo(30910985L, 50,64, Vector3(5526.5234f,3818.7344f,54.59375f), 2,2, false, 429, None,None),
|
||||||
|
// SquadStateInfo(42781919L, 64,0, Vector3(4673.5312f,2604.8047f,40.015625f), 2,2, false, 149, None,None),
|
||||||
|
// SquadStateInfo(353380L, 64,64, Vector3(4727.492f,2613.5312f,51.390625f), 2,2, false, 0, None,None),
|
||||||
|
// SquadStateInfo(41588340L, 64,64, Vector3(3675.0f,4789.8047f,63.21875f), 2,2, false, 0, None,None)
|
||||||
|
// )))
|
||||||
|
// sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(3), 0, SquadAction.Unknown(18, hex"00".toBitVector.take(6))))
|
||||||
|
// }
|
||||||
|
|
||||||
case msg @ GenericCollisionMsg(u1, p, t, php, thp, pv, tv, ppos, tpos, u2, u3, u4) =>
|
case msg @ GenericCollisionMsg(u1, p, t, php, thp, pv, tv, ppos, tpos, u2, u3, u4) =>
|
||||||
log.info("Ouch! " + msg)
|
log.info("Ouch! " + msg)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue