module Rattletrap.Decode.Replay ( decodeReplay ) where import Rattletrap.Decode.Common import Rattletrap.Decode.Content import Rattletrap.Decode.Header import Rattletrap.Decode.Section import Rattletrap.Encode.Content import Rattletrap.Type.Content import Rattletrap.Type.Dictionary import Rattletrap.Type.Header import Rattletrap.Type.Int32le import Rattletrap.Type.Property import Rattletrap.Type.PropertyValue import Rattletrap.Type.Replay import Rattletrap.Type.Section import Rattletrap.Type.Str import Rattletrap.Type.Word32le decodeReplay :: Bool -> Decode Replay decodeReplay fast = do header <- decodeSection decodeHeader content <- if fast then pure $ toSection putContent defaultContent else let body = sectionBody header in decodeSection $ decodeContent (getVersion body) (getNumFrames body) (getMaxChannels body) pure $ Replay header content getVersion :: Header -> (Int, Int, Int) getVersion header = ( fromIntegral (word32leValue (headerEngineVersion header)) , fromIntegral (word32leValue (headerLicenseeVersion header)) , getPatchVersion header ) getPatchVersion :: Header -> Int getPatchVersion header = case headerPatchVersion header of Just version -> fromIntegral (word32leValue version) Nothing -> case dictionaryLookup (toStr "MatchType") (headerProperties header) of -- This is an ugly, ugly hack to handle replays from season 2 of RLCS. -- See `decodeSpawnedReplicationBits` and #85. Just Property { propertyValue = PropertyValueName str } | fromStr str == "Lan" -> -1 _ -> 0 getNumFrames :: Header -> Int getNumFrames header = case dictionaryLookup (toStr "NumFrames") (headerProperties header) of Just (Property _ _ (PropertyValueInt numFrames)) -> fromIntegral (int32leValue numFrames) _ -> 0 getMaxChannels :: Header -> Word getMaxChannels header = case dictionaryLookup (toStr "MaxChannels") (headerProperties header) of Just (Property _ _ (PropertyValueInt numFrames)) -> fromIntegral (int32leValue numFrames) _ -> 1023