module Game.GoreAndAsh.Sync.API(
SyncMonad(..)
) where
import Control.Monad.State.Strict
import Control.Wire
import Data.Proxy
import Data.Serialize (encode, Serialize)
import Data.Text
import Data.Word
import Prelude hiding (id, (.))
import qualified Data.HashMap.Strict as H
import qualified Data.Sequence as S
import Game.GoreAndAsh.Actor
import Game.GoreAndAsh.Actor.TypeRep
import Game.GoreAndAsh.Logging
import Game.GoreAndAsh.Network
import Game.GoreAndAsh.Sync.Module
import Game.GoreAndAsh.Sync.State
class MonadIO m => SyncMonad m where
getSyncIdM :: HashableTypeRep -> m (Maybe Word64)
getSyncTypeRepM :: Word64 -> m (Maybe HashableTypeRep)
registerSyncIdM :: LoggingMonad m => HashableTypeRep -> m Word64
addSyncTypeRepM :: LoggingMonad m => HashableTypeRep -> Word64 -> m ()
syncScheduleMessageM :: (NetworkMonad m, LoggingMonad m, NetworkMessage i, Serialize (NetworkMessageType i))
=> Peer
-> ChannelID
-> i
-> MessageType
-> NetworkMessageType i
-> m ()
syncSetLoggingM :: Bool -> m ()
syncSetRoleM :: SyncRole -> m ()
syncGetRoleM :: m SyncRole
syncRequestIdM :: forall proxy i . (ActorMonad m, NetworkMonad m, LoggingMonad m, NetworkMessage i)
=> Peer -> proxy i -> m ()
instance MonadIO m => SyncMonad (SyncT s m) where
getSyncIdM !tr = do
sstate <- SyncT get
return . H.lookup tr . syncIdMap $! sstate
getSyncTypeRepM !w = do
sstate <- SyncT get
return . H.lookup w . syncIdMapRev $! sstate
registerSyncIdM !tr = do
sstate <- SyncT get
let (w64, s') = registerSyncIdInternal tr sstate
syncLog s' $ "Registering new actor type " <> pack (show tr) <> " with id " <> pack (show w64)
SyncT . put $! s'
return w64
addSyncTypeRepM !tr !i = do
sstate <- SyncT get
syncLog sstate $ "Registering new actor type " <> pack (show tr) <> " with id " <> pack (show i)
SyncT . put $! addSyncTypeRepInternal tr i sstate
syncScheduleMessageM peer ch i mt msg = do
sstate <- SyncT get
let name = getActorName i
serviceMsg = Message ReliableMessage $! encode (0 :: Word64, encode $! SyncServiceRequestId name )
actorId = fromIntegral (toCounter i) :: Word64
v = (name, ch, \netid -> Message mt $! encode (netid, encode (actorId, encode msg)))
serviceChan <- getServiceChannel
peerSendM peer serviceChan serviceMsg
SyncT . put $! sstate {
syncScheduledMessages = case H.lookup peer . syncScheduledMessages $! sstate of
Nothing -> H.insert peer (S.singleton v) . syncScheduledMessages $! sstate
Just msgs -> H.insert peer (msgs S.|> v) . syncScheduledMessages $! sstate
}
syncSetLoggingM f = do
sstate <- SyncT get
SyncT . put $! sstate {
syncLogging = f
}
syncSetRoleM r = do
sstate <- SyncT get
SyncT . put $! sstate {
syncRole = r
}
syncGetRoleM = syncRole <$> SyncT get
syncRequestIdM peer p = do
s <- SyncT get
syncLog s $ "request id of actor " <> pack (show $ actorFingerprint p)
s' <- syncRequestIdInternal peer p s
SyncT . put $! s'
instance (MonadIO (mt m), SyncMonad m, ActorMonad m, NetworkMonad m, LoggingMonad m, MonadTrans mt) => SyncMonad (mt m) where
getSyncIdM = lift . getSyncIdM
getSyncTypeRepM = lift . getSyncTypeRepM
registerSyncIdM = lift . registerSyncIdM
addSyncTypeRepM a b = lift $ addSyncTypeRepM a b
syncScheduleMessageM peer ch i mt msg = lift $ syncScheduleMessageM peer ch i mt msg
syncSetLoggingM = lift . syncSetLoggingM
syncSetRoleM = lift . syncSetRoleM
syncGetRoleM = lift syncGetRoleM
syncRequestIdM a b = lift $ syncRequestIdM a b
getActorName :: forall i . ActorMessage i => i -> String
getActorName _ = show $ actorFingerprint (Proxy :: Proxy i)