handle first Vty event: quit on escape key

This commit is contained in:
Amedeo Molnár 2024-10-28 12:20:04 +01:00
parent 6f0c65a29b
commit 26437b76be
6 changed files with 78 additions and 31 deletions

View file

@ -55,13 +55,10 @@ sendMessage msg sock = do
handleMessages handleMessages
:: Game () :: Game ()
handleMessages = do handleMessages = do
queue <- asks rcQueue queue <- asks rcMessageQueue
msgs <- liftIO $ STM.atomically $ STM.flushTQueue queue msgs <- liftIO $ STM.atomically $ STM.flushTQueue queue
mapM_ mapM_
(\msg -> do handleMessage
-- liftIO $ putStrLn $ "Handling following: " <> show msg
handleMessage msg
)
msgs msgs
handleMessage handleMessage

View file

@ -0,0 +1,46 @@
module Client.Events where
import Control.Concurrent.STM (atomically, writeTQueue, flushTQueue)
import Control.Monad.IO.Class (liftIO)
import Control.Monad.RWS (asks, gets)
import Data.IORef (modifyIORef')
import Graphics.Vty
-- internal imports
import Client.Types
handleEvent
:: Event
-> Game ()
handleEvent (EvKey KEsc _) = do
stopper <- gets scStopper
liftIO $ modifyIORef' stopper (const True)
handleEvent _ =
pure ()
handleEvents
:: Game ()
handleEvents = do
eventQueue <- asks rcEventQueue
evs <- liftIO $ atomically $ flushTQueue eventQueue
mapM_
handleEvent
evs
pumpEvents
:: Vty
-> Game ()
pumpEvents vty = do
eventQueue <- asks rcEventQueue
mev <- liftIO $ nextEventNonblocking vty
case mev of
Just ev -> do
liftIO $ atomically $ writeTQueue eventQueue ev
pumpEvents vty
Nothing ->
return ()

View file

@ -1,16 +1,19 @@
module Client.Game where module Client.Game where
import Control.Concurrent.STM (atomically, readTMVar)
import Control.Monad.IO.Class (liftIO)
import Control.Monad.Loops import Control.Monad.Loops
import Control.Monad.RWS import Control.Monad.RWS
import Data.IORef (readIORef) import Data.IORef (readIORef)
import Graphics.Vty
-- internal imports -- internal imports
import Client.Communication import Client.Communication
import Client.Events
import Client.Graphics import Client.Graphics
import Client.Types import Client.Types
@ -20,22 +23,18 @@ runGame
:: Game () :: Game ()
runGame = do runGame = do
sock <- asks rcSocket sock <- asks rcSocket
queue <- asks rcQueue messageQueue <- asks rcMessageQueue
clientId <- asks rcClientUUID clientId <- asks rcClientUUID
st <- get st <- get
vty <- clientVty <$> liftIO (atomically $ readTMVar (scClientState st))
liftIO $ sendMessage (ClientMessage clientId ClientReady) sock liftIO $ sendMessage (ClientMessage clientId ClientReady) sock
whileM_ whileM_
(liftIO (not <$> readIORef (scStopper st))) (liftIO (not <$> readIORef (scStopper st)))
(do (do
liftIO $ receiveMessage sock queue st liftIO $ receiveMessage sock messageQueue st
handleMessages handleMessages
pumpEvents vty
handleEvents
draw draw
) )
liftIO $ sendMessage (ClientMessage clientId ClientQuit) sock
handleEvent
:: Maybe Event
-> Game ()
handleEvent Nothing =
pure ()
handleEvent (Just event) =
pure ()

View file

@ -10,6 +10,8 @@ import Data.IORef (IORef)
import Data.UUID import Data.UUID
import Graphics.Vty
import Network.Socket import Network.Socket
import Options.Applicative as O import Options.Applicative as O
@ -32,7 +34,8 @@ options = Options
data ReaderContainer = ReaderContainer data ReaderContainer = ReaderContainer
{ rcSocket :: Socket { rcSocket :: Socket
, rcClientUUID :: UUID , rcClientUUID :: UUID
, rcQueue :: STM.TQueue ServerMessage , rcMessageQueue :: STM.TQueue ServerMessage
, rcEventQueue :: STM.TQueue Event
} }
data StateContainer = StateContainer data StateContainer = StateContainer

View file

@ -34,16 +34,17 @@ main = do
putStrLn "connected" putStrLn "connected"
queue <- STM.newTQueueIO messageQueue <- STM.newTQueueIO
eventQueue <- STM.newTQueueIO
-- threadDelay $ 1 * 10 ^ 6 -- threadDelay $ 1 * 10 ^ 6
mockClientState <- STM.newTMVarIO (ClientState undefined False) mockClientState <- STM.newTMVarIO (ClientState undefined False)
let mockState = StateContainer undefined mockClientState undefined undefined let mockState = StateContainer undefined mockClientState undefined undefined
sendMessage IdRequest sock sendMessage IdRequest sock
receiveMessage sock queue mockState receiveMessage sock messageQueue mockState
awaitResponse queue 1 awaitResponse messageQueue 1
clientIdMsg <- head <$> STM.atomically (STM.flushTQueue queue) clientIdMsg <- head <$> STM.atomically (STM.flushTQueue messageQueue)
let clientId = acClientUUID clientIdMsg let clientId = acClientUUID clientIdMsg
putStrLn $ "received client UUID: " <> show clientId putStrLn $ "received client UUID: " <> show clientId
@ -54,9 +55,9 @@ main = do
sendMessage (ClientMessage clientId ClientRequestWizard) sock sendMessage (ClientMessage clientId ClientRequestWizard) sock
-- threadDelay $ 1 * 10 ^ 6 -- threadDelay $ 1 * 10 ^ 6
receiveMessage sock queue mockState receiveMessage sock messageQueue mockState
awaitResponse queue 1 awaitResponse messageQueue 1
playerWizard <- head <$> STM.atomically (STM.flushTQueue queue) playerWizard <- head <$> STM.atomically (STM.flushTQueue messageQueue)
putStrLn $ "received wizard: " <> show (initWizard playerWizard) putStrLn $ "received wizard: " <> show (initWizard playerWizard)
vty <- mkVty defaultConfig vty <- mkVty defaultConfig
@ -68,7 +69,7 @@ main = do
stopper <- newIORef False stopper <- newIORef False
clientState <- STM.newTMVarIO (ClientState vty False) clientState <- STM.newTMVarIO (ClientState vty False)
let initSlice = MapSlice (M.matrix 9 9 (const Nothing)) [] let initSlice = MapSlice (M.matrix 9 9 (const Nothing)) []
let initRead = ReaderContainer sock clientId queue let initRead = ReaderContainer sock clientId messageQueue eventQueue
initState = StateContainer (initWizard playerWizard) clientState initSlice stopper initState = StateContainer (initWizard playerWizard) clientState initSlice stopper
-- putStrLn "sending quit message" -- putStrLn "sending quit message"
-- sendMessage (ClientMessage clientId ClientQuit) sock -- sendMessage (ClientMessage clientId ClientQuit) sock
@ -112,10 +113,10 @@ awaitResponse
-> Int -> Int
-> IO () -> IO ()
awaitResponse _ 10 = error "Tries to communicate with server exceeded" awaitResponse _ 10 = error "Tries to communicate with server exceeded"
awaitResponse queue numTries = do awaitResponse messageQueue numTries = do
responsePresent <- not <$> STM.atomically (STM.isEmptyTQueue queue) responsePresent <- not <$> STM.atomically (STM.isEmptyTQueue messageQueue)
if responsePresent if responsePresent
then pure () then pure ()
else do else do
threadDelay $ 10 ^ 6 threadDelay $ 10 ^ 6
awaitResponse queue (succ numTries) awaitResponse messageQueue (succ numTries)

View file

@ -37,6 +37,7 @@ executable wizard-wipeout-client
import: warnings import: warnings
main-is: Main.hs main-is: Main.hs
other-modules: Client.Communication other-modules: Client.Communication
Client.Events
Client.Game Client.Game
Client.Graphics Client.Graphics
Client.Types Client.Types