logic for door opening has been exorcised from SessionActor into DoorControl

This commit is contained in:
Jason_DiDonato@yahoo.com 2020-10-13 18:47:05 -04:00
parent ef0d18d214
commit 4a0805b698
5 changed files with 82 additions and 76 deletions

View file

@ -542,9 +542,6 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
case ProgressEvent(delta, finishedAction, stepAction, tick) =>
HandleProgressChange(delta, finishedAction, stepAction, tick)
case Door.DoorMessage(tplayer, msg, order) =>
HandleDoorMessage(tplayer, msg, order)
case GalaxyServiceResponse(_, reply) =>
reply match {
case GalaxyResponse.HotSpotUpdate(zone_index, priority, hot_spot_info) =>
@ -2189,36 +2186,6 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
}
}
/**
* na
* @param tplayer na
* @param msg na
* @param order na
*/
def HandleDoorMessage(tplayer: Player, msg: UseItemMessage, order: Door.Exchange): Unit = {
val door_guid = msg.object_guid
order match {
case Door.OpenEvent() =>
continent.GUID(door_guid) match {
case Some(door: Door) =>
sendResponse(GenericObjectStateMsg(door_guid, 16))
continent.LocalEvents ! LocalServiceMessage(
continent.id,
LocalAction.DoorOpens(tplayer.GUID, continent, door)
)
case _ =>
log.warn(s"door $door_guid wanted to be opened but could not be found")
}
case Door.CloseEvent() =>
sendResponse(GenericObjectStateMsg(door_guid, 17))
continent.LocalEvents ! LocalServiceMessage(continent.id, LocalAction.DoorCloses(tplayer.GUID, door_guid))
case Door.NoEvent() => ;
}
}
/**
* na
* @param toChannel na
@ -4477,29 +4444,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
}
ValidObject(object_guid) match {
case Some(door: Door) =>
if (
player.Faction == door.Faction || (continent.map.doorToLock.get(object_guid.guid) match {
case Some(lock_guid) =>
val lock = continent.GUID(lock_guid).get.asInstanceOf[IFFLock]
val owner = lock.Owner.asInstanceOf[Building]
val playerIsOnInside = Vector3.ScalarProjection(lock.Outwards, player.Position - door.Position) < 0f
// If an IFF lock exists and the IFF lock faction doesn't match the current player and one of the following conditions are met open the door:
// The player is on the inside of the door, determined by the lock orientation
// The lock is hacked
// A base is hacked
// A base is neutral
// todo: A base is out of power (generator down)
playerIsOnInside || lock.HackedBy.isDefined || owner.CaptureTerminalIsHacked || lock.Faction == PlanetSideEmpire.NEUTRAL
case None => !door.isOpen // If there's no linked IFF lock just open the door if it's closed.
})
) {
door.Actor ! Door.Use(player, msg)
} else if (door.isOpen) {
//the door is open globally ... except on our screen
sendResponse(GenericObjectStateMsg(object_guid, 16))
}
door.Actor ! CommonMessages.Use(player)
case Some(resourceSilo: ResourceSilo) =>
resourceSilo.Actor ! CommonMessages.Use(player)

View file

@ -25,16 +25,6 @@ class Door(private val ddef: DoorDefinition) extends Amenity {
Open
}
def Use(player: Player, msg: UseItemMessage): Door.Exchange = {
if (openState.isEmpty) {
openState = Some(player)
Door.OpenEvent()
} else {
openState = None
Door.CloseEvent()
}
}
def Definition: DoorDefinition = ddef
}

View file

@ -1,21 +1,90 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.doors
import akka.actor.Actor
import net.psforever.objects.Player
import net.psforever.objects.serverobject.CommonMessages
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
import net.psforever.objects.serverobject.locks.IFFLock
import net.psforever.objects.serverobject.structures.{Building, PoweredAmenityControl}
import net.psforever.services.Service
import net.psforever.services.local.{LocalAction, LocalResponse, LocalServiceMessage, LocalServiceResponse}
import net.psforever.types.{PlanetSideEmpire, Vector3}
/**
* An `Actor` that handles messages being dispatched to a specific `Door`.
* @param door the `Door` object being governed
*/
class DoorControl(door: Door) extends Actor with FactionAffinityBehavior.Check {
class DoorControl(door: Door)
extends PoweredAmenityControl
with FactionAffinityBehavior.Check {
def FactionObject: FactionAffinity = door
def receive: Receive =
checkBehavior.orElse {
case Door.Use(player, msg) =>
sender() ! Door.DoorMessage(player, msg, door.Use(player, msg))
val commonBehavior: Receive = checkBehavior
case _ => ;
def poweredStateLogic: Receive =
commonBehavior
.orElse {
case CommonMessages.Use(player, _) =>
val zone = door.Zone
val doorGUID = door.GUID
if (
player.Faction == door.Faction || (zone.GUID(zone.map.doorToLock.getOrElse(doorGUID.guid, 0)) match {
case Some(lock: IFFLock) =>
val owner = lock.Owner.asInstanceOf[Building]
val playerIsOnInside = Vector3.ScalarProjection(lock.Outwards, player.Position - door.Position) < 0f
/*
If an IFF lock exists and
the IFF lock faction doesn't match the current player and
one of the following conditions are met:
1. player is on the inside of the door (determined by the lock orientation)
2. lock is hacked
3. facility capture terminal has been hacked
4. base is neutral
... open the door.
*/
playerIsOnInside || lock.HackedBy.isDefined || owner.CaptureTerminalIsHacked || lock.Faction == PlanetSideEmpire.NEUTRAL
case _ => true // no linked IFF lock, just try open the door
})
) {
openDoor(player)
}
case _ => ;
}
def unpoweredStateLogic: Receive = {
commonBehavior
.orElse {
case CommonMessages.Use(player, _) =>
//without power, the door opens freely
openDoor(player)
case _ => ;
}
}
def openDoor(player: Player): Unit = {
val zone = door.Zone
val doorGUID = door.GUID
if (!door.isOpen) {
//global open
door.Open = player
zone.LocalEvents ! LocalServiceMessage(
zone.id,
LocalAction.DoorOpens(Service.defaultPlayerGUID, zone, door)
)
}
else {
//the door should already open, but the requesting player does not see it as open
sender() ! LocalServiceResponse(
player.Name,
Service.defaultPlayerGUID,
LocalResponse.DoorOpens(doorGUID)
)
}
}
override def powerTurnOffCallback() : Unit = { }
override def powerTurnOnCallback() : Unit = { }
}

View file

@ -21,7 +21,7 @@ class PainboxControl(painbox: Painbox) extends PoweredAmenityControl {
var disabled = false // Temporary to disable cavern non-radius fields
val initialStartup: Unit = {
def initialStartup(): Unit = {
if (painbox.Definition.HasNearestDoorDependency) {
(painbox.Owner match {
case obj : Building =>

View file

@ -59,10 +59,12 @@ class DoorTest extends Specification {
)
val door = Door(GlobalDefinitions.door)
door.Open.isEmpty mustEqual true
door.Use(player, msg)
door.Open = player
door.isOpen mustEqual true
door.Open.contains(player) mustEqual true
door.Use(player, msg)
door.Open = None
door.Open.isEmpty mustEqual true
door.isOpen mustEqual false
}
}
}