public IncludeZEditPatches(ACompiler compiler) : base(compiler) { var zEditPath = FindzEditPath(compiler); var havezEdit = zEditPath != null; Utils.Log(havezEdit ? $"Found zEdit at {zEditPath}" : $"zEdit not detected, disabling zEdit routines"); if (!havezEdit) { _mergesIndexed = new Dictionary <string, zEditMerge>(); return; } var merges = Directory.EnumerateFiles(Path.Combine(zEditPath, "profiles"), DirectoryEnumerationOptions.Files | DirectoryEnumerationOptions.Recursive) .Where(f => f.EndsWith("\\merges.json")) .SelectMany(f => f.FromJSON <List <zEditMerge> >()) .GroupBy(f => (f.name, f.filename)); merges.Where(m => m.Count() > 1) .Do(m => { Utils.Log( $"WARNING, you have two patches named {m.Key.name}\\{m.Key.filename} in your zEdit profiles. We'll pick one at random, this probably isn't what you want."); }); _mergesIndexed = merges.ToDictionary( m => Path.Combine(_mo2Compiler.MO2Folder, "mods", m.Key.name, m.Key.filename), m => m.First()); }
public static string FindzEditPath(ACompiler compiler) { _mo2Compiler = (MO2Compiler)compiler; var executables = _mo2Compiler.MO2Ini.customExecutables; if (executables.size == null) { return(null); } foreach (var idx in Enumerable.Range(1, int.Parse(executables.size))) { var path = (string)executables[$"{idx}\\binary"]; if (path == null) { continue; } if (path.EndsWith("zEdit.exe")) { return(Path.GetDirectoryName(path)); } } return(null); }
public ICompilationStep CreateStep(ACompiler compiler) { return(new IncludeZEditPatches(compiler)); }
public void Build(ACompiler c, ModList lst) { MO2Compiler compiler = null; if (lst.ModManager == ModManager.MO2) { compiler = (MO2Compiler)c; } Text($"### {lst.Name} by {lst.Author} - Installation Summary"); Text($"Build with Wabbajack Version {lst.WabbajackVersion}"); Text(lst.Description); Text("#### Website:"); NoWrapText($"[{lst.Website}]({lst.Website})"); Text($"Mod Manager: {lst.ModManager.ToString()}"); if (lst.ModManager == ModManager.MO2) { var readmeFile = Path.Combine(compiler?.MO2ProfileDir, "readme.md"); if (File.Exists(readmeFile)) { File.ReadAllLines(readmeFile) .Do(NoWrapText); } } var archiveCount = lst.Archives.Count + lst.Directives.Count(d => d is SteamMeta); var totalSize = lst.Archives.Sum(a => a.Size); totalSize += lst.Directives.Where(d => d is SteamMeta).Cast <SteamMeta>().Sum(s => s.Size); Text( $"#### Download Summary ({archiveCount} archives - {totalSize.ToFileSizeString()})"); foreach (var archive in SortArchives(lst.Archives)) { var hash = archive.Hash.FromBase64().ToHex(); NoWrapText(archive.State.GetReportEntry(archive)); NoWrapText($" * Size : {archive.Size.ToFileSizeString()}"); NoWrapText($" * SHA256 : [{hash}](https://www.virustotal.com/gui/file/{hash})"); } lst.Directives.Where(d => d is SteamMeta).Do(f => { if (!(f is SteamMeta s)) { return; } var link = $"https://steamcommunity.com/sharedfiles/filedetails/?id={s.ItemID}"; var size = ((long)s.Size).ToFileSizeString(); NoWrapText($"* Steam Workshop Item: [{s.ItemID}]({link}) | Size: {size}"); }); Text("\n\n"); var patched = lst.Directives.OfType <PatchedFromArchive>().OrderBy(p => p.To).ToList(); Text($"#### Summary of ({patched.Count}) patches"); foreach (var directive in patched) { NoWrapText( $"* Applying {SizeForID(directive.PatchID)} byte patch `{directive.FullPath}` to create `{directive.To}`"); } var files = lst.Directives.OrderBy(d => d.To).ToList(); Text($"\n\n### Install Plan of ({files.Count}) files"); Text("(ignoring files that are directly copied from archives or listed in the patches section above)"); foreach (var directive in files.OrderBy(f => f.GetType().Name).ThenByDescending(f => f.To)) { switch (directive) { case PropertyFile i: NoWrapText($"* `{i.SourceDataID}` as a `{Enum.GetName(typeof(PropertyType),i.Type)}`"); break; case FromArchive f: //NoWrapText($"* `{f.To}` from `{f.FullPath}`"); break; case CleanedESM i: NoWrapText($"* `{i.To}` by applying a patch to a game ESM ({i.SourceESMHash})"); break; case RemappedInlineFile i: NoWrapText($"* `{i.To}` by remapping the contents of an inline file"); break; case InlineFile i: NoWrapText($"* `{i.To}` from `{SizeForID(i.SourceDataID).ToFileSizeString()}` file included in modlist"); break; case CreateBSA i: NoWrapText( $"* `{i.To}` by creating a BSA of files found in `{Consts.BSACreationDir}\\{i.TempID}`"); break; } } var inlined = lst.Directives.OfType <InlineFile>() .Select(f => (f.To, "inlined", SizeForID(f.SourceDataID))) .Concat(lst.Directives .OfType <PatchedFromArchive>() .Select(f => (f.To, "patched", SizeForID(f.PatchID)))) .Distinct() .OrderByDescending(f => f.Item3); NoWrapText("\n\n### Summary of inlined files in this installer"); foreach (var inline in inlined) { NoWrapText($"* {inline.Item3.ToFileSizeString()} for {inline.Item2} file {inline.To}"); } }