// Todo: ME3Exp 5.1: Get rid of this and use the import resolver. It must support a cache so we don't constnatly open packages
        internal static ExportEntry FindExternalAsset(ImportEntry entry, List <ExportEntry> alreadyLoadedPackageEntries, List <IMEPackage> openedPackages)
        {
            //Debug.WriteLine("Finding external asset " + entry.GetFullPath);
            if (entry.Game == MEGame.ME1)
            {
                var    sourcePackageInternalPath = entry.FullPath.Substring(entry.FullPath.IndexOf('.') + 1);
                string baseName = entry.FileRef.FollowLink(entry.idxLink).Split('.')[0].ToUpper() + ".upk"; //Get package filename
                var    preloadedPackageEntry = alreadyLoadedPackageEntries?.FirstOrDefault(x => Path.GetFileName(x.FileRef.FilePath).Equals(baseName, StringComparison.InvariantCultureIgnoreCase));
                if (preloadedPackageEntry == null && MELoadedFiles.GetFilesLoadedInGame(MEGame.ME1).TryGetValue(baseName, out string packagePath))
                {
                    var package = MEPackageHandler.OpenMEPackage(packagePath);
                    if (openedPackages != null && !openedPackages.Contains(package))
                    {
                        openedPackages.Add(package);
                    }

                    var foundExp = package.Exports.FirstOrDefault(exp => exp.FullPath == sourcePackageInternalPath && exp.ClassName == entry.ClassName);
                    if (foundExp != null)
                    {
                        return(foundExp);
                    }
                    if (openedPackages == null)
                    {
                        package.Dispose();
                    }
                }
                else
                {
                    Debug.WriteLine("ME1 External Asset lookup: Using existing preloaded export package");
                    var foundExp = preloadedPackageEntry.FileRef.Exports.FirstOrDefault(exp => exp.FullPath == sourcePackageInternalPath && exp.ClassName == entry.ClassName);
                    if (foundExp != null)
                    {
                        return(foundExp);
                    }
                }
            }
            else
            {
                // Next, split the filename by underscores
                string filenameWithoutExtension = Path.GetFileNameWithoutExtension(entry.FileRef.FilePath).ToLower();
                string containingDirectory      = Path.GetDirectoryName(entry.FileRef.FilePath);
                var    packagesToCheck          = new List <string>();
                var    gameFiles = MELoadedFiles.GetFilesLoadedInGame(entry.Game);

                if (filenameWithoutExtension.StartsWith("bioa_") || filenameWithoutExtension.StartsWith("biod_"))
                {
                    string[] parts = filenameWithoutExtension.Split('_');
                    if (parts.Length >= 2) //BioA_Nor_WowThatsAlot310.pcc
                    {
                        string bioad    = $"{parts[0]}_{parts[1]}.pcc";
                        string filename = Path.Combine(containingDirectory, bioad); //BioA_Nor.pcc
                        if (File.Exists(filename))
                        {
                            packagesToCheck.Add(filename);
                        }
                        else
                        {
                            if (gameFiles.TryGetValue(filename, out string inGamePath))
                            {
                                packagesToCheck.Add(inGamePath);
                            }
                        }

                        string biop = $"BioP_{parts[1]}.pcc";
                        filename = Path.Combine(containingDirectory, biop); //BioP_Nor.pcc
                        if (File.Exists(filename))
                        {
                            packagesToCheck.Add(filename);
                        }
                        else
                        {
                            if (gameFiles.TryGetValue(filename, out string inGamePath))
                            {
                                packagesToCheck.Add(inGamePath);
                            }
                        }
                    }
                }

                // Add globals
                packagesToCheck.Add(Path.Combine(MEDirectories.GetCookedPath(entry.Game), "SFXGame.pcc"));
                packagesToCheck.Add(Path.Combine(MEDirectories.GetCookedPath(entry.Game), "EntryMenu.pcc"));
                packagesToCheck.Add(Path.Combine(MEDirectories.GetCookedPath(entry.Game), entry.Game == MEGame.ME3 ? "Startup.pcc" : "Startup_INT.pcc"));
                packagesToCheck.Add(Path.Combine(MEDirectories.GetCookedPath(entry.Game), "Engine.pcc"));
                packagesToCheck.Add(Path.Combine(MEDirectories.GetCookedPath(entry.Game), "Engine.u")); //ME1

                foreach (string packagePath in packagesToCheck)
                {
                    if (File.Exists(packagePath))
                    {
                        var preloadedPackageEntry = alreadyLoadedPackageEntries?.FirstOrDefault(x => Path.GetFileName(x.FileRef.FilePath).Equals(packagePath, StringComparison.InvariantCultureIgnoreCase));
                        if (preloadedPackageEntry == null)
                        {
                            var sentry = searchPackageForEntry(packagePath, entry.FullPath, entry.ClassName, openedPackages);
                            if (sentry != null)
                            {
                                return(sentry);
                            }
                        }
                        else
                        {
                            Debug.WriteLine("ME2/3 External Asset lookup: Using existing preloaded export package");
                            var foundExp = preloadedPackageEntry.FileRef.Exports.FirstOrDefault(exp => exp.FullPath == entry.FullPath && exp.ClassName == entry.ClassName);
                            if (foundExp != null)
                            {
                                return(foundExp);
                            }
                        }
                    }
                }
            }

            Debug.WriteLine("Could not find external asset: " + entry.FullPath);
            return(null);
        }
Exemple #2
0
 private static string shaderfilePath(MEGame game) => Path.Combine(MEDirectories.GetCookedPath(game), shaderFileName);
Exemple #3
0
 public static string GetCookedPath(GameTarget target) => MEDirectories.GetCookedPath(target.Game, target.TargetPath);
Exemple #4
0
        public static async void StartRestore(MainWindow mw, bool isQuick, Action postRestoreDelegate = null)
        {
            var pd = await mw.ShowProgressAsync("Restoring game", "Preparing to restore game");

            pd.SetIndeterminate();
            await Task.Run(() =>
            {
                if (isQuick)
                {
                    // Nuke the DLC
                    MERLog.Information(@"Quick restore started");
                    pd.SetMessage("Removing randomize DLC component");
                    var dlcModPath = MERFileSystem.GetDLCModPath();
                    if (Directory.Exists(dlcModPath))
                    {
                        MERLog.Information($@"Deleting {dlcModPath}");
                        Utilities.DeleteFilesAndFoldersRecursively(dlcModPath);
                    }

                    mw.DLCComponentInstalled = false;


                    // Restore basegame only files
                    pd.SetMessage("Restoring randomized basegame files");
                    var isControllerModInstalled = SFXGame.IsControllerBasedInstall();

                    var backupPath       = BackupService.GetGameBackupPath(MERFileSystem.Game, out _, false);
                    var gameCookedPath   = M3Directories.GetCookedPath(Locations.GetTarget(MERFileSystem.Game));
                    var backupCookedPath = MEDirectories.GetCookedPath(MERFileSystem.Game, backupPath);
                    foreach (var bgf in MERFileSystem.alwaysBasegameFiles)
                    {
                        var srcPath  = Path.Combine(backupCookedPath, bgf);
                        var destPath = Path.Combine(gameCookedPath, bgf);
                        MERLog.Information($@"Restoring {bgf}");
                        File.Copy(srcPath, destPath, true);
                    }

                    if (isControllerModInstalled)
                    {
                        // We must also restore Coalesced.ini or it will reference a UI that is no longer available and game will not boot
                        MERLog.Information(@"Controller based install detected, also restoring Coalesced.ini to prevent startup crash");
                        File.Copy(Path.Combine(backupPath, "BioGame", "Config", "PC", "Cooked", "Coalesced.ini"), Path.Combine(Locations.GetTarget(MERFileSystem.Game).TargetPath, "BioGame", "Config", "PC", "Cooked", "Coalesced.ini"), true);
                    }

                    // Delete basegame TFC
                    var baseTFC = MERFileSystem.GetTFCPath(false);
                    if (File.Exists(baseTFC))
                    {
                        File.Delete(baseTFC);
                    }

                    // Done!
                }
                else
                {
                    // Full restore
                    var target = Locations.GetTarget(MERFileSystem.Game);
                    MERLog.Information($@"Performing full game restore on {target.TargetPath} target after restore");

                    object syncObj = new object();
                    BackupHandler.GameRestore gr = new BackupHandler.GameRestore(MERFileSystem.Game)
                    {
                        ConfirmationCallback = (title, message) =>
                        {
                            bool response = false;
                            Application.Current.Dispatcher.Invoke(async() =>
                            {
                                response = await mw.ShowMessageAsync(title, message,
                                                                     MessageDialogStyle.AffirmativeAndNegative,
                                                                     new MetroDialogSettings()
                                {
                                    AffirmativeButtonText = "OK",
                                    NegativeButtonText    = "Cancel",
                                }) == MessageDialogResult.Affirmative;
                                lock (syncObj)
                                {
                                    Monitor.Pulse(syncObj);
                                }
                            });
                            lock (syncObj)
                            {
                                Monitor.Wait(syncObj);
                            }

                            return(response);
                        },
                        BlockingErrorCallback = (title, message) => { Application.Current.Dispatcher.Invoke(async() => { await mw.ShowMessageAsync(title, message); }); },
                        RestoreErrorCallback  = (title, message) => { Application.Current.Dispatcher.Invoke(async() => { await mw.ShowMessageAsync(title, message); }); },
                        UpdateStatusCallback  = message =>
                                                Application.Current.Dispatcher.Invoke(() => pd.SetMessage(message)),
                        UpdateProgressCallback = (done, total) =>
                                                 Application.Current.Dispatcher.Invoke(() =>
                        {
                            pd.SetProgress(done * 1d / total);
                            if (total != 0)
                            {
                                TaskbarHelper.SetProgressState(TaskbarProgressBarState.Normal);
                                TaskbarHelper.SetProgress(done * 1.0 / total);
                            }
                        }),
                        SetProgressIndeterminateCallback = indeterminate => Application.Current.Dispatcher.Invoke(() =>
                        {
                            if (indeterminate)
                            {
                                pd.SetIndeterminate();
                            }
                            TaskbarHelper.SetProgressState(indeterminate ? TaskbarProgressBarState.Indeterminate : TaskbarProgressBarState.Normal);
                        }),
                        SelectDestinationDirectoryCallback = (title, message) =>
                        {
                            string selectedPath = null;
                            Application.Current.Dispatcher.Invoke(() =>
                            {
                                // Not sure if this has to be synced
                                CommonOpenFileDialog ofd = new CommonOpenFileDialog()
                                {
                                    Title            = "Select restore destination directory",
                                    IsFolderPicker   = true,
                                    EnsurePathExists = true
                                };
                                if (ofd.ShowDialog() == CommonFileDialogResult.Ok)
                                {
                                    selectedPath = ofd.FileName;
                                }
                            });
                            return(selectedPath);
                        }
                    };
                    gr.PerformRestore(target.TargetPath);
                    mw.DLCComponentInstalled = false;
                    MERLog.Information(@"Reloading target after restore");
                    target.ReloadGameTarget(false, false);
                    mw.SetupTargetDescriptionText();
                }
            }).ContinueWithOnUIThread(async x =>
            {
                TaskbarHelper.SetProgressState(TaskbarProgressBarState.NoProgress);
                await pd.CloseAsync();
                postRestoreDelegate?.Invoke();
            });
        }