mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-11-08 01:12:59 +00:00
Rewrite monitor networking (#453)
This moves monitor networking into its own packet, rather than serialising using NBT. This allows us to be more flexible with how monitors are serialised. We now compress terminal data using gzip. This reduces the packet size of a max-sized-monitor from ~25kb to as little as 100b. On my test set of images (what I would consider to be the extreme end of the "reasonable" case), we have packets from 1.4kb bytes up to 12kb, with a mean of 6kb. Even in the worst case, this is a 2x reduction in packet size. While this is a fantastic win for the common case, it is not abuse-proof. One can create a terminal with high entropy (and so uncompressible). This will still be close to the original packet size. In order to prevent any other abuse, we also limit the amount of monitor data a client can possibly receive to 1MB (configurable).
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.network.client;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.core.terminal.TextBuffer;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.RepeatedTest;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* Tests {@link TerminalState} round tripping works as expected.
|
||||
*/
|
||||
public class TerminalStateTest
|
||||
{
|
||||
@BeforeAll
|
||||
public static void before()
|
||||
{
|
||||
ComputerCraft.log = LogManager.getLogger( ComputerCraft.MOD_ID );
|
||||
}
|
||||
|
||||
@RepeatedTest( 5 )
|
||||
public void testCompressed()
|
||||
{
|
||||
Terminal terminal = randomTerminal();
|
||||
|
||||
PacketBuffer buffer = new PacketBuffer( Unpooled.directBuffer() );
|
||||
new TerminalState( true, terminal, true ).write( buffer );
|
||||
|
||||
checkEqual( terminal, read( buffer ) );
|
||||
assertEquals( 0, buffer.readableBytes() );
|
||||
}
|
||||
|
||||
@RepeatedTest( 5 )
|
||||
public void testUncompressed()
|
||||
{
|
||||
Terminal terminal = randomTerminal();
|
||||
|
||||
PacketBuffer buffer = new PacketBuffer( Unpooled.directBuffer() );
|
||||
new TerminalState( true, terminal, false ).write( buffer );
|
||||
|
||||
checkEqual( terminal, read( buffer ) );
|
||||
assertEquals( 0, buffer.readableBytes() );
|
||||
}
|
||||
|
||||
private static Terminal randomTerminal()
|
||||
{
|
||||
Random random = new Random();
|
||||
Terminal terminal = new Terminal( 10, 5 );
|
||||
for( int y = 0; y < terminal.getHeight(); y++ )
|
||||
{
|
||||
TextBuffer buffer = terminal.getLine( y );
|
||||
for( int x = 0; x < buffer.length(); x++ ) buffer.setChar( x, (char) (random.nextInt( 26 ) + 65) );
|
||||
}
|
||||
|
||||
return terminal;
|
||||
}
|
||||
|
||||
private static void checkEqual( Terminal expected, Terminal actual )
|
||||
{
|
||||
assertNotNull( expected, "Expected cannot be null" );
|
||||
assertNotNull( actual, "Actual cannot be null" );
|
||||
assertEquals( expected.getHeight(), actual.getHeight(), "Heights must match" );
|
||||
assertEquals( expected.getWidth(), actual.getWidth(), "Widths must match" );
|
||||
|
||||
for( int y = 0; y < expected.getHeight(); y++ )
|
||||
{
|
||||
assertEquals( expected.getLine( y ).toString(), actual.getLine( y ).toString() );
|
||||
}
|
||||
}
|
||||
|
||||
private static Terminal read( PacketBuffer buffer )
|
||||
{
|
||||
TerminalState state = new TerminalState( buffer );
|
||||
assertTrue( state.colour );
|
||||
|
||||
if( !state.hasTerminal() ) return null;
|
||||
|
||||
Terminal other = new Terminal( state.width, state.height );
|
||||
state.apply( other );
|
||||
return other;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user