mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-19 12:17:17 -04:00
textures for hologram projector block; caching display list for hologram; fixed item bounds; added localization; added clear and fill callbacks; fixed pcall and xpcall being exploitable to avoid timeout enforcement
This commit is contained in:
parent
eb09bdc0ba
commit
e04a8767d6
@ -48,6 +48,7 @@ private[oc] class Proxy extends CommonProxy {
|
||||
override def postInit(e: FMLPostInitializationEvent) {
|
||||
super.postInit(e)
|
||||
|
||||
TickRegistry.registerTickHandler(HologramRenderer, Side.CLIENT)
|
||||
TickRegistry.registerTickHandler(ScreenRenderer, Side.CLIENT)
|
||||
if (Settings.get.rTreeDebugRenderer) {
|
||||
MinecraftForge.EVENT_BUS.register(WirelessNetworkDebugRenderer)
|
||||
|
@ -1,29 +1,65 @@
|
||||
package li.cil.oc.client.renderer.tileentity
|
||||
|
||||
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import li.cil.oc.common.tileentity.Hologram
|
||||
import net.minecraft.client.renderer.Tessellator
|
||||
import org.lwjgl.opengl.GL11
|
||||
import li.cil.oc.util.RenderState
|
||||
import com.google.common.cache.{RemovalNotification, RemovalListener, CacheBuilder}
|
||||
import cpw.mods.fml.common.{TickType, ITickHandler}
|
||||
import java.util
|
||||
import java.util.concurrent.{Callable, TimeUnit}
|
||||
import li.cil.oc.client.TexturePreloader
|
||||
import net.minecraftforge.client.MinecraftForgeClient
|
||||
import li.cil.oc.common.tileentity.Hologram
|
||||
import li.cil.oc.util.RenderState
|
||||
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
|
||||
import net.minecraft.client.renderer.{GLAllocation, Tessellator}
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import org.lwjgl.opengl.GL11
|
||||
import scala.util.Random
|
||||
|
||||
object HologramRenderer extends TileEntitySpecialRenderer with Callable[Int] with RemovalListener[TileEntity, Int] with ITickHandler {
|
||||
val random = new Random()
|
||||
|
||||
/** We cache the display lists for the projectors we render for performance. */
|
||||
val cache = com.google.common.cache.CacheBuilder.newBuilder().
|
||||
expireAfterAccess(2, TimeUnit.SECONDS).
|
||||
removalListener(this).
|
||||
asInstanceOf[CacheBuilder[Hologram, Int]].
|
||||
build[Hologram, Int]()
|
||||
|
||||
/** Used to pass the current screen along to call(). */
|
||||
private var hologram: Hologram = null
|
||||
|
||||
object HologramRenderer extends TileEntitySpecialRenderer {
|
||||
override def renderTileEntityAt(te: TileEntity, x: Double, y: Double, z: Double, f: Float) {
|
||||
if (MinecraftForgeClient.getRenderPass != 0) return
|
||||
|
||||
val hologram = te.asInstanceOf[Hologram]
|
||||
hologram = te.asInstanceOf[Hologram]
|
||||
|
||||
GL11.glPushAttrib(0xFFFFFFFF)
|
||||
GL11.glDisable(GL11.GL_CULL_FACE)
|
||||
|
||||
// RenderState.disableLighting()
|
||||
RenderState.makeItBlend()
|
||||
|
||||
GL11.glPushMatrix()
|
||||
|
||||
GL11.glScaled(1.01, 1.01, 1.01) // Avoid z-fighting with other blocks.
|
||||
GL11.glTranslated(x - 1, y + 0.5, z - 1)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
GL11.glColorMask(false, false, false, false)
|
||||
val list = cache.get(hologram, this)
|
||||
compileOrDraw(list)
|
||||
GL11.glColorMask(true, true, true, true)
|
||||
GL11.glDepthFunc(GL11.GL_EQUAL)
|
||||
compileOrDraw(list)
|
||||
|
||||
GL11.glPopMatrix()
|
||||
GL11.glPopAttrib()
|
||||
}
|
||||
|
||||
def compileOrDraw(list: Int) = if (hologram.dirty) {
|
||||
val doCompile = !RenderState.compilingDisplayList
|
||||
if (doCompile) {
|
||||
hologram.dirty = false
|
||||
GL11.glNewList(list, GL11.GL_COMPILE_AND_EXECUTE)
|
||||
}
|
||||
|
||||
def isSolid(hx: Int, hy: Int, hz: Int) = {
|
||||
hx >= 0 && hy >= 0 && hz >= 0 && hx < hologram.width && hy < hologram.height && hz < hologram.width &&
|
||||
(hologram.volume(hx + hz * hologram.width) & (1 << hy)) != 0
|
||||
@ -56,54 +92,53 @@ object HologramRenderer extends TileEntitySpecialRenderer {
|
||||
// South
|
||||
if (!isSolid(hx, hy, hz + 1)) {
|
||||
t.setNormal(0, 0, 1)
|
||||
t.addVertex(wx + s, wy + s, wz + s) // 5
|
||||
t.addVertex(wx + 0, wy + s, wz + s) // 4
|
||||
t.addVertex(wx + 0, wy + 0, wz + s) // 7
|
||||
t.addVertex(wx + s, wy + 0, wz + s) // 6
|
||||
t.addVertexWithUV(wx + s, wy + s, wz + s, 0, 0) // 5
|
||||
t.addVertexWithUV(wx + 0, wy + s, wz + s, 1, 0) // 4
|
||||
t.addVertexWithUV(wx + 0, wy + 0, wz + s, 1, 1) // 7
|
||||
t.addVertexWithUV(wx + s, wy + 0, wz + s, 0, 1) // 6
|
||||
}
|
||||
// North
|
||||
if (!isSolid(hx, hy, hz - 1)) {
|
||||
t.setNormal(0, 0, -1)
|
||||
t.addVertex(wx + s, wy + 0, wz + 0) // 3
|
||||
t.addVertex(wx + 0, wy + 0, wz + 0) // 2
|
||||
t.addVertex(wx + 0, wy + s, wz + 0) // 1
|
||||
t.addVertex(wx + s, wy + s, wz + 0) // 0
|
||||
t.addVertexWithUV(wx + s, wy + 0, wz + 0, 0, 0) // 3
|
||||
t.addVertexWithUV(wx + 0, wy + 0, wz + 0, 1, 0) // 2
|
||||
t.addVertexWithUV(wx + 0, wy + s, wz + 0, 1, 1) // 1
|
||||
t.addVertexWithUV(wx + s, wy + s, wz + 0, 0, 1) // 0
|
||||
}
|
||||
|
||||
// East
|
||||
if (!isSolid(hx + 1, hy, hz)) {
|
||||
t.setNormal(1, 0, 0)
|
||||
t.addVertex(wx + s, wy + s, wz + s) // 5
|
||||
t.addVertex(wx + s, wy + 0, wz + s) // 6
|
||||
t.addVertex(wx + s, wy + 0, wz + 0) // 3
|
||||
t.addVertex(wx + s, wy + s, wz + 0) // 0
|
||||
t.addVertexWithUV(wx + s, wy + s, wz + s, 1, 0) // 5
|
||||
t.addVertexWithUV(wx + s, wy + 0, wz + s, 1, 1) // 6
|
||||
t.addVertexWithUV(wx + s, wy + 0, wz + 0, 0, 1) // 3
|
||||
t.addVertexWithUV(wx + s, wy + s, wz + 0, 0, 0) // 0
|
||||
}
|
||||
// West
|
||||
if (!isSolid(hx - 1, hy, hz)) {
|
||||
t.setNormal(-1, 0, 0)
|
||||
t.addVertex(wx + 0, wy + 0, wz + s) // 7
|
||||
t.addVertex(wx + 0, wy + s, wz + s) // 4
|
||||
t.addVertex(wx + 0, wy + s, wz + 0) // 1
|
||||
t.addVertex(wx + 0, wy + 0, wz + 0) // 2
|
||||
t.addVertexWithUV(wx + 0, wy + 0, wz + s, 1, 0) // 7
|
||||
t.addVertexWithUV(wx + 0, wy + s, wz + s, 1, 1) // 4
|
||||
t.addVertexWithUV(wx + 0, wy + s, wz + 0, 0, 1) // 1
|
||||
t.addVertexWithUV(wx + 0, wy + 0, wz + 0, 0, 0) // 2
|
||||
}
|
||||
|
||||
// Up
|
||||
if (!isSolid(hx, hy + 1, hz)) {
|
||||
t.setNormal(0, 1, 0)
|
||||
t.addVertex(wx + s, wy + s, wz + 0) // 0
|
||||
t.addVertex(wx + 0, wy + s, wz + 0) // 1
|
||||
t.addVertex(wx + 0, wy + s, wz + s) // 4
|
||||
t.addVertex(wx + s, wy + s, wz + s) // 5
|
||||
t.addVertexWithUV(wx + s, wy + s, wz + 0, 0, 0) // 0
|
||||
t.addVertexWithUV(wx + 0, wy + s, wz + 0, 1, 0) // 1
|
||||
t.addVertexWithUV(wx + 0, wy + s, wz + s, 1, 1) // 4
|
||||
t.addVertexWithUV(wx + s, wy + s, wz + s, 0, 1) // 5
|
||||
}
|
||||
// Down
|
||||
if (!isSolid(hx, hy - 1, hz)) {
|
||||
t.setNormal(0, -1, 0)
|
||||
t.addVertex(wx + s, wy + 0, wz + s) // 6
|
||||
t.addVertex(wx + 0, wy + 0, wz + s) // 7
|
||||
t.addVertex(wx + 0, wy + 0, wz + 0) // 2
|
||||
t.addVertex(wx + s, wy + 0, wz + 0) // 3
|
||||
t.addVertexWithUV(wx + s, wy + 0, wz + s, 0, 0) // 6
|
||||
t.addVertexWithUV(wx + 0, wy + 0, wz + s, 1, 0) // 7
|
||||
t.addVertexWithUV(wx + 0, wy + 0, wz + 0, 1, 1) // 2
|
||||
t.addVertexWithUV(wx + s, wy + 0, wz + 0, 0, 1) // 3
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -111,7 +146,37 @@ object HologramRenderer extends TileEntitySpecialRenderer {
|
||||
|
||||
t.draw()
|
||||
|
||||
GL11.glPopMatrix()
|
||||
GL11.glPopAttrib()
|
||||
if (doCompile) {
|
||||
GL11.glEndList()
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
else GL11.glCallList(list)
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
// Cache
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
def call = {
|
||||
val list = GLAllocation.generateDisplayLists(1)
|
||||
hologram.dirty = true // Force compilation.
|
||||
list
|
||||
}
|
||||
|
||||
def onRemoval(e: RemovalNotification[TileEntity, Int]) {
|
||||
GLAllocation.deleteDisplayLists(e.getValue)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
// ITickHandler
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
def getLabel = "OpenComputers.Hologram"
|
||||
|
||||
def ticks() = util.EnumSet.of(TickType.CLIENT)
|
||||
|
||||
def tickStart(tickType: util.EnumSet[TickType], tickData: AnyRef*) = cache.cleanUp()
|
||||
|
||||
def tickEnd(tickType: util.EnumSet[TickType], tickData: AnyRef*) {}
|
||||
}
|
||||
|
@ -74,8 +74,7 @@ object ScreenRenderer extends TileEntitySpecialRenderer with Callable[Int] with
|
||||
|
||||
if (screen.hasPower) {
|
||||
MonospaceFontRenderer.init(tileEntityRenderer.renderEngine)
|
||||
val list = cache.get(screen, this)
|
||||
compileOrDraw(list)
|
||||
compileOrDraw(cache.get(screen, this))
|
||||
}
|
||||
|
||||
GL11.glPopMatrix()
|
||||
|
@ -7,23 +7,43 @@ import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.item.{ItemStack, EnumRarity}
|
||||
import net.minecraft.world.{World, IBlockAccess}
|
||||
import net.minecraftforge.common.ForgeDirection
|
||||
import net.minecraft.util.AxisAlignedBB
|
||||
import net.minecraft.util.{Icon, AxisAlignedBB}
|
||||
import net.minecraft.client.renderer.texture.IconRegister
|
||||
import li.cil.oc.Settings
|
||||
|
||||
class Hologram(val parent: SpecialDelegator) extends SpecialDelegate {
|
||||
val unlocalizedName = "Hologram"
|
||||
|
||||
private val icons = Array.fill[Icon](6)(null)
|
||||
|
||||
override def rarity = EnumRarity.rare
|
||||
|
||||
override def tooltipLines(stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) {
|
||||
tooltip.addAll(Tooltip.get(unlocalizedName))
|
||||
}
|
||||
|
||||
override def icon(side: ForgeDirection) = Some(icons(side.ordinal()))
|
||||
|
||||
override def luminance(world: IBlockAccess, x: Int, y: Int, z: Int) = 15
|
||||
|
||||
override def isSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = side == ForgeDirection.DOWN
|
||||
|
||||
override def bounds(world: IBlockAccess, x: Int, y: Int, z: Int) =
|
||||
AxisAlignedBB.getAABBPool.getAABB(0, 0, 0, 1, 0.2f, 1)
|
||||
AxisAlignedBB.getAABBPool.getAABB(0, 0, 0, 1, 3 / 16f, 1)
|
||||
|
||||
override def itemBounds() {
|
||||
parent.setBlockBounds(AxisAlignedBB.getAABBPool.getAABB(0, 0, 0, 1, 3 / 16f, 1))
|
||||
}
|
||||
|
||||
override def registerIcons(iconRegister: IconRegister) = {
|
||||
icons(ForgeDirection.DOWN.ordinal) = iconRegister.registerIcon(Settings.resourceDomain + ":generic_top")
|
||||
icons(ForgeDirection.UP.ordinal) = iconRegister.registerIcon(Settings.resourceDomain + ":hologram_top")
|
||||
|
||||
icons(ForgeDirection.NORTH.ordinal) = iconRegister.registerIcon(Settings.resourceDomain + ":hologram_side")
|
||||
icons(ForgeDirection.SOUTH.ordinal) = icons(ForgeDirection.NORTH.ordinal)
|
||||
icons(ForgeDirection.WEST.ordinal) = icons(ForgeDirection.NORTH.ordinal)
|
||||
icons(ForgeDirection.EAST.ordinal) = icons(ForgeDirection.NORTH.ordinal)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
|
@ -34,15 +34,22 @@ class Hologram extends Environment with SidedEnvironment {
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@Callback(doc = """function() -- Clears the hologram.""")
|
||||
def clear(computer: Context, args: Arguments): Array[AnyRef] = this.synchronized {
|
||||
for (i <- 0 until volume.length) volume(i) = 0
|
||||
dirty = true
|
||||
null
|
||||
}
|
||||
|
||||
@Callback(direct = true, doc = """function(x:number, z:number):number -- Returns the bit mask representing the specified column.""")
|
||||
def get(computer: Context, args: Arguments): Array[AnyRef] = {
|
||||
def get(computer: Context, args: Arguments): Array[AnyRef] = this.synchronized {
|
||||
val x = args.checkInteger(0) - 1
|
||||
val z = args.checkInteger(1) - 1
|
||||
result(volume(x + z * width))
|
||||
}
|
||||
|
||||
@Callback(direct = true, limit = 256, doc = """function(x:number, z:number, value:number) -- Set the bit mask for the specified column.""")
|
||||
def set(computer: Context, args: Arguments): Array[AnyRef] = {
|
||||
def set(computer: Context, args: Arguments): Array[AnyRef] = this.synchronized {
|
||||
val x = args.checkInteger(0) - 1
|
||||
val z = args.checkInteger(1) - 1
|
||||
val value = args.checkInteger(2)
|
||||
@ -51,6 +58,18 @@ class Hologram extends Environment with SidedEnvironment {
|
||||
null
|
||||
}
|
||||
|
||||
@Callback(direct = true, limit = 128, doc = """function(x:number, z:number, height:number) -- Fills a column to the specified height.""")
|
||||
def fill(computer: Context, args: Arguments): Array[AnyRef] = this.synchronized {
|
||||
val x = args.checkInteger(0) - 1
|
||||
val z = args.checkInteger(1) - 1
|
||||
val height = math.min(32, math.max(0, args.checkInteger(2)))
|
||||
// Bit shifts in the JVM only use the lowest five bits... so we have to
|
||||
// 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
|
||||
null
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def updateEntity() {
|
||||
@ -67,14 +86,18 @@ class Hologram extends Environment with SidedEnvironment {
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def getRenderBoundingBox = AxisAlignedBB.getAABBPool.getAABB(xCoord - 1, yCoord, zCoord - 1, xCoord + 2, yCoord + 3, zCoord + 2)
|
||||
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 readFromNBT(nbt: NBTTagCompound) {
|
||||
super.readFromNBT(nbt)
|
||||
nbt.getIntArray(Settings.namespace + "volume").copyToArray(volume)
|
||||
}
|
||||
|
||||
override def writeToNBT(nbt: NBTTagCompound) {
|
||||
override def writeToNBT(nbt: NBTTagCompound) = this.synchronized {
|
||||
super.writeToNBT(nbt)
|
||||
nbt.setIntArray(Settings.namespace + "volume", volume)
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ oc:tile.Case2.name=Computergehäuse (Stufe 3)
|
||||
oc:tile.Charger.name=Ladestation
|
||||
oc:tile.DiskDrive.name=Diskettenlaufwerk
|
||||
oc:tile.Keyboard.name=Tastatur
|
||||
oc:tile.Hologram.name=Hologrammprojektor
|
||||
oc:tile.PowerConverter.name=Leistungswandler
|
||||
oc:tile.PowerDistributor.name=Stromverteiler
|
||||
oc:tile.Redstone.name=Redstone-I/O
|
||||
@ -136,6 +137,7 @@ oc:tooltip.GraphicsCard=Erlaubt es, den angezeigten Inhalt von Bildschirmen zu
|
||||
oc:tooltip.InternetCard=Diese Karte erlaubt es, HTTP-Anfragen zu senden und echte TCP Sockets zu verwenden.
|
||||
oc:tooltip.IronNugget=Ein Nugget, das aus Eisen besteht, darum wird es ja auch Eisennugget genannt, duh...
|
||||
oc:tooltip.Keyboard=Kann an Bildschirmen befestigt werden, um auf ihnen zu tippen.
|
||||
oc:tooltip.Hologram=Ein Volumendisplay das beliebige, von Computern festgelegte Voxelstrukturen anzeigt.[nl] Auflösung: §f48x32x48§7. [nl] Farbtiefe: §fMonochrom§7.
|
||||
oc:tooltip.Memory=Braucht ein jeder Computer, um zu starten. Je mehr vorhanden, desto komplexere Programme können ausgeführt werden.
|
||||
oc:tooltip.Microchip=Tritt auch unter dem Alias Integrierter Schaltkreis auf. Keine Ahnung, warum das auch mit Redstone klappt, aber es funktioniert.
|
||||
oc:tooltip.NetworkCard=Erlaubt es Computern, die über mehrere Blöcke miteinander verbunden sind (z.B. Kabel), mittels Netzwerknachrichten zu kommunizieren.
|
||||
|
@ -12,6 +12,7 @@ oc:tile.Case2.name=Computer Case (Tier 3)
|
||||
oc:tile.Charger.name=Charger
|
||||
oc:tile.DiskDrive.name=Disk Drive
|
||||
oc:tile.Keyboard.name=Keyboard
|
||||
oc:tile.Hologram.name=Hologram Projector
|
||||
oc:tile.PowerConverter.name=Power Converter
|
||||
oc:tile.PowerDistributor.name=Power Distributor
|
||||
oc:tile.Redstone.name=Redstone I/O
|
||||
@ -136,6 +137,7 @@ oc:tooltip.GraphicsCard=Used to change what's displayed on screens.[nl] Maximum
|
||||
oc:tooltip.InternetCard=This card allows making HTTP requests and using real TCP sockets.
|
||||
oc:tooltip.IronNugget=A nugget made of iron, that's why it's called an Iron Nugget, duh...
|
||||
oc:tooltip.Keyboard=Can be attached to screens to allow typing on them.
|
||||
oc:tooltip.Hologram=A volumetric display that can be controlled by computers to display arbitrary voxel structures.[nl] Resolution: §f48x32x48§7. [nl] Color depth: §fMonochrome§7.
|
||||
oc:tooltip.Memory=Required to get computers to run. The more you have, the more complex the programs you can run.
|
||||
oc:tooltip.Microchip=The chip formerly known as Integrated Circuit. I have no idea why this works with redstone, but it does.
|
||||
oc:tooltip.NetworkCard=Allows distant computers connected by other blocks (such as cable) to communicate by sending messages to each other.
|
||||
|
@ -1,5 +1,5 @@
|
||||
local hookInterval = 100
|
||||
local deadline = 0
|
||||
local deadline = math.huge
|
||||
local function checkDeadline()
|
||||
if computer.realTime() > deadline then
|
||||
debug.sethook(coroutine.running(), checkDeadline, "", 1)
|
||||
@ -91,7 +91,11 @@ sandbox = {
|
||||
loadfile = nil, -- in boot/*_base.lua
|
||||
next = next,
|
||||
pairs = pairs,
|
||||
pcall = pcall,
|
||||
pcall = function(...)
|
||||
local result = table.pack(pcall(...))
|
||||
checkDeadline()
|
||||
return table.unpack(result, 1, result.n)
|
||||
end,
|
||||
print = nil, -- in boot/*_base.lua
|
||||
rawequal = rawequal,
|
||||
rawget = rawget,
|
||||
@ -103,7 +107,11 @@ sandbox = {
|
||||
tostring = tostring,
|
||||
type = type,
|
||||
_VERSION = "Lua 5.2",
|
||||
xpcall = xpcall,
|
||||
xpcall = function(...)
|
||||
local result = table.pack(xpcall(...))
|
||||
checkDeadline()
|
||||
return table.unpack(result, 1, result.n)
|
||||
end,
|
||||
|
||||
coroutine = {
|
||||
create = function(f)
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 157 B After Width: | Height: | Size: 149 B |
Binary file not shown.
After Width: | Height: | Size: 185 B |
Binary file not shown.
After Width: | Height: | Size: 421 B |
Loading…
x
Reference in New Issue
Block a user