package edx.basic.blocks import java.util.{HashSet, Iterator, Set} import codechicken.multipart.ControlKeyModifer import cpw.mods.fml.common.network.ByteBufUtils import cpw.mods.fml.relauncher.{Side, SideOnly} import edx.core.Reference import io.netty.buffer.ByteBuf import net.minecraft.block.Block import net.minecraft.block.material.Material import net.minecraft.client.renderer.texture.IIconRegister import net.minecraft.entity.player.EntityPlayer import net.minecraft.init.Blocks import net.minecraft.inventory.ISidedInventory import net.minecraft.item.ItemStack import net.minecraft.nbt.{NBTTagCompound, NBTTagList} import net.minecraft.network.Packet import net.minecraft.util.IIcon import net.minecraftforge.common.util.ForgeDirection import org.lwjgl.opengl.GL11 import resonantengine.api.network.IPacketReceiver import resonantengine.core.ResonantEngine import resonantengine.core.network.discriminator.{PacketTile, PacketType} import resonantengine.lib.modcontent.block.{ResonantBlock, ResonantTile} import resonantengine.lib.render.RenderItemOverlayUtility import resonantengine.lib.transform.vector.{Vector2, Vector3} import resonantengine.lib.utility.inventory.InventoryUtility import scala.collection.JavaConversions._ class TileImprinter extends ResonantTile(Material.circuits) with ISidedInventory with IPacketReceiver { var inventory: Array[ItemStack] = new Array[ItemStack](10) override def getDescriptionPacket: Packet = { val nbt: NBTTagCompound = new NBTTagCompound this.writeToNBT(nbt) return ResonantEngine.packetHandler.toMCPacket(new PacketTile(this, nbt)) } /** * Writes a tile entity to NBT. */ override def writeToNBT(nbt: NBTTagCompound) { super.writeToNBT(nbt) val var2: NBTTagList = new NBTTagList for (i <- 0 to this.getSizeInventory) { if (this.getStackInSlot(i) != null) { val var4: NBTTagCompound = new NBTTagCompound var4.setByte("Slot", i.asInstanceOf[Byte]) this.getStackInSlot(i).writeToNBT(var4) var2.appendTag(var4) } } nbt.setTag("Items", var2) } def read(data: ByteBuf, player: EntityPlayer, `type`: PacketType) { try { this.readFromNBT(ByteBufUtils.readTag(data)) } catch { case e: Exception => { e.printStackTrace } } } /** * NBT Data */ override def readFromNBT(nbt: NBTTagCompound) { super.readFromNBT(nbt) val var2: NBTTagList = nbt.getTagList("Items", 0) this.inventory = new Array[ItemStack](10) for (i <- 0 to var2.tagCount) { val var4: NBTTagCompound = var2.getCompoundTagAt(i).asInstanceOf[NBTTagCompound] val var5: Byte = var4.getByte("Slot") if (var5 >= 0 && var5 < this.getSizeInventory) { this.setInventorySlotContents(var5, ItemStack.loadItemStackFromNBT(var4)) } } } /** * Inventory methods. */ override def canUpdate: Boolean = { return false } def getInventoryName: String = { return null } def hasCustomInventoryName: Boolean = { return false } def decrStackSize(i: Int, amount: Int): ItemStack = { if (this.getStackInSlot(i) != null) { var stack: ItemStack = null if (this.getStackInSlot(i).stackSize <= amount) { stack = this.getStackInSlot(i) this.setInventorySlotContents(i, null) return stack } else { stack = this.getStackInSlot(i).splitStack(amount) if (this.getStackInSlot(i).stackSize == 0) { this.setInventorySlotContents(i, null) } return stack } } else { return null } } /** * Sets the given item stack to the specified slot in the inventory (can be crafting or armor * sections). */ def setInventorySlotContents(slot: Int, itemStack: ItemStack) { if (slot < this.getSizeInventory) { inventory(slot) = itemStack } } def getSizeInventory: Int = { return this.inventory.length } def getStackInSlot(slot: Int): ItemStack = { return this.inventory(slot) } /** * When some containers are closed they call this on each slot, then drop whatever it returns as * an EntityItem - like when you close a workbench GUI. */ def getStackInSlotOnClosing(slot: Int): ItemStack = { if (this.getStackInSlot(slot) != null) { val var2: ItemStack = this.getStackInSlot(slot) this.setInventorySlotContents(slot, null) return var2 } else { return null } } def openInventory { this.onInventoryChanged } def closeInventory { this.onInventoryChanged } /** * Updates all the output slots. Call this to update the Imprinter. */ def onInventoryChanged { if (!this.worldObj.isRemote) { val fitlerStack: ItemStack = this.inventory(9) if (fitlerStack != null && fitlerStack.getItem.isInstanceOf[ItemImprint]) { val outputStack: ItemStack = fitlerStack.copy val filters: java.util.List[ItemStack] = ItemImprint.getFilters(outputStack) val toAdd: Set[ItemStack] = new HashSet[ItemStack] val toBeImprinted: Set[ItemStack] = new HashSet[ItemStack] var i: Int = 0 while (i < 9) { val stackInInventory: ItemStack = inventory(i) if (stackInInventory != null) { for (check <- toBeImprinted) { if (check.isItemEqual(stackInInventory)) { i = 10 } } toBeImprinted.add(stackInInventory) } i += 1; } for (stackInInventory <- toBeImprinted) { val it: Iterator[ItemStack] = filters.iterator var removed: Boolean = false while (it.hasNext) { val filteredStack: ItemStack = it.next if (filteredStack.isItemEqual(stackInInventory)) { it.remove removed = true } } if (!removed) { toAdd.add(stackInInventory) } } filters.addAll(toAdd) ItemImprint.setFilters(outputStack, filters) this.inventory(9) = outputStack } } } def getInventoryStackLimit: Int = { return 64 } def isUseableByPlayer(entityplayer: EntityPlayer): Boolean = { return if (this.worldObj.getTileEntity(this.xCoord, this.yCoord, this.zCoord) ne this) false else entityplayer.getDistanceSq(this.xCoord + 0.5D, this.yCoord + 0.5D, this.zCoord + 0.5D) <= 64.0D } def getAccessibleSlotsFromSide(side: Int): Array[Int] = { return if (side == 1) Array[Int](0, 1, 2, 3, 4, 5, 6, 7, 8) else new Array[Int](10) } def canInsertItem(slot: Int, itemstack: ItemStack, side: Int): Boolean = { return this.isItemValidForSlot(slot, itemstack) } def isItemValidForSlot(i: Int, itemstack: ItemStack): Boolean = { return true } def canExtractItem(slot: Int, itemstack: ItemStack, side: Int): Boolean = { return this.isItemValidForSlot(slot, itemstack) } override def renderDynamic(position: Vector3, frame: Float, pass: Int) { GL11.glPushMatrix RenderItemOverlayUtility.renderTopOverlay(this, inventory, ForgeDirection.EAST, x, y, z) RenderItemOverlayUtility.renderItemOnSides(this, getStackInSlot(9), x, y, z) GL11.glPopMatrix } @SideOnly(Side.CLIENT) override def registerIcons(iconReg: IIconRegister) { super.registerIcons(iconReg) ResonantBlock.icon.put("imprinter_side", iconReg.registerIcon(Reference.prefix + "imprinter_side")) ResonantBlock.icon.put("imprinter_top", iconReg.registerIcon(Reference.prefix + "imprinter_top")) ResonantBlock.icon.put("imprinter_bottom", iconReg.registerIcon(Reference.prefix + "imprinter_bottom")) } @SideOnly(Side.CLIENT) override def getIcon(side: Int, meta: Int): IIcon = { if (side == 1) { return ResonantBlock.icon.get("imprinter_top") } else if (side == 0) { return ResonantBlock.icon.get("imprinter_bottom") } return ResonantBlock.icon.get("imprinter_side") } override def use(player: EntityPlayer, hitSide: Int, hit: Vector3): Boolean = { var current: ItemStack = player.inventory.getCurrentItem if (hitSide == 1) { if (!world.isRemote) { val hitVector: Vector2 = new Vector2(hit.x, hit.z) val regionLength: Double = 1d / 3d for (j <- 0 to 3) { for (k <- 0 to 3) { val check: Vector2 = new Vector2(j, k).multiply(regionLength) if (check.distance(hitVector) < regionLength) { val slotID: Int = j * 3 + k var didInsert: Boolean = false val checkStack: ItemStack = inventory(slotID) if (current != null) { if (checkStack == null || checkStack.isItemEqual(current)) { if (ControlKeyModifer.isControlDown(player)) { if (checkStack == null) { inventory(slotID) = current } else { inventory(slotID).stackSize += current.stackSize current.stackSize = 0 } current = null } else { if (checkStack == null) { inventory(slotID) = current.splitStack(1) } else { inventory(slotID).stackSize += 1 current.stackSize -= 1 } } if (current == null || current.stackSize <= 0) { player.inventory.setInventorySlotContents(player.inventory.currentItem, null) } didInsert = true } } if (!didInsert && checkStack != null) { InventoryUtility.dropItemStack(world, new Vector3(player), checkStack, 0) inventory(slotID) = null } world.markBlockForUpdate(x, y, z) return true } } } world.markBlockForUpdate(x, y, z) } return true } else if (hitSide != 0) { val output: ItemStack = getStackInSlot(9) if (output != null) { InventoryUtility.dropItemStack(world, new Vector3(player), output, 0) setInventorySlotContents(9, null) } else if (current != null && current.getItem.isInstanceOf[ItemImprint]) { setInventorySlotContents(9, current) player.inventory.setInventorySlotContents(player.inventory.currentItem, null) } } return false } override def onNeighborChanged(block: Block) { val b: Block = (position + ForgeDirection.getOrientation(1)).getBlock if (Blocks.piston_head eq b) { onInventoryChanged } } }