public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            NativeArray <Entity> chunkEntity = chunk.GetNativeArray(entityType);
            NativeArray <FormationPathFindingState> chunkPathfindingState  = chunk.GetNativeArray(archetypePathfindingState);
            NativeArray <FormationTargetPosition>   chunkTargetPosition    = chunk.GetNativeArray(archetypeTargetPosition);
            NativeArray <FormationPosition>         chunkFormationPosition = chunk.GetNativeArray(archetypeFormationPosition);

            for (int i = 0; i < chunk.Count; i++)
            {
                if (chunkPathfindingState[i].Value == PathfindingState.hasNewTarget)
                {
                    entityQueue.Enqueue(chunkEntity[i]);
                    startPositionQueue.Enqueue(new float2(chunkFormationPosition[i].x, chunkFormationPosition[i].y));
                    endPositionQueue.Enqueue(new float2(chunkTargetPosition[i].x, chunkTargetPosition[i].y));

                    chunkPathfindingState[i] = new FormationPathFindingState {
                        Value = PathfindingState.findingPath
                    };
                }
            }
        }
        public void Execute(int jobIndex)
        {
            Entity entity = entities[jobIndex];
            float2 startGridPositionAsFloat = startWorldPositions[jobIndex] / graphCellSize;
            float2 endGridPositionAsFloat   = endWorldPositions[jobIndex] / graphCellSize;
            int2   startGridPosition        = ( int2 )math.round(startGridPositionAsFloat);
            int2   endGridPosition          = ( int2 )math.round(endGridPositionAsFloat);
            int2   startClusterPosition     = startGridPosition / graphClusterSize;
            int2   endClusterPosition       = endGridPosition / graphClusterSize;

            pathfindingStateComponentData[entity] = new FormationPathFindingState {
                Value = PathfindingState.free
            };

            // If the start and end positions are in different clusters
            if (!startClusterPosition.Equals(endClusterPosition))
            {
                int  clusterIndex    = startClusterPosition.x + startClusterPosition.y * graphNumClusters;
                int2 clusterEdgesKey = graphClusterEdgesLists[clusterIndex];

                // If there are no paths from start position to any of the edges in current cluster, break out
                if (clusterEdgesKey.y - clusterEdgesKey.x > 0)
                {
                    NativeList <AbstractNode> abstractPath = FindAbstractPathInGraph(clusterEdgesKey, startGridPosition, endGridPosition);
                    if (abstractPath.Length > 0)
                    {
                        pathPositionBufferEntity[entity].Clear();
                        pathPositionBufferEntity[entity].Add(new PathPosition {
                            Value = endWorldPositions[jobIndex]
                        });
                        NativeList <int2> concretePath = FindConcretePathFromAbstract(abstractPath);
                        for (int i = 1; i < concretePath.Length; i++)
                        {
                            float2 pathPosition = concretePath[i] * graphCellSize;
                            pathPositionBufferEntity[entity].Add(new PathPosition {
                                Value = pathPosition
                            });
                        }
                        pathIndexComponentData[entity] = new PathIndex {
                            Value = pathPositionBufferEntity[entity].Length - 1
                        };
                        concretePath.Dispose();
                        abstractPath.Dispose();
                        return;
                    }
                    abstractPath.Dispose();
                }
            }
            else // OTHERWISE, the start and end positions are in the same cluster, so just do a quick low-level a* search
            {
                FixedList4096 <int2> path = FindLowLevelPathInCluster(startGridPosition, endGridPosition, startClusterPosition);
                if (path.Length > 0)
                {
                    pathPositionBufferEntity[entity].Clear();
                    pathPositionBufferEntity[entity].Add(new PathPosition {
                        Value = endWorldPositions[jobIndex]
                    });
                    for (int i = 1; i < path.Length; i++)
                    {
                        float2 pathPosition = path[i] * graphCellSize;
                        pathPositionBufferEntity[entity].Add(new PathPosition {
                            Value = pathPosition
                        });
                    }
                    pathIndexComponentData[entity] = new PathIndex {
                        Value = pathPositionBufferEntity[entity].Length - 1
                    };
                    return;
                }
            }

            // If no path was found we will reach here
            return;
        }