mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-04-25 05:45:23 +00:00
Splitting single vehicle spawn control process into several subtasks. Vehicle event bus attached to zone objects, especially for interacting with VehicleSpawnControl. Importing SouNourS copy of ServerVehicleOverrideMessage packet and tests.
This commit is contained in:
parent
dbc2ea8084
commit
fde49773cd
22 changed files with 993 additions and 339 deletions
|
|
@ -203,12 +203,29 @@ object PsLogin {
|
|||
)
|
||||
*/
|
||||
|
||||
val continentList = createContinents()
|
||||
val serviceManager = ServiceManager.boot
|
||||
serviceManager ! ServiceManager.Register(RandomPool(50).props(Props[TaskResolver]), "taskResolver")
|
||||
serviceManager ! ServiceManager.Register(Props[AvatarService], "avatar")
|
||||
serviceManager ! ServiceManager.Register(Props[LocalService], "local")
|
||||
serviceManager ! ServiceManager.Register(Props[VehicleService], "vehicle")
|
||||
serviceManager ! ServiceManager.Register(Props(classOf[InterstellarCluster], createContinents()), "galaxy")
|
||||
serviceManager ! ServiceManager.Register(Props(classOf[InterstellarCluster], continentList), "galaxy")
|
||||
|
||||
//attach event bus entry point to each zone
|
||||
import akka.pattern.ask
|
||||
import akka.util.Timeout
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
import scala.concurrent.Future
|
||||
import scala.util.{Failure, Success}
|
||||
implicit val timeout = Timeout(200 milliseconds)
|
||||
val requestVehicleEventBus : Future[ServiceManager.LookupResult] =
|
||||
(ServiceManager.serviceManager ask ServiceManager.Lookup("vehicle")).mapTo[ServiceManager.LookupResult]
|
||||
requestVehicleEventBus.onComplete {
|
||||
case Success(ServiceManager.LookupResult(_, bus)) =>
|
||||
continentList.foreach { _.VehicleEvents = bus }
|
||||
case Failure(_) => ;
|
||||
//TODO how to fail
|
||||
}
|
||||
|
||||
/** Create two actors for handling the login and world server endpoints */
|
||||
loginRouter = Props(new SessionRouter("Login", loginTemplate))
|
||||
|
|
|
|||
|
|
@ -409,6 +409,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
sendResponse(ChildObjectStateMessage(object_guid, pitch, yaw))
|
||||
}
|
||||
|
||||
case VehicleResponse.ConcealPlayer(player_guid) =>
|
||||
sendResponse(GenericObjectActionMessage(player_guid, 36))
|
||||
|
||||
case VehicleResponse.DismountVehicle(unk1, unk2) =>
|
||||
if(tplayer_guid != guid) {
|
||||
sendResponse(DismountVehicleMsg(guid, unk1, unk2))
|
||||
|
|
@ -456,6 +459,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
sendResponse(ObjectAttachMessage(vehicle_guid, guid, seat))
|
||||
}
|
||||
|
||||
case VehicleResponse.RevealPlayer(player_guid) =>
|
||||
//TODO any action will cause the player to appear after the effects of ConcealPlayer
|
||||
|
||||
case VehicleResponse.SeatPermissions(vehicle_guid, seat_group, permission) =>
|
||||
if(tplayer_guid != guid) {
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, seat_group, permission))
|
||||
|
|
@ -1000,46 +1006,30 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, msg.transaction_type, false))
|
||||
}
|
||||
|
||||
case VehicleSpawnPad.ConcealPlayer =>
|
||||
sendResponse(GenericObjectActionMessage(player.GUID, 36))
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ConcealPlayer(player.GUID))
|
||||
|
||||
case VehicleSpawnPad.LoadVehicle(vehicle, _/*pad*/) =>
|
||||
val player_guid = player.GUID
|
||||
val definition = vehicle.Definition
|
||||
val objedtId = definition.ObjectId
|
||||
case VehicleSpawnPad.StartPlayerSeatedInVehicle(vehicle) =>
|
||||
val vehicle_guid = vehicle.GUID
|
||||
val vdata = definition.Packet.ConstructorData(vehicle).get
|
||||
sendResponse(ObjectCreateMessage(objedtId, vehicle_guid, vdata))
|
||||
continent.Transport ! Zone.SpawnVehicle(vehicle)
|
||||
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.LoadVehicle(player_guid, vehicle, objedtId, vehicle_guid, vdata))
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, 22, 1L)) //mount points off?
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, 21, player_guid.guid)) //fte and ownership?
|
||||
//sendResponse(ObjectAttachMessage(vehicle_guid, player_guid, 0))
|
||||
vehicleService ! VehicleServiceMessage.UnscheduleDeconstruction(vehicle_guid) //cancel queue timeout delay
|
||||
vehicleService ! VehicleServiceMessage.DelayedVehicleDeconstruction(vehicle, continent, 21L) //temporary drive away from pad delay
|
||||
vehicle.Actor ! Mountable.TryMount(player, 0)
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, 21, player.GUID.guid)) //fte and ownership?
|
||||
|
||||
case VehicleSpawnPad.PlayerSeatedInVehicle(vehicle) =>
|
||||
vehicleService ! VehicleServiceMessage.DelayedVehicleDeconstruction(vehicle, continent, 21L) //sitting in the vehicle clears the drive away delay
|
||||
val vehicle_guid = vehicle.GUID
|
||||
if(player.VehicleSeated.nonEmpty) {
|
||||
vehicleService ! VehicleServiceMessage.UnscheduleDeconstruction(vehicle_guid)
|
||||
}
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, 22, 0L)) //mount points on?
|
||||
//sendResponse(PlanetsideAttributeMessage(vehicle_guid, 0, vehicle.Definition.MaxHealth)))
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, 68, 0L)) //???
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, 113, 0L)) //???
|
||||
ReloadVehicleAccessPermissions(vehicle)
|
||||
|
||||
case VehicleSpawnPad.SpawnPadBlockedWarning(vehicle, warning_count) =>
|
||||
if(warning_count > 2) {
|
||||
sendResponse(TriggerSoundMessage(TriggeredSound.Unknown14, vehicle.Position, 20, 1f))
|
||||
sendResponse(
|
||||
ChatMsg(ChatMessageType.CMT_TELL, true, "", "\\#FYour vehicle is blocking the spawn pad, and will be deconstructed if not moved.", None)
|
||||
)
|
||||
}
|
||||
case VehicleSpawnPad.ServerVehicleOverrideStart(speed) =>
|
||||
sendResponse(ServerVehicleOverrideMsg.On(speed))
|
||||
|
||||
case VehicleSpawnPad.SpawnPadUnblocked(vehicle_guid) =>
|
||||
//vehicle has moved away from spawn pad after initial spawn
|
||||
vehicleService ! VehicleServiceMessage.UnscheduleDeconstruction(vehicle_guid) //cancel temporary drive away from pad delay
|
||||
case VehicleSpawnPad.ServerVehicleOverrideEnd(speed) =>
|
||||
sendResponse(ServerVehicleOverrideMsg.Off(speed))
|
||||
|
||||
case VehicleSpawnPad.PeriodicReminder(msg) =>
|
||||
sendResponse(ChatMsg(ChatMessageType.CMT_OPEN, true, "", msg, None))
|
||||
|
||||
case ListAccountCharacters =>
|
||||
import net.psforever.objects.definition.converter.CharacterSelectConverter
|
||||
|
|
@ -2753,14 +2743,13 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
new Task() {
|
||||
private val localVehicle = obj
|
||||
private val localPad = pad.Actor
|
||||
private val localAnnounce = vehicleService
|
||||
private val localSession : String = sessionId.toString
|
||||
private val localPlayer = player
|
||||
private val localVehicleService = vehicleService
|
||||
private val localZone = continent
|
||||
|
||||
override def isComplete : Task.Resolution.Value = {
|
||||
if(localVehicle.Actor != ActorRef.noSender) {
|
||||
if(localVehicle.HasGUID) {
|
||||
Task.Resolution.Success
|
||||
}
|
||||
else {
|
||||
|
|
@ -2769,9 +2758,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
|
||||
def Execute(resolver : ActorRef) : Unit = {
|
||||
localAnnounce ! VehicleServiceMessage.GiveActorControl(obj, localSession)
|
||||
localPad ! VehicleSpawnPad.VehicleOrder(localPlayer, localVehicle)
|
||||
localVehicleService ! VehicleServiceMessage.DelayedVehicleDeconstruction(localVehicle, localZone, 60L)
|
||||
resolver ! scala.util.Success(this)
|
||||
}
|
||||
}, List(RegisterVehicle(obj)))
|
||||
|
|
|
|||
|
|
@ -11,12 +11,14 @@ object VehicleResponse {
|
|||
|
||||
final case class Awareness(vehicle_guid : PlanetSideGUID) extends Response
|
||||
final case class ChildObjectState(object_guid : PlanetSideGUID, pitch : Float, yaw : Float) extends Response
|
||||
final case class ConcealPlayer(player_guid : PlanetSideGUID) extends Response
|
||||
final case class DeployRequest(object_guid : PlanetSideGUID, state : DriveState.Value, unk1 : Int, unk2 : Boolean, pos : Vector3) extends Response
|
||||
final case class DismountVehicle(unk1 : Int, unk2 : Boolean) extends Response
|
||||
final case class InventoryState(obj : PlanetSideGameObject, parent_guid : PlanetSideGUID, start : Int, con_data : ConstructorData) extends Response
|
||||
final case class KickPassenger(unk1 : Int, unk2 : Boolean, vehicle_guid : PlanetSideGUID) extends Response
|
||||
final case class LoadVehicle(vehicle : Vehicle, vtype : Int, vguid : PlanetSideGUID, vdata : ConstructorData) extends Response
|
||||
final case class MountVehicle(object_guid : PlanetSideGUID, seat : Int) extends Response
|
||||
final case class RevealPlayer(player_guid : PlanetSideGUID) extends Response
|
||||
final case class SeatPermissions(vehicle_guid : PlanetSideGUID, seat_group : Int, permission : Long) extends Response
|
||||
final case class StowEquipment(vehicle_guid : PlanetSideGUID, slot : Int, itype : Int, iguid : PlanetSideGUID, idata : ConstructorData) extends Response
|
||||
final case class UnloadVehicle(vehicle_guid : PlanetSideGUID) extends Response
|
||||
|
|
|
|||
|
|
@ -2,11 +2,12 @@
|
|||
package services.vehicle
|
||||
|
||||
import akka.actor.{Actor, ActorRef, Props}
|
||||
import services.vehicle.support.{DeconstructionActor, DelayedDeconstructionActor, VehicleContextActor}
|
||||
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
|
||||
import net.psforever.objects.zones.Zone
|
||||
import services.vehicle.support.{DeconstructionActor, DelayedDeconstructionActor}
|
||||
import services.{GenericEventBus, Service}
|
||||
|
||||
class VehicleService extends Actor {
|
||||
private val vehicleContext : ActorRef = context.actorOf(Props[VehicleContextActor], "vehicle-context-root")
|
||||
private val vehicleDecon : ActorRef = context.actorOf(Props[DeconstructionActor], "vehicle-decon-agent")
|
||||
private val vehicleDelayedDecon : ActorRef = context.actorOf(Props[DelayedDeconstructionActor], "vehicle-delayed-decon-agent")
|
||||
vehicleDecon ! DeconstructionActor.RequestTaskResolver
|
||||
|
|
@ -91,14 +92,6 @@ class VehicleService extends Actor {
|
|||
case _ => ;
|
||||
}
|
||||
|
||||
//message to VehicleContext
|
||||
case VehicleServiceMessage.GiveActorControl(vehicle, actorName) =>
|
||||
vehicleContext ! VehicleServiceMessage.GiveActorControl(vehicle, actorName)
|
||||
|
||||
//message to VehicleContext
|
||||
case VehicleServiceMessage.RevokeActorControl(vehicle) =>
|
||||
vehicleContext ! VehicleServiceMessage.RevokeActorControl(vehicle)
|
||||
|
||||
//message to DeconstructionActor
|
||||
case VehicleServiceMessage.RequestDeleteVehicle(vehicle, continent) =>
|
||||
vehicleDecon ! DeconstructionActor.RequestDeleteVehicle(vehicle, continent)
|
||||
|
|
@ -117,6 +110,35 @@ class VehicleService extends Actor {
|
|||
VehicleServiceResponse(s"/$zone_id/Vehicle", Service.defaultPlayerGUID, VehicleResponse.UnloadVehicle(vehicle_guid))
|
||||
)
|
||||
|
||||
//from VehicleSpawnControl
|
||||
case VehicleSpawnPad.ConcealPlayer(player_guid, zone_id) =>
|
||||
VehicleEvents.publish(
|
||||
VehicleServiceResponse(s"/$zone_id/Vehicle", Service.defaultPlayerGUID, VehicleResponse.ConcealPlayer(player_guid))
|
||||
)
|
||||
|
||||
case VehicleSpawnPad.RevealPlayer(player_guid, zone_id) =>
|
||||
VehicleEvents.publish(
|
||||
VehicleServiceResponse(s"/$zone_id/Vehicle", Service.defaultPlayerGUID, VehicleResponse.RevealPlayer(player_guid))
|
||||
)
|
||||
|
||||
//from VehicleSpawnControl
|
||||
case VehicleSpawnPad.LoadVehicle(vehicle, zone) =>
|
||||
val definition = vehicle.Definition
|
||||
val vtype = definition.ObjectId
|
||||
val vguid = vehicle.GUID
|
||||
val vdata = definition.Packet.ConstructorData(vehicle).get
|
||||
zone.Transport ! Zone.Vehicle.Spawn(vehicle)
|
||||
VehicleEvents.publish(
|
||||
VehicleServiceResponse(s"/${zone.Id}/Vehicle", Service.defaultPlayerGUID, VehicleResponse.LoadVehicle(vehicle, vtype, vguid, vdata))
|
||||
)
|
||||
vehicleDelayedDecon ! DelayedDeconstructionActor.UnscheduleDeconstruction(vguid)
|
||||
vehicleDelayedDecon ! DelayedDeconstructionActor.ScheduleDeconstruction(vehicle, zone, 600L) //10min
|
||||
|
||||
//from VehicleSpawnControl
|
||||
case VehicleSpawnPad.DisposeVehicle(vehicle, zone) =>
|
||||
vehicleDelayedDecon ! DelayedDeconstructionActor.UnscheduleDeconstruction(vehicle.GUID)
|
||||
vehicleDecon ! DeconstructionActor.RequestDeleteVehicle(vehicle, zone)
|
||||
|
||||
case msg =>
|
||||
log.info(s"Unhandled message $msg from $sender")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,10 +81,13 @@ class DeconstructionActor extends Actor {
|
|||
vehiclesToScrap.foreach(entry => {
|
||||
val vehicle = entry.vehicle
|
||||
val zone = entry.zone
|
||||
<<<<<<< 18a068c10272376450c412425118c86612af7397
|
||||
vehicle.Position = Vector3.Zero //somewhere it will not disturb anything
|
||||
entry.zone.Transport ! Zone.DespawnVehicle(vehicle)
|
||||
=======
|
||||
vehicle.Position = Vector3.Zero
|
||||
>>>>>>> Splitting single vehicle spawn control process into several subtasks with their own control Actor objects. Importing SouNourS copy of ServerVehicleOverrideMessage packet and tests.
|
||||
entry.zone.Transport ! Zone.Vehicle.Despawn(vehicle)
|
||||
context.parent ! DeconstructionActor.DeleteVehicle(vehicle.GUID, zone.Id) //call up to the main event system
|
||||
context.parent ! VehicleServiceMessage.RevokeActorControl(vehicle) //call up to a sibling manager
|
||||
taskResolver ! DeconstructionTask(vehicle, zone)
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package services.vehicle.support
|
||||
|
||||
import akka.actor.{Actor, ActorRef, Props}
|
||||
import net.psforever.objects.vehicles.VehicleControl
|
||||
import services.vehicle.VehicleServiceMessage
|
||||
|
||||
/**
|
||||
* Provide a context for a `Vehicle` `Actor` - the `VehicleControl`.<br>
|
||||
* <br>
|
||||
* A vehicle can be passed between different zones and, therefore, does not belong to the zone.
|
||||
* A vehicle cna be given to different players and can persist and change though players have gone.
|
||||
* Therefore, also does not belong to `WorldSessionActor`.
|
||||
* A vehicle must anchored to something that exists outside of the `InterstellarCluster` and its agents.<br>
|
||||
* <br>
|
||||
* The only purpose of this `Actor` is to allow vehicles to borrow a context for the purpose of `Actor` creation.
|
||||
* It is also be allowed to be responsible for cleaning up that context.
|
||||
* (In reality, it can be cleaned up anywhere a `PoisonPill` can be sent.)<br>
|
||||
* <br>
|
||||
* This `Actor` is intended to sit on top of the event system that handles broadcast messaging.
|
||||
*/
|
||||
class VehicleContextActor() extends Actor {
|
||||
def receive : Receive = {
|
||||
case VehicleServiceMessage.GiveActorControl(vehicle, actorName) =>
|
||||
vehicle.Actor = context.actorOf(Props(classOf[VehicleControl], vehicle), s"${vehicle.Definition.Name}_$actorName.${System.nanoTime()}")
|
||||
|
||||
case VehicleServiceMessage.RevokeActorControl(vehicle) =>
|
||||
vehicle.Actor ! akka.actor.PoisonPill
|
||||
vehicle.Actor = ActorRef.noSender
|
||||
|
||||
case _ => ;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue