private void FetchME2File()
        {
            BackupFile     fileTofetch = SelectedME2File;
            SaveFileDialog m           = new SaveFileDialog
            {
                Title    = M3L.GetString(M3L.string_selectDestinationLocation),
                Filter   = M3L.GetString(M3L.string_packageFile) + @"|*" + Path.GetExtension(fileTofetch.Filename),
                FileName = fileTofetch.Filename
            };
            var result = m.ShowDialog(mainwindow);

            if (result.Value)
            {
                if (fileTofetch.Module == @"BASEGAME")
                {
                    var fetchedfilestream = VanillaDatabaseService.FetchBasegameFile(Mod.MEGame.ME2, fileTofetch.Filename);
                    fetchedfilestream.WriteToFile(m.FileName);
                }
                else
                {
                    var fetchedfilestream = VanillaDatabaseService.FetchME1ME2DLCFile(Mod.MEGame.ME2, fileTofetch.Module, fileTofetch.Filename);
                    fetchedfilestream.WriteToFile(m.FileName);
                }
            }

            M3L.ShowDialog(window, M3L.GetString(M3L.string_interp_fileFetchedAndWrittenToX, m.FileName), M3L.GetString(M3L.string_fileFetched));
        }
        private void LoadME2FilesList()
        {
            var me2files = new List <BackupFile>();

            var bup = Utilities.GetGameBackupPath(Mod.MEGame.ME2);

            if (bup != null)
            {
                var target     = new GameTarget(Mod.MEGame.ME2, bup, false);
                var cookedPath = MEDirectories.CookedPath(target);
                foreach (var f in Extensions.GetFiles(cookedPath, @"\.pcc|\.tfc|\.afc|\.bin|\.tlk", SearchOption.AllDirectories))
                {
                    me2files.Add(new BackupFile(@"BASEGAME", Path.GetFileName(f)));
                }

                var dlcDir      = MEDirectories.DLCPath(target);
                var officialDLC = VanillaDatabaseService.GetInstalledOfficialDLC(target);
                foreach (var v in officialDLC)
                {
                    var cookedDLCPath = Path.Combine(dlcDir, v, @"CookedPC");
                    if (Directory.Exists(cookedDLCPath))
                    {
                        foreach (var f in Directory.EnumerateFiles(cookedDLCPath, @"*.pcc", SearchOption.TopDirectoryOnly))
                        {
                            me2files.Add(new BackupFile(v, Path.GetFileName(f)));
                        }
                    }
                }
            }
            Application.Current.Dispatcher.Invoke(delegate
            {
                ME2Files.ReplaceAll(me2files);
            });
            Debug.WriteLine(@"Num ME2 files: " + ME2Files.Count);
        }
        public override void OnPanelVisible()
        {
            var installedDLCMods = VanillaDatabaseService.GetInstalledDLCMods(target);
            var uiModInstalled   = installedDLCMods.Intersect(DLCUIModFolderNames).Any();

            if (uiModInstalled)
            {
                var result = Xceed.Wpf.Toolkit.MessageBox.Show(window, "A GUI compatibility mod is used to make SP Controller Support, Interface Scaling Mod and Interface Scaling Add-on work with mods that modify the same files or include their own interface files. " +
                                                               "This is a critical step when using UI mods or you may experience softlocks or incorrect interfaces on screen.\n\n" +
                                                               "Generate a GUI compatibility pack ONLY when you have installed all other non-texture mods as it is built against your current installation.\n\nGenerate compatibility pack?",
                                                               "Confirm generation", MessageBoxButton.YesNo, MessageBoxImage.Warning);
                if (result == MessageBoxResult.No)
                {
                    OnClosing(DataEventArgs.Empty);
                    return;
                }

                StartGuiCompatibilityScanner();
            }
            else
            {
                Xceed.Wpf.Toolkit.MessageBox.Show(window, "No UI mods are installed. GUI compatibility generator only works with SP Controller Mod, Interface Scaling Mod, and Interface Scaling Add-On.", "No UI mods installed", MessageBoxButton.OK, MessageBoxImage.Error);
                OnClosing(DataEventArgs.Empty);
            }
        }
        private void LoadME3FilesList()
        {
            var me3files = new List <BackupFile>();
            var bup      = BackupService.GetGameBackupPath(Mod.MEGame.ME3);

            if (bup != null)
            {
                var target     = new GameTarget(Mod.MEGame.ME3, bup, false);
                var cookedPath = MEDirectories.CookedPath(target);
                foreach (var f in Extensions.GetFiles(cookedPath, @"\.pcc|\.tfc|\.afc|\.bin|\.tlk", SearchOption.AllDirectories))
                {
                    me3files.Add(new BackupFile(@"BASEGAME", Path.GetFileName(f)));
                }
                me3files.Sort(); //sort basegame

                var dlcDir      = MEDirectories.DLCPath(target);
                var officialDLC = VanillaDatabaseService.GetInstalledOfficialDLC(target);
                foreach (var v in officialDLC)
                {
                    var sfarPath = Path.Combine(dlcDir, v, @"CookedPCConsole", @"Default.sfar");
                    if (File.Exists(sfarPath))
                    {
                        var        filesToAdd = new List <BackupFile>();
                        DLCPackage dlc        = new DLCPackage(sfarPath);
                        foreach (var f in dlc.Files)
                        {
                            filesToAdd.Add(new BackupFile(v, Path.GetFileName(f.FileName)));
                        }
                        filesToAdd.Sort();
                        me3files.AddRange(filesToAdd);
                    }
                }

                //TESTPATCH
                var tpPath = ME3Directory.GetTestPatchPath(target);
                if (File.Exists(tpPath))
                {
                    var        filesToAdd = new List <BackupFile>();
                    DLCPackage dlc        = new DLCPackage(tpPath);
                    foreach (var f in dlc.Files)
                    {
                        filesToAdd.Add(new BackupFile(@"TESTPATCH", Path.GetFileName(f.FileName)));
                    }
                    filesToAdd.Sort();
                    me3files.AddRange(filesToAdd);
                }
            }
            Application.Current.Dispatcher.Invoke(delegate
            {
                ME3Files.ReplaceAll(me3files);
            });
            Debug.WriteLine(@"Num ME3 files: " + ME3Files.Count);
        }
Exemplo n.º 5
0
            public bool RevalidateIsModified(bool notify = true)
            {
                bool _isModified = IsModified;

                IsModified = !VanillaDatabaseService.IsFileVanilla(target, Path.Combine(target.TargetPath, FilePath));
                if (!IsModified && _isModified && notify)
                {
                    //Debug.WriteLine("Notifying that " + FilePath + " is no longer modified.");
                    notifyNoLongerModified?.Invoke(this);
                }
                return(IsModified);
            }
Exemplo n.º 6
0
        public static void UpdateMD5Map(MEGame game, string directory, string outName)
        {
            var outF = $@"C:\Users\mgame\source\repos\ME3Tweaks\MassEffectModManager\MassEffectModManagerCore\modmanager\gamemd5\{outName}";
            var db   = VanillaDatabaseService.LoadDatabaseFor(game, false);

            if (game.IsLEGame())
            {
                db.RemoveAll(x => x.Key.Contains(@"BioGame\Config")); // Do not include config files
            }

            MemoryStream mapStream = new MemoryStream();

            // Name Table
            mapStream.WriteInt32(db.Count); // Num Entries
            foreach (var f in db.Keys)
            {
                mapStream.WriteStringASCIINull(f);
            }

            // Data Table
            mapStream.WriteInt32(db.Count);
            int idx = 0;

            foreach (var f in db)
            {
                mapStream.WriteInt32(idx);             // Name Table IDX. Update this code for duplicates support
                mapStream.WriteInt32(f.Value[0].size); // Size
                var md5 = f.Value[0].md5;
                for (int i = 0; i < 32; i++)
                {
                    byte b = 0;
                    b |= HexToInt(md5[i]);
                    b  = (byte)(b << 4);
                    i++;
                    b |= HexToInt(md5[i]);

                    mapStream.WriteByte(b);
                }
                idx++;
            }

            var compBytes = LZMA.Compress(mapStream.ToArray());

            MemoryStream ms = new MemoryStream();

            ms.WriteStringASCII(@"MD5T");
            ms.WriteInt32((int)mapStream.Length);
            ms.Write(compBytes);
            ms.WriteToFile(outF);
        }
        public override void OnPanelVisible()
        {
            var db = VanillaDatabaseService.LoadDatabaseFor(Mod.MEGame.ME1, false);

            ME1Files.ReplaceAll(getDBItems(db));
            db = VanillaDatabaseService.LoadDatabaseFor(Mod.MEGame.ME2, false);
            ME2Files.ReplaceAll(getDBItems(db));
            db = VanillaDatabaseService.LoadDatabaseFor(Mod.MEGame.ME3, false);
            ME3Files.ReplaceAll(getDBItems(db));

            LoadingInProgress   = false;
            ME1FilesView.Filter = FilterBackupFilesME1;
            ME2FilesView.Filter = FilterBackupFilesME2;
            ME3FilesView.Filter = FilterBackupFilesME3;
        }
Exemplo n.º 8
0
        public void ReloadGameTarget()
        {
            if (Game != Mod.MEGame.Unknown && !IsCustomOption)
            {
                var oldTMOption = TextureModded;
                var alotInfo    = GetInstalledALOTInfo();
                if (alotInfo != null)
                {
                    TextureModded = true;
                    ALOTVersion   = alotInfo.ToString();
                    if (alotInfo.MEUITMVER > 0)
                    {
                        MEUITMInstalled = true;
                        MEUITMVersion   = alotInfo.MEUITMVER;
                    }
                }
                else
                {
                    TextureModded   = false;
                    ALOTVersion     = null;
                    MEUITMInstalled = false;
                    MEUITMVersion   = 0;
                }
                Log.Information(@"Getting game source for target " + TargetPath);
                var hashCheckResult = VanillaDatabaseService.GetGameSource(this);

                GameSource     = hashCheckResult.result;
                ExecutableHash = hashCheckResult.hash;
                if (GameSource == null)
                {
                    Log.Error(@"Unknown source or illegitimate installation: " + hashCheckResult.hash);
                }
                else
                {
                    Log.Information(@"Source: " + GameSource);
                }
                IsPolishME1 = Game == Mod.MEGame.ME1 && File.Exists(Path.Combine(TargetPath, @"BioGame", @"CookedPC", @"Movies", @"niebieska_pl.bik"));
                if (IsPolishME1)
                {
                    Log.Information(@"ME1 Polish Edition detected");
                }

                if (RegistryActive && Settings.AutoUpdateLODs && oldTMOption != TextureModded)
                {
                    UpdateLODs();
                }
            }
        }
Exemplo n.º 9
0
        public void PopulateModifiedBasegameFiles(Func <string, bool> restoreBasegamefileConfirmationCallback,
                                                  Func <string, bool> restoreSfarConfirmationCallback,
                                                  Action notifySFARRestoringCallback,
                                                  Action notifyFileRestoringCallback,
                                                  Action <object> notifyRestoredCallback)
        {
            ModifiedBasegameFiles.ClearEx();
            ModifiedSFARFiles.ClearEx();

            List <string> modifiedSfars = new List <string>();
            List <string> modifiedFiles = new List <string>();

            void failedCallback(string file)
            {
                if (file.EndsWith(@".sfar"))
                {
                    modifiedSfars.Add(file);
                    return;
                }

                if (file == getALOTMarkerFilePath())
                {
                    return; //Do not report this file as modified or user will desync game state with texture state
                }
                modifiedFiles.Add(file);
            }

            VanillaDatabaseService.ValidateTargetAgainstVanilla(this, failedCallback);

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

            VanillaDatabaseService.ValidateTargetDLCConsistency(this, x => inconsistentDLC.Add(x));

            modifiedSfars.AddRange(inconsistentDLC.Select(x => Path.Combine(x, "CookedPCConsole", "Default.sfar")));
            modifiedSfars = modifiedSfars.Distinct().ToList(); //filter out if modified + inconsistent

            ModifiedSFARFiles.AddRange(modifiedSfars.Select(file => new SFARObject(file, this, restoreSfarConfirmationCallback, notifySFARRestoringCallback, notifyRestoredCallback)));
            ModifiedBasegameFiles.AddRange(modifiedFiles.Select(file => new ModifiedFileObject(file.Substring(TargetPath.Length + 1), this,
                                                                                               restoreBasegamefileConfirmationCallback,
                                                                                               notifyFileRestoringCallback,
                                                                                               notifyRestoredCallback)));
        }
Exemplo n.º 10
0
        public static Dictionary <string, int> GetMountPriorities(GameTarget selectedTarget)
        {
            //make dictionary from basegame files
            var dlcmods      = VanillaDatabaseService.GetInstalledDLCMods(selectedTarget);
            var mountMapping = new Dictionary <string, int>();

            foreach (var dlc in dlcmods)
            {
                var mountpath = Path.Combine(MEDirectories.DLCPath(selectedTarget), dlc);
                try
                {
                    mountMapping[dlc] = MELoadedFiles.GetMountPriority(mountpath, selectedTarget.Game);
                }
                catch (Exception e)
                {
                    Log.Error($"Exception getting mount priority from file: {mountpath}: {e.Message}");
                }
            }

            return(mountMapping);
        }
        private void LoadME1FilesList()
        {
            var me1files = new List <BackupFile>();
            var bup      = BackupService.GetGameBackupPath(Mod.MEGame.ME1);

            if (bup != null)
            {
                var target     = new GameTarget(Mod.MEGame.ME1, bup, false);
                var cookedPath = MEDirectories.CookedPath(target);
                foreach (var f in Extensions.GetFiles(cookedPath, @"\.u|\.upk|\.sfm", SearchOption.AllDirectories))
                {
                    me1files.Add(new BackupFile(@"BASEGAME", Path.GetFileName(f)));
                }
                me1files.Sort(); //sort basegame

                var dlcDir      = MEDirectories.DLCPath(target);
                var officialDLC = VanillaDatabaseService.GetInstalledOfficialDLC(target);
                foreach (var v in officialDLC)
                {
                    var cookedDLCPath = Path.Combine(dlcDir, v, @"CookedPC");
                    if (Directory.Exists(cookedDLCPath))
                    {
                        var filesToAdd = new List <BackupFile>();

                        foreach (var f in Extensions.GetFiles(cookedDLCPath, @"\.u|\.upk|\.sfm", SearchOption.AllDirectories))
                        {
                            filesToAdd.Add(new BackupFile(v, Path.GetFileName(f)));
                        }
                        filesToAdd.Sort();
                        me1files.AddRange(filesToAdd);
                    }
                }
            }

            Application.Current.Dispatcher.Invoke(delegate
            {
                ME1Files.ReplaceAll(me1files);
            });
            Debug.WriteLine(@"Num ME1 files: " + ME2Files.Count);
        }
Exemplo n.º 12
0
 public void OnSelectedTargetChanged()
 {
     InstalledDLCs.ClearEx();
     if (SelectedTarget != null)
     {
         // maps DLC folder name -> mount number
         var installedDlc = VanillaDatabaseService.GetInstalledOfficialDLC(SelectedTarget, true);
         foreach (var dlc in installedDlc)
         {
             Debug.WriteLine(dlc);
             var foldername = dlc.TrimStart('x');
             InstalledDLCs.Add(new InstalledDLC()
             {
                 target          = SelectedTarget,
                 DLCFolderName   = dlc,
                 UIDLCFolderName = foldername,
                 Enabled         = !dlc.StartsWith('x'),
                 HumanName       = ThirdPartyServices.GetThirdPartyModInfo(foldername, SelectedTarget.Game).modname
             });
         }
     }
 }
Exemplo n.º 13
0
        public GameTarget(Mod.MEGame game, string target, bool currentRegistryActive, bool isCustomOption = false)
        {
            this.Game           = game;
            this.RegistryActive = currentRegistryActive;
            this.IsCustomOption = isCustomOption;
            this.TargetPath     = target.TrimEnd('\\');
            if (game != Mod.MEGame.Unknown && !IsCustomOption)
            {
                var alotInfo = GetInstalledALOTInfo();
                if (alotInfo != null)
                {
                    ALOTInstalled = true;
                    ALOTVersion   = alotInfo.ToString();
                    if (alotInfo.MEUITMVER > 0)
                    {
                        MEUITMInstalled = true;
                        MEUITMVersion   = alotInfo.MEUITMVER;
                    }
                }
                Log.Information(@"Getting game source for target " + TargetPath);
                var hashCheckResult = VanillaDatabaseService.GetGameSource(this);

                GameSource = hashCheckResult.result;
                if (GameSource == null)
                {
                    Log.Error(@"Unknown source or illegitimate installation: " + hashCheckResult.hash);
                }
                else
                {
                    Log.Information(@"Source: " + GameSource);
                }
                IsPolishME1 = game == Mod.MEGame.ME1 && File.Exists(Path.Combine(target, @"BioGame", @"CookedPC", @"Movies", @"niebieska_pl.bik"));
                if (IsPolishME1)
                {
                    Log.Information(@"ME1 Polish Edition detected");
                }
            }
        }
Exemplo n.º 14
0
        public override void OnPanelVisible()
        {
            var installedDLCMods = VanillaDatabaseService.GetInstalledDLCMods(target);
            var uiModInstalled   = installedDLCMods.Intersect(DLCUIModFolderNames).Any();

            if (uiModInstalled)
            {
                var result = M3L.ShowDialog(window, M3L.GetString(M3L.string_dialogWhatGuiCompatPackIsFor), M3L.GetString(M3L.string_confirmGeneration), MessageBoxButton.YesNo, MessageBoxImage.Warning);
                if (result == MessageBoxResult.No)
                {
                    OnClosing(DataEventArgs.Empty);
                    return;
                }

                StartGuiCompatibilityScanner();
            }
            else
            {
                Log.Information(@"No UI mods are installed. Cannot run GUI Compat Generator");
                M3L.ShowDialog(window, M3L.GetString(M3L.string_dialogNoUiModsAreInstalled), M3L.GetString(M3L.string_noUiModsAreInstalled), MessageBoxButton.OK, MessageBoxImage.Error);
                OnClosing(DataEventArgs.Empty);
            }
        }
Exemplo n.º 15
0
        public void PopulateModifiedBasegameFiles(Func <string, bool> restoreBasegamefileConfirmationCallback,
                                                  Func <string, bool> restoreSfarConfirmationCallback,
                                                  Action notifySFARRestoringCallback,
                                                  Action notifyFileRestoringCallback,
                                                  Action <object> notifyRestoredCallback)
        {
            ModifiedBasegameFiles.ClearEx();
            ModifiedSFARFiles.ClearEx();
            void failedCallback(string file)
            {
                //todo: Filter out SFARs?
                if (file.EndsWith(@".sfar"))
                {
                    ModifiedSFARFiles.Add(new SFARObject(file, this, restoreSfarConfirmationCallback, notifySFARRestoringCallback, notifyRestoredCallback));
                    return;
                }
                ModifiedBasegameFiles.Add(new ModifiedFileObject(file.Substring(TargetPath.Length + 1), this,
                                                                 restoreBasegamefileConfirmationCallback,
                                                                 notifyFileRestoringCallback,
                                                                 notifyRestoredCallback));
            }

            VanillaDatabaseService.ValidateTargetAgainstVanilla(this, failedCallback);
        }
            private void BeginBackup()
            {
                if (Utilities.IsGameRunning(BackupSourceTarget.Game))
                {
                    M3L.ShowDialog(window, M3L.GetString(M3L.string_interp_cannotBackupGameWhileRunning, Utilities.GetGameName(BackupSourceTarget.Game)), M3L.GetString(M3L.string_gameRunning), MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }
                NamedBackgroundWorker bw = new NamedBackgroundWorker(Game.ToString() + @"Backup");

                bw.DoWork += (a, b) =>
                {
                    BackupInProgress = true;
                    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 (BackupSourceTarget.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);
                    VanillaDatabaseService.LoadDatabaseFor(Game);
                    bool          isVanilla        = VanillaDatabaseService.ValidateTargetAgainstVanilla(BackupSourceTarget, nonVanillaFileFoundCallback);
                    bool          isDLCConsistent  = VanillaDatabaseService.ValidateTargetDLCConsistency(BackupSourceTarget, inconsistentDLCCallback: inconsistentDLCFoundCallback);
                    List <string> dlcModsInstalled = VanillaDatabaseService.GetInstalledDLCMods(BackupSourceTarget);


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

                        string backupPath = null;
                        bool   end        = false;
                        Application.Current.Dispatcher.Invoke(delegate
                        {
                            Log.Error(@"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)
                            {
                                //Check empty
                                backupPath = m.FileName;
                                if (Directory.Exists(backupPath))
                                {
                                    if (Directory.GetFiles(backupPath).Length > 0 || Directory.GetDirectories(backupPath).Length > 0)
                                    {
                                        //Directory not empty
                                        Log.Error(@"Selected backup directory is not empty.");
                                        M3L.ShowDialog(window, M3L.GetString(M3L.string_directoryIsNotEmptyMustBeEmpty), M3L.GetString(M3L.string_directoryNotEmpty), MessageBoxButton.OK, MessageBoxImage.Error);
                                        end = true;
                                        EndBackup();
                                        return;
                                    }
                                }
                            }
                            else
                            {
                                end = true;
                                EndBackup();
                                return;
                            }
                        });
                        if (end)
                        {
                            return;
                        }

                        #region callbacks
                        void fileCopiedCallback()
                        {
                            ProgressValue++;
                        }

                        string dlcFolderpath   = MEDirectories.DLCPath(BackupSourceTarget) + '\\';
                        int    dlcSubStringLen = dlcFolderpath.Length;
                        bool aboutToCopyCallback(string file)
                        {
                            if (file.Contains(@"\cmmbackup\"))
                            {
                                return(false);                               //do not copy cmmbackup files
                            }
                            if (file.StartsWith(dlcFolderpath))
                            {
                                //It's a DLC!
                                string dlcname = file.Substring(dlcSubStringLen);
                                dlcname = dlcname.Substring(0, dlcname.IndexOf('\\'));
                                if (MEDirectories.OfficialDLCNames(BackupSourceTarget.Game).TryGetValue(dlcname, out var hrName))
                                {
                                    BackupStatusLine2 = M3L.GetString(M3L.string_interp_backingUpX, hrName);
                                }
                                else
                                {
                                    BackupStatusLine2 = M3L.GetString(M3L.string_interp_backingUpX, dlcname);
                                }
                            }
                            else
                            {
                                //It's basegame
                                if (file.EndsWith(@".bik"))
                                {
                                    BackupStatusLine2 = M3L.GetString(M3L.string_interp_backingUpX, 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.string_basegame);
                                }
                            }
                            return(true);
                        }

                        void totalFilesToCopyCallback(int total)
                        {
                            ProgressValue         = 0;
                            ProgressIndeterminate = false;
                            ProgressMax           = total;
                        }

                        #endregion
                        BackupStatus = M3L.GetString(M3L.string_creatingBackup);


                        CopyDir.CopyAll_ProgressBar(new DirectoryInfo(BackupSourceTarget.TargetPath), new DirectoryInfo(backupPath),
                                                    totalItemsToCopyCallback: totalFilesToCopyCallback,
                                                    aboutToCopyCallback: aboutToCopyCallback,
                                                    fileCopiedCallback: fileCopiedCallback,
                                                    ignoredExtensions: new[] { @"*.pdf", @"*.mp3" });
                        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;
                        }
                        Analytics.TrackEvent(@"Created a backup", new Dictionary <string, string>()
                        {
                            { @"Game", Game.ToString() },
                            { @"Result", @"Success" }
                        });

                        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 (BackupSourceTarget.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();
                };
                bw.RunWorkerCompleted += (a, b) =>
                {
                    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();
                };
                bw.RunWorkerAsync();
            }
Exemplo n.º 17
0
        private void StartGuiCompatibilityScanner()
        {
            NamedBackgroundWorker bw = new NamedBackgroundWorker(@"GUICompatibilityScanner");

            bw.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 = getFileSupercedances().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(), filesToBePatched.Count == 1 ? singlesuffix : pluralsuffix);
                                            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;
                            var generatedMod = GenerateCompatibilityPackForFiles(nonUIinstalledDLCMods, filesToBePatched.Keys.ToList(), libraryArchive);
                            b.Result = GUICompatibilityThreadResult.GENERATED_PACK;
                            Application.Current.Dispatcher.Invoke(delegate { ((MainWindow)window).LoadMods(generatedMod); }); //reload to this mod
                        }
                    }

                    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;
                }
            };
            bw.RunWorkerCompleted += (a, b) =>
            {
                if (b.Result is GUICompatibilityThreadResult gctr)
                {
                    Analytics.TrackEvent(@"Generated a UI compatibility pack", new Dictionary <string, string>()
                    {
                        { @"Result", gctr.ToString() }
                    });
                    OnClosing(DataEventArgs.Empty);
                }
                else
                {
                    throw new Exception(@"GUI Compatibility generator thread did not return a result! Please report this to ME3Tweaks");
                }
            };
            bw.RunWorkerAsync();
        }
Exemplo n.º 18
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();
            }
Exemplo n.º 19
0
            private void BeginBackup()
            {
                if (Utilities.IsGameRunning(BackupSourceTarget.Game))
                {
                    M3L.ShowDialog(window, M3L.GetString(M3L.string_interp_cannotBackupGameWhileRunning, Utilities.GetGameName(BackupSourceTarget.Game)), M3L.GetString(M3L.string_gameRunning), MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }
                NamedBackgroundWorker bw = new NamedBackgroundWorker(Game.ToString() + @"Backup");

                bw.DoWork += (a, b) =>
                {
                    BackupInProgress = true;
                    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 (BackupSourceTarget.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);
                    VanillaDatabaseService.LoadDatabaseFor(Game);
                    bool          isVanilla        = VanillaDatabaseService.ValidateTargetAgainstVanilla(BackupSourceTarget, nonVanillaFileFoundCallback);
                    bool          isDLCConsistent  = VanillaDatabaseService.ValidateTargetDLCConsistency(BackupSourceTarget, inconsistentDLCCallback: inconsistentDLCFoundCallback);
                    List <string> dlcModsInstalled = VanillaDatabaseService.GetInstalledDLCMods(BackupSourceTarget);
                    List <string> installedDLC     = VanillaDatabaseService.GetInstalledOfficialDLC(BackupSourceTarget);
                    List <string> allOfficialDLC   = MEDirectories.OfficialDLC(BackupSourceTarget.Game);

                    bool end = false;

                    if (installedDLC.Count() < allOfficialDLC.Count())
                    {
                        var dlcList = string.Join("\n - ", allOfficialDLC.Except(installedDLC).Select(x => $@"{MEDirectories.OfficialDLCNames(BackupSourceTarget.Game)[x]} ({x})")); //do not localize
                        dlcList = @" - " + 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)
                    {
                        if (isVanilla && isDLCConsistent && dlcModsInstalled.Count == 0)
                        {
                            BackupStatus = M3L.GetString(M3L.string_waitingForUserInput);

                            string backupPath = null;
                            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);

                                    //Check empty
                                    if (Directory.Exists(backupPath))
                                    {
                                        if (Directory.GetFiles(backupPath).Length > 0 ||
                                            Directory.GetDirectories(backupPath).Length > 0)
                                        {
                                            //Directory not empty
                                            Log.Error(@"Selected backup directory is not empty.");
                                            M3L.ShowDialog(window,
                                                           M3L.GetString(M3L.string_directoryIsNotEmptyMustBeEmpty),
                                                           M3L.GetString(M3L.string_directoryNotEmpty), MessageBoxButton.OK,
                                                           MessageBoxImage.Error);
                                            end = true;
                                            EndBackup();
                                            return;
                                        }
                                    }

                                    //Check space
                                    Utilities.GetDiskFreeSpaceEx(backupPath, out var freeBytes, out var totalBytes,
                                                                 out var totalFreeBytes);
                                    var requiredSpace =
                                        Utilities.GetSizeOfDirectory(BackupSourceTarget.TargetPath) * 1.1; //10% buffer

                                    if (freeBytes < requiredSpace)
                                    {
                                        //Not enough space.
                                        Log.Error(
                                            $@"Not enough disk spcae to create backup at {backupPath}. Required space: {ByteSize.FromBytes(requiredSpace)} Free space: {ByteSize.FromBytes(freeBytes)}");
                                        M3L.ShowDialog(window,
                                                       M3L.GetString(M3L.string_dialogInsufficientDiskSpace,
                                                                     Path.GetPathRoot(backupPath), ByteSize.FromBytes(freeBytes).ToString(),
                                                                     ByteSize.FromBytes(requiredSpace).ToString()),
                                                       M3L.GetString(M3L.string_insufficientDiskSpace), MessageBoxButton.OK,
                                                       MessageBoxImage.Error);
                                        end = true;
                                        EndBackup();
                                        return;
                                    }

                                    //Check it is not subdirectory of the game (we might want ot check its not subdir of a target)
                                    foreach (var target in AvailableBackupSources)
                                    {
                                        if (backupPath.IsSubPathOf(target.TargetPath))
                                        {
                                            //Not enough space.
                                            Log.Error(
                                                $@"A backup cannot be created in a subdirectory of a game. {backupPath} is a subdir of {BackupSourceTarget.TargetPath}");
                                            M3L.ShowDialog(window,
                                                           M3L.GetString(M3L.string_dialogBackupCannotBeSubdirectoryOfGame,
                                                                         backupPath, target.TargetPath),
                                                           M3L.GetString(M3L.string_cannotCreateBackup), MessageBoxButton.OK,
                                                           MessageBoxImage.Error);
                                            end = true;
                                            EndBackup();
                                            return;
                                        }
                                    }
                                }
                                else
                                {
                                    end = true;
                                    EndBackup();
                                    return;
                                }
                            });
                            if (end)
                            {
                                return;
                            }

                            #region callbacks

                            void fileCopiedCallback()
                            {
                                ProgressValue++;
                            }

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

                            bool aboutToCopyCallback(string file)
                            {
                                try
                                {
                                    if (file.Contains(@"\cmmbackup\"))
                                    {
                                        return(false);                               //do not copy cmmbackup files
                                    }
                                    if (file.StartsWith(dlcFolderpath))
                                    {
                                        //It's a DLC!
                                        string dlcname = file.Substring(dlcSubStringLen);
                                        dlcname = dlcname.Substring(0, dlcname.IndexOf('\\'));
                                        if (MEDirectories.OfficialDLCNames(BackupSourceTarget.Game)
                                            .TryGetValue(dlcname, out var hrName))
                                        {
                                            BackupStatusLine2 = M3L.GetString(M3L.string_interp_backingUpX, hrName);
                                        }
                                        else
                                        {
                                            BackupStatusLine2 = M3L.GetString(M3L.string_interp_backingUpX, dlcname);
                                        }
                                    }
                                    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;
                            }

                            #endregion

                            BackupStatus = M3L.GetString(M3L.string_creatingBackup);

                            Log.Information($@"Backing up {BackupSourceTarget.TargetPath} to {backupPath}");

                            CopyDir.CopyAll_ProgressBar(new DirectoryInfo(BackupSourceTarget.TargetPath),
                                                        new DirectoryInfo(backupPath),
                                                        totalItemsToCopyCallback: totalFilesToCopyCallback,
                                                        aboutToCopyCallback: aboutToCopyCallback,
                                                        fileCopiedCallback: fileCopiedCallback,
                                                        ignoredExtensions: new[] { @"*.pdf", @"*.mp3" });
                            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;
                            }
                            Log.Information($@"Writing cmm_vanilla");

                            File.Create(Path.Combine(backupPath, "cmm_vanilla")).Close();

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

                            Analytics.TrackEvent(@"Created a backup", new Dictionary <string, string>()
                            {
                                { @"Game", Game.ToString() },
                                { @"Result", @"Success" }
                            });

                            EndBackup();
                            return;
                        }
            private void BeginBackup()
            {
                if (Utilities.IsGameRunning(BackupSourceTarget.Game))
                {
                    Xceed.Wpf.Toolkit.MessageBox.Show(window, $"Cannot backup {Utilities.GetGameName(BackupSourceTarget.Game)} while it is running.", $"Game is running", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }
                NamedBackgroundWorker bw = new NamedBackgroundWorker(Game.ToString() + "Backup");

                bw.DoWork += (a, b) =>
                {
                    BackupInProgress = true;
                    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 (BackupSourceTarget.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          = "Validating backup source";
                    VanillaDatabaseService.LoadDatabaseFor(Game);
                    bool          isVanilla        = VanillaDatabaseService.ValidateTargetAgainstVanilla(BackupSourceTarget, nonVanillaFileFoundCallback);
                    bool          isDLCConsistent  = VanillaDatabaseService.ValidateTargetDLCConsistency(BackupSourceTarget, inconsistentDLCCallback: inconsistentDLCFoundCallback);
                    List <string> dlcModsInstalled = VanillaDatabaseService.GetInstalledDLCMods(BackupSourceTarget);


                    if (isVanilla && isDLCConsistent && dlcModsInstalled.Count == 0)
                    {
                        BackupStatus = "Waiting for user input";
                        string backupPath = null;
                        bool   end        = false;
                        Application.Current.Dispatcher.Invoke(delegate
                        {
                            CommonOpenFileDialog m = new CommonOpenFileDialog
                            {
                                IsFolderPicker   = true,
                                EnsurePathExists = true,
                                Title            = "Select backup destination"
                            };
                            if (m.ShowDialog() == CommonFileDialogResult.Ok)
                            {
                                //Check empty
                                backupPath = m.FileName;
                                if (Directory.Exists(backupPath))
                                {
                                    if (Directory.GetFiles(backupPath).Length > 0 || Directory.GetDirectories(backupPath).Length > 0)
                                    {
                                        //Directory not empty
                                        MessageBox.Show("Directory is not empty. A backup destination must be empty.");
                                        end = true;
                                        EndBackup();
                                        return;
                                    }
                                }
                            }
                            else
                            {
                                end = true;
                                EndBackup();
                                return;
                            }
                        });
                        if (end)
                        {
                            return;
                        }

                        #region callbacks
                        void fileCopiedCallback()
                        {
                            ProgressValue++;
                        }

                        string dlcFolderpath   = MEDirectories.DLCPath(BackupSourceTarget) + '\\';
                        int    dlcSubStringLen = dlcFolderpath.Length;
                        bool aboutToCopyCallback(string file)
                        {
                            if (file.Contains("\\cmmbackup\\"))
                            {
                                return(false);                                //do not copy cmmbackup files
                            }
                            if (file.StartsWith(dlcFolderpath))
                            {
                                //It's a DLC!
                                string dlcname = file.Substring(dlcSubStringLen);
                                dlcname = dlcname.Substring(0, dlcname.IndexOf('\\'));
                                if (MEDirectories.OfficialDLCNames(BackupSourceTarget.Game).TryGetValue(dlcname, out var hrName))
                                {
                                    BackupStatusLine2 = "Backing up " + hrName;
                                }
                                else
                                {
                                    BackupStatusLine2 = "Backing up " + dlcname;
                                }
                            }
                            else
                            {
                                //It's basegame
                                if (file.EndsWith(".bik"))
                                {
                                    BackupStatusLine2 = "Backing up Movies";
                                }
                                else if (new FileInfo(file).Length > 52428800)
                                {
                                    BackupStatusLine2 = "Backing up " + Path.GetFileName(file);
                                }
                                else
                                {
                                    BackupStatusLine2 = "Backing up BASEGAME";
                                }
                            }
                            return(true);
                        }

                        void totalFilesToCopyCallback(int total)
                        {
                            ProgressValue         = 0;
                            ProgressIndeterminate = false;
                            ProgressMax           = total;
                        }

                        #endregion
                        BackupStatus = "Creating backup";

                        CopyDir.CopyAll_ProgressBar(new DirectoryInfo(BackupSourceTarget.TargetPath), new DirectoryInfo(backupPath),
                                                    totalItemsToCopyCallback: totalFilesToCopyCallback,
                                                    aboutToCopyCallback: aboutToCopyCallback,
                                                    fileCopiedCallback: fileCopiedCallback,
                                                    ignoredExtensions: new[] { "*.pdf", "*.mp3" });
                        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;
                        }
                        Analytics.TrackEvent("Created a backup", new Dictionary <string, string>()
                        {
                            { "Game", Game.ToString() },
                            { "Result", "Success" }
                        });

                        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, "Cannot backup modified game", "The following files do not match the vanilla database and appear to be modified. Due to these files being modified, a backup cannot be taken of this installation.");
                    }
                    else if (!isDLCConsistent)
                    {
                        Analytics.TrackEvent("Created a backup", new Dictionary <string, string>()
                        {
                            { "Game", Game.ToString() },
                            { "Result", "Failure, DLC inconsistent" }
                        });
                        if (BackupSourceTarget.Supported)
                        {
                            b.Result = (inconsistentDLC, "Inconsistent DLC detected", "The following DLC are in an inconsistent state; they have a packed SFAR file but contain unpacked game files. The configuration of these DLC are not supported, the unpacked files must be manually removed.");
                        }
                        else
                        {
                            b.Result = ("Inconsistent DLC detected", "Inconsistent DLC was detected. This may be due to using an unofficial copy of the game.");
                        }
                    }
                    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, "DLC mods are installed", "The following DLC folders were detected that are not part of the official game by BioWare. Backups cannot include DLC mods - the game must be unmodified.");
                    }
                    EndBackup();
                };
                bw.RunWorkerCompleted += (a, b) =>
                {
                    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))
                    {
                        Xceed.Wpf.Toolkit.MessageBox.Show(message, errortitle, MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                    CommandManager.InvalidateRequerySuggested();
                };
                bw.RunWorkerAsync();
            }
Exemplo n.º 21
0
        private void CheckModForTFCCompactability(DeploymentChecklistItem item)
        {
            // if (ModBeingDeployed.Game >= Mod.MEGame.ME2)
            //{
            bool hasError = false;

            item.HasError = false;
            item.ItemText = M3L.GetString(M3L.string_checkingTexturesInMod);
            var        referencedFiles  = ModBeingDeployed.GetAllRelativeReferences().Select(x => Path.Combine(ModBeingDeployed.ModPath, x)).ToList();
            int        numChecked       = 0;
            GameTarget validationTarget = mainWindow.InstallationTargets.FirstOrDefault(x => x.Game == ModBeingDeployed.Game);
            var        errors           = new List <string>();

            foreach (var f in referencedFiles)
            {
                if (_closed)
                {
                    return;
                }
                numChecked++;
                item.ItemText = $@"{M3L.GetString(M3L.string_checkingTexturesInMod)} [{numChecked}/{referencedFiles.Count}]";
                if (f.RepresentsPackageFilePath())
                {
                    Log.Information(@"Checking file for broken textures: " + f);
                    var package  = MEPackageHandler.OpenMEPackage(f);
                    var textures = package.Exports.Where(x => x.IsTexture()).ToList();
                    foreach (var texture in textures)
                    {
                        if (_closed)
                        {
                            return;
                        }
                        var cache = texture.GetProperty <NameProperty>(@"TextureFileCacheName");
                        if (cache != null)
                        {
                            if (!VanillaDatabaseService.IsBasegameTFCName(cache.Value, ModBeingDeployed.Game))
                            {
                                var       mips = Texture2D.GetTexture2DMipInfos(texture, cache.Value);
                                Texture2D tex  = new Texture2D(texture);
                                try
                                {
                                    tex.GetImageBytesForMip(tex.GetTopMip(), validationTarget, false); //use active target
                                }
                                catch (Exception e)
                                {
                                    Log.Information(@"Found broken texture: " + texture.GetInstancedFullPath);
                                    hasError        = true;
                                    item.Icon       = FontAwesomeIcon.TimesCircle;
                                    item.Foreground = Brushes.Red;
                                    item.Spinning   = false;
                                    errors.Add(M3L.GetString(M3L.string_interp_couldNotLoadTextureData, texture.FileRef.FilePath, texture.GetInstancedFullPath, e.Message));
                                }
                            }
                        }
                    }
                }
            }

            if (!hasError)
            {
                item.Foreground = Brushes.Green;
                item.Icon       = FontAwesomeIcon.CheckCircle;
                item.ItemText   = M3L.GetString(M3L.string_noBrokenTexturesWereFound);
                item.ToolTip    = M3L.GetString(M3L.string_validationOK);
            }
            else
            {
                item.Errors   = errors;
                item.ItemText = M3L.GetString(M3L.string_textureIssuesWereDetected);
                item.ToolTip  = M3L.GetString(M3L.string_validationFailed);
            }
            item.HasError = hasError;
        }
Exemplo n.º 22
0
        private void CheckModForAFCCompactability(DeploymentChecklistItem item)
        {
            bool hasError = false;

            item.HasError = false;
            item.ItemText = M3L.GetString(M3L.string_checkingAudioReferencesInMod);
            var           referencedFiles  = ModBeingDeployed.GetAllRelativeReferences().Select(x => Path.Combine(ModBeingDeployed.ModPath, x)).ToList();
            int           numChecked       = 0;
            GameTarget    validationTarget = mainWindow.InstallationTargets.FirstOrDefault(x => x.Game == ModBeingDeployed.Game);
            List <string> gameFiles        = MEDirectories.EnumerateGameFiles(validationTarget.Game, validationTarget.TargetPath);

            var errors = new List <string>();
            Dictionary <string, MemoryStream> cachedAudio = new Dictionary <string, MemoryStream>();

            foreach (var f in referencedFiles)
            {
                if (_closed)
                {
                    return;
                }
                numChecked++;
                item.ItemText = $@"{M3L.GetString(M3L.string_checkingAudioReferencesInMod)} [{numChecked}/{referencedFiles.Count}]";
                if (f.RepresentsPackageFilePath())
                {
                    var package      = MEPackageHandler.OpenMEPackage(f);
                    var wwiseStreams = package.Exports.Where(x => x.ClassName == @"WwiseStream" && !x.IsDefaultObject).ToList();
                    foreach (var wwisestream in wwiseStreams)
                    {
                        if (_closed)
                        {
                            return;
                        }
                        //Check each reference.
                        var afcNameProp = wwisestream.GetProperty <NameProperty>(@"Filename");
                        if (afcNameProp != null)
                        {
                            string afcNameWithExtension = afcNameProp + @".afc";
                            int    audioSize            = BitConverter.ToInt32(wwisestream.Data, wwisestream.Data.Length - 8);
                            int    audioOffset          = BitConverter.ToInt32(wwisestream.Data, wwisestream.Data.Length - 4);

                            string afcPath               = null;
                            Stream audioStream           = null;
                            var    localDirectoryAFCPath = Path.Combine(Path.GetDirectoryName(wwisestream.FileRef.FilePath), afcNameWithExtension);
                            bool   isInOfficialArea      = false;
                            if (File.Exists(localDirectoryAFCPath))
                            {
                                //local afc
                                afcPath = localDirectoryAFCPath;
                            }
                            else
                            {
                                //Check game
                                var fullPath = gameFiles.FirstOrDefault(x => Path.GetFileName(x).Equals(afcNameWithExtension, StringComparison.InvariantCultureIgnoreCase));
                                if (fullPath != null)
                                {
                                    afcPath          = fullPath;
                                    isInOfficialArea = MEDirectories.IsInBasegame(afcPath, validationTarget) || MEDirectories.IsInOfficialDLC(afcPath, validationTarget);
                                }
                                else if (cachedAudio.TryGetValue(afcNameProp.Value.Name, out var cachedAudioStream))
                                {
                                    audioStream = cachedAudioStream;
                                    //isInOfficialArea = true; //cached from vanilla SFAR
                                }
                                else if (MEDirectories.OfficialDLC(validationTarget.Game).Any(x => afcNameProp.Value.Name.StartsWith(x)))
                                {
                                    var dlcName = afcNameProp.Value.Name.Substring(0, afcNameProp.Value.Name.LastIndexOf(@"_", StringComparison.InvariantCultureIgnoreCase));
                                    var audio   = VanillaDatabaseService.FetchFileFromVanillaSFAR(validationTarget, dlcName, afcNameWithExtension);
                                    if (audio != null)
                                    {
                                        cachedAudio[afcNameProp.Value.Name] = audio;
                                    }

                                    audioStream = audio;
                                    //isInOfficialArea = true; as this is in a vanilla SFAR we don't test against this since it will be correct.
                                    continue;
                                }
                                else
                                {
                                    hasError        = true;
                                    item.Icon       = FontAwesomeIcon.TimesCircle;
                                    item.Foreground = Brushes.Red;
                                    item.Spinning   = false;
                                    errors.Add(M3L.GetString(M3L.string_interp_couldNotFindReferencedAFC, wwisestream.FileRef.FilePath, wwisestream.GetInstancedFullPath, afcNameProp.ToString()));
                                    continue;
                                }
                            }

                            if (afcPath != null)
                            {
                                audioStream = new FileStream(afcPath, FileMode.Open);
                            }

                            try
                            {
                                audioStream.Seek(audioOffset, SeekOrigin.Begin);
                                if (audioStream.ReadStringASCIINull(4) != @"RIFF")
                                {
                                    hasError        = true;
                                    item.Icon       = FontAwesomeIcon.TimesCircle;
                                    item.Foreground = Brushes.Red;
                                    item.Spinning   = false;
                                    errors.Add(M3L.GetString(M3L.string_interp_invalidAudioPointer, wwisestream.FileRef.FilePath, wwisestream.GetInstancedFullPath));
                                    if (audioStream is FileStream)
                                    {
                                        audioStream.Close();
                                    }
                                    continue;
                                }

                                //attempt to seek audio length.
                                audioStream.Seek(audioSize + 4, SeekOrigin.Current);

                                //Check if this file is in basegame
                                if (isInOfficialArea)
                                {
                                    //Verify offset is not greater than vanilla size
                                    var vanillaInfo = VanillaDatabaseService.GetVanillaFileInfo(validationTarget, afcPath.Substring(validationTarget.TargetPath.Length + 1));
                                    if (vanillaInfo == null)
                                    {
                                        Crashes.TrackError(new Exception($@"Vanilla information was null when performing vanilla file check for {afcPath.Substring(validationTarget.TargetPath.Length + 1)}"));
                                    }
                                    if (audioOffset >= vanillaInfo[0].size)
                                    {
                                        hasError        = true;
                                        item.Icon       = FontAwesomeIcon.TimesCircle;
                                        item.Foreground = Brushes.Red;
                                        item.Spinning   = false;
                                        errors.Add(M3L.GetString(M3L.string_interp_audioStoredInOfficialAFC, wwisestream.FileRef.FilePath, wwisestream.GetInstancedFullPath));
                                    }
                                }
                                if (audioStream is FileStream)
                                {
                                    audioStream.Close();
                                }
                            }
                            catch (Exception e)
                            {
                                hasError        = true;
                                item.Icon       = FontAwesomeIcon.TimesCircle;
                                item.Foreground = Brushes.Red;
                                item.Spinning   = false;
                                if (audioStream is FileStream)
                                {
                                    audioStream.Close();
                                }
                                errors.Add(M3L.GetString(M3L.string_errorValidatingAudioReference, wwisestream.FileRef.FilePath, wwisestream.GetInstancedFullPath, e.Message));
                                continue;
                            }
                        }
                    }
                }
            }


            if (!hasError)
            {
                item.Foreground = Brushes.Green;
                item.Icon       = FontAwesomeIcon.CheckCircle;
                item.ItemText   = M3L.GetString(M3L.string_noAudioIssuesWereDetected);
                item.ToolTip    = M3L.GetString(M3L.string_validationOK);
            }
            else
            {
                item.Errors   = errors;
                item.ItemText = M3L.GetString(M3L.string_audioIssuesWereDetected);
                item.ToolTip  = M3L.GetString(M3L.string_validationFailed);
            }
            item.HasError = hasError;
            cachedAudio.Clear();
        }
Exemplo n.º 23
0
        private Mod GenerateCompatibilityPackForFiles(List <string> dlcModList, List <string> filesToBePatched, SevenZipExtractor uiArchive)
        {
            dlcModList = dlcModList.Select(x =>
            {
                var tpmi = ThirdPartyServices.GetThirdPartyModInfo(x, MEGame.ME3);
                if (tpmi == null)
                {
                    return(x);
                }
                return(tpmi.modname);
            }).ToList();
            string dlcs = string.Join("\n - ", dlcModList); // do not localize

            StarterKitOptions sko = new StarterKitOptions
            {
                ModName          = M3L.GetString(M3L.string_guiCompatibilityPack),
                ModDescription   = M3L.GetString(M3L.string_interp_compatPackModDescription, dlcs, DateTime.Now.ToString()),
                ModDeveloper     = App.AppVersionHR,
                ModDLCFolderName = UI_MOD_NAME,
                ModGame          = MEGame.ME3,
                ModInternalName  = @"UI Mod Compatibility Pack",
                ModInternalTLKID = 1420400890,
                ModMountFlag     = EMountFileFlag.ME3_SPOnly_NoSaveFileDependency,
                ModMountPriority = 31050,
                ModURL           = null,
                ModModuleNumber  = 0
            };

            Mod generatedMod = null;

            void modGenerated(Mod mod)
            {
                generatedMod = mod;
                lock (modGeneratedSignaler)
                {
                    Monitor.Pulse(modGeneratedSignaler);
                }
            }

            void skUicallback(string text)
            {
                ActionSubstring = text;
            }

            StarterKitGeneratorWindow.CreateStarterKitMod(sko, skUicallback, modGenerated);
            lock (modGeneratedSignaler)
            {
                Monitor.Wait(modGeneratedSignaler);
            }

            //Mod has been generated.

            string outputPath = Path.Combine(generatedMod.ModPath, @"DLC_MOD_" + UI_MOD_NAME, @"CookedPCConsole");

            ActionString    = M3L.GetString(M3L.string_preparingUiLibrary);
            ActionSubstring = M3L.GetString(M3L.string_decompressingData);

            int done = 0;

            CaseInsensitiveDictionary <byte[]> uiLibraryData = new CaseInsensitiveDictionary <byte[]>();
            var filesToDecompress = uiArchive.ArchiveFileData.Where(x => x.FileName.EndsWith(@".swf")).ToList();

            foreach (var f in filesToDecompress)
            {
                MemoryStream decompressedStream = new MemoryStream();
                uiArchive.ExtractFile(f.Index, decompressedStream);
                string fname = f.FileName.Substring(f.FileName.IndexOf('\\') + 1);
                fname = fname.Substring(0, fname.IndexOf(@".swf", StringComparison.InvariantCultureIgnoreCase));

                uiLibraryData[fname] = decompressedStream.ToArray();
                done++;
                Percent = getPercent(done, filesToDecompress.Count);
            }

            ActionString = M3L.GetString(M3L.string_patchingFiles);
            Percent      = 0;
            done         = 0;
            string singlesuffix = M3L.GetString(M3L.string_singularFile);
            string pluralsuffix = M3L.GetString(M3L.string_pluralFiles);

            // Logging
            Log.Information(@"The following files will be promoted in the compatibility pack:");
            foreach (var file in filesToBePatched)
            {
                Log.Information(@" - " + file);
            }

            foreach (var file in filesToBePatched)
            {
                Log.Information(@"Patching file: " + file);
                ActionSubstring = Path.GetFileName(file);
                var package = MEPackageHandler.OpenMEPackage(file);
                if (package == null)
                {
                    Log.Error(@"pPackage object is null!!!");
                }
                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 (uiLibraryData.TryGetValue(export.GetFullPath, out var newData))
                        {
                            Log.Information(@" >> Patching export " + export.GetFullPath);
                            //Patching this export.
                            var exportProperties = export.GetProperties();
                            var rawData          = exportProperties.GetProp <ArrayProperty <ByteProperty> >(@"RawData");
                            if (rawData == null)
                            {
                                Log.Error(@"Rawdata is null!!");
                            }
                            rawData.Clear();
                            rawData.AddRange(newData.Select(x => new ByteProperty(x))); //This will be terribly slow. Need to port over new ME3Exp binary data handler
                            export.WriteProperties(exportProperties);
                        }
                        else
                        {
                            Debug.WriteLine(@"Not patching gui export, file not in library: " + export.GetFullPath);
                        }
                    }

                    var outpath = Path.Combine(outputPath, Path.GetFileName(package.FilePath));
                    if (package.IsModified)
                    {
                        Log.Information(@"Saving patched package to " + outpath);
                        package.save(outpath, true);
                        done++;
                        ActionSubstring = M3L.GetString(M3L.string_interp_patchedXY, done.ToString(), done == 1 ? singlesuffix : pluralsuffix);
                    }
                    else
                    {
                        done++;
                        Log.Information(@"File was patched but data did not change! " + outpath);
                    }

                    Percent = getPercent(done, filesToBePatched.Count);
                }
                else
                {
                    throw new Exception($@"Error: {Path.GetFileName(file)} doesn't contain GUI exports! This shouldn't have been possible.");
                }
            }

            // Write builtagainst for metacmm.
            IniData iniData      = new FileIniDataParser().ReadFile(generatedMod.ModDescPath);
            var     builtAgainst = VanillaDatabaseService.GetInstalledDLCMods(target);

            builtAgainst.Remove(@"DLC_MOD_" + UI_MOD_NAME);
            iniData[@"ControllerCompat"][@"builtagainst"] = string.Join(';', builtAgainst);
            File.WriteAllText(generatedMod.ModDescPath, iniData.ToString());

            return(generatedMod);
        }
        private void CheckModForTFCCompactability(DeploymentChecklistItem item)
        {
            // if (ModBeingDeployed.Game >= Mod.MEGame.ME2)
            //{
            bool hasError = false;

            item.HasError = false;
            item.ItemText = "Checking textures in mod";
            var        referencedFiles  = ModBeingDeployed.GetAllRelativeReferences().Select(x => Path.Combine(ModBeingDeployed.ModPath, x)).ToList();
            int        numChecked       = 0;
            GameTarget validationTarget = mainWindow.InstallationTargets.FirstOrDefault(x => x.Game == ModBeingDeployed.Game);
            var        errors           = new List <string>();

            foreach (var f in referencedFiles)
            {
                if (_closed)
                {
                    return;
                }
                numChecked++;
                item.ItemText = $"Checking textures in mod [{numChecked}/{referencedFiles.Count}]";
                if (f.RepresentsPackageFilePath())
                {
                    var package  = MEPackageHandler.OpenMEPackage(f);
                    var textures = package.Exports.Where(x => x.IsTexture()).ToList();
                    foreach (var texture in textures)
                    {
                        if (_closed)
                        {
                            return;
                        }
                        var cache = texture.GetProperty <NameProperty>("TextureFileCacheName");
                        if (cache != null)
                        {
                            if (!VanillaDatabaseService.IsBasegameTFCName(cache.Value, ModBeingDeployed.Game))
                            {
                                var       mips = Texture2D.GetTexture2DMipInfos(texture, cache.Value);
                                Texture2D tex  = new Texture2D(texture);
                                try
                                {
                                    tex.GetImageBytesForMip(tex.GetTopMip(), validationTarget, false); //use active target
                                }
                                catch (Exception e)
                                {
                                    hasError        = true;
                                    item.Icon       = FontAwesomeIcon.TimesCircle;
                                    item.Foreground = Brushes.Red;
                                    item.Spinning   = false;
                                    errors.Add($"{texture.FileRef.FilePath} - {texture.GetInstancedFullPath}: Could not load texture data: {e.Message}");
                                }
                            }
                        }
                    }
                }
            }

            if (!hasError)
            {
                item.Foreground = Brushes.Green;
                item.Icon       = FontAwesomeIcon.CheckCircle;
                item.ItemText   = "No broken textures were found";
                item.ToolTip    = "Validation passed";
            }
            else
            {
                item.Errors   = errors;
                item.ItemText = "Texture issues were detected";
                item.ToolTip  = "Validation failed";
            }
            item.HasError = hasError;
            //}
            //} else
            //{
            //    item.Foreground = Brushes.Green;
            //    item.Icon = FontAwesomeIcon.CheckCircle;
            //    item.ItemText = "Textures are not ";
            //    item.ToolTip = "Validation passed";
            //}
        }
Exemplo n.º 25
0
        private void CompileIntoGame()
        {
            NamedBackgroundWorker nbw = new NamedBackgroundWorker(@"MixinManager CompileIntoGameThread");
            List <string>         failedApplications = new List <string>();

            nbw.DoWork += (a, b) =>
            {
                BottomLeftMessage   = M3L.GetString(M3L.string_compilingMixins);
                OperationInProgress = true;
                //DEBUG STUFF
#if DEBUG
                int numCoresToApplyWith = 1;
#else
                var numCoresToApplyWith = Environment.ProcessorCount;
                if (numCoresToApplyWith > 4)
                {
                    numCoresToApplyWith = 4;                          //no more than 4 as this uses a lot of memory
                }
#endif

                var mixins = AvailableOfficialMixins.Where(x => x.UISelectedForUse).ToList();
                MixinHandler.LoadPatchDataForMixins(mixins); //before dynamic
                void failedApplicationCallback(string str)
                {
                    failedApplications.Add(str);
                }

                var compilingListsPerModule = MixinHandler.GetMixinApplicationList(mixins, failedApplicationCallback);
                if (failedApplications.Any())
                {
                    //Error building list
                    Log.Information(@"Aborting mixin install due to incompatible selection of mixins");
                    return;
                }

                ProgressBarMax   = mixins.Count();
                ProgressBarValue = 0;
                int numdone = 0;

                void completedSingleApplicationCallback()
                {
                    var val = Interlocked.Increment(ref numdone);

                    ProgressBarValue = val;
                }

                //Mixins are ready to be applied
                Parallel.ForEach(compilingListsPerModule,
                                 new ParallelOptions
                {
                    MaxDegreeOfParallelism = Environment.ProcessorCount > numCoresToApplyWith
                    ? numCoresToApplyWith
                    : Environment.ProcessorCount
                }, mapping =>
                {
                    var dlcFolderName = ModMakerCompiler.ModmakerChunkNameToDLCFoldername(mapping.Key.ToString());
                    //var outdir = Path.Combine(modpath, ModMakerCompiler.HeaderToDefaultFoldername(mapping.Key), @"CookedPCConsole");
                    //Directory.CreateDirectory(outdir);
                    if (mapping.Key == ModJob.JobHeader.BASEGAME)
                    {
                        //basegame
                        foreach (var file in mapping.Value)
                        {
                            try
                            {
                                using var vanillaPackageAsStream = VanillaDatabaseService.FetchBasegameFile(Mod.MEGame.ME3, Path.GetFileName(file.Key));
                                //packageAsStream.WriteToFile(@"C:\users\dev\desktop\compressed.pcc");
                                using var decompressedStream = MEPackage.GetDecompressedPackageStream(vanillaPackageAsStream, true);
                                decompressedStream.Position  = 0;
                                var vanillaPackage           = MEPackageHandler.OpenMEPackage(decompressedStream, $@"Vanilla - {Path.GetFileName(file.Key)}");
                                //decompressedStream.WriteToFile(@"C:\users\dev\desktop\decompressed.pcc");

                                using var mixinModifiedStream = MixinHandler.ApplyMixins(decompressedStream, file.Value,
                                                                                         completedSingleApplicationCallback, failedApplicationCallback);
                                mixinModifiedStream.Position = 0;
                                var modifiedPackage          = MEPackageHandler.OpenMEPackage(mixinModifiedStream, $@"Mixin Modified - {Path.GetFileName(file.Key)}");

                                // three way merge: get target stream
                                var targetFile    = Path.Combine(MEDirectories.CookedPath(SelectedInstallTarget), Path.GetFileName(file.Key));
                                var targetPackage = MEPackageHandler.OpenMEPackage(targetFile);

                                var merged = ThreeWayPackageMerge.AttemptMerge(vanillaPackage, modifiedPackage, targetPackage);
                                if (merged)
                                {
                                    targetPackage.save();
                                    Log.Information("Three way merge succeeded for " + targetFile);
                                }
                                else
                                {
                                    Log.Error("Could not merge three way merge into " + targetFile);
                                }
                                //var outfile = Path.Combine(outdir, Path.GetFileName(file.Key));
                                //package.save(outfile, false); // don't compress
                                //finalStream.WriteToFile(outfile);
                                //File.WriteAllBytes(outfile, finalStream.ToArray());
                            }
                            catch (Exception e)
                            {
                                var mixinsStr = string.Join(@", ", file.Value.Select(x => x.PatchName));
                                Log.Error($@"Error in mixin application for file {file.Key}: {e.Message}");
                                failedApplicationCallback(M3L.GetString(M3L.string_interp_errorApplyingMixinsForFile, mixinsStr, file.Key, e.Message));
                            }
                        }
                    }
                    else
                    {
                        //dlc
                        var dlcPackage        = VanillaDatabaseService.FetchVanillaSFAR(dlcFolderName); //do not have to open file multiple times.
                        var targetCookedPCDir = Path.Combine(MEDirectories.DLCPath(SelectedInstallTarget), dlcFolderName, @"CookedPCConsole");
                        var sfar      = mapping.Key == ModJob.JobHeader.TESTPATCH ? Utilities.GetTestPatchPath(SelectedInstallTarget) : Path.Combine(targetCookedPCDir, @"Default.sfar");
                        bool unpacked = new FileInfo(sfar).Length == 32;
                        DLCPackage targetDLCPackage = unpacked ? null : new DLCPackage(sfar); //cache SFAR target

                        foreach (var file in mapping.Value)
                        {
                            try
                            {
                                using var vanillaPackageAsStream = VanillaDatabaseService.FetchFileFromVanillaSFAR(dlcFolderName, file.Key, forcedDLC: dlcPackage);
                                using var decompressedStream     = MEPackage.GetDecompressedPackageStream(vanillaPackageAsStream);
                                decompressedStream.Position      = 0;
                                var vanillaPackage            = MEPackageHandler.OpenMEPackage(decompressedStream, $@"VanillaDLC - {Path.GetFileName(file.Key)}");
                                using var mixinModifiedStream = MixinHandler.ApplyMixins(decompressedStream, file.Value, completedSingleApplicationCallback, failedApplicationCallback);
                                mixinModifiedStream.Position  = 0;
                                var modifiedPackage           = MEPackageHandler.OpenMEPackage(mixinModifiedStream, $@"Mixin Modified - {Path.GetFileName(file.Key)}");

                                // three way merge: get target stream
                                // must see if DLC is unpacked first

                                MemoryStream targetFileStream = null;

                                //Packed
                                if (unpacked)
                                {
                                    targetFileStream = new MemoryStream(File.ReadAllBytes(Path.Combine(targetCookedPCDir, file.Key)));
                                }
                                else
                                {
                                    targetFileStream = VanillaDatabaseService.FetchFileFromVanillaSFAR(dlcFolderName, Path.GetFileName(file.Key), forcedDLC: targetDLCPackage);
                                }

                                var targetPackage = MEPackageHandler.OpenMEPackage(targetFileStream, $@"Target package {dlcFolderName} - {file.Key}, from SFAR: {unpacked}");

                                var merged = ThreeWayPackageMerge.AttemptMerge(vanillaPackage, modifiedPackage, targetPackage);
                                if (merged)
                                {
                                    if (unpacked)
                                    {
                                        targetPackage.save();
                                        Log.Information("Three way merge succeeded for " + targetPackage.FilePath);
                                    }
                                    else
                                    {
                                        var finalSTream = targetPackage.saveToStream();
                                        targetDLCPackage.ReplaceEntry(finalSTream.ToArray(), targetDLCPackage.FindFileEntry(Path.GetFileName(file.Key)));
                                        Log.Information("Three way merge succeeded for " + targetPackage.FileSourceForDebugging);
                                    }
                                }
                                else
                                {
                                    Log.Error("Could not merge three way merge into " + targetFileStream);
                                }
                            }
                            catch (Exception e)
                            {
                                var mixinsStr = string.Join(@", ", file.Value.Select(x => x.PatchName));
                                Log.Error($@"Error in mixin application for file {file.Key}: {e.Message}");
                                failedApplicationCallback(M3L.GetString(M3L.string_interp_errorApplyingMixinsForFile, mixinsStr, file.Key, e.Message));
                            }

                            //finalStream.WriteToFile(outfile);
                        }
                    }
                });

                MixinHandler.FreeME3TweaksPatchData();
                var percent = 0; //this is used to save a localization
                BottomLeftMessage = $"Running AutoTOC on game {percent}%";

                //Run autotoc
                void tocingUpdate(int percent)
                {
                    BottomLeftMessage = $"Running AutoTOC on game {percent}%";
                }

                AutoTOC.RunTOCOnGameTarget(SelectedInstallTarget, tocingUpdate);

                //Generate moddesc
                //IniData ini = new IniData();
                //ini[@"ModManager"][@"cmmver"] = App.HighestSupportedModDesc.ToString(CultureInfo.InvariantCulture); //prevent commas
                //ini[@"ModInfo"][@"game"] = @"ME3";
                //ini[@"ModInfo"][@"modname"] = modname;
                //ini[@"ModInfo"][@"moddev"] = App.AppVersionHR;
                //ini[@"ModInfo"][@"moddesc"] = M3L.GetString(M3L.string_compiledFromTheFollowingMixins);
                //ini[@"ModInfo"][@"modver"] = @"1.0";

                //generateRepaceFilesMapping(ini, modpath);
                //File.WriteAllText(Path.Combine(modpath, @"moddesc.ini"), ini.ToString());
            };
            nbw.RunWorkerCompleted += (a, b) =>
            {
                OperationInProgress = false;
                ClearMixinHandler();
                if (failedApplications.Count > 0)
                {
                    var ld = new ListDialog(failedApplications, M3L.GetString(M3L.string_failedToApplyAllMixins), M3L.GetString(M3L.string_theFollowingMixinsFailedToApply), mainwindow);
                    ld.ShowDialog();
                }

                /*if (modpath != null)
                 * {
                 *  OnClosing(new DataEventArgs(modpath));
                 * }
                 * else
                 * {*/
                BottomLeftMessage = "Mixins installed, maybe. Check logs";
                //}
            };
            CompilePanelButton.IsOpen = false;
            nbw.RunWorkerAsync();
        }
Exemplo n.º 26
0
        private void CompileAsNewMod()
        {
            NamedBackgroundWorker nbw = new NamedBackgroundWorker(@"MixinManager CompileAsNewModThread");
            List <string>         failedApplications = new List <string>();
            var modname = NewModName;
            var modpath = Path.Combine(Utilities.GetME3ModsDirectory(), Utilities.SanitizePath(modname));
            var result  = M3L.ShowDialog(mainwindow, M3L.GetString(M3L.string_interp_dialogCreatingNewModWithExistingName, NewModName, modpath), M3L.GetString(M3L.string_modAlreadyExists), MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);

            if (result == MessageBoxResult.No)
            {
                Log.Information(@"User has aborted mixin compilation due to same-named mod existing");
                return; //abort.
            }



            nbw.DoWork += (a, b) =>
            {
                BottomLeftMessage   = M3L.GetString(M3L.string_compilingMixins);
                OperationInProgress = true;
                //DEBUG STUFF
#if DEBUG
                int numCoresToApplyWith = 1;
#else
                var numCoresToApplyWith = Environment.ProcessorCount;
                if (numCoresToApplyWith > 4)
                {
                    numCoresToApplyWith = 4;                          //no more than 4 as this uses a lot of memory
                }
#endif

                var mixins = AvailableOfficialMixins.Where(x => x.UISelectedForUse).ToList();
                MixinHandler.LoadPatchDataForMixins(mixins); //before dynamic
                void failedApplicationCallback(string str)
                {
                    failedApplications.Add(str);
                }

                var compilingListsPerModule = MixinHandler.GetMixinApplicationList(mixins, failedApplicationCallback);
                if (failedApplications.Any())
                {
                    //Error building list
                    modpath = null;
                    Log.Information(@"Aborting mixin compiling due to incompatible selection of mixins");
                    return;
                }

                if (Directory.Exists(modpath))
                {
                    Utilities.DeleteFilesAndFoldersRecursively(modpath);
                }

                ProgressBarMax   = mixins.Count();
                ProgressBarValue = 0;
                int numdone = 0;

                void completedSingleApplicationCallback()
                {
                    var val = Interlocked.Increment(ref numdone);

                    ProgressBarValue = val;
                }

                //Mixins are ready to be applied
                Parallel.ForEach(compilingListsPerModule,
                                 new ParallelOptions
                {
                    MaxDegreeOfParallelism = Environment.ProcessorCount > numCoresToApplyWith
                        ? numCoresToApplyWith
                        : Environment.ProcessorCount
                }, mapping =>
                {
                    var dlcFolderName = ModMakerCompiler.ModmakerChunkNameToDLCFoldername(mapping.Key.ToString());
                    var outdir        = Path.Combine(modpath, ModMakerCompiler.HeaderToDefaultFoldername(mapping.Key), @"CookedPCConsole");
                    Directory.CreateDirectory(outdir);
                    if (mapping.Key == ModJob.JobHeader.BASEGAME)
                    {
                        //basegame
                        foreach (var file in mapping.Value)
                        {
                            try
                            {
                                using var packageAsStream =
                                          VanillaDatabaseService.FetchBasegameFile(Mod.MEGame.ME3,
                                                                                   Path.GetFileName(file.Key));
                                //packageAsStream.WriteToFile(@"C:\users\dev\desktop\compressed.pcc");
                                using var decompressedStream = MEPackage.GetDecompressedPackageStream(packageAsStream, true);
                                //decompressedStream.WriteToFile(@"C:\users\dev\desktop\decompressed.pcc");

                                using var finalStream = MixinHandler.ApplyMixins(decompressedStream, file.Value,
                                                                                 completedSingleApplicationCallback, failedApplicationCallback);
                                CLog.Information(@"Compressing package to mod directory: " + file.Key, Settings.LogModMakerCompiler);
                                finalStream.Position = 0;
                                var package          = MEPackageHandler.OpenMEPackage(finalStream);
                                var outfile          = Path.Combine(outdir, Path.GetFileName(file.Key));
                                package.save(outfile, false); // don't compress
                                                              //finalStream.WriteToFile(outfile);
                                                              //File.WriteAllBytes(outfile, finalStream.ToArray());
                            }
                            catch (Exception e)
                            {
                                var mixinsStr = string.Join(@", ", file.Value.Select(x => x.PatchName));
                                Log.Error($@"Error in mixin application for file {file.Key}: {e.Message}");
                                failedApplicationCallback(M3L.GetString(M3L.string_interp_errorApplyingMixinsForFile, mixinsStr, file.Key, e.Message));
                            }
                        }
                    }
                    else
                    {
                        //dlc
                        var dlcPackage = VanillaDatabaseService.FetchVanillaSFAR(dlcFolderName); //do not have to open file multiple times.
                        foreach (var file in mapping.Value)
                        {
                            try
                            {
                                using var packageAsStream =
                                          VanillaDatabaseService.FetchFileFromVanillaSFAR(dlcFolderName, file.Key, forcedDLC: dlcPackage);
                                using var decompressedStream = MEPackage.GetDecompressedPackageStream(packageAsStream);
                                using var finalStream        = MixinHandler.ApplyMixins(decompressedStream, file.Value, completedSingleApplicationCallback, failedApplicationCallback);
                                CLog.Information(@"Compressing package to mod directory: " + file.Key, Settings.LogModMakerCompiler);
                                finalStream.Position = 0;
                                var package          = MEPackageHandler.OpenMEPackage(finalStream);
                                var outfile          = Path.Combine(outdir, Path.GetFileName(file.Key));
                                package.save(outfile, true);
                            }
                            catch (Exception e)
                            {
                                var mixinsStr = string.Join(@", ", file.Value.Select(x => x.PatchName));
                                Log.Error($@"Error in mixin application for file {file.Key}: {e.Message}");
                                failedApplicationCallback(M3L.GetString(M3L.string_interp_errorApplyingMixinsForFile, mixinsStr, file.Key, e.Message));
                            }

                            //finalStream.WriteToFile(outfile);
                        }
                    }
                });

                MixinHandler.FreeME3TweaksPatchData();

                //Generate moddesc
                IniData ini = new IniData();
                ini[@"ModManager"][@"cmmver"] = App.HighestSupportedModDesc.ToString(CultureInfo.InvariantCulture); //prevent commas
                ini[@"ModInfo"][@"game"]      = @"ME3";
                ini[@"ModInfo"][@"modname"]   = modname;
                ini[@"ModInfo"][@"moddev"]    = App.AppVersionHR;
                ini[@"ModInfo"][@"moddesc"]   = M3L.GetString(M3L.string_compiledFromTheFollowingMixins);
                ini[@"ModInfo"][@"modver"]    = @"1.0";

                generateRepaceFilesMapping(ini, modpath);
                File.WriteAllText(Path.Combine(modpath, @"moddesc.ini"), ini.ToString());
            };
            nbw.RunWorkerCompleted += (a, b) =>
            {
                OperationInProgress = false;
                ClearMixinHandler();
                if (failedApplications.Count > 0)
                {
                    var ld = new ListDialog(failedApplications, M3L.GetString(M3L.string_failedToApplyAllMixins), M3L.GetString(M3L.string_theFollowingMixinsFailedToApply), mainwindow);
                    ld.ShowDialog();
                }

                if (modpath != null)
                {
                    OnClosing(new DataEventArgs(modpath));
                }
                else
                {
                    BottomLeftMessage = M3L.GetString(M3L.string_selectMixinsToCompile);
                }
            };
            CompilePanelButton.IsOpen = false;
            nbw.RunWorkerAsync();
        }
        public static void ApplyMixinsToModule(KeyValuePair <ModJob.JobHeader, Dictionary <string, List <Mixin> > > mapping, string modpath, Action completedSingleApplicationCallback, Action <string> failedApplicationCallback)
        {
            var dlcFolderName = ModMakerCompiler.ModmakerChunkNameToDLCFoldername(mapping.Key.ToString());
            var outdir        = Path.Combine(modpath, ModMakerCompiler.HeaderToDefaultFoldername(mapping.Key), @"CookedPCConsole");

            Directory.CreateDirectory(outdir);
            if (mapping.Key == ModJob.JobHeader.BASEGAME)
            {
                //basegame
                foreach (var file in mapping.Value)
                {
                    try
                    {
                        using var packageAsStream =
                                  VanillaDatabaseService.FetchBasegameFile(MEGame.ME3,
                                                                           Path.GetFileName(file.Key));
                        //packageAsStream.WriteToFile(@"C:\users\dev\desktop\compressed.pcc");
                        using var decompressedStream = MEPackage.GetDecompressedPackageStream(packageAsStream, false, true);
                        using var finalStream        = MixinHandler.ApplyMixins(decompressedStream, file.Value, true, completedSingleApplicationCallback, failedApplicationCallback);
                        CLog.Information(@"Compressing package to mod directory: " + file.Key, Settings.LogModMakerCompiler);
                        finalStream.Position = 0;
                        var package = MEPackageHandler.OpenMEPackageFromStream(finalStream);
                        var outfile = Path.Combine(outdir, Path.GetFileName(file.Key));
                        package.Save(outfile, false, includeAdditionalPackagesToCook: false, includeDependencyTable: true); // don't compress, use mixin saving rules for basegame files
                    }
                    catch (Exception e)
                    {
                        var mixinsStr = string.Join(@", ", file.Value.Select(x => x.PatchName));
                        Log.Error($@"Error in mixin application for file {file.Key}: {e.Message}");
                        failedApplicationCallback(M3L.GetString(M3L.string_interp_errorApplyingMixinsForFile, mixinsStr, file.Key, e.Message));
                    }
                }
            }
            else
            {
                //dlc
                var dlcPackage = VanillaDatabaseService.FetchVanillaSFAR(dlcFolderName); //do not have to open file multiple times.
                foreach (var file in mapping.Value)
                {
                    try
                    {
                        using var packageAsStream = VanillaDatabaseService.FetchFileFromVanillaSFAR(dlcFolderName, file.Key, forcedDLC: dlcPackage);
                        //as file comes from backup, we don't need to decompress it, it will always be decompressed in sfar
                        using var finalStream = MixinHandler.ApplyMixins(packageAsStream, file.Value, true, completedSingleApplicationCallback, failedApplicationCallback);

                        var outfile = Path.Combine(outdir, Path.GetFileName(file.Key));

                        if (mapping.Key != ModJob.JobHeader.TESTPATCH)
                        {
                            // TestPatch is never unpacked. So there is not really point to
                            // compressing it's rather small files. The other DLC jobs likely will be packed still, but this will save some disk space.

                            CLog.Information($@"Compressing package to mod directory: {outfile}", Settings.LogModMakerCompiler);
                            finalStream.Position = 0;
                            var package = MEPackageHandler.OpenMEPackageFromStream(finalStream);
                            package.Save(outfile, true);
                        }
                        else
                        {
                            Log.Information($@"Writing patched file to disk: {outfile}");
                            finalStream.WriteToFile(outfile);
                        }
                    }
                    catch (Exception e)
                    {
                        var mixinsStr = string.Join(@", ", file.Value.Select(x => x.PatchName));
                        Log.Error($@"Error in mixin application for file {file.Key}: {e.Message}");
                        failedApplicationCallback(M3L.GetString(M3L.string_interp_errorApplyingMixinsForFile, mixinsStr, file.Key, e.Message));
                    }

                    //finalStream.WriteToFile(outfile);
                }
            }
        }
Exemplo n.º 28
0
            public void RestoreSFAR(bool batchRestore, Action signalRestoreCompleted = null)
            {
                bool?restore = batchRestore;

                if (!restore.Value)
                {
                    restore = RestoreConfirmationCallback?.Invoke(FilePath);
                }
                if (restore.HasValue && restore.Value)
                {
                    NamedBackgroundWorker nbw = new NamedBackgroundWorker(@"RestoreSFARThread");
                    nbw.DoWork += (a, b) =>
                    {
                        var backupFile = Path.Combine(BackupService.GetGameBackupPath(target.Game), FilePath);
                        var targetFile = Path.Combine(target.TargetPath, FilePath);
                        Restoring = true;

                        var unpackedFiles = Directory.GetFiles(DLCDirectory, @"*", SearchOption.AllDirectories);
                        RestoreButtonContent = M3L.GetString(M3L.string_cleaningUp);
                        foreach (var file in unpackedFiles)
                        {
                            if (!file.EndsWith(@".sfar"))
                            {
                                Log.Information(@"Deleting unpacked file: " + file);
                                File.Delete(file);
                            }
                        }

                        // Check if we actually need to restore SFAR
                        if (!VanillaDatabaseService.IsFileVanilla(target, targetFile, false))
                        {
                            Log.Information($@"Restoring SFAR from backup: {backupFile} -> {targetFile}");
                            XCopy.Copy(backupFile, targetFile, true, true,
                                       (o, pce) =>
                            {
                                RestoreButtonContent = M3L.GetString(M3L.string_interp_restoringXpercent,
                                                                     pce.ProgressPercentage.ToString());
                            });
                        }

                        Utilities.DeleteEmptySubdirectories(DLCDirectory);
                        RestoreButtonContent = M3L.GetString(M3L.string_restored);
                    };
                    nbw.RunWorkerCompleted += (a, b) =>
                    {
                        if (b.Error != null)
                        {
                            Log.Error($@"Exception occured in {nbw.Name} thread: {b.Error.Message}");
                        }
                        //File.Copy(backupFile, targetFile, true);
                        //if (!batchRestore)
                        //{
                        RevalidateIsModified();
                        //restoreCompletedCallback?.Invoke();
                        //}
                        Restoring = false;
                        signalRestoreCompleted?.Invoke();
                    };
                    startingRestoreCallback?.Invoke();
                    nbw.RunWorkerAsync();
                }
            }
Exemplo n.º 29
0
        public void ReloadGameTarget(bool lodUpdateAndLogging = true, bool forceLodUpdate = false)
        {
            if (Game != Mod.MEGame.Unknown && !IsCustomOption)
            {
                if (Directory.Exists(TargetPath))
                {
                    var oldTMOption = TextureModded;
                    var alotInfo    = GetInstalledALOTInfo();
                    if (alotInfo != null)
                    {
                        TextureModded = true;
                        ALOTVersion   = alotInfo.ToString();
                        if (alotInfo.MEUITMVER > 0)
                        {
                            MEUITMInstalled = true;
                            MEUITMVersion   = alotInfo.MEUITMVER;
                        }
                    }
                    else
                    {
                        TextureModded   = false;
                        ALOTVersion     = null;
                        MEUITMInstalled = false;
                        MEUITMVersion   = 0;
                    }

                    CLog.Information(@"Getting game source for target " + TargetPath, lodUpdateAndLogging);
                    var hashCheckResult = VanillaDatabaseService.GetGameSource(this);

                    GameSource     = hashCheckResult.result;
                    ExecutableHash = hashCheckResult.hash;
                    if (GameSource == null)
                    {
                        CLog.Error(@"Unknown source or illegitimate installation: " + hashCheckResult.hash, lodUpdateAndLogging);
                    }
                    else
                    {
                        if (GameSource.Contains(@"Origin") && Game == Mod.MEGame.ME3)
                        {
                            // Check for steam
                            if (Directory.Exists(Path.Combine(TargetPath, @"__overlay")))
                            {
                                GameSource += @" (Steam version)";
                            }
                        }
                        CLog.Information(@"Source: " + GameSource, lodUpdateAndLogging);
                    }

                    IsPolishME1 = Game == Mod.MEGame.ME1 && File.Exists(Path.Combine(TargetPath, @"BioGame", @"CookedPC", @"Movies", @"niebieska_pl.bik"));
                    if (IsPolishME1)
                    {
                        CLog.Information(@"ME1 Polish Edition detected", lodUpdateAndLogging);
                    }

                    if (RegistryActive && (Settings.AutoUpdateLODs2K || Settings.AutoUpdateLODs4K) && oldTMOption != TextureModded && (lodUpdateAndLogging || forceLodUpdate))
                    {
                        UpdateLODs(Settings.AutoUpdateLODs2K);
                    }
                }
                else
                {
                    Log.Error($@"Target is invalid: {TargetPath} does not exist (or is not accessible)");
                    IsValid = false; //set to false if target becomes invalid
                }
            }
        }