diff --git a/Wabbajack.App.Wpf/View Models/Compilers/CompilerVM.cs b/Wabbajack.App.Wpf/View Models/Compilers/CompilerVM.cs index 116c832e..6fc38fba 100644 --- a/Wabbajack.App.Wpf/View Models/Compilers/CompilerVM.cs +++ b/Wabbajack.App.Wpf/View Models/Compilers/CompilerVM.cs @@ -180,7 +180,7 @@ namespace Wabbajack DownloadLocation.TargetPath = settings.Downloads; OutputLocation.TargetPath = settings.OutputFile; SelectedProfile = settings.Profile; - OtherProfiles = settings.OtherProfiles; + OtherProfiles = settings.AdditionalProfiles; AlwaysEnabled = settings.AlwaysEnabled; NoMatchInclude = settings.NoMatchInclude; } @@ -204,7 +204,7 @@ namespace Wabbajack Downloads = DownloadLocation.TargetPath, OutputFile = OutputLocation.TargetPath, Profile = SelectedProfile, - OtherProfiles = OtherProfiles, + AdditionalProfiles = OtherProfiles, AlwaysEnabled = AlwaysEnabled, NoMatchInclude = NoMatchInclude, UseGamePaths = true @@ -256,7 +256,7 @@ namespace Wabbajack UseGamePaths = true, OutputFile = OutputLocation.TargetPath.Combine(SelectedProfile).WithExtension(Ext.Wabbajack), AlwaysEnabled = AlwaysEnabled, - OtherProfiles = OtherProfiles, + AdditionalProfiles = OtherProfiles, NoMatchInclude = NoMatchInclude, }; } diff --git a/Wabbajack.CLI/Verbs/InstallCompileInstallVerify.cs b/Wabbajack.CLI/Verbs/InstallCompileInstallVerify.cs index 3a13ad5d..19bcfe47 100644 --- a/Wabbajack.CLI/Verbs/InstallCompileInstallVerify.cs +++ b/Wabbajack.CLI/Verbs/InstallCompileInstallVerify.cs @@ -101,14 +101,61 @@ public class InstallCompileInstallVerify : IVerb var compiler = MO2Compiler.Create(_serviceProvider, inferedSettings); result = await compiler.Begin(token); + if (!result) + return result ? 0 : 3; + + + var installPath2 = outputs.Combine("verify_list"); - return result ? 0 : 3; + var comparison = await StandardInstaller.LoadFromFile(_dtos, wabbajackPath); + + var modlist2 = await StandardInstaller.LoadFromFile(_dtos, inferedSettings.OutputFile); + if (CompareModlists(comparison, modlist2)) + return 3; + + var installer2 = StandardInstaller.Create(_serviceProvider, new InstallerConfiguration + { + Downloads = downloads, + Install = installPath2, + ModList = modlist2, + Game = modlist2.GameType, + ModlistArchive = inferedSettings.OutputFile, + GameFolder = _gameLocator.GameLocation(modlist2.GameType) + }); + + result = await installer2.Begin(token); + if (!result) + { + _logger.LogInformation("Error installing recompiled {MachineUrl}", machineUrl); + return 1; + } } return 0; } - + + private bool CompareModlists(ModList a, ModList b) + { + var aDirectives = a.Directives.ToDictionary(d => d.To); + var bDirectives = b.Directives.ToDictionary(d => d.To); + + var found = false; + foreach (var missing in aDirectives.Where(ad => !bDirectives.ContainsKey(ad.Key))) + { + _logger.LogWarning("File {To} is missing in recompiled list", missing.Key); + found = true; + } + + foreach (var missing in bDirectives.Where(bd => !aDirectives.ContainsKey(bd.Key))) + { + _logger.LogWarning("File {To} is missing in original list", missing.Key); + found = true; + } + + return found; + } + private async Task DownloadMachineUrl(string machineUrl, AbsolutePath wabbajack, CancellationToken token) { _logger.LogInformation("Downloading {MachineUrl}", machineUrl); diff --git a/Wabbajack.Compiler.Test/ModListHarness.cs b/Wabbajack.Compiler.Test/ModListHarness.cs index c50f2ce1..2e6cf4b9 100644 --- a/Wabbajack.Compiler.Test/ModListHarness.cs +++ b/Wabbajack.Compiler.Test/ModListHarness.cs @@ -85,7 +85,6 @@ public class ModListHarness settings.Game = Game.SkyrimSpecialEdition; settings.Source = _source; settings.ModListName = _profileName; - settings.SelectedProfiles = new[] {_profileName}; settings.Profile = _profileName; settings.OutputFile = _outputFile; configureSettings(settings); diff --git a/Wabbajack.Compiler/CompilationSteps/IgnoreDisabledMods.cs b/Wabbajack.Compiler/CompilationSteps/IgnoreDisabledMods.cs index 4a62c52d..14c1ce3a 100644 --- a/Wabbajack.Compiler/CompilationSteps/IgnoreDisabledMods.cs +++ b/Wabbajack.Compiler/CompilationSteps/IgnoreDisabledMods.cs @@ -21,7 +21,7 @@ public class IgnoreDisabledMods : ACompilationStep //var alwaysDisabled = _mo2Compiler.ModInis // .Where(f => HasFlagInNotes(f.Value, Consts.WABBAJACK_ALWAYS_DISABLE)).Select(f => f.Key).Distinct(); - _allEnabledMods = _mo2Compiler._settings.SelectedProfiles + _allEnabledMods = _mo2Compiler._settings.AllProfiles .SelectMany(p => _mo2Compiler._settings.Source.Combine("profiles", p, "modlist.txt").ReadAllLines()) .Where(line => line.StartsWith("+") || line.EndsWith("_separator")) .Select(line => line[1..].ToRelativePath().RelativeTo(_mo2Compiler.MO2ModsFolder)) diff --git a/Wabbajack.Compiler/CompilationSteps/IgnoreOtherProfiles.cs b/Wabbajack.Compiler/CompilationSteps/IgnoreOtherProfiles.cs index 33e3e7c0..b1f18fa8 100644 --- a/Wabbajack.Compiler/CompilationSteps/IgnoreOtherProfiles.cs +++ b/Wabbajack.Compiler/CompilationSteps/IgnoreOtherProfiles.cs @@ -18,7 +18,7 @@ public class IgnoreOtherProfiles : ACompilationStep _mo2Compiler = (MO2Compiler) compiler; _modProfilesFolder = _mo2Compiler._settings.Source.Combine("profiles"); - _profiles = _mo2Compiler._settings.SelectedProfiles + _profiles = _mo2Compiler._settings.AllProfiles .Select(p => _modProfilesFolder.Combine(p)) .ToList(); } diff --git a/Wabbajack.Compiler/CompilationSteps/IgnoreSaveFiles.cs b/Wabbajack.Compiler/CompilationSteps/IgnoreSaveFiles.cs index 308c5e75..b5865950 100644 --- a/Wabbajack.Compiler/CompilationSteps/IgnoreSaveFiles.cs +++ b/Wabbajack.Compiler/CompilationSteps/IgnoreSaveFiles.cs @@ -21,7 +21,7 @@ public class IgnoreSaveFiles : MO2CompilationStep _includeSaves = _compiler._settings.Source.EnumerateFiles(_tag).FirstOrDefault() != default; _profilePaths = - MO2Compiler._settings.SelectedProfiles + MO2Compiler._settings.AllProfiles .Select(p => _compiler._settings.Source.Combine(Consts.MO2Profiles, p, Consts.MO2Saves)).ToArray(); } diff --git a/Wabbajack.Compiler/CompilationSteps/IncludeThisProfile.cs b/Wabbajack.Compiler/CompilationSteps/IncludeThisProfile.cs index 2b7faccc..ec39e37f 100644 --- a/Wabbajack.Compiler/CompilationSteps/IncludeThisProfile.cs +++ b/Wabbajack.Compiler/CompilationSteps/IncludeThisProfile.cs @@ -18,7 +18,7 @@ public class IncludeThisProfile : ACompilationStep public IncludeThisProfile(ACompiler compiler) : base(compiler) { _mo2Compiler = (MO2Compiler) compiler; - _correctProfiles = _mo2Compiler._settings.SelectedProfiles + _correctProfiles = _mo2Compiler._settings.AllProfiles .Select(p => _mo2Compiler.MO2ProfileDir.Parent.Combine(p)).ToList(); } @@ -38,16 +38,18 @@ public class IncludeThisProfile : ACompilationStep private async Task ReadAndCleanModlist(AbsolutePath absolutePath) { - var alwaysEnabled = _mo2Compiler.ModInis - .Where(f => IgnoreDisabledMods.HasFlagInNotes(f.Value, Consts.WABBAJACK_ALWAYS_ENABLE)) - .Select(f => f.Key) - .Select(f => f.FileName.ToString()) - .Distinct(); + var alwaysEnabledMods = _compiler._settings.AlwaysEnabled + .Where(f => f.InFolder(Consts.MO2ModFolderName)) + .Where(f => f.Level > 1) + .Select(f => f.GetPart(1)) + .ToHashSet(); + var lines = await absolutePath.ReadAllLinesAsync() .Where(l => { + var modName = l[1..].Trim(); return l.StartsWith("+") - || alwaysEnabled.Any(x => x.Equals(l.Substring(1))) + || alwaysEnabledMods.Contains(modName) || l.EndsWith("_separator"); }).ToList(); return Encoding.UTF8.GetBytes(string.Join(Consts.LineSeparator, lines)); diff --git a/Wabbajack.Compiler/CompilerSettings.cs b/Wabbajack.Compiler/CompilerSettings.cs index 56c0f9dd..b86e3185 100644 --- a/Wabbajack.Compiler/CompilerSettings.cs +++ b/Wabbajack.Compiler/CompilerSettings.cs @@ -1,4 +1,7 @@ using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json.Serialization; using Wabbajack.DTOs; using Wabbajack.Paths; @@ -23,7 +26,24 @@ public class CompilerSettings public string ModlistReadme { get; set; } = ""; public Uri? ModListWebsite { get; set; } public Version ModlistVersion { get; set; } = Version.Parse("0.0.1.0"); - public string[] SelectedProfiles { get; set; } = Array.Empty(); + + /// + /// The main (default) profile + /// + public string Profile { get; set; } = ""; + + /// + /// Secondary profiles to include in the modlist + /// + public string[] AdditionalProfiles { get; set; } = Array.Empty(); + + + /// + /// All profiles to be added to the compiled modlist + /// + [JsonIgnore] + public IEnumerable AllProfiles => AdditionalProfiles.Append(Profile); + /// @@ -37,7 +57,6 @@ public class CompilerSettings /// public RelativePath[] Include { get; set; } = Array.Empty(); - public string Profile { get; set; } = ""; public RelativePath[] AlwaysEnabled { get; set; } = Array.Empty(); - public string[] OtherProfiles { get; set; } + } \ No newline at end of file diff --git a/Wabbajack.Compiler/CompilerSettingsInferencer.cs b/Wabbajack.Compiler/CompilerSettingsInferencer.cs index 3a2de351..0e1a633c 100644 --- a/Wabbajack.Compiler/CompilerSettingsInferencer.cs +++ b/Wabbajack.Compiler/CompilerSettingsInferencer.cs @@ -53,8 +53,9 @@ public class CompilerSettingsInferencer var selectedProfile = general["selected_profile"].FromMO2Ini(); //cs.GamePath = general["gamePath"].FromMO2Ini().ToAbsolutePath(); cs.ModListName = selectedProfile; - - cs.OutputFile = cs.Source.Parent; + cs.Profile = selectedProfile; + + cs.OutputFile = cs.Source.Parent.Combine(selectedProfile).WithExtension(Ext.Wabbajack); var settings = iniData["Settings"]; cs.Downloads = settings["download_directory"].FromMO2Ini().ToAbsolutePath(); @@ -88,7 +89,7 @@ public class CompilerSettingsInferencer var otherProfilesFile = settingsFile.Parent.Combine("otherprofiles.txt"); if (otherProfilesFile.FileExists()) { - cs.OtherProfiles = await otherProfilesFile.ReadAllLinesAsync().ToArray(); + cs.AdditionalProfiles = await otherProfilesFile.ReadAllLinesAsync().ToArray(); } cs.OutputFile = cs.Source.Parent.Combine(cs.Profile).WithExtension(Ext.Wabbajack); diff --git a/Wabbajack.Paths/RelativePath.cs b/Wabbajack.Paths/RelativePath.cs index 16984cf0..d4d29261 100644 --- a/Wabbajack.Paths/RelativePath.cs +++ b/Wabbajack.Paths/RelativePath.cs @@ -173,6 +173,7 @@ public struct RelativePath : IPath, IEquatable, IComparable new(Parts[..1]); public RelativePath FileNameWithoutExtension => Parts[^1][..Extension.ToString().Length].ToRelativePath(); + public int Level => Parts.Length; public bool EndsWith(string postfix) { @@ -188,4 +189,9 @@ public struct RelativePath : IPath, IEquatable, IComparable