#### Version - 3.0.0.7 - 9/12/2022

* Few compiler fixes for non Bethesda game compiling
* Fix Dragons' Dogma MO2 archive names
* Add Modlist Report for CLI
This commit is contained in:
Timothy Baldridge 2022-09-12 17:06:14 -06:00
parent 0f361a3f62
commit de9ddd62e1
10 changed files with 222 additions and 2 deletions

View File

@ -1,5 +1,9 @@
### Changelog
#### Version - 3.0.0.7 - 9/12/2022
* Fix Dragons' Dogma MO2 archive names
* Add Modlist Report for CLI
#### Version - 3.0.0.6 - 8/23/2022
* Upgrade several dependency libraries
* Provide a better error message when someone attempts to compile before logging into the Nexus (or installing a list)
@ -37,6 +41,9 @@
* Based on WebView2, .NET 6
* Probably lots of new bugs, please test
#### Version - 2.5.3.28 - 8/30/2022
* Auto-inline `.compiler_settings` files during compilation
#### Version - 2.5.3.27 - 8/7/2022
* A few fixes for VectorPlexis and LL, you may need to log out and back in from these sites

View File

@ -267,6 +267,11 @@ namespace Wabbajack
NoMatchInclude = settings.NoMatchInclude;
Include = settings.Include;
Ignore = settings.Ignore;
if (path.FileName == "modlist.txt".ToRelativePath())
{
await SaveSettingsFile();
await LoadLastSavedSettings();
}
}

View File

@ -80,6 +80,7 @@ internal class Program
services.AddSingleton<IVerb, InstallCompileInstallVerify>();
services.AddSingleton<IVerb, HashUrlString>();
services.AddSingleton<IVerb, DownloadAll>();
services.AddSingleton<IVerb, ModlistReport>();
services.AddSingleton<IUserInterventionHandler, UserInterventionHandler>();
}).Build();

View File

@ -0,0 +1,83 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Modlist Report for {{$.Name}}</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.12.1/css/jquery.dataTables.css">
<script type="text/javascript" charset="utf8" src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.12.1/js/jquery.dataTables.js"></script>
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.12.1/js/dataTables.bootstrap4.min.js"></script>
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/plug-ins/1.12.1/sorting/file-size.js"></script>
</head>
<body>
<div class="ml-2" style="width: 90%">
<h2>Modlist Report ({{$.WabbajackSize}} compressed)</h2>
<h3>Inlined Data ({{$.TotalInlinedSize}}) </h3>
<table id="inlined-data" class="table table-striped table-bordered" style="width:100%">
<thead>
<tr>
<th>To</th>
<th>Id</th>
<th>Size</th>
</tr>
</thead>
<tbody>
{{each $.InlinedData}}
<tr>
<td>{{$.To}}</td>
<td>{{$.Id}}</td>
<td>{{$.Size}}</td>
</tr>
{{/each}}
</tbody>
</table>
<h3>Patch Data ({{$.TotalPatchSize}}) </h3>
<table id="patch-data" class="table table-striped table-bordered" style="width:100%">
<thead>
<tr>
<th>From</th>
<th>To</th>
<th>Id</th>
<th>Patch Size</th>
<th>Final Size</th>
</tr>
</thead>
<tbody>
{{each $.PatchData}}
<tr>
<td>{{$.From}}</td>
<td>{{$.To}}</td>
<td>{{$.Id}}</td>
<td>{{$.PatchSize}}</td>
<td>{{$.FinalSize}}</td>
</tr>
{{/each}}
</tbody>
</table>
</div>
<script>
$(document).ready( function () {
$("#inlined-data").DataTable({
columnDefs: [
{ type: 'file-size', targets: 2},
]
});
} );
$(document).ready( function () {
$("#patch-data").DataTable({
columnDefs: [
{ type: 'file-size', targets: 3},
{ type: 'file-size', targets: 4},
]
});
} );
</script>
</body>
</html>

View File

@ -0,0 +1,109 @@
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Nettle;
using Wabbajack.Common;
using Wabbajack.DTOs.Directives;
using Wabbajack.DTOs.JsonConverters;
using Wabbajack.Installer;
using Wabbajack.Paths;
using Wabbajack.Paths.IO;
namespace Wabbajack.CLI.Verbs;
public class ModlistReport : IVerb
{
private readonly ILogger<ModlistReport> _logger;
private readonly DTOSerializer _dtos;
public ModlistReport(ILogger<ModlistReport> logger, DTOSerializer dtos)
{
_logger = logger;
_dtos = dtos;
}
public Command MakeCommand()
{
var command = new Command("modlist-report");
command.Add(new Option<AbsolutePath>(new[] {"-i", "-input"}, "Wabbajack file from which to generate a report"));
command.Description = "Generates a usage report for a Modlist file";
command.Handler = CommandHandler.Create(Run);
return command;
}
private static async Task<string> ReportTemplate(object o)
{
var data = (typeof(ModlistReport).Assembly.GetManifestResourceStream("Wabbajack.CLI.Resources.ModlistReport.html")!).ReadAllText();
var func = NettleEngine.GetCompiler().Compile(data);
return func(o);
}
public async Task<int> Run(AbsolutePath input)
{
_logger.LogInformation("Loading Modlist");
var modlist = await StandardInstaller.LoadFromFile(_dtos, input);
Dictionary<string, long> patchSizes;
using (var zip = new ZipArchive(input.Open(FileMode.Open, FileAccess.Read, FileShare.Read)))
{
patchSizes = zip.Entries.ToDictionary(e => e.Name, e => e.Length);
}
var archives = modlist.Archives.ToDictionary(a => a.Hash, a => a.Name);
var bsas = modlist.Directives.OfType<CreateBSA>().ToDictionary(bsa => bsa.TempID.ToString());
var inlinedData = modlist.Directives.OfType<InlineFile>()
.Select(e => new
{
To = e.To.ToString(),
Id = e.SourceDataID.ToString(),
SizeInt = e.Size,
Size = e.Size.ToFileSizeString()
}).ToArray();
string FixupTo(RelativePath path)
{
if (path.GetPart(0) != StandardInstaller.BSACreationDir.ToString()) return path.ToString();
var bsaId = path.GetPart(1);
if (!bsas.TryGetValue(bsaId, out var bsa))
{
return path.ToString();
}
var relPath = RelativePath.FromParts(path.Parts[2..]);
return $"<i> {bsa.To} </i> | {relPath}";
}
var patchData = modlist.Directives.OfType<PatchedFromArchive>()
.Select(e => new
{
From = $"<i> {archives[e.ArchiveHashPath.Hash]} </i> | {string.Join(" | ", e.ArchiveHashPath.Parts.Select(e => e.ToString()))}",
To = FixupTo(e.To),
Id = e.PatchID.ToString(),
PatchSize = patchSizes[e.PatchID.ToString()].ToFileSizeString(),
PatchSizeInt = patchSizes[e.PatchID.ToString()],
FinalSize = e.Size.ToFileSizeString(),
}).ToArray();
var data = await ReportTemplate(new
{
Name = modlist.Name,
TotalInlinedSize = inlinedData.Sum(i => i.SizeInt).ToFileSizeString(),
InlinedData = inlinedData,
TotalPatchSize = patchData.Sum(i => i.PatchSizeInt).ToFileSizeString(),
PatchData = patchData,
WabbajackSize = input.Size().ToFileSizeString()
});
await input.WithExtension(Ext.Html).WriteAllTextAsync(data);
return 0;
}
}

View File

@ -36,4 +36,9 @@
<ProjectReference Include="..\Wabbajack.VFS\Wabbajack.VFS.csproj" />
</ItemGroup>
<ItemGroup>
<None Remove="Resources\ModlistReport.html" />
<EmbeddedResource Include="Resources\ModlistReport.html" />
</ItemGroup>
</Project>

View File

@ -89,6 +89,7 @@ public struct DDS_HEADER
return 9 * 4 + PixelFormat.GetSize() + 14 * 4;
}
public void Write(BinaryWriter bw)
{
bw.Write(dwSize);

View File

@ -439,6 +439,7 @@ public static class GameRegistry
Game = Game.DragonsDogma,
SteamIDs = new[] {367500 },
MO2Name = "Dragon's Dogma: Dark Arisen",
MO2ArchiveName = "dragonsdogma",
NexusName = "dragonsdogma",
NexusGameId = 1249,
IsGenericMO2Plugin = true,

View File

@ -99,7 +99,10 @@ public class NexusDownloader : ADownloader<Nexus>, IUrlDownloader
{
if (iniData.TryGetValue("gameName", out var gameName) &&
iniData.TryGetValue("modID", out var modId) &&
iniData.TryGetValue("fileID", out var fileId))
iniData.TryGetValue("fileID", out var fileId) &&
!string.IsNullOrWhiteSpace(gameName) &&
!string.IsNullOrWhiteSpace(modId) &&
!string.IsNullOrWhiteSpace(fileId))
return new Nexus
{
Game = GameRegistry.GetByMO2ArchiveName(gameName)!.Game,

View File

@ -5,7 +5,7 @@ namespace Wabbajack.Paths;
public struct RelativePath : IPath, IEquatable<RelativePath>, IComparable<RelativePath>
{
internal readonly string[] Parts;
public readonly string[] Parts;
private int _hashCode = 0;
@ -14,6 +14,11 @@ public struct RelativePath : IPath, IEquatable<RelativePath>, IComparable<Relati
Parts = parts;
}
public static RelativePath FromParts(string[] parts)
{
return new RelativePath(parts);
}
public static explicit operator RelativePath(string i)
{
var splits = i.Split(AbsolutePath.StringSplits, StringSplitOptions.RemoveEmptyEntries);