Files
riversong-code-showcase/Source/Riversong/Game/World/Agents/Intents/PathfindingIntentExecutionLogic.cs
2026-05-21 16:04:49 +02:00

83 lines
3.1 KiB
C#

using System;
using Cysharp.Threading.Tasks;
using Unity.Mathematics;
namespace DanieleMarotta.RiversongCodeShowcase
{
public class PathfindingIntentExecutionLogic : IntentExecutionLogic
{
private IPathfinder _pathfinder;
private ITileSpace _tileSpace;
private IFailedPathCache _failedPathCache;
private ISignalBus _signalBus;
public override UniTask InitializeAsync(IServiceLocator serviceLocator)
{
_pathfinder = serviceLocator.GetService<IPathfinder>();
_tileSpace = serviceLocator.GetService<ITileSpace>();
_failedPathCache = serviceLocator.GetService<IFailedPathCache>();
_signalBus = serviceLocator.GetService<ISignalBus>();
return UniTask.CompletedTask;
}
public override IntentExecutionResult OnStartingIntent(Agent agent, in AgentIntent intent)
{
ref var path = ref agent.GetPathRW();
path.Steps.Clear();
var searchType = intent.Type switch
{
AgentIntentType.FindPath => PathSearchType.FindPath,
AgentIntentType.SearchResourceNode => PathSearchType.SearchResourceNode,
AgentIntentType.SearchFertileTile => PathSearchType.SearchFertileTile,
AgentIntentType.SearchCritter => PathSearchType.SearchCritterHerd,
_ => throw new ArgumentOutOfRangeException()
};
var query = new PathQuery
{
SearchType = searchType,
SourceTile = _tileSpace.WorldToTile(agent.Position),
DestinationRect = intent.Rect,
TargetId = intent.TargetId,
TraversalRules = intent.PathTraversalRules,
MaxDistance = intent.PathMaxDistance
};
agent.PathQueryHandle = _pathfinder.FindPath(path, ref query);
return IntentExecutionResult.Success;
}
public override IntentExecutionResult Execute(Agent agent, in AgentIntent intent)
{
switch (_pathfinder.CompletePath(agent.PathQueryHandle))
{
case PathQueryResult.InProgress:
return IntentExecutionResult.InProgress;
case PathQueryResult.InvalidQuery:
return IntentExecutionResult.Failure;
case PathQueryResult.Failure:
if ((intent.PathTraversalRules & PathTraversalRules.UpdateFailedPathCache) != 0) _failedPathCache.FailPath(agent.HomeId, intent.TargetId);
_signalBus.Raise(new PathQueryFailedSignal(intent.PathTraversalRules));
return IntentExecutionResult.Failure;
}
ref var path = ref agent.GetPathRW();
var agentTile = _tileSpace.WorldToTile(agent.Position);
if (path.Steps.Length > 0 && math.any(agentTile != path.Steps[0]))
{
agent.Position = _tileSpace.TileToWorld(path.Steps[0]);
agent.Velocity = float3.zero;
}
return IntentExecutionResult.Success;
}
}
}