public void OnSelectedTargetChanged() { Supercedances.ClearEx(); if (SelectedTarget != null) { // maps DLC folder name -> mount number var mountpriorities = MEDirectories.GetMountPriorities(SelectedTarget); //maps filename to list of DLC in order of precedence var supercedances = MEDirectories.GetFileSupercedances(SelectedTarget).Where(x => x.Value.Count > 1).ToList(); foreach (var supercedance in supercedances) { SupercedanceList sl = new SupercedanceList() { Filename = supercedance.Key, WinningFile = new SupercedanceFile() { DLCName = supercedance.Value.First(), MountPriority = mountpriorities[supercedance.Value.First()], Game = SelectedTarget.Game }, Game = SelectedTarget.Game }; sl.LosingFiles.ReplaceAll(supercedance.Value.Skip(1).Take(supercedance.Value.Count - 1).Select(x => new SupercedanceFile() { DLCName = x, MountPriority = mountpriorities[x], Game = SelectedTarget.Game })); Supercedances.Add(sl); //var dlcname = supercedance.Value //SupercedanceFile winningFile = new SupercedanceFile() //{ // Fi // MountPriority = mountpriorities[], // DLCName = supercedance.Value.First() //}; } } Supercedances.Sort(x => x.Filename); }
private void StartGuiCompatibilityScanner() { NamedBackgroundWorker nbw = new NamedBackgroundWorker(@"GUICompatibilityScanner"); nbw.DoWork += (a, b) => { Percent = 0; ActionString = M3L.GetString(M3L.string_preparingCompatGenerator); ActionSubstring = M3L.GetString(M3L.string_pleaseWait); var installedDLCMods = VanillaDatabaseService.GetInstalledDLCMods(target); var numTotalDLCMods = installedDLCMods.Count; var uiModInstalled = installedDLCMods.Intersect(DLCUIModFolderNames).Any(); var dlcRoot = MEDirectories.DLCPath(target); if (uiModInstalled) { var nonUIinstalledDLCMods = installedDLCMods.Except(DLCUIModFolderNamesIncludingPatch).ToList(); if (nonUIinstalledDLCMods.Count < numTotalDLCMods && nonUIinstalledDLCMods.Count > 0) { //Get UI library bool xbxLibrary = installedDLCMods.Contains(@"DLC_CON_XBX"); bool uiscalinglibrary = installedDLCMods.Contains(@"DLC_CON_UIScaling"); if (!xbxLibrary && !uiscalinglibrary) { uiscalinglibrary = installedDLCMods.Contains(@"DLC_CON_UIScaling_Shared"); } if (xbxLibrary && uiscalinglibrary) { //can't have both! Not supported. Application.Current.Dispatcher.Invoke(delegate { Log.Error(@"Cannot make compat pack: Both ISM and SP Controller are installed, this is not supported."); M3L.ShowDialog(window, M3L.GetString(M3L.string_dialogCannotGenerateCompatPackInvalidConfig), M3L.GetString(M3L.string_invalidConfiguration), MessageBoxButton.OK, MessageBoxImage.Error); OnClosing(DataEventArgs.Empty); }); b.Result = GUICompatibilityThreadResult.INVALID_UI_MOD_CONFIG; return; } void progressCallback(long done, long total) { ActionString = M3L.GetString(M3L.string_downloadingUiLibrary); ActionSubstring = xbxLibrary ? @"DLC_CON_XBX" : @"DLC_CON_UIScaling"; Percent = getPercent(done, total); } var uiLibraryPath = GetUILibraryPath(xbxLibrary ? @"DLC_CON_XBX" : @"DLC_CON_UIScaling", true, progressCallback); if (uiLibraryPath == null) { Log.Error(@"Required UI library could not be downloaded."); Application.Current.Dispatcher.Invoke(delegate { M3L.ShowDialog(window, M3L.GetString(M3L.string_cannotGeneratorCompatPackCouldNotDownload), M3L.GetString(M3L.string_couldNotAcquireUiLibrary), MessageBoxButton.OK, MessageBoxImage.Error); OnClosing(DataEventArgs.Empty); }); b.Result = GUICompatibilityThreadResult.NO_UI_LIBRARY; return; } //Open UI library SevenZipExtractor libraryArchive = new SevenZipExtractor(uiLibraryPath); List <string> libraryGUIs = libraryArchive.ArchiveFileData.Where(x => !x.IsDirectory).Select(x => x.FileName.Substring(Path.GetFileNameWithoutExtension(uiLibraryPath).Length + 1)).Select(x => x.Substring(0, x.Length - 4)).ToList(); //remove / on end too //We have UI mod(s) installed and at least one other DLC mod. var supercedanceList = MEDirectories.GetFileSupercedances(target).Where(x => x.Value.Any(x => !DLCUIModFolderNamesIncludingPatch.Contains(x))).ToDictionary(p => p.Key, p => p.Value); //Find GUIs ConcurrentDictionary <string, string> filesToBePatched = new ConcurrentDictionary <string, string>(); //Dictionary because there is no ConcurrentList. Keys and values are idenitcal. ActionString = M3L.GetString(M3L.string_scanningForGuiExports); ActionSubstring = M3L.GetString(M3L.string_pleaseWait); Percent = 0; int done = 0; string singlesuffix = M3L.GetString(M3L.string_singularFile); string pluralsuffix = M3L.GetString(M3L.string_pluralFiles); Parallel.ForEach(supercedanceList, new ParallelOptions() { MaxDegreeOfParallelism = 4 }, (pair) => { var firstNonUIModDlc = pair.Value.FirstOrDefault(x => !DLCUIModFolderNamesIncludingPatch.Contains(x)); if (firstNonUIModDlc != null) { //Scan file. var packagefile = Path.Combine(dlcRoot, firstNonUIModDlc, target.Game == MEGame.ME3 ? @"CookedPCConsole" : @"CookedPC", pair.Key); Log.Information(@"Scanning file for GFXMovieInfo exports: " + packagefile); if (!File.Exists(packagefile)) { throw new Exception($@"Package file for inspecting GUIs in was not found: {packagefile}"); } var package = MEPackageHandler.OpenMEPackage(packagefile); var guiExports = package.Exports.Where(x => !x.IsDefaultObject && x.ClassName == @"GFxMovieInfo").ToList(); if (guiExports.Count > 0) { //potential item needing replacement //Check GUI library to see if we have anything. foreach (var export in guiExports) { if (libraryGUIs.Contains(export.GetFullPath, StringComparer.InvariantCultureIgnoreCase)) { //match filesToBePatched[packagefile] = packagefile; ActionSubstring = M3L.GetString(M3L.string_interp_XFilesNeedToBePatched, filesToBePatched.Count.ToString()); Log.Information($@"{firstNonUIModDlc} {pair.Key} has GUI export that is in UI library, marking for patching. Trigger: {export.GetFullPath}"); break; } } } } Interlocked.Increment(ref done); Percent = getPercent(done, supercedanceList.Count); }); if (filesToBePatched.Count > 0) { Log.Information(@"A GUI compatibility patch is required for this game configuration"); b.Result = GUICompatibilityThreadResult.REQUIRED; finalGeneratedMod = GenerateCompatibilityPackForFiles(nonUIinstalledDLCMods, filesToBePatched.Keys.ToList(), libraryArchive); b.Result = GUICompatibilityThreadResult.GENERATED_PACK; Application.Current.Dispatcher.Invoke(delegate { mainwindow.LoadMods(finalGeneratedMod); }); //reload to this mod return; } } Log.Information(@"A GUI compatibility patch is not required for this game configuration"); b.Result = GUICompatibilityThreadResult.NOT_REQUIRED; } else { Log.Information(@"No UI mods are installed - no GUI compatibility pack required"); b.Result = GUICompatibilityThreadResult.NO_UI_MODS_INSTALLED; } }; nbw.RunWorkerCompleted += (a, b) => { if (b.Error != null) { Log.Error($@"Exception occured in {nbw.Name} thread: {b.Error.Message}"); } if (b.Result is GUICompatibilityThreadResult gctr) { Analytics.TrackEvent(@"Generated a UI compatibility pack", new Dictionary <string, string>() { { @"Result", gctr.ToString() } }); if (gctr == GUICompatibilityThreadResult.NOT_REQUIRED) { M3L.ShowDialog(mainwindow, M3L.GetString(M3L.string_dialogNoCompatPackRequired), M3L.GetString(M3L.string_noCompatPackRequired), MessageBoxButton.OK); } OnClosing(new DataEventArgs(finalGeneratedMod)); } else { throw new Exception(@"GUI Compatibility generator thread did not return a result! Please report this to ME3Tweaks"); } }; nbw.RunWorkerAsync(); }