Added methods for raw text and color setting to TextBuffer API.

This commit is contained in:
Florian Nücke 2015-01-14 18:53:19 +01:00
parent 90d0124cd5
commit 40de62056b
7 changed files with 296 additions and 61 deletions

View File

@ -11,7 +11,7 @@ import li.cil.oc.api.detail.*;
*/ */
public class API { public class API {
public static final String ID_OWNER = "OpenComputers|Core"; public static final String ID_OWNER = "OpenComputers|Core";
public static final String VERSION = "4.2.0"; public static final String VERSION = "4.2.1";
public static DriverAPI driver = null; public static DriverAPI driver = null;
public static FileSystemAPI fileSystem = null; public static FileSystemAPI fileSystem = null;

View File

@ -341,6 +341,71 @@ public interface TextBuffer extends ManagedEnvironment, Persistable {
*/ */
boolean isBackgroundFromPalette(int column, int row); boolean isBackgroundFromPalette(int column, int row);
/**
* Overwrites a portion of the text in raw mode.
* <p/>
* This will copy the given char array into the buffer, starting at the
* specified column and row. The array is expected to be indexed row-
* first, i.e. the first dimension is the vertical axis, the second
* the horizontal.
* <p/>
* <em>Important</em>: this performs no checks as to whether something
* actually changed. It will always send the changed patch to clients.
* It will also not crop the specified array to the actually used range.
* In other words, this is not intended to be exposed as-is to user code,
* it should always be called with validated, and, as necessary, cropped
* values.
*
* @param column the horizontal index.
* @param row the vertical index.
* @param text the text to write.
*/
void rawSetText(int column, int row, char[][] text);
/**
* Overwrites a portion of the foreground color information in raw mode.
* <p/>
* This will convert the specified RGB data (in <tt>0xRRGGBB</tt> format)
* to the internal, packed representation and copy it into the buffer,
* starting at the specified column and row. The array is expected to be
* indexed row-first, i.e. the first dimension is the vertical axis, the
* second the horizontal.
* <p/>
* <em>Important</em>: this performs no checks as to whether something
* actually changed. It will always send the changed patch to clients.
* It will also not crop the specified array to the actually used range.
* In other words, this is not intended to be exposed as-is to user code,
* it should always be called with validated, and, as necessary, cropped
* values.
*
* @param column the horizontal index.
* @param row the vertical index.
* @param color the foreground color data to write.
*/
void rawSetForeground(int column, int row, int[][] color);
/**
* Overwrites a portion of the background color information in raw mode.
* <p/>
* This will convert the specified RGB data (in <tt>0xRRGGBB</tt> format)
* to the internal, packed representation and copy it into the buffer,
* starting at the specified column and row. The array is expected to be
* indexed row-first, i.e. the first dimension is the vertical axis, the
* second the horizontal.
* <p/>
* <em>Important</em>: this performs no checks as to whether something
* actually changed. It will always send the changed patch to clients.
* It will also not crop the specified array to the actually used range.
* In other words, this is not intended to be exposed as-is to user code,
* it should always be called with validated, and, as necessary, cropped
* values.
*
* @param column the horizontal index.
* @param row the vertical index.
* @param color the background color data to write.
*/
void rawSetBackground(int column, int row, int[][] color);
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
/** /**

View File

@ -370,6 +370,9 @@ object PacketHandler extends CommonPacketHandler {
case PacketType.TextBufferMultiResolutionChange => onTextBufferMultiResolutionChange(p, buffer) case PacketType.TextBufferMultiResolutionChange => onTextBufferMultiResolutionChange(p, buffer)
case PacketType.TextBufferMultiMaxResolutionChange => onTextBufferMultiMaxResolutionChange(p, buffer) case PacketType.TextBufferMultiMaxResolutionChange => onTextBufferMultiMaxResolutionChange(p, buffer)
case PacketType.TextBufferMultiSet => onTextBufferMultiSet(p, buffer) case PacketType.TextBufferMultiSet => onTextBufferMultiSet(p, buffer)
case PacketType.TextBufferMultiRawSetText => onTextBufferMultiRawSetText(p, buffer)
case PacketType.TextBufferMultiRawSetBackground => onTextBufferMultiRawSetBackground(p, buffer)
case PacketType.TextBufferMultiRawSetForeground => onTextBufferMultiRawSetForeground(p, buffer)
case _ => // Invalid packet. case _ => // Invalid packet.
} }
} }
@ -441,6 +444,60 @@ object PacketHandler extends CommonPacketHandler {
buffer.set(col, row, s, vertical) buffer.set(col, row, s, vertical)
} }
def onTextBufferMultiRawSetText(p: PacketParser, buffer: component.TextBuffer) {
val col = p.readInt()
val row = p.readInt()
val rows = p.readShort()
val text = new Array[Array[Char]](rows)
for (y <- 0 until rows) {
val cols = p.readShort()
val line = new Array[Char](cols)
for (x <- 0 until cols) {
line(x) = p.readChar()
}
text(y) = line
}
buffer.rawSetText(col, row, text)
}
def onTextBufferMultiRawSetBackground(p: PacketParser, buffer: component.TextBuffer) {
val col = p.readInt()
val row = p.readInt()
val rows = p.readShort()
val color = new Array[Array[Int]](rows)
for (y <- 0 until rows) {
val cols = p.readShort()
val line = new Array[Int](cols)
for (x <- 0 until cols) {
line(x) = p.readInt()
}
color(y) = line
}
buffer.rawSetBackground(col, row, color)
}
def onTextBufferMultiRawSetForeground(p: PacketParser, buffer: component.TextBuffer) {
val col = p.readInt()
val row = p.readInt()
val rows = p.readShort()
val color = new Array[Array[Int]](rows)
for (y <- 0 until rows) {
val cols = p.readShort()
val line = new Array[Int](cols)
for (x <- 0 until cols) {
line(x) = p.readInt()
}
color(y) = line
}
buffer.rawSetForeground(col, row, color)
}
def onScreenTouchMode(p: PacketParser) = def onScreenTouchMode(p: PacketParser) =
p.readTileEntity[Screen]() match { p.readTileEntity[Screen]() match {
case Some(t) => t.invertTouchMode = p.readBoolean() case Some(t) => t.invertTouchMode = p.readBoolean()

View File

@ -41,6 +41,9 @@ object PacketType extends Enumeration {
TextBufferMultiResolutionChange, TextBufferMultiResolutionChange,
TextBufferMultiMaxResolutionChange, TextBufferMultiMaxResolutionChange,
TextBufferMultiSet, TextBufferMultiSet,
TextBufferMultiRawSetText,
TextBufferMultiRawSetBackground,
TextBufferMultiRawSetForeground,
TextBufferPowerChange, TextBufferPowerChange,
ScreenTouchMode, ScreenTouchMode,
ServerPresence, ServerPresence,

View File

@ -189,7 +189,7 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
if (height < 1) throw new IllegalArgumentException("height must be larger or equal to one") if (height < 1) throw new IllegalArgumentException("height must be larger or equal to one")
maxResolution = (width, height) maxResolution = (width, height)
fullyLitCost = computeFullyLitCost() fullyLitCost = computeFullyLitCost()
proxy.onScreenMaxResolutionChange(width, width) proxy.onBufferMaxResolutionChange(width, width)
} }
override def getMaximumWidth = maxResolution._1 override def getMaximumWidth = maxResolution._1
@ -205,7 +205,7 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
if (w < 1 || h < 1 || w > mw || h > mw || h * w > mw * mh) if (w < 1 || h < 1 || w > mw || h > mw || h * w > mw * mh)
throw new IllegalArgumentException("unsupported resolution") throw new IllegalArgumentException("unsupported resolution")
// Always send to clients, their state might be dirty. // Always send to clients, their state might be dirty.
proxy.onScreenResolutionChange(w, h) proxy.onBufferResolutionChange(w, h)
if (data.size = (w, h)) { if (data.size = (w, h)) {
if (node != null) { if (node != null) {
node.sendToReachable("computer.signal", "screen_resized", Int.box(w), Int.box(h)) node.sendToReachable("computer.signal", "screen_resized", Int.box(w), Int.box(h))
@ -227,7 +227,7 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
if (depth.ordinal > maxDepth.ordinal) if (depth.ordinal > maxDepth.ordinal)
throw new IllegalArgumentException("unsupported depth") throw new IllegalArgumentException("unsupported depth")
// Always send to clients, their state might be dirty. // Always send to clients, their state might be dirty.
proxy.onScreenDepthChange(depth) proxy.onBufferDepthChange(depth)
data.format = PackedColor.Depth.format(depth) data.format = PackedColor.Depth.format(depth)
} }
@ -236,7 +236,7 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
override def setPaletteColor(index: Int, color: Int) = data.format match { override def setPaletteColor(index: Int, color: Int) = data.format match {
case palette: PackedColor.MutablePaletteFormat => case palette: PackedColor.MutablePaletteFormat =>
palette(index) = color palette(index) = color
proxy.onScreenPaletteChange(index) proxy.onBufferPaletteChange(index)
case _ => throw new Exception("palette not available") case _ => throw new Exception("palette not available")
} }
@ -251,7 +251,7 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
val value = PackedColor.Color(color, isFromPalette) val value = PackedColor.Color(color, isFromPalette)
if (data.foreground != value) { if (data.foreground != value) {
data.foreground = value data.foreground = value
proxy.onScreenColorChange() proxy.onBufferColorChange()
} }
} }
@ -265,7 +265,7 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
val value = PackedColor.Color(color, isFromPalette) val value = PackedColor.Color(color, isFromPalette)
if (data.background != value) { if (data.background != value) {
data.background = value data.background = value
proxy.onScreenColorChange() proxy.onBufferColorChange()
} }
} }
@ -275,13 +275,14 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
def copy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) = def copy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) =
if (data.copy(col, row, w, h, tx, ty)) if (data.copy(col, row, w, h, tx, ty))
proxy.onScreenCopy(col, row, w, h, tx, ty) proxy.onBufferCopy(col, row, w, h, tx, ty)
def fill(col: Int, row: Int, w: Int, h: Int, c: Char) = def fill(col: Int, row: Int, w: Int, h: Int, c: Char) =
if (data.fill(col, row, w, h, c)) if (data.fill(col, row, w, h, c))
proxy.onScreenFill(col, row, w, h, c) proxy.onBufferFill(col, row, w, h, c)
def set(col: Int, row: Int, s: String, vertical: Boolean) = if (col < data.width && (col >= 0 || -col < s.length)) { def set(col: Int, row: Int, s: String, vertical: Boolean): Unit =
if (col < data.width && (col >= 0 || -col < s.length)) {
// Make sure the string isn't longer than it needs to be, in particular to // Make sure the string isn't longer than it needs to be, in particular to
// avoid sending too much data to our clients. // avoid sending too much data to our clients.
val (x, y, truncated) = val (x, y, truncated) =
@ -294,7 +295,7 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
else (col, row, s.substring(0, math.min(s.length, data.width - col))) else (col, row, s.substring(0, math.min(s.length, data.width - col)))
} }
if (data.set(x, y, truncated, vertical)) if (data.set(x, y, truncated, vertical))
proxy.onScreenSet(x, row, truncated, vertical) proxy.onBufferSet(x, row, truncated, vertical)
} }
def get(col: Int, row: Int) = data.get(col, row) def get(col: Int, row: Int) = data.get(col, row)
@ -321,6 +322,40 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
override def isBackgroundFromPalette(column: Int, row: Int) = override def isBackgroundFromPalette(column: Int, row: Int) =
data.format.isFromPalette(PackedColor.extractBackground(color(column, row))) data.format.isFromPalette(PackedColor.extractBackground(color(column, row)))
override def rawSetText(col: Int, row: Int, text: Array[Array[Char]]): Unit = {
for (y <- row until ((row + text.length) min data.height)) {
val line = text(y - row)
Array.copy(line, 0, data.buffer(y), col, line.length min data.width)
}
proxy.onBufferRawSetText(col, row, text)
}
override def rawSetBackground(col: Int, row: Int, color: Array[Array[Int]]): Unit = {
for (y <- row until ((row + color.length) min data.height)) {
val line = color(y - row)
for (x <- col until ((col + line.length) min data.width)) {
val packedBackground = data.color(row)(col) & 0x00FF
val packedForeground = (data.format.deflate(PackedColor.Color(line(x - col))) << PackedColor.ForegroundShift) & 0xFF00
data.color(row)(col) = (packedForeground | packedBackground).toShort
}
}
// TODO Better for bandwidth to send packed shorts here. Would need a special case for handling on client, though...
proxy.onBufferRawSetBackground(col, row, color)
}
override def rawSetForeground(col: Int, row: Int, color: Array[Array[Int]]): Unit = {
for (y <- row until ((row + color.length) min data.height)) {
val line = color(y - row)
for (x <- col until ((col + line.length) min data.width)) {
val packedBackground = data.format.deflate(PackedColor.Color(line(x - col))) & 0x00FF
val packedForeground = data.color(row)(col) & 0xFF00
data.color(row)(col) = (packedForeground | packedBackground).toShort
}
}
// TODO Better for bandwidth to send packed shorts here. Would need a special case for handling on client, though...
proxy.onBufferRawSetForeground(col, row, color)
}
private def color(column: Int, row: Int) = { private def color(column: Int, row: Int) = {
if (column < 0 || column >= getWidth || row < 0 || row >= getHeight) if (column < 0 || column >= getWidth || row < 0 || row >= getHeight)
throw new IndexOutOfBoundsException() throw new IndexOutOfBoundsException()
@ -477,28 +512,40 @@ object TextBuffer {
def render() = false def render() = false
def onScreenColorChange(): Unit def onBufferColorChange(): Unit
def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) { def onBufferCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) {
owner.relativeLitArea = -1 owner.relativeLitArea = -1
} }
def onScreenDepthChange(depth: ColorDepth): Unit def onBufferDepthChange(depth: ColorDepth): Unit
def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char) { def onBufferFill(col: Int, row: Int, w: Int, h: Int, c: Char) {
owner.relativeLitArea = -1 owner.relativeLitArea = -1
} }
def onScreenPaletteChange(index: Int): Unit def onBufferPaletteChange(index: Int): Unit
def onScreenResolutionChange(w: Int, h: Int) { def onBufferResolutionChange(w: Int, h: Int) {
owner.relativeLitArea = -1 owner.relativeLitArea = -1
} }
def onScreenMaxResolutionChange(w: Int, h: Int) { def onBufferMaxResolutionChange(w: Int, h: Int) {
} }
def onScreenSet(col: Int, row: Int, s: String, vertical: Boolean) { def onBufferSet(col: Int, row: Int, s: String, vertical: Boolean) {
owner.relativeLitArea = -1
}
def onBufferRawSetText(col: Int, row: Int, text: Array[Array[Char]]) {
owner.relativeLitArea = -1
}
def onBufferRawSetBackground(col: Int, row: Int, color: Array[Array[Int]]) {
owner.relativeLitArea = -1
}
def onBufferRawSetForeground(col: Int, row: Int, color: Array[Array[Int]]) {
owner.relativeLitArea = -1 owner.relativeLitArea = -1
} }
@ -532,35 +579,35 @@ object TextBuffer {
wasDirty wasDirty
} }
override def onScreenColorChange() { override def onBufferColorChange() {
markDirty() markDirty()
} }
override def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) { override def onBufferCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) {
super.onScreenCopy(col, row, w, h, tx, ty) super.onBufferCopy(col, row, w, h, tx, ty)
markDirty() markDirty()
} }
override def onScreenDepthChange(depth: ColorDepth) { override def onBufferDepthChange(depth: ColorDepth) {
markDirty() markDirty()
} }
override def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char) { override def onBufferFill(col: Int, row: Int, w: Int, h: Int, c: Char) {
super.onScreenFill(col, row, w, h, c) super.onBufferFill(col, row, w, h, c)
markDirty() markDirty()
} }
override def onScreenPaletteChange(index: Int) { override def onBufferPaletteChange(index: Int) {
markDirty() markDirty()
} }
override def onScreenResolutionChange(w: Int, h: Int) { override def onBufferResolutionChange(w: Int, h: Int) {
super.onScreenResolutionChange(w, h) super.onBufferResolutionChange(w, h)
markDirty() markDirty()
} }
override def onScreenSet(col: Int, row: Int, s: String, vertical: Boolean) { override def onBufferSet(col: Int, row: Int, s: String, vertical: Boolean) {
super.onScreenSet(col, row, s, vertical) super.onBufferSet(col, row, s, vertical)
dirty = true dirty = true
} }
@ -609,53 +656,71 @@ object TextBuffer {
} }
class ServerProxy(val owner: TextBuffer) extends Proxy { class ServerProxy(val owner: TextBuffer) extends Proxy {
override def onScreenColorChange() { override def onBufferColorChange() {
owner.host.markChanged() owner.host.markChanged()
owner.synchronized(ServerPacketSender.appendTextBufferColorChange(owner.pendingCommands, owner.data.foreground, owner.data.background)) owner.synchronized(ServerPacketSender.appendTextBufferColorChange(owner.pendingCommands, owner.data.foreground, owner.data.background))
} }
override def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) { override def onBufferCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) {
super.onScreenCopy(col, row, w, h, tx, ty) super.onBufferCopy(col, row, w, h, tx, ty)
owner.host.markChanged() owner.host.markChanged()
owner.synchronized(ServerPacketSender.appendTextBufferCopy(owner.pendingCommands, col, row, w, h, tx, ty)) owner.synchronized(ServerPacketSender.appendTextBufferCopy(owner.pendingCommands, col, row, w, h, tx, ty))
} }
override def onScreenDepthChange(depth: ColorDepth) { override def onBufferDepthChange(depth: ColorDepth) {
owner.host.markChanged() owner.host.markChanged()
owner.synchronized(ServerPacketSender.appendTextBufferDepthChange(owner.pendingCommands, depth)) owner.synchronized(ServerPacketSender.appendTextBufferDepthChange(owner.pendingCommands, depth))
} }
override def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char) { override def onBufferFill(col: Int, row: Int, w: Int, h: Int, c: Char) {
super.onScreenFill(col, row, w, h, c) super.onBufferFill(col, row, w, h, c)
owner.host.markChanged() owner.host.markChanged()
owner.synchronized(ServerPacketSender.appendTextBufferFill(owner.pendingCommands, col, row, w, h, c)) owner.synchronized(ServerPacketSender.appendTextBufferFill(owner.pendingCommands, col, row, w, h, c))
} }
override def onScreenPaletteChange(index: Int) { override def onBufferPaletteChange(index: Int) {
owner.host.markChanged() owner.host.markChanged()
owner.synchronized(ServerPacketSender.appendTextBufferPaletteChange(owner.pendingCommands, index, owner.getPaletteColor(index))) owner.synchronized(ServerPacketSender.appendTextBufferPaletteChange(owner.pendingCommands, index, owner.getPaletteColor(index)))
} }
override def onScreenResolutionChange(w: Int, h: Int) { override def onBufferResolutionChange(w: Int, h: Int) {
super.onScreenResolutionChange(w, h) super.onBufferResolutionChange(w, h)
owner.host.markChanged() owner.host.markChanged()
owner.synchronized(ServerPacketSender.appendTextBufferResolutionChange(owner.pendingCommands, w, h)) owner.synchronized(ServerPacketSender.appendTextBufferResolutionChange(owner.pendingCommands, w, h))
} }
override def onScreenMaxResolutionChange(w: Int, h: Int) { override def onBufferMaxResolutionChange(w: Int, h: Int) {
if (owner.node.network != null) { if (owner.node.network != null) {
super.onScreenMaxResolutionChange(w, h) super.onBufferMaxResolutionChange(w, h)
owner.host.markChanged() owner.host.markChanged()
owner.synchronized(ServerPacketSender.appendTextBufferMaxResolutionChange(owner.pendingCommands, w, h)) owner.synchronized(ServerPacketSender.appendTextBufferMaxResolutionChange(owner.pendingCommands, w, h))
} }
} }
override def onScreenSet(col: Int, row: Int, s: String, vertical: Boolean) { override def onBufferSet(col: Int, row: Int, s: String, vertical: Boolean) {
super.onScreenSet(col, row, s, vertical) super.onBufferSet(col, row, s, vertical)
owner.host.markChanged() owner.host.markChanged()
owner.synchronized(ServerPacketSender.appendTextBufferSet(owner.pendingCommands, col, row, s, vertical)) owner.synchronized(ServerPacketSender.appendTextBufferSet(owner.pendingCommands, col, row, s, vertical))
} }
override def onBufferRawSetText(col: Int, row: Int, text: Array[Array[Char]]) {
super.onBufferRawSetText(col, row, text)
owner.host.markChanged()
owner.synchronized(ServerPacketSender.appendTextBufferRawSetText(owner.pendingCommands, col, row, text))
}
override def onBufferRawSetBackground(col: Int, row: Int, color: Array[Array[Int]]) {
super.onBufferRawSetBackground(col, row, color)
owner.host.markChanged()
owner.synchronized(ServerPacketSender.appendTextBufferRawSetBackground(owner.pendingCommands, col, row, color))
}
override def onBufferRawSetForeground(col: Int, row: Int, color: Array[Array[Int]]) {
super.onBufferRawSetForeground(col, row, color)
owner.host.markChanged()
owner.synchronized(ServerPacketSender.appendTextBufferRawSetForeground(owner.pendingCommands, col, row, color))
}
override def keyDown(character: Char, code: Int, player: EntityPlayer) { override def keyDown(character: Char, code: Int, player: EntityPlayer) {
sendToKeyboards("keyboard.keyDown", player, Char.box(character), Int.box(code)) sendToKeyboards("keyboard.keyDown", player, Char.box(character), Int.box(code))
} }

View File

@ -402,6 +402,51 @@ object PacketSender {
pb.writeBoolean(vertical) pb.writeBoolean(vertical)
} }
def appendTextBufferRawSetText(pb: PacketBuilder, col: Int, row: Int, text: Array[Array[Char]]) {
pb.writePacketType(PacketType.TextBufferMultiRawSetText)
pb.writeInt(col)
pb.writeInt(row)
pb.writeShort(text.length.toShort)
for (y <- 0 until text.length.toShort) {
val line = text(y)
pb.writeShort(line.length.toShort)
for (x <- 0 until line.length.toShort) {
pb.writeChar(line(x))
}
}
}
def appendTextBufferRawSetBackground(pb: PacketBuilder, col: Int, row: Int, color: Array[Array[Int]]) {
pb.writePacketType(PacketType.TextBufferMultiRawSetBackground)
pb.writeInt(col)
pb.writeInt(row)
pb.writeShort(color.length.toShort)
for (y <- 0 until color.length.toShort) {
val line = color(y)
pb.writeShort(line.length.toShort)
for (x <- 0 until line.length.toShort) {
pb.writeInt(line(x))
}
}
}
def appendTextBufferRawSetForeground(pb: PacketBuilder, col: Int, row: Int, color: Array[Array[Int]]) {
pb.writePacketType(PacketType.TextBufferMultiRawSetForeground)
pb.writeInt(col)
pb.writeInt(row)
pb.writeShort(color.length.toShort)
for (y <- 0 until color.length.toShort) {
val line = color(y)
pb.writeShort(line.length.toShort)
for (x <- 0 until line.length.toShort) {
pb.writeInt(line(x))
}
}
}
def sendTextBufferInit(address: String, value: NBTTagCompound, player: EntityPlayerMP) { def sendTextBufferInit(address: String, value: NBTTagCompound, player: EntityPlayerMP) {
val pb = new CompressedPacketBuilder(PacketType.TextBufferInit) val pb = new CompressedPacketBuilder(PacketType.TextBufferInit)

View File

@ -165,16 +165,16 @@ object PackedColor {
case class Color(value: Int, isPalette: Boolean = false) case class Color(value: Int, isPalette: Boolean = false)
// Colors are packed: 0xFFBB (F = foreground, B = background) // Colors are packed: 0xFFBB (F = foreground, B = background)
private val fgShift = 8 val ForegroundShift = 8
private val bgMask = 0x000000FF val BackgroundMask = 0x000000FF
def pack(foreground: Color, background: Color, format: ColorFormat) = { def pack(foreground: Color, background: Color, format: ColorFormat) = {
(((format.deflate(foreground) & 0xFF) << fgShift) | (format.deflate(background) & 0xFF)).toShort (((format.deflate(foreground) & 0xFF) << ForegroundShift) | (format.deflate(background) & 0xFF)).toShort
} }
def extractForeground(color: Short) = (color & 0xFFFF) >>> fgShift def extractForeground(color: Short) = (color & 0xFFFF) >>> ForegroundShift
def extractBackground(color: Short) = color & bgMask def extractBackground(color: Short) = color & BackgroundMask
def unpackForeground(color: Short, format: ColorFormat) = def unpackForeground(color: Short, format: ColorFormat) =
format.inflate(extractForeground(color)) format.inflate(extractForeground(color))