diff --git a/cache/pom.xml b/cache/pom.xml index 4d1cb50e92..78eb5058de 100644 --- a/cache/pom.xml +++ b/cache/pom.xml @@ -87,6 +87,11 @@ antlr4-runtime ${antlr4.version} + + commons-cli + commons-cli + 1.3.1 + junit diff --git a/cache/src/main/java/net/runelite/cache/Cache.java b/cache/src/main/java/net/runelite/cache/Cache.java new file mode 100644 index 0000000000..ad678bd88e --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/Cache.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER 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. + */ +package net.runelite.cache; + +import java.io.File; +import java.io.IOException; +import net.runelite.cache.fs.Store; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.DefaultParser; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; + +public class Cache +{ + public static void main(String[] args) throws IOException + { + Options options = new Options(); + + options.addOption("c", "cache", true, "cache base"); + options.addOption("t", "tree", true, "tree base"); + + options.addOption("u", "unpack", false, "unpack cache"); + options.addOption("p", "pack", false, "pack cache"); + + options.addOption(null, "items", true, "directory to dump items to"); + options.addOption(null, "npcs", true, "directory to dump npcs to"); + options.addOption(null, "objects", true, "directory to dump objects to"); + + CommandLineParser parser = new DefaultParser(); + CommandLine cmd; + try + { + cmd = parser.parse(options, args); + } + catch (ParseException ex) + { + System.err.println("Error parsing command line options: " + ex.getMessage()); + System.exit(-1); + return; + } + + String cache = cmd.getOptionValue("cache"); + String tree = cmd.getOptionValue("tree"); + + if (cmd.hasOption("p")) + { + if (cache == null || tree == null) + { + System.err.println("Cache and tree base must be specified to pack"); + System.exit(-1); + } + + System.out.print("Packing tree from " + tree + " to " + cache + "..."); + + Store treeBase = new Store(new File(cache)); + treeBase.loadTree(new File(tree)); + treeBase.save(); + + System.out.println(" done!"); + return; + } + else if (cmd.hasOption("u")) + { + if (cache == null || tree == null) + { + System.err.println("Cache and tree base must be specified to unpack"); + System.exit(-1); + } + + System.out.print("Unpacking cache from " + cache + " to " + tree + "..."); + + Store treeBase = new Store(new File(cache)); + treeBase.load(); + + treeBase.saveTree(new File(tree)); + + System.out.println(" done!"); + return; + } + + if (cache != null && tree != null) + { + System.err.println("Cannot specify both cache and tree"); + System.exit(-1); + return; + } + + Store store = loadStore(cache, tree); + + if (cmd.hasOption("items")) + { + String itemdir = cmd.getOptionValue("items"); + + if (itemdir == null) + { + System.err.println("Item directory must be specified"); + } + + System.out.println("Dumping items to " + itemdir); + dumpItems(store, new File(itemdir)); + } + else if (cmd.hasOption("npcs")) + { + String npcdir = cmd.getOptionValue("npcs"); + + if (npcdir == null) + { + System.err.println("NPC directory must be specified"); + } + + System.out.println("Dumping npcs to " + npcdir); + dumpNpcs(store, new File(npcdir)); + } + else if (cmd.hasOption("objects")) + { + String objectdir = cmd.getOptionValue("objects"); + + if (objectdir == null) + { + System.err.println("Object directory must be specified"); + } + + System.out.println("Dumping objects to " + objectdir); + dumpObjects(store, new File(objectdir)); + } + else + { + System.err.println("Nothing to do"); + } + } + + private static Store loadStore(String cache, String tree) throws IOException + { + if (cache == null) + { + Store store = new Store(new File(tree)); + store.loadTree(new File(tree)); + return store; + } + else + { + Store store = new Store(new File(cache)); + store.load(); + return store; + } + + } + + private static void dumpItems(Store store, File itemdir) throws IOException + { + ItemDumper dumper = new ItemDumper(store, itemdir, itemdir); + dumper.load(); + dumper.dump(); + dumper.java(); + } + + private static void dumpNpcs(Store store, File npcdir) throws IOException + { + NpcDumper dumper = new NpcDumper(store, npcdir, npcdir); + dumper.load(); + dumper.dump(); + dumper.java(); + } + + private static void dumpObjects(Store store, File objectdir) throws IOException + { + ObjectDumper dumper = new ObjectDumper(store, objectdir, objectdir); + dumper.load(); + dumper.dump(); + dumper.java(); + } +} diff --git a/cache/src/main/java/net/runelite/cache/ItemDumper.java b/cache/src/main/java/net/runelite/cache/ItemDumper.java index 0f3ef0123d..12e4f48eb5 100644 --- a/cache/src/main/java/net/runelite/cache/ItemDumper.java +++ b/cache/src/main/java/net/runelite/cache/ItemDumper.java @@ -22,7 +22,6 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - package net.runelite.cache; import com.google.gson.Gson; @@ -32,26 +31,26 @@ import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.Set; import net.runelite.cache.definitions.ItemDefinition; import net.runelite.cache.definitions.loaders.ItemLoader; import net.runelite.cache.fs.Archive; import net.runelite.cache.fs.Index; import net.runelite.cache.fs.Store; import net.runelite.cache.io.InputStream; +import net.runelite.cache.util.Namer; public class ItemDumper { - private final File cache, out, java; + private final Store store; + private final File out, java; private final Gson gson; - private ItemLoader loader; private final List items = new ArrayList<>(); + private final Namer namer = new Namer(); - public ItemDumper(File cache, File out, File java) + public ItemDumper(Store store, File out, File java) { - this.cache = cache; + this.store = store; this.out = out; this.java = java; @@ -60,37 +59,17 @@ public class ItemDumper gson = builder.create(); } - public static void main(String[] args) throws IOException + public void load() { - if (args.length < 3) - System.exit(1); + ItemLoader loader = new ItemLoader(); - File cache = new File(args[0]); - File out = new File(args[1]); - File java = new File(args[2]); + Index index = store.getIndex(IndexType.CONFIGS); + Archive archive = index.getArchive(ConfigType.ITEM.getId()); - ItemDumper dumper = new ItemDumper(cache, out, java); - dumper.load(); - dumper.dump(); - dumper.java(); - } - - public void load() throws IOException - { - loader = new ItemLoader(); - - try (Store store = new Store(cache)) + for (net.runelite.cache.fs.File f : archive.getFiles()) { - store.load(); - - Index index = store.getIndex(IndexType.CONFIGS); - Archive archive = index.getArchive(ConfigType.ITEM.getId()); - - for (net.runelite.cache.fs.File f : archive.getFiles()) - { - ItemDefinition def = loader.load(f.getFileId(), new InputStream(f.getContents())); - items.add(def); - } + ItemDefinition def = loader.load(f.getFileId(), new InputStream(f.getContents())); + items.add(def); } } @@ -113,8 +92,6 @@ public class ItemDumper java.io.File targ = new java.io.File(java, "ItemID.java"); try (PrintWriter fw = new PrintWriter(targ)) { - Set used = new HashSet<>(); - fw.println("/* This file is automatically generated. Do not edit. */"); fw.println("package net.runelite.api;"); fw.println(""); @@ -122,40 +99,19 @@ public class ItemDumper for (ItemDefinition def : items) { if (def.name.equalsIgnoreCase("NULL")) - continue; - - String name = name(def.name); - if (name == null) - continue; - - String suffix = ""; - while (used.contains(name + suffix)) { - if (suffix.isEmpty()) - suffix = "_2"; - else - suffix = "_" + (Integer.parseInt(suffix.substring(1)) + 1); + continue; } - name += suffix; - used.add(name); + String name = namer.name(def.name); + if (name == null) + { + continue; + } fw.println(" public static final int " + name + " = " + def.id + ";"); } fw.println("}"); } } - - private static String name(String in) - { - String s = in.toUpperCase() - .replace(' ', '_') - .replaceAll("[^a-zA-Z0-9_]", ""); - if (s.isEmpty()) - return null; - if (Character.isDigit(s.charAt(0))) - return "_" + s; - else - return s; - } } diff --git a/cache/src/main/java/net/runelite/cache/NpcDumper.java b/cache/src/main/java/net/runelite/cache/NpcDumper.java index 1b1df0a214..f7002f1b0d 100644 --- a/cache/src/main/java/net/runelite/cache/NpcDumper.java +++ b/cache/src/main/java/net/runelite/cache/NpcDumper.java @@ -22,7 +22,6 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - package net.runelite.cache; import com.google.gson.Gson; @@ -32,26 +31,26 @@ import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.Set; import net.runelite.cache.definitions.NpcDefinition; import net.runelite.cache.definitions.loaders.NpcLoader; import net.runelite.cache.fs.Archive; import net.runelite.cache.fs.Index; import net.runelite.cache.fs.Store; import net.runelite.cache.io.InputStream; +import net.runelite.cache.util.Namer; public class NpcDumper { - private final File cache, out, java; + private final Store store; + private final File out, java; private final Gson gson; - private NpcLoader loader; private final List npcs = new ArrayList<>(); + private final Namer namer = new Namer(); - public NpcDumper(File cache, File out, File java) + public NpcDumper(Store store, File out, File java) { - this.cache = cache; + this.store = store; this.out = out; this.java = java; @@ -60,37 +59,17 @@ public class NpcDumper gson = builder.create(); } - public static void main(String[] args) throws IOException - { - if (args.length < 3) - System.exit(1); - - File cache = new File(args[0]); - File out = new File(args[1]); - File java = new File(args[2]); - - NpcDumper dumper = new NpcDumper(cache, out, java); - dumper.load(); - dumper.dump(); - dumper.java(); - } - public void load() throws IOException { - loader = new NpcLoader(); + NpcLoader loader = new NpcLoader(); - try (Store store = new Store(cache)) + Index index = store.getIndex(IndexType.CONFIGS); + Archive archive = index.getArchive(ConfigType.NPC.getId()); + + for (net.runelite.cache.fs.File f : archive.getFiles()) { - store.load(); - - Index index = store.getIndex(IndexType.CONFIGS); - Archive archive = index.getArchive(ConfigType.NPC.getId()); - - for (net.runelite.cache.fs.File f : archive.getFiles()) - { - NpcDefinition npc = loader.load(f.getFileId(), new InputStream(f.getContents())); - npcs.add(npc); - } + NpcDefinition npc = loader.load(f.getFileId(), new InputStream(f.getContents())); + npcs.add(npc); } } @@ -113,8 +92,6 @@ public class NpcDumper java.io.File targ = new java.io.File(java, "NpcID.java"); try (PrintWriter fw = new PrintWriter(targ)) { - Set used = new HashSet<>(); - fw.println("/* This file is automatically generated. Do not edit. */"); fw.println("package net.runelite.api;"); fw.println(""); @@ -122,40 +99,19 @@ public class NpcDumper for (NpcDefinition def : npcs) { if (def.name.equalsIgnoreCase("NULL")) - continue; - - String name = name(def.name); - if (name == null) - continue; - - String suffix = ""; - while (used.contains(name + suffix)) { - if (suffix.isEmpty()) - suffix = "_2"; - else - suffix = "_" + (Integer.parseInt(suffix.substring(1)) + 1); + continue; } - name += suffix; - used.add(name); + String name = namer.name(def.name); + if (name == null) + { + continue; + } fw.println(" public static final int " + name + " = " + def.id + ";"); } fw.println("}"); } } - - private static String name(String in) - { - String s = in.toUpperCase() - .replace(' ', '_') - .replaceAll("[^a-zA-Z0-9_]", ""); - if (s.isEmpty()) - return null; - if (Character.isDigit(s.charAt(0))) - return "_" + s; - else - return s; - } } diff --git a/cache/src/main/java/net/runelite/cache/ObjectDumper.java b/cache/src/main/java/net/runelite/cache/ObjectDumper.java index 497cdc985e..cf33b561aa 100644 --- a/cache/src/main/java/net/runelite/cache/ObjectDumper.java +++ b/cache/src/main/java/net/runelite/cache/ObjectDumper.java @@ -22,7 +22,6 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - package net.runelite.cache; import com.google.gson.Gson; @@ -32,25 +31,25 @@ import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.Set; import net.runelite.cache.definitions.ObjectDefinition; import net.runelite.cache.definitions.loaders.ObjectLoader; import net.runelite.cache.fs.Archive; import net.runelite.cache.fs.Index; import net.runelite.cache.fs.Store; +import net.runelite.cache.util.Namer; public class ObjectDumper { - private final File cache, out, java; + private final Store store; + private final File out, java; private final Gson gson; - private ObjectLoader loader; private final List objects = new ArrayList<>(); + private final Namer namer = new Namer(); - public ObjectDumper(File cache, File out, File java) + public ObjectDumper(Store store, File out, File java) { - this.cache = cache; + this.store = store; this.out = out; this.java = java; @@ -59,37 +58,17 @@ public class ObjectDumper gson = builder.create(); } - public static void main(String[] args) throws IOException - { - if (args.length < 3) - System.exit(1); - - File cache = new File(args[0]); - File out = new File(args[1]); - File java = new File(args[2]); - - ObjectDumper dumper = new ObjectDumper(cache, out, java); - dumper.load(); - dumper.dump(); - dumper.java(); - } - public void load() throws IOException { - loader = new ObjectLoader(); + ObjectLoader loader = new ObjectLoader(); - try (Store store = new Store(cache)) + Index index = store.getIndex(IndexType.CONFIGS); + Archive archive = index.getArchive(ConfigType.OBJECT.getId()); + + for (net.runelite.cache.fs.File f : archive.getFiles()) { - store.load(); - - Index index = store.getIndex(IndexType.CONFIGS); - Archive archive = index.getArchive(ConfigType.OBJECT.getId()); - - for (net.runelite.cache.fs.File f : archive.getFiles()) - { - ObjectDefinition def = loader.load(f.getFileId(), f.getContents()); - objects.add(def); - } + ObjectDefinition def = loader.load(f.getFileId(), f.getContents()); + objects.add(def); } } @@ -112,8 +91,6 @@ public class ObjectDumper java.io.File targ = new java.io.File(java, "ObjectID.java"); try (PrintWriter fw = new PrintWriter(targ)) { - Set used = new HashSet<>(); - fw.println("/* This file is automatically generated. Do not edit. */"); fw.println("package net.runelite.api;"); fw.println(""); @@ -121,40 +98,19 @@ public class ObjectDumper for (ObjectDefinition def : objects) { if (def.getName().equalsIgnoreCase("NULL")) - continue; - - String name = name(def.getName()); - if (name == null) - continue; - - String suffix = ""; - while (used.contains(name + suffix)) { - if (suffix.isEmpty()) - suffix = "_2"; - else - suffix = "_" + (Integer.parseInt(suffix.substring(1)) + 1); + continue; } - name += suffix; - used.add(name); + String name = namer.name(def.getName()); + if (name == null) + { + continue; + } fw.println(" public static final int " + name + " = " + def.getId() + ";"); } fw.println("}"); } } - - private static String name(String in) - { - String s = in.toUpperCase() - .replace(' ', '_') - .replaceAll("[^a-zA-Z0-9_]", ""); - if (s.isEmpty()) - return null; - if (Character.isDigit(s.charAt(0))) - return "_" + s; - else - return s; - } } diff --git a/cache/src/main/java/net/runelite/cache/util/Namer.java b/cache/src/main/java/net/runelite/cache/util/Namer.java new file mode 100644 index 0000000000..a474ede710 --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/util/Namer.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER 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. + */ +package net.runelite.cache.util; + +import java.util.HashSet; +import java.util.Set; + +public class Namer +{ + private final Set used = new HashSet<>(); + + public String name(String name) + { + name = sanitize(name); + + if (name == null) + { + return null; + } + + String suffix = ""; + while (used.contains(name + suffix)) + { + if (suffix.isEmpty()) + { + suffix = "_2"; + } + else + { + suffix = "_" + (Integer.parseInt(suffix.substring(1)) + 1); + } + } + + name += suffix; + used.add(name); + + return name; + } + + private static String sanitize(String in) + { + String s = in.toUpperCase() + .replace(' ', '_') + .replaceAll("[^a-zA-Z0-9_]", ""); + if (s.isEmpty()) + { + return null; + } + if (Character.isDigit(s.charAt(0))) + { + return "_" + s; + } + else + { + return s; + } + } +} diff --git a/cache/src/test/java/net/runelite/cache/ItemDumperTest.java b/cache/src/test/java/net/runelite/cache/ItemDumperTest.java index 3a23974be6..cc61fa9287 100644 --- a/cache/src/test/java/net/runelite/cache/ItemDumperTest.java +++ b/cache/src/test/java/net/runelite/cache/ItemDumperTest.java @@ -27,6 +27,7 @@ package net.runelite.cache; import java.io.File; import java.io.IOException; +import net.runelite.cache.fs.Store; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -45,9 +46,12 @@ public class ItemDumperTest { File dumpDir = folder.newFolder(), javaDir = folder.newFolder(); + + Store store = new Store(StoreLocation.LOCATION); + store.load(); ItemDumper dumper = new ItemDumper( - StoreLocation.LOCATION, + store, dumpDir, javaDir ); diff --git a/cache/src/test/java/net/runelite/cache/NpcDumperTest.java b/cache/src/test/java/net/runelite/cache/NpcDumperTest.java index 8263f40b5b..437630103d 100644 --- a/cache/src/test/java/net/runelite/cache/NpcDumperTest.java +++ b/cache/src/test/java/net/runelite/cache/NpcDumperTest.java @@ -22,11 +22,11 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - package net.runelite.cache; import java.io.File; import java.io.IOException; +import net.runelite.cache.fs.Store; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -46,8 +46,11 @@ public class NpcDumperTest File dumpDir = folder.newFolder(), javaDir = folder.newFolder(); + Store store = new Store(StoreLocation.LOCATION); + store.load(); + NpcDumper dumper = new NpcDumper( - StoreLocation.LOCATION, + store, dumpDir, javaDir ); diff --git a/cache/src/test/java/net/runelite/cache/ObjectDumperTest.java b/cache/src/test/java/net/runelite/cache/ObjectDumperTest.java index 3d0189c91b..7bc632bac4 100644 --- a/cache/src/test/java/net/runelite/cache/ObjectDumperTest.java +++ b/cache/src/test/java/net/runelite/cache/ObjectDumperTest.java @@ -26,6 +26,7 @@ package net.runelite.cache; import java.io.File; import java.io.IOException; +import net.runelite.cache.fs.Store; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -45,8 +46,11 @@ public class ObjectDumperTest File dumpDir = folder.newFolder(), javaDir = folder.newFolder(); + Store store = new Store(StoreLocation.LOCATION); + store.load(); + ObjectDumper dumper = new ObjectDumper( - StoreLocation.LOCATION, + store, dumpDir, javaDir );