mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
create infrastructure
This commit is contained in:
@@ -875,6 +875,9 @@
|
||||
<data name="ServiceGameFileOperationExceptionMessage" xml:space="preserve">
|
||||
<value>游戏文件操作失败:{0}</value>
|
||||
</data>
|
||||
<data name="ServiceGameLaunchExecutionSetChannelOptionsGamePathNotValid" xml:space="preserve">
|
||||
<value>请选择游戏路径</value>
|
||||
</data>
|
||||
<data name="ServiceGameLaunchPhaseProcessExited" xml:space="preserve">
|
||||
<value>游戏进程已退出</value>
|
||||
</data>
|
||||
|
||||
@@ -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<LaunchExecutionContext> LaunchExecutionDelegate();
|
||||
|
||||
internal interface ILaunchExecutionDelegateHandler
|
||||
{
|
||||
ValueTask OnExecutionAsync(LaunchExecutionContext context, LaunchExecutionDelegate next);
|
||||
}
|
||||
@@ -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!;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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<ILaunchExecutionDelegateHandler> handlers;
|
||||
|
||||
public LaunchExecutionInvoker()
|
||||
{
|
||||
handlers = [];
|
||||
handlers.Enqueue(new LaunchExecutionEnsureSchemeNotExistsHandler());
|
||||
handlers.Enqueue(new LaunchExecutionSetChannelOptionsHandler());
|
||||
}
|
||||
|
||||
public async ValueTask<LaunchExecutionResult> LaunchAsync(LaunchExecutionContext context)
|
||||
{
|
||||
await ExecuteAsync(context).ConfigureAwait(false);
|
||||
return context.Result;
|
||||
}
|
||||
|
||||
private async ValueTask<LaunchExecutionContext> 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;
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
}
|
||||
@@ -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<IniElement> 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user