Squad Chat Disabled (#761)

* spin up a test server where the chat channel for squads never gets interested with

* where art thou, oh, squad leader?

* leave only one channel, not be left with only one channel

* once again, filtering is wrong

* squad list reloads after zoning; squad size is checked against squad capacity before handling standard invitations
This commit is contained in:
Fate-JH 2021-04-14 21:06:01 -04:00 committed by GitHub
parent 0143f3b072
commit 51d46d86d3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 96 additions and 84 deletions

View file

@ -117,7 +117,7 @@ class ChatActor(
case LeaveChannel(channel) => case LeaveChannel(channel) =>
chatService ! ChatService.LeaveChannel(chatServiceAdapter, channel) chatService ! ChatService.LeaveChannel(chatServiceAdapter, channel)
channels = channels.filter(_ == channel) channels = channels.filterNot(_ == channel)
Behaviors.same Behaviors.same
case Message(message) => case Message(message) =>

View file

@ -775,7 +775,6 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
None None
) )
} }
.toList
) )
) )
@ -3303,6 +3302,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
*/ */
def ZoneChangeSquadSetup(): Unit = { def ZoneChangeSquadSetup(): Unit = {
RespawnSquadSetup() RespawnSquadSetup()
squadService ! SquadServiceMessage(player, continent, SquadServiceAction.InitSquadList())
GiveSquadColorsInZone() GiveSquadColorsInZone()
squadSetup = RespawnSquadSetup squadSetup = RespawnSquadSetup
} }

View file

