mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-13 15:34:42 +00:00
Playtest crash fixes (#265)
* Fix BIUM getting hack time in nanoseconds instead of milliseconds * Remove blocking call to calculate remaining hack time on CC * Fix HackClearActor crash when trying to schedule next check when no hacked objects are left * Potential fix for client disconnect when looting a corpse that gets removed
This commit is contained in:
parent
ef65c91740
commit
0730c0deb6
6 changed files with 40 additions and 39 deletions
|
|
@ -1,6 +1,8 @@
|
||||||
// Copyright (c) 2017 PSForever
|
// Copyright (c) 2017 PSForever
|
||||||
package net.psforever.objects.serverobject.structures
|
package net.psforever.objects.serverobject.structures
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
import akka.actor.ActorContext
|
import akka.actor.ActorContext
|
||||||
import net.psforever.objects.GlobalDefinitions
|
import net.psforever.objects.GlobalDefinitions
|
||||||
import net.psforever.objects.definition.ObjectDefinition
|
import net.psforever.objects.definition.ObjectDefinition
|
||||||
|
|
@ -66,12 +68,13 @@ class Building(private val building_guid : Int, private val map_id : Int, privat
|
||||||
case _ => //we have no silo; we have unlimited power
|
case _ => //we have no silo; we have unlimited power
|
||||||
10
|
10
|
||||||
}
|
}
|
||||||
//if we have a capture terminal, get the hack status & time from control console if it exists
|
//if we have a capture terminal, get the hack status & time (in milliseconds) from control console if it exists
|
||||||
val (hacking, hackingFaction, hackTime) : (Boolean, PlanetSideEmpire.Value, Long) = amenities.find(_.Definition == GlobalDefinitions.capture_terminal) match {
|
val (hacking, hackingFaction, hackTime) : (Boolean, PlanetSideEmpire.Value, Long) = amenities.find(_.Definition == GlobalDefinitions.capture_terminal) match {
|
||||||
case Some(obj: CaptureTerminal with Hackable) =>
|
case Some(obj: CaptureTerminal with Hackable) =>
|
||||||
obj.HackedBy match {
|
obj.HackedBy match {
|
||||||
case Some(Hackable.HackInfo(_, _, hfaction, _, start, length)) =>
|
case Some(Hackable.HackInfo(_, _, hfaction, _, start, length)) =>
|
||||||
(true, hfaction, math.max(0, start + length - System.nanoTime))
|
val hack_time_remaining_ms = TimeUnit.MILLISECONDS.convert(math.max(0, start + length - System.nanoTime), TimeUnit.NANOSECONDS)
|
||||||
|
(true, hfaction, hack_time_remaining_ms)
|
||||||
case _ =>
|
case _ =>
|
||||||
(false, PlanetSideEmpire.NEUTRAL, 0L)
|
(false, PlanetSideEmpire.NEUTRAL, 0L)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ import scodec.codecs._
|
||||||
* <li>196608 - 262143 - VS</li>
|
* <li>196608 - 262143 - VS</li>
|
||||||
* <li>17039360 - CC Resecured</li>
|
* <li>17039360 - CC Resecured</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
|
* <br>These values seem to correspond to the following data structure: Time left - 2 bytes, faction - 1 byte (1-4), isResecured - 1 byte (0-1)<br>
|
||||||
* `24 - Learn certifications with value :`<br>
|
* `24 - Learn certifications with value :`<br>
|
||||||
* 01 : Medium Assault<br>
|
* 01 : Medium Assault<br>
|
||||||
* 02 : Heavy Assault<br>
|
* 02 : Heavy Assault<br>
|
||||||
|
|
|
||||||
|
|
@ -208,9 +208,6 @@ class LocalService extends Actor {
|
||||||
case scala.util.Failure(_) => log.warn(s"LocalService Failed to get zone when hack timeout was reached")
|
case scala.util.Failure(_) => log.warn(s"LocalService Failed to get zone when hack timeout was reached")
|
||||||
}
|
}
|
||||||
|
|
||||||
case HackCaptureActor.GetHackTimeRemainingNanos(capture_console_guid) =>
|
|
||||||
hackCapturer forward HackCaptureActor.GetHackTimeRemainingNanos(capture_console_guid)
|
|
||||||
|
|
||||||
//message to Engineer
|
//message to Engineer
|
||||||
case LocalServiceMessage.Deployables(msg) =>
|
case LocalServiceMessage.Deployables(msg) =>
|
||||||
engineer forward msg
|
engineer forward msg
|
||||||
|
|
|
||||||
|
|
@ -71,16 +71,6 @@ class HackCaptureActor extends Actor {
|
||||||
|
|
||||||
// Restart the timer in case the object we just removed was the next one scheduled
|
// Restart the timer in case the object we just removed was the next one scheduled
|
||||||
RestartTimer()
|
RestartTimer()
|
||||||
|
|
||||||
case HackCaptureActor.GetHackTimeRemainingNanos(capture_console_guid) =>
|
|
||||||
hackedObjects.find(_.target.GUID == capture_console_guid) match {
|
|
||||||
case Some(obj: HackCaptureActor.HackEntry) =>
|
|
||||||
val time_left: Long = obj.duration.toNanos - (System.nanoTime - obj.hack_timestamp)
|
|
||||||
sender ! time_left
|
|
||||||
case _ =>
|
|
||||||
log.warn(s"Couldn't find capture terminal guid $capture_console_guid in hackedObjects list")
|
|
||||||
sender ! 0L
|
|
||||||
}
|
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,9 +100,6 @@ object HackCaptureActor {
|
||||||
|
|
||||||
final case class ClearHack(target : CaptureTerminal, zone : Zone)
|
final case class ClearHack(target : CaptureTerminal, zone : Zone)
|
||||||
|
|
||||||
final case class GetHackTimeRemainingNanos(capture_console_guid: PlanetSideGUID)
|
|
||||||
|
|
||||||
|
|
||||||
private final case class ProcessCompleteHacks()
|
private final case class ProcessCompleteHacks()
|
||||||
|
|
||||||
private final case class HackEntry(target : PlanetSideServerObject with Hackable, zone : Zone, unk1 : Long, unk2 : Long, duration: FiniteDuration, hack_timestamp : Long)
|
private final case class HackEntry(target : PlanetSideServerObject with Hackable, zone : Zone, unk1 : Long, unk2 : Long, duration: FiniteDuration, hack_timestamp : Long)
|
||||||
|
|
|
||||||
|
|
@ -66,11 +66,17 @@ class HackClearActor() extends Actor {
|
||||||
if(hackedObjects.length != 0) {
|
if(hackedObjects.length != 0) {
|
||||||
val now = System.nanoTime()
|
val now = System.nanoTime()
|
||||||
val (unhackObjects, stillHackedObjects) = PartitionEntries(hackedObjects, now)
|
val (unhackObjects, stillHackedObjects) = PartitionEntries(hackedObjects, now)
|
||||||
val short_timeout : FiniteDuration = math.max(1, stillHackedObjects.head.duration - (now - stillHackedObjects.head.time)) nanoseconds
|
|
||||||
|
|
||||||
log.warn(s"Still items left in hacked objects list. Checking again in ${short_timeout.toSeconds} seconds")
|
stillHackedObjects.headOption match {
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
case Some(hackEntry) =>
|
||||||
clearTrigger = context.system.scheduler.scheduleOnce(short_timeout, self, HackClearActor.TryClearHacks())
|
val short_timeout : FiniteDuration = math.max(1, hackEntry.duration - (now - hackEntry.time)) nanoseconds
|
||||||
|
|
||||||
|
log.info(s"HackClearActor: Still items left in hacked objects list. Checking again in ${short_timeout.toSeconds} seconds")
|
||||||
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
|
clearTrigger = context.system.scheduler.scheduleOnce(short_timeout, self, HackClearActor.TryClearHacks())
|
||||||
|
case None => log.info("HackClearActor: No objects left in hacked objects list. Not rescheduling check.")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1284,23 +1284,27 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
value = 17039360L
|
value = 17039360L
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
continent.GUID(target_guid) match {
|
||||||
val future = ask(localService, HackCaptureActor.GetHackTimeRemainingNanos(target_guid))(1 second)
|
case Some(capture_terminal: Hackable) =>
|
||||||
val time = Await.result(future, 1 second).asInstanceOf[Long]
|
capture_terminal.HackedBy match {
|
||||||
// todo: blocking call. Not good.
|
case Some(Hackable.HackInfo(_, _, hfaction, _, start, length)) =>
|
||||||
val hack_time_remaining_ms = TimeUnit.MILLISECONDS.convert(time, TimeUnit.NANOSECONDS)
|
val hack_time_remaining_ms = TimeUnit.MILLISECONDS.convert(math.max(0, start + length - System.nanoTime), TimeUnit.NANOSECONDS)
|
||||||
val deciseconds_remaining = (hack_time_remaining_ms / 100)
|
val deciseconds_remaining = (hack_time_remaining_ms / 100)
|
||||||
val hacking_faction = continent.GUID(target_guid).get.asInstanceOf[Hackable].HackedBy.get.hackerFaction
|
|
||||||
// See PlanetSideAttributeMessage #20 documentation for an explanation of how the timer is calculated
|
|
||||||
val start_num = hacking_faction match {
|
|
||||||
case PlanetSideEmpire.TR => 65536L
|
|
||||||
case PlanetSideEmpire.NC => 131072L
|
|
||||||
case PlanetSideEmpire.VS => 196608L
|
|
||||||
}
|
|
||||||
value = start_num + deciseconds_remaining
|
|
||||||
}
|
|
||||||
sendResponse(PlanetsideAttributeMessage(target_guid, 20, value))
|
|
||||||
|
|
||||||
|
// See PlanetSideAttributeMessage #20 documentation for an explanation of how the timer is calculated
|
||||||
|
val start_num = hfaction match {
|
||||||
|
case PlanetSideEmpire.TR => 65536L
|
||||||
|
case PlanetSideEmpire.NC => 131072L
|
||||||
|
case PlanetSideEmpire.VS => 196608L
|
||||||
|
}
|
||||||
|
value = start_num + deciseconds_remaining
|
||||||
|
|
||||||
|
sendResponse(PlanetsideAttributeMessage(target_guid, 20, value))
|
||||||
|
case _ => log.warn("LocalResponse.HackCaptureTerminal: HackedBy not defined")
|
||||||
|
}
|
||||||
|
case _ => log.warn(s"LocalResponse.HackCaptureTerminal: Couldn't find capture terminal with GUID ${target_guid} in zone ${continent.Id}")
|
||||||
|
}
|
||||||
|
}
|
||||||
case LocalResponse.ObjectDelete(object_guid, unk) =>
|
case LocalResponse.ObjectDelete(object_guid, unk) =>
|
||||||
if(tplayer_guid != guid) {
|
if(tplayer_guid != guid) {
|
||||||
sendResponse(ObjectDeleteMessage(object_guid, unk))
|
sendResponse(ObjectDeleteMessage(object_guid, unk))
|
||||||
|
|
@ -3211,7 +3215,10 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
case Some(container) => //just in case
|
case Some(container) => //just in case
|
||||||
if(vel.isDefined) {
|
if(vel.isDefined) {
|
||||||
val guid = player.GUID
|
val guid = player.GUID
|
||||||
sendResponse(UnuseItemMessage(guid, container.GUID))
|
// If the container is a corpse and gets removed just as this runs it can cause a client disconnect, so we'll check the container has a GUID first.
|
||||||
|
if(container.HasGUID) {
|
||||||
|
sendResponse(UnuseItemMessage(guid, container.GUID))
|
||||||
|
}
|
||||||
sendResponse(UnuseItemMessage(guid, guid))
|
sendResponse(UnuseItemMessage(guid, guid))
|
||||||
accessedContainer = None
|
accessedContainer = None
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue