packages feed

aztecs-0.13.0: src/Aztecs/ECS/Entities.hs

module Aztecs.ECS.Entities where

import Data.Bits
import Data.IntMap (IntMap)
import qualified Data.IntMap as IntMap
import Data.Word

newtype Entity = Entity {unEntity :: Word64}
  deriving (Eq, Ord)

instance Show Entity where
  show e = "Entity {index = " ++ show (entityIndex e) ++ ", generation = " ++ show (entityGeneration e) ++ "}"

mkEntity :: Word32 -> Word32 -> Entity
mkEntity index generation = Entity $ (fromIntegral generation `shiftL` 32) .|. fromIntegral index

entityIndex :: Entity -> Word32
entityIndex (Entity e) = fromIntegral (e .&. 0xFFFFFFFF)

entityGeneration :: Entity -> Word32
entityGeneration (Entity e) = fromIntegral ((e `shiftR` 32) .&. 0xFFFFFFFF)

data Entities = Entities
  { entitiesNextGeneration :: Word32,
    entitiesGenerations :: IntMap Word32,
    entitiesNextIndex :: Word32,
    entitiesFreeIndicies :: [Word32]
  }

emptyEntities :: Entities
emptyEntities = Entities 0 IntMap.empty 0 []

mkEntityWithCounter :: Entities -> (Entity, Entities)
mkEntityWithCounter (Entities gen gens index free) =
  let (i, nextIndex, free') = case free of
        (i' : rest) -> (i', index, rest)
        [] -> (index, index + 1, [])
      nextGeneration = gen + 1
      gens' = IntMap.insert (fromIntegral i) gen gens
   in (mkEntity i gen, Entities nextGeneration gens' nextIndex free')

entities :: Entities -> [Entity]
entities (Entities _ gens _ _) = map go (IntMap.toList gens)
  where
    go (i, gen) = mkEntity (fromIntegral i) gen