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