public static bool InstallMod(string ModFile) { if (!ModManager.ValidInstallPath) return false; // no valid install specified if (!File.Exists(GameArchivePath)) return false; // extract existing DAT file ExtractGameArchive(); // import existing DAT xml QarFile qarXml = new QarFile(); qarXml.LoadFromFile(GameArchiveXmlPath); // extract mod files to temp folder if (Directory.Exists("_temp")) Directory.Delete("_temp", true); FastZip unzipper = new FastZip(); unzipper.ExtractZip(ModFile, "_temp", "(.*?)"); // load mod metadata ModEntry modMetadata = new ModEntry(); modMetadata.ReadFromFile("_temp\\metadata.xml"); File.Delete("_temp\\metadata.xml"); // check for fpk merges List<ModFpkEntry> installedFpkFiles = new List<ModFpkEntry>(); foreach (QarEntry gzsQar in qarXml.QarEntries) { string qarExt = gzsQar.FilePath.Substring(gzsQar.FilePath.LastIndexOf(".") + 1).ToLower(); if (qarExt == "fpk" || qarExt == "fpkd") { // extract FPK and add files to list string fpkFile = GameArchiveDir + "\\" + gzsQar.FilePath; string fpkDir = fpkFile.Replace(".", "_"); GzsTool.GzsTool.Run(fpkFile); List<string> fpkFiles = Directory.GetFiles(fpkDir, "*.*", SearchOption.AllDirectories).ToList(); foreach (string file in fpkFiles) { string fpkFilePath = fpkFile.Substring(GameArchiveDir.Length); fpkFilePath = fpkFilePath.Replace("\\", "/"); string fpkPath = file.Substring(file.LastIndexOf("Assets\\")); fpkPath = "/" + fpkPath.Replace("\\", "/"); installedFpkFiles.Add(new ModFpkEntry() { FilePath = fpkFilePath, FpkFile = fpkPath }); } } } // compare lists and build merge fpk list List<string> mergeFpks = new List<string>(); foreach (ModFpkEntry installedFpk in installedFpkFiles) { foreach (ModEntry mod in GetInstalledMods()) { if (mod.ModFpkEntries.Find(entry => entry.FpkFile == installedFpk.FpkFile) != null) // if the mod has an fpk that should be merged with an installed fpk { if (!mergeFpks.Contains(installedFpk.FpkFile)) { mergeFpks.Add(installedFpk.FpkFile); } } } } if (mergeFpks.Count > 0) { // merge fpks foreach (string fpkFile in mergeFpks) { string fpkPath = Tools.ToQarPath(fpkFile); string gameFpkPath = GameArchiveDir + fpkPath; string gameFpkDir = GameArchiveDir + "\\master\\0\\01\\" + fpkPath.Replace(".", "_"); string modFpkPath = "_temp\\" + fpkPath; string modFpkDir = "_temp\\" + fpkPath.Replace(".", "_"); GzsTool.GzsTool.Run(gameFpkPath); GzsTool.GzsTool.Run(modFpkPath); // load existing xml data FpkFile fpkXml = new FpkFile(); fpkXml.LoadFromFile(gameFpkPath + ".xml"); // generate list of files to move and add to xml List<string> filesToMove = new List<string>(); foreach (ModFpkEntry file in modMetadata.ModFpkEntries.FindAll(entry => entry.FpkFile == fpkFile)) { filesToMove.Add(file.FilePath.Replace("/", "\\")); if (fpkXml.FpkEntries.Count(entry => entry.FilePath == file.FilePath) == 0) { // insert new fpk entries as required fpkXml.FpkEntries.Add(new FpkEntry() { FilePath = fpkFile }); } } // create directories and move files foreach (string file in filesToMove) { string fileDir = (gameFpkDir + file).Substring(0, (gameFpkDir + file).LastIndexOf("\\")); if (!Directory.Exists(fileDir)) { Directory.CreateDirectory(fileDir); } File.Copy(modFpkDir + file, gameFpkDir + file, true); } fpkXml.WriteToFile(gameFpkPath + ".xml"); GzsTool.GzsTool.Run(gameFpkPath + ".xml"); } } // copy files for new DAT foreach (ModQarEntry modQarFile in modMetadata.ModQarEntries) { string fileName = "/" + modQarFile.FilePath.Replace("\\", "/"); string fileDir = (GameArchiveDir + modQarFile.FilePath.Replace("/", "\\")).Substring(0, (GameArchiveDir + modQarFile.FilePath).LastIndexOf("/")); // if file is not already in QAR, add it if (qarXml.QarEntries.Count(entry => entry.FilePath == modQarFile.FilePath) == 0) { qarXml.QarEntries.Add(new QarEntry() { FilePath = modQarFile.FilePath, Compressed = modQarFile.Compressed, Hash = modQarFile.Hash }); } // copy all files that weren't merged FPKS if (!mergeFpks.Contains(fileName)) { if (!Directory.Exists(fileDir)) { Directory.CreateDirectory(fileDir); } File.Copy("_temp\\" + modQarFile.FilePath.Replace("/", "\\"), ModManager.GameArchiveDir + modQarFile.FilePath.Replace("/", "\\"), true); } } // build XML for new DAT qarXml.WriteToFile(GameArchiveXmlPath); // build new DAT GzsTool.GzsTool.Run(GameArchiveXmlPath); // remove temp files Directory.Delete("_temp", true); Directory.Delete(GameArchiveDir, true); File.Delete(GameArchiveXmlPath); UpdateDatHash(); return true; }
// gets information about the existing 01.dat archive internal static GameData RebuildGameData(bool copyBackup = false) { if (Directory.Exists(GameArchiveDir)) Directory.Delete(GameArchiveDir, true); ExtractGameArchive(); if (!Directory.Exists(GameArchiveDir)) return null; GameData buildData = new GameData(); // Extract game archive and load data QarFile gameQarXml = new QarFile(); gameQarXml.LoadFromFile(GameArchiveXmlPath); // Load currently installed mods Settings oSet = new Settings(); oSet.LoadSettings(); foreach (QarEntry gameQarEntry in gameQarXml.QarEntries) { buildData.GameQarEntries.Add(new ModQarEntry() { FilePath = gameQarEntry.FilePath, Compressed = gameQarEntry.Compressed, Hash = gameQarEntry.Hash }); } buildData.GameFpkEntries = BuildFpkList(GameArchiveDir); // recurse through all installed mods foreach (ModEntry mod in oSet.ModEntries) { // check all files in mod against qar archive foreach (ModFpkEntry modFpkFile in mod.ModFpkEntries) { buildData.GameFpkEntries.RemoveAll(entry => entry.FilePath == modFpkFile.FilePath && entry.FpkFile == modFpkFile.FpkFile); } foreach (ModQarEntry modQarFile in mod.ModQarEntries) { buildData.GameQarEntries.RemoveAll(entry => entry.FilePath == modQarFile.FilePath); } } if(copyBackup) { foreach (ModFpkEntry fpkEntry in buildData.GameFpkEntries) { string fpkDir = Tools.ToWinPath(fpkEntry.FpkFile.Replace(".", "_")); backupMan.AddFile(GameArchiveDir + fpkDir + Tools.ToWinPath(fpkEntry.FilePath), fpkEntry.FilePath, fpkEntry.FpkFile); } foreach (ModQarEntry qarEntry in buildData.GameQarEntries) { backupMan.AddFile(GameArchiveDir + Tools.ToWinPath(qarEntry.FilePath), Tools.ToQarPath(qarEntry.FilePath)); } backupMan.Save(); } DeleteGameArchive(); return buildData; }
internal static void CleanupModSettings() { // Load current settings Settings oSet = new Settings(); oSet.LoadSettings(); // Unpack game archive ExtractGameArchive(); // Load archive data QarFile gameQar = new QarFile(); gameQar.LoadFromFile(GameArchiveXmlPath); // recurse through all installed mods foreach (ModEntry mod in oSet.ModEntries) { List<string> remQar = new List<string>(); // list of files to remove foreach (ModQarEntry modQarFile in mod.ModQarEntries) // check all mod files { if (!File.Exists(GameArchiveDir + Tools.ToWinPath(modQarFile.FilePath))) { // if the file doesn't exist, it will be removed remQar.Add(modQarFile.FilePath); } } foreach (string remFile in remQar) { mod.ModQarEntries.RemoveAll(entry => entry.FilePath == remFile); // remove files from db mod.ModFpkEntries.RemoveAll(entry => entry.FpkFile == remFile); // fpks from db } } // remove empty mods oSet.ModEntries.RemoveAll(entry => entry.ModQarEntries.Count == 0 && entry.ModFpkEntries.Count == 0); oSet.SaveSettings(); DeleteGameArchive(); }
public static bool UninstallMod(ModEntry mod) { // extract 01.dat if (!ModManager.ValidInstallPath) return false; // no valid install specified if (!File.Exists(GameArchivePath)) return false; ExtractGameArchive(); // load xml data QarFile datXml = new QarFile(); datXml.LoadFromFile(GameArchiveXmlPath); // check for fpks List<string> modFpks = new List<string>(); foreach (ModFpkEntry modFpkFile in mod.ModFpkEntries) { if (datXml.QarEntries.Count(entry => entry.FilePath == modFpkFile.FpkFile) > 0 && !modFpks.Contains(modFpkFile.FpkFile)) { modFpks.Add(modFpkFile.FpkFile); } } // do the fpks thing // unpack fpk foreach (string fpkFile in modFpks) { // check if fpk file exists in game data if (File.Exists(GameArchiveDir + fpkFile.Replace("/", "\\"))) { // extract fpk GzsTool.GzsTool.Run(GameArchiveDir + Tools.ToWinPath(fpkFile)); string fpkDir = GameArchiveDir + Tools.ToWinPath(fpkFile.Replace(".", "_")); FpkFile fpkXml = new FpkFile(); fpkXml.LoadFromFile(GameArchiveDir + fpkFile + ".xml"); // check if any files left in fpk List<FpkEntry> fpkFiles = fpkXml.FpkEntries.ToList(); foreach (FpkEntry fpkSubFile in fpkXml.FpkEntries) { fpkFiles.RemoveAll(entry => entry.FilePath == fpkSubFile.FilePath); } // if not, remove it if (fpkFiles.Count == 0) { // delete fpk from dat XML datXml.QarEntries.RemoveAll(entry => entry.FilePath == fpkFile); } } } // remove mod files from xml foreach (ModQarEntry modQEntry in mod.ModQarEntries) { // delete files, fpks that were de-merged will be ignored if (!modFpks.Contains(modQEntry.FilePath)) { datXml.QarEntries.RemoveAll(entry => entry.FilePath == modQEntry.FilePath); } } // rebuild 01.dat datXml.WriteToFile(GameArchiveXmlPath); GzsTool.GzsTool.Run(GameArchiveXmlPath); DeleteGameArchive(); UpdateDatHash(); return true; }
// gets information about the existing 01.dat archive internal static GameData RebuildGameData() { if (Directory.Exists(GameArchiveDir)) Directory.Delete(GameArchiveDir, true); ExtractGameArchive(); if (!Directory.Exists(GameArchiveDir)) return null; GameData buildData = new GameData(); // Extract game archive and load data QarFile gameQarXml = new QarFile(); gameQarXml.LoadFromFile(GameArchiveXmlPath); // Load currently installed mods Settings oSet = new Settings(); oSet.LoadSettings(); foreach (QarEntry gameQarEntry in gameQarXml.QarEntries) { buildData.GameQarEntries.Add(new ModQarEntry() { FilePath = gameQarEntry.FilePath, Compressed = gameQarEntry.Compressed, Hash = gameQarEntry.Hash }); } buildData.GameFpkEntries = BuildFpkList(GameArchiveDir); // recurse through all installed mods foreach (ModEntry mod in oSet.ModEntries) { // check all files in mod against qar archive foreach (ModFpkEntry modFpkFile in mod.ModFpkEntries) { buildData.GameFpkEntries.RemoveAll(entry => entry.FilePath == modFpkFile.FilePath && entry.FpkFile == modFpkFile.FpkFile); } foreach (ModQarEntry modQarFile in mod.ModQarEntries) { buildData.GameQarEntries.RemoveAll(entry => entry.FilePath == modQarFile.FilePath); } } Directory.Delete(GameArchiveDir, true); File.Delete(GameArchiveXmlPath); return buildData; }
private void buttonBuild_Click(object sender, EventArgs e) { SaveFileDialog saveMod = new SaveFileDialog(); saveMod.Filter = "MGSV Mod|*.mgsv"; DialogResult saveResult = saveMod.ShowDialog(); if (saveResult != DialogResult.OK) return; string modPath = textModPath.Text; // delete existing temp directory if (Directory.Exists("_temp")) Directory.Delete("_temp", true); // create new temp fs and QAR file XML Directory.CreateDirectory("_temp\\makebite"); QarFile makeQar = new QarFile(); makeQar.Flags = 3150048; makeQar.Name = "makebite.dat"; makeQar.QarEntries = new List<QarEntry>(); // do files foreach (string modFile in Directory.GetFiles(modPath, "*.*", SearchOption.AllDirectories)) { if (!Hashing.ValidFileExtension(modFile.Substring(modPath.Length))) continue; string subDir = modFile.Substring(0, modFile.LastIndexOf("\\")); // the subdirectory for XML output subDir = subDir.Substring(modPath.Length); if (!Directory.Exists("_temp\\makebite" + subDir)) Directory.CreateDirectory("_temp\\makebite" + subDir); // create file structure File.Copy(modFile, "_temp\\makebite" + modFile.Substring(modPath.Length), true); makeQar.QarEntries.Add(new QarEntry() { FilePath = modFile.Substring(modPath.Length + 1) }); // add to xml } // write xml makeQar.WriteToFile("_temp\\makebite.dat.xml"); // create metadata ModEntry modMetadata = new ModEntry(); modMetadata.Name = textModName.Text; modMetadata.Version = textModVersion.Text; modMetadata.Author = textModAuthor.Text; modMetadata.Website = textModWebsite.Text; modMetadata.Description = textModDescription.Text; modMetadata.ModQarEntries = new List<ModQarEntry>(); modMetadata.ModFpkEntries = new List<ModFpkEntry>(); // create file data foreach (QarEntry newQarEntry in makeQar.QarEntries) { modMetadata.ModQarEntries.Add(new ModQarEntry() { FilePath = Hashing.DenormalizeFilePath(newQarEntry.FilePath), Compressed = newQarEntry.Compressed, Hash = newQarEntry.Hash }); string fileExt = newQarEntry.FilePath.Substring(newQarEntry.FilePath.LastIndexOf(".") + 1).ToLower(); if (fileExt == "fpk" || fileExt == "fpkd") { newQarEntry.Compressed = true; // decompress fpk files and create metadata string fpkDir = "_temp\\makebite\\" + newQarEntry.FilePath.Replace(".", "_"); SnakeBite.GzsTool.GzsTool.Run("_temp\\makebite\\" + newQarEntry.FilePath); foreach (string fpkSubFile in Directory.GetFiles(fpkDir, "*.*", SearchOption.AllDirectories)) { modMetadata.ModFpkEntries.Add(new ModFpkEntry() { FilePath = fpkSubFile.Substring(fpkSubFile.LastIndexOf("\\Assets")).Replace("\\", "/"), FpkFile = "/" + newQarEntry.FilePath.Replace("\\", "/") } ); } Directory.Delete(fpkDir, true); File.Delete("_temp\\makebite\\" + newQarEntry.FilePath + ".xml"); } } modMetadata.SaveToFile("_temp\\makebite\\metadata.xml"); // compress to file FastZip zipper = new FastZip(); zipper.CreateZip(saveMod.FileName, "_temp\\makebite", true, "(.*?)"); Directory.Delete("_temp", true); MessageBox.Show("Done"); }