@ -33,10 +33,11 @@ class SquadFeatures(val Squad: Squad) {
* <br> * <br>
* All of the waypoints constantly exist as long as the squad to which they are attached exists. * All of the waypoints constantly exist as long as the squad to which they are attached exists.
* They are merely "activated" and "deactivated." * They are merely "activated" and "deactivated."
* When "activated," the waypoint knows on which continent to appear and where on the map and in the game world to be positioned. * When "activated," the waypoint knows on which continent to appear
* Waypoints manifest in the game world as a far-off beam of light that extends into the sky * and where on the map and in the game world to be positioned.
* Waypoints manifest in the game world as a (usually far-off) beam of light that extends into the sky
* and whose ground contact utilizes a downwards pulsating arrow. * and whose ground contact utilizes a downwards pulsating arrow.
* On the continental map and deployment map, they appear as a diamond, with a differentiating number where applicable. * On the continental map and deployment map, they appear as a diamond, with a different number where applicable.
* The squad leader experience rally, for example, does not have a number like the preceding four waypoints. * The squad leader experience rally, for example, does not have a number like the preceding four waypoints.
* @see `Start` * @see `Start`
*/ */
@ -44,10 +45,10 @@ class SquadFeatures(val Squad: Squad) {
/** /**
* The particular position being recruited right at the moment. * The particular position being recruited right at the moment.
* When `None`. no highlighted searches have been indicated. * When `None`, no highlighted searches have been indicated.
* When a positive integer or 0, indicates distributed `LookingForSquadRoleInvite` messages as recorded by `proxyInvites`. * When a positive integer or 0, indicates distributed `LookingForSquadRoleInvite` messages as recorded by `proxyInvites`.
* Only one position may bne actively recruited at a time in this case. * Only one position may be actively recruited at a time in this case.
* When -1, indicates distributed `ProximityIvite` messages as recorded by `proxyInvites`. * When -1, indicates distributed `ProximityInvite` messages as recorded by `proxyInvites`.
* Previous efforts may or may not be forgotten if there is a switch between the two modes. * Previous efforts may or may not be forgotten if there is a switch between the two modes.
*/ */
private var searchForRole: Option[Int] = None private var searchForRole: Option[Int] = None
@ -58,14 +59,14 @@ class SquadFeatures(val Squad: Squad) {
private var proxyInvites: List[Long] = Nil private var proxyInvites: List[Long] = Nil
/** /**
* These useres rejected invitation to this squad. * These users rejected invitation to this squad.
* For the purposes of wide-searches for membership * For the purposes of wide-searches for membership
* such as Looking For Squad checks and proximity invitation, * such as Looking For Squad checks and proximity invitation,
* the unique character identifier numbers in this list are skipped. * the unique character identifier numbers in this list are skipped.
* Direct invitation requests from the non sqad member should remain functional. * Direct invitation requests from the non sqad member should remain functional.
*/ */
private var refusedPlayers: List[Long] = Nil private var refusedPlayers: List[Long] = Nil
private var autoApproveInvitationRequests: Boolean = true private var autoApproveInvitationRequests: Boolean = false
private var locationFollowsSquadLead: Boolean = true private var locationFollowsSquadLead: Boolean = true
private var listed: Boolean = false private var listed: Boolean = false

View file

@ -50,21 +50,21 @@ class ChatService(context: ActorContext[ChatService.Command]) extends AbstractBe
this this
case LeaveChannel(actor, channel) => case LeaveChannel(actor, channel) =>
subscriptions = subscriptions.filter { subscriptions = subscriptions.filterNot {
case JoinChannel(a, _, c) => actor != a && channel != c case JoinChannel(a, _, c) => actor == a && channel == c
} }
this this
case LeaveAllChannels(actor) => case LeaveAllChannels(actor) =>
subscriptions = subscriptions.filter { subscriptions = subscriptions.filterNot {
case JoinChannel(a, _, _) => actor != a case JoinChannel(a, _, _) => actor == a
} }
this this
case Message(session, message, channel) => case Message(session, message, channel) =>
(channel, message.messageType) match { (channel, message.messageType) match {
case (ChatChannel.Squad(_), CMT_SQUAD) => case (ChatChannel.Squad(_), CMT_SQUAD) => ;
case (ChatChannel.Default(), messageType) if messageType != CMT_SQUAD => case (ChatChannel.Default(), messageType) if messageType != CMT_SQUAD => ;
case _ => case _ =>
log.error(s"invalid chat channel $channel for messageType ${message.messageType}") log.error(s"invalid chat channel $channel for messageType ${message.messageType}")
return this return this

View file

@ -553,7 +553,9 @@ class SquadService extends Actor {
case (Some(squad1), Some(squad2)) if squad2.Size == 1 => case (Some(squad1), Some(squad2)) if squad2.Size == 1 =>
//both players belong to squads, but the invitedPlayer's squad (squad2) is underutilized by comparison //both players belong to squads, but the invitedPlayer's squad (squad2) is underutilized by comparison
//treat the same as "the classic situation" using squad1 //treat the same as "the classic situation" using squad1
if (!Refused(invitedPlayer).contains(invitingPlayer)) { if (squad1.Size == squad1.Capacity) {
debug(s"$invitingPlayer tried to invite $invitedPlayer to a squad without available positions")
} else if (!Refused(invitedPlayer).contains(invitingPlayer)) {
val charId = tplayer.CharId val charId = tplayer.CharId
AddInviteAndRespond( AddInviteAndRespond(
invitedPlayer, invitedPlayer,
@ -561,16 +563,20 @@ class SquadService extends Actor {
charId, charId,
tplayer.Name tplayer.Name
) )
} else {
debug(s"$invitedPlayer repeated a previous refusal to $invitingPlayer's invitation offer")
} }
case (Some(squad1), Some(squad2)) if squad1.Size == 1 => case (Some(squad1), Some(squad2)) if squad1.Size == 1 =>
//both players belong to squads, but the invitingPlayer's squad is underutilized by comparison //both players belong to squads, but the invitingPlayer's squad is underutilized by comparison
//treat the same as "indirection ..." using squad2 //treat the same as "indirection ..." using squad2
val leader = squad2.Leader.CharId val leader = squad2.Leader.CharId
if (Refused(invitingPlayer).contains(invitedPlayer)) { if (squad2.Size == squad2.Capacity) {
debug(s"$invitedPlayer repeated a previous refusal to $invitingPlayer's invitation offer") debug(s"$invitingPlayer's invitation got reversed to $invitedPlayer's squad, but the squad has no available positions")
} else if (Refused(invitingPlayer).contains(invitedPlayer)) {
debug(s"$invitingPlayer's invitation got reversed to $invitedPlayer's squad, but $invitedPlayer repeated a previous refusal to $invitingPlayer's invitation offer")
} else if (Refused(invitingPlayer).contains(leader)) { } else if (Refused(invitingPlayer).contains(leader)) {
debug(s"$invitedPlayer repeated a previous refusal to $leader's invitation offer") debug(s"$invitingPlayer's invitation got reversed to $invitedPlayer's squad, but $leader repeated a previous refusal to $invitingPlayer's invitation offer")
} else { } else {
AddInviteAndRespond( AddInviteAndRespond(
leader, leader,
@ -582,7 +588,9 @@ class SquadService extends Actor {
case (Some(squad), None) => case (Some(squad), None) =>
//the classic situation //the classic situation
if (!Refused(invitedPlayer).contains(invitingPlayer)) { if (squad.Size == squad.Capacity) {
debug(s"$invitingPlayer tried to invite $invitedPlayer to a squad without available positions")
} else if (!Refused(invitedPlayer).contains(invitingPlayer)) {
AddInviteAndRespond( AddInviteAndRespond(
invitedPlayer, invitedPlayer,
VacancyInvite(tplayer.CharId, tplayer.Name, squad.GUID), VacancyInvite(tplayer.CharId, tplayer.Name, squad.GUID),
@ -596,10 +604,12 @@ class SquadService extends Actor {
case (None, Some(squad)) => case (None, Some(squad)) =>
//indirection; we're trying to invite ourselves to someone else's squad //indirection; we're trying to invite ourselves to someone else's squad
val leader = squad.Leader.CharId val leader = squad.Leader.CharId
if (Refused(invitingPlayer).contains(invitedPlayer)) { if (squad.Size == squad.Capacity) {
debug(s"$invitedPlayer repeated a previous refusal to $invitingPlayer's invitation offer") debug(s"$invitingPlayer tried to invite to $invitedPlayer's squad, but the squad has no available positions")
} else if (Refused(invitingPlayer).contains(invitedPlayer)) {
debug(s"invitingPlayer tried to invite to $invitedPlayer's squad, but $invitedPlayer repeated a previous refusal to $invitingPlayer's invitation offer")
} else if (Refused(invitingPlayer).contains(leader)) { } else if (Refused(invitingPlayer).contains(leader)) {
debug(s"$invitedPlayer repeated a previous refusal to $leader's invitation offer") debug(s"invitingPlayer tried to invite to $invitedPlayer's squad, but $leader repeated a previous refusal to $invitingPlayer's invitation offer")
} else { } else {
AddInviteAndRespond( AddInviteAndRespond(
squad.Leader.CharId, squad.Leader.CharId,
@ -658,62 +668,64 @@ class SquadService extends Actor {
//positions that can be recruited to //positions that can be recruited to
val positions = squad.Membership.zipWithIndex val positions = squad.Membership.zipWithIndex
.collect { case (member, index) if member.CharId == 0 && squad.Availability(index) => member } .collect { case (member, index) if member.CharId == 0 && squad.Availability(index) => member }
/* if (positions.nonEmpty) {
players who are: /*
- the same faction as the squad players who are:
- have Looking For Squad enabled - the same faction as the squad
- do not currently belong to a squad - have Looking For Squad enabled
- are denied the opportunity to be invited - do not currently belong to a squad
- are a certain distance from the squad leader (n < 25m) - are denied the opportunity to be invited
*/ - are a certain distance from the squad leader (n < 25m)
(zone.LivePlayers */
.collect { (zone.LivePlayers
case player .collect {
if player.Faction == faction && player.avatar.lookingForSquad && case player
(memberToSquad.get(player.CharId).isEmpty || memberToSquad(player.CharId).Size == 1) && if player.Faction == faction && player.avatar.lookingForSquad &&
!excusedInvites (memberToSquad.get(player.CharId).isEmpty || memberToSquad(player.CharId).Size == 1) &&
.contains(player.CharId) && Refused(player.CharId).contains(squad.Leader.CharId) && !excusedInvites
Vector3.DistanceSquared(player.Position, center) < 625f && { .contains(player.CharId) && Refused(player.CharId).contains(squad.Leader.CharId) &&
positions Vector3.DistanceSquared(player.Position, center) < 625f && {
.map { role => positions
val requirementsToMeet = role.Requirements .map { role =>
requirementsToMeet.intersect(player.avatar.certifications) == requirementsToMeet val requirementsToMeet = role.Requirements
} requirementsToMeet.intersect(player.avatar.certifications) == requirementsToMeet
.foldLeft(false)(_ || _) }
} => .foldLeft(false)(_ || _)
player.CharId } =>
player.CharId
}
.partition { charId => outstandingActiveInvites.contains(charId) } match {
case (Nil, Nil) =>
//no one found
outstandingActiveInvites foreach RemoveInvite
features.ProxyInvites = Nil
None
case (outstandingPlayerList, invitedPlayerList) =>
//players who were actively invited for the previous position and are eligible for the new position
features.SearchForRole = Some(-1)
outstandingPlayerList.foreach { charId =>
val bid = invites(charId).asInstanceOf[LookingForSquadRoleInvite]
invites(charId) = ProximityInvite(bid.char_id, bid.name, sguid)
}
//players who were actively invited for the previous position but are ineligible for the new position
(features.ProxyInvites filterNot (outstandingPlayerList contains)) foreach RemoveInvite
features.ProxyInvites = outstandingPlayerList ++ invitedPlayerList
Some(invitedPlayerList)
}) match {
//add invitations for position in squad
case Some(invitedPlayers) =>
val invitingPlayer = tplayer.CharId
val name = tplayer.Name
invitedPlayers.foreach { invitedPlayer =>
AddInviteAndRespond(
invitedPlayer,
ProximityInvite(invitingPlayer, name, sguid),
invitingPlayer,
name
)
}
case None => ;
} }
.partition { charId => outstandingActiveInvites.contains(charId) } match {
case (Nil, Nil) =>
//no one found
outstandingActiveInvites foreach RemoveInvite
features.ProxyInvites = Nil
None
case (outstandingPlayerList, invitedPlayerList) =>
//players who were actively invited for the previous position and are eligible for the new position
features.SearchForRole = Some(-1)
outstandingPlayerList.foreach { charId =>
val bid = invites(charId).asInstanceOf[LookingForSquadRoleInvite]
invites(charId) = ProximityInvite(bid.char_id, bid.name, sguid)
}
//players who were actively invited for the previous position but are ineligible for the new position
(features.ProxyInvites filterNot (outstandingPlayerList contains)) foreach RemoveInvite
features.ProxyInvites = outstandingPlayerList ++ invitedPlayerList
Some(invitedPlayerList)
}) match {
//add invitations for position in squad
case Some(invitedPlayers) =>
val invitingPlayer = tplayer.CharId
val name = tplayer.Name
invitedPlayers.foreach { invitedPlayer =>
AddInviteAndRespond(
invitedPlayer,
ProximityInvite(invitingPlayer, name, sguid),
invitingPlayer,
name
)
}
case None => ;
} }
} }
@ -2772,7 +2784,7 @@ class SquadService extends Actor {
* At this point in the squad join process, the only consent required is that of the squad leader. * At this point in the squad join process, the only consent required is that of the squad leader.
* An automatic consent flag exists on the squad; * An automatic consent flag exists on the squad;
* but, if that is not set, then the squad leader must be asked whether or not to accept or to reject the recruit. * but, if that is not set, then the squad leader must be asked whether or not to accept or to reject the recruit.
* If the squad leader changes in the middle of the latter half of the process, * If the squad leader changes in the middle or the latter half of the process,
* the invitation may still fail even if the old squad leader accepts. * the invitation may still fail even if the old squad leader accepts.
* If the squad leader changes in the middle of the latter half of the process, * If the squad leader changes in the middle of the latter half of the process,
* the inquiry might be posed again of the new squad leader, of whether to accept or to reject the recruit. * the inquiry might be posed again of the new squad leader, of whether to accept or to reject the recruit.
@ -2908,7 +2920,7 @@ class SquadService extends Actor {
.unzip { case (member, index) => (member.CharId, index) } .unzip { case (member, index) => (member.CharId, index) }
val toChannel = features.ToChannel val toChannel = features.ToChannel
memberCharIds.foreach { charId => memberCharIds.foreach { charId =>
SquadEvents.subscribe(events, s"/$toChannel/Squad") SquadEvents.subscribe(UserEvents(charId), s"/$toChannel/Squad")
Publish( Publish(
charId, charId,
SquadResponse.Join( SquadResponse.Join(
@ -2923,8 +2935,7 @@ class SquadService extends Actor {
InitSquadDetail(squad) InitSquadDetail(squad)
} else { } else {
//joining an active squad; everybody updates differently //joining an active squad; everybody updates differently
val updatedIndex = List(position) val toChannel = features.ToChannel
val toChannel = features.ToChannel
//new member gets full squad UI updates //new member gets full squad UI updates
Publish( Publish(
charId, charId,
@ -2938,7 +2949,7 @@ class SquadService extends Actor {
) )
) )
//other squad members see new member joining the squad //other squad members see new member joining the squad
Publish(toChannel, SquadResponse.Join(squad, updatedIndex, "")) Publish(toChannel, SquadResponse.Join(squad, List(position), ""))
InitWaypoints(charId, squad.GUID) InitWaypoints(charId, squad.GUID)
InitSquadDetail(squad.GUID, Seq(charId), squad) InitSquadDetail(squad.GUID, Seq(charId), squad)
UpdateSquadDetail( UpdateSquadDetail(