122 lines
4.9 KiB
C#
122 lines
4.9 KiB
C#
using System.Security.Cryptography;
|
||
using DTLib.Extensions;
|
||
using Млаумчерб.Клиент.зримое;
|
||
using Млаумчерб.Клиент.классы;
|
||
using static Млаумчерб.Клиент.сеть.Сеть;
|
||
|
||
namespace Млаумчерб.Клиент.сеть.NetworkTaskFactories;
|
||
|
||
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 = Пути.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)
|
||
{
|
||
Приложение.Логгер.LogInfo(nameof(Сеть), "started downloading java runtime " +
|
||
$"{_descriptor.javaVersion.majorVersion} '{_descriptor.javaVersion.component}'");
|
||
|
||
ParallelOptions opt = new()
|
||
{
|
||
MaxDegreeOfParallelism = Приложение.Настройки.максимум_параллельных_загрузок,
|
||
CancellationToken = ct
|
||
};
|
||
await Parallel.ForEachAsync(_filesToDownload, opt, async (f, _ct) =>
|
||
{
|
||
if (f.props.downloads!.lzma != null)
|
||
{
|
||
Приложение.Логгер.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);
|
||
LZMACompressor.Decompress(pipe, fs);
|
||
}
|
||
else
|
||
{
|
||
Приложение.Логгер.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)
|
||
{
|
||
Приложение.Логгер.LogDebug(nameof(Сеть), $"adding execute rights to file '{f.path}'");
|
||
System.IO.File.SetUnixFileMode(f.path.ToString(), UnixFileMode.UserExecute);
|
||
}
|
||
});
|
||
|
||
Приложение.Логгер.LogInfo(nameof(Сеть), "finished downloading java runtime " +
|
||
$"{_descriptor.javaVersion.majorVersion} '{_descriptor.javaVersion.component}'");
|
||
}
|
||
|
||
|
||
} |