wizard-wipeout/src-client/Main.hs
2024-11-25 03:48:18 +01:00

137 lines
3.8 KiB
Haskell

module Main where
import Control.Concurrent (threadDelay)
import qualified Control.Concurrent.STM as STM
import Control.Monad
import Control.Monad.RWS
import Data.IORef
import qualified Data.Matrix as M
import Graphics.Vty
import Graphics.Vty.CrossPlatform
import Network.Socket (Socket, close)
import Options.Applicative
-- internal imports
import Client.Communication
import Client.Game
import Client.Log
import Client.Types
import Library.Types
main :: IO ()
main = do
putStrLn "Hello, Arena!"
(Options logLevel socketLocation) <- execParser opts
logPrintIO logLevel Info $ "connecting to Socket " <> socketLocation
sock <- connectSocket socketLocation
logPrintIO logLevel Info "connected"
messageQueue <- STM.newTQueueIO
eventQueue <- STM.newTQueueIO
-- threadDelay $ 1 * 10 ^ 6
mockClientState <- STM.newTMVarIO
( ClientState
(error "trying to access vty of mock client state")
False
)
let mockState =
StateContainer
(error "trying to access wizard of mock game state")
mockClientState
(error "trying to access map slice of mock game state")
(error "trying to access stop condition of mock game state")
sendMessage logLevel IdRequest sock
clientIdMsg <- awaitResponse logLevel sock messageQueue mockState 0
let clientId = acClientUUID clientIdMsg
logPrintIO logLevel Info $ "received client UUID: " <> show clientId
putStrLn welcomeText
threadDelay $ 5 * 10 ^ (6 :: Int)
sendMessage logLevel (ClientMessage clientId ClientRequestWizard) sock
-- threadDelay $ 1 * 10 ^ 6
playerWizard <- awaitResponse logLevel sock messageQueue mockState 1
logPrintIO logLevel Info $ "received wizard: " <> show (initWizard playerWizard)
vty <- mkVty defaultConfig
hideCursor (outputIface vty)
-- shut down graphical interface for now
-- shutdown vty
stopper <- newIORef False
clientState <- STM.newTMVarIO (ClientState vty False)
let initSlice = MapSlice (M.matrix 9 9 (const Nothing)) []
let initRead = ReaderContainer sock clientId messageQueue eventQueue logLevel
initState = StateContainer (initWizard playerWizard) clientState initSlice stopper
-- putStrLn "sending quit message"
-- sendMessage (ClientMessage clientId ClientQuit) sock
logPrintIO logLevel Info "entering Game Monad"
void $ execRWST
(do
terminateGameOnSigint stopper
logPrint Verbose "entering main game function"
runGame
)
initRead
initState
logPrintIO logLevel Info "Shutting down client…"
showCursor (outputIface vty)
shutdown vty
threadDelay 1000
logPrintIO logLevel Info "Closing connection to server…"
close sock
putStrLn "bye bye"
where
opts = info (options <**> helper)
( fullDesc
<> progDesc "Run the \"wizard-wipeout\" Client."
<> header "wizard-wipeout - Last Mage standing"
)
welcomeText :: String
welcomeText = mconcat $ map (<> "\n")
[ "Welcome to the arena, wizards."
, ""
, "Let the toughest and bravest of you survive"
, ""
, "Some last hints before you enter the fighting grounds:"
, ""
, "press [SPACE] to fire your wand"
, "press [1] through [9] to change wands, if you have collected more wands"
, "press [ESC] to leave"
, ""
, "Good Luck!"
]
awaitResponse
:: LogLevel
-> Socket
-> STM.TQueue ServerMessage
-> StateContainer
-> Int
-> IO ServerMessage
awaitResponse _ _ _ _ 10 = error "Tries to communicate with server exceeded"
awaitResponse curLevel sock messageQueue mockState numTries = do
receiveMessage curLevel sock messageQueue mockState
responsePresent <- not <$> STM.atomically (STM.isEmptyTQueue messageQueue)
if responsePresent
then STM.atomically $ STM.readTQueue messageQueue
else do
threadDelay $ 10 ^ (6 :: Int)
awaitResponse curLevel sock messageQueue mockState (numTries + 1)