This commit is contained in:
nek0 2024-04-17 19:44:47 +02:00
parent cd16ce7971
commit 65e0c5d272
5 changed files with 39 additions and 26 deletions

View file

@ -16,6 +16,8 @@ import qualified Data.Aeson as A
import qualified Data.ByteString as B import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy.Char8 as B8 import qualified Data.ByteString.Lazy.Char8 as B8
import Data.IORef
import Data.UUID import Data.UUID
import qualified Data.Vector.Storable as VS import qualified Data.Vector.Storable as VS
@ -50,12 +52,10 @@ sendMessage
-> IO () -> IO ()
sendMessage st msg sock = do sendMessage st msg sock = do
let msgJson = A.encode msg let msgJson = A.encode msg
msgVector = VS.fromList $ B.unpack $ B.toStrict msgJson msgList = B.unpack $ B.toStrict msgJson
VS.unsafeWith ptr <- newArray msgList
msgVector void $ sendBuf sock ptr (length msgList)
(\ptr -> do free ptr
void $ sendBuf sock ptr (VS.length msgVector)
)
handleMessages handleMessages
:: Game () :: Game ()
@ -141,24 +141,19 @@ receiveMessage sock queue st = do
mJsonMsg mJsonMsg
) )
msgs msgs
free ptr
-- | Function that installs a handler on SIGINT to terminate game -- | Function that installs a handler on SIGINT to terminate game
terminateGameOnSigint terminateGameOnSigint
:: Game () :: IORef Bool
terminateGameOnSigint = do -> Game ()
sock <- asks rcSocket terminateGameOnSigint stopper = do
clientId <- asks rcClientUUID
clientState <- gets scClientState
st <- get
void $ liftIO $ installHandler void $ liftIO $ installHandler
keyboardSignal keyboardSignal
(CatchOnce $ do (CatchOnce $ do
putStrLn "receiveMessage: SIGINT caught, terminating…" putStrLn "receiveMessage: SIGINT caught, terminating…"
STM.atomically $ do atomicWriteIORef stopper True
currentState <- STM.readTMVar clientState
void $ STM.swapTMVar clientState $ currentState { clientStop = True }
-- Vty.shutdown (clientVty currentState) -- Vty.shutdown (clientVty currentState)
partingMessage st clientId sock
-- Raise SIGINT again so it does not get blocked -- Raise SIGINT again so it does not get blocked
-- raiseSignal keyboardSignal -- raiseSignal keyboardSignal
) )

View file

@ -10,6 +10,8 @@ import Control.Monad.Loops
import Control.Monad.RWS import Control.Monad.RWS
import Data.IORef (IORef, readIORef)
import Graphics.Vty import Graphics.Vty
-- internal imports -- internal imports
@ -20,21 +22,25 @@ import Client.Types
import Library.Types import Library.Types
runGame :: Game () runGame
runGame = do :: IORef Bool
-> Game ()
runGame stopper = do
sock <- asks rcSocket sock <- asks rcSocket
queue <- asks rcQueue queue <- asks rcQueue
clientId <- asks rcClientUUID clientId <- asks rcClientUUID
st <- get st <- get
recvThread <- liftIO $ forkIO $ forever $ receiveMessage sock queue st -- recvThread <- liftIO $ forkIO $ forever $ receiveMessage sock queue st
liftIO $ sendMessage st(ClientMessage clientId ClientReady) sock liftIO $ sendMessage st(ClientMessage clientId ClientReady) sock
whileM_ whileM_
(not . clientStop <$> (liftIO . STM.atomically . STM.readTMVar =<< gets scClientState)) (liftIO (not <$> readIORef stopper))
(do (do
liftIO $ receiveMessage sock queue st
handleMessages handleMessages
-- draw -- draw
) )
liftIO $ killThread recvThread liftIO $ partingMessage st clientId sock
-- liftIO $ killThread recvThread
handleEvent handleEvent
:: Maybe Event :: Maybe Event

View file

@ -2,6 +2,8 @@ module Client.Types where
import qualified Control.Concurrent.STM as STM import qualified Control.Concurrent.STM as STM
import Control.Exception (Exception)
import Control.Monad.RWS import Control.Monad.RWS
import Data.UUID import Data.UUID
@ -38,3 +40,8 @@ data StateContainer = StateContainer
} }
type Game = RWST ReaderContainer String StateContainer IO type Game = RWST ReaderContainer String StateContainer IO
data ClientTerminate = ClientTerminate
deriving (Show)
instance Exception ClientTerminate

View file

@ -8,6 +8,8 @@ import Control.Monad
import Control.Monad.RWS import Control.Monad.RWS
import Data.IORef
import qualified Data.Matrix as M import qualified Data.Matrix as M
import Graphics.Vty import Graphics.Vty
@ -71,17 +73,18 @@ main = do
initState = StateContainer (initWizard playerWizard) clientState initSlice initState = StateContainer (initWizard playerWizard) clientState initSlice
-- putStrLn "sending quit message" -- putStrLn "sending quit message"
-- sendMessage (ClientMessage clientId ClientQuit) sock -- sendMessage (ClientMessage clientId ClientQuit) sock
stopper <- newIORef False
void $ execRWST void $ execRWST
(do (do
terminateGameOnSigint terminateGameOnSigint stopper
runGame runGame stopper
) )
initRead initRead
initState initState
-- shutdown vty -- shutdown vty
partingMessage initState clientId sock putStrLn "Shutting down client…"
threadDelay 100 -- threadDelay 100
close sock -- close sock
putStrLn "bye bye" putStrLn "bye bye"
where where
opts = info (options <**> helper) opts = info (options <**> helper)

View file

@ -252,11 +252,13 @@ handleMessage stateContainer readerContainer msg = do
ClientQuit -> do ClientQuit -> do
putStrLn $ "removing client " <> show clientId putStrLn $ "removing client " <> show clientId
let newClients = filter (\a -> ccUUID a /= Just clientId) clients let newClients = filter (\a -> ccUUID a /= Just clientId) clients
client = find (\a -> ccUUID a == Just clientId) clients
STM.atomically $ do STM.atomically $ do
currentPlayers <- STM.readTMVar (scPlayers stateContainer) currentPlayers <- STM.readTMVar (scPlayers stateContainer)
let newPlayers = filter (\p -> playerId p /= clientId) currentPlayers let newPlayers = filter (\p -> playerId p /= clientId) currentPlayers
void $ STM.swapTMVar (scPlayers stateContainer) newPlayers void $ STM.swapTMVar (scPlayers stateContainer) newPlayers
void $ STM.swapTMVar clientList newClients void $ STM.swapTMVar clientList newClients
close (ccSocket $ fromJust client)
ClientRequestWizard -> do ClientRequestWizard -> do
putStrLn "initializing new wizard" putStrLn "initializing new wizard"
let arena = rcMap readerContainer let arena = rcMap readerContainer