diff --git a/src/main/scala/net/psforever/actors/session/SessionActor.scala b/src/main/scala/net/psforever/actors/session/SessionActor.scala index 4da6c37a8..d4d9cba80 100644 --- a/src/main/scala/net/psforever/actors/session/SessionActor.scala +++ b/src/main/scala/net/psforever/actors/session/SessionActor.scala @@ -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") diff --git a/src/main/scala/net/psforever/objects/Vehicles.scala b/src/main/scala/net/psforever/objects/Vehicles.scala index aed7c017d..c3cee443f 100644 --- a/src/main/scala/net/psforever/objects/Vehicles.scala +++ b/src/main/scala/net/psforever/objects/Vehicles.scala @@ -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 } diff --git a/src/main/scala/net/psforever/objects/vehicles/CargoBehavior.scala b/src/main/scala/net/psforever/objects/vehicles/CargoBehavior.scala index be16cb458..8bff015a4 100644 --- a/src/main/scala/net/psforever/objects/vehicles/CargoBehavior.scala +++ b/src/main/scala/net/psforever/objects/vehicles/CargoBehavior.scala @@ -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 { diff --git a/src/main/scala/net/psforever/objects/vehicles/VehicleControl.scala b/src/main/scala/net/psforever/objects/vehicles/VehicleControl.scala index 93492d76d..62049f764 100644 --- a/src/main/scala/net/psforever/objects/vehicles/VehicleControl.scala +++ b/src/main/scala/net/psforever/objects/vehicles/VehicleControl.scala @@ -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 _ => } diff --git a/src/main/scala/net/psforever/objects/vehicles/VehicleManifest.scala b/src/main/scala/net/psforever/objects/vehicles/VehicleManifest.scala index 2101ff342..87a569e2b 100644 --- a/src/main/scala/net/psforever/objects/vehicles/VehicleManifest.scala +++ b/src/main/scala/net/psforever/objects/vehicles/VehicleManifest.scala @@ -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 = { diff --git a/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala b/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala index 3c73b4162..280715732 100644 --- a/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala +++ b/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala @@ -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 _ => ; } }