Beispiel #1
0
 //Cull any invalid entries that might have slipped in via older versions of snakebite
 public static void ValidateGameData(ref GameData gameData, ref List<string> zeroFiles)
 {
     Debug.LogLine("[ValidateGameData] Validating gameData files", Debug.LogLevel.Basic);
     Debug.LogLine("[ValidateGameData] Validating qar entries", Debug.LogLevel.Basic);
     for (int i = gameData.GameQarEntries.Count-1; i >= 0; i--)
     {
         ModQarEntry qarEntry = gameData.GameQarEntries[i];
         if (!GzsLib.IsExtensionValidForArchive(qarEntry.FilePath, ".dat"))
         {
             Debug.LogLine($"[ValidateGameData] Found invalid file entry {qarEntry.FilePath} for archive {qarEntry.SourceName}", Debug.LogLevel.Basic);
             gameData.GameQarEntries.RemoveAt(i);
             zeroFiles.Remove(qarEntry.FilePath);//DEBUGNOW VERIFY
         }
     }
     Debug.LogLine("[ValidateGameData] Validating fpk entries", Debug.LogLevel.Basic);
     for (int i = gameData.GameFpkEntries.Count-1; i >= 0; i--)
     {
         ModFpkEntry fpkEntry = gameData.GameFpkEntries[i];
         if (!GzsLib.IsExtensionValidForArchive(fpkEntry.FilePath, fpkEntry.FpkFile))
         {
             Debug.LogLine($"[ValidateGameData] Found invalid file entry {fpkEntry.FilePath} for archive {fpkEntry.FpkFile}", Debug.LogLevel.Basic);
             gameData.GameFpkEntries.RemoveAt(i);
         }
     }
 }
Beispiel #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="sourceFpkFolder">path to folder that contains the files that will go into the fpk (with fpk-internal layout)</param>
        /// <param name="destFpkName"></param>
        /// <param name="rootDir">The root the fpk will go into, used by smakebite to derive the qar-internal path</param>
        /// <param name="fpkReferences"></param>
        /// <returns></returns>
        public static List <ModFpkEntry> BuildFpk(string sourceFpkFolder, string destFpkName, string rootDir, List <string> fpkReferences)
        {
            SnakeBite.Debug.LogLine($"[BuildFpk] {sourceFpkFolder}.");

            List <string>      fpkFiles = new List <string>();
            List <ModFpkEntry> fpkList  = new List <ModFpkEntry>();

            foreach (string fileName in Directory.GetFiles(sourceFpkFolder, "*.*", SearchOption.AllDirectories))
            {
                if (!GzsLib.IsExtensionValidForArchive(fileName, destFpkName))
                {
                    SnakeBite.Debug.LogLine($"[BuildFpk] {fileName} is not a valid file for a {Path.GetExtension(destFpkName)} archive.");
                    continue;
                }
                string inQarName = fileName.Substring(sourceFpkFolder.Length).Replace("\\", "/");//tex actually fpk-internal name, but as fpks are subsets of qars then?
                fpkFiles.Add(inQarName);

                fpkList.Add(new ModFpkEntry()
                {
                    FilePath    = inQarName,
                    FpkFile     = Tools.ToQarPath(destFpkName.Substring(rootDir.Length)),//qar-internal name of fpk
                    ContentHash = Tools.GetMd5Hash(fileName)
                });
            }//foreach filename
            GzsLib.WriteFpkArchive(destFpkName, sourceFpkFolder, fpkFiles, fpkReferences);

            return(fpkList);
        }//BuildFpk
Beispiel #3
0
        public static List <ModFpkEntry> BuildFpk(string FpkFolder, string rootDir)
        {
            string FpkName        = FpkFolder.Substring(FpkFolder.LastIndexOf("\\") + 1).Replace("_fpk", ".fpk");
            string FpkBuildFolder = FpkFolder.Substring(0, FpkFolder.TrimEnd('\\').LastIndexOf("\\"));
            //string FpkXmlFile = FpkBuildFolder + "\\" + FpkName + ".xml";
            string FpkFile = FpkBuildFolder + "\\" + FpkName;
            string FpkType = FpkFolder.Substring(FpkFolder.LastIndexOf("_") + 1);

            List <string> fpkFiles = new List <string>();

            List <ModFpkEntry> fpkList = new List <ModFpkEntry>();

            foreach (string FileName in Directory.GetFiles(FpkFolder, "*.*", SearchOption.AllDirectories))
            {
                string xmlFileName = FileName.Substring(FpkFolder.Length).Replace("\\", "/");
                fpkList.Add(new ModFpkEntry()
                {
                    FilePath = xmlFileName, FpkFile = Tools.ToQarPath(FpkFile.Substring(rootDir.Length)), ContentHash = Tools.GetMd5Hash(FileName)
                });
                fpkFiles.Add(xmlFileName);
            }

            GzsLib.WriteFpkArchive(FpkFile, FpkFolder, fpkFiles);

            return(fpkList);
        }
Beispiel #4
0
        /// <summary>
        /// Merges the new mod files with the existing modded files and vanilla game files.
        /// The resulting file structure is the new _working0 folder to pack as 00.dat
        /// </summary>
        private static void InstallMods(List <string> modFilePaths, SettingsManager manager, List <string> pullFromVanillas, List <string> pullFromMods, ref HashSet <string> zeroFiles, ref List <string> oneFilesList, Dictionary <string, bool> pathUpdatesExist)
        {
            //Assumption: modded packs have already been extracted to _working0 directory - qarEntryEditList
            //Assumption: vanilla packs have already been extracted to _gameFpk directory (during AddToSettings) - fpkEntryRetrievalList
            //theoretically there should be no qar overlap between the _gamefpk(vanilla) and _working0(modded) files
            FastZip  unzipper = new FastZip();
            GameData gameData = manager.GetGameData();

            foreach (string modFilePath in modFilePaths)
            {
                Debug.LogLine($"[Install] Installation started: {Path.GetFileName(modFilePath)}", Debug.LogLevel.Basic);

                Debug.LogLine($"[Install] Unzipping mod .mgsv ({Tools.GetFileSizeKB(modFilePath)} KB)", Debug.LogLevel.Basic);
                unzipper.ExtractZip(modFilePath, "_extr", "(.*?)");

                Debug.LogLine("[Install] Load mod metadata", Debug.LogLevel.Basic);
                ModEntry extractedModEntry = new ModEntry("_extr\\metadata.xml");
                if (pathUpdatesExist[extractedModEntry.Name])
                {
                    Debug.LogLine(string.Format("[Install] Checking for Qar path updates: {0}", extractedModEntry.Name), Debug.LogLevel.Basic);
                    foreach (ModQarEntry modQar in extractedModEntry.ModQarEntries.Where(entry => !entry.FilePath.StartsWith("/Assets/")))
                    {
                        string unhashedName = HashingExtended.UpdateName(modQar.FilePath);
                        if (unhashedName != null)
                        {
                            Debug.LogLine(string.Format("[Install] Update successful: {0} -> {1}", modQar.FilePath, unhashedName), Debug.LogLevel.Basic);

                            string workingOldPath = Path.Combine("_extr", Tools.ToWinPath(modQar.FilePath));
                            string workingNewPath = Path.Combine("_extr", Tools.ToWinPath(unhashedName));
                            if (!Directory.Exists(Path.GetDirectoryName(workingNewPath)))
                            {
                                Directory.CreateDirectory(Path.GetDirectoryName(workingNewPath));
                            }
                            if (!File.Exists(workingNewPath))
                            {
                                File.Move(workingOldPath, workingNewPath);
                            }

                            modQar.FilePath = unhashedName;
                        }
                    }
                }

                GzsLib.LoadModDictionary(extractedModEntry);
                ValidateModEntries(ref extractedModEntry);

                Debug.LogLine("[Install] Check mod FPKs against game .dat fpks", Debug.LogLevel.Basic);
                zeroFiles.UnionWith(MergePacks(extractedModEntry, pullFromVanillas, pullFromMods));
                //foreach (string zeroFile in zeroFiles) Debug.LogLine(string.Format("Contained in zeroFiles: {0}", zeroFile));

                Debug.LogLine("[Install] Copying loose textures to 01.", Debug.LogLevel.Basic);
                InstallLooseFtexs(extractedModEntry, ref oneFilesList);

                Debug.LogLine("[Install] Copying game dir files", Debug.LogLevel.Basic);
                InstallGameDirFiles(extractedModEntry, ref gameData);
            }

            manager.SetGameData(gameData);
        }
Beispiel #5
0
 public static void PromoteBuildFiles(params string[] paths)
 {
     // Promote SB builds
     Debug.LogLine("[SB_Build] Promoting SB_Build files", Debug.LogLevel.Basic);
     foreach (string path in paths)
     {
         GzsLib.PromoteQarArchive(path + build_ext, path);
     }
     
     new SettingsManager(SnakeBiteSettings).UpdateDatHash();
 }
