From efe89e0d1faa57fe4b17c61a7071834a4781217f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sun, 17 Nov 2013 23:26:26 +0100 Subject: [PATCH] more inventory interaction for robots --- li/cil/oc/common/tileentity/Inventory.scala | 3 +- li/cil/oc/common/tileentity/Robot.scala | 154 ++++++++++++++------ li/cil/oc/server/network/Component.scala | 7 +- 3 files changed, 115 insertions(+), 49 deletions(-) diff --git a/li/cil/oc/common/tileentity/Inventory.scala b/li/cil/oc/common/tileentity/Inventory.scala index 44ea450b4..c5ca84dad 100644 --- a/li/cil/oc/common/tileentity/Inventory.scala +++ b/li/cil/oc/common/tileentity/Inventory.scala @@ -9,7 +9,6 @@ import net.minecraft.inventory.IInventory import net.minecraft.item.ItemStack import net.minecraft.nbt.NBTTagCompound import net.minecraftforge.common.ForgeDirection -import cpw.mods.fml.relauncher.{Side, SideOnly} trait Inventory extends TileEntity with IInventory with Persistable { protected val items = Array.fill[Option[ItemStack]](getSizeInventory)(None) @@ -19,7 +18,7 @@ trait Inventory extends TileEntity with IInventory with Persistable { def getStackInSlot(i: Int) = items(i).orNull def decrStackSize(slot: Int, amount: Int) = items(slot) match { - case Some(stack) if stack.stackSize <= amount => + case Some(stack) if stack.stackSize - amount <= 0 => setInventorySlotContents(slot, null) stack case Some(stack) => diff --git a/li/cil/oc/common/tileentity/Robot.scala b/li/cil/oc/common/tileentity/Robot.scala index e9906ebf4..e392a5936 100644 --- a/li/cil/oc/common/tileentity/Robot.scala +++ b/li/cil/oc/common/tileentity/Robot.scala @@ -39,36 +39,99 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power override def isRobot(context: Context, args: Arguments): Array[AnyRef] = Array(java.lang.Boolean.TRUE) - @LuaCallback(value = "select", direct = true) + // ----------------------------------------------------------------------- // + + @LuaCallback("select") def select(context: Context, args: Arguments): Array[AnyRef] = { // Get or set selected inventory slot. - if (args.count > 0) { - val slot = args.checkInteger(0) - if (slot < 0 || slot > 15) { - throw new IllegalArgumentException("invalid slot") - } + if (args.count > 0 && args.checkAny(0) != null) { + val slot = checkSlot(args, 0) if (slot != selectedSlot) { selectedSlot = slot - selectedSlotChanged = true + // TODO Update display on client side. + // TODO ServerPacketSender.sendRobotSelectedSlotChange(this) } } result(selectedSlot) } - // ----------------------------------------------------------------------- // + @LuaCallback("count") + def count(context: Context, args: Arguments): Array[AnyRef] = + result(stackInSlot(selectedSlot) match { + case Some(stack) => stack.stackSize + case _ => 0 + }) - @LuaCallback("attack") - def attack(context: Context, args: Arguments): Array[AnyRef] = { - // Attack with equipped tool. + @LuaCallback("space") + def space(context: Context, args: Arguments): Array[AnyRef] = + result(stackInSlot(selectedSlot) match { + case Some(stack) => getInventoryStackLimit - stack.stackSize + case _ => getInventoryStackLimit + }) + + @LuaCallback("compareTo") + def compareTo(context: Context, args: Arguments): Array[AnyRef] = { + val slot = checkSlot(args, 0) + result((stackInSlot(selectedSlot), stackInSlot(slot)) match { + case (Some(stackA), Some(stackB)) => haveSameItemType(stackA, stackB) + case (None, None) => true + case _ => false + }) + } + + @LuaCallback("transferTo") + def transferTo(context: Context, args: Arguments): Array[AnyRef] = { + val slot = checkSlot(args, 0) + val count = checkOptionalItemCount(args, 1) + if (slot == selectedSlot || count == 0) { + result(true) + } + else result((stackInSlot(selectedSlot), stackInSlot(slot)) match { + case (Some(from), Some(to)) => + if (haveSameItemType(from, to)) { + val space = (getInventoryStackLimit min to.getMaxStackSize) - to.stackSize + val amount = count min space min from.stackSize + if (amount > 0) { + from.stackSize -= amount + to.stackSize += amount + assert(from.stackSize >= 0) + if (from.stackSize == 0) { + setInventorySlotContents(actualSlot(selectedSlot), null) + } + true + } + else false + } + else { + setInventorySlotContents(actualSlot(slot), from) + setInventorySlotContents(actualSlot(selectedSlot), to) + true + } + case (Some(from), None) => + setInventorySlotContents(actualSlot(slot), decrStackSize(actualSlot(selectedSlot), count)) + true + case _ => false + }) + } + + @LuaCallback("drop") + def drop(context: Context, args: Arguments): Array[AnyRef] = { + val side = checkSideForAction(args, 0) + val count = checkOptionalItemCount(args, 1) + result(dropSlot(actualSlot(selectedSlot), count, side)) + } + + @LuaCallback("place") + def place(context: Context, args: Arguments): Array[AnyRef] = { + // Place block item selected in inventory. val side = checkSideForAction(args, 0) null } - @LuaCallback("use") - def use(context: Context, args: Arguments): Array[AnyRef] = { - // Use equipped tool (e.g. dig, chop, till). + @LuaCallback("suck") + def suck(context: Context, args: Arguments): Array[AnyRef] = { + // Pick up items lying around. val side = checkSideForAction(args, 0) - val sneaky = args.checkBoolean(1) null } @@ -77,7 +140,7 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power @LuaCallback("compare") def compare(context: Context, args: Arguments): Array[AnyRef] = { val side = checkSideForAction(args, 0) - items(actuallySelectedSlot) match { + stackInSlot(selectedSlot) match { case Some(stack) => Option(stack.getItem) match { case Some(item: ItemBlock) => val (bx, by, bz) = (x + side.offsetX, y + side.offsetY, z + side.offsetZ) @@ -116,26 +179,18 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power // ----------------------------------------------------------------------- // - @LuaCallback("drop") - def drop(context: Context, args: Arguments): Array[AnyRef] = { - val count = if (args.count > 0) { - args.checkInteger(0) max 0 min getInventoryStackLimit - } - else getInventoryStackLimit - result(dropSlot(actuallySelectedSlot, count, facing)) - } - - @LuaCallback("place") - def place(context: Context, args: Arguments): Array[AnyRef] = { - // Place block item selected in inventory. + @LuaCallback("attack") + def attack(context: Context, args: Arguments): Array[AnyRef] = { + // Attack with equipped tool. val side = checkSideForAction(args, 0) null } - @LuaCallback("suck") - def collect(context: Context, args: Arguments): Array[AnyRef] = { - // Pick up items lying around. + @LuaCallback("use") + def use(context: Context, args: Arguments): Array[AnyRef] = { + // Use equipped tool (e.g. dig, chop, till). val side = checkSideForAction(args, 0) + val sneaky = args.checkBoolean(1) null } @@ -152,12 +207,8 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power def turn(context: Context, args: Arguments): Array[AnyRef] = { // Turn in the specified direction. val clockwise = args.checkBoolean(0) - if (clockwise) { - rotate(ForgeDirection.UP) - } - else { - rotate(ForgeDirection.DOWN) - } + if (clockwise) rotate(ForgeDirection.UP) + else rotate(ForgeDirection.DOWN) result(true) } @@ -184,6 +235,26 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power else None } + private def haveSameItemType(stackA: ItemStack, stackB: ItemStack) = + stackA.itemID == stackB.itemID && + (!stackA.getHasSubtypes || stackA.getItemDamage == stackB.getItemDamage) + + private def stackInSlot(slot: Int) = items(actualSlot(slot)) + + private def checkOptionalItemCount(args: Arguments, n: Int) = + if (args.count > n && args.checkAny(n) != null) { + args.checkInteger(n) max 0 min getInventoryStackLimit + } + else getInventoryStackLimit + + private def checkSlot(args: Arguments, n: Int) = { + val slot = args.checkInteger(n) - 1 + if (slot < 0 || slot > 15) { + throw new IllegalArgumentException("invalid slot") + } + slot + } + private def checkSideForAction(args: Arguments, n: Int) = checkSide(args, n, ForgeDirection.SOUTH, ForgeDirection.UP, ForgeDirection.DOWN) private def checkSideForMovement(args: Arguments, n: Int) = checkSide(args, n, ForgeDirection.SOUTH, ForgeDirection.NORTH) @@ -211,9 +282,7 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power var selectedSlot = 0 - var selectedSlotChanged = false - - def actuallySelectedSlot = selectedSlot + 3 + def actualSlot(n: Int) = n + 3 // ----------------------------------------------------------------------- // @@ -249,11 +318,6 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power distributor.changeBuffer(10) // just for testing distributor.update() gpu.update() - - if (selectedSlotChanged) { - selectedSlotChanged = false - // TODO ServerPacketSender.sendRobotSelectedSlotChange(this) - } } } diff --git a/li/cil/oc/server/network/Component.scala b/li/cil/oc/server/network/Component.scala index 6e96e3ded..5102e77fa 100644 --- a/li/cil/oc/server/network/Component.scala +++ b/li/cil/oc/server/network/Component.scala @@ -158,7 +158,10 @@ object Component { def checkAny(index: Int) = { checkIndex(index, "value") - args(index) + args(index) match { + case Unit | None => null + case arg => arg + } } def checkBoolean(index: Int) = { @@ -246,7 +249,7 @@ object Component { format(index + 1, want, typeName(have))) private def typeName(value: AnyRef): String = value match { - case null => "nil" + case null | Unit | None => "nil" case _: java.lang.Boolean => "boolean" case _: java.lang.Double => "double" case _: java.lang.String => "string"