From 406e89ea5038069c848af33e43b27a9cf8b23db3 Mon Sep 17 00:00:00 2001 From: Fate-JH Date: Tue, 20 Jan 2026 18:24:13 -0500 Subject: [PATCH] introducing generic event message services; implementing GalaxyService using the generic framework --- .../session/normal/GalaxyHandlerLogic.scala | 25 ++--- .../support/SessionGalaxyHandlers.scala | 6 +- .../session/support/ZoningOperations.scala | 7 +- .../objects/zones/ZoneHotSpotProjector.scala | 13 +-- .../services/CavernRotationService.scala | 20 ++-- .../net/psforever/services/RemoverActor.scala | 2 +- .../net/psforever/services/Service.scala | 23 ----- .../services/avatar/AvatarService.scala | 3 +- .../avatar/AvatarServiceMessage.scala | 5 +- .../avatar/AvatarServiceResponse.scala | 4 +- .../services/base/EventExchange.scala | 16 ++++ .../services/base/GenericEventBus.scala | 27 ++++++ .../services/base/GenericEventService.scala | 72 +++++++++++++++ .../base/GenericEventServiceWithSupport.scala | 51 +++++++++++ .../support/SimilarityComparator.scala | 2 +- .../{ => base}/support/SupportActor.scala | 2 +- .../support/SupportActorCaseConversions.scala | 2 +- .../psforever/services/chat/ChatService.scala | 7 +- .../services/galaxy/GalaxyService.scala | 91 +++---------------- .../galaxy/GalaxyServiceMessage.scala | 41 ++++++++- .../galaxy/GalaxyServiceResponse.scala | 11 ++- .../psforever/services/hart/HartTimer.scala | 10 +- .../services/local/LocalService.scala | 5 +- .../services/local/LocalServiceMessage.scala | 5 +- .../services/local/LocalServiceResponse.scala | 4 +- .../properties/PropertyOverrideManager.scala | 6 +- .../teamwork/SquadServiceMessage.scala | 5 +- .../teamwork/SquadServiceResponse.scala | 4 +- .../teamwork/SquadSubscriptionEntity.scala | 4 +- .../services/vehicle/VehicleService.scala | 3 +- .../vehicle/VehicleServiceMessage.scala | 5 +- .../vehicle/VehicleServiceResponse.scala | 4 +- .../vehicle/support/TurretUpgrader.scala | 2 +- 33 files changed, 309 insertions(+), 178 deletions(-) create mode 100644 src/main/scala/net/psforever/services/base/EventExchange.scala create mode 100644 src/main/scala/net/psforever/services/base/GenericEventBus.scala create mode 100644 src/main/scala/net/psforever/services/base/GenericEventService.scala create mode 100644 src/main/scala/net/psforever/services/base/GenericEventServiceWithSupport.scala rename src/main/scala/net/psforever/services/{ => base}/support/SimilarityComparator.scala (87%) rename src/main/scala/net/psforever/services/{ => base}/support/SupportActor.scala (99%) rename src/main/scala/net/psforever/services/{ => base}/support/SupportActorCaseConversions.scala (96%) diff --git a/src/main/scala/net/psforever/actors/session/normal/GalaxyHandlerLogic.scala b/src/main/scala/net/psforever/actors/session/normal/GalaxyHandlerLogic.scala index fe2d4b873..28804cf8f 100644 --- a/src/main/scala/net/psforever/actors/session/normal/GalaxyHandlerLogic.scala +++ b/src/main/scala/net/psforever/actors/session/normal/GalaxyHandlerLogic.scala @@ -3,9 +3,10 @@ package net.psforever.actors.session.normal import akka.actor.{ActorContext, ActorRef, typed} import net.psforever.actors.session.AvatarActor -import net.psforever.actors.session.support.{GalaxyHandlerFunctions, SessionGalaxyHandlers, SessionData} +import net.psforever.actors.session.support.{GalaxyHandlerFunctions, SessionData, SessionGalaxyHandlers} import net.psforever.packet.game.{BroadcastWarpgateUpdateMessage, FriendsResponse, HotSpotUpdateMessage, ZoneInfoMessage, ZonePopulationUpdateMessage, HotSpotInfo => PacketHotSpotInfo} -import net.psforever.services.galaxy.{GalaxyAction, GalaxyResponse, GalaxyServiceMessage} +import net.psforever.services.base.EventResponse +import net.psforever.services.galaxy.{GalaxyAction, GalaxyServiceMessage} import net.psforever.types.{MemberAction, PlanetSideEmpire} object GalaxyHandlerLogic { @@ -32,9 +33,9 @@ class GalaxyHandlerLogic(val ops: SessionGalaxyHandlers, implicit val context: A /* response handlers */ - def handle(reply: GalaxyResponse.Response): Unit = { + def handle(reply: EventResponse): Unit = { reply match { - case GalaxyResponse.HotSpotUpdate(zone_index, priority, hot_spot_info) => + case GalaxyAction.HotSpotUpdate(zone_index, priority, hot_spot_info) => sendResponse( HotSpotUpdateMessage( zone_index, @@ -43,7 +44,7 @@ class GalaxyHandlerLogic(val ops: SessionGalaxyHandlers, implicit val context: A ) ) - case GalaxyResponse.MapUpdate(msg) => + case GalaxyAction.MapUpdate(msg) => sendResponse(msg) import net.psforever.actors.zone.ZoneActor import net.psforever.zones.Zones @@ -53,7 +54,7 @@ class GalaxyHandlerLogic(val ops: SessionGalaxyHandlers, implicit val context: A case None => } - case GalaxyResponse.UpdateBroadcastPrivileges(zoneId, gateMapId, fromFactions, toFactions) => + case GalaxyAction.UpdateBroadcastPrivileges(zoneId, gateMapId, fromFactions, toFactions) => val faction = player.Faction val from = fromFactions.contains(faction) val to = toFactions.contains(faction) @@ -63,16 +64,16 @@ class GalaxyHandlerLogic(val ops: SessionGalaxyHandlers, implicit val context: A sendResponse(BroadcastWarpgateUpdateMessage(zoneId, gateMapId, faction)) } - case GalaxyResponse.FlagMapUpdate(msg) => + case GalaxyAction.FlagMapUpdate(msg) => sendResponse(msg) - case GalaxyResponse.TransferPassenger(temp_channel, vehicle, _, manifest) => + case GalaxyAction.TransferPassenger(_, temp_channel, vehicle, _, manifest) => sessionLogic.zoning.handleTransferPassenger(temp_channel, vehicle, manifest) - case GalaxyResponse.LockedZoneUpdate(zone, time) => + case GalaxyAction.LockedZoneUpdate(zone, time) => sendResponse(ZoneInfoMessage(zone.Number, empire_status=false, lock_time=time)) - case GalaxyResponse.UnlockedZoneUpdate(zone) => + case GalaxyAction.UnlockedZoneUpdate(zone) => sendResponse(ZoneInfoMessage(zone.Number, empire_status=true, lock_time=0L)) val popBO = 0 val pop = zone.LivePlayers.distinctBy(_.CharId) @@ -81,10 +82,10 @@ class GalaxyHandlerLogic(val ops: SessionGalaxyHandlers, implicit val context: A val popVS = pop.count(_.Faction == PlanetSideEmpire.VS) sendResponse(ZonePopulationUpdateMessage(zone.Number, 414, 138, popTR, 138, popNC, 138, popVS, 138, popBO)) - case GalaxyResponse.LogStatusChange(name) if avatar.people.friend.exists(_.name.equals(name)) => + case GalaxyAction.LogStatusChange(name) if avatar.people.friend.exists(_.name.equals(name)) => avatarActor ! AvatarActor.MemberListRequest(MemberAction.UpdateFriend, name) - case GalaxyResponse.SendResponse(msg) => + case GalaxyAction.SendResponse(msg) => sendResponse(msg) case _ => () diff --git a/src/main/scala/net/psforever/actors/session/support/SessionGalaxyHandlers.scala b/src/main/scala/net/psforever/actors/session/support/SessionGalaxyHandlers.scala index ad7614296..3f01a8ce6 100644 --- a/src/main/scala/net/psforever/actors/session/support/SessionGalaxyHandlers.scala +++ b/src/main/scala/net/psforever/actors/session/support/SessionGalaxyHandlers.scala @@ -3,16 +3,18 @@ package net.psforever.actors.session.support import akka.actor.{ActorContext, ActorRef, typed} import net.psforever.packet.game.FriendsResponse +import net.psforever.services.base.EventResponse + +import scala.annotation.unused // import net.psforever.actors.session.AvatarActor -import net.psforever.services.galaxy.GalaxyResponse trait GalaxyHandlerFunctions extends CommonSessionInterfacingFunctionality { def ops: SessionGalaxyHandlers def handleUpdateIgnoredPlayers(pkt: FriendsResponse): Unit - def handle(reply: GalaxyResponse.Response): Unit + def handle(@unused reply: EventResponse): Unit } class SessionGalaxyHandlers( diff --git a/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala b/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala index a69a4a724..0b8e5924f 100644 --- a/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala +++ b/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala @@ -602,7 +602,7 @@ class ZoningOperations( sendResponse(ReplicationStreamMessage(5, Some(6), Vector.empty)) //clear squad list spawn.initializeFriendsAndIgnoredLists() //the following subscriptions last until character switch/logout - galaxyService ! Service.Join("galaxy") //for galaxy-wide messages + galaxyService ! Service.Join("") //for galaxy-wide messages galaxyService ! Service.Join(s"${avatar.faction}") //for hotspots, etc. sessionLogic.squadService ! Service.Join(s"${avatar.faction}") //channel will be player.Faction sessionLogic.squadService ! Service.Join(s"${avatar.id}") //channel will be player.CharId (in order to work with packets) @@ -1470,10 +1470,7 @@ class ZoningOperations( case Some(manifest) => val toChannel = manifest.file val topLevel = interstellarFerryTopLevelGUID.getOrElse(vehicle.GUID) - galaxyService ! GalaxyServiceMessage( - toChannel, - GalaxyAction.TransferPassenger(player_guid, toChannel, vehicle, topLevel, manifest) - ) + galaxyService ! GalaxyServiceMessage(toChannel, GalaxyAction.TransferPassenger(player_guid, toChannel, vehicle, topLevel, manifest)) vehicle.CargoHolds.values .collect { case hold if hold.isOccupied => diff --git a/src/main/scala/net/psforever/objects/zones/ZoneHotSpotProjector.scala b/src/main/scala/net/psforever/objects/zones/ZoneHotSpotProjector.scala index a22b32314..09c67d47b 100644 --- a/src/main/scala/net/psforever/objects/zones/ZoneHotSpotProjector.scala +++ b/src/main/scala/net/psforever/objects/zones/ZoneHotSpotProjector.scala @@ -5,6 +5,8 @@ import akka.actor.{Actor, ActorRef, Cancellable, Props} import net.psforever.objects.Default import net.psforever.types.{PlanetSideEmpire, Vector3} import net.psforever.services.ServiceManager +import net.psforever.services.galaxy.{GalaxyAction, GalaxyServiceMessage} + import scala.collection.mutable.ListBuffer import scala.concurrent.duration._ @@ -303,12 +305,11 @@ class ZoneHotSpotProjector(zone: Zone, hotspots: ListBuffer[HotSpotInfo], blanki val zoneNumber = zone.Number val hotSpotInfoList = hotSpotInfos.toList affectedFactions.foreach(faction => - galaxy ! Zone.HotSpot.Update( - faction, - zoneNumber, - 1, - ZoneHotSpotProjector.SpecificHotSpotInfo(faction, hotSpotInfoList) - ) + galaxy ! GalaxyServiceMessage(faction.toString, GalaxyAction.HotSpotUpdate( + zoneNumber, + 1, + ZoneHotSpotProjector.SpecificHotSpotInfo(faction, hotSpotInfoList) + )) ) } } diff --git a/src/main/scala/net/psforever/services/CavernRotationService.scala b/src/main/scala/net/psforever/services/CavernRotationService.scala index 824a817b1..102bcd9d9 100644 --- a/src/main/scala/net/psforever/services/CavernRotationService.scala +++ b/src/main/scala/net/psforever/services/CavernRotationService.scala @@ -12,7 +12,7 @@ import net.psforever.objects.Default import net.psforever.objects.serverobject.structures.{Building, WarpGate} import net.psforever.objects.zones.Zone import net.psforever.packet.game.ChatMsg -import net.psforever.services.galaxy.{GalaxyAction, GalaxyResponse, GalaxyServiceMessage, GalaxyServiceResponse} +import net.psforever.services.galaxy.{GalaxyAction, GalaxyServiceMessage, GalaxyServiceResponse} import net.psforever.types.ChatMessageType import net.psforever.util.Config import net.psforever.zones.Zones @@ -557,20 +557,14 @@ class CavernRotationService( val (lockedZones, unlockedZones) = managedZones.partition(_.locked) //borrow GalaxyService response structure, but send to the specific endpoint math.max(0, monitor.start + monitor.duration - curr) unlockedZones.foreach { monitor => - sendToSession ! GalaxyServiceResponse("", GalaxyResponse.UnlockedZoneUpdate(monitor.zone)) + sendToSession ! GalaxyServiceResponse("", GalaxyAction.UnlockedZoneUpdate(monitor.zone)) } val sortedLocked = lockedZones.sortBy(z => z.start) sortedLocked.take(2).foreach { monitor => - sendToSession ! GalaxyServiceResponse( - "", - GalaxyResponse.LockedZoneUpdate(monitor.zone, math.max(0, monitor.start + monitor.duration - curr)) - ) + sendToSession ! GalaxyServiceResponse("", GalaxyAction.LockedZoneUpdate(monitor.zone, math.max(0, monitor.start + monitor.duration - curr))) } sortedLocked.takeRight(2).foreach { monitor => - sendToSession ! GalaxyServiceResponse( - "", - GalaxyResponse.LockedZoneUpdate(monitor.zone, 0L) - ) + sendToSession ! GalaxyServiceResponse("", GalaxyAction.LockedZoneUpdate(monitor.zone, 0L)) } } @@ -654,8 +648,8 @@ class CavernRotationService( val unlocking = managedZones(nextToUnlock) val lockingZone = locking.zone val unlockingZone = unlocking.zone - val fullHoursBetweenRotationsAsHours = timeToCompleteAllRotationsHours.hours - val fullHoursBetweenRotationsAsMillis = fullHoursBetweenRotationsAsHours.toMillis + //val fullHoursBetweenRotationsAsHours = timeToCompleteAllRotationsHours.hours + //val fullHoursBetweenRotationsAsMillis = fullHoursBetweenRotationsAsHours.toMillis val hoursBetweenRotationsAsHours = timeBetweenRotationsHours.hours val prevToLock = nextToLock nextToLock = (nextToLock + 1) % managedZones.size @@ -729,7 +723,7 @@ class CavernRotationService( advanceTimeBy: FiniteDuration, galaxyService: ActorRef ) : Unit = { - val curr = System.currentTimeMillis() + //val curr = System.currentTimeMillis() val advanceByTimeAsMillis = advanceTimeBy.toMillis managedZones.foreach { zone => zone.start = zone.start - advanceByTimeAsMillis diff --git a/src/main/scala/net/psforever/services/RemoverActor.scala b/src/main/scala/net/psforever/services/RemoverActor.scala index d6118dccc..6b7ecb9a7 100644 --- a/src/main/scala/net/psforever/services/RemoverActor.scala +++ b/src/main/scala/net/psforever/services/RemoverActor.scala @@ -5,8 +5,8 @@ import akka.actor.Cancellable import net.psforever.objects.guid.{StraightforwardTask, TaskBundle, TaskWorkflow} import net.psforever.objects.zones.Zone import net.psforever.objects.{Default, PlanetSideGameObject} +import net.psforever.services.base.support.{SimilarityComparator, SupportActor, SupportActorCaseConversions} import net.psforever.types.Vector3 -import net.psforever.services.support.{SimilarityComparator, SupportActor, SupportActorCaseConversions} import scala.concurrent.Future import scala.concurrent.duration._ diff --git a/src/main/scala/net/psforever/services/Service.scala b/src/main/scala/net/psforever/services/Service.scala index 48d7a2f53..19ae064aa 100644 --- a/src/main/scala/net/psforever/services/Service.scala +++ b/src/main/scala/net/psforever/services/Service.scala @@ -1,8 +1,6 @@ // Copyright (c) 2017 PSForever package net.psforever.services -import akka.event.{ActorEventBus, SubchannelClassification} -import akka.util.Subclassification import net.psforever.types.PlanetSideGUID object Service { @@ -14,24 +12,3 @@ object Service { final case class Leave(channel: Option[String] = None) final case class LeaveAll() } - -trait GenericEventBusMsg { - def channel: String -} - -class GenericEventBus[A <: GenericEventBusMsg] extends ActorEventBus with SubchannelClassification { - type Event = A - type Classifier = String - - protected def classify(event: Event): Classifier = event.channel - - protected def subclassification = - new Subclassification[Classifier] { - def isEqual(x: Classifier, y: Classifier) = x == y - def isSubclass(x: Classifier, y: Classifier) = x.startsWith(y) - } - - protected def publish(event: Event, subscriber: Subscriber): Unit = { - subscriber ! event - } -} diff --git a/src/main/scala/net/psforever/services/avatar/AvatarService.scala b/src/main/scala/net/psforever/services/avatar/AvatarService.scala index bbdf1f99a..f76776be9 100644 --- a/src/main/scala/net/psforever/services/avatar/AvatarService.scala +++ b/src/main/scala/net/psforever/services/avatar/AvatarService.scala @@ -7,7 +7,8 @@ import net.psforever.packet.game.ObjectCreateMessage import net.psforever.packet.game.objectcreate.{DroppedItemData, ObjectCreateMessageParent, PlacementData} import net.psforever.types.PlanetSideGUID import net.psforever.services.avatar.support.{CorpseRemovalActor, DroppedItemRemover} -import net.psforever.services.{GenericEventBus, RemoverActor, Service} +import net.psforever.services.base.GenericEventBus +import net.psforever.services.{RemoverActor, Service} class AvatarService(zone: Zone) extends Actor { private val undertaker: ActorRef = context.actorOf(Props[CorpseRemovalActor](), s"${zone.id}-corpse-removal-agent") diff --git a/src/main/scala/net/psforever/services/avatar/AvatarServiceMessage.scala b/src/main/scala/net/psforever/services/avatar/AvatarServiceMessage.scala index e17cfe0aa..11e9ca16a 100644 --- a/src/main/scala/net/psforever/services/avatar/AvatarServiceMessage.scala +++ b/src/main/scala/net/psforever/services/avatar/AvatarServiceMessage.scala @@ -13,6 +13,7 @@ import net.psforever.objects.zones.Zone import net.psforever.packet.PlanetSideGamePacket import net.psforever.packet.game.ImplantAction import net.psforever.packet.game.objectcreate.{ConstructorData, ObjectCreateMessageParent} +import net.psforever.services.base.{EventMessage, EventResponse} import net.psforever.types.{ExoSuitType, ExperienceType, PlanetSideEmpire, PlanetSideGUID, TransactionType, Vector3} import scala.concurrent.duration.FiniteDuration @@ -25,7 +26,9 @@ object AvatarServiceMessage { } object AvatarAction { - sealed trait Action + sealed trait Action extends EventMessage { + def response(): EventResponse = null + } final case class ArmorChanged(player_guid: PlanetSideGUID, suit: ExoSuitType.Value, subtype: Int) extends Action final case class AvatarImplant(player_guid: PlanetSideGUID, action: ImplantAction.Value, implantSlot: Int, status: Int) extends Action diff --git a/src/main/scala/net/psforever/services/avatar/AvatarServiceResponse.scala b/src/main/scala/net/psforever/services/avatar/AvatarServiceResponse.scala index 87560d293..247a1eef8 100644 --- a/src/main/scala/net/psforever/services/avatar/AvatarServiceResponse.scala +++ b/src/main/scala/net/psforever/services/avatar/AvatarServiceResponse.scala @@ -13,7 +13,7 @@ import net.psforever.packet.PlanetSideGamePacket import net.psforever.packet.game.objectcreate.ConstructorData import net.psforever.packet.game.{ImplantAction, ObjectCreateMessage} import net.psforever.types.{ExoSuitType, ExperienceType, PlanetSideEmpire, PlanetSideGUID, TransactionType, Vector3} -import net.psforever.services.GenericEventBusMsg +import net.psforever.services.base.{EventResponse, GenericEventBusMsg} final case class AvatarServiceResponse( channel: String, @@ -22,7 +22,7 @@ final case class AvatarServiceResponse( ) extends GenericEventBusMsg object AvatarResponse { - sealed trait Response + sealed trait Response extends EventResponse final case class ArmorChanged(suit: ExoSuitType.Value, subtype: Int) extends Response final case class AvatarImplant(action: ImplantAction.Value, implantSlot: Int, status: Int) extends Response diff --git a/src/main/scala/net/psforever/services/base/EventExchange.scala b/src/main/scala/net/psforever/services/base/EventExchange.scala new file mode 100644 index 000000000..b566be39b --- /dev/null +++ b/src/main/scala/net/psforever/services/base/EventExchange.scala @@ -0,0 +1,16 @@ +// Copyright (c) 2026 PSForever +package net.psforever.services.base + +trait EventExchange + +trait EventResponse extends EventExchange + +trait EventMessage extends EventExchange { + def response(): EventResponse +} + +trait SelfResponseMessage + extends EventMessage + with EventResponse { + def response(): EventResponse = this +} diff --git a/src/main/scala/net/psforever/services/base/GenericEventBus.scala b/src/main/scala/net/psforever/services/base/GenericEventBus.scala new file mode 100644 index 000000000..72c2c43e3 --- /dev/null +++ b/src/main/scala/net/psforever/services/base/GenericEventBus.scala @@ -0,0 +1,27 @@ +// Copyright (c) 2017 PSForever +package net.psforever.services.base + +import akka.event.{ActorEventBus, SubchannelClassification} +import akka.util.Subclassification + +trait GenericEventBusMsg { + def channel: String +} + +class GenericEventBus[A <: GenericEventBusMsg] extends ActorEventBus with SubchannelClassification { + type Event = A + type Classifier = String + + protected def classify(event: Event): Classifier = event.channel + + protected def subclassification: Subclassification[String] = + new Subclassification[Classifier] { + def isEqual(x: Classifier, y: Classifier): Boolean = x == y + + def isSubclass(x: Classifier, y: Classifier): Boolean = x.startsWith(y) + } + + protected def publish(event: Event, subscriber: Subscriber): Unit = { + subscriber ! event + } +} diff --git a/src/main/scala/net/psforever/services/base/GenericEventService.scala b/src/main/scala/net/psforever/services/base/GenericEventService.scala new file mode 100644 index 000000000..dd4477a87 --- /dev/null +++ b/src/main/scala/net/psforever/services/base/GenericEventService.scala @@ -0,0 +1,72 @@ +// Copyright (c) 2026 PSForever +package net.psforever.services.base + +import akka.actor.Actor +import net.psforever.services.Service +import net.psforever.types.PlanetSideGUID +import org.log4s.Logger + +trait GenericResponseEnvelope + extends GenericEventBusMsg { + def exclude: PlanetSideGUID + def reply: EventResponse +} + +trait GenericMessageEnvelope { + def channel: String + def exclude: PlanetSideGUID + def msg: EventMessage + def response(outChannel: String): GenericResponseEnvelope +} + +abstract class GenericEventService[OUT <: GenericResponseEnvelope](busName: String) + extends Actor { + protected lazy val log: Logger = org.log4s.getLogger(getClass.getSimpleName) + + protected val eventBus = new GenericEventBus[OUT] + + def commonJoinBehavior: Receive = { + case Service.Join(channel) => + val path = formatChannelOnBusName(channel, busName) + val who = sender() + eventBus.subscribe(who, path) + } + + def commonLeaveBehavior: Receive = { + case Service.Leave(None) => + eventBus.unsubscribe(sender()) + + case Service.Leave(Some(channel)) => + val path = formatChannelOnBusName(channel, busName) + eventBus.unsubscribe(sender(), path) + + case Service.LeaveAll() => + eventBus.unsubscribe(sender()) + } + + def receive: Receive = + commonJoinBehavior.orElse(commonLeaveBehavior) + .orElse { + case msg: GenericMessageEnvelope => + compose(msg) + + case msg => () + log.warn(s"Unhandled message $msg from ${sender()}") + } + + protected def compose(msg: GenericMessageEnvelope): Unit = { + eventBus.publish(msg.response(formatChannelOnBusName(msg.channel, busName)).asInstanceOf[OUT]) + } + + def formatChannelOnBusName: (String, String) => String = GenericEventService.BusOnChannelFormat +} + +object GenericEventService { + final def BusOnChannelFormat(channel: String, busName: String): String = { + if (channel.trim.isEmpty) { + s"/$busName" + } else { + s"/$channel/$busName" + } + } +} diff --git a/src/main/scala/net/psforever/services/base/GenericEventServiceWithSupport.scala b/src/main/scala/net/psforever/services/base/GenericEventServiceWithSupport.scala new file mode 100644 index 000000000..0352ab014 --- /dev/null +++ b/src/main/scala/net/psforever/services/base/GenericEventServiceWithSupport.scala @@ -0,0 +1,51 @@ +// Copyright (c) 2026 PSForever +package net.psforever.services.base + +import akka.actor.{ActorContext, ActorRef} + +import scala.annotation.unused + +trait EventServiceSupport { + def label: String + def constructor(@unused context: ActorContext): ActorRef +} + +trait GenericMessageToSupportEnvelope + extends GenericMessageEnvelope { + def toSupport: String + def response(outChannel: String): GenericResponseEnvelope = null +} + +abstract class GenericEventServiceWithSupport[OUT <: GenericResponseEnvelope]( + busName: String, + eventSupportServices: List[EventServiceSupport] + ) + extends GenericEventService[OUT](busName) { + + private val supportServices: Map[String, ActorRef] = + eventSupportServices + .map { supportService => (supportService.label, supportService.constructor(context)) } + .toMap[String, ActorRef] + + private def supportReceive: Receive = { + case msg: GenericMessageToSupportEnvelope => + forwardToSupport(msg) + } + + override def receive: Receive = supportReceive.orElse(super.receive) + + private def forwardToSupport(msg: GenericMessageToSupportEnvelope): Unit = { + supportServices + .get(msg.toSupport) + .map { support => + support.forward(msg) + msg + } + .getOrElse { + log.error(s"support service ${msg.toSupport} was not found - check message routing or service params") + } + if (msg.response(outChannel = "") != null) { + compose(msg) + } + } +} diff --git a/src/main/scala/net/psforever/services/support/SimilarityComparator.scala b/src/main/scala/net/psforever/services/base/support/SimilarityComparator.scala similarity index 87% rename from src/main/scala/net/psforever/services/support/SimilarityComparator.scala rename to src/main/scala/net/psforever/services/base/support/SimilarityComparator.scala index d9ea16a1b..f840500cb 100644 --- a/src/main/scala/net/psforever/services/support/SimilarityComparator.scala +++ b/src/main/scala/net/psforever/services/base/support/SimilarityComparator.scala @@ -1,5 +1,5 @@ // Copyright (c) 2017 PSForever -package net.psforever.services.support +package net.psforever.services.base.support abstract class SimilarityComparator[A <: SupportActor.Entry] { diff --git a/src/main/scala/net/psforever/services/support/SupportActor.scala b/src/main/scala/net/psforever/services/base/support/SupportActor.scala similarity index 99% rename from src/main/scala/net/psforever/services/support/SupportActor.scala rename to src/main/scala/net/psforever/services/base/support/SupportActor.scala index bb52e1f0b..07503ad17 100644 --- a/src/main/scala/net/psforever/services/support/SupportActor.scala +++ b/src/main/scala/net/psforever/services/base/support/SupportActor.scala @@ -1,5 +1,5 @@ // Copyright (c) 2017 PSForever -package net.psforever.services.support +package net.psforever.services.base.support import akka.actor.Actor import net.psforever.objects.PlanetSideGameObject diff --git a/src/main/scala/net/psforever/services/support/SupportActorCaseConversions.scala b/src/main/scala/net/psforever/services/base/support/SupportActorCaseConversions.scala similarity index 96% rename from src/main/scala/net/psforever/services/support/SupportActorCaseConversions.scala rename to src/main/scala/net/psforever/services/base/support/SupportActorCaseConversions.scala index 4a1fedd77..3640cceff 100644 --- a/src/main/scala/net/psforever/services/support/SupportActorCaseConversions.scala +++ b/src/main/scala/net/psforever/services/base/support/SupportActorCaseConversions.scala @@ -1,5 +1,5 @@ // Copyright (c) 2017 PSForever -package net.psforever.services.support +package net.psforever.services.base.support import net.psforever.objects.PlanetSideGameObject import net.psforever.objects.zones.Zone diff --git a/src/main/scala/net/psforever/services/chat/ChatService.scala b/src/main/scala/net/psforever/services/chat/ChatService.scala index 68fc0edbb..e0e2d64f1 100644 --- a/src/main/scala/net/psforever/services/chat/ChatService.scala +++ b/src/main/scala/net/psforever/services/chat/ChatService.scala @@ -6,6 +6,7 @@ import akka.actor.typed.{ActorRef, Behavior} import akka.actor.typed.scaladsl.{AbstractBehavior, ActorContext, Behaviors} import net.psforever.objects.{Session, SessionSource} import net.psforever.packet.game.ChatMsg +import net.psforever.services.base.{EventMessage, EventResponse} import net.psforever.types.{ChatMessageType, PlanetSideEmpire} object ChatService { @@ -17,14 +18,16 @@ object ChatService { new ChatService(context) } - sealed trait Command + sealed trait Command extends EventMessage { + def response(): EventResponse = null + } final case class JoinChannel(actor: ActorRef[MessageResponse], sessionSource: SessionSource, channel: ChatChannel) extends Command final case class LeaveChannel(actor: ActorRef[MessageResponse], channel: ChatChannel) extends Command final case class LeaveAllChannels(actor: ActorRef[MessageResponse]) extends Command final case class Message(session: Session, message: ChatMsg, channel: ChatChannel) extends Command - final case class MessageResponse(session: Session, message: ChatMsg, channel: ChatChannel) + final case class MessageResponse(session: Session, message: ChatMsg, channel: ChatChannel) extends EventResponse } class ChatService(context: ActorContext[ChatService.Command]) extends AbstractBehavior[ChatService.Command](context) { diff --git a/src/main/scala/net/psforever/services/galaxy/GalaxyService.scala b/src/main/scala/net/psforever/services/galaxy/GalaxyService.scala index a526db02e..df9195c5f 100644 --- a/src/main/scala/net/psforever/services/galaxy/GalaxyService.scala +++ b/src/main/scala/net/psforever/services/galaxy/GalaxyService.scala @@ -2,26 +2,25 @@ package net.psforever.services.galaxy import akka.actor.Actor -import net.psforever.objects.zones.Zone -import net.psforever.packet.game.BuildingInfoUpdateMessage -import net.psforever.services.{GenericEventBus, Service} +import net.psforever.services.base.GenericEventBus +import net.psforever.services.Service class GalaxyService extends Actor { private[this] val log = org.log4s.getLogger val GalaxyEvents = new GenericEventBus[GalaxyServiceResponse] + private def correctChannelName(channel: String): String = { + if (channel.isEmpty) { + s"/Galaxy" + } else { + s"/$channel/Galaxy" + } + } + def receive: Receive = { - case Service.Join(faction) if "TRNCVS".containsSlice(faction) => - val path = s"/$faction/Galaxy" - GalaxyEvents.subscribe(sender(), path) - - case Service.Join("galaxy") => - val path = s"/Galaxy" - GalaxyEvents.subscribe(sender(), path) - case Service.Join(channel) => - val path = s"/$channel/Galaxy" + val path = correctChannelName(channel) GalaxyEvents.subscribe(sender(), path) case Service.Leave(None) => @@ -34,72 +33,8 @@ class GalaxyService extends Actor { case Service.LeaveAll() => GalaxyEvents.unsubscribe(sender()) - case GalaxyServiceMessage(forChannel, action) => - action match { - case GalaxyAction.MapUpdate(msg: BuildingInfoUpdateMessage) => - GalaxyEvents.publish( - GalaxyServiceResponse(s"/Galaxy", GalaxyResponse.MapUpdate(msg)) - ) - - case GalaxyAction.UpdateBroadcastPrivileges(zoneId, gateMapId, fromFactions, toFactions) => - GalaxyEvents.publish( - GalaxyServiceResponse( - s"/$forChannel/Galaxy", - GalaxyResponse.UpdateBroadcastPrivileges(zoneId, gateMapId, fromFactions, toFactions) - ) - ) - - case GalaxyAction.FlagMapUpdate(msg) => - GalaxyEvents.publish( - GalaxyServiceResponse(s"/Galaxy", GalaxyResponse.FlagMapUpdate(msg)) - ) - - case GalaxyAction.TransferPassenger(_, temp_channel, vehicle, vehicle_to_delete, manifest) => - GalaxyEvents.publish( - GalaxyServiceResponse( - s"/$forChannel/Galaxy", - GalaxyResponse.TransferPassenger(temp_channel, vehicle, vehicle_to_delete, manifest) - ) - ) - - case GalaxyAction.LockedZoneUpdate(zone, time) => - GalaxyEvents.publish( - GalaxyServiceResponse( - s"/Galaxy", - GalaxyResponse.LockedZoneUpdate(zone, time) - ) - ) - - case GalaxyAction.UnlockedZoneUpdate(zone) => - GalaxyEvents.publish( - GalaxyServiceResponse( - s"/Galaxy", - GalaxyResponse.UnlockedZoneUpdate(zone) - ) - ) - - case GalaxyAction.LogStatusChange(name) => - GalaxyEvents.publish( - GalaxyServiceResponse( - s"/Galaxy", - GalaxyResponse.LogStatusChange(name) - ) - ) - - case GalaxyAction.SendResponse(msg) => - GalaxyEvents.publish( - GalaxyServiceResponse( - s"/Galaxy", - GalaxyResponse.SendResponse(msg) - ) - ) - case _ => ; - } - - case Zone.HotSpot.Update(faction, zone_num, priority, info) => - GalaxyEvents.publish( - GalaxyServiceResponse(s"/$faction/Galaxy", GalaxyResponse.HotSpotUpdate(zone_num, priority, info)) - ) + case msg @ GalaxyServiceMessage(forChannel, _) => + GalaxyEvents.publish(msg.response(correctChannelName(forChannel))) case msg => log.warn(s"Unhandled message $msg from ${sender()}") diff --git a/src/main/scala/net/psforever/services/galaxy/GalaxyServiceMessage.scala b/src/main/scala/net/psforever/services/galaxy/GalaxyServiceMessage.scala index dcdaebfc2..504c014ff 100644 --- a/src/main/scala/net/psforever/services/galaxy/GalaxyServiceMessage.scala +++ b/src/main/scala/net/psforever/services/galaxy/GalaxyServiceMessage.scala @@ -3,22 +3,43 @@ package net.psforever.services.galaxy import net.psforever.objects.Vehicle import net.psforever.objects.vehicles.VehicleManifest -import net.psforever.objects.zones.Zone +import net.psforever.objects.zones.{HotSpotInfo, Zone} import net.psforever.packet.PlanetSideGamePacket import net.psforever.packet.game.{BuildingInfoUpdateMessage, CaptureFlagUpdateMessage} +import net.psforever.services.Service +import net.psforever.services.base.{EventMessage, EventResponse, GenericMessageEnvelope, SelfResponseMessage} import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID} -final case class GalaxyServiceMessage(forChannel: String, actionMessage: GalaxyAction.Action) +final case class GalaxyServiceMessage(channel: String, msg: EventMessage) + extends GenericMessageEnvelope { + def exclude: PlanetSideGUID = Service.defaultPlayerGUID + + def response(outChannel: String): GalaxyServiceResponse = { + GalaxyServiceResponse(outChannel, msg.response()) + } +} object GalaxyServiceMessage { def apply(actionMessage: GalaxyAction.Action): GalaxyServiceMessage = GalaxyServiceMessage("", actionMessage) } object GalaxyAction { - trait Action + trait Action extends EventMessage + trait Response extends EventResponse + + final case class HotSpotUpdate(zone_id: Int, priority: Int, host_spot_info: List[HotSpotInfo]) + extends Action + with Response + with SelfResponseMessage + + final case class MapUpdate(msg: BuildingInfoUpdateMessage) + extends Action + with Response + with SelfResponseMessage - final case class MapUpdate(msg: BuildingInfoUpdateMessage) extends Action final case class FlagMapUpdate(msg: CaptureFlagUpdateMessage) extends Action + with Response + with SelfResponseMessage final case class TransferPassenger( player_guid: PlanetSideGUID, @@ -27,6 +48,8 @@ object GalaxyAction { vehicle_to_delete: PlanetSideGUID, manifest: VehicleManifest ) extends Action + with Response + with SelfResponseMessage final case class UpdateBroadcastPrivileges( zoneId: Int, @@ -34,12 +57,22 @@ object GalaxyAction { fromFactions: Set[PlanetSideEmpire.Value], toFactions: Set[PlanetSideEmpire.Value] ) extends Action + with Response + with SelfResponseMessage final case class LockedZoneUpdate(zone: Zone, timeUntilUnlock: Long) extends Action + with Response + with SelfResponseMessage final case class UnlockedZoneUpdate(zone: Zone) extends Action + with Response + with SelfResponseMessage final case class LogStatusChange(name: String) extends Action + with Response + with SelfResponseMessage final case class SendResponse(msg: PlanetSideGamePacket) extends Action + with Response + with SelfResponseMessage } diff --git a/src/main/scala/net/psforever/services/galaxy/GalaxyServiceResponse.scala b/src/main/scala/net/psforever/services/galaxy/GalaxyServiceResponse.scala index dcaf93817..64d50871c 100644 --- a/src/main/scala/net/psforever/services/galaxy/GalaxyServiceResponse.scala +++ b/src/main/scala/net/psforever/services/galaxy/GalaxyServiceResponse.scala @@ -7,13 +7,16 @@ import net.psforever.objects.zones.{HotSpotInfo, Zone} import net.psforever.packet.PlanetSideGamePacket import net.psforever.packet.game.{BuildingInfoUpdateMessage, CaptureFlagUpdateMessage} import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID} -import net.psforever.services.GenericEventBusMsg +import net.psforever.services.Service +import net.psforever.services.base.{EventResponse, GenericResponseEnvelope} -final case class GalaxyServiceResponse(channel: String, replyMessage: GalaxyResponse.Response) - extends GenericEventBusMsg +final case class GalaxyServiceResponse(channel: String, reply: EventResponse) + extends GenericResponseEnvelope { + def exclude: PlanetSideGUID = Service.defaultPlayerGUID +} object GalaxyResponse { - trait Response + trait Response extends EventResponse final case class HotSpotUpdate(zone_id: Int, priority: Int, host_spot_info: List[HotSpotInfo]) extends Response final case class MapUpdate(msg: BuildingInfoUpdateMessage) extends Response diff --git a/src/main/scala/net/psforever/services/hart/HartTimer.scala b/src/main/scala/net/psforever/services/hart/HartTimer.scala index 3de884fe0..8267e2f76 100644 --- a/src/main/scala/net/psforever/services/hart/HartTimer.scala +++ b/src/main/scala/net/psforever/services/hart/HartTimer.scala @@ -4,8 +4,8 @@ package net.psforever.services.hart import akka.actor.{Actor, ActorRef, Cancellable} import net.psforever.objects.Default import net.psforever.objects.zones.Zone +import net.psforever.services.base.{EventResponse, GenericEventBus, GenericEventBusMsg} import net.psforever.services.local.{LocalAction, LocalServiceMessage} -import net.psforever.services.{GenericEventBus, GenericEventBusMsg} import net.psforever.types.{HartSequence, PlanetSideGUID} import scala.concurrent.duration._ @@ -20,7 +20,7 @@ import scala.concurrent.ExecutionContext.Implicits.global */ class HartTimer(zone: Zone) extends Actor { /** since the system is zone-locked, caching this value is fine */ - val zoneId = zone.id + val zoneId: String = zone.id /** all of the paired HART facility amenities and the shuttle housed in that facility (in that order) */ var padAndShuttlePairs: List[(PlanetSideGUID, PlanetSideGUID)] = List() @@ -45,8 +45,8 @@ class HartTimer(zone: Zone) extends Actor { /** a message bus to which all associated orbital shuttle pads are subscribed */ val padEvents = new GenericEventBus[HartTimer.Command] /** cache common messages */ - val shuttleDockedInThisZone = HartTimer.ShuttleDocked(zoneId) - val shuttleFreeFromDockInThisZone = HartTimer.ShuttleFreeFromDock(zoneId) + val shuttleDockedInThisZone: HartTimer.ShuttleDocked = HartTimer.ShuttleDocked(zoneId) + val shuttleFreeFromDockInThisZone: HartTimer.ShuttleFreeFromDock = HartTimer.ShuttleFreeFromDock(zoneId) /** the behaviors common to both the inert and active operations of the hart */ val commonBehavior: Receive = { @@ -259,7 +259,7 @@ object HartTimer { * to relay instructions back to the individual facility amenity portions of this HART system. * The channel is blank because it does not need special designation. */ - trait Command extends GenericEventBusMsg { def channel: String = "" } + trait Command extends EventResponse with GenericEventBusMsg { def channel: String = "" } /** * Forbid entry through the boartding gantry doors. */ diff --git a/src/main/scala/net/psforever/services/local/LocalService.scala b/src/main/scala/net/psforever/services/local/LocalService.scala index 751dce97b..6ac2eaae0 100644 --- a/src/main/scala/net/psforever/services/local/LocalService.scala +++ b/src/main/scala/net/psforever/services/local/LocalService.scala @@ -8,8 +8,9 @@ import net.psforever.packet.game.{ObjectCreateMessage, TriggeredEffect, Triggere import net.psforever.services.local.support.CaptureFlagManager import net.psforever.types.PlanetSideGUID import net.psforever.services.local.support._ -import net.psforever.services.{GenericEventBus, Service} -import net.psforever.services.support.SupportActor +import net.psforever.services.Service +import net.psforever.services.base.GenericEventBus +import net.psforever.services.base.support.SupportActor class LocalService(zone: Zone) extends Actor { private val doorCloser = context.actorOf( diff --git a/src/main/scala/net/psforever/services/local/LocalServiceMessage.scala b/src/main/scala/net/psforever/services/local/LocalServiceMessage.scala index ced629458..c928a2d3a 100644 --- a/src/main/scala/net/psforever/services/local/LocalServiceMessage.scala +++ b/src/main/scala/net/psforever/services/local/LocalServiceMessage.scala @@ -15,6 +15,7 @@ import net.psforever.packet.PlanetSideGamePacket import net.psforever.packet.game.GenericObjectActionEnum.GenericObjectActionEnum import net.psforever.packet.game.PlanetsideAttributeEnum.PlanetsideAttributeEnum import net.psforever.packet.game.{ChatMsg, DeployableInfo, DeploymentAction, GenericAction, HackState7, TriggeredSound} +import net.psforever.services.base.{EventMessage, EventResponse} import net.psforever.services.hart.HartTimer.OrbitalShuttleEvent import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID, Vector3} @@ -25,7 +26,9 @@ object LocalServiceMessage { } object LocalAction { - trait Action + trait Action extends EventMessage { + def response(): EventResponse = null + } final case class DeployItem(item: Deployable) extends Action final case class DeployableMapIcon( diff --git a/src/main/scala/net/psforever/services/local/LocalServiceResponse.scala b/src/main/scala/net/psforever/services/local/LocalServiceResponse.scala index 8834ab197..a7144fb5a 100644 --- a/src/main/scala/net/psforever/services/local/LocalServiceResponse.scala +++ b/src/main/scala/net/psforever/services/local/LocalServiceResponse.scala @@ -12,7 +12,7 @@ import net.psforever.packet.game.PlanetsideAttributeEnum.PlanetsideAttributeEnum import net.psforever.packet.PlanetSideGamePacket import net.psforever.packet.game._ import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID, Vector3} -import net.psforever.services.GenericEventBusMsg +import net.psforever.services.base.{EventResponse, GenericEventBusMsg} import net.psforever.services.hart.HartTimer.OrbitalShuttleEvent final case class LocalServiceResponse( @@ -22,7 +22,7 @@ final case class LocalServiceResponse( ) extends GenericEventBusMsg object LocalResponse { - trait Response + trait Response extends EventResponse final case class DeployableMapIcon(action: DeploymentAction.Value, deployInfo: DeployableInfo) extends Response final case class DeployableUIFor(obj: DeployedItem.Value) extends Response diff --git a/src/main/scala/net/psforever/services/properties/PropertyOverrideManager.scala b/src/main/scala/net/psforever/services/properties/PropertyOverrideManager.scala index 9af42b969..6ca16e72b 100644 --- a/src/main/scala/net/psforever/services/properties/PropertyOverrideManager.scala +++ b/src/main/scala/net/psforever/services/properties/PropertyOverrideManager.scala @@ -4,7 +4,9 @@ import akka.actor.Actor import net.psforever.packet.game.{GamePropertyTarget, PropertyOverrideMessage} import net.psforever.packet.game.PropertyOverrideMessage.GamePropertyScope import net.psforever.packet.game.objectcreate.ObjectClass +import net.psforever.services.base.{EventMessage, EventResponse} import net.psforever.zones.Zones + import scala.collection.mutable.ListBuffer class PropertyOverrideManager extends Actor { @@ -87,5 +89,7 @@ class PropertyOverrideManager extends Actor { } object PropertyOverrideManager { - final case object GetOverridesMessage + final case object GetOverridesMessage extends EventMessage { + def response(): EventResponse = null + } } diff --git a/src/main/scala/net/psforever/services/teamwork/SquadServiceMessage.scala b/src/main/scala/net/psforever/services/teamwork/SquadServiceMessage.scala index f99942df6..4f6548122 100644 --- a/src/main/scala/net/psforever/services/teamwork/SquadServiceMessage.scala +++ b/src/main/scala/net/psforever/services/teamwork/SquadServiceMessage.scala @@ -5,6 +5,7 @@ import net.psforever.objects.Player import net.psforever.objects.avatar.Certification import net.psforever.objects.zones.Zone import net.psforever.packet.game.{WaypointEventAction, WaypointInfo, SquadAction => PacketSquadAction} +import net.psforever.services.base.{EventMessage, EventResponse} import net.psforever.types.{PlanetSideGUID, SquadRequestType, SquadWaypoint, Vector3} final case class SquadServiceMessage(tplayer: Player, zone: Zone, actionMessage: Any) @@ -15,7 +16,9 @@ object SquadServiceMessage { } object SquadAction { - sealed trait Action + sealed trait Action extends EventMessage { + def response(): EventResponse = null + } final case class InitSquadList() extends Action final case class InitCharId() extends Action diff --git a/src/main/scala/net/psforever/services/teamwork/SquadServiceResponse.scala b/src/main/scala/net/psforever/services/teamwork/SquadServiceResponse.scala index bd2753292..49600cc48 100644 --- a/src/main/scala/net/psforever/services/teamwork/SquadServiceResponse.scala +++ b/src/main/scala/net/psforever/services/teamwork/SquadServiceResponse.scala @@ -6,10 +6,10 @@ import net.psforever.objects.avatar.Certification import net.psforever.objects.teamwork.Squad import net.psforever.packet.game.{SquadDetail, SquadInfo, WaypointEventAction, WaypointInfo} import net.psforever.types.{ChatMessageType, PlanetSideGUID, SquadResponseType, SquadWaypoint} -import net.psforever.services.GenericEventBusMsg +import net.psforever.services.base.{EventResponse, GenericEventBusMsg} final case class SquadServiceResponse(channel: String, exclude: Iterable[Long], response: SquadResponse.Response) - extends GenericEventBusMsg + extends EventResponse with GenericEventBusMsg object SquadServiceResponse { def apply(toChannel: String, response: SquadResponse.Response): SquadServiceResponse = diff --git a/src/main/scala/net/psforever/services/teamwork/SquadSubscriptionEntity.scala b/src/main/scala/net/psforever/services/teamwork/SquadSubscriptionEntity.scala index 104bd5320..af47196b6 100644 --- a/src/main/scala/net/psforever/services/teamwork/SquadSubscriptionEntity.scala +++ b/src/main/scala/net/psforever/services/teamwork/SquadSubscriptionEntity.scala @@ -2,11 +2,11 @@ package net.psforever.services.teamwork import akka.actor.ActorRef -import scala.collection.mutable +import scala.collection.mutable import net.psforever.objects.teamwork.{Squad, SquadFeatures} import net.psforever.packet.game.SquadDetail -import net.psforever.services.GenericEventBus +import net.psforever.services.base.GenericEventBus import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID} class SquadSubscriptionEntity { diff --git a/src/main/scala/net/psforever/services/vehicle/VehicleService.scala b/src/main/scala/net/psforever/services/vehicle/VehicleService.scala index 72168faa0..4ac69bfcc 100644 --- a/src/main/scala/net/psforever/services/vehicle/VehicleService.scala +++ b/src/main/scala/net/psforever/services/vehicle/VehicleService.scala @@ -6,9 +6,10 @@ import net.psforever.objects.serverobject.pad.VehicleSpawnPad import net.psforever.objects.zones.Zone import net.psforever.packet.game.ObjectCreateMessage import net.psforever.packet.game.objectcreate.ObjectCreateMessageParent +import net.psforever.services.base.GenericEventBus import net.psforever.services.vehicle.support.TurretUpgrader import net.psforever.types.DriveState -import net.psforever.services.{GenericEventBus, Service} +import net.psforever.services.Service class VehicleService(zone: Zone) extends Actor { private val turretUpgrade: ActorRef = context.actorOf(Props[TurretUpgrader](), s"${zone.id}-turret-upgrade-agent") diff --git a/src/main/scala/net/psforever/services/vehicle/VehicleServiceMessage.scala b/src/main/scala/net/psforever/services/vehicle/VehicleServiceMessage.scala index 07bb29769..54f6d4e96 100644 --- a/src/main/scala/net/psforever/services/vehicle/VehicleServiceMessage.scala +++ b/src/main/scala/net/psforever/services/vehicle/VehicleServiceMessage.scala @@ -7,6 +7,7 @@ import net.psforever.objects.inventory.InventoryItem import net.psforever.objects.zones.Zone import net.psforever.packet.PlanetSideGamePacket import net.psforever.packet.game.objectcreate.ConstructorData +import net.psforever.services.base.{EventMessage, EventResponse} import net.psforever.types.{BailType, DriveState, PlanetSideGUID, Vector3} final case class VehicleServiceMessage(forChannel: String, actionMessage: VehicleAction.Action) @@ -21,7 +22,9 @@ object VehicleServiceMessage { } object VehicleAction { - trait Action + trait Action extends EventMessage { + def response(): EventResponse = null + } final case class ChangeAmmo( player_guid: PlanetSideGUID, diff --git a/src/main/scala/net/psforever/services/vehicle/VehicleServiceResponse.scala b/src/main/scala/net/psforever/services/vehicle/VehicleServiceResponse.scala index 22e2ed94f..166d12302 100644 --- a/src/main/scala/net/psforever/services/vehicle/VehicleServiceResponse.scala +++ b/src/main/scala/net/psforever/services/vehicle/VehicleServiceResponse.scala @@ -11,7 +11,7 @@ import net.psforever.packet.PlanetSideGamePacket import net.psforever.packet.game.objectcreate.ConstructorData import net.psforever.packet.game.ObjectCreateMessage import net.psforever.types.{BailType, DriveState, PlanetSideGUID, Vector3} -import net.psforever.services.GenericEventBusMsg +import net.psforever.services.base.{EventResponse, GenericEventBusMsg} final case class VehicleServiceResponse( channel: String, @@ -20,7 +20,7 @@ final case class VehicleServiceResponse( ) extends GenericEventBusMsg object VehicleResponse { - trait Response + trait Response extends EventResponse final case class ChangeAmmo( weapon_guid: PlanetSideGUID, diff --git a/src/main/scala/net/psforever/services/vehicle/support/TurretUpgrader.scala b/src/main/scala/net/psforever/services/vehicle/support/TurretUpgrader.scala index bd6e02866..96939203a 100644 --- a/src/main/scala/net/psforever/services/vehicle/support/TurretUpgrader.scala +++ b/src/main/scala/net/psforever/services/vehicle/support/TurretUpgrader.scala @@ -10,7 +10,7 @@ import net.psforever.objects.serverobject.turret.{FacilityTurret, TurretUpgrade, import net.psforever.objects.vehicles.MountedWeapons import net.psforever.objects.zones.Zone import net.psforever.types.PlanetSideGUID -import net.psforever.services.support.{SimilarityComparator, SupportActor, SupportActorCaseConversions} +import net.psforever.services.base.support.{SimilarityComparator, SupportActor, SupportActorCaseConversions} import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage} import scala.concurrent.Future