97 lines
3.4 KiB
C#
97 lines
3.4 KiB
C#
using System.Buffers;
|
||
using System.Net.Http;
|
||
using Млаумчерб.Клиент.видимое;
|
||
using Млаумчерб.Клиент.классы;
|
||
|
||
namespace Млаумчерб.Клиент.сеть;
|
||
|
||
public static class Сеть
|
||
{
|
||
public static int ParallelDownloadsN = 32;
|
||
public static HttpClient http = new();
|
||
|
||
public static async Task DownloadFileHTTP(string url, IOPath outPath, CancellationToken ct = default,
|
||
Action<ArraySegment<byte>>? transformFunc = null)
|
||
{
|
||
await using var src = await http.GetStreamAsync(url, ct);
|
||
await using var dst = File.OpenWrite(outPath);
|
||
|
||
await src.CopyTransformAsync(dst, transformFunc, ct).ConfigureAwait(false);
|
||
}
|
||
|
||
public static async Task CopyTransformAsync(this Stream src, Stream dst,
|
||
Action<ArraySegment<byte>>? transformFunc = null, CancellationToken ct = default)
|
||
{
|
||
// default dotnet runtime buffer size
|
||
int bufferSize = 81920;
|
||
byte[] readBuffer = ArrayPool<byte>.Shared.Rent(bufferSize);
|
||
byte[] writeBuffer = ArrayPool<byte>.Shared.Rent(bufferSize);
|
||
try
|
||
{
|
||
var readTask = src.ReadAsync(readBuffer, 0, bufferSize, ct).ConfigureAwait(false);
|
||
while (true)
|
||
{
|
||
int readCount = await readTask;
|
||
if (readCount == 0)
|
||
break;
|
||
(readBuffer, writeBuffer) = (writeBuffer, readBuffer);
|
||
readTask = src.ReadAsync(readBuffer, 0, bufferSize, ct).ConfigureAwait(false);
|
||
transformFunc?.Invoke(new ArraySegment<byte>(writeBuffer, 0, readCount));
|
||
dst.Write(writeBuffer, 0, readCount);
|
||
}
|
||
}
|
||
catch (OperationCanceledException)
|
||
{
|
||
}
|
||
finally
|
||
{
|
||
ArrayPool<byte>.Shared.Return(readBuffer);
|
||
ArrayPool<byte>.Shared.Return(writeBuffer);
|
||
}
|
||
}
|
||
|
||
private static readonly string[] VERSION_MANIFEST_URLS =
|
||
{
|
||
"https://piston-meta.mojang.com/mc/game/version_manifest_v2.json"
|
||
};
|
||
|
||
private static async Task<List<RemoteVersionDescriptorProps>> GetRemoteVersionDescriptorsAsync()
|
||
{
|
||
List<RemoteVersionDescriptorProps> descriptors = new();
|
||
foreach (var url in VERSION_MANIFEST_URLS)
|
||
{
|
||
try
|
||
{
|
||
var manifestText = await http.GetStringAsync(url);
|
||
var catalog = JsonConvert.DeserializeObject<GameVersionCatalog>(manifestText);
|
||
if (catalog != null)
|
||
descriptors.AddRange(catalog.versions);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Приложение.Логгер.LogWarn(nameof(Сеть), ex);
|
||
}
|
||
}
|
||
|
||
return descriptors;
|
||
}
|
||
|
||
private static List<GameVersionProps>? _versionPropsList;
|
||
|
||
/// <returns>empty list if couldn't find any remote versions</returns>
|
||
public static async Task<IReadOnlyList<GameVersionProps>> GetDownloadableVersions()
|
||
{
|
||
if (_versionPropsList == null)
|
||
{
|
||
_versionPropsList = new();
|
||
var rvdlist = await GetRemoteVersionDescriptorsAsync();
|
||
foreach (var r in rvdlist)
|
||
{
|
||
if (r.type == "release")
|
||
_versionPropsList.Add(new GameVersionProps(r.id, r.url));
|
||
}
|
||
}
|
||
|
||
return _versionPropsList;
|
||
}
|
||
} |