Cargo vehicle Mounting and Gating Fix (#749)

* reorganizing flags that allow for cargo vehicle mounting; eliminating double zone transfer messaging that was interfering in cargo vehicle transfer

* insufficient dismount repaired so that vehicle mounts correctly; vehicle HasSpawned message on deconstruct actually goes somewhere now
This commit is contained in:
Fate-JH 2021-04-07 09:42:19 -04:00 committed by GitHub
parent 430c5d8890
commit ee969b2737
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 79 additions and 58 deletions

View file

@ -559,26 +559,34 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
sendResponse(msg)
case GalaxyResponse.TransferPassenger(temp_channel, vehicle, vehicle_to_delete, manifest) =>
(manifest.passengers.find { case (name, _) => player.Name.equals(name) } match {
case Some((name, index)) if vehicle.Seats(index).occupant.isEmpty =>
vehicle.Seats(index).mount(player)
val playerName = player.Name
log.debug(s"TransferPassenger: $playerName received the summons to transfer to ${vehicle.Zone.id} ...")
(manifest.passengers.find { _.name.equals(playerName) } match {
case Some(entry) if vehicle.Seats(entry.mount).occupant.isEmpty =>
player.VehicleSeated = None
vehicle.Seats(entry.mount).mount(player)
player.VehicleSeated = vehicle.GUID
Some(vehicle)
case Some((name, index)) =>
log.warn(s"TransferPassenger: $player tried to mount seat $index when it was already occupied, and was rebuked")
case Some(entry) if vehicle.Seats(entry.mount).occupant.contains(player) =>
Some(vehicle)
case Some(entry) =>
log.warn(s"TransferPassenger: $playerName tried to mount seat ${entry.mount} during summoning, but it was already occupied, and ${player.Sex.pronounSubject} was rebuked")
None
case None =>
//log.warn(s"TransferPassenger: $playerName is missing from the manifest of a summoning ${vehicle.Definition.Name} from ${vehicle.Zone.id}")
None
}).orElse(manifest.cargo.find { case (name, _) => player.Name.equals(name) } match {
case Some((name, index)) =>
vehicle.CargoHolds(index).occupant match {
case Some(cargo) =>
cargo.Seats(0).occupants.find(_.Name.equals(name))
case None =>
}).orElse {
manifest.cargo.find { _.name.equals(playerName) } match {
case Some(entry) =>
vehicle.CargoHolds(entry.mount).occupant match {
case out @ Some(cargo) if cargo.Seats(0).occupants.exists(_.Name.equals(playerName)) =>
out
case _ =>
None
}
case None =>
None
}) match {
}} match {
case Some(v: Vehicle) =>
galaxyService ! Service.Leave(Some(temp_channel)) //temporary vehicle-specific channel (see above)
deadState = DeadState.Release
@ -2886,6 +2894,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
Some(old_channel)
) //old vehicle-specific channel (was s"${vehicle.Actor}")
galaxyService ! Service.Join(temp_channel) //temporary vehicle-specific channel
log.debug(s"TransferPassengerChannel: ${player.Name} now subscribed to $temp_channel for vehicle gating")
}
case VehicleResponse.KickCargo(vehicle, speed, delay) =>
@ -5800,7 +5809,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
}
def Execute(resolver: ActorRef): Unit = {
log.trace(s"Player $localPlayer is registered")
log.trace(s"Player ${localPlayer.Name} is newly registered")
resolver ! Success(this)
localAnnounce ! NewPlayerLoaded(localPlayer) //alerts WorldSessionActor
}
@ -5990,6 +5999,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
}
def Execute(resolver: ActorRef): Unit = {
log.trace(s"${localDriver.Name} 's vehicle ${localVehicle.Definition.Name} is registered")
localDriver.VehicleSeated = localVehicle.GUID
Vehicles.Own(localVehicle, localDriver)
localAnnounce ! NewPlayerLoaded(localDriver) //alerts WorldSessionActor
@ -6000,7 +6010,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
localAnnounce ! PlayerFailedToLoad(localDriver) //alerts SessionActor
}
},
List(RegisterNewAvatar(driver), GUIDTask.RegisterVehicle(obj)(continent.GUID))
List(GUIDTask.RegisterAvatar(driver)(continent.GUID), GUIDTask.RegisterVehicle(obj)(continent.GUID))
)
}
@ -7012,12 +7022,13 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
//driver
continent.Transport ! Zone.Vehicle.Spawn(vehicle)
//as the driver, we must temporarily exclude ourselves from being in the vehicle during its creation
val seat = vehicle.Seats(0)
seat.unmount(player)
val mount = vehicle.Seats(0)
mount.unmount(player)
player.VehicleSeated = None
val data = vdef.Packet.ConstructorData(vehicle).get
sendResponse(ObjectCreateMessage(vehicle.Definition.ObjectId, vguid, data))
seat.mount(player)
mount.mount(player)
player.VehicleSeated = vguid
Vehicles.Own(vehicle, player)
vehicle.CargoHolds.values
.collect { case hold if hold.isOccupied => hold.occupant.get }
@ -8615,14 +8626,14 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
VehicleAction.TransferPassengerChannel(pguid, s"${vehicle.Actor}", toChannel, vehicle, topLevel)
)
manifest.cargo.foreach {
case ("MISSING_DRIVER", index) =>
case ManifestPassengerEntry("MISSING_DRIVER", index) =>
val cargo = vehicle.CargoHolds(index).occupant.get
log.warn(s"LoadZoneInVehicleAsDriver: ${player.Name} must eject cargo in hold $index; vehicle is missing driver")
CargoBehavior.HandleVehicleCargoDismount(cargo.GUID, cargo, vehicle.GUID, vehicle, false, false, true)
case (name, index) =>
val cargo = vehicle.CargoHolds(index).occupant.get
case entry =>
val cargo = vehicle.CargoHolds(entry.mount).occupant.get
continent.VehicleEvents ! VehicleServiceMessage(
name,
entry.name,
VehicleAction.TransferPassengerChannel(pguid, s"${cargo.Actor}", toChannel, cargo, topLevel)
)
}
@ -8649,9 +8660,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
player.VehicleSeated = vehicle.GUID
player.Continent = zoneId //forward-set the continent id to perform a test
interstellarFerryTopLevelGUID =
if (
manifest.passengers.isEmpty && manifest.cargo.count { case (name, _) => !name.equals("MISSING_DRIVER") } == 0
) {
if (manifest.passengers.isEmpty && manifest.cargo.count { !_.name.equals("MISSING_DRIVER") } == 0) {
//do not delete if vehicle has passengers or cargo
continent.VehicleEvents ! VehicleServiceMessage(
continent.id,
@ -8741,10 +8750,10 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
val cargo = hold.occupant.get
cargo.Continent = toZoneId
//point to the cargo vehicle to instigate cargo vehicle driver transportation
galaxyService ! GalaxyServiceMessage(
toChannel,
GalaxyAction.TransferPassenger(player_guid, toChannel, vehicle, topLevel, manifest)
)
// galaxyService ! GalaxyServiceMessage(
// toChannel,
// GalaxyAction.TransferPassenger(player_guid, toChannel, vehicle, topLevel, manifest)
// )
}
case None =>
log.error(s"LoadZoneTransferPassengerMessages: ${player.Name} expected a manifest for zone transfer; got nothing")

View file

@ -5,7 +5,7 @@ import net.psforever.objects.serverobject.CommonMessages
import net.psforever.objects.serverobject.deploy.Deployment
import net.psforever.objects.serverobject.transfer.TransferContainer
import net.psforever.objects.serverobject.structures.{StructureType, WarpGate}
import net.psforever.objects.vehicles.{CargoBehavior, Utility, UtilityType, VehicleLockState}
import net.psforever.objects.vehicles._
import net.psforever.objects.zones.Zone
import net.psforever.packet.game.TriggeredSound
import net.psforever.types.{DriveState, PlanetSideGUID, Vector3}
@ -192,12 +192,14 @@ object Vehicles {
val vzone = vehicle.Zone
vehicle.PreviousGatingManifest() match {
case Some(manifest) if vzone != manifest.origin =>
val manifestPassengers = manifest.passengers.collect { case (name, _) => name } :+ manifest.driverName
val manifestPassengerResults = manifestPassengers.map { name => vzone.Players.exists(_.name.equals(name)) }
manifestPassengerResults.forall(_ == true) &&
vehicle.CargoHolds.values
.collect { case hold if hold.isOccupied => AllGatedOccupantsInSameZone(hold.occupant.get) }
.forall(_ == true)
val manifestPassengers = manifest.passengers.collect {
case ManifestPassengerEntry(name, _) => name
} :+ manifest.driverName
manifestPassengers.forall { name => vzone.Players.exists(_.name.equals(name)) } &&
vehicle.CargoHolds.values.forall {
case hold if hold.isOccupied => AllGatedOccupantsInSameZone(hold.occupant.get)
case _ => true
}
case _ =>
false
}

View file

@ -113,7 +113,7 @@ object CargoBehavior {
case Some(carrier: Vehicle) =>
HandleCheckCargoMounting(cargoGUID, cargo, carrierGUID, carrier, mountPoint, iteration)
case carrier if iteration > 0 =>
log.error(s"HandleCheckCargoMounting: participant vehicles changed in the middle of a mounting event")
log.warn(s"HandleCheckCargoMounting: participant vehicles changed in the middle of a mounting event")
LogCargoEventMissingVehicleError("HandleCheckCargoMounting: carrier", carrier, carrierGUID)
false
case _ =>
@ -148,8 +148,8 @@ object CargoBehavior {
if (distance <= 64) {
//cargo vehicle is close enough to assume to be physically within the carrier's hold; mount it
log.debug(s"HandleCheckCargoMounting: mounting cargo vehicle in carrier at distance of $distance")
cargo.MountedIn = carrierGUID
hold.mount(cargo)
cargo.MountedIn = carrierGUID
cargo.Velocity = None
zone.VehicleEvents ! VehicleServiceMessage(
s"${cargo.Actor}",
@ -159,7 +159,7 @@ object CargoBehavior {
s"${cargo.Actor}",
VehicleAction.SendResponse(PlanetSideGUID(0), PlanetsideAttributeMessage(cargoGUID, 68, cargo.Shields))
)
val (attachMsg, mountPointMsg) = CargoMountBehaviorForAll(carrier, cargo, mountPoint)
CargoMountBehaviorForAll(carrier, cargo, mountPoint)
false
} else if (distance > 625 || iteration >= 40) {
//vehicles moved too far away or took too long to get into proper position; abort mounting
@ -286,8 +286,8 @@ object CargoBehavior {
//obviously, don't do this
} else if (iteration > 40) {
//cargo vehicle has spent too long not getting far enough away; restore the cargo's mount in the carrier hold
cargo.MountedIn = carrierGUID
hold.mount(cargo)
cargo.MountedIn = carrierGUID
CargoMountBehaviorForAll(carrier, cargo, mountPoint)
false
} else {

View file

@ -301,7 +301,7 @@ class VehicleControl(vehicle: Vehicle)
zone.id,
VehicleAction.UnloadVehicle(Service.defaultPlayerGUID, vehicle, vehicle.GUID)
)
zone.Transport ! Zone.Vehicle.Despawn(vehicle)
zone.Transport.tell(Zone.Vehicle.Despawn(vehicle), zone.Transport)
case _ =>
}

View file

@ -2,11 +2,18 @@
package net.psforever.objects.vehicles
import net.psforever.objects.Vehicle
import net.psforever.objects.serverobject.mount.Seat
import net.psforever.objects.zones.Zone
/**
* na
* A record that records some passenger information.
* @param name the passenger name for direct vehicle passengers;
* the driver name for cargo vehicles
* @param mount the mount index
*/
final case class ManifestPassengerEntry(name: String, mount: Int)
/**
* A record of accounting of the the vehicle's state at a given time.
* @param file the id of this manifest entry;
* used as the channel name for summoning passengers to the vehicle
* after it has been loaded to a new location or to a new zone;
@ -23,30 +30,29 @@ final case class VehicleManifest(
vehicle: Vehicle,
origin: Zone,
driverName: String,
passengers: List[(String, Int)],
cargo: List[(String, Int)]
passengers: List[ManifestPassengerEntry],
cargo: List[ManifestPassengerEntry]
)
object VehicleManifest {
def apply(vehicle: Vehicle): VehicleManifest = {
val driverName = vehicle.Seats(0).occupant match {
case Some(driver) => driver.Name
case None => "MISSING_DRIVER"
}
val passengers = vehicle.Seats.collect {
case (index: Int, seat: Seat) if index > 0 && seat.isOccupied =>
(seat.occupant.get.Name, index)
}
val cargo = vehicle.CargoHolds.collect {
case (index: Int, hold: Cargo) if hold.occupant.nonEmpty =>
hold.occupant.get.Seats(0).occupant match {
case Some(driver) =>
(driver.Name, index)
case None =>
("MISSING_DRIVER", index)
}
}
VehicleManifest(ManifestChannelName(vehicle), vehicle, vehicle.Zone, driverName, passengers.toList, cargo.toList)
val passengers = vehicle.Seats.toList
.filter { case (index, mount) => index > 0 && mount.isOccupied }
.map { case (index, mount) => ManifestPassengerEntry(mount.occupant.get.Name, index) }
val cargo = vehicle.CargoHolds.toList
.collect {
case (index: Int, hold: Cargo) if hold.occupant.nonEmpty =>
hold.occupant.get.Seats(0).occupant match {
case Some(driver) => ManifestPassengerEntry(driver.Name, index)
case None => ManifestPassengerEntry("MISSING_DRIVER", index)
}
}
VehicleManifest(ManifestChannelName(vehicle), vehicle, vehicle.Zone, driverName, passengers, cargo)
}
def ManifestChannelName(vehicle: Vehicle): String = {

View file

@ -57,6 +57,10 @@ class ZoneVehicleActor(zone: Zone, vehicleList: ListBuffer[Vehicle]) extends Act
sender() ! Zone.Vehicle.CanNotDespawn(zone, vehicle, "can not find")
}
case Zone.Vehicle.HasDespawned(_, _) => ;
case Zone.Vehicle.CanNotDespawn(_, _, _) => ;
case _ => ;
}
}