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)

This commit is contained in:
Florian Nücke 2013-12-25 21:33:41 +01:00
parent 69d64d2c67
commit 593fb615a3
10 changed files with 130 additions and 34 deletions

View File

@ -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 =>

View File

@ -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)
}
}

View File

@ -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 =>

View File

@ -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
}

View File

@ -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()

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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. */

View File

@ -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
})

View File

@ -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() {}