diff --git a/src/main/scala/net/psforever/actors/session/SessionActor.scala b/src/main/scala/net/psforever/actors/session/SessionActor.scala index a2919e2a..ec3e800f 100644 --- a/src/main/scala/net/psforever/actors/session/SessionActor.scala +++ b/src/main/scala/net/psforever/actors/session/SessionActor.scala @@ -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) diff --git a/src/main/scala/net/psforever/objects/serverobject/doors/Door.scala b/src/main/scala/net/psforever/objects/serverobject/doors/Door.scala index 56e7193b..b10574bf 100644 --- a/src/main/scala/net/psforever/objects/serverobject/doors/Door.scala +++ b/src/main/scala/net/psforever/objects/serverobject/doors/Door.scala @@ -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 } diff --git a/src/main/scala/net/psforever/objects/serverobject/doors/DoorControl.scala b/src/main/scala/net/psforever/objects/serverobject/doors/DoorControl.scala index 8614db3c..10fa58b8 100644 --- a/src/main/scala/net/psforever/objects/serverobject/doors/DoorControl.scala +++ b/src/main/scala/net/psforever/objects/serverobject/doors/DoorControl.scala @@ -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 = { } } diff --git a/src/main/scala/net/psforever/objects/serverobject/painbox/PainboxControl.scala b/src/main/scala/net/psforever/objects/serverobject/painbox/PainboxControl.scala index e53b0b91..8e09e30c 100644 --- a/src/main/scala/net/psforever/objects/serverobject/painbox/PainboxControl.scala +++ b/src/main/scala/net/psforever/objects/serverobject/painbox/PainboxControl.scala @@ -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 => diff --git a/src/test/scala/objects/DoorTest.scala b/src/test/scala/objects/DoorTest.scala index e1ef43bb..742af526 100644 --- a/src/test/scala/objects/DoorTest.scala +++ b/src/test/scala/objects/DoorTest.scala @@ -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 } } }