more petience with VehicleSeated; added independent DeadState variable (temporary?); changed conditions of vehicle deconstruction scheduler

This commit is contained in:
FateJH 2018-05-17 00:19:12 -04:00
parent 5e9edd789d
commit 98fc9f5fba
3 changed files with 71 additions and 47 deletions

View file

@ -460,8 +460,6 @@ object Maps {
def Building2() : Unit = { def Building2() : Unit = {
//HART building C //HART building C
LocalBuilding(2, FoundationBuilder(Building.Structure(StructureType.Building))) LocalBuilding(2, FoundationBuilder(Building.Structure(StructureType.Building)))
LocalObject(12, ProximityTerminal.Constructor(repair_silo)) //repair terminal A
LocalObject(13, Terminal.Constructor(repair_silo)) //rearm terminal A //ItemTransaction: ItemTransactionMessage(PlanetSideGUID(2050),Buy,3,25mmbullet,0,PlanetSideGUID(0))
LocalObject(186, Terminal.Constructor(cert_terminal)) LocalObject(186, Terminal.Constructor(cert_terminal))
LocalObject(187, Terminal.Constructor(cert_terminal)) LocalObject(187, Terminal.Constructor(cert_terminal))
LocalObject(188, Terminal.Constructor(cert_terminal)) LocalObject(188, Terminal.Constructor(cert_terminal))
@ -509,8 +507,6 @@ object Maps {
LocalObject(1087, Terminal.Constructor(implant_terminal_interface)) //TODO guid not correct LocalObject(1087, Terminal.Constructor(implant_terminal_interface)) //TODO guid not correct
LocalObject(1088, Terminal.Constructor(implant_terminal_interface)) //TODO guid not correct LocalObject(1088, Terminal.Constructor(implant_terminal_interface)) //TODO guid not correct
LocalObject(1089, Terminal.Constructor(implant_terminal_interface)) //TODO guid not correct LocalObject(1089, Terminal.Constructor(implant_terminal_interface)) //TODO guid not correct
ObjectToBuilding(12, 2)
ObjectToBuilding(13, 2)
ObjectToBuilding(186, 2) ObjectToBuilding(186, 2)
ObjectToBuilding(187, 2) ObjectToBuilding(187, 2)
ObjectToBuilding(188, 2) ObjectToBuilding(188, 2)
@ -652,11 +648,15 @@ object Maps {
def Building51() : Unit = { def Building51() : Unit = {
//air terminal west of HART C //air terminal west of HART C
LocalObject(12, ProximityTerminal.Constructor(repair_silo)) //repair terminal
LocalObject(13, Terminal.Constructor(repair_silo)) //rearm terminal
LocalBuilding(51, FoundationBuilder(Building.Structure(StructureType.Platform))) LocalBuilding(51, FoundationBuilder(Building.Structure(StructureType.Platform)))
LocalObject(304, Terminal.Constructor(dropship_vehicle_terminal)) LocalObject(304, Terminal.Constructor(dropship_vehicle_terminal))
LocalObject(292, LocalObject(292,
VehicleSpawnPad.Constructor(Vector3(3508.9844f, 2895.961f, 92.296875f), Vector3(0f, 0f, 90.0f)) VehicleSpawnPad.Constructor(Vector3(3508.9844f, 2895.961f, 92.296875f), Vector3(0f, 0f, 90.0f))
) )
ObjectToBuilding(12, 51)
ObjectToBuilding(13, 51)
ObjectToBuilding(304, 51) ObjectToBuilding(304, 51)
ObjectToBuilding(292, 51) ObjectToBuilding(292, 51)
TerminalToSpawnPad(304, 292) TerminalToSpawnPad(304, 292)

View file

@ -73,10 +73,12 @@ class WorldSessionActor extends Actor with MDCContextAware {
var delayedProximityTerminalResets : Map[PlanetSideGUID, Cancellable] = Map.empty var delayedProximityTerminalResets : Map[PlanetSideGUID, Cancellable] = Map.empty
var controlled : Option[Int] = None //keep track of avatar's ServerVehicleOverride state var controlled : Option[Int] = None //keep track of avatar's ServerVehicleOverride state
var traveler : Traveler = null var traveler : Traveler = null
var deadState : DeadState.Value = DeadState.Dead
var clientKeepAlive : Cancellable = DefaultCancellable.obj var clientKeepAlive : Cancellable = DefaultCancellable.obj
var progressBarUpdate : Cancellable = DefaultCancellable.obj var progressBarUpdate : Cancellable = DefaultCancellable.obj
var reviveTimer : Cancellable = DefaultCancellable.obj var reviveTimer : Cancellable = DefaultCancellable.obj
var respawnTimer : Cancellable = DefaultCancellable.obj
/** /**
* Convert a boolean value into an integer value. * Convert a boolean value into an integer value.
@ -89,6 +91,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
override def postStop() = { override def postStop() = {
clientKeepAlive.cancel clientKeepAlive.cancel
reviveTimer.cancel reviveTimer.cancel
respawnTimer.cancel
PlayerActionsToCancel() PlayerActionsToCancel()
localService ! Service.Leave() localService ! Service.Leave()
vehicleService ! Service.Leave() vehicleService ! Service.Leave()
@ -111,12 +114,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
if(player.isAlive) { if(player.isAlive) {
//actually being alive or manually deconstructing //actually being alive or manually deconstructing
player.VehicleSeated match { DismountVehicleOnLogOut()
case Some(vehicle_guid) =>
DismountVehicleOnLogOut(vehicle_guid, player_guid)
case None => ;
}
continent.Population ! Zone.Population.Release(avatar) continent.Population ! Zone.Population.Release(avatar)
player.Position = Vector3.Zero //save character before doing this player.Position = Vector3.Zero //save character before doing this
avatarService ! AvatarServiceMessage(player.Continent, AvatarAction.ObjectDelete(player_guid, player_guid)) avatarService ! AvatarServiceMessage(player.Continent, AvatarAction.ObjectDelete(player_guid, player_guid))
@ -148,7 +146,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
player.Position = Vector3.Zero //save character before doing this player.Position = Vector3.Zero //save character before doing this
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(player_guid, player_guid, 0)) avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(player_guid, player_guid, 0))
taskResolver ! GUIDTask.UnregisterAvatar(player)(continent.GUID) taskResolver ! GUIDTask.UnregisterAvatar(player)(continent.GUID)
DismountVehicleOnLogOut(vehicle_guid, player_guid) DismountVehicleOnLogOut()
} }
} }
@ -170,26 +168,27 @@ class WorldSessionActor extends Actor with MDCContextAware {
/** /**
* Vehicle cleanup that is specific to log out behavior. * Vehicle cleanup that is specific to log out behavior.
* @param vehicle_guid the vehicle being occupied
* @param player_guid the player
*/ */
def DismountVehicleOnLogOut(vehicle_guid : PlanetSideGUID, player_guid : PlanetSideGUID) : Unit = { def DismountVehicleOnLogOut() : Unit = {
// Use mountable type instead of Vehicle type to ensure mountables such as implant terminals are correctly dismounted on logout //TODO Will base guns implement Vehicle type? Don't want those to deconstruct
val mountable = continent.GUID(vehicle_guid).get.asInstanceOf[Mountable] (player.VehicleSeated match {
mountable.Seat(mountable.PassengerInSeat(player).get).get.Occupant = None case Some(vehicle_guid) =>
continent.GUID(vehicle_guid)
// If this is a player constructed vehicle then start deconstruction timer case None =>
// todo: Will base guns implement Vehicle type? Don't want those to deconstruct None
continent.GUID(vehicle_guid) match { }) match {
case Some(vehicle : Vehicle) => case Some(vehicle : Vehicle) =>
if(vehicle.Seats.values.count(_.isOccupied) == 0) { vehicle.Seat(vehicle.PassengerInSeat(player).get).get.Occupant = None
vehicleService ! VehicleServiceMessage.DelayedVehicleDeconstruction(vehicle, continent, 600L) //start vehicle decay (10m) if(vehicle.Seats.values.count(_.isOccupied) == 0) {
} vehicleService ! VehicleServiceMessage.DelayedVehicleDeconstruction(vehicle, continent, 600L) //start vehicle decay (10m)
}
vehicleService ! Service.Leave(Some(s"${vehicle.Actor}"))
case Some(mobj : Mountable) =>
mobj.Seat(mobj.PassengerInSeat(player).get).get.Occupant = None
case _ => ; case _ => ;
} }
vehicleService ! Service.Leave(Some(s"${mountable.Actor}"))
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.KickPassenger(player_guid, 0, true, vehicle_guid))
} }
def receive = Initializing def receive = Initializing
@ -1235,11 +1234,13 @@ class WorldSessionActor extends Actor with MDCContextAware {
case Zone.Lattice.SpawnPoint(zone_id, building, spawn_tube) => case Zone.Lattice.SpawnPoint(zone_id, building, spawn_tube) =>
log.info(s"Zone.Lattice.SpawnPoint: spawn point on $zone_id in ${building.Id} @ ${spawn_tube.GUID.guid} selected") log.info(s"Zone.Lattice.SpawnPoint: spawn point on $zone_id in ${building.Id} @ ${spawn_tube.GUID.guid} selected")
respawnTimer.cancel
reviveTimer.cancel reviveTimer.cancel
val sameZone = zone_id == continent.Id val sameZone = zone_id == continent.Id
val backpack = player.isBackpack val backpack = player.isBackpack
val respawnTime : Long = if(sameZone) { 10 } else { 0 } //s val respawnTime : Long = if(sameZone) { 10 } else { 0 } //s
val respawnTimeMillis = respawnTime * 1000 //ms val respawnTimeMillis = respawnTime * 1000 //ms
deadState = DeadState.RespawnTime
sendResponse(AvatarDeadStateMessage(DeadState.RespawnTime, respawnTimeMillis, respawnTimeMillis, Vector3.Zero, player.Faction, true)) sendResponse(AvatarDeadStateMessage(DeadState.RespawnTime, respawnTimeMillis, respawnTimeMillis, Vector3.Zero, player.Faction, true))
val tplayer = if(backpack) { val tplayer = if(backpack) {
RespawnClone(player) //new player RespawnClone(player) //new player
@ -1279,7 +1280,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
} }
import scala.concurrent.duration._ import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.ExecutionContext.Implicits.global
context.system.scheduler.scheduleOnce(respawnTime seconds, target, msg) respawnTimer = context.system.scheduler.scheduleOnce(respawnTime seconds, target, msg)
case Zone.Lattice.NoValidSpawnPoint(zone_number, None) => case Zone.Lattice.NoValidSpawnPoint(zone_number, None) =>
log.warn(s"Zone.Lattice.SpawnPoint: zone $zone_number could not be accessed as requested") log.warn(s"Zone.Lattice.SpawnPoint: zone $zone_number could not be accessed as requested")
@ -1304,6 +1305,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
case InterstellarCluster.GiveWorld(zoneId, zone) => case InterstellarCluster.GiveWorld(zoneId, zone) =>
log.info(s"Zone $zoneId will now load") log.info(s"Zone $zoneId will now load")
avatarService ! Service.Leave(Some(continent.Id))
localService ! Service.Leave(Some(continent.Id))
vehicleService ! Service.Leave(Some(continent.Id))
player.Continent = zoneId player.Continent = zoneId
continent = zone continent = zone
continent.Population ! Zone.Population.Join(avatar) continent.Population ! Zone.Population.Join(avatar)
@ -1362,6 +1366,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
sendResponse(ChangeShortcutBankMessage(guid, 0)) sendResponse(ChangeShortcutBankMessage(guid, 0))
//FavoritesMessage //FavoritesMessage
sendResponse(SetChatFilterMessage(ChatChannel.Local, false, ChatChannel.values.toList)) //TODO will not always be "on" like this sendResponse(SetChatFilterMessage(ChatChannel.Local, false, ChatChannel.values.toList)) //TODO will not always be "on" like this
deadState = DeadState.Alive
sendResponse(AvatarDeadStateMessage(DeadState.Alive, 0,0, tplayer.Position, player.Faction, true)) sendResponse(AvatarDeadStateMessage(DeadState.Alive, 0,0, tplayer.Position, player.Faction, true))
sendResponse(PlanetsideAttributeMessage(guid, 53, 1)) sendResponse(PlanetsideAttributeMessage(guid, 53, 1))
sendResponse(AvatarSearchCriteriaMessage(guid, List(0,0,0,0,0,0))) sendResponse(AvatarSearchCriteriaMessage(guid, List(0,0,0,0,0,0)))
@ -1545,6 +1550,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
log.info("Reticulating splines ...") log.info("Reticulating splines ...")
traveler.zone = continent.Id traveler.zone = continent.Id
StartBundlingPackets() StartBundlingPackets()
avatarService ! Service.Join(continent.Id)
localService ! Service.Join(continent.Id)
vehicleService ! Service.Join(continent.Id)
configZone(continent) configZone(continent)
sendResponse(TimeOfDayMessage(1191182336)) sendResponse(TimeOfDayMessage(1191182336))
@ -1619,9 +1627,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
} }
}) })
StopBundlingPackets() StopBundlingPackets()
avatarService ! Service.Join(player.Continent)
localService ! Service.Join(player.Continent)
vehicleService ! Service.Join(player.Continent)
self ! SetCurrentAvatar(player) self ! SetCurrentAvatar(player)
case msg @ PlayerStateMessageUpstream(avatar_guid, pos, vel, yaw, pitch, yaw_upper, seq_time, unk3, is_crouching, is_jumping, unk4, is_cloaking, unk5, unk6) => case msg @ PlayerStateMessageUpstream(avatar_guid, pos, vel, yaw, pitch, yaw_upper, seq_time, unk3, is_crouching, is_jumping, unk4, is_cloaking, unk5, unk6) =>
@ -1703,6 +1708,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
log.info(s"ReleaseAvatarRequest: ${player.GUID} on ${continent.Id} has released") log.info(s"ReleaseAvatarRequest: ${player.GUID} on ${continent.Id} has released")
reviveTimer.cancel reviveTimer.cancel
player.Release player.Release
deadState = DeadState.Release
sendResponse(AvatarDeadStateMessage(DeadState.Release, 0, 0, player.Position, player.Faction, true)) sendResponse(AvatarDeadStateMessage(DeadState.Release, 0, 0, player.Position, player.Faction, true))
continent.Population ! Zone.Population.Release(avatar) continent.Population ! Zone.Population.Release(avatar)
player.VehicleSeated match { player.VehicleSeated match {
@ -1808,7 +1814,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
} }
if(messagetype == ChatMessageType.CMT_SUICIDE) { if(messagetype == ChatMessageType.CMT_SUICIDE) {
KillPlayer(player) if(player.isAlive && deadState != DeadState.Release) {
KillPlayer(player)
}
} }
if(messagetype == ChatMessageType.CMT_DESTROY) { if(messagetype == ChatMessageType.CMT_DESTROY) {
@ -2404,6 +2412,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
PlayerActionsToCancel() PlayerActionsToCancel()
CancelAllProximityUnits() CancelAllProximityUnits()
player.Release player.Release
deadState = DeadState.Release
sendResponse(AvatarDeadStateMessage(DeadState.Release, 0, 0, player.Position, player.Faction, true)) sendResponse(AvatarDeadStateMessage(DeadState.Release, 0, 0, player.Position, player.Faction, true))
continent.Population ! Zone.Population.Release(avatar) continent.Population ! Zone.Population.Release(avatar)
@ -3972,14 +3981,19 @@ class WorldSessionActor extends Actor with MDCContextAware {
val pos = tplayer.Position val pos = tplayer.Position
val respawnTimer = 300000 //milliseconds val respawnTimer = 300000 //milliseconds
tplayer.Die tplayer.Die
deadState = DeadState.Dead
sendResponse(PlanetsideAttributeMessage(player_guid, 0, 0)) sendResponse(PlanetsideAttributeMessage(player_guid, 0, 0))
sendResponse(PlanetsideAttributeMessage(player_guid, 2, 0)) sendResponse(PlanetsideAttributeMessage(player_guid, 2, 0))
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(player_guid, 0, 0)) avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(player_guid, 0, 0))
sendResponse(DestroyMessage(player_guid, player_guid, PlanetSideGUID(0), pos)) //how many players get this message? sendResponse(DestroyMessage(player_guid, player_guid, PlanetSideGUID(0), pos)) //how many players get this message?
sendResponse(AvatarDeadStateMessage(DeadState.Dead, respawnTimer, respawnTimer, pos, player.Faction, true)) sendResponse(AvatarDeadStateMessage(DeadState.Dead, respawnTimer, respawnTimer, pos, player.Faction, true))
if(tplayer.VehicleSeated.nonEmpty) { if(tplayer.VehicleSeated.nonEmpty) {
continent.GUID(tplayer.VehicleSeated.get) match {
case Some(obj : Vehicle) =>
TotalDriverVehicleControl(obj)
case _ => ;
}
//make player invisible (if not, the cadaver sticks out the side in a seated position) //make player invisible (if not, the cadaver sticks out the side in a seated position)
TotalDriverVehicleControl(continent.GUID(tplayer.VehicleSeated.get).get.asInstanceOf[Vehicle])
sendResponse(PlanetsideAttributeMessage(player_guid, 29, 1)) sendResponse(PlanetsideAttributeMessage(player_guid, 29, 1))
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(player_guid, 29, 1)) avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(player_guid, 29, 1))
} }

