restructure of library and introducing channels to client
This commit is contained in:
parent
6db9d877aa
commit
afa21eaece
6 changed files with 127 additions and 54 deletions
|
@ -1,6 +1,8 @@
|
||||||
{-# LANGUAGE LambdaCase #-}
|
{-# LANGUAGE LambdaCase #-}
|
||||||
module Client.Communication where
|
module Client.Communication where
|
||||||
|
|
||||||
|
import qualified Control.Concurrent.STM as STM
|
||||||
|
|
||||||
import Control.Monad (void)
|
import Control.Monad (void)
|
||||||
|
|
||||||
import qualified Data.Aeson as A
|
import qualified Data.Aeson as A
|
||||||
|
@ -8,6 +10,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.Maybe (fromJust)
|
||||||
|
|
||||||
import qualified Data.Vector.Storable as VS
|
import qualified Data.Vector.Storable as VS
|
||||||
|
|
||||||
import Foreign hiding (void)
|
import Foreign hiding (void)
|
||||||
|
@ -41,16 +45,15 @@ sendMessage msg sock = do
|
||||||
|
|
||||||
receiveMessage
|
receiveMessage
|
||||||
:: Socket
|
:: Socket
|
||||||
-> IO ServerMessage
|
-> STM.TQueue ServerMessage
|
||||||
receiveMessage sock = do
|
-> IO ()
|
||||||
|
receiveMessage sock queue = do
|
||||||
let maxBufferLength = 4096
|
let maxBufferLength = 4096
|
||||||
ptr <- mallocArray maxBufferLength
|
ptr <- mallocArray maxBufferLength
|
||||||
bufferLength <- recvBuf sock ptr maxBufferLength
|
bufferLength <- recvBuf sock ptr maxBufferLength
|
||||||
msg <- B.pack <$> peekArray bufferLength ptr
|
msg <- B.pack <$> peekArray bufferLength ptr
|
||||||
let mJsonMsg = A.decode' $ B8.fromStrict msg
|
let mJsonMsg = A.decode' $ B8.fromStrict msg
|
||||||
jsonMsg <- maybe
|
maybe
|
||||||
(error $ "unexpected message from Server: " <> show msg)
|
(pure ())
|
||||||
pure
|
(STM.atomically . STM.writeTQueue queue)
|
||||||
mJsonMsg
|
mJsonMsg
|
||||||
free ptr
|
|
||||||
pure jsonMsg
|
|
||||||
|
|
|
@ -3,6 +3,8 @@ module Main where
|
||||||
|
|
||||||
import Control.Concurrent (threadDelay)
|
import Control.Concurrent (threadDelay)
|
||||||
|
|
||||||
|
import qualified Control.Concurrent.STM as STM
|
||||||
|
|
||||||
import Options.Applicative
|
import Options.Applicative
|
||||||
|
|
||||||
-- internal imports
|
-- internal imports
|
||||||
|
@ -18,17 +20,24 @@ main = do
|
||||||
(Options socketLocation) <- execParser opts
|
(Options socketLocation) <- execParser opts
|
||||||
putStrLn $ "connecting to Socket " <> socketLocation
|
putStrLn $ "connecting to Socket " <> socketLocation
|
||||||
sock <- connectSocket socketLocation
|
sock <- connectSocket socketLocation
|
||||||
|
queue <- STM.newTQueueIO
|
||||||
putStrLn "connected"
|
putStrLn "connected"
|
||||||
sendMessage (IdRequest) sock
|
sendMessage (IdRequest) sock
|
||||||
threadDelay $ 5 * 10 ^ 6
|
threadDelay $ 1 * 10 ^ 6
|
||||||
clientIdMsg <- receiveMessage sock
|
receiveMessage sock queue
|
||||||
|
threadDelay $ 1 * 10 ^ 6
|
||||||
|
clientIdMsg <- head <$> STM.atomically (STM.flushTQueue queue)
|
||||||
let clientId = acClientUUID clientIdMsg
|
let clientId = acClientUUID clientIdMsg
|
||||||
putStrLn $ "received client UUID: " <> show clientId
|
putStrLn $ "received client UUID: " <> show clientId
|
||||||
threadDelay $ 5 * 10 ^ 6
|
threadDelay $ 1 * 10 ^ 6
|
||||||
putStrLn welcomeText
|
putStrLn welcomeText
|
||||||
threadDelay $ 15 * 10 ^ 6
|
threadDelay $ 15 * 10 ^ 6
|
||||||
|
putStrLn welcomeText
|
||||||
sendMessage (ClientMessage clientId ClientRequestWizard) sock
|
sendMessage (ClientMessage clientId ClientRequestWizard) sock
|
||||||
playerWizard <- receiveMessage sock
|
threadDelay $ 1 * 10 ^ 6
|
||||||
|
receiveMessage sock queue
|
||||||
|
threadDelay $ 1 * 10 ^ 6
|
||||||
|
playerWizard <- head <$> STM.atomically (STM.flushTQueue queue)
|
||||||
putStrLn "received wizard"
|
putStrLn "received wizard"
|
||||||
print (initWizard playerWizard)
|
print (initWizard playerWizard)
|
||||||
let initRead = ReaderContainer sock clientId
|
let initRead = ReaderContainer sock clientId
|
||||||
|
@ -50,7 +59,7 @@ welcomeText = mconcat $ map (<> "\n")
|
||||||
, ""
|
, ""
|
||||||
, "Some last hints before you enter the fighting grounds:"
|
, "Some last hints before you enter the fighting grounds:"
|
||||||
, ""
|
, ""
|
||||||
, "press [SpACE] to fire your wand"
|
, "press [SPACE] to fire your wand"
|
||||||
, "press [1] through [9] to change wands, if you have collected more wands"
|
, "press [1] through [9] to change wands, if you have collected more wands"
|
||||||
, "press [ESC] to leave"
|
, "press [ESC] to leave"
|
||||||
, ""
|
, ""
|
||||||
|
|
|
@ -1,48 +1,7 @@
|
||||||
module Library.Types
|
module Library.Types
|
||||||
( module T
|
( module T
|
||||||
, module Library.Types
|
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Data.Matrix
|
|
||||||
import Graphics.Vty
|
|
||||||
|
|
||||||
import Library.Types.Communication as T
|
import Library.Types.Communication as T
|
||||||
import Library.Types.Player as T
|
import Library.Types.Player as T
|
||||||
|
import Library.Types.Map as T
|
||||||
-- | Data object for storing the client's state
|
|
||||||
data ClientState = ClientState
|
|
||||||
{ clientVty :: Vty -- ^ Context object for graphics
|
|
||||||
, clientGameOver :: Bool -- ^ client game over (contestant died)
|
|
||||||
, clientStop :: Bool -- ^ client shutdown
|
|
||||||
}
|
|
||||||
|
|
||||||
-- | Type synonym for the Map. Translates to a Matrix of 'Tile's
|
|
||||||
type ServerMap = Matrix Tile
|
|
||||||
|
|
||||||
-- | Type synonym for the Map. Translates to a Matrix of 'Maybe Tile's
|
|
||||||
type ClientMap = Matrix (Maybe Tile)
|
|
||||||
|
|
||||||
data Tile
|
|
||||||
= Air -- ^ walkable area
|
|
||||||
| Wall -- ^ obstacle
|
|
||||||
deriving (Show, Eq)
|
|
||||||
|
|
||||||
data Arena = Arena
|
|
||||||
{ arenaMap :: ServerMap
|
|
||||||
, arenaSpawners :: [Spawner]
|
|
||||||
}
|
|
||||||
deriving (Show, Eq)
|
|
||||||
|
|
||||||
data Spawner = Spawner
|
|
||||||
{ spawnerPowerup :: Wand -- ^ Which 'Powerup' is being spawned
|
|
||||||
, spawnerReloadTime :: Int -- ^ How long does it take for the 'Powerup' to reappear
|
|
||||||
, spawnerState :: SpawnerState
|
|
||||||
, spawnerReloadTTL :: Float
|
|
||||||
, spawnerPosition :: Position -- ^ Position of the `Spawner` on the map
|
|
||||||
}
|
|
||||||
deriving (Show, Eq)
|
|
||||||
|
|
||||||
data SpawnerState
|
|
||||||
= SpawnerFull
|
|
||||||
| SpawnerEmpty
|
|
||||||
deriving (Eq, Show)
|
|
||||||
|
|
|
@ -19,6 +19,10 @@ data ServerMessage
|
||||||
| ProvideInitialWizard
|
| ProvideInitialWizard
|
||||||
{ initWizard :: Wizard
|
{ initWizard :: Wizard
|
||||||
}
|
}
|
||||||
|
| TickUpdate
|
||||||
|
{ tuMapSlice :: MapSlice
|
||||||
|
, tuWizard :: Wizard
|
||||||
|
}
|
||||||
deriving (Eq, Show, Generic)
|
deriving (Eq, Show, Generic)
|
||||||
|
|
||||||
instance FromJSON ServerMessage
|
instance FromJSON ServerMessage
|
||||||
|
|
96
src-lib/Library/Types/Map.hs
Normal file
96
src-lib/Library/Types/Map.hs
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
{-# LANGUAGE DeriveGeneric #-}
|
||||||
|
module Library.Types.Map where
|
||||||
|
|
||||||
|
import Data.Matrix
|
||||||
|
|
||||||
|
import GHC.Generics
|
||||||
|
|
||||||
|
import Graphics.Vty
|
||||||
|
|
||||||
|
-- internal imports
|
||||||
|
|
||||||
|
import Library.Types.Player
|
||||||
|
import Data.Aeson (ToJSON, FromJSON)
|
||||||
|
|
||||||
|
-- | Data object for storing the client's state
|
||||||
|
data ClientState = ClientState
|
||||||
|
{ clientVty :: Vty -- ^ Context object for graphics
|
||||||
|
, clientGameOver :: Bool -- ^ client game over (contestant died)
|
||||||
|
, clientStop :: Bool -- ^ client shutdown
|
||||||
|
}
|
||||||
|
|
||||||
|
-- | Type synonym for the Map. Translates to a Matrix of 'Tile's
|
||||||
|
type ServerMap = Matrix Tile
|
||||||
|
|
||||||
|
-- | Type synonym for the Map. Translates to a Matrix of 'Maybe Tile's
|
||||||
|
type ClientMap = Matrix (Maybe Tile)
|
||||||
|
|
||||||
|
instance ToJSON ClientMap
|
||||||
|
|
||||||
|
instance FromJSON ClientMap
|
||||||
|
|
||||||
|
data Tile
|
||||||
|
= Air -- ^ walkable area
|
||||||
|
| Wall -- ^ obstacle
|
||||||
|
deriving (Show, Eq, Generic)
|
||||||
|
|
||||||
|
instance ToJSON Tile
|
||||||
|
|
||||||
|
instance FromJSON Tile
|
||||||
|
|
||||||
|
data Arena = Arena
|
||||||
|
{ arenaMap :: ServerMap
|
||||||
|
, arenaSpawners :: [Spawner]
|
||||||
|
}
|
||||||
|
deriving (Show, Eq)
|
||||||
|
|
||||||
|
data Spawner = Spawner
|
||||||
|
{ spawnerPowerup :: Wand -- ^ Which 'Powerup' is being spawned
|
||||||
|
, spawnerReloadTime :: Int -- ^ How long does it take for the 'Powerup' to reappear
|
||||||
|
, spawnerState :: SpawnerState
|
||||||
|
, spawnerReloadTTL :: Float
|
||||||
|
, spawnerPosition :: Position -- ^ Position of the `Spawner` on the map
|
||||||
|
}
|
||||||
|
deriving (Show, Eq)
|
||||||
|
|
||||||
|
data SpawnerState
|
||||||
|
= SpawnerFull
|
||||||
|
| SpawnerEmpty
|
||||||
|
deriving (Eq, Show)
|
||||||
|
|
||||||
|
data MapSlice = MapSlice
|
||||||
|
{ msViewMap :: ClientMap
|
||||||
|
, msViewOffset :: Position
|
||||||
|
, msContents :: [Effigy]
|
||||||
|
}
|
||||||
|
deriving (Eq, Show, Generic)
|
||||||
|
|
||||||
|
instance ToJSON MapSlice
|
||||||
|
|
||||||
|
instance FromJSON MapSlice
|
||||||
|
|
||||||
|
data Effigy = Effigy
|
||||||
|
{ effPosition :: Position
|
||||||
|
, effType :: EffigyType
|
||||||
|
}
|
||||||
|
deriving (Eq, Show, Generic)
|
||||||
|
|
||||||
|
instance ToJSON Effigy
|
||||||
|
|
||||||
|
instance FromJSON Effigy
|
||||||
|
|
||||||
|
data EffigyType
|
||||||
|
= EffZap
|
||||||
|
| EffBigZap
|
||||||
|
| EffFire
|
||||||
|
| EffIce
|
||||||
|
| EffBigWand
|
||||||
|
| EffFireWand
|
||||||
|
| EffIceWand
|
||||||
|
| EffWizard
|
||||||
|
| EffCorpse
|
||||||
|
deriving (Eq, Show, Generic)
|
||||||
|
|
||||||
|
instance ToJSON EffigyType
|
||||||
|
|
||||||
|
instance FromJSON EffigyType
|
|
@ -20,6 +20,7 @@ library
|
||||||
import: warnings
|
import: warnings
|
||||||
exposed-modules: Library.Types
|
exposed-modules: Library.Types
|
||||||
Library.Types.Communication
|
Library.Types.Communication
|
||||||
|
Library.Types.Map
|
||||||
Library.Types.Player
|
Library.Types.Player
|
||||||
build-depends: base ^>=4.17.2.1
|
build-depends: base ^>=4.17.2.1
|
||||||
, aeson
|
, aeson
|
||||||
|
@ -44,6 +45,7 @@ executable wizard-wipeout-client
|
||||||
, mtl
|
, mtl
|
||||||
, network
|
, network
|
||||||
, optparse-applicative
|
, optparse-applicative
|
||||||
|
, stm
|
||||||
, uuid
|
, uuid
|
||||||
, vector
|
, vector
|
||||||
, vty
|
, vty
|
||||||
|
|
Loading…
Reference in a new issue