diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index 8a95f8603..75b7913c5 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -82,7 +82,7 @@ opencomputers { # may want to lower this a bit, to avoid it flickering too much. hologramFlickerFrequency: 0.025 - # This controls the maximum scales of hologram projectors, by tier. + # This controls the maximum scales of holograms, by tier. # The size at scale 1 is 3x2x3 blocks, at scale 3 the hologram will # span up to 9x6x9 blocks. Unlike most other `client' settings, this # value is only used for validation *on the server*, with the effects @@ -94,6 +94,14 @@ opencomputers { 4 ] + # This controls the maximum translation of holograms, by tier. + # The scale is in "hologram sizes", i.e. scale 1 allows offsetting a + # hologram once by its own size. + hologramMaxTranslation: [ + 0.25 + 0.5 + ] + # The color of monochrome text (i.e. displayed when in 1-bit color depth, # e.g. tier one screens / GPUs, or higher tier set to 1-bit color depth). # Defaults to white, feel free to make it some other color, tho! diff --git a/src/main/scala/li/cil/oc/Settings.scala b/src/main/scala/li/cil/oc/Settings.scala index 323873b5b..6996a597d 100644 --- a/src/main/scala/li/cil/oc/Settings.scala +++ b/src/main/scala/li/cil/oc/Settings.scala @@ -45,6 +45,13 @@ class Settings(config: Config) { OpenComputers.log.warning("Bad number of hologram max scales, ignoring.") Array(3.0, 4.0) } + val hologramMaxTranslationByTier = Array(config.getDoubleList("client.hologramMaxTranslation"): _*) match { + case Array(tier1, tier2) => + Array((tier1: Double) max 0.0, (tier2: Double) max 0.0) + case _ => + OpenComputers.log.warning("Bad number of hologram max translations, ignoring.") + Array(0.25, 0.5) + } val monochromeColor = Integer.decode(config.getString("client.monochromeColor")) val fontRenderer = config.getString("client.fontRenderer") diff --git a/src/main/scala/li/cil/oc/client/PacketHandler.scala b/src/main/scala/li/cil/oc/client/PacketHandler.scala index 42ceab387..f7b6822b3 100644 --- a/src/main/scala/li/cil/oc/client/PacketHandler.scala +++ b/src/main/scala/li/cil/oc/client/PacketHandler.scala @@ -38,7 +38,7 @@ class PacketHandler extends CommonPacketHandler { case PacketType.HologramPowerChange => onHologramPowerChange(p) case PacketType.HologramScale => onHologramScale(p) case PacketType.HologramSet => onHologramSet(p) - case PacketType.HologramPositionOffsetY => onHologramPositionOffsetY(p) + case PacketType.HologramTranslation => onHologramPositionOffsetY(p) case PacketType.PetVisibility => onPetVisibility(p) case PacketType.PowerState => onPowerState(p) case PacketType.RedstoneState => onRedstoneState(p) @@ -190,7 +190,9 @@ class PacketHandler extends CommonPacketHandler { def onHologramPositionOffsetY(p: PacketParser) = p.readTileEntity[Hologram]() match { case Some(t) => - t.projectionOffsetY = p.readDouble() + t.translation.xCoord = p.readDouble() + t.translation.yCoord = p.readDouble() + t.translation.zCoord = p.readDouble() case _ => // Invalid packet. } diff --git a/src/main/scala/li/cil/oc/client/gui/DynamicGuiContainer.scala b/src/main/scala/li/cil/oc/client/gui/DynamicGuiContainer.scala index 8be2de463..d6a2298e8 100644 --- a/src/main/scala/li/cil/oc/client/gui/DynamicGuiContainer.scala +++ b/src/main/scala/li/cil/oc/client/gui/DynamicGuiContainer.scala @@ -26,6 +26,7 @@ abstract class DynamicGuiContainer(container: Container) extends CustomGuiContai } override def drawGuiContainerBackgroundLayer(dt: Float, mouseX: Int, mouseY: Int) { + GL11.glColor4f(1, 1, 1, 1) mc.renderEngine.bindTexture(Textures.guiBackground) drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize) } diff --git a/src/main/scala/li/cil/oc/client/renderer/tileentity/HologramRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/tileentity/HologramRenderer.scala index 71aff1db3..a46b179fe 100644 --- a/src/main/scala/li/cil/oc/client/renderer/tileentity/HologramRenderer.scala +++ b/src/main/scala/li/cil/oc/client/renderer/tileentity/HologramRenderer.scala @@ -85,7 +85,10 @@ object HologramRenderer extends TileEntitySpecialRenderer with Callable[Int] wit } GL11.glScaled(1.001, 1.001, 1.001) // Avoid z-fighting with other blocks. - GL11.glTranslated(-1.5 * hologram.scale, hologram.projectionOffsetY, -1.5 * hologram.scale) + GL11.glTranslated( + (hologram.translation.xCoord * hologram.width / 16 - 1.5) * hologram.scale, + hologram.translation.yCoord * hologram.height / 16 * hologram.scale, + (hologram.translation.zCoord * hologram.width / 16 - 1.5) * hologram.scale) // Do a bit of flickering, because that's what holograms do! if (Settings.get.hologramFlickerFrequency > 0 && random.nextDouble() < Settings.get.hologramFlickerFrequency) { diff --git a/src/main/scala/li/cil/oc/common/PacketType.scala b/src/main/scala/li/cil/oc/common/PacketType.scala index 89cf2f701..54e84575e 100644 --- a/src/main/scala/li/cil/oc/common/PacketType.scala +++ b/src/main/scala/li/cil/oc/common/PacketType.scala @@ -16,7 +16,7 @@ object PacketType extends Enumeration { HologramPowerChange, HologramScale, HologramSet, - HologramPositionOffsetY, + HologramTranslation, PetVisibility, // Goes both ways. PowerState, RedstoneState, diff --git a/src/main/scala/li/cil/oc/common/tileentity/Hologram.scala b/src/main/scala/li/cil/oc/common/tileentity/Hologram.scala index aeeabbed5..6b4efd516 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Hologram.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Hologram.scala @@ -7,7 +7,7 @@ import li.cil.oc.server.{PacketSender => ServerPacketSender} import li.cil.oc.{Settings, api} import net.minecraft.entity.player.EntityPlayer import net.minecraft.nbt.NBTTagCompound -import net.minecraft.util.AxisAlignedBB +import net.minecraft.util.{Vec3, AxisAlignedBB} import net.minecraftforge.common.ForgeDirection class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment with Analyzable with traits.Rotatable { @@ -18,9 +18,9 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w withConnector(). create() - val width = 3 * 16 + final val width = 3 * 16 - val height = 2 * 16 // 32 bit in an int + final val height = 2 * 16 // 32 bit in an int // Layout is: first half is lower bit, second half is higher bit for the // voxels in the cube. This is to retain compatibility with pre 1.3 saves. @@ -30,7 +30,7 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w var scale = 1.0 // Projection Y position offset - consider adding X,Z later perhaps - var projectionOffsetY: Double = 0.0 + var translation = Vec3.createVectorHelper(0, 0, 0) // Relative number of lit columns (for energy cost). var litRatio = -1.0 @@ -53,7 +53,7 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w var hasPower = true - val colorsByTier = Array(Array(0x00FF00), Array(0x0000FF, 0x00FF00, 0xFF0000)) // 0xBBGGRR for rendering convenience + final val colorsByTier = Array(Array(0x00FF00), Array(0x0000FF, 0x00FF00, 0xFF0000)) // 0xBBGGRR for rendering convenience // This is a def and not a val for loading (where the tier comes from the nbt and is always 0 here). def colors = colorsByTier(tier) @@ -202,7 +202,7 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w null } - @Callback(doc = """function():number -- Returns the render scale of the hologram.""") + @Callback(direct = true, doc = """function():number -- Returns the render scale of the hologram.""") def getScale(computer: Context, args: Arguments): Array[AnyRef] = { result(scale) } @@ -214,15 +214,23 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w null } - @Callback(doc = """function():number -- Returns the render projection offset of the hologram.""") - def getOffset(computer: Context, args: Arguments): Array[AnyRef] = { - result(projectionOffsetY) // consider adding a future axis parameter for X,Y or Z - but for now, just using Y + @Callback(direct = true, doc = """function():number, number, number -- Returns the relative render projection offsets of the hologram.""") + def getTranslation(computer: Context, args: Arguments): Array[AnyRef] = { + result(translation.xCoord, translation.yCoord, translation.zCoord) } - @Callback(doc = """function(value:number) -- Sets the render projection offset of the hologram..""") - def setOffset(computer: Context, args: Arguments): Array[AnyRef] = { - val maxOffset = 3 // this wants to be a config setting / by tier - perhaps - projectionOffsetY = math.max(0, math.min(maxOffset, args.checkDouble(0))) + @Callback(doc = """function(tx:number, ty:number, tz:number) -- Sets the relative render projection offsets of the hologram.""") + def setTranslation(computer: Context, args: Arguments): Array[AnyRef] = { + // Validate all axes before setting the values. + val maxTranslation = Settings.get.hologramMaxTranslationByTier(tier) + val tx = math.max(-maxTranslation, math.min(maxTranslation, args.checkDouble(0))) + val ty = math.max(0, math.min(maxTranslation, args.checkDouble(1))) + val tz = math.max(-maxTranslation, math.min(maxTranslation, args.checkDouble(2))) + + translation.xCoord = tx + translation.yCoord = ty + translation.zCoord = tz + ServerPacketSender.sendHologramOffset(this) null } @@ -318,7 +326,20 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w def getFadeStartDistanceSquared = scale / Settings.get.hologramMaxScaleByTier.max * Settings.get.hologramFadeStartDistance * Settings.get.hologramFadeStartDistance - override def getRenderBoundingBox = AxisAlignedBB.getAABBPool.getAABB(xCoord + 0.5 - 1.5 * scale, yCoord + projectionOffsetY, zCoord - scale, xCoord + 0.5 + 1.5 * scale, yCoord + 0.25 + projectionOffsetY + 2 * scale, zCoord + 0.5 + 1.5 * scale) + override def getRenderBoundingBox = { + val cx = x + 0.5 + val cy = y + 0.5 + val cz = z + 0.5 + val sh = width / 16 * scale + val sv = height / 16 * scale + AxisAlignedBB.getAABBPool.getAABB( + cx + (-0.5 + translation.xCoord) * sh, + cy + translation.yCoord * sv, + cz + (-0.5 + translation.zCoord) * sh, + cx + (0.5 + translation.xCoord) * sh, + cy + (1 + translation.yCoord) * sv, + cz + (0.5 + translation.xCoord) * sh) + } // ----------------------------------------------------------------------- // @@ -335,7 +356,9 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w tag.getIntArray("colors").map(convertColor).copyToArray(colors) } scale = nbt.getDouble(Settings.namespace + "scale") - projectionOffsetY = nbt.getDouble(Settings.namespace + "offsetY") + translation.xCoord = nbt.getDouble(Settings.namespace + "offsetX") + translation.yCoord = nbt.getDouble(Settings.namespace + "offsetY") + translation.zCoord = nbt.getDouble(Settings.namespace + "offsetZ") } override def writeToNBT(nbt: NBTTagCompound) = this.synchronized { @@ -346,7 +369,9 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w tag.setIntArray("colors", colors.map(convertColor)) }) nbt.setDouble(Settings.namespace + "scale", scale) - nbt.setDouble(Settings.namespace + "offsetY", projectionOffsetY) + nbt.setDouble(Settings.namespace + "offsetX", translation.xCoord) + nbt.setDouble(Settings.namespace + "offsetY", translation.yCoord) + nbt.setDouble(Settings.namespace + "offsetZ", translation.zCoord) } @SideOnly(Side.CLIENT) @@ -356,7 +381,9 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w nbt.getIntArray("colors").copyToArray(colors) scale = nbt.getDouble("scale") hasPower = nbt.getBoolean("hasPower") - projectionOffsetY = nbt.getDouble("offsetY") + translation.xCoord = nbt.getDouble("offsetX") + translation.yCoord = nbt.getDouble("offsetY") + translation.zCoord = nbt.getDouble("offsetZ") } override def writeToNBTForClient(nbt: NBTTagCompound) { @@ -365,6 +392,8 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w nbt.setIntArray("colors", colors) nbt.setDouble("scale", scale) nbt.setBoolean("hasPower", hasPower) - nbt.setDouble("offsetY", projectionOffsetY) + nbt.setDouble("offsetX", translation.xCoord) + nbt.setDouble("offsetY", translation.yCoord) + nbt.setDouble("offsetZ", translation.zCoord) } } diff --git a/src/main/scala/li/cil/oc/server/PacketSender.scala b/src/main/scala/li/cil/oc/server/PacketSender.scala index d80139c3c..aa7ab65bd 100644 --- a/src/main/scala/li/cil/oc/server/PacketSender.scala +++ b/src/main/scala/li/cil/oc/server/PacketSender.scala @@ -140,10 +140,12 @@ object PacketSender { } def sendHologramOffset(t: tileentity.Hologram) { - val pb = new SimplePacketBuilder(PacketType.HologramPositionOffsetY) + val pb = new SimplePacketBuilder(PacketType.HologramTranslation) pb.writeTileEntity(t) - pb.writeDouble(t.projectionOffsetY) + pb.writeDouble(t.translation.xCoord) + pb.writeDouble(t.translation.yCoord) + pb.writeDouble(t.translation.zCoord) pb.sendToNearbyPlayers(t) }