packages feed

ansi-terminal-game-1.9.4.0: src/Terminal/Game/Layer/Object/Record.hs

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Terminal.Game.Layer.Object.Record where

-- Record Monad, for when I need to play the game and record Events
-- (keypresses, ticks, screen size, FPS) to a file.

import Terminal.Game.Layer.Object.Interface
import Terminal.Game.Layer.Object.Primitive
import Terminal.Game.Layer.Object.IO ()

import qualified Control.Concurrent   as CC
import qualified Control.Monad.Catch  as MC
import qualified Control.Monad.Reader as R
import qualified Control.Monad.Trans  as T -- MonadIO
import qualified Data.ByteString      as BS
import qualified Data.Serialize       as S

-- record the key pressed in a game session

newtype Record a = Record (R.ReaderT (CC.MVar GRec) IO a)
                deriving (Functor, Applicative, Monad,
                          T.MonadIO, R.MonadReader (CC.MVar GRec),
                          MC.MonadThrow, MC.MonadCatch, MC.MonadMask)

-- Lifts IO interface, records where necessary
instance MonadInput Record where
    startEvents tps = T.liftIO (startEvents tps)
    pollEvents ve = T.liftIO (pollEvents ve) >>= \es ->
                    modMRec addPolled es
    stopEvents ts = T.liftIO (stopEvents ts)
    areEventsOver = T.liftIO areEventsOver

instance MonadDisplay Record where
    setupDisplay = T.liftIO setupDisplay
    clearDisplay = T.liftIO clearDisplay
    displaySize = T.liftIO displaySize >>= \ds ->
                  modMRec addDims ds
    blitPlane mp p = T.liftIO (blitPlane mp p)
    shutdownDisplay = T.liftIO shutdownDisplay

-- logs and passes the value on
modMRec :: (a -> GRec -> GRec) -> a -> Record a
modMRec f a = R.ask >>= \mv ->
              let fmv = CC.modifyMVar_ mv (return . f a) in
              T.liftIO fmv >>
              return a

runRecord :: Record a -> CC.MVar GRec -> IO a
runRecord (Record r) me = R.runReaderT r me

writeRec :: FilePath -> CC.MVar GRec -> IO ()
writeRec fp vr = CC.readMVar vr                >>= \k ->
                 BS.writeFile fp (S.encode k)