Index: /java/installer2/.classpath
===================================================================
--- /java/installer2/.classpath	(revision 748)
+++ /java/installer2/.classpath	(revision 749)
@@ -26,4 +26,5 @@
 	<classpathentry kind="lib" path="/_ThirdPartyLibs/NaturalOrderComparator.jar"/>
 	<classpathentry combineaccessrules="false" kind="src" path="/HTTPFileDownloader"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/ModDepotAccess"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
Index: va/installer2/doc/AEI1-stuff_onisplit-commands.txt
===================================================================
--- /java/installer2/doc/AEI1-stuff_onisplit-commands.txt	(revision 748)
+++ 	(revision )
@@ -1,30 +1,0 @@
-filter mod-types from combobox with no nodes
-
-save current installed config
-
-install
-select all (only of current type?)
-revert - select mods that are currently installed
-
-
-globalization:
-
-installation:
-- remove current .dat/.raw/.sep from GDF
-- remove current BSL-folders?
-- combine vanilla+default-mods+selected-mods
-- combine BSL
-
-
-orig:
-globalization: installer.cpp/h - globalizeData() in #31
-installation: installer.cpp/h - recompileAll() in #500
-
-
-
-
-check .net>2.0:
-win: http://msdn.microsoft.com/en-us/kb/kbarticle.aspx?id=318785
-mac: which mono
-
-http://www.microsoft.com/downloads/details.aspx?familyid=0856eacb-4362-4b0d-8edd-aab15c5e04f5
Index: va/installer2/doc/conflict-resolving.txt
===================================================================
--- /java/installer2/doc/conflict-resolving.txt	(revision 748)
+++ 	(revision )
@@ -1,15 +1,0 @@
-Multi-.Oni: No conflict, priority based resolution
-
-BSL:
-1. Mods containing different BSL-files for the same level (addon=no):
-"light" warning window
-
-2. Mods containing (partially) same BSL-files for the same level (addon=no):
-Conflict warning, if accepted take only files of higher priority mod
-
-3. Mods containing (partially) same BSL-files for the same level (addon=yes):
-no conflict, overwrite base files with addon-files
-
-4. As 3 with Addon on Addon:
-("Light" warning?) conflicting files are resolved by higher priority addon taking precedence
-
Index: va/installer2/doc/drupal_node_types_json.txt
===================================================================
--- /java/installer2/doc/drupal_node_types_json.txt	(revision 748)
+++ 	(revision )
@@ -1,180 +1,0 @@
-type=page:
-    "uid": "4",
-    "body": {"und": [{
-        "summary": null,
-        "safe_value": "<p><img src=\"/sites/default/images/Yogurt!-200px.png\" alt=\"A tasty favicon\" align=\"right\" /><u>What is the Mod Depot?<\/u><br />\n... The site is administered by Iritscen, who can be reached through mods{at}oni2{dot}net. The oni2.net domain is administered by Alloc.<\/p>",
-        "safe_summary": "",
-        "value": "<p><img src=\"/sites/default/images/Yogurt!-200px.png\" alt=\"A tasty favicon\" align=\"right\"><u>What is the Mod Depot?<\/u><br />\r\n... The site is administered by Iritscen, who can be reached through mods{at}oni2{dot}net. The oni2.net domain is administered by Alloc.<\/p>",
-        "format": "2"
-    }]},
-    "data": "a:1:{s:13:\"form_build_id\";s:37:\"form-134923bd25b368dc3c2dfa412f22a42a\";}",
-    "last_comment_uid": "1",
-    "type": "page",
-    "last_comment_name": null,
-    "changed": "1290977713",
-    "title": "About the Mod Depot",
-    "created": "1221420696",
-    "name": "Iritscen",
-    "path": "http://mods.oni2.net/node/1",
-    "revision_uid": "1",
-    "tnid": "0",
-    "vid": "1",
-    "comment_count": "0",
-    "status": "1",
-    "nid": "1",
-    "log": "",
-    "cid": "0",
-    "picture": "0",
-    "sticky": "0",
-    "promote": "0",
-    "last_comment_timestamp": "1221420696",
-    "revision_timestamp": "1290977713",
-    "translate": "0",
-    "language": "en",
-    "comment": "1"
-
-type=file:
-    "uid": "6",
-    "body": {"und": [{
-        "summary": null,
-        "safe_value": "A mod that adds a ...\n\nRequires Character Globalization (included with Edition)",
-        "safe_summary": "",
-        "value": "A mod that adds a level ...\r\nRequires Character Globalization (included with Edition)",
-        "format": "2"
-    }]},
-    "data": "a:1:{s:13:\"form_build_id\";s:37:\"form-9c92f19269ee6aa14969207bb41ec9cb\";}",
-    "last_comment_uid": "6",
-    "type": "file",
-    "last_comment_name": "",
-    "upload": {"und": [{
-        "timestamp": "1221588058",
-        "uid": "6",
-        "fid": "8",
-        "filesize": "173633",
-        "status": "1",
-        "description": "Arena.v.1.zip",
-        "filename": "Arena.v.1.zip",
-        "display": "1",
-        "filemime": "application/zip",
-        "uri": "private://Arena.v.1.zip"
-    }]},
-    "changed": "1250546844",
-    "title": "Arena of Pain (Win)",
-    "created": "1221588073",
-    "name": "Gumby",
-    "path": "http://mods.oni2.net/node/4",
-    "revision_uid": "1",
-    "tnid": "0",
-    "vid": "4",
-    "comment_count": 0,
-    "taxonomy_vocabulary_1": {"und": [{"tid": "2"}]},
-    "taxonomy_vocabulary_2": {"und": [{"tid": "21"}]},
-    "status": "1",
-    "nid": "4",
-    "taxonomy_vocabulary_3": {"und": [{"tid": "15"}]},
-    "log": "",
-    "cid": 0,
-    "picture": "0",
-    "sticky": "0",
-    "promote": "0",
-    "last_comment_timestamp": "1221588073",
-    "revision_timestamp": "1250546844",
-    "translate": "0",
-    "language": "en",
-    "comment": "0"
-
-    "vid":"218",
-    "uid":"42",
-    "title":"23615 Hanako",
-    "log":"",
-    "status":"1",
-    "comment":"2",
-    "promote":"0",
-    "sticky":"0",
-    "nid":"218",
-    "type":"file",
-    "language":"en",
-    "created":"1348876643",
-    "changed":"1349355480",
-    "tnid":"0",
-    "translate":"0",
-    "revision_timestamp":"1349355480",
-    "revision_uid":"42",
-    "taxonomy_vocabulary_3": {"und": [{"tid":"20"}]},
-    "taxonomy_vocabulary_2": {"und": [{"tid":"9"}]},
-    "taxonomy_vocabulary_1": {"und": [{"tid":"3"}]},
-    "body": {"und":[{
-        "value":"Adds New character Hanako, Hayate's female partner. Comes with 5 outfits. Chenille and heavy kick move by paradox, Running kick throw by Andrew. \r\n\r\nRequires Character Additives Package version 5 or above.\r\n\r\nUpdated Oct 4, 2012 fixed some LOD issues.",
-        "summary":null,
-        "format":"1",
-        "safe_value":"<p>Adds New character Hanako, Hayate's female partner. Comes with 5 outfits. Chenille and heavy kick move by paradox, Running kick throw by Andrew. </p>\n<p>Requires Character Additives Package version 5 or above.</p>\n<p>Updated Oct 4, 2012 fixed some LOD issues.</p>\n",
-        "safe_summary":""
-    }]},
-    "upload": {"und":[{
-        "fid":"585",
-        "display":"1",
-        "description":"23615Hanako.zip",
-        "uid":"42",
-        "filename":"23615Hanako.zip",
-        "uri":"private://23615Hanako.zip",
-        "filemime":"application/zip",
-        "filesize":"7890641",
-        "status":"1",
-        "timestamp":"1349353975"
-    }]},
-    "field_creator": {"und":[{
-        "value":"Samer",
-        "format":null,
-        "safe_value":"Samer"
-    }]},
-    "field_version": {"und":[{
-        "value":"1",
-        "format":null,
-        "safe_value":"1"
-    }]},
-    "cid":"0",
-    "last_comment_timestamp":"1348876643",
-    "last_comment_name":null,
-    "last_comment_uid":"42",
-    "comment_count":"0",
-    "name":"Samer",
-    "picture":"0",
-    "data":"a:1:{s:13:\"form_build_id\";s:37:\"form-f8d981ba47500e3df419bf009280cbb4\";}",
-    "path":"http://mods.oni2.net/node/218"
-
-
-
-type=story:
-    "uid": "4",
-    "body": {"und": [{
-        "summary": "This was ...\r\n\r\n<a href=\"http://www.simplici7y.com/\">Simplici7y<\/a> has a ...to me.",
-        "safe_value": "<p>This was already pretty ... to me.<\/p>\n",
-        "safe_summary": "<p>This was already pretty ...to me.<\/p>\n",
-        "value": "This was ...\r\n\r\n<a href=\"http://www.simplici7y.com/\">Simplici7y<\/a> has a... me.",
-        "format": "1"
-    }]},
-    "data": "a:1:{s:13:\"form_build_id\";s:37:\"form-134923bd25b368dc3c2dfa412f22a42a\";}",
-    "last_comment_uid": "4",
-    "type": "story",
-    "last_comment_name": null,
-    "changed": "1356050024",
-    "title": "Commenting is up",
-    "created": "1221591584",
-    "name": "Iritscen",
-    "path": "http://mods.oni2.net/node/5",
-    "revision_uid": "1",
-    "tnid": "0",
-    "vid": "5",
-    "comment_count": "0",
-    "status": "1",
-    "nid": "5",
-    "log": "",
-    "cid": "0",
-    "picture": "0",
-    "sticky": "0",
-    "promote": "1",
-    "last_comment_timestamp": "1221591584",
-    "revision_timestamp": "1356050024",
-    "translate": "0",
-    "language": "en",
-    "comment": "1"
Index: va/installer2/doc/nodes-with-multiple-files.txt
===================================================================
--- /java/installer2/doc/nodes-with-multiple-files.txt	(revision 748)
+++ 	(revision )
@@ -1,40 +1,0 @@
-Node 210, Files 2, Platform Both, Type Tool, InstMeth (none)
-Node 203, Files 2, Platform Windows, Type Tool, InstMeth (none)
-Node 184, Files 2, Platform Both, Type Tool, InstMeth (none)
-Node 172, Files 2, Platform Windows, Type Tool, InstMeth File swap
-Node 129, Files 2, Platform Both, Type Tool, InstMeth (none)
-Node 118, Files 2, Platform Windows, Type Tool, InstMeth (none)
-Node 72, Files 3, Platform Windows, Type Tool, InstMeth (none)
-Node 38, Files 5, Platform Both, Type Tool, InstMeth (none)
-
-Node 144, Files 3, Platform Both, Type Script, InstMeth (none)
-Node 114, Files 2, Platform Both, Type Script, InstMeth File swap
-Node 94, Files 3, Platform Both, Type Script, InstMeth File swap
-
-Node 222, Files 3, Platform Both, Type Character, InstMeth Package
-Node 214, Files 2, Platform Both, Type Texture, InstMeth Package
-Node 208, Files 2, Platform Both, Type Level, InstMeth Package
-Node 198, Files 1, Platform Both, Type Level, InstMeth Package
-Node 194, Files 1, Platform Both, Type Level, InstMeth Package
-Node 193, Files 2, Platform Both, Type Character, InstMeth Package
-Node 191, Files 2, Platform Both, Type Character, InstMeth Package
-Node 183, Files 2, Platform Windows, Type Character, InstMeth Package
-Node 181, Files 3, Platform Both, Type Level, InstMeth Package
-Node 180, Files 2, Platform Windows, Type Character, InstMeth Package
-Node 177, Files 2, Platform Both, Type Other, InstMeth Package
-Node 147, Files 1, Platform Windows, Type Character, InstMeth Package
-Node 134, Files 2, Platform Both, Type Character, InstMeth Package
-Node 123, Files 1, Platform Both, Type Level, InstMeth Package
-Node 121, Files 2, Platform Both, Type Character, InstMeth Package
-Node 108, Files 1, Platform Both, Type Character, InstMeth Package
-Node 101, Files 3, Platform Windows, Type Character, InstMeth Package
-Node 82, Files 1, Platform Both, Type Texture, InstMeth Package
-Node 63, Files 1, Platform Both, Type Script, InstMeth Package
-
-
-if you filter out those which only have multiple files cause of win+mac and old versions you get the following *packages* with multiple files:
-Node 214, Files 2, Platform Both, Type Texture, InstMeth Package - Split into two packages, lighter = created by VR/Samer #+1
-Node 193, Files 2, Platform Both, Type Character, InstMeth Package - Split into two, shapeshifted = #+1
-Node 181, Files 3, Platform Both, Type Level, InstMeth Package - split, dependency, delete noblue?
-Node 134, Files 2, Platform Both, Type Character, InstMeth Package - Split into two packages, #+1
-Node 101, Files 3, Platform Windows, Type Character, InstMeth Package - merge + separate package #+1
Index: /java/installer2/src/net/oni2/aeinstaller/AEInstaller.properties
===================================================================
--- /java/installer2/src/net/oni2/aeinstaller/AEInstaller.properties	(revision 748)
+++ /java/installer2/src/net/oni2/aeinstaller/AEInstaller.properties	(revision 749)
@@ -1,2 +1,2 @@
 appname=AE Installer 2
