mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-05-21 09:45:48 +08:00
- 新增 IGearTaskEventBus 接口及默认实现,用于解耦执行器与记录器、UI 投影等消费者 - 新增 IGearTaskResumable 接口,支持任务节点内部恢复(如 Pathing 任务可恢复至特定路径点) - 重构任务执行流程,使用 GearTaskExecutionRunner 替代旧的 GearTaskExecutionManager - 实现基于磁盘 JSON 的历史记录存储(IGearTaskHistoryStore),支持执行记录的保存、加载与清理 - 为 PathingGearTask 添加恢复能力,通过 PathingGearTaskResumeState 记录断点状态 - 在 PathExecutor 中集成运行时事件通知,支持路径点进入、完成、传送等事件的发布 - 统一执行事件模型(GearTaskExecutionEvent),包含任务定义、节点路径、时间戳等元数据 - 服务注册更新,使用新的执行器、事件总线、历史记录器等组件
88 lines
2.8 KiB
C#
88 lines
2.8 KiB
C#
using System;
|
|
using System.IO;
|
|
using BetterGenshinImpact.Core.Config;
|
|
using BetterGenshinImpact.ViewModel.Pages;
|
|
|
|
namespace BetterGenshinImpact.Service.GearTask.Execution;
|
|
|
|
/// <summary>
|
|
/// 执行记录中的任务路径格式化器。
|
|
/// 将运行期绝对路径转换为和任务定义列表一致的占位符路径。
|
|
/// </summary>
|
|
public static class GearTaskExecutionPathFormatter
|
|
{
|
|
public const string PathingRepoFolderPlaceholder = "{pathingRepoFolder}";
|
|
public const string JsUserFolderPlaceholder = "{jsUserFolder}";
|
|
|
|
public static string FormatTaskPath(string? taskPath)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(taskPath))
|
|
{
|
|
return string.Empty;
|
|
}
|
|
|
|
var normalizedInput = taskPath.Trim();
|
|
if (!Path.IsPathRooted(normalizedInput))
|
|
{
|
|
return normalizedInput;
|
|
}
|
|
|
|
if (TryFormatUnderRoot(normalizedInput, MapPathingViewModel.PathJsonPath, PathingRepoFolderPlaceholder, out var pathingPath))
|
|
{
|
|
return pathingPath;
|
|
}
|
|
|
|
if (TryFormatUnderRoot(normalizedInput, Global.ScriptPath(), JsUserFolderPlaceholder, out var jsPath))
|
|
{
|
|
return jsPath;
|
|
}
|
|
|
|
return normalizedInput;
|
|
}
|
|
|
|
private static bool TryFormatUnderRoot(string sourcePath, string rootPath, string placeholder, out string formattedPath)
|
|
{
|
|
formattedPath = string.Empty;
|
|
|
|
var normalizedSource = Path.GetFullPath(sourcePath);
|
|
var normalizedRoot = Path.GetFullPath(rootPath);
|
|
var sourceWithSeparator = EnsureTrailingSeparator(normalizedSource);
|
|
var rootWithSeparator = EnsureTrailingSeparator(normalizedRoot);
|
|
|
|
if (string.Equals(normalizedSource, normalizedRoot, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
formattedPath = sourcePath.EndsWith(Path.DirectorySeparatorChar) || sourcePath.EndsWith(Path.AltDirectorySeparatorChar)
|
|
? placeholder + Path.DirectorySeparatorChar
|
|
: placeholder;
|
|
return true;
|
|
}
|
|
|
|
if (!sourceWithSeparator.StartsWith(rootWithSeparator, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var relativePath = Path.GetRelativePath(normalizedRoot, normalizedSource);
|
|
formattedPath = string.IsNullOrEmpty(relativePath)
|
|
? placeholder
|
|
: $@"{placeholder}\{relativePath}";
|
|
|
|
if (sourcePath.EndsWith(Path.DirectorySeparatorChar) || sourcePath.EndsWith(Path.AltDirectorySeparatorChar))
|
|
{
|
|
formattedPath += Path.DirectorySeparatorChar;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private static string EnsureTrailingSeparator(string path)
|
|
{
|
|
if (path.EndsWith(Path.DirectorySeparatorChar) || path.EndsWith(Path.AltDirectorySeparatorChar))
|
|
{
|
|
return path;
|
|
}
|
|
|
|
return path + Path.DirectorySeparatorChar;
|
|
}
|
|
}
|