From 249eb96cc5eb24f0ad6872b130a38daf10be1d39 Mon Sep 17 00:00:00 2001 From: FateJH Date: Tue, 3 Oct 2017 20:32:21 -0400 Subject: [PATCH] hack testing; RepairMessage is suitable for a progress bar for now but it needs replacing with the correct operation and the last part feels wrong --- .../objects/doors/DoorCloseControl.scala | 45 +++++++++++++++---- .../src/main/scala/WorldSessionActor.scala | 35 +++++++++++++++ 2 files changed, 72 insertions(+), 8 deletions(-) diff --git a/common/src/main/scala/net/psforever/objects/doors/DoorCloseControl.scala b/common/src/main/scala/net/psforever/objects/doors/DoorCloseControl.scala index ae20b6e7..3b845804 100644 --- a/common/src/main/scala/net/psforever/objects/doors/DoorCloseControl.scala +++ b/common/src/main/scala/net/psforever/objects/doors/DoorCloseControl.scala @@ -3,29 +3,58 @@ package net.psforever.objects.doors import akka.actor.{Actor, ActorRef, Cancellable} import net.psforever.packet.game.PlanetSideGUID +import scala.concurrent.duration._ -import scala.collection.mutable.ListBuffer +import scala.annotation.tailrec class DoorCloseControl(implicit val environment : ActorRef) extends Actor { import DoorCloseControl._ - private var doorCloser : Cancellable = DefaultCloser + private var doorCloserTrigger : Cancellable = DefaultCloser private var openDoors : List[DoorEntry] = Nil def receive : Receive = { case DoorIsOpen(guid, time) => - if(openDoors.isEmpty) { - //doorCloser = context.system.scheduler.scheduleOnce(timeout, environment, Door.DoorMessage()) + openDoors = openDoors :+ DoorEntry(guid, time) + if(doorCloserTrigger.isCancelled) { + import scala.concurrent.ExecutionContext.Implicits.global + doorCloserTrigger = context.system.scheduler.scheduleOnce(timeout, self, DoorCloseControl.CloseTheDoor()) } - else { - openDoors = openDoors :+ DoorEntry(guid, time) + + case CloseTheDoor() => + doorCloserTrigger.cancel + val now : Long = System.nanoTime + recursiveCloseDoors(openDoors.iterator, now) match { + case entry :: rest => + openDoors = entry :: rest + import scala.concurrent.ExecutionContext.Implicits.global + doorCloserTrigger = context.system.scheduler.scheduleOnce((now - entry.opened_at_time + timeout_time)*1000 milliseconds, self, DoorCloseControl.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 DoorCloseControl { - private final val timeout : Long = 5000L + 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 @@ -36,5 +65,5 @@ object DoorCloseControl { final case class DoorIsOpen(door_guid : PlanetSideGUID, opened_at_time : Long = System.nanoTime()) - final case class CloseTheDoor(door_guid : PlanetSideGUID) + private final case class CloseTheDoor() } diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index 76ec1a7b..9242b8fd 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -37,8 +37,10 @@ class WorldSessionActor extends Actor with MDCContextAware { var taskResolver : ActorRef = Actor.noSender var galaxy : ActorRef = Actor.noSender var continent : Zone = null + var progressBarValue : Option[Float] = None var clientKeepAlive : Cancellable = WorldSessionActor.DefaultCancellable + var progressBarUpdate : Cancellable = WorldSessionActor.DefaultCancellable override def postStop() = { if(clientKeepAlive != null) @@ -547,6 +549,25 @@ class WorldSessionActor extends Actor with MDCContextAware { continent.Actor ! Zone.DropItemOnGround(item, item.Position, item.Orientation) //restore } + case ItemHacking(tplayer, target, tool_guid, delta) => + progressBarUpdate.cancel + if(progressBarValue.isDefined) { + val progressBarVal : Float = progressBarValue.get + delta + sendResponse(PacketCoding.CreateGamePacket(0, RepairMessage(target.GUID, progressBarVal.toInt))) + if(progressBarVal > 100) { + progressBarValue = None + log.info(s"We've hacked the item $target! Now what?") + sendResponse(PacketCoding.CreateGamePacket(0, ChangeFireStateMessage_Stop(tool_guid))) + //TODO now what? + } + else { + progressBarValue = Some(progressBarVal) + import scala.concurrent.duration._ + import scala.concurrent.ExecutionContext.Implicits.global + progressBarUpdate = context.system.scheduler.scheduleOnce(250 milliseconds, self, ItemHacking(tplayer, target, tool_guid, delta)) + } + } + case ResponseToSelf(pkt) => log.info(s"Received a direct message: $pkt") sendResponse(pkt) @@ -791,6 +812,7 @@ class WorldSessionActor extends Actor with MDCContextAware { case msg @ ChangeFireStateMessage_Stop(item_guid) => log.info("ChangeFireState_Stop: " + msg) + progressBarUpdate.cancel case msg @ EmoteMsg(avatar_guid, emote) => log.info("Emote: " + msg) @@ -979,6 +1001,18 @@ class WorldSessionActor extends Actor with MDCContextAware { door.Actor ! Door.Use(player, msg) //let door open freely } + case Some(panel : IFFLock) => + player.Slot(player.DrawnSlot).Equipment match { + case Some(tool : SimpleItem) => + if(tool.Definition == GlobalDefinitions.remote_electronics_kit) { + progressBarValue = Some(-2.66f) + self ! WorldSessionActor.ItemHacking(player, panel, tool.GUID, 2.66f) + } + case _ => ; + } + log.info("Hacking a door~") + //TODO get player hack level (for now, presume 15s in internals of 4/s) + case Some(obj : PlanetSideGameObject) => if(itemType != 121) { sendResponse(PacketCoding.CreateGamePacket(0, UseItemMessage(avatar_guid, unk1, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType))) @@ -1569,6 +1603,7 @@ object WorldSessionActor { private final case class PlayerFailedToLoad(tplayer : Player) private final case class ListAccountCharacters() private final case class SetCurrentAvatar(tplayer : Player) + private final case class ItemHacking(tplayer : Player, target : PlanetSideGameObject, tool_guid : PlanetSideGUID, delta : Float) /** * A placeholder `Cancellable` object.