mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-04-29 16:25:30 +00:00
Merge pull request #782 from Fate-JH/locker-swap
Right Click Locker Swap
This commit is contained in:
commit
c515c727ff
1 changed files with 78 additions and 32 deletions
|
|
@ -20,7 +20,7 @@ import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
import scala.concurrent.Future
|
import scala.concurrent.Future
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
import scala.language.implicitConversions
|
import scala.language.implicitConversions
|
||||||
import scala.util.{Failure, Success}
|
import scala.util.{Failure, Success, Try}
|
||||||
|
|
||||||
object WorldSession {
|
object WorldSession {
|
||||||
|
|
||||||
|
|
@ -67,6 +67,41 @@ object WorldSession {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this for placing equipment that has yet to be registered into a container,
|
||||||
|
* such as in support of changing ammunition types in `Tool` objects (weapons).
|
||||||
|
* Equipment will go wherever it fits in containing object, or be dropped if it fits nowhere.
|
||||||
|
* Item swapping during the placement is not allowed.
|
||||||
|
* @see `ChangeAmmoMessage`
|
||||||
|
* @see `GUIDTask.RegisterEquipment`
|
||||||
|
* @see `PutEquipmentInInventoryOrDrop`
|
||||||
|
* @see `Task`
|
||||||
|
* @see `TaskResolver.GiveTask`
|
||||||
|
* @param obj the container
|
||||||
|
* @param item the item being manipulated
|
||||||
|
* @return a `TaskResolver` object
|
||||||
|
*/
|
||||||
|
def PutNewEquipmentInInventorySlot(
|
||||||
|
obj: PlanetSideServerObject with Container
|
||||||
|
)(item: Equipment, slot: Int): TaskResolver.GiveTask = {
|
||||||
|
val localZone = obj.Zone
|
||||||
|
TaskResolver.GiveTask(
|
||||||
|
new Task() {
|
||||||
|
private val localContainer = obj
|
||||||
|
private val localItem = item
|
||||||
|
private val localSlot = slot
|
||||||
|
|
||||||
|
override def isComplete: Task.Resolution.Value = Task.Resolution.Success
|
||||||
|
|
||||||
|
def Execute(resolver: ActorRef): Unit = {
|
||||||
|
PutEquipmentInInventorySlot(localContainer)(localItem, localSlot)
|
||||||
|
resolver ! Success(this)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
List(GUIDTask.RegisterEquipment(item)(localZone.GUID))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use this for placing equipment that has yet to be registered into a container,
|
* Use this for placing equipment that has yet to be registered into a container,
|
||||||
* such as in support of changing ammunition types in `Tool` objects (weapons).
|
* such as in support of changing ammunition types in `Tool` objects (weapons).
|
||||||
|
|
@ -560,45 +595,40 @@ object WorldSession {
|
||||||
item: Equipment,
|
item: Equipment,
|
||||||
dest: Int
|
dest: Int
|
||||||
): Unit = {
|
): Unit = {
|
||||||
val registrationTask = GUIDTask.UnregisterEquipment(item)(source.Zone.GUID)
|
val (performSwap, swapItemGUID): (Boolean, Option[PlanetSideGUID]) = {
|
||||||
//check for the existence of a swap item - account for that in advance
|
|
||||||
val (subtasks, swapItemGUID): (List[TaskResolver.GiveTask], Option[PlanetSideGUID]) = {
|
|
||||||
val tile = item.Definition.Tile
|
val tile = item.Definition.Tile
|
||||||
destination.Inventory.CheckCollisionsVar(dest, tile.Width, tile.Height)
|
destination.Inventory.CheckCollisionsVar(dest, tile.Width, tile.Height)
|
||||||
} match {
|
} match {
|
||||||
case Success(Nil) =>
|
case Success(Nil) =>
|
||||||
//no swap item
|
//no swap item
|
||||||
(List(registrationTask), None)
|
(true, None)
|
||||||
case Success(List(swapEntry: InventoryItem)) =>
|
case Success(List(swapEntry: InventoryItem)) =>
|
||||||
//the swap item is to be registered to the source's zone
|
//the swap item is to be registered to the source's zone
|
||||||
/*
|
(true, Some(swapEntry.obj.GUID))
|
||||||
destination is a locker container that has its own internal unique number system
|
|
||||||
the swap item is currently registered to this system
|
|
||||||
the swap item will be moved into the system in which the source operates
|
|
||||||
to facilitate the transfer, the item needs to be partially unregistered from the destination's system
|
|
||||||
to facilitate the transfer, the item needs to be preemptively registered to the source's system
|
|
||||||
invalidating the current unique number is sufficient for both of these steps
|
|
||||||
*/
|
|
||||||
val swapItem = swapEntry.obj
|
|
||||||
swapItem.Invalidate()
|
|
||||||
(List(GUIDTask.RegisterEquipment(swapItem)(source.Zone.GUID), registrationTask), Some(swapItem.GUID))
|
|
||||||
case _ =>
|
case _ =>
|
||||||
//too many swap items or other error; this attempt will probably fail
|
//too many swap items or other error; this attempt will not execute
|
||||||
(Nil, None)
|
(false, None)
|
||||||
}
|
}
|
||||||
destination.Zone.tasks ! TaskResolver.GiveTask(
|
if (performSwap) {
|
||||||
new Task() {
|
def moveItemTaskFunc(toSlot: Int): Task = new Task() {
|
||||||
val localGUID = swapItemGUID //the swap item's original GUID, if any swap item
|
val localGUID = swapItemGUID //the swap item's original GUID, if any swap item
|
||||||
val localChannel = toChannel
|
val localChannel = toChannel
|
||||||
val localSource = source
|
val localSource = source
|
||||||
val localDestination = destination
|
val localDestination = destination
|
||||||
val localItem = item
|
val localItem = item
|
||||||
val localSlot = dest
|
val localDestSlot = dest
|
||||||
|
val localSrcSlot = toSlot
|
||||||
|
val localMoveOnComplete: Try[Any] => Unit = {
|
||||||
|
case Success(Containable.ItemPutInSlot(_, _, _, Some(swapItem))) =>
|
||||||
|
//swapItem is not registered right now, we can not drop the item without re-registering it
|
||||||
|
localSource.Zone.tasks ! PutNewEquipmentInInventorySlot(localSource)(swapItem, localSrcSlot)
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
|
||||||
override def Description: String = s"unregistering $localItem before stowing in $localDestination"
|
override def Description: String = s"unregistering $localItem before stowing in $localDestination"
|
||||||
|
|
||||||
override def isComplete: Task.Resolution.Value = {
|
override def isComplete: Task.Resolution.Value = {
|
||||||
if (localItem.HasGUID && localDestination.Find(localItem).contains(localSlot)) {
|
if (localItem.HasGUID && localDestination.Find(localItem).contains(localDestSlot)) {
|
||||||
Task.Resolution.Success
|
Task.Resolution.Success
|
||||||
} else {
|
} else {
|
||||||
Task.Resolution.Incomplete
|
Task.Resolution.Incomplete
|
||||||
|
|
@ -609,16 +639,28 @@ object WorldSession {
|
||||||
localGUID match {
|
localGUID match {
|
||||||
case Some(guid) =>
|
case Some(guid) =>
|
||||||
//see LockerContainerControl.RemoveItemFromSlotCallback
|
//see LockerContainerControl.RemoveItemFromSlotCallback
|
||||||
val zone = localSource.Zone
|
localSource.Zone.AvatarEvents ! AvatarServiceMessage(
|
||||||
zone.AvatarEvents ! AvatarServiceMessage(localChannel, AvatarAction.ObjectDelete(Service.defaultPlayerGUID, guid))
|
localChannel,
|
||||||
|
AvatarAction.ObjectDelete(Service.defaultPlayerGUID, guid)
|
||||||
|
)
|
||||||
case None => ;
|
case None => ;
|
||||||
}
|
}
|
||||||
localSource.Actor ! Containable.MoveItem(localDestination, localItem, localSlot)
|
val moveResult = ask(localDestination.Actor, Containable.PutItemInSlotOrAway(localItem, Some(localDestSlot)))
|
||||||
|
moveResult.onComplete(localMoveOnComplete)
|
||||||
resolver ! Success(this)
|
resolver ! Success(this)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
subtasks
|
val resultOnComplete: Try[Any] => Unit = {
|
||||||
)
|
case Success(Containable.ItemFromSlot(fromSource, Some(itemToMove), Some(fromSlot))) =>
|
||||||
|
destination.Zone.tasks ! TaskResolver.GiveTask(
|
||||||
|
moveItemTaskFunc(fromSlot),
|
||||||
|
List(GUIDTask.UnregisterEquipment(itemToMove)(fromSource.Zone.GUID))
|
||||||
|
)
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
val result = ask(source.Actor, Containable.RemoveItemFromSlot(item))
|
||||||
|
result.onComplete(resultOnComplete)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -670,6 +712,10 @@ object WorldSession {
|
||||||
invalidating the current unique number is sufficient for both of these steps
|
invalidating the current unique number is sufficient for both of these steps
|
||||||
*/
|
*/
|
||||||
localItem.Invalidate()
|
localItem.Invalidate()
|
||||||
|
localItem match {
|
||||||
|
case t: Tool => t.AmmoSlots.foreach { _.Box.Invalidate() }
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
|
||||||
override def Description: String = s"registering $localItem in ${localDestination.Zone.id} before removing from $localSource"
|
override def Description: String = s"registering $localItem in ${localDestination.Zone.id} before removing from $localSource"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue