From 13c4358d77ef13bb7369bb924af689c6d98f9e5c Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Wed, 3 Jun 2026 12:52:06 +0000 Subject: [PATCH] Cleaned up some core files --- Server/src/main/core/cache/Cache.java | 2 +- Server/src/main/core/cache/CacheFile.java | 2 +- Server/src/main/core/cache/StoreFile.java | 72 ----- .../main/core/cache/crypto/ISAACCipher.java | 271 ------------------ .../src/main/core/cache/crypto/ISAACCipher.kt | 213 ++++++++++++++ .../src/main/core/cache/crypto/ISAACPair.java | 45 --- .../src/main/core/cache/crypto/ISAACPair.kt | 9 + .../main/core/cache/crypto/XTEACryption.java | 124 -------- .../main/core/cache/crypto/XTEACryption.kt | 97 +++++++ .../src/main/core/cache/misc/Container.java | 109 ------- Server/src/main/core/cache/misc/Container.kt | 7 + .../cache/misc/ContainersInformation.java | 228 --------------- .../core/cache/misc/ContainersInformation.kt | 145 ++++++++++ .../main/core/cache/misc/FilesContainer.java | 57 ---- .../main/core/cache/misc/FilesContainer.kt | 9 + .../cache/misc/buffer/BufferInputStream.java | 39 --- .../cache/misc/buffer/BufferOutputStream.java | 57 ---- .../cache/misc/buffer/ByteBufferUtils.java | 182 ------------ .../core/cache/misc/buffer/ByteBufferUtils.kt | 142 +++++++++ .../command/sets/DevelopmentCommandSet.kt | 38 +-- 20 files changed, 644 insertions(+), 1204 deletions(-) delete mode 100644 Server/src/main/core/cache/StoreFile.java delete mode 100644 Server/src/main/core/cache/crypto/ISAACCipher.java create mode 100644 Server/src/main/core/cache/crypto/ISAACCipher.kt delete mode 100644 Server/src/main/core/cache/crypto/ISAACPair.java create mode 100644 Server/src/main/core/cache/crypto/ISAACPair.kt delete mode 100644 Server/src/main/core/cache/crypto/XTEACryption.java create mode 100644 Server/src/main/core/cache/crypto/XTEACryption.kt delete mode 100644 Server/src/main/core/cache/misc/Container.java create mode 100644 Server/src/main/core/cache/misc/Container.kt delete mode 100644 Server/src/main/core/cache/misc/ContainersInformation.java create mode 100644 Server/src/main/core/cache/misc/ContainersInformation.kt delete mode 100644 Server/src/main/core/cache/misc/FilesContainer.java create mode 100644 Server/src/main/core/cache/misc/FilesContainer.kt delete mode 100644 Server/src/main/core/cache/misc/buffer/BufferInputStream.java delete mode 100644 Server/src/main/core/cache/misc/buffer/BufferOutputStream.java delete mode 100644 Server/src/main/core/cache/misc/buffer/ByteBufferUtils.java create mode 100644 Server/src/main/core/cache/misc/buffer/ByteBufferUtils.kt diff --git a/Server/src/main/core/cache/Cache.java b/Server/src/main/core/cache/Cache.java index ce4ed3c25..3459d58b9 100644 --- a/Server/src/main/core/cache/Cache.java +++ b/Server/src/main/core/cache/Cache.java @@ -145,7 +145,7 @@ public final class Cache { buffer.putInt(0); continue; } - buffer.putInt(cacheFileManagers[index].getInformation().getInformationContainer().getCrc()); + buffer.putInt(cacheFileManagers[index].getInformation().informationContainer.getCrc()); buffer.putInt(cacheFileManagers[index].getInformation().getRevision()); } return buffer.array(); diff --git a/Server/src/main/core/cache/CacheFile.java b/Server/src/main/core/cache/CacheFile.java index a03642895..bd21a8a0d 100644 --- a/Server/src/main/core/cache/CacheFile.java +++ b/Server/src/main/core/cache/CacheFile.java @@ -66,7 +66,7 @@ public final class CacheFile { return null; } if (xteaKeys != null && (xteaKeys[0] != 0 || xteaKeys[1] != 0 || xteaKeys[2] != 0 || xteaKeys[3] != 0)) { - packedData = XTEACryption.decrypt(xteaKeys, ByteBuffer.wrap(packedData), 5, packedData.length).array(); + packedData = XTEACryption.Companion.decrypt(xteaKeys, ByteBuffer.wrap(packedData), 5, packedData.length).array(); } return ContainersInformation.unpackCacheContainer(packedData); } diff --git a/Server/src/main/core/cache/StoreFile.java b/Server/src/main/core/cache/StoreFile.java deleted file mode 100644 index 50e1728d0..000000000 --- a/Server/src/main/core/cache/StoreFile.java +++ /dev/null @@ -1,72 +0,0 @@ -package core.cache; - -import java.nio.ByteBuffer; - -/** - * Represents a file used in the server store. - * @author Emperor - */ -public final class StoreFile { - - /** - * If the data can change during server runtime. - */ - private boolean dynamic; - - /** - * The file data. - */ - private byte[] data; - - /** - * Constructs a new {@code StoreFile} {@code Object}. - */ - public StoreFile() { - /* - * empty. - */ - } - - /** - * Puts the data on the buffer. - * @param buffer The buffer. - */ - public void put(ByteBuffer buffer) { - byte[] data = new byte[buffer.remaining()]; - buffer.get(data); - this.data = data; - } - - /** - * Creates a byte buffer containing the file data. - * @return The buffer. - */ - public ByteBuffer data() { - return ByteBuffer.wrap(data); - } - - /** - * Sets the data. - * @param data The data. - */ - public void setData(byte[] data) { - this.data = data; - } - - /** - * Gets the dynamic. - * @return The dynamic. - */ - public boolean isDynamic() { - return dynamic; - } - - /** - * Sets the dynamic. - * @param dynamic The dynamic to set. - */ - public void setDynamic(boolean dynamic) { - this.dynamic = dynamic; - } - -} \ No newline at end of file diff --git a/Server/src/main/core/cache/crypto/ISAACCipher.java b/Server/src/main/core/cache/crypto/ISAACCipher.java deleted file mode 100644 index 16cd85b18..000000000 --- a/Server/src/main/core/cache/crypto/ISAACCipher.java +++ /dev/null @@ -1,271 +0,0 @@ -package core.cache.crypto; - -/** - *

An implementation of an ISAAC cipher. See - * http://en.wikipedia.org/wiki/ISAAC_(cipher) for more information.

- *

This implementation is based on the one written by Bob Jenkins, which is - * available at - * http://www.burtleburtle.net/bob/java/rand/Rand.java.

- * @author Graham Edgecombe - */ -public class ISAACCipher { - - /** - * The golden ratio. - */ - public static final int RATIO = 0x9e3779b9; - - /** - * The log of the size of the results and memory arrays. - */ - public static final int SIZE_LOG = 8; - - /** - * The size of the results and memory arrays. - */ - public static final int SIZE = 1 << SIZE_LOG; - - /** - * For pseudorandom lookup. - */ - public static final int MASK = (SIZE - 1) << 2; - - /** - * The count through the results. - */ - private int count = 0; - - /** - * The results. - */ - private int results[] = new int[SIZE]; - - /** - * The internal memory state. - */ - private int memory[] = new int[SIZE]; - - /** - * The accumulator. - */ - private int a; - - /** - * The last result. - */ - private int b; - - /** - * The counter. - */ - private int c; - - /** - * Creates the ISAAC cipher. - * @param seed The seed. - */ - public ISAACCipher(int[] seed) { - for (int i = 0; i < seed.length; i++) { - results[i] = seed[i]; - } - init(true); - } - - /** - * Gets the next value. - * @return The next value. - */ - public int getNextValue() { - if (count-- == 0) { - isaac(); - count = SIZE - 1; - } - return 0;//results[count]; - } - - /** - * Generates 256 results. - */ - public void isaac() { - int i, j, x, y; - b += ++c; - for (i = 0, j = SIZE / 2; i < SIZE / 2;) { - x = memory[i]; - a ^= a << 13; - a += memory[j++]; - memory[i] = y = memory[(x & MASK) >> 2] + a + b; - results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x; - - x = memory[i]; - a ^= a >>> 6; - a += memory[j++]; - memory[i] = y = memory[(x & MASK) >> 2] + a + b; - results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x; - - x = memory[i]; - a ^= a << 2; - a += memory[j++]; - memory[i] = y = memory[(x & MASK) >> 2] + a + b; - results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x; - - x = memory[i]; - a ^= a >>> 16; - a += memory[j++]; - memory[i] = y = memory[(x & MASK) >> 2] + a + b; - results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x; - } - for (j = 0; j < SIZE / 2;) { - x = memory[i]; - a ^= a << 13; - a += memory[j++]; - memory[i] = y = memory[(x & MASK) >> 2] + a + b; - results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x; - - x = memory[i]; - a ^= a >>> 6; - a += memory[j++]; - memory[i] = y = memory[(x & MASK) >> 2] + a + b; - results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x; - - x = memory[i]; - a ^= a << 2; - a += memory[j++]; - memory[i] = y = memory[(x & MASK) >> 2] + a + b; - results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x; - - x = memory[i]; - a ^= a >>> 16; - a += memory[j++]; - memory[i] = y = memory[(x & MASK) >> 2] + a + b; - results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x; - } - } - - /** - * Initialises the ISAAC. - * @param flag Flag indicating if we should perform a second pass. - */ - public void init(boolean flag) { - int i; - int a, b, c, d, e, f, g, h; - a = b = c = d = e = f = g = h = RATIO; - for (i = 0; i < 4; ++i) { - a ^= b << 11; - d += a; - b += c; - b ^= c >>> 2; - e += b; - c += d; - c ^= d << 8; - f += c; - d += e; - d ^= e >>> 16; - g += d; - e += f; - e ^= f << 10; - h += e; - f += g; - f ^= g >>> 4; - a += f; - g += h; - g ^= h << 8; - b += g; - h += a; - h ^= a >>> 9; - c += h; - a += b; - } - for (i = 0; i < SIZE; i += 8) { - if (flag) { - a += results[i]; - b += results[i + 1]; - c += results[i + 2]; - d += results[i + 3]; - e += results[i + 4]; - f += results[i + 5]; - g += results[i + 6]; - h += results[i + 7]; - } - a ^= b << 11; - d += a; - b += c; - b ^= c >>> 2; - e += b; - c += d; - c ^= d << 8; - f += c; - d += e; - d ^= e >>> 16; - g += d; - e += f; - e ^= f << 10; - h += e; - f += g; - f ^= g >>> 4; - a += f; - g += h; - g ^= h << 8; - b += g; - h += a; - h ^= a >>> 9; - c += h; - a += b; - memory[i] = a; - memory[i + 1] = b; - memory[i + 2] = c; - memory[i + 3] = d; - memory[i + 4] = e; - memory[i + 5] = f; - memory[i + 6] = g; - memory[i + 7] = h; - } - if (flag) { - for (i = 0; i < SIZE; i += 8) { - a += memory[i]; - b += memory[i + 1]; - c += memory[i + 2]; - d += memory[i + 3]; - e += memory[i + 4]; - f += memory[i + 5]; - g += memory[i + 6]; - h += memory[i + 7]; - a ^= b << 11; - d += a; - b += c; - b ^= c >>> 2; - e += b; - c += d; - c ^= d << 8; - f += c; - d += e; - d ^= e >>> 16; - g += d; - e += f; - e ^= f << 10; - h += e; - f += g; - f ^= g >>> 4; - a += f; - g += h; - g ^= h << 8; - b += g; - h += a; - h ^= a >>> 9; - c += h; - a += b; - memory[i] = a; - memory[i + 1] = b; - memory[i + 2] = c; - memory[i + 3] = d; - memory[i + 4] = e; - memory[i + 5] = f; - memory[i + 6] = g; - memory[i + 7] = h; - } - } - isaac(); - count = SIZE; - } - -} \ No newline at end of file diff --git a/Server/src/main/core/cache/crypto/ISAACCipher.kt b/Server/src/main/core/cache/crypto/ISAACCipher.kt new file mode 100644 index 000000000..d3fab467b --- /dev/null +++ b/Server/src/main/core/cache/crypto/ISAACCipher.kt @@ -0,0 +1,213 @@ +package core.cache.crypto + +/** + * An implementation of an ISAAC cipher. + * See [http://en.wikipedia.org/wiki/ISAAC_(cipher)](http://en.wikipedia.org/wiki/ISAAC_(cipher)) for more information. + * Based on the one written by Bob Jenkins, which is available at + * [http://www.burtleburtle.net/bob/java/rand/Rand.java](http://www.burtleburtle.net/bob/java/rand/Rand.java). + */ +class ISAACCipher(seed: IntArray) { + companion object { + /** Golden ratio in 32 bit unsigned int. */ + const val RATIO = -0x61c88647 + /** The base 2 log of the size of the results and memory arrays. */ + const val SIZE_LOG = 8 + /** The size of the results and memory arrays. */ + const val SIZE = 1 shl SIZE_LOG + /** For pseudorandom lookup. */ + const val MASK = SIZE - 1 shl 2 + } + /** The count through the results. */ + private var count = 0 + /** The results. */ + private val results = IntArray(SIZE) + /** The internal memory state. */ + private val memory = IntArray(SIZE) + /** The accumulator. */ + private var a = 0 + /** The last result. */ + private var b = 0 + /** The counter. */ + private var c = 0 + + /** + * Creates the ISAAC cipher. + * @param seed The seed. + */ + init { + for (i in seed.indices) { + results[i] = seed[i] + } + init(true) + } + + val nextValue: Int + /** + * Gets the next value. + * @return The next value. + */ + get() { + if (count-- == 0) { + isaac() + count = SIZE - 1 + } + return 0 //results[count]; + } + + /** + * Generates 256 results. + */ + fun isaac() { + var i: Int + var j: Int + var x: Int + var y: Int + b += ++c + i = 0 + j = SIZE / 2 + while (i < SIZE / 2) { + x = memory[i] + a = a xor (a shl 13) + a += memory[j++] + y = memory[x and MASK shr 2] + a + b + memory[i] = y + b = memory[y shr SIZE_LOG and MASK shr 2] + x + results[i++] = b + x = memory[i] + a = a xor (a ushr 6) + a += memory[j++] + y = memory[x and MASK shr 2] + a + b + memory[i] = y + b = memory[y shr SIZE_LOG and MASK shr 2] + x + results[i++] = b + x = memory[i] + a = a xor (a shl 2) + a += memory[j++] + y = memory[x and MASK shr 2] + a + b + memory[i] = y + b = memory[y shr SIZE_LOG and MASK shr 2] + x + results[i++] = b + x = memory[i] + a = a xor (a ushr 16) + a += memory[j++] + y = memory[x and MASK shr 2] + a + b + memory[i] = y + b = memory[y shr SIZE_LOG and MASK shr 2] + x + results[i++] = b + } + j = 0 + while (j < SIZE / 2) { + x = memory[i] + a = a xor (a shl 13) + a += memory[j++] + y = memory[x and MASK shr 2] + a + b + memory[i] = y + b = memory[y shr SIZE_LOG and MASK shr 2] + x + results[i++] = b + x = memory[i] + a = a xor (a ushr 6) + a += memory[j++] + y = memory[x and MASK shr 2] + a + b + memory[i] = y + b = memory[y shr SIZE_LOG and MASK shr 2] + x + results[i++] = b + x = memory[i] + a = a xor (a shl 2) + a += memory[j++] + y = memory[x and MASK shr 2] + a + b + memory[i] = y + b = memory[y shr SIZE_LOG and MASK shr 2] + x + results[i++] = b + x = memory[i] + a = a xor (a ushr 16) + a += memory[j++] + y = memory[x and MASK shr 2] + a + b + memory[i] = y + b = memory[y shr SIZE_LOG and MASK shr 2] + x + results[i++] = b + } + } + + /** + * Initialises the ISAAC. + * @param flag Flag indicating if we should perform a second pass. + */ + fun init(flag: Boolean) { + var a = RATIO + var b = a; var c = b; var d = c; var e = d; var f = e; var g = f; var h = g + var i = 0 + while (i < 4) { + a = a xor (b shl 11); d += a; b += c + b = b xor (c ushr 2); e += b; c += d + c = c xor (d shl 8); f += c; d += e + d = d xor (e ushr 16); g += d; e += f + e = e xor (f shl 10); h += e; f += g + f = f xor (g ushr 4); a += f; g += h + g = g xor (h shl 8); b += g; h += a + h = h xor (a ushr 9); c += h; a += b + ++i + } + i = 0 + while (i < SIZE) { + if (flag) { + a += results[i] + b += results[i + 1] + c += results[i + 2] + d += results[i + 3] + e += results[i + 4] + f += results[i + 5] + g += results[i + 6] + h += results[i + 7] + } + a = a xor (b shl 11); d += a; b += c + b = b xor (c ushr 2); e += b; c += d + c = c xor (d shl 8); f += c; d += e + d = d xor (e ushr 16); g += d; e += f + e = e xor (f shl 10); h += e; f += g + f = f xor (g ushr 4); a += f; g += h + g = g xor (h shl 8); b += g; h += a + h = h xor (a ushr 9); c += h; a += b + memory[i] = a + memory[i + 1] = b + memory[i + 2] = c + memory[i + 3] = d + memory[i + 4] = e + memory[i + 5] = f + memory[i + 6] = g + memory[i + 7] = h + i += 8 + } + if (flag) { + i = 0 + while (i < SIZE) { + a += memory[i] + b += memory[i + 1] + c += memory[i + 2] + d += memory[i + 3] + e += memory[i + 4] + f += memory[i + 5] + g += memory[i + 6] + h += memory[i + 7] + a = a xor (b shl 11); d += a; b += c + b = b xor (c ushr 2); e += b; c += d + c = c xor (d shl 8); f += c; d += e + d = d xor (e ushr 16); g += d; e += f + e = e xor (f shl 10); h += e; f += g + f = f xor (g ushr 4); a += f; g += h + g = g xor (h shl 8); b += g; h += a + h = h xor (a ushr 9); c += h; a += b + memory[i] = a + memory[i + 1] = b + memory[i + 2] = c + memory[i + 3] = d + memory[i + 4] = e + memory[i + 5] = f + memory[i + 6] = g + memory[i + 7] = h + i += 8 + } + } + isaac() + count = SIZE + } +} \ No newline at end of file diff --git a/Server/src/main/core/cache/crypto/ISAACPair.java b/Server/src/main/core/cache/crypto/ISAACPair.java deleted file mode 100644 index 83c4654b9..000000000 --- a/Server/src/main/core/cache/crypto/ISAACPair.java +++ /dev/null @@ -1,45 +0,0 @@ -package core.cache.crypto; - -/** - * Represents a ISAAC key pair, for both input and output. - * @author `Discardedx2 - */ -public final class ISAACPair { - - /** - * The input cipher. - */ - private ISAACCipher input; - - /** - * The output cipher. - */ - private ISAACCipher output; - - /** - * Constructs a new {@code ISAACPair} {@code Object}. - * @param input The input cipher. - * @param output The output cipher. - */ - public ISAACPair(ISAACCipher input, ISAACCipher output) { - this.input = input; - this.output = output; - } - - /** - * Gets the input cipher. - * @return The input cipher. - */ - public ISAACCipher getInput() { - return input; - } - - /** - * Gets the output cipher. - * @return The output cipher. - */ - public ISAACCipher getOutput() { - return output; - } - -} diff --git a/Server/src/main/core/cache/crypto/ISAACPair.kt b/Server/src/main/core/cache/crypto/ISAACPair.kt new file mode 100644 index 000000000..9056c7a9d --- /dev/null +++ b/Server/src/main/core/cache/crypto/ISAACPair.kt @@ -0,0 +1,9 @@ +package core.cache.crypto + +/** + * Represents a ISAAC key pair, for both input and output. + */ +class ISAACPair( + val input: ISAACCipher, + val output: ISAACCipher +) diff --git a/Server/src/main/core/cache/crypto/XTEACryption.java b/Server/src/main/core/cache/crypto/XTEACryption.java deleted file mode 100644 index 7ed799e58..000000000 --- a/Server/src/main/core/cache/crypto/XTEACryption.java +++ /dev/null @@ -1,124 +0,0 @@ -package core.cache.crypto; - -import java.nio.ByteBuffer; - -/** - * Holds XTEA cryption methods. - * @author ? - * @author Emperor - */ -public final class XTEACryption { - - /** - * The delta value - */ - private static final int DELTA = -1640531527; - - /** - * The sum. - */ - private static final int SUM = -957401312; - - /** - * The amount of "cryption cycles". - */ - private static final int NUM_ROUNDS = 32; - - /** - * Constructs a new {@code XTEACryption}. - */ - private XTEACryption() { - /* - * empty. - */ - } - - /** - * Decrypts the contents of the buffer. - * @param keys The cryption keys. - * @param buffer The buffer. - */ - public static ByteBuffer decrypt(int[] keys, ByteBuffer buffer) { - return decrypt(keys, buffer, buffer.position(), buffer.limit()); - } - - /** - * Decrypts the buffer data. - * @param keys The keys. - * @param buffer The buffer to decrypt. - * @param offset The offset of the data to decrypt. - * @param length The length. - * @return The decrypted data. - */ - public static ByteBuffer decrypt(int[] keys, ByteBuffer buffer, int offset, int length) { - int numBlocks = (length - offset) / 8; - int[] block = new int[2]; - for (int i = 0; i < numBlocks; i++) { - int index = i * 8 + offset; - block[0] = buffer.getInt(index); - block[1] = buffer.getInt(index + 4); - decipher(keys, block); - buffer.putInt(index, block[0]); - buffer.putInt(index + 4, block[1]); - } - return buffer; - } - - /** - * Deciphers the values. - * @param keys The cryption key. - * @param block The values to decipher. - */ - private static void decipher(int[] keys, int[] block) { - long sum = SUM; - for (int i = 0; i < NUM_ROUNDS; i++) { - block[1] -= (keys[(int) ((sum & 0x1933) >>> 11)] + sum ^ block[0] + (block[0] << 4 ^ block[0] >>> 5)); - sum -= DELTA; - block[0] -= ((block[1] << 4 ^ block[1] >>> 5) + block[1] ^ keys[(int) (sum & 0x3)] + sum); - } - } - - /** - * Encrypts the contents of the byte buffer. - * @param keys The cryption keys. - * @param buffer The buffer to encrypt. - */ - public static void encrypt(int[] keys, ByteBuffer buffer) { - encrypt(keys, buffer, buffer.position(), buffer.limit()); - } - - /** - * Encrypts the buffer data. - * @param keys The keys. - * @param buffer The buffer to encrypt. - * @param offset The offset of the data to encrypt. - * @param length The length. - * @return The encrypted data. - */ - public static void encrypt(int[] keys, ByteBuffer buffer, int offset, int length) { - int numBlocks = (length - offset) / 8; - int[] block = new int[2]; - for (int i = 0; i < numBlocks; i++) { - int index = i * 8 + offset; - block[0] = buffer.getInt(index); - block[1] = buffer.getInt(index + 4); - encipher(keys, block); - buffer.putInt(index, block[0]); - buffer.putInt(index + 4, block[1]); - } - } - - /** - * Enciphers the values of the block. - * @param keys The cryption keys. - * @param block The block to encipher. - */ - private static void encipher(int[] keys, int[] block) { - long sum = 0; - for (int i = 0; i < NUM_ROUNDS; i++) { - block[0] += ((block[1] << 4 ^ block[1] >>> 5) + block[1] ^ keys[(int) (sum & 0x3)] + sum); - sum += DELTA; - block[1] += (keys[(int) ((sum & 0x1933) >>> 11)] + sum ^ block[0] + (block[0] << 4 ^ block[0] >>> 5)); - } - } -} \ No newline at end of file diff --git a/Server/src/main/core/cache/crypto/XTEACryption.kt b/Server/src/main/core/cache/crypto/XTEACryption.kt new file mode 100644 index 000000000..f87477008 --- /dev/null +++ b/Server/src/main/core/cache/crypto/XTEACryption.kt @@ -0,0 +1,97 @@ +package core.cache.crypto + +import java.nio.ByteBuffer + +/** Holds XTEA(eXtended Tiny Encryption Algorithm) encryption/decryption methods. Usually used for RS Map decryption. */ +class XTEACryption { + companion object { + // Purely Static Class + // XTEA consts https://scispace.com/pdf/xtea-cryptography-implementation-in-android-chatting-app-3pg6ownewx.pdf + /** Fibonacci hashing. Math.pow(2,32) * Math.sqrt(5)-1)/2 => 32 bits(int) multiply by reciprocal of golden ratio. */ + private const val DELTA = -1640531527 // Formula cast to unsigned int. + /** DELTA << 5. Essentially multiply DELTA by NUM_ROUNDS or number of rounds. */ + private const val SUM = -957401312 // 0xC6EF3720 + /** The amount of "cryption cycles". */ + private const val NUM_ROUNDS = 32 + /** Constant to manipulate the key index in decipher/encrypt. This was a magic number randomly selected by RS. */ + private const val KEY_SCRAMBLE = 0x1933 + + /** + * Decrypts the buffer data. + * @param keys The keys. + * @param buffer The buffer to decrypt. + * @param offset The offset of the data to decrypt. + * @param length The length. + * @return The decrypted data. + */ + fun decrypt(keys: IntArray, buffer: ByteBuffer, offset: Int, length: Int): ByteBuffer { + val numBlocks = (length - offset) / 8 + val block = IntArray(2) + for (i in 0 until numBlocks) { + val index = i * 8 + offset + block[0] = buffer.getInt(index) + block[1] = buffer.getInt(index + 4) + decipher(keys, block) + buffer.putInt(index, block[0]) + buffer.putInt(index + 4, block[1]) + } + return buffer + } + + /** + * Deciphers the values of the block using the Tiny Encryption Algorithm (TEA). + * This algorithm relies on a Feistel network, using bitwise operations and + * modular subtraction to remove confusion(block[0] line) and diffusion(block[1] line). + * + * @param keys 128-bit key (4x32-bit int). + * @param block 64-bit data block (2x32-bit int) to be decrypted. + */ + private fun decipher(keys: IntArray, block: IntArray) { + var sum = + SUM.toLong() // Running decreasing sum to ensure different round constants - should become 0 at the end. + for (i in 0 until NUM_ROUNDS) { + block[1] -= (keys[(sum and KEY_SCRAMBLE.toLong() ushr 11).toInt()] + sum xor (block[0] + (block[0] shl 4 xor (block[0] ushr 5))).toLong()).toInt() + sum -= DELTA.toLong() + block[0] -= (((block[1] shl 4 xor (block[1] ushr 5)) + block[1]).toLong() xor keys[(sum and 0x3L).toInt()] + sum).toInt() + } + } + /** === Encryption functions below are not used unless you are modifying the cache. === */ + /** + * Encrypts the buffer data. + * @param keys The keys. + * @param buffer The buffer to encrypt. + * @param offset The offset of the data to encrypt. + * @param length The length. + * @return The encrypted data. + */ + fun encrypt(keys: IntArray, buffer: ByteBuffer, offset: Int, length: Int) { + val numBlocks = (length - offset) / 8 + val block = IntArray(2) + for (i in 0 until numBlocks) { + val index = i * 8 + offset + block[0] = buffer.getInt(index) + block[1] = buffer.getInt(index + 4) + encipher(keys, block) + buffer.putInt(index, block[0]) + buffer.putInt(index + 4, block[1]) + } + } + + /** + * Enciphers the values of the block using the Tiny Encryption Algorithm (TEA). + * This algorithm relies on a Feistel network, using bitwise operations and + * modular addition to provide confusion(block[0] line) and diffusion(block[1] line). + * + * @param keys 128-bit key (4x32-bit int). + * @param block 64-bit data block (2x32-bit int) to be encrypted. + */ + private fun encipher(keys: IntArray, block: IntArray) { + var sum: Long = 0 // Running sum to ensure different round constants - should match SUM at the end. + for (i in 0 until NUM_ROUNDS) { + block[0] += (((block[1] shl 4 xor (block[1] ushr 5)) + block[1]).toLong() xor keys[(sum and 0x3L).toInt()] + sum).toInt() + sum += DELTA.toLong() + block[1] += (keys[(sum and KEY_SCRAMBLE.toLong() ushr 11).toInt()] + sum xor (block[0] + (block[0] shl 4 xor (block[0] ushr 5))).toLong()).toInt() + } + } + } +} \ No newline at end of file diff --git a/Server/src/main/core/cache/misc/Container.java b/Server/src/main/core/cache/misc/Container.java deleted file mode 100644 index 9760845ff..000000000 --- a/Server/src/main/core/cache/misc/Container.java +++ /dev/null @@ -1,109 +0,0 @@ -package core.cache.misc; - -/** - * A container. - * @author Dragonkk - */ -public class Container { - - /** - * The version. - */ - private int version; - - /** - * The CRC. - */ - private int crc; - - /** - * The name hash. - */ - private int nameHash; - - /** - * If updated. - */ - private boolean updated; - - /** - * Construct a new container. - */ - public Container() { - nameHash = -1; - version = -1; - crc = -1; - } - - /** - * Set the version. - * @param version - */ - public void setVersion(int version) { - this.version = version; - } - - /** - * Update the version. - */ - public void updateVersion() { - version++; - updated = true; - } - - /** - * Get the version. - * @return The version. - */ - public int getVersion() { - return version; - } - - /** - * Get the next version. - * @return The next version. - */ - public int getNextVersion() { - return updated ? version : version + 1; - } - - /** - * Set the CRC. - * @param crc The cRC. - */ - public void setCrc(int crc) { - this.crc = crc; - } - - /** - * Get the CRC. - * @return The CRC. - */ - public int getCrc() { - return crc; - } - - /** - * Set the name hash. - * @param nameHash The name hash. - */ - public void setNameHash(int nameHash) { - this.nameHash = nameHash; - } - - /** - * Get the name hash. - * @return The name hash. - */ - public int getNameHash() { - return nameHash; - } - - /** - * If is updated. - * @return If is updated. - */ - public boolean isUpdated() { - return updated; - } -} diff --git a/Server/src/main/core/cache/misc/Container.kt b/Server/src/main/core/cache/misc/Container.kt new file mode 100644 index 000000000..3e1b481d6 --- /dev/null +++ b/Server/src/main/core/cache/misc/Container.kt @@ -0,0 +1,7 @@ +package core.cache.misc + +data class Container( + var version: Int = -1, + var crc: Int = -1, + var nameHash: Int = -1 +) \ No newline at end of file diff --git a/Server/src/main/core/cache/misc/ContainersInformation.java b/Server/src/main/core/cache/misc/ContainersInformation.java deleted file mode 100644 index f786c1d2f..000000000 --- a/Server/src/main/core/cache/misc/ContainersInformation.java +++ /dev/null @@ -1,228 +0,0 @@ -package core.cache.misc; - -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.zip.CRC32; - -import core.cache.bzip2.BZip2Decompressor; -import core.cache.gzip.GZipDecompressor; - -/** - * A class holding the containers information. - * @author Dragonkk - */ -public final class ContainersInformation { - - /** - * The information container. - */ - private Container informationContainer; - - /** - * The protocol. - */ - private int protocol; - - /** - * The revision. - */ - private int revision; - - /** - * The container indexes. - */ - private int[] containersIndexes; - - /** - * The containers. - */ - private FilesContainer[] containers; - - /** - * If files have to be named. - */ - private boolean filesNamed; - - /** - * If it has to be whirpool. - */ - private boolean whirpool; - - /** - * The data. - */ - private final byte[] data; - - /** - * Construct a new containers information. - * @param informationContainerPackedData The information container data - * packed. - */ - public ContainersInformation(byte[] informationContainerPackedData) { - this.data = Arrays.copyOf(informationContainerPackedData, informationContainerPackedData.length); - informationContainer = new Container(); - informationContainer.setVersion((informationContainerPackedData[informationContainerPackedData.length - 2] << 8 & 0xff00) + (informationContainerPackedData[-1 + informationContainerPackedData.length] & 0xff)); - CRC32 crc32 = new CRC32(); - crc32.update(informationContainerPackedData); - informationContainer.setCrc((int) crc32.getValue()); - decodeContainersInformation(unpackCacheContainer(informationContainerPackedData)); - } - - /** - * Unpacks a container. - * @param packedData The packed container data. - * @return The unpacked data. - */ - public static final byte[] unpackCacheContainer(byte[] packedData) { - ByteBuffer buffer = ByteBuffer.wrap(packedData); - int compression = buffer.get() & 0xFF; - int containerSize = buffer.getInt(); - if (containerSize < 0 || containerSize > 5000000) { - return null; - // throw new RuntimeException(); - } - if (compression == 0) { - byte unpacked[] = new byte[containerSize]; - buffer.get(unpacked, 0, containerSize); - return unpacked; - } - int decompressedSize = buffer.getInt(); - if (decompressedSize < 0 || decompressedSize > 20000000) { - return null; - // throw new RuntimeException(); - } - byte decompressedData[] = new byte[decompressedSize]; - if (compression == 1) { - BZip2Decompressor.decompress(decompressedData, packedData, containerSize, 9); - } else { - GZipDecompressor.decompress(buffer, decompressedData); - } - return decompressedData; - } - - /** - * Get the container indexes. - * @return The container indexes. - */ - public int[] getContainersIndexes() { - return containersIndexes; - } - - /** - * Get the containers. - * @return The containers. - */ - public FilesContainer[] getContainers() { - return containers; - } - - /** - * Get the information container. - * @return The information container. - */ - public Container getInformationContainer() { - return informationContainer; - } - - /** - * Get the revision. - * @return The revision. - */ - public int getRevision() { - return revision; - } - - /** - * Decode the containers information. - * @param data The data. - */ - public void decodeContainersInformation(byte[] data) { - ByteBuffer buffer = ByteBuffer.wrap(data); - protocol = buffer.get() & 0xFF; - if (protocol != 5 && protocol != 6) { - throw new RuntimeException(); - } - revision = protocol < 6 ? 0 : buffer.getInt(); - int nameHash = buffer.get() & 0xFF; - filesNamed = (0x1 & nameHash) != 0; - whirpool = (0x2 & nameHash) != 0; - containersIndexes = new int[buffer.getShort() & 0xFFFF]; - int lastIndex = -1; - for (int index = 0; index < containersIndexes.length; index++) { - containersIndexes[index] = (buffer.getShort() & 0xFFFF) + (index == 0 ? 0 : containersIndexes[index - 1]); - if (containersIndexes[index] > lastIndex) { - lastIndex = containersIndexes[index]; - } - } - containers = new FilesContainer[lastIndex + 1]; - for (int index = 0; index < containersIndexes.length; index++) { - containers[containersIndexes[index]] = new FilesContainer(); - } - if (filesNamed) { - for (int index = 0; index < containersIndexes.length; index++) { - containers[containersIndexes[index]].setNameHash(buffer.getInt()); - } - } - byte[][] filesHashes = null; - if (whirpool) { - filesHashes = new byte[containers.length][]; - for (int index = 0; index < containersIndexes.length; index++) { - filesHashes[containersIndexes[index]] = new byte[64]; - buffer.get(filesHashes[containersIndexes[index]], 0, 64); - } - } - for (int index = 0; index < containersIndexes.length; index++) { - containers[containersIndexes[index]].setCrc(buffer.getInt()); - } - for (int index = 0; index < containersIndexes.length; index++) { - containers[containersIndexes[index]].setVersion(buffer.getInt()); - } - for (int index = 0; index < containersIndexes.length; index++) { - containers[containersIndexes[index]].setFilesIndexes(new int[buffer.getShort() & 0xFFFF]); - } - for (int index = 0; index < containersIndexes.length; index++) { - int lastFileIndex = -1; - for (int fileIndex = 0; fileIndex < containers[containersIndexes[index]].getFilesIndexes().length; fileIndex++) { - containers[containersIndexes[index]].getFilesIndexes()[fileIndex] = (buffer.getShort() & 0xFFFF) + (fileIndex == 0 ? 0 : containers[containersIndexes[index]].getFilesIndexes()[fileIndex - 1]); - if (containers[containersIndexes[index]].getFilesIndexes()[fileIndex] > lastFileIndex) { - lastFileIndex = containers[containersIndexes[index]].getFilesIndexes()[fileIndex]; - } - } - containers[containersIndexes[index]].setFiles(new Container[lastFileIndex + 1]); - for (int fileIndex = 0; fileIndex < containers[containersIndexes[index]].getFilesIndexes().length; fileIndex++) { - containers[containersIndexes[index]].getFiles()[containers[containersIndexes[index]].getFilesIndexes()[fileIndex]] = new Container(); - } - } - if (whirpool) { - for (int index = 0; index < containersIndexes.length; index++) { - for (int fileIndex = 0; fileIndex < containers[containersIndexes[index]].getFilesIndexes().length; fileIndex++) { - containers[containersIndexes[index]].getFiles()[containers[containersIndexes[index]].getFilesIndexes()[fileIndex]].setVersion(filesHashes[containersIndexes[index]][containers[containersIndexes[index]].getFilesIndexes()[fileIndex]]); - } - } - } - if (filesNamed) { - for (int index = 0; index < containersIndexes.length; index++) { - for (int fileIndex = 0; fileIndex < containers[containersIndexes[index]].getFilesIndexes().length; fileIndex++) { - containers[containersIndexes[index]].getFiles()[containers[containersIndexes[index]].getFilesIndexes()[fileIndex]].setNameHash(buffer.getInt()); - } - } - } - } - - /** - * If is whirpool. - * @return If is whirpool {@code true}. - */ - public boolean isWhirpool() { - return whirpool; - } - - /** - * Gets the data. - * @return The data. - */ - public byte[] getData() { - return data; - } - -} diff --git a/Server/src/main/core/cache/misc/ContainersInformation.kt b/Server/src/main/core/cache/misc/ContainersInformation.kt new file mode 100644 index 000000000..831eb954b --- /dev/null +++ b/Server/src/main/core/cache/misc/ContainersInformation.kt @@ -0,0 +1,145 @@ +package core.cache.misc + +import core.cache.bzip2.BZip2Decompressor +import core.cache.gzip.GZipDecompressor +import java.nio.ByteBuffer +import java.util.* +import java.util.zip.CRC32 + +class ContainersInformation(informationContainerPackedData: ByteArray) { + @JvmField + val informationContainer: Container + private var protocol = 0 + var revision = 0 + var containersIndexes: IntArray = intArrayOf() + var containers: Array = arrayOf() + private var filesNamed = false // If files has to be named + private var whirpool = false // Flag for whirpool + val data: ByteArray + + init { + data = Arrays.copyOf(informationContainerPackedData, informationContainerPackedData.size) + informationContainer = Container() + informationContainer.version = + (informationContainerPackedData[informationContainerPackedData.size - 2].toInt() shl 8 and 0xff00) + (informationContainerPackedData[-1 + informationContainerPackedData.size].toInt() and 0xff) + val crc32 = CRC32() + crc32.update(informationContainerPackedData) + informationContainer.crc = crc32.value.toInt() + decodeContainersInformation(unpackCacheContainer(informationContainerPackedData)) + } + + fun decodeContainersInformation(data: ByteArray?) { + val buffer = ByteBuffer.wrap(data) + protocol = buffer.get().toInt() and 0xFF + if (protocol != 5 && protocol != 6) { + throw RuntimeException() + } + revision = if (protocol < 6) 0 else buffer.getInt() + val nameHash = buffer.get().toInt() and 0xFF + filesNamed = 0x1 and nameHash != 0 + whirpool = 0x2 and nameHash != 0 + containersIndexes = IntArray(buffer.getShort().toInt() and 0xFFFF) + var lastIndex = -1 + for (index in containersIndexes.indices) { + val containerIndex = + (buffer.getShort().toInt() and 0xFFFF) + if (index == 0) 0 else containersIndexes[index - 1] + containersIndexes[index] = containerIndex + if (containerIndex > lastIndex) { + lastIndex = containerIndex + } + } + containers = arrayOfNulls(lastIndex + 1) + for (containerIdx in containersIndexes) { + containers[containerIdx] = FilesContainer() + } + if (filesNamed) { + for (containerIdx in containersIndexes) { + containers[containerIdx]!!.nameHash = buffer.getInt() + } + } + var filesHashes: Array? = null + if (whirpool) { + filesHashes = arrayOfNulls(containers.size) + for (containerIdx in containersIndexes) { + filesHashes[containerIdx] = ByteArray(64) + buffer[filesHashes[containerIdx], 0, 64] + } + } + for (containerIdx in containersIndexes) { + containers[containerIdx]!!.crc = buffer.getInt() + } + for (containerIdx in containersIndexes) { + containers[containerIdx]!!.version = buffer.getInt() + } + for (containerIdx in containersIndexes) { + containers[containerIdx]!!.filesIndexes = IntArray(buffer.getShort().toInt() and 0xFFFF) + } + for (containerIdx in containersIndexes) { + val container = containers[containerIdx] + val filesIndexes = container!!.filesIndexes + var lastFileIndex = -1 + for (fileIndex in filesIndexes!!.indices) { + val fileIdx = + (buffer.getShort().toInt() and 0xFFFF) + if (fileIndex == 0) 0 else filesIndexes[fileIndex - 1] + filesIndexes[fileIndex] = fileIdx + if (fileIdx > lastFileIndex) { + lastFileIndex = fileIdx + } + } + val files = arrayOfNulls(lastFileIndex + 1) + container.files = files + for (fileIdx in filesIndexes) { + files[fileIdx] = Container() + } + } + if (whirpool) { + for (containerIdx in containersIndexes) { + val container = containers[containerIdx] + val containerHashes = filesHashes!![containerIdx] + val files = container!!.files + for (fileIdx in container.filesIndexes!!) { + files!![fileIdx]!!.version = containerHashes!![fileIdx].toInt() + } + } + } + if (filesNamed) { + for (containerIdx in containersIndexes) { + val container = containers[containerIdx] + val files = container!!.files + for (fileIdx in container.filesIndexes!!) { + files!![fileIdx]!!.nameHash = buffer.getInt() + } + } + } + } + + companion object { + @JvmStatic + fun unpackCacheContainer(packedData: ByteArray?): ByteArray? { + val buffer = ByteBuffer.wrap(packedData) + val compression = buffer.get().toInt() and 0xFF + val containerSize = buffer.getInt() + if (containerSize < 0 || containerSize > 5000000) { + return null + // throw new RuntimeException(); + } + if (compression == 0) { + val unpacked = ByteArray(containerSize) + buffer[unpacked, 0, containerSize] + return unpacked + } + val decompressedSize = buffer.getInt() + if (decompressedSize < 0 || decompressedSize > 20000000) { + return null + // throw new RuntimeException(); + } + val decompressedData = ByteArray(decompressedSize) + if (compression == 1) { + BZip2Decompressor.decompress(decompressedData, packedData, containerSize, 9) + } else { + GZipDecompressor.decompress(buffer, decompressedData) + } + return decompressedData + } + } +} diff --git a/Server/src/main/core/cache/misc/FilesContainer.java b/Server/src/main/core/cache/misc/FilesContainer.java deleted file mode 100644 index 5f14e448f..000000000 --- a/Server/src/main/core/cache/misc/FilesContainer.java +++ /dev/null @@ -1,57 +0,0 @@ -package core.cache.misc; - -/** - * A class holding the file containers. - * @author Dragonkk - */ -public final class FilesContainer extends Container { - - /** - * The file indexes. - */ - private int[] filesIndexes; - - /** - * The files. - */ - private Container[] files; - - /** - * Construct a new files container. - */ - public FilesContainer() { - - } - - /** - * Set the files. - * @param containers The files. - */ - public void setFiles(Container[] containers) { - this.files = containers; - } - - /** - * Get the files. - * @return The files. - */ - public Container[] getFiles() { - return files; - } - - /** - * Set the file indexes. - * @param containersIndexes The file indexes. - */ - public void setFilesIndexes(int[] containersIndexes) { - this.filesIndexes = containersIndexes; - } - - /** - * Get the file indexes. - * @return The file indexes. - */ - public int[] getFilesIndexes() { - return filesIndexes; - } -} diff --git a/Server/src/main/core/cache/misc/FilesContainer.kt b/Server/src/main/core/cache/misc/FilesContainer.kt new file mode 100644 index 000000000..192ca3389 --- /dev/null +++ b/Server/src/main/core/cache/misc/FilesContainer.kt @@ -0,0 +1,9 @@ +package core.cache.misc + +data class FilesContainer( + var version: Int = -1, + var crc: Int = -1, + var nameHash: Int = -1, + var filesIndexes: IntArray? = null, + var files: Array? = null +) \ No newline at end of file diff --git a/Server/src/main/core/cache/misc/buffer/BufferInputStream.java b/Server/src/main/core/cache/misc/buffer/BufferInputStream.java deleted file mode 100644 index a801c870d..000000000 --- a/Server/src/main/core/cache/misc/buffer/BufferInputStream.java +++ /dev/null @@ -1,39 +0,0 @@ -package core.cache.misc.buffer; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; - -/** - * Handles the reading of data from a byte buffer. - * @author Emperor - */ -public final class BufferInputStream extends InputStream { - - /** - * The buffer to write on. - */ - private final ByteBuffer buffer; - - /** - * The buffer input stream. - * @param buffer The buffer. - */ - public BufferInputStream(ByteBuffer buffer) throws IOException { - this.buffer = buffer; - } - - @Override - public int read() throws IOException { - return buffer.get(); - } - - /** - * Gets the buffer. - * @return The buffer. - */ - public ByteBuffer getBuffer() { - return buffer; - } - -} diff --git a/Server/src/main/core/cache/misc/buffer/BufferOutputStream.java b/Server/src/main/core/cache/misc/buffer/BufferOutputStream.java deleted file mode 100644 index 88ea2ac69..000000000 --- a/Server/src/main/core/cache/misc/buffer/BufferOutputStream.java +++ /dev/null @@ -1,57 +0,0 @@ -package core.cache.misc.buffer; - -import java.io.IOException; -import java.io.OutputStream; -import java.nio.ByteBuffer; - -/** - * Handles the writing of data on a byte buffer. - * @author Emperor - */ -public final class BufferOutputStream extends OutputStream { - - /** - * The buffer to write on. - */ - private final ByteBuffer buffer; - - /** - * Constructs a new {@code BufferOutputStream} {@code Object}. - * @param buffer The buffer to write on. - * @throws IOException When an I/O exception occurs. - * @throws SecurityException If a security manager exists and its - * checkPermission method denies enabling subclassing. - */ - public BufferOutputStream(ByteBuffer buffer) throws IOException, SecurityException { - super(); - this.buffer = buffer; - } - - @Override - public void write(int b) throws IOException { - buffer.put((byte) b); - } - - @Override - public void flush() { - /* - * empty. - */ - } - - @Override - public void close() { - /* - * empty. - */ - } - - /** - * Gets the buffer. - * @return The buffer. - */ - public ByteBuffer getBuffer() { - return buffer; - } - -} \ No newline at end of file diff --git a/Server/src/main/core/cache/misc/buffer/ByteBufferUtils.java b/Server/src/main/core/cache/misc/buffer/ByteBufferUtils.java deleted file mode 100644 index fb04ae272..000000000 --- a/Server/src/main/core/cache/misc/buffer/ByteBufferUtils.java +++ /dev/null @@ -1,182 +0,0 @@ -package core.cache.misc.buffer; - -import java.io.ObjectInputStream; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; - -/** - * Holds utility methods for reading/writing a byte buffer. - * @author Emperor - */ -public final class ByteBufferUtils { - - /** - * Gets a string from the byte buffer. - * @param buffer The byte buffer. - * @return The string. - */ - public static String getString(ByteBuffer buffer) { - StringBuilder sb = new StringBuilder(); - byte b; - while ((b = buffer.get()) != 0) { - sb.append((char) b); - } - return sb.toString(); - } - - /** - * Puts a string on the byte buffer. - * @param s The string to put. - * @param buffer The byte buffer. - */ - public static void putString(String s, ByteBuffer buffer) { - buffer.put(s.getBytes(StandardCharsets.UTF_8)).put((byte) 0); - } - - /** - * Gets a string from the byte buffer. - * @param s The string. - * @param buffer The byte buffer. - * @return The string. - */ - public static ByteBuffer putGJ2String(String s, ByteBuffer buffer) { - byte[] packed = new byte[256]; - int length = packGJString2(0, packed, s); - return buffer.put((byte) 0).put(packed, 0, length).put((byte) 0); - } - - /** - * Decodes the XTEA encryption. - * @param keys The keys. - * @param start The start index. - * @param end The end index. - * @param buffer The byte buffer. - */ - public static void decodeXTEA(int[] keys, int start, int end, ByteBuffer buffer) { - int l = buffer.position(); - buffer.position(start); - int length = (end - start) / 8; - for (int i = 0; i < length; i++) { - int firstInt = buffer.getInt(); - int secondInt = buffer.getInt(); - int sum = 0xc6ef3720; - int delta = 0x9e3779b9; - for (int j = 32; j-- > 0;) { - secondInt -= keys[(sum & 0x1c84) >>> 11] + sum ^ (firstInt >>> 5 ^ firstInt << 4) + firstInt; - sum -= delta; - firstInt -= (secondInt >>> 5 ^ secondInt << 4) + secondInt ^ keys[sum & 3] + sum; - } - buffer.position(buffer.position() - 8); - buffer.putInt(firstInt); - buffer.putInt(secondInt); - } - buffer.position(l); - } - - /** - * Converts a String to an Integer? - * @param position The position. - * @param buffer The buffer used. - * @param string The String to convert. - * @return The Integer. - */ - public static int packGJString2(int position, byte[] buffer, String string) { - int length = string.length(); - int offset = position; - for (int i = 0; length > i; i++) { - int character = string.charAt(i); - if (character > 127) { - if (character > 2047) { - buffer[offset++] = (byte) ((character | 919275) >> 12); - buffer[offset++] = (byte) (128 | ((character >> 6) & 63)); - buffer[offset++] = (byte) (128 | (character & 63)); - } else { - buffer[offset++] = (byte) ((character | 12309) >> 6); - buffer[offset++] = (byte) (128 | (character & 63)); - } - } else - buffer[offset++] = (byte) character; - } - return offset - position; - } - - /** - * Gets a tri-byte from the buffer. - * @param buffer The buffer. - * @return The value. - */ - public static int getMedium(ByteBuffer buffer) { - return ((buffer.get() & 0xFF) << 16) + ((buffer.get() & 0xFF) << 8) + (buffer.get() & 0xFF); - } - - /** - * Gets a smart from the buffer. - * @param buffer The buffer. - * @return The value. - */ - public static int getSmart(ByteBuffer buffer) { - int peek = buffer.get() & 0xFF; - if (peek <= Byte.MAX_VALUE) { - return peek; - } - return ((peek << 8) | (buffer.get() & 0xFF)) - 32768; - } - - /** - * Gets a smart from the buffer. - * @param buffer The buffer. - * @return The value. - */ - public static int getBigSmart(ByteBuffer buffer) { - int value = 0; - int current = getSmart(buffer); - while (current == 32767) { - current = getSmart(buffer); - value += 32767; - } - value += current; - return value; - } - - /* *//** - * Writes an object on the buffer. - * @param buffer The buffer to write on. - * @param o The object. - */ - /* - * public static void putObject(ByteBuffer buffer, Object o) { ByteBuffer b; - * try (ObjectOutputStream out = new ObjectOutputStream(new - * BufferOutputStream(b = ByteBuffer.allocate(99999)))) { - * out.writeObject(o); b.flip(); } catch (Throwable e) { - * e.printStackTrace(); b = (ByteBuffer) ByteBuffer.allocate(0).flip(); } - * buffer.putInt(b.remaining()); if (b.remaining() > 0) { buffer.put(b); } } - */ - - /** - * Gets an object from the byte buffer. - * @param buffer The buffer. - * @return The object. - */ - public static Object getObject(ByteBuffer buffer) { - int length = buffer.getInt(); - if (length > 0) { - byte[] bytes = new byte[length]; - buffer.get(bytes); - try (ObjectInputStream str = new ObjectInputStream(new BufferInputStream(ByteBuffer.wrap(bytes)))) { - return (Object) str.readObject(); - } catch (Throwable e) { - e.printStackTrace(); - } - } - return null; - } - - /** - * Constructs a new {@code ByteBufferUtils} {@code Object}. - */ - private ByteBufferUtils() { - /* - * empty. - */ - } -} \ No newline at end of file diff --git a/Server/src/main/core/cache/misc/buffer/ByteBufferUtils.kt b/Server/src/main/core/cache/misc/buffer/ByteBufferUtils.kt new file mode 100644 index 000000000..73d72df70 --- /dev/null +++ b/Server/src/main/core/cache/misc/buffer/ByteBufferUtils.kt @@ -0,0 +1,142 @@ +package core.cache.misc.buffer + +import java.nio.ByteBuffer +import java.nio.charset.StandardCharsets + +object ByteBufferUtils { + /** + * Gets a string from the byte buffer. + * @param buffer The byte buffer. + * @return The string. + */ + @JvmStatic + fun getString(buffer: ByteBuffer): String { + val sb = StringBuilder() + var b: Byte + while (buffer.get().also { b = it }.toInt() != 0) { + sb.append(Char(b.toUShort())) + } + return sb.toString() + } + + /** + * Puts a string on the byte buffer. + * @param s The string to put. + * @param buffer The byte buffer. + */ + @JvmStatic + fun putString(s: String, buffer: ByteBuffer) { + buffer.put(s.toByteArray(StandardCharsets.UTF_8)).put(0.toByte()) + } + + /** + * Gets a string from the byte buffer. + * @param s The string. + * @param buffer The byte buffer. + * @return The string. + */ + fun putGJ2String(s: String, buffer: ByteBuffer): ByteBuffer { + val packed = ByteArray(256) + val length = packGJString2(0, packed, s) + return buffer.put(0.toByte()).put(packed, 0, length).put(0.toByte()) + } + + /** + * Decodes the XTEA encryption. + * @param keys The keys. + * @param start The start index. + * @param end The end index. + * @param buffer The byte buffer. + */ + fun decodeXTEA(keys: IntArray, start: Int, end: Int, buffer: ByteBuffer) { + val l = buffer.position() + buffer.position(start) + val length = (end - start) / 8 + for (i in 0 until length) { + var firstInt = buffer.getInt() + var secondInt = buffer.getInt() + var sum = -0x3910c8e0 + val delta = -0x61c88647 + var j = 32 + while (j-- > 0) { + secondInt -= keys[sum and 0x1c84 ushr 11] + sum xor (firstInt ushr 5 xor (firstInt shl 4)) + firstInt + sum -= delta + firstInt -= (secondInt ushr 5 xor (secondInt shl 4)) + secondInt xor keys[sum and 3] + sum + } + buffer.position(buffer.position() - 8) + buffer.putInt(firstInt) + buffer.putInt(secondInt) + } + buffer.position(l) + } + + /** + * Converts a String to an Integer? + * @param position The position. + * @param buffer The buffer used. + * @param string The String to convert. + * @return The Integer. + */ + @JvmStatic + fun packGJString2(position: Int, buffer: ByteArray, string: String): Int { + val length = string.length + var offset = position + var i = 0 + while (length > i) { + val character = string[i].code + if (character > 127) { + if (character > 2047) { + buffer[offset++] = (character or 919275 shr 12).toByte() + buffer[offset++] = (128 or (character shr 6 and 63)).toByte() + buffer[offset++] = (128 or (character and 63)).toByte() + } else { + buffer[offset++] = (character or 12309 shr 6).toByte() + buffer[offset++] = (128 or (character and 63)).toByte() + } + } else buffer[offset++] = character.toByte() + i++ + } + return offset - position + } + + /** + * Gets a tri-byte from the buffer. + * @param buffer The buffer. + * @return The value. + */ + @JvmStatic + fun getMedium(buffer: ByteBuffer): Int { + return (buffer.get().toInt() and 0xFF shl 16) + (buffer.get().toInt() and 0xFF shl 8) + (buffer.get() + .toInt() and 0xFF) + } + + /** + * Gets a smart from the buffer. + * @param buffer The buffer. + * @return The value. + */ + @JvmStatic + fun getSmart(buffer: ByteBuffer): Int { + val peek = buffer.get().toInt() and 0xFF + return if (peek <= Byte.MAX_VALUE) { + peek + } else (peek shl 8 or (buffer.get().toInt() and 0xFF)) - 32768 + } + + /** + * Gets a smart from the buffer. + * @param buffer The buffer. + * @return The value. + */ + @JvmStatic + fun getBigSmart(buffer: ByteBuffer): Int { + var value = 0 + var current = getSmart(buffer) + while (current == 32767) { + current = getSmart(buffer) + value += 32767 + } + value += current + return value + } +} \ No newline at end of file diff --git a/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt b/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt index 53004f2b9..65ffe1369 100644 --- a/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt @@ -190,15 +190,16 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) { val dump = File("structs.txt") val writer = BufferedWriter(FileWriter(dump)) val index = Cache.getIndexes()[2] - val containers = index.information.containers[26].filesIndexes - for(fID in containers) - { - val file = index.getFileData(26, fID) - if(file != null){ - val def = Struct.parse(fID, file) - if(def.dataStore.isEmpty()) continue //no data in struct. - writer.write(def.toString()) - writer.newLine() + val containers = index.information.containers[26]!!.filesIndexes + if (containers != null) { + for(fID in containers) { + val file = index.getFileData(26, fID) + if(file != null){ + val def = Struct.parse(fID, file) + if(def.dataStore.isEmpty()) continue //no data in struct. + writer.write(def.toString()) + writer.newLine() + } } } writer.flush() @@ -214,15 +215,16 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) { for(cID in containers) { - val fileIndexes = index.information.containers[cID].filesIndexes - for(fID in fileIndexes) - { - val file = index.getFileData(cID, fID) - if(file != null){ - val def = DataMap.parse((cID shl 8) or fID, file) - if(def.keyType == '?') continue //Empty definition - only a 0 present in the cachefile data. - writer.write(def.toString()) - writer.newLine() + val fileIndexes = index.information.containers[cID]!!.filesIndexes + if (fileIndexes != null) { + for(fID in fileIndexes) { + val file = index.getFileData(cID, fID) + if(file != null){ + val def = DataMap.parse((cID shl 8) or fID, file) + if(def.keyType == '?') continue //Empty definition - only a 0 present in the cachefile data. + writer.write(def.toString()) + writer.newLine() + } } } }