mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Merge branch 'master' into issue-520
This commit is contained in:
commit
109681b2c6
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Platforms>x64</Platforms>
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
|
@ -113,6 +113,9 @@ namespace Wabbajack.BuildServer.Controllers
|
||||
continue;
|
||||
}
|
||||
|
||||
if (data is ManualDownloader.State)
|
||||
continue;
|
||||
|
||||
var key = data.PrimaryKeyString;
|
||||
var found = await Db.DownloadStates.AsQueryable().Where(f => f.Key == key).Take(1).ToListAsync();
|
||||
if (found.Count > 0)
|
||||
|
@ -24,6 +24,9 @@ namespace Wabbajack.BuildServer.Models.Jobs
|
||||
public override bool UsesNexus { get => Archive.State is NexusDownloader.State; }
|
||||
public override async Task<JobResult> Execute(DBContext db, SqlService sql, AppSettings settings)
|
||||
{
|
||||
if (Archive.State is ManualDownloader.State)
|
||||
return JobResult.Success();
|
||||
|
||||
var pk = new List<object>();
|
||||
pk.Add(AbstractDownloadState.TypeToName[Archive.State.GetType()]);
|
||||
pk.AddRange(Archive.State.PrimaryKey);
|
||||
|
@ -102,5 +102,6 @@ namespace Wabbajack.Common
|
||||
public const string MO2ModFolderName = "mods";
|
||||
|
||||
public static string PatchCacheFolder => Path.Combine(LocalAppDataPath, "patch_cache");
|
||||
public static int MaxConnectionsPerServer = 4;
|
||||
}
|
||||
}
|
||||
|
62
Wabbajack.Common/Http/Client.cs
Normal file
62
Wabbajack.Common/Http/Client.cs
Normal file
@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Wabbajack.Common.Http
|
||||
{
|
||||
public class Client
|
||||
{
|
||||
public List<(string, string)> Headers = new List<(string, string)>();
|
||||
public List<Cookie> Cookies = new List<Cookie>();
|
||||
public async Task<HttpResponseMessage> GetAsync(string url, HttpCompletionOption responseHeadersRead = HttpCompletionOption.ResponseContentRead)
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||
foreach (var (k, v) in Headers)
|
||||
request.Headers.Add(k, v);
|
||||
return await SendAsync(request, responseHeadersRead);
|
||||
}
|
||||
|
||||
public async Task<string> GetStringAsync(string url)
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||
foreach (var (k, v) in Headers)
|
||||
request.Headers.Add(k, v);
|
||||
if (Cookies.Count > 0)
|
||||
Cookies.ForEach(c => ClientFactory.Cookies.Add(c));
|
||||
|
||||
return await SendStringAsync(request);
|
||||
}
|
||||
|
||||
private async Task<string> SendStringAsync(HttpRequestMessage request)
|
||||
{
|
||||
var result = await SendAsync(request);
|
||||
return await result.Content.ReadAsStringAsync();
|
||||
}
|
||||
|
||||
|
||||
public async Task<HttpResponseMessage> SendAsync(HttpRequestMessage msg, HttpCompletionOption responseHeadersRead = HttpCompletionOption.ResponseContentRead)
|
||||
{
|
||||
int retries = 0;
|
||||
TOP:
|
||||
try
|
||||
{
|
||||
var response = await ClientFactory.Client.SendAsync(msg, responseHeadersRead);
|
||||
return response;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
if (retries > Consts.MaxHTTPRetries) throw;
|
||||
|
||||
retries++;
|
||||
Utils.Log($"Http Connect error to {msg.RequestUri} retry {retries}");
|
||||
await Task.Delay(100 * retries);
|
||||
goto TOP;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
25
Wabbajack.Common/Http/ClientFactory.cs
Normal file
25
Wabbajack.Common/Http/ClientFactory.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using SysHttp = System.Net.Http;
|
||||
namespace Wabbajack.Common.Http
|
||||
{
|
||||
public static class ClientFactory
|
||||
{
|
||||
private static SysHttp.SocketsHttpHandler _socketsHandler { get; }
|
||||
internal static SysHttp.HttpClient Client { get; }
|
||||
internal static CookieContainer Cookies { get; }
|
||||
|
||||
static ClientFactory()
|
||||
{
|
||||
Cookies = new CookieContainer();
|
||||
_socketsHandler = new SysHttp.SocketsHttpHandler
|
||||
{
|
||||
CookieContainer = Cookies,
|
||||
MaxConnectionsPerServer = 8,
|
||||
PooledConnectionLifetime = TimeSpan.FromSeconds(2),
|
||||
PooledConnectionIdleTimeout = TimeSpan.FromSeconds(2)
|
||||
};
|
||||
Client = new SysHttp.HttpClient(_socketsHandler);
|
||||
}
|
||||
}
|
||||
}
|
@ -32,7 +32,7 @@ namespace Wabbajack.Common
|
||||
var tempKey = progIDKey?.OpenSubKey("shell\\open\\command");
|
||||
if (progIDKey == null || tempKey == null) return true;
|
||||
var value = tempKey.GetValue("");
|
||||
return value == null || value.ToString().Equals($"\"{appPath}\" -i=\"%1\"");
|
||||
return value == null || !value.ToString().Equals($"\"{appPath}\" -i=\"%1\"");
|
||||
}
|
||||
|
||||
public static bool IsAssociated()
|
||||
|
@ -53,15 +53,18 @@ namespace Wabbajack.Common
|
||||
if (!Directory.Exists(Consts.LocalAppDataPath))
|
||||
Directory.CreateDirectory(Consts.LocalAppDataPath);
|
||||
|
||||
if (!Directory.Exists("logs"))
|
||||
Directory.CreateDirectory("logs");
|
||||
|
||||
var programName = Assembly.GetEntryAssembly()?.Location ?? "Wabbajack";
|
||||
LogFile = Path.GetFileNameWithoutExtension(programName) + ".current.log";
|
||||
LogFile = Path.Combine("logs", Path.GetFileNameWithoutExtension(programName) + ".current.log");
|
||||
_startTime = DateTime.Now;
|
||||
|
||||
|
||||
if (LogFile.FileExists())
|
||||
{
|
||||
var new_path = Path.GetFileNameWithoutExtension(programName) + (new FileInfo(LogFile)).LastWriteTime.ToString(" yyyy-MM-dd HH_mm_ss") + ".log";
|
||||
File.Move(LogFile, new_path, MoveOptions.ReplaceExisting);
|
||||
var newPath = Path.Combine("logs", Path.GetFileNameWithoutExtension(programName) + (new FileInfo(LogFile)).LastWriteTime.ToString(" yyyy-MM-dd HH_mm_ss") + ".log");
|
||||
File.Move(LogFile, newPath, MoveOptions.ReplaceExisting);
|
||||
}
|
||||
|
||||
var watcher = new FileSystemWatcher(Consts.LocalAppDataPath);
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<Platforms>x64</Platforms>
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
|
||||
@ -40,6 +40,7 @@
|
||||
<PackageReference Include="ReactiveUI" Version="11.1.23" />
|
||||
<PackageReference Include="SharpZipLib" Version="1.2.0" />
|
||||
<PackageReference Include="System.Data.HashFunction.xxHash" Version="2.0.0" />
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
||||
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.7.0" />
|
||||
<PackageReference Include="System.Security.Principal.Windows" Version="4.7.0" />
|
||||
<PackageReference Include="YamlDotNet" Version="8.1.0" />
|
||||
|
@ -22,7 +22,7 @@ namespace Wabbajack.Lib
|
||||
public bool ReadmeIsWebsite;
|
||||
public string WabbajackVersion;
|
||||
|
||||
protected static string _vfsCacheName => Path.Combine(Consts.LocalAppDataPath, "vfs_compile_cache.bin");
|
||||
protected string _vfsCacheName => Path.Combine(Consts.LocalAppDataPath, $"vfs_compile_cache_{ModListName?.StringSHA256Hex() ?? "_Unknown_"}.bin");
|
||||
/// <summary>
|
||||
/// A stream of tuples of ("Update Title", 0.25) which represent the name of the current task
|
||||
/// and the current progress.
|
||||
|
@ -21,7 +21,7 @@ namespace Wabbajack.Lib.Downloaders
|
||||
private readonly string _encryptedKeyName;
|
||||
private readonly string _cookieDomain;
|
||||
private readonly string _cookieName;
|
||||
internal HttpClient AuthedClient;
|
||||
internal Common.Http.Client AuthedClient;
|
||||
|
||||
/// <summary>
|
||||
/// Sets up all the login facilites needed for a INeedsLogin downloader based on having the user log
|
||||
@ -81,7 +81,7 @@ namespace Wabbajack.Lib.Downloaders
|
||||
return cookies;
|
||||
}
|
||||
|
||||
public async Task<HttpClient> GetAuthedClient()
|
||||
public async Task<Common.Http.Client> GetAuthedClient()
|
||||
{
|
||||
Helpers.Cookie[] cookies;
|
||||
try
|
||||
|
@ -53,7 +53,7 @@ namespace Wabbajack.Lib.Downloaders
|
||||
private async Task<HTTPDownloader.State> ToHttpState()
|
||||
{
|
||||
var initialURL = $"https://drive.google.com/uc?id={Id}&export=download";
|
||||
var client = new HttpClient();
|
||||
var client = new Common.Http.Client();
|
||||
var response = await client.GetAsync(initialURL);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
throw new HttpException((int)response.StatusCode, response.ReasonPhrase);
|
||||
|
@ -61,7 +61,7 @@ namespace Wabbajack.Lib.Downloaders
|
||||
public List<string> Headers { get; set; }
|
||||
|
||||
[Exclude]
|
||||
public HttpClient Client { get; set; }
|
||||
public Common.Http.Client Client { get; set; }
|
||||
|
||||
public override object[] PrimaryKey { get => new object[] {Url};}
|
||||
|
||||
@ -86,8 +86,8 @@ namespace Wabbajack.Lib.Downloaders
|
||||
|
||||
using (var fs = download ? File.Open(destination, FileMode.Create) : null)
|
||||
{
|
||||
var client = Client ?? new HttpClient();
|
||||
client.DefaultRequestHeaders.Add("User-Agent", Consts.UserAgent);
|
||||
var client = Client ?? new Common.Http.Client();
|
||||
client.Headers.Add(("User-Agent", Consts.UserAgent));
|
||||
|
||||
if (Headers != null)
|
||||
foreach (var header in Headers)
|
||||
@ -95,7 +95,7 @@ namespace Wabbajack.Lib.Downloaders
|
||||
var idx = header.IndexOf(':');
|
||||
var k = header.Substring(0, idx);
|
||||
var v = header.Substring(idx + 1);
|
||||
client.DefaultRequestHeaders.Add(k, v);
|
||||
client.Headers.Add((k, v));
|
||||
}
|
||||
|
||||
long totalRead = 0;
|
||||
|
@ -53,7 +53,7 @@ namespace Wabbajack.Lib.Downloaders
|
||||
if (newURL == null || !newURL.StartsWith("http")) return null;
|
||||
return new HTTPDownloader.State()
|
||||
{
|
||||
Client = new HttpClient(),
|
||||
Client = new Common.Http.Client(),
|
||||
Url = newURL
|
||||
};
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ namespace Wabbajack.Lib.FileUploader
|
||||
|
||||
public static HttpClient GetAuthorizedClient()
|
||||
{
|
||||
var handler = new HttpClientHandler {MaxConnectionsPerServer = MAX_CONNECTIONS};
|
||||
var handler = new HttpClientHandler {MaxConnectionsPerServer = Consts.MaxConnectionsPerServer};
|
||||
var client = new HttpClient(handler);
|
||||
client.DefaultRequestHeaders.Add("X-API-KEY", AuthorAPI.GetAPIKey());
|
||||
return client;
|
||||
@ -144,7 +144,7 @@ namespace Wabbajack.Lib.FileUploader
|
||||
return await RunJob("UpdateModLists");
|
||||
}
|
||||
|
||||
public static async Task UploadPackagedInis(IEnumerable<IndexedArchive> archives)
|
||||
public static async Task UploadPackagedInis(WorkQueue queue, IEnumerable<Archive> archives)
|
||||
{
|
||||
archives = archives.ToArray(); // defensive copy
|
||||
Utils.Log($"Packaging {archives.Count()} inis");
|
||||
@ -153,12 +153,12 @@ namespace Wabbajack.Lib.FileUploader
|
||||
await using var ms = new MemoryStream();
|
||||
using (var z = new ZipArchive(ms, ZipArchiveMode.Create, true))
|
||||
{
|
||||
foreach (var archive in archives)
|
||||
foreach (var e in archives)
|
||||
{
|
||||
var state = (AbstractDownloadState)(await DownloadDispatcher.ResolveArchive(archive.IniData));
|
||||
var entry = z.CreateEntry(Path.GetFileName(archive.Name));
|
||||
if (e.State == null) continue;
|
||||
var entry = z.CreateEntry(Path.GetFileName(e.Name));
|
||||
await using var os = entry.Open();
|
||||
await os.WriteAsync(Encoding.UTF8.GetBytes(string.Join("\n", state.GetMetaIni())));
|
||||
await os.WriteAsync(Encoding.UTF8.GetBytes(string.Join("\n", e.State.GetMetaIni())));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,12 +16,11 @@ namespace Wabbajack.Lib.LibCefHelpers
|
||||
{
|
||||
public static class Helpers
|
||||
{
|
||||
public static HttpClient GetClient(IEnumerable<Cookie> cookies, string referer)
|
||||
public static Common.Http.Client GetClient(IEnumerable<Cookie> cookies, string referer)
|
||||
{
|
||||
var container = ToCookieContainer(cookies);
|
||||
var handler = new HttpClientHandler { CookieContainer = container };
|
||||
var client = new HttpClient(handler);
|
||||
client.DefaultRequestHeaders.Referrer = new Uri(referer);
|
||||
var client = new Common.Http.Client();
|
||||
client.Headers.Add(("Referrer", referer));
|
||||
client.Cookies.AddRange(cookies.Select(cookie => new System.Net.Cookie(cookie.Name, cookie.Value, cookie.Path, cookie.Domain)));
|
||||
return client;
|
||||
}
|
||||
|
||||
|
@ -129,6 +129,7 @@ namespace Wabbajack.Lib
|
||||
if (Directory.Exists(ModListOutputFolder))
|
||||
Utils.DeleteDirectory(ModListOutputFolder);
|
||||
|
||||
/*
|
||||
if (cancel.IsCancellationRequested) return false;
|
||||
UpdateTracker.NextStep("Inferring metas for game file downloads");
|
||||
await InferMetas();
|
||||
@ -137,10 +138,12 @@ namespace Wabbajack.Lib
|
||||
UpdateTracker.NextStep("Reindexing downloads after meta inferring");
|
||||
await VFS.AddRoot(MO2DownloadsFolder);
|
||||
await VFS.WriteToFile(_vfsCacheName);
|
||||
*/
|
||||
|
||||
if (cancel.IsCancellationRequested) return false;
|
||||
UpdateTracker.NextStep("Pre-validating Archives");
|
||||
|
||||
|
||||
IndexedArchives = Directory.EnumerateFiles(MO2DownloadsFolder)
|
||||
.Where(f => File.Exists(f + Consts.MetaFileExtension))
|
||||
.Select(f => new IndexedArchive
|
||||
@ -152,8 +155,7 @@ namespace Wabbajack.Lib
|
||||
})
|
||||
.ToList();
|
||||
|
||||
// Don't await this because we don't care if it fails.
|
||||
var _ = AuthorAPI.UploadPackagedInis(IndexedArchives);
|
||||
|
||||
|
||||
await CleanInvalidArchives();
|
||||
|
||||
@ -261,6 +263,11 @@ namespace Wabbajack.Lib
|
||||
|
||||
UpdateTracker.NextStep("Gathering Archives");
|
||||
await GatherArchives();
|
||||
|
||||
// Don't await this because we don't care if it fails.
|
||||
Utils.Log("Finding States to package");
|
||||
await AuthorAPI.UploadPackagedInis(Queue, SelectedArchives.ToArray());
|
||||
|
||||
UpdateTracker.NextStep("Including Archive Metadata");
|
||||
await IncludeArchiveMetadata();
|
||||
UpdateTracker.NextStep("Building Patches");
|
||||
@ -349,7 +356,15 @@ namespace Wabbajack.Lib
|
||||
await client.GetAsync(
|
||||
$"http://build.wabbajack.org/indexed_files/{vf.Hash.FromBase64().ToHex()}/meta.ini");
|
||||
|
||||
if (!response.IsSuccessStatusCode) return;
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
File.WriteAllLines(vf.FullPath + Consts.MetaFileExtension, new []
|
||||
{
|
||||
"[General]",
|
||||
"unknownArchive=true"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var ini_data = await response.Content.ReadAsStringAsync();
|
||||
Utils.Log($"Inferred .meta for {Path.GetFileName(vf.FullPath)}, writing to disk");
|
||||
|
@ -24,9 +24,7 @@ namespace Wabbajack.Lib.NexusApi
|
||||
private static readonly string API_KEY_CACHE_FILE = "nexus.key_cache";
|
||||
private static string _additionalEntropy = "vtP2HF6ezg";
|
||||
|
||||
private static object _diskLock = new object();
|
||||
|
||||
public HttpClient HttpClient { get; } = new HttpClient();
|
||||
public Common.Http.Client HttpClient { get; } = new Common.Http.Client();
|
||||
|
||||
#region Authentication
|
||||
|
||||
@ -202,14 +200,13 @@ namespace Wabbajack.Lib.NexusApi
|
||||
{
|
||||
ApiKey = apiKey;
|
||||
|
||||
HttpClient.BaseAddress = new Uri("https://api.nexusmods.com");
|
||||
// set default headers for all requests to the Nexus API
|
||||
var headers = HttpClient.DefaultRequestHeaders;
|
||||
headers.Add("User-Agent", Consts.UserAgent);
|
||||
headers.Add("apikey", ApiKey);
|
||||
headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
headers.Add("Application-Name", Consts.AppName);
|
||||
headers.Add("Application-Version", $"{Assembly.GetEntryAssembly()?.GetName()?.Version ?? new Version(0, 1)}");
|
||||
var headers = HttpClient.Headers;
|
||||
headers.Add(("User-Agent", Consts.UserAgent));
|
||||
headers.Add(("apikey", ApiKey));
|
||||
headers.Add(("Accept", "application/json"));
|
||||
headers.Add(("Application-Name", Consts.AppName));
|
||||
headers.Add(("Application-Version", $"{Assembly.GetEntryAssembly()?.GetName()?.Version ?? new Version(0, 1)}"));
|
||||
|
||||
if (!Directory.Exists(Consts.NexusCacheDirectory))
|
||||
Directory.CreateDirectory(Consts.NexusCacheDirectory);
|
||||
@ -227,16 +224,17 @@ namespace Wabbajack.Lib.NexusApi
|
||||
TOP:
|
||||
try
|
||||
{
|
||||
var response = await HttpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
|
||||
using var response = await HttpClient.GetAsync(url, HttpCompletionOption.ResponseContentRead);
|
||||
UpdateRemaining(response);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
throw new HttpRequestException($"{response.StatusCode} - {response.ReasonPhrase}");
|
||||
|
||||
|
||||
using (var stream = await response.Content.ReadAsStreamAsync())
|
||||
{
|
||||
return stream.FromJSON<T>();
|
||||
Utils.Log($"Nexus call failed: {response.RequestMessage}");
|
||||
throw new HttpRequestException($"{response.StatusCode} - {response.ReasonPhrase}");
|
||||
}
|
||||
|
||||
|
||||
await using var stream = await response.Content.ReadAsStreamAsync();
|
||||
return stream.FromJSON<T>();
|
||||
}
|
||||
catch (TimeoutException)
|
||||
{
|
||||
@ -246,13 +244,18 @@ namespace Wabbajack.Lib.NexusApi
|
||||
retries++;
|
||||
goto TOP;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Utils.Log(e.ToString());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<T> GetCached<T>(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
var builder = new UriBuilder(url) { Host = Consts.WabbajackCacheHostname, Port = Consts.WabbajackCachePort, Scheme = "http" };
|
||||
var builder = new UriBuilder(url) { Host = Consts.WabbajackCacheHostname, Scheme = "https" };
|
||||
return await Get<T>(builder.ToString());
|
||||
}
|
||||
catch (Exception)
|
||||
@ -273,6 +276,10 @@ namespace Wabbajack.Lib.NexusApi
|
||||
}
|
||||
catch (HttpRequestException)
|
||||
{
|
||||
if (await IsPremium())
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
@ -319,19 +326,6 @@ namespace Wabbajack.Lib.NexusApi
|
||||
return await GetCached<ModInfo>(url);
|
||||
}
|
||||
|
||||
public async Task<EndorsementResponse> EndorseMod(NexusDownloader.State mod)
|
||||
{
|
||||
Utils.Status($"Endorsing ${mod.GameName} - ${mod.ModID}");
|
||||
var url = $"https://api.nexusmods.com/v1/games/{ConvertGameName(mod.GameName)}/mods/{mod.ModID}/endorse.json";
|
||||
|
||||
var content = new FormUrlEncodedContent(new Dictionary<string, string> { { "version", mod.Version } });
|
||||
|
||||
using (var stream = await HttpClient.PostStream(url, content))
|
||||
{
|
||||
return stream.FromJSON<EndorsementResponse>();
|
||||
}
|
||||
}
|
||||
|
||||
private class DownloadLink
|
||||
{
|
||||
public string URI { get; set; }
|
||||
|
@ -12,8 +12,8 @@ namespace Wabbajack.Lib
|
||||
public override string ShortDescription { get; }
|
||||
public override string ExtendedDescription { get; }
|
||||
|
||||
private TaskCompletionSource<(Uri, HttpClient)> _tcs = new TaskCompletionSource<(Uri, HttpClient)>();
|
||||
public Task<(Uri, HttpClient)> Task => _tcs.Task;
|
||||
private TaskCompletionSource<(Uri, Common.Http.Client)> _tcs = new TaskCompletionSource<(Uri, Common.Http.Client)>();
|
||||
public Task<(Uri, Common.Http.Client)> Task => _tcs.Task;
|
||||
|
||||
private ManuallyDownloadFile(ManualDownloader.State state)
|
||||
{
|
||||
@ -30,7 +30,7 @@ namespace Wabbajack.Lib
|
||||
_tcs.SetCanceled();
|
||||
}
|
||||
|
||||
public void Resume(Uri s, HttpClient client)
|
||||
public void Resume(Uri s, Common.Http.Client client)
|
||||
{
|
||||
_tcs.SetResult((s, client));
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<Platforms>x64</Platforms>
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
@ -24,7 +24,7 @@ namespace Wabbajack.VirtualFileSystem
|
||||
Utils.Log("Cleaning VFS, this may take a bit of time");
|
||||
Utils.DeleteDirectory(_stagingFolder);
|
||||
}
|
||||
public const ulong FileVersion = 0x02;
|
||||
public const ulong FileVersion = 0x03;
|
||||
public const string Magic = "WABBAJACK VFS FILE";
|
||||
|
||||
private static readonly string _stagingFolder = "vfs_staging";
|
||||
@ -420,13 +420,16 @@ namespace Wabbajack.VirtualFileSystem
|
||||
public TemporaryDirectory(string name)
|
||||
{
|
||||
FullName = name;
|
||||
if (!Directory.Exists(FullName))
|
||||
Directory.CreateDirectory(FullName);
|
||||
}
|
||||
|
||||
public string FullName { get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Utils.DeleteDirectory(FullName);
|
||||
if (Directory.Exists(FullName))
|
||||
Utils.DeleteDirectory(FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -114,6 +114,20 @@ namespace Wabbajack.VirtualFileSystem
|
||||
}
|
||||
|
||||
|
||||
public T ThisAndAllChildrenReduced<T>(T acc, Func<T, VirtualFile, T> fn)
|
||||
{
|
||||
acc = fn(acc, this);
|
||||
return this.Children.Aggregate(acc, (current, itm) => itm.ThisAndAllChildrenReduced<T>(current, fn));
|
||||
}
|
||||
|
||||
public void ThisAndAllChildrenReduced(Action<VirtualFile> fn)
|
||||
{
|
||||
fn(this);
|
||||
foreach (var itm in Children)
|
||||
itm.ThisAndAllChildrenReduced(fn);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns all the virtual files in the path to this file, starting from the root file.
|
||||
/// </summary>
|
||||
@ -233,6 +247,7 @@ namespace Wabbajack.VirtualFileSystem
|
||||
private void Write(BinaryWriter bw)
|
||||
{
|
||||
bw.Write(Name);
|
||||
bw.Write(FullPath);
|
||||
bw.Write(Hash);
|
||||
bw.Write(Size);
|
||||
bw.Write(LastModified);
|
||||
@ -258,6 +273,7 @@ namespace Wabbajack.VirtualFileSystem
|
||||
Context = context,
|
||||
Parent = parent,
|
||||
Name = br.ReadString(),
|
||||
_fullPath = br.ReadString(),
|
||||
Hash = br.ReadString(),
|
||||
Size = br.ReadInt64(),
|
||||
LastModified = br.ReadInt64(),
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<Platforms>x64</Platforms>
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
@ -76,12 +76,20 @@ Global
|
||||
{5D6A2EAF-6604-4C51-8AE2-A746B4BC5E3E}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{5D6A2EAF-6604-4C51-8AE2-A746B4BC5E3E}.Release|x64.ActiveCfg = Release|x64
|
||||
{5D6A2EAF-6604-4C51-8AE2-A746B4BC5E3E}.Release|x64.Build.0 = Release|x64
|
||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Debug|x64.Build.0 = Debug|x64
|
||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Release|x64.ActiveCfg = Release|x64
|
||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Release|x64.Build.0 = Release|x64
|
||||
{37E4D421-8FD3-4D57-8F3A-7A511D6ED5C5}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{37E4D421-8FD3-4D57-8F3A-7A511D6ED5C5}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{37E4D421-8FD3-4D57-8F3A-7A511D6ED5C5}.Debug|x64.Build.0 = Debug|x64
|
||||
{37E4D421-8FD3-4D57-8F3A-7A511D6ED5C5}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{37E4D421-8FD3-4D57-8F3A-7A511D6ED5C5}.Release|x64.ActiveCfg = Release|x64
|
||||
{37E4D421-8FD3-4D57-8F3A-7A511D6ED5C5}.Release|x64.Build.0 = Release|x64
|
||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Release|x64.Build.0 = Release|Any CPU
|
||||
{6ED08CFB-B879-4B55-8741-663A4A3491CE}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{6ED08CFB-B879-4B55-8741-663A4A3491CE}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6ED08CFB-B879-4B55-8741-663A4A3491CE}.Debug|x64.Build.0 = Debug|x64
|
||||
|
Loading…
Reference in New Issue
Block a user