2023-12-07 23:45:33 +00:00
|
|
|
{-# LANGUAGE DeriveGeneric #-}
|
2024-11-04 22:58:15 +00:00
|
|
|
{-# LANGUAGE StrictData #-}
|
2023-12-08 04:19:32 +00:00
|
|
|
module Server.Types where
|
|
|
|
|
2024-04-06 00:18:08 +00:00
|
|
|
import Control.Concurrent
|
|
|
|
|
2023-12-10 05:57:48 +00:00
|
|
|
import qualified Control.Concurrent.STM as STM
|
|
|
|
|
2023-12-08 04:19:32 +00:00
|
|
|
import Control.Monad.RWS.Strict
|
2023-12-07 23:45:33 +00:00
|
|
|
|
|
|
|
import qualified Data.Aeson as Aeson
|
2023-12-08 04:19:32 +00:00
|
|
|
|
|
|
|
import Data.Time.Clock
|
|
|
|
|
2023-12-11 08:49:24 +00:00
|
|
|
import Data.UUID
|
|
|
|
|
2023-12-07 23:45:33 +00:00
|
|
|
import GHC.Generics
|
|
|
|
|
2023-12-09 12:58:59 +00:00
|
|
|
import Network.Socket
|
|
|
|
|
2023-12-08 04:19:32 +00:00
|
|
|
import Options.Applicative as O
|
|
|
|
|
2023-12-10 05:57:48 +00:00
|
|
|
--internal imports
|
|
|
|
|
2023-12-08 04:19:32 +00:00
|
|
|
import Library.Types
|
|
|
|
|
2023-12-08 01:26:29 +00:00
|
|
|
data Settings = Settings
|
2024-12-12 08:09:17 +00:00
|
|
|
{ setSocketPath :: !FilePath
|
|
|
|
, setMapRows :: !Int
|
|
|
|
, setMapColumns :: !Int
|
|
|
|
, setSpawnerProbability :: !Float
|
|
|
|
, setFPS :: !Int
|
|
|
|
, setClientMaxTimeout :: !Float
|
|
|
|
, setFramesPerPing :: !Int
|
|
|
|
, setLogLevel :: !LogLevel
|
2023-12-07 23:45:33 +00:00
|
|
|
}
|
|
|
|
deriving (Show, Generic)
|
|
|
|
|
2023-12-08 01:26:29 +00:00
|
|
|
instance Aeson.FromJSON Settings
|
|
|
|
|
2024-11-04 05:53:58 +00:00
|
|
|
data LogLevel
|
|
|
|
= Error
|
|
|
|
| Warning
|
|
|
|
| Info
|
|
|
|
| Verbose
|
|
|
|
deriving (Show, Generic, Eq, Ord)
|
|
|
|
|
|
|
|
instance Aeson.FromJSON LogLevel
|
|
|
|
|
2023-12-08 04:19:32 +00:00
|
|
|
newtype Options = Options
|
2023-12-08 01:26:29 +00:00
|
|
|
{ optConfLoc :: FilePath
|
|
|
|
}
|
2023-12-08 04:19:32 +00:00
|
|
|
|
|
|
|
options :: O.Parser Options
|
|
|
|
options = Options
|
|
|
|
<$> strOption
|
|
|
|
( long "configuration"
|
|
|
|
<> short 'c'
|
|
|
|
<> metavar "FILEPATH"
|
|
|
|
<> help "Location of the configuration YAML-file"
|
|
|
|
)
|
|
|
|
|
|
|
|
data ReaderContainer = ReaderContainer
|
2024-12-12 08:09:17 +00:00
|
|
|
{ rcMap :: !ServerMap
|
|
|
|
, rcFPS :: !Int
|
|
|
|
, rcFramesPerPing :: !Int
|
|
|
|
, rcClientMaxTimeout :: !Float
|
|
|
|
, rcMainSocket :: !Socket
|
|
|
|
, rcLogLevel :: !LogLevel
|
2023-12-08 04:19:32 +00:00
|
|
|
}
|
|
|
|
deriving (Eq, Show)
|
|
|
|
|
|
|
|
data StateContainer = StateContainer
|
2024-11-29 10:24:07 +00:00
|
|
|
{ scSpawners :: ![Spawner]
|
|
|
|
, scPlayers :: !(STM.TMVar [Player])
|
|
|
|
, scServerState :: !(STM.TMVar ServerState)
|
|
|
|
, scServerLastTick :: !UTCTime
|
|
|
|
, scClientSockets :: !(STM.TMVar [ClientSocket])
|
|
|
|
, scClientQueues :: !(STM.TMVar [ClientQueue])
|
|
|
|
, scMessageQueue :: !(STM.TQueue ClientMessage)
|
2023-12-08 04:19:32 +00:00
|
|
|
}
|
|
|
|
|
2024-11-03 03:40:46 +00:00
|
|
|
data ClientSocket = ClientSocket
|
2024-12-12 08:09:17 +00:00
|
|
|
{ csUUID :: !(Maybe UUID)
|
|
|
|
, csSocket :: !Socket
|
|
|
|
, csSender :: !ThreadId
|
|
|
|
, csReceiver :: !ThreadId
|
2024-11-03 03:40:46 +00:00
|
|
|
}
|
|
|
|
deriving (Eq)
|
|
|
|
|
|
|
|
data ClientQueue = ClientQueue
|
2024-12-12 08:09:17 +00:00
|
|
|
{ cqUUID :: !(Maybe UUID)
|
|
|
|
, cqQueue :: !(STM.TQueue ServerMessage)
|
2024-04-06 00:18:08 +00:00
|
|
|
}
|
|
|
|
deriving (Eq)
|
|
|
|
|
2023-12-13 10:06:45 +00:00
|
|
|
data Player = Player
|
2024-12-12 08:09:17 +00:00
|
|
|
{ playerId :: !UUID
|
|
|
|
, playerWizard :: !Wizard
|
|
|
|
, playerReady :: !Bool
|
|
|
|
, playerLastPong :: !(UTCTime, UUID)
|
2023-12-13 10:06:45 +00:00
|
|
|
}
|
|
|
|
deriving (Eq, Show)
|
|
|
|
|
2023-12-10 01:02:09 +00:00
|
|
|
-- | Data object for storing the server's state
|
|
|
|
data ServerState = ServerState
|
2024-12-12 08:09:17 +00:00
|
|
|
{ serverGameOver :: !Bool -- ^ global game over state (only one contestant left)
|
|
|
|
, serverStop :: !Bool -- ^ Server shutdown
|
2023-12-10 01:02:09 +00:00
|
|
|
}
|
|
|
|
deriving (Show, Eq)
|
|
|
|
|
2023-12-10 05:57:48 +00:00
|
|
|
type Game = RWST ReaderContainer String StateContainer IO
|