diff --git a/src/main/java/dan200/computercraft/core/terminal/Terminal.java b/src/main/java/dan200/computercraft/core/terminal/Terminal.java index e053e41b4..2e6ac273d 100644 --- a/src/main/java/dan200/computercraft/core/terminal/Terminal.java +++ b/src/main/java/dan200/computercraft/core/terminal/Terminal.java @@ -7,16 +7,17 @@ package dan200.computercraft.core.terminal; import dan200.computercraft.shared.util.Palette; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; public class Terminal { private static final String base16 = "0123456789abcdef"; - private int m_cursorX; - private int m_cursorY; - private boolean m_cursorBlink; - private int m_cursorColour; - private int m_cursorBackgroundColour; + private int m_cursorX = 0; + private int m_cursorY = 0; + private boolean m_cursorBlink = false; + private int m_cursorColour = 0; + private int m_cursorBackgroundColour = 15; private int m_width; private int m_height; @@ -25,9 +26,9 @@ public class Terminal private TextBuffer[] m_textColour; private TextBuffer[] m_backgroundColour; - private final Palette m_palette; + private final Palette m_palette = new Palette(); - private boolean m_changed; + private boolean m_changed = false; private final Runnable onChanged; public Terminal( int width, int height ) @@ -41,9 +42,6 @@ public class Terminal m_height = height; onChanged = changedCallback; - m_cursorColour = 0; - m_cursorBackgroundColour = 15; - m_text = new TextBuffer[m_height]; m_textColour = new TextBuffer[m_height]; m_backgroundColour = new TextBuffer[m_height]; @@ -53,14 +51,6 @@ public class Terminal m_textColour[i] = new TextBuffer( base16.charAt( m_cursorColour ), m_width ); m_backgroundColour[i] = new TextBuffer( base16.charAt( m_cursorBackgroundColour ), m_width ); } - - m_cursorX = 0; - m_cursorY = 0; - m_cursorBlink = false; - - m_changed = false; - - m_palette = new Palette(); } public synchronized void reset() @@ -336,6 +326,59 @@ public class Terminal m_changed = false; } + public synchronized void write( PacketBuffer buffer ) + { + buffer.writeInt( m_cursorX ); + buffer.writeInt( m_cursorY ); + buffer.writeBoolean( m_cursorBlink ); + buffer.writeByte( m_cursorBackgroundColour << 4 | m_cursorColour ); + + for( int y = 0; y < m_height; y++ ) + { + TextBuffer text = m_text[y]; + TextBuffer textColour = m_textColour[y]; + TextBuffer backColour = m_backgroundColour[y]; + + for( int x = 0; x < m_width; x++ ) + { + buffer.writeByte( text.charAt( x ) & 0xFF ); + buffer.writeByte( colourIndex( backColour.charAt( x ) ) << 4 | colourIndex( textColour.charAt( x ) ) ); + } + } + + m_palette.write( buffer ); + } + + public synchronized void read( PacketBuffer buffer ) + { + m_cursorX = buffer.readInt(); + m_cursorY = buffer.readInt(); + m_cursorBlink = buffer.readBoolean(); + + byte cursorColour = buffer.readByte(); + m_cursorBackgroundColour = (cursorColour >> 4) & 0xF; + m_cursorColour = cursorColour & 0xF; + + for( int y = 0; y < m_height; y++ ) + { + TextBuffer text = m_text[y]; + TextBuffer textColour = m_textColour[y]; + TextBuffer backColour = m_backgroundColour[y]; + + for( int x = 0; x < m_width; x++ ) + { + text.setChar( x, (char) (buffer.readByte() & 0xFF) ); + + byte colour = buffer.readByte(); + backColour.setChar( x, base16.charAt( (colour >> 4) & 0xF ) ); + textColour.setChar( x, base16.charAt( colour & 0xF ) ); + } + } + + m_palette.read( buffer ); + setChanged(); + } + public synchronized NBTTagCompound writeToNBT( NBTTagCompound nbt ) { nbt.setInteger( "term_cursorX", m_cursorX ); @@ -349,10 +392,8 @@ public class Terminal nbt.setString( "term_textColour_" + n, m_textColour[n].toString() ); nbt.setString( "term_textBgColour_" + n, m_backgroundColour[n].toString() ); } - if( m_palette != null ) - { - m_palette.writeToNBT( nbt ); - } + + m_palette.writeToNBT( nbt ); return nbt; } @@ -382,10 +423,15 @@ public class Terminal m_backgroundColour[n].write( nbt.getString( "term_textBgColour_" + n ) ); } } - if( m_palette != null ) - { - m_palette.readFromNBT( nbt ); - } + + m_palette.readFromNBT( nbt ); setChanged(); } + + private static int colourIndex( char c ) + { + if( c >= '0' && c <= '9' ) return c - '0'; + if( c >= 'a' && c <= 'f' ) return c - 'a' + 10; + return 0; + } } diff --git a/src/main/java/dan200/computercraft/shared/common/ClientTerminal.java b/src/main/java/dan200/computercraft/shared/common/ClientTerminal.java index f823724d0..5df44befa 100644 --- a/src/main/java/dan200/computercraft/shared/common/ClientTerminal.java +++ b/src/main/java/dan200/computercraft/shared/common/ClientTerminal.java @@ -6,7 +6,9 @@ package dan200.computercraft.shared.common; import dan200.computercraft.core.terminal.Terminal; +import io.netty.buffer.Unpooled; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; public class ClientTerminal implements ITerminal { @@ -53,7 +55,7 @@ public class ClientTerminal implements ITerminal { NBTTagCompound terminal = nbt.getCompoundTag( "terminal" ); resizeTerminal( terminal.getInteger( "term_width" ), terminal.getInteger( "term_height" ) ); - m_terminal.readFromNBT( terminal ); + m_terminal.read( new PacketBuffer( Unpooled.wrappedBuffer( terminal.getByteArray( "term_contents" ) ) ) ); } else { diff --git a/src/main/java/dan200/computercraft/shared/common/ServerTerminal.java b/src/main/java/dan200/computercraft/shared/common/ServerTerminal.java index 7c72b11c5..d4c89dba5 100644 --- a/src/main/java/dan200/computercraft/shared/common/ServerTerminal.java +++ b/src/main/java/dan200/computercraft/shared/common/ServerTerminal.java @@ -5,8 +5,12 @@ */ package dan200.computercraft.shared.common; +import dan200.computercraft.ComputerCraft; import dan200.computercraft.core.terminal.Terminal; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; import java.util.concurrent.atomic.AtomicBoolean; @@ -83,17 +87,28 @@ public class ServerTerminal implements ITerminal return m_colour; } - // Networking stuff - public void writeDescription( NBTTagCompound nbt ) { nbt.setBoolean( "colour", m_colour ); if( m_terminal != null ) { + // We have a 10 byte header (2 integer positions, then blinking and current colours), followed by the + // contents and palette. + // Yes, this serialisation code is terrible, but we need to serialise to NBT in order to work with monitors + // (or rather tile entity serialisation). + final int length = 10 + (2 * m_terminal.getWidth() * m_terminal.getHeight()) + (16 * 3); + ByteBuf buffer = Unpooled.buffer( length ); + m_terminal.write( new PacketBuffer( buffer ) ); + + if( buffer.writableBytes() != 0 ) + { + ComputerCraft.log.warn( "Should have written {} bytes, but have {} ({} remaining).", length, buffer.writerIndex(), buffer.writableBytes() ); + } + NBTTagCompound terminal = new NBTTagCompound(); terminal.setInteger( "term_width", m_terminal.getWidth() ); terminal.setInteger( "term_height", m_terminal.getHeight() ); - m_terminal.writeToNBT( terminal ); + terminal.setByteArray( "term_contents", buffer.array() ); nbt.setTag( "terminal", terminal ); } } diff --git a/src/main/java/dan200/computercraft/shared/util/Palette.java b/src/main/java/dan200/computercraft/shared/util/Palette.java index e177940c2..e7c296388 100644 --- a/src/main/java/dan200/computercraft/shared/util/Palette.java +++ b/src/main/java/dan200/computercraft/shared/util/Palette.java @@ -6,6 +6,7 @@ package dan200.computercraft.shared.util; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; public class Palette { @@ -78,6 +79,22 @@ public class Palette }; } + public void write( PacketBuffer buffer ) + { + for( double[] colour : colours ) + { + for( double channel : colour ) buffer.writeByte( (int) (channel * 0xFF) & 0xFF ); + } + } + + public void read( PacketBuffer buffer ) + { + for( double[] colour : colours ) + { + for( int i = 0; i < colour.length; i++ ) colour[i] = buffer.readByte() * 255; + } + } + public NBTTagCompound writeToNBT( NBTTagCompound nbt ) { int[] rgb8 = new int[colours.length];