View file

@ -33,37 +33,47 @@ class DelayedDeconstructionActor extends Actor {
def receive : Receive = { def receive : Receive = {
case DelayedDeconstructionActor.ScheduleDeconstruction(vehicle, zone, timeAlive) => case DelayedDeconstructionActor.ScheduleDeconstruction(vehicle, zone, timeAlive) =>
trace(s"delayed deconstruction order for $vehicle in $timeAlive") trace(s"delayed deconstruction order for $vehicle in $timeAlive")
vehicles = vehicles :+ DelayedDeconstructionActor.VehicleEntry(vehicle, zone, timeAlive * 1000000000L) val oldHead = vehicles.headOption
if(vehicles.size == 1) { //we were the only entry so the event must be started from scratch val now : Long = System.nanoTime
import scala.concurrent.ExecutionContext.Implicits.global vehicles = (vehicles :+ DelayedDeconstructionActor.VehicleEntry(vehicle, zone, timeAlive * 1000000000L))
monitor = context.system.scheduler.scheduleOnce(DelayedDeconstructionActor.periodicTest, self, DelayedDeconstructionActor.PeriodicTaskCulling) .sortBy(entry => entry.survivalTime - (now - entry.logTime))
if(vehicles.size == 1 || oldHead != vehicles.headOption) { //we were the only entry so the event must be started from scratch
RetimePeriodicTest()
} }
case DelayedDeconstructionActor.UnscheduleDeconstruction(vehicle_guid) => case DelayedDeconstructionActor.UnscheduleDeconstruction(vehicle_guid) =>
//all tasks for this vehicle are cleared from the queue //all tasks for this vehicle are cleared from the queue
//clear any task that is no longer valid by determination of unregistered GUID //clear any task that is no longer valid by determination of unregistered GUID
val before = vehicles.length val before = vehicles.length
vehicles = vehicles.filter(entry => { !entry.vehicle.HasGUID || entry.vehicle.GUID != vehicle_guid }) val now : Long = System.nanoTime
vehicles = vehicles.filter(entry => { entry.vehicle.HasGUID && entry.vehicle.GUID != vehicle_guid })
.sortBy(entry => entry.survivalTime - (now - entry.logTime))
trace(s"attempting to clear deconstruction order for vehicle $vehicle_guid, found ${before - vehicles.length}") trace(s"attempting to clear deconstruction order for vehicle $vehicle_guid, found ${before - vehicles.length}")
if(vehicles.isEmpty) { RetimePeriodicTest()
monitor.cancel
}
case DelayedDeconstructionActor.PeriodicTaskCulling => case DelayedDeconstructionActor.PeriodicTaskCulling =>
//filter the list of deconstruction tasks for any that are need to be triggered //filter the list of deconstruction tasks for any that are need to be triggered
monitor.cancel monitor.cancel
val now : Long = System.nanoTime val now : Long = System.nanoTime
val (vehiclesToDecon, vehiclesRemain) = vehicles.partition(entry => { now - entry.logTime >= entry.survivalTime }) val (vehiclesToDecon, vehiclesRemain) = vehicles.partition(entry => { now - entry.logTime >= entry.survivalTime })
vehicles = vehiclesRemain vehicles = vehiclesRemain.sortBy(_.survivalTime)
trace(s"vehicle culling - ${vehiclesToDecon.length} deconstruction tasks found") trace(s"vehicle culling - ${vehiclesToDecon.length} deconstruction tasks found; ${vehiclesRemain.length} tasks remain")
vehiclesToDecon.foreach(entry => { context.parent ! VehicleServiceMessage.RequestDeleteVehicle(entry.vehicle, entry.zone) }) vehiclesToDecon.foreach(entry => { context.parent ! VehicleServiceMessage.RequestDeleteVehicle(entry.vehicle, entry.zone) })
if(vehiclesRemain.nonEmpty) { RetimePeriodicTest()
import scala.concurrent.ExecutionContext.Implicits.global
monitor = context.system.scheduler.scheduleOnce(DelayedDeconstructionActor.periodicTest, self, DelayedDeconstructionActor.PeriodicTaskCulling)
}
case _ => ; case _ => ;
} }
def RetimePeriodicTest() : Unit = {
monitor.cancel
vehicles.headOption match {
case None => ;
case Some(entry) =>
val retime = math.max(1, entry.survivalTime - (System.nanoTime - entry.logTime)) nanoseconds
import scala.concurrent.ExecutionContext.Implicits.global
monitor = context.system.scheduler.scheduleOnce(retime, self, DelayedDeconstructionActor.PeriodicTaskCulling)
}
}
} }
object DelayedDeconstructionActor { object DelayedDeconstructionActor {