// 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); }
private static string shaderfilePath(MEGame game) => Path.Combine(MEDirectories.GetCookedPath(game), shaderFileName);
public static string GetCookedPath(GameTarget target) => MEDirectories.GetCookedPath(target.Game, target.TargetPath);
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(); }); }