From 6e510569d2e8be5498c8270422d49e242b82e523 Mon Sep 17 00:00:00 2001 From: YangSpring <99802662+YangSpring114@users.noreply.github.com> Date: Thu, 29 Aug 2024 02:33:14 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=AE=89=E8=A3=85=E5=99=A8?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E4=BB=A3=E7=A0=81=EF=BC=8C=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E4=BA=86=E5=A4=8D=E5=90=88=E5=AE=89=E8=A3=85=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MinecraftLaunch.BanchTest.csproj | 1 - MinecraftLaunch.BanchTest/Program.cs | 85 ++++++- .../MinecraftLaunch.Simple.csproj | 1 - MinecraftLaunch.Test/Program.cs | 236 +++++++++++------- .../Installer/CompositionInstaller.cs | 78 ++++++ .../Components/Installer/FabricInstaller.cs | 9 +- .../Components/Installer/ForgeInstaller.cs | 34 +-- .../Components/Installer/InstallerBase.cs | 9 +- .../Components/Installer/NeoForgeInstaller.cs | 4 + .../Components/Installer/OptifineInstaller.cs | 32 +-- .../Components/Installer/QuiltInstaller.cs | 7 +- .../Components/Installer/VanlliaInstaller.cs | 3 + MinecraftLaunch/Utilities/DownloadUitl.cs | 2 +- 13 files changed, 362 insertions(+), 139 deletions(-) create mode 100644 MinecraftLaunch/Components/Installer/CompositionInstaller.cs diff --git a/MinecraftLaunch.BanchTest/MinecraftLaunch.BanchTest.csproj b/MinecraftLaunch.BanchTest/MinecraftLaunch.BanchTest.csproj index 3f035a6..9adfd8e 100644 --- a/MinecraftLaunch.BanchTest/MinecraftLaunch.BanchTest.csproj +++ b/MinecraftLaunch.BanchTest/MinecraftLaunch.BanchTest.csproj @@ -3,7 +3,6 @@ enable Exe - true enable net8.0 true diff --git a/MinecraftLaunch.BanchTest/Program.cs b/MinecraftLaunch.BanchTest/Program.cs index 31df623..9d5fa52 100644 --- a/MinecraftLaunch.BanchTest/Program.cs +++ b/MinecraftLaunch.BanchTest/Program.cs @@ -2,25 +2,92 @@ using BenchmarkDotNet.Attributes; using MinecraftLaunch.Components.Checker; using MinecraftLaunch.Components.Resolver; +using MinecraftLaunch.Extensions; +using MinecraftLaunch.Classes.Interfaces; +using System.Threading.Tasks.Dataflow; +using MinecraftLaunch.Utilities; +using System.Diagnostics; -var summary = BenchmarkRunner.Run(); +//var summary = BenchmarkRunner.Run(); + +await new BenchmarkClass().RunTaskParallel(); +Console.ReadKey(); [MemoryDiagnoser] public class BenchmarkClass { private readonly ResourceChecker _checker; - private readonly GameResolver _gameResolver = new("D:\\GamePackages\\.minecraft"); + private readonly GameResolver _gameResolver = new("C:\\Users\\w\\Desktop\\temp\\.minecraft"); public BenchmarkClass() { - _checker = new(_gameResolver.GetGameEntity("Life in the village")); + _checker = new(_gameResolver.GetGameEntity("1.16.5")); + _ = _checker.CheckAsync(); } - //[Benchmark] - //public Task RunTask() { - // return _checker.CheckAsync1(); - //} + [Benchmark] + public ValueTask RunTaskParallel() { + return _checker.MissingResources.DownloadResourceParallel(); + } [Benchmark] - public ValueTask RunValueTask() { - return _checker.CheckAsync(); + public ValueTask RunParallel() { + return _checker.MissingResources.DownloadResourceEntrysAsync(); + } +} + +public static class Downloader { + public static async ValueTask DownloadResourceParallel(this IEnumerable entries) { + int completedCount = 0; + int totalCount = entries.Count(); + + TransformBlock transformBlock = new(x => { + return x; + }, new ExecutionDataflowBlockOptions { + BoundedCapacity = DownloadUitl.DefaultDownloadRequest.MultiThreadsCount, + MaxDegreeOfParallelism = DownloadUitl.DefaultDownloadRequest.MultiThreadsCount, + }); + + ActionBlock actionBlock = new(async x => { + await Task.Run(async () => { + if (string.IsNullOrEmpty(x.Url)) { + return; + } + + await DownloadUitl.DownloadAsync(x).AsTask().ContinueWith(task => { + if (task.IsFaulted) { + if (!x.Verify()) { + Debug.WriteLine(task.Exception.Message); + return; + } + + return; + } + + var downloadResult = task.Result; + }); + + Interlocked.Increment(ref completedCount); + }); + }, new ExecutionDataflowBlockOptions { + BoundedCapacity = DownloadUitl.DefaultDownloadRequest.MultiThreadsCount, + MaxDegreeOfParallelism = DownloadUitl.DefaultDownloadRequest.MultiThreadsCount, + }); + + var transformManyBlock = new TransformManyBlock, IDownloadEntry>(chunk => chunk, + new ExecutionDataflowBlockOptions()); + + var linkOptions = new DataflowLinkOptions { + PropagateCompletion = true + }; + + transformManyBlock.LinkTo(transformBlock, linkOptions); + transformBlock.LinkTo(actionBlock, linkOptions); + + if (entries != null) { + transformManyBlock.Post(entries); + } + + transformManyBlock.Complete(); + await actionBlock.Completion.WaitAsync(new CancellationToken()); + return true; } } \ No newline at end of file diff --git a/MinecraftLaunch.Test/MinecraftLaunch.Simple.csproj b/MinecraftLaunch.Test/MinecraftLaunch.Simple.csproj index d251f97..c1a7f5c 100644 --- a/MinecraftLaunch.Test/MinecraftLaunch.Simple.csproj +++ b/MinecraftLaunch.Test/MinecraftLaunch.Simple.csproj @@ -8,7 +8,6 @@ - diff --git a/MinecraftLaunch.Test/Program.cs b/MinecraftLaunch.Test/Program.cs index 1d1845f..9f10490 100644 --- a/MinecraftLaunch.Test/Program.cs +++ b/MinecraftLaunch.Test/Program.cs @@ -1,133 +1,199 @@ using MinecraftLaunch; +using MinecraftLaunch.Extensions; +using MinecraftLaunch.Classes.Models.Auth; +using MinecraftLaunch.Classes.Models.Launch; using MinecraftLaunch.Components.Resolver; using MinecraftLaunch.Components.Analyzer; +using MinecraftLaunch.Components.Launcher; using MinecraftLaunch.Components.Installer; using MinecraftLaunch.Components.Authenticator; -using MinecraftLaunch.Extensions; -using MinecraftLaunch.Classes.Models.Auth; -MirrorDownloadManager.IsUseMirrorDownloadSource = true; +MirrorDownloadManager.IsUseMirrorDownloadSource = false; + +try { + #region ServerPing + + //ServerPingWatcher serverPingWatcher = new(25565, "mc.163mc.cn", 47); + + //serverPingWatcher.ServerConnectionProgressChanged += OnServerConnectionProgressChanged; + + //serverPingWatcher.ServerLatencyChanged += (_, args) => { + // Console.WriteLine($"{args.Latency}ms"); + //}; + + //await serverPingWatcher.StartAsync(); + + //void OnServerConnectionProgressChanged(object? sender, ProgressChangedEventArgs args) { + // Console.WriteLine($"{args.Progress * 100:0.00} - {args.Status} - {args.ProgressStatus}"); + // if (args.Status == TaskStatus.Canceled) { + // serverPingWatcher.ServerConnectionProgressChanged -= OnServerConnectionProgressChanged; + // } + //} + + #endregion + + #region Forge Install + + //GameResolver gameResolver = new("C:\\Users\\w\\Downloads\\.minecraft"); + + //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(); + + //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(); + + #endregion + + #region Fabric Install + + //GameResolver gameResolver = new("C:\\Users\\w\\Downloads\\.minecraft"); + //VanlliaInstaller vanlliaInstaller = new(gameResolver, "1.16.5"); + //vanlliaInstaller.ProgressChanged += (_, args) => { + // Console.WriteLine($"{args.Progress * 100:0.00}% - {args.Status} - {args.ProgressStatus}"); + //}; + + //await vanlliaInstaller.InstallAsync(); -#region ServerPing + //FabricInstaller fabricInstaller = new(gameResolver.GetGameEntity("1.16.5"), + // (await FabricInstaller.EnumerableFromVersionAsync("1.16.5")).First(), + // "1.16.5-fabric-114514"); -//ServerPingWatcher serverPingWatcher = new(25565, "mc.163mc.cn", 47); + //fabricInstaller.ProgressChanged += (_, args) => { + // Console.WriteLine($"{args.Progress * 100:0.00}% - {args.Status} - {args.ProgressStatus}"); + //}; -//serverPingWatcher.ServerConnectionProgressChanged += OnServerConnectionProgressChanged; + //await fabricInstaller.InstallAsync(); -//serverPingWatcher.ServerLatencyChanged += (_, args) => { -// Console.WriteLine($"{args.Latency}ms"); -//}; + //foreach (var item in gameResolver.GetGameEntitys()){ + // Console.WriteLine(item.Id); + //}; -//await serverPingWatcher.StartAsync(); + #endregion -//void OnServerConnectionProgressChanged(object? sender, ProgressChangedEventArgs args) { -// Console.WriteLine($"{args.Progress * 100:0.00} - {args.Status} - {args.ProgressStatus}"); -// if (args.Status == TaskStatus.Canceled) { -// serverPingWatcher.ServerConnectionProgressChanged -= OnServerConnectionProgressChanged; -// } -//} + #region Optifine Install -#endregion + //GameResolver gameResolver = new("C:\\Users\\w\\Downloads\\.minecraft"); -#region Forge Install + //VanlliaInstaller vanlliaInstaller = new(gameResolver, "1.12.2", MirrorDownloadManager.Bmcl); + //vanlliaInstaller.ProgressChanged += (_, args) => { + // Console.WriteLine($"{args.Progress * 100:0.00} - {args.Status} - {args.ProgressStatus}"); + //}; -//GameResolver gameResolver = new("C:\\Users\\w\\Downloads\\.minecraft"); + //await vanlliaInstaller.InstallAsync(); -//VanlliaInstaller vanlliaInstaller = new(gameResolver, "1.12.2"); -//vanlliaInstaller.ProgressChanged += (_, args) => { -// Console.WriteLine($"{args.Progress * 100:0.00} - {args.Status} - {args.ProgressStatus}"); -//}; + //Console.WriteLine(); -//await vanlliaInstaller.InstallAsync(); + //OptifineInstaller optifineInstaller = new(gameResolver.GetGameEntity("1.12.2"), + // (await OptifineInstaller.EnumerableFromVersionAsync("1.12.2")).First(), + // "C:\\Program Files\\Java\\jdk1.8.0_301\\bin\\javaw.exe", + // "1.12.2-optifine-114514"); -//Console.WriteLine(); + //optifineInstaller.ProgressChanged += (_, args) => { + // Console.WriteLine($"{args.Progress * 100:0.00} - {args.Status} - {args.ProgressStatus}"); + //}; -//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"); + //await optifineInstaller.InstallAsync(); -//forgeInstaller.ProgressChanged += (_, args) => { -// Console.WriteLine($"{args.Progress * 100:0.00} - {args.Status} - {args.ProgressStatus}"); -//}; + #endregion -//await forgeInstaller.InstallAsync(); + #region Composition Install -#endregion + GameResolver gameResolver = new("C:\\Users\\wxysd\\Desktop\\temp\\.minecraft"); -#region Fabric Install + VanlliaInstaller vanlliaInstaller = new(gameResolver, "1.18.2", MirrorDownloadManager.Bmcl); + vanlliaInstaller.ProgressChanged += (_, args) => { + Console.WriteLine($"{args.Progress * 100:0.00} - {args.Status} - {args.ProgressStatus}"); + }; -//GameResolver gameResolver = new("C:\\Users\\w\\Downloads\\.minecraft"); -//VanlliaInstaller vanlliaInstaller = new(gameResolver, "1.16.5"); -//vanlliaInstaller.ProgressChanged += (_, args) => { -// Console.WriteLine($"{args.Progress * 100:0.00}% - {args.Status} - {args.ProgressStatus}"); -//}; + await vanlliaInstaller.InstallAsync(); -//await vanlliaInstaller.InstallAsync(); + Console.WriteLine(); -//FabricInstaller fabricInstaller = new(gameResolver.GetGameEntity("1.16.5"), -// (await FabricInstaller.EnumerableFromVersionAsync("1.16.5")).First(), -// "1.16.5-fabric-114514"); + ForgeInstaller forgeInstaller = new(gameResolver.GetGameEntity("1.18.2"), + (await ForgeInstaller.EnumerableFromVersionAsync("1.18.2")).First(), + "C:\\Users\\wxysd\\AppData\\Roaming\\.minecraft\\runtime\\java-runtime-gamma\\bin\\javaw.exe", + "1.18.2-Composition-114514", + MirrorDownloadManager.Bmcl); -//fabricInstaller.ProgressChanged += (_, args) => { -// Console.WriteLine($"{args.Progress * 100:0.00}% - {args.Status} - {args.ProgressStatus}"); -//}; + CompositionInstaller compositionInstaller = new(forgeInstaller, + "1.18.2-Composition-114514", + (await OptifineInstaller.EnumerableFromVersionAsync("1.18.2")).First()); -//await fabricInstaller.InstallAsync(); + compositionInstaller.ProgressChanged += (_, args) => { + Console.WriteLine($"{args.Progress * 100:0.00} - {args.Status} - {args.ProgressStatus}"); + }; -//foreach (var item in gameResolver.GetGameEntitys()){ -// Console.WriteLine(item.Id); -//}; + await compositionInstaller.InstallAsync(); -#endregion + #endregion -#region Optifine Install + #region MicrosoftAuthenticator -//GameResolver gameResolver = new("C:\\Users\\w\\Downloads\\.minecraft"); + //MicrosoftAuthenticator microsoftAuthenticator = new("Your Client ID"); + //await microsoftAuthenticator.DeviceFlowAuthAsync(x => { + // Console.WriteLine(x.UserCode); + // Console.WriteLine(x.VerificationUrl); + //}); -//VanlliaInstaller vanlliaInstaller = new(gameResolver, "1.12.2", MirrorDownloadManager.Bmcl); -//vanlliaInstaller.ProgressChanged += (_, args) => { -// Console.WriteLine($"{args.Progress * 100:0.00} - {args.Status} - {args.ProgressStatus}"); -//}; + //var account = await microsoftAuthenticator.AuthenticateAsync(); -//await vanlliaInstaller.InstallAsync(); + #endregion -//Console.WriteLine(); + #region Launch -//OptifineInstaller optifineInstaller = new(gameResolver.GetGameEntity("1.12.2"), -// (await OptifineInstaller.EnumerableFromVersionAsync("1.12.2")).First(), -// "C:\\Program Files\\Java\\jdk1.8.0_301\\bin\\javaw.exe", -// "1.12.2-optifine-114514"); + var account = new OfflineAuthenticator("Yang114").Authenticate(); + var resolver = new GameResolver("C:\\Users\\wxysd\\Desktop\\temp\\.minecraft"); -//optifineInstaller.ProgressChanged += (_, args) => { -// Console.WriteLine($"{args.Progress * 100:0.00} - {args.Status} - {args.ProgressStatus}"); -//}; + var config = new LaunchConfig { + Account = account, + IsEnableIndependencyCore = true, + JvmConfig = new(@"C:\Users\wxysd\AppData\Roaming\.minecraft\runtime\java-runtime-gamma\bin\\javaw.exe") { + MaxMemory = 1024, + } + }; -//await optifineInstaller.InstallAsync(); + Launcher launcher = new(resolver, config); + var gameProcessWatcher = await launcher.LaunchAsync("1.18.2-Composition-114514"); -#endregion + //获取输出日志 + gameProcessWatcher.OutputLogReceived += (sender, args) => { + Console.WriteLine(args.Original); + }; -#region MicrosoftAuthenticator + //检测游戏退出 + gameProcessWatcher.Exited += (sender, args) => { + Console.WriteLine("exit"); + }; -//MicrosoftAuthenticator microsoftAuthenticator = new("Your Client ID"); -//await microsoftAuthenticator.DeviceFlowAuthAsync(x => { -// Console.WriteLine(x.UserCode); -// Console.WriteLine(x.VerificationUrl); -//}); + #endregion -//var account = await microsoftAuthenticator.AuthenticateAsync(); + #region Crash Analysis -#endregion + //GameResolver gameResolver = new("C:\\Users\\w\\Desktop\\总整包\\MC\\mc启动器\\BakaXL\\.minecraft"); -#region Crash Analysis -//GameResolver gameResolver = new("C:\\Users\\w\\Desktop\\总整包\\MC\\mc启动器\\BakaXL\\.minecraft"); + var crashAnalyzer = new GameCrashAnalyzer(gameResolver.GetGameEntity("1.18.2-Composition-114514"), true); + var reports = crashAnalyzer.AnalysisLogs(); -//var crashAnalyzer = new GameCrashAnalyzer(gameResolver.GetGameEntity("1.20.1"), true); -//var reports = crashAnalyzer.AnalysisLogs(); + foreach (var report in reports) { + Console.WriteLine(report); + } -//foreach (var report in reports) { -// Console.WriteLine(report); -//} -#endregion + #endregion +} catch (Exception) { +} Console.ReadKey(); \ No newline at end of file diff --git a/MinecraftLaunch/Components/Installer/CompositionInstaller.cs b/MinecraftLaunch/Components/Installer/CompositionInstaller.cs new file mode 100644 index 0000000..ff8329b --- /dev/null +++ b/MinecraftLaunch/Components/Installer/CompositionInstaller.cs @@ -0,0 +1,78 @@ + +using MinecraftLaunch.Classes.Models.Event; +using MinecraftLaunch.Classes.Models.Game; +using MinecraftLaunch.Classes.Models.Install; +using MinecraftLaunch.Extensions; + +namespace MinecraftLaunch.Components.Installer; + +/// +/// 复合安装器 +/// +public sealed class CompositionInstaller : InstallerBase { + private readonly string _customId; + private readonly InstallerBase _installerBase; + private readonly OptiFineInstallEntity _entity; + + /// + /// 自定义下载进度计算表达式 + /// + public override Func CalculateExpression { get; set; } = x => x.ToPercentage(0.0d, 0.8d); + + public override GameEntry InheritedFrom { get; } + + public CompositionInstaller(InstallerBase installerBase, string customId, OptiFineInstallEntity entity = default) { + if (installerBase is NeoForgeInstaller or QuiltInstaller) { + throw new ArgumentException("选择的安装器类型不支持复合安装"); + } + + _entity = entity; + _customId = customId; + _installerBase = installerBase; + + InheritedFrom = _installerBase.InheritedFrom; + } + + public override async ValueTask InstallAsync() { + _installerBase.ProgressChanged += OnProgressChanged; + await _installerBase.InstallAsync(); + + if (_entity is null) { + CalculateExpression = null; + ReportProgress(1.0d, "Installation is complete", TaskStatus.RanToCompletion); + ReportCompleted(); + return true; + } + + ReportProgress(0.8d, "Start installing the sub loader", TaskStatus.WaitingToRun); + + string downloadUrl = $"https://bmclapi2.bangbang93.com/optifine/{_entity.McVersion}/{_entity.Type}/{_entity.Patch}"; + string packagePath = Path.Combine(Path.Combine(InheritedFrom.GameFolderPath, "versions", _customId, "mods"), _entity.FileName); + var request = downloadUrl.ToDownloadRequest(packagePath.ToFileInfo()); + CalculateExpression = x => x.ToPercentage(0.8d, 1.0d); + + var result = await request.DownloadAsync(x => { + ReportProgress(x, + "Downloading Optifine installation package", + TaskStatus.Running); + }); + + ReportCompleted(); + + if (result) { + ReportProgress(1.0d, "Installation is complete", TaskStatus.RanToCompletion); + return true; + } + + ReportProgress(1.0d, "Installation is complete", TaskStatus.Faulted); + return false; + } + + private void OnCompleted(object sender, EventArgs e) { + ReportCompleted(); + } + + private void OnProgressChanged(object sender, ProgressChangedEventArgs e) { + ReportProgress(e.Progress, e.ProgressStatus, e.Status); + } +} \ No newline at end of file diff --git a/MinecraftLaunch/Components/Installer/FabricInstaller.cs b/MinecraftLaunch/Components/Installer/FabricInstaller.cs index ad157e0..2186982 100644 --- a/MinecraftLaunch/Components/Installer/FabricInstaller.cs +++ b/MinecraftLaunch/Components/Installer/FabricInstaller.cs @@ -8,9 +8,10 @@ namespace MinecraftLaunch.Components.Installer; public sealed class FabricInstaller(GameEntry inheritedFrom, FabricBuildEntry entry, string customId = default, MirrorDownloadSource source = default) : InstallerBase { - private readonly string _customId = customId; + private readonly string _customId = customId; private readonly FabricBuildEntry _fabricBuildEntry = entry; - private readonly GameEntry _inheritedFrom = inheritedFrom; + + public override GameEntry InheritedFrom => inheritedFrom; public override async ValueTask InstallAsync() { /* @@ -23,7 +24,7 @@ public override async ValueTask InstallAsync() { var libraries = LibrariesResolver.GetLibrariesFromJsonArray(versionInfoNode .GetEnumerable("libraries"), - _inheritedFrom.GameFolderPath); + InheritedFrom.GameFolderPath); /* * Download dependent resources @@ -43,7 +44,7 @@ await libraries.DownloadResourceEntrysAsync(source, x => { } var id = versionInfoNode.GetString("id"); - var jsonFile = new FileInfo(Path.Combine(_inheritedFrom.GameFolderPath, + var jsonFile = new FileInfo(Path.Combine(InheritedFrom.GameFolderPath, "versions", id, $"{id}.json")); if (!jsonFile.Directory.Exists) { diff --git a/MinecraftLaunch/Components/Installer/ForgeInstaller.cs b/MinecraftLaunch/Components/Installer/ForgeInstaller.cs index 6285b05..f6e251d 100644 --- a/MinecraftLaunch/Components/Installer/ForgeInstaller.cs +++ b/MinecraftLaunch/Components/Installer/ForgeInstaller.cs @@ -13,13 +13,15 @@ namespace MinecraftLaunch.Components.Installer; public sealed class ForgeInstaller(GameEntry inheritedFrom, ForgeInstallEntry installEntry, string javaPath, string customId = default, MirrorDownloadSource mirror = default) : InstallerBase { private readonly string _customId = customId; private readonly string _javaPath = javaPath; - private readonly GameEntry _inheritedFrom = inheritedFrom; private readonly ForgeInstallEntry _installEntry = installEntry; private readonly MirrorDownloadSource _mirrorDownloadSource = mirror; + public override GameEntry InheritedFrom => inheritedFrom; + public override async ValueTask InstallAsync() { List highVersionForgeProcessors = default; + /* * Download Forge installation package */ @@ -60,7 +62,7 @@ await request.DownloadAsync(x => { var libraries = LibrariesResolver.GetLibrariesFromJsonArray(versionInfoJson .GetEnumerable("libraries"), - _inheritedFrom.GameFolderPath).ToList(); + InheritedFrom.GameFolderPath).ToList(); if (MirrorDownloadManager.IsUseMirrorDownloadSource) { foreach (var lib in libraries) { @@ -70,8 +72,8 @@ await request.DownloadAsync(x => { if (!isLegacyForgeVersion) { libraries.AddRange(LibrariesResolver.GetLibrariesFromJsonArray(installProfile - .GetEnumerable("libraries"), - _inheritedFrom.GameFolderPath)); + .GetEnumerable("libraries"), + InheritedFrom.GameFolderPath)); var highVersionForgeDataDictionary = installProfile .Select("data") @@ -87,11 +89,11 @@ await request.DownloadAsync(x => { var replaceValues = new Dictionary { { "{SIDE}", "client" }, - { "{MINECRAFT_JAR}", _inheritedFrom.JarPath.ToPath() }, + { "{MINECRAFT_JAR}", InheritedFrom.JarPath.ToPath() }, { "{MINECRAFT_VERSION}", installProfile.GetString("minecraft") }, - { "{ROOT}", _inheritedFrom.GameFolderPath.ToPath() }, + { "{ROOT}", InheritedFrom.GameFolderPath.ToPath() }, { "{INSTALLER}", packagePath.ToPath() }, - { "{LIBRARY_DIR}", Path.Combine(_inheritedFrom.GameFolderPath, "libraries").ToPath() } + { "{LIBRARY_DIR}", Path.Combine(InheritedFrom.GameFolderPath, "libraries").ToPath() } }; var replaceProcessorArgs = highVersionForgeDataDictionary.ToDictionary( @@ -100,7 +102,7 @@ await request.DownloadAsync(x => { if (!value.StartsWith('[')) { return value; } - return Path.Combine(_inheritedFrom.GameFolderPath, + return Path.Combine(InheritedFrom.GameFolderPath, "libraries", LibrariesResolver.FormatLibraryNameToRelativePath(value.TrimStart('[').TrimEnd(']'))) .ToPath(); @@ -116,7 +118,7 @@ await request.DownloadAsync(x => { processor.Args = processor.Args.Select(x => { if (x.StartsWith("[")) return Path.Combine( - _inheritedFrom.GameFolderPath, + InheritedFrom.GameFolderPath, "libraries", LibrariesResolver.FormatLibraryNameToRelativePath(x.TrimStart('[').TrimEnd(']'))) .ToPath(); @@ -144,7 +146,7 @@ await libraries.DownloadResourceEntrysAsync(_mirrorDownloadSource, x => { * Write information to version json */ ReportProgress(0.85d, "Write information to version json", TaskStatus.WaitingToRun); - string forgeLibsFolder = Path.Combine(_inheritedFrom.GameFolderPath, + string forgeLibsFolder = Path.Combine(InheritedFrom.GameFolderPath, "libraries\\net\\minecraftforge\\forge", forgeVersion); @@ -168,7 +170,7 @@ await libraries.DownloadResourceEntrysAsync(_mirrorDownloadSource, x => { } var jsonFile = new FileInfo(Path.Combine( - _inheritedFrom.GameFolderPath, + InheritedFrom.GameFolderPath, "versions", versionInfoJson.GetString("id"), $"{versionInfoJson.GetString("id")}.json")); @@ -194,7 +196,7 @@ await libraries.DownloadResourceEntrysAsync(_mirrorDownloadSource, x => { foreach (var processor in highVersionForgeProcessors) { var fileName = Path.Combine( - _inheritedFrom.GameFolderPath, + InheritedFrom.GameFolderPath, "libraries", LibrariesResolver.FormatLibraryNameToRelativePath(processor.Jar)); @@ -207,7 +209,7 @@ await libraries.DownloadResourceEntrysAsync(_mirrorDownloadSource, x => { string classPath = string.Join(Path.PathSeparator.ToString(), new List() { fileName } .Concat(processor.Classpath.Select(x => Path.Combine( - _inheritedFrom.GameFolderPath, + InheritedFrom.GameFolderPath, "libraries", LibrariesResolver.FormatLibraryNameToRelativePath(x))))); @@ -220,11 +222,11 @@ await libraries.DownloadResourceEntrysAsync(_mirrorDownloadSource, x => { args.AddRange(processor.Args); using var process = Process.Start(new ProcessStartInfo(_javaPath) { - Arguments = string.Join(" ", args), UseShellExecute = false, - WorkingDirectory = _inheritedFrom.GameFolderPath, RedirectStandardError = true, - RedirectStandardOutput = true + RedirectStandardOutput = true, + Arguments = string.Join(" ", args), + WorkingDirectory = InheritedFrom.GameFolderPath }); var outputs = new List(); diff --git a/MinecraftLaunch/Components/Installer/InstallerBase.cs b/MinecraftLaunch/Components/Installer/InstallerBase.cs index 7e68789..6c77d01 100644 --- a/MinecraftLaunch/Components/Installer/InstallerBase.cs +++ b/MinecraftLaunch/Components/Installer/InstallerBase.cs @@ -1,13 +1,16 @@ using MinecraftLaunch.Classes.Interfaces; using MinecraftLaunch.Classes.Models.Event; +using MinecraftLaunch.Classes.Models.Game; namespace MinecraftLaunch.Components.Installer; public abstract class InstallerBase : IInstaller { public event EventHandler Completed; - public event EventHandler ProgressChanged; + public abstract GameEntry InheritedFrom { get; } + public virtual Func CalculateExpression { get; set; } + public abstract ValueTask InstallAsync(); public void ReportCompleted() { @@ -15,6 +18,6 @@ public void ReportCompleted() { } internal virtual void ReportProgress(double progress, string progressStatus, TaskStatus status) { - ProgressChanged?.Invoke(this, new(status, progress, progressStatus)); + ProgressChanged?.Invoke(this, new(status, CalculateExpression is null ? progress : CalculateExpression.Invoke(progress), progressStatus)); } -} \ No newline at end of file +} diff --git a/MinecraftLaunch/Components/Installer/NeoForgeInstaller.cs b/MinecraftLaunch/Components/Installer/NeoForgeInstaller.cs index a813923..17b15b5 100644 --- a/MinecraftLaunch/Components/Installer/NeoForgeInstaller.cs +++ b/MinecraftLaunch/Components/Installer/NeoForgeInstaller.cs @@ -1,7 +1,11 @@  +using MinecraftLaunch.Classes.Models.Game; + namespace MinecraftLaunch.Components.Installer; public sealed class NeoForgeInstaller : InstallerBase { + public override GameEntry InheritedFrom => throw new NotImplementedException(); + public override ValueTask InstallAsync() { throw new NotImplementedException(); } diff --git a/MinecraftLaunch/Components/Installer/OptifineInstaller.cs b/MinecraftLaunch/Components/Installer/OptifineInstaller.cs index cbb6534..40b3044 100644 --- a/MinecraftLaunch/Components/Installer/OptifineInstaller.cs +++ b/MinecraftLaunch/Components/Installer/OptifineInstaller.cs @@ -1,28 +1,28 @@ using Flurl.Http; using System.Text.Json; -using MinecraftLaunch.Classes.Models.Game; -using MinecraftLaunch.Classes.Models.Install; -using MinecraftLaunch.Classes.Models.Download; -using System; -using MinecraftLaunch.Extensions; +using System.Diagnostics; using System.IO.Compression; using System.Text.Json.Serialization; +using MinecraftLaunch.Extensions; using MinecraftLaunch.Components.Resolver; -using System.Diagnostics; +using MinecraftLaunch.Classes.Models.Game; +using MinecraftLaunch.Classes.Models.Install; +using MinecraftLaunch.Classes.Models.Download; namespace MinecraftLaunch.Components.Installer; -public sealed class OptifineInstaller(GameEntry inheritedFrom, +public sealed class OptifineInstaller( + GameEntry inheritedFrom, OptiFineInstallEntity installEntry, string javaPath, string customId = default, MirrorDownloadSource mirror = default) : InstallerBase { - private readonly string _customId = customId; private readonly string _javaPath = javaPath; - private readonly GameEntry _inheritedFrom = inheritedFrom; private readonly OptiFineInstallEntity _installEntry = installEntry; private readonly MirrorDownloadSource _mirrorDownloadSource = mirror; + public override GameEntry InheritedFrom => inheritedFrom; + public override async ValueTask InstallAsync() { /* * Download Optifine installation package @@ -74,15 +74,15 @@ await request.DownloadAsync(x => { minecraftArguments = " --tweakClass optifine.OptiFineTweaker" }; - var jarFilePath = Path.Combine(_inheritedFrom.GameFolderPath, "versions", jsonEntity.id, $"{jsonEntity.id}.jar"); - var jsonFilePath = Path.Combine(_inheritedFrom.GameFolderPath, "versions", jsonEntity.id, $"{jsonEntity.id}.json"); + var jarFilePath = Path.Combine(InheritedFrom.GameFolderPath, "versions", jsonEntity.id, $"{jsonEntity.id}.jar"); + var jsonFilePath = Path.Combine(InheritedFrom.GameFolderPath, "versions", jsonEntity.id, $"{jsonEntity.id}.json"); var launchwrapperFile = Path.Combine( - _inheritedFrom.GameFolderPath, + InheritedFrom.GameFolderPath, "libraries", LibrariesResolver.FormatLibraryNameToRelativePath(jsonEntity.libraries[1].Name)); var optifineLibraryPath = Path.Combine( - _inheritedFrom.GameFolderPath, + InheritedFrom.GameFolderPath, "libraries", LibrariesResolver.FormatLibraryNameToRelativePath(jsonEntity.libraries[0].Name)); @@ -98,21 +98,21 @@ await request.DownloadAsync(x => { })); packageArchive.GetEntry($"launchwrapper-of-{launchwrapper}.jar").ExtractToFile(launchwrapperFile, true); - File.Copy(_inheritedFrom.JarPath, jarFilePath, true); + File.Copy(InheritedFrom.JarPath, jarFilePath, true); /* * Running install processor */ using var process = Process.Start(new ProcessStartInfo(_javaPath) { UseShellExecute = false, - WorkingDirectory = _inheritedFrom.GameFolderPath, + WorkingDirectory = InheritedFrom.GameFolderPath, RedirectStandardError = true, RedirectStandardOutput = true, Arguments = string.Join(" ", [ "-cp", packagePath.ToPath(), "optifine.Patcher", - _inheritedFrom.JarPath.ToPath(), + InheritedFrom.JarPath.ToPath(), packagePath.ToPath(), optifineLibraryPath.ToPath() ]) diff --git a/MinecraftLaunch/Components/Installer/QuiltInstaller.cs b/MinecraftLaunch/Components/Installer/QuiltInstaller.cs index b94ca76..3ced728 100644 --- a/MinecraftLaunch/Components/Installer/QuiltInstaller.cs +++ b/MinecraftLaunch/Components/Installer/QuiltInstaller.cs @@ -11,7 +11,8 @@ namespace MinecraftLaunch.Components.Installer; public sealed class QuiltInstaller(GameEntry inheritedFrom, QuiltBuildEntry entry, string customId = default, MirrorDownloadSource source = default) : InstallerBase { private readonly string _customId = customId; private readonly QuiltBuildEntry _quiltBuildEntry = entry; - private readonly GameEntry _inheritedFrom = inheritedFrom; + + public override GameEntry InheritedFrom => inheritedFrom; public override async ValueTask InstallAsync() { /* @@ -24,7 +25,7 @@ public override async ValueTask InstallAsync() { var libraries = LibrariesResolver.GetLibrariesFromJsonArray(versionInfoNode .GetEnumerable("libraries"), - _inheritedFrom.GameFolderPath); + InheritedFrom.GameFolderPath); /* @@ -49,7 +50,7 @@ await libraries.DownloadResourceEntrysAsync(source, x => { } var id = versionInfoNode.GetString("id"); - var jsonFile = new FileInfo(Path.Combine(_inheritedFrom.GameFolderPath, + var jsonFile = new FileInfo(Path.Combine(InheritedFrom.GameFolderPath, "versions", id, $"{id}.json")); if (!jsonFile.Directory.Exists) { diff --git a/MinecraftLaunch/Components/Installer/VanlliaInstaller.cs b/MinecraftLaunch/Components/Installer/VanlliaInstaller.cs index ffac1ec..900e6a1 100644 --- a/MinecraftLaunch/Components/Installer/VanlliaInstaller.cs +++ b/MinecraftLaunch/Components/Installer/VanlliaInstaller.cs @@ -5,6 +5,7 @@ using MinecraftLaunch.Components.Checker; using MinecraftLaunch.Classes.Models.Install; using MinecraftLaunch.Classes.Models.Download; +using MinecraftLaunch.Classes.Models.Game; namespace MinecraftLaunch.Components.Installer; @@ -16,6 +17,8 @@ public sealed class VanlliaInstaller(IGameResolver gameFoloder, string gameId, M private readonly MirrorDownloadSource _source = source; private readonly IGameResolver _gameResolver = gameFoloder; + public override GameEntry InheritedFrom => throw new NotSupportedException(); + public override async ValueTask InstallAsync() { /* * Check if the specified id exists diff --git a/MinecraftLaunch/Utilities/DownloadUitl.cs b/MinecraftLaunch/Utilities/DownloadUitl.cs index bdc34e3..f46efcd 100644 --- a/MinecraftLaunch/Utilities/DownloadUitl.cs +++ b/MinecraftLaunch/Utilities/DownloadUitl.cs @@ -17,7 +17,7 @@ public static class DownloadUitl { public static DownloadRequest DefaultDownloadRequest { get; set; } = new() { IsPartialContentSupported = true, FileSizeThreshold = 1024 * 1024 * 3, - MultiThreadsCount = 64, + MultiThreadsCount = 256, MultiPartsCount = 8 };