using System.IO.Compression; using Mlaumcherb.Client.Avalonia.зримое; using Mlaumcherb.Client.Avalonia.классы; using Mlaumcherb.Client.Avalonia.холопы; using static Mlaumcherb.Client.Avalonia.сеть.NetworkHelper; namespace Mlaumcherb.Client.Avalonia.сеть.TaskFactories; public class LibrariesDownloadTaskFactory : INetworkTaskFactory { private GameVersionDescriptor _descriptor; private Libraries _libraries; private List _libsToDownload = new(); private IOPath _nativesDir; public LibrariesDownloadTaskFactory(GameVersionDescriptor descriptor, Libraries libraries) { _descriptor = descriptor; _libraries = libraries; _nativesDir = PathHelper.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 (!HashHelper.CheckFileSHA1(l.jarFilePath, l.artifact.sha1, checkHashes)) { _libsToDownload.Add(l); } //TODO: replace with actual native libraries check else if (!nativeDirExists && l is Libraries.NativeLib) { _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) { LauncherApp.Logger.LogInfo(nameof(NetworkHelper), $"started downloading libraries '{_descriptor.id}'"); ParallelOptions opt = new() { MaxDegreeOfParallelism = LauncherApp.Config.max_parallel_downloads, CancellationToken = ct }; await Parallel.ForEachAsync(_libsToDownload, opt, async (l, _ct) => { LauncherApp.Logger.LogDebug(nameof(NetworkHelper), $"downloading library '{l.name}' to '{l.jarFilePath}'"); if(string.IsNullOrEmpty(l.artifact.url)) throw new Exception($"library '{l.name}' doesn't have a url to download"); await DownloadFile(l.artifact.url, l.jarFilePath, _ct, pr.AddBytesCount); if (l is Libraries.NativeLib n) { await using var zipf = File.OpenRead(n.jarFilePath); using var archive = new ZipArchive(zipf); foreach (var entry in archive.Entries) { if (n.extractionOptions?.exclude?.Contains(entry.FullName) is true or null) continue; var real_path = Path.Concat(_nativesDir, entry.FullName); Directory.Create(real_path.ParentDir()); entry.ExtractToFile(real_path.ToString(), true); } } }); LauncherApp.Logger.LogInfo(nameof(NetworkHelper), $"finished downloading libraries '{_descriptor.id}'"); } }