Beispiel #6
0
        /// <summary>
        /// move vanilla 00 files to 01, moves vanilla 01 textures to texture7, cleans snakebite.xml 
        /// as DoWorkEventHandler
        /// </summary>
        public static void backgroundWorker_MergeAndCleanup(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker mergeProcessor = (BackgroundWorker)sender;
            try
            {
                GzsLib.LoadDictionaries();
                ClearBuildFiles(c7Path, t7Path, ZeroPath, OnePath, SnakeBiteSettings, SavePresetPath);
                ClearSBGameDir();
                CleanupFolders();
                
                mergeProcessor.ReportProgress(0, $"Migrating files to new archives ({Tools.GetFileSizeKB(ZeroPath, OnePath)} KB)");
                if (!MoveDatFiles()) //moves vanilla 00 files into 01, excluding foxpatch. 
                {
                    Debug.LogLine("[DatMerge] Failed to complete archive migration. Cancelling...");
                    e.Cancel = true;
                    ClearBuildFiles(c7Path, t7Path, ZeroPath, OnePath);
                    return;
                }

                mergeProcessor.ReportProgress(0, $"Modfying foxfs in chunk0.dat ({Tools.GetFileSizeKB(chunk0Path)} KB)");
                if (!ModifyFoxfs()) // adds lines to foxfs in chunk0.
                {
                    Debug.LogLine("[ModifyFoxfs] Failed to complete Foxfs modification. Cancelling...");
                    e.Cancel = true;
                    ClearBuildFiles(c7Path, t7Path, ZeroPath, OnePath, chunk0Path);
                    return;
                }

                mergeProcessor.ReportProgress(0, "Promoting new archives");
                PromoteBuildFiles(c7Path, t7Path, ZeroPath, OnePath, chunk0Path); // overwrites existing archives with modified archives

                mergeProcessor.ReportProgress(0, "Cleaning database");
                CleanupDatabase();
            }
            catch (Exception f)
            {
                MessageBox.Show(string.Format("An error has occurred while attempting to merge or clean up SnakeBite data: {0}", f), "Exception Occurred", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Debug.LogLine(string.Format("[MergeAndCleanup] Exception Occurred: {0}", f), Debug.LogLevel.Basic);
                Debug.LogLine("[MergeAndCleanup] SnakeBite has failed to merge and clean up SnakeBite data", Debug.LogLevel.Basic);
                e.Cancel = true;
                try
                {
                    ClearBuildFiles(c7Path, t7Path, ZeroPath, OnePath, chunk0Path);
                }
                catch (Exception g)
                {
                    Debug.LogLine(string.Format("[MergeAndCleanup] Exception Occurred: {0}", g), Debug.LogLevel.Basic);
                    Debug.LogLine("[MergeAndCleanup] SnakeBite has failed to remove the build files.", Debug.LogLevel.Basic);
                }
                return;
            }
        }
Beispiel #7
0
        private static void MoveDatFilesClean(SettingsManager manager)
        {
            string sourceName = null;
            string destName = null;
            string destFolder = null;

            // lua files 00 -> 01,    texture files 01 -> texture7,   foxpatch 00 -> 00,   chunkfiles 00 -> chunk7
            Debug.LogLine("[DatMerge] First Time Setup Started", Debug.LogLevel.Debug);
            
            if (manager.SettingsExist()) manager.ClearAllMods();

            List<string> zeroFiles = GzsLib.ExtractArchive<QarFile>(ZeroPath, "_extr");
            List<string> chunk7Files = new List<string>();
            List<string> oneFiles = new List<string>();

            List<string> zeroOut = zeroFiles.ToList();

            foreach (string zeroFile in zeroFiles)
            {
                if (zeroFile == "foxpatch.dat") continue;

                sourceName = Path.Combine("_extr", Tools.ToWinPath(zeroFile));

                if (zeroFile.Contains(".lua"))
                {
                    destName = Path.Combine("_working1", Tools.ToWinPath(zeroFile)); // 00 -> 01
                    oneFiles.Add(zeroFile);
                } else
                {
                    destName = Path.Combine("_working2", Tools.ToWinPath(zeroFile)); // 00 -> chunk7
                    chunk7Files.Add(zeroFile);
                }
                zeroOut.Remove(zeroFile);

                destFolder = Path.GetDirectoryName(destName);
                if (!Directory.Exists(destFolder)) Directory.CreateDirectory(destFolder);
                if (!File.Exists(destName)) File.Move(sourceName, destName);
            }
            
            // Build a_chunk7.dat.SB_Build
            GzsLib.WriteQarArchive(c7Path + build_ext, "_working2", chunk7Files, GzsLib.chunk7Flags);

            // Build a_texture7.dat.SB_Build
            File.Copy(OnePath, t7Path + build_ext, true);

            // Build 00.dat.SB_Build
            GzsLib.WriteQarArchive(ZeroPath + build_ext, "_extr", zeroOut, GzsLib.zeroFlags);

            // Build 01.dat.SB_Build
            GzsLib.WriteQarArchive(OnePath + build_ext, "_working1", oneFiles, GzsLib.oneFlags);
        }
Beispiel #8
0
        public static void GenerateMgsv(string MgsvFile, string ModName, string SourceFolder)
        {
            ModEntry metaData = new ModEntry();

            metaData.Name               = ModName;
            metaData.Author             = "SnakeBite";
            metaData.MGSVersion.Version = "0.0.0.0";
            metaData.SBVersion.Version  = "0.8.0.0";
            metaData.Version            = "[QM]";
            metaData.Description        = "[Generated by SnakeBite]";
            metaData.Website            = "";

            List <ModFpkEntry> fpkEntries = new List <ModFpkEntry>();
            List <ModQarEntry> qarEntries = new List <ModQarEntry>();

            foreach (var File in Directory.GetFiles(SourceFolder, "*", SearchOption.AllDirectories))
            {
                string ShortFileName = File.Substring(SourceFolder.Length + 1);
                if (File.ToLower().Contains(".fpk"))
                {
                    // do fpk
                    var fpkCont = GzsLib.ListArchiveContents <FpkFile>(File);
                    foreach (var fpkFile in fpkCont)
                    {
                        fpkEntries.Add(new ModFpkEntry()
                        {
                            FpkFile    = ShortFileName,
                            FilePath   = fpkFile,
                            SourceType = FileSource.Mod
                        });
                    }
                }
                else
                {
                    // do qar
                    qarEntries.Add(new ModQarEntry()
                    {
                        FilePath = ShortFileName, SourceType = FileSource.Mod
                    });
                }
            }

            metaData.ModQarEntries = qarEntries;
            metaData.ModFpkEntries = fpkEntries;
            metaData.SaveToFile(Path.Combine(SourceFolder, "metadata.xml"));

            FastZip makeZip = new FastZip();

            makeZip.CreateZip(MgsvFile, SourceFolder, true, ".*");
        }
Beispiel #9
0
        private void PopulateBoxes(string DataPath)
        {
            // unpack existing fpks
            foreach (string fpkFile in Directory.GetFiles(DataPath, "*.fpk*", SearchOption.AllDirectories))
            {
                string fpkDir = Path.Combine(Path.GetDirectoryName(fpkFile), Path.GetFileName(fpkFile).Replace(".", "_"));
                if (!Directory.Exists(fpkDir))
                {
                    //extract fpk
                    GzsLib.ExtractArchive <FpkFile>(fpkFile, fpkDir);
                }
            }

            foreach (string modFile in Directory.GetFiles(DataPath, "*.*", SearchOption.AllDirectories))
            {
                string filePath = modFile.Substring(DataPath.Length).Replace("\\", "/");
                if (Tools.IsValidFile(filePath) && filePath != "/metadata.xml")
                {
                    listModFiles.Items.Add(filePath);
                }
            }

            if (File.Exists(Path.Combine(DataPath, "metadata.xml")))
            {
                ModEntry modMetaData = new ModEntry();
                modMetaData.ReadFromFile(Path.Combine(DataPath, "metadata.xml"));

                textModName.Text        = modMetaData.Name;
                textModVersion.Text     = modMetaData.Version;
                textModAuthor.Text      = modMetaData.Author;
                textModWebsite.Text     = modMetaData.Website;
                textModDescription.Text = modMetaData.Description.Replace("\n", "\r\n");
                foreach (string li in comboForVersion.Items)
                {
                    if (modMetaData.MGSVersion.AsString() == li)
                    {
                        comboForVersion.SelectedIndex = comboForVersion.Items.IndexOf(li);
                        break;
                    }
                }
            }

            if (File.Exists(DataPath + "\\readme.txt"))
            {
                StreamReader s      = new StreamReader(DataPath + "\\readme.txt");
                string       readme = s.ReadToEnd();
                textModDescription.Text = readme;
            }
        }
Beispiel #10
0
        public static List <string> ListQarFiles(string PathName)
        {
            List <string> ListQarFolders = new List <string>();
            List <string> ListQarFiles   = new List <string>();

            // Get a list of all folders to check for files (no _fpk/_fpkd)
            foreach (string Directory in Directory.GetDirectories(PathName, "*.*", SearchOption.AllDirectories))
            {
                if (IsArchiveFolder(PathName, Directory))
                {
                    continue;
                }

                if (Directory.Substring(PathName.Length).Contains(ExternalDirName))// tex KLUDGE ignore MGS_TPP
                {
                    continue;
                }

                ListQarFolders.Add(Directory);
            }
            ListQarFolders.Add(PathName);
            // Check all folders for files
            foreach (string Folder in ListQarFolders)
            {
                foreach (string FileName in Directory.GetFiles(Folder))
                {
                    string FilePath = FileName.Substring(Folder.Length);
                    if (!GzsLib.IsExtensionValidForArchive(FileName, ".dat"))
                    {
                        Debug.LogLine($"[BuildArchive] {FileName} is not a valid file for a .dat archive.");
                        continue;
                    }

                    if (!FilePath.Contains("metadata.xml") && !FilePath.Contains("readme.txt"))// ignore xml metadata and readme
                    {
                        ListQarFiles.Add(FileName);
                    }
                }
            }

            return(ListQarFiles);
        }
Beispiel #11
0
 private static void ValidateModEntries(ref ModEntry modEntry)
 {
     Debug.LogLine("[ValidateModEntries] Validating qar entries", Debug.LogLevel.Basic);
     for (int i = modEntry.ModQarEntries.Count - 1; i >= 0; i--)
     {
         ModQarEntry qarEntry = modEntry.ModQarEntries[i];
         if (!GzsLib.IsExtensionValidForArchive(qarEntry.FilePath, ".dat"))
         {
             Debug.LogLine($"[ValidateModEntries] Found invalid file entry {qarEntry.FilePath} for archive {qarEntry.SourceName}", Debug.LogLevel.Basic);
             modEntry.ModQarEntries.RemoveAt(i);
         }
     }
     Debug.LogLine("[ValidateModEntries] Validating fpk entries", Debug.LogLevel.Basic);
     for (int i = modEntry.ModFpkEntries.Count - 1; i >= 0; i--)
     {
         ModFpkEntry fpkEntry = modEntry.ModFpkEntries[i];
         if (!GzsLib.IsExtensionValidForArchive(fpkEntry.FilePath, fpkEntry.FpkFile))
         {
             Debug.LogLine($"[ValidateModEntries] Found invalid file entry {fpkEntry.FilePath} for archive {fpkEntry.FpkFile}", Debug.LogLevel.Basic);
             modEntry.ModFpkEntries.RemoveAt(i);
         }
     }
 }
Beispiel #12
0
        public static List <ModFpkEntry> BuildFpk(string FpkFolder, string rootDir)
        {
            Debug.LogLine($"[BuildFpk] {FpkFolder}.");
            string FpkName        = FpkFolder.Substring(FpkFolder.LastIndexOf("\\") + 1).Replace("_fpk", ".fpk");
            string FpkBuildFolder = FpkFolder.Substring(0, FpkFolder.TrimEnd('\\').LastIndexOf("\\"));
            //string FpkXmlFile = FpkBuildFolder + "\\" + FpkName + ".xml";
            string FpkFile = FpkBuildFolder + "\\" + FpkName;
            string FpkType = FpkFolder.Substring(FpkFolder.LastIndexOf("_") + 1);

            List <string> fpkFiles = new List <string>();

            List <ModFpkEntry> fpkList = new List <ModFpkEntry>();

            foreach (string FileName in Directory.GetFiles(FpkFolder, "*.*", SearchOption.AllDirectories))
            {
                if (!GzsLib.IsExtensionValidForArchive(FileName, FpkName))
                {
                    Debug.LogLine($"[BuildFpk] {FileName} is not a valid file for a {Path.GetExtension(FpkName)} archive.");
                    continue;
                }

                string inQarName = FileName.Substring(FpkFolder.Length).Replace("\\", "/");
                fpkList.Add(new ModFpkEntry()
                {
                    FilePath    = inQarName,
                    FpkFile     = Tools.ToQarPath(FpkFile.Substring(rootDir.Length)),
                    ContentHash = Tools.GetMd5Hash(FileName)
                });
                fpkFiles.Add(inQarName);
            }

            List <string> fpkFilesSorted = GzsLib.SortFpksFiles(FpkType, fpkFiles);

            GzsLib.WriteFpkArchive(FpkFile, FpkFolder, fpkFilesSorted);

            return(fpkList);
        }
Beispiel #13
0
        public static bool InstallMods(List <string> ModFiles, bool skipCleanup = false)
        {
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();

            Debug.LogLine("[Install] Start", Debug.LogLevel.Basic);
            ModManager.ClearBuildFiles(ZeroPath, OnePath, SnakeBiteSettings, SavePresetPath); // deletes any leftover sb_build files that might still be in the directory (ie from a mid-process shutdown)
            ModManager.ClearSBGameDir();                                                      // deletes the game directory sb_build
            ModManager.CleanupFolders();                                                      // deletes the work folders which contain extracted files from 00/01

            if (Properties.Settings.Default.AutosaveRevertPreset == true)
            {
                PresetManager.SavePreset(SavePresetPath + build_ext); // creates a backup preset file sb_build
            }
            else
            {
                Debug.LogLine("[Install] Skipping RevertChanges.MGSVPreset Save", Debug.LogLevel.Basic);
            }
            File.Copy(SnakeBiteSettings, SnakeBiteSettings + build_ext, true); // creates a settings sb_build

            GzsLib.LoadDictionaries();
            List <ModEntry> installEntryList = new List <ModEntry>();

            foreach (string modFile in ModFiles)
            {
                installEntryList.Add(Tools.ReadMetaData(modFile));
            }


            List <string> zeroFiles  = new List <string>();
            bool          hasQarZero = ModManager.hasQarZeroFiles(installEntryList);

            if (hasQarZero)
            {
                zeroFiles = GzsLib.ExtractArchive <QarFile>(ZeroPath, "_working0");
            }

            List <string> oneFiles = null;
            bool          hasFtexs = ModManager.foundLooseFtexs(installEntryList);

            if (hasFtexs)
            {
                oneFiles = GzsLib.ExtractArchive <QarFile>(OnePath, "_working1");
            }

            SettingsManager SBBuildManager = new SettingsManager(SnakeBiteSettings + build_ext);
            var             gameData       = SBBuildManager.GetGameData();

            ModManager.ValidateGameData(ref gameData, ref zeroFiles);

            var zeroFilesHashSet = new HashSet <string>(zeroFiles);

            Debug.LogLine("[Install] Building gameFiles lists", Debug.LogLevel.Basic);
            var baseGameFiles   = GzsLib.ReadBaseData();
            var allQarGameFiles = new List <Dictionary <ulong, GameFile> >();

            allQarGameFiles.AddRange(baseGameFiles);


            try
            {
                ModManager.PrepGameDirFiles();
                List <string> pullFromVanillas; List <string> pullFromMods; Dictionary <string, bool> pathUpdatesExist;

                Debug.LogLine("[Install] Writing FPK data to Settings", Debug.LogLevel.Basic);
                AddToSettingsFpk(installEntryList, SBBuildManager, allQarGameFiles, out pullFromVanillas, out pullFromMods, out pathUpdatesExist);
                InstallMods(ModFiles, SBBuildManager, pullFromVanillas, pullFromMods, ref zeroFilesHashSet, ref oneFiles, pathUpdatesExist);

                if (hasQarZero)
                {
                    zeroFiles = zeroFilesHashSet.ToList();
                    zeroFiles.Sort();
                    GzsLib.WriteQarArchive(ZeroPath + build_ext, "_working0", zeroFiles, GzsLib.zeroFlags);
                }
                if (hasFtexs)
                {
                    oneFiles.Sort();
                    GzsLib.WriteQarArchive(OnePath + build_ext, "_working1", oneFiles, GzsLib.oneFlags);
                }

                ModManager.PromoteGameDirFiles();
                ModManager.PromoteBuildFiles(ZeroPath, OnePath, SnakeBiteSettings, SavePresetPath);

                if (!skipCleanup)
                {
                    ModManager.CleanupFolders();
                    ModManager.ClearSBGameDir();
                }

                stopwatch.Stop();
                Debug.LogLine($"[Install] Installation finished in {stopwatch.ElapsedMilliseconds} ms", Debug.LogLevel.Basic);
                return(true);
            }
            catch (Exception e)
            {
                stopwatch.Stop();
                Debug.LogLine($"[Install] Installation failed at {stopwatch.ElapsedMilliseconds} ms", Debug.LogLevel.Basic);
                Debug.LogLine("[Install] Exception: " + e, Debug.LogLevel.Basic);
                MessageBox.Show("An error has occurred during the installation process and SnakeBite could not install the selected mod(s).\nException: " + e, "Mod(s) could not be installed", MessageBoxButtons.OK, MessageBoxIcon.Error);

                ModManager.ClearBuildFiles(ZeroPath, OnePath, SnakeBiteSettings, SavePresetPath);
                ModManager.CleanupFolders();

                bool restoreRetry = false;
                do
                {
                    try
                    {
                        ModManager.RestoreBackupGameDir(SBBuildManager);
                    }
                    catch (Exception f)
                    {
                        Debug.LogLine("[Uninstall] Exception: " + f, Debug.LogLevel.Basic);
                        restoreRetry = DialogResult.Retry == MessageBox.Show("SnakeBite could not restore Game Directory mod files due to the following exception: {f} \nWould you like to retry?", "Exception Occurred", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);
                    }
                } while (restoreRetry);

                ModManager.ClearSBGameDir();
                return(false);
            }
        }
Beispiel #14
0
        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);
        }
