package net.oni2.aeinstaller.backend.mods; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStreamReader; import java.util.HashSet; import net.oni2.aeinstaller.backend.Paths; import net.oni2.aeinstaller.backend.Settings; import net.oni2.aeinstaller.backend.Settings.Platform; 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; /** * @author Christian Illy */ public class Mod implements Comparable { private String name = ""; private int packageNumber = 0; private HashSet types = new HashSet(); private boolean tool = false; private ECompatiblePlatform platform = null; private String version = ""; private String creator = ""; private EBSLInstallType bslInstallType = EBSLInstallType.NORMAL; private String description = ""; private double aeVersion = 0; private int zipSize = 0; private NodeMod node = null; private net.oni2.aeinstaller.backend.depot.model.File file = null; private File exeFile = null; private File iconFile = null; private String workingDir = "Base"; private HashSet incompatibilities = new HashSet(); private HashSet dependencies = new HashSet(); private HashSet unlockLevel = new HashSet(); private long localTimestamp = 0; /** * Create a new Mod entry from a given Mod-Node * * @param nm * Mod-Node */ public Mod(NodeMod nm) { node = nm; name = nm.getTitle(); packageNumber = nm.getPackageNumber(); platform = nm.getPlatform(); tool = nm.isTool(); for (TaxonomyTerm tt : nm.getTypes()) { Type t = ModManager.getInstance().getTypeByName(tt.getName()); types.add(t); if (!tool && !isMandatoryMod() && isValidOnPlatform()) t.addEntry(this); } version = nm.getVersion(); creator = nm.getCreator(); if (nm.getBody() != null) description = nm.getBody().getSafe_value(); file = DepotManager.getInstance().getFile( nm.getUploads().firstElement().getFid()); zipSize = file.getFilesize(); if (isLocalAvailable()) updateLocalData(); } /** * Update information for local package existence */ public void updateLocalData() { File config = new File(getLocalPath(), "Mod_Info.cfg"); File aeicfg = new File(getLocalPath(), "aei.cfg"); File plain = new File(getLocalPath(), "plain"); if (config.exists()) { try { FileInputStream fstream = new FileInputStream(config); InputStreamReader isr = new InputStreamReader(fstream); BufferedReader br = new BufferedReader(isr); String strLine; while ((strLine = br.readLine()) != null) { if (strLine.indexOf("->") < 1) continue; if (strLine.indexOf("//") >= 0) strLine = strLine.substring(0, strLine.indexOf("//")); String[] split = strLine.split("->", 2); String sName = split[0].trim(); String sVal = split[1].trim(); if (sName.equalsIgnoreCase("AEInstallVersion")) { aeVersion = Double.parseDouble(sVal); } else if (sName.equalsIgnoreCase("NameOfMod")) { if (node == null) name = sVal; } else if (sName.equalsIgnoreCase("Creator")) { if (node == null) creator = sVal; } else if (sName.equalsIgnoreCase("HasBsl")) { if (sVal.equalsIgnoreCase("addon")) bslInstallType = EBSLInstallType.ADDON; } else if (sName.equalsIgnoreCase("ModVersion")) { if (node == null) version = sVal; } else if (sName.equalsIgnoreCase("Readme")) { if (node == null) description = sVal.replaceAll("\\\\n", "
"); } else if (sName.equalsIgnoreCase("DependsOn")) { String[] depsS = sVal.split(","); for (String s : depsS) { try { int dep = Integer.parseInt(s); dependencies.add(dep); } catch (NumberFormatException e) { System.err .format("Mod %05d does contain a non-number dependency: '%s'\n", packageNumber, s); } } } else if (sName.equalsIgnoreCase("IncompatibleWith")) { String[] confS = sVal.split(","); for (String s : confS) { try { int conf = Integer.parseInt(s); incompatibilities.add(conf); } catch (NumberFormatException e) { System.err .format("Mod %05d does contain a non-number incompatibility: '%s'\n", packageNumber, s); } } } else if (sName.equalsIgnoreCase("UnlockLevel")) { String[] levelsS = sVal.split(","); for (String s : levelsS) { try { int level = Integer.parseInt(s); unlockLevel.add(level); } catch (NumberFormatException e) { System.err .format("Mod %05d does contain a non-number UnlockLevel value: '%s'\n", packageNumber, s); } } } else if (sName.equalsIgnoreCase("ExeName")) { exeFile = new File(Paths.getEditionBasePath(), sVal); } else if (sName.equalsIgnoreCase("WorkingDir")) { workingDir = sVal; } else if (sName.equalsIgnoreCase("IconName")) { iconFile = new File(Paths.getEditionBasePath(), sVal); } } isr.close(); } catch (FileNotFoundException e) { } catch (IOException e) { e.printStackTrace(); } } else { System.err.println("No config found for mod folder: " + getLocalPath().getPath()); } if (aeicfg.exists()) { try { FileInputStream fstream = new FileInputStream(aeicfg); InputStreamReader isr = new InputStreamReader(fstream); BufferedReader br = new BufferedReader(isr); String strLine; while ((strLine = br.readLine()) != null) { if (strLine.indexOf("->") < 1) continue; if (strLine.indexOf("//") >= 0) strLine = strLine.substring(0, strLine.indexOf("//")); String[] split = strLine.split("->", 2); String sName = split[0].trim(); String sVal = split[1].trim(); if (sName.equalsIgnoreCase("Timestamp")) { localTimestamp = Long.parseLong(sVal); } } isr.close(); } catch (FileNotFoundException e) { } catch (IOException e) { e.printStackTrace(); } } if (node == null) tool = plain.exists(); } /** * Create a new Mod entry from the given local mod folder * * @param folder * Mod folder with Mod_Info.cfg */ public Mod(File folder) { packageNumber = Integer.parseInt(folder.getName().substring(0, 5)); updateLocalData(); platform = ECompatiblePlatform.BOTH; } /** * @return has separate paths for win/mac/common or not */ public boolean hasSeparatePlatformDirs() { return aeVersion >= 2; } private String getSanitizedPathName() { return name.replaceAll("[^a-zA-Z0-9_.-]", "_"); } /** * @return Path to local mod folder */ public File getLocalPath() { final String folderStart = String.format("%05d", packageNumber); if (Paths.getModsPath().exists()) { for (File f : Paths.getModsPath().listFiles(new FilenameFilter() { @Override public boolean accept(File d, String fn) { return fn.startsWith(folderStart); } })) { return f; } } return new File(Paths.getModsPath(), folderStart + getSanitizedPathName()); } /** * @return Is there a newer version on the depot? */ public boolean isNewerAvailable() { if (file != null) return file.getTimestamp() > localTimestamp; else return false; } /** * @return Mod exists within mods folder */ public boolean isLocalAvailable() { return getLocalPath().exists(); } /** * @return Is mod installed? */ public boolean isInstalled() { return ModManager.getInstance().isModInstalled(this); } /** * @return Name of mod */ public String getName() { return name; } /** * @return the package number */ public int getPackageNumber() { return packageNumber; } /** * @return the package number as 5 digit string */ public String getPackageNumberString() { return String.format("%05d", packageNumber); } /** * @return Types of mod */ public HashSet getTypes() { return types; } /** * @return Is this mod actually a tool? */ public boolean isTool() { return tool; } /** * @return Compatible platforms */ public ECompatiblePlatform getPlatform() { return platform; } /** * @return Version of mod */ public String getVersion() { return version; } /** * @return Creator of mod */ public String getCreator() { return creator; } /** * @return Installation type of BSL files */ public EBSLInstallType getBSLInstallType() { return bslInstallType; } /** * @return Description of mod */ public String getDescription() { return description; } /** * @return Size of Zip file on Depot */ public int getZipSize() { return zipSize; } /** * @return Is a mod that is always installed? */ public boolean isMandatoryMod() { return packageNumber < DepotConfig.getMandatoryLimit(); } /** * @return Get the depot file entry */ public net.oni2.aeinstaller.backend.depot.model.File getFile() { return file; } @Override public String toString() { return name; } /** * @return the incompabitilities */ public HashSet getIncompabitilities() { return incompatibilities; } /** * @return the dependencies */ public HashSet getDependencies() { return dependencies; } /** * @return the levels this mod will unlock */ public HashSet getUnlockLevels() { return unlockLevel; } /** * @return Executable name of this tool */ public File getExeFile() { return exeFile; } /** * @return Icon file of this tool */ public File getIconFile() { return iconFile; } /** * @return Working directory of this tool */ public File getWorkingDir() { if (workingDir.equalsIgnoreCase("Exe")) { if (exeFile != null) return exeFile.getParentFile(); else return Paths.getEditionGDF(); } else if (workingDir.equalsIgnoreCase("GDF")) return Paths.getEditionGDF(); else return Paths.getEditionBasePath(); } /** * @return Is this mod valid on the running platform? */ public boolean isValidOnPlatform() { switch (platform) { case BOTH: return true; case MACOS: return (Settings.getPlatform() == Platform.MACOS); case WIN: return (Settings.getPlatform() == Platform.WIN) || (Settings.getPlatform() == Platform.LINUX); } return false; } @Override public int compareTo(Mod o) { return getPackageNumber() - o.getPackageNumber(); } }