mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-12-12 19:20:29 +00:00
Improve serialisation of terminals
- Write to a PacketBuffer instead of generating an NBT tag. This is then converted to an NBT byte array when we send across the network. - Pack background/foreground colours into a single byte. This derives from some work I did back in 2017, and some of the changes made/planned in #409. However, this patch does not change how terminals are represented, it simply makes the transfer more compact. This makes the patch incredibly small (100 lines!), but also limited in what improvements it can make compared with #409. We send 26626 bytes for a full-sized monitor. While a 2x improvement over the previous 58558 bytes, there's a lot of room for improvement.
This commit is contained in:
parent
4553e404b2
commit
17b7727262
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
@ -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];
|
||||
|
Loading…
Reference in New Issue
Block a user