Beispiel #15
0
        private void PopulateBoxes(string modPath)
        {
            // unpack existing fpks if extracted folders don't exist
            foreach (string fpkFile in Directory.GetFiles(modPath, "*.fpk*", SearchOption.AllDirectories))
            {
                //tex chunk0\Assets\tpp\pack\collectible\common\col_common_tpp_fpk\Assets\tpp\pack\resident\resident00.fpkl is the only fpkl, don't know what a fpkl is, but gzcore crashes on it. also checks for xml in case user opened the fpk with gzstool and produced a xml file
                if (fpkFile.EndsWith(".fpkl") || fpkFile.EndsWith(".xml"))
                {
                    continue;
                }

                string fpkDir = Path.Combine(Path.GetDirectoryName(fpkFile), Path.GetFileName(fpkFile).Replace(".", "_"));
                if (!Directory.Exists(fpkDir))
                {
                    //extract fpk
                    GzsLib.ExtractArchive <FpkFile>(fpkFile, fpkDir);
                }
            }

            foreach (string modFile in Directory.GetFiles(modPath, "*.*", SearchOption.AllDirectories))
            {
                string filePath = modFile.Substring(modPath.Length).Replace("\\", "/");
                //GOTCHA: IsValidFile is only roughly accurate for this purpose, but listModFiles is only currently being used as non interactive user feedback so no big issue.
                if ((Tools.IsValidFile(filePath) || filePath.Contains("/GameDir")) && filePath != "/metadata.xml")
                {
                    listModFiles.Items.Add(filePath);
                }
            }

            if (File.Exists(Path.Combine(modPath, "metadata.xml")))
            {
                ModEntry modMetaData = new ModEntry();
                modMetaData.ReadFromFile(Path.Combine(modPath, "metadata.xml"));

                textModName.Text        = modMetaData.Name;
                textModVersion.Text     = modMetaData.Version;
                textModAuthor.Text      = modMetaData.Author;
                textModWebsite.Text     = modMetaData.Website;
                textModDescription.Text = modMetaData.Description.Replace("\n", "\r\n");
                string mgsvVersion  = modMetaData.MGSVersion.AsString();
                bool   foundVersion = false;
                foreach (string li in comboForVersion.Items)
                {
                    if (mgsvVersion == li)
                    {
                        comboForVersion.SelectedIndex = comboForVersion.Items.IndexOf(li);
                        foundVersion = true;
                        break;
                    }
                }
                if (!foundVersion)
                {
                    comboForVersion.Items.Add(mgsvVersion);
                    comboForVersion.Text = mgsvVersion;
                }
            }

            if (File.Exists(modPath + "\\readme.txt"))
            {
                StreamReader s      = new StreamReader(modPath + "\\readme.txt");
                string       readme = s.ReadToEnd();
                textModDescription.Text = readme;
            }
        }
