From 593fb615a3613390f5fda5a84f53d04191032abf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Wed, 25 Dec 2013 21:33:41 +0100 Subject: [PATCH] some changes to allow reusing existing inventory implementation with zero size item stacks; added adapter container and gui logic for phantom slot (i.e. inserting an item will just copy the stack info, but will actually store a stack with size zero) --- li/cil/oc/client/GuiHandler.scala | 2 + li/cil/oc/client/gui/Adapter.scala | 16 ++++++++ li/cil/oc/common/GuiHandler.scala | 2 + li/cil/oc/common/GuiType.scala | 10 ++++- li/cil/oc/common/block/Adapter.scala | 15 +++++++- li/cil/oc/common/container/Adapter.scala | 36 ++++++++++++++++++ .../oc/common/container/ComponentSlot.scala | 20 ++++++++++ li/cil/oc/common/container/Player.scala | 19 ++-------- li/cil/oc/common/tileentity/Adapter.scala | 38 ++++++++++++------- li/cil/oc/common/tileentity/Inventory.scala | 6 ++- 10 files changed, 130 insertions(+), 34 deletions(-) create mode 100644 li/cil/oc/client/gui/Adapter.scala create mode 100644 li/cil/oc/common/container/Adapter.scala create mode 100644 li/cil/oc/common/container/ComponentSlot.scala diff --git a/li/cil/oc/client/GuiHandler.scala b/li/cil/oc/client/GuiHandler.scala index faf56b7b1..6064a4f53 100644 --- a/li/cil/oc/client/GuiHandler.scala +++ b/li/cil/oc/client/GuiHandler.scala @@ -8,6 +8,8 @@ import net.minecraft.world.World object GuiHandler extends CommonGuiHandler { override def getClientGuiElement(id: Int, player: EntityPlayer, world: World, x: Int, y: Int, z: Int) = world.getBlockTileEntity(x, y, z) match { + case adapter: tileentity.Adapter if id == GuiType.Adapter.id => + new gui.Adapter(player.inventory, adapter) case computer: tileentity.Case if id == GuiType.Case.id => new gui.Case(player.inventory, computer) case drive: tileentity.DiskDrive if id == GuiType.DiskDrive.id => diff --git a/li/cil/oc/client/gui/Adapter.scala b/li/cil/oc/client/gui/Adapter.scala new file mode 100644 index 000000000..aeed32f60 --- /dev/null +++ b/li/cil/oc/client/gui/Adapter.scala @@ -0,0 +1,16 @@ +package li.cil.oc.client.gui + +import li.cil.oc.Settings +import li.cil.oc.common.container +import li.cil.oc.common.tileentity +import net.minecraft.entity.player.InventoryPlayer +import net.minecraft.util.StatCollector + +class Adapter(playerInventory: InventoryPlayer, val adapter: tileentity.Adapter) extends DynamicGuiContainer(new container.Adapter(playerInventory, adapter)) { + override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) = { + super.drawGuiContainerForegroundLayer(mouseX, mouseY) + fontRenderer.drawString( + StatCollector.translateToLocal(Settings.namespace + "container.Adapter"), + 8, 6, 0x404040) + } +} diff --git a/li/cil/oc/common/GuiHandler.scala b/li/cil/oc/common/GuiHandler.scala index defbabd22..269b48dbc 100644 --- a/li/cil/oc/common/GuiHandler.scala +++ b/li/cil/oc/common/GuiHandler.scala @@ -7,6 +7,8 @@ import net.minecraft.world.World abstract class GuiHandler extends IGuiHandler { override def getServerGuiElement(id: Int, player: EntityPlayer, world: World, x: Int, y: Int, z: Int) = world.getBlockTileEntity(x, y, z) match { + case adapter: tileentity.Adapter if id == GuiType.Adapter.id => + new container.Adapter(player.inventory, adapter) case computer: tileentity.Case if id == GuiType.Case.id => new container.Case(player.inventory, computer) case drive: tileentity.DiskDrive if id == GuiType.DiskDrive.id => diff --git a/li/cil/oc/common/GuiType.scala b/li/cil/oc/common/GuiType.scala index 5ac3601bb..b74396573 100644 --- a/li/cil/oc/common/GuiType.scala +++ b/li/cil/oc/common/GuiType.scala @@ -1,5 +1,13 @@ package li.cil.oc.common object GuiType extends Enumeration { - val Case, DiskDrive, Robot, Screen = Value + val + + Adapter, + Case, + DiskDrive, + Robot, + Screen + + = Value } diff --git a/li/cil/oc/common/block/Adapter.scala b/li/cil/oc/common/block/Adapter.scala index 2ccc47f04..a5f873fa3 100644 --- a/li/cil/oc/common/block/Adapter.scala +++ b/li/cil/oc/common/block/Adapter.scala @@ -1,8 +1,8 @@ package li.cil.oc.common.block import java.util -import li.cil.oc.Settings -import li.cil.oc.common.tileentity +import li.cil.oc.{OpenComputers, Settings} +import li.cil.oc.common.{GuiType, tileentity} import li.cil.oc.util.Tooltip import net.minecraft.client.renderer.texture.IconRegister import net.minecraft.entity.player.EntityPlayer @@ -42,6 +42,17 @@ class Adapter(val parent: SimpleDelegator) extends SimpleDelegate { // ----------------------------------------------------------------------- // + override def rightClick(world: World, x: Int, y: Int, z: Int, player: EntityPlayer, + side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) = { + if (!player.isSneaking) { + if (!world.isRemote) { + player.openGui(OpenComputers, GuiType.Adapter.id, world, x, y, z) + } + true + } + else false + } + override def neighborBlockChanged(world: World, x: Int, y: Int, z: Int, blockId: Int) = world.getBlockTileEntity(x, y, z) match { case adapter: tileentity.Adapter => adapter.neighborChanged() diff --git a/li/cil/oc/common/container/Adapter.scala b/li/cil/oc/common/container/Adapter.scala new file mode 100644 index 000000000..c01d6ed21 --- /dev/null +++ b/li/cil/oc/common/container/Adapter.scala @@ -0,0 +1,36 @@ +package li.cil.oc.common.container + +import li.cil.oc.common.tileentity +import net.minecraft.entity.player.{EntityPlayer, InventoryPlayer} +import net.minecraft.inventory.Slot + +class Adapter(playerInventory: InventoryPlayer, adapter: tileentity.Adapter) extends Player(playerInventory, adapter) { + addSlotToContainer(new ComponentSlot(otherInventory, 0, 80, 35) { + override def decrStackSize(amount: Int) = { + val stack = super.decrStackSize(math.max(amount, 1)) + if (stack == null || stack.stackSize < 1) null + else stack + } + }) + addPlayerInventorySlots(8, 84) + + override def slotClick(index: Int, mouseClick: Int, holdingShift: Int, player: EntityPlayer) = { + if (index == 0) { + inventorySlots.get(0) match { + case slot: Slot => slot.putStack(null) + case _ => + } + } + super.slotClick(index, mouseClick, holdingShift, player) + } + + override protected def tryTransferStackInSlot(from: Slot, offset: Int, length: Int, intoPlayerInventory: Boolean) = { + if (!intoPlayerInventory) { + inventorySlots.get(0) match { + case slot: Slot => slot.putStack(null) + case _ => + } + } + super.tryTransferStackInSlot(from, offset, length, intoPlayerInventory) + } +} diff --git a/li/cil/oc/common/container/ComponentSlot.scala b/li/cil/oc/common/container/ComponentSlot.scala new file mode 100644 index 000000000..514d52f97 --- /dev/null +++ b/li/cil/oc/common/container/ComponentSlot.scala @@ -0,0 +1,20 @@ +package li.cil.oc.common.container + +import li.cil.oc.api +import li.cil.oc.client.gui.Icons +import net.minecraft.inventory.{IInventory, Slot} +import net.minecraft.item.ItemStack + +class ComponentSlot(inventory: IInventory, index: Int, x: Int, y: Int, val slot: api.driver.Slot = api.driver.Slot.None) extends Slot(inventory, index, x, y) { + setBackgroundIcon(Icons.get(slot)) + + override def getSlotStackLimit = + slot match { + case api.driver.Slot.Tool | api.driver.Slot.None => super.getSlotStackLimit + case _ => 1 + } + + override def isItemValid(stack: ItemStack) = { + inventory.isItemValidForSlot(index, stack) + } +} diff --git a/li/cil/oc/common/container/Player.scala b/li/cil/oc/common/container/Player.scala index 40803bfde..2ca91091f 100644 --- a/li/cil/oc/common/container/Player.scala +++ b/li/cil/oc/common/container/Player.scala @@ -29,7 +29,8 @@ abstract class Player(protected val playerInventory: InventoryPlayer, val otherI // because stacks can change their... "character" just by being inserted in // certain containers - by being assigned an address. } - result + if (result != null && result.stackSize > 0) result + else null } override def transferStackInSlot(player: EntityPlayer, index: Int): ItemStack = { @@ -55,7 +56,7 @@ abstract class Player(protected val playerInventory: InventoryPlayer, val otherI null } - private def tryTransferStackInSlot(from: Slot, offset: Int, length: Int, intoPlayerInventory: Boolean) { + protected def tryTransferStackInSlot(from: Slot, offset: Int, length: Int, intoPlayerInventory: Boolean) { val fromStack = from.getStack var somethingChanged = false @@ -99,19 +100,7 @@ abstract class Player(protected val playerInventory: InventoryPlayer, val otherI def addSlotToContainer(x: Int, y: Int, slot: api.driver.Slot = api.driver.Slot.None) { val index = getInventory.size - addSlotToContainer(new Slot(otherInventory, index, x, y) { - setBackgroundIcon(Icons.get(slot)) - - override def getSlotStackLimit = - slot match { - case api.driver.Slot.Tool | api.driver.Slot.None => super.getSlotStackLimit - case _ => 1 - } - - override def isItemValid(stack: ItemStack) = { - otherInventory.isItemValidForSlot(index, stack) - } - }) + addSlotToContainer(new ComponentSlot(otherInventory, index, x, y, slot)) } /** Render player inventory at the specified coordinates. */ diff --git a/li/cil/oc/common/tileentity/Adapter.scala b/li/cil/oc/common/tileentity/Adapter.scala index 4b5bdc020..8a342e45c 100644 --- a/li/cil/oc/common/tileentity/Adapter.scala +++ b/li/cil/oc/common/tileentity/Adapter.scala @@ -2,22 +2,19 @@ package li.cil.oc.common.tileentity import li.cil.oc.api.network._ import li.cil.oc.server.driver -import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.{Settings, api} import net.minecraft.item.{ItemBlock, ItemStack} import net.minecraft.nbt.{NBTTagList, NBTTagCompound} import net.minecraftforge.common.ForgeDirection import scala.{Array, Some} -class Adapter extends Environment { +class Adapter extends Environment with Inventory { val node = api.Network.newNode(this, Visibility.Network).create() private val blocks = Array.fill[Option[(ManagedEnvironment, api.driver.Block)]](6)(None) private val blocksData = Array.fill[Option[BlockData]](6)(None) - private var filter: Option[ItemStack] = None - // ----------------------------------------------------------------------- // override def updateEntity() { @@ -34,7 +31,7 @@ class Adapter extends Environment { driver.Registry.driverFor(world, x, y, z) match { case Some(newDriver) => blocks(d.ordinal()) match { case Some((oldEnvironment, driver)) => - if (newDriver != driver) { + if (newDriver != driver || !isBlockSupported(x, y, z)) { // This is... odd. Maybe moved by some other mod? node.disconnect(oldEnvironment.node) if (isBlockSupported(x, y, z)) { @@ -98,10 +95,6 @@ class Adapter extends Environment { blocksData(i) = Some(new BlockData(blockNbt.getString("name"), blockNbt.getCompoundTag("data"))) } } - - if (nbt.hasKey(Settings.namespace + "adapter.filter")) { - filter = Option(ItemStack.loadItemStackFromNBT(nbt.getCompoundTag(Settings.namespace + "adapter.filter"))) - } } override def writeToNBT(nbt: NBTTagCompound) { @@ -123,18 +116,35 @@ class Adapter extends Environment { blocksNbt.appendTag(blockNbt) } nbt.setTag(Settings.namespace + "adapter.blocks", blocksNbt) + } - if (filter.isDefined) { - nbt.setNewCompoundTag(Settings.namespace + "adapter.filter", filter.get.writeToNBT) - } + // ----------------------------------------------------------------------- // + + def getSizeInventory = 1 + + def getInvName = Settings.namespace + "container.Adapter" + + def getInventoryStackLimit = 0 + + override def getInventoryStackRequired = 0 + + def isItemValidForSlot(i: Int, stack: ItemStack) = + stack != null && stack.stackSize > 0 && (stack.getItem match { + case block: ItemBlock => true + case _ => false + }) + + override def onInventoryChanged() { + super.onInventoryChanged() + neighborChanged() } // ----------------------------------------------------------------------- // private def isBlockSupported(x: Int, y: Int, z: Int) = - filter.isDefined && (filter.get.getItem match { + items(0).isDefined && (items(0).get.getItem match { case block: ItemBlock => - block.getBlockID == world.getBlockId(x, y, z) && block.getMetadata(block.getDamage(filter.get)) == world.getBlockMetadata(x, y, z) + block.getBlockID == world.getBlockId(x, y, z) && block.getMetadata(block.getDamage(items(0).get)) == world.getBlockMetadata(x, y, z) case _ => false }) diff --git a/li/cil/oc/common/tileentity/Inventory.scala b/li/cil/oc/common/tileentity/Inventory.scala index b139c663d..d7c5ffbcb 100644 --- a/li/cil/oc/common/tileentity/Inventory.scala +++ b/li/cil/oc/common/tileentity/Inventory.scala @@ -18,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 <= 0 => + case Some(stack) if stack.stackSize - amount < getInventoryStackRequired => setInventorySlotContents(slot, null) stack case Some(stack) => @@ -33,7 +33,7 @@ trait Inventory extends TileEntity with IInventory with Persistable { onItemRemoved(slot, items(slot).get) } - if (stack == null || stack.stackSize <= 0) { + if (stack == null || stack.stackSize < getInventoryStackRequired) { items(slot) = None } else { @@ -50,6 +50,8 @@ trait Inventory extends TileEntity with IInventory with Persistable { onInventoryChanged() } + def getInventoryStackRequired = 1 + def getStackInSlotOnClosing(slot: Int) = null def openChest() {}