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 JavaDownloadTaskFactory : INetworkTaskFactory { private const string CATALOG_URL = "https://launchermeta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"; private GameVersionDescriptor _descriptor; private IOPath _javaVersionDir; private JavaDistributiveManifest? _distributiveManifest; private List<(IOPath path, JavaDistributiveElementProps props)> _filesToDownload = new(); public JavaDownloadTaskFactory(GameVersionDescriptor descriptor) { _descriptor = descriptor; _javaVersionDir = PathHelper.GetJavaRuntimeDir(_descriptor.javaVersion.component); } public async Task CreateAsync(bool checkHashes) { var catalog = await DownloadStringAndDeserialize(CATALOG_URL); var versionProps = catalog.GetVersionProps(_descriptor.javaVersion); _distributiveManifest = await DownloadStringAndDeserialize(versionProps.manifest.url); NetworkTask? networkTask = null; if (!CheckFiles(checkHashes)) networkTask = new( $"java runtime '{_descriptor.javaVersion.component}'", GetTotalSize(), Download ); return networkTask; } private bool CheckFiles(bool checkHashes) { _filesToDownload.Clear(); foreach (var pair in _distributiveManifest!.files) { if (pair.Value.type != "file") continue; if (pair.Value.downloads != null) { var artifact = pair.Value.downloads; IOPath file_path = Path.Concat(_javaVersionDir, pair.Key); if (!HashHelper.CheckFileSHA1(file_path, artifact.raw.sha1, checkHashes)) { _filesToDownload.Add((file_path, pair.Value)); } } } return _filesToDownload.Count == 0; } private long GetTotalSize() { long totalSize = 0; foreach (var file in _filesToDownload) { if(file.props.downloads == null) continue; totalSize += file.props.downloads.lzma?.size ?? file.props.downloads.raw.size; } return totalSize; } private async Task Download(NetworkProgressReporter pr, CancellationToken ct) { LauncherApp.Logger.LogInfo(nameof(NetworkHelper), "started downloading java runtime " + $"{_descriptor.javaVersion.majorVersion} '{_descriptor.javaVersion.component}'"); ParallelOptions opt = new() { MaxDegreeOfParallelism = LauncherApp.Config.max_parallel_downloads, CancellationToken = ct }; await Parallel.ForEachAsync(_filesToDownload, opt, async (f, _ct) => { if (f.props.downloads!.lzma != null) { LauncherApp.Logger.LogDebug(nameof(NetworkHelper), $"downloading lzma-compressed file '{f.path}'"); await using var pipe = new TransformStream(await GetStream(f.props.downloads.lzma.url, _ct)); pipe.AddTransform(pr.AddBytesCount); await using var fs = File.OpenWrite(f.path); LZMAHelper.Decompress(pipe, fs); } else { LauncherApp.Logger.LogDebug(nameof(NetworkHelper), $"downloading raw file '{f.path}'"); await DownloadFile(f.props.downloads.raw.url, f.path, _ct, pr.AddBytesCount); } if(!OperatingSystem.IsWindows() && f.props.executable is true) { LauncherApp.Logger.LogDebug(nameof(NetworkHelper), $"adding execute rights to file '{f.path}'"); System.IO.File.SetUnixFileMode(f.path.ToString(), UnixFileMode.UserExecute); } }); LauncherApp.Logger.LogInfo(nameof(NetworkHelper), "finished downloading java runtime " + $"{_descriptor.javaVersion.majorVersion} '{_descriptor.javaVersion.component}'"); } }