wizard-wipeout/src-server/Server/Communication/Handler.hs

137 lines
5 KiB
Haskell
Raw Normal View History

2024-05-01 21:52:49 +00:00
module Server.Communication.Handler where
2024-11-03 14:22:28 +00:00
import Control.Concurrent (threadDelay)
2024-05-01 21:52:49 +00:00
import qualified Control.Concurrent.STM as STM
import Control.Monad
import Control.Monad.Reader
import Control.Monad.State
import Data.List
import Data.Maybe
import Data.Time
import Data.UUID.V4
import Library.Types
import Server.Communication.Send
import Server.Types
import Server.Util
-- | function for translating 'ClientMessage's into server actions
handleMessage
:: StateContainer
-> ReaderContainer
-> ClientMessage
-> IO ()
handleMessage stateContainer readerContainer msg = do
2024-11-03 10:19:19 +00:00
let socketList = scClientSockets stateContainer
queueList = scClientQueues stateContainer
socks <- liftIO $ STM.atomically $ STM.readTMVar socketList
queues <- liftIO $ STM.atomically $ STM.readTMVar queueList
2024-05-01 21:52:49 +00:00
-- putStrLn $ "Handling: " <> show msg
case msg of
IdRequest -> do
clientId <- nextRandom
2024-11-03 14:22:28 +00:00
threadDelay 1000
2024-11-03 10:19:19 +00:00
let clientIdx = findIndex (isNothing . csUUID) socks
sock = socks !! fromJust clientIdx
queue = queues !! fromJust clientIdx
if csUUID sock == cqUUID queue
then do
let otherSocks = delete sock socks
newSocks = sock
{ csUUID = Just clientId
} : otherSocks
otherQueues = delete queue queues
newQueues = queue
{ cqUUID = Just clientId
} : otherQueues
liftIO $ STM.atomically $ do
void $ STM.swapTMVar socketList newSocks
void $ STM.swapTMVar queueList newQueues
putStrLn $ "Accepted Client with UUID: " <> show clientId
2024-11-03 10:51:13 +00:00
queueMessage (AcceptClient clientId) clientId queueList
2024-11-03 10:19:19 +00:00
else
2024-11-03 14:22:28 +00:00
putStrLn $ "Unable to assign ID to socket and queue: " <> show clientId
2024-05-01 21:52:49 +00:00
ClientMessage clientId payload ->
case payload of
ClientQuit -> do
putStrLn $ "client has quit the game: " <> show clientId
2024-11-03 15:21:03 +00:00
currentPlayers <- STM.atomically $ STM.readTMVar (scPlayers stateContainer)
let newPlayers = filter (\p -> playerId p /= clientId) currentPlayers
void $ STM.atomically $ STM.swapTMVar (scPlayers stateContainer) newPlayers
2024-11-03 10:19:19 +00:00
let client = find (\a -> csUUID a == Just clientId) socks
2024-11-03 14:22:28 +00:00
dropClient socketList queueList (csSocket $ fromJust client)
2024-05-01 21:52:49 +00:00
ClientRequestWizard -> do
putStrLn "initializing new wizard"
let arena = rcMap readerContainer
initPos <- rollInitPosition arena
now <- liftIO getCurrentTime
uuid <- nextRandom
let freshWizard = newWizard initPos
STM.atomically $ do
currentPlayers <- STM.readTMVar (scPlayers stateContainer)
void $ STM.swapTMVar (scPlayers stateContainer) $
Player clientId freshWizard False (now, uuid) : currentPlayers
2024-11-03 10:51:13 +00:00
queueMessage (ProvideInitialWizard freshWizard) clientId queueList
2024-05-01 21:52:49 +00:00
ClientReady -> do
now <- getCurrentTime
STM.atomically $ do
currentPlayers <- STM.readTMVar (scPlayers stateContainer)
let (thisPlayers, otherPlayers) =
partition (\p -> playerId p == clientId) currentPlayers
unless (null thisPlayers) $
void $ STM.swapTMVar (scPlayers stateContainer) $
(head thisPlayers)
{ playerReady = True
, playerLastPong = (now, snd (playerLastPong $ head thisPlayers))
}
: otherPlayers
2024-11-03 03:40:46 +00:00
putStrLn $ "client ready: " <> show clientId
Pong pongUuid -> do
2024-11-03 10:19:19 +00:00
let mclient = find (\c -> csUUID c == Just clientId) socks
2024-11-03 03:40:46 +00:00
players <- STM.atomically $ STM.readTMVar (scPlayers stateContainer)
2024-05-01 21:52:49 +00:00
maybe
2024-11-03 03:40:46 +00:00
(putStrLn $ "Unknown client: " <> show clientId)
(const $ do
2024-05-01 21:52:49 +00:00
mPlayer <- STM.atomically $ do
pure $ find (\p -> playerId p == clientId) players
maybe
(pure ())
(\player ->
2024-11-03 03:40:46 +00:00
if snd (playerLastPong player) /= pongUuid
2024-05-01 21:52:49 +00:00
then
2024-11-03 03:40:46 +00:00
putStrLn $ "Pong ID mismatch from: " <> show clientId
2024-05-01 21:52:49 +00:00
else do
now <- getCurrentTime
STM.atomically$ do
let otherPlayers = filter (\a -> playerId a /= playerId player) players
modPlayer = player
2024-11-03 03:40:46 +00:00
{ playerLastPong = (now, pongUuid)
2024-05-01 21:52:49 +00:00
}
void $ STM.swapTMVar (scPlayers stateContainer) (modPlayer : otherPlayers)
2024-06-09 05:32:03 +00:00
sendUpdate stateContainer (rcMap readerContainer) player
2024-05-01 21:52:49 +00:00
)
mPlayer
)
mclient
-- | handle received messages
handleMessages :: Game ()
handleMessages = do
queue <- gets scMessageQueue
serverState <- get
readerContainer <- ask
liftIO $ do
2024-10-31 18:19:13 +00:00
msgs <- STM.atomically $
STM.flushTQueue queue
2024-10-31 20:01:53 +00:00
mapM_
(handleMessage serverState readerContainer)
msgs