packages feed

mischief-ecs-0.2.0.0: src/Mischief/ECS/Relationships/Order.hs

module Mischief.ECS.Relationships.Order where

import Data.Foldable
import Data.Maybe
import Data.Set (Set)
import Data.Set qualified as Set
import Mischief.ECS.Components
import Mischief.ECS.Entities
import Mischief.ECS.Utils
import Mischief.ECS.World
import Mischief.ECS.World.Insert
import Mischief.ECS.World.Query
import Mischief.ECS.World.Query.Markers
import Mischief.ECS.World.Query.QueryFilter
import Mischief.ECS.World.Remove

data Before = Before deriving (Component)

data Visited = Visited deriving (Component)

orderEntities :: [Entity] -> System [Entity]
orderEntities !entities = do
  !res <- orderEntitiesStep (Set.fromList entities)
  for_ entities $ remove (C @Visited)
  -- err $ text res
  pure res

orderEntitiesStep :: Set Entity -> System [Entity]
orderEntitiesStep !entities =
  if null entities
    then
      return []
    else do
      !next <- expect "Attempted to Order Cyclic Graph!" <$> findM isAvailable entities
      insert Visited next
      (next :) <$> orderEntitiesStep (Set.delete next entities)

isAvailable :: Entity -> System Bool
isAvailable !entity = do
  !before <- query $ mkQuery' E (With (R @Before entity))
  isNothing <$> findM (\(!x) -> (not . unwrap <$>) $ single $ mkGet x (Has @Visited)) before