diff --git a/src/main/scala/li/cil/oc/server/component/traits/InventoryAnalytics.scala b/src/main/scala/li/cil/oc/server/component/traits/InventoryAnalytics.scala index ff10d399fb..bc8696af44 100644 --- a/src/main/scala/li/cil/oc/server/component/traits/InventoryAnalytics.scala +++ b/src/main/scala/li/cil/oc/server/component/traits/InventoryAnalytics.scala @@ -7,6 +7,7 @@ import li.cil.oc.api.machine.Context 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.minecraftforge.oredict.OreDictionary trait InventoryAnalytics extends InventoryAware with NetworkAware { @@ -40,7 +41,7 @@ trait InventoryAnalytics extends InventoryAware with NetworkAware { }) } - @Callback(doc = """function(slot:number, dbAddress:string, dbSlot:number):boolean -- Compare an item in the specified slot with one in the database with the specified address.""") + @Callback(doc = """function(slot:number, dbAddress:string, dbSlot:number[, checkNBT:boolean=false]):boolean -- Compare an item in the specified slot with one in the database with the specified address.""") def compareToDatabase(context: Context, args: Arguments): Array[AnyRef] = { val localSlot = args.checkSlot(inventory, 0) val dbAddress = args.checkString(1) @@ -48,7 +49,7 @@ trait InventoryAnalytics extends InventoryAware with NetworkAware { DatabaseAccess.withDatabase(node, dbAddress, database => { val dbSlot = args.checkSlot(database.data, 2) val dbStack = database.getStackInSlot(dbSlot) - result(haveSameItemType(localStack, dbStack)) + result(InventoryUtils.haveSameItemType(localStack, dbStack, args.optBoolean(3, false))) }) } } diff --git a/src/main/scala/li/cil/oc/server/component/traits/InventoryAware.scala b/src/main/scala/li/cil/oc/server/component/traits/InventoryAware.scala index 5bc635ea2e..816ab6f355 100644 --- a/src/main/scala/li/cil/oc/server/component/traits/InventoryAware.scala +++ b/src/main/scala/li/cil/oc/server/component/traits/InventoryAware.scala @@ -3,7 +3,6 @@ package li.cil.oc.server.component.traits import li.cil.oc.api.machine.Arguments import li.cil.oc.util.ExtendedArguments._ import net.minecraft.inventory.IInventory -import net.minecraft.item.ItemStack trait InventoryAware { def inventory: IInventory @@ -21,9 +20,4 @@ trait InventoryAware { else selectedSlot protected def stackInSlot(slot: Int) = Option(inventory.getStackInSlot(slot)) - - protected def haveSameItemType(stackA: ItemStack, stackB: ItemStack) = - stackA != null && stackB != null && - stackA.getItem == stackB.getItem && - (!stackA.getHasSubtypes || stackA.getItemDamage == stackB.getItemDamage) } diff --git a/src/main/scala/li/cil/oc/server/component/traits/InventoryControl.scala b/src/main/scala/li/cil/oc/server/component/traits/InventoryControl.scala index b4001edec4..25591dcb21 100644 --- a/src/main/scala/li/cil/oc/server/component/traits/InventoryControl.scala +++ b/src/main/scala/li/cil/oc/server/component/traits/InventoryControl.scala @@ -4,6 +4,7 @@ import li.cil.oc.api.machine.Arguments import li.cil.oc.api.machine.Callback 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 trait InventoryControl extends InventoryAware { @@ -37,11 +38,11 @@ trait InventoryControl extends InventoryAware { }) } - @Callback(doc = "function(otherSlot:number):boolean -- Compare the contents of the selected slot to the contents of the specified slot.") + @Callback(doc = "function(otherSlot:number[, checkNBT:boolean=false]):boolean -- Compare the contents of the selected slot to the contents of the specified slot.") def compareTo(context: Context, args: Arguments): Array[AnyRef] = { val slot = args.checkSlot(inventory, 0) result((stackInSlot(selectedSlot), stackInSlot(slot)) match { - case (Some(stackA), Some(stackB)) => haveSameItemType(stackA, stackB) + case (Some(stackA), Some(stackB)) => InventoryUtils.haveSameItemType(stackA, stackB, args.optBoolean(1, false)) case (None, None) => true case _ => false }) @@ -56,7 +57,7 @@ trait InventoryControl extends InventoryAware { } else result((stackInSlot(selectedSlot), stackInSlot(slot)) match { case (Some(from), Some(to)) => - if (haveSameItemType(from, to)) { + if (InventoryUtils.haveSameItemType(from, to, checkNBT = true)) { val space = math.min(inventory.getInventoryStackLimit, to.getMaxStackSize) - to.stackSize val amount = math.min(count, math.min(space, from.stackSize)) if (amount > 0) { diff --git a/src/main/scala/li/cil/oc/server/component/traits/WorldInventoryAnalytics.scala b/src/main/scala/li/cil/oc/server/component/traits/WorldInventoryAnalytics.scala index 5eb50d0a35..cc5d39706c 100644 --- a/src/main/scala/li/cil/oc/server/component/traits/WorldInventoryAnalytics.scala +++ b/src/main/scala/li/cil/oc/server/component/traits/WorldInventoryAnalytics.scala @@ -32,16 +32,28 @@ trait WorldInventoryAnalytics extends WorldAware with SideRestricted with Networ withInventory(facing, inventory => result(Option(inventory.getStackInSlot(args.checkSlot(inventory, 1))).fold(0)(_.getMaxStackSize))) } - @Callback(doc = """function(side:number, slotA:number, slotB:number):boolean -- Get whether the items in the two specified slots of the inventory on the specified side of the device are of the same type.""") + @Callback(doc = """function(side:number, slotA:number, slotB:number[, checkNBT:boolean=false]):boolean -- Get whether the items in the two specified slots of the inventory on the specified side of the device are of the same type.""") def compareStacks(context: Context, args: Arguments): Array[AnyRef] = { val facing = checkSideForAction(args, 0) withInventory(facing, inventory => { val stackA = inventory.getStackInSlot(args.checkSlot(inventory, 1)) val stackB = inventory.getStackInSlot(args.checkSlot(inventory, 2)) - result(stackA == stackB || - (stackA != null && stackB != null && - stackA.getItem == stackB.getItem && - (!stackA.getHasSubtypes || stackA.getItemDamage == stackB.getItemDamage))) + result(stackA == stackB || InventoryUtils.haveSameItemType(stackA, stackB, args.optBoolean(3, false))) + }) + } + + @Callback(doc = """function(side:number, slot:number, dbAddress:string, dbSlot:number[, checkNBT:boolean=false]):boolean -- Compare an item in the specified slot in the inventory on the specified side with one in the database with the specified address.""") + def compareStackToDatabase(context: Context, args: Arguments): Array[AnyRef] = { + val facing = checkSideForAction(args, 0) + withInventory(facing, inventory => { + val slot = args.checkSlot(inventory, 1) + val dbAddress = args.checkString(2) + val stack = inventory.getStackInSlot(slot) + DatabaseAccess.withDatabase(node, dbAddress, database => { + val dbSlot = args.checkSlot(database.data, 3) + val dbStack = database.getStackInSlot(dbSlot) + result(InventoryUtils.haveSameItemType(stack, dbStack, args.optBoolean(4, false))) + }) }) } diff --git a/src/main/scala/li/cil/oc/util/InventoryUtils.scala b/src/main/scala/li/cil/oc/util/InventoryUtils.scala index e1e2c78fc3..3a570e1316 100644 --- a/src/main/scala/li/cil/oc/util/InventoryUtils.scala +++ b/src/main/scala/li/cil/oc/util/InventoryUtils.scala @@ -14,6 +14,17 @@ import net.minecraftforge.common.util.ForgeDirection import scala.collection.convert.WrapAsScala._ object InventoryUtils { + /** + * Check if two item stacks are of equal type, ignoring the stack size. + *
+ * Optionally check for equality in NBT data. + */ + def haveSameItemType(stackA: ItemStack, stackB: ItemStack, checkNBT: Boolean = false) = + stackA != null && stackB != null && + stackA.getItem == stackB.getItem && + (!stackA.getHasSubtypes || stackA.getItemDamage == stackB.getItemDamage) && + (!checkNBT || ItemStack.areItemStackTagsEqual(stackA, stackB)) + /** * Retrieves an actual inventory implementation for a specified world coordinate. * @@ -340,5 +351,4 @@ object InventoryUtils { entity case _ => null } - }