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 FullReplay
decodeReplay :: Bool -> Decode FullReplay
decodeReplay Bool
fast = do
  Section Header
header <- Decode Header -> Decode (Section Header)
forall a. Decode a -> Decode (Section a)
decodeSection Decode Header
decodeHeader
  Section Content
content <- if Bool
fast
    then Section Content -> Get (Section Content)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Section Content -> Get (Section Content))
-> Section Content -> Get (Section Content)
forall a b. (a -> b) -> a -> b
$ (Content -> Put) -> Content -> Section Content
forall a. (a -> Put) -> a -> Section a
toSection Content -> Put
putContent Content
defaultContent
    else
      let body :: Header
body = Section Header -> Header
forall a. Section a -> a
sectionBody Section Header
header
      in
        Decode Content -> Get (Section Content)
forall a. Decode a -> Decode (Section a)
decodeSection (Decode Content -> Get (Section Content))
-> Decode Content -> Get (Section Content)
forall a b. (a -> b) -> a -> b
$ (Int, Int, Int) -> Int -> Word -> Decode Content
decodeContent
          (Header -> (Int, Int, Int)
getVersion Header
body)
          (Header -> Int
getNumFrames Header
body)
          (Header -> Word
getMaxChannels Header
body)
  FullReplay -> Decode FullReplay
forall (f :: * -> *) a. Applicative f => a -> f a
pure (FullReplay -> Decode FullReplay)
-> FullReplay -> Decode FullReplay
forall a b. (a -> b) -> a -> b
$ Section Header -> Section Content -> FullReplay
forall content. Section Header -> Section content -> Replay content
Replay Section Header
header Section Content
content

getVersion :: Header -> (Int, Int, Int)
getVersion :: Header -> (Int, Int, Int)
getVersion Header
header =
  ( Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32le -> Word32
word32leValue (Header -> Word32le
headerEngineVersion Header
header))
  , Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32le -> Word32
word32leValue (Header -> Word32le
headerLicenseeVersion Header
header))
  , Header -> Int
getPatchVersion Header
header
  )

getPatchVersion :: Header -> Int
getPatchVersion :: Header -> Int
getPatchVersion Header
header = case Header -> Maybe Word32le
headerPatchVersion Header
header of
  Just Word32le
version -> Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32le -> Word32
word32leValue Word32le
version)
  Maybe Word32le
Nothing ->
    case Str -> Dictionary Property -> Maybe Property
forall a. Str -> Dictionary a -> Maybe a
dictionaryLookup (String -> Str
toStr String
"MatchType") (Header -> Dictionary Property
headerProperties Header
header) of
      -- This is an ugly, ugly hack to handle replays from season 2 of RLCS.
      -- See `decodeSpawnedReplicationBits` and #85.
      Just Property { propertyValue :: Property -> PropertyValue Property
propertyValue = PropertyValueName Str
str }
        | Str -> String
fromStr Str
str String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"Lan" -> -Int
1
      Maybe Property
_ -> Int
0

getNumFrames :: Header -> Int
getNumFrames :: Header -> Int
getNumFrames Header
header =
  case Str -> Dictionary Property -> Maybe Property
forall a. Str -> Dictionary a -> Maybe a
dictionaryLookup (String -> Str
toStr String
"NumFrames") (Header -> Dictionary Property
headerProperties Header
header) of
    Just (Property Str
_ Word64le
_ (PropertyValueInt Int32le
numFrames)) ->
      Int32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int32le -> Int32
int32leValue Int32le
numFrames)
    Maybe Property
_ -> Int
0

getMaxChannels :: Header -> Word
getMaxChannels :: Header -> Word
getMaxChannels Header
header =
  case Str -> Dictionary Property -> Maybe Property
forall a. Str -> Dictionary a -> Maybe a
dictionaryLookup (String -> Str
toStr String
"MaxChannels") (Header -> Dictionary Property
headerProperties Header
header) of
    Just (Property Str
_ Word64le
_ (PropertyValueInt Int32le
numFrames)) ->
      Int32 -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int32le -> Int32
int32leValue Int32le
numFrames)
    Maybe Property
_ -> Word
1023