Beispiel #16
0
        public static void BuildArchive(string SourceDir, ModEntry metaData, string outputFilePath)
        {
            Debug.LogLine($"[BuildArchive] {SourceDir}.");
            HashingExtended.ReadDictionary();
            string buildDir = Directory.GetCurrentDirectory() + "\\_build";

            try
            {
                if (Directory.Exists(buildDir))
                {
                    Directory.Delete(buildDir, true);
                }
            }
            catch
            {
                Debug.LogLine(string.Format("[BuildArchive] preexisting _build directory could not be deleted: {0}", buildDir));
            }

            Directory.CreateDirectory("_build");

            List <string> fpkFiles = Directory.GetFiles(SourceDir, "*.fpk*", SearchOption.AllDirectories).ToList();

            for (int i = fpkFiles.Count - 1; i >= 0; i--)
            {
                string fpkFile = fpkFiles[i].Substring(SourceDir.Length + 1);
                if (!fpkFile.StartsWith("Assets"))
                {
                    string updatedFileName = HashingExtended.UpdateName(fpkFile);
                    if (updatedFileName != null)
                    {
                        updatedFileName = SourceDir + updatedFileName.Replace('/', '\\');
                        if (fpkFiles.Contains(updatedFileName))
                        {
                            fpkFiles.Remove(fpkFiles[i]);
                        }
                    }
                }
            }

            List <string> fpkFolders = ListFpkFolders(SourceDir);

            for (int i = fpkFolders.Count - 1; i >= 0; i--)
            {
                string fpkFolder = fpkFolders[i].Substring(SourceDir.Length + 1);
                if (!fpkFolder.StartsWith("Assets"))
                {
                    string updatedFileName = HashingExtended.UpdateName(fpkFolder.Replace("_fpk", ".fpk"));
                    if (updatedFileName != null)
                    {
                        updatedFileName = SourceDir + updatedFileName.Replace('/', '\\');
                        if (fpkFolders.Contains(updatedFileName.Replace(".fpk", "_fpk")) || fpkFiles.Contains(updatedFileName))
                        {
                            MessageBox.Show(string.Format("{0} was not packed or added to the build, because {1} (the unhashed filename of {0}) already exists in the mod directory.", Path.GetFileName(fpkFolders[i]), Path.GetFileName(updatedFileName)));
                            fpkFolders.Remove(fpkFolders[i]);
                        }
                    }
                }
            }

            // check for FPKs that must be built and build
            metaData.ModFpkEntries = new List <ModFpkEntry>();
            List <string> builtFpks = new List <string>();

            foreach (string FpkFullDir in fpkFolders)
            {
                foreach (ModFpkEntry fpkEntry in BuildFpk(FpkFullDir, SourceDir))
                {
                    metaData.ModFpkEntries.Add(fpkEntry);
                    if (!builtFpks.Contains(fpkEntry.FpkFile))
                    {
                        builtFpks.Add(fpkEntry.FpkFile);
                    }
                }
            }

            // check for other FPKs and build fpkentry data
            foreach (string SourceFile in Directory.GetFiles(SourceDir, "*.fpk*", SearchOption.AllDirectories))
            {
                //tex chunk0\Assets\tpp\pack\collectible\common\col_common_tpp_fpk\Assets\tpp\pack\resident\resident00.fpkl is the only fpkl, don't know what a fpkl is, but gzcore crashes on it.
                if (SourceFile.EndsWith(".fpkl") || SourceFile.EndsWith(".xml"))
                {
                    continue;
                }
                string FileName = Tools.ToQarPath(SourceFile.Substring(SourceDir.Length));
                if (!builtFpks.Contains(FileName))
                {
                    // unpack FPK and build FPK list
                    string fpkDir     = Tools.ToWinPath(FileName.Replace(".fpk", "_fpk"));
                    string fpkFullDir = Path.Combine(SourceDir, fpkDir);
                    if (!Directory.Exists(fpkFullDir))
                    {
                        GzsLib.ExtractArchive <FpkFile>(SourceFile, fpkFullDir);
                    }

                    var fpkContents = GzsLib.ListArchiveContents <FpkFile>(SourceFile);
                    foreach (string file in fpkContents)
                    {
                        if (!GzsLib.IsExtensionValidForArchive(file, fpkDir))
                        {
                            Debug.LogLine($"[BuildArchive] {file} is not a valid file for a {Path.GetExtension(fpkDir)} archive.");
                            continue;
                        }

                        metaData.ModFpkEntries.Add(new ModFpkEntry()
                        {
                            FilePath    = file,
                            FpkFile     = FileName,
                            ContentHash = Tools.GetMd5Hash(Path.Combine(SourceDir, fpkDir, Tools.ToWinPath(file)))
                        });
                    }
                }
            }

            // build QAR entries
            List <string> qarFiles = ListQarFiles(SourceDir);

            for (int i = qarFiles.Count - 1; i >= 0; i--)
            {
                string qarFile = qarFiles[i].Substring(SourceDir.Length + 1);
                if (!qarFile.StartsWith("Assets"))
                {
                    string updatedQarName = HashingExtended.UpdateName(qarFile);
                    if (updatedQarName != null)
                    {
                        updatedQarName = SourceDir + updatedQarName.Replace('/', '\\');
                        if (qarFiles.Contains(updatedQarName))
                        {
                            MessageBox.Show(string.Format("{0} was not added to the build, because {1} (the unhashed filename of {0}) already exists in the mod directory.", Path.GetFileName(qarFiles[i]), Path.GetFileName(updatedQarName)));
                            qarFiles.Remove(qarFiles[i]);
                        }
                    }
                }
            }

            metaData.ModQarEntries = new List <ModQarEntry>();
            foreach (string qarFile in qarFiles)
            {
                string subDir      = qarFile.Substring(0, qarFile.LastIndexOf("\\")).Substring(SourceDir.Length).TrimStart('\\'); // the subdirectory for XML output
                string qarFilePath = Tools.ToQarPath(qarFile.Substring(SourceDir.Length));

                if (!Directory.Exists(Path.Combine("_build", subDir)))
                {
                    Directory.CreateDirectory(Path.Combine("_build", subDir));                                                    // create file structure
                }
                File.Copy(qarFile, Path.Combine("_build", Tools.ToWinPath(qarFilePath)), true);

                ulong hash = Tools.NameToHash(qarFilePath);
                metaData.ModQarEntries.Add(new ModQarEntry()
                {
                    FilePath    = qarFilePath,
                    Compressed  = qarFile.EndsWith(".fpk") || qarFile.EndsWith(".fpkd") ? true : false,
                    ContentHash = Tools.GetMd5Hash(qarFile), Hash = hash
                });
            }

            //tex build external entries
            metaData.ModFileEntries = new List <ModFileEntry>();
            var externalFiles = ListExternalFiles(SourceDir);

            foreach (string externalFile in externalFiles)
            {
                string subDir           = externalFile.Substring(0, externalFile.LastIndexOf("\\")).Substring(SourceDir.Length).TrimStart('\\'); // the subdirectory for XML output
                string externalFilePath = Tools.ToQarPath(externalFile.Substring(SourceDir.Length));

                if (!Directory.Exists(Path.Combine("_build", subDir)))
                {
                    Directory.CreateDirectory(Path.Combine("_build", subDir));                                                    // create file structure
                }
                File.Copy(externalFile, Path.Combine("_build", Tools.ToWinPath(externalFilePath)), true);
                string strip = "/" + ExternalDirName;
                if (externalFilePath.StartsWith(strip))
                {
                    externalFilePath = externalFilePath.Substring(strip.Length);
                }
                //ulong hash = Tools.NameToHash(qarFilePath);
                metaData.ModFileEntries.Add(new ModFileEntry()
                {
                    FilePath = externalFilePath, ContentHash = Tools.GetMd5Hash(externalFile)
                });
            }

            metaData.SBVersion.Version = Application.ProductVersion;

            metaData.SaveToFile("_build\\metadata.xml");

            // build archive
            FastZip zipper = new FastZip();

            zipper.CreateZip(outputFilePath, "_build", true, "(.*?)");

            try
            {
                Directory.Delete("_build", true);
            }
            catch (Exception e)
            {
                Debug.LogLine(string.Format("[BuildArchive] _build directory could not be deleted: {0}", e.ToString()));
            }
        }
