mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-15 18:30:27 -04:00
Simulating the insertion instead of inserting directly
Previously the extraction was simulated and based on the simulated extraction the extracted items were inserted. This was problematic, as it relyed on the fact, that the simulation returns the same result as the actual extraction. This caused problems, as extracting a component only saves the changes to the component, when it is not simulated. Furthermore it could cause item deduplication, if the actual extraction returned something different. To solve these issues, the insertion is also simulated on the simulated extraction and the actual insertion is done on the actual extracted items.
This commit is contained in:
parent
a7eb1db087
commit
654b1507bd
@ -105,7 +105,7 @@ trait InventoryWorldControl extends InventoryAware with WorldAware with SideRest
|
||||
val blockPos = position.offset(facing)
|
||||
var extracted: Int = InventoryUtils.inventoryAt(blockPos, facing.getOpposite) match {
|
||||
case Some(inventory) => mayInteract(blockPos, facing.getOpposite)
|
||||
InventoryUtils.extractAnyFromInventory(InventoryUtils.insertIntoInventory(_, InventoryUtils.asItemHandler(this.inventory), slots = Option(insertionSlots)), inventory, count)
|
||||
InventoryUtils.extractAnyFromInventory((is, sim) => InventoryUtils.insertIntoInventory(is, InventoryUtils.asItemHandler(this.inventory), slots = Option(insertionSlots), simulate = sim), inventory, count)
|
||||
case _ => 0
|
||||
}
|
||||
if (extracted <= 0) {
|
||||
|
@ -50,7 +50,7 @@ trait InventoryWorldControlMk2 extends InventoryAware with WorldAware with SideR
|
||||
val fromSide = args.optSideAny(3, facing.getOpposite)
|
||||
withInventory(position.offset(facing), fromSide, inventory => {
|
||||
val slot = args.checkSlot(inventory, 1)
|
||||
val extracted = InventoryUtils.extractFromInventorySlot(InventoryUtils.insertIntoInventory(_, InventoryUtils.asItemHandler(this.inventory), slots = Option(insertionSlots)), inventory, slot, count)
|
||||
val extracted = InventoryUtils.extractFromInventorySlot((is, sim) => InventoryUtils.insertIntoInventory(is, InventoryUtils.asItemHandler(this.inventory), slots = Option(insertionSlots), simulate = sim), inventory, slot, count)
|
||||
if (extracted > 0) {
|
||||
context.pause(Settings.get.suckDelay)
|
||||
result(extracted)
|
||||
|
@ -21,7 +21,7 @@ trait ItemInventoryControl extends InventoryAware {
|
||||
withItemInventory(args.checkSlot(inventory, 0), itemInventory => {
|
||||
val slot = args.checkSlot(itemInventory, 1)
|
||||
val count = args.optItemCount(2)
|
||||
result(InventoryUtils.extractFromInventorySlot(InventoryUtils.insertIntoInventorySlot(_, itemInventory, slot), inventory, null, selectedSlot, count))
|
||||
result(InventoryUtils.extractFromInventorySlot((is, sim) => InventoryUtils.insertIntoInventorySlot(is, itemInventory, slot, simulate = sim), inventory, null, selectedSlot, count))
|
||||
})
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ trait ItemInventoryControl extends InventoryAware {
|
||||
withItemInventory(args.checkSlot(inventory, 0), itemInventory => {
|
||||
val slot = args.checkSlot(itemInventory, 1)
|
||||
val count = args.optItemCount(2)
|
||||
result(InventoryUtils.extractFromInventorySlot(InventoryUtils.insertIntoInventory(_, InventoryUtils.asItemHandler(inventory), slots = Option(insertionSlots)), itemInventory, slot, count))
|
||||
result(InventoryUtils.extractFromInventorySlot((is, sim) => InventoryUtils.insertIntoInventory(is, InventoryUtils.asItemHandler(inventory), slots = Option(insertionSlots), simulate = sim), itemInventory, slot, count))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -110,9 +110,9 @@ object InventoryUtils {
|
||||
* <p/>
|
||||
* Only tries to extract from the specified slot. This <em>can</em> be used
|
||||
* to empty a slot. It will extract items using the specified consumer method
|
||||
* which is called with the extracted stack before the stack in the inventory
|
||||
* that we extract from is cleared from. This allows placing back excess
|
||||
* items with as few inventory updates as possible.
|
||||
* which is called with the extracted stack and a simulation flag before the
|
||||
* stack in the inventory that we extract from is cleared from. This allows
|
||||
* placing back excess items with as few inventory updates as possible.
|
||||
* <p/>
|
||||
* The consumer is the only way to retrieve the actually extracted stack. It
|
||||
* is called with a separate stack instance, so it does not have to be copied
|
||||
@ -129,7 +129,7 @@ object InventoryUtils {
|
||||
* also be achieved by a check in the consumer, but it saves some unnecessary
|
||||
* code repetition this way.
|
||||
*/
|
||||
def extractFromInventorySlot(consumer: ItemStack => Unit, inventory: IItemHandler, slot: Int, limit: Int = 64): Int = {
|
||||
def extractFromInventorySlot(consumer: (ItemStack, Boolean) => Unit, inventory: IItemHandler, slot: Int, limit: Int = 64): Int = {
|
||||
val stack = inventory.getStackInSlot(slot)
|
||||
if (stack.isEmpty || limit <= 0 || stack.getCount <= 0)
|
||||
return 0
|
||||
@ -138,19 +138,19 @@ object InventoryUtils {
|
||||
case simExtracted: ItemStack =>
|
||||
val extracted = simExtracted.copy
|
||||
amount = extracted.getCount
|
||||
consumer(extracted)
|
||||
consumer(extracted, true)
|
||||
val count = (amount - extracted.getCount) max 0
|
||||
if (count > 0) inventory.extractItem(slot, count, false) match {
|
||||
case realExtracted: ItemStack if realExtracted.getCount == count =>
|
||||
case realExtracted: ItemStack if realExtracted.getCount == count => consumer(realExtracted, false)
|
||||
case _ =>
|
||||
OpenComputers.log.warn("Items may have been duplicated during inventory extraction. This means an IItemHandler instance acted differently between simulated and non-simulated extraction. Offender: " + inventory)
|
||||
OpenComputers.log.warn("An IItemHandler instance acted differently between simulated and non-simulated extraction. Offender: " + inventory)
|
||||
}
|
||||
count
|
||||
case _ => 0
|
||||
}
|
||||
}
|
||||
|
||||
def extractFromInventorySlot(consumer: (ItemStack) => Unit, inventory: IInventory, side: EnumFacing, slot: Int, limit: Int): Int =
|
||||
def extractFromInventorySlot(consumer: (ItemStack, Boolean) => Unit, inventory: IInventory, side: EnumFacing, slot: Int, limit: Int): Int =
|
||||
extractFromInventorySlot(consumer, asItemHandler(inventory, side), slot, limit)
|
||||
|
||||
/**
|
||||
@ -200,7 +200,7 @@ object InventoryUtils {
|
||||
* <p/>
|
||||
* This returns <tt>true</tt> if at least one item was extracted.
|
||||
*/
|
||||
def extractAnyFromInventory(consumer: ItemStack => Unit, inventory: IItemHandler, limit: Int = 64): Int = {
|
||||
def extractAnyFromInventory(consumer: (ItemStack, Boolean) => Unit, inventory: IItemHandler, limit: Int = 64): Int = {
|
||||
for (slot <- 0 until inventory.getSlots) {
|
||||
val extracted = extractFromInventorySlot(consumer, inventory, slot, limit)
|
||||
if (extracted > 0)
|
||||
@ -209,7 +209,7 @@ object InventoryUtils {
|
||||
0
|
||||
}
|
||||
|
||||
def extractAnyFromInventory(consumer: ItemStack => Unit, inventory: IInventory, side: EnumFacing, limit: Int): Int =
|
||||
def extractAnyFromInventory(consumer: (ItemStack, Boolean) => Unit, inventory: IInventory, side: EnumFacing, limit: Int): Int =
|
||||
extractAnyFromInventory(consumer, asItemHandler(inventory, side), limit)
|
||||
|
||||
/**
|
||||
@ -225,11 +225,13 @@ object InventoryUtils {
|
||||
def extractFromInventory(stack: ItemStack, inventory: IItemHandler, simulate: Boolean = false, exact: Boolean = true): ItemStack = {
|
||||
val remaining = stack.copy()
|
||||
for (slot <- 0 until inventory.getSlots if remaining.getCount > 0) {
|
||||
extractFromInventorySlot(stackInInv => {
|
||||
extractFromInventorySlot((stackInInv, simulateInsert) => {
|
||||
if (stackInInv != null && remaining.getItem == stackInInv.getItem && (!exact || haveSameItemType(remaining, stackInInv, checkNBT = true))) {
|
||||
val transferred = stackInInv.getCount min remaining.getCount
|
||||
remaining.shrink(transferred)
|
||||
if (!simulate) {
|
||||
if(!simulateInsert) {
|
||||
remaining.shrink(transferred)
|
||||
}
|
||||
if (simulateInsert || !simulate) {
|
||||
stackInInv.shrink(transferred)
|
||||
}
|
||||
}
|
||||
@ -254,7 +256,7 @@ object InventoryUtils {
|
||||
* Utility method for calling <tt>extractFromInventory</tt> on an inventory
|
||||
* in the world.
|
||||
*/
|
||||
def getExtractorFromInventoryAt(consumer: (ItemStack) => Unit, position: BlockPosition, side: EnumFacing, limit: Int = 64): Extractor =
|
||||
def getExtractorFromInventoryAt(consumer: (ItemStack, Boolean) => Unit, position: BlockPosition, side: EnumFacing, limit: Int = 64): Extractor =
|
||||
inventoryAt(position, side) match {
|
||||
case Some(inventory) => () => extractAnyFromInventory(consumer, inventory, limit)
|
||||
case _ => null
|
||||
@ -275,7 +277,7 @@ object InventoryUtils {
|
||||
*/
|
||||
def transferBetweenInventories(source: IItemHandler, sink: IItemHandler, limit: Int = 64): Int =
|
||||
extractAnyFromInventory(
|
||||
insertIntoInventory(_, sink, limit), source, limit = limit)
|
||||
insertIntoInventory(_, sink, limit, _), source, limit = limit)
|
||||
|
||||
def transferBetweenInventories(source: IInventory, sourceSide: EnumFacing, sink: IInventory, sinkSide: Option[EnumFacing], limit: Int): Int =
|
||||
transferBetweenInventories(asItemHandler(source, sourceSide), asItemHandler(sink, sinkSide.orNull), limit)
|
||||
@ -287,10 +289,10 @@ object InventoryUtils {
|
||||
sinkSlot match {
|
||||
case Some(explicitSinkSlot) =>
|
||||
extractFromInventorySlot(
|
||||
insertIntoInventorySlot(_, sink, explicitSinkSlot, limit), source, sourceSlot, limit = limit)
|
||||
insertIntoInventorySlot(_, sink, explicitSinkSlot, limit, _), source, sourceSlot, limit = limit)
|
||||
case _ =>
|
||||
extractFromInventorySlot(
|
||||
insertIntoInventory(_, sink, limit), source, sourceSlot, limit = limit)
|
||||
insertIntoInventory(_, sink, limit, _), source, sourceSlot, limit = limit)
|
||||
}
|
||||
|
||||
def transferBetweenInventoriesSlots(source: IInventory, sourceSide: EnumFacing, sourceSlot: Int, sink: IInventory, sinkSide: Option[EnumFacing], sinkSlot: Option[Int], limit: Int): Int =
|
||||
|
Loading…
x
Reference in New Issue
Block a user