diff --git a/Wabbajack.Installer/StandardInstaller.cs b/Wabbajack.Installer/StandardInstaller.cs index 8b7bb3c6..ae5153b2 100644 --- a/Wabbajack.Installer/StandardInstaller.cs +++ b/Wabbajack.Installer/StandardInstaller.cs @@ -107,7 +107,7 @@ public class StandardInstaller : AInstaller _configuration.Downloads.CreateDirectory(); await OptimizeModlist(token); - + await HashArchives(token); await DownloadArchives(token); @@ -134,7 +134,7 @@ public class StandardInstaller : AInstaller await InstallIncludedFiles(token); - await InstallIncludedDownloadMetas(token); + await WriteMetaFiles(token); await BuildBSAs(token); @@ -145,10 +145,8 @@ public class StandardInstaller : AInstaller await RemapMO2File(); CreateOutputMods(); - - SetScreenSizeInPrefs(); - SetDownloadMetasToHideInMO2(token); + SetScreenSizeInPrefs(); await ExtractedModlistFolder!.DisposeAsync(); await _wjClient.SendMetric(MetricNames.FinishInstall, ModList.Name); @@ -177,7 +175,7 @@ public class StandardInstaller : AInstaller // Non MO2 Installs won't have this var profileDir = _configuration.Install.Combine("profiles"); if (!profileDir.DirectoryExists()) return; - + profileDir .EnumerateFiles() .Where(f => f.FileName == Consts.SettingsIni) @@ -224,7 +222,7 @@ public class StandardInstaller : AInstaller } } - private async Task InstallIncludedDownloadMetas(CancellationToken token) + private async Task WriteMetaFiles(CancellationToken token) { _logger.LogInformation("Looking for downloads by size"); var bySize = UnoptimizedArchives.ToLookup(x => x.Size); @@ -233,89 +231,87 @@ public class StandardInstaller : AInstaller await _configuration.Downloads.EnumerateFiles() .PDoAll(async download => { + var metaFile = download.WithExtension(Ext.Meta); + var found = bySize[download.Size()]; var hash = await FileHashCache.FileHashCachedAsync(download, token); var archive = found.FirstOrDefault(f => f.Hash == hash); - if (archive == default) return; - var metaFile = download.WithExtension(Ext.Meta); - if (metaFile.FileExists()) + IEnumerable meta; + + if (archive == default) { - try + // archive is not part of the Modlist + + if (metaFile.FileExists()) { - var parsed = metaFile.LoadIniFile(); - if (parsed["General"] != null && parsed["General"]["unknownArchive"] == null) + try + { + var parsed = metaFile.LoadIniFile(); + if (parsed["General"] is not null && ( + parsed["General"]["removed"] is null || + parsed["General"]["removed"].Equals(bool.FalseString, StringComparison.OrdinalIgnoreCase))) + { + // add removed=true to files not part of the Modlist so they don't show up in MO2 + parsed["General"]["removed"] = "true"; + + _logger.LogInformation("Writing {FileName}", metaFile.FileName); + parsed.SaveIniFile(metaFile); + } + } + catch (Exception) { return; } + + return; } - catch (Exception) + + // create new meta file if missing + meta = new[] { - // Ignore - } + "[General]", + "removed=true" + }; } - + else + { + if (metaFile.FileExists()) + { + try + { + var parsed = metaFile.LoadIniFile(); + if (parsed["General"] is not null && parsed["General"]["unknownArchive"] is null) + { + // meta doesn't have an associated archive + return; + } + } + catch (Exception) + { + // ignored + } + } + + meta = AddInstalled(_downloadDispatcher.MetaIni(archive)); + } + _logger.LogInformation("Writing {FileName}", metaFile.FileName); - var meta = AddInstalled(_downloadDispatcher.MetaIni(archive)); await metaFile.WriteAllLinesAsync(meta, token); }); } - private IEnumerable AddInstalled(IEnumerable getMetaIni) + private static IEnumerable AddInstalled(IEnumerable getMetaIni) { yield return "[General]"; yield return "installed=true"; - + foreach (var f in getMetaIni) { yield return f; } } - private async Task SetDownloadMetasToHideInMO2(CancellationToken token) - { - _logger.LogInformation("Updating Metas To Hide"); - await _configuration.Downloads.EnumerateFiles() - .PDoAll(async download => - { - if (download == default) return; - if (download.Extension == Ext.Meta) return; - - var linesToWriteNewFile = new HashSet( ); - linesToWriteNewFile.Add("[General]"); - linesToWriteNewFile.Add("removed=true"); - - var lineToWriteAppendFile = new HashSet {"removed=true"}; - - var metaFile = download.WithExtension(Ext.Meta); - if (metaFile.FileExists()) - { - try - { - var parsed = metaFile.LoadIniFile(); - if (parsed["General"] != null) - { - _logger.LogInformation("Updating {FileName}", metaFile.FileName); - - await metaFile.WriteAllLinesAsync(lineToWriteAppendFile,FileMode.Append,token); - } - } - catch (Exception e) - { - _logger.LogInformation("Re-Generating corrupted {FileName}", metaFile.FileName); - - await metaFile.WriteAllLinesAsync(linesToWriteNewFile,FileMode.Create,token); - } - } - else //Generate new metas to hide files without metas. - { - _logger.LogInformation("Generating {FileName}", metaFile.FileName); - - await metaFile.WriteAllLinesAsync(linesToWriteNewFile,FileMode.Create,token); - } - }); - } - private async Task BuildBSAs(CancellationToken token) { var bsas = ModList.Directives.OfType().ToList(); @@ -340,17 +336,17 @@ public class StandardInstaller : AInstaller _logger.LogInformation("Writing {bsaTo}", bsa.To); var outPath = _configuration.Install.Combine(bsa.To); - + await using (var outStream = outPath.Open(FileMode.Create, FileAccess.Write, FileShare.None)) { await a.Build(outStream, token); } - + streams.Do(s => s.Dispose()); - + await FileHashCache.FileHashWriteCache(outPath, bsa.Hash); sourceDir.DeleteDirectory(); - + _logger.LogInformation("Verifying {bsaTo}", bsa.To); var reader = await BSADispatch.Open(outPath); var results = await reader.Files.PMapAllBatchedAsync(_limiter, async state => @@ -362,7 +358,7 @@ public class StandardInstaller : AInstaller var astate = bsa.FileStates.First(f => f.Path == state.Path); var srcDirective = indexedByDestination[Consts.BSACreationDir.Combine(bsa.TempID, astate.Path)]; //DX10Files are lossy - if (astate is not BA2DX10File && srcDirective.IsDeterministic) + if (astate is not BA2DX10File && srcDirective.IsDeterministic) ThrowOnNonMatchingHash(bsa, srcDirective, astate, hash); return (srcDirective, hash); }).ToHashSet(); @@ -408,7 +404,7 @@ public class StandardInstaller : AInstaller private void SetScreenSizeInPrefs() { var profilesPath = _configuration.Install.Combine("profiles"); - + // Don't remap files for Native Game Compiler games if (!profilesPath.DirectoryExists()) return; if (_configuration.SystemParameters == null) @@ -478,7 +474,7 @@ public class StandardInstaller : AInstaller { _logger.LogCritical(ex, "Skipping screen size remap for {file} due to parse error.", file); } - + // The Witcher 3 if (_configuration.Game == Game.Witcher3) { @@ -586,4 +582,4 @@ public class StandardInstaller : AInstaller ms.Position = 0; return JsonSerializer.Deserialize(ms, dtos.Options)!; } -} \ No newline at end of file +}