NetworkTaskFactory
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
using System.Security.Cryptography;
|
||||
using DTLib.Extensions;
|
||||
using Млаумчерб.Клиент.видимое;
|
||||
using Млаумчерб.Клиент.классы;
|
||||
using static Млаумчерб.Клиент.сеть.Сеть;
|
||||
|
||||
namespace Млаумчерб.Клиент.сеть.NetworkTaskFactories;
|
||||
|
||||
public class AssetsDownloadTaskFactory : INetworkTaskFactory
|
||||
{
|
||||
private const string ASSET_SERVER_URL = "https://resources.download.minecraft.net/";
|
||||
private VersionDescriptor _descriptor;
|
||||
private SHA1 _hasher;
|
||||
private IOPath _indexFilePath;
|
||||
List<AssetDownloadProperties> _assetsToDownload = new();
|
||||
|
||||
public AssetsDownloadTaskFactory(VersionDescriptor descriptor)
|
||||
{
|
||||
_descriptor = descriptor;
|
||||
_hasher = SHA1.Create();
|
||||
_indexFilePath = Пути.GetAssetIndexFilePath(_descriptor.assetIndex.id);
|
||||
}
|
||||
|
||||
public async Task<NetworkTask?> CreateAsync(bool checkHashes)
|
||||
{
|
||||
if (!await CheckFilesAsync(checkHashes))
|
||||
return new NetworkTask(
|
||||
$"assets '{_descriptor.assetIndex.id}'",
|
||||
GetTotalSize(),
|
||||
Download
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
private async Task<bool> CheckFilesAsync(bool checkHashes)
|
||||
{
|
||||
if(!File.Exists(_indexFilePath))
|
||||
{
|
||||
Приложение.Логгер.LogInfo(nameof(Сеть), $"started downloading asset index to '{_indexFilePath}'");
|
||||
await DownloadFileHTTP(_descriptor.assetIndex.url, _indexFilePath);
|
||||
Приложение.Логгер.LogInfo(nameof(Сеть), "finished downloading asset index");
|
||||
}
|
||||
|
||||
string indexFileText = File.ReadAllText(_indexFilePath);
|
||||
var assetIndex = JsonConvert.DeserializeObject<AssetIndex>(indexFileText)
|
||||
?? throw new Exception($"can't deserialize asset index file '{_indexFilePath}'");
|
||||
|
||||
_assetsToDownload.Clear();
|
||||
// removing duplicates for Dictionary (idk how can it be possible, but Newtonsoft.Json creates them)
|
||||
HashSet<string> assetHashes = new HashSet<string>();
|
||||
foreach (var pair in assetIndex.objects)
|
||||
{
|
||||
if (assetHashes.Add(pair.Value.hash))
|
||||
{
|
||||
var a = new AssetDownloadProperties(pair.Key, pair.Value);
|
||||
if (!File.Exists(a.filePath))
|
||||
{
|
||||
_assetsToDownload.Add(a);
|
||||
}
|
||||
else if(checkHashes)
|
||||
{
|
||||
await using var fs = File.OpenRead(a.filePath);
|
||||
string hash = _hasher.ComputeHash(fs).HashToString();
|
||||
if (hash != a.hash)
|
||||
_assetsToDownload.Add(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _assetsToDownload.Count == 0;
|
||||
}
|
||||
|
||||
private long GetTotalSize()
|
||||
{
|
||||
long totalSize = 0;
|
||||
foreach (var a in _assetsToDownload)
|
||||
totalSize += a.size;
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
private class AssetDownloadProperties
|
||||
{
|
||||
public string name;
|
||||
public string hash;
|
||||
public long size;
|
||||
public string url;
|
||||
public IOPath filePath;
|
||||
|
||||
public AssetDownloadProperties(string key, AssetProperties p)
|
||||
{
|
||||
name = key;
|
||||
hash = p.hash;
|
||||
size = p.size;
|
||||
string hashStart = hash.Substring(0, 2);
|
||||
url = $"{ASSET_SERVER_URL}/{hashStart}/{hash}";
|
||||
filePath = Path.Concat(IOPath.ArrayCast(["assets", "objects", hashStart, hash], true));
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Download(NetworkProgressReporter pr, CancellationToken ct)
|
||||
{
|
||||
Приложение.Логгер.LogInfo(nameof(Сеть), "started downloading assets");
|
||||
ParallelOptions opt = new() { MaxDegreeOfParallelism = ParallelDownloadsN, CancellationToken = ct };
|
||||
await Parallel.ForEachAsync(_assetsToDownload, opt,
|
||||
async (a, _ct) =>
|
||||
{
|
||||
Приложение.Логгер.LogDebug(nameof(Сеть), $"downloading asset '{a.name}' {a.hash}");
|
||||
await DownloadFileHTTP(a.url, a.filePath, _ct, pr.AddBytesCount);
|
||||
});
|
||||
Приложение.Логгер.LogInfo(nameof(Сеть), "finished downloading assets");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Млаумчерб.Клиент.сеть.NetworkTaskFactories;
|
||||
|
||||
public interface INetworkTaskFactory
|
||||
{
|
||||
/// <returns>unstarted network task or null if there is nothing to download</returns>
|
||||
Task<NetworkTask?> CreateAsync(bool checkHashes);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System.Security.Cryptography;
|
||||
using Млаумчерб.Клиент.классы;
|
||||
using static Млаумчерб.Клиент.сеть.Сеть;
|
||||
|
||||
namespace Млаумчерб.Клиент.сеть.NetworkTaskFactories;
|
||||
|
||||
public class JavaDownloadTaskFactory : INetworkTaskFactory
|
||||
{
|
||||
private VersionDescriptor _descriptor;
|
||||
private SHA1 _hasher;
|
||||
IOPath _javaVersionDir;
|
||||
|
||||
public JavaDownloadTaskFactory(VersionDescriptor descriptor)
|
||||
{
|
||||
_descriptor = descriptor;
|
||||
_hasher = SHA1.Create();
|
||||
_javaVersionDir = Пути.GetJavaRuntimeDir(_descriptor.javaVersion.component);
|
||||
}
|
||||
|
||||
public Task<NetworkTask?> CreateAsync(bool checkHashes)
|
||||
{
|
||||
NetworkTask? networkTask = null;
|
||||
if (!CheckFiles(checkHashes))
|
||||
networkTask = new(
|
||||
$"java runtime '{_descriptor.javaVersion.component}'",
|
||||
GetTotalSize(),
|
||||
Download
|
||||
);
|
||||
return Task.FromResult(networkTask);
|
||||
}
|
||||
|
||||
private bool CheckFiles(bool checkHashes)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private long GetTotalSize()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private Task Download(NetworkProgressReporter pr, CancellationToken ct)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using System.Security.Cryptography;
|
||||
using DTLib.Extensions;
|
||||
using Млаумчерб.Клиент.видимое;
|
||||
using Млаумчерб.Клиент.классы;
|
||||
using static Млаумчерб.Клиент.сеть.Сеть;
|
||||
|
||||
namespace Млаумчерб.Клиент.сеть.NetworkTaskFactories;
|
||||
|
||||
public class LibrariesDownloadTaskFactory : INetworkTaskFactory
|
||||
{
|
||||
private VersionDescriptor _descriptor;
|
||||
private Libraries _libraries;
|
||||
private SHA1 _hasher;
|
||||
private List<Libraries.JarLib> _libsToDownload = new();
|
||||
|
||||
public LibrariesDownloadTaskFactory(VersionDescriptor descriptor, Libraries libraries)
|
||||
{
|
||||
_descriptor = descriptor;
|
||||
_libraries = libraries;
|
||||
_hasher = SHA1.Create();
|
||||
}
|
||||
|
||||
public Task<NetworkTask?> CreateAsync(bool checkHashes)
|
||||
{
|
||||
NetworkTask? networkTask = null;
|
||||
if (!CheckFiles(checkHashes))
|
||||
networkTask = new NetworkTask(
|
||||
$"libraries '{_descriptor.id}'",
|
||||
GetTotalSize(),
|
||||
Download
|
||||
);
|
||||
return Task.FromResult(networkTask);
|
||||
}
|
||||
|
||||
private bool CheckFiles(bool checkHashes)
|
||||
{
|
||||
_libsToDownload.Clear();
|
||||
|
||||
foreach (var l in _libraries.Libs)
|
||||
{
|
||||
if (!File.Exists(l.jarFilePath))
|
||||
{
|
||||
_libsToDownload.Add(l);
|
||||
}
|
||||
else if (checkHashes)
|
||||
{
|
||||
using var fs = File.OpenRead(l.jarFilePath);
|
||||
string hash = _hasher.ComputeHash(fs).HashToString();
|
||||
if(hash != l.artifact.sha1)
|
||||
_libsToDownload.Add(l);
|
||||
}
|
||||
}
|
||||
|
||||
return _libsToDownload.Count == 0;
|
||||
}
|
||||
|
||||
private long GetTotalSize()
|
||||
{
|
||||
long total = 0;
|
||||
foreach (var l in _libsToDownload)
|
||||
total += l.artifact.size;
|
||||
return total;
|
||||
}
|
||||
|
||||
private async Task Download(NetworkProgressReporter pr, CancellationToken ct)
|
||||
{
|
||||
Приложение.Логгер.LogInfo(nameof(Сеть), "started downloading libraries");
|
||||
ParallelOptions opt = new() { MaxDegreeOfParallelism = ParallelDownloadsN, CancellationToken = ct };
|
||||
await Parallel.ForEachAsync(_libsToDownload, opt, async (l, _ct) =>
|
||||
{
|
||||
Приложение.Логгер.LogDebug(nameof(Сеть),
|
||||
$"downloading library '{l.name}' to '{l.jarFilePath}'");
|
||||
await DownloadFileHTTP(l.artifact.url, l.jarFilePath, _ct, pr.AddBytesCount);
|
||||
//TODO: extract natives from jar
|
||||
});
|
||||
Приложение.Логгер.LogInfo(nameof(Сеть), "finished downloading libraries");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using System.Security.Cryptography;
|
||||
using DTLib.Extensions;
|
||||
using Млаумчерб.Клиент.классы;
|
||||
using static Млаумчерб.Клиент.сеть.Сеть;
|
||||
|
||||
namespace Млаумчерб.Клиент.сеть.NetworkTaskFactories;
|
||||
|
||||
public class VersionFileDownloadTaskFactory : INetworkTaskFactory
|
||||
{
|
||||
private VersionDescriptor _descriptor;
|
||||
private IOPath _filePath;
|
||||
private SHA1 _hasher;
|
||||
|
||||
public VersionFileDownloadTaskFactory(VersionDescriptor descriptor)
|
||||
{
|
||||
_descriptor = descriptor;
|
||||
_filePath = Пути.GetVersionJarFilePath(_descriptor.id);
|
||||
_hasher = SHA1.Create();
|
||||
}
|
||||
|
||||
public Task<NetworkTask?> CreateAsync(bool checkHashes)
|
||||
{
|
||||
NetworkTask? networkTask = null;
|
||||
if (!CheckFiles(checkHashes))
|
||||
networkTask = new NetworkTask(
|
||||
$"version file '{_descriptor.id}'",
|
||||
GetTotalSize(),
|
||||
Download
|
||||
);
|
||||
return Task.FromResult(networkTask);
|
||||
}
|
||||
|
||||
private bool CheckFiles(bool checkHashes)
|
||||
{
|
||||
if (!File.Exists(_filePath))
|
||||
return false;
|
||||
if (!checkHashes)
|
||||
return true;
|
||||
using var fs = File.OpenRead(_filePath);
|
||||
string hash = _hasher.ComputeHash(fs).HashToString();
|
||||
return hash == _descriptor.downloads.client.sha1;
|
||||
}
|
||||
|
||||
private long GetTotalSize()
|
||||
{
|
||||
return _descriptor.downloads.client.size;
|
||||
}
|
||||
|
||||
private Task Download(NetworkProgressReporter pr, CancellationToken ct)
|
||||
{
|
||||
return DownloadFileHTTP(_descriptor.downloads.client.url, _filePath, ct, pr.AddBytesCount);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user