diff --git a/src/main/java/net/runelite/cache/definitions/Definition.java b/src/main/java/net/runelite/cache/definitions/Definition.java deleted file mode 100644 index 6e52de526c..0000000000 --- a/src/main/java/net/runelite/cache/definitions/Definition.java +++ /dev/null @@ -1,38 +0,0 @@ -package net.runelite.cache.definitions; - -import net.runelite.cache.io.InputStream; - - -/** - * Created by Allen Kinzalow on 3/14/2015. - */ -public abstract class Definition { - - int definitionID; - - public Definition(int definitionID) { - this.definitionID = definitionID; - } - - //abstract OutputStream encode(OutputStream stream); - - public void decode(InputStream stream) { - while(true) { - int opcode = stream.readUnsignedByte(); - if(opcode == 0) { - return; - } - - this.decodeValues(opcode, stream); - } - } - - abstract void decodeValues(int opcode, InputStream stream); - - //public abstract void printDefinition(); - - public int getDefinitionID() { - return this.definitionID; - } - -} diff --git a/src/main/java/net/runelite/cache/definitions/NPCDefinition.java b/src/main/java/net/runelite/cache/definitions/NPCDefinition.java deleted file mode 100644 index b0a9b4a8e6..0000000000 --- a/src/main/java/net/runelite/cache/definitions/NPCDefinition.java +++ /dev/null @@ -1,164 +0,0 @@ -//package net.runelite.cache.definitions; -// -//import net.runelite.cache.io.InputStream; -//import net.runelite.cache.utils.StringUtilities; -// -///** -// * Created by Allen Kinzalow on 3/15/2015. -// */ -//public class NPCDefinition extends Definition { -// -// public final static int INDEX_ID = 2; -// public final static int ARCHIVE_ID = 9; -// -// public short[] recolorToFind; -// public int anInt2156 = 32; -// public String name = "null"; -// public short[] recolorToReplace; -// public int[] models; -// public int[] models_2; -// public int stanceAnimation = -1; -// public int anInt2165 = -1; -// public int tileSpacesOccupied = 1; -// public int walkAnimation = -1; -// public short[] retextureToReplace; -// public int rotate90RightAnimation = -1; -// public boolean aBool2170 = true; -// public int resizeX = 128; -// public int contrast = 0; -// public int rotate180Animation = -1; -// public int anInt2174 = -1; -// public String[] options = new String[5]; -// public boolean renderOnMinimap = true; -// public int combatLevel = -1; -// public int rotate90LeftAnimation = -1; -// public int resizeY = 128; -// public boolean hasRenderPriority = false; -// public int ambient = 0; -// public int headIcon = -1; -// public int anInt2184 = 30; -// public int[] anIntArray2185; -// public short[] retextureToFind; -// public int anInt2187 = -1; -// public boolean isClickable = true; -// public int anInt2189 = -1; -// public boolean aBool2190 = false; -// -// public NPCDefinition(int definitionID) { -// super(definitionID); -// } -// -// @Override -// void decodeValues(int opcode, InputStream stream) { -// int length; -// int index; -// if(1 == opcode) { -// length = stream.readUnsignedByte(); -// this.models = new int[length]; -// -// for(index = 0; index < length; ++index) { -// this.models[index] = stream.readUnsignedShort(); -// } -// -// } else if(2 == opcode) { -// this.name = StringUtilities.readString_2(stream); -// } else if(12 == opcode) { -// this.tileSpacesOccupied = stream.readUnsignedShort(); -// } else if(opcode == 13) { -// this.stanceAnimation = stream.readUnsignedShort(); -// } else if(opcode == 14) { -// this.walkAnimation = stream.readUnsignedShort(); -// } else if(15 == opcode) { -// this.anInt2165 = stream.readUnsignedShort(); -// } else if(opcode == 16) { -// this.anInt2189 = stream.readUnsignedShort(); -// } else if(17 == opcode) { -// this.walkAnimation = stream.readUnsignedShort(); -// this.rotate180Animation = stream.readUnsignedShort(); -// this.rotate90RightAnimation = stream.readUnsignedShort(); -// this.rotate90LeftAnimation = stream.readUnsignedShort(); -// } else if(opcode >= 30 && opcode < 35) { -// this.options[opcode - 30] = StringUtilities.readString_2(stream); -// if(this.options[opcode - 30].equalsIgnoreCase("Hidden")) { -// this.options[opcode - 30] = null; -// } -// } else if(opcode == 40) { -// length = stream.readUnsignedByte(); -// this.recolorToFind = new short[length]; -// this.recolorToReplace = new short[length]; -// -// for(index = 0; index < length; ++index) { -// this.recolorToFind[index] = (short)stream.readUnsignedShort(); -// this.recolorToReplace[index] = (short)stream.readUnsignedShort(); -// } -// -// } else if(opcode == 41) { -// length = stream.readUnsignedByte(); -// this.retextureToFind = new short[length]; -// this.retextureToReplace = new short[length]; -// -// for(index = 0; index < length; ++index) { -// this.retextureToFind[index] = (short)stream.readUnsignedShort(); -// this.retextureToReplace[index] = (short)stream.readUnsignedShort(); -// } -// -// } else if(60 != opcode) { -// if(opcode == 93) { -// this.renderOnMinimap = false; -// } else if(95 == opcode) { -// this.combatLevel = stream.readUnsignedShort(); -// } else if(97 == opcode) { -// this.resizeX = stream.readUnsignedShort(); -// } else if(98 == opcode) { -// this.resizeY = stream.readUnsignedShort(); -// } else if(opcode == 99) { -// this.hasRenderPriority = true; -// } else if(100 == opcode) { -// this.ambient = stream.readByte(); -// } else if(101 == opcode) { -// this.contrast = stream.readByte(); -// } else if(opcode == 102) { -// this.headIcon = stream.readUnsignedShort(); -// } else if(103 == opcode) { -// this.anInt2156 = stream.readUnsignedShort(); -// } else if(opcode == 106) { -// this.anInt2174 = stream.readUnsignedShort(); -// if('\uffff' == this.anInt2174) { -// this.anInt2174 = -1; -// } -// -// this.anInt2187 = stream.readUnsignedShort(); -// if('\uffff' == this.anInt2187) { -// this.anInt2187 = -40212193; -// } -// -// length = stream.readUnsignedByte(); -// this.anIntArray2185 = new int[length + 1]; -// -// for(index = 0; index <= length; ++index) { -// this.anIntArray2185[index] = stream.readUnsignedShort(); -// if(this.anIntArray2185[index] == '\uffff') { -// this.anIntArray2185[index] = -1; -// } -// } -// -// } else if(107 == opcode) { -// this.isClickable = false; -// } else if(opcode == 109) { -// this.aBool2170 = false; -// } else if(opcode == 111) { -// this.aBool2190 = true; -// } else if(opcode == 112) { -// this.anInt2184 = stream.readUnsignedByte(); -// } -// } else { -// length = stream.readUnsignedByte(); -// this.models_2 = new int[length]; -// -// for(index = 0; index < length; ++index) { -// this.models_2[index] = stream.readUnsignedShort(); -// } -// -// } -// } -//} diff --git a/src/main/java/net/runelite/cache/definitions/NpcDefinition.java b/src/main/java/net/runelite/cache/definitions/NpcDefinition.java new file mode 100644 index 0000000000..eb51dd172e --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/NpcDefinition.java @@ -0,0 +1,44 @@ +package net.runelite.cache.definitions; + +public class NpcDefinition +{ + + public int id; + public short[] recolorToFind; + public int anInt2156 = 32; + public String name = "null"; + public short[] recolorToReplace; + public int[] models; + public int[] models_2; + public int stanceAnimation = -1; + public int anInt2165 = -1; + public int tileSpacesOccupied = 1; + public int walkAnimation = -1; + public short[] retextureToReplace; + public int rotate90RightAnimation = -1; + public boolean aBool2170 = true; + public int resizeX = 128; + public int contrast = 0; + public int rotate180Animation = -1; + public int anInt2174 = -1; + public String[] options = new String[5]; + public boolean renderOnMinimap = true; + public int combatLevel = -1; + public int rotate90LeftAnimation = -1; + public int resizeY = 128; + public boolean hasRenderPriority = false; + public int ambient = 0; + public int headIcon = -1; + public int anInt2184 = 30; + public int[] anIntArray2185; + public short[] retextureToFind; + public int anInt2187 = -1; + public boolean isClickable = true; + public int anInt2189 = -1; + public boolean aBool2190 = false; + + public NpcDefinition(int definitionID) + { + this.id = definitionID; + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/NpcLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/NpcLoader.java new file mode 100644 index 0000000000..c80c4be823 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/NpcLoader.java @@ -0,0 +1,212 @@ +package net.runelite.cache.definitions.loaders; + +import java.util.ArrayList; +import java.util.List; +import net.runelite.cache.IndexType; +import net.runelite.cache.definitions.NpcDefinition; +import net.runelite.cache.io.InputStream; +import net.runelite.cache.utils.StringUtilities; + +public class NpcLoader +{ + public static final IndexType INDEX_TYPE = IndexType.TWO; + public static final int ARCHIVE_ID = 9; + + private final List npcs = new ArrayList<>(); + + public List getNpcs() + { + return npcs; + } + + public void load(int id, InputStream stream) + { + NpcDefinition def = new NpcDefinition(id); + while (true) + { + int opcode = stream.readUnsignedByte(); + if (opcode == 0) + { + break; + } + + this.decodeValues(opcode, def, stream); + } + npcs.add(def); + } + + void decodeValues(int opcode, NpcDefinition def, InputStream stream) + { + int length; + int index; + if (1 == opcode) + { + length = stream.readUnsignedByte(); + def.models = new int[length]; + + for (index = 0; index < length; ++index) + { + def.models[index] = stream.readUnsignedShort(); + } + + } + else if (2 == opcode) + { + def.name = StringUtilities.readString_2(stream); + } + else if (12 == opcode) + { + def.tileSpacesOccupied = stream.readUnsignedShort(); + } + else if (opcode == 13) + { + def.stanceAnimation = stream.readUnsignedShort(); + } + else if (opcode == 14) + { + def.walkAnimation = stream.readUnsignedShort(); + } + else if (15 == opcode) + { + def.anInt2165 = stream.readUnsignedShort(); + } + else if (opcode == 16) + { + def.anInt2189 = stream.readUnsignedShort(); + } + else if (17 == opcode) + { + def.walkAnimation = stream.readUnsignedShort(); + def.rotate180Animation = stream.readUnsignedShort(); + def.rotate90RightAnimation = stream.readUnsignedShort(); + def.rotate90LeftAnimation = stream.readUnsignedShort(); + } + else if (opcode >= 30 && opcode < 35) + { + def.options[opcode - 30] = StringUtilities.readString_2(stream); + if (def.options[opcode - 30].equalsIgnoreCase("Hidden")) + { + def.options[opcode - 30] = null; + } + } + else if (opcode == 40) + { + length = stream.readUnsignedByte(); + def.recolorToFind = new short[length]; + def.recolorToReplace = new short[length]; + + for (index = 0; index < length; ++index) + { + def.recolorToFind[index] = (short) stream.readUnsignedShort(); + def.recolorToReplace[index] = (short) stream.readUnsignedShort(); + } + + } + else if (opcode == 41) + { + length = stream.readUnsignedByte(); + def.retextureToFind = new short[length]; + def.retextureToReplace = new short[length]; + + for (index = 0; index < length; ++index) + { + def.retextureToFind[index] = (short) stream.readUnsignedShort(); + def.retextureToReplace[index] = (short) stream.readUnsignedShort(); + } + + } + else if (60 != opcode) + { + if (opcode == 93) + { + def.renderOnMinimap = false; + } + else if (95 == opcode) + { + def.combatLevel = stream.readUnsignedShort(); + } + else if (97 == opcode) + { + def.resizeX = stream.readUnsignedShort(); + } + else if (98 == opcode) + { + def.resizeY = stream.readUnsignedShort(); + } + else if (opcode == 99) + { + def.hasRenderPriority = true; + } + else if (100 == opcode) + { + def.ambient = stream.readByte(); + } + else if (101 == opcode) + { + def.contrast = stream.readByte(); + } + else if (opcode == 102) + { + def.headIcon = stream.readUnsignedShort(); + } + else if (103 == opcode) + { + def.anInt2156 = stream.readUnsignedShort(); + } + else if (opcode == 106) + { + def.anInt2174 = stream.readUnsignedShort(); + if ('\uffff' == def.anInt2174) + { + def.anInt2174 = -1; + } + + def.anInt2187 = stream.readUnsignedShort(); + if ('\uffff' == def.anInt2187) + { + def.anInt2187 = -40212193; + } + + length = stream.readUnsignedByte(); + def.anIntArray2185 = new int[length + 1]; + + for (index = 0; index <= length; ++index) + { + def.anIntArray2185[index] = stream.readUnsignedShort(); + if (def.anIntArray2185[index] == '\uffff') + { + def.anIntArray2185[index] = -1; + } + } + + } + else if (107 == opcode) + { + def.isClickable = false; + } + else if (opcode == 109) + { + def.aBool2170 = false; + } + else if (opcode == 111) + { + def.aBool2190 = true; + } + else if (opcode == 112) + { + def.anInt2184 = stream.readUnsignedByte(); + } + } + else + { + length = stream.readUnsignedByte(); + def.models_2 = new int[length]; + + for (index = 0; index < length; ++index) + { + def.models_2[index] = stream.readUnsignedShort(); + } + + } + } +} diff --git a/src/test/java/net/runelite/cache/loaders/NpcLoaderTest.java b/src/test/java/net/runelite/cache/loaders/NpcLoaderTest.java new file mode 100644 index 0000000000..b2a0ce2667 --- /dev/null +++ b/src/test/java/net/runelite/cache/loaders/NpcLoaderTest.java @@ -0,0 +1,53 @@ +package net.runelite.cache.loaders; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import java.io.FileWriter; +import java.io.IOException; +import net.runelite.cache.StoreLocation; +import net.runelite.cache.definitions.NpcDefinition; +import net.runelite.cache.definitions.loaders.NpcLoader; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.File; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Store; +import net.runelite.cache.io.InputStream; +import org.junit.Test; + +public class NpcLoaderTest +{ + @Test + public void extract() throws IOException + { + NpcLoader loader = new NpcLoader(); + + java.io.File base = StoreLocation.LOCATION; + try (Store store = new Store(base)) + { + store.load(); + + Index index = store.getIndex(NpcLoader.INDEX_TYPE); + Archive archive = index.getArchive(NpcLoader.ARCHIVE_ID); + + for (File f : archive.getFiles()) + { + loader.load(f.getFileId(), new InputStream(f.getContents())); + } + } + + new java.io.File(base, "npcs").mkdir(); + + GsonBuilder builder = new GsonBuilder() + .setPrettyPrinting(); + Gson g = builder.create(); + + for (NpcDefinition def : loader.getNpcs()) + { + java.io.File targ = new java.io.File(base, "npcs/" + def.id + ".json"); + try (FileWriter fw = new FileWriter(targ)) + { + fw.write(g.toJson(def)); + } + } + } +}