From 85a6eb00fd79f8c0ea658c821b6443e464a81a20 Mon Sep 17 00:00:00 2001 From: FateJH Date: Wed, 30 Aug 2017 20:20:33 -0400 Subject: [PATCH] added a LockerContainer global definition; adjusted how the lockers inhabit the fifthtSlot on players and how they are accessed; fixed converter tests to account for contents and added a quick content test; Live players will now register and unregister the contents of their fifthslot --- .../psforever/objects/GlobalDefinitions.scala | 9 ++++- .../psforever/objects/LockerContainer.scala | 8 ++--- .../scala/net/psforever/objects/Player.scala | 5 ++- .../converter/LockerContainerConverter.scala | 22 +++++++++--- .../test/scala/objects/ConverterTest.scala | 26 ++++++++++++-- .../src/main/scala/WorldSessionActor.scala | 34 +++++++++++++------ 6 files changed, 79 insertions(+), 25 deletions(-) diff --git a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala index 34976c0c2..b8666006e 100644 --- a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala +++ b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala @@ -2,7 +2,7 @@ package net.psforever.objects import net.psforever.objects.definition._ -import net.psforever.objects.definition.converter.{CommandDetonaterConverter, REKConverter} +import net.psforever.objects.definition.converter.{CommandDetonaterConverter, LockerContainerConverter, REKConverter} import net.psforever.objects.equipment.CItem.DeployedItem import net.psforever.objects.equipment._ import net.psforever.objects.inventory.InventoryTile @@ -241,6 +241,13 @@ object GlobalDefinitions { } } + val + locker_container = new EquipmentDefinition(456) { + Name = "locker container" + Size = EquipmentSize.Inventory + Packet = new LockerContainerConverter() + } + val medkit = KitDefinition(Kits.medkit) diff --git a/common/src/main/scala/net/psforever/objects/LockerContainer.scala b/common/src/main/scala/net/psforever/objects/LockerContainer.scala index 0e5357839..6c79c6046 100644 --- a/common/src/main/scala/net/psforever/objects/LockerContainer.scala +++ b/common/src/main/scala/net/psforever/objects/LockerContainer.scala @@ -7,17 +7,13 @@ import net.psforever.objects.equipment.{Equipment, EquipmentSize} import net.psforever.objects.inventory.GridInventory class LockerContainer extends Equipment { - private val inventory = GridInventory() //? + private val inventory = GridInventory(30, 20) def Inventory : GridInventory = inventory def Fit(obj : Equipment) : Option[Int] = inventory.Fit(obj.Definition.Tile) - def Definition : EquipmentDefinition = new EquipmentDefinition(456) { - Name = "locker container" - Size = EquipmentSize.Inventory - Packet = new LockerContainerConverter() - } + def Definition : EquipmentDefinition = GlobalDefinitions.locker_container } object LockerContainer { diff --git a/common/src/main/scala/net/psforever/objects/Player.scala b/common/src/main/scala/net/psforever/objects/Player.scala index 85e830e75..c2300965f 100644 --- a/common/src/main/scala/net/psforever/objects/Player.scala +++ b/common/src/main/scala/net/psforever/objects/Player.scala @@ -70,6 +70,7 @@ class Player(private val name : String, var PlanetsideAttribute : Array[Long] = Array.ofDim(120) Player.SuitSetup(this, ExoSuit) + fifthSlot.Equipment = new LockerContainer() //the fifth slot is the player's "locker" def Name : String = name @@ -158,7 +159,9 @@ class Player(private val name : String, holsters(slot) } else if(slot == 5) { - fifthSlot + new OffhandEquipmentSlot(EquipmentSize.Inventory) { + Equipment = fifthSlot.Equipment + } } else if(slot == Player.FreeHandSlot) { freeHand diff --git a/common/src/main/scala/net/psforever/objects/definition/converter/LockerContainerConverter.scala b/common/src/main/scala/net/psforever/objects/definition/converter/LockerContainerConverter.scala index c9bc0785f..bd3213136 100644 --- a/common/src/main/scala/net/psforever/objects/definition/converter/LockerContainerConverter.scala +++ b/common/src/main/scala/net/psforever/objects/definition/converter/LockerContainerConverter.scala @@ -4,7 +4,6 @@ package net.psforever.objects.definition.converter import net.psforever.objects.LockerContainer import net.psforever.objects.equipment.Equipment import net.psforever.objects.inventory.GridInventory -import net.psforever.packet.game.PlanetSideGUID import net.psforever.packet.game.objectcreate._ import scala.util.{Success, Try} @@ -16,7 +15,7 @@ class LockerContainerConverter extends ObjectCreateConverter[LockerContainer]() override def DetailedConstructorData(obj : LockerContainer) : Try[DetailedLockerContainerData] = { if(obj.Inventory.Size > 0) { - Success(DetailedLockerContainerData(8, Some(InventoryData(MakeInventory(obj.Inventory))))) + Success(DetailedLockerContainerData(8, Some(InventoryData(MakeDetailedInventory(obj.Inventory))))) } else { Success(DetailedLockerContainerData(8, None)) @@ -32,9 +31,24 @@ class LockerContainerConverter extends ObjectCreateConverter[LockerContainer]() private def MakeInventory(inv : GridInventory) : List[InternalSlot] = { inv.Items .map({ - case(guid, item) => + case(_, item) => val equip : Equipment = item.obj - InternalSlot(equip.Definition.ObjectId, PlanetSideGUID(guid), item.start, equip.Definition.Packet.ConstructorData(equip).get) + InternalSlot(equip.Definition.ObjectId, equip.GUID, item.start, equip.Definition.Packet.ConstructorData(equip).get) }).toList } + + /** + * Transform a list of contained items into a list of contained `InternalSlot` objects. + * All objects will take the form of data as if found in an `0x18` packet. + * @param inv the inventory container + * @return a list of all items that were in the inventory in decoded packet form + */ + private def MakeDetailedInventory(inv : GridInventory) : List[InternalSlot] = { + inv.Items + .map({ + case(_, item) => + val equip : Equipment = item.obj + InternalSlot(equip.Definition.ObjectId, equip.GUID, item.start, equip.Definition.Packet.DetailedConstructorData(equip).get) + }).toList + } } diff --git a/common/src/test/scala/objects/ConverterTest.scala b/common/src/test/scala/objects/ConverterTest.scala index 636357e78..2bcde21f0 100644 --- a/common/src/test/scala/objects/ConverterTest.scala +++ b/common/src/test/scala/objects/ConverterTest.scala @@ -155,6 +155,7 @@ class ConverterTest extends Specification { tool.AmmoSlots.head.Box = box1 val obj = Player(PlanetSideGUID(93), "Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5) obj.Slot(2).Equipment = tool + obj.Slot(5).Equipment.get.GUID = PlanetSideGUID(94) obj.Inventory += 8 -> box2 obj.Definition.Packet.DetailedConstructorData(obj).isSuccess mustEqual true @@ -163,11 +164,11 @@ class ConverterTest extends Specification { } "LockerContainer" should { - "convert to packet" in { + "convert to packet (empty)" in { val obj = LockerContainer() obj.Definition.Packet.DetailedConstructorData(obj) match { case Success(pkt) => - pkt mustEqual DetailedLockerContainerData(8) + pkt mustEqual DetailedLockerContainerData(8, None) case _ => ko } @@ -178,6 +179,27 @@ class ConverterTest extends Specification { ko } } + + "convert to packet (occupied)" in { + import GlobalDefinitions._ + val obj = LockerContainer() + val rek = SimpleItem(remote_electronics_kit) + rek.GUID = PlanetSideGUID(1) + obj.Inventory += 0 -> rek + + obj.Definition.Packet.DetailedConstructorData(obj) match { + case Success(pkt) => + pkt mustEqual DetailedLockerContainerData(8, InternalSlot(remote_electronics_kit.ObjectId, PlanetSideGUID(1), 0, DetailedREKData(8)) :: Nil) + case _ => + ko + } + obj.Definition.Packet.ConstructorData(obj) match { + case Success(pkt) => + pkt mustEqual LockerContainerData(InventoryData(InternalSlot(remote_electronics_kit.ObjectId, PlanetSideGUID(1), 0, REKData(8,0)) :: Nil)) + case _ => + ko + } + } } "Vehicle" should { diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index 52094defe..f91367a46 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -564,7 +564,7 @@ class WorldSessionActor extends Actor with MDCContextAware { forceblade1 = Tool(forceblade) forceblade1.AmmoSlots.head.Box = melee_ammo_box val rek = SimpleItem(remote_electronics_kit) - val lockerContainer = LockerContainer() + val extra_rek = SimpleItem(remote_electronics_kit) val player = Player("IlllIIIlllIlIllIlllIllI", PlanetSideEmpire.VS, CharacterGender.Female, 41, 1) player.Position = Vector3(3674.8438f, 2726.789f, 91.15625f) @@ -573,13 +573,13 @@ class WorldSessionActor extends Actor with MDCContextAware { player.Slot(0).Equipment = beamer1 player.Slot(2).Equipment = suppressor1 player.Slot(4).Equipment = forceblade1 - player.Slot(5).Equipment = lockerContainer player.Slot(6).Equipment = bullet_9mm_box1 player.Slot(9).Equipment = bullet_9mm_box2 player.Slot(12).Equipment = bullet_9mm_box3 player.Slot(33).Equipment = bullet_9mm_AP_box player.Slot(36).Equipment = energy_cell_box1 player.Slot(39).Equipment = rek + player.Slot(5).Equipment.get.asInstanceOf[LockerContainer].Inventory += 0 -> extra_rek //for player2 val energy_cell_box3 = AmmoBox(PlanetSideGUID(187), energy_cell) @@ -603,8 +603,6 @@ class WorldSessionActor extends Actor with MDCContextAware { val rek2 = SimpleItem(PlanetSideGUID(188), remote_electronics_kit) val - lockerContainer2 = LockerContainer(PlanetSideGUID(182)) - val player2 = Player(PlanetSideGUID(275), "Doppelganger", PlanetSideEmpire.NC, CharacterGender.Female, 41, 1) player2.Position = Vector3(3680f, 2726.789f, 91.15625f) player2.Orientation = Vector3(0f, 0f, 0f) @@ -612,7 +610,7 @@ class WorldSessionActor extends Actor with MDCContextAware { player2.Slot(0).Equipment = beamer2 player2.Slot(2).Equipment = suppressor2 player2.Slot(4).Equipment = forceblade2 - player2.Slot(5).Equipment = lockerContainer2 + player2.Slot(5).Equipment.get.GUID = PlanetSideGUID(182) player2.Slot(6).Equipment = bullet_9mm_box5 player2.Slot(9).Equipment = bullet_9mm_box6 player2.Slot(12).Equipment = bullet_9mm_box7 @@ -1271,8 +1269,8 @@ class WorldSessionActor extends Actor with MDCContextAware { private def RegisterAvatar(tplayer : Player) : TaskResolver.GiveTask = { val holsterTasks = recursiveHolsterTaskBuilding(tplayer.Holsters().iterator, RegisterEquipment) val fifthHolsterTask = tplayer.Slot(5).Equipment match { - case Some(item) => - RegisterEquipment(item) :: Nil + case Some(locker) => + RegisterObjectTask(locker) :: locker.asInstanceOf[LockerContainer].Inventory.Items.map({ case((_ : Int, entry : InventoryItem)) => RegisterEquipment(entry.obj)}).toList case None => List.empty[TaskResolver.GiveTask]; } @@ -1399,8 +1397,8 @@ class WorldSessionActor extends Actor with MDCContextAware { val holsterTasks = recursiveHolsterTaskBuilding(tplayer.Holsters().iterator, UnregisterEquipment) val inventoryTasks = tplayer.Inventory.Items.map({ case((_ : Int, entry : InventoryItem)) => UnregisterEquipment(entry.obj)}) val fifthHolsterTask = tplayer.Slot(5).Equipment match { - case Some(item) => - UnregisterEquipment(item) :: Nil + case Some(locker) => + UnregisterObjectTask(locker) :: locker.asInstanceOf[LockerContainer].Inventory.Items.map({ case((_ : Int, entry : InventoryItem)) => UnregisterEquipment(entry.obj)}).toList case None => List.empty[TaskResolver.GiveTask]; } @@ -1422,7 +1420,14 @@ class WorldSessionActor extends Actor with MDCContextAware { tplayer.Inventory.Items.foreach({ case((_, entry : InventoryItem)) => SetCharacterSelectScreenGUID_SelectEquipment(Some(entry.obj), gen) }) - tplayer.Slot(5).Equipment.get.GUID = PlanetSideGUID(gen.getAndIncrement) + tplayer.Slot(5).Equipment match { + case Some(locker) => + locker.GUID = PlanetSideGUID(gen.getAndIncrement) + locker.asInstanceOf[LockerContainer].Inventory.Items.foreach({ case((_, entry : InventoryItem)) => + SetCharacterSelectScreenGUID_SelectEquipment(Some(entry.obj), gen) + }) + case None => ; + } tplayer.GUID = PlanetSideGUID(gen.getAndIncrement) } @@ -1457,7 +1462,14 @@ class WorldSessionActor extends Actor with MDCContextAware { tplayer.Inventory.Items.foreach({ case((_, entry : InventoryItem)) => RemoveCharacterSelectScreenGUID_SelectEquipment(Some(entry.obj)) }) - tplayer.Slot(5).Equipment.get.Invalidate() + tplayer.Slot(5).Equipment match { + case Some(locker) => + locker.Invalidate() + locker.asInstanceOf[LockerContainer].Inventory.Items.foreach({ case((_, entry : InventoryItem)) => + RemoveCharacterSelectScreenGUID_SelectEquipment(Some(entry.obj)) + }) + case None => ; + } tplayer.Invalidate() }