mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-06-25 06:44:19 +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.game.ContinentalLockUpdateMessage
|
||||
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.galaxy.GalaxyAction
|
||||
import net.psforever.services.{InterstellarClusterService, ServiceManager}
|
||||
|
|
@ -232,8 +232,10 @@ class BuildingActor(
|
|||
Behaviors.same
|
||||
|
||||
case MapUpdate() =>
|
||||
details.galaxyService ! MessageEnvelope("", GalaxyAction.MapUpdate(details.building.infoUpdateMessage()))
|
||||
details.galaxyService ! MessageEnvelope("", SendResponse(details.building.densityLevelUpdateMessage(building)))
|
||||
details.galaxyService ! BundledEnvelope(
|
||||
MessageEnvelope("", GalaxyAction.MapUpdate(details.building.infoUpdateMessage())),
|
||||
MessageEnvelope("", SendResponse(details.building.densityLevelUpdateMessage(building)))
|
||||
)
|
||||
Behaviors.same
|
||||
|
||||
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.packet.game.{GenericObjectActionMessage, PlanetsideAttributeMessage}
|
||||
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.galaxy.GalaxyAction
|
||||
import net.psforever.services.local.support.{CaptureEnvelope, HackCaptureActor, HackClearActor, HackClearEnvelope}
|
||||
|
|
@ -204,25 +204,19 @@ case object MajorFacilityLogic
|
|||
val events = zone.AvatarEvents
|
||||
val guid = building.GUID
|
||||
val msg = GenericObjectAction(guid, 15)
|
||||
building.PlayersInSOI.foreach { player =>
|
||||
events ! MessageEnvelope(player.Name, msg)
|
||||
}
|
||||
events ! BundledEnvelope(building.PlayersInSOI.map { player => MessageEnvelope(player.Name, msg) })
|
||||
false
|
||||
case Some(GeneratorControl.Event.Critical) =>
|
||||
val events = zone.AvatarEvents
|
||||
val guid = building.GUID
|
||||
val msg = PlanetsideAttribute(guid, 46, 1)
|
||||
building.PlayersInSOI.foreach { player =>
|
||||
events ! MessageEnvelope(player.Name, msg)
|
||||
}
|
||||
events ! BundledEnvelope(building.PlayersInSOI.map { player => MessageEnvelope(player.Name, msg) })
|
||||
true
|
||||
case Some(GeneratorControl.Event.Destabilized) =>
|
||||
val events = zone.AvatarEvents
|
||||
val guid = building.GUID
|
||||
val msg = GenericObjectAction(guid, 16)
|
||||
building.PlayersInSOI.foreach { player =>
|
||||
events ! MessageEnvelope(player.Name, msg)
|
||||
}
|
||||
events ! BundledEnvelope(building.PlayersInSOI.map { player => MessageEnvelope(player.Name, msg) })
|
||||
if (building.hasCavernLockBenefit) {
|
||||
zone.LocalEvents ! MessageEnvelope(
|
||||
zone.id,
|
||||
|
|
@ -235,10 +229,9 @@ case object MajorFacilityLogic
|
|||
case Some(GeneratorControl.Event.Offline) =>
|
||||
powerLost(details)
|
||||
val zone = building.Zone
|
||||
val events = zone.AvatarEvents
|
||||
val msg = PlanetsideAttribute(building.GUID, 46, 2)
|
||||
building.PlayersInSOI.foreach { player =>
|
||||
zone.AvatarEvents ! MessageEnvelope(player.Name, msg)
|
||||
} //???
|
||||
events ! BundledEnvelope(building.PlayersInSOI.map { player => MessageEnvelope(player.Name, msg) }) //???
|
||||
true
|
||||
case Some(GeneratorControl.Event.Normal) =>
|
||||
true
|
||||
|
|
@ -253,9 +246,7 @@ case object MajorFacilityLogic
|
|||
PlanetsideAttributeMessage(guid, 46, 0),
|
||||
GenericObjectActionMessage(guid, 17)
|
||||
))
|
||||
building.PlayersInSOI.foreach { player =>
|
||||
events ! MessageEnvelope(player.Name, list)
|
||||
}
|
||||
events ! BundledEnvelope(building.PlayersInSOI.map { player => MessageEnvelope(player.Name, list) })
|
||||
true
|
||||
case _ =>
|
||||
false
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import akka.actor.typed.scaladsl.Behaviors
|
|||
import net.psforever.actors.commands.NtuCommand
|
||||
import net.psforever.actors.zone.BuildingActor
|
||||
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.types.PlanetSideEmpire
|
||||
import net.psforever.util.Config
|
||||
|
|
@ -209,9 +209,7 @@ case object WarpGateLogic
|
|||
warpgate.Zone.Number, warpgate.MapId, previousAllowances, setBroadcastTo
|
||||
)
|
||||
warpgate.AllowBroadcastFor = setBroadcastTo
|
||||
(setBroadcastTo ++ previousAllowances).foreach { faction =>
|
||||
events ! MessageEnvelope(faction.toString, msg)
|
||||
}
|
||||
events ! BundledEnvelope((setBroadcastTo ++ previousAllowances).map { faction => MessageEnvelope(faction.toString, msg) })
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -107,10 +107,7 @@ class BoomerDeployableControl(mine: BoomerDeployable)
|
|||
zone.Ground ! Zone.Ground.RemoveItem(guid)
|
||||
case _ => ()
|
||||
}
|
||||
zone.AvatarEvents! MessageEnvelope(
|
||||
zone.id,
|
||||
ObjectDelete(guid)
|
||||
)
|
||||
zone.AvatarEvents! MessageEnvelope(zone.id, ObjectDelete(guid))
|
||||
TaskWorkflow.execute(GUIDTask.unregisterObject(zone.GUID, trigger))
|
||||
case None => ()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,11 +20,12 @@ import net.psforever.objects.zones.Zone
|
|||
import net.psforever.packet.game._
|
||||
import net.psforever.types.{ChatMessageType, ExoSuitType, PlanetSideGUID, Vector3}
|
||||
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.local.LocalAction
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
|
||||
object Players {
|
||||
private val log = org.log4s.getLogger("Players")
|
||||
|
|
@ -49,10 +50,7 @@ object Players {
|
|||
) {
|
||||
val events = target.Zone.AvatarEvents
|
||||
val uname = user.Name
|
||||
events ! MessageEnvelope(
|
||||
uname,
|
||||
SendResponse(RepairMessage(target.GUID, progress.toInt))
|
||||
)
|
||||
events ! MessageEnvelope(uname, SendResponse(RepairMessage(target.GUID, progress.toInt)))
|
||||
true
|
||||
} else {
|
||||
false
|
||||
|
|
@ -439,24 +437,20 @@ object Players {
|
|||
if ((player.Slot(index).Equipment = obj).contains(obj)) {
|
||||
val fireMode = tool.FireModeIndex
|
||||
val ammoType = tool.AmmoTypeIndex
|
||||
val list: ArrayBuffer[MessageEnvelope] = ArrayBuffer()
|
||||
player.Inventory -= x.start
|
||||
obj.FireModeIndex = fireMode
|
||||
//TODO any penalty for being handed an OCM version of the tool?
|
||||
events ! MessageEnvelope(
|
||||
zone.id,
|
||||
AvatarAction.EquipmentInHand(pguid, index, obj)
|
||||
)
|
||||
list.append(MessageEnvelope(zone.id, AvatarAction.EquipmentInHand(pguid, index, obj)))
|
||||
if (obj.AmmoTypeIndex != ammoType) {
|
||||
obj.AmmoTypeIndex = ammoType
|
||||
events ! MessageEnvelope(
|
||||
name,
|
||||
SendResponse(ChangeAmmoMessage(obj.GUID, ammoType))
|
||||
)
|
||||
list.append(MessageEnvelope(name, SendResponse(ChangeAmmoMessage(obj.GUID, ammoType))))
|
||||
}
|
||||
if (player.DrawnSlot == Player.HandsDownSlot) {
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,11 +12,13 @@ import net.psforever.objects.vehicles._
|
|||
import net.psforever.objects.zones.Zone
|
||||
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.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.local.LocalAction
|
||||
import net.psforever.services.vehicle.VehicleAction
|
||||
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
|
||||
//import scala.concurrent.duration._
|
||||
|
||||
object Vehicles {
|
||||
|
|
@ -248,13 +250,15 @@ object Vehicles {
|
|||
val hFaction = hacker.Faction
|
||||
val zone = target.Zone
|
||||
val zoneid = zone.id
|
||||
val avatarEvents = zone.AvatarEvents
|
||||
val vehicleEvents = zone.VehicleEvents
|
||||
val localEvents = zone.LocalEvents
|
||||
val previousOwnerName = target.OwnerName.getOrElse("")
|
||||
vehicleEvents ! MessageEnvelope(
|
||||
val occupantMessages: ArrayBuffer[MessageEnvelope] = ArrayBuffer()
|
||||
val vehicleMessages: ArrayBuffer[MessageEnvelope] = ArrayBuffer()
|
||||
vehicleMessages.append(MessageEnvelope(
|
||||
zoneid,
|
||||
SendResponse(HackMessage(HackState1.Unk2, tGuid, hGuid, 100, 0f, HackState.Hacked, HackState7.Unk8))
|
||||
)
|
||||
))
|
||||
target.Actor ! CommonMessages.Hack(hacker, target)
|
||||
// Forcefully dismount any cargo
|
||||
target.CargoHolds.foreach { case (_, cargoHold) =>
|
||||
|
|
@ -268,26 +272,29 @@ object Vehicles {
|
|||
player: Player =>
|
||||
seat.unmount(player)
|
||||
player.VehicleSeated = None
|
||||
vehicleEvents ! MessageEnvelope(
|
||||
occupantMessages.append(MessageEnvelope(
|
||||
zoneid,
|
||||
player.GUID,
|
||||
VehicleAction.KickPassenger(4, unk2 = false, tGuid)
|
||||
)
|
||||
))
|
||||
}
|
||||
// In case BFR is occupied and may or may not be crouched
|
||||
if (GlobalDefinitions.isBattleFrameVehicle(target.Definition) && target.Seat(0).isDefined) {
|
||||
zone.LocalEvents ! MessageEnvelope(
|
||||
zoneid,
|
||||
GenericObjectAction(target.GUID, GenericObjectActionEnum.BFRShieldsDown.id)
|
||||
)
|
||||
zone.LocalEvents ! MessageEnvelope(
|
||||
zoneid,
|
||||
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)))
|
||||
zone.LocalEvents ! MessageEnvelope(
|
||||
zoneid,
|
||||
SendResponse(
|
||||
VehicleStateMessage(target.GUID, 0, target.Position, target.Orientation, Some(Vector3(0f, 0f, 0f)), None, 0, 0, 15, is_decelerating=false, is_cloaked=false)))
|
||||
vehicleMessages.appendAll(List(
|
||||
MessageEnvelope(zoneid,
|
||||
GenericObjectAction(target.GUID, GenericObjectActionEnum.BFRShieldsDown.id)
|
||||
),
|
||||
MessageEnvelope(zoneid,
|
||||
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)
|
||||
)
|
||||
),
|
||||
MessageEnvelope(zoneid,
|
||||
SendResponse(
|
||||
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
|
||||
|
|
@ -312,26 +319,17 @@ object Vehicles {
|
|||
Vehicles.Own(target, hacker)
|
||||
//todo: Send HackMessage -> HackCleared to vehicle? can be found in packet captures. Not sure if necessary.
|
||||
// And broadcast the faction change to other clients
|
||||
zone.AvatarEvents ! MessageEnvelope(
|
||||
zoneid,
|
||||
SetEmpire(tGuid, hFaction)
|
||||
)
|
||||
vehicleMessages.append(MessageEnvelope(zoneid, SetEmpire(tGuid, hFaction)))
|
||||
}
|
||||
localEvents ! MessageEnvelope(
|
||||
vehicleMessages.append(MessageEnvelope(
|
||||
zoneid,
|
||||
hGuid,
|
||||
LocalAction.TriggerSound(TriggeredSound.HackVehicle, target.Position, 30, 0.49803925f)
|
||||
)
|
||||
))
|
||||
if (zone.Players.exists(_.name.equals(previousOwnerName))) {
|
||||
localEvents ! MessageEnvelope(
|
||||
previousOwnerName,
|
||||
SendResponse(ChatMsg(ChatMessageType.UNK_226, "@JackStolen"))
|
||||
)
|
||||
vehicleMessages.append(MessageEnvelope(previousOwnerName, SendResponse(ChatMsg(ChatMessageType.UNK_226, "@JackStolen"))))
|
||||
}
|
||||
localEvents ! MessageEnvelope(
|
||||
hacker.Name,
|
||||
SendResponse(ChatMsg(ChatMessageType.UNK_226, "@JackVehicleOwned"))
|
||||
)
|
||||
occupantMessages.append(MessageEnvelope(hacker.Name, SendResponse(ChatMsg(ChatMessageType.UNK_226, "@JackVehicleOwned"))))
|
||||
// Clean up after specific vehicles, e.g. remove router telepads
|
||||
// If AMS is deployed, swap it to the new faction
|
||||
target.Definition match {
|
||||
|
|
@ -343,13 +341,15 @@ object Vehicles {
|
|||
util.Actor ! TelepadLike.Activate(util)
|
||||
}
|
||||
case GlobalDefinitions.ams if target.DeploymentState == DriveState.Deployed =>
|
||||
vehicleEvents ! MessageEnvelope(zone.id, VehicleAction.AMSDeploymentChange(zone))
|
||||
vehicleMessages.append(MessageEnvelope(zone.id, VehicleAction.AMSDeploymentChange(zone)))
|
||||
case _ => ()
|
||||
}
|
||||
vehicleEvents ! MessageEnvelope(
|
||||
vehicleMessages.append(MessageEnvelope(
|
||||
zoneid,
|
||||
SendResponse(HackMessage(HackState1.Unk2, tGuid, tGuid, 0, 1L, HackState.HackCleared, HackState7.Unk8))
|
||||
)
|
||||
))
|
||||
avatarEvents ! BundledEnvelope(occupantMessages)
|
||||
vehicleEvents ! BundledEnvelope(vehicleMessages)
|
||||
target.Actor ! CommonMessages.ClearHack()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import net.psforever.objects.guid.{GUIDTask, TaskWorkflow}
|
|||
import net.psforever.objects._
|
||||
import net.psforever.objects.zones.Zone
|
||||
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.local.LocalAction
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
|
|
@ -198,11 +198,14 @@ trait DeployableBehavior {
|
|||
None
|
||||
}
|
||||
//zone build
|
||||
localEvents ! MessageEnvelope(zone.id, LocalAction.DeployItem(obj))
|
||||
//zone map icon
|
||||
localEvents ! MessageEnvelope(
|
||||
obj.Faction.toString,
|
||||
LocalAction.DeployableMapIcon(DeploymentAction.Build, DeployableInfo(obj.GUID, Deployable.Icon(obj.Definition.Item), obj.Position, obj.OwnerGuid.getOrElse(Default.GUID0)))
|
||||
localEvents ! BundledEnvelope(
|
||||
/* zone build */
|
||||
MessageEnvelope(zone.id, LocalAction.DeployItem(obj)),
|
||||
/* zone map icon */
|
||||
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
|
||||
callback ! Zone.Deployable.IsBuilt(obj)
|
||||
|
|
@ -281,15 +284,13 @@ object DeployableBehavior {
|
|||
val localEvents = zone.LocalEvents
|
||||
if (originalFaction != toFaction) {
|
||||
obj.Faction = toFaction
|
||||
//visual tells in regards to ownership by faction
|
||||
zone.AvatarEvents ! MessageEnvelope(
|
||||
zone.id,
|
||||
SetEmpire(dGuid, toFaction)
|
||||
)
|
||||
//remove knowledge by the previous owner's faction
|
||||
localEvents ! MessageEnvelope(
|
||||
originalFaction.toString,
|
||||
LocalAction.DeployableMapIcon(DeploymentAction.Dismiss, info)
|
||||
localEvents ! BundledEnvelope(
|
||||
/* visual tells in regards to ownership by faction */
|
||||
MessageEnvelope(zone.id, SetEmpire(dGuid, toFaction)),
|
||||
/* remove knowledge by the previous owner's faction */
|
||||
MessageEnvelope(originalFaction.toString, LocalAction.DeployableMapIcon(DeploymentAction.Dismiss, info)),
|
||||
/* display to the given faction */
|
||||
MessageEnvelope(toFaction.toString, LocalAction.DeployableMapIcon(DeploymentAction.Build, info))
|
||||
)
|
||||
//remove deployable from original owner's toolbox and UI counter
|
||||
zone.AllPlayers.filter(p => obj.OriginalOwnerName.contains(p.Name))
|
||||
|
|
@ -297,11 +298,6 @@ object DeployableBehavior {
|
|||
originalOwner.avatar.deployables.Remove(obj)
|
||||
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.packet.game.{GenericObjectActionMessage, ObjectCreateMessage, ObjectDeleteMessage}
|
||||
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.local.LocalAction
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
|
|
@ -115,21 +115,23 @@ object TelepadLike {
|
|||
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
|
||||
*/
|
||||
events ! MessageEnvelope(
|
||||
zoneId,
|
||||
SendResponse(
|
||||
ObjectCreateMessage(
|
||||
udef.ObjectId,
|
||||
utilityGUID,
|
||||
ObjectCreateMessageParent(routerGUID, 2), //TODO stop assuming slot number
|
||||
udef.Packet.ConstructorData(obj).get
|
||||
events ! BundledEnvelope(
|
||||
MessageEnvelope(
|
||||
zoneId,
|
||||
SendResponse(
|
||||
ObjectCreateMessage(
|
||||
udef.ObjectId,
|
||||
utilityGUID,
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import net.psforever.objects.sourcing.{PlayerSource, SourceEntry}
|
|||
import net.psforever.objects.vital.interaction.{Adversarial, DamageResult}
|
||||
import net.psforever.objects.vital.{DamagingActivity, HealingActivity, InGameActivity, RepairingActivity, RevivingActivity, SpawningActivity}
|
||||
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.util.Config
|
||||
|
||||
|
|
@ -52,9 +52,9 @@ object KillAssists {
|
|||
history: Iterable[InGameActivity],
|
||||
eventBus: ActorRef
|
||||
): Unit = {
|
||||
rewardThisPlayerDeath(victim, lastDamage, history).foreach { case (p, kda) =>
|
||||
eventBus ! MessageEnvelope(p.Name, AvatarAction.UpdateKillsDeathsAssists(p.CharId, kda))
|
||||
}
|
||||
eventBus ! BundledEnvelope(rewardThisPlayerDeath(victim, lastDamage, history).map { case (p, kda) =>
|
||||
MessageEnvelope(p.Name, AvatarAction.UpdateKillsDeathsAssists(p.CharId, kda))
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ package net.psforever.services.base
|
|||
import akka.actor.Actor
|
||||
import net.psforever.services.Service
|
||||
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
|
||||
|
||||
/**
|
||||
|
|
@ -78,6 +78,9 @@ class GenericEventService(stamp: EventSystemStamp)
|
|||
* Accept and handle designated messages.
|
||||
*/
|
||||
protected def commonBehavior: Receive = {
|
||||
case bundle: BundledEnvelope =>
|
||||
bundle.msgs.foreach(commonBehavior.apply)
|
||||
|
||||
case msg: GenericMessageEnvelope =>
|
||||
handleMessage(msg)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package net.psforever.services.base
|
|||
|
||||
import akka.actor.Cancellable
|
||||
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.types.PlanetSideGUID
|
||||
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,
|
||||
* but before that previous message was dispatched,
|
||||
* will overwrite the previous message without fanfare or warning.
|
||||
* @param event event system message
|
||||
* @param eventClassName event system message identifier
|
||||
* @param eventGuid event system message filter
|
||||
*/
|
||||
private def pushToCache(event: CachedGenericEventEnvelope): Unit = {
|
||||
val eventClassName = event.msg.getClass.getName
|
||||
private def pushToCache(event: GenericMessageEnvelope, eventClassName: String, eventGuid: PlanetSideGUID): Unit = {
|
||||
val updateBranch = cache
|
||||
.getOrElseUpdate(event.channel, new ConcurrentHashMap[String, CMap[PlanetSideGUID, GenericMessageEnvelope]]().asScala)
|
||||
.getOrElseUpdate(eventClassName, new ConcurrentHashMap[PlanetSideGUID, GenericMessageEnvelope]().asScala)
|
||||
updateBranch.updateWith(event.guid) { _ => Some(event) }
|
||||
updateBranch.updateWith(eventGuid) { _ => Some(event) }
|
||||
tryRetimeFlushCache()
|
||||
}
|
||||
|
||||
|
|
@ -194,6 +211,8 @@ class GenericEventServiceWithCacheAndSupport
|
|||
event match {
|
||||
case FlushCachedMessages =>
|
||||
flushCache()
|
||||
case bundle: BundledEnvelope =>
|
||||
handleMessageBundled(bundle)
|
||||
case _: CachedGenericEventEnvelope if tryFlushCache() =>
|
||||
super.handleMessage(event)
|
||||
case envelope: CachedGenericEventEnvelope =>
|
||||
|
|
@ -203,4 +222,24 @@ class GenericEventServiceWithCacheAndSupport
|
|||
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.zones.Zone
|
||||
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
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
|
|
@ -64,11 +64,13 @@ class DoorCloseActor() extends Actor {
|
|||
doorsLeftOpen1 ++
|
||||
doorsLeftOpen2.map(entry => DoorCloseActor.DoorEntry(entry.door, entry.zone, now))
|
||||
).sortBy(_.time)
|
||||
doorsToClose2.foreach { case DoorCloseActor.DoorEntry(door, zone, _) =>
|
||||
door.Open = None //permissible break from synchronization
|
||||
zone.LocalEvents ! MessageEnvelope(zone.id, LocalAction.DoorCloses(door.GUID)) //call up to the main event system
|
||||
}
|
||||
|
||||
doorsToClose2
|
||||
.map { case DoorCloseActor.DoorEntry(door, zone, _) =>
|
||||
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) {
|
||||
val short_timeout: FiniteDuration = math.max(1, DoorCloseActor.timeout_time - (now - openDoors.head.time)).milliseconds
|
||||
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.objects.sourcing.PlayerSource
|
||||
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.local.support.HackCaptureActor.GetHackingFaction
|
||||
import net.psforever.services.local.LocalAction
|
||||
|
|
@ -22,6 +22,7 @@ import net.psforever.types.{ChatMessageType, PlanetSideEmpire, PlanetSideGUID}
|
|||
|
||||
import java.util.concurrent.{Executors, TimeUnit}
|
||||
import scala.collection.Seq
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
import scala.concurrent.duration.{FiniteDuration, _}
|
||||
import scala.util.Random
|
||||
|
||||
|
|
@ -277,18 +278,18 @@ class HackCaptureActor extends Actor {
|
|||
|
||||
private def HackCompleted(terminal: CaptureTerminal with Hackable, hackedByFaction: PlanetSideEmpire.Value): Unit = {
|
||||
val building = terminal.Owner.asInstanceOf[Building]
|
||||
val zone = building.Zone
|
||||
val events = zone.LocalEvents
|
||||
val messages: ArrayBuffer[MessageEnvelope] = ArrayBuffer()
|
||||
if (building.NtuLevel > 0) {
|
||||
building.virusId = 8
|
||||
building.virusInstalledBy = None
|
||||
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
|
||||
val events = building.Zone.LocalEvents
|
||||
val msg = LocalAction.GenericActionMessage(GenericAction.FacilityCaptureFanfare)
|
||||
building
|
||||
.PlayersInSOI
|
||||
.collect { case p if p.Faction == hackedByFaction =>
|
||||
events ! MessageEnvelope(p.Name, msg)
|
||||
}
|
||||
messages.appendAll(building.PlayersInSOI.collect { case p if p.Faction == hackedByFaction =>
|
||||
MessageEnvelope(p.Name, msg)
|
||||
})
|
||||
val buildings = building.Zone.Buildings.values
|
||||
val hackedBaseId = building.GUID
|
||||
val facilities = if (building.Zone.id.startsWith("c")) {
|
||||
|
|
@ -322,8 +323,8 @@ class HackCaptureActor extends Actor {
|
|||
}
|
||||
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.
|
||||
val zone = building.Zone
|
||||
zone.LocalEvents ! MessageEnvelope(zone.id, LocalAction.HackClear(building.GUID, 3212836864L, HackState7.Unk8))
|
||||
messages.append(MessageEnvelope(zone.id, LocalAction.HackClear(building.GUID, 3212836864L, HackState7.Unk8)))
|
||||
events ! BundledEnvelope(messages)
|
||||
}
|
||||
|
||||
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.zones.Zone
|
||||
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.message.GenericObjectAction
|
||||
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
|
||||
val (unhackObjects, stillHackedObjects) = PartitionEntries(hackedObjects, now)
|
||||
hackedObjects = stillHackedObjects
|
||||
unhackObjects.foreach { case HackClearActor.HackEntry(target, zone, unk1, unk2, _, _) =>
|
||||
target.Actor ! CommonMessages.ClearHack()
|
||||
zone.LocalEvents ! MessageEnvelope(zone.id, LocalAction.HackClear(target.GUID, unk1, unk2))
|
||||
if (target.Definition == GlobalDefinitions.main_terminal) {
|
||||
ClearVirusFromBuilding(target)
|
||||
unhackObjects
|
||||
.map { case HackClearActor.HackEntry(target, zone, unk1, unk2, _, _) =>
|
||||
target.Actor ! CommonMessages.ClearHack()
|
||||
if (target.Definition == GlobalDefinitions.main_terminal) {
|
||||
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()
|
||||
|
||||
|
|
@ -132,9 +137,7 @@ class HackClearActor() extends Actor {
|
|||
building.virusInstalledBy = None
|
||||
val msg = GenericObjectAction(target.GUID, 60)
|
||||
val events = building.Zone.AvatarEvents
|
||||
building.PlayersInSOI.foreach { player =>
|
||||
events ! MessageEnvelope(player.Name, msg)
|
||||
}
|
||||
events ! BundledEnvelope(building.PlayersInSOI.map { player => MessageEnvelope(player.Name, msg) })
|
||||
building.Actor ! BuildingActor.MapUpdate()
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue