public static void Freeze(ManagedMod mod) { // TODO: Remove connection to ManagedMods // Only freeze if not already frozen: if (mod.Frozen && File.Exists(mod.FrozenArchivePath)) { // TODO: ModActions.Freeze: Should the mod get "refrozen"? //ManagedMods.Instance.logFile.WriteLine($"Cannot freeze a mod ('{mod.Title}') that is already frozen.\n"); return; } Directory.CreateDirectory(mod.FrozenDataPath); // Getting preset: Archive2.Preset preset = ModHelpers.GetArchive2Preset(mod); ModDeployment.LogFile.WriteLine($" Freezing mod '{mod.Title}'..."); ModDeployment.LogFile.WriteLine($" Format: {preset.format}"); ModDeployment.LogFile.WriteLine($" Compression: {preset.compression}"); ModDeployment.LogFile.WriteLine($" Destination: FrozenData\\{mod.FrozenArchiveName}"); // Create archive: Archive2.Create(mod.FrozenArchivePath, mod.ManagedFolderPath, preset); // Change DiskState and save: mod.Frozen = true; mod.FrozenCompression = mod.Compression; mod.FrozenFormat = mod.Format; }
public static void Create(String ba2Archive, String folder, Archive2.Compression compression, Archive2.Format format) { if (!Directory.Exists(folder)) { return; } String compressionStr = Enum.GetName(typeof(Archive2.Compression), (int)compression); String formatStr = Enum.GetName(typeof(Archive2.Format), (int)format); folder = Path.GetFullPath(folder); Archive2.Call($"\"{folder}\" -create=\"{ba2Archive}\" -compression={compressionStr} -format={formatStr} -root=\"{folder}\" -tempFiles -quiet"); }
/// <summary> /// Used in the deployment chain to pack each bundled temporary folder to an archive. /// </summary> private static void PackBundledArchives(ResourceList resources, DeployArchiveList archives, bool freezeArchives) { // For each archive... foreach (DeployArchive archive in archives.Reverse()) { // ... if needed ... if (archive.Count > 0 && !Utils.IsDirectoryEmpty(archive.TempPath)) { // ... pack the temporary folder to an archive ... if (freezeArchives) { LogFile.WriteLine($" Freezing archive '{archive.ArchiveName}'"); // either freeze to FrozenData and then copy to Data: Archive2.Create(archive.GetFrozenArchivePath(), archive.TempPath, archive.Compression, archive.Format); if (Configuration.bUseHardlinks) { Utils.CreateHardLink(archive.GetFrozenArchivePath(), archive.GetArchivePath(), true); } else { File.Copy(archive.GetFrozenArchivePath(), archive.GetArchivePath(), true); } } else { LogFile.WriteLine($" Creating archive '{archive.ArchiveName}'"); // or create directly in Data: Archive2.Create(archive.GetArchivePath(), archive.TempPath, archive.Compression, archive.Format); } // ... and add it to the resource list. resources.Insert(0, archive.ArchiveName); } } // Clean up after we're finished. LogFile.WriteLine($" Deleting temporary folder..."); archives.DeleteTempFolder(); }
/// <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> /// Used in the deployment chain to deploy a single mod with the SeparateBA2 method. /// Freezes a mod if necessary. /// </summary> private static void DeploySeparateArchive(ManagedMod mod, ResourceList resources) { LogFile.WriteLine($" Installing mod '{mod.Title}' as SeparateBA2"); // If mod is supposed to be deployed frozen... if (mod.Freeze) { // ... freeze if necessary ... if (!mod.Frozen) { //LogFile.WriteLine($" Freezing mod..."); ModActions.Freeze(mod); } LogFile.WriteLine($" Copying frozen archive..."); // ... and copy it to the Data folder. if (Configuration.bUseHardlinks) { Utils.CreateHardLink( mod.FrozenArchivePath, mod.ArchivePath, true); } else { File.Copy( mod.FrozenArchivePath, mod.ArchivePath, true); } } // If mod isn't supposed to be deployed frozen... else { // ... unfreeze mod if needed ... if (mod.Frozen) { LogFile.WriteLine($" Unfreezing mod..."); ModActions.Unfreeze(mod); } // Getting preset: Archive2.Preset preset = ModHelpers.GetArchive2Preset(mod); LogFile.WriteLine($" Creating new archive..."); LogFile.WriteLine($" Format: {preset.format}"); LogFile.WriteLine($" Compression: {preset.compression}"); // ... and create a new archive. Archive2.Create( mod.ArchivePath, mod.ManagedFolderPath, preset); } // Finally, update the disk state ... mod.CurrentArchiveName = mod.ArchiveName; mod.CurrentCompression = mod.Frozen ? mod.FrozenCompression : mod.Compression; mod.CurrentFormat = mod.Frozen ? mod.FrozenFormat : mod.Format; mod.Deployed = true; mod.PreviousMethod = ManagedMod.DeploymentMethod.SeparateBA2; // ... and add the archive to the resource list. resources.Add(mod.ArchiveName); LogFile.WriteLine($" Installed."); }
public static void Create(String ba2Archive, String folder, Archive2.Preset preset) { Archive2.Create(ba2Archive, folder, preset.compression, preset.format); }
public static void Create(String ba2Archive, String folder) { Archive2.Create(ba2Archive, folder, Archive2.Compression.Default, Archive2.Format.General); }
public static void Explore() { Archive2.CallParallel(""); }
public static void Explore(String ba2Archive) { Archive2.CallParallel($"\"{ba2Archive}\""); }
public static void Extract(String ba2Archive, String outputFolder) { Archive2.Call($"\"{ba2Archive}\" -extract=\"{outputFolder}\" -quiet"); }
/// <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.")); }