Beispiel #17
0
        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);
        }
Beispiel #18
0
        public static void BuildArchive(string SourceDir, ModEntry metaData, string outputFilePath)
        {
            string buildDir = Directory.GetCurrentDirectory() + "\\build";

            if (Directory.Exists(buildDir))
            {
                Directory.Delete(buildDir, true);
            }

            Directory.CreateDirectory("_build");

            // check for FPKs that must be built and build
            metaData.ModFpkEntries = new List <ModFpkEntry>();
            List <string> builtFpks = new List <string>();

            foreach (string FpkDir in ListFpkFolders(SourceDir))
            {
                foreach (ModFpkEntry fpkEntry in BuildFpk(FpkDir, SourceDir))
                {
                    metaData.ModFpkEntries.Add(fpkEntry);
                    if (!builtFpks.Contains(fpkEntry.FpkFile))
                    {
                        builtFpks.Add(fpkEntry.FpkFile);
                    }
                }
            }

            // check for other FPKs and build fpkentry data
            foreach (string SourceFile in Directory.GetFiles(SourceDir, "*.fpk*", SearchOption.AllDirectories))
            {
                //tex chunk0\Assets\tpp\pack\collectible\common\col_common_tpp_fpk\Assets\tpp\pack\resident\resident00.fpkl is the only fpkl, don't know what a fpkl is, but gzcore crashes on it.
                if (SourceFile.Contains(".fpkl"))
                {
                    continue;
                }

                string FileName = Tools.ToQarPath(SourceFile.Substring(SourceDir.Length));
                if (!builtFpks.Contains(FileName))
                {
                    // unpack FPK and build FPK list

                    foreach (string file in GzsLib.ListArchiveContents <FpkFile>(SourceFile))
                    {
                        string fpkDir     = Tools.ToWinPath(FileName.Replace(".fpk", "_fpk"));
                        string fpkFullDir = Path.Combine(SourceDir, fpkDir);
                        if (!Directory.Exists(fpkFullDir))
                        {
                            GzsLib.ExtractArchive <FpkFile>(SourceFile, fpkFullDir);
                        }
                        metaData.ModFpkEntries.Add(new ModFpkEntry()
                        {
                            FilePath = file, FpkFile = FileName, ContentHash = Tools.GetMd5Hash(Path.Combine(SourceDir, fpkDir, Tools.ToWinPath(file)))
                        });
                    }
                }
            }

            // build QAR entries
            metaData.ModQarEntries = new List <ModQarEntry>();
            foreach (string qarFile in ListQarFiles(SourceDir))
            {
                string subDir      = qarFile.Substring(0, qarFile.LastIndexOf("\\")).Substring(SourceDir.Length).TrimStart('\\'); // the subdirectory for XML output
                string qarFilePath = Tools.ToQarPath(qarFile.Substring(SourceDir.Length));
                if (!Directory.Exists(Path.Combine("_build", subDir)))
                {
                    Directory.CreateDirectory(Path.Combine("_build", subDir));                                                    // create file structure
                }
                File.Copy(qarFile, Path.Combine("_build", Tools.ToWinPath(qarFilePath)), true);

                ulong hash = Tools.NameToHash(qarFilePath);
                metaData.ModQarEntries.Add(new ModQarEntry()
                {
                    FilePath = qarFilePath, Compressed = qarFile.Substring(qarFile.LastIndexOf(".") + 1).Contains("fpk") ? true : false, ContentHash = Tools.GetMd5Hash(qarFile), Hash = hash
                });
            }

            //tex build external entries
            metaData.ModFileEntries = new List <ModFileEntry>();
            foreach (string externalFile in ListExternalFiles(SourceDir))
            {
                string subDir           = externalFile.Substring(0, externalFile.LastIndexOf("\\")).Substring(SourceDir.Length).TrimStart('\\'); // the subdirectory for XML output
                string externalFilePath = Tools.ToQarPath(externalFile.Substring(SourceDir.Length));

                if (!Directory.Exists(Path.Combine("_build", subDir)))
                {
                    Directory.CreateDirectory(Path.Combine("_build", subDir));                                                    // create file structure
                }
                File.Copy(externalFile, Path.Combine("_build", Tools.ToWinPath(externalFilePath)), true);
                string strip = "/" + ExternalDirName;
                if (externalFilePath.StartsWith(strip))
                {
                    externalFilePath = externalFilePath.Substring(strip.Length);
                }
                //ulong hash = Tools.NameToHash(qarFilePath);
                metaData.ModFileEntries.Add(new ModFileEntry()
                {
                    FilePath = externalFilePath, ContentHash = Tools.GetMd5Hash(externalFile)
                });
            }

            metaData.SBVersion.Version = SnakeBiteVersionStr;

            metaData.SaveToFile("_build\\metadata.xml");

            // build archive
            FastZip zipper = new FastZip();

            zipper.CreateZip(outputFilePath, "_build", true, "(.*?)");

            Directory.Delete("_build", true);
        }
Beispiel #19
0
        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);
            }
        }