-appversion=0.99w
+appversion=0.99x
Index: /java/installer2/src/net/oni2/aeinstaller/AEInstaller2.java
===================================================================
--- /java/installer2/src/net/oni2/aeinstaller/AEInstaller2.java	(revision 748)
+++ /java/installer2/src/net/oni2/aeinstaller/AEInstaller2.java	(revision 749)
@@ -25,9 +25,9 @@
 import net.oni2.aeinstaller.backend.Paths;
 import net.oni2.aeinstaller.backend.SizeFormatter;
-import net.oni2.aeinstaller.backend.depot.DepotManager;
-import net.oni2.aeinstaller.backend.oni.Installer;
 import net.oni2.aeinstaller.backend.oni.OniSplit;
+import net.oni2.aeinstaller.backend.oni.management.Installer;
 import net.oni2.aeinstaller.gui.HTMLLinkLabel;
 import net.oni2.aeinstaller.gui.MainWin;
+import net.oni2.moddepot.DepotManager;
 import net.oni2.platformtools.PlatformInformation;
 import net.oni2.platformtools.PlatformInformation.Platform;
@@ -117,4 +117,5 @@
 		boolean debug = false;
 		boolean noCacheUpdate = false;
+		boolean offline = false;
 		for (String a : args) {
 			if (a.equalsIgnoreCase("-debug"))
@@ -122,4 +123,6 @@
 			if (a.equalsIgnoreCase("-nocacheupdate"))
 				noCacheUpdate = true;
+			if (a.equalsIgnoreCase("-offline"))
+				offline = true;
 		}
 		if (!debug) {
@@ -239,8 +242,4 @@
 		}
 
