module Fresco.Entity (
(#:),
Entity (..),
newE,
readC,
updateC,
setC,
CallbackSystem (..),
createCBS,
stepCBS,
registerReceiverCBS,
)
where
import Data.Maybe
import Data.ByteString
import qualified Data.Map as M
import Data.IORef
import Control.Concurrent
import Control.Applicative
import Foreign
import Foreign.C
import Data.MessagePack
import Data.Serialize
import Fresco.System
import Fresco.Component
type EntityData = M.Map Word64 Component
(#:) :: ComponentClass a => ComponentType a -> a -> (Word64, Component)
(ComponentType c) #: val = (c, toMsg val)
entityData :: [(Word64, Component)] -> EntityData
entityData clist = M.fromList clist
(#?) :: EntityData -> ComponentType a -> Bool
e #? (ComponentType c) = Prelude.elem c $ M.keys e
(#!) :: ComponentClass a => EntityData -> ComponentType a -> a
e #! (ComponentType c) = fromJust $ M.lookup c e >>= fromMsg
(#) :: ComponentClass a => EntityData -> ComponentType a -> Maybe a
e # (ComponentType c) = M.lookup c e >>= fromMsg
updateDataC :: ComponentClass a => EntityData -> ComponentType a -> (a -> a) -> EntityData
updateDataC e c'@(ComponentType c) f = M.insert c ((toMsg . f) (e #! c')) e
setDataC :: ComponentClass a => EntityData -> ComponentType a -> a -> EntityData
setDataC e (ComponentType c) val = M.insert c (toMsg val) e
data CallbackSystem = CallbackSystem (Ptr ())
createCBS :: IO CallbackSystem
createCBS = do
cbs <- callbackSystemCreate
return $ CallbackSystem cbs
stepCBS :: CallbackSystem -> IO ()
stepCBS (CallbackSystem cbs) = callbackSystemStep cbs
registerReceiverCBS :: ComponentClass a => CallbackSystem -> Entity -> ComponentType a -> (a -> IO ()) -> IO ()
registerReceiverCBS (CallbackSystem cbs) (Entity ep) (ComponentType ct) f = do
let f' = \_ _ cdata len -> do
bs <- packCStringLen (cdata, fromIntegral len)
let c = fromJust(fromMsg bs)
f c
return 0
mf <- mkMsgFunPtr f'
callbackSystemRegisterReceiver cbs ep ct mf
return ()
type Listeners = ()
data Entity = Entity (Ptr ()) deriving (Eq)
msgFromE :: EntityData -> Component
msgFromE ed = let
pairs = (M.toList ed)
bs = Prelude.concatMap (\(a, b) -> [encode (ObjectUInt (fromIntegral a)), b]) pairs
in Data.ByteString.concat bs
msgFromC :: ComponentClass a => ComponentType a -> EntityData -> Component
msgFromC (ComponentType u) e = let
d = fromJust $ M.lookup u e
in Data.ByteString.concat [encode (ObjectUInt (fromIntegral u)), d]
newE :: [(Word64, Component)] -> IO Entity
newE inlist = do
let e = entityData inlist
ep <- entityCreate (msgFromE e)
return $ Entity ep
readC :: ComponentClass a => Entity -> ComponentType a -> IO a
readC (Entity ep) (ComponentType ct) = do
edat <- entityGetData ep ct
bs <- entityDataRead edat
entityDataRelease edat
return (fromJust (fromMsg bs))
updateC :: ComponentClass a => Entity -> ComponentType a -> (a -> a) -> IO ()
updateC er@(Entity ep) c f = do
val <- readC er c
let val' = f val
setC er c val'
return ()
setC :: ComponentClass a => Entity -> ComponentType a -> a -> IO ()
setC er@(Entity ep) (ComponentType ct) val = do
let d = Data.ByteString.concat [encode (ObjectUInt (fromIntegral ct)), toMsg val]
entitySet d ep
return ()