public static ToQarPath ( string Path ) : string | ||
Path | string | |
return | string |
public List <string> GetModQarFiles(bool HideExtension = false) { Settings settings = new Settings(); settings.LoadFrom(directory, filename); List <string> qarList = new List <string>(); foreach (ModEntry mod in settings.ModEntries) { foreach (ModQarEntry qarFile in mod.ModQarEntries) { string fileName; if (HideExtension) { fileName = Tools.ToQarPath(qarFile.FilePath.Substring(0, qarFile.FilePath.IndexOf("."))); } else { fileName = Tools.ToQarPath(qarFile.FilePath); } qarList.Add(fileName); } } return(qarList); }
internal static ulong NameToHash(string FileName) { // regenerate hash for file string filePath = Tools.ToQarPath(FileName); ulong hash; if (!filePath.Substring(1).Contains("/")) { // try to parse hash from filename string fileName = filePath.TrimStart('/'); string fileNoExt = fileName.Substring(0, fileName.IndexOf(".")); string fileExt = fileName.Substring(fileName.IndexOf(".") + 1); bool tryParseHash = ulong.TryParse(fileNoExt, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.CurrentCulture, out hash); if (tryParseHash) // successfully parsed filename { ulong ExtHash = Hashing.HashFileName(fileExt, false) & 0x1FFF; hash = (ExtHash << 51) | hash; } } else { hash = Hashing.HashFileNameWithExtension(filePath); } return(hash); }
internal static ulong NameToHash(string FileName) { // regenerate hash for file string filePath = Tools.ToQarPath(FileName); ulong hash = Hashing.HashFileNameWithExtension(filePath); // find hashed names, which will be in root if (!filePath.Substring(1).Contains("/")) { // try to parse hash from filename string fileName = filePath.TrimStart('/'); string fileNoExt = fileName.Substring(0, fileName.IndexOf(".")); string fileExt = fileName.Substring(fileName.IndexOf(".") + 1); //tex NMC aparently cant use HashFileNameWithExtension with undictionaried/files with hash names // tryParseHash will fail for non hashed files in root (currently only init.lua and foxpatch.dat) bool tryParseHash = ulong.TryParse(fileNoExt, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.CurrentCulture, out hash); if (tryParseHash) // successfully parsed filename { //TODO: create Hashing.HashFileExtension ulong ExtHash = Hashing.HashFileName(fileExt, false) & 0x1FFF; hash = (ExtHash << 51) | hash; } else //tex attempted fix for above { hash = Hashing.HashFileNameWithExtension(filePath); } } return(hash); }
internal static ulong NameToHash(string FileName) { // regenerate hash for file string filePath = Tools.ToQarPath(FileName); ulong hash = Hashing.HashFileNameWithExtension(filePath); if (!filePath.Substring(1).Contains("/")) { // try to parse hash from filename string fileName = filePath.TrimStart('/'); string fileNoExt = fileName.Substring(0, fileName.IndexOf(".")); string fileExt = fileName.Substring(fileName.IndexOf(".") + 1); //tex NMC aparently cant use HashFileNameWithExtension with undictionaried/files with hash names // however BUG? because hexnumber is only 0-9, a-f thus tryParseHash will fail and return 0 for init.lua and foxpatch.dat // see also duplicate function in makebite/classes/tools NameToHash bool tryParseHash = ulong.TryParse(fileNoExt, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.CurrentCulture, out hash); if (tryParseHash) // successfully parsed filename { ulong ExtHash = Hashing.HashFileName(fileExt, false) & 0x1FFF; hash = (ExtHash << 51) | hash; } else //tex attempted fix for above { hash = Hashing.HashFileNameWithExtension(filePath); } } return(hash); }
public List <string> GetModExternalFiles() { Settings settings = new Settings(); settings.LoadFrom(directory, filename); List <string> fileList = new List <string>(); foreach (ModEntry mod in settings.ModEntries) { foreach (ModFileEntry fpkFile in mod.ModFileEntries) { fileList.Add(Tools.ToQarPath(fpkFile.FilePath)); } } return(fileList); }
public static List <string> GetModFpkFiles() { Settings settings = new Settings(); settings.Load(); List <string> fpkList = new List <string>(); foreach (ModEntry mod in settings.ModEntries) { foreach (ModFpkEntry fpkFile in mod.ModFpkEntries) { fpkList.Add(Tools.ToQarPath(fpkFile.FilePath)); } } return(fpkList); }
public void AddMod(ModEntry Mod) { Settings settings = new Settings(); settings.LoadFrom(directory, filename); foreach (ModFpkEntry f in Mod.ModFpkEntries) { f.SourceType = FileSource.Mod; f.FpkFile = Tools.ToQarPath(f.FpkFile); f.FilePath = Tools.ToQarPath(f.FilePath); } foreach (ModQarEntry q in Mod.ModQarEntries) { q.SourceType = FileSource.Mod; q.FilePath = Tools.ToQarPath(q.FilePath); } settings.ModEntries.Add(Mod); settings.SaveTo(directory, filename); }
internal static bool CompareNames(string File1, string File2) { // TODO: change name comparison to use function return(Tools.ToQarPath(File1) == Tools.ToQarPath(File2)); }
public static bool InstallMod(string ModFile) { CleanupFolders(); Debug.LogLine(String.Format("[Mod] Installation started: {0}", ModFile), Debug.LogLevel.Basic); // Extract game archive var zeroFiles = GzsLib.ExtractArchive <QarFile>(ZeroPath, "_working"); // Extract mod data FastZip unzipper = new FastZip(); unzipper.ExtractZip(ModFile, "_extr", "(.*?)"); // Load mod metadata ModEntry metaData = new ModEntry("_extr\\metadata.xml"); // Build a list of FPKs contained in mod List <string> modFpks = new List <string>(); foreach (ModFpkEntry fpkEntry in metaData.ModFpkEntries) { if (!modFpks.Contains(fpkEntry.FpkFile)) { modFpks.Add(fpkEntry.FpkFile); } } List <string> mergeFpks = new List <string>(); List <ModQarEntry> MergeFiles = new List <ModQarEntry>(); Debug.LogLine("[Mod] Checking existing game data", Debug.LogLevel.Basic); // Check for FPKs in 00.dat foreach (string fpk in modFpks) { string datFile = zeroFiles.FirstOrDefault(file => Tools.CompareHashes(file, fpk)); if (datFile != null) { if (mergeFpks.Contains(Tools.ToQarPath(datFile))) { continue; } mergeFpks.Add(fpk); MergeFiles.Add(new ModQarEntry() { FilePath = fpk, SourceType = FileSource.Merged, SourceName = "00.dat" }); } } var gameData = GzsLib.ReadBaseData(); var oneFiles = gameData.FileList.FindAll(entry => entry.QarFile == "01.dat"); var baseFiles = gameData.FileList.FindAll(entry => entry.QarFile != "01.dat"); // Check for FPKs in 01.dat foreach (string fpk in modFpks) { GameFile file = oneFiles.FirstOrDefault(entry => entry.FileHash == Tools.NameToHash(fpk)); if (file != null) { if (mergeFpks.Contains(Tools.ToQarPath(file.FilePath))) { continue; } // Create destination directory string destDirectory = Path.Combine("_working", Path.GetDirectoryName(Tools.ToWinPath(file.FilePath))); if (!Directory.Exists(destDirectory)) { Directory.CreateDirectory(destDirectory); } // Extract file into dat directory var ex = GzsLib.ExtractFileByHash <QarFile>(Path.Combine(GameDir, "master\\0\\01.dat"), file.FileHash, Path.Combine("_working", Tools.ToWinPath(file.FilePath))); mergeFpks.Add(Tools.ToQarPath(file.FilePath)); MergeFiles.Add(new ModQarEntry() { FilePath = file.FilePath, SourceType = FileSource.Merged, SourceName = "01.dat" }); if (zeroFiles.FirstOrDefault(datFile => Tools.CompareHashes(datFile, file.FilePath)) == null) { zeroFiles.Add(Tools.ToWinPath(file.FilePath)); } } } // Check for FPKs in base data foreach (string fpk in modFpks) { GameFile file = baseFiles.FirstOrDefault(entry => entry.FileHash == Tools.NameToHash(fpk)); if (file != null) { if (mergeFpks.Contains(Tools.ToQarPath(file.FilePath))) { continue; } // Create destination directory string destDirectory = Path.Combine("_working", Path.GetDirectoryName(Tools.ToWinPath(file.FilePath))); if (!Directory.Exists(destDirectory)) { Directory.CreateDirectory(destDirectory); } // Extract file into dat directory var ex = GzsLib.ExtractFileByHash <QarFile>(Path.Combine(GameDir, "master\\" + file.QarFile), file.FileHash, Path.Combine("_working", Tools.ToWinPath(file.FilePath))); mergeFpks.Add(Tools.ToQarPath(file.FilePath)); MergeFiles.Add(new ModQarEntry() { FilePath = file.FilePath, SourceType = FileSource.Merged, SourceName = file.QarFile }); if (zeroFiles.FirstOrDefault(datFile => Tools.CompareHashes(datFile, file.FilePath)) == null) { zeroFiles.Add(Tools.ToWinPath(file.FilePath)); } } } Debug.LogLine(String.Format("[Mod] Merging {0} FPK files", MergeFiles.Count), Debug.LogLevel.Basic); var g = SettingsManager.GetGameData(); // Merge FPK files foreach (ModQarEntry gf in MergeFiles) { Debug.LogLine(String.Format("[Mod] Starting merge: {0} ({1})", gf.FilePath, gf.SourceName), Debug.LogLevel.Debug); // Extract game FPK string fpkDatPath = zeroFiles.FirstOrDefault(file => Tools.CompareHashes(file, gf.FilePath)); string fpkPath = Path.Combine("_working", Tools.ToWinPath(fpkDatPath)); var gameFpk = GzsLib.ExtractArchive <FpkFile>(fpkPath, "_gamefpk"); // Extract mod FPK var exFpk = GzsLib.ExtractArchive <FpkFile>(Path.Combine("_extr", Tools.ToWinPath(gf.FilePath)), "_modfpk"); // Add file to gamedata info var q = g.GameQarEntries.FirstOrDefault(entry => entry.FilePath == gf.FilePath); if (q == null) { g.GameQarEntries.Add(new ModQarEntry() { FilePath = Tools.ToQarPath(gf.FilePath), SourceType = gf.SourceType, SourceName = gf.SourceName, Hash = Tools.NameToHash(gf.FilePath) }); } foreach (string f in gameFpk) { var c = exFpk.FirstOrDefault(entry => Tools.CompareHashes(entry, f)); if (c == null) { if (g.GameFpkEntries.FirstOrDefault(entry => Tools.CompareHashes(entry.FpkFile, gf.FilePath) && Tools.CompareNames(entry.FilePath, f)) == null) { g.GameFpkEntries.Add(new ModFpkEntry() { FpkFile = Tools.ToQarPath(gf.FilePath), FilePath = f, SourceType = gf.SourceType, SourceName = gf.SourceName }); } } } // Merge contents foreach (string fileName in exFpk) { string fileDir = (Path.Combine("_gamefpk", Path.GetDirectoryName(fileName))); string sourceFile = Path.Combine("_modfpk", fileName); string destFile = Path.Combine("_gamefpk", fileName); Debug.LogLine(String.Format("[Mod] Copying file: {0}", fileName), Debug.LogLevel.All); if (!Directory.Exists(fileDir)) { Directory.CreateDirectory(fileDir); } File.Copy(sourceFile, destFile, true); if (!gameFpk.Contains(fileName)) { gameFpk.Add(Tools.ToQarPath(fileName)); } } // Rebuild game FPK GzsLib.WriteFpkArchive(fpkPath, "_gamefpk", gameFpk); if (!zeroFiles.Contains(Tools.ToWinPath(gf.FilePath))) { zeroFiles.Add(Tools.ToWinPath(gf.FilePath)); } Directory.Delete("_modfpk", true); Directory.Delete("_gamefpk", true); Debug.LogLine(String.Format("[Mod] Merge complete"), Debug.LogLevel.Debug); } SettingsManager.SetGameData(g); Debug.LogLine("[Mod] Copying remaining mod files", Debug.LogLevel.Basic); // Copy files for 01.dat, ignoring merged FPKs foreach (ModQarEntry modEntry in metaData.ModQarEntries) { if (!zeroFiles.Contains(Tools.ToWinPath(modEntry.FilePath))) { zeroFiles.Add(Tools.ToWinPath(modEntry.FilePath)); } if (modEntry.FilePath.Contains(".fpk")) { if (mergeFpks.Count(fpk => Tools.CompareHashes(fpk, modEntry.FilePath)) > 0) { continue; } } string sourceFile = Path.Combine("_extr", Tools.ToWinPath(modEntry.FilePath)); string destFile = Path.Combine("_working", Tools.ToWinPath(modEntry.FilePath)); string destDir = Path.GetDirectoryName(destFile); Debug.LogLine(String.Format("[Mod] Copying file: {0}", modEntry.FilePath), Debug.LogLevel.All); if (!Directory.Exists(destDir)) { Directory.CreateDirectory(destDir); } File.Copy(sourceFile, destFile, true); } // Rebuild 01.dat Debug.LogLine("[Mod] Rebuilding game archive", Debug.LogLevel.Basic); GzsLib.WriteQarArchive(ZeroPath, "_working", zeroFiles, 3150048); SettingsManager.UpdateDatHash(); SettingsManager.AddMod(metaData); Debug.LogLine("[Mod] Running database cleanup", Debug.LogLevel.Debug); CleanupDatabase(); CleanupFolders(); Debug.LogLine("[Mod] Installation finished", Debug.LogLevel.Basic); return(true); }
/// <summary> /// Checks 00.dat files, indcluding fpk contents and adds the different mod entry types (if missing) to database (snakebite.xml) /// Slows down as number of fpks increase /// </summary> public static void CleanupDatabase() { Debug.LogLine("[Cleanup] Database cleanup started", Debug.LogLevel.Basic); // Retrieve installation data SettingsManager manager = new SettingsManager(SnakeBiteSettings); var mods = manager.GetInstalledMods(); var game = manager.GetGameData(); var zeroFiles = GzsLib.ListArchiveContents<QarFile>(ZeroPath); //Should only happen if user manually mods 00.dat Debug.LogLine("[Cleanup] Removing duplicate file entries", Debug.LogLevel.Debug); // Remove duplicate file entries var cleanFiles = zeroFiles.ToList(); foreach (string file in zeroFiles) { while (cleanFiles.Count(entry => entry == file) > 1) { cleanFiles.Remove(file); Debug.LogLine(String.Format("[Cleanup] Found duplicate file in 00.dat: {0}", file), Debug.LogLevel.Debug); } } Debug.LogLine("[Cleanup] Examining FPK archives", Debug.LogLevel.Debug); var GameFpks = game.GameFpkEntries.ToList(); // Search for FPKs in game data var fpkFiles = cleanFiles.FindAll(entry => entry.EndsWith(".fpk") || entry.EndsWith(".fpkd")); foreach (string fpkFile in fpkFiles) { string fpkName = Path.GetFileName(fpkFile); // Extract FPK from archive Debug.LogLine(String.Format("[Cleanup] Examining {0}", fpkName)); GzsLib.ExtractFile<QarFile>(ZeroPath, fpkFile, fpkName); // Read FPK contents var fpkContent = GzsLib.ListArchiveContents<FpkFile>(fpkName); // Add contents to game FPK list foreach (var c in fpkContent) { if (GameFpks.Count(entry => Tools.CompareNames(entry.FilePath, c) && Tools.CompareHashes(entry.FpkFile, fpkFile)) == 0) { GameFpks.Add(new ModFpkEntry() { FpkFile = fpkFile, FilePath = c }); } } try { File.Delete(fpkName); } catch { Console.WriteLine("[Uninstall] Could not delete: " + fpkName); } } Debug.LogLine("[Cleanup] Checking installed mods", Debug.LogLevel.Debug); Debug.LogLine("[Cleanup] Removing all installed mod data from game data list", Debug.LogLevel.Debug); foreach (var mod in mods) { foreach (var qarEntry in mod.ModQarEntries) { cleanFiles.RemoveAll(file => Tools.CompareHashes(file, qarEntry.FilePath)); } foreach (var fpkEntry in mod.ModFpkEntries) { GameFpks.RemoveAll(fpk => Tools.CompareHashes(fpk.FpkFile, fpkEntry.FpkFile) && Tools.ToQarPath(fpk.FilePath) == Tools.ToQarPath(fpkEntry.FilePath)); } } Debug.LogLine("[Cleanup] Checking mod QAR files against game files", Debug.LogLevel.Debug); foreach (var s in cleanFiles) { if (game.GameQarEntries.Count(entry => Tools.CompareHashes(entry.FilePath, s)) == 0) { Debug.LogLine($"[Cleanup] Adding missing {s}", Debug.LogLevel.Debug); game.GameQarEntries.Add(new ModQarEntry() { FilePath = Tools.ToQarPath(s), SourceType = FileSource.System, Hash = Tools.NameToHash(s) }); } } game.GameFpkEntries = GameFpks; manager.SetGameData(game); }
// 00 non-snakebite Files to 01, 01 lua files unchanged, 01 textures -> t7, 01 chunkfiles -> c7, private static void MoveDatFilesDirty(SettingsManager manager) { var modQarFiles = manager.GetModQarFiles(); string sourceName = null; string destName = null; string destFolder = null; Debug.LogLine("[DatMerge] Dispersing files from 00 to 01, and then from 01 to a_chunk7 and a_texture7 if necessary.", Debug.LogLevel.Debug); List<string> oneFiles = GzsLib.ExtractArchive<QarFile>(OnePath, "_extr"); List<string> zeroList = new List<string>(); int moveCount = 0; try { zeroList = GzsLib.ListArchiveContents<QarFile>(ZeroPath); } catch (Exception e) { Debug.LogLine(String.Format("[Error] GzsLib.ListArchiveContents exception: {0}", e.ToString()), Debug.LogLevel.Debug); throw e; } foreach (string zeroFile in zeroList) { if (zeroFile == "foxpatch.dat") continue; if (modQarFiles.Contains(Tools.ToQarPath(zeroFile)) || oneFiles.Contains(zeroFile)) continue; if (oneFiles.Contains(zeroFile)) continue; moveCount++; } if (moveCount > 0) //if any non-snakebite files exist in 00, move them to 01. { Debug.LogLine("[DatMerge] Moving files to 01.dat.", Debug.LogLevel.Debug); List<string> zeroFiles = GzsLib.ExtractArchive<QarFile>(ZeroPath, "_working1"); List<string> zeroOut = zeroFiles.ToList(); foreach (string zeroFile in zeroFiles) { if (zeroFile == "foxpatch.dat") continue; if (modQarFiles.Contains(Tools.ToQarPath(zeroFile))) continue; if (oneFiles.Contains(zeroFile)) { zeroOut.Remove(zeroFile); continue; } //if it already exists in 01 then there's nowhere for it to go. sourceName = Path.Combine("_working1", Tools.ToWinPath(zeroFile)); destName = Path.Combine("_extr", Tools.ToWinPath(zeroFile)); oneFiles.Add(zeroFile); // 00 -> 01 zeroOut.Remove(zeroFile); destFolder = Path.GetDirectoryName(destName); if (!Directory.Exists(destFolder)) Directory.CreateDirectory(destFolder); if (!File.Exists(destName)) File.Move(sourceName, destName); } GzsLib.WriteQarArchive(ZeroPath + build_ext, "_working1", zeroOut, GzsLib.zeroFlags); // rebuild 00 archive Directory.Delete("_working1", true); // clean up _working1, to be used by texture7 while (Directory.Exists("_working1")) Thread.Sleep(100); } moveCount = 0; // check if any files need to be moved to C7/T7 int textureCount = 0; List<string> chunk7List = new List<string>(); List<string> tex7List = new List<string>(); try { if (File.Exists(t7Path)) tex7List = GzsLib.ListArchiveContents<QarFile>(t7Path); if (File.Exists(c7Path)) chunk7List = GzsLib.ListArchiveContents<QarFile>(c7Path); } catch (Exception e) { Debug.LogLine(String.Format("[Error] GzsLib.ListArchiveContents exception: {0}", e.ToString()), Debug.LogLevel.Debug); throw e; } foreach (string oneFile in oneFiles) { if (modQarFiles.Contains(Tools.ToQarPath(oneFile)) || tex7List.Contains(oneFile) || chunk7List.Contains(oneFile)) continue; if (oneFile.Contains(".lua")) continue; // vanilla lua files must stay in 01 if (oneFile.Contains(".ftex")) textureCount++; moveCount++; } if (moveCount > 0) { List<string> oneOut = oneFiles.ToList(); if (textureCount > 0) // if non-snakebite textures exist, move them to t7 { Debug.LogLine("[DatMerge] Moving files to a_texture7.dat.", Debug.LogLevel.Debug); List<string> texture7Files = new List<string>(); if (File.Exists(t7Path)) texture7Files = GzsLib.ExtractArchive<QarFile>(t7Path, "_working1"); foreach (string oneFile in oneFiles) // once 00 files have been moved, move 01 files into t7, c7. { if (modQarFiles.Contains(Tools.ToQarPath(oneFile))) continue; if (oneFile.Contains(".ftex")) { sourceName = Path.Combine("_extr", Tools.ToWinPath(oneFile)); destName = Path.Combine("_working1", Tools.ToWinPath(oneFile)); // 01 -> texture7 destFolder = Path.GetDirectoryName(destName); if (!texture7Files.Contains(oneFile)) texture7Files.Add(oneFile); oneOut.Remove(oneFile); if (!Directory.Exists(destFolder)) Directory.CreateDirectory(destFolder); if (!File.Exists(destName)) File.Move(sourceName, destName); } } GzsLib.WriteQarArchive(t7Path + build_ext, "_working1", texture7Files, GzsLib.texture7Flags); } oneFiles = oneOut.ToList(); // update oneFiles to remove any .ftex already found if (oneFiles.Count > 0) // if any other files need to be moved, they go in chunk7 { Debug.LogLine("[DatMerge] Moving files to a_chunk7.dat.", Debug.LogLevel.Debug); List<string> chunk7Files = new List<string>(); if (File.Exists(c7Path)) chunk7Files = GzsLib.ExtractArchive<QarFile>(c7Path, "_working2"); foreach (string oneFile in oneFiles) // once 00 files have been moved, move 01 files into t7, c7. { if (modQarFiles.Contains(Tools.ToQarPath(oneFile))) continue; if (oneFile.Contains(".lua")) continue; sourceName = Path.Combine("_extr", Tools.ToWinPath(oneFile)); destName = Path.Combine("_working2", Tools.ToWinPath(oneFile)); // 00 -> chunk7 destFolder = Path.GetDirectoryName(destName); if (!chunk7Files.Contains(oneFile)) chunk7Files.Add(oneFile); oneOut.Remove(oneFile); if (!Directory.Exists(destFolder)) Directory.CreateDirectory(destFolder); if (!File.Exists(destName)) File.Move(sourceName, destName); } GzsLib.WriteQarArchive(c7Path + build_ext, "_working2", chunk7Files, GzsLib.chunk7Flags); // rebuild chunk7 archive } GzsLib.WriteQarArchive(OnePath + build_ext, "_extr", oneOut, GzsLib.oneFlags); // rebuild 01 archive } }
public static bool CheckConflicts(string ModFile, bool ignoreConflicts = false) { var metaData = Tools.ReadMetaData(ModFile); if (metaData == null) { return(false); } if (!SettingsManager.DisableConflictCheck && !ignoreConflicts) { // check version conflicts var SBVersion = ModManager.GetSBVersion(); var MGSVersion = ModManager.GetMGSVersion(); Version modSBVersion = new Version(); Version modMGSVersion = new Version(); try { modSBVersion = metaData.SBVersion.AsVersion(); modMGSVersion = metaData.MGSVersion.AsVersion(); } catch { MessageBox.Show(String.Format("The selected version of {0} was created with an older version of SnakeBite and is no longer compatible, please download the latest version and try again.", metaData.Name), "Mod update required", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } // Check if mod requires SB update if (modSBVersion > SBVersion) { MessageBox.Show(String.Format("{0} requires a newer version of SnakeBite. Please follow the link on the Settings page to get the latest version.", metaData.Name), "Update required", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } if (modSBVersion < new Version(0, 8, 0, 0)) // 0.8.0.0 { MessageBox.Show(String.Format("The selected version of {0} was created with an older version of SnakeBite and is no longer compatible, please download the latest version and try again.", metaData.Name), "Mod update required", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } // Check MGS version compatibility if (MGSVersion != modMGSVersion && modMGSVersion != new Version(0, 0, 0, 0)) { if (MGSVersion > modMGSVersion && modMGSVersion > new Version(0, 0, 0, 0)) { var contInstall = MessageBox.Show(String.Format("{0} appears to be for an older version of MGSV. It is recommended that you at least check for an updated version before installing.\n\nContinue installation?", metaData.Name, modMGSVersion, MGSVersion), "Game version mismatch", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); if (contInstall == DialogResult.No) { return(false); } } if (MGSVersion < modMGSVersion) { MessageBox.Show(String.Format("{0} requires MGSV version {1}, but your installation is version {2}. Please update MGSV and try again.", metaData.Name, modMGSVersion, MGSVersion), "Update required", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } } Debug.LogLine(String.Format("[Mod] Checking conflicts for {0}", metaData.Name)); int confCounter = 0; // search installed mods for conflicts var mods = SettingsManager.GetInstalledMods(); List <string> conflictingMods = new List <string>(); int confIndex = -1; foreach (ModEntry mod in mods) // iterate through installed mods { foreach (ModQarEntry qarEntry in metaData.ModQarEntries) // iterate qar files from new mod { if (qarEntry.FilePath.Contains(".fpk")) { continue; } ModQarEntry conflicts = mod.ModQarEntries.FirstOrDefault(entry => Tools.CompareHashes(entry.FilePath, qarEntry.FilePath)); if (conflicts != null) { if (confIndex == -1) { confIndex = mods.IndexOf(mod); } if (!conflictingMods.Contains(mod.Name)) { conflictingMods.Add(mod.Name); } Debug.LogLine(String.Format("[{0}] Conflict in 00.dat: {1}", mod.Name, conflicts.FilePath)); confCounter++; } } foreach (ModFpkEntry fpkEntry in metaData.ModFpkEntries) // iterate fpk files from new mod { ModFpkEntry conflicts = mod.ModFpkEntries.FirstOrDefault(entry => Tools.CompareHashes(entry.FpkFile, fpkEntry.FpkFile) && Tools.CompareHashes(entry.FilePath, fpkEntry.FilePath)); if (conflicts != null) { if (confIndex == -1) { confIndex = mods.IndexOf(mod); } if (!conflictingMods.Contains(mod.Name)) { conflictingMods.Add(mod.Name); } Debug.LogLine(String.Format("[{0}] Conflict in {2}: {1}", mod.Name, conflicts.FilePath, Path.GetFileName(conflicts.FpkFile))); confCounter++; } } } // if the mod conflicts, display message if (conflictingMods.Count > 0) { Debug.LogLine(String.Format("[Mod] Found {0} conflicts", confCounter)); string msgboxtext = "The selected mod conflicts with these mods:\n"; foreach (string Conflict in conflictingMods) { msgboxtext += Conflict + "\n"; } msgboxtext += "\nMore information regarding the conflicts has been output to the logfile. Double click the version number shown in the Launcher to view the current logfile."; MessageBox.Show(msgboxtext, "Installation Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } Debug.LogLine("[Mod] No conflicts found"); bool sysConflict = false; // check for system file conflicts var gameData = SettingsManager.GetGameData(); foreach (ModQarEntry gameQarFile in gameData.GameQarEntries.FindAll(entry => entry.SourceType == FileSource.System)) { if (metaData.ModQarEntries.Count(entry => Tools.ToQarPath(entry.FilePath) == Tools.ToQarPath(gameQarFile.FilePath)) > 0) { sysConflict = true; } } foreach (ModFpkEntry gameFpkFile in gameData.GameFpkEntries.FindAll(entry => entry.SourceType == FileSource.System)) { if (metaData.ModFpkEntries.Count(entry => entry.FilePath == gameFpkFile.FilePath && entry.FpkFile == gameFpkFile.FpkFile) > 0) { sysConflict = true; } } if (sysConflict) { MessageBox.Show("The selected mod conflicts with existing MGSV system files.", "SnakeBite", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } DialogResult confirmInstall = MessageBox.Show(String.Format("You are about to install {0}, continue?", metaData.Name), "SnakeBite", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (confirmInstall == DialogResult.No) { return(false); } } return(true); }
public static void MoveDatFiles() { Debug.LogLine("[DatMerge] System data merge started", Debug.LogLevel.Debug); var zeroList = GzsLib.ListArchiveContents <QarFile>(ZeroPath); var modQarFiles = SettingsManager.GetModQarFiles(); int mc = 0; foreach (string zeroFile in zeroList) { if (zeroFile == "foxpatch.dat") { continue; } if (modQarFiles.Contains(Tools.ToQarPath(zeroFile))) { continue; } mc++; } if (mc > 0) { CleanupFolders(); // Extract 00.dat var zeroFiles = GzsLib.ExtractArchive <QarFile>(ZeroPath, "_extr"); // Extract 01.dat var oneFiles = GzsLib.ExtractArchive <QarFile>(OnePath, "_working"); var zeroOut = zeroFiles.ToList(); Debug.LogLine(string.Format("[DatMerge] Moving {0} system files", mc), Debug.LogLevel.Debug); // Move files from 00 to 01 (excluding foxpatch.dat) foreach (string zeroFile in zeroFiles) { if (zeroFile == "foxpatch.dat") { continue; } if (modQarFiles.Contains(Tools.ToQarPath(zeroFile))) { continue; } string sourceName = Path.Combine("_extr", Tools.ToWinPath(zeroFile)); string destName = Path.Combine("_working", Tools.ToWinPath(zeroFile)); string destFolder = Path.GetDirectoryName(destName); Debug.LogLine(string.Format("[DatMerge] Moving system file {0}", zeroFile)); if (!Directory.Exists(destFolder)) { Directory.CreateDirectory(destFolder); } File.Move(sourceName, destName); zeroOut.Remove(zeroFile); oneFiles.Add(zeroFile); } Debug.LogLine("[DatMerge] Rebuilding game archives", Debug.LogLevel.Debug); // Rebuild 01.dat with files GzsLib.WriteQarArchive(OnePath, "_working", oneFiles, 3150048); // Rebuild 00.dat GzsLib.WriteQarArchive(ZeroPath, "_extr", zeroOut, 3150304); SettingsManager.UpdateDatHash(); CleanupFolders(); Debug.LogLine("[DatMerge] Merge finished", Debug.LogLevel.Debug); } else { Debug.LogLine("[DatMerge] No files to merge, aborting", Debug.LogLevel.Debug); } }
public static bool UninstallMod(ModEntry mod) { Debug.LogLine(String.Format("[Mod] Uninstall started: {0}", mod.Name), Debug.LogLevel.Basic); CleanupFolders(); // Extract game archive var zeroFiles = GzsLib.ExtractArchive <QarFile>(ZeroPath, "_working"); // List all FPKs in mod List <string> modFpks = new List <string>(); foreach (ModFpkEntry fpkEntry in mod.ModFpkEntries) { if (!modFpks.Contains(fpkEntry.FpkFile)) { modFpks.Add(fpkEntry.FpkFile); } } var gameData = SettingsManager.GetGameData(); // Extract FPK foreach (string fpk in modFpks) { string fpkName = Path.GetFileName(fpk); string fpkDatPath = zeroFiles.FirstOrDefault(file => Tools.CompareHashes(file, fpk)); if (fpkDatPath == null) { continue; } var fpkFile = GzsLib.ExtractArchive <FpkFile>(Path.Combine("_working", Tools.ToWinPath(fpkDatPath)), "_modfpk"); // Remove all mod fpk files from fpk foreach (ModFpkEntry fpkEntry in mod.ModFpkEntries) { Debug.LogLine(String.Format("[Mod] Removing {1}\\{0}", Tools.ToWinPath(fpkEntry.FilePath), fpkName), Debug.LogLevel.Debug); fpkFile.RemoveAll(file => Tools.ToQarPath(file) == Tools.ToQarPath(fpkEntry.FilePath)); } var gameFpks = gameData.GameFpkEntries.ToList(); // remove all merged files from fpk foreach (ModFpkEntry gameFpkFile in gameFpks) { if (Tools.ToQarPath(gameFpkFile.FpkFile) == Tools.ToQarPath(fpk) && gameFpkFile.SourceType == FileSource.Merged) { Debug.LogLine(String.Format("[Mod] Removing merged file {0}", gameFpkFile.FilePath)); fpkFile.RemoveAll(entry => entry == gameFpkFile.FilePath); gameData.GameFpkEntries.Remove(gameFpkFile); } } // remove fpk if no files left if (fpkFile.Count == 0) { Debug.LogLine(String.Format("[Mod] {0} is empty, removing", fpkName), Debug.LogLevel.Debug); zeroFiles.RemoveAll(file => Tools.CompareHashes(file, fpk)); gameData.GameQarEntries.RemoveAll(file => Tools.CompareHashes(file.FilePath, fpk)); } else { Debug.LogLine(String.Format("[Mod] Rebuilding {0}", fpk), Debug.LogLevel.Debug); // rebuild fpk from base file var baseData = GzsLib.ReadBaseData(); var oneFiles = baseData.FileList.FindAll(entry => entry.QarFile == "01.dat"); var baseFiles = baseData.FileList.FindAll(entry => entry.QarFile != "01.dat"); // Check for FPKs in 00.dat first GameFile file = oneFiles.FirstOrDefault(entry => entry.FileHash == Tools.NameToHash(fpk)); if (file != null) { // Extract base FPK files GzsLib.ExtractFileByHash <QarFile>(Path.Combine(GameDir, "master\\0\\01.dat"), file.FileHash, "_working\\temp.fpk"); var gameFpk = GzsLib.ExtractArchive <FpkFile>("_working\\temp.fpk", "_gamefpk"); // Add merged base files to game file database var mCount = 0; foreach (var fpkF in gameFpk) { if (!fpkFile.Contains(fpkF)) { gameData.GameFpkEntries.Add(new ModFpkEntry() { FpkFile = fpk, FilePath = fpkF, SourceType = FileSource.Merged, SourceName = file.QarFile }); mCount++; } } Debug.LogLine(String.Format("[Mod] {0} files restored from {1}", mCount, file.QarFile), Debug.LogLevel.Debug); // Copy remaining files over base FPK foreach (string mFile in fpkFile) { string fDir = Path.GetDirectoryName(mFile); if (!Directory.Exists(Path.Combine("_gamefpk", fDir))) { Directory.CreateDirectory(Path.Combine("_gamefpk", fDir)); } Debug.LogLine(String.Format("[Mod] Merging existing file: {0}", mFile)); File.Copy(Path.Combine("_modfpk", mFile), Path.Combine(Path.Combine("_gamefpk", mFile)), true); if (!gameFpk.Contains(mFile)) { gameFpk.Add(mFile); } } // Rebuild FPK GzsLib.WriteFpkArchive(Path.Combine("_working", Tools.ToWinPath(fpkDatPath)), "_gamefpk", gameFpk); Directory.Delete("_gamefpk", true); Directory.Delete("_modfpk", true); continue; // don't check base data if it's in 01 } // check base files for FPK file = baseFiles.FirstOrDefault(entry => entry.FileHash == Tools.NameToHash(fpk)); if (file != null) { // Extract base FPK files GzsLib.ExtractFileByHash <QarFile>(Path.Combine(GameDir, "master\\" + file.QarFile), file.FileHash, "_working\\temp.fpk"); var gameFpk = GzsLib.ExtractArchive <FpkFile>("_working\\temp.fpk", "_gamefpk"); // Add merged base files to game file database var mCount = 0; foreach (var fpkF in gameFpk) { if (!fpkFile.Contains(fpkF)) { gameData.GameFpkEntries.Add(new ModFpkEntry() { FpkFile = fpk, FilePath = fpkF, SourceType = FileSource.Merged, SourceName = file.QarFile }); mCount++; } } Debug.LogLine(String.Format("[Mod] {0} files restored from {1}", mCount, file.QarFile), Debug.LogLevel.Debug); // Copy remaining files over base FPK foreach (string mFile in fpkFile) { string fDir = Path.GetDirectoryName(mFile); if (!Directory.Exists(Path.Combine("_gamefpk", fDir))) { Directory.CreateDirectory(Path.Combine("_gamefpk", fDir)); } Debug.LogLine(String.Format("[Mod] Merging existing file: {0}", mFile)); File.Copy(Path.Combine("_modfpk", mFile), Path.Combine(Path.Combine("_gamefpk", mFile)), true); if (!gameFpk.Contains(mFile)) { gameFpk.Add(mFile); } } // Rebuild FPK GzsLib.WriteFpkArchive(Path.Combine("_working", Tools.ToWinPath(fpk)), "_gamefpk", gameFpk); Directory.Delete("_gamefpk", true); Directory.Delete("_modfpk", true); } } } SettingsManager.SetGameData(gameData); // Remove all mod files from 01.dat foreach (ModQarEntry qarEntry in mod.ModQarEntries) { string fExt = Path.GetExtension(qarEntry.FilePath); if (!fExt.Contains(".fpk")) { zeroFiles.RemoveAll(file => Tools.CompareHashes(file, qarEntry.FilePath)); } } Debug.LogLine("[Mod] Rebuilding game archive", Debug.LogLevel.Basic); // Rebuild 01.dat GzsLib.WriteQarArchive(ZeroPath, "_working", zeroFiles, 3150048); SettingsManager.UpdateDatHash(); SettingsManager.RemoveMod(mod); CleanupDatabase(); CleanupFolders(); Debug.LogLine("[Mod] Uninstall complete", Debug.LogLevel.Basic); return(true); }
public static void FilterModConflicts(List <string> ModFiles)//checks if the mods in the list conflict with installed mods or with the game files { // asks user for input if a conflict is found. //return a list of mods that the user has OK'd int confCounter; int confIndex; SettingsManager manager = new SettingsManager(GameDir); var mods = manager.GetInstalledMods(); List <string> conflictingMods; ModEntry metaData; formModConflict conflictForm = new formModConflict(); // search installed mods for conflicts for (int i = ModFiles.Count() - 1; i >= 0; i--) { metaData = Tools.ReadMetaData(ModFiles[i]); confCounter = 0; confIndex = -1; conflictingMods = new List <string>(); Debug.LogLine(String.Format("[Mod] Checking conflicts for {0}", metaData.Name)); foreach (ModEntry mod in mods) // iterate through installed mods [Morbid: TODO iterate pftxs files as well] { foreach (ModFileEntry fileEntry in metaData.ModFileEntries) // iterate external files from new mod { ModFileEntry conflicts = mod.ModFileEntries.FirstOrDefault(entry => Tools.CompareHashes(entry.FilePath, fileEntry.FilePath)); if (conflicts != null) { if (confIndex == -1) { confIndex = mods.IndexOf(mod); } if (!conflictingMods.Contains(mod.Name)) { conflictingMods.Add(mod.Name); } Debug.LogLine(String.Format("[{0}] Conflict in 00.dat: {1}", mod.Name, conflicts.FilePath)); confCounter++; } } foreach (ModQarEntry qarEntry in metaData.ModQarEntries) // iterate qar files from new mod { if (qarEntry.FilePath.Contains(".fpk")) { continue; } ModQarEntry conflicts = mod.ModQarEntries.FirstOrDefault(entry => Tools.CompareHashes(entry.FilePath, qarEntry.FilePath)); if (conflicts != null) { if (confIndex == -1) { confIndex = mods.IndexOf(mod); } if (!conflictingMods.Contains(mod.Name)) { conflictingMods.Add(mod.Name); } Debug.LogLine(String.Format("[{0}] Conflict in 00.dat: {1}", mod.Name, conflicts.FilePath)); confCounter++; } } foreach (ModFpkEntry fpkEntry in metaData.ModFpkEntries) // iterate fpk files from new mod { ModFpkEntry conflicts = mod.ModFpkEntries.FirstOrDefault(entry => Tools.CompareHashes(entry.FpkFile, fpkEntry.FpkFile) && Tools.CompareHashes(entry.FilePath, fpkEntry.FilePath)); if (conflicts != null) { if (confIndex == -1) { confIndex = mods.IndexOf(mod); } if (!conflictingMods.Contains(mod.Name)) { conflictingMods.Add(mod.Name); } Debug.LogLine(String.Format("[{0}] Conflict in {2}: {1}", mod.Name, conflicts.FilePath, Path.GetFileName(conflicts.FpkFile))); confCounter++; } } } // if the mod conflicts, prompt user for resolution if (conflictingMods.Count > 0) { Debug.LogLine(String.Format("[Mod] Found {0} conflicts", confCounter)); string msgboxtext = String.Format("\"{0}\" conflicts with the following pre-existing mods:\n\n", Tools.ReadMetaData(ModFiles[i]).Name); foreach (string Conflict in conflictingMods) { msgboxtext += String.Format("\"{0}\"\n", Conflict); } msgboxtext += "\n\nMore information regarding these conflicts can be found in the Debug Logs."; DialogResult userInput = conflictForm.ShowDialog(msgboxtext); if (userInput == DialogResult.Cancel) { ModFiles.RemoveAt(i); continue; } } Debug.LogLine("[Mod] No conflicts found"); bool sysConflict = false; // check for system file conflicts var gameData = manager.GetGameData(); foreach (ModQarEntry gameQarFile in gameData.GameQarEntries.FindAll(entry => entry.SourceType == FileSource.System)) { if (metaData.ModQarEntries.Count(entry => Tools.ToQarPath(entry.FilePath) == Tools.ToQarPath(gameQarFile.FilePath)) > 0) { sysConflict = true; } } foreach (ModFpkEntry gameFpkFile in gameData.GameFpkEntries.FindAll(entry => entry.SourceType == FileSource.System)) { if (metaData.ModFpkEntries.Count(entry => entry.FilePath == gameFpkFile.FilePath && entry.FpkFile == gameFpkFile.FpkFile) > 0) { sysConflict = true; } } if (sysConflict) { //tex TODO: figure out what it's actually checking and how this can be corrupted string msgboxtext = String.Format("\"{0}\" conflicts with existing MGSV system files,\n", Tools.ReadMetaData(ModFiles[i]).Name); msgboxtext += "or the snakebite.xml base entries has become corrupt.\n"; msgboxtext += "Please use the Restore Original Game Files option in Snakebite settings and re-run snakebite\n"; DialogResult userInput = conflictForm.ShowDialog(msgboxtext); if (userInput == DialogResult.Cancel) { ModFiles.RemoveAt(i); continue; } } } }
public static bool CheckConflicts(string ModFile) { //Morbid: Conflict check has been reworked as of 0.9.0. CheckConflicts is now split into PreinstallManager.FilterModValidity and PreinstallManager.FilterModConflicts. // CheckConflicts is only used for command-line installation. ModEntry metaData = Tools.ReadMetaData(ModFile); if (metaData == null) { return(false); } // check version conflicts var SBVersion = ModManager.GetSBVersion(); var MGSVersion = ModManager.GetMGSVersion(); Version modSBVersion = new Version(); Version modMGSVersion = new Version(); try { modSBVersion = metaData.SBVersion.AsVersion(); modMGSVersion = metaData.MGSVersion.AsVersion(); } catch { MessageBox.Show(String.Format("The selected version of {0} was created with an older version of SnakeBite and is no longer compatible, please download the latest version and try again.", metaData.Name), "Mod update required", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } // Check if mod requires SB update if (modSBVersion > SBVersion) { MessageBox.Show(String.Format("{0} requires SnakeBite version {1} or newer. Please follow the link on the Settings page to get the latest version.", metaData.Name, metaData.SBVersion), "Update required", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } if (modSBVersion < new Version(0, 8, 0, 0)) // 0.8.0.0 { MessageBox.Show(String.Format("The selected version of {0} was created with an older version of SnakeBite and is no longer compatible, please download the latest version and try again.", metaData.Name), "Mod update required", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } // Check MGS version compatibility if (MGSVersion != modMGSVersion && modMGSVersion != new Version(0, 0, 0, 0)) { if (MGSVersion > modMGSVersion && modMGSVersion > new Version(0, 0, 0, 0)) { var contInstall = MessageBox.Show(String.Format("{0} appears to be for an older version of MGSV. It is recommended that you at least check for an updated version before installing.\n\nContinue installation?", metaData.Name), "Game version mismatch", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); if (contInstall == DialogResult.No) { return(false); } } if (MGSVersion < modMGSVersion) { MessageBox.Show(String.Format("{0} requires MGSV version {1}, but your installation is version {2}. Please update MGSV and try again.", metaData.Name, modMGSVersion, MGSVersion), "Update required", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } } //end of validity checks Debug.LogLine(String.Format("[Mod] Checking conflicts for {0}", metaData.Name)); int confCounter = 0; // search installed mods for conflicts SettingsManager manager = new SettingsManager(GameDir); var mods = manager.GetInstalledMods(); List <string> conflictingMods = new List <string>(); int confIndex = -1; foreach (ModEntry mod in mods) // iterate through installed mods { foreach (ModFileEntry fileEntry in metaData.ModFileEntries) // iterate external files from new mod { ModFileEntry conflicts = mod.ModFileEntries.FirstOrDefault(entry => Tools.CompareHashes(entry.FilePath, fileEntry.FilePath)); if (conflicts != null) { if (confIndex == -1) { confIndex = mods.IndexOf(mod); } if (!conflictingMods.Contains(mod.Name)) { conflictingMods.Add(mod.Name); } Debug.LogLine(String.Format("[{0}] Conflict in 00.dat: {1}", mod.Name, conflicts.FilePath)); confCounter++; } } foreach (ModQarEntry qarEntry in metaData.ModQarEntries) // iterate qar files from new mod { if (qarEntry.FilePath.Contains(".fpk")) { continue; } ModQarEntry conflicts = mod.ModQarEntries.FirstOrDefault(entry => Tools.CompareHashes(entry.FilePath, qarEntry.FilePath)); if (conflicts != null) { if (confIndex == -1) { confIndex = mods.IndexOf(mod); } if (!conflictingMods.Contains(mod.Name)) { conflictingMods.Add(mod.Name); } Debug.LogLine(String.Format("[{0}] Conflict in 00.dat: {1}", mod.Name, conflicts.FilePath)); confCounter++; } } foreach (ModFpkEntry fpkEntry in metaData.ModFpkEntries) // iterate fpk files from new mod { ModFpkEntry conflicts = mod.ModFpkEntries.FirstOrDefault(entry => Tools.CompareHashes(entry.FpkFile, fpkEntry.FpkFile) && Tools.CompareHashes(entry.FilePath, fpkEntry.FilePath)); if (conflicts != null) { if (confIndex == -1) { confIndex = mods.IndexOf(mod); } if (!conflictingMods.Contains(mod.Name)) { conflictingMods.Add(mod.Name); } Debug.LogLine(String.Format("[{0}] Conflict in {2}: {1}", mod.Name, conflicts.FilePath, Path.GetFileName(conflicts.FpkFile))); confCounter++; } } } // if the mod conflicts, display message if (conflictingMods.Count > 0) { Debug.LogLine(String.Format("[Mod] Found {0} conflicts", confCounter)); string msgboxtext = "The selected mod conflicts with these mods:\n"; foreach (string Conflict in conflictingMods) { msgboxtext += Conflict + "\n"; } msgboxtext += "\nMore information regarding the conflicts has been output to the logfile."; MessageBox.Show(msgboxtext, "Installation Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } Debug.LogLine("[Mod] No conflicts found"); bool sysConflict = false; // check for system file conflicts var gameData = manager.GetGameData(); foreach (ModQarEntry gameQarFile in gameData.GameQarEntries.FindAll(entry => entry.SourceType == FileSource.System)) { if (metaData.ModQarEntries.Count(entry => Tools.ToQarPath(entry.FilePath) == Tools.ToQarPath(gameQarFile.FilePath)) > 0) { sysConflict = true; } } foreach (ModFpkEntry gameFpkFile in gameData.GameFpkEntries.FindAll(entry => entry.SourceType == FileSource.System)) { if (metaData.ModFpkEntries.Count(entry => entry.FilePath == gameFpkFile.FilePath && entry.FpkFile == gameFpkFile.FpkFile) > 0) { sysConflict = true; } } if (sysConflict) { //tex TODO: figure out what it's actually checking and how this can be corrupted string msgboxtext = "The selected mod conflicts with existing MGSV system files,\n"; msgboxtext += "or the snakebite.xml base entries has become corrupt.\n"; msgboxtext += "Please use the Restore Original Game Files option in Snakebite settings and re-run snakebite\n"; MessageBox.Show(msgboxtext, "SnakeBite", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } return(true); }
private static void UnmergePackFiles(List <ModQarEntry> partialEditQarEntries, List <ModFpkEntry> partialRemoveFpkEntries) { GameData gameData = SBBuildManager.GetGameData(); List <ModFpkEntry> addedRepairFpkEntries = new List <ModFpkEntry>(); foreach (ModQarEntry partialEditQarEntry in partialEditQarEntries) { // create a list of fpk filepaths that need to be modified for the specific qar file (either restored to vanilla or removed from the pack) List <string> fpkPathsForThisQar = partialRemoveFpkEntries.Where(entry => entry.FpkFile == partialEditQarEntry.FilePath).Select(fpkEntry => Tools.ToWinPath(fpkEntry.FilePath)).ToList(); var fpkReferences = new List <string>();//tex references in fpk that need to be preserved/transfered to the rebuilt fpk // pull the vanilla qar file from the game archive, send to _gameFpk folder string winQarEntryPath = Tools.ToWinPath(partialEditQarEntry.FilePath); string gameQarPath = Path.Combine("_gameFpk", winQarEntryPath); if (partialEditQarEntry.SourceName != null) { string vanillaArchivePath = Path.Combine(GameDir, "master\\" + partialEditQarEntry.SourceName); //Debug.LogLine(string.Format("Pulling {0} from {1}", partialRemoveQarEntry.FilePath, partialRemoveQarEntry.SourceName)); GzsLib.ExtractFileByHash <QarFile>(vanillaArchivePath, partialEditQarEntry.Hash, gameQarPath); fpkReferences = GzsLib.GetFpkReferences(gameQarPath); } // pull the modded qar file from _working0 (assumed to already exist when the uninstall process reads 00.dat), send to _build folder string workingZeroQarPath = Path.Combine("_working0", winQarEntryPath); List <string> moddedFpkFiles = GzsLib.ExtractArchive <FpkFile>(workingZeroQarPath, "_build"); // split the fpk paths for this Qar into two categories: List <string> repairFilePathList = new List <string>(); // files that need to be repaired (aka overwritten by a vanilla file) if (partialEditQarEntry.SourceName != null) { repairFilePathList = GzsLib.ListArchiveContents <FpkFile>(gameQarPath).Intersect(fpkPathsForThisQar).ToList(); } List <string> removeFilePathList = fpkPathsForThisQar.Except(repairFilePathList).ToList(); // files that need to be removed (i.e. files that were non-native to the vanilla Qar) foreach (string repairFilePath in repairFilePathList) { string fpkBuildPath = Path.Combine("_build", repairFilePath); Debug.LogLine(string.Format("[Unmerge Fpk] Extracting repair file: {0}", repairFilePath), Debug.LogLevel.Basic); GzsLib.ExtractFile <FpkFile>(gameQarPath, repairFilePath, fpkBuildPath); // overwrites modded fpk files ModFpkEntry repairEntry = new ModFpkEntry { FpkFile = partialEditQarEntry.FilePath, FilePath = repairFilePath, // this will be a window path SourceType = FileSource.Merged, SourceName = partialEditQarEntry.SourceName }; gameData.GameFpkEntries.Add(repairEntry); addedRepairFpkEntries.Add(repairEntry); } var buildFiles = moddedFpkFiles.Except(removeFilePathList).ToList(); //tex refs werent grabbed from vanilla (or there weren't any in there in that case we're probably doubling the work lol) if (fpkReferences.Count == 0) { fpkReferences = GzsLib.GetFpkReferences(workingZeroQarPath); } GzsLib.WriteFpkArchive(workingZeroQarPath, "_build", buildFiles, fpkReferences); // writes the pack back to _working folder (leaving out the non-native fpk files) foreach (string removeFilePath in removeFilePathList) { int indexToRemove = gameData.GameFpkEntries.FindIndex(entry => entry.FilePath == removeFilePath); if (indexToRemove >= 0) { gameData.GameFpkEntries.RemoveAt(indexToRemove); } } } List <ModEntry> installedMods = SBBuildManager.GetInstalledMods(); foreach (ModEntry installedMod in installedMods) { List <string> qarPathsFound = new List <string>(); foreach (ModFpkEntry addedRepairEntry in addedRepairFpkEntries) { if (installedMod.ModQarEntries.FirstOrDefault(entry => entry.FilePath == addedRepairEntry.FpkFile) == null) { continue; } //Debug.LogLine(string.Format("checking {0} for {1} of {2}", installedMod.Name, addedRepairEntry.FilePath, addedRepairEntry.FpkFile)); if (installedMod.ModFpkEntries.RemoveAll(entry => entry.FilePath == Tools.ToQarPath(addedRepairEntry.FilePath) && entry.FpkFile == addedRepairEntry.FpkFile) > 0) { //Debug.LogLine(string.Format("found {0} of {1} in {2}", addedRepairEntry.FilePath, addedRepairEntry.FpkFile, installedMod.Name)); if (!qarPathsFound.Contains(addedRepairEntry.FpkFile)) { qarPathsFound.Add(addedRepairEntry.FpkFile); } } } foreach (string qarPathFound in qarPathsFound) { if (installedMod.ModFpkEntries.FirstOrDefault(entry => entry.FpkFile == qarPathFound) == null) //when the duplicate fpk file(s) were removed, there was nothing left in the modded qar. { //Debug.LogLine(string.Format("Removing {0} from {1}", qarPathFound, installedMod.Name)); installedMod.ModQarEntries.RemoveAll(entry => entry.FilePath == qarPathFound); // filters the qar file out of the list } } } SBBuildManager.SetInstalledMods(installedMods); SBBuildManager.SetGameData(gameData); }