{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedLabels #-} {-# LANGUAGE StrictData #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} module Octane.Type.Initialization ( Initialization(..) , getInitialization , putInitialization ) where import qualified Control.DeepSeq as DeepSeq import qualified Data.Binary.Bits.Get as BinaryBit import qualified Data.Binary.Bits.Put as BinaryBit import qualified Data.Default.Class as Default import qualified Data.OverloadedRecords.TH as OverloadedRecords import qualified Data.Set as Set import qualified Data.Text as StrictText import qualified GHC.Generics as Generics import qualified Octane.Data as Data import qualified Octane.Type.Int8 as Int8 import qualified Octane.Type.Vector as Vector -- | Information about a new instance of a class. -- -- This cannot be an instance of 'Data.Binary.Bits.BinaryBit' because it -- requires out-of-band information (the class name) to decode. data Initialization = Initialization { initializationLocation :: Maybe (Vector.Vector Int) -- ^ The instance's initial position. , initializationRotation :: Maybe (Vector.Vector Int8.Int8) -- ^ The instance's initial rotation. } deriving (Eq, Generics.Generic, Show) $(OverloadedRecords.overloadedRecord Default.def ''Initialization) instance DeepSeq.NFData Initialization -- | Gets the 'Initialization' for a given class. getInitialization :: StrictText.Text -> BinaryBit.BitGet Initialization getInitialization className = do location <- if Set.member className Data.classesWithLocation then fmap Just Vector.getIntVector else pure Nothing rotation <- if Set.member className Data.classesWithRotation then fmap Just Vector.getInt8Vector else pure Nothing pure Initialization {initializationLocation = location, initializationRotation = rotation} -- | Puts the 'Initialization'. Note that unlike 'getInitialization', this does -- not require the class name. putInitialization :: Initialization -> BinaryBit.BitPut () putInitialization initialization = do case #location initialization of Nothing -> pure () Just x -> Vector.putIntVector x case #rotation initialization of Nothing -> pure () Just x -> Vector.putInt8Vector x