Files
better-genshin-impact/BetterGenshinImpact/Service/GearTask/Execution/PathingRuntimeNotifier.cs
辉鸭蛋 7f7a34e9ba feat(gear-task): 引入事件驱动的任务执行与历史记录系统
- 新增 IGearTaskEventBus 接口及默认实现,用于解耦执行器与记录器、UI 投影等消费者
- 新增 IGearTaskResumable 接口,支持任务节点内部恢复(如 Pathing 任务可恢复至特定路径点)
- 重构任务执行流程,使用 GearTaskExecutionRunner 替代旧的 GearTaskExecutionManager
- 实现基于磁盘 JSON 的历史记录存储(IGearTaskHistoryStore),支持执行记录的保存、加载与清理
- 为 PathingGearTask 添加恢复能力,通过 PathingGearTaskResumeState 记录断点状态
- 在 PathExecutor 中集成运行时事件通知,支持路径点进入、完成、传送等事件的发布
- 统一执行事件模型(GearTaskExecutionEvent),包含任务定义、节点路径、时间戳等元数据
- 服务注册更新,使用新的执行器、事件总线、历史记录器等组件
2026-05-11 01:57:29 +08:00

119 lines
5.4 KiB
C#

using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace BetterGenshinImpact.Service.GearTask.Execution;
/// <summary>
/// Pathing 运行期通知接口。
/// PathExecutor 从业务步骤出发发出通知,外部可以选择记录、展示或转发。
/// </summary>
public interface IPathingRuntimeNotifier
{
ValueTask NotifyWaypointEnteredAsync(int waypointGroupIndex, int waypointIndex, string? action, double positionX, double positionY, CancellationToken ct = default);
ValueTask NotifyWaypointCompletedAsync(int waypointGroupIndex, int waypointIndex, string? action, double positionX, double positionY, CancellationToken ct = default);
ValueTask NotifyTeleportCompletedAsync(int waypointGroupIndex, int waypointIndex, double positionX, double positionY, CancellationToken ct = default);
ValueTask NotifyActionCompletedAsync(int waypointGroupIndex, int waypointIndex, string action, double positionX, double positionY, CancellationToken ct = default);
ValueTask NotifyResumePointUpdatedAsync(PathingGearTaskResumeState state, string? message = null, CancellationToken ct = default);
}
/// <summary>
/// 空通知器,供不关心 Pathing 运行态的场景使用。
/// </summary>
public sealed class NullPathingRuntimeNotifier : IPathingRuntimeNotifier
{
public static readonly NullPathingRuntimeNotifier Instance = new();
public ValueTask NotifyActionCompletedAsync(int waypointGroupIndex, int waypointIndex, string action, double positionX, double positionY, CancellationToken ct = default) => ValueTask.CompletedTask;
public ValueTask NotifyResumePointUpdatedAsync(PathingGearTaskResumeState state, string? message = null, CancellationToken ct = default) => ValueTask.CompletedTask;
public ValueTask NotifyTeleportCompletedAsync(int waypointGroupIndex, int waypointIndex, double positionX, double positionY, CancellationToken ct = default) => ValueTask.CompletedTask;
public ValueTask NotifyWaypointCompletedAsync(int waypointGroupIndex, int waypointIndex, string? action, double positionX, double positionY, CancellationToken ct = default) => ValueTask.CompletedTask;
public ValueTask NotifyWaypointEnteredAsync(int waypointGroupIndex, int waypointIndex, string? action, double positionX, double positionY, CancellationToken ct = default) => ValueTask.CompletedTask;
}
/// <summary>
/// 把 Pathing 运行步骤转换成 GearTask 执行事件。
/// </summary>
public sealed class GearTaskPathingRuntimeNotifier : IPathingRuntimeNotifier
{
private readonly GearTaskNodeExecutionContext _context;
public GearTaskPathingRuntimeNotifier(GearTaskNodeExecutionContext context)
{
_context = context;
}
public ValueTask NotifyWaypointEnteredAsync(int waypointGroupIndex, int waypointIndex, string? action, double positionX, double positionY, CancellationToken ct = default)
{
var evt = _context.CreateEvent<PathingWaypointEnteredEvent>();
evt.WaypointGroupIndex = waypointGroupIndex;
evt.WaypointIndex = waypointIndex;
evt.Action = action;
evt.PositionX = positionX;
evt.PositionY = positionY;
evt.Extra["positionX"] = positionX;
evt.Extra["positionY"] = positionY;
return _context.PublishAsync(evt, ct);
}
public ValueTask NotifyWaypointCompletedAsync(int waypointGroupIndex, int waypointIndex, string? action, double positionX, double positionY, CancellationToken ct = default)
{
var evt = _context.CreateEvent<PathingWaypointCompletedEvent>();
evt.WaypointGroupIndex = waypointGroupIndex;
evt.WaypointIndex = waypointIndex;
evt.Action = action;
evt.PositionX = positionX;
evt.PositionY = positionY;
evt.Extra["positionX"] = positionX;
evt.Extra["positionY"] = positionY;
return _context.PublishAsync(evt, ct);
}
public ValueTask NotifyTeleportCompletedAsync(int waypointGroupIndex, int waypointIndex, double positionX, double positionY, CancellationToken ct = default)
{
var evt = _context.CreateEvent<PathingTeleportCompletedEvent>();
evt.WaypointGroupIndex = waypointGroupIndex;
evt.WaypointIndex = waypointIndex;
evt.PositionX = positionX;
evt.PositionY = positionY;
evt.Extra["positionX"] = positionX;
evt.Extra["positionY"] = positionY;
return _context.PublishAsync(evt, ct);
}
public ValueTask NotifyActionCompletedAsync(int waypointGroupIndex, int waypointIndex, string action, double positionX, double positionY, CancellationToken ct = default)
{
var evt = _context.CreateEvent<PathingActionCompletedEvent>();
evt.WaypointGroupIndex = waypointGroupIndex;
evt.WaypointIndex = waypointIndex;
evt.Action = action;
evt.PositionX = positionX;
evt.PositionY = positionY;
evt.Extra["positionX"] = positionX;
evt.Extra["positionY"] = positionY;
return _context.PublishAsync(evt, ct);
}
public ValueTask NotifyResumePointUpdatedAsync(PathingGearTaskResumeState state, string? message = null, CancellationToken ct = default)
{
if (string.IsNullOrWhiteSpace(state.PathFile))
{
state.PathFile = _context.TaskPath;
}
var evt = _context.CreateEvent<ResumePointUpdatedEvent>();
evt.CanResumeInsideTask = true;
evt.ResumeTokenJson = JsonConvert.SerializeObject(state);
evt.Message = message;
return _context.PublishAsync(evt, ct);
}
}