Example #1
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);
        }
Example #2
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);
        }