diff --git a/MinecraftLaunch.Test/Program.cs b/MinecraftLaunch.Test/Program.cs index 45b5069..e962ee5 100644 --- a/MinecraftLaunch.Test/Program.cs +++ b/MinecraftLaunch.Test/Program.cs @@ -1,8 +1,30 @@ -using MinecraftLaunch.Components.Resolver; +using MinecraftLaunch; +using MinecraftLaunch.Components.Resolver; +using MinecraftLaunch.Components.Installer; GameResolver gameResolver = new("C:\\Users\\w\\Downloads\\.minecraft"); -var result = gameResolver.GetGameEntitys(); -foreach (var item in result) { - Console.WriteLine(item.Id); -} \ No newline at end of file +VanlliaInstaller vanlliaInstaller = new(gameResolver, "1.12.2"); +vanlliaInstaller.ProgressChanged += (_, args) => { + Console.WriteLine($"{args.Progress * 100:0.00} - {args.Status} - {args.ProgressStatus}"); +}; + +await vanlliaInstaller.InstallAsync(); + +Console.WriteLine(); +Console.WriteLine(); +Console.WriteLine(); +Console.WriteLine(); +Console.WriteLine(); + +ForgeInstaller forgeInstaller = new(gameResolver.GetGameEntity("1.12.2"), + (await ForgeInstaller.EnumerableFromVersionAsync("1.12.2")).First(), + "C:\\Program Files\\Java\\jdk1.8.0_301\\bin\\javaw.exe", + "1.12.2-forge-114514"); + +forgeInstaller.ProgressChanged += (_, args) => { + Console.WriteLine($"{args.Progress * 100:0.00} - {args.Status} - {args.ProgressStatus}"); +}; + +await forgeInstaller.InstallAsync(); +Console.ReadKey(); \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Download/DownloadRequest.cs b/MinecraftLaunch/Classes/Models/Download/DownloadRequest.cs index 10b8e1a..bc8c4df 100644 --- a/MinecraftLaunch/Classes/Models/Download/DownloadRequest.cs +++ b/MinecraftLaunch/Classes/Models/Download/DownloadRequest.cs @@ -22,7 +22,7 @@ public sealed record DownloadRequest { /// /// 下载链接 /// - public string Url { get; init; } + public string Url { get; set; } /// /// 保存文件信息 diff --git a/MinecraftLaunch/Components/Installer/ForgeInstaller.cs b/MinecraftLaunch/Components/Installer/ForgeInstaller.cs index f7abeec..2e6e4d1 100644 --- a/MinecraftLaunch/Components/Installer/ForgeInstaller.cs +++ b/MinecraftLaunch/Components/Installer/ForgeInstaller.cs @@ -23,10 +23,12 @@ public override async ValueTask InstallAsync() { /* * Download Forge installation package */ - var suffix = $"/forge/download/{_installEntry.Build}"; + var suffix = $"/net/minecraftforge/forge/{_installEntry.McVersion}-{_installEntry.ForgeVersion}/forge-{_installEntry + .McVersion}-{_installEntry.ForgeVersion}-installer.jar"; + var host = MirrorDownloadManager.IsUseMirrorDownloadSource - ? MirrorDownloadManager.Bmcl.Host - : _mirrorDownloadSource.Host; + ? _mirrorDownloadSource.Host + : "https://files.minecraftforge.net/maven"; var packageUrl = $"{host}{suffix}"; string packagePath = Path.Combine(Path.GetTempPath(), @@ -34,7 +36,7 @@ public override async ValueTask InstallAsync() { var request = packageUrl.ToDownloadRequest(packagePath.ToFileInfo()); await request.DownloadAsync(x => { - ReportProgress(x.ToPercentage().ToPercentage(0.0d, 0.15d), + ReportProgress(x.ToPercentage(0.0d, 0.15d), "Downloading Forge installation package", TaskStatus.Running); }); @@ -60,8 +62,10 @@ await request.DownloadAsync(x => { .GetEnumerable("libraries"), _inheritedFrom.GameFolderPath).ToList(); - foreach (var lib in libraries) { - lib.Url = $"https://download.mcbbs.net/maven/{lib.RelativePath.Replace("\\", "/")}"; + if (MirrorDownloadManager.IsUseMirrorDownloadSource) { + foreach (var lib in libraries) { + lib.Url = $"https://bmclapi2.bangbang93.com/maven/{lib.RelativePath.Replace("\\", "/")}"; + } } if (!isLegacyForgeVersion) { diff --git a/MinecraftLaunch/Components/Installer/VanlliaInstaller.cs b/MinecraftLaunch/Components/Installer/VanlliaInstaller.cs index 9fc0c21..ffac1ec 100644 --- a/MinecraftLaunch/Components/Installer/VanlliaInstaller.cs +++ b/MinecraftLaunch/Components/Installer/VanlliaInstaller.cs @@ -42,7 +42,7 @@ public override async ValueTask InstallAsync() { versionJsonFile.Directory.Create(); } - await File.WriteAllTextAsync(versionJsonFile.FullName, + await File.WriteAllTextAsync(versionJsonFile.FullName, await coreInfo.Url.GetStringAsync()); /* @@ -50,15 +50,14 @@ await File.WriteAllTextAsync(versionJsonFile.FullName, */ ReportProgress(0.45d, "Start downloading dependent resources", TaskStatus.WaitingToRun); ResourceChecker resourceChecker = new(_gameResolver.GetGameEntity(_gameId)); - await resourceChecker.CheckAsync(); - - await resourceChecker.MissingResources.DownloadResourceEntrysAsync(_source, - x => { + var hasMissResource = await resourceChecker.CheckAsync(); + if (!hasMissResource) { + await resourceChecker.MissingResources.DownloadResourceEntrysAsync(_source, x => { ReportProgress(x.ToPercentage().ToPercentage(0.45d, 0.95d), $"Downloading dependent resources:{x.CompletedCount}/{x.TotalCount}", TaskStatus.Running); }); - + } ReportProgress(1.0d, "Installation is complete", TaskStatus.Canceled); ReportCompleted(); diff --git a/MinecraftLaunch/Extensions/DownloadExtension.cs b/MinecraftLaunch/Extensions/DownloadExtension.cs index 9267ae9..1db7809 100644 --- a/MinecraftLaunch/Extensions/DownloadExtension.cs +++ b/MinecraftLaunch/Extensions/DownloadExtension.cs @@ -32,30 +32,16 @@ public static IDownloadEntry OfMirrorSource(this IDownloadEntry entry, return entry; } - public static ValueTask DownloadAsync(this DownloadRequest request, - Action action = default!) { - //DefaultDownloader.Setup(Enumerable.Repeat(request, 1)); - - //DefaultDownloader.ProgressChanged += (sender, args) => { - // action(args); - //}; - - //return DefaultDownloader.DownloadAsync(); - throw new NotImplementedException(); + public static ValueTask DownloadAsync( + this DownloadRequest request, + Action action = default!) { + return DownloadUitl.DownloadAsync(request, default, action); } public static ValueTask DownloadResourceEntryAsync(this IDownloadEntry downloadEntry, MirrorDownloadSource source = default!) { return DownloadUitl.DownloadAsync(downloadEntry, DownloadUitl.DefaultDownloadRequest,default,x=>{}); - - //DefaultDownloader.Setup(Enumerable.Repeat(downloadEntry - // .OfMirrorSource(source) - // .ToDownloadRequest(), 1)); - - //Console.WriteLine(downloadEntry.Path); - //return DefaultDownloader.DownloadAsync(); - //throw new NotImplementedException(); } public static ValueTask DownloadResourceEntrysAsync(this diff --git a/MinecraftLaunch/MinecraftLaunch.csproj b/MinecraftLaunch/MinecraftLaunch.csproj index 61c6cd7..2182e49 100644 --- a/MinecraftLaunch/MinecraftLaunch.csproj +++ b/MinecraftLaunch/MinecraftLaunch.csproj @@ -1,6 +1,6 @@  - 3.0.04 + 3.0.05 diff --git a/MinecraftLaunch/Utilities/DownloadUitl.cs b/MinecraftLaunch/Utilities/DownloadUitl.cs index 22212c7..bdc34e3 100644 --- a/MinecraftLaunch/Utilities/DownloadUitl.cs +++ b/MinecraftLaunch/Utilities/DownloadUitl.cs @@ -21,6 +21,60 @@ public static class DownloadUitl { MultiPartsCount = 8 }; + public static async ValueTask DownloadAsync( + DownloadRequest downloadRequest, + CancellationTokenSource tokenSource = default, + Action perSecondProgressChangedAction = default) { + Timer timer = default; + downloadRequest ??= DefaultDownloadRequest; + tokenSource ??= new CancellationTokenSource(); + perSecondProgressChangedAction ??= x => { }; + var responseMessage = (await downloadRequest.Url.GetAsync(cancellationToken: tokenSource.Token)) + .ResponseMessage; + + if (responseMessage.StatusCode.Equals(HttpStatusCode.Found)) { + downloadRequest.Url = responseMessage.Headers.Location.AbsoluteUri; + return await DownloadAsync(downloadRequest, tokenSource); + } + + if (perSecondProgressChangedAction != null) { + timer = new Timer(1000); + } + + responseMessage.EnsureSuccessStatusCode(); + var contentLength = responseMessage.Content.Headers.ContentLength ?? 0; + + //use multipart download method + if (downloadRequest.IsPartialContentSupported && contentLength > downloadRequest.FileSizeThreshold) { + var requestMessage = new HttpRequestMessage(HttpMethod.Get, responseMessage.RequestMessage.RequestUri.AbsoluteUri); + requestMessage.Headers.Range = new RangeHeaderValue(0, 1); + + return await MultiPartDownloadAsync(responseMessage, downloadRequest, downloadRequest.FileInfo.FullName, tokenSource) + .AsTask() + .ContinueWith(task => { + return !task.IsFaulted; + }); + } + + return await WriteFileFromHttpResponseAsync(downloadRequest.FileInfo.FullName, responseMessage, tokenSource, (timer, perSecondProgressChangedAction, contentLength)) + .AsTask() + .ContinueWith(task => { + if (timer != null) { + try { + perSecondProgressChangedAction(responseMessage.Content.Headers.ContentLength != null ? + task.Result / (double)responseMessage.Content.Headers.ContentLength : 0); + } catch (Exception) { + + } + + timer.Stop(); + timer.Dispose(); + } + + return !task.IsFaulted; + }); + } + public static async ValueTask DownloadAsync( IDownloadEntry downloadEntry, DownloadRequest downloadRequest = default,