Beispiel #20
0
        public static bool UninstallMods(CheckedListBox.CheckedIndexCollection modIndices, bool skipCleanup = false) // Uninstalls mods based on their indices in the list
        {
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();
            Debug.LogLine("[Uninstall] Start", Debug.LogLevel.Basic);

            // initial cleanup
            ModManager.ClearBuildFiles(ZeroPath, OnePath, SnakeBiteSettings, SavePresetPath);
            ModManager.ClearSBGameDir();
            ModManager.CleanupFolders();

            // backup preset build
            if (Properties.Settings.Default.AutosaveRevertPreset == true)
            {
                PresetManager.SavePreset(SavePresetPath + build_ext);
            }
            else
            {
                Debug.LogLine("[Uninstall] Skipping RevertChanges.MGSVPreset Save", Debug.LogLevel.Basic);
            }

            GzsLib.LoadDictionaries();
            File.Copy(SnakeBiteSettings, SnakeBiteSettings + build_ext, true);
            List <ModEntry> mods = SBBuildManager.GetInstalledMods();

            List <ModEntry> selectedMods = new List <ModEntry>();

            foreach (int index in modIndices)
            {
                ModEntry mod = mods[index];
                selectedMods.Add(mod);
            }

            List <string> zeroFiles  = new List <string>();
            bool          hasQarZero = ModManager.hasQarZeroFiles(selectedMods);

            if (hasQarZero)
            {
                // if necessary, extracts 00.dat and creates a list of filenames, which is pruned throughout the uninstall process and repacked at the end.
                zeroFiles = GzsLib.ExtractArchive <QarFile>(ZeroPath, "_working0");
                zeroFiles.RemoveAll(file => file.EndsWith("_unknown"));
            }

            List <string> oneFiles = null;
            bool          hasFtexs = ModManager.foundLooseFtexs(selectedMods);

            if (hasFtexs)
            {
                // if necessary, extracts 01.dat and creates a list of filenames similar to zeroFiles. only textures are pruned from the list.
                oneFiles = GzsLib.ExtractArchive <QarFile>(OnePath, "_working1");
                oneFiles.RemoveAll(file => file.EndsWith("_unknown"));
            }

            //end of qar extraction
            GameData gameData = SBBuildManager.GetGameData();

            ModManager.ValidateGameData(ref gameData, ref zeroFiles);

            Debug.LogLine("[Uninstall] Building gameFiles lists", Debug.LogLevel.Basic);
            var baseGameFiles = GzsLib.ReadBaseData();

            try
            {
                ModManager.PrepGameDirFiles();
                // begin uninstall
                UninstallMods(selectedMods, ref zeroFiles, ref oneFiles);

                if (hasQarZero)
                {
                    zeroFiles.Sort();
                    GzsLib.WriteQarArchive(ZeroPath + build_ext, "_working0", zeroFiles, GzsLib.zeroFlags);
                }

                if (hasFtexs)
                {
                    oneFiles.Sort();
                    GzsLib.WriteQarArchive(OnePath + build_ext, "_working1", oneFiles, GzsLib.oneFlags);
                }
                // end of qar rebuild

                // overwrite old mod data
                ModManager.PromoteGameDirFiles();
                ModManager.PromoteBuildFiles(ZeroPath, OnePath, SnakeBiteSettings, SavePresetPath);

                if (!skipCleanup)
                {
                    ModManager.CleanupFolders();
                    ModManager.ClearSBGameDir();
                }

                Debug.LogLine("[Uninstall] Uninstall complete", Debug.LogLevel.Basic);
                stopwatch.Stop();
                Debug.LogLine($"[Uninstall] Uninstall took {stopwatch.ElapsedMilliseconds} ms", Debug.LogLevel.Basic);
                return(true);
            }
            catch (Exception e)
            {
                Debug.LogLine("[Uninstall] Exception: " + e, Debug.LogLevel.Basic);
                stopwatch.Stop();
                Debug.LogLine($"[Uninstall] Uninstall failed at {stopwatch.ElapsedMilliseconds} ms", Debug.LogLevel.Basic);
                MessageBox.Show("An error has occurred during the uninstallation process and SnakeBite could not uninstall the selected mod(s).\nException: " + e);

                // clean up failed files
                ModManager.ClearBuildFiles(ZeroPath, OnePath, SnakeBiteSettings, SavePresetPath);
                ModManager.CleanupFolders();

                bool restoreRetry = false;
                do
                {
                    try
                    {
                        ModManager.RestoreBackupGameDir(SBBuildManager);
                    }
                    catch (Exception f)
                    {
                        Debug.LogLine("[Uninstall] Exception: " + f, Debug.LogLevel.Basic);
                        restoreRetry = DialogResult.Retry == MessageBox.Show("SnakeBite could not restore Game Directory mod files due to the following exception: {f} \nWould you like to retry?", "Exception Occurred", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);
                    }
                } while (restoreRetry);

                ModManager.ClearSBGameDir();
                return(false);
            }
        }//UninstallMod batch
Beispiel #21
0
        private static HashSet <string> MergePacks(ModEntry extractedModEntry, List <string> pullFromVanillas, List <string> pullFromMods)
        {
            HashSet <string> modQarZeroPaths = new HashSet <string>();

            foreach (ModQarEntry modQar in extractedModEntry.ModQarEntries)
            {
                string workingDestination = Path.Combine("_working0", Tools.ToWinPath(modQar.FilePath));
                if (!Directory.Exists(Path.GetDirectoryName(workingDestination)))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(workingDestination));
                }
                string modQarSource = Path.Combine("_extr", Tools.ToWinPath(modQar.FilePath));
                string existingQarSource;

                if (pullFromMods.FirstOrDefault(e => e == modQar.FilePath) != null)
                {
                    //Debug.LogLine(string.Format("{0}'s Qar file '{1}' will pull from _working0 (modded)", extractedModEntry.Name, modQar.FilePath));
                    existingQarSource = workingDestination;
                }
                else
                {
                    int indexToRemove = pullFromVanillas.FindIndex(m => m == modQar.FilePath); // remove from retrievalfilepaths and add to editlist
                    if (indexToRemove >= 0)
                    {
                        //Debug.LogLine(string.Format("{0}'s Qar file '{1}' will pull from _gameFpk (fresh game file)", extractedModEntry.Name, modQar.FilePath));
                        existingQarSource = Path.Combine("_gameFpk", Tools.ToWinPath(modQar.FilePath));
                        pullFromVanillas.RemoveAt(indexToRemove); pullFromMods.Add(modQar.FilePath);
                    }
                    else
                    {
                        //Debug.LogLine(string.Format("{0}'s Qar file '{1}' is non-native or not mergeable", extractedModEntry.Name, modQar.FilePath));
                        existingQarSource = null;
                        if (modQar.FilePath.EndsWith(".fpk") || modQar.FilePath.EndsWith(".fpkd"))
                        {
                            pullFromMods.Add(modQar.FilePath); // for merging non-native fpk files consecutively
                        }
                    }
                }

                if (existingQarSource != null)
                {
                    var pulledPack = GzsLib.ExtractArchive <FpkFile>(existingQarSource, "_build");
                    var extrPack   = GzsLib.ExtractArchive <FpkFile>(modQarSource, "_build");
                    pulledPack = pulledPack.Union(extrPack).ToList();
                    //foreach(string file in extrPack) Debug.LogLine(string.Format("{0} is listed in the archive extr", file));
                    //TODO: merge referenced from mod archive to (but then that would probably be tricky keeping track of for Unmerge)
                    //I think only fpks have references (not fpkd), but whatev.
                    var fpkReferences = GzsLib.GetFpkReferences(existingQarSource);
                    GzsLib.WriteFpkArchive(workingDestination, "_build", pulledPack, fpkReferences);
                }
                else
                {
                    File.Copy(modQarSource, workingDestination, true);
                }

                if (!modQar.FilePath.Contains(".ftex"))
                {
                    //Debug.LogLine(string.Format("Adding {0}'s Qar file '{1}' to 00.dat", extractedModEntry.Name, modQar.FilePath));
                    modQarZeroPaths.Add(Tools.ToWinPath(modQar.FilePath));
                }
            }

            return(modQarZeroPaths);
        }
Beispiel #22
0
        /// <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);
        }
Beispiel #23
0
        // 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
            }
        }
