mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2025-12-12 17:40:17 -07:00
666 lines
No EOL
10 KiB
Java
666 lines
No EOL
10 KiB
Java
package ms.net.packet;
|
|
|
|
import java.nio.ByteBuffer;
|
|
import java.nio.charset.StandardCharsets;
|
|
|
|
import ms.system.util.ByteBufferUtils;
|
|
|
|
/**
|
|
* Represents the buffer used for reading/writing packets.
|
|
* @author Emperor
|
|
*
|
|
*/
|
|
public class IoBuffer {
|
|
|
|
/**
|
|
* The bit masks.
|
|
*/
|
|
private static final int[] BIT_MASK = new int[32];
|
|
|
|
/**
|
|
* The packet size.
|
|
*/
|
|
private int packetSize;
|
|
|
|
/**
|
|
* The opcode.
|
|
*/
|
|
private final int opcode;
|
|
|
|
/**
|
|
* The packet header.
|
|
*/
|
|
private final PacketHeader header;
|
|
|
|
/**
|
|
* The byte buffer.
|
|
*/
|
|
private ByteBuffer buf;
|
|
|
|
/**
|
|
* The bit position.
|
|
*/
|
|
private int bitPosition = 0;
|
|
|
|
/**
|
|
* Constructs a new {@code IoBuffer} {@code Object}.
|
|
*/
|
|
public IoBuffer() {
|
|
this(-1, PacketHeader.NORMAL, ByteBuffer.allocate(2048));
|
|
}
|
|
|
|
/**
|
|
* Constructs a new {@code IoBuffer} {@code Object}.
|
|
* @param opcode The opcode.
|
|
*/
|
|
public IoBuffer(int opcode) {
|
|
this(opcode, PacketHeader.NORMAL, ByteBuffer.allocate(2048));
|
|
}
|
|
|
|
/**
|
|
* Constructs a new {@code IoBuffer} {@code Object}.
|
|
* @param opcode The opcode.
|
|
* @param header The packet header.
|
|
*/
|
|
public IoBuffer(int opcode, PacketHeader header) {
|
|
this(opcode, header, ByteBuffer.allocate((1 << 16) + 1));
|
|
}
|
|
|
|
/**
|
|
* Constructs a new {@code IoBuffer} {@code Object}.
|
|
* @param opcode The opcode.
|
|
* @param header The packet header.
|
|
* @param buf The byte buffer.
|
|
*/
|
|
public IoBuffer(int opcode, PacketHeader header, ByteBuffer buf) {
|
|
this.opcode = opcode;
|
|
this.header = header;
|
|
this.buf = buf;
|
|
}
|
|
|
|
static {
|
|
for (int i = 0; i < 32; i++) {
|
|
BIT_MASK[i] = (1 << i) - 1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public IoBuffer clear() {
|
|
buf.clear();
|
|
bitPosition = 0;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param val
|
|
* @return
|
|
*/
|
|
public IoBuffer put(int val) {
|
|
buf.put((byte) val);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param datas
|
|
* @param offset
|
|
* @param len
|
|
* @return
|
|
*/
|
|
public IoBuffer putBytes(byte[] datas, int offset, int len) {
|
|
for (int i = offset; i < len; i++) {
|
|
put(datas[i]);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
public final void getBytes(byte data[], int off, int len) {
|
|
for (int k = off; k < len + off; k++) {
|
|
data[k] = data[off++];
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param val
|
|
* @return
|
|
*/
|
|
public IoBuffer putA(int val) {
|
|
buf.put((byte) (val + 128));
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param val
|
|
* @return
|
|
*/
|
|
public IoBuffer putC(int val) {
|
|
buf.put((byte) -val);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param val
|
|
* @return
|
|
*/
|
|
public IoBuffer putS(int val) {
|
|
buf.put((byte) (128 - val));
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param val
|
|
* @return
|
|
*/
|
|
public IoBuffer putTri(int val) {
|
|
buf.put((byte) (val >> 16));
|
|
buf.put((byte) (val >> 8));
|
|
buf.put((byte) val);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param val
|
|
* @return
|
|
*/
|
|
public IoBuffer putShort(int val) {
|
|
buf.putShort((short) val);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param val
|
|
* @return
|
|
*/
|
|
public IoBuffer putLEShort(int val) {
|
|
buf.put((byte) val);
|
|
buf.put((byte) (val >> 8));
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param val
|
|
* @return
|
|
*/
|
|
public IoBuffer putShortA(int val) {
|
|
buf.put((byte) (val >> 8));
|
|
buf.put((byte) (val + 128));
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param val
|
|
* @return
|
|
*/
|
|
public IoBuffer putLEShortA(int val) {
|
|
buf.put((byte) (val + 128));
|
|
buf.put((byte) (val >> 8));
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param val
|
|
* @return
|
|
*/
|
|
public IoBuffer putInt(int val) {
|
|
buf.putInt(val);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param val
|
|
* @return
|
|
*/
|
|
public IoBuffer putLEInt(int val) {
|
|
buf.put((byte) val);
|
|
buf.put((byte) (val >> 8));
|
|
buf.put((byte) (val >> 16));
|
|
buf.put((byte) (val >> 24));
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param val
|
|
* @return
|
|
*/
|
|
public IoBuffer putIntA(int val) {
|
|
buf.put((byte) (val >> 8));
|
|
buf.put((byte) val);
|
|
buf.put((byte) (val >> 24));
|
|
buf.put((byte) (val >> 16));
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param val
|
|
* @return
|
|
*/
|
|
public IoBuffer putIntB(int val) {
|
|
buf.put((byte) (val >> 16));
|
|
buf.put((byte) (val >> 24));
|
|
buf.put((byte) val);
|
|
buf.put((byte) (val >> 8));
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param val
|
|
* @return
|
|
*/
|
|
public IoBuffer putLong(long val) {
|
|
buf.putLong(val);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param val
|
|
* @return
|
|
*/
|
|
public IoBuffer putSmart(int val) {
|
|
if (val > Byte.MAX_VALUE) {
|
|
buf.putShort((short) (val + 32768));
|
|
} else {
|
|
buf.put((byte) val);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param val
|
|
* @return
|
|
*/
|
|
public IoBuffer putIntSmart(int val) {
|
|
if (val > Short.MAX_VALUE) {
|
|
buf.putInt(val + 32768);
|
|
} else {
|
|
buf.putShort((short) val);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param val
|
|
* @return
|
|
*/
|
|
public IoBuffer putString(String val) {
|
|
buf.put(val.getBytes(StandardCharsets.UTF_8));
|
|
buf.put((byte) 0);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param val
|
|
* @return
|
|
*/
|
|
public IoBuffer putJagString(String val) {
|
|
buf.put((byte) 0);
|
|
buf.put(val.getBytes(StandardCharsets.UTF_8));
|
|
buf.put((byte) 0);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param val
|
|
* @return
|
|
*/
|
|
public IoBuffer putJagString2(String val) {
|
|
byte[] packed = new byte[256];
|
|
int length = ByteBufferUtils.packGJString2(0, packed, val);
|
|
buf.put((byte) 0).put(packed, 0, length).put((byte) 0);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param val
|
|
* @return
|
|
*/
|
|
public IoBuffer put(byte[] val) {
|
|
buf.put(val);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Puts a byte array as byte A in reverse.
|
|
* @param data The data to put.
|
|
* @param start The start index.
|
|
* @param offset The offset.
|
|
*/
|
|
public void putReverseA(byte[] data, int start, int offset) {
|
|
for (int i = offset + start; i >= start; i--) {
|
|
putA(data[i]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param numBits
|
|
* @param value
|
|
* @return
|
|
*/
|
|
public IoBuffer putBits(int numBits, int value) {
|
|
int bytePos = getBitPosition() >> 3;
|
|
int bitOffset = 8 - (getBitPosition() & 7);
|
|
bitPosition += numBits;
|
|
for (; numBits > bitOffset; bitOffset = 8) {
|
|
byte b = buf.get(bytePos);
|
|
buf.put(bytePos, b &= ~BIT_MASK[bitOffset]);
|
|
buf.put(bytePos++, b |= value >> numBits - bitOffset & BIT_MASK[bitOffset]);
|
|
numBits -= bitOffset;
|
|
}
|
|
byte b = buf.get(bytePos);
|
|
if (numBits == bitOffset) {
|
|
buf.put(bytePos, b &= ~BIT_MASK[bitOffset]);
|
|
buf.put(bytePos, b |= value & BIT_MASK[bitOffset]);
|
|
} else {
|
|
buf.put(bytePos, b &= ~(BIT_MASK[numBits] << bitOffset - numBits));
|
|
buf.put(bytePos, b |= (value & BIT_MASK[numBits]) << bitOffset - numBits);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param buffer
|
|
* @return
|
|
*/
|
|
public IoBuffer put(IoBuffer buffer) {
|
|
buffer.toByteBuffer().flip();
|
|
buf.put(buffer.toByteBuffer());
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param buffer
|
|
* @return
|
|
*/
|
|
public IoBuffer putA(IoBuffer buffer) {
|
|
buffer.toByteBuffer().flip();
|
|
while (buffer.toByteBuffer().hasRemaining()) {
|
|
putA(buffer.toByteBuffer().get());
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param buffer
|
|
* @return
|
|
*/
|
|
public IoBuffer put(ByteBuffer buffer) {
|
|
buf.put(buffer);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public IoBuffer setBitAccess() {
|
|
bitPosition = buf.position() * 8;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public IoBuffer setByteAccess() {
|
|
buf.position((getBitPosition() + 7) / 8);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public int get() {
|
|
return buf.get();
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public int getA() {
|
|
return (buf.get() & 0xFF) - 128;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public int getC() {
|
|
return -buf.get();
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public int getS() {
|
|
return 128 - buf.get();
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public int getTri() {
|
|
return ((buf.get() << 16) & 0xFF) | ((buf.get() << 8) & 0xFF) | (buf.get() & 0xFF);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public int getShort() {
|
|
return buf.getShort();
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public int getLEShort() {
|
|
return (buf.get() & 0xFF) | ((buf.get() & 0xFF) << 8);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public int getShortA() {
|
|
return ((buf.get() & 0xFF) << 8) | (buf.get() - 128 & 0xFF);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public int getLEShortA() {
|
|
return (buf.get() - 128 & 0xFF) | ((buf.get() & 0xFF) << 8);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public int getInt() {
|
|
return buf.getInt();
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public int getLEInt() {
|
|
return (buf.get() & 0xFF) + ((buf.get() & 0xFF) << 8)
|
|
+ ((buf.get() & 0xFF) << 16) + ((buf.get() & 0xFF) << 24);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public int getIntA() {
|
|
return ((buf.get() & 0xFF) << 8) + (buf.get() & 0xFF)+ ((buf.get() & 0xFF) << 24) + ((buf.get() & 0xFF) << 16);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public int getIntB() {
|
|
return ((buf.get() & 0xFF) << 16) + ((buf.get() & 0xFF) << 24)
|
|
+ (buf.get() & 0xFF) + ((buf.get() & 0xFF) << 8);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public long getLongL() {
|
|
long first = getIntB();
|
|
long second = getIntB();
|
|
if (second < 0)
|
|
second = second & 0xffffffffL;
|
|
return (first << -41780448) + second;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public long getLong() {
|
|
return buf.getLong();
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public int getIntSmart() {
|
|
int peek = buf.getShort(buf.position());
|
|
if (peek <= Short.MAX_VALUE) {
|
|
return buf.getShort() & 0xFFFF;
|
|
}
|
|
return (buf.getInt() & 0xFFFFFFFF) - 32768;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public String getString() {
|
|
return ByteBufferUtils.getString(buf);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public String getJagString() {
|
|
buf.get();
|
|
return ByteBufferUtils.getString(buf);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param is
|
|
* @param offset
|
|
* @param length
|
|
* @return
|
|
*/
|
|
public IoBuffer getReverseA(byte[] is, int offset, int length) {
|
|
for (int i = (offset + length - 1); i >= offset; i--) {
|
|
is[i] = (byte) (buf.get() - 128);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public ByteBuffer toByteBuffer() {
|
|
return buf;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public int opcode() {
|
|
return opcode;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public int readableBytes() {
|
|
return buf.capacity() - buf.remaining();
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public PacketHeader getHeader() {
|
|
return header;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return
|
|
*/
|
|
public byte[] array() {
|
|
return buf.array();
|
|
}
|
|
|
|
/**
|
|
* @return the packetSize.
|
|
*/
|
|
public int getPacketSize() {
|
|
return packetSize;
|
|
}
|
|
|
|
/**
|
|
* @param packetSize the packetSize to set.
|
|
*/
|
|
public void setPacketSize(int packetSize) {
|
|
this.packetSize = packetSize;
|
|
}
|
|
|
|
/**
|
|
* Gets the bitPosition.
|
|
* @return The bitPosition.
|
|
*/
|
|
public int getBitPosition() {
|
|
return bitPosition;
|
|
}
|
|
|
|
} |