コード例 #1
0
ファイル: SFARTests.cs プロジェクト: henbagle/ME3Explorer
        public void TestSFARParsing()
        {
            GlobalTest.Init();
            // Loads compressed packages and attempts to enumerate every object's properties.
            var sfarsPath = GlobalTest.GetTestSFARsDirectory();
            var sfars     = Directory.GetFiles(sfarsPath, "*.sfar", SearchOption.AllDirectories);

            foreach (var s in sfars)
            {
                var expectedCompressionType = Path.GetFileNameWithoutExtension(s);
                Console.WriteLine($"Opening SFAR {s}");
                DLCPackage dlc = new DLCPackage(s);
                Assert.AreEqual(expectedCompressionType, dlc.Header.CompressionScheme);

                // Enumerate files
                foreach (var f in dlc.Files)
                {
                    var lookup = dlc.FindFileEntry(Path.GetFileName(f.FileName));
                    Assert.AreEqual(dlc.Files[lookup], f);
                    var de = dlc.DecompressEntry(lookup);
                    Assert.AreEqual(f.RealUncompressedSize, de.Length);
                }
            }
        }
コード例 #2
0
        private bool HandleCommandLineArgs(string[] args, out int exitCode)
        {
            if (args.Length < 2)
            {
                exitCode = 0;
                return(false);
            }
            //automation
            try
            {
                if (args[1].Equals("-dlcinject"))
                {
                    if (args.Length % 2 != 1 || args.Length < 5)
                    {
                        MessageBox.Show("Wrong number of arguments for the -dlcinject switch.:\nSyntax is: <exe> -dlcinject SFARPATH SEARCHTERM NEWFILEPATH [SEARCHTERM2 NEWFILEPATH2]...", "ME3 DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error);
                        exitCode = 1;
                        return(true);
                    }
                    string dlcFileName = args[2];
                    int    numfiles    = (args.Length - 3) / 2;

                    string[] filesToReplace = new string[numfiles];
                    string[] newFiles       = new string[numfiles];

                    int argnum = 3; //starts at 3
                    for (int i = 0; i < filesToReplace.Length; i++)
                    {
                        filesToReplace[i] = args[argnum];
                        argnum++;
                        newFiles[i] = args[argnum];
                        argnum++;
                    }
                    if (File.Exists(dlcFileName))
                    {
                        DLCPackage dlc = new DLCPackage(dlcFileName);
                        for (int i = 0; i < numfiles; i++)
                        {
                            int idx = dlc.FindFileEntry(filesToReplace[i]);
                            if (idx == -1)
                            {
                                MessageBox.Show("DLCEditor2 automator encountered an error: the file to replace does not exist.", "ME3 DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error);
                                exitCode = 1;
                                return(true);
                            }
                            dlc.ReplaceEntry(newFiles[i], idx);
                        }
                        exitCode = 0;
                        return(true);
                    }
                    MessageBox.Show("Failed to autoinject: DLC file does not exist: " + dlcFileName, "ME3Explorer DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    exitCode = 1;
                    return(true);
                }
                else if (args[1].Equals("-dlcextract"))
                {
                    if (args.Length != 5)
                    {
                        //-2 for me3explorer & -dlcextract
                        MessageBox.Show("Wrong number of arguments for the -dlcextract switch.:\nSyntax is: <exe> -dlcextract SFARPATH SEARCHTERM EXTRACTIONPATH", "ME3 DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error);
                        exitCode = 1;
                        return(true);
                    }
                    string dlcFileName    = args[2];
                    string searchTerm     = args[3];
                    string extractionPath = args[4];
                    if (File.Exists(dlcFileName))
                    {
                        DLCPackage dlc = new DLCPackage(dlcFileName);
                        int        idx = dlc.FindFileEntry(searchTerm);
                        if (idx == -1)
                        {
                            MessageBox.Show("DLCEditor2 extraction automator encountered an error:\nThe file to replace does not exist or the tree has not been initialized.", "DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error);
                            exitCode = 1;
                            return(true);
                        }
                        using (FileStream fs = new FileStream(extractionPath, FileMode.Create, FileAccess.Write, FileShare.None, 4096, useAsync: true))
                        {
                            dlc.DecompressEntryAsync(idx, fs).Wait();
                        }
                        exitCode = 0;
                        return(true);
                    }
                    MessageBox.Show("Failed to autoextract: DLC file does not exist: " + dlcFileName, "ME3Explorer DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    exitCode = 1;
                    return(true);
                }
                else if (args[1].Equals("-dlcaddfiles"))
                {
                    if (args.Length % 2 != 1 || args.Length < 5)
                    {
                        MessageBox.Show("Wrong number of arguments for the -dlcaddfiles switch.:\nSyntax is: <exe> -dlcinject SFARPATH INTERNALPATH NEWFILEPATH [INTERNALPATH2 NEWFILEPATH2]...", "ME3 DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error);
                        exitCode = 1;
                        return(true);
                    }

                    string   dlcFileName   = args[2];
                    int      numfiles      = (args.Length - 3) / 2;
                    string[] internalPaths = new string[numfiles];
                    string[] sourcePaths   = new string[numfiles];

                    int argnum = 3; //starts at 3
                    for (int i = 0; i < internalPaths.Length; i++)
                    {
                        internalPaths[i] = args[argnum];
                        argnum++;
                        sourcePaths[i] = args[argnum];
                        argnum++;
                    }

                    if (File.Exists(dlcFileName))
                    {
                        DLCPackage dlc = new DLCPackage(dlcFileName);
                        for (int i = 0; i < internalPaths.Length; i++)
                        {
                            dlc.AddFileQuick(sourcePaths[i], internalPaths[i]);
                        }
                        exitCode = 0;
                        return(true);
                    }
                    MessageBox.Show("Failed to autoadd: DLC file does not exist: " + dlcFileName, "ME3Explorer DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    exitCode = 1;
                    return(true);
                }
                else if (args[1].Equals("-dlcremovefiles"))
                {
                    if (args.Length < 4)
                    {
                        //-2 for me3explorer & -dlcextract
                        MessageBox.Show("Wrong number of arguments for the -dlcremovefiles switch.:\nSyntax is: <exe> -dlcinject SFARPATH INTERNALPATH [INTERNALPATH2]...", "ME3 DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error);
                        exitCode = 1;
                        return(true);
                    }
                    string   dlcFileName   = args[2];
                    int      numfiles      = (args.Length - 3);
                    string[] filesToRemove = new string[numfiles];
                    int      argnum        = 3; //starts at 3
                    for (int i = 0; i < filesToRemove.Length; i++)
                    {
                        filesToRemove[i] = args[argnum];
                        argnum++;
                    }

                    if (File.Exists(dlcFileName))
                    {
                        DLCPackage dlc = new DLCPackage(dlcFileName);
                        for (int i = 0; i < filesToRemove.Length; i++)
                        {
                            int idx = dlc.FindFileEntry(filesToRemove[i]);
                            if (idx == -1)
                            {
                                MessageBox.Show("DLCEditor2 file removal automator encountered an error:\nThe file to remove does not exist or the tree has not been initialized.", "DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error);
                                exitCode = 1;
                                return(true);
                            }
                            dlc.DeleteEntry(idx);
                        }
                        exitCode = 0;
                        return(true);
                    }
                    MessageBox.Show("Failed to autoremove: DLC file does not exist: " + dlcFileName, "ME3Explorer DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    exitCode = 1;
                    return(true);
                }
                else if (args[1].Equals("-dlcunpack") || args[1].Equals("-dlcunpack-nodebug"))
                {
                    if (args.Length != 4)
                    {
                        MessageBox.Show("Wrong number of arguments for automated DLC unpacking:\nSyntax is: <exe> -dlcunpack SFARPATH EXTRACTIONPATH", "ME3 DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error);
                        exitCode = 1;
                        return(true);
                    }

                    string sfarPath         = args[2];
                    string autoUnpackFolder = args[3];

                    if (File.Exists(sfarPath))
                    {
                        DLCPackage dlc = new DLCPackage(sfarPath);
                        if (args[1].Equals("-dlcunpack"))
                        {
                            //open debugging window since this operation takes a long time.
                            KFreonLib.Debugging.DebugOutput.StartDebugger("DLC Editor 2");
                        }
                        //Simulate Unpack operation click.
                        SFAREditor2.unpackSFAR(dlc);
                        exitCode = 0;
                        return(true);
                    }
                    else
                    {
                        MessageBox.Show("Failed to autounpack: DLC file does not exist: " + sfarPath, "ME3Explorer DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error);
                        exitCode = 1;
                        return(true);
                    }
                }
                else if (args[1].Equals("-toceditorupdate"))
                {
                    //Legacy command requested by FemShep
                    TOCeditor toc = new TOCeditor();
                    exitCode = toc.updateTOCFromCommandLine(args.Skip(2).ToList());
                    return(true);
                }
                else if (args[1].Equals("-autotoc"))
                {
                    if (args.Length == 2)
                    {
                        AutoTOC.GenerateAllTOCs();
                    }
                    else
                    {
                        AutoTOC.prepareToCreateTOC(args[2]);
                    }
                    exitCode = 0;
                    return(true);
                }
                else if (args[1].Equals("-sfarautotoc"))
                {
                    if (args.Length != 3)
                    {
                        MessageBox.Show("-sfarautotoc command line argument requires at least 1 parameter:\nSFARFILE.sfar", "Automated SFAR TOC Update Fail", MessageBoxButton.OK, MessageBoxImage.Error);
                        exitCode = 1;
                        return(true);
                    }

                    var result = Parallel.For(2, args.Length, i =>
                    {
                        if (args[i].EndsWith(".sfar") && File.Exists(args[i]))
                        {
                            DLCPackage DLC = new DLCPackage(args[2]);
                            DLC.UpdateTOCbin(true);
                        }
                    });
                    exitCode = result.IsCompleted ? 0 : 1;
                    return(true);
                }
                else if (args[1].Equals("-decompresspcc"))
                {
                    if (args.Length != 4)
                    {
                        MessageBox.Show("-decompresspcc command line argument requires 2 parameters:\ninputfile.pcc outputfile.pcc\nBoth arguments can be the same.", "Auto Decompression Error", MessageBoxButton.OK, MessageBoxImage.Error);

                        exitCode = 1;
                        return(true);
                    }
                    exitCode = PCCRepack.autoDecompressPcc(args[2], args[3]);
                    return(true);
                }
                else if (args[1].Equals("-compresspcc"))
                {
                    if (args.Length != 4)
                    {
                        MessageBox.Show("-compresspcc command line argument requires 2 parameters:\ninputfile.pcc outputfile.pcc\nBoth arguments can be the same.", "Auto Compression Error", MessageBoxButton.OK, MessageBoxImage.Error);

                        exitCode = 1;
                        return(true);
                    }
                    exitCode = PCCRepack.autoCompressPcc(args[2], args[3]);
                    return(true);
                }
            }
            catch
            {
                exitCode = 1;
                return(true);
            }

            string ending = Path.GetExtension(args[1]).ToLower();

            switch (ending)
            {
            case ".pcc":
                PackageEditor editor = new PackageEditor();
                editor.Show();
                editor.LoadFile(args[1]);
                break;
            }
            exitCode = 0;
            return(false);
        }
コード例 #3
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();
        }