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; }
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; }
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"); }