module Rattletrap.Attribute where import Rattletrap.ActorMap import Rattletrap.AttributeValue import Rattletrap.ClassAttributeMap import Rattletrap.Primitive import qualified Data.Binary.Bits.Get as BinaryBit import qualified Data.Binary.Bits.Put as BinaryBit data Attribute = Attribute { attributeId :: CompressedWord , attributeName :: Text -- ^ Read-only! Changing an attribute's name requires editing the class -- attribute map. , attributeValue :: AttributeValue } deriving (Eq, Ord, Show) getAttributes :: (Int, Int) -> ClassAttributeMap -> ActorMap -> CompressedWord -> BinaryBit.BitGet [Attribute] getAttributes version classAttributeMap actorMap actorId = do hasAttribute <- BinaryBit.getBool if not hasAttribute then pure [] else do attribute <- getAttribute version classAttributeMap actorMap actorId attributes <- getAttributes version classAttributeMap actorMap actorId pure (attribute : attributes) putAttributes :: [Attribute] -> BinaryBit.BitPut () putAttributes attributes = do mapM_ putAttribute attributes BinaryBit.putBool False getAttribute :: (Int, Int) -> ClassAttributeMap -> ActorMap -> CompressedWord -> BinaryBit.BitGet Attribute getAttribute version classAttributeMap actorMap actorId = case getAttributeMap classAttributeMap actorMap actorId of Nothing -> fail ("could not get attribute map for " ++ show actorId) Just attributeMap -> case getAttributeIdLimit attributeMap of Nothing -> fail ("could not get attribute ID limit for " ++ show actorId) Just limit -> do id_ <- getCompressedWord limit case getAttributeName classAttributeMap attributeMap id_ of Nothing -> fail ("could not get attribute name for " ++ show id_) Just name -> do value <- getAttributeValue version (classAttributeMapObjectMap classAttributeMap) name pure (Attribute id_ name value) putAttribute :: Attribute -> BinaryBit.BitPut () putAttribute attribute = do BinaryBit.putBool True putCompressedWord (attributeId attribute) putAttributeValue (attributeValue attribute)