mirror of
https://github.com/2006-Scape/2006Scape.git
synced 2026-07-04 00:31:54 +00:00
Replace clipping files with loading straight from the cache. (#540)
* Archive decompression from apollo * Removed unused object definition fields * Add more options to IndexedFileSystem New methods are to read directly to a bytearray rather than allocating a large number of ByteBuffers on server startup for map loading. decompress is from client and will be depre * Fix opcode 19 of object defs * Initial commit of loading maps from cache * Removed deprecated methods Methods were in IndexedFileSystem for testing to ensure the getFileBytes method worked correctly. * Some code cleanup to fix packaging. #TODO review methods in CompressionUtil to use the best Gzip decompression * map_index loading from cache * Update pom.xml Added commons compress dependency from maven for bzip2 decompression * Renaming some object definition values. * Update ObjectDefinition.java Removed rest of unused variables * Update ObjectDefinition.java * Object Definitions loading from cache * Remove dead code * Remove unneeded files Maps/Definitions now load from in the cache. * Firemaking clipping
This commit is contained in:
@@ -213,7 +213,6 @@ public class GameEngine {
|
||||
/**
|
||||
* Initialise Handlers
|
||||
*/
|
||||
ObjectDefinition.loadConfig();
|
||||
RegionFactory.load();
|
||||
Doors.getSingleton().load();
|
||||
DoubleDoors.getSingleton().load();
|
||||
|
||||
+17
-6
@@ -81,14 +81,24 @@ public class Firemaking {
|
||||
GameEngine.itemHandler.createGroundItem(c, logId, c.absX, c.absY, 1, c.playerId);
|
||||
}
|
||||
}
|
||||
final boolean walk;
|
||||
|
||||
int[] dir = { 0, 0 };
|
||||
if (Region.getClipping(x - 1, y, c.heightLevel, -1, 0)) {
|
||||
walk = true;
|
||||
} else {
|
||||
walk = false;
|
||||
dir[0] = -1;
|
||||
dir[1] = 0;
|
||||
} else if (Region.getClipping(x + 1, y, c.heightLevel, 1, 0)) {
|
||||
dir[0] = 1;
|
||||
dir[1] = 0;
|
||||
} else if (Region.getClipping(x, y - 1, c.heightLevel, 0, -1)) {
|
||||
dir[0] = 0;
|
||||
dir[1] = -1;
|
||||
} else if (Region.getClipping(x, y + 1, c.heightLevel, 0, 1)) {
|
||||
dir[0] = 0;
|
||||
dir[1] = 1;
|
||||
}
|
||||
|
||||
c.startAnimation(733);
|
||||
c.getPlayerAssistant().walkTo(walk ? -1 : 1, 0);
|
||||
c.getPlayerAssistant().walkTo(dir[0], dir[1]);
|
||||
c.stopFiremaking = false;
|
||||
CycleEventHandler.getSingleton().addEvent(c, new CycleEvent() {
|
||||
|
||||
@@ -121,7 +131,7 @@ public class Firemaking {
|
||||
|
||||
@Override
|
||||
public void execute(CycleEventContainer container) {
|
||||
c.turnPlayerTo(walk ? x + 1 : x - 1, y);
|
||||
c.turnPlayerTo(x - dir[0], y - dir[1]);
|
||||
c.logLit = true;
|
||||
stopFiremaking(c);
|
||||
container.stop();
|
||||
@@ -164,4 +174,5 @@ public class Firemaking {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,49 +14,14 @@ public class ByteStream {
|
||||
offset += length;
|
||||
}
|
||||
|
||||
public void setOffset(int position) {
|
||||
offset = position;
|
||||
}
|
||||
|
||||
public void setOffset(long position) {
|
||||
offset = (int) position;
|
||||
}
|
||||
|
||||
public int length() {
|
||||
return buffer.length;
|
||||
}
|
||||
|
||||
public byte getByte() {
|
||||
return buffer[offset++];
|
||||
}
|
||||
|
||||
public int getUByte() {
|
||||
return buffer[offset++] & 0xff;
|
||||
}
|
||||
|
||||
public int getShort() {
|
||||
int val = (getByte() << 8) + getByte();
|
||||
if (val > 32767) {
|
||||
val -= 0x10000;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
public int getUShort() {
|
||||
return (getUByte() << 8) + getUByte();
|
||||
}
|
||||
|
||||
public int getInt() {
|
||||
return (getUByte() << 24) + (getUByte() << 16) + (getUByte() << 8)
|
||||
+ getUByte();
|
||||
}
|
||||
|
||||
public long getLong() {
|
||||
return (getUByte() << 56) + (getUByte() << 48) + (getUByte() << 40)
|
||||
+ (getUByte() << 32) + (getUByte() << 24) + (getUByte() << 16)
|
||||
+ (getUByte() << 8) + getUByte();
|
||||
}
|
||||
|
||||
public int getUSmart() {
|
||||
int i = buffer[offset] & 0xff;
|
||||
if (i < 128) {
|
||||
@@ -65,31 +30,4 @@ public class ByteStream {
|
||||
return getUShort() - 32768;
|
||||
}
|
||||
}
|
||||
|
||||
public String getNString() {
|
||||
int i = offset;
|
||||
while (buffer[offset++] != 0) {
|
||||
;
|
||||
}
|
||||
return new String(buffer, i, offset - i - 1);
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
int i = offset;
|
||||
while (buffer[offset++] != 10) {
|
||||
;
|
||||
}
|
||||
byte abyte0[] = new byte[offset - i - 1];
|
||||
System.arraycopy(buffer, i, abyte0, i - i, offset - 1 - i);
|
||||
return abyte0;
|
||||
}
|
||||
|
||||
public byte[] read(int length) {
|
||||
byte[] b = new byte[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
b[i] = buffer[offset++];
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
package com.rs2.world.clip;
|
||||
|
||||
public final class ByteStreamExt {
|
||||
|
||||
public void skip(int length) {
|
||||
currentOffset += length;
|
||||
}
|
||||
|
||||
public ByteStreamExt(byte abyte0[]) {
|
||||
buffer = abyte0;
|
||||
currentOffset = 0;
|
||||
}
|
||||
|
||||
public int readUnsignedByte() {
|
||||
return buffer[currentOffset++] & 0xff;
|
||||
}
|
||||
|
||||
public byte readSignedByte() {
|
||||
return buffer[currentOffset++];
|
||||
}
|
||||
|
||||
public int readUnsignedWord() {
|
||||
currentOffset += 2;
|
||||
return ((buffer[currentOffset - 2] & 0xff) << 8)
|
||||
+ (buffer[currentOffset - 1] & 0xff);
|
||||
}
|
||||
|
||||
public int readSignedWord() {
|
||||
currentOffset += 2;
|
||||
int i = ((buffer[currentOffset - 2] & 0xff) << 8)
|
||||
+ (buffer[currentOffset - 1] & 0xff);
|
||||
if (i > 32767) {
|
||||
i -= 0x10000;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public int read3Bytes() {
|
||||
currentOffset += 3;
|
||||
return ((buffer[currentOffset - 3] & 0xff) << 16)
|
||||
+ ((buffer[currentOffset - 2] & 0xff) << 8)
|
||||
+ (buffer[currentOffset - 1] & 0xff);
|
||||
}
|
||||
|
||||
public int readR3Bytes() {
|
||||
currentOffset += 3;
|
||||
return ((buffer[currentOffset - 1] & 0xff) << 16)
|
||||
+ ((buffer[currentOffset - 2] & 0xff) << 8)
|
||||
+ (buffer[currentOffset - 3] & 0xff);
|
||||
}
|
||||
|
||||
public int readDWord() {
|
||||
currentOffset += 4;
|
||||
return ((buffer[currentOffset - 4] & 0xff) << 24)
|
||||
+ ((buffer[currentOffset - 3] & 0xff) << 16)
|
||||
+ ((buffer[currentOffset - 2] & 0xff) << 8)
|
||||
+ (buffer[currentOffset - 1] & 0xff);
|
||||
}
|
||||
|
||||
public long readQWord() {
|
||||
long l = readDWord() & 0xffffffffL;
|
||||
long l1 = readDWord() & 0xffffffffL;
|
||||
return (l << 32) + l1;
|
||||
}
|
||||
|
||||
public String readString() {
|
||||
int i = currentOffset;
|
||||
while (buffer[currentOffset++] != 10) {
|
||||
;
|
||||
}
|
||||
return new String(buffer, i, currentOffset - i - 1);
|
||||
}
|
||||
|
||||
public String readNewString() {
|
||||
int i = currentOffset;
|
||||
while (buffer[currentOffset++] != 0) {
|
||||
;
|
||||
}
|
||||
return new String(buffer, i, currentOffset - i - 1);
|
||||
}
|
||||
|
||||
public byte[] readBytes() {
|
||||
int i = currentOffset;
|
||||
while (buffer[currentOffset++] != 10) {
|
||||
;
|
||||
}
|
||||
byte abyte0[] = new byte[currentOffset - i - 1];
|
||||
System.arraycopy(buffer, i, abyte0, i - i, currentOffset - 1 - i);
|
||||
return abyte0;
|
||||
}
|
||||
|
||||
public void readBytes(int i, int j, byte abyte0[]) {
|
||||
for (int l = j; l < j + i; l++) {
|
||||
abyte0[l] = buffer[currentOffset++];
|
||||
}
|
||||
}
|
||||
|
||||
public byte buffer[];
|
||||
public int currentOffset;
|
||||
|
||||
// removed useless static initializer
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package com.rs2.world.clip;
|
||||
|
||||
public class MemoryArchive {
|
||||
|
||||
private final ByteStream cache;
|
||||
private final ByteStream index;
|
||||
private static final int INDEX_DATA_CHUNK_SIZE = 12;
|
||||
|
||||
public MemoryArchive(ByteStream cache, ByteStream index) {
|
||||
this.cache = cache;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public byte[] get(int dataIndex) {
|
||||
try {
|
||||
if (index.length() < dataIndex * INDEX_DATA_CHUNK_SIZE) {
|
||||
return null;
|
||||
}
|
||||
index.setOffset(dataIndex * INDEX_DATA_CHUNK_SIZE);
|
||||
long fileOffset = index.getLong();
|
||||
int fileSize = index.getInt();
|
||||
cache.setOffset(fileOffset);
|
||||
byte[] buffer = cache.read(fileSize);
|
||||
return buffer;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public int contentSize() {
|
||||
return index.length() / 12;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,260 +1,191 @@
|
||||
package com.rs2.world.clip;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.apollo.archive.Archive;
|
||||
import org.apollo.jagcached.fs.IndexedFileSystem;
|
||||
|
||||
public final class ObjectDefinition {
|
||||
|
||||
private static ObjectDefinition[] definitions;
|
||||
|
||||
public static ObjectDefinition getObjectDef(int i) {
|
||||
for (int j = 0; j < 20; j++) {
|
||||
if (cache[j].type == i) {
|
||||
return cache[j];
|
||||
}
|
||||
}
|
||||
|
||||
cacheIndex = (cacheIndex + 1) % 20;
|
||||
ObjectDefinition class46 = cache[cacheIndex];
|
||||
class46.type = i;
|
||||
class46.setDefaults();
|
||||
byte[] buffer = archive.get(i);
|
||||
if (buffer != null && buffer.length > 0) {
|
||||
class46.readValues(new ByteStreamExt(buffer));
|
||||
}
|
||||
return class46;
|
||||
return definitions[i];
|
||||
}
|
||||
|
||||
private void setDefaults() {
|
||||
anIntArray773 = null;
|
||||
anIntArray776 = null;
|
||||
name = null;
|
||||
description = null;
|
||||
modifiedModelColors = null;
|
||||
originalModelColors = null;
|
||||
anInt744 = 1;
|
||||
anInt761 = 1;
|
||||
aBoolean767 = true;
|
||||
aBoolean757 = true;
|
||||
hasActions = false;
|
||||
aBoolean762 = false;
|
||||
aBoolean764 = false;
|
||||
anInt781 = -1;
|
||||
anInt775 = 16;
|
||||
actions = null;
|
||||
anInt746 = -1;
|
||||
anInt758 = -1;
|
||||
aBoolean779 = true;
|
||||
anInt768 = 0;
|
||||
aBoolean736 = false;
|
||||
anInt774 = -1;
|
||||
anInt749 = -1;
|
||||
childrenIDs = null;
|
||||
}
|
||||
|
||||
public static void loadConfig() {
|
||||
archive = new MemoryArchive(new ByteStream(getBuffer("loc.dat")),
|
||||
new ByteStream(getBuffer("loc.idx")));
|
||||
cache = new ObjectDefinition[20];
|
||||
for (int k = 0; k < 20; k++) {
|
||||
cache[k] = new ObjectDefinition();
|
||||
public static void loadConfig(IndexedFileSystem fs) throws IOException {
|
||||
Archive config = Archive.decode(fs.getFile(0, 2));
|
||||
ByteBuffer data = config.getEntry("loc.dat").getBuffer();
|
||||
ByteBuffer idx = config.getEntry("loc.idx").getBuffer();
|
||||
int count = idx.getShort(), index = 2;
|
||||
int[] indices = new int[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
indices[i] = index;
|
||||
index += idx.getShort();
|
||||
}
|
||||
definitions = new ObjectDefinition[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
data.position(indices[i]);
|
||||
definitions[i] = readValues(i, data);
|
||||
}
|
||||
System.out.println("[ObjectDef] DONE LOADING OBJECT CONFIGURATION");
|
||||
}
|
||||
|
||||
public static byte[] getBuffer(String s) {
|
||||
try {
|
||||
java.io.File f = new java.io.File("./data/world/object/" + s);
|
||||
if (!f.exists()) {
|
||||
return null;
|
||||
}
|
||||
byte[] buffer = new byte[(int) f.length()];
|
||||
java.io.DataInputStream dis = new java.io.DataInputStream(
|
||||
new java.io.FileInputStream(f));
|
||||
dis.readFully(buffer);
|
||||
dis.close();
|
||||
return buffer;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private static ObjectDefinition readValues(int id, ByteBuffer data) {
|
||||
ObjectDefinition def = new ObjectDefinition();
|
||||
def.type = id;
|
||||
int[] modelId = null;
|
||||
int[] modelType = null;
|
||||
|
||||
private void readValues(ByteStreamExt stream) {
|
||||
int flag = -1;
|
||||
boolean actions = false;
|
||||
do {
|
||||
int type = stream.readUnsignedByte();
|
||||
int type = data.get() & 0xFF;
|
||||
if (type == 0) {
|
||||
break;
|
||||
}
|
||||
if (type == 1) {
|
||||
int len = stream.readUnsignedByte();
|
||||
int len = data.get() & 0xFF;
|
||||
if (len > 0) {
|
||||
if (anIntArray773 == null || lowMem) {
|
||||
anIntArray776 = new int[len];
|
||||
anIntArray773 = new int[len];
|
||||
if (modelId == null) {
|
||||
modelType = new int[len];
|
||||
modelId = new int[len];
|
||||
for (int k1 = 0; k1 < len; k1++) {
|
||||
anIntArray773[k1] = stream.readUnsignedWord();
|
||||
anIntArray776[k1] = stream.readUnsignedByte();
|
||||
modelId[k1] = data.getShort() & 0xFFFF;
|
||||
modelType[k1] = data.get() & 0xFF;
|
||||
}
|
||||
} else {
|
||||
stream.currentOffset += len * 3;
|
||||
for (int i = 0; i < len; i++) {
|
||||
data.getShort();
|
||||
data.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (type == 2) {
|
||||
name = stream.readNewString();
|
||||
def.name = readString(data);
|
||||
} else if (type == 3) {
|
||||
readString(data);
|
||||
} else if (type == 5) {
|
||||
int len = stream.readUnsignedByte();
|
||||
int len = data.get() & 0xFF;
|
||||
if (len > 0) {
|
||||
if (anIntArray773 == null || lowMem) {
|
||||
anIntArray776 = null;
|
||||
anIntArray773 = new int[len];
|
||||
if (modelId == null) {
|
||||
modelType = null;
|
||||
modelId = new int[len];
|
||||
for (int l1 = 0; l1 < len; l1++) {
|
||||
anIntArray773[l1] = stream.readUnsignedWord();
|
||||
modelId[l1] = data.getShort() & 0xFFFF;
|
||||
}
|
||||
} else {
|
||||
stream.currentOffset += len * 2;
|
||||
for (int i = 0; i < len; i++) {
|
||||
data.getShort();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (type == 14) {
|
||||
anInt744 = stream.readUnsignedByte();
|
||||
def.width = data.get() & 0xFF;
|
||||
} else if (type == 15) {
|
||||
anInt761 = stream.readUnsignedByte();
|
||||
def.length = data.get() & 0xFF;
|
||||
} else if (type == 17) {
|
||||
aBoolean767 = false;
|
||||
def.solid = false;
|
||||
} else if (type == 18) {
|
||||
aBoolean757 = false;
|
||||
def.impenetrable = false;
|
||||
} else if (type == 19) {
|
||||
hasActions = stream.readUnsignedByte() == 1;
|
||||
flag = data.get() & 0xFF;
|
||||
def.hasActions = flag == 1;
|
||||
} else if (type == 21) {
|
||||
aBoolean762 = true;
|
||||
// aBoolean762 = true;
|
||||
} else if (type == 22) {
|
||||
} else if (type == 23) {
|
||||
aBoolean764 = true;
|
||||
// aBoolean764 = true;
|
||||
} else if (type == 24) {
|
||||
anInt781 = stream.readUnsignedWord();
|
||||
if (anInt781 == 65535) {
|
||||
anInt781 = -1;
|
||||
}
|
||||
data.getShort();
|
||||
} else if (type == 27) {
|
||||
continue;
|
||||
} else if (type == 28) {
|
||||
anInt775 = stream.readUnsignedByte();
|
||||
data.get();
|
||||
} else if (type == 29) {
|
||||
stream.readSignedByte();
|
||||
data.get();
|
||||
} else if (type == 39) {
|
||||
stream.readSignedByte();
|
||||
data.get();
|
||||
} else if (type >= 30 && type < 39) {
|
||||
if (actions == null) {
|
||||
actions = new String[5];
|
||||
}
|
||||
actions[type - 30] = stream.readNewString();
|
||||
hasActions = true;
|
||||
if (actions[type - 30].equalsIgnoreCase("hidden")) {
|
||||
actions[type - 30] = null;
|
||||
}
|
||||
actions = true;
|
||||
readString(data);
|
||||
def.hasActions = true;
|
||||
} else if (type == 40) {
|
||||
int i1 = stream.readUnsignedByte();
|
||||
modifiedModelColors = new int[i1];
|
||||
originalModelColors = new int[i1];
|
||||
for (int i2 = 0; i2 < i1; i2++) {
|
||||
modifiedModelColors[i2] = stream.readUnsignedWord();
|
||||
originalModelColors[i2] = stream.readUnsignedWord();
|
||||
int amount = data.get() & 0xFF;
|
||||
for (int i = 0; i < amount; i++) {
|
||||
data.getShort();
|
||||
data.getShort();
|
||||
}
|
||||
|
||||
} else if (type == 41) {
|
||||
int l = stream.readUnsignedByte();
|
||||
stream.skip(l * 4);
|
||||
} else if (type == 42) {
|
||||
int l = stream.readUnsignedByte();
|
||||
stream.skip(l);
|
||||
} else if (type == 60) {
|
||||
anInt746 = stream.readUnsignedWord();
|
||||
data.getShort();
|
||||
} else if (type == 62) {
|
||||
} else if (type == 64) {
|
||||
aBoolean779 = false;
|
||||
def.clipped = false;
|
||||
} else if (type == 65) {
|
||||
stream.readUnsignedWord();
|
||||
data.getShort();
|
||||
} else if (type == 66) {
|
||||
stream.readUnsignedWord();
|
||||
data.getShort();
|
||||
} else if (type == 67) {
|
||||
stream.readUnsignedWord();
|
||||
data.getShort();
|
||||
} else if (type == 68) {
|
||||
anInt758 = stream.readUnsignedWord();
|
||||
data.getShort();
|
||||
} else if (type == 69) {
|
||||
anInt768 = stream.readUnsignedByte();
|
||||
data.get();
|
||||
} else if (type == 70) {
|
||||
stream.readSignedWord();
|
||||
data.getShort();
|
||||
} else if (type == 71) {
|
||||
stream.readSignedWord();
|
||||
data.getShort();
|
||||
} else if (type == 72) {
|
||||
stream.readSignedWord();
|
||||
data.getShort();
|
||||
} else if (type == 73) {
|
||||
aBoolean736 = true;
|
||||
// #TODO obstructive = true;
|
||||
} else if (type == 74) {
|
||||
} else if (type == 75) {
|
||||
stream.readUnsignedByte();
|
||||
} else if (type == 77 || type == 92) {
|
||||
anInt774 = stream.readUnsignedWord();
|
||||
if (anInt774 == 65535) {
|
||||
anInt774 = -1;
|
||||
}
|
||||
anInt749 = stream.readUnsignedWord();
|
||||
if (anInt749 == 65535) {
|
||||
anInt749 = -1;
|
||||
}
|
||||
int endChild = -1;
|
||||
if (type == 92) {
|
||||
endChild = stream.readUnsignedWord();
|
||||
if (endChild == 65535) {
|
||||
endChild = -1;
|
||||
}
|
||||
}
|
||||
int j1 = stream.readUnsignedByte();
|
||||
childrenIDs = new int[j1 + 2];
|
||||
for (int j2 = 0; j2 <= j1; j2++) {
|
||||
childrenIDs[j2] = stream.readUnsignedWord();
|
||||
if (childrenIDs[j2] == 65535) {
|
||||
childrenIDs[j2] = -1;
|
||||
}
|
||||
}
|
||||
childrenIDs[j1 + 1] = endChild;
|
||||
} else if (type == 78) {
|
||||
stream.skip(3);
|
||||
} else if (type == 79) {
|
||||
stream.skip(5);
|
||||
int l = stream.readUnsignedByte();
|
||||
stream.skip(l * 2);
|
||||
} else if (type == 81) {
|
||||
stream.skip(1);
|
||||
} else if (type == 82 || type == 88 || type == 89 || type == 90
|
||||
|| type == 91 || type == 94 || type == 95 || type == 96
|
||||
|| type == 97) {
|
||||
continue;
|
||||
} else if (type == 93) {
|
||||
stream.skip(2);
|
||||
} else if (type == 249) {
|
||||
int l = stream.readUnsignedByte();
|
||||
for (int ii = 0; ii < l; ii++) {
|
||||
boolean b = stream.readUnsignedByte() == 1;
|
||||
stream.skip(3);
|
||||
if (b) {
|
||||
stream.readNewString();
|
||||
} else {
|
||||
stream.skip(4);
|
||||
}
|
||||
data.get();
|
||||
} else if (type == 77) {
|
||||
data.getShort();
|
||||
data.getShort();
|
||||
int count = data.get() & 0xFF;
|
||||
for (int i = 0; i <= count; i++) {
|
||||
data.getShort();
|
||||
}
|
||||
} else {
|
||||
System.out.println("Unknown config: " + type);
|
||||
System.out.println("Unknown config: " + type);
|
||||
System.exit(0);
|
||||
}
|
||||
} while (true);
|
||||
if (flag == -1) {
|
||||
hasActions = anIntArray773 != null
|
||||
&& (anIntArray776 == null || anIntArray776[0] == 10);
|
||||
if (actions != null) {
|
||||
hasActions = true;
|
||||
def.hasActions = modelId != null && (modelType == null || modelType[0] == 10);
|
||||
if (actions) {
|
||||
def.hasActions = true;
|
||||
}
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a string from the specified {@link ByteBuffer}.
|
||||
*
|
||||
* @param buffer The buffer.
|
||||
* @return The string.
|
||||
*/
|
||||
public static String readString(ByteBuffer buffer) {
|
||||
StringBuilder bldr = new StringBuilder();
|
||||
char character;
|
||||
while ((character = (char) buffer.get()) != 10) {
|
||||
bldr.append(character);
|
||||
}
|
||||
return bldr.toString();
|
||||
}
|
||||
|
||||
private ObjectDefinition() {
|
||||
type = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO is this needed? Only called by type 22 objects (ground decorations/map signs).
|
||||
*/
|
||||
public boolean hasActions() {
|
||||
return hasActions;
|
||||
}
|
||||
@@ -264,53 +195,32 @@ public final class ObjectDefinition {
|
||||
}
|
||||
|
||||
public boolean solid() {
|
||||
return aBoolean779;
|
||||
return clipped;
|
||||
}
|
||||
|
||||
public int xLength() {
|
||||
return anInt744;
|
||||
return width;
|
||||
}
|
||||
|
||||
public int yLength() {
|
||||
return anInt761;
|
||||
return length;
|
||||
}
|
||||
|
||||
public boolean aBoolean767() {
|
||||
return aBoolean767;
|
||||
return solid;
|
||||
}
|
||||
|
||||
public boolean isUnshootable() {
|
||||
return aBoolean757;
|
||||
return impenetrable;
|
||||
}
|
||||
|
||||
public boolean aBoolean736;
|
||||
public String name;
|
||||
public int anInt744;
|
||||
public int anInt746;
|
||||
private int[] originalModelColors;
|
||||
public int anInt749;
|
||||
public static boolean lowMem;
|
||||
public int type;
|
||||
public boolean aBoolean757;
|
||||
public int anInt758;
|
||||
public int childrenIDs[];
|
||||
public int anInt761;
|
||||
public boolean aBoolean762;
|
||||
public boolean aBoolean764;
|
||||
public boolean aBoolean767;
|
||||
public int anInt768;
|
||||
private static int cacheIndex;
|
||||
private int[] anIntArray773;
|
||||
public int anInt774;
|
||||
public int anInt775;
|
||||
private int[] anIntArray776;
|
||||
public byte description[];
|
||||
public boolean hasActions;
|
||||
public boolean aBoolean779;
|
||||
public int anInt781;
|
||||
private static ObjectDefinition[] cache;
|
||||
private int[] modifiedModelColors;
|
||||
public String actions[];
|
||||
private static MemoryArchive archive;
|
||||
|
||||
public String name = null;
|
||||
private int width = 1;
|
||||
@SuppressWarnings("unused")
|
||||
private int type;
|
||||
private boolean impenetrable = true;
|
||||
private int length = 1;
|
||||
private boolean solid = true;
|
||||
private boolean hasActions = false;
|
||||
private boolean clipped = true;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
package com.rs2.world.clip;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.apollo.archive.Archive;
|
||||
import org.apollo.archive.ArchiveEntry;
|
||||
import org.apollo.archive.CompressionUtil;
|
||||
import org.apollo.jagcached.Constants;
|
||||
import org.apollo.jagcached.fs.IndexedFileSystem;
|
||||
|
||||
public class RegionFactory {
|
||||
|
||||
@@ -17,13 +22,14 @@ public class RegionFactory {
|
||||
public static void load() {
|
||||
//GameEngine.getLogger(Region.class).info("Loading region configurations...");
|
||||
try {
|
||||
File f = new File("./data/world/map_index");
|
||||
byte[] buffer = new byte[(int) f.length()];
|
||||
DataInputStream dis = new DataInputStream(new FileInputStream(f));
|
||||
dis.readFully(buffer);
|
||||
dis.close();
|
||||
ByteStream in = new ByteStream(buffer);
|
||||
int size = in.length() / 7;
|
||||
IndexedFileSystem fs = new IndexedFileSystem(new File(Constants.FILE_SYSTEM_DIR), true);
|
||||
ObjectDefinition.loadConfig(fs);
|
||||
|
||||
Archive archive = Archive.decode(fs.getFile(0, 5));
|
||||
ArchiveEntry entry = archive.getEntry("map_index");
|
||||
ByteBuffer buffer = entry.getBuffer();
|
||||
|
||||
int size = buffer.capacity() / 7;
|
||||
regions = new Region[size];
|
||||
int[] regionIds = new int[size];
|
||||
int[] mapGroundFileIds = new int[size];
|
||||
@@ -37,10 +43,10 @@ public class RegionFactory {
|
||||
* isMembers (8 bits)
|
||||
*/
|
||||
for (int i = 0; i < size; i++) {
|
||||
regionIds[i] = in.getUShort();
|
||||
mapGroundFileIds[i] = in.getUShort();
|
||||
mapObjectsFileIds[i] = in.getUShort();
|
||||
isMembers[i] = in.getUByte() == 0;
|
||||
regionIds[i] = buffer.getShort() & 0xFFFF;
|
||||
mapGroundFileIds[i] = buffer.getShort() & 0xFFFF;
|
||||
mapObjectsFileIds[i] = buffer.getShort() & 0xFFFF;
|
||||
isMembers[i] = buffer.get() == 0;
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
regions[i] = new Region(regionIds[i], isMembers[i]);
|
||||
@@ -49,11 +55,9 @@ public class RegionFactory {
|
||||
//GameEngine.getLogger(Region.class).info("Populating regions...");
|
||||
for (int i = 0; i < size; i++) {
|
||||
//GameEngine.getLogger(Region.class).info("Region: " + i + " RegionId: " + regionIds[i] + " ObjectsId: " + mapObjectsFileIds[i]
|
||||
// + " ClippingsId: " + mapGroundFileIds[i]);
|
||||
byte[] file1 = getBuffer(new File("./data/world/map/"
|
||||
+ mapObjectsFileIds[i] + ".gz"));
|
||||
byte[] file2 = getBuffer(new File("./data/world/map/"
|
||||
+ mapGroundFileIds[i] + ".gz"));
|
||||
// + " ClippingsId: " + mapGroundFileIds[i]);
|
||||
byte[] file1 = CompressionUtil.degzip(fs.getFileBytes(4, mapObjectsFileIds[i]));
|
||||
byte[] file2 = CompressionUtil.degzip(fs.getFileBytes(4, mapGroundFileIds[i]));
|
||||
if (file1 == null || file2 == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -158,39 +162,4 @@ public class RegionFactory {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] getBuffer(File f) throws Exception {
|
||||
if (!f.exists()) {
|
||||
return null;
|
||||
}
|
||||
byte[] buffer = new byte[(int) f.length()];
|
||||
DataInputStream dis = new DataInputStream(new FileInputStream(f));
|
||||
dis.readFully(buffer);
|
||||
dis.close();
|
||||
byte[] gzipInputBuffer = new byte[999999];
|
||||
int bufferlength = 0;
|
||||
GZIPInputStream gzip = new GZIPInputStream(new ByteArrayInputStream(
|
||||
buffer));
|
||||
do {
|
||||
if (bufferlength == gzipInputBuffer.length) {
|
||||
System.out
|
||||
.println("Error inflating data.\nGZIP buffer overflow.");
|
||||
break;
|
||||
}
|
||||
int readByte = gzip.read(gzipInputBuffer, bufferlength,
|
||||
gzipInputBuffer.length - bufferlength);
|
||||
if (readByte == -1) {
|
||||
break;
|
||||
}
|
||||
bufferlength += readByte;
|
||||
} while (true);
|
||||
byte[] inflated = new byte[bufferlength];
|
||||
System.arraycopy(gzipInputBuffer, 0, inflated, 0, bufferlength);
|
||||
buffer = inflated;
|
||||
if (buffer.length < 10) {
|
||||
return null;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
package org.apollo.archive;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
|
||||
|
||||
/**
|
||||
* Represents an archive.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public final class Archive {
|
||||
|
||||
/**
|
||||
* Decodes the archive in the specified buffer.
|
||||
*
|
||||
* @param buffer The buffer.
|
||||
* @return The archive.
|
||||
* @throws IOException If there is an error decompressing the archive.
|
||||
*/
|
||||
public static Archive decode(ByteBuffer buffer) throws IOException {
|
||||
int extractedSize = Archive.readUnsignedMedium(buffer);
|
||||
int size = Archive.readUnsignedMedium(buffer);
|
||||
boolean extracted = false;
|
||||
|
||||
if (size != extractedSize) {
|
||||
byte[] compressed = new byte[size];
|
||||
byte[] decompressed = new byte[extractedSize];
|
||||
buffer.get(compressed);
|
||||
Archive.debzip2(compressed, decompressed);
|
||||
buffer = ByteBuffer.wrap(decompressed);
|
||||
extracted = true;
|
||||
}
|
||||
|
||||
int entryCount = buffer.getShort() & 0xFFFF;
|
||||
int[] identifiers = new int[entryCount];
|
||||
int[] extractedSizes = new int[entryCount];
|
||||
int[] sizes = new int[entryCount];
|
||||
|
||||
for (int i = 0; i < entryCount; i++) {
|
||||
identifiers[i] = buffer.getInt();
|
||||
extractedSizes[i] = Archive.readUnsignedMedium(buffer);
|
||||
sizes[i] = Archive.readUnsignedMedium(buffer);
|
||||
}
|
||||
|
||||
ArchiveEntry[] entries = new ArchiveEntry[entryCount];
|
||||
for (int entry = 0; entry < entryCount; entry++) {
|
||||
ByteBuffer entryBuffer;
|
||||
if (!extracted) {
|
||||
byte[] compressed = new byte[sizes[entry]];
|
||||
byte[] decompressed = new byte[extractedSizes[entry]];
|
||||
buffer.get(compressed);
|
||||
Archive.debzip2(compressed, decompressed);
|
||||
entryBuffer = ByteBuffer.wrap(decompressed);
|
||||
} else {
|
||||
byte[] buf = new byte[extractedSizes[entry]];
|
||||
buffer.get(buf);
|
||||
entryBuffer = ByteBuffer.wrap(buf);
|
||||
}
|
||||
entries[entry] = new ArchiveEntry(identifiers[entry], entryBuffer);
|
||||
}
|
||||
return new Archive(entries);
|
||||
}
|
||||
|
||||
/**
|
||||
* The entries in this archive.
|
||||
*/
|
||||
private final ArchiveEntry[] entries;
|
||||
|
||||
/**
|
||||
* Creates a new archive.
|
||||
*
|
||||
* @param entries The entries in this archive.
|
||||
*/
|
||||
public Archive(ArchiveEntry[] entries) {
|
||||
this.entries = entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an {@link ArchiveEntry} by its name.
|
||||
*
|
||||
* @param name The name.
|
||||
* @return The entry.
|
||||
* @throws FileNotFoundException If the entry could not be found.
|
||||
*/
|
||||
public ArchiveEntry getEntry(String name) throws FileNotFoundException {
|
||||
int hash = hash(name);
|
||||
|
||||
for (ArchiveEntry entry : entries) {
|
||||
if (entry.getIdentifier() == hash) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
throw new FileNotFoundException("Could not find entry: " + name + ".");
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashes the specified string into an integer used to identify an {@link ArchiveEntry}.
|
||||
*
|
||||
* @param name The name of the entry.
|
||||
* @return The hash.
|
||||
*/
|
||||
public static int hash(String name) {
|
||||
return name.toUpperCase().chars().reduce(0, (hash, character) -> hash * 61 + character - 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* Debzip2s the compressed array and places the result into the decompressed array.
|
||||
*
|
||||
* @param compressed The compressed array, <strong>without</strong> the header.
|
||||
* @param decompressed The decompressed array.
|
||||
* @throws IOException If there is an error decompressing the array.
|
||||
*/
|
||||
private static void debzip2(byte[] compressed, byte[] decompressed) throws IOException {
|
||||
byte[] newCompressed = new byte[compressed.length + 4];
|
||||
newCompressed[0] = 'B';
|
||||
newCompressed[1] = 'Z';
|
||||
newCompressed[2] = 'h';
|
||||
newCompressed[3] = '1';
|
||||
System.arraycopy(compressed, 0, newCompressed, 4, compressed.length);
|
||||
|
||||
try (DataInputStream is = new DataInputStream(new BZip2CompressorInputStream(new ByteArrayInputStream(newCompressed)))) {
|
||||
is.readFully(decompressed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a 24-bit medium integer from the specified {@link ByteBuffer}s current position and increases the buffers
|
||||
* position by 3.
|
||||
*
|
||||
* @param buffer The {@link ByteBuffer} to read from.
|
||||
* @return The read 24-bit medium integer.
|
||||
*/
|
||||
private static int readUnsignedMedium(ByteBuffer buffer) {
|
||||
return (buffer.getShort() & 0xFFFF) << 8 | buffer.get() & 0xFF;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.apollo.archive;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Represents a single entry in an {@link Archive}.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public final class ArchiveEntry {
|
||||
|
||||
/**
|
||||
* The buffer of this entry.
|
||||
*/
|
||||
private final ByteBuffer buffer;
|
||||
|
||||
/**
|
||||
* The identifier of this entry.
|
||||
*/
|
||||
private final int identifier;
|
||||
|
||||
/**
|
||||
* Creates a new archive entry.
|
||||
*
|
||||
* @param identifier The identifier.
|
||||
* @param buffer The buffer.
|
||||
*/
|
||||
public ArchiveEntry(int identifier, ByteBuffer buffer) {
|
||||
this.identifier = identifier;
|
||||
this.buffer = buffer.asReadOnlyBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the buffer of this entry.
|
||||
*
|
||||
* @return This buffer of this entry.
|
||||
*/
|
||||
public ByteBuffer getBuffer() {
|
||||
return buffer.duplicate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the identifier of this entry.
|
||||
*
|
||||
* @return The identifier of this entry.
|
||||
*/
|
||||
public int getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package org.apollo.archive;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream;
|
||||
|
||||
/**
|
||||
* A utility class for performing compression/decompression.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public final class CompressionUtil {
|
||||
|
||||
/**
|
||||
* Degzips the compressed array and places the results into the decompressed array.
|
||||
*
|
||||
* @param compressed The compressed array.
|
||||
* @param decompressed The decompressed array.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
*/
|
||||
public static void degzip(byte[] compressed, byte[] decompressed) throws IOException {
|
||||
try (DataInputStream is = new DataInputStream(new GZIPInputStream(new ByteArrayInputStream(compressed)))) {
|
||||
is.readFully(decompressed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Degzips <strong>all</strong> of the datain the specified {@link ByteBuffer}.
|
||||
*
|
||||
* @param compressed The compressed buffer.
|
||||
* @return The decompressed array.
|
||||
* @throws IOException If there is an error decompressing the buffer.
|
||||
*/
|
||||
public static byte[] degzip(ByteBuffer compressed) throws IOException {
|
||||
try (InputStream is = new GZIPInputStream(new ByteArrayInputStream(compressed.array()));
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream()) {
|
||||
byte[] buffer = new byte[1024];
|
||||
|
||||
while (true) {
|
||||
int read = is.read(buffer, 0, buffer.length);
|
||||
if (read == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
out.write(buffer, 0, read);
|
||||
}
|
||||
|
||||
return out.toByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gzips the specified array.
|
||||
*
|
||||
* @param uncompressed The uncompressed array.
|
||||
* @return The compressed array.
|
||||
* @throws IOException If there is an error compressing the array.
|
||||
*/
|
||||
public static byte[] gzip(byte[] uncompressed) throws IOException {
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
|
||||
try (DeflaterOutputStream os = new GZIPOutputStream(bout)) {
|
||||
os.write(uncompressed);
|
||||
os.finish();
|
||||
return bout.toByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default private constructor to prevent instantiation.
|
||||
*/
|
||||
private CompressionUtil() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Was originally from RegionFactory and titled getBuffer where it loaded off the FS rather than cache.
|
||||
* #TODO testing on this vs the methods from Apollo above.
|
||||
*/
|
||||
public static byte[] degzip(byte[] buffer) throws Exception {
|
||||
byte[] gzipInputBuffer = new byte[999999];
|
||||
int bufferlength = 0;
|
||||
GZIPInputStream gzip = new GZIPInputStream(new ByteArrayInputStream(
|
||||
buffer));
|
||||
do {
|
||||
if (bufferlength == gzipInputBuffer.length) {
|
||||
System.out
|
||||
.println("Error inflating data.\nGZIP buffer overflow.");
|
||||
break;
|
||||
}
|
||||
int readByte = gzip.read(gzipInputBuffer, bufferlength,
|
||||
gzipInputBuffer.length - bufferlength);
|
||||
if (readByte == -1) {
|
||||
break;
|
||||
}
|
||||
bufferlength += readByte;
|
||||
} while (true);
|
||||
byte[] inflated = new byte[bufferlength];
|
||||
System.arraycopy(gzipInputBuffer, 0, inflated, 0, bufferlength);
|
||||
buffer = inflated;
|
||||
if (buffer.length < 10) {
|
||||
return null;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -269,6 +269,78 @@ public final class IndexedFileSystem implements Closeable {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public byte[] getFileBytes(int type, int file) throws IOException {
|
||||
return getFileBytes(new FileDescriptor(type, file));
|
||||
}
|
||||
|
||||
public byte[] getFileBytes(FileDescriptor fd) throws IOException {
|
||||
Index index = getIndex(fd);
|
||||
byte[] decompressed = new byte[index.getSize()];
|
||||
|
||||
// calculate some initial values
|
||||
long ptr = (long) index.getBlock() * (long) FileSystemConstants.BLOCK_SIZE;
|
||||
int read = 0;
|
||||
int size = index.getSize();
|
||||
int blocks = size / FileSystemConstants.CHUNK_SIZE;
|
||||
if (size % FileSystemConstants.CHUNK_SIZE != 0) {
|
||||
blocks++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < blocks; i++) {
|
||||
|
||||
// read header
|
||||
byte[] header = new byte[FileSystemConstants.HEADER_SIZE];
|
||||
synchronized (data) {
|
||||
data.seek(ptr);
|
||||
data.readFully(header);
|
||||
}
|
||||
|
||||
// increment pointers
|
||||
ptr += FileSystemConstants.HEADER_SIZE;
|
||||
|
||||
// parse header
|
||||
int nextFile = ((header[0] & 0xFF) << 8) | (header[1] & 0xFF);
|
||||
int curChunk = ((header[2] & 0xFF) << 8) | (header[3] & 0xFF);
|
||||
int nextBlock = ((header[4] & 0xFF) << 16) | ((header[5] & 0xFF) << 8) | (header[6] & 0xFF);
|
||||
int nextType = header[7] & 0xFF;
|
||||
|
||||
// check expected chunk id is correct
|
||||
if (i != curChunk) {
|
||||
throw new IOException("Chunk id mismatch.");
|
||||
}
|
||||
|
||||
// calculate how much we can read
|
||||
int chunkSize = size - read;
|
||||
if (chunkSize > FileSystemConstants.CHUNK_SIZE) {
|
||||
chunkSize = FileSystemConstants.CHUNK_SIZE;
|
||||
}
|
||||
|
||||
// read the next chunk and put it in the buffer
|
||||
synchronized (data) {
|
||||
data.seek(ptr);
|
||||
data.readFully(decompressed, read, chunkSize);
|
||||
}
|
||||
|
||||
// increment pointers
|
||||
read += chunkSize;
|
||||
ptr = (long) nextBlock * (long) FileSystemConstants.BLOCK_SIZE;
|
||||
|
||||
// if we still have more data to read, check the validity of the
|
||||
// header
|
||||
if (size > read) {
|
||||
if (nextType != (fd.getType() + 1)) {
|
||||
throw new IOException("File type mismatch.");
|
||||
}
|
||||
|
||||
if (nextFile != fd.getFile()) {
|
||||
throw new IOException("File id mismatch.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return decompressed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (data != null) {
|
||||
|
||||
Reference in New Issue
Block a user