From f2f858de15c8ef1a392e783b4b0713c2328696b8 Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Thu, 4 Jan 2024 22:51:58 +0800 Subject: [PATCH] create infrastructure --- .../Snap.Hutao/Resource/Localization/SH.resx | 3 + .../ILaunchExecutionDelegateHandler.cs | 11 +++ .../Game/Launching/LaunchExecutionContext.cs | 17 ++++ ...chExecutionEnsureSchemeNotExistsHandler.cs | 19 +++++ .../Game/Launching/LaunchExecutionInvoker.cs | 37 +++++++++ .../LaunchExecutionPackageConvertHandler.cs | 11 +++ .../Game/Launching/LaunchExecutionResult.cs | 21 +++++ ...LaunchExecutionSetChannelOptionsHandler.cs | 80 +++++++++++++++++++ 8 files changed, 199 insertions(+) create mode 100644 src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/ILaunchExecutionDelegateHandler.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionContext.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionEnsureSchemeNotExistsHandler.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionInvoker.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionPackageConvertHandler.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionResult.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionSetChannelOptionsHandler.cs diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx index bb761610..3e49c037 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx @@ -875,6 +875,9 @@ 游戏文件操作失败:{0} + + 请选择游戏路径 + 游戏进程已退出 diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/ILaunchExecutionDelegateHandler.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/ILaunchExecutionDelegateHandler.cs new file mode 100644 index 00000000..78ff79ad --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/ILaunchExecutionDelegateHandler.cs @@ -0,0 +1,11 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Service.Game.Launching; + +internal delegate ValueTask LaunchExecutionDelegate(); + +internal interface ILaunchExecutionDelegateHandler +{ + ValueTask OnExecutionAsync(LaunchExecutionContext context, LaunchExecutionDelegate next); +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionContext.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionContext.cs new file mode 100644 index 00000000..0e2e2b86 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionContext.cs @@ -0,0 +1,17 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Snap.Hutao.Service.Game.Scheme; + +namespace Snap.Hutao.Service.Game.Launching; + +internal sealed class LaunchExecutionContext +{ + public LaunchExecutionResult Result { get; } = new(); + + public ILogger Logger { get; set; } = default!; + + public LaunchScheme Scheme { get; set; } = default!; + + public LaunchOptions Options { get; set; } = default!; +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionEnsureSchemeNotExistsHandler.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionEnsureSchemeNotExistsHandler.cs new file mode 100644 index 00000000..1cc14fe6 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionEnsureSchemeNotExistsHandler.cs @@ -0,0 +1,19 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Service.Game.Launching; + +internal sealed class LaunchExecutionEnsureSchemeNotExistsHandler : ILaunchExecutionDelegateHandler +{ + public async ValueTask OnExecutionAsync(LaunchExecutionContext context, LaunchExecutionDelegate next) + { + if (context.Scheme is null) + { + context.Result.Kind = LaunchExecutionResultKind.NoActiveScheme; + context.Result.ErrorMessage = SH.ViewModelLaunchGameSchemeNotSelected; + return; + } + + await next().ConfigureAwait(false); + } +} diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionInvoker.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionInvoker.cs new file mode 100644 index 00000000..1e2f8829 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionInvoker.cs @@ -0,0 +1,37 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Service.Game.Launching; + +[Injection(InjectAs.Transient)] +internal sealed class LaunchExecutionInvoker +{ + private readonly Queue handlers; + + public LaunchExecutionInvoker() + { + handlers = []; + handlers.Enqueue(new LaunchExecutionEnsureSchemeNotExistsHandler()); + handlers.Enqueue(new LaunchExecutionSetChannelOptionsHandler()); + } + + public async ValueTask LaunchAsync(LaunchExecutionContext context) + { + await ExecuteAsync(context).ConfigureAwait(false); + return context.Result; + } + + private async ValueTask ExecuteAsync(LaunchExecutionContext context) + { + if (handlers.TryDequeue(out ILaunchExecutionDelegateHandler? handler)) + { + string handlerName = handler.GetType().Name; + + context.Logger.LogInformation("Handler[{Handler}] begin execute", handlerName); + await handler.OnExecutionAsync(context, () => ExecuteAsync(context)).ConfigureAwait(false); + context.Logger.LogInformation("Handler[{Handler}] end execute", handlerName); + } + + return context; + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionPackageConvertHandler.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionPackageConvertHandler.cs new file mode 100644 index 00000000..2d7fc6c8 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionPackageConvertHandler.cs @@ -0,0 +1,11 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Service.Game.Launching; + +internal sealed class LaunchExecutionPackageConvertHandler : ILaunchExecutionDelegateHandler +{ + public async ValueTask OnExecutionAsync(LaunchExecutionContext context, LaunchExecutionDelegate next) + { + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionResult.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionResult.cs new file mode 100644 index 00000000..4461cf8d --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionResult.cs @@ -0,0 +1,21 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Service.Game.Launching; + +internal sealed class LaunchExecutionResult +{ + public LaunchExecutionResultKind Kind { get; set; } + + public string ErrorMessage { get; set; } = default!; +} + +internal enum LaunchExecutionResultKind +{ + Ok, + NoActiveScheme, + NoActiveGamePath, + GameConfigFileNotFound, + GameConfigDirectoryNotFound, + GameConfigUnauthorizedAccess, +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionSetChannelOptionsHandler.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionSetChannelOptionsHandler.cs new file mode 100644 index 00000000..60bd081b --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionSetChannelOptionsHandler.cs @@ -0,0 +1,80 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Snap.Hutao.Core.IO.Ini; +using Snap.Hutao.Service.Game.Configuration; +using System.IO; + +namespace Snap.Hutao.Service.Game.Launching; + +internal sealed class LaunchExecutionSetChannelOptionsHandler : ILaunchExecutionDelegateHandler +{ + private const string ConfigFileName = "config.ini"; + + public async ValueTask OnExecutionAsync(LaunchExecutionContext context, LaunchExecutionDelegate next) + { + if (!context.Options.TryGetGamePathAndFilePathByName(ConfigFileName, out string gamePath, out string? configPath)) + { + context.Result.Kind = LaunchExecutionResultKind.NoActiveGamePath; + context.Result.ErrorMessage = SH.ServiceGameLaunchExecutionSetChannelOptionsGamePathNotValid; + return; + } + + List elements = default!; + try + { + using (FileStream readStream = File.OpenRead(configPath)) + { + elements = [.. IniSerializer.Deserialize(readStream)]; + } + } + catch (FileNotFoundException) + { + context.Result.Kind = LaunchExecutionResultKind.GameConfigFileNotFound; + context.Result.ErrorMessage = SH.FormatServiceGameSetMultiChannelConfigFileNotFound(configPath); + return; + } + catch (DirectoryNotFoundException) + { + context.Result.Kind = LaunchExecutionResultKind.GameConfigDirectoryNotFound; + context.Result.ErrorMessage = SH.FormatServiceGameSetMultiChannelConfigFileNotFound(configPath); + return; + } + catch (UnauthorizedAccessException) + { + context.Result.Kind = LaunchExecutionResultKind.GameConfigUnauthorizedAccess; + context.Result.ErrorMessage = SH.ServiceGameSetMultiChannelUnauthorizedAccess; + return; + } + + bool changed = false; + + foreach (IniElement element in elements) + { + if (element is IniParameter parameter) + { + if (parameter.Key is ChannelOptions.ChannelName) + { + changed = parameter.Set(context.Scheme.Channel.ToString("D")) || changed; + continue; + } + + if (parameter.Key is ChannelOptions.SubChannelName) + { + changed = parameter.Set(context.Scheme.SubChannel.ToString("D")) || changed; + continue; + } + } + } + + if (changed) + { + using (FileStream writeStream = File.Create(configPath)) + { + IniSerializer.Serialize(writeStream, elements); + } + } + + await next().ConfigureAwait(false); + } +} \ No newline at end of file