Merge pull request #782 from Fate-JH/locker-swap

Right Click Locker Swap
This commit is contained in:
Fate-JH 2021-04-21 17:32:13 -04:00 committed by GitHub
commit c515c727ff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -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"