package net.oni2.aeinstaller.backend.oni; import java.io.File; import java.io.FileFilter; import java.io.FileNotFoundException; import java.io.FilenameFilter; import java.io.IOException; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Scanner; import java.util.TreeSet; import java.util.Vector; import net.oni2.aeinstaller.backend.Paths; import net.oni2.aeinstaller.backend.Settings; import net.oni2.aeinstaller.backend.Settings.Platform; import net.oni2.aeinstaller.backend.mods.Mod; import org.apache.commons.io.FileUtils; /** * @author Christian Illy */ public class Installer { /** * @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(); } public static void install(TreeSet mods, InstallProgressListener listener) { Vector folders = new Vector(); folders.add(Paths.getVanillaOnisPath()); for (Mod m : mods) { File oni = new File(m.getLocalPath(), "oni"); if (oni.exists()) { if (m.hasSeparatePlatformDirs()) { File oniCommon = new File(oni, "common"); File oniMac = new File(oni, "mac_only"); File oniWin = new File(oni, "win_only"); if (oniCommon.exists()) folders.add(oniCommon); if (Settings.getPlatform() == Platform.MACOS && oniMac.exists()) folders.add(oniMac); else if (oniWin.exists()) folders.add(oniWin); } else { folders.add(oni); } } } // for (File f : Paths.getModsPath().listFiles()) { // File oni = new File(f, "oni"); // if (oni.exists()) // folders.add(oni); // } combineBinaryFiles(folders, listener); // TODO: bsl() } private static void combineBinaryFiles(List srcFoldersFiles, InstallProgressListener listener) { try { HashMap> levels = new HashMap>(); for (File path : srcFoldersFiles) { 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('.')); } if (levelN != null) { if (!levels.containsKey(levelN)) levels.put(levelN, new Vector()); levels.get(levelN).add(levelF); } } } int totalSteps = 0; int stepsDone = 0; for (@SuppressWarnings("unused") String s : levels.keySet()) totalSteps++; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); File logFile = new File(Paths.getInstallerPath(), "Installation.log"); PrintWriter log = null; try { log = new PrintWriter(logFile); } catch (FileNotFoundException e) { e.printStackTrace(); } Date start = new Date(); log.println("Installation of mods started at " + sdf.format(start)); log.println("Cleaning directories"); listener.installProgressUpdate(stepsDone, totalSteps, "Cleaning up directories"); createEmptyPath(Paths.getEditionGDF()); log.println("Importing levels"); for (String l : levels.keySet()) { log.println("\tLevel " + l); for (File f : levels.get(l)) { log.println("\t\t\t" + f.getPath()); } Vector res = OniSplit.packLevel(levels.get(l), new File(Paths.getEditionGDF(), l + ".dat")); if (res != null && res.size() > 0) { for (String s : res) log.println("\t\t" + s); } 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(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 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"); for (@SuppressWarnings("unused") File f : Paths.getVanillaGDF().listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.endsWith(".dat"); } })) { totalSteps++; } 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 : Paths.getVanillaGDF().listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.endsWith(".dat"); } })) { 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 Vector res = OniSplit.export(tempLevelFolder, f); if (res != null && res.size() > 0) { for (String s : res) log.println("\t\t\t" + s); } log.println("\t\tMoving files"); handleFileGlobalisation(tempLevelFolder, level0Folder, levelNumber); stepsDone++; log.println(); } log.println("Reimporting levels"); for (File f : init.listFiles()) { String levelName = f.getName(); log.println("\t" + levelName); listener.installProgressUpdate(stepsDone, totalSteps, "Creating globalized " + levelName); Vector folders = new Vector(); folders.add(f); Vector res = OniSplit.importLevel(folders, new File( Paths.getVanillaOnisPath(), levelName + ".dat")); if (res != null && res.size() > 0) { for (String s : res) log.println("\t\t" + s); } 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); // TODO: 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); } } } }