package net.md_5.bungee.protocol; import com.google.common.base.Charsets; import io.netty.buffer.ByteBuf; import java.util.ArrayList; import java.util.List; import lombok.RequiredArgsConstructor; import java.util.UUID; @RequiredArgsConstructor public abstract class DefinedPacket { public static void writeString(String s, ByteBuf buf) { if ( s.length() > Short.MAX_VALUE ) { throw new OverflowPacketException( String.format( "Cannot send string longer than Short.MAX_VALUE (got %s characters)", s.length() ) ); } byte[] b = s.getBytes( Charsets.UTF_8 ); writeVarInt( b.length, buf ); buf.writeBytes( b ); } public static String readString(ByteBuf buf) { int len = readVarInt( buf ); if ( len > Short.MAX_VALUE ) { throw new OverflowPacketException( String.format( "Cannot receive string longer than Short.MAX_VALUE (got %s characters)", len ) ); } byte[] b = new byte[ len ]; buf.readBytes( b ); return new String( b, Charsets.UTF_8 ); } public static void writeArray(byte[] b, ByteBuf buf) { if ( b.length > Short.MAX_VALUE ) { throw new OverflowPacketException( String.format( "Cannot send byte array longer than Short.MAX_VALUE (got %s bytes)", b.length ) ); } writeVarInt( b.length, buf ); buf.writeBytes( b ); } public static byte[] toArray(ByteBuf buf) { byte[] ret = new byte[ buf.readableBytes() ]; buf.readBytes( ret ); return ret; } public static byte[] readArray(ByteBuf buf) { return readArray( buf, buf.readableBytes() ); } public static byte[] readArray(ByteBuf buf, int limit) { int len = readVarInt( buf ); if ( len > limit ) { throw new OverflowPacketException( String.format( "Cannot receive byte array longer than %s (got %s bytes)", limit, len ) ); } byte[] ret = new byte[ len ]; buf.readBytes( ret ); return ret; } public static void writeStringArray(List<String> s, ByteBuf buf) { writeVarInt( s.size(), buf ); for ( String str : s ) { writeString( str, buf ); } } public static List<String> readStringArray(ByteBuf buf) { int len = readVarInt( buf ); List<String> ret = new ArrayList<>( len ); for ( int i = 0; i < len; i++ ) { ret.add( readString( buf ) ); } return ret; } public static int readVarInt(ByteBuf input) { return readVarInt( input, 5 ); } public static int readVarInt(ByteBuf input, int maxBytes) { int out = 0; int bytes = 0; byte in; while ( true ) { in = input.readByte(); out |= ( in & 0x7F ) << ( bytes++ * 7 ); if ( bytes > maxBytes ) { throw new RuntimeException( "VarInt too big" ); } if ( ( in & 0x80 ) != 0x80 ) { break; } } return out; } public static void writeVarInt(int value, ByteBuf output) { int part; while ( true ) { part = value & 0x7F; value >>>= 7; if ( value != 0 ) { part |= 0x80; } output.writeByte( part ); if ( value == 0 ) { break; } } } public static int readVarShort(ByteBuf buf) { int low = buf.readUnsignedShort(); int high = 0; if ( ( low & 0x8000 ) != 0 ) { low = low & 0x7FFF; high = buf.readUnsignedByte(); } return ( ( high & 0xFF ) << 15 ) | low; } public static void writeVarShort(ByteBuf buf, int toWrite) { int low = toWrite & 0x7FFF; int high = ( toWrite & 0x7F8000 ) >> 15; if ( high != 0 ) { low = low | 0x8000; } buf.writeShort( low ); if ( high != 0 ) { buf.writeByte( high ); } } public static void writeUUID(UUID value, ByteBuf output) { output.writeLong( value.getMostSignificantBits() ); output.writeLong( value.getLeastSignificantBits() ); } public static UUID readUUID(ByteBuf input) { return new UUID( input.readLong(), input.readLong() ); } public void read(ByteBuf buf) { throw new UnsupportedOperationException( "Packet must implement read method" ); } public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { read( buf ); } public void write(ByteBuf buf) { throw new UnsupportedOperationException( "Packet must implement write method" ); } public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { write( buf ); } public abstract void handle(AbstractPacketHandler handler) throws Exception; @Override public abstract boolean equals(Object obj); @Override public abstract int hashCode(); @Override public abstract String toString(); }