mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-14 07:55:07 +00:00
modified squad user initialization messages to better focus on specific steps of the process; dealt with different methods of communicating squad information to users, though not yet ready to implement the switchboard protocol
This commit is contained in:
parent
e5b2efd381
commit
56d8748e99
5 changed files with 356 additions and 85 deletions
|
|
@ -35,7 +35,7 @@ object SquadAction{
|
||||||
* Dispatched from client to server to indicate a squad detail update that has no foundation entry to update?
|
* Dispatched from client to server to indicate a squad detail update that has no foundation entry to update?
|
||||||
* Not dissimilar from `DisplaySquad`.
|
* Not dissimilar from `DisplaySquad`.
|
||||||
*/
|
*/
|
||||||
final case class DisplayFullSquad() extends SquadAction(1)
|
final case class SquadMemberInitializationIssue() extends SquadAction(1)
|
||||||
|
|
||||||
final case class SaveSquadFavorite() extends SquadAction(3)
|
final case class SaveSquadFavorite() extends SquadAction(3)
|
||||||
|
|
||||||
|
|
@ -53,6 +53,8 @@ object SquadAction{
|
||||||
|
|
||||||
final case class CancelSelectRoleForYourself(value: Long = 0) extends SquadAction(15)
|
final case class CancelSelectRoleForYourself(value: Long = 0) extends SquadAction(15)
|
||||||
|
|
||||||
|
final case class AssociateWithSquad() extends SquadAction(16)
|
||||||
|
|
||||||
final case class SetListSquad() extends SquadAction(17)
|
final case class SetListSquad() extends SquadAction(17)
|
||||||
|
|
||||||
final case class ChangeSquadPurpose(purpose : String) extends SquadAction(19)
|
final case class ChangeSquadPurpose(purpose : String) extends SquadAction(19)
|
||||||
|
|
@ -110,10 +112,10 @@ object SquadAction{
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
val displayFullSquadCodec = everFailCondition.xmap[DisplayFullSquad] (
|
val squadMemberInitializationIssueCodec = everFailCondition.xmap[SquadMemberInitializationIssue] (
|
||||||
_ => DisplayFullSquad(),
|
_ => SquadMemberInitializationIssue(),
|
||||||
{
|
{
|
||||||
case DisplayFullSquad() => None
|
case SquadMemberInitializationIssue() => None
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -173,6 +175,13 @@ object SquadAction{
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val associateWithSquadCodec = everFailCondition.xmap[AssociateWithSquad] (
|
||||||
|
_ => AssociateWithSquad(),
|
||||||
|
{
|
||||||
|
case AssociateWithSquad() => None
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
val setListSquadCodec = everFailCondition.xmap[SetListSquad] (
|
val setListSquadCodec = everFailCondition.xmap[SetListSquad] (
|
||||||
_ => SetListSquad(),
|
_ => SetListSquad(),
|
||||||
{
|
{
|
||||||
|
|
@ -347,7 +356,7 @@ object SquadAction{
|
||||||
* `6 ` - UNKNOWN<br>
|
* `6 ` - UNKNOWN<br>
|
||||||
* `8 ` - Request List Squad<br>
|
* `8 ` - Request List Squad<br>
|
||||||
* `9 ` - Stop List Squad<br>
|
* `9 ` - Stop List Squad<br>
|
||||||
* `16` - UNKNOWN<br>
|
* `16` - Associate with Squad<br>
|
||||||
* `17` - Set List Squad (ui)<br>
|
* `17` - Set List Squad (ui)<br>
|
||||||
* `18` - UNKNOWN<br>
|
* `18` - UNKNOWN<br>
|
||||||
* `26` - Reset All<br>
|
* `26` - Reset All<br>
|
||||||
|
|
@ -415,7 +424,7 @@ object SquadDefinitionActionMessage extends Marshallable[SquadDefinitionActionMe
|
||||||
import scala.annotation.switch
|
import scala.annotation.switch
|
||||||
((code : @switch) match {
|
((code : @switch) match {
|
||||||
case 0 => displaySquadCodec
|
case 0 => displaySquadCodec
|
||||||
case 1 => displayFullSquadCodec
|
case 1 => squadMemberInitializationIssueCodec
|
||||||
case 3 => saveSquadFavoriteCodec
|
case 3 => saveSquadFavoriteCodec
|
||||||
case 4 => loadSquadFavoriteCodec
|
case 4 => loadSquadFavoriteCodec
|
||||||
case 5 => deleteSquadFavoriteCodec
|
case 5 => deleteSquadFavoriteCodec
|
||||||
|
|
@ -424,6 +433,7 @@ object SquadDefinitionActionMessage extends Marshallable[SquadDefinitionActionMe
|
||||||
case 9 => stopListSquadCodec
|
case 9 => stopListSquadCodec
|
||||||
case 10 => selectRoleForYourselfCodec
|
case 10 => selectRoleForYourselfCodec
|
||||||
case 15 => cancelSelectRoleForYourselfCodec
|
case 15 => cancelSelectRoleForYourselfCodec
|
||||||
|
case 16 => associateWithSquadCodec
|
||||||
case 17 => setListSquadCodec
|
case 17 => setListSquadCodec
|
||||||
case 19 => changeSquadPurposeCodec
|
case 19 => changeSquadPurposeCodec
|
||||||
case 20 => changeSquadZoneCodec
|
case 20 => changeSquadZoneCodec
|
||||||
|
|
@ -442,7 +452,7 @@ object SquadDefinitionActionMessage extends Marshallable[SquadDefinitionActionMe
|
||||||
case 40 => findLfsSoldiersForRoleCodec
|
case 40 => findLfsSoldiersForRoleCodec
|
||||||
case 41 => cancelFindCodec
|
case 41 => cancelFindCodec
|
||||||
case 2 | 6 | 11 |
|
case 2 | 6 | 11 |
|
||||||
12 | 13 | 14 | 16 |
|
12 | 13 | 14 |
|
||||||
18 | 29 | 30 | 32 | 33 |
|
18 | 29 | 30 | 32 | 33 |
|
||||||
36 | 37 | 42 | 43 => unknownCodec(code)
|
36 | 37 | 42 | 43 => unknownCodec(code)
|
||||||
case _ => failureCodec(code)
|
case _ => failureCodec(code)
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,14 @@
|
||||||
package services.teamwork
|
package services.teamwork
|
||||||
|
|
||||||
import net.psforever.objects.Player
|
import net.psforever.objects.Player
|
||||||
|
import net.psforever.objects.zones.Zone
|
||||||
import net.psforever.packet.game._
|
import net.psforever.packet.game._
|
||||||
import net.psforever.types.{SquadRequestType, Vector3}
|
import net.psforever.types.{SquadRequestType, Vector3}
|
||||||
|
|
||||||
object SquadAction {
|
object SquadAction {
|
||||||
trait Action
|
trait Action
|
||||||
|
|
||||||
final case class Definition(player : Player, zone_ordinal_number : Int, guid : PlanetSideGUID, line : Int, action : SquadAction) extends Action
|
final case class Definition(player : Player, zone : Zone, guid : PlanetSideGUID, line : Int, action : SquadAction) extends 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 Membership(request_type : SquadRequestType.Value, unk2 : Long, unk3 : Option[Long], player_name : String, unk5 : Option[Option[String]]) extends Action
|
||||||
final case class Update(char_id : Long, health : Int, max_health : Int, armor : Int, max_armor : Int, pos : Vector3, zone_number : Int) extends Action
|
final case class Update(char_id : Long, health : Int, max_health : Int, armor : Int, max_armor : Int, pos : Vector3, zone_number : Int) extends Action
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,10 @@ object SquadResponse {
|
||||||
final case class UpdateList(infos : Iterable[(Int, SquadInfo)]) extends Response
|
final case class UpdateList(infos : Iterable[(Int, SquadInfo)]) extends Response
|
||||||
final case class RemoveFromList(infos : Iterable[Int]) extends Response
|
final case class RemoveFromList(infos : Iterable[Int]) extends Response
|
||||||
|
|
||||||
final case class InitSquad(squad_guid : PlanetSideGUID) extends Response
|
final case class AssociateWithSquad(squad_guid : PlanetSideGUID) extends Response
|
||||||
|
final case class SetListSquad(squad_guid : PlanetSideGUID) extends Response
|
||||||
final case class Unknown17(squad : Squad, char_id : Long) extends Response
|
final case class Unknown17(squad : Squad, char_id : Long) extends Response
|
||||||
|
|
||||||
final case class Membership(request_type : SquadResponseType.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 Membership(request_type : SquadResponseType.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 Invite(from_char_id : Long, to_char_id : Long, name : String) extends Response
|
final case class Invite(from_char_id : Long, to_char_id : Long, name : String) extends Response
|
||||||
final case class WantsSquadPosition(bid_name : String) extends Response
|
final case class WantsSquadPosition(bid_name : String) extends Response
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import net.psforever.objects.Player
|
||||||
import net.psforever.objects.definition.converter.StatConverter
|
import net.psforever.objects.definition.converter.StatConverter
|
||||||
import net.psforever.objects.loadouts.SquadLoadout
|
import net.psforever.objects.loadouts.SquadLoadout
|
||||||
import net.psforever.objects.teamwork.{Member, Squad}
|
import net.psforever.objects.teamwork.{Member, Squad}
|
||||||
|
import net.psforever.objects.zones.Zone
|
||||||
import net.psforever.packet.game._
|
import net.psforever.packet.game._
|
||||||
import net.psforever.types._
|
import net.psforever.types._
|
||||||
import services.{GenericEventBus, Service}
|
import services.{GenericEventBus, Service}
|
||||||
|
|
@ -29,6 +30,19 @@ class SquadService extends Actor {
|
||||||
PlanetSideEmpire.VS -> ListBuffer.empty
|
PlanetSideEmpire.VS -> ListBuffer.empty
|
||||||
)
|
)
|
||||||
private val invites : mutable.LongMap[Invitation] = mutable.LongMap[Invitation]()
|
private val invites : mutable.LongMap[Invitation] = mutable.LongMap[Invitation]()
|
||||||
|
/**
|
||||||
|
* `initialAssociation` per squad is similar to "Does this squad want to recruit members?"
|
||||||
|
* The squad does not have to be listed.
|
||||||
|
* Dispatches an `AssociateWithSquad` `SDAM` to the squad leader and ???
|
||||||
|
* and then a `SDDUM` that includes at least the squad owner name and char id
|
||||||
|
* when a squad entry is removed from the list.
|
||||||
|
* Dispatched only once when a squad is first listed
|
||||||
|
* or when the squad leader searches for recruits by proximity or for certain roles or by invite
|
||||||
|
* or when a spontaneous squad forms,
|
||||||
|
* whichever happens first.
|
||||||
|
* Additionally, the packets are also sent when the check is made when the continent is changed (or set).
|
||||||
|
*/
|
||||||
|
private val initialAssociation : ListBuffer[PlanetSideGUID] = new ListBuffer[PlanetSideGUID]()
|
||||||
private val queuedInvites : mutable.LongMap[List[Invitation]] = mutable.LongMap[List[Invitation]]()
|
private val queuedInvites : mutable.LongMap[List[Invitation]] = mutable.LongMap[List[Invitation]]()
|
||||||
private val viewDetails : mutable.LongMap[PlanetSideGUID] = mutable.LongMap[PlanetSideGUID]()
|
private val viewDetails : mutable.LongMap[PlanetSideGUID] = mutable.LongMap[PlanetSideGUID]()
|
||||||
|
|
||||||
|
|
@ -166,6 +180,7 @@ class SquadService extends Actor {
|
||||||
memberToSquad += charId -> squad
|
memberToSquad += charId -> squad
|
||||||
idToSquad += id -> squad
|
idToSquad += id -> squad
|
||||||
idToSwitchboard += id -> switchboard
|
idToSwitchboard += id -> switchboard
|
||||||
|
initialAssociation += squad.GUID
|
||||||
squad
|
squad
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -241,6 +256,7 @@ class SquadService extends Actor {
|
||||||
case SquadServiceMessage(tplayer, squad_action) => squad_action match {
|
case SquadServiceMessage(tplayer, squad_action) => squad_action match {
|
||||||
case SquadAction.Membership(SquadRequestType.Invite, invitingPlayer, Some(invitedPlayer), _, _) =>
|
case SquadAction.Membership(SquadRequestType.Invite, invitingPlayer, Some(invitedPlayer), _, _) =>
|
||||||
//this is just busy work; for actual joining operations, see SquadRequestType.Accept
|
//this is just busy work; for actual joining operations, see SquadRequestType.Accept
|
||||||
|
//for the purposes of this code, tplayer.CharId == invitingPlayer
|
||||||
// FindBid(invitingPlayer, invitedPlayer) match {
|
// FindBid(invitingPlayer, invitedPlayer) match {
|
||||||
// case Some(bid) =>
|
// case Some(bid) =>
|
||||||
// //invitingPlayer and invitedPlayer have both tried to join each others's squads
|
// //invitingPlayer and invitedPlayer have both tried to join each others's squads
|
||||||
|
|
@ -262,29 +278,25 @@ class SquadService extends Actor {
|
||||||
case (Some(squad), None) =>
|
case (Some(squad), None) =>
|
||||||
//the classic situation
|
//the classic situation
|
||||||
log.info(s"$invitedPlayer has been invited to squad ${squad.Task} by $invitingPlayer")
|
log.info(s"$invitedPlayer has been invited to squad ${squad.Task} by $invitingPlayer")
|
||||||
val leader = squad.Leader
|
val charId = tplayer.CharId
|
||||||
val leaderCharId = leader.CharId
|
val bid = VacancyInvite(charId, tplayer.Name, squad.GUID)
|
||||||
val bid = VacancyInvite(leaderCharId, leader.Name, squad.GUID)
|
|
||||||
AddInvite(invitedPlayer, bid) match {
|
AddInvite(invitedPlayer, bid) match {
|
||||||
case out @ Some(_) if out.contains(bid) =>
|
case out @ Some(_) if out.contains(bid) =>
|
||||||
SquadEvents.publish(SquadServiceResponse(s"/$invitedPlayer/Squad", SquadResponse.Membership(SquadResponseType.Invite, 0, 0, leaderCharId, Some(invitedPlayer), tplayer.Name, false, Some(None))))
|
SquadEvents.publish(SquadServiceResponse(s"/$invitedPlayer/Squad", SquadResponse.Membership(SquadResponseType.Invite, 0, 0, charId, Some(invitedPlayer), tplayer.Name, false, Some(None))))
|
||||||
SquadEvents.publish(SquadServiceResponse(s"/$leaderCharId/Squad", SquadResponse.Membership(SquadResponseType.Invite, 0, 0, invitedPlayer, Some(leaderCharId), tplayer.Name, true, Some(None))))
|
SquadEvents.publish(SquadServiceResponse(s"/$charId/Squad", SquadResponse.Membership(SquadResponseType.Invite, 0, 0, invitedPlayer, Some(charId), tplayer.Name, true, Some(None))))
|
||||||
case Some(_) =>
|
case Some(_) =>
|
||||||
SquadEvents.publish(SquadServiceResponse(s"/$leaderCharId/Squad", SquadResponse.Membership(SquadResponseType.Invite, 0, 0, invitedPlayer, Some(leaderCharId), tplayer.Name, true, Some(None))))
|
SquadEvents.publish(SquadServiceResponse(s"/$charId/Squad", SquadResponse.Membership(SquadResponseType.Invite, 0, 0, invitedPlayer, Some(charId), tplayer.Name, true, Some(None))))
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
case (None, Some(squad)) =>
|
case (None, Some(squad)) =>
|
||||||
//flip around the roles - the inviting becomes the invited
|
//indirection; we're trying to invite ourselves to someone else's squad
|
||||||
//TODO needs work
|
val leaderCharId = squad.Leader.CharId
|
||||||
log.info(s"$invitedPlayer has asked $invitingPlayer for an invition to squad ${squad.Task}")
|
val bid = IndirectVacancy(tplayer, squad.GUID)
|
||||||
val bid = VacancyInvite(invitedPlayer, "", squad.GUID)
|
log.warn(s"$invitedPlayer has asked $invitingPlayer for an invitation to squad ${squad.Task}, but the squad leader needs to approve")
|
||||||
AddInvite(invitingPlayer, bid) match {
|
AddInvite(leaderCharId, bid) match {
|
||||||
case out @ Some(_) if out.contains(bid) =>
|
case out @ Some(_) if out.contains(bid) =>
|
||||||
SquadEvents.publish(SquadServiceResponse(s"/$invitingPlayer/Squad", SquadResponse.Membership(SquadResponseType.Invite, 0, 0, invitedPlayer, Some(invitingPlayer), tplayer.Name, false, Some(None))))
|
HandleBidForPosition(bid, tplayer)
|
||||||
SquadEvents.publish(SquadServiceResponse(s"/$invitedPlayer/Squad", SquadResponse.Membership(SquadResponseType.Invite, 0, 0, invitingPlayer, Some(invitedPlayer), tplayer.Name, true, Some(None))))
|
|
||||||
case Some(_) =>
|
|
||||||
SquadEvents.publish(SquadServiceResponse(s"/$invitedPlayer/Squad", SquadResponse.Membership(SquadResponseType.Invite, 0, 0, invitingPlayer, Some(invitedPlayer), tplayer.Name, true, Some(None))))
|
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -314,28 +326,61 @@ class SquadService extends Actor {
|
||||||
JoinSquad(petitioner, idToSquad(guid), position)
|
JoinSquad(petitioner, idToSquad(guid), position)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log.warn("Accept -> Bid: the invited player is already a member of a squad and can not join a second one")
|
log.warn("Accept->Bid: the invited player is already a member of a squad and can not join a second one")
|
||||||
}
|
}
|
||||||
|
|
||||||
case Some(VacancyInvite(invitingPlayer, _, guid))
|
case Some(IndirectVacancy(recruit, guid)) =>
|
||||||
if idToSquad.get(guid).nonEmpty =>
|
//tplayer / invitedPlayer is actually the squad leader
|
||||||
//we were invited by the squad leader into an existing squad
|
val recuitCharId = recruit.CharId
|
||||||
if(memberToSquad.get(invitedPlayer).isEmpty) {
|
HandleVacancyInvite(guid, recuitCharId, invitedPlayer, recruit) match {
|
||||||
val squad = idToSquad(guid)
|
case Some((squad, line)) =>
|
||||||
squad.Membership.zipWithIndex.find({ case (member, index) =>
|
SquadEvents.publish(SquadServiceResponse(s"/$recuitCharId/Squad", SquadResponse.Membership(SquadResponseType.Accept, 0, 0, invitedPlayer, Some(recuitCharId), "", true, Some(None))))
|
||||||
ValidOpenSquadPosition(squad, index, member, tplayer.Certifications)
|
JoinSquad(recruit, squad, line)
|
||||||
}) match {
|
//since we are the squad leader, we do not want to brush off our queued squad invite tasks
|
||||||
case Some((_, line)) =>
|
case _ => ;
|
||||||
SquadEvents.publish(SquadServiceResponse(s"/$invitingPlayer/Squad", SquadResponse.Membership(SquadResponseType.Accept, 0, 0, invitingPlayer, Some(invitedPlayer), tplayer.Name, false, Some(None))))
|
|
||||||
SquadEvents.publish(SquadServiceResponse(s"/$invitedPlayer/Squad", SquadResponse.Membership(SquadResponseType.Accept, 0, 0, invitedPlayer, Some(invitingPlayer), "", true, Some(None))))
|
|
||||||
JoinSquad(tplayer, squad, line)
|
|
||||||
RemoveQueuedInvites(invitedPlayer) //TODO deal with these somehow
|
|
||||||
case _ => ;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
log.warn("Accept -> Invite: the invited player is already a member of a squad and can not join a second one")
|
case Some(VacancyInvite(invitingPlayer, _, guid)) =>
|
||||||
|
//accepted an invitation to join an existing squad
|
||||||
|
HandleVacancyInvite(guid, invitedPlayer, invitingPlayer, tplayer) match {
|
||||||
|
case Some((squad, line)) =>
|
||||||
|
SquadEvents.publish(SquadServiceResponse(s"/$invitingPlayer/Squad", SquadResponse.Membership(SquadResponseType.Accept, 0, 0, invitingPlayer, Some(invitedPlayer), tplayer.Name, false, Some(None))))
|
||||||
|
SquadEvents.publish(SquadServiceResponse(s"/$invitedPlayer/Squad", SquadResponse.Membership(SquadResponseType.Accept, 0, 0, invitedPlayer, Some(invitingPlayer), "", true, Some(None))))
|
||||||
|
JoinSquad(tplayer, squad, line)
|
||||||
|
RemoveQueuedInvites(invitedPlayer) //TODO deal with these somehow
|
||||||
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
// if(idToSquad.get(guid).isEmpty) {
|
||||||
|
// log.warn("Accept->Invite: the squad no longer exists")
|
||||||
|
// }
|
||||||
|
// else if(memberToSquad.get(invitedPlayer).nonEmpty) {
|
||||||
|
// log.warn("Accept->Invite: player is already a member of a squad and can not join a second one")
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// val squad = idToSquad(guid)
|
||||||
|
// if(!squad.AutoApproveInvitationRequests && squad.Leader.CharId != invitingPlayer) {
|
||||||
|
// //the inviting player was not the squad leader and this decision should be bounced off the squad leader
|
||||||
|
// val bid = IndirectVacancy(tplayer, guid)
|
||||||
|
// AddInvite(squad.Leader.CharId, bid) match {
|
||||||
|
// case out @ Some(_) if out.contains(bid) =>
|
||||||
|
// HandleBidForPosition(bid, tplayer)
|
||||||
|
// case _ => ;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// //if a suitable position in the squad can be found, player may occupy it
|
||||||
|
// squad.Membership.zipWithIndex.find({ case (member, index) =>
|
||||||
|
// ValidOpenSquadPosition(squad, index, member, tplayer.Certifications)
|
||||||
|
// }) match {
|
||||||
|
// case Some((_, line)) =>
|
||||||
|
// SquadEvents.publish(SquadServiceResponse(s"/$invitingPlayer/Squad", SquadResponse.Membership(SquadResponseType.Accept, 0, 0, invitingPlayer, Some(invitedPlayer), tplayer.Name, false, Some(None))))
|
||||||
|
// SquadEvents.publish(SquadServiceResponse(s"/$invitedPlayer/Squad", SquadResponse.Membership(SquadResponseType.Accept, 0, 0, invitedPlayer, Some(invitingPlayer), "", true, Some(None))))
|
||||||
|
// JoinSquad(tplayer, squad, line)
|
||||||
|
// RemoveQueuedInvites(invitedPlayer) //TODO deal with these somehow
|
||||||
|
// case _ => ;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
case Some(SpontaneousInvite(invitingPlayer)) =>
|
case Some(SpontaneousInvite(invitingPlayer)) =>
|
||||||
//we were invited by someone into a new squad they would form
|
//we were invited by someone into a new squad they would form
|
||||||
|
|
@ -364,7 +409,7 @@ class SquadService extends Actor {
|
||||||
case None =>
|
case None =>
|
||||||
val squad = StartSquad(invitingPlayer)
|
val squad = StartSquad(invitingPlayer)
|
||||||
squad.Task = s"${tplayer.Name}'s Squad"
|
squad.Task = s"${tplayer.Name}'s Squad"
|
||||||
SquadEvents.publish(SquadServiceResponse(s"/$invitingPlayer/Squad", SquadResponse.InitSquad(squad.GUID)))
|
SquadEvents.publish(SquadServiceResponse(s"/$invitingPlayer/Squad", SquadResponse.AssociateWithSquad(squad.GUID)))
|
||||||
Some(squad)
|
Some(squad)
|
||||||
}) match {
|
}) match {
|
||||||
case Some(squad) =>
|
case Some(squad) =>
|
||||||
|
|
@ -409,7 +454,7 @@ class SquadService extends Actor {
|
||||||
.foreach { charId =>
|
.foreach { charId =>
|
||||||
SquadEvents.publish(SquadServiceResponse(s"/$charId/Squad", SquadResponse.Membership(SquadResponseType.Disband, 0, 0, charId, None, "", false, Some(None))))
|
SquadEvents.publish(SquadServiceResponse(s"/$charId/Squad", SquadResponse.Membership(SquadResponseType.Disband, 0, 0, charId, None, "", false, Some(None))))
|
||||||
}
|
}
|
||||||
SquadEvents.publish( SquadServiceResponse(s"/$leader/Squad", SquadResponse.InitSquad(PlanetSideGUID(0))) )
|
SquadEvents.publish( SquadServiceResponse(s"/$leader/Squad", SquadResponse.AssociateWithSquad(PlanetSideGUID(0))) )
|
||||||
SquadEvents.publish( SquadServiceResponse(s"/$leader/Squad", SquadResponse.Detail(PlanetSideGUID(0), SquadDetail().Complete)) )
|
SquadEvents.publish( SquadServiceResponse(s"/$leader/Squad", SquadResponse.Detail(PlanetSideGUID(0), SquadDetail().Complete)) )
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -456,19 +501,53 @@ class SquadService extends Actor {
|
||||||
case None => ;
|
case None => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// case SquadAction.Membership(SquadRequestType.Cancel, cancellingPlayer, _, _, _) =>
|
||||||
|
// //look for queued BidForPosition entries where we are the player who wants to join
|
||||||
|
// queuedInvites.foreach { case (leader, queueOfInvites) =>
|
||||||
|
// val list = queueOfInvites.filterNot { entry =>
|
||||||
|
// entry.isInstanceOf[BidForPosition] &&
|
||||||
|
// entry.asInstanceOf[BidForPosition].player.CharId == cancellingPlayer
|
||||||
|
// }
|
||||||
|
// if(list.nonEmpty && list.size != queueOfInvites.size) {
|
||||||
|
// queuedInvites(leader) = list
|
||||||
|
// }
|
||||||
|
// else if(list.isEmpty) {
|
||||||
|
// queuedInvites.remove(leader)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// //clean up active BidForPosition invite entries where we are the player who wants to join
|
||||||
|
// val list = invites.filter { case(_, entry) =>
|
||||||
|
// entry.isInstanceOf[BidForPosition] &&
|
||||||
|
// entry.asInstanceOf[BidForPosition].player.CharId == cancellingPlayer
|
||||||
|
// }
|
||||||
|
// list.foreach {
|
||||||
|
// case(charId, entry : BidForPosition) =>
|
||||||
|
// RemoveInvite(charId)
|
||||||
|
// SquadEvents.publish( SquadServiceResponse(s"/$charId/Squad", SquadResponse.Membership(SquadResponseType.Cancel, 0, 0, cancellingPlayer, None, entry.player.Name, false, None)))
|
||||||
|
// NextInvite(charId) match {
|
||||||
|
// case Some(bid : BidForPosition) =>
|
||||||
|
// HandleBidForPosition(bid, tplayer)
|
||||||
|
// case Some(bid) =>
|
||||||
|
// SquadEvents.publish(SquadServiceResponse(s"/$charId/Squad", SquadResponse.Membership(SquadResponseType.Invite, 0, 0, bid.InviterCharId, Some(charId), bid.InviterName, false, Some(None))))
|
||||||
|
// case _ => ;
|
||||||
|
// }
|
||||||
|
// case _ => ;
|
||||||
|
// }
|
||||||
|
|
||||||
case SquadAction.Membership(SquadRequestType.Promote, promotingPlayer, Some(promotedPlayer), _, _) =>
|
case SquadAction.Membership(SquadRequestType.Promote, promotingPlayer, Some(promotedPlayer), _, _) =>
|
||||||
(memberToSquad.get(promotingPlayer), memberToSquad.get(promotedPlayer)) match {
|
(memberToSquad.get(promotingPlayer), memberToSquad.get(promotedPlayer)) match {
|
||||||
case (Some(squad), Some(squad2)) if squad.GUID == squad2.GUID && squad.Leader.CharId == promotingPlayer =>
|
case (Some(squad), Some(squad2)) if squad.GUID == squad2.GUID && squad.Leader.CharId == promotingPlayer =>
|
||||||
val membership = squad.Membership.filter { _member => _member.CharId > 0 }
|
val membership = squad.Membership.filter { _member => _member.CharId > 0 }
|
||||||
val (leader, position) = (squad.Leader, 0)
|
val (leader, position) = (squad.Leader, 0)
|
||||||
val (member, index) = membership.zipWithIndex.find { case (_member, _) => _member.CharId == promotedPlayer }.get
|
val (member, index) = membership.zipWithIndex.find { case (_member, _) => _member.CharId == promotedPlayer }.get
|
||||||
|
log.info(s"Player ${leader.Name} steps down from leading ${squad.Task}")
|
||||||
SwapMemberPosition(squad, leader, member)
|
SwapMemberPosition(squad, leader, member)
|
||||||
log.info(s"Promoting player ${leader.Name} to be the leader of ${squad.Task}")
|
log.info(s"Promoting player ${leader.Name} to be the leader of ${squad.Task}")
|
||||||
membership.foreach { _member =>
|
membership.foreach { _member =>
|
||||||
SquadEvents.publish(SquadServiceResponse(s"/${_member.CharId}/Squad", SquadResponse.PromoteMember(squad, promotedPlayer, index, position)))
|
SquadEvents.publish(SquadServiceResponse(s"/${_member.CharId}/Squad", SquadResponse.PromoteMember(squad, promotedPlayer, index, position)))
|
||||||
}
|
}
|
||||||
SquadEvents.publish(SquadServiceResponse(s"/$promotingPlayer/Squad", SquadResponse.InitSquad(PlanetSideGUID(0))))
|
SquadEvents.publish(SquadServiceResponse(s"/$promotingPlayer/Squad", SquadResponse.AssociateWithSquad(PlanetSideGUID(0))))
|
||||||
SquadEvents.publish(SquadServiceResponse(s"/$promotedPlayer/Squad", SquadResponse.InitSquad(squad.GUID)))
|
SquadEvents.publish(SquadServiceResponse(s"/$promotedPlayer/Squad", SquadResponse.AssociateWithSquad(squad.GUID)))
|
||||||
UpdateSquadListWhenListed(
|
UpdateSquadListWhenListed(
|
||||||
squad,
|
squad,
|
||||||
SquadInfo().Leader(leader.Name)
|
SquadInfo().Leader(leader.Name)
|
||||||
|
|
@ -509,10 +588,10 @@ class SquadService extends Actor {
|
||||||
case None => ;
|
case None => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SquadAction.Definition(tplayer : Player, zone_ordinal_number : Int, guid : PlanetSideGUID, line : Int, action : SquadAction) =>
|
case SquadAction.Definition(tplayer : Player, zone : Zone, guid : PlanetSideGUID, line : Int, action : SquadAction) =>
|
||||||
import net.psforever.packet.game.SquadAction._
|
import net.psforever.packet.game.SquadAction._
|
||||||
val pSquadOpt = GetParticipatingSquad(tplayer)
|
val pSquadOpt = GetParticipatingSquad(tplayer)
|
||||||
val lSquadOpt = GetLeadingSquad(tplayer, zone_ordinal_number, pSquadOpt)
|
val lSquadOpt = GetLeadingSquad(tplayer, zone.Number, pSquadOpt)
|
||||||
//the following actions can only be performed by a squad's leader
|
//the following actions can only be performed by a squad's leader
|
||||||
action match {
|
action match {
|
||||||
case SaveSquadFavorite() =>
|
case SaveSquadFavorite() =>
|
||||||
|
|
@ -528,8 +607,8 @@ class SquadService extends Actor {
|
||||||
case Some(loadout : SquadLoadout) if squad.Size == 1 =>
|
case Some(loadout : SquadLoadout) if squad.Size == 1 =>
|
||||||
log.info(s"${tplayer.Name} is loading a squad composition: $loadout")
|
log.info(s"${tplayer.Name} is loading a squad composition: $loadout")
|
||||||
SquadService.LoadSquadDefinition(squad, loadout)
|
SquadService.LoadSquadDefinition(squad, loadout)
|
||||||
sender ! SquadServiceResponse("", SquadResponse.InitSquad(squad.GUID))
|
sender ! SquadServiceResponse("", SquadResponse.AssociateWithSquad(squad.GUID))
|
||||||
UpdateSquadList(squad, SquadInfo().Task(squad.Task).ZoneId(PlanetSideZoneID(squad.ZoneId)).Capacity(squad.Capacity))
|
UpdateSquadList(squad, SquadService.SquadList.Publish(squad))
|
||||||
UpdateSquadDetail(PlanetSideGUID(0), squad)
|
UpdateSquadDetail(PlanetSideGUID(0), squad)
|
||||||
case _ =>
|
case _ =>
|
||||||
}
|
}
|
||||||
|
|
@ -550,7 +629,12 @@ class SquadService extends Actor {
|
||||||
val squad = lSquadOpt.getOrElse(StartSquad(tplayer))
|
val squad = lSquadOpt.getOrElse(StartSquad(tplayer))
|
||||||
squad.ZoneId = zone.zoneId.toInt
|
squad.ZoneId = zone.zoneId.toInt
|
||||||
UpdateSquadListWhenListed(squad, SquadInfo().ZoneId(zone))
|
UpdateSquadListWhenListed(squad, SquadInfo().ZoneId(zone))
|
||||||
UpdateSquadDetail(squad.GUID, squad, SquadDetail().ZoneId(zone))
|
InitialAssociation(squad)
|
||||||
|
sender ! SquadServiceResponse("", SquadResponse.Detail(
|
||||||
|
squad.GUID,
|
||||||
|
SquadService.Detail.Publish(squad))
|
||||||
|
)
|
||||||
|
UpdateSquadDetail(squad.GUID, squad.Membership.map { _m => _m.CharId }.filterNot { _ == squad.Leader.CharId }, SquadDetail().ZoneId(zone))
|
||||||
|
|
||||||
case CloseSquadMemberPosition(position) =>
|
case CloseSquadMemberPosition(position) =>
|
||||||
val squad = lSquadOpt.getOrElse(StartSquad(tplayer))
|
val squad = lSquadOpt.getOrElse(StartSquad(tplayer))
|
||||||
|
|
@ -647,7 +731,8 @@ class SquadService extends Actor {
|
||||||
if(!squad.Listed && squad.Task.nonEmpty && squad.ZoneId > 0) {
|
if(!squad.Listed && squad.Task.nonEmpty && squad.ZoneId > 0) {
|
||||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has opened public recruitment for squad ${squad.Task}")
|
log.info(s"${tplayer.Name}-${tplayer.Faction} has opened public recruitment for squad ${squad.Task}")
|
||||||
squad.Listed = true
|
squad.Listed = true
|
||||||
sender ! SquadServiceResponse("", SquadResponse.InitSquad(squad.GUID))
|
InitialAssociation(squad)
|
||||||
|
sender ! SquadServiceResponse("", SquadResponse.SetListSquad(squad.GUID))
|
||||||
UpdateSquadList(squad, None)
|
UpdateSquadList(squad, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -656,7 +741,7 @@ class SquadService extends Actor {
|
||||||
if(squad.Listed) {
|
if(squad.Listed) {
|
||||||
log.info(s"${tplayer.Name}-${tplayer.Faction} has closed public recruitment for squad ${squad.Task}")
|
log.info(s"${tplayer.Name}-${tplayer.Faction} has closed public recruitment for squad ${squad.Task}")
|
||||||
squad.Listed = false
|
squad.Listed = false
|
||||||
sender ! SquadServiceResponse("", SquadResponse.InitSquad(PlanetSideGUID(0)))
|
sender ! SquadServiceResponse("", SquadResponse.AssociateWithSquad(PlanetSideGUID(0)))
|
||||||
UpdateSquadList(squad, None)
|
UpdateSquadList(squad, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -676,6 +761,9 @@ class SquadService extends Actor {
|
||||||
squad.AutoApproveInvitationRequests = false
|
squad.AutoApproveInvitationRequests = false
|
||||||
UpdateSquadListWhenListed(squad, SquadInfo().Task("").ZoneId(None).Capacity(squad.Capacity))
|
UpdateSquadListWhenListed(squad, SquadInfo().Task("").ZoneId(None).Capacity(squad.Capacity))
|
||||||
UpdateSquadDetail(squad.GUID, squad)
|
UpdateSquadDetail(squad.GUID, squad)
|
||||||
|
sender ! SquadServiceResponse("", SquadResponse.AssociateWithSquad(PlanetSideGUID(0)))
|
||||||
|
initialAssociation += squad.GUID
|
||||||
|
//do not unlist an already listed squad
|
||||||
|
|
||||||
case _ =>
|
case _ =>
|
||||||
}
|
}
|
||||||
|
|
@ -736,6 +824,63 @@ class SquadService extends Actor {
|
||||||
//squad does not exist? assume old local data; force update to correct discrepancy
|
//squad does not exist? assume old local data; force update to correct discrepancy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//the following action can be performed by anyone who has tried to join a squad
|
||||||
|
case (_, CancelSelectRoleForYourself(_)) =>
|
||||||
|
val cancellingPlayer = tplayer.CharId
|
||||||
|
idToSquad.get(guid) match {
|
||||||
|
case Some(squad) =>
|
||||||
|
//assumption: a player who is cancelling will rarely end up with their invite queued
|
||||||
|
val leaderCharId = squad.Leader.CharId
|
||||||
|
//clean up any active BidForPosition invite entry where we are the player who wants to join the leader's squad
|
||||||
|
((invites.get(leaderCharId) match {
|
||||||
|
case out @ Some(entry) if entry.isInstanceOf[BidForPosition] &&
|
||||||
|
entry.asInstanceOf[BidForPosition].player.CharId == cancellingPlayer =>
|
||||||
|
out
|
||||||
|
case _ =>
|
||||||
|
None
|
||||||
|
}) match {
|
||||||
|
case Some(entry : BidForPosition) =>
|
||||||
|
RemoveInvite(leaderCharId)
|
||||||
|
SquadEvents.publish( SquadServiceResponse(s"/$leaderCharId/Squad", SquadResponse.Membership(SquadResponseType.Cancel, 0, 0, cancellingPlayer, None, entry.player.Name, false, Some(None))))
|
||||||
|
NextInvite(leaderCharId) match {
|
||||||
|
case Some(bid : BidForPosition) =>
|
||||||
|
HandleBidForPosition(bid, tplayer)
|
||||||
|
case Some(bid) =>
|
||||||
|
SquadEvents.publish(SquadServiceResponse(s"/$leaderCharId/Squad", SquadResponse.Membership(SquadResponseType.Invite, 0, 0, bid.InviterCharId, Some(leaderCharId), bid.InviterName, false, Some(None))))
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
Some(true)
|
||||||
|
case _ =>
|
||||||
|
None
|
||||||
|
}).orElse(
|
||||||
|
//look for a queued BidForPosition entry where we are the player who wants to join the leader's squad
|
||||||
|
(queuedInvites.get(leaderCharId) match {
|
||||||
|
case Some(_list) =>
|
||||||
|
(_list, _list.indexWhere { entry =>
|
||||||
|
entry.isInstanceOf[BidForPosition] &&
|
||||||
|
entry.asInstanceOf[BidForPosition].player.CharId == cancellingPlayer
|
||||||
|
})
|
||||||
|
case None =>
|
||||||
|
(Nil, -1)
|
||||||
|
}) match {
|
||||||
|
case (_, -1) =>
|
||||||
|
None //no change
|
||||||
|
case (list, index) if list.size == 1 =>
|
||||||
|
val entry = list.head.asInstanceOf[BidForPosition]
|
||||||
|
SquadEvents.publish( SquadServiceResponse(s"/$leaderCharId/Squad", SquadResponse.Membership(SquadResponseType.Cancel, 0, 0, cancellingPlayer, None, entry.player.Name, false, Some(None))))
|
||||||
|
queuedInvites.remove(leaderCharId)
|
||||||
|
Some(true)
|
||||||
|
case (list, index) =>
|
||||||
|
val entry = list(index).asInstanceOf[BidForPosition]
|
||||||
|
SquadEvents.publish( SquadServiceResponse(s"/$leaderCharId/Squad", SquadResponse.Membership(SquadResponseType.Cancel, 0, 0, cancellingPlayer, None, entry.player.Name, false, Some(None))))
|
||||||
|
queuedInvites(leaderCharId) = list.take(index) ++ list.drop(index+1)
|
||||||
|
Some(true)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
|
||||||
//the following action can be performed by ???
|
//the following action can be performed by ???
|
||||||
case (Some(squad), AssignSquadMemberToRole(position, char_id)) =>
|
case (Some(squad), AssignSquadMemberToRole(position, char_id)) =>
|
||||||
val membership = squad.Membership.zipWithIndex
|
val membership = squad.Membership.zipWithIndex
|
||||||
|
|
@ -771,12 +916,12 @@ class SquadService extends Actor {
|
||||||
}
|
}
|
||||||
|
|
||||||
//the following message is feedback from a specific client, awaiting proper initialization
|
//the following message is feedback from a specific client, awaiting proper initialization
|
||||||
case (_, DisplayFullSquad()) =>
|
case (_, SquadMemberInitializationIssue()) =>
|
||||||
idToSquad.get(guid) match {
|
// idToSquad.get(guid) match {
|
||||||
case Some(squad) =>
|
// case Some(squad) =>
|
||||||
sender ! SquadServiceResponse("", SquadResponse.InitSquad(squad.GUID))
|
// sender ! SquadServiceResponse("", SquadResponse.Detail(squad.GUID, SquadService.Detail.Publish(squad)))
|
||||||
case None => ;
|
// case None => ;
|
||||||
}
|
// }
|
||||||
|
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
@ -886,19 +1031,90 @@ class SquadService extends Actor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def HandleVacancyInvite(squad_guid : PlanetSideGUID, invitedPlayer : Long, invitingPlayer : Long, recruit : Player) : Option[(Squad, Int)] = {
|
||||||
|
//accepted an invitation to join an existing squad
|
||||||
|
if(idToSquad.get(squad_guid).isEmpty) {
|
||||||
|
log.warn(s"Accept->Invite: the squad #${squad_guid.guid} no longer exists")
|
||||||
|
None
|
||||||
|
}
|
||||||
|
else if(memberToSquad.get(invitedPlayer).nonEmpty) {
|
||||||
|
log.warn(s"Accept->Invite: ${recruit.Name} is already a member of a squad and can not join squad #${squad_guid.guid}")
|
||||||
|
None
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val squad = idToSquad(squad_guid)
|
||||||
|
if(!squad.AutoApproveInvitationRequests && squad.Leader.CharId != invitingPlayer) {
|
||||||
|
//the inviting player was not the squad leader and this decision should be bounced off the squad leader
|
||||||
|
val bid = IndirectVacancy(recruit, squad_guid)
|
||||||
|
AddInvite(squad.Leader.CharId, bid) match {
|
||||||
|
case out @ Some(_) if out.contains(bid) =>
|
||||||
|
SquadEvents.publish(SquadServiceResponse(s"/$invitingPlayer/Squad", SquadResponse.Membership(SquadResponseType.Accept, 0, 0, invitingPlayer, Some(invitedPlayer), recruit.Name, false, Some(None))))
|
||||||
|
HandleBidForPosition(bid, recruit)
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
log.info(s"Accept->Invite: ${recruit.Name} must await an invitation from the leader of squad #${squad_guid.guid}")
|
||||||
|
None
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//if a suitable position in the squad can be found, player may occupy it
|
||||||
|
squad.Membership.zipWithIndex.find({ case (member, index) =>
|
||||||
|
ValidOpenSquadPosition(squad, index, member, recruit.Certifications)
|
||||||
|
}) match {
|
||||||
|
case Some((_, line)) =>
|
||||||
|
Some((squad, line))
|
||||||
|
case _ =>
|
||||||
|
if(squad.Size == squad.Capacity) {
|
||||||
|
log.warn(s"Accept->Invite: squad #${squad_guid.guid} is already full and ${recruit.Name} can not join it")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log.warn(s"Accept->Invite: squad #${squad_guid.guid} has no positions available that satisfy ${recruit.Name}")
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def InitialAssociation(squad : Squad) : Boolean = {
|
||||||
|
val guid = squad.GUID
|
||||||
|
initialAssociation.indexOf(guid) match {
|
||||||
|
case -1 => ;
|
||||||
|
case index =>
|
||||||
|
initialAssociation.remove(index)
|
||||||
|
val charId = squad.Leader.CharId
|
||||||
|
SquadEvents.publish(
|
||||||
|
SquadServiceResponse(s"/$charId/Squad", SquadResponse.AssociateWithSquad(guid))
|
||||||
|
)
|
||||||
|
SquadEvents.publish(
|
||||||
|
SquadServiceResponse(s"/$charId/Squad", SquadResponse.Detail(
|
||||||
|
guid,
|
||||||
|
SquadService.Detail.Publish(squad))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
def HandleBidForPosition(bid : BidForPosition, player : Player) : Unit = {
|
def HandleBidForPosition(bid : BidForPosition, player : Player) : Unit = {
|
||||||
idToSquad.get(bid.squad_guid) match {
|
HandleBidForPosition(bid, bid.squad_guid, bid.player.Name, player)
|
||||||
|
}
|
||||||
|
def HandleBidForPosition(bid : IndirectVacancy, player : Player) : Unit = {
|
||||||
|
HandleBidForPosition(bid, bid.squad_guid, bid.player.Name, player)
|
||||||
|
}
|
||||||
|
|
||||||
|
def HandleBidForPosition(bid : Invitation, squad_guid : PlanetSideGUID, name : String, player : Player) : Unit = {
|
||||||
|
idToSquad.get(squad_guid) match {
|
||||||
case Some(squad) =>
|
case Some(squad) =>
|
||||||
val leaderCharId = squad.Leader.CharId
|
val leaderCharId = squad.Leader.CharId
|
||||||
if(squad.AutoApproveInvitationRequests) {
|
if(squad.AutoApproveInvitationRequests) {
|
||||||
self ! SquadServiceMessage(player, SquadAction.Membership(SquadRequestType.Accept, leaderCharId, None, "", None))
|
self ! SquadServiceMessage(player, SquadAction.Membership(SquadRequestType.Accept, leaderCharId, None, "", None))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SquadEvents.publish(SquadServiceResponse(s"/$leaderCharId/Squad", SquadResponse.WantsSquadPosition(bid.player.Name)))
|
SquadEvents.publish(SquadServiceResponse(s"/$leaderCharId/Squad", SquadResponse.WantsSquadPosition(name)))
|
||||||
}
|
}
|
||||||
case _ =>
|
case _ =>
|
||||||
//squad is missing; will this properly short-circuit?
|
//squad is missing; will this properly short-circuit?
|
||||||
log.error(s"Attempted to process ${bid.InviterName}'s bid for a position in a squad (id:${bid.squad_guid.guid}) that does not exist")
|
log.error(s"Attempted to process ${bid.InviterName}'s bid for a position in a squad (id:${squad_guid.guid}) that does not exist")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -915,6 +1131,8 @@ class SquadService extends Actor {
|
||||||
position.ZoneId = 13
|
position.ZoneId = 13
|
||||||
memberToSquad(charId) = squad
|
memberToSquad(charId) = squad
|
||||||
|
|
||||||
|
InitialAssociation(squad)
|
||||||
|
SquadEvents.publish( SquadServiceResponse(s"/$charId/Squad", SquadResponse.AssociateWithSquad(squad.GUID)) )
|
||||||
val size = squad.Size
|
val size = squad.Size
|
||||||
if(size == 1) {
|
if(size == 1) {
|
||||||
//leader joins the squad? do nothing?
|
//leader joins the squad? do nothing?
|
||||||
|
|
@ -934,20 +1152,18 @@ class SquadService extends Actor {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//joining an active squad; everybody updates differently
|
//joining an active squad; everybody updates differently
|
||||||
//new member gets full UI updates
|
//new member gets full squad UI updates
|
||||||
val indices = squad.Membership.zipWithIndex
|
val indices = squad.Membership.zipWithIndex.collect({ case (member, index) if member.CharId != 0 => index }).toList
|
||||||
.collect({ case (member, index) if member.CharId != 0 => index }).toList
|
|
||||||
SquadEvents.publish(SquadServiceResponse(s"/$charId/Squad", SquadResponse.Join(squad, indices)))
|
SquadEvents.publish(SquadServiceResponse(s"/$charId/Squad", SquadResponse.Join(squad, indices)))
|
||||||
//other squad members see us joining the squad
|
InitSquadDetail(squad.GUID, Seq(charId), squad)
|
||||||
|
//other squad members see new member joining the squad
|
||||||
val updatedIndex = List(line)
|
val updatedIndex = List(line)
|
||||||
squad.Membership
|
val otherMembers = squad.Membership.filterNot { member => member.CharId == 0 || member.CharId == charId }.map{ _.CharId }
|
||||||
.filterNot { member => member.CharId == 0 || member.CharId == charId }
|
otherMembers.foreach { member =>
|
||||||
.foreach { member =>
|
SquadEvents.publish(SquadServiceResponse(s"/$member/Squad", SquadResponse.Join(squad, updatedIndex)))
|
||||||
SquadEvents.publish(SquadServiceResponse(s"/${member.CharId}/Squad", SquadResponse.Join(squad, updatedIndex)))
|
}
|
||||||
}
|
val details = SquadDetail().Members(List(SquadPositionEntry(line, SquadPositionDetail().CharId(charId).Name(player.Name))))
|
||||||
UpdateSquadDetail(squad.GUID, squad,
|
UpdateSquadDetail(squad.GUID, Seq(charId), details)
|
||||||
SquadDetail().Members(List(SquadPositionEntry(line, SquadPositionDetail().CharId(charId).Name(player.Name))))
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
UpdateSquadListWhenListed(squad, SquadInfo().Size(size))
|
UpdateSquadListWhenListed(squad, SquadInfo().Size(size))
|
||||||
true
|
true
|
||||||
|
|
@ -1085,17 +1301,36 @@ class SquadService extends Actor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def InitSquadDetail(squad : Squad) : Unit = {
|
||||||
|
InitSquadDetail(squad.GUID, squad.Membership.map { member => member.CharId }, squad)
|
||||||
|
}
|
||||||
|
|
||||||
|
def InitSquadDetail(guid : PlanetSideGUID, squad : Squad) : Unit = {
|
||||||
|
InitSquadDetail(guid, squad.Membership.map { member => member.CharId }, squad)
|
||||||
|
}
|
||||||
|
|
||||||
|
def InitSquadDetail(guid : PlanetSideGUID, toMembers : Iterable[Long], squad : Squad) : Unit = {
|
||||||
|
val output = SquadResponse.Detail(guid, SquadService.Detail.Publish(squad))
|
||||||
|
toMembers.foreach { charId => SquadEvents.publish(SquadServiceResponse(s"/$charId/Squad", output)) }
|
||||||
|
}
|
||||||
|
|
||||||
def UpdateSquadDetail(guid : PlanetSideGUID, squad : Squad) : Unit = {
|
def UpdateSquadDetail(guid : PlanetSideGUID, squad : Squad) : Unit = {
|
||||||
UpdateSquadDetail(guid, squad, SquadService.Detail.Publish(squad))
|
UpdateSquadDetail(guid, squad, SquadService.Detail.Publish(squad))
|
||||||
}
|
}
|
||||||
|
|
||||||
def UpdateSquadDetail(guid : PlanetSideGUID, squad : Squad, detail : SquadDetail) : Unit = {
|
def UpdateSquadDetail(squad : Squad, details : SquadDetail) : Unit = {
|
||||||
val output = SquadResponse.Detail(guid, detail)
|
UpdateSquadDetail(squad.GUID, squad.Membership.map { member => member.CharId }, details)
|
||||||
squad.Membership
|
}
|
||||||
.filter { _.CharId > 0L }
|
|
||||||
.foreach { member =>
|
def UpdateSquadDetail(guid : PlanetSideGUID, squad : Squad, details : SquadDetail) : Unit = {
|
||||||
SquadEvents.publish(SquadServiceResponse(s"/${member.CharId}/Squad", output))
|
UpdateSquadDetail(guid, squad.Membership.map { member => member.CharId }, details)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def UpdateSquadDetail(guid : PlanetSideGUID, toMembers : Iterable[Long], details : SquadDetail) : Unit = {
|
||||||
|
if(toMembers.nonEmpty) {
|
||||||
|
val output = SquadResponse.Detail(guid, details)
|
||||||
|
toMembers.foreach { charId => SquadEvents.publish(SquadServiceResponse(s"/$charId/Squad", output)) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1105,12 +1340,31 @@ object SquadService {
|
||||||
def InviterName : String = name
|
def InviterName : String = name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utilized when one player attempts to join an existing squad in a specific role.
|
||||||
|
* @param player na
|
||||||
|
* @param squad_guid na
|
||||||
|
* @param position na
|
||||||
|
*/
|
||||||
final case class BidForPosition(player : Player, squad_guid : PlanetSideGUID, position : Int)
|
final case class BidForPosition(player : Player, squad_guid : PlanetSideGUID, position : Int)
|
||||||
extends Invitation(player.CharId, player.Name)
|
extends Invitation(player.CharId, player.Name)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utilized when one squad member issues an invite for some other player.
|
||||||
|
* @param char_id na
|
||||||
|
* @param name na
|
||||||
|
* @param squad_guid na
|
||||||
|
*/
|
||||||
final case class VacancyInvite(char_id : Long, name : String, squad_guid : PlanetSideGUID)
|
final case class VacancyInvite(char_id : Long, name : String, squad_guid : PlanetSideGUID)
|
||||||
extends Invitation(char_id, name)
|
extends Invitation(char_id, name)
|
||||||
|
|
||||||
|
final case class IndirectVacancy(player : Player, squad_guid : PlanetSideGUID)
|
||||||
|
extends Invitation(player.CharId, player.Name)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utilized when one player issues an invite for some other player for a squad that does not yet exist.
|
||||||
|
* @param player na
|
||||||
|
*/
|
||||||
final case class SpontaneousInvite(player : Player)
|
final case class SpontaneousInvite(player : Player)
|
||||||
extends Invitation(player.CharId, player.Name)
|
extends Invitation(player.CharId, player.Name)
|
||||||
|
|
||||||
|
|
@ -1130,6 +1384,7 @@ object SquadService {
|
||||||
object Detail {
|
object Detail {
|
||||||
def Publish(squad : Squad) : SquadDetail = {
|
def Publish(squad : Squad) : SquadDetail = {
|
||||||
SquadDetail()
|
SquadDetail()
|
||||||
|
.Field1(squad.GUID.guid)
|
||||||
.LeaderCharId(squad.Leader.CharId)
|
.LeaderCharId(squad.Leader.CharId)
|
||||||
.LeaderName(squad.Leader.Name)
|
.LeaderName(squad.Leader.Name)
|
||||||
.Task(squad.Task)
|
.Task(squad.Task)
|
||||||
|
|
|
||||||
|
|
@ -379,8 +379,10 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
case SquadResponse.Detail(guid, detail) =>
|
case SquadResponse.Detail(guid, detail) =>
|
||||||
sendResponse(SquadDetailDefinitionUpdateMessage(guid, detail))
|
sendResponse(SquadDetailDefinitionUpdateMessage(guid, detail))
|
||||||
|
|
||||||
case SquadResponse.InitSquad(squad_guid) =>
|
case SquadResponse.AssociateWithSquad(squad_guid) =>
|
||||||
sendResponse(SquadDefinitionActionMessage(squad_guid, 0, SquadAction.Unknown(16)))
|
sendResponse(SquadDefinitionActionMessage(squad_guid, 0, SquadAction.AssociateWithSquad()))
|
||||||
|
|
||||||
|
case SquadResponse.SetListSquad(squad_guid) =>
|
||||||
sendResponse(SquadDefinitionActionMessage(squad_guid, 0, SquadAction.SetListSquad()))
|
sendResponse(SquadDefinitionActionMessage(squad_guid, 0, SquadAction.SetListSquad()))
|
||||||
|
|
||||||
case SquadResponse.Unknown17(squad, char_id) =>
|
case SquadResponse.Unknown17(squad, char_id) =>
|
||||||
|
|
@ -3010,7 +3012,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(0), line, SquadAction.ListSquadFavorite("")))
|
sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(0), line, SquadAction.ListSquadFavorite("")))
|
||||||
})
|
})
|
||||||
sendResponse(SquadDetailDefinitionUpdateMessage.Init)
|
sendResponse(SquadDetailDefinitionUpdateMessage.Init)
|
||||||
sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(0), 0,SquadAction.Unknown(16)))
|
sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(0), 0,SquadAction.AssociateWithSquad()))
|
||||||
sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(0), 0,SquadAction.SetListSquad()))
|
sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(0), 0,SquadAction.SetListSquad()))
|
||||||
sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(0), 0,SquadAction.Unknown(18)))
|
sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(0), 0,SquadAction.Unknown(18)))
|
||||||
//MapObjectStateBlockMessage and ObjectCreateMessage?
|
//MapObjectStateBlockMessage and ObjectCreateMessage?
|
||||||
|
|
@ -3108,6 +3110,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
avatar.Certifications += AssaultEngineering
|
avatar.Certifications += AssaultEngineering
|
||||||
avatar.Certifications += Hacking
|
avatar.Certifications += Hacking
|
||||||
avatar.Certifications += AdvancedHacking
|
avatar.Certifications += AdvancedHacking
|
||||||
|
avatar.CEP = 6000001
|
||||||
this.avatar = avatar
|
this.avatar = avatar
|
||||||
|
|
||||||
InitializeDeployableQuantities(avatar) //set deployables ui elements
|
InitializeDeployableQuantities(avatar) //set deployables ui elements
|
||||||
|
|
@ -4957,7 +4960,7 @@ 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(player, SquadServiceAction.Definition(player, continent.Number, u1, u2, action))
|
squadService ! SquadServiceMessage(player, SquadServiceAction.Definition(player, continent, u1, u2, action))
|
||||||
|
|
||||||
case msg @ SquadMembershipRequest(request_type, unk2, unk3, player_name, unk5) =>
|
case msg @ SquadMembershipRequest(request_type, unk2, unk3, player_name, unk5) =>
|
||||||
log.info(s"$msg")
|
log.info(s"$msg")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue