mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-07-14 16:04:43 +00:00
allowed bundling of event message envelopes to streamline event system communication
This commit is contained in:
parent
f1b0d2e920
commit
f3fedaf55d
15 changed files with 256 additions and 145 deletions
|
|
@ -11,7 +11,7 @@ import net.psforever.objects.zones.Zone
|
||||||
import net.psforever.packet.PlanetSideGamePacket
|
import net.psforever.packet.PlanetSideGamePacket
|
||||||
import net.psforever.packet.game.ContinentalLockUpdateMessage
|
import net.psforever.packet.game.ContinentalLockUpdateMessage
|
||||||
import net.psforever.persistence
|
import net.psforever.persistence
|
||||||
import net.psforever.services.base.envelope.MessageEnvelope
|
import net.psforever.services.base.envelope.{BundledEnvelope, MessageEnvelope}
|
||||||
import net.psforever.services.base.message.{SendResponse, SetEmpire}
|
import net.psforever.services.base.message.{SendResponse, SetEmpire}
|
||||||
import net.psforever.services.galaxy.GalaxyAction
|
import net.psforever.services.galaxy.GalaxyAction
|
||||||
import net.psforever.services.{InterstellarClusterService, ServiceManager}
|
import net.psforever.services.{InterstellarClusterService, ServiceManager}
|
||||||
|
|
@ -232,8 +232,10 @@ class BuildingActor(
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
|
|
||||||
case MapUpdate() =>
|
case MapUpdate() =>
|
||||||
details.galaxyService ! MessageEnvelope("", GalaxyAction.MapUpdate(details.building.infoUpdateMessage()))
|
details.galaxyService ! BundledEnvelope(
|
||||||
details.galaxyService ! MessageEnvelope("", SendResponse(details.building.densityLevelUpdateMessage(building)))
|
MessageEnvelope("", GalaxyAction.MapUpdate(details.building.infoUpdateMessage())),
|
||||||
|
MessageEnvelope("", SendResponse(details.building.densityLevelUpdateMessage(building)))
|
||||||
|
)
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
|
|
||||||
case AmenityStateChange(amenity, data) =>
|
case AmenityStateChange(amenity, data) =>
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import net.psforever.objects.serverobject.terminals.capture.{CaptureTerminal, Ca
|
||||||
import net.psforever.objects.sourcing.PlayerSource
|
import net.psforever.objects.sourcing.PlayerSource
|
||||||
import net.psforever.packet.game.{GenericObjectActionMessage, PlanetsideAttributeMessage}
|
import net.psforever.packet.game.{GenericObjectActionMessage, PlanetsideAttributeMessage}
|
||||||
import net.psforever.services.InterstellarClusterService
|
import net.psforever.services.InterstellarClusterService
|
||||||
import net.psforever.services.base.envelope.MessageEnvelope
|
import net.psforever.services.base.envelope.{BundledEnvelope, MessageEnvelope}
|
||||||
import net.psforever.services.base.message.{GenericObjectAction, PlanetsideAttribute, SendResponse}
|
import net.psforever.services.base.message.{GenericObjectAction, PlanetsideAttribute, SendResponse}
|
||||||
import net.psforever.services.galaxy.GalaxyAction
|
import net.psforever.services.galaxy.GalaxyAction
|
||||||
import net.psforever.services.local.support.{CaptureEnvelope, HackCaptureActor, HackClearActor, HackClearEnvelope}
|
import net.psforever.services.local.support.{CaptureEnvelope, HackCaptureActor, HackClearActor, HackClearEnvelope}
|
||||||
|
|
@ -204,25 +204,19 @@ case object MajorFacilityLogic
|
||||||
val events = zone.AvatarEvents
|
val events = zone.AvatarEvents
|
||||||
val guid = building.GUID
|
val guid = building.GUID
|
||||||
val msg = GenericObjectAction(guid, 15)
|
val msg = GenericObjectAction(guid, 15)
|
||||||
building.PlayersInSOI.foreach { player =>
|
events ! BundledEnvelope(building.PlayersInSOI.map { player => MessageEnvelope(player.Name, msg) })
|
||||||
events ! MessageEnvelope(player.Name, msg)
|
|
||||||
}
|
|
||||||
false
|
false
|
||||||
case Some(GeneratorControl.Event.Critical) =>
|
case Some(GeneratorControl.Event.Critical) =>
|
||||||
val events = zone.AvatarEvents
|
val events = zone.AvatarEvents
|
||||||
val guid = building.GUID
|
val guid = building.GUID
|
||||||
val msg = PlanetsideAttribute(guid, 46, 1)
|
val msg = PlanetsideAttribute(guid, 46, 1)
|
||||||
building.PlayersInSOI.foreach { player =>
|
events ! BundledEnvelope(building.PlayersInSOI.map { player => MessageEnvelope(player.Name, msg) })
|
||||||
events ! MessageEnvelope(player.Name, msg)
|
|
||||||
}
|
|
||||||
true
|
true
|
||||||
case Some(GeneratorControl.Event.Destabilized) =>
|
case Some(GeneratorControl.Event.Destabilized) =>
|
||||||
val events = zone.AvatarEvents
|
val events = zone.AvatarEvents
|
||||||
val guid = building.GUID
|
val guid = building.GUID
|
||||||
val msg = GenericObjectAction(guid, 16)
|
val msg = GenericObjectAction(guid, 16)
|
||||||
building.PlayersInSOI.foreach { player =>
|
events ! BundledEnvelope(building.PlayersInSOI.map { player => MessageEnvelope(player.Name, msg) })
|
||||||
events ! MessageEnvelope(player.Name, msg)
|
|
||||||
}
|
|
||||||
if (building.hasCavernLockBenefit) {
|
if (building.hasCavernLockBenefit) {
|
||||||
zone.LocalEvents ! MessageEnvelope(
|
zone.LocalEvents ! MessageEnvelope(
|
||||||
zone.id,
|
zone.id,
|
||||||
|
|
@ -235,10 +229,9 @@ case object MajorFacilityLogic
|
||||||
case Some(GeneratorControl.Event.Offline) =>
|
case Some(GeneratorControl.Event.Offline) =>
|
||||||
powerLost(details)
|
powerLost(details)
|
||||||
val zone = building.Zone
|
val zone = building.Zone
|
||||||
|
val events = zone.AvatarEvents
|
||||||
val msg = PlanetsideAttribute(building.GUID, 46, 2)
|
val msg = PlanetsideAttribute(building.GUID, 46, 2)
|
||||||
building.PlayersInSOI.foreach { player =>
|
events ! BundledEnvelope(building.PlayersInSOI.map { player => MessageEnvelope(player.Name, msg) }) //???
|
||||||
zone.AvatarEvents ! MessageEnvelope(player.Name, msg)
|
|
||||||
} //???
|
|
||||||
true
|
true
|
||||||
case Some(GeneratorControl.Event.Normal) =>
|
case Some(GeneratorControl.Event.Normal) =>
|
||||||
true
|
true
|
||||||
|
|
@ -253,9 +246,7 @@ case object MajorFacilityLogic
|
||||||
PlanetsideAttributeMessage(guid, 46, 0),
|
PlanetsideAttributeMessage(guid, 46, 0),
|
||||||
GenericObjectActionMessage(guid, 17)
|
GenericObjectActionMessage(guid, 17)
|
||||||
))
|
))
|
||||||
building.PlayersInSOI.foreach { player =>
|
events ! BundledEnvelope(building.PlayersInSOI.map { player => MessageEnvelope(player.Name, list) })
|
||||||
events ! MessageEnvelope(player.Name, list)
|
|
||||||
}
|
|
||||||
true
|
true
|
||||||
case _ =>
|
case _ =>
|
||||||
false
|
false
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import akka.actor.typed.scaladsl.Behaviors
|
||||||
import net.psforever.actors.commands.NtuCommand
|
import net.psforever.actors.commands.NtuCommand
|
||||||
import net.psforever.actors.zone.BuildingActor
|
import net.psforever.actors.zone.BuildingActor
|
||||||
import net.psforever.objects.serverobject.structures.{Amenity, Building, WarpGate}
|
import net.psforever.objects.serverobject.structures.{Amenity, Building, WarpGate}
|
||||||
import net.psforever.services.base.envelope.MessageEnvelope
|
import net.psforever.services.base.envelope.{BundledEnvelope, MessageEnvelope}
|
||||||
import net.psforever.services.galaxy.GalaxyAction
|
import net.psforever.services.galaxy.GalaxyAction
|
||||||
import net.psforever.types.PlanetSideEmpire
|
import net.psforever.types.PlanetSideEmpire
|
||||||
import net.psforever.util.Config
|
import net.psforever.util.Config
|
||||||
|
|
@ -209,9 +209,7 @@ case object WarpGateLogic
|
||||||
warpgate.Zone.Number, warpgate.MapId, previousAllowances, setBroadcastTo
|
warpgate.Zone.Number, warpgate.MapId, previousAllowances, setBroadcastTo
|
||||||
)
|
)
|
||||||
warpgate.AllowBroadcastFor = setBroadcastTo
|
warpgate.AllowBroadcastFor = setBroadcastTo
|
||||||
(setBroadcastTo ++ previousAllowances).foreach { faction =>
|
events ! BundledEnvelope((setBroadcastTo ++ previousAllowances).map { faction => MessageEnvelope(faction.toString, msg) })
|
||||||
events ! MessageEnvelope(faction.toString, msg)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -107,10 +107,7 @@ class BoomerDeployableControl(mine: BoomerDeployable)
|
||||||
zone.Ground ! Zone.Ground.RemoveItem(guid)
|
zone.Ground ! Zone.Ground.RemoveItem(guid)
|
||||||
case _ => ()
|
case _ => ()
|
||||||
}
|
}
|
||||||
zone.AvatarEvents! MessageEnvelope(
|
zone.AvatarEvents! MessageEnvelope(zone.id, ObjectDelete(guid))
|
||||||
zone.id,
|
|
||||||
ObjectDelete(guid)
|
|
||||||
)
|
|
||||||
TaskWorkflow.execute(GUIDTask.unregisterObject(zone.GUID, trigger))
|
TaskWorkflow.execute(GUIDTask.unregisterObject(zone.GUID, trigger))
|
||||||
case None => ()
|
case None => ()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,12 @@ import net.psforever.objects.zones.Zone
|
||||||
import net.psforever.packet.game._
|
import net.psforever.packet.game._
|
||||||
import net.psforever.types.{ChatMessageType, ExoSuitType, PlanetSideGUID, Vector3}
|
import net.psforever.types.{ChatMessageType, ExoSuitType, PlanetSideGUID, Vector3}
|
||||||
import net.psforever.services.avatar.AvatarAction
|
import net.psforever.services.avatar.AvatarAction
|
||||||
import net.psforever.services.base.envelope.MessageEnvelope
|
import net.psforever.services.base.envelope.{BundledEnvelope, MessageEnvelope}
|
||||||
import net.psforever.services.base.message.{ObjectDelete, SendResponse}
|
import net.psforever.services.base.message.{ObjectDelete, SendResponse}
|
||||||
import net.psforever.services.local.LocalAction
|
import net.psforever.services.local.LocalAction
|
||||||
|
|
||||||
import scala.annotation.tailrec
|
import scala.annotation.tailrec
|
||||||
|
import scala.collection.mutable.ArrayBuffer
|
||||||
|
|
||||||
object Players {
|
object Players {
|
||||||
private val log = org.log4s.getLogger("Players")
|
private val log = org.log4s.getLogger("Players")
|
||||||
|
|
@ -49,10 +50,7 @@ object Players {
|
||||||
) {
|
) {
|
||||||
val events = target.Zone.AvatarEvents
|
val events = target.Zone.AvatarEvents
|
||||||
val uname = user.Name
|
val uname = user.Name
|
||||||
events ! MessageEnvelope(
|
events ! MessageEnvelope(uname, SendResponse(RepairMessage(target.GUID, progress.toInt)))
|
||||||
uname,
|
|
||||||
SendResponse(RepairMessage(target.GUID, progress.toInt))
|
|
||||||
)
|
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
|
@ -439,24 +437,20 @@ object Players {
|
||||||
if ((player.Slot(index).Equipment = obj).contains(obj)) {
|
if ((player.Slot(index).Equipment = obj).contains(obj)) {
|
||||||
val fireMode = tool.FireModeIndex
|
val fireMode = tool.FireModeIndex
|
||||||
val ammoType = tool.AmmoTypeIndex
|
val ammoType = tool.AmmoTypeIndex
|
||||||
|
val list: ArrayBuffer[MessageEnvelope] = ArrayBuffer()
|
||||||
player.Inventory -= x.start
|
player.Inventory -= x.start
|
||||||
obj.FireModeIndex = fireMode
|
obj.FireModeIndex = fireMode
|
||||||
//TODO any penalty for being handed an OCM version of the tool?
|
//TODO any penalty for being handed an OCM version of the tool?
|
||||||
events ! MessageEnvelope(
|
list.append(MessageEnvelope(zone.id, AvatarAction.EquipmentInHand(pguid, index, obj)))
|
||||||
zone.id,
|
|
||||||
AvatarAction.EquipmentInHand(pguid, index, obj)
|
|
||||||
)
|
|
||||||
if (obj.AmmoTypeIndex != ammoType) {
|
if (obj.AmmoTypeIndex != ammoType) {
|
||||||
obj.AmmoTypeIndex = ammoType
|
obj.AmmoTypeIndex = ammoType
|
||||||
events ! MessageEnvelope(
|
list.append(MessageEnvelope(name, SendResponse(ChangeAmmoMessage(obj.GUID, ammoType))))
|
||||||
name,
|
|
||||||
SendResponse(ChangeAmmoMessage(obj.GUID, ammoType))
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if (player.DrawnSlot == Player.HandsDownSlot) {
|
if (player.DrawnSlot == Player.HandsDownSlot) {
|
||||||
player.DrawnSlot = index
|
player.DrawnSlot = index
|
||||||
events ! MessageEnvelope(zone.id, pguid, AvatarAction.ObjectHeld(index, index))
|
list.append(MessageEnvelope(zone.id, pguid, AvatarAction.ObjectHeld(index, index)))
|
||||||
}
|
}
|
||||||
|
events ! BundledEnvelope(list)
|
||||||
}
|
}
|
||||||
case Nil => ; //no replacements found
|
case Nil => ; //no replacements found
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,13 @@ import net.psforever.objects.vehicles._
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.Zone
|
||||||
import net.psforever.packet.game.{ChatMsg, FrameVehicleStateMessage, GenericObjectActionEnum, HackMessage, HackState, HackState1, HackState7, TriggeredSound, VehicleStateMessage}
|
import net.psforever.packet.game.{ChatMsg, FrameVehicleStateMessage, GenericObjectActionEnum, HackMessage, HackState, HackState1, HackState7, TriggeredSound, VehicleStateMessage}
|
||||||
import net.psforever.types.{ChatMessageType, DriveState, PlanetSideEmpire, PlanetSideGUID, Vector3}
|
import net.psforever.types.{ChatMessageType, DriveState, PlanetSideEmpire, PlanetSideGUID, Vector3}
|
||||||
import net.psforever.services.base.envelope.MessageEnvelope
|
import net.psforever.services.base.envelope.{BundledEnvelope, MessageEnvelope}
|
||||||
import net.psforever.services.base.message.{GenericObjectAction, PlanetsideAttribute, SendResponse, SetEmpire}
|
import net.psforever.services.base.message.{GenericObjectAction, PlanetsideAttribute, SendResponse, SetEmpire}
|
||||||
import net.psforever.services.local.LocalAction
|
import net.psforever.services.local.LocalAction
|
||||||
import net.psforever.services.vehicle.VehicleAction
|
import net.psforever.services.vehicle.VehicleAction
|
||||||
|
|
||||||
|
import scala.collection.mutable.ArrayBuffer
|
||||||
|
|
||||||
//import scala.concurrent.duration._
|
//import scala.concurrent.duration._
|
||||||
|
|
||||||
object Vehicles {
|
object Vehicles {
|
||||||
|
|
@ -248,13 +250,15 @@ object Vehicles {
|
||||||
val hFaction = hacker.Faction
|
val hFaction = hacker.Faction
|
||||||
val zone = target.Zone
|
val zone = target.Zone
|
||||||
val zoneid = zone.id
|
val zoneid = zone.id
|
||||||
|
val avatarEvents = zone.AvatarEvents
|
||||||
val vehicleEvents = zone.VehicleEvents
|
val vehicleEvents = zone.VehicleEvents
|
||||||
val localEvents = zone.LocalEvents
|
|
||||||
val previousOwnerName = target.OwnerName.getOrElse("")
|
val previousOwnerName = target.OwnerName.getOrElse("")
|
||||||
vehicleEvents ! MessageEnvelope(
|
val occupantMessages: ArrayBuffer[MessageEnvelope] = ArrayBuffer()
|
||||||
|
val vehicleMessages: ArrayBuffer[MessageEnvelope] = ArrayBuffer()
|
||||||
|
vehicleMessages.append(MessageEnvelope(
|
||||||
zoneid,
|
zoneid,
|
||||||
SendResponse(HackMessage(HackState1.Unk2, tGuid, hGuid, 100, 0f, HackState.Hacked, HackState7.Unk8))
|
SendResponse(HackMessage(HackState1.Unk2, tGuid, hGuid, 100, 0f, HackState.Hacked, HackState7.Unk8))
|
||||||
)
|
))
|
||||||
target.Actor ! CommonMessages.Hack(hacker, target)
|
target.Actor ! CommonMessages.Hack(hacker, target)
|
||||||
// Forcefully dismount any cargo
|
// Forcefully dismount any cargo
|
||||||
target.CargoHolds.foreach { case (_, cargoHold) =>
|
target.CargoHolds.foreach { case (_, cargoHold) =>
|
||||||
|
|
@ -268,26 +272,29 @@ object Vehicles {
|
||||||
player: Player =>
|
player: Player =>
|
||||||
seat.unmount(player)
|
seat.unmount(player)
|
||||||
player.VehicleSeated = None
|
player.VehicleSeated = None
|
||||||
vehicleEvents ! MessageEnvelope(
|
occupantMessages.append(MessageEnvelope(
|
||||||
zoneid,
|
zoneid,
|
||||||
player.GUID,
|
player.GUID,
|
||||||
VehicleAction.KickPassenger(4, unk2 = false, tGuid)
|
VehicleAction.KickPassenger(4, unk2 = false, tGuid)
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
// In case BFR is occupied and may or may not be crouched
|
// In case BFR is occupied and may or may not be crouched
|
||||||
if (GlobalDefinitions.isBattleFrameVehicle(target.Definition) && target.Seat(0).isDefined) {
|
if (GlobalDefinitions.isBattleFrameVehicle(target.Definition) && target.Seat(0).isDefined) {
|
||||||
zone.LocalEvents ! MessageEnvelope(
|
vehicleMessages.appendAll(List(
|
||||||
zoneid,
|
MessageEnvelope(zoneid,
|
||||||
GenericObjectAction(target.GUID, GenericObjectActionEnum.BFRShieldsDown.id)
|
GenericObjectAction(target.GUID, GenericObjectActionEnum.BFRShieldsDown.id)
|
||||||
)
|
),
|
||||||
zone.LocalEvents ! MessageEnvelope(
|
MessageEnvelope(zoneid,
|
||||||
zoneid,
|
SendResponse(
|
||||||
SendResponse(
|
FrameVehicleStateMessage(target.GUID, 0, target.Position, target.Orientation, Some(Vector3(0f, 0f, 0f)), unk2=false, 0, 0, is_crouched=true, is_airborne=false, ascending_flight=false, 10, 0, 0)
|
||||||
FrameVehicleStateMessage(target.GUID, 0, target.Position, target.Orientation, Some(Vector3(0f, 0f, 0f)), unk2=false, 0, 0, is_crouched=true, is_airborne=false, ascending_flight=false, 10, 0, 0)))
|
)
|
||||||
zone.LocalEvents ! MessageEnvelope(
|
),
|
||||||
zoneid,
|
MessageEnvelope(zoneid,
|
||||||
SendResponse(
|
SendResponse(
|
||||||
VehicleStateMessage(target.GUID, 0, target.Position, target.Orientation, Some(Vector3(0f, 0f, 0f)), None, 0, 0, 15, is_decelerating=false, is_cloaked=false)))
|
VehicleStateMessage(target.GUID, 0, target.Position, target.Orientation, Some(Vector3(0f, 0f, 0f)), None, 0, 0, 15, is_decelerating=false, is_cloaked=false)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// If the vehicle can fly and is flying: deconstruct it; and well played to whomever managed to hack a plane in mid air
|
// If the vehicle can fly and is flying: deconstruct it; and well played to whomever managed to hack a plane in mid air
|
||||||
|
|
@ -312,26 +319,17 @@ object Vehicles {
|
||||||
Vehicles.Own(target, hacker)
|
Vehicles.Own(target, hacker)
|
||||||
//todo: Send HackMessage -> HackCleared to vehicle? can be found in packet captures. Not sure if necessary.
|
//todo: Send HackMessage -> HackCleared to vehicle? can be found in packet captures. Not sure if necessary.
|
||||||
// And broadcast the faction change to other clients
|
// And broadcast the faction change to other clients
|
||||||
zone.AvatarEvents ! MessageEnvelope(
|
vehicleMessages.append(MessageEnvelope(zoneid, SetEmpire(tGuid, hFaction)))
|
||||||
zoneid,
|
|
||||||
SetEmpire(tGuid, hFaction)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
localEvents ! MessageEnvelope(
|
vehicleMessages.append(MessageEnvelope(
|
||||||
zoneid,
|
zoneid,
|
||||||
hGuid,
|
hGuid,
|
||||||
LocalAction.TriggerSound(TriggeredSound.HackVehicle, target.Position, 30, 0.49803925f)
|
LocalAction.TriggerSound(TriggeredSound.HackVehicle, target.Position, 30, 0.49803925f)
|
||||||
)
|
))
|
||||||
if (zone.Players.exists(_.name.equals(previousOwnerName))) {
|
if (zone.Players.exists(_.name.equals(previousOwnerName))) {
|
||||||
localEvents ! MessageEnvelope(
|
vehicleMessages.append(MessageEnvelope(previousOwnerName, SendResponse(ChatMsg(ChatMessageType.UNK_226, "@JackStolen"))))
|
||||||
previousOwnerName,
|
|
||||||
SendResponse(ChatMsg(ChatMessageType.UNK_226, "@JackStolen"))
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
localEvents ! MessageEnvelope(
|
occupantMessages.append(MessageEnvelope(hacker.Name, SendResponse(ChatMsg(ChatMessageType.UNK_226, "@JackVehicleOwned"))))
|
||||||
hacker.Name,
|
|
||||||
SendResponse(ChatMsg(ChatMessageType.UNK_226, "@JackVehicleOwned"))
|
|
||||||
)
|
|
||||||
// Clean up after specific vehicles, e.g. remove router telepads
|
// Clean up after specific vehicles, e.g. remove router telepads
|
||||||
// If AMS is deployed, swap it to the new faction
|
// If AMS is deployed, swap it to the new faction
|
||||||
target.Definition match {
|
target.Definition match {
|
||||||
|
|
@ -343,13 +341,15 @@ object Vehicles {
|
||||||
util.Actor ! TelepadLike.Activate(util)
|
util.Actor ! TelepadLike.Activate(util)
|
||||||
}
|
}
|
||||||
case GlobalDefinitions.ams if target.DeploymentState == DriveState.Deployed =>
|
case GlobalDefinitions.ams if target.DeploymentState == DriveState.Deployed =>
|
||||||
vehicleEvents ! MessageEnvelope(zone.id, VehicleAction.AMSDeploymentChange(zone))
|
vehicleMessages.append(MessageEnvelope(zone.id, VehicleAction.AMSDeploymentChange(zone)))
|
||||||
case _ => ()
|
case _ => ()
|
||||||
}
|
}
|
||||||
vehicleEvents ! MessageEnvelope(
|
vehicleMessages.append(MessageEnvelope(
|
||||||
zoneid,
|
zoneid,
|
||||||
SendResponse(HackMessage(HackState1.Unk2, tGuid, tGuid, 0, 1L, HackState.HackCleared, HackState7.Unk8))
|
SendResponse(HackMessage(HackState1.Unk2, tGuid, tGuid, 0, 1L, HackState.HackCleared, HackState7.Unk8))
|
||||||
)
|
))
|
||||||
|
avatarEvents ! BundledEnvelope(occupantMessages)
|
||||||
|
vehicleEvents ! BundledEnvelope(vehicleMessages)
|
||||||
target.Actor ! CommonMessages.ClearHack()
|
target.Actor ! CommonMessages.ClearHack()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import net.psforever.objects.guid.{GUIDTask, TaskWorkflow}
|
||||||
import net.psforever.objects._
|
import net.psforever.objects._
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.Zone
|
||||||
import net.psforever.packet.game._
|
import net.psforever.packet.game._
|
||||||
import net.psforever.services.base.envelope.MessageEnvelope
|
import net.psforever.services.base.envelope.{BundledEnvelope, MessageEnvelope}
|
||||||
import net.psforever.services.base.message.SetEmpire
|
import net.psforever.services.base.message.SetEmpire
|
||||||
import net.psforever.services.local.LocalAction
|
import net.psforever.services.local.LocalAction
|
||||||
import net.psforever.types.PlanetSideEmpire
|
import net.psforever.types.PlanetSideEmpire
|
||||||
|
|
@ -198,11 +198,14 @@ trait DeployableBehavior {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
//zone build
|
//zone build
|
||||||
localEvents ! MessageEnvelope(zone.id, LocalAction.DeployItem(obj))
|
localEvents ! BundledEnvelope(
|
||||||
//zone map icon
|
/* zone build */
|
||||||
localEvents ! MessageEnvelope(
|
MessageEnvelope(zone.id, LocalAction.DeployItem(obj)),
|
||||||
obj.Faction.toString,
|
/* zone map icon */
|
||||||
LocalAction.DeployableMapIcon(DeploymentAction.Build, DeployableInfo(obj.GUID, Deployable.Icon(obj.Definition.Item), obj.Position, obj.OwnerGuid.getOrElse(Default.GUID0)))
|
MessageEnvelope(
|
||||||
|
obj.Faction.toString,
|
||||||
|
LocalAction.DeployableMapIcon(DeploymentAction.Build, DeployableInfo(obj.GUID, Deployable.Icon(obj.Definition.Item), obj.Position, obj.OwnerGuid.getOrElse(Default.GUID0)))
|
||||||
|
)
|
||||||
)
|
)
|
||||||
//local build management
|
//local build management
|
||||||
callback ! Zone.Deployable.IsBuilt(obj)
|
callback ! Zone.Deployable.IsBuilt(obj)
|
||||||
|
|
@ -281,15 +284,13 @@ object DeployableBehavior {
|
||||||
val localEvents = zone.LocalEvents
|
val localEvents = zone.LocalEvents
|
||||||
if (originalFaction != toFaction) {
|
if (originalFaction != toFaction) {
|
||||||
obj.Faction = toFaction
|
obj.Faction = toFaction
|
||||||
//visual tells in regards to ownership by faction
|
localEvents ! BundledEnvelope(
|
||||||
zone.AvatarEvents ! MessageEnvelope(
|
/* visual tells in regards to ownership by faction */
|
||||||
zone.id,
|
MessageEnvelope(zone.id, SetEmpire(dGuid, toFaction)),
|
||||||
SetEmpire(dGuid, toFaction)
|
/* remove knowledge by the previous owner's faction */
|
||||||
)
|
MessageEnvelope(originalFaction.toString, LocalAction.DeployableMapIcon(DeploymentAction.Dismiss, info)),
|
||||||
//remove knowledge by the previous owner's faction
|
/* display to the given faction */
|
||||||
localEvents ! MessageEnvelope(
|
MessageEnvelope(toFaction.toString, LocalAction.DeployableMapIcon(DeploymentAction.Build, info))
|
||||||
originalFaction.toString,
|
|
||||||
LocalAction.DeployableMapIcon(DeploymentAction.Dismiss, info)
|
|
||||||
)
|
)
|
||||||
//remove deployable from original owner's toolbox and UI counter
|
//remove deployable from original owner's toolbox and UI counter
|
||||||
zone.AllPlayers.filter(p => obj.OriginalOwnerName.contains(p.Name))
|
zone.AllPlayers.filter(p => obj.OriginalOwnerName.contains(p.Name))
|
||||||
|
|
@ -297,11 +298,6 @@ object DeployableBehavior {
|
||||||
originalOwner.avatar.deployables.Remove(obj)
|
originalOwner.avatar.deployables.Remove(obj)
|
||||||
originalOwner.Zone.LocalEvents ! MessageEnvelope(originalOwner.Name, LocalAction.DeployableUIFor(obj.Definition.Item))
|
originalOwner.Zone.LocalEvents ! MessageEnvelope(originalOwner.Name, LocalAction.DeployableUIFor(obj.Definition.Item))
|
||||||
}
|
}
|
||||||
//display to the given faction
|
|
||||||
localEvents ! MessageEnvelope(
|
|
||||||
toFaction.toString,
|
|
||||||
LocalAction.DeployableMapIcon(DeploymentAction.Build, info)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import net.psforever.objects.vehicles.Utility.InternalTelepad
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.Zone
|
||||||
import net.psforever.packet.game.{GenericObjectActionMessage, ObjectCreateMessage, ObjectDeleteMessage}
|
import net.psforever.packet.game.{GenericObjectActionMessage, ObjectCreateMessage, ObjectDeleteMessage}
|
||||||
import net.psforever.packet.game.objectcreate.ObjectCreateMessageParent
|
import net.psforever.packet.game.objectcreate.ObjectCreateMessageParent
|
||||||
import net.psforever.services.base.envelope.MessageEnvelope
|
import net.psforever.services.base.envelope.{BundledEnvelope, MessageEnvelope}
|
||||||
import net.psforever.services.base.message.SendResponse
|
import net.psforever.services.base.message.SendResponse
|
||||||
import net.psforever.services.local.LocalAction
|
import net.psforever.services.local.LocalAction
|
||||||
import net.psforever.types.PlanetSideGUID
|
import net.psforever.types.PlanetSideGUID
|
||||||
|
|
@ -115,21 +115,23 @@ object TelepadLike {
|
||||||
normally dispatched while the Router is transitioned into its Deploying state
|
normally dispatched while the Router is transitioned into its Deploying state
|
||||||
it is safe, however, to perform these actions at any time during and after the Deploying state
|
it is safe, however, to perform these actions at any time during and after the Deploying state
|
||||||
*/
|
*/
|
||||||
events ! MessageEnvelope(
|
events ! BundledEnvelope(
|
||||||
zoneId,
|
MessageEnvelope(
|
||||||
SendResponse(
|
zoneId,
|
||||||
ObjectCreateMessage(
|
SendResponse(
|
||||||
udef.ObjectId,
|
ObjectCreateMessage(
|
||||||
utilityGUID,
|
udef.ObjectId,
|
||||||
ObjectCreateMessageParent(routerGUID, 2), //TODO stop assuming slot number
|
utilityGUID,
|
||||||
udef.Packet.ConstructorData(obj).get
|
ObjectCreateMessageParent(routerGUID, 2), //TODO stop assuming slot number
|
||||||
|
udef.Packet.ConstructorData(obj).get
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
),
|
||||||
|
MessageEnvelope(zoneId, SendResponse(Seq(
|
||||||
|
GenericObjectActionMessage(utilityGUID, 27),
|
||||||
|
GenericObjectActionMessage(utilityGUID, 30)
|
||||||
|
)))
|
||||||
)
|
)
|
||||||
events ! MessageEnvelope(zoneId, SendResponse(Seq(
|
|
||||||
GenericObjectActionMessage(utilityGUID, 27),
|
|
||||||
GenericObjectActionMessage(utilityGUID, 30)
|
|
||||||
)))
|
|
||||||
LinkTelepad(zone, utilityGUID)
|
LinkTelepad(zone, utilityGUID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import net.psforever.objects.sourcing.{PlayerSource, SourceEntry}
|
||||||
import net.psforever.objects.vital.interaction.{Adversarial, DamageResult}
|
import net.psforever.objects.vital.interaction.{Adversarial, DamageResult}
|
||||||
import net.psforever.objects.vital.{DamagingActivity, HealingActivity, InGameActivity, RepairingActivity, RevivingActivity, SpawningActivity}
|
import net.psforever.objects.vital.{DamagingActivity, HealingActivity, InGameActivity, RepairingActivity, RevivingActivity, SpawningActivity}
|
||||||
import net.psforever.services.avatar.AvatarAction
|
import net.psforever.services.avatar.AvatarAction
|
||||||
import net.psforever.services.base.envelope.MessageEnvelope
|
import net.psforever.services.base.envelope.{BundledEnvelope, MessageEnvelope}
|
||||||
import net.psforever.types.PlanetSideEmpire
|
import net.psforever.types.PlanetSideEmpire
|
||||||
import net.psforever.util.Config
|
import net.psforever.util.Config
|
||||||
|
|
||||||
|
|
@ -52,9 +52,9 @@ object KillAssists {
|
||||||
history: Iterable[InGameActivity],
|
history: Iterable[InGameActivity],
|
||||||
eventBus: ActorRef
|
eventBus: ActorRef
|
||||||
): Unit = {
|
): Unit = {
|
||||||
rewardThisPlayerDeath(victim, lastDamage, history).foreach { case (p, kda) =>
|
eventBus ! BundledEnvelope(rewardThisPlayerDeath(victim, lastDamage, history).map { case (p, kda) =>
|
||||||
eventBus ! MessageEnvelope(p.Name, AvatarAction.UpdateKillsDeathsAssists(p.CharId, kda))
|
MessageEnvelope(p.Name, AvatarAction.UpdateKillsDeathsAssists(p.CharId, kda))
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ package net.psforever.services.base
|
||||||
import akka.actor.Actor
|
import akka.actor.Actor
|
||||||
import net.psforever.services.Service
|
import net.psforever.services.Service
|
||||||
import net.psforever.services.base.bus.GenericEventBus
|
import net.psforever.services.base.bus.GenericEventBus
|
||||||
import net.psforever.services.base.envelope.GenericMessageEnvelope
|
import net.psforever.services.base.envelope.{BundledEnvelope, GenericMessageEnvelope}
|
||||||
import org.log4s.Logger
|
import org.log4s.Logger
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -78,6 +78,9 @@ class GenericEventService(stamp: EventSystemStamp)
|
||||||
* Accept and handle designated messages.
|
* Accept and handle designated messages.
|
||||||
*/
|
*/
|
||||||
protected def commonBehavior: Receive = {
|
protected def commonBehavior: Receive = {
|
||||||
|
case bundle: BundledEnvelope =>
|
||||||
|
bundle.msgs.foreach(commonBehavior.apply)
|
||||||
|
|
||||||
case msg: GenericMessageEnvelope =>
|
case msg: GenericMessageEnvelope =>
|
||||||
handleMessage(msg)
|
handleMessage(msg)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package net.psforever.services.base
|
||||||
|
|
||||||
import akka.actor.Cancellable
|
import akka.actor.Cancellable
|
||||||
import net.psforever.objects.Default
|
import net.psforever.objects.Default
|
||||||
import net.psforever.services.base.envelope.{GenericMessageEnvelope, GenericResponseEnvelope, MessageEnvelope, MessageTransformationBehavior}
|
import net.psforever.services.base.envelope.{BundledEnvelope, GenericMessageEnvelope, GenericResponseEnvelope, MessageEnvelope, MessageTransformationBehavior}
|
||||||
import net.psforever.services.base.message.EventMessage
|
import net.psforever.services.base.message.EventMessage
|
||||||
import net.psforever.types.PlanetSideGUID
|
import net.psforever.types.PlanetSideGUID
|
||||||
import net.psforever.util.Config
|
import net.psforever.util.Config
|
||||||
|
|
@ -137,18 +137,35 @@ class GenericEventServiceWithCacheAndSupport
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add messages to the cache based on their channel, then their type, then their cache target identifier.
|
* Add messages to the cache.
|
||||||
|
* @param event event system message
|
||||||
|
*/
|
||||||
|
private def pushToCache(event: CachedGenericEventEnvelope): Unit = {
|
||||||
|
pushToCache(event, event.msg.getClass.getName, event.guid)
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Add messages to the cache.
|
||||||
|
* @param event event system message
|
||||||
|
* @param eventGuid event system message filter
|
||||||
|
*/
|
||||||
|
private def pushToCache(event: GenericMessageEnvelope, eventGuid: PlanetSideGUID): Unit = {
|
||||||
|
pushToCache(event, event.msg.getClass.getName, eventGuid)
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Add messages to the cache
|
||||||
|
* based on their channel, then their type, then their cache target identifier.
|
||||||
* Messages that arrive with the same cache profile as a previous message,
|
* Messages that arrive with the same cache profile as a previous message,
|
||||||
* but before that previous message was dispatched,
|
* but before that previous message was dispatched,
|
||||||
* will overwrite the previous message without fanfare or warning.
|
* will overwrite the previous message without fanfare or warning.
|
||||||
* @param event event system message
|
* @param event event system message
|
||||||
|
* @param eventClassName event system message identifier
|
||||||
|
* @param eventGuid event system message filter
|
||||||
*/
|
*/
|
||||||
private def pushToCache(event: CachedGenericEventEnvelope): Unit = {
|
private def pushToCache(event: GenericMessageEnvelope, eventClassName: String, eventGuid: PlanetSideGUID): Unit = {
|
||||||
val eventClassName = event.msg.getClass.getName
|
|
||||||
val updateBranch = cache
|
val updateBranch = cache
|
||||||
.getOrElseUpdate(event.channel, new ConcurrentHashMap[String, CMap[PlanetSideGUID, GenericMessageEnvelope]]().asScala)
|
.getOrElseUpdate(event.channel, new ConcurrentHashMap[String, CMap[PlanetSideGUID, GenericMessageEnvelope]]().asScala)
|
||||||
.getOrElseUpdate(eventClassName, new ConcurrentHashMap[PlanetSideGUID, GenericMessageEnvelope]().asScala)
|
.getOrElseUpdate(eventClassName, new ConcurrentHashMap[PlanetSideGUID, GenericMessageEnvelope]().asScala)
|
||||||
updateBranch.updateWith(event.guid) { _ => Some(event) }
|
updateBranch.updateWith(eventGuid) { _ => Some(event) }
|
||||||
tryRetimeFlushCache()
|
tryRetimeFlushCache()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -194,6 +211,8 @@ class GenericEventServiceWithCacheAndSupport
|
||||||
event match {
|
event match {
|
||||||
case FlushCachedMessages =>
|
case FlushCachedMessages =>
|
||||||
flushCache()
|
flushCache()
|
||||||
|
case bundle: BundledEnvelope =>
|
||||||
|
handleMessageBundled(bundle)
|
||||||
case _: CachedGenericEventEnvelope if tryFlushCache() =>
|
case _: CachedGenericEventEnvelope if tryFlushCache() =>
|
||||||
super.handleMessage(event)
|
super.handleMessage(event)
|
||||||
case envelope: CachedGenericEventEnvelope =>
|
case envelope: CachedGenericEventEnvelope =>
|
||||||
|
|
@ -203,4 +222,24 @@ class GenericEventServiceWithCacheAndSupport
|
||||||
super.handleMessage(event)
|
super.handleMessage(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If even one message in a bundle is to be cached, the contents of the whole bundle should be cached.
|
||||||
|
* Otherwise, just handle things normally.
|
||||||
|
* @param bundle event system message that may be cached
|
||||||
|
*/
|
||||||
|
private def handleMessageBundled(bundle: BundledEnvelope): Unit = {
|
||||||
|
val messages = bundle.msgs
|
||||||
|
messages.find(_.isInstanceOf[CachedGenericEventEnvelope]) match {
|
||||||
|
case Some(cache: CachedGenericEventEnvelope) if messages.size == 1 =>
|
||||||
|
pushToCache(messages.head, cache.guid)
|
||||||
|
tryFlushCache()
|
||||||
|
case Some(cache: CachedGenericEventEnvelope) =>
|
||||||
|
val guid = cache.guid
|
||||||
|
messages.foreach(msg => pushToCache(msg, guid))
|
||||||
|
tryFlushCache()
|
||||||
|
case _ =>
|
||||||
|
messages.foreach(handleMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
// Copyright (c) 2026 PSForever
|
||||||
|
package net.psforever.services.base.envelope
|
||||||
|
|
||||||
|
import net.psforever.objects.Default
|
||||||
|
import net.psforever.services.base.EventSystemStamp
|
||||||
|
import net.psforever.services.base.message.{EventMessage, EventResponse}
|
||||||
|
import net.psforever.types.PlanetSideGUID
|
||||||
|
|
||||||
|
import scala.annotation.tailrec
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A message when there should be none, but a message is required to be defined anyway.
|
||||||
|
*/
|
||||||
|
case object NoMessage extends EventMessage {
|
||||||
|
override def response(): EventResponse = NoReply
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A response envelope when there should be none, but an envelope for messaging product is required to be defined anyway.
|
||||||
|
*/
|
||||||
|
case object NoResponse extends GenericResponseEnvelope {
|
||||||
|
override def reply: EventResponse = NoReply
|
||||||
|
override def stamp: EventSystemStamp = Undelivered
|
||||||
|
override def channel: String = ""
|
||||||
|
override def filter: PlanetSideGUID = Default.GUID0
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A collection of messaging envelopes to be dispatched to an event system at the same time
|
||||||
|
* within the conditions of event system synchronization between different messages.
|
||||||
|
* All messages contained within the bundling are to be processed at the time of processing by the bundling.
|
||||||
|
* The order of the bundled message envelopes should be considered important.
|
||||||
|
* @see `SendResponse(Seq[PlanetSideGamePacket])`
|
||||||
|
* @param msgs list of message envelopes
|
||||||
|
*/
|
||||||
|
final case class BundledEnvelope(msgs: Iterable[GenericMessageEnvelope])
|
||||||
|
extends GenericMessageEnvelope {
|
||||||
|
assert(msgs.size == BundledEnvelope.unwind(msgs).size, "do not nest bundled event system envelopes")
|
||||||
|
|
||||||
|
override def msg: EventMessage = NoMessage
|
||||||
|
override def response(stamp: EventSystemStamp): GenericResponseEnvelope = NoResponse
|
||||||
|
override def channel: String = ""
|
||||||
|
override def filter: PlanetSideGUID = Default.GUID0
|
||||||
|
}
|
||||||
|
|
||||||
|
object BundledEnvelope {
|
||||||
|
/**
|
||||||
|
* Overloaded constructor for `BundledEnvelope` objects.
|
||||||
|
* The entities are separated between "the first" and "any others" to distinguish from
|
||||||
|
* the `case class` constructor that accepts any number of message envelopes
|
||||||
|
* including no message envelopes at all.
|
||||||
|
* @param first single, required `GenericMessageEnvelope` entity for bundling
|
||||||
|
* @param msgs any other `GenericMessageEnvelope` entity for bundling
|
||||||
|
* @return a `BundledEnvelope` object
|
||||||
|
*/
|
||||||
|
def apply(first: GenericMessageEnvelope, msgs: GenericMessageEnvelope*): BundledEnvelope = {
|
||||||
|
new BundledEnvelope(unwind(first +: msgs))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input sanitization method that unpacks `BundledEnvelope` message envelopes
|
||||||
|
* producing a single-dimensional list of `GenericMessageEnvelope` entities.
|
||||||
|
* An assertion in the constructor of `BundledEnvelope` aborts object creation
|
||||||
|
* if a `BundledEnvelope` entity is within that `BundledEnvelope` entity.
|
||||||
|
* @param in list of `GenericMessageEnvelope` entities to be processed
|
||||||
|
* @param out list of `GenericMessageEnvelope` entities that have been processed
|
||||||
|
* @return list of `GenericMessageEnvelope` entities that have been processed
|
||||||
|
*/
|
||||||
|
@tailrec
|
||||||
|
private def unwind(in: Iterable[GenericMessageEnvelope], out: List[GenericMessageEnvelope] = Nil): List[GenericMessageEnvelope] = {
|
||||||
|
if (in.isEmpty) {
|
||||||
|
out
|
||||||
|
} else {
|
||||||
|
val first :: remainder = in
|
||||||
|
first match {
|
||||||
|
case bundle: BundledEnvelope =>
|
||||||
|
unwind(bundle.msgs ++ remainder, out)
|
||||||
|
case _ =>
|
||||||
|
unwind(remainder, out :+ first)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,7 +6,7 @@ import net.psforever.objects.{Default, Doors}
|
||||||
import net.psforever.objects.serverobject.doors.Door
|
import net.psforever.objects.serverobject.doors.Door
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.Zone
|
||||||
import net.psforever.services.base.{EventServiceSupport, GenericSupportEnvelope}
|
import net.psforever.services.base.{EventServiceSupport, GenericSupportEnvelope}
|
||||||
import net.psforever.services.base.envelope.MessageEnvelope
|
import net.psforever.services.base.envelope.{BundledEnvelope, MessageEnvelope}
|
||||||
import net.psforever.services.local.LocalAction.IsADoorMessage
|
import net.psforever.services.local.LocalAction.IsADoorMessage
|
||||||
import net.psforever.services.local.LocalAction
|
import net.psforever.services.local.LocalAction
|
||||||
import net.psforever.types.PlanetSideGUID
|
import net.psforever.types.PlanetSideGUID
|
||||||
|
|
@ -64,11 +64,13 @@ class DoorCloseActor() extends Actor {
|
||||||
doorsLeftOpen1 ++
|
doorsLeftOpen1 ++
|
||||||
doorsLeftOpen2.map(entry => DoorCloseActor.DoorEntry(entry.door, entry.zone, now))
|
doorsLeftOpen2.map(entry => DoorCloseActor.DoorEntry(entry.door, entry.zone, now))
|
||||||
).sortBy(_.time)
|
).sortBy(_.time)
|
||||||
doorsToClose2.foreach { case DoorCloseActor.DoorEntry(door, zone, _) =>
|
doorsToClose2
|
||||||
door.Open = None //permissible break from synchronization
|
.map { case DoorCloseActor.DoorEntry(door, zone, _) =>
|
||||||
zone.LocalEvents ! MessageEnvelope(zone.id, LocalAction.DoorCloses(door.GUID)) //call up to the main event system
|
door.Open = None //permissible break from synchronization
|
||||||
}
|
(zone, MessageEnvelope(zone.id, LocalAction.DoorCloses(door.GUID))) //call up to the main event system
|
||||||
|
}
|
||||||
|
.groupBy(_._1)
|
||||||
|
.foreach { case (zone, list) => zone.LocalEvents ! BundledEnvelope(list.map(_._2)) }
|
||||||
if (openDoors.nonEmpty) {
|
if (openDoors.nonEmpty) {
|
||||||
val short_timeout: FiniteDuration = math.max(1, DoorCloseActor.timeout_time - (now - openDoors.head.time)).milliseconds
|
val short_timeout: FiniteDuration = math.max(1, DoorCloseActor.timeout_time - (now - openDoors.head.time)).milliseconds
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import net.psforever.objects.serverobject.structures.participation.MajorFacility
|
||||||
import net.psforever.packet.game.{ChatMsg, GenericAction, HackState7, PlanetsideAttributeEnum}
|
import net.psforever.packet.game.{ChatMsg, GenericAction, HackState7, PlanetsideAttributeEnum}
|
||||||
import net.psforever.objects.sourcing.PlayerSource
|
import net.psforever.objects.sourcing.PlayerSource
|
||||||
import net.psforever.services.base.{EventServiceSupport, GenericSupportEnvelopeOnly}
|
import net.psforever.services.base.{EventServiceSupport, GenericSupportEnvelopeOnly}
|
||||||
import net.psforever.services.base.envelope.MessageEnvelope
|
import net.psforever.services.base.envelope.{BundledEnvelope, MessageEnvelope}
|
||||||
import net.psforever.services.base.message.PlanetsideAttribute
|
import net.psforever.services.base.message.PlanetsideAttribute
|
||||||
import net.psforever.services.local.support.HackCaptureActor.GetHackingFaction
|
import net.psforever.services.local.support.HackCaptureActor.GetHackingFaction
|
||||||
import net.psforever.services.local.LocalAction
|
import net.psforever.services.local.LocalAction
|
||||||
|
|
@ -22,6 +22,7 @@ import net.psforever.types.{ChatMessageType, PlanetSideEmpire, PlanetSideGUID}
|
||||||
|
|
||||||
import java.util.concurrent.{Executors, TimeUnit}
|
import java.util.concurrent.{Executors, TimeUnit}
|
||||||
import scala.collection.Seq
|
import scala.collection.Seq
|
||||||
|
import scala.collection.mutable.ArrayBuffer
|
||||||
import scala.concurrent.duration.{FiniteDuration, _}
|
import scala.concurrent.duration.{FiniteDuration, _}
|
||||||
import scala.util.Random
|
import scala.util.Random
|
||||||
|
|
||||||
|
|
@ -277,18 +278,18 @@ class HackCaptureActor extends Actor {
|
||||||
|
|
||||||
private def HackCompleted(terminal: CaptureTerminal with Hackable, hackedByFaction: PlanetSideEmpire.Value): Unit = {
|
private def HackCompleted(terminal: CaptureTerminal with Hackable, hackedByFaction: PlanetSideEmpire.Value): Unit = {
|
||||||
val building = terminal.Owner.asInstanceOf[Building]
|
val building = terminal.Owner.asInstanceOf[Building]
|
||||||
|
val zone = building.Zone
|
||||||
|
val events = zone.LocalEvents
|
||||||
|
val messages: ArrayBuffer[MessageEnvelope] = ArrayBuffer()
|
||||||
if (building.NtuLevel > 0) {
|
if (building.NtuLevel > 0) {
|
||||||
building.virusId = 8
|
building.virusId = 8
|
||||||
building.virusInstalledBy = None
|
building.virusInstalledBy = None
|
||||||
log.info(s"Setting base ${building.GUID} / MapId: ${building.MapId} as owned by $hackedByFaction")
|
log.info(s"Setting base ${building.GUID} / MapId: ${building.MapId} as owned by $hackedByFaction")
|
||||||
//dispatch to players aligned with the capturing faction within the SOI
|
//dispatch to players aligned with the capturing faction within the SOI
|
||||||
val events = building.Zone.LocalEvents
|
|
||||||
val msg = LocalAction.GenericActionMessage(GenericAction.FacilityCaptureFanfare)
|
val msg = LocalAction.GenericActionMessage(GenericAction.FacilityCaptureFanfare)
|
||||||
building
|
messages.appendAll(building.PlayersInSOI.collect { case p if p.Faction == hackedByFaction =>
|
||||||
.PlayersInSOI
|
MessageEnvelope(p.Name, msg)
|
||||||
.collect { case p if p.Faction == hackedByFaction =>
|
})
|
||||||
events ! MessageEnvelope(p.Name, msg)
|
|
||||||
}
|
|
||||||
val buildings = building.Zone.Buildings.values
|
val buildings = building.Zone.Buildings.values
|
||||||
val hackedBaseId = building.GUID
|
val hackedBaseId = building.GUID
|
||||||
val facilities = if (building.Zone.id.startsWith("c")) {
|
val facilities = if (building.Zone.id.startsWith("c")) {
|
||||||
|
|
@ -322,8 +323,8 @@ class HackCaptureActor extends Actor {
|
||||||
}
|
}
|
||||||
NotifyHackStateChange(terminal, isResecured = true)
|
NotifyHackStateChange(terminal, isResecured = true)
|
||||||
// todo: this appears to be the way to reset the base warning lights after the hack finishes but it doesn't seem to work.
|
// todo: this appears to be the way to reset the base warning lights after the hack finishes but it doesn't seem to work.
|
||||||
val zone = building.Zone
|
messages.append(MessageEnvelope(zone.id, LocalAction.HackClear(building.GUID, 3212836864L, HackState7.Unk8)))
|
||||||
zone.LocalEvents ! MessageEnvelope(zone.id, LocalAction.HackClear(building.GUID, 3212836864L, HackState7.Unk8))
|
events ! BundledEnvelope(messages)
|
||||||
}
|
}
|
||||||
|
|
||||||
private def RestartTimer(): Unit = {
|
private def RestartTimer(): Unit = {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import net.psforever.objects.serverobject.hackable.Hackable
|
||||||
import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject}
|
import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject}
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.Zone
|
||||||
import net.psforever.packet.game.HackState7
|
import net.psforever.packet.game.HackState7
|
||||||
import net.psforever.services.base.envelope.MessageEnvelope
|
import net.psforever.services.base.envelope.{BundledEnvelope, MessageEnvelope}
|
||||||
import net.psforever.services.base.{EventServiceSupport, GenericSupportEnvelope, GenericSupportEnvelopeOnly}
|
import net.psforever.services.base.{EventServiceSupport, GenericSupportEnvelope, GenericSupportEnvelopeOnly}
|
||||||
import net.psforever.services.base.message.GenericObjectAction
|
import net.psforever.services.base.message.GenericObjectAction
|
||||||
import net.psforever.services.local.LocalAction.IsAHackMessage
|
import net.psforever.services.local.LocalAction.IsAHackMessage
|
||||||
|
|
@ -72,13 +72,18 @@ class HackClearActor() extends Actor {
|
||||||
//TODO we can just walk across the list of doors and extract only the first few entries
|
//TODO we can just walk across the list of doors and extract only the first few entries
|
||||||
val (unhackObjects, stillHackedObjects) = PartitionEntries(hackedObjects, now)
|
val (unhackObjects, stillHackedObjects) = PartitionEntries(hackedObjects, now)
|
||||||
hackedObjects = stillHackedObjects
|
hackedObjects = stillHackedObjects
|
||||||
unhackObjects.foreach { case HackClearActor.HackEntry(target, zone, unk1, unk2, _, _) =>
|
unhackObjects
|
||||||
target.Actor ! CommonMessages.ClearHack()
|
.map { case HackClearActor.HackEntry(target, zone, unk1, unk2, _, _) =>
|
||||||
zone.LocalEvents ! MessageEnvelope(zone.id, LocalAction.HackClear(target.GUID, unk1, unk2))
|
target.Actor ! CommonMessages.ClearHack()
|
||||||
if (target.Definition == GlobalDefinitions.main_terminal) {
|
if (target.Definition == GlobalDefinitions.main_terminal) {
|
||||||
ClearVirusFromBuilding(target)
|
ClearVirusFromBuilding(target)
|
||||||
|
}
|
||||||
|
(zone, MessageEnvelope(zone.id, LocalAction.HackClear(target.GUID, unk1, unk2)))
|
||||||
|
}
|
||||||
|
.groupBy(_._1)
|
||||||
|
.foreach { case (zone, list) =>
|
||||||
|
zone.LocalEvents ! BundledEnvelope(list.map(_._2))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
RestartTimer()
|
RestartTimer()
|
||||||
|
|
||||||
|
|
@ -132,9 +137,7 @@ class HackClearActor() extends Actor {
|
||||||
building.virusInstalledBy = None
|
building.virusInstalledBy = None
|
||||||
val msg = GenericObjectAction(target.GUID, 60)
|
val msg = GenericObjectAction(target.GUID, 60)
|
||||||
val events = building.Zone.AvatarEvents
|
val events = building.Zone.AvatarEvents
|
||||||
building.PlayersInSOI.foreach { player =>
|
events ! BundledEnvelope(building.PlayersInSOI.map { player => MessageEnvelope(player.Name, msg) })
|
||||||
events ! MessageEnvelope(player.Name, msg)
|
|
||||||
}
|
|
||||||
building.Actor ! BuildingActor.MapUpdate()
|
building.Actor ! BuildingActor.MapUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue