fix some communication issues
This commit is contained in:
parent
be888101a0
commit
58120fbc1b
6 changed files with 64 additions and 35 deletions
|
@ -2,6 +2,8 @@
|
||||||
{-# LANGUAGE RecordWildCards #-}
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
module Client.Communication where
|
module Client.Communication where
|
||||||
|
|
||||||
|
import Control.Exception
|
||||||
|
|
||||||
import qualified Control.Concurrent.STM as STM
|
import qualified Control.Concurrent.STM as STM
|
||||||
|
|
||||||
import Control.Monad.RWS
|
import Control.Monad.RWS
|
||||||
|
@ -39,15 +41,21 @@ connectSocket path = do
|
||||||
|
|
||||||
-- | Sends a specified message through given socket to the server
|
-- | Sends a specified message through given socket to the server
|
||||||
sendMessage
|
sendMessage
|
||||||
:: ClientMessage
|
:: StateContainer
|
||||||
|
-> ClientMessage
|
||||||
-> Socket
|
-> Socket
|
||||||
-> IO ()
|
-> IO ()
|
||||||
sendMessage 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
|
msgVector = VS.fromList $ B.unpack $ B.toStrict msgJson
|
||||||
VS.unsafeWith
|
VS.unsafeWith
|
||||||
msgVector
|
msgVector
|
||||||
(\ptr -> void $ sendBuf sock ptr (VS.length msgVector))
|
(\ptr -> do
|
||||||
|
eResult <- try $ sendBuf sock ptr (VS.length msgVector)
|
||||||
|
case eResult of
|
||||||
|
Left (_ :: IOException) -> gracefulExit st "Quitting due to connection loss…"
|
||||||
|
Right _ -> pure ()
|
||||||
|
)
|
||||||
|
|
||||||
handleMessages
|
handleMessages
|
||||||
:: Game ()
|
:: Game ()
|
||||||
|
@ -55,7 +63,10 @@ handleMessages = do
|
||||||
queue <- asks rcQueue
|
queue <- asks rcQueue
|
||||||
msgs <- liftIO $ STM.atomically $ STM.flushTQueue queue
|
msgs <- liftIO $ STM.atomically $ STM.flushTQueue queue
|
||||||
mapM_
|
mapM_
|
||||||
handleMessage
|
(\msg -> do
|
||||||
|
liftIO $ print msg
|
||||||
|
handleMessage msg
|
||||||
|
)
|
||||||
msgs
|
msgs
|
||||||
|
|
||||||
handleMessage
|
handleMessage
|
||||||
|
@ -63,21 +74,14 @@ handleMessage
|
||||||
-> Game ()
|
-> Game ()
|
||||||
handleMessage ServerQuit = do
|
handleMessage ServerQuit = do
|
||||||
st <- get
|
st <- get
|
||||||
let stateCont = scClientState st
|
liftIO (gracefulExit st "Quitting due to server shutdown")
|
||||||
liftIO $ STM.atomically $ do
|
|
||||||
stateContainer <- STM.readTMVar stateCont
|
|
||||||
void $ STM.swapTMVar stateCont $ stateContainer
|
|
||||||
{ clientStop = True
|
|
||||||
}
|
|
||||||
put $ st
|
|
||||||
{ scClientState = stateCont
|
|
||||||
}
|
|
||||||
liftIO $ putStrLn "Quitting due to server shutdown"
|
|
||||||
|
|
||||||
handleMessage (Ping id') = do
|
handleMessage (Ping id') = do
|
||||||
cid <- asks rcClientUUID
|
cid <- asks rcClientUUID
|
||||||
sock <- asks rcSocket
|
sock <- asks rcSocket
|
||||||
|
st <- get
|
||||||
liftIO $ sendMessage
|
liftIO $ sendMessage
|
||||||
|
st
|
||||||
( ClientMessage
|
( ClientMessage
|
||||||
cid
|
cid
|
||||||
(Pong id')
|
(Pong id')
|
||||||
|
@ -95,14 +99,34 @@ handleMessage (TickUpdate slice wizard) = do
|
||||||
handleMessage x =
|
handleMessage x =
|
||||||
liftIO $ putStrLn $ "received unexpected message from server: " <> show x
|
liftIO $ putStrLn $ "received unexpected message from server: " <> show x
|
||||||
|
|
||||||
|
-- Gracefully shut down the client with an error message
|
||||||
|
gracefulExit
|
||||||
|
:: StateContainer
|
||||||
|
-> String
|
||||||
|
-> IO ()
|
||||||
|
gracefulExit st reason = do
|
||||||
|
liftIO $ putStrLn reason
|
||||||
|
let stateCont = scClientState st
|
||||||
|
liftIO $ STM.atomically $ do
|
||||||
|
stateContainer <- STM.readTMVar stateCont
|
||||||
|
void $ STM.swapTMVar stateCont $ stateContainer
|
||||||
|
{ clientStop = True
|
||||||
|
}
|
||||||
|
|
||||||
receiveMessage
|
receiveMessage
|
||||||
:: Socket
|
:: Socket
|
||||||
-> STM.TQueue ServerMessage
|
-> STM.TQueue ServerMessage
|
||||||
|
-> StateContainer
|
||||||
-> IO ()
|
-> IO ()
|
||||||
receiveMessage sock queue = do
|
receiveMessage sock queue st = do
|
||||||
let maxBufferLength = 4096
|
let maxBufferLength = 4096
|
||||||
ptr <- mallocArray maxBufferLength
|
ptr <- mallocArray maxBufferLength
|
||||||
bufferLength <- recvBuf sock ptr maxBufferLength
|
ebufferLength <- try $ recvBuf sock ptr maxBufferLength
|
||||||
|
bufferLength <- case ebufferLength of
|
||||||
|
Left (_ :: IOException) -> do
|
||||||
|
gracefulExit st "Quitting due to connection loss"
|
||||||
|
pure 0
|
||||||
|
Right len -> pure len
|
||||||
rawMsg <- B.pack <$> peekArray bufferLength ptr
|
rawMsg <- B.pack <$> peekArray bufferLength ptr
|
||||||
let msgs =
|
let msgs =
|
||||||
if B.length rawMsg < 1
|
if B.length rawMsg < 1
|
||||||
|
@ -125,23 +149,26 @@ terminateGameOnSigint = do
|
||||||
sock <- asks rcSocket
|
sock <- asks rcSocket
|
||||||
clientId <- asks rcClientUUID
|
clientId <- asks rcClientUUID
|
||||||
clientState <- gets scClientState
|
clientState <- gets scClientState
|
||||||
|
st <- get
|
||||||
void $ liftIO $ installHandler
|
void $ liftIO $ installHandler
|
||||||
keyboardSignal
|
keyboardSignal
|
||||||
(CatchOnce $ do
|
(CatchOnce $ do
|
||||||
|
putStrLn "SIGINT caught, terminating…"
|
||||||
STM.atomically $ do
|
STM.atomically $ do
|
||||||
currentState <- STM.readTMVar clientState
|
currentState <- STM.readTMVar clientState
|
||||||
void $ STM.swapTMVar clientState $ currentState { clientStop = True }
|
void $ STM.swapTMVar clientState $ currentState { clientStop = True }
|
||||||
-- Vty.shutdown (clientVty currentState)
|
-- Vty.shutdown (clientVty currentState)
|
||||||
partingMessage clientId sock
|
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
|
||||||
)
|
)
|
||||||
Nothing
|
Nothing
|
||||||
|
|
||||||
partingMessage
|
partingMessage
|
||||||
:: UUID
|
:: StateContainer
|
||||||
|
-> UUID
|
||||||
-> Socket
|
-> Socket
|
||||||
-> IO ()
|
-> IO ()
|
||||||
partingMessage clientId sock = do
|
partingMessage st clientId sock = do
|
||||||
sendMessage (ClientMessage clientId ClientQuit) sock
|
sendMessage st (ClientMessage clientId ClientQuit) sock
|
||||||
-- close sock
|
-- close sock
|
||||||
|
|
|
@ -25,15 +25,16 @@ runGame = do
|
||||||
sock <- asks rcSocket
|
sock <- asks rcSocket
|
||||||
queue <- asks rcQueue
|
queue <- asks rcQueue
|
||||||
clientId <- asks rcClientUUID
|
clientId <- asks rcClientUUID
|
||||||
recvThread <- liftIO $ forkIO $ forever $ receiveMessage sock queue
|
st <- get
|
||||||
liftIO $ sendMessage (ClientMessage clientId ClientReady) sock
|
recvThread <- liftIO $ forkIO $ forever $ receiveMessage sock queue st
|
||||||
|
liftIO $ sendMessage st(ClientMessage clientId ClientReady) sock
|
||||||
whileM_
|
whileM_
|
||||||
(not . clientStop <$> (liftIO . STM.atomically . STM.readTMVar =<< gets scClientState))
|
(not . clientStop <$> (liftIO . STM.atomically . STM.readTMVar =<< gets scClientState))
|
||||||
(do
|
(do
|
||||||
handleMessages
|
handleMessages
|
||||||
-- draw
|
-- draw
|
||||||
)
|
)
|
||||||
liftIO $ killThread recvThread
|
-- liftIO $ killThread recvThread
|
||||||
|
|
||||||
handleEvent
|
handleEvent
|
||||||
:: Maybe Event
|
:: Maybe Event
|
||||||
|
|
|
@ -36,9 +36,11 @@ main = do
|
||||||
queue <- STM.newTQueueIO
|
queue <- STM.newTQueueIO
|
||||||
|
|
||||||
|
|
||||||
sendMessage (IdRequest) sock
|
|
||||||
-- threadDelay $ 1 * 10 ^ 6
|
-- threadDelay $ 1 * 10 ^ 6
|
||||||
receiveMessage sock queue
|
mockClientState <- STM.newTMVarIO (ClientState undefined False False)
|
||||||
|
let mockState = StateContainer undefined mockClientState undefined
|
||||||
|
sendMessage mockState (IdRequest) sock
|
||||||
|
receiveMessage sock queue mockState
|
||||||
awaitResponse queue 1
|
awaitResponse queue 1
|
||||||
clientIdMsg <- head <$> STM.atomically (STM.flushTQueue queue)
|
clientIdMsg <- head <$> STM.atomically (STM.flushTQueue queue)
|
||||||
let clientId = acClientUUID clientIdMsg
|
let clientId = acClientUUID clientIdMsg
|
||||||
|
@ -49,9 +51,9 @@ main = do
|
||||||
threadDelay $ 5 * 10 ^ 6
|
threadDelay $ 5 * 10 ^ 6
|
||||||
|
|
||||||
|
|
||||||
sendMessage (ClientMessage clientId ClientRequestWizard) sock
|
sendMessage mockState (ClientMessage clientId ClientRequestWizard) sock
|
||||||
-- threadDelay $ 1 * 10 ^ 6
|
-- threadDelay $ 1 * 10 ^ 6
|
||||||
receiveMessage sock queue
|
receiveMessage sock queue mockState
|
||||||
awaitResponse queue 1
|
awaitResponse queue 1
|
||||||
playerWizard <- head <$> STM.atomically (STM.flushTQueue queue)
|
playerWizard <- head <$> STM.atomically (STM.flushTQueue queue)
|
||||||
putStrLn $ "received wizard: " <> show (initWizard playerWizard)
|
putStrLn $ "received wizard: " <> show (initWizard playerWizard)
|
||||||
|
@ -77,7 +79,7 @@ main = do
|
||||||
initRead
|
initRead
|
||||||
initState
|
initState
|
||||||
-- shutdown vty
|
-- shutdown vty
|
||||||
partingMessage clientId sock
|
partingMessage initState clientId sock
|
||||||
threadDelay 100
|
threadDelay 100
|
||||||
close sock
|
close sock
|
||||||
where
|
where
|
||||||
|
|
|
@ -70,7 +70,7 @@ main = do
|
||||||
)
|
)
|
||||||
initRead
|
initRead
|
||||||
initState
|
initState
|
||||||
-- removeIfExists setSocketPath
|
removeIfExists setSocketPath
|
||||||
threadDelay 1000
|
threadDelay 1000
|
||||||
putStrLn "bye bye"
|
putStrLn "bye bye"
|
||||||
where
|
where
|
||||||
|
|
|
@ -73,7 +73,7 @@ terminateGameOnSigint path = do
|
||||||
putStrLn "SIGINT caught, terminating…"
|
putStrLn "SIGINT caught, terminating…"
|
||||||
disconnectClients clientList clients
|
disconnectClients clientList clients
|
||||||
close sock
|
close sock
|
||||||
removeIfExists path
|
-- removeIfExists path
|
||||||
void $ STM.atomically $ STM.swapTMVar serverState (ServerState False True)
|
void $ STM.atomically $ STM.swapTMVar serverState (ServerState False True)
|
||||||
)
|
)
|
||||||
Nothing
|
Nothing
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
module Server.Game where
|
module Server.Game where
|
||||||
|
|
||||||
import Control.Concurrent (threadDelay)
|
import Control.Concurrent
|
||||||
|
|
||||||
import qualified Control.Concurrent.STM as STM
|
import qualified Control.Concurrent.STM as STM
|
||||||
|
|
||||||
|
@ -9,8 +9,6 @@ import Control.Monad.RWS.Strict
|
||||||
|
|
||||||
import Control.Monad.Loops
|
import Control.Monad.Loops
|
||||||
|
|
||||||
import Control.Concurrent
|
|
||||||
|
|
||||||
import qualified Data.ByteString.Char8 as B8
|
import qualified Data.ByteString.Char8 as B8
|
||||||
|
|
||||||
import Data.Time
|
import Data.Time
|
||||||
|
@ -53,7 +51,8 @@ runGame = do
|
||||||
when (remainingTime > 0) $
|
when (remainingTime > 0) $
|
||||||
liftIO $ threadDelay $ floor $ remainingTime * 10 ^ 6
|
liftIO $ threadDelay $ floor $ remainingTime * 10 ^ 6
|
||||||
)
|
)
|
||||||
liftIO $ killThread recvThread
|
liftIO $ threadDelay (10 ^ 6)
|
||||||
|
-- liftIO $ killThread recvThread
|
||||||
|
|
||||||
updateSpawners :: Float -> Game ()
|
updateSpawners :: Float -> Game ()
|
||||||
updateSpawners dt =
|
updateSpawners dt =
|
||||||
|
|
Loading…
Reference in a new issue