Beispiel #24
0
        public static bool ModifyFoxfs() // edits the chunk/texture lines in foxfs.dat to accommodate a_chunk7 a_texture7, MGO and GZs data.
        {
            CleanupFolders();

            Debug.LogLine("[ModifyFoxfs] Beginning foxfs.dat check.", Debug.LogLevel.Debug);
            try
            {
                string foxfsInPath = "foxfs.dat";
                string foxfsOutPath = "_extr\\foxfs.dat";

                if (GzsLib.ExtractFile<QarFile>(chunk0Path, foxfsInPath, foxfsOutPath)) //extract foxfs alone, to save time if the changes are already made
                {
                    if (!File.ReadAllText(foxfsOutPath).Contains("a_chunk7.dat")) // checks if there's an indication that it's modified
                    {
                        Debug.LogLine("[ModifyFoxfs] foxfs.dat is unmodified, extracting chunk0.dat.", Debug.LogLevel.Debug);
                        List<string> chunk0Files = GzsLib.ExtractArchive<QarFile>(chunk0Path, "_extr"); //extract chunk0 into _extr


                        string[] linesToAdd = new string[8]
                        {
                    "		<chunk id=\"0\" label=\"old\" qar=\"a_chunk7.dat\" textures=\"a_texture7.dat\"/>",
                    "		<chunk id=\"1\" label=\"cypr\" qar=\"chunk0.dat\" textures=\"texture0.dat\"/>",
                    "		<chunk id=\"2\" label=\"base\" qar=\"chunk1.dat\" textures=\"texture1.dat\"/>",
                    "		<chunk id=\"3\" label=\"afgh\" qar=\"chunk2.dat\" textures=\"texture2.dat\"/>",
                    "		<chunk id=\"4\" label=\"mtbs\" qar=\"chunk3.dat\" textures=\"texture3.dat\"/>",
                    "		<chunk id=\"5\" label=\"mafr\" qar=\"chunk4.dat\" textures=\"texture4.dat\"/>",
                    "		<chunk id=\"6\" label=\"mgo\" qar=\"chunk5_mgo0.dat\" textures=\"texture5_mgo0.dat\"/>",
                    "		<chunk id=\"7\" label=\"gzs\" qar=\"chunk6_gzs0.dat\" textures=\"texture6_gzs0.dat\"/>",
                        };
                        Debug.LogLine("[ModifyFoxfs] Updating foxfs.dat", Debug.LogLevel.Debug);
                        var foxfsLine = File.ReadAllLines(foxfsOutPath).ToList();   // read the file
                        int startIndex = foxfsLine.IndexOf("		<chunk id=\"0\" label=\"cypr\" qar=\"chunk0.dat\" textures=\"texture0.dat\"/>");

                        foxfsLine.RemoveRange(startIndex, 6);
                        foxfsLine.InsertRange(startIndex, linesToAdd);

                        File.WriteAllLines(foxfsOutPath, foxfsLine); // write to file

                        Debug.LogLine("[ModifyFoxfs] repacking chunk0.dat", Debug.LogLevel.Debug);

                        //Build chunk0.dat.SB_Build with modified foxfs
                        GzsLib.WriteQarArchive(chunk0Path + build_ext, "_extr", chunk0Files, GzsLib.chunk0Flags);

                    }
                    else
                    {
                        Debug.LogLine("[ModifyFoxfs] foxfs.dat is already modified", Debug.LogLevel.Debug);
                    }
                }
                else
                {
                    MessageBox.Show(string.Format("Setup cancelled: SnakeBite failed to extract foxfs from chunk0."), "foxfs check failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    Debug.LogLine("[ModifyFoxfs] Process failed: could not check foxfs.dat", Debug.LogLevel.Debug);
                    CleanupFolders();

                    return false;
                }

                Debug.LogLine("[ModifyFoxfs] Archive modification complete.", Debug.LogLevel.Debug);
                CleanupFolders();

                return true;
            }
            catch (Exception e)
            {
                MessageBox.Show(string.Format("An error has occured while modifying foxfs in chunk0: {0}", e), "Exception Occurred", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Debug.LogLine(string.Format("[ModifyFoxfs] Exception Occurred: {0}", e), Debug.LogLevel.Basic);
                Debug.LogLine("[ModifyFoxfs] SnakeBite has failed to modify foxfs in chunk0", Debug.LogLevel.Basic);

                return false;
            }
        }
Beispiel #25
0
        }//InstallGameDirFiles

        private static void AddToSettingsFpk(List <ModEntry> installEntryList, SettingsManager manager, List <Dictionary <ulong, GameFile> > allQarGameFiles, out List <string> PullFromVanillas, out List <string> pullFromMods, out Dictionary <string, bool> pathUpdatesExist)
        {
            GameData gameData = manager.GetGameData();

            pathUpdatesExist = new Dictionary <string, bool>();

            List <string> newModQarEntries = new List <string>();
            List <string> modQarFiles      = manager.GetModQarFiles();

            pullFromMods = new List <string>();
            foreach (ModEntry modToInstall in installEntryList)
            {
                Dictionary <string, string> newNameDictionary = new Dictionary <string, string>();
                int foundUpdate = 0;
                foreach (ModQarEntry modQar in modToInstall.ModQarEntries.Where(entry => !entry.FilePath.StartsWith("/Assets/")))
                {
                    //Debug.LogLine(string.Format("Attempting to update Qar filename: {0}", modQar.FilePath), Debug.LogLevel.Basic);
                    string unhashedName = HashingExtended.UpdateName(modQar.FilePath);
                    if (unhashedName != null)
                    {
                        //Debug.LogLine(string.Format("Success: {0}", unhashedName), Debug.LogLevel.Basic);
                        newNameDictionary.Add(modQar.FilePath, unhashedName);
                        foundUpdate++;

                        modQar.FilePath = unhashedName;
                        if (!pathUpdatesExist.ContainsKey(modToInstall.Name))
                        {
                            pathUpdatesExist.Add(modToInstall.Name, true);
                        }
                        else
                        {
                            pathUpdatesExist[modToInstall.Name] = true;
                        }
                    }
                }
                if (foundUpdate > 0)
                {
                    foreach (ModFpkEntry modFpkEntry in modToInstall.ModFpkEntries)
                    {
                        string unHashedName;
                        if (newNameDictionary.TryGetValue(modFpkEntry.FpkFile, out unHashedName))
                        {
                            modFpkEntry.FpkFile = unHashedName;
                        }
                    }
                }
                else if (!pathUpdatesExist.ContainsKey(modToInstall.Name))
                {
                    pathUpdatesExist.Add(modToInstall.Name, false);
                }

                manager.AddMod(modToInstall);
                //foreach (ModQarEntry modqar in modToInstall.ModQarEntries) Debug.LogLine("Mod Qar in modToInstall: " + modqar.FilePath);
                foreach (ModQarEntry modQarEntry in modToInstall.ModQarEntries) // add qar entries (fpk, fpkd) to GameData if they don't already exist
                {
                    string modQarFilePath = modQarEntry.FilePath;
                    if (!(modQarFilePath.EndsWith(".fpk") || modQarFilePath.EndsWith(".fpkd")))
                    {
                        continue;                                                                         // only pull for Qar's with Fpk's
                    }
                    if (modQarFiles.Any(entry => entry == modQarFilePath))
                    {
                        pullFromMods.Add(modQarFilePath);
                        //Debug.LogLine("Pulling from 00.dat: {0} " + modQarFilePath);
                    }
                    else if (!newModQarEntries.Contains(modQarFilePath))
                    {
                        newModQarEntries.Add(modQarFilePath);
                        //Debug.LogLine("Pulling from base archives: {0} " + modQarFilePath);
                    }
                }
            }
            //Debug.LogLine(string.Format("Foreach nest 1 complete"));
            List <ModFpkEntry> newModFpkEntries = new List <ModFpkEntry>();

            foreach (ModEntry modToInstall in installEntryList)
            {
                foreach (ModFpkEntry modFpkEntry in modToInstall.ModFpkEntries)
                {
                    //Debug.LogLine(string.Format("Checking out {0} from {1}", modFpkEntry.FilePath, modFpkEntry.FpkFile));

                    if (newModQarEntries.Contains(modFpkEntry.FpkFile)) // it isn't already part of the snakebite environment
                    {
                        //Debug.LogLine(string.Format("seeking repair files around {0}", modFpkEntry.FilePath));
                        newModFpkEntries.Add(modFpkEntry);
                    }
                    else
                    {
                        //Debug.LogLine(string.Format("Removing {0} from gameFpkEntries so it will only be listed in the mod's entries", modFpkEntry.FilePath));
                        int indexToRemove = gameData.GameFpkEntries.FindIndex(m => m.FilePath == Tools.ToWinPath(modFpkEntry.FilePath)); // this will remove the gamedata's listing of the file under fpkentries (repair entries), so the filepath will only be listed in the modentry
                        if (indexToRemove >= 0)
                        {
                            gameData.GameFpkEntries.RemoveAt(indexToRemove);
                        }
                    }
                }
            }
            //Debug.LogLine(string.Format("Foreach nest 2 complete"));
            HashSet <ulong> mergeFpkHashes = new HashSet <ulong>();

            PullFromVanillas = new List <string>();
            var repairFpkEntries = new List <ModFpkEntry>();

            foreach (ModFpkEntry newFpkEntry in newModFpkEntries) // this will add the fpkentry listings (repair entries) to the settings xml
            {
                //Debug.LogLine(string.Format("checking {0} for repairs", newFpkEntry.FilePath));
                ulong packHash = Tools.NameToHash(newFpkEntry.FpkFile);
                if (mergeFpkHashes.Contains(packHash))
                {
                    continue;                                        // the process has already plucked this particular qar file
                }
                foreach (var archiveQarGameFiles in allQarGameFiles) // check every archive (except 00) to see if the particular qar file already exists
                {
                    //Debug.LogLine(string.Format("checking archive for an existing qar file"));
                    if (archiveQarGameFiles.Count > 0)
                    {
                        GameFile existingPack = null;
                        archiveQarGameFiles.TryGetValue(packHash, out existingPack);
                        if (existingPack != null) // the qar file is found
                        {
                            //Debug.LogLine(string.Format("Qar file {0} found in {1}. adding to gameqarentries", newFpkEntry.FpkFile, existingPack.QarFile));
                            mergeFpkHashes.Add(packHash);
                            gameData.GameQarEntries.Add(new ModQarEntry {
                                FilePath   = newFpkEntry.FpkFile,
                                SourceType = FileSource.Merged,
                                SourceName = existingPack.QarFile,
                                Hash       = existingPack.FileHash
                            });
                            PullFromVanillas.Add(newFpkEntry.FpkFile);

                            string windowsFilePath = Tools.ToWinPath(newFpkEntry.FpkFile); // Extract the pack file from the vanilla game files, place into _gamefpk for future use
                            string sourceArchive   = Path.Combine(GameDir, "master\\" + existingPack.QarFile);
                            string workingPath     = Path.Combine("_gameFpk", windowsFilePath);
                            if (!Directory.Exists(Path.GetDirectoryName(workingPath)))
                            {
                                Directory.CreateDirectory(Path.GetDirectoryName(workingPath));
                            }

                            GzsLib.ExtractFileByHash <QarFile>(sourceArchive, existingPack.FileHash, workingPath); // extracts the specific .fpk from the game data
                            foreach (string listedFile in GzsLib.ListArchiveContents <FpkFile>(workingPath))
                            {
                                repairFpkEntries.Add(new ModFpkEntry {
                                    FpkFile    = newFpkEntry.FpkFile,
                                    FilePath   = listedFile,
                                    SourceType = FileSource.Merged,
                                    SourceName = existingPack.QarFile
                                });
                                //Debug.LogLine(string.Format("File Listed: {0} in {1}", extractedFile, newFpkEntry.FpkFile));
                            }
                            break;
                        }
                    }
                }
            }
            //Debug.LogLine(string.Format("Foreach nest 3 complete"));
            foreach (ModFpkEntry newFpkEntry in newModFpkEntries) // finally, strip away the modded entries from the repair entries
            {
                //Debug.LogLine(string.Format("checking to remove {0} from gamefpkentries", Tools.ToWinPath(newFpkEntry.FilePath)));
                int indexToRemove = repairFpkEntries.FindIndex(m => m.FilePath == Tools.ToWinPath(newFpkEntry.FilePath));
                if (indexToRemove >= 0)
                {
                    repairFpkEntries.RemoveAt(indexToRemove);
                }
            }
            gameData.GameFpkEntries = gameData.GameFpkEntries.Union(repairFpkEntries).ToList();
            manager.SetGameData(gameData);
        }
Beispiel #26
0
        public static void BuildArchive(string SourceDir, ModEntry metaData, string OutputFile)
        {
            string buildDir = Directory.GetCurrentDirectory() + "\\build";

            if (Directory.Exists(buildDir))
            {
                Directory.Delete(buildDir, true);
            }

            Directory.CreateDirectory("_build");

            // check for FPKs that must be built and build
            metaData.ModFpkEntries = new List <ModFpkEntry>();
            List <string> builtFpks = new List <string>();

            foreach (string FpkDir in ListFpkFolders(SourceDir))
            {
                foreach (ModFpkEntry fpkEntry in BuildFpk(FpkDir, SourceDir))
                {
                    metaData.ModFpkEntries.Add(fpkEntry);
                    if (!builtFpks.Contains(fpkEntry.FpkFile))
                    {
                        builtFpks.Add(fpkEntry.FpkFile);
                    }
                }
            }

            // check for other FPKs and build fpkentry data
            foreach (string SourceFile in Directory.GetFiles(SourceDir, "*.fpk*", SearchOption.AllDirectories))
            {
                string FileName = Tools.ToQarPath(SourceFile.Substring(SourceDir.Length));
                if (!builtFpks.Contains(FileName))
                {
                    // unpack FPK and build FPK list

                    foreach (string file in GzsLib.ListArchiveContents <FpkFile>(SourceFile))
                    {
                        string fpkDir     = Tools.ToWinPath(FileName.Replace(".fpk", "_fpk"));
                        string fpkFullDir = Path.Combine(SourceDir, fpkDir);
                        if (!Directory.Exists(fpkFullDir))
                        {
                            GzsLib.ExtractArchive <FpkFile>(SourceFile, fpkFullDir);
                        }
                        metaData.ModFpkEntries.Add(new ModFpkEntry()
                        {
                            FilePath = file, FpkFile = FileName, ContentHash = Tools.GetMd5Hash(Path.Combine(SourceDir, fpkDir, Tools.ToWinPath(file)))
                        });
                    }
                }
            }

            // build QAR entries
            metaData.ModQarEntries = new List <ModQarEntry>();
            foreach (string qarFile in ListQarFiles(SourceDir))
            {
                string subDir      = qarFile.Substring(0, qarFile.LastIndexOf("\\")).Substring(SourceDir.Length).TrimStart('\\'); // the subdirectory for XML output
                string qarFilePath = Tools.ToQarPath(qarFile.Substring(SourceDir.Length));
                if (!Directory.Exists(Path.Combine("_build", subDir)))
                {
                    Directory.CreateDirectory(Path.Combine("_build", subDir));                                                    // create file structure
                }
                File.Copy(qarFile, Path.Combine("_build", Tools.ToWinPath(qarFilePath)), true);

                ulong hash = Tools.NameToHash(qarFilePath);
                metaData.ModQarEntries.Add(new ModQarEntry()
                {
                    FilePath = qarFilePath, Compressed = qarFile.Substring(qarFile.LastIndexOf(".") + 1).Contains("fpk") ? true : false, ContentHash = Tools.GetMd5Hash(qarFile), Hash = hash
                });
            }

            metaData.SBVersion.Version = "0.8.0.0";

            metaData.SaveToFile("_build\\metadata.xml");

            // build archive
            FastZip zipper = new FastZip();

            zipper.CreateZip(OutputFile, "_build", true, "(.*?)");

            Directory.Delete("_build", true);
        }
Beispiel #27
0
        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);
        }
