{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-- | The implementation of our custom game client monads. Just as any other
-- component of the library, this implementation can be substituted.
module Implementation.MonadClientImplementation
  ( executorCli
#ifdef EXPOSE_INTERNAL
    -- * Internal operations
  , CliState(..), CliImplementation(..)
#endif
  ) where

import Prelude ()

import Game.LambdaHack.Core.Prelude

import           Control.Concurrent
import qualified Control.Monad.IO.Class as IO
import           Control.Monad.Trans.State.Strict hiding (State)

import           Game.LambdaHack.Atomic (MonadStateWrite (..))
import           Game.LambdaHack.Client
import qualified Game.LambdaHack.Client.BfsM as BfsM
import           Game.LambdaHack.Client.HandleAtomicM
import           Game.LambdaHack.Client.HandleResponseM
import           Game.LambdaHack.Client.LoopM
import           Game.LambdaHack.Client.MonadClient
import           Game.LambdaHack.Client.State
import           Game.LambdaHack.Client.UI
import           Game.LambdaHack.Client.UI.SessionUI
import           Game.LambdaHack.Common.ClientOptions
import           Game.LambdaHack.Common.Kind
import           Game.LambdaHack.Common.MonadStateRead
import qualified Game.LambdaHack.Common.Save as Save
import           Game.LambdaHack.Common.State
import           Game.LambdaHack.Common.Types
import           Game.LambdaHack.Server (ChanServer (..))

data CliState = CliState
  { CliState -> State
cliState   :: State            -- ^ current global state
  , CliState -> StateClient
cliClient  :: StateClient      -- ^ current client state
  , CliState -> Maybe SessionUI
cliSession :: Maybe SessionUI  -- ^ UI state, empty for AI clients
  , CliState -> ChanServer
cliDict    :: ChanServer       -- ^ this client connection information
  , CliState -> ChanSave (StateClient, Maybe SessionUI)
cliToSave  :: Save.ChanSave (StateClient, Maybe SessionUI)
                                   -- ^ connection to the save thread
  }

-- | Client state transformation monad.
newtype CliImplementation a = CliImplementation
  { CliImplementation a -> StateT CliState IO a
runCliImplementation :: StateT CliState IO a }
  deriving (Applicative CliImplementation
a -> CliImplementation a
Applicative CliImplementation =>
(forall a b.
 CliImplementation a
 -> (a -> CliImplementation b) -> CliImplementation b)
-> (forall a b.
    CliImplementation a -> CliImplementation b -> CliImplementation b)
-> (forall a. a -> CliImplementation a)
-> Monad CliImplementation
CliImplementation a
-> (a -> CliImplementation b) -> CliImplementation b
CliImplementation a -> CliImplementation b -> CliImplementation b
forall a. a -> CliImplementation a
forall a b.
CliImplementation a -> CliImplementation b -> CliImplementation b
forall a b.
CliImplementation a
-> (a -> CliImplementation b) -> CliImplementation b
forall (m :: * -> *).
Applicative m =>
(forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: a -> CliImplementation a
$creturn :: forall a. a -> CliImplementation a
>> :: CliImplementation a -> CliImplementation b -> CliImplementation b
$c>> :: forall a b.
CliImplementation a -> CliImplementation b -> CliImplementation b
>>= :: CliImplementation a
-> (a -> CliImplementation b) -> CliImplementation b
$c>>= :: forall a b.
CliImplementation a
-> (a -> CliImplementation b) -> CliImplementation b
$cp1Monad :: Applicative CliImplementation
Monad, a -> CliImplementation b -> CliImplementation a
(a -> b) -> CliImplementation a -> CliImplementation b
(forall a b.
 (a -> b) -> CliImplementation a -> CliImplementation b)
-> (forall a b. a -> CliImplementation b -> CliImplementation a)
-> Functor CliImplementation
forall a b. a -> CliImplementation b -> CliImplementation a
forall a b. (a -> b) -> CliImplementation a -> CliImplementation b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> CliImplementation b -> CliImplementation a
$c<$ :: forall a b. a -> CliImplementation b -> CliImplementation a
fmap :: (a -> b) -> CliImplementation a -> CliImplementation b
$cfmap :: forall a b. (a -> b) -> CliImplementation a -> CliImplementation b
Functor, Functor CliImplementation
a -> CliImplementation a
Functor CliImplementation =>
(forall a. a -> CliImplementation a)
-> (forall a b.
    CliImplementation (a -> b)
    -> CliImplementation a -> CliImplementation b)
-> (forall a b c.
    (a -> b -> c)
    -> CliImplementation a
    -> CliImplementation b
    -> CliImplementation c)
-> (forall a b.
    CliImplementation a -> CliImplementation b -> CliImplementation b)
-> (forall a b.
    CliImplementation a -> CliImplementation b -> CliImplementation a)
-> Applicative CliImplementation
CliImplementation a -> CliImplementation b -> CliImplementation b
CliImplementation a -> CliImplementation b -> CliImplementation a
CliImplementation (a -> b)
-> CliImplementation a -> CliImplementation b
(a -> b -> c)
-> CliImplementation a
-> CliImplementation b
-> CliImplementation c
forall a. a -> CliImplementation a
forall a b.
CliImplementation a -> CliImplementation b -> CliImplementation a
forall a b.
CliImplementation a -> CliImplementation b -> CliImplementation b
forall a b.
CliImplementation (a -> b)
-> CliImplementation a -> CliImplementation b
forall a b c.
(a -> b -> c)
-> CliImplementation a
-> CliImplementation b
-> CliImplementation c
forall (f :: * -> *).
Functor f =>
(forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: CliImplementation a -> CliImplementation b -> CliImplementation a
$c<* :: forall a b.
CliImplementation a -> CliImplementation b -> CliImplementation a
*> :: CliImplementation a -> CliImplementation b -> CliImplementation b
$c*> :: forall a b.
CliImplementation a -> CliImplementation b -> CliImplementation b
liftA2 :: (a -> b -> c)
-> CliImplementation a
-> CliImplementation b
-> CliImplementation c
$cliftA2 :: forall a b c.
(a -> b -> c)
-> CliImplementation a
-> CliImplementation b
-> CliImplementation c
<*> :: CliImplementation (a -> b)
-> CliImplementation a -> CliImplementation b
$c<*> :: forall a b.
CliImplementation (a -> b)
-> CliImplementation a -> CliImplementation b
pure :: a -> CliImplementation a
$cpure :: forall a. a -> CliImplementation a
$cp1Applicative :: Functor CliImplementation
Applicative)

instance MonadStateRead CliImplementation where
  {-# INLINE getsState #-}
  getsState :: (State -> a) -> CliImplementation a
getsState f :: State -> a
f = StateT CliState IO a -> CliImplementation a
forall a. StateT CliState IO a -> CliImplementation a
CliImplementation (StateT CliState IO a -> CliImplementation a)
-> StateT CliState IO a -> CliImplementation a
forall a b. (a -> b) -> a -> b
$ (CliState -> a) -> StateT CliState IO a
forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets ((CliState -> a) -> StateT CliState IO a)
-> (CliState -> a) -> StateT CliState IO a
forall a b. (a -> b) -> a -> b
$ State -> a
f (State -> a) -> (CliState -> State) -> CliState -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CliState -> State
cliState

instance MonadStateWrite CliImplementation where
  {-# INLINE modifyState #-}
  modifyState :: (State -> State) -> CliImplementation ()
modifyState f :: State -> State
f = StateT CliState IO () -> CliImplementation ()
forall a. StateT CliState IO a -> CliImplementation a
CliImplementation (StateT CliState IO () -> CliImplementation ())
-> StateT CliState IO () -> CliImplementation ()
forall a b. (a -> b) -> a -> b
$ (CliState -> ((), CliState)) -> StateT CliState IO ()
forall (m :: * -> *) s a. Monad m => (s -> (a, s)) -> StateT s m a
state ((CliState -> ((), CliState)) -> StateT CliState IO ())
-> (CliState -> ((), CliState)) -> StateT CliState IO ()
forall a b. (a -> b) -> a -> b
$ \cliS :: CliState
cliS ->
    let !newCliS :: CliState
newCliS = CliState
cliS {cliState :: State
cliState = State -> State
f (State -> State) -> State -> State
forall a b. (a -> b) -> a -> b
$ CliState -> State
cliState CliState
cliS}
    in ((), CliState
newCliS)
  {-# INLINE putState #-}
  putState :: State -> CliImplementation ()
putState newCliState :: State
newCliState = StateT CliState IO () -> CliImplementation ()
forall a. StateT CliState IO a -> CliImplementation a
CliImplementation (StateT CliState IO () -> CliImplementation ())
-> StateT CliState IO () -> CliImplementation ()
forall a b. (a -> b) -> a -> b
$ (CliState -> ((), CliState)) -> StateT CliState IO ()
forall (m :: * -> *) s a. Monad m => (s -> (a, s)) -> StateT s m a
state ((CliState -> ((), CliState)) -> StateT CliState IO ())
-> (CliState -> ((), CliState)) -> StateT CliState IO ()
forall a b. (a -> b) -> a -> b
$ \cliS :: CliState
cliS ->
    let !newCliS :: CliState
newCliS = CliState
cliS {cliState :: State
cliState = State
newCliState}
    in ((), CliState
newCliS)

instance MonadClientRead CliImplementation where
  {-# INLINE getsClient #-}
  getsClient :: (StateClient -> a) -> CliImplementation a
getsClient f :: StateClient -> a
f = StateT CliState IO a -> CliImplementation a
forall a. StateT CliState IO a -> CliImplementation a
CliImplementation (StateT CliState IO a -> CliImplementation a)
-> StateT CliState IO a -> CliImplementation a
forall a b. (a -> b) -> a -> b
$ (CliState -> a) -> StateT CliState IO a
forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets ((CliState -> a) -> StateT CliState IO a)
-> (CliState -> a) -> StateT CliState IO a
forall a b. (a -> b) -> a -> b
$ StateClient -> a
f (StateClient -> a) -> (CliState -> StateClient) -> CliState -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CliState -> StateClient
cliClient
  liftIO :: IO a -> CliImplementation a
liftIO = StateT CliState IO a -> CliImplementation a
forall a. StateT CliState IO a -> CliImplementation a
CliImplementation (StateT CliState IO a -> CliImplementation a)
-> (IO a -> StateT CliState IO a) -> IO a -> CliImplementation a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO a -> StateT CliState IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
IO.liftIO

instance MonadClient CliImplementation where
  {-# INLINE modifyClient #-}
  modifyClient :: (StateClient -> StateClient) -> CliImplementation ()
modifyClient f :: StateClient -> StateClient
f = StateT CliState IO () -> CliImplementation ()
forall a. StateT CliState IO a -> CliImplementation a
CliImplementation (StateT CliState IO () -> CliImplementation ())
-> StateT CliState IO () -> CliImplementation ()
forall a b. (a -> b) -> a -> b
$ (CliState -> ((), CliState)) -> StateT CliState IO ()
forall (m :: * -> *) s a. Monad m => (s -> (a, s)) -> StateT s m a
state ((CliState -> ((), CliState)) -> StateT CliState IO ())
-> (CliState -> ((), CliState)) -> StateT CliState IO ()
forall a b. (a -> b) -> a -> b
$ \cliS :: CliState
cliS ->
    let !newCliS :: CliState
newCliS = CliState
cliS {cliClient :: StateClient
cliClient = StateClient -> StateClient
f (StateClient -> StateClient) -> StateClient -> StateClient
forall a b. (a -> b) -> a -> b
$ CliState -> StateClient
cliClient CliState
cliS}
    in ((), CliState
newCliS)

instance MonadClientSetup CliImplementation where
  saveClient :: CliImplementation ()
saveClient = StateT CliState IO () -> CliImplementation ()
forall a. StateT CliState IO a -> CliImplementation a
CliImplementation (StateT CliState IO () -> CliImplementation ())
-> StateT CliState IO () -> CliImplementation ()
forall a b. (a -> b) -> a -> b
$ do
    ChanSave (StateClient, Maybe SessionUI)
toSave <- (CliState -> ChanSave (StateClient, Maybe SessionUI))
-> StateT CliState IO (ChanSave (StateClient, Maybe SessionUI))
forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets CliState -> ChanSave (StateClient, Maybe SessionUI)
cliToSave
    StateClient
cli <- (CliState -> StateClient) -> StateT CliState IO StateClient
forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets CliState -> StateClient
cliClient
    Maybe SessionUI
msess <- (CliState -> Maybe SessionUI)
-> StateT CliState IO (Maybe SessionUI)
forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets CliState -> Maybe SessionUI
cliSession
    IO () -> StateT CliState IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
IO.liftIO (IO () -> StateT CliState IO ()) -> IO () -> StateT CliState IO ()
forall a b. (a -> b) -> a -> b
$ ChanSave (StateClient, Maybe SessionUI)
-> (StateClient, Maybe SessionUI) -> IO ()
forall a. ChanSave a -> a -> IO ()
Save.saveToChan ChanSave (StateClient, Maybe SessionUI)
toSave (StateClient
cli, Maybe SessionUI
msess)

instance MonadClientUI CliImplementation where
  {-# INLINE getsSession #-}
  getsSession :: (SessionUI -> a) -> CliImplementation a
getsSession f :: SessionUI -> a
f = StateT CliState IO a -> CliImplementation a
forall a. StateT CliState IO a -> CliImplementation a
CliImplementation (StateT CliState IO a -> CliImplementation a)
-> StateT CliState IO a -> CliImplementation a
forall a b. (a -> b) -> a -> b
$ (CliState -> a) -> StateT CliState IO a
forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets ((CliState -> a) -> StateT CliState IO a)
-> (CliState -> a) -> StateT CliState IO a
forall a b. (a -> b) -> a -> b
$ SessionUI -> a
f (SessionUI -> a) -> (CliState -> SessionUI) -> CliState -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe SessionUI -> SessionUI
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe SessionUI -> SessionUI)
-> (CliState -> Maybe SessionUI) -> CliState -> SessionUI
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CliState -> Maybe SessionUI
cliSession
  {-# INLINE modifySession #-}
  modifySession :: (SessionUI -> SessionUI) -> CliImplementation ()
modifySession f :: SessionUI -> SessionUI
f = StateT CliState IO () -> CliImplementation ()
forall a. StateT CliState IO a -> CliImplementation a
CliImplementation (StateT CliState IO () -> CliImplementation ())
-> StateT CliState IO () -> CliImplementation ()
forall a b. (a -> b) -> a -> b
$ (CliState -> ((), CliState)) -> StateT CliState IO ()
forall (m :: * -> *) s a. Monad m => (s -> (a, s)) -> StateT s m a
state ((CliState -> ((), CliState)) -> StateT CliState IO ())
-> (CliState -> ((), CliState)) -> StateT CliState IO ()
forall a b. (a -> b) -> a -> b
$ \cliS :: CliState
cliS ->
    let !newCliSession :: SessionUI
newCliSession = SessionUI -> SessionUI
f (SessionUI -> SessionUI) -> SessionUI -> SessionUI
forall a b. (a -> b) -> a -> b
$ Maybe SessionUI -> SessionUI
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe SessionUI -> SessionUI) -> Maybe SessionUI -> SessionUI
forall a b. (a -> b) -> a -> b
$ CliState -> Maybe SessionUI
cliSession CliState
cliS
        !newCliS :: CliState
newCliS = CliState
cliS {cliSession :: Maybe SessionUI
cliSession = SessionUI -> Maybe SessionUI
forall a. a -> Maybe a
Just SessionUI
newCliSession}
    in ((), CliState
newCliS)
  updateClientLeader :: ActorId -> CliImplementation ()
updateClientLeader aid :: ActorId
aid = do
    State
s <- CliImplementation State
forall (m :: * -> *). MonadStateRead m => m State
getState
    (StateClient -> StateClient) -> CliImplementation ()
forall (m :: * -> *).
MonadClient m =>
(StateClient -> StateClient) -> m ()
modifyClient ((StateClient -> StateClient) -> CliImplementation ())
-> (StateClient -> StateClient) -> CliImplementation ()
forall a b. (a -> b) -> a -> b
$ ActorId -> State -> StateClient -> StateClient
updateLeader ActorId
aid State
s
  getCacheBfs :: ActorId -> CliImplementation (Array BfsDistance)
getCacheBfs = ActorId -> CliImplementation (Array BfsDistance)
forall (m :: * -> *).
MonadClient m =>
ActorId -> m (Array BfsDistance)
BfsM.getCacheBfs
  getCachePath :: ActorId -> Point -> CliImplementation (Maybe AndPath)
getCachePath = ActorId -> Point -> CliImplementation (Maybe AndPath)
forall (m :: * -> *).
MonadClient m =>
ActorId -> Point -> m (Maybe AndPath)
BfsM.getCachePath

instance MonadClientReadResponse CliImplementation where
  receiveResponse :: CliImplementation Response
receiveResponse = StateT CliState IO Response -> CliImplementation Response
forall a. StateT CliState IO a -> CliImplementation a
CliImplementation (StateT CliState IO Response -> CliImplementation Response)
-> StateT CliState IO Response -> CliImplementation Response
forall a b. (a -> b) -> a -> b
$ do
    ChanServer{CliSerQueue Response
responseS :: ChanServer -> CliSerQueue Response
responseS :: CliSerQueue Response
responseS} <- (CliState -> ChanServer) -> StateT CliState IO ChanServer
forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets CliState -> ChanServer
cliDict
    IO Response -> StateT CliState IO Response
forall (m :: * -> *) a. MonadIO m => IO a -> m a
IO.liftIO (IO Response -> StateT CliState IO Response)
-> IO Response -> StateT CliState IO Response
forall a b. (a -> b) -> a -> b
$ CliSerQueue Response -> IO Response
forall a. MVar a -> IO a
takeMVar CliSerQueue Response
responseS

instance MonadClientWriteRequest CliImplementation where
  sendRequestAI :: RequestAI -> CliImplementation ()
sendRequestAI scmd :: RequestAI
scmd = StateT CliState IO () -> CliImplementation ()
forall a. StateT CliState IO a -> CliImplementation a
CliImplementation (StateT CliState IO () -> CliImplementation ())
-> StateT CliState IO () -> CliImplementation ()
forall a b. (a -> b) -> a -> b
$ do
    ChanServer{CliSerQueue RequestAI
requestAIS :: ChanServer -> CliSerQueue RequestAI
requestAIS :: CliSerQueue RequestAI
requestAIS} <- (CliState -> ChanServer) -> StateT CliState IO ChanServer
forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets CliState -> ChanServer
cliDict
    IO () -> StateT CliState IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
IO.liftIO (IO () -> StateT CliState IO ()) -> IO () -> StateT CliState IO ()
forall a b. (a -> b) -> a -> b
$ CliSerQueue RequestAI -> RequestAI -> IO ()
forall a. MVar a -> a -> IO ()
putMVar CliSerQueue RequestAI
requestAIS RequestAI
scmd
  sendRequestUI :: RequestUI -> CliImplementation ()
sendRequestUI scmd :: RequestUI
scmd = StateT CliState IO () -> CliImplementation ()
forall a. StateT CliState IO a -> CliImplementation a
CliImplementation (StateT CliState IO () -> CliImplementation ())
-> StateT CliState IO () -> CliImplementation ()
forall a b. (a -> b) -> a -> b
$ do
    ChanServer{Maybe (CliSerQueue RequestUI)
requestUIS :: ChanServer -> Maybe (CliSerQueue RequestUI)
requestUIS :: Maybe (CliSerQueue RequestUI)
requestUIS} <- (CliState -> ChanServer) -> StateT CliState IO ChanServer
forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets CliState -> ChanServer
cliDict
    IO () -> StateT CliState IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
IO.liftIO (IO () -> StateT CliState IO ()) -> IO () -> StateT CliState IO ()
forall a b. (a -> b) -> a -> b
$ CliSerQueue RequestUI -> RequestUI -> IO ()
forall a. MVar a -> a -> IO ()
putMVar (Maybe (CliSerQueue RequestUI) -> CliSerQueue RequestUI
forall a. HasCallStack => Maybe a -> a
fromJust Maybe (CliSerQueue RequestUI)
requestUIS) RequestUI
scmd
  clientHasUI :: CliImplementation Bool
clientHasUI = StateT CliState IO Bool -> CliImplementation Bool
forall a. StateT CliState IO a -> CliImplementation a
CliImplementation (StateT CliState IO Bool -> CliImplementation Bool)
-> StateT CliState IO Bool -> CliImplementation Bool
forall a b. (a -> b) -> a -> b
$ do
    Maybe SessionUI
mSession <- (CliState -> Maybe SessionUI)
-> StateT CliState IO (Maybe SessionUI)
forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets CliState -> Maybe SessionUI
cliSession
    Bool -> StateT CliState IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> StateT CliState IO Bool)
-> Bool -> StateT CliState IO Bool
forall a b. (a -> b) -> a -> b
$! Maybe SessionUI -> Bool
forall a. Maybe a -> Bool
isJust Maybe SessionUI
mSession

instance MonadClientAtomic CliImplementation where
  {-# INLINE execUpdAtomic #-}
  execUpdAtomic :: UpdAtomic -> CliImplementation ()
execUpdAtomic _ = () -> CliImplementation ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()  -- handleUpdAtomic, until needed, save resources
    -- Don't catch anything; assume exceptions impossible.
  {-# INLINE execPutState #-}
  execPutState :: State -> CliImplementation ()
execPutState = State -> CliImplementation ()
forall (m :: * -> *). MonadStateWrite m => State -> m ()
putState

-- | Run the main client loop, with the given arguments and empty
-- initial states, in the @IO@ monad.
executorCli :: CCUI -> UIOptions -> ClientOptions
            -> COps
            -> Bool
            -> FactionId
            -> ChanServer
            -> IO ()
executorCli :: CCUI
-> UIOptions
-> ClientOptions
-> COps
-> Bool
-> FactionId
-> ChanServer
-> IO ()
executorCli ccui :: CCUI
ccui sUIOptions :: UIOptions
sUIOptions clientOptions :: ClientOptions
clientOptions cops :: COps
cops@COps{RuleContent
corule :: COps -> RuleContent
corule :: RuleContent
corule} isUI :: Bool
isUI fid :: FactionId
fid cliDict :: ChanServer
cliDict =
  let cliSession :: Maybe SessionUI
cliSession | Bool
isUI = SessionUI -> Maybe SessionUI
forall a. a -> Maybe a
Just (SessionUI -> Maybe SessionUI) -> SessionUI -> Maybe SessionUI
forall a b. (a -> b) -> a -> b
$ UIOptions -> SessionUI
emptySessionUI UIOptions
sUIOptions
                 | Bool
otherwise = Maybe SessionUI
forall a. Maybe a
Nothing
      stateToFileName :: (StateClient, Maybe SessionUI) -> String
stateToFileName (cli :: StateClient
cli, _) =
        ClientOptions -> String
ssavePrefixCli (StateClient -> ClientOptions
soptions StateClient
cli) String -> String -> String
forall a. Semigroup a => a -> a -> a
<> RuleContent -> FactionId -> String
Save.saveNameCli RuleContent
corule (StateClient -> FactionId
sside StateClient
cli)
      totalState :: ChanSave (StateClient, Maybe SessionUI) -> CliState
totalState cliToSave :: ChanSave (StateClient, Maybe SessionUI)
cliToSave = $WCliState :: State
-> StateClient
-> Maybe SessionUI
-> ChanServer
-> ChanSave (StateClient, Maybe SessionUI)
-> CliState
CliState
        { cliState :: State
cliState = (COps -> COps) -> State -> State
updateCOpsAndCachedData (COps -> COps -> COps
forall a b. a -> b -> a
const COps
cops) State
emptyState
            -- state is empty, so the cached data is left empty and untouched
        , cliClient :: StateClient
cliClient = FactionId -> StateClient
emptyStateClient FactionId
fid
        , ChanServer
cliDict :: ChanServer
cliDict :: ChanServer
cliDict
        , ChanSave (StateClient, Maybe SessionUI)
cliToSave :: ChanSave (StateClient, Maybe SessionUI)
cliToSave :: ChanSave (StateClient, Maybe SessionUI)
cliToSave
        , Maybe SessionUI
cliSession :: Maybe SessionUI
cliSession :: Maybe SessionUI
cliSession
        }
      m :: CliImplementation ()
m = CCUI -> UIOptions -> ClientOptions -> CliImplementation ()
forall (m :: * -> *).
(MonadClientSetup m, MonadClientUI m, MonadClientAtomic m,
 MonadClientReadResponse m, MonadClientWriteRequest m) =>
CCUI -> UIOptions -> ClientOptions -> m ()
loopCli CCUI
ccui UIOptions
sUIOptions ClientOptions
clientOptions
      exe :: ChanSave (StateClient, Maybe SessionUI) -> IO ()
exe = StateT CliState IO () -> CliState -> IO ()
forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
evalStateT (CliImplementation () -> StateT CliState IO ()
forall a. CliImplementation a -> StateT CliState IO a
runCliImplementation CliImplementation ()
m) (CliState -> IO ())
-> (ChanSave (StateClient, Maybe SessionUI) -> CliState)
-> ChanSave (StateClient, Maybe SessionUI)
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ChanSave (StateClient, Maybe SessionUI) -> CliState
totalState
  in COps
-> ((StateClient, Maybe SessionUI) -> String)
-> (ChanSave (StateClient, Maybe SessionUI) -> IO ())
-> IO ()
forall a.
Binary a =>
COps -> (a -> String) -> (ChanSave a -> IO ()) -> IO ()
Save.wrapInSaves COps
cops (StateClient, Maybe SessionUI) -> String
stateToFileName ChanSave (StateClient, Maybe SessionUI) -> IO ()
exe