forked from 2009Scape/Server
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:
parent
34a24140c1
commit
0fc8d6ee4c
1207 changed files with 66670 additions and 27 deletions
165
Tools/Cache Editor/src/alex/CacheLoader.java
Normal file
165
Tools/Cache Editor/src/alex/CacheLoader.java
Normal 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;
|
||||
}
|
||||
}
|
||||
215
Tools/Cache Editor/src/alex/cache/CacheFile.java
vendored
Normal file
215
Tools/Cache Editor/src/alex/cache/CacheFile.java
vendored
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
44
Tools/Cache Editor/src/alex/cache/CacheFileWorker.java
vendored
Normal file
44
Tools/Cache Editor/src/alex/cache/CacheFileWorker.java
vendored
Normal 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);
|
||||
}
|
||||
}
|
||||
70
Tools/Cache Editor/src/alex/cache/FileOnDisk.java
vendored
Normal file
70
Tools/Cache Editor/src/alex/cache/FileOnDisk.java
vendored
Normal 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;
|
||||
}
|
||||
}
|
||||
576
Tools/Cache Editor/src/alex/cache/FileSystem.java
vendored
Normal file
576
Tools/Cache Editor/src/alex/cache/FileSystem.java
vendored
Normal 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;
|
||||
}
|
||||
}
|
||||
333
Tools/Cache Editor/src/alex/cache/ReferenceTable.java
vendored
Normal file
333
Tools/Cache Editor/src/alex/cache/ReferenceTable.java
vendored
Normal 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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
294
Tools/Cache Editor/src/alex/cache/SeekableFile.java
vendored
Normal file
294
Tools/Cache Editor/src/alex/cache/SeekableFile.java
vendored
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
130
Tools/Cache Editor/src/alex/cache/loaders/ConfigFileDefinition.java
vendored
Normal file
130
Tools/Cache Editor/src/alex/cache/loaders/ConfigFileDefinition.java
vendored
Normal 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;
|
||||
}
|
||||
}
|
||||
38
Tools/Cache Editor/src/alex/cache/loaders/EquipIds.java
vendored
Normal file
38
Tools/Cache Editor/src/alex/cache/loaders/EquipIds.java
vendored
Normal 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);
|
||||
}
|
||||
}
|
||||
600
Tools/Cache Editor/src/alex/cache/loaders/ItemDefinition.java
vendored
Normal file
600
Tools/Cache Editor/src/alex/cache/loaders/ItemDefinition.java
vendored
Normal 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;
|
||||
}
|
||||
}
|
||||
914
Tools/Cache Editor/src/alex/cache/loaders/ObjectDefinitions.java
vendored
Normal file
914
Tools/Cache Editor/src/alex/cache/loaders/ObjectDefinitions.java
vendored
Normal 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>();
|
||||
}
|
||||
|
||||
}
|
||||
147
Tools/Cache Editor/src/alex/cache/loaders/OverlayDefinition.java
vendored
Normal file
147
Tools/Cache Editor/src/alex/cache/loaders/OverlayDefinition.java
vendored
Normal 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;
|
||||
}
|
||||
}
|
||||
20
Tools/Cache Editor/src/alex/cache/updateServer/UpdateServer.java
vendored
Normal file
20
Tools/Cache Editor/src/alex/cache/updateServer/UpdateServer.java
vendored
Normal 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;
|
||||
}
|
||||
}
|
||||
38
Tools/Cache Editor/src/alex/compressors/BZip2Constants.java
Normal file
38
Tools/Cache Editor/src/alex/compressors/BZip2Constants.java
Normal 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;
|
||||
|
||||
}
|
||||
1879
Tools/Cache Editor/src/alex/compressors/BZip2OutputStream.java
Normal file
1879
Tools/Cache Editor/src/alex/compressors/BZip2OutputStream.java
Normal file
File diff suppressed because it is too large
Load diff
134
Tools/Cache Editor/src/alex/compressors/CRC.java
Normal file
134
Tools/Cache Editor/src/alex/compressors/CRC.java
Normal 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;
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
91
Tools/Cache Editor/src/alex/compressors/Rand.java
Normal file
91
Tools/Cache Editor/src/alex/compressors/Rand.java
Normal 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];
|
||||
}
|
||||
}
|
||||
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
550
Tools/Cache Editor/src/alex/decompressors/BZip2Decompressor.java
Normal file
550
Tools/Cache Editor/src/alex/decompressors/BZip2Decompressor.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
504
Tools/Cache Editor/src/alex/io/Stream.java
Normal file
504
Tools/Cache Editor/src/alex/io/Stream.java
Normal 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);
|
||||
}
|
||||
}
|
||||
41
Tools/Cache Editor/src/alex/util/LookupTable.java
Normal file
41
Tools/Cache Editor/src/alex/util/LookupTable.java
Normal 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);
|
||||
}
|
||||
}
|
||||
372
Tools/Cache Editor/src/alex/util/Methods.java
Normal file
372
Tools/Cache Editor/src/alex/util/Methods.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
263
Tools/Cache Editor/src/com/alex/io/InputStream.java
Normal file
263
Tools/Cache Editor/src/com/alex/io/InputStream.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
335
Tools/Cache Editor/src/com/alex/io/OutputStream.java
Normal file
335
Tools/Cache Editor/src/com/alex/io/OutputStream.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
94
Tools/Cache Editor/src/com/alex/io/Stream.java
Normal file
94
Tools/Cache Editor/src/com/alex/io/Stream.java
Normal 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++];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package com.alex.loaders.clientscripts;
|
||||
|
||||
public class ClientScript {
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
159
Tools/Cache Editor/src/com/alex/store/Archive.java
Normal file
159
Tools/Cache Editor/src/com/alex/store/Archive.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
133
Tools/Cache Editor/src/com/alex/store/ArchiveReference.java
Normal file
133
Tools/Cache Editor/src/com/alex/store/ArchiveReference.java
Normal 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));
|
||||
}
|
||||
|
||||
}
|
||||
15
Tools/Cache Editor/src/com/alex/store/FileReference.java
Normal file
15
Tools/Cache Editor/src/com/alex/store/FileReference.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
446
Tools/Cache Editor/src/com/alex/store/Index.java
Normal file
446
Tools/Cache Editor/src/com/alex/store/Index.java
Normal 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;
|
||||
}
|
||||
}
|
||||
249
Tools/Cache Editor/src/com/alex/store/MainFile.java
Normal file
249
Tools/Cache Editor/src/com/alex/store/MainFile.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
241
Tools/Cache Editor/src/com/alex/store/ReferenceTable.java
Normal file
241
Tools/Cache Editor/src/com/alex/store/ReferenceTable.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
149
Tools/Cache Editor/src/com/alex/store/Store.java
Normal file
149
Tools/Cache Editor/src/com/alex/store/Store.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
415
Tools/Cache Editor/src/com/alex/util/whirlpool/Whirlpool.java
Normal file
415
Tools/Cache Editor/src/com/alex/util/whirlpool/Whirlpool.java
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
153
Tools/Cache Editor/src/com/alex/utils/ByteBufferUtils.java
Normal file
153
Tools/Cache Editor/src/com/alex/utils/ByteBufferUtils.java
Normal 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.
|
||||
*/
|
||||
}
|
||||
}
|
||||
26
Tools/Cache Editor/src/com/alex/utils/Constants.java
Normal file
26
Tools/Cache Editor/src/com/alex/utils/Constants.java
Normal 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() {
|
||||
|
||||
}
|
||||
}
|
||||
62
Tools/Cache Editor/src/com/alex/utils/Utils.java
Normal file
62
Tools/Cache Editor/src/com/alex/utils/Utils.java
Normal 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() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
27
Tools/Cache Editor/src/emperor/DefDumper.java
Normal file
27
Tools/Cache Editor/src/emperor/DefDumper.java
Normal 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();
|
||||
}
|
||||
}
|
||||
159
Tools/Cache Editor/src/emperor/DonatorIconPacker.java
Normal file
159
Tools/Cache Editor/src/emperor/DonatorIconPacker.java
Normal 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;
|
||||
}
|
||||
}
|
||||
139
Tools/Cache Editor/src/emperor/ItemPacker.java
Normal file
139
Tools/Cache Editor/src/emperor/ItemPacker.java
Normal 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;
|
||||
}
|
||||
}
|
||||
83
Tools/Cache Editor/src/emperor/LandMap.java
Normal file
83
Tools/Cache Editor/src/emperor/LandMap.java
Normal 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() + ").");
|
||||
}
|
||||
}
|
||||
15
Tools/Cache Editor/src/emperor/Landscape.java
Normal file
15
Tools/Cache Editor/src/emperor/Landscape.java
Normal 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;
|
||||
}
|
||||
}
|
||||
243
Tools/Cache Editor/src/emperor/LandscapeCache.java
Normal file
243
Tools/Cache Editor/src/emperor/LandscapeCache.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
465
Tools/Cache Editor/src/emperor/LandscapeEditor.java
Normal file
465
Tools/Cache Editor/src/emperor/LandscapeEditor.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
393
Tools/Cache Editor/src/emperor/MapEditor.java
Normal file
393
Tools/Cache Editor/src/emperor/MapEditor.java
Normal 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!");
|
||||
}
|
||||
|
||||
}
|
||||
195
Tools/Cache Editor/src/emperor/ModelPacker.java
Normal file
195
Tools/Cache Editor/src/emperor/ModelPacker.java
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
406
Tools/Cache Editor/src/emperor/MusicPropertiesPacker.java
Normal file
406
Tools/Cache Editor/src/emperor/MusicPropertiesPacker.java
Normal 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();
|
||||
}
|
||||
}
|
||||
207
Tools/Cache Editor/src/emperor/ObjectMap.java
Normal file
207
Tools/Cache Editor/src/emperor/ObjectMap.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
247
Tools/Cache Editor/src/net/jpountz/lz4/LZ4BlockInputStream.java
Normal file
247
Tools/Cache Editor/src/net/jpountz/lz4/LZ4BlockInputStream.java
Normal 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 + ")";
|
||||
}
|
||||
|
||||
}
|
||||
257
Tools/Cache Editor/src/net/jpountz/lz4/LZ4BlockOutputStream.java
Normal file
257
Tools/Cache Editor/src/net/jpountz/lz4/LZ4BlockOutputStream.java
Normal 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 + ")";
|
||||
}
|
||||
|
||||
}
|
||||
98
Tools/Cache Editor/src/net/jpountz/lz4/LZ4Compressor.java
Normal file
98
Tools/Cache Editor/src/net/jpountz/lz4/LZ4Compressor.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
50
Tools/Cache Editor/src/net/jpountz/lz4/LZ4Constants.java
Normal file
50
Tools/Cache Editor/src/net/jpountz/lz4/LZ4Constants.java
Normal 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;
|
||||
|
||||
}
|
||||
25
Tools/Cache Editor/src/net/jpountz/lz4/LZ4Decompressor.java
Normal file
25
Tools/Cache Editor/src/net/jpountz/lz4/LZ4Decompressor.java
Normal 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);
|
||||
|
||||
}
|
||||
36
Tools/Cache Editor/src/net/jpountz/lz4/LZ4Exception.java
Normal file
36
Tools/Cache Editor/src/net/jpountz/lz4/LZ4Exception.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
222
Tools/Cache Editor/src/net/jpountz/lz4/LZ4Factory.java
Normal file
222
Tools/Cache Editor/src/net/jpountz/lz4/LZ4Factory.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
41
Tools/Cache Editor/src/net/jpountz/lz4/LZ4JNI.java
Normal file
41
Tools/Cache Editor/src/net/jpountz/lz4/LZ4JNI.java
Normal 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);
|
||||
|
||||
}
|
||||
|
||||
37
Tools/Cache Editor/src/net/jpountz/lz4/LZ4JNICompressor.java
Normal file
37
Tools/Cache Editor/src/net/jpountz/lz4/LZ4JNICompressor.java
Normal 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
109
Tools/Cache Editor/src/net/jpountz/lz4/LZ4SafeDecompressor.java
Normal file
109
Tools/Cache Editor/src/net/jpountz/lz4/LZ4SafeDecompressor.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
}
|
||||
206
Tools/Cache Editor/src/net/jpountz/lz4/LZ4Utils.java
Normal file
206
Tools/Cache Editor/src/net/jpountz/lz4/LZ4Utils.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
55
Tools/Cache Editor/src/net/jpountz/lz4/package.html
Normal file
55
Tools/Cache Editor/src/net/jpountz/lz4/package.html
Normal 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>
|
||||
121
Tools/Cache Editor/src/net/jpountz/util/Native.java
Normal file
121
Tools/Cache Editor/src/net/jpountz/util/Native.java
Normal 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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
89
Tools/Cache Editor/src/net/jpountz/util/Utils.java
Normal file
89
Tools/Cache Editor/src/net/jpountz/util/Utils.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
22
Tools/Cache Editor/src/net/jpountz/util/package.html
Normal file
22
Tools/Cache Editor/src/net/jpountz/util/package.html
Normal 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>
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
111
Tools/Cache Editor/src/net/jpountz/xxhash/StreamingXXHash32.java
Normal file
111
Tools/Cache Editor/src/net/jpountz/xxhash/StreamingXXHash32.java
Normal 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();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue