mlaumcherb/Mlaumcherb.Client.Avalonia/сеть/TaskFactories/JavaDownloadTaskFactory.cs
2024-11-06 00:04:12 +05:00

123 lines
4.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Security.Cryptography;
using DTLib.Extensions;
using Mlaumcherb.Client.Avalonia.зримое;
using Mlaumcherb.Client.Avalonia.классы;
using Mlaumcherb.Client.Avalonia.холопы;
using static Mlaumcherb.Client.Avalonia.сеть.Сеть;
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 SHA1 _hasher;
private JavaDistributiveManifest? _distributiveManifest;
private List<(IOPath path, JavaDistributiveElementProps props)> _filesToDownload = new();
public JavaDownloadTaskFactory(GameVersionDescriptor descriptor)
{
_descriptor = descriptor;
_javaVersionDir = PathHelper.GetJavaRuntimeDir(_descriptor.javaVersion.component);
_hasher = SHA1.Create();
}
public async Task<NetworkTask?> CreateAsync(bool checkHashes)
{
var catalog = await DownloadStringAndDeserialize<JavaVersionCatalog>(CATALOG_URL);
var versionProps = catalog.GetVersionProps(_descriptor.javaVersion);
_distributiveManifest = await DownloadStringAndDeserialize<JavaDistributiveManifest>(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 (!File.Exists(file_path))
{
_filesToDownload.Add((file_path, pair.Value));
}
else if(checkHashes)
{
using var fs = File.OpenRead(file_path);
if (_hasher.ComputeHash(fs).HashToString() != artifact.raw.sha1)
{
_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(Сеть), "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(Сеть), $"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(Сеть), $"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(Сеть), $"adding execute rights to file '{f.path}'");
System.IO.File.SetUnixFileMode(f.path.ToString(), UnixFileMode.UserExecute);
}
});
LauncherApp.Logger.LogInfo(nameof(Сеть), "finished downloading java runtime " +
$"{_descriptor.javaVersion.majorVersion} '{_descriptor.javaVersion.component}'");
}
}