mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-12 16:57:32 -04:00
more color screen stuff; made advanced screen 4 bit, pro screen 8 bit (which is actually pretty much for a pseudo computer in a game with 16x16 textures...); depth can be dynamically changed; colors are always provided as 32bit rgb from the lua side to make things easier, so it's ok to call these even on a color-less gpu+screen; added vertical gap between chars in char texture to avoid bleeding when interpolating due to downscaling; made some programs use colors (sh, lua and ls); screw scanlines, aliasing is too much of a pain
This commit is contained in:
parent
4ee76b146d
commit
0c8347df62
@ -13,7 +13,19 @@ for i = 1, #dirs do
|
||||
if not list then
|
||||
print(reason)
|
||||
else
|
||||
local function setColor(c)
|
||||
if component.gpu.getForeground() ~= c then
|
||||
component.gpu.setForeground(c)
|
||||
end
|
||||
end
|
||||
for f in list do
|
||||
if f:sub(-1) == "/" then
|
||||
setColor(0x99CCFF)
|
||||
elseif f:sub(-4) == ".lua" then
|
||||
setColor(0x00FF00)
|
||||
else
|
||||
setColor(0xFFFFFF)
|
||||
end
|
||||
if options.a or f:sub(1, 1) ~= "." then
|
||||
if options.l then
|
||||
print(f, fs.size(fs.concat(path, f)))
|
||||
@ -22,6 +34,7 @@ for i = 1, #dirs do
|
||||
end
|
||||
end
|
||||
end
|
||||
setColor(0xFFFFFF)
|
||||
if not options.l then
|
||||
print()
|
||||
end
|
||||
|
@ -2,7 +2,9 @@ print("Lua 5.2.2 Copyright (C) 1994-2013 Lua.org, PUC-Rio")
|
||||
local history = {}
|
||||
local env = setmetatable({}, {__index=_ENV})
|
||||
while term.isAvailable() do
|
||||
local foreground = component.gpu.setForeground(0x00FF00)
|
||||
term.write("lua> ")
|
||||
component.gpu.setForeground(foreground)
|
||||
local command = term.read(history)
|
||||
if command == nil then -- eof
|
||||
return
|
||||
|
@ -16,7 +16,9 @@ while true do
|
||||
end
|
||||
end
|
||||
while term.isAvailable() do
|
||||
local foreground = component.gpu.setForeground(0xFF0000)
|
||||
term.write("# ")
|
||||
component.gpu.setForeground(foreground)
|
||||
local command = term.read(history)
|
||||
if not command then
|
||||
print("exit")
|
||||
|
@ -4,8 +4,6 @@ local function onComponentAvailable(_, componentType)
|
||||
then
|
||||
local gpu = component.primary("gpu")
|
||||
gpu.bind(component.primary("screen").address)
|
||||
local maxX, maxY = gpu.maxResolution()
|
||||
gpu.setResolution(maxX, maxY)
|
||||
end
|
||||
end
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 13 KiB |
@ -1,6 +1,7 @@
|
||||
package li.cil.oc
|
||||
|
||||
import java.io.File
|
||||
import li.cil.oc.util.PackedColor
|
||||
|
||||
object Config {
|
||||
val resourceDomain = "opencomputers"
|
||||
@ -10,6 +11,7 @@ object Config {
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
val screenResolutionsByTier = Array((50, 16), (80, 25), (160, 50))
|
||||
val screenDepthsByTier = Array(PackedColor.Depth.OneBit, PackedColor.Depth.FourBit, PackedColor.Depth.EightBit)
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@ -39,6 +41,7 @@ object Config {
|
||||
|
||||
var maxScreenTextRenderDistance = 10.0
|
||||
var screenTextFadeStartDistance = 8.0
|
||||
var textLinearFiltering = false
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@ -97,6 +100,15 @@ object Config {
|
||||
"instantly disappear when moving away from the screen displaying it.").
|
||||
getDouble(screenTextFadeStartDistance)
|
||||
|
||||
textLinearFiltering = config.get("client", "textLinearFiltering", textLinearFiltering, "" +
|
||||
"Whether to apply linear filtering for text displayed on screens when the\n" +
|
||||
"screen has to be scaled down - i.e. the text is rendered at a resolution\n" +
|
||||
"lower than their native one, e.g. when the GUI scale is less than one or\n" +
|
||||
"when looking at a far away screen. This leads to smoother text for scaled\n" +
|
||||
"down text but results in characters not perfectly connecting anymore (for\n" +
|
||||
"example for box drawing characters. Look it up on Wikipedia.)").
|
||||
getBoolean(textLinearFiltering)
|
||||
|
||||
// --------------------------------------------------------------------- //
|
||||
|
||||
config.getCategory("power").
|
||||
|
@ -5,6 +5,7 @@ import li.cil.oc.common.PacketType
|
||||
import li.cil.oc.common.tileentity.{PowerDistributor, Computer, Rotatable, Screen}
|
||||
import li.cil.oc.common.{PacketHandler => CommonPacketHandler}
|
||||
import li.cil.oc.server.component.Redstone
|
||||
import li.cil.oc.util.PackedColor
|
||||
import net.minecraft.client.gui.GuiScreen
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
@ -25,7 +26,9 @@ class PacketHandler extends CommonPacketHandler {
|
||||
case PacketType.RedstoneStateResponse => onRedstoneStateResponse(p)
|
||||
case PacketType.RotatableStateResponse => onRotatableStateResponse(p)
|
||||
case PacketType.ScreenBufferResponse => onScreenBufferResponse(p)
|
||||
case PacketType.ScreenColorChange => onScreenColorChange(p)
|
||||
case PacketType.ScreenCopy => onScreenCopy(p)
|
||||
case PacketType.ScreenDepthChange => onScreenDepthChange(p)
|
||||
case PacketType.ScreenFill => onScreenFill(p)
|
||||
case PacketType.ScreenResolutionChange => onScreenResolutionChange(p)
|
||||
case PacketType.ScreenSet => onScreenSet(p)
|
||||
@ -74,12 +77,31 @@ class PacketHandler extends CommonPacketHandler {
|
||||
def onScreenBufferResponse(p: PacketParser) =
|
||||
p.readTileEntity[Screen]() match {
|
||||
case Some(t) =>
|
||||
val screen = t.instance
|
||||
val w = p.readInt()
|
||||
val h = p.readInt()
|
||||
t.instance.resolution = (w, h)
|
||||
screen.resolution = (w, h)
|
||||
p.readUTF.split('\n').zipWithIndex.foreach {
|
||||
case (line, i) => t.instance.set(0, i, line)
|
||||
case (line, i) => screen.set(0, i, line)
|
||||
}
|
||||
screen.depth = PackedColor.Depth(p.readInt())
|
||||
screen.foreground = p.readInt()
|
||||
screen.background = p.readInt()
|
||||
for (row <- 0 until h) {
|
||||
val rowColor = screen.colors(row)
|
||||
for (col <- 0 until w) {
|
||||
rowColor(col) = p.readShort()
|
||||
}
|
||||
}
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onScreenColorChange(p: PacketParser) =
|
||||
p.readTileEntity[Screen]() match {
|
||||
case Some(t) => {
|
||||
t.instance.foreground = p.readInt()
|
||||
t.instance.background = p.readInt()
|
||||
}
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
@ -97,6 +119,14 @@ class PacketHandler extends CommonPacketHandler {
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onScreenDepthChange(p: PacketParser) =
|
||||
p.readTileEntity[Screen]() match {
|
||||
case Some(t) => {
|
||||
t.instance.depth = PackedColor.Depth(p.readInt())
|
||||
}
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onScreenFill(p: PacketParser) =
|
||||
p.readTileEntity[Screen]() match {
|
||||
case Some(t) => {
|
||||
|
@ -4,6 +4,7 @@ import li.cil.oc.Config
|
||||
import li.cil.oc.client.PacketSender
|
||||
import li.cil.oc.client.renderer.MonospaceFontRenderer
|
||||
import li.cil.oc.common.tileentity
|
||||
import li.cil.oc.util.PackedColor
|
||||
import net.minecraft.client.gui.{GuiScreen => MCGuiScreen}
|
||||
import net.minecraft.client.renderer.GLAllocation
|
||||
import net.minecraft.client.renderer.Tessellator
|
||||
@ -12,7 +13,6 @@ import net.minecraft.util.ResourceLocation
|
||||
import org.lwjgl.input.Keyboard
|
||||
import org.lwjgl.opengl.GL11
|
||||
import scala.collection.mutable
|
||||
import li.cil.oc.util.PackedColor
|
||||
|
||||
/**
|
||||
* This GUI shows the buffer of a single screen.
|
||||
@ -184,9 +184,11 @@ object Screen {
|
||||
GL11.glEndList()
|
||||
}
|
||||
|
||||
private[gui] def compileText(scale: Double, lines: Array[Array[Char]], colors:Array[Array[Int]], depth: PackedColor.Depth.Value) =
|
||||
private[gui] def compileText(scale: Double, lines: Array[Array[Char]], colors: Array[Array[Short]], depth: PackedColor.Depth.Value) =
|
||||
if (textureManager.isDefined) {
|
||||
GL11.glNewList(displayLists.get + 1, GL11.GL_COMPILE)
|
||||
GL11.glPushAttrib(GL11.GL_DEPTH_BUFFER_BIT)
|
||||
GL11.glDepthMask(false)
|
||||
|
||||
GL11.glTranslatef(margin + innerMargin, margin + innerMargin, 0)
|
||||
GL11.glScaled(scale, scale, 1)
|
||||
@ -194,6 +196,7 @@ object Screen {
|
||||
case ((line, color), i) => MonospaceFontRenderer.drawString(0, i * MonospaceFontRenderer.fontHeight, line, color, depth)
|
||||
}
|
||||
|
||||
GL11.glPopAttrib()
|
||||
GL11.glEndList()
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
package li.cil.oc.client.renderer
|
||||
|
||||
import li.cil.oc.util.{RenderState, PackedColor}
|
||||
import li.cil.oc.util.PackedColor
|
||||
import li.cil.oc.{OpenComputers, Config}
|
||||
import net.minecraft.client.renderer.GLAllocation
|
||||
import net.minecraft.client.renderer.Tessellator
|
||||
@ -10,7 +10,7 @@ import org.lwjgl.opengl.GL11
|
||||
import scala.io.Source
|
||||
|
||||
object MonospaceFontRenderer {
|
||||
private val font = new ResourceLocation(Config.resourceDomain, "textures/font/chars.png")
|
||||
val font = new ResourceLocation(Config.resourceDomain, "textures/font/chars.png")
|
||||
|
||||
private val chars = Source.fromInputStream(MonospaceFontRenderer.getClass.getResourceAsStream("/assets/" + Config.resourceDomain + "/textures/font/chars.txt")).mkString
|
||||
|
||||
@ -21,7 +21,7 @@ object MonospaceFontRenderer {
|
||||
|
||||
val (fontWidth, fontHeight) = (5, 9)
|
||||
|
||||
def drawString(x: Int, y: Int, value: Array[Char], color: Array[Int], depth: PackedColor.Depth.Value) = instance match {
|
||||
def drawString(x: Int, y: Int, value: Array[Char], color: Array[Short], depth: PackedColor.Depth.Value) = instance match {
|
||||
case None => OpenComputers.log.warning("Trying to render string with uninitialized MonospaceFontRenderer.")
|
||||
case Some(renderer) => renderer.drawString(x, y, value, color, depth)
|
||||
}
|
||||
@ -36,7 +36,9 @@ object MonospaceFontRenderer {
|
||||
private val (charWidth, charHeight) = (MonospaceFontRenderer.fontWidth * 2, MonospaceFontRenderer.fontHeight * 2)
|
||||
private val cols = 256 / charWidth
|
||||
private val uStep = charWidth / 256.0
|
||||
private val vStep = charHeight / 256.0
|
||||
private val uSize = uStep
|
||||
private val vStep = (charHeight + 1) / 256.0
|
||||
private val vSize = charHeight / 256.0
|
||||
|
||||
// Set up the display lists.
|
||||
{
|
||||
@ -49,9 +51,9 @@ object MonospaceFontRenderer {
|
||||
val v = y * vStep
|
||||
GL11.glNewList(charLists + index, GL11.GL_COMPILE)
|
||||
t.startDrawingQuads()
|
||||
t.addVertexWithUV(0, charHeight, 0, u, v + vStep)
|
||||
t.addVertexWithUV(charWidth, charHeight, 0, u + uStep, v + vStep)
|
||||
t.addVertexWithUV(charWidth, 0, 0, u + uStep, v)
|
||||
t.addVertexWithUV(0, charHeight, 0, u, v + vSize)
|
||||
t.addVertexWithUV(charWidth, charHeight, 0, u + uSize, v + vSize)
|
||||
t.addVertexWithUV(charWidth, 0, 0, u + uSize, v)
|
||||
t.addVertexWithUV(0, 0, 0, u, v)
|
||||
t.draw()
|
||||
GL11.glTranslatef(charWidth, 0, 0)
|
||||
@ -63,35 +65,39 @@ object MonospaceFontRenderer {
|
||||
GL11.glEndList()
|
||||
}
|
||||
|
||||
def drawString(x: Int, y: Int, value: Array[Char], color: Array[Int], depth: PackedColor.Depth.Value) = {
|
||||
def drawString(x: Int, y: Int, value: Array[Char], color: Array[Short], depth: PackedColor.Depth.Value) = {
|
||||
if (color.length != value.length) throw new IllegalArgumentException("Color count must match char count.")
|
||||
|
||||
textureManager.bindTexture(MonospaceFontRenderer.font)
|
||||
GL11.glPushMatrix()
|
||||
GL11.glPushAttrib(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT)
|
||||
GL11.glPushAttrib(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_TEXTURE_BIT)
|
||||
GL11.glTranslatef(x, y, 0)
|
||||
GL11.glScalef(0.5f, 0.5f, 1)
|
||||
GL11.glDepthMask(false)
|
||||
RenderState.makeItBlend()
|
||||
|
||||
// Background first. We try to merge adjacent backgrounds of the same
|
||||
// color to reduce the number of quads we have to draw.
|
||||
var cbg = 0x000000
|
||||
var offset = 0
|
||||
var width = 0
|
||||
for (col <- color.map(PackedColor.unpackBackground(_, depth))) {
|
||||
if (col != cbg) {
|
||||
draw(cbg, width)
|
||||
draw(cbg, offset, width)
|
||||
cbg = col
|
||||
offset += width
|
||||
width = 0
|
||||
}
|
||||
width = width + 1
|
||||
}
|
||||
draw(cbg, width)
|
||||
draw(cbg, offset, width)
|
||||
|
||||
if (Config.textLinearFiltering) {
|
||||
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR)
|
||||
}
|
||||
|
||||
// Foreground second. We only have to flush when the color changes, so
|
||||
// unless every char has a different color this should be quite efficient.
|
||||
var cfg = 0x000000
|
||||
GL11.glColor3f(0, 0, 0)
|
||||
var cfg = -1
|
||||
for ((ch, col) <- value.zip(color.map(PackedColor.unpackForeground(_, depth)))) {
|
||||
val index = 1 + chars.indexOf(ch) match {
|
||||
case -1 => chars.indexOf('?')
|
||||
@ -102,9 +108,9 @@ object MonospaceFontRenderer {
|
||||
flush()
|
||||
cfg = col
|
||||
GL11.glColor3ub(
|
||||
(cfg & 0xFF0000 >> 16).toByte,
|
||||
(cfg & 0x00FF00 >> 8).toByte,
|
||||
(cfg & 0x0000FF).toByte)
|
||||
((cfg & 0xFF0000) >> 16).toByte,
|
||||
((cfg & 0x00FF00) >> 8).toByte,
|
||||
((cfg & 0x0000FF) >> 0).toByte)
|
||||
}
|
||||
listBuffer.put(charLists + index)
|
||||
if (listBuffer.remaining == 0)
|
||||
@ -116,18 +122,23 @@ object MonospaceFontRenderer {
|
||||
GL11.glPopMatrix()
|
||||
}
|
||||
|
||||
private def draw(color: Int, width: Int) = if (color != 0 && width > 0) {
|
||||
private val bgu1 = 254.0 / 256.0
|
||||
private val bgu2 = 255.0 / 256.0
|
||||
private val bgv1 = 255.0 / 256.0
|
||||
private val bgv2 = 256.0 / 256.0
|
||||
|
||||
private def draw(color: Int, offset: Int, width: Int) = if (color != 0 && width > 0) {
|
||||
val t = Tessellator.instance
|
||||
t.startDrawingQuads()
|
||||
t.setColorOpaque_I(color)
|
||||
t.addVertexWithUV(0, charHeight, 0, 0, vStep)
|
||||
t.addVertexWithUV(charWidth, charHeight, 0, width * uStep, vStep)
|
||||
t.addVertexWithUV(charWidth, 0, 0, width * uStep, 0)
|
||||
t.addVertexWithUV(0, 0, 0, 0, 0)
|
||||
t.addVertexWithUV(charWidth * offset, charHeight, 0, bgu1, bgv2)
|
||||
t.addVertexWithUV(charWidth * (offset + width), charHeight, 0, bgu2, bgv2)
|
||||
t.addVertexWithUV(charWidth * (offset + width), 0, 0, bgu2, bgv1)
|
||||
t.addVertexWithUV(charWidth * offset, 0, 0, bgu1, bgv1)
|
||||
t.draw()
|
||||
}
|
||||
|
||||
private def flush() = {
|
||||
private def flush() = if (listBuffer.position > 0) {
|
||||
listBuffer.flip()
|
||||
GL11.glCallLists(listBuffer)
|
||||
listBuffer.clear()
|
||||
|
@ -34,7 +34,9 @@ object PacketType extends Enumeration {
|
||||
val ScreenBufferResponse = Value("ScreenBufferResponse")
|
||||
|
||||
/** These are sent from the server to the client for partial updates. */
|
||||
val ScreenColorChange = Value("ScreenColorChange")
|
||||
val ScreenCopy = Value("ScreenCopy")
|
||||
val ScreenDepthChange = Value("ScreenDepthChange")
|
||||
val ScreenFill = Value("ScreenFill")
|
||||
val ScreenResolutionChange = Value("ScreenResolutionChange")
|
||||
val ScreenSet = Value("ScreenSet")
|
||||
|
@ -7,7 +7,7 @@ import li.cil.oc.util.{PackedColor, TextBuffer}
|
||||
import li.cil.oc.{Config, util, api}
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
|
||||
class Screen(val owner: Screen.Environment, val maxResolution: (Int, Int)) extends Persistable {
|
||||
class Screen(val owner: Screen.Environment, val maxResolution: (Int, Int), val maxDepth: PackedColor.Depth.Value) extends Persistable {
|
||||
private val buffer = new TextBuffer(maxResolution, PackedColor.Depth.OneBit)
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
@ -20,12 +20,48 @@ class Screen(val owner: Screen.Environment, val maxResolution: (Int, Int)) exten
|
||||
|
||||
def depth = buffer.depth
|
||||
|
||||
def depth_=(value: PackedColor.Depth.Value) = {
|
||||
if (value > maxDepth)
|
||||
throw new IllegalArgumentException("unsupported depth")
|
||||
if (buffer.depth = value) {
|
||||
owner.onScreenDepthChange(value)
|
||||
true
|
||||
}
|
||||
else false
|
||||
}
|
||||
|
||||
def foreground = buffer.foreground
|
||||
|
||||
def foreground_=(value: Int) = {
|
||||
if (buffer.foreground != value) {
|
||||
val result = buffer.foreground
|
||||
buffer.foreground = value
|
||||
owner.onScreenColorChange(foreground, background)
|
||||
result
|
||||
}
|
||||
else value
|
||||
}
|
||||
|
||||
def background = buffer.background
|
||||
|
||||
def background_=(value: Int) = {
|
||||
if (buffer.background != value) {
|
||||
val result = buffer.background
|
||||
buffer.background = value
|
||||
owner.onScreenColorChange(foreground, background)
|
||||
result
|
||||
}
|
||||
else value
|
||||
}
|
||||
|
||||
def resolution = buffer.size
|
||||
|
||||
def resolution_=(value: (Int, Int)) = {
|
||||
val (w, h) = value
|
||||
val (mw, mh) = maxResolution
|
||||
if (w <= mw && h <= mh && (buffer.size = value)) {
|
||||
if (w < 1 || w > mw || h < 1 || h > mh)
|
||||
throw new IllegalArgumentException("unsupported resolution")
|
||||
if (buffer.size = value) {
|
||||
owner.onScreenResolutionChange(w, h)
|
||||
true
|
||||
}
|
||||
@ -58,12 +94,12 @@ class Screen(val owner: Screen.Environment, val maxResolution: (Int, Int)) exten
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def load(nbt: NBTTagCompound) = {
|
||||
buffer.readFromNBT(nbt.getCompoundTag("oc.screen"))
|
||||
buffer.load(nbt.getCompoundTag("oc.screen"))
|
||||
}
|
||||
|
||||
override def save(nbt: NBTTagCompound) = {
|
||||
val screenNbt = new NBTTagCompound
|
||||
buffer.writeToNBT(screenNbt)
|
||||
buffer.save(screenNbt)
|
||||
nbt.setCompoundTag("oc.screen", screenNbt)
|
||||
}
|
||||
|
||||
@ -81,7 +117,7 @@ object Screen {
|
||||
withConnector(Config.bufferScreen * (tier + 1)).
|
||||
create()
|
||||
|
||||
final val instance = new component.Screen(this, Config.screenResolutionsByTier(tier))
|
||||
final val instance = new component.Screen(this, Config.screenResolutionsByTier(tier), Config.screenDepthsByTier(tier))
|
||||
|
||||
protected def tier: Int
|
||||
|
||||
@ -101,8 +137,12 @@ object Screen {
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
def onScreenColorChange(foreground: Int, background: Int) {}
|
||||
|
||||
def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) {}
|
||||
|
||||
def onScreenDepthChange(depth: PackedColor.Depth.Value) {}
|
||||
|
||||
def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char) {}
|
||||
|
||||
def onScreenResolutionChange(w: Int, h: Int) {
|
||||
|
@ -8,6 +8,8 @@ class GraphicsCard(val parent: Delegator, val tier: Int) extends Delegate {
|
||||
|
||||
val maxResolution = Config.screenResolutionsByTier(tier)
|
||||
|
||||
val maxDepth = Config.screenDepthsByTier(tier)
|
||||
|
||||
override def registerIcons(iconRegister: IconRegister) {
|
||||
super.registerIcons(iconRegister)
|
||||
|
||||
|
@ -7,11 +7,12 @@ import li.cil.oc.client.gui
|
||||
import li.cil.oc.client.{PacketSender => ClientPacketSender}
|
||||
import li.cil.oc.common.component.Screen.{Environment => ScreenEnvironment}
|
||||
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
||||
import li.cil.oc.util.PackedColor
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.util.AxisAlignedBB
|
||||
import net.minecraftforge.common.ForgeDirection
|
||||
import scala.collection.mutable
|
||||
import net.minecraft.client.Minecraft
|
||||
|
||||
class ScreenTier1 extends Screen {
|
||||
protected def tier = 0
|
||||
@ -225,6 +226,46 @@ abstract class Screen extends Rotatable with ScreenEnvironment {
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def onScreenColorChange(foreground: Int, background: Int) {
|
||||
super.onScreenColorChange(foreground, background)
|
||||
if (!worldObj.isRemote) {
|
||||
worldObj.markTileEntityChunkModified(xCoord, yCoord, zCoord, this)
|
||||
ServerPacketSender.sendScreenColorChange(this, foreground, background)
|
||||
}
|
||||
}
|
||||
|
||||
override def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) = {
|
||||
super.onScreenCopy(col, row, w, h, tx, ty)
|
||||
if (worldObj.isRemote) {
|
||||
currentGui.foreach(_.updateText())
|
||||
hasChanged = true
|
||||
}
|
||||
else {
|
||||
worldObj.markTileEntityChunkModified(xCoord, yCoord, zCoord, this)
|
||||
ServerPacketSender.sendScreenCopy(this, col, row, w, h, tx, ty)
|
||||
}
|
||||
}
|
||||
|
||||
override def onScreenDepthChange(depth: PackedColor.Depth.Value) {
|
||||
super.onScreenDepthChange(depth)
|
||||
if (!worldObj.isRemote) {
|
||||
worldObj.markTileEntityChunkModified(xCoord, yCoord, zCoord, this)
|
||||
ServerPacketSender.sendScreenDepthChange(this, depth)
|
||||
}
|
||||
}
|
||||
|
||||
override def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char) = {
|
||||
super.onScreenFill(col, row, w, h, c)
|
||||
if (worldObj.isRemote) {
|
||||
currentGui.foreach(_.updateText())
|
||||
hasChanged = true
|
||||
}
|
||||
else {
|
||||
worldObj.markTileEntityChunkModified(xCoord, yCoord, zCoord, this)
|
||||
ServerPacketSender.sendScreenFill(this, col, row, w, h, c)
|
||||
}
|
||||
}
|
||||
|
||||
override def onScreenResolutionChange(w: Int, h: Int) = {
|
||||
super.onScreenResolutionChange(w, h)
|
||||
if (worldObj.isRemote) {
|
||||
@ -248,28 +289,4 @@ abstract class Screen extends Rotatable with ScreenEnvironment {
|
||||
ServerPacketSender.sendScreenSet(this, col, row, s)
|
||||
}
|
||||
}
|
||||
|
||||
override def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char) = {
|
||||
super.onScreenFill(col, row, w, h, c)
|
||||
if (worldObj.isRemote) {
|
||||
currentGui.foreach(_.updateText())
|
||||
hasChanged = true
|
||||
}
|
||||
else {
|
||||
worldObj.markTileEntityChunkModified(xCoord, yCoord, zCoord, this)
|
||||
ServerPacketSender.sendScreenFill(this, col, row, w, h, c)
|
||||
}
|
||||
}
|
||||
|
||||
override def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) = {
|
||||
super.onScreenCopy(col, row, w, h, tx, ty)
|
||||
if (worldObj.isRemote) {
|
||||
currentGui.foreach(_.updateText())
|
||||
hasChanged = true
|
||||
}
|
||||
else {
|
||||
worldObj.markTileEntityChunkModified(xCoord, yCoord, zCoord, this)
|
||||
ServerPacketSender.sendScreenCopy(this, col, row, w, h, tx, ty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,9 +52,7 @@ class PacketHandler extends CommonPacketHandler {
|
||||
|
||||
def onScreenBufferRequest(p: PacketParser) =
|
||||
p.readTileEntity[tileentity.Screen]() match {
|
||||
case Some(t) =>
|
||||
val (w, h) = t.instance.resolution
|
||||
PacketSender.sendScreenBufferState(t, w, h, t.instance.text, Option(p.player))
|
||||
case Some(t) => PacketSender.sendScreenBufferState(t, Option(p.player))
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
|
@ -3,8 +3,10 @@ package li.cil.oc.server
|
||||
import cpw.mods.fml.common.network.Player
|
||||
import li.cil.oc.common.PacketBuilder
|
||||
import li.cil.oc.common.PacketType
|
||||
import li.cil.oc.common.component.Screen
|
||||
import li.cil.oc.common.tileentity.{PowerDistributor, Rotatable}
|
||||
import li.cil.oc.server.component.Redstone
|
||||
import li.cil.oc.util.PackedColor
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraftforge.common.ForgeDirection
|
||||
|
||||
@ -70,13 +72,20 @@ object PacketSender {
|
||||
}
|
||||
}
|
||||
|
||||
def sendScreenBufferState(t: TileEntity, w: Int, h: Int, text: String, player: Option[Player] = None) {
|
||||
def sendScreenBufferState(t: TileEntity with Screen.Environment, player: Option[Player] = None) {
|
||||
val pb = new PacketBuilder(PacketType.ScreenBufferResponse)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
|
||||
val screen = t.instance
|
||||
val (w, h) = screen.resolution
|
||||
pb.writeInt(w)
|
||||
pb.writeInt(h)
|
||||
pb.writeUTF(text)
|
||||
pb.writeUTF(screen.text)
|
||||
pb.writeInt(screen.depth.id)
|
||||
pb.writeInt(screen.foreground)
|
||||
pb.writeInt(screen.background)
|
||||
for (cs <- screen.colors) for (c <- cs) pb.writeShort(c)
|
||||
|
||||
player match {
|
||||
case Some(p) => pb.sendToPlayer(p)
|
||||
@ -84,6 +93,16 @@ object PacketSender {
|
||||
}
|
||||
}
|
||||
|
||||
def sendScreenColorChange(t: TileEntity, foreground: Int, background: Int) {
|
||||
val pb = new PacketBuilder(PacketType.ScreenColorChange)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
pb.writeInt(foreground)
|
||||
pb.writeInt(background)
|
||||
|
||||
pb.sendToAllPlayers()
|
||||
}
|
||||
|
||||
def sendScreenCopy(t: TileEntity, col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) {
|
||||
val pb = new PacketBuilder(PacketType.ScreenCopy)
|
||||
|
||||
@ -98,6 +117,15 @@ object PacketSender {
|
||||
pb.sendToAllPlayers()
|
||||
}
|
||||
|
||||
def sendScreenDepthChange(t: TileEntity, value: PackedColor.Depth.Value) {
|
||||
val pb = new PacketBuilder(PacketType.ScreenDepthChange)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
pb.writeInt(value.id)
|
||||
|
||||
pb.sendToAllPlayers()
|
||||
}
|
||||
|
||||
def sendScreenFill(t: TileEntity, col: Int, row: Int, w: Int, h: Int, c: Char) {
|
||||
val pb = new PacketBuilder(PacketType.ScreenFill)
|
||||
|
||||
|
@ -3,10 +3,11 @@ package li.cil.oc.server.component
|
||||
import li.cil.oc.api
|
||||
import li.cil.oc.api.network._
|
||||
import li.cil.oc.common.component.Screen
|
||||
import li.cil.oc.util.PackedColor
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import scala.Some
|
||||
|
||||
class GraphicsCard(val maxResolution: (Int, Int)) extends ManagedComponent {
|
||||
class GraphicsCard(val maxResolution: (Int, Int), val maxDepth: PackedColor.Depth.Value) extends ManagedComponent {
|
||||
val node = api.Network.newNode(this, Visibility.Neighbors).
|
||||
withComponent("gpu").
|
||||
create()
|
||||
@ -15,7 +16,7 @@ class GraphicsCard(val maxResolution: (Int, Int)) extends ManagedComponent {
|
||||
|
||||
private var screenInstance: Option[Screen] = None
|
||||
|
||||
private def screen(f: (Screen) => Array[AnyRef]) = {
|
||||
private def screen(f: (Screen) => Array[AnyRef]) = this.synchronized {
|
||||
if (screenInstance.isEmpty && screenAddress.isDefined) {
|
||||
Option(node.network.node(screenAddress.get)) match {
|
||||
case Some(node: Node) if node.host.isInstanceOf[Screen.Environment] =>
|
||||
@ -38,18 +39,73 @@ class GraphicsCard(val maxResolution: (Int, Int)) extends ManagedComponent {
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@LuaCallback("bind")
|
||||
def bind(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def bind(context: Context, args: Arguments): Array[AnyRef] = this.synchronized {
|
||||
val address = args.checkString(0)
|
||||
node.network.node(address) match {
|
||||
case null => Array(Unit, "invalid address")
|
||||
case node: Node if node.host.isInstanceOf[Screen.Environment] =>
|
||||
screenAddress = Option(address)
|
||||
screenInstance = None
|
||||
result(true)
|
||||
screen(s => {
|
||||
val (gmw, gmh) = maxResolution
|
||||
val (smw, smh) = s.maxResolution
|
||||
s.resolution = (gmw min smw, gmh min smh)
|
||||
s.depth = PackedColor.Depth(maxDepth.id min s.maxDepth.id)
|
||||
s.foreground = 0xFFFFFF
|
||||
s.background = 0x000000
|
||||
result(true)
|
||||
})
|
||||
case _ => Array(Unit, "not a screen")
|
||||
}
|
||||
}
|
||||
|
||||
@LuaCallback(value = "getBackground", direct = true)
|
||||
def getBackground(context: Context, args: Arguments): Array[AnyRef] =
|
||||
screen(s => result(s.background))
|
||||
|
||||
@LuaCallback("setBackground")
|
||||
def setBackground(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val color = args.checkInteger(0)
|
||||
screen(s => result(s.background = color))
|
||||
}
|
||||
|
||||
@LuaCallback(value = "getForeground", direct = true)
|
||||
def getForeground(context: Context, args: Arguments): Array[AnyRef] =
|
||||
screen(s => result(s.foreground))
|
||||
|
||||
@LuaCallback("setForeground")
|
||||
def setForeground(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val color = args.checkInteger(0)
|
||||
screen(s => result(s.foreground = color))
|
||||
}
|
||||
|
||||
@LuaCallback(value = "getDepth", direct = true)
|
||||
def getDepth(context: Context, args: Arguments): Array[AnyRef] =
|
||||
screen(s => result(s.depth match {
|
||||
case PackedColor.Depth.OneBit => 1
|
||||
case PackedColor.Depth.FourBit => 4
|
||||
case PackedColor.Depth.EightBit => 8
|
||||
}))
|
||||
|
||||
@LuaCallback("setDepth")
|
||||
def setDepth(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val depth = args.checkInteger(0)
|
||||
screen(s => result(s.depth = depth match {
|
||||
case 1 => PackedColor.Depth.OneBit
|
||||
case 4 if maxDepth >= PackedColor.Depth.FourBit => PackedColor.Depth.FourBit
|
||||
case 8 if maxDepth >= PackedColor.Depth.EightBit => PackedColor.Depth.EightBit
|
||||
case _ => throw new IllegalArgumentException("unsupported depth")
|
||||
}))
|
||||
}
|
||||
|
||||
@LuaCallback(value = "maxDepth", direct = true)
|
||||
def maxDepth(context: Context, args: Arguments): Array[AnyRef] =
|
||||
screen(s => result(PackedColor.Depth(maxDepth.id min s.maxDepth.id) match {
|
||||
case PackedColor.Depth.OneBit => 1
|
||||
case PackedColor.Depth.FourBit => 4
|
||||
case PackedColor.Depth.EightBit => 8
|
||||
}))
|
||||
|
||||
@LuaCallback(value = "getResolution", direct = true)
|
||||
def getResolution(context: Context, args: Arguments): Array[AnyRef] =
|
||||
screen(s => {
|
||||
@ -62,10 +118,8 @@ class GraphicsCard(val maxResolution: (Int, Int)) extends ManagedComponent {
|
||||
val w = args.checkInteger(0)
|
||||
val h = args.checkInteger(1)
|
||||
val (mw, mh) = maxResolution
|
||||
if (w > 0 && h > 0 && w <= mw && h <= mh)
|
||||
screen(s => result(s.resolution = (w, h)))
|
||||
else
|
||||
Array(Unit, "unsupported resolution")
|
||||
if (w > 0 && h > 0 && w <= mw && h <= mh) screen(s => result(s.resolution = (w, h)))
|
||||
else throw new IllegalArgumentException("unsupported resolution")
|
||||
}
|
||||
|
||||
@LuaCallback(value = "maxResolution", direct = true)
|
||||
|
@ -12,7 +12,7 @@ object GraphicsCard extends Item {
|
||||
override def createEnvironment(item: ItemStack, container: AnyRef) =
|
||||
Items.multi.subItem(item) match {
|
||||
case Some(gpu: common.item.GraphicsCard) =>
|
||||
new component.GraphicsCard(gpu.maxResolution)
|
||||
new component.GraphicsCard(gpu.maxResolution, gpu.maxDepth)
|
||||
case _ => null
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ package li.cil.oc.util
|
||||
object PackedColor {
|
||||
|
||||
object Depth extends Enumeration {
|
||||
val OneBit, EightBit, SixteenBit = Value
|
||||
val OneBit, FourBit, EightBit = Value
|
||||
}
|
||||
|
||||
private val rMask32 = 0xFF0000
|
||||
@ -13,88 +13,65 @@ object PackedColor {
|
||||
private val gShift32 = 8
|
||||
private val bShift32 = 0
|
||||
|
||||
// 7 6 5 4 3 2 1 0
|
||||
// r r r g g g b b : 3.3.2
|
||||
private val rMask8 = Integer.parseInt("11100000", 2)
|
||||
private val gMask8 = Integer.parseInt("00011100", 2)
|
||||
private val bMask8 = Integer.parseInt("00000011", 2)
|
||||
private val rShift8 = 5
|
||||
private val gShift8 = 2
|
||||
private val bShift8 = 0
|
||||
private val rScale8 = 255.0 / 0x7
|
||||
private val gScale8 = 255.0 / 0x7
|
||||
private val bScale8 = 255.0 / 0x3
|
||||
private abstract class ColorFormat {
|
||||
def inflate(value: Int): Int
|
||||
|
||||
// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
// r r r r r g g g g g g b b b b b : 5.6.5
|
||||
private val rMask16 = Integer.parseInt("1111100000000000", 2)
|
||||
private val gMask16 = Integer.parseInt("0000011111100000", 2)
|
||||
private val bMask16 = Integer.parseInt("0000000000011111", 2)
|
||||
private val rShift16 = 11
|
||||
private val gShift16 = 5
|
||||
private val bShift16 = 0
|
||||
private val rScale16 = 255.0 / 0x1F
|
||||
private val gScale16 = 255.0 / 0x3F
|
||||
private val bScale16 = 255.0 / 0x1F
|
||||
|
||||
private def extractFrom1Bit(c: Short) = if (c == 0) 0x000000 else 0xFFFFFF
|
||||
|
||||
private def compressTo1Bit(c: Int) = (if (c == 0) 0 else 1).toShort
|
||||
|
||||
private def extractFrom8Bit(c: Short) = {
|
||||
val r = ((((c & rMask8) >>> rShift8) * rScale8).toInt << rShift32) & rMask32
|
||||
val g = ((((c & gMask8) >>> gShift8) * gScale8).toInt << gShift32) & gMask32
|
||||
val b = ((((c & bMask8) >>> bShift8) * bScale8).toInt << bShift32) & bMask32
|
||||
r | g | b
|
||||
def deflate(value: Int): Int
|
||||
}
|
||||
|
||||
private def compressTo8Bit(c: Int) = {
|
||||
val r = ((((c & rMask32) >>> rShift32) / rScale8).toInt << rShift8) & rMask8
|
||||
val g = ((((c & gMask32) >>> gShift32) / gScale8).toInt << gShift8) & gMask8
|
||||
val b = ((((c & bMask32) >>> bShift32) / bScale8).toInt << bShift8) & bMask8
|
||||
(r | g | b).toShort
|
||||
private class SingleBitFormat extends ColorFormat {
|
||||
def inflate(value: Int) = if (value == 0) 0x000000 else 0xFFFFFF
|
||||
|
||||
def deflate(value: Int) = if (value == 0) 0 else 1
|
||||
}
|
||||
|
||||
private def extractFrom16Bit(c: Short) = {
|
||||
val r = ((((c & rMask16) >>> rShift16) * rScale16).toInt << rShift32) & rMask32
|
||||
val g = ((((c & gMask16) >>> gShift16) * gScale16).toInt << gShift32) & gMask32
|
||||
val b = ((((c & bMask16) >>> bShift16) * bScale16).toInt << bShift32) & bMask32
|
||||
r | g | b
|
||||
}
|
||||
private class MultiBitFormat(rBits: Int, gBits: Int, bBits: Int) extends ColorFormat {
|
||||
def mask(nBits: Int) = 0xFFFFFFFF >>> (32 - nBits)
|
||||
|
||||
private def compressTo16Bit(c: Int) = {
|
||||
val r = ((((c & rMask32) >>> rShift32) / rScale16).toInt << rShift16) & rMask16
|
||||
val g = ((((c & gMask32) >>> gShift32) / gScale16).toInt << gShift16) & gMask16
|
||||
val b = ((((c & bMask32) >>> bShift32) / bScale16).toInt << bShift16) & bMask16
|
||||
(r | g | b).toShort
|
||||
}
|
||||
private val bShift = 0
|
||||
private val gShift = bBits
|
||||
private val rShift = gShift + gBits
|
||||
|
||||
// Colors are packed: 0xFFFFBBBB (F = foreground, B = background)
|
||||
private val fgShift = 16
|
||||
private val bgShift = 0
|
||||
private val bMask = mask(bBits) << bShift
|
||||
private val gMask = mask(gBits) << gShift
|
||||
private val rMask = mask(rBits) << rShift
|
||||
|
||||
def pack(foreground: Int, background: Int, depth: Depth.Value) =
|
||||
depth match {
|
||||
case Depth.OneBit => (compressTo1Bit(foreground) << fgShift) | (compressTo1Bit(background) << bgShift)
|
||||
case Depth.EightBit => (compressTo8Bit(foreground) << fgShift) | (compressTo8Bit(background) << bgShift)
|
||||
case Depth.SixteenBit => (compressTo16Bit(foreground) << fgShift) | (compressTo16Bit(background) << bgShift)
|
||||
private val bScale = 255.0 / ((1 << bBits) - 1)
|
||||
private val gScale = 255.0 / ((1 << gBits) - 1)
|
||||
private val rScale = 255.0 / ((1 << rBits) - 1)
|
||||
|
||||
def inflate(value: Int) = {
|
||||
val r = ((((value & rMask) >>> rShift) * rScale).toInt << rShift32) & rMask32
|
||||
val g = ((((value & gMask) >>> gShift) * gScale).toInt << gShift32) & gMask32
|
||||
val b = ((((value & bMask) >>> bShift) * bScale).toInt << bShift32) & bMask32
|
||||
r | g | b
|
||||
}
|
||||
|
||||
def unpackForeground(color: Int, depth: Depth.Value) = {
|
||||
val c = (color >>> fgShift).toShort
|
||||
depth match {
|
||||
case Depth.OneBit => extractFrom1Bit(c)
|
||||
case Depth.EightBit => extractFrom8Bit(c)
|
||||
case Depth.SixteenBit => extractFrom16Bit(c)
|
||||
def deflate(value: Int) = {
|
||||
val r = ((((value & rMask32) >>> rShift32) / rScale).toInt << rShift) & rMask
|
||||
val g = ((((value & gMask32) >>> gShift32) / gScale).toInt << gShift) & gMask
|
||||
val b = ((((value & bMask32) >>> bShift32) / bScale).toInt << bShift) & bMask
|
||||
r | g | b
|
||||
}
|
||||
}
|
||||
|
||||
def unpackBackground(color: Int, depth: Depth.Value) = {
|
||||
val c = (color >>> bgShift).toShort
|
||||
depth match {
|
||||
case Depth.OneBit => extractFrom1Bit(c)
|
||||
case Depth.EightBit => extractFrom8Bit(c)
|
||||
case Depth.SixteenBit => extractFrom16Bit(c)
|
||||
}
|
||||
private val formats = Map(
|
||||
Depth.OneBit -> new SingleBitFormat(),
|
||||
Depth.FourBit -> new MultiBitFormat(1, 2, 1),
|
||||
Depth.EightBit -> new MultiBitFormat(3, 3, 2))
|
||||
|
||||
// Colors are packed: 0xFFBB (F = foreground, B = background)
|
||||
private val fgShift = 8
|
||||
private val bgMask = 0x000000FF
|
||||
|
||||
def pack(foreground: Int, background: Int, depth: Depth.Value) = {
|
||||
val format = formats(depth)
|
||||
((format.deflate(foreground) << fgShift) | format.deflate(background)).toShort
|
||||
}
|
||||
|
||||
def unpackForeground(color: Short, depth: Depth.Value) =
|
||||
formats(depth).inflate((color & 0xFFFF) >>> fgShift)
|
||||
|
||||
def unpackBackground(color: Short, depth: Depth.Value) =
|
||||
formats(depth).inflate(color & bgMask)
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ object RenderState {
|
||||
|
||||
def makeItBlend() {
|
||||
GL11.glEnable(GL11.GL_BLEND)
|
||||
GL11.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_COLOR)
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA)
|
||||
GL11.glDepthFunc(GL11.GL_LEQUAL)
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
package li.cil.oc.util
|
||||
|
||||
import net.minecraft.nbt.{NBTTagIntArray, NBTTagCompound, NBTTagList, NBTTagString}
|
||||
import net.minecraft.nbt._
|
||||
|
||||
/**
|
||||
* This stores chars in a 2D-Array and provides some manipulation functions.
|
||||
@ -10,27 +10,49 @@ import net.minecraft.nbt.{NBTTagIntArray, NBTTagCompound, NBTTagList, NBTTagStri
|
||||
* relatively fast updates, given a smart algorithm (using copy()/fill()
|
||||
* instead of set()ing everything).
|
||||
*/
|
||||
class TextBuffer(var width: Int, var height: Int, val depth: PackedColor.Depth.Value) {
|
||||
class TextBuffer(var width: Int, var height: Int, initialDepth: PackedColor.Depth.Value) extends Persistable {
|
||||
def this(size: (Int, Int), depth: PackedColor.Depth.Value) = this(size._1, size._2, depth)
|
||||
|
||||
private var depth_ = initialDepth
|
||||
|
||||
private var foreground_ = 0xFFFFFF
|
||||
|
||||
private var background_ = 0x000000
|
||||
|
||||
private var packed = PackedColor.pack(foreground_, background_, depth)
|
||||
private var packed = PackedColor.pack(foreground_, background_, depth_)
|
||||
|
||||
def foreground = foreground_
|
||||
|
||||
def foreground_=(value: Int) = {
|
||||
foreground_ = value
|
||||
packed = PackedColor.pack(foreground_, background_, depth)
|
||||
packed = PackedColor.pack(foreground_, background_, depth_)
|
||||
}
|
||||
|
||||
def background = background_
|
||||
|
||||
def background_=(value: Int) = {
|
||||
background_ = value
|
||||
packed = PackedColor.pack(foreground_, background_, depth)
|
||||
packed = PackedColor.pack(foreground_, background_, depth_)
|
||||
}
|
||||
|
||||
def depth = depth_
|
||||
|
||||
def depth_=(value: PackedColor.Depth.Value) = {
|
||||
if (depth != value) {
|
||||
for (row <- 0 until height) {
|
||||
val rowColor = color(row)
|
||||
for (col <- 0 until width) {
|
||||
val packed = rowColor(col)
|
||||
val fg = PackedColor.unpackForeground(packed, depth_)
|
||||
val bg = PackedColor.unpackBackground(packed, depth_)
|
||||
rowColor(col) = PackedColor.pack(fg, bg, value)
|
||||
}
|
||||
}
|
||||
depth_ = value
|
||||
packed = PackedColor.pack(foreground_, background_, depth_)
|
||||
true
|
||||
}
|
||||
else false
|
||||
}
|
||||
|
||||
var color = Array.fill(height, width)(packed)
|
||||
@ -143,33 +165,50 @@ class TextBuffer(var width: Int, var height: Int, val depth: PackedColor.Depth.V
|
||||
changed
|
||||
}
|
||||
|
||||
def readFromNBT(nbt: NBTTagCompound): Unit = {
|
||||
override def load(nbt: NBTTagCompound): Unit = {
|
||||
val w = nbt.getInteger("width")
|
||||
val h = nbt.getInteger("height")
|
||||
size = (w, h)
|
||||
|
||||
val b = nbt.getTagList("buffer")
|
||||
for (i <- 0 until (h min b.tagCount)) {
|
||||
val line = b.tagAt(i).asInstanceOf[NBTTagString].data
|
||||
set(0, i, line)
|
||||
}
|
||||
|
||||
depth_ = PackedColor.Depth(nbt.getInteger("depth"))
|
||||
foreground = nbt.getInteger("foreground")
|
||||
background = nbt.getInteger("background")
|
||||
|
||||
val c = nbt.getTagList("color")
|
||||
for (i <- 0 until (h min c.tagCount)) {
|
||||
val line = c.tagAt(i).asInstanceOf[NBTTagIntArray].intArray
|
||||
Array.copy(line, 0, color(i), 0, line.length min width)
|
||||
for (i <- 0 until h) {
|
||||
val rowColor = color(i)
|
||||
for (j <- 0 until w) {
|
||||
rowColor(j) = c.tagAt(j + i * w).asInstanceOf[NBTTagShort].data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def writeToNBT(nbt: NBTTagCompound): Unit = {
|
||||
override def save(nbt: NBTTagCompound): Unit = {
|
||||
nbt.setInteger("width", width)
|
||||
nbt.setInteger("height", height)
|
||||
|
||||
val b = new NBTTagList()
|
||||
for (i <- 0 until height) {
|
||||
b.appendTag(new NBTTagString(null, String.valueOf(buffer(i))))
|
||||
}
|
||||
nbt.setTag("buffer", b)
|
||||
|
||||
nbt.setInteger("depth", depth_.id)
|
||||
nbt.setInteger("foreground", foreground_)
|
||||
nbt.setInteger("background", background_)
|
||||
|
||||
val c = new NBTTagList()
|
||||
for (i <- 0 until height) {
|
||||
c.appendTag(new NBTTagIntArray(null, color(i)))
|
||||
val rowColor = color(i)
|
||||
for (j <- 0 until width) {
|
||||
c.appendTag(new NBTTagShort(null, rowColor(j)))
|
||||
}
|
||||
}
|
||||
nbt.setTag("color", c)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user