From 964985b150bfd261e227b936761371df5089b245 Mon Sep 17 00:00:00 2001 From: YangSpring <99802662+YangSpring114@users.noreply.github.com> Date: Thu, 29 Aug 2024 22:59:33 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=A4=A7=E9=87=8F=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=EF=BC=8C=E9=87=8D=E5=86=99=E5=8F=82=E6=95=B0=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E5=99=A8=EF=BC=8C=E6=9B=B4=E6=96=B0=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...sproj => MinecraftLaunch.Banchmark.csproj} | 0 MinecraftLaunch.Test/Program.cs | 36 +-- MinecraftLaunch.sln | 12 +- MinecraftLaunch/Classes/Enums/AccountType.cs | 3 +- MinecraftLaunch/Classes/Enums/CrashCauses.cs | 19 +- .../Classes/Interfaces/IAuthenticator.cs | 5 +- .../Classes/Interfaces/IChecker.cs | 1 + .../Classes/Interfaces/IDownloader.cs | 1 + .../Classes/Interfaces/IFetcher.cs | 1 + .../Classes/Interfaces/IGameProcessWatcher.cs | 6 +- .../Classes/Interfaces/IGameResolver.cs | 3 +- .../Classes/Interfaces/IInstaller.cs | 1 + .../Classes/Interfaces/ILauncher.cs | 1 + .../Classes/Interfaces/IWatcher.cs | 3 +- .../Classes/Models/Auth/Account.cs | 2 +- .../Classes/Models/Auth/DeviceCodeResponse.cs | 2 +- .../Models/Auth/LauncherAccountEntry.cs | 26 +-- .../Models/Auth/OAuth2TokenResponse.cs | 4 +- .../Classes/Models/Auth/YggdrasilResponse.cs | 4 +- .../Classes/Models/Download/DownloadsEntry.cs | 4 +- .../Models/Download/ModrinthResourceEntry.cs | 12 +- .../Classes/Models/Download/MultiPartRange.cs | 2 +- .../Models/Event/LogReceivedEventArgs.cs | 1 - .../Event/ServerLatencyChangedEventArgs.cs | 1 + .../Classes/Models/Game/AssetEntry.cs | 6 +- .../Classes/Models/Game/AssetJsonEntry.cs | 4 +- .../Classes/Models/Game/GameEntry.cs | 31 +-- .../Classes/Models/Game/GameJsonEntry.cs | 6 +- .../Models/Game/LauncherProfileEntry.cs | 17 +- .../Classes/Models/Game/LibraryJsonEntry.cs | 12 +- .../Models/Install/FabricBuildEntry.cs | 10 +- .../Models/Install/ForgeInstallEntry.cs | 4 +- .../Install/HighVersionForgeProcessorEntry.cs | 4 +- .../Classes/Models/Install/QuiltBuildEntry.cs | 4 +- .../Models/Install/VersionManifestEntry.cs | 4 +- .../Models/Launch/ArgumentsJsonEntry.cs | 4 +- .../Classes/Models/Launch/CrashReport.cs | 2 +- .../Classes/Models/Launch/LaunchConfig.cs | 5 +- .../Classes/Models/ServerPing/PingPayload.cs | 2 +- .../Components/Analyzer/GameLogAnalyzer.cs | 11 +- .../Authenticator/MicrosoftAuthenticator.cs | 3 +- .../Authenticator/OfflineAuthenticator.cs | 7 +- .../Authenticator/UnifiedPassAuthenticator.cs | 4 +- .../Authenticator/YggdrasilAuthenticator.cs | 2 +- .../Components/Checker/PreLaunchChecker.cs | 2 +- .../Components/Checker/ResourceChecker.cs | 8 +- .../Converter/AccountJsonConverter.cs | 10 +- .../Downloader/ResourceDownloader.cs | 7 +- .../Components/Fetcher/CurseForgeFetcher.cs | 22 +- .../Components/Fetcher/JavaFetcher.cs | 18 +- .../Components/Fetcher/ModrinthFetcher.cs | 13 +- .../Installer/CompositionInstaller.cs | 3 +- .../Components/Installer/FabricInstaller.cs | 6 +- .../Components/Installer/ForgeInstaller.cs | 21 +- .../Components/Installer/InstallerBase.cs | 6 +- .../Components/Installer/NeoForgeInstaller.cs | 3 +- .../Components/Installer/OptifineInstaller.cs | 12 +- .../Components/Installer/QuiltInstaller.cs | 10 +- .../Components/Installer/VanlliaInstaller.cs | 8 +- .../Components/Launcher/ArgumentsBuilder.cs | 207 ++++++++---------- .../Components/Launcher/Launcher.cs | 23 +- .../Arguments/GameArgumentResolver.cs | 36 +++ .../Resolver/Arguments/JvmArgumentResolver.cs | 67 ++++++ .../Components/Resolver/AssetsResolver.cs | 16 +- .../Resolver/CurseforgeModpacksResolver.cs | 1 - ...eCrashAnalyzer.cs => GameCrashResolver.cs} | 3 +- .../Components/Resolver/GameResolver.cs | 79 ++++--- .../Resolver/LauncherAccountReslver.cs | 39 ++-- .../Resolver/LauncherProfileResolver.cs | 31 ++- .../Components/Resolver/LibrariesResolver.cs | 19 +- .../Components/Resolver/ModResolver.cs | 24 +- .../Resolver/ResourcePackResolver.cs | 4 +- .../Components/Resolver/TomlResolver.cs | 15 +- .../Components/Watcher/GameProcessWatcher.cs | 7 +- .../Components/Watcher/ServerPingWatcher.cs | 15 +- MinecraftLaunch/Extensions/CryptoExtension.cs | 1 + .../Extensions/DownloadEntryExtension.cs | 9 +- .../Extensions/DownloadExtension.cs | 12 +- MinecraftLaunch/Extensions/FileExtension.cs | 13 +- .../Extensions/GameEntryExtension.cs | 30 ++- MinecraftLaunch/Extensions/JsonExtension.cs | 12 +- MinecraftLaunch/Extensions/StringExtension.cs | 28 ++- .../Extensions/ZipArchiveExtension.cs | 1 + MinecraftLaunch/MinecraftLaunch.csproj | 2 +- MinecraftLaunch/MirrorDownloadManager.cs | 3 +- MinecraftLaunch/Utilities/DirectoryUtil.cs | 1 + MinecraftLaunch/Utilities/DownloadUitl.cs | 26 +-- MinecraftLaunch/Utilities/EnvironmentUtil.cs | 1 + MinecraftLaunch/Utilities/GameUtil.cs | 1 + MinecraftLaunch/Utilities/JavaUtil.cs | 14 +- MinecraftLaunch/Utilities/ZipUtil.cs | 9 +- 91 files changed, 657 insertions(+), 533 deletions(-) rename MinecraftLaunch.BanchTest/{MinecraftLaunch.BanchTest.csproj => MinecraftLaunch.Banchmark.csproj} (100%) create mode 100644 MinecraftLaunch/Components/Resolver/Arguments/GameArgumentResolver.cs create mode 100644 MinecraftLaunch/Components/Resolver/Arguments/JvmArgumentResolver.cs rename MinecraftLaunch/Components/Resolver/{GameCrashAnalyzer.cs => GameCrashResolver.cs} (99%) diff --git a/MinecraftLaunch.BanchTest/MinecraftLaunch.BanchTest.csproj b/MinecraftLaunch.BanchTest/MinecraftLaunch.Banchmark.csproj similarity index 100% rename from MinecraftLaunch.BanchTest/MinecraftLaunch.BanchTest.csproj rename to MinecraftLaunch.BanchTest/MinecraftLaunch.Banchmark.csproj diff --git a/MinecraftLaunch.Test/Program.cs b/MinecraftLaunch.Test/Program.cs index 9f10490..37c36d8 100644 --- a/MinecraftLaunch.Test/Program.cs +++ b/MinecraftLaunch.Test/Program.cs @@ -114,30 +114,30 @@ GameResolver gameResolver = new("C:\\Users\\wxysd\\Desktop\\temp\\.minecraft"); - VanlliaInstaller vanlliaInstaller = new(gameResolver, "1.18.2", MirrorDownloadManager.Bmcl); - vanlliaInstaller.ProgressChanged += (_, args) => { - Console.WriteLine($"{args.Progress * 100:0.00} - {args.Status} - {args.ProgressStatus}"); - }; + //VanlliaInstaller vanlliaInstaller = new(gameResolver, "1.18.2", MirrorDownloadManager.Bmcl); + //vanlliaInstaller.ProgressChanged += (_, args) => { + // Console.WriteLine($"{args.Progress * 100:0.00} - {args.Status} - {args.ProgressStatus}"); + //}; - await vanlliaInstaller.InstallAsync(); + //await vanlliaInstaller.InstallAsync(); - Console.WriteLine(); + //Console.WriteLine(); - 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); + //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); - CompositionInstaller compositionInstaller = new(forgeInstaller, - "1.18.2-Composition-114514", - (await OptifineInstaller.EnumerableFromVersionAsync("1.18.2")).First()); + //CompositionInstaller compositionInstaller = new(forgeInstaller, + // "1.18.2-Composition-114514", + // (await OptifineInstaller.EnumerableFromVersionAsync("1.18.2")).First()); - compositionInstaller.ProgressChanged += (_, args) => { - Console.WriteLine($"{args.Progress * 100:0.00} - {args.Status} - {args.ProgressStatus}"); - }; + //compositionInstaller.ProgressChanged += (_, args) => { + // Console.WriteLine($"{args.Progress * 100:0.00} - {args.Status} - {args.ProgressStatus}"); + //}; - await compositionInstaller.InstallAsync(); + //await compositionInstaller.InstallAsync(); #endregion diff --git a/MinecraftLaunch.sln b/MinecraftLaunch.sln index 2e9b263..20e2630 100644 --- a/MinecraftLaunch.sln +++ b/MinecraftLaunch.sln @@ -7,7 +7,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MinecraftLaunch", "Minecraf EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MinecraftLaunch.Simple", "MinecraftLaunch.Test\MinecraftLaunch.Simple.csproj", "{76E3BD50-5A2C-43D0-A5B5-CD139EB60C94}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MinecraftLaunch.BanchTest", "MinecraftLaunch.BanchTest\MinecraftLaunch.BanchTest.csproj", "{95AA9E60-2FD0-41C1-ACC7-1C3021B30F73}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MinecraftLaunch.Banchmark", "MinecraftLaunch.BanchTest\MinecraftLaunch.Banchmark.csproj", "{95AA9E60-2FD0-41C1-ACC7-1C3021B30F73}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Natsurainko.FluentCore", "..\..\..\Code\Natsurainko.FluentLauncher\Natsurainko.FluentCore\Natsurainko.FluentCore\Natsurainko.FluentCore.csproj", "{0EEEF9C0-49BE-4D3D-80B4-B01ED15CF7CA}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -41,6 +43,14 @@ Global {95AA9E60-2FD0-41C1-ACC7-1C3021B30F73}.Release|Any CPU.Build.0 = Release|Any CPU {95AA9E60-2FD0-41C1-ACC7-1C3021B30F73}.Release|x64.ActiveCfg = Release|Any CPU {95AA9E60-2FD0-41C1-ACC7-1C3021B30F73}.Release|x64.Build.0 = Release|Any CPU + {0EEEF9C0-49BE-4D3D-80B4-B01ED15CF7CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0EEEF9C0-49BE-4D3D-80B4-B01ED15CF7CA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0EEEF9C0-49BE-4D3D-80B4-B01ED15CF7CA}.Debug|x64.ActiveCfg = Debug|Any CPU + {0EEEF9C0-49BE-4D3D-80B4-B01ED15CF7CA}.Debug|x64.Build.0 = Debug|Any CPU + {0EEEF9C0-49BE-4D3D-80B4-B01ED15CF7CA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0EEEF9C0-49BE-4D3D-80B4-B01ED15CF7CA}.Release|Any CPU.Build.0 = Release|Any CPU + {0EEEF9C0-49BE-4D3D-80B4-B01ED15CF7CA}.Release|x64.ActiveCfg = Release|Any CPU + {0EEEF9C0-49BE-4D3D-80B4-B01ED15CF7CA}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/MinecraftLaunch/Classes/Enums/AccountType.cs b/MinecraftLaunch/Classes/Enums/AccountType.cs index 5f7c00a..911c322 100644 --- a/MinecraftLaunch/Classes/Enums/AccountType.cs +++ b/MinecraftLaunch/Classes/Enums/AccountType.cs @@ -1,6 +1,7 @@ namespace MinecraftLaunch.Classes.Enums; public enum AccountType { + /// /// 离线账户 /// @@ -15,7 +16,7 @@ public enum AccountType { /// Yggdrasil 第三方账户 /// Yggdrasil, - + /// /// UnifiedPass 统一通行证 /// diff --git a/MinecraftLaunch/Classes/Enums/CrashCauses.cs b/MinecraftLaunch/Classes/Enums/CrashCauses.cs index 7f6a483..f4b6569 100644 --- a/MinecraftLaunch/Classes/Enums/CrashCauses.cs +++ b/MinecraftLaunch/Classes/Enums/CrashCauses.cs @@ -1,12 +1,13 @@ namespace MinecraftLaunch.Classes.Enums; public enum CrashCauses { + #region Memory NoEnoughMemory, NoEnoughMemory32, - #endregion + #endregion Memory #region Java @@ -15,7 +16,7 @@ public enum CrashCauses { JavaVersionTooHigh, UnsupportedJavaVersion, - #endregion + #endregion Java #region GPU @@ -24,7 +25,7 @@ public enum CrashCauses { UnableToSetPixelFormat, UnsupportedIntelDriver, - #endregion + #endregion GPU #region Mod @@ -38,21 +39,21 @@ public enum CrashCauses { ModCausedGameCrash, MissingOrUnsupportedMandatoryMod, - #endregion + #endregion Mod #region OpenGL OpenGl1282Error, GpuDoesNotSupportOpenGl, - #endregion + #endregion OpenGL #region Shaders TextureTooLargeOrLowEndGpu, - FailedToLoadWorldBecauseOptiFine, + FailedToLoadWorldBecauseOptiFine, - #endregion + #endregion Shaders #region AffiliatedComponent @@ -63,7 +64,7 @@ public enum CrashCauses { IncompatibleForgeAndOptifine, LegacyForgeDoesNotSupportNewerJava, - #endregion + #endregion AffiliatedComponent LogFileNotFound, BlockCausedGameCrash, @@ -73,4 +74,4 @@ public enum CrashCauses { IncorrectPathEncodingOrMainClassNotFound, Other -} +} \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Interfaces/IAuthenticator.cs b/MinecraftLaunch/Classes/Interfaces/IAuthenticator.cs index 75a492a..ea5e649 100644 --- a/MinecraftLaunch/Classes/Interfaces/IAuthenticator.cs +++ b/MinecraftLaunch/Classes/Interfaces/IAuthenticator.cs @@ -1,11 +1,10 @@ -using MinecraftLaunch.Classes.Models.Auth; - -namespace MinecraftLaunch.Classes.Interfaces; +namespace MinecraftLaunch.Classes.Interfaces; /// /// 验证器统一接口 /// public interface IAuthenticator { + /// /// 验证方法 /// diff --git a/MinecraftLaunch/Classes/Interfaces/IChecker.cs b/MinecraftLaunch/Classes/Interfaces/IChecker.cs index dbb3c10..0fade2b 100644 --- a/MinecraftLaunch/Classes/Interfaces/IChecker.cs +++ b/MinecraftLaunch/Classes/Interfaces/IChecker.cs @@ -4,6 +4,7 @@ /// 检查器统一接口 /// public interface IChecker { + /// /// 异步检查方法 /// diff --git a/MinecraftLaunch/Classes/Interfaces/IDownloader.cs b/MinecraftLaunch/Classes/Interfaces/IDownloader.cs index 00a837b..050a10c 100644 --- a/MinecraftLaunch/Classes/Interfaces/IDownloader.cs +++ b/MinecraftLaunch/Classes/Interfaces/IDownloader.cs @@ -4,6 +4,7 @@ /// 下载器统一接口 /// public interface IDownloader { + /// /// 异步下载方法 /// diff --git a/MinecraftLaunch/Classes/Interfaces/IFetcher.cs b/MinecraftLaunch/Classes/Interfaces/IFetcher.cs index 6adc88c..d557815 100644 --- a/MinecraftLaunch/Classes/Interfaces/IFetcher.cs +++ b/MinecraftLaunch/Classes/Interfaces/IFetcher.cs @@ -4,6 +4,7 @@ /// 统一搜寻器接口 /// public interface IFetcher { + /// /// 同步搜寻 类型方法 /// diff --git a/MinecraftLaunch/Classes/Interfaces/IGameProcessWatcher.cs b/MinecraftLaunch/Classes/Interfaces/IGameProcessWatcher.cs index 33863f2..4ff2508 100644 --- a/MinecraftLaunch/Classes/Interfaces/IGameProcessWatcher.cs +++ b/MinecraftLaunch/Classes/Interfaces/IGameProcessWatcher.cs @@ -1,9 +1,11 @@ -using System.Diagnostics; -using MinecraftLaunch.Classes.Models.Event; +using MinecraftLaunch.Classes.Models.Event; + +using System.Diagnostics; namespace MinecraftLaunch.Classes.Interfaces; public interface IGameProcessWatcher { + /// /// 游戏进程 /// diff --git a/MinecraftLaunch/Classes/Interfaces/IGameResolver.cs b/MinecraftLaunch/Classes/Interfaces/IGameResolver.cs index 4cef834..2e1e9c4 100644 --- a/MinecraftLaunch/Classes/Interfaces/IGameResolver.cs +++ b/MinecraftLaunch/Classes/Interfaces/IGameResolver.cs @@ -6,10 +6,11 @@ namespace MinecraftLaunch.Classes.Interfaces; /// 游戏实例解析器接口 /// public interface IGameResolver { + /// /// 根目录 /// - DirectoryInfo Root { get; } + DirectoryInfo Root { get; } /// /// 根据 Id 获取指定的 游戏实例 diff --git a/MinecraftLaunch/Classes/Interfaces/IInstaller.cs b/MinecraftLaunch/Classes/Interfaces/IInstaller.cs index 58635f7..9a74028 100644 --- a/MinecraftLaunch/Classes/Interfaces/IInstaller.cs +++ b/MinecraftLaunch/Classes/Interfaces/IInstaller.cs @@ -3,6 +3,7 @@ namespace MinecraftLaunch.Classes.Interfaces; public interface IInstaller { + /// /// 异步安装方法 /// diff --git a/MinecraftLaunch/Classes/Interfaces/ILauncher.cs b/MinecraftLaunch/Classes/Interfaces/ILauncher.cs index c76154a..88ec922 100644 --- a/MinecraftLaunch/Classes/Interfaces/ILauncher.cs +++ b/MinecraftLaunch/Classes/Interfaces/ILauncher.cs @@ -6,6 +6,7 @@ namespace MinecraftLaunch.Classes.Interfaces; /// 启动器统一接口 /// public interface ILauncher { + /// /// 游戏启动配置 /// diff --git a/MinecraftLaunch/Classes/Interfaces/IWatcher.cs b/MinecraftLaunch/Classes/Interfaces/IWatcher.cs index 177252a..7215cc8 100644 --- a/MinecraftLaunch/Classes/Interfaces/IWatcher.cs +++ b/MinecraftLaunch/Classes/Interfaces/IWatcher.cs @@ -4,5 +4,6 @@ /// 监视器统一接口 /// public interface IWatcher { + void Start(); -} +} \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Auth/Account.cs b/MinecraftLaunch/Classes/Models/Auth/Account.cs index 2fa1dc4..f9ddc7a 100644 --- a/MinecraftLaunch/Classes/Models/Auth/Account.cs +++ b/MinecraftLaunch/Classes/Models/Auth/Account.cs @@ -42,4 +42,4 @@ public sealed record UnifiedPassAccount : Account { } [JsonSerializable(typeof(Account))] -sealed partial class AccountContext : JsonSerializerContext; \ No newline at end of file +internal sealed partial class AccountContext : JsonSerializerContext; \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Auth/DeviceCodeResponse.cs b/MinecraftLaunch/Classes/Models/Auth/DeviceCodeResponse.cs index 7369d36..5b91991 100644 --- a/MinecraftLaunch/Classes/Models/Auth/DeviceCodeResponse.cs +++ b/MinecraftLaunch/Classes/Models/Auth/DeviceCodeResponse.cs @@ -23,4 +23,4 @@ public sealed record DeviceCodeResponse { } [JsonSerializable(typeof(DeviceCodeResponse))] -sealed partial class DeviceCodeResponseContext : JsonSerializerContext; \ No newline at end of file +internal sealed partial class DeviceCodeResponseContext : JsonSerializerContext; \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Auth/LauncherAccountEntry.cs b/MinecraftLaunch/Classes/Models/Auth/LauncherAccountEntry.cs index 5317427..19ff1f9 100644 --- a/MinecraftLaunch/Classes/Models/Auth/LauncherAccountEntry.cs +++ b/MinecraftLaunch/Classes/Models/Auth/LauncherAccountEntry.cs @@ -5,11 +5,11 @@ namespace MinecraftLaunch.Classes.Models.Auth; public sealed record LauncherAccountEntry { [JsonPropertyName("mojangClientToken")] public string MojangClientToken { get; set; } - + [JsonPropertyName("activeAccountLocalId")] public string ActiveAccountLocalId { get; set; } - - [JsonPropertyName("accounts")] + + [JsonPropertyName("accounts")] public Dictionary Accounts { get; set; } } @@ -20,7 +20,7 @@ public sealed record AccountEntry { [JsonPropertyName("accessTokenExpiresAt")] public DateTime AccessTokenExpiresAt { get; set; } - [JsonPropertyName("avatar")] + [JsonPropertyName("avatar")] public string AvatarUrl { get; set; } [JsonPropertyName("eligibleForMigration")] @@ -29,28 +29,28 @@ public sealed record AccountEntry { [JsonPropertyName("hasMultipleProfiles")] public bool HasMultipleProfiles { get; set; } - [JsonPropertyName("legacy")] + [JsonPropertyName("legacy")] public bool IsLegacy { get; set; } - [JsonPropertyName("localId")] + [JsonPropertyName("localId")] public string LocalId { get; set; } [JsonPropertyName("minecraftProfile")] public AccountProfileEntry MinecraftProfile { get; set; } - [JsonPropertyName("persistent")] + [JsonPropertyName("persistent")] public bool IsPersistent { get; set; } - [JsonPropertyName("remoteId")] + [JsonPropertyName("remoteId")] public string RemoteId { get; set; } - [JsonPropertyName("type")] + [JsonPropertyName("type")] public string Type { get; set; } - [JsonPropertyName("userProperites")] + [JsonPropertyName("userProperites")] public AccountProfileEntry[] UserProperites { get; set; } - [JsonPropertyName("username")] + [JsonPropertyName("username")] public string UserName { get; set; } [JsonPropertyName("__id")] @@ -61,9 +61,9 @@ public sealed record AccountProfileEntry { [JsonPropertyName("id")] public string Uuid { get; set; } - [JsonPropertyName("name")] + [JsonPropertyName("name")] public string Name { get; set; } } [JsonSerializable(typeof(LauncherAccountEntry))] -partial class LauncherAccountEntryContext : JsonSerializerContext; \ No newline at end of file +internal partial class LauncherAccountEntryContext : JsonSerializerContext; \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Auth/OAuth2TokenResponse.cs b/MinecraftLaunch/Classes/Models/Auth/OAuth2TokenResponse.cs index 5f16a94..9735509 100644 --- a/MinecraftLaunch/Classes/Models/Auth/OAuth2TokenResponse.cs +++ b/MinecraftLaunch/Classes/Models/Auth/OAuth2TokenResponse.cs @@ -24,6 +24,6 @@ public sealed record OAuth2TokenResponse { [JsonPropertyName("foci")] public string Foci { get; set; } } - + [JsonSerializable(typeof(OAuth2TokenResponse))] -sealed partial class OAuth2TokenResponseContext : JsonSerializerContext; \ No newline at end of file +internal sealed partial class OAuth2TokenResponseContext : JsonSerializerContext; \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Auth/YggdrasilResponse.cs b/MinecraftLaunch/Classes/Models/Auth/YggdrasilResponse.cs index f102189..e0faef9 100644 --- a/MinecraftLaunch/Classes/Models/Auth/YggdrasilResponse.cs +++ b/MinecraftLaunch/Classes/Models/Auth/YggdrasilResponse.cs @@ -48,6 +48,6 @@ public sealed record ProfileModel { [JsonPropertyName("id")] public string Id { get; set; } } - + [JsonSerializable(typeof(YggdrasilResponse))] -sealed partial class YggdrasilResponseContext : JsonSerializerContext; \ No newline at end of file +internal sealed partial class YggdrasilResponseContext : JsonSerializerContext; \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Download/DownloadsEntry.cs b/MinecraftLaunch/Classes/Models/Download/DownloadsEntry.cs index ce1ece7..e9af7fd 100644 --- a/MinecraftLaunch/Classes/Models/Download/DownloadsEntry.cs +++ b/MinecraftLaunch/Classes/Models/Download/DownloadsEntry.cs @@ -27,6 +27,6 @@ public sealed record FileEntry { [JsonPropertyName("id")] public string Id { get; set; } } - + [JsonSerializable(typeof(DownloadsEntry))] -sealed partial class DownloadsEntryContext : JsonSerializerContext; \ No newline at end of file +internal sealed partial class DownloadsEntryContext : JsonSerializerContext; \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Download/ModrinthResourceEntry.cs b/MinecraftLaunch/Classes/Models/Download/ModrinthResourceEntry.cs index b657115..a4af5fe 100644 --- a/MinecraftLaunch/Classes/Models/Download/ModrinthResourceEntry.cs +++ b/MinecraftLaunch/Classes/Models/Download/ModrinthResourceEntry.cs @@ -8,16 +8,16 @@ public sealed record ModrinthResourceEntry { [JsonPropertyName("slug")] public string Slug { get; set; } - + [JsonPropertyName("title")] public string Name { get; set; } [JsonPropertyName("author")] public string Author { get; set; } - + [JsonPropertyName("description")] public string Summary { get; set; } - + [JsonPropertyName("icon_url")] public string IconUrl { get; set; } @@ -26,10 +26,10 @@ public sealed record ModrinthResourceEntry { [JsonPropertyName("project_type")] public string ProjectType { get; set; } - + [JsonPropertyName("date_modified")] public DateTime DateModified { get; set; } - + [JsonPropertyName("display_categories")] public IEnumerable Categories { get; set; } @@ -41,4 +41,4 @@ public sealed record ModrinthResourceEntry { } [JsonSerializable(typeof(ModrinthResourceEntry))] -sealed partial class ModrinthResourceEntryContext : JsonSerializerContext; \ No newline at end of file +internal sealed partial class ModrinthResourceEntryContext : JsonSerializerContext; \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Download/MultiPartRange.cs b/MinecraftLaunch/Classes/Models/Download/MultiPartRange.cs index efa9a06..4c0270f 100644 --- a/MinecraftLaunch/Classes/Models/Download/MultiPartRange.cs +++ b/MinecraftLaunch/Classes/Models/Download/MultiPartRange.cs @@ -6,4 +6,4 @@ public record MultiPartRange { public long Start { get; set; } public string TempFilePath { get; set; } -} +} \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Event/LogReceivedEventArgs.cs b/MinecraftLaunch/Classes/Models/Event/LogReceivedEventArgs.cs index 1b1bae2..cbf4357 100644 --- a/MinecraftLaunch/Classes/Models/Event/LogReceivedEventArgs.cs +++ b/MinecraftLaunch/Classes/Models/Event/LogReceivedEventArgs.cs @@ -1,5 +1,4 @@ using MinecraftLaunch.Classes.Enums; -using MinecraftLaunch.Classes.Models.Game; namespace MinecraftLaunch.Classes.Models.Event; diff --git a/MinecraftLaunch/Classes/Models/Event/ServerLatencyChangedEventArgs.cs b/MinecraftLaunch/Classes/Models/Event/ServerLatencyChangedEventArgs.cs index 79850db..5120824 100644 --- a/MinecraftLaunch/Classes/Models/Event/ServerLatencyChangedEventArgs.cs +++ b/MinecraftLaunch/Classes/Models/Event/ServerLatencyChangedEventArgs.cs @@ -1,6 +1,7 @@ using MinecraftLaunch.Classes.Models.ServerPing; namespace MinecraftLaunch.Classes.Models.Event; + public sealed class ServerLatencyChangedEventArgs : EventArgs { public long Latency { get; set; } public PingPayload Response { get; set; } diff --git a/MinecraftLaunch/Classes/Models/Game/AssetEntry.cs b/MinecraftLaunch/Classes/Models/Game/AssetEntry.cs index 15c56fd..3a2ea33 100644 --- a/MinecraftLaunch/Classes/Models/Game/AssetEntry.cs +++ b/MinecraftLaunch/Classes/Models/Game/AssetEntry.cs @@ -12,11 +12,11 @@ public sealed class AssetEntry : IDownloadEntry { public string Checksum { get; set; } - public required string Url { get; set; } + public string Url { get; set; } - public required string Path { get; set; } + public string Path { get; set; } - public required string RelativePath { get; set; } + public string RelativePath { get; set; } public DownloadEntryType Type => DownloadEntryType.Asset; } \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Game/AssetJsonEntry.cs b/MinecraftLaunch/Classes/Models/Game/AssetJsonEntry.cs index 5b28f07..0e4ae12 100644 --- a/MinecraftLaunch/Classes/Models/Game/AssetJsonEntry.cs +++ b/MinecraftLaunch/Classes/Models/Game/AssetJsonEntry.cs @@ -9,6 +9,6 @@ public sealed record AssetJsonEntry { [JsonPropertyName("hash")] public string Hash { get; set; } } - + [JsonSerializable(typeof(AssetJsonEntry))] -sealed partial class AssetJsonEntryContext : JsonSerializerContext; \ No newline at end of file +internal sealed partial class AssetJsonEntryContext : JsonSerializerContext; \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Game/GameEntry.cs b/MinecraftLaunch/Classes/Models/Game/GameEntry.cs index fe3a960..f40d7d5 100644 --- a/MinecraftLaunch/Classes/Models/Game/GameEntry.cs +++ b/MinecraftLaunch/Classes/Models/Game/GameEntry.cs @@ -4,30 +4,19 @@ namespace MinecraftLaunch.Classes.Models.Game; public sealed record GameEntry { public string Id { get; set; } - - public string Version { get; set; } - public string Type { get; set; } - - public int JavaVersion { get; set; } - - public LoaderType MainLoaderType { get; set; } - + public string JarPath { get; set; } + public string Version { get; set; } + public string MainClass { get; set; } + public string GameFolderPath { get; set; } + public string AssetsIndexJsonPath { get; set; } public bool IsVanilla { get; set; } - + public int JavaVersion { get; set; } public bool IsInheritedFrom { get; set; } - public GameEntry InheritsFrom { get; set; } + public LoaderType MainLoaderType { get; set; } - public string GameFolderPath { get; set; } - - public string JarPath { get; set; } - - public string AssetsIndexJsonPath { get; set; } - - public string MainClass { get; set; } - - public IEnumerable FrontArguments { get; set; } - - public IEnumerable BehindArguments { get; set; } + internal GameJsonEntry GameJsonEntry { get; set; } + //public IEnumerable FrontArguments { get; set; } + //public IEnumerable BehindArguments { get; set; } } \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Game/GameJsonEntry.cs b/MinecraftLaunch/Classes/Models/Game/GameJsonEntry.cs index e1c48e6..dd49b54 100644 --- a/MinecraftLaunch/Classes/Models/Game/GameJsonEntry.cs +++ b/MinecraftLaunch/Classes/Models/Game/GameJsonEntry.cs @@ -24,7 +24,7 @@ public sealed record GameJsonEntry { public string Assets { get; set; } [JsonPropertyName("javaVersion")] - public JsonNode JavaVersion { get; set; } + public JsonNode JavaVersion { get; set; } [JsonPropertyName("arguments")] public ArgumentsJsonEntry Arguments { get; set; } @@ -46,6 +46,6 @@ public sealed record AssstIndex { [JsonPropertyName("sha1")] public string Sha1 { get; set; } } - + [JsonSerializable(typeof(GameJsonEntry))] -sealed partial class GameJsonEntryContext : JsonSerializerContext; \ No newline at end of file +internal sealed partial class GameJsonEntryContext : JsonSerializerContext; \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Game/LauncherProfileEntry.cs b/MinecraftLaunch/Classes/Models/Game/LauncherProfileEntry.cs index 7c541c7..e14d0a9 100644 --- a/MinecraftLaunch/Classes/Models/Game/LauncherProfileEntry.cs +++ b/MinecraftLaunch/Classes/Models/Game/LauncherProfileEntry.cs @@ -6,13 +6,13 @@ public sealed record LauncherProfileEntry { /// /// 客户端令牌 /// - [JsonPropertyName("clientToken")] + [JsonPropertyName("clientToken")] public string ClientToken { get; set; } /// /// 活动账户信息 /// - [JsonPropertyName("selectedUser")] + [JsonPropertyName("selectedUser")] public SelectedUserEntry SelectedAccount { get; set; } /// @@ -24,7 +24,7 @@ public sealed record LauncherProfileEntry { /// /// 档案信息 /// - [JsonPropertyName("profiles")] + [JsonPropertyName("profiles")] public Dictionary Profiles { get; set; } } @@ -91,7 +91,7 @@ public sealed record GameProfileEntry { } public sealed record SelectedUserEntry { - [JsonPropertyName("account")] + [JsonPropertyName("account")] public string Account { get; set; } [JsonPropertyName("profile")] @@ -106,12 +106,11 @@ public sealed record LauncherVersionEntry { public int Format { get; set; } } -public sealed record ResolutionEntry -{ - [JsonPropertyName("width")] +public sealed record ResolutionEntry { + [JsonPropertyName("width")] public uint Width { get; set; } - [JsonPropertyName("height")] + [JsonPropertyName("height")] public uint Height { get; set; } [JsonIgnore] @@ -121,4 +120,4 @@ public sealed record ResolutionEntry } [JsonSerializable(typeof(LauncherProfileEntry))] -sealed partial class LauncherProfileEntryContext : JsonSerializerContext; \ No newline at end of file +internal sealed partial class LauncherProfileEntryContext : JsonSerializerContext; \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Game/LibraryJsonEntry.cs b/MinecraftLaunch/Classes/Models/Game/LibraryJsonEntry.cs index b5d4e40..28d042e 100644 --- a/MinecraftLaunch/Classes/Models/Game/LibraryJsonEntry.cs +++ b/MinecraftLaunch/Classes/Models/Game/LibraryJsonEntry.cs @@ -1,6 +1,5 @@ -using System.Text.Json.Serialization; -using MinecraftLaunch.Classes.Enums; -using MinecraftLaunch.Classes.Models.Download; +using MinecraftLaunch.Classes.Models.Download; +using System.Text.Json.Serialization; namespace MinecraftLaunch.Classes.Models.Game; @@ -15,14 +14,13 @@ public sealed record LibraryJsonEntry { public Dictionary Natives { get; set; } } -public sealed record RuleModel -{ +public sealed record RuleModel { [JsonPropertyName("action")] public string Action { get; set; } [JsonPropertyName("os")] public Dictionary System { get; set; } } - + [JsonSerializable(typeof(LibraryJsonEntry))] -sealed partial class LibraryJsonEntryContext : JsonSerializerContext; \ No newline at end of file +internal sealed partial class LibraryJsonEntryContext : JsonSerializerContext; \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Install/FabricBuildEntry.cs b/MinecraftLaunch/Classes/Models/Install/FabricBuildEntry.cs index 620b064..7ba452c 100644 --- a/MinecraftLaunch/Classes/Models/Install/FabricBuildEntry.cs +++ b/MinecraftLaunch/Classes/Models/Install/FabricBuildEntry.cs @@ -1,7 +1,7 @@ -using System.Text.Json.Nodes; -using MinecraftLaunch.Classes.Enums; -using System.Text.Json.Serialization; +using MinecraftLaunch.Classes.Enums; using MinecraftLaunch.Classes.Models.Game; +using System.Text.Json.Nodes; +using System.Text.Json.Serialization; namespace MinecraftLaunch.Classes.Models.Install; @@ -46,6 +46,6 @@ public sealed record FabricMavenItem { [JsonPropertyName("version")] public string Version { get; set; } } - + [JsonSerializable(typeof(FabricBuildEntry))] -sealed partial class FabricBuildEntryContext : JsonSerializerContext; \ No newline at end of file +internal sealed partial class FabricBuildEntryContext : JsonSerializerContext; \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Install/ForgeInstallEntry.cs b/MinecraftLaunch/Classes/Models/Install/ForgeInstallEntry.cs index 82f9aa3..43c64db 100644 --- a/MinecraftLaunch/Classes/Models/Install/ForgeInstallEntry.cs +++ b/MinecraftLaunch/Classes/Models/Install/ForgeInstallEntry.cs @@ -18,6 +18,6 @@ public sealed record ForgeInstallEntry { [JsonPropertyName("modified")] public DateTime ModifiedTime { get; set; } } - + [JsonSerializable(typeof(ForgeInstallEntry))] -sealed partial class ForgeInstallEntryContext : JsonSerializerContext; \ No newline at end of file +internal sealed partial class ForgeInstallEntryContext : JsonSerializerContext; \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Install/HighVersionForgeProcessorEntry.cs b/MinecraftLaunch/Classes/Models/Install/HighVersionForgeProcessorEntry.cs index 2fba4ab..e5187b9 100644 --- a/MinecraftLaunch/Classes/Models/Install/HighVersionForgeProcessorEntry.cs +++ b/MinecraftLaunch/Classes/Models/Install/HighVersionForgeProcessorEntry.cs @@ -18,6 +18,6 @@ public sealed record HighVersionForgeProcessorEntry { [JsonPropertyName("outputs")] public Dictionary Outputs { get; set; } = new(); } - + [JsonSerializable(typeof(HighVersionForgeProcessorEntry))] -sealed partial class HighVersionForgeProcessorEntryContext : JsonSerializerContext; \ No newline at end of file +internal sealed partial class HighVersionForgeProcessorEntryContext : JsonSerializerContext; \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Install/QuiltBuildEntry.cs b/MinecraftLaunch/Classes/Models/Install/QuiltBuildEntry.cs index eaf37e0..83e8298 100644 --- a/MinecraftLaunch/Classes/Models/Install/QuiltBuildEntry.cs +++ b/MinecraftLaunch/Classes/Models/Install/QuiltBuildEntry.cs @@ -37,6 +37,6 @@ public sealed record QuiltMavenItem { [JsonPropertyName("version")] public string Version { get; set; } } - + [JsonSerializable(typeof(QuiltBuildEntry))] -sealed partial class QuiltBuildEntryContext : JsonSerializerContext; \ No newline at end of file +internal sealed partial class QuiltBuildEntryContext : JsonSerializerContext; \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Install/VersionManifestEntry.cs b/MinecraftLaunch/Classes/Models/Install/VersionManifestEntry.cs index ef6ff5a..2be15fc 100644 --- a/MinecraftLaunch/Classes/Models/Install/VersionManifestEntry.cs +++ b/MinecraftLaunch/Classes/Models/Install/VersionManifestEntry.cs @@ -18,6 +18,6 @@ public sealed record VersionManifestEntry { [JsonPropertyName("releaseTime")] public DateTime ReleaseTime { get; set; } } - + [JsonSerializable(typeof(VersionManifestEntry))] -sealed partial class VersionManifestEntryContext : JsonSerializerContext; \ No newline at end of file +internal sealed partial class VersionManifestEntryContext : JsonSerializerContext; \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Launch/ArgumentsJsonEntry.cs b/MinecraftLaunch/Classes/Models/Launch/ArgumentsJsonEntry.cs index 239ec09..982ab8b 100644 --- a/MinecraftLaunch/Classes/Models/Launch/ArgumentsJsonEntry.cs +++ b/MinecraftLaunch/Classes/Models/Launch/ArgumentsJsonEntry.cs @@ -10,6 +10,6 @@ public sealed record ArgumentsJsonEntry { [JsonPropertyName("game")] public List Game { get; set; } } - + [JsonSerializable(typeof(ArgumentsJsonEntry))] -sealed partial class ArgumentsJsonEntryContext : JsonSerializerContext; \ No newline at end of file +internal sealed partial class ArgumentsJsonEntryContext : JsonSerializerContext; \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Launch/CrashReport.cs b/MinecraftLaunch/Classes/Models/Launch/CrashReport.cs index e7aaee4..e910fd6 100644 --- a/MinecraftLaunch/Classes/Models/Launch/CrashReport.cs +++ b/MinecraftLaunch/Classes/Models/Launch/CrashReport.cs @@ -6,4 +6,4 @@ public sealed record CrashReport { public string Original { get; set; } public CrashCauses CrashCauses { get; set; } public IReadOnlyCollection Details { get; set; } -} +} \ No newline at end of file diff --git a/MinecraftLaunch/Classes/Models/Launch/LaunchConfig.cs b/MinecraftLaunch/Classes/Models/Launch/LaunchConfig.cs index f7299f7..d29d5f1 100644 --- a/MinecraftLaunch/Classes/Models/Launch/LaunchConfig.cs +++ b/MinecraftLaunch/Classes/Models/Launch/LaunchConfig.cs @@ -18,7 +18,7 @@ public sealed record LaunchConfig() { public bool IsEnableIndependencyCore { get; set; } = true; public GameWindowConfig GameWindowConfig { get; set; } = new(); - + public LaunchConfig(Account account) : this() { Account = account; } @@ -49,7 +49,6 @@ public sealed record JvmConfig(string file) { public bool UsedGC { get; set; } = true; - public int MinMemory { get; set; } = 512; public IEnumerable AdvancedArguments { get; set; } @@ -70,10 +69,8 @@ public sealed record ServerConfig(int port, string ip) { public sealed record GameWindowConfig { public int Width { get; set; } = 854; - public int Height { get; set; } = 480; - public bool IsFullscreen { get; set; } public static implicit operator GameWindowConfig(bool isFullscreen) => new() { diff --git a/MinecraftLaunch/Classes/Models/ServerPing/PingPayload.cs b/MinecraftLaunch/Classes/Models/ServerPing/PingPayload.cs index 867a188..4e3c15e 100644 --- a/MinecraftLaunch/Classes/Models/ServerPing/PingPayload.cs +++ b/MinecraftLaunch/Classes/Models/ServerPing/PingPayload.cs @@ -12,4 +12,4 @@ public sealed class PingPayload { } [JsonSerializable(typeof(PingPayload))] -sealed partial class PingPayloadContext : JsonSerializerContext; \ No newline at end of file +internal sealed partial class PingPayloadContext : JsonSerializerContext; \ No newline at end of file diff --git a/MinecraftLaunch/Components/Analyzer/GameLogAnalyzer.cs b/MinecraftLaunch/Components/Analyzer/GameLogAnalyzer.cs index b489b8d..b1a5fdf 100644 --- a/MinecraftLaunch/Components/Analyzer/GameLogAnalyzer.cs +++ b/MinecraftLaunch/Components/Analyzer/GameLogAnalyzer.cs @@ -1,8 +1,7 @@ -using MinecraftLaunch.Extensions; -using MinecraftLaunch.Classes.Enums; +using MinecraftLaunch.Classes.Enums; using MinecraftLaunch.Classes.Models.Game; using MinecraftLaunch.Classes.Models.Launch; - +using MinecraftLaunch.Extensions; using System.Collections.Immutable; using System.Text.RegularExpressions; @@ -21,6 +20,7 @@ public sealed partial class GameCrashAnalyzer(GameEntry gameEntry, bool isIndepe private readonly GameEntry _gameEntry = gameEntry; private readonly bool _isIndependencyCore = isIndependencyCore; + private readonly Dictionary _logCrashCauses = new() { { ".J9VMInternals.", CrashCauses.OpenJ9Use }, { "OpenJ9 is incompatible", CrashCauses.OpenJ9Use }, @@ -157,7 +157,7 @@ public sealed partial class GameCrashAnalyzer(GameEntry gameEntry, bool isIndepe [GeneratedRegex("(?<=Failed loading config file ).+(?= of type)")] private static partial Regex ConfigFileMatch2(); - #endregion + #endregion Regex /// /// Analyzes logs. @@ -178,7 +178,7 @@ public IEnumerable AnalysisLogs() { private void GetAllLogs() { var gamePath = Path.Combine(_isIndependencyCore - ? _gameEntry.OfVersionDirectoryPath(_isIndependencyCore) + ? _gameEntry.ToVersionDirectoryPath(_isIndependencyCore) : _gameEntry.GameFolderPath); _gameLogs = ReadAllLine(Path.Combine(gamePath, "logs", "latest.log").ToFileInfo()); @@ -254,7 +254,6 @@ private IEnumerable SpecificProcessGameLogs() { Original = log, CrashCauses = CrashCauses.NoEnoughMemory32 }; - } else { yield return new CrashReport { Original = log, diff --git a/MinecraftLaunch/Components/Authenticator/MicrosoftAuthenticator.cs b/MinecraftLaunch/Components/Authenticator/MicrosoftAuthenticator.cs index 997bfb5..58db898 100644 --- a/MinecraftLaunch/Components/Authenticator/MicrosoftAuthenticator.cs +++ b/MinecraftLaunch/Components/Authenticator/MicrosoftAuthenticator.cs @@ -1,8 +1,7 @@ using Flurl.Http; -using MinecraftLaunch.Extensions; -using MinecraftLaunch.Classes.Enums; using MinecraftLaunch.Classes.Interfaces; using MinecraftLaunch.Classes.Models.Auth; +using MinecraftLaunch.Extensions; namespace MinecraftLaunch.Components.Authenticator; diff --git a/MinecraftLaunch/Components/Authenticator/OfflineAuthenticator.cs b/MinecraftLaunch/Components/Authenticator/OfflineAuthenticator.cs index 61e3da5..dfa7fad 100644 --- a/MinecraftLaunch/Components/Authenticator/OfflineAuthenticator.cs +++ b/MinecraftLaunch/Components/Authenticator/OfflineAuthenticator.cs @@ -1,7 +1,7 @@ -using System.Text; -using System.Security.Cryptography; -using MinecraftLaunch.Classes.Interfaces; +using MinecraftLaunch.Classes.Interfaces; using MinecraftLaunch.Classes.Models.Auth; +using System.Security.Cryptography; +using System.Text; namespace MinecraftLaunch.Components.Authenticator; @@ -11,6 +11,7 @@ namespace MinecraftLaunch.Components.Authenticator; /// The name of the account. /// The UUID of the account. If not provided, a new UUID will be generated based on the account name. public sealed class OfflineAuthenticator(string name, Guid? uuid = default) : IAuthenticator { + /// /// Authenticates the offline account. /// diff --git a/MinecraftLaunch/Components/Authenticator/UnifiedPassAuthenticator.cs b/MinecraftLaunch/Components/Authenticator/UnifiedPassAuthenticator.cs index 561e411..96b3aa7 100644 --- a/MinecraftLaunch/Components/Authenticator/UnifiedPassAuthenticator.cs +++ b/MinecraftLaunch/Components/Authenticator/UnifiedPassAuthenticator.cs @@ -1,7 +1,7 @@ using Flurl.Http; -using MinecraftLaunch.Extensions; using MinecraftLaunch.Classes.Interfaces; using MinecraftLaunch.Classes.Models.Auth; +using MinecraftLaunch.Extensions; namespace MinecraftLaunch.Components.Authenticator; @@ -56,7 +56,7 @@ public async ValueTask AuthenticateAsync() { clientToken = null as string, requestUser = true, }; - + var node = (await (await authUrl.PostJsonAsync(content)) .GetStringAsync()) .AsNode(); diff --git a/MinecraftLaunch/Components/Authenticator/YggdrasilAuthenticator.cs b/MinecraftLaunch/Components/Authenticator/YggdrasilAuthenticator.cs index abd0000..dae33d4 100644 --- a/MinecraftLaunch/Components/Authenticator/YggdrasilAuthenticator.cs +++ b/MinecraftLaunch/Components/Authenticator/YggdrasilAuthenticator.cs @@ -1,7 +1,7 @@ using Flurl.Http; -using MinecraftLaunch.Extensions; using MinecraftLaunch.Classes.Interfaces; using MinecraftLaunch.Classes.Models.Auth; +using MinecraftLaunch.Extensions; namespace MinecraftLaunch.Components.Authenticator; diff --git a/MinecraftLaunch/Components/Checker/PreLaunchChecker.cs b/MinecraftLaunch/Components/Checker/PreLaunchChecker.cs index a600446..5798af1 100644 --- a/MinecraftLaunch/Components/Checker/PreLaunchChecker.cs +++ b/MinecraftLaunch/Components/Checker/PreLaunchChecker.cs @@ -15,7 +15,7 @@ public sealed class PreLaunchChecker(GameEntry entry) : IChecker { public ValueTask CheckAsync() { /* - * + * */ throw new NotImplementedException(); } diff --git a/MinecraftLaunch/Components/Checker/ResourceChecker.cs b/MinecraftLaunch/Components/Checker/ResourceChecker.cs index e13ec64..e0e5bb1 100644 --- a/MinecraftLaunch/Components/Checker/ResourceChecker.cs +++ b/MinecraftLaunch/Components/Checker/ResourceChecker.cs @@ -1,8 +1,8 @@ -using MinecraftLaunch.Extensions; -using System.Collections.Immutable; -using MinecraftLaunch.Classes.Interfaces; +using MinecraftLaunch.Classes.Interfaces; using MinecraftLaunch.Classes.Models.Game; using MinecraftLaunch.Components.Resolver; +using MinecraftLaunch.Extensions; +using System.Collections.Immutable; namespace MinecraftLaunch.Components.Checker; @@ -43,4 +43,4 @@ public async ValueTask CheckAsync() { return !MissingResources.Any(); } -} +} \ No newline at end of file diff --git a/MinecraftLaunch/Components/Converter/AccountJsonConverter.cs b/MinecraftLaunch/Components/Converter/AccountJsonConverter.cs index 25d6660..2358003 100644 --- a/MinecraftLaunch/Components/Converter/AccountJsonConverter.cs +++ b/MinecraftLaunch/Components/Converter/AccountJsonConverter.cs @@ -1,11 +1,12 @@ -using System.Text.Json; -using System.Text.Json.Serialization; -using MinecraftLaunch.Classes.Enums; +using MinecraftLaunch.Classes.Enums; using MinecraftLaunch.Classes.Models.Auth; +using System.Text.Json; +using System.Text.Json.Serialization; namespace MinecraftLaunch.Components.Converter; public sealed class AccountJsonConverter : JsonConverter { + public override bool CanConvert(Type typeToConvert) { return typeToConvert == typeof(Account); } @@ -58,10 +59,12 @@ public override void Write(Utf8JsonWriter writer, Account value, JsonSerializerO case OfflineAccount offlineAccount: writer.WriteNumber("Type", (int)AccountType.Offline); break; + case MicrosoftAccount microsoftAccount: writer.WriteNumber("Type", (int)AccountType.Microsoft); writer.WriteString("RefreshToken", microsoftAccount.RefreshToken); break; + case YggdrasilAccount yggdrasilAccount: writer.WriteNumber("Type", (int)AccountType.Yggdrasil); writer.WriteString("ClientToken", yggdrasilAccount.ClientToken); @@ -71,5 +74,4 @@ public override void Write(Utf8JsonWriter writer, Account value, JsonSerializerO writer.WriteEndObject(); } - } \ No newline at end of file diff --git a/MinecraftLaunch/Components/Downloader/ResourceDownloader.cs b/MinecraftLaunch/Components/Downloader/ResourceDownloader.cs index 2a3b7fc..2ff79c3 100644 --- a/MinecraftLaunch/Components/Downloader/ResourceDownloader.cs +++ b/MinecraftLaunch/Components/Downloader/ResourceDownloader.cs @@ -9,10 +9,11 @@ namespace MinecraftLaunch.Components.Downloader; public class ResourceDownloader( - DownloadRequest request, + DownloadRequest request, IEnumerable downloadEntries, MirrorDownloadSource downloadSource = default, CancellationTokenSource tokenSource = default) : IDownloader { + public event EventHandler ProgressChanged; public async ValueTask DownloadAsync() { @@ -68,8 +69,8 @@ await DownloadUitl.DownloadAsync(e, tokenSource: tokenSource).AsTask().ContinueW var transformManyBlock = new TransformManyBlock, IDownloadEntry>(chunk => chunk, new ExecutionDataflowBlockOptions()); - var linkOptions = new DataflowLinkOptions { - PropagateCompletion = true + var linkOptions = new DataflowLinkOptions { + PropagateCompletion = true }; transformManyBlock.LinkTo(transformBlock, linkOptions); diff --git a/MinecraftLaunch/Components/Fetcher/CurseForgeFetcher.cs b/MinecraftLaunch/Components/Fetcher/CurseForgeFetcher.cs index da67a66..9f2dc7a 100644 --- a/MinecraftLaunch/Components/Fetcher/CurseForgeFetcher.cs +++ b/MinecraftLaunch/Components/Fetcher/CurseForgeFetcher.cs @@ -1,12 +1,12 @@ -using System.Text; -using System.Text.Json; -using System.Text.Json.Nodes; -using System.Web; -using Flurl.Http; +using Flurl.Http; using MinecraftLaunch.Classes.Enums; -using MinecraftLaunch.Extensions; using MinecraftLaunch.Classes.Interfaces; using MinecraftLaunch.Classes.Models.Download; +using MinecraftLaunch.Extensions; +using System.Text; +using System.Text.Json; +using System.Text.Json.Nodes; +using System.Web; namespace MinecraftLaunch.Components.Fetcher; @@ -60,7 +60,7 @@ public async ValueTask> FetchAsync() { result.Add(ResolveFromJsonNode(resource)); } } catch (Exception) { } - + return result; } @@ -75,9 +75,9 @@ public async ValueTask> FetchAsync() { /// A ValueTask that represents the asynchronous operation. The task result contains an enumerable collection of CurseForge resources. public async ValueTask> SearchResourcesAsync( string searchFilter, - int classId = 6, + int classId = 6, int category = -1, - string gameVersion = null, + string gameVersion = null, LoaderType modLoaderType = LoaderType.Any) { var stringBuilder = new StringBuilder(BASE_API); stringBuilder.Append("/search?gameId=432"); @@ -87,7 +87,7 @@ public async ValueTask> SearchResourcesAsyn stringBuilder.Append($"modLoaderType={(int)modLoaderType}"); stringBuilder.Append($"gameVersion={gameVersion}"); stringBuilder.Append($"&searchFilter={HttpUtility.UrlEncode(searchFilter)}"); - + var jsonNode = (await stringBuilder.ToString() .WithHeader("x-api-key", _key) .GetStringAsync()) @@ -95,7 +95,7 @@ public async ValueTask> SearchResourcesAsyn return jsonNode.GetEnumerable("data").Select(ResolveFromJsonNode); } - + private CurseForgeResourceEntry ResolveFromJsonNode(JsonNode node) { var entry = node.Deserialize(); diff --git a/MinecraftLaunch/Components/Fetcher/JavaFetcher.cs b/MinecraftLaunch/Components/Fetcher/JavaFetcher.cs index 47ebaf7..17f6614 100644 --- a/MinecraftLaunch/Components/Fetcher/JavaFetcher.cs +++ b/MinecraftLaunch/Components/Fetcher/JavaFetcher.cs @@ -1,12 +1,11 @@ -using System.Diagnostics; -using MinecraftLaunch.Utilities; -using System.Runtime.Versioning; +using MinecraftLaunch.Classes.Interfaces; +using MinecraftLaunch.Classes.Models.Game; using MinecraftLaunch.Extensions; +using MinecraftLaunch.Utilities; using System.Collections.Immutable; +using System.Diagnostics; using System.Runtime.InteropServices; -using MinecraftLaunch.Classes.Interfaces; -using MinecraftLaunch.Classes.Models.Game; -using MinecraftLaunch.Classes.Enums; +using System.Runtime.Versioning; namespace MinecraftLaunch.Components.Fetcher; @@ -14,7 +13,9 @@ namespace MinecraftLaunch.Components.Fetcher; /// Fetches Java installations on the system. /// public sealed class JavaFetcher : IFetcher> { + #region Fields + [SupportedOSPlatform(nameof(OSPlatform.OSX))] private const string _macJavaHomePath = "/Library/Java/JavaVirtualMachines"; @@ -67,7 +68,7 @@ public sealed class JavaFetcher : IFetcher> { "android", ]; - #endregion + #endregion Fields /// /// Fetches the Java installations synchronously. @@ -203,8 +204,7 @@ private void FetchJavaw(DirectoryInfo directory, ref List results) { } } } - } - catch (UnauthorizedAccessException) { + } catch (UnauthorizedAccessException) { } } } \ No newline at end of file diff --git a/MinecraftLaunch/Components/Fetcher/ModrinthFetcher.cs b/MinecraftLaunch/Components/Fetcher/ModrinthFetcher.cs index 97b684c..4a100aa 100644 --- a/MinecraftLaunch/Components/Fetcher/ModrinthFetcher.cs +++ b/MinecraftLaunch/Components/Fetcher/ModrinthFetcher.cs @@ -1,11 +1,11 @@ using Flurl.Http; -using System.Text; -using System.Text.Json; -using MinecraftLaunch.Utilities; -using MinecraftLaunch.Extensions; using MinecraftLaunch.Classes.Enums; using MinecraftLaunch.Classes.Interfaces; using MinecraftLaunch.Classes.Models.Download; +using MinecraftLaunch.Extensions; +using MinecraftLaunch.Utilities; +using System.Text; +using System.Text.Json; namespace MinecraftLaunch.Components.Fetcher; @@ -50,8 +50,7 @@ public async ValueTask> SearchResourcesAsync( var facets = new List(); if (resourceType != null) { - facets.Add($"[\"project_type:{resourceType switch - { + facets.Add($"[\"project_type:{resourceType switch { ModrinthResourceType.ModPack => "modpack", ModrinthResourceType.Resourcepack => "resourcepack", _ => "mod" @@ -65,7 +64,7 @@ public async ValueTask> SearchResourcesAsync( if (facets.Any()) { stringBuilder.Append($"&facets=[{string.Join(',', facets)}]"); } - + var jNode = (await stringBuilder.ToString().GetStringAsync()).AsNode(); return jNode?.Select("hits")?.GetEnumerable() .Deserialize>(JsonConverterUtil.DefaultJsonOptions); diff --git a/MinecraftLaunch/Components/Installer/CompositionInstaller.cs b/MinecraftLaunch/Components/Installer/CompositionInstaller.cs index ff8329b..e751d15 100644 --- a/MinecraftLaunch/Components/Installer/CompositionInstaller.cs +++ b/MinecraftLaunch/Components/Installer/CompositionInstaller.cs @@ -1,5 +1,4 @@ - -using MinecraftLaunch.Classes.Models.Event; +using MinecraftLaunch.Classes.Models.Event; using MinecraftLaunch.Classes.Models.Game; using MinecraftLaunch.Classes.Models.Install; using MinecraftLaunch.Extensions; diff --git a/MinecraftLaunch/Components/Installer/FabricInstaller.cs b/MinecraftLaunch/Components/Installer/FabricInstaller.cs index 2186982..4ef84e9 100644 --- a/MinecraftLaunch/Components/Installer/FabricInstaller.cs +++ b/MinecraftLaunch/Components/Installer/FabricInstaller.cs @@ -1,9 +1,9 @@ using Flurl.Http; -using MinecraftLaunch.Extensions; -using MinecraftLaunch.Components.Resolver; +using MinecraftLaunch.Classes.Models.Download; using MinecraftLaunch.Classes.Models.Game; using MinecraftLaunch.Classes.Models.Install; -using MinecraftLaunch.Classes.Models.Download; +using MinecraftLaunch.Components.Resolver; +using MinecraftLaunch.Extensions; namespace MinecraftLaunch.Components.Installer; diff --git a/MinecraftLaunch/Components/Installer/ForgeInstaller.cs b/MinecraftLaunch/Components/Installer/ForgeInstaller.cs index f6e251d..9ad3200 100644 --- a/MinecraftLaunch/Components/Installer/ForgeInstaller.cs +++ b/MinecraftLaunch/Components/Installer/ForgeInstaller.cs @@ -1,12 +1,12 @@ using Flurl.Http; -using System.Text.Json; -using System.Diagnostics; -using System.IO.Compression; -using MinecraftLaunch.Extensions; -using MinecraftLaunch.Components.Resolver; +using MinecraftLaunch.Classes.Models.Download; using MinecraftLaunch.Classes.Models.Game; using MinecraftLaunch.Classes.Models.Install; -using MinecraftLaunch.Classes.Models.Download; +using MinecraftLaunch.Components.Resolver; +using MinecraftLaunch.Extensions; +using System.Diagnostics; +using System.IO.Compression; +using System.Text.Json; namespace MinecraftLaunch.Components.Installer; @@ -21,25 +21,24 @@ public sealed class ForgeInstaller(GameEntry inheritedFrom, ForgeInstallEntry in public override async ValueTask InstallAsync() { List highVersionForgeProcessors = default; - /* * Download Forge installation package */ var suffix = $"/net/minecraftforge/forge/{_installEntry.McVersion}-{_installEntry.ForgeVersion}/forge-{_installEntry .McVersion}-{_installEntry.ForgeVersion}-installer.jar"; - var host = MirrorDownloadManager.IsUseMirrorDownloadSource + var host = MirrorDownloadManager.IsUseMirrorDownloadSource ? _mirrorDownloadSource.Host : "https://files.minecraftforge.net/maven"; var packageUrl = $"{host}{suffix}"; - string packagePath = Path.Combine(Path.GetTempPath(), + string packagePath = Path.Combine(Path.GetTempPath(), Path.GetFileName(packageUrl)); var request = packageUrl.ToDownloadRequest(packagePath.ToFileInfo()); await request.DownloadAsync(x => { ReportProgress(x.ToPercentage(0.0d, 0.15d), - "Downloading Forge installation package", + "Downloading Forge installation package", TaskStatus.Running); }); @@ -108,7 +107,6 @@ await request.DownloadAsync(x => { .ToPath(); }); - highVersionForgeProcessors = installProfile["processors"] .Deserialize>() .Where(x => !(x.Sides.Count == 1 && x.Sides.Contains("server"))) @@ -156,7 +154,6 @@ await libraries.DownloadResourceEntrysAsync(_mirrorDownloadSource, x => { .ExtractTo(Path.Combine(forgeLibsFolder, fileName)); } - packageArchive.GetEntry($"maven/net/minecraftforge/forge/{forgeVersion}/forge-{forgeVersion}.jar")? .ExtractTo(Path.Combine(forgeLibsFolder, $"forge-{forgeVersion}.jar")); packageArchive.GetEntry($"maven/net/minecraftforge/forge/{forgeVersion}/forge-{forgeVersion}-universal.jar")? diff --git a/MinecraftLaunch/Components/Installer/InstallerBase.cs b/MinecraftLaunch/Components/Installer/InstallerBase.cs index 6c77d01..6b9b3ff 100644 --- a/MinecraftLaunch/Components/Installer/InstallerBase.cs +++ b/MinecraftLaunch/Components/Installer/InstallerBase.cs @@ -5,7 +5,9 @@ namespace MinecraftLaunch.Components.Installer; public abstract class InstallerBase : IInstaller { + public event EventHandler Completed; + public event EventHandler ProgressChanged; public abstract GameEntry InheritedFrom { get; } @@ -16,8 +18,8 @@ public abstract class InstallerBase : IInstaller { public void ReportCompleted() { Completed?.Invoke(this, EventArgs.Empty); } - + internal virtual void ReportProgress(double progress, string progressStatus, TaskStatus status) { 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 17b15b5..0b8af4d 100644 --- a/MinecraftLaunch/Components/Installer/NeoForgeInstaller.cs +++ b/MinecraftLaunch/Components/Installer/NeoForgeInstaller.cs @@ -1,5 +1,4 @@ - -using MinecraftLaunch.Classes.Models.Game; +using MinecraftLaunch.Classes.Models.Game; namespace MinecraftLaunch.Components.Installer; diff --git a/MinecraftLaunch/Components/Installer/OptifineInstaller.cs b/MinecraftLaunch/Components/Installer/OptifineInstaller.cs index 40b3044..3449653 100644 --- a/MinecraftLaunch/Components/Installer/OptifineInstaller.cs +++ b/MinecraftLaunch/Components/Installer/OptifineInstaller.cs @@ -1,13 +1,13 @@ using Flurl.Http; -using System.Text.Json; +using MinecraftLaunch.Classes.Models.Download; +using MinecraftLaunch.Classes.Models.Game; +using MinecraftLaunch.Classes.Models.Install; +using MinecraftLaunch.Components.Resolver; +using MinecraftLaunch.Extensions; using System.Diagnostics; using System.IO.Compression; +using System.Text.Json; using System.Text.Json.Serialization; -using MinecraftLaunch.Extensions; -using MinecraftLaunch.Components.Resolver; -using MinecraftLaunch.Classes.Models.Game; -using MinecraftLaunch.Classes.Models.Install; -using MinecraftLaunch.Classes.Models.Download; namespace MinecraftLaunch.Components.Installer; diff --git a/MinecraftLaunch/Components/Installer/QuiltInstaller.cs b/MinecraftLaunch/Components/Installer/QuiltInstaller.cs index 3ced728..1ae6e72 100644 --- a/MinecraftLaunch/Components/Installer/QuiltInstaller.cs +++ b/MinecraftLaunch/Components/Installer/QuiltInstaller.cs @@ -1,10 +1,10 @@ using Flurl.Http; -using System.Diagnostics; -using MinecraftLaunch.Extensions; -using MinecraftLaunch.Components.Resolver; +using MinecraftLaunch.Classes.Models.Download; using MinecraftLaunch.Classes.Models.Game; using MinecraftLaunch.Classes.Models.Install; -using MinecraftLaunch.Classes.Models.Download; +using MinecraftLaunch.Components.Resolver; +using MinecraftLaunch.Extensions; +using System.Diagnostics; namespace MinecraftLaunch.Components.Installer; @@ -27,7 +27,6 @@ public override async ValueTask InstallAsync() { .GetEnumerable("libraries"), InheritedFrom.GameFolderPath); - /* * Download dependent resources */ @@ -60,7 +59,6 @@ await libraries.DownloadResourceEntrysAsync(source, x => { File.WriteAllText(jsonFile.FullName, versionInfoNode.ToString()); ReportProgress(1.0d, "Installation is complete", TaskStatus.Canceled); return true; - } public static async ValueTask> EnumerableFromVersionAsync(string mcVersion) { diff --git a/MinecraftLaunch/Components/Installer/VanlliaInstaller.cs b/MinecraftLaunch/Components/Installer/VanlliaInstaller.cs index 900e6a1..c1e9d2f 100644 --- a/MinecraftLaunch/Components/Installer/VanlliaInstaller.cs +++ b/MinecraftLaunch/Components/Installer/VanlliaInstaller.cs @@ -1,11 +1,11 @@ using Flurl.Http; -using System.Text.Json; -using MinecraftLaunch.Extensions; using MinecraftLaunch.Classes.Interfaces; -using MinecraftLaunch.Components.Checker; -using MinecraftLaunch.Classes.Models.Install; using MinecraftLaunch.Classes.Models.Download; using MinecraftLaunch.Classes.Models.Game; +using MinecraftLaunch.Classes.Models.Install; +using MinecraftLaunch.Components.Checker; +using MinecraftLaunch.Extensions; +using System.Text.Json; namespace MinecraftLaunch.Components.Installer; diff --git a/MinecraftLaunch/Components/Launcher/ArgumentsBuilder.cs b/MinecraftLaunch/Components/Launcher/ArgumentsBuilder.cs index dca9b7c..9ff565c 100644 --- a/MinecraftLaunch/Components/Launcher/ArgumentsBuilder.cs +++ b/MinecraftLaunch/Components/Launcher/ArgumentsBuilder.cs @@ -1,152 +1,131 @@ -using MinecraftLaunch.Utilities; -using MinecraftLaunch.Extensions; +using MinecraftLaunch.Extensions; using MinecraftLaunch.Classes.Enums; -using MinecraftLaunch.Components.Resolver; using MinecraftLaunch.Classes.Models.Game; +using MinecraftLaunch.Components.Resolver; using MinecraftLaunch.Classes.Models.Launch; +using MinecraftLaunch.Components.Resolver.Arguments; using System.Collections.Immutable; -namespace MinecraftLaunch.Components.Launcher; +#if NET8_0 -internal sealed class ArgumentsBuilder(GameEntry gameEntity, LaunchConfig launchConfig) { - private GameEntry GameEntry => gameEntity; - - private LaunchConfig LaunchConfig => launchConfig; - - private IEnumerable DefaultAdvancedArguments => - ["-XX:-OmitStackTraceInFastThrow", - "-XX:-DontCompileHugeMethods", - "-Dfile.encoding=GB18030", - "-Dfml.ignoreInvalidMinecraftCertificates=true", - "-Dfml.ignorePatchDiscrepancies=true", - "-Djava.rmi.server.useCodebaseOnly=true", - "-Dcom.sun.jndi.rmi.object.trustURLCodebase=false", - "-Dcom.sun.jndi.cosnaming.object.trustURLCodebase=false"]; - - private IEnumerable DefaultGCArguments => - ["-XX:+UseG1GC", - "-XX:+UnlockExperimentalVMOptions", - "-XX:G1NewSizePercent=20", - "-XX:G1ReservePercent=20", - "-XX:MaxGCPauseMillis=50", - "-XX:G1HeapRegionSize=16m", - "-XX:-UseAdaptiveSizePolicy"]; +using System.Collections.Frozen; - public IEnumerable Build() { - foreach (string frontArgument in GetFrontArguments()) { - yield return frontArgument; - } +#endif - yield return GameEntry.MainClass; +namespace MinecraftLaunch.Components.Launcher; - foreach (string behindArgument in GetBehindArguments()) { - yield return behindArgument; +internal sealed class ArgumentsBuilder(GameEntry _gameEntity, LaunchConfig _launchConfig) { + public IEnumerable Build() { + var jvmArguments = JvmArgumentResolver.Resolve(_gameEntity.GameJsonEntry); + var gameArguments = GameArgumentResolver.Resolve(_gameEntity.GameJsonEntry); + + //合并父级核心参数 + if (_gameEntity.IsInheritedFrom) { + jvmArguments = JvmArgumentResolver + .Resolve(_gameEntity.InheritsFrom.GameJsonEntry) + .Union(jvmArguments); + + gameArguments = GameArgumentResolver + .Resolve(_gameEntity.InheritsFrom.GameJsonEntry) + .Union(gameArguments); } - } - public IEnumerable GetBehindArguments() { - var keyValuePairs = new Dictionary() { - { "${user_properties}", "{}" }, - { "${version_name}", GameEntry.Id.ToPath() }, - { "${auth_player_name}", LaunchConfig.Account.Name }, - { "${auth_session}", LaunchConfig.Account.AccessToken }, - { "${version_type}", LaunchConfig.LauncherName.ToPath() }, - { "${auth_uuid}", LaunchConfig.Account.Uuid.ToString("N") }, - { "${auth_access_token}", LaunchConfig.Account.AccessToken }, - { "${assets_root}", Path.Combine(GameEntry.GameFolderPath, "assets").ToPath() }, - { "${game_assets}", Path.Combine(GameEntry.GameFolderPath, "assets").ToPath() }, - { "${assets_index_name}", Path.GetFileNameWithoutExtension(GameEntry.AssetsIndexJsonPath) }, - { "${user_type}", LaunchConfig.Account.Type.Equals(AccountType.Microsoft) ? "MSA" : "Mojang" }, - { "${game_directory}", GameEntry.OfVersionDirectoryPath(LaunchConfig.IsEnableIndependencyCore).ToPath() }, - }; + var jvmArgumentsReplace = new Dictionary() + { + { "${launcher_version}", "4" }, + { "${launcher_name}", "MinecraftLaunch" }, - var args = new List(GameEntry.BehindArguments); + { "${classpath}", GetClasspath().ToPath() }, + { "${natives_directory}", GetNativesDirectory() }, + { "${classpath_separator}", Path.PathSeparator.ToString() }, + { "${library_directory}", _gameEntity.ToLibrariesPath().ToPath() }, + { + "${version_name}", _gameEntity.IsInheritedFrom + ? _gameEntity.InheritsFrom.Id + : _gameEntity.Id + }, + }; - if (LaunchConfig.GameWindowConfig != null) { - args.Add($"--width {LaunchConfig.GameWindowConfig.Width}"); - args.Add($"--height {LaunchConfig.GameWindowConfig.Height}"); - if (LaunchConfig.GameWindowConfig.IsFullscreen) { - args.Add("--fullscreen"); - } + var gameArgumentsReplace = new Dictionary() { + { "${user_properties}", "{}" }, + { "${auth_player_name}", _launchConfig.Account.Name }, + { "${auth_session}", _launchConfig.Account.AccessToken }, + { "${auth_uuid}", _launchConfig.Account.Uuid.ToString("N") }, + { "${auth_access_token}", _launchConfig.Account.AccessToken }, + { "${user_type}", _launchConfig.Account.Type.Equals(AccountType.Microsoft) ? "MSA" : "Mojang" }, + + { "${game_assets}", Path.Combine(_gameEntity.GameFolderPath, "assets").ToPath() }, + { "${assets_root}", Path.Combine(_gameEntity.GameFolderPath, "assets").ToPath() }, + { "${assets_index_name}", Path.GetFileNameWithoutExtension(_gameEntity.AssetsIndexJsonPath) }, + { "${game_directory}", _gameEntity.ToVersionDirectoryPath(_launchConfig.IsEnableIndependencyCore).ToPath() }, + + { "${version_name}", _gameEntity.Id.ToPath() }, + { "${version_type}", _launchConfig.LauncherName.ToPath() }, + }; + +#if NET8_0 + var fastJvmParametersReplace = jvmArgumentsReplace.ToFrozenDictionary(); + var fastGameParametersReplace = gameArgumentsReplace.ToFrozenDictionary(); +#else + var fastJvmParametersReplace = jvmArgumentsReplace.ToImmutableDictionary(); + var fastGameParametersReplace = gameArgumentsReplace.ToImmutableDictionary(); +#endif + + yield return $"-Dlog4j2.formatMsgNoLookups=true"; + yield return $"-Xms{_launchConfig.JvmConfig.MinMemory}M"; + yield return $"-Xmx{_launchConfig.JvmConfig.MaxMemory}M"; + yield return $"-Dminecraft.client.jar={_gameEntity.JarPath.ToPath()}"; + + foreach (var arg in JvmArgumentResolver.GetEnvironmentJVMArguments()) { + yield return arg; } - if (LaunchConfig.ServerConfig != null && !string.IsNullOrEmpty(LaunchConfig.ServerConfig.Ip) - && LaunchConfig.ServerConfig.Port != 0) { - args.Add($"--server {LaunchConfig.ServerConfig.Ip}"); - args.Add($"--port {LaunchConfig.ServerConfig.Port}"); + foreach (var arg in jvmArguments) { + yield return arg.Replace(fastJvmParametersReplace); } - return args.Select(arg => arg.Replace(keyValuePairs)); - } - - public IEnumerable GetFrontArguments() { - var keyValuePairs = new Dictionary() { - { "${launcher_name}", "MinecraftLaunch" }, - { "${launcher_version}", "3" }, - { "${classpath_separator}", Path.PathSeparator.ToString() }, - { "${classpath}", GetClasspath().ToPath() }, - { "${client}", GameEntry.JarPath.ToPath() }, - { "${min_memory}", LaunchConfig.JvmConfig.MinMemory.ToString() }, - { "${max_memory}", LaunchConfig.JvmConfig.MaxMemory.ToString() }, - { "${library_directory}", Path.Combine(GameEntry.GameFolderPath, "libraries").ToPath() }, - { "${version_name}", GameEntry.InheritsFrom is null ? GameEntry.Id : GameEntry.InheritsFrom.Id }, - { "${natives_directory}", GetNativesDirectory() } - }; + yield return _gameEntity.MainClass; - if (!Directory.Exists(keyValuePairs["${natives_directory}"])) { - Directory.CreateDirectory(keyValuePairs["${natives_directory}"].Trim('"')); + foreach (var arg in gameArguments) { + yield return arg.Replace(fastGameParametersReplace); } - var args = new List { - "-Xmn${min_memory}m", - "-Xmx${max_memory}m", - "-Dminecraft.client.jar=${client}", - "-Dlog4j2.formatMsgNoLookups=true" - }; + //Custom args + if (_launchConfig.GameWindowConfig != null) { + yield return $"--width {_launchConfig.GameWindowConfig.Width}"; + yield return $"--height {_launchConfig.GameWindowConfig.Height}"; - args.AddRange(GetEnvironmentJvmArguments()); - args.AddRange(LaunchConfig.JvmConfig.GCArguments ?? DefaultGCArguments); - args.AddRange(LaunchConfig.JvmConfig.AdvancedArguments ?? DefaultAdvancedArguments); - args.AddRange(GameEntry.FrontArguments); + if (_launchConfig.GameWindowConfig.IsFullscreen) yield return "--fullscreen"; + } - foreach (string arg in args) { - yield return arg.Replace(keyValuePairs); + if (_launchConfig.ServerConfig != null + && _launchConfig.ServerConfig.Port != 0 + && !string.IsNullOrEmpty(_launchConfig.ServerConfig.Ip)) { + yield return $"--server {_launchConfig.ServerConfig.Ip}"; + yield return $"--port {_launchConfig.ServerConfig.Port}"; } + } private string GetClasspath() { - var libraries = new LibrariesResolver(gameEntity) - .GetLibraries().ToImmutableArray(); + var libraries = new LibrariesResolver(_gameEntity) + .GetLibraries() + .Where(x => x is not null) + .ToImmutableArray(); var classPath = string.Join(Path.PathSeparator, libraries.Select(lib => lib?.Path)); - if (!string.IsNullOrEmpty(gameEntity.JarPath)) { - classPath += Path.PathSeparator + gameEntity.JarPath; + if (!string.IsNullOrEmpty(_gameEntity.JarPath)) { + classPath += $"{Path.PathSeparator}{_gameEntity.JarPath}"; } return classPath; } private string GetNativesDirectory() { - return LaunchConfig.NativesFolder != null && LaunchConfig.NativesFolder.Exists - ? LaunchConfig.NativesFolder.FullName.ToString() - : Path.Combine(GameEntry.OfVersionDirectoryPath(LaunchConfig.IsEnableIndependencyCore), "natives").ToPath(); - } - - private static IEnumerable GetEnvironmentJvmArguments() { - string platformName = EnvironmentUtil.GetPlatformName(); - if (!(platformName == "windows")) { - if (platformName == "osx") - yield return "-XstartOnFirstThread"; - } else { - yield return "-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump"; - if (Environment.OSVersion.Version.Major == 10) { - yield return "-Dos.name=\"Windows 10\""; - yield return "-Dos.version=10.0"; - } - } - if (EnvironmentUtil.Arch == "32") - yield return "-Xss1M"; + return _launchConfig.NativesFolder != null && _launchConfig.NativesFolder.Exists + ? _launchConfig.NativesFolder.FullName.ToString() + : Path.Combine(_gameEntity.ToVersionDirectoryPath(_launchConfig.IsEnableIndependencyCore), "natives").ToPath(); } } \ No newline at end of file diff --git a/MinecraftLaunch/Components/Launcher/Launcher.cs b/MinecraftLaunch/Components/Launcher/Launcher.cs index 8b1b9cd..bb17307 100644 --- a/MinecraftLaunch/Components/Launcher/Launcher.cs +++ b/MinecraftLaunch/Components/Launcher/Launcher.cs @@ -1,11 +1,12 @@ -using System.Diagnostics; -using MinecraftLaunch.Utilities; -using MinecraftLaunch.Extensions; -using MinecraftLaunch.Classes.Interfaces; -using MinecraftLaunch.Components.Watcher; -using MinecraftLaunch.Components.Resolver; +using MinecraftLaunch.Classes.Interfaces; using MinecraftLaunch.Classes.Models.Game; using MinecraftLaunch.Classes.Models.Launch; +using MinecraftLaunch.Components.Resolver; +using MinecraftLaunch.Components.Watcher; +using MinecraftLaunch.Extensions; +using MinecraftLaunch.Utilities; +using System.Collections.Immutable; +using System.Diagnostics; namespace MinecraftLaunch.Components.Launcher; @@ -38,13 +39,13 @@ public Launcher(IGameResolver resolver, LaunchConfig config) { /// The ID of the game to launch. /// A ValueTask that represents the asynchronous operation. The task result contains a . public async ValueTask LaunchAsync(string id) { - var gameEntry = GameResolver.GetGameEntity(id); - var versionPath = gameEntry.OfVersionDirectoryPath(LaunchConfig.IsEnableIndependencyCore); + var gameEntry = GameResolver.GetGameEntity(id); + var versionPath = gameEntry.ToVersionDirectoryPath(LaunchConfig.IsEnableIndependencyCore); _argumentsBuilder = new(gameEntry, LaunchConfig); - - var arguments = _argumentsBuilder.Build(); - var process = CreateProcess(arguments, versionPath); + var arguments = _argumentsBuilder.Build().ToImmutableArray(); + var process = CreateProcess(arguments, versionPath); + Console.WriteLine(string.Join(Environment.NewLine, arguments)); LibrariesResolver librariesResolver = new(gameEntry); await ExtractNatives(versionPath, librariesResolver); return new GameProcessWatcher(process, arguments); diff --git a/MinecraftLaunch/Components/Resolver/Arguments/GameArgumentResolver.cs b/MinecraftLaunch/Components/Resolver/Arguments/GameArgumentResolver.cs new file mode 100644 index 0000000..6feca7f --- /dev/null +++ b/MinecraftLaunch/Components/Resolver/Arguments/GameArgumentResolver.cs @@ -0,0 +1,36 @@ +using MinecraftLaunch.Extensions; +using MinecraftLaunch.Classes.Models.Game; +using System.Collections.Immutable; +using System.Text.Json; + +namespace MinecraftLaunch.Components.Resolver.Arguments; + +/// +/// 游戏参数解析器 +/// +internal sealed class GameArgumentResolver { + /// + /// 解析参数 + /// + /// + public static IEnumerable Resolve(GameJsonEntry gameJsonEntry) { + if (!string.IsNullOrEmpty(gameJsonEntry.MinecraftArguments)) { + foreach (var arg in gameJsonEntry.MinecraftArguments.Split(' ').GroupArguments()) { + yield return arg; + } + } + + if (gameJsonEntry.Arguments.Game is null) { + yield break; + } + + var game = gameJsonEntry.Arguments.Game + .Where(x => x.ValueKind is JsonValueKind.String) + .Select(x => x.GetString().ToPath()) + .GroupArguments(); + + foreach (var item in game.ToImmutableArray()) { + yield return item; + } + } +} \ No newline at end of file diff --git a/MinecraftLaunch/Components/Resolver/Arguments/JvmArgumentResolver.cs b/MinecraftLaunch/Components/Resolver/Arguments/JvmArgumentResolver.cs new file mode 100644 index 0000000..d045f00 --- /dev/null +++ b/MinecraftLaunch/Components/Resolver/Arguments/JvmArgumentResolver.cs @@ -0,0 +1,67 @@ +using System.Text.Json; +using MinecraftLaunch.Utilities; +using MinecraftLaunch.Extensions; +using MinecraftLaunch.Classes.Models.Game; + +namespace MinecraftLaunch.Components.Resolver.Arguments; + +/// +/// Jvm 虚拟机参数解析器 +/// +internal sealed class JvmArgumentResolver { + public static IEnumerable Resolve(GameJsonEntry gameJsonEntry) { + var jvm = new List(); + + if (gameJsonEntry.Arguments.Jvm is null) { + yield return "-Djava.library.path=${natives_directory}"; + yield return "-Dminecraft.launcher.brand=${launcher_name}"; + yield return "-Dminecraft.launcher.version=${launcher_version}"; + yield return "-cp ${classpath}"; + + yield break; + } + + foreach (var arg in gameJsonEntry.Arguments.Jvm) { + if (arg.ValueKind is JsonValueKind.String) { + var argValue = arg.GetString().Trim(); + + if (argValue.Contains(' ')) { + jvm.AddRange(argValue.Split(' ')); + } else { + jvm.Add(argValue); + } + } + } + + foreach (var arg in jvm.GroupArguments()) { + yield return arg; + } + + //有些沟槽带加载器的版本的 Json 里可能没有 -cp 键,加一个判断以防启动失败 + if (!jvm.Contains("-cp")) { + yield return "-cp ${classpath}"; + } + } + + /// + /// 获取虚拟机环境参数 + /// + /// + public static IEnumerable GetEnvironmentJVMArguments() { + switch (EnvironmentUtil.GetPlatformName()) { + case "windows": + yield return "-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump"; + if (System.Environment.OSVersion.Version.Major == 10) { + yield return "-Dos.name=\"Windows 10\""; + yield return "-Dos.version=10.0"; + } + break; + case "osx": + yield return "-XstartOnFirstThread"; + break; + } + + if (EnvironmentUtil.Arch == "32") + yield return "-Xss1M"; + } +} \ No newline at end of file diff --git a/MinecraftLaunch/Components/Resolver/AssetsResolver.cs b/MinecraftLaunch/Components/Resolver/AssetsResolver.cs index 4c55842..8cb96fb 100644 --- a/MinecraftLaunch/Components/Resolver/AssetsResolver.cs +++ b/MinecraftLaunch/Components/Resolver/AssetsResolver.cs @@ -1,7 +1,6 @@ -using System.Text.Json; +using MinecraftLaunch.Classes.Models.Game; using MinecraftLaunch.Extensions; -using MinecraftLaunch.Classes.Interfaces; -using MinecraftLaunch.Classes.Models.Game; +using System.Text.Json; namespace MinecraftLaunch.Components.Resolver; @@ -9,19 +8,20 @@ namespace MinecraftLaunch.Components.Resolver; /// Minecraft 资源材质库解析器 /// internal sealed class AssetsResolver(GameEntry entity) { + public AssetEntry GetAssetIndexJson() { - var assetIndex = (File.ReadAllText(entity.IsInheritedFrom - ? entity.InheritsFrom.OfVersionJsonPath() - : entity.OfVersionJsonPath())) + var assetIndex = (File.ReadAllText(entity.IsInheritedFrom + ? entity.InheritsFrom.ToVersionJsonPath() + : entity.ToVersionJsonPath())) .AsNode() .Select("assetIndex") .Deserialize(); var assetIndexFilePath = entity.IsInheritedFrom - ? entity.InheritsFrom.AssetsIndexJsonPath + ? entity.InheritsFrom.AssetsIndexJsonPath : entity.AssetsIndexJsonPath; - if(assetIndexFilePath is null) { + if (assetIndexFilePath is null) { return default!; } diff --git a/MinecraftLaunch/Components/Resolver/CurseforgeModpacksResolver.cs b/MinecraftLaunch/Components/Resolver/CurseforgeModpacksResolver.cs index 31634ab..147e853 100644 --- a/MinecraftLaunch/Components/Resolver/CurseforgeModpacksResolver.cs +++ b/MinecraftLaunch/Components/Resolver/CurseforgeModpacksResolver.cs @@ -1,5 +1,4 @@ namespace MinecraftLaunch.Components.Resolver; public sealed class CurseforgeModpacksResolver { - } \ No newline at end of file diff --git a/MinecraftLaunch/Components/Resolver/GameCrashAnalyzer.cs b/MinecraftLaunch/Components/Resolver/GameCrashResolver.cs similarity index 99% rename from MinecraftLaunch/Components/Resolver/GameCrashAnalyzer.cs rename to MinecraftLaunch/Components/Resolver/GameCrashResolver.cs index 245e366..8649f2f 100644 --- a/MinecraftLaunch/Components/Resolver/GameCrashAnalyzer.cs +++ b/MinecraftLaunch/Components/Resolver/GameCrashResolver.cs @@ -1,6 +1,6 @@ using MinecraftLaunch.Classes.Enums; -using System.Text.RegularExpressions; using MinecraftLaunch.Classes.Models.Game; +using System.Text.RegularExpressions; namespace MinecraftLaunch.Components.Resolver; @@ -8,6 +8,7 @@ namespace MinecraftLaunch.Components.Resolver; /// 游戏日志解析器 /// public sealed partial class GameLogResolver { + [GeneratedRegex("(20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d")] private partial Regex TimeRegex(); diff --git a/MinecraftLaunch/Components/Resolver/GameResolver.cs b/MinecraftLaunch/Components/Resolver/GameResolver.cs index f7a28c1..3de64c2 100644 --- a/MinecraftLaunch/Components/Resolver/GameResolver.cs +++ b/MinecraftLaunch/Components/Resolver/GameResolver.cs @@ -1,10 +1,10 @@ -using System.Text.Json; -using MinecraftLaunch.Utilities; -using MinecraftLaunch.Extensions; -using MinecraftLaunch.Classes.Interfaces; +using MinecraftLaunch.Classes.Interfaces; +using MinecraftLaunch.Classes.Models.Exceptions; using MinecraftLaunch.Classes.Models.Game; using MinecraftLaunch.Classes.Models.Launch; -using MinecraftLaunch.Classes.Models.Exceptions; +using MinecraftLaunch.Extensions; +using MinecraftLaunch.Utilities; +using System.Text.Json; namespace MinecraftLaunch.Components.Resolver; @@ -17,7 +17,7 @@ public sealed class GameResolver() : IGameResolver { public GameResolver(string path) : this() { Root = new(path); } - + /// /// 获取特定游戏实体信息 /// @@ -32,18 +32,19 @@ public GameEntry GetGameEntity(string id) { var gameEntity = new GameEntry { Id = entity.Id, Type = entity.Type, - GameFolderPath = Root.FullName, + GameJsonEntry = entity, IsInheritedFrom = false, MainClass = entity.MainClass, + GameFolderPath = Root.FullName, MainLoaderType = entity.GetGameLoaderType(), JavaVersion = entity.JavaVersion?.GetInt32("majorVersion") ?? 8, }; var assetsIndexFile = Path.Combine(Root.FullName, "assets", "indexes", $"{entity.AssetIndex?.Id}.json"); - var jarFile = Path.Combine(gameEntity.OfVersionDirectoryPath(), + var jarFile = Path.Combine(gameEntity.ToVersionDirectoryPath(), $"{id}.jar"); - gameEntity.JarPath = jarFile; + gameEntity.JarPath = jarFile.CheckAndSet(); gameEntity.AssetsIndexJsonPath = assetsIndexFile; if (!string.IsNullOrEmpty(entity.InheritsFrom)) { var inheritsFrom = GetGameEntity(entity.InheritsFrom); @@ -57,32 +58,32 @@ public GameEntry GetGameEntity(string id) { gameEntity.AssetsIndexJsonPath = inheritsFrom.AssetsIndexJsonPath; } - if (entity.MinecraftArguments != null) { - gameEntity.BehindArguments = HandleMinecraftArguments(entity.MinecraftArguments); - } - - if (entity.Arguments is { Game: not null }) { - IEnumerable behindArguments; - if (gameEntity.BehindArguments != null) { - behindArguments = gameEntity.BehindArguments.Union(HandleGameArguments(entity.Arguments)); - } else { - IEnumerable enumerable = HandleGameArguments(entity.Arguments); - behindArguments = enumerable; - } - gameEntity.BehindArguments = behindArguments; - } - - if (entity.Arguments is { Jvm: not null }) { - gameEntity.FrontArguments = HandleJvmArguments(entity.Arguments); - } else { - gameEntity.FrontArguments = ["-Djava.library.path=${natives_directory}", - "-Dminecraft.launcher.brand=${launcher_name}", - "-Dminecraft.launcher.version=${launcher_version}", - "-cp ${classpath}"]; - } + //if (entity.MinecraftArguments != null) { + // gameEntity.BehindArguments = HandleMinecraftArguments(entity.MinecraftArguments); + //} + + //if (entity.Arguments is { Game: not null }) { + // IEnumerable behindArguments; + // if (gameEntity.BehindArguments != null) { + // behindArguments = gameEntity.BehindArguments.Union(HandleGameArguments(entity.Arguments)); + // } else { + // IEnumerable enumerable = HandleGameArguments(entity.Arguments); + // behindArguments = enumerable; + // } + // gameEntity.BehindArguments = behindArguments; + //} + + //if (entity.Arguments is { Jvm: not null }) { + // gameEntity.FrontArguments = HandleJvmArguments(entity.Arguments); + //} else { + // gameEntity.FrontArguments = ["-Djava.library.path=${natives_directory}", + // "-Dminecraft.launcher.brand=${launcher_name}", + // "-Dminecraft.launcher.version=${launcher_version}", + // "-cp ${classpath}"]; + //} TryGetIsVanillaAndVersion(ref gameEntity, entity, gameEntity - .OfVersionJsonPath()); + .ToVersionJsonPath()); return gameEntity; } @@ -97,13 +98,12 @@ public IEnumerable GetGameEntitys() { if (!versionsPath.Exists) { versionsPath.Create(); } - + foreach (var item in versionsPath.EnumerateDirectories()) { try { entry = GetGameEntity(item.Name); - } - catch (Exception) { } - + } catch (Exception) { } + if (entry is null) { continue; } @@ -121,8 +121,7 @@ public GameJsonEntry Resolve(string id) { try { var json = File.ReadAllText(path); return json.Deserialize(GameJsonEntryContext.Default.GameJsonEntry)!; - } - catch { + } catch { throw new GameResolveFailedException($"[{id}]解析失败"); } } @@ -177,7 +176,7 @@ bool IsVanilla(GameJsonEntry jsonEntity) { var hasTweakClassArgument = jsonEntity.Arguments?.Game ?.Any(e => e.ValueKind.Equals(JsonValueKind.String) - && e.GetString().Equals("--tweakClass")) ?? false; + && e.GetString().Equals("--tweakClass")) ?? false; return string.IsNullOrEmpty(jsonEntity.InheritsFrom) && isMainClassValid diff --git a/MinecraftLaunch/Components/Resolver/LauncherAccountReslver.cs b/MinecraftLaunch/Components/Resolver/LauncherAccountReslver.cs index 4dc254c..1717a38 100644 --- a/MinecraftLaunch/Components/Resolver/LauncherAccountReslver.cs +++ b/MinecraftLaunch/Components/Resolver/LauncherAccountReslver.cs @@ -1,9 +1,8 @@ -using System.Text; -using MinecraftLaunch.Classes.Interfaces; using MinecraftLaunch.Classes.Models.Auth; using MinecraftLaunch.Classes.Models.Game; using MinecraftLaunch.Extensions; using MinecraftLaunch.Utilities; +using System.Text; namespace MinecraftLaunch.Components.Resolver; @@ -15,26 +14,26 @@ namespace MinecraftLaunch.Components.Resolver; /// public sealed class LauncherAccountReslver(string rootPath, Guid clientToken = default) { private readonly Guid _clientToken = clientToken; - private readonly string _accountPath = rootPath.OfLauncherAccountPath(); - + private readonly string _accountPath = rootPath.ToLauncherAccountPath(); + public LauncherAccountEntry LauncherAccount { get; set; } - + public LauncherAccountEntry Resolve(string str = default) { if (File.Exists(_accountPath)) { var launcherAccountJson = File.ReadAllText(_accountPath, Encoding.UTF8); LauncherAccount = launcherAccountJson.Deserialize(LauncherAccountEntryContext .Default.LauncherAccountEntry); - + return LauncherAccount; } - + var launcherAccount = new LauncherAccountEntry { Accounts = new(), MojangClientToken = _clientToken.ToString("N") }; - + LauncherAccount = launcherAccount; - string profileJson = LauncherAccount.Serialize(typeof(LauncherProfileEntry), + string profileJson = LauncherAccount.Serialize(typeof(LauncherProfileEntry), new LauncherProfileEntryContext(JsonConverterUtil.DefaultJsonOptions)); if (!Directory.Exists(rootPath)) { @@ -44,16 +43,15 @@ public LauncherAccountEntry Resolve(string str = default) { File.WriteAllText(_accountPath, profileJson); return LauncherAccount; } - + public void Save() { - var launcherProfileJson = LauncherAccount.Serialize(typeof(LauncherAccountEntry), + var launcherProfileJson = LauncherAccount.Serialize(typeof(LauncherAccountEntry), new LauncherAccountEntryContext(JsonConverterUtil.DefaultJsonOptions)); - + File.WriteAllText(_accountPath, launcherProfileJson); } - - public bool Remove(Guid id) - { + + public bool Remove(Guid id) { var result = Find(id); if (!result.HasValue) { return false; @@ -63,7 +61,7 @@ public bool Remove(Guid id) if (value == default) { return false; } - + return LauncherAccount.Accounts.Remove(key); } @@ -75,14 +73,14 @@ public bool Select(string uuid) { LauncherAccount.ActiveAccountLocalId = uuid; return true; } - + public Guid Add(string uuid, AccountEntry account) { if (LauncherAccount == null || LauncherAccount.Accounts?.ContainsKey(uuid) == true) { return default; } var oldRecord = LauncherAccount.Accounts - !.FirstOrDefault(a => + !.FirstOrDefault(a => a.Value.MinecraftProfile.Uuid == account.MinecraftProfile.Uuid).Value; if (oldRecord != null) { @@ -93,14 +91,13 @@ public Guid Add(string uuid, AccountEntry account) { if (findResult is { Key: not null, Value: not null }) { LauncherAccount.Accounts[findResult.Value.Key] = account; return account.Id; - } - else { + } else { Guid newId = account.Id == default ? Guid.NewGuid() : account.Id; LauncherAccount.Accounts.Add(uuid, account); return newId; } } - + public KeyValuePair? Find(Guid id) { return LauncherAccount?.Accounts?.FirstOrDefault(a => a.Value.Id == id); } diff --git a/MinecraftLaunch/Components/Resolver/LauncherProfileResolver.cs b/MinecraftLaunch/Components/Resolver/LauncherProfileResolver.cs index 59764b1..aaa8ec2 100644 --- a/MinecraftLaunch/Components/Resolver/LauncherProfileResolver.cs +++ b/MinecraftLaunch/Components/Resolver/LauncherProfileResolver.cs @@ -1,8 +1,7 @@ -using System.Text; -using MinecraftLaunch.Utilities; -using MinecraftLaunch.Extensions; -using MinecraftLaunch.Classes.Interfaces; using MinecraftLaunch.Classes.Models.Game; +using MinecraftLaunch.Extensions; +using MinecraftLaunch.Utilities; +using System.Text; namespace MinecraftLaunch.Components.Resolver; @@ -14,27 +13,27 @@ namespace MinecraftLaunch.Components.Resolver; /// public sealed class LauncherProfileResolver(string rootPath, Guid clientToken = default) { private readonly Guid _clientToken = clientToken; - private readonly string _proFilePath = rootPath.OfLauncherProfilePath(); + private readonly string _proFilePath = rootPath.ToLauncherProfilePath(); public LauncherProfileEntry LauncherProfile { get; set; } - + public void SaveProfile() { - var launcherProfileJson = LauncherProfile.Serialize(typeof(LauncherProfileEntry), + var launcherProfileJson = LauncherProfile.Serialize(typeof(LauncherProfileEntry), new LauncherProfileEntryContext(JsonConverterUtil.DefaultJsonOptions)); - + File.WriteAllText(_proFilePath, launcherProfileJson); } public bool HasProfile(string name) { return LauncherProfile.Profiles.Any(x => x.Value.Name.Equals(name, StringComparison.Ordinal)); } - + public bool RemoveProfile(string name) { return LauncherProfile.Profiles.Remove(name); } public GameProfileEntry GetProfile(string name) { - var profile = LauncherProfile.Profiles.FirstOrDefault(pe => + var profile = LauncherProfile.Profiles.FirstOrDefault(pe => pe.Value.Name.Equals(name, StringComparison.Ordinal)).Value; if (profile == null) { @@ -44,8 +43,8 @@ public GameProfileEntry GetProfile(string name) { profile.Resolution ??= new ResolutionEntry(); return profile; } - - public bool AddProfile(GameProfileEntry gameProfile) { + + public bool AddProfile(GameProfileEntry gameProfile) { return LauncherProfile.Profiles.TryAdd(gameProfile.Name, gameProfile); } @@ -56,7 +55,7 @@ public LauncherProfileEntry Resolve(string str = default) { .Default.LauncherProfileEntry); return LauncherProfile; } - + var launcherProfile = new LauncherProfileEntry { Profiles = new(), ClientToken = _clientToken.ToString("D"), @@ -65,16 +64,16 @@ public LauncherProfileEntry Resolve(string str = default) { Name = "下北泽" }, }; - + LauncherProfile = launcherProfile; - string profileJson = LauncherProfile.Serialize(typeof(LauncherProfileEntry), + string profileJson = LauncherProfile.Serialize(typeof(LauncherProfileEntry), new LauncherProfileEntryContext(JsonConverterUtil.DefaultJsonOptions)); if (!Directory.Exists(rootPath)) { Directory.CreateDirectory(rootPath); } - File.WriteAllText(_proFilePath, profileJson); + File.WriteAllText(_proFilePath, profileJson); return LauncherProfile; } } \ No newline at end of file diff --git a/MinecraftLaunch/Components/Resolver/LibrariesResolver.cs b/MinecraftLaunch/Components/Resolver/LibrariesResolver.cs index 4c78b24..665afe2 100644 --- a/MinecraftLaunch/Components/Resolver/LibrariesResolver.cs +++ b/MinecraftLaunch/Components/Resolver/LibrariesResolver.cs @@ -1,11 +1,10 @@ -using System.Text.Json; -using System.Text.Json.Nodes; -using MinecraftLaunch.Utilities; -using MinecraftLaunch.Extensions; -using MinecraftLaunch.Classes.Interfaces; +using MinecraftLaunch.Classes.Interfaces; using MinecraftLaunch.Classes.Models.Game; -using MinecraftLaunch.Classes.Enums; +using MinecraftLaunch.Extensions; +using MinecraftLaunch.Utilities; using System.Diagnostics; +using System.Text.Json; +using System.Text.Json.Nodes; namespace MinecraftLaunch.Components.Resolver; @@ -41,7 +40,7 @@ public LibraryEntry Resolve(JsonNode libNode) { } public IEnumerable GetLibraries() { - var jsonPath = Path.Combine(GameEntry.OfVersionJsonPath()); + var jsonPath = Path.Combine(GameEntry.ToVersionJsonPath()); var libsNode = File.ReadAllText(jsonPath).AsNode() .GetEnumerable("libraries"); @@ -82,7 +81,7 @@ public static string FormatLibraryNameToRelativePath(string name) { private JarEntry GetJarEntry() { var jsonClient = File.ReadAllText(GameEntry - .OfVersionJsonPath()).AsNode()? + .ToVersionJsonPath()).AsNode()? .Select("downloads")? .Select("client"); @@ -133,9 +132,11 @@ private bool GetLibraryEnable(IEnumerable rules) { case "windows": windows = true; break; + case "linux": linux = true; break; + case "osx": osx = true; break; @@ -152,9 +153,11 @@ private bool GetLibraryEnable(IEnumerable rules) { case "windows": windows = false; break; + case "linux": linux = false; break; + case "osx": osx = false; break; diff --git a/MinecraftLaunch/Components/Resolver/ModResolver.cs b/MinecraftLaunch/Components/Resolver/ModResolver.cs index f96e05e..e025086 100644 --- a/MinecraftLaunch/Components/Resolver/ModResolver.cs +++ b/MinecraftLaunch/Components/Resolver/ModResolver.cs @@ -1,8 +1,7 @@ -using System.IO.Compression; +using MinecraftLaunch.Classes.Models.Game; using MinecraftLaunch.Extensions; using System.Collections.Immutable; -using MinecraftLaunch.Classes.Interfaces; -using MinecraftLaunch.Classes.Models.Game; +using System.IO.Compression; namespace MinecraftLaunch.Components.Resolver; @@ -29,8 +28,7 @@ public ModEntry Resolve(string str) { } return result; - } - catch (Exception) { + } catch (Exception) { return null; } } @@ -38,7 +36,7 @@ public ModEntry Resolve(string str) { public Task> LoadAllAsync() { List entries = new(); var mods = Directory.EnumerateFiles(_gameEntry - .OfModDirectorypath()); + .ToModDirectorypath()); Parallel.ForEach(mods, path => { entries.Add(Resolve(path)); @@ -57,8 +55,7 @@ public static bool Switch(ModEntry entry, bool isEnable) { try { File.Move(rawFilePath, entry.Path); return true; - } - catch (Exception) { + } catch (Exception) { return false; } } @@ -80,8 +77,7 @@ private void OfLegacyForgeModEntry(string text, ref ModEntry entry) { entry.Authors = (jsonNode["authorList"] ?? jsonNode["authors"]) .GetEnumerable() .ToImmutableArray(); - } - catch (Exception) { + } catch (Exception) { entry.IsError = true; } } @@ -99,8 +95,7 @@ private void OfFabricModEntry(ZipArchive zipArchive, ref ModEntry entry) { entry.Authors = jsonNode["authors"] .GetEnumerable() .ToImmutableArray(); - } - catch (Exception) { + } catch (Exception) { entry.IsError = true; } } @@ -133,7 +128,7 @@ private void OfQulitModEntry(ZipArchive zipArchive, ref ModEntry entry) { var zipEntry = zipArchive.GetEntry("quilt.mod.json"); using var stream = zipEntry.Open(); using var reader = new StreamReader(stream); - + try { var jsonNode = reader.ReadToEnd().AsNode(); jsonNode = jsonNode.Select("quilt_loader").Select("metadata"); @@ -144,8 +139,7 @@ private void OfQulitModEntry(ZipArchive zipArchive, ref ModEntry entry) { entry.Authors = jsonNode["authors"] .GetEnumerable() .ToImmutableArray(); - } - catch (Exception) { + } catch (Exception) { entry.IsError = true; } } diff --git a/MinecraftLaunch/Components/Resolver/ResourcePackResolver.cs b/MinecraftLaunch/Components/Resolver/ResourcePackResolver.cs index 58bc500..2edfca7 100644 --- a/MinecraftLaunch/Components/Resolver/ResourcePackResolver.cs +++ b/MinecraftLaunch/Components/Resolver/ResourcePackResolver.cs @@ -1,6 +1,4 @@ -using MinecraftLaunch.Classes.Interfaces; - -namespace MinecraftLaunch.Components.Resolver; +namespace MinecraftLaunch.Components.Resolver; public sealed class ResourcePackResolver { } \ No newline at end of file diff --git a/MinecraftLaunch/Components/Resolver/TomlResolver.cs b/MinecraftLaunch/Components/Resolver/TomlResolver.cs index 9febd17..b0a2002 100644 --- a/MinecraftLaunch/Components/Resolver/TomlResolver.cs +++ b/MinecraftLaunch/Components/Resolver/TomlResolver.cs @@ -1,15 +1,16 @@ using System.Text.RegularExpressions; -using MinecraftLaunch.Classes.Interfaces; namespace MinecraftLaunch.Components.Resolver; /// /// Toml 文件解析器 /// -public sealed class TomlResolver() { +public sealed partial class TomlResolver() { private readonly char[] _separator = ['\r', '\n']; - private readonly Dictionary _data = new(); - private readonly Regex _regex = new(@"(?<=(" + "\"" + "))[.\\s\\S]*?(?=(" + "\"" + "))"); + private readonly Dictionary _data = []; + + [GeneratedRegex(@"(?<=(" + "\"" + "))[.\\s\\S]*?(?=(" + "\"" + "))")] + private static partial Regex TomlResolveRegex(); public TomlResolver(string content) : this() { Parse(content); @@ -25,15 +26,15 @@ private void Parse(string content) { var lines = content.Split(_separator, StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines) { - if (line.StartsWith("#")) { + if (line.StartsWith('#')) { continue; } var parts = line.Split(['='], 2); if (parts.Length == 2) { var key = parts[0].Trim(); - var value = _regex.Match(parts[1]).Value; - + var value = TomlResolveRegex().Match(parts[1]).Value; + _data[key] = value; } } diff --git a/MinecraftLaunch/Components/Watcher/GameProcessWatcher.cs b/MinecraftLaunch/Components/Watcher/GameProcessWatcher.cs index e897c58..e03f316 100644 --- a/MinecraftLaunch/Components/Watcher/GameProcessWatcher.cs +++ b/MinecraftLaunch/Components/Watcher/GameProcessWatcher.cs @@ -1,7 +1,7 @@ -using System.Diagnostics; -using MinecraftLaunch.Classes.Interfaces; -using MinecraftLaunch.Components.Resolver; +using MinecraftLaunch.Classes.Interfaces; using MinecraftLaunch.Classes.Models.Event; +using MinecraftLaunch.Components.Resolver; +using System.Diagnostics; namespace MinecraftLaunch.Components.Watcher; @@ -15,6 +15,7 @@ public sealed class GameProcessWatcher : IWatcher, IGameProcessWatcher { public IEnumerable Arguments { get; } public event EventHandler Exited; + public event EventHandler OutputLogReceived; public GameProcessWatcher(Process process, IEnumerable arguments) { diff --git a/MinecraftLaunch/Components/Watcher/ServerPingWatcher.cs b/MinecraftLaunch/Components/Watcher/ServerPingWatcher.cs index b79da0d..899520e 100644 --- a/MinecraftLaunch/Components/Watcher/ServerPingWatcher.cs +++ b/MinecraftLaunch/Components/Watcher/ServerPingWatcher.cs @@ -1,10 +1,10 @@ -using System.Text; -using System.Net.Sockets; -using MinecraftLaunch.Classes.Interfaces; +using MinecraftLaunch.Classes.Interfaces; +using MinecraftLaunch.Classes.Models.Event; +using MinecraftLaunch.Classes.Models.ServerPing; using System.Diagnostics; +using System.Net.Sockets; +using System.Text; using System.Text.Json; -using MinecraftLaunch.Classes.Models.ServerPing; -using MinecraftLaunch.Classes.Models.Event; namespace MinecraftLaunch.Components.Watcher; @@ -18,6 +18,7 @@ public sealed class ServerPingWatcher(ushort port, string address, int versionId private CancellationTokenSource _cancellationTokenSource = tokenSource; public event EventHandler ServerLatencyChanged; + public event EventHandler ServerConnectionProgressChanged; public ushort Port => port; @@ -93,7 +94,7 @@ public async ValueTask PingAsync() { await Flush(0); /* - * If you are using a modded server then use a larger buffer to account, + * If you are using a modded server then use a larger buffer to account, * see link for explanation and a motd to HTML snippet * https://gist.github.com/csh/2480d14fbbb33b4bbae3#gistcomment-2672658 */ @@ -216,5 +217,5 @@ private void ReportProgress(double progress, string progressStatus, TaskStatus s ServerConnectionProgressChanged?.Invoke(this, new(status, progress, progressStatus)); } - #endregion + #endregion Read/Write methods } \ No newline at end of file diff --git a/MinecraftLaunch/Extensions/CryptoExtension.cs b/MinecraftLaunch/Extensions/CryptoExtension.cs index 4fb9e6a..cb9572f 100644 --- a/MinecraftLaunch/Extensions/CryptoExtension.cs +++ b/MinecraftLaunch/Extensions/CryptoExtension.cs @@ -1,6 +1,7 @@ namespace MinecraftLaunch.Extensions; public static class CryptoExtension { + public static string BytesToString(this byte[] bytes) { return BitConverter.ToString(bytes).Replace("-", string.Empty); } diff --git a/MinecraftLaunch/Extensions/DownloadEntryExtension.cs b/MinecraftLaunch/Extensions/DownloadEntryExtension.cs index d7c7b84..2414795 100644 --- a/MinecraftLaunch/Extensions/DownloadEntryExtension.cs +++ b/MinecraftLaunch/Extensions/DownloadEntryExtension.cs @@ -1,10 +1,11 @@ -using System.Security.Cryptography; -using MinecraftLaunch.Classes.Interfaces; +using MinecraftLaunch.Classes.Interfaces; using MinecraftLaunch.Classes.Models.Download; +using System.Security.Cryptography; namespace MinecraftLaunch.Extensions; public static class DownloadEntryExtension { + private static readonly char[] _hexTable = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; @@ -16,10 +17,10 @@ public static DownloadRequest ToDownloadRequest(this IDownloadEntry entry) { } public static bool Verify(this IDownloadEntry entry) { - if(entry == null) + if (entry == null) return true; - if(!File.Exists(entry.Path)) + if (!File.Exists(entry.Path)) return false; if (entry.Checksum == null) diff --git a/MinecraftLaunch/Extensions/DownloadExtension.cs b/MinecraftLaunch/Extensions/DownloadExtension.cs index d12b48c..1ff9bf7 100644 --- a/MinecraftLaunch/Extensions/DownloadExtension.cs +++ b/MinecraftLaunch/Extensions/DownloadExtension.cs @@ -1,14 +1,15 @@ using MinecraftLaunch.Classes.Enums; using MinecraftLaunch.Classes.Interfaces; -using MinecraftLaunch.Classes.Models.Event; using MinecraftLaunch.Classes.Models.Download; -using MinecraftLaunch.Components.Downloader; +using MinecraftLaunch.Classes.Models.Event; using MinecraftLaunch.Classes.Models.Game; +using MinecraftLaunch.Components.Downloader; using MinecraftLaunch.Utilities; namespace MinecraftLaunch.Extensions; public static class DownloadExtension { + /// /// Applies the mirror source to the download entry if the use of mirror download source is enabled. /// @@ -21,13 +22,12 @@ public static IDownloadEntry OfMirrorSource(this IDownloadEntry entry, if (entry.Type is DownloadEntryType.Jar) { entry.Url = $"{source.Host}/version/{(entry as JarEntry).McVersion}/client"; } - + var urls = entry.Type is DownloadEntryType.Asset ? source.AssetsUrls : source.LibrariesUrls; entry.Url = entry.Url.Replace(urls); - } return entry; @@ -51,10 +51,10 @@ public static ValueTask DownloadAsync( /// The download entry to be downloaded. /// The mirror download source to be used. /// A ValueTask that represents the asynchronous download operation. The task result contains a boolean value that indicates whether the download operation was successful. - public static ValueTask DownloadResourceEntryAsync(this + public static ValueTask DownloadResourceEntryAsync(this IDownloadEntry downloadEntry, MirrorDownloadSource source = default!) { - return DownloadUitl.DownloadAsync(downloadEntry, DownloadUitl.DefaultDownloadRequest,default,x=>{}); + return DownloadUitl.DownloadAsync(downloadEntry, DownloadUitl.DefaultDownloadRequest, default, x => { }); } /// diff --git a/MinecraftLaunch/Extensions/FileExtension.cs b/MinecraftLaunch/Extensions/FileExtension.cs index 53e4fe9..30e9611 100644 --- a/MinecraftLaunch/Extensions/FileExtension.cs +++ b/MinecraftLaunch/Extensions/FileExtension.cs @@ -1,11 +1,12 @@ namespace MinecraftLaunch.Extensions; public static class FileExtension { + public static DirectoryInfo DiveTo(this DirectoryInfo parentDir, string childDirectoryInfo) { var divePath = parentDir.FullName; return divePath.AppendPath(childDirectoryInfo).ToDirectoryInfo(); } - + public static FileInfo DiveToFile(this DirectoryInfo parentDir, string childFileNameHierarchy) { var divePath = parentDir.FullName; if (childFileNameHierarchy.Contains('/')) { @@ -17,11 +18,19 @@ public static FileInfo DiveToFile(this DirectoryInfo parentDir, string childFile return new FileInfo(divePath); } - + public static string AppendPath(this string path, string toAppend) { return Path.Combine(path, toAppend); } + public static string CheckAndSet(this string path) { + if (path.ToFileInfo().Exists) { + return path; + } + + return null; + } + public static FileInfo ToFileInfo(this string path) => new(path); public static DirectoryInfo ToDirectoryInfo(this string path) => new(path); diff --git a/MinecraftLaunch/Extensions/GameEntryExtension.cs b/MinecraftLaunch/Extensions/GameEntryExtension.cs index 9521b3a..df0c612 100644 --- a/MinecraftLaunch/Extensions/GameEntryExtension.cs +++ b/MinecraftLaunch/Extensions/GameEntryExtension.cs @@ -1,17 +1,19 @@ using MinecraftLaunch.Classes.Models.Game; -namespace MinecraftLaunch.Extensions; +namespace MinecraftLaunch.Extensions; /// /// Provides extension methods for game entries. /// public static class GameEntryExtension { + #region String + /// /// Gets the path of the launcher profile. /// /// The root directory. /// The path of the launcher profile. - public static string OfLauncherProfilePath(this string root) => + public static string ToLauncherProfilePath(this string root) => Path.Combine(root, "launcher_profiles.json"); /// @@ -19,15 +21,27 @@ public static string OfLauncherProfilePath(this string root) => /// /// The root directory. /// The path of the launcher account. - public static string OfLauncherAccountPath(this string root) => + public static string ToLauncherAccountPath(this string root) => Path.Combine(root, "launcher_accounts.json"); + #endregion + + #region GameEntry + + /// + /// Gets the path ofthe libraries directory. + /// + /// The game entry. + /// The path of the libraries directory. + public static string ToLibrariesPath(this GameEntry entry) => +Path.Combine(entry.GameFolderPath, "libraries"); + /// /// Gets the path of the version JSON file. /// /// The game entry. /// The path of the version JSON file. - public static string OfVersionJsonPath(this GameEntry entry) => + public static string ToVersionJsonPath(this GameEntry entry) => Path.Combine(entry.GameFolderPath, "versions", entry.Id, $"{entry.Id}.json"); /// @@ -36,7 +50,7 @@ public static string OfVersionJsonPath(this GameEntry entry) => /// The game entry. /// A value indicating whether to isolate the version directory. /// The path of the version directory. - public static string OfVersionDirectoryPath(this GameEntry entry, bool Isolate = true) => Isolate + public static string ToVersionDirectoryPath(this GameEntry entry, bool Isolate = true) => Isolate ? Path.Combine(entry.GameFolderPath, "versions", entry.Id) : entry.GameFolderPath; @@ -46,6 +60,8 @@ public static string OfVersionDirectoryPath(this GameEntry entry, bool Isolate = /// The game entry. /// A value indicating whether to isolate the mod directory. /// The path of the mod directory. - public static string OfModDirectorypath(this GameEntry entry, bool Isolate = true) => Path - .Combine(entry.OfVersionDirectoryPath(Isolate), "mods"); + public static string ToModDirectorypath(this GameEntry entry, bool Isolate = true) => + Path.Combine(entry.ToVersionDirectoryPath(Isolate), "mods"); + + #endregion } \ No newline at end of file diff --git a/MinecraftLaunch/Extensions/JsonExtension.cs b/MinecraftLaunch/Extensions/JsonExtension.cs index 9e6ed65..a0381c8 100644 --- a/MinecraftLaunch/Extensions/JsonExtension.cs +++ b/MinecraftLaunch/Extensions/JsonExtension.cs @@ -1,20 +1,21 @@ -using System.Text.Json; +using MinecraftLaunch.Utilities; +using System.Text.Json; using System.Text.Json.Nodes; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Metadata; -using MinecraftLaunch.Utilities; namespace MinecraftLaunch.Extensions; public static class JsonExtension { + public static string Serialize(this object value, Type inputType, JsonSerializerContext context) { return JsonSerializer.Serialize(value, inputType, context); } - + public static T Deserialize(this string json, JsonTypeInfo jsonType) { return JsonSerializer.Deserialize(json, jsonType); } - + public static string AsJson(this object obj) { return JsonSerializer.Serialize(obj, JsonConverterUtil.DefaultJsonOptions); } @@ -22,6 +23,7 @@ public static string AsJson(this object obj) { public static T AsJsonEntry(this string json) { return JsonSerializer.Deserialize(json, JsonConverterUtil.DefaultJsonOptions); } + public static JsonNode AsNode(this string json) { return JsonNode.Parse(json); } @@ -79,7 +81,7 @@ public static IEnumerable GetEnumerable(this JsonNode node, string name, s .Select(x => x.Select(elementName).GetValue()); } - public static JsonNode SetString(this JsonNode node,string name, string value) { + public static JsonNode SetString(this JsonNode node, string name, string value) { node[name] = value; return node; } diff --git a/MinecraftLaunch/Extensions/StringExtension.cs b/MinecraftLaunch/Extensions/StringExtension.cs index b739693..aa7346f 100644 --- a/MinecraftLaunch/Extensions/StringExtension.cs +++ b/MinecraftLaunch/Extensions/StringExtension.cs @@ -3,10 +3,11 @@ namespace MinecraftLaunch.Extensions; public static class StringExtension { + public static bool IsUrl(this string str) { Uri uriResult; bool result = Uri.TryCreate(str, UriKind.Absolute, out uriResult) - && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); + && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); return result; } @@ -17,7 +18,7 @@ public static string ToPath(this string raw) { return "\"" + raw + "\""; } - public static string Replace(this string text, Dictionary keyValuePairs) { + public static string Replace(this string text, IDictionary keyValuePairs) { string replacedText = text; foreach (var item in keyValuePairs) { replacedText = replacedText.Replace(item.Key, item.Value); @@ -32,4 +33,27 @@ public static DownloadRequest ToDownloadRequest(this string url, FileInfo path) FileInfo = path, }; } + + public static IEnumerable GroupArguments(this IEnumerable parameters) { + var queue = new Queue(parameters); + var group = new List(); + + while (queue.Count > 0) { + var next = queue.Dequeue(); + + if (group.Count == 0) { + group.Add(next); + } else { + if (group.First().StartsWith('-') && next.StartsWith('-')) { + yield return string.Join(group.First().EndsWith('=') ? "" : " ", group); + group.Clear(); + } + group.Add(next); + } + } + + if (group.Count > 0) { + yield return string.Join(group.First().EndsWith('=') ? "" : " ", group); + } + } } \ No newline at end of file diff --git a/MinecraftLaunch/Extensions/ZipArchiveExtension.cs b/MinecraftLaunch/Extensions/ZipArchiveExtension.cs index f5eb0c7..af5478f 100644 --- a/MinecraftLaunch/Extensions/ZipArchiveExtension.cs +++ b/MinecraftLaunch/Extensions/ZipArchiveExtension.cs @@ -6,6 +6,7 @@ namespace MinecraftLaunch.Extensions; /// Provides extension methods for ZipArchiveEntry. /// public static class ZipArchiveExtension { + /// /// Reads the contents of the ZipArchiveEntry as a string. /// diff --git a/MinecraftLaunch/MinecraftLaunch.csproj b/MinecraftLaunch/MinecraftLaunch.csproj index f10f0df..900daed 100644 --- a/MinecraftLaunch/MinecraftLaunch.csproj +++ b/MinecraftLaunch/MinecraftLaunch.csproj @@ -1,6 +1,6 @@  - 3.1.0-preview06 + 3.1.0-preview07 diff --git a/MinecraftLaunch/MirrorDownloadManager.cs b/MinecraftLaunch/MirrorDownloadManager.cs index 0988464..3fbb98d 100644 --- a/MinecraftLaunch/MirrorDownloadManager.cs +++ b/MinecraftLaunch/MirrorDownloadManager.cs @@ -6,6 +6,7 @@ namespace MinecraftLaunch; /// The default manager for mirror download sources. /// public static class MirrorDownloadManager { + /// /// Gets or sets a value indicating whether to use mirror download source. /// @@ -35,4 +36,4 @@ public static class MirrorDownloadManager { { "https://maven.neoforged.net/releases/net/neoforged/forge", "https://bmclapi2.bangbang93.com/maven/net/neoforged/forge" } } }; -} +} \ No newline at end of file diff --git a/MinecraftLaunch/Utilities/DirectoryUtil.cs b/MinecraftLaunch/Utilities/DirectoryUtil.cs index b15222d..3bf52f5 100644 --- a/MinecraftLaunch/Utilities/DirectoryUtil.cs +++ b/MinecraftLaunch/Utilities/DirectoryUtil.cs @@ -1,6 +1,7 @@ namespace MinecraftLaunch.Utilities; public static class DirectoryUtil { + public static void DeleteAllFiles(string folder) => DeleteAllFiles(new DirectoryInfo(folder)); diff --git a/MinecraftLaunch/Utilities/DownloadUitl.cs b/MinecraftLaunch/Utilities/DownloadUitl.cs index f46efcd..ba086da 100644 --- a/MinecraftLaunch/Utilities/DownloadUitl.cs +++ b/MinecraftLaunch/Utilities/DownloadUitl.cs @@ -1,11 +1,10 @@ using Flurl.Http; -using System.Net; +using MinecraftLaunch.Classes.Interfaces; +using MinecraftLaunch.Classes.Models.Download; using System.Buffers; +using System.Net; using System.Net.Http.Headers; using System.Threading.Tasks.Dataflow; -using MinecraftLaunch.Classes.Interfaces; -using MinecraftLaunch.Classes.Models.Download; - using Timer = System.Timers.Timer; namespace MinecraftLaunch.Utilities; @@ -14,6 +13,7 @@ namespace MinecraftLaunch.Utilities; /// 下载工具类 /// public static class DownloadUitl { + public static DownloadRequest DefaultDownloadRequest { get; set; } = new() { IsPartialContentSupported = true, FileSizeThreshold = 1024 * 1024 * 3, @@ -31,7 +31,7 @@ public static async ValueTask DownloadAsync( 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); @@ -64,7 +64,6 @@ public static async ValueTask DownloadAsync( perSecondProgressChangedAction(responseMessage.Content.Headers.ContentLength != null ? task.Result / (double)responseMessage.Content.Headers.ContentLength : 0); } catch (Exception) { - } timer.Stop(); @@ -80,7 +79,6 @@ public static async ValueTask DownloadAsync( DownloadRequest downloadRequest = default, CancellationTokenSource tokenSource = default, Action perSecondProgressChangedAction = default) { - Timer timer = default; downloadRequest ??= DefaultDownloadRequest; tokenSource ??= new CancellationTokenSource(); @@ -120,7 +118,6 @@ public static async ValueTask DownloadAsync( perSecondProgressChangedAction(responseMessage.Content.Headers.ContentLength != null ? task.Result / (double)responseMessage.Content.Headers.ContentLength : 0); } catch (Exception) { - } timer.Stop(); @@ -131,10 +128,10 @@ public static async ValueTask DownloadAsync( }); } - private async static ValueTask WriteFileFromHttpResponseAsync( - string path, - HttpResponseMessage responseMessage, - CancellationTokenSource tokenSource, + private static async ValueTask WriteFileFromHttpResponseAsync( + string path, + HttpResponseMessage responseMessage, + CancellationTokenSource tokenSource, (Timer, Action perSecondProgressChangedAction, long?)? perSecondProgressChange = default) { var parentFolder = Path.GetDirectoryName(path); Directory.CreateDirectory(parentFolder); @@ -160,7 +157,6 @@ private async static ValueTask WriteFileFromHttpResponseAsync( return totalReadMemory; } - private static async ValueTask MultiPartDownloadAsync( HttpResponseMessage responseMessage, DownloadRequest downloadSetting, @@ -169,7 +165,7 @@ private static async ValueTask MultiPartDownloadAsync( var requestMessage = new HttpRequestMessage(HttpMethod.Get, responseMessage.RequestMessage.RequestUri.AbsoluteUri); requestMessage.Headers.Range = new RangeHeaderValue(0, 1); - var httpResponse = (await responseMessage.RequestMessage.RequestUri.GetAsync(cancellationToken:tokenSource.Token)).ResponseMessage; + var httpResponse = (await responseMessage.RequestMessage.RequestUri.GetAsync(cancellationToken: tokenSource.Token)).ResponseMessage; if (!httpResponse.IsSuccessStatusCode || httpResponse.Content.Headers.ContentLength.Value != 2) return await WriteFileFromHttpResponseAsync(absolutePath, responseMessage, tokenSource); @@ -198,7 +194,7 @@ private static async ValueTask MultiPartDownloadAsync( var transformBlock = new TransformBlock(async range => { var message = (await responseMessage.RequestMessage.RequestUri.WithHeader("Range", $"bytes={range.Start}-{range.End}") - .GetAsync(cancellationToken:tokenSource.Token)).ResponseMessage; + .GetAsync(cancellationToken: tokenSource.Token)).ResponseMessage; return (message, range); }, new ExecutionDataflowBlockOptions { BoundedCapacity = downloadSetting.MultiPartsCount, diff --git a/MinecraftLaunch/Utilities/EnvironmentUtil.cs b/MinecraftLaunch/Utilities/EnvironmentUtil.cs index a7989fe..7763379 100644 --- a/MinecraftLaunch/Utilities/EnvironmentUtil.cs +++ b/MinecraftLaunch/Utilities/EnvironmentUtil.cs @@ -3,6 +3,7 @@ namespace MinecraftLaunch.Utilities; public static class EnvironmentUtil { + public static string Arch => Environment.Is64BitOperatingSystem ? "64" : "32"; diff --git a/MinecraftLaunch/Utilities/GameUtil.cs b/MinecraftLaunch/Utilities/GameUtil.cs index 7756b07..4c45355 100644 --- a/MinecraftLaunch/Utilities/GameUtil.cs +++ b/MinecraftLaunch/Utilities/GameUtil.cs @@ -4,6 +4,7 @@ namespace MinecraftLaunch.Utilities; public static class GameUtil { + public static LoaderType GetGameLoaderType(this GameJsonEntry entity) { return entity.MainClass switch { "net.minecraft.launchwrapper.Launch" => LoaderType.Forge, diff --git a/MinecraftLaunch/Utilities/JavaUtil.cs b/MinecraftLaunch/Utilities/JavaUtil.cs index 727669f..30c46f3 100644 --- a/MinecraftLaunch/Utilities/JavaUtil.cs +++ b/MinecraftLaunch/Utilities/JavaUtil.cs @@ -1,8 +1,6 @@ -using System.Diagnostics; -using System.Runtime.Versioning; -using System.Runtime.InteropServices; +using MinecraftLaunch.Classes.Models.Game; +using System.Diagnostics; using System.Text.RegularExpressions; -using MinecraftLaunch.Classes.Models.Game; namespace MinecraftLaunch.Utilities; @@ -54,8 +52,7 @@ public static JavaEntry GetJavaInfo(string path) { JavaDirectoryPath = Directory.GetParent(path).FullName, JavaSlugVersion = (int.Parse(versionParts[0]) == 1) ? int.Parse(versionParts[1]) : int.Parse(versionParts[0]), }; - } - catch (Exception ex) { + } catch (Exception ex) { Console.WriteLine($"Error getting Java info: {ex.Message}"); return null; } @@ -71,7 +68,7 @@ public static JavaEntry GetCurrentJava(IReadOnlyList javaEntries, Gam return result; } - + private static bool GetIs64BitWindows(string path) { ushort architecture = 0; @@ -88,8 +85,7 @@ private static bool GetIs64BitWindows(string path) { architecture = binaryReader.ReadUInt16(); } } - } - catch (Exception ex) { + } catch (Exception ex) { Console.WriteLine($"Error checking if file is 64 bit: {ex.Message}"); } diff --git a/MinecraftLaunch/Utilities/ZipUtil.cs b/MinecraftLaunch/Utilities/ZipUtil.cs index e77a024..beae474 100644 --- a/MinecraftLaunch/Utilities/ZipUtil.cs +++ b/MinecraftLaunch/Utilities/ZipUtil.cs @@ -1,11 +1,11 @@ -using MinecraftLaunch.Classes.Enums; -using System.IO.Compression; +using System.IO.Compression; namespace MinecraftLaunch.Utilities; public static class ZipUtil { + public static void ExtractNatives(string targetFolder, IEnumerable files) { - try { + try { if (!Directory.Exists(targetFolder)) { Directory.CreateDirectory(targetFolder); } @@ -28,7 +28,6 @@ public static void ExtractNatives(string targetFolder, IEnumerable files } } } - } - catch (Exception) {} + } catch (Exception) { } } } \ No newline at end of file