Removed JavaService, and moved Java handling to CmlLib.
This commit is contained in:
6
.idea/.idea.AlayaCore/.idea/vcs.xml
generated
Normal file
6
.idea/.idea.AlayaCore/.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -1,3 +1,22 @@
|
|||||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ADefaultFileExtractors_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F11957ce69cb24b8a8e3979c0980ffeb33a400_003Fe8_003F52aaf39a_003FDefaultFileExtractors_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AExtensions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F11957ce69cb24b8a8e3979c0980ffeb33a400_003F5c_003Ff0b24cad_003FExtensions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIGameInstaller_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F11957ce69cb24b8a8e3979c0980ffeb33a400_003Fdf_003F3b38ca47_003FIGameInstaller_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIVersionMetadata_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F11957ce69cb24b8a8e3979c0980ffeb33a400_003Ff2_003Fc2330846_003FIVersionMetadata_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIXboxGameAccountManager_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F101e700861b6410da498d4e79271a86112600_003Fc4_003F2054a44d_003FIXboxGameAccountManager_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AJELoginHandlerBuilder_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F2dce88ad0d604d86b0d410923cb59f4bb200_003Fb4_003F534fcf72_003FJELoginHandlerBuilder_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AJELoginHandler_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F2dce88ad0d604d86b0d410923cb59f4bb200_003Fcd_003Ffe209c30_003FJELoginHandler_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMinecraftJavaPathResolver_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F11957ce69cb24b8a8e3979c0980ffeb33a400_003F5f_003F3f4c19e9_003FMinecraftJavaPathResolver_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMinecraftLauncherParameters_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F11957ce69cb24b8a8e3979c0980ffeb33a400_003F67_003Fd3bb8531_003FMinecraftLauncherParameters_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMinecraftLauncher_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F11957ce69cb24b8a8e3979c0980ffeb33a400_003F93_003F1a552b3b_003FMinecraftLauncher_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMinecraftPath_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F75bf69b9634b4f328866dbcd8b90304a2600_003F3c_003Fef2111c9_003FMinecraftPath_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMinecraftProcessBuilder_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F11957ce69cb24b8a8e3979c0980ffeb33a400_003Fc0_003F15c03583_003FMinecraftProcessBuilder_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMsalClientHelper_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fee6114ec878e41eeb911687986e3a3fd6600_003F4b_003F0b7d25f6_003FMsalClientHelper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMSession_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F75bf69b9634b4f328866dbcd8b90304a2600_003Fa0_003F9cf699df_003FMSession_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANeoForgeInstaller_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F16599bff24b948d2b1e1d928222947e1de00_003F39_003F21a3bcfd_003FNeoForgeInstaller_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANeoForgeInstallOptions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F16599bff24b948d2b1e1d928222947e1de00_003Fa3_003F837206c4_003FNeoForgeInstallOptions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AOperatingSystem_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb5d933e666c84a3394cfc49363e3e5bdd2b08_003Fb9_003Fd737a5e2_003FOperatingSystem_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AOperatingSystem_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb5d933e666c84a3394cfc49363e3e5bdd2b08_003Fb9_003Fd737a5e2_003FOperatingSystem_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AVersionConverter_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FSourcesCache_003F346166506159999f4fec5f7c475ba964d2495ee825dd6e4c48dedef117f086_003FVersionConverter_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AProcessWrapper_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F11957ce69cb24b8a8e3979c0980ffeb33a400_003F97_003F3a1ed5f7_003FProcessWrapper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003APublicClientApplicationBuilder_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FSourcesCache_003Fe7dcae430a36a6030304d2dec7149bc9e40cb379e3a8e0efb762d5d19da5c_003FPublicClientApplicationBuilder_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AVersionConverter_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FSourcesCache_003F346166506159999f4fec5f7c475ba964d2495ee825dd6e4c48dedef117f086_003FVersionConverter_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AVersionMetadataCollection_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F11957ce69cb24b8a8e3979c0980ffeb33a400_003Ff7_003Fb6ecd842_003FVersionMetadataCollection_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>
|
||||||
@@ -11,5 +11,7 @@ namespace AlayaCore.Abstractions.Interfaces.Clients
|
|||||||
Uri uri,
|
Uri uri,
|
||||||
HttpCompletionOption completionOption,
|
HttpCompletionOption completionOption,
|
||||||
CancellationToken cancellationToken);
|
CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
HttpClient HttpClient { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,7 @@ namespace AlayaCore.Abstractions.Interfaces.Services
|
|||||||
{
|
{
|
||||||
public interface IGameInstallService
|
public interface IGameInstallService
|
||||||
{
|
{
|
||||||
|
|
||||||
Task EnsureMinecraftInstalledAsync(
|
Task EnsureMinecraftInstalledAsync(
|
||||||
ManifestModel manifest,
|
ManifestModel manifest,
|
||||||
InstallEnvironment environment,
|
InstallEnvironment environment,
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace AlayaCore.Abstractions.Interfaces.Services
|
|||||||
|
|
||||||
Task<LauncherManifestModel?> GetLocalLauncherManifestAsync(CancellationToken cancellationToken = default);
|
Task<LauncherManifestModel?> GetLocalLauncherManifestAsync(CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
Task<string> GetRemoteLauncherManifestHashAsync(CancellationToken cancellationToken = default);
|
Task<LauncherManifestModel> GetRemoteLauncherManifestAsync(CancellationToken cancellationToken = default);
|
||||||
Task<Version> GetRemoteCoreManifestVersionAsync(CancellationToken cancellationToken = default);
|
Task<Version> GetRemoteCoreManifestVersionAsync(CancellationToken cancellationToken = default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,6 @@ namespace AlayaCore
|
|||||||
private readonly IManifestService _manifestService;
|
private readonly IManifestService _manifestService;
|
||||||
private readonly IUpdateService _updateService;
|
private readonly IUpdateService _updateService;
|
||||||
private readonly IInstallStateService _installStateService;
|
private readonly IInstallStateService _installStateService;
|
||||||
private readonly IJavaService _javaService;
|
|
||||||
private readonly IModService _modService;
|
private readonly IModService _modService;
|
||||||
private readonly IGameLaunchService _gameLaunchService;
|
private readonly IGameLaunchService _gameLaunchService;
|
||||||
private readonly IGameInstallService _gameInstallService;
|
private readonly IGameInstallService _gameInstallService;
|
||||||
@@ -36,7 +35,6 @@ namespace AlayaCore
|
|||||||
IManifestService manifestService,
|
IManifestService manifestService,
|
||||||
IUpdateService updateService,
|
IUpdateService updateService,
|
||||||
IInstallStateService installStateService,
|
IInstallStateService installStateService,
|
||||||
IJavaService javaService,
|
|
||||||
IModService modService,
|
IModService modService,
|
||||||
IGameLaunchService gameLaunchService,
|
IGameLaunchService gameLaunchService,
|
||||||
IGameInstallService gameInstallService,
|
IGameInstallService gameInstallService,
|
||||||
@@ -47,7 +45,6 @@ namespace AlayaCore
|
|||||||
_manifestService = manifestService ?? throw new ArgumentNullException(nameof(manifestService));
|
_manifestService = manifestService ?? throw new ArgumentNullException(nameof(manifestService));
|
||||||
_updateService = updateService ?? throw new ArgumentNullException(nameof(updateService));
|
_updateService = updateService ?? throw new ArgumentNullException(nameof(updateService));
|
||||||
_installStateService = installStateService ?? throw new ArgumentNullException(nameof(installStateService));
|
_installStateService = installStateService ?? throw new ArgumentNullException(nameof(installStateService));
|
||||||
_javaService = javaService ?? throw new ArgumentNullException(nameof(javaService));
|
|
||||||
_modService = modService ?? throw new ArgumentNullException(nameof(modService));
|
_modService = modService ?? throw new ArgumentNullException(nameof(modService));
|
||||||
_gameLaunchService = gameLaunchService ?? throw new ArgumentNullException(nameof(gameLaunchService));
|
_gameLaunchService = gameLaunchService ?? throw new ArgumentNullException(nameof(gameLaunchService));
|
||||||
_gameInstallService = gameInstallService ?? throw new ArgumentNullException(nameof(gameInstallService));
|
_gameInstallService = gameInstallService ?? throw new ArgumentNullException(nameof(gameInstallService));
|
||||||
@@ -68,7 +65,6 @@ namespace AlayaCore
|
|||||||
{
|
{
|
||||||
LaunchPlan launcherUpdatePlan = new LaunchPlan(
|
LaunchPlan launcherUpdatePlan = new LaunchPlan(
|
||||||
launcherNeedsUpdate: true,
|
launcherNeedsUpdate: true,
|
||||||
javaNeedsInstallOrUpdate: false,
|
|
||||||
minecraftNeedsInstallOrUpdate: false,
|
minecraftNeedsInstallOrUpdate: false,
|
||||||
neoforgeNeedsInstallOrUpdate: false,
|
neoforgeNeedsInstallOrUpdate: false,
|
||||||
modsNeedSync: false,
|
modsNeedSync: false,
|
||||||
@@ -84,17 +80,13 @@ namespace AlayaCore
|
|||||||
.GetCurrentEnvironmentAsync(cancellationToken)
|
.GetCurrentEnvironmentAsync(cancellationToken)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
bool javaNeedsInstallOrUpdate =
|
|
||||||
_options.ForceReinstall ||
|
|
||||||
!environment.JavaInstalled ||
|
|
||||||
!string.Equals(environment.JavaVersion, manifest.RequiredJavaVersion, StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
bool needAuthenticating = !await _authService
|
bool needAuthenticating = !await _authService
|
||||||
.IsAuthenticatedAsync(cancellationToken)
|
.IsAuthenticatedAsync(cancellationToken)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
bool minecraftNeedsInstallOrUpdate =
|
bool minecraftNeedsInstallOrUpdate =
|
||||||
_options.ForceReinstall ||
|
_options.ForceReinstall ||
|
||||||
|
!environment.JavaInstalled ||
|
||||||
!environment.MinecraftInstalled ||
|
!environment.MinecraftInstalled ||
|
||||||
!string.Equals(environment.MinecraftVersion, manifest.MinecraftVersion, StringComparison.OrdinalIgnoreCase);
|
!string.Equals(environment.MinecraftVersion, manifest.MinecraftVersion, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
@@ -109,7 +101,6 @@ namespace AlayaCore
|
|||||||
|
|
||||||
LaunchPlan plan = new LaunchPlan(
|
LaunchPlan plan = new LaunchPlan(
|
||||||
launcherNeedsUpdate: false,
|
launcherNeedsUpdate: false,
|
||||||
javaNeedsInstallOrUpdate: javaNeedsInstallOrUpdate,
|
|
||||||
minecraftNeedsInstallOrUpdate: minecraftNeedsInstallOrUpdate,
|
minecraftNeedsInstallOrUpdate: minecraftNeedsInstallOrUpdate,
|
||||||
neoforgeNeedsInstallOrUpdate: neoforgeNeedsInstallOrUpdate,
|
neoforgeNeedsInstallOrUpdate: neoforgeNeedsInstallOrUpdate,
|
||||||
modsNeedSync: modsNeedSync,
|
modsNeedSync: modsNeedSync,
|
||||||
@@ -119,8 +110,9 @@ namespace AlayaCore
|
|||||||
return plan;
|
return plan;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task InstallOrUpdateAsync(CancellationToken cancellationToken = default,
|
public async Task InstallOrUpdateAsync(
|
||||||
EventHandler<InstallerProgressChangedEventArgs>? minecraftProgess = null,
|
CancellationToken cancellationToken = default,
|
||||||
|
EventHandler<InstallerProgressChangedEventArgs>? minecraftProgress = null,
|
||||||
EventHandler<ByteProgress>? byteProgress = null,
|
EventHandler<ByteProgress>? byteProgress = null,
|
||||||
IProgress<InstallerProgressChangedEventArgs>? neoForgeProgress = null,
|
IProgress<InstallerProgressChangedEventArgs>? neoForgeProgress = null,
|
||||||
IProgress<ByteProgress>? neoForgeByteProgress = null)
|
IProgress<ByteProgress>? neoForgeByteProgress = null)
|
||||||
@@ -133,8 +125,8 @@ namespace AlayaCore
|
|||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
ManifestModel? manifest;
|
ManifestModel manifest;
|
||||||
InstallEnvironment? environment;
|
InstallEnvironment environment;
|
||||||
|
|
||||||
switch (plan.State)
|
switch (plan.State)
|
||||||
{
|
{
|
||||||
@@ -152,23 +144,12 @@ namespace AlayaCore
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LaunchState.InstallJava:
|
|
||||||
{
|
|
||||||
manifest = await EnsureCurrentManifestAsync(cancellationToken).ConfigureAwait(false);
|
|
||||||
environment = await _installStateService
|
|
||||||
.GetCurrentEnvironmentAsync(cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
await _javaService
|
|
||||||
.EnsureValidJavaInstalledAsync(manifest, environment, cancellationToken)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case LaunchState.NeedAuthenticating:
|
case LaunchState.NeedAuthenticating:
|
||||||
{
|
{
|
||||||
await _authService.AuthenticateAsync(cancellationToken);
|
await _authService
|
||||||
|
.AuthenticateAsync(cancellationToken)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +161,12 @@ namespace AlayaCore
|
|||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
await _gameInstallService
|
await _gameInstallService
|
||||||
.EnsureMinecraftInstalledAsync(manifest, environment, cancellationToken, minecraftProgess, byteProgress)
|
.EnsureMinecraftInstalledAsync(
|
||||||
|
manifest,
|
||||||
|
environment,
|
||||||
|
cancellationToken,
|
||||||
|
minecraftProgress,
|
||||||
|
byteProgress)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -194,7 +180,12 @@ namespace AlayaCore
|
|||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
await _gameInstallService
|
await _gameInstallService
|
||||||
.EnsureNeoForgeInstalledAsync(manifest, environment, cancellationToken, neoForgeProgress, neoForgeByteProgress)
|
.EnsureNeoForgeInstalledAsync(
|
||||||
|
manifest,
|
||||||
|
environment,
|
||||||
|
cancellationToken,
|
||||||
|
neoForgeProgress,
|
||||||
|
neoForgeByteProgress)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -230,7 +221,9 @@ namespace AlayaCore
|
|||||||
|
|
||||||
if (_options.ForceReinstall)
|
if (_options.ForceReinstall)
|
||||||
{
|
{
|
||||||
await _settingsService.SetForceReinstallAsync(false, cancellationToken).ConfigureAwait(false);
|
await _settingsService
|
||||||
|
.SetForceReinstallAsync(false, cancellationToken)
|
||||||
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
plan = await EvaluateAsync(cancellationToken).ConfigureAwait(false);
|
plan = await EvaluateAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ namespace AlayaCore.Models.Manifests.DTO
|
|||||||
[JsonConverter(typeof(UriConverter))]
|
[JsonConverter(typeof(UriConverter))]
|
||||||
public Uri RequiredJavaUrl { get; set; } = null!;
|
public Uri RequiredJavaUrl { get; set; } = null!;
|
||||||
|
|
||||||
|
[JsonProperty("javaArchiveHash", Required = Required.Always)]
|
||||||
|
public string JavaArchiveHash { get; set; } = string.Empty;
|
||||||
|
|
||||||
[JsonProperty("minecraftVersion", Required = Required.Always)]
|
[JsonProperty("minecraftVersion", Required = Required.Always)]
|
||||||
public string MinecraftVersion { get; set; } = string.Empty;
|
public string MinecraftVersion { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace AlayaCore.Models.Manifests
|
|||||||
{
|
{
|
||||||
public sealed class LauncherManifestModel
|
public sealed class LauncherManifestModel
|
||||||
{
|
{
|
||||||
public Version Version { get; }
|
public Version? Version { get; }
|
||||||
public string Sha512Hash { get; }
|
public string Sha512Hash { get; }
|
||||||
public Uri DownloadUri { get; }
|
public Uri DownloadUri { get; }
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ namespace AlayaCore.Models.Manifests
|
|||||||
public sealed class ManifestModel
|
public sealed class ManifestModel
|
||||||
{
|
{
|
||||||
public Version AlayaVersion { get; }
|
public Version AlayaVersion { get; }
|
||||||
public string RequiredJavaVersion { get; }
|
|
||||||
public Uri RequiredJavaBaseUrl { get; }
|
|
||||||
public string MinecraftVersion { get; }
|
public string MinecraftVersion { get; }
|
||||||
public string NeoforgedVersion { get; }
|
public string NeoforgedVersion { get; }
|
||||||
|
|
||||||
@@ -20,8 +18,6 @@ namespace AlayaCore.Models.Manifests
|
|||||||
|
|
||||||
public ManifestModel(
|
public ManifestModel(
|
||||||
Version alayaVersion,
|
Version alayaVersion,
|
||||||
string requiredJavaVersion,
|
|
||||||
Uri requiredJavaUrl,
|
|
||||||
string minecraftVersion,
|
string minecraftVersion,
|
||||||
string neoforgedVersion,
|
string neoforgedVersion,
|
||||||
Uri serverUrl,
|
Uri serverUrl,
|
||||||
@@ -29,8 +25,6 @@ namespace AlayaCore.Models.Manifests
|
|||||||
IEnumerable<ModFileEntry> files)
|
IEnumerable<ModFileEntry> files)
|
||||||
{
|
{
|
||||||
AlayaVersion = alayaVersion ?? throw new ArgumentNullException(nameof(alayaVersion));
|
AlayaVersion = alayaVersion ?? throw new ArgumentNullException(nameof(alayaVersion));
|
||||||
RequiredJavaVersion = RequireNonEmpty(requiredJavaVersion, nameof(requiredJavaVersion));
|
|
||||||
RequiredJavaBaseUrl = requiredJavaUrl ?? throw new ArgumentNullException(nameof(requiredJavaUrl));
|
|
||||||
|
|
||||||
MinecraftVersion = RequireNonEmpty(minecraftVersion, nameof(minecraftVersion));
|
MinecraftVersion = RequireNonEmpty(minecraftVersion, nameof(minecraftVersion));
|
||||||
|
|
||||||
|
|||||||
@@ -26,12 +26,34 @@ namespace AlayaCore.Services
|
|||||||
_fileStore = fileStore ?? throw new ArgumentNullException(nameof(fileStore));
|
_fileStore = fileStore ?? throw new ArgumentNullException(nameof(fileStore));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<bool> IsAuthenticatedAsync(CancellationToken cancellationToken = default)
|
public async Task<bool> IsAuthenticatedAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
bool authenticated = _session != null && _session.CheckIsValid();
|
if (_session != null && _session.CheckIsValid())
|
||||||
return Task.FromResult(authenticated);
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
JELoginHandler loginHandler = await BuildHandlerAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
_session = await loginHandler
|
||||||
|
.AuthenticateSilently(cancellationToken: cancellationToken)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
return _session != null && _session.CheckIsValid();
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
_session = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task AuthenticateAsync(CancellationToken cancellationToken = default)
|
public async Task AuthenticateAsync(CancellationToken cancellationToken = default)
|
||||||
@@ -46,6 +68,10 @@ namespace AlayaCore.Services
|
|||||||
.AuthenticateSilently(cancellationToken: cancellationToken)
|
.AuthenticateSilently(cancellationToken: cancellationToken)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
_session = await loginHandler
|
_session = await loginHandler
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ using CmlLib.Core;
|
|||||||
using CmlLib.Core.Installer.NeoForge;
|
using CmlLib.Core.Installer.NeoForge;
|
||||||
using CmlLib.Core.Installer.NeoForge.Installers;
|
using CmlLib.Core.Installer.NeoForge.Installers;
|
||||||
using CmlLib.Core.Installers;
|
using CmlLib.Core.Installers;
|
||||||
using CmlLib.Core.Java;
|
|
||||||
using CmlLib.Core.VersionMetadata;
|
|
||||||
|
|
||||||
namespace AlayaCore.Services
|
namespace AlayaCore.Services
|
||||||
{
|
{
|
||||||
@@ -39,7 +37,7 @@ namespace AlayaCore.Services
|
|||||||
ManifestModel manifest,
|
ManifestModel manifest,
|
||||||
InstallEnvironment environment,
|
InstallEnvironment environment,
|
||||||
CancellationToken cancellationToken = default,
|
CancellationToken cancellationToken = default,
|
||||||
EventHandler<InstallerProgressChangedEventArgs>? minecraftProgess = null,
|
EventHandler<InstallerProgressChangedEventArgs>? minecraftProgress = null,
|
||||||
EventHandler<ByteProgress>? byteProgress = null)
|
EventHandler<ByteProgress>? byteProgress = null)
|
||||||
{
|
{
|
||||||
if (manifest == null)
|
if (manifest == null)
|
||||||
@@ -77,7 +75,7 @@ namespace AlayaCore.Services
|
|||||||
await CleanOldInstallAsync(cancellationToken).ConfigureAwait(false);
|
await CleanOldInstallAsync(cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
MinecraftLauncher launcher = GetOrCreateLauncher(minecraftProgess, byteProgress);
|
MinecraftLauncher launcher = GetOrCreateLauncher(minecraftProgress, byteProgress);
|
||||||
|
|
||||||
await launcher
|
await launcher
|
||||||
.InstallAsync(manifest.MinecraftVersion, cancellationToken)
|
.InstallAsync(manifest.MinecraftVersion, cancellationToken)
|
||||||
@@ -122,6 +120,16 @@ namespace AlayaCore.Services
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool neoForgeMismatch =
|
||||||
|
environment.NeoforgedInstalled &&
|
||||||
|
!string.Equals(environment.NeoforgedVersion, manifest.NeoforgedVersion, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
if (neoForgeMismatch)
|
||||||
|
{
|
||||||
|
await CleanOldInstallAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!environment.MinecraftInstalled ||
|
if (!environment.MinecraftInstalled ||
|
||||||
!string.Equals(environment.MinecraftVersion, manifest.MinecraftVersion, StringComparison.OrdinalIgnoreCase))
|
!string.Equals(environment.MinecraftVersion, manifest.MinecraftVersion, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
@@ -135,12 +143,13 @@ namespace AlayaCore.Services
|
|||||||
|
|
||||||
MinecraftLauncher launcher = GetOrCreateLauncher();
|
MinecraftLauncher launcher = GetOrCreateLauncher();
|
||||||
|
|
||||||
await DownloadAndInstallNeoForgeAsync(
|
await InstallNeoForgeAsync(
|
||||||
launcher,
|
launcher,
|
||||||
manifest,
|
manifest,
|
||||||
environment,
|
environment,
|
||||||
cancellationToken,
|
cancellationToken,
|
||||||
progress, byteProgress).ConfigureAwait(false);
|
progress,
|
||||||
|
byteProgress).ConfigureAwait(false);
|
||||||
|
|
||||||
await launcher
|
await launcher
|
||||||
.InstallAsync(manifest.MinecraftVersion, cancellationToken)
|
.InstallAsync(manifest.MinecraftVersion, cancellationToken)
|
||||||
@@ -193,10 +202,13 @@ namespace AlayaCore.Services
|
|||||||
_gamePath = null;
|
_gamePath = null;
|
||||||
_minecraftLauncher = null;
|
_minecraftLauncher = null;
|
||||||
|
|
||||||
await _settingsService.UpdateLaunchVersionAsync(string.Empty, cancellationToken).ConfigureAwait(false);
|
await _settingsService
|
||||||
|
.UpdateLaunchVersionAsync(string.Empty, cancellationToken)
|
||||||
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MinecraftLauncher GetOrCreateLauncher(EventHandler<InstallerProgressChangedEventArgs>? minecraftProgess = null,
|
private MinecraftLauncher GetOrCreateLauncher(
|
||||||
|
EventHandler<InstallerProgressChangedEventArgs>? minecraftProgress = null,
|
||||||
EventHandler<ByteProgress>? byteProgress = null)
|
EventHandler<ByteProgress>? byteProgress = null)
|
||||||
{
|
{
|
||||||
if (_minecraftLauncher != null)
|
if (_minecraftLauncher != null)
|
||||||
@@ -207,17 +219,20 @@ namespace AlayaCore.Services
|
|||||||
_gamePath = new AlayaPath(_fileStore);
|
_gamePath = new AlayaPath(_fileStore);
|
||||||
_minecraftLauncher = new MinecraftLauncher(_gamePath);
|
_minecraftLauncher = new MinecraftLauncher(_gamePath);
|
||||||
|
|
||||||
if(byteProgress != null)
|
if (byteProgress != null)
|
||||||
|
{
|
||||||
_minecraftLauncher.ByteProgressChanged += byteProgress;
|
_minecraftLauncher.ByteProgressChanged += byteProgress;
|
||||||
|
}
|
||||||
|
|
||||||
if(minecraftProgess != null)
|
if (minecraftProgress != null)
|
||||||
_minecraftLauncher.FileProgressChanged += minecraftProgess;
|
{
|
||||||
|
_minecraftLauncher.FileProgressChanged += minecraftProgress;
|
||||||
|
}
|
||||||
|
|
||||||
return _minecraftLauncher;
|
return _minecraftLauncher;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DownloadAndInstallNeoForgeAsync(
|
private async Task InstallNeoForgeAsync(
|
||||||
MinecraftLauncher launcher,
|
MinecraftLauncher launcher,
|
||||||
ManifestModel manifest,
|
ManifestModel manifest,
|
||||||
InstallEnvironment environment,
|
InstallEnvironment environment,
|
||||||
@@ -230,16 +245,6 @@ namespace AlayaCore.Services
|
|||||||
throw new ArgumentNullException(nameof(launcher));
|
throw new ArgumentNullException(nameof(launcher));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool neoForgeMismatch =
|
|
||||||
environment.NeoforgedInstalled &&
|
|
||||||
!string.Equals(environment.NeoforgedVersion, manifest.NeoforgedVersion, StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
if (neoForgeMismatch)
|
|
||||||
{
|
|
||||||
await CleanOldInstallAsync(cancellationToken).ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
NeoForgeInstaller installer = new NeoForgeInstaller(launcher);
|
NeoForgeInstaller installer = new NeoForgeInstaller(launcher);
|
||||||
|
|
||||||
NeoForgeInstallOptions options = new NeoForgeInstallOptions
|
NeoForgeInstallOptions options = new NeoForgeInstallOptions
|
||||||
@@ -249,11 +254,15 @@ namespace AlayaCore.Services
|
|||||||
SkipIfAlreadyInstalled = true
|
SkipIfAlreadyInstalled = true
|
||||||
};
|
};
|
||||||
|
|
||||||
if(progress != null)
|
if (progress != null)
|
||||||
|
{
|
||||||
options.FileProgress = progress;
|
options.FileProgress = progress;
|
||||||
|
}
|
||||||
|
|
||||||
if(byteProgress != null)
|
if (byteProgress != null)
|
||||||
|
{
|
||||||
options.ByteProgress = byteProgress;
|
options.ByteProgress = byteProgress;
|
||||||
|
}
|
||||||
|
|
||||||
string version = await installer
|
string version = await installer
|
||||||
.Install(manifest.MinecraftVersion, manifest.NeoforgedVersion, options)
|
.Install(manifest.MinecraftVersion, manifest.NeoforgedVersion, options)
|
||||||
|
|||||||
@@ -8,9 +8,7 @@ using AlayaCore.Installation;
|
|||||||
using AlayaCore.Models;
|
using AlayaCore.Models;
|
||||||
using AlayaCore.Models.Configuration;
|
using AlayaCore.Models.Configuration;
|
||||||
using AlayaCore.Models.Manifests;
|
using AlayaCore.Models.Manifests;
|
||||||
using AlayaCore.Utilities.Enums;
|
|
||||||
using CmlLib.Core;
|
using CmlLib.Core;
|
||||||
using CmlLib.Core.Auth;
|
|
||||||
using CmlLib.Core.ProcessBuilder;
|
using CmlLib.Core.ProcessBuilder;
|
||||||
|
|
||||||
namespace AlayaCore.Services
|
namespace AlayaCore.Services
|
||||||
@@ -22,7 +20,6 @@ namespace AlayaCore.Services
|
|||||||
private readonly ILaunchDirector _director;
|
private readonly ILaunchDirector _director;
|
||||||
private readonly GameOptions _gameOptions;
|
private readonly GameOptions _gameOptions;
|
||||||
|
|
||||||
private AlayaPath? _gamePath;
|
|
||||||
private MinecraftLauncher? _minecraftLauncher;
|
private MinecraftLauncher? _minecraftLauncher;
|
||||||
|
|
||||||
public GameLaunchService(
|
public GameLaunchService(
|
||||||
@@ -69,7 +66,11 @@ namespace AlayaCore.Services
|
|||||||
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
MLaunchOption option = await BuildLaunchOptions(manifest, environment);
|
MLaunchOption option = await BuildLaunchOptionsAsync(
|
||||||
|
manifest,
|
||||||
|
environment,
|
||||||
|
cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
MinecraftLauncher launcher = GetOrCreateLauncher();
|
MinecraftLauncher launcher = GetOrCreateLauncher();
|
||||||
|
|
||||||
var process = await launcher
|
var process = await launcher
|
||||||
@@ -89,27 +90,23 @@ namespace AlayaCore.Services
|
|||||||
return _minecraftLauncher;
|
return _minecraftLauncher;
|
||||||
}
|
}
|
||||||
|
|
||||||
_gamePath = new AlayaPath(_fileStore);
|
_minecraftLauncher = new MinecraftLauncher(new AlayaPath(_fileStore));
|
||||||
_minecraftLauncher = new MinecraftLauncher(_gamePath);
|
|
||||||
|
|
||||||
return _minecraftLauncher;
|
return _minecraftLauncher;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetMinecraftPath()
|
private async Task<MLaunchOption> BuildLaunchOptionsAsync(
|
||||||
{
|
ManifestModel manifest,
|
||||||
return _fileStore.GetOrCreate(FolderLocation.Game);
|
InstallEnvironment environment,
|
||||||
}
|
CancellationToken cancellationToken)
|
||||||
|
|
||||||
private async Task<MLaunchOption> BuildLaunchOptions(ManifestModel manifest, InstallEnvironment environment)
|
|
||||||
{
|
{
|
||||||
if (manifest.ServerUrl == null)
|
if (manifest.ServerUrl == null)
|
||||||
{
|
{
|
||||||
throw new InvalidDataException("Manifest Server Url is not configured.");
|
throw new InvalidDataException("Manifest ServerUrl is not configured.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new MLaunchOption
|
return new MLaunchOption
|
||||||
{
|
{
|
||||||
Session = await _authService.GetSessionAsync(),
|
Session = await _authService.GetSessionAsync(cancellationToken).ConfigureAwait(false),
|
||||||
JavaPath = environment.JavaPath,
|
JavaPath = environment.JavaPath,
|
||||||
MinimumRamMb = _gameOptions.MinimumRamMB,
|
MinimumRamMb = _gameOptions.MinimumRamMB,
|
||||||
MaximumRamMb = _gameOptions.MaximumRamMB,
|
MaximumRamMb = _gameOptions.MaximumRamMB,
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace AlayaCore.Services
|
|||||||
{
|
{
|
||||||
public sealed class HttpDownloadService : IDownloadService
|
public sealed class HttpDownloadService : IDownloadService
|
||||||
{
|
{
|
||||||
private const int BUFFER_SIZE = 81920;
|
private const int BufferSize = 81920;
|
||||||
|
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClient _httpClient;
|
||||||
|
|
||||||
@@ -45,16 +45,10 @@ namespace AlayaCore.Services
|
|||||||
throw new ArgumentException("Destination path cannot be null, empty, or whitespace.", nameof(destinationPath));
|
throw new ArgumentException("Destination path cannot be null, empty, or whitespace.", nameof(destinationPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(sha512Hash))
|
string normalizedExpectedHash = NormalizeHash(sha512Hash);
|
||||||
{
|
|
||||||
throw new ArgumentException("SHA-512 hash cannot be null, empty, or whitespace.", nameof(sha512Hash));
|
|
||||||
}
|
|
||||||
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
string normalizedExpectedHash = NormalizeHash(sha512Hash);
|
|
||||||
string fileName = Path.GetFileName(destinationPath);
|
string fileName = Path.GetFileName(destinationPath);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(fileName))
|
if (string.IsNullOrWhiteSpace(fileName))
|
||||||
{
|
{
|
||||||
throw new ArgumentException("Destination path must include a file name.", nameof(destinationPath));
|
throw new ArgumentException("Destination path must include a file name.", nameof(destinationPath));
|
||||||
@@ -69,7 +63,7 @@ namespace AlayaCore.Services
|
|||||||
progress?.Report(new DownloadProgress(
|
progress?.Report(new DownloadProgress(
|
||||||
fileName: fileName,
|
fileName: fileName,
|
||||||
destinationPath: destinationPath,
|
destinationPath: destinationPath,
|
||||||
bytesDownloaded: existingLength,
|
bytesDownloaded: 0,
|
||||||
totalBytes: existingLength,
|
totalBytes: existingLength,
|
||||||
bytesPerSecond: null,
|
bytesPerSecond: null,
|
||||||
statusMessage: "File already present and valid."));
|
statusMessage: "File already present and valid."));
|
||||||
@@ -91,7 +85,7 @@ namespace AlayaCore.Services
|
|||||||
using HttpResponseMessage response = await _httpClient.GetAsync(
|
using HttpResponseMessage response = await _httpClient.GetAsync(
|
||||||
sourceUri,
|
sourceUri,
|
||||||
HttpCompletionOption.ResponseHeadersRead,
|
HttpCompletionOption.ResponseHeadersRead,
|
||||||
cancellationToken);
|
cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
response.EnsureSuccessStatusCode();
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
@@ -106,17 +100,21 @@ namespace AlayaCore.Services
|
|||||||
bytesPerSecond: null,
|
bytesPerSecond: null,
|
||||||
statusMessage: "Starting download..."));
|
statusMessage: "Starting download..."));
|
||||||
|
|
||||||
await using Stream responseStream = await response.Content.ReadAsStreamAsync();
|
await using Stream responseStream = await response.Content
|
||||||
|
.ReadAsStreamAsync()
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
await using FileStream fileStream = new FileStream(
|
await using FileStream fileStream = new FileStream(
|
||||||
tempFilePath,
|
tempFilePath,
|
||||||
FileMode.Create,
|
FileMode.Create,
|
||||||
FileAccess.Write,
|
FileAccess.Write,
|
||||||
FileShare.None,
|
FileShare.None,
|
||||||
BUFFER_SIZE,
|
BufferSize,
|
||||||
useAsync: true);
|
useAsync: true);
|
||||||
|
|
||||||
using SHA512 sha512 = SHA512.Create();
|
using SHA512 sha512 = SHA512.Create();
|
||||||
|
|
||||||
byte[] buffer = new byte[BUFFER_SIZE];
|
byte[] buffer = new byte[BufferSize];
|
||||||
Stopwatch stopwatch = Stopwatch.StartNew();
|
Stopwatch stopwatch = Stopwatch.StartNew();
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
@@ -125,7 +123,7 @@ namespace AlayaCore.Services
|
|||||||
buffer,
|
buffer,
|
||||||
0,
|
0,
|
||||||
buffer.Length,
|
buffer.Length,
|
||||||
cancellationToken);
|
cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (bytesRead == 0)
|
if (bytesRead == 0)
|
||||||
{
|
{
|
||||||
@@ -136,7 +134,7 @@ namespace AlayaCore.Services
|
|||||||
buffer,
|
buffer,
|
||||||
0,
|
0,
|
||||||
bytesRead,
|
bytesRead,
|
||||||
cancellationToken);
|
cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
sha512.TransformBlock(buffer, 0, bytesRead, null, 0);
|
sha512.TransformBlock(buffer, 0, bytesRead, null, 0);
|
||||||
|
|
||||||
@@ -158,10 +156,9 @@ namespace AlayaCore.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
sha512.TransformFinalBlock(Array.Empty<byte>(), 0, 0);
|
sha512.TransformFinalBlock(Array.Empty<byte>(), 0, 0);
|
||||||
await fileStream.FlushAsync(cancellationToken);
|
await fileStream.FlushAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
string actualHash = ConvertToLowerHex(sha512.Hash);
|
string actualHash = ConvertToLowerHex(sha512.Hash);
|
||||||
|
|
||||||
if (!string.Equals(actualHash, normalizedExpectedHash, StringComparison.OrdinalIgnoreCase))
|
if (!string.Equals(actualHash, normalizedExpectedHash, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
throw new InvalidDataException(
|
throw new InvalidDataException(
|
||||||
@@ -204,18 +201,13 @@ namespace AlayaCore.Services
|
|||||||
throw new ArgumentException("File path cannot be null, empty, or whitespace.", nameof(filePath));
|
throw new ArgumentException("File path cannot be null, empty, or whitespace.", nameof(filePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(sha512Hash))
|
string normalizedExpectedHash = NormalizeHash(sha512Hash);
|
||||||
{
|
|
||||||
throw new ArgumentException("SHA-512 hash cannot be null, empty, or whitespace.", nameof(sha512Hash));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!File.Exists(filePath))
|
if (!File.Exists(filePath))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
string normalizedExpectedHash = NormalizeHash(sha512Hash);
|
|
||||||
|
|
||||||
using FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
using FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
using SHA512 sha512 = SHA512.Create();
|
using SHA512 sha512 = SHA512.Create();
|
||||||
|
|
||||||
@@ -228,6 +220,7 @@ namespace AlayaCore.Services
|
|||||||
private static void EnsureDestinationDirectoryExists(string destinationPath)
|
private static void EnsureDestinationDirectoryExists(string destinationPath)
|
||||||
{
|
{
|
||||||
string? directoryPath = Path.GetDirectoryName(destinationPath);
|
string? directoryPath = Path.GetDirectoryName(destinationPath);
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(directoryPath))
|
if (!string.IsNullOrWhiteSpace(directoryPath))
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(directoryPath);
|
Directory.CreateDirectory(directoryPath);
|
||||||
@@ -250,7 +243,31 @@ namespace AlayaCore.Services
|
|||||||
|
|
||||||
private static string NormalizeHash(string hash)
|
private static string NormalizeHash(string hash)
|
||||||
{
|
{
|
||||||
return hash.Trim().Replace("-", string.Empty).ToLowerInvariant();
|
if (string.IsNullOrWhiteSpace(hash))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("SHA-512 hash cannot be null, empty, or whitespace.", nameof(hash));
|
||||||
|
}
|
||||||
|
|
||||||
|
string normalized = hash.Trim().Replace("-", string.Empty).ToLowerInvariant();
|
||||||
|
|
||||||
|
if (normalized.Length != 128)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("SHA-512 hash must be 128 hexadecimal characters long.", nameof(hash));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (char c in normalized)
|
||||||
|
{
|
||||||
|
bool isHex =
|
||||||
|
(c >= '0' && c <= '9') ||
|
||||||
|
(c >= 'a' && c <= 'f');
|
||||||
|
|
||||||
|
if (!isHex)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("SHA-512 hash contains invalid characters.", nameof(hash));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string ConvertToLowerHex(byte[]? hashBytes)
|
private static string ConvertToLowerHex(byte[]? hashBytes)
|
||||||
|
|||||||
@@ -137,9 +137,9 @@ namespace AlayaCore.Services
|
|||||||
{
|
{
|
||||||
string executableName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
string executableName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
||||||
? "javaw.exe"
|
? "javaw.exe"
|
||||||
: "javaw";
|
: "java";
|
||||||
|
|
||||||
string runtimePath = _fileStore.GetOrCreate(FolderLocation.JavaRuntime);
|
string runtimePath = _fileStore.Get(FolderLocation.JavaRuntime);
|
||||||
string fullPath = Path.Combine(runtimePath, "bin", executableName);
|
string fullPath = Path.Combine(runtimePath, "bin", executableName);
|
||||||
|
|
||||||
if (!File.Exists(fullPath))
|
if (!File.Exists(fullPath))
|
||||||
@@ -161,7 +161,10 @@ namespace AlayaCore.Services
|
|||||||
return InstalledVersionState.Empty();
|
return InstalledVersionState.Empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
string[] versionDirectories = Directory.GetDirectories(versionsPath);
|
string[] versionDirectories = Directory
|
||||||
|
.GetDirectories(versionsPath)
|
||||||
|
.OrderBy(path => path, StringComparer.OrdinalIgnoreCase)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
if (versionDirectories.Length == 0)
|
if (versionDirectories.Length == 0)
|
||||||
{
|
{
|
||||||
@@ -187,7 +190,10 @@ namespace AlayaCore.Services
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
JObject versionJson = LoadJson(versionJsonPath);
|
if (!TryLoadJson(versionJsonPath, out JObject? versionJson))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
string? id = versionJson.Value<string>("id");
|
string? id = versionJson.Value<string>("id");
|
||||||
string? inheritsFrom = versionJson.Value<string>("inheritsFrom");
|
string? inheritsFrom = versionJson.Value<string>("inheritsFrom");
|
||||||
@@ -199,7 +205,7 @@ namespace AlayaCore.Services
|
|||||||
|
|
||||||
if (IsNeoForgeVersion(id, inheritsFrom))
|
if (IsNeoForgeVersion(id, inheritsFrom))
|
||||||
{
|
{
|
||||||
neoForgeVersion = id;
|
neoForgeVersion ??= id;
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(minecraftVersion) && !string.IsNullOrWhiteSpace(inheritsFrom))
|
if (string.IsNullOrWhiteSpace(minecraftVersion) && !string.IsNullOrWhiteSpace(inheritsFrom))
|
||||||
{
|
{
|
||||||
@@ -209,10 +215,7 @@ namespace AlayaCore.Services
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(minecraftVersion))
|
minecraftVersion ??= id;
|
||||||
{
|
|
||||||
minecraftVersion = id;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new InstalledVersionState(minecraftVersion, neoForgeVersion);
|
return new InstalledVersionState(minecraftVersion, neoForgeVersion);
|
||||||
@@ -220,7 +223,7 @@ namespace AlayaCore.Services
|
|||||||
|
|
||||||
private string GetVersionsPath()
|
private string GetVersionsPath()
|
||||||
{
|
{
|
||||||
return Path.Combine(_fileStore.GetOrCreate(FolderLocation.Game), VersionsFolderName);
|
return Path.Combine(_fileStore.Get(FolderLocation.Game), VersionsFolderName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsNeoForgeVersion(string? id, string? inheritsFrom)
|
private static bool IsNeoForgeVersion(string? id, string? inheritsFrom)
|
||||||
@@ -239,21 +242,31 @@ namespace AlayaCore.Services
|
|||||||
value.Contains("neoforged", StringComparison.OrdinalIgnoreCase);
|
value.Contains("neoforged", StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JObject LoadJson(string path)
|
private static bool TryLoadJson(string path, out JObject? jsonObject)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(path))
|
jsonObject = null;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(path) || !File.Exists(path))
|
||||||
{
|
{
|
||||||
throw new ArgumentException("Path cannot be null, empty, or whitespace.", nameof(path));
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
string json = File.ReadAllText(path);
|
string json = File.ReadAllText(path);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(json))
|
if (string.IsNullOrWhiteSpace(json))
|
||||||
{
|
{
|
||||||
throw new InvalidDataException($"File '{path}' was empty.");
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return JObject.Parse(json);
|
try
|
||||||
|
{
|
||||||
|
jsonObject = JObject.Parse(json);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class InstalledVersionState
|
private sealed class InstalledVersionState
|
||||||
|
|||||||
@@ -40,30 +40,65 @@ namespace AlayaCore.Services
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (localManifest.Version == null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(localManifest.Sha512Hash))
|
if (string.IsNullOrWhiteSpace(localManifest.Sha512Hash))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
string remoteHash = await _manifestService
|
LauncherManifestModel remoteManifest = await _manifestService
|
||||||
.GetRemoteLauncherManifestHashAsync(cancellationToken)
|
.GetRemoteLauncherManifestAsync(cancellationToken)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(remoteHash))
|
if (remoteManifest == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Remote launcher manifest could not be loaded.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remoteManifest.Version == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Remote launcher manifest returned an invalid version.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(remoteManifest.Sha512Hash))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Remote launcher manifest returned an invalid SHA-512 hash.");
|
throw new InvalidOperationException("Remote launcher manifest returned an invalid SHA-512 hash.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return !string.Equals(
|
bool versionMismatch = localManifest.Version != remoteManifest.Version;
|
||||||
|
bool hashMismatch = !string.Equals(
|
||||||
localManifest.Sha512Hash.Trim(),
|
localManifest.Sha512Hash.Trim(),
|
||||||
remoteHash.Trim(),
|
remoteManifest.Sha512Hash.Trim(),
|
||||||
StringComparison.OrdinalIgnoreCase);
|
StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
return versionMismatch || hashMismatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task LaunchUpdaterAsync(LauncherManifestModel newManifest, CancellationToken cancellationToken = default)
|
public Task LaunchUpdaterAsync(
|
||||||
|
LauncherManifestModel newManifest,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
if (newManifest == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(newManifest));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newManifest.DownloadUri == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Launcher manifest does not contain a download URI.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!newManifest.DownloadUri.IsAbsoluteUri)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Launcher download URI must be absolute.");
|
||||||
|
}
|
||||||
|
|
||||||
string updaterPath = _options.AlayaUpdaterPath;
|
string updaterPath = _options.AlayaUpdaterPath;
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(updaterPath))
|
if (string.IsNullOrWhiteSpace(updaterPath))
|
||||||
@@ -84,11 +119,13 @@ namespace AlayaCore.Services
|
|||||||
string workingDirectory = Path.GetDirectoryName(updaterPath)
|
string workingDirectory = Path.GetDirectoryName(updaterPath)
|
||||||
?? throw new InvalidOperationException("Updater working directory could not be resolved.");
|
?? throw new InvalidOperationException("Updater working directory could not be resolved.");
|
||||||
|
|
||||||
|
string arguments = $"-url \"{newManifest.DownloadUri.AbsoluteUri}\"";
|
||||||
|
|
||||||
var startInfo = new ProcessStartInfo
|
var startInfo = new ProcessStartInfo
|
||||||
{
|
{
|
||||||
FileName = updaterPath,
|
FileName = updaterPath,
|
||||||
WorkingDirectory = workingDirectory,
|
WorkingDirectory = workingDirectory,
|
||||||
Arguments = $@"-url {newManifest.DownloadUri}",
|
Arguments = arguments,
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
CreateNoWindow = true
|
CreateNoWindow = true
|
||||||
};
|
};
|
||||||
@@ -102,7 +139,7 @@ namespace AlayaCore.Services
|
|||||||
throw new InvalidOperationException("Failed to start updater process.");
|
throw new InvalidOperationException("Failed to start updater process.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex) when (!(ex is OperationCanceledException))
|
catch (Exception ex) when (ex is not OperationCanceledException)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Failed to launch updater process.", ex);
|
throw new InvalidOperationException("Failed to launch updater process.", ex);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ namespace AlayaCore.Services
|
|||||||
{
|
{
|
||||||
public sealed class ManifestService : IManifestService
|
public sealed class ManifestService : IManifestService
|
||||||
{
|
{
|
||||||
private const string CORE_MANIFEST_FILE_NAME = "CoreManifest.json";
|
private const string CoreManifestFileName = "CoreManifest.json";
|
||||||
private const string LAUNCHER_MANIFEST_FILE_NAME = "LauncherManifest.json";
|
private const string LauncherManifestFileName = "LauncherManifest.json";
|
||||||
private const string INSTALLED_MODS_MANIFEST_FILE_NAME = "InstalledModsManifest.json";
|
private const string InstalledModsManifestFileName = "InstalledModsManifest.json";
|
||||||
|
|
||||||
private readonly IDownloadService _downloadService;
|
private readonly IDownloadService _downloadService;
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClient _httpClient;
|
||||||
@@ -50,7 +50,8 @@ namespace AlayaCore.Services
|
|||||||
cancellationToken);
|
cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<InstalledModsManifestModel> GetInstalledModsManifestAsync(CancellationToken cancellationToken = default)
|
public async Task<InstalledModsManifestModel> GetInstalledModsManifestAsync(
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
string path = GetInstalledModsManifestPath();
|
string path = GetInstalledModsManifestPath();
|
||||||
|
|
||||||
@@ -66,11 +67,12 @@ namespace AlayaCore.Services
|
|||||||
return InstalledModsManifestModel.Empty();
|
return InstalledModsManifestModel.Empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
InstalledModsManifestModel? manifest = DeserializeAndMapManifest<InstalledModsManifestDto, InstalledModsManifestModel>(
|
InstalledModsManifestModel? manifest =
|
||||||
json,
|
DeserializeAndMapManifest<InstalledModsManifestDto, InstalledModsManifestModel>(
|
||||||
path,
|
json,
|
||||||
static dto => dto.ToModel(),
|
path,
|
||||||
swallowDeserializationErrors: true);
|
static dto => dto.ToModel(),
|
||||||
|
swallowDeserializationErrors: true);
|
||||||
|
|
||||||
return manifest ?? InstalledModsManifestModel.Empty();
|
return manifest ?? InstalledModsManifestModel.Empty();
|
||||||
}
|
}
|
||||||
@@ -105,28 +107,10 @@ namespace AlayaCore.Services
|
|||||||
|
|
||||||
public async Task<Version> GetRemoteCoreManifestVersionAsync(CancellationToken cancellationToken = default)
|
public async Task<Version> GetRemoteCoreManifestVersionAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
ManifestModel remoteManifest = await GetRemoteManifestAsync<ManifestDto, ManifestModel>(
|
||||||
|
|
||||||
using HttpResponseMessage response = await _httpClient.GetAsync(
|
|
||||||
_options.CoreManifestUri,
|
_options.CoreManifestUri,
|
||||||
HttpCompletionOption.ResponseContentRead,
|
|
||||||
cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
|
|
||||||
string json = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(json))
|
|
||||||
{
|
|
||||||
throw new InvalidDataException(
|
|
||||||
$"Remote core manifest response from '{_options.CoreManifestUri}' was empty.");
|
|
||||||
}
|
|
||||||
|
|
||||||
ManifestModel remoteManifest = DeserializeAndMapManifest<ManifestDto, ManifestModel>(
|
|
||||||
json,
|
|
||||||
_options.CoreManifestUri.ToString(),
|
|
||||||
static dto => dto.ToModel(),
|
static dto => dto.ToModel(),
|
||||||
swallowDeserializationErrors: false)!;
|
cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (remoteManifest.AlayaVersion == null)
|
if (remoteManifest.AlayaVersion == null)
|
||||||
{
|
{
|
||||||
@@ -137,30 +121,13 @@ namespace AlayaCore.Services
|
|||||||
return remoteManifest.AlayaVersion;
|
return remoteManifest.AlayaVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> GetRemoteLauncherManifestHashAsync(CancellationToken cancellationToken = default)
|
public async Task<LauncherManifestModel> GetRemoteLauncherManifestAsync(
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
LauncherManifestModel remoteManifest = await GetRemoteManifestAsync<LauncherManifestDto, LauncherManifestModel>(
|
||||||
|
|
||||||
using HttpResponseMessage response = await _httpClient.GetAsync(
|
|
||||||
_options.LauncherManifestUri,
|
_options.LauncherManifestUri,
|
||||||
HttpCompletionOption.ResponseContentRead,
|
|
||||||
cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
|
|
||||||
string json = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(json))
|
|
||||||
{
|
|
||||||
throw new InvalidDataException(
|
|
||||||
$"Remote launcher manifest response from '{_options.LauncherManifestUri}' was empty.");
|
|
||||||
}
|
|
||||||
|
|
||||||
LauncherManifestModel remoteManifest = DeserializeAndMapManifest<LauncherManifestDto, LauncherManifestModel>(
|
|
||||||
json,
|
|
||||||
_options.LauncherManifestUri.ToString(),
|
|
||||||
static dto => dto.ToModel(),
|
static dto => dto.ToModel(),
|
||||||
swallowDeserializationErrors: false)!;
|
cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(remoteManifest.Sha512Hash))
|
if (string.IsNullOrWhiteSpace(remoteManifest.Sha512Hash))
|
||||||
{
|
{
|
||||||
@@ -168,22 +135,28 @@ namespace AlayaCore.Services
|
|||||||
$"Remote launcher manifest from '{_options.LauncherManifestUri}' does not contain a valid SHA-512 hash.");
|
$"Remote launcher manifest from '{_options.LauncherManifestUri}' does not contain a valid SHA-512 hash.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return remoteManifest.Sha512Hash.Trim();
|
if (remoteManifest.DownloadUri == null || !remoteManifest.DownloadUri.IsAbsoluteUri)
|
||||||
|
{
|
||||||
|
throw new InvalidDataException(
|
||||||
|
$"Remote launcher manifest from '{_options.LauncherManifestUri}' does not contain a valid download URI.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return remoteManifest;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetLauncherManifestPath()
|
public string GetLauncherManifestPath()
|
||||||
{
|
{
|
||||||
return Path.Combine(_fileStore.GetOrCreate(FolderLocation.Manifests), LAUNCHER_MANIFEST_FILE_NAME);
|
return Path.Combine(_fileStore.Get(FolderLocation.Manifests), LauncherManifestFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetCoreManifestPath()
|
public string GetCoreManifestPath()
|
||||||
{
|
{
|
||||||
return Path.Combine(_fileStore.GetOrCreate(FolderLocation.Manifests), CORE_MANIFEST_FILE_NAME);
|
return Path.Combine(_fileStore.Get(FolderLocation.Manifests), CoreManifestFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetInstalledModsManifestPath()
|
public string GetInstalledModsManifestPath()
|
||||||
{
|
{
|
||||||
return Path.Combine(_fileStore.GetOrCreate(FolderLocation.Manifests), INSTALLED_MODS_MANIFEST_FILE_NAME);
|
return Path.Combine(_fileStore.Get(FolderLocation.Manifests), InstalledModsManifestFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<TModel?> LoadLocalManifestAsync<TDto, TModel>(
|
private async Task<TModel?> LoadLocalManifestAsync<TDto, TModel>(
|
||||||
@@ -283,6 +256,51 @@ namespace AlayaCore.Services
|
|||||||
swallowDeserializationErrors: false)!;
|
swallowDeserializationErrors: false)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<TModel> GetRemoteManifestAsync<TDto, TModel>(
|
||||||
|
Uri manifestUri,
|
||||||
|
Func<TDto, TModel> map,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
where TDto : class
|
||||||
|
{
|
||||||
|
if (manifestUri == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(manifestUri));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!manifestUri.IsAbsoluteUri)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Manifest URI must be absolute.", nameof(manifestUri));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(map));
|
||||||
|
}
|
||||||
|
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
using HttpResponseMessage response = await _httpClient.GetAsync(
|
||||||
|
manifestUri,
|
||||||
|
HttpCompletionOption.ResponseContentRead,
|
||||||
|
cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
string json = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(json))
|
||||||
|
{
|
||||||
|
throw new InvalidDataException(
|
||||||
|
$"Remote manifest response from '{manifestUri}' was empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return DeserializeAndMapManifest<TDto, TModel>(
|
||||||
|
json,
|
||||||
|
manifestUri.ToString(),
|
||||||
|
map,
|
||||||
|
swallowDeserializationErrors: false)!;
|
||||||
|
}
|
||||||
|
|
||||||
private static TModel? DeserializeAndMapManifest<TDto, TModel>(
|
private static TModel? DeserializeAndMapManifest<TDto, TModel>(
|
||||||
string json,
|
string json,
|
||||||
string sourceName,
|
string sourceName,
|
||||||
@@ -342,7 +360,7 @@ namespace AlayaCore.Services
|
|||||||
{
|
{
|
||||||
return map(dto);
|
return map(dto);
|
||||||
}
|
}
|
||||||
catch (Exception ex) when (!(ex is OperationCanceledException))
|
catch (Exception ex) when (ex is not OperationCanceledException)
|
||||||
{
|
{
|
||||||
if (swallowDeserializationErrors)
|
if (swallowDeserializationErrors)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ namespace AlayaCore.States
|
|||||||
Ready,
|
Ready,
|
||||||
LauncherNeedsUpdate,
|
LauncherNeedsUpdate,
|
||||||
NeedAuthenticating,
|
NeedAuthenticating,
|
||||||
InstallJava,
|
|
||||||
InstallMinecraft,
|
InstallMinecraft,
|
||||||
InstallNeoforge,
|
InstallNeoforge,
|
||||||
SyncMods
|
SyncMods
|
||||||
@@ -14,7 +13,6 @@ namespace AlayaCore.States
|
|||||||
public sealed class LaunchPlan
|
public sealed class LaunchPlan
|
||||||
{
|
{
|
||||||
public bool LauncherNeedsUpdate { get; }
|
public bool LauncherNeedsUpdate { get; }
|
||||||
public bool JavaNeedsInstallOrUpdate { get; }
|
|
||||||
public bool MinecraftNeedsInstallOrUpdate { get; }
|
public bool MinecraftNeedsInstallOrUpdate { get; }
|
||||||
public bool NeoforgeNeedsInstallOrUpdate { get; }
|
public bool NeoforgeNeedsInstallOrUpdate { get; }
|
||||||
public bool ModsNeedSync { get; }
|
public bool ModsNeedSync { get; }
|
||||||
@@ -26,7 +24,6 @@ namespace AlayaCore.States
|
|||||||
|
|
||||||
public bool NeedsUpdating =>
|
public bool NeedsUpdating =>
|
||||||
LauncherNeedsUpdate ||
|
LauncherNeedsUpdate ||
|
||||||
JavaNeedsInstallOrUpdate ||
|
|
||||||
MinecraftNeedsInstallOrUpdate ||
|
MinecraftNeedsInstallOrUpdate ||
|
||||||
NeoforgeNeedsInstallOrUpdate ||
|
NeoforgeNeedsInstallOrUpdate ||
|
||||||
ModsNeedSync;
|
ModsNeedSync;
|
||||||
@@ -36,14 +33,12 @@ namespace AlayaCore.States
|
|||||||
|
|
||||||
public LaunchPlan(
|
public LaunchPlan(
|
||||||
bool launcherNeedsUpdate,
|
bool launcherNeedsUpdate,
|
||||||
bool javaNeedsInstallOrUpdate,
|
|
||||||
bool minecraftNeedsInstallOrUpdate,
|
bool minecraftNeedsInstallOrUpdate,
|
||||||
bool neoforgeNeedsInstallOrUpdate,
|
bool neoforgeNeedsInstallOrUpdate,
|
||||||
bool modsNeedSync,
|
bool modsNeedSync,
|
||||||
bool needAuthenticating)
|
bool needAuthenticating)
|
||||||
{
|
{
|
||||||
LauncherNeedsUpdate = launcherNeedsUpdate;
|
LauncherNeedsUpdate = launcherNeedsUpdate;
|
||||||
JavaNeedsInstallOrUpdate = javaNeedsInstallOrUpdate;
|
|
||||||
MinecraftNeedsInstallOrUpdate = minecraftNeedsInstallOrUpdate;
|
MinecraftNeedsInstallOrUpdate = minecraftNeedsInstallOrUpdate;
|
||||||
NeoforgeNeedsInstallOrUpdate = neoforgeNeedsInstallOrUpdate;
|
NeoforgeNeedsInstallOrUpdate = neoforgeNeedsInstallOrUpdate;
|
||||||
ModsNeedSync = modsNeedSync;
|
ModsNeedSync = modsNeedSync;
|
||||||
@@ -58,9 +53,6 @@ namespace AlayaCore.States
|
|||||||
if (NeedAuthenticating)
|
if (NeedAuthenticating)
|
||||||
return LaunchState.NeedAuthenticating;
|
return LaunchState.NeedAuthenticating;
|
||||||
|
|
||||||
if (JavaNeedsInstallOrUpdate)
|
|
||||||
return LaunchState.InstallJava;
|
|
||||||
|
|
||||||
if (MinecraftNeedsInstallOrUpdate)
|
if (MinecraftNeedsInstallOrUpdate)
|
||||||
return LaunchState.InstallMinecraft;
|
return LaunchState.InstallMinecraft;
|
||||||
|
|
||||||
@@ -77,7 +69,6 @@ namespace AlayaCore.States
|
|||||||
{
|
{
|
||||||
return new LaunchPlan(
|
return new LaunchPlan(
|
||||||
launcherNeedsUpdate: false,
|
launcherNeedsUpdate: false,
|
||||||
javaNeedsInstallOrUpdate: false,
|
|
||||||
minecraftNeedsInstallOrUpdate: false,
|
minecraftNeedsInstallOrUpdate: false,
|
||||||
neoforgeNeedsInstallOrUpdate: false,
|
neoforgeNeedsInstallOrUpdate: false,
|
||||||
modsNeedSync: false,
|
modsNeedSync: false,
|
||||||
|
|||||||
@@ -47,8 +47,6 @@ namespace AlayaCore.Utilities.Extensions
|
|||||||
|
|
||||||
return new ManifestModel(
|
return new ManifestModel(
|
||||||
dto.AlayaVersion,
|
dto.AlayaVersion,
|
||||||
dto.RequiredJavaVersion,
|
|
||||||
dto.RequiredJavaUrl,
|
|
||||||
dto.MinecraftVersion,
|
dto.MinecraftVersion,
|
||||||
dto.NeoforgedVersion,
|
dto.NeoforgedVersion,
|
||||||
dto.ServerUrl,
|
dto.ServerUrl,
|
||||||
@@ -80,8 +78,6 @@ namespace AlayaCore.Utilities.Extensions
|
|||||||
return new ManifestDto
|
return new ManifestDto
|
||||||
{
|
{
|
||||||
AlayaVersion = model.AlayaVersion,
|
AlayaVersion = model.AlayaVersion,
|
||||||
RequiredJavaVersion = model.RequiredJavaVersion,
|
|
||||||
RequiredJavaUrl = model.RequiredJavaBaseUrl,
|
|
||||||
MinecraftVersion = model.MinecraftVersion,
|
MinecraftVersion = model.MinecraftVersion,
|
||||||
NeoforgedVersion = model.NeoforgedVersion,
|
NeoforgedVersion = model.NeoforgedVersion,
|
||||||
Files = model.Files.Select(file => file.ToDto()).ToList()
|
Files = model.Files.Select(file => file.ToDto()).ToList()
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace AlayaCore.Utilities.Stores
|
|||||||
{
|
{
|
||||||
private static readonly string BaseDirectoryPath = AppContext.BaseDirectory;
|
private static readonly string BaseDirectoryPath = AppContext.BaseDirectory;
|
||||||
private static readonly string JavaDirectoryPath = Path.Combine(BaseDirectoryPath, "Java");
|
private static readonly string JavaDirectoryPath = Path.Combine(BaseDirectoryPath, "Java");
|
||||||
private static readonly string JavaRuntimeDirectoryPath = Path.Combine(JavaDirectoryPath, "java-runtime-epsilon");
|
private static readonly string JavaRuntimeDirectoryPath = Path.Combine(JavaDirectoryPath, "runtime");
|
||||||
private static readonly string GameDirectoryPath = Path.Combine(BaseDirectoryPath, "Game");
|
private static readonly string GameDirectoryPath = Path.Combine(BaseDirectoryPath, "Game");
|
||||||
private static readonly string ModsDirectoryPath = Path.Combine(GameDirectoryPath, "mods");
|
private static readonly string ModsDirectoryPath = Path.Combine(GameDirectoryPath, "mods");
|
||||||
private static readonly string ResourcePacksDirectoryPath = Path.Combine(GameDirectoryPath, "resourcepacks");
|
private static readonly string ResourcePacksDirectoryPath = Path.Combine(GameDirectoryPath, "resourcepacks");
|
||||||
@@ -36,6 +36,26 @@ namespace AlayaCore.Utilities.Stores
|
|||||||
{ FolderLocation.Data, DataDirectoryPath}
|
{ FolderLocation.Data, DataDirectoryPath}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public LocalFileStore()
|
||||||
|
{
|
||||||
|
CreateDirectories();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateDirectories()
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(BaseDirectoryPath);
|
||||||
|
Directory.CreateDirectory(JavaDirectoryPath);
|
||||||
|
Directory.CreateDirectory(JavaRuntimeDirectoryPath);
|
||||||
|
Directory.CreateDirectory(GameDirectoryPath);
|
||||||
|
Directory.CreateDirectory(ModsDirectoryPath);
|
||||||
|
Directory.CreateDirectory(ResourcePacksDirectoryPath);
|
||||||
|
Directory.CreateDirectory(ConfigDirectoryPath);
|
||||||
|
Directory.CreateDirectory(DownloadsDirectoryPath);
|
||||||
|
Directory.CreateDirectory(ManifestsDirectoryPath);
|
||||||
|
Directory.CreateDirectory(PluginsDirectoryPath);
|
||||||
|
Directory.CreateDirectory(DataDirectoryPath);
|
||||||
|
}
|
||||||
|
|
||||||
public string Get(FolderLocation location)
|
public string Get(FolderLocation location)
|
||||||
{
|
{
|
||||||
if (!Folders.TryGetValue(location, out string? path))
|
if (!Folders.TryGetValue(location, out string? path))
|
||||||
|
|||||||
Reference in New Issue
Block a user