diff --git a/Server/pom.xml b/Server/pom.xml index 188230d74..dd64602bf 100644 --- a/Server/pom.xml +++ b/Server/pom.xml @@ -90,6 +90,11 @@ 2.9.0 compile + + com.displee + rs-cache-library + 6.9-RC2 + diff --git a/Server/src/main/java/core/cache/Cache.java b/Server/src/main/java/core/cache/Cache.java deleted file mode 100644 index d4733986d..000000000 --- a/Server/src/main/java/core/cache/Cache.java +++ /dev/null @@ -1,238 +0,0 @@ -package core.cache; - -import java.io.File; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; - -import rs09.ServerConstants; -import core.cache.def.impl.AnimationDefinition; -import core.cache.def.impl.GraphicDefinition; -import core.cache.def.impl.ItemDefinition; -import core.cache.def.impl.NPCDefinition; -import core.cache.def.impl.SceneryDefinition; -import rs09.game.system.SystemLogger; - -/** - * A cache reader. - * - * @author Emperor - * @author Dragonkk - */ -public final class Cache { - - /** - * The cache file manager. - */ - private static CacheFileManager[] cacheFileManagers; - - /** - * The container cache file informer. - */ - private static CacheFile referenceFile; - - /** - * Construct a new instance. - */ - private Cache(String location) { - try { - init(location); - } catch (Throwable e) { - e.printStackTrace(); - } - } - - /** - * Initialize the cache reader. - * - * @param path The cache path.x - * @throws Throwable When an exception occurs. - */ - public static void init(String path) throws Throwable { - SystemLogger.logInfo(Cache.class, "Initializing cache..."); - byte[] cacheFileBuffer = new byte[520]; - RandomAccessFile containersInformFile = new RandomAccessFile(path + File.separator + "main_file_cache.idx255", "r"); - RandomAccessFile dataFile = new RandomAccessFile(path + File.separator + "main_file_cache.dat2", "r"); - referenceFile = new CacheFile(255, containersInformFile, dataFile, 500000, cacheFileBuffer); - int length = (int) (containersInformFile.length() / 6); - cacheFileManagers = new CacheFileManager[length]; - for (int i = 0; i < length; i++) { - File f = new File(path + File.separator + "main_file_cache.idx" + i); - if (f.exists() && f.length() > 0) { - CacheFile cacheFile = new CacheFile(i, new RandomAccessFile(f, "r"), dataFile, 1000000, cacheFileBuffer); - cacheFileManagers[i] = new CacheFileManager(cacheFile, true); - if (cacheFileManagers[i].getInformation() == null) { - SystemLogger.logErr(Cache.class, "Error loading cache index " + i + ": no information."); - cacheFileManagers[i] = null; - } - } - } - ItemDefinition.parse(); - SceneryDefinition.parse(); - } - - /** - * Initializes the cache. - */ - public static void init() { - try { - init(ServerConstants.CACHE_PATH); - } catch (Throwable e) { - e.printStackTrace(); - } - } - - /** - * Gets the archive buffer for the grab requests. - * - * @param index The index id. - * @param archive The archive id. - * @param priority The priority. - * @param encryptionValue The current encryption value. - * @return The byte buffer. - */ - public static ByteBuffer getArchiveData(int index, int archive, boolean priority, int encryptionValue) { - byte[] data = index == 255 ? referenceFile.getContainerData(archive) : cacheFileManagers[index].getCacheFile().getContainerData(archive); - if (data == null || data.length < 1) { - SystemLogger.logErr(Cache.class, "Invalid JS-5 request - " + index + ", " + archive + ", " + priority + ", " + encryptionValue + "!"); - return null; - } - int compression = data[0] & 0xff; - int length = ((data[1] & 0xff) << 24) + ((data[2] & 0xff) << 16) + ((data[3] & 0xff) << 8) + (data[4] & 0xff); - int settings = compression; - if (!priority) { - settings |= 0x80; - } - int realLength = compression != 0 ? length + 4 : length; - - // TODO There are two archives that lack two bytes at the end (The version, most likely). This causes the client CRC to be miscalculated. To combat this, we simply send two more bytes if the length seems to be off. - realLength += (index != 255 && compression != 0 && data.length - length == 9) ? 2 : 0; - ByteBuffer buffer = ByteBuffer.allocate((realLength + 5) + (realLength / 512) + 10); - buffer.put((byte) index); - buffer.putShort((short) archive); - buffer.put((byte) settings); - buffer.putInt(length); - for (int i = 5; i < realLength + 5; i++) { - if (buffer.position() % 512 == 0) { - buffer.put((byte) 255); - } - if (data.length > i) - buffer.put(data[i]); - else - buffer.put((byte) 0); - } - if (encryptionValue != 0) { - for (int i = 0; i < buffer.position(); i++) { - buffer.put(i, (byte) (buffer.get(i) ^ encryptionValue)); - } - } - buffer.flip(); - return buffer; - } - - /** - * Generate the reference data for the cache files. - * - * @return The reference data byte array. - */ - public static final byte[] generateReferenceData() { - ByteBuffer buffer = ByteBuffer.allocate(cacheFileManagers.length * 8); - for (int index = 0; index < cacheFileManagers.length; index++) { - if (cacheFileManagers[index] == null) { - buffer.putInt(index == 24 ? 609698396 : 0); - buffer.putInt(0); - continue; - } - buffer.putInt(cacheFileManagers[index].getInformation().getInformationContainer().getCrc()); - buffer.putInt(cacheFileManagers[index].getInformation().getRevision()); - } - return buffer.array(); - } - - /** - * Get the cache file managers. - * - * @return The cache file managers. - */ - public static final CacheFileManager[] getIndexes() { - return cacheFileManagers; - } - - /** - * Get the container cache file informer. - * - * @return The container cache file informer. - */ - public static final CacheFile getReferenceFile() { - return referenceFile; - } - - /** - * Method used to return the component size of the interface. - * - * @param interfaceId the interface. - * @return the value. - */ - public static final int getInterfaceDefinitionsComponentsSize(int interfaceId) { - return getIndexes()[3].getFilesSize(interfaceId); - } - - /** - * Method used to return the max size of the interface definitions. - * - * @return the size. - */ - public static final int getInterfaceDefinitionsSize() { - return getIndexes()[3].getContainersSize(); - } - - /** - * Method used to return the {@link NPCDefinition} size. - * - * @return the size. - */ - public static final int getNPCDefinitionsSize() { - int lastContainerId = getIndexes()[18].getContainersSize() - 1; - return lastContainerId * 128 + getIndexes()[18].getFilesSize(lastContainerId); - } - - /** - * Method used to return the {@link GraphicDefinition} size. - * - * @return the size. - */ - public static final int getGraphicDefinitionsSize() { - int lastContainerId = getIndexes()[21].getContainersSize() - 1; - return lastContainerId * 256 + getIndexes()[21].getFilesSize(lastContainerId); - } - - /** - * Method used to return the {@link AnimationDefinition} size. - * - * @return the size. - */ - public static final int getAnimationDefinitionsSize() { - int lastContainerId = getIndexes()[20].getContainersSize() - 1; - return lastContainerId * 128 + getIndexes()[20].getFilesSize(lastContainerId); - } - - /** - * Method used to return the {@link SceneryDefinition} size. - * - * @return the size. - */ - public static final int getObjectDefinitionsSize() { - int lastContainerId = getIndexes()[16].getContainersSize() - 1; - return lastContainerId * 256 + getIndexes()[16].getFilesSize(lastContainerId); - } - - /** - * Method used to return the item definition size. - * - * @return the size. - */ - public static final int getItemDefinitionsSize() { - int lastContainerId = getIndexes()[19].getContainersSize() - 1; - return lastContainerId * 256 + getIndexes()[19].getFilesSize(lastContainerId); - } - -} \ No newline at end of file diff --git a/Server/src/main/java/core/cache/CacheFile.java b/Server/src/main/java/core/cache/CacheFile.java deleted file mode 100644 index a03642895..000000000 --- a/Server/src/main/java/core/cache/CacheFile.java +++ /dev/null @@ -1,148 +0,0 @@ -package core.cache; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; - -import core.cache.crypto.XTEACryption; -import core.cache.misc.ContainersInformation; - -/** - * A cache file. - * @author Dragonkk - */ -public final class CacheFile { - - /** - * The index file id. - */ - private int indexFileId; - - /** - * The cache file buffer. - */ - private byte[] cacheFileBuffer; - - /** - * The maximum container size. - */ - private int maxContainerSize; - - /** - * The index file. - */ - private RandomAccessFile indexFile; - - /** - * The data file. - */ - private RandomAccessFile dataFile; - - /** - * Construct a new cache file. - * @param indexFileId The index file id. - * @param indexFile The index file. - * @param dataFile The data file. - * @param maxContainerSize The maximum container size. - * @param cacheFileBuffer The cache file buffer. - */ - public CacheFile(int indexFileId, RandomAccessFile indexFile, RandomAccessFile dataFile, int maxContainerSize, byte[] cacheFileBuffer) { - this.cacheFileBuffer = cacheFileBuffer; - this.indexFileId = indexFileId; - this.maxContainerSize = maxContainerSize; - this.indexFile = indexFile; - this.dataFile = dataFile; - } - - /** - * Get the unpacked container data. - * @param containerId The container id. - * @param xteaKeys The container keys. - * @return The unpacked container data. - */ - public final byte[] getContainerUnpackedData(int containerId, int[] xteaKeys) { - byte[] packedData = getContainerData(containerId); - if (packedData == null) { - 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(); - } - return ContainersInformation.unpackCacheContainer(packedData); - } - - /** - * Get the container data for the specified container id. - * @param containerId The container id. - * @return The container data. - */ - public final byte[] getContainerData(int containerId) { - synchronized (dataFile) { - try { - if (indexFile.length() < (6 * containerId + 6)) { - return null; - } - indexFile.seek(6 * containerId); - indexFile.read(cacheFileBuffer, 0, 6); - int containerSize = (cacheFileBuffer[2] & 0xff) + (((0xff & cacheFileBuffer[0]) << 16) + (cacheFileBuffer[1] << 8 & 0xff00)); - int sector = ((cacheFileBuffer[3] & 0xff) << 16) - (-(0xff00 & cacheFileBuffer[4] << 8) - (cacheFileBuffer[5] & 0xff)); - if (containerSize < 0 || containerSize > maxContainerSize) { - return null; - } - if (sector <= 0 || dataFile.length() / 520L < sector) { - return null; - } - byte data[] = new byte[containerSize]; - int dataReadCount = 0; - int part = 0; - while (containerSize > dataReadCount) { - if (sector == 0) { - return null; - } - dataFile.seek(520 * sector); - int dataToReadCount = containerSize - dataReadCount; - if (dataToReadCount > 512) { - dataToReadCount = 512; - } - dataFile.read(cacheFileBuffer, 0, 8 + dataToReadCount); - int currentContainerId = (0xff & cacheFileBuffer[1]) + (0xff00 & cacheFileBuffer[0] << 8); - int currentPart = ((cacheFileBuffer[2] & 0xff) << 8) + (0xff & cacheFileBuffer[3]); - int nextSector = (cacheFileBuffer[6] & 0xff) + (0xff00 & cacheFileBuffer[5] << 8) + ((0xff & cacheFileBuffer[4]) << 16); - int currentIndexFileId = cacheFileBuffer[7] & 0xff; - if (containerId != currentContainerId || currentPart != part || indexFileId != currentIndexFileId) { - return null; - } - if (nextSector < 0 || (dataFile.length() / 520L) < nextSector) { - return null; - } - for (int index = 0; dataToReadCount > index; index++) { - data[dataReadCount++] = cacheFileBuffer[8 + index]; - } - part++; - sector = nextSector; - } - return data; - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - } - - /** - * Get the index file id. - * @return - */ - public int getIndexFileId() { - return indexFileId; - } - - /** - * Get the unpacked container data. - * @param containerId The container id. - * @return The unpacked container data. - */ - public final byte[] getContainerUnpackedData(int containerId) { - return getContainerUnpackedData(containerId, null); - } -} diff --git a/Server/src/main/java/core/cache/CacheFileManager.java b/Server/src/main/java/core/cache/CacheFileManager.java deleted file mode 100644 index 023803ea2..000000000 --- a/Server/src/main/java/core/cache/CacheFileManager.java +++ /dev/null @@ -1,293 +0,0 @@ -package core.cache; - -import java.nio.ByteBuffer; - -import core.cache.misc.ContainersInformation; -import core.tools.StringUtils; - -/** - * A cache file manager. - * @author Dragonkk - */ -public final class CacheFileManager { - - /** - * The cache file. - */ - private CacheFile cacheFile; - - /** - * The containers information. - */ - private ContainersInformation information; - - /** - * Discard a files data. - */ - private boolean discardFilesData; - - /** - * A array holding file data. - */ - private byte[][][] filesData; - - /** - * Construct a new cache file manager. - * @param cacheFile The cache file. - * @param discardFilesData To discard a files data. - */ - public CacheFileManager(CacheFile cacheFile, boolean discardFilesData) { - this.cacheFile = cacheFile; - this.discardFilesData = discardFilesData; - byte[] informContainerPackedData = Cache.getReferenceFile().getContainerData(cacheFile.getIndexFileId()); - if (informContainerPackedData == null) { - return; - } - information = new ContainersInformation(informContainerPackedData); - resetFilesData(); - } - - /** - * Get the cache file. - * @return The cache file. - */ - public CacheFile getCacheFile() { - return cacheFile; - } - - /** - * Get the containers size. - * @return The containers size. - */ - public int getContainersSize() { - return information.getContainers().length; - } - - /** - * Get the files size. - * @param containerId The container id. - * @return The files size. - */ - public int getFilesSize(int containerId) { - if (!validContainer(containerId)) { - return -1; - } - return information.getContainers()[containerId].getFiles().length; - } - - /** - * Reset the file data. - */ - public void resetFilesData() { - filesData = new byte[information.getContainers().length][][]; - } - - /** - * Check if a file is valid. - * @param containerId The container id. - * @param fileId The file id. - * @return If the file is valid {@code true}. - */ - public boolean validFile(int containerId, int fileId) { - if (!validContainer(containerId)) { - return false; - } - if (fileId < 0 || information.getContainers()[containerId] == null || information.getContainers()[containerId].getFiles().length <= fileId) { - return false; - } - return true; - - } - - /** - * If a container is valid. - * @param containerId The container id. - * @return If the container is valid {@code true}. - */ - public boolean validContainer(int containerId) { - if (containerId < 0 || information.getContainers().length <= containerId) { - return false; - } - return true; - } - - /** - * Get the file ids. - * @param containerId The container id. - * @return The file ids. - */ - public int[] getFileIds(int containerId) { - if (!validContainer(containerId)) { - return null; - } - return information.getContainers()[containerId].getFilesIndexes(); - } - - /** - * Get the archive id. - * @param name The archive name. - * @return The archive id. - */ - public int getArchiveId(String name) { - if (name == null) { - return -1; - } - int hash = StringUtils.getNameHash(name); - for (int containerIndex = 0; containerIndex < information.getContainersIndexes().length; containerIndex++) { - if (information.getContainers()[information.getContainersIndexes()[containerIndex]].getNameHash() == hash) { - return information.getContainersIndexes()[containerIndex]; - } - } - return -1; - } - - /** - * Get the file data. - * @param containerId The container id. - * @param fileId The file id. - * @return The get file data. - */ - public byte[] getFileData(int containerId, int fileId) { - return getFileData(containerId, fileId, null); - } - - /** - * Load the file data. - * @param archiveId The container id. - * @param keys The container keys. - * @return If the file data is loaded {@code true}. - */ - public boolean loadFilesData(int archiveId, int[] keys) { - byte[] data = cacheFile.getContainerUnpackedData(archiveId, keys); - if (data == null) { - return false; - } - if (filesData[archiveId] == null) { - if (information.getContainers()[archiveId] == null) { - return false; // container inform doesnt exist anymore - } - filesData[archiveId] = new byte[information.getContainers()[archiveId].getFiles().length][]; - } - if (information.getContainers()[archiveId].getFilesIndexes().length == 1) { - int fileId = information.getContainers()[archiveId].getFilesIndexes()[0]; - filesData[archiveId][fileId] = data; - } else { - int readPosition = data.length; - int amtOfLoops = data[--readPosition] & 0xff; - readPosition -= amtOfLoops * (information.getContainers()[archiveId].getFilesIndexes().length * 4); - ByteBuffer buffer = ByteBuffer.wrap(data); - int filesSize[] = new int[information.getContainers()[archiveId].getFilesIndexes().length]; - buffer.position(readPosition); - for (int loop = 0; loop < amtOfLoops; loop++) { - int offset = 0; - for (int fileIndex = 0; fileIndex < information.getContainers()[archiveId].getFilesIndexes().length; fileIndex++) { - filesSize[fileIndex] += offset += buffer.getInt(); - } - } - byte[][] filesBufferData = new byte[information.getContainers()[archiveId].getFilesIndexes().length][]; - for (int fileIndex = 0; fileIndex < information.getContainers()[archiveId].getFilesIndexes().length; fileIndex++) { - filesBufferData[fileIndex] = new byte[filesSize[fileIndex]]; - filesSize[fileIndex] = 0; - } - buffer.position(readPosition); - int sourceOffset = 0; - for (int loop = 0; loop < amtOfLoops; loop++) { - int dataRead = 0; - for (int fileIndex = 0; fileIndex < information.getContainers()[archiveId].getFilesIndexes().length; fileIndex++) { - dataRead += buffer.getInt(); - System.arraycopy(data, sourceOffset, filesBufferData[fileIndex], filesSize[fileIndex], dataRead); - sourceOffset += dataRead; - filesSize[fileIndex] += dataRead; - } - } - for (int fileIndex = 0; fileIndex < information.getContainers()[archiveId].getFilesIndexes().length; fileIndex++) { - filesData[archiveId][information.getContainers()[archiveId].getFilesIndexes()[fileIndex]] = filesBufferData[fileIndex]; - } - } - return true; - - } - - /** - * Get the file data. - * @param containerId The container id. - * @param fileId The file id. - * @param xteaKeys The container keys. - * @return The file data. - */ - public byte[] getFileData(int containerId, int fileId, int[] xteaKeys) { - if (!validFile(containerId, fileId)) { - return null; - } - if (filesData[containerId] == null || filesData[containerId][fileId] == null) { - if (!loadFilesData(containerId, xteaKeys)) { - return null; - } - } - byte[] data = filesData[containerId][fileId]; - if (discardFilesData) { - if (filesData[containerId].length == 1) { - filesData[containerId] = null; - } else { - filesData[containerId][fileId] = null; - } - } - return data; - } - - /** - * Get the containers information. - * @return The containers information. - */ - public ContainersInformation getInformation() { - return information; - } - - /** - * Gets the discardFilesData. - * @return the discardFilesData. - */ - public boolean isDiscardFilesData() { - return discardFilesData; - } - - /** - * Sets the discardFilesData. - * @param discardFilesData the discardFilesData to set - */ - public void setDiscardFilesData(boolean discardFilesData) { - this.discardFilesData = discardFilesData; - } - - /** - * Gets the filesData. - * @return the filesData. - */ - public byte[][][] getFilesData() { - return filesData; - } - - /** - * Sets the filesData. - * @param filesData the filesData to set - */ - public void setFilesData(byte[][][] filesData) { - this.filesData = filesData; - } - - /** - * Sets the cacheFile. - * @param cacheFile the cacheFile to set - */ - public void setCacheFile(CacheFile cacheFile) { - this.cacheFile = cacheFile; - } - - /** - * Sets the information. - * @param information the information to set - */ - public void setInformation(ContainersInformation information) { - this.information = information; - } -} diff --git a/Server/src/main/java/core/cache/StoreFile.java b/Server/src/main/java/core/cache/StoreFile.java deleted file mode 100644 index 50e1728d0..000000000 --- a/Server/src/main/java/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/java/core/cache/bzip2/BZip2BlockEntry.java b/Server/src/main/java/core/cache/bzip2/BZip2BlockEntry.java deleted file mode 100644 index c5c304dd7..000000000 --- a/Server/src/main/java/core/cache/bzip2/BZip2BlockEntry.java +++ /dev/null @@ -1,56 +0,0 @@ -package core.cache.bzip2; - -public class BZip2BlockEntry { - - boolean aBooleanArray2205[]; - boolean aBooleanArray2213[]; - byte aByte2201; - byte aByteArray2204[]; - byte aByteArray2211[]; - byte aByteArray2212[]; - byte aByteArray2214[]; - byte aByteArray2219[]; - byte aByteArray2224[]; - byte aByteArrayArray2229[][]; - int anInt2202; - int anInt2203; - int anInt2206; - int anInt2207; - int anInt2208; - int anInt2209; - int anInt2215; - int anInt2216; - int anInt2217; - int anInt2221; - int anInt2222; - int anInt2223; - int anInt2225; - int anInt2227; - int anInt2232; - int anIntArray2200[]; - int anIntArray2220[]; - int anIntArray2226[]; - int anIntArray2228[]; - int anIntArrayArray2210[][]; - int anIntArrayArray2218[][]; - int anIntArrayArray2230[][]; - - public BZip2BlockEntry() { - anIntArray2200 = new int[6]; - anInt2203 = 0; - aByteArray2204 = new byte[4096]; - aByteArray2211 = new byte[256]; - aByteArray2214 = new byte[18002]; - aByteArray2219 = new byte[18002]; - anIntArray2220 = new int[257]; - anIntArrayArray2218 = new int[6][258]; - aBooleanArray2205 = new boolean[16]; - aBooleanArray2213 = new boolean[256]; - anInt2209 = 0; - anIntArray2226 = new int[16]; - anIntArrayArray2210 = new int[6][258]; - aByteArrayArray2229 = new byte[6][258]; - anIntArrayArray2230 = new int[6][258]; - anIntArray2228 = new int[256]; - } -} diff --git a/Server/src/main/java/core/cache/bzip2/BZip2Decompressor.java b/Server/src/main/java/core/cache/bzip2/BZip2Decompressor.java deleted file mode 100644 index f62ec1145..000000000 --- a/Server/src/main/java/core/cache/bzip2/BZip2Decompressor.java +++ /dev/null @@ -1,532 +0,0 @@ -package core.cache.bzip2; - -public class BZip2Decompressor { - - private static int anIntArray257[]; - private static BZip2BlockEntry entryInstance = new BZip2BlockEntry(); - - public static final void decompress(byte decompressedData[], byte packedData[], int containerSize, int blockSize) { - synchronized (entryInstance) { - entryInstance.aByteArray2224 = packedData; - entryInstance.anInt2209 = blockSize; - entryInstance.aByteArray2212 = decompressedData; - entryInstance.anInt2203 = 0; - entryInstance.anInt2206 = decompressedData.length; - entryInstance.anInt2232 = 0; - entryInstance.anInt2207 = 0; - entryInstance.anInt2217 = 0; - entryInstance.anInt2216 = 0; - method1793(entryInstance); - entryInstance.aByteArray2224 = null; - entryInstance.aByteArray2212 = null; - } - } - - private static final void method1785(BZip2BlockEntry entry) { - entry.anInt2215 = 0; - for (int i = 0; i < 256; i++) { - if (entry.aBooleanArray2213[i]) { - entry.aByteArray2211[entry.anInt2215] = (byte) i; - entry.anInt2215++; - } - } - - } - - private static final void method1786(int ai[], int ai1[], int ai2[], byte abyte0[], int i, int j, int k) { - int l = 0; - for (int i1 = i; i1 <= j; i1++) { - for (int l2 = 0; l2 < k; l2++) { - if (abyte0[l2] == i1) { - ai2[l] = l2; - l++; - } - } - - } - - for (int j1 = 0; j1 < 23; j1++) { - ai1[j1] = 0; - } - - for (int k1 = 0; k1 < k; k1++) { - ai1[abyte0[k1] + 1]++; - } - - for (int l1 = 1; l1 < 23; l1++) { - ai1[l1] += ai1[l1 - 1]; - } - - for (int i2 = 0; i2 < 23; i2++) { - ai[i2] = 0; - } - - int i3 = 0; - for (int j2 = i; j2 <= j; j2++) { - i3 += ai1[j2 + 1] - ai1[j2]; - ai[j2] = i3 - 1; - i3 <<= 1; - } - - for (int k2 = i + 1; k2 <= j; k2++) { - ai1[k2] = (ai[k2 - 1] + 1 << 1) - ai1[k2]; - } - - } - - private static final void method1787(BZip2BlockEntry entry) { - byte byte4 = entry.aByte2201; - int i = entry.anInt2222; - int j = entry.anInt2227; - int k = entry.anInt2221; - int ai[] = anIntArray257; - int l = entry.anInt2208; - byte abyte0[] = entry.aByteArray2212; - int i1 = entry.anInt2203; - int j1 = entry.anInt2206; - int k1 = j1; - int l1 = entry.anInt2225 + 1; - label0: do { - if (i > 0) { - do { - if (j1 == 0) { - break label0; - } - if (i == 1) { - break; - } - abyte0[i1] = byte4; - i--; - i1++; - j1--; - } while (true); - abyte0[i1] = byte4; - i1++; - j1--; - } - boolean flag = true; - while (flag) { - flag = false; - if (j == l1) { - i = 0; - break label0; - } - byte4 = (byte) k; - l = ai[l]; - byte byte0 = (byte) (l & 0xff); - l >>= 8; - j++; - if (byte0 != k) { - k = byte0; - if (j1 == 0) { - i = 1; - } else { - abyte0[i1] = byte4; - i1++; - j1--; - flag = true; - continue; - } - break label0; - } - if (j != l1) { - continue; - } - if (j1 == 0) { - i = 1; - break label0; - } - abyte0[i1] = byte4; - i1++; - j1--; - flag = true; - } - i = 2; - l = ai[l]; - byte byte1 = (byte) (l & 0xff); - l >>= 8; - if (++j != l1) { - if (byte1 != k) { - k = byte1; - } else { - i = 3; - l = ai[l]; - byte byte2 = (byte) (l & 0xff); - l >>= 8; - if (++j != l1) { - if (byte2 != k) { - k = byte2; - } else { - l = ai[l]; - byte byte3 = (byte) (l & 0xff); - l >>= 8; - j++; - i = (byte3 & 0xff) + 4; - l = ai[l]; - k = (byte) (l & 0xff); - l >>= 8; - j++; - } - } - } - } - } while (true); - entry.anInt2216 += k1 - j1; - entry.aByte2201 = byte4; - entry.anInt2222 = i; - entry.anInt2227 = j; - entry.anInt2221 = k; - anIntArray257 = ai; - entry.anInt2208 = l; - entry.aByteArray2212 = abyte0; - entry.anInt2203 = i1; - entry.anInt2206 = j1; - } - - private static final byte method1788(BZip2BlockEntry entry) { - return (byte) method1790(1, entry); - } - - private static final byte method1789(BZip2BlockEntry entryInstance2) { - return (byte) method1790(8, entryInstance2); - } - - private static final int method1790(int i, BZip2BlockEntry entry) { - int j; - do { - if (entry.anInt2232 >= i) { - int k = entry.anInt2207 >> entry.anInt2232 - i & (1 << i) - 1; - entry.anInt2232 -= i; - j = k; - break; - } - entry.anInt2207 = entry.anInt2207 << 8 | entry.aByteArray2224[entry.anInt2209] & 0xff; - entry.anInt2232 += 8; - entry.anInt2209++; - entry.anInt2217++; - } while (true); - return j; - } - - public static void clearBlockEntryInstance() { - entryInstance = null; - } - - private static final void method1793(BZip2BlockEntry entryInstance2) { - // unused - /* - * boolean flag = false; boolean flag1 = false; boolean flag2 = false; - * boolean flag3 = false; boolean flag4 = false; boolean flag5 = false; - * boolean flag6 = false; boolean flag7 = false; boolean flag8 = false; - * boolean flag9 = false; boolean flag10 = false; boolean flag11 = - * false; boolean flag12 = false; boolean flag13 = false; boolean flag14 - * = false; boolean flag15 = false; boolean flag16 = false; boolean - * flag17 = false; - */ - int j8 = 0; - int ai[] = null; - int ai1[] = null; - int ai2[] = null; - entryInstance2.anInt2202 = 1; - if (anIntArray257 == null) { - anIntArray257 = new int[entryInstance2.anInt2202 * 0x186a0]; - } - boolean flag18 = true; - while (flag18) { - byte byte0 = method1789(entryInstance2); - if (byte0 == 23) { - return; - } - byte0 = method1789(entryInstance2); - byte0 = method1789(entryInstance2); - byte0 = method1789(entryInstance2); - byte0 = method1789(entryInstance2); - byte0 = method1789(entryInstance2); - byte0 = method1789(entryInstance2); - byte0 = method1789(entryInstance2); - byte0 = method1789(entryInstance2); - byte0 = method1789(entryInstance2); - byte0 = method1788(entryInstance2); - entryInstance2.anInt2223 = 0; - byte0 = method1789(entryInstance2); - entryInstance2.anInt2223 = entryInstance2.anInt2223 << 8 | byte0 & 0xff; - byte0 = method1789(entryInstance2); - entryInstance2.anInt2223 = entryInstance2.anInt2223 << 8 | byte0 & 0xff; - byte0 = method1789(entryInstance2); - entryInstance2.anInt2223 = entryInstance2.anInt2223 << 8 | byte0 & 0xff; - for (int j = 0; j < 16; j++) { - byte byte1 = method1788(entryInstance2); - if (byte1 == 1) { - entryInstance2.aBooleanArray2205[j] = true; - } else { - entryInstance2.aBooleanArray2205[j] = false; - } - } - - for (int k = 0; k < 256; k++) { - entryInstance2.aBooleanArray2213[k] = false; - } - - for (int l = 0; l < 16; l++) { - if (entryInstance2.aBooleanArray2205[l]) { - for (int i3 = 0; i3 < 16; i3++) { - byte byte2 = method1788(entryInstance2); - if (byte2 == 1) { - entryInstance2.aBooleanArray2213[l * 16 + i3] = true; - } - } - - } - } - - method1785(entryInstance2); - int i4 = entryInstance2.anInt2215 + 2; - int j4 = method1790(3, entryInstance2); - int k4 = method1790(15, entryInstance2); - for (int i1 = 0; i1 < k4; i1++) { - int j3 = 0; - do { - byte byte3 = method1788(entryInstance2); - if (byte3 == 0) { - break; - } - j3++; - } while (true); - entryInstance2.aByteArray2214[i1] = (byte) j3; - } - - byte abyte0[] = new byte[6]; - for (byte byte16 = 0; byte16 < j4; byte16++) { - abyte0[byte16] = byte16; - } - - for (int j1 = 0; j1 < k4; j1++) { - byte byte17 = entryInstance2.aByteArray2214[j1]; - byte byte15 = abyte0[byte17]; - for (; byte17 > 0; byte17--) { - abyte0[byte17] = abyte0[byte17 - 1]; - } - - abyte0[0] = byte15; - entryInstance2.aByteArray2219[j1] = byte15; - } - - for (int k3 = 0; k3 < j4; k3++) { - int k6 = method1790(5, entryInstance2); - for (int k1 = 0; k1 < i4; k1++) { - do { - byte byte4 = method1788(entryInstance2); - if (byte4 == 0) { - break; - } - byte4 = method1788(entryInstance2); - if (byte4 == 0) { - k6++; - } else { - k6--; - } - } while (true); - entryInstance2.aByteArrayArray2229[k3][k1] = (byte) k6; - } - - } - - for (int l3 = 0; l3 < j4; l3++) { - byte byte8 = 32; - int i = 0; - for (int l1 = 0; l1 < i4; l1++) { - if (entryInstance2.aByteArrayArray2229[l3][l1] > i) { - i = entryInstance2.aByteArrayArray2229[l3][l1]; - } - if (entryInstance2.aByteArrayArray2229[l3][l1] < byte8) { - byte8 = entryInstance2.aByteArrayArray2229[l3][l1]; - } - } - - method1786(entryInstance2.anIntArrayArray2230[l3], entryInstance2.anIntArrayArray2218[l3], entryInstance2.anIntArrayArray2210[l3], entryInstance2.aByteArrayArray2229[l3], byte8, i, i4); - entryInstance2.anIntArray2200[l3] = byte8; - } - - int l4 = entryInstance2.anInt2215 + 1; - int i5 = -1; - int j5 = 0; - for (int i2 = 0; i2 <= 255; i2++) { - entryInstance2.anIntArray2228[i2] = 0; - } - - int i9 = 4095; - for (int k8 = 15; k8 >= 0; k8--) { - for (int l8 = 15; l8 >= 0; l8--) { - entryInstance2.aByteArray2204[i9] = (byte) (k8 * 16 + l8); - i9--; - } - - entryInstance2.anIntArray2226[k8] = i9 + 1; - } - - int l5 = 0; - if (j5 == 0) { - i5++; - j5 = 50; - byte byte12 = entryInstance2.aByteArray2219[i5]; - j8 = entryInstance2.anIntArray2200[byte12]; - ai = entryInstance2.anIntArrayArray2230[byte12]; - ai2 = entryInstance2.anIntArrayArray2210[byte12]; - ai1 = entryInstance2.anIntArrayArray2218[byte12]; - } - j5--; - int l6 = j8; - int k7; - byte byte9; - for (k7 = method1790(l6, entryInstance2); k7 > ai[l6]; k7 = k7 << 1 | byte9) { - l6++; - byte9 = method1788(entryInstance2); - } - - for (int k5 = ai2[k7 - ai1[l6]]; k5 != l4;) { - if (k5 == 0 || k5 == 1) { - int i6 = -1; - int j6 = 1; - do { - if (k5 == 0) { - i6 += j6; - } else if (k5 == 1) { - i6 += 2 * j6; - } - j6 *= 2; - if (j5 == 0) { - i5++; - j5 = 50; - byte byte13 = entryInstance2.aByteArray2219[i5]; - j8 = entryInstance2.anIntArray2200[byte13]; - ai = entryInstance2.anIntArrayArray2230[byte13]; - ai2 = entryInstance2.anIntArrayArray2210[byte13]; - ai1 = entryInstance2.anIntArrayArray2218[byte13]; - } - j5--; - int i7 = j8; - int l7; - byte byte10; - for (l7 = method1790(i7, entryInstance2); l7 > ai[i7]; l7 = l7 << 1 | byte10) { - i7++; - byte10 = method1788(entryInstance2); - } - - k5 = ai2[l7 - ai1[i7]]; - } while (k5 == 0 || k5 == 1); - i6++; - byte byte5 = entryInstance2.aByteArray2211[entryInstance2.aByteArray2204[entryInstance2.anIntArray2226[0]] & 0xff]; - entryInstance2.anIntArray2228[byte5 & 0xff] += i6; - for (; i6 > 0; i6--) { - anIntArray257[l5] = byte5 & 0xff; - l5++; - } - - } else { - int i11 = k5 - 1; - byte byte6; - if (i11 < 16) { - int i10 = entryInstance2.anIntArray2226[0]; - byte6 = entryInstance2.aByteArray2204[i10 + i11]; - for (; i11 > 3; i11 -= 4) { - int j11 = i10 + i11; - entryInstance2.aByteArray2204[j11] = entryInstance2.aByteArray2204[j11 - 1]; - entryInstance2.aByteArray2204[j11 - 1] = entryInstance2.aByteArray2204[j11 - 2]; - entryInstance2.aByteArray2204[j11 - 2] = entryInstance2.aByteArray2204[j11 - 3]; - entryInstance2.aByteArray2204[j11 - 3] = entryInstance2.aByteArray2204[j11 - 4]; - } - - for (; i11 > 0; i11--) { - entryInstance2.aByteArray2204[i10 + i11] = entryInstance2.aByteArray2204[(i10 + i11) - 1]; - } - - entryInstance2.aByteArray2204[i10] = byte6; - } else { - int k10 = i11 / 16; - int l10 = i11 % 16; - int j10 = entryInstance2.anIntArray2226[k10] + l10; - byte6 = entryInstance2.aByteArray2204[j10]; - for (; j10 > entryInstance2.anIntArray2226[k10]; j10--) { - entryInstance2.aByteArray2204[j10] = entryInstance2.aByteArray2204[j10 - 1]; - } - - entryInstance2.anIntArray2226[k10]++; - for (; k10 > 0; k10--) { - entryInstance2.anIntArray2226[k10]--; - entryInstance2.aByteArray2204[entryInstance2.anIntArray2226[k10]] = entryInstance2.aByteArray2204[(entryInstance2.anIntArray2226[k10 - 1] + 16) - 1]; - } - - entryInstance2.anIntArray2226[0]--; - entryInstance2.aByteArray2204[entryInstance2.anIntArray2226[0]] = byte6; - if (entryInstance2.anIntArray2226[0] == 0) { - int l9 = 4095; - for (int j9 = 15; j9 >= 0; j9--) { - for (int k9 = 15; k9 >= 0; k9--) { - entryInstance2.aByteArray2204[l9] = entryInstance2.aByteArray2204[entryInstance2.anIntArray2226[j9] + k9]; - l9--; - } - - entryInstance2.anIntArray2226[j9] = l9 + 1; - } - - } - } - entryInstance2.anIntArray2228[entryInstance2.aByteArray2211[byte6 & 0xff] & 0xff]++; - anIntArray257[l5] = entryInstance2.aByteArray2211[byte6 & 0xff] & 0xff; - l5++; - if (j5 == 0) { - i5++; - j5 = 50; - byte byte14 = entryInstance2.aByteArray2219[i5]; - j8 = entryInstance2.anIntArray2200[byte14]; - ai = entryInstance2.anIntArrayArray2230[byte14]; - ai2 = entryInstance2.anIntArrayArray2210[byte14]; - ai1 = entryInstance2.anIntArrayArray2218[byte14]; - } - j5--; - int j7 = j8; - int i8; - byte byte11; - for (i8 = method1790(j7, entryInstance2); i8 > ai[j7]; i8 = i8 << 1 | byte11) { - j7++; - byte11 = method1788(entryInstance2); - } - - k5 = ai2[i8 - ai1[j7]]; - } - } - - entryInstance2.anInt2222 = 0; - entryInstance2.aByte2201 = 0; - entryInstance2.anIntArray2220[0] = 0; - for (int j2 = 1; j2 <= 256; j2++) { - entryInstance2.anIntArray2220[j2] = entryInstance2.anIntArray2228[j2 - 1]; - } - - for (int k2 = 1; k2 <= 256; k2++) { - entryInstance2.anIntArray2220[k2] += entryInstance2.anIntArray2220[k2 - 1]; - } - - for (int l2 = 0; l2 < l5; l2++) { - byte byte7 = (byte) (anIntArray257[l2] & 0xff); - anIntArray257[entryInstance2.anIntArray2220[byte7 & 0xff]] |= l2 << 8; - entryInstance2.anIntArray2220[byte7 & 0xff]++; - } - - entryInstance2.anInt2208 = anIntArray257[entryInstance2.anInt2223] >> 8; - entryInstance2.anInt2227 = 0; - entryInstance2.anInt2208 = anIntArray257[entryInstance2.anInt2208]; - entryInstance2.anInt2221 = (byte) (entryInstance2.anInt2208 & 0xff); - entryInstance2.anInt2208 >>= 8; - entryInstance2.anInt2227++; - entryInstance2.anInt2225 = l5; - method1787(entryInstance2); - if (entryInstance2.anInt2227 == entryInstance2.anInt2225 + 1 && entryInstance2.anInt2222 == 0) { - flag18 = true; - } else { - flag18 = false; - } - } - } - -} diff --git a/Server/src/main/java/core/cache/def/impl/AnimationDefinition.java b/Server/src/main/java/core/cache/def/impl/AnimationDefinition.java index 9f54a1d61..e4087c19c 100644 --- a/Server/src/main/java/core/cache/def/impl/AnimationDefinition.java +++ b/Server/src/main/java/core/cache/def/impl/AnimationDefinition.java @@ -4,8 +4,9 @@ import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Map; -import core.cache.Cache; import core.cache.misc.buffer.ByteBufferUtils; +import rs09.cache.Cache; +import rs09.cache.CacheIndex; /** * Represents an animation's definitions. @@ -47,7 +48,7 @@ public final class AnimationDefinition { if (defs != null) { return defs; } - byte[] data = Cache.getIndexes()[20].getFileData(emoteId >>> 7, emoteId & 0x7f); + byte[] data = Cache.getData(CacheIndex.SEQUENCE_CONFIGURATION, emoteId >>> 7, emoteId & 0x7f); defs = new AnimationDefinition(); if (data != null) { defs.readValueLoop(ByteBuffer.wrap(data)); diff --git a/Server/src/main/java/core/cache/def/impl/CS2Mapping.java b/Server/src/main/java/core/cache/def/impl/CS2Mapping.java index cc1914b50..06236188e 100644 --- a/Server/src/main/java/core/cache/def/impl/CS2Mapping.java +++ b/Server/src/main/java/core/cache/def/impl/CS2Mapping.java @@ -1,17 +1,17 @@ package core.cache.def.impl; +import core.cache.misc.buffer.ByteBufferUtils; +import rs09.cache.Cache; +import rs09.cache.CacheIndex; +import rs09.game.world.GameWorld; + import java.io.BufferedWriter; -import java.io.FileWriter; import java.nio.ByteBuffer; import java.nio.file.Files; import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; -import core.cache.Cache; -import core.cache.misc.buffer.ByteBufferUtils; -import rs09.game.world.GameWorld; - /** * The CS2 mapping. * @author Emperor @@ -104,7 +104,7 @@ public final class CS2Mapping { return mapping; } mapping = new CS2Mapping(scriptId); - byte[] bs = Cache.getIndexes()[17].getFileData(scriptId >>> 8, scriptId & 0xFF); + byte[] bs = Cache.getData(CacheIndex.CLIENT_SCRIPTS, scriptId >>> 8, scriptId & 0xFF); if (bs != null) { mapping.load(ByteBuffer.wrap(bs)); } else { diff --git a/Server/src/main/java/core/cache/def/impl/ClothDefinition.java b/Server/src/main/java/core/cache/def/impl/ClothDefinition.java index fb34666fa..f7cc74d3d 100644 --- a/Server/src/main/java/core/cache/def/impl/ClothDefinition.java +++ b/Server/src/main/java/core/cache/def/impl/ClothDefinition.java @@ -4,7 +4,9 @@ import java.nio.ByteBuffer; import java.util.Arrays; import rs09.ServerConstants; -import core.cache.Cache; +import rs09.cache.Cache; +import rs09.cache.CacheArchive; +import rs09.cache.CacheIndex; /** * The definitions for player clothing/look. @@ -59,7 +61,7 @@ public final class ClothDefinition { */ public static ClothDefinition forId(int clothId) { ClothDefinition def = new ClothDefinition(); - byte[] bs = Cache.getIndexes()[2].getFileData(3, clothId); + byte[] bs = Cache.getData(CacheIndex.CONFIGURATION, CacheArchive.PLAYER_KIT, clothId); if (bs != null) { def.load(ByteBuffer.wrap(bs)); } @@ -76,7 +78,7 @@ public final class ClothDefinition { } catch (Throwable e) { e.printStackTrace(); } - int length = Cache.getIndexes()[2].getFilesSize(3); + int length = Cache.getArchiveCapacity(CacheIndex.CONFIGURATION, CacheArchive.PLAYER_KIT); System.out.println("Definition size: " + length + "."); for (int i = 0; i < length; i++) { ClothDefinition def = forId(i); diff --git a/Server/src/main/java/core/cache/def/impl/DataMap.java b/Server/src/main/java/core/cache/def/impl/DataMap.java index 40fe2694c..3181ba563 100644 --- a/Server/src/main/java/core/cache/def/impl/DataMap.java +++ b/Server/src/main/java/core/cache/def/impl/DataMap.java @@ -1,14 +1,12 @@ package core.cache.def.impl; -import core.cache.Cache; -import core.cache.CacheFileManager; -import core.cache.misc.Container; import core.cache.misc.buffer.ByteBufferUtils; import core.tools.CP1252; +import rs09.cache.Cache; +import rs09.cache.CacheIndex; import rs09.game.system.SystemLogger; import java.nio.ByteBuffer; -import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -68,7 +66,7 @@ public class DataMap { if (def != null) { return def; } - byte[] data = Cache.getIndexes()[17].getFileData(id >>> 8, id & 0xFF); + byte[] data = Cache.getData(CacheIndex.ENUM_CONFIGURATION, id >>> 8, id & 0xFF); def = parse(id, data); definitions.put(id, def); return def; diff --git a/Server/src/main/java/core/cache/def/impl/GraphicDefinition.java b/Server/src/main/java/core/cache/def/impl/GraphicDefinition.java index e554a3b1e..f3ae58a96 100644 --- a/Server/src/main/java/core/cache/def/impl/GraphicDefinition.java +++ b/Server/src/main/java/core/cache/def/impl/GraphicDefinition.java @@ -1,12 +1,13 @@ package core.cache.def.impl; +import rs09.ServerConstants; +import rs09.cache.Cache; +import rs09.cache.CacheIndex; + import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Map; -import rs09.ServerConstants; -import core.cache.Cache; - /** * Represents a Graphic's definition. * @author Jagex @@ -48,7 +49,7 @@ public class GraphicDefinition { if (def != null) { return def; } - byte[] data = Cache.getIndexes()[21].getFileData(gfxId >>> 8, gfxId & 0xff); + byte[] data = Cache.getData(CacheIndex.SPOTANIM_CONFIGURATION, gfxId >>> 8, gfxId & 0xFF); def = new GraphicDefinition(); def.graphicsId = gfxId; if (data != null) { diff --git a/Server/src/main/java/core/cache/def/impl/ItemDefinition.java b/Server/src/main/java/core/cache/def/impl/ItemDefinition.java index cc640ac6a..9872e378b 100644 --- a/Server/src/main/java/core/cache/def/impl/ItemDefinition.java +++ b/Server/src/main/java/core/cache/def/impl/ItemDefinition.java @@ -1,6 +1,5 @@ package core.cache.def.impl; -import core.cache.Cache; import core.cache.def.Definition; import core.cache.misc.buffer.ByteBufferUtils; import core.game.container.Container; @@ -15,6 +14,8 @@ import core.net.packet.PacketRepository; import core.net.packet.out.WeightUpdate; import core.plugin.Plugin; import core.tools.StringUtils; +import rs09.cache.Cache; +import rs09.cache.CacheIndex; import rs09.game.system.SystemLogger; import rs09.game.system.config.ItemConfigParser; import org.rs09.consts.Items; @@ -286,8 +287,8 @@ public class ItemDefinition extends Definition { * Parses the item definitions. */ public static void parse() { - for (int itemId = 0; itemId < Cache.getItemDefinitionsSize(); itemId++) { - byte[] data = Cache.getIndexes()[19].getFileData(itemId >>> 8, itemId & 0xFF); + for (int itemId = 0; itemId < Cache.getIndexCapacity(CacheIndex.ITEM_CONFIGURATION); itemId++) { + byte[] data = Cache.getData(CacheIndex.ITEM_CONFIGURATION, itemId >>> 8, itemId & 0xFF); if (data == null) { ItemDefinition.getDefinitions().put(itemId, new ItemDefinition()); continue; @@ -303,6 +304,7 @@ public class ItemDefinition extends Definition { ItemDefinition.getDefinitions().put(itemId, def); } ItemDefinition.defineTemplates(); + SystemLogger.logCache("Loaded " + ItemDefinition.getDefinitions().size() + " Item definitions."); } /** @@ -485,7 +487,7 @@ public class ItemDefinition extends Definition { */ public static void defineTemplates() { int equipId = 0; - for (int i = 0; i < Cache.getItemDefinitionsSize(); i++) { + for (int i = 0; i < Cache.getIndexCapacity(CacheIndex.ITEM_CONFIGURATION); i++) { ItemDefinition def = forId(i); if (def.noteTemplateId != -1) { def.transferNoteDefinition(forId(def.noteId), forId(def.noteTemplateId)); diff --git a/Server/src/main/java/core/cache/def/impl/NPCDefinition.java b/Server/src/main/java/core/cache/def/impl/NPCDefinition.java index 013492a3c..2524ad2ec 100644 --- a/Server/src/main/java/core/cache/def/impl/NPCDefinition.java +++ b/Server/src/main/java/core/cache/def/impl/NPCDefinition.java @@ -1,6 +1,5 @@ package core.cache.def.impl; -import core.cache.Cache; import core.cache.def.Definition; import core.cache.misc.buffer.ByteBufferUtils; import core.game.interaction.OptionHandler; @@ -10,6 +9,8 @@ import core.game.node.entity.player.Player; import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Graphics; import core.tools.StringUtils; +import rs09.cache.Cache; +import rs09.cache.CacheIndex; import rs09.game.system.config.NPCConfigParser; import rs09.game.world.GameWorld; @@ -199,7 +200,7 @@ public final class NPCDefinition extends Definition { NPCDefinition def = DEFINITIONS.get(id); if (def == null) { def = new NPCDefinition(id); - byte[] data = Cache.getIndexes()[18].getFileData(id >>> 7, id & 0x7f); + byte[] data = Cache.getData(CacheIndex.NPC_CONFIGURATION, id >>> 7, id & 0x7f); if (data == null) { if (id != -1) { // System.out.println("Failed loading NPC " + id + "."); diff --git a/Server/src/main/java/core/cache/def/impl/RenderAnimationDefinition.java b/Server/src/main/java/core/cache/def/impl/RenderAnimationDefinition.java index d9f9363a5..2ad4083bb 100644 --- a/Server/src/main/java/core/cache/def/impl/RenderAnimationDefinition.java +++ b/Server/src/main/java/core/cache/def/impl/RenderAnimationDefinition.java @@ -1,6 +1,8 @@ package core.cache.def.impl; -import core.cache.Cache; +import rs09.cache.Cache; +import rs09.cache.CacheArchive; +import rs09.cache.CacheIndex; import rs09.game.system.SystemLogger; import rs09.game.world.GameWorld; @@ -67,12 +69,12 @@ public class RenderAnimationDefinition { if (animId == -1) { return null; } - byte[] data = Cache.getIndexes()[2].getFileData(32, animId); + byte[] data = Cache.getData(CacheIndex.CONFIGURATION, CacheArchive.BAS_TYPE, animId); RenderAnimationDefinition defs = new RenderAnimationDefinition(); if (data != null) { defs.parse(ByteBuffer.wrap(data)); } else { - SystemLogger.logErr(RenderAnimationDefinition.class, "No definitions found for render animation " + animId + ", size=" + Cache.getIndexes()[2].getFilesSize(32) + "!"); + SystemLogger.logErr(RenderAnimationDefinition.class, "No definitions found for render animation " + animId + ", size=" + Cache.getArchiveCapacity(CacheIndex.CONFIGURATION, CacheArchive.BAS_TYPE) + "!"); } return defs; } diff --git a/Server/src/main/java/core/cache/def/impl/SceneryDefinition.java b/Server/src/main/java/core/cache/def/impl/SceneryDefinition.java index 77838d2db..90f542c20 100644 --- a/Server/src/main/java/core/cache/def/impl/SceneryDefinition.java +++ b/Server/src/main/java/core/cache/def/impl/SceneryDefinition.java @@ -1,11 +1,12 @@ package core.cache.def.impl; -import core.cache.Cache; import core.cache.def.Definition; import core.cache.misc.buffer.ByteBufferUtils; import core.game.interaction.OptionHandler; import core.game.node.entity.player.Player; import core.game.node.scenery.Scenery; +import rs09.cache.Cache; +import rs09.cache.CacheIndex; import rs09.game.system.SystemLogger; import rs09.game.world.GameWorld; @@ -569,8 +570,8 @@ public class SceneryDefinition extends Definition { * @throws Throwable the throwable. */ public static void parse() throws Throwable { - for (int objectId = 0; objectId < Cache.getObjectDefinitionsSize(); objectId++) { - byte[] data = Cache.getIndexes()[16].getFileData(getContainerId(objectId), objectId & 0xff); + for (int objectId = 0; objectId < Cache.getIndexCapacity(CacheIndex.SCENERY_CONFIGURATION); objectId++) { + byte[] data = Cache.getData(CacheIndex.SCENERY_CONFIGURATION, objectId >>> 8, objectId & 0xFF); if (data == null) { SceneryDefinition.getDefinitions().put(objectId, new SceneryDefinition()); //SystemLogger.logErr("Could not load object definitions for id " + objectId + " - no data!"); @@ -584,6 +585,7 @@ public class SceneryDefinition extends Definition { SceneryDefinition.getDefinitions().put(objectId, def); data = null; } + SystemLogger.logCache("Loaded " + SceneryDefinition.getDefinitions().size() + " Scenery definitions."); } /** diff --git a/Server/src/main/java/core/cache/def/impl/Struct.java b/Server/src/main/java/core/cache/def/impl/Struct.java index 06a0bfeb6..6a499daa3 100644 --- a/Server/src/main/java/core/cache/def/impl/Struct.java +++ b/Server/src/main/java/core/cache/def/impl/Struct.java @@ -1,9 +1,9 @@ package core.cache.def.impl; -import core.cache.Cache; -import core.cache.CacheFileManager; -import core.cache.misc.Container; import core.cache.misc.buffer.ByteBufferUtils; +import rs09.cache.Cache; +import rs09.cache.CacheArchive; +import rs09.cache.CacheIndex; import rs09.game.system.SystemLogger; import java.nio.ByteBuffer; @@ -53,7 +53,7 @@ public class Struct { if (def != null) { return def; } - byte[] data = Cache.getIndexes()[2].getFileData(26, id); + byte[] data = Cache.getData(CacheIndex.CONFIGURATION, CacheArchive.STRUCT_TYPE, id); def = parse(id, data); definitions.put(id, def); @@ -89,10 +89,6 @@ public class Struct { return def; } - public static int getCount() { - return Cache.getIndexes()[2].getFilesSize(26); - } - public int getId() { return id; } diff --git a/Server/src/main/java/core/cache/def/impl/VarbitDefinition.java b/Server/src/main/java/core/cache/def/impl/VarbitDefinition.java index 10c20ae14..1310224e3 100644 --- a/Server/src/main/java/core/cache/def/impl/VarbitDefinition.java +++ b/Server/src/main/java/core/cache/def/impl/VarbitDefinition.java @@ -1,7 +1,8 @@ package core.cache.def.impl; -import core.cache.Cache; import core.game.node.entity.player.Player; +import rs09.cache.Cache; +import rs09.cache.CacheIndex; import java.nio.ByteBuffer; import java.util.HashMap; @@ -94,7 +95,7 @@ public final class VarbitDefinition { } def = new VarbitDefinition(id); - byte[] bs = Cache.getIndexes()[22].getFileData(id >>> 10, id & 0x3ff); + byte[] bs = Cache.getData(CacheIndex.VARBIT_CONFIGURATION, id >>> 10, id & 0x3ff); if (bs != null) { ByteBuffer buffer = ByteBuffer.wrap(bs); int opcode = 0; diff --git a/Server/src/main/java/core/cache/gzip/GZipDecompressor.java b/Server/src/main/java/core/cache/gzip/GZipDecompressor.java deleted file mode 100644 index 0b4506456..000000000 --- a/Server/src/main/java/core/cache/gzip/GZipDecompressor.java +++ /dev/null @@ -1,47 +0,0 @@ -package core.cache.gzip; - -import java.nio.ByteBuffer; -import java.util.zip.Inflater; - -public class GZipDecompressor { - - private static final Inflater inflaterInstance = new Inflater(true); - - public static final void decompress(ByteBuffer buffer, byte[] data) { - synchronized (inflaterInstance) { - if (~buffer.get(buffer.position()) != -32 || buffer.get(buffer.position() + 1) != -117) { - data = null; - // throw new RuntimeException("Invalid GZIP header!"); - } - try { - inflaterInstance.setInput(buffer.array(), buffer.position() + 10, -buffer.position() - 18 + buffer.limit()); - inflaterInstance.inflate(data); - } catch (Exception e) { - // inflaterInstance.reset(); - data = null; - // throw new RuntimeException("Invalid GZIP compressed data!"); - } - inflaterInstance.reset(); - } - } - - public static final boolean decompress(byte[] compressed, byte data[], int offset, int length) { - synchronized (inflaterInstance) { - if (data[offset] != 31 || data[offset + 1] != -117) - return false; - // throw new RuntimeException("Invalid GZIP header!"); - try { - inflaterInstance.setInput(data, offset + 10, -offset - 18 + length); - inflaterInstance.inflate(compressed); - } catch (Exception e) { - inflaterInstance.reset(); - e.printStackTrace(); - return false; - // throw new RuntimeException("Invalid GZIP compressed data!"); - } - inflaterInstance.reset(); - return true; - } - } - -} diff --git a/Server/src/main/java/core/cache/misc/Container.java b/Server/src/main/java/core/cache/misc/Container.java deleted file mode 100644 index 9760845ff..000000000 --- a/Server/src/main/java/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/java/core/cache/misc/ContainersInformation.java b/Server/src/main/java/core/cache/misc/ContainersInformation.java deleted file mode 100644 index f786c1d2f..000000000 --- a/Server/src/main/java/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/java/core/cache/misc/FilesContainer.java b/Server/src/main/java/core/cache/misc/FilesContainer.java deleted file mode 100644 index 5f14e448f..000000000 --- a/Server/src/main/java/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/java/core/game/world/map/Region.java b/Server/src/main/java/core/game/world/map/Region.java index aa35b00a7..6a6ec6071 100644 --- a/Server/src/main/java/core/game/world/map/Region.java +++ b/Server/src/main/java/core/game/world/map/Region.java @@ -1,17 +1,16 @@ package core.game.world.map; -import core.cache.Cache; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.music.MusicZone; -import core.game.node.scenery.Scenery; -import core.game.node.scenery.SceneryBuilder; import core.game.system.communication.CommunicationInfo; import core.game.system.task.Pulse; import core.game.world.map.build.DynamicRegion; import core.game.world.map.build.LandscapeParser; import core.game.world.map.build.MapscapeParser; import core.game.world.map.zone.RegionZone; +import rs09.cache.Cache; +import rs09.cache.CacheIndex; import rs09.game.system.SystemLogger; import rs09.game.system.config.XteaParser; import rs09.game.world.GameWorld; @@ -302,28 +301,34 @@ public class Region { int regionId = dynamic ? ((DynamicRegion) r).getRegionId() : r.getId(); int regionX = regionId >> 8 & 0xFF; int regionY = regionId & 0xFF; - int mapscapeId = Cache.getIndexes()[5].getArchiveId("m" + regionX + "_"+ regionY); byte[][][] mapscapeData = new byte[4][SIZE][SIZE]; for (RegionPlane plane : r.planes) { plane.getFlags().setLandscape(new boolean[SIZE][SIZE]); //plane.getFlags().setClippingFlags(new int[SIZE][SIZE]); //plane.getProjectileFlags().setClippingFlags(new int[SIZE][SIZE]); } - if (mapscapeId > -1) { - ByteBuffer mapscape = ByteBuffer.wrap(Cache.getIndexes()[5].getCacheFile().getContainerUnpackedData(mapscapeId)); + byte[] mData = Cache.getData(CacheIndex.MAPS, "m" + regionX + "_"+ regionY); + if (mData != null) { + ByteBuffer mapscape = ByteBuffer.wrap(mData); MapscapeParser.parse(r, mapscapeData, mapscape); } r.hasFlags = dynamic; r.setLoaded(true); - int landscapeId = Cache.getIndexes()[5].getArchiveId("l" + regionX + "_" + regionY); - if (landscapeId > -1) { - byte[] landscape = Cache.getIndexes()[5].getFileData(landscapeId, 0, XteaParser.Companion.getRegionXTEA(regionId)); - if (landscape == null || landscape.length < 4) { + + int[] keys = XteaParser.Companion.getRegionXTEA(regionId); + if (keys == null) { + keys = new int[]{0,0,0,0}; + } + byte[] lData = Cache.getData(CacheIndex.MAPS, "l" + regionX + "_"+ regionY, keys); + if (lData == null) { + return; + } else { + if (lData.length < 4) { return; } r.hasFlags = true; try { - LandscapeParser.parse(r, mapscapeData, ByteBuffer.wrap(landscape), build); + LandscapeParser.parse(r, mapscapeData, ByteBuffer.wrap(lData), build); } catch (Throwable t) { new Throwable("Failed parsing region " + regionId + "!", t).printStackTrace(); } diff --git a/Server/src/main/java/core/net/IoSession.java b/Server/src/main/java/core/net/IoSession.java index 61c2e2f3c..a70372bc0 100644 --- a/Server/src/main/java/core/net/IoSession.java +++ b/Server/src/main/java/core/net/IoSession.java @@ -105,10 +105,10 @@ public class IoSession { */ private final String address; - /** - * The JS-5 queue. - */ - private final JS5Queue js5Queue; +// /** +// * The JS-5 queue. +// */ +// private final JS5Queue js5Queue; /** * The client info. @@ -126,7 +126,7 @@ public class IoSession { this.key = key; this.service = service; this.address = getRemoteAddress().replaceAll("/", "").split(":")[0]; - this.js5Queue = new JS5Queue(this); +// this.js5Queue = new JS5Queue(this); } /** @@ -417,13 +417,13 @@ public class IoSession { this.isaacPair = isaacPair; } - /** - * Gets the js5Queue. - * @return the js5Queue - */ - public JS5Queue getJs5Queue() { - return js5Queue; - } +// /** +// * Gets the js5Queue. +// * @return the js5Queue +// */ +// public JS5Queue getJs5Queue() { +// return js5Queue; +// } /** * Gets the clientInfo value. diff --git a/Server/src/main/java/core/net/JS5Queue.java b/Server/src/main/java/core/net/JS5Queue.java deleted file mode 100644 index b08d1b10a..000000000 --- a/Server/src/main/java/core/net/JS5Queue.java +++ /dev/null @@ -1,97 +0,0 @@ -package core.net; - -import java.util.concurrent.LinkedBlockingDeque; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * Handles the JS5 queue for a session. - * @author Techdaan - */ -public final class JS5Queue { - - public static AtomicBoolean RUNNING = new AtomicBoolean(true); - - private static final Js5QueueHandler handler = new Js5QueueHandler(); - - private static class Js5QueueHandler extends Thread { - private final LinkedBlockingDeque requests = new LinkedBlockingDeque<>(); - - @Override - public void run() { - while (RUNNING.get()) { - try { - Js5Request request = requests.take(); - - JS5Queue queue = request.queue; - - if (queue.session.isActive()) { - queue.session.write(new int[]{request.index, request.archive, request.priority ? 1 : 0}); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - } - } - - static { - try { - handler.start(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private static class Js5Request { - private final JS5Queue queue; - private final int index; - private final int archive; - private final boolean priority; - - public Js5Request(JS5Queue queue, int index, int archive, boolean priority) { - this.queue = queue; - this.index = index; - this.archive = archive; - this.priority = priority; - } - } - - /** - * The I/O session. - */ - private final IoSession session; - - /** - * Constructs a new {@code JS5Queue} {@code Object}. - * @param session The I/O session. - */ - public JS5Queue(IoSession session) { - this.session = session; - } - - /** - * Queues a JS-5 request. - * Timers: - * 1000ms queue up files for this long - * 100ms release a file from the queue - * - * @param container The container. - * @param archive The archive. - * @param highPriority If the request is high priority. - * - */ - public void queue(int container, int archive, boolean highPriority) { - Js5Request request = new Js5Request(this, container, archive, highPriority); - handler.requests.add(request); - } - - /** - * Gets the session. - * @return the session - */ - public IoSession getSession() { - return session; - } - - -} \ No newline at end of file diff --git a/Server/src/main/java/core/net/event/JS5ReadEvent.java b/Server/src/main/java/core/net/event/JS5ReadEvent.java deleted file mode 100644 index ded5d14d5..000000000 --- a/Server/src/main/java/core/net/event/JS5ReadEvent.java +++ /dev/null @@ -1,81 +0,0 @@ -package core.net.event; - -import core.cache.misc.buffer.ByteBufferUtils; -import core.net.IoReadEvent; -import core.net.IoSession; - -import java.nio.ByteBuffer; - -/** - * Handles JS-5 reading events. - * @author Emperor - */ -public final class JS5ReadEvent extends IoReadEvent { - - /** - * Constructs a new {@code JS5ReadEvent}. - * @param session The session. - * @param buffer The buffer. - */ - public JS5ReadEvent(IoSession session, ByteBuffer buffer) { - super(session, buffer); - } - - @Override - public void read(IoSession session, ByteBuffer buffer) { - while (buffer.hasRemaining()) { - int opcode = buffer.get() & 0xFF; - //System.out.println("JS5 initiated! Opcode: " + opcode); - if (buffer.remaining() < 3) { - queueBuffer(opcode); - return; - } - switch (opcode) { - case 0: - case 1: - int request = ByteBufferUtils.getMedium(buffer); - //System.out.println("Requested file " + request); - int container = request >> 16 & 0xFF; - //System.out.println("In container " + container); - int archive = request & 0xFFFF; - //System.out.println("In archive " + archive); - session.getJs5Queue().queue(container, archive, opcode == 1); - break; - case 2: // music - case 3: // Music - buffer.get(); - buffer.getShort(); - break; - case 4: - session.setJs5Encryption(buffer.get()); - if (buffer.getShort() != 0) { - session.disconnect(); - return; - } - break; - case 5: - case 9: - if (buffer.remaining() < 4) { - queueBuffer(opcode); - return; - } - buffer.getInt(); - break; - case 6: - ByteBufferUtils.getMedium(buffer); // Value should be 3 - // buffer.getShort(); // Value should be 0 - break; - case 7: - buffer.get(); - buffer.getShort(); - session.disconnect(); - return; - default: - System.out.println("Unhandled JS5 opcode " + opcode + "!"); - buffer.get(); - buffer.getShort(); - break; - } - } - } -} \ No newline at end of file diff --git a/Server/src/main/java/core/net/event/JS5WriteEvent.java b/Server/src/main/java/core/net/event/JS5WriteEvent.java deleted file mode 100644 index bd0bd223f..000000000 --- a/Server/src/main/java/core/net/event/JS5WriteEvent.java +++ /dev/null @@ -1,71 +0,0 @@ -package core.net.event; - -import core.cache.Cache; -import core.net.IoSession; -import core.net.IoWriteEvent; - -import java.nio.ByteBuffer; - -/** - * Handles JS-5 writing events. - * @author Emperor - */ -public final class JS5WriteEvent extends IoWriteEvent { - - /** - * The cached reference data. - */ - private static byte[] cachedReference; - - /** - * Constructs a new {@code JS5WriteEvent}. - * @param session The session. - * @param context The event context. - */ - public JS5WriteEvent(IoSession session, Object context) { - super(session, context); - } - - @Override - public void write(IoSession session, Object context) { - int[] request = (int[]) context; - int container = request[0]; - int archive = request[1]; - boolean priority = request[2] == 1; - if (archive == 255 && container == 255) { - session.queue(getReferenceData()); - return; - } - ByteBuffer response = Cache.getArchiveData(container, archive, priority, session.getJs5Encryption()); - if (response != null) { - session.queue(response); - } - } - - /** - * Gets the reference data. - * @return The reference data. - */ - private static ByteBuffer getReferenceData() { - if (cachedReference == null) { - cachedReference = Cache.generateReferenceData(); - } - ByteBuffer buffer = ByteBuffer.allocate(cachedReference.length << 2); - buffer.put((byte) 255); - buffer.putShort((short) 255); - buffer.put((byte) 0); - buffer.putInt(cachedReference.length); - int offset = 10; - for (int index = 0; index < cachedReference.length; index++) { - if (offset == 512) { - buffer.put((byte) 255); - offset = 1; - } - buffer.put(cachedReference[index]); - offset++; - } - buffer.flip(); - return buffer; - } - -} \ No newline at end of file diff --git a/Server/src/main/java/core/net/packet/in/ExaminePacket.java b/Server/src/main/java/core/net/packet/in/ExaminePacket.java index c603c73d1..3356c6374 100644 --- a/Server/src/main/java/core/net/packet/in/ExaminePacket.java +++ b/Server/src/main/java/core/net/packet/in/ExaminePacket.java @@ -1,6 +1,5 @@ package core.net.packet.in; -import core.cache.Cache; import core.cache.def.impl.ItemDefinition; import core.cache.def.impl.NPCDefinition; import core.cache.def.impl.SceneryDefinition; @@ -8,7 +7,8 @@ import core.cache.def.impl.VarbitDefinition; import core.game.node.entity.player.Player; import core.net.packet.IncomingPacket; import core.net.packet.IoBuffer; -import org.rs09.consts.Items; +import rs09.cache.Cache; +import rs09.cache.CacheIndex; import java.util.Arrays; @@ -24,7 +24,7 @@ public final class ExaminePacket implements IncomingPacket { switch (buffer.opcode()) { case 94: // Object examine int id = buffer.getLEShortA(); - if (id < 0 || id > Cache.getObjectDefinitionsSize()) { + if (id < 0 || id > Cache.getIndexCapacity(CacheIndex.SCENERY_CONFIGURATION)) { break; } SceneryDefinition d = SceneryDefinition.forId(id); @@ -40,7 +40,7 @@ public final class ExaminePacket implements IncomingPacket { case 235: case 92: // Item examine id = buffer.getLEShortA(); - if (id < 0 || id > Cache.getItemDefinitionsSize()) { + if (id < 0 || id > Cache.getIndexCapacity(CacheIndex.ITEM_CONFIGURATION)) { break; } ItemDefinition itemDef = ItemDefinition.forId(id); @@ -48,7 +48,7 @@ public final class ExaminePacket implements IncomingPacket { break; case 72: // NPC examine id = buffer.getShort(); - if (id < 0 || id > Cache.getNPCDefinitionsSize()) { + if (id < 0 || id > Cache.getIndexCapacity(CacheIndex.NPC_CONFIGURATION)) { break; } player.debug("NPC id: " + id + "."); diff --git a/Server/src/main/java/core/net/producer/JS5EventProducer.java b/Server/src/main/java/core/net/producer/JS5EventProducer.java index 26cf8635a..413c754ee 100644 --- a/Server/src/main/java/core/net/producer/JS5EventProducer.java +++ b/Server/src/main/java/core/net/producer/JS5EventProducer.java @@ -4,8 +4,8 @@ import core.net.EventProducer; import core.net.IoReadEvent; import core.net.IoSession; import core.net.IoWriteEvent; -import core.net.event.JS5ReadEvent; -import core.net.event.JS5WriteEvent; +import rs09.net.event.js5.JS5ReadEvent; +import rs09.net.event.js5.JS5WriteEvent; import java.nio.ByteBuffer; diff --git a/Server/src/main/kotlin/rs09/cache/Cache.kt b/Server/src/main/kotlin/rs09/cache/Cache.kt new file mode 100644 index 000000000..53f8db881 --- /dev/null +++ b/Server/src/main/kotlin/rs09/cache/Cache.kt @@ -0,0 +1,81 @@ +package rs09.cache + +import com.displee.cache.CacheLibrary +import com.displee.cache.ProgressListener +import com.displee.cache.index.Index +import core.cache.def.impl.ItemDefinition +import core.cache.def.impl.SceneryDefinition +import rs09.game.system.SystemLogger +import rs09.net.event.js5.DataProvider +import java.nio.ByteBuffer + +object Cache { + + private lateinit var cacheLibrary: CacheLibrary + private lateinit var progressListener: ProgressListener + lateinit var versionTable: ByteArray + lateinit var provider: DataProvider + + @JvmStatic + fun init(cachePath: String?) { + progressListener = SystemLogger.CreateProgressListener() + cacheLibrary = CacheLibrary(cachePath.toString(), false, progressListener) + versionTable = generateUKeys() + provider = DataProvider(cacheLibrary) + parseDefinitions() + } + + private fun parseDefinitions() { + ItemDefinition.parse() + SceneryDefinition.parse() + } + + private fun generateUKeys(): ByteArray { + val buffer = ByteBuffer.allocate(cacheLibrary.indices().size * 8) + for (index in cacheLibrary.indices()) { + buffer.putInt(index.crc) + buffer.putInt(index.revision) + } + return buffer.array() + } + + fun getIndex(index: CacheIndex): Index { + return cacheLibrary.index(index.id) + } + + @JvmStatic + fun getData(index: CacheIndex, archive: Int, file: Int): ByteArray? { + return cacheLibrary.data(index.id, archive, file, null) + } + + @JvmStatic + fun getData(index: CacheIndex, archive: CacheArchive, file: Int): ByteArray? { + return cacheLibrary.data(index.id, archive.id, file, null) + } + + @JvmStatic + fun getData(index: CacheIndex, archive: String): ByteArray? { + return cacheLibrary.data(index.id, archive, 0) + } + + @JvmStatic + fun getData(index: CacheIndex, archive: String, xtea: IntArray): ByteArray? { + return cacheLibrary.data(index.id, archive, 0, xtea) + } + + @JvmStatic + fun getArchiveId(index: CacheIndex, archive: String): Int { + return cacheLibrary.index(index.id).archiveId(archive) + } + + @JvmStatic + fun getArchiveCapacity(index: CacheIndex, archive: CacheArchive): Int { + return cacheLibrary.index(index.id).archive(archive.id)?.files()?.size ?: -1 + } + + @JvmStatic + fun getIndexCapacity(index: CacheIndex): Int { + val lastArchive = (cacheLibrary.index(index.id).archives().last()) + return (lastArchive.files().size) + (lastArchive.id * 256) + } +} \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/cache/CacheArchive.kt b/Server/src/main/kotlin/rs09/cache/CacheArchive.kt new file mode 100644 index 000000000..c4fcdd57e --- /dev/null +++ b/Server/src/main/kotlin/rs09/cache/CacheArchive.kt @@ -0,0 +1,11 @@ +package rs09.cache + +enum class CacheArchive(val id: Int) { + FLOOR_UNDERLAYS(1), + PLAYER_KIT(3), + FLOOR_OVERLAYS(4), + INVENTORIES(5), + PARAM_TYPE(11), + STRUCT_TYPE(26), + BAS_TYPE(32) +} \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/cache/CacheIndex.kt b/Server/src/main/kotlin/rs09/cache/CacheIndex.kt new file mode 100644 index 000000000..76b322052 --- /dev/null +++ b/Server/src/main/kotlin/rs09/cache/CacheIndex.kt @@ -0,0 +1,31 @@ +package rs09.cache + +enum class CacheIndex(val id: Int) { + ANIMS(0), + BASES(1), + CONFIGURATION(2), + COMPONENTS(3), + SYNTH_SOUNDS(4), + MAPS(5), + MUSIC(6), + MODELS(7), + SPRITES(8), + TEXTURES(9), + HUFFMAN_ENCODING(10), + MIDI_JINGLES(11), + CLIENT_SCRIPTS(12), + FONTMETRICS(13), + VORBIS(14), + MIDI_INSTRUMENTS(15), + SCENERY_CONFIGURATION(16), + ENUM_CONFIGURATION(17), + NPC_CONFIGURATION(18), + ITEM_CONFIGURATION(19), + SEQUENCE_CONFIGURATION(20), + SPOTANIM_CONFIGURATION(21), + VARBIT_CONFIGURATION(22), + WORLD_MAP(23), + QUICKCHAT_MESSAGES(24), + QUICKCHAT_MENUS(25), + MATERIALS(26) +} \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/game/interaction/QCRepository.kt b/Server/src/main/kotlin/rs09/game/interaction/QCRepository.kt index efd921457..50e25d4ea 100644 --- a/Server/src/main/kotlin/rs09/game/interaction/QCRepository.kt +++ b/Server/src/main/kotlin/rs09/game/interaction/QCRepository.kt @@ -1,6 +1,5 @@ package rs09.game.interaction -import core.cache.Cache import core.cache.def.impl.DataMap import core.cache.def.impl.ItemDefinition import core.cache.def.impl.NPCDefinition @@ -11,6 +10,8 @@ import core.game.system.task.Pulse import core.game.world.update.flag.context.ChatMessage import core.game.world.update.flag.player.ChatFlag import proto.management.ClanMessage +import rs09.cache.Cache +import rs09.cache.CacheIndex import rs09.game.node.entity.skill.slayer.SlayerManager import rs09.game.world.GameWorld.Pulser import rs09.net.packet.`in`.QCPacketType @@ -24,7 +25,7 @@ import java.util.* * @author Ceikry */ object QCRepository { - private val quickChatIndex = Cache.getIndexes()[24] + private val quickChatIndex = Cache.getIndex(CacheIndex.QUICKCHAT_MESSAGES) /** * The entry method that connects to the other more specific methods @@ -314,7 +315,8 @@ object QCRepository { } } - private fun getQCString(index: Int): String{ - return ByteBufferUtils.getString(ByteBuffer.wrap(quickChatIndex.getFileData(1, index))) + private fun getQCString(index: Int): String { + val data = Cache.getData(CacheIndex.QUICKCHAT_MESSAGES, 1, index) + return ByteBufferUtils.getString(ByteBuffer.wrap(data)) } } \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/game/system/SystemLogger.kt b/Server/src/main/kotlin/rs09/game/system/SystemLogger.kt index 4ad223b2b..0fd7faf39 100644 --- a/Server/src/main/kotlin/rs09/game/system/SystemLogger.kt +++ b/Server/src/main/kotlin/rs09/game/system/SystemLogger.kt @@ -1,7 +1,8 @@ package rs09.game.system +import com.displee.cache.ProgressListener import com.github.ajalt.mordant.rendering.TextColors -import com.github.ajalt.mordant.terminal.* +import com.github.ajalt.mordant.terminal.Terminal import rs09.ServerConstants import java.io.BufferedWriter import java.io.File @@ -118,4 +119,28 @@ object SystemLogger { fun logMS(s: String) { if(s.isNotBlank()) t.println("${getTime()}: ${TextColors.gray("[ MS] $s")}") } + + @JvmStatic + fun logCache(message: String){ + val msg = "${getTime()}: [CacheOps] $message" + if(message.isNotBlank()) { + t.println(msg) + } + } + + @JvmStatic + fun logJS5(clazz: Class<*>, vararg messages: String){ + for(m in messages){ + val msg = "${getTime()}: [${clazz.simpleName}] $m" + if(m.isNotBlank()) { + t.println(msg) + } + } + } + + class CreateProgressListener: ProgressListener { + override fun notify(progress: Double, message: String?) { + logCache(message.toString()) + } + } } \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/game/system/command/oldsys/VisualCommand.kt b/Server/src/main/kotlin/rs09/game/system/command/oldsys/VisualCommand.kt index 33fcd3e77..47b05b118 100644 --- a/Server/src/main/kotlin/rs09/game/system/command/oldsys/VisualCommand.kt +++ b/Server/src/main/kotlin/rs09/game/system/command/oldsys/VisualCommand.kt @@ -1,17 +1,17 @@ package rs09.game.system.command.oldsys -import api.* -import core.cache.Cache +import api.sendMessage +import api.submitWorldPulse import core.game.container.access.InterfaceContainer import core.game.content.quest.tutorials.tutorialisland.CharacterDesign -import core.game.node.scenery.Scenery -import core.game.node.scenery.SceneryBuilder import core.game.node.entity.combat.ImpactHandler.HitsplatType import core.game.node.entity.impl.Projectile import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player import core.game.node.entity.player.link.audio.Audio import core.game.node.item.Item +import core.game.node.scenery.Scenery +import core.game.node.scenery.SceneryBuilder import core.game.system.command.CommandSet import core.game.system.task.Pulse import core.game.world.map.Location @@ -23,6 +23,8 @@ import core.net.packet.context.VarbitContext import core.net.packet.out.Varbit import core.plugin.Initializable import core.plugin.Plugin +import rs09.cache.Cache +import rs09.cache.CacheIndex import rs09.game.system.command.CommandPlugin import rs09.game.world.GameWorld import java.awt.Toolkit @@ -205,8 +207,9 @@ class VisualCommand : CommandPlugin() { return true } val componentId = toInteger(args[1]!!) - if (componentId < 0 || componentId > Cache.getInterfaceDefinitionsSize()) { - player!!.debug("Invalid component id [id=" + componentId + ", max=" + Cache.getInterfaceDefinitionsSize() + "].") + val componentArchiveSize = Cache.getIndexCapacity(CacheIndex.COMPONENTS) + if (componentId < 0 || componentId > componentArchiveSize) { + player!!.debug("Invalid component id [id=" + componentId + ", max=" + componentArchiveSize + "].") return true } player!!.interfaceManager.openComponent(componentId) diff --git a/Server/src/main/kotlin/rs09/game/system/command/sets/DevelopmentCommandSet.kt b/Server/src/main/kotlin/rs09/game/system/command/sets/DevelopmentCommandSet.kt index 1f2580227..203e757d2 100644 --- a/Server/src/main/kotlin/rs09/game/system/command/sets/DevelopmentCommandSet.kt +++ b/Server/src/main/kotlin/rs09/game/system/command/sets/DevelopmentCommandSet.kt @@ -1,11 +1,10 @@ package rs09.game.system.command.sets import api.sendMessage -import core.cache.Cache import core.cache.def.impl.DataMap import core.cache.def.impl.NPCDefinition -import core.cache.def.impl.VarbitDefinition import core.cache.def.impl.Struct +import core.cache.def.impl.VarbitDefinition import core.game.node.entity.combat.ImpactHandler.HitsplatType import core.game.node.entity.player.Player import core.game.node.entity.player.link.SpellBookManager @@ -17,12 +16,15 @@ import core.plugin.Initializable import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import org.rs09.consts.Items +import rs09.cache.Cache +import rs09.cache.CacheArchive +import rs09.cache.CacheIndex import rs09.game.system.SystemLogger import rs09.game.system.command.Privilege +import rs09.net.packet.PacketWriteQueue import java.io.BufferedWriter import java.io.File import java.io.FileWriter -import rs09.net.packet.PacketWriteQueue @Initializable class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) { @@ -85,13 +87,11 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) { define("dumpstructs", Privilege.ADMIN, "", "Dumps all the cache structs to structs.txt") {player, _ -> 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) + val amount = Cache.getArchiveCapacity(CacheIndex.CONFIGURATION, CacheArchive.STRUCT_TYPE) + for (structId in 0 until amount) { + val data = Cache.getData(CacheIndex.CONFIGURATION, CacheArchive.STRUCT_TYPE, structId) + if (data != null) { + val def = Struct.parse(structId, data) if(def.dataStore.isEmpty()) continue //no data in struct. writer.write(def.toString()) writer.newLine() @@ -102,24 +102,19 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) { } define("dumpdatamaps", Privilege.ADMIN, "", "Dumps all the cache data maps to datamaps.txt") {player, _ -> - val index = Cache.getIndexes()[17] - val containers = index.information.containersIndexes - + val amount = Cache.getIndexCapacity(CacheIndex.ENUM_CONFIGURATION) val dump = File("datamaps.txt") val writer = BufferedWriter(FileWriter(dump)) - 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() - } + for (enumId in 0 until amount) { + val archiveId = enumId shl 8 + val fileId = enumId and 0xFF + val data = Cache.getData(CacheIndex.ENUM_CONFIGURATION, archiveId, fileId) + if (data != null){ + val def = DataMap.parse(enumId, data) + if(def.keyType == '?') continue //Empty definition - only a 0 present in the cachefile data. + writer.write(def.toString()) + writer.newLine() } } writer.flush() diff --git a/Server/src/main/kotlin/rs09/game/system/command/sets/SpawnCommandSet.kt b/Server/src/main/kotlin/rs09/game/system/command/sets/SpawnCommandSet.kt index 2ea1dcdcb..8247e6885 100644 --- a/Server/src/main/kotlin/rs09/game/system/command/sets/SpawnCommandSet.kt +++ b/Server/src/main/kotlin/rs09/game/system/command/sets/SpawnCommandSet.kt @@ -1,14 +1,14 @@ package rs09.game.system.command.sets -import core.cache.Cache -import core.game.node.scenery.Scenery -import core.game.node.scenery.SceneryBuilder import core.game.node.entity.npc.NPC import core.game.node.item.Item -import rs09.game.system.SystemLogger -import rs09.game.system.command.Command -import rs09.game.system.command.CommandPlugin +import core.game.node.scenery.Scenery +import core.game.node.scenery.SceneryBuilder import core.plugin.Initializable +import rs09.cache.Cache +import rs09.cache.CacheIndex +import rs09.game.system.SystemLogger +import rs09.game.system.command.CommandPlugin import rs09.game.system.command.Privilege import java.awt.Toolkit import java.awt.datatransfer.StringSelection @@ -46,7 +46,7 @@ class SpawnCommandSet : CommandSet(Privilege.ADMIN){ } val id = args[1].toIntOrNull() ?: return@define var amount = (args.getOrNull(2) ?: "1").toInt() - if (id > Cache.getItemDefinitionsSize()) { + if (id > Cache.getIndexCapacity(CacheIndex.ITEM_CONFIGURATION)) { reject(player,"Item ID '$id' out of range.") return@define } diff --git a/Server/src/main/kotlin/rs09/game/world/GameWorld.kt b/Server/src/main/kotlin/rs09/game/world/GameWorld.kt index e32fc18a5..e4c87f653 100644 --- a/Server/src/main/kotlin/rs09/game/world/GameWorld.kt +++ b/Server/src/main/kotlin/rs09/game/world/GameWorld.kt @@ -1,7 +1,6 @@ package rs09.game.world import api.* -import core.cache.Cache import core.cache.def.impl.SceneryDefinition import core.game.node.entity.player.Player import core.game.system.SystemManager @@ -16,6 +15,7 @@ import core.tools.RandomFunction import rs09.ServerConstants import rs09.ServerStore import rs09.auth.AuthProvider +import rs09.cache.Cache import rs09.game.system.Auth import rs09.game.system.SystemLogger import rs09.game.system.SystemLogger.logInfo @@ -27,7 +27,6 @@ import rs09.worker.MajorUpdateWorker import java.text.SimpleDateFormat import java.util.* import java.util.function.Consumer -import kotlin.collections.ArrayList /** * Represents the game world. diff --git a/Server/src/main/kotlin/rs09/net/JagexBufTypesEXT.kt b/Server/src/main/kotlin/rs09/net/JagexBufTypesEXT.kt new file mode 100644 index 000000000..4119c1c9f --- /dev/null +++ b/Server/src/main/kotlin/rs09/net/JagexBufTypesEXT.kt @@ -0,0 +1,79 @@ +package rs09.net + +import java.nio.ByteBuffer + +/* Extension methods for the Java ByteBuffer + * These are the same method names used in the client for buffer operations + */ + +/** + * P1 - puts a byte to the buffer + * @param value as Byte + */ +fun ByteBuffer.p1(value: Byte) { + put(value) +} + +/** + * P1 - puts a byte to the buffer + * @param value as Int + */ +fun ByteBuffer.p1(value: Int) { + put(value.toByte()) +} + +/** + * G1 - gets an unsigned byte from the buffer + * @return value as Int + */ +fun ByteBuffer.g1(): Int { + return get().toInt() and 0xFF +} + +/** + * G1s - gets a signed byte from the buffer + * @return value as Int + */ +fun ByteBuffer.g1s(): Int { + return get().toInt() +} + +/** + * P2 - puts a short to the buffer + * @param value as Int + */ +fun ByteBuffer.p2(value: Int) { + putShort(value.toShort()) +} + +/** + * G2 - gets an unsigned short from the buffer + * @return value as Int + */ +fun ByteBuffer.g2(): Int { + return short.toInt() and 0xFFFF +} + +/** + * G2s - gets a signed short from the buffer + * @return value as Int + */ +fun ByteBuffer.g2s(): Int { + return short.toInt() +} + +/** + * G3 - gets an unsigned medium (3 bytes) from the buffer + * @return value as Int + */ +fun ByteBuffer.g3(): Int { + return ((get().toInt() and 0xFF) shl 16) + ((get().toInt() and 0xFF) shl 8) + (get().toInt() and 0xFF) +} + +/** + * P4 - puts an integer to the buffer + * @param value as Int + */ +fun ByteBuffer.p4(value: Int) { + putInt(value) +} \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/net/event/js5/DataProvider.kt b/Server/src/main/kotlin/rs09/net/event/js5/DataProvider.kt new file mode 100644 index 000000000..1fad468b7 --- /dev/null +++ b/Server/src/main/kotlin/rs09/net/event/js5/DataProvider.kt @@ -0,0 +1,18 @@ +package rs09.net.event.js5 + +import com.displee.cache.CacheLibrary + +interface DataProvider { + fun data(index: Int, archive: Int): ByteArray? + + companion object { + operator fun invoke(cache: CacheLibrary) = object : DataProvider { + override fun data(index: Int, archive: Int) = + if (index == 255) { + cache.index255?.readArchiveSector(archive)?.data + } else { + cache.index(index).readArchiveSector(archive)?.data + } + } + } +} \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/net/event/js5/JS5ReadEvent.kt b/Server/src/main/kotlin/rs09/net/event/js5/JS5ReadEvent.kt new file mode 100644 index 000000000..1d37c741c --- /dev/null +++ b/Server/src/main/kotlin/rs09/net/event/js5/JS5ReadEvent.kt @@ -0,0 +1,141 @@ +package rs09.net.event.js5 + +import core.net.IoReadEvent +import core.net.IoSession +import rs09.game.system.SystemLogger +import rs09.net.g1 +import rs09.net.g2 +import rs09.net.g3 +import java.nio.ByteBuffer + +class JS5ReadEvent(session: IoSession?, buffer: ByteBuffer?) : IoReadEvent(session, buffer) { + + override fun read(session: IoSession?, buffer: ByteBuffer?) { + if (session != null && buffer != null) { + while (buffer.hasRemaining()) { + when (val opcode = buffer.g1()) { + + /** + * OPCODE 0 - Prefetch file request (Low priority request) + * Handler for the prefetch file request opcode for the JS5 connection + * The request information (subUID) is contained in a medium. To decode + * first get the unsigned byte which is the Cache index ID, then read an unsigned short + * which is the archive ID. (or just a medium 3 bytes) + * + * On initial connection: + * -Prefetch will NEVER be the first request on initial connection + * + * After high priority sends 255 CRC info + user cache is incomplete: + * -We will start receiving files that the client does not need immediately + * + * Buffer size 4: [(byte) 0, (medium) request.subUID as Int] + */ + PREFETCH_REQUEST -> { + val value = buffer.g3() + val index = value shr 16 + val archive = value and 0xFFFF + session.write(Triple(index, archive, opcode == 0), true) + } + + /** + * OPCODE 1 - High priority file request + * Handler for the high priority file request opcode for the JS5 connection + * The request information (subUID) is contained in a medium. To decode + * first get the unsigned byte which is the Cache Index ID, then read an unsigned short + * which is the archive ID. + * + * On initial connection: + * -Requests index 255, archive 255 which contains the master record of index CRC information + * + * After 255 CRC info sent + user has a brand new cache: + * -We will start to receive requests for files the client needs IMMEDIATELY, i.e. login interfaces/music/models + * The client stores and knows what files it needs upon moving past the main menu/login screen + * + * Buffer size 4: [(byte) 1, (medium) request.subUID as Int] + */ + PRIORITY_REQUEST -> { + val value = buffer.g3() + val index = value shr 16 + val archive = value and 0xFFFF + session.write(Triple(index, archive, opcode == 0)) + } + + /** + * OPCODE 2 - Client logged in + * Handler for the client logged in opcode for the JS5 connection + * If the client gameState is NOT on stage 5 || 10 || 28 then it sends OP2 + * + * Buffer size 4: [(byte) 2, (medium) 0] + */ + STATUS_LOGGED_IN -> { + buffer.g3() + } + + /** + * OPCODE 3 - Client logged out + * Handler for the client logged out opcode for the JS5 connection + * If the client gameState is ON stage 5 || 10 || 28 then it sends OP3 + * + * Buffer size 4: [(byte) 3, (medium) 0] + */ + STATUS_LOGGED_OUT -> { + buffer.g3() + } + + /** + * OPCODE 4 - Encryption + * Handler for the encryption opcode for the JS5 connection + * The client sends a byte encryption key that we'll send out with the requests + * + * Buffer size 4: [(byte) 4, (byte) encryptionKey, (shortMirrored) 0] + */ + ENCRYPTED -> { + val value = buffer.g1() + val mark = buffer.g2() + if (mark != 0) { + SystemLogger.logErr(this::class.java, "[$opcode] mark [$mark] not 0!") + } + } + + /** + * OPCODE 6 - Connection Initialized + * Handler for the initial connection opcode for the JS5 connection + * We connect the client then clear the buffer by skipping the remaining 3 bytes + * + * Buffer size 4: [(byte) 6, (medium) 3] + */ + ACKNOWLEDGE -> { + buffer.g3() + } + + /** + * OPCODE 7 - Connection Disconnect + * Handler for the disconnection connection opcode for the JS5 connection + * This is only sent by request of a client command + * + * Buffer size 4: [(byte) 7, (medium) 3] + */ + DISCONNECT -> { + buffer.g3() + session.disconnect() + } + + else -> { + SystemLogger.logErr(this::class.java, "What the fuck is happening [$opcode]") + } + } + } + } + } + + companion object { + // Opcodes + const val PREFETCH_REQUEST = 0 + const val PRIORITY_REQUEST = 1 + const val STATUS_LOGGED_IN = 2 + const val STATUS_LOGGED_OUT = 3 + const val ENCRYPTED = 4 + const val ACKNOWLEDGE = 6 + const val DISCONNECT = 7 + } +} \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/net/event/js5/JS5WriteEvent.kt b/Server/src/main/kotlin/rs09/net/event/js5/JS5WriteEvent.kt new file mode 100644 index 000000000..e42a74328 --- /dev/null +++ b/Server/src/main/kotlin/rs09/net/event/js5/JS5WriteEvent.kt @@ -0,0 +1,89 @@ +package rs09.net.event.js5 + +import core.net.IoSession +import core.net.IoWriteEvent +import rs09.cache.Cache.provider +import rs09.cache.Cache.versionTable +import rs09.game.system.SystemLogger +import rs09.net.p1 +import rs09.net.p2 +import rs09.net.p4 +import java.nio.ByteBuffer +import kotlin.math.min + +class JS5WriteEvent(session: IoSession?, context: Any?) : IoWriteEvent(session, context) { + + override fun write(session: IoSession, context: Any) { + val request = context as Triple<*, *, *> + val index = request.first as Int + val archive = request.second as Int + val priority = request.third as Boolean + val data = data(index, archive) ?: return SystemLogger.logErr(this::class.java,"Unable to fulfill request $index $archive $priority.") + if (index == 255 && archive == 255) { + val buffer = serve255(data) + session.queue(buffer) + } else { + val buffer = serve(index, archive, data, priority) + session.queue(buffer) + } + return + } + + /** + * @return data for an [index]'s [archive] file or [versionTable] when index and archive are both 255 + */ + fun data(index: Int, archive: Int): ByteArray? { + if (index == 255 && archive == 255) { + return versionTable + } + return provider.data(index, archive) + } + + /** + * Serve255 - Prepares a buffer to send the version table data + * + * @param data - The binary data retrieved from the cache + * @return buffer containing version table information + */ + private fun serve255(data: ByteArray): ByteBuffer { + val buffer = ByteBuffer.allocate(8 + data.size) + buffer.p1(255) + buffer.p2(255) + buffer.p1(0) + buffer.p4(data.size) + buffer.put(data) + buffer.flip() + return buffer + } + + fun serve(index: Int, archive: Int, data: ByteArray, prefetch: Boolean): ByteBuffer { + val compression = data[0].toInt() + val size = getInt(data[1], data[2], data[3], data[4]) + if (compression != 0) 8 else 4 // 9 : 5? + val buffer = ByteBuffer.allocate((size + 5) + (size / 512) + 10) + buffer.p1(index) + buffer.p2(archive) + buffer.p1((if (prefetch) compression or 0x80 else compression)) + + var length = min(size, SPLIT - HEADER) + buffer.put(data, OFFSET, length) + var written = length + + while (written < size) { + buffer.p1(SEPARATOR) + length = if (size - written < SPLIT) size - written else SPLIT - 1 + buffer.put(data, written + OFFSET, length) + written += length + } + buffer.flip() + return buffer + } + + companion object { + private fun getInt(b1: Byte, b2: Byte, b3: Byte, b4: Byte) = b1.toInt() shl 24 or (b2.toInt() and 0xff shl 16) or (b3.toInt() and 0xff shl 8) or (b4.toInt() and 0xff) + + private const val SEPARATOR = 255 + private const val HEADER = 4 + private const val SPLIT = 512 + private const val OFFSET = 1 + } +} \ No newline at end of file diff --git a/Server/src/test/kotlin/RegionTests.kt b/Server/src/test/kotlin/RegionTests.kt index 44d42e61a..25669daaa 100644 --- a/Server/src/test/kotlin/RegionTests.kt +++ b/Server/src/test/kotlin/RegionTests.kt @@ -1,14 +1,8 @@ -import core.cache.Cache import core.game.world.map.Region -import core.game.world.map.RegionChunk import core.game.world.map.RegionManager import core.game.world.map.build.DynamicRegion -import core.game.world.map.build.LandscapeParser -import org.junit.Assert import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test -import rs09.game.system.config.ServerConfigParser -import rs09.game.system.config.XteaParser class RegionTests { companion object { diff --git a/Server/src/test/kotlin/TestUtils.kt b/Server/src/test/kotlin/TestUtils.kt index 53e1454de..8bc3b04b4 100644 --- a/Server/src/test/kotlin/TestUtils.kt +++ b/Server/src/test/kotlin/TestUtils.kt @@ -1,4 +1,4 @@ -import core.cache.Cache + import core.cache.crypto.ISAACCipher import core.cache.crypto.ISAACPair import core.game.node.entity.player.Player @@ -10,6 +10,7 @@ import core.net.IoSession import core.net.packet.IoBuffer import org.rs09.consts.Items import rs09.ServerConstants +import rs09.cache.Cache import rs09.game.content.global.shops.Shop import rs09.game.content.global.shops.ShopItem import rs09.game.system.SystemLogger @@ -18,7 +19,6 @@ import rs09.game.system.config.ServerConfigParser import rs09.game.world.GameWorld import rs09.game.world.repository.Repository import rs09.game.world.update.UpdateSequence -import java.io.File import java.net.URI import java.nio.ByteBuffer