gore-and-ash-actor-1.1.0.0: src/Game/GoreAndAsh/Actor/State.hs
{-# OPTIONS_GHC -fno-warn-orphans #-}
{-|
Module : Game.GoreAndAsh.Actor.State
Description : State of actor core module
Copyright : (c) Anton Gushcha, 2015-2016
License : BSD3
Maintainer : ncrashed@gmail.com
Stability : experimental
Portability : POSIX
Internal state of actor core module.
-}
module Game.GoreAndAsh.Actor.State(
ActorState(..)
, emptyActorState
, moveSendedMessages
) where
import Control.DeepSeq
import Data.Dynamic
import GHC.Generics (Generic)
import qualified Data.HashMap.Strict as H
import qualified Data.Sequence as S
import Game.GoreAndAsh.Actor.TypeRep
-- | Inner state of actor module.
--
-- [@s@] - State of next module, the states are chained via nesting.
data ActorState s = ActorState {
-- | Stores messages for actor with specified id
--
-- Message has type of Dynamic as message manager doesn't know anything about message types.
-- We don't need to serialization protocol due passing via memory. Type safety is forced
-- with Messagable type class with type family (see Actor.Message module). Id space is separate for each actor type
--
-- There are two sequences of messages, one for recieved messages from previous frame, and
-- the second one for messages recieved at current frame. At the end of each frame first
-- sequence is purged and filled with contents of first and the second one is replaced with
-- empty sequence.
actorBoxes :: !(H.HashMap (HashableTypeRep, Int) (S.Seq Dynamic, S.Seq Dynamic))
-- | Next empty id of actor, id space is separate for each actor type
, actorNextId :: !(H.HashMap HashableTypeRep Int)
-- | Search table for actor names
, actorNameMap :: !(H.HashMap String HashableTypeRep)
-- | Next state in state chain of modules
, actorNextState :: !s
} deriving (Generic)
instance NFData Dynamic where
rnf = (`seq` ())
instance NFData s => NFData (ActorState s)
-- | Create empty actor state
emptyActorState :: s -> ActorState s
emptyActorState s = ActorState {
actorBoxes = H.empty
, actorNextId = H.empty
, actorNameMap = H.empty
, actorNextState = s
}
-- | Perform rotation between sended messages and recieved ones
moveSendedMessages :: ActorState s -> ActorState s
moveSendedMessages s = s {
actorBoxes = fmap (\(_, b) -> (b, S.empty)) . actorBoxes $! s
}