diff --git a/common/src/test/scala/objects/terminal/MedicalTerminalTest.scala b/common/src/test/scala/objects/terminal/MedicalTerminalTest.scala index 89efb86f..86b39fe3 100644 --- a/common/src/test/scala/objects/terminal/MedicalTerminalTest.scala +++ b/common/src/test/scala/objects/terminal/MedicalTerminalTest.scala @@ -3,7 +3,7 @@ package objects.terminal import akka.actor.ActorRef import net.psforever.objects.serverobject.terminals.{MedicalTerminalDefinition, ProximityTerminal, Terminal} -import net.psforever.objects.{GlobalDefinitions, Player} +import net.psforever.objects.{Avatar, GlobalDefinitions, Player} import net.psforever.packet.game.{ItemTransactionMessage, PlanetSideGUID} import net.psforever.types.{CharacterGender, PlanetSideEmpire, TransactionType} import org.specs2.mutable.Specification @@ -64,14 +64,14 @@ class MedicalTerminalTest extends Specification { ProximityTerminal(GlobalDefinitions.medical_terminal).Actor mustEqual ActorRef.noSender } - "can add a a player to a list of users" in { + "can add a player to a list of users" in { val terminal = ProximityTerminal(GlobalDefinitions.medical_terminal) terminal.NumberUsers mustEqual 0 terminal.AddUser(PlanetSideGUID(10)) terminal.NumberUsers mustEqual 1 } - "can remove a a player to a list of users" in { + "can remove a player from a list of users" in { val terminal = ProximityTerminal(GlobalDefinitions.medical_terminal) terminal.AddUser(PlanetSideGUID(10)) terminal.NumberUsers mustEqual 1 @@ -81,7 +81,7 @@ class MedicalTerminalTest extends Specification { "player can not interact with the proximity terminal normally (buy)" in { val terminal = ProximityTerminal(GlobalDefinitions.medical_terminal) - val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0) + val player = Player(Avatar("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)) val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 1, "lite_armor", 0, PlanetSideGUID(0)) terminal.Request(player, msg) mustEqual Terminal.NoDeal() diff --git a/common/src/test/scala/objects/terminal/ProximityTerminalControlTest.scala b/common/src/test/scala/objects/terminal/ProximityTerminalControlTest.scala index d288ff11..f817be6a 100644 --- a/common/src/test/scala/objects/terminal/ProximityTerminalControlTest.scala +++ b/common/src/test/scala/objects/terminal/ProximityTerminalControlTest.scala @@ -3,7 +3,7 @@ package objects.terminal import akka.actor.{ActorSystem, Props} import net.psforever.objects.serverobject.CommonMessages -import net.psforever.objects.{GlobalDefinitions, Player} +import net.psforever.objects.{Avatar, GlobalDefinitions, Player} import net.psforever.objects.serverobject.terminals._ import net.psforever.packet.game.PlanetSideGUID import net.psforever.types.{CharacterGender, PlanetSideEmpire} @@ -35,7 +35,7 @@ class MedicalTerminalControl1Test extends ActorTest() { "ProximityTerminalControl sends a message to the first new user only" in { val (player, terminal) = ProximityTerminalControlTest.SetUpAgents(GlobalDefinitions.medical_terminal, PlanetSideEmpire.TR) player.GUID = PlanetSideGUID(10) - val player2 = Player("someothertest", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0) + val player2 = Player(Avatar("someothertest", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)) player2.GUID = PlanetSideGUID(11) terminal.Actor ! CommonMessages.Use(player) @@ -58,7 +58,7 @@ class MedicalTerminalControl2Test extends ActorTest() { "ProximityTerminalControl sends a message to the last user only" in { val (player, terminal) : (Player, ProximityTerminal) = ProximityTerminalControlTest.SetUpAgents(GlobalDefinitions.medical_terminal, PlanetSideEmpire.TR) player.GUID = PlanetSideGUID(10) - val player2 = Player("someothertest", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0) + val player2 = Player(Avatar("someothertest", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)) player2.GUID = PlanetSideGUID(11) terminal.Actor ! CommonMessages.Use(player) @@ -87,7 +87,7 @@ class MedicalTerminalControl3Test extends ActorTest() { "ProximityTerminalControl sends a message to the last user only (confirmation of test #2)" in { val (player, terminal) : (Player, ProximityTerminal) = ProximityTerminalControlTest.SetUpAgents(GlobalDefinitions.medical_terminal, PlanetSideEmpire.TR) player.GUID = PlanetSideGUID(10) - val player2 = Player("someothertest", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0) + val player2 = Player(Avatar("someothertest", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)) player2.GUID = PlanetSideGUID(11) terminal.Actor ! CommonMessages.Use(player) @@ -116,6 +116,6 @@ object ProximityTerminalControlTest { def SetUpAgents(tdef : MedicalTerminalDefinition, faction : PlanetSideEmpire.Value)(implicit system : ActorSystem) : (Player, ProximityTerminal) = { val terminal = ProximityTerminal(tdef) terminal.Actor = system.actorOf(Props(classOf[ProximityTerminalControl], terminal), "test-term") - (Player("test", faction, CharacterGender.Male, 0, 0), terminal) + (Player(Avatar("test", faction, CharacterGender.Male, 0, 0)), terminal) } } diff --git a/pslogin/src/main/scala/Maps.scala b/pslogin/src/main/scala/Maps.scala index 2bdf50e8..8b9351b1 100644 --- a/pslogin/src/main/scala/Maps.scala +++ b/pslogin/src/main/scala/Maps.scala @@ -100,6 +100,8 @@ object Maps { LocalObject(1186, Locker.Constructor) LocalObject(1187, Locker.Constructor) LocalObject(1188, Locker.Constructor) + LocalObject(1492, ProximityTerminal.Constructor(medical_terminal)) //lobby + LocalObject(1494, ProximityTerminal.Constructor(medical_terminal)) //kitchen LocalObject(1564, Terminal.Constructor(order_terminal)) LocalObject(1568, Terminal.Constructor(order_terminal)) LocalObject(1569, Terminal.Constructor(order_terminal)) @@ -200,6 +202,8 @@ object Maps { ObjectToBuilding(1186, 2) ObjectToBuilding(1187, 2) ObjectToBuilding(1188, 2) + ObjectToBuilding(1492, 2) + ObjectToBuilding(1494, 2) ObjectToBuilding(1564, 2) ObjectToBuilding(1568, 2) ObjectToBuilding(1569, 2) diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index b2e4b6bf..46fe9aef 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -85,6 +85,18 @@ class WorldSessionActor extends Actor with MDCContextAware { LivePlayerList.Remove(sessionId) if(player != null && player.HasGUID) { val player_guid = player.GUID + //proximity vehicle terminals must be considered too + delayedProximityTerminalResets.foreach({case(_, task) => task.cancel}) + usingProximityTerminal.foreach(term_guid => { + continent.GUID(term_guid) match { + case Some(obj : ProximityTerminal) => + if(obj.NumberUsers > 0 && obj.RemoveUser(player_guid) == 0) { //refer to ProximityTerminalControl when modernizng + localService ! LocalServiceMessage(continent.Id, LocalAction.ProximityTerminalEffect(player_guid, term_guid, false)) + } + case _ => ; + } + }) + if(player.isAlive) { //actually being alive or manually deconstructing player.VehicleSeated match { @@ -93,17 +105,6 @@ class WorldSessionActor extends Actor with MDCContextAware { case None => ; } - delayedProximityTerminalResets.foreach({case(_, task) => task.cancel}) - usingProximityTerminal.foreach(term_guid => { - continent.GUID(term_guid) match { - case Some(obj : ProximityTerminal) => - if(obj.RemoveUser(player_guid) == 0) { //manual; see ProximityTerminalControl - localService ! LocalServiceMessage(continent.Id, LocalAction.ProximityTerminalEffect(player_guid, term_guid, false)) - } - case _ => ; - } - }) - continent.Population ! Zone.Population.Release(avatar) player.Position = Vector3.Zero //save character before doing this avatarService ! AvatarServiceMessage(player.Continent, AvatarAction.ObjectDelete(player_guid, player_guid)) @@ -989,7 +990,13 @@ class WorldSessionActor extends Actor with MDCContextAware { localService ! LocalServiceMessage(continent.Id, LocalAction.ProximityTerminalEffect(player_guid, term_guid, false)) case Terminal.NoDeal() => - log.warn(s"$tplayer made a request but the terminal rejected the order $msg") + val order : String = if(msg == null) { + s"order $msg" + } + else { + "missing order" + } + log.warn(s"${tplayer.Name} made a request but the terminal rejected the $order") sendResponse(ItemTransactionResultMessage(msg.terminal_guid, msg.transaction_type, false)) } @@ -2203,6 +2210,7 @@ class WorldSessionActor extends Actor with MDCContextAware { case Some(obj : SpawnTube) => //deconstruction PlayerActionsToCancel() + CancelAllProximityUnits() player.Release sendResponse(AvatarDeadStateMessage(DeadState.Release, 0, 0, player.Position, player.Faction, true)) continent.Population ! Zone.Population.Release(avatar) @@ -2228,7 +2236,6 @@ class WorldSessionActor extends Actor with MDCContextAware { SelectProximityUnit(obj) } else { - //obj.Actor ! ProximityTerminal.Use(player) StartUsingProximityUnit(obj) } case Some(obj) => ; @@ -3462,7 +3469,7 @@ class WorldSessionActor extends Actor with MDCContextAware { sendResponse(HackMessage(3, PlanetSideGUID(building.ModelId), PlanetSideGUID(0), 0, 3212836864L, HackState.HackCleared, 8)) }) } - + /** * The player has lost all his vitality and must be killed.
*
@@ -3493,6 +3500,7 @@ class WorldSessionActor extends Actor with MDCContextAware { avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(player_guid, 29, 1)) } PlayerActionsToCancel() + CancelAllProximityUnits() import scala.concurrent.duration._ import scala.concurrent.ExecutionContext.Implicits.global @@ -3536,7 +3544,7 @@ class WorldSessionActor extends Actor with MDCContextAware { } if(speed > 1) { sendResponse(ChatMsg(ChatMessageType.CMT_SPEED, false, "", "1.000", None)) - speed = 1f + speed = 1f } } @@ -3548,6 +3556,7 @@ class WorldSessionActor extends Actor with MDCContextAware { def AvatarCreate() : Unit = { player.Spawn player.Health = 50 //TODO temp + player.Armor = 25 val packet = player.Definition.Packet val dcdata = packet.DetailedConstructorData(player).get sendResponse(ObjectCreateDetailedMessage(ObjectClass.avatar, player.GUID, dcdata)) @@ -3671,30 +3680,32 @@ class WorldSessionActor extends Actor with MDCContextAware { def StartUsingProximityUnit(terminal : ProximityTerminal) : Unit = { val term_guid = terminal.GUID if(!usingProximityTerminal.contains(term_guid)) { + usingProximityTerminal += term_guid terminal.Definition match { case GlobalDefinitions.adv_med_terminal | GlobalDefinitions.medical_terminal => usingMedicalTerminal = Some(term_guid) - case _ => ; + case _ => + SetDelayedProximityUnitReset(terminal) } - usingProximityTerminal += term_guid - SetDelayedProximityUnitReset(terminal) terminal.Actor ! CommonMessages.Use(player) } } /** * Stop using a proximity-base service. - * Special note is warranted in the case of a medical terminal or an advanced medical terminal. + * Special note is warranted when determining the identity of the proximity terminal. + * Medical terminals of both varieties can be cancelled by movement. + * Other sorts of proximity-based units are put on a timer. * @param terminal the proximity-based unit */ def StopUsingProximityUnit(terminal : ProximityTerminal) : Unit = { val term_guid = terminal.GUID if(usingProximityTerminal.contains(term_guid)) { + usingProximityTerminal -= term_guid + ClearDelayedProximityUnitReset(term_guid) if(usingMedicalTerminal.contains(term_guid)) { usingMedicalTerminal = None } - usingProximityTerminal -= term_guid - ClearDelayedProximityUnitReset(term_guid) terminal.Actor ! CommonMessages.Unuse(player) } } @@ -3729,18 +3740,35 @@ class WorldSessionActor extends Actor with MDCContextAware { } } + /** + * Cease all current interactions with proximity-based units. + * Pair with `PlayerActionsToCancel`, except when logging out (stopping). + * This operations may invoke callback messages. + * @see `postStop`
+ * `Terminal.StopProximityEffects` + */ + def CancelAllProximityUnits() : Unit = { + delayedProximityTerminalResets.foreach({case(term_guid, task) => + task.cancel + delayedProximityTerminalResets -= term_guid + }) + usingProximityTerminal.foreach(term_guid => { + StopUsingProximityUnit(continent.GUID(term_guid).get.asInstanceOf[ProximityTerminal]) + }) + } + /** * Determine which functionality to pursue, by being given a generic proximity-functional unit * and determinig which kind of unit is being utilized. * @param terminal the proximity-based unit */ def SelectProximityUnit(terminal : ProximityTerminal) : Unit = { - SetDelayedProximityUnitReset(terminal) terminal.Definition match { case GlobalDefinitions.adv_med_terminal | GlobalDefinitions.medical_terminal => ProximityMedicalTerminal(terminal) case GlobalDefinitions.crystals_health_a | GlobalDefinitions.crystals_health_b => + SetDelayedProximityUnitReset(terminal) ProximityHealCrystal(terminal) case _ => ;