packages feed

mischief-ecs-0.2.0.0: src/Mischief/ECS/Resources.hs

module Mischief.ECS.Resources
  ( insertRes,
    res,
    resOrInsert,
    resOrInsertM,
    modifyRes,
    modifyRes',
  )
where

import Data.Maybe
import Mischief.ECS.Components
import Mischief.ECS.Components.Bundle
import Mischief.ECS.Components.Spawn
import Mischief.ECS.World
import Mischief.ECS.World.Insert
import Mischief.ECS.World.Query
import Mischief.ECS.World.Query.Markers

-- | Insert a resource into the World. If the resource already exists, its value will be overwritten.
insertRes :: forall r. (Component r, Bundle r) => r -> System ()
insertRes res = do
  entity <- meta @r
  insert res entity

-- | Get the value of a resource from the World.
res :: forall c m w. (MonadSystem w m) => (Component c) => m (Maybe c)
res = do
  meta <- tryMeta @c
  case meta of
    Nothing -> pure Nothing
    Just meta -> do
      single $ mkGet meta (C @c)

-- | Get the value of a resource, or insert a resource if it doesn't exist.
resOrInsert :: forall r. (Component r, Bundle r) => r -> System r
resOrInsert r = do
  meta <- meta @r
  x <- single $ mkGet meta (C @r)
  case x of
    Nothing -> do
      insertRes r
      pure $! r
    Just x -> pure $! x

-- | Same as 'resOrInsert' but allows the default resource to be produced by a System.
resOrInsertM :: forall r. (Component r, Bundle r) => System r -> System r
resOrInsertM r = do
  meta <- meta @r
  x <- single $ mkGet meta (C @r)
  case x of
    Nothing -> do
      r <- r
      insertRes r
      pure r
    Just x -> pure x

-- | Modify the value of a resource if it exists, otherwise insert the result of the function.
modifyRes :: forall r. (Component r, Bundle r) => (Maybe r -> r) -> System ()
modifyRes f = do
  x <- res @r
  insertRes $ f x

-- | Modify the value of a resource if it exists, otherwise do nothing.
modifyRes' :: forall r. (Component r, Bundle r) => (r -> r) -> System ()
modifyRes' f = do
  x <- res @r
  case x of
    Nothing -> pure ()
    Just x -> insertRes $ f x