Fixes and more (#69)

* Fixes

Fixed #11 and implemented a beta command for testing (stops the need to go into database and manually change  when debugging, very slow, now one command in game, very fast)

* Space to continue

Does what it says on the tin!

* Fixes + more

What I've done this update:
- Fixed tutorial island's chef giving infinite amounts of buckets and water to players
- Fixed fishing without a tool.
- Added the wilderness teleport lever to Edgeville south of the bank (as some have requested)
- Added some useful tools for editing cache.

Enjoy!
This commit is contained in:
Jamix77 2020-01-26 21:30:32 +00:00 committed by Daniel Ginovker
parent 34a24140c1
commit 0fc8d6ee4c
1207 changed files with 66670 additions and 27 deletions

View file

@ -0,0 +1,165 @@
package alex;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import alex.cache.CacheFile;
import alex.cache.FileOnDisk;
import alex.cache.FileSystem;
import alex.cache.SeekableFile;
import alex.cache.loaders.ItemDefinition;
import alex.cache.updateServer.UpdateServer;
import alex.io.Stream;
import alex.util.Methods;
/*
* ----------\_/--------------
* ----------/-\--------------
* -------|-/@.@\-|----------
* ---------\___/-------------
* ALL CREDITS TO ALEX(DRAGONKK)
* CREATED DATA 15/04/2011
* @@alex_dkk@hotmail.com@@
* ----------------------------
* ----------------------------
* ----------------------------
*/
public class CacheLoader {
private static final String cachePath = "data/cache/";
public static SeekableFile dataFile;
private static final FileSystem[] fileSystems = new FileSystem[30];
public static final SeekableFile[] indexFiles = new SeekableFile[getFileSystems().length];
public static boolean OLD_CACHE;
private static CacheFile referenceCache;
private static SeekableFile referenceFile;
public static void main(String[] args) {
if (args.length < 2) {
System.out.println("Parameters: isOldCache[bool], preload[bool]");
return;
}
OLD_CACHE = Boolean.parseBoolean(args[0]);
boolean preload = Boolean.parseBoolean(args[1]);
if (load(preload)) {
makeTests();
}
}
public static boolean putItemOnCache(ItemDefinition item) {
return fileSystems[Methods.ITEMDEF_IDX_ID].putFile(item.id >>> 8, 0xff & item.id, null, 2, item.packItemDefinition());
}
public static void makeTests() {
ItemDefinition dragonkkAgsDefinition = new ItemDefinition(11694);
System.out.println("DragonkkAgs: "+dragonkkAgsDefinition.getName());
dragonkkAgsDefinition.setName("Dragonkk's AGS");
dragonkkAgsDefinition.id = Methods.getAmountOfItems(); //a new item :o
dragonkkAgsDefinition.inventoryOptions[0] = "kill Noobs";
dragonkkAgsDefinition.inventoryOptions[1] = "I love cakes";
dragonkkAgsDefinition.inventoryOptions[2] = "unban flamable please <3";
System.out.println("DragonkkAgs Id: "+dragonkkAgsDefinition.id);
System.out.println(putItemOnCache(dragonkkAgsDefinition));
byte[] ukeys = generateUkeysFile();
System.out.println("UKEYS: "+Arrays.toString(ukeys));
/*byte[] whipData = fileSystems[19].getFile(4151 >>> 8, 0xff & 4151, null);
if(fileSystems[19].putFile(11694 >>> 8, 0xff & 11694, null, 2, whipData))
System.out.println("Packed sucefully.");*/
}
public static byte[] generateUkeysFile() {
return UpdateServer.getReadyForSendFile(255, 255, 0, generateUkeysContainer());
}
public static byte[] generateUkeysContainer() {
Stream stream = new Stream(5+fileSystems.length * 8);
for(int index = 0; index < fileSystems.length; index++) {
if(fileSystems[index] == null) {
stream.putInt(0);
stream.putInt(0);
}
byte[] buffer = CacheLoader.getReferenceCache().readFile(index);
stream.putInt(Methods.getCrc(buffer, buffer.length));
stream.putInt(fileSystems[index].referenceTable.revision);
}
byte[] ukeysFile = new byte[stream.offset];
stream.offset = 0;
stream.getBytes(ukeysFile, 0, ukeysFile.length);
return ukeysFile;
}
private static void createFileSystems() {
for (int id = 0; id < getFileSystems().length; id++) {
if (indexFiles[id] == null)
continue;
boolean discardEntryBuffers = false;
if (id == 5 || id == 6 || id == 23 || id == 26 || id == 28)
discardEntryBuffers = true;
getFileSystems()[id] = new FileSystem(id, discardEntryBuffers, 1);
}
}
public static FileSystem[] getFileSystems() {
return fileSystems;
}
public static CacheFile getReferenceCache() {
return referenceCache;
}
public static boolean load(boolean preload) {
File[] files = new File(cachePath).listFiles();
for (File file : files) {
if (file.getName().startsWith("main_file_cache.idx")) {
if (file.length() == 0)
continue;
try {
try {
int id = Integer
.parseInt(file.getName().split(".idx")[1]);
if (id == 255)
referenceFile = new SeekableFile(new FileOnDisk(file), 6000, 0);
else if (id < fileSystems.length)
indexFiles[id] = new SeekableFile(new FileOnDisk(file), 6000, 0);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
} else if (file.getName().equals("main_file_cache.dat2")) {
try {
dataFile = new SeekableFile(new FileOnDisk(file), 5200, 0);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
if (dataFile == null)
return false;
if (referenceFile == null)
return false;
referenceCache = new CacheFile(255, dataFile, referenceFile, 0x7a120);
createFileSystems();
if(preload) {
for(int index = 0; index < fileSystems.length; index++) {
if(fileSystems[index] == null)
continue;
fileSystems[index].filesCompleted();
}
}
return true;
}
}

View file

@ -0,0 +1,215 @@
package alex.cache;
import java.io.EOFException;
import java.io.IOException;
import alex.io.Stream;
import alex.util.Methods;
public class CacheFile {
public static byte cacheFileBuffer[] = new byte[520];
private int cacheId;
private SeekableFile dataFile;
private SeekableFile indexFile;
private int maxLength;
public CacheFile(int cacheId, SeekableFile dataFile, SeekableFile indexFile, int length) {
this.indexFile = indexFile;
this.maxLength = length;
this.dataFile = dataFile;
this.cacheId = cacheId;
}
public final byte[] readFile(int file) {
synchronized (dataFile) {
try {
if (indexFile.getFileLength() < (6 * file + 6)) {
return null;
}
indexFile.seek(6 * file);
indexFile.read(CacheFile.cacheFileBuffer, 0, 6);
int fileSize = (CacheFile.cacheFileBuffer[2] & 0xff)
+ (((0xff & CacheFile.cacheFileBuffer[0]) << 16) + (CacheFile.cacheFileBuffer[1] << 8 & 0xff00));
int sector = ((CacheFile.cacheFileBuffer[3] & 0xff) << 16)
- (-(0xff00 & CacheFile.cacheFileBuffer[4] << 8) - (CacheFile.cacheFileBuffer[5] & 0xff));
if (fileSize < 0 || fileSize > maxLength) {
return null;
}
if (sector <= 0
|| dataFile.getFileLength() / 520L < sector) {
return null;
}
byte buffer[] = new byte[fileSize];
int dataRead = 0;
int part = 0;
while (fileSize > dataRead) {
if (sector == 0) {
return null;
}
dataFile.seek(520 * sector);
int dataToRead = fileSize - dataRead;
if (dataToRead > 512) {
dataToRead = 512;
}
dataFile.read(CacheFile.cacheFileBuffer, 0, 8 + dataToRead);
int currentFile = (0xff & CacheFile.cacheFileBuffer[1])
+ (0xff00 & CacheFile.cacheFileBuffer[0] << 8);
int currentPart = ((CacheFile.cacheFileBuffer[2] & 0xff) << 8)
+ (0xff & CacheFile.cacheFileBuffer[3]);
int nextSector = (CacheFile.cacheFileBuffer[6] & 0xff)
+ (0xff00 & CacheFile.cacheFileBuffer[5] << 8)
+ ((0xff & CacheFile.cacheFileBuffer[4]) << 16);
int currentCache = CacheFile.cacheFileBuffer[7] & 0xff;
if (file != currentFile || currentPart != part
|| cacheId != currentCache) {
return null;
}
if (nextSector < 0
|| (dataFile.getFileLength() / 520L) < nextSector) {
return null;
}
for (int l2 = 0; dataToRead > l2; l2++) {
buffer[dataRead++] = CacheFile.cacheFileBuffer[8 + l2];
}
part++;
sector = nextSector;
}
return buffer;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
@Override
public final String toString() {
return "Cache:" + cacheId;
}
public boolean writeFile(int file, int compression, byte[] data, int version, int[] keys) {
byte[] readyFileData = Methods.packContainer(compression, data);
if (keys != null && (~keys[0] != -1 || keys[1] != 0 || keys[2] != 0 || ~keys[3] != -1)) {
Stream stream = new Stream(readyFileData);
stream.encodeXTEA(keys);
}
readyFileData[readyFileData.length - 2] = (byte) (version >>> 8);
readyFileData[readyFileData.length - 1] = (byte) version;
return writeFile(file, readyFileData, readyFileData.length);
}
private final boolean writeFile(int file, byte buffer[], int fileSize) {
synchronized (dataFile) {
if (fileSize < 0 || maxLength < fileSize) {
throw new IllegalArgumentException();
}
boolean succ = writeFile(file, buffer, fileSize, true);
if (!succ) {
succ = writeFile(file, buffer, fileSize, false);
}
return succ;
}
}
private final boolean writeFile(int file, byte buffer[], int fileSize,
boolean exists) {
synchronized (dataFile) {
try {
int sector;
if (!exists) {
sector = (int) ((dataFile.getFileLength() + 519L) / 520L);
if (sector == 0) {
sector = 1;
}
} else {
if ((6 * file + 6) > indexFile.getFileLength()) {
return false;
}
indexFile.seek(file * 6);
indexFile.read(CacheFile.cacheFileBuffer, 0, 6);
sector = (CacheFile.cacheFileBuffer[5] & 0xff)
+ (((CacheFile.cacheFileBuffer[4] & 0xff) << 8) + (CacheFile.cacheFileBuffer[3] << 16 & 0xff0000));
if (sector <= 0
|| sector > dataFile.getFileLength() / 520L) {
return false;
}
}
CacheFile.cacheFileBuffer[1] = (byte) (fileSize >> 8);
CacheFile.cacheFileBuffer[3] = (byte) (sector >> 16);
CacheFile.cacheFileBuffer[2] = (byte) fileSize;
CacheFile.cacheFileBuffer[0] = (byte) (fileSize >> 16);
CacheFile.cacheFileBuffer[4] = (byte) (sector >> 8);
CacheFile.cacheFileBuffer[5] = (byte) sector;
indexFile.seek(file * 6);
indexFile.write(CacheFile.cacheFileBuffer, 0, 6);
int dataWritten = 0;
for (int part = 0; dataWritten < fileSize; part++) {
int nextSector = 0;
if (exists) {
dataFile.seek(sector * 520);
try {
dataFile.read(CacheFile.cacheFileBuffer, 0, 8);
} catch (EOFException e) {
e.printStackTrace();
break;
}
int currentFile = (0xff & CacheFile.cacheFileBuffer[1])
+ (0xff00 & CacheFile.cacheFileBuffer[0] << 8);
int currentPart = (0xff & CacheFile.cacheFileBuffer[3])
+ (0xff00 & CacheFile.cacheFileBuffer[2] << 8);
nextSector = ((0xff & CacheFile.cacheFileBuffer[4]) << 16)
+ (((0xff & CacheFile.cacheFileBuffer[5]) << 8) + (0xff & CacheFile.cacheFileBuffer[6]));
int currentCache = CacheFile.cacheFileBuffer[7] & 0xff;
if (currentFile != file || part != currentPart
|| cacheId != currentCache) {
return false;
}
if (nextSector < 0
|| dataFile.getFileLength() / 520L < nextSector) {
return false;
}
}
if (nextSector == 0) {
exists = false;
nextSector = (int) ((dataFile.getFileLength() + 519L) / 520L);
if (nextSector == 0) {
nextSector++;
}
if (nextSector == sector) {
nextSector++;
}
}
CacheFile.cacheFileBuffer[3] = (byte) part;
if (fileSize - dataWritten <= 512) {
nextSector = 0;
}
CacheFile.cacheFileBuffer[0] = (byte) (file >> 8);
CacheFile.cacheFileBuffer[1] = (byte) file;
CacheFile.cacheFileBuffer[2] = (byte) (part >> 8);
CacheFile.cacheFileBuffer[7] = (byte) cacheId;
CacheFile.cacheFileBuffer[4] = (byte) (nextSector >> 16);
CacheFile.cacheFileBuffer[5] = (byte) (nextSector >> 8);
CacheFile.cacheFileBuffer[6] = (byte) nextSector;
dataFile.seek(sector * 520);
dataFile.write(CacheFile.cacheFileBuffer, 0, 8);
int dataToWrite = fileSize - dataWritten;
if (dataToWrite > 512) {
dataToWrite = 512;
}
dataFile.write(buffer, dataWritten, dataToWrite);
dataWritten += dataToWrite;
sector = nextSector;
}
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
}
}

View file

@ -0,0 +1,44 @@
package alex.cache;
import alex.CacheLoader;
import alex.util.Methods;
public class CacheFileWorker {
private CacheFile cache;
private int id;
private ReferenceTable referenceTable;
private int tableVersion;
public CacheFileWorker(int id) {
cache = new CacheFile(id, CacheLoader.dataFile, CacheLoader.indexFiles[id], 0xf4240);
this.id = id;
byte[] buffer = CacheLoader.getReferenceCache().readFile(id);
tableVersion = (buffer[buffer.length - 2] << 8 & 0xff00) + (buffer[-1 + buffer.length] & 0xff);
referenceTable = new ReferenceTable(buffer);
}
public byte[] getFileBuffer(int file) {
return cache.readFile(file);
}
public ReferenceTable getReferenceTable() {
return referenceTable;
}
public int generateTableFileVersion() {
tableVersion++;
return tableVersion;
}
public int getTableFileVersion() {
return tableVersion;
}
public boolean putFile(int fileId, int compression, byte[] data, int version) {
return putFile(fileId, compression, data, version, null);
}
public boolean putFile(int fileId, int compression, byte[] data, int version, int[] keys) {
return cache.writeFile(fileId, compression, data, version, keys);
}
}

View file

@ -0,0 +1,70 @@
package alex.cache;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
public class FileOnDisk {
private RandomAccessFile file;
private long length;
private long position;
private File wrappedFile;
public FileOnDisk(File wrappedFile) throws IOException {
this.wrappedFile = wrappedFile;
file = new RandomAccessFile(wrappedFile, "rw");
length = getFileLength();
}
public final void close() throws IOException {
if (file != null) {
file.close();
file = null;
}
}
@Override
protected final void finalize() throws Throwable {
if (file != null) {
System.out
.println("Warning! fileondisk "
+ wrappedFile
+ " not closed correctly using close(). Auto-closing instead. ");
close();
}
}
public final long getFileLength() throws IOException {
return file.length();
}
public final File getWrappedFile() {
return wrappedFile;
}
public final int read(byte buffer[], int off, int len) throws IOException {
int k = file.read(buffer, off, len);
if (k > 0) {
position += k;
}
return k;
}
public final void seek(long l) throws IOException {
file.seek(l);
position = l;
}
public final void write(byte buffer[], int off, int len) throws IOException {
//we gonna write so size wil get bigger
/*if (length < len + position) {
file.seek(length);
file.write(1);
throw new EOFException();
}*/
file.write(buffer, off, len);
position += len;
}
}

View file

@ -0,0 +1,576 @@
package alex.cache;
import alex.CacheLoader;
import alex.io.Stream;
import alex.util.Methods;
public class FileSystem {
private Object childBuffers[][];
private boolean discardEntryBuffers;
private int discardUnpacked;
private Object entryBuffers[];
private int id;
public ReferenceTable referenceTable;
public CacheFileWorker worker;
public FileSystem(int id, boolean discardEntryBuffers, int discardUnpacked) {
if (discardUnpacked < 0 || discardUnpacked > 2)
throw new IllegalArgumentException("js5: Invalid value "
+ discardUnpacked + " supplied for discardunpacked");
this.id = id;
this.discardEntryBuffers = discardEntryBuffers;
this.discardUnpacked = discardUnpacked;
worker = new CacheFileWorker(id);
referenceTable = worker.getReferenceTable();
entryBuffers = new Object[referenceTable.entryIndexCount];
childBuffers = new Object[referenceTable.entryIndexCount][];
}
public void clearChildBuffer(int file) {
if (childBuffers != null) {
childBuffers[file] = null;
}
}
public void clearChildBuffers() {
if (childBuffers != null) {
for (int i = 0; childBuffers.length > i; i++) {
childBuffers[i] = null;
}
}
}
public void clearEntryBuffers() {
if (entryBuffers != null) {
for (int i = 0; i < entryBuffers.length; i++) {
entryBuffers[i] = null;
}
}
}
public void clearIdentifiers(boolean children, boolean entries) {
if (children) {
referenceTable.childIdentTables = null;
referenceTable.childIdentifiers = null;
}
if (entries) {
referenceTable.entryIdentifiers = null;
referenceTable.entryIdentTable = null;
}
}
public boolean filesCompleted() {
boolean complete = true;
for (int index = 0; referenceTable.entryIndices.length > index; index++) {
int file = referenceTable.entryIndices[index];
if (entryBuffers[file] == null) {
loadBuffer(file);
if (entryBuffers[file] == null)
complete = false;
}
}
return complete;
}
public int getChildCount() {
return referenceTable.childIndexCounts.length;
}
public int getChildIndexCount(int file) {
if (!validEntryIndex(file)) {
return 0;
}
return referenceTable.childIndexCounts[file];
}
final int[] getChildIndices(int file) {
int childIndices[] = referenceTable.childIndices[file];
if (childIndices == null) {
childIndices = new int[referenceTable.entryChildCounts[file]];
for (int index = 0; childIndices.length > index; index++)
childIndices[index] = index;
}
return childIndices;
}
public byte[] getFile(int file) {
if (referenceTable.childIndexCounts.length == 1) {
return getFile(0, file);
}
if (!validEntryIndex(file)) {
return null;
}
if (referenceTable.childIndexCounts[file] == 1) {
return getFile(file, 0);
} else {
throw new RuntimeException();
}
}
public byte[] getFile(int file, int child) {
return getFile(file, child, null);
}
/*
* packs all container, havnt finished this just use the other putfile which is fully done
*/
public boolean putFile(int fileId, int compression, byte[] unpackedContainer) {
int version = referenceTable.entryVersions[fileId]+1;
if(worker.putFile(fileId, compression, unpackedContainer, version)) {
referenceTable.entryVersions[fileId] = version;
byte[] packedBuffer = worker.getFileBuffer(fileId);
Methods.CRC32.reset();
Methods.CRC32.update(packedBuffer, 0, packedBuffer.length-2);
int crc = (int) Methods.CRC32.getValue();
referenceTable.entryCrcs[fileId] = crc;
byte[] packedTable = referenceTable.packTable();
return CacheLoader.getReferenceCache().writeFile(id, 2, packedTable, worker.generateTableFileVersion(), null);
}
return false;
}
public byte[] getFile(int file, int child, int keys[]) {
if (!validIndices(file, child)) {
return null;
}
if (childBuffers[file] == null || childBuffers[file][child] == null) {
boolean prepared = prepareChildBuffers(file, child, keys);
if (!prepared) {
loadBuffer(file);
boolean prepared1 = prepareChildBuffers(file, child, keys);
if (!prepared1) {
return null;
}
}
}
byte unwrapped[] = (byte[]) childBuffers[file][child];
if (discardUnpacked != 1) {
if (discardUnpacked == 2) {
childBuffers[file] = null;
}
} else {
childBuffers[file][child] = null;
if (referenceTable.childIndexCounts[file] == 1) {
childBuffers[file] = null;
}
}
return unwrapped;
}
public boolean putFile(int fileId, int child, int[] keys, int compression, byte[] data) {
return putFile(fileId, child, keys, compression, data, null, null);
}
public boolean putFile(int fileId, int childId, int[] keys, int compression, byte[] data, String fileName, String childName) {
if(!validEntryIndex(fileId))
referenceTable.expandTable(fileId+1);
int oldChildCount = referenceTable.entryChildCounts[fileId];
if (!validIndices(fileId, childId))
referenceTable.expandTableChilds(fileId, childId+1); //gonna create thid now
int childCount = referenceTable.entryChildCounts[fileId];
if (!validIndices(fileId, childId)) {
return false;
}
byte[] unpackedContainer;
if (childCount > 1) {
byte childBufferData[][] = null;
if(oldChildCount > 0) {
byte[] unpackedData = Methods.unpackContainer(worker.getFileBuffer(fileId));
int length = unpackedData.length;
int amtOfLoops = 0xff & unpackedData[--length];
length -= amtOfLoops * (oldChildCount * 4);
Stream stream = new Stream(unpackedData);
int childBufferLength[] = new int[oldChildCount];
stream.offset = length;
for (int l2 = 0; l2 < amtOfLoops; l2++) {
int offset = 0;
for (int childIndex = 0; oldChildCount > childIndex; childIndex++) {
offset += stream.getInt();
childBufferLength[childIndex] += offset;
}
}
childBufferData = new byte[oldChildCount][];
for (int childIndex = 0; childIndex < oldChildCount; childIndex++) {
childBufferData[childIndex] = new byte[childBufferLength[childIndex]];
childBufferLength[childIndex] = 0;
}
stream.offset = length;
int unpackedOff = 0;
for (int loop = 0; amtOfLoops > loop; loop++) {
int dataRead = 0;
for (int childIndex = 0; oldChildCount > childIndex; childIndex++) {
dataRead += stream.getInt();
System.arraycopy(unpackedData, unpackedOff, childBufferData[childIndex], childBufferLength[childIndex],dataRead);
unpackedOff += dataRead;
childBufferLength[childIndex] += dataRead;
}
}
}
//we setted new data
Stream outStream = new Stream(250000);
int amtOfLoops = 1; //dont change this
byte[][] childsData = new byte[childCount][];
if(childBufferData != null)
for(int index = 0; index < oldChildCount; index++)
childsData[index] = childBufferData[index];
childsData[childId] = data;
//added files data
for(int index = 0; index < childCount; index++) {
if(childsData[index] != null) {
for(int i = 0; i < childsData[index].length; i++) {
outStream.putByte(childsData[index][i]);
}
}
}
//added files lengths
int lastLength = 0;
for(int index = 0; index < childCount; index++) {
outStream.putInt((childsData[index] == null ? 0 : childsData[index].length)-lastLength);
lastLength = childsData[index] == null ? 0 : childsData[index].length;
}
outStream.putByte(amtOfLoops);
unpackedContainer = new byte[outStream.offset];
outStream.offset = 0;
outStream.getBytes(unpackedContainer, 0, unpackedContainer.length);
}else
unpackedContainer = data;
int version = referenceTable.entryVersions[fileId]+1;
if(worker.putFile(fileId, compression, unpackedContainer, version, keys)) {
referenceTable.entryVersions[fileId] = version;
byte[] packedBuffer = worker.getFileBuffer(fileId);
Methods.CRC32.reset();
Methods.CRC32.update(packedBuffer, 0, packedBuffer.length-2);
referenceTable.entryCrcs[fileId] = (int) Methods.CRC32.getValue();
if(referenceTable.identifierFlag != 0) {
referenceTable.entryIdentifiers[fileId] = fileName == null ? -1 : Methods.hashFile(fileName);
referenceTable.childIdentifiers[fileId][childId] = childName == null ? -1 : Methods.hashFile(childName);
}
CacheLoader.getReferenceCache().writeFile(id, 2, referenceTable.packTable(), worker.generateTableFileVersion(), null);
}
return true;
}
private final boolean prepareChildBuffers(int file, int child, int keys[]) {
if (!validEntryIndex(file)) {
return false;
}
if (entryBuffers[file] == null) {
return false;
}
int childCount = referenceTable.entryChildCounts[file];
int childIndices[] = referenceTable.childIndices[file];
if (childBuffers[file] == null) {
childBuffers[file] = new Object[referenceTable.childIndexCounts[file]];
}
Object buffers[] = childBuffers[file];
boolean prepared = true;
for (int childIndex = 0; childCount > childIndex; childIndex++) {
int childIndice;
if (childIndices == null) {
childIndice = childIndex;
} else {
childIndice = childIndices[childIndex];
}
if (buffers[childIndice] != null) {
continue;
}
prepared = false;
break;
}
if (prepared) {
return true;
}
byte unwrapped[];
if (keys != null && (~keys[0] != -1 || keys[1] != 0 || keys[2] != 0 || ~keys[3] != -1)) {
unwrapped = Methods.copyBuffer((byte[]) entryBuffers[file]);// Methods.unwrapBuffer(entryBuffers[file],
// true);
Stream stream = new Stream(unwrapped);
stream.decodeXTEA(keys, 5, stream.payload.length);
} else {
unwrapped = (byte[]) entryBuffers[file];// Methods.unwrapBuffer(entryBuffers[file],
// false);
}
byte unpackedData[];
try {
unpackedData = Methods.unpackContainer(unwrapped);
} catch (RuntimeException runtimeexception) {
throw runtimeexception;
}
if (discardEntryBuffers) {
entryBuffers[file] = null;
}
if (childCount > 1) {
if (discardUnpacked != 2) {
int length = unpackedData.length;
int amtOfLoops = 0xff & unpackedData[--length];
length -= amtOfLoops * (childCount * 4);
Stream stream = new Stream(unpackedData);
int childBufferOffset[] = new int[childCount];
stream.offset = length;
for (int l2 = 0; l2 < amtOfLoops; l2++) {
int childLength = 0;
for (int childIndex = 0; childCount > childIndex; childIndex++) {
childLength += stream.getInt();
// System.out.println(childLength);
childBufferOffset[childIndex] += childLength;
// System.out.println(offset);
}
}
byte childBufferData[][] = new byte[childCount][];
for (int childIndex = 0; childIndex < childCount; childIndex++) {
childBufferData[childIndex] = new byte[childBufferOffset[childIndex]];
childBufferOffset[childIndex] = 0;
}
stream.offset = length;
int unpackedOff = 0;
for (int loop = 0; amtOfLoops > loop; loop++) {
int dataRead = 0;
for (int childIndex = 0; childCount > childIndex; childIndex++) {
dataRead += stream.getInt();
System.arraycopy(unpackedData, unpackedOff, childBufferData[childIndex], childBufferOffset[childIndex],dataRead);
unpackedOff += dataRead;
childBufferOffset[childIndex] += dataRead;
}
}
for (int index = 0; childCount > index; index++) {
int childIndice;
if (childIndices != null) {
childIndice = childIndices[index];
} else {
childIndice = index;
}
if (discardUnpacked != 0) {
buffers[childIndice] = childBufferData[index];
} else {
buffers[childIndice] = childBufferData[index];// Methods.wrapBuffer(childBufs[j6],
// false);
}
}
//after here useless
} else {
int unpackedLength = unpackedData.length;
int lastUnpackedByte = unpackedData[--unpackedLength] & 0xff;
unpackedLength -= lastUnpackedByte * childCount * 4;
Stream stream_2 = new Stream(unpackedData);
int childOffset = 0;
stream_2.offset = unpackedLength;
int childIndice = 0;
for (int k3 = 0; k3 < lastUnpackedByte; k3++) {
int dataLength = 0;
for (int childIndex = 0; childCount > childIndex; childIndex++) {
dataLength += stream_2.getInt();
int thisChildIndice;
if (childIndices != null) {
thisChildIndice = childIndices[childIndex];
} else {
thisChildIndice = childIndex;
}
if (child == thisChildIndice) {
childIndice = thisChildIndice;
childOffset += dataLength;
}
}
}
if (childOffset == 0) {
return true;
}
byte childBufferData[] = new byte[childOffset];
stream_2.offset = unpackedLength;
childOffset = 0;
int unpackedOffset = 0;
for (int l5 = 0; l5 < lastUnpackedByte; l5++) {
int dataLength = 0;
for (int childIndex = 0; childIndex < childCount; childIndex++) {
dataLength += stream_2.getInt();
int thisChildIndice;
if (childIndices == null) {
thisChildIndice = childIndex;
} else {
thisChildIndice = childIndices[childIndex];
}
if (thisChildIndice == child) {
System.arraycopy(unpackedData, unpackedOffset, childBufferData, childOffset, dataLength);
childOffset += dataLength;
}
unpackedOffset += dataLength;
}
}
buffers[childIndice] = childBufferData;
}
} else {
int l1;
if (childIndices != null) {
l1 = childIndices[0];
} else {
l1 = 0;
}
if (discardUnpacked == 0) {
buffers[l1] = unpackedData;// Methods.wrapBuffer(unpacked, false);
} else {
buffers[l1] = unpackedData;
}
}
return true;
}
public byte[] getFile(String fileName, String childName) {
fileName = fileName.toLowerCase();
childName = childName.toLowerCase();
int file = referenceTable.entryIdentTable.lookupIdentifier(Methods.hashFile(fileName));
if (!validEntryIndex(file)) {
return null;
} else {
int child = referenceTable.childIdentTables[file].lookupIdentifier(Methods.hashFile(childName));
return getFile(file, child);
}
}
private final int getFileCompletion(int file) {
if (entryBuffers[file] != null) {
return 100;
} else {
return 0;
}
}
public int getFileCompletion(String name) {
name = name.toLowerCase();
int file = referenceTable.entryIdentTable.lookupIdentifier(Methods
.hashFile(name));
return getFileCompletion(file);
}
public int getFileIndex(int ident) {
int file = referenceTable.entryIdentTable.lookupIdentifier(ident);
if (!validEntryIndex(file)) {
return -1;
}
return file;
}
public int getFileIndex(String name) {
name = name.toLowerCase();
int index = referenceTable.entryIdentTable.lookupIdentifier(Methods
.hashFile(name));
if (!validEntryIndex(index))
return -1;
else
return index;
}
public int getReferenceCrc() {
return referenceTable.crc;
}
public int getTotalCompletion() {
int total = 0;
int completed = 0;
for (int k = 0; k < entryBuffers.length; k++) {
if (referenceTable.entryChildCounts[k] > 0) {
total += 100;
completed += getFileCompletion(k);
}
}
if (total == 0) {
return 100;
} else {
return (completed * 100) / total;
}
}
public boolean hasEntryBuffer(int file) {
if (referenceTable.childIndexCounts.length == 1) {
return hasEntryBuffer(0, file);
}
if (!validEntryIndex(file)) {
return false;
}
if (referenceTable.childIndexCounts[file] == 1) {
return hasEntryBuffer(file, 0);
} else {
throw new RuntimeException();
}
}
public boolean hasEntryBuffer(int file, int child) {
if (!validIndices(file, child)) {
return false;
}
if (childBuffers[file] != null && childBuffers[file][child] != null) {
return true;
}
if (entryBuffers[file] != null) {
return true;
}
loadBuffer(file);
return entryBuffers[file] != null;
}
final boolean hasEntryBuffer(String fileName, String childName) {
fileName = fileName.toLowerCase();
childName = childName.toLowerCase();
int file = referenceTable.entryIdentTable.lookupIdentifier(Methods
.hashFile(fileName));
if (!validEntryIndex(file)) {
return false;
}
int child = referenceTable.childIdentTables[file]
.lookupIdentifier(Methods.hashFile(childName));
return hasEntryBuffer(file, child);
}
final boolean hasFile(String name) {
name = name.toLowerCase();
int file = referenceTable.entryIdentTable.lookupIdentifier(Methods
.hashFile(name));
return file >= 0;
}
private boolean hasFileBuffer(int file) {
if (!validEntryIndex(file))
return false;
if (entryBuffers[file] != null)
return true;
loadBuffer(file);
return entryBuffers[file] != null;
}
private boolean hasFileBuffer(String name) {
name = name.toLowerCase();
int file = referenceTable.entryIdentTable.lookupIdentifier(Methods
.hashFile(name));
return hasFileBuffer(file);
}
public void loadBuffer(int file) {
entryBuffers[file] = worker.getFileBuffer(file);
}
private final boolean validEntryIndex(int file) {
if (file < 0 || referenceTable.childIndexCounts.length <= file
|| referenceTable.childIndexCounts[file] == 0)
return false;
return true;
}
private boolean validIndices(int file, int child) {
if (file < 0 || child < 0
|| referenceTable.childIndexCounts.length <= file
|| child >= referenceTable.childIndexCounts[file])
return false;
return true;
}
}

View file

@ -0,0 +1,333 @@
package alex.cache;
import alex.CacheLoader;
import alex.io.Stream;
import alex.util.LookupTable;
import alex.util.Methods;
public class ReferenceTable {
int childIdentifiers[][];
LookupTable childIdentTables[];
int childIndexCounts[];
int childIndices[][];
int crc;
int entryChildCounts[];
private int entryCount;
int entryCrcs[];
int entryIdentifiers[];
LookupTable entryIdentTable;
int entryIndexCount;
int entryIndices[];
public int entryVersions[];
public int revision;
private int protocol;
int identifierFlag;
private boolean needRevisionUpdate;
public ReferenceTable(byte buffer[]) {
crc = Methods.getCrc(buffer, buffer.length);
unpackTable(buffer);
}
/*
* notice if we make it smaller than actualy is we will loss alot of files information
*
*/
public byte[] packTable() {
Stream stream = new Stream(2500000);
if (CacheLoader.OLD_CACHE) {
stream.putByte(protocol);
if (protocol >= 6) {
if(needRevisionUpdate)
revision++;
stream.putInt(revision);
}
stream.putByte(identifierFlag);
stream.putShort(entryCount);
int lastEntryOffset = 0;
for (int i = 0; entryCount > i; i++) {
stream.putShort(entryIndices[i] - lastEntryOffset);
lastEntryOffset = entryIndices[i];
}
if (identifierFlag != 0) {
for (int index = 0; entryCount > index; index++) {
stream.putInt(entryIdentifiers[entryIndices[index]]);
}
}
for (int index = 0; index < entryCount; index++) {
stream.putInt(entryCrcs[entryIndices[index]]);
}
for (int index = 0; index < entryCount; index++) {
stream.putInt(entryVersions[entryIndices[index]]);
}
for (int index = 0; index < entryCount; index++) {
stream.putShort(entryChildCounts[entryIndices[index]]);
}
for (int index = 0; entryCount > index; index++) {
int indice = entryIndices[index];
int lastEntryChildOffset = 0;
for (int childIndex = 0; entryChildCounts[indice] > childIndex; childIndex++) {
int nextChildIndice = childIndices[indice] != null ? childIndices[indice][childIndex] : childIndex;
stream.putShort(nextChildIndice - lastEntryChildOffset);
lastEntryChildOffset = nextChildIndice;
}
}
if (identifierFlag != 0) {
for (int index = 0; index < entryCount; index++) {
int indice = entryIndices[index];
int entryChildCount = entryChildCounts[indice];
for (int childIndex = 0; childIndex < entryChildCount; childIndex++) {
int childIndice;
if (childIndices[indice] != null) {
childIndice = childIndices[indice][childIndex];
} else {
childIndice = childIndex;
}
stream.putInt(childIdentifiers[indice][childIndice]);
}
}
}
}
byte[] buffer = new byte[stream.offset];
stream.offset = 0;
stream.getBytes(buffer, 0, buffer.length);
needRevisionUpdate = false;
return buffer;
}
public void expandTable(int newEntryCount) {
int[] newEntryIndices = new int[newEntryCount];
int count = entryIndexCount - 1; //the old count
//copys the indices and creates new indices
System.arraycopy(entryIndices, 0, newEntryIndices, 0, entryIndices.length);
for(int index = entryIndices.length; index < newEntryIndices.length; index++) {
newEntryIndices[index] = index == 0 ? 1 : newEntryIndices[index-1]+1;
if (newEntryIndices[index] > count)
count = newEntryIndices[index];
}
//creates new stuff with new size
int newEntryIndexCount = count + 1;
int[] newChildIndexCounts = new int[newEntryIndexCount];
int[][] newChildIndices = new int[newEntryIndexCount][];
int[] newEntryVersions = new int[newEntryIndexCount];
int[] newEntryCrcs = new int[newEntryIndexCount];
int[] newEntryChildCounts = new int[newEntryIndexCount];
LookupTable newEntryIdentTable = null;
int[] newEntryIdentifiers = null;
if (identifierFlag != 0) {
newEntryIdentifiers = new int[newEntryIndexCount];
//sets default identifiers
for (int l1 = 0; l1 < newEntryIndexCount; l1++) {
newEntryIdentifiers[l1] = -1;
}
//copys the old entry identifiers
System.arraycopy(entryIdentifiers, 0, newEntryIdentifiers, 0, entryIdentifiers.length);
newEntryIdentTable = new LookupTable(newEntryIdentifiers);
}
//copys the old entrycrcs
System.arraycopy(entryCrcs, 0, newEntryCrcs, 0, entryCrcs.length);
//copys the old entryVersions
System.arraycopy(entryVersions, 0, newEntryVersions, 0, entryVersions.length);
//copys the old entryChildCounts
System.arraycopy(entryChildCounts, 0, newEntryChildCounts, 0, entryChildCounts.length);
for (int index = 0; newEntryCount > index; index++) {
int indice = newEntryIndices[index];
if(childIndices.length > indice) {
int entryChildCount = newEntryChildCounts[indice];
for (int childIndex = 0; entryChildCount > childIndex; childIndex++)
newChildIndices[indice] = childIndices[indice];
newChildIndexCounts[index] = childIndexCounts[indice];
}else{
int entryChildCount = newEntryChildCounts[indice];
newChildIndices[indice] = new int[entryChildCount];
newChildIndexCounts[index] = 1;
}
}
LookupTable[] newChildIdentTables = null;
int[][] newChildIdentifiers = null;
if (identifierFlag != 0) {
newChildIdentifiers = new int[1 + count][];
newChildIdentTables = new LookupTable[1 + count];
for (int index = 0; index < newEntryCount; index++) {
int indice = newEntryIndices[index];
int entryChildCount = newEntryChildCounts[indice];
newChildIdentifiers[indice] = new int[newChildIndexCounts[indice]];
for (int childIndex = 0; childIndex < newChildIndexCounts[indice]; childIndex++) {
newChildIdentifiers[indice][childIndex] = -1;
}
for (int childIndex = 0; childIndex < entryChildCount; childIndex++) {
int childIndice;
if (newChildIndices[indice] != null) {
childIndice = newChildIndices[indice][childIndex];
} else {
childIndice = childIndex;
}
if(newChildIdentifiers.length > indice)
newChildIdentifiers[indice][childIndice] = childIdentifiers[indice][childIndice];
}
newChildIdentTables[indice] = new LookupTable(newChildIdentifiers[indice]);
}
}
//sets the new entrys that were expanded
entryCount = newEntryCount;
entryIndices = newEntryIndices;
entryIndexCount = newEntryIndexCount;
childIndexCounts = newChildIndexCounts;
childIndices = newChildIndices;
entryVersions = newEntryVersions;
entryCrcs = newEntryCrcs;
entryChildCounts = newEntryChildCounts;
entryIdentTable = newEntryIdentTable;
entryIdentifiers = newEntryIdentifiers;
childIdentTables = newChildIdentTables;
childIdentifiers = newChildIdentifiers;
//on end
needRevisionUpdate = true;
}
public void expandTableChilds(int indice, int entryChildCount) {
int[] newChildIndices = new int[entryChildCount];
int count = childIndexCounts[indice] - 1;
if(childIndices[indice] != null)
System.arraycopy(childIndices[indice], 0, newChildIndices, 0, childIndices[indice].length);
for(int index = childIndices[indice] == null ? 0 : childIndices[indice].length; index < newChildIndices.length; index++) {
newChildIndices[index] = index == 0 ? 1 : newChildIndices[index-1]+1;
if (newChildIndices[index] > count)
count = newChildIndices[index];
}
int newChildIndexCounts = count+1;
int[] newChildIdentifiers = null;
LookupTable newChildIdentTable = null;
if (identifierFlag != 0) {
newChildIdentifiers = new int[newChildIndexCounts];
//sets default identifiers
for (int l1 = 0; l1 < newChildIndexCounts; l1++) {
newChildIdentifiers[l1] = -1;
}
//copys the old entry identifiers
if(childIdentifiers[indice] != null)
System.arraycopy(childIdentifiers[indice], 0, newChildIdentifiers, 0, childIdentifiers[indice].length);
newChildIdentTable = new LookupTable(newChildIdentifiers);
childIdentTables[indice] = newChildIdentTable;
childIdentifiers[indice] = newChildIdentifiers;
}
childIndices[indice] = newChildIndices;
childIndexCounts[indice] = newChildIndexCounts;
entryChildCounts[indice] = entryChildCount;
}
private void unpackTable(byte buffer[]) {
if (CacheLoader.OLD_CACHE) {
Stream stream = new Stream(Methods.unpackContainer(buffer));
protocol = stream.getUByte();
if (protocol != 5 && protocol != 6) {
throw new RuntimeException();
}
if (protocol < 6) {
revision = 0;
} else {
revision = stream.getInt();
}
identifierFlag = stream.getUByte();
entryCount = stream.getUShort();
int offset = 0;
entryIndices = new int[entryCount];
int count = -1;
for (int index = 0; entryCount > index; index++) {
entryIndices[index] = offset += stream.getUShort();
if (entryIndices[index] > count) {
count = entryIndices[index];
}
}
entryIndexCount = count + 1;
childIndexCounts = new int[entryIndexCount];
childIndices = new int[entryIndexCount][];
entryVersions = new int[entryIndexCount];
entryCrcs = new int[entryIndexCount];
entryChildCounts = new int[entryIndexCount];
if (identifierFlag != 0) {
entryIdentifiers = new int[entryIndexCount];
for (int l1 = 0; l1 < entryIndexCount; l1++) {
entryIdentifiers[l1] = -1;
}
for (int index = 0; entryCount > index; index++) {
entryIdentifiers[entryIndices[index]] = stream.getInt();
}
entryIdentTable = new LookupTable(entryIdentifiers);
}
for (int index = 0; index < entryCount; index++) {
entryCrcs[entryIndices[index]] = stream.getInt();
}
for (int index = 0; index < entryCount; index++) {
entryVersions[entryIndices[index]] = stream.getInt();
}
for (int index = 0; index < entryCount; index++) {
entryChildCounts[entryIndices[index]] = stream.getUShort();
}
for (int index = 0; entryCount > index; index++) {
int indice = entryIndices[index];
int childOffset = 0;
int entryChildCount = entryChildCounts[indice];
childIndices[indice] = new int[entryChildCount];
int childCount = -1;
for (int childIndex = 0; entryChildCount > childIndex; childIndex++) {
int childIndice = childIndices[indice][childIndex] = childOffset += stream.getUShort();
if (childIndice > childCount) {
childCount = childIndice;
}
}
childIndexCounts[indice] = childCount + 1;
if ((childCount + 1) == entryChildCount) {
childIndices[indice] = null;
}
}
if (identifierFlag != 0) {
childIdentifiers = new int[1 + count][];
childIdentTables = new LookupTable[1 + count];
for (int index = 0; index < entryCount; index++) {
int indice = entryIndices[index];
int entryChildCount = entryChildCounts[indice];
childIdentifiers[indice] = new int[childIndexCounts[indice]];
for (int childIndex = 0; childIndex < childIndexCounts[indice]; childIndex++) {
childIdentifiers[indice][childIndex] = -1;
}
for (int childIndex = 0; childIndex < entryChildCount; childIndex++) {
int childIndice;
if (childIndices[indice] != null) {
childIndice = childIndices[indice][childIndex];
} else {
childIndice = childIndex;
}
childIdentifiers[indice][childIndice] = stream.getInt();
}
childIdentTables[indice] = new LookupTable(childIdentifiers[indice]);
}
}
} else {
// TODO
}
}
}

View file

@ -0,0 +1,294 @@
package alex.cache;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
public class SeekableFile {
private byte aByteArray2745[];
private byte aByteArray2748[];
private long aLong2739;
private long aLong2741;
private long aLong2743;
private long aLong2750;
private int anInt2737;
private int anInt2749;
private FileOnDisk file;
private long fileLength;
private long position;
public SeekableFile(FileOnDisk fileOnDisk, int maxFileLength,
int unknownLength) throws IOException {
anInt2737 = 0;
aLong2741 = -1L;
aLong2743 = -1L;
file = fileOnDisk;
fileLength = aLong2750 = fileOnDisk.getFileLength();
aByteArray2748 = new byte[maxFileLength];
aByteArray2745 = new byte[unknownLength];
position = 0L;
}
final long getFileLength() {
return fileLength;
}
private final File getWrappedFile() {
return file.getWrappedFile();
}
private final void method2264() throws IOException {
anInt2749 = 0;
if (~position != ~aLong2739) {
file.seek(position);
aLong2739 = position;
}
aLong2741 = position;
while (~anInt2749 > ~aByteArray2748.length) {
int i = aByteArray2748.length - anInt2749;
if (i > 0xbebc200) {
i = 0xbebc200;
}
int j = file.read(aByteArray2748, anInt2749, i);
if (j == -1) {
break;
}
anInt2749 += j;
aLong2739 += j;
}
}
final void read(byte buffer[]) throws IOException {
read(buffer, 0, buffer.length);
}
final void read(byte buffer[], int off, int len) throws IOException {
try {
if (~buffer.length > ~(off + len)) {
throw new ArrayIndexOutOfBoundsException(-buffer.length + len
+ off);
}
if (~aLong2743 != 0L
&& position >= aLong2743
&& ~(position + len) >= ~(aLong2743 + anInt2737)) {
System.arraycopy(aByteArray2745, (int) (-aLong2743 + position),
buffer, off, len);
position += len;
return;
}
long l = position;
int k = off;
int i1 = len;
if (position >= aLong2741
&& position < aLong2741 + anInt2749) {
int j1 = (int) (anInt2749 + aLong2741 - position);
if (j1 > len) {
j1 = len;
}
System.arraycopy(aByteArray2748, (int) (-aLong2741 + position),
buffer, off, j1);
off += j1;
position += j1;
len -= j1;
}
if (aByteArray2748.length >= len) {
if (len > 0) {
method2264();
int k1 = len;
if (k1 > anInt2749) {
k1 = anInt2749;
}
System.arraycopy(aByteArray2748, 0, buffer, off, k1);
off += k1;
position += k1;
len -= k1;
}
} else {
file.seek(position);
aLong2739 = position;
while (len > 0) {
int l1 = file.read(buffer, off, len);
if (l1 == -1) {
break;
}
position += l1;
len -= l1;
aLong2739 += l1;
off += l1;
}
}
if (~aLong2743 != 0L) {
if (aLong2743 > position && len > 0) {
int i2 = (int) (-position + aLong2743) + off;
if (len + off < i2) {
i2 = off + len;
}
while (i2 > off) {
len--;
buffer[off++] = 0;
position++;
}
}
long l2 = -1L;
long l3 = -1L;
if (~l < ~aLong2743 || aLong2743 >= l + i1) {
if (~aLong2743 >= ~l && l < aLong2743 + anInt2737) {
l2 = l;
}
} else {
l2 = aLong2743;
}
if (aLong2743 + anInt2737 <= l
|| anInt2737 + aLong2743 > l + i1) {
if (i1 + l > aLong2743
&& ~(i1 + l) >= ~(aLong2743 + anInt2737)) {
l3 = l + i1;
}
} else {
l3 = aLong2743 + anInt2737;
}
if (l2 > -1L && ~l2 > ~l3) {
int j2 = (int) (-l2 + l3);
System.arraycopy(aByteArray2745, (int) (-aLong2743 + l2),
buffer, k + (int) (-l + l2), j2);
if (~position > ~l3) {
len = (int) (len - (l3 - position));
position = l3;
}
}
}
} catch (IOException ioexception) {
aLong2739 = -1L;
throw ioexception;
}
if (len > 0) {
throw new EOFException();
} else {
return;
}
}
private final void refresh() throws IOException {
if (~aLong2743 != 0L) {
if (aLong2739 != aLong2743) {
file.seek(aLong2743);
aLong2739 = aLong2743;
}
file.write(aByteArray2745, 0, anInt2737);
aLong2739 += anInt2737;
if (aLong2750 < aLong2739) {
aLong2750 = aLong2739;
}
long l = -1L;
long l1 = -1L;
if (aLong2743 < aLong2741
|| aLong2743 >= anInt2749 + aLong2741) {
if (~aLong2741 <= ~aLong2743
&& anInt2737 + aLong2743 > aLong2741) {
l = aLong2741;
}
} else {
l = aLong2743;
}
if (aLong2741 < anInt2737 + aLong2743
&& aLong2741 + anInt2749 >= anInt2737
+ aLong2743) {
l1 = aLong2743 + anInt2737;
} else if (~(anInt2749 + aLong2741) < ~aLong2743
&& ~(anInt2749 + aLong2741) >= ~(aLong2743 + anInt2737)) {
l1 = anInt2749 + aLong2741;
}
if (l > -1L && l1 > l) {
int i = (int) (l1 - l);
System.arraycopy(aByteArray2745, (int) (l - aLong2743),
aByteArray2748, (int) (l - aLong2741), i);
}
aLong2743 = -1L;
anInt2737 = 0;
}
}
final void seek(long l) throws IOException {
if (l < 0L) {
throw new IOException("Invalid seek to " + l + " in file "
+ getWrappedFile());
}
position = l;
}
final void write(byte buffer[], int off, int len) throws IOException {
try {
if (~(len + position) < ~fileLength) {
fileLength = len + position;
}
if (~aLong2743 != 0L
&& (position < aLong2743 || ~(anInt2737 + aLong2743) > ~position)) {
refresh();
}
if (~aLong2743 != 0L
&& ~(aLong2743 + aByteArray2745.length) > ~(position + len)) {
int l = (int) (aByteArray2745.length - (position - aLong2743));
System.arraycopy(buffer, off, aByteArray2745,
(int) (position - aLong2743), l);
off += l;
len -= l;
position += l;
anInt2737 = aByteArray2745.length;
refresh();
}
if (~len < ~aByteArray2745.length) {
if (position != aLong2739) {
file.seek(position);
aLong2739 = position;
}
file.write(buffer, off, len);
aLong2739 += len;
if (aLong2739 > aLong2750) {
aLong2750 = aLong2739;
}
long l1 = -1L;
long l2 = -1L;
if (~position <= ~aLong2741
&& aLong2741 + anInt2749 > position) {
l1 = position;
} else if (position <= aLong2741
&& ~(position + len) < ~aLong2741) {
l1 = aLong2741;
}
if (~(len + position) < ~aLong2741
&& position + len <= aLong2741
+ anInt2749) {
l2 = len + position;
} else if (~position > ~(anInt2749 + aLong2741)
&& position + len >= anInt2749
+ aLong2741) {
l2 = anInt2749 + aLong2741;
}
if (l1 > -1L && ~l2 < ~l1) {
int i1 = (int) (-l1 + l2);
System.arraycopy(buffer,
(int) (-position + off + l1),
aByteArray2748, (int) (-aLong2741 + l1), i1);
}
position += len;
return;
}
if (len > 0) {
if (aLong2743 == -1L) {
aLong2743 = position;
}
System.arraycopy(buffer, off, aByteArray2745,
(int) (-aLong2743 + position), len);
position += len;
if (~(long) anInt2737 > ~(position - aLong2743)) {
anInt2737 = (int) (position - aLong2743);
}
return;
}
} catch (IOException ioexception) {
aLong2739 = -1L;
throw ioexception;
}
}
}

View file

@ -0,0 +1,130 @@
package alex.cache.loaders;
import java.util.HashMap;
import java.util.Map;
import com.alex.io.InputStream;
import com.alex.store.Store;
/**
* Handles config definition reading.
* @author Emperor
*
*/
public final class ConfigFileDefinition {
/**
* The config definitions mapping.
*/
private static final Map<Integer, ConfigFileDefinition> MAPPING = new HashMap<>();
/**
* The bit size flags.
*/
private static final int[] BITS = new int[32];
/**
* The file id.
*/
private final int id;
/**
* The config id.
*/
private int configId;
/**
* The bit shift amount.
*/
private int bitShift;
/**
* The bit amount.
*/
private int bitSize;
/**
* Constructs a new {@code ConfigFileDefinition} {@code Object}.
* @param id The file id.
*/
public ConfigFileDefinition(int id) {
this.id = id;
}
/**
* Initializes the bit flags.
*/
static {
int flag = 2;
for (int i = 0; i < 32; i++) {
BITS[i] = flag - 1;
flag += flag;
}
}
/**
* Gets the config file definitions for the given file id.
* @param id The file id.
* @return The definition.
*/
public static ConfigFileDefinition forId(int id, Store store) {
ConfigFileDefinition def = MAPPING.get(id);
if (def != null) {
return def;
}
byte[] bs = store.getIndexes()[22].getFile(id >>> 1416501898, id & 0x3ff);
if (bs == null) {
return null;
}
def = new ConfigFileDefinition(id);
InputStream buffer = new InputStream(bs);
int opcode = 0;
while ((opcode = buffer.readByte()) != 0) {
if (opcode == 1) {
def.configId = buffer.readShort();
def.bitShift = buffer.readByte();
def.bitSize = buffer.readByte();
}
}
return def;
}
/**
* Gets the mapping.
* @return The mapping.
*/
public static Map<Integer, ConfigFileDefinition> getMapping() {
return MAPPING;
}
/**
* Gets the id.
* @return The id.
*/
public int getId() {
return id;
}
/**
* Gets the configId.
* @return The configId.
*/
public int getConfigId() {
return configId;
}
/**
* Gets the bitShift.
* @return The bitShift.
*/
public int getBitShift() {
return bitShift;
}
/**
* Gets the bitSize.
* @return The bitSize.
*/
public int getBitSize() {
return bitSize;
}
}

View file

@ -0,0 +1,38 @@
package alex.cache.loaders;
import java.util.HashMap;
import alex.util.Methods;
public class EquipIds {
private static HashMap<Integer, Integer> equipIds = new HashMap<Integer, Integer>();
public static int getEquipId(int itemId) {
return getEquipIds(itemId, true, true);
}
public static int getEquipIds(int itemId, boolean putEquipIdsOnMemory, boolean putItemsOnMemory) {
if(!equipIds.isEmpty()) {
if(!equipIds.containsKey(itemId))
return -1;
return equipIds.get(itemId);
}
int equipId = 0;
for(int itemIds = 0; itemIds < Methods.getAmountOfItems(); itemIds++) {
ItemDefinition itemDef = putItemsOnMemory ? ItemDefinition.getItemDefinition(itemIds) : new ItemDefinition(itemIds);
if(itemDef.getMaleWornModelId1()>= 0 || itemDef.getMaleWornModelId2()>= 0) {
if(putEquipIdsOnMemory)
equipIds.put(itemId, equipId);
else {
if(itemIds == itemId)
return equipId;
}
equipId++;
}
}
if(!equipIds.containsKey(itemId))
return -1;
return equipIds.get(itemId);
}
}

View file

@ -0,0 +1,600 @@
package alex.cache.loaders;
import java.util.HashMap;
import alex.CacheLoader;
import alex.io.Stream;
import alex.util.Methods;
public class ItemDefinition {
private static HashMap<Integer, ItemDefinition> itemsDefs = new HashMap<Integer, ItemDefinition>();
public int id;
private boolean loaded;
private int interfaceModelId;
private String name;
//model size information
private int modelZoom;
private int modelRotation1;
private int modelRotation2;
private int modelOffset1;
private int modelOffset2;
//extra information
private int stackable;
private int value;
private boolean membersOnly;
//wearing model information
private int maleWornModelId1;
private int femaleWornModelId1;
private int maleWornModelId2;
private int femaleWornModelId2;
//options
private String[] groundOptions;
public String[] inventoryOptions;
//model information
private short[] originalModelColors;
private short[] modifiedModelColors;
private short[] textureColour1;
private short[] textureColour2;
private byte[] unknownArray1;
private int[] unknownArray2;
//extra information, not used for newer items
private boolean unnoted;
private int colourEquip1;
private int colourEquip2;
private int unknownInt1;
private int unknownInt2;
private int unknownInt3;
private int unknownInt4;
private int unknownInt5;
private int unknownInt6;
private int certId;
private int certTemplateId;
private int[] stackIds;
private int[] stackAmounts;
private int unknownInt7;
private int unknownInt8;
private int unknownInt9;
private int unknownInt10;
private int unknownInt11;
private int teamId;
private int lendId;
private int lendTemplateId;
private int unknownInt12;
private int unknownInt13;
private int unknownInt14;
private int unknownInt15;
private int unknownInt16;
private int unknownInt17;
private int unknownInt18;
private int unknownInt19;
private int unknownInt20;
private int unknownInt21;
private int unknownInt22;
private int unknownInt23;
private static HashMap<Integer, Object> clientScriptData;
public static ItemDefinition getItemDefinition(int itemId) {
return getItemDefinition(itemId, true);
}
public static ItemDefinition getItemDefinition(int itemId, boolean load) {
if (itemsDefs.containsKey(itemId))
return itemsDefs.get(itemId);
ItemDefinition def = new ItemDefinition(itemId, load);
itemsDefs.put(itemId, def);
return def;
}
public ItemDefinition(int id) {
this(id, true);
}
public ItemDefinition(int id, boolean load) {
this.id = id;
setDefaultsVariableValules();
setDefaultOptions();
if (load) {
loadItemDefinition();
}
}
public boolean isLoaded() {
return loaded;
}
public void loadItemDefinition() {
byte[] data = CacheLoader.getFileSystems()[Methods.ITEMDEF_IDX_ID].getFile(id >>> 8, 0xff & id);
if (data == null) {
System.out.println("FAILED LOADING ITEM " + id);
return;
}
readOpcodeValues(new Stream(data));
printClientScriptData();
loaded = true;
}
public boolean hasSpecialBar() {
if(clientScriptData == null)
return false;
Object specialBar = clientScriptData.get(686);
if(specialBar != null && specialBar instanceof Integer)
return (Integer) specialBar == 1;
return false;
}
public int getRenderAnimId() {
if(clientScriptData == null)
return 1426;
Object animId = clientScriptData.get(644);
if(animId != null && animId instanceof Integer)
return (Integer) animId;
return 1426;
}
public int getQuestId() {
if(clientScriptData == null)
return -1;
Object questId = clientScriptData.get(861);
if(questId != null && questId instanceof Integer)
return (Integer) questId;
return -1;
}
public HashMap<Integer, Integer> getWearingSkillRequiriments() {
if(clientScriptData == null)
return null;
HashMap<Integer, Integer> skills = new HashMap<Integer, Integer>();
int nextLevel = -1;
int nextSkill = -1;
for(int key : clientScriptData.keySet()) {
Object value = clientScriptData.get(key);
if(value instanceof String)
continue;
if(key == 23) {
skills.put(Methods.RANGE, (Integer) value);
skills.put(Methods.FIREMAKING, 61);
}else if (key >= 749 && key < 797) {
if(key % 2 == 0)
nextLevel = (Integer) value;
else
nextSkill = (Integer) value;
if(nextLevel != -1 && nextSkill != -1) {
skills.put(nextSkill, nextLevel);
nextLevel = -1;
nextSkill = -1;
}
}
}
return skills;
}
//test :P
public void printClientScriptData() {
for(int key : clientScriptData.keySet()) {
Object value = clientScriptData.get(key);
System.out.println("KEY: "+key+", VALUE: "+value);
}
HashMap<Integer, Integer> requiriments = getWearingSkillRequiriments();
if(requiriments == null) {
System.out.println("null.");
return;
}
System.out.println(requiriments.keySet().size());
for(int key : requiriments.keySet()) {
Object value = requiriments.get(key);
System.out.println("SKILL: "+key+", LEVEL: "+value);
}
}
private void setDefaultOptions() {
groundOptions = new String[] { null, null, "take", null, null };
inventoryOptions = new String[] { null, null, null, null, "drop" };
}
private void setDefaultsVariableValules() {
name = "null";
maleWornModelId1 = -1;
maleWornModelId2 = -1;
femaleWornModelId1 = -1;
femaleWornModelId2 = -1;
modelZoom = 2000;
lendId = -1;
lendTemplateId = -1;
certId = -1;
certTemplateId = -1;
unknownInt9 = 128;
value = 1;
colourEquip1 = -1;
colourEquip2 = -1;
}
public byte[] packItemDefinition() {
Stream stream = new Stream(10000);
stream.putByte(1);
stream.putShort(interfaceModelId);
if(!name.equals("null")) {
stream.putByte(2);
stream.putString(name);
}
if(modelZoom != 2000) {
stream.putByte(4);
stream.putShort(modelZoom);
}
if(modelRotation1 != 0) {
stream.putByte(5);
stream.putShort(modelRotation1);
}
if(modelRotation2 != 0) {
stream.putByte(6);
stream.putShort(modelRotation2);
}
if(modelOffset1 != 0) {
stream.putByte(7);
int value = modelOffset1 >>= 0;
if (value < 0)
value += 65536;
stream.putShort(value);
}
if(modelOffset2 != 0) {
stream.putByte(8);
int value = modelOffset2 >>= 0;
if (value < 0)
value += 65536;
stream.putShort(value);
}
if(stackable >= 1) {
stream.putByte(11);
}
if(value != 1) {
stream.putByte(12);
stream.putInt(value);
}
if(membersOnly) {
stream.putByte(16);
}
if(maleWornModelId1 != -1) {
stream.putByte(23);
stream.putShort(maleWornModelId1);
}
if(maleWornModelId2 != -1) {
stream.putByte(24);
stream.putShort(maleWornModelId2);
}
if(femaleWornModelId1 != -1) {
stream.putByte(25);
stream.putShort(femaleWornModelId1);
}
if(femaleWornModelId2 != -1) {
stream.putByte(26);
stream.putShort(femaleWornModelId2);
}
for(int index = 0; index < groundOptions.length; index++) {
if(groundOptions[index] == null || (index == 2 && groundOptions[index].equals("take")))
continue;
stream.putByte(30+index);
stream.putString(groundOptions[index]);
}
for(int index = 0; index < inventoryOptions.length; index++) {
if(inventoryOptions[index] == null || (index == 4 && inventoryOptions[index].equals("drop")))
continue;
stream.putByte(35+index);
stream.putString(inventoryOptions[index]);
}
if(originalModelColors != null && modifiedModelColors != null) {
stream.putByte(40);
stream.putByte(originalModelColors.length);
for(int index = 0; index < originalModelColors.length; index++) {
stream.putShort(originalModelColors[index]);
stream.putShort(modifiedModelColors[index]);
}
}
if(textureColour1 != null && textureColour2 != null) {
stream.putByte(41);
stream.putByte(textureColour1.length);
for(int index = 0; index < textureColour1.length; index++) {
stream.putShort(textureColour1[index]);
stream.putShort(textureColour2[index]);
}
}
if(unknownArray1 != null) {
stream.putByte(42);
stream.putByte(unknownArray1.length);
for(int index = 0; index < unknownArray1.length; index++)
stream.putByte(unknownArray1[index]);
}
if(unnoted) {
stream.putByte(65);
}
if(colourEquip1 != -1) {
stream.putByte(78);
stream.putShort(colourEquip1);
}
if(colourEquip2 != -1) {
stream.putByte(79);
stream.putShort(colourEquip2);
}
//TODO FEW OPCODES HERE
if(certId != -1) {
stream.putByte(97);
stream.putShort(certId);
}
if(certTemplateId != -1) {
stream.putByte(98);
stream.putShort(certTemplateId);
}
if(stackIds != null && stackAmounts != null) {
for(int index = 0; index < stackIds.length; index++) {
if(stackIds[index] == 0 && stackAmounts[index] == 0)
continue;
stream.putByte(100+index);
stream.putShort(stackIds[index]);
stream.putShort(stackAmounts[index]);
}
}
//TODO FEW OPCODES HERE
if(teamId != 0) {
stream.putByte(115);
stream.putByte(teamId);
}
if(lendId != -1) {
stream.putByte(121);
stream.putShort(lendId);
}
if(lendTemplateId != -1) {
stream.putByte(122);
stream.putShort(lendTemplateId);
}
//TODO FEW OPCODES HERE
if(unknownArray2 != null) {
stream.putByte(132);
stream.putByte(unknownArray2.length);
for(int index = 0; index < unknownArray2.length; index++)
stream.putShort(unknownArray2[index]);
}
if(clientScriptData != null) {
stream.putByte(249);
stream.putByte(clientScriptData.size());
for(int key : clientScriptData.keySet()) {
Object value = clientScriptData.get(key);
stream.putByte(value instanceof String ? 1 : 0);
stream.putMediumInt(key);
if(value instanceof String) {
stream.putString((String) value);
}else{
stream.putInt((Integer) value);
}
}
}
//end
stream.putByte(0);
byte[] data = new byte[stream.offset];
stream.offset = 0;
stream.getBytes(data, 0, data.length);
return data;
}
private void readValues(Stream stream, int opcode) {
if(opcode == 1)
interfaceModelId = stream.getUShort();
else if (opcode == 2)
setName(stream.getString());
else if (opcode == 4)
modelZoom = stream.getUShort();
else if (opcode == 5)
modelRotation1 = stream.getUShort();
else if (opcode == 6)
modelRotation2 = stream.getUShort();
else if (opcode == 7) {
modelOffset1 = stream.getUShort();
if (modelOffset1 > 32767)
modelOffset1 -= 65536;
modelOffset1 <<= 0;
}else if (opcode == 8) {
modelOffset2 = stream.getUShort();
if (modelOffset2 > 32767)
modelOffset2 -= 65536;
modelOffset2 <<= 0;
}else if (opcode == 11)
stackable = 1;
else if (opcode == 12)
value = stream.getInt();
else if (opcode == 16)
membersOnly = true;
else if (opcode == 23)
setMaleWornModelId1(stream.getUShort());
else if (opcode == 24)
femaleWornModelId1 = stream.getUShort();
else if (opcode == 25)
setMaleWornModelId2(stream.getUShort());
else if (opcode == 26)
femaleWornModelId2 = stream.getUShort();
else if (opcode >= 30 && opcode < 35)
groundOptions[opcode-30] = stream.getString();
else if (opcode >= 35 && opcode < 40)
inventoryOptions[opcode-35] = stream.getString();
else if (opcode == 40) {
int length = stream.getUByte();
originalModelColors = new short[length];
modifiedModelColors = new short[length];
for(int index = 0; index < length; index++) {
originalModelColors[index] = (short) stream.getUShort();
modifiedModelColors[index] = (short) stream.getUShort();
}
}else if (opcode == 41) {
int length = stream.getUByte();
textureColour1 = new short[length];
textureColour2 = new short[length];
for(int index = 0; index < length; index++) {
textureColour1[index] = (short) stream.getUShort();
textureColour2[index] = (short) stream.getUShort();
}
}else if (opcode == 42) {
int length = stream.getUByte();
unknownArray1 = new byte[length];
for(int index = 0; index < length; index++)
unknownArray1[index] = stream.getByte();
}else if (opcode == 65)
unnoted = true;
else if (opcode == 78)
colourEquip1 = stream.getUShort();
else if (opcode == 79)
colourEquip2 = stream.getUShort();
else if (opcode == 90)
unknownInt1 = stream.getUShort();
else if (opcode == 91)
unknownInt2 = stream.getUShort();
else if (opcode == 92)
unknownInt3 = stream.getUShort();
else if (opcode == 93)
unknownInt4 = stream.getUShort();
else if (opcode == 95)
unknownInt5 = stream.getUShort();
else if (opcode == 96)
unknownInt6 = stream.getUShort();
else if (opcode == 97)
certId = stream.getUShort();
else if (opcode == 98)
certTemplateId = stream.getUShort();
else if (opcode >= 100 && opcode < 110) {
if (stackIds == null) {
stackIds = new int[10];
stackAmounts = new int[10];
}
stackIds[opcode-100] = stream.getUShort();
stackAmounts[opcode-100] = stream.getUShort();
}else if (opcode == 110)
unknownInt7 = stream.getUShort();
else if (opcode == 111)
unknownInt8 = stream.getUShort();
else if (opcode == 112)
unknownInt9 = stream.getUShort();
else if (opcode == 113)
unknownInt10 = stream.getByte();
else if (opcode == 114)
unknownInt11 = stream.getByte() * 5;
else if (opcode == 115)
teamId = stream.getUByte();
else if (opcode == 121)
lendId = stream.getUShort();
else if (opcode == 122)
lendTemplateId = stream.getUShort();
else if (opcode == 125) {
unknownInt12 = stream.getByte() << 0;
unknownInt13 = stream.getByte() << 0;
unknownInt14 = stream.getByte() << 0;
}else if (opcode == 126) {
unknownInt15 = stream.getByte() << 0;
unknownInt16 = stream.getByte() << 0;
unknownInt17 = stream.getByte() << 0;
}else if (opcode == 127) {
unknownInt18 = stream.getUByte();
unknownInt19 = stream.getUShort();
}else if (opcode == 128) {
unknownInt20 = stream.getUByte();
unknownInt21 = stream.getUShort();
}else if (opcode == 129) {
unknownInt20 = stream.getUByte();
unknownInt21 = stream.getUShort();
}else if (opcode == 130) {
unknownInt22 = stream.getUByte();
unknownInt23 = stream.getUShort();
}else if (opcode == 132) {
int length = stream.getUByte();
unknownArray2 = new int[length];
for(int index = 0; index < length; index++)
unknownArray2[index] = stream.getUShort();
}else if (opcode == 249) {
int length = stream.getUByte();
if(clientScriptData == null)
clientScriptData = new HashMap<Integer, Object>(Methods.getTableSize(length));
for (int index = 0; index < length; index++) {
boolean stringInstance = stream.getUByte() == 1;
int key = stream.getMediumInt();
Object value = stringInstance ? stream.getString() : stream.getInt();
clientScriptData.put(key, value);
}
}
else
throw new IllegalArgumentException("MISSING OPCODE "+opcode+" FOR ITEM "+id);
}
private void readOpcodeValues(Stream stream) {
while (true) {
int opcode = stream.getUByte();
if (opcode == 0)
break;
readValues(stream, opcode);
}
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setMaleWornModelId1(int maleWornModelId1) {
this.maleWornModelId1 = maleWornModelId1;
}
public int getMaleWornModelId1() {
return maleWornModelId1;
}
public void setMaleWornModelId2(int maleWornModelId2) {
this.maleWornModelId2 = maleWornModelId2;
}
public int getMaleWornModelId2() {
return maleWornModelId2;
}
}

View file

@ -0,0 +1,914 @@
package alex.cache.loaders;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import com.alex.io.InputStream;
import com.alex.store.Store;
import emperor.ObjectMap.GameObject;
/**
* The {@link Definitions} of {@link GameObject}s
* @author SonicForce41
*/
public class ObjectDefinitions {
/**
* The {@link Map} of {@link ObjectDefinitions}
*/
private static Map<Integer, ObjectDefinitions> DEFINITIONS = new HashMap<Integer, ObjectDefinitions>();
/**
* anInt3832
*/
static int anInt3832;
/**
* anInt3836
*/
static int anInt3836;
/**
* anInt3842
*/
static int anInt3842;
/**
* anInt3843
*/
static int anInt3843;
/**
* anInt3846
*/
static int anInt3846;
/**
* Gets the {@link ObjectDefinitions} for 'objectId'
*/
public static ObjectDefinitions forId(final int id) {
return DEFINITIONS.get(id);
}
/**
* Gets the {@link Map} of {@link] ObjectDefinitions}
* @return
*/
public static Map<Integer, ObjectDefinitions> getObjectDefinitions() {
return DEFINITIONS;
}
/**
* Gets the archive Id
* @return
*/
private static int getArchiveId(final int objectID2) {
return objectID2 >>> -1135990488;
}
/**
* aBoolean3853
*/
public boolean aBoolean3853;
/**
* aBoolean3891
*/
public boolean aBoolean3891;
/**
* actionCount
*/
public int actionCount;
/**
* clippingFlag
*/
public boolean clippingFlag;
/**
* configFileId
*/
public int configFileId;
/**
* id
*/
public int id;
/**
* name
*/
public String name;
/**
* secondBool
*/
public boolean secondBool;
/**
* secondInt
*/
public int secondInt;
/**
* sizeX
*/
public int sizeX;
/**
* sizeY
*/
public int sizeY;
/**
* thirdInt
*/
public int thirdInt;
/**
* aByte3912
*/
private byte aByte3912;
/**
* aByteArray3858
*/
private byte[] aByteArray3858;
/**
* anInt3881
*/
private int anInt3881;
/**
* anIntArray3869
*/
private int[] anIntArray3869;
/**
* anIntArrayArray3916
*/
@SuppressWarnings("unused")
private int[][] anIntArrayArray3916;
/**
* aShortArray3919
*/
private short[] aShortArray3919;
public String[] options;
/**
* aShortArray3920
*/
private short[] aShortArray3920;
/**
* modelConfiguration
*/
private byte[] modelConfiguration;
/**
* modifiedColors
*/
private short[] modifiedColors;
/**
* The object Id
*/
private int objectId;
/**
* The original colors array
*/
private short[] originalColors;
/**
* solid
*/
private boolean solid;
/**
* walkBitFlag
*/
private int walkBitFlag;
/**
* aBoolean3839
*/
boolean aBoolean3839;
/**
* aBoolean3845
*/
boolean aBoolean3845;
/**
* aBoolean3866
*/
boolean aBoolean3866;
/**
* aBoolean3867
*/
boolean aBoolean3867;
/**
* aBoolean3870
*/
boolean aBoolean3870;
/**
* aBoolean3872
*/
boolean aBoolean3872;
/**
* aBoolean3873
*/
boolean aBoolean3873;
/**
* aBoolean3894
*/
boolean aBoolean3894;
/**
* aBoolean3895
*/
boolean aBoolean3895;
/**
* aBoolean3906
*/
boolean aBoolean3906;
/**
* aBoolean3923
*/
boolean aBoolean3923;
/**
* aBoolean3924
*/
boolean aBoolean3924;
/**
* anInt3835
*/
int anInt3835;
/**
* anInt3838
*/
int anInt3838 = -1;
/**
* anInt3844
*/
int anInt3844;
/**
* anInt3850
*/
int anInt3850;
/**
* anInt3851
*/
int anInt3851;
/**
* anInt3855
*/
int anInt3855;
/**
* anInt3857
*/
int anInt3857;
/**
* anInt3860
*/
int anInt3860;
/**
* anInt3865
*/
int anInt3865;
/**
* anInt3876
*/
public int animationId;
/**
* anInt3892
*/
int anInt3892;
/**
* anInt3896
*/
int anInt3896;
/**
* anInt3900
*/
int anInt3900;
/**
* anInt3904
*/
int anInt3904;
/**
* anInt3905
*/
int anInt3905;
/**
* anInt3913
*/
int anInt3913;
/**
* anInt3921
*/
int anInt3921;
/**
* anIntArray3833
*/
int[] anIntArray3833 = null;
/**
* anIntArray3859
*/
int[] anIntArray3859;
/**
* anIntArray3908
*/
int[] anIntArray3908;
/**
* The childrens id
*/
int[] childrenIds;
/**
* configId
*/
int configId;
public int[] models;
/**
* Constructs a new {@code ObjectDefinitions.java} {@code Object}.
* @param objectId the object Id
*/
public ObjectDefinitions(final int objectId) {
this.objectId = objectId;
anInt3835 = -1;
anInt3860 = -1;
configFileId = -1;
aBoolean3866 = false;
anInt3851 = -1;
anInt3865 = 255;
aBoolean3845 = false;
aBoolean3867 = false;
anInt3850 = 0;
anInt3844 = -1;
setAnInt3881(0);
anInt3857 = -1;
aBoolean3872 = true;
options = new String[5];
aBoolean3839 = false;
anIntArray3869 = null;
sizeX = 1;
thirdInt = -1;
solid = true;
aBoolean3895 = true;
aBoolean3870 = false;
aBoolean3853 = true;
secondBool = false;
actionCount = 2;
anInt3855 = -1;
anInt3904 = 0;
sizeY = 1;
animationId = -1;
clippingFlag = false;
aBoolean3891 = false;
anInt3905 = 0;
name = "null";
anInt3913 = -1;
aBoolean3906 = false;
aBoolean3873 = false;
anInt3900 = 0;
secondInt = -1;
aBoolean3894 = false;
setaByte3912((byte) 0);
anInt3921 = 0;
configId = -1;
setWalkBitFlag(0);
anInt3892 = 64;
aBoolean3923 = false;
aBoolean3924 = false;
}
/**
* Method returns the value of aByte3912
* @return the aByte3912
*/
public byte getaByte3912() {
return aByte3912;
}
/**
* Method returns the value of anInt3881
* @return the anInt3881
*/
public int getAnInt3881() {
return anInt3881;
}
/**
* Gets the object Id
* @return the objectId
*/
public int getObjectId() {
return objectId;
}
/**
* Method returns the value of walkBitFlag
* @return the walkBitFlag
*/
public int getWalkBitFlag() {
return walkBitFlag;
}
public static ObjectDefinitions initialize(int objectId, Store store) {
byte[] is = store.getIndexes()[16].getFile(getArchiveId(objectId), objectId & 0xff);
if (is == null) {
return null;
}
ObjectDefinitions def = new ObjectDefinitions(objectId);
def.readValueLoop(new InputStream(is));
def.configureObject();
if (def.clippingFlag) {
def.solid = false;
def.actionCount = 0;
}
if (def.name.contains("booth")) {
def.clippingFlag = false;
def.solid = true;
def.actionCount = 2;
}
DEFINITIONS.put(objectId, def);
return def;
}
/**
* Checks if the object is clipped
* @return
*/
public boolean isClippingFlag() {
return clippingFlag;
}
/**
* Checks if the object is solid
* @return
*/
public boolean isSolid() {
return solid;
}
/**
* Gets the size X
* @return
*/
public int getSizeX() {
return sizeX;
}
/**
* Gets the size Y
* @return
*/
public int getSizeY() {
return sizeY;
}
/**
* Gets the acount count
* @return
*/
public int getActionCount() {
return actionCount;
}
/**
* Gets the name
*/
public String getName() {
return name;
}
/**
* Gets the walk bit
* @return
*/
public int getWalkBit() {
return walkBitFlag;
}
/**
* Method sets the value for aByte3912
* @param aByte3912 the aByte3912 to set
*/
public void setaByte3912(final byte aByte3912) {
this.aByte3912 = aByte3912;
}
/**
* Method sets the value for anInt3881
* @param anInt3881 the anInt3881 to set
*/
public void setAnInt3881(final int anInt3881) {
this.anInt3881 = anInt3881;
}
/**
* Method sets the value for walkBitFlag
* @param walkBitFlag the walkBitFlag to set
*/
public void setWalkBitFlag(final int walkBitFlag) {
this.walkBitFlag = walkBitFlag;
}
/**
* Reads the values in a loop
* @param builder
*/
private void readValueLoop(final InputStream builder) {
for (;;) {
int opcode = builder.readUnsignedByte();
if (opcode == 0)
break;
readValues(builder, opcode);
}
}
/**
* Reads the values
* @param builder the PacketBuilder
* @param opcode the opcode
*/
private void readValues(final InputStream builder, final int opcode) {
// System.out.println("Reading opcode " + opcode);
if (opcode != 1 && opcode != 5) {
if (opcode != 2) {
if (opcode != 14) {
if (opcode != 15) {
if (opcode == 17) {
solid = false;
actionCount = 0;
} else if (opcode != 18) {
if (opcode == 19)
secondInt = builder.readUnsignedByte();
else if (opcode == 21)
setaByte3912((byte) 1);
else if (opcode != 22) {
if (opcode != 23) {
if (opcode != 24) {
if (opcode == 27)
actionCount = 1;
else if (opcode == 28)
anInt3892 = (builder.readUnsignedByte() << 2);
else if (opcode != 29) {
if (opcode != 39) {
if (opcode < 30 || opcode >= 35) {
if (opcode == 40) {
int i_53_ = (builder.readUnsignedByte());
originalColors = new short[i_53_];
modifiedColors = new short[i_53_];
for (int i_54_ = 0; i_53_ > i_54_; i_54_++) {
originalColors[i_54_] = (short) (builder.readUnsignedShort());
modifiedColors[i_54_] = (short) (builder.readUnsignedShort());
}
} else if (opcode != 41) {
if (opcode != 42) {
if (opcode != 62) {
if (opcode != 64) {
if (opcode == 65)
builder.readUnsignedShort();
else if (opcode != 66) {
if (opcode != 67) {
if (opcode == 69)
setWalkBitFlag(builder.readUnsignedByte());
else if (opcode != 70) {
if (opcode == 71)
builder.readShort();
else if (opcode != 72) {
if (opcode == 73)
secondBool = true;
else if (opcode == 74)
clippingFlag = true;
else if (opcode != 75) {
if (opcode != 77 && opcode != 92) {
if (opcode == 78) {
anInt3860 = builder.readUnsignedShort();
anInt3904 = builder.readUnsignedByte();
} else if (opcode != 79) {
if (opcode == 81) {
setaByte3912((byte) 2);
builder.readUnsignedByte();
} else if (opcode != 82) {
if (opcode == 88)
aBoolean3853 = false;
else if (opcode != 89) {
if (opcode == 90)
aBoolean3870 = true;
else if (opcode != 91) {
if (opcode != 93) {
if (opcode == 94)
setaByte3912((byte) 4);
else if (opcode != 95) {
if (opcode != 96) {
if (opcode == 97)
aBoolean3866 = true;
else if (opcode == 98)
aBoolean3923 = true;
else if (opcode == 99) {
anInt3857 = builder.readUnsignedByte();
anInt3835 = builder.readUnsignedShort();
} else if (opcode == 100) {
anInt3844 = builder.readUnsignedByte();
anInt3913 = builder.readUnsignedShort();
} else if (opcode != 101) {
if (opcode == 102)
anInt3838 = builder.readUnsignedShort();
else if (opcode == 103)
thirdInt = 0;
else if (opcode != 104) {
if (opcode == 105)
aBoolean3906 = true;
else if (opcode == 106) {
int i_55_ = builder.readUnsignedByte();
anIntArray3869 = new int[i_55_];
anIntArray3833 = new int[i_55_];
for (int i_56_ = 0; i_56_ < i_55_; i_56_++) {
anIntArray3833[i_56_] = builder.readUnsignedShort();
int i_57_ = builder.readUnsignedByte();
anIntArray3869[i_56_] = i_57_;
setAnInt3881(getAnInt3881()
+ i_57_);
}
} else if (opcode == 107)
anInt3851 = builder.readUnsignedShort();
else if (opcode >= 150 && opcode < 155) {
options[opcode - 150] = builder.readString();
} else if (opcode != 160) {
if (opcode == 162) {
setaByte3912((byte) 3);
builder.readInt();
} else if (opcode == 163) {
builder.readByte();
builder.readByte();
builder.readByte();
builder.readByte();
} else if (opcode != 164) {
if (opcode != 165) {
if (opcode != 166) {
if (opcode == 167)
anInt3921 = builder.readUnsignedShort();
else if (opcode != 168) {
if (opcode == 169) {
aBoolean3845 = true;
} else if (opcode == 170) {
builder.readUnsignedSmart();
} else if (opcode == 171) {
builder.readUnsignedSmart();
} else if (opcode == 173) {
builder.readUnsignedShort();
builder.readUnsignedShort();
} else if (opcode == 177) {
// something
// =
// true
} else if (opcode == 178) {
builder.readUnsignedByte();
} else if (opcode == 249) {
int i_58_ = builder.readUnsignedByte();
for (int i_60_ = 0; i_60_ < i_58_; i_60_++) {
boolean bool = builder.readUnsignedByte() == 1;
builder.readByte();
builder.readShort();
if (!bool)
builder.readInt();
else
builder.readString();
}
}
} else
aBoolean3894 = true;
} else
builder.readShort();
} else
builder.readShort();
} else
builder.readShort();
} else {
int i_62_ = builder.readUnsignedByte();
anIntArray3908 = new int[i_62_];
for (int i_63_ = 0; i_62_ > i_63_; i_63_++)
anIntArray3908[i_63_] = builder.readUnsignedShort();
}
} else
anInt3865 = builder.readUnsignedByte();
} else
anInt3850 = builder.readUnsignedByte();
} else
aBoolean3924 = true;
} else {
setaByte3912((byte) 5);
builder.readShort();
}
} else {
setaByte3912((byte) 3);
builder.readUnsignedShort();
}
} else
aBoolean3873 = true;
} else
aBoolean3895 = false;
} else
aBoolean3891 = true;
} else {
anInt3900 = builder.readUnsignedShort();
anInt3905 = builder.readUnsignedShort();
anInt3904 = builder.readUnsignedByte();
int i_64_ = builder.readUnsignedByte();
anIntArray3859 = new int[i_64_];
for (int i_65_ = 0; i_65_ < i_64_; i_65_++)
anIntArray3859[i_65_] = builder.readUnsignedShort();
}
} else {
configFileId = builder.readUnsignedShort();
if (configFileId == 65535)
configFileId = -1;
configId = builder.readUnsignedShort();
if (configId == 65535)
configId = -1;
int i_66_ = -1;
if (opcode == 92) {
i_66_ = builder.readUnsignedShort();
if (i_66_ == 65535)
i_66_ = -1;
}
int i_67_ = builder.readUnsignedByte();
childrenIds = new int[i_67_ + 2];
for (int i_68_ = 0; i_67_ >= i_68_; i_68_++) {
childrenIds[i_68_] = builder.readUnsignedShort();
if (childrenIds[i_68_] == 65535)
childrenIds[i_68_] = -1;
}
childrenIds[i_67_ + 1] = i_66_;
}
} else
anInt3855 = builder.readUnsignedByte();
} else
builder.readShort();
} else
builder.readShort();
} else
builder.readUnsignedShort();
} else
builder.readUnsignedShort();
} else
aBoolean3872 = false;
} else
aBoolean3839 = true;
} else {
int i_69_ = builder.readUnsignedByte();
aByteArray3858 = new byte[i_69_];
for (int i_70_ = 0; i_70_ < i_69_; i_70_++)
aByteArray3858[i_70_] = (byte) builder.readUnsignedByte();
}
} else {
int i_71_ = builder.readUnsignedByte();
aShortArray3920 = new short[i_71_];
aShortArray3919 = new short[i_71_];
for (int i_72_ = 0; i_71_ > i_72_; i_72_++) {
aShortArray3920[i_72_] = (short) builder.readUnsignedShort();
aShortArray3919[i_72_] = (short) builder.readUnsignedShort();
}
}
} else
options[opcode - 30] = builder.readString();
} else
builder.readByte();
} else
builder.readByte();
} else {
animationId = builder.readUnsignedShort();
if (animationId == 65535)
animationId = -1;
}
} else
thirdInt = 1;
} else
aBoolean3867 = true;
} else
solid = false;
} else
sizeX = builder.readUnsignedByte();
} else
sizeY = builder.readUnsignedByte();
} else
name = builder.readString();
} else {
int length = builder.readUnsignedByte() & 0xff;
if (opcode == 1) {
modelConfiguration = new byte[length];
}
models = new int[length];
for (int i = 0; i < length; i++) {
models[i] = builder.readShort() & 0xFFFF;
int config = -1;
if (opcode == 1) {
config = modelConfiguration[i] = (byte) (builder.readUnsignedByte() & 0xFF);
}
// System.out.println("Model id: " + model + ", " + config);
}
// boolean aBoolean1162 = false;
// if (opcode == 5 && aBoolean1162)
// skipBytes(builder);
// int length = builder.readUnsignedByte();
// anIntArrayArray3916 = new int[length][];
// modelConfiguration = new byte[length];
// for (int i = 0; i < length; i++) {
// modelConfiguration[i] = (byte) builder.readByte();
// int i_75_ = builder.readUnsignedByte();
// anIntArrayArray3916[i] = new int[i_75_];
// for (int i_76_ = 0; i_75_ > i_76_; i_76_++) {
// anIntArrayArray3916[i][i_76_] = builder.readUnsignedShort();
// if (opcode == 1)
// System.out.println("Model id " + anIntArrayArray3916[i][i_76_]);
// }
// }
// if (opcode == 5 && !aBoolean1162)
// skipBytes(builder);
}
}
/**
* Skips few bytes
* @param builder
*/
private void skipBytes(final InputStream builder) {
int length = builder.readUnsignedByte();
for (int index = 0; index < length; index++) {
builder.skip(1);
builder.skip(builder.readUnsignedByte() * 2);
}
}
/**
* Checks object variables
*/
void configureObject() {
if (id == 4039) {
name = "Trapdoor";
options[0] = "Open";
}
if (secondInt == -1) {
secondInt = 0;
if (modelConfiguration != null && modelConfiguration.length == 1 && modelConfiguration[0] == 10)
secondInt = 1;
for (int i = 0; i < 5; i++) {
if (options[i] != null) {
secondInt = 1;
break;
}
}
}
if (anInt3855 == -1)
anInt3855 = actionCount != 0 ? 1 : 0;
}
/**
* Clears the definition
*/
public static void clear() {
DEFINITIONS = new TreeMap<Integer, ObjectDefinitions>();
}
}

View file

@ -0,0 +1,147 @@
package alex.cache.loaders;
import java.util.HashMap;
import java.util.Map;
import com.alex.io.InputStream;
import com.alex.store.Store;
public class OverlayDefinition {
private static final Map<Integer, OverlayDefinition> DEFINITIONS = new HashMap<>();
private int rgb = -1;
private int textureId;
private boolean bool;
private int id;
public OverlayDefinition(int id) {
this.id = id;
}
public static OverlayDefinition forId(Store store, int id) {
OverlayDefinition def = DEFINITIONS.get(id);
if (def != null) {
return def;
}
byte[] data = store.getIndexes()[2].getFile(4, id);
if (data == null) {
return null;
}
def = new OverlayDefinition(id);
def.readValues(new InputStream(data), id);
DEFINITIONS.put(id, def);
return def;
}
public void readValues(InputStream buffer, int id) {
for (;;) {
int opcode = buffer.readByte();
if (opcode == 0) {
break;
}
parseOpcode(buffer, opcode, id);
}
}
private final void parseOpcode(InputStream buffer, int opcode, int id) {
switch (opcode) {
case 1:
rgb = ((buffer.readByte() & 0xff) << 16) + ((buffer.readByte() & 0xff) << 8) + (buffer.readByte() & 0xff);
break;
case 2:
textureId = buffer.readByte();
break;
case 3:
textureId = buffer.readShort() & 0xFFFF;
if (textureId == 65535) {
textureId = -1;
}
break;
case 5:
bool = false;
break;
case 7:
buffer.readByte();
buffer.readShort(); //Class68.method1252(false, buffer.getTriByte(124));
break;
// case 8: Class17.anInt305 = id;
case 9:
buffer.readShort();
break;
case 11:
buffer.readByte();
break;
case 13:
buffer.readByte();
buffer.readShort();
break;
case 14:
buffer.readByte();
break;
}
}
/**
* @return the textureId
*/
public int getTextureId() {
return textureId;
}
/**
* @param textureId the textureId to set
*/
public void setTextureId(int textureId) {
this.textureId = textureId;
}
/**
* @return the bool
*/
public boolean isBool() {
return bool;
}
/**
* @param bool the bool to set
*/
public void setBool(boolean bool) {
this.bool = bool;
}
/**
* @return the id
*/
public int getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* @return the definitions
*/
public static Map<Integer, OverlayDefinition> getDefinitions() {
return DEFINITIONS;
}
/**
* @return the rgb
*/
public int getRgb() {
return rgb;
}
/**
* @param rgb the rgb to set
*/
public void setRgb(int rgb) {
this.rgb = rgb;
}
}

View file

@ -0,0 +1,20 @@
package alex.cache.updateServer;
import alex.io.Stream;
import alex.util.Methods;
public class UpdateServer {
public static byte[] getReadyForSendFile(int idxid, int fileid, int compression, byte[] data) {
Stream stream = new Stream(data.length+100);
stream.putByte(idxid);
stream.putShort(fileid);
byte[] compressedData = Methods.packContainer(compression, data);
for(int index = 0; index < compressedData.length; index++)
stream.putByte(compressedData[index]);
byte[] file = new byte[stream.offset];
stream.offset = 0;
stream.getBytes(file, 0, file.length);
return file;
}
}

View file

@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package alex.compressors;
/**
* Constants for both the compress and decompress BZip2 classes.
*/
interface BZip2Constants {
int BASEBLOCKSIZE = 100000;
int MAX_ALPHA_SIZE = 258;
int MAX_CODE_LEN = 23;
int RUNA = 0;
int RUNB = 1;
int N_GROUPS = 6;
int G_SIZE = 50;
int N_ITERS = 4;
int MAX_SELECTORS = (2 + (900000 / G_SIZE));
int NUM_OVERSHOOT_BYTES = 20;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,134 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package alex.compressors;
/**
* A simple class the hold and calculate the CRC for sanity checking of the
* data.
* @NotThreadSafe
*/
class CRC {
private static final int crc32Table[] = {
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
};
CRC() {
initialiseCRC();
}
void initialiseCRC() {
globalCrc = 0xffffffff;
}
int getFinalCRC() {
return ~globalCrc;
}
int getGlobalCRC() {
return globalCrc;
}
void setGlobalCRC(int newCrc) {
globalCrc = newCrc;
}
void updateCRC(int inCh) {
int temp = (globalCrc >> 24) ^ inCh;
if (temp < 0) {
temp = 256 + temp;
}
globalCrc = (globalCrc << 8) ^ CRC.crc32Table[temp];
}
void updateCRC(int inCh, int repeat) {
int globalCrcShadow = this.globalCrc;
while (repeat-- > 0) {
int temp = (globalCrcShadow >> 24) ^ inCh;
globalCrcShadow = (globalCrcShadow << 8) ^ crc32Table[(temp >= 0)
? temp
: (temp + 256)];
}
this.globalCrc = globalCrcShadow;
}
private int globalCrc;
}

View file

@ -0,0 +1,25 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package alex.compressors;
import java.io.OutputStream;
public abstract class CompressorOutputStream extends OutputStream {
// TODO
}

View file

@ -0,0 +1,91 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package alex.compressors;
/**
* Random numbers for both the compress and decompress BZip2 classes.
*/
final class Rand {
private static final int[] RNUMS = {
619, 720, 127, 481, 931, 816, 813, 233, 566, 247,
985, 724, 205, 454, 863, 491, 741, 242, 949, 214,
733, 859, 335, 708, 621, 574, 73, 654, 730, 472,
419, 436, 278, 496, 867, 210, 399, 680, 480, 51,
878, 465, 811, 169, 869, 675, 611, 697, 867, 561,
862, 687, 507, 283, 482, 129, 807, 591, 733, 623,
150, 238, 59, 379, 684, 877, 625, 169, 643, 105,
170, 607, 520, 932, 727, 476, 693, 425, 174, 647,
73, 122, 335, 530, 442, 853, 695, 249, 445, 515,
909, 545, 703, 919, 874, 474, 882, 500, 594, 612,
641, 801, 220, 162, 819, 984, 589, 513, 495, 799,
161, 604, 958, 533, 221, 400, 386, 867, 600, 782,
382, 596, 414, 171, 516, 375, 682, 485, 911, 276,
98, 553, 163, 354, 666, 933, 424, 341, 533, 870,
227, 730, 475, 186, 263, 647, 537, 686, 600, 224,
469, 68, 770, 919, 190, 373, 294, 822, 808, 206,
184, 943, 795, 384, 383, 461, 404, 758, 839, 887,
715, 67, 618, 276, 204, 918, 873, 777, 604, 560,
951, 160, 578, 722, 79, 804, 96, 409, 713, 940,
652, 934, 970, 447, 318, 353, 859, 672, 112, 785,
645, 863, 803, 350, 139, 93, 354, 99, 820, 908,
609, 772, 154, 274, 580, 184, 79, 626, 630, 742,
653, 282, 762, 623, 680, 81, 927, 626, 789, 125,
411, 521, 938, 300, 821, 78, 343, 175, 128, 250,
170, 774, 972, 275, 999, 639, 495, 78, 352, 126,
857, 956, 358, 619, 580, 124, 737, 594, 701, 612,
669, 112, 134, 694, 363, 992, 809, 743, 168, 974,
944, 375, 748, 52, 600, 747, 642, 182, 862, 81,
344, 805, 988, 739, 511, 655, 814, 334, 249, 515,
897, 955, 664, 981, 649, 113, 974, 459, 893, 228,
433, 837, 553, 268, 926, 240, 102, 654, 459, 51,
686, 754, 806, 760, 493, 403, 415, 394, 687, 700,
946, 670, 656, 610, 738, 392, 760, 799, 887, 653,
978, 321, 576, 617, 626, 502, 894, 679, 243, 440,
680, 879, 194, 572, 640, 724, 926, 56, 204, 700,
707, 151, 457, 449, 797, 195, 791, 558, 945, 679,
297, 59, 87, 824, 713, 663, 412, 693, 342, 606,
134, 108, 571, 364, 631, 212, 174, 643, 304, 329,
343, 97, 430, 751, 497, 314, 983, 374, 822, 928,
140, 206, 73, 263, 980, 736, 876, 478, 430, 305,
170, 514, 364, 692, 829, 82, 855, 953, 676, 246,
369, 970, 294, 750, 807, 827, 150, 790, 288, 923,
804, 378, 215, 828, 592, 281, 565, 555, 710, 82,
896, 831, 547, 261, 524, 462, 293, 465, 502, 56,
661, 821, 976, 991, 658, 869, 905, 758, 745, 193,
768, 550, 608, 933, 378, 286, 215, 979, 792, 961,
61, 688, 793, 644, 986, 403, 106, 366, 905, 644,
372, 567, 466, 434, 645, 210, 389, 550, 919, 135,
780, 773, 635, 389, 707, 100, 626, 958, 165, 504,
920, 176, 193, 713, 857, 265, 203, 50, 668, 108,
645, 990, 626, 197, 510, 357, 358, 850, 858, 364,
936, 638
};
/**
* Return the random number at a specific index.
*
* @param i the index
* @return the random number
*/
static int rNums(int i){
return RNUMS[i];
}
}

View file

@ -0,0 +1,56 @@
package alex.decompressors;
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[][];
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];
}
}

View file

@ -0,0 +1,550 @@
package alex.decompressors;
public class BZip2Decompressor {
private static int anIntArray257[];
private static BZip2BlockEntry entry = new BZip2BlockEntry();
public static final int decompress(byte abyte0[], int i, byte abyte1[],
int j, int k) {
synchronized (entry) {
entry.aByteArray2224 = abyte1;
entry.anInt2209 = k;
entry.aByteArray2212 = abyte0;
entry.anInt2203 = 0;
entry.anInt2206 = i;
entry.anInt2232 = 0;
entry.anInt2207 = 0;
entry.anInt2217 = 0;
entry.anInt2216 = 0;
method1793(entry);
i -= entry.anInt2206;
entry.aByteArray2224 = null;
entry.aByteArray2212 = null;
int l = i;
return l;
}
}
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);
if (j1 == 0) {
i = 1;
break;
}
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);
int i2 = entry.anInt2216;
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 entry) {
return (byte) method1790(8, entry);
}
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 method1791() {
entry = null;
}
private static final void method1793(BZip2BlockEntry entry) {
// 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;
entry.anInt2202 = 1;
if (anIntArray257 == null) {
anIntArray257 = new int[entry.anInt2202 * 0x186a0];
}
boolean flag18 = true;
while (flag18) {
byte byte0 = method1789(entry);
if (byte0 == 23) {
return;
}
byte0 = method1789(entry);
byte0 = method1789(entry);
byte0 = method1789(entry);
byte0 = method1789(entry);
byte0 = method1789(entry);
byte0 = method1789(entry);
byte0 = method1789(entry);
byte0 = method1789(entry);
byte0 = method1789(entry);
byte0 = method1788(entry);
entry.anInt2223 = 0;
byte0 = method1789(entry);
entry.anInt2223 = entry.anInt2223 << 8 | byte0 & 0xff;
byte0 = method1789(entry);
entry.anInt2223 = entry.anInt2223 << 8 | byte0 & 0xff;
byte0 = method1789(entry);
entry.anInt2223 = entry.anInt2223 << 8 | byte0 & 0xff;
for (int j = 0; j < 16; j++) {
byte byte1 = method1788(entry);
if (byte1 == 1) {
entry.aBooleanArray2205[j] = true;
} else {
entry.aBooleanArray2205[j] = false;
}
}
for (int k = 0; k < 256; k++) {
entry.aBooleanArray2213[k] = false;
}
for (int l = 0; l < 16; l++) {
if (entry.aBooleanArray2205[l]) {
for (int i3 = 0; i3 < 16; i3++) {
byte byte2 = method1788(entry);
if (byte2 == 1) {
entry.aBooleanArray2213[l * 16 + i3] = true;
}
}
}
}
method1785(entry);
int i4 = entry.anInt2215 + 2;
int j4 = method1790(3, entry);
int k4 = method1790(15, entry);
for (int i1 = 0; i1 < k4; i1++) {
int j3 = 0;
do {
byte byte3 = method1788(entry);
if (byte3 == 0) {
break;
}
j3++;
} while (true);
entry.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 = entry.aByteArray2214[j1];
byte byte15 = abyte0[byte17];
for (; byte17 > 0; byte17--) {
abyte0[byte17] = abyte0[byte17 - 1];
}
abyte0[0] = byte15;
entry.aByteArray2219[j1] = byte15;
}
for (int k3 = 0; k3 < j4; k3++) {
int k6 = method1790(5, entry);
for (int k1 = 0; k1 < i4; k1++) {
do {
byte byte4 = method1788(entry);
if (byte4 == 0) {
break;
}
byte4 = method1788(entry);
if (byte4 == 0) {
k6++;
} else {
k6--;
}
} while (true);
entry.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 (entry.aByteArrayArray2229[l3][l1] > i) {
i = entry.aByteArrayArray2229[l3][l1];
}
if (entry.aByteArrayArray2229[l3][l1] < byte8) {
byte8 = entry.aByteArrayArray2229[l3][l1];
}
}
method1786(entry.anIntArrayArray2230[l3],
entry.anIntArrayArray2218[l3],
entry.anIntArrayArray2210[l3],
entry.aByteArrayArray2229[l3], byte8, i, i4);
entry.anIntArray2200[l3] = byte8;
}
int l4 = entry.anInt2215 + 1;
int i5 = -1;
int j5 = 0;
for (int i2 = 0; i2 <= 255; i2++) {
entry.anIntArray2228[i2] = 0;
}
int i9 = 4095;
for (int k8 = 15; k8 >= 0; k8--) {
for (int l8 = 15; l8 >= 0; l8--) {
entry.aByteArray2204[i9] = (byte) (k8 * 16 + l8);
i9--;
}
entry.anIntArray2226[k8] = i9 + 1;
}
int l5 = 0;
if (j5 == 0) {
i5++;
j5 = 50;
byte byte12 = entry.aByteArray2219[i5];
j8 = entry.anIntArray2200[byte12];
ai = entry.anIntArrayArray2230[byte12];
ai2 = entry.anIntArrayArray2210[byte12];
ai1 = entry.anIntArrayArray2218[byte12];
}
j5--;
int l6 = j8;
int k7;
byte byte9;
for (k7 = method1790(l6, entry); k7 > ai[l6]; k7 = k7 << 1 | byte9) {
l6++;
byte9 = method1788(entry);
}
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 = entry.aByteArray2219[i5];
j8 = entry.anIntArray2200[byte13];
ai = entry.anIntArrayArray2230[byte13];
ai2 = entry.anIntArrayArray2210[byte13];
ai1 = entry.anIntArrayArray2218[byte13];
}
j5--;
int i7 = j8;
int l7;
byte byte10;
for (l7 = method1790(i7, entry); l7 > ai[i7]; l7 = l7 << 1
| byte10) {
i7++;
byte10 = method1788(entry);
}
k5 = ai2[l7 - ai1[i7]];
} while (k5 == 0 || k5 == 1);
i6++;
byte byte5 = entry.aByteArray2211[entry.aByteArray2204[entry.anIntArray2226[0]] & 0xff];
entry.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 = entry.anIntArray2226[0];
byte6 = entry.aByteArray2204[i10 + i11];
for (; i11 > 3; i11 -= 4) {
int j11 = i10 + i11;
entry.aByteArray2204[j11] = entry.aByteArray2204[j11 - 1];
entry.aByteArray2204[j11 - 1] = entry.aByteArray2204[j11 - 2];
entry.aByteArray2204[j11 - 2] = entry.aByteArray2204[j11 - 3];
entry.aByteArray2204[j11 - 3] = entry.aByteArray2204[j11 - 4];
}
for (; i11 > 0; i11--) {
entry.aByteArray2204[i10 + i11] = entry.aByteArray2204[(i10 + i11) - 1];
}
entry.aByteArray2204[i10] = byte6;
} else {
int k10 = i11 / 16;
int l10 = i11 % 16;
int j10 = entry.anIntArray2226[k10] + l10;
byte6 = entry.aByteArray2204[j10];
for (; j10 > entry.anIntArray2226[k10]; j10--) {
entry.aByteArray2204[j10] = entry.aByteArray2204[j10 - 1];
}
entry.anIntArray2226[k10]++;
for (; k10 > 0; k10--) {
entry.anIntArray2226[k10]--;
entry.aByteArray2204[entry.anIntArray2226[k10]] = entry.aByteArray2204[(entry.anIntArray2226[k10 - 1] + 16) - 1];
}
entry.anIntArray2226[0]--;
entry.aByteArray2204[entry.anIntArray2226[0]] = byte6;
if (entry.anIntArray2226[0] == 0) {
int l9 = 4095;
for (int j9 = 15; j9 >= 0; j9--) {
for (int k9 = 15; k9 >= 0; k9--) {
entry.aByteArray2204[l9] = entry.aByteArray2204[entry.anIntArray2226[j9]
+ k9];
l9--;
}
entry.anIntArray2226[j9] = l9 + 1;
}
}
}
entry.anIntArray2228[entry.aByteArray2211[byte6 & 0xff] & 0xff]++;
anIntArray257[l5] = entry.aByteArray2211[byte6 & 0xff] & 0xff;
l5++;
if (j5 == 0) {
i5++;
j5 = 50;
byte byte14 = entry.aByteArray2219[i5];
j8 = entry.anIntArray2200[byte14];
ai = entry.anIntArrayArray2230[byte14];
ai2 = entry.anIntArrayArray2210[byte14];
ai1 = entry.anIntArrayArray2218[byte14];
}
j5--;
int j7 = j8;
int i8;
byte byte11;
for (i8 = method1790(j7, entry); i8 > ai[j7]; i8 = i8 << 1
| byte11) {
j7++;
byte11 = method1788(entry);
}
k5 = ai2[i8 - ai1[j7]];
}
}
entry.anInt2222 = 0;
entry.aByte2201 = 0;
entry.anIntArray2220[0] = 0;
for (int j2 = 1; j2 <= 256; j2++) {
entry.anIntArray2220[j2] = entry.anIntArray2228[j2 - 1];
}
for (int k2 = 1; k2 <= 256; k2++) {
entry.anIntArray2220[k2] += entry.anIntArray2220[k2 - 1];
}
for (int l2 = 0; l2 < l5; l2++) {
byte byte7 = (byte) (anIntArray257[l2] & 0xff);
anIntArray257[entry.anIntArray2220[byte7 & 0xff]] |= l2 << 8;
entry.anIntArray2220[byte7 & 0xff]++;
}
entry.anInt2208 = anIntArray257[entry.anInt2223] >> 8;
entry.anInt2227 = 0;
entry.anInt2208 = anIntArray257[entry.anInt2208];
entry.anInt2221 = (byte) (entry.anInt2208 & 0xff);
entry.anInt2208 >>= 8;
entry.anInt2227++;
entry.anInt2225 = l5;
method1787(entry);
if (entry.anInt2227 == entry.anInt2225 + 1 && entry.anInt2222 == 0) {
flag18 = true;
} else {
flag18 = false;
}
}
}
}

View file

@ -0,0 +1,26 @@
package alex.decompressors;
import java.util.zip.Inflater;
import alex.io.Stream;
public class GZipDecompressor {
private static final Inflater inflater = new Inflater(true);
public static final void decompress(Stream stream, byte output[]) {
if (~stream.payload[stream.offset] != -32
|| stream.payload[stream.offset + 1] != -117) {
throw new RuntimeException("Invalid GZIP header!");
}
try {
inflater.setInput(stream.payload, stream.offset + 10,
-stream.offset - 18 + stream.payload.length);
inflater.inflate(output);
} catch (Exception _ex) {
inflater.reset();
throw new RuntimeException("Invalid GZIP compressed data!");
}
inflater.reset();
}
}

View file

@ -0,0 +1,504 @@
package alex.io;
import java.math.BigInteger;
import alex.util.Methods;
public class Stream {
public int offset;
public byte payload[];
public Stream(byte abyte0[]) {
offset = 0;
payload = abyte0;
}
public Stream(int abyte0[]) {
offset = 0;
payload = new byte[abyte0.length];
for(int i = 0; i < payload.length; i++)
payload[i] = (byte) abyte0[i];
}
public Stream(int size) {
payload = new byte[size];
offset = 0;
}
final boolean compareCrcs() {
offset -= 4;
int i = Methods.getCrc(payload, 0, offset);
int j = getInt();
return j == i;
}
public final void decodeXTEA(int keys[], int start, int end) {
int l = offset;
offset = start;
int i1 = (end - start) / 8;
for (int j1 = 0; j1 < i1; j1++) {
int k1 = getInt();
int l1 = getInt();
int sum = 0xc6ef3720;
int delta = 0x9e3779b9;
for (int k2 = 32; k2-- > 0;) {
l1 -= keys[(sum & 0x1c84) >>> 11] + sum ^ (k1 >>> 5 ^ k1 << 4)
+ k1;
sum -= delta;
k1 -= (l1 >>> 5 ^ l1 << 4) + l1 ^ keys[sum & 3] + sum;
}
offset -= 8;
putInt(k1);
putInt(l1);
}
offset = l;
}
public final void encodeXTEA(int keys[]) {
int j = offset / 8;
offset = 0;
for (int k = 0; k < j; k++) {
int l = getInt();
int i1 = getInt();
int sum = 0;
int delta = 0x9e3779b9;
for (int l1 = 32; l1-- > 0;) {
l += sum + keys[3 & sum] ^ i1 + (i1 >>> 5 ^ i1 << 4);
sum += delta;
i1 += l + (l >>> 5 ^ l << 4) ^ keys[(0x1eec & sum) >>> 11]
+ sum;
}
offset -= 8;
putInt(l);
putInt(i1);
}
}
public final byte getByte() {
return payload[offset++];
}
final byte getByteA() {
return (byte) (payload[offset++] - 128);
}
public final void getBytes(byte buffer[], int off, int len) {
for (int k = off; k < len + off; k++) {
buffer[k] = payload[offset++];
}
}
final byte getByteS() {
return (byte) (-payload[offset++] + 128);
}
final void getBytesAReverse(byte buffer[], int off, int len) {
int l = -1 + len + off;
for (; off <= l; l--) {
buffer[l] = (byte) (payload[offset++] - 128);
}
}
final void getBytesReverse(byte buffer[], int off, int len) {
for (int l = -1 + (off + len); l >= off; l--) {
buffer[l] = payload[offset++];
}
}
final String getCheckedString() {
if (payload[offset] == 0) {
offset++;
return null;
}
return getString();
}
public final int getInt() {
offset += 4;
return ((0xff & payload[-3 + offset]) << 16)
+ ((((0xff & payload[-4 + offset]) << 24) + ((payload[-2
+ offset] & 0xff) << 8)) + (payload[-1 + offset] & 0xff));
}
final String getJStr() {
byte byte0 = payload[offset++];
if (byte0 != 0) {
throw new IllegalStateException("Bad version number in gjstr2");
}
int j = offset;
while (payload[offset++] != 0)
;
int k = -1 + offset - j;
if (k == 0) {
return "";
} else {
return Methods.getStringFromBytes(payload, j, k);
}
}
final int getLEInt() {
offset += 4;
return ((0xff & payload[offset - 1]) << 24)
+ ((0xff0000 & payload[-2 + offset] << 16)
+ ((0xff & payload[offset - 3]) << 8) + (0xff & payload[offset - 4]));
}
final int getLEShort() {
offset += 2;
int i = (0xff & payload[-2 + offset])
+ (0xff00 & payload[offset - 1] << 8);
if (i > 32767) {
i -= 0x10000;
}
return i;
}
final int getLEShortA() {
offset += 2;
int i = (-128 + payload[-2 + offset] & 0xff)
+ ((0xff & payload[offset - 1]) << 8);
if (i > 32767) {
i -= 0x10000;
}
return i;
}
final int getLEUShort() {
offset += 2;
return (payload[-2 + offset] & 0xff)
+ ((0xff & payload[-1 + offset]) << 8);
}
final int getLEUShortA() {
offset += 2;
return ((payload[offset - 1] & 0xff) << 8)
+ (-128 + payload[-2 + offset] & 0xff);
}
final long getLong() {
long l = 0xffffffffL & getInt();
long l1 = 0xffffffffL & getInt();
return l1 + (l << 32);
}
public final int getMediumInt() {
offset += 3;
return (0xff & payload[offset - 1])
+ ((payload[offset - 3] << 16 & 0xff0000) + (0xff00 & payload[offset - 2] << 8));
}
final int getMEInt1() {
offset += 4;
return ((payload[offset - 4] & 0xff) << 16)
+ (((0xff000000 & payload[offset - 3] << 24) + ((0xff & payload[offset - 1]) << 8)) + (0xff & payload[offset - 2]));
}
final int getMEInt2() {
offset += 4;
return (payload[offset - 2] << 24 & 0xff000000)
+ (((payload[-1 + offset] & 0xff) << 16) + (payload[-4 + offset] << 8 & 0xff00))
+ (0xff & payload[-3 + offset]);
}
final byte getNegByte() {
return (byte) (-payload[offset++]);
}
final int getNegUByte() {
return 0xff & -payload[offset++];
}
final long getShiftedLong(int i) {
if (--i < 0 || i > 7) {
throw new IllegalArgumentException();
}
int j = i * 8;
long l = 0L;
for (; j >= 0; j -= 8) {
l |= (payload[offset++] & 255L) << j;
}
return l;
}
public final int getShort() {
offset += 2;
int i = ((payload[offset - 2] & 0xff) << 8)
+ (0xff & payload[offset - 1]);
if (i > 32767) {
i -= 0x10000;
}
return i;
}
final int getShortA() {
offset += 2;
int j = (payload[-1 + offset] - 128 & 0xff)
+ (0xff00 & payload[offset - 2] << 8);
if (j > 32767) {
j -= 0x10000;
}
return j;
}
final int getSmallSmart() {
int i = 0xff & payload[offset];
if (i >= 128) {
return -49152 + getUShort();
} else {
return -64 + getUByte();
}
}
final int getSmart() {
int i = payload[offset] & 0xff;
if (i >= 128) {
return getUShort() - 32768;
} else {
return getUByte();
}
}
final int getSmarts() {
int i = 0;
int j;
for (j = getSmart(); j == 32767;) {
j = getSmart();
i += 32767;
}
i += j;
return i;
}
public final String getString() {
int j = offset;
while (payload[offset++] != 0)
;
int k = -1 + (offset - j);
if (k == 0) {
return "";
} else {
return Methods.getStringFromBytes(payload, j, k);
}
}
public final int getUByte() {
return payload[offset++] & 0xff;
}
final int getUByteA() {
return -128 + payload[offset++] & 0xff;
}
final int getUByteS() {
return 0xff & -payload[offset++] + 128;
}
public final int getUShort() {
offset += 2;
return (payload[offset - 2] << 8 & 0xff00)
+ (payload[offset - 1] & 0xff);
}
final int getUShortA() {
offset += 2;
return (0xff & payload[offset - 1] - 128)
+ ((0xff & payload[offset - 2]) << 8);
}
final int method124() {
byte byte1 = payload[offset++];
int i = 0;
for (; byte1 < 0; byte1 = payload[offset++]) {
i = (0x7f & byte1 | i) << 7;
}
return i | byte1;
}
public final void putByte(int i) {
payload[offset++] = (byte) i;
}
public void putString(String s) {
System.arraycopy(s.getBytes(), 0, payload, offset, s.length());
offset = offset + s.length();
putByte(0);
}
final void putByteA(int i) {
payload[offset++] = (byte) (i + 128);
}
final void putBytes(byte buffer[], int off, int len) {
for (int k = off; off + len > k; k++) {
payload[offset++] = buffer[k];
}
}
final void putByteS(int i) {
payload[offset++] = (byte) (128 - i);
}
final int putCrc(int off) {
int k = Methods.getCrc(payload, off, offset);
putInt(k);
return k;
}
final void putFlags(int i) {
if (~(0xffffff80 & i) != -1) {
if (~(i & 0xffffc000) != -1) {
if ((0xffe00000 & i) != 0) {
if ((i & 0xf0000000) != 0) {
putByte(i >>> 28 | 0x80);
}
putByte((0x10039c30 | i) >>> 21);
}
putByte((i | 0x203a0e) >>> 14);
}
putByte((0x403d | i) >>> 7);
}
putByte(i & 0x7f);
}
public final void putInt(int i) {
payload[offset++] = (byte) (i >> 24);
payload[offset++] = (byte) (i >> 16);
payload[offset++] = (byte) (i >> 8);
payload[offset++] = (byte) i;
}
final void putJStr(String s) {
int j = s.indexOf('\0');
if (j >= 0) {
throw new IllegalArgumentException("NUL character at " + j
+ " - cannot pjstr");
}
offset += Methods.getStringBytes(s, 0, s.length(), payload, offset);
payload[offset++] = 0;
}
final void putLEInt(int i) {
payload[offset++] = (byte) i;
payload[offset++] = (byte) (i >> 8);
payload[offset++] = (byte) (i >> 16);
payload[offset++] = (byte) (i >> 24);
}
final void putLEShort(int i) {
payload[offset++] = (byte) i;
payload[offset++] = (byte) (i >> 8);
}
final void putLEShortA(int i) {
payload[offset++] = (byte) (i + 128);
payload[offset++] = (byte) (i >> 8);
}
final void putLong(long l) {
payload[offset++] = (byte) (int) (l >> 56);
payload[offset++] = (byte) (int) (l >> 48);
payload[offset++] = (byte) (int) (l >> 40);
payload[offset++] = (byte) (int) (l >> 32);
payload[offset++] = (byte) (int) (l >> 24);
payload[offset++] = (byte) (int) (l >> 16);
payload[offset++] = (byte) (int) (l >> 8);
payload[offset++] = (byte) (int) l;
}
public final void putMediumInt(int j) {
payload[offset++] = (byte) (j >> 16);
payload[offset++] = (byte) (j >> 8);
payload[offset++] = (byte) j;
}
final void putMEInt1(int j) {
payload[offset++] = (byte) (j >> 16);
payload[offset++] = (byte) (j >> 24);
payload[offset++] = (byte) j;
payload[offset++] = (byte) (j >> 8);
}
final void putMEInt2(int i) {
payload[offset++] = (byte) (i >> 8);
payload[offset++] = (byte) i;
payload[offset++] = (byte) (i >> 24);
payload[offset++] = (byte) (i >> 16);
}
final void putNegByte(int i) {
payload[offset++] = (byte) (-i);
}
final void putShiftedLong(int j, long l) {
if (--j < 0 || j > 7) {
throw new IllegalArgumentException();
}
for (int k = j * 8; k >= 0; k -= 8) {
payload[offset++] = (byte) (int) (l >> k);
}
}
public final void putShort(int i) {
payload[offset++] = (byte) (i >> 8);
payload[offset++] = (byte) i;
}
final void putShortA(int i) {
payload[offset++] = (byte) (i >> 8);
payload[offset++] = (byte) (128 + i);
}
final void putSizeByte(int i) {
payload[-1 - i + offset] = (byte) i;
}
final void putSizeInt(int i) {
payload[offset - (i + 4)] = (byte) (i >> 24);
payload[-3 + (-i + offset)] = (byte) (i >> 16);
payload[-2 + (offset - i)] = (byte) (i >> 8);
payload[-i + (offset - 1)] = (byte) i;
}
final void putSizeShort(int j) {
payload[-2 + (offset - j)] = (byte) (j >> 8);
payload[-1 + offset - j] = (byte) j;
}
final void putSmart(int i) {
if (i >= 0 && i < 128) {
putByte(i);
return;
}
if (i >= 0 && i < 32768) {
putShort(i + 32768);
} else {
throw new IllegalArgumentException();
}
}
final void rsaEncode(BigInteger exponent, BigInteger modulus) {
int j = offset;
offset = 0;
byte abyte0[] = new byte[j];
getBytes(abyte0, 0, j);
BigInteger biginteger2 = new BigInteger(abyte0);
BigInteger biginteger3 = biginteger2.modPow(exponent, modulus);
byte abyte1[] = biginteger3.toByteArray();
offset = 0;
putByte(abyte1.length);
putBytes(abyte1, 0, abyte1.length);
}
}

View file

@ -0,0 +1,41 @@
package alex.util;
public class LookupTable {
private int identTable[];
public LookupTable(int ai[]) {
int i;
for (i = 1; (ai.length >> 1) + ai.length >= i; i <<= 1) {
}
identTable = new int[i + i];
for (int j = 0; i + i > j; j++) {
identTable[j] = -1;
}
for (int k = 0; ai.length > k; k++) {
int l;
for (l = -1 + i & ai[k]; ~identTable[l + l + 1] != 0; l = 1 + l
& -1 + i) {
}
identTable[l + l] = ai[k];
identTable[1 + l + l] = k;
}
}
public final int lookupIdentifier(int i) {
int k = (identTable.length >> 1) - 1;
int l = i & k;
do {
int i1 = identTable[1 + l + l];
if (i1 == -1) {
return -1;
}
if (i == identTable[l + l]) {
return i1;
}
l = l + 1 & k;
} while (true);
}
}

View file

@ -0,0 +1,372 @@
package alex.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.CRC32;
import java.util.zip.GZIPOutputStream;
import alex.CacheLoader;
import alex.compressors.BZip2OutputStream;
import alex.decompressors.BZip2Decompressor;
import alex.decompressors.GZipDecompressor;
import alex.io.Stream;
public class Methods {
public static final CRC32 CRC32 = new CRC32();
public static final int ATTACK = 0, DEFENCE = 1, STRENGTH = 2, HITPOINTS = 3, RANGE = 4, PRAYER = 5,
MAGIC = 6, COOKING = 7, WOODCUTTING = 8, FLETCHING = 9, FISHING = 10, FIREMAKING = 11,
CRAFTING = 12, SMITHING = 13, MINING = 14, HERBLORE = 15, AGILITY = 16, THIEVING = 17, SLAYER = 18,
FARMING = 19, RUNECRAFTING = 20, CONSTRUCTION = 21, HUNTER = 22, SUMMONING = 23;
public static char aCharArray5916[] = { '\u20AC', '\0', '\u201A', '\u0192',
'\u201E', '\u2026', '\u2020', '\u2021', '\u02C6', '\u2030',
'\u0160', '\u2039', '\u0152', '\0', '\u017D', '\0', '\0', '\u2018',
'\u2019', '\u201C', '\u201D', '\u2022', '\u2013', '\u2014',
'\u02DC', '\u2122', '\u0161', '\u203A', '\u0153', '\0', '\u017E',
'\u0178' };
public final static byte ANIM_IDX_ID = 20;
public final static byte ANIMFRAMES_IDX_ID = 0;
static int minLength = 0;
static int crcTable[];
public final static short CRCTABLE_IDX_ID = 255;
public final static byte GFX_IDX_ID = 21;
public final static byte HUFFMAN_IDX_ID = 10;
public final static byte INTERFACEDEF_IDX_ID = 3;
public final static byte INTERFACESCRIPT_IDX_ID = 12;
public final static byte ITEMDEF_IDX_ID = 19;
public final static byte LANDSCAPEDEF_IDX_ID = 5;
public final static byte MODELS_IDX_ID = 7;
public final static byte MUSIC_IDX_ID = 6;
public final static byte NPCDEF_IDX_ID = 18;
public final static byte OBJECTDEF_IDX_ID = 16;
public final static byte SPRITES_IDX_ID = 8;
static {
crcTable = new int[256];
for (int j = 0; j < 256; j++) {
int i = j;
for (int k = 0; k < 8; k++) {
if ((1 & i) != 1) {
i >>>= 1;
} else {
i = 0xedb88320 ^ i >>> 1;
}
}
crcTable[j] = i;
}
}
public static final int getAmountOfItems() {
int lastContainerId = CacheLoader.getFileSystems()[ITEMDEF_IDX_ID].getChildCount() -1;
return (256 * lastContainerId) + CacheLoader.getFileSystems()[ITEMDEF_IDX_ID].getChildIndexCount(lastContainerId);
//256 is the max size of each container for items(rs does that doesnt mean its limit), and then the size of last container cuz it may not be 256
}
public static final int getTableSize(int length) {
length--;
length |= length >>> -1810941663;
length |= length >>> 2010624802;
length |= length >>> 10996420;
length |= length >>> 491045480;
length |= length >>> 1388313616;
return 1 + length;
}
public static final byte[] copyBuffer(byte buffer[]) {
int len = buffer.length;
byte copy[] = new byte[len];
System.arraycopy(buffer, 0, copy, 0, len);
return copy;
}
public static final int getCrc(byte buffer[], int len) {
return getCrc(buffer, 0, len);
}
public static final int getCrc(byte buffer[], int off, int len) {
int l = -1;
for (int i1 = off; len > i1; i1++) {
l = crcTable[(buffer[i1] ^ l) & 0xff] ^ l >>> 8;
}
l = ~l;
return l;
}
public static final int getStringBytes(String s, int strOff, int strLen,
byte buffer[], int bufOff) {
int l = -strOff + strLen;
for (int i1 = 0; i1 < l; i1++) {
char c = s.charAt(strOff + i1);
if (c > '\0' && c < '\200' || c >= '\240' && c <= '\377') {
buffer[i1 + bufOff] = (byte) c;
} else if (c == '\u20AC') {
buffer[i1 + bufOff] = -128;
} else if (c != '\u201A') {
if (c == '\u0192') {
buffer[bufOff + i1] = -125;
} else if (c != '\u201E') {
if (c == '\u2026') {
buffer[bufOff + i1] = -123;
} else if (c != '\u2020') {
if (c == '\u2021') {
buffer[bufOff + i1] = -121;
} else if (c != '\u02C6') {
if (c == '\u2030') {
buffer[i1 + bufOff] = -119;
} else if (c == '\u0160') {
buffer[bufOff + i1] = -118;
} else if (c == '\u2039') {
buffer[i1 + bufOff] = -117;
} else if (c == '\u0152') {
buffer[i1 + bufOff] = -116;
} else if (c == '\u017D') {
buffer[i1 + bufOff] = -114;
} else if (c == '\u2018') {
buffer[i1 + bufOff] = -111;
} else if (c == '\u2019') {
buffer[i1 + bufOff] = -110;
} else if (c == '\u201C') {
buffer[bufOff + i1] = -109;
} else if (c == '\u201D') {
buffer[i1 + bufOff] = -108;
} else if (c == '\u2022') {
buffer[i1 + bufOff] = -107;
} else if (c != '\u2013') {
if (c == '\u2014') {
buffer[i1 + bufOff] = -105;
} else if (c != '\u02DC') {
if (c != '\u2122') {
if (c == '\u0161') {
buffer[i1 + bufOff] = -102;
} else if (c == '\u203A') {
buffer[bufOff + i1] = -101;
} else if (c == '\u0153') {
buffer[bufOff + i1] = -100;
} else if (c == '\u017E') {
buffer[bufOff + i1] = -98;
} else if (c == '\u0178') {
buffer[i1 + bufOff] = -97;
} else {
buffer[i1 + bufOff] = 63;
}
} else {
buffer[bufOff + i1] = -103;
}
} else {
buffer[i1 + bufOff] = -104;
}
} else {
buffer[i1 + bufOff] = -106;
}
} else {
buffer[i1 + bufOff] = -120;
}
} else {
buffer[bufOff + i1] = -122;
}
} else {
buffer[i1 + bufOff] = -124;
}
} else {
buffer[bufOff + i1] = -126;
}
}
return l;
}
public static final String getStringFromBytes(byte buffer[], int off,
int len) {
char ac[] = new char[len];
int l = 0;
for (int i1 = 0; len > i1; i1++) {
int j1 = 0xff & buffer[off + i1];
if (j1 != 0) {
if (j1 >= 128 && j1 < 160) {
char c = aCharArray5916[-128 + j1];
if (c == 0) {
c = '?';
}
j1 = c;
}
ac[l++] = (char) j1;
}
}
return new String(ac, 0, l);
}
public static final int hashFile(String name) {
int j = name.length();
int k = 0;
for (int l = 0; l < j; l++) {
k = method1258(name.charAt(l)) + ((k << 5) - k);
}
return k;
}
static final byte method1258(char c) {
byte byte0;
if (c > 0 && c < '\200' || c >= '\240' && c <= '\377') {
byte0 = (byte) c;
} else if (c != '\u20AC') {
if (c != '\u201A') {
if (c != '\u0192') {
if (c == '\u201E') {
byte0 = -124;
} else if (c != '\u2026') {
if (c != '\u2020') {
if (c == '\u2021') {
byte0 = -121;
} else if (c == '\u02C6') {
byte0 = -120;
} else if (c == '\u2030') {
byte0 = -119;
} else if (c == '\u0160') {
byte0 = -118;
} else if (c == '\u2039') {
byte0 = -117;
} else if (c == '\u0152') {
byte0 = -116;
} else if (c != '\u017D') {
if (c == '\u2018') {
byte0 = -111;
} else if (c != '\u2019') {
if (c != '\u201C') {
if (c == '\u201D') {
byte0 = -108;
} else if (c != '\u2022') {
if (c == '\u2013') {
byte0 = -106;
} else if (c == '\u2014') {
byte0 = -105;
} else if (c == '\u02DC') {
byte0 = -104;
} else if (c == '\u2122') {
byte0 = -103;
} else if (c != '\u0161') {
if (c == '\u203A') {
byte0 = -101;
} else if (c != '\u0153') {
if (c == '\u017E') {
byte0 = -98;
} else if (c != '\u0178') {
byte0 = 63;
} else {
byte0 = -97;
}
} else {
byte0 = -100;
}
} else {
byte0 = -102;
}
} else {
byte0 = -107;
}
} else {
byte0 = -109;
}
} else {
byte0 = -110;
}
} else {
byte0 = -114;
}
} else {
byte0 = -122;
}
} else {
byte0 = -123;
}
} else {
byte0 = -125;
}
} else {
byte0 = -126;
}
} else {
byte0 = -128;
}
return byte0;
}
static int method664(int i, int j) {
return i ^ j;
}
public static final byte[] packContainer(int compression, byte[] data) {
Stream stream = new Stream(data.length+100); //lets be sure enougth space
if(compression == 1) //we dont have compression 1 working
compression = 2;
stream.putByte(compression);
byte[] compressedData = null;
if(compression == 0) {
compressedData = data;
}else if(compression == 1) {//BZip2Compressor
ByteArrayOutputStream compressedBytes = new ByteArrayOutputStream();
try {
BZip2OutputStream out = new BZip2OutputStream(compressedBytes, 9);
out.write(data);
out.finish();
out.close();
compressedData = compressedBytes.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
}else if (compression >= 2) { //GZipCompressor
ByteArrayOutputStream compressedBytes = new ByteArrayOutputStream();
try {
GZIPOutputStream out = new GZIPOutputStream(compressedBytes);
out.write(data);
out.finish();
out.close();
compressedData = compressedBytes.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
}
stream.putInt(compressedData.length);
if(compression >= 1)
stream.putInt(data.length);
for(int index = 0; index < compressedData.length; index++)
stream.putByte(compressedData[index]);
byte[] readyFileData = new byte[stream.offset];
stream.offset = 0;
stream.getBytes(readyFileData, 0, readyFileData.length);
return readyFileData;
}
public static final byte[] unpackContainer(byte buffer[]) {
Stream stream = new Stream(buffer);
int compression = stream.getUByte();
int fileSize = stream.getInt();
if (fileSize < 0 || minLength != 0 && minLength < fileSize) {
throw new RuntimeException();
}
if (compression == 0) {
byte unpacked[] = new byte[fileSize];
stream.getBytes(unpacked, 0, fileSize);
return unpacked;
}
int decompressedSize = stream.getInt();
if (decompressedSize < 0 || minLength != 0 && minLength < decompressedSize) {
throw new RuntimeException();
}
byte decompressed[] = new byte[decompressedSize];
if (compression != 1) {
GZipDecompressor.decompress(stream, decompressed);
} else {
BZip2Decompressor.decompress(decompressed, decompressedSize, buffer, fileSize, 9);
}
return decompressed;
}
}

View file

@ -0,0 +1,263 @@
package com.alex.io;
import com.alex.utils.Constants;
public final class InputStream extends Stream {
public void initBitAccess() {
bitPosition = offset * 8;
}
private static final int[] BIT_MASK = new int[] { 0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023,
2047, 4095, 8191, 16383, 32767, 65535, 131071, 262143, 524287,
1048575, 2097151, 4194303, 8388607, 16777215, 33554431, 67108863,
134217727, 268435455, 536870911, 1073741823, 2147483647, -1 };
public void finishBitAccess() {
offset = (7 + bitPosition) / 8;
}
public int readBits(int bitOffset) {
int bytePos = bitPosition >> 1779819011;
int i_8_ = -(0x7 & bitPosition) + 8;
bitPosition += bitOffset;
int value = 0;
for (/**/; (bitOffset ^ 0xffffffff) < (i_8_ ^ 0xffffffff); i_8_ = 8) {
value += (BIT_MASK[i_8_] & buffer[bytePos++]) << -i_8_ + bitOffset;
bitOffset -= i_8_;
}
if ((i_8_ ^ 0xffffffff) == (bitOffset ^ 0xffffffff))
value += buffer[bytePos] & BIT_MASK[i_8_];
else
value += (buffer[bytePos] >> -bitOffset + i_8_ & BIT_MASK[bitOffset]);
return value;
}
public InputStream(int capacity) {
buffer = new byte[capacity];
}
public InputStream(byte[] buffer) {
this.buffer = buffer;
this.length = buffer.length;
}
public void checkCapacity(int length) {
if (offset + length >= buffer.length) {
byte[] newBuffer = new byte[(offset + length) * 2];
System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
buffer = newBuffer;
}
}
public void skip(int length) {
offset += length;
}
public void setLength(int length) {
this.length = length;
}
public void setOffset(int offset) {
this.offset = offset;
}
public int getRemaining() {
return offset < length ? length - offset : 0;
}
public void addBytes(byte[] b, int offset, int length) {
checkCapacity(length - offset);
System.arraycopy(b, offset, buffer, this.offset, length);
this.length += length - offset;
}
public int readPacket() {
return readUnsignedByte();
}
public int readByte() {
return getRemaining() > 0 ? buffer[offset++] : 0;
}
public void readBytes(byte buffer[], int off, int len) {
for (int k = off; k < len + off; k++) {
buffer[k] = (byte) readByte();
}
}
public void readBytes(byte buffer[]) {
readBytes(buffer, 0, buffer.length);
}
public int readSmart2() {
int i = 0;
int i_33_ = readUnsignedSmart();
while ((i_33_ ^ 0xffffffff) == -32768) {
i_33_ = readUnsignedSmart();
i += 32767;
}
i += i_33_;
return i;
}
public int readUnsignedByte() {
return readByte() & 0xff;
}
public int readByte128() {
return (byte) (readByte() - 128);
}
public int readByteC() {
return (byte) -readByte();
}
public int read128Byte() {
return (byte) (128 - readByte());
}
public int readUnsignedByte128() {
return readUnsignedByte() - 128 & 0xff;
}
public int readUnsignedByteC() {
return -readUnsignedByte() & 0xff;
}
public int readUnsigned128Byte() {
return 128 - readUnsignedByte() & 0xff;
}
public int readShortLE() {
int i = readUnsignedByte() + (readUnsignedByte() << 8);
if (i > 32767) {
i -= 0x10000;
}
return i;
}
public int readShort128() {
int i = (readUnsignedByte() << 8) + (readByte() - 128 & 0xff);
if (i > 32767) {
i -= 0x10000;
}
return i;
}
public int readShortLE128() {
int i = (readByte() - 128 & 0xff) + (readUnsignedByte() << 8);
if (i > 32767) {
i -= 0x10000;
}
return i;
}
public int read128ShortLE() {
int i = (128 - readByte() & 0xff) + (readUnsignedByte() << 8);
if (i > 32767) {
i -= 0x10000;
}
return i;
}
public int readShort() {
int i = (readUnsignedByte() << 8) + readUnsignedByte();
if (i > 32767) {
i -= 0x10000;
}
return i;
}
public int readUnsignedShortLE() {
return readUnsignedByte() + (readUnsignedByte() << 8);
}
public int readUnsignedShort() {
return (readUnsignedByte() << 8) + readUnsignedByte();
}
public int readUnsignedShort128() {
return (readUnsignedByte() << 8) + (readByte() - 128 & 0xff);
}
public int readUnsignedShortLE128() {
return (readByte() - 128 & 0xff) + (readUnsignedByte() << 8);
}
public int readInt() {
return (readUnsignedByte() << 24) + (readUnsignedByte() << 16)
+ (readUnsignedByte() << 8) + readUnsignedByte();
}
public int read24BitInt() {
return (readUnsignedByte() << 16) + (readUnsignedByte() << 8)
+ (readUnsignedByte());
}
public int readIntV1() {
return (readUnsignedByte() << 8) + readUnsignedByte()
+ (readUnsignedByte() << 24) + (readUnsignedByte() << 16);
}
public int readIntV2() {
return (readUnsignedByte() << 16) + (readUnsignedByte() << 24)
+ readUnsignedByte() + (readUnsignedByte() << 8);
}
public int readIntLE() {
return readUnsignedByte() + (readUnsignedByte() << 8)
+ (readUnsignedByte() << 16) + (readUnsignedByte() << 24);
}
public long readLong() {
long l = readInt() & 0xffffffffL;
long l1 = readInt() & 0xffffffffL;
return (l << 32) + l1;
}
public String readString() {
String s = "";
int b;
while ((b = readByte()) != 0) {
s += (char) b;
}
return s;
}
public String readJagString() {
readByte();
String s = "";
int b;
while ((b = readByte()) != 0) {
s += (char) b;
}
return s;
}
@SuppressWarnings("unused")
public int readBigSmart() {
if(Constants.CLIENT_BUILD < 670)
return readUnsignedShort();
if ((buffer[offset] ^ 0xffffffff) <= -1) {
int value = readUnsignedShort();
if (value == 32767) {
return -1;
}
return value;
}
return readInt() & 0x7fffffff;
}
public int readUnsignedSmart() {
int i = 0xff & buffer[offset];
if (i >= 128)
return -32768 + readUnsignedShort();
return readUnsignedByte();
}
}

View file

@ -0,0 +1,335 @@
package com.alex.io;
import java.math.BigInteger;
import com.alex.utils.Constants;
public final class OutputStream extends Stream {
private static final int[] BIT_MASK = new int[32];
private int opcodeStart = 0;
static {
for (int i = 0; i < 32; i++)
BIT_MASK[i] = (1 << i) - 1;
}
public OutputStream(int capacity) {
setBuffer(new byte[capacity]);
}
public OutputStream() {
setBuffer(new byte[16]);
}
public OutputStream(byte[] buffer) {
this.setBuffer(buffer);
this.offset = buffer.length;
length = buffer.length;
}
public OutputStream(int[] buffer) {
setBuffer(new byte[buffer.length]);
for(int value : buffer)
writeByte(value);
}
public void checkCapacityPosition(int position) {
if (position >= getBuffer().length) {
byte[] newBuffer = new byte[position + 16];
System.arraycopy(getBuffer(), 0, newBuffer, 0, getBuffer().length);
setBuffer(newBuffer);
}
}
public void skip(int length) {
setOffset(getOffset() + length);
}
public void setOffset(int offset) {
this.offset = offset;
}
public void writeBytes(byte[] b, int offset, int length) {
checkCapacityPosition(this.getOffset() + length - offset);
System.arraycopy(b, offset, getBuffer(), this.getOffset(), length);
this.setOffset(this.getOffset() + (length - offset));
}
public void writeBytes(byte[] b) {
int offset = 0;
int length = b.length;
checkCapacityPosition(this.getOffset() + length - offset);
System.arraycopy(b, offset, getBuffer(), this.getOffset(), length);
this.setOffset(this.getOffset() + (length - offset));
}
public void addBytes128(byte[] data, int offset, int len) {
for (int k = offset; k < len; k++)
writeByte((byte) (data[k] + 128));
}
public void addBytesS(byte[] data, int offset, int len) {
for (int k = offset; k < len; k++)
writeByte((byte) (-128 + data[k]));
}
public void addBytes_Reverse(byte[] data, int offset, int len) {
for (int i = len - 1; i >= 0; i--) {
writeByte((byte) (data[i]));
}
}
public void addBytes_Reverse128(byte[] data, int offset, int len) {
for (int i = len - 1; i >= 0; i--) {
writeByte((byte) (data[i] + 128));
}
}
public void writeByte(int i) {
writeByte(i, offset++);
}
public void writeNegativeByte(int i) {
writeByte(-i, offset++);
}
public void writeByte(int i, int position) {
checkCapacityPosition(position);
getBuffer()[position] = (byte) i;
}
public void writeByte128(int i) {
writeByte(i + 128);
}
public void writeByteC(int i) {
writeByte(-i);
}
public void write3Byte(int i) {
writeByte(i >> 16);
writeByte(i >> 8);
writeByte(i);
}
public void write128Byte(int i) {
writeByte(128 - i);
}
public void writeShortLE128(int i) {
writeByte(i + 128);
writeByte(i >> 8);
}
public void writeShort128(int i) {
writeByte(i >> 8);
writeByte(i + 128);
}
@SuppressWarnings("unused")
public void writeBigSmart(int i) {
if(Constants.CLIENT_BUILD < 670) {
writeShort(i);
return;
}
if(i >= Short.MAX_VALUE && i >= 0)
writeInt(i-Integer.MAX_VALUE-1);
else {
writeShort(i >= 0 ? i : 32767);
}
}
public void writeSmart2(int i) {
while (i >= 0) {
if (i < 32767) {
writeSmart(i);
return;
}
writeSmart(32767);
i -= 32767;
}
}
public void writeSmart(int i) {
if (i >= 128) {
writeShort(i + 32768);
} else {
writeByte(i);
}
}
public void writeShort(int i) {
writeByte(i >> 8);
writeByte(i);
}
public void writeShortLE(int i) {
writeByte(i);
writeByte(i >> 8);
}
public void write24BitInt(int i) {
writeByte(i >> 16);
writeByte(i >> 8);
writeByte(i);
}
@Override
public void writeInt(int i) {
writeByte(i >> 24);
writeByte(i >> 16);
writeByte(i >> 8);
writeByte(i);
}
public void writeIntV1(int i) {
writeByte(i >> 8);
writeByte(i);
writeByte(i >> 24);
writeByte(i >> 16);
}
public void writeIntV2(int i) {
writeByte(i >> 16);
writeByte(i >> 24);
writeByte(i);
writeByte(i >> 8);
}
public void writeIntLE(int i) {
writeByte(i);
writeByte(i >> 8);
writeByte(i >> 16);
writeByte(i >> 24);
}
public void writeLong(long l) {
writeByte((int) (l >> 56));
writeByte((int) (l >> 48));
writeByte((int) (l >> 40));
writeByte((int) (l >> 32));
writeByte((int) (l >> 24));
writeByte((int) (l >> 16));
writeByte((int) (l >> 8));
writeByte((int) l);
}
public void writePSmarts(int i) {
if (i < 128) {
writeByte(i);
return;
}
if (i < 32768) {
writeShort(32768 + i);
return;
} else {
System.out.println("Error psmarts out of range:");
return;
}
}
public void writeString(String s) {
checkCapacityPosition(getOffset() + s.length() + 1);
System.arraycopy(s.getBytes(), 0, getBuffer(), getOffset(), s.length());
setOffset(getOffset() + s.length());
writeByte(0);
}
public void writeGJString(String s) {
writeByte(0);
writeString(s);
}
public void putGJString3(String s) {
writeByte(0);
writeString(s);
writeByte(0);
}
public void writePacket(int id) {
writeByte(id);
}
public void writePacketVarByte(int id) {
writePacket(id);
writeByte(0);
opcodeStart = getOffset() - 1;
}
public void writePacketVarShort(int id) {
writePacket(id);
writeShort(0);
opcodeStart = getOffset() - 2;
}
/*
* public void writePacketShort(int id) { writeByte(id); writeShort(0);
* opcodeStart = getOffset() - 2; }
*/
public void endPacketVarByte() {
writeByte(getOffset() - (opcodeStart + 2) + 1, opcodeStart);
}
public void endPacketVarShort() {
int size = getOffset() - (opcodeStart + 2);
writeByte(size >> 8, opcodeStart++);
writeByte(size, opcodeStart);
}
public void initBitAccess() {
bitPosition = getOffset() * 8;
}
public void finishBitAccess() {
setOffset((bitPosition + 7) / 8);
}
public int getBitPos(int i) {
return 8 * i - bitPosition;
}
public void writeBits(int numBits, int value) {
int bytePos = bitPosition >> 3;
int bitOffset = 8 - (bitPosition & 7);
bitPosition += numBits;
for (; numBits > bitOffset; bitOffset = 8) {
checkCapacityPosition(bytePos);
getBuffer()[bytePos] &= ~BIT_MASK[bitOffset];
getBuffer()[bytePos++] |= value >> numBits - bitOffset
& BIT_MASK[bitOffset];
numBits -= bitOffset;
}
checkCapacityPosition(bytePos);
if (numBits == bitOffset) {
getBuffer()[bytePos] &= ~BIT_MASK[bitOffset];
getBuffer()[bytePos] |= value & BIT_MASK[bitOffset];
} else {
getBuffer()[bytePos] &= ~(BIT_MASK[numBits] << bitOffset - numBits);
getBuffer()[bytePos] |= (value & BIT_MASK[numBits]) << bitOffset
- numBits;
}
}
public void setBuffer(byte[] buffer) {
this.buffer = buffer;
}
public final void rsaEncode(BigInteger key, BigInteger modulus) {
int length = offset;
offset = 0;
byte data[] = new byte[length];
getBytes(data, 0, length);
BigInteger biginteger2 = new BigInteger(data);
BigInteger biginteger3 = biginteger2.modPow(key, modulus);
byte out[] = biginteger3.toByteArray();
offset = 0;
writeBytes(out, 0, out.length);
}
}

View file

@ -0,0 +1,94 @@
package com.alex.io;
public abstract class Stream {
protected int offset;
protected int length;
protected byte[] buffer;
protected int bitPosition;
public int getLength() {
return length;
}
public byte[] getBuffer() {
return buffer;
}
public int getOffset() {
return offset;
}
public void decodeXTEA(int keys[]) {
decodeXTEA(keys, 5, length);
}
public void decodeXTEA(int keys[], int start, int end) {
int l = offset;
offset = start;
int i1 = (end - start) / 8;
for (int j1 = 0; j1 < i1; j1++) {
int k1 = readInt();
int l1 = readInt();
int sum = 0xc6ef3720;
int delta = 0x9e3779b9;
for (int k2 = 32; k2-- > 0;) {
l1 -= keys[(sum & 0x1c84) >>> 11] + sum ^ (k1 >>> 5 ^ k1 << 4)
+ k1;
sum -= delta;
k1 -= (l1 >>> 5 ^ l1 << 4) + l1 ^ keys[sum & 3] + sum;
}
offset -= 8;
writeInt(k1);
writeInt(l1);
}
offset = l;
}
public final void encodeXTEA(int keys[], int start, int end) {
int o = offset;
int j = (end - start) / 8;
offset = start;
for (int k = 0; k < j; k++) {
int l = readInt();
int i1 = readInt();
int sum = 0;
int delta = 0x9e3779b9;
for (int l1 = 32; l1-- > 0;) {
l += sum + keys[3 & sum] ^ i1 + (i1 >>> 5 ^ i1 << 4);
sum += delta;
i1 += l + (l >>> 5 ^ l << 4) ^ keys[(0x1eec & sum) >>> 11]
+ sum;
}
offset -= 8;
writeInt(l);
writeInt(i1);
}
offset = o;
}
private final int readInt() {
offset += 4;
return ((0xff & buffer[-3 + offset]) << 16)
+ ((((0xff & buffer[-4 + offset]) << 24) + ((buffer[-2
+ offset] & 0xff) << 8)) + (buffer[-1 + offset] & 0xff));
}
public void writeInt(int value) {
buffer[offset++] = (byte) (value >> 24);
buffer[offset++] = (byte) (value >> 16);
buffer[offset++] = (byte) (value >> 8);
buffer[offset++] = (byte) value;
}
public final void getBytes(byte data[], int off, int len) {
for (int k = off; k < len + off; k++) {
data[k] = buffer[offset++];
}
}
}

View file

@ -0,0 +1,253 @@
package com.alex.loaders.clientscripts;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import com.alex.store.Store;
import com.alex.utils.ByteBufferUtils;
/**
* The CS2 mapping.
* @author Emperor
*
*/
public final class CS2Mapping {
/**
* The CS2 mappings.
*/
private static final Map<Integer, CS2Mapping> maps = new HashMap<>();
/**
* The script id.
*/
private final int scriptId;
/**
* Unknown value.
*/
private int unknown;
/**
* Second unknown value.
*/
private int unknown1;
/**
* The default string value.
*/
private String defaultString;
/**
* The default integer value.
*/
private int defaultInt;
/**
* The mapping.
*/
private HashMap<Integer, Object> map;
/**
* Constructs a new {@code CS2Mapping} {@code Object}.
* @param scriptId The script id.
*/
public CS2Mapping(int scriptId) {
this.scriptId = scriptId;
}
/**
* The main method.
* @param args The arguments cast on runtime.
* @throws Throwable When an exception occurs.
*/
public static void main(String...args) throws Throwable {
Store store = new Store("./666/");
BufferedWriter bw = new BufferedWriter(new FileWriter("./music_indexes.txt"));
CS2Mapping musicList = forId(1347, store);
CS2Mapping idList = forId(1351, store);
for (int index : musicList.map.keySet()) {
String name = (String) musicList.map.get(index);
int id = (int) idList.map.get(index);
bw.append(name + ": " + id);
bw.newLine();
}
// for (int i = 0; i < 20000; i++) {
// CS2Mapping mapping = forId(i, store);
// if (mapping == null || mapping.map == null) {
// continue;
// }
// bw.append(i + " - [default=" + mapping.defaultString + "/" + mapping.defaultInt + "] map=" + mapping.map);
// bw.newLine();
// }
bw.flush();
bw.close();
}
/**
* Gets the mapping for the given script id.
* @param scriptId The script id.
* @return The mapping.
*/
public static CS2Mapping forId(int scriptId, Store store) {
CS2Mapping mapping = maps.get(scriptId);
if (mapping != null) {
return mapping;
}
mapping = new CS2Mapping(scriptId);
byte[] bs = store.getIndexes()[17].getFile(scriptId >>> 8, scriptId & 0xFF);
if (bs != null) {
mapping.load(ByteBuffer.wrap(bs));
} else {
return null;
}
maps.put(scriptId, mapping);
return mapping;
}
/**
* Loads the mapping data.
* @param stream The buffer to read the data from.
*/
private void load(ByteBuffer buffer) {
int opcode;
while ((opcode = buffer.get() & 0xFF) != 0) {
switch (opcode) {
case 1:
unknown = buffer.get() & 0xFF;
break;
case 2:
unknown1 = buffer.get() & 0xFF;
break;
case 3:
defaultString = ByteBufferUtils.getString(buffer);
break;
case 4:
defaultInt = buffer.getInt();
break;
case 5:
case 6:
case 7:
case 8:
int size = buffer.getShort() & 0xFFFF;
map = new HashMap<>(size);
int loop = opcode > 6 ? buffer.getShort() & 0xFFFF : size;
for (int i = 0; i < loop; i++) {
int key = opcode > 6 ? buffer.getShort() & 0xFFFF : buffer.getInt();
if (opcode % 2 != 0) {
map.put(key, ByteBufferUtils.getString(buffer));
} else {
map.put(key, buffer.getInt());
}
}
break;
/*
* else if (opcode == 5 || opcode == 6 || opcode == 7 || opcode == 8) {
int count = stream.readUnsignedShort();
int loop = opcode == 7 || opcode == 8 ? stream.readUnsignedShort()
: count;
values = new HashMap<Long, Object>(Utils.getHashMapSize(count));
for (int i = 0; i < loop; i++) {
int key = opcode == 7 || opcode == 8 ? stream
.readUnsignedShort() : stream.readInt();
Object value = opcode == 5 || opcode == 7 ? stream.readString()
: stream.readInt();
values.put((long) key, value);
}
}
*/
}
}
}
/**
* Gets the scriptId.
* @return The scriptId.
*/
public int getScriptId() {
return scriptId;
}
/**
* Gets the unknown.
* @return The unknown.
*/
public int getUnknown() {
return unknown;
}
/**
* Sets the unknown.
* @param unknown The unknown to set.
*/
public void setUnknown(int unknown) {
this.unknown = unknown;
}
/**
* Gets the unknown1.
* @return The unknown1.
*/
public int getUnknown1() {
return unknown1;
}
/**
* Sets the unknown1.
* @param unknown1 The unknown1 to set.
*/
public void setUnknown1(int unknown1) {
this.unknown1 = unknown1;
}
/**
* Gets the defaultString.
* @return The defaultString.
*/
public String getDefaultString() {
return defaultString;
}
/**
* Sets the defaultString.
* @param defaultString The defaultString to set.
*/
public void setDefaultString(String defaultString) {
this.defaultString = defaultString;
}
/**
* Gets the defaultInt.
* @return The defaultInt.
*/
public int getDefaultInt() {
return defaultInt;
}
/**
* Sets the defaultInt.
* @param defaultInt The defaultInt to set.
*/
public void setDefaultInt(int defaultInt) {
this.defaultInt = defaultInt;
}
/**
* Gets the map.
* @return The map.
*/
public HashMap<Integer, Object> getMap() {
return map;
}
/**
* Sets the map.
* @param map The map to set.
*/
public void setMap(HashMap<Integer, Object> map) {
this.map = map;
}
}

View file

@ -0,0 +1,5 @@
package com.alex.loaders.clientscripts;
public class ClientScript {
}

View file

@ -0,0 +1,336 @@
package com.alex.loaders.images;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import com.alex.io.InputStream;
import com.alex.io.OutputStream;
import com.alex.store.Store;
import com.alex.utils.Constants;
public final class IndexedColorImageFile {
private BufferedImage[] images;
public static boolean oldRevision = true;
private int pallete[];
private int pixelsIndexes[][];
private byte alpha[][];
private boolean[] usesAlpha;
private int biggestWidth;
private int biggestHeight;
private int[] minX;
private int[] minY;
public IndexedColorImageFile(BufferedImage... images) {
this.images = images;
}
public IndexedColorImageFile(Store cache, int archiveId, int fileId) {
this(cache, Constants.SPRITES_INDEX, archiveId, fileId);
}
/*
*
*/
public IndexedColorImageFile(Store cache, int idx, int archiveId, int fileId) {
decodeArchive(cache, idx, archiveId, fileId);
}
public void decodeArchive(Store cache, int idx, int archiveId, int fileId) {
byte[] data = cache.getIndexes()[idx].getFile(archiveId, fileId);
if(data == null)
return;
InputStream stream = new InputStream(data);
stream.setOffset(data.length - 2);
int count = stream.readUnsignedShort();
images = new BufferedImage[count];
pixelsIndexes = new int[images.length][];
alpha = new byte[images.length][];
usesAlpha = new boolean[images.length];
minX = new int[images.length];
minY = new int[images.length];
int[] imagesWidth = new int[images.length];
int[] imagesHeight = new int[images.length];
stream.setOffset(data.length - 7 - images.length * 8);
setBiggestWidth(stream.readShort()); //biggestWidth
setBiggestHeight(stream.readShort()); //biggestHeight
int palleteLength = (stream.readUnsignedByte() & 0xff) + 1;
for (int index = 0; index < images.length; index++) {
minX[index] = stream.readUnsignedShort();
if (minX[index] != 0) {
// System.out.println("Hai x " + minX[index] + ", index " + index + ", length " + images.length);
}
}
for (int index = 0; index < images.length; index++) {
minY[index] = stream.readUnsignedShort();
if (minY[index] != 0) {
//System.out.println("Hai y " + minY[index] + ", index " + index + ", length " + images.length);
}
}
for (int index = 0; index < images.length; index++) {
imagesWidth[index] = stream.readUnsignedShort();
}
for (int index = 0; index < images.length; index++) {
imagesHeight[index] = stream.readUnsignedShort();
}
stream.setOffset(data.length - 7 - images.length * 8 - (palleteLength - 1) * 3);
pallete = new int[palleteLength];
for (int index = 1; index < palleteLength; index++) {
pallete[index] = stream.read24BitInt();
if (pallete[index] == 0)
pallete[index] = 1;
}
stream.setOffset(0);
for (int i_20_ = 0; i_20_ < images.length; i_20_++) {
int pixelsIndexesLength = imagesWidth[i_20_] * imagesHeight[i_20_];
pixelsIndexes[i_20_] = new int[pixelsIndexesLength];
alpha[i_20_] = new byte[pixelsIndexesLength];
int maskData = stream.readUnsignedByte();
if ((maskData & 0x2) == 0) {
if ((maskData & 0x1) == 0) {
for (int index = 0; index < pixelsIndexesLength; index++) {
pixelsIndexes[i_20_][index] = (byte) stream.readByte();
}
} else {
for (int i_24_ = 0; i_24_ < imagesWidth[i_20_]; i_24_++) {
for (int i_25_ = 0; i_25_ < imagesHeight[i_20_]; i_25_++) {
pixelsIndexes[i_20_][i_24_ + i_25_ * imagesWidth[i_20_]] = (byte) stream.readByte();
}
}
}
} else {
usesAlpha[i_20_] = true;
boolean bool = false;
if ((maskData & 0x1) == 0) {
for (int index = 0; index < pixelsIndexesLength; index++) {
pixelsIndexes[i_20_][index] = (byte) stream.readByte();
}
for (int i_27_ = 0; i_27_ < pixelsIndexesLength; i_27_++) {
byte i_28_ = (alpha[i_20_][i_27_] = (byte) stream.readByte());
bool = bool | i_28_ != -1;
}
} else {
for (int i_29_ = 0; i_29_ < imagesWidth[i_20_]; i_29_++) {
for (int i_30_ = 0; i_30_ < imagesHeight[i_20_]; i_30_++) {
pixelsIndexes[i_20_][i_29_ + i_30_ * imagesWidth[i_20_]] = stream.readByte();
}
}
for (int i_31_ = 0; i_31_ < imagesWidth[i_20_]; i_31_++) {
for (int i_32_ = 0; i_32_ < imagesHeight[i_20_]; i_32_++) {
byte i_33_ = (alpha[i_20_][i_31_ + i_32_
* imagesWidth[i_20_]] = (byte) stream.readByte());
bool = bool | i_33_ != -1;
}
}
}
if (!bool)
alpha[i_20_] = null;
}
images[i_20_] = getBufferedImage(imagesWidth[i_20_], imagesHeight[i_20_], pixelsIndexes[i_20_], alpha[i_20_], usesAlpha[i_20_]);
}
}
public BufferedImage getBufferedImage(int width, int height, int[] pixelsIndexes, byte[] extraPixels, boolean useExtraPixels) {
if(width <= 0 || height <= 0)
return null;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
int[] rgbArray = new int[width * height];
int i = 0;
int i_43_ = 0;
if(useExtraPixels && extraPixels != null) {
for (int i_44_ = 0; i_44_ < height; i_44_++) {
for (int i_45_ = 0; i_45_ < width; i_45_++) {
rgbArray[i_43_++] = (extraPixels[i] << 24 | (pallete[pixelsIndexes[i] & 0xff]));
i++;
}
}
}else{
for (int i_46_ = 0; i_46_ < height; i_46_++) {
for (int i_47_ = 0; i_47_ < width; i_47_++) {
int i_48_ = pallete[pixelsIndexes[i++] & 0xff];
rgbArray[i_43_++] = i_48_ != 0 ? ~0xffffff | i_48_ : 0;
}
}
}
image.setRGB(0, 0, width, height, rgbArray, 0, width);
image.flush();
return image;
}
public byte[] encodeFile() {
if(pallete == null) //if not generated yet
generatePallete();
OutputStream stream = new OutputStream();
//sets pallete indexes and int size bytes
for(int imageId = 0; imageId < images.length; imageId++) {
int pixelsMask = 0;
if(usesAlpha[imageId] && !oldRevision)
pixelsMask |= 0x2;
//pixelsMask |= 0x1; //sets read all rgbarray indexes 1by1
stream.writeByte(pixelsMask);
for (int index = 0; index < pixelsIndexes[imageId].length; index++)
stream.writeByte(pixelsIndexes[imageId][index]);
if(usesAlpha[imageId] && !oldRevision)
for (int index = 0; index < alpha[imageId].length; index++)
stream.writeByte(alpha[imageId][index]);
}
//sets up to 256colors pallete, index0 is black
for(int index = 0; index < pallete.length; index++)
stream.write24BitInt(pallete[index]);
//extra inform
if(biggestWidth == 0 && biggestHeight == 0) {
for(BufferedImage image : images) {
if(image.getWidth() > biggestWidth)
biggestWidth = image.getWidth();
if(image.getHeight() > biggestHeight)
biggestHeight = image.getHeight();
}
}
stream.writeShort(biggestWidth); //probably used for textures
stream.writeShort(biggestHeight);//probably used for textures
stream.writeByte(pallete.length-1); //sets pallete size, -1 cuz of black index
for(int imageId = 0; imageId < images.length; imageId++)
stream.writeShort(minX[imageId]);
for(int imageId = 0; imageId < images.length; imageId++)
stream.writeShort(minY[imageId]);
for(int imageId = 0; imageId < images.length; imageId++)
stream.writeShort(images[imageId].getWidth());
for(int imageId = 0; imageId < images.length; imageId++)
stream.writeShort(images[imageId].getHeight());
stream.writeShort(images.length); //amt of images
//generates fixed byte data array
byte[] container = new byte[stream.getOffset()];
stream.setOffset(0);
stream.getBytes(container, 0, container.length);
return container;
}
public int getPalleteIndex(int rgb) {
if(pallete == null) {
pallete = new int[] {0};
}
for(int index = 0; index < pallete.length; index++) {
if(pallete[index] == rgb)
return index;
}
if(pallete.length == 256) {
System.out.println("Pallete to big, please reduce images quality.");
return 0;
}
//throw new RuntimeException("Pallete to big, please reduce images quality.");
int[] newpallete = new int[pallete.length+1];
System.arraycopy(pallete, 0, newpallete, 0, pallete.length);
newpallete[pallete.length] = rgb;
pallete = newpallete;
return pallete.length-1;
}
public void delete(int index) {
System.out.println(images.length);
BufferedImage[] newImages = Arrays.copyOf(images, images.length-1);
images = newImages;
int[] offsetX = Arrays.copyOf(this.minX, this.minX.length - 1);
offsetX[this.minX.length-2] = 0;
this.minX = offsetX;
int[] offsetY = Arrays.copyOf(this.minY, this.minY.length - 1);
offsetY[this.minY.length-2] = 0;
this.minY = offsetY;
pallete = null;
pixelsIndexes = null;
alpha = null;
usesAlpha = null;
}
public int addImage(BufferedImage image) {
return addImage(image, 0, 0);
}
public int addImage(BufferedImage image, int minX, int minY) {
BufferedImage[] newImages = Arrays.copyOf(images, images.length+1);
newImages[images.length] = image;
images = newImages;
int[] offsetX = Arrays.copyOf(this.minX, this.minX.length + 1);
offsetX[this.minX.length] = minX;
this.minX = offsetX;
int[] offsetY = Arrays.copyOf(this.minY, this.minY.length + 1);
offsetY[this.minY.length] = minY;
this.minY = offsetY;
pallete = null;
pixelsIndexes = null;
alpha = null;
usesAlpha = null;
return images.length - 1;
}
public void replaceImage(BufferedImage image, int index) {
images[index] = image;
pallete = null;
pixelsIndexes = null;
alpha = null;
usesAlpha = null;
}
public void generatePallete() {
pixelsIndexes = new int[images.length][];
alpha = new byte[images.length][];
usesAlpha = new boolean[images.length];
for(int index = 0; index < images.length; index++) {
BufferedImage image = images[index];
int[] rgbArray = new int[image.getWidth()*image.getHeight()];
image.getRGB(0, 0, image.getWidth(), image.getHeight(), rgbArray, 0, image.getWidth());
pixelsIndexes[index] = new int[image.getWidth()*image.getHeight()];
alpha[index] = new byte[image.getWidth()*image.getHeight()];
for(int pixel = 0; pixel < pixelsIndexes[index].length; pixel++) {
int rgb = rgbArray[pixel];
int medintrgb = convertToMediumInt(rgb);
int i = getPalleteIndex(medintrgb);
pixelsIndexes[index][pixel] = i;
if(rgb >> 24 != 0) {
alpha[index][pixel] = (byte) (rgb >> 24);
usesAlpha[index] = !oldRevision;
}
}
}
}
public int convertToMediumInt(int rgb) {
OutputStream out = new OutputStream(4);
out.writeInt(rgb);
InputStream stream = new InputStream(out.getBuffer());
stream.setOffset(1);
rgb = stream.read24BitInt();
return rgb;
}
public BufferedImage[] getImages() {
return images;
}
public int getBiggestWidth() {
return biggestWidth;
}
public void setBiggestWidth(int biggestWidth) {
this.biggestWidth = biggestWidth;
}
public int getBiggestHeight() {
return biggestHeight;
}
public void setBiggestHeight(int biggestHeight) {
this.biggestHeight = biggestHeight;
}
}

View file

@ -0,0 +1,40 @@
package com.alex.loaders.images;
import java.awt.Image;
import java.awt.Toolkit;
import com.alex.store.Store;
import com.alex.utils.Constants;
public class LoaderImageArchive {
private byte[] data;
public LoaderImageArchive(byte[] data) {
this.data = data;
}
public LoaderImageArchive(Store cache, int archiveId) {
this(cache, Constants.LOADER_IMAGES_INDEX, archiveId, 0);
}
private LoaderImageArchive(Store cache, int idx, int archiveId, int fileId) {
decodeArchive(cache, idx, archiveId, fileId);
}
private void decodeArchive(Store cache, int idx, int archiveId, int fileId) {
byte[] data = cache.getIndexes()[idx].getFile(archiveId, fileId);
if(data == null)
return;
this.data = data;
}
public Image getImage() {
return Toolkit.getDefaultToolkit().createImage(data);
}
public byte[] getImageData() {
return data;
}
}

View file

@ -0,0 +1,801 @@
package com.alex.loaders.interfaces;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;
import alex.cache.loaders.ConfigFileDefinition;
import com.alex.io.InputStream;
import com.alex.store.Store;
public class IComponent {
public Object[] anObjectArray2296;
public int anInt2297;
public int otherAnimationId;
public int[] anIntArray2299;
public int anInt2300;
public int anInt2301;
public Object[] anObjectArray2302;
public int anInt2303;
public int anInt2305;
public boolean aBoolean2306;
public int anInt2308 = 0;
public int[] anIntArray2310;
public byte aByte2311;
public int anInt2312;
public Object[] anObjectArray2313;
public int anInt2314;
public int[] anIntArray2315;
public Object[] anObjectArray2316;
public byte[] aByteArray2317;
public Object[] anObjectArray2318;
public int anInt2319;
public int anInt2321;
public int height;
public int[] anIntArray2323;
public int anInt2324;
public int anInt2325;
public IComponent[] aClass173Array2326;
public int[][] childDataBuffers;
public Object[] anObjectArray2328;
public String optionName;
public String aString2330;
public Object[] anObjectArray2331;
public int anInt2332;
public int anInt2333;
public String aString2334;
public int anInt2335;
public Object[] anObjectArray2336;
public int[] anIntArray2337;
public int anInt2338;
public int anInt2340;
public byte aByte2341;
public boolean aBoolean2342;
public int anInt2343;
public Object[] anObjectArray2344;
public IComponent aClass173_2345;
public static int anInt2346;
public int anInt2347;
public Object[] anObjectArray2348;
public int anInt2349;
public int anInt2350;
public Object[] anObjectArray2351;
public Object[] anObjectArray2352;
public boolean aBoolean2353;
public boolean useScripts;
public byte aByte2356;
public String aString2357;
public int modelId;
public int[] anIntArray2360;
public int anInt2361;
public Object[] anObjectArray2362;
public String[] aStringArray2363;
public int anInt2364;
public int anInt2365;
public boolean aBoolean2366;
public boolean aBoolean2367;
public boolean aBoolean2368;
public int anInt2369;
public Object[] anObjectArray2371;
public String aString2373;
public int anInt2374;
public int anInt2375;
public int imageId;
public int[] anIntArray2379;
public boolean aBoolean2380;
public int anInt2381;
public int anInt2382;
public short aShort2383;
public int[] anIntArray2384;
public String[] aStringArray2385;
public int anInt2386;
public int[] anIntArray2388;
public int anInt2389;
public int anInt2390;
public String textToolTip;
public boolean aBoolean2393;
public int anInt2394;
public Object[] anObjectArray2395;
public int anInt2396;
public int anInt2397;
public IComponentSettings settings;
public Object[] anObjectArray2399;
public int[] itemIds;
public boolean aBoolean2401;
public Object[] anObjectArray2402;
public int anInt2403;
public boolean hidden;
public Object[] anObjectArray2405;
public int[] anIntArray2407;
public Object[] anObjectArray2408;
public int anInt2409;
public Object[] anObjectArray2410;
public int anInt2411;
public int anInt2412;
public boolean aBoolean2413;
public int anInt2414;
public int anInt2415;
public int modelType;
public byte[] aByteArray2417;
public int[] anIntArray2418;
public boolean aBoolean2419;
public short aShort2420;
public int anInt2421;
public boolean aBoolean2422;
public int anInt2423;
public int anInt2424;
public Object[] defaultScript;
public int anInt2427;
public boolean aBoolean2429;
public int[] anIntArray2431;
public int y;
public int borderThickness;
public boolean aBoolean2434;
public int anInt2435;
public boolean aBoolean2436;
public int anInt2437;
public int anInt2438;
public Object[] anObjectArray2439;
public int width;
public int anInt2441;
public int anInt2442;
public int animationId;
public int anInt2444;
public int x;
public Object[] anObjectArray2446;
public Object[] anObjectArray2447;
public int anInt2448;
public int[] anIntArray2449;
public int anInt2450;
public int anInt2451;
public int[] anIntArray2452;
public int anInt2453;
public Object[] anObjectArray2454;
public int hash;
public int parentId;
public int anInt2457;
public int anInt2458;
public int anInt2459;
public int anInt2461;
public Object[] anObjectArray2462;
public String aString2463;
public Object[] anObjectArray2464;
public Object[] anObjectArray2465;
public int anInt2467;
public byte aByte2469;
public int type;
public int anInt2471;
public int[] anIntArray2472;
public String aString2473;
public int anInt2474;
public Object[] anObjectArray2475;
public boolean aBoolean2476;
public int anInt2477;
public int[] anIntArray2478;
public int anInt2479;
public int anInt2480;
public int anInt2481;
public int anInt2482;
public Object[] anObjectArray2483;
public int anInt2484;
@SuppressWarnings("unused")
private boolean aBoolean4782;
int[] configs;
int[] configShifts;
public void debug() throws IllegalArgumentException, IllegalAccessException {
for (Field f : getClass().getDeclaredFields()) {
if (!Modifier.isStatic(f.getModifiers())) {
if (f.getType().isArray()) {
Object object = f.get(this);
if (object != null) {
int length = Array.getLength(object);
System.out.print(f.getName() + ", [");
for (int i = 0; i < length; i++) {
System.out.print(Array.get(object, i) + (i < (length - 1) ? ", " : ""));
}
System.out.println("]");
continue;
}
}
System.out.println(f.getName() + ", " + f.get(this));
}
}
}
public void decodeScriptsFormat(InputStream stream) {
useScripts = true;
int newInt = stream.readUnsignedByte();
if (newInt == 255) {
newInt = -1;
}
type = stream.readUnsignedByte();
if ((type & 0x80 ^ 0xffffffff) != -1) {
type &= 0x7f;
aString2473 = stream.readString();
}
anInt2441 = stream.readUnsignedShort();
x = stream.readShort();
y = stream.readShort();
width = stream.readUnsignedShort();
height = stream.readUnsignedShort();
aByte2356 = (byte) stream.readByte();
aByte2341 = (byte) stream.readByte();
aByte2469 = (byte) stream.readByte();
aByte2311 = (byte) stream.readByte();
parentId = stream.readUnsignedShort();
if ((parentId ^ 0xffffffff) != -65536)
parentId = (hash & ~0xffff) + parentId;
else
parentId = -1;
int i_17_ = stream.readUnsignedByte();
hidden = (0x1 & i_17_ ^ 0xffffffff) != -1;
if (newInt >= 0) {
aBoolean2429 = (i_17_ & 0x2 ^ 0xffffffff) != -1;
}
if ((type ^ 0xffffffff) == -1) {
anInt2444 = stream.readUnsignedShort();
anInt2479 = stream.readUnsignedShort();
if ((newInt ^ 0xffffffff) > -1)
aBoolean2429 = stream.readUnsignedByte() == 1;
}
if ((type ^ 0xffffffff) == -6) {
imageId = stream.readInt();
anInt2381 = stream.readUnsignedShort();
int i = stream.readUnsignedByte();
aBoolean2422 = (0x2 & i ^ 0xffffffff) != -1;
aBoolean2434 = (i & 0x1 ^ 0xffffffff) != -1;
anInt2369 = stream.readUnsignedByte();
borderThickness = stream.readUnsignedByte();
anInt2325 = stream.readInt();
aBoolean2419 = (stream.readUnsignedByte() ^ 0xffffffff) == -2;
aBoolean2342 = (stream.readUnsignedByte() ^ 0xffffffff) == -2;
anInt2467 = stream.readInt();
if ((newInt ^ 0xffffffff) <= -4)
aBoolean4782 = (stream.readUnsignedByte() ^ 0xffffffff) == -2;
}
if ((type ^ 0xffffffff) == -7) {
modelType = 1;
modelId = stream.readBigSmart();
anInt2480 = stream.readShort();
anInt2459 = stream.readShort();
anInt2461 = stream.readUnsignedShort();
anInt2482 = stream.readUnsignedShort();
anInt2308 = stream.readUnsignedShort();
anInt2403 = stream.readUnsignedShort();
animationId = stream.readUnsignedShort();
if (animationId == 65535)
animationId = -1;
aBoolean2476 = stream.readUnsignedByte() == 1;
aShort2383 = (short) stream.readUnsignedShort();
aShort2420 = (short) stream.readUnsignedShort();
aBoolean2368 = stream.readUnsignedByte() == 1;
if ((aByte2356 ^ 0xffffffff) != -1)
anInt2423 = stream.readUnsignedShort();
if (aByte2341 != 0)
anInt2397 = stream.readUnsignedShort();
}
if (type == 4) {
anInt2375 = stream.readBigSmart();
if ((anInt2375 ^ 0xffffffff) == -65536)
anInt2375 = -1;
aString2357 = stream.readString();
if(aString2357.toLowerCase().contains("ship"))
System.out.println(this.hash >> 16);
anInt2364 = stream.readUnsignedByte();
anInt2312 = stream.readUnsignedByte();
anInt2297 = stream.readUnsignedByte();
aBoolean2366 = (stream.readUnsignedByte() ^ 0xffffffff) == -2;
anInt2467 = stream.readInt();
}
if (type == 3) {
anInt2467 = stream.readInt();
aBoolean2367 = (stream.readUnsignedByte() ^ 0xffffffff) == -2;
anInt2369 = stream.readUnsignedByte();
}
if ((type ^ 0xffffffff) == -10) {
anInt2471 = stream.readUnsignedByte();
anInt2467 = stream.readInt();
aBoolean2306 = (stream.readUnsignedByte() ^ 0xffffffff) == -2;
}
int settingsHash = stream.read24BitInt();
// int i_28_ = stream.readUnsignedByte();
// if (i_28_ != 0) {
// anIntArray2449 = new int[11];
// aByteArray2417 = new byte[11];
// aByteArray2317 = new byte[11];
// for (/**/; (i_28_ ^ 0xffffffff) != -1;
// i_28_ = stream.readUnsignedByte()) {
// int i_29_ = -1 + (i_28_ >> 360744868);
// i_28_ = i_28_ << -456693784 | stream.readUnsignedByte();
// i_28_ &= 0xfff;
// if ((i_28_ ^ 0xffffffff) != -4096)
// anIntArray2449[i_29_] = i_28_;
// else
// anIntArray2449[i_29_] = -1;
// aByteArray2317[i_29_] = (byte) stream.readByte();
// if ((aByteArray2317[i_29_] ^ 0xffffffff) != -1)
// aBoolean2401 = true;
// aByteArray2417[i_29_] = (byte) stream.readByte();
// }
// }
textToolTip = stream.readString();
int i_30_ = stream.readUnsignedByte();
int i_31_ = i_30_ & 0xf;
if ((i_31_ ^ 0xffffffff) < -1) {
aStringArray2385 = new String[i_31_];
for (int i_32_ = 0; i_31_ > i_32_; i_32_++)
aStringArray2385[i_32_] = stream.readString();
}
int i_33_ = i_30_ >> -686838332;
if ((i_33_ ^ 0xffffffff) < -1) {
int i_34_ = stream.readUnsignedByte();
anIntArray2315 = new int[1 + i_34_];
for (int i_35_ = 0; i_35_ < anIntArray2315.length; i_35_++)
anIntArray2315[i_35_] = -1;
anIntArray2315[i_34_] = stream.readUnsignedShort();
}
if ((i_33_ ^ 0xffffffff) < -2) {
int i_36_ = stream.readUnsignedByte();
anIntArray2315[i_36_] = stream.readUnsignedShort();
}
aString2330 = stream.readString();
if (aString2330.equals(""))
aString2330 = null;
anInt2335 = stream.readUnsignedByte();
anInt2319 = stream.readUnsignedByte();
aBoolean2436 = (stream.readUnsignedByte() ^ 0xffffffff) == -2;
aString2463 = stream.readString();
int defaultHash = -1;
if ((method2412(settingsHash) ^ 0xffffffff) != -1) {
defaultHash = stream.readUnsignedShort();
if ((defaultHash ^ 0xffffffff) == -65536)
defaultHash = -1;
anInt2303 = stream.readUnsignedShort();
if (anInt2303 == 65535)
anInt2303 = -1;
anInt2374 = stream.readUnsignedShort();
if (anInt2374 == 65535)
anInt2374 = -1;
}
settings = new IComponentSettings(settingsHash, defaultHash);
defaultScript = decodeScript(stream);
anObjectArray2462 = decodeScript(stream);
anObjectArray2402 = decodeScript(stream);
anObjectArray2371 = decodeScript(stream);
anObjectArray2408 = decodeScript(stream);
anObjectArray2439 = decodeScript(stream);
anObjectArray2454 = decodeScript(stream);
anObjectArray2410 = decodeScript(stream);
anObjectArray2316 = decodeScript(stream);
anObjectArray2465 = decodeScript(stream);
anObjectArray2446 = decodeScript(stream);
anObjectArray2313 = decodeScript(stream);
anObjectArray2318 = decodeScript(stream);
anObjectArray2328 = decodeScript(stream);
anObjectArray2395 = decodeScript(stream);
anObjectArray2331 = decodeScript(stream);
anObjectArray2405 = decodeScript(stream);
anObjectArray2351 = decodeScript(stream);
anObjectArray2302 = decodeScript(stream);
anObjectArray2296 = decodeScript(stream);
anIntArray2452 = method2465(stream);
anIntArray2472 = method2465(stream);
anIntArray2360 = method2465(stream);
anIntArray2388 = method2465(stream);
anIntArray2299 = method2465(stream);
}
public Object[] decodeScript(InputStream stream) {
int size = stream.readUnsignedByte();
Object[] objects = new Object[size];
for (int index = 0; index < size; index++) {
int type = stream.readUnsignedByte();
if (type == 0) {
objects[index] = new Integer(stream.readInt());
}
else if (type == 1) {
objects[index] = stream.readString();
}
}
aBoolean2353 = true;
return objects;
}
public int[] method2465(InputStream stream) {
int size = stream.readUnsignedByte();
if (size == 0)
return null;
int[] array = new int[size];
for (int index = 0; size > index; index++)
array[index] = stream.readInt();
return array;
}
public int setConfigs(List<Integer> configs, int childIndex, Store store) {
if (childDataBuffers == null || childIndex >= childDataBuffers.length) {
return -2;
}
try {
int[] buffer = childDataBuffers[childIndex];
int index = 0;
for (;;) {
int opcode = buffer[index++];
if (opcode == 0) {
this.configs = new int[configs.size()];
this.configShifts = new int[configs.size()];
for (int i = 0; i < configs.size(); i++) {
int configId = configs.get(i);
int id = configId & 0xFFFF;
int shift = configId >> 16 & 0xFF;
this.configs[i] = id;
this.configShifts[i] = shift;
}
return 0;
}
if (opcode == 1) {
index++;
}
if (opcode == 2) {
index++;
}
if (opcode == 3) {
index++;
}
if (opcode == 4) {
index += 3;
}
if (opcode == 5) {
int configId = buffer[index++];
if (!configs.contains(configId)) {
configs.add(configId);
}
}
if (opcode == 6) {
index++;
}
if (opcode == 7) {
int configId = buffer[index++];
if (!configs.contains(configId)) {
configs.add(configId);
}
}
if (opcode == 10) {
index += 3;
}
if (opcode == 13) {
int configId = buffer[index++];
int shift = buffer[index++];
int id = configId | shift << 16;
if (!configs.contains(id)) {
configs.add(id);
}
}
if (opcode == 14) {
int configFileId = buffer[index++];
ConfigFileDefinition def = ConfigFileDefinition.forId(configFileId, store);
int id = def.getConfigId() | (def.getBitShift() << 16);
if (!configs.contains(id)) {
configs.add(id);
}
}
if (opcode == 20) {
index++;
}
}
} catch (Exception exception) {
return -1;
}
}
public void decodeNoscriptsFormat(InputStream stream) {
useScripts = false;
type = stream.readUnsignedByte();
anInt2324 = stream.readUnsignedByte();
anInt2441 = stream.readUnsignedShort();
x = stream.readShort();
y = stream.readShort();
width = stream.readUnsignedShort();
height = stream.readUnsignedShort();
aByte2341 = (byte) 0;
aByte2356 = (byte) 0;
aByte2311 = (byte) 0;
aByte2469 = (byte) 0;
anInt2369 = stream.readUnsignedByte();
parentId = stream.readUnsignedShort();
if ((parentId ^ 0xffffffff) == -65536)
parentId = -1;
else
parentId = parentId + (hash & ~0xffff);
anInt2448 = stream.readUnsignedShort();
if ((anInt2448 ^ 0xffffffff) == -65536)
anInt2448 = -1;
int i = stream.readUnsignedByte();
if ((i ^ 0xffffffff) < -1) {
anIntArray2407 = new int[i];
anIntArray2384 = new int[i];
for (int i_0_ = 0; i > i_0_; i_0_++) {
anIntArray2384[i_0_] = stream.readUnsignedByte();
anIntArray2407[i_0_] = stream.readUnsignedShort();
}
}
int i_1_ = stream.readUnsignedByte();
if ((i_1_ ^ 0xffffffff) < -1) {
childDataBuffers = new int[i_1_][];
for (int i_2_ = 0;
(i_1_ ^ 0xffffffff) < (i_2_ ^ 0xffffffff); i_2_++) {
int i_3_ = stream.readUnsignedShort();
childDataBuffers[i_2_] = new int[i_3_];
for (int i_4_ = 0; (i_3_ ^ 0xffffffff) < (i_4_ ^ 0xffffffff); i_4_++) {
childDataBuffers[i_2_][i_4_] = stream.readUnsignedShort();
if ((childDataBuffers[i_2_][i_4_] ^ 0xffffffff) == -65536)
childDataBuffers[i_2_][i_4_] = -1;
}
}
}
if ((type ^ 0xffffffff) == -1) {
anInt2479 = stream.readUnsignedShort();
hidden = stream.readUnsignedByte() == 1;
}
if (type == 1) {
stream.readUnsignedShort();
stream.readUnsignedByte();
}
int i_5_ = 0;
if ((type ^ 0xffffffff) == -3) {
itemIds = new int[height * width];
aByte2341 = (byte) 3;
anIntArray2418 = new int[height * width];
aByte2356 = (byte) 3;
int i_6_ = stream.readUnsignedByte();
if (i_6_ == 1)
i_5_ |= 0x10000000;
int i_7_ = stream.readUnsignedByte();
if (i_7_ == 1)
i_5_ |= 0x40000000;
int i_8_ = stream.readUnsignedByte();
stream.readUnsignedByte();
if ((i_8_ ^ 0xffffffff) == -2)
i_5_ |= ~0x7fffffff;
anInt2332 = stream.readUnsignedByte();
anInt2414 = stream.readUnsignedByte();
anIntArray2337 = new int[20];
anIntArray2323 = new int[20];
anIntArray2431 = new int[20];
for (int i_9_ = 0; i_9_ < 20; i_9_++) {
int i_10_ = stream.readUnsignedByte();
if ((i_10_ ^ 0xffffffff) != -2)
anIntArray2431[i_9_] = -1;
else {
anIntArray2323[i_9_] = stream.readShort();
anIntArray2337[i_9_] = stream.readShort();
anIntArray2431[i_9_] = stream.readInt();
}
}
aStringArray2363 = new String[5];
for (int i_11_ = 0; i_11_ < 5; i_11_++) {
String string = stream.readString();
if ((string.length() ^ 0xffffffff) < -1) {
aStringArray2363[i_11_] = string;
i_5_ |= 1 << 23 + i_11_;
}
}
}
if ((type ^ 0xffffffff) == -4)
aBoolean2367 = (stream.readUnsignedByte() ^ 0xffffffff) == -2;
if ((type ^ 0xffffffff) == -5 || type == 1) {
anInt2312 = stream.readUnsignedByte();
anInt2297 = stream.readUnsignedByte();
anInt2364 = stream.readUnsignedByte();
anInt2375 = stream.readUnsignedShort();
if ((anInt2375 ^ 0xffffffff) == -65536)
anInt2375 = -1;
aBoolean2366 = stream.readUnsignedByte() == 1;
}
if ((type ^ 0xffffffff) == -5) {
aString2357 = stream.readString();
aString2334 = stream.readString();
}
if (type == 1 || (type ^ 0xffffffff) == -4
|| type == 4)
anInt2467 = stream.readInt();
if (type == 3 || type == 4) {
anInt2424 = stream.readInt();
anInt2451 = stream.readInt();
anInt2477 = stream.readInt();
}
if ((type ^ 0xffffffff) == -6) {
imageId = stream.readInt();
anInt2349 = stream.readInt();
}
if ((type ^ 0xffffffff) == -7) {
modelType = 1;
modelId = stream.readUnsignedShort();
anInt2301 = 1;
if (modelId == 65535)
modelId = -1;
anInt2386 = stream.readUnsignedShort(); //Model id
if ((anInt2386 ^ 0xffffffff) == -65536)
anInt2386 = -1;
animationId = stream.readUnsignedShort();
if (animationId == 65535)
animationId = -1;
otherAnimationId = stream.readUnsignedShort();
if (otherAnimationId == 65535)
otherAnimationId = -1;
anInt2403 = stream.readUnsignedShort();
anInt2461 = stream.readUnsignedShort();
anInt2482 = stream.readUnsignedShort();
}
if ((type ^ 0xffffffff) == -8) {
aByte2341 = (byte) 3;
anIntArray2418 = new int[width * height];
aByte2356 = (byte) 3;
itemIds = new int[width * height];
anInt2312 = stream.readUnsignedByte();
anInt2375 = stream.readUnsignedShort();
if (anInt2375 == 65535)
anInt2375 = -1;
aBoolean2366 = stream.readUnsignedByte() == 1;
anInt2467 = stream.readInt();
anInt2332 = stream.readShort();
anInt2414 = stream.readShort();
int i_12_ = stream.readUnsignedByte();
if ((i_12_ ^ 0xffffffff) == -2)
i_5_ |= 0x40000000;
aStringArray2363 = new String[5];
for (int i_13_ = 0; i_13_ < 5; i_13_++) {
String string = stream.readString();
if (string.length() > 0) {
aStringArray2363[i_13_] = string;
i_5_ |= 1 << i_13_ + 23;
}
}
}
if ((type ^ 0xffffffff) == -9)
aString2357 = stream.readString();
if (anInt2324 == 2 || (type ^ 0xffffffff) == -3) {
aString2463 = stream.readString();
aString2373 = stream.readString();
int i_14_ = 0x3f & stream.readUnsignedShort();
i_5_ |= i_14_ << -116905845;
}
if ((anInt2324 ^ 0xffffffff) == -2
|| (anInt2324 ^ 0xffffffff) == -5 || anInt2324 == 5
|| anInt2324 == 6) {
optionName = stream.readString();
if ((optionName.length() ^ 0xffffffff) == -1) {
if ((anInt2324 ^ 0xffffffff) == -2)
optionName = "Ok";
if ((anInt2324 ^ 0xffffffff) == -5)
optionName = "Select";
if ((anInt2324 ^ 0xffffffff) == -6)
optionName = "Select";
if ((anInt2324 ^ 0xffffffff) == -7)
optionName = "Continue";
}
}
if (anInt2324 == 1 || anInt2324 == 4
|| (anInt2324 ^ 0xffffffff) == -6)
i_5_ |= 0x400000;
if ((anInt2324 ^ 0xffffffff) == -7)
i_5_ |= 0x1;
settings = new IComponentSettings(i_5_, -1);
}
public static int method2412(int arg0) {
return 0x7f & arg0 >> -809958741;
}
public IComponent() {
anInt2301 = 1;
otherAnimationId = -1;
aByte2311 = (byte) 0;
optionName = "Ok";
anInt2347 = 0;
anInt2319 = 0;
anInt2349 = -1;
aBoolean2366 = false;
aString2357 = "";
anInt2321 = -1;
imageId = -1;
aBoolean2380 = false;
anInt2350 = -1;
aBoolean2306 = false;
anInt2364 = 0;
anInt2374 = -1;
anInt2324 = 0;
anInt2375 = -1;
anInt2343 = 0;
anInt2396 = 0;
anInt2369 = 0;
anInt2394 = 1;
aBoolean2401 = false;
height = 0;
anInt2303 = -1;
anInt2390 = 0;
aBoolean2393 = false;
anInt2333 = 0;
textToolTip = "";
aBoolean2367 = false;
anInt2415 = 0;
anInt2332 = 0;
anInt2312 = 0;
anInt2386 = -1;
anInt2381 = 0;
anInt2423 = 0;
anInt2305 = 0;
aBoolean2436 = false;
aShort2383 = (short) 0;
anInt2389 = 0;
anInt2335 = 0;
aClass173_2345 = null;
aString2334 = "";
aBoolean2422 = false;
hidden = false;
anInt2448 = -1;
aByte2356 = (byte) 0;
anInt2325 = 0;
anInt2442 = 0;
modelType = 1;
anInt2438 = 1;
anInt2441 = 0;
width = 0;
anInt2437 = 0;
anInt2414 = 0;
hash = -1;
aString2373 = "";
aBoolean2368 = false;
anInt2457 = -1;
anInt2365 = -1;
anInt2435 = 0;
anInt2467 = 0;
anInt2397 = 0;
aBoolean2434 = false;
anInt2361 = -1;
anInt2424 = 0;
useScripts = false;
x = 0;
anInt2427 = 0;
anInt2412 = 0;
y = 0;
aBoolean2413 = false;
animationId = -1;
anInt2444 = 0;
borderThickness = 0;
aBoolean2476 = false;
anInt2471 = 1;
anInt2459 = 0;
anInt2403 = 100;
aByte2469 = (byte) 0;
anInt2477 = 0;
aBoolean2353 = false;
anInt2461 = 0;
aByte2341 = (byte) 0;
anInt2479 = 0;
anInt2297 = 0;
anInt2411 = 0;
aBoolean2429 = false;
anInt2481 = 1;
aShort2420 = (short) 3000;
anInt2338 = 0;
anInt2451 = 0;
anInt2450 = 0;
aString2463 = "";
anInt2480 = 0;
anInt2453 = -1;
anInt2484 = 0;
anInt2474 = 2;
parentId = -1;
anInt2482 = 0;
anInt2421 = -1;
}
}

View file

@ -0,0 +1,14 @@
package com.alex.loaders.interfaces;
public final class IComponentSettings {
@SuppressWarnings("unused")
private int settingsHash;
@SuppressWarnings("unused")
private int defaultHash;
public IComponentSettings(int settingsHash, int defaultHash) { //not using atm but can be used for easy find which options unlock, easy as fk
this.settingsHash = settingsHash;
this.defaultHash = defaultHash;
}
}

View file

@ -0,0 +1,135 @@
package com.alex.loaders.interfaces;
import java.awt.Component;
import java.awt.Image;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.awt.image.ImageProducer;
import java.awt.image.ReplicateScaleFilter;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JComponent;
import com.alex.io.InputStream;
import com.alex.store.Store;
import com.alex.utils.Utils;
public class Interface {
public int id;
public Store cache;
public IComponent[] components;
public JComponent[] jcomponents;
public static void main(String[] args) throws IOException, Throwable {
Store rscache = new Store("./498/");
if (true) {
Interface inter = new Interface(25, rscache);
for (int i = 0; i < inter.components.length; i++) {
if (inter.components[i] != null) {
inter.components[i].debug();
System.out.println("----------------------------------------");
}
}
return;
}
@SuppressWarnings("unused")
BufferedWriter bw = new BufferedWriter(new FileWriter("498_interface_configs.txt"));
for (int i = 0; i < 750; i++) {
try {
Interface inter = new Interface(i, rscache);
if (inter.components == null) {
continue;
}
int child = 0;
Map<Integer, List<Integer>> childConfigs = new HashMap<>();
for (IComponent c : inter.components) {
if (c == null) {
continue;
}
List<Integer> configs = new ArrayList<>();
childConfigs.put(child, configs);
if (c.childDataBuffers != null) {
if (c.childDataBuffers[0][0] == 5) {
int id = c.childDataBuffers[0][1];
if (!configs.contains(id)) {
configs.add(id);
}
}
for (int j = 0; j < c.childDataBuffers.length; j++) {
c.setConfigs(configs, j, rscache);
}
}
child++;
}
for (int c : childConfigs.keySet()) {
List<Integer> configs = childConfigs.get(c);
if (configs.isEmpty()) {
continue;
}
String data = "Interface " + i + " child " + c + " config: ";
for (int j = 0; j < configs.size(); j++) {
if (j != 0) {
data += ", ";
}
int id = configs.get(j);
data += "[" + (id & 0xFFFF) + ", " + (id >> 16) + "]";
}
bw.append(data);
bw.newLine();
}
} catch(Throwable e) {
e.printStackTrace();
}
}
bw.flush();
bw.close();
}
public Interface(int id, Store cache) {
this(id,cache,true);
}
public Interface(int id, Store cache, boolean load) {
this.id = id;
this.cache = cache;
if(load)
getComponents();
}
public void draw(JComponent parent) {
}
public Image resizeImage(Image image, int width, int height, Component c) {
ImageFilter replicate = new ReplicateScaleFilter(width, height);
ImageProducer prod = new FilteredImageSource(image.getSource(),replicate);
return c.createImage(prod);
}
public void getComponents() {
if (Utils.getInterfaceDefinitionsSize(cache) <= id) {
// throw new RuntimeException("Invalid interface id.");
return;
}
components = new IComponent[Utils.getInterfaceDefinitionsComponentsSize(cache, id)];
for(int componentId = 0; componentId < components.length; componentId++) {
components[componentId] = new IComponent();
components[componentId].hash = id << 16 | componentId;
byte[] data = cache.getIndexes()[3].getFile(id, componentId);
if (data == null)
throw new RuntimeException("Interface "+id+", component "+componentId+" data is null.");
if (data[0] != -1)
components[componentId].decodeNoscriptsFormat(new InputStream(data));
else
components[componentId].decodeScriptsFormat(new InputStream(data));
}
}
}

View file

@ -0,0 +1,58 @@
package com.alex.loaders.interfaces;
import java.io.IOException;
import com.alex.store.Store;
import com.alex.utils.Constants;
import com.alex.utils.Utils;
public class InterfaceName {
public static final char[] VALID_CHARS = { 'a', 'b', 'c', 'd', 'e',
'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
public static void printAllCombinations4Letters(){
}
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
Store rscache = new Store("cache697/", false);
System.out.println( rscache.getIndexes()[Constants.INTERFACE_DEFINITIONS_INDEX].getTable().isNamed());
System.out.println(rscache.getIndexes()[Constants.INTERFACE_DEFINITIONS_INDEX].getArchiveId("chat"));
System.out.println(Utils.getNameHash("price checker"));
/* System.out.println(Utils.getNameHash("prayer"));
System.out.println(Utils.unhash(Utils.getNameHash("t")));*/
//System.out.println(Utils.getNameHash("prayer"));
/* int hash = rscache.getIndexes()[Constants.INTERFACE_DEFINITIONS_INDEX].getTable().getArchives()[884].getNameHash();
for(char l1 : VALID_CHARS) {
System.out.println(l1);
for(char l2 : VALID_CHARS) {
for(char l3 : VALID_CHARS) {
for(char l4 : VALID_CHARS) {
for(char l5 : VALID_CHARS) {
for(char l6 : VALID_CHARS) {
String name = new String(new char[] {l1, l2, l3, l4,l5, l6});
if(Utils.getNameHash(name) == hash)
System.out.println(name);
}
}
}
}
}
}*/
}
}

View file

@ -0,0 +1,738 @@
package com.alex.loaders.items;
import java.util.Arrays;
import java.util.HashMap;
import com.alex.io.InputStream;
import com.alex.io.OutputStream;
import com.alex.store.Store;
import com.alex.utils.Constants;
@SuppressWarnings("unused")
public class ItemDefinitions implements Cloneable {
public int id;
private boolean loaded;
public int invModelId;
private String name;
//model size information
private int invModelZoom;
private int modelRotation1;
private int modelRotation2;
private int modelOffset1;
private int modelOffset2;
//extra information
private int stackable;
private int value;
public boolean membersOnly;
//wearing model information
public int maleEquipModelId1;
public int femaleEquipModelId1;
public int maleEquipModelId2;
public int femaleEquipModelId2;
public int maleEquipModelId3;
public int femaleEquipModelId3;
//options
private String[] groundOptions;
public String[] inventoryOptions;
//model information
public int[] originalModelColors;
public int[] modifiedModelColors;
public int[] originalTextureColors;
public int[] modifiedTextureColors;
private byte[] unknownArray1;
private int[] unknownArray2;
//extra information, not used for newer items
private boolean unnoted;
private int unknownInt1;
private int unknownInt2;
private int unknownInt3;
private int unknownInt4;
private int unknownInt5;
private int unknownInt6;
public int switchNoteItemId;
public int notedItemId;
private int[] stackIds;
private int[] stackAmounts;
private int unknownInt7;
private int unknownInt8;
private int unknownInt9;
private int unknownInt10;
private int unknownInt11;
public int teamId;
public int switchLendItemId;
public int lendedItemId;
private int unknownInt12;
private int unknownInt13;
private int unknownInt14;
private int unknownInt15;
private int unknownInt16;
private int unknownInt17;
private int unknownInt18;
private int unknownInt19;
private int unknownInt20;
private int unknownInt21;
private int unknownInt22;
private int unknownInt23;
private int equipSlot;
private HashMap<Integer, Object> clientScriptData;
public static ItemDefinitions getItemDefinition(Store cache, int itemId) {
return getItemDefinition(cache, itemId, true);
}
public static ItemDefinitions getItemDefinition(Store cache, int itemId, boolean load) {
return new ItemDefinitions(cache, itemId, load);
}
public ItemDefinitions(Store cache, int id) {
this(cache, id, true);
}
public ItemDefinitions(Store cache, int id, boolean load) {
this.id = id;
setDefaultsVariableValules();
setDefaultOptions();
if (load)
loadItemDefinition(cache);
}
public boolean isLoaded() {
return loaded;
}
public void write(Store store) {
store.getIndexes()[Constants.ITEM_DEFINITIONS_INDEX].putFile(getArchiveId(), getFileId(), encode());
}
private void loadItemDefinition(Store cache) {
byte[] data = cache.getIndexes()[Constants.ITEM_DEFINITIONS_INDEX].getFile(getArchiveId(), getFileId());
if (data == null) {
System.out.println("FAILED LOADING ITEM " + id);
return;
}
try {
readOpcodeValues(new InputStream(data));
}catch(RuntimeException e) {
e.printStackTrace();
}
if(notedItemId != -1)
toNote(cache);
if(lendedItemId != -1)
toLend(cache);
loaded = true;
}
private void toNote(Store store) {
//ItemDefinitions noteItem; //certTemplateId
ItemDefinitions realItem = getItemDefinition(store, switchNoteItemId);
membersOnly = realItem.membersOnly;
value = realItem.value;
name = realItem.name;
stackable = 1;
}
private void toLend(Store store) {
//ItemDefinitions lendItem; //lendTemplateId
ItemDefinitions realItem = getItemDefinition(store, switchLendItemId);
originalModelColors = realItem.originalModelColors;
modifiedModelColors = realItem.modifiedModelColors;
teamId = realItem.teamId;
value = 0;
membersOnly = realItem.membersOnly;
name = realItem.name;
inventoryOptions = new String[5];
groundOptions = realItem.groundOptions;
if (realItem.inventoryOptions != null)
for (int optionIndex = 0; optionIndex < 4; optionIndex++)
inventoryOptions[optionIndex] = realItem.inventoryOptions[optionIndex];
inventoryOptions[4] = "Discard";
maleEquipModelId1 = realItem.maleEquipModelId1;
maleEquipModelId2 = realItem.maleEquipModelId2;
femaleEquipModelId1 = realItem.femaleEquipModelId1;
femaleEquipModelId2 = realItem.femaleEquipModelId2;
maleEquipModelId3 = realItem.maleEquipModelId3;
femaleEquipModelId3 = realItem.femaleEquipModelId3;
equipSlot = realItem.equipSlot;
}
public int getArchiveId() {
return id >>> 8;
}
public int getFileId() {
return 0xff & id;
}
public boolean hasSpecialBar() {
if(clientScriptData == null)
return false;
Object specialBar = clientScriptData.get(686);
if(specialBar != null && specialBar instanceof Integer)
return (Integer) specialBar == 1;
return false;
}
public int getRenderAnimId() {
if(clientScriptData == null)
return 1426;
Object animId = clientScriptData.get(644);
if(animId != null && animId instanceof Integer)
return (Integer) animId;
return 1426;
}
public void setRenderAnimId(int animId) {
if(clientScriptData == null)
clientScriptData = new HashMap<Integer, Object>();
clientScriptData.put(644, animId);
}
public int getQuestId() {
if(clientScriptData == null)
return -1;
Object questId = clientScriptData.get(861);
if(questId != null && questId instanceof Integer)
return (Integer) questId;
return -1;
}
public HashMap<Integer, Integer> getWearingSkillRequiriments() {
if(clientScriptData == null)
return null;
HashMap<Integer, Integer> skills = new HashMap<Integer, Integer>();
int nextLevel = -1;
int nextSkill = -1;
for(int key : clientScriptData.keySet()) {
Object value = clientScriptData.get(key);
if(value instanceof String)
continue;
if(key == 23) {
skills.put(4, (Integer) value);
skills.put(11, 61);
}else if (key >= 749 && key < 797) {
if(key % 2 == 0)
nextLevel = (Integer) value;
else
nextSkill = (Integer) value;
if(nextLevel != -1 && nextSkill != -1) {
skills.put(nextSkill, nextLevel);
nextLevel = -1;
nextSkill = -1;
}
}
}
return skills;
}
//test :P
public void printClientScriptData() {
for(int key : clientScriptData.keySet()) {
Object value = clientScriptData.get(key);
System.out.println("KEY: "+key+", VALUE: "+value);
}
HashMap<Integer, Integer> requiriments = getWearingSkillRequiriments();
if(requiriments == null) {
System.out.println("null.");
return;
}
System.out.println(requiriments.keySet().size());
for(int key : requiriments.keySet()) {
Object value = requiriments.get(key);
System.out.println("SKILL: "+key+", LEVEL: "+value);
}
}
private void setDefaultOptions() {
groundOptions = new String[] { null, null, "take", null, null };
inventoryOptions = new String[] { null, null, null, null, "drop" };
}
private void setDefaultsVariableValules() {
name = "null";
maleEquipModelId1 = -1;
maleEquipModelId2 = -1;
femaleEquipModelId1 = -1;
femaleEquipModelId2 = -1;
invModelZoom = 2000;
switchLendItemId = -1;
lendedItemId = -1;
switchNoteItemId = -1;
notedItemId = -1;
unknownInt9 = 128;
value = 1;
maleEquipModelId3 = -1;
femaleEquipModelId3 = -1;
equipSlot = -1;
}
public byte[] encode() {
OutputStream stream = new OutputStream();
stream.writeByte(1);
stream.writeBigSmart(invModelId);
if(!name.equals("null") && notedItemId == -1) {
stream.writeByte(2);
stream.writeString(name);
}
if(invModelZoom != 2000) {
stream.writeByte(4);
stream.writeShort(invModelZoom);
}
if(modelRotation1 != 0) {
stream.writeByte(5);
stream.writeShort(modelRotation1);
}
if(modelRotation2 != 0) {
stream.writeByte(6);
stream.writeShort(modelRotation2);
}
if(modelOffset1 != 0) {
stream.writeByte(7);
int value = modelOffset1 >>= 0;
if (value < 0)
value += 65536;
stream.writeShort(value);
}
if(modelOffset2 != 0) {
stream.writeByte(8);
int value = modelOffset2 >>= 0;
if (value < 0)
value += 65536;
stream.writeShort(value);
}
if(stackable >= 1 && notedItemId == -1) {
stream.writeByte(11);
}
if(value != 1 && lendedItemId == -1) {
stream.writeByte(12);
stream.writeInt(value);
}
if(equipSlot != -1) {
stream.writeByte(13);
stream.writeByte(equipSlot);
}
if(membersOnly && notedItemId == -1) {
stream.writeByte(16);
}
if(maleEquipModelId1 != -1) {
stream.writeByte(23);
stream.writeBigSmart(maleEquipModelId1);
}
if(maleEquipModelId2 != -1) {
stream.writeByte(24);
stream.writeBigSmart(maleEquipModelId2);
}
if(femaleEquipModelId1 != -1) {
stream.writeByte(25);
stream.writeBigSmart(femaleEquipModelId1);
}
if(femaleEquipModelId2 != -1) {
stream.writeByte(26);
stream.writeBigSmart(femaleEquipModelId2);
}
for(int index = 0; index < groundOptions.length; index++) {
if(groundOptions[index] == null || (index == 2 && groundOptions[index].equals("take")))
continue;
stream.writeByte(30+index);
stream.writeString(groundOptions[index]);
}
for(int index = 0; index < inventoryOptions.length; index++) {
if(inventoryOptions[index] == null || (index == 4 && inventoryOptions[index].equals("drop")))
continue;
stream.writeByte(35+index);
stream.writeString(inventoryOptions[index]);
}
if(originalModelColors != null && modifiedModelColors != null) {
stream.writeByte(40);
stream.writeByte(originalModelColors.length);
for(int index = 0; index < originalModelColors.length; index++) {
stream.writeShort(originalModelColors[index]);
stream.writeShort(modifiedModelColors[index]);
}
}
if(originalTextureColors != null && modifiedTextureColors != null) {
stream.writeByte(41);
stream.writeByte(originalTextureColors.length);
for(int index = 0; index < originalTextureColors.length; index++) {
stream.writeShort(originalTextureColors[index]);
stream.writeShort(modifiedTextureColors[index]);
}
}
if(unknownArray1 != null) {
stream.writeByte(42);
stream.writeByte(unknownArray1.length);
for(int index = 0; index < unknownArray1.length; index++)
stream.writeByte(unknownArray1[index]);
}
if(unnoted) {
stream.writeByte(65);
}
if(maleEquipModelId3 != -1) {
stream.writeByte(78);
stream.writeBigSmart(maleEquipModelId3);
}
if(femaleEquipModelId3 != -1) {
stream.writeByte(79);
stream.writeBigSmart(femaleEquipModelId3);
}
//TODO FEW OPCODES HERE
if(switchNoteItemId != -1) {
stream.writeByte(97);
stream.writeShort(switchNoteItemId);
}
if(notedItemId != -1) {
stream.writeByte(98);
stream.writeShort(notedItemId);
}
if(stackIds != null && stackAmounts != null) {
for(int index = 0; index < stackIds.length; index++) {
if(stackIds[index] == 0 && stackAmounts[index] == 0)
continue;
stream.writeByte(100+index);
stream.writeShort(stackIds[index]);
stream.writeShort(stackAmounts[index]);
}
}
//TODO FEW OPCODES HERE
if(teamId != 0) {
stream.writeByte(115);
stream.writeByte(teamId);
}
if(switchLendItemId != -1) {
stream.writeByte(121);
stream.writeShort(switchLendItemId);
}
if(lendedItemId != -1) {
stream.writeByte(122);
stream.writeShort(lendedItemId);
}
//TODO FEW OPCODES HERE
if(unknownArray2 != null) {
stream.writeByte(132);
stream.writeByte(unknownArray2.length);
for(int index = 0; index < unknownArray2.length; index++)
stream.writeShort(unknownArray2[index]);
}
if(clientScriptData != null) {
stream.writeByte(249);
stream.writeByte(clientScriptData.size());
for(int key : clientScriptData.keySet()) {
Object value = clientScriptData.get(key);
stream.writeByte(value instanceof String ? 1 : 0);
stream.write24BitInt(key);
if(value instanceof String) {
stream.writeString((String) value);
}else{
stream.writeInt((Integer) value);
}
}
}
//end
stream.writeByte(0);
byte[] data = new byte[stream.getOffset()];
stream.setOffset(0);
stream.getBytes(data, 0, data.length);
return data;
}
public int getInvModelId() {
return invModelId;
}
public void setInvModelId(int modelId) {
this.invModelId = modelId;
}
public int getInvModelZoom() {
return invModelZoom;
}
public void setInvModelZoom(int modelZoom) {
this.invModelZoom = modelZoom;
}
private void readValues(InputStream stream, int opcode) {
if(opcode == 1)
invModelId = stream.readBigSmart();
else if (opcode == 2)
name = stream.readString();
else if (opcode == 4)
invModelZoom = stream.readUnsignedShort();
else if (opcode == 5)
modelRotation1 = stream.readUnsignedShort();
else if (opcode == 6)
modelRotation2 = stream.readUnsignedShort();
else if (opcode == 7) {
modelOffset1 = stream.readUnsignedShort();
if (modelOffset1 > 32767)
modelOffset1 -= 65536;
modelOffset1 <<= 0;
}else if (opcode == 8) {
modelOffset2 = stream.readUnsignedShort();
if (modelOffset2 > 32767)
modelOffset2 -= 65536;
modelOffset2 <<= 0;
}else if (opcode == 11)
stackable = 1;
else if (opcode == 12)
value = stream.readInt();
else if (opcode == 13)
equipSlot = stream.readUnsignedByte();
else if (opcode == 14)
stream.readUnsignedByte();
else if (opcode == 16)
membersOnly = true;
else if (opcode == 23)
maleEquipModelId1 = stream.readBigSmart();
else if (opcode == 24)
maleEquipModelId2 = stream.readBigSmart();
else if (opcode == 25)
femaleEquipModelId1 = stream.readBigSmart();
else if (opcode == 26)
femaleEquipModelId2 = stream.readBigSmart();
else if (opcode >= 30 && opcode < 35)
groundOptions[opcode-30] = stream.readString();
else if (opcode >= 35 && opcode < 40)
inventoryOptions[opcode-35] = stream.readString();
else if (opcode == 40) {
int length = stream.readUnsignedByte();
originalModelColors = new int[length];
modifiedModelColors = new int[length];
for(int index = 0; index < length; index++) {
originalModelColors[index] = stream.readUnsignedShort();
modifiedModelColors[index] = stream.readUnsignedShort();
}
}else if (opcode == 41) {
int length = stream.readUnsignedByte();
originalTextureColors = new int[length];
modifiedTextureColors = new int[length];
for(int index = 0; index < length; index++) {
originalTextureColors[index] = stream.readUnsignedShort();
modifiedTextureColors[index] = stream.readUnsignedShort();
}
}else if (opcode == 42) {
int length = stream.readUnsignedByte();
unknownArray1 = new byte[length];
for(int index = 0; index < length; index++)
unknownArray1[index] = (byte) stream.readByte();
}else if (opcode == 65)
unnoted = true;
else if (opcode == 78)
maleEquipModelId3 = stream.readBigSmart();
else if (opcode == 79)
femaleEquipModelId3 = stream.readBigSmart();
else if (opcode == 90)
unknownInt1 = stream.readBigSmart();
else if (opcode == 91)
unknownInt2 = stream.readBigSmart();
else if (opcode == 92)
unknownInt3 = stream.readBigSmart();
else if (opcode == 93)
unknownInt4 = stream.readBigSmart();
else if (opcode == 95)
unknownInt5 = stream.readUnsignedShort();
else if (opcode == 96)
unknownInt6 = stream.readUnsignedByte();
else if (opcode == 97)
switchNoteItemId = stream.readUnsignedShort();
else if (opcode == 98)
notedItemId = stream.readUnsignedShort();
else if (opcode >= 100 && opcode < 110) {
if (stackIds == null) {
stackIds = new int[10];
stackAmounts = new int[10];
}
stackIds[opcode-100] = stream.readUnsignedShort();
stackAmounts[opcode-100] = stream.readUnsignedShort();
}else if (opcode == 110)
unknownInt7 = stream.readUnsignedShort();
else if (opcode == 111)
unknownInt8 = stream.readUnsignedShort();
else if (opcode == 112)
unknownInt9 = stream.readUnsignedShort();
else if (opcode == 113)
unknownInt10 = stream.readByte();
else if (opcode == 114)
unknownInt11 = stream.readByte() * 5;
else if (opcode == 115)
teamId = stream.readUnsignedByte();
else if (opcode == 121)
switchLendItemId = stream.readUnsignedShort();
else if (opcode == 122)
lendedItemId = stream.readUnsignedShort();
else if (opcode == 125) {
unknownInt12 = stream.readByte() << 0;
unknownInt13 = stream.readByte() << 0;
unknownInt14 = stream.readByte() << 0;
}else if (opcode == 126) {
unknownInt15 = stream.readByte() << 0;
unknownInt16 = stream.readByte() << 0;
unknownInt17 = stream.readByte() << 0;
}else if (opcode == 127) {
unknownInt18 = stream.readUnsignedByte();
unknownInt19 = stream.readUnsignedShort();
}else if (opcode == 128) {
unknownInt20 = stream.readUnsignedByte();
unknownInt21 = stream.readUnsignedShort();
}else if (opcode == 129) {
unknownInt20 = stream.readUnsignedByte();
unknownInt21 = stream.readUnsignedShort();
}else if (opcode == 130) {
unknownInt22 = stream.readUnsignedByte();
unknownInt23 = stream.readUnsignedShort();
}else if (opcode == 132) {
int length = stream.readUnsignedByte();
unknownArray2 = new int[length];
for(int index = 0; index < length; index++)
unknownArray2[index] = stream.readUnsignedShort();
} else if (opcode == 134) {
int unknownValue = stream.readUnsignedByte();
}else if (opcode == 139) {
int unknownValue = stream.readUnsignedShort();
}else if (opcode == 140) {
int unknownValue = stream.readUnsignedShort();
}else if (opcode == 249) {
int length = stream.readUnsignedByte();
if(clientScriptData == null)
clientScriptData = new HashMap<Integer, Object>(length);
for (int index = 0; index < length; index++) {
boolean stringInstance = stream.readUnsignedByte() == 1;
int key = stream.read24BitInt();
Object value = stringInstance ? stream.readString() : stream.readInt();
clientScriptData.put(key, value);
}
}
else
throw new RuntimeException("MISSING OPCODE "+opcode+" FOR ITEM "+id);
}
private void readOpcodeValues(InputStream stream) {
while (true) {
int opcode = stream.readUnsignedByte();
if (opcode == 0)
break;
readValues(stream, opcode);
}
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void resetTextureColors() {
originalTextureColors = null;
modifiedTextureColors = null;
}
public void changeTextureColor(int originalModelColor, int modifiedModelColor) {
if(originalTextureColors != null) {
for(int i = 0; i < originalTextureColors.length; i++) {
if(originalTextureColors[i] == originalModelColor) {
modifiedTextureColors[i] = modifiedModelColor;
return;
}
}
int[] newOriginalModelColors = Arrays.copyOf(originalTextureColors, originalTextureColors.length+1);
int[] newModifiedModelColors = Arrays.copyOf(modifiedTextureColors, modifiedTextureColors.length+1);
newOriginalModelColors[newOriginalModelColors.length-1] = originalModelColor;
newModifiedModelColors[newModifiedModelColors.length-1] = modifiedModelColor;
originalTextureColors = newOriginalModelColors;
modifiedTextureColors = newModifiedModelColors;
}else{
originalTextureColors = new int[] { originalModelColor};
modifiedTextureColors = new int[] { modifiedModelColor};
}
}
public void resetModelColors() {
originalModelColors = null;
modifiedModelColors = null;
}
public void changeModelColor(int originalModelColor, int modifiedModelColor) {
if(originalModelColors != null) {
for(int i = 0; i < originalModelColors.length; i++) {
if(originalModelColors[i] == originalModelColor) {
modifiedModelColors[i] = modifiedModelColor;
return;
}
}
int[] newOriginalModelColors = Arrays.copyOf(originalModelColors, originalModelColors.length+1);
int[] newModifiedModelColors = Arrays.copyOf(modifiedModelColors, modifiedModelColors.length+1);
newOriginalModelColors[newOriginalModelColors.length-1] = originalModelColor;
newModifiedModelColors[newModifiedModelColors.length-1] = modifiedModelColor;
originalModelColors = newOriginalModelColors;
modifiedModelColors = newModifiedModelColors;
}else{
originalModelColors = new int[] { originalModelColor};
modifiedModelColors = new int[] { modifiedModelColor};
}
}
public String[] getGroundOptions() {
return groundOptions;
}
public String[] getInventoryOptions() {
return inventoryOptions;
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
@Override
public String toString() {
return id+" - "+name;
}
}

View file

@ -0,0 +1,159 @@
package com.alex.store;
import com.alex.io.InputStream;
import com.alex.io.OutputStream;
import com.alex.util.bzip2.BZip2Compressor;
import com.alex.util.bzip2.BZip2Decompressor;
import com.alex.util.crc32.CRC32HGenerator;
import com.alex.util.gzip.GZipCompressor;
import com.alex.util.gzip.GZipDecompressor;
import com.alex.util.whirlpool.Whirlpool;
import com.alex.utils.Constants;
public class Archive {
private int id;
private int revision;
private int compression;
private byte[] data;
private int[] keys;
protected Archive(int id, byte[] archive, int[] keys) {
this.id = id;
this.keys = keys;
decompress(archive);
}
public Archive(int id, int compression, int revision, byte[] data) {
this.id = id;
this.compression = compression;
this.revision = revision;
this.data = data;
}
public byte[] compress() {
OutputStream stream = new OutputStream();
stream.writeByte(compression);
byte[] compressedData;
switch(compression) {
case Constants.NO_COMPRESSION: //no compression
compressedData = data;
stream.writeInt(data.length);
break;
case Constants.BZIP2_COMPRESSION:
compressedData = null; //TODO
compressedData = BZip2Compressor.compress(data);
stream.writeInt(compressedData.length);
stream.writeInt(data.length);
//throw new RuntimeException("BZIP2_COMPRESSION NOT ADDED");
default: //gzip
compressedData = GZipCompressor.compress(data);
stream.writeInt(compressedData.length);
stream.writeInt(data.length);
break;
}
stream.writeBytes(compressedData);
if(keys != null && keys.length == 4)
stream.encodeXTEA(keys, 5, stream.getOffset());
if(revision != -1)
stream.writeShort(revision);
byte[] compressed = new byte[stream.getOffset()];
stream.setOffset(0);
stream.getBytes(compressed, 0, compressed.length);
return compressed;
}
private void decompress(byte[] archive) {
InputStream stream = new InputStream(archive);
if(keys != null && keys.length == 4)
stream.decodeXTEA(keys);
compression = stream.readUnsignedByte();
int compressedLength = stream.readInt();
if(compressedLength < 0 || compressedLength > Constants.MAX_VALID_ARCHIVE_LENGTH)
throw new RuntimeException("INVALID ARCHIVE HEADER");
switch(compression) {
case Constants.NO_COMPRESSION: //no compression
data = new byte[compressedLength];
checkRevision(compressedLength, archive, stream.getOffset());
stream.readBytes(data, 0, compressedLength);
break;
case Constants.BZIP2_COMPRESSION: //bzip2
int length = stream.readInt();
if(length <= 0) {
data = null;
break;
}
data = new byte[length];
checkRevision(compressedLength, archive, stream.getOffset());
BZip2Decompressor.decompress(data, archive, compressedLength, 9);
break;
default: //gzip
length = stream.readInt();
if(length <= 0 || length > 1000000000) {
data = null;
break;
}
data = new byte[length];
checkRevision(compressedLength, archive, stream.getOffset());
if(!GZipDecompressor.decompress(stream, data))
data = null;
break;
}
}
private void checkRevision(int compressedLength, byte[] archive, int o) {
InputStream stream = new InputStream(archive);
int offset = stream.getOffset();
if(stream.getLength()- (compressedLength+o) >= 2) {
stream.setOffset(stream.getLength()-2);
revision = stream.readUnsignedShort();
stream.setOffset(offset);
}else
revision = -1;
}
public Object[] editNoRevision(byte[] data, MainFile mainFile) {
this.data = data;
if(compression == Constants.BZIP2_COMPRESSION)
compression = Constants.GZIP_COMPRESSION;
byte[] compressed = compress();
if(!mainFile.putArchiveData(id, compressed))
return null;
return new Object[] {CRC32HGenerator.getHash(compressed), Whirlpool.getHash(compressed, 0, compressed.length)};
}
public int getId() {
return id;
}
public byte[] getData() {
return data;
}
public int getDecompressedLength() {
return data.length;
}
public int getRevision() {
return revision;
}
public void setRevision(int revision) {
this.revision = revision;
}
public int getCompression() {
return compression;
}
public int[] getKeys() {
return keys;
}
public void setKeys(int[] keys) {
this.keys = keys;
}
}

View file

@ -0,0 +1,133 @@
package com.alex.store;
import java.util.Arrays;
public class ArchiveReference {
private int nameHash;
private byte[] whirpool;
private int crc;
private int revision;
private FileReference[] files;
private int[] validFileIds;
private boolean needsFilesSort;
private boolean updatedRevision;
public void updateRevision() {
if(updatedRevision)
return;
revision++;
updatedRevision = true;
}
public int getNameHash() {
return nameHash;
}
public void setNameHash(int nameHash) {
this.nameHash = nameHash;
}
public byte[] getWhirpool() {
return whirpool;
}
public void setWhirpool(byte[] whirpool) {
this.whirpool = whirpool;
}
public int getCRC() {
return crc;
}
public void setCrc(int crc) {
this.crc = crc;
}
public int getRevision() {
return revision;
}
public FileReference[] getFiles() {
return files;
}
public void setFiles(FileReference[] files) {
this.files = files;
}
public void setRevision(int revision) {
this.revision = revision;
}
public int[] getValidFileIds() {
return validFileIds;
}
public void setValidFileIds(int[] validFileIds) {
this.validFileIds = validFileIds;
}
public boolean isNeedsFilesSort() {
return needsFilesSort;
}
public void setNeedsFilesSort(boolean needsFilesSort) {
this.needsFilesSort = needsFilesSort;
}
public void removeFileReference(int fileId) {
int[] newValidFileIds = new int[validFileIds.length-1];
int count = 0;
for(int id : validFileIds) {
if(id == fileId)
continue;
newValidFileIds[count++] = id;
}
validFileIds = newValidFileIds;
files[fileId] = null;
}
public void addEmptyFileReference(int fileId) {
needsFilesSort = true;
int[] newValidFileIds = Arrays.copyOf(validFileIds, validFileIds.length+1);
newValidFileIds[newValidFileIds.length-1] = fileId;
validFileIds = newValidFileIds;
if(files.length <= fileId) {
FileReference[] newFiles = Arrays.copyOf(files, fileId+1);
newFiles[fileId] = new FileReference();
files = newFiles;
}else
files[fileId] = new FileReference();
}
public void sortFiles() {
Arrays.sort(validFileIds);
needsFilesSort = false;
}
public void reset() {
whirpool = null;
updatedRevision = true;
revision = 0;
nameHash = 0;
crc = 0;
files = new FileReference[0];
validFileIds = new int[0];
needsFilesSort = false;
}
public void copyHeader(ArchiveReference fromReference) {
setCrc(fromReference.getCRC());
setNameHash(fromReference.getNameHash());
setWhirpool(fromReference.getWhirpool());
int[] validFiles = fromReference.getValidFileIds();
setValidFileIds(Arrays.copyOf(validFiles, validFiles.length));
FileReference[] files = fromReference.getFiles();
setFiles(Arrays.copyOf(files, files.length));
}
}

View file

@ -0,0 +1,15 @@
package com.alex.store;
public class FileReference {
private int nameHash;
public int getNameHash() {
return nameHash;
}
public void setNameHash(int nameHash) {
this.nameHash = nameHash;
}
}

View file

@ -0,0 +1,446 @@
package com.alex.store;
import com.alex.io.InputStream;
import com.alex.io.OutputStream;
import com.alex.util.crc32.CRC32HGenerator;
import com.alex.util.whirlpool.Whirlpool;
import com.alex.utils.Constants;
import com.alex.utils.Utils;
public final class Index {
private MainFile mainFile;
private MainFile index255;
private ReferenceTable table;
private byte[][][] cachedFiles;
private int crc;
private byte[] whirlpool;
protected Index(MainFile index255, MainFile mainFile, int[] keys) {
this.mainFile = mainFile;
this.index255 = index255;
byte[] archiveData = index255.getArchiveData(getId());
if (archiveData == null)
return;
crc = CRC32HGenerator.getHash(archiveData);
whirlpool = Whirlpool.getHash(archiveData, 0, archiveData.length);
Archive archive = new Archive(getId(), archiveData, keys);
table = new ReferenceTable(archive);
resetCachedFiles();
}
public void resetCachedFiles() {
cachedFiles = new byte[getLastArchiveId() + 1][][];
}
public int getLastFileId(int archiveId) {
if (!archiveExists(archiveId))
return -1;
return table.getArchives()[archiveId].getFiles().length - 1;
}
public int getLastArchiveId() {
return table.getArchives().length - 1;
}
public int getValidArchivesCount() {
return table.getValidArchiveIds().length;
}
public int getValidFilesCount(int archiveId) {
if (!archiveExists(archiveId))
return -1;
return table.getArchives()[archiveId].getValidFileIds().length;
}
public boolean archiveExists(int archiveId) {
if(archiveId < 0)
return false;
ArchiveReference[] archives = table.getArchives();
return archives.length > archiveId && archives[archiveId] != null;
}
public boolean fileExists(int archiveId, int fileId) {
if (!archiveExists(archiveId))
return false;
FileReference[] files = table.getArchives()[archiveId].getFiles();
return files.length > fileId && files[fileId] != null;
}
public int getArchiveId(String name) {
int nameHash = Utils.getNameHash(name);
ArchiveReference[] archives = table.getArchives();
int[] validArchiveIds = table.getValidArchiveIds();
for (int archiveId : validArchiveIds) {
if (archives[archiveId].getNameHash() == nameHash)
return archiveId;
}
return -1;
}
public int getFileId(int archiveId, String name) {
if (!archiveExists(archiveId))
return -1;
int nameHash = Utils.getNameHash(name);
FileReference[] files = table.getArchives()[archiveId].getFiles();
int[] validFileIds = table.getArchives()[archiveId].getValidFileIds();
for (int index = 0; index < validFileIds.length; index++) {
int fileId = validFileIds[index];
if (files[fileId].getNameHash() == nameHash)
return fileId;
}
return -1;
}
public byte[] getFile(int archiveId) {
if (!archiveExists(archiveId))
return null;
return getFile(archiveId,
table.getArchives()[archiveId].getValidFileIds()[0]);
}
public byte[] getFile(int archiveId, int fileId) {
return getFile(archiveId, fileId, null);
}
public byte[] getFile(int archiveId, int fileId, int[] keys) {
try {
if (!fileExists(archiveId, fileId)) {
return null;
}
if (cachedFiles[archiveId] == null || cachedFiles[archiveId][fileId] == null) cacheArchiveFiles(archiveId, keys);
byte[] file = cachedFiles[archiveId][fileId];
cachedFiles[archiveId][fileId] = null;
return file;
} catch (Throwable e) {
e.printStackTrace();
return null;
}
}
public boolean packIndex(Store originalStore) {
return packIndex(originalStore, false);
}
public boolean packIndex(Store originalStore, boolean checkCRC) {
try {
return packIndex(getId(), originalStore, checkCRC);
}catch (Exception e) {
}
return packIndex(getId(), originalStore, checkCRC);
}
public boolean packIndex(int id, Store originalStore, boolean checkCRC) {
try {
Index originalIndex = originalStore.getIndexes()[id];
for (int archiveId : originalIndex.table.getValidArchiveIds()) {
if (checkCRC
&& archiveExists(archiveId)
&& originalIndex.table.getArchives()[archiveId]
.getCRC() == table.getArchives()[archiveId]
.getCRC())
continue;
if (!putArchive(id, archiveId, originalStore, false, false))
return false;
}
if (!rewriteTable())
return false;
resetCachedFiles();
return true;
} catch (Exception e) {
}
return true;
}
public boolean putArchive(int archiveId, Store originalStore) {
return putArchive(getId(), archiveId, originalStore, true, true);
}
public boolean putArchive(int archiveId, Store originalStore,
boolean rewriteTable, boolean resetCache) {
return putArchive(getId(), archiveId, originalStore, rewriteTable, resetCache);
}
public boolean putArchive(int id, int archiveId, Store originalStore,
boolean rewriteTable, boolean resetCache) {
try {
Index originalIndex = originalStore.getIndexes()[id];
byte[] data = originalIndex.getMainFile().getArchiveData(archiveId);
if (data == null)
return false;
if (!archiveExists(archiveId))
table.addEmptyArchiveReference(archiveId);
ArchiveReference reference = table.getArchives()[archiveId];
reference.updateRevision();
ArchiveReference originalReference = originalIndex.table.getArchives()[archiveId];
reference.copyHeader(originalReference);
int revision = reference.getRevision();
data[data.length - 2] = (byte) (revision >> 8);
data[data.length - 1] = (byte) revision;
if (!mainFile.putArchiveData(archiveId, data))
return false;
if (rewriteTable && !rewriteTable())
return false;
if (resetCache)
resetCachedFiles();
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public boolean putFile(int archiveId, int fileId, byte[] data) {
return putFile(archiveId, fileId, Constants.GZIP_COMPRESSION, data,
null, true, true, -1, -1);
}
public boolean removeFile(int archiveId, int fileId) {
return removeFile(archiveId, fileId, Constants.GZIP_COMPRESSION, null);
}
public boolean removeFile(int archiveId, int fileId, int compression,
int[] keys) {
if (!fileExists(archiveId, fileId))
return false;
cacheArchiveFiles(archiveId, keys);
ArchiveReference reference = table.getArchives()[archiveId];
reference.removeFileReference(fileId);
int filesCount = getValidFilesCount(archiveId);
byte[] archiveData;
if (filesCount == 1)
archiveData = getFile(archiveId, reference.getValidFileIds()[0],
keys);
else {
int[] filesSize = new int[filesCount];
OutputStream stream = new OutputStream();
for (int index = 0; index < filesCount; index++) {
int id = reference.getValidFileIds()[index];
byte[] fileData = getFile(archiveId, id, keys);
filesSize[index] = fileData.length;
stream.writeBytes(fileData);
}
for (int index = 0; index < filesSize.length; index++) {
int offset = filesSize[index];
if (index != 0)
offset -= filesSize[index - 1];
stream.writeInt(offset);
}
stream.writeByte(1); // 1loop
archiveData = new byte[stream.getOffset()];
stream.setOffset(0);
stream.getBytes(archiveData, 0, archiveData.length);
}
reference.updateRevision();
Archive archive = new Archive(archiveId, compression,
reference.getRevision(), archiveData);
byte[] closedArchive = archive.compress();
reference.setCrc(CRC32HGenerator.getHash(closedArchive, 0,
closedArchive.length - 2));
reference.setWhirpool(Whirlpool.getHash(closedArchive, 0,
closedArchive.length - 2));
if (!mainFile.putArchiveData(archiveId, closedArchive))
return false;
if (!rewriteTable())
return false;
resetCachedFiles();
return true;
}
public boolean putFile(int archiveId, int fileId, int compression,
byte[] data, int[] keys, boolean rewriteTable, boolean resetCache,
int archiveName, int fileName) {
if (!archiveExists(archiveId)) {
table.addEmptyArchiveReference(archiveId);
resetCachedFiles();
cachedFiles[archiveId] = new byte[1][];
} else {
cacheArchiveFiles(archiveId, keys);
}
ArchiveReference reference = table.getArchives()[archiveId];
if (!fileExists(archiveId, fileId))
reference.addEmptyFileReference(fileId);
reference.sortFiles();
int filesCount = getValidFilesCount(archiveId);
byte[] archiveData;
if (filesCount == 1)
archiveData = data;
else {
int[] filesSize = new int[filesCount];
OutputStream stream = new OutputStream();
for (int index = 0; index < filesCount; index++) {
int id = reference.getValidFileIds()[index];
byte[] fileData;
if (id == fileId)
fileData = data;
else
fileData = getFile(archiveId, id, keys);
filesSize[index] = fileData.length;
stream.writeBytes(fileData);
}
for (int index = 0; index < filesCount; index++) {
int offset = filesSize[index];
if (index != 0)
offset -= filesSize[index - 1];
stream.writeInt(offset);
}
stream.writeByte(1); // 1loop
archiveData = new byte[stream.getOffset()];
stream.setOffset(0);
stream.getBytes(archiveData, 0, archiveData.length);
}
reference.updateRevision();
Archive archive = new Archive(archiveId, compression,
reference.getRevision(), archiveData);
//Fixed packing maps on 498
archive.setKeys(keys);
byte[] closedArchive = archive.compress();
reference.setCrc(CRC32HGenerator.getHash(closedArchive, 0,
closedArchive.length - 2));
reference.setWhirpool(Whirlpool.getHash(closedArchive, 0,
closedArchive.length - 2));
if (archiveName != -1)
reference.setNameHash(archiveName);
if (fileName != -1)
reference.getFiles()[fileId].setNameHash(fileName);
if (!mainFile.putArchiveData(archiveId, closedArchive))
return false;
if (rewriteTable && !rewriteTable())
return false;
if (resetCache)
resetCachedFiles();
return true;
}
public boolean encryptArchive(int archiveId, int[] keys) {
return encryptArchive(archiveId, null, keys, true, true);
}
public boolean encryptArchive(int archiveId, int[] oldKeys, int[] keys, boolean rewriteTable, boolean resetCache) {
if (!archiveExists(archiveId))
return false;
Archive archive = mainFile.getArchive(archiveId, oldKeys);
if (archive == null)
return false;
ArchiveReference reference = table.getArchives()[archiveId];
if(reference.getRevision() != archive.getRevision())
throw new RuntimeException("ERROR REVISION");
reference.updateRevision();
archive.setRevision(reference.getRevision());
archive.setKeys(keys);
byte[] closedArchive = archive.compress();
reference.setCrc(CRC32HGenerator.getHash(closedArchive, 0,
closedArchive.length - 2));
reference.setWhirpool(Whirlpool.getHash(closedArchive, 0,
closedArchive.length - 2));
if (!mainFile.putArchiveData(archiveId, closedArchive))
return false;
if (rewriteTable && !rewriteTable())
return false;
if (resetCache)
resetCachedFiles();
return true;
}
public boolean rewriteTable() {
table.updateRevision();
table.sortTable();
Object[] hashes = table.encodeHeader(index255);
if (hashes == null)
return false;
//crc = (int) hashes[0];
whirlpool = (byte[]) hashes[1];
return true;
}
public void setKeys(int[] keys) {
table.setKeys(keys);
}
public int[] getKeys() {
return table.getKeys();
}
private void cacheArchiveFiles(int archiveId, int[] keys) {
Archive archive = getArchive(archiveId, keys);
int lastFileId = getLastFileId(archiveId);
cachedFiles[archiveId] = new byte[lastFileId + 1][];
if (archive == null)
return;
byte[] data = archive.getData();
if (data == null)
return;
int filesCount = getValidFilesCount(archiveId);
if (filesCount == 1)
cachedFiles[archiveId][lastFileId] = data;
else {
int readPosition = data.length;
int amtOfLoops = data[--readPosition] & 0xff;
readPosition -= amtOfLoops * (filesCount * 4);
InputStream stream = new InputStream(data);
stream.setOffset(readPosition);
int filesSize[] = new int[filesCount];
for (int loop = 0; loop < amtOfLoops; loop++) {
int offset = 0;
for (int i = 0; i < filesCount; i++)
filesSize[i] += offset += stream.readInt();
}
byte[][] filesData = new byte[filesCount][];
for (int i = 0; i < filesCount; i++) {
filesData[i] = new byte[filesSize[i]];
filesSize[i] = 0;
}
stream.setOffset(readPosition);
int sourceOffset = 0;
for (int loop = 0; loop < amtOfLoops; loop++) {
int dataRead = 0;
for (int i = 0; i < filesCount; i++) {
dataRead += stream.readInt();
System.arraycopy(data, sourceOffset, filesData[i],
filesSize[i], dataRead);
sourceOffset += dataRead;
filesSize[i] += dataRead;
}
}
int count = 0;
for (int fileId : table.getArchives()[archiveId].getValidFileIds())
cachedFiles[archiveId][fileId] = filesData[count++];
}
}
public int getId() {
return mainFile.getId();
}
public ReferenceTable getTable() {
return table;
}
public MainFile getMainFile() {
return mainFile;
}
public Archive getArchive(int id) {
return mainFile.getArchive(id, null);
}
public Archive getArchive(int id, int[] keys) {
return mainFile.getArchive(id, keys);
}
public int getCRC() {
return crc;
}
public byte[] getWhirlpool() {
return whirlpool;
}
}

View file

@ -0,0 +1,249 @@
package com.alex.store;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import com.alex.utils.Constants;
/*
* Created by Alex(Dragonkk)
* 23/10/11
*/
public final class MainFile {
private static final int IDX_BLOCK_LEN = 6;
private static final int HEADER_LEN = 8;
private static final int EXPANDED_HEADER_LEN = 10;
private static final int BLOCK_LEN = 512;
private static final int EXPANDED_BLOCK_LEN = 510;
private static final int TOTAL_BLOCK_LEN = HEADER_LEN + BLOCK_LEN;
private static final ByteBuffer tempBuffer = ByteBuffer.allocateDirect(TOTAL_BLOCK_LEN);
private int id;
private FileChannel index;
private FileChannel data;
private boolean newProtocol;
protected MainFile(int id, RandomAccessFile data, RandomAccessFile index, boolean newProtocol) throws IOException {
this.id = id;
this.data = data.getChannel();
this.index = index.getChannel();
this.newProtocol = newProtocol;
}
public Archive getArchive(int id) {
return getArchive(id, null);
}
public Archive getArchive(int id, int[] keys) {
byte[] data = getArchiveData(id);
if(data == null)
return null;
return new Archive(id, data, keys);
}
public byte[] getArchiveData(int archiveId) {
synchronized(data) {
try {
tempBuffer.position(0).limit(IDX_BLOCK_LEN);
index.read(tempBuffer, archiveId * IDX_BLOCK_LEN);
tempBuffer.flip();
int size = getMediumInt(tempBuffer);
int block = getMediumInt(tempBuffer);
if (size < 0)
return null;
if (block <= 0 || block > data.size() / TOTAL_BLOCK_LEN) {
return null;
}
ByteBuffer fileBuffer = ByteBuffer.allocate(size);
int remaining = size;
int chunk = 0;
int blockLen = !newProtocol || archiveId <= 0xffff ? BLOCK_LEN : EXPANDED_BLOCK_LEN;
int headerLen = !newProtocol || archiveId <= 0xffff ? HEADER_LEN : EXPANDED_HEADER_LEN;
while (remaining > 0) {
if (block == 0) {
System.out.println(archiveId+", "+newProtocol);
return null;
}
int blockSize = remaining > blockLen ? blockLen : remaining;
tempBuffer.position(0).limit(blockSize + headerLen);
data.read(tempBuffer, block * TOTAL_BLOCK_LEN);
tempBuffer.flip();
int currentFile, currentChunk, nextBlock, currentIndex;
if (!newProtocol || archiveId <= 65535) {
currentFile = tempBuffer.getShort() & 0xffff;
currentChunk = tempBuffer.getShort() & 0xffff;
nextBlock = getMediumInt(tempBuffer);
currentIndex = tempBuffer.get() & 0xff;
} else {
currentFile = tempBuffer.getInt();
currentChunk = tempBuffer.getShort() & 0xffff;
nextBlock = getMediumInt(tempBuffer);
currentIndex = tempBuffer.get() & 0xff;
}
if ((archiveId != currentFile && archiveId <= 65535) || chunk != currentChunk || id != currentIndex) {
return null;
}
if (nextBlock < 0 || nextBlock > data.size() / TOTAL_BLOCK_LEN) {
return null;
}
fileBuffer.put(tempBuffer);
remaining -= blockSize;
block = nextBlock;
chunk++;
}
return (byte[]) fileBuffer.flip().array();
} catch (Exception ex) {
return null;
}
}
}
private static int getMediumInt(ByteBuffer buffer) {
return ((buffer.get() & 0xff) << 16) | ((buffer.get() & 0xff) << 8) |
(buffer.get() & 0xff);
}
private static void putMediumInt(ByteBuffer buffer, int val) {
buffer.put((byte) (val >> 16));
buffer.put((byte) (val >> 8));
buffer.put((byte) val);
}
public boolean putArchive(Archive archive) {
return putArchiveData(archive.getId(), archive.getData());
}
public boolean putArchiveData(int id, byte[] archive) {
ByteBuffer buffer = ByteBuffer.wrap(archive);
boolean done = putArchiveData(id, buffer, archive.length, true);
if(!done)
done = putArchiveData(id, buffer, archive.length, false);
return done;
}
public boolean putArchiveData(int archiveId, ByteBuffer archive, int size, boolean exists) {
synchronized(data) {
try {
int block;
if (exists) {
if (archiveId * IDX_BLOCK_LEN + IDX_BLOCK_LEN > index.size()) {
return false;
}
tempBuffer.position(0).limit(IDX_BLOCK_LEN);
index.read(tempBuffer, archiveId * IDX_BLOCK_LEN);
tempBuffer.flip().position(3);
block = getMediumInt(tempBuffer);
if (block <= 0 || block > data.size() / TOTAL_BLOCK_LEN) {
return false;
}
} else {
block = (int) (data.size() + TOTAL_BLOCK_LEN - 1) / TOTAL_BLOCK_LEN;
if (block == 0) {
block = 1;
}
}
tempBuffer.position(0);
putMediumInt(tempBuffer, size);
putMediumInt(tempBuffer, block);
tempBuffer.flip();
index.write(tempBuffer, archiveId * IDX_BLOCK_LEN);
int remaining = size;
int chunk = 0;
int blockLen = !newProtocol || archiveId <= 0xffff ? BLOCK_LEN : EXPANDED_BLOCK_LEN;
int headerLen = !newProtocol || archiveId <= 0xffff ? HEADER_LEN : EXPANDED_HEADER_LEN;
while (remaining > 0) {
int nextBlock = 0;
if (exists) {
tempBuffer.position(0).limit(headerLen);
data.read(tempBuffer, block * TOTAL_BLOCK_LEN);
tempBuffer.flip();
int currentFile, currentChunk, currentIndex;
if (!newProtocol || archiveId <= 0xffff) {
currentFile = tempBuffer.getShort() & 0xffff;
currentChunk = tempBuffer.getShort() & 0xffff;
nextBlock = getMediumInt(tempBuffer);
currentIndex = tempBuffer.get() & 0xff;
} else {
currentFile = tempBuffer.getInt();
currentChunk = tempBuffer.getShort() & 0xffff;
nextBlock = getMediumInt(tempBuffer);
currentIndex = tempBuffer.get() & 0xff;
}
if ((archiveId != currentFile && archiveId <= 65535)|| chunk != currentChunk || id != currentIndex) {
return false;
}
if (nextBlock < 0 || nextBlock > data.size() / TOTAL_BLOCK_LEN) {
return false;
}
}
if (nextBlock == 0) {
exists = false;
nextBlock = (int) ((data.size() + TOTAL_BLOCK_LEN - 1) / TOTAL_BLOCK_LEN);
if (nextBlock == 0) {
nextBlock = 1;
}
if (nextBlock == block) {
nextBlock++;
}
}
if (remaining <= blockLen) {
nextBlock = 0;
}
tempBuffer.position(0).limit(TOTAL_BLOCK_LEN);
if (!newProtocol || archiveId <= 0xffff) {
tempBuffer.putShort((short) archiveId);
tempBuffer.putShort((short) chunk);
putMediumInt(tempBuffer, nextBlock);
tempBuffer.put((byte) id);
} else {
tempBuffer.putInt(archiveId);
tempBuffer.putShort((short) chunk);
putMediumInt(tempBuffer, nextBlock);
tempBuffer.put((byte) id);
}
int blockSize = remaining > blockLen ? blockLen : remaining;
archive.limit(archive.position() + blockSize);
tempBuffer.put(archive);
tempBuffer.flip();
data.write(tempBuffer, block * TOTAL_BLOCK_LEN);
remaining -= blockSize;
block = nextBlock;
chunk++;
}
return true;
} catch (Exception ex) {
return false;
}
}
}
public int getId() {
return id;
}
public int getArchivesCount() throws IOException {
synchronized(index) {
return (int) (index.size()/6);
}
}
}

View file

@ -0,0 +1,241 @@
package com.alex.store;
import java.util.Arrays;
import com.alex.io.InputStream;
import com.alex.io.OutputStream;
public final class ReferenceTable {
private Archive archive;
private int revision;
private boolean named;
private boolean usesWhirpool;
private ArchiveReference[] archives;
private int[] validArchiveIds;
//editing
private boolean updatedRevision;
private boolean needsArchivesSort;
protected ReferenceTable(Archive archive) {
this.archive = archive;
decodeHeader();
}
public void setKeys(int[] keys) {
archive.setKeys(keys);
}
public int[] getKeys() {
return archive.getKeys();
}
public void sortArchives() {
Arrays.sort(validArchiveIds);
needsArchivesSort = false;
}
public void addEmptyArchiveReference(int archiveId) {
needsArchivesSort = true;
int[] newValidArchiveIds = Arrays.copyOf(validArchiveIds, validArchiveIds.length+1);
newValidArchiveIds[newValidArchiveIds.length-1] = archiveId;
validArchiveIds = newValidArchiveIds;
ArchiveReference reference;
if(archives.length <= archiveId) {
ArchiveReference[] newArchives = Arrays.copyOf(archives, archiveId+1);
reference = newArchives[archiveId] = new ArchiveReference();
archives = newArchives;
}else
reference = archives[archiveId] = new ArchiveReference();
reference.reset();
}
public void sortTable() {
if(needsArchivesSort)
sortArchives();
for(int index = 0; index < validArchiveIds.length; index++) {
ArchiveReference archive = archives[validArchiveIds[index]];
if(archive.isNeedsFilesSort())
archive.sortFiles();
}
}
public Object[] encodeHeader(MainFile mainFile) {
OutputStream stream = new OutputStream();
int protocol = getProtocol();
stream.writeByte(protocol);
if(protocol >= 6)
stream.writeInt(revision);
stream.writeByte((named ? 0x1 : 0) | (usesWhirpool ? 0x2 : 0));
if(protocol >= 7)
stream.writeBigSmart(validArchiveIds.length);
else
stream.writeShort(validArchiveIds.length);
for(int index = 0; index < validArchiveIds.length; index++) {
int offset = validArchiveIds[index];
if(index != 0)
offset -= validArchiveIds[index-1];
if(protocol >= 7)
stream.writeBigSmart(offset);
else
stream.writeShort(offset);
}
if(named)
for(int index = 0; index < validArchiveIds.length; index++)
stream.writeInt(archives[validArchiveIds[index]].getNameHash());
if(usesWhirpool)
for(int index = 0; index < validArchiveIds.length; index++)
stream.writeBytes(archives[validArchiveIds[index]].getWhirpool());
for(int index = 0; index < validArchiveIds.length; index++)
stream.writeInt(archives[validArchiveIds[index]].getCRC());
for(int index = 0; index < validArchiveIds.length; index++)
stream.writeInt(archives[validArchiveIds[index]].getRevision());
for(int index = 0; index < validArchiveIds.length; index++) {
int value = archives[validArchiveIds[index]].getValidFileIds().length;
if(protocol >= 7)
stream.writeBigSmart(value);
else
stream.writeShort(value);
}
for(int index = 0; index < validArchiveIds.length; index++) {
ArchiveReference archive = archives[validArchiveIds[index]];
for(int index2 = 0; index2 < archive.getValidFileIds().length; index2++) {
int offset = archive.getValidFileIds()[index2];
if(index2 != 0)
offset -= archive.getValidFileIds()[index2-1];
if(protocol >= 7)
stream.writeBigSmart(offset);
else
stream.writeShort(offset);
}
}
if(named) {
for(int index = 0; index < validArchiveIds.length; index++) {
ArchiveReference archive = archives[validArchiveIds[index]];
for(int index2 = 0; index2 < archive.getValidFileIds().length; index2++)
stream.writeInt(archive.getFiles()[archive.getValidFileIds()[index2]].getNameHash());
}
}
byte[] data = new byte[stream.getOffset()];
stream.setOffset(0);
stream.getBytes(data, 0, data.length);
return archive.editNoRevision(data, mainFile);
}
public int getProtocol() {
if(archives.length > 65535)
return 7;
for(int index = 0; index < validArchiveIds.length; index++) {
if(index > 0)
if(validArchiveIds[index] - validArchiveIds[index-1] > 65535)
return 7;
if(archives[validArchiveIds[index]].getValidFileIds().length > 65535)
return 7;
}
return revision == 0 ? 5 : 6;
}
public void setRevision(int revision) {
updatedRevision = true;
this.revision = revision;
}
public void updateRevision() {
if(updatedRevision)
return;
revision++;
updatedRevision = true;
}
private void decodeHeader() {
InputStream stream = new InputStream(archive.getData());
int protocol = stream.readUnsignedByte();
if (protocol < 5 || protocol > 7)
throw new RuntimeException("INVALID PROTOCOL");
if(protocol >= 6)
revision = stream.readInt();
int hash = stream.readUnsignedByte();
named = (0x1 & hash) != 0;
usesWhirpool = (0x2 & hash) != 0;
int validArchivesCount = protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort();
validArchiveIds = new int[validArchivesCount];
int lastArchiveId = 0;
int biggestArchiveId = 0;
for(int index = 0; index < validArchivesCount; index++) {
int archiveId = lastArchiveId += protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort();
if(archiveId > biggestArchiveId)
biggestArchiveId = archiveId;
validArchiveIds[index] = archiveId;
}
archives = new ArchiveReference[biggestArchiveId+1];
for(int index = 0; index < validArchivesCount; index++)
archives[validArchiveIds[index]] = new ArchiveReference();
if(named)
for(int index = 0; index < validArchivesCount; index++)
archives[validArchiveIds[index]].setNameHash(stream.readInt());
if(usesWhirpool) {
for(int index = 0; index < validArchivesCount; index++) {
byte[] whirpool = new byte[64];
stream.getBytes(whirpool, 0, 64);
archives[validArchiveIds[index]].setWhirpool(whirpool);
}
}
for(int index = 0; index < validArchivesCount; index++)
archives[validArchiveIds[index]].setCrc(stream.readInt());
for(int index = 0; index < validArchivesCount; index++)
archives[validArchiveIds[index]].setRevision(stream.readInt());
for(int index = 0; index < validArchivesCount; index++)
archives[validArchiveIds[index]].setValidFileIds(new int[protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort()]);
for(int index = 0; index < validArchivesCount; index++) {
int lastFileId = 0;
int biggestFileId = 0;
ArchiveReference archive = archives[validArchiveIds[index]];
for(int index2 = 0; index2 < archive.getValidFileIds().length; index2++) {
int fileId = lastFileId += protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort();
if(fileId > biggestFileId)
biggestFileId = fileId;
archive.getValidFileIds()[index2] = fileId;
}
archive.setFiles(new FileReference[biggestFileId+1]);
for(int index2 = 0; index2 < archive.getValidFileIds().length; index2++)
archive.getFiles()[archive.getValidFileIds()[index2]] = new FileReference();
}
if(named) {
for(int index = 0; index < validArchivesCount; index++) {
ArchiveReference archive = archives[validArchiveIds[index]];
for(int index2 = 0; index2 < archive.getValidFileIds().length; index2++)
archive.getFiles()[archive.getValidFileIds()[index2]].setNameHash(stream.readInt());
}
}
}
public int getRevision() {
return revision;
}
public ArchiveReference[] getArchives() {
return archives;
}
public int[] getValidArchiveIds() {
return validArchiveIds;
}
public boolean isNamed() {
return named;
}
public boolean usesWhirpool() {
return usesWhirpool;
}
public int getCompression() {
return archive.getCompression();
}
}

View file

@ -0,0 +1,149 @@
package com.alex.store;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.math.BigInteger;
import java.util.Arrays;
import com.alex.io.OutputStream;
import com.alex.util.whirlpool.Whirlpool;
import com.alex.utils.Constants;
import com.alex.utils.Utils;
public final class Store {
private Index[] indexes;
private MainFile index255;
private String path;
private RandomAccessFile data;
private boolean newProtocol;
public Store(String path) throws IOException {
this(path, Constants.CLIENT_BUILD >= 704);
}
public Store(String path, boolean newProtocol) throws IOException {
this(path, newProtocol, null);
}
public Store(String path, boolean newProtocol, int[][] keys) throws IOException {
this.path = path;
this.newProtocol = newProtocol;
data = new RandomAccessFile(path + "main_file_cache.dat2", "rw");
index255 = new MainFile(255, data, new RandomAccessFile(path + "main_file_cache.idx255", "rw"), newProtocol);
int idxsCount = index255.getArchivesCount();
indexes = new Index[idxsCount];
for (int id = 0; id < idxsCount; id++) {
Index index = new Index(index255, new MainFile(id, data, new RandomAccessFile(path + "main_file_cache.idx" + id, "rw"), newProtocol), keys == null ? null : keys[id]);
if (index.getTable() == null)
continue;
indexes[id] = index;
}
}
public final byte[] generateIndex255Archive255Current(BigInteger grab_server_private_exponent, BigInteger grab_server_modulus) {
OutputStream stream = new OutputStream();
stream.writeByte(getIndexes().length);
for (int index = 0; index < getIndexes().length; index++) {
if (getIndexes()[index] == null) {
stream.writeInt(0);
stream.writeInt(0);
stream.writeBytes(new byte[64]);
continue;
}
stream.writeInt(getIndexes()[index].getCRC());
stream.writeInt(getIndexes()[index].getTable().getRevision());
stream.writeBytes(getIndexes()[index].getWhirlpool());
if (Constants.ENCRYPTED_CACHE) {
// custom protection, encryption of tables addition, by me
// dragonkk ofc
if (getIndexes()[index].getKeys() != null)
for (int key : getIndexes()[index].getKeys())
stream.writeInt(key);
else
for (int i = 0; i < 4; i++)
stream.writeInt(0);
}
}
byte[] archive = new byte[stream.getOffset()];
stream.setOffset(0);
stream.getBytes(archive, 0, archive.length);
OutputStream hashStream = new OutputStream(65);
hashStream.writeByte(0);
hashStream.writeBytes(Whirlpool.getHash(archive, 0, archive.length));
byte[] hash = new byte[hashStream.getOffset()];
hashStream.setOffset(0);
hashStream.getBytes(hash, 0, hash.length);
if (grab_server_private_exponent != null && grab_server_modulus != null)
hash = Utils.cryptRSA(hash, grab_server_private_exponent, grab_server_modulus);
stream.writeBytes(hash);
archive = new byte[stream.getOffset()];
stream.setOffset(0);
stream.getBytes(archive, 0, archive.length);
return archive;
}
@SuppressWarnings("unused")
public byte[] generateIndex255Archive255() {
return Constants.CLIENT_BUILD < 614 ? generateIndex255Archive255Outdated() : generateIndex255Archive255Current(null, null);
}
/*
* old code
*/
public byte[] generateIndex255Archive255Outdated() {
OutputStream stream = new OutputStream(indexes.length * 8);
for (int index = 0; index < indexes.length; index++) {
if (indexes[index] == null) {
stream.writeInt(0);
stream.writeInt(0);
continue;
}
stream.writeInt(indexes[index].getCRC());
stream.writeInt(indexes[index].getTable().getRevision());
}
byte[] archive = new byte[stream.getOffset()];
stream.setOffset(0);
stream.getBytes(archive, 0, archive.length);
return archive;
}
public Index[] getIndexes() {
return indexes;
}
public MainFile getIndex255() {
return index255;
}
/*
* returns index
*/
public int addIndex(boolean named, boolean usesWhirpool, int tableCompression) throws IOException {
int id = indexes.length;
Index[] newIndexes = Arrays.copyOf(indexes, indexes.length + 1);
resetIndex(id, newIndexes, named, usesWhirpool, tableCompression);
indexes = newIndexes;
return id;
}
public void resetIndex(int id, boolean named, boolean usesWhirpool, int tableCompression) throws FileNotFoundException, IOException {
resetIndex(id, indexes, named, usesWhirpool, tableCompression);
}
public void resetIndex(int id, Index[] indexes, boolean named, boolean usesWhirpool, int tableCompression) throws FileNotFoundException, IOException {
OutputStream stream = new OutputStream(4);
stream.writeByte(5);
stream.writeByte((named ? 0x1 : 0) | (usesWhirpool ? 0x2 : 0));
stream.writeShort(0);
byte[] archiveData = new byte[stream.getOffset()];
stream.setOffset(0);
stream.getBytes(archiveData, 0, archiveData.length);
Archive archive = new Archive(id, tableCompression, -1, archiveData);
index255.putArchiveData(id, archive.compress());
indexes[id] = new Index(index255, new MainFile(id, data, new RandomAccessFile(path + "main_file_cache.idx" + id, "rw"), newProtocol), null);
}
}

View file

@ -0,0 +1,45 @@
package com.alex.tools.clientCacheUpdater;
import java.io.IOException;
import java.util.Random;
import com.alex.store.Archive;
import com.alex.store.ArchiveReference;
import com.alex.store.Index;
import com.alex.store.Store;
public class ArchiveValidation {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
Store rscache = new Store("498/");
for(int i = 0; i < rscache.getIndexes().length; i++) {
if(i == 5)
continue;
Index index = rscache.getIndexes()[i];
System.out.println("checking index: "+i);
for(int archiveId : index.getTable().getValidArchiveIds()) {
Archive archive = index.getArchive(archiveId);
if(archive == null) {
System.out.println("Missing:: "+i+", "+archiveId);
continue;
}
ArchiveReference reference = index.getTable().getArchives()[archiveId];
if(archive.getRevision() != reference.getRevision() ) {
System.out.println("corrupted: "+i+", "+archiveId);
}
}
}
}
public static int[] generateKeys() {
int[] keys = new int[4];
for (int index = 0; index < keys.length; index++)
keys[index] = new Random().nextInt();
return keys;
}
}

View file

@ -0,0 +1,272 @@
package com.alex.tools.clientCacheUpdater;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import com.alex.loaders.items.ItemDefinitions;
import com.alex.store.Index;
import com.alex.store.Store;
import com.alex.utils.Constants;
import com.alex.utils.Utils;
public class CacheEditor {
public static byte[] getBytesFromFile(File file) throws IOException {
InputStream is = new FileInputStream(file);
// Get the size of the file
long length = file.length();
// You cannot create an array using a long type.
// It needs to be an int type.
// Before converting to an int type, check
// to ensure that file is not larger than Integer.MAX_VALUE.
if (length > Integer.MAX_VALUE) {
// File is too large
}
// Create the byte array to hold the data
byte[] bytes = new byte[(int)length];
// Read in the bytes
int offset = 0;
int numRead = 0;
while (offset < bytes.length
&& (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
offset += numRead;
}
// Ensure all the bytes have been read in
if (offset < bytes.length) {
throw new IOException("Could not completely read file "+file.getName());
}
// Close the input stream and return bytes
is.close();
return bytes;
}
public static int packCustomModel(Store cache, byte[] data) {
//recommended id 80000+ since rs uses all ids till 66000
int archiveId = cache.getIndexes()[19].getLastArchiveId()+1;
if(cache.getIndexes()[19].putFile(archiveId, 0, data))
return archiveId;
System.out.println("Failing packing model "+archiveId);
return -1;
}
public static void packCustomItems(Store cache) throws IOException {
int modelID = packCustomModel(cache, getBytesFromFile(new File("44590.dat")));
if (modelID == -1) {
System.err.println("Error! Model id =-1!");
return;
}
ItemDefinitions donatorCape = ItemDefinitions.getItemDefinition(cache, 9747);
donatorCape.setName("Dragon Claws");
donatorCape.femaleEquipModelId1 = modelID;
donatorCape.maleEquipModelId1 = modelID;
donatorCape.invModelId = modelID;
donatorCape.resetModelColors();
packCustomItem(cache, 29999, donatorCape);
}
public static void packCustomItem(Store cache, int id, ItemDefinitions def) {
cache.getIndexes()[19].putFile(id >>> 8, 0xff & id, def.encode());
}
/*
* divides bg
*/
public static void divideBackgrounds() throws IOException {
BufferedImage background = ImageIO.read(new File("718/sprites/bg.jpg"));
int id = 4139;
int sx = background.getWidth() / 4;
int sy = background.getHeight() / 2;
for(int y = 0; y < 2; y++) {
for(int x = 0; x < 4; x++) {
BufferedImage part = background.getSubimage(x * sx, y * sy, sx, sy);
ImageIO.write(part, "gif", new File("718/sprites/bg/"+(id++)+".gif"));
}
}
BufferedImage load = ImageIO.read(new File("718/sprites/load.png"));
id = 3769;
sx = load.getWidth() / 2;
sy = load.getHeight() / 2;
for(int y = 0; y < 2; y++) {
for(int x = 0; x < 2; x++) {
BufferedImage part = load.getSubimage(x * sx, y * sy, sx, sy);
ImageIO.write(part, "png", new File("718/sprites/load/"+id+".png"));
ImageIO.write(part, "gif", new File("718/sprites/load/"+(id++)+".gif"));
}
}
}
public static byte[] getImage(File file) throws IOException {
ImageOutputStream stream = ImageIO.createImageOutputStream(file);
byte[] data = new byte[(int) stream.length()];
stream.read(data);
return data;
}
public static void main(String[] args) throws IOException {
packCustomItems(new Store("./498/"));
/*boolean beta = false;
boolean addNewItemDefinitions = false; //only needed once
boolean divideBackgrounds = false; //only needed once
if(divideBackgrounds)
divideBackgrounds();
Store rscache = new Store(beta ? "718/rsCacheBeta/" : "718/rscache/");
Store cache = new Store(beta ? "718/cacheBeta/" : "718/cache/");
boolean result;
cache.resetIndex(7, false, false, Constants.GZIP_COMPRESSION);
for(int i = 0; i < cache.getIndexes().length; i++) {
if(i != 3 //interfaces
&& i != 5 //maps
&& i != 12) //client scripts
{
result = cache.getIndexes()[i].packIndex(rscache, true);
System.out.println("Packed index archives: "+i+", "+result);
}
}
if(addNewItemDefinitions) {
System.out.println("Packing old item definitions...");
Store cache667 = new Store("cache667/", false);
int currentSize = 30000;//Utils.getItemDefinitionsSize(cache);
int oldSize = Utils.getItemDefinitionsSize(cache667);
for(int i = currentSize ; i < currentSize+oldSize; i++) {
int newItemId = i;
int oldItemId = i - currentSize;
cache.getIndexes()[19].putFile(newItemId >>> 8, 0xff & newItemId, Constants.GZIP_COMPRESSION, cache667.getIndexes()[19].getFile(oldItemId >>> 8, 0xff & oldItemId), null, false, false, -1, -1);
}
result = cache.getIndexes()[19].rewriteTable();
System.out.println("Packed old item definitions: "+result);
}
/*System.out.println("Packing custom items...");
packCustomItems(cache);
System.out.println("Adding new interfaces...");
for(int i = cache.getIndexes()[3].getLastArchiveId()+1; i <= rscache.getIndexes()[3].getLastArchiveId(); i++) {
if(i == 548 || i == 746)
continue;
if(rscache.getIndexes()[3].archiveExists(i))
cache.getIndexes()[3].putArchive(i, rscache, false, false);
}
result = cache.getIndexes()[3].rewriteTable();
System.out.println("Packed new interfaces: "+result);*/
//System.out.println("Adding custom sprites...");
//adds icons
//IndexedColorImageFile iconsFile = new IndexedColorImageFile(cache, 1455, 0);
//BufferedImage icon = ImageIO.read(new File("1455.png"));
//System.out.println("Added icon: "+iconsFile.addImage(icon)+".");
//BufferedImage icon2 = ImageIO.read(new File("1455f.png"));
//System.out.println("Added icon2: "+iconsFile.addImage(icon2)+".");
//BufferedImage icon3 = ImageIO.read(new File("crown_green.gif"));
//System.out.println("Added icon3: "+iconsFile.addImage(icon3)+".");
//BufferedImage icon4 = ImageIO.read(new File("1455_11.png"));
//System.out.println("Added icon4: "+iconsFile.addImage(icon4)+".");
//result = cache.getIndexes()[8].putFile(1455, 0, Constants.GZIP_COMPRESSION, iconsFile.encodeFile(), null, false, false, -1, -1);
//System.out.println("Added icons: "+result);
//result = cache.getIndexes()[8].putFile(2173, 0, Constants.GZIP_COMPRESSION,
//new IndexedColorImageFile(ImageIO.read(new File("2173.png"))).encodeFile()
//, null, false, false, -1, -1);
//System.out.println("Added matrix flag: "+result);
//result = cache.getIndexes()[8].putFile(2498, 0, Constants.GZIP_COMPRESSION,
//new IndexedColorImageFile(ImageIO.read(new File("718/sprites/logo.png"))).encodeFile()
//, null, false, false, -1, -1);
//System.out.println("Added matrix logo: "+result);
//Login Background
/*
for(int i = 4139; i <= 4146; i++) {
result = cache.getIndexes()[8].putFile(i, 0, Constants.GZIP_COMPRESSION,
new IndexedColorImageFile(ImageIO.read(new File("718/sprites/bg/"+i+".png"))).encodeFile()
, null, false, false, -1, -1);
}
System.out.println("Added noregret background: "+result);
*s
//Loading Background
for(int i = 0; i < 4; i++) {
int realid = 3769 + i;
byte[] sprite = new IndexedColorImageFile(ImageIO.read(new File("718/sprites/load/"+realid+".gif"))).encodeFile();
byte[] image = getImage(new File("718/sprites/load/"+realid+".png"));
int[] ids = new int[] {3769 + i
, 3779 + i
, 3783 + (i >= 2 ? (i-2) : i + 2)
, 8494 + (i >= 2 ? (i-2) : i + 2)
, 8498 + (i >= 2 ? (i-2) : i + 2)};
for(int id : ids) {
result = cache.getIndexes()[8].putFile(id, 0, Constants.GZIP_COMPRESSION, sprite, null, false, false, -1, -1);
result = cache.getIndexes()[32].putFile(id, 0, Constants.GZIP_COMPRESSION, image, null, false, false, -1, -1);
result = cache.getIndexes()[34].putFile(id, 0, Constants.GZIP_COMPRESSION, image, null, false, false, -1, -1);
}
}
//System.out.println("Added Loading background: "+result);
result = cache.getIndexes()[8].rewriteTable();
result = cache.getIndexes()[32].rewriteTable();
result = cache.getIndexes()[34].rewriteTable();
System.out.println("Added custom sprites: "+result);
/*RSXteas.loadUnpackedXteas();
System.out.println("Updating Maps.");
for(int regionId = 0; regionId < 30000; regionId++) {
int regionX = (regionId >> 8) * 64;
int regionY = (regionId & 0xff) * 64;
String name = "m"+ ((regionX >> 3) / 8) + "_" + ((regionY >> 3) / 8);
byte[] data = rscache.getIndexes()[5].getFile(rscache.getIndexes()[5].getArchiveId(name));
if(data != null) {
result = addMapFile(cache.getIndexes()[5], name, data);
System.out.println(name+", "+result);
}
name = "um"+ ((regionX >> 3) / 8) + "_" + ((regionY >> 3) / 8);
data = rscache.getIndexes()[5].getFile(rscache.getIndexes()[5].getArchiveId(name));
if(data != null) {
result = addMapFile(cache.getIndexes()[5], name, data);
System.out.println(name+", "+result);
}
int[] xteas = RSXteas.getXteas(regionId);
name = "l"+ ((regionX >> 3) / 8) + "_" + ((regionY >> 3) / 8);
data = rscache.getIndexes()[5].getFile(rscache.getIndexes()[5].getArchiveId(name), 0, xteas);
if(data != null) {
result = addMapFile(cache.getIndexes()[5], name, data);
System.out.println(name+", "+result);
}
name = "ul"+ ((regionX >> 3) / 8) + "_" + ((regionY >> 3) / 8);
data = rscache.getIndexes()[5].getFile(rscache.getIndexes()[5].getArchiveId(name), 0, xteas);
if(data != null) {
result = addMapFile(cache.getIndexes()[5], name, data);
System.out.println(name+", "+result);
}
name = "n"+ ((regionX >> 3) / 8) + "_" + ((regionY >> 3) / 8);
data = rscache.getIndexes()[5].getFile(rscache.getIndexes()[5].getArchiveId(name), 0);
if(data != null) {
result = addMapFile(cache.getIndexes()[5], name, data);
System.out.println(name+", "+result);
}
}
result = cache.getIndexes()[5].rewriteTable();
System.out.println("Updated maps: "+result);*/
}
public static boolean addMapFile(Index index, String name, byte[] data) {
int archiveId = index.getArchiveId(name);
if(archiveId == -1)
archiveId = index.getTable().getValidArchiveIds().length;
return index.putFile(archiveId, 0, Constants.GZIP_COMPRESSION, data, null, false, false, Utils.getNameHash(name), -1);
}
}

View file

@ -0,0 +1,162 @@
package com.alex.tools.clientCacheUpdater;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import com.alex.loaders.images.IndexedColorImageFile;
import com.alex.loaders.items.ItemDefinitions;
import com.alex.store.Index;
import com.alex.store.Store;
import com.alex.utils.Constants;
import com.alex.utils.Utils;
public class CacheEditormodels {
public static byte[] getBytesFromFile(File file) throws IOException {
InputStream is = new FileInputStream(file);
// Get the size of the file
long length = file.length();
// You cannot create an array using a long type.
// It needs to be an int type.
// Before converting to an int type, check
// to ensure that file is not larger than Integer.MAX_VALUE.
if (length > Integer.MAX_VALUE) {
// File is too large
}
// Create the byte array to hold the data
byte[] bytes = new byte[(int)length];
// Read in the bytes
int offset = 0;
int numRead = 0;
while (offset < bytes.length
&& (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
offset += numRead;
}
// Ensure all the bytes have been read in
if (offset < bytes.length) {
throw new IOException("Could not completely read file "+file.getName());
}
// Close the input stream and return bytes
is.close();
return bytes;
}
public static int packCustomModel(Store cache, byte[] data) {
//recommended id 80000+ since rs uses all ids till 66000
int archiveId = cache.getIndexes()[7].getLastArchiveId()+1;
if(cache.getIndexes()[7].putFile(archiveId, 0, data))
return archiveId;
System.out.println("Failing packing model "+archiveId);
return -1;
}
public static void packCustomItems(Store cache) throws IOException {
int modelID = packCustomModel(cache, getBytesFromFile(new File("pkcapefinalb.dat")));
ItemDefinitions pkCape = ItemDefinitions.getItemDefinition(cache, 9747);
pkCape.setName("PK Cape");
//donatorCape.getInventoryOptions()[2] = "Customise";
pkCape.femaleEquipModelId1 = modelID;
pkCape.maleEquipModelId1 = modelID;
pkCape.invModelId = modelID;
pkCape.resetModelColors();
packCustomItem(cache, 30000, pkCape);
/*int wearModelID = packCustomModel(cache, getBytesFromFile(new File("718/lightSaber/wear.dat")));
int invModelID = packCustomModel(cache, getBytesFromFile(new File("718/lightSaber/inv.dat")));
ItemDefinitions lightSaber = ItemDefinitions.getItemDefinition(cache, 2402);
lightSaber.setName("Light Saber");
lightSaber.getInventoryOptions()[2] = "Customise";
lightSaber.femaleEquipModelId1 = wearModelID;
lightSaber.maleEquipModelId1 = wearModelID;
lightSaber.invModelId = invModelID;
lightSaber.resetModelColors();
packCustomItem(cache, 29998, lightSaber);*/
}
public static void packCustomItem(Store cache, int id, ItemDefinitions def) {
cache.getIndexes()[19].putFile(id >>> 8, 0xff & id, def.encode());
}
/*
* divides bg
*/
public static void divideBackgrounds() throws IOException {
BufferedImage background = ImageIO.read(new File("718/sprites/bg.jpg"));
int id = 4139;
int sx = background.getWidth() / 4;
int sy = background.getHeight() / 2;
for(int y = 0; y < 2; y++) {
for(int x = 0; x < 4; x++) {
BufferedImage part = background.getSubimage(x * sx, y * sy, sx, sy);
ImageIO.write(part, "gif", new File("718/sprites/bg/"+(id++)+".gif"));
}
}
BufferedImage load = ImageIO.read(new File("718/sprites/load.png"));
id = 3769;
sx = load.getWidth() / 2;
sy = load.getHeight() / 2;
for(int y = 0; y < 2; y++) {
for(int x = 0; x < 2; x++) {
BufferedImage part = load.getSubimage(x * sx, y * sy, sx, sy);
ImageIO.write(part, "png", new File("718/sprites/load/"+id+".png"));
ImageIO.write(part, "gif", new File("718/sprites/load/"+(id++)+".gif"));
}
}
}
public static byte[] getImage(File file) throws IOException {
ImageOutputStream stream = ImageIO.createImageOutputStream(file);
byte[] data = new byte[(int) stream.length()];
stream.read(data);
return data;
}
public static void main(String[] args) throws IOException {
boolean beta = false;
boolean addNewItemDefinitions = false; //only needed once
boolean divideBackgrounds = false; //only needed once
if(divideBackgrounds)
divideBackgrounds();
Store rscache = new Store(beta ? "718/rsCacheBeta/" : "718/rscache/");
Store cache = new Store(beta ? "718/cacheBeta/" : "718/cache/");
boolean result;
cache.resetIndex(7, false, false, Constants.GZIP_COMPRESSION);
for(int i = 0; i < cache.getIndexes().length; i++) {
if(i != 3 //interfaces
&& i != 5 //maps
&& i != 12) //client scripts
{
result = cache.getIndexes()[i].packIndex(rscache, true);
System.out.println("Packed index archives: "+i+", "+result);
}
}
if(addNewItemDefinitions) {
System.out.println("Packing old item definitions...");
Store cache667 = new Store("cache667/", false);
int currentSize = 30000;//Utils.getItemDefinitionsSize(cache);
int oldSize = Utils.getItemDefinitionsSize(cache667);
for(int i = currentSize ; i < currentSize+oldSize; i++) {
int newItemId = i;
int oldItemId = i - currentSize;
cache.getIndexes()[19].putFile(newItemId >>> 8, 0xff & newItemId, Constants.GZIP_COMPRESSION, cache667.getIndexes()[19].getFile(oldItemId >>> 8, 0xff & oldItemId), null, false, false, -1, -1);
}
result = cache.getIndexes()[19].rewriteTable();
System.out.println("Packed old item definitions: "+result);
}
}
}

View file

@ -0,0 +1,114 @@
package com.alex.tools.clientCacheUpdater;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
import com.alex.store.Store;
import com.alex.utils.Constants;
import com.alex.utils.Utils;
public class CheckMap {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
/* OriginalXteas.init();
int count = 1;
Store cache = new Store("cache667_2/", false, CACHE_TABLE_KEYS);
Store mapsFrom = new Store("newCache/", false);
for(int regionId = 0; regionId < 30000; regionId++) {
int regionX = (regionId >> 8) * 64;
int regionY = (regionId & 0xff) * 64;
String name = "l"
+ ((regionX >> 3) / 8) + "_" + ((regionY >> 3) / 8);
int archiveId = cache.getIndexes()[5].getArchiveId(name);
if(archiveId != -1)
continue;
int archiveId2 = mapsFrom.getIndexes()[5].getArchiveId(name);
if(archiveId2 == -1)
continue;
boolean pass = passArchive(regionId, mapsFrom, cache, name, 5, null, OriginalXteas.getXteas(regionId));
if(pass) {
System.out.println("count: "+(count++)+", region: "+regionId);
}
//else
}
cache.getIndexes()[5].rewriteTable();
cache.getIndexes()[5].resetCachedFiles();*/
Store cache = new Store("cache667_2/", false, null);
double land = 0;
double map = 0;
for(int regionId = 0; regionId < 30000; regionId++) {
int regionX = (regionId >> 8) * 64;
int regionY = (regionId & 0xff) * 64;
String name1 = "l"
+ ((regionX >> 3) / 8) + "_" + ((regionY >> 3) / 8);
String name2 = "m"
+ ((regionX >> 3) / 8) + "_" + ((regionY >> 3) / 8);
if(cache.getIndexes()[5].getArchiveId(name1) != -1)
land ++;
if(cache.getIndexes()[5].getArchiveId(name2) != -1)
map ++;
}
System.out.println("land: "+land+", newMaps: "+map);
double perc = land * 100 / map ;
System.out.println( perc + "% complete!");
}
public static boolean passArchive(int regionId, Store store1, Store store2, String nameHash, int i, int[] keys1, int[] keys2) {
if(keys2 != null)
System.out.println(keys2);
int archiveId = store1.getIndexes()[i].getArchiveId(nameHash);
if(archiveId == -1)
return false;
int oldArchiveId = store2.getIndexes()[i].getArchiveId(nameHash);
if(oldArchiveId == -1)
oldArchiveId = store2.getIndexes()[i].getLastArchiveId()+1;
byte[] data = store1.getIndexes()[i].getFile(archiveId, 0, keys1);
if(data == null)
return false;
try {
boolean pass = store2.getIndexes()[i].putFile(oldArchiveId, 0, Constants.GZIP_COMPRESSION, data, keys2, false, false, Utils.getNameHash(nameHash), -1);
if(!pass)
return false;
int[] keys = writeKeys(regionId);
return store2.getIndexes()[i].encryptArchive(oldArchiveId, keys2, keys, false, false);
}catch(Error e) {
return false;
}catch(Exception e) {
e.printStackTrace();
return false;
}
}
public static int[] generateKeys() {
int[] keys = new int[4];
for (int index = 0; index < keys.length; index++)
keys[index] = new Random().nextInt();
return keys;
}
public static int[] writeKeys(int regionId) throws IOException {
BufferedWriter writer = new BufferedWriter(new FileWriter("cache667_protected/keys/"+regionId+".txt"));
int[] keys = generateKeys();
for (int index = 0; index < keys.length; index++) {
writer.write("" + keys[index]);
writer.newLine();
writer.flush();
}
System.out.println("Region: "+regionId+", "+Arrays.toString(keys));
return keys;
}
}

View file

@ -0,0 +1,27 @@
package com.alex.tools.clientCacheUpdater;
import java.io.IOException;
import com.alex.store.Index;
import com.alex.store.Store;
import com.alex.utils.Constants;
public class CopyCache {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
Store cache = new Store("./498/");
Store newCache = new Store("./498_out/");
for(int i = 0; i < cache.getIndexes().length; i++) {
Index index = cache.getIndexes()[i];
newCache.addIndex(index.getTable().isNamed(), index.getTable().usesWhirpool(), Constants.GZIP_COMPRESSION);
newCache.getIndexes()[i].packIndex(cache);
newCache.getIndexes()[i].getTable().setRevision(cache.getIndexes()[i].getTable().getRevision());
newCache.getIndexes()[i].rewriteTable();
}
}
}

View file

@ -0,0 +1,58 @@
package com.alex.tools.clientCacheUpdater;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
public final class OriginalXteas {
public final static HashMap<Integer, int[]> mapContainersXteas = new HashMap<Integer, int[]>();
public static final int[] getXteas(int regionId) {
return mapContainersXteas.get(regionId);
}
public static void init() {
loadUnpackedXteas();
}
public static final void delete() {
}
public static final void loadUnpackedXteas() {
try {
File unpacked = new File("cache667_protected/keys");
File[] xteasFiles = unpacked.listFiles();
for (File region : xteasFiles) {
String name = region.getName();
if (!name.contains(".txt")) {
region.delete();
continue;
}
int regionId = Short.parseShort(name.replace(".txt", ""));
if(regionId <= 0) {
region.delete();
continue;
}
BufferedReader in = new BufferedReader(new FileReader(region));
final int[] xteas = new int[4];
for (int index = 0; index < 4; index++) {
xteas[index] = Integer.parseInt(in.readLine());
}
mapContainersXteas.put(regionId, xteas);
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private OriginalXteas() {
}
}

View file

@ -0,0 +1,92 @@
package com.alex.tools.clientCacheUpdater;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
import com.alex.store.Index;
import com.alex.store.Store;
public class ProtectCache {
public static void main(String[] args) throws IOException {
boolean encryptMaps = true;
boolean encryptTables = false;
Store cache = new Store("718/cacheEncrypted/");
if(encryptMaps) {
Store rscache = new Store("718/rscache/");
Index index = cache.getIndexes()[5];
Index rsIndex = rscache.getIndexes()[5];
for(int regionId = 0; regionId < 25000; regionId++) {
int regionX = (regionId >> 8) * 64;
int regionY = (regionId & 0xff) * 64;
String name;
int[] keys = null;
name = "l"+ ((regionX >> 3) / 8) + "_" + ((regionY >> 3) / 8);
if(rsIndex.getFile(rsIndex.getArchiveId(name), 0) == null) {//not backgground file
int archiveId = index.getArchiveId(name);
if(archiveId != -1) {
keys = writeKeys(regionId);
if(!index.encryptArchive(archiveId, null, keys, false, false))
throw new RuntimeException("FAIL");
}
}
name = "ul"+ ((regionX >> 3) / 8) + "_" + ((regionY >> 3) / 8);
if(rsIndex.getFile(rsIndex.getArchiveId(name), 0) == null) {//not backgground file
int archiveId = index.getArchiveId(name);
if(archiveId != -1) {
if(keys == null)
keys = writeKeys(regionId);
if(!index.encryptArchive(archiveId, null, keys, false, false))
throw new RuntimeException("FAIL");
}
}
}
index.rewriteTable();
}
if(encryptTables) {
int[][] keys = new int[cache.getIndexes().length][];
for(int i = 0; i < keys.length; i++) {
keys[i] = generateKeys();
if(cache.getIndexes()[i] == null)
continue;
System.out.println("encrypting idx table: "+i);
cache.getIndexes()[i].setKeys(keys[i]);
cache.getIndexes()[i].rewriteTable();
}
for(int i = 0; i < keys.length; i++)
System.out.println(Arrays.toString(keys[i]));
}
}
public static int[] generateKeys() {
int[] keys = new int[4];
for (int index = 0; index < keys.length; index++)
keys[index] = new Random().nextInt();
return keys;
}
public static int[] writeKeys(int regionId) throws IOException {
BufferedWriter writer = new BufferedWriter(new FileWriter("718/maps/unpacked/"+regionId+".txt"));
int[] keys = generateKeys();
for (int index = 0; index < keys.length; index++) {
writer.write("" + keys[index]);
writer.newLine();
writer.flush();
}
System.out.println("Region: "+regionId+", "+Arrays.toString(keys));
return keys;
}
}

View file

@ -0,0 +1,67 @@
package com.alex.tools.clientCacheUpdater;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.HashMap;
public final class RSXteas {
public final static HashMap<Integer, int[]> mapContainersXteas = new HashMap<Integer, int[]>();
public static final int[] getXteas(int regionId) {
return mapContainersXteas.get(regionId);
}
public static void init() {
loadUnpackedXteas(468);
}
public static final void loadUnpackedXteas(int revision) {
try {
File unpacked = new File("xteas" + revision + "/");
File[] xteasFiles = unpacked.listFiles();
for (File region : xteasFiles) {
String name = region.getName();
if (!name.contains(".txt")) {
region.delete();
continue;
}
int regionId = -1;
try {
regionId = Short.parseShort(name.replace(".txt", ""));
} catch (Throwable t) {
continue;
}
if (regionId <= 0) {
region.delete();
continue;
}
BufferedReader in = new BufferedReader(new FileReader(region));
final int[] xteas = new int[4];
boolean delete = true;
for (int index = 0; index < 4; index++) {
xteas[index] = Integer.parseInt(in.readLine());
if (xteas[index] != 0) {
delete = false;
}
}
in.close();
if (delete) {
region.delete();
continue;
}
mapContainersXteas.put(regionId, xteas);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private RSXteas() {
}
}

View file

@ -0,0 +1,249 @@
package com.alex.tools.clientCacheUpdater;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import javax.swing.ImageIcon;
import com.alex.store.Index;
import com.alex.store.Store;
public class SpritesDumper {
/*public static void main(String[] args) throws IOException {
Store cache = new Store("cache667_2/", false);
ImagesFile file = new ImagesFile(cache, 498, 0);
file.replaceImage(ImageIO.read(new File("498_0_0.png")), 0);
cache.getIndexes()[8].putFile(2498, 0, file.encodeFile());
file = new ImagesFile(cache, 2498, 0);
for(int count = 0; count < file.getImages().length; count++) {
String name = ""+498+"_2_"+0+"_"+count;
BufferedImage image = file.getImages()[count];
if(image == null) {
System.out.println("NULL: "+name);
continue;
}
ImageIO.write(image, "png", new File(name+".png"));
System.out.println(name);
}
}*/
/*private static BufferedImage internalResize(BufferedImage source, int destWidth, int destHeight) {
int sourceWidth = source.getWidth();
int sourceHeight = source.getHeight();
double xScale = ((double) destWidth) / (double) sourceWidth;
double yScale = ((double) destHeight) / (double) sourceHeight;
Graphics2D g2d = null;
BufferedImage resizedImage = new BufferedImage(destWidth, destHeight, BufferedImage.TRANSLUCENT);
try {
g2d = resizedImage.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
AffineTransform at = AffineTransform.getScaleInstance(xScale, yScale);
g2d.drawRenderedImage(source, at);
} finally {
if (g2d != null)
g2d.dispose();
}
//doesn't keep the transparency
if (source.getType() == BufferedImage.TYPE_BYTE_INDEXED) {
BufferedImage indexedImage = new BufferedImage(destWidth, destHeight, BufferedImage.TYPE_BYTE_INDEXED);
try {
Graphics g = indexedImage.createGraphics();
g.drawImage(resizedImage, 0, 0, null);
} finally {
if (g != null)
g.dispose();
}
return indexedImage;
}
return resizedImage;
}*/
/*
* divides backgorund
*/
public static void main2(String[] args) throws IOException {
BufferedImage background = ImageIO.read(new File("bg/matrix.jpg"));
int id = 3769;
int sx = background.getWidth() / 2;
int sy = background.getHeight() / 2;
for(int y = 0; y < 2; y++) {
for(int x = 0; x < 2; x++) {
System.out.println("id "+id);
BufferedImage part = background.getSubimage(x * sx, y * sy, sx, sy);
ImageIO.write(part, "gif", new File("bg/"+(id++)+".gif"));
}
}
}
public static void main3(String[] args) throws IOException {
Store cache = new Store("cache667_2/", false);
UpdateCache.packLogo(cache);
System.out.println("Adding donator icon...");
UpdateCache.packDonatorIcon(cache);
System.out.println("Adding Matrix icon...");
UpdateCache.packMatrixIcon(cache);
/*for(int i = 0; i < 4; i++) {
int realid = 3769 + i;
int id = 3769 + i;
cache.getIndexes()[8].putFile(id, 0, new ImagesFile(ImageIO.read(new File("bg/"+realid+".gif"))).encodeFile());
id = 3779 + i;
cache.getIndexes()[8].putFile(id, 0, new ImagesFile(ImageIO.read(new File("bg/"+realid+".gif"))).encodeFile());
id = 3783 + (i >= 2 ? (i-2) : i + 2);
cache.getIndexes()[8].putFile(id, 0, new ImagesFile(ImageIO.read(new File("bg/"+realid+".gif"))).encodeFile());
id = 3769 + i;
cache.getIndexes()[34].putFile(id, 0, new ImagesFile(ImageIO.read(new File("bg/"+realid+".gif"))).encodeFile());
id = 3779 + i;
cache.getIndexes()[34].putFile(id, 0, new ImagesFile(ImageIO.read(new File("bg/"+realid+".gif"))).encodeFile());
id = 3783 + (i >= 2 ? (i-2) : i + 2);
cache.getIndexes()[34].putFile(id, 0, new ImagesFile(ImageIO.read(new File("bg/"+realid+".gif"))).encodeFile());
id = 3769 + i;
cache.getIndexes()[32].putFile(id, 0, getImage(new File("bg/"+realid+".png")));
id = 3779 + i;
cache.getIndexes()[32].putFile(id, 0, getImage(new File("bg/"+realid+".png")));
id = 3783 + (i >= 2 ? (i-2) : i + 2);
cache.getIndexes()[32].putFile(id, 0, getImage(new File("bg/"+realid+".png")));;
System.out.println("added file: "+i);
}*/
}
public static byte[] getImage(File file) throws IOException {
ImageOutputStream stream = ImageIO.createImageOutputStream(file);
byte[] data = new byte[(int) stream.length()];
stream.read(data);
return data;
}
public static void main(String[] args) throws IOException {
Store cache = new Store("718/rscache/");
Index sprites = cache.getIndexes()[32];
for(int archiveId : sprites.getTable().getValidArchiveIds()) {
for(int fileId : sprites.getTable().getArchives()[archiveId].getValidFileIds()) {
byte[] data = sprites.getFile(archiveId, fileId);
Image image = Toolkit.getDefaultToolkit().createImage(data);
String name = "sprites32/"+archiveId+"_"+fileId;
BufferedImage bi = toBufferedImage(image);
if(bi == null) {
System.out.println("failed "+name);
continue;
}
ImageIO.write(bi, "png", new File(name+".png"));
}
}
}
// This method returns a buffered image with the contents of an image
public static BufferedImage toBufferedImage(Image image) {
if (image instanceof BufferedImage) {
return (BufferedImage)image;
}
// This code ensures that all the pixels in the image are loaded
image = new ImageIcon(image).getImage();
// Determine if the image has transparent pixels; for this method's
// implementation, see Determining If an Image Has Transparent Pixels
boolean hasAlpha = true;//hasAlpha(image);
// Create a buffered image with a format that's compatible with the screen
BufferedImage bimage = null;
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
try {
// Determine the type of transparency of the new buffered image
int transparency = Transparency.OPAQUE;
if (hasAlpha) {
transparency = Transparency.BITMASK;
}
// Create the buffered image
GraphicsDevice gs = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gs.getDefaultConfiguration();
if(image.getWidth(null) < 0 || image.getHeight(null) < 0)
return null;
bimage = gc.createCompatibleImage(
image.getWidth(null), image.getHeight(null), transparency);
} catch (HeadlessException e) {
// The system does not have a screen
}
if (bimage == null) {
// Create a buffered image using the default color model
int type = BufferedImage.TYPE_INT_RGB;
if (hasAlpha) {
type = BufferedImage.TYPE_INT_ARGB;
}
bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
}
// Copy image to buffered image
Graphics g = bimage.createGraphics();
// Paint the image onto the buffered image
g.drawImage(image, 0, 0, null);
g.dispose();
return bimage;
}
/*public static void main(String[] args) throws IOException {
Store cache = new Store("cache667_2/", false);
Index sprites = cache.getIndexes()[34];
for(int archiveId : sprites.getTable().getValidArchiveIds()) {
for(int fileId : sprites.getTable().getArchives()[archiveId].getValidFileIds()) {
ImagesFile file = new ImagesFile(cache, 34, archiveId, fileId);
/*if(file.getImages() == null)
continue;*/
/* for(int count = 0; count < file.getImages().length; count++) {
String name = "sprites34/"+archiveId+"_"+fileId+"_"+count;
BufferedImage image = file.getImages()[count];
if(image == null) {
System.out.println("NULL: "+name);
continue;
}
ImageIO.write(image, "png", new File(name+".png"));
System.out.println(name);
}
}
}
}*/
}

View file

@ -0,0 +1,390 @@
package com.alex.tools.clientCacheUpdater;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
import com.alex.loaders.images.IndexedColorImageFile;
import com.alex.loaders.items.ItemDefinitions;
import com.alex.store.Index;
import com.alex.store.Store;
import com.alex.utils.Constants;
import com.alex.utils.Utils;
public class UpdateCache {
/* public static void main(String[] args) throws IOException {
Store rscache = new Store("cache697/");
Store cache = new Store("cache667_2/", false);
// System.out.println(rscache.getIndexes()[36].getTable().getValidArchiveIds().length);
for(int i = 0; i < rscache.getIndexes()[3].getLastArchiveId(); i++) {
if(i == 548 || i == 746)
continue;
cache.getIndexes()[3].putArchive(i, rscache, false, false);
}
cache.getIndexes()[3].rewriteTable();
//Interface inter = new Interface(746, rscache);
}*/
// Returns the contents of the file in a byte array.
public static byte[] getBytesFromFile(File file) throws IOException {
InputStream is = new FileInputStream(file);
// Get the size of the file
long length = file.length();
// You cannot create an array using a long type.
// It needs to be an int type.
// Before converting to an int type, check
// to ensure that file is not larger than Integer.MAX_VALUE.
if (length > Integer.MAX_VALUE) {
// File is too large
}
// Create the byte array to hold the data
byte[] bytes = new byte[(int)length];
// Read in the bytes
int offset = 0;
int numRead = 0;
while (offset < bytes.length
&& (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
offset += numRead;
}
// Ensure all the bytes have been read in
if (offset < bytes.length) {
throw new IOException("Could not completely read file "+file.getName());
}
// Close the input stream and return bytes
is.close();
return bytes;
}
public static void main6(String[] args) throws IOException {
Store cache = new Store("cache667_2/", false);
cache.getIndexes()[6].putFile(0, 0, getBytesFromFile(new File("0")));
}
public static void main5(String[] args) throws IOException {
Store rscache = new Store("cache697/");
Store cache = new Store("cache667_2/", false);
boolean result = false;
//settings
/*cache.getIndexes()[3].putArchive(261, rscache);
System.out.println("Packed skill interface: 261, "+result);*/
//skills
result = cache.getIndexes()[3].putArchive(320, rscache, false, false);
System.out.println("Packed skill interface: 320, "+result);
/* //equipment
result = cache.getIndexes()[3].putArchive(387, rscache, false, false);
System.out.println("Packed skill interface: 387, "+result);*/
//inventory
result = cache.getIndexes()[3].putArchive(679, rscache, false, false);
System.out.println("Packed skill interface: 679, "+result);
//attack style bar
// result = cache.getIndexes()[3].putArchive(884, rscache);
// System.out.println("Packed skill interface: 884, "+result);
cache.getIndexes()[3].rewriteTable();
}
/* public static void main(String[] args) throws IOException {
Store rscache = new Store("cache697/");
Store cache = new Store("cache667_2/", false);
cache.getIndexes()[17].packIndex(rscache);
}*/
public static void main555(String[] args) throws IOException {
Store cache = new Store("cache667_2/", false);
Store originalCache = new Store("rscache/", false);
cache.addIndex(false, false, Constants.GZIP_COMPRESSION);
for(int i : originalCache.getIndexes()[19].getTable().getValidArchiveIds()) {
System.out.println(i);
for(int i2 : originalCache.getIndexes()[19].getTable().getArchives()[i].getValidFileIds()) {
try {
cache.getIndexes()[37].putFile(i, i2, Constants.GZIP_COMPRESSION, originalCache.getIndexes()[19].getFile(i, i2), null, false, false, -1, -1);
}catch(Throwable e) {
e.printStackTrace();
}
}
}
cache.getIndexes()[37].rewriteTable();
//cache.getIndexes()[37].packIndex(19, originalCache, false);
/* System.out.println(ItemDefinitions.getItemDefinition(cache, 4708).maleEquipModelId1);
System.out.println(ItemDefinitions.getItemDefinition(cache, 4708).femaleEquipModelId1);
System.out.println(ItemDefinitions.getItemDefinition(cache, 4708).invModelId);*/
// Store originalCache = new Store("cache667/", false);
// cache.addIndex(cache.getIndexes()[7].getTable().isNamed(), cache.getIndexes()[7].getTable().usesWhirpool(), Constants.GZIP_COMPRESSION);
}
public static void main77(String[] args) throws IOException {
//Store mapcache = new Store("cache667_1/", false);
Store originalCache = new Store("cache667/", false);
Store cache = new Store("cache667_2/", false);
for(int i = 1610; i < 1616; i++)
cache.getIndexes()[17].putFile(i >>> 8, i & 0xff, originalCache.getIndexes()[17].getFile(i >>> 8, i & 0xff));
/* cache.getIndexes()[3].putArchive(320, rscache, false, false);
cache.getIndexes()[3].putArchive(667, rscache, false, false);
cache.getIndexes()[3].putArchive(751, rscache, false, false);
cache.getIndexes()[3].rewriteTable();*/
/*cache.resetIndex(5, true, mapcache.getIndexes()[5].getTable().usesWhirpool(), Constants.GZIP_COMPRESSION);
boolean result = cache.getIndexes()[5].packIndex(mapcache, false);*/
// cache.getIndexes()[8].packIndex(originalCache);
// System.out.println("Packed index archives: "+5+", "+result);
}
public static void packLogo(Store cache) throws IOException {
int id = 2498;
IndexedColorImageFile f = null;
try {
f = new IndexedColorImageFile(ImageIO.read(new File("bg/logo.png")));
} catch (IOException e) {
e.printStackTrace();
}
byte[] data = f.encodeFile();
cache.getIndexes()[8].putFile(id, 0, data);
//back background
for(int i = 4139; i <= 4146; i++) {
try {
cache.getIndexes()[8].putFile(i, 0, new IndexedColorImageFile(ImageIO.read(new File("bg/"+i+".gif"))).encodeFile());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for(int i = 0; i < 4; i++) {
int realid = 3769 + i;
id = 3769 + i;
cache.getIndexes()[8].putFile(id, 0, new IndexedColorImageFile(ImageIO.read(new File("bg/"+realid+".gif"))).encodeFile());
id = 3779 + i;
cache.getIndexes()[8].putFile(id, 0, new IndexedColorImageFile(ImageIO.read(new File("bg/"+realid+".gif"))).encodeFile());
id = 3783 + (i >= 2 ? (i-2) : i + 2);
cache.getIndexes()[8].putFile(id, 0, new IndexedColorImageFile(ImageIO.read(new File("bg/"+realid+".gif"))).encodeFile());
id = 3769 + i;
cache.getIndexes()[34].putFile(id, 0, new IndexedColorImageFile(ImageIO.read(new File("bg/"+realid+".gif"))).encodeFile());
id = 3779 + i;
cache.getIndexes()[34].putFile(id, 0, new IndexedColorImageFile(ImageIO.read(new File("bg/"+realid+".gif"))).encodeFile());
id = 3783 + (i >= 2 ? (i-2) : i + 2);
cache.getIndexes()[34].putFile(id, 0, new IndexedColorImageFile(ImageIO.read(new File("bg/"+realid+".gif"))).encodeFile());
id = 3769 + i;
cache.getIndexes()[32].putFile(id, 0, SpritesDumper.getImage(new File("bg/"+realid+".png")));
id = 3779 + i;
cache.getIndexes()[32].putFile(id, 0, SpritesDumper.getImage(new File("bg/"+realid+".png")));
id = 3783 + (i >= 2 ? (i-2) : i + 2);
cache.getIndexes()[32].putFile(id, 0, SpritesDumper.getImage(new File("bg/"+realid+".png")));;
System.out.println("added file: "+i);
}
}
public static void packDonatorIcon(Store cache) {
int id = 1455;
IndexedColorImageFile f = null;
try {
f = new IndexedColorImageFile(cache, id, 0);
BufferedImage icon = ImageIO.read(new File("1455.png"));
System.out.println("Added icon: "+f.addImage(icon)+".");
BufferedImage icon2 = ImageIO.read(new File("1455f.png"));
System.out.println("Added icon2: "+f.addImage(icon2)+".");
BufferedImage icon3 = ImageIO.read(new File("crown_green.gif"));
System.out.println("Added icon3: "+f.addImage(icon3)+".");
BufferedImage icon4 = ImageIO.read(new File("1455_11.png"));
System.out.println("Added icon4: "+f.addImage(icon4)+".");
} catch (IOException e) {
e.printStackTrace();
}
cache.getIndexes()[8].putFile(id, 0, f.encodeFile());
}
public static void packMatrixIcon(Store cache) {
int id = 2173;
IndexedColorImageFile f = null;
try {
f = new IndexedColorImageFile(ImageIO.read(new File("2173.png")));
} catch (IOException e) {
e.printStackTrace();
}
byte[] data = f.encodeFile();
cache.getIndexes()[8].putFile(id, 0, data);
}
public static int packCustomModel(Store cache, byte[] data) {
//recommended id 80000+ since rs uses all ids till 66000
int archiveId = cache.getIndexes()[7].getLastArchiveId()+1;
if(cache.getIndexes()[7].putFile(archiveId, 0, data))
return archiveId;
System.out.println("Failing packing model "+archiveId);
return -1;
}
public static void packCustomItems(Store cache) throws IOException {
int modelID = packCustomModel(cache, getBytesFromFile(new File("donatorCape.dat")));
System.out.println("model id "+modelID);
ItemDefinitions donatorCape = ItemDefinitions.getItemDefinition(cache, 9747);
donatorCape.setName("Donator cape");
//donatorCape.getInventoryOptions()[2] = "Customise";
donatorCape.femaleEquipModelId1 = modelID;
donatorCape.maleEquipModelId1 = modelID;
donatorCape.invModelId = modelID;
donatorCape.resetModelColors();
// donatorCape.changeModelColor();
int newId = 29999;
System.out.println(cache.getIndexes()[19].putFile(newId >>> 8, 0xff & newId, donatorCape.encode()));
}
public static void main(String[] args) throws IOException {
boolean updateJustMaps = false;
boolean addOldItems = true;
Store rscache = new Store("cache697/");
Store cache = new Store("cache667_2/", false);
Store originalCache = new Store("cache667/", false);
if(addOldItems)
cache.resetIndex(19, false, false, Constants.GZIP_COMPRESSION);
cache.resetIndex(7, false, false, Constants.GZIP_COMPRESSION);
cache.getIndexes()[7].packIndex(originalCache);
if(!updateJustMaps) {
for(int i = 0; i < cache.getIndexes().length; i++) {
if(i != 3 //interfaces
&& i != 5 //maps
&& i != 12 //client scripts
&& i != 33
&& i != 30) //native libs
{
boolean result = cache.getIndexes()[i].packIndex(rscache, true);
System.out.println("Packed index archives: "+i+", "+result);
}
}
System.out.println("Adding logo...");
packLogo(cache);
System.out.println("Adding donator icon...");
packDonatorIcon(cache);
System.out.println("Adding Matrix icon...");
packMatrixIcon(cache);
System.out.println("Adding Custom items...");
packCustomItems(cache);
if(addOldItems) {
System.out.println("Adding back old item definitions...");
int currentSize = 30000;//Utils.getItemDefinitionsSize(cache);
System.out.println(currentSize);
int oldSize = Utils.getItemDefinitionsSize(originalCache);
for(int i = currentSize ; i < currentSize+oldSize; i++) {
int newItemId = i;
int oldItemId = i - currentSize;
cache.getIndexes()[19].putFile(newItemId >>> 8, 0xff & newItemId, Constants.GZIP_COMPRESSION, originalCache.getIndexes()[19].getFile(oldItemId >>> 8, 0xff & oldItemId), null, false, false, -1, -1);
}
cache.getIndexes()[19].rewriteTable();
}
System.out.println("Recovering Client Script Maps...");
for(int i : originalCache.getIndexes()[17].getTable().getValidArchiveIds()) {
for(int i2 : originalCache.getIndexes()[17].getTable().getArchives()[i].getValidFileIds()) {
if(!cache.getIndexes()[17].fileExists(i, i2) || cache.getIndexes()[17].getFile(i, i2).length == 1) {
cache.getIndexes()[17].putFile(i, i2, originalCache.getIndexes()[17].getFile(i, i2));
}
}
}
System.out.println("Recovering Bank Client Script Maps...");
for(int i = 1610; i < 1616; i++)
cache.getIndexes()[17].putFile(i >>> 8, i & 0xff, originalCache.getIndexes()[17].getFile(i >>> 8, i & 0xff));
System.out.println("Adding new interfaces...");
//adds new interfaces
for(int i = cache.getIndexes()[3].getLastArchiveId()+1; i <= rscache.getIndexes()[3].getLastArchiveId(); i++) {
if(rscache.getIndexes()[3].archiveExists(i))
cache.getIndexes()[3].putArchive(i, rscache, false, false);
}
cache.getIndexes()[3].putArchive(320, rscache, false, false);
cache.getIndexes()[3].putArchive(751, rscache, false, false);
cache.getIndexes()[3].putArchive(1092, rscache, false, false);
boolean result = cache.getIndexes()[3].rewriteTable();
cache.getIndexes()[8].rewriteTable();
System.out.println("Packed new interfaces: "+result);
}
boolean result;
// int oldRevision = cache.getIndexes()[5].getTable().getRevision();
// cache.resetIndex(5, true, cache.getIndexes()[5].getTable().usesWhirpool(), Constants.GZIP_COMPRESSION);
Index index = cache.getIndexes()[5];
// index.getTable().setRevision(oldRevision+1);
Index rsIndex = rscache.getIndexes()[5];
Index originalIndex = originalCache.getIndexes()[5];
RSXteas.loadUnpackedXteas(679);
//OriginalXteas.loadUnpackedXteas();
System.out.println("Updating Maps.");
for(int regionId = 0; regionId < 30000; regionId++) {
int regionX = (regionId >> 8) * 64;
int regionY = (regionId & 0xff) * 64;
String name = "m"+ ((regionX >> 3) / 8) + "_" + ((regionY >> 3) / 8);
byte[] data = rsIndex.getFile(rsIndex.getArchiveId(name));
if(data == null)
data = originalIndex.getFile(originalIndex.getArchiveId(name));
if(data != null) {
result = addMapFile(index, name, data);
System.out.println(name+", "+result);
}
name = "um"+ ((regionX >> 3) / 8) + "_" + ((regionY >> 3) / 8);
data = rsIndex.getFile(rsIndex.getArchiveId(name));
if(data == null)
data = originalIndex.getFile(originalIndex.getArchiveId(name));
if(data != null) {
result = addMapFile(index, name, data);
System.out.println(name+", "+result);
}
int[] xteas = RSXteas.getXteas(regionId);
name = "l"+ ((regionX >> 3) / 8) + "_" + ((regionY >> 3) / 8);
data = rsIndex.getFile(rsIndex.getArchiveId(name), 0, xteas);
/*if(data == null)
data = originalIndex.getFile(originalIndex.getArchiveId(name), 0, OriginalXteas.getXteas(regionId));
*/if(data != null) {
result = addMapFile(index, name, data);
System.out.println(name+", "+result);
}
name = "ul"+ ((regionX >> 3) / 8) + "_" + ((regionY >> 3) / 8);
data = rsIndex.getFile(rsIndex.getArchiveId(name), 0, xteas);
/*if(data == null)
data = originalIndex.getFile(originalIndex.getArchiveId(name), 0, OriginalXteas.getXteas(regionId));
*/if(data != null) {
result = addMapFile(index, name, data);
System.out.println(name+", "+result);
}
name = "n"+ ((regionX >> 3) / 8) + "_" + ((regionY >> 3) / 8);
data = rsIndex.getFile(rsIndex.getArchiveId(name), 0);
if(data == null)
data = originalIndex.getFile(originalIndex.getArchiveId(name), 0);
if(data != null) {
result = addMapFile(index, name, data);
System.out.println(name+", "+result);
}
}
index.rewriteTable();
}
public static boolean addMapFile(Index index, String name, byte[] data) {
int archiveId = index.getArchiveId(name);
if(archiveId == -1)
archiveId = index.getTable().getValidArchiveIds().length;
return index.putFile(archiveId, 0, Constants.GZIP_COMPRESSION, data, null, false, false, Utils.getNameHash(name), -1);
}
}

View file

@ -0,0 +1,220 @@
package com.alex.tools.itemsDefsEditor;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.ListSelectionModel;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import com.alex.loaders.items.ItemDefinitions;
import com.alex.store.Store;
import com.alex.utils.Constants;
import com.alex.utils.Utils;
public class Application {
public static Store STORE;
private JFrame frmCacheEditorV;
/**
* Launch the application.
* @throws IOException
*/
public static void main(String[] args) throws IOException {
STORE = new Store("cache/", false);
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Application window = new Application();
window.frmCacheEditorV.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Application() {
initialize();
}
private void setLook() {
boolean found = false;
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if(info.getName().equals("Nimbus"))
try {
UIManager.setLookAndFeel(info.getClassName());
found = true;
}catch(Exception e) {
e.printStackTrace();
}
}
if(!found)
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(Exception e) {
e.printStackTrace();
}
}
private JList<ItemDefinitions> itemsList;
private DefaultListModel<ItemDefinitions> itemsListmodel;
/**
* Initialize the contents of the frame.
*/
private void initialize() {
setLook();
frmCacheEditorV = new JFrame();
frmCacheEditorV.setTitle("Cache Editor V0.1");
frmCacheEditorV.setBounds(100, 100, 352, 435);
frmCacheEditorV.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
frmCacheEditorV.getContentPane().add(tabbedPane, BorderLayout.CENTER);
JPanel panel = new JPanel();
tabbedPane.addTab("Main", null, panel, null);
panel.setLayout(null);
JButton btnGenerateUkeys = new JButton("Generate Ukeys (614- Client Builts)");
btnGenerateUkeys.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
byte[] ukeys = Utils.getArchivePacketData(255, 255, STORE.generateIndex255Archive255Outdated());
new GeneratedUkeys(getFrame(), ukeys);
}
});
btnGenerateUkeys.setBounds(33, 64, 257, 28);
panel.add(btnGenerateUkeys);
JLabel lblCreatedByAlexalso = new JLabel("Created By Alex(Also named Dragonkk)");
lblCreatedByAlexalso.setFont(new Font("Tekton Pro Ext", Font.PLAIN, 15));
lblCreatedByAlexalso.setBounds(6, 290, 322, 46);
panel.add(lblCreatedByAlexalso);
JPanel panel_1 = new JPanel();
tabbedPane.addTab("Items", null, panel_1, null);
panel_1.setLayout(null);
itemsListmodel = new DefaultListModel<ItemDefinitions>();
itemsList = new JList<ItemDefinitions>(itemsListmodel);
itemsList.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
itemsList.setLayoutOrientation(JList.VERTICAL);
itemsList.setVisibleRowCount(-1);
JScrollPane itemListscrollPane = new JScrollPane(itemsList);
itemListscrollPane.setBounds(34, 49, 155, 254);
panel_1.add(itemListscrollPane);
JButton btnEdit = new JButton("Edit");
final Application app = this;
btnEdit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ItemDefinitions defs = itemsList.getSelectedValue();
if(defs == null)
return;
new ItemDefsEditor(app, defs);
}
});
btnEdit.setBounds(201, 48, 90, 28);
panel_1.add(btnEdit);
JButton btnAdd = new JButton("Add");
btnAdd.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
new ItemDefsEditor(app, new ItemDefinitions(STORE, Utils.getItemDefinitionsSize(STORE) , false));
}
});
btnAdd.setBounds(201, 88, 90, 28);
panel_1.add(btnAdd);
JButton btnRemove = new JButton("Remove");
btnRemove.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ItemDefinitions defs = itemsList.getSelectedValue();
if(defs == null)
return;
STORE.getIndexes()[Constants.ITEM_DEFINITIONS_INDEX].removeFile(defs.getArchiveId(), defs.getFileId());
removeItemDefs(defs);
}
});
btnRemove.setBounds(201, 128, 90, 28);
panel_1.add(btnRemove);
JLabel label = new JLabel("Cached Items:");
label.setFont(new Font("Comic Sans MS", Font.PLAIN, 18));
label.setBounds(34, 18, 155, 21);
panel_1.add(label);
JButton btnDuplicate = new JButton("Clone");
btnDuplicate.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ItemDefinitions defs = itemsList.getSelectedValue();
if(defs == null)
return;
defs = (ItemDefinitions) defs.clone();
if(defs == null)
return;
defs.id = Utils.getItemDefinitionsSize(STORE);
new ItemDefsEditor(app, defs);
}
});
btnDuplicate.setBounds(201, 168, 90, 28);
panel_1.add(btnDuplicate);
addAllItems();
}
public void addAllItems() {
for(int id = 0; id < Utils.getItemDefinitionsSize(STORE) - 22314; id++) {
addItemDefs(ItemDefinitions.getItemDefinition(STORE, id));
}
}
public void addItemDefs(final ItemDefinitions defs) {
EventQueue.invokeLater(new Runnable() {
public void run() {
itemsListmodel.addElement(defs);
}
});
}
public void updateItemDefs(final ItemDefinitions defs) {
EventQueue.invokeLater(new Runnable() {
public void run() {
int index = itemsListmodel.indexOf(defs);
if(index == -1)
itemsListmodel.addElement(defs);
else
itemsListmodel.setElementAt(defs, index);
}
});
}
public void removeItemDefs(final ItemDefinitions defs) {
EventQueue.invokeLater(new Runnable() {
public void run() {
itemsListmodel.removeElement(defs);
}
});
}
public JFrame getFrame() {
return frmCacheEditorV;
}
}

View file

@ -0,0 +1,48 @@
package com.alex.tools.itemsDefsEditor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
@SuppressWarnings("serial")
public class GeneratedUkeys extends JDialog {
public GeneratedUkeys(JFrame frame, byte[] ukeys) {
super(frame, "Ukeys", true);
setBounds(100, 100, 450, 300);
getContentPane().setLayout(null);
final JEditorPane editorPane = new JEditorPane();
editorPane.setText(Arrays.toString(ukeys));
editorPane.setBounds(6, 6, 420, 213);
getContentPane().add(editorPane);
JButton btnClose = new JButton("Close");
btnClose.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dispose();
}
});
btnClose.setBounds(101, 221, 90, 28);
getContentPane().add(btnClose);
JButton btnCopy = new JButton("Copy");
btnCopy.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ActionEvent nev = new ActionEvent(editorPane, ActionEvent.ACTION_PERFORMED, "copy");
editorPane.selectAll();
editorPane.getActionMap().get(nev.getActionCommand()).actionPerformed(nev);
}
});
btnCopy.setBounds(6, 221, 90, 28);
getContentPane().add(btnCopy);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setVisible(true);
}
}

View file

@ -0,0 +1,404 @@
package com.alex.tools.itemsDefsEditor;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import com.alex.loaders.items.ItemDefinitions;
@SuppressWarnings("serial")
public class ItemDefsEditor extends JDialog {
private final JPanel contentPanel = new JPanel();
private ItemDefinitions defs;
private Application application;
private JTextField modelIDField;
private JTextField nameField;
private JTextField modelZoomField;
private JTextField groundOptionsField;
private JTextField inventoryOptionsField;
private JTextField femaleModelId2Field;
private JTextField maleModelId1Field;
private JTextField maleModelId2Field;
private JTextField maleModelId3Field;
private JTextField femaleModelId1Field;
private JTextField femaleModelId3Field;
private JTextField teamIdField;
private JTextField notedItemIdField;
private JTextField switchNotedItemField;
private JTextField lendedItemIdField;
private JTextField switchLendedItemField;
private JTextField changedModelColorsField;
private JTextField changedTextureColorsField;
private JCheckBox membersOnlyCheck;
public void save() {
//inv
defs.setInvModelId(Integer.valueOf(modelIDField.getText()));
defs.setName(nameField.getText());
defs.setInvModelZoom(Integer.valueOf(modelZoomField.getText()));
String[] groundOptions = groundOptionsField.getText().split(";");
for(int i = 0; i < defs.getGroundOptions().length; i++)
defs.getGroundOptions()[i] = groundOptions[i].equals("null") ? null : groundOptions[i];
String[] invOptions = inventoryOptionsField.getText().split(";");
for(int i = 0; i < defs.getInventoryOptions().length; i++)
defs.getInventoryOptions()[i] = invOptions[i].equals("null") ? null : invOptions[i];
//wearing
defs.maleEquipModelId1 = Integer.valueOf(maleModelId1Field.getText());
defs.maleEquipModelId2 = Integer.valueOf(maleModelId2Field.getText());
defs.maleEquipModelId3 = Integer.valueOf(maleModelId3Field.getText());
defs.femaleEquipModelId1 = Integer.valueOf(femaleModelId1Field.getText());
defs.femaleEquipModelId2 = Integer.valueOf(femaleModelId2Field.getText());
defs.femaleEquipModelId3 = Integer.valueOf(femaleModelId3Field.getText());
defs.teamId = Integer.valueOf(teamIdField.getText());
//others
defs.notedItemId = Integer.valueOf(notedItemIdField.getText());
defs.switchNoteItemId = Integer.valueOf(switchNotedItemField.getText());
defs.lendedItemId = Integer.valueOf(lendedItemIdField.getText());
defs.switchLendItemId = Integer.valueOf(switchLendedItemField.getText());
defs.resetModelColors();
if(!changedModelColorsField.getText().equals("")) {
String[] splitedModelColorsTexts = changedModelColorsField.getText().split(";");
for(String t : splitedModelColorsTexts) {
String[] editedColor = t.split("=");
defs.changeModelColor(Integer.valueOf(editedColor[0]), Integer.valueOf(editedColor[1]));
}
}
defs.resetTextureColors();
if(!changedTextureColorsField.getText().equals("")) {
String[] splitedTextureColorsTexts = changedTextureColorsField.getText().split(";");
for(String t : splitedTextureColorsTexts) {
String[] editedColor = t.split("=");
defs.changeTextureColor(Integer.valueOf(editedColor[0]), Integer.valueOf(editedColor[1]));
}
}
defs.membersOnly = membersOnlyCheck.isSelected();
defs.write(Application.STORE);
application.updateItemDefs(defs);
}
/**
* Create the dialog.
*/
public ItemDefsEditor(Application application, ItemDefinitions defs) {
super(application.getFrame(), "Item Definitions Editor", true);
this.defs = defs;
this.application = application;
setBounds(100, 100, 912, 354);
getContentPane().setLayout(new BorderLayout());
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
getContentPane().add(contentPanel, BorderLayout.CENTER);
contentPanel.setLayout(null);
JLabel lblNewLabel = new JLabel("Model ID:");
lblNewLabel.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
lblNewLabel.setBounds(6, 43, 81, 21);
contentPanel.add(lblNewLabel);
{
modelIDField = new JTextField();
modelIDField.setBounds(139, 40, 122, 28);
contentPanel.add(modelIDField);
modelIDField.setColumns(10);
modelIDField.setText(""+defs.getInvModelId());
}
{
JLabel label = new JLabel("Name:");
label.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
label.setBounds(6, 76, 81, 21);
contentPanel.add(label);
}
{
nameField = new JTextField();
nameField.setBounds(139, 73, 122, 28);
contentPanel.add(nameField);
nameField.setColumns(10);
nameField.setText(defs.getName());
}
{
JLabel label = new JLabel("Model Zoom:");
label.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
label.setBounds(6, 109, 95, 21);
contentPanel.add(label);
}
{
modelZoomField = new JTextField();
modelZoomField.setBounds(139, 106, 122, 28);
contentPanel.add(modelZoomField);
modelZoomField.setColumns(10);
modelZoomField.setText(""+defs.getInvModelZoom());
}
{
JLabel label = new JLabel("Ground Options:");
label.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
label.setBounds(6, 142, 108, 21);
contentPanel.add(label);
}
{
groundOptionsField = new JTextField();
groundOptionsField.setBounds(139, 139, 122, 28);
contentPanel.add(groundOptionsField);
groundOptionsField.setColumns(10);
String text = "";
for(String option : defs.getGroundOptions())
text += (option == null ? "null" : option)+";";
groundOptionsField.setText(text);
}
{
JLabel label = new JLabel("Inventory Options:");
label.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
label.setBounds(6, 175, 139, 21);
contentPanel.add(label);
}
{
inventoryOptionsField = new JTextField();
inventoryOptionsField.setBounds(139, 172, 122, 28);
contentPanel.add(inventoryOptionsField);
inventoryOptionsField.setColumns(10);
String text = "";
for(String option : defs.getInventoryOptions())
text += (option == null ? "null" : option)+";";
inventoryOptionsField.setText(text);
}
{
JButton saveButton = new JButton("Save");
saveButton.setBounds(6, 265, 55, 28);
contentPanel.add(saveButton);
saveButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
save();
dispose();
}
});
getRootPane().setDefaultButton(saveButton);
}
{
JButton cancelButton = new JButton("Cancel");
cancelButton.setBounds(73, 265, 67, 28);
contentPanel.add(cancelButton);
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dispose();
}
});
cancelButton.setActionCommand("Cancel");
}
JLabel label = new JLabel("Interface / Droped");
label.setFont(new Font("Comic Sans MS", Font.PLAIN, 18));
label.setBounds(6, 6, 205, 21);
contentPanel.add(label);
JLabel label_1 = new JLabel("Wearing");
label_1.setFont(new Font("Comic Sans MS", Font.PLAIN, 18));
label_1.setBounds(273, 6, 205, 21);
contentPanel.add(label_1);
JLabel label_2 = new JLabel("Male Model ID 1:");
label_2.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
label_2.setBounds(273, 43, 131, 21);
contentPanel.add(label_2);
JLabel label_3 = new JLabel("Male Model ID 2:");
label_3.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
label_3.setBounds(273, 76, 131, 21);
contentPanel.add(label_3);
JLabel label_4 = new JLabel("Male Model ID 3:");
label_4.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
label_4.setBounds(273, 112, 131, 21);
contentPanel.add(label_4);
JLabel label_5 = new JLabel("Female Model ID 1:");
label_5.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
label_5.setBounds(273, 145, 131, 21);
contentPanel.add(label_5);
JLabel label_6 = new JLabel("Female Model ID 2:");
label_6.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
label_6.setBounds(273, 175, 131, 21);
contentPanel.add(label_6);
JLabel label_7 = new JLabel("Female Model ID 3:");
label_7.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
label_7.setBounds(273, 208, 131, 21);
contentPanel.add(label_7);
femaleModelId2Field = new JTextField();
femaleModelId2Field.setBounds(411, 172, 122, 28);
contentPanel.add(femaleModelId2Field);
femaleModelId2Field.setColumns(10);
femaleModelId2Field.setText(""+defs.femaleEquipModelId2);
maleModelId1Field = new JTextField();
maleModelId1Field.setBounds(411, 40, 122, 28);
contentPanel.add(maleModelId1Field);
maleModelId1Field.setColumns(10);
maleModelId1Field.setText(""+defs.maleEquipModelId1);
{
maleModelId2Field = new JTextField();
maleModelId2Field.setBounds(411, 73, 122, 28);
contentPanel.add(maleModelId2Field);
maleModelId2Field.setColumns(10);
maleModelId2Field.setText(""+defs.maleEquipModelId2);
}
{
maleModelId3Field = new JTextField();
maleModelId3Field.setBounds(411, 106, 122, 28);
contentPanel.add(maleModelId3Field);
maleModelId3Field.setColumns(10);
maleModelId3Field.setText(""+defs.maleEquipModelId3);
}
{
femaleModelId1Field = new JTextField();
femaleModelId1Field.setBounds(411, 139, 122, 28);
contentPanel.add(femaleModelId1Field);
femaleModelId1Field.setColumns(10);
femaleModelId1Field.setText(""+defs.femaleEquipModelId1);
}
{
femaleModelId3Field = new JTextField();
femaleModelId3Field.setBounds(411, 205, 122, 28);
contentPanel.add(femaleModelId3Field);
femaleModelId3Field.setColumns(10);
femaleModelId3Field.setText(""+defs.femaleEquipModelId3);
}
{
JLabel label_8 = new JLabel("Team ID:");
label_8.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
label_8.setBounds(273, 241, 131, 21);
contentPanel.add(label_8);
}
{
teamIdField = new JTextField();
teamIdField.setBounds(411, 238, 122, 28);
contentPanel.add(teamIdField);
teamIdField.setColumns(10);
teamIdField.setText(""+defs.teamId);
}
{
JLabel label_8 = new JLabel("Others");
label_8.setFont(new Font("Comic Sans MS", Font.PLAIN, 18));
label_8.setBounds(539, 6, 205, 21);
contentPanel.add(label_8);
}
{
JLabel label_8 = new JLabel("Noted Item ID:");
label_8.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
label_8.setBounds(545, 43, 131, 21);
contentPanel.add(label_8);
}
{
JLabel label_8 = new JLabel("Switch Noted Item Id:");
label_8.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
label_8.setBounds(545, 76, 160, 21);
contentPanel.add(label_8);
}
{
JLabel label_8 = new JLabel("Lended Item ID:");
label_8.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
label_8.setBounds(545, 109, 160, 21);
contentPanel.add(label_8);
}
{
JLabel label_8 = new JLabel("Switch Lended Item Id:");
label_8.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
label_8.setBounds(545, 145, 160, 21);
contentPanel.add(label_8);
}
{
notedItemIdField = new JTextField();
notedItemIdField.setBounds(707, 39, 122, 28);
contentPanel.add(notedItemIdField);
notedItemIdField.setColumns(10);
notedItemIdField.setText(""+defs.notedItemId);
}
{
switchNotedItemField = new JTextField();
switchNotedItemField.setBounds(707, 73, 122, 28);
contentPanel.add(switchNotedItemField);
switchNotedItemField.setColumns(10);
switchNotedItemField.setText(""+defs.switchNoteItemId);
}
{
lendedItemIdField = new JTextField();
lendedItemIdField.setBounds(707, 106, 122, 28);
contentPanel.add(lendedItemIdField);
lendedItemIdField.setColumns(10);
lendedItemIdField.setText(""+defs.lendedItemId);
}
{
switchLendedItemField = new JTextField();
switchLendedItemField.setBounds(707, 139, 122, 28);
contentPanel.add(switchLendedItemField);
switchLendedItemField.setColumns(10);
switchLendedItemField.setText(""+defs.switchLendItemId);
}
{
JLabel label_8 = new JLabel("Changed Model Colors:");
label_8.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
label_8.setBounds(545, 175, 160, 21);
contentPanel.add(label_8);
}
{
changedModelColorsField = new JTextField();
changedModelColorsField.setBounds(707, 172, 122, 28);
contentPanel.add(changedModelColorsField);
changedModelColorsField.setColumns(10);
String text = "";
if(defs.originalModelColors != null) {
for(int i = 0; i < defs.originalModelColors.length; i++) {
text += defs.originalModelColors[i]+"="+defs.modifiedModelColors[i]+";";
}
}
changedModelColorsField.setText(text);
}
{
JLabel label_8 = new JLabel("Changed Texture Colors:");
label_8.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
label_8.setBounds(545, 205, 160, 21);
contentPanel.add(label_8);
}
{
changedTextureColorsField = new JTextField();
changedTextureColorsField.setBounds(707, 205, 122, 28);
contentPanel.add(changedTextureColorsField);
changedTextureColorsField.setColumns(10);
String text = "";
if(defs.originalTextureColors != null) {
for(int i = 0; i < defs.originalTextureColors.length; i++) {
text += defs.originalTextureColors[i]+"="+defs.modifiedTextureColors[i]+";";
}
}
changedTextureColorsField.setText(text);
}
membersOnlyCheck = new JCheckBox("Members Only");
membersOnlyCheck.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
membersOnlyCheck.setBounds(545, 243, 131, 18);
membersOnlyCheck.setSelected(defs.membersOnly);
contentPanel.add(membersOnlyCheck);
{
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
getContentPane().add(buttonPane, BorderLayout.SOUTH);
}
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setVisible(true);
}
}

View file

@ -0,0 +1,56 @@
package com.alex.util.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];
}
}

View file

@ -0,0 +1,22 @@
package com.alex.util.bzip2;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.apache.tools.bzip2.CBZip2OutputStream;
public class BZip2Compressor {
public static final byte[] compress(byte[] data) {
ByteArrayOutputStream compressedBytes = new ByteArrayOutputStream();
try {
CBZip2OutputStream out = new CBZip2OutputStream(compressedBytes);
out.write(data);
out.close();
return compressedBytes.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}

View file

@ -0,0 +1,546 @@
package com.alex.util.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);
if (j1 == 0) {
i = 1;
break;
}
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 entry) {
return (byte) method1790(8, entry);
}
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 entry) {
// 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;
entry.anInt2202 = 1;
if (anIntArray257 == null) {
anIntArray257 = new int[entry.anInt2202 * 0x186a0];
}
boolean flag18 = true;
while (flag18) {
byte byte0 = method1789(entry);
if (byte0 == 23) {
return;
}
byte0 = method1789(entry);
byte0 = method1789(entry);
byte0 = method1789(entry);
byte0 = method1789(entry);
byte0 = method1789(entry);
byte0 = method1789(entry);
byte0 = method1789(entry);
byte0 = method1789(entry);
byte0 = method1789(entry);
byte0 = method1788(entry);
entry.anInt2223 = 0;
byte0 = method1789(entry);
entry.anInt2223 = entry.anInt2223 << 8 | byte0 & 0xff;
byte0 = method1789(entry);
entry.anInt2223 = entry.anInt2223 << 8 | byte0 & 0xff;
byte0 = method1789(entry);
entry.anInt2223 = entry.anInt2223 << 8 | byte0 & 0xff;
for (int j = 0; j < 16; j++) {
byte byte1 = method1788(entry);
if (byte1 == 1) {
entry.aBooleanArray2205[j] = true;
} else {
entry.aBooleanArray2205[j] = false;
}
}
for (int k = 0; k < 256; k++) {
entry.aBooleanArray2213[k] = false;
}
for (int l = 0; l < 16; l++) {
if (entry.aBooleanArray2205[l]) {
for (int i3 = 0; i3 < 16; i3++) {
byte byte2 = method1788(entry);
if (byte2 == 1) {
entry.aBooleanArray2213[l * 16 + i3] = true;
}
}
}
}
method1785(entry);
int i4 = entry.anInt2215 + 2;
int j4 = method1790(3, entry);
int k4 = method1790(15, entry);
for (int i1 = 0; i1 < k4; i1++) {
int j3 = 0;
do {
byte byte3 = method1788(entry);
if (byte3 == 0) {
break;
}
j3++;
} while (true);
entry.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 = entry.aByteArray2214[j1];
byte byte15 = abyte0[byte17];
for (; byte17 > 0; byte17--) {
abyte0[byte17] = abyte0[byte17 - 1];
}
abyte0[0] = byte15;
entry.aByteArray2219[j1] = byte15;
}
for (int k3 = 0; k3 < j4; k3++) {
int k6 = method1790(5, entry);
for (int k1 = 0; k1 < i4; k1++) {
do {
byte byte4 = method1788(entry);
if (byte4 == 0) {
break;
}
byte4 = method1788(entry);
if (byte4 == 0) {
k6++;
} else {
k6--;
}
} while (true);
entry.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 (entry.aByteArrayArray2229[l3][l1] > i) {
i = entry.aByteArrayArray2229[l3][l1];
}
if (entry.aByteArrayArray2229[l3][l1] < byte8) {
byte8 = entry.aByteArrayArray2229[l3][l1];
}
}
method1786(entry.anIntArrayArray2230[l3],
entry.anIntArrayArray2218[l3],
entry.anIntArrayArray2210[l3],
entry.aByteArrayArray2229[l3], byte8, i, i4);
entry.anIntArray2200[l3] = byte8;
}
int l4 = entry.anInt2215 + 1;
int i5 = -1;
int j5 = 0;
for (int i2 = 0; i2 <= 255; i2++) {
entry.anIntArray2228[i2] = 0;
}
int i9 = 4095;
for (int k8 = 15; k8 >= 0; k8--) {
for (int l8 = 15; l8 >= 0; l8--) {
entry.aByteArray2204[i9] = (byte) (k8 * 16 + l8);
i9--;
}
entry.anIntArray2226[k8] = i9 + 1;
}
int l5 = 0;
if (j5 == 0) {
i5++;
j5 = 50;
byte byte12 = entry.aByteArray2219[i5];
j8 = entry.anIntArray2200[byte12];
ai = entry.anIntArrayArray2230[byte12];
ai2 = entry.anIntArrayArray2210[byte12];
ai1 = entry.anIntArrayArray2218[byte12];
}
j5--;
int l6 = j8;
int k7;
byte byte9;
for (k7 = method1790(l6, entry); k7 > ai[l6]; k7 = k7 << 1 | byte9) {
l6++;
byte9 = method1788(entry);
}
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 = entry.aByteArray2219[i5];
j8 = entry.anIntArray2200[byte13];
ai = entry.anIntArrayArray2230[byte13];
ai2 = entry.anIntArrayArray2210[byte13];
ai1 = entry.anIntArrayArray2218[byte13];
}
j5--;
int i7 = j8;
int l7;
byte byte10;
for (l7 = method1790(i7, entry); l7 > ai[i7]; l7 = l7 << 1
| byte10) {
i7++;
byte10 = method1788(entry);
}
k5 = ai2[l7 - ai1[i7]];
} while (k5 == 0 || k5 == 1);
i6++;
byte byte5 = entry.aByteArray2211[entry.aByteArray2204[entry.anIntArray2226[0]] & 0xff];
entry.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 = entry.anIntArray2226[0];
byte6 = entry.aByteArray2204[i10 + i11];
for (; i11 > 3; i11 -= 4) {
int j11 = i10 + i11;
entry.aByteArray2204[j11] = entry.aByteArray2204[j11 - 1];
entry.aByteArray2204[j11 - 1] = entry.aByteArray2204[j11 - 2];
entry.aByteArray2204[j11 - 2] = entry.aByteArray2204[j11 - 3];
entry.aByteArray2204[j11 - 3] = entry.aByteArray2204[j11 - 4];
}
for (; i11 > 0; i11--) {
entry.aByteArray2204[i10 + i11] = entry.aByteArray2204[(i10 + i11) - 1];
}
entry.aByteArray2204[i10] = byte6;
} else {
int k10 = i11 / 16;
int l10 = i11 % 16;
int j10 = entry.anIntArray2226[k10] + l10;
byte6 = entry.aByteArray2204[j10];
for (; j10 > entry.anIntArray2226[k10]; j10--) {
entry.aByteArray2204[j10] = entry.aByteArray2204[j10 - 1];
}
entry.anIntArray2226[k10]++;
for (; k10 > 0; k10--) {
entry.anIntArray2226[k10]--;
entry.aByteArray2204[entry.anIntArray2226[k10]] = entry.aByteArray2204[(entry.anIntArray2226[k10 - 1] + 16) - 1];
}
entry.anIntArray2226[0]--;
entry.aByteArray2204[entry.anIntArray2226[0]] = byte6;
if (entry.anIntArray2226[0] == 0) {
int l9 = 4095;
for (int j9 = 15; j9 >= 0; j9--) {
for (int k9 = 15; k9 >= 0; k9--) {
entry.aByteArray2204[l9] = entry.aByteArray2204[entry.anIntArray2226[j9]
+ k9];
l9--;
}
entry.anIntArray2226[j9] = l9 + 1;
}
}
}
entry.anIntArray2228[entry.aByteArray2211[byte6 & 0xff] & 0xff]++;
anIntArray257[l5] = entry.aByteArray2211[byte6 & 0xff] & 0xff;
l5++;
if (j5 == 0) {
i5++;
j5 = 50;
byte byte14 = entry.aByteArray2219[i5];
j8 = entry.anIntArray2200[byte14];
ai = entry.anIntArrayArray2230[byte14];
ai2 = entry.anIntArrayArray2210[byte14];
ai1 = entry.anIntArrayArray2218[byte14];
}
j5--;
int j7 = j8;
int i8;
byte byte11;
for (i8 = method1790(j7, entry); i8 > ai[j7]; i8 = i8 << 1
| byte11) {
j7++;
byte11 = method1788(entry);
}
k5 = ai2[i8 - ai1[j7]];
}
}
entry.anInt2222 = 0;
entry.aByte2201 = 0;
entry.anIntArray2220[0] = 0;
for (int j2 = 1; j2 <= 256; j2++) {
entry.anIntArray2220[j2] = entry.anIntArray2228[j2 - 1];
}
for (int k2 = 1; k2 <= 256; k2++) {
entry.anIntArray2220[k2] += entry.anIntArray2220[k2 - 1];
}
for (int l2 = 0; l2 < l5; l2++) {
byte byte7 = (byte) (anIntArray257[l2] & 0xff);
anIntArray257[entry.anIntArray2220[byte7 & 0xff]] |= l2 << 8;
entry.anIntArray2220[byte7 & 0xff]++;
}
entry.anInt2208 = anIntArray257[entry.anInt2223] >> 8;
entry.anInt2227 = 0;
entry.anInt2208 = anIntArray257[entry.anInt2208];
entry.anInt2221 = (byte) (entry.anInt2208 & 0xff);
entry.anInt2208 >>= 8;
entry.anInt2227++;
entry.anInt2225 = l5;
method1787(entry);
if (entry.anInt2227 == entry.anInt2225 + 1 && entry.anInt2222 == 0) {
flag18 = true;
} else {
flag18 = false;
}
}
}
}

View file

@ -0,0 +1,26 @@
package com.alex.util.crc32;
import java.util.zip.CRC32;
public final class CRC32HGenerator {
public static final CRC32 CRC32Instance = new CRC32();
public static int getHash(byte[] data) {
return getHash(data, 0, data.length);
}
public static int getHash(byte[] data, int offset, int length) {
synchronized(CRC32Instance) {
CRC32Instance.update(data, offset, length);
int hash = (int) CRC32Instance.getValue();
CRC32Instance.reset();
return hash;
}
}
private CRC32HGenerator() {
}
}

View file

@ -0,0 +1,22 @@
package com.alex.util.gzip;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;
public class GZipCompressor {
public static final byte[] compress(byte[] data) {
ByteArrayOutputStream compressedBytes = new ByteArrayOutputStream();
try {
GZIPOutputStream out = new GZIPOutputStream(compressedBytes);
out.write(data);
out.finish();
out.close();
return compressedBytes.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}

View file

@ -0,0 +1,48 @@
package com.alex.util.gzip;
import java.util.zip.Inflater;
import com.alex.io.Stream;
public class GZipDecompressor {
private static final Inflater inflaterInstance = new Inflater(true);
public static final boolean decompress(Stream stream, byte data[]) {
synchronized(inflaterInstance) {
if (stream.getBuffer()[stream.getOffset()] != 31 || stream.getBuffer()[stream.getOffset() + 1] != -117)
return false;
//throw new RuntimeException("Invalid GZIP header!");
try {
inflaterInstance.setInput(stream.getBuffer(), stream.getOffset() + 10, -stream.getOffset() - 18 + stream.getBuffer().length);
inflaterInstance.inflate(data);
} catch (Exception e) {
inflaterInstance.reset();
return false;
//throw new RuntimeException("Invalid GZIP compressed data!");
}
inflaterInstance.reset();
return true;
}
}
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;
}
}
}

View file

@ -0,0 +1,415 @@
package com.alex.util.whirlpool;
import java.util.Arrays;
/**
* The Whirlpool hashing function.
*
* <P>
* <b>References</b>
*
* <P>
* The Whirlpool algorithm was developed by
* <a href="mailto:pbarreto@scopus.com.br">Paulo S. L. M. Barreto</a> and
* <a href="mailto:vincent.rijmen@cryptomathic.com">Vincent Rijmen</a>.
*
* See
* P.S.L.M. Barreto, V. Rijmen,
* ``The Whirlpool hashing function,''
* First NESSIE workshop, 2000 (tweaked version, 2003),
* <https://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/whirlpool.zip>
*
* @author Paulo S.L.M. Barreto
* @author Vincent Rijmen.
*
* @version 3.0 (2003.03.12)
*
* =============================================================================
*
* Differences from version 2.1:
*
* - Suboptimal diffusion matrix replaced by cir(1, 1, 4, 1, 8, 5, 2, 9).
*
* =============================================================================
*
* Differences from version 2.0:
*
* - Generation of ISO/IEC 10118-3 test vectors.
* - Bug fix: nonzero carry was ignored when tallying the data length
* (this bug apparently only manifested itself when feeding data
* in pieces rather than in a single chunk at once).
*
* Differences from version 1.0:
*
* - Original S-box replaced by the tweaked, hardware-efficient version.
*
* =============================================================================
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
public class Whirlpool {
/**
* The message digest size (in bits)
*/
public static final int DIGESTBITS = 512;
/**
* The message digest size (in bytes)
*/
public static final int DIGESTBYTES = DIGESTBITS >>> 3;
/**
* The number of rounds of the internal dedicated block cipher.
*/
protected static final int R = 10;
/**
* The substitution box.
*/
private static final String sbox =
"\u1823\uc6E8\u87B8\u014F\u36A6\ud2F5\u796F\u9152" +
"\u60Bc\u9B8E\uA30c\u7B35\u1dE0\ud7c2\u2E4B\uFE57" +
"\u1577\u37E5\u9FF0\u4AdA\u58c9\u290A\uB1A0\u6B85" +
"\uBd5d\u10F4\ucB3E\u0567\uE427\u418B\uA77d\u95d8" +
"\uFBEE\u7c66\udd17\u479E\ucA2d\uBF07\uAd5A\u8333" +
"\u6302\uAA71\uc819\u49d9\uF2E3\u5B88\u9A26\u32B0" +
"\uE90F\ud580\uBEcd\u3448\uFF7A\u905F\u2068\u1AAE" +
"\uB454\u9322\u64F1\u7312\u4008\uc3Ec\udBA1\u8d3d" +
"\u9700\ucF2B\u7682\ud61B\uB5AF\u6A50\u45F3\u30EF" +
"\u3F55\uA2EA\u65BA\u2Fc0\udE1c\uFd4d\u9275\u068A" +
"\uB2E6\u0E1F\u62d4\uA896\uF9c5\u2559\u8472\u394c" +
"\u5E78\u388c\ud1A5\uE261\uB321\u9c1E\u43c7\uFc04" +
"\u5199\u6d0d\uFAdF\u7E24\u3BAB\ucE11\u8F4E\uB7EB" +
"\u3c81\u94F7\uB913\u2cd3\uE76E\uc403\u5644\u7FA9" +
"\u2ABB\uc153\udc0B\u9d6c\u3174\uF646\uAc89\u14E1" +
"\u163A\u6909\u70B6\ud0Ed\ucc42\u98A4\u285c\uF886";
private static long[][] C = new long[8][256];
private static long[] rc = new long[R + 1];
static {
for (int x = 0; x < 256; x++) {
char c = sbox.charAt(x/2);
long v1 = ((x & 1) == 0) ? c >>> 8 : c & 0xff;
long v2 = v1 << 1;
if (v2 >= 0x100L) {
v2 ^= 0x11dL;
}
long v4 = v2 << 1;
if (v4 >= 0x100L) {
v4 ^= 0x11dL;
}
long v5 = v4 ^ v1;
long v8 = v4 << 1;
if (v8 >= 0x100L) {
v8 ^= 0x11dL;
}
long v9 = v8 ^ v1;
/*
* build the circulant table C[0][x] = S[x].[1, 1, 4, 1, 8, 5, 2, 9]:
*/
C[0][x] =
(v1 << 56) | (v1 << 48) | (v4 << 40) | (v1 << 32) |
(v8 << 24) | (v5 << 16) | (v2 << 8) | (v9 );
/*
* build the remaining circulant tables C[t][x] = C[0][x] rotr t
*/
for (int t = 1; t < 8; t++) {
C[t][x] = (C[t - 1][x] >>> 8) | ((C[t - 1][x] << 56));
}
}
/*
* build the round constants:
*/
rc[0] = 0L; /* not used (assigment kept only to properly initialize all variables) */
for (int r = 1; r <= R; r++) {
int i = 8*(r - 1);
rc[r] =
(C[0][i ] & 0xff00000000000000L) ^
(C[1][i + 1] & 0x00ff000000000000L) ^
(C[2][i + 2] & 0x0000ff0000000000L) ^
(C[3][i + 3] & 0x000000ff00000000L) ^
(C[4][i + 4] & 0x00000000ff000000L) ^
(C[5][i + 5] & 0x0000000000ff0000L) ^
(C[6][i + 6] & 0x000000000000ff00L) ^
(C[7][i + 7] & 0x00000000000000ffL);
}
}
public static byte[] getHash(byte[] data, int off, int len) {
byte source[];
if(off <= 0) {
source = data;
} else {
source = new byte[len];
for(int i = 0; i < len; i++)
source[i] = data[off + i];
}
Whirlpool whirlpool = new Whirlpool();
whirlpool.NESSIEinit();
whirlpool.NESSIEadd(source, len * 8);
byte digest[] = new byte[64];
whirlpool.NESSIEfinalize(digest);
return digest;
}
/**
* Global number of hashed bits (256-bit counter).
*/
protected byte[] bitLength = new byte[32];
/**
* Buffer of data to hash.
*/
protected byte[] buffer = new byte[64];
/**
* Current number of bits on the buffer.
*/
protected int bufferBits = 0;
/**
* Current (possibly incomplete) byte slot on the buffer.
*/
protected int bufferPos = 0;
/**
* The hashing state.
*/
protected long[] hash = new long[8];
protected long[] K = new long[8]; // the round key
protected long[] L = new long[8];
protected long[] block = new long[8]; // mu(buffer)
protected long[] state = new long[8]; // the cipher state
public Whirlpool() {
}
/**
* The core Whirlpool transform.
*/
protected void processBuffer() {
/*
* map the buffer to a block:
*/
for (int i = 0, j = 0; i < 8; i++, j += 8) {
block[i] =
(((long)buffer[j ] ) << 56) ^
(((long)buffer[j + 1] & 0xffL) << 48) ^
(((long)buffer[j + 2] & 0xffL) << 40) ^
(((long)buffer[j + 3] & 0xffL) << 32) ^
(((long)buffer[j + 4] & 0xffL) << 24) ^
(((long)buffer[j + 5] & 0xffL) << 16) ^
(((long)buffer[j + 6] & 0xffL) << 8) ^
(((long)buffer[j + 7] & 0xffL) );
}
/*
* compute and apply K^0 to the cipher state:
*/
for (int i = 0; i < 8; i++) {
state[i] = block[i] ^ (K[i] = hash[i]);
}
/*
* iterate over all rounds:
*/
for (int r = 1; r <= R; r++) {
/*
* compute K^r from K^{r-1}:
*/
for (int i = 0; i < 8; i++) {
L[i] = 0L;
for (int t = 0, s = 56; t < 8; t++, s -= 8) {
L[i] ^= C[t][(int)(K[(i - t) & 7] >>> s) & 0xff];
}
}
for (int i = 0; i < 8; i++) {
K[i] = L[i];
}
K[0] ^= rc[r];
/*
* apply the r-th round transformation:
*/
for (int i = 0; i < 8; i++) {
L[i] = K[i];
for (int t = 0, s = 56; t < 8; t++, s -= 8) {
L[i] ^= C[t][(int)(state[(i - t) & 7] >>> s) & 0xff];
}
}
for (int i = 0; i < 8; i++) {
state[i] = L[i];
}
}
/*
* apply the Miyaguchi-Preneel compression function:
*/
for (int i = 0; i < 8; i++) {
hash[i] ^= state[i] ^ block[i];
}
}
/**
* Initialize the hashing state.
*/
public void NESSIEinit() {
Arrays.fill(bitLength, (byte)0);
bufferBits = bufferPos = 0;
buffer[0] = 0; // it's only necessary to cleanup buffer[bufferPos].
Arrays.fill(hash, 0L); // initial value
}
/**
* Delivers input data to the hashing algorithm.
*
* @param source plaintext data to hash.
* @param sourceBits how many bits of plaintext to process.
*
* This method maintains the invariant: bufferBits < 512
*/
public void NESSIEadd(byte[] source, long sourceBits) {
/*
sourcePos
|
+-------+-------+-------
||||||||||||||||||||| source
+-------+-------+-------
+-------+-------+-------+-------+-------+-------
|||||||||||||||||||||| buffer
+-------+-------+-------+-------+-------+-------
|
bufferPos
*/
int sourcePos = 0; // index of leftmost source byte containing data (1 to 8 bits).
int sourceGap = (8 - ((int)sourceBits & 7)) & 7; // space on source[sourcePos].
int bufferRem = bufferBits & 7; // occupied bits on buffer[bufferPos].
int b;
// tally the length of the added data:
long value = sourceBits;
for (int i = 31, carry = 0; i >= 0; i--) {
carry += (bitLength[i] & 0xff) + ((int)value & 0xff);
bitLength[i] = (byte)carry;
carry >>>= 8;
value >>>= 8;
}
// process data in chunks of 8 bits:
while (sourceBits > 8) { // at least source[sourcePos] and source[sourcePos+1] contain data.
// take a byte from the source:
b = ((source[sourcePos] << sourceGap) & 0xff) |
((source[sourcePos + 1] & 0xff) >>> (8 - sourceGap));
if (b < 0 || b >= 256) {
throw new RuntimeException("LOGIC ERROR");
}
// process this byte:
buffer[bufferPos++] |= b >>> bufferRem;
bufferBits += 8 - bufferRem; // bufferBits = 8*bufferPos;
if (bufferBits == 512) {
// process data block:
processBuffer();
// reset buffer:
bufferBits = bufferPos = 0;
}
buffer[bufferPos] = (byte)((b << (8 - bufferRem)) & 0xff);
bufferBits += bufferRem;
// proceed to remaining data:
sourceBits -= 8;
sourcePos++;
}
// now 0 <= sourceBits <= 8;
// furthermore, all data (if any is left) is in source[sourcePos].
if (sourceBits > 0) {
b = (source[sourcePos] << sourceGap) & 0xff; // bits are left-justified on b.
// process the remaining bits:
buffer[bufferPos] |= b >>> bufferRem;
} else {
b = 0;
}
if (bufferRem + sourceBits < 8) {
// all remaining data fits on buffer[bufferPos], and there still remains some space.
bufferBits += sourceBits;
} else {
// buffer[bufferPos] is full:
bufferPos++;
bufferBits += 8 - bufferRem; // bufferBits = 8*bufferPos;
sourceBits -= 8 - bufferRem;
// now 0 <= sourceBits < 8; furthermore, all data is in source[sourcePos].
if (bufferBits == 512) {
// process data block:
processBuffer();
// reset buffer:
bufferBits = bufferPos = 0;
}
buffer[bufferPos] = (byte)((b << (8 - bufferRem)) & 0xff);
bufferBits += (int)sourceBits;
}
}
/**
* Get the hash value from the hashing state.
*
* This method uses the invariant: bufferBits < 512
*/
public void NESSIEfinalize(byte[] digest) {
// append a '1'-bit:
buffer[bufferPos] |= 0x80 >>> (bufferBits & 7);
bufferPos++; // all remaining bits on the current byte are set to zero.
// pad with zero bits to complete 512N + 256 bits:
if (bufferPos > 32) {
while (bufferPos < 64) {
buffer[bufferPos++] = 0;
}
// process data block:
processBuffer();
// reset buffer:
bufferPos = 0;
}
while (bufferPos < 32) {
buffer[bufferPos++] = 0;
}
// append bit length of hashed data:
System.arraycopy(bitLength, 0, buffer, 32, 32);
// process data block:
processBuffer();
// return the completed message digest:
for (int i = 0, j = 0; i < 8; i++, j += 8) {
long h = hash[i];
digest[j ] = (byte)(h >>> 56);
digest[j + 1] = (byte)(h >>> 48);
digest[j + 2] = (byte)(h >>> 40);
digest[j + 3] = (byte)(h >>> 32);
digest[j + 4] = (byte)(h >>> 24);
digest[j + 5] = (byte)(h >>> 16);
digest[j + 6] = (byte)(h >>> 8);
digest[j + 7] = (byte)(h );
}
}
/**
* Delivers string input data to the hashing algorithm.
*
* @param source plaintext data to hash (ASCII text string).
*
* This method maintains the invariant: bufferBits < 512
*/
public void NESSIEadd(String source) {
if (source.length() > 0) {
byte[] data = new byte[source.length()];
for (int i = 0; i < source.length(); i++) {
data[i] = (byte)source.charAt(i);
}
NESSIEadd(data, 8 * data.length);
}
}
}

View file

@ -0,0 +1,153 @@
package com.alex.utils;
import java.nio.ByteBuffer;
/**
* Holds utility methods for reading/writing a byte buffer.
* @author Emperor
*
*/
public final class ByteBufferUtils {
/**
* Gets a string from the byte buffer.
* @param buffer The byte buffer.
* @return The string.
*/
public static String getString(ByteBuffer buffer) {
StringBuilder sb = new StringBuilder();
byte b;
while ((b = buffer.get()) != 0) {
sb.append((char) b);
}
return sb.toString();
}
/**
* Puts a string on the byte buffer.
* @param s The string to put.
* @param buffer The byte buffer.
*/
public static void putString(String s, ByteBuffer buffer) {
buffer.put(s.getBytes()).put((byte) 0);
}
/**
* Gets a string from the byte buffer.
* @param s The string.
* @param buffer The byte buffer.
* @return The string.
*/
public static ByteBuffer putGJ2String(String s, ByteBuffer buffer) {
byte[] packed = new byte[256];
int length = packGJString2(0, packed, s);
return buffer.put((byte) 0).put(packed, 0, length).put((byte) 0);
}
/**
* Decodes the XTEA encryption.
* @param keys The keys.
* @param start The start index.
* @param end The end index.
* @param buffer The byte buffer.
*/
public static void decodeXTEA(int[] keys, int start, int end, ByteBuffer buffer) {
int l = buffer.position();
buffer.position(start);
int length = (end - start) / 8;
for (int i = 0; i < length; i++) {
int firstInt = buffer.getInt();
int secondInt = buffer.getInt();
int sum = 0xc6ef3720;
int delta = 0x9e3779b9;
for (int j = 32; j-- > 0;) {
secondInt -= keys[(sum & 0x1c84) >>> 11] + sum ^ (firstInt >>> 5 ^ firstInt << 4) + firstInt;
sum -= delta;
firstInt -= (secondInt >>> 5 ^ secondInt << 4) + secondInt ^ keys[sum & 3] + sum;
}
buffer.position(buffer.position() - 8);
buffer.putInt(firstInt);
buffer.putInt(secondInt);
}
buffer.position(l);
}
/**
* Converts a String to an Integer?
*
* @param position
* The position.
* @param buffer
* The buffer used.
* @param string
* The String to convert.
* @return The Integer.
*/
public static int packGJString2(int position, byte[] buffer, String string) {
int length = string.length();
int offset = position;
for (int i = 0; length > i; i++) {
int character = string.charAt(i);
if (character > 127) {
if (character > 2047) {
buffer[offset++] = (byte) ((character | 919275) >> 12);
buffer[offset++] = (byte) (128 | ((character >> 6) & 63));
buffer[offset++] = (byte) (128 | (character & 63));
} else {
buffer[offset++] = (byte) ((character | 12309) >> 6);
buffer[offset++] = (byte) (128 | (character & 63));
}
} else
buffer[offset++] = (byte) character;
}
return offset - position;
}
/**
* Gets a tri-byte from the buffer.
* @param buffer The buffer.
* @return The value.
*/
public static int getTriByte(ByteBuffer buffer) {
return ((buffer.get() & 0xFF) << 16) + ((buffer.get() & 0xFF) << 8) + (buffer.get() & 0xFF);
}
/**
* Gets a smart from the buffer.
* @param buffer The buffer.
* @return The value.
*/
public static int getSmart(ByteBuffer buffer) {
int peek = buffer.get() & 0xFF;
if (peek <= Byte.MAX_VALUE) {
return peek;
}
return ((peek << 8) | (buffer.get() & 0xFF)) - 32768;
}
/**
* Gets a smart from the buffer.
* @param buffer The buffer.
* @return The value.
*/
public static int getBigSmart(ByteBuffer buffer) {
int value = 0;
int current = getSmart(buffer);
while (current == 32767) {
current = getSmart(buffer);
value += 32767;
}
value += current;
return value;
}
/**
* Constructs a new {@code ByteBufferUtils} {@code Object}.
*/
private ByteBufferUtils() {
/*
* empty.
*/
}
}

View file

@ -0,0 +1,26 @@
package com.alex.utils;
public final class Constants {
public static final int NO_COMPRESSION = 0;
public static final int BZIP2_COMPRESSION = 1;
public static final int GZIP_COMPRESSION = 2;
public static final int MAX_VALID_ARCHIVE_LENGTH = 1000000;
public static final int INTERFACE_DEFINITIONS_INDEX = 3;
public static final int MAPS_INDEX = 5;
public static final int MODELS_INDEX = 7;
public static final int SPRITES_INDEX = 8;
public static final int INDEXED_IMAGES_INDEX = 8;
public static final int OBJECTS_DEFINITIONS_INDEX = 18;
public static final int ITEM_DEFINITIONS_INDEX = 19;
public static final int LOADER_IMAGES_INDEX = 32;
public static final int LOADER_INDEXED_IMAGES_INDEX = 34;
public static final int CLIENT_BUILD = 718;
public static final boolean ENCRYPTED_CACHE = true;
private Constants() {
}
}

View file

@ -0,0 +1,62 @@
package com.alex.utils;
import java.math.BigInteger;
import com.alex.io.OutputStream;
import com.alex.store.Store;
public final class Utils {
public static byte[] cryptRSA(byte[] data, BigInteger exponent, BigInteger modulus) {
return new BigInteger(data).modPow(exponent, modulus).toByteArray();
}
public static byte[] getArchivePacketData(int indexId, int archiveId,
byte[] archive) {
OutputStream stream = new OutputStream(archive.length + 4);
stream.writeByte(indexId);
stream.writeShort(archiveId);
stream.writeByte(0); // priority, no compression
stream.writeInt(archive.length);
int offset = 8;
for (int index = 0; index < archive.length; index++) {
if (offset == 512) {
stream.writeByte(-1);
offset = 1;
}
stream.writeByte(archive[index]);
offset++;
}
byte[] packet = new byte[stream.getOffset()];
stream.setOffset(0);
stream.getBytes(packet, 0, packet.length);
return packet;
}
public static int getNameHash(String name) {
return name.toLowerCase().hashCode();
}
public static final int getInterfaceDefinitionsSize(Store store) {
return store.getIndexes()[3].getLastArchiveId();
}
public static final int getInterfaceDefinitionsComponentsSize(Store store,
int interfaceId) {
return store.getIndexes()[3].getLastFileId(interfaceId);
}
public static final int getItemDefinitionsSize(Store store) {
int lastArchiveId = store.getIndexes()[19].getLastArchiveId();
return lastArchiveId * 256
+ store.getIndexes()[19].getValidFilesCount(lastArchiveId);
}
private Utils() {
}
}

View file

@ -0,0 +1,27 @@
package emperor;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.util.Arrays;
import alex.cache.loaders.ObjectDefinitions;
import com.alex.store.Store;
public class DefDumper {
public static void main(String...args) throws Throwable {
Store store = new Store("./508/");
BufferedWriter bw = new BufferedWriter(new FileWriter("./508_object_list.txt"));
for (int i = 0; i < 100_000; i++) {
ObjectDefinitions def = ObjectDefinitions.initialize(i, store);
if (def == null) {
continue;
}
bw.append("definition [id=" + i + ", options=" + Arrays.toString(def.options) + "]");
bw.newLine();
}
bw.flush();
bw.close();
}
}

View file

@ -0,0 +1,159 @@
package emperor;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import com.alex.loaders.images.IndexedColorImageFile;
import com.alex.store.Store;
/**
* Handles the donator icon packing.
* @author Vexia
*
*/
public final class DonatorIconPacker {
/**
* The icons to pack.
*/
private static String[] ICONS = new String[] {"green", "red", "yellow", "blue", "orange", "pink", "purple", "brown", "world_announce", "rainbow", "whip_icon"};
/**
* The path.
*/
private static final String PATH = "./icons";
/**
* The icon dump.
*/
private static final String DUMP_PATH = "./icon_dump";
/**
* The archive id.
*/
private static final int ACRHIVE_ID = 815;
/**
* The starting index.
*/
private static final int START_INDEX = 2;
/**
* The index color image file.
*/
private static IndexedColorImageFile colorFile;
/**
* The store to work with.
*/
private static Store store;
/**
* Runs the donator icon packer.
* @param args the arguments.
* @throws IOException the exception.
*/
public static void main(String...args) throws IOException {
setStore(new Store("./498/"));
colorFile = new IndexedColorImageFile(store, ACRHIVE_ID, 0);
//colorFile.replaceImage(ImageIO.read(new File("logo.png")), 0);
colorFile.addImage(ImageIO.read(new File("nazi.png")));
//colorFile.delete(1);
//packAll();
dump();
save();
}
/**
* Packs all the icons.
* @throws IOException the exception.
*/
public static void packAll() throws IOException {
for (int i = 0; i < ICONS.length; i++) {
pack(i, getImage(ICONS[i]));
}
}
/**
* Packs an image to the cache.
* @param index the index.
* @param image the image.
*/
public static void pack(int index, BufferedImage image) {
if (image == null) {
System.out.println("Image null at " + index + "!");
return;
}
String name = ICONS[index];
int realIndex = START_INDEX + index;
int indexPacked = 0;
boolean replace = false;
if (realIndex < colorFile.getImages().length) {
colorFile.replaceImage(image, realIndex);
replace = true;
} else {
indexPacked = colorFile.addImage(image);
}
save();
System.out.println("Packing icon with name - " + name + ", chat index=" + realIndex + ", indexPacked=" + indexPacked + ", replace=" + replace + "!");
}
/**
* Dumps the icon
* @throws IOException the exception.
*/
public static void dump() throws IOException {
dumpIcons(DUMP_PATH);
}
/**
* Dumps the icons to a path.
* @param path the path.
* @throws IOException the exception.
*/
public static void dumpIcons(String path) throws IOException {
int index = 0;
System.out.println("Size=" + colorFile.getImages().length);
for (BufferedImage image : colorFile.getImages()) {
String name = path + "/icon-" + index++ + ".png";
ImageIO.write(image, "PNG", new File(name));
System.out.println("Dumping icon - " + name);
}
}
/**
* Saves the index.
*/
public static void save() {
store.getIndexes()[8].putFile(ACRHIVE_ID, 0, colorFile.encodeFile());
}
/**
* Gets a buffered image.
* @param name the name.
* @return the image.
* @throws IOException the exception.
*/
public static BufferedImage getImage(String name) throws IOException {
return ImageIO.read(new File(PATH + "/" + name + ".png"));
}
/**
* Gets the store.
* @return the store
*/
public static Store getStore() {
return store;
}
/**
* Sets the store.
* @param store the store to set
*/
public static void setStore(Store store) {
DonatorIconPacker.store = store;
}
}

View file

@ -0,0 +1,139 @@
package emperor;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import com.alex.loaders.items.ItemDefinitions;
import com.alex.store.Index;
import com.alex.store.Store;
/**
* Packs items.
* @author Vexia
*
*/
public class ItemPacker {
/**
* The store to pack to.
*/
private static Store store;
/**
* The main method.
* @param args the arguments.
* @throws IOException the exception.
*/
public static void main(String...args) throws IOException {
store = new Store("./498/");
String modelName = "models/44590.dat";
packItem(modelName, "Dragon claws");
}
/**
* Gets the size.
* @return the size.
*/
public static int getSize() {
Index index = store.getIndexes()[19];
int lastId = index.getLastArchiveId();
int fileSize = index.getFile(lastId).length;
System.err.println(fileSize);
System.err.println(index.getValidFilesCount(lastId));
int size = lastId * 256 + fileSize;
return size;//13247, 51, 191
}
/**
* Packs an item.
* @param modelName the model name.
* @param itemName the name.
* @throws IOException the exception.
*/
public static void packItem(String modelName, String itemName) throws IOException {
ItemDefinitions def = buildItem(modelName, itemName);
System.out.println("Attempting to pack the model - " + modelName + ", for item name - " + itemName);
packCustomItem(def);
System.out.println("Item packed.");
}
/**
* Packs a custom model.
* @param data the data.
* @return the model.
*/
public static int packCustomModel(byte[] data) {
int archiveId = store.getIndexes()[19].getLastArchiveId()+1;
if(store.getIndexes()[19].putFile(archiveId, 0, data)) {
return archiveId;
}
return -1;
}
/**
* Builds an item.
* @param modelName the name.
* @param itemName the item name.
* @return the def.
* @throws IOException
*/
public static ItemDefinitions buildItem(String modelName, String itemName) throws IOException {
int modelId = packCustomModel(getBytesFromFile(new File(modelName)));
ItemDefinitions definition = ItemDefinitions.getItemDefinition(store, 3101);
definition.setName(itemName);
definition.femaleEquipModelId1 = modelId;
definition.maleEquipModelId1 = modelId;
definition.invModelId = modelId;
return definition;
}
/**
* Packs the custom item.
* @param cache the cache.
* @param id the id.
* @param def the def.
*/
public static void packCustomItem(ItemDefinitions def) {
int id = 13248;
store.getIndexes()[19].putFile(id >>> 8, 0xff & id, def.encode());
}
/**
* Gets all the bytes from the file.
* @param file the file.
* @return the bytes.
* @throws IOException the exception.
*/
@SuppressWarnings("resource")
public static byte[] getBytesFromFile(File file) throws IOException {
InputStream is = new FileInputStream(file);
// Get the size of the file
long length = file.length();
// You cannot create an array using a long type.
// It needs to be an int type.
// Before converting to an int type, check
// to ensure that file is not larger than Integer.MAX_VALUE.
if (length > Integer.MAX_VALUE) {
// File is too large
}
// Create the byte array to hold the data
byte[] bytes = new byte[(int)length];
// Read in the bytes
int offset = 0;
int numRead = 0;
while (offset < bytes.length
&& (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
offset += numRead;
}
// Ensure all the bytes have been read in
if (offset < bytes.length) {
throw new IOException("Could not completely read file "+file.getName());
}
// Close the input stream and return bytes
is.close();
return bytes;
}
}

View file

@ -0,0 +1,83 @@
package emperor;
import java.nio.ByteBuffer;
public class LandMap {
ByteBuffer buffer;
Byte[][][] overlayOpcodes = new Byte[4][64][64];
Byte[][][] overlays = new Byte[4][64][64];
Byte[][][] underlays = new Byte[4][64][64];
Byte[][][] defaultOpcodes = new Byte[4][64][64];
Byte[][][] height = new Byte[4][64][64];
public void addOverlay(int z, int x, int y, int overlay) {
overlays[z][x][y] = (byte) overlay;
}
public void addUnderlay(int z, int x, int y, int underlay) {
underlays[z][x][y] = (byte) underlay;
}
public byte[] generate() {
ByteBuffer buffer = ByteBuffer.allocate(1 << 20);
for (int z = 0; z < 4; z++) {
for (int x = 0; x < 64; x++) {
for (int y = 0; y < 64; y++) {
Byte b = null;
if ((b = defaultOpcodes[z][x][y]) != null) {
buffer.put(b);
}
if ((b = underlays[z][x][y]) != null) {
buffer.put(b);
}
if ((b = overlayOpcodes[z][x][y]) != null) {
buffer.put(b);
buffer.put(overlays[z][x][y]);
}
if ((b = height[z][x][y]) != null) {
buffer.put((byte) 1);
buffer.put(b);
} else {
buffer.put((byte) 0);
}
}
}
}
while (this.buffer.hasRemaining()) {
buffer.put(this.buffer.get());
}
buffer.flip();
byte[] bs = new byte[buffer.remaining()];
buffer.get(bs);
return bs;
}
public void map(ByteBuffer buffer) {
this.buffer = buffer;
for (int z = 0; z < 4; z++) {
for (int x = 0; x < 64; x++) {
for (int y = 0; y < 64; y++) {
while (true) {
int opcode = buffer.get() & 0xFF;
if (opcode == 0) {
break;
}
if (opcode == 1) {
height[z][x][y] = buffer.get();
break;
}
if (opcode <= 49) {
overlayOpcodes[z][x][y] = (byte) opcode;
overlays[z][x][y] = buffer.get();
} else if (opcode <= 81) {
underlays[z][x][y] = (byte) opcode;
} else {
defaultOpcodes[z][x][y] = (byte) opcode;
}
}
}
}
}
System.out.println("Read landscape (remaining=" + buffer.remaining() + ").");
}
}

View file

@ -0,0 +1,15 @@
package emperor;
public class Landscape {
byte[][][] flags = new byte[4][64][64];
byte[][][] overlays = new byte[4][64][64];
byte[][][] underlays = new byte[4][64][64];
public void addOverlay(int z, int x, int y, int overlay) {
overlays[z][x][y] = (byte) overlay;
}
public void addUnderlay(int z, int x, int y, int underlay) {
underlays[z][x][y] = (byte) underlay;
}
}

View file

@ -0,0 +1,243 @@
package emperor;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.util.HashMap;
import java.util.Map;
import com.alex.store.Store;
import com.alex.util.gzip.GZipCompressor;
import com.alex.util.gzip.GZipDecompressor;
/**
* Holds the map cache.
*
* @author Emperor
*
*/
public final class LandscapeCache {
/**
* The map indices buffer.
*/
private static ByteBuffer mapIndices;
/**
* The landscapes;
*/
private static final Map<Integer, byte[]> landscapes = new HashMap<>();
/**
* The amount of indexes.
*/
private static int indexes;
/**
* The cache length.
*/
private static int cacheLength;
/**
* The indexes list.
*/
private static int[] indices = null;
/**
* The path.
*/
private static String path;
/**
* The file store.
*/
private static Store store;
/**
* Initializes the landscape cache stuff.
*
* @param path
* The cache path.
* @throws Throwable
* When an exception occurs.
*/
public static void init(String path, Store store) throws Throwable {
LandscapeCache.path = path;
LandscapeCache.store = store;
try {
RandomAccessFile raf = new RandomAccessFile(path + "/idx_reference.dat", "r");
FileChannel channel = raf.getChannel();
mapIndices = channel.map(MapMode.READ_ONLY, 0, channel.size());
raf.close();
channel.close();
} catch (Throwable t) {
t.printStackTrace();
}
cacheLength = (int) new File(path + "/map_cache_file.idx0").length();
ByteBuffer buffer = mapIndices.duplicate();
indexes = buffer.getShort() & 0xFFFF;
indices = new int[indexes];
for (int i = 0; i < indexes; i++) {
indices[i] = buffer.getInt();
}
int count = 0;
for (int i = 0; i < indexes; i++) {
byte[] b = forId(i);
if (b != null && b.length > 0) {
landscapes.put(i, b);
count++;
}
}
System.out.println("Succesfully loaded " + count + "/" + indexes + " regions!");
}
/**
* Gets the landscape byte buffer.
*
* @param regionId
* The region id.
* @return The landscape buffer.
*/
public static byte[] getLandscape(int regionId) {
int index = LandscapeCache.indexFor(regionId);
return forId(index);
}
/**
* Gets the maps for the given id.
*
* @param id
* The id.
* @return The map data.
*/
public static byte[] forId(int id) {
if (id < 0) {
return new byte[0];
}
try {
RandomAccessFile raf = new RandomAccessFile(path + "/map_cache_file.idx0", "r");
FileChannel channel = raf.getChannel();
int size = (int) ((id >= indexes - 1 ? channel.size() : indices[id + 1]) - indices[id]);
if (size < 3) {
raf.close();
channel.close();
// System.out.println("Index " + id + " has invalid size!");
channel.close();
return new byte[0];
}
//System.out.println("Size: " + size + "/" + channel.size() + ", index: " + indices[id]);
MappedByteBuffer buffer = channel.map(MapMode.READ_ONLY, indices[id], size);
raf.close();
channel.close();
int length = size - 2;
if (length < 1) {
return new byte[0];
}
int decompressedLength = buffer.getShort() & 0xFFFF;
byte[] b = new byte[length];
buffer.get(b);
byte[] data = new byte[decompressedLength];
try {
GZipDecompressor.decompress(data, b, 0, b.length);
} catch (Throwable t) {
System.err.println("Failed to decompress idx " + id + "!");
return new byte[0];
}
return data;
} catch (IOException e) {
e.printStackTrace();
}
return new byte[0];
}
public static void dump(String path) throws Throwable {
indices = new int[indexes];
int offset = 0;
ByteBuffer mapCache = ByteBuffer.allocate(10_000_000);
for (int i = 0; i < indexes; i++) {
indices[i] = offset;
byte[] bs = landscapes.get(i);
if (bs != null && bs.length > 1) {
mapCache.putShort((short) bs.length);
byte[] b = GZipCompressor.compress(bs);
mapCache.put(b);
offset += 2 + b.length;
}
}
mapCache.flip();
File f = new File(path + "/map_cache_file.idx0");
if (f.exists()) {
if (!f.delete()) {
System.err.println("Could not delete #1!");
}
}
RandomAccessFile raf = new RandomAccessFile(f, "rw");
FileChannel channel = raf.getChannel();
channel.write(mapCache);
raf.close();
channel.close();
ByteBuffer buffer = ByteBuffer.allocate(100_000);
buffer.putShort((short) indexes);
for (int i = 0; i < indexes; i++) {
buffer.putInt(indices[i]);
}
buffer.flip();
f = new File(path + "/idx_reference.dat");
if (f.exists()) {
if (!f.delete()) {
System.err.println("Could not delete #2!");
f = new File(path + "/conflict-idx_reference.dat");
}
}
raf = new RandomAccessFile(f, "rw");
channel = raf.getChannel();
channel.write(buffer);
raf.close();
channel.close();
}
/**
* Gets the index for the region id.
*
* @param regionId
* The region id.
* @return The index.
*/
public static int indexFor(int regionId) {
int regionX = regionId >> 8 & 0xFF;
int regionY = regionId & 0xFF;
return store.getIndexes()[5].getArchiveId(new StringBuilder("l").append(regionX).append("_").append(regionY).toString());
}
/**
* Gets the reference table buffer.
*
* @return The reference table buffer.
*/
public static ByteBuffer getReferenceTable() {
ByteBuffer buffer = ByteBuffer.allocate(mapIndices.remaining() + 10);
return buffer.put((byte) 251).putInt(LandscapeCache.getMapIndices().remaining()).putInt(cacheLength).put(LandscapeCache.getMapIndices().duplicate());
}
/**
* Gets the mapIndices.
*
* @return The mapIndices.
*/
public static ByteBuffer getMapIndices() {
return mapIndices;
}
/**
* Gets the landscapes mapping.
* @return The mapping.
*/
public static Map<Integer, byte[]> getLandscapes() {
return landscapes;
}
}

View file

@ -0,0 +1,465 @@
package emperor;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apollo.fs.IndexedFileSystem;
import org.apollo.fs.util.ZipUtils;
import alex.cache.loaders.OverlayDefinition;
import com.alex.io.InputStream;
import com.alex.store.Index;
import com.alex.store.Store;
import com.alex.tools.clientCacheUpdater.RSXteas;
import com.alex.utils.Constants;
import com.alex.utils.Utils;
import emperor.ObjectMap.GameObject;
/**
* @author Emperor
*/
public class LandscapeEditor {
public static final boolean COPY_OUT = true;
public static final void main(String...args) throws Throwable {
if (COPY_OUT) {
for (File f : new File("./mapcache_out/").listFiles()) {
copyFile(f, new File("./mapcache/" + f.getName()));
}
}
// Store store = new Store("./498/");
// packMaps(store);
// checkNonOceanic(store, new int[] {8240, 8241, 8242, 8243, 8249, 8250, 8251, 8254, 8255, 8256, 8505, 8506, 8507, 8510, 8511, 8512, 8761, 8762, 8764, 8765, 8766, 8767, 8768, 9018, 9019, 9020, 9021, 9022, 9023, 9024, 9262, 9274, 9277, 9278, 9279, 9280, 9363, 9518, 9529, 9530, 9533, 9534, 9535, 9536, 9539, 9618, 9784, 9785, 9786, 9787, 9788, 9789, 9790, 9791, 9792, 10023, 10024, 10025, 10026, 10027, 10041, 10045, 10046, 10047, 10048, 10279, 10280, 10281, 10282, 10283, 10298, 10299, 10302, 10303, 10304, 10535, 10538, 10539, 10541, 10543, 10555, 10556, 10557, 10560, 10568, 10570, 10791, 10792, 10796, 10797, 10798, 10799, 10800, 10813, 10815, 10816, 10824, 10825, 10826, 11047, 11048, 11049, 11052, 11069, 11070, 11071, 11072, 11080, 11082, 11303, 11305, 11307, 11308, 11326, 11327, 11328, 11559, 11560, 11561, 11563, 11564, 11582, 11583, 11584, 11815, 11816, 11817, 11818, 11819, 11820, 11838, 11839, 11840, 12071, 12072, 12073, 12074, 12075, 12076, 12077, 12094, 12095, 12096, 12333, 12334, 12350, 12351, 12352, 12606, 12607, 12608, 12862, 12863, 12864, 13118, 13119, 13120, 13374, 13375, 13376, 13466, 13610, 13628, 13629, 13630, 13631, 13632, 13866, 13867, 13868, 14128, 14136, 14379, 14380, 14381, 14382, 14383, 14384, 14392, 14635, 14636, 14640, 14891, 14892, 14896, 14903, 14904, 15147, 15152, 15158, 15160, 15403, 15404, 15405, 15407, 15408, 15414, 15415, 15416});//new int[] {6731, 6985, 8022, 8240, 8241, 8242, 8243, 8249, 8250, 8251, 8254, 8255, 8256, 8280, 8505, 8506, 8507, 8510, 8511, 8512, 8513, 8515, 8761, 8762, 8764, 8765, 8766, 8767, 8768, 9018, 9019, 9020, 9021, 9022, 9023, 9024, 9262, 9274, 9277, 9278, 9279, 9280, 9363, 9518, 9529, 9530, 9533, 9534, 9535, 9536, 9539, 9618, 9784, 9785, 9786, 9787, 9788, 9789, 9790, 9791, 9792, 10023, 10024, 10025, 10026, 10027, 10041, 10045, 10046, 10047, 10048, 10129, 10279, 10280, 10281, 10282, 10283, 10298, 10299, 10302, 10303, 10304, 10308, 10535, 10538, 10539, 10541, 10543, 10555, 10556, 10557, 10560, 10568, 10570, 10583, 10791, 10792, 10796, 10797, 10798, 10799, 10800, 10813, 10815, 10816, 10824, 10825, 10826, 11047, 11048, 11049, 11052, 11069, 11070, 11071, 11072, 11080, 11082, 11303, 11304, 11305, 11307, 11308, 11326, 11327, 11328, 11559, 11560, 11561, 11563, 11564, 11582, 11583, 11584, 11815, 11816, 11817, 11818, 11819, 11820, 11838, 11839, 11840, 12071, 12072, 12073, 12074, 12075, 12076, 12077, 12094, 12095, 12096, 12333, 12334, 12350, 12351, 12352, 12606, 12607, 12608, 12627, 12862, 12863, 12864, 12889, 12890, 13118, 13119, 13120, 13144, 13145, 13146, 13354, 13374, 13375, 13376, 13400, 13401, 13402, 13466, 13610, 13625, 13626, 13628, 13629, 13630, 13631, 13632, 13866, 13867, 13868, 14128, 14136, 14379, 14380, 14381, 14382, 14383, 14384, 14392, 14635, 14636, 14640, 14648, 14891, 14892, 14896, 14903, 14904, 15147, 15152, 15158, 15160, 15403, 15404, 15405, 15407, 15408, 15414, 15415, 15416});
// generateCache(store);
// override(store, 788, 12187);
// packOSRSMaps(store);
// packLandscape(store);
// pack377Maps(store);
// addMissingMaps(store);
// createMap(store);
// changeMap(store);
}
static void packMaps(Store store) throws Throwable {
LandscapeCache.init("./mapcache/", store);
int[] keys = new int[] { 14881828, -6662814, 58238456, 146761213 };
int count = 0;
int failed = 0;
for (int regionId = 0; regionId < 50_000; regionId++) {
int regionX = regionId >> 8 & 0xFF;
int regionY = regionId & 0xFF;
String name = "l" + regionX + "_" + regionY;
int index = store.getIndexes()[5].getArchiveId(name);
if (index < 0) {
continue;
}
byte[] b = LandscapeCache.forId(index);
if (b == null || b.length < 2 || !validRegion(new InputStream(b))) {
failed++;
continue;
}
if (store.getIndexes()[5].putFile(index, 0, Constants.GZIP_COMPRESSION, b, keys, true, true, Utils.getNameHash(name), -1)) {
count++;
} else {
failed++;
}
}
// store.getIndexes()[5].rewriteTable();
// store.getIndexes()[5].resetCachedFiles();
System.out.println("Packed " + count + " maps (failed " + failed + " maps)!");
// store2.getIndexes()[i].putFile(oldArchiveId, 0, Constants.GZIP_COMPRESSION, data, keys2, false, false, Utils.getNameHash(nameHash), -1);
}
static void createMap(Store store) throws Throwable {
ObjectMap map = new ObjectMap();
for (int x = 0; x < 64; x++) {
for (int y = 0; y < 64; y++) {
if (x == 32 || y == 32) {
continue;
}
map.add(1276, x, y, 0, 10, 0);
}
}
byte[] bs = map.generate();
int regionId = 11110;
int x = regionId >> 8 & 0xFF;
int y = regionId & 0xFF;
LandscapeCache.init("./mapcache/", store);
int archive = store.getIndexes()[5].getArchiveId("l" + x + "_" + y);
if (archive > -1) {
System.out.println("Already contained region " + regionId + " (archive=" + archive + ", len=" + bs.length + " - " +LandscapeCache.forId(archive).length + ")!");
return;
}
for (int ar = 0; ar < 50000; ar++) {
if (!store.getIndexes()[5].archiveExists(ar)) {
if (LandscapeCache.forId(ar).length < 1) {
archive = ar;
System.out.println("Archive available: " + ar);
break;
}
}
}
store.getIndexes()[5].putFile(archive, 0, Constants.GZIP_COMPRESSION, bs, null, true, true,
Utils.getNameHash("l" + x + "_" + y), -1);
LandscapeCache.getLandscapes().put(archive, bs);
LandscapeCache.dump("./mapcache_out/");
System.out.println("Done!");
}
static void changeMap(Store store) throws Throwable {
int regionId = 12439;
GameObject[] remove = new GameObject[] {
new GameObject(32099, 42, 27, 0, 10, 3)
};
GameObject[] replace = new GameObject[] {
new GameObject(29139, 42, 27, 0, 10, 3)
};
LandscapeCache.init("./mapcache/", store);
ObjectMap map = new ObjectMap();
map.map(new InputStream(LandscapeCache.getLandscape(regionId)));
for (int i = 0; i < remove.length; i++) {
GameObject r = remove[i];
GameObject object = map.get(r.id, r.loc.x, r.loc.y, r.loc.z, r.type, r.rotation);
if (object == null) {
System.err.println("Could not find object!");
return;
}
map.getObjects().remove(object);
if (replace[i] != null) {
map.getObjects().add(replace[i]);
}
}
byte[] bs = map.generate();
LandscapeCache.getLandscapes().put(LandscapeCache.indexFor(regionId), bs);
LandscapeCache.dump("./mapcache_out/");
}
/**
* Overrides the regions.
* @param store The file store.
* @param revision The revision to get the regions from.
* @param regionIds The region ids to override.
* @throws Throwable When an exception occurs.
*/
public static void override(Store store, int revision, int...regionIds) throws Throwable {
LandscapeCache.init("./mapcache/", store);
int count = 0;
if (revision == 377) {
Store s = new Store("./468/");
IndexedFileSystem fs = new IndexedFileSystem(new File("./377/"), true);
for (int regionId : regionIds) {
int regionX = regionId >> 8 & 0xFF;
int regionY = regionId & 0xFF;
int index = store.getIndexes()[5].getArchiveId(new StringBuilder("l").append(regionX).append("_").append(regionY).toString());
byte[] bs = null;
try {
ByteBuffer buffer = fs.getFile(4, index);
bs = ZipUtils.unzip(buffer).array();
} catch (Throwable t) {
continue;
}
if (bs != null && validRegion(new InputStream(bs))) {
System.out.println("Added region " + regionId + "!");
count++;
LandscapeCache.getLandscapes().put(index, bs);
store.getIndexes()[5].putArchive(s.getIndexes()[5].getArchiveId(new StringBuilder("m").append(regionX).append("_").append(regionY).toString()), s);
}
}
fs.close();
} else {
RSXteas.loadUnpackedXteas(revision);
Store s = new Store("./" + revision + "/");
boolean newFormat = revision > 750;
for (int regionId : regionIds) {
int regionX = regionId >> 8 & 0xFF;
int regionY = regionId & 0xFF;
int index = store.getIndexes()[5].getArchiveId(new StringBuilder("l").append(regionX).append("_").append(regionY).toString());
int[] xteas = RSXteas.getXteas(regionId);
byte[] b = newFormat ? s.getIndexes()[5].getFile(regionX | regionY << 7, 0)
: s.getIndexes()[5].getFile(index, 0, xteas);
if (b != null && b.length > 1 && validRegion(new InputStream(b))) {
System.out.println("Added region " + regionId + "!");
LandscapeCache.getLandscapes().put(index, b);
count++;
if (!newFormat) {
store.getIndexes()[5].putArchive(s.getIndexes()[5].getArchiveId(new StringBuilder("m").append(regionX).append("_").append(regionY).toString()), s);
}
}
}
}
LandscapeCache.dump("./mapcache_out/");
System.out.println("Packed " + count + "/" + regionIds.length + " regions.");
}
/**
* Fully generates a map cache (from scratch).
* @param store The file store.
* @throws Throwable
*/
public static void generateCache(Store store) throws Throwable {
LandscapeCache.init("./mapcache/", store);
Store s = new Store("./508/");
List<Integer> missingRegions = new ArrayList<>();
System.out.println("Packing 508 maps...");
RSXteas.loadUnpackedXteas(508);
int count = 0;
for (int regionId = 0; regionId < 50_000; regionId++) {
int regionX = regionId >> 8 & 0xFF;
int regionY = regionId & 0xFF;
int index = store.getIndexes()[5].getArchiveId(new StringBuilder("l").append(regionX).append("_").append(regionY).toString());
if (index < 0) {
continue;
}
int[] xteas = RSXteas.getXteas(regionId);
byte[] b = s.getIndexes()[5].getFile(index, 0, xteas);
if (b == null || b.length < 2 || !validRegion(new InputStream(b))) {
RandomAccessFile raf = new RandomAccessFile(new File("./508_Maps/" + index), "r");
ByteBuffer buffer = raf.getChannel().map(MapMode.READ_ONLY, 0, raf.length());
b = new byte[(int) raf.length()];
buffer.get(b);
raf.close();
if (!validRegion(new InputStream(b))) {
missingRegions.add(regionId);
continue;
}
System.out.println("Used 508 map data file for index " + index + "!");
}
int archiveId = s.getIndexes()[5].getArchiveId(new StringBuilder("m").append(regionX).append("_").append(regionY).toString());
if (archiveId > -1) {
store.getIndexes()[5].putArchive(archiveId, s);
}
LandscapeCache.getLandscapes().put(index, b);
count++;
}
System.out.println("Added " + count + " 508 regions!");
System.out.println("Packing 468 maps...");
RSXteas.loadUnpackedXteas(468);
s = new Store("./468/");
int subCount = 0;
for (int regionId = 0; regionId < 50_000; regionId++) {
int regionX = regionId >> 8 & 0xFF;
int regionY = regionId & 0xFF;
int index = s.getIndexes()[5].getArchiveId(new StringBuilder("l").append(regionX).append("_").append(regionY).toString());
if (!missingRegions.contains(regionId)) {
continue;
}
int[] xteas = RSXteas.getXteas(regionId);
byte[] b = s.getIndexes()[5].getFile(index, 0, xteas);
if (b != null && b.length > 1 && validRegion(new InputStream(b))) {
System.out.println("Added missing region " + regionId + "!");
count++;
subCount++;
missingRegions.remove((Object) regionId);
LandscapeCache.getLandscapes().put(index, b);
store.getIndexes()[5].putArchive(s.getIndexes()[5].getArchiveId(new StringBuilder("m").append(regionX).append("_").append(regionY).toString()), s);
}
}
System.out.println("Added " + subCount + " 468 regions!");
System.out.println("Packing 377 maps...");
subCount = 0;
IndexedFileSystem fs = new IndexedFileSystem(new File("./377/"), true);
for (int regionId = 0; regionId < 50_000; regionId++) {
int regionX = regionId >> 8 & 0xFF;
int regionY = regionId & 0xFF;
int index = store.getIndexes()[5].getArchiveId(new StringBuilder("l").append(regionX).append("_").append(regionY).toString());
if (!missingRegions.contains(regionId)) {
continue;
}
byte[] bs = null;
try {
ByteBuffer buffer = fs.getFile(4, index);
bs = ZipUtils.unzip(buffer).array();
} catch (Throwable t) {
continue;
}
if (bs != null && validRegion(new InputStream(bs))) {
System.out.println("Added missing region " + regionId + "!");
count++;
subCount++;
missingRegions.remove((Object) regionId);
LandscapeCache.getLandscapes().put(index, bs);
store.getIndexes()[5].putArchive(s.getIndexes()[5].getArchiveId(new StringBuilder("m").append(regionX).append("_").append(regionY).toString()), s);
}
}
System.out.println("Added " + subCount + " 377 regions!");
fs.close();
System.out.println("Packing 666 maps...");
RSXteas.loadUnpackedXteas(666);
s = new Store("./666/");
subCount = 0;
for (int regionId = 0; regionId < 50_000; regionId++) {
int regionX = regionId >> 8 & 0xFF;
int regionY = regionId & 0xFF;
int index = store.getIndexes()[5].getArchiveId(new StringBuilder("l").append(regionX).append("_").append(regionY).toString());
if (index < 0) {
continue;
}
if (!missingRegions.contains(regionId)) {
continue;
}
int[] xteas = RSXteas.getXteas(regionId);
byte[] b = s.getIndexes()[5].getFile(index, 0, xteas);
if (b != null && b.length > 1 && validRegion(new InputStream(b))) {
System.out.println("Added missing region " + regionId + "!");
count++;
subCount++;
missingRegions.remove((Object) regionId);
LandscapeCache.getLandscapes().put(index, b);
store.getIndexes()[5].putArchive(s.getIndexes()[5].getArchiveId(new StringBuilder("m").append(regionX).append("_").append(regionY).toString()), s);
}
}
System.out.println("Added " + subCount + " 666 regions!");
System.out.println("Packing 788 maps...");
s = new Store("./788/");
subCount = 0;
for (int regionId = 0; regionId < 50_000; regionId++) {
int regionX = regionId >> 8 & 0xFF;
int regionY = regionId & 0xFF;
if (!missingRegions.contains(regionId) && regionId != 6234) {
continue;
}
int index = regionX | regionY << 7;
byte[] b = s.getIndexes()[5].getFile(index, 0);
if (b != null && b.length > 1 && validRegion(new InputStream(b))) {
index = store.getIndexes()[5].getArchiveId(new StringBuilder("l").append(regionX).append("_").append(regionY).toString());
System.out.println("Added missing region " + regionId + "!");
count++;
subCount++;
missingRegions.remove((Object) regionId);
LandscapeCache.getLandscapes().put(index, b);
}
}
System.out.println("Added " + subCount + " 788 regions!");
LandscapeCache.dump("./mapcache_out/");
System.out.println("Added a total of " + count + " map regions, missing " + missingRegions.size() + " regions.");
System.out.println("Missing: " + Arrays.toString(missingRegions.toArray()));
System.exit(0);
}
/**
* Checks for non-oceanic regions (regions that don't exist purely of sea).
* @param store The store.
* @param regions The regions array.
*/
public static void checkNonOceanic(Store store, int[] regions) {
List<Integer> missing = new ArrayList<>();
for (int regionId : regions) {
int regionX = regionId >> 8 & 0xFF;
int regionY = regionId & 0xFF;
int mapscapeId = store.getIndexes()[5].getArchiveId(new StringBuilder("m").append(regionX).append("_").append(regionY).toString());
if (mapscapeId < 0) {
System.err.println("Invalid mapscape index for region " + regionId + "!");
continue;
}
boolean abort = false;
ByteBuffer buffer = ByteBuffer.wrap(store.getIndexes()[5].getFile(mapscapeId, 0));
byte[][][] mapscape = new byte[4][64][64];
main: for (int z = 0; z < 4; z++) {
for (int x = 0; x < 64; x++) {
for (int y = 0; y < 64; y++) {
while (true) {
int value = buffer.get() & 0xFF;
if (value == 0) {
break;
}
if (value == 1) {
buffer.get();
break;
}
if (value <= 49) {
int overlay = buffer.get() & 0xFF;
OverlayDefinition def = OverlayDefinition.forId(store, overlay);
if (def != null && def.getTextureId() != 25) {
abort = true;
break main;
}
} else if (value <= 81) {
mapscape[z][x][y] = (byte) (value - 49);
}
}
}
}
}
if (abort) {
missing.add(regionId);
}
}
System.out.println("Missing region count: " + missing.size() + "..");
System.out.println(Arrays.toString(missing.toArray()));
}
public static void packLandscape(Store store) throws Throwable {
Store s = new Store("./508/");
int[] ids = new int[] {13722};
for (int regionId : ids) {
int regionX = regionId >> 8 & 0xFF;
int regionY = regionId & 0xFF;
boolean b = store.getIndexes()[5].putArchive(s.getIndexes()[5].getArchiveId(new StringBuilder("m").append(regionX).append("_").append(regionY).toString()), s);
System.out.println("Packed landscape (" + regionId + "): " + b);
}
}
public static boolean addMapFile(Index index, String name, byte[] data) {
int archiveId = index.getArchiveId(name);
if(archiveId == -1)
archiveId = index.getTable().getValidArchiveIds().length;
return index.putFile(archiveId, 0, Constants.GZIP_COMPRESSION, data, null, false, false, Utils.getNameHash(name), -1);
}
public static boolean validRegion(InputStream stream) {
int count = 0;
for (;;) {
int offset = stream.readSmart2();
if (offset == 0) {
break;
}
int location = 0;
for (;;) {
offset = stream.readUnsignedSmart();
if (offset == 0) {
break;
}
location += offset - 1;
int y = location & 0x3f;
int x = location >> 6 & 0x3f;
stream.readUnsignedByte();
if (x >= 0 && y >= 0 && x < 64 && y < 64) {
if (++count > 10) {
return true;
}
}
}
}
return false;
}
/**
* Copies a file.
* @param in The file to be copied.
* @param out The file to copy to.
*/
private static void copyFile(File in, File out) {
try (FileChannel channel = new FileInputStream(in).getChannel()) {
try (FileChannel output = new FileOutputStream(out).getChannel()) {
channel.transferTo(0, channel.size(), output);
channel.close();
output.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

View file

@ -0,0 +1,393 @@
package emperor;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import alex.cache.loaders.OverlayDefinition;
import com.alex.io.InputStream;
import com.alex.store.Store;
import com.alex.utils.Constants;
import com.alex.utils.Utils;
import emperor.ObjectMap.GameObject;
/**
* Used for editting maps.
* @author Emperor
*
*/
public final class MapEditor {
/**
* The valid revisions.
*/
private static final int[] VALID_REVISIONS = {
377, 468, 474, 498, 503, 508, 538, 546, 562, 569, 666, 788
};
/**
* The xtea keys used to encrypt the maps.
*/
private static final int[] XTEA_KEYS = {
14881828, -6662814, 58238456, 146761213
};
/**
* The mapscape type (floor).
*/
private static final String MAP_TYPE = "m";
/**
* The landscape type (objects).
*/
private static final String LAND_TYPE = "l";
/**
* The map cache index.
*/
private static final int MAP_INDEX = 5;
/**
* The cache file store to change.
*/
private static Store store;
/**
* Used the update the maps.
* @throws Throwable When an exception occurs.
*/
private static void update() throws Throwable {
// replaceObjects(new GameObject[][] {
// { new GameObject(5281, 3666, 3521, 1, 10, 0), new GameObject(5281, 3666, 3520, 1, 10, 0) }
// });
// copy(13099, 13099, new Store("./508/"), new int[] { 273193181, -1465876115, -151667950, 40605898 });
replaceMapPart(13099, new Store("./468/"), new int[] {-636687345, -1379232722, -1661855973, 666075756}, 18, 36, 31, 49, 0);
// int regionId = 13099;
// System.out.println("Revisions for region " + regionId + ": " + Arrays.toString(getValidRevisions(regionId)) + ".");
}
/**
* Replaces a part of the map.
* @param regionId The region id.
* @param from The store to copy from.
* @param xteaKeys The XTEA keys used to decrypt the region from the store to copy from.
* @param southWestX The south west x (on region) coordinate of the part to replace.
* @param southWestY The south west y (on region) coordinate of the part to replace.
* @param northEastX The north east x (on region) coordinate of the part to replace.
* @param northEastY The north east y (on region) coordinate of the part to replace.
*/
static void replaceMapPart(int regionId, Store from, int[] xteaKeys, int southWestX, int southWestY, int northEastX, int northEastY, int...planes) {
ObjectMap map = new ObjectMap();
map.map(new InputStream(getLandscape(regionId, store, XTEA_KEYS)));
for (Iterator<GameObject> it = map.getObjects().iterator(); it.hasNext();) {
GameObject object = it.next();
if (object.loc.x >= southWestX && object.loc.x <= northEastX && object.loc.y >= southWestY && object.loc.y <= northEastY) {
it.remove();
}
}
ObjectMap m = new ObjectMap();
m.map(new InputStream(getLandscape(regionId, from, xteaKeys)));
for (GameObject object : m.getObjects()) {
for (int z : planes) {
if (object.loc.z == z && object.loc.x >= southWestX && object.loc.x <= northEastX && object.loc.y >= southWestY && object.loc.y <= northEastY) {
map.getObjects().add(object);
break;
}
}
}
packLandscape(regionId, map.generate(), store, XTEA_KEYS);
LandMap l = new LandMap();
l.map(ByteBuffer.wrap(store.getIndexes()[5].getFile(getArchiveIndex(MAP_TYPE, regionId, store))));
LandMap lm = new LandMap();
lm.map(ByteBuffer.wrap(from.getIndexes()[5].getFile(getArchiveIndex(MAP_TYPE, regionId, from))));
for (int z : planes) {
for (int x = southWestX; x <= northEastX; x++) {
for (int y = southWestY; y <= northEastY; y++) {
l.defaultOpcodes[z][x][y] = lm.defaultOpcodes[z][x][y];
l.height[z][x][y] = lm.height[z][x][y];
l.overlayOpcodes[z][x][y] = lm.overlayOpcodes[z][x][y];
l.overlays[z][x][y] = lm.overlays[z][x][y];
l.underlays[z][x][y] = lm.underlays[z][x][y];
}
}
}
packMapscape(regionId, l.generate(), store);
}
/**
* Gets the revisions of the caches having this region.
* @param regionId The region id.
* @return The cache revisions.
*/
public static int[] getValidRevisions(int regionId) {
int[] revisions = new int[VALID_REVISIONS.length];
int count = 0;
for (int revision : VALID_REVISIONS) {
String rev = revision == 498 ? "clean_498" : Integer.toString(revision);
try {
Store store = new Store("./" + rev + "/");
System.out.println("./" + rev + "/");
if (getArchiveIndex(LAND_TYPE, regionId, store) > -1) {
revisions[count++] = revision;
}
} catch (Throwable t) {
t.printStackTrace();
}
}
return Arrays.copyOf(revisions, count);
}
/**
* Copies a region.
* @param fromId The region id to copy.
* @param toId The region id to paste on.
* @param from The store to get the data from.
* @param xtea The XTEA keys to decrypt the map.
*/
static void copy(int fromId, int toId, Store from, int[] xtea) {
copy(LAND_TYPE, fromId, toId, from, xtea);
copy(MAP_TYPE, fromId, toId, from, null);
}
/**
* Copies the landscape from a region.
* @param fromId The region id to copy the landscape from.
* @param toId The region id to paste the landscape on.
* @param from the store to get the data from.
* @param xtea The XTEA keys to decrypt the landscape.
*/
private static void copy(String type, int fromId, int toId, Store from, int[] xtea) {
int index = getArchiveIndex(type, fromId, from);
if (index < 0) {
throw new IllegalArgumentException("Region " + fromId + " does not exist!");
}
byte[] bs = from.getIndexes()[MAP_INDEX].getFile(index, 0, xtea);
if (bs == null || bs.length < 1) {
throw new IllegalArgumentException("Region " + fromId + " is invalid!");
}
index = getArchiveIndex(type, toId, store);
if (index < 0) {
index = findEmptyArchive(store, 0);
System.out.println("Creating new region - id=" + index + "!");
}
store.getIndexes()[MAP_INDEX].putFile(index, 0, Constants.GZIP_COMPRESSION, bs, type == LAND_TYPE ? XTEA_KEYS : null, true, true, getNameHash(type, toId), -1);
}
/**
* Replaces objects.
* @param changes The array of object changes.
* @throws Throwable when an exception occurs.
*/
static void replaceObjects(GameObject[][] changes) throws Throwable {
Map<Integer, Map<GameObject, GameObject>> objects = new HashMap<>();
for (int i = 0; i < changes.length; i++) {
GameObject old = changes[i][0];
int regionId = (old.loc.x >> 6) << 8 | (old.loc.y >> 6);
old = old.getLocal();
Map<GameObject, GameObject> map = objects.get(regionId);
if (map == null) {
objects.put(regionId, map = new HashMap<>());
}
GameObject replace = changes[i][1];
if (replace != null) {
replace = replace.getLocal();
}
map.put(old, replace);
}
int count = 0;
for (int regionId : objects.keySet()) {
Map<GameObject, GameObject> replacements = objects.get(regionId);
ObjectMap map = new ObjectMap();
map.map(new InputStream(getLandscape(regionId, store, XTEA_KEYS)));
for (GameObject object : replacements.keySet()) {
GameObject current = map.get(object);
if (current == null) {
throw new IllegalArgumentException("Could not find object " + object + "!");
}
map.getObjects().remove(current);
current = replacements.get(object);
if (current != null) {
map.getObjects().add(current);
}
count++;
}
packLandscape(regionId, map.generate(), store, XTEA_KEYS);
}
System.out.println("Changed " + count + " objects in " + objects.size() + " regions!");
}
/**
* Packs the landscape.
* @param regionId The region id to pack on.
* @param data The landscape data to pack.
* @param store The store used.
* @param xtea The XTEA keys.
*/
private static void packMapscape(int regionId, byte[] data, Store store) {
int index = getArchiveIndex(MAP_TYPE, regionId, store);
store.getIndexes()[MAP_INDEX].putFile(index, 0, Constants.GZIP_COMPRESSION, data, null, true, true, getNameHash(MAP_TYPE, regionId), -1);
}
/**
* Packs the landscape.
* @param regionId The region id to pack on.
* @param data The landscape data to pack.
* @param store The store used.
* @param xtea The XTEA keys.
*/
private static void packLandscape(int regionId, byte[] data, Store store, int[] xtea) {
int index = getArchiveIndex(LAND_TYPE, regionId, store);
store.getIndexes()[MAP_INDEX].putFile(index, 0, Constants.GZIP_COMPRESSION, data, xtea, true, true, getNameHash("l", regionId), -1);
}
/**
* Gets the landscape data.
* @param regionId The region id.
* @param store The store to get the landscape data from.
* @param xtea The XTEA keys used to decrypt the landscape.
* @return The landscape data.
*/
private static byte[] getLandscape(int regionId, Store store, int[] xtea) {
int index = getArchiveIndex(LAND_TYPE, regionId, store);
if (index < 0) {
throw new IllegalArgumentException("Region " + regionId + " does not exist!");
}
byte[] bs = store.getIndexes()[MAP_INDEX].getFile(index, 0, xtea);
if (bs == null) {
throw new IllegalArgumentException("Region " + regionId + " has no valid landscape!");
}
return bs;
}
/**
* Finds an empty archive id.
* @param store The store to check.
* @param offset The archive offset to start checking from.
* @return The new archive index.
*/
private static int findEmptyArchive(Store store, int offset) {
for (int index = offset; index < 50000; index++) {
if (!store.getIndexes()[MAP_INDEX].archiveExists(index)) {
return index;
}
}
return -1;
}
/**
* Gets the name hash for the given region id.
* @param type The archive type "m"=mapscape, "l"=landscape.
* @param regionId The region id.
* @return The name hash.
*/
private static int getNameHash(String type, int regionId) {
int x = regionId >> 8 & 0xFF;
int y = regionId & 0xFF;
return Utils.getNameHash(type + x + "_" + y);
}
/**
* Gets the archive index.
* @param type The archive type "m"=mapscape, "l"=landscape.
* @param regionId The region id.
* @param store The store.
* @return The archive index.
*/
private static int getArchiveIndex(String type, int regionId, Store store) {
int x = regionId >> 8 & 0xFF;
int y = regionId & 0xFF;
return store.getIndexes()[MAP_INDEX].getArchiveId(type + x + "_" + y);
}
/**
* The main method.
* @param args The arguments cast on runtime.
* @throws Throwable When an exception occurs.
*/
public static void main(String...args) throws Throwable {
String revision = "498";
if (args.length > 0) {
revision = args[0];
}
System.out.println("Updating revision " + revision + "...");
long start = System.currentTimeMillis();
store = new Store("./" + revision + "/");
update();
System.out.println("Finished after " + (System.currentTimeMillis() - start) + " milliseconds.");
}
/**
* Checks if the region is valid.
* @param regionId The region id.
* @param store The store.
* @return {@code True} if so.
*/
public static boolean isValid(int regionId, int[] xtea, Store store) {
int index = getArchiveIndex("l", regionId, store);
if (index > -1) {
byte[] bs = store.getIndexes()[MAP_INDEX].getFile(index, 0, xtea);
if (bs == null) {
if (regionId == 11082) { //Elf city is an empty region
return true;
}
ByteBuffer buffer = ByteBuffer.wrap(store.getIndexes()[5].getFile(getArchiveIndex("m", regionId, store), 0));
byte[][][] mapscape = new byte[4][64][64];
boolean ocean = true;
main: for (int z = 0; z < 4; z++) {
for (int i = 0; i < 64; i++) {
for (int j = 0; j < 64; j++) {
while (true) {
int value = buffer.get() & 0xFF;
if (value == 0) {
break;
}
if (value == 1) {
buffer.get();
break;
}
if (value <= 49) {
int overlay = buffer.get() & 0xFF;
OverlayDefinition def = OverlayDefinition.forId(store, overlay);
if (def != null && def.getTextureId() != 25) {
ocean = false;
break main;
}
} else if (value <= 81) {
mapscape[z][i][j] = (byte) (value - 49);
}
}
}
}
}
if (!ocean) {
return false;
}
}
return true;
}
return false;
}
/**
* Debugs the world map.
*/
static void debugWorldMap() {
int regions = 0;
int missing = 0;
for (int x = 0; x < 255; x++) {
for (int y = 0; y < 255; y++) {
int regionId = x << 8 | y;
if (!isValid(regionId, XTEA_KEYS, store)) {
missing++;
System.out.println("Missing region " + regionId + "!");
}
}
}
System.out.println("World map is missing " + missing + "/" + regions + " regions!");
}
}

View file

@ -0,0 +1,195 @@
package emperor;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import javax.imageio.ImageIO;
import alex.cache.loaders.OverlayDefinition;
import com.alex.loaders.images.IndexedColorImageFile;
import com.alex.store.Store;
/**
* Packs the models.
* @author Emperor
*
*/
public final class ModelPacker {
public static void main(String...args) throws Throwable {
Store to = new Store("./498/");
packDonatorIcons(to);
// packObjectDefinitions(from, to);
// packAnimations(from, to);
// List<Integer> anims = new ArrayList<>();
// for (int i = 0; i < 50_000; i++) {
// byte[] data = from.getIndexes()[16].getFile(i >>> 1998118472, i & 0xff);
// if (data == null) {
// continue;
// }
// ObjectDefinitions def = new ObjectDefinitions(i);
// def.initialize(from);
// if (def.animationId > -1) {
// if (!anims.contains(def.animationId)) {
// anims.add(def.animationId);
// }
//// System.out.println(def.getName() + " anim: " + def.animationId + ", " + Arrays.toString(def.models));
// }
// }
// System.out.println(Arrays.toString(anims.toArray()));
// packAnimations(from, to);
}
static void packObjectDefinitions(Store from, Store to) {
int[] defs = new int[] { 5461 };//5099, 5100, 5094, 5096, 5098, 5097, 5110, 5111};//5088, 5089, 5090 };
for (int id : defs) {
int archive = id >>> 1998118472;
int file = id & 0xFF;
byte[] bs = from.getIndexes()[16].getFile(archive, file);
to.getIndexes()[16].putFile(archive, file, bs);
}
}
static void editObjectDefinitions(int itemId, Store store, int opcode, Object value) {
int archive = itemId >>> 1998118472;
int file = itemId & 0xFF;
byte[] bs = store.getIndexes()[16].getFile(archive, file);
ByteBuffer buffer = ByteBuffer.allocate(bs.length + 128);
for (int i = 0; i < bs.length - 1; i++) {
buffer.put(bs[i]);
}
buffer.put((byte) opcode);
if (value instanceof Byte) {
buffer.put((Byte) value);
}
else if (value instanceof Short) {
buffer.putShort((Short) value);
}
else if (value instanceof Integer) {
buffer.putInt((Integer) value);
}
else if (value instanceof Long) {
buffer.putLong((Long) value);
}
else if (value instanceof String) {
buffer.put(((String) value).getBytes()).put((byte) 0);
}
else if (value instanceof Boolean) {
buffer.put((byte) ((Boolean) value ? 1 : 0));
}
bs = new byte[buffer.remaining()];
buffer.get(bs);
store.getIndexes()[16].putFile(archive, file, bs);
}
static void packSprite(Store to) {
int id = 423;
IndexedColorImageFile f = null;
try {
f = new IndexedColorImageFile(to, id, 0);
BufferedImage icon = ImageIO.read(new File("green.png"));
f.replaceImage(icon, 3);
//System.out.println("Added icon: "+f.addImage(icon, 0, 1)+".");
} catch (IOException e) {
e.printStackTrace();
}
to.getIndexes()[8].putFile(id, 0, f.encodeFile());
}
static void packDonatorIcons(Store to) {
int id = 423;
File[] files = new File("donator_icons").listFiles();
IndexedColorImageFile f = null;
int index = 0;
for (File file : files) {
try {
f = new IndexedColorImageFile(to, id, 0);
BufferedImage icon = ImageIO.read(file);
if (index == 0) {
f.replaceImage(icon, 3);
System.out.println("Replaced icon - " + 3);
} else {
System.out.println("Added icon: "+f.addImage(icon, 0, 1)+".");
}
} catch (IOException e) {
e.printStackTrace();
}
to.getIndexes()[8].putFile(id, 0, f.encodeFile());
index++;
}
}
static void packAnimations(Store from, Store to) {
int [] anims = new int[] {4856};//3206, 498, 499, 500, 501, 481, 467, 526, 527, 907, 505, 524, 449, 523, 2709, 1726, 480, 488, 479, 469, 475, 476, 473, 1071, 493, 494, 504, 471, 468, 470, 332, 333, 492, 1731, 472, 491, 503, 522, 456, 464, 2714, 9101, 502, 525, 6023, 6561, 477, 478, 1223, 446, 6913, 912, 917, 474, 1051, 1049, 4860, 1052, 1073, 9123, 3106, 1072, 1096, 1098, 1097, 1103, 1104, 1108, 1112, 1127, 1138, 1211, 1212, 1216, 1233, 1234, 1235, 1231, 1260, 1261, 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 8618, 1334, 1433, 1347, 1349, 1348, 1362, 1355, 1416, 1398, 1411, 1430, 1431, 1532, 1533, 1600, 1631, 1629, 1632, 1630, 1636, 1657, 1641, 1642, 1643, 1729, 1733, 1727, 1017, 1734, 1730, 1732, 1747, 1812, 1845, 1846, 1847, 1869, 1868, 1875, 1881, 1908, 1909, 1923, 1915, 1943, 1940, 1936, 1937, 1938, 1939, 1944, 1998, 1999, 2056, 2054, 2091, 2131, 2133, 2136, 2135, 2137, 2178, 2260, 2174, 2173, 2199, 2198, 2196, 2201, 2203, 2204, 2209, 2210, 2212, 5855, 2313, 2331, 2346, 2359, 2360, 2349, 2350, 2348, 2379, 2440, 2439, 2437, 2451, 2564, 4291, 3743, 2598, 4123, 2600, 2641, 2657, 2699, 2708, 2734, 2746, 2747, 2742, 2743, 2744, 2768, 447, 2807, 2870, 2871, 2878, 2883, 2897, 2899, 2901, 2898, 2900, 2905, 2997, 3022, 3029, 3028, 3030, 3038, 3070, 3099, 3100, 3095, 3105, 3107, 3101, 3097, 3104, 3113, 3174, 3173, 3180, 4354, 3217, 3218, 3219, 3172, 3230, 3231, 3237, 3246, 3247, 3264, 6094, 3304, 3305, 3306, 3343, 3347, 3511, 7263, 3349, 3351, 3352, 3408, 3405, 3406, 3407, 3438, 3439, 3440, 3445, 3472, 3528, 3534, 3529, 3530, 3531, 3532, 3478, 3542, 3558, 4477, 4564, 3586, 3573, 3577, 3117, 3118, 5483, 166, 286, 145, 3707, 6218, 6496, 1338, 9241, 3587, 3582, 3647, 3720, 3644, 3646, 3648, 3578, 3579, 3580, 3581, 3615, 3616, 3742, 3835, 3843, 3927, 3932, 3939, 3940, 3943, 3944, 3976, 3998, 4005, 4006, 4015, 4013, 4014, 4022, 3699, 3698, 3700, 4133, 4132, 6477, 4126, 4157, 4161, 4163, 4220, 4217, 4218, 4239, 4260, 4241, 4240, 4242, 4274, 4284, 4308, 4309, 4323, 4324, 4325, 4338, 4339, 4336, 4335, 459, 4357, 4355, 4356, 4358, 4393, 4392, 4408, 4394, 4395, 4396, 4397, 4398, 4377, 4359, 4361, 4360, 4363, 4364, 4399, 4431, 4535, 4565, 4566, 4567, 4568, 4569, 4577, 4557, 4559, 4560, 4563, 4561, 4562, 4572, 4571, 4595, 4599, 4621, 4622, 4627, 4628, 4746, 4747, 4778, 4744, 4745, 4743, 4781, 4798, 4783, 4894, 4879, 4880, 4881, 4895, 4896, 4899, 4883, 4897, 4898, 4900, 4901, 5012, 5044, 5073, 5058, 5141, 5109, 5170, 5169, 5173, 5174, 5175, 5179, 5180, 5176, 5177, 5178, 5197, 5193, 5195, 5196, 5194, 5203, 5220, 5219, 5222, 5221, 5235, 5237, 5239, 5260, 5261, 5267, 5269, 5268, 5271, 5270, 5278, 5308, 5295, 5296, 5297, 5350, 5351, 5360, 5068, 5430, 5415, 5422, 5423, 5429, 5431, 5432, 5603, 5599, 5601, 5600, 5598, 5605, 5631, 5604, 5564, 5740, 5742, 5737, 5745, 5743, 5744, 5738, 5728, 5730, 5729, 5739, 5741, 5734, 5771, 5772, 5768, 5797, 5798, 5828, 5829, 5830, 5844, 5824, 5825, 5847, 5900, 5901, 5906, 5874, 5857, 5909, 5975, 5976, 5977, 5983, 5984, 5985, 5974, 6015, 6069, 6037, 6038, 6036, 6035, 6034, 6029, 6031, 6032, 6027, 6028, 6024, 6025, 6026, 6039, 6123, 6211, 6161, 6162, 6163, 6164, 6165, 6166, 6167, 6168, 6170, 6196, 6269, 6274, 6481, 4130, 4128, 4131, 4129, 6491, 4127, 4125, 6495, 6493, 6494, 6466, 6467, 6492, 4124, 6426, 6461, 6453, 6439, 6522, 6497, 6499, 6500, 6509, 6506, 6523, 6623, 6624, 6625, 6626, 6627, 6597, 6598, 6635, 6637, 6636, 6638, 6639, 6645, 6646, 6652, 6653, 6656, 6737, 6732, 6731, 6733, 6734, 6735, 6736, 6854, 6853, 6873, 6874, 6875, 6912, 6914, 6915, 4782, 6925, 6900, 6901, 6902, 6903, 6917, 6898, 6890, 6891, 6892, 6893, 6894, 6895, 6931, 6932, 6982, 6995, 6996, 7007, 7066, 7067, 7087, 7097, 7118, 7115, 7117, 7120, 7138, 7144, 7146, 7152, 7225, 7226, 7245, 7252, 7231, 7291, 7286, 7283, 7284, 7285, 7352, 7354, 7353, 7361, 7346, 7357, 7356, 7358, 7360, 7375, 7373, 7378, 7379, 7380, 7381, 7544, 7546, 7552, 7577, 7603, 7601, 7580, 7602, 7600, 8526, 8510, 8663, 8664, 8666, 8665, 8653, 8624, 8646, 8654, 8647, 8667, 2418, 8708, 8714, 8735, 7158, 808, 8881, 8845, 8857, 8894, 8892, 8897, 8967, 8968, 8969, 8970, 8972, 8971, 9005, 9011, 9007, 9010, 9008, 9090, 9088, 9089, 9085, 9083, 9084, 9033, 9035, 9036, 9041, 9135, 9122, 4290, 4295, 4296, 9137, 9143, 9144, 9150, 9146, 4297, 9154, 9199, 9303, 9348, 9329, 9330, 9347};
for (int i : anims) {
byte[] a = from.getIndexes()[20].getFile(i >>> 7, i & 0x7F);
if (a == null) {
continue;
}
// i = 10222;//from.getIndexes()[20].getLastArchiveId() + 1;
System.out.println("Packed animation " + i + " - " + to.getIndexes()[20].putFile(i >>> 7, i & 0x7F, a));
}
}
static void packTextures(Store from, Store to) {
for (int i = 0; i < from.getIndexes()[9].getValidFilesCount(0); i++) {
byte[] bs = from.getIndexes()[9].getFile(0, i);
if (bs == null || bs.length < 1) {
System.out.println("Missing texture id " + i);
continue;
}
System.out.println("Packing texture id " + i + ": " + to.getIndexes()[9].putFile(0, i, bs));//+ (i < 200 ? Arrays.toString(bs) : null));//to.getIndexes()[6].putFile(0, i, bs));
}
}
/**
* Packs the overlays.
* @param from The cache to get the data from.
* @param to The cache to store the data.
*/
static void packOverlays(Store from, Store to) {
System.out.println("Start");
// int changeOverlay = 135;
// int newOverlay = 135;
// System.out.println("Success = " + to.getIndexes()[2].putFile(4, changeOverlay, from.getIndexes()[2].getFile(4, newOverlay)));
for (int id = 0; id < to.getIndexes()[2].getValidFilesCount(4); id++) {
byte[] bs = to.getIndexes()[2].getFile(4, id);
if (bs == null || bs.length < 1) {
continue;
}
OverlayDefinition def = OverlayDefinition.forId(to, id);
if (def.getTextureId() > 0) {
System.out.println("Packed overlay definition " + id + " - texture=" + def.getTextureId() + "!");
// boolean success = to.getIndexes()[2].putFile(4, id, from.getIndexes()[2].getFile(4, id));
// System.out.println("Packed overlay definition " + id + " - success=" + success);
}
}
}
static void packModels(Store from, Store to) {
int[] models = new int[] {16400};
for (int model : models) {
byte[] a = from.getIndexes()[7].getFile(model);
if (a == null) {
continue;
}
System.out.println(Arrays.toString(a) + "");
to.getIndexes()[7].putFile(1046, 0, a);
break;
}
}
static void packMusic(Store from, Store to) throws Throwable {
for (int i = 0; i < to.getIndexes()[6].getValidArchivesCount(); i++) {
byte[] bs = to.getIndexes()[6].getFile(i);
if (bs == null || bs.length < 1) {
continue;
}
System.out.println("Packing music id " + i + ": ");// + to.getIndexes()[6].putArchive(i, from));//.putArchive(2, , from));
}
}
}

View file

@ -0,0 +1,406 @@
package emperor;
import com.alex.loaders.clientscripts.CS2Mapping;
import com.alex.store.Store;
public final class MusicPropertiesPacker {
/**
* The music zones.
*/
/**
* Configures the music data.
*/
private static void configureMusic() {
//Don't remove anything from this!
//Also make sure zones don't overlap!
add(40, "brew hoo hoo!", 338, (14747));
add(53, "chef surprise", 399, (7507));
add(76, "davy jones' locker", 394, (11924));
add(102, "etceteria", 227, (10300));
add(156, "hells bells", 254, (11066));
add(175, "jolly-r", 65, (11058));
add(189, "land of the dwarves", 310, (11423));
add(205, "mad eadgar", 213, (11677));
add(254, "pharaoh's tomb", 355, (13356), (12105));
add(259, "pirates of peril", 262, (12093));
add(304, "spirits of elid", 331, (13461));
add(318, "subterranea", 362, (10142));
add(322, "tale of keldagrim", 309, (11678));
add(323, "talking forest", 119, (10550));
add(328, "cellar dwellers", 342, (10135));
add(329, "chosen", 324, (9805));
add(330, "desert", 120, (12591));
add(331, "desolate isle", 330, (10042));
add(333, "far side", 314, (12111));
add(335, "genie", 332, (13457));
add(336, "the golem", 295, (13616), (13872));
add(338, "the lost melody", 315, (13206));
add(341, "the mad mole", 393, (6992));
add(342, "monsters below", 329, (9886));
add(343, "the navigator", 255, (10652));
add(345, "other side", 278, (14646));
add(347, "quiz master", 318, (7754));
add(348, "rogues' den", 313, (11853), (12109));
add(349, "shadow", 121, (11314));
add(350, "the slayer", 269, (11164));
add(351, "terrible tower", 267, (13623));
add(352, "tower", 122, (10292), (10136));
add(360, "tomorrow", 163, (12081));
add(361, "too many cooks...", 398, (11930));
add(413, "zogre dance", 306, (9775));
add(2, "adventure", 0, (12854));
add(5, "alone", 2, (12086), (10134));
add(6, "ambient jungle", 3, (11310));
add(7, "anywhere", 240, (10795));
add(11, "arabique", 7, (11417));
add(12, "army of darkness", 8, (12088));
add(13, "arrival", 9, (11572));
add(14, "artistry", 200, (8010));
add(15, "attack 1", 10, (10034));
add(16, "attack 2", 11, (11414));
add(17, "attack 3", 12, (12192));
add(18, "attack 4", 13, (10289), (10389));
add(19, "attack 5", 14, (9033));
add(20, "attack 6", 15, (10387));
add(21, "attention", 16, (11825));
add(22, "autumn voyage", 17, (12851));
add(23, "aye car rum ba", 351, (8527));
add(24, "aztec", 201, (11157));
add(25, "background", 18, (11060), (7758));
add(26, "ballad of enchantment", 19, (10290));
add(27, "bandit camp", 214, (12590));
add(28, "barbarianism", 257, (12341), (12441));
add(29, "barking mad", 274, (14234));
add(30, "baroque", 20, (10547));
add(31, "beyond", 21, (11418), (11419));
add(32, "big chords", 22, (10032));
add(33, "blistering barnacles", 352, (8528));
add(34, "body parts", 270, (13979));
add(35, "bone dance", 183, (13619));
add(36, "bone dry", 216, (12946));
add(37, "book of spells", 23, (12593));
add(38, "borderland", 233, (10809));
add(39, "breeze", 194, (9010));
add(42, "bubble and squeak", 347, (7753));
add(43, "camelot", 24, (11062));
add(44, "castlewars", 247, (9520));
add(45, "catch me if you can", 344, (10646));
add(46, "cave background", 25, (12184), (11929));
add(47, "cave of beasts", 280, (11165));
add(48, "cave of the goblins", 304, (12693));
add(49, "cavern", 26, (12193), (10388));
add(50, "cellar song", 173, (12697));
add(51, "chain of command", 27, (10648), (10905));
add(52, "chamber", 225, (10821), (11078));
add(54, "chickened out", 395, (9796));
add(55, "chompy hunt", 178, (10542), (10642));
add(56, "city of the dead", 300, (12843), (13099));
add(57, "claustrophobia", 291, (9293));
add(58, "close quarters", 175, (12602));
add(59, "competition", 217, (8781));
add(60, "complication", 258, (9035));
add(61, "contest", 208, (11576));
add(62, "corporal punishment", 323, (12619));
add(64, "courage", 260, (11673));
add(65, "crystal castle", 210, (9011));
add(66, "crystal cave", 28, (9797));
add(67, "crystal sword", 29, (12855), (10647));
add(68, "cursed", 186, (9623));
add(69, "dagannoth dawn", 365, (7236), (7748));
add(71, "dance of the undead", 298, (14131));
add(72, "dangerous road", 263, (11413));
add(73, "dangerous way", 299, (14231));
add(74, "dangerous", 30, (12343), (13115));
add(75, "dark", 31, (13113));
add(77, "dead can dance", 341, (12601));
add(78, "dead quiet", 181, (13621), (9294));
add(79, "deadlands", 230, (14134));
add(80, "deep down", 224, (10823), (10822));
add(81, "deep wildy", 32, (11835));
add(82, "desert heat", 333, (13614));
add(83, "desert voyage", 33, (13102), (13359));
add(84, "diango's little helpers", 371, (8005));
add(86, "distant land", 353, (13873));
add(89, "doorways", 34, (12598));
add(90, "down below", 284, (12438));
add(91, "down to earth", 259, (10571));
add(92, "dragontooth island", 281, (15159));
add(93, "dream", 35, (12594));
add(95, "dunjun", 36, (11672));
add(96, "dynasty", 275, (13358));
add(98, "elven mist", 202, (9266));
add(99, "emotion", 38, (10033), (10309), (10133));
add(100, "emperor", 39, (11570), (11670));
add(101, "escape", 176, (10903));
add(103, "everlasting fire", 417, (13373));
add(104, "everywhere", 219, (8499));
add(105, "evil bob's island", 316, (10058));
add(106, "expanse", 40, (12605), (12852), (12952));
add(107, "expecting", 41, (9778), (9878));
add(108, "expedition", 42, (11676));
add(109, "exposed", 220, (8752));
add(110, "faerie", 43, (9540));
add(111, "faithless", 265, (12856));
add(112, "fanfare", 44, (11828));
add(113, "fanfare 2", 162, (11823));
add(114, "fanfare 3", 45, (10545));
add(116, "far away", 292, (9265));
add(118, "fenkenstrain's refrain", 271, (13879));
add(119, "fight or flight", 293, (7752));
add(120, "find my way", 246, (10894));
add(121, "fire and brimstone", 334, (9552));
add(122, "fishing", 46, (11317));
add(123, "flute salad", 47, (12595));
add(125, "forbidden", 185, (13111));
add(126, "forest", 203, (9009));
add(127, "forever", 48, (12342), (12442));
add(130, "frogland", 336, (9802));
add(131, "frostbite", 236, (11323));
add(132, "fruits de mer", 273, (11059));
add(133, "funny bunnies", 406, (9810));
add(134, "gaol", 49, (12090), (10031), (10131));
add(135, "garden", 50, (12853));
add(136, "gnome king", 51, (9782));
add(138, "gnome village", 53, (9781));
add(139, "gnome village 2", 54, (9269));
add(141, "gnomeball", 56, (9270));
add(142, "goblin game", 252, (10393));
add(144, "greatness", 57, (12596));
add(146, "grotto", 198, (13720));
add(148, "grumpy", 177, (10286));
add(151, "harmony 2", 167, (12950));
add(152, "haunted mine", 222, (11077));
add(153, "have a blast", 325, (7757));
add(155, "heart and mind", 174, (10059));
add(157, "hermit", 191, (9034));
add(158, "high seas", 59, (11057));
add(159, "horizon", 60, (11573));
add(161, "iban", 61, (8519));
add(162, "ice melody", 165, (11318));
add(163, "in between", 290, (10061));
add(164, "in the brine", 370, (14638));
add(165, "in the clink", 360, (8261));
add(166, "in the manor", 62, (10287));
add(167, "in the pits", 335, (9808));
add(169, "insect queen", 212, (13972));
add(170, "inspiration", 63, (12087));
add(171, "into the abyss", 317, (12107));
add(172, "intrepid", 64, (9369));
add(173, "island life", 242, (10794));
add(176, "jungle island", 66, (11313), (11309));
add(177, "jungle troubles", 343, (11568));
add(178, "jungly 1", 67, (11054), (11154));
add(179, "jungly 2", 68, (10802));
add(180, "jungly 3", 69, (11055));
add(182, "kingdom", 190, (11319));
add(183, "knightly", 70, (10291));
add(184, "la mort", 192, (8779));
add(185, "lair", 229, (13975));
add(187, "lament", 381, (12433));
add(190, "landlubber", 169, (10801));
add(192, "lasting", 71, (10549));
add(193, "legend", 235, (10808));
add(194, "legion", 72, (12089), (10039));
add(196, "lighthouse", 251, (10040));
add(197, "lightness", 73, (12599));
add(198, "lightwalk", 74, (11061));
add(200, "lonesome", 149, (13203));
add(201, "long ago", 75, (10544));
add(202, "long way home", 76, (11826));
add(203, "lost soul", 204, (9008));
add(204, "lullaby", 77, (13365), (10551));
add(206, "mage arena", 78, (12349), (10057));
add(207, "magic dance", 79, (10288));
add(208, "magical journey", 80, (10805));
add(209, "making waves", 378, (9273), (9272));
add(211, "march", 81, (10036));
add(212, "marooned", 241, (11562), (12117));
add(213, "marzipan", 211, (11166), (11421));
add(214, "masquerade", 268, (10908));
add(216, "mausoleum", 184, (13722));
add(218, "medieval", 82, (13109));
add(219, "mellow", 83, (10293));
add(220, "melodrama", 248, (9776));
add(221, "meridian", 205, (8497));
add(223, "miles away", 84, (11571), (10569));
add(225, "miracle dance", 85, (11083));
add(226, "mirage", 303, (13199));
add(227, "miscellania", 226, (10044));
add(228, "monarch waltz", 86, (10807));
add(229, "monkey madness", 239, (11051));
add(230, "monster melee", 272, (12694));
add(231, "moody", 87, (12600), (9523));
add(232, "morytania", 180, (13622));
add(233, "mudskipper melody", 361, (11824));
add(234, "narnode's theme", 513, (9882));
add(235, "natural", 197, (13620), (9038));
add(236, "neverland", 88, (9780));
add(239, "nightfall", 90, (12861), (11827));
add(241, "no way out", 403, (13209), (12369), (12113));
add(242, "nomad", 171, (11056));
add(243, "null and void", 400, (10537));
add(245, "oriental", 91, (11666));
add(246, "out of the deep", 253, (10140));
add(247, "over to nardah", 328, (13613));
add(248, "overpass", 207, (9267));
add(249, "overture", 92, (10806));
add(250, "parade", 93, (13110));
add(251, "path of peril", 307, (10575));
add(253, "pest control", 401, (10536));
add(255, "phasmatys", 277, (14746));
add(256, "pheasant peasant", 321, (10314));
add(258, "principality", 188, (11575));
add(260, "quest", 94, (10315));
add(261, "rat a tat tat", 345, (11599));
add(262, "rat hunt", 349, (11343));
add(263, "ready for battle", 249, (9620));
add(264, "regal", 95, (13117));
add(265, "reggae", 96, (11565));
add(266, "reggae 2", 97, (11567));
add(267, "rellekka", 231, (10297));
add(269, "righteousness", 223, (9803));
add(270, "riverside", 98, (10803), (8496));
add(272, "romancing the crone", 264, (11068));
add(273, "romper chomper", 312, (9263));
add(274, "royale", 99, (11671));
add(275, "rune essence", 100, (11595));
add(276, "sad meadow", 101, (10035), (11081));
add(277, "saga", 232, (10296));
add(278, "sarcophagus", 283, (12945));
add(279, "sarim's vermin", 348, (11926));
add(280, "scape cave", 102, (12698), (12437));
add(283, "scape sad", 104, (13116));
add(286, "scape soft", 159, (11829));
add(287, "scape wild", 105, (12857), (12604));
add(288, "scarab", 282, (12589));
add(290, "sea shanty", 106, (11569));
add(289, "sea shanty 2", 107, (12082));
add(291, "serenade", 108, (9521));
add(292, "serene", 109, (11837), (11936), (11339));
add(293, "settlement", 279, (11065));
add(294, "shadowland", 228, (13618), (13875), (8526));
add(296, "shining", 160, (12858));
add(297, "shipwrecked", 276, (14391));
add(298, "showdown", 245, (10895));
add(300, "sojourn", 209, (11321));
add(301, "soundscape", 111, (9774));
add(302, "sphinx", 302, (13100));
add(303, "spirit", 112, (12597));
add(305, "splendour", 113, (11574));
add(306, "spooky jungle", 115, (11053), (11668));
add(307, "spooky", 114, (12340));
add(308, "spooky 2", 218, (13718));
add(309, "stagnant", 193, (13876), (8782));
add(310, "starlight", 116, (11925), (12949));
add(311, "start", 117, (12339));
add(312, "still night", 118, (13108));
add(313, "stillness", 250, (13977));
add(314, "stranded", 234, (11322));
add(316, "stratosphere", 195, (8523));
add(319, "sunburn", 215, (12846), (13357));
add(320, "superstition", 261, (11153));
add(324, "tears of guthix", 311, (12948));
add(325, "technology", 238, (10310));
add(326, "temple of light", 294, (7496));
add(327, "temple", 243, (11151));
add(353, "theme", 123, (10294), (10138));
add(355, "time out", 196, (11591));
add(356, "time to mine", 289, (11422));
add(357, "tiptoe", 266, (12440));
// add(358, "title fight", 367, (12696));
add(362, "trawler minor", 125, (7755));
add(363, "trawler", 124, (7499));
add(364, "tree spirits", 126, (9268));
add(365, "tremble", 189, (11320));
add(367, "tribal background", 127, (11312), (11412));
add(368, "tribal", 128, (11311));
add(366, "tribal 2", 129, (11566));
add(369, "trinity", 130, (10804), (10904));
add(371, "troubled", 131, (11833));
add(372, "twilight", 179, (10906));
add(373, "tzhaar!", 339, (9551));
add(374, "undercurrent", 170, (12345));
add(376, "underground pass", 134, (9621));
add(375, "underground", 132, (13368), (11416));
add(377, "understanding", 187, (9547));
add(378, "unknown land", 133, (12338));
add(379, "upcoming", 135, (10546));
add(380, "venture", 136, (13364));
add(381, "venture 2", 168, (13464));
add(382, "victory is mine", 368, (12696));
add(383, "village", 182, (13878));
add(384, "vision", 137, (12337), (12436));
add(385, "voodoo cult", 138, (9545), (11665));
add(386, "voyage", 139, (10038));
add(388, "wander", 140, (12083));
add(389, "warrior", 237, (10653));
add(391, "waterfall", 141, (10037), (10137));
add(392, "waterlogged", 199, (13877), (8014));
add(394, "wayward", 308, (9875));
add(396, "well of voyage", 221, (9366));
add(397, "wild side", 340, (12092));
add(398, "wilderness", 142, (11832), (12346));
add(399, "wilderness 2", 143, (12091));
add(400, "wilderness 3", 144, (11834));
add(401, "wildwood", 256, (12344));
add(402, "witching", 145, (13114));
add(403, "woe of the wyvern", 369, (12181));
add(405, "wonder", 146, (11831));
add(406, "wonderous", 147, (10548));
add(407, "woodland", 206, (8498));
add(408, "workshop", 148, (12084));
add(410, "xenophobe", 366, (7492), (11589));
add(411, "yesteryear", 161, (12849));
add(412, "zealot", 172, (10827));
//Al kharid/desert
add(3, "al kharid", 1, (13105), (13361));
add(8, "arabian2", 5, (13107));
add(9, "arabian3", 6, (12848));
add(10, "arabian", 4, (13106), (13617));
add(94, "duel arena", 164, (13362));
add(295, "shine", 110, (13363));
add(97, "egypt", 37, (13104));
//Brimhaven
add(1, "7th realm", 285, (10645), (10644));
add(181, "karamja jam", 286, (10900), (10899));
add(252, "pathways", 287, (10901));
//Tutorial island
// add(237, "newbie melody", 89, new ZoneBorders(3052, 3055, 3155, 3135));
//Lumbridge
add(150, "harmony", 58, (12850));
}
static CS2Mapping indexes;
static CS2Mapping ids;
/**
* Adds a new music entry.
* @param musicId The music id.
* @param name The song name.
* @param index The list index.
* @param borders The zone borders.
*/
private static void add(int musicId, String name, int index, int... regions) {
String n = (String) indexes.getMap().get(index);
System.out.print("add(" + ids.getMap().get(index) + ", \"" + n + "\", " + index);
for (int id : regions) {
System.out.print(", forRegion(" + id + ")");
}
System.out.println(");");
}
/**
* The main method.
* @param args The arguments cast on runtime.
* @throws Throwable When an exception occurs.
*/
public static void main(String[] args) throws Throwable {
Store store = new Store("./666/");
indexes = CS2Mapping.forId(1345, store);
ids = CS2Mapping.forId(1351, store);
configureMusic();
}
}

View file

@ -0,0 +1,207 @@
package emperor;
import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
import com.alex.io.InputStream;
import com.alex.io.OutputStream;
/**
* Represents an object map.
* @author Emperor
*
*/
public final class ObjectMap {
private List<GameObject> objects = new ArrayList<>();
public void add(int id, int x, int y, int z, int type, int rotation) {
objects.add(new GameObject(id, x, y, z, type, rotation));
}
public GameObject get(GameObject object) {
return get(object.id, object.loc.x, object.loc.y, object.loc.z, object.type, object.rotation);
}
public GameObject get(int id, int x, int y, int z, int type, int rotation) {
for (GameObject object : objects) {
Location loc = object.loc;
if (object.id == id && loc.x == x && loc.y == y && loc.z == z && object.type == type && object.rotation == rotation) {
return object;
}
}
return null;
}
public List<GameObject> getObjects() {
return objects;
}
public static void compare(ObjectMap map, ObjectMap m) {
if (map.objects.size() != m.objects.size()) {
System.err.println("Mismatch [s1=" + map.objects.size() + ", s2=" + m.objects.size() + "]!");
return;
}
Queue<GameObject> queue1 = new PriorityQueue<>(map.objects);
Queue<GameObject> queue2 = new PriorityQueue<>(m.objects);
while (!queue1.isEmpty()) {
int id = queue1.peek().id;
int id1 = queue2.peek().id;
if (id != id1) {
System.err.println("Object id mismatch [o1=" + id + ", o2=" + id1 + "]!");
return;
}
Queue<QueueEntry> entry = new PriorityQueue<>();
Queue<QueueEntry> entry1 = new PriorityQueue<>();
while (!queue1.isEmpty() && (queue1.peek().id == id)) {
entry.add(new QueueEntry(queue1.poll()));
}
while (!queue2.isEmpty() && (queue2.peek().id == id)) {
entry1.add(new QueueEntry(queue2.poll()));
}
if (entry.size() != entry1.size()) {
System.err.println("Entry mismatch [s1=" + entry.size() + ", s2=" + entry1.size() + "]!");
return;
}
while (!entry.isEmpty()) {
GameObject object = entry.poll().object;
GameObject object1 = entry1.poll().object;
if (object.loc.getHash() != object1.loc.getHash()) {
System.err.println("Location mismatch " + id + "!");
return;
}
if (object.rotation != object1.rotation) {
System.err.println("Rotation mismatch " + id + "!");
return;
}
if (object.type != object1.type) {
System.err.println("Type mismatch " + id + "!");
return;
}
}
}
System.out.println("Matching object maps [s1=" + map.objects.size() + ", s2=" + m.objects.size() + "]!");
}
public void map(InputStream stream) {
int objectId = -1;
for (;;) {
int offset = stream.readSmart2();
if (offset == 0) {
break;
}
objectId += offset;
int location = 0;
for (;;) {
offset = stream.readUnsignedSmart();
if (offset == 0) {
break;
}
location += offset - 1;
int y = location & 0x3f;
int x = location >> 6 & 0x3f;
int configuration = stream.readUnsignedByte();
int rotation = configuration & 0x3;
int type = configuration >> 2;
int z = location >> 12;
if (x >= 0 && y >= 0 && x < 64 && y < 64) {
add(objectId, x, y, z, type, rotation);
} else {
System.out.println("Object out of bounds: " + objectId + " - " + x + ", " + y + ", " + z);
}
}
}
}
public byte[] generate() {
OutputStream stream = new OutputStream();
PriorityQueue<GameObject> queue = new PriorityQueue<>(objects);
int offset = -1;
while (!queue.isEmpty()) {
int id = queue.peek().id;
Queue<QueueEntry> entry = new PriorityQueue<>();
while (!queue.isEmpty() && (queue.peek().id == id)) {
entry.add(new QueueEntry(queue.poll()));
}
stream.writeSmart2(id - offset);
int location = 0;
while (!entry.isEmpty()) {
GameObject object = entry.poll().object;
stream.writeSmart(1 + (object.loc.getHash() - location));
stream.writeByte(object.rotation | object.type << 2);
location = object.loc.getHash();
}
stream.writeSmart(0);
offset = id;
}
stream.writeSmart2(0);
byte[] bs = new byte[stream.getOffset()];
for (int i = 0; i < stream.getOffset(); i++) {
bs[i] = stream.getBuffer()[i];
}
return bs;
}
public static class GameObject implements Comparable<GameObject> {
int id;
Location loc;
int type;
int rotation;
public GameObject(int id, int x, int y, int z, int type, int rotation) {
this.id = id;
this.loc = new Location(x, y, z);
this.type = type;
this.rotation = rotation;
}
public GameObject getLocal() {
return new GameObject(id, loc.getRegionX(), loc.getRegionY(), loc.z, type, rotation);
}
@Override
public int compareTo(GameObject o) {
return id - o.id;
}
@Override
public String toString() {
return id + ", " + type + ", " + rotation;
}
}
public static class QueueEntry implements Comparable<QueueEntry> {
GameObject object;
public QueueEntry(GameObject object) {
this.object = object;
}
@Override
public int compareTo(QueueEntry o) {
return object.loc.getHash() - o.object.loc.getHash();
}
}
public static class Location {
int x;
int y;
int z;
public Location(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public int getRegionX() {
return x - ((x >> 6) << 6);
}
public int getRegionY() {
return y - ((y >> 6) << 6);
}
public int getHash() {
return z << 12 | x << 6 | y;
}
}
}

View file

@ -0,0 +1,247 @@
package net.jpountz.lz4;
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static net.jpountz.lz4.LZ4BlockOutputStream.COMPRESSION_LEVEL_BASE;
import static net.jpountz.lz4.LZ4BlockOutputStream.COMPRESSION_METHOD_LZ4;
import static net.jpountz.lz4.LZ4BlockOutputStream.COMPRESSION_METHOD_RAW;
import static net.jpountz.lz4.LZ4BlockOutputStream.DEFAULT_SEED;
import static net.jpountz.lz4.LZ4BlockOutputStream.HEADER_LENGTH;
import static net.jpountz.lz4.LZ4BlockOutputStream.MAGIC;
import static net.jpountz.lz4.LZ4BlockOutputStream.MAGIC_LENGTH;
import java.io.EOFException;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.Checksum;
import net.jpountz.util.Utils;
import net.jpountz.xxhash.StreamingXXHash32;
import net.jpountz.xxhash.XXHash32;
import net.jpountz.xxhash.XXHashFactory;
/**
* {@link InputStream} implementation to decode data written with
* {@link LZ4BlockOutputStream}. This class is not thread-safe and does not
* support {@link #mark(int)}/{@link #reset()}.
* @see LZ4BlockOutputStream
*/
public final class LZ4BlockInputStream extends FilterInputStream {
private final LZ4FastDecompressor decompressor;
private final Checksum checksum;
private byte[] buffer;
private byte[] compressedBuffer;
private int originalLen;
private int o;
private boolean finished;
/**
* Create a new {@link InputStream}.
*
* @param in the {@link InputStream} to poll
* @param decompressor the {@link LZ4FastDecompressor decompressor} instance to
* use
* @param checksum the {@link Checksum} instance to use, must be
* equivalent to the instance which has been used to
* write the stream
*/
public LZ4BlockInputStream(InputStream in, LZ4FastDecompressor decompressor, Checksum checksum) {
super(in);
this.decompressor = decompressor;
this.checksum = checksum;
this.buffer = new byte[0];
this.compressedBuffer = new byte[HEADER_LENGTH];
o = originalLen = 0;
finished = false;
}
/**
* Create a new instance using {@link XXHash32} for checksuming.
* @see #LZ4BlockInputStream(InputStream, LZ4FastDecompressor, Checksum)
* @see StreamingXXHash32#asChecksum()
*/
public LZ4BlockInputStream(InputStream in, LZ4FastDecompressor decompressor) {
this(in, decompressor, XXHashFactory.fastestInstance().newStreamingHash32(DEFAULT_SEED).asChecksum());
}
/**
* Create a new instance which uses the fastest {@link LZ4FastDecompressor} available.
* @see LZ4Factory#fastestInstance()
* @see #LZ4BlockInputStream(InputStream, LZ4FastDecompressor)
*/
public LZ4BlockInputStream(InputStream in) {
this(in, LZ4Factory.fastestInstance().fastDecompressor());
}
@Override
public int available() throws IOException {
return originalLen - o;
}
@Override
public int read() throws IOException {
if (finished) {
return -1;
}
if (o == originalLen) {
refill();
}
if (finished) {
return -1;
}
return buffer[o++] & 0xFF;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
Utils.checkRange(b, off, len);
if (finished) {
return -1;
}
if (o == originalLen) {
refill();
}
if (finished) {
return -1;
}
len = Math.min(len, originalLen - o);
System.arraycopy(buffer, o, b, off, len);
o += len;
return len;
}
@Override
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
@Override
public long skip(long n) throws IOException {
if (finished) {
return -1;
}
if (o == originalLen) {
refill();
}
if (finished) {
return -1;
}
final int skipped = (int) Math.min(n, originalLen - o);
o += skipped;
return skipped;
}
private void refill() throws IOException {
readFully(compressedBuffer, HEADER_LENGTH);
for (int i = 0; i < MAGIC_LENGTH; ++i) {
if (compressedBuffer[i] != MAGIC[i]) {
throw new IOException("Stream is corrupted");
}
}
final int token = compressedBuffer[MAGIC_LENGTH] & 0xFF;
final int compressionMethod = token & 0xF0;
final int compressionLevel = COMPRESSION_LEVEL_BASE + (token & 0x0F);
if (compressionMethod != COMPRESSION_METHOD_RAW && compressionMethod != COMPRESSION_METHOD_LZ4) {
throw new IOException("Stream is corrupted");
}
final int compressedLen = Utils.readIntLE(compressedBuffer, MAGIC_LENGTH + 1);
originalLen = Utils.readIntLE(compressedBuffer, MAGIC_LENGTH + 5);
final int check = Utils.readIntLE(compressedBuffer, MAGIC_LENGTH + 9);
assert HEADER_LENGTH == MAGIC_LENGTH + 13;
if (originalLen > 1 << compressionLevel
|| originalLen < 0
|| compressedLen < 0
|| (originalLen == 0 && compressedLen != 0)
|| (originalLen != 0 && compressedLen == 0)
|| (compressionMethod == COMPRESSION_METHOD_RAW && originalLen != compressedLen)) {
throw new IOException("Stream is corrupted");
}
if (originalLen == 0 && compressedLen == 0) {
if (check != 0) {
throw new IOException("Stream is corrupted");
}
finished = true;
return;
}
if (buffer.length < originalLen) {
buffer = new byte[Math.max(originalLen, buffer.length * 3 / 2)];
}
switch (compressionMethod) {
case COMPRESSION_METHOD_RAW:
readFully(buffer, originalLen);
break;
case COMPRESSION_METHOD_LZ4:
if (compressedBuffer.length < originalLen) {
compressedBuffer = new byte[Math.max(compressedLen, compressedBuffer.length * 3 / 2)];
}
readFully(compressedBuffer, compressedLen);
try {
final int compressedLen2 = decompressor.decompress(compressedBuffer, 0, buffer, 0, originalLen);
if (compressedLen != compressedLen2) {
throw new IOException("Stream is corrupted");
}
} catch (LZ4Exception e) {
throw new IOException("Stream is corrupted", e);
}
break;
default:
throw new AssertionError();
}
checksum.reset();
checksum.update(buffer, 0, originalLen);
if ((int) checksum.getValue() != check) {
throw new IOException("Stream is corrupted");
}
o = 0;
}
private void readFully(byte[] b, int len) throws IOException {
int read = 0;
while (read < len) {
final int r = in.read(b, read, len - read);
if (r < 0) {
throw new EOFException("Stream ended prematurely");
}
read += r;
}
assert len == read;
}
@Override
public boolean markSupported() {
return false;
}
@SuppressWarnings("sync-override")
@Override
public void mark(int readlimit) {
// unsupported
}
@SuppressWarnings("sync-override")
@Override
public void reset() throws IOException {
throw new IOException("mark/reset not supported");
}
@Override
public String toString() {
return getClass().getSimpleName() + "(in=" + in
+ ", decompressor=" + decompressor + ", checksum=" + checksum + ")";
}
}

View file

@ -0,0 +1,257 @@
package net.jpountz.lz4;
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.Checksum;
import net.jpountz.util.Utils;
import net.jpountz.xxhash.StreamingXXHash32;
import net.jpountz.xxhash.XXHashFactory;
/**
* Streaming LZ4.
* <p>
* This class compresses data into fixed-size blocks of compressed data.
* @see LZ4BlockInputStream
*/
public final class LZ4BlockOutputStream extends FilterOutputStream {
static final byte[] MAGIC = new byte[] { 'L', 'Z', '4', 'B', 'l', 'o', 'c', 'k' };
static final int MAGIC_LENGTH = MAGIC.length;
static final int HEADER_LENGTH =
MAGIC_LENGTH // magic bytes
+ 1 // token
+ 4 // compressed length
+ 4 // decompressed length
+ 4; // checksum
static final int COMPRESSION_LEVEL_BASE = 10;
static final int MIN_BLOCK_SIZE = 64;
static final int MAX_BLOCK_SIZE = 1 << (COMPRESSION_LEVEL_BASE + 0x0F);
static final int COMPRESSION_METHOD_RAW = 0x10;
static final int COMPRESSION_METHOD_LZ4 = 0x20;
static final int DEFAULT_SEED = 0x9747b28c;
private static int compressionLevel(int blockSize) {
if (blockSize < MIN_BLOCK_SIZE) {
throw new IllegalArgumentException("blockSize must be >= " + MIN_BLOCK_SIZE + ", got " + blockSize);
} else if (blockSize > MAX_BLOCK_SIZE) {
throw new IllegalArgumentException("blockSize must be <= " + MAX_BLOCK_SIZE + ", got " + blockSize);
}
int compressionLevel = 32 - Integer.numberOfLeadingZeros(blockSize - 1); // ceil of log2
assert (1 << compressionLevel) >= blockSize;
assert blockSize * 2 > (1 << compressionLevel);
compressionLevel = Math.max(0, compressionLevel - COMPRESSION_LEVEL_BASE);
assert compressionLevel >= 0 && compressionLevel <= 0x0F;
return compressionLevel;
}
private final int blockSize;
private final int compressionLevel;
private final LZ4Compressor compressor;
private final Checksum checksum;
private final byte[] buffer;
private final byte[] compressedBuffer;
private final boolean syncFlush;
private boolean finished;
private int o;
/**
* Create a new {@link OutputStream} with configurable block size. Large
* blocks require more memory at compression and decompression time but
* should improve the compression ratio.
*
* @param out the {@link OutputStream} to feed
* @param blockSize the maximum number of bytes to try to compress at once,
* must be >= 64 and <= 32 M
* @param compressor the {@link LZ4Compressor} instance to use to compress
* data
* @param checksum the {@link Checksum} instance to use to check data for
* integrity.
* @param syncFlush true if pending data should also be flushed on {@link #flush()}
*/
public LZ4BlockOutputStream(OutputStream out, int blockSize, LZ4Compressor compressor, Checksum checksum, boolean syncFlush) {
super(out);
this.blockSize = blockSize;
this.compressor = compressor;
this.checksum = checksum;
this.compressionLevel = compressionLevel(blockSize);
this.buffer = new byte[blockSize];
final int compressedBlockSize = HEADER_LENGTH + compressor.maxCompressedLength(blockSize);
this.compressedBuffer = new byte[compressedBlockSize];
this.syncFlush = syncFlush;
o = 0;
finished = false;
System.arraycopy(MAGIC, 0, compressedBuffer, 0, MAGIC_LENGTH);
}
/**
* Create a new instance which checks stream integrity using
* {@link StreamingXXHash32} and doesn't sync flush.
* @see #LZ4BlockOutputStream(OutputStream, int, LZ4Compressor, Checksum, boolean)
* @see StreamingXXHash32#asChecksum()
*/
public LZ4BlockOutputStream(OutputStream out, int blockSize, LZ4Compressor compressor) {
this(out, blockSize, compressor, XXHashFactory.fastestInstance().newStreamingHash32(DEFAULT_SEED).asChecksum(), false);
}
/**
* Create a new instance which compresses with the standard LZ4 compression
* algorithm.
* @see #LZ4BlockOutputStream(OutputStream, int, LZ4Compressor)
* @see LZ4Factory#fastCompressor()
*/
public LZ4BlockOutputStream(OutputStream out, int blockSize) {
this(out, blockSize, LZ4Factory.fastestInstance().fastCompressor());
}
/**
* Create a new instance which compresses into blocks of 64 KB.
* @see #LZ4BlockOutputStream(OutputStream, int)
*/
public LZ4BlockOutputStream(OutputStream out) {
this(out, 1 << 16);
}
private void ensureNotFinished() {
if (finished) {
throw new IllegalStateException("This stream is already closed");
}
}
@Override
public void write(int b) throws IOException {
ensureNotFinished();
if (o == blockSize) {
flushBufferedData();
}
buffer[o++] = (byte) b;
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
Utils.checkRange(b, off, len);
ensureNotFinished();
while (o + len > blockSize) {
final int l = blockSize - o;
System.arraycopy(b, off, buffer, o, blockSize - o);
o = blockSize;
flushBufferedData();
off += l;
len -= l;
}
System.arraycopy(b, off, buffer, o, len);
o += len;
}
@Override
public void write(byte[] b) throws IOException {
ensureNotFinished();
write(b, 0, b.length);
}
@Override
public void close() throws IOException {
if (!finished) {
finish();
}
if (out != null) {
out.close();
out = null;
}
}
private void flushBufferedData() throws IOException {
if (o == 0) {
return;
}
checksum.reset();
checksum.update(buffer, 0, o);
final int check = (int) checksum.getValue();
int compressedLength = compressor.compress(buffer, 0, o, compressedBuffer, HEADER_LENGTH);
final int compressMethod;
if (compressedLength >= o) {
compressMethod = COMPRESSION_METHOD_RAW;
compressedLength = o;
System.arraycopy(buffer, 0, compressedBuffer, HEADER_LENGTH, o);
} else {
compressMethod = COMPRESSION_METHOD_LZ4;
}
compressedBuffer[MAGIC_LENGTH] = (byte) (compressMethod | compressionLevel);
writeIntLE(compressedLength, compressedBuffer, MAGIC_LENGTH + 1);
writeIntLE(o, compressedBuffer, MAGIC_LENGTH + 5);
writeIntLE(check, compressedBuffer, MAGIC_LENGTH + 9);
assert MAGIC_LENGTH + 13 == HEADER_LENGTH;
out.write(compressedBuffer, 0, HEADER_LENGTH + compressedLength);
o = 0;
}
/**
* Flush this compressed {@link OutputStream}.
*
* If the stream has been created with <code>syncFlush=true</code>, pending
* data will be compressed and appended to the underlying {@link OutputStream}
* before calling {@link OutputStream#flush()} on the underlying stream.
* Otherwise, this method just flushes the underlying stream, so pending
* data might not be available for reading until {@link #finish()} or
* {@link #close()} is called.
*/
@Override
public void flush() throws IOException {
if (syncFlush) {
flushBufferedData();
}
out.flush();
}
/**
* Same as {@link #close()} except that it doesn't close the underlying stream.
* This can be useful if you want to keep on using the underlying stream.
*/
public void finish() throws IOException {
ensureNotFinished();
flushBufferedData();
compressedBuffer[MAGIC_LENGTH] = (byte) (COMPRESSION_METHOD_RAW | compressionLevel);
writeIntLE(0, compressedBuffer, MAGIC_LENGTH + 1);
writeIntLE(0, compressedBuffer, MAGIC_LENGTH + 5);
writeIntLE(0, compressedBuffer, MAGIC_LENGTH + 9);
assert MAGIC_LENGTH + 13 == HEADER_LENGTH;
out.write(compressedBuffer, 0, HEADER_LENGTH);
finished = true;
out.flush();
}
private static void writeIntLE(int i, byte[] buf, int off) {
buf[off++] = (byte) i;
buf[off++] = (byte) (i >>> 8);
buf[off++] = (byte) (i >>> 16);
buf[off++] = (byte) (i >>> 24);
}
@Override
public String toString() {
return getClass().getSimpleName() + "(out=" + out + ", blockSize=" + blockSize
+ ", compressor=" + compressor + ", checksum=" + checksum + ")";
}
}

View file

@ -0,0 +1,98 @@
package net.jpountz.lz4;
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.Arrays;
/**
* LZ4 compressor.
* <p>
* Instances of this class are thread-safe.
*/
public abstract class LZ4Compressor {
/** Return the maximum compressed length for an input of size <code>length</code>. */
@SuppressWarnings("static-method")
public final int maxCompressedLength(int length) {
return LZ4Utils.maxCompressedLength(length);
}
/**
* Compress <code>src[srcOff:srcOff+srcLen]</code> into
* <code>dest[destOff:destOff+destLen]</code> and return the compressed
* length.
*
* This method will throw a {@link LZ4Exception} if this compressor is unable
* to compress the input into less than <code>maxDestLen</code> bytes. To
* prevent this exception to be thrown, you should make sure that
* <code>maxDestLen >= maxCompressedLength(srcLen)</code>.
*
* @throws LZ4Exception if maxDestLen is too small
* @return the compressed size
*/
public abstract int compress(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff, int maxDestLen);
/**
* Convenience method, equivalent to calling
* {@link #compress(byte[], int, int, byte[], int, int) compress(src, srcOff, srcLen, dest, destOff, dest.length - destOff)}.
*/
public final int compress(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff) {
return compress(src, srcOff, srcLen, dest, destOff, dest.length - destOff);
}
/**
* Convenience method, equivalent to calling
* {@link #compress(byte[], int, int, byte[], int) compress(src, 0, src.length, dest, 0)}.
*/
public final int compress(byte[] src, byte[] dest) {
return compress(src, 0, src.length, dest, 0);
}
/**
* Convenience method which returns <code>src[srcOff:srcOff+srcLen]</code>
* compressed.
* <p><b><span style="color:red">Warning</span></b>: this method has an
* important overhead due to the fact that it needs to allocate a buffer to
* compress into, and then needs to resize this buffer to the actual
* compressed length.</p>
* <p>Here is how this method is implemented:</p>
* <pre>
* final int maxCompressedLength = maxCompressedLength(srcLen);
* final byte[] compressed = new byte[maxCompressedLength];
* final int compressedLength = compress(src, srcOff, srcLen, compressed, 0);
* return Arrays.copyOf(compressed, compressedLength);
* </pre>
*/
public final byte[] compress(byte[] src, int srcOff, int srcLen) {
final int maxCompressedLength = maxCompressedLength(srcLen);
final byte[] compressed = new byte[maxCompressedLength];
final int compressedLength = compress(src, srcOff, srcLen, compressed, 0);
return Arrays.copyOf(compressed, compressedLength);
}
/**
* Convenience method, equivalent to calling
* {@link #compress(byte[], int, int) compress(src, 0, src.length)}.
*/
public final byte[] compress(byte[] src) {
return compress(src, 0, src.length);
}
@Override
public String toString() {
return getClass().getSimpleName();
}
}

View file

@ -0,0 +1,50 @@
package net.jpountz.lz4;
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
enum LZ4Constants {
;
static final int MEMORY_USAGE = 14;
static final int NOT_COMPRESSIBLE_DETECTION_LEVEL = 6;
static final int MIN_MATCH = 4;
static final int HASH_LOG = MEMORY_USAGE - 2;
static final int HASH_TABLE_SIZE = 1 << HASH_LOG;
static final int SKIP_STRENGTH = Math.max(NOT_COMPRESSIBLE_DETECTION_LEVEL, 2);
static final int COPY_LENGTH = 8;
static final int LAST_LITERALS = 5;
static final int MF_LIMIT = COPY_LENGTH + MIN_MATCH;
static final int MIN_LENGTH = MF_LIMIT + 1;
static final int MAX_DISTANCE = 1 << 16;
static final int ML_BITS = 4;
static final int ML_MASK = (1 << ML_BITS) - 1;
static final int RUN_BITS = 8 - ML_BITS;
static final int RUN_MASK = (1 << RUN_BITS) - 1;
static final int LZ4_64K_LIMIT = (1 << 16) + (MF_LIMIT - 1);
static final int HASH_LOG_64K = HASH_LOG + 1;
static final int HASH_TABLE_SIZE_64K = 1 << HASH_LOG_64K;
static final int HASH_LOG_HC = 15;
static final int HASH_TABLE_SIZE_HC = 1 << HASH_LOG_HC;
static final int OPTIMAL_ML = ML_MASK - 1 + MIN_MATCH;
}

View file

@ -0,0 +1,25 @@
package net.jpountz.lz4;
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @deprecated Use {@link LZ4FastDecompressor} instead.
*/
@Deprecated
public interface LZ4Decompressor {
int decompress(byte[] src, int srcOff, byte[] dest, int destOff, int destLen);
}

View file

@ -0,0 +1,36 @@
package net.jpountz.lz4;
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* LZ4 compression or decompression error.
*/
public class LZ4Exception extends RuntimeException {
private static final long serialVersionUID = 1L;
public LZ4Exception(String msg, Throwable t) {
super(msg, t);
}
public LZ4Exception(String msg) {
super(msg);
}
public LZ4Exception() {
super();
}
}

View file

@ -0,0 +1,222 @@
package net.jpountz.lz4;
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.lang.reflect.Field;
import java.util.Arrays;
import net.jpountz.util.Native;
/**
* Entry point for the LZ4 API.
* <p>
* This class has 3 instances<ul>
* <li>a {@link #nativeInstance() native} instance which is a JNI binding to
* <a href="http://code.google.com/p/lz4/">the original LZ4 C implementation</a>.
* <li>a {@link #safeInstance() safe Java} instance which is a pure Java port
* of the original C library,</li>
* <li>an {@link #unsafeInstance() unsafe Java} instance which is a Java port
* using the unofficial {@link sun.misc.Unsafe} API.
* </ul>
* <p>
* Only the {@link #safeInstance() safe instance} is guaranteed to work on your
* JVM, as a consequence it is advised to use the {@link #fastestInstance()} or
* {@link #fastestJavaInstance()} to pull a {@link LZ4Factory} instance.
* <p>
* All methods from this class are very costly, so you should get an instance
* once, and then reuse it whenever possible. This is typically done by storing
* a {@link LZ4Factory} instance in a static field.
*/
public final class LZ4Factory {
private static LZ4Factory instance(String impl) {
try {
return new LZ4Factory(impl);
} catch (Exception e) {
throw new AssertionError(e);
}
}
private static LZ4Factory NATIVE_INSTANCE,
JAVA_UNSAFE_INSTANCE,
JAVA_SAFE_INSTANCE;
/**
* Return a {@link LZ4Factory} instance that returns compressors and
* decompressors that are native bindings to the original C library.
* <p>
* Please note that this instance has some traps you should be aware of:<ol>
* <li>Upon loading this instance, files will be written to the temporary
* directory of the system. Although these files are supposed to be deleted
* when the JVM exits, they might remain on systems that don't support
* removal of files being used such as Windows.
* <li>The instance can only be loaded once per JVM. This can be a problem
* if your application uses multiple class loaders (such as most servlet
* containers): this instance will only be available to the children of the
* class loader which has loaded it. As a consequence, it is advised to
* either not use this instance in webapps or to put this library in the lib
* directory of your servlet container so that it is loaded by the system
* class loader.
* </ol>
*/
public static synchronized LZ4Factory nativeInstance() {
if (NATIVE_INSTANCE == null) {
NATIVE_INSTANCE = instance("JNI");
}
return NATIVE_INSTANCE;
}
/** Return a {@link LZ4Factory} instance that returns compressors and
* decompressors that are written with Java's official API. */
public static synchronized LZ4Factory safeInstance() {
if (JAVA_SAFE_INSTANCE == null) {
JAVA_SAFE_INSTANCE = instance("JavaSafe");
}
return JAVA_SAFE_INSTANCE;
}
/** Return a {@link LZ4Factory} instance that returns compressors and
* decompressors that may use {@link sun.misc.Unsafe} to speed up compression
* and decompression. */
public static synchronized LZ4Factory unsafeInstance() {
if (JAVA_UNSAFE_INSTANCE == null) {
JAVA_UNSAFE_INSTANCE = instance("JavaUnsafe");
}
return JAVA_UNSAFE_INSTANCE;
}
/**
* Return the fastest available {@link LZ4Factory} instance which does not
* rely on JNI bindings. It first tries to load the
* {@link #unsafeInstance() unsafe instance}, and then the
* {@link #safeInstance() safe Java instance} if the JVM doesn't have a
* working {@link sun.misc.Unsafe}.
*/
public static LZ4Factory fastestJavaInstance() {
try {
return unsafeInstance();
} catch (Throwable t) {
return safeInstance();
}
}
/**
* Return the fastest available {@link LZ4Factory} instance. If the class
* loader is the system class loader and if the
* {@link #nativeInstance() native instance} loads successfully, then the
* {@link #nativeInstance() native instance} is returned, otherwise the
* {@link #fastestJavaInstance() fastest Java instance} is returned.
* <p>
* Please read {@link #nativeInstance() javadocs of nativeInstance()} before
* using this method.
*/
public static LZ4Factory fastestInstance() {
if (Native.isLoaded()
|| Native.class.getClassLoader() == ClassLoader.getSystemClassLoader()) {
try {
return nativeInstance();
} catch (Throwable t) {
return fastestJavaInstance();
}
} else {
return fastestJavaInstance();
}
}
@SuppressWarnings("unchecked")
private static <T> T classInstance(String cls) throws NoSuchFieldException, SecurityException, ClassNotFoundException, IllegalArgumentException, IllegalAccessException {
final Class<?> c = Class.forName(cls);
Field f = c.getField("INSTANCE");
return (T) f.get(null);
}
private final String impl;
private final LZ4Compressor fastCompressor;
private final LZ4Compressor highCompressor;
private final LZ4FastDecompressor fastDecompressor;
private final LZ4SafeDecompressor safeDecompressor;
private LZ4Factory(String impl) throws ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
this.impl = impl;
fastCompressor = classInstance("net.jpountz.lz4.LZ4" + impl + "Compressor");
highCompressor = classInstance("net.jpountz.lz4.LZ4HC" + impl + "Compressor");
fastDecompressor = classInstance("net.jpountz.lz4.LZ4" + impl + "FastDecompressor");
safeDecompressor = classInstance("net.jpountz.lz4.LZ4" + impl + "SafeDecompressor");
// quickly test that everything works as expected
final byte[] original = new byte[] {'a','b','c','d',' ',' ',' ',' ',' ',' ','a','b','c','d','e','f','g','h','i','j'};
for (LZ4Compressor compressor : Arrays.asList(fastCompressor, highCompressor)) {
final int maxCompressedLength = compressor.maxCompressedLength(original.length);
final byte[] compressed = new byte[maxCompressedLength];
final int compressedLength = compressor.compress(original, 0, original.length, compressed, 0, maxCompressedLength);
final byte[] restored = new byte[original.length];
fastDecompressor.decompress(compressed, 0, restored, 0, original.length);
if (!Arrays.equals(original, restored)) {
throw new AssertionError();
}
Arrays.fill(restored, (byte) 0);
final int decompressedLength = safeDecompressor.decompress(compressed, 0, compressedLength, restored, 0);
if (decompressedLength != original.length || !Arrays.equals(original, restored)) {
throw new AssertionError();
}
}
}
/** Return a blazing fast {@link LZ4Compressor}. */
public LZ4Compressor fastCompressor() {
return fastCompressor;
}
/** Return a {@link LZ4Compressor} which requires more memory than
* {@link #fastCompressor()} and is slower but compresses more efficiently. */
public LZ4Compressor highCompressor() {
return highCompressor;
}
/** Return a {@link LZ4FastDecompressor} instance. */
public LZ4FastDecompressor fastDecompressor() {
return fastDecompressor;
}
/** Return a {@link LZ4SafeDecompressor} instance. */
public LZ4SafeDecompressor safeDecompressor() {
return safeDecompressor;
}
/** Return a {@link LZ4UnknownSizeDecompressor} instance.
* @deprecated use {@link #safeDecompressor()} */
public LZ4UnknownSizeDecompressor unknwonSizeDecompressor() {
return safeDecompressor();
}
/** Return a {@link LZ4Decompressor} instance.
* @deprecated use {@link #fastDecompressor()} */
public LZ4Decompressor decompressor() {
return fastDecompressor();
}
/** Prints the fastest instance. */
public static void main(String[] args) {
System.out.println("Fastest instance is " + fastestInstance());
System.out.println("Fastest Java instance is " + fastestJavaInstance());
}
@Override
public String toString() {
return getClass().getSimpleName() + ":" + impl;
}
}

View file

@ -0,0 +1,90 @@
package net.jpountz.lz4;
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* LZ4 decompressor that requires the size of the original input to be known.
* Use {@link LZ4SafeDecompressor} if you only know the size of the
* compressed stream.
* <p>
* Instances of this class are thread-safe.
*/
public abstract class LZ4FastDecompressor implements LZ4Decompressor {
/** Decompress <code>src[srcOff:]</code> into <code>dest[destOff:destOff+destLen]</code>
* and return the number of bytes read from <code>src</code>.
* <code>destLen</code> must be exactly the size of the decompressed data.
*
* @param destLen the <b>exact</b> size of the original input
* @return the number of bytes read to restore the original input
*/
public abstract int decompress(byte[] src, int srcOff, byte[] dest, int destOff, int destLen);
/**
* Same as {@link #decompress(byte[], int, byte[], int, int)} except that up
* to 64 KB before <code>srcOff</code> in <code>src</code>. This is useful for
* providing LZ4 with a dictionary that can be reused during decompression.
*/
public abstract int decompressWithPrefix64k(byte[] src, int srcOff, byte[] dest, int destOff, int destLen);
/**
* Convenience method, equivalent to calling
* {@link #decompress(byte[], int, byte[], int, int) decompress(src, 0, dest, 0, destLen)}.
*/
public final int decompress(byte[] src, byte[] dest, int destLen) {
return decompress(src, 0, dest, 0, destLen);
}
/**
* Convenience method, equivalent to calling
* {@link #decompress(byte[], byte[], int) decompress(src, dest, dest.length)}.
*/
public final int decompress(byte[] src, byte[] dest) {
return decompress(src, dest, dest.length);
}
/**
* Convenience method which returns <code>src[srcOff:?]</code>
* decompressed.
* <p><b><span style="color:red">Warning</span></b>: this method has an
* important overhead due to the fact that it needs to allocate a buffer to
* decompress into.</p>
* <p>Here is how this method is implemented:</p>
* <pre>
* final byte[] decompressed = new byte[destLen];
* decompress(src, srcOff, decompressed, 0, destLen);
* return decompressed;
* </pre>
*/
public final byte[] decompress(byte[] src, int srcOff, int destLen) {
final byte[] decompressed = new byte[destLen];
decompress(src, srcOff, decompressed, 0, destLen);
return decompressed;
}
/**
* Convenience method, equivalent to calling
* {@link #decompress(byte[], int, int) decompress(src, 0, destLen)}.
*/
public final byte[] decompress(byte[] src, int destLen) {
return decompress(src, 0, destLen);
}
@Override
public String toString() {
return getClass().getSimpleName();
}
}

View file

@ -0,0 +1,38 @@
package net.jpountz.lz4;
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static net.jpountz.util.Utils.checkRange;
/**
* High compression {@link LZ4Compressor}s implemented with JNI bindings to the
* original C implementation of LZ4.
*/
final class LZ4HCJNICompressor extends LZ4Compressor {
public static final LZ4Compressor INSTANCE = new LZ4HCJNICompressor();
@Override
public int compress(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff, int maxDestLen) {
checkRange(src, srcOff, srcLen);
checkRange(dest, destOff, maxDestLen);
final int result = LZ4JNI.LZ4_compressHC(src, srcOff, srcLen, dest, destOff, maxDestLen);
if (result <= 0) {
throw new LZ4Exception();
}
return result;
}
}

View file

@ -0,0 +1,41 @@
package net.jpountz.lz4;
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import net.jpountz.util.Native;
/**
* JNI bindings to the original C implementation of LZ4.
*/
enum LZ4JNI {
;
static {
Native.load();
init();
}
static native void init();
static native int LZ4_compress_limitedOutput(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff, int maxDestLen);
static native int LZ4_compressHC(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff, int maxDestLen);
static native int LZ4_decompress_fast(byte[] src, int srcOff, byte[] dest, int destOff, int destLen);
static native int LZ4_decompress_fast_withPrefix64k(byte[] src, int srcOff, byte[] dest, int destOff, int destLen);
static native int LZ4_decompress_safe(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff, int maxDestLen);
static native int LZ4_decompress_safe_withPrefix64k(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff, int maxDestLen);
static native int LZ4_compressBound(int len);
}

View file

@ -0,0 +1,37 @@
package net.jpountz.lz4;
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static net.jpountz.util.Utils.checkRange;
/**
* Fast {@link LZ4FastCompressor}s implemented with JNI bindings to the original C
* implementation of LZ4.
*/
final class LZ4JNICompressor extends LZ4Compressor {
public static final LZ4Compressor INSTANCE = new LZ4JNICompressor();
@Override
public int compress(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff, int maxDestLen) {
checkRange(src, srcOff, srcLen);
checkRange(dest, destOff, maxDestLen);
final int result = LZ4JNI.LZ4_compress_limitedOutput(src, srcOff, srcLen, dest, destOff, maxDestLen);
if (result <= 0) {
throw new LZ4Exception("maxDestLen is too small");
}
return result;
}
}

View file

@ -0,0 +1,48 @@
package net.jpountz.lz4;
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static net.jpountz.util.Utils.checkRange;
/**
* {@link LZ4FastDecompressor} implemented with JNI bindings to the original C
* implementation of LZ4.
*/
final class LZ4JNIFastDecompressor extends LZ4FastDecompressor {
public static final LZ4JNIFastDecompressor INSTANCE = new LZ4JNIFastDecompressor();
@Override
public final int decompress(byte[] src, int srcOff, byte[] dest, int destOff, int destLen) {
checkRange(src, srcOff);
checkRange(dest, destOff, destLen);
final int result = LZ4JNI.LZ4_decompress_fast(src, srcOff, dest, destOff, destLen);
if (result < 0) {
throw new LZ4Exception("Error decoding offset " + (srcOff - result) + " of input buffer");
}
return result;
}
@Override
public final int decompressWithPrefix64k(byte[] src, int srcOff, byte[] dest, int destOff, int destLen) {
checkRange(src, srcOff);
checkRange(dest, destOff, destLen);
final int result = LZ4JNI.LZ4_decompress_fast_withPrefix64k(src, srcOff, dest, destOff, destLen);
if (result < 0) {
throw new LZ4Exception("Error decoding offset " + (srcOff - result) + " of input buffer");
}
return result;
}
}

View file

@ -0,0 +1,48 @@
package net.jpountz.lz4;
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static net.jpountz.util.Utils.checkRange;
/**
* {@link LZ4SafeDecompressor} implemented with JNI bindings to the original C
* implementation of LZ4.
*/
final class LZ4JNISafeDecompressor extends LZ4SafeDecompressor {
public static final LZ4SafeDecompressor INSTANCE = new LZ4JNISafeDecompressor();
@Override
public final int decompress(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff, int maxDestLen) {
checkRange(src, srcOff, srcLen);
checkRange(dest, destOff, maxDestLen);
final int result = LZ4JNI.LZ4_decompress_safe(src, srcOff, srcLen, dest, destOff, maxDestLen);
if (result < 0) {
throw new LZ4Exception("Error decoding offset " + (srcOff - result) + " of input buffer");
}
return result;
}
@Override
public final int decompressWithPrefix64k(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff, int maxDestLen) {
checkRange(src, srcOff, srcLen);
checkRange(dest, destOff, maxDestLen);
final int result = LZ4JNI.LZ4_decompress_safe_withPrefix64k(src, srcOff, srcLen, dest, destOff, maxDestLen);
if (result < 0) {
throw new LZ4Exception("Error decoding offset " + (srcOff - result) + " of input buffer");
}
return result;
}
}

View file

@ -0,0 +1,109 @@
package net.jpountz.lz4;
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.Arrays;
/**
* LZ4 decompressor that requires the size of the compressed data to be known.
* <p>
* Implementations of this class are usually a little slower than those of
* {@link LZ4FastDecompressor} but do not require the size of the original data to
* be known.
*/
public abstract class LZ4SafeDecompressor implements LZ4UnknownSizeDecompressor {
/**
* Uncompress <code>src[srcOff:srcLen]</code> into
* <code>dest[destOff:destOff+maxDestLen]</code> and returns the number of
* decompressed bytes written into <code>dest</code>.
*
* @param srcLen the exact size of the compressed stream
* @return the original input size
* @throws LZ4Exception if maxDestLen is too small
*/
public abstract int decompress(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff, int maxDestLen);
/**
* Same as {@link #decompress(byte[], int, int, byte[], int, int) except that
* up to 64 KB before <code>srcOff</code> in <code>src</code>. This is useful
* for providing LZ4 with a dictionary that can be reused during decompression.
*/
public abstract int decompressWithPrefix64k(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff, int maxDestLen);
/**
* Convenience method, equivalent to calling
* {@link #decompress(byte[], int, int, byte[], int, int) decompress(src, srcOff, srcLen, dest, destOff, dest.length - destOff)}.
*/
public final int decompress(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff) {
return decompress(src, srcOff, srcLen, dest, destOff, dest.length - destOff);
}
/**
* Convenience method, equivalent to calling
* {@link #decompressWithPrefix64k(byte[], int, int, byte[], int, int) decompress(src, srcOff, srcLen, dest, destOff, dest.length - destOff)}.
*/
public final int decompressWithPrefix64k(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff) {
return decompressWithPrefix64k(src, srcOff, srcLen, dest, destOff, dest.length - destOff);
}
/**
* Convenience method, equivalent to calling
* {@link #decompress(byte[], int, int, byte[], int) decompress(src, 0, src.length, dest, 0)}
*/
public final int decompress(byte[] src, byte[] dest) {
return decompress(src, 0, src.length, dest, 0);
}
/**
* Convenience method which returns <code>src[srcOff:srcOff+srcLen]</code>
* decompressed.
* <p><b><span style="color:red">Warning</span></b>: this method has an
* important overhead due to the fact that it needs to allocate a buffer to
* decompress into, and then needs to resize this buffer to the actual
* decompressed length.</p>
* <p>Here is how this method is implemented:</p>
* <pre>
* byte[] decompressed = new byte[maxDestLen];
* final int decompressedLength = decompress(src, srcOff, srcLen, decompressed, 0, maxDestLen);
* if (decompressedLength != decompressed.length) {
* decompressed = Arrays.copyOf(decompressed, decompressedLength);
* }
* return decompressed;
* </pre>
*/
public final byte[] decompress(byte[] src, int srcOff, int srcLen, int maxDestLen) {
byte[] decompressed = new byte[maxDestLen];
final int decompressedLength = decompress(src, srcOff, srcLen, decompressed, 0, maxDestLen);
if (decompressedLength != decompressed.length) {
decompressed = Arrays.copyOf(decompressed, decompressedLength);
}
return decompressed;
}
/**
* Convenience method, equivalent to calling
* {@link #decompress(byte[], int, int, int) decompress(src, 0, src.length, maxDestLen)}.
*/
public final byte[] decompress(byte[] src, int maxDestLen) {
return decompress(src, 0, src.length, maxDestLen);
}
@Override
public String toString() {
return getClass().getSimpleName();
}
}

View file

@ -0,0 +1,27 @@
package net.jpountz.lz4;
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @deprecated Use {@link LZ4SafeDecompressor} instead.
*/
@Deprecated
public interface LZ4UnknownSizeDecompressor {
int decompress(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff, int maxDestLen);
int decompress(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff);
}

View file

@ -0,0 +1,206 @@
package net.jpountz.lz4;
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static net.jpountz.lz4.LZ4Constants.HASH_LOG;
import static net.jpountz.lz4.LZ4Constants.HASH_LOG_64K;
import static net.jpountz.lz4.LZ4Constants.HASH_LOG_HC;
import static net.jpountz.lz4.LZ4Constants.LAST_LITERALS;
import static net.jpountz.lz4.LZ4Constants.MIN_MATCH;
import static net.jpountz.lz4.LZ4Constants.ML_BITS;
import static net.jpountz.lz4.LZ4Constants.ML_MASK;
import static net.jpountz.lz4.LZ4Constants.RUN_MASK;
import static net.jpountz.util.Utils.readInt;
enum LZ4Utils {
;
static final int maxCompressedLength(int length) {
if (length < 0) {
throw new IllegalArgumentException("length must be >= 0, got " + length);
}
return length + length / 255 + 16;
}
static int hash(int i) {
return (i * -1640531535) >>> ((MIN_MATCH * 8) - HASH_LOG);
}
static int hash64k(int i) {
return (i * -1640531535) >>> ((MIN_MATCH * 8) - HASH_LOG_64K);
}
static int hashHC(int i) {
return (i * -1640531535) >>> ((MIN_MATCH * 8) - HASH_LOG_HC);
}
static int readShortLittleEndian(byte[] buf, int i) {
return (buf[i] & 0xFF) | ((buf[i+1] & 0xFF) << 8);
}
static int hash(byte[] buf, int i) {
return hash(readInt(buf, i));
}
static int hash64k(byte[] buf, int i) {
return hash64k(readInt(buf, i));
}
static boolean readIntEquals(byte[] buf, int i, int j) {
return buf[i] == buf[j] && buf[i+1] == buf[j+1] && buf[i+2] == buf[j+2] && buf[i+3] == buf[j+3];
}
static void safeIncrementalCopy(byte[] dest, int matchOff, int dOff, int matchLen) {
for (int i = 0; i < matchLen; ++i) {
dest[dOff + i] = dest[matchOff + i];
}
}
static void wildIncrementalCopy(byte[] dest, int matchOff, int dOff, int matchCopyEnd) {
do {
copy8Bytes(dest, matchOff, dest, dOff);
matchOff += 8;
dOff += 8;
} while (dOff < matchCopyEnd);
}
static void copy8Bytes(byte[] src, int sOff, byte[] dest, int dOff) {
for (int i = 0; i < 8; ++i) {
dest[dOff + i] = src[sOff + i];
}
}
static int commonBytes(byte[] b, int o1, int o2, int limit) {
int count = 0;
while (o2 < limit && b[o1++] == b[o2++]) {
++count;
}
return count;
}
static int commonBytesBackward(byte[] b, int o1, int o2, int l1, int l2) {
int count = 0;
while (o1 > l1 && o2 > l2 && b[--o1] == b[--o2]) {
++count;
}
return count;
}
static void safeArraycopy(byte[] src, int sOff, byte[] dest, int dOff, int len) {
System.arraycopy(src, sOff, dest, dOff, len);
}
static void wildArraycopy(byte[] src, int sOff, byte[] dest, int dOff, int len) {
try {
for (int i = 0; i < len; i += 8) {
copy8Bytes(src, sOff + i, dest, dOff + i);
}
} catch (ArrayIndexOutOfBoundsException e) {
throw new LZ4Exception("Malformed input at offset " + sOff);
}
}
static int encodeSequence(byte[] src, int anchor, int matchOff, int matchRef, int matchLen, byte[] dest, int dOff, int destEnd) {
final int runLen = matchOff - anchor;
final int tokenOff = dOff++;
if (dOff + runLen + (2 + 1 + LAST_LITERALS) + (runLen >>> 8) > destEnd) {
throw new LZ4Exception("maxDestLen is too small");
}
int token;
if (runLen >= RUN_MASK) {
token = (byte) (RUN_MASK << ML_BITS);
dOff = writeLen(runLen - RUN_MASK, dest, dOff);
} else {
token = runLen << ML_BITS;
}
// copy literals
wildArraycopy(src, anchor, dest, dOff, runLen);
dOff += runLen;
// encode offset
final int matchDec = matchOff - matchRef;
dest[dOff++] = (byte) matchDec;
dest[dOff++] = (byte) (matchDec >>> 8);
// encode match len
matchLen -= 4;
if (dOff + (1 + LAST_LITERALS) + (matchLen >>> 8) > destEnd) {
throw new LZ4Exception("maxDestLen is too small");
}
if (matchLen >= ML_MASK) {
token |= ML_MASK;
dOff = writeLen(matchLen - RUN_MASK, dest, dOff);
} else {
token |= matchLen;
}
dest[tokenOff] = (byte) token;
return dOff;
}
static int lastLiterals(byte[] src, int sOff, int srcLen, byte[] dest, int dOff, int destEnd) {
final int runLen = srcLen;
if (dOff + runLen + 1 + (runLen + 255 - RUN_MASK) / 255 > destEnd) {
throw new LZ4Exception();
}
if (runLen >= RUN_MASK) {
dest[dOff++] = (byte) (RUN_MASK << ML_BITS);
dOff = writeLen(runLen - RUN_MASK, dest, dOff);
} else {
dest[dOff++] = (byte) (runLen << ML_BITS);
}
// copy literals
System.arraycopy(src, sOff, dest, dOff, runLen);
dOff += runLen;
return dOff;
}
static int writeLen(int len, byte[] dest, int dOff) {
while (len >= 0xFF) {
dest[dOff++] = (byte) 0xFF;
len -= 0xFF;
}
dest[dOff++] = (byte) len;
return dOff;
}
static class Match {
int start, ref, len;
void fix(int correction) {
start += correction;
ref += correction;
len -= correction;
}
int end() {
return start + len;
}
}
static void copyTo(Match m1, Match m2) {
m2.len = m1.len;
m2.start = m1.start;
m2.ref = m1.ref;
}
}

View file

@ -0,0 +1,55 @@
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<!--
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
<p>LZ4 compression. The entry point of the API is the
{@link net.jpountz.lz4.LZ4Factory} class, which gives access to
{@link net.jpountz.lz4.LZ4Compressor compressors} and
{@link net.jpountz.lz4.LZ4SafeDecompressor decompressors}.</p>
<p>Sample usage:</p>
<pre class="prettyprint">
LZ4Factory factory = LZ4Factory.fastestInstance();
byte[] data = "12345345234572".getBytes("UTF-8");
final int decompressedLength = data.length;
// compress data
LZ4Compressor compressor = factory.fastCompressor();
int maxCompressedLength = compressor.maxCompressedLength(decompressedLength);
byte[] compressed = new byte[maxCompressedLength];
int compressedLength = compressor.compress(data, 0, decompressedLength, compressed, 0, maxCompressedLength);
// decompress data
// - method 1: when the decompressed length is known
LZ4FastDecompressor decompressor = factory.fastDecompressor();
byte[] restored = new byte[decompressedLength];
int compressedLength2 = decompressor.decompress(compressed, 0, restored, 0, decompressedLength);
// compressedLength == compressedLength2
// - method 2: when the compressed length is known (a little slower)
// the destination buffer needs to be over-sized
LZ4SafeDecompressor decompressor2 = factory.safeDecompressor();
int decompressedLength2 = decompressor2.decompress(compressed, 0, compressedLength, restored, 0);
// decompressedLength == decompressedLength2
</pre>
</body>
</html>

View file

@ -0,0 +1,121 @@
package net.jpountz.util;
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
/** FOR INTERNAL USE ONLY */
public enum Native {
;
private enum OS {
// Even on Windows, the default compiler from cpptasks (gcc) uses .so as a shared lib extension
WINDOWS("win32", "so"), LINUX("linux", "so"), MAC("darwin", "dylib"), SOLARIS("solaris", "so");
public final String name, libExtension;
private OS(String name, String libExtension) {
this.name = name;
this.libExtension = libExtension;
}
}
private static String arch() {
return System.getProperty("os.arch");
}
private static OS os() {
String osName = System.getProperty("os.name");
if (osName.contains("Linux")) {
return OS.LINUX;
} else if (osName.contains("Mac")) {
return OS.MAC;
} else if (osName.contains("Windows")) {
return OS.WINDOWS;
} else if (osName.contains("Solaris")) {
return OS.SOLARIS;
} else {
throw new UnsupportedOperationException("Unsupported operating system: "
+ osName);
}
}
private static String resourceName() {
OS os = os();
return "/" + os.name + "/" + arch() + "/liblz4-java." + os.libExtension;
}
private static boolean loaded = false;
public static synchronized boolean isLoaded() {
return loaded;
}
public static synchronized void load() {
if (loaded) {
return;
}
String resourceName = resourceName();
InputStream is = Native.class.getResourceAsStream(resourceName);
if (is == null) {
throw new UnsupportedOperationException("Unsupported OS/arch, cannot find " + resourceName + ". Please try building from source.");
}
File tempLib;
try {
tempLib = File.createTempFile("liblz4-java", "." + os().libExtension);
// copy to tempLib
FileOutputStream out = new FileOutputStream(tempLib);
try {
byte[] buf = new byte[4096];
while (true) {
int read = is.read(buf);
if (read == -1) {
break;
}
out.write(buf, 0, read);
}
try {
out.close();
out = null;
} catch (IOException e) {
// ignore
}
System.load(tempLib.getAbsolutePath());
loaded = true;
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
// ignore
}
if (tempLib != null && tempLib.exists()) {
if (!loaded) {
tempLib.delete();
} else {
// try to delete on exit, does it work on Windows?
tempLib.deleteOnExit();
}
}
}
} catch (IOException e) {
throw new ExceptionInInitializerError("Cannot unpack liblz4-java");
}
}
}

View file

@ -0,0 +1,89 @@
package net.jpountz.util;
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.nio.ByteOrder;
public enum Utils {
;
public static final ByteOrder NATIVE_BYTE_ORDER = ByteOrder.nativeOrder();
public static void checkRange(byte[] buf, int off) {
if (off < 0 || off >= buf.length) {
throw new ArrayIndexOutOfBoundsException(off);
}
}
public static void checkRange(byte[] buf, int off, int len) {
checkLength(len);
if (len > 0) {
checkRange(buf, off);
checkRange(buf, off + len - 1);
}
}
public static void checkLength(int len) {
if (len < 0) {
throw new IllegalArgumentException("lengths must be >= 0");
}
}
public static byte readByte(byte[] buf, int i) {
return buf[i];
}
public static int readIntBE(byte[] buf, int i) {
return ((buf[i] & 0xFF) << 24) | ((buf[i+1] & 0xFF) << 16) | ((buf[i+2] & 0xFF) << 8) | (buf[i+3] & 0xFF);
}
public static int readIntLE(byte[] buf, int i) {
return (buf[i] & 0xFF) | ((buf[i+1] & 0xFF) << 8) | ((buf[i+2] & 0xFF) << 16) | ((buf[i+3] & 0xFF) << 24);
}
public static int readInt(byte[] buf, int i) {
if (NATIVE_BYTE_ORDER == ByteOrder.BIG_ENDIAN) {
return readIntBE(buf, i);
} else {
return readIntLE(buf, i);
}
}
public static void writeShortLittleEndian(byte[] buf, int off, int v) {
buf[off++] = (byte) v;
buf[off++] = (byte) (v >>> 8);
}
public static void writeInt(int[] buf, int off, int v) {
buf[off] = v;
}
public static int readInt(int[] buf, int off) {
return buf[off];
}
public static void writeByte(byte[] dest, int tokenOff, int i) {
dest[tokenOff] = (byte) i;
}
public static void writeShort(short[] buf, int off, int v) {
buf[off] = (short) v;
}
public static int readShort(short[] buf, int off) {
return buf[off] & 0xFFFF;
}
}

View file

@ -0,0 +1,22 @@
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<!--
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
<p>Utility classes.</p>
</body>
</html>

View file

@ -0,0 +1,42 @@
package net.jpountz.xxhash;
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static net.jpountz.xxhash.XXHashConstants.PRIME1;
import static net.jpountz.xxhash.XXHashConstants.PRIME2;
abstract class AbstractStreamingXXHash32Java extends StreamingXXHash32 {
int v1, v2, v3, v4, memSize;
long totalLen;
final byte[] memory;
AbstractStreamingXXHash32Java(int seed) {
super(seed);
memory = new byte[16];
reset();
}
@Override
public void reset() {
v1 = seed + PRIME1 + PRIME2;
v2 = seed + PRIME2;
v3 = seed + 0;
v4 = seed - PRIME1;
totalLen = 0;
memSize = 0;
}
}

View file

@ -0,0 +1,111 @@
package net.jpountz.xxhash;
import java.util.zip.Checksum;
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Streaming interface for {@link XXHash32}.
* <p>
* This API is compatible with the {@link XXHash32 block API} and the following
* code samples are equivalent:
* <pre class="prettyprint">
* int hash(XXHashFactory xxhashFactory, byte[] buf, int off, int len, int seed) {
* return xxhashFactory.hash32().hash(buf, off, len, seed);
* }
* </pre>
* <pre class="prettyprint">
* int hash(XXHashFactory xxhashFactory, byte[] buf, int off, int len, int seed) {
* StreamingXXHash32 sh32 = xxhashFactory.newStreamingHash32(seed);
* sh32.update(buf, off, len);
* return sh32.getValue();
* }
* </pre>
* <p>
* Instances of this class are <b>not</b> thread-safe.
*/
public abstract class StreamingXXHash32 {
interface Factory {
StreamingXXHash32 newStreamingHash(int seed);
}
final int seed;
StreamingXXHash32(int seed) {
this.seed = seed;
}
/**
* Get the value of the checksum.
*/
public abstract int getValue();
/**
* Update the value of the hash with buf[off:off+len].
*/
public abstract void update(byte[] buf, int off, int len);
/**
* Reset this instance to the state it had right after instantiation. The
* seed remains unchanged.
*/
public abstract void reset();
@Override
public String toString() {
return getClass().getSimpleName() + "(seed=" + seed + ")";
}
/**
* Return a {@link Checksum} view of this instance. Modifications to the view
* will modify this instance too and vice-versa.
*/
public final Checksum asChecksum() {
return new Checksum() {
@Override
public long getValue() {
return StreamingXXHash32.this.getValue() & 0xFFFFFFFL;
}
@Override
public void reset() {
StreamingXXHash32.this.reset();
}
@Override
public void update(int b) {
StreamingXXHash32.this.update(new byte[] {(byte) b}, 0, 1);
}
@Override
public void update(byte[] b, int off, int len) {
StreamingXXHash32.this.update(b, off, len);
}
@Override
public String toString() {
return StreamingXXHash32.this.toString();
}
};
}
}

View file

@ -0,0 +1,71 @@
package net.jpountz.xxhash;
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class StreamingXXHash32JNI extends StreamingXXHash32 {
static class Factory implements StreamingXXHash32.Factory {
public static final StreamingXXHash32.Factory INSTANCE = new Factory();
@Override
public StreamingXXHash32 newStreamingHash(int seed) {
return new StreamingXXHash32JNI(seed);
}
}
private long state;
StreamingXXHash32JNI(int seed) {
super(seed);
state = XXHashJNI.XXH32_init(seed);
}
private void checkState() {
if (state == 0) {
throw new AssertionError("Already finalized");
}
}
@Override
public void reset() {
checkState();
XXHashJNI.XXH32_free(state);
state = XXHashJNI.XXH32_init(seed);
}
@Override
public int getValue() {
checkState();
return XXHashJNI.XXH32_intermediateDigest(state);
}
@Override
public void update(byte[] bytes, int off, int len) {
checkState();
XXHashJNI.XXH32_update(state, bytes, off, len);
}
@Override
protected void finalize() throws Throwable {
super.finalize();
// free memory
XXHashJNI.XXH32_free(state);
state = 0;
}
}

Some files were not shown because too many files have changed in this diff Show more