qstbak/Questionable/Questionable.Navigation/SmartNavReRouteService.cs
2026-08-17 20:29:32 +10:00

83 lines
2.5 KiB
C#

using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Microsoft.Extensions.Logging;
using Questionable.Controller.Steps;
using Questionable.Controller.Steps.Common;
using Questionable.Controller.Steps.Movement;
using Questionable.Controller.Steps.Shared;
using SmartNav;
namespace Questionable.Navigation;
internal sealed class SmartNavReRouteService(ReRoutePolicy reRoutePolicy, SmartNavTaskMapper taskMapper, Configuration configuration, ILogger<SmartNavReRouteService> logger)
{
public void SetDestination(uint territoryId, Vector3 position)
{
reRoutePolicy.SetDestination(territoryId, position);
}
public void ClearDestination()
{
reRoutePolicy.ClearDestination();
}
public bool HandleMovementFailure(TaskQueue taskQueue)
{
if (!configuration.Navigation.ReRouteOnFailure)
{
return false;
}
string failedTargetNodeId = null;
string failedApproachNodeId = null;
if (taskQueue.CurrentTaskExecutor?.CurrentTask is MoveTask moveTask)
{
string routeTargetNodeId = moveTask.RouteTargetNodeId;
if (routeTargetNodeId != null)
{
failedTargetNodeId = routeTargetNodeId;
failedApproachNodeId = moveTask.RouteApproachNodeId;
}
}
List<ITask> list = ExtractNonMovementTasks(taskQueue);
ReRouteDecision reRouteDecision = reRoutePolicy.HandleMovementFailure(failedTargetNodeId, failedApproachNodeId, list.Count > 0);
if (!(reRouteDecision is ReRouteDecision.SkipMovement))
{
if (reRouteDecision is ReRouteDecision.Replan replan)
{
taskQueue.Reset();
foreach (ITask item in taskMapper.MapInstructions(replan.Instructions))
{
taskQueue.Enqueue(item);
}
foreach (ITask item2 in list)
{
taskQueue.Enqueue(item2);
}
return true;
}
return false;
}
taskQueue.Reset();
foreach (ITask item3 in list)
{
taskQueue.Enqueue(item3);
}
logger.LogInformation("Re-route: skipping movement with {TaskCount} preserved tasks", list.Count);
return true;
}
private static List<ITask> ExtractNonMovementTasks(TaskQueue taskQueue)
{
return taskQueue.RemainingTasks.Where((ITask t) => !IsMovementTask(t)).ToList();
}
private static bool IsMovementTask(ITask task)
{
if (task is MoveTask || task is LandTask || task is Mount.MountTask || task is AetheryteTeleport.Task || task is AethernetRide.Task || task is WaitNavmesh.Task || task is WaitCondition.Task || task is WarpInteract.Task || task is TaxiInteract.Task || task is SubRegionTransport.Task || task is TicketTeleport.Task)
{
return true;
}
return false;
}
}