-		boolean offline = false;
-		for (String a : args)
-			if (a.equalsIgnoreCase("-offline"))
-				offline = true;
 		if (!offline) {
 			offline = !DepotManager.getInstance().checkConnection();
Index: /java/installer2/src/net/oni2/aeinstaller/DepotPackageCheck.java
===================================================================
--- /java/installer2/src/net/oni2/aeinstaller/DepotPackageCheck.java	(revision 748)
+++ /java/installer2/src/net/oni2/aeinstaller/DepotPackageCheck.java	(revision 749)
@@ -4,8 +4,8 @@
 import java.util.HashSet;
 
-import net.oni2.aeinstaller.backend.depot.DepotConfig;
-import net.oni2.aeinstaller.backend.depot.DepotManager;
-import net.oni2.aeinstaller.backend.depot.model.Node;
-import net.oni2.aeinstaller.backend.depot.model.NodeMod;
+import net.oni2.moddepot.DepotConfig;
+import net.oni2.moddepot.DepotManager;
+import net.oni2.moddepot.model.Node;
+import net.oni2.moddepot.model.NodeMod;
 
 /**
@@ -34,11 +34,11 @@
 		HashMap<String, HashSet<NodeMod>> foundNodes = new HashMap<String, HashSet<NodeMod>>();
 		for (Node n : DepotManager.getInstance().getNodesByType(
-				DepotConfig.getNodeType_Mod())) {
+				DepotConfig.nodeType_Package)) {
 			NodeMod nm = (NodeMod) n;
 			if (nm.getUploads().size() != 1) {
-				if (!foundNodes.containsKey(nm.getInstallMethod().getName()))
-					foundNodes.put(nm.getInstallMethod().getName(),
+				if (!foundNodes.containsKey(nm.getInstallMethod()))
+					foundNodes.put(nm.getInstallMethod(),
 							new HashSet<NodeMod>());
-				foundNodes.get(nm.getInstallMethod().getName()).add(nm);
+				foundNodes.get(nm.getInstallMethod()).add(nm);
 			}
 		}
Index: va/installer2/src/net/oni2/aeinstaller/backend/oni/InstallProgressListener.java
===================================================================
--- /java/installer2/src/net/oni2/aeinstaller/backend/oni/InstallProgressListener.java	(revision 748)
+++ 	(revision )
@@ -1,18 +1,0 @@
-package net.oni2.aeinstaller.backend.oni;
-
-/**
- * @author Christian Illy
- */
-public interface InstallProgressListener {
-	/**
-	 * Called when installation process advances
-	 * 
-	 * @param done
-	 *            Steps done
-	 * @param total
-	 *            Steps in total
-	 * @param step
-	 *            Name of step
-	 */
-	public void installProgressUpdate(int done, int total, String step);
-}
Index: va/installer2/src/net/oni2/aeinstaller/backend/oni/Installer.java
===================================================================
--- /java/installer2/src/net/oni2/aeinstaller/backend/oni/Installer.java	(revision 748)
+++ 	(revision )
@@ -1,951 +1,0 @@
-package net.oni2.aeinstaller.backend.oni;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PrintWriter;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Scanner;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import java.util.Vector;
-import java.util.regex.Pattern;
-
-import net.oni2.SettingsManager;
-import net.oni2.aeinstaller.AEInstaller2;
-import net.oni2.aeinstaller.backend.CaseInsensitiveFile;
-import net.oni2.aeinstaller.backend.Paths;
-import net.oni2.aeinstaller.backend.packages.EBSLInstallType;
-import net.oni2.aeinstaller.backend.packages.Package;
-import net.oni2.aeinstaller.backend.packages.PackageManager;
-import net.oni2.platformtools.PlatformInformation;
-import net.oni2.platformtools.PlatformInformation.Platform;
-import net.oni2.platformtools.applicationinvoker.ApplicationInvocationResult;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.filefilter.RegexFileFilter;
-import org.apache.commons.io.filefilter.TrueFileFilter;
-import org.javabuilders.swing.SwingJavaBuilder;
-
-import com.paour.NaturalOrderComparator;
-import com.thoughtworks.xstream.XStream;
-import com.thoughtworks.xstream.io.xml.StaxDriver;
-
-/**
- * @author Christian Illy
- */
-public class Installer {
-	private static FileFilter dirFileFilter = new FileFilter() {
-		@Override
-		public boolean accept(File pathname) {
-			return pathname.isDirectory();
-		}
-	};
-
-	/**
-	 * @return Is Edition Core initialized
-	 */
-	public static boolean isEditionInitialized() {
-		return Paths.getVanillaOnisPath().exists();
-	}
-
-	private static void createEmptyPath(File path) throws IOException {
-		if (path.exists())
-			FileUtils.deleteDirectory(path);
-		path.mkdirs();
-	}
-
-	/**
-	 * @return list of currently installed mods
-	 */
-	public static Vector<Integer> getInstalledMods() {
-		File installCfg = new File(Paths.getEditionGDF(), "installed_mods.xml");
-		return PackageManager.getInstance().loadModSelection(installCfg);
-	}
-
-	/**
-	 * @return Currently installed tools
-	 */
-	@SuppressWarnings("unchecked")
-	public static TreeSet<Integer> getInstalledTools() {
-		File installCfg = new File(Paths.getInstallerPath(),
-				"installed_tools.xml");
-		TreeSet<Integer> res = new TreeSet<Integer>();
-		try {
-			if (installCfg.exists()) {
-				FileInputStream fis = new FileInputStream(installCfg);
-				XStream xs = new XStream(new StaxDriver());
-				Object obj = xs.fromXML(fis);
-				if (obj instanceof TreeSet<?>)
-					res = (TreeSet<Integer>) obj;
-				fis.close();
-			}
-		} catch (FileNotFoundException e) {
-			e.printStackTrace();
-		} catch (IOException e) {
-			e.printStackTrace();
-		}
-		return res;
-	}
-
-	private static void writeInstalledTools(TreeSet<Integer> tools) {
-		File installCfg = new File(Paths.getInstallerPath(),
-				"installed_tools.xml");
-		try {
-			FileOutputStream fos = new FileOutputStream(installCfg);
-			XStream xs = new XStream(new StaxDriver());
-			xs.toXML(tools, fos);
-			fos.close();
-		} catch (FileNotFoundException e) {
-			e.printStackTrace();
-		} catch (IOException e) {
-			e.printStackTrace();
-		}
-	}
-
-	/**
-	 * @param tools
-	 *            Tools to (un)install
-	 * @param uninstall
-	 *            Uninstall tools or install?
-	 */
-	public static void installTools(TreeSet<Package> tools, boolean uninstall) {
-		TreeSet<Integer> installed = getInstalledTools();
-		for (Package m : tools) {
-			if (!uninstall || installed.contains(m.getPackageNumber())) {
-				File plain = CaseInsensitiveFile.getCaseInsensitiveFile(
-						m.getLocalPath(), "plain");
-				if (plain.exists()) {
-					if (m.hasSeparatePlatformDirs()) {
-						File plainCommon = CaseInsensitiveFile
-								.getCaseInsensitiveFile(plain, "common");
-						File plainMac = CaseInsensitiveFile
-								.getCaseInsensitiveFile(plain, "mac_only");
-						File plainWin = CaseInsensitiveFile
-								.getCaseInsensitiveFile(plain, "win_only");
-						if (plainCommon.exists())
-							copyRemoveToolsFiles(plainCommon,
-									Paths.getEditionBasePath(), uninstall);
-						if (PlatformInformation.getPlatform() == Platform.MACOS
-								&& plainMac.exists())
-							copyRemoveToolsFiles(plainMac,
-									Paths.getEditionBasePath(), uninstall);
-						else if (plainWin.exists())
-							copyRemoveToolsFiles(plainWin,
-									Paths.getEditionBasePath(), uninstall);
-					} else {
-						copyRemoveToolsFiles(plain, Paths.getEditionBasePath(),
-								uninstall);
-					}
-				}
-			}
-			if (uninstall)
-				installed.remove(m.getPackageNumber());
-			else
-				installed.add(m.getPackageNumber());
-		}
-		writeInstalledTools(installed);
-	}
-
-	private static void copyRemoveToolsFiles(File srcFolder, File targetFolder,
-			boolean remove) {
-		for (File f : srcFolder.listFiles()) {
-			try {
-				if (f.isDirectory())
-					copyRemoveToolsFiles(f,
-							CaseInsensitiveFile.getCaseInsensitiveFile(
-									targetFolder, f.getName()), remove);
-				else {
-					File targetFile = CaseInsensitiveFile
-							.getCaseInsensitiveFile(targetFolder, f.getName());
-					if (remove) {
-						if (targetFile.exists())
-							targetFile.delete();
-					} else {
-						if (!targetFile.getName().equals(f.getName()))
-							targetFile.delete();
-						FileUtils.copyFileToDirectory(f, targetFolder);
-					}
-				}
-			} catch (IOException e) {
-				e.printStackTrace();
-			}
-		}
-		if (remove)
-			if (targetFolder.list().length == 0)
-				targetFolder.delete();
-	}
-
-	/**
-	 * Install the given set of mods
-	 * 
-	 * @param mods
-	 *            Mods to install
-	 * @param listener
-	 *            Listener for install progress updates
-	 */
-	public static void install(TreeSet<Package> mods,
-			InstallProgressListener listener) {
-		File logFile = new File(Paths.getInstallerPath(), "Installation.log");
-		PrintWriter log = null;
-		try {
-			log = new PrintWriter(logFile);
-		} catch (FileNotFoundException e) {
-			e.printStackTrace();
-		}
-		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-		Date start = new Date();
-		log.println("Installation of mods started at " + sdf.format(start));
-
-		log.println();
-		log.println("AEI2 version: "
-				+ SwingJavaBuilder.getConfig().getResource("appversion"));
-		log.println("Installed tools:");
-		for (Package t : PackageManager.getInstance().getInstalledTools()) {
-			log.println(String.format(" - %s (%s)", t.getName(), t.getVersion()));
-		}
-		log.println("Installing mods:");
-		for (Package m : mods) {
-			log.println(String.format(" - %s (%s)", m.getName(), m.getVersion()));
-		}
-		log.println();
-
-		Paths.getEditionGDF().mkdirs();
-		for (File f : Paths.getEditionGDF().listFiles(new FilenameFilter() {
-			public boolean accept(File arg0, String arg1) {
-				String s = arg1.toLowerCase();
-				return s.endsWith(".dat")
-						|| s.endsWith(".raw")
-						|| s.endsWith(".sep")
-						|| (s.equals("intro.bik") && !SettingsManager
-								.getInstance().get("copyintro", false))
-						|| (s.equals("outro.bik") && !SettingsManager
-								.getInstance().get("copyoutro", false));
-			}
-		})) {
-			f.delete();
-		}
-		File IGMD = new File(Paths.getEditionGDF(), "IGMD");
-		if (IGMD.exists()) {
-			for (File f : IGMD.listFiles(new FileFilter() {
-				@Override
-				public boolean accept(File pathname) {
-					return pathname.isDirectory();
-				}
-			})) {
-				File ignore = CaseInsensitiveFile.getCaseInsensitiveFile(f,
-						"ignore.txt");
-				if (!ignore.exists()) {
-					try {
-						FileUtils.deleteDirectory(f);
-					} catch (IOException e) {
-						e.printStackTrace();
-					}
-				}
-			}
-		}
-
-		File installCfg = new File(Paths.getEditionGDF(), "installed_mods.xml");
-		PackageManager.getInstance().saveModSelection(installCfg, mods);
-
-		TreeSet<Integer> unlockLevels = new TreeSet<Integer>();
-
-		Vector<File> foldersOni = new Vector<File>();
-		foldersOni.add(Paths.getVanillaOnisPath());
-
-		Vector<File> foldersPatches = new Vector<File>();
-
-		for (Package m : mods) {
-			for (int lev : m.getUnlockLevels())
-				unlockLevels.add(lev);
-
-			File oni = CaseInsensitiveFile.getCaseInsensitiveFile(
-					m.getLocalPath(), "oni");
-			if (oni.exists()) {
-				if (m.hasSeparatePlatformDirs()) {
-					File oniCommon = CaseInsensitiveFile
-							.getCaseInsensitiveFile(oni, "common");
-					File oniMac = CaseInsensitiveFile.getCaseInsensitiveFile(
-							oni, "mac_only");
-					File oniWin = CaseInsensitiveFile.getCaseInsensitiveFile(
-							oni, "win_only");
-					if (oniCommon.exists())
-						foldersOni.add(oniCommon);
-					if (PlatformInformation.getPlatform() == Platform.MACOS
-							&& oniMac.exists())
-						foldersOni.add(oniMac);
-					else if (oniWin.exists())
-						foldersOni.add(oniWin);
-				} else {
-					foldersOni.add(oni);
-				}
-			}
-
-			File patches = CaseInsensitiveFile.getCaseInsensitiveFile(
-					m.getLocalPath(), "patches");
-			if (patches.exists()) {
-				if (m.hasSeparatePlatformDirs()) {
-					File patchesCommon = CaseInsensitiveFile
-							.getCaseInsensitiveFile(patches, "common");
-					File patchesMac = CaseInsensitiveFile
-							.getCaseInsensitiveFile(patches, "mac_only");
-					File patchesWin = CaseInsensitiveFile
-							.getCaseInsensitiveFile(patches, "win_only");
-					if (patchesCommon.exists())
-						foldersPatches.add(patchesCommon);
-					if (PlatformInformation.getPlatform() == Platform.MACOS
-							&& patchesMac.exists())
-						foldersPatches.add(patchesMac);
-					else if (patchesWin.exists())
-						foldersPatches.add(patchesWin);
-				} else {
-					foldersPatches.add(patches);
-				}
-			}
-		}
-
-		TreeMap<String, Vector<File>> levels = new TreeMap<String, Vector<File>>(
-				new NaturalOrderComparator());
-		for (File path : foldersOni) {
-			for (File levelF : path.listFiles()) {
-				String fn = levelF.getName().toLowerCase();
-				String levelN = null;
-				if (levelF.isDirectory()) {
-					levelN = fn;
-				} else if (fn.endsWith(".dat")) {
-					levelN = fn.substring(0, fn.lastIndexOf('.')).toLowerCase();
-				}
-				if (levelN != null) {
-					if (!levels.containsKey(levelN))
-						levels.put(levelN, new Vector<File>());
-					levels.get(levelN).add(levelF);
-				}
-			}
-		}
-
-		applyPatches(levels, foldersPatches, listener, log);
-
-		combineBinaryFiles(levels, listener, log);
-		combineBSLFolders(mods, listener, log);
-
-		copyVideos(log);
-
-		if (unlockLevels.size() > 0) {
-			unlockLevels(unlockLevels, log);
-		}
-
-		log.println();
-		Date end = new Date();
-		log.println("Initialization ended at " + sdf.format(end));
-		log.println("Process took "
-				+ ((end.getTime() - start.getTime()) / 1000) + " seconds");
-		log.close();
-	}
-
-	private static void combineBSLFolders(TreeSet<Package> mods,
-			InstallProgressListener listener, PrintWriter log) {
-		listener.installProgressUpdate(95, 100, "Installing BSL files");
-		log.println("Installing BSL files");
-
-		HashMap<EBSLInstallType, Vector<Package>> modsToInclude = new HashMap<EBSLInstallType, Vector<Package>>();
-		modsToInclude.put(EBSLInstallType.NORMAL, new Vector<Package>());
-		modsToInclude.put(EBSLInstallType.ADDON, new Vector<Package>());
-
-		for (Package m : mods.descendingSet()) {
-			File bsl = CaseInsensitiveFile.getCaseInsensitiveFile(
-					m.getLocalPath(), "bsl");
-			if (bsl.exists()) {
-				if (m.hasSeparatePlatformDirs()) {
-					File bslCommon = CaseInsensitiveFile
-							.getCaseInsensitiveFile(bsl, "common");
-					File bslMac = CaseInsensitiveFile.getCaseInsensitiveFile(
-							bsl, "mac_only");
-					File bslWin = CaseInsensitiveFile.getCaseInsensitiveFile(
-							bsl, "win_only");
-					if ((PlatformInformation.getPlatform() == Platform.MACOS && bslMac
-							.exists())
-							|| ((PlatformInformation.getPlatform() == Platform.WIN || PlatformInformation
-									.getPlatform() == Platform.LINUX) && bslWin
-									.exists()) || bslCommon.exists()) {
-						modsToInclude.get(m.getBSLInstallType()).add(m);
-					}
-				} else {
-					modsToInclude.get(m.getBSLInstallType()).add(m);
-				}
-			}
-		}
-
-		for (Package m : modsToInclude.get(EBSLInstallType.NORMAL)) {
-			copyBSL(m, false);
-		}
-		Vector<Package> addons = modsToInclude.get(EBSLInstallType.ADDON);
-		for (int i = addons.size() - 1; i >= 0; i--) {
-			copyBSL(addons.get(i), true);
-		}
-	}
-
-	private static void copyBSL(Package sourceMod, boolean addon) {
-		File targetBaseFolder = new File(Paths.getEditionGDF(), "IGMD");
-		if (!targetBaseFolder.exists())
-			targetBaseFolder.mkdir();
-
-		Vector<File> sources = new Vector<File>();
-		File bsl = CaseInsensitiveFile.getCaseInsensitiveFile(
-				sourceMod.getLocalPath(), "bsl");
-		if (sourceMod.hasSeparatePlatformDirs()) {
-			File bslCommon = CaseInsensitiveFile.getCaseInsensitiveFile(bsl,
-					"common");
-			File bslMac = CaseInsensitiveFile.getCaseInsensitiveFile(bsl,
-					"mac_only");
-			File bslWin = CaseInsensitiveFile.getCaseInsensitiveFile(bsl,
-					"win_only");
-			if (PlatformInformation.getPlatform() == Platform.MACOS
-					&& bslMac.exists()) {
-				for (File f : bslMac.listFiles(dirFileFilter)) {
-					File targetBSL = new File(targetBaseFolder, f.getName());
-					if (addon || !targetBSL.exists())
-						sources.add(f);
-				}
-			}
-			if ((PlatformInformation.getPlatform() == Platform.WIN || PlatformInformation
-					.getPlatform() == Platform.LINUX) && bslWin.exists()) {
-				for (File f : bslWin.listFiles(dirFileFilter)) {
-					File targetBSL = new File(targetBaseFolder, f.getName());
-					if (addon || !targetBSL.exists())
-						sources.add(f);
-				}
-			}
-			if (bslCommon.exists()) {
-				for (File f : bslCommon.listFiles(dirFileFilter)) {
-					File targetBSL = new File(targetBaseFolder, f.getName());
-					if (addon || !targetBSL.exists())
-						sources.add(f);
-				}
-			}
-		} else {
-			for (File f : bsl.listFiles(dirFileFilter)) {
-				File targetBSL = new File(targetBaseFolder, f.getName());
-				if (addon || !targetBSL.exists())
-					sources.add(f);
-			}
-		}
-
-		System.out.println("For mod: " + sourceMod.getName()
-				+ " install BSL folders: " + sources.toString());
-		for (File f : sources) {
-			File targetPath = new File(targetBaseFolder, f.getName());
-			if (!targetPath.exists())
-				targetPath.mkdir();
-			if (!(CaseInsensitiveFile.getCaseInsensitiveFile(targetPath,
-					"ignore.txt").exists())) {
-				for (File fbsl : f.listFiles()) {
-					if (fbsl.getName().toLowerCase().endsWith(".bsl")) {
-						File targetFile = new File(targetPath, fbsl.getName());
-						if (addon || !targetFile.exists()) {
-							try {
-								FileUtils.copyFile(fbsl, targetFile);
-							} catch (IOException e) {
-								e.printStackTrace();
-							}
-						}
-					}
-				}
-			}
-		}
-	}
-
-	private static void applyPatches(
-			TreeMap<String, Vector<File>> oniLevelFolders,
-			List<File> patchFolders, InstallProgressListener listener,
-			PrintWriter log) {
-		log.println();
-		log.println("Applying XML patches");
-		listener.installProgressUpdate(0, 1, "Applying XML patches");
-
-		long startMS = new Date().getTime();
-
-		String tmpFolderName = "installrun_temp-"
-				+ new SimpleDateFormat("yyyy_MM_dd-HH_mm_ss")
-						.format(new Date());
-		File tmpFolder = new File(Paths.getTempPath(), tmpFolderName);
-		tmpFolder.mkdir();
-
-		TreeMap<String, Vector<File>> patches = new TreeMap<String, Vector<File>>(
-				new NaturalOrderComparator());
-		for (File patchFolder : patchFolders) {
-			for (File levelFolder : patchFolder.listFiles(dirFileFilter)) {
-				String lvlName = levelFolder.getName().toLowerCase();
-				for (File f : FileUtils.listFiles(levelFolder,
-						new String[] { "oni-patch" }, true)) {
-					if (!patches.containsKey(lvlName))
-						patches.put(lvlName, new Vector<File>());
-					patches.get(lvlName).add(f);
-				}
-			}
-		}
-
-		for (String level : patches.keySet()) {
-			File levelFolder = new File(tmpFolder, level);
-			levelFolder.mkdir();
-
-			log.println("\t\tPatches for " + level);
-
-			Vector<String> exportPatterns = new Vector<String>();
-			// Get files to be patched from vanilla.dat
-			for (File patch : patches.get(level)) {
-				String patternWildcard = patch.getName();
-				patternWildcard = patternWildcard.substring(0,
-						patternWildcard.indexOf(".oni-patch"));
-				patternWildcard = patternWildcard.replace('-', '*');
-				exportPatterns.add(patternWildcard);
-			}
-			for (File srcFolder : oniLevelFolders.get(level)) {
-				if (srcFolder.isFile()) {
-					if (srcFolder.getPath().toLowerCase().contains("vanilla")) {
-						// Extract from .dat
-						ApplicationInvocationResult res = OniSplit.export(
-								levelFolder, srcFolder, exportPatterns);
-						logAppOutput(res, log);
-					}
-				}
-			}
-
-			// Get files to be patched from packages
-			for (File patch : patches.get(level)) {
-				String patternWildcard = patch.getName();
-				patternWildcard = patternWildcard.substring(0,
-						patternWildcard.indexOf(".oni-patch"));
-				patternWildcard = patternWildcard.replace('-', '*');
-				patternWildcard = patternWildcard + ".oni";
-				Vector<String> patterns = new Vector<String>();
-				patterns.add(patternWildcard);
-				final Pattern patternRegex = Pattern.compile(
-						patternWildcard.replaceAll("\\*", ".\\*"),
-						Pattern.CASE_INSENSITIVE);
-
-				for (File srcFolder : oniLevelFolders.get(level)) {
-					if (srcFolder.isFile()) {
-						if (!srcFolder.getPath().toLowerCase()
-								.contains("vanilla")) {
-							// Extract from .dat
-							ApplicationInvocationResult res = OniSplit.export(
-									levelFolder, srcFolder, patterns);
-							logAppOutput(res, log);
-						}
-					} else {
-						// Copy from folder with overwrite
-						for (File f : FileUtils.listFiles(srcFolder,
-								new RegexFileFilter(patternRegex),
-								TrueFileFilter.TRUE)) {
-							try {
-								FileUtils.copyFileToDirectory(f, levelFolder);
-							} catch (IOException e) {
-								e.printStackTrace();
-							}
-						}
-					}
-				}
-			}
-
-			// Extract files to XML
-			File levelFolderXML = new File(levelFolder, "xml");
-			Vector<File> files = new Vector<File>();
-			files.add(new File(levelFolder, "*.oni"));
-			ApplicationInvocationResult res = OniSplit.convertOniToXML(
-					levelFolderXML, files);
-			logAppOutput(res, log);
-
-			// Create masterpatch file (containing calls to all individual
-			// patches)
-			File masterpatch = new File(levelFolderXML, "masterpatch.oni-patch");
-			PrintWriter masterpatchWriter = null;
-			try {
-				masterpatchWriter = new PrintWriter(masterpatch);
-			} catch (FileNotFoundException e) {
-				e.printStackTrace();
-			}
-			for (File patch : patches.get(level)) {
-				String patternWildcard = patch.getName();
-				patternWildcard = patternWildcard.substring(0,
-						patternWildcard.indexOf(".oni-patch"));
-				patternWildcard = patternWildcard + ".xml";
-				patternWildcard = patternWildcard.replace('-', '*');
-				File xmlFilePath = new File(levelFolderXML, patternWildcard);
-				masterpatchWriter.println(String.format("@COMMAND patchfile -filename:\"%s\" -forceinfiles:\"%s\"", patch.getPath(), xmlFilePath.getPath()));
-			}
-			masterpatchWriter.close();
-			// Apply patches through masterpatch in levelFolderXML
-			res = XMLTools.patch(masterpatch, null);
-			logAppOutput(res, log);
-
-			// Create .oni files from XML
-			files.clear();
-			files.add(new File(levelFolderXML, "*.xml"));
-			res = OniSplit.convertXMLtoOni(levelFolder, files);
-			logAppOutput(res, log);
-
-			// Remove XML folder as import will only require .oni's
-			// try {
-			// FileUtils.deleteDirectory(levelFolderXML);
-			// } catch (IOException e) {
-			// e.printStackTrace();
-			// }
-
-			oniLevelFolders.get(level).add(levelFolder);
-		}
-
-		log.println("Applying XML patches took "
-				+ (new Date().getTime() - startMS) + " ms");
-	}
-
-	private static void combineBinaryFiles(
-			TreeMap<String, Vector<File>> oniLevelFolders,
-			InstallProgressListener listener, PrintWriter log) {
-		long startMS = new Date().getTime();
-
-		int totalSteps = oniLevelFolders.size() + 1;
-		int stepsDone = 0;
-
-		log.println();
-		log.println("Importing levels");
-		for (String l : oniLevelFolders.keySet()) {
-			log.println("\tLevel " + l);
-			listener.installProgressUpdate(stepsDone, totalSteps,
-					"Installing level " + l);
-
-			ApplicationInvocationResult res = OniSplit.packLevel(
-					oniLevelFolders.get(l), new File(Paths.getEditionGDF(),
-							sanitizeLevelName(l) + ".dat"));
-			logAppOutput(res, log);
-
-			stepsDone++;
-		}
-
-		log.println("Importing levels took " + (new Date().getTime() - startMS)
-				+ " ms");
-		log.println();
-	}
-
-	private static void copyVideos(PrintWriter log) {
-		if (SettingsManager.getInstance().get("copyintro", false)) {
-			File src = new File(Paths.getVanillaGDF(), "intro.bik");
-			log.println("Copying intro");
-			if (src.exists()) {
-				try {
-					FileUtils.copyFileToDirectory(src, Paths.getEditionGDF());
-				} catch (IOException e) {
-					e.printStackTrace();
-				}
-			}
-		} else {
-			log.println("NOT copying intro");
-		}
-		if (SettingsManager.getInstance().get("copyoutro", true)) {
-			File src = new File(Paths.getVanillaGDF(), "outro.bik");
-			log.println("Copying outro");
-			if (src.exists()) {
-				try {
-					FileUtils.copyFileToDirectory(src, Paths.getEditionGDF());
-				} catch (IOException e) {
-					e.printStackTrace();
-				}
-			}
-		} else {
-			log.println("NOT copying outro");
-		}
-	}
-
-	private static void unlockLevels(TreeSet<Integer> unlockLevels,
-			PrintWriter log) {
-		File dat = new File(Paths.getEditionBasePath(), "persist.dat");
-		log.println("Unlocking levels: " + unlockLevels.toString());
-		if (!dat.exists()) {
-			InputStream is = AEInstaller2.class
-					.getResourceAsStream("/net/oni2/aeinstaller/resources/persist.dat");
-			try {
-				FileUtils.copyInputStreamToFile(is, dat);
-			} catch (IOException e) {
-				e.printStackTrace();
-			}
-		}
-		PersistDat save = new PersistDat(dat);
-		HashSet<Integer> currentlyUnlocked = save.getUnlockedLevels();
-		currentlyUnlocked.addAll(unlockLevels);
-		save.setUnlockedLevels(currentlyUnlocked);
-		save.close();
-	}
-
-	/**
-	 * Initializes the Edition core
-	 * 
-	 * @param listener
-	 *            Listener for status updates
-	 */
-	public static void initializeEdition(InstallProgressListener listener) {
-		File init = new File(Paths.getTempPath(), "init");
-
-		int totalSteps = 0;
-		int stepsDone = 0;
-
-		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-
-		TreeSet<File> levelFiles = new TreeSet<File>(
-				new NaturalOrderComparator());
-
-		for (File f : Paths.getVanillaGDF().listFiles(new FilenameFilter() {
-			@Override
-			public boolean accept(File dir, String name) {
-				return name.endsWith(".dat");
-			}
-		})) {
-			totalSteps++;
-			levelFiles.add(f);
-		}
-		totalSteps = totalSteps * 2 + 2;
-
-		try {
-			File logFile = new File(Paths.getInstallerPath(),
-					"Initialization.log");
-			PrintWriter log = new PrintWriter(logFile);
-
-			Date start = new Date();
-			log.println("Initialization of Edition core started at "
-					+ sdf.format(start));
-			log.println("Cleaning directories");
-
-			listener.installProgressUpdate(stepsDone, totalSteps,
-					"Cleaning up directories");
-			createEmptyPath(Paths.getVanillaOnisPath());
-			createEmptyPath(init);
-			File level0Folder = new File(init, "level0_Final");
-			createEmptyPath(level0Folder);
-
-			stepsDone++;
-
-			log.println("Exporting levels and moving files to level0");
-
-			for (File f : levelFiles) {
-				String levelName = f.getName().substring(0,
-						f.getName().indexOf('.'));
-				Scanner fi = new Scanner(levelName);
-				int levelNumber = Integer.parseInt(fi.findInLine("[0-9]+"));
-
-				log.println("\t" + levelName + ":");
-				log.println("\t\tExporting");
-				listener.installProgressUpdate(stepsDone, totalSteps,
-						"Exporting vanilla level " + levelNumber);
-
-				// Edition/GameDataFolder/level*_Final/
-				File tempLevelFolder = new File(init, levelName);
-
-				// Export Vanilla-Level-Dat -> Temp/Level
-				ApplicationInvocationResult res = OniSplit.export(
-						tempLevelFolder, f);
-				logAppOutput(res, log);
-
-				log.println("\t\tMoving files");
-				handleFileGlobalisation(tempLevelFolder, level0Folder,
-						levelNumber);
-				stepsDone++;
-				log.println();
-			}
-
-			log.println("Reimporting levels");
-			TreeSet<File> initFolders = new TreeSet<File>(
-					new NaturalOrderComparator());
-			for (File f : init.listFiles()) {
-				initFolders.add(f);
-			}
-
-			for (File f : initFolders) {
-				String levelName = f.getName();
-
-				log.println("\t" + levelName);
-				listener.installProgressUpdate(stepsDone, totalSteps,
-						"Creating globalized " + levelName);
-
-				Vector<File> folders = new Vector<File>();
-				folders.add(f);
-
-				ApplicationInvocationResult res = OniSplit
-						.importLevel(folders,
-								new File(Paths.getVanillaOnisPath(), levelName
-										+ ".dat"));
-				logAppOutput(res, log);
-
-				log.println();
-				stepsDone++;
-			}
-
-			listener.installProgressUpdate(stepsDone, totalSteps,
-					"Copying basic files");
-			// Copy Oni-configs
-			File persistVanilla = new File(Paths.getOniBasePath(),
-					"persist.dat");
-			File persistEdition = new File(Paths.getEditionBasePath(),
-					"persist.dat");
-			File keyConfVanilla = new File(Paths.getOniBasePath(),
-					"key_config.txt");
-			File keyConfEdition = new File(Paths.getEditionBasePath(),
-					"key_config.txt");
-			if (persistVanilla.exists() && !persistEdition.exists())
-				FileUtils.copyFile(persistVanilla, persistEdition);
-			if (keyConfVanilla.exists() && !keyConfEdition.exists())
-				FileUtils.copyFile(keyConfVanilla, keyConfEdition);
-
-			FileUtils.deleteDirectory(init);
-
-			Date end = new Date();
-			log.println("Initialization ended at " + sdf.format(end));
-			log.println("Process took "
-					+ ((end.getTime() - start.getTime()) / 1000) + " seconds");
-			log.close();
-		} catch (IOException e) {
-			e.printStackTrace();
-		}
-	}
-
-	private static void moveFileToTargetOrDelete(File source, File target) {
-		if (source.equals(target))
-			return;
-		if (!target.exists()) {
-			if (!source.renameTo(target)) {
-				System.err.println("File " + source.getPath() + " not moved!");
-			}
-		} else if (!source.delete()) {
-			System.err.println("File " + source.getPath() + " not deleted!");
-		}
-	}
-
-	private static void handleFileGlobalisation(File tempFolder,
-			File level0Folder, int levelNumber) {
-		// Move AKEV and related files to subfolder so they're not globalized:
-		if (levelNumber != 0) {
-			File akevFolder = new File(tempFolder, "AKEV");
-			akevFolder.mkdir();
-			OniSplit.move(akevFolder, tempFolder.getPath() + "/AKEV*.oni",
-					"overwrite");
-		}
-
-		for (File f : tempFolder.listFiles(new FileFilter() {
-			@Override
-			public boolean accept(File pathname) {
-				return pathname.isFile();
-			}
-		})) {
-			// Move matching files to subfolder NoGlobal:
-			if (f.getName().startsWith("TXMPfail")
-					|| f.getName().startsWith("TXMPlevel")
-					|| (f.getName().startsWith("TXMP") && f.getName().contains(
-							"intro"))
-					|| f.getName().startsWith("TXMB")
-					|| f.getName().equals("M3GMpowerup_lsi.oni")
-					|| f.getName().equals("TXMPlsi_icon.oni")
-					|| (f.getName().startsWith("TXMB") && f.getName().contains(
-							"splash_screen.oni"))) {
-				File noGlobal = new File(tempFolder, "NoGlobal");
-				noGlobal.mkdir();
-				File noGlobalFile = new File(noGlobal, f.getName());
-				moveFileToTargetOrDelete(f, noGlobalFile);
-			}
-			// Move matching files to level0_Animations/level0_TRAC
-			else if (f.getName().startsWith("TRAC")) {
-				File level0File = new File(level0Folder, f.getName());
-				moveFileToTargetOrDelete(f, level0File);
-			}
-			// Move matching files to level0_Animations/level0_TRAM
-			else if (f.getName().startsWith("TRAM")) {
-				File level0File = new File(level0Folder, f.getName());
-				moveFileToTargetOrDelete(f, level0File);
-			}
-			// Move matching files to level0_Textures
-			else if (f.getName().startsWith("ONSK")
-					|| f.getName().startsWith("TXMP")) {
-				File level0File = new File(level0Folder, f.getName());
-				moveFileToTargetOrDelete(f, level0File);
-			}
-			// Move matching files to *VANILLA*/level0_Characters
-			else if (f.getName().startsWith("ONCC")
-					|| f.getName().startsWith("TRBS")
-					|| f.getName().startsWith("ONCV")
-					|| f.getName().startsWith("ONVL")
-					|| f.getName().startsWith("TRMA")
-					|| f.getName().startsWith("TRSC")
-					|| f.getName().startsWith("TRAS")) {
-				File level0File = new File(level0Folder, f.getName());
-				moveFileToTargetOrDelete(f, level0File);
-			}
-			// Move matching files to level0_Sounds
-			else if (f.getName().startsWith("OSBD")
-					|| f.getName().startsWith("SNDD")) {
-				File level0File = new File(level0Folder, f.getName());
-				moveFileToTargetOrDelete(f, level0File);
-			}
-			// Move matching files to level0_Particles
-			else if (f.getName().startsWith("BINA3")
-					|| f.getName().startsWith("M3GMdebris")
-					|| f.getName().equals("M3GMtoxic_bubble.oni")
-					|| f.getName().startsWith("M3GMelec")
-					|| f.getName().startsWith("M3GMrat")
-					|| f.getName().startsWith("M3GMjet")
-					|| f.getName().startsWith("M3GMbomb_")
-					|| f.getName().equals("M3GMbarab_swave.oni")
-					|| f.getName().equals("M3GMbloodyfoot.oni")) {
-				File level0File = new File(level0Folder, f.getName());
-				moveFileToTargetOrDelete(f, level0File);
-			}
-			// Move matching files to Archive (aka delete them)
-			else if (f.getName().startsWith("AGDB")
-					|| f.getName().startsWith("TRCM")) {
-				f.delete();
-			}
-			// Move matching files to /level0_Final/
-			else if (f.getName().startsWith("ONWC")) {
-				File level0File = new File(level0Folder, f.getName());
-				moveFileToTargetOrDelete(f, level0File);
-			}
-		}
-	}
-
-	private static String sanitizeLevelName(String ln) {
-		int ind = ln.indexOf("_");
-		String res = ln.substring(0, ind + 1);
-		res += ln.substring(ind + 1, ind + 2).toUpperCase();
-		res += ln.substring(ind + 2);
-		return res;
-	}
-
-	/**
-	 * Verify that the Edition is within a subfolder to vanilla Oni
-	 * (..../Oni/Edition/AEInstaller)
-	 * 
-	 * @return true if GDF can be found in the parent's parent-path
-	 */
-	public static boolean verifyRunningDirectory() {
-		return Paths.getVanillaGDF().exists()
-				&& Paths.getVanillaGDF().isDirectory();
-	}
-
-	private static void logAppOutput(ApplicationInvocationResult result,
-			PrintWriter log) {
-		if (result != null) {
-			log.println("\t\t\tCalled:");
-			for (String s : result.cmdLine)
-				log.println("\t\t\t\t" + s);
-			log.println("\t\t\tReturned: " + result.errorCode);
-			for (String s : result.output)
-				log.println("\t\t\t\t" + s);
-			log.println("\t\t\tDuration: " + result.time + " ms");
-			log.println();
-		}
-	}
-}
Index: /java/installer2/src/net/oni2/aeinstaller/backend/oni/management/Initializer.java
===================================================================
--- /java/installer2/src/net/oni2/aeinstaller/backend/oni/management/Initializer.java	(revision 749)
+++ /java/installer2/src/net/oni2/aeinstaller/backend/oni/management/Initializer.java	(revision 749)
@@ -0,0 +1,263 @@
+package net.oni2.aeinstaller.backend.oni.management;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Scanner;
+import java.util.TreeSet;
+import java.util.Vector;
+
+import net.oni2.aeinstaller.backend.Paths;
+import net.oni2.aeinstaller.backend.oni.OniSplit;
+import net.oni2.platformtools.applicationinvoker.ApplicationInvocationResult;
+
+import org.apache.commons.io.FileUtils;
+
+import com.paour.NaturalOrderComparator;
+
+/**
+ * @author Christian Illy
+ */
+public class Initializer {
+	private static void createEmptyPath(File path) throws IOException {
+		if (path.exists())
+			FileUtils.deleteDirectory(path);
+		path.mkdirs();
+	}
+
+	/**
+	 * Initializes the Edition core
+	 * 
+	 * @param listener
+	 *            Listener for status updates
+	 */
+	public static void initializeEdition(InstallProgressListener listener) {
+		File init = new File(Paths.getTempPath(), "init");
+
+		int totalSteps = 0;
+		int stepsDone = 0;
+
+		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+		TreeSet<File> levelFiles = new TreeSet<File>(
+				new NaturalOrderComparator());
+
+		for (File f : Paths.getVanillaGDF().listFiles(new FilenameFilter() {
+			@Override
+			public boolean accept(File dir, String name) {
+				return name.endsWith(".dat");
+			}
+		})) {
+			totalSteps++;
+			levelFiles.add(f);
+		}
+		totalSteps = totalSteps * 2 + 2;
+
+		try {
+			File logFile = new File(Paths.getInstallerPath(),
+					"Initialization.log");
+			Logger log = new Logger(logFile);
+
+			Date start = new Date();
+			log.println("Initialization of Edition core started at "
+					+ sdf.format(start));
+			log.println("Cleaning directories");
+
+			listener.installProgressUpdate(stepsDone, totalSteps,
+					"Cleaning up directories");
+			createEmptyPath(Paths.getVanillaOnisPath());
+			createEmptyPath(init);
+			File level0Folder = new File(init, "level0_Final");
+			createEmptyPath(level0Folder);
+
+			stepsDone++;
+
+			log.println("Exporting levels and moving files to level0");
+
+			for (File f : levelFiles) {
+				String levelName = f.getName().substring(0,
+						f.getName().indexOf('.'));
+				Scanner fi = new Scanner(levelName);
+				int levelNumber = Integer.parseInt(fi.findInLine("[0-9]+"));
+
+				log.println("\t" + levelName + ":");
+				log.println("\t\tExporting");
+				listener.installProgressUpdate(stepsDone, totalSteps,
+						"Exporting vanilla level " + levelNumber);
+
+				// Edition/GameDataFolder/level*_Final/
+				File tempLevelFolder = new File(init, levelName);
+
+				// Export Vanilla-Level-Dat -> Temp/Level
+				ApplicationInvocationResult res = OniSplit.export(
+						tempLevelFolder, f);
+				log.logAppOutput(res, true);
+
+				log.println("\t\tMoving files");
+				handleFileGlobalisation(tempLevelFolder, level0Folder,
+						levelNumber);
+				stepsDone++;
+				log.println();
+			}
+
+			log.println("Reimporting levels");
+			TreeSet<File> initFolders = new TreeSet<File>(
+					new NaturalOrderComparator());
+			for (File f : init.listFiles()) {
+				initFolders.add(f);
+			}
+
+			for (File f : initFolders) {
+				String levelName = f.getName();
+
+				log.println("\t" + levelName);
+				listener.installProgressUpdate(stepsDone, totalSteps,
+						"Creating globalized " + levelName);
+
+				Vector<File> folders = new Vector<File>();
+				folders.add(f);
+
+				ApplicationInvocationResult res = OniSplit
+						.importLevel(folders,
+								new File(Paths.getVanillaOnisPath(), levelName
+										+ ".dat"));
+				log.logAppOutput(res, true);
+
+				log.println();
+				stepsDone++;
+			}
+
+			listener.installProgressUpdate(stepsDone, totalSteps,
+					"Copying basic files");
+			// Copy Oni-configs
+			File persistVanilla = new File(Paths.getOniBasePath(),
+					"persist.dat");
+			File persistEdition = new File(Paths.getEditionBasePath(),
+					"persist.dat");
+			File keyConfVanilla = new File(Paths.getOniBasePath(),
+					"key_config.txt");
+			File keyConfEdition = new File(Paths.getEditionBasePath(),
+					"key_config.txt");
+			if (persistVanilla.exists() && !persistEdition.exists())
+				FileUtils.copyFile(persistVanilla, persistEdition);
+			if (keyConfVanilla.exists() && !keyConfEdition.exists())
+				FileUtils.copyFile(keyConfVanilla, keyConfEdition);
+
+			FileUtils.deleteDirectory(init);
+
+			Date end = new Date();
+			log.println("Initialization ended at " + sdf.format(end));
+			log.println("Process took "
+					+ ((end.getTime() - start.getTime()) / 1000) + " seconds");
+			log.close();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+
+	private static void moveFileToTargetOrDelete(File source, File target) {
+		if (source.equals(target))
+			return;
+		if (!target.exists()) {
+			if (!source.renameTo(target)) {
+				System.err.println("File " + source.getPath() + " not moved!");
+			}
+		} else if (!source.delete()) {
+			System.err.println("File " + source.getPath() + " not deleted!");
+		}
+	}
+
+	private static void handleFileGlobalisation(File tempFolder,
+			File level0Folder, int levelNumber) {
+		// Move AKEV and related files to subfolder so they're not globalized:
+		if (levelNumber != 0) {
+			File akevFolder = new File(tempFolder, "AKEV");
+			akevFolder.mkdir();
+			OniSplit.move(akevFolder, tempFolder.getPath() + "/AKEV*.oni",
+					"overwrite");
+		}
+
+		for (File f : tempFolder.listFiles(new FileFilter() {
+			@Override
+			public boolean accept(File pathname) {
+				return pathname.isFile();
+			}
+		})) {
+			// Move matching files to subfolder NoGlobal:
+			if (f.getName().startsWith("TXMPfail")
+					|| f.getName().startsWith("TXMPlevel")
+					|| (f.getName().startsWith("TXMP") && f.getName().contains(
+							"intro"))
+					|| f.getName().startsWith("TXMB")
+					|| f.getName().equals("M3GMpowerup_lsi.oni")
+					|| f.getName().equals("TXMPlsi_icon.oni")
+					|| (f.getName().startsWith("TXMB") && f.getName().contains(
+							"splash_screen.oni"))) {
+				File noGlobal = new File(tempFolder, "NoGlobal");
+				noGlobal.mkdir();
+				File noGlobalFile = new File(noGlobal, f.getName());
+				moveFileToTargetOrDelete(f, noGlobalFile);
+			}
+			// Move matching files to level0_Animations/level0_TRAC
+			else if (f.getName().startsWith("TRAC")) {
+				File level0File = new File(level0Folder, f.getName());
+				moveFileToTargetOrDelete(f, level0File);
+			}
+			// Move matching files to level0_Animations/level0_TRAM
+			else if (f.getName().startsWith("TRAM")) {
+				File level0File = new File(level0Folder, f.getName());
+				moveFileToTargetOrDelete(f, level0File);
+			}
+			// Move matching files to level0_Textures
+			else if (f.getName().startsWith("ONSK")
+					|| f.getName().startsWith("TXMP")) {
+				File level0File = new File(level0Folder, f.getName());
+				moveFileToTargetOrDelete(f, level0File);
+			}
+			// Move matching files to *VANILLA*/level0_Characters
+			else if (f.getName().startsWith("ONCC")
+					|| f.getName().startsWith("TRBS")
+					|| f.getName().startsWith("ONCV")
+					|| f.getName().startsWith("ONVL")
+					|| f.getName().startsWith("TRMA")
+					|| f.getName().startsWith("TRSC")
+					|| f.getName().startsWith("TRAS")) {
+				File level0File = new File(level0Folder, f.getName());
+				moveFileToTargetOrDelete(f, level0File);
+			}
+			// Move matching files to level0_Sounds
+			else if (f.getName().startsWith("OSBD")
+					|| f.getName().startsWith("SNDD")) {
+				File level0File = new File(level0Folder, f.getName());
+				moveFileToTargetOrDelete(f, level0File);
+			}
+			// Move matching files to level0_Particles
+			else if (f.getName().startsWith("BINA3")
+					|| f.getName().startsWith("M3GMdebris")
+					|| f.getName().equals("M3GMtoxic_bubble.oni")
+					|| f.getName().startsWith("M3GMelec")
+					|| f.getName().startsWith("M3GMrat")
+					|| f.getName().startsWith("M3GMjet")
+					|| f.getName().startsWith("M3GMbomb_")
+					|| f.getName().equals("M3GMbarab_swave.oni")
+					|| f.getName().equals("M3GMbloodyfoot.oni")) {
+				File level0File = new File(level0Folder, f.getName());
+				moveFileToTargetOrDelete(f, level0File);
+			}
+			// Move matching files to Archive (aka delete them)
+			else if (f.getName().startsWith("AGDB")
+					|| f.getName().startsWith("TRCM")) {
+				f.delete();
+			}
+			// Move matching files to /level0_Final/
+			else if (f.getName().startsWith("ONWC")) {
+				File level0File = new File(level0Folder, f.getName());
+				moveFileToTargetOrDelete(f, level0File);
+			}
+		}
+	}
+
+}
Index: /java/installer2/src/net/oni2/aeinstaller/backend/oni/management/InstallProgressListener.java
===================================================================
--- /java/installer2/src/net/oni2/aeinstaller/backend/oni/management/InstallProgressListener.java	(revision 749)
+++ /java/installer2/src/net/oni2/aeinstaller/backend/oni/management/InstallProgressListener.java	(revision 749)
@@ -0,0 +1,18 @@
+package net.oni2.aeinstaller.backend.oni.management;
+
+/**
+ * @author Christian Illy
+ */
+public interface InstallProgressListener {
+	/**
+	 * Called when installation process advances
+	 * 
+	 * @param done
+	 *            Steps done
+	 * @param total
+	 *            Steps in total
+	 * @param step
+	 *            Name of step
+	 */
+	public void installProgressUpdate(int done, int total, String step);
+}
Index: /java/installer2/src/net/oni2/aeinstaller/backend/oni/management/Installer.java
===================================================================
--- /java/installer2/src/net/oni2/aeinstaller/backend/oni/management/Installer.java	(revision 749)
+++ /java/installer2/src/net/oni2/aeinstaller/backend/oni/management/Installer.java	(revision 749)
@@ -0,0 +1,590 @@
+package net.oni2.aeinstaller.backend.oni.management;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileNotFoundException;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.Vector;
+import java.util.regex.Pattern;
+
+import net.oni2.SettingsManager;
+import net.oni2.aeinstaller.AEInstaller2;
+import net.oni2.aeinstaller.backend.CaseInsensitiveFile;
+import net.oni2.aeinstaller.backend.Paths;
+import net.oni2.aeinstaller.backend.oni.OniSplit;
+import net.oni2.aeinstaller.backend.oni.PersistDat;
+import net.oni2.aeinstaller.backend.oni.XMLTools;
+import net.oni2.aeinstaller.backend.packages.EBSLInstallType;
+import net.oni2.aeinstaller.backend.packages.Package;
+import net.oni2.aeinstaller.backend.packages.PackageManager;
+import net.oni2.platformtools.PlatformInformation;
+import net.oni2.platformtools.PlatformInformation.Platform;
+import net.oni2.platformtools.applicationinvoker.ApplicationInvocationResult;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.filefilter.RegexFileFilter;
+import org.apache.commons.io.filefilter.TrueFileFilter;
+import org.javabuilders.swing.SwingJavaBuilder;
+
+import com.paour.NaturalOrderComparator;
+
+/**
+ * @author Christian Illy
+ */
+public class Installer {
+	private static FileFilter dirFileFilter = new FileFilter() {
+		@Override
+		public boolean accept(File pathname) {
+			return pathname.isDirectory();
+		}
+	};
+
+	/**
+	 * Verify that the Edition is within a subfolder to vanilla Oni
+	 * (..../Oni/Edition/AEInstaller)
+	 * 
+	 * @return true if GDF can be found in the parent's parent-path
+	 */
+	public static boolean verifyRunningDirectory() {
+		return Paths.getVanillaGDF().exists()
+				&& Paths.getVanillaGDF().isDirectory();
+	}
+
+	/**
+	 * @return Is Edition Core initialized
+	 */
+	public static boolean isEditionInitialized() {
+		return Paths.getVanillaOnisPath().exists();
+	}
+
+	/**
+	 * @return list of currently installed mods
+	 */
+	public static Vector<Integer> getInstalledMods() {
+		File installCfg = new File(Paths.getEditionGDF(), "installed_mods.xml");
+		return PackageManager.getInstance().loadModSelection(installCfg);
+	}
+
+	/**
+	 * Install the given set of mods
+	 * 
+	 * @param mods
+	 *            Mods to install
+	 * @param listener
+	 *            Listener for install progress updates
+	 */
+	public static void install(TreeSet<Package> mods,
+			InstallProgressListener listener) {
+		File logFile = new File(Paths.getInstallerPath(), "Installation.log");
+		Logger log = null;
+		try {
+			log = new Logger(logFile);
+		} catch (FileNotFoundException e) {
+			e.printStackTrace();
+		}
+		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+		Date start = new Date();
+		log.println("Installation of mods started at " + sdf.format(start));
+
+		log.println();
+		log.println("AEI2 version: "
+				+ SwingJavaBuilder.getConfig().getResource("appversion"));
+		log.println("Installed tools:");
+		for (Package t : PackageManager.getInstance().getInstalledTools()) {
+			log.println(String.format(" - %s (%s)", t.getName(), t.getVersion()));
+		}
+		log.println("Installing mods:");
+		for (Package m : mods) {
+			log.println(String.format(" - %s (%s)", m.getName(), m.getVersion()));
+		}
+		log.println();
+
+		Paths.getEditionGDF().mkdirs();
+		for (File f : Paths.getEditionGDF().listFiles(new FilenameFilter() {
+			public boolean accept(File arg0, String arg1) {
+				String s = arg1.toLowerCase();
+				return s.endsWith(".dat")
+						|| s.endsWith(".raw")
+						|| s.endsWith(".sep")
+						|| (s.equals("intro.bik") && !SettingsManager
+								.getInstance().get("copyintro", false))
+						|| (s.equals("outro.bik") && !SettingsManager
+								.getInstance().get("copyoutro", false));
+			}
+		})) {
+			f.delete();
+		}
+		File IGMD = new File(Paths.getEditionGDF(), "IGMD");
+		if (IGMD.exists()) {
+			for (File f : IGMD.listFiles(new FileFilter() {
+				@Override
+				public boolean accept(File pathname) {
+					return pathname.isDirectory();
+				}
+			})) {
+				File ignore = CaseInsensitiveFile.getCaseInsensitiveFile(f,
+						"ignore.txt");
+				if (!ignore.exists()) {
+					try {
+						FileUtils.deleteDirectory(f);
+					} catch (IOException e) {
+						e.printStackTrace();
+					}
+				}
+			}
+		}
+
+		File installCfg = new File(Paths.getEditionGDF(), "installed_mods.xml");
+		PackageManager.getInstance().saveModSelection(installCfg, mods);
+
+		TreeSet<Integer> unlockLevels = new TreeSet<Integer>();
+
+		Vector<File> foldersOni = new Vector<File>();
+		foldersOni.add(Paths.getVanillaOnisPath());
+
+		Vector<File> foldersPatches = new Vector<File>();
+
+		for (Package m : mods) {
+			for (int lev : m.getUnlockLevels())
+				unlockLevels.add(lev);
+
+			File oni = CaseInsensitiveFile.getCaseInsensitiveFile(
+					m.getLocalPath(), "oni");
+			if (oni.exists()) {
+				if (m.hasSeparatePlatformDirs()) {
+					File oniCommon = CaseInsensitiveFile
+							.getCaseInsensitiveFile(oni, "common");
+					File oniMac = CaseInsensitiveFile.getCaseInsensitiveFile(
+							oni, "mac_only");
+					File oniWin = CaseInsensitiveFile.getCaseInsensitiveFile(
+							oni, "win_only");
+					if (oniCommon.exists())
+						foldersOni.add(oniCommon);
+					if (PlatformInformation.getPlatform() == Platform.MACOS
+							&& oniMac.exists())
+						foldersOni.add(oniMac);
+					else if (oniWin.exists())
+						foldersOni.add(oniWin);
+				} else {
+					foldersOni.add(oni);
+				}
+			}
+
+			File patches = CaseInsensitiveFile.getCaseInsensitiveFile(
+					m.getLocalPath(), "patches");
+			if (patches.exists()) {
+				if (m.hasSeparatePlatformDirs()) {
+					File patchesCommon = CaseInsensitiveFile
+							.getCaseInsensitiveFile(patches, "common");
+					File patchesMac = CaseInsensitiveFile
+							.getCaseInsensitiveFile(patches, "mac_only");
+					File patchesWin = CaseInsensitiveFile
+							.getCaseInsensitiveFile(patches, "win_only");
+					if (patchesCommon.exists())
+						foldersPatches.add(patchesCommon);
+					if (PlatformInformation.getPlatform() == Platform.MACOS
+							&& patchesMac.exists())
+						foldersPatches.add(patchesMac);
+					else if (patchesWin.exists())
+						foldersPatches.add(patchesWin);
+				} else {
+					foldersPatches.add(patches);
+				}
+			}
+		}
+
+		TreeMap<String, Vector<File>> levels = new TreeMap<String, Vector<File>>(
+				new NaturalOrderComparator());
+		for (File path : foldersOni) {
+			for (File levelF : path.listFiles()) {
+				String fn = levelF.getName().toLowerCase();
+				String levelN = null;
+				if (levelF.isDirectory()) {
+					levelN = fn;
+				} else if (fn.endsWith(".dat")) {
+					levelN = fn.substring(0, fn.lastIndexOf('.')).toLowerCase();
+				}
+				if (levelN != null) {
+					if (!levels.containsKey(levelN))
+						levels.put(levelN, new Vector<File>());
+					levels.get(levelN).add(levelF);
+				}
+			}
+		}
+
+		applyPatches(levels, foldersPatches, listener, log);
+
+		combineBinaryFiles(levels, listener, log);
+		combineBSLFolders(mods, listener, log);
+
+		copyVideos(log);
+
+		if (unlockLevels.size() > 0) {
+			unlockLevels(unlockLevels, log);
+		}
+
+		log.println();
+		Date end = new Date();
+		log.println("Initialization ended at " + sdf.format(end));
+		log.println("Process took "
+				+ ((end.getTime() - start.getTime()) / 1000) + " seconds");
+		log.close();
+	}
+
+	private static void combineBSLFolders(TreeSet<Package> mods,
+			InstallProgressListener listener, Logger log) {
+		listener.installProgressUpdate(95, 100, "Installing BSL files");
+		log.println();
+		log.println("Installing BSL files");
+
+		HashMap<EBSLInstallType, Vector<Package>> modsToInclude = new HashMap<EBSLInstallType, Vector<Package>>();
+		modsToInclude.put(EBSLInstallType.NORMAL, new Vector<Package>());
+		modsToInclude.put(EBSLInstallType.ADDON, new Vector<Package>());
+
+		for (Package m : mods.descendingSet()) {
+			File bsl = CaseInsensitiveFile.getCaseInsensitiveFile(
+					m.getLocalPath(), "bsl");
+			if (bsl.exists()) {
+				if (m.hasSeparatePlatformDirs()) {
+					File bslCommon = CaseInsensitiveFile
+							.getCaseInsensitiveFile(bsl, "common");
+					File bslMac = CaseInsensitiveFile.getCaseInsensitiveFile(
+							bsl, "mac_only");
+					File bslWin = CaseInsensitiveFile.getCaseInsensitiveFile(
+							bsl, "win_only");
+					if ((PlatformInformation.getPlatform() == Platform.MACOS && bslMac
+							.exists())
+							|| ((PlatformInformation.getPlatform() == Platform.WIN || PlatformInformation
+									.getPlatform() == Platform.LINUX) && bslWin
+									.exists()) || bslCommon.exists()) {
+						modsToInclude.get(m.getBSLInstallType()).add(m);
+					}
+				} else {
+					modsToInclude.get(m.getBSLInstallType()).add(m);
+				}
+			}
+		}
+
+		for (Package m : modsToInclude.get(EBSLInstallType.NORMAL)) {
+			copyBSL(m, false, log);
+		}
+		Vector<Package> addons = modsToInclude.get(EBSLInstallType.ADDON);
+		for (int i = addons.size() - 1; i >= 0; i--) {
+			copyBSL(addons.get(i), true, log);
+		}
+	}
+
+	private static void copyBSL(Package sourceMod, boolean addon, Logger log) {
+		File targetBaseFolder = new File(Paths.getEditionGDF(), "IGMD");
+		if (!targetBaseFolder.exists())
+			targetBaseFolder.mkdir();
+
+		Vector<File> sources = new Vector<File>();
+		File bsl = CaseInsensitiveFile.getCaseInsensitiveFile(
+				sourceMod.getLocalPath(), "bsl");
+		if (sourceMod.hasSeparatePlatformDirs()) {
+			File bslCommon = CaseInsensitiveFile.getCaseInsensitiveFile(bsl,
+					"common");
+			File bslMac = CaseInsensitiveFile.getCaseInsensitiveFile(bsl,
+					"mac_only");
+			File bslWin = CaseInsensitiveFile.getCaseInsensitiveFile(bsl,
+					"win_only");
+			if (PlatformInformation.getPlatform() == Platform.MACOS
+					&& bslMac.exists()) {
+				for (File f : bslMac.listFiles(dirFileFilter)) {
+					File targetBSL = new File(targetBaseFolder, f.getName());
+					if (addon || !targetBSL.exists())
+						sources.add(f);
+				}
+			}
+			if ((PlatformInformation.getPlatform() == Platform.WIN || PlatformInformation
+					.getPlatform() == Platform.LINUX) && bslWin.exists()) {
+				for (File f : bslWin.listFiles(dirFileFilter)) {
+					File targetBSL = new File(targetBaseFolder, f.getName());
+					if (addon || !targetBSL.exists())
+						sources.add(f);
+				}
+			}
+			if (bslCommon.exists()) {
+				for (File f : bslCommon.listFiles(dirFileFilter)) {
+					File targetBSL = new File(targetBaseFolder, f.getName());
+					if (addon || !targetBSL.exists())
+						sources.add(f);
+				}
+			}
+		} else {
+			for (File f : bsl.listFiles(dirFileFilter)) {
+				File targetBSL = new File(targetBaseFolder, f.getName());
+				if (addon || !targetBSL.exists())
+					sources.add(f);
+			}
+		}
+
+		log.println("\tMod \"" + sourceMod.getName() + "\"");
+		for (File f : sources) {
+			log.println("\t\t" + f.getName());
+			File targetPath = new File(targetBaseFolder, f.getName());
+			if (!targetPath.exists())
+				targetPath.mkdir();
+			if (!(CaseInsensitiveFile.getCaseInsensitiveFile(targetPath,
+					"ignore.txt").exists())) {
+				for (File fbsl : f.listFiles()) {
+					if (fbsl.getName().toLowerCase().endsWith(".bsl")) {
+						File targetFile = new File(targetPath, fbsl.getName());
+						if (addon || !targetFile.exists()) {
+							try {
+								FileUtils.copyFile(fbsl, targetFile);
+							} catch (IOException e) {
+								e.printStackTrace();
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	private static void applyPatches(
+			TreeMap<String, Vector<File>> oniLevelFolders,
+			List<File> patchFolders, InstallProgressListener listener,
+			Logger log) {
+		log.println();
+		log.println("Applying XML patches");
+		listener.installProgressUpdate(0, 1, "Applying XML patches");
+
+		long startMS = new Date().getTime();
+
+		String tmpFolderName = "installrun_temp-"
+				+ new SimpleDateFormat("yyyy_MM_dd-HH_mm_ss")
+						.format(new Date());
+		File tmpFolder = new File(Paths.getTempPath(), tmpFolderName);
+		tmpFolder.mkdir();
+
+		TreeMap<String, Vector<File>> patches = new TreeMap<String, Vector<File>>(
+				new NaturalOrderComparator());
+		for (File patchFolder : patchFolders) {
+			for (File levelFolder : patchFolder.listFiles(dirFileFilter)) {
+				String lvlName = levelFolder.getName().toLowerCase();
+				for (File f : FileUtils.listFiles(levelFolder,
+						new String[] { "oni-patch" }, true)) {
+					if (!patches.containsKey(lvlName))
+						patches.put(lvlName, new Vector<File>());
+					patches.get(lvlName).add(f);
+				}
+			}
+		}
+
+		for (String level : patches.keySet()) {
+			File levelFolder = new File(tmpFolder, level);
+			levelFolder.mkdir();
+
+			log.println("\t\tPatches for " + level);
+
+			Vector<String> exportPatterns = new Vector<String>();
+			// Get files to be patched from vanilla.dat
+			for (File patch : patches.get(level)) {
+				String patternWildcard = patch.getName();
+				patternWildcard = patternWildcard.substring(0,
+						patternWildcard.indexOf(".oni-patch"));
+				patternWildcard = patternWildcard.replace('-', '*');
+				exportPatterns.add(patternWildcard);
+			}
+			for (File srcFolder : oniLevelFolders.get(level)) {
+				if (srcFolder.isFile()) {
+					if (srcFolder.getPath().toLowerCase().contains("vanilla")) {
+						// Extract from .dat
+						ApplicationInvocationResult res = OniSplit.export(
+								levelFolder, srcFolder, exportPatterns);
+						log.logAppOutput(res, true);
+					}
+				}
+			}
+
+			// Get files to be patched from packages
+			for (File patch : patches.get(level)) {
+				String patternWildcard = patch.getName();
+				patternWildcard = patternWildcard.substring(0,
+						patternWildcard.indexOf(".oni-patch"));
+				patternWildcard = patternWildcard.replace('-', '*');
+				patternWildcard = patternWildcard + ".oni";
+				Vector<String> patterns = new Vector<String>();
+				patterns.add(patternWildcard);
+				final Pattern patternRegex = Pattern.compile(
+						patternWildcard.replaceAll("\\*", ".\\*"),
+						Pattern.CASE_INSENSITIVE);
+
+				for (File srcFolder : oniLevelFolders.get(level)) {
+					if (srcFolder.isFile()) {
+						if (!srcFolder.getPath().toLowerCase()
+								.contains("vanilla")) {
+							// Extract from .dat
+							ApplicationInvocationResult res = OniSplit.export(
+									levelFolder, srcFolder, patterns);
+							log.logAppOutput(res, true);
+						}
+					} else {
+						// Copy from folder with overwrite
+						for (File f : FileUtils.listFiles(srcFolder,
+								new RegexFileFilter(patternRegex),
+								TrueFileFilter.TRUE)) {
+							try {
+								FileUtils.copyFileToDirectory(f, levelFolder);
+							} catch (IOException e) {
+								e.printStackTrace();
+							}
+						}
+					}
+				}
+			}
+
+			// Extract files to XML
+			File levelFolderXML = new File(levelFolder, "xml");
+			Vector<File> files = new Vector<File>();
+			files.add(new File(levelFolder, "*.oni"));
+			ApplicationInvocationResult res = OniSplit.convertOniToXML(
+					levelFolderXML, files);
+			log.logAppOutput(res, true);
+
+			// Create masterpatch file (containing calls to all individual
+			// patches)
+			File masterpatch = new File(levelFolderXML, "masterpatch.oni-patch");
+			PrintWriter masterpatchWriter = null;
+			try {
+				masterpatchWriter = new PrintWriter(masterpatch);
+			} catch (FileNotFoundException e) {
+				e.printStackTrace();
+			}
+			for (File patch : patches.get(level)) {
+				String patternWildcard = patch.getName();
+				patternWildcard = patternWildcard.substring(0,
+						patternWildcard.indexOf(".oni-patch"));
+				patternWildcard = patternWildcard + ".xml";
+				patternWildcard = patternWildcard.replace('-', '*');
+				File xmlFilePath = new File(levelFolderXML, patternWildcard);
+				masterpatchWriter
+						.println(String
+								.format("@COMMAND patchfile -filename:\"%s\" -forceinfiles:\"%s\"",
+										patch.getPath(), xmlFilePath.getPath()));
+			}
+			masterpatchWriter.close();
+			// Apply patches through masterpatch in levelFolderXML
+			res = XMLTools.patch(masterpatch, null);
+			log.logAppOutput(res, false);
+
+			// Create .oni files from XML
+			files.clear();
+			files.add(new File(levelFolderXML, "*.xml"));
+			res = OniSplit.convertXMLtoOni(levelFolder, files);
+			log.logAppOutput(res, true);
+
+			// Remove XML folder as import will only require .oni's
+			// try {
+			// FileUtils.deleteDirectory(levelFolderXML);
+			// } catch (IOException e) {
+			// e.printStackTrace();
+			// }
+
+			oniLevelFolders.get(level).add(levelFolder);
+		}
+
+		log.println("Applying XML patches took "
+				+ (new Date().getTime() - startMS) + " ms");
+	}
+
+	private static void combineBinaryFiles(
+			TreeMap<String, Vector<File>> oniLevelFolders,
+			InstallProgressListener listener, Logger log) {
+		long startMS = new Date().getTime();
+
+		int totalSteps = oniLevelFolders.size() + 1;
+		int stepsDone = 0;
+
+		log.println();
+		log.println("Importing levels");
+		for (String l : oniLevelFolders.keySet()) {
+			log.println("\tLevel " + l);
+			listener.installProgressUpdate(stepsDone, totalSteps,
+					"Installing level " + l);
+
+			ApplicationInvocationResult res = OniSplit.packLevel(
+					oniLevelFolders.get(l), new File(Paths.getEditionGDF(),
+							sanitizeLevelName(l) + ".dat"));
+			log.logAppOutput(res, true);
+
+			stepsDone++;
+		}
+
+		log.println("Importing levels took " + (new Date().getTime() - startMS)
+				+ " ms");
+		log.println();
+	}
+
+	private static void copyVideos(Logger log) {
+		log.println();
+		if (SettingsManager.getInstance().get("copyintro", false)) {
+			File src = new File(Paths.getVanillaGDF(), "intro.bik");
+			log.println("Copying intro");
+			if (src.exists()) {
+				try {
+					FileUtils.copyFileToDirectory(src, Paths.getEditionGDF());
+				} catch (IOException e) {
+					e.printStackTrace();
+				}
+			}
+		} else {
+			log.println("NOT copying intro");
+		}
+		if (SettingsManager.getInstance().get("copyoutro", true)) {
+			File src = new File(Paths.getVanillaGDF(), "outro.bik");
+			log.println("Copying outro");
+			if (src.exists()) {
+				try {
+					FileUtils.copyFileToDirectory(src, Paths.getEditionGDF());
+				} catch (IOException e) {
+					e.printStackTrace();
+				}
+			}
+		} else {
+			log.println("NOT copying outro");
+		}
+	}
+
+	private static void unlockLevels(TreeSet<Integer> unlockLevels, Logger log) {
+		File dat = new File(Paths.getEditionBasePath(), "persist.dat");
+		log.println();
+		log.println("Unlocking levels: " + unlockLevels.toString());
+		if (!dat.exists()) {
+			InputStream is = AEInstaller2.class
+					.getResourceAsStream("/net/oni2/aeinstaller/resources/persist.dat");
+			try {
+				FileUtils.copyInputStreamToFile(is, dat);
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+		PersistDat save = new PersistDat(dat);
+		HashSet<Integer> currentlyUnlocked = save.getUnlockedLevels();
+		currentlyUnlocked.addAll(unlockLevels);
+		save.setUnlockedLevels(currentlyUnlocked);
+		save.close();
+	}
+
+	private static String sanitizeLevelName(String ln) {
+		int ind = ln.indexOf("_");
+		String res = ln.substring(0, ind + 1);
+		res += ln.substring(ind + 1, ind + 2).toUpperCase();
+		res += ln.substring(ind + 2);
+		return res;
+	}
+
+}
Index: /java/installer2/src/net/oni2/aeinstaller/backend/oni/management/Logger.java
===================================================================
--- /java/installer2/src/net/oni2/aeinstaller/backend/oni/management/Logger.java	(revision 749)
+++ /java/installer2/src/net/oni2/aeinstaller/backend/oni/management/Logger.java	(revision 749)
@@ -0,0 +1,86 @@
+package net.oni2.aeinstaller.backend.oni.management;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+
+import net.oni2.platformtools.applicationinvoker.ApplicationInvocationResult;
+
+/**
+ * @author Christian Illy
+ */
+public class Logger {
+	PrintWriter log = null;
+
+	/**
+	 * @param logfile
+	 *            File to log to
+	 * @throws FileNotFoundException
+	 *             Huh?
+	 */
+	public Logger(File logfile) throws FileNotFoundException {
+		log = new PrintWriter(logfile);
+	}
+
+	/**
+	 * Print an empty line
+	 */
+	public void println() {
+		log.println();
+	}
+
+	/**
+	 * Print a string as a line
+	 * 
+	 * @param line
+	 *            String to print
+	 */
+	public void println(String line) {
+		log.println(line);
+	}
+
+	/**
+	 * Print a formatted string as a line
+	 * 
+	 * @param fmt
+	 *            Format string
+	 * @param args
+	 *            Values
+	 */
+	public void printlnFmt(String fmt, Object... args) {
+		log.println(String.format(fmt, args));
+	}
+
+	/**
+	 * Close logger
+	 */
+	public void close() {
+		log.close();
+		log = null;
+	}
+
+	/**
+	 * Log the application invocation result
+	 * 
+	 * @param result
+	 *            App result
+	 * @param onlyOnError
+	 *            Print returned output only on errorcode != 0
+	 */
+	public void logAppOutput(ApplicationInvocationResult result,
+			boolean onlyOnError) {
+		if (result != null) {
+			log.println("\t\t\tCalled:");
+			for (String s : result.cmdLine)
+				log.println("\t\t\t\t" + s);
+			log.println("\t\t\tReturned: " + result.errorCode);
+			if (!onlyOnError || result.errorCode != 0) {
+				for (String s : result.output)
+					log.println("\t\t\t\t" + s);
+			}
+			log.println("\t\t\tDuration: " + result.time + " ms");
+			log.println();
+		}
+	}
+
+}
Index: /java/installer2/src/net/oni2/aeinstaller/backend/oni/management/ToolsManager.java
===================================================================
--- /java/installer2/src/net/oni2/aeinstaller/backend/oni/management/ToolsManager.java	(revision 749)
+++ /java/installer2/src/net/oni2/aeinstaller/backend/oni/management/ToolsManager.java	(revision 749)
@@ -0,0 +1,138 @@
+package net.oni2.aeinstaller.backend.oni.management;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.TreeSet;
+
+import net.oni2.aeinstaller.backend.CaseInsensitiveFile;
+import net.oni2.aeinstaller.backend.Paths;
+import net.oni2.aeinstaller.backend.packages.Package;
+import net.oni2.platformtools.PlatformInformation;
+import net.oni2.platformtools.PlatformInformation.Platform;
+
+import org.apache.commons.io.FileUtils;
+
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.io.xml.StaxDriver;
+
+/**
+ * @author Christian Illy
+ */
+public class ToolsManager {
+	/**
+	 * @return Currently installed tools
+	 */
+	@SuppressWarnings("unchecked")
+	public static TreeSet<Integer> getInstalledTools() {
+		File installCfg = new File(Paths.getInstallerPath(),
+				"installed_tools.xml");
+		TreeSet<Integer> res = new TreeSet<Integer>();
+		try {
+			if (installCfg.exists()) {
+				FileInputStream fis = new FileInputStream(installCfg);
+				XStream xs = new XStream(new StaxDriver());
+				Object obj = xs.fromXML(fis);
+				if (obj instanceof TreeSet<?>)
+					res = (TreeSet<Integer>) obj;
+				fis.close();
+			}
+		} catch (FileNotFoundException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+		return res;
+	}
+
+	private static void writeInstalledTools(TreeSet<Integer> tools) {
+		File installCfg = new File(Paths.getInstallerPath(),
+				"installed_tools.xml");
+		try {
+			FileOutputStream fos = new FileOutputStream(installCfg);
+			XStream xs = new XStream(new StaxDriver());
+			xs.toXML(tools, fos);
+			fos.close();
+		} catch (FileNotFoundException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * @param tools
+	 *            Tools to (un)install
+	 * @param uninstall
+	 *            Uninstall tools or install?
+	 */
+	public static void installTools(TreeSet<Package> tools, boolean uninstall) {
+		TreeSet<Integer> installed = getInstalledTools();
+		for (Package m : tools) {
+			if (!uninstall || installed.contains(m.getPackageNumber())) {
+				File plain = CaseInsensitiveFile.getCaseInsensitiveFile(
+						m.getLocalPath(), "plain");
+				if (plain.exists()) {
+					if (m.hasSeparatePlatformDirs()) {
+						File plainCommon = CaseInsensitiveFile
+								.getCaseInsensitiveFile(plain, "common");
+						File plainMac = CaseInsensitiveFile
+								.getCaseInsensitiveFile(plain, "mac_only");
+						File plainWin = CaseInsensitiveFile
+								.getCaseInsensitiveFile(plain, "win_only");
+						if (plainCommon.exists())
+							copyRemoveToolsFiles(plainCommon,
+									Paths.getEditionBasePath(), uninstall);
+						if (PlatformInformation.getPlatform() == Platform.MACOS
+								&& plainMac.exists())
+							copyRemoveToolsFiles(plainMac,
+									Paths.getEditionBasePath(), uninstall);
+						else if (plainWin.exists())
+							copyRemoveToolsFiles(plainWin,
+									Paths.getEditionBasePath(), uninstall);
+					} else {
+						copyRemoveToolsFiles(plain, Paths.getEditionBasePath(),
+								uninstall);
+					}
+				}
+			}
+			if (uninstall)
+				installed.remove(m.getPackageNumber());
+			else
+				installed.add(m.getPackageNumber());
+		}
+		writeInstalledTools(installed);
+	}
+
+	private static void copyRemoveToolsFiles(File srcFolder, File targetFolder,
+			boolean remove) {
+		for (File f : srcFolder.listFiles()) {
+			try {
+				if (f.isDirectory())
+					copyRemoveToolsFiles(f,
+							CaseInsensitiveFile.getCaseInsensitiveFile(
+									targetFolder, f.getName()), remove);
+				else {
+					File targetFile = CaseInsensitiveFile
+							.getCaseInsensitiveFile(targetFolder, f.getName());
+					if (remove) {
+						if (targetFile.exists())
+							targetFile.delete();
+					} else {
+						if (!targetFile.getName().equals(f.getName()))
+							targetFile.delete();
+						FileUtils.copyFileToDirectory(f, targetFolder);
+					}
+				}
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+		if (remove)
+			if (targetFolder.list().length == 0)
+				targetFolder.delete();
+	}
+
+}
Index: va/installer2/src/net/oni2/aeinstaller/backend/packages/ECompatiblePlatform.java
===================================================================
--- /java/installer2/src/net/oni2/aeinstaller/backend/packages/ECompatiblePlatform.java	(revision 748)
+++ 	(revision )
@@ -1,19 +1,0 @@
-package net.oni2.aeinstaller.backend.packages;
-
-/**
- * @author Christian Illy
- */
-public enum ECompatiblePlatform {
-	/**
-	 * Only for Win
-	 */
-	WIN,
-	/**
-	 * Only for MacOS
-	 */
-	MACOS,
-	/**
-	 * Usable with both platforms
-	 */
-	BOTH
-}
Index: /java/installer2/src/net/oni2/aeinstaller/backend/packages/Package.java
===================================================================
--- /java/installer2/src/net/oni2/aeinstaller/backend/packages/Package.java	(revision 748)
+++ /java/installer2/src/net/oni2/aeinstaller/backend/packages/Package.java	(revision 749)
@@ -14,9 +14,8 @@
 import net.oni2.aeinstaller.backend.CaseInsensitiveFile;
 import net.oni2.aeinstaller.backend.Paths;
-import net.oni2.aeinstaller.backend.depot.DepotConfig;
-import net.oni2.aeinstaller.backend.depot.DepotManager;
-import net.oni2.aeinstaller.backend.depot.model.NodeMod;
-import net.oni2.aeinstaller.backend.depot.model.TaxonomyTerm;
-import net.oni2.aeinstaller.backend.oni.Installer;
+import net.oni2.aeinstaller.backend.oni.management.ToolsManager;
+import net.oni2.moddepot.DepotConfig;
+import net.oni2.moddepot.ECompatiblePlatform;
+import net.oni2.moddepot.model.NodeMod;
 import net.oni2.platformtools.PlatformInformation;
 import net.oni2.platformtools.PlatformInformation.Platform;
@@ -43,5 +42,5 @@
 	private int zipSize = 0;
 	private NodeMod node = null;
-	private net.oni2.aeinstaller.backend.depot.model.File file = null;
+	private net.oni2.moddepot.model.File file = null;
 
 	private File exeFile = null;
@@ -68,6 +67,6 @@
 		platform = nm.getPlatform();
 		tool = nm.isTool();
-		for (TaxonomyTerm tt : nm.getTypes()) {
-			Type t = PackageManager.getInstance().getTypeByName(tt.getName());
+		for (String nType : nm.getTypes()) {
+			Type t = PackageManager.getInstance().getTypeByName(nType);
 			types.add(t);
 			if (!tool && !isCorePackage() && isValidOnPlatform())
@@ -82,6 +81,5 @@
 				description = "<p>" + description + "</p>";
 		}
-		file = DepotManager.getInstance().getFile(
-				nm.getUploads().firstElement().getFid());
+		file = nm.getUploads().firstElement();
 		zipSize = file.getFilesize();
 
@@ -107,7 +105,9 @@
 	 */
 	public void updateLocalData() {
-		File config = CaseInsensitiveFile.getCaseInsensitiveFile(getLocalPath(), "Mod_Info.cfg");
+		File config = CaseInsensitiveFile.getCaseInsensitiveFile(
+				getLocalPath(), "Mod_Info.cfg");
 		File aeicfg = new File(getLocalPath(), "aei.cfg");
-		File plain = CaseInsensitiveFile.getCaseInsensitiveFile(getLocalPath(), "plain");
+		File plain = CaseInsensitiveFile.getCaseInsensitiveFile(getLocalPath(),
+				"plain");
 		if (config.exists()) {
 			Mod_Info mi = new Mod_Info(config, packageNumber);
@@ -230,5 +230,5 @@
 	public boolean isInstalled() {
 		if (tool)
-			return Installer.getInstalledTools().contains(packageNumber);
+			return ToolsManager.getInstalledTools().contains(packageNumber);
 		else
 			return PackageManager.getInstance().isModInstalled(this);
@@ -323,5 +323,5 @@
 	 */
 	public boolean isCorePackage() {
-		return packageNumber < DepotConfig.getCoreNumberLimit();
+		return packageNumber < DepotConfig.corePackageNumberLimit;
 	}
 
@@ -329,5 +329,5 @@
 	 * @return Get the depot file entry
 	 */
-	public net.oni2.aeinstaller.backend.depot.model.File getFile() {
+	public net.oni2.moddepot.model.File getFile() {
 		return file;
 	}
Index: /java/installer2/src/net/oni2/aeinstaller/backend/packages/PackageManager.java
===================================================================
--- /java/installer2/src/net/oni2/aeinstaller/backend/packages/PackageManager.java	(revision 748)
+++ /java/installer2/src/net/oni2/aeinstaller/backend/packages/PackageManager.java	(revision 749)
@@ -14,8 +14,9 @@
 
 import net.oni2.aeinstaller.backend.Paths;
-import net.oni2.aeinstaller.backend.depot.DepotManager;
-import net.oni2.aeinstaller.backend.depot.model.NodeMod;
-import net.oni2.aeinstaller.backend.depot.model.TaxonomyTerm;
-import net.oni2.aeinstaller.backend.oni.Installer;
+import net.oni2.moddepot.DepotManager;
+import net.oni2.moddepot.model.NodeMod;
+import net.oni2.moddepot.model.TaxonomyTerm;
+import net.oni2.aeinstaller.backend.oni.management.Installer;
+import net.oni2.aeinstaller.backend.oni.management.ToolsManager;
 
 import com.thoughtworks.xstream.XStream;
@@ -89,9 +90,9 @@
 		mods = new HashMap<Integer, Package>();
 
-		Type localType = new Type("-Local-", null);
+		Type localType = new Type("-Local-");
 		types.put("-Local-", localType);
 
 		for (TaxonomyTerm tt : DepotManager.getInstance().getTypes()) {
-			types.put(tt.getName(), new Type(tt.getName(), tt));
+			types.put(tt.getName(), new Type(tt.getName()));
 		}
 
@@ -110,5 +111,5 @@
 
 		for (NodeMod nm : DepotManager.getInstance().getModPackageNodes()) {
-			if (nm.getUploads().size() == 1 && nm.getStatus() == 1) {
+			if (nm.getUploads().size() == 1) {
 				Package m = new Package(nm);
 				if (nm.isTool())
@@ -265,5 +266,5 @@
 	public TreeSet<Package> getInstalledTools() {
 		TreeSet<Package> res = new TreeSet<Package>();
-		for (int n : Installer.getInstalledTools()) {
+		for (int n : ToolsManager.getInstalledTools()) {
 			res.add(getPackageByNumber(n));
 		}
@@ -293,5 +294,6 @@
 	 * @return Unmet dependencies
 	 */
-	public HashMap<Package, HashSet<Package>> checkDependencies(TreeSet<Package> mods) {
+	public HashMap<Package, HashSet<Package>> checkDependencies(
+			TreeSet<Package> mods) {
 		HashMap<Package, HashSet<Package>> res = new HashMap<Package, HashSet<Package>>();
 
@@ -317,5 +319,6 @@
 	 * @return Incompatible mods
 	 */
-	public HashMap<Package, HashSet<Package>> checkIncompabitilites(TreeSet<Package> mods) {
+	public HashMap<Package, HashSet<Package>> checkIncompabitilites(
+			TreeSet<Package> mods) {
 		HashMap<Package, HashSet<Package>> res = new HashMap<Package, HashSet<Package>>();
 
Index: /java/installer2/src/net/oni2/aeinstaller/backend/packages/Type.java
===================================================================
--- /java/installer2/src/net/oni2/aeinstaller/backend/packages/Type.java	(revision 748)
+++ /java/installer2/src/net/oni2/aeinstaller/backend/packages/Type.java	(revision 749)
@@ -2,6 +2,4 @@
 
 import java.util.HashSet;
-
-import net.oni2.aeinstaller.backend.depot.model.TaxonomyTerm;
 
 /**
@@ -10,6 +8,4 @@
 public class Type {
 	private String name;
-	@SuppressWarnings("unused")
-	private TaxonomyTerm depotTerm;
 
 	private HashSet<Package> entries = new HashSet<Package>();
@@ -20,10 +16,7 @@
 	 * @param name
 	 *            Name of type
-	 * @param tt
-	 *            Optional TaxTerm link
 	 */
-	public Type(String name, TaxonomyTerm tt) {
+	public Type(String name) {
 		this.name = name;
-		this.depotTerm = tt;
 	}
 
Index: /java/installer2/src/net/oni2/aeinstaller/gui/MainWin.java
===================================================================
--- /java/installer2/src/net/oni2/aeinstaller/gui/MainWin.java	(revision 748)
+++ /java/installer2/src/net/oni2/aeinstaller/gui/MainWin.java	(revision 749)
@@ -45,9 +45,10 @@
 import net.oni2.aeinstaller.backend.Paths;
 import net.oni2.aeinstaller.backend.SizeFormatter;
-import net.oni2.aeinstaller.backend.depot.DepotManager;
-import net.oni2.aeinstaller.backend.oni.InstallProgressListener;
-import net.oni2.aeinstaller.backend.oni.Installer;
 import net.oni2.aeinstaller.backend.oni.OniLauncher;
 import net.oni2.aeinstaller.backend.oni.OniSplit;
+import net.oni2.aeinstaller.backend.oni.management.Initializer;
+import net.oni2.aeinstaller.backend.oni.management.InstallProgressListener;
+import net.oni2.aeinstaller.backend.oni.management.Installer;
+import net.oni2.aeinstaller.backend.oni.management.ToolsManager;
 import net.oni2.aeinstaller.backend.packages.Package;
 import net.oni2.aeinstaller.backend.packages.PackageManager;
@@ -67,4 +68,5 @@
 import net.oni2.aeinstaller.gui.settings.SettingsDialog;
 import net.oni2.aeinstaller.gui.toolmanager.ToolManager;
+import net.oni2.moddepot.DepotManager;
 import net.oni2.platformtools.PlatformInformation;
 import net.oni2.platformtools.PlatformInformation.Platform;
@@ -205,13 +207,13 @@
 	@DoInBackground(progressMessage = "updateDepot.title", cancelable = false, indeterminateProgress = false)
 	private void execDepotUpdate(final BackgroundEvent evt) {
+		DepotManager.loadFromCacheFile(Paths.getDepotCacheFilename());
+
 		if (!SettingsManager.getInstance().isOfflineMode()
 				&& !SettingsManager.getInstance().isNoCacheUpdateMode()) {
 			long start = new Date().getTime();
 
-			try {
-				DepotManager.getInstance().updateInformation();
-			} catch (Exception e) {
-				e.printStackTrace();
-			}
+			if (DepotManager.getInstance().updateInformation())
+				DepotManager.getInstance().saveToCacheFile(
+						Paths.getDepotCacheFilename());
 
 			System.out.println("Took: " + (new Date().getTime() - start)
@@ -360,5 +362,6 @@
 				dl.setVisible(true);
 				if (dl.isFinished()) {
-					TreeSet<Integer> installed = Installer.getInstalledTools();
+					TreeSet<Integer> installed = ToolsManager
+							.getInstalledTools();
 					TreeSet<Package> tools = new TreeSet<Package>();
 					for (Package m : execUpdates)
@@ -367,5 +370,5 @@
 							tools.add(m);
 					if (tools.size() > 0) {
-						Installer.installTools(tools, false);
+						ToolsManager.installTools(tools, false);
 					}
 				}
@@ -461,5 +464,5 @@
 	@DoInBackground(progressMessage = "initializingEdition.title", cancelable = false, indeterminateProgress = false)
 	private void reglobalize(final BackgroundEvent evt) {
-		Installer.initializeEdition(new InstallProgressListener() {
+		Initializer.initializeEdition(new InstallProgressListener() {
 			@Override
 			public void installProgressUpdate(int done, int total, String step) {
@@ -580,6 +583,6 @@
 			}
 			evt.setProgressMessage(bundle.getString("coreToolsInstall.title"));
-			Installer.installTools(PackageManager.getInstance().getCoreTools(),
-					false);
+			ToolsManager.installTools(PackageManager.getInstance()
+					.getCoreTools(), false);
 		}
 	}
@@ -731,5 +734,5 @@
 
 			if (actuallyTools.size() > 0) {
-				Installer.installTools(actuallyTools, false);
+				ToolsManager.installTools(actuallyTools, false);
 			}
 		}
@@ -847,5 +850,5 @@
 	private void initialize(final BackgroundEvent evt) {
 		if (!Installer.isEditionInitialized()) {
-			Installer.initializeEdition(new InstallProgressListener() {
+			Initializer.initializeEdition(new InstallProgressListener() {
 				@Override
 				public void installProgressUpdate(int done, int total,
Index: /java/installer2/src/net/oni2/aeinstaller/gui/toolmanager/ToolManager.java
===================================================================
--- /java/installer2/src/net/oni2/aeinstaller/gui/toolmanager/ToolManager.java	(revision 748)
+++ /java/installer2/src/net/oni2/aeinstaller/gui/toolmanager/ToolManager.java	(revision 749)
@@ -18,5 +18,5 @@
 
 import net.oni2.SettingsManager;
-import net.oni2.aeinstaller.backend.oni.Installer;
+import net.oni2.aeinstaller.backend.oni.management.ToolsManager;
 import net.oni2.aeinstaller.backend.packages.Package;
 import net.oni2.aeinstaller.gui.downloadwindow.Downloader;
@@ -97,5 +97,5 @@
 				TreeSet<Package> tools = new TreeSet<Package>();
 				tools.add(selectedPackage);
-				Installer.installTools(tools, true);
+				ToolsManager.installTools(tools, true);
 			} else {
 				if (!selectedPackage.isLocalAvailable()) {
@@ -123,5 +123,5 @@
 				TreeSet<Package> tools = new TreeSet<Package>();
 				tools.add(selectedPackage);
-				Installer.installTools(tools, false);
+				ToolsManager.installTools(tools, false);
 			}
 		}
