From 799224e92b2879724e1bde86a43b6b688a05a308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Mon, 23 Mar 2015 01:58:35 +0100 Subject: [PATCH 01/17] Also calling doCustomInit on client side. --- .../cil/oc/common/block/Microcontroller.scala | 6 ++++-- .../scala/li/cil/oc/common/block/Raid.scala | 18 ++++++++++-------- .../oc/common/block/traits/CustomDrops.scala | 10 ++++------ .../li/cil/oc/common/item/data/ItemData.scala | 4 ---- 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/main/scala/li/cil/oc/common/block/Microcontroller.scala b/src/main/scala/li/cil/oc/common/block/Microcontroller.scala index c4c475bcd..de1ede9e4 100644 --- a/src/main/scala/li/cil/oc/common/block/Microcontroller.scala +++ b/src/main/scala/li/cil/oc/common/block/Microcontroller.scala @@ -102,8 +102,10 @@ class Microcontroller(protected implicit val tileTag: ClassTag[tileentity.Microc override protected def doCustomInit(tileEntity: tileentity.Microcontroller, player: EntityLivingBase, stack: ItemStack): Unit = { super.doCustomInit(tileEntity, player, stack) - tileEntity.info.load(stack) - tileEntity.snooperNode.changeBuffer(tileEntity.info.storedEnergy - tileEntity.snooperNode.localBuffer) + if (!tileEntity.world.isRemote) { + tileEntity.info.load(stack) + tileEntity.snooperNode.changeBuffer(tileEntity.info.storedEnergy - tileEntity.snooperNode.localBuffer) + } } override protected def doCustomDrops(tileEntity: tileentity.Microcontroller, player: EntityPlayer, willHarvest: Boolean): Unit = { diff --git a/src/main/scala/li/cil/oc/common/block/Raid.scala b/src/main/scala/li/cil/oc/common/block/Raid.scala index e23b1a959..db0c17f6d 100644 --- a/src/main/scala/li/cil/oc/common/block/Raid.scala +++ b/src/main/scala/li/cil/oc/common/block/Raid.scala @@ -55,14 +55,16 @@ class Raid(protected implicit val tileTag: ClassTag[tileentity.Raid]) extends Si override protected def doCustomInit(tileEntity: tileentity.Raid, player: EntityLivingBase, stack: ItemStack): Unit = { super.doCustomInit(tileEntity, player, stack) - val data = new RaidData(stack) - for (i <- 0 until math.min(data.disks.length, tileEntity.getSizeInventory)) { - tileEntity.setInventorySlotContents(i, data.disks(i)) - } - data.label.foreach(tileEntity.label.setLabel) - if (!data.filesystem.hasNoTags) { - tileEntity.tryCreateRaid(data.filesystem.getCompoundTag("node").getString("address")) - tileEntity.filesystem.foreach(_.load(data.filesystem)) + if (!tileEntity.world.isRemote) { + val data = new RaidData(stack) + for (i <- 0 until math.min(data.disks.length, tileEntity.getSizeInventory)) { + tileEntity.setInventorySlotContents(i, data.disks(i)) + } + data.label.foreach(tileEntity.label.setLabel) + if (!data.filesystem.hasNoTags) { + tileEntity.tryCreateRaid(data.filesystem.getCompoundTag("node").getString("address")) + tileEntity.filesystem.foreach(_.load(data.filesystem)) + } } } diff --git a/src/main/scala/li/cil/oc/common/block/traits/CustomDrops.scala b/src/main/scala/li/cil/oc/common/block/traits/CustomDrops.scala index 8a74a8897..40aafff03 100644 --- a/src/main/scala/li/cil/oc/common/block/traits/CustomDrops.scala +++ b/src/main/scala/li/cil/oc/common/block/traits/CustomDrops.scala @@ -31,12 +31,10 @@ trait CustomDrops[Tile <: TileEntity] extends SimpleBlock { override def onBlockPlacedBy(world: World, x: Int, y: Int, z: Int, player: EntityLivingBase, stack: ItemStack): Unit = { super.onBlockPlacedBy(world, x, y, z, player, stack) - if (!world.isRemote) { - val matcher = tileTag - world.getTileEntity(x, y, z) match { - case matcher(tileEntity) => doCustomInit(tileEntity, player, stack) - case _ => - } + val matcher = tileTag + world.getTileEntity(x, y, z) match { + case matcher(tileEntity) => doCustomInit(tileEntity, player, stack) + case _ => } } diff --git a/src/main/scala/li/cil/oc/common/item/data/ItemData.scala b/src/main/scala/li/cil/oc/common/item/data/ItemData.scala index 1df64ade7..c721c78bb 100644 --- a/src/main/scala/li/cil/oc/common/item/data/ItemData.scala +++ b/src/main/scala/li/cil/oc/common/item/data/ItemData.scala @@ -4,10 +4,6 @@ import li.cil.oc.api.Persistable import net.minecraft.item.ItemStack import net.minecraft.nbt.NBTTagCompound -object ItemData { - -} - abstract class ItemData extends Persistable { def load(stack: ItemStack) { if (stack.hasTagCompound) { From bb3456d86eee99c6623b1b954f328129b2865714 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Mon, 23 Mar 2015 01:59:55 +0100 Subject: [PATCH 02/17] Added block type with data driven model, stored in item stack. --- .../client/renderer/block/BlockRenderer.scala | 83 ++----------------- .../oc/client/renderer/block/Keyboard.scala | 36 ++++++++ .../cil/oc/client/renderer/block/Print.scala | 24 ++++++ .../oc/client/renderer/block/ServerRack.scala | 62 ++++++++++++++ .../scala/li/cil/oc/common/block/Print.scala | 61 ++++++++++++++ .../scala/li/cil/oc/common/init/Blocks.scala | 4 + .../cil/oc/common/item/data/PrintData.scala | 79 ++++++++++++++++++ .../li/cil/oc/common/tileentity/Print.scala | 48 +++++++++++ 8 files changed, 322 insertions(+), 75 deletions(-) create mode 100644 src/main/scala/li/cil/oc/client/renderer/block/Keyboard.scala create mode 100644 src/main/scala/li/cil/oc/client/renderer/block/Print.scala create mode 100644 src/main/scala/li/cil/oc/client/renderer/block/ServerRack.scala create mode 100644 src/main/scala/li/cil/oc/common/block/Print.scala create mode 100644 src/main/scala/li/cil/oc/common/item/data/PrintData.scala create mode 100644 src/main/scala/li/cil/oc/common/tileentity/Print.scala diff --git a/src/main/scala/li/cil/oc/client/renderer/block/BlockRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/block/BlockRenderer.scala index f198424d5..1181198aa 100644 --- a/src/main/scala/li/cil/oc/client/renderer/block/BlockRenderer.scala +++ b/src/main/scala/li/cil/oc/client/renderer/block/BlockRenderer.scala @@ -3,7 +3,6 @@ package li.cil.oc.client.renderer.block import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler import cpw.mods.fml.common.Loader import li.cil.oc.Settings -import li.cil.oc.client.Textures import li.cil.oc.client.renderer.tileentity.RobotRenderer import li.cil.oc.common.block._ import li.cil.oc.common.tileentity @@ -91,85 +90,19 @@ object BlockRenderer extends ISimpleBlockRenderingHandler { true case keyboard: tileentity.Keyboard => - if (keyboard.facing == ForgeDirection.UP || keyboard.facing == ForgeDirection.DOWN) { - keyboard.yaw match { - case ForgeDirection.NORTH => - renderer.uvRotateTop = 0 - renderer.uvRotateBottom = 0 - case ForgeDirection.SOUTH => - renderer.uvRotateTop = 3 - renderer.uvRotateBottom = 3 - case ForgeDirection.WEST => - renderer.uvRotateTop = 2 - renderer.uvRotateBottom = 1 - case ForgeDirection.EAST => - renderer.uvRotateTop = 1 - renderer.uvRotateBottom = 2 - case _ => throw new AssertionError("Impossible yaw value on keyboard.") - } - if (keyboard.facing == ForgeDirection.DOWN) { - renderer.flipTexture = true - } - } - val result = renderer.renderStandardBlock(block, x, y, z) - renderer.uvRotateTop = 0 - renderer.uvRotateBottom = 0 - renderer.flipTexture = false + val result = Keyboard.render(keyboard, x, y, z, block, renderer) RenderState.checkError(getClass.getName + ".renderWorldBlock: keyboard") result + case print: tileentity.Print => + Print.render(print, x, y, z, block, renderer) + + RenderState.checkError(getClass.getName + ".renderWorldBlock: print") + + true case rack: tileentity.ServerRack => - val previousRenderAllFaces = renderer.renderAllFaces - val u1 = 1 / 16f - val u2 = 15 / 16f - val v1 = 2 / 16f - val v2 = 14 / 16f - val fs = 3 / 16f - - // Top and bottom. - renderer.renderAllFaces = true - renderer.setRenderBounds(0, 0, 0, 1, v1, 1) - renderer.renderStandardBlock(block, x, y, z) - renderer.setRenderBounds(0, v2, 0, 1, 1, 1) - renderer.renderStandardBlock(block, x, y, z) - - // Sides. - val front = rack.facing - def renderSide(side: ForgeDirection, lx: Double, lz: Double, hx: Double, hz: Double) { - if (side == front) { - for (i <- 0 until 4 if rack.isPresent(i).isDefined) { - side match { - case ForgeDirection.WEST => - renderer.setRenderBounds(lx, v2 - (i + 1) * fs, lz + u1, u2, v2 - i * fs, hz - u1) - case ForgeDirection.EAST => - renderer.setRenderBounds(u1, v2 - (i + 1) * fs, lz + u1, hx, v2 - i * fs, hz - u1) - case ForgeDirection.NORTH => - renderer.setRenderBounds(lx + u1, v2 - (i + 1) * fs, lz, hx - u1, v2 - i * fs, u2) - case ForgeDirection.SOUTH => - renderer.setRenderBounds(lx + u1, v2 - (i + 1) * fs, u1, hx - u1, v2 - i * fs, hz) - case _ => - } - renderer.renderStandardBlock(block, x, y, z) - } - } - else { - val isBack = front == side.getOpposite - if (isBack) { - renderer.setOverrideBlockTexture(Textures.ServerRack.icons(ForgeDirection.NORTH.ordinal)) - } - renderer.setRenderBounds(lx, v1, lz, hx, v2, hz) - renderer.renderStandardBlock(block, x, y, z) - renderer.clearOverrideBlockTexture() - } - } - - renderSide(ForgeDirection.WEST, 0, 0, u1, 1) - renderSide(ForgeDirection.EAST, u2, 0, 1, 1) - renderSide(ForgeDirection.NORTH, 0, 0, 1, u1) - renderSide(ForgeDirection.SOUTH, 0, u2, 1, 1) - - renderer.renderAllFaces = previousRenderAllFaces + ServerRack.render(rack, x, y, z, block, renderer) RenderState.checkError(getClass.getName + ".renderWorldBlock: rack") diff --git a/src/main/scala/li/cil/oc/client/renderer/block/Keyboard.scala b/src/main/scala/li/cil/oc/client/renderer/block/Keyboard.scala new file mode 100644 index 000000000..3fb92ff5d --- /dev/null +++ b/src/main/scala/li/cil/oc/client/renderer/block/Keyboard.scala @@ -0,0 +1,36 @@ +package li.cil.oc.client.renderer.block + +import li.cil.oc.common.tileentity +import net.minecraft.block.Block +import net.minecraft.client.renderer.RenderBlocks +import net.minecraftforge.common.util.ForgeDirection + +object Keyboard { + def render(keyboard: tileentity.Keyboard, x: Int, y: Int, z: Int, block: Block, renderer: RenderBlocks): Boolean = { + if (keyboard.facing == ForgeDirection.UP || keyboard.facing == ForgeDirection.DOWN) { + keyboard.yaw match { + case ForgeDirection.NORTH => + renderer.uvRotateTop = 0 + renderer.uvRotateBottom = 0 + case ForgeDirection.SOUTH => + renderer.uvRotateTop = 3 + renderer.uvRotateBottom = 3 + case ForgeDirection.WEST => + renderer.uvRotateTop = 2 + renderer.uvRotateBottom = 1 + case ForgeDirection.EAST => + renderer.uvRotateTop = 1 + renderer.uvRotateBottom = 2 + case _ => throw new AssertionError("Impossible yaw value on keyboard.") + } + if (keyboard.facing == ForgeDirection.DOWN) { + renderer.flipTexture = true + } + } + val result = renderer.renderStandardBlock(block, x, y, z) + renderer.uvRotateTop = 0 + renderer.uvRotateBottom = 0 + renderer.flipTexture = false + result + } +} diff --git a/src/main/scala/li/cil/oc/client/renderer/block/Print.scala b/src/main/scala/li/cil/oc/client/renderer/block/Print.scala new file mode 100644 index 000000000..f4bf03c60 --- /dev/null +++ b/src/main/scala/li/cil/oc/client/renderer/block/Print.scala @@ -0,0 +1,24 @@ +package li.cil.oc.client.renderer.block + +import li.cil.oc.common.tileentity +import net.minecraft.block.Block +import net.minecraft.client.Minecraft +import net.minecraft.client.renderer.RenderBlocks +import net.minecraft.util.IIcon + +object Print { + def render(print: tileentity.Print, x: Int, y: Int, z: Int, block: Block, renderer: RenderBlocks): Unit = { + for (shape <- print.data.stateOff) { + renderer.setOverrideBlockTexture(resolveTexture(shape.texture)) + renderer.setRenderBounds( + shape.bounds.minX, shape.bounds.minY, shape.bounds.minZ, + shape.bounds.maxX, shape.bounds.maxY, shape.bounds.maxZ) + renderer.renderStandardBlock(block, x, y, z) + } + renderer.clearOverrideBlockTexture() + } + + private def resolveTexture(name: String): IIcon = + Option(Minecraft.getMinecraft.getTextureMapBlocks.getTextureExtry(name)). + getOrElse(Minecraft.getMinecraft.getTextureMapBlocks.getTextureExtry("wool_colored_magenta")) +} diff --git a/src/main/scala/li/cil/oc/client/renderer/block/ServerRack.scala b/src/main/scala/li/cil/oc/client/renderer/block/ServerRack.scala new file mode 100644 index 000000000..fdf3fba32 --- /dev/null +++ b/src/main/scala/li/cil/oc/client/renderer/block/ServerRack.scala @@ -0,0 +1,62 @@ +package li.cil.oc.client.renderer.block + +import li.cil.oc.client.Textures +import li.cil.oc.common.tileentity +import net.minecraft.block.Block +import net.minecraft.client.renderer.RenderBlocks +import net.minecraftforge.common.util.ForgeDirection + +object ServerRack { + def render(rack: tileentity.ServerRack, x: Int, y: Int, z: Int, block: Block, renderer: RenderBlocks): Unit = { + val previousRenderAllFaces = renderer.renderAllFaces + val u1 = 1 / 16f + val u2 = 15 / 16f + val v1 = 2 / 16f + val v2 = 14 / 16f + val fs = 3 / 16f + + // Top and bottom. + renderer.renderAllFaces = true + renderer.setRenderBounds(0, 0, 0, 1, v1, 1) + renderer.renderStandardBlock(block, x, y, z) + renderer.setRenderBounds(0, v2, 0, 1, 1, 1) + renderer.renderStandardBlock(block, x, y, z) + + // Sides. + val front = rack.facing + def renderSide(side: ForgeDirection, lx: Double, lz: Double, hx: Double, hz: Double) { + if (side == front) { + for (i <- 0 until 4 if rack.isPresent(i).isDefined) { + side match { + case ForgeDirection.WEST => + renderer.setRenderBounds(lx, v2 - (i + 1) * fs, lz + u1, u2, v2 - i * fs, hz - u1) + case ForgeDirection.EAST => + renderer.setRenderBounds(u1, v2 - (i + 1) * fs, lz + u1, hx, v2 - i * fs, hz - u1) + case ForgeDirection.NORTH => + renderer.setRenderBounds(lx + u1, v2 - (i + 1) * fs, lz, hx - u1, v2 - i * fs, u2) + case ForgeDirection.SOUTH => + renderer.setRenderBounds(lx + u1, v2 - (i + 1) * fs, u1, hx - u1, v2 - i * fs, hz) + case _ => + } + renderer.renderStandardBlock(block, x, y, z) + } + } + else { + val isBack = front == side.getOpposite + if (isBack) { + renderer.setOverrideBlockTexture(Textures.ServerRack.icons(ForgeDirection.NORTH.ordinal)) + } + renderer.setRenderBounds(lx, v1, lz, hx, v2, hz) + renderer.renderStandardBlock(block, x, y, z) + renderer.clearOverrideBlockTexture() + } + } + + renderSide(ForgeDirection.WEST, 0, 0, u1, 1) + renderSide(ForgeDirection.EAST, u2, 0, 1, 1) + renderSide(ForgeDirection.NORTH, 0, 0, 1, u1) + renderSide(ForgeDirection.SOUTH, 0, u2, 1, 1) + + renderer.renderAllFaces = previousRenderAllFaces + } +} diff --git a/src/main/scala/li/cil/oc/common/block/Print.scala b/src/main/scala/li/cil/oc/common/block/Print.scala new file mode 100644 index 000000000..ffde03aa7 --- /dev/null +++ b/src/main/scala/li/cil/oc/common/block/Print.scala @@ -0,0 +1,61 @@ +package li.cil.oc.common.block + +import li.cil.oc.Settings +import li.cil.oc.common.tileentity +import net.minecraft.entity.EntityLivingBase +import net.minecraft.entity.player.EntityPlayer +import net.minecraft.item.ItemStack +import net.minecraft.util.MovingObjectPosition +import net.minecraft.world.IBlockAccess +import net.minecraft.world.World +import net.minecraftforge.common.util.ForgeDirection + +import scala.reflect.ClassTag + +class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends SimpleBlock with traits.SpecialBlock with traits.CustomDrops[tileentity.Print] { + setLightOpacity(0) + // setCreativeTab(null) + // NEI.hide(this) + setBlockTextureName(Settings.resourceDomain + "GenericTop") + + override def shouldSideBeRendered(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = true + + override def isBlockSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = true + + override def isSideSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = false + + override def getPickBlock(target: MovingObjectPosition, world: World, x: Int, y: Int, z: Int, player: EntityPlayer): ItemStack = { + world.getTileEntity(x, y, z) match { + case print: tileentity.Print => print.data.createItemStack() + case _ => null + } + } + + override protected def doSetBlockBoundsBasedOnState(world: IBlockAccess, x: Int, y: Int, z: Int): Unit = { + world.getTileEntity(x, y, z) match { + case print: tileentity.Print => setBlockBounds(if (print.state) print.boundsOn else print.boundsOff) + case _ => super.doSetBlockBoundsBasedOnState(world, x, y, z) + } + } + + // ----------------------------------------------------------------------- // + + override def hasTileEntity(metadata: Int) = true + + override def createTileEntity(world: World, metadata: Int) = new tileentity.Print() + + // ----------------------------------------------------------------------- // + + override protected def doCustomInit(tileEntity: tileentity.Print, player: EntityLivingBase, stack: ItemStack): Unit = { + super.doCustomInit(tileEntity, player, stack) + tileEntity.data.load(stack) + tileEntity.updateBounds() + } + + override protected def doCustomDrops(tileEntity: tileentity.Print, player: EntityPlayer, willHarvest: Boolean): Unit = { + super.doCustomDrops(tileEntity, player, willHarvest) + if (!player.capabilities.isCreativeMode) { + dropBlockAsItem(tileEntity.world, tileEntity.x, tileEntity.y, tileEntity.z, tileEntity.data.createItemStack()) + } + } +} diff --git a/src/main/scala/li/cil/oc/common/init/Blocks.scala b/src/main/scala/li/cil/oc/common/init/Blocks.scala index c28554da4..40576f02a 100644 --- a/src/main/scala/li/cil/oc/common/init/Blocks.scala +++ b/src/main/scala/li/cil/oc/common/init/Blocks.scala @@ -25,6 +25,7 @@ object Blocks { GameRegistry.registerTileEntity(classOf[tileentity.MotionSensor], Settings.namespace + "motion_sensor") GameRegistry.registerTileEntity(classOf[tileentity.PowerConverter], Settings.namespace + "power_converter") GameRegistry.registerTileEntity(classOf[tileentity.PowerDistributor], Settings.namespace + "power_distributor") + GameRegistry.registerTileEntity(classOf[tileentity.Print], Settings.namespace + "print") GameRegistry.registerTileEntity(classOf[tileentity.Raid], Settings.namespace + "raid") GameRegistry.registerTileEntity(classOf[tileentity.Redstone], Settings.namespace + "redstone") GameRegistry.registerTileEntity(classOf[tileentity.RobotProxy], Settings.namespace + "robot") @@ -81,5 +82,8 @@ object Blocks { // v1.4.2 Recipes.addBlock(new Raid(), "raid", "oc:raid") Items.registerBlock(new Microcontroller(), "microcontroller") + + // v1.5.4 + Items.registerBlock(new Print(), "print") } } diff --git a/src/main/scala/li/cil/oc/common/item/data/PrintData.scala b/src/main/scala/li/cil/oc/common/item/data/PrintData.scala new file mode 100644 index 000000000..b9eefd4f9 --- /dev/null +++ b/src/main/scala/li/cil/oc/common/item/data/PrintData.scala @@ -0,0 +1,79 @@ +package li.cil.oc.common.item.data + +import li.cil.oc.api +import li.cil.oc.util.ExtendedNBT._ +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.util.AxisAlignedBB +import net.minecraftforge.common.util.Constants.NBT + +import scala.collection.mutable + +class PrintData extends ItemData { + def this(stack: ItemStack) { + this() + load(stack) + } + + var label: Option[String] = None + var tooltip: Option[String] = None + var autoRevert = false + var emitRedstone = false + var pressurePlate = false + val stateOff = mutable.Set.empty[PrintData.Shape] + val stateOn = mutable.Set.empty[PrintData.Shape] + + override def load(nbt: NBTTagCompound): Unit = { + if (nbt.hasKey("label")) label = Option(nbt.getString("label")) + if (nbt.hasKey("tooltip")) tooltip = Option(nbt.getString("tooltip")) + autoRevert = nbt.getBoolean("autoRevert") + emitRedstone = nbt.getBoolean("emitRedstone") + pressurePlate = nbt.getBoolean("pressurePlate") + stateOff ++= nbt.getTagList("stateOff", NBT.TAG_COMPOUND).map(PrintData.nbtToShape) + stateOn ++= nbt.getTagList("stateOn", NBT.TAG_COMPOUND).map(PrintData.nbtToShape) + } + + override def save(nbt: NBTTagCompound): Unit = { + label.foreach(nbt.setString("label", _)) + tooltip.foreach(nbt.setString("tooltip", _)) + nbt.setBoolean("autoRevert", autoRevert) + nbt.setBoolean("emitRedstone", emitRedstone) + nbt.setBoolean("pressurePlate", pressurePlate) + nbt.setNewTagList("stateOff", stateOff.map(PrintData.shapeToNBT)) + nbt.setNewTagList("stateOn", stateOn.map(PrintData.shapeToNBT)) + } + + def createItemStack() = { + val stack = api.Items.get("print").createItemStack(1) + save(stack) + stack + } +} + +object PrintData { + def nbtToShape(nbt: NBTTagCompound): Shape = { + val minX = nbt.getByte("minX") / 16f + val minY = nbt.getByte("minY") / 16f + val minZ = nbt.getByte("minZ") / 16f + val maxX = nbt.getByte("maxX") / 16f + val maxY = nbt.getByte("maxY") / 16f + val maxZ = nbt.getByte("maxZ") / 16f + val texture = nbt.getString("texture") + new Shape(AxisAlignedBB.getBoundingBox(minX, minY, minZ, maxX, maxY, maxZ), texture) + } + + def shapeToNBT(shape: Shape): NBTTagCompound = { + val nbt = new NBTTagCompound() + nbt.setByte("minX", (shape.bounds.minX * 16).round.toByte) + nbt.setByte("minY", (shape.bounds.minY * 16).round.toByte) + nbt.setByte("minZ", (shape.bounds.minZ * 16).round.toByte) + nbt.setByte("maxX", (shape.bounds.maxX * 16).round.toByte) + nbt.setByte("maxY", (shape.bounds.maxY * 16).round.toByte) + nbt.setByte("maxZ", (shape.bounds.maxZ * 16).round.toByte) + nbt.setString("texture", shape.texture) + nbt + } + + class Shape(val bounds: AxisAlignedBB, val texture: String) + +} \ No newline at end of file diff --git a/src/main/scala/li/cil/oc/common/tileentity/Print.scala b/src/main/scala/li/cil/oc/common/tileentity/Print.scala new file mode 100644 index 000000000..ad0e30924 --- /dev/null +++ b/src/main/scala/li/cil/oc/common/tileentity/Print.scala @@ -0,0 +1,48 @@ +package li.cil.oc.common.tileentity + +import cpw.mods.fml.relauncher.Side +import cpw.mods.fml.relauncher.SideOnly +import li.cil.oc.common.item.data.PrintData +import li.cil.oc.util.ExtendedNBT._ +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.util.AxisAlignedBB + +class Print extends traits.TileEntity { + val data = new PrintData() + + var boundsOff = unitBounds + var boundsOn = unitBounds + var state = false + + override def canUpdate: Boolean = false + + override def readFromNBTForServer(nbt: NBTTagCompound): Unit = { + super.readFromNBTForServer(nbt) + data.load(nbt.getCompoundTag("data")) + updateBounds() + } + + override def writeToNBTForServer(nbt: NBTTagCompound): Unit = { + super.writeToNBTForServer(nbt) + nbt.setNewCompoundTag("data", data.save) + } + + @SideOnly(Side.CLIENT) + override def readFromNBTForClient(nbt: NBTTagCompound): Unit = { + super.readFromNBTForClient(nbt) + data.load(nbt.getCompoundTag("data")) + updateBounds() + } + + override def writeToNBTForClient(nbt: NBTTagCompound): Unit = { + super.writeToNBTForClient(nbt) + nbt.setNewCompoundTag("data", data.save) + } + + def updateBounds(): Unit = { + boundsOff = data.stateOff.drop(1).foldLeft(data.stateOff.headOption.fold(unitBounds)(_.bounds))((a, b) => a.func_111270_a(b.bounds)) + boundsOn = data.stateOn.drop(1).foldLeft(data.stateOn.headOption.fold(unitBounds)(_.bounds))((a, b) => a.func_111270_a(b.bounds)) + } + + private def unitBounds = AxisAlignedBB.getBoundingBox(0, 0, 0, 1, 1, 1) +} From 1d7b6caa6f7c4b4cc76235019e99d15cd46e8ebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Mon, 23 Mar 2015 17:58:41 +0100 Subject: [PATCH 03/17] Printer block to allow printing 3d prints. --- src/main/resources/application.conf | 11 + .../opencomputers/textures/gui/printer.png | Bin 0 -> 634 bytes .../textures/gui/printer_progress.png | Bin 0 -> 189 bytes src/main/scala/li/cil/oc/Settings.scala | 2 + .../scala/li/cil/oc/client/GuiHandler.scala | 2 + .../scala/li/cil/oc/client/Textures.scala | 2 + .../scala/li/cil/oc/client/gui/Printer.scala | 66 +++++ .../oc/client/gui/widget/ProgressBar.scala | 4 +- .../li/cil/oc/client/gui/widget/Widget.scala | 2 +- .../scala/li/cil/oc/common/GuiHandler.scala | 2 + src/main/scala/li/cil/oc/common/GuiType.scala | 1 + .../scala/li/cil/oc/common/block/Print.scala | 5 + .../li/cil/oc/common/block/Printer.scala | 42 +++ .../li/cil/oc/common/container/Printer.scala | 53 ++++ .../scala/li/cil/oc/common/init/Blocks.scala | 2 + .../li/cil/oc/common/tileentity/Print.scala | 15 +- .../li/cil/oc/common/tileentity/Printer.scala | 247 ++++++++++++++++++ .../scala/li/cil/oc/util/ExtendedAABB.scala | 28 ++ 18 files changed, 475 insertions(+), 9 deletions(-) create mode 100644 src/main/resources/assets/opencomputers/textures/gui/printer.png create mode 100644 src/main/resources/assets/opencomputers/textures/gui/printer_progress.png create mode 100644 src/main/scala/li/cil/oc/client/gui/Printer.scala create mode 100644 src/main/scala/li/cil/oc/common/block/Printer.scala create mode 100644 src/main/scala/li/cil/oc/common/container/Printer.scala create mode 100644 src/main/scala/li/cil/oc/common/tileentity/Printer.scala create mode 100644 src/main/scala/li/cil/oc/util/ExtendedAABB.scala diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index be996ee43..f68159751 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -729,6 +729,11 @@ opencomputers { # Energy it costs to re-program an EEPROM. This is deliberately # expensive, to discourage frequent re-writing of EEPROMs. eepromWrite: 50 + + # How much energy is required per shape in a 3D print. With the + # default of 200 for example, it will take 1600 energy to print a + # block with 8 shapes in it. + printerShape: 200 } # The rate at which different blocks accept external power. All of these @@ -1011,6 +1016,12 @@ opencomputers { # format 'itemid@damage', were the damage is optional. # Examples: 'OpenComputers:case3', 'minecraft:stonebrick@1' assemblerBlacklist: [] + + # The maximum number of shape for a single 3D print allowed. This is for + # the sum of shapes in both states (off and on), so e.g. with the default + # of 32 you can use 10 shapes for the off state and 22 for the on state + # at maximum. + maxPrinterShapes: 32 } # Settings for mod integration (the mod previously known as OpenComponents). diff --git a/src/main/resources/assets/opencomputers/textures/gui/printer.png b/src/main/resources/assets/opencomputers/textures/gui/printer.png new file mode 100644 index 0000000000000000000000000000000000000000..f7e756e2385d55f3ac1bf83c653e5701fba418e0 GIT binary patch literal 634 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5FjO4;u=vBoS#-wo>-L1;Fyx1 zl&avFo0y&&l$w}QS$Hzl2B=6hz$e5tG&I!Q+`PNH8z}Jq|NmphjsZ#CGoRdneD;zc zzhEF22pFWincaZ4yzq2!45_&F=CPx&0m>Id zc<={YX1a}OsEWSFdUW+6HVZLLt=yzSSZIR$6 zRtz~Q#oh_J7@`+AVi`W%QD9)0Cv%l+Hy^tEmP1jAbAhtibN{n6+`D(2cQPl#-c-B) r<_`IVmzFau!O(zi0Ofp#8Gkqo7_^L@x}|9Pg1zPG>gTe~DWM4fD)Fht literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/opencomputers/textures/gui/printer_progress.png b/src/main/resources/assets/opencomputers/textures/gui/printer_progress.png new file mode 100644 index 0000000000000000000000000000000000000000..a4df8cc55389ac613e13cdd7393f4d2dfe382310 GIT binary patch literal 189 zcmeAS@N?(olHy`uVBq!ia0vp^dLYcf3?viMZ?gg^$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1GYymzYuK&RxwB~CLP=u)@$S?Rm!_(~sUO=9`r;B4q#jT_S z6;6X5lczix4ZBWVJmNOBU+Z|lIfq3>Y(i6wAB6U?1_WAm_AR`yda-9t$WMo9?-zg7 d;$UErU=Z|XpZ new gui.DiskDrive(player.inventory, t) + case t: tileentity.Printer if id == GuiType.Printer.id => + new gui.Printer(player.inventory, t) case t: tileentity.Raid if id == GuiType.Raid.id => new gui.Raid(player.inventory, t) case t: tileentity.RobotProxy if id == GuiType.Robot.id => diff --git a/src/main/scala/li/cil/oc/client/Textures.scala b/src/main/scala/li/cil/oc/client/Textures.scala index 324cab790..4d02efe8f 100644 --- a/src/main/scala/li/cil/oc/client/Textures.scala +++ b/src/main/scala/li/cil/oc/client/Textures.scala @@ -25,6 +25,8 @@ object Textures { val guiDisassembler = new ResourceLocation(Settings.resourceDomain, "textures/gui/disassembler.png") val guiDrone = new ResourceLocation(Settings.resourceDomain, "textures/gui/drone.png") val guiKeyboardMissing = new ResourceLocation(Settings.resourceDomain, "textures/gui/keyboard_missing.png") + val guiPrinter = new ResourceLocation(Settings.resourceDomain, "textures/gui/printer.png") + val guiPrinterProgress = new ResourceLocation(Settings.resourceDomain, "textures/gui/printer_progress.png") val guiRaid = new ResourceLocation(Settings.resourceDomain, "textures/gui/raid.png") val guiRange = new ResourceLocation(Settings.resourceDomain, "textures/gui/range.png") val guiRobot = new ResourceLocation(Settings.resourceDomain, "textures/gui/robot.png") diff --git a/src/main/scala/li/cil/oc/client/gui/Printer.scala b/src/main/scala/li/cil/oc/client/gui/Printer.scala new file mode 100644 index 000000000..3ad735a26 --- /dev/null +++ b/src/main/scala/li/cil/oc/client/gui/Printer.scala @@ -0,0 +1,66 @@ +package li.cil.oc.client.gui + +import li.cil.oc.Localization +import li.cil.oc.client.Textures +import li.cil.oc.client.gui.widget.ProgressBar +import li.cil.oc.client.{PacketSender => ClientPacketSender} +import li.cil.oc.common.container +import li.cil.oc.common.container.ComponentSlot +import li.cil.oc.common.tileentity +import net.minecraft.entity.player.InventoryPlayer +import net.minecraft.util.ResourceLocation +import org.lwjgl.opengl.GL11 + +class Printer(playerInventory: InventoryPlayer, val printer: tileentity.Printer) extends DynamicGuiContainer(new container.Printer(playerInventory, printer)) { + xSize = 176 + ySize = 166 + + private val progress = addWidget(new ProgressBar(104, 21) { + override def width = 46 + + override def height = 46 + + override def barTexture = Textures.guiPrinterProgress + }) + + private def assemblerContainer = inventorySlots.asInstanceOf[container.Printer] + + override def initGui() { + super.initGui() + } + + override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = { + super.drawSecondaryForegroundLayer(mouseX, mouseY) + fontRendererObj.drawString( + Localization.localizeImmediately(printer.getInventoryName), + 8, 6, 0x404040) + GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS) // Me lazy... prevents NEI render glitch. + if (assemblerContainer.isAssembling && func_146978_c(progress.x, progress.y, progress.width, progress.height, mouseX, mouseY)) { + val tooltip = new java.util.ArrayList[String] + val timeRemaining = formatTime(assemblerContainer.assemblyRemainingTime) + tooltip.add(Localization.Assembler.Progress(assemblerContainer.assemblyProgress, timeRemaining)) + copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRendererObj) + } + GL11.glPopAttrib() + } + + private def formatTime(seconds: Int) = { + // Assembly times should not / rarely exceed one hour, so this is good enough. + if (seconds < 60) f"0:$seconds%02d" + else f"${seconds / 60}:${seconds % 60}%02d" + } + + override def drawGuiContainerBackgroundLayer(dt: Float, mouseX: Int, mouseY: Int) { + GL11.glColor3f(1, 1, 1) // Required under Linux. + mc.renderEngine.bindTexture(Textures.guiPrinter) + drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize) + if (assemblerContainer.isAssembling) progress.level = assemblerContainer.assemblyProgress / 100.0 + else progress.level = 0 + drawWidgets() + drawInventorySlots() + } + + override protected def drawDisabledSlot(slot: ComponentSlot) {} + + override def doesGuiPauseGame = false +} \ No newline at end of file diff --git a/src/main/scala/li/cil/oc/client/gui/widget/ProgressBar.scala b/src/main/scala/li/cil/oc/client/gui/widget/ProgressBar.scala index 7f9beb31e..22541fbe5 100644 --- a/src/main/scala/li/cil/oc/client/gui/widget/ProgressBar.scala +++ b/src/main/scala/li/cil/oc/client/gui/widget/ProgressBar.scala @@ -9,6 +9,8 @@ class ProgressBar(val x: Int, val y: Int) extends Widget { override def height = 12 + def barTexture = Textures.guiBar + var level = 0.0 def draw() { @@ -21,7 +23,7 @@ class ProgressBar(val x: Int, val y: Int) extends Widget { val ty = owner.windowY + y val w = width * level - Minecraft.getMinecraft.renderEngine.bindTexture(Textures.guiBar) + Minecraft.getMinecraft.renderEngine.bindTexture(barTexture) val t = Tessellator.instance t.startDrawingQuads() t.addVertexWithUV(tx, ty, owner.windowZ, u0, v0) diff --git a/src/main/scala/li/cil/oc/client/gui/widget/Widget.scala b/src/main/scala/li/cil/oc/client/gui/widget/Widget.scala index c97facd41..db1552137 100644 --- a/src/main/scala/li/cil/oc/client/gui/widget/Widget.scala +++ b/src/main/scala/li/cil/oc/client/gui/widget/Widget.scala @@ -11,5 +11,5 @@ abstract class Widget { def height: Int - def draw() + def draw(): Unit } diff --git a/src/main/scala/li/cil/oc/common/GuiHandler.scala b/src/main/scala/li/cil/oc/common/GuiHandler.scala index 366963ebc..b6a42bfee 100644 --- a/src/main/scala/li/cil/oc/common/GuiHandler.scala +++ b/src/main/scala/li/cil/oc/common/GuiHandler.scala @@ -24,6 +24,8 @@ abstract class GuiHandler extends IGuiHandler { new container.Disassembler(player.inventory, t) case t: tileentity.DiskDrive if id == GuiType.DiskDrive.id => new container.DiskDrive(player.inventory, t) + case t: tileentity.Printer if id == GuiType.Printer.id => + new container.Printer(player.inventory, t) case t: tileentity.Raid if id == GuiType.Raid.id => new container.Raid(player.inventory, t) case t: tileentity.RobotProxy if id == GuiType.Robot.id => diff --git a/src/main/scala/li/cil/oc/common/GuiType.scala b/src/main/scala/li/cil/oc/common/GuiType.scala index 7628f8178..17927f40b 100644 --- a/src/main/scala/li/cil/oc/common/GuiType.scala +++ b/src/main/scala/li/cil/oc/common/GuiType.scala @@ -21,6 +21,7 @@ object GuiType extends ScalaEnum { val Disassembler = new EnumVal { def name = "Disassembler"; def subType = GuiType.Category.Block } val DiskDrive = new EnumVal { def name = "DiskDrive"; def subType = GuiType.Category.Block } val Drone = new EnumVal { def name = "Drone"; def subType = GuiType.Category.Entity } + val Printer = new EnumVal { def name = "Printer"; def subType = GuiType.Category.Block } val Rack = new EnumVal { def name = "Rack"; def subType = GuiType.Category.Block } val Raid = new EnumVal { def name = "Raid"; def subType = GuiType.Category.Block } val Robot = new EnumVal { def name = "Robot"; def subType = GuiType.Category.Block } diff --git a/src/main/scala/li/cil/oc/common/block/Print.scala b/src/main/scala/li/cil/oc/common/block/Print.scala index ffde03aa7..f28a8540f 100644 --- a/src/main/scala/li/cil/oc/common/block/Print.scala +++ b/src/main/scala/li/cil/oc/common/block/Print.scala @@ -2,6 +2,7 @@ package li.cil.oc.common.block import li.cil.oc.Settings import li.cil.oc.common.tileentity +import li.cil.oc.util.ExtendedAABB import net.minecraft.entity.EntityLivingBase import net.minecraft.entity.player.EntityPlayer import net.minecraft.item.ItemStack @@ -38,6 +39,10 @@ class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends } } + override def setBlockBoundsForItemRender(metadata: Int): Unit = { + setBlockBounds(ExtendedAABB.unitBounds) + } + // ----------------------------------------------------------------------- // override def hasTileEntity(metadata: Int) = true diff --git a/src/main/scala/li/cil/oc/common/block/Printer.scala b/src/main/scala/li/cil/oc/common/block/Printer.scala new file mode 100644 index 000000000..d0be27b26 --- /dev/null +++ b/src/main/scala/li/cil/oc/common/block/Printer.scala @@ -0,0 +1,42 @@ +package li.cil.oc.common.block + +import li.cil.oc.Settings +import li.cil.oc.client.Textures +import li.cil.oc.common.GuiType +import li.cil.oc.common.tileentity +import net.minecraft.client.renderer.texture.IIconRegister +import net.minecraft.world.IBlockAccess +import net.minecraft.world.World +import net.minecraftforge.common.util.ForgeDirection + +class Printer extends SimpleBlock with traits.SpecialBlock with traits.PowerAcceptor with traits.StateAware with traits.GUI { + override protected def customTextures = Array( + None, + Some("AssemblerTop"), + Some("AssemblerSide"), + Some("AssemblerSide"), + Some("AssemblerSide"), + Some("AssemblerSide") + ) + + override def registerBlockIcons(iconRegister: IIconRegister) = { + super.registerBlockIcons(iconRegister) + Textures.Assembler.iconSideAssembling = iconRegister.registerIcon(Settings.resourceDomain + ":AssemblerSideAssembling") + Textures.Assembler.iconSideOn = iconRegister.registerIcon(Settings.resourceDomain + ":AssemblerSideOn") + Textures.Assembler.iconTopOn = iconRegister.registerIcon(Settings.resourceDomain + ":AssemblerTopOn") + } + + override def isBlockSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = side == ForgeDirection.DOWN + + override def isSideSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = side == ForgeDirection.DOWN + + // ----------------------------------------------------------------------- // + + override def energyThroughput = Settings.get.assemblerRate + + override def guiType = GuiType.Printer + + override def hasTileEntity(metadata: Int) = true + + override def createTileEntity(world: World, metadata: Int) = new tileentity.Printer() +} diff --git a/src/main/scala/li/cil/oc/common/container/Printer.scala b/src/main/scala/li/cil/oc/common/container/Printer.scala new file mode 100644 index 000000000..c50c50acf --- /dev/null +++ b/src/main/scala/li/cil/oc/common/container/Printer.scala @@ -0,0 +1,53 @@ +package li.cil.oc.common.container + +import cpw.mods.fml.relauncher.Side +import cpw.mods.fml.relauncher.SideOnly +import li.cil.oc.common.tileentity +import li.cil.oc.util.SideTracker +import net.minecraft.entity.player.InventoryPlayer + +class Printer(playerInventory: InventoryPlayer, val printer: tileentity.Printer) extends Player(playerInventory, printer) { + addSlotToContainer(18, 19) + addSlotToContainer(18, 51) + addSlotToContainer(152, 35) + + // Show the player's inventory. + addPlayerInventorySlots(8, 84) + + var isAssembling = false + var assemblyProgress = 0.0 + var assemblyRemainingTime = 0 + + @SideOnly(Side.CLIENT) + override def updateProgressBar(id: Int, value: Int) { + super.updateProgressBar(id, value) + if (id == 0) { + isAssembling = value == 1 + } + + if (id == 1) { + assemblyProgress = value / 5.0 + } + + if (id == 2) { + assemblyRemainingTime = value + } + } + + override def detectAndSendChanges() { + super.detectAndSendChanges() + if (SideTracker.isServer) { + if (isAssembling != printer.isAssembling) { + isAssembling = printer.isAssembling + sendProgressBarUpdate(0, if (isAssembling) 1 else 0) + } + val timeRemaining = printer.timeRemaining + if (math.abs(printer.progress - assemblyProgress) > 0.2 || assemblyRemainingTime != timeRemaining) { + assemblyProgress = printer.progress + assemblyRemainingTime = timeRemaining + sendProgressBarUpdate(1, (assemblyProgress * 5).toInt) + sendProgressBarUpdate(2, timeRemaining) + } + } + } +} \ No newline at end of file diff --git a/src/main/scala/li/cil/oc/common/init/Blocks.scala b/src/main/scala/li/cil/oc/common/init/Blocks.scala index 40576f02a..396fc42b9 100644 --- a/src/main/scala/li/cil/oc/common/init/Blocks.scala +++ b/src/main/scala/li/cil/oc/common/init/Blocks.scala @@ -26,6 +26,7 @@ object Blocks { GameRegistry.registerTileEntity(classOf[tileentity.PowerConverter], Settings.namespace + "power_converter") GameRegistry.registerTileEntity(classOf[tileentity.PowerDistributor], Settings.namespace + "power_distributor") GameRegistry.registerTileEntity(classOf[tileentity.Print], Settings.namespace + "print") + GameRegistry.registerTileEntity(classOf[tileentity.Printer], Settings.namespace + "printer") GameRegistry.registerTileEntity(classOf[tileentity.Raid], Settings.namespace + "raid") GameRegistry.registerTileEntity(classOf[tileentity.Redstone], Settings.namespace + "redstone") GameRegistry.registerTileEntity(classOf[tileentity.RobotProxy], Settings.namespace + "robot") @@ -85,5 +86,6 @@ object Blocks { // v1.5.4 Items.registerBlock(new Print(), "print") + Items.registerBlock(new Printer(), "printer") } } diff --git a/src/main/scala/li/cil/oc/common/tileentity/Print.scala b/src/main/scala/li/cil/oc/common/tileentity/Print.scala index ad0e30924..7b1973f21 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Print.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Print.scala @@ -3,15 +3,16 @@ package li.cil.oc.common.tileentity import cpw.mods.fml.relauncher.Side import cpw.mods.fml.relauncher.SideOnly import li.cil.oc.common.item.data.PrintData +import li.cil.oc.util.ExtendedAABB +import li.cil.oc.util.ExtendedAABB._ import li.cil.oc.util.ExtendedNBT._ import net.minecraft.nbt.NBTTagCompound -import net.minecraft.util.AxisAlignedBB class Print extends traits.TileEntity { val data = new PrintData() - var boundsOff = unitBounds - var boundsOn = unitBounds + var boundsOff = ExtendedAABB.unitBounds + var boundsOn = ExtendedAABB.unitBounds var state = false override def canUpdate: Boolean = false @@ -40,9 +41,9 @@ class Print extends traits.TileEntity { } def updateBounds(): Unit = { - boundsOff = data.stateOff.drop(1).foldLeft(data.stateOff.headOption.fold(unitBounds)(_.bounds))((a, b) => a.func_111270_a(b.bounds)) - boundsOn = data.stateOn.drop(1).foldLeft(data.stateOn.headOption.fold(unitBounds)(_.bounds))((a, b) => a.func_111270_a(b.bounds)) + boundsOff = data.stateOff.drop(1).foldLeft(data.stateOff.headOption.fold(ExtendedAABB.unitBounds)(_.bounds))((a, b) => a.func_111270_a(b.bounds)) + if (boundsOff.volume == 0) boundsOff = ExtendedAABB.unitBounds + boundsOn = data.stateOn.drop(1).foldLeft(data.stateOn.headOption.fold(ExtendedAABB.unitBounds)(_.bounds))((a, b) => a.func_111270_a(b.bounds)) + if (boundsOn.volume == 0) boundsOn = ExtendedAABB.unitBounds } - - private def unitBounds = AxisAlignedBB.getBoundingBox(0, 0, 0, 1, 1, 1) } diff --git a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala new file mode 100644 index 000000000..00954516d --- /dev/null +++ b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala @@ -0,0 +1,247 @@ +package li.cil.oc.common.tileentity + +import java.util + +import cpw.mods.fml.relauncher.Side +import cpw.mods.fml.relauncher.SideOnly +import li.cil.oc.Settings +import li.cil.oc.api +import li.cil.oc.api.machine.Arguments +import li.cil.oc.api.machine.Callback +import li.cil.oc.api.machine.Context +import li.cil.oc.api.network._ +import li.cil.oc.common.item.data.PrintData +import li.cil.oc.util.ExtendedAABB._ +import li.cil.oc.util.ExtendedNBT._ +import li.cil.oc.util.ItemUtils +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.util.AxisAlignedBB +import net.minecraftforge.common.util.ForgeDirection + +class Printer extends traits.Environment with traits.PowerAcceptor with traits.Inventory with traits.Rotatable with SidedEnvironment with traits.StateAware { + val node = api.Network.newNode(this, Visibility.Network). + withComponent("printer3d"). + withConnector(Settings.get.bufferConverter). + create() + + var data = new PrintData() + var isActive = false + var output: Option[ItemStack] = None + var totalRequiredEnergy = 0.0 + var requiredEnergy = 0.0 + + val slotPlastic = 0 + val slotInk = 1 + val slotOutput = 2 + + // ----------------------------------------------------------------------- // + + @SideOnly(Side.CLIENT) + override def canConnect(side: ForgeDirection) = side != ForgeDirection.UP + + override def sidedNode(side: ForgeDirection) = if (side != ForgeDirection.UP) node else null + + @SideOnly(Side.CLIENT) + override protected def hasConnector(side: ForgeDirection) = canConnect(side) + + override protected def connector(side: ForgeDirection) = Option(if (side != ForgeDirection.UP) node else null) + + override protected def energyThroughput = Settings.get.assemblerRate + + override def currentState = { + if (isAssembling) util.EnumSet.of(traits.State.IsWorking) + else if (canAssemble) util.EnumSet.of(traits.State.CanWork) + else util.EnumSet.noneOf(classOf[traits.State]) + } + + // ----------------------------------------------------------------------- // + + def canAssemble = { + val complexity = data.stateOff.size + data.stateOn.size + complexity > 0 && complexity <= Settings.get.maxPrintComplexity + } + + def isAssembling = requiredEnergy > 0 + + def progress = (1 - requiredEnergy / totalRequiredEnergy) * 100 + + def timeRemaining = (requiredEnergy / Settings.get.assemblerTickAmount / 20).toInt + + // ----------------------------------------------------------------------- // + + @Callback(doc = """function() -- Resets the configuration of the printer and stop printing (current job will finish).""") + def reset(context: Context, args: Arguments): Array[Object] = { + data = new PrintData() + isActive = false // Needs committing. + null + } + + @Callback(doc = """function(value:string) -- Set a label for the block being printed.""") + def setLabel(context: Context, args: Arguments): Array[Object] = { + data.label = Option(args.optString(0, null)) + isActive = false // Needs committing. + null + } + + @Callback(doc = """function():string -- Get the current label for the block being printed.""") + def getLabel(context: Context, args: Arguments): Array[Object] = { + result(data.label.orNull) + } + + @Callback(doc = """function(value:string) -- Set a tooltip for the block being printed.""") + def setTooltip(context: Context, args: Arguments): Array[Object] = { + data.tooltip = Option(args.optString(0, null)) + isActive = false // Needs committing. + null + } + + @Callback(doc = """function():string -- Get the current tooltip for the block being printed.""") + def getTooltip(context: Context, args: Arguments): Array[Object] = { + result(data.tooltip.orNull) + } + + @Callback(doc = """function(minX:number, minY:number, minZ:number, maxX:number, maxY:number, maxZ:number, texture:string[, state:boolean=false]) -- Adds a shape to the printers configuration, optionally specifying whether it is for the off or on state.""") + def addShape(context: Context, args: Arguments): Array[Object] = { + if (data.stateOff.size + data.stateOn.size >= Settings.get.maxPrintComplexity) { + return result(null, "model too complex") + } + val minX = (args.checkInteger(0) max 0 min 16) / 16f + val minY = (args.checkInteger(1) max 0 min 16) / 16f + val minZ = (args.checkInteger(2) max 0 min 16) / 16f + val maxX = (args.checkInteger(3) max 0 min 16) / 16f + val maxY = (args.checkInteger(4) max 0 min 16) / 16f + val maxZ = (args.checkInteger(5) max 0 min 16) / 16f + val texture = args.checkString(6) + val state = args.optBoolean(7, false) + + if (minX == maxX) throw new IllegalArgumentException("empty block") + if (minY == maxY) throw new IllegalArgumentException("empty block") + if (minZ == maxZ) throw new IllegalArgumentException("empty block") + + val list = if (state) data.stateOn else data.stateOff + list += new PrintData.Shape(AxisAlignedBB.getBoundingBox( + math.min(minX, maxX), + math.min(minY, maxY), + math.min(minZ, maxZ), + math.max(maxX, minX), + math.max(maxY, minY), + math.max(maxZ, minZ)), texture) + isActive = false // Needs committing. + + result(true) + } + + @Callback(doc = """function():number -- Get the number of shapes in the current configuration.""") + def getShapeCount(context: Context, args: Arguments): Array[Object] = result(data.stateOff.size + data.stateOn.size) + + @Callback(doc = """function():number -- Get the maximum allowed number of shapes.""") + def getMaxShapeCount(context: Context, args: Arguments): Array[Object] = result(Settings.get.maxPrintComplexity) + + @Callback(doc = """function():boolean -- Commit and begin printing the current configuration.""") + def commit(context: Context, args: Arguments): Array[Object] = { + if (!canAssemble) { + return result(null, "model invalid") + } + isActive = true + result(true) + } + + @Callback(doc = """function(): string, number or boolean -- The current state of the printer, `busy' or `idle', followed by the progress or model validity, respectively.""") + def status(context: Context, args: Arguments): Array[Object] = { + if (isAssembling) result("busy", progress) + else if (canAssemble) result("idle", true) + else result("idle", false) + } + + // ----------------------------------------------------------------------- // + + override def canUpdate = isServer + + // ----------------------------------------------------------------------- // + + override def updateEntity() { + super.updateEntity() + + if (world.getTotalWorldTime % Settings.get.tickFrequency == 0) { + if (isActive && output.isEmpty) { + val totalVolume = data.stateOn.foldLeft(0)((acc, shape) => acc + shape.bounds.volume) + data.stateOff.foldLeft(0)((acc, shape) => acc + shape.bounds.volume) + val totalSurface = data.stateOn.foldLeft(0)((acc, shape) => acc + shape.bounds.surface) + data.stateOff.foldLeft(0)((acc, shape) => acc + shape.bounds.surface) + val totalShapes = data.stateOn.size + data.stateOff.size + // TODO Consume plastic (totalVolume) and ink (totalSurface). + totalRequiredEnergy = totalShapes * Settings.get.printShapeCost + requiredEnergy = totalRequiredEnergy + output = Option(data.createItemStack()) + // ServerPacketSender.sendRobotAssembling(this, assembling = true) + } + + if (output.isDefined) { + val want = math.max(1, math.min(requiredEnergy, Settings.get.assemblerTickAmount * Settings.get.tickFrequency)) + val success = Settings.get.ignorePower || node.tryChangeBuffer(-want) + if (success) { + requiredEnergy -= want + } + if (requiredEnergy <= 0) { + val result = getStackInSlot(slotOutput) + if (result == null) { + setInventorySlotContents(slotOutput, output.get) + } + else if (output.get.isItemEqual(result) && ItemStack.areItemStackTagsEqual(output.get, result) && result.stackSize < result.getMaxStackSize) { + result.stackSize += 1 + markDirty() + } + else { + return + } + requiredEnergy = 0 + output = None + } + // ServerPacketSender.sendRobotAssembling(this, success && output.isDefined) + } + } + } + + override def readFromNBTForServer(nbt: NBTTagCompound) { + super.readFromNBTForServer(nbt) + data.load(nbt.getCompoundTag("data")) + isActive = nbt.getBoolean(Settings.namespace + "active") + if (nbt.hasKey(Settings.namespace + "output")) { + output = Option(ItemUtils.loadStack(nbt.getCompoundTag(Settings.namespace + "output"))) + } + totalRequiredEnergy = nbt.getDouble(Settings.namespace + "total") + requiredEnergy = nbt.getDouble(Settings.namespace + "remaining") + } + + override def writeToNBTForServer(nbt: NBTTagCompound) { + super.writeToNBTForServer(nbt) + nbt.setNewCompoundTag("data", data.save) + nbt.setBoolean(Settings.namespace + "active", isActive) + output.foreach(stack => nbt.setNewCompoundTag(Settings.namespace + "output", stack.writeToNBT)) + nbt.setDouble(Settings.namespace + "total", totalRequiredEnergy) + nbt.setDouble(Settings.namespace + "remaining", requiredEnergy) + } + + @SideOnly(Side.CLIENT) override + def readFromNBTForClient(nbt: NBTTagCompound) { + super.readFromNBTForClient(nbt) + requiredEnergy = nbt.getDouble("remaining") + } + + override def writeToNBTForClient(nbt: NBTTagCompound) { + super.writeToNBTForClient(nbt) + nbt.setDouble("remaining", requiredEnergy) + } + + // ----------------------------------------------------------------------- // + + override def getSizeInventory = 3 + + override def getInventoryStackLimit = 64 + + override def isItemValidForSlot(slot: Int, stack: ItemStack) = + if (slot == 0) + true // TODO Plastic + else if (slot == 1) + true // TODO Color + else false +} diff --git a/src/main/scala/li/cil/oc/util/ExtendedAABB.scala b/src/main/scala/li/cil/oc/util/ExtendedAABB.scala new file mode 100644 index 000000000..80ec8af81 --- /dev/null +++ b/src/main/scala/li/cil/oc/util/ExtendedAABB.scala @@ -0,0 +1,28 @@ +package li.cil.oc.util + +import net.minecraft.util.AxisAlignedBB + +import scala.language.implicitConversions + +object ExtendedAABB { + implicit def extendedAABB(bounds: AxisAlignedBB): ExtendedAABB = new ExtendedAABB(bounds) + + def unitBounds = AxisAlignedBB.getBoundingBox(0, 0, 0, 1, 1, 1) + + class ExtendedAABB(val bounds: AxisAlignedBB) { + def volume: Int = { + val sx = ((bounds.maxX - bounds.minX) * 16).round.toInt + val sy = ((bounds.maxY - bounds.minY) * 16).round.toInt + val sz = ((bounds.maxZ - bounds.minZ) * 16).round.toInt + sx * sy * sz + } + + def surface: Int = { + val sx = ((bounds.maxX - bounds.minX) * 16).round.toInt + val sy = ((bounds.maxY - bounds.minY) * 16).round.toInt + val sz = ((bounds.maxZ - bounds.minZ) * 16).round.toInt + sx * sy * 2 + sx * sz * 2 + sy * sz * 2 + } + } + +} From 311973e33e152eac9d1519f53b9cb1f2c3711222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Mon, 23 Mar 2015 21:02:08 +0100 Subject: [PATCH 04/17] Materials for printing (plastic and ink). --- assets/items.psd | Bin 580270 -> 583622 bytes src/main/resources/application.conf | 4 + .../assets/opencomputers/lang/en_US.lang | 10 ++ .../opencomputers/recipes/default.recipes | 15 ++ .../textures/gui/printer_ink.png | Bin 0 -> 1615 bytes .../textures/gui/printer_plastic.png | Bin 0 -> 1266 bytes .../textures/gui/printer_progress.png | Bin 189 -> 189 bytes .../textures/items/InkCartridge.png | Bin 0 -> 645 bytes .../textures/items/InkCartridgeEmpty.png | Bin 0 -> 636 bytes .../opencomputers/textures/items/Plastic.png | Bin 0 -> 316 bytes src/main/scala/li/cil/oc/Settings.scala | 1 + .../li/cil/oc/client/PacketHandler.scala | 9 ++ .../scala/li/cil/oc/client/Textures.scala | 2 + .../scala/li/cil/oc/client/gui/Printer.scala | 42 ++++-- .../oc/client/gui/widget/ProgressBar.scala | 4 +- .../scala/li/cil/oc/common/PacketType.scala | 1 + src/main/scala/li/cil/oc/common/Slot.scala | 1 + .../scala/li/cil/oc/common/block/Item.scala | 9 ++ .../scala/li/cil/oc/common/block/Print.scala | 10 ++ .../li/cil/oc/common/block/Printer.scala | 4 +- .../container/DynamicComponentSlot.scala | 2 +- .../li/cil/oc/common/container/Printer.scala | 36 ++--- .../container/StaticComponentSlot.scala | 2 +- .../scala/li/cil/oc/common/init/Items.scala | 5 + .../li/cil/oc/common/item/InkCartridge.scala | 5 + .../oc/common/item/InkCartridgeEmpty.scala | 5 + .../scala/li/cil/oc/common/item/Plastic.scala | 3 + .../li/cil/oc/common/tileentity/Printer.scala | 133 +++++++++++------- .../scala/li/cil/oc/server/PacketSender.scala | 9 ++ 29 files changed, 223 insertions(+), 89 deletions(-) create mode 100644 src/main/resources/assets/opencomputers/textures/gui/printer_ink.png create mode 100644 src/main/resources/assets/opencomputers/textures/gui/printer_plastic.png create mode 100644 src/main/resources/assets/opencomputers/textures/items/InkCartridge.png create mode 100644 src/main/resources/assets/opencomputers/textures/items/InkCartridgeEmpty.png create mode 100644 src/main/resources/assets/opencomputers/textures/items/Plastic.png create mode 100644 src/main/scala/li/cil/oc/common/item/InkCartridge.scala create mode 100644 src/main/scala/li/cil/oc/common/item/InkCartridgeEmpty.scala create mode 100644 src/main/scala/li/cil/oc/common/item/Plastic.scala diff --git a/assets/items.psd b/assets/items.psd index 6856b63bd4ca7fff37968744184d5d205d6918be..9eaa421ece300068932778eed3f24445ca692638 100644 GIT binary patch delta 8632 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 ZWY3bY1@KS@ljXWxiC(YE2i&F1=zq}Y diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index f68159751..f3a84f3ba 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -509,6 +509,10 @@ opencomputers { # controls the speed at which items are disassembled, basically. disassemblerTickAmount: 25 + # The amount of energy the printer can apply per tick. This controls + # the speed at which prints are completed, basically. + printerTickAmount: 10 + # If you don't want OpenComputers to accept power from one or more of the # supported power mods, for example because it doesn't suit the vision # of your mod pack, you can disable support for them here. To stop diff --git a/src/main/resources/assets/opencomputers/lang/en_US.lang b/src/main/resources/assets/opencomputers/lang/en_US.lang index 5de7bef65..629e1551e 100644 --- a/src/main/resources/assets/opencomputers/lang/en_US.lang +++ b/src/main/resources/assets/opencomputers/lang/en_US.lang @@ -23,6 +23,8 @@ tile.oc.microcontroller.name=Microcontroller tile.oc.motionSensor.name=Motion Sensor tile.oc.powerConverter.name=Power Converter tile.oc.powerDistributor.name=Power Distributor +tile.oc.print.name=3D Print +tile.oc.printer.name=3D Printer tile.oc.raid.name=Raid tile.oc.redstone.name=Redstone I/O tile.oc.robot.name=Robot @@ -66,6 +68,8 @@ item.oc.GraphicsCard2.name=Graphics Card (Tier 3) item.oc.HardDiskDrive0.name=Hard Disk Drive (Tier 1) item.oc.HardDiskDrive1.name=Hard Disk Drive (Tier 2) item.oc.HardDiskDrive2.name=Hard Disk Drive (Tier 3) +item.oc.InkCartridge.name=Ink Cartidge +item.oc.InkCartridgeEmpty.name=Ink Cartidge (Empty) item.oc.InternetCard.name=Internet Card item.oc.Interweb.name=Interweb item.oc.IronNugget.name=Iron Nugget @@ -84,6 +88,7 @@ item.oc.MicrocontrollerCase1.name=Microcontroller Case (Tier 2) item.oc.MicrocontrollerCase3.name=Microcontroller Case (Creative) item.oc.NetworkCard.name=Network Card item.oc.NumPad.name=Numeric Keypad +item.oc.Plastic.name=Plastic item.oc.Present.name=A little something... item.oc.PrintedCircuitBoard.name=Printed Circuit Board (PCB) item.oc.RawCircuitBoard.name=Raw Circuit Board @@ -197,6 +202,7 @@ oc:container.Charger=Charger oc:container.Case=Computer oc:container.Disassembler=Disassembler oc:container.DiskDrive=Disk Drive +oc:container.Printer=Printer oc:container.Raid=Raid oc:container.Server=Server oc:container.ServerRack=Server Rack @@ -237,6 +243,8 @@ oc:tooltip.DroneCase=This casing is used to build Drones in the assembler. It ha oc:tooltip.EEPROM=Small, programmable storage that contains the BIOS computers use to boot. oc:tooltip.Geolyzer=Allows scanning the surrounding area's blocks' hardness. This information can be useful for generating holograms of the area or for detecting ores. oc:tooltip.GraphicsCard=Used to change what's displayed on screens.[nl] Maximum resolution: §f%sx%s§7[nl] Maximum color depth: §f%s§7[nl] Operations/tick: §f%s§7 +oc:tooltip.InkCartridge=Used to refill ink in 3D printers. For mysterious reasons it does not have to remain in the printer. +oc:tooltip.InkCartridgeEmpty=This ink cartridge has been sucked dry. Refill it using dyes. Or throw it away. See if I care. oc:tooltip.InternetCard=This card allows making HTTP requests and using real TCP sockets. oc:tooltip.Interweb=Congratulations, you win one (1) interweb. You can connect to it using an Internet Card. Beware: don't feed the trolls. oc:tooltip.IronNugget=A nugget made of iron, that's why it's called an Iron Nugget, duh... @@ -253,6 +261,7 @@ oc:tooltip.Microcontroller=Microcontrollers are computers boiled down to the ess oc:tooltip.MicrocontrollerCase=Base component for building microcontrollers. Place it into an assembler to add further components and assemble a microcontroller. oc:tooltip.MotionSensor=Can detect movement of nearby living beings. Requires clear line-of-sight. oc:tooltip.NetworkCard=Allows distant computers connected by other blocks (such as cable) to communicate by sending messages to each other. +oc:tooltip.Plastic=Raw material for 3D prints. Do not swallow. Not that you could even if you wanted to. oc:tooltip.PowerAcceptor=Energy conversion speed: §f%s/t§7 oc:tooltip.PowerConverter.BuildCraft=§fBuildCraft MJ§7: §a%s:%s§7 oc:tooltip.PowerConverter.Factorization=§fFactorization Charge§7: §a%s:%s§7 @@ -262,6 +271,7 @@ oc:tooltip.PowerConverter.ThermalExpansion=§fThermal Expansion RF§7: §a%s:%s oc:tooltip.PowerConverter.ResonantEngine=§fResonant Engine Coulombs§7: §a%s:%s§7 oc:tooltip.PowerConverter=Converts power from other mods to the internal energy type. Conversion rates: oc:tooltip.PowerDistributor=Distributes energy among different networks. This is useful for sharing power fed into your system from one converter among different sub-networks that should remain separate. +oc:tooltip.Printer=Allows printing blocks of user-defined shapes using plastic and ink cartridges. Must be configured using a computer. Keep away from small children. Because reasons. oc:tooltip.PrintedCircuitBoard=The basic building block for expansion cards and memory and such. oc:tooltip.Present=... for your troubles. Open this present for a chance to receive some §kphat lewt§7![nl]§8Craft OpenComputers items when the time is right for a chance to receive a present.§7 oc:tooltip.Raid=Allows combining three hard drives into one larger file system that can be used by all connected computers. diff --git a/src/main/resources/assets/opencomputers/recipes/default.recipes b/src/main/resources/assets/opencomputers/recipes/default.recipes index 6cb743bcd..b85a2a94b 100644 --- a/src/main/resources/assets/opencomputers/recipes/default.recipes +++ b/src/main/resources/assets/opencomputers/recipes/default.recipes @@ -318,6 +318,21 @@ disk { [nuggetIron, "", nuggetIron] ["", nuggetIron, ""]] } +plastic { + input: [[gravel, gravel, gravel], + [gravel, {item=coal, subID=1}, gravel], + [gravel, water_bucket, gravel]] + output: 8 +} +inkCartridgeEmpty { + input: [[nuggetIron, dispenser, nuggetIron], + ["oc:materialTransistor", bucket, "oc:materialTransistor"], + [nuggetIron, "oc:materialCircuitBoardPrinted", nuggetIron]] +} +inkCartridge { + type: shapeless + input: [dyeCyan, dyeMagenta, dyeYellow, dyeBlack, "oc:inkCartridgeEmpty"] +} buttonGroup { input: [[button, button, button] diff --git a/src/main/resources/assets/opencomputers/textures/gui/printer_ink.png b/src/main/resources/assets/opencomputers/textures/gui/printer_ink.png new file mode 100644 index 0000000000000000000000000000000000000000..b125722a708216366bd10a19b8ce211061ad0905 GIT binary patch literal 1615 zcmV-V2C(^wP)B#|g%)0pr0}GS`8kmv;s;T)D1p0_y$%tStw7)B5TGdfEcJ0=3rx zw++Z@@&f_>uLJya0rCO9)C>#)QMvR5!rTU{2qU5Z&y&sg1LFDv{>udD3&{f9{sG&o z2Jrl70Ga#400PpX0lZ!60s?LUpa8N;Zr&9P_Wu0a0qXw>7OxcR0=4~;006pY{5=K& z%!Cd1>i{&P-v1N@;r}DNA}Yct6uB(_;ROCH0}Zk!Rnr+q(IMG~ z3=;hR7YUdE;>5!L5&*sN)&B|vA)Fili|qut^a~3(0h9b%0072*1H$&?3AF$J3gQI? zCIpo9`~p139`$Vi1MT4etvUDp1pwym{3ZYerRx5&1PaXm{P+L_)|!R@o(8!^0GZ#R z@eKJ@0RJ-z0iosqwqmyR1^M*=4zBY9!*K2O006XA0zIw&{|5g;0|35j@wou>PymYS z6ZWM6g5nBZ3#9*u4Y~69013ZU_yNQ+0F9mP2;l|7ao`u_6TknN2IvH{_6-34^#=d(1NGDZNC1ui zV86-;2pYaJ1Ghr}+PeqYoCv%~&j7Cx9;5)kc>m=HKg%IS44~E#5&vimF%Y1D-vxSP{QtQN{|5z+@E8EejqS?-5-qIskpTa`5b&P> z2gr2)@(8Nx00X#B4Z1~@^c??r2>%Y#_6x`d&xrpD&hQAn|IrFS%OUxw0036C5aOo) z&j|Vb2L|A;@-zVWI{*OK`d!;057GYs=iK!W5DD+l|C$I8zd-=$-v3e&0IuQ+sqX-? zJ_xuu=n)YI?9B<&LA$59>{og!-v@E>@&>Q-)Z+fQa;kiY0s}}p z6N__oxb(xz+H2-TC!4eu^N1SmjJJ36Nb1%tTm4gq&06!j-P1z$Ma;}WTtMxy(}3Fh zXY^e#Q(#!%uE(@jFZEWwbVvHdH6m5zD!+@THyXO~**m^iVW4~T+;W{|_fiCJXA}xE z$k_x1t@7m!p0-e*`=j_&nK@A)+nJc=7IfzSFmF(G5&_!&n}cVQVecge7mw#BDlDv& zbe1LZ3)*GmvI~E*d4G_L(>HeALM?7FwLY_uD2Bx`dQ5tf&YeKp8&nS*oA{2k)jzKu zXuE^Ui=_s-HLLgEU`y28tsa@nzDUmIy&@;CFWB)PSDrWfH;X~`rQTjimQ>5|Er<48 zGoCl`x{5Lf(CnFY(AZp$OUJL-=$m=~Fz9-0 zAR!;-*^>QnhP(_g;vm{ntHV!s9I0IZ3_4)EzXjS3bi7B>6p1pcs~T+0nu2zbrR)r! zDuWb3wohvUIo?cW4lv^MB=>r=e7+ejZJu7cW_wk#imiX%rkSp86P5^_G|(-xS`PBN z;Ozily!U+KQsm|J-S`C*bmC{uhRg!_U2^Z-0?T~q*;3k0A`{=4*cMM0HT=Uj!9^%% zif+-ltQ)VoQUtf&O=D;1VScZ;iq|*zYm?RvF>zq3n*?-xC=-)pL3O^g`DN7wZ!*hS zm5+Pv1KIBQVrh4U#p>4rY}Q7aK-+~E$yIVGazTPFyMHAx*-QcmFaUOr8A~G3qHq8J N002ovPDHLkV1iqL2)zIR literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/opencomputers/textures/gui/printer_plastic.png b/src/main/resources/assets/opencomputers/textures/gui/printer_plastic.png new file mode 100644 index 0000000000000000000000000000000000000000..3f67324d2e16922104e70b410e9a4066bc9723a8 GIT binary patch literal 1266 zcmViSJ-q_UJ)6dq<%HP-1(#yx%)X?PJ+1%97-qzCJ+12Ud-sj=n z*wD<^&&%D{)7;k5*3Zl7f+wj z&B@Qm#O&qa*3it^(ahl3)YZ+%(#pou%g62K*eC#+1BOX+~wWb(8$Bg#K7X(*6rux>Ez+r z)6ePQ-0$e*&Bej!;@{iS&Dqn?=HcGb%*o5czVhnk&Bns*=;h(t*v`hn=;Pqv+t}C9 z>RZ%*Dac%g5Hv$?oUl)z8c0+STvs=i}Sf<>1}X$;92))a>Ts@apE+($CAp!0qPZ z+SSs}#=+Fg$M5Ik%fr9vCVW+*3ixN@a*N?*x%aM+SJi3 z-ScMv00N>(L_t(|+62LaqFq-M0Km0%Y~$KCo^8iA>n24|8?maCf7%%!EU)Hf!X-oK zCw8bvf>Ts?K>xJ>b&Pf`K4OZE4Mw$$6{((6L6I@|S0T!E^#y)%2e2{KmgEEify-rz zxYcDSH7c{W)m^~TfkWBHlf0T=-mqp**rL*DbSX-LrE}+g0JOtAy7z=hCFg)~?!{ZVt z0yXmi$#%6%ickEnd6qy<$^$oB$GzT}KdC@x#E9F&+T7EI=!CrwL1@Bbnw9TKMpfkO zY@ByaB({rveTws}bxv_5+*&zVN-H*+Gto8wQUwcD7?GbBTjCF+FVw#cNc>XNxoo^W z$@PCC#ep3kDHpi?e8h=qu7f=&&}E63TimCOjNd*<>=f zPsPTP%&o-$E9)B{N#!!39PWJ<;wbk-+=zA zh~4hc;jU_?r=@SxH`9@aNS5XJQTlE=pDV{n{y&w|=7mQ@AsK(udmpL!VNH_Y5D!zh z85T;y=A54T{=3LNdqf7#dt;oLac4ua!Uo45&cgp_k1QRautIE)+lw?%MGmnaC*P4ZP{b;iZ zLW^~{bP0l+XkKOdt-r delta 40 vcmdnXxR-H48K=opo{WZFr!F3uSg$1_=*>R;`CJzc1|aZs^>bP0l+XkKNU9FJ diff --git a/src/main/resources/assets/opencomputers/textures/items/InkCartridge.png b/src/main/resources/assets/opencomputers/textures/items/InkCartridge.png new file mode 100644 index 0000000000000000000000000000000000000000..a2b92d00b00f8d421ef0c158818df9ca1960c33f GIT binary patch literal 645 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8{{cQBt|mdo+AdnQ2{v4Y;tEFcN@hy3da|7QqF1k$m93Kw zETeaCPiS+I`WLzWYE&J4|bp*ImbShodJA zraK(n?DMjCO;N?h@^>E$U9y}5>jRuJ9GAM@(2duA{>rRj@v(@`@P%i8SzB8hXBqm{ z`0AzV1lI+HwTGrJNqhRjWX8eQ|NsBD`qSAC^gw7ykY6y6OLf4oVIli@par`okL*zhmWRfb<37txFe_`c5bWr;q?1Fq3`-$#I9{O4d%|;UbnzOp|-R$yfpAk zmkDq51$L$d8n-O(rp@5-Gzxg9|DV$}(8fXGf!e-GZUcq@Q60bbZ+Rbp-eB-_^>bP0 Hl+XkKdde~m literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/opencomputers/textures/items/InkCartridgeEmpty.png b/src/main/resources/assets/opencomputers/textures/items/InkCartridgeEmpty.png new file mode 100644 index 0000000000000000000000000000000000000000..007697d69a7571dd7956a253f31a27ce7f0bcbd6 GIT binary patch literal 636 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8p8-B0uJ&&BCRQe1L0)QFYFc_)l1egHua+pQD+A>v6r{Io zNlD31IjpB=W@VO^n|8s>%)#9uBql`9ST8X3AV=09aB3xr*+O>HQznNT}DR6$=}H%)WgQfCN4SC%P!E{Kg7|@ z-NVBqJSNf0FWB1E+Sb!HDL2VK!r#{+#KYRJuBR?OGv3A3sG+YRqc|fd$jZ>#Ff~6_ zTwW@zAkEIzE-5F;%Qhe&GN5->uYZ80xr4d2yLEbD`i31F<}9BR6djaRn&snTYVU0y z5NMU0n=CFa{{R2~6KYW}fSwF43GxdDa;Xd$(mLxRfyVFhba4!+xRug>Rj4UIppD=C zkwWjHMNDPo<>jY;+xO_jt-Sx{=sENMISSv|pX^#Q|7-Q%-Hd`$4JWAxY-%&?XjsYv=C^*_$d%Vc@_U*bCsC+`OqH=6DRF!&bVd#QK+ uyhL03uRovWUnsrH-g0>U5p#V;HilI^+ETjJSDyfV!QkoY=d#Wzp$Py><{4lB literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/opencomputers/textures/items/Plastic.png b/src/main/resources/assets/opencomputers/textures/items/Plastic.png new file mode 100644 index 0000000000000000000000000000000000000000..914588f6b48eb3be3830a4a60542384f5862057d GIT binary patch literal 316 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!fo%K)DcS4$&ZJq_jJyo7`pzwlsJPd6J^CySK$fV!%j_-Mb- zK-btvpTgXv#2CMcea&r6WgTs`E0@pz|NsBq{(JdALxf9${DOg8G{CT__6`S7y2{hV zF{I*F%=yK%i(##NymOIXTXVmmhPKCL- onHologramPositionOffsetY(p) case PacketType.PetVisibility => onPetVisibility(p) case PacketType.PowerState => onPowerState(p) + case PacketType.PrinterState => onPrinterState(p) case PacketType.RaidStateChange => onRaidStateChange(p) case PacketType.RedstoneState => onRedstoneState(p) case PacketType.RobotAnimateSwing => onRobotAnimateSwing(p) @@ -242,6 +243,14 @@ object PacketHandler extends CommonPacketHandler { case _ => // Invalid packet. } + def onPrinterState(p: PacketParser) = + p.readTileEntity[Printer]() match { + case Some(t) => + if (p.readBoolean()) t.requiredEnergy = 9001 + else t.requiredEnergy = 0 + case _ => // Invalid packet. + } + def onRaidStateChange(p: PacketParser) = p.readTileEntity[Raid]() match { case Some(t) => diff --git a/src/main/scala/li/cil/oc/client/Textures.scala b/src/main/scala/li/cil/oc/client/Textures.scala index 4d02efe8f..19e3ce67d 100644 --- a/src/main/scala/li/cil/oc/client/Textures.scala +++ b/src/main/scala/li/cil/oc/client/Textures.scala @@ -26,6 +26,8 @@ object Textures { val guiDrone = new ResourceLocation(Settings.resourceDomain, "textures/gui/drone.png") val guiKeyboardMissing = new ResourceLocation(Settings.resourceDomain, "textures/gui/keyboard_missing.png") val guiPrinter = new ResourceLocation(Settings.resourceDomain, "textures/gui/printer.png") + val guiPrinterInk = new ResourceLocation(Settings.resourceDomain, "textures/gui/printer_ink.png") + val guiPrinterPlastic = new ResourceLocation(Settings.resourceDomain, "textures/gui/printer_plastic.png") val guiPrinterProgress = new ResourceLocation(Settings.resourceDomain, "textures/gui/printer_progress.png") val guiRaid = new ResourceLocation(Settings.resourceDomain, "textures/gui/raid.png") val guiRange = new ResourceLocation(Settings.resourceDomain, "textures/gui/range.png") diff --git a/src/main/scala/li/cil/oc/client/gui/Printer.scala b/src/main/scala/li/cil/oc/client/gui/Printer.scala index 3ad735a26..d5217af59 100644 --- a/src/main/scala/li/cil/oc/client/gui/Printer.scala +++ b/src/main/scala/li/cil/oc/client/gui/Printer.scala @@ -3,19 +3,31 @@ package li.cil.oc.client.gui import li.cil.oc.Localization import li.cil.oc.client.Textures import li.cil.oc.client.gui.widget.ProgressBar -import li.cil.oc.client.{PacketSender => ClientPacketSender} import li.cil.oc.common.container import li.cil.oc.common.container.ComponentSlot import li.cil.oc.common.tileentity import net.minecraft.entity.player.InventoryPlayer -import net.minecraft.util.ResourceLocation import org.lwjgl.opengl.GL11 class Printer(playerInventory: InventoryPlayer, val printer: tileentity.Printer) extends DynamicGuiContainer(new container.Printer(playerInventory, printer)) { xSize = 176 ySize = 166 - private val progress = addWidget(new ProgressBar(104, 21) { + private val plasticBar = addWidget(new ProgressBar(40, 21) { + override def width = 62 + + override def height = 12 + + override def barTexture = Textures.guiPrinterPlastic + }) + private val inkBar = addWidget(new ProgressBar(40, 53) { + override def width = 62 + + override def height = 12 + + override def barTexture = Textures.guiPrinterInk + }) + private val progressBar = addWidget(new ProgressBar(105, 20) { override def width = 46 override def height = 46 @@ -23,7 +35,7 @@ class Printer(playerInventory: InventoryPlayer, val printer: tileentity.Printer) override def barTexture = Textures.guiPrinterProgress }) - private def assemblerContainer = inventorySlots.asInstanceOf[container.Printer] + private def printerContainer = inventorySlots.asInstanceOf[container.Printer] override def initGui() { super.initGui() @@ -35,27 +47,27 @@ class Printer(playerInventory: InventoryPlayer, val printer: tileentity.Printer) Localization.localizeImmediately(printer.getInventoryName), 8, 6, 0x404040) GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS) // Me lazy... prevents NEI render glitch. - if (assemblerContainer.isAssembling && func_146978_c(progress.x, progress.y, progress.width, progress.height, mouseX, mouseY)) { + if (func_146978_c(plasticBar.x, plasticBar.y, plasticBar.width, plasticBar.height, mouseX, mouseY)) { val tooltip = new java.util.ArrayList[String] - val timeRemaining = formatTime(assemblerContainer.assemblyRemainingTime) - tooltip.add(Localization.Assembler.Progress(assemblerContainer.assemblyProgress, timeRemaining)) + tooltip.add(printerContainer.amountPlastic + "/" + printer.maxAmountPlastic) + copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRendererObj) + } + if (func_146978_c(inkBar.x, inkBar.y, inkBar.width, inkBar.height, mouseX, mouseY)) { + val tooltip = new java.util.ArrayList[String] + tooltip.add(printerContainer.amountInk + "/" + printer.maxAmountInk) copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRendererObj) } GL11.glPopAttrib() } - private def formatTime(seconds: Int) = { - // Assembly times should not / rarely exceed one hour, so this is good enough. - if (seconds < 60) f"0:$seconds%02d" - else f"${seconds / 60}:${seconds % 60}%02d" - } - override def drawGuiContainerBackgroundLayer(dt: Float, mouseX: Int, mouseY: Int) { GL11.glColor3f(1, 1, 1) // Required under Linux. mc.renderEngine.bindTexture(Textures.guiPrinter) drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize) - if (assemblerContainer.isAssembling) progress.level = assemblerContainer.assemblyProgress / 100.0 - else progress.level = 0 + plasticBar.level = printerContainer.amountPlastic / printer.maxAmountPlastic.toDouble + inkBar.level = printerContainer.amountInk / printer.maxAmountInk.toDouble + if (printerContainer.isPrinting) progressBar.level = (System.currentTimeMillis() % 3000) / 3000.0 + else progressBar.level = 0 drawWidgets() drawInventorySlots() } diff --git a/src/main/scala/li/cil/oc/client/gui/widget/ProgressBar.scala b/src/main/scala/li/cil/oc/client/gui/widget/ProgressBar.scala index 22541fbe5..4a049d221 100644 --- a/src/main/scala/li/cil/oc/client/gui/widget/ProgressBar.scala +++ b/src/main/scala/li/cil/oc/client/gui/widget/ProgressBar.scala @@ -16,8 +16,8 @@ class ProgressBar(val x: Int, val y: Int) extends Widget { def draw() { if (level > 0) { val u0 = 0 - val u1 = width / 256.0 * level - val v0 = 1 - height / 256.0 + val u1 = level + val v0 = 0 val v1 = 1 val tx = owner.windowX + x val ty = owner.windowY + y diff --git a/src/main/scala/li/cil/oc/common/PacketType.scala b/src/main/scala/li/cil/oc/common/PacketType.scala index 6a0a0f201..f2f16c868 100644 --- a/src/main/scala/li/cil/oc/common/PacketType.scala +++ b/src/main/scala/li/cil/oc/common/PacketType.scala @@ -20,6 +20,7 @@ object PacketType extends Enumeration { HologramTranslation, PetVisibility, // Goes both ways. PowerState, + PrinterState, RaidStateChange, RedstoneState, RobotAnimateSwing, diff --git a/src/main/scala/li/cil/oc/common/Slot.scala b/src/main/scala/li/cil/oc/common/Slot.scala index 4cbb05bd6..fed8e914b 100644 --- a/src/main/scala/li/cil/oc/common/Slot.scala +++ b/src/main/scala/li/cil/oc/common/Slot.scala @@ -5,6 +5,7 @@ import li.cil.oc.api.driver object Slot { val None = driver.item.Slot.None val Any = driver.item.Slot.Any + val Filtered = "filtered" val Card = driver.item.Slot.Card val ComponentBus = driver.item.Slot.ComponentBus diff --git a/src/main/scala/li/cil/oc/common/block/Item.scala b/src/main/scala/li/cil/oc/common/block/Item.scala index 022012ada..42a121d6b 100644 --- a/src/main/scala/li/cil/oc/common/block/Item.scala +++ b/src/main/scala/li/cil/oc/common/block/Item.scala @@ -5,6 +5,7 @@ import java.util import li.cil.oc.Settings import li.cil.oc.api import li.cil.oc.client.KeyBindings +import li.cil.oc.common.item.data.PrintData import li.cil.oc.common.item.data.RobotData import li.cil.oc.common.tileentity import li.cil.oc.util.ItemCosts @@ -47,6 +48,14 @@ class Item(value: Block) extends ItemBlock(value) { override def getMetadata(itemDamage: Int) = itemDamage + override def getItemStackDisplayName(stack: ItemStack): String = { + if (api.Items.get(stack) == api.Items.get("print")) { + val data = new PrintData(stack) + data.label.getOrElse(super.getItemStackDisplayName(stack)) + } + else super.getItemStackDisplayName(stack) + } + override def getUnlocalizedName = block match { case simple: SimpleBlock => simple.getUnlocalizedName case _ => Settings.namespace + "tile" diff --git a/src/main/scala/li/cil/oc/common/block/Print.scala b/src/main/scala/li/cil/oc/common/block/Print.scala index f28a8540f..5fe0b37bc 100644 --- a/src/main/scala/li/cil/oc/common/block/Print.scala +++ b/src/main/scala/li/cil/oc/common/block/Print.scala @@ -1,6 +1,9 @@ package li.cil.oc.common.block +import java.util + import li.cil.oc.Settings +import li.cil.oc.common.item.data.PrintData import li.cil.oc.common.tileentity import li.cil.oc.util.ExtendedAABB import net.minecraft.entity.EntityLivingBase @@ -11,6 +14,7 @@ import net.minecraft.world.IBlockAccess import net.minecraft.world.World import net.minecraftforge.common.util.ForgeDirection +import scala.collection.convert.WrapAsJava._ import scala.reflect.ClassTag class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends SimpleBlock with traits.SpecialBlock with traits.CustomDrops[tileentity.Print] { @@ -19,6 +23,12 @@ class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends // NEI.hide(this) setBlockTextureName(Settings.resourceDomain + "GenericTop") + override protected def tooltipBody(metadata: Int, stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean): Unit = { + super.tooltipBody(metadata, stack, player, tooltip, advanced) + val data = new PrintData(stack) + data.tooltip.foreach(s => tooltip.addAll(s.lines.toIterable)) + } + override def shouldSideBeRendered(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = true override def isBlockSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = true diff --git a/src/main/scala/li/cil/oc/common/block/Printer.scala b/src/main/scala/li/cil/oc/common/block/Printer.scala index d0be27b26..5f56b939e 100644 --- a/src/main/scala/li/cil/oc/common/block/Printer.scala +++ b/src/main/scala/li/cil/oc/common/block/Printer.scala @@ -9,7 +9,7 @@ import net.minecraft.world.IBlockAccess import net.minecraft.world.World import net.minecraftforge.common.util.ForgeDirection -class Printer extends SimpleBlock with traits.SpecialBlock with traits.PowerAcceptor with traits.StateAware with traits.GUI { +class Printer extends SimpleBlock with traits.SpecialBlock with traits.StateAware with traits.GUI { override protected def customTextures = Array( None, Some("AssemblerTop"), @@ -32,8 +32,6 @@ class Printer extends SimpleBlock with traits.SpecialBlock with traits.PowerAcce // ----------------------------------------------------------------------- // - override def energyThroughput = Settings.get.assemblerRate - override def guiType = GuiType.Printer override def hasTileEntity(metadata: Int) = true diff --git a/src/main/scala/li/cil/oc/common/container/DynamicComponentSlot.scala b/src/main/scala/li/cil/oc/common/container/DynamicComponentSlot.scala index 0d296d213..bc96137b4 100644 --- a/src/main/scala/li/cil/oc/common/container/DynamicComponentSlot.scala +++ b/src/main/scala/li/cil/oc/common/container/DynamicComponentSlot.scala @@ -28,7 +28,7 @@ class DynamicComponentSlot(val container: Player, inventory: IInventory, index: override def getSlotStackLimit = slot match { - case common.Slot.Tool | common.Slot.Any => super.getSlotStackLimit + case common.Slot.Tool | common.Slot.Any | common.Slot.Filtered => super.getSlotStackLimit case common.Slot.None => 0 case _ => 1 } diff --git a/src/main/scala/li/cil/oc/common/container/Printer.scala b/src/main/scala/li/cil/oc/common/container/Printer.scala index c50c50acf..b9172c9d1 100644 --- a/src/main/scala/li/cil/oc/common/container/Printer.scala +++ b/src/main/scala/li/cil/oc/common/container/Printer.scala @@ -2,51 +2,53 @@ package li.cil.oc.common.container import cpw.mods.fml.relauncher.Side import cpw.mods.fml.relauncher.SideOnly +import li.cil.oc.common.Slot import li.cil.oc.common.tileentity import li.cil.oc.util.SideTracker import net.minecraft.entity.player.InventoryPlayer class Printer(playerInventory: InventoryPlayer, val printer: tileentity.Printer) extends Player(playerInventory, printer) { - addSlotToContainer(18, 19) - addSlotToContainer(18, 51) + addSlotToContainer(18, 19, Slot.Filtered) + addSlotToContainer(18, 51, Slot.Filtered) addSlotToContainer(152, 35) // Show the player's inventory. addPlayerInventorySlots(8, 84) - var isAssembling = false - var assemblyProgress = 0.0 - var assemblyRemainingTime = 0 + var isPrinting = false + var amountPlastic = 0 + var amountInk = 0 @SideOnly(Side.CLIENT) override def updateProgressBar(id: Int, value: Int) { super.updateProgressBar(id, value) if (id == 0) { - isAssembling = value == 1 + isPrinting = value == 1 } if (id == 1) { - assemblyProgress = value / 5.0 + amountPlastic = value } if (id == 2) { - assemblyRemainingTime = value + amountInk = value } } override def detectAndSendChanges() { super.detectAndSendChanges() if (SideTracker.isServer) { - if (isAssembling != printer.isAssembling) { - isAssembling = printer.isAssembling - sendProgressBarUpdate(0, if (isAssembling) 1 else 0) + if (isPrinting != printer.isPrinting) { + isPrinting = printer.isPrinting + sendProgressBarUpdate(0, if (isPrinting) 1 else 0) } - val timeRemaining = printer.timeRemaining - if (math.abs(printer.progress - assemblyProgress) > 0.2 || assemblyRemainingTime != timeRemaining) { - assemblyProgress = printer.progress - assemblyRemainingTime = timeRemaining - sendProgressBarUpdate(1, (assemblyProgress * 5).toInt) - sendProgressBarUpdate(2, timeRemaining) + if (amountPlastic != printer.amountPlastic) { + amountPlastic = printer.amountPlastic + sendProgressBarUpdate(1, amountPlastic) + } + if (amountInk != printer.amountInk) { + amountInk = printer.amountInk + sendProgressBarUpdate(2, amountInk) } } } diff --git a/src/main/scala/li/cil/oc/common/container/StaticComponentSlot.scala b/src/main/scala/li/cil/oc/common/container/StaticComponentSlot.scala index 0155308b4..ea7bae721 100644 --- a/src/main/scala/li/cil/oc/common/container/StaticComponentSlot.scala +++ b/src/main/scala/li/cil/oc/common/container/StaticComponentSlot.scala @@ -12,7 +12,7 @@ class StaticComponentSlot(val container: Player, inventory: IInventory, index: I override def getSlotStackLimit = slot match { - case common.Slot.Tool | common.Slot.Any => super.getSlotStackLimit + case common.Slot.Tool | common.Slot.Any | common.Slot.Filtered => super.getSlotStackLimit case common.Slot.None => 0 case _ => 1 } diff --git a/src/main/scala/li/cil/oc/common/init/Items.scala b/src/main/scala/li/cil/oc/common/init/Items.scala index 88fb189e5..960dac1ce 100644 --- a/src/main/scala/li/cil/oc/common/init/Items.scala +++ b/src/main/scala/li/cil/oc/common/init/Items.scala @@ -470,5 +470,10 @@ object Items extends ItemAPI { // 1.4.7 Recipes.addMultiItem(new item.TabletCase(multi, Tier.Two), "tabletCase2", "oc:tabletCase2") registerItem(new item.TabletCase(multi, Tier.Four), "tabletCaseCreative") + + // 1.5.4 + Recipes.addMultiItem(new item.InkCartridgeEmpty(multi), "inkCartridgeEmpty", "oc:inkCartridgeEmpty") + Recipes.addMultiItem(new item.InkCartridge(multi), "inkCartridge", "oc:inkCartridge") + Recipes.addMultiItem(new item.Plastic(multi), "plastic", "oc:plastic") } } diff --git a/src/main/scala/li/cil/oc/common/item/InkCartridge.scala b/src/main/scala/li/cil/oc/common/item/InkCartridge.scala new file mode 100644 index 000000000..363af10c2 --- /dev/null +++ b/src/main/scala/li/cil/oc/common/item/InkCartridge.scala @@ -0,0 +1,5 @@ +package li.cil.oc.common.item + +class InkCartridge(val parent: Delegator) extends Delegate { + override def maxStackSize = 1 +} diff --git a/src/main/scala/li/cil/oc/common/item/InkCartridgeEmpty.scala b/src/main/scala/li/cil/oc/common/item/InkCartridgeEmpty.scala new file mode 100644 index 000000000..913460404 --- /dev/null +++ b/src/main/scala/li/cil/oc/common/item/InkCartridgeEmpty.scala @@ -0,0 +1,5 @@ +package li.cil.oc.common.item + +class InkCartridgeEmpty(val parent: Delegator) extends Delegate { + override def maxStackSize = 1 +} diff --git a/src/main/scala/li/cil/oc/common/item/Plastic.scala b/src/main/scala/li/cil/oc/common/item/Plastic.scala new file mode 100644 index 000000000..ead7618ac --- /dev/null +++ b/src/main/scala/li/cil/oc/common/item/Plastic.scala @@ -0,0 +1,3 @@ +package li.cil.oc.common.item + +class Plastic(val parent: Delegator) extends Delegate diff --git a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala index 00954516d..b54aa3cee 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala @@ -11,6 +11,7 @@ import li.cil.oc.api.machine.Callback import li.cil.oc.api.machine.Context import li.cil.oc.api.network._ import li.cil.oc.common.item.data.PrintData +import li.cil.oc.server.{PacketSender => ServerPacketSender} import li.cil.oc.util.ExtendedAABB._ import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.util.ItemUtils @@ -19,18 +20,26 @@ import net.minecraft.nbt.NBTTagCompound import net.minecraft.util.AxisAlignedBB import net.minecraftforge.common.util.ForgeDirection -class Printer extends traits.Environment with traits.PowerAcceptor with traits.Inventory with traits.Rotatable with SidedEnvironment with traits.StateAware { +class Printer extends traits.Environment with traits.Inventory with traits.Rotatable with SidedEnvironment with traits.StateAware { val node = api.Network.newNode(this, Visibility.Network). withComponent("printer3d"). withConnector(Settings.get.bufferConverter). create() + val maxAmountPlastic = 256000 + var amountPlastic = 0 + val maxAmountInk = 100000 + var amountInk = 0 + var data = new PrintData() var isActive = false var output: Option[ItemStack] = None var totalRequiredEnergy = 0.0 var requiredEnergy = 0.0 + val plasticPerItem = 2000 + val inkPerCartridge = 50000 + val slotPlastic = 0 val slotInk = 1 val slotOutput = 2 @@ -42,27 +51,22 @@ class Printer extends traits.Environment with traits.PowerAcceptor with traits.I override def sidedNode(side: ForgeDirection) = if (side != ForgeDirection.UP) node else null - @SideOnly(Side.CLIENT) - override protected def hasConnector(side: ForgeDirection) = canConnect(side) - - override protected def connector(side: ForgeDirection) = Option(if (side != ForgeDirection.UP) node else null) - - override protected def energyThroughput = Settings.get.assemblerRate - override def currentState = { - if (isAssembling) util.EnumSet.of(traits.State.IsWorking) - else if (canAssemble) util.EnumSet.of(traits.State.CanWork) + if (isPrinting) util.EnumSet.of(traits.State.IsWorking) + else if (canPrint) util.EnumSet.of(traits.State.CanWork) else util.EnumSet.noneOf(classOf[traits.State]) } // ----------------------------------------------------------------------- // - def canAssemble = { + def canPrint = { val complexity = data.stateOff.size + data.stateOn.size complexity > 0 && complexity <= Settings.get.maxPrintComplexity } - def isAssembling = requiredEnergy > 0 + def isPrinting = (requiredEnergy > 0 || isActive) && Option(getStackInSlot(slotOutput)).fold(true)(stack => { + stack.stackSize < stack.getMaxStackSize && output.fold(true)(ItemStack.areItemStackTagsEqual(stack, _)) + }) def progress = (1 - requiredEnergy / totalRequiredEnergy) * 100 @@ -79,7 +83,7 @@ class Printer extends traits.Environment with traits.PowerAcceptor with traits.I @Callback(doc = """function(value:string) -- Set a label for the block being printed.""") def setLabel(context: Context, args: Arguments): Array[Object] = { - data.label = Option(args.optString(0, null)) + data.label = Option(args.optString(0, null)).map(_.take(16)) isActive = false // Needs committing. null } @@ -91,7 +95,7 @@ class Printer extends traits.Environment with traits.PowerAcceptor with traits.I @Callback(doc = """function(value:string) -- Set a tooltip for the block being printed.""") def setTooltip(context: Context, args: Arguments): Array[Object] = { - data.tooltip = Option(args.optString(0, null)) + data.tooltip = Option(args.optString(0, null)).map(_.take(128)) isActive = false // Needs committing. null } @@ -140,7 +144,7 @@ class Printer extends traits.Environment with traits.PowerAcceptor with traits.I @Callback(doc = """function():boolean -- Commit and begin printing the current configuration.""") def commit(context: Context, args: Arguments): Array[Object] = { - if (!canAssemble) { + if (!canPrint) { return result(null, "model invalid") } isActive = true @@ -149,8 +153,8 @@ class Printer extends traits.Environment with traits.PowerAcceptor with traits.I @Callback(doc = """function(): string, number or boolean -- The current state of the printer, `busy' or `idle', followed by the progress or model validity, respectively.""") def status(context: Context, args: Arguments): Array[Object] = { - if (isAssembling) result("busy", progress) - else if (canAssemble) result("idle", true) + if (isPrinting) result("busy", progress) + else if (canPrint) result("idle", true) else result("idle", false) } @@ -163,47 +167,74 @@ class Printer extends traits.Environment with traits.PowerAcceptor with traits.I override def updateEntity() { super.updateEntity() - if (world.getTotalWorldTime % Settings.get.tickFrequency == 0) { - if (isActive && output.isEmpty) { - val totalVolume = data.stateOn.foldLeft(0)((acc, shape) => acc + shape.bounds.volume) + data.stateOff.foldLeft(0)((acc, shape) => acc + shape.bounds.volume) - val totalSurface = data.stateOn.foldLeft(0)((acc, shape) => acc + shape.bounds.surface) + data.stateOff.foldLeft(0)((acc, shape) => acc + shape.bounds.surface) - val totalShapes = data.stateOn.size + data.stateOff.size - // TODO Consume plastic (totalVolume) and ink (totalSurface). + if (isActive && output.isEmpty) { + val totalVolume = data.stateOn.foldLeft(0)((acc, shape) => acc + shape.bounds.volume) + data.stateOff.foldLeft(0)((acc, shape) => acc + shape.bounds.volume) + val totalSurface = data.stateOn.foldLeft(0)((acc, shape) => acc + shape.bounds.surface) + data.stateOff.foldLeft(0)((acc, shape) => acc + shape.bounds.surface) + val totalShapes = data.stateOn.size + data.stateOff.size + + if (totalVolume == 0) { + isActive = false + } + else { + val plasticRequired = totalVolume + val inkRequired = (totalSurface / 6) max 1 + totalRequiredEnergy = totalShapes * Settings.get.printShapeCost requiredEnergy = totalRequiredEnergy - output = Option(data.createItemStack()) - // ServerPacketSender.sendRobotAssembling(this, assembling = true) - } - if (output.isDefined) { - val want = math.max(1, math.min(requiredEnergy, Settings.get.assemblerTickAmount * Settings.get.tickFrequency)) - val success = Settings.get.ignorePower || node.tryChangeBuffer(-want) - if (success) { - requiredEnergy -= want + if (amountPlastic >= plasticRequired && amountInk >= inkRequired) { + amountPlastic -= plasticRequired + amountInk -= inkRequired + output = Option(data.createItemStack()) + ServerPacketSender.sendPrinting(this, printing = true) } - if (requiredEnergy <= 0) { - val result = getStackInSlot(slotOutput) - if (result == null) { - setInventorySlotContents(slotOutput, output.get) - } - else if (output.get.isItemEqual(result) && ItemStack.areItemStackTagsEqual(output.get, result) && result.stackSize < result.getMaxStackSize) { - result.stackSize += 1 - markDirty() - } - else { - return - } - requiredEnergy = 0 - output = None + } + } + + if (output.isDefined) { + val want = math.max(1, math.min(requiredEnergy, Settings.get.printerTickAmount)) + val success = Settings.get.ignorePower || node.tryChangeBuffer(-want) + if (success) { + requiredEnergy -= want + } + if (requiredEnergy <= 0) { + val result = getStackInSlot(slotOutput) + if (result == null) { + setInventorySlotContents(slotOutput, output.get) } - // ServerPacketSender.sendRobotAssembling(this, success && output.isDefined) + else if (output.get.isItemEqual(result) && ItemStack.areItemStackTagsEqual(output.get, result) && result.stackSize < result.getMaxStackSize) { + result.stackSize += 1 + markDirty() + } + else { + return + } + requiredEnergy = 0 + output = None + } + ServerPacketSender.sendPrinting(this, success && output.isDefined) + } + + if (maxAmountPlastic - amountPlastic >= plasticPerItem) { + val plastic = decrStackSize(slotPlastic, 1) + if (plastic != null) { + amountPlastic += plasticPerItem + } + } + + if (maxAmountInk - amountInk >= inkPerCartridge) { + if (api.Items.get(getStackInSlot(slotInk)) == api.Items.get("inkCartridge")) { + setInventorySlotContents(slotInk, api.Items.get("inkCartridgeEmpty").createItemStack(1)) + amountInk += inkPerCartridge } } } override def readFromNBTForServer(nbt: NBTTagCompound) { super.readFromNBTForServer(nbt) - data.load(nbt.getCompoundTag("data")) + amountPlastic = nbt.getInteger(Settings.namespace + "amountPlastic") + amountInk = nbt.getInteger(Settings.namespace + "amountInk") + data.load(nbt.getCompoundTag(Settings.namespace + "data")) isActive = nbt.getBoolean(Settings.namespace + "active") if (nbt.hasKey(Settings.namespace + "output")) { output = Option(ItemUtils.loadStack(nbt.getCompoundTag(Settings.namespace + "output"))) @@ -214,7 +245,9 @@ class Printer extends traits.Environment with traits.PowerAcceptor with traits.I override def writeToNBTForServer(nbt: NBTTagCompound) { super.writeToNBTForServer(nbt) - nbt.setNewCompoundTag("data", data.save) + nbt.setInteger(Settings.namespace + "amountPlastic", amountPlastic) + nbt.setInteger(Settings.namespace + "amountInk", amountInk) + nbt.setNewCompoundTag(Settings.namespace + "data", data.save) nbt.setBoolean(Settings.namespace + "active", isActive) output.foreach(stack => nbt.setNewCompoundTag(Settings.namespace + "output", stack.writeToNBT)) nbt.setDouble(Settings.namespace + "total", totalRequiredEnergy) @@ -240,8 +273,8 @@ class Printer extends traits.Environment with traits.PowerAcceptor with traits.I override def isItemValidForSlot(slot: Int, stack: ItemStack) = if (slot == 0) - true // TODO Plastic + api.Items.get(stack) == api.Items.get("plastic") else if (slot == 1) - true // TODO Color + api.Items.get(stack) == api.Items.get("inkCartridge") else false } diff --git a/src/main/scala/li/cil/oc/server/PacketSender.scala b/src/main/scala/li/cil/oc/server/PacketSender.scala index 68e1df349..17c4278fd 100644 --- a/src/main/scala/li/cil/oc/server/PacketSender.scala +++ b/src/main/scala/li/cil/oc/server/PacketSender.scala @@ -226,6 +226,15 @@ object PacketSender { pb.sendToPlayersNearTileEntity(t) } + def sendPrinting(t: tileentity.Printer, printing: Boolean) { + val pb = new SimplePacketBuilder(PacketType.PrinterState) + + pb.writeTileEntity(t) + pb.writeBoolean(printing) + + pb.sendToPlayersNearHost(t) + } + def sendRaidChange(t: tileentity.Raid) { val pb = new SimplePacketBuilder(PacketType.RaidStateChange) From bdc006d31e3c9b947c2e4d3ccc5226fde5b04f95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Mon, 23 Mar 2015 23:41:07 +0100 Subject: [PATCH 05/17] Redstone logic for printed blocks. --- .../opencomputers/recipes/default.recipes | 4 +- .../cil/oc/client/renderer/block/Print.scala | 2 +- .../scala/li/cil/oc/common/block/Print.scala | 51 ++++++++++++++++--- .../cil/oc/common/block/RedstoneAware.scala | 6 ++- .../cil/oc/common/item/data/PrintData.scala | 6 +-- .../li/cil/oc/common/tileentity/Print.scala | 49 ++++++++++++++++-- .../li/cil/oc/common/tileentity/Printer.scala | 33 ++++++++++-- .../tileentity/traits/RedstoneAware.scala | 2 +- 8 files changed, 129 insertions(+), 24 deletions(-) diff --git a/src/main/resources/assets/opencomputers/recipes/default.recipes b/src/main/resources/assets/opencomputers/recipes/default.recipes index b85a2a94b..e65e75f70 100644 --- a/src/main/resources/assets/opencomputers/recipes/default.recipes +++ b/src/main/resources/assets/opencomputers/recipes/default.recipes @@ -319,8 +319,8 @@ disk { ["", nuggetIron, ""]] } plastic { - input: [[gravel, gravel, gravel], - [gravel, {item=coal, subID=1}, gravel], + input: [[gravel, redstone, gravel], + [redstone, {item=coal, subID=1}, redstone], [gravel, water_bucket, gravel]] output: 8 } diff --git a/src/main/scala/li/cil/oc/client/renderer/block/Print.scala b/src/main/scala/li/cil/oc/client/renderer/block/Print.scala index f4bf03c60..d5401d893 100644 --- a/src/main/scala/li/cil/oc/client/renderer/block/Print.scala +++ b/src/main/scala/li/cil/oc/client/renderer/block/Print.scala @@ -8,7 +8,7 @@ import net.minecraft.util.IIcon object Print { def render(print: tileentity.Print, x: Int, y: Int, z: Int, block: Block, renderer: RenderBlocks): Unit = { - for (shape <- print.data.stateOff) { + for (shape <- if (print.state) print.data.stateOn else print.data.stateOff) { renderer.setOverrideBlockTexture(resolveTexture(shape.texture)) renderer.setRenderBounds( shape.bounds.minX, shape.bounds.minY, shape.bounds.minZ, diff --git a/src/main/scala/li/cil/oc/common/block/Print.scala b/src/main/scala/li/cil/oc/common/block/Print.scala index 5fe0b37bc..fd34628c1 100644 --- a/src/main/scala/li/cil/oc/common/block/Print.scala +++ b/src/main/scala/li/cil/oc/common/block/Print.scala @@ -1,12 +1,15 @@ package li.cil.oc.common.block import java.util +import java.util.Random import li.cil.oc.Settings import li.cil.oc.common.item.data.PrintData import li.cil.oc.common.tileentity +import li.cil.oc.integration.util.NEI import li.cil.oc.util.ExtendedAABB import net.minecraft.entity.EntityLivingBase +import net.minecraft.entity.EnumCreatureType import net.minecraft.entity.player.EntityPlayer import net.minecraft.item.ItemStack import net.minecraft.util.MovingObjectPosition @@ -17,10 +20,10 @@ import net.minecraftforge.common.util.ForgeDirection import scala.collection.convert.WrapAsJava._ import scala.reflect.ClassTag -class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends SimpleBlock with traits.SpecialBlock with traits.CustomDrops[tileentity.Print] { +class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends RedstoneAware with traits.SpecialBlock with traits.CustomDrops[tileentity.Print] { setLightOpacity(0) - // setCreativeTab(null) - // NEI.hide(this) + setCreativeTab(null) + NEI.hide(this) setBlockTextureName(Settings.resourceDomain + "GenericTop") override protected def tooltipBody(metadata: Int, stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean): Unit = { @@ -31,9 +34,27 @@ class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends override def shouldSideBeRendered(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = true - override def isBlockSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = true + override def isBlockSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = isSideSolid(world, x, y, z, side) - override def isSideSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = false + override def isSideSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = { + world.getTileEntity(x, y, z) match { + case print: tileentity.Print => + val bounds = if (print.state) print.boundsOn else print.boundsOff + val fullX = bounds.minX == 0 && bounds.maxX == 1 + val fullY = bounds.minY == 0 && bounds.maxY == 1 + val fullZ = bounds.minZ == 0 && bounds.maxZ == 1 + side match { + case ForgeDirection.DOWN => bounds.minY == 0 && fullX && fullZ + case ForgeDirection.UP => bounds.maxY == 1 && fullX && fullZ + case ForgeDirection.NORTH => bounds.minZ == 0 && fullX && fullY + case ForgeDirection.SOUTH => bounds.maxZ == 1 && fullX && fullY + case ForgeDirection.WEST => bounds.minX == 0 && fullY && fullZ + case ForgeDirection.EAST => bounds.minX == 1 && fullY && fullZ + case _ => false + } + case _ => super.isSideSolid(world, x, y, z, side) + } + } override def getPickBlock(target: MovingObjectPosition, world: World, x: Int, y: Int, z: Int, player: EntityPlayer): ItemStack = { world.getTileEntity(x, y, z) match { @@ -53,6 +74,17 @@ class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends setBlockBounds(ExtendedAABB.unitBounds) } + override def canCreatureSpawn(creature: EnumCreatureType, world: IBlockAccess, x: Int, y: Int, z: Int): Boolean = true + + override def tickRate(world: World) = 20 + + override def updateTick(world: World, x: Int, y: Int, z: Int, rng: Random): Unit = { + if (!world.isRemote) world.getTileEntity(x, y, z) match { + case print: tileentity.Print => if (print.state) print.toggleState() + case _ => + } + } + // ----------------------------------------------------------------------- // override def hasTileEntity(metadata: Int) = true @@ -61,10 +93,17 @@ class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends // ----------------------------------------------------------------------- // + override def onBlockActivated(world: World, x: Int, y: Int, z: Int, player: EntityPlayer, side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float): Boolean = { + world.getTileEntity(x, y, z) match { + case print: tileentity.Print => print.activate() + case _ => super.onBlockActivated(world, x, y, z, player, side, hitX, hitY, hitZ) + } + } + override protected def doCustomInit(tileEntity: tileentity.Print, player: EntityLivingBase, stack: ItemStack): Unit = { super.doCustomInit(tileEntity, player, stack) tileEntity.data.load(stack) - tileEntity.updateBounds() + tileEntity.updateFromData() } override protected def doCustomDrops(tileEntity: tileentity.Print, player: EntityPlayer, willHarvest: Boolean): Unit = { diff --git a/src/main/scala/li/cil/oc/common/block/RedstoneAware.scala b/src/main/scala/li/cil/oc/common/block/RedstoneAware.scala index e7f34c0fc..99c8c6175 100644 --- a/src/main/scala/li/cil/oc/common/block/RedstoneAware.scala +++ b/src/main/scala/li/cil/oc/common/block/RedstoneAware.scala @@ -51,7 +51,11 @@ abstract class RedstoneAware extends SimpleBlock with IRedNetOmniNode { } } world.getTileEntity(x, y, z) match { - case redstone: tileentity.traits.RedstoneAware => redstone.checkRedstoneInputChanged() + case redstone: tileentity.traits.RedstoneAware => + if (redstone.canUpdate) + redstone.checkRedstoneInputChanged() + else + ForgeDirection.VALID_DIRECTIONS.foreach(redstone.updateRedstoneInput) case _ => // Ignore. } } diff --git a/src/main/scala/li/cil/oc/common/item/data/PrintData.scala b/src/main/scala/li/cil/oc/common/item/data/PrintData.scala index b9eefd4f9..e58293e1d 100644 --- a/src/main/scala/li/cil/oc/common/item/data/PrintData.scala +++ b/src/main/scala/li/cil/oc/common/item/data/PrintData.scala @@ -17,7 +17,7 @@ class PrintData extends ItemData { var label: Option[String] = None var tooltip: Option[String] = None - var autoRevert = false + var isButtonMode = false var emitRedstone = false var pressurePlate = false val stateOff = mutable.Set.empty[PrintData.Shape] @@ -26,7 +26,7 @@ class PrintData extends ItemData { override def load(nbt: NBTTagCompound): Unit = { if (nbt.hasKey("label")) label = Option(nbt.getString("label")) if (nbt.hasKey("tooltip")) tooltip = Option(nbt.getString("tooltip")) - autoRevert = nbt.getBoolean("autoRevert") + isButtonMode = nbt.getBoolean("isButtonMode") emitRedstone = nbt.getBoolean("emitRedstone") pressurePlate = nbt.getBoolean("pressurePlate") stateOff ++= nbt.getTagList("stateOff", NBT.TAG_COMPOUND).map(PrintData.nbtToShape) @@ -36,7 +36,7 @@ class PrintData extends ItemData { override def save(nbt: NBTTagCompound): Unit = { label.foreach(nbt.setString("label", _)) tooltip.foreach(nbt.setString("tooltip", _)) - nbt.setBoolean("autoRevert", autoRevert) + nbt.setBoolean("isButtonMode", isButtonMode) nbt.setBoolean("emitRedstone", emitRedstone) nbt.setBoolean("pressurePlate", pressurePlate) nbt.setNewTagList("stateOff", stateOff.map(PrintData.shapeToNBT)) diff --git a/src/main/scala/li/cil/oc/common/tileentity/Print.scala b/src/main/scala/li/cil/oc/common/tileentity/Print.scala index 7b1973f21..65317091d 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Print.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Print.scala @@ -7,40 +7,79 @@ import li.cil.oc.util.ExtendedAABB import li.cil.oc.util.ExtendedAABB._ import li.cil.oc.util.ExtendedNBT._ import net.minecraft.nbt.NBTTagCompound +import net.minecraftforge.common.util.ForgeDirection -class Print extends traits.TileEntity { +class Print extends traits.TileEntity with traits.RedstoneAware { val data = new PrintData() var boundsOff = ExtendedAABB.unitBounds var boundsOn = ExtendedAABB.unitBounds var state = false - override def canUpdate: Boolean = false + _isOutputEnabled = true + + def activate(): Boolean = { + if (data.stateOn.size > 0) { + if (!state || !data.isButtonMode) { + toggleState() + return true + } + } + false + } + + def toggleState(): Unit = { + state = !state + world.playSoundEffect(x + 0.5, y + 0.5, z + 0.5, "random.click", 0.3F, if (state) 0.6F else 0.5F) + world.markBlockForUpdate(x, y, z) + if (data.emitRedstone) { + ForgeDirection.VALID_DIRECTIONS.foreach(output(_, if (state) 15 else 0)) + } + if (state && data.isButtonMode) { + world.scheduleBlockUpdate(x, y, z, block, block.tickRate(world)) + } + } + + override def canUpdate = false + + override protected def onRedstoneInputChanged(side: ForgeDirection, oldMaxValue: Int, newMaxValue: Int): Unit = { + super.onRedstoneInputChanged(side, oldMaxValue, newMaxValue) + if (!data.emitRedstone) { + state = newMaxValue > 0 + world.playSoundEffect(x + 0.5, y + 0.5, z + 0.5, "random.click", 0.3F, if (state) 0.6F else 0.5F) + world.markBlockForUpdate(x, y, z) + } + } override def readFromNBTForServer(nbt: NBTTagCompound): Unit = { super.readFromNBTForServer(nbt) data.load(nbt.getCompoundTag("data")) - updateBounds() + state = nbt.getBoolean("state") + updateFromData() } override def writeToNBTForServer(nbt: NBTTagCompound): Unit = { super.writeToNBTForServer(nbt) nbt.setNewCompoundTag("data", data.save) + nbt.setBoolean("state", state) } @SideOnly(Side.CLIENT) override def readFromNBTForClient(nbt: NBTTagCompound): Unit = { super.readFromNBTForClient(nbt) data.load(nbt.getCompoundTag("data")) - updateBounds() + state = nbt.getBoolean("state") + updateFromData() + world.markBlockForUpdate(x, y, z) } override def writeToNBTForClient(nbt: NBTTagCompound): Unit = { super.writeToNBTForClient(nbt) nbt.setNewCompoundTag("data", data.save) + nbt.setBoolean("state", state) } - def updateBounds(): Unit = { + def updateFromData(): Unit = { boundsOff = data.stateOff.drop(1).foldLeft(data.stateOff.headOption.fold(ExtendedAABB.unitBounds)(_.bounds))((a, b) => a.func_111270_a(b.bounds)) if (boundsOff.volume == 0) boundsOff = ExtendedAABB.unitBounds boundsOn = data.stateOn.drop(1).foldLeft(data.stateOn.headOption.fold(ExtendedAABB.unitBounds)(_.bounds))((a, b) => a.func_111270_a(b.bounds)) diff --git a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala index b54aa3cee..883da7a0f 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala @@ -59,10 +59,7 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat // ----------------------------------------------------------------------- // - def canPrint = { - val complexity = data.stateOff.size + data.stateOn.size - complexity > 0 && complexity <= Settings.get.maxPrintComplexity - } + def canPrint = data.stateOff.size > 0 && data.stateOff.size + data.stateOn.size <= Settings.get.maxPrintComplexity def isPrinting = (requiredEnergy > 0 || isActive) && Option(getStackInSlot(slotOutput)).fold(true)(stack => { stack.stackSize < stack.getMaxStackSize && output.fold(true)(ItemStack.areItemStackTagsEqual(stack, _)) @@ -84,6 +81,7 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat @Callback(doc = """function(value:string) -- Set a label for the block being printed.""") def setLabel(context: Context, args: Arguments): Array[Object] = { data.label = Option(args.optString(0, null)).map(_.take(16)) + if (data.label.fold(false)(_.isEmpty)) data.label = None isActive = false // Needs committing. null } @@ -96,6 +94,7 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat @Callback(doc = """function(value:string) -- Set a tooltip for the block being printed.""") def setTooltip(context: Context, args: Arguments): Array[Object] = { data.tooltip = Option(args.optString(0, null)).map(_.take(128)) + if (data.tooltip.fold(false)(_.isEmpty)) data.tooltip = None isActive = false // Needs committing. null } @@ -105,6 +104,30 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat result(data.tooltip.orNull) } + @Callback(doc = """function(value:boolean) -- Set whether the printed block should emit redstone when in its active state.""") + def setRedstoneEmitter(context: Context, args: Arguments): Array[Object] = { + data.emitRedstone = args.checkBoolean(0) + isActive = false // Needs committing. + null + } + + @Callback(doc = """function():boolean -- Get whether the printed block should emit redstone when in its active state.""") + def isRedstoneEmitter(context: Context, args: Arguments): Array[Object] = { + result(data.emitRedstone) + } + + @Callback(doc = """function(value:boolean) -- Set whether the printed block should automatically return to its off state.""") + def setButtonMode(context: Context, args: Arguments): Array[Object] = { + data.isButtonMode = args.checkBoolean(0) + isActive = false // Needs committing. + null + } + + @Callback(doc = """function():boolean -- Get whether the printed block should automatically return to its off state.""") + def isButtonMode(context: Context, args: Arguments): Array[Object] = { + result(data.isButtonMode) + } + @Callback(doc = """function(minX:number, minY:number, minZ:number, maxX:number, maxY:number, maxZ:number, texture:string[, state:boolean=false]) -- Adds a shape to the printers configuration, optionally specifying whether it is for the off or on state.""") def addShape(context: Context, args: Arguments): Array[Object] = { if (data.stateOff.size + data.stateOn.size >= Settings.get.maxPrintComplexity) { @@ -117,7 +140,7 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat val maxY = (args.checkInteger(4) max 0 min 16) / 16f val maxZ = (args.checkInteger(5) max 0 min 16) / 16f val texture = args.checkString(6) - val state = args.optBoolean(7, false) + val state = args.checkAny(7) != null && args.optBoolean(7, false) if (minX == maxX) throw new IllegalArgumentException("empty block") if (minY == maxY) throw new IllegalArgumentException("empty block") diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/RedstoneAware.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/RedstoneAware.scala index f9e3c4d68..2f38a5651 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/traits/RedstoneAware.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/traits/RedstoneAware.scala @@ -75,7 +75,7 @@ trait RedstoneAware extends RotationAware with IConnectable with IRedstoneEmitte } } - protected def updateRedstoneInput(side: ForgeDirection) { + def updateRedstoneInput(side: ForgeDirection) { val oldInput = _input(side.ordinal()) val newInput = computeInput(side) _input(side.ordinal()) = newInput From d45cc724b53a9bdd34883ff4d74e8762ce88b02d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 24 Mar 2015 00:03:01 +0100 Subject: [PATCH 06/17] Refactoring. --- assets/items.psd | Bin 583622 -> 584048 bytes .../assets/opencomputers/lang/en_US.lang | 6 ++-- .../opencomputers/recipes/default.recipes | 2 +- ...inter_plastic.png => printer_material.png} | Bin .../textures/items/Chamelium.png | Bin 0 -> 313 bytes .../opencomputers/textures/items/Plastic.png | Bin 316 -> 0 bytes .../scala/li/cil/oc/client/Textures.scala | 2 +- .../scala/li/cil/oc/client/gui/Printer.scala | 10 +++--- .../li/cil/oc/common/container/Printer.scala | 10 +++--- .../scala/li/cil/oc/common/init/Items.scala | 2 +- .../li/cil/oc/common/item/Chamelium.scala | 3 ++ .../scala/li/cil/oc/common/item/Plastic.scala | 3 -- .../li/cil/oc/common/tileentity/Printer.scala | 33 +++++++++--------- 13 files changed, 36 insertions(+), 35 deletions(-) rename src/main/resources/assets/opencomputers/textures/gui/{printer_plastic.png => printer_material.png} (100%) create mode 100644 src/main/resources/assets/opencomputers/textures/items/Chamelium.png delete mode 100644 src/main/resources/assets/opencomputers/textures/items/Plastic.png create mode 100644 src/main/scala/li/cil/oc/common/item/Chamelium.scala delete mode 100644 src/main/scala/li/cil/oc/common/item/Plastic.scala diff --git a/assets/items.psd b/assets/items.psd index 9eaa421ece300068932778eed3f24445ca692638..3ac63c947e14d403369751e7070c0a1e4c9698e9 100644 GIT binary patch delta 2426 zcmZvbeN+=y8pdZP$=rb^1f(u!cT1zeGHcrYhzlrYPy^XS+=b>266q^ zDrlf-v2L}s#N)*eu(XG=c1>+b%h)3F&$b6YLSWspR*$7>6wx+x&rwv?%ngH!|qdM52&bPB;iB@e;9;C@0ntPMF%?c7(c~-K%!~Lh;V)q!vEDh)Rj+Um;3nx&NxDbpO`7%>sF3vTxPRd%Y^7fM{Zn%Cr4sE)kC$yQjo zj7lSCh;J^VR;XRVrk!8TU#`qfC>6iG>Uv>#WV3HLoZfXlZ)ENMLlxJ)SU<4y%sI_%zBwp~ zja%0>3Mq$|wp}>h(EEM*vg6;Kb+B7ZyIr>T8wa%W$TqJC%|mDbLWPLOD!IyvH9QZOpQLNGJ(yapkur|wtvtMSlCIYJ zLzrS5VVs|bZa-bB4k13w5xm5adDlT~m`8ZWNjwTcu7}pELx2y-wR|`vmiEw| zKWe>Rsh#ThSD9o+?Mzz`QhH#}U?$lfaGK4=HjGSquu$u5Ycrb7Z${PXjec9A}d( zD&A(ZSn?$fwoU_XEvw@!7CR<j+lTk!%nyVSz~<46_LD zbP|h#@I4mj)j_}px$yZVIOl4qO1{gt6E;9B}$Y@M5AvaW`>r$3^g} z#)0YyIc*e98=M>jE=^3>U~>?AH7;w}mq1-y*1o!gg|XR!&tC>LYChq9vf%fZK~*Y_ z3$o(H-$CJ=JC7kfl@53O0478CATX=sc)??XV3rCC2_7o006ocznO8tyv7*duhPR$# z3@RIia|0hYG1i2!z!;72H52nlsVqvF+d08bV0sgL#c~XT>2o{zX zGJ28~w-qw&(V^zh`P{7`j` cF+(LbF@GK#YIPGcdu%9glRQ*!6EiaZXZX9%FaQ7m delta 2374 zcmZXT4Nw&48OL|`xZOR3I|LaWTWjK};ilQcZ1}h%MBsFZ1UR8rJoS!p;8zpzGW3wq zBisi}NZPbSb4lM4Q_;jWnqaKC$ad1XIJCBiyP;F#1D{>mJO1T- zW5(C)2bpToLZ#?NZ&XiBkP&w*Ba)R;p!|)lNomo%9(y!;gDD+|{EnuhmyRMnL-UnV zPoxqAR)5jfuTG?pRngK(BW+-b8lstKBz#0G@f@)(vg5xFlsiUdphE^K1FeLam@rT; zlU*S!hA^3tN11Anx0ZTW%+I6VBPmm@_|JUmS&B5Fy&scV=vF=zM))i&kg&mH{wOSf zpC-4GDDWheNtql7$|LB|I6J}!Wto!?{o~pR#;NrYWN`zfqQ_Uw`%JQS?i891t1JyQt3%6Pz9$87P%2*Uu|0!t-&;upzH7jHim{9~iOcj8KNGdH<@ z;C+qx$A2rBS^ef`CzhW4kvZQx(bB(HMjveGnRp_Wd-^=OF26B!EvI$V=3aigYFn#3 z`Rcl?50n1j%0%?BedpqF|J?s=%p8KTlwEWtL-2R`AlF@jue^%4l;nusipbCQ027Q7R zy)#U|XoyLmf~;ufm=$pe+LI<>Ytl?uWix4&P;Y`ROp}sU3~#U)meAi5^nx^ru}W&M zH7SXyr|5`dnpC&!nj+P2WTr@MnbG5NITTXYj7(()kaD*pSEPpwOd5f5^-jVcT_v{A0*W2I*?N5uCkiNX! zE4#I8yk57vRxU@iiJw#ptylfZ~kBc6&1@Rf5IHap=*I0xF2{`)?h=yD{#?IE*={QoAe`qs$r5 z;gA9fREtGvgFXv~%EBrrP(fBSV~j)bFw+E}xTKNbWFyH*sHl^%0x1r|8!QH-f}JWU zPLh;f4oDsBWPa1Ad8MHN)m>(CwJj7x4*m2pQ>MF{HK!AeTxRN1oto*Gp`t6ywsa>B z5NgCIh!{G0g$brVkT6s^4s0F@*oASX`&$8f;VKkULeV?KweQ-H2AGW~Y(8qmjlU8*n Z`pzDsy$d{Qv)d{iBNUKof*Yg8YJkTvWjDX#aj8plr3Li(^Q| zt(fzXLPr!hST49ZT+EsLJHBj|#mZAh^nX8OvWVyY{_OH^VV9KoMUCIueF@v+W|6 s&TQT&^346U<_~$k3jgZ$>lv6C=BjapJg+UE4Ri*Br>mdKI;Vst0J3p?tpET3 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/opencomputers/textures/items/Plastic.png b/src/main/resources/assets/opencomputers/textures/items/Plastic.png deleted file mode 100644 index 914588f6b48eb3be3830a4a60542384f5862057d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 316 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!fo%K)DcS4$&ZJq_jJyo7`pzwlsJPd6J^CySK$fV!%j_-Mb- zK-btvpTgXv#2CMcea&r6WgTs`E0@pz|NsBq{(JdALxf9${DOg8G{CT__6`S7y2{hV zF{I*F%=yK%i(##NymOIXTXVmmhPKCL- 0 || isActive) && Option(getStackInSlot(slotOutput)).fold(true)(stack => { stack.stackSize < stack.getMaxStackSize && output.fold(true)(ItemStack.areItemStackTagsEqual(stack, _)) - }) + }) && (output.isDefined || (amountMaterial > 0 && amountInk > 0)) def progress = (1 - requiredEnergy / totalRequiredEnergy) * 100 @@ -190,23 +190,24 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat override def updateEntity() { super.updateEntity() - if (isActive && output.isEmpty) { + if (isActive && output.isEmpty && Option(getStackInSlot(slotOutput)).fold(true)(stack => stack.stackSize < stack.getMaxStackSize)) { val totalVolume = data.stateOn.foldLeft(0)((acc, shape) => acc + shape.bounds.volume) + data.stateOff.foldLeft(0)((acc, shape) => acc + shape.bounds.volume) val totalSurface = data.stateOn.foldLeft(0)((acc, shape) => acc + shape.bounds.surface) + data.stateOff.foldLeft(0)((acc, shape) => acc + shape.bounds.surface) val totalShapes = data.stateOn.size + data.stateOff.size if (totalVolume == 0) { isActive = false + data = new PrintData() } else { - val plasticRequired = totalVolume + val materialRequired = totalVolume val inkRequired = (totalSurface / 6) max 1 totalRequiredEnergy = totalShapes * Settings.get.printShapeCost requiredEnergy = totalRequiredEnergy - if (amountPlastic >= plasticRequired && amountInk >= inkRequired) { - amountPlastic -= plasticRequired + if (amountMaterial >= materialRequired && amountInk >= inkRequired) { + amountMaterial -= materialRequired amountInk -= inkRequired output = Option(data.createItemStack()) ServerPacketSender.sendPrinting(this, printing = true) @@ -238,10 +239,10 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat ServerPacketSender.sendPrinting(this, success && output.isDefined) } - if (maxAmountPlastic - amountPlastic >= plasticPerItem) { - val plastic = decrStackSize(slotPlastic, 1) - if (plastic != null) { - amountPlastic += plasticPerItem + if (maxAmountMaterial - amountMaterial >= materialPerItem) { + val material = decrStackSize(slotMaterial, 1) + if (material != null) { + amountMaterial += materialPerItem } } @@ -255,7 +256,7 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat override def readFromNBTForServer(nbt: NBTTagCompound) { super.readFromNBTForServer(nbt) - amountPlastic = nbt.getInteger(Settings.namespace + "amountPlastic") + amountMaterial = nbt.getInteger(Settings.namespace + "amountMaterial") amountInk = nbt.getInteger(Settings.namespace + "amountInk") data.load(nbt.getCompoundTag(Settings.namespace + "data")) isActive = nbt.getBoolean(Settings.namespace + "active") @@ -268,7 +269,7 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat override def writeToNBTForServer(nbt: NBTTagCompound) { super.writeToNBTForServer(nbt) - nbt.setInteger(Settings.namespace + "amountPlastic", amountPlastic) + nbt.setInteger(Settings.namespace + "amountMaterial", amountMaterial) nbt.setInteger(Settings.namespace + "amountInk", amountInk) nbt.setNewCompoundTag(Settings.namespace + "data", data.save) nbt.setBoolean(Settings.namespace + "active", isActive) @@ -296,7 +297,7 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat override def isItemValidForSlot(slot: Int, stack: ItemStack) = if (slot == 0) - api.Items.get(stack) == api.Items.get("plastic") + api.Items.get(stack) == api.Items.get("chamelium") else if (slot == 1) api.Items.get(stack) == api.Items.get("inkCartridge") else false From 3625626fe5f768e0a7c4d7188f891aa457d49d09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 24 Mar 2015 01:31:34 +0100 Subject: [PATCH 07/17] Textures and model for printer, nicer rendering. Inventory and item entity rendering for prints. --- assets/blocks.psd | Bin 158404 -> 161532 bytes .../textures/blocks/PrinterSide.png | Bin 0 -> 509 bytes .../textures/blocks/PrinterTop.png | Bin 0 -> 365 bytes src/main/scala/li/cil/oc/client/Proxy.scala | 2 + .../client/renderer/block/BlockRenderer.scala | 18 ++- .../cil/oc/client/renderer/block/Print.scala | 2 +- .../oc/client/renderer/block/Printer.scala | 68 ++++++++++++ .../client/renderer/item/ItemRenderer.scala | 104 +++++++++++++++++- .../renderer/tileentity/PrinterRenderer.scala | 46 ++++++++ .../li/cil/oc/common/block/Printer.scala | 10 +- .../cil/oc/common/item/data/PrintData.scala | 6 +- .../li/cil/oc/common/tileentity/Printer.scala | 6 +- 12 files changed, 250 insertions(+), 12 deletions(-) create mode 100644 src/main/resources/assets/opencomputers/textures/blocks/PrinterSide.png create mode 100644 src/main/resources/assets/opencomputers/textures/blocks/PrinterTop.png create mode 100644 src/main/scala/li/cil/oc/client/renderer/block/Printer.scala create mode 100644 src/main/scala/li/cil/oc/client/renderer/tileentity/PrinterRenderer.scala diff --git a/assets/blocks.psd b/assets/blocks.psd index b66def3a9678b7c6d04f60e96ca2d19e3ea6ed10..396012a4db77ce85835afe35c57a5b2a34a7e2af 100644 GIT binary patch delta 2259 zcmd^7Uu;uV7{BMX>$cmK{z2P&hb3jgy0&g~yX*dRirAGYVfNmh+ir=@xCOj07-KS( z&Ih{5%cc@t4($nIbeS;(Gi38VG(2ny8YK&Zpc!r^g7_!+LPUfui`(kC9VDW`7i0F| zcm93nJHPY$zVm(Ov&r1~Yq@VaR(w2P71;cwR!gb!OMl6g{zr3=5v+XR>l?>MJCB@T zkLi23`uDn4WMFGmRR2k31GolEzG5$5Tvi_Odi|w7(ov13;%`Q!M-$UHs_H6BYx&BG zKv}SKQ+a7=psKF=vC7&&byZ!k((B_DE_?VXl(zS-{%0H-G5Cys@r(9Y&!F$JbjtY_ zW0^^FLk*E)C@P&1WeRzK;hjwMw0Z)9iaAjOkRy?c>XUjfh+2{f)R8oxnWPz*lpOqp zW!>rwK2OEdz3L@0Ot*)ZqBN?#O}Tl@LN|TydVgkgV%N0fer_9j+J5u!=()~!Q?t@^ z?FTPBa&{!yxb>|~ZF?^4DDG^UxIC7y`j1xs@YP82qv6`2UHf0FIQe1gx4(}!Htl}t zDl>JlaqGt22lsusgYpgVvrtm@4`q`)`@OustlV)Y&r0HWu1Wjy#)T3zIJ$F5F^!2i z$`l2ZA!-mcpS9!1bAU~Gd#ooP3FqyKe|ja*1)a|bSI(g|XZ*^+Z!T$ZI0m|uA1}{i z*UF=0`E;is_*Mc%_$KKX<^!(NPvOB1~R4dhv zF3nhJuo?$qpiigzmF7|xVt{7=gIkQihaSFFlX~$0u$ghQ5oF>1Lm-xUMCz3UnDF3k zH|@u7oC3|+vUOIbc^Nl<3ZB3lP6PSgmK4EA-N`ASGvtvH=TToaG_8Xh9goGhC;9*!rDZO#jFaME%q?Sie^Sn8WBC?3bP!v z=q1<)!(vF(yCKI(W=1R&VL0TH7*~YjpqY`v5`-`+Fh!8F2^PI5L@lct1jx9z#0i0! z35k(>cUU!qZG?~^w*@Ff!>R)k03*1B1}W+$=a9992th;;B*LjLg86KNMU6*|NY6M$ zmW8W|obDpG=OLHdc6ZR Qh^wDq88e_$KLN-60X(8);{X5v delta 683 zcmezKmh;F}&It;9`)n+nJbhVM7(n3pM7@WT#TkWVo_V*d?bYpB>p53P@=Rv#0Tf%=(2;vJhWtQKObfBb&mneyDf(#Eu7(thX=iViXsg{NNhv!*JRVB(o>aF|hOdRG9G6PVZzWO*u2zgEnoHvO^{lj`*Uj!d_w XU$lg<A&LXF_~V^r=2d6U^+JQy4%w8 z-w&rHikY;Bz6!n>dTYt4WnD*>Jf0cV_4%uJgRFIXdug`%%^X`{OJ;4R#;_-sCugv# xoDKAh44Hbz?rC)7gapOfx8@8S^X-{<81@zMyBQ|#hzEL%!PC{xWt~$(69CgPqm=*v literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/opencomputers/textures/blocks/PrinterTop.png b/src/main/resources/assets/opencomputers/textures/blocks/PrinterTop.png new file mode 100644 index 0000000000000000000000000000000000000000..afa1ef1def358d185054f2d7186adfe13a5b3fa0 GIT binary patch literal 365 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8kN}?$*Px&vNl8gAE-ncPiGY9re}8{&ZtlRqKtVx4At50@ zKR+!kt>EBbadGjGkPuBx&Ct-$u&^)<4Gnd5btx$+X=!O~ZEaauSsfi6H8r*H@NjQ$ z@7MdcECiar-qXb~q~exN0DB*cB2Tdt&qBYOtN;Ih-g;G1MC5d#j)L?R&qwdrpX{69 z9$j$Uk|oyL(rnSR^F9K$7DqW%=2^N01Rdtzv}>7^?$+k7(GzRU<|%W?+$mz-(6c^c z_tYiZPQ5lM_&as`p;8;ue5LQXrxFu3OuZki#D06r=Cx8>EDs+Vo{9RgjGO<7&P)5q zN71S#>tC-6|NCQB={+$^5s9nM);OXk; Jvd$@?2>=-2ea!#> literal 0 HcmV?d00001 diff --git a/src/main/scala/li/cil/oc/client/Proxy.scala b/src/main/scala/li/cil/oc/client/Proxy.scala index 15c057756..67e9561c0 100644 --- a/src/main/scala/li/cil/oc/client/Proxy.scala +++ b/src/main/scala/li/cil/oc/client/Proxy.scala @@ -58,6 +58,7 @@ private[oc] class Proxy extends CommonProxy { ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Hologram], HologramRendererFallback) ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Microcontroller], MicrocontrollerRenderer) ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.PowerDistributor], PowerDistributorRenderer) + ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Printer], PrinterRenderer) ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Raid], RaidRenderer) ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.ServerRack], ServerRackRenderer) ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Switch], SwitchRenderer) @@ -66,6 +67,7 @@ private[oc] class Proxy extends CommonProxy { ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Screen], ScreenRenderer) MinecraftForgeClient.registerItemRenderer(Items.multi, ItemRenderer) + MinecraftForgeClient.registerItemRenderer(Items.get("print").createItemStack(1).getItem, ItemRenderer) ClientRegistry.registerKeyBinding(KeyBindings.materialCosts) ClientRegistry.registerKeyBinding(KeyBindings.clipboardPaste) diff --git a/src/main/scala/li/cil/oc/client/renderer/block/BlockRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/block/BlockRenderer.scala index 1181198aa..7a78eb8e6 100644 --- a/src/main/scala/li/cil/oc/client/renderer/block/BlockRenderer.scala +++ b/src/main/scala/li/cil/oc/client/renderer/block/BlockRenderer.scala @@ -53,6 +53,13 @@ object BlockRenderer extends ISimpleBlockRenderingHandler { Tessellator.instance.draw() RenderState.checkError(getClass.getName + ".renderInventoryBlock: hologram") + case printer: Printer => + GL11.glTranslatef(-0.5f, -0.5f, -0.5f) + Tessellator.instance.startDrawingQuads() + Printer.render(block, metadata, renderer) + Tessellator.instance.draw() + + RenderState.checkError(getClass.getName + ".renderInventoryBlock: printer") case _ => block match { case simple: SimpleBlock => @@ -81,7 +88,7 @@ object BlockRenderer extends ISimpleBlockRenderingHandler { override def renderWorldBlock(world: IBlockAccess, x: Int, y: Int, z: Int, block: Block, modelId: Int, realRenderer: RenderBlocks) = { RenderState.checkError(getClass.getName + ".renderWorldBlock: entering (aka: wasntme)") - val renderer = patchedRenderer(realRenderer) + val renderer = patchedRenderer(realRenderer, block) world.getTileEntity(x, y, z) match { case cable: tileentity.Cable => Cable.render(world, x, y, z, block, renderer) @@ -100,6 +107,12 @@ object BlockRenderer extends ISimpleBlockRenderingHandler { RenderState.checkError(getClass.getName + ".renderWorldBlock: print") + true + case printer: tileentity.Printer => + Printer.render(block, x, y, z, renderer) + + RenderState.checkError(getClass.getName + ".renderWorldBlock: printer") + true case rack: tileentity.ServerRack => ServerRack.render(rack, x, y, z, block, renderer) @@ -130,7 +143,8 @@ object BlockRenderer extends ISimpleBlockRenderingHandler { val isOneSevenTwo = Loader.instance.getMinecraftModContainer.getVersion == "1.7.2" - def patchedRenderer(renderer: RenderBlocks) = if (isOneSevenTwo) { + // I can't be bothered to adjust the screen rendering logic... so special case ahoy. + def patchedRenderer(renderer: RenderBlocks, block: Block) = if (!block.isInstanceOf[Screen]) { PatchedRenderBlocks.blockAccess = renderer.blockAccess PatchedRenderBlocks.overrideBlockTexture = renderer.overrideBlockTexture PatchedRenderBlocks.flipTexture = renderer.flipTexture diff --git a/src/main/scala/li/cil/oc/client/renderer/block/Print.scala b/src/main/scala/li/cil/oc/client/renderer/block/Print.scala index d5401d893..524cf96fe 100644 --- a/src/main/scala/li/cil/oc/client/renderer/block/Print.scala +++ b/src/main/scala/li/cil/oc/client/renderer/block/Print.scala @@ -18,7 +18,7 @@ object Print { renderer.clearOverrideBlockTexture() } - private def resolveTexture(name: String): IIcon = + def resolveTexture(name: String): IIcon = Option(Minecraft.getMinecraft.getTextureMapBlocks.getTextureExtry(name)). getOrElse(Minecraft.getMinecraft.getTextureMapBlocks.getTextureExtry("wool_colored_magenta")) } diff --git a/src/main/scala/li/cil/oc/client/renderer/block/Printer.scala b/src/main/scala/li/cil/oc/client/renderer/block/Printer.scala new file mode 100644 index 000000000..860ff381d --- /dev/null +++ b/src/main/scala/li/cil/oc/client/renderer/block/Printer.scala @@ -0,0 +1,68 @@ +package li.cil.oc.client.renderer.block + +import net.minecraft.block.Block +import net.minecraft.client.renderer.RenderBlocks + +object Printer { + def render(block: Block, x: Int, y: Int, z: Int, renderer: RenderBlocks) { + val previousRenderAllFaces = renderer.renderAllFaces + renderer.renderAllFaces = true + + // Bottom. + renderer.setRenderBounds(0, 0, 0, 1, 8 / 16f, 1) + renderer.renderStandardBlock(block, x, y, z) + // Corners. + renderer.setRenderBounds(0 / 16f, 8 / 16f, 0 / 16f, 3 / 16f, 16 / 16f, 3 / 16f) + renderer.renderStandardBlock(block, x, y, z) + renderer.setRenderBounds(13 / 16f, 8 / 16f, 0 / 16f, 16 / 16f, 16 / 16f, 3 / 16f) + renderer.renderStandardBlock(block, x, y, z) + renderer.setRenderBounds(0 / 16f, 8 / 16f, 13 / 16f, 3 / 16f, 16 / 16f, 16 / 16f) + renderer.renderStandardBlock(block, x, y, z) + renderer.setRenderBounds(13 / 16f, 8 / 16f, 13 / 16f, 16 / 16f, 16 / 16f, 16 / 16f) + renderer.renderStandardBlock(block, x, y, z) + // Top. + renderer.setRenderBounds(3 / 16f, 13 / 16f, 0 / 16f, 13 / 16f, 16 / 16f, 3 / 16f) + renderer.renderStandardBlock(block, x, y, z) + renderer.setRenderBounds(3 / 16f, 13 / 16f, 13 / 16f, 13 / 16f, 16 / 16f, 16 / 16f) + renderer.renderStandardBlock(block, x, y, z) + renderer.setRenderBounds(0 / 16f, 13 / 16f, 3 / 16f, 3 / 16f, 16 / 16f, 13 / 16f) + renderer.renderStandardBlock(block, x, y, z) + renderer.setRenderBounds(13 / 16f, 13 / 16f, 3 / 16f, 16 / 16f, 16 / 16f, 13 / 16f) + renderer.renderStandardBlock(block, x, y, z) + + renderer.renderAllFaces = previousRenderAllFaces + } + + def render(block: Block, metadata: Int, renderer: RenderBlocks) { + // Bottom. + renderer.setRenderBounds(0, 0, 0, 1, 8 / 16f, 1) + renderAllFaces(block, metadata, renderer) + // Corners. + renderer.setRenderBounds(0 / 16f, 8 / 16f, 0 / 16f, 3 / 16f, 16 / 16f, 3 / 16f) + renderAllFaces(block, metadata, renderer) + renderer.setRenderBounds(13 / 16f, 8 / 16f, 0 / 16f, 16 / 16f, 16 / 16f, 3 / 16f) + renderAllFaces(block, metadata, renderer) + renderer.setRenderBounds(0 / 16f, 8 / 16f, 13 / 16f, 3 / 16f, 16 / 16f, 16 / 16f) + renderAllFaces(block, metadata, renderer) + renderer.setRenderBounds(13 / 16f, 8 / 16f, 13 / 16f, 16 / 16f, 16 / 16f, 16 / 16f) + renderAllFaces(block, metadata, renderer) + // Top. + renderer.setRenderBounds(3 / 16f, 13 / 16f, 0 / 16f, 13 / 16f, 16 / 16f, 3 / 16f) + renderAllFaces(block, metadata, renderer) + renderer.setRenderBounds(3 / 16f, 13 / 16f, 13 / 16f, 13 / 16f, 16 / 16f, 16 / 16f) + renderAllFaces(block, metadata, renderer) + renderer.setRenderBounds(0 / 16f, 13 / 16f, 3 / 16f, 3 / 16f, 16 / 16f, 13 / 16f) + renderAllFaces(block, metadata, renderer) + renderer.setRenderBounds(13 / 16f, 13 / 16f, 3 / 16f, 16 / 16f, 16 / 16f, 13 / 16f) + renderAllFaces(block, metadata, renderer) + } + + private def renderAllFaces(block: Block, metadata: Int, renderer: RenderBlocks): Unit = { + BlockRenderer.renderFaceYPos(block, metadata, renderer) + BlockRenderer.renderFaceYNeg(block, metadata, renderer) + BlockRenderer.renderFaceXPos(block, metadata, renderer) + BlockRenderer.renderFaceXNeg(block, metadata, renderer) + BlockRenderer.renderFaceZPos(block, metadata, renderer) + BlockRenderer.renderFaceZNeg(block, metadata, renderer) + } +} diff --git a/src/main/scala/li/cil/oc/client/renderer/item/ItemRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/item/ItemRenderer.scala index 59e8286de..4ed009a97 100644 --- a/src/main/scala/li/cil/oc/client/renderer/item/ItemRenderer.scala +++ b/src/main/scala/li/cil/oc/client/renderer/item/ItemRenderer.scala @@ -4,13 +4,16 @@ import li.cil.oc.Settings import li.cil.oc.api import li.cil.oc.api.detail.ItemInfo import li.cil.oc.client.Textures +import li.cil.oc.client.renderer.block.Print import li.cil.oc.client.renderer.entity.DroneRenderer +import li.cil.oc.common.item.data.PrintData import li.cil.oc.integration.opencomputers.Item import li.cil.oc.util.RenderState import net.minecraft.client.Minecraft import net.minecraft.client.gui.ScaledResolution import net.minecraft.client.renderer.entity.RenderItem import net.minecraft.client.renderer.entity.RenderManager +import net.minecraft.client.renderer.texture.TextureMap import net.minecraft.item.ItemStack import net.minecraft.util.AxisAlignedBB import net.minecraft.util.EnumChatFormatting @@ -32,6 +35,7 @@ object ItemRenderer extends IItemRenderer { lazy val floppy = api.Items.get("floppy") lazy val lootDisk = api.Items.get("lootDisk") + lazy val print = api.Items.get("print") def bounds = AxisAlignedBB.getBoundingBox(-0.1, -0.1, -0.1, 0.1, 0.1, 0.1) @@ -48,11 +52,13 @@ object ItemRenderer extends IItemRenderer { val descriptor = api.Items.get(stack) (renderType == ItemRenderType.EQUIPPED && isUpgrade(api.Items.get(stack))) || (renderType == ItemRenderType.INVENTORY && isFloppy(api.Items.get(stack))) || - ((renderType == ItemRenderType.INVENTORY || renderType == ItemRenderType.ENTITY || renderType == ItemRenderType.EQUIPPED || renderType == ItemRenderType.EQUIPPED_FIRST_PERSON) && descriptor == drone) + ((renderType == ItemRenderType.INVENTORY || renderType == ItemRenderType.ENTITY || renderType == ItemRenderType.EQUIPPED || renderType == ItemRenderType.EQUIPPED_FIRST_PERSON) && descriptor == drone) || + ((renderType == ItemRenderType.INVENTORY || renderType == ItemRenderType.ENTITY || renderType == ItemRenderType.EQUIPPED || renderType == ItemRenderType.EQUIPPED_FIRST_PERSON) && api.Items.get(stack) == print) } override def shouldUseRenderHelper(renderType: ItemRenderType, stack: ItemStack, helper: ItemRendererHelper) = if (renderType == ItemRenderType.ENTITY) true + else if (renderType == ItemRenderType.INVENTORY && api.Items.get(stack) == print) helper == ItemRendererHelper.INVENTORY_BLOCK // Note: it's easier to revert changes introduced by this "helper" than by // the code that applies if no helper is used... else helper == ItemRendererHelper.EQUIPPED_BLOCK @@ -116,6 +122,7 @@ object ItemRenderer extends IItemRenderer { RenderState.checkError("ItemRenderer.renderItem: floppy") } + else if (descriptor == drone) { GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS) GL11.glPushMatrix() @@ -144,6 +151,26 @@ object ItemRenderer extends IItemRenderer { RenderState.checkError("ItemRenderer.renderItem: drone") } + else if (descriptor == print) { + GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS) + GL11.glPushMatrix() + + if (renderType == ItemRenderType.ENTITY) { + GL11.glTranslatef(-0.5f, 0, -0.5f) + } + + val data = new PrintData(stack) + Minecraft.getMinecraft.renderEngine.bindTexture(TextureMap.locationBlocksTexture) + for (shape <- data.stateOff) { + drawShape(shape) + } + + GL11.glPopMatrix() + GL11.glPopAttrib() + + RenderState.checkError("ItemRenderer.renderItem: print") + } + RenderState.checkError("ItemRenderer.renderItem: leaving") } @@ -207,4 +234,79 @@ object ItemRenderer extends IItemRenderer { GL11.glEnd() } + + private def drawShape(shape: PrintData.Shape) { + val bounds = shape.bounds + val texture = Print.resolveTexture(shape.texture) + + GL11.glBegin(GL11.GL_QUADS) + + // Front. + GL11.glNormal3f(0, 0, 1) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(bounds.minY * 16)) + GL11.glVertex3d(bounds.minX, bounds.minY, bounds.maxZ) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(bounds.minY * 16)) + GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.maxZ) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(bounds.maxY * 16)) + GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.maxZ) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(bounds.maxY * 16)) + GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.maxZ) + + // Back. + GL11.glNormal3f(0, 0, -1) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(bounds.minY * 16)) + GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.minZ) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(bounds.minY * 16)) + GL11.glVertex3d(bounds.minX, bounds.minY, bounds.minZ) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(bounds.maxY * 16)) + GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.minZ) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(bounds.maxY * 16)) + GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.minZ) + + // Top. + GL11.glNormal3f(0, 1, 0) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(bounds.maxZ * 16)) + GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.maxZ) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(bounds.minZ * 16)) + GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.minZ) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(bounds.minZ * 16)) + GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.minZ) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(bounds.maxZ * 16)) + GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.maxZ) + + // Bottom. + GL11.glNormal3f(0, -1, 0) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(bounds.maxZ * 16)) + GL11.glVertex3d(bounds.minX, bounds.minY, bounds.maxZ) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(bounds.minZ * 16)) + GL11.glVertex3d(bounds.minX, bounds.minY, bounds.minZ) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(bounds.minZ * 16)) + GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.minZ) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(bounds.maxZ * 16)) + GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.maxZ) + + // Left. + GL11.glNormal3f(1, 0, 0) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxY * 16), texture.getInterpolatedV(bounds.maxZ * 16)) + GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.maxZ) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minY * 16), texture.getInterpolatedV(bounds.maxZ * 16)) + GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.maxZ) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minY * 16), texture.getInterpolatedV(bounds.minZ * 16)) + GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.minZ) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxY * 16), texture.getInterpolatedV(bounds.minZ * 16)) + GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.minZ) + + // Right. + GL11.glNormal3f(-1, 0, 0) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minY * 16), texture.getInterpolatedV(bounds.maxZ * 16)) + GL11.glVertex3d(bounds.minX, bounds.minY, bounds.maxZ) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxY * 16), texture.getInterpolatedV(bounds.maxZ * 16)) + GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.maxZ) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxY * 16), texture.getInterpolatedV(bounds.minZ * 16)) + GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.minZ) + GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minY * 16), texture.getInterpolatedV(bounds.minZ * 16)) + GL11.glVertex3d(bounds.minX, bounds.minY, bounds.minZ) + + GL11.glEnd() + } } diff --git a/src/main/scala/li/cil/oc/client/renderer/tileentity/PrinterRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/tileentity/PrinterRenderer.scala new file mode 100644 index 000000000..5e1c79f92 --- /dev/null +++ b/src/main/scala/li/cil/oc/client/renderer/tileentity/PrinterRenderer.scala @@ -0,0 +1,46 @@ +package li.cil.oc.client.renderer.tileentity + +import li.cil.oc.common.tileentity.Printer +import li.cil.oc.util.RenderState +import net.minecraft.client.renderer.OpenGlHelper +import net.minecraft.client.renderer.entity.RenderItem +import net.minecraft.client.renderer.entity.RenderManager +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer +import net.minecraft.entity.item.EntityItem +import net.minecraft.tileentity.TileEntity +import org.lwjgl.opengl.GL11 + +object PrinterRenderer extends TileEntitySpecialRenderer { + override def renderTileEntityAt(tileEntity: TileEntity, x: Double, y: Double, z: Double, f: Float) { + RenderState.checkError(getClass.getName + ".renderTileEntityAt: entering (aka: wasntme)") + + val printer = tileEntity.asInstanceOf[Printer] + if (printer.data.stateOff.size > 0) { + val stack = printer.data.createItemStack() + + GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS) + GL11.glPushMatrix() + + GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5) + +// GL11.glTranslated(-0.5, -0.5, -0.5) + GL11.glRotated((System.currentTimeMillis() % 20000) / 20000.0 * 360, 0, 1, 0) +// GL11.glTranslated(0.5, 0.5, 0.5) + + val brightness = printer.world.getLightBrightnessForSkyBlocks(printer.x, printer.y, printer.z, 0) + OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, brightness % 65536, brightness / 65536) + + // This is very 'meh', but item frames do it like this, too! + val entity = new EntityItem(printer.world, 0, 0, 0, stack) + entity.hoverStart = 0 + RenderItem.renderInFrame = true + RenderManager.instance.renderEntityWithPosYaw(entity, 0, -0.1, 0, 0, 0) + RenderItem.renderInFrame = false + + GL11.glPopMatrix() + GL11.glPopAttrib() + } + + RenderState.checkError(getClass.getName + ".renderTileEntityAt: leaving") + } +} \ No newline at end of file diff --git a/src/main/scala/li/cil/oc/common/block/Printer.scala b/src/main/scala/li/cil/oc/common/block/Printer.scala index 5f56b939e..1590426fc 100644 --- a/src/main/scala/li/cil/oc/common/block/Printer.scala +++ b/src/main/scala/li/cil/oc/common/block/Printer.scala @@ -12,11 +12,11 @@ import net.minecraftforge.common.util.ForgeDirection class Printer extends SimpleBlock with traits.SpecialBlock with traits.StateAware with traits.GUI { override protected def customTextures = Array( None, - Some("AssemblerTop"), - Some("AssemblerSide"), - Some("AssemblerSide"), - Some("AssemblerSide"), - Some("AssemblerSide") + Some("PrinterTop"), + Some("PrinterSide"), + Some("PrinterSide"), + Some("PrinterSide"), + Some("PrinterSide") ) override def registerBlockIcons(iconRegister: IIconRegister) = { diff --git a/src/main/scala/li/cil/oc/common/item/data/PrintData.scala b/src/main/scala/li/cil/oc/common/item/data/PrintData.scala index e58293e1d..ee9bad962 100644 --- a/src/main/scala/li/cil/oc/common/item/data/PrintData.scala +++ b/src/main/scala/li/cil/oc/common/item/data/PrintData.scala @@ -24,12 +24,14 @@ class PrintData extends ItemData { val stateOn = mutable.Set.empty[PrintData.Shape] override def load(nbt: NBTTagCompound): Unit = { - if (nbt.hasKey("label")) label = Option(nbt.getString("label")) - if (nbt.hasKey("tooltip")) tooltip = Option(nbt.getString("tooltip")) + if (nbt.hasKey("label")) label = Option(nbt.getString("label")) else label = None + if (nbt.hasKey("tooltip")) tooltip = Option(nbt.getString("tooltip")) else tooltip = None isButtonMode = nbt.getBoolean("isButtonMode") emitRedstone = nbt.getBoolean("emitRedstone") pressurePlate = nbt.getBoolean("pressurePlate") + stateOff.clear() stateOff ++= nbt.getTagList("stateOff", NBT.TAG_COMPOUND).map(PrintData.nbtToShape) + stateOn.clear() stateOn ++= nbt.getTagList("stateOn", NBT.TAG_COMPOUND).map(PrintData.nbtToShape) } diff --git a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala index 9fb6ddd60..a8addd318 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala @@ -63,7 +63,7 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat def isPrinting = (requiredEnergy > 0 || isActive) && Option(getStackInSlot(slotOutput)).fold(true)(stack => { stack.stackSize < stack.getMaxStackSize && output.fold(true)(ItemStack.areItemStackTagsEqual(stack, _)) - }) && (output.isDefined || (amountMaterial > 0 && amountInk > 0)) + }) def progress = (1 - requiredEnergy / totalRequiredEnergy) * 100 @@ -156,6 +156,8 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat math.max(maxZ, minZ)), texture) isActive = false // Needs committing. + world.markBlockForUpdate(x, y, z) + result(true) } @@ -281,11 +283,13 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat @SideOnly(Side.CLIENT) override def readFromNBTForClient(nbt: NBTTagCompound) { super.readFromNBTForClient(nbt) + data.load(nbt.getCompoundTag(Settings.namespace + "data")) requiredEnergy = nbt.getDouble("remaining") } override def writeToNBTForClient(nbt: NBTTagCompound) { super.writeToNBTForClient(nbt) + nbt.setNewCompoundTag(Settings.namespace + "data", data.save) nbt.setDouble("remaining", requiredEnergy) } From a906759283dbdba48fce8be41f05b1ab5be5c984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 24 Mar 2015 01:40:58 +0100 Subject: [PATCH 08/17] Cleanup. --- .../scala/li/cil/oc/client/renderer/block/BlockRenderer.scala | 3 --- src/main/scala/li/cil/oc/common/block/Print.scala | 1 + src/main/scala/li/cil/oc/common/block/SimpleBlock.scala | 1 + 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/scala/li/cil/oc/client/renderer/block/BlockRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/block/BlockRenderer.scala index 7a78eb8e6..10e28c2ea 100644 --- a/src/main/scala/li/cil/oc/client/renderer/block/BlockRenderer.scala +++ b/src/main/scala/li/cil/oc/client/renderer/block/BlockRenderer.scala @@ -1,7 +1,6 @@ package li.cil.oc.client.renderer.block import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler -import cpw.mods.fml.common.Loader import li.cil.oc.Settings import li.cil.oc.client.renderer.tileentity.RobotRenderer import li.cil.oc.common.block._ @@ -141,8 +140,6 @@ object BlockRenderer extends ISimpleBlockRenderingHandler { } } - val isOneSevenTwo = Loader.instance.getMinecraftModContainer.getVersion == "1.7.2" - // I can't be bothered to adjust the screen rendering logic... so special case ahoy. def patchedRenderer(renderer: RenderBlocks, block: Block) = if (!block.isInstanceOf[Screen]) { PatchedRenderBlocks.blockAccess = renderer.blockAccess diff --git a/src/main/scala/li/cil/oc/common/block/Print.scala b/src/main/scala/li/cil/oc/common/block/Print.scala index fd34628c1..144511c5b 100644 --- a/src/main/scala/li/cil/oc/common/block/Print.scala +++ b/src/main/scala/li/cil/oc/common/block/Print.scala @@ -22,6 +22,7 @@ import scala.reflect.ClassTag class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends RedstoneAware with traits.SpecialBlock with traits.CustomDrops[tileentity.Print] { setLightOpacity(0) + setHardness(1) setCreativeTab(null) NEI.hide(this) setBlockTextureName(Settings.resourceDomain + "GenericTop") diff --git a/src/main/scala/li/cil/oc/common/block/SimpleBlock.scala b/src/main/scala/li/cil/oc/common/block/SimpleBlock.scala index 6d9ae64bc..02b30d99a 100644 --- a/src/main/scala/li/cil/oc/common/block/SimpleBlock.scala +++ b/src/main/scala/li/cil/oc/common/block/SimpleBlock.scala @@ -27,6 +27,7 @@ import net.minecraftforge.common.util.ForgeDirection class SimpleBlock(material: Material = Material.iron) extends Block(material) { setHardness(2f) + setResistance(5) setCreativeTab(CreativeTab) var showInItemList = true From 495ec3a86921fc9671eb708273357360c5ca5505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 24 Mar 2015 02:39:09 +0100 Subject: [PATCH 09/17] Made prints rotatable around y axis. --- .../cil/oc/client/renderer/block/Print.scala | 6 +++-- .../scala/li/cil/oc/common/block/Print.scala | 2 +- .../li/cil/oc/common/tileentity/Print.scala | 15 ++++++++---- .../scala/li/cil/oc/util/ExtendedAABB.scala | 23 +++++++++++++++++++ 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/main/scala/li/cil/oc/client/renderer/block/Print.scala b/src/main/scala/li/cil/oc/client/renderer/block/Print.scala index 524cf96fe..3b9919ff4 100644 --- a/src/main/scala/li/cil/oc/client/renderer/block/Print.scala +++ b/src/main/scala/li/cil/oc/client/renderer/block/Print.scala @@ -1,6 +1,7 @@ package li.cil.oc.client.renderer.block import li.cil.oc.common.tileentity +import li.cil.oc.util.ExtendedAABB._ import net.minecraft.block.Block import net.minecraft.client.Minecraft import net.minecraft.client.renderer.RenderBlocks @@ -9,10 +10,11 @@ import net.minecraft.util.IIcon object Print { def render(print: tileentity.Print, x: Int, y: Int, z: Int, block: Block, renderer: RenderBlocks): Unit = { for (shape <- if (print.state) print.data.stateOn else print.data.stateOff) { + val bounds = shape.bounds.rotateTowards(print.facing) renderer.setOverrideBlockTexture(resolveTexture(shape.texture)) renderer.setRenderBounds( - shape.bounds.minX, shape.bounds.minY, shape.bounds.minZ, - shape.bounds.maxX, shape.bounds.maxY, shape.bounds.maxZ) + bounds.minX, bounds.minY, bounds.minZ, + bounds.maxX, bounds.maxY, bounds.maxZ) renderer.renderStandardBlock(block, x, y, z) } renderer.clearOverrideBlockTexture() diff --git a/src/main/scala/li/cil/oc/common/block/Print.scala b/src/main/scala/li/cil/oc/common/block/Print.scala index 144511c5b..d35348e35 100644 --- a/src/main/scala/li/cil/oc/common/block/Print.scala +++ b/src/main/scala/li/cil/oc/common/block/Print.scala @@ -104,7 +104,7 @@ class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends override protected def doCustomInit(tileEntity: tileentity.Print, player: EntityLivingBase, stack: ItemStack): Unit = { super.doCustomInit(tileEntity, player, stack) tileEntity.data.load(stack) - tileEntity.updateFromData() + tileEntity.updateBounds() } override protected def doCustomDrops(tileEntity: tileentity.Print, player: EntityPlayer, willHarvest: Boolean): Unit = { diff --git a/src/main/scala/li/cil/oc/common/tileentity/Print.scala b/src/main/scala/li/cil/oc/common/tileentity/Print.scala index 65317091d..7d9535d21 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Print.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Print.scala @@ -9,7 +9,7 @@ import li.cil.oc.util.ExtendedNBT._ import net.minecraft.nbt.NBTTagCompound import net.minecraftforge.common.util.ForgeDirection -class Print extends traits.TileEntity with traits.RedstoneAware { +class Print extends traits.TileEntity with traits.RedstoneAware with traits.Rotatable { val data = new PrintData() var boundsOff = ExtendedAABB.unitBounds @@ -55,7 +55,7 @@ class Print extends traits.TileEntity with traits.RedstoneAware { super.readFromNBTForServer(nbt) data.load(nbt.getCompoundTag("data")) state = nbt.getBoolean("state") - updateFromData() + updateBounds() } override def writeToNBTForServer(nbt: NBTTagCompound): Unit = { @@ -69,7 +69,7 @@ class Print extends traits.TileEntity with traits.RedstoneAware { super.readFromNBTForClient(nbt) data.load(nbt.getCompoundTag("data")) state = nbt.getBoolean("state") - updateFromData() + updateBounds() world.markBlockForUpdate(x, y, z) } @@ -79,10 +79,17 @@ class Print extends traits.TileEntity with traits.RedstoneAware { nbt.setBoolean("state", state) } - def updateFromData(): Unit = { + def updateBounds(): Unit = { boundsOff = data.stateOff.drop(1).foldLeft(data.stateOff.headOption.fold(ExtendedAABB.unitBounds)(_.bounds))((a, b) => a.func_111270_a(b.bounds)) if (boundsOff.volume == 0) boundsOff = ExtendedAABB.unitBounds + else boundsOff = boundsOff.rotateTowards(facing) boundsOn = data.stateOn.drop(1).foldLeft(data.stateOn.headOption.fold(ExtendedAABB.unitBounds)(_.bounds))((a, b) => a.func_111270_a(b.bounds)) if (boundsOn.volume == 0) boundsOn = ExtendedAABB.unitBounds + else boundsOn = boundsOn.rotateTowards(facing) + } + + override protected def onRotationChanged(): Unit = { + super.onRotationChanged() + updateBounds() } } diff --git a/src/main/scala/li/cil/oc/util/ExtendedAABB.scala b/src/main/scala/li/cil/oc/util/ExtendedAABB.scala index 80ec8af81..079b4790a 100644 --- a/src/main/scala/li/cil/oc/util/ExtendedAABB.scala +++ b/src/main/scala/li/cil/oc/util/ExtendedAABB.scala @@ -1,6 +1,8 @@ package li.cil.oc.util import net.minecraft.util.AxisAlignedBB +import net.minecraft.util.Vec3 +import net.minecraftforge.common.util.ForgeDirection import scala.language.implicitConversions @@ -23,6 +25,27 @@ object ExtendedAABB { val sz = ((bounds.maxZ - bounds.minZ) * 16).round.toInt sx * sy * 2 + sx * sz * 2 + sy * sz * 2 } + + def rotateTowards(facing: ForgeDirection) = rotateY(facing match { + case ForgeDirection.WEST => 3 + case ForgeDirection.NORTH => 2 + case ForgeDirection.EAST => 1 + case _ => 0 + }) + + def rotateY(count: Int): AxisAlignedBB = { + val min = Vec3.createVectorHelper(bounds.minX - 0.5, bounds.minY - 0.5, bounds.minZ - 0.5) + val max = Vec3.createVectorHelper(bounds.maxX - 0.5, bounds.maxY - 0.5, bounds.maxZ - 0.5) + min.rotateAroundY(count * Math.PI.toFloat * 0.5f) + max.rotateAroundY(count * Math.PI.toFloat * 0.5f) + AxisAlignedBB.getBoundingBox( + math.min(min.xCoord + 0.5, max.xCoord + 0.5), + math.min(min.yCoord + 0.5, max.yCoord + 0.5), + math.min(min.zCoord + 0.5, max.zCoord + 0.5), + math.max(min.xCoord + 0.5, max.xCoord + 0.5), + math.max(min.yCoord + 0.5, max.yCoord + 0.5), + math.max(min.zCoord + 0.5, max.zCoord + 0.5)) + } } } From 9898428cc086cacec6da42350137fa296852baf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 24 Mar 2015 03:13:12 +0100 Subject: [PATCH 10/17] More fine-grained collision / bounding box logic for prints. --- .../client/renderer/HighlightRenderer.scala | 31 ++++++++++++++ .../scala/li/cil/oc/common/block/Print.scala | 40 +++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/src/main/scala/li/cil/oc/client/renderer/HighlightRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/HighlightRenderer.scala index 6f0e8621a..55342a82a 100644 --- a/src/main/scala/li/cil/oc/client/renderer/HighlightRenderer.scala +++ b/src/main/scala/li/cil/oc/client/renderer/HighlightRenderer.scala @@ -4,12 +4,15 @@ import cpw.mods.fml.common.eventhandler.SubscribeEvent import li.cil.oc.Settings import li.cil.oc.api import li.cil.oc.client.Textures +import li.cil.oc.common import li.cil.oc.util.BlockPosition +import li.cil.oc.util.ExtendedAABB._ import li.cil.oc.util.ExtendedBlock._ import li.cil.oc.util.ExtendedWorld._ import li.cil.oc.util.RenderState import net.minecraft.client.Minecraft import net.minecraft.client.renderer.OpenGlHelper +import net.minecraft.client.renderer.RenderGlobal import net.minecraft.client.renderer.Tessellator import net.minecraft.util.MovingObjectPosition.MovingObjectType import net.minecraftforge.client.event.DrawBlockHighlightEvent @@ -95,5 +98,33 @@ object HighlightRenderer { GL11.glPopMatrix() } } + + if (hitInfo.typeOfHit == MovingObjectType.BLOCK) e.player.getEntityWorld.getTileEntity(hitInfo.blockX, hitInfo.blockY, hitInfo.blockZ) match { + case print: common.tileentity.Print => + val pos = e.player.getPosition(e.partialTicks) + val expansion = 0.002f + + // See RenderGlobal.drawSelectionBox. + GL11.glEnable(GL11.GL_BLEND) + OpenGlHelper.glBlendFunc(770, 771, 1, 0) + GL11.glColor4f(0, 0, 0, 0.4f) + GL11.glLineWidth(2) + GL11.glDisable(GL11.GL_TEXTURE_2D) + GL11.glDepthMask(false) + + for (shape <- if (print.state) print.data.stateOn else print.data.stateOff) { + val bounds = shape.bounds.rotateTowards(print.facing) + RenderGlobal.drawOutlinedBoundingBox(bounds.copy().expand(expansion, expansion, expansion) + .offset(e.target.blockX, e.target.blockY, e.target.blockZ) + .offset(-pos.xCoord, -pos.yCoord, -pos.zCoord), -1) + } + + GL11.glDepthMask(true) + GL11.glEnable(GL11.GL_TEXTURE_2D) + GL11.glDisable(GL11.GL_BLEND) + + e.setCanceled(true) + case _ => + } } } diff --git a/src/main/scala/li/cil/oc/common/block/Print.scala b/src/main/scala/li/cil/oc/common/block/Print.scala index d35348e35..ab014850b 100644 --- a/src/main/scala/li/cil/oc/common/block/Print.scala +++ b/src/main/scala/li/cil/oc/common/block/Print.scala @@ -8,11 +8,15 @@ import li.cil.oc.common.item.data.PrintData import li.cil.oc.common.tileentity import li.cil.oc.integration.util.NEI import li.cil.oc.util.ExtendedAABB +import li.cil.oc.util.ExtendedAABB._ +import net.minecraft.entity.Entity import net.minecraft.entity.EntityLivingBase import net.minecraft.entity.EnumCreatureType import net.minecraft.entity.player.EntityPlayer import net.minecraft.item.ItemStack +import net.minecraft.util.AxisAlignedBB import net.minecraft.util.MovingObjectPosition +import net.minecraft.util.Vec3 import net.minecraft.world.IBlockAccess import net.minecraft.world.World import net.minecraftforge.common.util.ForgeDirection @@ -64,6 +68,42 @@ class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends } } + override def addCollisionBoxesToList(world: World, x: Int, y: Int, z: Int, mask: AxisAlignedBB, list: util.List[_], entity: Entity): Unit = { + world.getTileEntity(x, y, z) match { + case print: tileentity.Print => + def add[T](list: util.List[T], value: Any) = list.add(value.asInstanceOf[T]) + val shapes = if (print.state) print.data.stateOn else print.data.stateOff + for (shape <- shapes) { + val bounds = shape.bounds.rotateTowards(print.facing).offset(x, y, z) + if (bounds.intersectsWith(mask)) { + add(list, bounds) + } + } + case _ => super.addCollisionBoxesToList(world, x, y, z, mask, list, entity) + } + } + + override protected def intersect(world: World, x: Int, y: Int, z: Int, origin: Vec3, direction: Vec3): MovingObjectPosition = { + world.getTileEntity(x, y, z) match { + case print: tileentity.Print => + var closestDistance = Double.PositiveInfinity + var closest: Option[MovingObjectPosition] = None + for (shape <- if (print.state) print.data.stateOn else print.data.stateOff) { + val bounds = shape.bounds.rotateTowards(print.facing).offset(x, y, z) + val hit = bounds.calculateIntercept(origin, direction) + if (hit != null) { + val distance = hit.hitVec.distanceTo(origin) + if (distance < closestDistance) { + closestDistance = distance + closest = Option(hit) + } + } + } + closest.map(hit => new MovingObjectPosition(x, y, z, hit.sideHit, hit.hitVec)).orNull + case _ => super.intersect(world, x, y, z, origin, direction) + } + } + override protected def doSetBlockBoundsBasedOnState(world: IBlockAccess, x: Int, y: Int, z: Int): Unit = { world.getTileEntity(x, y, z) match { case print: tileentity.Print => setBlockBounds(if (print.state) print.boundsOn else print.boundsOff) From f9736a792ab23658e863dde335b675cc23adfe1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 24 Mar 2015 14:37:34 +0100 Subject: [PATCH 11/17] Fixed transmitting fill state (y u only short for progress bars MC). Using custom logic for synchronizing container data now. Tweaked power values a bit. --- src/main/resources/application.conf | 18 ++- src/main/scala/li/cil/oc/Settings.scala | 2 +- .../li/cil/oc/client/PacketHandler.scala | 12 ++ .../client/renderer/block/BlockRenderer.scala | 4 +- .../scala/li/cil/oc/common/PacketType.scala | 1 + .../cil/oc/common/container/Assembler.scala | 44 ++------ .../oc/common/container/Disassembler.scala | 25 +---- .../li/cil/oc/common/container/Player.scala | 104 ++++++++++++++++++ .../li/cil/oc/common/container/Printer.scala | 47 ++------ .../li/cil/oc/common/container/Switch.scala | 62 +++-------- .../li/cil/oc/common/tileentity/Printer.scala | 3 +- .../scala/li/cil/oc/server/PacketSender.scala | 12 ++ 12 files changed, 179 insertions(+), 155 deletions(-) diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index f3a84f3ba..82d6db829 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -511,7 +511,7 @@ opencomputers { # The amount of energy the printer can apply per tick. This controls # the speed at which prints are completed, basically. - printerTickAmount: 10 + printerTickAmount: 1 # If you don't want OpenComputers to accept power from one or more of the # supported power mods, for example because it doesn't suit the vision @@ -734,10 +734,8 @@ opencomputers { # expensive, to discourage frequent re-writing of EEPROMs. eepromWrite: 50 - # How much energy is required per shape in a 3D print. With the - # default of 200 for example, it will take 1600 energy to print a - # block with 8 shapes in it. - printerShape: 200 + # How much energy is required for a single 3D print. + printerModel: 25 } # The rate at which different blocks accept external power. All of these @@ -1021,11 +1019,11 @@ opencomputers { # Examples: 'OpenComputers:case3', 'minecraft:stonebrick@1' assemblerBlacklist: [] - # The maximum number of shape for a single 3D print allowed. This is for - # the sum of shapes in both states (off and on), so e.g. with the default - # of 32 you can use 10 shapes for the off state and 22 for the on state - # at maximum. - maxPrinterShapes: 32 + # The maximum number of shape for a state of a 3D print allowed. This is + # for the individual states (off and on), so it is possible to have up to + # this many shapes *per state* (the reasoning being that only one state + # will ever be visible at a time). + maxPrinterShapes: 16 } # Settings for mod integration (the mod previously known as OpenComponents). diff --git a/src/main/scala/li/cil/oc/Settings.scala b/src/main/scala/li/cil/oc/Settings.scala index 3cc13b778..cc5fe94ff 100644 --- a/src/main/scala/li/cil/oc/Settings.scala +++ b/src/main/scala/li/cil/oc/Settings.scala @@ -193,7 +193,7 @@ class Settings(val config: Config) { val chunkloaderCost = config.getDouble("power.cost.chunkloaderCost") max 0 val pistonCost = config.getDouble("power.cost.pistonPush") max 0 val eepromWriteCost = config.getDouble("power.cost.eepromWrite") max 0 - val printShapeCost = config.getDouble("power.cost.printerShape") max 0 + val printCost = config.getDouble("power.cost.printerModel") max 0 // power.rate val accessPointRate = config.getDouble("power.rate.accessPoint") max 0 diff --git a/src/main/scala/li/cil/oc/client/PacketHandler.scala b/src/main/scala/li/cil/oc/client/PacketHandler.scala index b4d7162c6..5ab795ed3 100644 --- a/src/main/scala/li/cil/oc/client/PacketHandler.scala +++ b/src/main/scala/li/cil/oc/client/PacketHandler.scala @@ -9,6 +9,7 @@ import li.cil.oc.api.component import li.cil.oc.api.event.FileSystemAccessEvent import li.cil.oc.client.renderer.PetRenderer import li.cil.oc.common.PacketType +import li.cil.oc.common.container import li.cil.oc.common.tileentity._ import li.cil.oc.common.tileentity.traits._ import li.cil.oc.common.{PacketHandler => CommonPacketHandler} @@ -41,6 +42,7 @@ object PacketHandler extends CommonPacketHandler { case PacketType.ColorChange => onColorChange(p) case PacketType.ComputerState => onComputerState(p) case PacketType.ComputerUserList => onComputerUserList(p) + case PacketType.ContainerUpdate => onContainerUpdate(p) case PacketType.DisassemblerActiveChange => onDisassemblerActiveChange(p) case PacketType.FileSystemActivity => onFileSystemActivity(p) case PacketType.FloppyChange => onFloppyChange(p) @@ -135,6 +137,16 @@ object PacketHandler extends CommonPacketHandler { case _ => // Invalid packet. } + def onContainerUpdate(p: PacketParser) = { + val windowId = p.readUnsignedByte() + if (p.player.openContainer != null && p.player.openContainer.windowId == windowId) { + p.player.openContainer match { + case container: container.Player => container.updateCustomData(p.readNBT()) + case _ => // Invalid packet. + } + } + } + def onDisassemblerActiveChange(p: PacketParser) = p.readTileEntity[Disassembler]() match { case Some(t) => t.isActive = p.readBoolean() diff --git a/src/main/scala/li/cil/oc/client/renderer/block/BlockRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/block/BlockRenderer.scala index 10e28c2ea..3d05d230b 100644 --- a/src/main/scala/li/cil/oc/client/renderer/block/BlockRenderer.scala +++ b/src/main/scala/li/cil/oc/client/renderer/block/BlockRenderer.scala @@ -140,8 +140,8 @@ object BlockRenderer extends ISimpleBlockRenderingHandler { } } - // I can't be bothered to adjust the screen rendering logic... so special case ahoy. - def patchedRenderer(renderer: RenderBlocks, block: Block) = if (!block.isInstanceOf[Screen]) { + // The texture flip this works around only seems to occur for blocks with custom block renderers? + def patchedRenderer(renderer: RenderBlocks, block: Block) = if (block.isInstanceOf[Hologram] || block.isInstanceOf[Printer]) { PatchedRenderBlocks.blockAccess = renderer.blockAccess PatchedRenderBlocks.overrideBlockTexture = renderer.overrideBlockTexture PatchedRenderBlocks.flipTexture = renderer.flipTexture diff --git a/src/main/scala/li/cil/oc/common/PacketType.scala b/src/main/scala/li/cil/oc/common/PacketType.scala index f2f16c868..d34b1d04f 100644 --- a/src/main/scala/li/cil/oc/common/PacketType.scala +++ b/src/main/scala/li/cil/oc/common/PacketType.scala @@ -9,6 +9,7 @@ object PacketType extends Enumeration { ColorChange, ComputerState, ComputerUserList, + ContainerUpdate, DisassemblerActiveChange, FileSystemActivity, FloppyChange, diff --git a/src/main/scala/li/cil/oc/common/container/Assembler.scala b/src/main/scala/li/cil/oc/common/container/Assembler.scala index 9829bbd4f..929e21aaf 100644 --- a/src/main/scala/li/cil/oc/common/container/Assembler.scala +++ b/src/main/scala/li/cil/oc/common/container/Assembler.scala @@ -7,8 +7,8 @@ import li.cil.oc.common import li.cil.oc.common.InventorySlots.InventorySlot import li.cil.oc.common.template.AssemblerTemplates import li.cil.oc.common.tileentity -import li.cil.oc.util.SideTracker import net.minecraft.entity.player.InventoryPlayer +import net.minecraft.nbt.NBTTagCompound class Assembler(playerInventory: InventoryPlayer, val assembler: tileentity.Assembler) extends Player(playerInventory, assembler) { // Computer case. @@ -67,40 +67,16 @@ class Assembler(playerInventory: InventoryPlayer, val assembler: tileentity.Asse // Show the player's inventory. addPlayerInventorySlots(8, 110) - var isAssembling = false - var assemblyProgress = 0.0 - var assemblyRemainingTime = 0 + def isAssembling = synchronizedData.getBoolean("isAssembling") - @SideOnly(Side.CLIENT) - override def updateProgressBar(id: Int, value: Int) { - super.updateProgressBar(id, value) - if (id == 0) { - isAssembling = value == 1 - } + def assemblyProgress = synchronizedData.getDouble("assemblyProgress") - if (id == 1) { - assemblyProgress = value / 5.0 - } + def assemblyRemainingTime = synchronizedData.getInteger("assemblyRemainingTime") - if (id == 2) { - assemblyRemainingTime = value - } + override protected def detectCustomDataChanges(nbt: NBTTagCompound): Unit = { + synchronizedData.setBoolean("isAssembling", assembler.isAssembling) + synchronizedData.setDouble("assemblyProgress", assembler.progress) + synchronizedData.setInteger("assemblyRemainingTime", assembler.timeRemaining) + super.detectCustomDataChanges(nbt) } - - override def detectAndSendChanges() { - super.detectAndSendChanges() - if (SideTracker.isServer) { - if (isAssembling != assembler.isAssembling) { - isAssembling = assembler.isAssembling - sendProgressBarUpdate(0, if (isAssembling) 1 else 0) - } - val timeRemaining = assembler.timeRemaining - if (math.abs(assembler.progress - assemblyProgress) > 0.2 || assemblyRemainingTime != timeRemaining) { - assemblyProgress = assembler.progress - assemblyRemainingTime = timeRemaining - sendProgressBarUpdate(1, (assemblyProgress * 5).toInt) - sendProgressBarUpdate(2, timeRemaining) - } - } - } -} \ No newline at end of file +} diff --git a/src/main/scala/li/cil/oc/common/container/Disassembler.scala b/src/main/scala/li/cil/oc/common/container/Disassembler.scala index 638de7f29..248e137b8 100644 --- a/src/main/scala/li/cil/oc/common/container/Disassembler.scala +++ b/src/main/scala/li/cil/oc/common/container/Disassembler.scala @@ -1,32 +1,17 @@ package li.cil.oc.common.container -import cpw.mods.fml.relauncher.Side -import cpw.mods.fml.relauncher.SideOnly import li.cil.oc.common.tileentity -import li.cil.oc.util.SideTracker import net.minecraft.entity.player.InventoryPlayer +import net.minecraft.nbt.NBTTagCompound class Disassembler(playerInventory: InventoryPlayer, val disassembler: tileentity.Disassembler) extends Player(playerInventory, disassembler) { addSlotToContainer(80, 35, "ocitem") addPlayerInventorySlots(8, 84) - var disassemblyProgress = 0.0 + def disassemblyProgress = synchronizedData.getDouble("disassemblyProgress") - @SideOnly(Side.CLIENT) - override def updateProgressBar(id: Int, value: Int) { - super.updateProgressBar(id, value) - if (id == 0) { - disassemblyProgress = value / 5.0 - } - } - - override def detectAndSendChanges() { - super.detectAndSendChanges() - if (SideTracker.isServer) { - if (math.abs(disassembler.progress - disassemblyProgress) > 0.2) { - disassemblyProgress = disassembler.progress - sendProgressBarUpdate(0, (disassemblyProgress * 5).toInt) - } - } + override protected def detectCustomDataChanges(nbt: NBTTagCompound): Unit = { + synchronizedData.setDouble("disassemblyProgress", disassembler.progress) + super.detectCustomDataChanges(nbt) } } diff --git a/src/main/scala/li/cil/oc/common/container/Player.scala b/src/main/scala/li/cil/oc/common/container/Player.scala index 1c8d16aa6..3b9ead2ae 100644 --- a/src/main/scala/li/cil/oc/common/container/Player.scala +++ b/src/main/scala/li/cil/oc/common/container/Player.scala @@ -3,14 +3,18 @@ package li.cil.oc.common.container import li.cil.oc.common import li.cil.oc.common.InventorySlots.InventorySlot import li.cil.oc.common.Tier +import li.cil.oc.server.{PacketSender => ServerPacketSender} import li.cil.oc.util.SideTracker import net.minecraft.entity.player.EntityPlayer +import net.minecraft.entity.player.EntityPlayerMP import net.minecraft.entity.player.InventoryPlayer import net.minecraft.inventory.Container import net.minecraft.inventory.ICrafting import net.minecraft.inventory.IInventory import net.minecraft.inventory.Slot import net.minecraft.item.ItemStack +import net.minecraft.nbt.NBTBase +import net.minecraft.nbt.NBTTagCompound import scala.collection.convert.WrapAsScala._ @@ -133,4 +137,104 @@ abstract class Player(val playerInventory: InventoryPlayer, val otherInventory: case _ => } } + + override def detectAndSendChanges(): Unit = { + super.detectAndSendChanges() + if (SideTracker.isServer) { + val nbt = new NBTTagCompound() + detectCustomDataChanges(nbt) + for (entry <- crafters) entry match { + case player: EntityPlayerMP => ServerPacketSender.sendContainerUpdate(this, nbt, player) + case _ => + } + } + } + + // Used for custom value synchronization, because shorts simply don't cut it most of the time. + protected def detectCustomDataChanges(nbt: NBTTagCompound): Unit = { + val delta = synchronizedData.getDelta + if (delta != null && !delta.hasNoTags) { + nbt.setTag("delta", delta) + } + } + + def updateCustomData(nbt: NBTTagCompound): Unit = { + if (nbt.hasKey("delta")) { + val delta = nbt.getCompoundTag("delta") + delta.func_150296_c().foreach { + case key: String => synchronizedData.setTag(key, delta.getTag(key)) + } + } + } + + protected class SynchronizedData extends NBTTagCompound { + private var delta = new NBTTagCompound() + + def getDelta: NBTTagCompound = this.synchronized { + if (delta.hasNoTags) null + else { + val result = delta + delta = new NBTTagCompound() + result + } + } + + override def setTag(key: String, value: NBTBase): Unit = this.synchronized { + if (!value.equals(getTag(key))) delta.setTag(key, value) + super.setTag(key, value) + } + + override def setByte(key: String, value: Byte): Unit = this.synchronized { + if (value != getByte(key)) delta.setByte(key, value) + super.setByte(key, value) + } + + override def setShort(key: String, value: Short): Unit = this.synchronized { + if (value != getShort(key)) delta.setShort(key, value) + super.setShort(key, value) + } + + override def setInteger(key: String, value: Int): Unit = this.synchronized { + if (value != getInteger(key)) delta.setInteger(key, value) + super.setInteger(key, value) + } + + override def setLong(key: String, value: Long): Unit = this.synchronized { + if (value != getLong(key)) delta.setLong(key, value) + super.setLong(key, value) + } + + override def setFloat(key: String, value: Float): Unit = this.synchronized { + if (value != getFloat(key)) delta.setFloat(key, value) + super.setFloat(key, value) + } + + override def setDouble(key: String, value: Double): Unit = this.synchronized { + if (value != getDouble(key)) delta.setDouble(key, value) + super.setDouble(key, value) + } + + override def setString(key: String, value: String): Unit = this.synchronized { + if (value != getString(key)) delta.setString(key, value) + super.setString(key, value) + } + + override def setByteArray(key: String, value: Array[Byte]): Unit = this.synchronized { + if (value.deep != getByteArray(key).deep) delta.setByteArray(key, value) + super.setByteArray(key, value) + } + + override def setIntArray(key: String, value: Array[Int]): Unit = this.synchronized { + if (value.deep != getIntArray(key).deep) delta.setIntArray(key, value) + super.setIntArray(key, value) + } + + override def setBoolean(key: String, value: Boolean): Unit = this.synchronized { + if (value != getBoolean(key)) delta.setBoolean(key, value) + super.setBoolean(key, value) + } + } + + protected val synchronizedData = new SynchronizedData() + } \ No newline at end of file diff --git a/src/main/scala/li/cil/oc/common/container/Printer.scala b/src/main/scala/li/cil/oc/common/container/Printer.scala index ce9ecf205..11cf0691b 100644 --- a/src/main/scala/li/cil/oc/common/container/Printer.scala +++ b/src/main/scala/li/cil/oc/common/container/Printer.scala @@ -1,11 +1,9 @@ package li.cil.oc.common.container -import cpw.mods.fml.relauncher.Side -import cpw.mods.fml.relauncher.SideOnly import li.cil.oc.common.Slot import li.cil.oc.common.tileentity -import li.cil.oc.util.SideTracker import net.minecraft.entity.player.InventoryPlayer +import net.minecraft.nbt.NBTTagCompound class Printer(playerInventory: InventoryPlayer, val printer: tileentity.Printer) extends Player(playerInventory, printer) { addSlotToContainer(18, 19, Slot.Filtered) @@ -15,41 +13,16 @@ class Printer(playerInventory: InventoryPlayer, val printer: tileentity.Printer) // Show the player's inventory. addPlayerInventorySlots(8, 84) - var isPrinting = false - var amountMaterial = 0 - var amountInk = 0 + def isPrinting = synchronizedData.getBoolean("isPrinting") - @SideOnly(Side.CLIENT) - override def updateProgressBar(id: Int, value: Int) { - super.updateProgressBar(id, value) - if (id == 0) { - isPrinting = value == 1 - } + def amountMaterial = synchronizedData.getInteger("amountMaterial") - if (id == 1) { - amountMaterial = value - } + def amountInk = synchronizedData.getInteger("amountInk") - if (id == 2) { - amountInk = value - } + override protected def detectCustomDataChanges(nbt: NBTTagCompound): Unit = { + synchronizedData.setBoolean("isPrinting", printer.isPrinting) + synchronizedData.setInteger("amountMaterial", printer.amountMaterial) + synchronizedData.setInteger("amountInk", printer.amountInk) + super.detectCustomDataChanges(nbt) } - - override def detectAndSendChanges() { - super.detectAndSendChanges() - if (SideTracker.isServer) { - if (isPrinting != printer.isPrinting) { - isPrinting = printer.isPrinting - sendProgressBarUpdate(0, if (isPrinting) 1 else 0) - } - if (amountMaterial != printer.amountMaterial) { - amountMaterial = printer.amountMaterial - sendProgressBarUpdate(1, amountMaterial) - } - if (amountInk != printer.amountInk) { - amountInk = printer.amountInk - sendProgressBarUpdate(2, amountInk) - } - } - } -} \ No newline at end of file +} diff --git a/src/main/scala/li/cil/oc/common/container/Switch.scala b/src/main/scala/li/cil/oc/common/container/Switch.scala index c90cc8d39..ae6c16254 100644 --- a/src/main/scala/li/cil/oc/common/container/Switch.scala +++ b/src/main/scala/li/cil/oc/common/container/Switch.scala @@ -1,9 +1,9 @@ package li.cil.oc.common.container -import cpw.mods.fml.common.FMLCommonHandler import li.cil.oc.common.Slot import li.cil.oc.common.tileentity import net.minecraft.entity.player.InventoryPlayer +import net.minecraft.nbt.NBTTagCompound class Switch(playerInventory: InventoryPlayer, switch: tileentity.Switch) extends Player(playerInventory, switch) { addSlotToContainer(151, 15, Slot.CPU) @@ -11,58 +11,22 @@ class Switch(playerInventory: InventoryPlayer, switch: tileentity.Switch) extend addSlotToContainer(151, 53, Slot.HDD) addPlayerInventorySlots(8, 84) - var relayDelay = 0 + def relayDelay = synchronizedData.getInteger("relayDelay") - var relayAmount = 0 + def relayAmount = synchronizedData.getInteger("relayAmount") - var maxQueueSize = 0 + def maxQueueSize = synchronizedData.getInteger("maxQueueSize") - var packetsPerCycleAvg = 0 + def packetsPerCycleAvg = synchronizedData.getInteger("packetsPerCycleAvg") - var queueSize = 0 + def queueSize = synchronizedData.getInteger("queueSize") - override def updateProgressBar(id: Int, value: Int) { - super.updateProgressBar(id, value) - if (id == 0) { - relayDelay = value - } - else if (id == 1) { - relayAmount = value - } - else if (id == 2) { - maxQueueSize = value - } - else if (id == 3) { - packetsPerCycleAvg = value - } - else if (id == 4) { - queueSize = value - } - } - - override def detectAndSendChanges() { - super.detectAndSendChanges() - if (FMLCommonHandler.instance.getEffectiveSide.isServer) { - if (switch.relayDelay != relayDelay) { - relayDelay = switch.relayDelay - sendProgressBarUpdate(0, relayDelay) - } - if (switch.relayAmount != relayAmount) { - relayAmount = switch.relayAmount - sendProgressBarUpdate(1, relayAmount) - } - if (switch.maxQueueSize != maxQueueSize) { - maxQueueSize = switch.maxQueueSize - sendProgressBarUpdate(2, maxQueueSize) - } - if (switch.packetsPerCycleAvg() != packetsPerCycleAvg) { - packetsPerCycleAvg = switch.packetsPerCycleAvg() - sendProgressBarUpdate(3, packetsPerCycleAvg) - } - if (switch.queue.size != queueSize) { - queueSize = switch.queue.size - sendProgressBarUpdate(4, queueSize) - } - } + override protected def detectCustomDataChanges(nbt: NBTTagCompound): Unit = { + synchronizedData.setInteger("relayDelay", switch.relayDelay) + synchronizedData.setInteger("relayAmount", switch.relayAmount) + synchronizedData.setInteger("maxQueueSize", switch.maxQueueSize) + synchronizedData.setInteger("packetsPerCycleAvg", switch.packetsPerCycleAvg()) + synchronizedData.setInteger("queueSize", switch.queue.size) + super.detectCustomDataChanges(nbt) } } diff --git a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala index a8addd318..58cd55172 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala @@ -195,7 +195,6 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat if (isActive && output.isEmpty && Option(getStackInSlot(slotOutput)).fold(true)(stack => stack.stackSize < stack.getMaxStackSize)) { val totalVolume = data.stateOn.foldLeft(0)((acc, shape) => acc + shape.bounds.volume) + data.stateOff.foldLeft(0)((acc, shape) => acc + shape.bounds.volume) val totalSurface = data.stateOn.foldLeft(0)((acc, shape) => acc + shape.bounds.surface) + data.stateOff.foldLeft(0)((acc, shape) => acc + shape.bounds.surface) - val totalShapes = data.stateOn.size + data.stateOff.size if (totalVolume == 0) { isActive = false @@ -205,7 +204,7 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat val materialRequired = totalVolume val inkRequired = (totalSurface / 6) max 1 - totalRequiredEnergy = totalShapes * Settings.get.printShapeCost + totalRequiredEnergy = Settings.get.printCost requiredEnergy = totalRequiredEnergy if (amountMaterial >= materialRequired && amountInk >= inkRequired) { diff --git a/src/main/scala/li/cil/oc/server/PacketSender.scala b/src/main/scala/li/cil/oc/server/PacketSender.scala index 17c4278fd..e9f652b86 100644 --- a/src/main/scala/li/cil/oc/server/PacketSender.scala +++ b/src/main/scala/li/cil/oc/server/PacketSender.scala @@ -9,6 +9,7 @@ import li.cil.oc.common.tileentity.traits._ import li.cil.oc.util.BlockPosition import li.cil.oc.util.PackedColor import net.minecraft.entity.player.EntityPlayerMP +import net.minecraft.inventory.Container import net.minecraft.item.ItemStack import net.minecraft.nbt.CompressedStreamTools import net.minecraft.nbt.NBTTagCompound @@ -74,6 +75,17 @@ object PacketSender { pb.sendToPlayersNearTileEntity(t) } + def sendContainerUpdate(c: Container, nbt: NBTTagCompound, player: EntityPlayerMP): Unit = { + if (!nbt.hasNoTags) { + val pb = new SimplePacketBuilder(PacketType.ContainerUpdate) + + pb.writeByte(c.windowId.toByte) + pb.writeNBT(nbt) + + pb.sendToPlayer(player) + } + } + def sendDisassemblerActive(t: tileentity.Disassembler, active: Boolean) { val pb = new SimplePacketBuilder(PacketType.DisassemblerActiveChange) From 652bf484789c56bce8c505ced2917a92eb637282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 24 Mar 2015 14:59:29 +0100 Subject: [PATCH 12/17] Avoid inaccuracies on rotated prints (to make sure solid faces are still recognized as such, e.g. for placing levers/torches). --- .../assets/opencomputers/recipes/default.recipes | 2 +- src/main/scala/li/cil/oc/common/block/Print.scala | 2 +- .../scala/li/cil/oc/common/tileentity/Print.scala | 2 +- src/main/scala/li/cil/oc/util/ExtendedAABB.scala | 12 ++++++------ 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/resources/assets/opencomputers/recipes/default.recipes b/src/main/resources/assets/opencomputers/recipes/default.recipes index 37d1b4dc9..e5759a8e6 100644 --- a/src/main/resources/assets/opencomputers/recipes/default.recipes +++ b/src/main/resources/assets/opencomputers/recipes/default.recipes @@ -322,7 +322,7 @@ chamelium { input: [[gravel, redstone, gravel], [redstone, {item=coal, subID=1}, redstone], [gravel, water_bucket, gravel]] - output: 8 + output: 16 } inkCartridgeEmpty { input: [[nuggetIron, dispenser, nuggetIron], diff --git a/src/main/scala/li/cil/oc/common/block/Print.scala b/src/main/scala/li/cil/oc/common/block/Print.scala index ab014850b..0216f9509 100644 --- a/src/main/scala/li/cil/oc/common/block/Print.scala +++ b/src/main/scala/li/cil/oc/common/block/Print.scala @@ -54,7 +54,7 @@ class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends case ForgeDirection.NORTH => bounds.minZ == 0 && fullX && fullY case ForgeDirection.SOUTH => bounds.maxZ == 1 && fullX && fullY case ForgeDirection.WEST => bounds.minX == 0 && fullY && fullZ - case ForgeDirection.EAST => bounds.minX == 1 && fullY && fullZ + case ForgeDirection.EAST => bounds.maxX == 1 && fullY && fullZ case _ => false } case _ => super.isSideSolid(world, x, y, z, side) diff --git a/src/main/scala/li/cil/oc/common/tileentity/Print.scala b/src/main/scala/li/cil/oc/common/tileentity/Print.scala index 7d9535d21..ac945183a 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Print.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Print.scala @@ -44,7 +44,7 @@ class Print extends traits.TileEntity with traits.RedstoneAware with traits.Rota override protected def onRedstoneInputChanged(side: ForgeDirection, oldMaxValue: Int, newMaxValue: Int): Unit = { super.onRedstoneInputChanged(side, oldMaxValue, newMaxValue) - if (!data.emitRedstone) { + if (!data.emitRedstone && data.stateOn.size > 0) { state = newMaxValue > 0 world.playSoundEffect(x + 0.5, y + 0.5, z + 0.5, "random.click", 0.3F, if (state) 0.6F else 0.5F) world.markBlockForUpdate(x, y, z) diff --git a/src/main/scala/li/cil/oc/util/ExtendedAABB.scala b/src/main/scala/li/cil/oc/util/ExtendedAABB.scala index 079b4790a..ff28b246b 100644 --- a/src/main/scala/li/cil/oc/util/ExtendedAABB.scala +++ b/src/main/scala/li/cil/oc/util/ExtendedAABB.scala @@ -39,12 +39,12 @@ object ExtendedAABB { min.rotateAroundY(count * Math.PI.toFloat * 0.5f) max.rotateAroundY(count * Math.PI.toFloat * 0.5f) AxisAlignedBB.getBoundingBox( - math.min(min.xCoord + 0.5, max.xCoord + 0.5), - math.min(min.yCoord + 0.5, max.yCoord + 0.5), - math.min(min.zCoord + 0.5, max.zCoord + 0.5), - math.max(min.xCoord + 0.5, max.xCoord + 0.5), - math.max(min.yCoord + 0.5, max.yCoord + 0.5), - math.max(min.zCoord + 0.5, max.zCoord + 0.5)) + (math.min(min.xCoord + 0.5, max.xCoord + 0.5) * 32).round / 32f, + (math.min(min.yCoord + 0.5, max.yCoord + 0.5) * 32).round / 32f, + (math.min(min.zCoord + 0.5, max.zCoord + 0.5) * 32).round / 32f, + (math.max(min.xCoord + 0.5, max.xCoord + 0.5) * 32).round / 32f, + (math.max(min.yCoord + 0.5, max.yCoord + 0.5) * 32).round / 32f, + (math.max(min.zCoord + 0.5, max.zCoord + 0.5) * 32).round / 32f) } } From 47b6b2788406f271a26c708159485f4f1e0b966c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 24 Mar 2015 15:01:00 +0100 Subject: [PATCH 13/17] A little less intense on material consumption. --- src/main/scala/li/cil/oc/common/tileentity/Printer.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala index 58cd55172..56274260f 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala @@ -201,7 +201,7 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat data = new PrintData() } else { - val materialRequired = totalVolume + val materialRequired = (totalVolume / 2) max 1 val inkRequired = (totalSurface / 6) max 1 totalRequiredEnergy = Settings.get.printCost From e0645f061c061b50a8e8e83eceee090e8ace8f03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 24 Mar 2015 15:19:10 +0100 Subject: [PATCH 14/17] Increase max label length a little. --- src/main/scala/li/cil/oc/common/tileentity/Printer.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala index 56274260f..1d9adb8df 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala @@ -80,7 +80,7 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat @Callback(doc = """function(value:string) -- Set a label for the block being printed.""") def setLabel(context: Context, args: Arguments): Array[Object] = { - data.label = Option(args.optString(0, null)).map(_.take(16)) + data.label = Option(args.optString(0, null)).map(_.take(24)) if (data.label.fold(false)(_.isEmpty)) data.label = None isActive = false // Needs committing. null From fe68cb7759015adbd44595f78ae80c3c1f2d29e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 24 Mar 2015 15:39:45 +0100 Subject: [PATCH 15/17] Default missing texture texture for missing textures. --- .../scala/li/cil/oc/client/renderer/block/Print.scala | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/scala/li/cil/oc/client/renderer/block/Print.scala b/src/main/scala/li/cil/oc/client/renderer/block/Print.scala index 3b9919ff4..fbbc79c20 100644 --- a/src/main/scala/li/cil/oc/client/renderer/block/Print.scala +++ b/src/main/scala/li/cil/oc/client/renderer/block/Print.scala @@ -5,6 +5,7 @@ import li.cil.oc.util.ExtendedAABB._ import net.minecraft.block.Block import net.minecraft.client.Minecraft import net.minecraft.client.renderer.RenderBlocks +import net.minecraft.client.renderer.texture.TextureMap import net.minecraft.util.IIcon object Print { @@ -20,7 +21,9 @@ object Print { renderer.clearOverrideBlockTexture() } - def resolveTexture(name: String): IIcon = - Option(Minecraft.getMinecraft.getTextureMapBlocks.getTextureExtry(name)). - getOrElse(Minecraft.getMinecraft.getTextureMapBlocks.getTextureExtry("wool_colored_magenta")) + def resolveTexture(name: String): IIcon = { + val icon = Minecraft.getMinecraft.getTextureMapBlocks.getTextureExtry(name) + if (icon == null) Minecraft.getMinecraft.getTextureManager.getTexture(TextureMap.locationBlocksTexture).asInstanceOf[TextureMap].getAtlasSprite("missingno") + else icon + } } From 72c73f4cc74e80515b6fc456c7efaf78903020fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 24 Mar 2015 16:02:42 +0100 Subject: [PATCH 16/17] Added tool to display block texture names, for use in 3D shape definitions. --- assets/blocks.psd | Bin 161532 -> 161729 bytes assets/items.psd | Bin 584048 -> 585508 bytes .../assets/opencomputers/lang/en_US.lang | 3 +++ .../opencomputers/recipes/default.recipes | 5 ++++ .../textures/items/TexturePicker.png | Bin 0 -> 346 bytes src/main/scala/li/cil/oc/Localization.scala | 2 ++ .../scala/li/cil/oc/common/init/Items.scala | 1 + .../li/cil/oc/common/item/TexturePicker.scala | 24 ++++++++++++++++++ .../li/cil/oc/common/tileentity/Printer.scala | 2 +- 9 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/assets/opencomputers/textures/items/TexturePicker.png create mode 100644 src/main/scala/li/cil/oc/common/item/TexturePicker.scala diff --git a/assets/blocks.psd b/assets/blocks.psd index 396012a4db77ce85835afe35c57a5b2a34a7e2af..cef221fd40c12576717c2acb14685f573e2c80ea 100644 GIT binary patch delta 300 zcmezKmh<3y&It-k2iI*>QetG9oW0qN@hc;Tp{bRLiIuU@WM^hOIA?Pwa|JV#rQzhr zB!$h&>*U`rjHZ8{&FD6Le;{Mk_RVt`J+4o`@5iJ#{ed5o0*II}oeRV@ S)Mv7vZtu@zIDIcNHwXZWaeXQP delta 995 zcmX^3p7YOJ&It-k`~PfIQetG9xO1}`<5$MXTapAOdo!DX=*<(E3z#Q|Cn;@KW>1LO zY?>PH74t}Q>9@USvu_4#rKU`dmi;nw@44dn+rJ0jbY4|rduHRb@Z?#pIr$eebc%xbyiGBgFE&FmXF1z4&a{_0H@IhX}zY;HPuZSUk)M^d)$sb}0IJGtR7>-60X zj7HO!&Si9)eD_h+_SAWd9@py`BtSq?Tv7svK$N7PUuaNZNN{M7pI=Z|h=h26kdPn< z07)U)KuL)JK`w3}1Ojd@%|HpsAR+GHpzxr;0KWiktsqIsU_q_`wSb^NKh0n+%@9e+ zAVIF+z~G>upiqA&3xE#b^4Iha3l7x+$_Gh^`vDCI@%Ik~n#rvZBqb3h1ac3^MciEK0TL2H(i-Yo z8d};qnp&Fb{*sabK|vt_{y~00p?*OjK|qg6NJ@hIEGa1^Q4e7cSP0Z}X$@!y)JuT^ UV&Kw1Jt)oxFa+2^i2xV^0E963y8r+H diff --git a/assets/items.psd b/assets/items.psd index 3ac63c947e14d403369751e7070c0a1e4c9698e9..b8354d9789fc9a9ebaa4c8d909da43c0a3eaf21a 100644 GIT binary patch delta 3137 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 diff --git a/src/main/resources/assets/opencomputers/lang/en_US.lang b/src/main/resources/assets/opencomputers/lang/en_US.lang index 324d66a05..8118232ca 100644 --- a/src/main/resources/assets/opencomputers/lang/en_US.lang +++ b/src/main/resources/assets/opencomputers/lang/en_US.lang @@ -103,6 +103,7 @@ item.oc.TabletCase0.name=Tablet Case (Tier 1) item.oc.TabletCase1.name=Tablet Case (Tier 2) item.oc.TabletCase3.name=Tablet Case (Creative) item.oc.Terminal.name=Remote Terminal +item.oc.TexturePicker.name=Texture Picker item.oc.Transistor.name=Transistor item.oc.UpgradeAngel.name=Angel Upgrade item.oc.UpgradeBattery0.name=Battery Upgrade (Tier 1) @@ -169,6 +170,7 @@ oc:gui.Chat.NewVersion=A new version is available: %s oc:gui.Chat.WarningFingerprint=§cWARNING§f - fingerprint mismatch! Expected '§a%s§f' but got '§e%s§f'. Unless you are a modder and are running the deobfuscated version of the mod, it is §lstrongly§f recommended to redownload OpenComputers, because the JAR you are using may have been tampered with. oc:gui.Chat.WarningLuaFallback=Native Lua libraries are not available, computers will not be able to persist their state. They will reboot on chunk reloads. oc:gui.Chat.WarningPower=No supported power providing mod available. Computers, screens and all other components will §lnot§f require energy. Install one of the following mods to enable power: BuildCraft, Electrical Age, IndustrialCraft2, Mekanism or Thermal Expansion. Disable power in the config to suppress this warning. +oc:gui.Chat.TextureName=§7Texture name is §a%s§f. oc:gui.Chat.WarningProjectRed=You are using a version of Project: Red that is incompatible with OpenComputers. Try updating your version of Project: Red. oc:gui.Error.ComponentOverflow=Too many components connected to the computer. oc:gui.Error.InternalError=Internal error, please see the log file. This is probably a bug. @@ -295,6 +297,7 @@ oc:tooltip.Switch=Allows connecting different networks to each other. Only netwo oc:tooltip.Tablet=A tablet computer, for fresh Lua on the go. Can be forced to shut down by sneak-activating it. oc:tooltip.TabletCase=Basic case for tablets. Place it into the assembler to add in components and create a tablet computer. oc:tooltip.Terminal=Allows controlling a server remotely, as long as you are in range of it. Acts like a portable screen and keyboard. Shift-right-click a server in a server rack to bind the terminal to it. +oc:tooltip.TexturePicker=This tool allows showing a string describing a block's surface, for use in 3D printer shape definitions. Totally not texture names, nope. No sir. oc:tooltip.Tier=§8Tier %s oc:tooltip.TooLong=Hold [§f%s§7] for a detailed tooltip. oc:tooltip.Transistor=A basic element in most other computer parts. It's a bit twisted, but it does the job. diff --git a/src/main/resources/assets/opencomputers/recipes/default.recipes b/src/main/resources/assets/opencomputers/recipes/default.recipes index e5759a8e6..415e999c9 100644 --- a/src/main/resources/assets/opencomputers/recipes/default.recipes +++ b/src/main/resources/assets/opencomputers/recipes/default.recipes @@ -6,6 +6,11 @@ analyzer { ["oc:materialTransistor", nuggetGold, ""] ["oc:materialCircuitBoardPrinted", nuggetGold, ""]] } +texturePicker { + input: [[dyeBlack, dyeRed, dyeGreen] + [dyeBlue, "oc:analyzer", dyePurple] + [dyeYellow, dyeMagenta, dyeWhite]] +} droneCase1 { input: [[{block="minecraft:end_stone"}, compass, {block="minecraft:end_stone"}] ["oc:circuitChip1", "oc:microcontrollerCase1", "oc:circuitChip1"] diff --git a/src/main/resources/assets/opencomputers/textures/items/TexturePicker.png b/src/main/resources/assets/opencomputers/textures/items/TexturePicker.png new file mode 100644 index 0000000000000000000000000000000000000000..f8565ef0357afe80cf19e69764a7d1201973e13f GIT binary patch literal 346 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8gaDrqR}L1T@YCUP{(-ndEIzi` z=Via`?uBQ6t@OMz{lKgL|NnOw|K0&KNTDRiFBr(h2N+^vq~8M7rg*wIhE&|jIqxpi zpuppBQK6}8Z~4yux}gdUPt%XiHegnWKPb;))>5K(eOERMQ_j&%{% + if (player.getEntityWorld.isRemote) { + val icon = block.getIcon(player.getEntityWorld, position.x, position.y, position.z, side) + if (icon != null) { + player.addChatMessage(Localization.Chat.TextureName(icon.getIconName)) + } + } + true + case _ => super.onItemUse(stack, player, position, side, hitX, hitY, hitZ) + } + } +} diff --git a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala index 1d9adb8df..0abd4a53f 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala @@ -139,7 +139,7 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat val maxX = (args.checkInteger(3) max 0 min 16) / 16f val maxY = (args.checkInteger(4) max 0 min 16) / 16f val maxZ = (args.checkInteger(5) max 0 min 16) / 16f - val texture = args.checkString(6) + val texture = args.checkString(6).take(64) val state = args.checkAny(7) != null && args.optBoolean(7, false) if (minX == maxX) throw new IllegalArgumentException("empty block") From ab7e371fe13293376db9e36249bb0107e376781f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 24 Mar 2015 16:44:53 +0100 Subject: [PATCH 17/17] Fixed isSolid check in 3d prints. Made Z in shape declaration go to the back to make it more intuitive. --- .../scala/li/cil/oc/common/block/Print.scala | 32 +++++++++++-------- .../li/cil/oc/common/tileentity/Printer.scala | 4 +-- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/main/scala/li/cil/oc/common/block/Print.scala b/src/main/scala/li/cil/oc/common/block/Print.scala index 0216f9509..cfcb70fa7 100644 --- a/src/main/scala/li/cil/oc/common/block/Print.scala +++ b/src/main/scala/li/cil/oc/common/block/Print.scala @@ -41,24 +41,28 @@ class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends override def isBlockSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = isSideSolid(world, x, y, z, side) - override def isSideSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = { + override def isSideSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection): Boolean = { world.getTileEntity(x, y, z) match { case print: tileentity.Print => - val bounds = if (print.state) print.boundsOn else print.boundsOff - val fullX = bounds.minX == 0 && bounds.maxX == 1 - val fullY = bounds.minY == 0 && bounds.maxY == 1 - val fullZ = bounds.minZ == 0 && bounds.maxZ == 1 - side match { - case ForgeDirection.DOWN => bounds.minY == 0 && fullX && fullZ - case ForgeDirection.UP => bounds.maxY == 1 && fullX && fullZ - case ForgeDirection.NORTH => bounds.minZ == 0 && fullX && fullY - case ForgeDirection.SOUTH => bounds.maxZ == 1 && fullX && fullY - case ForgeDirection.WEST => bounds.minX == 0 && fullY && fullZ - case ForgeDirection.EAST => bounds.maxX == 1 && fullY && fullZ - case _ => false + val shapes = if (print.state) print.data.stateOn else print.data.stateOff + for (shape <- shapes) { + val bounds = shape.bounds + val fullX = bounds.minX == 0 && bounds.maxX == 1 + val fullY = bounds.minY == 0 && bounds.maxY == 1 + val fullZ = bounds.minZ == 0 && bounds.maxZ == 1 + if (side match { + case ForgeDirection.DOWN => bounds.minY == 0 && fullX && fullZ + case ForgeDirection.UP => bounds.maxY == 1 && fullX && fullZ + case ForgeDirection.NORTH => bounds.minZ == 0 && fullX && fullY + case ForgeDirection.SOUTH => bounds.maxZ == 1 && fullX && fullY + case ForgeDirection.WEST => bounds.minX == 0 && fullY && fullZ + case ForgeDirection.EAST => bounds.maxX == 1 && fullY && fullZ + case _ => false + }) return true } - case _ => super.isSideSolid(world, x, y, z, side) + case _ => } + false } override def getPickBlock(target: MovingObjectPosition, world: World, x: Int, y: Int, z: Int, player: EntityPlayer): ItemStack = { diff --git a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala index 0abd4a53f..709cd0068 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Printer.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Printer.scala @@ -135,10 +135,10 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat } val minX = (args.checkInteger(0) max 0 min 16) / 16f val minY = (args.checkInteger(1) max 0 min 16) / 16f - val minZ = (args.checkInteger(2) max 0 min 16) / 16f + val minZ = (16 - (args.checkInteger(2) max 0 min 16)) / 16f val maxX = (args.checkInteger(3) max 0 min 16) / 16f val maxY = (args.checkInteger(4) max 0 min 16) / 16f - val maxZ = (args.checkInteger(5) max 0 min 16) / 16f + val maxZ = (16 - (args.checkInteger(5) max 0 min 16)) / 16f val texture = args.checkString(6).take(64) val state = args.checkAny(7) != null && args.optBoolean(7, false)