Beispiel #28
0
        public static List <ModFpkEntry> BuildFpk(string FpkFolder, string rootDir)
        {
            string FpkName        = FpkFolder.Substring(FpkFolder.LastIndexOf("\\") + 1).Replace("_fpk", ".fpk");
            string FpkBuildFolder = FpkFolder.Substring(0, FpkFolder.TrimEnd('\\').LastIndexOf("\\"));
            //string FpkXmlFile = FpkBuildFolder + "\\" + FpkName + ".xml";
            string FpkFile = FpkBuildFolder + "\\" + FpkName;
            string FpkType = FpkFolder.Substring(FpkFolder.LastIndexOf("_") + 1);

            List <string> fpkFiles = new List <string>();

            List <ModFpkEntry> fpkList = new List <ModFpkEntry>();

            foreach (string FileName in Directory.GetFiles(FpkFolder, "*.*", SearchOption.AllDirectories))
            {
                string xmlFileName = FileName.Substring(FpkFolder.Length).Replace("\\", "/");
                fpkList.Add(new ModFpkEntry()
                {
                    FilePath = xmlFileName, FpkFile = Tools.ToQarPath(FpkFile.Substring(rootDir.Length)), ContentHash = Tools.GetMd5Hash(FileName)
                });
                fpkFiles.Add(xmlFileName);
            }

            List <string> fpkFilesSorted = fpkFiles.OrderBy(fileName => Path.GetExtension(fileName)).ThenBy(fileName => fileName).ToList();

            //tex all positions reletively solid except for "bnd", analysis from my ExtensionOrder.lua puts it somewhere between veh and tgt.
            //have put it between des and tgt in line with init.lua RegisterPackageExtensionInfo call
            // RegisterPackageExtensionInfo call seems to mostly match my derived order in reverse - however clo doesnt fit the order and lng isn't in its table.
            //snakebite seems to honor packed order.
            List <string> fpkdExtensionsOrder = new List <string> {
                "fox2", "evf", "parts", "vfxlb", "vfx", "vfxlf", "veh", "frld", "des", "bnd", "tgt", "phsd", "ph", "sim", "clo", "fsd", "sdf", "lua", "lng"
            };

            Dictionary <string, List <string> > filesByExtension = new Dictionary <string, List <string> >();

            if (fpkFilesSorted.Count() > 1)
            {
                if (FpkType == "fpkd")
                {
                    foreach (var fileName in fpkFilesSorted)
                    {
                        var           extension      = Path.GetExtension(fileName).Substring(1);
                        List <string> extensionFiles = null;
                        filesByExtension.TryGetValue(extension, out extensionFiles);
                        if (extensionFiles == null)
                        {
                            extensionFiles = new List <string>();
                            filesByExtension.Add(extension, extensionFiles);
                        }
                        extensionFiles.Add(fileName);
                    }

                    //tex sorting by alphabetical just 'cause. I don't know if there's supposed to be some order within extension groupings.
                    foreach (KeyValuePair <string, List <string> > entry in filesByExtension)
                    {
                        entry.Value.Sort();
                    }

                    fpkFilesSorted = new List <string>();
                    foreach (var extension in fpkdExtensionsOrder)
                    {
                        List <string> extensionFiles = null;
                        filesByExtension.TryGetValue(extension, out extensionFiles);
                        if (extensionFiles != null)
                        {
                            foreach (var fileName in extensionFiles)
                            {
                                fpkFilesSorted.Add(fileName);
                            }
                        }
                    }
                }
            }


            GzsLib.WriteFpkArchive(FpkFile, FpkFolder, fpkFilesSorted);

            return(fpkList);
        }