Пример #1
0
        private IndexedArchive LoadArchive(string file)
        {
            var info = new IndexedArchive();

            info.File = VFS.Lookup(file);

            info.Name = Path.GetFileName(file);

            var ini_name = file + ".meta";

            if (ini_name.FileExists())
            {
                info.IniData = ini_name.LoadIniFile();
                info.Meta    = File.ReadAllText(ini_name);
            }

            return(info);
        }
Пример #2
0
        private Func <RawSourceFile, Directive> PatchStockESMs()
        {
            return(source =>
            {
                string filename = Path.GetFileName(source.Path);
                string game_file = Path.Combine(GamePath, "Data", filename);
                if (Consts.GameESMs.Contains(filename) && source.Path.StartsWith("mods\\") && File.Exists(game_file))
                {
                    Info($"A ESM named {filename} was found in a mod that shares a name with a core game ESMs, it is assumed this is a cleaned ESM and it will be binary patched.");
                    var result = source.EvolveTo <CleanedESM>();
                    result.SourceESMHash = VFS.Lookup(game_file).Hash;

                    Status($"Generating patch of {filename}");
                    using (var ms = new MemoryStream()) {
                        BSDiff.Create(File.ReadAllBytes(game_file), File.ReadAllBytes(source.AbsolutePath), ms);
                        result.SourceData = ms.ToArray().ToBase64();
                    }
                    Info($"Generated a {result.SourceData.Length} byte patch for {filename}");

                    return result;
                }
                return null;
            });
        }
Пример #3
0
        public void Compile()
        {
            Info($"Indexing {MO2Folder}");
            VFS.AddRoot(MO2Folder);
            Info($"Indexing {GamePath}");
            VFS.AddRoot(GamePath);

            var mo2_files = Directory.EnumerateFiles(MO2Folder, "*", SearchOption.AllDirectories)
                            .Where(p => p.FileExists())
                            .Select(p => new RawSourceFile(VFS.Lookup(p))
            {
                Path = p.RelativeTo(MO2Folder)
            });

            var game_files = Directory.EnumerateFiles(GamePath, "*", SearchOption.AllDirectories)
                             .Where(p => p.FileExists())
                             .Select(p => new RawSourceFile(VFS.Lookup(p))
            {
                Path = Path.Combine(Consts.GameFolderFilesDir, p.RelativeTo(GamePath))
            });

            var loot_path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "LOOT");

            Info($"Indexing {loot_path}");
            VFS.AddRoot(loot_path);

            var loot_files = Directory.EnumerateFiles(loot_path, "userlist.yaml", SearchOption.AllDirectories)
                             .Where(p => p.FileExists())
                             .Select(p => new RawSourceFile(VFS.Lookup(p))
            {
                Path = Path.Combine(Consts.LOOTFolderFilesDir, p.RelativeTo(loot_path))
            });


            Info($"Indexing Archives");
            IndexedArchives = Directory.EnumerateFiles(MO2DownloadsFolder)
                              .Where(f => Consts.SupportedArchives.Contains(Path.GetExtension(f)))
                              .Where(f => File.Exists(f + ".meta"))
                              .Select(f => new IndexedArchive()
            {
                File    = VFS.Lookup(f),
                Name    = Path.GetFileName(f),
                IniData = (f + ".meta").LoadIniFile(),
                Meta    = File.ReadAllText(f + ".meta")
            })
                              .ToList();

            Info($"Indexing Files");
            IndexedFiles = IndexedArchives.PMap(f => { Status($"Finding files in {Path.GetFileName(f.File.FullPath)}");
                                                       return(VFS.FilesInArchive(f.File)); })
                           .SelectMany(fs => fs)
                           .OrderByDescending(f => f.TopLevelArchive.LastModified)
                           .GroupBy(f => f.Hash)
                           .ToDictionary(f => f.Key, f => f.AsEnumerable());

            Info("Searching for mod files");

            AllFiles = mo2_files.Concat(game_files)
                       .Concat(loot_files)
                       .ToList();

            Info("Found {0} files to build into mod list", AllFiles.Count);

            ExtraFiles = new ConcurrentBag <Directive>();

            ModInis = Directory.EnumerateDirectories(Path.Combine(MO2Folder, "mods"))
                      .Select(f =>
            {
                var mod_name  = Path.GetFileName(f);
                var meta_path = Path.Combine(f, "meta.ini");
                if (File.Exists(meta_path))
                {
                    return(mod_name, meta_path.LoadIniFile());
                }
                return(null, null);
            })
                      .Where(f => f.Item2 != null)
                      .ToDictionary(f => f.Item1, f => f.Item2);

            var stack = MakeStack();


            Info("Running Compilation Stack");
            var results = AllFiles.PMap(f => RunStack(stack, f)).ToList();

            // Add the extra files that were generated by the stack
            Info($"Adding {ExtraFiles.Count} that were generated by the stack");
            results = results.Concat(ExtraFiles).ToList();

            var nomatch = results.OfType <NoMatch>();

            Info("No match for {0} files", nomatch.Count());
            foreach (var file in nomatch)
            {
                Info("     {0}", file.To);
            }
            if (nomatch.Count() > 0)
            {
                if (IgnoreMissingFiles)
                {
                    Info("Continuing even though files were missing at the request of the user.");
                }
                else
                {
                    Info("Exiting due to no way to compile these files");
                    return;
                }
            }

            InstallDirectives = results.Where(i => !(i is IgnoredDirectly)).ToList();

            Info("Getting nexus api_key please click authorize if a browser window appears");

            NexusKey = NexusAPI.GetNexusAPIKey();
            User     = NexusAPI.GetUserStatus(NexusKey);

            if (!User.is_premium)
            {
                Info($"User {User.name} is not a premium Nexus user, cannot continue");
            }


            GatherArchives();
            BuildPatches();

            ModList = new ModList()
            {
                Archives   = SelectedArchives,
                Directives = InstallDirectives,
                Name       = MO2Profile
            };

            GenerateReport();
            PatchExecutable();

            ResetMembers();

            ShowReport();

            Info("Done Building Modpack");
        }