forked from wabbajack-tools/wabbajack
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ModListHarness.cs
189 lines (163 loc) · 7.08 KB
/
ModListHarness.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Wabbajack.Common;
using Wabbajack.Downloaders;
using Wabbajack.DTOs;
using Wabbajack.DTOs.JsonConverters;
using Wabbajack.Installer;
using Wabbajack.Paths;
using Wabbajack.Paths.IO;
using Xunit;
namespace Wabbajack.Compiler.Test;
public class ModListHarness
{
private readonly DownloadDispatcher _downloadDispatcher;
private readonly AbsolutePath _downloadPath;
private readonly DTOSerializer _dtos;
public readonly FileExtractor.FileExtractor _fileExtractor;
private readonly AbsolutePath _gameFolder;
private readonly AbsolutePath _installDownloads;
private readonly AbsolutePath _installLocation;
private readonly ILogger<ModListHarness> _logger;
private readonly TemporaryFileManager _manager;
private readonly Dictionary<RelativePath, Mod> _mods;
private readonly AbsolutePath _modsFolder;
private readonly AbsolutePath _outputFile;
private readonly TemporaryPath _outputFolder;
private readonly string _profileName;
private readonly IServiceProvider _serviceProvider;
public readonly AbsolutePath _source;
public ModListHarness(ILogger<ModListHarness> logger, TemporaryFileManager manager,
FileExtractor.FileExtractor fileExtractor, IServiceProvider serviceProvider,
DownloadDispatcher downloadDispatcher, DTOSerializer dtos)
{
_logger = logger;
_manager = manager;
_source = _manager.CreateFolder();
_profileName = Guid.NewGuid().ToString();
_downloadPath = _manager.CreateFolder();
_installLocation = _manager.CreateFolder();
_outputFolder = _manager.CreateFolder();
_modsFolder = _source.Combine(Consts.MO2ModFolderName);
_mods = new Dictionary<RelativePath, Mod>();
_fileExtractor = fileExtractor;
_serviceProvider = serviceProvider;
_downloadDispatcher = downloadDispatcher;
_gameFolder = _manager.CreateFolder();
_outputFile = _outputFolder.Path.Combine(_profileName + ".wabbajack");
_installDownloads = _installLocation.Combine("downloads");
_dtos = dtos;
}
public Mod AddMod(string? name = null)
{
name ??= Guid.NewGuid().ToString();
var mod = new Mod(name.ToRelativePath(), _modsFolder.Combine(name), this, new HashSet<string>());
_mods[name!.ToRelativePath()] = mod;
return mod;
}
public async Task<ModList?> CompileAndInstall(Action<CompilerSettings>? configureSettings = null)
{
var modlist = await Compile(configureSettings);
await Install();
return modlist;
}
public async Task<ModList?> Compile(Action<CompilerSettings>? configureSettings = null)
{
configureSettings ??= x => { };
_source.Combine(Consts.MO2Profiles, _profileName).CreateDirectory();
using var scope = _serviceProvider.CreateScope();
var settings = scope.ServiceProvider.GetService<CompilerSettings>()!;
settings.Downloads = _downloadPath;
settings.Game = Game.SkyrimSpecialEdition;
settings.Source = _source;
settings.ModListName = _profileName;
settings.Profile = _profileName;
settings.OutputFile = _outputFile;
settings.UseTextureRecompression = true;
configureSettings(settings);
var modLines = _mods.Select(
m => (m.Value.EnabledIn.Contains(_profileName) ? "+" : "-") + m.Key);
await _source.Combine(Consts.MO2Profiles, _profileName, Consts.ModListTxt)
.WriteAllLinesAsync(modLines,
CancellationToken.None);
var compiler = scope.ServiceProvider.GetService<MO2Compiler>();
if (!await compiler!.Begin(CancellationToken.None))
return null;
var modlist = await StandardInstaller.LoadFromFile(_dtos, settings.OutputFile);
return modlist;
}
public async Task<bool> Install()
{
using var scope = _serviceProvider.CreateScope();
var settings = scope.ServiceProvider.GetService<InstallerConfiguration>()!;
settings.Install = _installLocation;
settings.Downloads = _installDownloads;
settings.ModList = await StandardInstaller.LoadFromFile(_dtos, _outputFile);
settings.ModlistArchive = _outputFile;
settings.Game = Game.SkyrimSpecialEdition;
settings.GameFolder = _gameFolder;
settings.SystemParameters = new SystemParameters
{
ScreenWidth = 1920,
ScreenHeight = 1080,
SystemMemorySize = 8L * 1024 * 1024 * 1024,
SystemPageSize = 8L * 1024 * 1024 * 1024,
VideoMemorySize = 8L * 1024 * 1024 * 1024
};
var installer = scope.ServiceProvider.GetService<StandardInstaller>()!;
return await installer.Begin(CancellationToken.None);
}
public async Task AddManualDownload(AbsolutePath path)
{
var toPath = path.FileName.RelativeTo(_downloadPath);
await path.CopyToAsync(toPath, CancellationToken.None);
await toPath.WithExtension(Ext.Meta)
.WriteAllLinesAsync(new[] {"[General]", $"manualURL={path.FileName}"}, CancellationToken.None);
}
public async Task<Mod> InstallMod(Extension ext, Uri uri)
{
var state = _downloadDispatcher.Parse(uri);
var file = (Guid.NewGuid() + ext.ToString()).ToRelativePath();
var archive = new Archive {State = state!, Name = file.ToString()};
_logger.LogInformation("Downloading: {uri}", uri);
await _downloadDispatcher.Download(archive, file.RelativeTo(_downloadPath), CancellationToken.None);
await file.WithExtension(Ext.Meta).RelativeTo(_downloadPath)
.WriteAllTextAsync(_downloadDispatcher.MetaIniSection(archive), CancellationToken.None);
var mod = AddMod(file.WithoutExtension().ToString());
mod.EnabledIn.Add(_profileName);
_logger.LogInformation("Extracting: {file}", file);
await mod.AddFromArchive(file.RelativeTo(_downloadPath));
return mod;
}
public void VerifyInstalledFile(AbsolutePath source)
{
var dest = source.RelativeTo(_source).RelativeTo(_installLocation);
_logger.LogInformation("Verifying {file}", source.RelativeTo(_source));
Assert.Equal(source.Size(), dest.Size());
}
}
public record Mod(RelativePath Name, AbsolutePath FullPath, ModListHarness Harness, HashSet<string> EnabledIn)
{
public async Task<AbsolutePath> AddFile(AbsolutePath src)
{
var dest = FullPath.Combine(src.FileName);
await src.CopyToAsync(dest, CancellationToken.None);
return dest;
}
public async Task AddFromArchive(AbsolutePath src)
{
await Harness._fileExtractor.ExtractAll(src, FullPath, CancellationToken.None);
}
public async Task<AbsolutePath> AddData(RelativePath path, string data)
{
var fullPath = FullPath.Combine(path);
fullPath.Parent.CreateDirectory();
await fullPath.WriteAllTextAsync(data);
return fullPath;
}
}