mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
add support for ESM cleaning
This commit is contained in:
parent
40950b442c
commit
bf181cdc2d
@ -43,5 +43,7 @@ namespace Wabbajack.Common
|
||||
|
||||
public static String AppName = "Wabbajack";
|
||||
public static string HashCacheName = "Wabbajack.hash_cache";
|
||||
|
||||
public static HashSet<string> GameESMs = new HashSet<string>() { "Skyrim.esm", "Update.esm", "Dawnguard.esm", "HearthFires.esm", "Dragonborn.esm" };
|
||||
}
|
||||
}
|
||||
|
@ -205,6 +205,7 @@ namespace Wabbajack
|
||||
|
||||
var stack = MakeStack();
|
||||
|
||||
|
||||
Info("Running Compilation Stack");
|
||||
var results = AllFiles.PMap(f => RunStack(stack, f)).ToList();
|
||||
|
||||
@ -363,26 +364,7 @@ namespace Wabbajack
|
||||
|
||||
Archive result;
|
||||
|
||||
if (general.modID != null && general.fileID != null && general.gameName != null)
|
||||
{
|
||||
result = new NexusMod()
|
||||
{
|
||||
GameName = general.gameName,
|
||||
FileID = general.fileID,
|
||||
ModID = general.modID
|
||||
};
|
||||
Status($"Getting Nexus info for {found.Name}");
|
||||
try
|
||||
{
|
||||
var link = NexusAPI.GetNexusDownloadLink((NexusMod)result, NexusKey, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Error($"Unable to resolve {found.Name} on the Nexus was the file removed?");
|
||||
}
|
||||
|
||||
}
|
||||
else if (general.directURL != null && general.directURL.StartsWith("https://drive.google.com"))
|
||||
if (general.directURL != null && general.directURL.StartsWith("https://drive.google.com"))
|
||||
{
|
||||
var regex = new Regex("((?<=id=)[a-zA-Z0-9_-]*)|(?<=\\/file\\/d\\/)[a-zA-Z0-9_-]*");
|
||||
var match = regex.Match(general.directURL);
|
||||
@ -452,6 +434,25 @@ namespace Wabbajack
|
||||
URL = general.manualURL.ToString()
|
||||
};
|
||||
}
|
||||
else if (general.modID != null && general.fileID != null && general.gameName != null)
|
||||
{
|
||||
result = new NexusMod()
|
||||
{
|
||||
GameName = general.gameName,
|
||||
FileID = general.fileID,
|
||||
ModID = general.modID
|
||||
};
|
||||
Status($"Getting Nexus info for {found.Name}");
|
||||
try
|
||||
{
|
||||
var link = NexusAPI.GetNexusDownloadLink((NexusMod)result, NexusKey, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Error($"Unable to resolve {found.Name} on the Nexus was the file removed?");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Error("No way to handle archive {0} but it's required by the modpack", found.Name);
|
||||
@ -532,10 +533,40 @@ namespace Wabbajack
|
||||
IgnoreEndsWith("HavokBehaviorPostProcess.exe"),
|
||||
// Theme file MO2 downloads somehow
|
||||
IgnoreEndsWith("splash.png"),
|
||||
|
||||
PatchStockESMs(),
|
||||
|
||||
DropAll()
|
||||
};
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
private Func<RawSourceFile, Directive> IncludeLootFiles()
|
||||
{
|
||||
var prefix = Consts.LOOTFolderFilesDir + "\\";
|
||||
|
@ -96,6 +96,11 @@ namespace Wabbajack
|
||||
public string SourceData;
|
||||
}
|
||||
|
||||
public class CleanedESM : InlineFile
|
||||
{
|
||||
public string SourceESMHash;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A file that has the game and MO2 folders remapped on installation
|
||||
/// </summary>
|
||||
|
@ -217,6 +217,10 @@ namespace Wabbajack
|
||||
{
|
||||
WriteRemappedFile((RemappedInlineFile)directive);
|
||||
}
|
||||
else if (directive is CleanedESM)
|
||||
{
|
||||
GenerateCleanedESM((CleanedESM)directive);
|
||||
}
|
||||
else
|
||||
{
|
||||
File.WriteAllBytes(out_path, directive.SourceData.FromBase64());
|
||||
@ -224,6 +228,28 @@ namespace Wabbajack
|
||||
});
|
||||
}
|
||||
|
||||
private void GenerateCleanedESM(CleanedESM directive)
|
||||
{
|
||||
var filename = Path.GetFileName(directive.To);
|
||||
var game_file = Path.Combine(GameFolder, "Data", filename);
|
||||
Info($"Generating cleaned ESM for {filename}");
|
||||
if (!File.Exists(game_file))
|
||||
{
|
||||
throw new InvalidDataException($"Missing {filename} at {game_file}");
|
||||
}
|
||||
Status($"Hashing game version of {filename}");
|
||||
var sha = Utils.FileSHA256(game_file);
|
||||
if (sha != directive.SourceESMHash)
|
||||
throw new InvalidDataException($"Cannot patch {filename} from the game folder hashes don't match have you already cleaned the file?");
|
||||
|
||||
var patch_data = directive.SourceData.FromBase64();
|
||||
var to_file = Path.Combine(Outputfolder, directive.To);
|
||||
Status($"Patching {filename}");
|
||||
using (var output = File.OpenWrite(to_file)) {
|
||||
BSDiff.Apply(File.OpenRead(game_file), () => new MemoryStream(patch_data), output);
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteRemappedFile(RemappedInlineFile directive)
|
||||
{
|
||||
var data = Encoding.UTF8.GetString(directive.SourceData.FromBase64());
|
||||
|
Loading…
Reference in New Issue
Block a user