mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-03-07 22:20:27 +00:00
doors open and async close now via LocalEnvironment and DoorCloseActor
This commit is contained in:
parent
1c41972d69
commit
74b718c536
7 changed files with 138 additions and 94 deletions
|
|
@ -33,6 +33,7 @@ class Door(ddef : DoorDefinition) extends PlanetSideServerObject {
|
|||
Door.OpenEvent()
|
||||
}
|
||||
else if(openState) {
|
||||
openState = false
|
||||
Door.CloseEvent()
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ class DoorControl(door : Door) extends Actor {
|
|||
def receive : Receive = {
|
||||
case Door.Use(player, msg) =>
|
||||
sender ! Door.DoorMessage(player, msg, door.Use(player, msg))
|
||||
|
||||
case _ =>
|
||||
sender ! Door.NoEvent()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.zones
|
||||
|
||||
import akka.actor.{Actor, Cancellable}
|
||||
import net.psforever.objects.serverobject.doors.Door
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import scala.concurrent.duration._
|
||||
|
||||
class DoorCloseActor() extends Actor {
|
||||
import DoorCloseActor._
|
||||
private var doorCloserTrigger : Cancellable = DefaultCloser
|
||||
private var openDoors : List[DoorEntry] = Nil
|
||||
//private[this] val log = org.log4s.getLogger
|
||||
|
||||
def receive : Receive = {
|
||||
case DoorIsOpen(door, zone, time) =>
|
||||
openDoors = openDoors :+ DoorEntry(door, zone, time)
|
||||
if(openDoors.size == 1) {
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
doorCloserTrigger = context.system.scheduler.scheduleOnce(timeout, self, DoorCloseActor.TryCloseDoors())
|
||||
}
|
||||
|
||||
case TryCloseDoors() =>
|
||||
doorCloserTrigger.cancel
|
||||
val now : Long = System.nanoTime
|
||||
//TODO we can just walk across the list of doors and extract only the first few entries
|
||||
val (doorsToClose, doorsLeftOpen) = recursivePartitionDoors(openDoors.iterator, now)
|
||||
openDoors = doorsLeftOpen
|
||||
doorsToClose.foreach(entry => {
|
||||
entry.door.Open = false //permissible
|
||||
context.parent ! DoorCloseActor.CloseTheDoor(entry.door.GUID, entry.zone.Id)
|
||||
})
|
||||
|
||||
if(doorsLeftOpen.nonEmpty) {
|
||||
val short_timeout : FiniteDuration = math.max(1, timeout_time - (now - doorsLeftOpen.head.opened_at_time)) nanoseconds
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
doorCloserTrigger = context.system.scheduler.scheduleOnce(short_timeout, self, DoorCloseActor.TryCloseDoors())
|
||||
}
|
||||
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
/**
|
||||
* na
|
||||
* @param iter na
|
||||
* @param now na
|
||||
* @param list na
|
||||
* @see `List.partition`
|
||||
* @return a `Tuple` of two `Lists`:
|
||||
* the entries for all `Door`s that are closing,
|
||||
* and the entries for all doors that are staying open
|
||||
*/
|
||||
@tailrec private def recursivePartitionDoors(iter : Iterator[DoorEntry], now : Long, list : List[DoorEntry] = Nil) : (List[DoorEntry], List[DoorEntry]) = {
|
||||
if(!iter.hasNext) {
|
||||
(list, iter.toList)
|
||||
}
|
||||
else {
|
||||
val entry = iter.next()
|
||||
if(now - entry.opened_at_time >= timeout_time) {
|
||||
recursivePartitionDoors(iter, now, list :+ entry)
|
||||
}
|
||||
else {
|
||||
(list, entry +: iter.toList)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object DoorCloseActor {
|
||||
private final val timeout_time : Long = 5000000000L //nanoseconds
|
||||
private final val timeout : FiniteDuration = timeout_time nanoseconds
|
||||
|
||||
private final val DefaultCloser : Cancellable = new Cancellable() {
|
||||
override def cancel : Boolean = true
|
||||
override def isCancelled : Boolean = true
|
||||
}
|
||||
|
||||
final case class DoorIsOpen(door : Door, zone : Zone, opened_at_time : Long = System.nanoTime())
|
||||
|
||||
final case class CloseTheDoor(door_guid : PlanetSideGUID, zone_id : String)
|
||||
|
||||
private final case class DoorEntry(door : Door, zone : Zone, opened_at_time : Long)
|
||||
|
||||
private final case class TryCloseDoors()
|
||||
}
|
||||
|
|
@ -48,10 +48,6 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
|
|||
private val equipmentOnGround : ListBuffer[Equipment] = ListBuffer[Equipment]()
|
||||
/** Used by the `Zone` to coordinate `Equipment` dropping and collection requests. */
|
||||
private var ground : ActorRef = ActorRef.noSender
|
||||
/** */
|
||||
private var doors : ActorRef = ActorRef.noSender
|
||||
/** */
|
||||
private var events : ActorRef = ActorRef.noSender
|
||||
|
||||
private var bases : List[Base] = List()
|
||||
|
||||
|
|
@ -72,7 +68,6 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
|
|||
implicit val guid : NumberPoolHub = this.guid //passed into builderObject.Build implicitly
|
||||
accessor = context.actorOf(Props(classOf[UniqueNumberSystem], guid, UniqueNumberSystem.AllocateNumberPoolActors(guid)), s"$Id-uns")
|
||||
ground = context.actorOf(Props(classOf[ZoneGroundActor], equipmentOnGround), s"$Id-ground")
|
||||
doors = context.actorOf(Props(classOf[ZoneDoorActor], this), s"$Id-doors")
|
||||
|
||||
Map.LocalObjects.foreach({ builderObject =>
|
||||
builderObject.Build
|
||||
|
|
@ -179,17 +174,6 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
|
|||
*/
|
||||
def Ground : ActorRef = ground
|
||||
|
||||
def Doors : ActorRef = doors
|
||||
|
||||
def Events : ActorRef = events
|
||||
|
||||
def Events_=(zoneActor : ActorRef) : ActorRef = {
|
||||
if(events == ActorRef.noSender) {
|
||||
events = zoneActor
|
||||
}
|
||||
Events
|
||||
}
|
||||
|
||||
def MakeBases(num : Int) : List[Base] = {
|
||||
bases = (0 to num).map(id => new Base(id)).toList
|
||||
bases
|
||||
|
|
|
|||
|
|
@ -1,69 +0,0 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.zones
|
||||
|
||||
import akka.actor.{Actor, Cancellable}
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import scala.concurrent.duration._
|
||||
|
||||
class ZoneDoorActor(implicit val zone : Zone) extends Actor {
|
||||
import ZoneDoorActor._
|
||||
private var doorCloserTrigger : Cancellable = DefaultCloser
|
||||
private var openDoors : List[DoorEntry] = Nil
|
||||
|
||||
def receive : Receive = {
|
||||
case DoorIsOpen(guid, time) =>
|
||||
openDoors = openDoors :+ DoorEntry(guid, time)
|
||||
if(doorCloserTrigger.isCancelled) {
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
doorCloserTrigger = context.system.scheduler.scheduleOnce(timeout, self, ZoneDoorActor.CloseTheDoor())
|
||||
}
|
||||
|
||||
case CloseTheDoor() =>
|
||||
doorCloserTrigger.cancel
|
||||
val now : Long = System.nanoTime
|
||||
recursiveCloseDoors(openDoors.iterator, now) match {
|
||||
case entry :: rest =>
|
||||
openDoors = rest
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
doorCloserTrigger = context.system.scheduler.scheduleOnce((now - entry.opened_at_time + timeout_time)*1000 milliseconds, self, ZoneDoorActor.CloseTheDoor())
|
||||
case Nil =>
|
||||
openDoors = Nil
|
||||
}
|
||||
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
@tailrec private def recursiveCloseDoors(iter : Iterator[DoorEntry], now : Long) : List[DoorEntry] = {
|
||||
if(!iter.hasNext) {
|
||||
Nil
|
||||
}
|
||||
else {
|
||||
val entry = iter.next
|
||||
if(now - entry.opened_at_time < timeout_time) {
|
||||
entry +: iter.toList
|
||||
}
|
||||
else {
|
||||
//TODO close this door entry
|
||||
recursiveCloseDoors(iter, now)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object ZoneDoorActor {
|
||||
private final val timeout_time = 5000
|
||||
private final val timeout : FiniteDuration = timeout_time milliseconds
|
||||
|
||||
private final val DefaultCloser : Cancellable = new Cancellable() {
|
||||
override def cancel : Boolean = true
|
||||
override def isCancelled : Boolean = true
|
||||
}
|
||||
|
||||
final case class DoorIsOpen(door_guid : PlanetSideGUID, opened_at_time : Long = System.nanoTime())
|
||||
|
||||
private final case class DoorEntry(door_guid : PlanetSideGUID, opened_at_time : Long)
|
||||
|
||||
private final case class CloseTheDoor()
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue