コード例 #1
0
        private void generateRepaceFilesMapping(IniData ini, string modpath)
        {
            var dirs = Directory.GetDirectories(modpath);

            foreach (var dir in dirs)
            {
                //automap
                var dirname    = Path.GetFileName(dir);
                var headername = ModMakerCompiler.defaultFoldernameToHeader(dirname).ToString();
                ini[headername][@"moddir"] = dirname;
                if (dirname != @"BALANCE_CHANGES")
                {
                    ini[headername][@"newfiles"] = @"CookedPCConsole";

                    string inGameDestdir;
                    if (dirname == @"BASEGAME")
                    {
                        inGameDestdir = @"BIOGame/CookedPCConsole";
                    }
                    else
                    {
                        //DLC
                        inGameDestdir = $@"BIOGame/DLC/{ModMakerCompiler.ModmakerChunkNameToDLCFoldername(dirname)}/CookedPCConsole";
                    }

                    ini[headername][@"replacefiles"]           = inGameDestdir;
                    ini[headername][@"gamedirectorystructure"] = @"true";
                }
                else
                {
                    ini[headername][@"newfiles"] = @"ServerCoalesced.bin"; //BALANCE_CHANGES
                }
            }
        }
コード例 #2
0
        private void UpdateModMakerMod(OnlineContent.ModMakerModUpdateInfo mui)
        {
            //throw new NotImplementedException();
            NamedBackgroundWorker nbw = new NamedBackgroundWorker(@"ModmakerModUpdaterThread-" + mui.mod.ModName);

            nbw.WorkerReportsProgress = true;
            nbw.ProgressChanged      += (a, b) =>
            {
                if (b.UserState is double d)
                {
                    mainwindow.TaskBarItemInfoHandler.ProgressValue = d;
                }
            };
            nbw.DoWork += (a, b) =>
            {
                mui.DownloadButtonText = M3L.GetString(M3L.string_compiling);

                OperationInProgress  = true;
                mui.UpdateInProgress = true;
                mui.Indeterminate    = false;

                mui.UIStatusString = M3L.GetString(M3L.string_downloadingDelta);
                var normalEndpoint = OnlineContent.ModmakerModsEndpoint + mui.ModMakerId;
                var lzmaEndpoint   = normalEndpoint + @"&method=lzma";

                string modDelta = null;

                //Try LZMA first
                try
                {
                    var download = OnlineContent.DownloadToMemory(lzmaEndpoint);
                    if (download.errorMessage == null)
                    {
                        mui.UIStatusString = M3L.GetString(M3L.string_decompressingDelta);
                        // OK
                        var decompressed = SevenZipHelper.LZMA.DecompressLZMAFile(download.result.ToArray());
                        modDelta = Encoding.UTF8.GetString(decompressed);
                    }
                    else
                    {
                        Log.Error(@"Error downloading lzma mod delta to memory: " + download.errorMessage);
                    }
                }
                catch (Exception e)
                {
                    Log.Error(@"Error downloading LZMA mod delta to memory: " + e.Message);
                }

                if (modDelta == null)
                {
                    //failed to download LZMA.
                    var download = OnlineContent.DownloadToMemory(normalEndpoint);
                    if (download.errorMessage == null)
                    {
                        //OK
                        modDelta = Encoding.UTF8.GetString(download.result.ToArray());
                    }
                    else
                    {
                        Log.Error(@"Error downloading decompressed mod delta to memory: " + download.errorMessage);
                    }
                }

                void setOverallMax(int max)
                {
                    mui.OverallProgressMax = max;
                }

                void setOverallValue(int current)
                {
                    mui.OverallProgressValue = current;
                    nbw.ReportProgress(0, current * 1.0 / mui.OverallProgressMax);
                    if (current > mui.OverallProgressMax)
                    {
                        Debugger.Break();
                    }
                }

                void setCurrentTaskString(string str)
                {
                    mui.UIStatusString = str;
                }

                if (modDelta != null)
                {
                    var compiler = new ModMakerCompiler(mui.ModMakerId);
                    //compiler.SetCurrentMaxCallback = SetCurrentMax;
                    //compiler.SetCurrentValueCallback = SetCurrentProgressValue;
                    compiler.SetOverallMaxCallback   = setOverallMax;
                    compiler.SetOverallValueCallback = setOverallValue;
                    //compiler.SetCurrentTaskIndeterminateCallback = SetCurrentTaskIndeterminate;
                    compiler.SetCurrentTaskStringCallback = setCurrentTaskString;
                    //compiler.SetModNameCallback = SetModNameOrDownloadText;
                    //compiler.SetCompileStarted = CompilationInProgress;
                    //compiler.SetModNotFoundCallback = ModNotFound;
                    Mod m = compiler.DownloadAndCompileMod(modDelta);
                    if (m != null)
                    {
                        try
                        {
                            File.WriteAllText(System.IO.Path.Combine(Utilities.GetModmakerDefinitionsCache(), mui.ModMakerId + @".xml"), modDelta);
                        }
                        catch (Exception e)
                        {
                            Log.Error(@"Couldn't cache modmaker xml file: " + e.Message);
                        }

                        mui.DownloadButtonText = M3L.GetString(M3L.string_updated);
                        mui.UIStatusString     = M3L.GetString(M3L.string_interp_modMakerCodeX, mui.ModMakerId);
                        mui.UpdateInProgress   = false;
                        mui.CanUpdate          = false;
                        AnyModUpdated          = true;
                    }
                    else
                    {
                        mui.UpdateInProgress   = false;
                        mui.DownloadButtonText = M3L.GetString(M3L.string_compilingFailed);
                        mui.UpdateInProgress   = false;
                    }
                }
            };
            nbw.RunWorkerCompleted += (a, b) =>
            {
                if (b.Error != null)
                {
                    Log.Error($@"Exception occured in {nbw.Name} thread: {b.Error.Message}");
                }
                Analytics.TrackEvent(@"Updated mod", new Dictionary <string, string>()
                {
                    { @"Type", @"ModMaker" },
                    { @"ModName", mui.mod.ModName },
                    { @"Result", mui.CanUpdate ? @"Success" : @"Failed" }
                });

                mainwindow.TaskBarItemInfoHandler.ProgressState = TaskbarItemProgressState.None;
                OperationInProgress = false;
                CommandManager.InvalidateRequerySuggested();
            };
            mainwindow.TaskBarItemInfoHandler.ProgressValue = 0;
            mainwindow.TaskBarItemInfoHandler.ProgressState = TaskbarItemProgressState.Normal;
            nbw.RunWorkerAsync();
        }
コード例 #3
0
        private void UpdateModMakerMod(OnlineContent.ModMakerModUpdateInfo mui)
        {
            //throw new NotImplementedException();
            NamedBackgroundWorker bw = new NamedBackgroundWorker(@"ModmakerModUpdaterThread-" + mui.mod.ModName);

            bw.DoWork += (a, b) =>
            {
                mui.DownloadButtonText = M3L.GetString(M3L.string_compiling);

                OperationInProgress  = true;
                mui.UpdateInProgress = true;
                mui.Indeterminate    = false;

                mui.UIStatusString = M3L.GetString(M3L.string_downloadingDelta);
                var normalEndpoint = OnlineContent.ModmakerModsEndpoint + mui.ModMakerId;
                var lzmaEndpoint   = normalEndpoint + @"&method=lzma";

                string modDelta = null;

                //Try LZMA first
                try
                {
                    var download = OnlineContent.DownloadToMemory(lzmaEndpoint);
                    if (download.errorMessage == null)
                    {
                        mui.UIStatusString = M3L.GetString(M3L.string_decompressingDelta);
                        // OK
                        var decompressed = SevenZipHelper.LZMA.DecompressLZMAFile(download.result.ToArray());
                        modDelta = Encoding.UTF8.GetString(decompressed);
                        // File.WriteAllText(@"C:\users\mgamerz\desktop\decomp.txt", modDelta);
                    }
                    else
                    {
                        Log.Error(@"Error downloading lzma mod delta to memory: " + download.errorMessage);
                    }
                }
                catch (Exception e)
                {
                    Log.Error(@"Error downloading LZMA mod delta to memory: " + e.Message);
                }

                if (modDelta == null)
                {
                    //failed to download LZMA.
                    var download = OnlineContent.DownloadToMemory(normalEndpoint);
                    if (download.errorMessage == null)
                    {
                        //OK
                        modDelta = Encoding.UTF8.GetString(download.result.ToArray());
                    }
                    else
                    {
                        Log.Error(@"Error downloading decompressed mod delta to memory: " + download.errorMessage);
                    }
                }

                void setOverallMax(int max)
                {
                    mui.OverallProgressMax = max;
                }

                void setOverallValue(int current)
                {
                    mui.OverallProgressValue = current;
                    if (current > mui.OverallProgressMax)
                    {
                        Debugger.Break();
                    }
                }

                void setCurrentTaskString(string str)
                {
                    mui.UIStatusString = str;
                }

                if (modDelta != null)
                {
                    var compiler = new ModMakerCompiler(mui.ModMakerId);
                    //compiler.SetCurrentMaxCallback = SetCurrentMax;
                    //compiler.SetCurrentValueCallback = SetCurrentProgressValue;
                    compiler.SetOverallMaxCallback   = setOverallMax;
                    compiler.SetOverallValueCallback = setOverallValue;
                    //compiler.SetCurrentTaskIndeterminateCallback = SetCurrentTaskIndeterminate;
                    compiler.SetCurrentTaskStringCallback = setCurrentTaskString;
                    //compiler.SetModNameCallback = SetModNameOrDownloadText;
                    //compiler.SetCompileStarted = CompilationInProgress;
                    //compiler.SetModNotFoundCallback = ModNotFound;
                    Mod m = compiler.DownloadAndCompileMod(modDelta);
                    File.WriteAllText(System.IO.Path.Combine(Utilities.GetModmakerDefinitionsCache(), mui.ModMakerId + @".xml"), modDelta);
                    mui.DownloadButtonText = M3L.GetString(M3L.string_updated);
                    mui.UIStatusString     = M3L.GetString(M3L.string_interp_modMakerCodeX, mui.ModMakerId);
                    mui.UpdateInProgress   = false;
                    mui.CanUpdate          = false;
                    AnyModUpdated          = true;
                    //b.Result = m;
                }
            };
            bw.RunWorkerCompleted += (a, b) =>
            {
                OperationInProgress = false;
                CommandManager.InvalidateRequerySuggested();
            };
            bw.RunWorkerAsync();
        }
コード例 #4
0
        private void StartCompiler()
        {
            CompileInProgress = true;
            Settings.Save(); //Persist controller mixin option, keybinds injection
            NamedBackgroundWorker nbw = new NamedBackgroundWorker(@"ModmakerCompiler");

            nbw.DoWork += (a, b) =>
            {
                string modDelta = null;

                if (int.TryParse(ModMakerCode, out var code))
                {
                    DownloadAndModNameText = @"Downloading mod delta from ME3Tweaks";
                    var normalEndpoint = OnlineContent.ModmakerModsEndpoint + code;
                    var lzmaEndpoint   = normalEndpoint + @"&method=lzma";


                    //Try LZMA first
                    try
                    {
                        var download = OnlineContent.DownloadToMemory(lzmaEndpoint, (done, total) =>
                        {
                            if (total != -1)
                            {
                                var suffix             = $@" {(done * 100.0 / total).ToString(@"0")}%"; //do not localize
                                DownloadAndModNameText = M3L.GetString(M3L.string_downloadingModDeltaFromME3Tweaks) + suffix;
                            }
                            else
                            {
                                DownloadAndModNameText = M3L.GetString(M3L.string_downloadingModDeltaFromME3Tweaks);
                            }
                        });
                        if (download.errorMessage == null)
                        {
                            DownloadAndModNameText = M3L.GetString(M3L.string_decompressingDelta);
                            // OK
                            var decompressed = SevenZipHelper.LZMA.DecompressLZMAFile(download.result.ToArray());
                            modDelta = Encoding.UTF8.GetString(decompressed);
                            // File.WriteAllText(@"C:\users\mgamerz\desktop\decomp.txt", modDelta);
                        }
                        else
                        {
                            Log.Error(@"Error downloading lzma mod delta to memory: " + download.errorMessage);
                        }
                    }
                    catch (Exception e)
                    {
                        Log.Error(@"Error downloading LZMA mod delta to memory: " + e.Message);
                    }

                    if (modDelta == null)
                    {
                        //failed to download LZMA.
                        var download = OnlineContent.DownloadToMemory(normalEndpoint, (done, total) =>
                        {
                            var suffix             = $" {(done * 100.0 / total).ToString(@"0")}%"; //do not localize
                            DownloadAndModNameText = M3L.GetString(M3L.string_downloadingModDeltaFromME3Tweaks) + suffix;
                        });
                        if (download.errorMessage == null)
                        {
                            //OK
                            modDelta = Encoding.UTF8.GetString(download.result.ToArray());
                        }
                        else
                        {
                            Log.Error(@"Error downloading decompressed mod delta to memory: " + download.errorMessage);
                        }
                    }
                }
                else if (File.Exists(LocalFilePath))
                {
                    modDelta = File.ReadAllText(LocalFilePath);
                }


                if (modDelta != null)
                {
                    KeepOpenWhenThreadFinishes = false;
                    var compiler = new ModMakerCompiler(code);
                    compiler.SetCurrentMaxCallback               = SetCurrentMax;
                    compiler.SetCurrentValueCallback             = SetCurrentProgressValue;
                    compiler.SetOverallMaxCallback               = SetOverallMax;
                    compiler.SetOverallValueCallback             = SetOverallValue;
                    compiler.SetCurrentTaskIndeterminateCallback = SetCurrentTaskIndeterminate;
                    compiler.SetCurrentTaskStringCallback        = SetCurrentTaskString;
                    compiler.SetModNameCallback     = SetModNameOrDownloadText;
                    compiler.SetCompileStarted      = CompilationInProgress;
                    compiler.SetModNotFoundCallback = ModNotFound;
                    compiler.NotifySomeDLCIsMissing = NotifySomeDLCIsMissing;
                    Mod m = compiler.DownloadAndCompileMod(modDelta);
                    if (m != null && !LocalFileOption)
                    {
                        var sanitizedname = Utilities.SanitizePath(m.ModName);
                        File.WriteAllText(Path.Combine(Utilities.GetModmakerDefinitionsCache(), $@"{code}-{sanitizedname}.xml"), modDelta);
                    }
                    b.Result = m;
                }
            };
            nbw.RunWorkerCompleted += (a, b) =>
            {
                if (b.Error != null)
                {
                    Log.Error($@"Exception occured in {nbw.Name} thread: {b.Error.Message}");
                }
                CompileInProgress = false;
                if (!KeepOpenWhenThreadFinishes && b.Result is Mod m)
                {
                    OnClosing(new DataEventArgs(m));
                }
                else
                {
                    CloseProgressPanel();
                    ShowCloseButton = true;
                }
                CommandManager.InvalidateRequerySuggested();
            };
            nbw.RunWorkerAsync();
        }
コード例 #5
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();
        }
コード例 #6
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();
        }
コード例 #7
0
        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);
                }
            }
        }