From 065d59e5704a304c0cd3685ae1c8758c4679c015 Mon Sep 17 00:00:00 2001 From: laolarou Date: Tue, 19 Dec 2023 11:05:25 -0800 Subject: [PATCH 1/9] add basic samples --- .../Commands/SystemInfoCommands.cs | 44 +++++++++++++++++++ .../Commands/SystemMetricsCommands.cs | 34 ++++++++++++++ .../ProjBobcat.Sample/Commands/TestCommand.cs | 15 +++++++ ProjBobcat/ProjBobcat.Sample/Program.cs | 28 ++++++++++++ .../ProjBobcat.Sample.csproj | 22 ++++++++++ ProjBobcat/ProjBobcat.sln | 10 ++++- ProjBobcat/ProjBobcat/ProjBobcat.csproj | 2 +- 7 files changed, 152 insertions(+), 3 deletions(-) create mode 100644 ProjBobcat/ProjBobcat.Sample/Commands/SystemInfoCommands.cs create mode 100644 ProjBobcat/ProjBobcat.Sample/Commands/SystemMetricsCommands.cs create mode 100644 ProjBobcat/ProjBobcat.Sample/Commands/TestCommand.cs create mode 100644 ProjBobcat/ProjBobcat.Sample/Program.cs create mode 100644 ProjBobcat/ProjBobcat.Sample/ProjBobcat.Sample.csproj diff --git a/ProjBobcat/ProjBobcat.Sample/Commands/SystemInfoCommands.cs b/ProjBobcat/ProjBobcat.Sample/Commands/SystemInfoCommands.cs new file mode 100644 index 0000000..9d42963 --- /dev/null +++ b/ProjBobcat/ProjBobcat.Sample/Commands/SystemInfoCommands.cs @@ -0,0 +1,44 @@ +using System.Runtime.InteropServices; +using System.Runtime.Versioning; +using Cocona; +using Microsoft.Extensions.Logging; +using ProjBobcat.Class.Helper; + +namespace ProjBobcat.Sample.Commands; + +public class SystemInfoCommands(ILogger logger) +{ + [SupportedOSPlatform("windows10.0.10586")] + [SupportedOSPlatform(nameof(OSPlatform.OSX))] + [Command("running-native", Description = "Check if the current process is running on native platform.")] + public void CheckCpuTranslation() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + logger.LogError("This command is not supported on Linux."); + return; + } + + logger.LogInformation("Is running under translation: {IsRunningUnderTranslation}", + SystemInfoHelper.IsRunningUnderTranslation()); + } + + [SupportedOSPlatform(nameof(OSPlatform.Windows))] + [SupportedOSPlatform(nameof(OSPlatform.OSX))] + [SupportedOSPlatform(nameof(OSPlatform.Linux))] + [Command("find-java", Description = "Search Java on the local machine")] + public async Task SearchJavaAsync( + [Option("d", Description = "Enable deep search")] bool deepSearch) + { + logger.LogInformation("Searching Java..."); + + await foreach(var java in SystemInfoHelper.FindJava(deepSearch)) + logger.LogInformation("Found Java: {JavaPath}", java); + } + + [Command("arch", Description = "Get system arch")] + public void CheckSystemArch() + { + logger.LogInformation("System arch: {SystemArch}", SystemInfoHelper.GetSystemArch()); + } +} \ No newline at end of file diff --git a/ProjBobcat/ProjBobcat.Sample/Commands/SystemMetricsCommands.cs b/ProjBobcat/ProjBobcat.Sample/Commands/SystemMetricsCommands.cs new file mode 100644 index 0000000..9dbdeee --- /dev/null +++ b/ProjBobcat/ProjBobcat.Sample/Commands/SystemMetricsCommands.cs @@ -0,0 +1,34 @@ +using Cocona; +using Microsoft.Extensions.Logging; +using ProjBobcat.Class.Helper; + +namespace ProjBobcat.Sample.Commands; + +public class SystemMetricsCommands(ILogger logger) +{ + [Command("cpu", Description = "Get CPU usage")] + public async Task GetCpuUsage( + [Argument(Description = "Sample count")] int sampleCount = 6) + { + for (var i = 0; i < sampleCount; i++) + { + var cpuUsage = SystemInfoHelper.GetProcessorUsage(); + logger.LogInformation("CPU usage: {CpuUsage}", cpuUsage); + + await Task.Delay(TimeSpan.FromSeconds(1)); + } + } + + [Command("mem", Description = "Get memory usage")] + public async Task GetMemoryUsage( + [Argument(Description = "Sample count")] int sampleCount = 6) + { + for (var i = 0; i < sampleCount; i++) + { + var memUsage = SystemInfoHelper.GetMemoryUsage(); + logger.LogInformation("Memory usage: {MemoryUsage}", memUsage); + + await Task.Delay(TimeSpan.FromSeconds(1)); + } + } +} \ No newline at end of file diff --git a/ProjBobcat/ProjBobcat.Sample/Commands/TestCommand.cs b/ProjBobcat/ProjBobcat.Sample/Commands/TestCommand.cs new file mode 100644 index 0000000..c666b44 --- /dev/null +++ b/ProjBobcat/ProjBobcat.Sample/Commands/TestCommand.cs @@ -0,0 +1,15 @@ +using Cocona; +using Microsoft.Extensions.Logging; + +namespace ProjBobcat.Sample.Commands; + +public class TestCommand(ILogger logger) +{ + readonly ILogger _logger = logger; + + [Command("hello")] + public void Hello() + { + _logger.LogInformation("Hello from Cocona."); + } +} \ No newline at end of file diff --git a/ProjBobcat/ProjBobcat.Sample/Program.cs b/ProjBobcat/ProjBobcat.Sample/Program.cs new file mode 100644 index 0000000..a91b9d8 --- /dev/null +++ b/ProjBobcat/ProjBobcat.Sample/Program.cs @@ -0,0 +1,28 @@ +using Cocona; +using ProjBobcat.Sample.Commands; +using Serilog; + +namespace ProjBobcat.Sample +{ + [HasSubCommands(typeof(SystemMetricsCommands), "usage", Description = "System usage metrics commands")] + [HasSubCommands(typeof(SystemInfoCommands), "utils", Description = "System information utilities")] + class Program + { + static void Main(string[] args) + { + var builder = CoconaApp.CreateBuilder(); + builder + .Host.UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration + .ReadFrom.Configuration(hostingContext.Configuration) + .Enrich.FromLogContext() + .WriteTo.Console()); + + var app = builder.Build(); + + app.AddCommands(); + app.AddCommands(); + + app.Run(); + } + } +} diff --git a/ProjBobcat/ProjBobcat.Sample/ProjBobcat.Sample.csproj b/ProjBobcat/ProjBobcat.Sample/ProjBobcat.Sample.csproj new file mode 100644 index 0000000..e300cf8 --- /dev/null +++ b/ProjBobcat/ProjBobcat.Sample/ProjBobcat.Sample.csproj @@ -0,0 +1,22 @@ + + + + Exe + net8.0 + enable + enable + true + + + + + + + + + + + + + + diff --git a/ProjBobcat/ProjBobcat.sln b/ProjBobcat/ProjBobcat.sln index 2ab3e35..aead6d5 100644 --- a/ProjBobcat/ProjBobcat.sln +++ b/ProjBobcat/ProjBobcat.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29728.190 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34330.188 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProjBobcat", "ProjBobcat\ProjBobcat.csproj", "{9777E280-8601-4A6C-BD75-0D29FD4F5D6F}" EndProject @@ -10,6 +10,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .editorconfig = .editorconfig EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjBobcat.Sample", "ProjBobcat.Sample\ProjBobcat.Sample.csproj", "{65C4CA49-E835-4AFD-A46E-7E188A821B0D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -20,6 +22,10 @@ Global {9777E280-8601-4A6C-BD75-0D29FD4F5D6F}.Debug|Any CPU.Build.0 = Debug|Any CPU {9777E280-8601-4A6C-BD75-0D29FD4F5D6F}.Release|Any CPU.ActiveCfg = Release|Any CPU {9777E280-8601-4A6C-BD75-0D29FD4F5D6F}.Release|Any CPU.Build.0 = Release|Any CPU + {65C4CA49-E835-4AFD-A46E-7E188A821B0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {65C4CA49-E835-4AFD-A46E-7E188A821B0D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {65C4CA49-E835-4AFD-A46E-7E188A821B0D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {65C4CA49-E835-4AFD-A46E-7E188A821B0D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ProjBobcat/ProjBobcat/ProjBobcat.csproj b/ProjBobcat/ProjBobcat/ProjBobcat.csproj index 17758ec..e92b107 100644 --- a/ProjBobcat/ProjBobcat/ProjBobcat.csproj +++ b/ProjBobcat/ProjBobcat/ProjBobcat.csproj @@ -66,7 +66,7 @@ resolved the issue that LaunchWrapper may not return the correct exit code - 0.34.2 + 0.35.0 From abbde29ba3ebe4f28f5849bc811268611077ca16 Mon Sep 17 00:00:00 2001 From: laolarou Date: Tue, 19 Dec 2023 17:09:35 -0800 Subject: [PATCH 2/9] add more samples --- .../Commands/Game/GameLaunchCommands.cs | 6 + .../Commands/Game/GameManageCommands.cs | 170 ++++++++++++++++++ .../Commands/SystemMetricsCommands.cs | 4 +- .../DownloadMirrors/BangBangDownloadMirror.cs | 13 ++ .../DownloadMirrors/IDownloadMirror.cs | 13 ++ .../DownloadMirrors/McBbsDownloadMirror.cs | 13 ++ .../DownloadMirrors/OfficialDownloadMirror.cs | 13 ++ ProjBobcat/ProjBobcat.Sample/GameHelper.cs | 139 ++++++++++++++ ProjBobcat/ProjBobcat.Sample/Program.cs | 3 + 9 files changed, 372 insertions(+), 2 deletions(-) create mode 100644 ProjBobcat/ProjBobcat.Sample/Commands/Game/GameLaunchCommands.cs create mode 100644 ProjBobcat/ProjBobcat.Sample/Commands/Game/GameManageCommands.cs create mode 100644 ProjBobcat/ProjBobcat.Sample/DownloadMirrors/BangBangDownloadMirror.cs create mode 100644 ProjBobcat/ProjBobcat.Sample/DownloadMirrors/IDownloadMirror.cs create mode 100644 ProjBobcat/ProjBobcat.Sample/DownloadMirrors/McBbsDownloadMirror.cs create mode 100644 ProjBobcat/ProjBobcat.Sample/DownloadMirrors/OfficialDownloadMirror.cs create mode 100644 ProjBobcat/ProjBobcat.Sample/GameHelper.cs diff --git a/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameLaunchCommands.cs b/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameLaunchCommands.cs new file mode 100644 index 0000000..80dd674 --- /dev/null +++ b/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameLaunchCommands.cs @@ -0,0 +1,6 @@ +namespace ProjBobcat.Sample.Commands.Game; + +public class GameLaunchCommands +{ + +} \ No newline at end of file diff --git a/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameManageCommands.cs b/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameManageCommands.cs new file mode 100644 index 0000000..96f7fdc --- /dev/null +++ b/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameManageCommands.cs @@ -0,0 +1,170 @@ +using System.Collections.Immutable; +using System.ComponentModel.DataAnnotations; +using Cocona; +using Microsoft.Extensions.Logging; +using ProjBobcat.Class.Helper; +using ProjBobcat.Class.Model; +using ProjBobcat.Interface; +using ProjBobcat.Sample.DownloadMirrors; + +namespace ProjBobcat.Sample.Commands.Game; + +public class GameManageCommands(ILogger logger) +{ + [Command("search", Description = "Search games on the local machine")] + public void GetLocalGames() + { + logger.LogInformation("Start searching games..."); + + var games = GameHelper.GameCore.VersionLocator.GetAllGames().ToImmutableList(); + + if (games.Count == 0) + { + logger.LogWarning("No games found."); + return; + } + + foreach (var game in games) + logger.LogInformation("Found game: {GameId}[{GameName}]", game.Id, game.Name); + } + + [Command("mirrors", Description = "Get download mirrors")] + public void GetDownloadMirrors() + { + string[] mirrors = + [ + nameof(OfficialDownloadMirror), + nameof(BangBangDownloadMirror), + nameof(McBbsDownloadMirror) + ]; + + for (var i = 0; i < mirrors.Length; i++) + { + var mirror = mirrors[i]; + var mirrorName = mirror[..^"DownloadMirror".Length]; + + logger.LogInformation("[{Index}] {MirrorName}", i, mirrorName); + } + } + + [Command("repair", Description = "Check game files and repair them if needed")] + public async Task RepairGameAsync( + [Argument(Description = "Game id")] string gameId, + [Range(0, 2)] [Argument("mirror", Description = "Download mirror index, use [game mirrors] to reveal mirror indexes")] int mirrorIndex = 0, + [Range(1, 32)] [Argument("parallel", Description = "Parallel tasks")] int parallel = 8, + [Range(1, 128)] [Argument("download-threads", Description = "Download threads")] int downloadThreads = 32, + [Range(1, 16)] [Argument("download-parts", Description = "Download parts")] int downloadParts = 8, + [Option("verbose", Description = "Enable verbose mode")] bool verbose = false, + [Option("disable-verify", Description = "Disable file verification")] bool disableVerify = false, + [Option("uncheck-version", Description = "Disable Version Info checker")] bool uncheckVersion = false, + [Option("uncheck-asset", Description = "Disable Asset Info checker")] bool uncheckAsset = false, + [Option("uncheck-lib", Description = "Disable Library checker")] bool uncheckLib = false) + { + logger.LogInformation("Start repairing game {GameId}...", gameId); + + var versionInfo = GameHelper.GameCore.VersionLocator.GetGame(gameId); + IDownloadMirror mirror = mirrorIndex switch + { + 0 => new OfficialDownloadMirror(), + 1 => new BangBangDownloadMirror(), + 2 => new McBbsDownloadMirror(), + _ => throw new ArgumentOutOfRangeException(nameof(mirrorIndex)) + }; + + if (versionInfo == null) + { + logger.LogCritical( + "Game {GameId} not found. Please check if the game id is correct.", + gameId); + + return; + } + + var resolvers = new List(); + + if (!uncheckVersion) + resolvers.Add(GameHelper.GetVersionInfoResolver(versionInfo)); + if (!uncheckAsset) + { + logger.LogInformation("Start to fetch Version Manifest from remote..."); + + var vm = await GameHelper.GetVersionManifestTaskAsync(mirror); + + if (vm == null) + { + logger.LogCritical("Failed to fetch Version Manifest from remote. Please check your network connection."); + return; + } + + resolvers.Add(GameHelper.GetAssetInfoResolver(versionInfo, vm, mirror)); + } + if (!uncheckLib) + resolvers.Add(GameHelper.GetLibraryInfoResolver(versionInfo, mirror)); + + if (resolvers.Count == 0) + { + logger.LogWarning("No resolver enabled. Please check your command."); + return; + } + + foreach (var resolver in resolvers) + logger.LogInformation("Resolver enabled: {Resolver}", resolver.GetType().Name); + + var completer = GameHelper.GetResourceCompleter( + resolvers, + parallel, + downloadThreads, + downloadParts, + !disableVerify); + + if (verbose) + { + completer.GameResourceInfoResolveStatus += (_, args) => + { + logger.LogInformation("[{Progress:P2}] {Message}", args.Progress, args.Status); + }; + } + + var progressVal = 0d; + + completer.DownloadFileChangedEvent += (_, args) => + { + progressVal = args.ProgressPercentage; + }; + + completer.DownloadFileCompletedEvent += (sender, args) => + { + if (sender is not DownloadFile file) return; + + if (args.Error != null) + logger.LogError(args.Error, "Failed to download file {FileName}", file.FileName); + + var isSuccess = args.Success == null + ? null + : $"[{(args.Success.Value ? "Succeeded" : "Failed")}]"; + var retry = file.RetryCount == 0 + ? null + : $""; + var fileName = file.FileType switch + { + ResourceType.Asset => file.FileName, + ResourceType.LibraryOrNative => file.FileName, + _ => file.FileName + }; + + var speed = DownloadHelper.AutoFormatSpeedString(args.AverageSpeed); + var pD = $"<{file.FileType}>{retry}{isSuccess} {fileName} [{speed}]"; + + logger.LogInformation("[{Progress:P}] {ProgressDetail}", progressVal, pD); + }; + + logger.LogInformation("Start to check and download game {GameId}...", gameId); + + var rCResult = await completer.CheckAndDownloadTaskAsync(); + + if (rCResult.TaskStatus == TaskResultStatus.Error || (rCResult.Value?.IsLibDownloadFailed ?? false)) + logger.LogCritical("Failed to repair game {GameId}.", gameId); + else + logger.LogInformation("Game {GameId} repaired.", gameId); + } +} \ No newline at end of file diff --git a/ProjBobcat/ProjBobcat.Sample/Commands/SystemMetricsCommands.cs b/ProjBobcat/ProjBobcat.Sample/Commands/SystemMetricsCommands.cs index 9dbdeee..2188c68 100644 --- a/ProjBobcat/ProjBobcat.Sample/Commands/SystemMetricsCommands.cs +++ b/ProjBobcat/ProjBobcat.Sample/Commands/SystemMetricsCommands.cs @@ -7,7 +7,7 @@ namespace ProjBobcat.Sample.Commands; public class SystemMetricsCommands(ILogger logger) { [Command("cpu", Description = "Get CPU usage")] - public async Task GetCpuUsage( + public async Task GetCpuUsageAsync( [Argument(Description = "Sample count")] int sampleCount = 6) { for (var i = 0; i < sampleCount; i++) @@ -20,7 +20,7 @@ public async Task GetCpuUsage( } [Command("mem", Description = "Get memory usage")] - public async Task GetMemoryUsage( + public async Task GetMemoryUsageAsync( [Argument(Description = "Sample count")] int sampleCount = 6) { for (var i = 0; i < sampleCount; i++) diff --git a/ProjBobcat/ProjBobcat.Sample/DownloadMirrors/BangBangDownloadMirror.cs b/ProjBobcat/ProjBobcat.Sample/DownloadMirrors/BangBangDownloadMirror.cs new file mode 100644 index 0000000..e07a2e3 --- /dev/null +++ b/ProjBobcat/ProjBobcat.Sample/DownloadMirrors/BangBangDownloadMirror.cs @@ -0,0 +1,13 @@ +namespace ProjBobcat.Sample.DownloadMirrors; + +public record BangBangDownloadMirror : IDownloadMirror +{ + public string RootUri => "https://bmclapi2.bangbang93.com"; + public string VersionManifestJson => $"{RootUri}/mc/game/version_manifest.json"; + public string Assets => $"{RootUri}/assets/"; + public string Libraries => $"{RootUri}/maven/"; + public string Forge => $"{RootUri}/maven/"; + public string ForgeMaven => Forge; + public string ForgeMavenOld => Forge; + public string FabricMaven => $"{RootUri}/maven/"; +} \ No newline at end of file diff --git a/ProjBobcat/ProjBobcat.Sample/DownloadMirrors/IDownloadMirror.cs b/ProjBobcat/ProjBobcat.Sample/DownloadMirrors/IDownloadMirror.cs new file mode 100644 index 0000000..614221a --- /dev/null +++ b/ProjBobcat/ProjBobcat.Sample/DownloadMirrors/IDownloadMirror.cs @@ -0,0 +1,13 @@ +namespace ProjBobcat.Sample.DownloadMirrors; + +public interface IDownloadMirror +{ + string? RootUri { get; } + string VersionManifestJson { get; } + string Assets { get; } + string Libraries { get; } + string Forge { get; } + string ForgeMaven { get; } + string ForgeMavenOld { get; } + string FabricMaven { get; } +} \ No newline at end of file diff --git a/ProjBobcat/ProjBobcat.Sample/DownloadMirrors/McBbsDownloadMirror.cs b/ProjBobcat/ProjBobcat.Sample/DownloadMirrors/McBbsDownloadMirror.cs new file mode 100644 index 0000000..be76a66 --- /dev/null +++ b/ProjBobcat/ProjBobcat.Sample/DownloadMirrors/McBbsDownloadMirror.cs @@ -0,0 +1,13 @@ +namespace ProjBobcat.Sample.DownloadMirrors; + +public record McBbsDownloadMirror : IDownloadMirror +{ + public string RootUri => "https://download.mcbbs.net"; + public string VersionManifestJson => $"{RootUri}/mc/game/version_manifest.json"; + public string Assets => $"{RootUri}/assets/"; + public string Libraries => $"{RootUri}/maven/"; + public string Forge => $"{RootUri}/maven/"; + public string ForgeMaven => Forge; + public string ForgeMavenOld => Forge; + public string FabricMaven => $"{RootUri}/maven/"; +} \ No newline at end of file diff --git a/ProjBobcat/ProjBobcat.Sample/DownloadMirrors/OfficialDownloadMirror.cs b/ProjBobcat/ProjBobcat.Sample/DownloadMirrors/OfficialDownloadMirror.cs new file mode 100644 index 0000000..7e9eab4 --- /dev/null +++ b/ProjBobcat/ProjBobcat.Sample/DownloadMirrors/OfficialDownloadMirror.cs @@ -0,0 +1,13 @@ +namespace ProjBobcat.Sample.DownloadMirrors; + +public record OfficialDownloadMirror : IDownloadMirror +{ + public string? RootUri => null; + public string VersionManifestJson => "https://launchermeta.mojang.com/mc/game/version_manifest.json"; + public string Assets => "https://resources.download.minecraft.net/"; + public string Libraries => "https://libraries.minecraft.net/"; + public string Forge => "https://files.minecraftforge.net/maven/"; + public string ForgeMaven => "https://maven.minecraftforge.net/"; + public string ForgeMavenOld => "https://files.minecraftforge.net/maven/"; + public string FabricMaven => "https://maven.fabricmc.net/"; +}; \ No newline at end of file diff --git a/ProjBobcat/ProjBobcat.Sample/GameHelper.cs b/ProjBobcat/ProjBobcat.Sample/GameHelper.cs new file mode 100644 index 0000000..35cf54b --- /dev/null +++ b/ProjBobcat/ProjBobcat.Sample/GameHelper.cs @@ -0,0 +1,139 @@ +using System.Net.Http.Json; +using ProjBobcat.Class.Helper; +using ProjBobcat.Class.Model; +using ProjBobcat.Class.Model.Mojang; +using ProjBobcat.DefaultComponent; +using ProjBobcat.DefaultComponent.Launch; +using ProjBobcat.DefaultComponent.Launch.GameCore; +using ProjBobcat.DefaultComponent.Logging; +using ProjBobcat.DefaultComponent.ResourceInfoResolver; +using ProjBobcat.Interface; +using ProjBobcat.Sample.DownloadMirrors; + +namespace ProjBobcat.Sample; + +public static class GameHelper +{ + static GameHelper() + { + GameCore = GetGameCore(Path.GetFullPath(".minecraft")); + } + + public static IGameCore GameCore { get; private set; } + static HttpClient Client => HttpClientHelper.DefaultClient; + + static DefaultGameCore GetGameCore(string rootPath) + { + var clientToken = Guid.Parse("ea6a16d6-2d03-4280-9b0b-279816834993"); + var fullRootPath = Path.GetFullPath(rootPath); + + return new DefaultGameCore + { + ClientToken = clientToken, + RootPath = rootPath, + VersionLocator = new DefaultVersionLocator(fullRootPath, clientToken) + { + LauncherProfileParser = + new DefaultLauncherProfileParser(fullRootPath, clientToken), + LauncherAccountParser = new DefaultLauncherAccountParser(fullRootPath, clientToken) + }, + GameLogResolver = new DefaultGameLogResolver() + }; + } + + public static async Task GetVersionManifestTaskAsync( + IDownloadMirror downloadMirror) + { + VersionManifest? result = null; + var retryCount = 0; + + do + { + try + { + var vmUrl = downloadMirror.VersionManifestJson; + using var req = new HttpRequestMessage(HttpMethod.Get, vmUrl); + using var cts = new CancellationTokenSource(5000); + using var res = await Client.SendAsync(req, cts.Token); + + result = await res.Content.ReadFromJsonAsync( + VersionManifestContext.Default.VersionManifest, + cts.Token); + } + catch (TaskCanceledException) + { + } + finally + { + retryCount++; + await Task.Delay(1500 * retryCount); + } + } while (result == null && retryCount != 3); + + return result; + } + + public static IResourceInfoResolver GetVersionInfoResolver( + VersionInfo versionInfo) + { + return new VersionInfoResolver + { + BasePath = GameCore.RootPath, + VersionInfo = versionInfo, + CheckLocalFiles = true + }; + } + + public static IResourceInfoResolver GetAssetInfoResolver( + VersionInfo versionInfo, + VersionManifest versionManifest, + IDownloadMirror downloadMirror) + { + return new AssetInfoResolver + { + AssetIndexUriRoot = string.IsNullOrEmpty(downloadMirror.RootUri) + ? "https://launchermeta.mojang.com/" + : $"{downloadMirror.RootUri}/", + AssetUriRoot = downloadMirror.Assets, + BasePath = GameCore.RootPath, + VersionInfo = versionInfo, + CheckLocalFiles = true, + Versions = versionManifest.Versions + }; + } + + public static IResourceInfoResolver GetLibraryInfoResolver( + VersionInfo versionInfo, + IDownloadMirror downloadMirror) + { + return new LibraryInfoResolver + { + BasePath = GameCore.RootPath, + ForgeUriRoot = downloadMirror.Forge, + ForgeMavenUriRoot = downloadMirror.ForgeMaven, + ForgeMavenOldUriRoot = downloadMirror.ForgeMavenOld, + FabricMavenUriRoot = downloadMirror.FabricMaven, + LibraryUriRoot = downloadMirror.Libraries, + VersionInfo = versionInfo, + CheckLocalFiles = true + }; + } + + public static IResourceCompleter GetResourceCompleter( + IReadOnlyList resourceInfoResolvers, + int maxDegreeOfParallelism, + int downloadThreads, + int downloadParts, + bool verifyDownloadedFiles) + { + return new DefaultResourceCompleter + { + MaxDegreeOfParallelism = maxDegreeOfParallelism, + ResourceInfoResolvers = resourceInfoResolvers, + TotalRetry = 2, + CheckFile = verifyDownloadedFiles, + DownloadParts = downloadParts, + DownloadThread = downloadThreads + }; + } +} \ No newline at end of file diff --git a/ProjBobcat/ProjBobcat.Sample/Program.cs b/ProjBobcat/ProjBobcat.Sample/Program.cs index a91b9d8..ce5f316 100644 --- a/ProjBobcat/ProjBobcat.Sample/Program.cs +++ b/ProjBobcat/ProjBobcat.Sample/Program.cs @@ -1,9 +1,12 @@ using Cocona; using ProjBobcat.Sample.Commands; +using ProjBobcat.Sample.Commands.Game; using Serilog; namespace ProjBobcat.Sample { + [HasSubCommands(typeof(GameLaunchCommands), "game", Description = "Game launch commands")] + [HasSubCommands(typeof(GameManageCommands), "game", Description = "Game management commands")] [HasSubCommands(typeof(SystemMetricsCommands), "usage", Description = "System usage metrics commands")] [HasSubCommands(typeof(SystemInfoCommands), "utils", Description = "System information utilities")] class Program From 53d0ae0f8f7224adaede714c65585de9c30db749 Mon Sep 17 00:00:00 2001 From: laolarou Date: Tue, 19 Dec 2023 17:32:50 -0800 Subject: [PATCH 3/9] modify publish config --- ProjBobcat/ProjBobcat.Sample/Program.cs | 2 +- .../ProjBobcat.Sample.csproj | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/ProjBobcat/ProjBobcat.Sample/Program.cs b/ProjBobcat/ProjBobcat.Sample/Program.cs index ce5f316..ff5e959 100644 --- a/ProjBobcat/ProjBobcat.Sample/Program.cs +++ b/ProjBobcat/ProjBobcat.Sample/Program.cs @@ -5,7 +5,6 @@ namespace ProjBobcat.Sample { - [HasSubCommands(typeof(GameLaunchCommands), "game", Description = "Game launch commands")] [HasSubCommands(typeof(GameManageCommands), "game", Description = "Game management commands")] [HasSubCommands(typeof(SystemMetricsCommands), "usage", Description = "System usage metrics commands")] [HasSubCommands(typeof(SystemInfoCommands), "utils", Description = "System information utilities")] @@ -24,6 +23,7 @@ static void Main(string[] args) app.AddCommands(); app.AddCommands(); + app.AddCommands(); app.Run(); } diff --git a/ProjBobcat/ProjBobcat.Sample/ProjBobcat.Sample.csproj b/ProjBobcat/ProjBobcat.Sample/ProjBobcat.Sample.csproj index e300cf8..87c39fa 100644 --- a/ProjBobcat/ProjBobcat.Sample/ProjBobcat.Sample.csproj +++ b/ProjBobcat/ProjBobcat.Sample/ProjBobcat.Sample.csproj @@ -6,6 +6,30 @@ enable enable true + en + + + + true + false + + + + + + + + + + + true + true + full + true + true + true + false + true From 4e431d21b89babaadf0c6119c713f020197947e1 Mon Sep 17 00:00:00 2001 From: laolarou Date: Tue, 19 Dec 2023 17:44:28 -0800 Subject: [PATCH 4/9] minor fix --- .../ProjBobcat.Sample/Commands/Game/GameManageCommands.cs | 2 +- ProjBobcat/ProjBobcat.Sample/GameHelper.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameManageCommands.cs b/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameManageCommands.cs index 96f7fdc..b95d7cb 100644 --- a/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameManageCommands.cs +++ b/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameManageCommands.cs @@ -88,7 +88,7 @@ public async Task RepairGameAsync( { logger.LogInformation("Start to fetch Version Manifest from remote..."); - var vm = await GameHelper.GetVersionManifestTaskAsync(mirror); + var vm = await GameHelper.GetVersionManifestAsync(mirror); if (vm == null) { diff --git a/ProjBobcat/ProjBobcat.Sample/GameHelper.cs b/ProjBobcat/ProjBobcat.Sample/GameHelper.cs index 35cf54b..5a26542 100644 --- a/ProjBobcat/ProjBobcat.Sample/GameHelper.cs +++ b/ProjBobcat/ProjBobcat.Sample/GameHelper.cs @@ -41,7 +41,7 @@ static DefaultGameCore GetGameCore(string rootPath) }; } - public static async Task GetVersionManifestTaskAsync( + public static async Task GetVersionManifestAsync( IDownloadMirror downloadMirror) { VersionManifest? result = null; From 83b2bf83c79b66e0128556026e08a60a7a2b67bc Mon Sep 17 00:00:00 2001 From: laolarou Date: Tue, 19 Dec 2023 22:59:19 -0800 Subject: [PATCH 5/9] add game launch sample --- .../Commands/Game/GameLaunchCommands.cs | 111 +++++++++++++++++- .../Commands/Game/GameManageCommands.cs | 15 ++- 2 files changed, 122 insertions(+), 4 deletions(-) diff --git a/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameLaunchCommands.cs b/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameLaunchCommands.cs index 80dd674..3772780 100644 --- a/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameLaunchCommands.cs +++ b/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameLaunchCommands.cs @@ -1,6 +1,111 @@ -namespace ProjBobcat.Sample.Commands.Game; +using System.ComponentModel.DataAnnotations; +using Cocona; +using Microsoft.Extensions.Logging; +using ProjBobcat.Class.Helper; +using ProjBobcat.Class.Model; +using ProjBobcat.DefaultComponent.Authenticator; -public class GameLaunchCommands +namespace ProjBobcat.Sample.Commands.Game; + +public class GameLaunchCommands(ILogger logger) { - + [Command("launch", Aliases = ["run", "start", "play"], Description = "Launch the game.")] + public async Task LaunchGameAsync( + [Argument(Description = "Game Id")] string gameId, + [Argument(Description = "Offline account name")] string displayName, + [Argument(Description = "Java executable path")] string javaPath, + [Range(0, 5)] [Option("gc", Description = "Garbage collection type")] int gcType = 0, + [Range(1024, 1024 * 1024 * 10)] [Option("max-memory", Description = "Max memory size in MB")] uint maxMemory = 1024, + [Option("title")] string windowTitle = "Minecraft - By ProjBobcat") + { + var version = GameHelper.GameCore.VersionLocator.GetGame(gameId); + + if (version == null) + { + logger.LogCritical( + "Game {GameId} not found. Please check if the game id is correct.", + gameId); + + return; + } + + var auth = new OfflineAuthenticator + { + LauncherAccountParser = GameHelper.GameCore.VersionLocator.LauncherAccountParser!, + Username = displayName + }; + var authResult = await auth.AuthTaskAsync(false); + + var args = new GameArguments + { + GcType = (GcType)gcType, + JavaExecutable = javaPath, + MaxMemory = maxMemory + }; + var ls = new LaunchSettings + { + Authenticator = auth, + Version = gameId, + GameArguments = args, + GameName = version.Name, + GamePath = GamePathHelper.GetVersionPath(GameHelper.GameCore.RootPath), + GameResourcePath = GameHelper.GameCore.RootPath, + LauncherName = "LauncherX (By ProjBobcat)", + VersionInsulation = true, + VersionLocator = GameHelper.GameCore.VersionLocator, + WindowTitle = windowTitle, + SelectedProfile = authResult.SelectedProfile + }; + + GameHelper.GameCore.LaunchLogEventDelegate += (_, eventArgs) => + { + logger.LogInformation("[{Time}] {Message}", eventArgs.ItemRunTime, eventArgs.Item); + }; + + GameHelper.GameCore.GameExitEventDelegate += (_, eventArgs) => + { + logger.LogInformation("Game exit with code {ExitCode}.", eventArgs.ExitCode); + }; + + GameHelper.GameCore.GameLogEventDelegate += (_, eventArgs) => + { + logger.LogInformation(eventArgs.RawContent); + }; + + var result = await GameHelper.GameCore.LaunchTaskAsync(ls); + var isSucceed = result.Error == null; + var isSucceedStr = isSucceed ? "Succeeded" : "Failed"; + var type = isSucceed ? "Success" : "Error"; + var errorReason = result.ErrorType switch + { + LaunchErrorType.AuthFailed => "AuthFailed", + LaunchErrorType.DecompressFailed => "DecompressFailed", + LaunchErrorType.IncompleteArguments => "IncompleteArgument", + LaunchErrorType.NoJava => "NoJava", + LaunchErrorType.None => "None", + LaunchErrorType.OperationFailed => "OperationFailed", + LaunchErrorType.Unknown => "Unknown", + var x => throw new ArgumentOutOfRangeException(x.ToString()) + }; + var detail = isSucceed + ? $"Duration: {result.RunTime:g}" + : $"{result.Error?.ErrorMessage ?? "Unknown"}, Reason: {errorReason}"; + + logger.Log(isSucceed ? LogLevel.Information : LogLevel.Critical, detail); + + if (!isSucceed && result.Error?.Exception != null) + { + logger.LogError(result.Error?.Exception, "Exception occurred when launching game."); + + return; + } + + if (result.GameProcess == null) return; + + logger.LogInformation("Game process started, wait for game to exit."); + + await result.GameProcess.WaitForExitAsync(); + + logger.LogInformation("Game process exited."); + } } \ No newline at end of file diff --git a/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameManageCommands.cs b/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameManageCommands.cs index b95d7cb..5151838 100644 --- a/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameManageCommands.cs +++ b/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameManageCommands.cs @@ -11,7 +11,7 @@ namespace ProjBobcat.Sample.Commands.Game; public class GameManageCommands(ILogger logger) { - [Command("search", Description = "Search games on the local machine")] + [Command("search", Aliases = ["list", "find"], Description = "Search games on the local machine")] public void GetLocalGames() { logger.LogInformation("Start searching games..."); @@ -47,6 +47,19 @@ public void GetDownloadMirrors() } } + [Command("gc", Description = "Get garbage collection types")] + public void GetGcTypes() + { + var arr = Enum.GetNames(); + + for (var i = 0; i < arr.Length; i++) + { + var name = arr[i]; + + logger.LogInformation("[{Index}] {Name}", i, name); + } + } + [Command("repair", Description = "Check game files and repair them if needed")] public async Task RepairGameAsync( [Argument(Description = "Game id")] string gameId, From a246eb9c74c9618a175cfab9dfa0efe4899e11ed Mon Sep 17 00:00:00 2001 From: laolarou Date: Tue, 19 Dec 2023 23:06:29 -0800 Subject: [PATCH 6/9] Update GameLaunchCommands.cs --- .../ProjBobcat.Sample/Commands/Game/GameLaunchCommands.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameLaunchCommands.cs b/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameLaunchCommands.cs index 3772780..5895fce 100644 --- a/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameLaunchCommands.cs +++ b/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameLaunchCommands.cs @@ -16,7 +16,7 @@ public async Task LaunchGameAsync( [Argument(Description = "Java executable path")] string javaPath, [Range(0, 5)] [Option("gc", Description = "Garbage collection type")] int gcType = 0, [Range(1024, 1024 * 1024 * 10)] [Option("max-memory", Description = "Max memory size in MB")] uint maxMemory = 1024, - [Option("title")] string windowTitle = "Minecraft - By ProjBobcat") + [Option("title", Description = "Custom game window title (Windows only)")] string windowTitle = "Minecraft - By ProjBobcat") { var version = GameHelper.GameCore.VersionLocator.GetGame(gameId); From f322a48e4e9483985bfcfc75ed82e8555924e9ca Mon Sep 17 00:00:00 2001 From: laolarou Date: Tue, 19 Dec 2023 23:08:08 -0800 Subject: [PATCH 7/9] Update OfficialDownloadMirror.cs --- .../ProjBobcat.Sample/DownloadMirrors/OfficialDownloadMirror.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ProjBobcat/ProjBobcat.Sample/DownloadMirrors/OfficialDownloadMirror.cs b/ProjBobcat/ProjBobcat.Sample/DownloadMirrors/OfficialDownloadMirror.cs index 7e9eab4..26049ef 100644 --- a/ProjBobcat/ProjBobcat.Sample/DownloadMirrors/OfficialDownloadMirror.cs +++ b/ProjBobcat/ProjBobcat.Sample/DownloadMirrors/OfficialDownloadMirror.cs @@ -10,4 +10,4 @@ public record OfficialDownloadMirror : IDownloadMirror public string ForgeMaven => "https://maven.minecraftforge.net/"; public string ForgeMavenOld => "https://files.minecraftforge.net/maven/"; public string FabricMaven => "https://maven.fabricmc.net/"; -}; \ No newline at end of file +} \ No newline at end of file From cf07b7974ba450bc16260351da2f1cee561991ec Mon Sep 17 00:00:00 2001 From: laolarou Date: Tue, 19 Dec 2023 23:08:52 -0800 Subject: [PATCH 8/9] Update GameManageCommands.cs --- .../ProjBobcat.Sample/Commands/Game/GameManageCommands.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameManageCommands.cs b/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameManageCommands.cs index 5151838..1f3101e 100644 --- a/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameManageCommands.cs +++ b/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameManageCommands.cs @@ -158,13 +158,7 @@ public async Task RepairGameAsync( var retry = file.RetryCount == 0 ? null : $""; - var fileName = file.FileType switch - { - ResourceType.Asset => file.FileName, - ResourceType.LibraryOrNative => file.FileName, - _ => file.FileName - }; - + var fileName = file.FileName; var speed = DownloadHelper.AutoFormatSpeedString(args.AverageSpeed); var pD = $"<{file.FileType}>{retry}{isSuccess} {fileName} [{speed}]"; From dabc03e3bffa879540f06c6b9ef31e744057c998 Mon Sep 17 00:00:00 2001 From: BiDuang Date: Wed, 20 Dec 2023 15:44:03 +0800 Subject: [PATCH 9/9] fix: Removed unused variables and ternary operator. --- .../Commands/Game/GameLaunchCommands.cs | 2 - .../Commands/Game/GameManageCommands.cs | 68 +++++++++++-------- ProjBobcat/ProjBobcat.Sample/GameHelper.cs | 11 ++- 3 files changed, 46 insertions(+), 35 deletions(-) diff --git a/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameLaunchCommands.cs b/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameLaunchCommands.cs index 5895fce..c19ba0b 100644 --- a/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameLaunchCommands.cs +++ b/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameLaunchCommands.cs @@ -74,8 +74,6 @@ public async Task LaunchGameAsync( var result = await GameHelper.GameCore.LaunchTaskAsync(ls); var isSucceed = result.Error == null; - var isSucceedStr = isSucceed ? "Succeeded" : "Failed"; - var type = isSucceed ? "Success" : "Error"; var errorReason = result.ErrorType switch { LaunchErrorType.AuthFailed => "AuthFailed", diff --git a/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameManageCommands.cs b/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameManageCommands.cs index 1f3101e..4715897 100644 --- a/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameManageCommands.cs +++ b/ProjBobcat/ProjBobcat.Sample/Commands/Game/GameManageCommands.cs @@ -15,7 +15,7 @@ public class GameManageCommands(ILogger logger) public void GetLocalGames() { logger.LogInformation("Start searching games..."); - + var games = GameHelper.GameCore.VersionLocator.GetAllGames().ToImmutableList(); if (games.Count == 0) @@ -23,11 +23,11 @@ public void GetLocalGames() logger.LogWarning("No games found."); return; } - + foreach (var game in games) logger.LogInformation("Found game: {GameId}[{GameName}]", game.Id, game.Name); } - + [Command("mirrors", Description = "Get download mirrors")] public void GetDownloadMirrors() { @@ -42,7 +42,7 @@ public void GetDownloadMirrors() { var mirror = mirrors[i]; var mirrorName = mirror[..^"DownloadMirror".Length]; - + logger.LogInformation("[{Index}] {MirrorName}", i, mirrorName); } } @@ -51,11 +51,11 @@ public void GetDownloadMirrors() public void GetGcTypes() { var arr = Enum.GetNames(); - + for (var i = 0; i < arr.Length; i++) { var name = arr[i]; - + logger.LogInformation("[{Index}] {Name}", i, name); } } @@ -63,15 +63,25 @@ public void GetGcTypes() [Command("repair", Description = "Check game files and repair them if needed")] public async Task RepairGameAsync( [Argument(Description = "Game id")] string gameId, - [Range(0, 2)] [Argument("mirror", Description = "Download mirror index, use [game mirrors] to reveal mirror indexes")] int mirrorIndex = 0, - [Range(1, 32)] [Argument("parallel", Description = "Parallel tasks")] int parallel = 8, - [Range(1, 128)] [Argument("download-threads", Description = "Download threads")] int downloadThreads = 32, - [Range(1, 16)] [Argument("download-parts", Description = "Download parts")] int downloadParts = 8, - [Option("verbose", Description = "Enable verbose mode")] bool verbose = false, - [Option("disable-verify", Description = "Disable file verification")] bool disableVerify = false, - [Option("uncheck-version", Description = "Disable Version Info checker")] bool uncheckVersion = false, - [Option("uncheck-asset", Description = "Disable Asset Info checker")] bool uncheckAsset = false, - [Option("uncheck-lib", Description = "Disable Library checker")] bool uncheckLib = false) + [Range(0, 2)] + [Argument("mirror", Description = "Download mirror index, use [game mirrors] to reveal mirror indexes")] + int mirrorIndex = 0, + [Range(1, 32)] [Argument("parallel", Description = "Parallel tasks")] + int parallel = 8, + [Range(1, 128)] [Argument("download-threads", Description = "Download threads")] + int downloadThreads = 32, + [Range(1, 16)] [Argument("download-parts", Description = "Download parts")] + int downloadParts = 8, + [Option("verbose", Description = "Enable verbose mode")] + bool verbose = false, + [Option("disable-verify", Description = "Disable file verification")] + bool disableVerify = false, + [Option("uncheck-version", Description = "Disable Version Info checker")] + bool uncheckVersion = false, + [Option("uncheck-asset", Description = "Disable Asset Info checker")] + bool uncheckAsset = false, + [Option("uncheck-lib", Description = "Disable Library checker")] + bool uncheckLib = false) { logger.LogInformation("Start repairing game {GameId}...", gameId); @@ -89,12 +99,12 @@ public async Task RepairGameAsync( logger.LogCritical( "Game {GameId} not found. Please check if the game id is correct.", gameId); - + return; } - + var resolvers = new List(); - + if (!uncheckVersion) resolvers.Add(GameHelper.GetVersionInfoResolver(versionInfo)); if (!uncheckAsset) @@ -105,15 +115,17 @@ public async Task RepairGameAsync( if (vm == null) { - logger.LogCritical("Failed to fetch Version Manifest from remote. Please check your network connection."); + logger.LogCritical( + "Failed to fetch Version Manifest from remote. Please check your network connection."); return; } - + resolvers.Add(GameHelper.GetAssetInfoResolver(versionInfo, vm, mirror)); } + if (!uncheckLib) resolvers.Add(GameHelper.GetLibraryInfoResolver(versionInfo, mirror)); - + if (resolvers.Count == 0) { logger.LogWarning("No resolver enabled. Please check your command."); @@ -140,21 +152,17 @@ public async Task RepairGameAsync( var progressVal = 0d; - completer.DownloadFileChangedEvent += (_, args) => - { - progressVal = args.ProgressPercentage; - }; + completer.DownloadFileChangedEvent += (_, args) => { progressVal = args.ProgressPercentage; }; completer.DownloadFileCompletedEvent += (sender, args) => { if (sender is not DownloadFile file) return; - + if (args.Error != null) logger.LogError(args.Error, "Failed to download file {FileName}", file.FileName); - var isSuccess = args.Success == null - ? null - : $"[{(args.Success.Value ? "Succeeded" : "Failed")}]"; + + var isSuccess = args.Success == true ? "Success" : "Failed"; var retry = file.RetryCount == 0 ? null : $""; @@ -164,7 +172,7 @@ public async Task RepairGameAsync( logger.LogInformation("[{Progress:P}] {ProgressDetail}", progressVal, pD); }; - + logger.LogInformation("Start to check and download game {GameId}...", gameId); var rCResult = await completer.CheckAndDownloadTaskAsync(); diff --git a/ProjBobcat/ProjBobcat.Sample/GameHelper.cs b/ProjBobcat/ProjBobcat.Sample/GameHelper.cs index 5a26542..9218868 100644 --- a/ProjBobcat/ProjBobcat.Sample/GameHelper.cs +++ b/ProjBobcat/ProjBobcat.Sample/GameHelper.cs @@ -18,10 +18,10 @@ static GameHelper() { GameCore = GetGameCore(Path.GetFullPath(".minecraft")); } - + public static IGameCore GameCore { get; private set; } static HttpClient Client => HttpClientHelper.DefaultClient; - + static DefaultGameCore GetGameCore(string rootPath) { var clientToken = Guid.Parse("ea6a16d6-2d03-4280-9b0b-279816834993"); @@ -40,7 +40,7 @@ static DefaultGameCore GetGameCore(string rootPath) GameLogResolver = new DefaultGameLogResolver() }; } - + public static async Task GetVersionManifestAsync( IDownloadMirror downloadMirror) { @@ -62,6 +62,11 @@ static DefaultGameCore GetGameCore(string rootPath) } catch (TaskCanceledException) { + // ignored + } + catch (Exception e) + { + Console.WriteLine(e); } finally {