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 _libsToDownload = new(); private IOPath _nativesDir; public LibrariesDownloadTaskFactory(GameVersionDescriptor descriptor, Libraries libraries) { _descriptor = descriptor; _libraries = libraries; _hasher = SHA1.Create(); _nativesDir = Пути.GetNativeLibrariesDir(descriptor.id); } public Task 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}'"); } }