/// <summary> /// Extracts an archive into the given folder. (Throws exceptions) /// </summary> /// <param name="archivePath"></param> /// <param name="destinationPath"></param> /// <param name="updateProgress"></param> public static void ExtractArchive(string archivePath, string destinationPath, Action <Progress> ProgressChanged = null) { // TODO: Make a ModUtilities.cs? string filePath = Path.GetFullPath(archivePath); string fileName = Path.GetFileName(filePath); string fileExtension = Path.GetExtension(filePath); Directory.CreateDirectory(destinationPath); ProgressChanged?.Invoke(Progress.Indetermined($"Extracting {fileName} ...")); /* * Depending on file extention: */ // Use Archive2.exe to extract: if (fileExtension.ToLower() == ".ba2") { Archive2.Extract(filePath, destinationPath); } // Use 7-Zip (7za.exe) to extract: else if (Utils.SevenZipSupportedFileTypes.Contains(fileExtension.ToLower())) { Utils.ExtractArchive(filePath, destinationPath); } // Not supported: else { throw new NotSupportedException($"File type not supported: {fileExtension}"); } ProgressChanged?.Invoke(Progress.Done("Extracting finished.")); }
/// <summary> /// Loads and converts legacy managed mods to the new format. /// It adds them to an already existing ManagedMods object. /// </summary> public static void ConvertLegacy(ManagedMods mods, GameEdition edition, Action <Progress> ProgressChanged = null) { Directory.CreateDirectory(Path.Combine(mods.GamePath, "FrozenData")); XDocument xmlDoc = XDocument.Load(Path.Combine(mods.ModsPath, "manifest.xml")); // I added a doNotImport="true" attribute, so I can check, whether the manifest.xml has only been generated for backwards-compatibility. // If it exists, we can just skip the import: if (xmlDoc.Root.Attribute("doNotImport") != null) { ProgressChanged?.Invoke(Progress.Aborted("Import skipped.")); return; } // Make backups: File.Copy(Path.Combine(mods.ModsPath, "manifest.xml"), Path.Combine(mods.ModsPath, "manifest.old.xml"), true); if (File.Exists(Path.Combine(mods.ModsPath, "managed.xml"))) { File.Copy(Path.Combine(mods.ModsPath, "managed.xml"), Path.Combine(mods.ModsPath, "managed.old.xml"), true); } // Converting the legacy list will completely erase the current mod list: mods.Mods.Clear(); /* * Converting: */ int modCount = xmlDoc.Descendants("Mod").Count(); int modIndex = 0; foreach (XElement xmlMod in xmlDoc.Descendants("Mod")) { modIndex++; if (xmlMod.Attribute("modFolder") == null) { continue; } ManagedMod mod = new ManagedMod(mods.GamePath); string managedFolderName = xmlMod.Attribute("modFolder").Value; string managedFolderPath = Path.Combine(mods.ModsPath, managedFolderName); string frozenArchivePath = Path.Combine(mods.ModsPath, managedFolderName, "frozen.ba2"); bool isFrozen = File.Exists(frozenArchivePath); mod.ManagedFolderName = managedFolderName; if (xmlMod.Attribute("title") != null) { mod.Title = xmlMod.Attribute("title").Value; } string progressTitle = $"Converting \"{mod.Title}\" ({modIndex} of {modCount})"; float progressPercentage = (float)modIndex / (float)modCount; // In case the mod was "frozen" before, // we'll need to move the *.ba2 archive into the FrozenData folder and then extract it. if (isFrozen) { ProgressChanged?.Invoke(Progress.Ongoing($"{progressTitle}: Extracting *.ba2 archive...", progressPercentage)); File.Move(frozenArchivePath, mod.FrozenArchivePath); Archive2.Extract(mod.FrozenArchivePath, managedFolderPath); mod.Frozen = true; mod.Freeze = true; } // OBSOLETE: We need to rename the old folder to fit with the new format. /*if (Directory.Exists(managedFolderPath)) * { * ProgressChanged?.Invoke(Progress.Ongoing($"{progressTitle}: Moving managed folder...", progressPercentage)); * if (Directory.Exists(mod.ManagedFolderPath)) * Directory.Delete(mod.ManagedFolderPath, true); * Directory.Move(managedFolderPath, mod.ManagedFolderPath); * }*/ ProgressChanged?.Invoke(Progress.Ongoing($"{progressTitle}: Parsing XML...", progressPercentage)); if (xmlMod.Attribute("url") != null) { mod.URL = xmlMod.Attribute("url").Value; } if (xmlMod.Attribute("version") != null) { mod.Version = xmlMod.Attribute("version").Value; } if (xmlMod.Attribute("enabled") != null) { try { mod.Deployed = XmlConvert.ToBoolean(xmlMod.Attribute("enabled").Value); } catch { mod.Deployed = false; } mod.Enabled = mod.Deployed; } if (xmlMod.Attribute("installType") != null) { switch (xmlMod.Attribute("installType").Value) { case "Loose": mod.PreviousMethod = ManagedMod.DeploymentMethod.LooseFiles; break; case "SeparateBA2": mod.PreviousMethod = ManagedMod.DeploymentMethod.SeparateBA2; break; case "BA2Archive": // Backward compatibility case "BundledBA2": case "BundledBA2Textures": // Backward compatibility default: mod.PreviousMethod = ManagedMod.DeploymentMethod.BundledBA2; break; } mod.Method = mod.PreviousMethod; } if (xmlMod.Attribute("format") != null) { switch (xmlMod.Attribute("format").Value) { case "General": mod.CurrentFormat = ManagedMod.ArchiveFormat.General; break; case "DDS": // Backward compatibility case "Textures": mod.CurrentFormat = ManagedMod.ArchiveFormat.Textures; break; case "Auto": default: mod.CurrentFormat = ManagedMod.ArchiveFormat.Auto; break; } mod.Format = mod.CurrentFormat; } if (xmlMod.Attribute("compression") != null) { switch (xmlMod.Attribute("compression").Value) { case "Default": // Backward compatibility case "Compressed": mod.CurrentCompression = ManagedMod.ArchiveCompression.Compressed; break; case "None": // Backward compatibility case "Uncompressed": mod.CurrentCompression = ManagedMod.ArchiveCompression.Uncompressed; break; case "Auto": default: mod.CurrentCompression = ManagedMod.ArchiveCompression.Auto; break; } mod.Compression = mod.CurrentCompression; } if (xmlMod.Attribute("archiveName") != null) { mod.CurrentArchiveName = xmlMod.Attribute("archiveName").Value; mod.ArchiveName = mod.CurrentArchiveName; } if (xmlMod.Attribute("root") != null) { mod.CurrentRootFolder = xmlMod.Attribute("root").Value; mod.RootFolder = mod.CurrentRootFolder; foreach (XElement xmlFile in xmlMod.Descendants("File")) { if (xmlFile.Attribute("path") != null) { mod.LooseFiles.Add(xmlFile.Attribute("path").Value); } } } /*if (xmlMod.Attribute("frozen") != null) * { * frozen = XmlConvert.ToBoolean(xmlMod.Attribute("frozen").Value); * }*/ mods.Add(mod); } // Legacy resource list: if (IniFiles.Config.GetBool("Preferences", "bMultipleGameEditionsUsed", false)) { string backedUpList = IniFiles.Config.GetString("Mods", $"sResourceIndexFileList{edition}", ""); string actualList = IniFiles.F76Custom.GetString("Archive", "sResourceIndexFileList", ""); if (backedUpList != "") { mods.Resources.ReplaceRange(ResourceList.FromString(backedUpList)); } else if (actualList != "") { mods.Resources.ReplaceRange(ResourceList.FromString(actualList)); } } ProgressChanged?.Invoke(Progress.Ongoing("Saving XML...", 1f)); mods.Save(); ProgressChanged?.Invoke(Progress.Done("Legacy mods imported.")); }