Example #1
0
        public void ValidateTargetsME3()
        {
            GlobalTest.Init();
            var root = GlobalTest.GetTestGameFoldersDirectory(Mod.MEGame.ME3);

            Console.WriteLine("TargetTesting: Game directories folder for ME3: " + root);

            var normal = Path.Combine(root, "normal");

            //correct game
            GameTarget gt            = new GameTarget(Mod.MEGame.ME3, normal, false);
            var        failureReason = gt.ValidateTarget();

            Assert.IsNull(failureReason, "GameTarget for ME3 Normal should not have returned a failure string when validating against the correct game. Failure reason returned: " + failureReason);
            Assert.IsTrue(gt.IsValid, "GameTarget for ME3 Normal should have been marked as valid when validating against the correct game, but it wasn't");

            //wrong game
            gt            = new GameTarget(Mod.MEGame.ME1, normal, false);
            failureReason = gt.ValidateTarget();
            Assert.IsNotNull(failureReason, "GameTarget for ME3 Normal should have returned a failure string when validating against the wrong game (ME1), but none was returned");
            Assert.IsFalse(gt.IsValid, "GameTarget for ME3 Normal should have been marked as invalid when validating against the wrong game (ME1), but wasn't");

            gt            = new GameTarget(Mod.MEGame.ME2, normal, false);
            failureReason = gt.ValidateTarget();
            Assert.IsNotNull(failureReason, "GameTarget for ME3 Normal should have returned a failure string when validating against the wrong game (ME2), but none was returned");
            Assert.IsFalse(gt.IsValid, "GameTarget for ME3 Normal should have been marked as invalid when validating against the wrong game (ME2), but wasn't");
        }
Example #2
0
        internal static List <GameTarget> GetCachedTargets(Mod.MEGame game)
        {
            var cacheFile = GetCachedTargetsFile(game);

            if (File.Exists(cacheFile))
            {
                List <GameTarget> targets = new List <GameTarget>();
                foreach (var file in File.ReadAllLines(cacheFile))
                {
                    //Validate game directory
                    GameTarget target        = new GameTarget(game, file, false);
                    var        failureReason = target.ValidateTarget();
                    if (failureReason == null)
                    {
                        targets.Add(target);
                    }
                    else
                    {
                        Log.Error("Cached target for " + target.Game.ToString() + " is invalid: " + failureReason);
                    }
                }

                return(targets);
            }
            else
            {
                return(new List <GameTarget>());
            }
        }
Example #3
0
        private static void handleM3Passthrough()
        {
            if (PassthroughME1Path != null)
            {
                handlePassthrough(MEGame.ME1, PassthroughME1Path);
            }
            if (PassthroughME2Path != null)
            {
                handlePassthrough(MEGame.ME2, PassthroughME2Path);
            }
            if (PassthroughME3Path != null)
            {
                handlePassthrough(MEGame.ME3, PassthroughME3Path);
            }

            PassthroughME1Path = PassthroughME2Path = PassthroughME3Path = null;

            void handlePassthrough(MEGame game, string path)
            {
                if (path != null && Directory.Exists(path))
                {
                    GameTarget gt = new GameTarget(game, path, true, false);
                    var        passThroughValidationResult = gt.ValidateTarget(false);
                    if (passThroughValidationResult != null)
                    {
                        MERLog.Error($@"{game} path passthrough failed game target validation: {passThroughValidationResult}");
                    }
                    else
                    {
                        MERLog.Information($@"Valid passthrough for game {game}. Assigning path.");
                        Locations.SetTarget(gt, false);
                    }
                }
            }
        }
