mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-16 18:55:03 -04:00
Merge pull request #2175 from Vexatos/itemhandlers
Rewrote InventoryUtils to use IItemHandlers.
This commit is contained in:
commit
1ad747e486
@ -13,6 +13,7 @@ import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@ -224,10 +225,20 @@ public final class Driver {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an inventory implementation providing access to an item inventory.
|
||||
* @deprecated Use {@link #itemHandlerFor(ItemStack, EntityPlayer)} instead.
|
||||
*/
|
||||
@Deprecated // TODO Remove in OC 1.7
|
||||
public static IInventory inventoryFor(ItemStack stack, EntityPlayer player) {
|
||||
if (API.driver != null)
|
||||
return API.driver.inventoryFor(stack, player);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an IItemHandler implementation providing access to an item inventory.
|
||||
* <p/>
|
||||
* This will use the registered {@link InventoryProvider}s to find an
|
||||
* inventory implementation providing access to the specified stack.
|
||||
* IItemHandler implementation providing access to the specified stack.
|
||||
* If none can be found, returns <tt>null</tt>.
|
||||
* <p/>
|
||||
* Note that the specified <tt>player</tt> may be null, but will usually
|
||||
@ -235,11 +246,11 @@ public final class Driver {
|
||||
*
|
||||
* @param stack the item stack to get the inventory access for.
|
||||
* @param player the player holding the item. May be <tt>null</tt>.
|
||||
* @return the inventory implementation interfacing the stack, or <tt>null</tt>.
|
||||
* @return the IItemHandler implementation interfacing the stack, or <tt>null</tt>.
|
||||
*/
|
||||
public static IInventory inventoryFor(ItemStack stack, EntityPlayer player) {
|
||||
public static IItemHandler itemHandlerFor(ItemStack stack, EntityPlayer player) {
|
||||
if (API.driver != null)
|
||||
return API.driver.inventoryFor(stack, player);
|
||||
return API.driver.itemHandlerFor(stack, player);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -279,4 +290,4 @@ public final class Driver {
|
||||
|
||||
private Driver() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@ -170,10 +171,16 @@ public interface DriverAPI {
|
||||
Class<?> environmentFor(ItemStack stack);
|
||||
|
||||
/**
|
||||
* Get an inventory implementation providing access to an item inventory.
|
||||
* @deprecated Use {@link #itemHandlerFor(ItemStack, EntityPlayer)} instead.
|
||||
*/
|
||||
@Deprecated // TODO Remove in OC 1.7
|
||||
IInventory inventoryFor(ItemStack stack, EntityPlayer player);
|
||||
|
||||
/**
|
||||
* Get an IItemHandler implementation providing access to an item inventory.
|
||||
* <p/>
|
||||
* This will use the registered {@link InventoryProvider}s to find an
|
||||
* inventory implementation providing access to the specified stack.
|
||||
* IItemHandler implementation providing access to the specified stack.
|
||||
* If none can be found, returns <tt>null</tt>.
|
||||
* <p/>
|
||||
* Note that the specified <tt>player</tt> may be null, but will usually
|
||||
@ -181,9 +188,9 @@ public interface DriverAPI {
|
||||
*
|
||||
* @param stack the item stack to get the inventory access for.
|
||||
* @param player the player holding the item. May be <tt>null</tt>.
|
||||
* @return the inventory implementation interfacing the stack, or <tt>null</tt>.
|
||||
* @return the IItemHandler implementation interfacing the stack, or <tt>null</tt>.
|
||||
*/
|
||||
IInventory inventoryFor(ItemStack stack, EntityPlayer player);
|
||||
IItemHandler itemHandlerFor(ItemStack stack, EntityPlayer player);
|
||||
|
||||
/**
|
||||
* Get a list of all registered block drivers.
|
||||
|
@ -1,6 +1,7 @@
|
||||
package li.cil.oc.server.agent
|
||||
|
||||
import li.cil.oc.api.internal
|
||||
import li.cil.oc.util.ExtendedInventory._
|
||||
import li.cil.oc.util.InventoryUtils
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
@ -9,9 +10,9 @@ import net.minecraft.item.Item
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.nbt.NBTTagList
|
||||
import li.cil.oc.util.ExtendedInventory._
|
||||
|
||||
class Inventory(val agent: internal.Agent) extends InventoryPlayer(null) {
|
||||
|
||||
def selectedItemStack = agent.mainInventory.getStackInSlot(agent.selectedSlot)
|
||||
|
||||
def inventorySlots = (agent.selectedSlot until getSizeInventory) ++ (0 until agent.selectedSlot)
|
||||
@ -53,7 +54,7 @@ class Inventory(val agent: internal.Agent) extends InventoryPlayer(null) {
|
||||
|
||||
override def addItemStackToInventory(stack: ItemStack) = {
|
||||
val slots = this.indices.drop(agent.selectedSlot) ++ this.indices.take(agent.selectedSlot)
|
||||
InventoryUtils.insertIntoInventory(stack, this, slots = Option(slots))
|
||||
InventoryUtils.insertIntoInventory(stack, InventoryUtils.asItemHandler(this), slots = Option(slots))
|
||||
}
|
||||
|
||||
override def canHeldItemHarvest(block: Block): Boolean = block.getMaterial.isToolNotRequired || (getCurrentItem != null && getCurrentItem.canHarvestBlock(block))
|
||||
|
@ -14,7 +14,8 @@ import li.cil.oc.api.network.SidedEnvironment
|
||||
import li.cil.oc.api.network.Visibility
|
||||
import li.cil.oc.api.prefab
|
||||
import li.cil.oc.api.prefab.AbstractValue
|
||||
import li.cil.oc.server.component.DebugCard.{AccessContext, CommandSender}
|
||||
import li.cil.oc.server.component.DebugCard.AccessContext
|
||||
import li.cil.oc.server.component.DebugCard.CommandSender
|
||||
import li.cil.oc.util.BlockPosition
|
||||
import li.cil.oc.util.ExtendedArguments._
|
||||
import li.cil.oc.util.ExtendedNBT._
|
||||
@ -541,11 +542,11 @@ object DebugCard {
|
||||
val tag = if (Strings.isNullOrEmpty(tagJson)) null else JsonToNBT.getTagFromJson(tagJson)
|
||||
val position = BlockPosition(args.checkDouble(4), args.checkDouble(5), args.checkDouble(6), world)
|
||||
val side = args.checkSideAny(7)
|
||||
InventoryUtils.inventoryAt(position) match {
|
||||
InventoryUtils.inventoryAt(position, side) match {
|
||||
case Some(inventory) =>
|
||||
val stack = new ItemStack(item, count, damage)
|
||||
stack.setTagCompound(tag)
|
||||
result(InventoryUtils.insertIntoInventory(stack, inventory, Option(side)))
|
||||
result(InventoryUtils.insertIntoInventory(stack, inventory))
|
||||
case _ => result(Unit, "no inventory")
|
||||
}
|
||||
}
|
||||
@ -554,11 +555,11 @@ object DebugCard {
|
||||
def removeItem(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
checkAccess()
|
||||
val position = BlockPosition(args.checkDouble(0), args.checkDouble(1), args.checkDouble(2), world)
|
||||
InventoryUtils.inventoryAt(position) match {
|
||||
InventoryUtils.anyInventoryAt(position) match {
|
||||
case Some(inventory) =>
|
||||
val slot = args.checkSlot(inventory, 3)
|
||||
val count = args.optInteger(4, inventory.getInventoryStackLimit)
|
||||
val removed = inventory.decrStackSize(slot, count)
|
||||
val count = args.optInteger(4, 64)
|
||||
val removed = inventory.extractItem(slot, count, false)
|
||||
if (removed == null) result(0)
|
||||
else result(removed.stackSize)
|
||||
case _ => result(Unit, "no inventory")
|
||||
|
@ -3,11 +3,11 @@ package li.cil.oc.server.component
|
||||
import java.util
|
||||
|
||||
import li.cil.oc.Constants
|
||||
import li.cil.oc.api.driver.DeviceInfo.DeviceAttribute
|
||||
import li.cil.oc.api.driver.DeviceInfo.DeviceClass
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.api.Network
|
||||
import li.cil.oc.api.driver.DeviceInfo
|
||||
import li.cil.oc.api.driver.DeviceInfo.DeviceAttribute
|
||||
import li.cil.oc.api.driver.DeviceInfo.DeviceClass
|
||||
import li.cil.oc.api.machine.Arguments
|
||||
import li.cil.oc.api.machine.Callback
|
||||
import li.cil.oc.api.machine.Context
|
||||
@ -22,8 +22,6 @@ import net.minecraft.util.EnumFacing
|
||||
import scala.collection.convert.WrapAsJava._
|
||||
import scala.collection.convert.WrapAsScala._
|
||||
|
||||
import scala.collection.convert.WrapAsJava._
|
||||
|
||||
class Drone(val agent: entity.Drone) extends prefab.ManagedEnvironment with Agent with DeviceInfo {
|
||||
override val node = Network.newNode(this, Visibility.Network).
|
||||
withComponent("drone").
|
||||
@ -46,7 +44,7 @@ class Drone(val agent: entity.Drone) extends prefab.ManagedEnvironment with Agen
|
||||
override protected def suckableItems(side: EnumFacing) = entitiesInBlock(classOf[EntityItem], position) ++ super.suckableItems(side)
|
||||
|
||||
override protected def onSuckCollect(entity: EntityItem) = {
|
||||
if (InventoryUtils.insertIntoInventory(entity.getEntityItem, inventory, slots = Option(insertionSlots))) {
|
||||
if (InventoryUtils.insertIntoInventory(entity.getEntityItem, InventoryUtils.asItemHandler(inventory), slots = Option(insertionSlots))) {
|
||||
world.playSoundAtEntity(agent, "random.pop", 0.2f, ((world.rand.nextFloat - world.rand.nextFloat) * 0.7f + 1) * 2)
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ class Trade(val info: TradeInfo) extends AbstractValue {
|
||||
InventoryUtils.extractFromInventory(stack, inventory, null, simulate = true).stackSize == 0
|
||||
def hasRoomForItemStack(stack: ItemStack) = {
|
||||
val remainder = stack.copy()
|
||||
InventoryUtils.insertIntoInventory(remainder, inventory, None, remainder.stackSize, simulate = true)
|
||||
InventoryUtils.insertIntoInventory(remainder, InventoryUtils.asItemHandler(inventory), remainder.stackSize, simulate = true)
|
||||
remainder.stackSize == 0
|
||||
}
|
||||
|
||||
@ -87,9 +87,9 @@ class Trade(val info: TradeInfo) extends AbstractValue {
|
||||
val outputStack = recipe.getItemToSell.copy()
|
||||
if (hasRoomForItemStack(outputStack)) {
|
||||
// We established that out inventory allows to perform the trade, now actually do the trade.
|
||||
InventoryUtils.extractFromInventory(firstInputStack, inventory, null)
|
||||
secondInputStack.map(InventoryUtils.extractFromInventory(_, inventory, null))
|
||||
InventoryUtils.insertIntoInventory(outputStack, inventory, None, outputStack.stackSize)
|
||||
InventoryUtils.extractFromInventory(firstInputStack, InventoryUtils.asItemHandler(inventory))
|
||||
secondInputStack.map(InventoryUtils.extractFromInventory(_, InventoryUtils.asItemHandler(inventory)))
|
||||
InventoryUtils.insertIntoInventory(outputStack, InventoryUtils.asItemHandler(inventory), outputStack.stackSize)
|
||||
|
||||
// Tell the merchant we used the recipe, so MC can disable it and/or enable more recipes.
|
||||
info.merchant.get.orNull.useRecipe(recipe)
|
||||
|
@ -25,8 +25,8 @@ trait InventoryTransfer extends traits.WorldAware with traits.SideRestricted {
|
||||
result(Unit, reason)
|
||||
case _ =>
|
||||
if (args.count > 3) {
|
||||
val sourceSlot = args.checkSlot(InventoryUtils.inventoryAt(sourcePos).getOrElse(throw new IllegalArgumentException("no inventory")), 3)
|
||||
val sinkSlot = args.optSlot(InventoryUtils.inventoryAt(sinkPos).getOrElse(throw new IllegalArgumentException("no inventory")), 4, -1)
|
||||
val sourceSlot = args.checkSlot(InventoryUtils.inventoryAt(sourcePos, sourceSide).getOrElse(throw new IllegalArgumentException("no inventory")), 3)
|
||||
val sinkSlot = args.optSlot(InventoryUtils.inventoryAt(sinkPos, sinkSide).getOrElse(throw new IllegalArgumentException("no inventory")), 4, -1)
|
||||
|
||||
result(InventoryUtils.transferBetweenInventoriesSlotsAt(sourcePos, sourceSide.getOpposite, sourceSlot, sinkPos, Option(sinkSide.getOpposite), if (sinkSlot < 0) None else Option(sinkSlot), count))
|
||||
}
|
||||
|
@ -39,9 +39,9 @@ trait InventoryWorldControl extends InventoryAware with WorldAware with SideRest
|
||||
val stack = inventory.getStackInSlot(selectedSlot)
|
||||
if (stack != null && stack.stackSize > 0) {
|
||||
val blockPos = position.offset(facing)
|
||||
InventoryUtils.inventoryAt(blockPos) match {
|
||||
case Some(inv) if inv.isUseableByPlayer(fakePlayer) && mayInteract(blockPos, facing.getOpposite) =>
|
||||
if (!InventoryUtils.insertIntoInventory(stack, inv, Option(facing.getOpposite), count)) {
|
||||
InventoryUtils.inventoryAt(blockPos, facing.getOpposite) match {
|
||||
case Some(inv) if mayInteract(blockPos, facing.getOpposite, inv) =>
|
||||
if (!InventoryUtils.insertIntoInventory(stack, inv, count)) {
|
||||
// Cannot drop into that inventory.
|
||||
return result(false, "inventory full")
|
||||
}
|
||||
@ -74,8 +74,8 @@ trait InventoryWorldControl extends InventoryAware with WorldAware with SideRest
|
||||
val count = args.optItemCount(1)
|
||||
|
||||
val blockPos = position.offset(facing)
|
||||
if (InventoryUtils.inventoryAt(blockPos).exists(inventory => {
|
||||
inventory.isUseableByPlayer(fakePlayer) && mayInteract(blockPos, facing.getOpposite) && InventoryUtils.extractAnyFromInventory(InventoryUtils.insertIntoInventory(_, this.inventory, slots = Option(insertionSlots)), inventory, facing.getOpposite, count)
|
||||
if (InventoryUtils.inventoryAt(blockPos, facing.getOpposite).exists(inventory => {
|
||||
mayInteract(blockPos, facing.getOpposite) && InventoryUtils.extractAnyFromInventory(InventoryUtils.insertIntoInventory(_, InventoryUtils.asItemHandler(this.inventory), slots = Option(insertionSlots)), inventory, count)
|
||||
})) {
|
||||
context.pause(Settings.get.suckDelay)
|
||||
result(true)
|
||||
|
@ -8,8 +8,8 @@ import li.cil.oc.server.component.result
|
||||
import li.cil.oc.util.BlockPosition
|
||||
import li.cil.oc.util.ExtendedArguments._
|
||||
import li.cil.oc.util.InventoryUtils
|
||||
import net.minecraft.inventory.IInventory
|
||||
import net.minecraft.util.EnumFacing
|
||||
import net.minecraftforge.items.IItemHandler
|
||||
|
||||
trait InventoryWorldControlMk2 extends InventoryAware with WorldAware with SideRestricted {
|
||||
@Callback(doc = """function(facing:number, slot:number[, count:number[, fromSide:number]]):boolean -- Drops the selected item stack into the specified slot of an inventory.""")
|
||||
@ -21,7 +21,7 @@ trait InventoryWorldControlMk2 extends InventoryAware with WorldAware with SideR
|
||||
if (stack != null && stack.stackSize > 0) {
|
||||
withInventory(position.offset(facing), fromSide, inventory => {
|
||||
val slot = args.checkSlot(inventory, 1)
|
||||
if (!InventoryUtils.insertIntoInventorySlot(stack, inventory, Option(fromSide), slot, count)) {
|
||||
if (!InventoryUtils.insertIntoInventorySlot(stack, inventory, slot, count)) {
|
||||
// Cannot drop into that inventory.
|
||||
return result(false, "inventory full/invalid slot")
|
||||
}
|
||||
@ -49,7 +49,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)
|
||||
if (InventoryUtils.extractFromInventorySlot(InventoryUtils.insertIntoInventory(_, this.inventory, slots = Option(insertionSlots)), inventory, fromSide, slot, count)) {
|
||||
if (InventoryUtils.extractFromInventorySlot(InventoryUtils.insertIntoInventory(_, InventoryUtils.asItemHandler(this.inventory), slots = Option(insertionSlots)), inventory, slot, count)) {
|
||||
context.pause(Settings.get.suckDelay)
|
||||
result(true)
|
||||
}
|
||||
@ -57,9 +57,9 @@ trait InventoryWorldControlMk2 extends InventoryAware with WorldAware with SideR
|
||||
})
|
||||
}
|
||||
|
||||
private def withInventory(blockPos: BlockPosition, fromSide: EnumFacing, f: IInventory => Array[AnyRef]) =
|
||||
InventoryUtils.inventoryAt(blockPos) match {
|
||||
case Some(inventory) if inventory.isUseableByPlayer(fakePlayer) && mayInteract(blockPos, fromSide) => f(inventory)
|
||||
private def withInventory(blockPos: BlockPosition, fromSide: EnumFacing, f: IItemHandler => Array[AnyRef]) =
|
||||
InventoryUtils.inventoryAt(blockPos, fromSide) match {
|
||||
case Some(inventory) if mayInteract(blockPos, fromSide) => f(inventory)
|
||||
case _ => result(Unit, "no inventory")
|
||||
}
|
||||
}
|
||||
|
@ -7,21 +7,21 @@ import li.cil.oc.api.machine.Context
|
||||
import li.cil.oc.util.ExtendedArguments._
|
||||
import li.cil.oc.util.InventoryUtils
|
||||
import li.cil.oc.util.ResultWrapper.result
|
||||
import net.minecraft.inventory.IInventory
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraftforge.items.IItemHandler
|
||||
|
||||
trait ItemInventoryControl extends InventoryAware {
|
||||
@Callback(doc = "function(slot:number):number -- The size of an item inventory in the specified slot.")
|
||||
def getItemInventorySize(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
withItemInventory(args.checkSlot(inventory, 0), itemInventory => result(itemInventory.getSizeInventory))
|
||||
withItemInventory(args.checkSlot(inventory, 0), itemInventory => result(itemInventory.getSlots))
|
||||
}
|
||||
|
||||
@Callback(doc = "function(inventorySlot:number, slot:number[, count:number=64]):number -- Drops an item into the specified slot in the item inventory.")
|
||||
@Callback(doc = "function(inventorySlot:number, slot:number[, count:number=64]):number -- Drops an item from the selected slot into the specified slot in the item inventory.")
|
||||
def dropIntoItemInventory(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
withItemInventory(args.checkSlot(inventory, 0), itemInventory => {
|
||||
val slot = args.checkSlot(itemInventory, 1)
|
||||
val count = args.optItemCount(2)
|
||||
result(InventoryUtils.extractAnyFromInventory(InventoryUtils.insertIntoInventorySlot(_, itemInventory, None, slot), inventory, null, count))
|
||||
result(InventoryUtils.extractFromInventorySlot(InventoryUtils.insertIntoInventorySlot(_, itemInventory, slot), inventory, null, selectedSlot, count))
|
||||
})
|
||||
}
|
||||
|
||||
@ -30,14 +30,14 @@ 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(_, inventory, slots = Option(insertionSlots)), itemInventory, null, slot, count))
|
||||
result(InventoryUtils.extractFromInventorySlot(InventoryUtils.insertIntoInventory(_, InventoryUtils.asItemHandler(inventory), slots = Option(insertionSlots)), itemInventory, slot, count))
|
||||
})
|
||||
}
|
||||
|
||||
private def withItemInventory(slot: Int, f: IInventory => Array[AnyRef]): Array[AnyRef] = {
|
||||
private def withItemInventory(slot: Int, f: IItemHandler => Array[AnyRef]): Array[AnyRef] = {
|
||||
inventory.getStackInSlot(slot) match {
|
||||
case stack: ItemStack => api.Driver.inventoryFor(stack, fakePlayer) match {
|
||||
case inventory: IInventory => f(inventory)
|
||||
case stack: ItemStack => api.Driver.itemHandlerFor(stack, fakePlayer) match {
|
||||
case inventory: IItemHandler => f(inventory)
|
||||
case _ => result(0, "no item inventory")
|
||||
}
|
||||
case _ => result(0, "no item inventory")
|
||||
|
@ -51,7 +51,7 @@ trait TankInventoryControl extends WorldAware with InventoryAware with TankAware
|
||||
else {
|
||||
into.fill(contents, true)
|
||||
inventory.decrStackSize(selectedSlot, 1)
|
||||
InventoryUtils.insertIntoInventory(container, inventory, slots = Option(insertionSlots))
|
||||
InventoryUtils.insertIntoInventory(container, InventoryUtils.asItemHandler(inventory), slots = Option(insertionSlots))
|
||||
if (container.stackSize > 0) {
|
||||
InventoryUtils.spawnStackInWorld(position, container)
|
||||
}
|
||||
@ -91,7 +91,7 @@ trait TankInventoryControl extends WorldAware with InventoryAware with TankAware
|
||||
val amount = FluidContainerRegistry.getFluidForFilledItem(filled).amount
|
||||
from.drain(amount, true)
|
||||
inventory.decrStackSize(selectedSlot, 1)
|
||||
InventoryUtils.insertIntoInventory(filled, inventory, slots = Option(insertionSlots))
|
||||
InventoryUtils.insertIntoInventory(filled, InventoryUtils.asItemHandler(inventory), slots = Option(insertionSlots))
|
||||
if (filled.stackSize > 0) {
|
||||
InventoryUtils.spawnStackInWorld(position, filled)
|
||||
}
|
||||
@ -128,6 +128,7 @@ trait TankInventoryControl extends WorldAware with InventoryAware with TankAware
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
|
||||
inventory.getStackInSlot(slot) match {
|
||||
case stack: ItemStack => fluidInfo(stack) match {
|
||||
case Some((fluid, capacity)) => f(fluid, capacity)
|
||||
|
@ -19,6 +19,7 @@ import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action
|
||||
import net.minecraftforge.event.world.BlockEvent
|
||||
import net.minecraftforge.fluids.FluidRegistry
|
||||
import net.minecraftforge.fml.common.eventhandler.Event.Result
|
||||
import net.minecraftforge.items.IItemHandler
|
||||
|
||||
trait WorldAware {
|
||||
def position: BlockPosition
|
||||
@ -44,6 +45,8 @@ trait WorldAware {
|
||||
}
|
||||
}
|
||||
|
||||
def mayInteract(blockPos: BlockPosition, side: EnumFacing, inventory: IItemHandler): Boolean = mayInteract(blockPos, side) // This uses the inventory object in 1.9+
|
||||
|
||||
def entitiesInBounds[Type <: Entity](clazz: Class[Type], bounds: AxisAlignedBB) = {
|
||||
world.getEntitiesWithinAABB(clazz, bounds)
|
||||
}
|
||||
|
@ -8,16 +8,16 @@ import li.cil.oc.server.component.result
|
||||
import li.cil.oc.util.DatabaseAccess
|
||||
import li.cil.oc.util.ExtendedArguments._
|
||||
import li.cil.oc.util.InventoryUtils
|
||||
import net.minecraft.inventory.IInventory
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.util.EnumFacing
|
||||
import net.minecraftforge.items.IItemHandler
|
||||
import net.minecraftforge.oredict.OreDictionary
|
||||
|
||||
trait WorldInventoryAnalytics extends WorldAware with SideRestricted with NetworkAware {
|
||||
@Callback(doc = """function(side:number):number -- Get the number of slots in the inventory on the specified side of the device.""")
|
||||
def getInventorySize(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val facing = checkSideForAction(args, 0)
|
||||
withInventory(facing, inventory => result(inventory.getSizeInventory))
|
||||
withInventory(facing, inventory => result(inventory.getSlots))
|
||||
}
|
||||
|
||||
@Callback(doc = """function(side:number, slot:number):number -- Get number of items in the specified slot of the inventory on the specified side of the device.""")
|
||||
@ -89,9 +89,9 @@ trait WorldInventoryAnalytics extends WorldAware with SideRestricted with Networ
|
||||
withInventory(facing, inventory => store(inventory.getStackInSlot(args.checkSlot(inventory, 1))))
|
||||
}
|
||||
|
||||
private def withInventory(side: EnumFacing, f: IInventory => Array[AnyRef]) =
|
||||
InventoryUtils.inventoryAt(position.offset(side)) match {
|
||||
case Some(inventory) if inventory.isUseableByPlayer(fakePlayer) && mayInteract(position.offset(side), side.getOpposite) => f(inventory)
|
||||
private def withInventory(side: EnumFacing, f: IItemHandler => Array[AnyRef]) =
|
||||
InventoryUtils.inventoryAt(position.offset(side), side.getOpposite) match {
|
||||
case Some(inventory) if mayInteract(position.offset(side), side.getOpposite, inventory) => f(inventory)
|
||||
case _ => result(Unit, "no inventory")
|
||||
}
|
||||
}
|
||||
|
@ -11,12 +11,15 @@ import li.cil.oc.api.driver.item.HostAware
|
||||
import li.cil.oc.api.machine.Value
|
||||
import li.cil.oc.api.network.EnvironmentHost
|
||||
import li.cil.oc.api.network.ManagedEnvironment
|
||||
import li.cil.oc.util.InventoryUtils
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.inventory.IInventory
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.util.BlockPos
|
||||
import net.minecraft.util.EnumFacing
|
||||
import net.minecraft.world.World
|
||||
import net.minecraftforge.items.CapabilityItemHandler
|
||||
import net.minecraftforge.items.IItemHandler
|
||||
|
||||
import scala.collection.convert.WrapAsJava._
|
||||
import scala.collection.convert.WrapAsScala._
|
||||
@ -143,10 +146,20 @@ private[oc] object Registry extends api.detail.DriverAPI {
|
||||
}.orNull
|
||||
}
|
||||
|
||||
override def inventoryFor(stack: ItemStack, player: EntityPlayer): IInventory = {
|
||||
@Deprecated
|
||||
override def inventoryFor(stack: ItemStack, player: EntityPlayer):IInventory = {
|
||||
OpenComputers.log.warn("A mod is using the deprecated method li.cil.oc.api.Driver.inventoryFor; use itemHandlerFor instead.")
|
||||
null
|
||||
}
|
||||
|
||||
override def itemHandlerFor(stack: ItemStack, player: EntityPlayer): IItemHandler = {
|
||||
inventoryProviders.find(provider => provider.worksWith(stack, player)).
|
||||
map(provider => provider.getInventory(stack, player)).
|
||||
orNull
|
||||
map(provider => InventoryUtils.asItemHandler(provider.getInventory(stack, player))).
|
||||
getOrElse {
|
||||
if(stack.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null))
|
||||
stack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null)
|
||||
else null
|
||||
}
|
||||
}
|
||||
|
||||
override def blockDrivers = blocks.toSeq
|
||||
|
@ -4,6 +4,7 @@ import li.cil.oc.api.internal.MultiTank
|
||||
import li.cil.oc.api.machine.Arguments
|
||||
import net.minecraft.inventory.IInventory
|
||||
import net.minecraft.util.EnumFacing
|
||||
import net.minecraftforge.items.IItemHandler
|
||||
import net.minecraftforge.fluids.FluidContainerRegistry
|
||||
|
||||
import scala.language.implicitConversions
|
||||
@ -21,19 +22,23 @@ object ExtendedArguments {
|
||||
if (!isDefined(index) || !hasValue(index)) default
|
||||
else math.max(0, args.checkInteger(index))
|
||||
|
||||
def checkSlot(inventory: IInventory, n: Int) = {
|
||||
def checkSlot(inventory: IItemHandler, n: Int): Int = {
|
||||
val slot = args.checkInteger(n) - 1
|
||||
if (slot < 0 || slot >= inventory.getSizeInventory) {
|
||||
if (slot < 0 || slot >= inventory.getSlots) {
|
||||
throw new IllegalArgumentException("invalid slot")
|
||||
}
|
||||
slot
|
||||
}
|
||||
|
||||
def optSlot(inventory: IInventory, index: Int, default: Int) = {
|
||||
def optSlot(inventory: IItemHandler, index: Int, default: Int): Int = {
|
||||
if (!isDefined(index)) default
|
||||
else checkSlot(inventory, index)
|
||||
}
|
||||
|
||||
def checkSlot(inventory: IInventory, n: Int): Int = checkSlot(InventoryUtils.asItemHandler(inventory), n)
|
||||
|
||||
def optSlot(inventory: IInventory, index: Int, default: Int): Int = optSlot(InventoryUtils.asItemHandler(inventory), index, default)
|
||||
|
||||
def checkTank(multi: MultiTank, n: Int) = {
|
||||
val tank = args.checkInteger(n) - 1
|
||||
if (tank < 0 || tank >= multi.tankCount) {
|
||||
|
@ -1,25 +1,38 @@
|
||||
package li.cil.oc.util
|
||||
|
||||
import li.cil.oc.OpenComputers
|
||||
import li.cil.oc.util.ExtendedWorld._
|
||||
import net.minecraft.block.BlockChest
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.entity.item.EntityItem
|
||||
import net.minecraft.entity.item.EntityMinecartContainer
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.inventory.IInventory
|
||||
import net.minecraft.inventory.ISidedInventory
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.tileentity.TileEntityChest
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.util.EnumFacing
|
||||
import net.minecraftforge.items.CapabilityItemHandler
|
||||
import net.minecraftforge.items.IItemHandler
|
||||
import net.minecraftforge.items.IItemHandlerModifiable
|
||||
import net.minecraftforge.items.wrapper.InvWrapper
|
||||
import net.minecraftforge.items.wrapper.SidedInvWrapper
|
||||
|
||||
import scala.collection.convert.WrapAsScala._
|
||||
|
||||
object InventoryUtils {
|
||||
|
||||
def asItemHandler(inventory: IInventory, side: EnumFacing): IItemHandlerModifiable = inventory match {
|
||||
case inv: ISidedInventory if side != null => new SidedInvWrapper(inv, side)
|
||||
case _ => new InvWrapper(inventory)
|
||||
}
|
||||
|
||||
def asItemHandler(inventory: IInventory): IItemHandlerModifiable = asItemHandler(inventory, null)
|
||||
|
||||
/**
|
||||
* Check if two item stacks are of equal type, ignoring the stack size.
|
||||
* <p/>
|
||||
* Optionally check for equality in NBT data.
|
||||
*/
|
||||
def haveSameItemType(stackA: ItemStack, stackB: ItemStack, checkNBT: Boolean = false) =
|
||||
def haveSameItemType(stackA: ItemStack, stackB: ItemStack, checkNBT: Boolean = false): Boolean =
|
||||
stackA != null && stackB != null &&
|
||||
stackA.getItem == stackB.getItem &&
|
||||
(!stackA.getHasSubtypes || stackA.getItemDamage == stackB.getItemDamage) &&
|
||||
@ -31,15 +44,28 @@ object InventoryUtils {
|
||||
* This performs special handling for (double-)chests and also checks for
|
||||
* mine carts with chests.
|
||||
*/
|
||||
def inventoryAt(position: BlockPosition): Option[IInventory] = position.world match {
|
||||
case Some(world) if world.blockExists(position) => (world.getBlock(position), world.getTileEntity(position)) match {
|
||||
case (block: BlockChest, chest: TileEntityChest) => Option(block.getLockableContainer(world, chest.getPos))
|
||||
case (_, inventory: IInventory) => Some(inventory)
|
||||
case _ => world.getEntitiesWithinAABB(classOf[EntityMinecartContainer], position.bounds).find(!_.isDead)
|
||||
def inventoryAt(position: BlockPosition, side: EnumFacing): Option[IItemHandler] = position.world match {
|
||||
case Some(world) if world.blockExists(position) => world.getTileEntity(position) match {
|
||||
case tile: TileEntity if tile.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side) => Option(tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side))
|
||||
case tile: IInventory => Option(asItemHandler(tile))
|
||||
case _ => world.getEntitiesWithinAABB(classOf[Entity], position.bounds)
|
||||
.filter(e => !e.isDead && e.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side))
|
||||
.map(_.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side))
|
||||
.find(_ != null)
|
||||
}
|
||||
case _ => None
|
||||
}
|
||||
|
||||
def anyInventoryAt(position: BlockPosition): Option[IItemHandler] = {
|
||||
for(side <- null :: EnumFacing.VALUES.toList) {
|
||||
inventoryAt(position, side) match {
|
||||
case inv: Some[IItemHandler] => return inv
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a stack into an inventory.
|
||||
* <p/>
|
||||
@ -61,40 +87,31 @@ object InventoryUtils {
|
||||
* The number of items inserted can be limited, to avoid unnecessary
|
||||
* changes to the inventory the stack may come from, for example.
|
||||
*/
|
||||
def insertIntoInventorySlot(stack: ItemStack, inventory: IInventory, side: Option[EnumFacing], slot: Int, limit: Int = 64, simulate: Boolean = false) =
|
||||
(stack != null && limit > 0) && {
|
||||
val isSideValidForSlot = (inventory, side) match {
|
||||
case (inventory: ISidedInventory, Some(s)) => inventory.canInsertItem(slot, stack, s)
|
||||
case _ => true
|
||||
}
|
||||
(stack.stackSize > 0 && inventory.isItemValidForSlot(slot, stack) && isSideValidForSlot) && {
|
||||
val maxStackSize = math.min(inventory.getInventoryStackLimit, stack.getMaxStackSize)
|
||||
val existing = inventory.getStackInSlot(slot)
|
||||
val shouldMerge = existing != null && existing.stackSize < maxStackSize &&
|
||||
existing.isItemEqual(stack) && ItemStack.areItemStackTagsEqual(existing, stack)
|
||||
if (shouldMerge) {
|
||||
val space = maxStackSize - existing.stackSize
|
||||
val amount = math.min(space, math.min(stack.stackSize, limit))
|
||||
stack.stackSize -= amount
|
||||
if (simulate) amount > 0
|
||||
else {
|
||||
existing.stackSize += amount
|
||||
inventory.markDirty()
|
||||
true
|
||||
}
|
||||
def insertIntoInventorySlot(stack: ItemStack, inventory: IItemHandler, slot: Int, limit: Int = 64, simulate: Boolean = false): Boolean =
|
||||
(stack != null && limit > 0 && stack.stackSize > 0) && {
|
||||
val amount = math.min(stack.stackSize, limit)
|
||||
if (simulate) {
|
||||
val toInsert = stack.copy()
|
||||
toInsert.stackSize = amount
|
||||
inventory.insertItem(slot, toInsert, simulate) match {
|
||||
case remaining: ItemStack => remaining.stackSize < amount
|
||||
case _ => true
|
||||
}
|
||||
else (existing == null) && {
|
||||
val amount = math.min(maxStackSize, math.min(stack.stackSize, limit))
|
||||
val inserted = stack.splitStack(amount)
|
||||
if (simulate) amount > 0
|
||||
else {
|
||||
inventory.setInventorySlotContents(slot, inserted)
|
||||
true
|
||||
}
|
||||
} else {
|
||||
val toInsert = stack.splitStack(amount)
|
||||
inventory.insertItem(slot, toInsert, simulate) match {
|
||||
case remaining: ItemStack =>
|
||||
val result = remaining.stackSize < amount
|
||||
stack.stackSize = remaining.stackSize
|
||||
result
|
||||
case _ => true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def insertIntoInventorySlot(stack: ItemStack, inventory: IInventory, side: Option[EnumFacing], slot: Int, limit: Int, simulate: Boolean): Boolean =
|
||||
insertIntoInventorySlot(stack, asItemHandler(inventory, side.orNull), slot, limit, simulate)
|
||||
|
||||
/**
|
||||
* Extracts a stack from an inventory.
|
||||
* <p/>
|
||||
@ -120,32 +137,31 @@ 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: IInventory, side: EnumFacing, slot: Int, limit: Int = 64) = {
|
||||
def extractFromInventorySlot(consumer: (ItemStack) => Unit, inventory: IItemHandler, slot: Int, limit: Int = 64): Boolean = {
|
||||
val stack = inventory.getStackInSlot(slot)
|
||||
(stack != null && limit > 0) && {
|
||||
val isSideValidForSlot = inventory match {
|
||||
case inventory: ISidedInventory => inventory.canExtractItem(slot, stack, side)
|
||||
case _ => true
|
||||
}
|
||||
(stack.stackSize > 0 && isSideValidForSlot) && {
|
||||
val maxStackSize = math.min(inventory.getInventoryStackLimit, stack.getMaxStackSize)
|
||||
val amount = math.min(maxStackSize, math.min(stack.stackSize, limit))
|
||||
val extracted = stack.splitStack(amount)
|
||||
consumer(extracted)
|
||||
val success = extracted.stackSize < amount
|
||||
stack.stackSize += extracted.stackSize
|
||||
if (stack.stackSize == 0) {
|
||||
inventory.setInventorySlotContents(slot, null)
|
||||
}
|
||||
else if (success) {
|
||||
inventory.markDirty()
|
||||
}
|
||||
success
|
||||
(stack != null && limit > 0 && stack.stackSize > 0) && {
|
||||
var amount = math.min(stack.getMaxStackSize, math.min(stack.stackSize, limit))
|
||||
inventory.extractItem(slot, amount, true) match {
|
||||
case extracted: ItemStack =>
|
||||
amount = extracted.stackSize
|
||||
consumer(extracted)
|
||||
if(extracted.stackSize >= amount) return false
|
||||
inventory.extractItem(slot, amount - extracted.stackSize, false) match {
|
||||
case realExtracted: ItemStack if realExtracted.stackSize == amount - extracted.stackSize => true
|
||||
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)
|
||||
true
|
||||
}
|
||||
case _ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
def extractFromInventorySlot(consumer: (ItemStack) => Unit, inventory: IInventory, side: EnumFacing, slot: Int, limit: Int): Boolean = {
|
||||
extractFromInventorySlot(consumer, asItemHandler(inventory, side), slot, limit)
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a stack into an inventory.
|
||||
* <p/>
|
||||
* This will try to fit the stack in any and as many as necessary slots in
|
||||
@ -160,14 +176,11 @@ object InventoryUtils {
|
||||
* item stack will be adjusted to reflect the number items inserted, by
|
||||
* having its size decremented accordingly.
|
||||
*/
|
||||
def insertIntoInventory(stack: ItemStack, inventory: IInventory, side: Option[EnumFacing] = None, limit: Int = 64, simulate: Boolean = false, slots: Option[Iterable[Int]] = None) =
|
||||
(stack != null && limit > 0) && {
|
||||
def insertIntoInventory(stack: ItemStack, inventory: IItemHandler, limit: Int = 64, simulate: Boolean = false, slots: Option[Iterable[Int]] = None): Boolean =
|
||||
(stack != null && limit > 0 && stack.stackSize > 0) && {
|
||||
var success = false
|
||||
var remaining = limit
|
||||
val range = slots.getOrElse(inventory match {
|
||||
case sided: ISidedInventory => sided.getSlotsForFace(side.orNull).toIterable
|
||||
case _ => 0 until inventory.getSizeInventory
|
||||
})
|
||||
val range = slots.getOrElse(0 until inventory.getSlots)
|
||||
|
||||
if (range.nonEmpty) {
|
||||
// This is a special case for inserting with an explicit ordering,
|
||||
@ -176,26 +189,15 @@ object InventoryUtils {
|
||||
// slot, if at all possible, over merging.
|
||||
if (slots.isDefined) {
|
||||
val stackSize = stack.stackSize
|
||||
if ((inventory.getStackInSlot(range.head) == null) && insertIntoInventorySlot(stack, inventory, side, range.head, remaining, simulate)) {
|
||||
if (insertIntoInventorySlot(stack, inventory, range.head, remaining, simulate)) {
|
||||
remaining -= stackSize - stack.stackSize
|
||||
success = true
|
||||
}
|
||||
}
|
||||
|
||||
val shouldTryMerge = !stack.isItemStackDamageable && stack.getMaxStackSize > 1 && inventory.getInventoryStackLimit > 1
|
||||
if (shouldTryMerge) {
|
||||
for (slot <- range) {
|
||||
val stackSize = stack.stackSize
|
||||
if ((inventory.getStackInSlot(slot) != null) && insertIntoInventorySlot(stack, inventory, side, slot, remaining, simulate)) {
|
||||
remaining -= stackSize - stack.stackSize
|
||||
success = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (slot <- range) {
|
||||
val stackSize = stack.stackSize
|
||||
if ((inventory.getStackInSlot(slot) == null) && insertIntoInventorySlot(stack, inventory, side, slot, remaining, simulate)) {
|
||||
if (insertIntoInventorySlot(stack, inventory, slot, remaining, simulate)) {
|
||||
remaining -= stackSize - stack.stackSize
|
||||
success = true
|
||||
}
|
||||
@ -205,6 +207,9 @@ object InventoryUtils {
|
||||
success
|
||||
}
|
||||
|
||||
def insertIntoInventory(stack: ItemStack, inventory: IInventory, side: Option[EnumFacing], limit: Int, simulate: Boolean, slots: Option[Iterable[Int]]): Boolean =
|
||||
insertIntoInventory(stack, asItemHandler(inventory, side.orNull), limit, simulate, slots)
|
||||
|
||||
/**
|
||||
* Extracts a slot from an inventory.
|
||||
* <p/>
|
||||
@ -216,13 +221,11 @@ object InventoryUtils {
|
||||
* <p/>
|
||||
* This returns <tt>true</tt> if at least one item was extracted.
|
||||
*/
|
||||
def extractAnyFromInventory(consumer: (ItemStack) => Unit, inventory: IInventory, side: EnumFacing, limit: Int = 64) = {
|
||||
val range = inventory match {
|
||||
case sided: ISidedInventory => sided.getSlotsForFace(side).toIterable
|
||||
case _ => 0 until inventory.getSizeInventory
|
||||
}
|
||||
range.exists(slot => extractFromInventorySlot(consumer, inventory, side, slot, limit))
|
||||
}
|
||||
def extractAnyFromInventory(consumer: (ItemStack) => Unit, inventory: IItemHandler, limit: Int = 64): Boolean =
|
||||
(0 until inventory.getSlots).exists(slot => extractFromInventorySlot(consumer, inventory, slot, limit))
|
||||
|
||||
def extractAnyFromInventory(consumer: (ItemStack) => Unit, inventory: IInventory, side: EnumFacing, limit: Int): Boolean =
|
||||
extractAnyFromInventory(consumer, asItemHandler(inventory, side), limit)
|
||||
|
||||
/**
|
||||
* Extracts an item stack from an inventory.
|
||||
@ -233,13 +236,9 @@ object InventoryUtils {
|
||||
* This uses the <tt>extractFromInventorySlot</tt> method, and therefore
|
||||
* handles special cases such as sided inventories and stack size limits.
|
||||
*/
|
||||
def extractFromInventory(stack: ItemStack, inventory: IInventory, side: EnumFacing, simulate: Boolean = false) = {
|
||||
val range = inventory match {
|
||||
case sided: ISidedInventory => sided.getSlotsForFace(side).toIterable
|
||||
case _ => 0 until inventory.getSizeInventory
|
||||
}
|
||||
def extractFromInventory(stack: ItemStack, inventory: IItemHandler, simulate: Boolean = false): ItemStack = {
|
||||
val remaining = stack.copy()
|
||||
for (slot <- range if remaining.stackSize > 0) {
|
||||
for (slot <- 0 until inventory.getSlots if remaining.stackSize > 0) {
|
||||
extractFromInventorySlot(stack => {
|
||||
if (haveSameItemType(remaining, stack, checkNBT = true)) {
|
||||
val transferred = stack.stackSize min remaining.stackSize
|
||||
@ -248,24 +247,27 @@ object InventoryUtils {
|
||||
stack.stackSize -= transferred
|
||||
}
|
||||
}
|
||||
}, inventory, side, slot, remaining.stackSize)
|
||||
}, inventory, slot, limit = remaining.stackSize)
|
||||
}
|
||||
remaining
|
||||
}
|
||||
|
||||
/**
|
||||
def extractFromInventory(stack: ItemStack, inventory: IInventory, side: EnumFacing, simulate: Boolean): ItemStack =
|
||||
extractFromInventory(stack, asItemHandler(inventory, side), simulate)
|
||||
|
||||
/**
|
||||
* Utility method for calling <tt>insertIntoInventory</tt> on an inventory
|
||||
* in the world.
|
||||
*/
|
||||
def insertIntoInventoryAt(stack: ItemStack, position: BlockPosition, side: Option[EnumFacing] = None, limit: Int = 64, simulate: Boolean = false): Boolean =
|
||||
inventoryAt(position).exists(insertIntoInventory(stack, _, side, limit, simulate))
|
||||
inventoryAt(position, side.orNull).exists(insertIntoInventory(stack, _, limit, simulate))
|
||||
|
||||
/**
|
||||
* Utility method for calling <tt>extractFromInventory</tt> on an inventory
|
||||
* in the world.
|
||||
*/
|
||||
def extractFromInventoryAt(consumer: (ItemStack) => Unit, position: BlockPosition, side: EnumFacing, limit: Int = 64) =
|
||||
inventoryAt(position).exists(extractAnyFromInventory(consumer, _, side, limit))
|
||||
def extractFromInventoryAt(consumer: (ItemStack) => Unit, position: BlockPosition, side: EnumFacing, limit: Int = 64): Boolean =
|
||||
inventoryAt(position, side).exists(extractAnyFromInventory(consumer, _, limit))
|
||||
|
||||
/**
|
||||
* Transfers some items between two inventories.
|
||||
@ -280,46 +282,52 @@ object InventoryUtils {
|
||||
* <p/>
|
||||
* This returns <tt>true</tt> if at least one item was transferred.
|
||||
*/
|
||||
def transferBetweenInventories(source: IInventory, sourceSide: EnumFacing, sink: IInventory, sinkSide: Option[EnumFacing], limit: Int = 64) =
|
||||
def transferBetweenInventories(source: IItemHandler, sink: IItemHandler, limit: Int = 64): Boolean =
|
||||
extractAnyFromInventory(
|
||||
insertIntoInventory(_, sink, sinkSide, limit), source, sourceSide, limit)
|
||||
insertIntoInventory(_, sink, limit), source, limit = limit)
|
||||
|
||||
def transferBetweenInventories(source: IInventory, sourceSide: EnumFacing, sink: IInventory, sinkSide: Option[EnumFacing], limit: Int): Boolean =
|
||||
transferBetweenInventories(asItemHandler(source, sourceSide), asItemHandler(sink, sinkSide.orNull), limit)
|
||||
|
||||
/**
|
||||
* Like <tt>transferBetweenInventories</tt> but moving between specific slots.
|
||||
*/
|
||||
def transferBetweenInventoriesSlots(source: IInventory, sourceSide: EnumFacing, sourceSlot: Int, sink: IInventory, sinkSide: Option[EnumFacing], sinkSlot: Option[Int], limit: Int = 64) =
|
||||
def transferBetweenInventoriesSlots(source: IItemHandler, sourceSlot: Int, sink: IItemHandler, sinkSlot: Option[Int], limit: Int = 64): Boolean =
|
||||
sinkSlot match {
|
||||
case Some(explicitSinkSlot) =>
|
||||
extractFromInventorySlot(
|
||||
insertIntoInventorySlot(_, sink, sinkSide, explicitSinkSlot, limit), source, sourceSide, sourceSlot, limit)
|
||||
insertIntoInventorySlot(_, sink, explicitSinkSlot, limit), source, sourceSlot, limit = limit)
|
||||
case _ =>
|
||||
extractFromInventorySlot(
|
||||
insertIntoInventory(_, sink, sinkSide, limit), source, sourceSide, sourceSlot, 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): Boolean =
|
||||
transferBetweenInventoriesSlots(asItemHandler(source, sourceSide), sourceSlot, asItemHandler(sink, sinkSide.orNull), sinkSlot, limit)
|
||||
|
||||
/**
|
||||
* Utility method for calling <tt>transferBetweenInventories</tt> on inventories
|
||||
* in the world.
|
||||
*/
|
||||
def transferBetweenInventoriesAt(source: BlockPosition, sourceSide: EnumFacing, sink: BlockPosition, sinkSide: Option[EnumFacing], limit: Int = 64) =
|
||||
inventoryAt(source).exists(sourceInventory =>
|
||||
inventoryAt(sink).exists(sinkInventory =>
|
||||
transferBetweenInventories(sourceInventory, sourceSide, sinkInventory, sinkSide, limit)))
|
||||
def transferBetweenInventoriesAt(source: BlockPosition, sourceSide: EnumFacing, sink: BlockPosition, sinkSide: Option[EnumFacing], limit: Int = 64): Boolean =
|
||||
inventoryAt(source, sourceSide).exists(sourceInventory =>
|
||||
inventoryAt(sink, sinkSide.orNull).exists(sinkInventory =>
|
||||
transferBetweenInventories(sourceInventory, sinkInventory, limit)))
|
||||
|
||||
/**
|
||||
* Utility method for calling <tt>transferBetweenInventoriesSlots</tt> on inventories
|
||||
* in the world.
|
||||
*/
|
||||
def transferBetweenInventoriesSlotsAt(sourcePos: BlockPosition, sourceSide: EnumFacing, sourceSlot: Int, sinkPos: BlockPosition, sinkSide: Option[EnumFacing], sinkSlot: Option[Int], limit: Int = 64) =
|
||||
inventoryAt(sourcePos).exists(sourceInventory =>
|
||||
inventoryAt(sinkPos).exists(sinkInventory =>
|
||||
transferBetweenInventoriesSlots(sourceInventory, sourceSide, sourceSlot, sinkInventory, sinkSide, sinkSlot, limit)))
|
||||
def transferBetweenInventoriesSlotsAt(sourcePos: BlockPosition, sourceSide: EnumFacing, sourceSlot: Int, sinkPos: BlockPosition, sinkSide: Option[EnumFacing], sinkSlot: Option[Int], limit: Int = 64): Boolean =
|
||||
inventoryAt(sourcePos, sourceSide).exists(sourceInventory =>
|
||||
inventoryAt(sinkPos, sinkSide.orNull).exists(sinkInventory =>
|
||||
transferBetweenInventoriesSlots(sourceInventory, sourceSlot, sinkInventory, sinkSlot, limit)))
|
||||
|
||||
/**
|
||||
* Utility method for dropping contents from a single inventory slot into
|
||||
* the world.
|
||||
*/
|
||||
def dropSlot(position: BlockPosition, inventory: IInventory, slot: Int, count: Int, direction: Option[EnumFacing] = None) = {
|
||||
def dropSlot(position: BlockPosition, inventory: IInventory, slot: Int, count: Int, direction: Option[EnumFacing] = None): Boolean = {
|
||||
Option(inventory.decrStackSize(slot, count)) match {
|
||||
case Some(stack) if stack.stackSize > 0 => spawnStackInWorld(position, stack, direction); true
|
||||
case _ => false
|
||||
|
Loading…
x
Reference in New Issue
Block a user