mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-25 04:54:45 +00:00
added DetailedLockerContainerData Codec; modified PacketConverter for LockerContainer; modified tests
This commit is contained in:
parent
3e5e8a2573
commit
110dcdf675
|
|
@ -5,7 +5,7 @@ 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.{DetailedAmmoBoxData, InternalSlot, InventoryData, LockerContainerData}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
|
||||
import scala.util.{Success, Try}
|
||||
|
||||
|
|
@ -14,8 +14,8 @@ class LockerContainerConverter extends ObjectCreateConverter[LockerContainer]()
|
|||
Success(LockerContainerData(InventoryData(MakeInventory(obj.Inventory))))
|
||||
}
|
||||
|
||||
override def DetailedConstructorData(obj : LockerContainer) : Try[DetailedAmmoBoxData] = {
|
||||
Success(DetailedAmmoBoxData(8, 1)) //same format as AmmoBox data
|
||||
override def DetailedConstructorData(obj : LockerContainer) : Try[DetailedLockerContainerData] = {
|
||||
Success(DetailedLockerContainerData(8))
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,89 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.packet.game.objectcreate
|
||||
|
||||
import net.psforever.packet.Marshallable
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import scodec.codecs._
|
||||
import scodec.{Attempt, Codec, Err}
|
||||
import shapeless.{::, HNil}
|
||||
|
||||
/**
|
||||
* A representation of the inventory portion of `ObjectCreateDetailedMessage` packet data that contains the items in the avatar's locker space.<br>
|
||||
* <br>
|
||||
* Although these items are technically always loaded and registered with globally unique identifiers for the current zone,
|
||||
* the actual container for them, in grid format, can only be accessed by interacting with locker objects in the game world.
|
||||
* Items are generally added and removed in the same way as with any other opened inventory.
|
||||
* Unlike other inventories, however, locker space is personal to an avatar and can not be accessed by other players.
|
||||
* @param unk na
|
||||
* @param contents the items in the inventory
|
||||
*/
|
||||
final case class DetailedLockerContainerData(unk : Int,
|
||||
contents : Option[List[InternalSlot]]
|
||||
) extends ConstructorData {
|
||||
override def bitsize : Long = {
|
||||
val base : Long = 40L
|
||||
var invSize : Long = 0L //length of all items in inventory
|
||||
if(contents.isDefined) {
|
||||
invSize = InventoryData.BaseSize
|
||||
for(item <- contents.get) {
|
||||
invSize += item.bitsize
|
||||
}
|
||||
}
|
||||
base + invSize
|
||||
}
|
||||
}
|
||||
|
||||
object DetailedLockerContainerData extends Marshallable[DetailedLockerContainerData] {
|
||||
/**
|
||||
* Overloaded constructor for creating `DetailedLockerContainerData` without a list of contents.
|
||||
* @param unk na
|
||||
* @return a `DetailedLockerContainerData` object
|
||||
*/
|
||||
def apply(unk : Int) : DetailedLockerContainerData =
|
||||
new DetailedLockerContainerData(unk, None)
|
||||
|
||||
/**
|
||||
* Overloaded constructor for creating `DetailedLockerContainerData` containing known items.
|
||||
* @param unk na
|
||||
* @param contents the items in the inventory
|
||||
* @return a `DetailedLockerContainerData` object
|
||||
*/
|
||||
def apply(unk : Int, contents : List[InternalSlot]) : DetailedLockerContainerData =
|
||||
new DetailedLockerContainerData(unk, Some(contents))
|
||||
|
||||
/**
|
||||
* Overloaded constructor for creating `DetailedLockerContainerData` while masking use of `InternalSlot`.
|
||||
* @param cls the code for the type of object being constructed
|
||||
* @param guid the GUID this object will be assigned
|
||||
* @param parentSlot a parent-defined slot identifier that explains where the child is to be attached to the parent
|
||||
* @param locker the `DetailedLockerContainerData`
|
||||
* @return an `InternalSlot` object that encapsulates `DetailedLockerContainerData`
|
||||
*/
|
||||
def apply(cls : Int, guid : PlanetSideGUID, parentSlot : Int, locker : DetailedLockerContainerData) : InternalSlot =
|
||||
new InternalSlot(cls, guid, parentSlot, locker)
|
||||
|
||||
implicit val codec : Codec[DetailedLockerContainerData] = (
|
||||
uint4L ::
|
||||
("unk" | uint4L) :: // 8 - common - 4 - safe, 2 - stream misalignment, 1 - safe, 0 - common
|
||||
uint(15) ::
|
||||
uint16L :: //always 1
|
||||
optional(bool, InventoryData.codec_detailed)
|
||||
).exmap[DetailedLockerContainerData] (
|
||||
{
|
||||
case 0xC :: unk :: 0 :: 1 :: None :: HNil =>
|
||||
Attempt.successful(DetailedLockerContainerData(unk, None))
|
||||
|
||||
case 0xC :: unk :: 0 :: 1 :: Some(InventoryData(list)) :: HNil =>
|
||||
Attempt.successful(DetailedLockerContainerData(unk, Some(list)))
|
||||
case _ =>
|
||||
Attempt.failure(Err(s"invalid locker container data format"))
|
||||
},
|
||||
{
|
||||
case DetailedLockerContainerData(unk, None) =>
|
||||
Attempt.successful(0xC :: unk :: 0 :: 1 :: None :: HNil)
|
||||
|
||||
case DetailedLockerContainerData(unk, Some(list)) =>
|
||||
Attempt.successful(0xC :: unk :: 0 :: 1 :: Some(InventoryData(list)) :: HNil)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@ import shapeless.{::, HNil}
|
|||
*/
|
||||
final case class InventoryData(contents : List[InventoryItem] = List.empty) extends StreamBitSize {
|
||||
override def bitsize : Long = {
|
||||
val base : Long = 10L //8u + 1u + 1u
|
||||
val base : Long = InventoryData.BaseSize
|
||||
var invSize : Long = 0L //length of all items in inventory
|
||||
for(item <- contents) {
|
||||
invSize += item.bitsize
|
||||
|
|
@ -33,6 +33,8 @@ final case class InventoryData(contents : List[InventoryItem] = List.empty) exte
|
|||
}
|
||||
|
||||
object InventoryData {
|
||||
final val BaseSize : Long = 10L //8u + 1u + 1u
|
||||
|
||||
/**
|
||||
* The primary `Codec` that parses the common format for an inventory `List`.
|
||||
* @param itemCodec a `Codec` that describes each of the contents of the list
|
||||
|
|
|
|||
|
|
@ -638,7 +638,7 @@ object ObjectClass {
|
|||
case ObjectClass.boomer_trigger => ConstructorData.genericCodec(DetailedBoomerTriggerData.codec, "boomer trigger")
|
||||
//other
|
||||
case ObjectClass.avatar => ConstructorData.genericCodec(DetailedCharacterData.codec, "avatar")
|
||||
case ObjectClass.locker_container => ConstructorData.genericCodec(DetailedAmmoBoxData.codec, "locker container")
|
||||
case ObjectClass.locker_container => ConstructorData.genericCodec(DetailedLockerContainerData.codec, "locker container")
|
||||
|
||||
//failure case
|
||||
case _ => defaultFailureCodec(objClass)
|
||||
|
|
|
|||
|
|
@ -260,7 +260,8 @@ class ObjectCreateDetailedMessageTest extends Specification {
|
|||
inventory(3).objectClass mustEqual ObjectClass.locker_container
|
||||
inventory(3).guid mustEqual PlanetSideGUID(82)
|
||||
inventory(3).parentSlot mustEqual 5
|
||||
inventory(3).obj.asInstanceOf[DetailedAmmoBoxData].magazine mustEqual 1
|
||||
inventory(3).obj.isInstanceOf[DetailedLockerContainerData] mustEqual true
|
||||
inventory(3).obj.asInstanceOf[DetailedLockerContainerData].contents.isDefined mustEqual false
|
||||
//4
|
||||
inventory(4).objectClass mustEqual ObjectClass.bullet_9mm
|
||||
inventory(4).guid mustEqual PlanetSideGUID(83)
|
||||
|
|
@ -342,7 +343,7 @@ class ObjectCreateDetailedMessageTest extends Specification {
|
|||
Nil
|
||||
)(2)
|
||||
val msg = ObjectCreateDetailedMessage(ObjectClass.punisher, PlanetSideGUID(1703), ObjectCreateMessageParent(PlanetSideGUID(75), 2), obj)
|
||||
var pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_punisher
|
||||
}
|
||||
|
|
@ -394,7 +395,7 @@ class ObjectCreateDetailedMessageTest extends Specification {
|
|||
val inv = InventoryItemData(ObjectClass.beamer, PlanetSideGUID(76), 0, DetailedWeaponData(4, 8, ObjectClass.energy_cell, PlanetSideGUID(77), 0, DetailedAmmoBoxData(8, 16))) ::
|
||||
InventoryItemData(ObjectClass.suppressor, PlanetSideGUID(78), 2, DetailedWeaponData(4, 8, ObjectClass.bullet_9mm, PlanetSideGUID(79), 0, DetailedAmmoBoxData(8, 25))) ::
|
||||
InventoryItemData(ObjectClass.forceblade, PlanetSideGUID(80), 4, DetailedWeaponData(4, 8, ObjectClass.melee_ammo, PlanetSideGUID(81), 0, DetailedAmmoBoxData(8, 1))) ::
|
||||
InventoryItemData(ObjectClass.locker_container, PlanetSideGUID(82), 5, DetailedAmmoBoxData(8, 1)) ::
|
||||
InventoryItemData(ObjectClass.locker_container, PlanetSideGUID(82), 5, DetailedLockerContainerData(8)) ::
|
||||
InventoryItemData(ObjectClass.bullet_9mm, PlanetSideGUID(83), 6, DetailedAmmoBoxData(8, 50)) ::
|
||||
InventoryItemData(ObjectClass.bullet_9mm, PlanetSideGUID(84), 9, DetailedAmmoBoxData(8, 50)) ::
|
||||
InventoryItemData(ObjectClass.bullet_9mm, PlanetSideGUID(85), 12, DetailedAmmoBoxData(8, 50)) ::
|
||||
|
|
|
|||
Loading…
Reference in a new issue