Example #4
0
            private void BeginBackup()
            {
                var targetToBackup = BackupSourceTarget;

                if (!targetToBackup.IsCustomOption)
                {
                    if (Utilities.IsGameRunning(targetToBackup.Game))
                    {
                        M3L.ShowDialog(window, M3L.GetString(M3L.string_interp_cannotBackupGameWhileRunning, Utilities.GetGameName(BackupSourceTarget.Game)), M3L.GetString(M3L.string_gameRunning), MessageBoxButton.OK, MessageBoxImage.Error);
                        return;
                    }
                }
                else
                {
                    // Point to existing game installation
                    Log.Information(@"BeginBackup() with IsCustomOption.");
                    var linkWarning = M3L.ShowDialog(window,
                                                     M3L.GetString(M3L.string_dialog_linkTargetWontBeModdable), M3L.GetString(M3L.string_linkWarning), MessageBoxButton.OKCancel, MessageBoxImage.Warning);
                    if (linkWarning == MessageBoxResult.Cancel)
                    {
                        Log.Information(@"User aborted linking due to dialog");
                        return;
                    }

                    Log.Information(@"Prompting user to select executable of link target");
                    var gameexe = Utilities.PromptForGameExecutable(new[] { Game });
                    if (gameexe == null)
                    {
                        return;
                    }
                    targetToBackup = new GameTarget(Game, Utilities.GetGamePathFromExe(Game, gameexe), false, true);
                    if (AvailableBackupSources.Any(x => x.TargetPath.Equals(targetToBackup.TargetPath, StringComparison.InvariantCultureIgnoreCase)))
                    {
                        // Can't point to an existing modding target
                        Log.Error(@"This target is not valid to point to as a backup: It is listed a modding target already, it must be removed as a target first");
                        M3L.ShowDialog(window, M3L.GetString(M3L.string_interp_dialog_linkFailedAlreadyATarget), M3L.GetString(M3L.string_cannotLinkGameCopy), MessageBoxButton.OK, MessageBoxImage.Error);
                        return;
                    }

                    var validationFailureReason = targetToBackup.ValidateTarget(ignoreCmmVanilla: true);
                    if (!targetToBackup.IsValid)
                    {
                        Log.Error(@"This installation is not valid to point to as a backup: " + validationFailureReason);
                        M3L.ShowDialog(window, M3L.GetString(M3L.string_interp_dialog_linkFailedInvalidTarget, validationFailureReason), M3L.GetString(M3L.string_invalidGameCopy), MessageBoxButton.OK, MessageBoxImage.Error);
                        return;
                    }
                }

                NamedBackgroundWorker nbw = new NamedBackgroundWorker(Game + @"Backup");

                nbw.WorkerReportsProgress = true;
                nbw.ProgressChanged      += (a, b) =>
                {
                    if (b.UserState is double d)
                    {
                        window.TaskBarItemInfoHandler.ProgressValue = d;
                    }
                    else if (b.UserState is TaskbarItemProgressState tbs)
                    {
                        window.TaskBarItemInfoHandler.ProgressState = tbs;
                    }
                };
                nbw.DoWork += (a, b) =>
                {
                    Log.Information(@"Starting the backup thread. Checking path: " + targetToBackup.TargetPath);
                    BackupInProgress = true;
                    bool end = false;

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

                    void nonVanillaFileFoundCallback(string filepath)
                    {
                        Log.Error($@"Non-vanilla file found: {filepath}");
                        nonVanillaFiles.Add(filepath);
                    }

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

                    void inconsistentDLCFoundCallback(string filepath)
                    {
                        if (targetToBackup.Supported)
                        {
                            Log.Error($@"DLC is in an inconsistent state: {filepath}");
                            inconsistentDLC.Add(filepath);
                        }
                        else
                        {
                            Log.Error(@"Detected an inconsistent DLC, likely due to an unofficial copy of the game");
                        }
                    }

                    ProgressVisible       = true;
                    ProgressIndeterminate = true;
                    BackupStatus          = M3L.GetString(M3L.string_validatingBackupSource);
                    Log.Information(@"Checking target is vanilla");
                    bool isVanilla = VanillaDatabaseService.ValidateTargetAgainstVanilla(targetToBackup, nonVanillaFileFoundCallback);

                    Log.Information(@"Checking DLC consistency");
                    bool isDLCConsistent = VanillaDatabaseService.ValidateTargetDLCConsistency(targetToBackup, inconsistentDLCCallback: inconsistentDLCFoundCallback);

                    Log.Information(@"Checking only vanilla DLC is installed");
                    List <string> dlcModsInstalled = VanillaDatabaseService.GetInstalledDLCMods(targetToBackup).Select(x =>
                    {
                        var tpmi = ThirdPartyServices.GetThirdPartyModInfo(x, targetToBackup.Game);
                        if (tpmi != null)
                        {
                            return($@"{x} ({tpmi.modname})");
                        }
                        return(x);
                    }).ToList();
                    List <string> installedDLC   = VanillaDatabaseService.GetInstalledOfficialDLC(targetToBackup);
                    List <string> allOfficialDLC = MEDirectories.OfficialDLC(targetToBackup.Game);

                    if (installedDLC.Count() < allOfficialDLC.Count())
                    {
                        var dlcList = string.Join("\n - ", allOfficialDLC.Except(installedDLC).Select(x => $@"{MEDirectories.OfficialDLCNames(targetToBackup.Game)[x]} ({x})")); //do not localize
                        dlcList = @" - " + dlcList;
                        Log.Information(@"The following dlc will be missing in the backup if user continues: " + dlcList);

                        Application.Current.Dispatcher.Invoke(delegate
                        {
                            var cancelDueToNotAllDLC = M3L.ShowDialog(window, M3L.GetString(M3L.string_dialog_notAllDLCInstalled, dlcList), M3L.GetString(M3L.string_someDlcNotInstalled), MessageBoxButton.YesNo, MessageBoxImage.Warning);
                            if (cancelDueToNotAllDLC == MessageBoxResult.No)
                            {
                                end = true;
                                EndBackup();
                                return;
                            }
                        });
                    }

                    if (end)
                    {
                        return;
                    }
                    if (isVanilla && isDLCConsistent && dlcModsInstalled.Count == 0)
                    {
                        BackupStatus = M3L.GetString(M3L.string_waitingForUserInput);

                        string backupPath = null;
                        if (!targetToBackup.IsCustomOption)
                        {
                            // Creating a new backup
                            nbw.ReportProgress(0, TaskDialogProgressBarState.Paused);

                            Application.Current.Dispatcher.Invoke(delegate
                            {
                                Log.Information(@"Prompting user to select backup destination");

                                CommonOpenFileDialog m = new CommonOpenFileDialog
                                {
                                    IsFolderPicker   = true,
                                    EnsurePathExists = true,
                                    Title            = M3L.GetString(M3L.string_selectBackupDestination)
                                };
                                if (m.ShowDialog() == CommonFileDialogResult.Ok)
                                {
                                    backupPath = m.FileName;
                                    Log.Information(@"Backup path chosen: " + backupPath);

                                    bool okToBackup = validateBackupPath(backupPath, targetToBackup);
                                    if (!okToBackup)
                                    {
                                        end = true;
                                        EndBackup();
                                        return;
                                    }
                                }
                                else
                                {
                                    end = true;
                                    EndBackup();
                                    return;
                                }
                            });
                            if (end)
                            {
                                return;
                            }
                            nbw.ReportProgress(0, TaskbarItemProgressState.Indeterminate);
                        }
                        else
                        {
                            Log.Information(@"Linking existing backup at " + targetToBackup.TargetPath);
                            backupPath = targetToBackup.TargetPath;
                            // Linking existing backup
                            Application.Current.Dispatcher.Invoke(delegate
                            {
                                bool okToBackup = validateBackupPath(targetToBackup.TargetPath, targetToBackup);
                                if (!okToBackup)
                                {
                                    end = true;
                                    EndBackup();
                                    return;
                                }
                            });
                        }

                        if (end)
                        {
                            return;
                        }

                        if (!targetToBackup.IsCustomOption)
                        {
                            #region callbacks and copy code

                            // Copy to new backup
                            void fileCopiedCallback()
                            {
                                ProgressValue++;
                                if (ProgressMax > 0)
                                {
                                    nbw.ReportProgress(0, ProgressValue * 1.0 / ProgressMax);
                                }
                            }

                            string dlcFolderpath   = MEDirectories.DLCPath(targetToBackup) + '\\';
                            int    dlcSubStringLen = dlcFolderpath.Length;

                            bool aboutToCopyCallback(string file)
                            {
                                try
                                {
                                    if (file.Contains(@"\cmmbackup\"))
                                    {
                                        return(false);                               //do not copy cmmbackup files
                                    }
                                    if (file.StartsWith(dlcFolderpath, StringComparison.InvariantCultureIgnoreCase))
                                    {
                                        //It's a DLC!
                                        string dlcname             = file.Substring(dlcSubStringLen);
                                        var    dlcFolderNameEndPos = dlcname.IndexOf('\\');
                                        if (dlcFolderNameEndPos > 0)
                                        {
                                            dlcname = dlcname.Substring(0, dlcFolderNameEndPos);
                                            if (MEDirectories.OfficialDLCNames(targetToBackup.Game)
                                                .TryGetValue(dlcname, out var hrName))
                                            {
                                                BackupStatusLine2 = M3L.GetString(M3L.string_interp_backingUpX,
                                                                                  hrName);
                                            }
                                            else
                                            {
                                                BackupStatusLine2 = M3L.GetString(M3L.string_interp_backingUpX,
                                                                                  dlcname);
                                            }
                                        }
                                        else
                                        {
                                            // Loose files in the DLC folder
                                            BackupStatusLine2 = M3L.GetString(M3L.string_interp_backingUpX,
                                                                              M3L.GetString(M3L.string_basegame));
                                        }
                                    }
                                    else
                                    {
                                        //It's basegame
                                        if (file.EndsWith(@".bik"))
                                        {
                                            BackupStatusLine2 = M3L.GetString(M3L.string_interp_backingUpX,
                                                                              M3L.GetString(M3L.string_movies));
                                        }
                                        else if (new FileInfo(file).Length > 52428800)
                                        {
                                            BackupStatusLine2 = M3L.GetString(M3L.string_interp_backingUpX,
                                                                              Path.GetFileName(file));
                                        }
                                        else
                                        {
                                            BackupStatusLine2 = M3L.GetString(M3L.string_interp_backingUpX,
                                                                              M3L.GetString(M3L.string_basegame));
                                        }
                                    }
                                }
                                catch (Exception e)
                                {
                                    Crashes.TrackError(e, new Dictionary <string, string>()
                                    {
                                        { @"dlcFolderpath", dlcFolderpath },
                                        { @"dlcSubStringLen", dlcSubStringLen.ToString() },
                                        { @"file", file }
                                    });
                                }

                                return(true);
                            }

                            void totalFilesToCopyCallback(int total)
                            {
                                ProgressValue         = 0;
                                ProgressIndeterminate = false;
                                ProgressMax           = total;
                                nbw.ReportProgress(0, TaskbarItemProgressState.Normal);
                            }

                            BackupStatus = M3L.GetString(M3L.string_creatingBackup);
                            Log.Information($@"Backing up {targetToBackup.TargetPath} to {backupPath}");
                            nbw.ReportProgress(0, TaskbarItemProgressState.Normal);
                            CopyDir.CopyAll_ProgressBar(new DirectoryInfo(targetToBackup.TargetPath),
                                                        new DirectoryInfo(backupPath),
                                                        totalItemsToCopyCallback: totalFilesToCopyCallback,
                                                        aboutToCopyCallback: aboutToCopyCallback,
                                                        fileCopiedCallback: fileCopiedCallback,
                                                        ignoredExtensions: new[] { @"*.pdf", @"*.mp3" });
                            #endregion
                        }

                        // Write key
                        switch (Game)
                        {
                        case Mod.MEGame.ME1:
                        case Mod.MEGame.ME2:
                            Utilities.WriteRegistryKey(App.BACKUP_REGISTRY_KEY, Game + @"VanillaBackupLocation",
                                                       backupPath);
                            break;

                        case Mod.MEGame.ME3:
                            Utilities.WriteRegistryKey(App.REGISTRY_KEY_ME3CMM, @"VanillaCopyLocation",
                                                       backupPath);
                            break;
                        }

                        var cmmvanilla = Path.Combine(backupPath, @"cmm_vanilla");
                        if (!File.Exists(cmmvanilla))
                        {
                            Log.Information($@"Writing cmm_vanilla to " + cmmvanilla);
                            File.Create(cmmvanilla).Close();
                        }

                        Log.Information($@"Backup completed.");

                        Analytics.TrackEvent(@"Created a backup", new Dictionary <string, string>()
                        {
                            { @"Game", Game.ToString() },
                            { @"Result", @"Success" },
                            { @"Type", targetToBackup.IsCustomOption ? @"Linked" : @"Copy" }
                        });

                        EndBackup();
                        return;
                    }


                    if (!isVanilla)
                    {
                        //Show UI for non vanilla
                        Analytics.TrackEvent(@"Created a backup", new Dictionary <string, string>()
                        {
                            { @"Game", Game.ToString() },
                            { @"Result", @"Failure, Game modified" }
                        });
                        b.Result = (nonVanillaFiles, M3L.GetString(M3L.string_cannotBackupModifiedGame),
                                    M3L.GetString(M3L.string_followingFilesDoNotMatchTheVanillaDatabase));
                    }
                    else if (!isDLCConsistent)
                    {
                        Analytics.TrackEvent(@"Created a backup", new Dictionary <string, string>()
                        {
                            { @"Game", Game.ToString() },
                            { @"Result", @"Failure, DLC inconsistent" }
                        });
                        if (targetToBackup.Supported)
                        {
                            b.Result = (inconsistentDLC, M3L.GetString(M3L.string_inconsistentDLCDetected),
                                        M3L.GetString(M3L.string_dialogTheFollowingDLCAreInAnInconsistentState));
                        }
                        else
                        {
                            b.Result = (M3L.GetString(M3L.string_inconsistentDLCDetected),
                                        M3L.GetString(M3L.string_inconsistentDLCDetectedUnofficialGame));
                        }
                    }
                    else if (dlcModsInstalled.Count > 0)
                    {
                        Analytics.TrackEvent(@"Created a backup", new Dictionary <string, string>()
                        {
                            { @"Game", Game.ToString() },
                            { @"Result", @"Failure, DLC mods found" }
                        });
                        b.Result = (dlcModsInstalled, M3L.GetString(M3L.string_dlcModsAreInstalled),
                                    M3L.GetString(M3L.string_dialogDLCModsWereDetectedCannotBackup));
                    }
                    EndBackup();
                };
                nbw.RunWorkerCompleted += (a, b) =>
                {
                    if (b.Error != null)
                    {
                        Log.Error($@"Exception occured in {nbw.Name} thread: {b.Error.Message}");
                    }
                    window.TaskBarItemInfoHandler.ProgressState = TaskbarItemProgressState.None;
                    if (b.Result is (List <string> listItems, string title, string text))
                    {
                        ListDialog ld = new ListDialog(listItems, title, text, window);
                        ld.Show();
                    }
                    else if (b.Result is (string errortitle, string message))
                    {
                        M3L.ShowDialog(window, message, errortitle, MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                    CommandManager.InvalidateRequerySuggested();
                };
                nbw.RunWorkerAsync();
            }
        private void Migration_ContentRendered(object sender, EventArgs e)
        {
            NamedBackgroundWorker nbw = new NamedBackgroundWorker(@"ME3CMMMigration");

            nbw.DoWork += (a, b) =>
            {
                bool cleanup  = false;
                bool migrated = true;
                Log.Information(@">>>> ME3CMMMigration Thread");
                Log.Information(@"Validate ME3CMM folders and files");
                var exeDir = Utilities.GetMMExecutableDirectory();


                var modsDir = Path.Combine(exeDir, @"mods");
                var dataDir = Path.Combine(exeDir, @"data");
                try
                {
                    if (Directory.Exists(modsDir) && Directory.Exists(dataDir))
                    {
                        Log.Information(@"mods and data dir exist.");
                        // 1. MIGRATE MODS
                        Log.Information(@"Step 1: Migrate mods");
                        MigratingModsTask.SetInProgress();

                        var targetModLibrary = Utilities.GetModsDirectory();

                        targetModLibrary = Path.Combine(targetModLibrary, @"ME3");
                        if (!Directory.Exists(targetModLibrary))
                        {
                            Log.Information(@"Creating target mod library directory: " + targetModLibrary);
                            Directory.CreateDirectory(targetModLibrary);
                        }

                        var sameRoot = Path.GetPathRoot(targetModLibrary) == Path.GetPathRoot(modsDir);

                        var directoriesInModsDir = Directory.GetDirectories(modsDir);

                        var numToMigrate = directoriesInModsDir.Count(x => File.Exists(Path.Combine(x, @"moddesc.ini")));
                        var numMigrated  = 0;

                        foreach (var modDirToMove in directoriesInModsDir)
                        {
                            var moddesc = Path.Combine(modDirToMove, @"moddesc.ini");
                            if (File.Exists(moddesc))
                            {
                                numMigrated++;
                                MigratingModsTask.TaskText = M3L.GetString(M3L.string_interp_migratingModsXoFY, numMigrated, numToMigrate);
                                //Migrate this folder
                                var targetDir = Path.Combine(targetModLibrary, Path.GetFileName(modDirToMove));
                                Log.Information($@"Migrating mod into ME3 directory: {modDirToMove} -> {targetDir}");
                                if (!Directory.Exists(targetDir))
                                {
                                    if (sameRoot)
                                    {
                                        Directory.Move(modDirToMove, targetDir);
                                    }
                                    else
                                    {
                                        Log.Information(@" >> Copying existing mod directory");
                                        Directory.CreateDirectory(targetDir);
                                        CopyDir.CopyAll_ProgressBar(new DirectoryInfo(modDirToMove), new DirectoryInfo(targetDir));
                                        Log.Information(@" >> Deleting existing directory");
                                        Utilities.DeleteFilesAndFoldersRecursively(modDirToMove);
                                    }

                                    Log.Information($@"Migrated {modDirToMove}");
                                }
                                else
                                {
                                    Log.Warning(@"Target directory already exists! Not migrating this directory.");
                                }
                            }
                        }

                        MigratingModsTask.SetDone();
                        Log.Information(@"Step 1: Finished mod migration");

                        // 2. MIGRATE SETTINGS
                        MigratingSettings.SetInProgress();
                        Log.Information(@"Step 2: Begin settings migration");
                        var me3cmminif = Path.Combine(exeDir, @"me3cmm.ini");
                        if (File.Exists(me3cmminif))
                        {
                            Log.Information(@"Migrating me3cmm.ini settings");
                            IniData me3cmmini = new FileIniDataParser().ReadFile(me3cmminif);
                            var     updaterServiceUsername = me3cmmini[@"UpdaterService"][@"username"];
                            if (string.IsNullOrWhiteSpace(Settings.UpdaterServiceUsername) && !string.IsNullOrWhiteSpace(updaterServiceUsername))
                            {
                                Settings.UpdaterServiceUsername = updaterServiceUsername;
                                Log.Information(@"Migrated Updater Service Username: "******"UpdaterService"][@"manifestspath"];
                            if (string.IsNullOrWhiteSpace(Settings.UpdaterServiceManifestStoragePath) && !string.IsNullOrWhiteSpace(manifestsPath))
                            {
                                Settings.UpdaterServiceManifestStoragePath = manifestsPath;
                                Log.Information(@"Migrated Updater Service Manifests Path: " + manifestsPath);
                            }

                            var lzmaStoragePath = me3cmmini[@"UpdaterService"][@"lzmastoragepath"];
                            if (string.IsNullOrWhiteSpace(Settings.UpdaterServiceLZMAStoragePath) && !string.IsNullOrWhiteSpace(lzmaStoragePath))
                            {
                                Settings.UpdaterServiceLZMAStoragePath = lzmaStoragePath;
                                Log.Information(@"Migrated Updater Service LZMA Storage Path: " + lzmaStoragePath);
                            }

                            //Modmaker Auto Injections
                            var controllerModOption = me3cmmini[@"Settings"][@"controllermoduser"];
                            if (Settings.ModMakerControllerModOption == false && controllerModOption == "1")
                            {
                                Settings.ModMakerControllerModOption = true; //Set to true (default is false)
                                Log.Information(@"Migrated Auto install controller mixins for ModMaker (true)");
                            }

                            var keybindsInjectionOption = me3cmmini[@"Settings"][@"autoinjectkeybinds"];
                            if (Settings.ModMakerAutoInjectCustomKeybindsOption == false && keybindsInjectionOption == "1")
                            {
                                Settings.ModMakerAutoInjectCustomKeybindsOption = true; //Set to true (default is false)
                                Log.Information(@"Migrated Auto inject keybinds for ModMaker (true)");
                            }

                            //Settings.Save();
                        }

                        //Migrate BIOGAME_DIRECTORIES
                        var biogameDirsF = Path.Combine(dataDir, @"BIOGAME_DIRECTORIES");
                        if (File.Exists(biogameDirsF))
                        {
                            var biodirs = File.ReadAllLines(biogameDirsF);
                            foreach (var line in biodirs)
                            {
                                var gamepath = Directory.GetParent(line).FullName;
                                Log.Information(@"Validating ME3CMM target: " + gamepath);
                                GameTarget t             = new GameTarget(MEGame.ME3, gamepath, false);
                                var        failureReason = t.ValidateTarget();
                                if (failureReason == null)
                                {
                                    Utilities.AddCachedTarget(t);
                                }
                                else
                                {
                                    Log.Error($@"Not migrating invalid target {gamepath}: {failureReason}");
                                }
                            }
                        }

                        //Migrate ALOT Installer, if found
                        var alotInstallerDir = Path.Combine(dataDir, @"ALOTInstaller");
                        if (Directory.Exists(alotInstallerDir))
                        {
                            Log.Information(@"Migrating ALOTInstaller tool");
                            var externalToolsALOTInstaller = Path.Combine(dataDir, @"ExternalTools", @"ALOTInstaller");
                            Directory.CreateDirectory(Path.Combine(dataDir, @"ExternalTools"));
                            Directory.Move(alotInstallerDir, externalToolsALOTInstaller);
                            Log.Information(@"Migrated ALOTInstaller to ExternalTools");
                        }

                        //Migrate ME3Explorer, if found
                        var me3explorerDir = Path.Combine(dataDir, @"ME3Explorer");
                        if (Directory.Exists(me3explorerDir))
                        {
                            Log.Information(@"Migrating ME3Explorer tool");
                            var externalToolsME3ExplorerDir = Path.Combine(dataDir, @"ExternalTools", @"ME3Explorer");
                            Directory.CreateDirectory(Path.Combine(dataDir, @"ExternalTools"));
                            Directory.Move(me3explorerDir, externalToolsME3ExplorerDir);
                            Log.Information(@"Migrated ME3Explorer to ExternalTools");
                        }

                        //Migrate cached modmaker mods
                        var modmakerCacheDir = Path.Combine(dataDir, @"modmaker", @"cache");
                        if (Directory.Exists(modmakerCacheDir))
                        {
                            var modmakerXmls = Directory.GetFiles(modmakerCacheDir, @"*.xml");
                            if (modmakerXmls.Any())
                            {
                                var mmNewCacheDir = Utilities.GetModmakerDefinitionsCache();
                                Log.Information(@"Migrating ME3Tweaks ModMaker cached files");
                                foreach (var f in modmakerXmls)
                                {
                                    var fname    = Path.GetFileName(f);
                                    var destName = Path.Combine(mmNewCacheDir, fname);
                                    if (!File.Exists(destName))
                                    {
                                        Log.Information(@"Migrating modmaker mod delta definition file " + fname);
                                        File.Move(f, destName);
                                    }
                                }

                                Log.Information(@"Migrated ModMaker cached files");
                            }
                        }


                        //MIGRATE 7z.dll - this will only perform an interim fix (maybe network failure?) as we use 19.0 and ME3MM used 18.05
                        var me3mm7z  = Path.Combine(dataDir, @"tools\ModManagerCommandLine\x64\7z.dll");
                        var target7z = Utilities.Get7zDllPath();
                        if (File.Exists(me3mm7z) && !File.Exists(target7z))
                        {
                            Log.Information($@"Copying ME3MM 7z.dll to ME3Tweaks Mod Manager dll location: {me3mm7z} -> {target7z}");
                            File.Copy(me3mm7z, target7z, true);
                            Log.Information(@"Copied ME3MM 7z dll");
                        }

                        // Migrate DLC_AUTH_FAIL
                        var me3mmAuthFail  = Path.Combine(dataDir, @"help\DLC_AUTH_FAIL.png");
                        var targetAuthFail = Path.Combine(Utilities.GetLocalHelpResourcesDirectory(), @"DLC_AUTH_FAIL.png");
                        if (File.Exists(me3mmAuthFail) && !File.Exists(targetAuthFail))
                        {
                            Log.Information($@"Copying DLC_AUTH_FAIL help resource to ME3Tweaks Mod Manager help resources location: {me3mmAuthFail} -> {targetAuthFail}");
                            File.Copy(me3mmAuthFail, targetAuthFail, true);
                            Log.Information(@"Copied DLC_AUTH_FAIL");
                        }

                        //MIGRATE MOD GROUPS (batch install queues)
                        var modGroupsDir = Path.Combine(dataDir, @"modgroups");
                        if (Directory.Exists(modGroupsDir))
                        {
                            Log.Information(@"Migrating batch mod groups");
                            var queues = Directory.EnumerateFiles(modGroupsDir, @"*.txt").ToList();
                            foreach (var queue in queues)
                            {
                                var biqDest = Path.Combine(Utilities.GetBatchInstallGroupsFolder(), Path.GetFileName(queue));
                                Log.Information($@"Migrating mod install group: {queue} -> {biqDest}");
                                File.Move(queue, biqDest, true);
                                Log.Information(@"Migrated " + Path.GetFileName(queue));
                            }
                        }


                        // MIGRATE override
                        var overrideDir = Path.Combine(dataDir, @"override");
                        if (Directory.Exists(overrideDir))
                        {
                            Log.Information(@"Migrating override");
                            var filesInKBDir = Directory.EnumerateFiles(overrideDir, @"*.xml").ToList();
                            foreach (var file in filesInKBDir)
                            {
                                var keybindDir = Path.Combine(Utilities.GetKeybindsOverrideFolder(), @"me3-" + Path.GetFileName(file));
                                Log.Information($@"Migrating keybinds override: {file} -> {keybindDir}");
                                File.Move(file, keybindDir, true);
                                Log.Information(@"Migrated " + Path.GetFileName(file));
                            }
                        }

                        MigratingSettings.SetDone();

                        Log.Information(@"Step 2: Finished settings migration");
                        // 3. CLEANUP
                        App.Current.Dispatcher.Invoke(delegate { cleanup = M3L.ShowDialog(null, M3L.GetString(M3L.string_dialog_performMe3cmmCleanup), M3L.GetString(M3L.string_performCleanupQuestion), MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.Yes) == MessageBoxResult.Yes; });
                        if (cleanup)
                        {
                            Log.Information(@"Step 3: Cleaning up");
                            CleaningUpTask.SetInProgress();
                            var directoriesInDataDir = Directory.GetFileSystemEntries(dataDir);
                            foreach (var entry in directoriesInDataDir)
                            {
                                var name = Path.GetFileName(entry);
                                if (Directory.Exists(entry))
                                {
                                    switch (name.ToLower())
                                    {
                                    case @"deployed mods":
                                    case @"externaltools": // Created by M3 at this point
                                    case @"patch_001_extracted":
                                    case @"pccdumps":      //guess these might be useful
                                        continue;

                                    default:
                                        try
                                        {
                                            Log.Information(@"Deleting directory: " + entry);
                                            Utilities.DeleteFilesAndFoldersRecursively(entry, true);
                                        }
                                        catch (Exception e)
                                        {
                                            Log.Error($@"Unable to delete item in data directory: {entry}, reason: {e.Message}");
                                        }

                                        break;
                                    }
                                }
                                else if (File.Exists(entry))
                                {
                                    try
                                    {
                                        Log.Information(@"Cleanup: Deleting file " + entry);
                                        File.Delete(entry);
                                    }
                                    catch (Exception e)
                                    {
                                        Log.Error($@"Unable to delete {entry}: {e.Message}");
                                    }
                                }
                            }

                            // Install redirect to ensure user shortcuts continue to work
                            var me3cmmPath = Path.Combine(exeDir, @"ME3CMM.exe");
                            Log.Information(@"Writing redirector to " + me3cmmPath);
                            Utilities.ExtractInternalFile(@"MassEffectModManagerCore.updater.ME3CMM.exe", me3cmmPath, true);
                        }
                        else
                        {
                            Log.Information(@"Skipping step 3: cleanup due to user request.");
                        }

                        CleaningUpTask.SetDone();
                        Log.Information(@"Step 3: Cleaned up");
                        Thread.Sleep(3000);
                    }
                    else
                    {
                        migrated = false;
                        Log.Error(@"mods and/or data dir don't exist! We will not attempt migration.");
                    }
                }
                catch (Exception e)
                {
                    migrated = false;
                    Log.Error(@"Error in migration: " + e.Message);
                    Crashes.TrackError(e);
                }
                Analytics.TrackEvent(@"ME3CMM Migration", new Dictionary <string, string>()
                {
                    { @"Migrated", migrated.ToString() },
                    { @"Cleaned up", cleanup.ToString() },
                });
                Log.Information(@"<<<< Exiting ME3CMMMigration Thread");
            };
            nbw.RunWorkerCompleted += (a, b) =>
            {
                if (b.Error != null)
                {
                    Log.Error($@"Exception occurred in {nbw.Name} thread: {b.Error.Message}");
                }
                Log.Information(@"Migration has completed.");
                M3L.ShowDialog(null, M3L.GetString(M3L.string_dialog_me3cmmMigrationCompleted));
                Close();
            };
            nbw.RunWorkerAsync();
        }
Example #6
0
        public void TestBuildingExtractionQueues()
        {
            GlobalTest.Init();

            Console.WriteLine("Fetching third party services");
            App.ThirdPartyImportingService      = OnlineContent.FetchThirdPartyImportingService();
            App.ThirdPartyIdentificationService = OnlineContent.FetchThirdPartyIdentificationManifest();

            var        compressedModsDirectory = Path.Combine(GlobalTest.GetTestDataDirectory(), "compressedmods");
            List <Mod> modsFoundInArchive      = new List <Mod>();

            void addModCallback(Mod m)
            {
                Console.WriteLine($"Found mod in archive: {m.ModName}");
                modsFoundInArchive.Add(m);
            }

            void failedModCallback(Mod m)
            {
                //Console.WriteLine($"A mod failed to load. This may be expected: {m.ModName}");
            }

            void logMessageCallback(string m)
            {
                Console.WriteLine(m);
            }

            #region Get Targets
            List <GameTarget> targets = new List <GameTarget>();
            var root = GlobalTest.GetTestGameFoldersDirectory(Mod.MEGame.ME1);
            foreach (var d in Directory.GetDirectories(root))
            {
                GameTarget gt = new GameTarget(Mod.MEGame.ME1, d, false, false);
                gt.ValidateTarget();
                if (gt.IsValid)
                {
                    targets.Add(gt);
                }
            }
            root = GlobalTest.GetTestGameFoldersDirectory(Mod.MEGame.ME2);
            foreach (var d in Directory.GetDirectories(root))
            {
                GameTarget gt = new GameTarget(Mod.MEGame.ME2, d, false, false);
                gt.ValidateTarget();
                if (gt.IsValid)
                {
                    targets.Add(gt);
                }
            }
            root = GlobalTest.GetTestGameFoldersDirectory(Mod.MEGame.ME3);
            foreach (var d in Directory.GetDirectories(root))
            {
                GameTarget gt = new GameTarget(Mod.MEGame.ME3, d, false, false);
                gt.ValidateTarget();
                if (gt.IsValid)
                {
                    targets.Add(gt);
                }
            }
            #endregion

            //Compressed Mods

            foreach (var archive in Directory.GetFiles(compressedModsDirectory))
            {
                modsFoundInArchive.Clear();
                var realArchiveInfo = GlobalTest.ParseRealArchiveAttributes(archive);
                Console.WriteLine($@"Inspecting archive: { archive}");
                ModArchiveImporter.InspectArchive(archive, addModCallback, failedModCallback, logMessageCallback, forcedMD5: realArchiveInfo.md5, forcedSize: realArchiveInfo.size);
                var archiveZ = new SevenZipExtractor(archive);
                foreach (var mod in modsFoundInArchive)
                {
                    bool altsOn = false;
                    while (true)
                    {
                        if (altsOn)
                        {
                            foreach (var job in mod.InstallationJobs)
                            {
                                List <string> selectedGroups = new List <string>();
                                foreach (var altfile in job.AlternateFiles)
                                {
                                    if (altfile.GroupName != null)
                                    {
                                        if (selectedGroups.Contains(altfile.GroupName))
                                        {
                                            continue; //we already did first time of this. I know that's a weak test case...
                                        }
                                        selectedGroups.Add(altfile.GroupName);
                                    }

                                    altfile.IsSelected = true;
                                }
                            }
                        }

                        var refs = mod.GetAllRelativeReferences(!mod.IsVirtualized, archiveZ); //test
                        //validate references are actually in this archive
                        foreach (var fileREf in refs)
                        {
                            var expectedPath = FilesystemInterposer.PathCombine(mod.IsInArchive, mod.ModPath, fileREf);
                            //var expectedPath = fileREf;
                            var inArchiveFile = archiveZ.ArchiveFileData.FirstOrDefault(x => x.FileName == expectedPath);
                            Assert.IsNotNull(inArchiveFile.FileName, "Relative referenced file was not found in archive: " + fileREf);
                        }

                        //size test
                        Assert.AreNotEqual(0, mod.SizeRequiredtoExtract, "Archive extraction size is zero! For file " + archive);

                        var targetsForMod = targets.Where(x => x.Game == mod.Game).ToList();
                        foreach (var target in targetsForMod)
                        {
                            var queue = mod.GetInstallationQueues(target);
                            foreach (var jobMapping in queue.Item1)
                            {
                                foreach (var unpackedItem in jobMapping.Value.unpackedJobMapping)
                                {
                                    string sourceFile;
                                    if (jobMapping.Key.JobDirectory == null || unpackedItem.Value.IsFullRelativeFilePath)
                                    {
                                        sourceFile = FilesystemInterposer.PathCombine(mod.IsInArchive, mod.ModPath, unpackedItem.Value.FilePath);
                                    }
                                    else
                                    {
                                        sourceFile = FilesystemInterposer.PathCombine(mod.IsInArchive, mod.ModPath, jobMapping.Key.JobDirectory, unpackedItem.Value.FilePath);
                                    }
                                    Assert.IsTrue(archiveZ.ArchiveFileNames.Contains(sourceFile), "Archive should contain a file specified by mod (mod is valid) but does not appear to. File: " + sourceFile);
                                }
                            }
                        }

                        if (!altsOn)
                        {
                            altsOn = true;
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }

            //EXE mods
            var exeModsDirectory = Path.Combine(GlobalTest.GetTestDataDirectory(), "exemods");

            if (Directory.Exists(exeModsDirectory))
            {
                foreach (var exe in Directory.GetFiles(exeModsDirectory))
                {
                    modsFoundInArchive.Clear();
                    //var realArchiveInfo = GlobalTest.ParseRealArchiveAttributes(exe);
                    Console.WriteLine($@"Inspecting exe: { exe}");
                    ModArchiveImporter.InspectArchive(exe, addModCallback, failedModCallback, logMessageCallback);
                    var archiveZ = new SevenZipExtractor(exe, InArchiveFormat.Nsis);
                    foreach (var mod in modsFoundInArchive)
                    {
                        foreach (var job in mod.InstallationJobs)
                        {
                            List <string> selectedGroups = new List <string>();
                            foreach (var altfile in job.AlternateFiles)
                            {
                                if (altfile.GroupName != null)
                                {
                                    if (selectedGroups.Contains(altfile.GroupName))
                                    {
                                        continue; //we already did first time of this. I know that's a weak test case...
                                    }
                                    selectedGroups.Add(altfile.GroupName);
                                }

                                altfile.IsSelected = true;
                            }
                        }


                        var refs = mod.GetAllRelativeReferences(false, archiveZ); //test and get refs. exe mods will always be virtualized as they won't have a moddesc.ini file.
                                                                                  //exe mods remap to subconetns
                                                                                  //same code as Mod-Extraction.cs
                        foreach (var fileREf in refs)
                        {
                            var expectedPath = FilesystemInterposer.PathCombine(mod.IsInArchive, mod.ModPath, fileREf);
                            //var expectedPath = fileREf;
                            var inArchiveFile = archiveZ.ArchiveFileData.FirstOrDefault(x => x.FileName == expectedPath);
                            Assert.IsNotNull(inArchiveFile.FileName, "Relative referenced file was not found in archive: " + fileREf);
                        }

                        mod.ExtractFromArchive(exe, "", false, testRun: true);
                    }
                }
            }
            else
            {
                Console.WriteLine("No exemods directory found. This section of testing will be skipped");
            }
        }
Example #7
0
        public static async void BeginFlow(MainWindow window)
        {
            // PRE LIBRARY LOAD
            RegistryHandler.RegistrySettingsPath       = @"HKEY_CURRENT_USER\Software\MassEffect2Randomizer";
            RegistryHandler.CurrentUserRegistrySubpath = @"Software\MassEffect2Randomizer";
            LegendaryExplorerCoreLib.SetSynchronizationContext(TaskScheduler.FromCurrentSynchronizationContext());

            try
            {
                // This is in a try catch because this is a critical no-crash zone that is before launch
                window.Title = $"Mass Effect 2 Randomizer {App.AppVersion}";
            }
            catch { }

            if (Utilities.GetExecutablePath().StartsWith(Path.GetTempPath(), StringComparison.InvariantCultureIgnoreCase))
            {
                // Running from temp! This is not allowed
                await window.ShowMessageAsync("Cannot run from temp directory", $"Mass Effect 2 Randomizer cannot be run from the system's Temp directory. If this executable was run from within an archive, it needs to be extracted first.");

                Environment.Exit(1);
            }

            var pd = await window.ShowProgressAsync("Starting up", $"Mass Effect 2 Randomizer is starting up. Please wait.");

            pd.SetIndeterminate();
            NamedBackgroundWorker bw = new NamedBackgroundWorker("StartupThread");

            bw.DoWork += (a, b) =>
            {
                ALOTInstallerCoreLib.Startup(SetWrapperLogger, RunOnUIThread, startTelemetry, stopTelemetry, $"Mass Effect 2 Randomizer {App.AppVersion} starting up", false);
                // Logger is now available

                // Setup telemetry handlers
                CoreAnalytics.TrackEvent = TelemetryController.TrackEvent;
                CoreCrashes.TrackError   = TelemetryController.TrackError;
                CoreCrashes.TrackError2  = TelemetryController.TrackError2;
                CoreCrashes.TrackError3  = TelemetryController.TrackError3;

                // Setup the InteropPackage for the update check
                #region Update interop
                CancellationTokenSource ct = new CancellationTokenSource();

                AppUpdateInteropPackage interopPackage = new AppUpdateInteropPackage()
                {
                    GithubOwner              = "Mgamerz",
                    GithubReponame           = "MassEffect2Randomizer",
                    UpdateAssetPrefix        = "ME2Randomizer",
                    UpdateFilenameInArchive  = "ME2Randomizer.exe",
                    ShowUpdatePromptCallback = (title, text, updateButtonText, declineButtonText) =>
                    {
                        bool   response = false;
                        object syncObj  = new object();
                        Application.Current.Dispatcher.Invoke(async() =>
                        {
                            if (Application.Current.MainWindow is MainWindow mw)
                            {
                                var result = await mw.ShowMessageAsync(title, text, MessageDialogStyle.AffirmativeAndNegative, new MetroDialogSettings()
                                {
                                    AffirmativeButtonText = updateButtonText,
                                    NegativeButtonText    = declineButtonText,
                                    DefaultButtonFocus    = MessageDialogResult.Affirmative
                                },
                                                                       75);
                                response = result == MessageDialogResult.Affirmative;
                                lock (syncObj)
                                {
                                    Monitor.Pulse(syncObj);
                                }
                            }
                        });
                        lock (syncObj)
                        {
                            Monitor.Wait(syncObj);
                        }
                        return(response);
                    },
                    ShowUpdateProgressDialogCallback = (title, initialmessage, canCancel) =>
                    {
                        // We don't use this as we are already in a progress dialog
                        pd.SetCancelable(canCancel);
                        pd.SetMessage(initialmessage);
                        pd.SetTitle(title);
                    },
                    SetUpdateDialogTextCallback = s =>
                    {
                        pd.SetMessage(s);
                    },
                    ProgressCallback = (done, total) =>
                    {
                        pd.SetProgress(done * 1d / total);
                        pd.SetMessage($"Downloading update {FileSize.FormatSize(done)} / {FileSize.FormatSize(total)}");
                    },
                    ProgressIndeterminateCallback = () =>
                    {
                        pd.SetIndeterminate();
                    },
                    ShowMessageCallback = (title, message) =>
                    {
                        object syncObj = new object();
                        Application.Current.Dispatcher.Invoke(async() =>
                        {
                            if (Application.Current.MainWindow is MainWindow mw)
                            {
                                await mw.ShowMessageAsync(title, message);
                                lock (syncObj)
                                {
                                    Monitor.Pulse(syncObj);
                                }
                            }
                        });
                        lock (syncObj)
                        {
                            Monitor.Wait(syncObj);
                        }
                    },
                    NotifyBetaAvailable = () =>
                    {
                        App.BetaAvailable = true;
                    },
                    DownloadCompleted = () =>
                    {
                        pd.SetCancelable(false);
                    },
                    cancellationTokenSource    = ct,
                    ApplicationName            = "Mass Effect 2 Randomizer",
                    RequestHeader              = "ME2Randomizer",
                    ForcedUpgradeMaxReleaseAge = 3
                };

                #endregion



                pd.SetMessage("Checking for application updates");
                pd.Canceled += (sender, args) =>
                {
                    ct.Cancel();
                };
                AppUpdater.PerformGithubAppUpdateCheck(interopPackage);

                // If user aborts download
                pd.SetCancelable(false);
                pd.SetIndeterminate();
                pd.SetTitle("Starting up");

                void setStatus(string message)
                {
                    pd.SetIndeterminate();
                    pd.SetMessage(message);
                }

                GameTarget target = null;
                try
                {
                    pd.SetMessage("Loading Mass Effect 2 Randomizer framework");
                    ToolTipService.ShowOnDisabledProperty.OverrideMetadata(typeof(Control), new FrameworkPropertyMetadata(true));
                    ToolTipService.ShowDurationProperty.OverrideMetadata(typeof(DependencyObject), new FrameworkPropertyMetadata(int.MaxValue));

                    ALOTInstallerCoreLib.PostCriticalStartup(x => pd.SetMessage(x), RunOnUIThread, false);

#if __LE2__
                    LE2Directory.ReloadDefaultGamePath(true);
                    if (LE2Directory.DefaultGamePath != null)
                    {
                        GameTarget gt = new GameTarget(MEGame.LE2, LE2Directory.DefaultGamePath, true);
                        if (gt.ValidateTarget() == null)
                        {
                            Locations.SetTarget(gt, false);
                        }
                    }
#endif
                    MEPackageHandler.GlobalSharedCacheEnabled = false; // ME2R does not use the global shared cache.

                    handleM3Passthrough();
                    target = Locations.GetTarget(MERFileSystem.Game);
                    if (target == null)
                    {
                        var gamePath = MEDirectories.GetDefaultGamePath(MERFileSystem.Game);
                        if (Directory.Exists(gamePath))
                        {
                            target = new GameTarget(MERFileSystem.Game, gamePath, true);
                            var validationFailedReason = target.ValidateTarget();
                            if (validationFailedReason == null)
                            {
                                // CHECK NOT TEXTURE MODIFIED
                                if (target.TextureModded)
                                {
                                    MERLog.Error($@"Game target is texture modded: {target.TargetPath}. This game target is not targetable by ME2R");
                                    object o = new object();
                                    Application.Current.Dispatcher.Invoke(async() =>
                                    {
                                        if (Application.Current.MainWindow is MainWindow mw)
                                        {
                                            await mw.ShowMessageAsync("Mass Effect 2 target is texture modded", $"The game located at {target.TargetPath} has had textures modified. Mass Effect 2 Randomizer cannot randomize texture modified games, as it adds package files. If you want to texture mod your game, it must be done after randomization.", ContentWidthPercent: 75);
                                            lock (o)
                                            {
                                                Monitor.Pulse(o);
                                            }
                                        }
                                    });
                                    lock (o)
                                    {
                                        Monitor.Wait(o);
                                    }
                                }

                                // We still set target so we can restore game if necessary
                                Locations.SetTarget(target, false);
                            }
                        }
                    }


                    pd.SetMessage("Performing startup checks");
                    MERStartupCheck.PerformStartupCheck((title, message) =>
                    {
                        object o = new object();
                        Application.Current.Dispatcher.Invoke(async() =>
                        {
                            if (Application.Current.MainWindow is MainWindow mw)
                            {
                                await mw.ShowMessageAsync(title, message, ContentWidthPercent: 75);
                                lock (o)
                                {
                                    Monitor.Pulse(o);
                                }
                            }
                        });
                        lock (o)
                        {
                            Monitor.Wait(o);
                        }
                    }, x => pd.SetMessage(x));

                    // force initial refresh
                    MERPeriodicRefresh(null, null);
                }
                catch (Exception e)
                {
                    MERLog.Exception(e, @"There was an error starting up the framework!");
                }

                pd.SetMessage("Preparing interface");
                Thread.Sleep(250); // This will allow this message to show up for moment so user can see it.

                Application.Current.Dispatcher.Invoke(async() =>
                {
                    if (Application.Current.MainWindow is MainWindow mw)
                    {
                        mw.SetupTargetDescriptionText();


                        var backupStatus                = BackupService.GetBackupStatus(MERFileSystem.Game);
                        mw.BackupRestoreText            = backupStatus?.BackupActionText;
                        mw.BackupRestore_Button.ToolTip = backupStatus != null && backupStatus.BackedUp ? "Click to restore game/uninstall randomizer mod" : "Click to backup game";

                        mw.FinalizeInterfaceLoad();

                        /*
                         * if (!hasWorkingMEM)
                         * {
                         *  await mw.ShowMessageAsync("Required components are not available",
                         *      "Some components for installation are not available, likely due to network issues (blocking, no internet, etc). To install these components, folow the 'How to install the Installer Support Package' directions on any of the ALOT pages on NexusMods. The installer will not work without these files installed.",
                         *      ContentWidthPercent: 75);
                         * }*/

                        PeriodicRefresh.OnPeriodicRefresh += MERPeriodicRefresh;
                    }
                });
            };
            bw.RunWorkerCompleted += async(a, b) =>
            {
                // Post critical startup
                Random random  = new Random();
                var    preseed = random.Next();
                window.ImageCredits.ReplaceAll(ImageCredit.LoadImageCredits("imagecredits.txt", false));
                window.ContributorCredits.ReplaceAll(window.GetContributorCredits());
                window.LibraryCredits.ReplaceAll(LibraryCredit.LoadLibraryCredits("librarycredits.txt"));
#if DEBUG
                window.SeedTextBox.Text = 529572808.ToString();
#else
                window.SeedTextBox.Text = preseed.ToString();
#endif
                window.TextBlock_AssemblyVersion.Text = $"Version {App.AppVersion}";
                window.SelectedRandomizeMode          = MainWindow.RandomizationMode.ERandomizationMode_SelectAny;


                var hasFirstRun = RegistryHandler.GetRegistrySettingBool(MainWindow.SETTING_FIRSTRUN);
                if (hasFirstRun == null || !hasFirstRun.Value)
                {
                    window.FirstRunFlyoutOpen = true;
                }
                await pd.CloseAsync();
            };
            bw.RunWorkerAsync();
        }
Example #8
0
        public void TestM3DirectoryResults()
        {
            GlobalTest.Init();
            List <GameTarget> targets = new List <GameTarget>();
            var root = GlobalTest.GetTestGameFoldersDirectory(MEGame.ME1);

            foreach (var d in Directory.GetDirectories(root))
            {
                GameTarget gt = new GameTarget(MEGame.ME1, d, false, false);
                gt.ValidateTarget();
                if (gt.IsValid)
                {
                    targets.Add(gt);
                }
            }
            root = GlobalTest.GetTestGameFoldersDirectory(MEGame.ME2);
            foreach (var d in Directory.GetDirectories(root))
            {
                GameTarget gt = new GameTarget(MEGame.ME2, d, false, false);
                gt.ValidateTarget();
                if (gt.IsValid)
                {
                    targets.Add(gt);
                }
            }
            root = GlobalTest.GetTestGameFoldersDirectory(MEGame.ME3);
            foreach (var d in Directory.GetDirectories(root))
            {
                GameTarget gt = new GameTarget(MEGame.ME3, d, false, false);
                gt.ValidateTarget();
                if (gt.IsValid)
                {
                    targets.Add(gt);
                }
            }

            foreach (var target in targets)
            {
                string expectedDLCPath;
                string expectedASIPath;
                string expectedBioGamePath;
                string expectedCookedPath;
                string expectedExecutableDir;
                if (target.Game == MEGame.ME1)
                {
                    expectedDLCPath       = Path.Combine(target.TargetPath, @"DLC");
                    expectedASIPath       = Path.Combine(target.TargetPath, @"Binaries", @"asi");
                    expectedBioGamePath   = Path.Combine(target.TargetPath, @"BioGame");
                    expectedCookedPath    = Path.Combine(target.TargetPath, @"BioGame", @"CookedPC");
                    expectedExecutableDir = Path.Combine(target.TargetPath, @"Binaries");
                }
                else if (target.Game == MEGame.ME2)
                {
                    expectedDLCPath       = Path.Combine(target.TargetPath, @"BioGame", @"DLC");
                    expectedASIPath       = Path.Combine(target.TargetPath, @"Binaries", @"asi");
                    expectedBioGamePath   = Path.Combine(target.TargetPath, @"BioGame");
                    expectedCookedPath    = Path.Combine(target.TargetPath, @"BioGame", @"CookedPC");
                    expectedExecutableDir = Path.Combine(target.TargetPath, @"Binaries");
                }
                else
                {
                    expectedDLCPath       = Path.Combine(target.TargetPath, @"BIOGame", @"DLC");
                    expectedASIPath       = Path.Combine(target.TargetPath, @"Binaries", @"Win32", @"asi");
                    expectedBioGamePath   = Path.Combine(target.TargetPath, @"BIOGame");
                    expectedCookedPath    = Path.Combine(target.TargetPath, @"BIOGame", @"CookedPCConsole");
                    expectedExecutableDir = Path.Combine(target.TargetPath, @"Binaries", @"Win32");
                }

                Assert.AreEqual(expectedDLCPath, M3Directories.GetDLCPath(target));
                Assert.AreEqual(expectedASIPath, M3Directories.GetASIPath(target));
                Assert.AreEqual(expectedBioGamePath, M3Directories.GetBioGamePath(target));
                Assert.AreEqual(expectedCookedPath, M3Directories.GetCookedPath(target));
                Assert.AreEqual(expectedExecutableDir, M3Directories.GetExecutableDirectory(target));
            }
        }
        private void Migration_ContentRendered(object sender, EventArgs e)
        {
            NamedBackgroundWorker nbw = new NamedBackgroundWorker(@"ME3CMMMigration");

            nbw.DoWork += (a, b) =>
            {
                Log.Information(@">>>> ME3CMMMigration Thread");
                Log.Information(@"Validate ME3CMM folders and files");
                var exeDir = Utilities.GetMMExecutableDirectory();
                //DEBUG ONLY

                //exeDir = @"E:\ME3CMM";

                var modsDir = Path.Combine(exeDir, @"mods");
                var dataDir = Path.Combine(exeDir, @"data");
                if (Directory.Exists(modsDir) && Directory.Exists(dataDir))
                {
                    Log.Information(@"mods and data dir exist.");
                    // 1. MIGRATE MODS
                    Log.Information(@"Step 1: Migrate mods");
                    MigratingModsTask.SetInProgress();

                    var targetModLibrary = Utilities.GetModsDirectory();
                    //DEBUG ONLY
                    //targetModLibrary = @"E:\ME3CMM\mods";

                    targetModLibrary = Path.Combine(targetModLibrary, @"ME3");
                    if (!Directory.Exists(targetModLibrary))
                    {
                        Log.Information(@"Creating target mod library directory: " + targetModLibrary);
                        Directory.CreateDirectory(targetModLibrary);
                    }

                    var sameRoot = Path.GetPathRoot(targetModLibrary) == Path.GetPathRoot(modsDir);

                    var directoriesInModsDir = Directory.GetDirectories(modsDir);

                    var numToMigrate = directoriesInModsDir.Count(x => File.Exists(Path.Combine(x, @"moddesc.ini")));
                    var numMigrated  = 0;

                    foreach (var modDirToMove in directoriesInModsDir)
                    {
                        var moddesc = Path.Combine(modDirToMove, @"moddesc.ini");
                        if (File.Exists(moddesc))
                        {
                            numMigrated++;
                            MigratingModsTask.TaskText = $"Migrating mods [{numMigrated}/{numToMigrate}]";
                            //Migrate this folder
                            var targetDir = Path.Combine(modsDir, @"ME3", Path.GetFileName(modDirToMove));
                            Log.Information($@"Migrating mod into ME3 directory: {modDirToMove} -> {targetDir}");
                            if (!Directory.Exists(targetDir))
                            {
                                if (sameRoot)
                                {
                                    Directory.Move(modDirToMove, targetDir);
                                }
                                else
                                {
                                    Log.Information(@"Copying existing mod directory");
                                    Directory.CreateDirectory(targetDir);
                                    CopyDir.CopyAll_ProgressBar(new DirectoryInfo(modDirToMove), new DirectoryInfo(targetDir));
                                    Log.Information(@"Deleting existing directory");
                                    Utilities.DeleteFilesAndFoldersRecursively(modDirToMove);
                                }

                                Log.Information($@"Migrated {modDirToMove}");
                                //Thread.Sleep(200);
                            }
                            else
                            {
                                Log.Warning(@"Target directory already exists! Not migrating this directory.");
                            }
                        }
                    }

                    MigratingModsTask.SetDone();
                    Log.Information(@"Step 1: Finished mod migration");


                    // 2. MIGRATE SETTINGS
                    MigratingSettings.SetInProgress();
                    Log.Information(@"Step 2: Begin settings migration");
                    var me3cmminif = Path.Combine(exeDir, @"me3cmm.ini");
                    if (File.Exists(me3cmminif))
                    {
                        Log.Information(@"Migrating me3cmm.ini settings");
                        IniData me3cmmini = new FileIniDataParser().ReadFile(me3cmminif);
                        var     updaterServiceUsername = me3cmmini[@"UpdaterService"][@"username"];
                        if (string.IsNullOrWhiteSpace(Settings.UpdaterServiceUsername) && !string.IsNullOrWhiteSpace(updaterServiceUsername))
                        {
                            Settings.UpdaterServiceUsername = updaterServiceUsername;
                            Log.Information(@"Migrated Updater Service Username: "******"UpdaterService"][@"manifestspath"];
                        if (string.IsNullOrWhiteSpace(Settings.UpdaterServiceManifestStoragePath) && !string.IsNullOrWhiteSpace(manifestsPath))
                        {
                            Settings.UpdaterServiceManifestStoragePath = manifestsPath;
                            Log.Information(@"Migrated Updater Service Manifests Path: " + manifestsPath);
                        }

                        var lzmaStoragePath = me3cmmini[@"UpdaterService"][@"lzmastoragepath"];
                        if (string.IsNullOrWhiteSpace(Settings.UpdaterServiceLZMAStoragePath) && !string.IsNullOrWhiteSpace(lzmaStoragePath))
                        {
                            Settings.UpdaterServiceLZMAStoragePath = updaterServiceUsername;
                            Log.Information(@"Migrated Updater Service LZMA Storage Path: " + lzmaStoragePath);
                        }

                        //TODO: MODMAKER CONTROLLER AUTO-ADDINS

                        Settings.Save();
                    }

                    //Migrate BIOGAME_DIRECTORIES
                    var biogameDirsF = Path.Combine(dataDir, @"BIOGAME_DIRECTORIES");
                    if (File.Exists(biogameDirsF))
                    {
                        var biodirs = File.ReadAllLines(biogameDirsF);
                        foreach (var line in biodirs)
                        {
                            var gamepath = Directory.GetParent(line).FullName;
                            Log.Information(@"Validating ME3CMM target: " + gamepath);
                            GameTarget t             = new GameTarget(Mod.MEGame.ME3, gamepath, false);
                            var        failureReason = t.ValidateTarget();
                            if (failureReason == null)
                            {
                                Utilities.AddCachedTarget(t);
                            }
                            else
                            {
                                Log.Error($@"Not migrating invalid target {gamepath}: {failureReason}");
                            }
                        }
                    }

                    //Migrate ALOT Installer, if found
                    var alotInstallerDir = Path.Combine(dataDir, @"ALOTInstaller");
                    if (Directory.Exists(alotInstallerDir))
                    {
                        Log.Information(@"Migrating ALOTInstaller tool");
                        var externalToolsALOTInstaller = Path.Combine(dataDir, @"ExternalTools", @"ALOTInstaller");
                        Directory.CreateDirectory(Path.Combine(dataDir, @"ExternalTools"));
                        Directory.Move(alotInstallerDir, externalToolsALOTInstaller);
                        Log.Information(@"Migrated ALOTInstaller to ExternalTools");
                    }

                    //Migrate ME3Explorer, if found
                    var me3explorerDir = Path.Combine(dataDir, @"ME3Explorer");
                    if (Directory.Exists(me3explorerDir))
                    {
                        Log.Information(@"Migrating ME3Explorer tool");
                        var externalToolsME3ExplorerDir = Path.Combine(dataDir, @"ExternalTools", @"ME3Explorer");
                        Directory.CreateDirectory(Path.Combine(dataDir, @"ExternalTools"));
                        Directory.Move(me3explorerDir, externalToolsME3ExplorerDir);
                        Log.Information(@"Migrated ME3Explorer to ExternalTools");
                    }

                    //MIGRATE 7z.dll - this will only perform an interim fix as we use 19.0 and ME3MM used 18.05
                    var me3mm7z  = Path.Combine(dataDir, @"tools\ModManagerCommandLine\x64\7z.dll");
                    var target7z = Utilities.Get7zDllPath();
                    if (File.Exists(me3mm7z) && !File.Exists(target7z))
                    {
                        Log.Information($@"Copying ME3CMM 7z.dll to ME3Tweaks Mod Manager dll location: {me3mm7z} -> {target7z}");
                        File.Copy(me3mm7z, target7z, true);
                        Log.Information(@"Copied ME3MM 7z dll");
                    }

                    //MIGRATE MOD GROUPS (batch install queues)/
                    //Migrate ME3Explorer, if found
                    var modGroupsDir = Path.Combine(dataDir, @"modgroups");
                    if (Directory.Exists(modGroupsDir))
                    {
                        Log.Information(@"Migrating batch mod groups");
                        var queues = Directory.EnumerateFiles(modGroupsDir, @"*.txt").ToList();
                        foreach (var queue in queues)
                        {
                            var biqDest = Path.Combine(Utilities.GetBatchInstallGroupsFolder(), Path.GetFileName(queue));
                            Log.Information($@"Migrating mod install group: {queue} -> {biqDest}");
                            File.Move(queue, biqDest, true);
                            Log.Information(@"Migrated " + Path.GetFileName(queue));
                        }
                    }

                    MigratingSettings.SetDone();

                    Log.Information(@"Step 2: Finished settings migration");
                    // 3. CLEANUP
                    Log.Information(@"Step 3: Cleaning up");
                    CleaningUpTask.SetInProgress();
                    CleaningUpTask.SetDone();
                    Log.Information(@"Step 3: Cleaned up");
                    Thread.Sleep(3000);
                }
                else
                {
                    Log.Error(@"mods and/or data dir don't exist! We will not attempt migration.");
                }

                Log.Information(@"<<<< Exiting ME3CMMMigration Thread");
            };
            nbw.RunWorkerCompleted += (a, b) =>
            {
                Log.Information(@"Migration has completed.");
                Close();
            };
            nbw.RunWorkerAsync();
        }