Skip to content

Commit

Permalink
添加原版核心安装器
Browse files Browse the repository at this point in the history
  • Loading branch information
YangSpring114 committed Dec 10, 2023
1 parent 901a444 commit b4dd725
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 21 deletions.
19 changes: 18 additions & 1 deletion MinecraftLaunch.Test/Program.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,25 @@
using MinecraftLaunch.Components.Authenticator;
using MinecraftLaunch;
using MinecraftLaunch.Classes.Interfaces;
using MinecraftLaunch.Components.Authenticator;
using MinecraftLaunch.Components.Checker;
using MinecraftLaunch.Components.Installer;
using MinecraftLaunch.Components.Resolver;
using MinecraftLaunch.Extensions;
using System.Diagnostics;

string gameFolder = "C:\\Users\\w\\Desktop\\temp\\.minecraft";

var _ = (await VanlliaInstaller.EnumerableGameCoreAsync());

var installer = new VanlliaInstaller(gameFolder, "1.12.2", MirrorDownloadManager.Mcbbs);

installer.ProgressChanged += (_, x) => {
Console.Clear();
Console.SetCursorPosition(0, 0);
Console.WriteLine($"{x.Status} - {x.ProgressStatus} - {x.Progress:0.00} - {x.Speed}");
Console.SetCursorPosition(0, 0);
};

var result = await installer.InstallAsync();

Console.ReadKey();
12 changes: 11 additions & 1 deletion MinecraftLaunch.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MinecraftLaunch", "Minecraf
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Natsurainko.FluentCore", "..\..\..\Code\Natsurainko.FluentCore.New\Natsurainko.FluentCore\Natsurainko.FluentCore.csproj", "{510C557E-E4EB-4E28-BB05-969373030054}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MinecraftLaunch.Test", "MinecraftLaunch.Test\MinecraftLaunch.Test.csproj", "{76E3BD50-5A2C-43D0-A5B5-CD139EB60C94}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MinecraftLaunch.Test", "MinecraftLaunch.Test\MinecraftLaunch.Test.csproj", "{76E3BD50-5A2C-43D0-A5B5-CD139EB60C94}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GBCLV3", "..\..\..\Code\GBCLV3-master\GBCLV3\GBCLV3.csproj", "{062AA8ED-1936-4379-9199-C80E1876668A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -41,6 +43,14 @@ Global
{76E3BD50-5A2C-43D0-A5B5-CD139EB60C94}.Release|Any CPU.Build.0 = Release|Any CPU
{76E3BD50-5A2C-43D0-A5B5-CD139EB60C94}.Release|x64.ActiveCfg = Release|Any CPU
{76E3BD50-5A2C-43D0-A5B5-CD139EB60C94}.Release|x64.Build.0 = Release|Any CPU
{062AA8ED-1936-4379-9199-C80E1876668A}.Debug|Any CPU.ActiveCfg = Debug|x64
{062AA8ED-1936-4379-9199-C80E1876668A}.Debug|Any CPU.Build.0 = Debug|x64
{062AA8ED-1936-4379-9199-C80E1876668A}.Debug|x64.ActiveCfg = Debug|x64
{062AA8ED-1936-4379-9199-C80E1876668A}.Debug|x64.Build.0 = Debug|x64
{062AA8ED-1936-4379-9199-C80E1876668A}.Release|Any CPU.ActiveCfg = Release|x64
{062AA8ED-1936-4379-9199-C80E1876668A}.Release|Any CPU.Build.0 = Release|x64
{062AA8ED-1936-4379-9199-C80E1876668A}.Release|x64.ActiveCfg = Release|x64
{062AA8ED-1936-4379-9199-C80E1876668A}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
2 changes: 2 additions & 0 deletions MinecraftLaunch/Classes/Interfaces/IInstaller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ namespace MinecraftLaunch.Classes.Interfaces {
public interface IInstaller {
ValueTask<bool> InstallAsync();

void ReportProgress(double progress, string progressStatus, TaskStatus status);

event EventHandler<EventArgs> Completed;

event EventHandler<ProgressChangedEventArgs> ProgressChanged;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ public class ProgressChangedEventArgs(TaskStatus status, double progress, string
public TaskStatus Status => status;

public string ProgressStatus => progressStatus;

public string Speed { get; set; }
}
20 changes: 20 additions & 0 deletions MinecraftLaunch/Classes/Models/Install/VersionManifestEntry.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.Text.Json.Serialization;

namespace MinecraftLaunch.Classes.Models.Install {
public record VersionManifestEntry {
[JsonPropertyName("id")]
public string Id { get; set; }

[JsonPropertyName("type")]
public string Type { get; set; }

[JsonPropertyName("url")]
public string Url { get; set; }

[JsonPropertyName("time")]
public DateTime Time { get; set; }

[JsonPropertyName("releaseTime")]
public DateTime ReleaseTime { get; set; }
}
}
22 changes: 7 additions & 15 deletions MinecraftLaunch/Components/Downloader/FileDownloader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,24 @@

using Timer = System.Timers.Timer;
using DownloadProgressChangedEventArgs = MinecraftLaunch.Classes.Models.Event.DownloadProgressChangedEventArgs;
using System.Diagnostics;

namespace MinecraftLaunch.Components.Downloader {
public class FileDownloader {
private int _totalBytes;

private int _totalCount;

private int _failedCount;

private int _completedCount;

private int _downloadedBytes;

private readonly Timer _timer;

private const int BUFFER_SIZE = 4096;

private int _previousDownloadedBytes;

private const int MAX_RETRY_COUNT = 3;

private CancellationTokenSource _userCts;

private const double UPDATE_INTERVAL = 1.0;

private readonly ArrayPool<byte> _bufferPool;

private readonly AutoResetEvent _autoResetEvent;

private ImmutableList<DownloadRequest> _downloadRequests;

private readonly ExecutionDataflowBlockOptions _parallelOptions;

public event Action<bool> Completed;
Expand Down Expand Up @@ -114,6 +101,11 @@ public async ValueTask<bool> StartAsync() {
}
}

public void Refresh(IEnumerable<DownloadRequest> downloadRequests) {
_downloadRequests = downloadRequests.ToImmutableList();
Init();
}

private async Task ProcessDownloadRequests() {
var downloader = new ActionBlock<DownloadRequest>(async item => {
await DownloadItemWithRetry(item);
Expand Down Expand Up @@ -253,7 +245,7 @@ private async ValueTask<bool> DownloadAsync(DownloadRequest item) {
}
catch (Exception ex) {
// Log the error
Console.WriteLine(ex);
Debug.WriteLine(ex);
}
finally {
GC.Collect();
Expand Down
94 changes: 90 additions & 4 deletions MinecraftLaunch/Components/Installer/VanlliaInstaller.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,103 @@
using MinecraftLaunch.Classes.Interfaces;
using Flurl.Http;
using System.Text.Json;
using System.Text.Json.Nodes;
using MinecraftLaunch.Extensions;
using System.Collections.Immutable;
using MinecraftLaunch.Classes.Interfaces;
using MinecraftLaunch.Classes.Models.Event;
using MinecraftLaunch.Classes.Models.Install;
using MinecraftLaunch.Classes.Models.Download;
using MinecraftLaunch.Components.Checker;
using MinecraftLaunch.Classes.Models.Game;
using MinecraftLaunch.Components.Resolver;

namespace MinecraftLaunch.Components.Installer {
/// <summary>
/// 原版核心安装器
/// </summary>
public class VanlliaInstaller : IInstaller {
public class VanlliaInstaller(string gameFoloder, string gameId, MirrorDownloadSource source = default) : IInstaller {
private string _gameId = gameId;

private ResourceChecker _resourceChecker;

private string _gameFoloder = gameFoloder;

private MirrorDownloadSource _source = source;

private GameResolver _gameResolver = new(gameFoloder);

private static IEnumerable<VersionManifestEntry> _cache;

public event EventHandler<EventArgs> Completed;

public event EventHandler<ProgressChangedEventArgs> ProgressChanged;

public ValueTask<bool> InstallAsync() {
throw new NotImplementedException();
public async ValueTask<bool> InstallAsync() {
/*
* Check if the specified id exists
*/
ReportProgress(0.0d, "Check if the specified id exists", TaskStatus.Created);
if (_cache is null && string.IsNullOrEmpty(_gameId)) {
return false;
}

/*
* Download game core json
*/
ReportProgress(0.15d, "Start downloading the game core json", TaskStatus.WaitingToRun);
var coreInfo = _cache.SingleOrDefault(x => x.Id == _gameId);
if (coreInfo is null) {
return false;
}

var versionJsonFile = Path.Combine(_gameFoloder, "versions", _gameId,
$"{_gameId}.json").ToFileInfo();

if (!versionJsonFile.Directory.Exists) {
versionJsonFile.Directory.Create();
}

await File.WriteAllTextAsync(versionJsonFile.FullName,
await coreInfo.Url.GetStringAsync());

/*
* Download dependent resources
*/
ReportProgress(0.15d, "Start downloading dependent resources", TaskStatus.WaitingToRun);
_resourceChecker = new(_gameResolver.GetGameEntity(_gameId));
await _resourceChecker.CheckAsync();

await _resourceChecker.MissingResources.DownloadResourceEntrysAsync(source,
x => {
ReportProgress(0.15d, $"Downloading dependent resources:{x.CompletedCount}/{x.TotalCount}",
TaskStatus.Running, x.ToSpeedText());
});


ReportProgress(0.15d, "Installation is complete", TaskStatus.Canceled);
return true;
}

public void ReportProgress(double progress, string progressStatus, TaskStatus status) {
ProgressChanged?.Invoke(this, new(status, progress, progressStatus));
}

public void ReportProgress(double progress, string progressStatus, TaskStatus status, string speed) {
ProgressChanged?.Invoke(this, new(status, progress, progressStatus) {
Speed = speed
});
}

public static async ValueTask<IEnumerable<VersionManifestEntry>> EnumerableGameCoreAsync(MirrorDownloadSource source = default) {
string url = string.Empty;
if (MirrorDownloadManager.IsUseMirrorDownloadSource && source is not null) {
url = source.VersionManifestUrl;
} else {
url = "http://launchermeta.mojang.com/mc/game/version_manifest.json";
}

var node = JsonNode.Parse(await url.GetStringAsync());
return _cache = node.GetEnumerable("versions").Deserialize<IEnumerable<VersionManifestEntry>>();
}
}
}
8 changes: 8 additions & 0 deletions MinecraftLaunch/Extensions/JsonExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ public static string GetString(this JsonNode node, string name) {
return node[name].GetValue<string>();
}

public static JsonArray GetEnumerable(this JsonNode node) {
return node.AsArray();
}

public static JsonArray GetEnumerable(this JsonNode node, string name) {
return node[name].AsArray();
}

public static IEnumerable<T> GetEnumerable<T>(this JsonNode node) {
return node.AsArray()
.Select(x => x.GetValue<T>());
Expand Down
File renamed without changes.

0 comments on commit b4dd725

Please sign in to comment.