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(); _tileSpace = serviceLocator.GetService(); _failedPathCache = serviceLocator.GetService(); _signalBus = serviceLocator.GetService(); 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; } } }