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 Info logLevel $ "connecting to Socket " <> socketLocation sock <- connectSocket socketLocation logPrintIO Info logLevel "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 Info logLevel $ "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 Info logLevel $ "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 Info logLevel "entering Game Monad" void $ execRWST (do terminateGameOnSigint stopper logPrint Verbose "entering main game function" runGame ) initRead initState logPrintIO Info logLevel "Shutting down client…" showCursor (outputIface vty) shutdown vty threadDelay 1000 logPrintIO Info logLevel "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)