From 9c0a3754d4b86c4d08ed0160909f9622d3dc4ec6 Mon Sep 17 00:00:00 2001 From: Fate-JH Date: Thu, 29 Apr 2021 09:38:51 -0400 Subject: [PATCH] Load Vehicle (#797) * vehicle will not try to introduce itself to zone if already in zone; vehicle spawn pad construction uses generic messages rather than class-specific ones * better seat locking while server controlled * copious amounts of ant deployment check-ery --- .../actor/objects/VehicleSpawnPadTest.scala | 10 +- .../actors/session/SessionActor.scala | 145 ++++++++++-------- .../psforever/objects/GlobalDefinitions.scala | 1 + .../serverobject/pad/VehicleSpawnPad.scala | 6 - .../VehicleSpawnControlLoadVehicle.scala | 49 +++++- .../vehicles/AntTransferBehavior.scala | 27 ++-- .../services/vehicle/VehicleService.scala | 14 -- 7 files changed, 145 insertions(+), 107 deletions(-) diff --git a/server/src/test/scala/actor/objects/VehicleSpawnPadTest.scala b/server/src/test/scala/actor/objects/VehicleSpawnPadTest.scala index 81b3f0a2e..142eb0df4 100644 --- a/server/src/test/scala/actor/objects/VehicleSpawnPadTest.scala +++ b/server/src/test/scala/actor/objects/VehicleSpawnPadTest.scala @@ -36,7 +36,7 @@ class VehicleSpawnControl2Test extends ActorTest { pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle) //order probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ConcealPlayer]) - probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.LoadVehicle]) + probe.expectMsgClass(1 minute, classOf[VehicleServiceMessage]) probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.AttachToRails]) probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.StartPlayerSeatedInVehicle]) vehicle.Seats(0).mount(player) @@ -72,7 +72,7 @@ class VehicleSpawnControl3Test extends ActorTest { case _ => false }) probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ConcealPlayer]) - probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.LoadVehicle]) + probe.expectMsgClass(1 minute, classOf[VehicleServiceMessage]) probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.AttachToRails]) probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.StartPlayerSeatedInVehicle]) vehicle.Seats(0).mount(player) @@ -132,7 +132,7 @@ class VehicleSpawnControl5Test extends ActorTest() { pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle) //order probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ConcealPlayer]) - probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.LoadVehicle]) + probe.expectMsgClass(1 minute, classOf[VehicleServiceMessage]) vehicle.Health = 0 //problem probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.AttachToRails]) probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.DetachFromRails]) @@ -159,7 +159,7 @@ class VehicleSpawnControl6Test extends ActorTest() { pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle) //order probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ConcealPlayer]) - probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.LoadVehicle]) + probe.expectMsgClass(1 minute, classOf[VehicleServiceMessage]) player.Die probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.AttachToRails]) probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.DetachFromRails]) @@ -187,7 +187,7 @@ class VehicleSpawnControl7Test extends ActorTest { pad.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle) //order probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.ConcealPlayer]) - probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.LoadVehicle]) + probe.expectMsgClass(1 minute, classOf[VehicleServiceMessage]) probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.AttachToRails]) probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.StartPlayerSeatedInVehicle]) probe.expectMsgClass(1 minute, classOf[VehicleSpawnPad.DetachFromRails]) diff --git a/src/main/scala/net/psforever/actors/session/SessionActor.scala b/src/main/scala/net/psforever/actors/session/SessionActor.scala index 1b1639073..154d34a39 100644 --- a/src/main/scala/net/psforever/actors/session/SessionActor.scala +++ b/src/main/scala/net/psforever/actors/session/SessionActor.scala @@ -193,7 +193,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con var loadConfZone: Boolean = false var noSpawnPointHere: Boolean = false var usingMedicalTerminal: Option[PlanetSideGUID] = None - var controlled: Option[Int] = None + var serverVehicleControlVelocity: Option[Int] = None var deadState: DeadState.Value = DeadState.Dead val projectiles: Array[Option[Projectile]] = Array.fill[Option[Projectile]](Projectile.rangeUID - Projectile.baseUID)(None) @@ -502,41 +502,45 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con accountPersistence ! AccountPersistenceService.Kick(player.Name, time) case SetZone(zoneId, position) => - PlayerActionsToCancel() - continent.GUID(player.VehicleSeated) match { - case Some(vehicle: Vehicle) if vehicle.MountedIn.isEmpty => - vehicle.PassengerInSeat(player) match { - case Some(0) => - deadState = DeadState.Release // cancel movement updates - vehicle.Position = position - LoadZonePhysicalSpawnPoint(zoneId, position, Vector3.Zero, 0 seconds) - case _ => // not seated as the driver, in which case we can't move - } - case None => - deadState = DeadState.Release // cancel movement updates - player.Position = position - // continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(player.GUID, player.GUID)) - LoadZonePhysicalSpawnPoint(zoneId, position, Vector3.Zero, 0 seconds) - case _ => // seated in something that is not a vehicle or the vehicle is cargo, in which case we can't move + if (serverVehicleControlVelocity.isEmpty) { + PlayerActionsToCancel() + continent.GUID(player.VehicleSeated) match { + case Some(vehicle : Vehicle) if vehicle.MountedIn.isEmpty => + vehicle.PassengerInSeat(player) match { + case Some(0) => + deadState = DeadState.Release // cancel movement updates + vehicle.Position = position + LoadZonePhysicalSpawnPoint(zoneId, position, Vector3.Zero, 0 seconds) + case _ => // not seated as the driver, in which case we can't move + } + case None => + deadState = DeadState.Release // cancel movement updates + player.Position = position + // continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(player.GUID, player.GUID)) + LoadZonePhysicalSpawnPoint(zoneId, position, Vector3.Zero, 0 seconds) + case _ => // seated in something that is not a vehicle or the vehicle is cargo, in which case we can't move + } } case SetPosition(position) => - PlayerActionsToCancel() - continent.GUID(player.VehicleSeated) match { - case Some(vehicle: Vehicle) if vehicle.MountedIn.isEmpty => - vehicle.PassengerInSeat(player) match { - case Some(0) => - deadState = DeadState.Release // cancel movement updates - vehicle.Position = position - LoadZonePhysicalSpawnPoint(continent.id, position, Vector3.z(vehicle.Orientation.z), 0 seconds) - case _ => // not seated as the driver, in which case we can't move - } - case None => - deadState = DeadState.Release // cancel movement updates - player.Position = position - sendResponse(PlayerStateShiftMessage(ShiftState(0, position, player.Orientation.z, None))) - deadState = DeadState.Alive // must be set here - case _ => // seated in something that is not a vehicle or the vehicle is cargo, in which case we can't move + if (serverVehicleControlVelocity.isEmpty) { + PlayerActionsToCancel() + continent.GUID(player.VehicleSeated) match { + case Some(vehicle : Vehicle) if vehicle.MountedIn.isEmpty => + vehicle.PassengerInSeat(player) match { + case Some(0) => + deadState = DeadState.Release // cancel movement updates + vehicle.Position = position + LoadZonePhysicalSpawnPoint(continent.id, position, Vector3.z(vehicle.Orientation.z), 0 seconds) + case _ => // not seated as the driver, in which case we can't move + } + case None => + deadState = DeadState.Release // cancel movement updates + player.Position = position + sendResponse(PlayerStateShiftMessage(ShiftState(0, position, player.Orientation.z, None))) + deadState = DeadState.Alive // must be set here + case _ => // seated in something that is not a vehicle or the vehicle is cargo, in which case we can't move + } } case SetConnectionState(state) => @@ -2762,6 +2766,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con val tplayer_guid = if (player.HasGUID) player.GUID else PlanetSideGUID(0) reply match { case VehicleResponse.AttachToRails(vehicle_guid, pad_guid) => + serverVehicleControlVelocity = Some(0) sendResponse(ObjectAttachMessage(pad_guid, vehicle_guid, 3)) case VehicleResponse.ChildObjectState(object_guid, pitch, yaw) => @@ -2936,7 +2941,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con if (strafe > 1) 0 else speed //strafe or reverse, not both - controlled = Some(reverseSpeed) + serverVehicleControlVelocity = Some(reverseSpeed) sendResponse(ServerVehicleOverrideMsg(true, true, true, false, 0, strafe, reverseSpeed, Some(0))) import scala.concurrent.ExecutionContext.Implicits.global context.system.scheduler.scheduleOnce( @@ -2945,7 +2950,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con VehicleServiceResponse(toChannel, PlanetSideGUID(0), VehicleResponse.KickCargo(vehicle, 0, delay)) ) } else { - controlled = None + serverVehicleControlVelocity = None sendResponse(ServerVehicleOverrideMsg(false, false, false, false, 0, 0, 0, None)) } } @@ -3316,16 +3321,18 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con * only the zone-specific squad members will receive the important messages about their squad member's spawn. */ def RespawnSquadSetup(): Unit = { - squadUI.get(player.CharId) match { - case Some(elem) => - sendResponse(PlanetsideAttributeMessage(player.GUID, 31, squad_supplement_id)) - continent.AvatarEvents ! AvatarServiceMessage( - s"${player.Faction}", - AvatarAction.PlanetsideAttribute(player.GUID, 31, squad_supplement_id) - ) - sendResponse(PlanetsideAttributeMessage(player.GUID, 32, elem.index)) - case _ => - log.warn(s"RespawnSquadSetup: asked to redraw squad information, but ${player.Name} has no squad element for squad $squad_supplement_id") + if (squad_supplement_id > 0) { + squadUI.get(player.CharId) match { + case Some(elem) => + sendResponse(PlanetsideAttributeMessage(player.GUID, 31, squad_supplement_id)) + continent.AvatarEvents ! AvatarServiceMessage( + s"${player.Faction}", + AvatarAction.PlanetsideAttribute(player.GUID, 31, squad_supplement_id) + ) + sendResponse(PlanetsideAttributeMessage(player.GUID, 32, elem.index)) + case _ => + log.warn(s"RespawnSquadSetup: asked to redraw squad information, but ${player.Name} has no squad element for squad $squad_supplement_id") + } } } @@ -5556,7 +5563,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con destinationBuildingGuid, context.self ) - log.info(s"${player.Name} is trying to use a warp gate") + log.info(s"${player.Name} wants to use a warp gate") case Some(wg: WarpGate) if !wg.Active => log.warn(s"WarpgateRequest: ${player.Name} is knocking on an inactive warp gate") @@ -5600,13 +5607,13 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con ) None }) match { + case Some(_) if serverVehicleControlVelocity.nonEmpty => + log.debug( + s"DismountVehicleMsg: ${player.Name} can not dismount from vehicle while server has asserted control; please wait" + ) case Some(obj: Mountable) => obj.PassengerInSeat(player) match { - case Some(0) if controlled.nonEmpty => - log.warn( - s"DismountVehicleMsg: ${player.Name} can not dismount from vehicle as driver while server has asserted control; please wait ..." - ) - case Some(seat_num) => + case Some(seat_num) => obj.Actor ! Mountable.TryDismount(player, seat_num) if (interstellarFerry.isDefined) { //short-circuit the temporary channel for transferring between zones, the player is no longer doing that @@ -5668,11 +5675,12 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con } case msg @ DeployRequestMessage(player_guid, vehicle_guid, deploy_state, unk2, unk3, pos) => - if (player.avatar.vehicle.contains(vehicle_guid)) { - if (player.avatar.vehicle == player.VehicleSeated) { + val vehicle = player.avatar.vehicle + if (vehicle.contains(vehicle_guid)) { + if (vehicle == player.VehicleSeated) { continent.GUID(vehicle_guid) match { case Some(obj: Vehicle) => - log.info(s"${player.Name} is requesting a deployment change for ${obj.Definition.Name}") + log.info(s"${player.Name} is requesting a deployment change for ${obj.Definition.Name} - $deploy_state") obj.Actor ! Deployment.TryDeploymentChange(deploy_state) case _ => @@ -7019,6 +7027,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con progressBarUpdate.cancel() progressBarValue = None lastTerminalOrderFulfillment = true + serverVehicleControlVelocity = None accessedContainer match { case Some(v: Vehicle) => val vguid = v.GUID @@ -7100,7 +7109,9 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con vehicle.Orientation = shiftOrientation.getOrElse(vehicle.Orientation) val vdata = if (seat == 0) { //driver - continent.Transport ! Zone.Vehicle.Spawn(vehicle) + if (vehicle.Zone ne continent) { + continent.Transport ! Zone.Vehicle.Spawn(vehicle) + } //as the driver, we must temporarily exclude ourselves from being in the vehicle during its creation val mount = vehicle.Seats(0) mount.unmount(player) @@ -7738,7 +7749,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con * Set the vehicle to move in reverse */ def ServerVehicleLockReverse(): Unit = { - controlled = Some(0) + serverVehicleControlVelocity = Some(0) sendResponse( ServerVehicleOverrideMsg( lock_accelerator = true, @@ -7759,7 +7770,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con * Set the vehicle to strafe right */ def ServerVehicleLockStrafeRight(): Unit = { - controlled = Some(0) + serverVehicleControlVelocity = Some(0) sendResponse( ServerVehicleOverrideMsg( lock_accelerator = true, @@ -7780,7 +7791,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con * Set the vehicle to strafe left */ def ServerVehicleLockStrafeLeft(): Unit = { - controlled = Some(0) + serverVehicleControlVelocity = Some(0) sendResponse( ServerVehicleOverrideMsg( lock_accelerator = true, @@ -7801,7 +7812,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con * @param vehicle the vehicle being controlled */ def ServerVehicleLock(vehicle: Vehicle): Unit = { - controlled = Some(0) + serverVehicleControlVelocity = Some(0) sendResponse(ServerVehicleOverrideMsg(true, true, false, false, 0, 1, 0, Some(0))) } @@ -7812,7 +7823,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con * @param flight whether the vehicle is ascending or not, if the vehicle is an applicable type */ def ServerVehicleOverride(vehicle: Vehicle, speed: Int = 0, flight: Int = 0): Unit = { - controlled = Some(speed) + serverVehicleControlVelocity = Some(speed) sendResponse(ServerVehicleOverrideMsg(true, true, false, false, flight, 0, speed, Some(0))) } @@ -7824,8 +7835,8 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con * @param flight whether the vehicle is ascending or not, if the vehicle is an applicable type */ def DriverVehicleControl(vehicle: Vehicle, speed: Int = 0, flight: Int = 0): Unit = { - if (controlled.nonEmpty) { - controlled = None + if (serverVehicleControlVelocity.nonEmpty) { + serverVehicleControlVelocity = None sendResponse(ServerVehicleOverrideMsg(false, false, false, true, flight, 0, speed, None)) } } @@ -7837,8 +7848,8 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con * @param vehicle the vehicle */ def TotalDriverVehicleControl(vehicle: Vehicle): Unit = { - if (controlled.nonEmpty) { - controlled = None + if (serverVehicleControlVelocity.nonEmpty) { + serverVehicleControlVelocity = None sendResponse(ServerVehicleOverrideMsg(false, false, false, false, 0, 0, 0, None)) } } @@ -9542,8 +9553,10 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con val projectilePlace = projectiles(projectileIndex) if ( projectilePlace match { - case Some(projectile) => !projectile.isResolved - case None => false + case Some(projectile) => + !projectile.isResolved && System.currentTimeMillis() - projectile.fire_time < projectile.profile.Lifespan.toLong + case None => + false } ) { log.debug( diff --git a/src/main/scala/net/psforever/objects/GlobalDefinitions.scala b/src/main/scala/net/psforever/objects/GlobalDefinitions.scala index fda65d681..0899ba585 100644 --- a/src/main/scala/net/psforever/objects/GlobalDefinitions.scala +++ b/src/main/scala/net/psforever/objects/GlobalDefinitions.scala @@ -6797,6 +6797,7 @@ object GlobalDefinitions { dropship.Seats += 5 -> bailableSeat dropship.Seats += 6 -> bailableSeat dropship.Seats += 7 -> bailableSeat + dropship.Seats += 8 -> bailableSeat dropship.Seats += 9 -> new SeatDefinition() { bailable = true restriction = MaxOnly diff --git a/src/main/scala/net/psforever/objects/serverobject/pad/VehicleSpawnPad.scala b/src/main/scala/net/psforever/objects/serverobject/pad/VehicleSpawnPad.scala index f3c9ceeae..544cf117c 100644 --- a/src/main/scala/net/psforever/objects/serverobject/pad/VehicleSpawnPad.scala +++ b/src/main/scala/net/psforever/objects/serverobject/pad/VehicleSpawnPad.scala @@ -44,12 +44,6 @@ object VehicleSpawnPad { */ final case class RevealPlayer(player_guid: PlanetSideGUID) - /** - * Message to properly introduce the vehicle into the zone. - * @param vehicle the vehicle being spawned - */ - final case class LoadVehicle(vehicle: Vehicle) - /** * Message to attach the vehicle to the spawn pad's lifting platform ("put on rails"). * The attachment process (to the third slot) itself begins autonomous operation of the lifting platform. diff --git a/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlLoadVehicle.scala b/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlLoadVehicle.scala index abe66ac0c..1ad844721 100644 --- a/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlLoadVehicle.scala +++ b/src/main/scala/net/psforever/objects/serverobject/pad/process/VehicleSpawnControlLoadVehicle.scala @@ -1,9 +1,12 @@ // Copyright (c) 2017 PSForever package net.psforever.objects.serverobject.pad.process -import akka.actor.Props -import net.psforever.objects.GlobalDefinitions +import akka.actor.{Cancellable, Props} +import net.psforever.objects.{Default, GlobalDefinitions} import net.psforever.objects.serverobject.pad.{VehicleSpawnControl, VehicleSpawnPad} +import net.psforever.objects.zones.Zone +import net.psforever.services.Service +import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage} import net.psforever.types.Vector3 import scala.concurrent.ExecutionContext.Implicits.global @@ -25,6 +28,13 @@ class VehicleSpawnControlLoadVehicle(pad: VehicleSpawnPad) extends VehicleSpawnC val railJack = context.actorOf(Props(classOf[VehicleSpawnControlRailJack], pad), s"${context.parent.path.name}-rails") + var temp: Cancellable = Default.Cancellable + + override def postStop() : Unit = { + temp.cancel() + super.postStop() + } + def receive: Receive = { case order @ VehicleSpawnControl.Order(driver, vehicle) => if (driver.Continent == pad.Continent && vehicle.Health > 0 && driver.isAlive) { @@ -33,17 +43,48 @@ class VehicleSpawnControlLoadVehicle(pad: VehicleSpawnPad) extends VehicleSpawnC if (GlobalDefinitions.isFlightVehicle(vehicle.Definition)) 9 else 5 ) //appear below the trench and doors vehicle.Cloaked = vehicle.Definition.CanCloak && driver.Cloaked - pad.Zone.VehicleEvents ! VehicleSpawnPad.LoadVehicle(vehicle) - context.system.scheduler.scheduleOnce(100 milliseconds, railJack, order) + pad.Zone.Transport.tell(Zone.Vehicle.Spawn(vehicle), self) + temp = context.system.scheduler.scheduleOnce( + delay = 100 milliseconds, + self, + VehicleSpawnControlLoadVehicle.WaitOnSpawn(order) + ) } else { trace("owner lost or vehicle in poor condition; abort order fulfillment") VehicleSpawnControl.DisposeVehicle(order.vehicle, pad.Zone) context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder } + case Zone.Vehicle.HasSpawned(zone, vehicle) => + val definition = vehicle.Definition + val vtype = definition.ObjectId + val vguid = vehicle.GUID + val vdata = definition.Packet.ConstructorData(vehicle).get + zone.VehicleEvents ! VehicleServiceMessage( + zone.id, + VehicleAction.LoadVehicle(Service.defaultPlayerGUID, vehicle, vtype, vguid, vdata) + ) + + case VehicleSpawnControlLoadVehicle.WaitOnSpawn(order) => + if (pad.Zone.Vehicles.contains(order.vehicle)) { + railJack ! order + } else { + VehicleSpawnControl.DisposeVehicle(order.vehicle, pad.Zone) + context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder + } + + case Zone.Vehicle.CanNotSpawn(_, _, reason) => + trace(s"vehicle $reason; abort order fulfillment") + temp.cancel() + context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder + case msg @ (VehicleSpawnControl.ProcessControl.Reminder | VehicleSpawnControl.ProcessControl.GetNewOrder) => context.parent ! msg case _ => ; } } + +object VehicleSpawnControlLoadVehicle { + private case class WaitOnSpawn(order: VehicleSpawnControl.Order) +} diff --git a/src/main/scala/net/psforever/objects/vehicles/AntTransferBehavior.scala b/src/main/scala/net/psforever/objects/vehicles/AntTransferBehavior.scala index 75f09a623..bb8f43c60 100644 --- a/src/main/scala/net/psforever/objects/vehicles/AntTransferBehavior.scala +++ b/src/main/scala/net/psforever/objects/vehicles/AntTransferBehavior.scala @@ -58,7 +58,7 @@ trait AntTransferBehavior extends TransferBehavior with NtuStorageBehavior { ntuChargingTick.cancel() val obj = ChargeTransferObject //log.trace(s"NtuCharging: Vehicle $guid is charging NTU capacitor.") - if (obj.NtuCapacitor < obj.Definition.MaxNtuCapacitor) { + if (obj.NtuCapacitor < obj.Definition.MaxNtuCapacitor && obj.DeploymentState == DriveState.Deployed) { //charging panelAnimationFunc = InitialCharge transferTarget = Some(target) @@ -96,7 +96,7 @@ trait AntTransferBehavior extends TransferBehavior with NtuStorageBehavior { def HandleDischargingEvent(target: TransferContainer): Boolean = { //log.trace(s"NtuDischarging: Vehicle $guid is discharging NTU into silo $silo_guid") val obj = ChargeTransferObject - if (obj.NtuCapacitor > 0) { + if (obj.NtuCapacitor > 0 && obj.DeploymentState == DriveState.Deployed) { panelAnimationFunc = InitialDischarge transferTarget = Some(target) transferEvent = TransferBehavior.Event.Discharging @@ -177,8 +177,8 @@ trait AntTransferBehavior extends TransferBehavior with NtuStorageBehavior { def HandleNtuOffer(sender: ActorRef, src: NtuContainer): Unit = {} def HandleNtuRequest(sender: ActorRef, min: Float, max: Float): Unit = { - if (transferEvent == TransferBehavior.Event.Discharging) { - val chargeable = ChargeTransferObject + val chargeable = ChargeTransferObject + if (chargeable.DeploymentState == DriveState.Deployed && transferEvent == TransferBehavior.Event.Discharging) { val chargeToDeposit = if (min == 0) { transferTarget match { case Some(silo: ResourceSilo) => @@ -194,18 +194,21 @@ trait AntTransferBehavior extends TransferBehavior with NtuStorageBehavior { chargeable.NtuCapacitor -= chargeToDeposit UpdateNtuUI(chargeable) sender ! Ntu.Grant(chargeable, chargeToDeposit) + } else { + TryStopChargingEvent(chargeable) + sender ! Ntu.Grant(chargeable, 0) } } def HandleNtuGrant(sender: ActorRef, src: NtuContainer, amount: Float): Unit = { - if (transferEvent == TransferBehavior.Event.Charging) { - val obj = ChargeTransferObject - if (ReceiveAndDepositUntilFull(obj, amount)) { - panelAnimationFunc() - } else { - TryStopChargingEvent(obj) - sender ! Ntu.Request(0, 0) - } + val obj = ChargeTransferObject + if (obj.DeploymentState == DriveState.Deployed && + transferEvent == TransferBehavior.Event.Charging && + ReceiveAndDepositUntilFull(obj, amount)) { + panelAnimationFunc() + } else { + TryStopChargingEvent(obj) + sender ! Ntu.Request(0, 0) } } } diff --git a/src/main/scala/net/psforever/services/vehicle/VehicleService.scala b/src/main/scala/net/psforever/services/vehicle/VehicleService.scala index 5edb6c04d..0e5269bd1 100644 --- a/src/main/scala/net/psforever/services/vehicle/VehicleService.scala +++ b/src/main/scala/net/psforever/services/vehicle/VehicleService.scala @@ -338,20 +338,6 @@ class VehicleService(zone: Zone) extends Actor { ) ) - case VehicleSpawnPad.LoadVehicle(vehicle) => - 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) - ) - ) - //correspondence from WorldSessionActor case VehicleServiceMessage.AMSDeploymentChange(_) => VehicleEvents.publish(