LambdaHack-0.2.12: Game/LambdaHack/Server/State.hs
-- | Server and client game state types and operations.
module Game.LambdaHack.Server.State
( StateServer(..), emptyStateServer
, DebugModeSer(..), defDebugModeSer
, RNGs(..)
) where
import Data.Binary
import qualified Data.EnumMap.Strict as EM
import qualified Data.HashMap.Strict as HM
import Data.List
import Data.Text (Text)
import qualified System.Random as R
import System.Time
import Game.LambdaHack.Common.Actor
import Game.LambdaHack.Common.Animation
import Game.LambdaHack.Common.AtomicCmd
import Game.LambdaHack.Common.Faction
import Game.LambdaHack.Common.Item
import Game.LambdaHack.Common.Perception
import Game.LambdaHack.Common.Time
import Game.LambdaHack.Content.RuleKind
-- | Global, server state.
data StateServer = StateServer
{ sdisco :: !Discovery -- ^ full item discoveries data
, sdiscoRev :: !DiscoRev -- ^ reverse disco map, used for item creation
, sitemRev :: !ItemRev -- ^ reverse id map, used for item creation
, sflavour :: !FlavourMap -- ^ association of flavour to items
, sacounter :: !ActorId -- ^ stores next actor index
, sicounter :: !ItemId -- ^ stores next item index
, sundo :: ![Atomic] -- ^ atomic commands performed to date
, sper :: !Pers -- ^ perception of all factions
, srandom :: !R.StdGen -- ^ current random generator
, srngs :: !RNGs -- ^ initial random generators
, squit :: !Bool -- ^ exit the game loop
, sbkpSave :: !Bool -- ^ make backup savefile now
, sstart :: !ClockTime -- ^ this session start time
, sgstart :: !ClockTime -- ^ this game start time
, sallTime :: !Time -- ^ clips since the start of the session
, sheroNames :: !(EM.EnumMap FactionId [(Int, Text)])
-- ^ hero names sent by clients
, sdebugSer :: !DebugModeSer -- ^ current debugging mode
, sdebugNxt :: !DebugModeSer -- ^ debugging mode for the next game
}
deriving (Show)
-- | Debug commands. See 'Server.debugArgs' for the descriptions.
data DebugModeSer = DebugModeSer
{ sknowMap :: !Bool
, sknowEvents :: !Bool
, sniffIn :: !Bool
, sniffOut :: !Bool
, sallClear :: !Bool
, sgameMode :: !Text
, sstopAfter :: !(Maybe Int)
, sbenchmark :: !Bool
, sdungeonRng :: !(Maybe R.StdGen)
, smainRng :: !(Maybe R.StdGen)
, sfovMode :: !(Maybe FovMode)
, snewGameSer :: !Bool
, sdifficultySer :: !Int
, sdumpInitRngs :: !Bool
, ssavePrefixSer :: !(Maybe String)
, sdbgMsgSer :: !Bool
, sdebugCli :: !DebugModeCli
}
deriving Show
data RNGs = RNGs
{ dungeonRandomGenerator :: !(Maybe R.StdGen)
, startingRandomGenerator :: !(Maybe R.StdGen)
}
instance Show RNGs where
show RNGs{..} =
let args = [ maybe "" (\gen -> "--setDungeonRng \"" ++ show gen ++ "\"")
dungeonRandomGenerator
, maybe "" (\gen -> "--setMainRng \"" ++ show gen ++ "\"")
startingRandomGenerator ]
in intercalate " " args
-- | Initial, empty game server state.
emptyStateServer :: StateServer
emptyStateServer =
StateServer
{ sdisco = EM.empty
, sdiscoRev = EM.empty
, sitemRev = HM.empty
, sflavour = emptyFlavourMap
, sacounter = toEnum 0
, sicounter = toEnum 0
, sundo = []
, sper = EM.empty
, srandom = R.mkStdGen 42
, srngs = RNGs { dungeonRandomGenerator = Nothing
, startingRandomGenerator = Nothing }
, squit = False
, sbkpSave = False
, sstart = TOD 0 0
, sgstart = TOD 0 0
, sallTime = timeZero
, sheroNames = EM.empty
, sdebugSer = defDebugModeSer
, sdebugNxt = defDebugModeSer
}
defDebugModeSer :: DebugModeSer
defDebugModeSer = DebugModeSer { sknowMap = False
, sknowEvents = False
, sniffIn = False
, sniffOut = False
, sallClear = False
, sgameMode = "campaign"
, sstopAfter = Nothing
, sbenchmark = False
, sdungeonRng = Nothing
, smainRng = Nothing
, sfovMode = Nothing
, snewGameSer = False
, sdifficultySer = 0
, sdumpInitRngs = False
, ssavePrefixSer = Nothing
, sdbgMsgSer = False
, sdebugCli = defDebugModeCli
}
instance Binary StateServer where
put StateServer{..} = do
put sdisco
put sdiscoRev
put sitemRev
put sflavour
put sacounter
put sicounter
put sundo
put (show srandom)
put srngs
put sheroNames
put sdebugSer
get = do
sdisco <- get
sdiscoRev <- get
sitemRev <- get
sflavour <- get
sacounter <- get
sicounter <- get
sundo <- get
g <- get
srngs <- get
sheroNames <- get
sdebugSer <- get
let srandom = read g
sper = EM.empty
squit = False
sbkpSave = False
sstart = TOD 0 0
sgstart = TOD 0 0
sallTime = timeZero
sdebugNxt = defDebugModeSer -- TODO: here difficulty level, etc. from the last session is wiped out
return $! StateServer{..}
instance Binary DebugModeSer where
put DebugModeSer{..} = do
put sknowMap
put sknowEvents
put sniffIn
put sniffOut
put sallClear
put sgameMode
put sdifficultySer
put sfovMode
put ssavePrefixSer
put sdbgMsgSer
put sdebugCli
get = do
sknowMap <- get
sknowEvents <- get
sniffIn <- get
sniffOut <- get
sallClear <- get
sgameMode <- get
sdifficultySer <- get
sfovMode <- get
ssavePrefixSer <- get
sdbgMsgSer <- get
sdebugCli <- get
let sstopAfter = Nothing
sbenchmark = False
sdungeonRng = Nothing
smainRng = Nothing
snewGameSer = False
sdumpInitRngs = False
return $! DebugModeSer{..}
instance Binary RNGs where
put RNGs{..} = do
put (show dungeonRandomGenerator)
put (show startingRandomGenerator)
get = do
dg <- get
sg <- get
let dungeonRandomGenerator = read dg
startingRandomGenerator = read sg
return $! RNGs{..}