mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-20 02:24:45 +00:00
commit
c5246d5f10
|
|
@ -500,6 +500,8 @@ object GlobalDefinitions {
|
|||
|
||||
val spawn_pad = new ObjectDefinition(800) { Name = "spawn_pad" }
|
||||
|
||||
val mb_locker = new ObjectDefinition(524) { Name = "mb_locker" }
|
||||
|
||||
val lock_external = new IFFLockDefinition
|
||||
|
||||
val door = new DoorDefinition
|
||||
|
|
|
|||
|
|
@ -2,17 +2,55 @@
|
|||
package net.psforever.objects
|
||||
|
||||
import net.psforever.objects.definition.EquipmentDefinition
|
||||
import net.psforever.objects.definition.converter.LockerContainerConverter
|
||||
import net.psforever.objects.equipment.{Equipment, EquipmentSize}
|
||||
import net.psforever.objects.inventory.GridInventory
|
||||
import net.psforever.objects.equipment.Equipment
|
||||
import net.psforever.objects.inventory.{Container, GridInventory, InventoryItem}
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
|
||||
class LockerContainer extends Equipment {
|
||||
import scala.annotation.tailrec
|
||||
|
||||
class LockerContainer extends Equipment with Container {
|
||||
private val inventory = GridInventory(30, 20)
|
||||
|
||||
def Inventory : GridInventory = inventory
|
||||
|
||||
def VisibleSlots : Set[Int] = Set.empty[Int]
|
||||
|
||||
override def Slot(slot : Int) : EquipmentSlot = {
|
||||
if(inventory.Offset <= slot && slot <= inventory.LastIndex) {
|
||||
inventory.Slot(slot)
|
||||
}
|
||||
else {
|
||||
OffhandEquipmentSlot.BlockedSlot
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def Fit(obj : Equipment) : Option[Int] = inventory.Fit(obj.Definition.Tile)
|
||||
|
||||
def Find(guid : PlanetSideGUID) : Option[Int] = {
|
||||
findInInventory(inventory.Items.values.iterator, guid) match {
|
||||
case Some(index) =>
|
||||
Some(index)
|
||||
case None =>
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@tailrec private def findInInventory(iter : Iterator[InventoryItem], guid : PlanetSideGUID) : Option[Int] = {
|
||||
if(!iter.hasNext) {
|
||||
None
|
||||
}
|
||||
else {
|
||||
val item = iter.next
|
||||
if(item.obj.GUID == guid) {
|
||||
Some(item.start)
|
||||
}
|
||||
else {
|
||||
findInInventory(iter, guid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def Definition : EquipmentDefinition = GlobalDefinitions.locker_container
|
||||
}
|
||||
|
||||
|
|
@ -20,11 +58,4 @@ object LockerContainer {
|
|||
def apply() : LockerContainer = {
|
||||
new LockerContainer()
|
||||
}
|
||||
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
def apply(guid : PlanetSideGUID) : LockerContainer = {
|
||||
val obj = new LockerContainer()
|
||||
obj.GUID = guid
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,6 +188,8 @@ class Player(private val name : String,
|
|||
|
||||
def Inventory : GridInventory = inventory
|
||||
|
||||
def Locker : LockerContainer = fifthSlot.Equipment.get.asInstanceOf[LockerContainer]
|
||||
|
||||
def Fit(obj : Equipment) : Option[Int] = {
|
||||
recursiveHolsterFit(holsters.iterator, obj.Size) match {
|
||||
case Some(index) =>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects.serverobject.mblocker
|
||||
|
||||
import akka.actor.ActorContext
|
||||
import net.psforever.objects.GlobalDefinitions
|
||||
import net.psforever.objects.definition.ObjectDefinition
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
|
||||
class Locker extends PlanetSideServerObject {
|
||||
def Definition : ObjectDefinition = GlobalDefinitions.mb_locker
|
||||
}
|
||||
|
||||
object Locker {
|
||||
/**
|
||||
* Overloaded constructor.
|
||||
* @return a `VehicleSpawnPad` object
|
||||
*/
|
||||
def apply() : Locker = {
|
||||
new Locker()
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate an configure a `Locker` object
|
||||
* @param id the unique id that will be assigned to this entity
|
||||
* @param context a context to allow the object to properly set up `ActorSystem` functionality;
|
||||
* not necessary for this object, but required by signature
|
||||
* @return the `Locker` object
|
||||
*/
|
||||
def Constructor(id : Int, context : ActorContext) : Locker = {
|
||||
val obj = Locker()
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,6 @@
|
|||
package objects
|
||||
|
||||
import akka.actor.{Actor, Props}
|
||||
import net.psforever.objects.GlobalDefinitions.order_terminal
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.objects.serverobject.ServerObjectBuilder
|
||||
|
|
@ -62,6 +61,7 @@ class ImplantTerminalMechObjectBuilderTest extends ActorTest {
|
|||
}
|
||||
|
||||
class TerminalObjectBuilderTest extends ActorTest {
|
||||
import net.psforever.objects.GlobalDefinitions.order_terminal
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
"TerminalObjectBuilder" should {
|
||||
"build" in {
|
||||
|
|
@ -99,6 +99,24 @@ class VehicleSpawnPadObjectBuilderTest extends ActorTest {
|
|||
}
|
||||
}
|
||||
|
||||
class LockerObjectBuilderTest extends ActorTest {
|
||||
import net.psforever.objects.serverobject.mblocker.Locker
|
||||
"LockerObjectBuilder" should {
|
||||
"build" in {
|
||||
val hub = ServerObjectBuilderTest.NumberPoolHub
|
||||
val actor = system.actorOf(Props(classOf[ServerObjectBuilderTest.BuilderTestActor], ServerObjectBuilder(1,
|
||||
Locker.Constructor), hub), "locker")
|
||||
actor ! "!"
|
||||
|
||||
val reply = receiveOne(Duration.create(1000, "ms"))
|
||||
assert(reply.isInstanceOf[Locker])
|
||||
assert(reply.asInstanceOf[Locker].HasGUID)
|
||||
assert(reply.asInstanceOf[Locker].GUID == PlanetSideGUID(1))
|
||||
assert(reply == hub(1).get)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object ServerObjectBuilderTest {
|
||||
import net.psforever.objects.guid.source.LimitedNumberSource
|
||||
def NumberPoolHub : NumberPoolHub = {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import net.psforever.objects.serverobject.ServerObjectBuilder
|
|||
import net.psforever.objects.serverobject.doors.Door
|
||||
import net.psforever.objects.serverobject.implantmech.ImplantTerminalMech
|
||||
import net.psforever.objects.serverobject.locks.IFFLock
|
||||
import net.psforever.objects.serverobject.mblocker.Locker
|
||||
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
import net.psforever.types.Vector3
|
||||
|
|
@ -62,6 +63,14 @@ object Maps {
|
|||
LocalObject(ServerObjectBuilder(529, ImplantTerminalMech.Constructor)) //Hart C
|
||||
LocalObject(ServerObjectBuilder(556, IFFLock.Constructor))
|
||||
LocalObject(ServerObjectBuilder(558, IFFLock.Constructor))
|
||||
LocalObject(ServerObjectBuilder(686, Locker.Constructor))
|
||||
LocalObject(ServerObjectBuilder(687, Locker.Constructor))
|
||||
LocalObject(ServerObjectBuilder(688, Locker.Constructor))
|
||||
LocalObject(ServerObjectBuilder(689, Locker.Constructor))
|
||||
LocalObject(ServerObjectBuilder(690, Locker.Constructor))
|
||||
LocalObject(ServerObjectBuilder(691, Locker.Constructor))
|
||||
LocalObject(ServerObjectBuilder(692, Locker.Constructor))
|
||||
LocalObject(ServerObjectBuilder(693, Locker.Constructor))
|
||||
LocalObject(ServerObjectBuilder(186, Terminal.Constructor(cert_terminal)))
|
||||
LocalObject(ServerObjectBuilder(187, Terminal.Constructor(cert_terminal)))
|
||||
LocalObject(ServerObjectBuilder(188, Terminal.Constructor(cert_terminal)))
|
||||
|
|
@ -95,17 +104,17 @@ object Maps {
|
|||
ObjectToBase(330, 29)
|
||||
ObjectToBase(332, 29)
|
||||
//ObjectToBase(520, 29)
|
||||
ObjectToBase(522, 29)
|
||||
ObjectToBase(523, 29)
|
||||
ObjectToBase(524, 29)
|
||||
ObjectToBase(525, 29)
|
||||
ObjectToBase(526, 29)
|
||||
ObjectToBase(527, 29)
|
||||
ObjectToBase(528, 29)
|
||||
ObjectToBase(529, 29)
|
||||
ObjectToBase(522, 2)
|
||||
ObjectToBase(523, 2)
|
||||
ObjectToBase(524, 2)
|
||||
ObjectToBase(525, 2)
|
||||
ObjectToBase(526, 2)
|
||||
ObjectToBase(527, 2)
|
||||
ObjectToBase(528, 2)
|
||||
ObjectToBase(529, 2)
|
||||
ObjectToBase(556, 29)
|
||||
ObjectToBase(558, 29)
|
||||
ObjectToBase(1081, 29)
|
||||
ObjectToBase(1081, 2)
|
||||
ObjectToBase(1063, 2) //TODO unowned courtyard terminal?
|
||||
ObjectToBase(500, 2) //TODO unowned courtyard spawnpad?
|
||||
ObjectToBase(304, 2) //TODO unowned courtyard terminal?
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObjec
|
|||
import net.psforever.objects.serverobject.doors.Door
|
||||
import net.psforever.objects.serverobject.implantmech.ImplantTerminalMech
|
||||
import net.psforever.objects.serverobject.locks.IFFLock
|
||||
import net.psforever.objects.serverobject.mblocker.Locker
|
||||
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
|
||||
import net.psforever.objects.serverobject.terminals.Terminal
|
||||
import net.psforever.objects.vehicles.{AccessPermissionGroup, VehicleLockState}
|
||||
|
|
@ -48,6 +49,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
var continent : Zone = null
|
||||
var progressBarValue : Option[Float] = None
|
||||
var shooting : Option[PlanetSideGUID] = None
|
||||
var accessedContainer : Option[PlanetSideGameObject with Container] = None
|
||||
|
||||
var clientKeepAlive : Cancellable = DefaultCancellable.obj
|
||||
var progressBarUpdate : Cancellable = DefaultCancellable.obj
|
||||
|
|
@ -1460,7 +1462,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
previousBox.Capacity = capacity
|
||||
}
|
||||
|
||||
|
||||
if(previousBox.Capacity > 0) {
|
||||
//TODO split previousBox into AmmoBox objects of appropriate max capacity, e.g., 100 9mm -> 2 x 50 9mm
|
||||
obj.Inventory.Fit(previousBox.Definition.Tile) match {
|
||||
|
|
@ -1677,13 +1679,24 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
|
||||
case Some(obj : Equipment) =>
|
||||
player.Find(object_guid) match { //player should be holding it
|
||||
case Some(slot) =>
|
||||
taskResolver ! RemoveEquipmentFromSlot(player, player.Slot(slot).Equipment.get, slot)
|
||||
val findFunc : PlanetSideGameObject with Container => Option[(PlanetSideGameObject with Container, Option[Int])] = FindInLocalContainer(object_guid)
|
||||
|
||||
findFunc(player)
|
||||
.orElse(findFunc(player.Locker))
|
||||
.orElse(accessedContainer match {
|
||||
case Some(parent) =>
|
||||
findFunc(parent)
|
||||
case None =>
|
||||
None
|
||||
}) match {
|
||||
case Some((parent, Some(slot))) =>
|
||||
taskResolver ! RemoveEquipmentFromSlot(parent, obj, slot)
|
||||
log.info(s"RequestDestroy: equipment $object_guid")
|
||||
case None =>
|
||||
|
||||
case _ =>
|
||||
//TODO search for item on ground
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, ObjectDeleteMessage(object_guid, 0)))
|
||||
log.warn(s"RequestDestroy: object $object_guid not found in player hands")
|
||||
log.warn(s"RequestDestroy: object $object_guid not found")
|
||||
}
|
||||
|
||||
case None =>
|
||||
|
|
@ -1698,6 +1711,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
log.info("ObjectDelete: " + msg)
|
||||
|
||||
case msg @ MoveItemMessage(item_guid, source_guid, destination_guid, dest, unk1) =>
|
||||
log.info(s"MoveItem: $msg")
|
||||
(continent.GUID(source_guid), continent.GUID(destination_guid), continent.GUID(item_guid)) match {
|
||||
case (Some(source : Container), Some(destination : Container), Some(item : Equipment)) =>
|
||||
source.Find(item_guid) match {
|
||||
|
|
@ -1842,6 +1856,11 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case _ => ;
|
||||
}
|
||||
|
||||
case Some(obj : Locker) =>
|
||||
val container = player.Locker
|
||||
accessedContainer = Some(container)
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, UseItemMessage(avatar_guid, unk1, container.GUID, unk2, unk3, unk4, unk5, unk6, unk7, unk8, 456)))
|
||||
|
||||
case Some(obj : Vehicle) =>
|
||||
if(obj.Faction == player.Faction) {
|
||||
val equipment = player.Slot(player.DrawnSlot).Equipment
|
||||
|
|
@ -1856,6 +1875,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
//access to trunk
|
||||
if(obj.AccessingTrunk.isEmpty) {
|
||||
obj.AccessingTrunk = player.GUID
|
||||
accessedContainer = Some(obj)
|
||||
AccessContents(obj)
|
||||
sendResponse(PacketCoding.CreateGamePacket(0, UseItemMessage(avatar_guid, unk1, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType)))
|
||||
}
|
||||
|
|
@ -1900,6 +1920,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
|
||||
case _ =>;
|
||||
}
|
||||
accessedContainer = None
|
||||
|
||||
case msg @ DeployObjectMessage(guid, unk1, pos, roll, pitch, yaw, unk2) =>
|
||||
log.info("DeployObject: " + msg)
|
||||
|
|
@ -2891,6 +2912,24 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
GlobalDefinitions.isCavernEquipment(objDef) || (faction != tplayer.Faction && faction != PlanetSideEmpire.NEUTRAL)
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an object globally unique identifier, search in a given location for it.
|
||||
* @param object_guid the object
|
||||
* @param parent a `Container` object wherein to search
|
||||
* @return an optional tuple that contains two values;
|
||||
* the first value is the container that matched correctly with the object's GUID;
|
||||
* the second value is the slot position of the object
|
||||
*/
|
||||
def FindInLocalContainer(object_guid : PlanetSideGUID)(parent : PlanetSideGameObject with Container) : Option[(PlanetSideGameObject with Container, Option[Int])] = {
|
||||
val slot : Option[Int] = parent.Find(object_guid)
|
||||
slot match {
|
||||
case place @ Some(_) =>
|
||||
Some(parent, slot)
|
||||
case None =>
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
def failWithError(error : String) = {
|
||||
log.error(error)
|
||||
sendResponse(PacketCoding.CreateControlPacket(ConnectionClose()))
|
||||
|
|
|
|||
Loading…
Reference in a new issue