From c3e9ed1e97ccf12581dab102f9d65f00665e2ecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Thu, 27 Feb 2014 03:25:27 +0100 Subject: [PATCH] added power consumption for hologram projector; added scale setting, so hologram can be from 1x1x1 up to 9x6x9, higher scale consumes more energy --- src/main/java/li/cil/oc/Settings.scala | 1 + .../java/li/cil/oc/client/PacketHandler.scala | 9 +++ .../renderer/tileentity/CableRenderer.scala | 12 +--- .../tileentity/HologramRenderer.scala | 13 +++-- .../java/li/cil/oc/common/PacketType.scala | 1 + .../cil/oc/common/tileentity/Hologram.scala | 52 +++++++++++++++--- .../java/li/cil/oc/server/PacketSender.scala | 9 +++ .../textures/blocks/hologram_effect.png | Bin 149 -> 157 bytes src/main/resources/reference.conf | 5 ++ 9 files changed, 79 insertions(+), 23 deletions(-) diff --git a/src/main/java/li/cil/oc/Settings.scala b/src/main/java/li/cil/oc/Settings.scala index 6bd97680a..566d9d485 100644 --- a/src/main/java/li/cil/oc/Settings.scala +++ b/src/main/java/li/cil/oc/Settings.scala @@ -120,6 +120,7 @@ class Settings(config: Config) { val robotCost = config.getDouble("power.cost.robot") max 0 val sleepCostFactor = config.getDouble("power.cost.sleepFactor") max 0 val screenCost = config.getDouble("power.cost.screen") max 0 + val hologramCost = config.getDouble("power.cost.hologram") max 0 val hddReadCost = (config.getDouble("power.cost.hddRead") max 0) / 1024 val hddWriteCost = (config.getDouble("power.cost.hddWrite") max 0) / 1024 val gpuSetCost = (config.getDouble("power.cost.gpuSet") max 0) / Settings.basicScreenPixels diff --git a/src/main/java/li/cil/oc/client/PacketHandler.scala b/src/main/java/li/cil/oc/client/PacketHandler.scala index 47a7c593a..28b8a04a6 100644 --- a/src/main/java/li/cil/oc/client/PacketHandler.scala +++ b/src/main/java/li/cil/oc/client/PacketHandler.scala @@ -26,6 +26,7 @@ class PacketHandler extends CommonPacketHandler { case PacketType.ChargerState => onChargerState(p) case PacketType.ComputerState => onComputerState(p) case PacketType.ComputerUserList => onComputerUserList(p) + case PacketType.HologramScale => onHologramScale(p) case PacketType.HologramSet => onHologramSet(p) case PacketType.PowerState => onPowerState(p) case PacketType.RedstoneState => onRedstoneState(p) @@ -101,6 +102,14 @@ class PacketHandler extends CommonPacketHandler { case _ => // Invalid packet. } + def onHologramScale(p: PacketParser) = + p.readTileEntity[Hologram]() match { + case Some(t) => + t.scale = p.readDouble() + t.dirty = true + case _ => // Invalid packet. + } + def onHologramSet(p: PacketParser) = p.readTileEntity[Hologram]() match { case Some(t) => diff --git a/src/main/java/li/cil/oc/client/renderer/tileentity/CableRenderer.scala b/src/main/java/li/cil/oc/client/renderer/tileentity/CableRenderer.scala index 35bde5a61..b485b0892 100644 --- a/src/main/java/li/cil/oc/client/renderer/tileentity/CableRenderer.scala +++ b/src/main/java/li/cil/oc/client/renderer/tileentity/CableRenderer.scala @@ -40,6 +40,7 @@ object CableRenderer extends TileEntitySpecialRenderer { for (mask <- 0 to 0xFF >> 2) { GL11.glNewList(displayLists + mask, GL11.GL_COMPILE) + t.startDrawingQuads() for (side <- ForgeDirection.VALID_DIRECTIONS) { val connects = (side.flag & mask) != 0 val z = if (connects) 0 else lb @@ -48,7 +49,6 @@ object CableRenderer extends TileEntitySpecialRenderer { exists(s => (s.flag & mask) != 0)) uo else 0 - t.startDrawingQuads() t.setNormal(side.offsetX, side.offsetY, -side.offsetZ) val (tx, ty, tz, u, v) = side match { case ForgeDirection.WEST => (Array.fill(4)(z), t2, t1, uv1.reverse, uv2) @@ -63,7 +63,6 @@ object CableRenderer extends TileEntitySpecialRenderer { t.addVertexWithUV(tx(1), ty(1), tz(1), u(1) + uc, v(1)) t.addVertexWithUV(tx(2), ty(2), tz(2), u(2) + uc, v(2)) t.addVertexWithUV(tx(3), ty(3), tz(3), u(3) + uc, v(3)) - t.draw() if (connects) { val (axis, sign, uv1, uv2, uv3, uv4) = side match { @@ -79,39 +78,32 @@ object CableRenderer extends TileEntitySpecialRenderer { val o1 = offsets((axis + sign + 3) % 3) val o2 = offsets((axis - sign + 3) % 3) - t.startDrawingQuads() normal(side, 0) t.addVertexWithUV(tx(0) - sign * tl(0), ty(0) - sign * tl(1), tz(0) - sign * tl(2), u(uv(0 + uv1)) + uo, v(uv(0 + uv1)) * vs) t.addVertexWithUV(tx(1) - sign * tl(0), ty(1) - sign * tl(1), tz(1) - sign * tl(2), u(uv(1 + uv1)) + uo, v(uv(1 + uv1)) * vs) t.addVertexWithUV(tx(2) + o1(0), ty(2) + o1(1), tz(2) + o1(2), u(uv(2 + uv1)) + uo, v(uv(2 + uv1)) * vs) t.addVertexWithUV(tx(3) + o1(0), ty(3) + o1(1), tz(3) + o1(2), u(uv(3 + uv1)) + uo, v(uv(3 + uv1)) * vs) - t.draw() - t.startDrawingQuads() normal(side, 1) t.addVertexWithUV(tx(0) - o1(0), ty(0) - o1(1), tz(0) - o1(2), u(uv(0 + uv2)) + uo, v(uv(0 + uv2)) * vs) t.addVertexWithUV(tx(1) - o1(0), ty(1) - o1(1), tz(1) - o1(2), u(uv(1 + uv2)) + uo, v(uv(1 + uv2)) * vs) t.addVertexWithUV(tx(2) - sign * tl(0), ty(2) - sign * tl(1), tz(2) - sign * tl(2), u(uv(2 + uv2)) + uo, v(uv(2 + uv2)) * vs) t.addVertexWithUV(tx(3) - sign * tl(0), ty(3) - sign * tl(1), tz(3) - sign * tl(2), u(uv(3 + uv2)) + uo, v(uv(3 + uv2)) * vs) - t.draw() - t.startDrawingQuads() normal(side, 2) t.addVertexWithUV(tx(0) - sign * tl(0), ty(0) - sign * tl(1), tz(0) - sign * tl(2), u(uv(0 + uv3)) + uo, v(uv(0 + uv3)) * vs) t.addVertexWithUV(tx(1) - o2(0), ty(1) - o2(1), tz(1) - o2(2), u(uv(1 + uv3)) + uo, v(uv(1 + uv3)) * vs) t.addVertexWithUV(tx(2) - o2(0), ty(2) - o2(1), tz(2) - o2(2), u(uv(2 + uv3)) + uo, v(uv(2 + uv3)) * vs) t.addVertexWithUV(tx(3) - sign * tl(0), ty(3) - sign * tl(1), tz(3) - sign * tl(2), u(uv(3 + uv3)) + uo, v(uv(3 + uv3)) * vs) - t.draw() - t.startDrawingQuads() normal(side, 3) t.addVertexWithUV(tx(0) + o2(0), ty(0) + o2(1), tz(0) + o2(2), u(uv(0 + uv4)) + uo, v(uv(0 + uv4)) * vs) t.addVertexWithUV(tx(1) - sign * tl(0), ty(1) - sign * tl(1), tz(1) - sign * tl(2), u(uv(1 + uv4)) + uo, v(uv(1 + uv4)) * vs) t.addVertexWithUV(tx(2) - sign * tl(0), ty(2) - sign * tl(1), tz(2) - sign * tl(2), u(uv(2 + uv4)) + uo, v(uv(2 + uv4)) * vs) t.addVertexWithUV(tx(3) + o2(0), ty(3) + o2(1), tz(3) + o2(2), u(uv(3 + uv4)) + uo, v(uv(3 + uv4)) * vs) - t.draw() } } + t.draw() GL11.glEndList() } diff --git a/src/main/java/li/cil/oc/client/renderer/tileentity/HologramRenderer.scala b/src/main/java/li/cil/oc/client/renderer/tileentity/HologramRenderer.scala index 991d4a34b..da5692247 100644 --- a/src/main/java/li/cil/oc/client/renderer/tileentity/HologramRenderer.scala +++ b/src/main/java/li/cil/oc/client/renderer/tileentity/HologramRenderer.scala @@ -28,15 +28,16 @@ object HologramRenderer extends TileEntitySpecialRenderer with Callable[Int] wit override def renderTileEntityAt(te: TileEntity, x: Double, y: Double, z: Double, f: Float) { hologram = te.asInstanceOf[Hologram] + if (!hologram.hasPower) return GL11.glPushAttrib(0xFFFFFFFF) - RenderState.makeItBlend() GL11.glPushMatrix() + GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5) + GL11.glScaled(1.001, 1.001, 1.001) // Avoid z-fighting with other blocks. + GL11.glTranslated(-1.5 * hologram.scale, 0, -1.5 * hologram.scale) - GL11.glScaled(1.01, 1.01, 1.01) // Avoid z-fighting with other blocks. - GL11.glTranslated(x - 1, y + 0.5, z - 1) - + // Do a bit of flickering, because that's what holograms do! if (random.nextDouble() < 0.025) { GL11.glScaled(1 + random.nextGaussian() * 0.01, 1 + random.nextGaussian() * 0.001, 1 + random.nextGaussian() * 0.01) GL11.glTranslated(random.nextGaussian() * 0.01, random.nextGaussian() * 0.01, random.nextGaussian() * 0.01) @@ -68,9 +69,9 @@ object HologramRenderer extends TileEntitySpecialRenderer with Callable[Int] wit bindTexture(TexturePreloader.blockHologram) val t = Tessellator.instance t.startDrawingQuads() - t.setColorRGBA_F(1, 1, 1, 0.7f) + t.setColorRGBA_F(1, 1, 1, 0.5f) - val s = 1f / 16f + val s = 1f / 16f * hologram.scale for (hx <- 0 until hologram.width) { val wx = hx * s for (hz <- 0 until hologram.width) { diff --git a/src/main/java/li/cil/oc/common/PacketType.scala b/src/main/java/li/cil/oc/common/PacketType.scala index 11013c6c1..059b3d2f1 100644 --- a/src/main/java/li/cil/oc/common/PacketType.scala +++ b/src/main/java/li/cil/oc/common/PacketType.scala @@ -8,6 +8,7 @@ object PacketType extends Enumeration { ChargerState, ComputerState, ComputerUserList, + HologramScale, HologramSet, PowerState, RedstoneState, diff --git a/src/main/java/li/cil/oc/common/tileentity/Hologram.scala b/src/main/java/li/cil/oc/common/tileentity/Hologram.scala index f0ed42622..f5f24e323 100644 --- a/src/main/java/li/cil/oc/common/tileentity/Hologram.scala +++ b/src/main/java/li/cil/oc/common/tileentity/Hologram.scala @@ -20,12 +20,20 @@ class Hologram extends Environment with SidedEnvironment { val volume = new Array[Int](width * width) + // Render scale. + var scale = 1.0 + + // Relative number of lit columns (for energy cost). + var litRatio = -1.0 + // Whether we need to send an update packet/recompile our display list. var dirty = false // Time to wait before sending another update packet. var cooldown = 0 + var hasPower = true + // ----------------------------------------------------------------------- // override def canConnect(side: ForgeDirection) = side != ForgeDirection.UP @@ -38,6 +46,7 @@ class Hologram extends Environment with SidedEnvironment { def clear(computer: Context, args: Arguments): Array[AnyRef] = this.synchronized { for (i <- 0 until volume.length) volume(i) = 0 dirty = true + litRatio = 0 null } @@ -55,6 +64,7 @@ class Hologram extends Environment with SidedEnvironment { val value = args.checkInteger(2) volume(x + z * width) = value dirty = true + litRatio = -1 null } @@ -67,6 +77,19 @@ class Hologram extends Environment with SidedEnvironment { // manually check the height, to avoid the shift being a no-op. volume(x + z * width) = if (height > 0) 0xFFFFFFFF >>> (32 - height) else 0 dirty = true + litRatio = -1 + null + } + + @Callback(doc = """function():number -- Returns the render scale of the hologram.""") + def getScale(computer: Context, args: Arguments): Array[AnyRef] = { + result(scale) + } + + @Callback(doc = """function(value:number) -- Set the render scale. A larger scale consumes more energy.""") + def setScale(computer: Context, args: Arguments): Array[AnyRef] = { + scale = math.max(0.333333, math.min(3, args.checkDouble(0))) + ServerPacketSender.sendHologramScale(this) null } @@ -74,13 +97,24 @@ class Hologram extends Environment with SidedEnvironment { override def updateEntity() { super.updateEntity() - if (isServer && dirty) { - cooldown -= 1 - if (cooldown <= 0) { - dirty = false - cooldown = 10 - ServerPacketSender.sendHologramSet(this) + if (isServer) { + if (dirty) { + cooldown -= 1 + if (cooldown <= 0) { + dirty = false + cooldown = 10 + ServerPacketSender.sendHologramSet(this) + } } + if (litRatio < 0) { + litRatio = 0 + for (i <- 0 until volume.length) { + if (volume(i) != 0) litRatio += 1 + } + litRatio /= volume.length + } + + hasPower = node.changeBuffer(-Settings.get.hologramCost * litRatio * scale) == 0 } } @@ -88,29 +122,33 @@ class Hologram extends Environment with SidedEnvironment { override def shouldRenderInPass(pass: Int) = pass == 1 - override def getRenderBoundingBox = AxisAlignedBB.getAABBPool.getAABB(xCoord - 1, yCoord, zCoord - 1, xCoord + 2, yCoord + 2.25, zCoord + 2) + override def getRenderBoundingBox = AxisAlignedBB.getAABBPool.getAABB(xCoord + 0.5 - 1.5 * scale, yCoord, zCoord - scale, xCoord + 0.5 + 1.5 * scale, yCoord + 0.25 + 2 * scale, zCoord + 0.5 + 1.5 * scale) // ----------------------------------------------------------------------- // override def readFromNBT(nbt: NBTTagCompound) { super.readFromNBT(nbt) nbt.getIntArray(Settings.namespace + "volume").copyToArray(volume) + scale = nbt.getDouble(Settings.namespace + "scale") } override def writeToNBT(nbt: NBTTagCompound) = this.synchronized { super.writeToNBT(nbt) nbt.setIntArray(Settings.namespace + "volume", volume) + nbt.setDouble(Settings.namespace + "scale", scale) } @SideOnly(Side.CLIENT) override def readFromNBTForClient(nbt: NBTTagCompound) { super.readFromNBTForClient(nbt) nbt.getIntArray("volume").copyToArray(volume) + scale = nbt.getDouble("scale") dirty = true } override def writeToNBTForClient(nbt: NBTTagCompound) { super.writeToNBTForClient(nbt) nbt.setIntArray("volume", volume) + nbt.setDouble("scale", scale) } } diff --git a/src/main/java/li/cil/oc/server/PacketSender.scala b/src/main/java/li/cil/oc/server/PacketSender.scala index 2290137f8..55dc419b3 100644 --- a/src/main/java/li/cil/oc/server/PacketSender.scala +++ b/src/main/java/li/cil/oc/server/PacketSender.scala @@ -55,6 +55,15 @@ object PacketSender { pb.sendToNearbyPlayers(t) } + def sendHologramScale(t: Hologram) { + val pb = new PacketBuilder(PacketType.HologramScale) + + pb.writeTileEntity(t) + pb.writeDouble(t.scale) + + pb.sendToNearbyPlayers(t) + } + def sendHologramSet(t: Hologram) { val pb = new PacketBuilder(PacketType.HologramSet) diff --git a/src/main/resources/assets/opencomputers/textures/blocks/hologram_effect.png b/src/main/resources/assets/opencomputers/textures/blocks/hologram_effect.png index 5be656cec646fc72f7f889645587f7160bb94b0c..154039406c1e4562c5c11f4c691b26801287cc1d 100644 GIT binary patch delta 103 zcmbQrIG1sPBnLAC1H(N1JfDe*8X=+qJ|V6QR~Q%`F)%!4V7Sb{_=J(+5(DE^#;dv_ z$AJpvJY5_^DsCkuB&4M#C!{2$09grX2?>cQNsJr@42+cw%6HrMhyYbGc)I$ztaD0e F0s!CT9rpkL delta 95 zcmV-l0HFV!0hIxe83+ad0061+o_>)bC`>m=L_t(|+9Zj&4ZtuE!$`!n;r(YynMpE$ z<>v&jASE9!frF1U`W7q1?C?`d9nB$`xuUWJ7yz;;3&QpK@*4mE002ovPDHLkV1oY? BCPDxJ diff --git a/src/main/resources/reference.conf b/src/main/resources/reference.conf index cb2bf7eff..e56652212 100644 --- a/src/main/resources/reference.conf +++ b/src/main/resources/reference.conf @@ -471,6 +471,11 @@ opencomputers { # tick. screen: 0.05 + # The amount of energy a hologram projetor consumes per tick. This + # is the cost if every column is lit. If not a single voxel is + # displayed the hologram projector will not drain energy. + hologram: 0.2 + # Energy it takes read one kilobyte from a file system. Note that non # I/O operations on file systems such as `list` or `getFreeSpace` do # *not* consume power. Note that this very much determines how much