added enumeration for squad waypoints and changed field datatypes where appriopriate; added assertions to squad detail packet; removed old logic from squad request and squad response enumerations; WSA lfs -> lfsm

This commit is contained in:
FateJH 2019-10-20 15:34:01 -04:00
parent aa2e0089a4
commit 93f2264f61
12 changed files with 71 additions and 68 deletions

View file

@ -3,6 +3,7 @@ package net.psforever.objects.teamwork
import akka.actor.{Actor, ActorContext, ActorRef, Cancellable, Props}
import net.psforever.objects.DefaultCancellable
import net.psforever.types.SquadWaypoints
import services.teamwork.SquadService.WaypointData
import services.teamwork.SquadSwitchboard
@ -70,7 +71,7 @@ class SquadFeatures(val Squad : Squad) {
def Start(implicit context : ActorContext) : SquadFeatures = {
switchboard = context.actorOf(Props[SquadSwitchboard], s"squad${Squad.GUID.guid}")
waypoints = Array.fill[WaypointData](5)(new WaypointData())
waypoints = Array.fill[WaypointData](SquadWaypoints.values.size)(new WaypointData())
this
}

View file

@ -114,7 +114,10 @@ final case class SquadPositionDetail(is_closed : Option[Boolean],
* when 255, this indicated the end of enumerated squad position data and the data for that position is absent
* @param info the squad position field data
*/
final case class SquadPositionEntry(index : Int, info : Option[SquadPositionDetail])
final case class SquadPositionEntry(index : Int, info : Option[SquadPositionDetail]) {
assert((index > -1 && index < 10) || index == 255, "index value is out of range 0=>n<=9 or n=255")
assert(if(index == 255) { info.isEmpty } else { true }, "index=255 indicates end of stream exclusively and field data should be blank")
}
/**
* Information regarding a squad's position as a series of common fields.

View file

@ -1,8 +1,8 @@
// Copyright (c) 2017 PSForever
// Copyright (c) 2019 PSForever
package net.psforever.packet.game
import net.psforever.packet.{GamePacketOpcode, Marshallable, PlanetSideGamePacket}
import net.psforever.types.Vector3
import net.psforever.types.{SquadWaypoints, Vector3}
import scodec.{Attempt, Codec, Err}
import scodec.codecs._
import shapeless.{::, HNil}
@ -14,7 +14,7 @@ final case class WaypointEvent(zone_number : Int,
final case class SquadWaypointEvent(event_type : WaypointEventAction.Value,
unk : Int,
char_id : Long,
waypoint_type : Int,
waypoint_type : SquadWaypoints.Value,
unk5 : Option[Long],
waypoint_info : Option[WaypointEvent])
extends PlanetSideGamePacket {
@ -24,13 +24,13 @@ final case class SquadWaypointEvent(event_type : WaypointEventAction.Value,
}
object SquadWaypointEvent extends Marshallable[SquadWaypointEvent] {
def Add(unk : Int, char_id : Long, waypoint_type : Int, waypoint : WaypointEvent) : SquadWaypointEvent =
def Add(unk : Int, char_id : Long, waypoint_type : SquadWaypoints.Value, waypoint : WaypointEvent) : SquadWaypointEvent =
SquadWaypointEvent(WaypointEventAction.Add, unk, char_id, waypoint_type, None, Some(waypoint))
def Unknown1(unk : Int, char_id : Long, waypoint_type : Int, unk_a : Long) : SquadWaypointEvent =
def Unknown1(unk : Int, char_id : Long, waypoint_type : SquadWaypoints.Value, unk_a : Long) : SquadWaypointEvent =
SquadWaypointEvent(WaypointEventAction.Unknown1, unk, char_id, waypoint_type, Some(unk_a), None)
def Remove(unk : Int, char_id : Long, waypoint_type : Int) : SquadWaypointEvent =
def Remove(unk : Int, char_id : Long, waypoint_type : SquadWaypoints.Value) : SquadWaypointEvent =
SquadWaypointEvent(WaypointEventAction.Remove, unk, char_id, waypoint_type, None, None)
private val waypoint_codec : Codec[WaypointEvent] = (
@ -43,7 +43,7 @@ object SquadWaypointEvent extends Marshallable[SquadWaypointEvent] {
("event_type" | WaypointEventAction.codec) >>:~ { event_type =>
("unk" | uint16L) ::
("char_id" | uint32L) ::
("waypoint_type" | uint8L) ::
("waypoint_type" | SquadWaypoints.codec) ::
("unk5" | conditional(event_type == WaypointEventAction.Unknown1, uint32L)) ::
("waypoint_info" | conditional(event_type == WaypointEventAction.Add, waypoint_codec))
}

View file

@ -2,7 +2,7 @@
package net.psforever.packet.game
import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket}
import net.psforever.types.Vector3
import net.psforever.types.{SquadWaypoints, Vector3}
import scodec.{Attempt, Codec, Err}
import scodec.codecs._
import shapeless.{::, HNil}
@ -46,7 +46,7 @@ final case class WaypointInfo(zone_number : Int,
*/
final case class SquadWaypointRequest(request_type : WaypointEventAction.Value,
char_id : Long,
waypoint_type : Int,
waypoint_type : SquadWaypoints.Value,
unk4 : Option[Long],
waypoint_info : Option[WaypointInfo])
extends PlanetSideGamePacket {
@ -56,13 +56,13 @@ final case class SquadWaypointRequest(request_type : WaypointEventAction.Value,
}
object SquadWaypointRequest extends Marshallable[SquadWaypointRequest] {
def Add(char_id : Long, waypoint_type : Int, waypoint : WaypointInfo) : SquadWaypointRequest =
def Add(char_id : Long, waypoint_type : SquadWaypoints.Value, waypoint : WaypointInfo) : SquadWaypointRequest =
SquadWaypointRequest(WaypointEventAction.Add, char_id, waypoint_type, None, Some(waypoint))
def Unknown1(char_id : Long, waypoint_type : Int, unk_a : Long) : SquadWaypointRequest =
def Unknown1(char_id : Long, waypoint_type : SquadWaypoints.Value, unk_a : Long) : SquadWaypointRequest =
SquadWaypointRequest(WaypointEventAction.Unknown1, char_id, waypoint_type, Some(unk_a), None)
def Remove(char_id : Long, waypoint_type : Int) : SquadWaypointRequest =
def Remove(char_id : Long, waypoint_type : SquadWaypoints.Value) : SquadWaypointRequest =
SquadWaypointRequest(WaypointEventAction.Remove, char_id, waypoint_type, None, None)
private val waypoint_codec : Codec[WaypointInfo] = (
@ -80,7 +80,7 @@ object SquadWaypointRequest extends Marshallable[SquadWaypointRequest] {
implicit val codec : Codec[SquadWaypointRequest] = (
("request_type" | WaypointEventAction.codec) >>:~ { request_type =>
("char_id" | uint32L) ::
("waypoint_type" | uint8L) ::
("waypoint_type" | SquadWaypoints.codec) ::
("unk4" | conditional(request_type == WaypointEventAction.Unknown1, uint32L)) ::
("waypoint" | conditional(request_type == WaypointEventAction.Add, waypoint_codec))
}

View file

@ -24,11 +24,4 @@ object SquadRequestType extends Enumeration {
= Value
implicit val codec = PacketHelpers.createEnumerationCodec(this, uint4L)
def toResponse(request : SquadRequestType.Value) : SquadResponseType.Value = {
val id = request.id
if(id < 6) SquadResponseType(id)
else if(id > 6) SquadResponseType(id - 1)
else throw new NoSuchElementException("request does not have an applicable response")
}
}

View file

@ -23,11 +23,4 @@ object SquadResponseType extends Enumeration {
= Value
implicit val codec = PacketHelpers.createEnumerationCodec(this, uint4L)
def fromRequest(response : SquadResponseType.Value) : SquadRequestType.Value = {
val id = response.id
if(id < 6) SquadRequestType(id)
else if(id > 5) SquadRequestType(id + 1)
else throw new NoSuchElementException("response does not stem from an applicable request")
}
}

View file

@ -0,0 +1,18 @@
// Copyright (c) 2019 PSForever
package net.psforever.types
import net.psforever.packet.PacketHelpers
import scodec.codecs._
object SquadWaypoints extends Enumeration {
type Type = Value
val
One,
Two,
Three,
Four,
ExperienceRally
= Value
implicit val codec = PacketHelpers.createEnumerationCodec(this, uint8L)
}

View file

@ -3,7 +3,7 @@ package services.teamwork
import net.psforever.objects.zones.Zone
import net.psforever.packet.game._
import net.psforever.types.{PlanetSideEmpire, SquadRequestType, Vector3}
import net.psforever.types.{PlanetSideEmpire, SquadRequestType, SquadWaypoints, Vector3}
object SquadAction {
trait Action
@ -13,6 +13,6 @@ object SquadAction {
final case class Definition(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 Waypoint(event_type : WaypointEventAction.Value, waypoint_type : Int, unk : Option[Long], waypoint_info : Option[WaypointInfo]) extends Action
final case class Waypoint(event_type : WaypointEventAction.Value, waypoint_type : SquadWaypoints.Value, unk : Option[Long], waypoint_info : Option[WaypointInfo]) 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
}

View file

@ -3,7 +3,7 @@ package services.teamwork
import net.psforever.objects.teamwork.Squad
import net.psforever.packet.game._
import net.psforever.types.SquadResponseType
import net.psforever.types.{SquadResponseType, SquadWaypoints}
object SquadResponse {
trait Response
@ -27,8 +27,8 @@ object SquadResponse {
final case class Detail(guid : PlanetSideGUID, squad_detail : SquadDetail) extends Response
final case class InitWaypoints(char_id : Long, waypoints : Iterable[(Int, WaypointInfo, Int)]) extends Response
final case class WaypointEvent(event_type : WaypointEventAction.Value, char_id : Long, waypoint_type : Int, unk5 : Option[Long], waypoint_info : Option[WaypointInfo], unk : Int) extends Response
final case class InitWaypoints(char_id : Long, waypoints : Iterable[(SquadWaypoints.Value, WaypointInfo, Int)]) extends Response
final case class WaypointEvent(event_type : WaypointEventAction.Value, char_id : Long, waypoint_type : SquadWaypoints.Value, unk5 : Option[Long], waypoint_info : Option[WaypointInfo], unk : Int) extends Response
final case class SquadSearchResults() extends Response
}

View file

@ -2544,16 +2544,14 @@ class SquadService extends Actor {
* @see `SquadWaypointRequest`
* @see `WaypointInfo`
* @param guid the squad's unique identifier
* @param waypointType the type of the waypoint as an integer;
* 0-4 are squad waypoints;
* 5 is the squad leader's experience waypoint
* @param waypointType the type of the waypoint
* @param info information about the waypoint, as was reported by the client's packet
* @return the waypoint data, if the waypoint type is changed
*/
def AddWaypoint(guid : PlanetSideGUID, waypointType : Int, info : WaypointInfo) : Option[WaypointData] = {
def AddWaypoint(guid : PlanetSideGUID, waypointType : SquadWaypoints.Value, info : WaypointInfo) : Option[WaypointData] = {
squadFeatures.get(guid) match {
case Some(features) =>
features.Waypoints.lift(waypointType) match {
features.Waypoints.lift(waypointType.id) match {
case Some(point) =>
point.zone_number = info.zone_number
point.pos = info.pos
@ -2576,14 +2574,12 @@ class SquadService extends Actor {
* All of the waypoints constantly exist as long as the squad to which they are attached exists.
* They are merely "activated" and "deactivated."
* @param guid the squad's unique identifier
* @param waypointType the type of the waypoint as an integer;
* 0-4 are squad waypoints;
* 5 is the squad leader's experience waypoint
* @param waypointType the type of the waypoint
*/
def RemoveWaypoint(guid : PlanetSideGUID, waypointType : Int) : Unit = {
def RemoveWaypoint(guid : PlanetSideGUID, waypointType : SquadWaypoints.Value) : Unit = {
squadFeatures.get(guid) match {
case Some(features) =>
features.Waypoints.lift(waypointType) match {
features.Waypoints.lift(waypointType.id) match {
case Some(point) =>
point.pos = Vector3.z(1)
case _ =>
@ -2608,7 +2604,7 @@ class SquadService extends Actor {
Publish(
toCharId, SquadResponse.InitWaypoints(squad.Leader.CharId,
list.zipWithIndex.collect { case (point, index) if point.pos != vz1 =>
(index, WaypointInfo(point.zone_number, point.pos), 1)
(SquadWaypoints(index), WaypointInfo(point.zone_number, point.pos), 1)
}
)
)

View file

@ -3,8 +3,8 @@ package game
import org.specs2.mutable._
import net.psforever.packet._
import net.psforever.packet.game.{SquadWaypointEvent, WaypointEventAction, WaypointEvent}
import net.psforever.types.Vector3
import net.psforever.packet.game.{SquadWaypointEvent, WaypointEvent, WaypointEventAction}
import net.psforever.types.{SquadWaypoints, Vector3}
import scodec.bits._
class SquadWaypointEventTest extends Specification {
@ -19,7 +19,7 @@ class SquadWaypointEventTest extends Specification {
unk1 mustEqual WaypointEventAction.Remove
unk2 mustEqual 11
unk3 mustEqual 31155863L
unk4 mustEqual 0
unk4 mustEqual SquadWaypoints.One
unk5.isEmpty mustEqual true
unk6.isEmpty mustEqual true
case _ =>
@ -33,7 +33,7 @@ class SquadWaypointEventTest extends Specification {
unk1 mustEqual WaypointEventAction.Remove
unk2 mustEqual 10
unk3 mustEqual 0L
unk4 mustEqual 4
unk4 mustEqual SquadWaypoints.ExperienceRally
unk5.isEmpty mustEqual true
unk6.isEmpty mustEqual true
case _ =>
@ -47,7 +47,7 @@ class SquadWaypointEventTest extends Specification {
unk1 mustEqual WaypointEventAction.Add
unk2 mustEqual 3
unk3 mustEqual 41581052L
unk4 mustEqual 1
unk4 mustEqual SquadWaypoints.Two
unk5.isEmpty mustEqual true
unk6.contains( WaypointEvent(10, Vector3(3457.9688f, 5514.4688f, 0.0f), 1) ) mustEqual true
case _ =>
@ -61,7 +61,7 @@ class SquadWaypointEventTest extends Specification {
unk1 mustEqual WaypointEventAction.Unknown1
unk2 mustEqual 3
unk3 mustEqual 41581052L
unk4 mustEqual 1
unk4 mustEqual SquadWaypoints.Two
unk5.contains( 4L ) mustEqual true
unk6.isEmpty mustEqual true
case _ =>
@ -70,28 +70,28 @@ class SquadWaypointEventTest extends Specification {
}
"encode (1)" in {
val msg = SquadWaypointEvent.Remove(11, 31155863L, 0)
val msg = SquadWaypointEvent.Remove(11, 31155863L, SquadWaypoints.One)
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_1
}
"encode (2)" in {
val msg = SquadWaypointEvent.Remove(10, 0L, 4)
val msg = SquadWaypointEvent.Remove(10, 0L, SquadWaypoints.ExperienceRally)
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_2
}
"encode (3)" in {
val msg = SquadWaypointEvent.Add(3, 41581052L, 1, WaypointEvent(10, Vector3(3457.9688f, 5514.4688f, 0.0f), 1))
val msg = SquadWaypointEvent.Add(3, 41581052L, SquadWaypoints.Two, WaypointEvent(10, Vector3(3457.9688f, 5514.4688f, 0.0f), 1))
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_3
}
"encode (4)" in {
val msg = SquadWaypointEvent.Unknown1(3, 41581052L, 1, 4L)
val msg = SquadWaypointEvent.Unknown1(3, 41581052L, SquadWaypoints.Two, 4L)
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string_4

View file

@ -121,14 +121,14 @@ class WorldSessionActor extends Actor with MDCContextAware {
val squadUI : LongMap[SquadUIElement] = new LongMap[SquadUIElement]()
var squad_supplement_id : Int = 0
/**
* `AvatarConverter` can only rely on the `Avatar`-local Looking For Squad variable.
* When joining or creating a squad, the original state of the avatar's local LFS variable is blanked.
* When joining or creating a squad, the original state of the avatar's internal LFS variable is blanked.
* This `WSA`-local variable is then used to indicate the ongoing state of the LFS UI component,
* now called "Looking for Squad Member."
* Only the squad leader may toggle the LFSM marquee.
* Upon leaving or disbanding a squad, this value is made false.
* Control switching between the `Avatar`-local and the `WSA`-local variable is contingent on `squadUI` being populated.
* Control switching between the `Avatar`-local and the `WorldSessionActor`-local variable is contingent on `squadUI` being populated.
*/
var lfs : Boolean = false
var lfsm : Boolean = false
var squadChannel : Option[String] = None
var squadSetup : () => Unit = FirstTimeSquadSetup
var squadUpdateCounter : Int = 0
@ -492,7 +492,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
avatarService ! AvatarServiceMessage(s"${continent.Id}/${player.Faction}", AvatarAction.PlanetsideAttribute(playerGuid, 31, 0))
sendResponse(PlanetsideAttributeMessage(playerGuid, 32, 0)) //disassociate with member position in squad?
sendResponse(PlanetsideAttributeMessage(playerGuid, 34, 4294967295L)) //unknown, perhaps unrelated?
lfs = false
lfsm = false
//a finalization? what does this do?
sendResponse(SquadDefinitionActionMessage(PlanetSideGUID(0), 0, SquadAction.Unknown(18)))
squad_supplement_id = 0
@ -523,11 +523,11 @@ class WorldSessionActor extends Actor with MDCContextAware {
//are we being demoted?
if(squadUI(charId).index == 0) {
//lfsm -> lfs
if(lfs) {
if(lfsm) {
sendResponse(PlanetsideAttributeMessage(guid, 53, 0))
avatarService ! AvatarServiceMessage(factionOnContinentChannel, AvatarAction.PlanetsideAttribute(guid, 53, 0))
}
lfs = false
lfsm = false
sendResponse(PlanetsideAttributeMessage(guid, 32, from_index)) //associate with member position in squad
}
//are we being promoted?
@ -3055,7 +3055,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
deadState = DeadState.Alive
sendResponse(AvatarDeadStateMessage(DeadState.Alive, 0, 0, tplayer.Position, player.Faction, true))
//looking for squad (members)
if(tplayer.LFS || lfs) {
if(tplayer.LFS || lfsm) {
sendResponse(PlanetsideAttributeMessage(guid, 53, 1))
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(guid, 53, 1))
}
@ -3692,7 +3692,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.VehicleState(player.GUID, vehicle_guid, unk1, pos, ang, vel, flight, unk6, unk7, wheels, unk9, unkA))
}
//vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.VehicleState(player.GUID, vehicle_guid, unk1, pos, ang, vel, flight, unk6, unk7, wheels, unk9, unkA))
updateSquad()
case (None, _) =>
//log.error(s"VehicleState: no vehicle $vehicle_guid found in zone")
@ -4797,8 +4796,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
else if(action == 36) { //Looking For Squad ON
if(squadUI.nonEmpty) {
if(!lfs && squadUI(player.CharId).index == 0) {
lfs = true
if(!lfsm && squadUI(player.CharId).index == 0) {
lfsm = true
avatarService ! AvatarServiceMessage(s"${continent.Id}/${player.Faction}", AvatarAction.PlanetsideAttribute(player.GUID, 53, 1))
}
}
@ -4809,8 +4808,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
else if(action == 37) { //Looking For Squad OFF
if(squadUI.nonEmpty) {
if(lfs && squadUI(player.CharId).index == 0) {
lfs = false
if(lfsm && squadUI(player.CharId).index == 0) {
lfsm = false
avatarService ! AvatarServiceMessage(s"${continent.Id}/${player.Faction}", AvatarAction.PlanetsideAttribute(player.GUID, 53, 0))
}
}