Add game file patching in compiler

This commit is contained in:
Timothy Baldridge 2022-05-25 22:58:11 -06:00
parent 36d63b04a0
commit 0a2abfa1be
3 changed files with 67 additions and 0 deletions

View File

@ -95,6 +95,7 @@ public abstract class ACompiler
public Dictionary<Game, HashSet<Hash>> GameHashes { get; set; } = new(); public Dictionary<Game, HashSet<Hash>> GameHashes { get; set; } = new();
public Dictionary<Hash, Game[]> GamesWithHashes { get; set; } = new(); public Dictionary<Hash, Game[]> GamesWithHashes { get; set; } = new();
public ILookup<Hash,Archive> GameFiles { get; private set; }
public bool IgnoreMissingFiles { get; set; } public bool IgnoreMissingFiles { get; set; }
@ -211,6 +212,7 @@ public abstract class ACompiler
protected async Task IndexGameFileHashes() protected async Task IndexGameFileHashes()
{ {
NextStep("Compiling", "Indexing Game Files"); NextStep("Compiling", "Indexing Game Files");
var gameFiles = new List<Archive>();
if (_settings.UseGamePaths) if (_settings.UseGamePaths)
{ {
//taking the games in Settings.IncludedGames + currently compiling game so you can eg //taking the games in Settings.IncludedGames + currently compiling game so you can eg
@ -232,6 +234,7 @@ public abstract class ACompiler
var versionInfo = FileVersionInfo.GetVersionInfo(mainFile.ToString()); var versionInfo = FileVersionInfo.GetVersionInfo(mainFile.ToString());
var files = await _wjClient.GetGameArchives(ag, versionInfo.FileVersion ?? "0.0.0.0"); var files = await _wjClient.GetGameArchives(ag, versionInfo.FileVersion ?? "0.0.0.0");
gameFiles.AddRange(files);
_logger.LogInformation($"Including {files.Length} stock game files from {ag} as download sources"); _logger.LogInformation($"Including {files.Length} stock game files from {ag} as download sources");
GameHashes[ag] = files.Select(f => f.Hash).ToHashSet(); GameHashes[ag] = files.Select(f => f.Hash).ToHashSet();
@ -256,8 +259,11 @@ public abstract class ACompiler
.GroupBy(gh => gh.h) .GroupBy(gh => gh.h)
.ToDictionary(gh => gh.Key, gh => gh.Select(p => p.g.Key).ToArray()); .ToDictionary(gh => gh.Key, gh => gh.Select(p => p.g.Key).ToArray());
} }
GameFiles = gameFiles.ToLookup(f => f.Hash);
} }
protected async Task CleanInvalidArchivesAndFillState() protected async Task CleanInvalidArchivesAndFillState()
{ {
NextStep("Compiling", "Cleaning Invalid Archives"); NextStep("Compiling", "Cleaning Invalid Archives");

View File

@ -0,0 +1,60 @@
using Wabbajack.DTOs.DownloadStates;
using Wabbajack.Networking.WabbajackClientApi;
using Wabbajack.VFS;
namespace Wabbajack.Compiler.CompilationSteps;
using Wabbajack.DTOs;
using Wabbajack.DTOs.Directives;
using Wabbajack.Hashing.xxHash64;
using System.Linq;
using System.Threading.Tasks;
using F23.StringSimilarity;
public class PatchStockGameFiles : ACompilationStep
{
private readonly Task<ILookup<Hash, Archive>> _files;
private readonly Levenshtein _distFn;
private readonly Client _client;
public PatchStockGameFiles(ACompiler compiler, Client client) : base(compiler)
{
_client = client;
_distFn = new Levenshtein();
_files = Task.Run(async () => (await _client.GetGameArchives(Game.SkyrimSpecialEdition, "1.5.97.0"))
.ToLookup(f => f.Hash));
}
public override async ValueTask<Directive?> Run(RawSourceFile source)
{
if (_compiler._settings.Game != Game.SkyrimSpecialEdition) return null;
var found = (await _files)[source.Hash];
if (!found.Any()) return null;
var srcFile = _compiler.IndexedArchives
.Where(f => f.State is GameFileSource)
.MinBy(l => _distFn.Distance(l.File.Name.FileName.ToString(), source.Path.FileName.ToString()));
if (srcFile == null) return null;
var e = source.EvolveTo<PatchedFromArchive>();
var data = await _compiler._patchCache.GetPatch(srcFile.File.Hash, source.File.Hash);
if (data != null)
{
e.FromHash = srcFile.File.Hash;
e.ArchiveHashPath = srcFile.File.MakeRelativePaths();
e.PatchID = await _compiler.IncludeFile(await _compiler._patchCache.GetData(data));
}
else
{
_compiler._patchOptions[e] = new[]{srcFile.File};
}
return e;
}
}

View File

@ -257,6 +257,7 @@ public class MO2Compiler : ACompiler
// new IncludeTaggedFolders(this, Consts.WABBAJACK_INCLUDE), // new IncludeTaggedFolders(this, Consts.WABBAJACK_INCLUDE),
new IgnoreExtension(this, Ext.Pyc), new IgnoreExtension(this, Ext.Pyc),
new IgnoreExtension(this, Ext.Log), new IgnoreExtension(this, Ext.Log),
new PatchStockGameFiles(this, _wjClient),
new DeconstructBSAs( new DeconstructBSAs(
this), // Deconstruct BSAs before building patches so we don't generate massive patch files this), // Deconstruct BSAs before building patches so we don't generate massive patch files