106 lines
3.8 KiB
C#
106 lines
3.8 KiB
C#
using System.IO.Compression;
|
||
using System.Security.Cryptography;
|
||
using DTLib.Extensions;
|
||
using Млаумчерб.Клиент.зримое;
|
||
using Млаумчерб.Клиент.классы;
|
||
using static Млаумчерб.Клиент.сеть.Сеть;
|
||
|
||
namespace Млаумчерб.Клиент.сеть.NetworkTaskFactories;
|
||
|
||
public class LibrariesDownloadTaskFactory : INetworkTaskFactory
|
||
{
|
||
private GameVersionDescriptor _descriptor;
|
||
private Libraries _libraries;
|
||
private SHA1 _hasher;
|
||
private List<Libraries.JarLib> _libsToDownload = new();
|
||
private IOPath _nativesDir;
|
||
|
||
public LibrariesDownloadTaskFactory(GameVersionDescriptor descriptor, Libraries libraries)
|
||
{
|
||
_descriptor = descriptor;
|
||
_libraries = libraries;
|
||
_hasher = SHA1.Create();
|
||
_nativesDir = Пути.GetNativeLibrariesDir(descriptor.id);
|
||
}
|
||
|
||
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();
|
||
bool nativeDirExists = Directory.Exists(_nativesDir);
|
||
|
||
foreach (var l in _libraries.Libs)
|
||
{
|
||
if (!File.Exists(l.jarFilePath))
|
||
{
|
||
_libsToDownload.Add(l);
|
||
}
|
||
else if (!nativeDirExists && l is Libraries.NativeLib)
|
||
{
|
||
_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 '{_descriptor.id}'");
|
||
|
||
ParallelOptions opt = new()
|
||
{
|
||
MaxDegreeOfParallelism = Приложение.Настройки.максимум_параллельных_загрузок,
|
||
CancellationToken = ct
|
||
};
|
||
await Parallel.ForEachAsync(_libsToDownload, opt, async (l, _ct) =>
|
||
{
|
||
Приложение.Логгер.LogDebug(nameof(Сеть), $"downloading library '{l.name}' to '{l.jarFilePath}'");
|
||
await DownloadFile(l.artifact.url, l.jarFilePath, _ct, pr.AddBytesCount);
|
||
if (l is Libraries.NativeLib n)
|
||
{
|
||
var zipf = File.OpenRead(n.jarFilePath);
|
||
ZipFile.ExtractToDirectory(zipf, _nativesDir.ToString(), true);
|
||
if (n.extractionOptions?.exclude != null)
|
||
{
|
||
foreach (var excluded in n.extractionOptions.exclude)
|
||
{
|
||
IOPath path = Path.Concat(_nativesDir, excluded);
|
||
if(Directory.Exists(path))
|
||
Directory.Delete(path);
|
||
if(File.Exists(path))
|
||
File.Delete(path);
|
||
}
|
||
}
|
||
}
|
||
});
|
||
|
||
Приложение.Логгер.LogInfo(nameof(Сеть), $"finished downloading libraries '{_descriptor.id}'");
|
||
}
|
||
} |