cache: consolidate dumper entrypoints, add pack/unpack commands

This commit is contained in:
Adam
2017-03-16 12:36:11 -04:00
parent b2327d7e8e
commit 592a2502cf
9 changed files with 352 additions and 193 deletions

View File

@@ -0,0 +1,195 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* 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();
}
}

View File

@@ -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<ItemDefinition> 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<String> 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;
}
}

View File

@@ -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<NpcDefinition> 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<String> 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;
}
}

View File

@@ -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<ObjectDefinition> 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<String> 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;
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* 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<String> 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;
}
}
}

View File

@@ -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
);

View File

@@ -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
);

View File

@@ -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
);