more inventory interaction for robots

This commit is contained in:
Florian Nücke 2013-11-17 23:26:26 +01:00
parent 5f6a9cf65b
commit efe89e0d1f
3 changed files with 115 additions and 49 deletions

View File

@ -9,7 +9,6 @@ import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.ForgeDirection import net.minecraftforge.common.ForgeDirection
import cpw.mods.fml.relauncher.{Side, SideOnly}
trait Inventory extends TileEntity with IInventory with Persistable { trait Inventory extends TileEntity with IInventory with Persistable {
protected val items = Array.fill[Option[ItemStack]](getSizeInventory)(None) 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 getStackInSlot(i: Int) = items(i).orNull
def decrStackSize(slot: Int, amount: Int) = items(slot) match { 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) setInventorySlotContents(slot, null)
stack stack
case Some(stack) => case Some(stack) =>

View File

@ -39,36 +39,99 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power
override def isRobot(context: Context, args: Arguments): Array[AnyRef] = override def isRobot(context: Context, args: Arguments): Array[AnyRef] =
Array(java.lang.Boolean.TRUE) Array(java.lang.Boolean.TRUE)
@LuaCallback(value = "select", direct = true) // ----------------------------------------------------------------------- //
@LuaCallback("select")
def select(context: Context, args: Arguments): Array[AnyRef] = { def select(context: Context, args: Arguments): Array[AnyRef] = {
// Get or set selected inventory slot. // Get or set selected inventory slot.
if (args.count > 0) { if (args.count > 0 && args.checkAny(0) != null) {
val slot = args.checkInteger(0) val slot = checkSlot(args, 0)
if (slot < 0 || slot > 15) {
throw new IllegalArgumentException("invalid slot")
}
if (slot != selectedSlot) { if (slot != selectedSlot) {
selectedSlot = slot selectedSlot = slot
selectedSlotChanged = true // TODO Update display on client side.
// TODO ServerPacketSender.sendRobotSelectedSlotChange(this)
} }
} }
result(selectedSlot) 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") @LuaCallback("space")
def attack(context: Context, args: Arguments): Array[AnyRef] = { def space(context: Context, args: Arguments): Array[AnyRef] =
// Attack with equipped tool. 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) val side = checkSideForAction(args, 0)
null null
} }
@LuaCallback("use") @LuaCallback("suck")
def use(context: Context, args: Arguments): Array[AnyRef] = { def suck(context: Context, args: Arguments): Array[AnyRef] = {
// Use equipped tool (e.g. dig, chop, till). // Pick up items lying around.
val side = checkSideForAction(args, 0) val side = checkSideForAction(args, 0)
val sneaky = args.checkBoolean(1)
null null
} }
@ -77,7 +140,7 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power
@LuaCallback("compare") @LuaCallback("compare")
def compare(context: Context, args: Arguments): Array[AnyRef] = { def compare(context: Context, args: Arguments): Array[AnyRef] = {
val side = checkSideForAction(args, 0) val side = checkSideForAction(args, 0)
items(actuallySelectedSlot) match { stackInSlot(selectedSlot) match {
case Some(stack) => Option(stack.getItem) match { case Some(stack) => Option(stack.getItem) match {
case Some(item: ItemBlock) => case Some(item: ItemBlock) =>
val (bx, by, bz) = (x + side.offsetX, y + side.offsetY, z + side.offsetZ) 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") @LuaCallback("attack")
def drop(context: Context, args: Arguments): Array[AnyRef] = { def attack(context: Context, args: Arguments): Array[AnyRef] = {
val count = if (args.count > 0) { // Attack with equipped tool.
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.
val side = checkSideForAction(args, 0) val side = checkSideForAction(args, 0)
null null
} }
@LuaCallback("suck") @LuaCallback("use")
def collect(context: Context, args: Arguments): Array[AnyRef] = { def use(context: Context, args: Arguments): Array[AnyRef] = {
// Pick up items lying around. // Use equipped tool (e.g. dig, chop, till).
val side = checkSideForAction(args, 0) val side = checkSideForAction(args, 0)
val sneaky = args.checkBoolean(1)
null null
} }
@ -152,12 +207,8 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power
def turn(context: Context, args: Arguments): Array[AnyRef] = { def turn(context: Context, args: Arguments): Array[AnyRef] = {
// Turn in the specified direction. // Turn in the specified direction.
val clockwise = args.checkBoolean(0) val clockwise = args.checkBoolean(0)
if (clockwise) { if (clockwise) rotate(ForgeDirection.UP)
rotate(ForgeDirection.UP) else rotate(ForgeDirection.DOWN)
}
else {
rotate(ForgeDirection.DOWN)
}
result(true) result(true)
} }
@ -184,6 +235,26 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power
else None 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 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) 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 selectedSlot = 0
var selectedSlotChanged = false def actualSlot(n: Int) = n + 3
def actuallySelectedSlot = selectedSlot + 3
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
@ -249,11 +318,6 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power
distributor.changeBuffer(10) // just for testing distributor.changeBuffer(10) // just for testing
distributor.update() distributor.update()
gpu.update() gpu.update()
if (selectedSlotChanged) {
selectedSlotChanged = false
// TODO ServerPacketSender.sendRobotSelectedSlotChange(this)
}
} }
} }

View File

@ -158,7 +158,10 @@ object Component {
def checkAny(index: Int) = { def checkAny(index: Int) = {
checkIndex(index, "value") checkIndex(index, "value")
args(index) args(index) match {
case Unit | None => null
case arg => arg
}
} }
def checkBoolean(index: Int) = { def checkBoolean(index: Int) = {
@ -246,7 +249,7 @@ object Component {
format(index + 1, want, typeName(have))) format(index + 1, want, typeName(have)))
private def typeName(value: AnyRef): String = value match { private def typeName(value: AnyRef): String = value match {
case null => "nil" case null | Unit | None => "nil"
case _: java.lang.Boolean => "boolean" case _: java.lang.Boolean => "boolean"
case _: java.lang.Double => "double" case _: java.lang.Double => "double"
case _: java.lang.String => "string" case _: java.lang.String => "string"