diff --git a/li/cil/oc/common/tileentity/Robot.scala b/li/cil/oc/common/tileentity/Robot.scala index de81ed493..e1cb0d9e0 100644 --- a/li/cil/oc/common/tileentity/Robot.scala +++ b/li/cil/oc/common/tileentity/Robot.scala @@ -10,18 +10,12 @@ import li.cil.oc.common import li.cil.oc.server.component import li.cil.oc.server.component.GraphicsCard import li.cil.oc.server.driver.Registry -import li.cil.oc.server.{PacketSender => ServerPacketSender} import li.cil.oc.util.ExtendedNBT._ -import net.minecraft.block.Block +import li.cil.oc.util.RobotPlayer import net.minecraft.client.Minecraft -import net.minecraft.entity.EntityLivingBase -import net.minecraft.item.{ItemBlock, ItemStack} +import net.minecraft.item.ItemStack import net.minecraft.nbt.NBTTagCompound -import net.minecraft.util.AxisAlignedBB -import net.minecraftforge.common.ForgeDirection -import net.minecraftforge.fluids.FluidRegistry import scala.Some -import scala.collection.convert.WrapAsScala._ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with PowerInformation { def this() = this(false) @@ -32,243 +26,11 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power withComponent("computer", Visibility.Neighbors). create() + lazy val player = new RobotPlayer(this) override val buffer = new common.component.Buffer(this) { override def maxResolution = (48, 14) } - override val computer = if (isRemote) null - else new component.Computer(this) { - override def isRobot(context: Context, args: Arguments): Array[AnyRef] = - Array(java.lang.Boolean.TRUE) - - // ----------------------------------------------------------------------- // - - @LuaCallback("select") - def select(context: Context, args: Arguments): Array[AnyRef] = { - // Get or set selected inventory slot. - if (args.count > 0 && args.checkAny(0) != null) { - val slot = checkSlot(args, 0) - if (slot != selectedSlot) { - selectedSlot = slot - ServerPacketSender.sendRobotSelectedSlotState(Robot.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("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("suck") - def suck(context: Context, args: Arguments): Array[AnyRef] = { - // Pick up items lying around. - val side = checkSideForAction(args, 0) - null - } - - // ----------------------------------------------------------------------- // - - @LuaCallback("compare") - def compare(context: Context, args: Arguments): Array[AnyRef] = { - val side = checkSideForAction(args, 0) - 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) - val idMatches = item.getBlockID == world.getBlockId(bx, by, bz) - val subTypeMatches = !item.getHasSubtypes || item.getMetadata(stack.getItemDamage) == world.getBlockMetadata(bx, by, bz) - return result(idMatches && subTypeMatches) - case _ => - } - case _ => - } - result(false) - } - - @LuaCallback("detect") - def detect(context: Context, args: Arguments): Array[AnyRef] = { - val side = checkSideForAction(args, 0) - val (bx, by, bz) = (x + side.offsetX, y + side.offsetY, z + side.offsetZ) - val id = world.getBlockId(bx, by, bz) - val block = Block.blocksList(id) - if (id == 0 || block == null || block.isAirBlock(world, bx, by, bz)) { - closestEntity(side) match { - case Some(entity) => result(true, "entity") - case _ => result(false, "air") - } - } - else if (FluidRegistry.lookupFluidForBlock(block) != null) { - result(false, "liquid") - } - else if (block.isBlockReplaceable(world, bx, by, bz)) { - result(false, "replaceable") - } - else { - result(true, "solid") - } - } - - // ----------------------------------------------------------------------- // - - @LuaCallback("attack") - def attack(context: Context, args: Arguments): Array[AnyRef] = { - // Attack with equipped tool. - val side = checkSideForAction(args, 0) - null - } - - @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 - } - - // ----------------------------------------------------------------------- // - - @LuaCallback("move") - def move(context: Context, args: Arguments): Array[AnyRef] = { - // Try to move in the specified direction. - val side = checkSideForMovement(args, 0) - null - } - - @LuaCallback("turn") - 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) - result(true) - } - - // ----------------------------------------------------------------------- // - - private def closestEntity(side: ForgeDirection) = { - val (bx, by, bz) = (x + side.offsetX, y + side.offsetY, z + side.offsetZ) - val id = world.getBlockId(bx, by, bz) - val block = Block.blocksList(id) - if (id == 0 || block == null || block.isAirBlock(world, bx, by, bz)) { - val bounds = AxisAlignedBB.getAABBPool.getAABB(bx, by, bz, bx + 1, by + 1, bz + 1) - val entities = world.getEntitiesWithinAABB(classOf[EntityLivingBase], bounds) - entities.foldLeft((Double.PositiveInfinity, None: Option[EntityLivingBase])) { - case ((bestDistance, bestEntity), entity: EntityLivingBase) => - val distance = entity.getDistanceSq(x + 0.5, y + 0.5, z + 0.5) - if (distance < bestDistance) (distance, Some(entity)) - else (bestDistance, bestEntity) - case (best, _) => best - } match { - case (_, Some(entity)) => Some(entity) - case _ => 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 checkSideForMovement(args: Arguments, n: Int) = checkSide(args, n, ForgeDirection.SOUTH, ForgeDirection.NORTH) - - private def checkSide(args: Arguments, n: Int, allowed: ForgeDirection*) = { - val side = args.checkInteger(n) - if (side < 0 || side > 5) { - throw new IllegalArgumentException("invalid side") - } - val direction = ForgeDirection.getOrientation(side) - if (allowed contains direction) toGlobal(direction) - else throw new IllegalArgumentException("unsupported side") - } - } + override val computer = if (isRemote) null else new component.Robot(this) val (battery, distributor, gpu, keyboard) = if (isServer) { val battery = api.Network.newNode(this, Visibility.Network).withConnector(10000).create() val distributor = new component.PowerDistributor(this) @@ -282,8 +44,6 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power var selectedSlot = 0 - def actualSlot(n: Int) = n + 3 - // ----------------------------------------------------------------------- // def tier = 0 @@ -292,6 +52,8 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power override def installedMemory = 64 * 1024 + def actualSlot(n: Int) = n + 3 + // ----------------------------------------------------------------------- // @LuaCallback("start") diff --git a/li/cil/oc/server/component/Robot.scala b/li/cil/oc/server/component/Robot.scala new file mode 100644 index 000000000..e115f1b3a --- /dev/null +++ b/li/cil/oc/server/component/Robot.scala @@ -0,0 +1,262 @@ +package li.cil.oc.server.component + +import li.cil.oc.api.network.{LuaCallback, Arguments, Context} +import li.cil.oc.common.tileentity +import li.cil.oc.server.{PacketSender => ServerPacketSender} +import net.minecraft.block.Block +import net.minecraft.entity.item.EntityItem +import net.minecraft.entity.{Entity, EntityLivingBase} +import net.minecraft.item.{ItemStack, ItemBlock} +import net.minecraft.util.AxisAlignedBB +import net.minecraftforge.common.ForgeDirection +import net.minecraftforge.fluids.FluidRegistry +import scala.Some +import scala.collection.convert.WrapAsScala._ +import scala.reflect._ + +class Robot(val robot: tileentity.Robot) extends Computer(robot) { + + override def isRobot(context: Context, args: Arguments): Array[AnyRef] = + Array(java.lang.Boolean.TRUE) + + // ----------------------------------------------------------------------- // + + @LuaCallback("select") + def select(context: Context, args: Arguments): Array[AnyRef] = { + if (args.count > 0 && args.checkAny(0) != null) { + val slot = checkSlot(args, 0) + if (slot != robot.selectedSlot) { + robot.selectedSlot = slot + ServerPacketSender.sendRobotSelectedSlotState(robot) + } + } + result(robot.selectedSlot) + } + + @LuaCallback("count") + def count(context: Context, args: Arguments): Array[AnyRef] = + result(stackInSlot(robot.selectedSlot) match { + case Some(stack) => stack.stackSize + case _ => 0 + }) + + @LuaCallback("space") + def space(context: Context, args: Arguments): Array[AnyRef] = + result(stackInSlot(robot.selectedSlot) match { + case Some(stack) => robot.getInventoryStackLimit - stack.stackSize + case _ => robot.getInventoryStackLimit + }) + + @LuaCallback("compareTo") + def compareTo(context: Context, args: Arguments): Array[AnyRef] = { + val slot = checkSlot(args, 0) + result((stackInSlot(robot.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 == robot.selectedSlot || count == 0) { + result(true) + } + else result((stackInSlot(robot.selectedSlot), stackInSlot(slot)) match { + case (Some(from), Some(to)) => + if (haveSameItemType(from, to)) { + val space = (robot.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) { + robot.setInventorySlotContents(robot.actualSlot(robot.selectedSlot), null) + } + true + } + else false + } + else { + robot.setInventorySlotContents(robot.actualSlot(slot), from) + robot.setInventorySlotContents(robot.actualSlot(robot.selectedSlot), to) + true + } + case (Some(from), None) => + robot.setInventorySlotContents(robot.actualSlot(slot), robot.decrStackSize(robot.actualSlot(robot.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) + // TODO inventory, if available + result(robot.dropSlot(robot.actualSlot(robot.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("suck") + def suck(context: Context, args: Arguments): Array[AnyRef] = { + // Pick up items lying around. + val side = checkSideForAction(args, 0) + val count = checkOptionalItemCount(args, 1) + // TODO inventory, if available + for (entity <- entitiesOnSide[EntityItem](side) if !entity.isDead && entity.delayBeforeCanPickup <= 0) { + val stack = entity.getEntityItem + val size = stack.stackSize + entity.onCollideWithPlayer(robot.player) + if (stack.stackSize < size || entity.isDead) return result(true) + } + result(false) + } + + // ----------------------------------------------------------------------- // + + @LuaCallback("compare") + def compare(context: Context, args: Arguments): Array[AnyRef] = { + val side = checkSideForAction(args, 0) + stackInSlot(robot.selectedSlot) match { + case Some(stack) => Option(stack.getItem) match { + case Some(item: ItemBlock) => + val (bx, by, bz) = (robot.x + side.offsetX, robot.y + side.offsetY, robot.z + side.offsetZ) + val idMatches = item.getBlockID == robot.world.getBlockId(bx, by, bz) + val subTypeMatches = !item.getHasSubtypes || item.getMetadata(stack.getItemDamage) == robot.world.getBlockMetadata(bx, by, bz) + return result(idMatches && subTypeMatches) + case _ => + } + case _ => + } + result(false) + } + + @LuaCallback("detect") + def detect(context: Context, args: Arguments): Array[AnyRef] = { + val side = checkSideForAction(args, 0) + val (bx, by, bz) = (robot.x + side.offsetX, robot.y + side.offsetY, robot.z + side.offsetZ) + val id = robot.world.getBlockId(bx, by, bz) + val block = Block.blocksList(id) + if (id == 0 || block == null || block.isAirBlock(robot.world, bx, by, bz)) { + closestLivingEntity(side) match { + case Some(entity) => result(true, "entity") + case _ => result(false, "air") + } + } + else if (FluidRegistry.lookupFluidForBlock(block) != null) { + result(false, "liquid") + } + else if (block.isBlockReplaceable(robot.world, bx, by, bz)) { + result(false, "replaceable") + } + else { + result(true, "solid") + } + } + + // ----------------------------------------------------------------------- // + + @LuaCallback("attack") + def attack(context: Context, args: Arguments): Array[AnyRef] = { + // Attack with equipped tool. + val side = checkSideForAction(args, 0) + null + } + + @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 + } + + // ----------------------------------------------------------------------- // + + @LuaCallback("move") + def move(context: Context, args: Arguments): Array[AnyRef] = { + // Try to move in the specified direction. + val side = checkSideForMovement(args, 0) + null + } + + @LuaCallback("turn") + def turn(context: Context, args: Arguments): Array[AnyRef] = { + // Turn in the specified direction. + val clockwise = args.checkBoolean(0) + if (clockwise) robot.rotate(ForgeDirection.UP) + else robot.rotate(ForgeDirection.DOWN) + result(true) + } + + // ----------------------------------------------------------------------- // + + private def closestLivingEntity(side: ForgeDirection) = { + entitiesOnSide[EntityLivingBase](side). + foldLeft((Double.PositiveInfinity, None: Option[EntityLivingBase])) { + case ((bestDistance, bestEntity), entity: EntityLivingBase) => + val distance = entity.getDistanceSq(robot.x + 0.5, robot.y + 0.5, robot.z + 0.5) + if (distance < bestDistance) (distance, Some(entity)) + else (bestDistance, bestEntity) + case (best, _) => best + } match { + case (_, Some(entity)) => Some(entity) + case _ => None + } + } + + private def entitiesOnSide[Type <: Entity : ClassTag](side: ForgeDirection) = { + val (bx, by, bz) = (robot.x + side.offsetX, robot.y + side.offsetY, robot.z + side.offsetZ) + val id = robot.world.getBlockId(bx, by, bz) + val block = Block.blocksList(id) + if (id == 0 || block == null || block.isAirBlock(robot.world, bx, by, bz)) { + val bounds = AxisAlignedBB.getAABBPool.getAABB(bx, by, bz, bx + 1, by + 1, bz + 1) + robot.world.getEntitiesWithinAABB(classTag[Type].runtimeClass, bounds).map(_.asInstanceOf[Type]) + } + else Iterable.empty + } + + private def haveSameItemType(stackA: ItemStack, stackB: ItemStack) = + stackA.itemID == stackB.itemID && + (!stackA.getHasSubtypes || stackA.getItemDamage == stackB.getItemDamage) + + private def stackInSlot(slot: Int) = Option(robot.getStackInSlot(robot.actualSlot(slot))) + + private def checkOptionalItemCount(args: Arguments, n: Int) = + if (args.count > n && args.checkAny(n) != null) { + args.checkInteger(n) max 0 min robot.getInventoryStackLimit + } + else robot.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) + + private def checkSide(args: Arguments, n: Int, allowed: ForgeDirection*) = { + val side = args.checkInteger(n) + if (side < 0 || side > 5) { + throw new IllegalArgumentException("invalid side") + } + val direction = ForgeDirection.getOrientation(side) + if (allowed contains direction) robot.toGlobal(direction) + else throw new IllegalArgumentException("unsupported side") + } +} diff --git a/li/cil/oc/util/InventoryRobot.scala b/li/cil/oc/util/InventoryRobot.scala new file mode 100644 index 000000000..e6a2add69 --- /dev/null +++ b/li/cil/oc/util/InventoryRobot.scala @@ -0,0 +1,136 @@ +package li.cil.oc.util + +import net.minecraft.block.Block +import net.minecraft.entity.player.InventoryPlayer +import net.minecraft.item.{Item, ItemStack} +import net.minecraft.nbt.NBTTagList +import scala.util.control.Breaks._ + +class InventoryRobot(player: RobotPlayer) extends InventoryPlayer(player) { + val robot = player.robot + + def selectedSlot = robot.actualSlot(robot.selectedSlot) + + def selectedItemStack = robot.getStackInSlot(selectedSlot) + + def inventorySlots = (robot.actualSlot(robot.selectedSlot) until getSizeInventory) ++ (0 until robot.actualSlot(robot.selectedSlot)) + + override def getCurrentItem = getStackInSlot(0) + + override def getFirstEmptyStack = { + if (selectedItemStack == null) selectedSlot + else inventorySlots.find(getStackInSlot(_) == null).getOrElse(-1) + } + + def getFirstEmptyStackAccepting(stack: ItemStack) = { + if (selectedItemStack == null && isItemValidForSlot(selectedSlot, stack)) selectedSlot + else inventorySlots.find(slot => getStackInSlot(slot) == null && isItemValidForSlot(slot, stack)).getOrElse(-1) + } + + override def setCurrentItem(itemId: Int, itemDamage: Int, checkDamage: Boolean, create: Boolean) {} + + override def changeCurrentItem(direction: Int) {} + + override def clearInventory(itemId: Int, itemDamage: Int) = 0 + + override def func_70439_a(item: Item, itemDamage: Int) {} + + override def decrementAnimations() {} + + override def consumeInventoryItem(itemId: Int) = false + + override def hasItem(itemId: Int) = (0 until getSizeInventory).map(getStackInSlot).filter(_ != null).exists(_.itemID == itemId) + + override def addItemStackToInventory(stack: ItemStack) = { + if (stack == null || stack.stackSize == 0) false + else if (stack.isItemDamaged || (stack.stackSize == 1 && stack.getMaxStackSize == 1)) { + val slot = getFirstEmptyStackAccepting(stack) + if (slot >= 0) { + setInventorySlotContents(slot, stack.splitStack(1)) + true + } + else false + } + else { + val originalSize = stack.stackSize + breakable { + while (stack.stackSize > 0) { + if (stack.getMaxStackSize == 1) { + val slot = getFirstEmptyStackAccepting(stack) + if (slot >= 0) { + setInventorySlotContents(slot, stack.splitStack(1)) + } + else break() + } + else { + val slot = + if (selectedItemStack == null) selectedSlot + else inventorySlots.find(slot => { + val existing = getStackInSlot(slot) + existing != null && existing.isItemEqual(stack) && + (!existing.getHasSubtypes || existing.getItemDamage == stack.getItemDamage) && + (existing.stackSize < (existing.getMaxStackSize min getInventoryStackLimit)) + }).getOrElse(getFirstEmptyStackAccepting(stack)) + if (slot >= 0) { + if (getStackInSlot(slot) == null) { + val amount = stack.stackSize min (getInventoryStackLimit min stack.getMaxStackSize) + setInventorySlotContents(slot, stack.splitStack(amount)) + } + else { + val existing = getStackInSlot(slot) + val space = (getInventoryStackLimit min existing.getMaxStackSize) - existing.stackSize + val amount = stack.stackSize min space + existing.stackSize += amount + stack.stackSize -= amount + } + } + else break() + } + } + } + if (stack.stackSize < originalSize) { + // This emulates behavior of the player's inventory, where surplus + // items from a collected stack vanish (yes, they do, yes, it sucks). + stack.stackSize = 0 + true + } + else false + } + } + + override def decrStackSize(slot: Int, amount: Int) = robot.decrStackSize(slot, amount) + + override def getStackInSlotOnClosing(slot: Int) = robot.getStackInSlotOnClosing(slot) + + override def setInventorySlotContents(slot: Int, stack: ItemStack) = robot.setInventorySlotContents(slot, stack) + + override def getStrVsBlock(block: Block) = Option(getCurrentItem).fold(1f)(_.getStrVsBlock(block)) + + override def writeToNBT(nbt: NBTTagList) = nbt + + override def readFromNBT(nbt: NBTTagList) {} + + override def getSizeInventory = robot.getSizeInventory + + override def getStackInSlot(slot: Int) = robot.getStackInSlot(slot) + + override def getInvName = robot.getInvName + + override def getInventoryStackLimit = robot.getInventoryStackLimit + + override def armorItemInSlot(slot: Int) = null + + override def getTotalArmorValue = 0 + + override def damageArmor(damage: Float) {} + + override def dropAllItems() = robot.dropAllSlots() + + override def onInventoryChanged() = robot.onInventoryChanged() + + override def hasItemStack(stack: ItemStack) = (0 until getSizeInventory).map(getStackInSlot).filter(_ != null).exists(_.isItemEqual(stack)) + + override def isItemValidForSlot(slot: Int, item: ItemStack) = robot.isItemValidForSlot(slot, item) + + override def copyInventory(from: InventoryPlayer) {} +} diff --git a/li/cil/oc/util/RobotPlayer.scala b/li/cil/oc/util/RobotPlayer.scala new file mode 100644 index 000000000..21e6a2864 --- /dev/null +++ b/li/cil/oc/util/RobotPlayer.scala @@ -0,0 +1,16 @@ +package li.cil.oc.util + +import li.cil.oc.common.tileentity.Robot +import net.minecraft.util.ChunkCoordinates +import net.minecraftforge.common.FakePlayer + +class RobotPlayer(val robot: Robot) extends FakePlayer(robot.world, "OpenComputers") { + capabilities.allowFlying = true + capabilities.disableDamage = true + capabilities.isFlying = true + inventory = new InventoryRobot(this) + + // TODO override def getBoundingBox = super.getBoundingBox + + override def getPlayerCoordinates = new ChunkCoordinates(robot.x, robot.y, robot.z) +}