Code:
import java.math.BigInteger;
/**
* In the new method names, the following represent:
* H - Half/Halves (When used with V, indicates the 128 magic number is used)
* P - Partial (In this case 3/4 or 1/4)
* A - Altered (When used with V, indicates the 128 magic number is used)
* V - Value
* @author TeleNubby (42/55)
* @author Taharok (13/55) <3
*/
public class Stream extends Node
{
/**
* Replaced all 128 instances in read/write methods with this.
*/
private static final int MAGIC_NUMBER = 128;
public byte[] buffer;
public int offset;
public Stream(byte[] is) {
buffer = is;
offset = 0;
}
public Stream(int i) {
buffer = Class29.method874(i, 100);
offset = 0;
}
public int writeBufferChecksum(int ofs) {
int value = Class1.getCRC(buffer, ofs, offset);
writeInt(value);
return value;
}
public void writeString(RSString string) {
offset += string.getRawStringLen(buffer, offset, string.length());
buffer[offset++] = (byte) 0;
}
public void writeBytes(byte[] writeBuffer, int ofs, int len) {
for (int i = ofs; i < ofs + len; i++)
buffer[offset++] = writeBuffer[i];
}
public void writeByte(int i) {
buffer[offset++] = (byte) i;
}
public void writeByteHV(int i) {
buffer[offset++] = (byte) (i + MAGIC_NUMBER);
}
public void writeNegativeByte(int i) {
buffer[offset++] = (byte) -i;
}
public void writeByteAtPos(int valueAndIndex) {
buffer[offset - valueAndIndex - 1] = (byte) valueAndIndex;
}
public void writeShort(int i) {
buffer[offset++] = (byte) (i >> 8);
buffer[offset++] = (byte) i;
}
public void writeReverseShort(int i) {
buffer[offset++] = (byte) i;
buffer[offset++] = (byte) (i >> 8);
}
public void writeShortHV(int i) {
buffer[offset++] = (byte) (i >> 8);
buffer[offset++] = (byte) (i + MAGIC_NUMBER);
}
public void writeReverseShortHV(int i) {
buffer[offset++] = (byte) (i + MAGIC_NUMBER);
buffer[offset++] = (byte) (i >> 8);
}
public void writeShortInt(int i) {
buffer[offset++] = (byte) (i >> 16);
buffer[offset++] = (byte) (i >> 8);
buffer[offset++] = (byte) i;
}
public void writeInt(int i) {
buffer[offset++] = (byte) (i >> 24);
buffer[offset++] = (byte) (i >> 16);
buffer[offset++] = (byte) (i >> 8);
buffer[offset++] = (byte) i;
}
public void writeReverseInt(int i) {
buffer[offset++] = (byte) i;
buffer[offset++] = (byte) (i >> 8);
buffer[offset++] = (byte) (i >> 16);
buffer[offset++] = (byte) (i >> 24);
}
public void writeInFlippedInt(int i) {
buffer[offset++] = (byte) (i >> 16);
buffer[offset++] = (byte) (i >> 24);
buffer[offset++] = (byte) i;
buffer[offset++] = (byte) (i >> 8);
}
public void writeReverseInFlippedInt(int i) {
buffer[offset++] = (byte) (i >> 8);
buffer[offset++] = (byte) i;
buffer[offset++] = (byte) (i >> 24);
buffer[offset++] = (byte) (i >> 16);
}
public void writeIntAtPos(int valueAndIndex) {
buffer[offset - 4 - valueAndIndex] = (byte) (valueAndIndex >> 24);
buffer[offset - 3 - valueAndIndex] = (byte) (valueAndIndex >> 16);
buffer[offset - 2 - valueAndIndex] = (byte) (valueAndIndex >> 8);
buffer[offset - 1 - valueAndIndex] = (byte) valueAndIndex;
}
public void writeLong(long l) {
buffer[offset++] = (byte) (int) (l >> 56);
buffer[offset++] = (byte) (int) (l >> 48);
buffer[offset++] = (byte) (int) (l >> 40);
buffer[offset++] = (byte) (int) (l >> 32);
buffer[offset++] = (byte) (int) (l >> 24);
buffer[offset++] = (byte) (int) (l >> 16);
buffer[offset++] = (byte) (int) (l >> 8);
buffer[offset++] = (byte) (int) l;
}
public void writeUnsignedBytes(long val, int numBytes, int i) {
if ((--numBytes < 0) || (numBytes > 7))
throw new IllegalArgumentException();
for (int shift = i * numBytes; shift > 0; shift -= 8)
buffer[offset++] = (byte) (int) (val >> shift);
}
public void writeByteOrShortH(int i) {
if ((i >= 0) && (i < 128)) //Write half-byte
writeByte(i);
else if ((i >= 0) && (i < 0x8000)) //Write half-short + byte
writeShort(i + 0x8000);
else
throw new IllegalArgumentException();
}
public RSString readString() {
int startPos = offset;
while (buffer[offset++] != 0) { }
int length = offset - startPos - 1;
return Class105.method1565(length, startPos, buffer);
}
public RSString readCheckedString() {
if (buffer[offset] == 0) {
offset++;
return null;
}
return readString();
}
public void readBytes(byte[] readBuffer, int ofs, int len) {
for (int i = ofs; i < ofs + len; i++)
readBuffer[i] = buffer[offset++];
}
public long readUnsignedBytes(int numBytes) {
if ((--numBytes < 0) || (numBytes > 7))
throw new IllegalArgumentException();
int shift = numBytes * 8;
long l = 0L;
for (; shift >= 0; shift -= 8)
l |= (buffer[offset++] & 0xffL) << shift;
return l;
}
public void readBytesHV(byte[] readBuffer, int ofs, int len) {
for (int i = ofs; i < ofs + len; i++)
readBuffer[i] = (byte) (buffer[offset++] - MAGIC_NUMBER);
}
public void readBytesBackwards(byte[] readBuffer, int ofs, int len) {
for (int i = len + ofs - 1; i >= ofs; i--)
readBuffer[i] = buffer[offset++];
}
public byte readByte() {
return buffer[offset++];
}
public byte readByteHV() {
return (byte) (buffer[offset++] - MAGIC_NUMBER);
}
public byte readByteAV() {
return (byte) (128 - buffer[offset++]);
}
public int readUnsignedByteAV() {
return 128 - buffer[offset++] & 0xff;
}
public int readUnsignedByte() {
return buffer[offset++] & 0xff;
}
public byte readNegativeByte() {
return (byte) -buffer[offset++];
}
public int readUnsignedNegativeByte() {
return -buffer[offset++] & 0xff;
}
public int readUnsignedByteHV() {
return 0xff & buffer[offset++] - MAGIC_NUMBER;
}
public int readByteOrShortP() {
int read = buffer[offset] & 0xff;
if (read >= 128)
return readShort() - 0xC000;
return readUnsignedByte() - 64;
}
public int readByteOrShortH() {
int read = buffer[offset] & 0xFF;
if (read >= 128)
return readShort() - 0x8000;
return readUnsignedByte();
}
public int readShort() {
offset += 2;
return (0xff & buffer[offset - 1])
+ (buffer[offset - 2] << 8 & 0xff00);
}
public int readReverseShort() {
offset += 2;
return (0xff & buffer[offset - 2])
+ (0xff00 & buffer[offset - 1] << 8);
}
public int readShortHV() {
offset += 2;
return (buffer[offset - 2] << 8 & 0xff00)
+ (0xff & buffer[offset - 1] - MAGIC_NUMBER);
}
public int readReverseShortHV() {
offset += 2;
return ((0xff & buffer[offset - 1]) << 8)
+ (0xff & buffer[offset - 2] - MAGIC_NUMBER);
}
public int readShortsH() {
int result = 0;
int read = readByteOrShortH();
while (read == 32767) {
read = readByteOrShortH();
result += 32767;
}
result += read;
return result;
}
public int readNegHalfShortOrPosFullShort() {
offset += 2;
int read = (0xff & buffer[offset - 1])
+ (buffer[offset - 2] << 8 & 0xff00);
if (read > 0x7FFF)
read -= 0x10000;
return read;
}
public int readShortInt() {
offset += 3;
return (0xff & buffer[offset - 1])
+ ((0xff & buffer[offset - 3]) << 16)
+ ((0xff & buffer[offset - 2]) << 8);
}
public int readLargeShortInt() {
offset += 3;
return (buffer[offset - 2] & 0xff)
+ (0xff00 & buffer[offset - 1] << 8)
+ ((0xff & buffer[offset - 3]) << 16);
}
public int readShortOrInt() {
offset += 2;
int read = (buffer[offset - 2] - MAGIC_NUMBER & 0xFF)
+ (buffer[offset - 1] << 8 & 0xFF00);
if (read > 0x7FFF)
read -= 0x10000; //0xFFFF + 1
return read;
}
public int readInt() {
offset += 4;
return ((buffer[offset - 2] & 0xff) << 8)
+ ((buffer[offset - 3] & 0xff) << 16)
+ ((buffer[offset - 4] & 0xff) << 24)
+ (buffer[offset - 1] & 0xff);
}
public int readReverseInt() {
offset += 4;
return (buffer[offset - 2] << 16 & 0xff0000)
+ (~0xffffff & buffer[offset - 1] << 24)
+ ((buffer[offset - 3] & 0xff) << 8)
+ (buffer[offset - 4] & 0xff);
}
public int readInFlippedInt() {
offset += 4;
return (0xff & buffer[offset - 2])
+ ((0xff & buffer[offset - 1]) << 8)
+ ((0xff & buffer[offset - 4]) << 16)
+ ((0xff & buffer[offset - 3]) << 24);
}
public int readReverseInFlippedInt() {
offset += 4;
return ((0xff & buffer[offset - 4]) << 8)
+ (buffer[offset - 1] << 16 & 0xff0000)
+ (~0xffffff & buffer[offset - 2] << 24)
+ (0xff & buffer[offset - 3]);
}
public long readLong() {
long l = 0xffffffffL & readInt();
long l_40_ = readInt() & 0xffffffffL;
return l_40_ + (l << 32);
}
public int readShiftedBytesH() {
int read = buffer[offset++];
int result = 0;
for (; read < 0; read = buffer[offset++])
result = (read & 0x7f | result) //& 0x7F ensures half-byte
<< 7; //Shifts half-byte by 7 bits
return result | read;
}
public void randomizeNextStream(int[] keys, int ofs, int randomLen) {
int oldOffset = offset;
offset = ofs;
int length = (randomLen - ofs) / 8;
for (int i = 0; i < length; i++) {
int read1 = readInt();
int read2 = readInt();
int randomizer = -957401312;
int iterator = 32;
while (iterator-- > 0) {
read2 -= read1 + (read1 << 4 ^ read1 >>> 5)
^ keys[randomizer >>> 11 & ~0x2b3ffffc] + randomizer;
randomizer -= -1640531527;
read1 -= keys[randomizer & 0x3] + randomizer ^ read2
+ (read2 >>> 5 ^ read2 << 4);
}
offset -= 8;
writeInt(read1);
writeInt(read2);
}
offset = oldOffset;
}
public void encryptStream(BigInteger key1, BigInteger key2) {
int length = readUnsignedByte();
byte[] readBuffer = new byte[length];
readBytes(readBuffer, 0, length);
BigInteger readBufferWrapper = new BigInteger(readBuffer);
BigInteger encryptedWrapper = readBufferWrapper;//.modPow(key1, key2);
byte[] encryptedBuffer = encryptedWrapper.toByteArray();
offset = 0;
writeBytes(encryptedBuffer, 0, encryptedBuffer.length);
}
public void encryptEntireStream(BigInteger key1, BigInteger key2) {
int oldOffset = offset;
offset = 0;
byte[] currentBuffer = new byte[oldOffset];
readBytes(currentBuffer, 0, oldOffset);
BigInteger currentBufferWrapper = new BigInteger(currentBuffer);
BigInteger encryptedBufferWrapper = currentBufferWrapper;//.modPow(key1, key2);
byte[] encryptedBuffer = encryptedBufferWrapper.toByteArray();
offset = 0;
writeByte(encryptedBuffer.length);
writeBytes(encryptedBuffer, 0, encryptedBuffer.length);
}
/**
* <3Taharok
* This method is a bit confusing
* First off, it can handle 3 types of signatures: byte, short, 'short int'
* It will only write a byte if the byte is not a half byte
* It will automatically write 0x363C7F
* It will only write a short if it is greater than a 1/4 of a short
* It will automatically write 0x3ffff and 0x363C7F
* It will only write a 'short int' if it is greater than 7/8 of a 'short int'
* It will automatically write 2047, 0x3ffff, and 0x363C7F
* On top of the rest, this method will automatically write the half byte
* of the parameter, despite its former value (used in the conditionals)
* PERSONAL REFLECTION: Because this method writes constants based on specific values,
* I am nearly certain it is a flagging method
* I could be totally wrong, but its your stream class, your choice
*/
public void writeFlag(int i) {
if ((~0x7f & i) != 0) { // 0x7f is used to get 1/2 of a byte
if ((~0x3fff & i) != 0) { // 0x3fff is used to get 1/4 of a short
if ((~0x1fffff & i) != 0) { // used to get 7/8 of a 'short int'
// int & ~0xfffffff is always 0
if ((i & ~0xfffffff) != 0)
// half bytes become 128
// over half bytes become 143
writeByte(0x80 | i >>> 28);
// half bytes become 128
// over half bytes become 0x7FF, or 2047 which is
// the magic id number for the player update packet
// (or was)
writeByte(i >>> 21 | 0x80);
}
// half bytes become 128
// over half bytes become 0x3ffff
// i dont know the significance
writeByte((0x2003bd | i) >>> 14);
}
// if its a half byte, it will become 128 (1 + half byte 0x7f)
// if it is over a half byte, it will become 0x363C7F (no idea what that is)
writeByte(0x80 | i >>> 7);
}
writeByte(0x7f & i); // force the byte to a half byte
}
}
Credits: