diff --git a/LICENSE.markdown b/LICENSE.markdown
--- a/LICENSE.markdown
+++ b/LICENSE.markdown
@@ -1,6 +1,6 @@
 MIT License
 
-Copyright (c) 2022 Taylor Fausak
+Copyright (c) 2023 Taylor Fausak
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/README.markdown b/README.markdown
--- a/README.markdown
+++ b/README.markdown
@@ -1,8 +1,8 @@
 # [Rattletrap][]
 
-[![Version badge][]][version]
-[![Build badge][]][build]
-[![Docker badge][]][docker]
+[![Workflow](https://github.com/tfausak/rattletrap/actions/workflows/workflow.yaml/badge.svg)](https://github.com/tfausak/rattletrap/actions/workflows/workflow.yaml)
+[![Hackage](https://img.shields.io/hackage/v/rattletrap)](https://hackage.haskell.org/package/rattletrap)
+[![Stackage](https://www.stackage.org/package/rattletrap/badge/nightly?label=stackage)](https://www.stackage.org/package/rattletrap)
 
 Rattletrap parses and generates [Rocket League][] replays. Parsing replays can
 be used to analyze data in order to collect high-level statistics like players
@@ -21,10 +21,10 @@
 using another tool like [Ball Chasing][].
 
 The best way to get Rattletrap is by downloading [the latest release][] for
-your platform. Rattletrap is also available as [a Docker image][docker].
+your platform.
 
 Rattletrap is written in [Haskell][]. To build Rattletrap from source, install
-[Stack][]. Then run `stack --resolver nightly-2021-08-14 install rattletrap`.
+[Stack][]. Then run `stack --resolver nightly-2023-02-12 install rattletrap`.
 If you'd like to use a program written in a different language, consider one of
 the following:
 
@@ -56,7 +56,7 @@
 ```
 
 ```
-rattletrap version 11.2.0
+rattletrap version 12.0.0
   -c           --compact         minify JSON output
   -f           --fast            only encode or decode the header
   -h           --help            show the help
@@ -133,8 +133,6 @@
 [version]: https://hackage.haskell.org/package/rattletrap
 [Build badge]: https://github.com/tfausak/rattletrap/workflows/ci/badge.svg
 [build]: https://github.com/tfausak/rattletrap/actions
-[Docker badge]: https://img.shields.io/docker/v/taylorfausak/rattletrap?label=docker&logo=docker&logoColor=white
-[docker]: https://hub.docker.com/r/taylorfausak/rattletrap
 [Rocket League]: https://www.rocketleague.com
 [2.23]: https://www.rocketleague.com/news/patch-notes-v2-23/
 [Ball Chasing]: https://ballchasing.com
diff --git a/rattletrap.cabal b/rattletrap.cabal
--- a/rattletrap.cabal
+++ b/rattletrap.cabal
@@ -1,7 +1,7 @@
 cabal-version: 2.2
 
 name: rattletrap
-version: 12.0.0
+version: 12.0.1
 synopsis: Parse and generate Rocket League replays.
 description: Rattletrap parses and generates Rocket League replays.
 
@@ -18,6 +18,7 @@
 
 flag pedantic
   default: False
+  description: Enables @-Werror@, which turns warnings into errors.
   manual: True
 
 common library
@@ -58,7 +59,7 @@
     , aeson ^>= 2.0.3 || ^>= 2.1.0
     , aeson-pretty ^>= 0.8.9
     , array ^>= 0.5.4
-    , bytestring >= 0.10 && < 0.12
+    , bytestring >= 0.10.12 && < 0.12
     , containers >= 0.6 && < 0.7
     , filepath ^>= 1.4.2
     , http-client ^>= 0.7.11
@@ -212,7 +213,7 @@
   hs-source-dirs: src/exe
   main-is: Main.hs
 
-test-suite test
+test-suite rattletrap-test-suite
   import: executable
 
   build-depends: bytestring, filepath
diff --git a/src/lib/Rattletrap.hs b/src/lib/Rattletrap.hs
--- a/src/lib/Rattletrap.hs
+++ b/src/lib/Rattletrap.hs
@@ -1,11 +1,12 @@
 module Rattletrap
-  ( Rattletrap.Console.Main.main
-  , Rattletrap.Console.Main.rattletrap
-  , Rattletrap.Utility.Helper.decodeReplayFile
-  , Rattletrap.Utility.Helper.encodeReplayJson
-  , Rattletrap.Utility.Helper.decodeReplayJson
-  , Rattletrap.Utility.Helper.encodeReplayFile
-  ) where
+  ( Rattletrap.Console.Main.main,
+    Rattletrap.Console.Main.rattletrap,
+    Rattletrap.Utility.Helper.decodeReplayFile,
+    Rattletrap.Utility.Helper.encodeReplayJson,
+    Rattletrap.Utility.Helper.decodeReplayJson,
+    Rattletrap.Utility.Helper.encodeReplayFile,
+  )
+where
 
 import qualified Rattletrap.Console.Main
 import qualified Rattletrap.Utility.Helper
diff --git a/src/lib/Rattletrap/BitBuilder.hs b/src/lib/Rattletrap/BitBuilder.hs
--- a/src/lib/Rattletrap/BitBuilder.hs
+++ b/src/lib/Rattletrap/BitBuilder.hs
@@ -8,25 +8,25 @@
 import qualified Data.Word as Word
 
 data BitBuilder = BitBuilder
-  { buffer :: Word.Word8
-  , builder :: Builder.Builder
-  , offset :: Int
+  { buffer :: Word.Word8,
+    builder :: Builder.Builder,
+    offset :: Int
   }
 
 empty :: BitBuilder
-empty = BitBuilder { buffer = 0x00, builder = mempty, offset = 0 }
+empty = BitBuilder {buffer = 0x00, builder = mempty, offset = 0}
 
 push :: Bool -> BitBuilder -> BitBuilder
 push b x =
   let !newBuffer = if b then Bits.setBit (buffer x) (offset x) else buffer x
-  in
-    if offset x == 7
-      then BitBuilder
-        { buffer = 0x00
-        , builder = builder x <> Builder.word8 newBuffer
-        , offset = 0
-        }
-      else x { buffer = newBuffer, offset = offset x + 1 }
+   in if offset x == 7
+        then
+          BitBuilder
+            { buffer = 0x00,
+              builder = builder x <> Builder.word8 newBuffer,
+              offset = 0
+            }
+        else x {buffer = newBuffer, offset = offset x + 1}
 
 toBuilder :: BitBuilder -> Builder.Builder
 toBuilder x =
diff --git a/src/lib/Rattletrap/BitGet.hs b/src/lib/Rattletrap/BitGet.hs
--- a/src/lib/Rattletrap/BitGet.hs
+++ b/src/lib/Rattletrap/BitGet.hs
@@ -26,11 +26,10 @@
   x <- byteString n
   Get.embed f x
 
-bits :: Bits.Bits a => Int -> BitGet a
+bits :: (Bits.Bits a) => Int -> BitGet a
 bits n = do
-  let
-    f :: Bits.Bits a => Bool -> a -> a
-    f bit x = let y = Bits.shiftL x 1 in if bit then Bits.setBit y 0 else y
+  let f :: (Bits.Bits a) => Bool -> a -> a
+      f bit x = let y = Bits.shiftL x 1 in if bit then Bits.setBit y 0 else y
   xs <- Monad.replicateM n bool
   pure $ foldr f Bits.zeroBits xs
 
@@ -46,7 +45,7 @@
 byteString :: Int -> BitGet ByteString.ByteString
 byteString n = fmap ByteString.pack . Monad.replicateM n $ bits 8
 
-throw :: Exception.Exception e => e -> BitGet a
+throw :: (Exception.Exception e) => e -> BitGet a
 throw = Get.throw
 
 label :: String -> BitGet a -> BitGet a
diff --git a/src/lib/Rattletrap/BitPut.hs b/src/lib/Rattletrap/BitPut.hs
--- a/src/lib/Rattletrap/BitPut.hs
+++ b/src/lib/Rattletrap/BitPut.hs
@@ -22,7 +22,7 @@
 fromBytePut :: BytePut.BytePut -> BitPut
 fromBytePut = byteString . BytePut.toByteString
 
-bits :: Bits.Bits a => Int -> a -> BitPut
+bits :: (Bits.Bits a) => Int -> a -> BitPut
 bits n x = foldMap (bool . Bits.testBit x) [0 .. n - 1]
 
 bool :: Bool -> BitPut
diff --git a/src/lib/Rattletrap/BitString.hs b/src/lib/Rattletrap/BitString.hs
--- a/src/lib/Rattletrap/BitString.hs
+++ b/src/lib/Rattletrap/BitString.hs
@@ -4,20 +4,20 @@
 import qualified Data.ByteString as ByteString
 
 data BitString = BitString
-  { byteString :: ByteString.ByteString
-  , offset :: Int
+  { byteString :: ByteString.ByteString,
+    offset :: Int
   }
   deriving (Eq, Show)
 
 fromByteString :: ByteString.ByteString -> BitString
-fromByteString byteString = BitString { byteString, offset = 0 }
+fromByteString byteString = BitString {byteString, offset = 0}
 
 pop :: BitString -> Maybe (Bool, BitString)
 pop old = do
   (word, byteString) <- ByteString.uncons $ byteString old
-  let
-    bit = Bits.testBit word $ offset old
-    new = if offset old == 7
-      then fromByteString byteString
-      else old { offset = offset old + 1 }
+  let bit = Bits.testBit word $ offset old
+      new =
+        if offset old == 7
+          then fromByteString byteString
+          else old {offset = offset old + 1}
   pure (bit, new)
diff --git a/src/lib/Rattletrap/ByteGet.hs b/src/lib/Rattletrap/ByteGet.hs
--- a/src/lib/Rattletrap/ByteGet.hs
+++ b/src/lib/Rattletrap/ByteGet.hs
@@ -13,10 +13,10 @@
 
 type ByteGet = Get.Get ByteString.ByteString Identity.Identity
 
-run
-  :: ByteGet a
-  -> ByteString.ByteString
-  -> Either ([String], Exception.SomeException) a
+run ::
+  ByteGet a ->
+  ByteString.ByteString ->
+  Either ([String], Exception.SomeException) a
 run g = fmap snd . Identity.runIdentity . Get.run g
 
 byteString :: Int -> ByteGet ByteString.ByteString
@@ -53,26 +53,26 @@
 word32 :: ByteGet Word.Word32
 word32 = do
   x <- byteString 4
-  pure
-    $ Bits.shiftL (fromIntegral $ ByteString.index x 0) 0
-    + Bits.shiftL (fromIntegral $ ByteString.index x 1) 8
-    + Bits.shiftL (fromIntegral $ ByteString.index x 2) 16
-    + Bits.shiftL (fromIntegral $ ByteString.index x 3) 24
+  pure $
+    Bits.shiftL (fromIntegral $ ByteString.index x 0) 0
+      + Bits.shiftL (fromIntegral $ ByteString.index x 1) 8
+      + Bits.shiftL (fromIntegral $ ByteString.index x 2) 16
+      + Bits.shiftL (fromIntegral $ ByteString.index x 3) 24
 
 word64 :: ByteGet Word.Word64
 word64 = do
   x <- byteString 8
-  pure
-    $ Bits.shiftL (fromIntegral $ ByteString.index x 0) 0
-    + Bits.shiftL (fromIntegral $ ByteString.index x 1) 8
-    + Bits.shiftL (fromIntegral $ ByteString.index x 2) 16
-    + Bits.shiftL (fromIntegral $ ByteString.index x 3) 24
-    + Bits.shiftL (fromIntegral $ ByteString.index x 4) 32
-    + Bits.shiftL (fromIntegral $ ByteString.index x 5) 40
-    + Bits.shiftL (fromIntegral $ ByteString.index x 6) 48
-    + Bits.shiftL (fromIntegral $ ByteString.index x 7) 56
+  pure $
+    Bits.shiftL (fromIntegral $ ByteString.index x 0) 0
+      + Bits.shiftL (fromIntegral $ ByteString.index x 1) 8
+      + Bits.shiftL (fromIntegral $ ByteString.index x 2) 16
+      + Bits.shiftL (fromIntegral $ ByteString.index x 3) 24
+      + Bits.shiftL (fromIntegral $ ByteString.index x 4) 32
+      + Bits.shiftL (fromIntegral $ ByteString.index x 5) 40
+      + Bits.shiftL (fromIntegral $ ByteString.index x 6) 48
+      + Bits.shiftL (fromIntegral $ ByteString.index x 7) 56
 
-throw :: Exception.Exception e => e -> ByteGet a
+throw :: (Exception.Exception e) => e -> ByteGet a
 throw = Get.throw
 
 embed :: ByteGet a -> ByteString.ByteString -> ByteGet a
diff --git a/src/lib/Rattletrap/Console/Config.hs b/src/lib/Rattletrap/Console/Config.hs
--- a/src/lib/Rattletrap/Console/Config.hs
+++ b/src/lib/Rattletrap/Console/Config.hs
@@ -5,53 +5,53 @@
 import qualified System.FilePath as FilePath
 
 data Config = Config
-  { compact :: Bool
-  , fast :: Bool
-  , help :: Bool
-  , input :: Maybe String
-  , mode :: Maybe Mode.Mode
-  , output :: Maybe String
-  , schema :: Bool
-  , skipCrc :: Bool
-  , version :: Bool
+  { compact :: Bool,
+    fast :: Bool,
+    help :: Bool,
+    input :: Maybe String,
+    mode :: Maybe Mode.Mode,
+    output :: Maybe String,
+    schema :: Bool,
+    skipCrc :: Bool,
+    version :: Bool
   }
   deriving (Eq, Show)
 
 initial :: Config
-initial = Config
-  { compact = False
-  , fast = False
-  , help = False
-  , input = Nothing
-  , mode = Nothing
-  , output = Nothing
-  , schema = False
-  , skipCrc = False
-  , version = False
-  }
+initial =
+  Config
+    { compact = False,
+      fast = False,
+      help = False,
+      input = Nothing,
+      mode = Nothing,
+      output = Nothing,
+      schema = False,
+      skipCrc = False,
+      version = False
+    }
 
 applyFlag :: Config -> Flag.Flag -> Either String Config
 applyFlag config flag = case flag of
-  Flag.Compact -> Right config { compact = True }
-  Flag.Fast -> Right config { fast = True }
-  Flag.Help -> Right config { help = True }
-  Flag.Input x -> Right config { input = Just x }
+  Flag.Compact -> Right config {compact = True}
+  Flag.Fast -> Right config {fast = True}
+  Flag.Help -> Right config {help = True}
+  Flag.Input x -> Right config {input = Just x}
   Flag.Mode x -> do
     y <- Mode.fromString x
-    Right config { mode = Just y }
-  Flag.Output x -> Right config { output = Just x }
-  Flag.Schema -> Right config { schema = True }
-  Flag.SkipCrc -> Right config { skipCrc = True }
-  Flag.Version -> Right config { version = True }
+    Right config {mode = Just y}
+  Flag.Output x -> Right config {output = Just x}
+  Flag.Schema -> Right config {schema = True}
+  Flag.SkipCrc -> Right config {skipCrc = True}
+  Flag.Version -> Right config {version = True}
 
 getMode :: Config -> Mode.Mode
 getMode config =
-  let
-    i = fmap FilePath.takeExtension $ input config
-    o = fmap FilePath.takeExtension $ output config
-  in case (i, o) of
-    (Just ".json", _) -> Mode.Encode
-    (Just ".replay", _) -> Mode.Decode
-    (_, Just ".json") -> Mode.Decode
-    (_, Just ".replay") -> Mode.Encode
-    _ -> Mode.Decode
+  let i = fmap FilePath.takeExtension $ input config
+      o = fmap FilePath.takeExtension $ output config
+   in case (i, o) of
+        (Just ".json", _) -> Mode.Encode
+        (Just ".replay", _) -> Mode.Decode
+        (_, Just ".json") -> Mode.Decode
+        (_, Just ".replay") -> Mode.Encode
+        _ -> Mode.Decode
diff --git a/src/lib/Rattletrap/Console/Main.hs b/src/lib/Rattletrap/Console/Main.hs
--- a/src/lib/Rattletrap/Console/Main.hs
+++ b/src/lib/Rattletrap/Console/Main.hs
@@ -119,17 +119,20 @@
   config <- getConfig arguments
   if Config.help config
     then helpMain name
-    else if Config.version config
-      then versionMain
-      else if Config.schema config
-        then schemaMain config
-        else defaultMain name config
+    else
+      if Config.version config
+        then versionMain
+        else
+          if Config.schema config
+            then schemaMain config
+            else defaultMain name config
 
 helpMain :: String -> IO ()
 helpMain name = do
-  putStr $ Console.usageInfo
-    (unwords [name, "version", Version.string])
-    Option.all
+  putStr $
+    Console.usageInfo
+      (unwords [name, "version", Version.string])
+      Option.all
 
 versionMain :: IO ()
 versionMain = do
@@ -144,13 +147,14 @@
   let decode = getDecoder config
   replay <- case decode input of
     Left (ls, e) -> do
-      IO.hPutStr IO.stderr $ unlines
-        [ "ERROR: " <> Exception.displayException e
-        , "-- Context: " <> List.intercalate ", " ls
-        , "-- You are using Rattletrap version " <> Version.string
-        , "-- " <> show config
-        , "-- Please report this problem at https://github.com/tfausak/rattletrap/issues/new"
-        ]
+      IO.hPutStr IO.stderr $
+        unlines
+          [ "ERROR: " <> Exception.displayException e,
+            "-- Context: " <> List.intercalate ", " ls,
+            "-- You are using Rattletrap version " <> Version.string,
+            "-- " <> show config,
+            "-- Please report this problem at https://github.com/tfausak/rattletrap/issues/new"
+          ]
       Exit.exitFailure
     Right x -> pure x
   let encode = getEncoder config
@@ -159,114 +163,114 @@
 schema :: Json.Value
 schema =
   let contentSchema = Content.schema $ List.schema Frame.schema
-  in
-    Json.object
-      [ Json.pair "$schema" "http://json-schema.org/draft-07/schema"
-      , Json.pair "$id" Replay.schemaUrl
-      , Json.pair "$ref" "#/definitions/replay"
-      , Json.pair "definitions" . Json.object $ fmap
-        (\s -> Json.pair (Text.unpack $ Schema.name s) $ Schema.json s)
-        [ Attribute.schema
-        , Attribute.AppliedDamage.schema
-        , Attribute.Boolean.schema
-        , Attribute.Byte.schema
-        , Attribute.CamSettings.schema
-        , Attribute.ClubColors.schema
-        , Attribute.CustomDemolish.schema
-        , Attribute.DamageState.schema
-        , Attribute.Demolish.schema
-        , Attribute.Enum.schema
-        , Attribute.Explosion.schema
-        , Attribute.ExtendedExplosion.schema
-        , Attribute.FlaggedByte.schema
-        , Attribute.FlaggedInt.schema
-        , Attribute.Float.schema
-        , Attribute.GameMode.schema
-        , Attribute.GameServer.schema
-        , Attribute.Int.schema
-        , Attribute.Int64.schema
-        , Attribute.Loadout.schema
-        , Attribute.LoadoutOnline.schema
-        , Attribute.Loadouts.schema
-        , Attribute.LoadoutsOnline.schema
-        , Attribute.Location.schema
-        , Attribute.MusicStinger.schema
-        , Attribute.PartyLeader.schema
-        , Attribute.Pickup.schema
-        , Attribute.PickupInfo.schema
-        , Attribute.PickupNew.schema
-        , Attribute.PlayerHistoryKey.schema
-        , Attribute.PrivateMatchSettings.schema
-        , Attribute.Product.schema
-        , Attribute.ProductValue.schema
-        , Attribute.QWord.schema
-        , Attribute.RepStatTitle.schema
-        , Attribute.Reservation.schema
-        , Attribute.RigidBodyState.schema
-        , Attribute.Rotation.schema
-        , Attribute.StatEvent.schema
-        , Attribute.String.schema
-        , Attribute.TeamPaint.schema
-        , Attribute.Title.schema
-        , Attribute.UniqueId.schema
-        , Attribute.WeldedInfo.schema
-        , AttributeMapping.schema
-        , AttributeValue.schema
-        , Cache.schema
-        , ClassMapping.schema
-        , CompressedWord.schema
-        , CompressedWordVector.schema
-        , contentSchema
-        , Dictionary.schema Property.schema
-        , F32.schema
-        , Frame.schema
-        , Header.schema
-        , I32.schema
-        , I64.schema
-        , I8.schema
-        , Initialization.schema
-        , Int8Vector.schema
-        , Keyframe.schema
-        , List.schema Attribute.Product.schema
-        , Mark.schema
-        , Message.schema
-        , Property.schema
-        , Property.Array.schema Property.schema
-        , Property.Byte.schema
-        , PropertyValue.schema Property.schema
-        , Quaternion.schema
-        , RemoteId.schema
-        , RemoteId.PlayStation.schema
-        , RemoteId.PsyNet.schema
-        , RemoteId.Switch.schema
-        , Replay.schema (Section.schema Header.schema)
-        . Section.schema
-        $ contentSchema
-        , Replication.Destroyed.schema
-        , Replication.schema
-        , Replication.Spawned.schema
-        , Replication.Updated.schema
-        , ReplicationValue.schema
-        , Rotation.schema
-        , Schema.boolean
-        , Schema.integer
-        , Schema.null
-        , Schema.number
-        , Schema.string
-        , Section.schema contentSchema
-        , Section.schema Header.schema
-        , Str.schema
-        , U32.schema
-        , U64.schema
-        , U8.schema
-        , Vector.schema
+   in Json.object
+        [ Json.pair "$schema" "http://json-schema.org/draft-07/schema",
+          Json.pair "$id" Replay.schemaUrl,
+          Json.pair "$ref" "#/definitions/replay",
+          Json.pair "definitions" . Json.object $
+            fmap
+              (\s -> Json.pair (Text.unpack $ Schema.name s) $ Schema.json s)
+              [ Attribute.schema,
+                Attribute.AppliedDamage.schema,
+                Attribute.Boolean.schema,
+                Attribute.Byte.schema,
+                Attribute.CamSettings.schema,
+                Attribute.ClubColors.schema,
+                Attribute.CustomDemolish.schema,
+                Attribute.DamageState.schema,
+                Attribute.Demolish.schema,
+                Attribute.Enum.schema,
+                Attribute.Explosion.schema,
+                Attribute.ExtendedExplosion.schema,
+                Attribute.FlaggedByte.schema,
+                Attribute.FlaggedInt.schema,
+                Attribute.Float.schema,
+                Attribute.GameMode.schema,
+                Attribute.GameServer.schema,
+                Attribute.Int.schema,
+                Attribute.Int64.schema,
+                Attribute.Loadout.schema,
+                Attribute.LoadoutOnline.schema,
+                Attribute.Loadouts.schema,
+                Attribute.LoadoutsOnline.schema,
+                Attribute.Location.schema,
+                Attribute.MusicStinger.schema,
+                Attribute.PartyLeader.schema,
+                Attribute.Pickup.schema,
+                Attribute.PickupInfo.schema,
+                Attribute.PickupNew.schema,
+                Attribute.PlayerHistoryKey.schema,
+                Attribute.PrivateMatchSettings.schema,
+                Attribute.Product.schema,
+                Attribute.ProductValue.schema,
+                Attribute.QWord.schema,
+                Attribute.RepStatTitle.schema,
+                Attribute.Reservation.schema,
+                Attribute.RigidBodyState.schema,
+                Attribute.Rotation.schema,
+                Attribute.StatEvent.schema,
+                Attribute.String.schema,
+                Attribute.TeamPaint.schema,
+                Attribute.Title.schema,
+                Attribute.UniqueId.schema,
+                Attribute.WeldedInfo.schema,
+                AttributeMapping.schema,
+                AttributeValue.schema,
+                Cache.schema,
+                ClassMapping.schema,
+                CompressedWord.schema,
+                CompressedWordVector.schema,
+                contentSchema,
+                Dictionary.schema Property.schema,
+                F32.schema,
+                Frame.schema,
+                Header.schema,
+                I32.schema,
+                I64.schema,
+                I8.schema,
+                Initialization.schema,
+                Int8Vector.schema,
+                Keyframe.schema,
+                List.schema Attribute.Product.schema,
+                Mark.schema,
+                Message.schema,
+                Property.schema,
+                Property.Array.schema Property.schema,
+                Property.Byte.schema,
+                PropertyValue.schema Property.schema,
+                Quaternion.schema,
+                RemoteId.schema,
+                RemoteId.PlayStation.schema,
+                RemoteId.PsyNet.schema,
+                RemoteId.Switch.schema,
+                Replay.schema (Section.schema Header.schema)
+                  . Section.schema
+                  $ contentSchema,
+                Replication.Destroyed.schema,
+                Replication.schema,
+                Replication.Spawned.schema,
+                Replication.Updated.schema,
+                ReplicationValue.schema,
+                Rotation.schema,
+                Schema.boolean,
+                Schema.integer,
+                Schema.null,
+                Schema.number,
+                Schema.string,
+                Section.schema contentSchema,
+                Section.schema Header.schema,
+                Str.schema,
+                U32.schema,
+                U64.schema,
+                U8.schema,
+                Vector.schema
+              ]
         ]
-      ]
 
-getDecoder
-  :: Config.Config
-  -> ByteString.ByteString
-  -> Either ([String], Exception.SomeException) Replay.Replay
+getDecoder ::
+  Config.Config ->
+  ByteString.ByteString ->
+  Either ([String], Exception.SomeException) Replay.Replay
 getDecoder config = case Config.getMode config of
   Mode.Decode ->
     Rattletrap.decodeReplayFile (Config.fast config) (Config.skipCrc config)
@@ -281,12 +285,13 @@
 getInput name config = case Config.input config of
   Nothing -> do
     isTerminalDevice <- IO.hIsTerminalDevice IO.stdin
-    Monad.when isTerminalDevice . IO.hPutStr IO.stderr $ unlines
-      [ "-- You did not supply any input, so Rattletrap will read from STDIN."
-      , "-- If that is unexpected, try running: "
-      <> FilePath.combine "." name
-      <> " --help"
-      ]
+    Monad.when isTerminalDevice . IO.hPutStr IO.stderr $
+      unlines
+        [ "-- You did not supply any input, so Rattletrap will read from STDIN.",
+          "-- If that is unexpected, try running: "
+            <> FilePath.combine "." name
+            <> " --help"
+        ]
     ByteString.getContents
   Just fileOrUrl -> case Client.parseUrlThrow fileOrUrl of
     Nothing -> ByteString.readFile fileOrUrl
@@ -299,18 +304,17 @@
 putOutput =
   maybe LazyByteString.putStr LazyByteString.writeFile . Config.output
 
-encodeJson :: Json.ToJSON a => Config.Config -> a -> LazyByteString.ByteString
+encodeJson :: (Json.ToJSON a) => Config.Config -> a -> LazyByteString.ByteString
 encodeJson = Bool.bool Json.encodePretty Json.encode . Config.compact
 
 getConfig :: [String] -> IO Config.Config
 getConfig arguments = do
-  let
-    (flags, unexpectedArguments, unknownOptions, problems) =
-      Console.getOpt' Console.Permute Option.all arguments
+  let (flags, unexpectedArguments, unknownOptions, problems) =
+        Console.getOpt' Console.Permute Option.all arguments
   Monad.forM_ unexpectedArguments $ \x ->
     IO.hPutStrLn IO.stderr $ "WARNING: unexpected argument `" <> x <> "'"
-  Monad.forM_ unknownOptions
-    $ \x -> IO.hPutStrLn IO.stderr $ "WARNING: unknown option `" <> x <> "'"
+  Monad.forM_ unknownOptions $
+    \x -> IO.hPutStrLn IO.stderr $ "WARNING: unknown option `" <> x <> "'"
   Monad.forM_ problems $ \x -> IO.hPutStr IO.stderr $ "ERROR: " <> x
   Monad.unless (null problems) Exit.exitFailure
   either fail pure $ Monad.foldM Config.applyFlag Config.initial flags
diff --git a/src/lib/Rattletrap/Console/Option.hs b/src/lib/Rattletrap/Console/Option.hs
--- a/src/lib/Rattletrap/Console/Option.hs
+++ b/src/lib/Rattletrap/Console/Option.hs
@@ -9,42 +9,47 @@
 all = [compact, fast, help, input, mode, output, schema, skipCrc, version]
 
 compact :: Option
-compact = Console.Option
-  ['c']
-  ["compact"]
-  (Console.NoArg Flag.Compact)
-  "minify JSON output"
+compact =
+  Console.Option
+    ['c']
+    ["compact"]
+    (Console.NoArg Flag.Compact)
+    "minify JSON output"
 
 fast :: Option
-fast = Console.Option
-  ['f']
-  ["fast"]
-  (Console.NoArg Flag.Fast)
-  "only encode or decode the header"
+fast =
+  Console.Option
+    ['f']
+    ["fast"]
+    (Console.NoArg Flag.Fast)
+    "only encode or decode the header"
 
 help :: Option
 help = Console.Option ['h'] ["help"] (Console.NoArg Flag.Help) "show the help"
 
 input :: Option
-input = Console.Option
-  ['i']
-  ["input"]
-  (Console.ReqArg Flag.Input "FILE|URL")
-  "input file or URL"
+input =
+  Console.Option
+    ['i']
+    ["input"]
+    (Console.ReqArg Flag.Input "FILE|URL")
+    "input file or URL"
 
 mode :: Option
-mode = Console.Option
-  ['m']
-  ["mode"]
-  (Console.ReqArg Flag.Mode "MODE")
-  "decode or encode"
+mode =
+  Console.Option
+    ['m']
+    ["mode"]
+    (Console.ReqArg Flag.Mode "MODE")
+    "decode or encode"
 
 output :: Option
-output = Console.Option
-  ['o']
-  ["output"]
-  (Console.ReqArg Flag.Output "FILE")
-  "output file"
+output =
+  Console.Option
+    ['o']
+    ["output"]
+    (Console.ReqArg Flag.Output "FILE")
+    "output file"
 
 schema :: Option
 schema =
@@ -55,8 +60,9 @@
   Console.Option [] ["skip-crc"] (Console.NoArg Flag.SkipCrc) "skip the CRC"
 
 version :: Option
-version = Console.Option
-  ['v']
-  ["version"]
-  (Console.NoArg Flag.Version)
-  "show the version"
+version =
+  Console.Option
+    ['v']
+    ["version"]
+    (Console.NoArg Flag.Version)
+    "show the version"
diff --git a/src/lib/Rattletrap/Data.hs b/src/lib/Rattletrap/Data.hs
--- a/src/lib/Rattletrap/Data.hs
+++ b/src/lib/Rattletrap/Data.hs
@@ -8,445 +8,455 @@
 import qualified Rattletrap.Type.AttributeType as AttributeType
 
 parentClasses :: Map.Map Text.Text Text.Text
-parentClasses = Map.fromList $ fmap
-  (Bifunctor.bimap Text.pack Text.pack)
-  [ ("Engine.Actor", "Core.Object")
-  , ("Engine.GameReplicationInfo", "Engine.ReplicationInfo")
-  , ("Engine.Info", "Engine.Actor")
-  , ("Engine.Pawn", "Engine.Actor")
-  , ("Engine.PlayerReplicationInfo", "Engine.ReplicationInfo")
-  , ("Engine.ReplicationInfo", "Engine.Info")
-  , ("Engine.TeamInfo", "Engine.ReplicationInfo")
-  , ("ProjectX.GRI_X", "Engine.GameReplicationInfo")
-  , ("ProjectX.Pawn_X", "Engine.Pawn")
-  , ("ProjectX.PRI_X", "Engine.PlayerReplicationInfo")
-  , ("TAGame.Ball_God_TA", "TAGame.Ball_TA")
-  , ("TAGame.Ball_Haunted_TA", "TAGame.Ball_TA")
-  , ("TAGame.Ball_TA", "TAGame.RBActor_TA")
-  , ("TAGame.CameraSettingsActor_TA", "Engine.ReplicationInfo")
-  , ("TAGame.Car_Season_TA", "TAGame.PRI_TA")
-  , ("TAGame.Car_TA", "TAGame.Vehicle_TA")
-  , ("TAGame.CarComponent_Boost_TA", "TAGame.CarComponent_TA")
-  , ("TAGame.CarComponent_Dodge_TA", "TAGame.CarComponent_TA")
-  , ("TAGame.CarComponent_DoubleJump_TA", "TAGame.CarComponent_TA")
-  , ("TAGame.CarComponent_FlipCar_TA", "TAGame.CarComponent_TA")
-  , ("TAGame.CarComponent_Jump_TA", "TAGame.CarComponent_TA")
-  , ("TAGame.CarComponent_TA", "Engine.ReplicationInfo")
-  , ("TAGame.CrowdActor_TA", "Engine.ReplicationInfo")
-  , ("TAGame.CrowdManager_TA", "Engine.ReplicationInfo")
-  , ("TAGame.GameEvent_Football_TA", "TAGame.GameEvent_Soccar_TA")
-  , ("TAGame.GameEvent_GodBall_TA", "TAGame.GameEvent_Soccar_TA")
-  , ("TAGame.GameEvent_Season_TA", "TAGame.GameEvent_Soccar_TA")
-  , ("TAGame.GameEvent_Soccar_TA", "TAGame.GameEvent_Team_TA")
-  , ("TAGame.GameEvent_SoccarPrivate_TA", "TAGame.GameEvent_Soccar_TA")
-  , ("TAGame.GameEvent_SoccarSplitscreen_TA", "TAGame.GameEvent_SoccarPrivate_TA")
-  , ("TAGame.GameEvent_TA", "Engine.ReplicationInfo")
-  , ("TAGame.GameEvent_Team_TA", "TAGame.GameEvent_TA")
-  , ("TAGame.GRI_TA", "ProjectX.GRI_X")
-  , ("TAGame.HauntedBallTrapTrigger_TA", "Engine.Actor")
-  , ("TAGame.InMapScoreboard_TA", "Engine.Actor")
-  , ("TAGame.PRI_TA", "ProjectX.PRI_X")
-  , ("TAGame.RBActor_TA", "ProjectX.Pawn_X")
-  , ("TAGame.SpecialPickup_BallCarSpring_TA", "TAGame.SpecialPickup_Spring_TA")
-  , ("TAGame.SpecialPickup_BallFreeze_TA", "TAGame.SpecialPickup_Targeted_TA")
-  , ("TAGame.SpecialPickup_BallGravity_TA", "TAGame.SpecialPickup_TA")
-  , ("TAGame.SpecialPickup_BallLasso_TA", "TAGame.SpecialPickup_GrapplingHook_TA")
-  , ("TAGame.SpecialPickup_BallVelcro_TA", "TAGame.SpecialPickup_TA")
-  , ("TAGame.SpecialPickup_Batarang_TA", "TAGame.SpecialPickup_BallLasso_TA")
-  , ("TAGame.SpecialPickup_BoostOverride_TA", "TAGame.SpecialPickup_Targeted_TA")
-  , ("TAGame.SpecialPickup_Football_TA", "TAGame.SpecialPickup_TA")
-  , ("TAGame.SpecialPickup_GrapplingHook_TA", "TAGame.SpecialPickup_Targeted_TA")
-  , ("TAGame.SpecialPickup_HauntedBallBeam_TA", "TAGame.SpecialPickup_TA")
-  , ("TAGame.SpecialPickup_HitForce_TA", "TAGame.SpecialPickup_TA")
-  , ("TAGame.SpecialPickup_Rugby_TA", "TAGame.SpecialPickup_TA")
-  , ("TAGame.SpecialPickup_Spring_TA", "TAGame.SpecialPickup_Targeted_TA")
-  , ("TAGame.SpecialPickup_Swapper_TA", "TAGame.SpecialPickup_Targeted_TA")
-  , ("TAGame.SpecialPickup_TA", "TAGame.CarComponent_TA")
-  , ("TAGame.SpecialPickup_Targeted_TA", "TAGame.SpecialPickup_TA")
-  , ("TAGame.SpecialPickup_Tornado_TA", "TAGame.SpecialPickup_TA")
-  , ("TAGame.Team_Soccar_TA", "TAGame.Team_TA")
-  , ("TAGame.Team_TA", "Engine.TeamInfo")
-  , ("TAGame.Vehicle_TA", "TAGame.RBActor_TA")
-  , ("TAGame.VehiclePickup_Boost_TA", "TAGame.VehiclePickup_TA")
-  , ("TAGame.VehiclePickup_TA", "Engine.ReplicationInfo")
-  ]
+parentClasses =
+  Map.fromList $
+    fmap
+      (Bifunctor.bimap Text.pack Text.pack)
+      [ ("Engine.Actor", "Core.Object"),
+        ("Engine.GameReplicationInfo", "Engine.ReplicationInfo"),
+        ("Engine.Info", "Engine.Actor"),
+        ("Engine.Pawn", "Engine.Actor"),
+        ("Engine.PlayerReplicationInfo", "Engine.ReplicationInfo"),
+        ("Engine.ReplicationInfo", "Engine.Info"),
+        ("Engine.TeamInfo", "Engine.ReplicationInfo"),
+        ("ProjectX.GRI_X", "Engine.GameReplicationInfo"),
+        ("ProjectX.Pawn_X", "Engine.Pawn"),
+        ("ProjectX.PRI_X", "Engine.PlayerReplicationInfo"),
+        ("TAGame.Ball_God_TA", "TAGame.Ball_TA"),
+        ("TAGame.Ball_Haunted_TA", "TAGame.Ball_TA"),
+        ("TAGame.Ball_TA", "TAGame.RBActor_TA"),
+        ("TAGame.CameraSettingsActor_TA", "Engine.ReplicationInfo"),
+        ("TAGame.Car_Season_TA", "TAGame.PRI_TA"),
+        ("TAGame.Car_TA", "TAGame.Vehicle_TA"),
+        ("TAGame.CarComponent_Boost_TA", "TAGame.CarComponent_TA"),
+        ("TAGame.CarComponent_Dodge_TA", "TAGame.CarComponent_TA"),
+        ("TAGame.CarComponent_DoubleJump_TA", "TAGame.CarComponent_TA"),
+        ("TAGame.CarComponent_FlipCar_TA", "TAGame.CarComponent_TA"),
+        ("TAGame.CarComponent_Jump_TA", "TAGame.CarComponent_TA"),
+        ("TAGame.CarComponent_TA", "Engine.ReplicationInfo"),
+        ("TAGame.CrowdActor_TA", "Engine.ReplicationInfo"),
+        ("TAGame.CrowdManager_TA", "Engine.ReplicationInfo"),
+        ("TAGame.GameEvent_Football_TA", "TAGame.GameEvent_Soccar_TA"),
+        ("TAGame.GameEvent_GodBall_TA", "TAGame.GameEvent_Soccar_TA"),
+        ("TAGame.GameEvent_Season_TA", "TAGame.GameEvent_Soccar_TA"),
+        ("TAGame.GameEvent_Soccar_TA", "TAGame.GameEvent_Team_TA"),
+        ("TAGame.GameEvent_SoccarPrivate_TA", "TAGame.GameEvent_Soccar_TA"),
+        ("TAGame.GameEvent_SoccarSplitscreen_TA", "TAGame.GameEvent_SoccarPrivate_TA"),
+        ("TAGame.GameEvent_TA", "Engine.ReplicationInfo"),
+        ("TAGame.GameEvent_Team_TA", "TAGame.GameEvent_TA"),
+        ("TAGame.GRI_TA", "ProjectX.GRI_X"),
+        ("TAGame.HauntedBallTrapTrigger_TA", "Engine.Actor"),
+        ("TAGame.InMapScoreboard_TA", "Engine.Actor"),
+        ("TAGame.PRI_TA", "ProjectX.PRI_X"),
+        ("TAGame.RBActor_TA", "ProjectX.Pawn_X"),
+        ("TAGame.SpecialPickup_BallCarSpring_TA", "TAGame.SpecialPickup_Spring_TA"),
+        ("TAGame.SpecialPickup_BallFreeze_TA", "TAGame.SpecialPickup_Targeted_TA"),
+        ("TAGame.SpecialPickup_BallGravity_TA", "TAGame.SpecialPickup_TA"),
+        ("TAGame.SpecialPickup_BallLasso_TA", "TAGame.SpecialPickup_GrapplingHook_TA"),
+        ("TAGame.SpecialPickup_BallVelcro_TA", "TAGame.SpecialPickup_TA"),
+        ("TAGame.SpecialPickup_Batarang_TA", "TAGame.SpecialPickup_BallLasso_TA"),
+        ("TAGame.SpecialPickup_BoostOverride_TA", "TAGame.SpecialPickup_Targeted_TA"),
+        ("TAGame.SpecialPickup_Football_TA", "TAGame.SpecialPickup_TA"),
+        ("TAGame.SpecialPickup_GrapplingHook_TA", "TAGame.SpecialPickup_Targeted_TA"),
+        ("TAGame.SpecialPickup_HauntedBallBeam_TA", "TAGame.SpecialPickup_TA"),
+        ("TAGame.SpecialPickup_HitForce_TA", "TAGame.SpecialPickup_TA"),
+        ("TAGame.SpecialPickup_Rugby_TA", "TAGame.SpecialPickup_TA"),
+        ("TAGame.SpecialPickup_Spring_TA", "TAGame.SpecialPickup_Targeted_TA"),
+        ("TAGame.SpecialPickup_Swapper_TA", "TAGame.SpecialPickup_Targeted_TA"),
+        ("TAGame.SpecialPickup_TA", "TAGame.CarComponent_TA"),
+        ("TAGame.SpecialPickup_Targeted_TA", "TAGame.SpecialPickup_TA"),
+        ("TAGame.SpecialPickup_Tornado_TA", "TAGame.SpecialPickup_TA"),
+        ("TAGame.Team_Soccar_TA", "TAGame.Team_TA"),
+        ("TAGame.Team_TA", "Engine.TeamInfo"),
+        ("TAGame.Vehicle_TA", "TAGame.RBActor_TA"),
+        ("TAGame.VehiclePickup_Boost_TA", "TAGame.VehiclePickup_TA"),
+        ("TAGame.VehiclePickup_TA", "Engine.ReplicationInfo")
+      ]
 
 classesWithLocation :: Set.Set Text.Text
-classesWithLocation = Set.fromList $ fmap
-  Text.pack
-  [ "Archetypes.Ball.Ball_BasketBall_Mutator"
-  , "Archetypes.Ball.Ball_Basketball"
-  , "Archetypes.Ball.Ball_BasketBall"
-  , "Archetypes.Ball.Ball_Breakout"
-  , "Archetypes.Ball.Ball_Default"
-  , "Archetypes.Ball.Ball_Puck"
-  , "Archetypes.Ball.Ball_Trajectory"
-  , "Archetypes.Ball.CubeBall"
-  , "Archetypes.Car.Car_Default"
-  , "Archetypes.GameEvent.GameEvent_Season:CarArchetype"
-  , "Archetypes.SpecialPickups.SpecialPickup_Rugby"
-  , "ProjectX.NetModeReplicator"
-  , "TAGame.Ball_Breakout_TA"
-  , "TAGame.Ball_God_TA"
-  , "TAGame.Ball_Haunted_TA"
-  , "TAGame.Ball_TA"
-  , "TAGame.CameraSettingsActor_TA"
-  , "TAGame.Cannon_TA"
-  , "TAGame.Car_Season_TA"
-  , "TAGame.Car_TA"
-  , "TAGame.CarComponent_Boost_TA"
-  , "TAGame.CarComponent_Dodge_TA"
-  , "TAGame.CarComponent_DoubleJump_TA"
-  , "TAGame.CarComponent_FlipCar_TA"
-  , "TAGame.CarComponent_Jump_TA"
-  , "TAGame.Default__CameraSettingsActor_TA"
-  , "TAGame.Default__PRI_TA"
-  , "TAGame.GameEvent_Football_TA"
-  , "TAGame.GameEvent_GodBall_TA"
-  , "TAGame.GameEvent_Season_TA"
-  , "TAGame.GameEvent_Soccar_TA"
-  , "TAGame.GameEvent_SoccarPrivate_TA"
-  , "TAGame.GameEvent_SoccarSplitscreen_TA"
-  , "TAGame.GameEvent_Tutorial_TA"
-  , "TAGame.GRI_TA"
-  , "TAGame.MaxTimeWarningData_TA"
-  , "TAGame.PickupTimer_TA"
-  , "TAGame.PRI_TA"
-  , "TAGame.RumblePickups_TA"
-  , "TAGame.SpecialPickup_BallCarSpring_TA"
-  , "TAGame.SpecialPickup_BallFreeze_TA"
-  , "TAGame.SpecialPickup_BallGravity_TA"
-  , "TAGame.SpecialPickup_BallLasso_TA"
-  , "TAGame.SpecialPickup_BallVelcro_TA"
-  , "TAGame.SpecialPickup_Batarang_TA"
-  , "TAGame.SpecialPickup_BoostOverride_TA"
-  , "TAGame.SpecialPickup_Football_TA"
-  , "TAGame.SpecialPickup_GrapplingHook_TA"
-  , "TAGame.SpecialPickup_HauntedBallBeam_TA"
-  , "TAGame.SpecialPickup_HitForce_TA"
-  , "TAGame.SpecialPickup_Rugby_TA"
-  , "TAGame.SpecialPickup_Swapper_TA"
-  , "TAGame.SpecialPickup_Tornado_TA"
-  , "TAGame.Team_Soccar_TA"
-  , "TheWorld:PersistentLevel.BreakOutActor_Platform_TA"
-  , "TheWorld:PersistentLevel.CrowdActor_TA"
-  , "TheWorld:PersistentLevel.CrowdManager_TA"
-  , "TheWorld:PersistentLevel.InMapScoreboard_TA"
-  , "TheWorld:PersistentLevel.VehiclePickup_Boost_TA"
-  ]
+classesWithLocation =
+  Set.fromList $
+    fmap
+      Text.pack
+      [ "Archetypes.Ball.Ball_BasketBall_Mutator",
+        "Archetypes.Ball.Ball_Basketball",
+        "Archetypes.Ball.Ball_BasketBall",
+        "Archetypes.Ball.Ball_Breakout",
+        "Archetypes.Ball.Ball_Default",
+        "Archetypes.Ball.Ball_Puck",
+        "Archetypes.Ball.Ball_Trajectory",
+        "Archetypes.Ball.CubeBall",
+        "Archetypes.Car.Car_Default",
+        "Archetypes.GameEvent.GameEvent_Season:CarArchetype",
+        "Archetypes.SpecialPickups.SpecialPickup_Rugby",
+        "ProjectX.NetModeReplicator",
+        "TAGame.Ball_Breakout_TA",
+        "TAGame.Ball_God_TA",
+        "TAGame.Ball_Haunted_TA",
+        "TAGame.Ball_TA",
+        "TAGame.CameraSettingsActor_TA",
+        "TAGame.Cannon_TA",
+        "TAGame.Car_Season_TA",
+        "TAGame.Car_TA",
+        "TAGame.CarComponent_Boost_TA",
+        "TAGame.CarComponent_Dodge_TA",
+        "TAGame.CarComponent_DoubleJump_TA",
+        "TAGame.CarComponent_FlipCar_TA",
+        "TAGame.CarComponent_Jump_TA",
+        "TAGame.Default__CameraSettingsActor_TA",
+        "TAGame.Default__PRI_TA",
+        "TAGame.GameEvent_Football_TA",
+        "TAGame.GameEvent_GodBall_TA",
+        "TAGame.GameEvent_Season_TA",
+        "TAGame.GameEvent_Soccar_TA",
+        "TAGame.GameEvent_SoccarPrivate_TA",
+        "TAGame.GameEvent_SoccarSplitscreen_TA",
+        "TAGame.GameEvent_Tutorial_TA",
+        "TAGame.GRI_TA",
+        "TAGame.MaxTimeWarningData_TA",
+        "TAGame.PickupTimer_TA",
+        "TAGame.PRI_TA",
+        "TAGame.RumblePickups_TA",
+        "TAGame.SpecialPickup_BallCarSpring_TA",
+        "TAGame.SpecialPickup_BallFreeze_TA",
+        "TAGame.SpecialPickup_BallGravity_TA",
+        "TAGame.SpecialPickup_BallLasso_TA",
+        "TAGame.SpecialPickup_BallVelcro_TA",
+        "TAGame.SpecialPickup_Batarang_TA",
+        "TAGame.SpecialPickup_BoostOverride_TA",
+        "TAGame.SpecialPickup_Football_TA",
+        "TAGame.SpecialPickup_GrapplingHook_TA",
+        "TAGame.SpecialPickup_HauntedBallBeam_TA",
+        "TAGame.SpecialPickup_HitForce_TA",
+        "TAGame.SpecialPickup_Rugby_TA",
+        "TAGame.SpecialPickup_Swapper_TA",
+        "TAGame.SpecialPickup_Tornado_TA",
+        "TAGame.Team_Soccar_TA",
+        "TheWorld:PersistentLevel.BreakOutActor_Platform_TA",
+        "TheWorld:PersistentLevel.CrowdActor_TA",
+        "TheWorld:PersistentLevel.CrowdManager_TA",
+        "TheWorld:PersistentLevel.InMapScoreboard_TA",
+        "TheWorld:PersistentLevel.VehiclePickup_Boost_TA"
+      ]
 
 classesWithRotation :: Set.Set Text.Text
-classesWithRotation = Set.fromList $ fmap
-  Text.pack
-  [ "Archetypes.Ball.Ball_BasketBall_Mutator"
-  , "Archetypes.Ball.Ball_Basketball"
-  , "Archetypes.Ball.Ball_BasketBall"
-  , "Archetypes.Ball.Ball_Breakout"
-  , "Archetypes.Ball.Ball_Default"
-  , "Archetypes.Ball.Ball_Puck"
-  , "Archetypes.Ball.Ball_Trajectory"
-  , "Archetypes.Ball.CubeBall"
-  , "Archetypes.Car.Car_Default"
-  , "Archetypes.GameEvent.GameEvent_Season:CarArchetype"
-  , "Archetypes.SpecialPickups.SpecialPickup_Rugby"
-  , "TAGame.Ball_Breakout_TA"
-  , "TAGame.Ball_God_TA"
-  , "TAGame.Ball_Haunted_TA"
-  , "TAGame.Ball_TA"
-  , "TAGame.Car_Season_TA"
-  , "TAGame.Car_TA"
-  ]
+classesWithRotation =
+  Set.fromList $
+    fmap
+      Text.pack
+      [ "Archetypes.Ball.Ball_BasketBall_Mutator",
+        "Archetypes.Ball.Ball_Basketball",
+        "Archetypes.Ball.Ball_BasketBall",
+        "Archetypes.Ball.Ball_Breakout",
+        "Archetypes.Ball.Ball_Default",
+        "Archetypes.Ball.Ball_Puck",
+        "Archetypes.Ball.Ball_Trajectory",
+        "Archetypes.Ball.CubeBall",
+        "Archetypes.Car.Car_Default",
+        "Archetypes.GameEvent.GameEvent_Season:CarArchetype",
+        "Archetypes.SpecialPickups.SpecialPickup_Rugby",
+        "TAGame.Ball_Breakout_TA",
+        "TAGame.Ball_God_TA",
+        "TAGame.Ball_Haunted_TA",
+        "TAGame.Ball_TA",
+        "TAGame.Car_Season_TA",
+        "TAGame.Car_TA"
+      ]
 
 objectClasses :: Map.Map Text.Text Text.Text
-objectClasses = Map.fromList $ fmap
-  (Bifunctor.bimap Text.pack Text.pack)
-  [ ("Archetypes.Ball.Ball_Anniversary", "TAGame.Ball_TA")
-  , ("Archetypes.Ball.Ball_BasketBall_Mutator", "TAGame.Ball_TA")
-  , ("Archetypes.Ball.Ball_Basketball", "TAGame.Ball_TA")
-  , ("Archetypes.Ball.Ball_BasketBall", "TAGame.Ball_TA")
-  , ("Archetypes.Ball.Ball_Beachball", "TAGame.Ball_TA")
-  , ("Archetypes.Ball.Ball_Breakout", "TAGame.Ball_Breakout_TA")
-  , ("Archetypes.Ball.Ball_Default", "TAGame.Ball_TA")
-  , ("Archetypes.Ball.Ball_Football", "TAGame.Ball_TA")
-  , ("Archetypes.Ball.Ball_God", "TAGame.Ball_God_TA")
-  , ("Archetypes.Ball.Ball_Haunted", "TAGame.Ball_Haunted_TA")
-  , ("Archetypes.Ball.Ball_Puck", "TAGame.Ball_TA")
-  , ("Archetypes.Ball.Ball_Training", "TAGame.Ball_TA")
-  , ("Archetypes.Ball.Ball_Trajectory", "TAGame.Ball_TA")
-  , ("Archetypes.Ball.CubeBall", "TAGame.Ball_TA")
-  , ("Archetypes.Car.Car_Default", "TAGame.Car_TA")
-  , ("Archetypes.Car.Car_PostGameLobby", "TAGame.Car_TA")
-  , ("Archetypes.CarComponents.CarComponent_Boost", "TAGame.CarComponent_Boost_TA")
-  , ("Archetypes.CarComponents.CarComponent_Dodge", "TAGame.CarComponent_Dodge_TA")
-  , ("Archetypes.CarComponents.CarComponent_DoubleJump", "TAGame.CarComponent_DoubleJump_TA")
-  , ("Archetypes.CarComponents.CarComponent_FlipCar", "TAGame.CarComponent_FlipCar_TA")
-  , ("Archetypes.CarComponents.CarComponent_Jump", "TAGame.CarComponent_Jump_TA")
-  , ("Archetypes.GameEvent.GameEvent_Basketball", "TAGame.GameEvent_Soccar_TA")
-  , ("Archetypes.GameEvent.GameEvent_BasketballPrivate", "TAGame.GameEvent_SoccarPrivate_TA")
-  , ("Archetypes.GameEvent.GameEvent_BasketballSplitscreen", "TAGame.GameEvent_SoccarSplitscreen_TA")
-  , ("Archetypes.GameEvent.GameEvent_Breakout", "TAGame.GameEvent_Soccar_TA")
-  , ("Archetypes.GameEvent.GameEvent_Hockey", "TAGame.GameEvent_Soccar_TA")
-  , ("Archetypes.GameEvent.GameEvent_HockeyPrivate", "TAGame.GameEvent_SoccarPrivate_TA")
-  , ("Archetypes.GameEvent.GameEvent_HockeySplitscreen", "TAGame.GameEvent_SoccarSplitscreen_TA")
-  , ("Archetypes.GameEvent.GameEvent_Items", "TAGame.GameEvent_Soccar_TA")
-  , ("Archetypes.GameEvent.GameEvent_Season:CarArchetype", "TAGame.Car_TA")
-  , ("Archetypes.GameEvent.GameEvent_Season", "TAGame.GameEvent_Season_TA")
-  , ("Archetypes.GameEvent.GameEvent_Soccar", "TAGame.GameEvent_Soccar_TA")
-  , ("Archetypes.GameEvent.GameEvent_SoccarLan", "TAGame.GameEvent_Soccar_TA")
-  , ("Archetypes.GameEvent.GameEvent_SoccarPrivate", "TAGame.GameEvent_SoccarPrivate_TA")
-  , ("Archetypes.GameEvent.GameEvent_SoccarSplitscreen", "TAGame.GameEvent_SoccarSplitscreen_TA")
-  , ("Archetypes.SpecialPickups.SpecialPickup_BallFreeze", "TAGame.SpecialPickup_BallFreeze_TA")
-  , ("Archetypes.SpecialPickups.SpecialPickup_BallGrapplingHook", "TAGame.SpecialPickup_GrapplingHook_TA")
-  , ("Archetypes.SpecialPickups.SpecialPickup_BallLasso", "TAGame.SpecialPickup_BallLasso_TA")
-  , ("Archetypes.SpecialPickups.SpecialPickup_BallSpring", "TAGame.SpecialPickup_BallCarSpring_TA")
-  , ("Archetypes.SpecialPickups.SpecialPickup_BallVelcro", "TAGame.SpecialPickup_BallVelcro_TA")
-  , ("Archetypes.SpecialPickups.SpecialPickup_Batarang", "TAGame.SpecialPickup_Batarang_TA")
-  , ("Archetypes.SpecialPickups.SpecialPickup_BoostOverride", "TAGame.SpecialPickup_BoostOverride_TA")
-  , ("Archetypes.SpecialPickups.SpecialPickup_CarSpring", "TAGame.SpecialPickup_BallCarSpring_TA")
-  , ("Archetypes.SpecialPickups.SpecialPickup_Football", "TAGame.SpecialPickup_Football_TA")
-  , ("Archetypes.SpecialPickups.SpecialPickup_GravityWell", "TAGame.SpecialPickup_BallGravity_TA")
-  , ("Archetypes.SpecialPickups.SpecialPickup_HauntedBallBeam", "TAGame.SpecialPickup_HauntedBallBeam_TA")
-  , ("Archetypes.SpecialPickups.SpecialPickup_Rugby", "TAGame.SpecialPickup_Rugby_TA")
-  , ("Archetypes.SpecialPickups.SpecialPickup_StrongHit", "TAGame.SpecialPickup_HitForce_TA")
-  , ("Archetypes.SpecialPickups.SpecialPickup_Swapper", "TAGame.SpecialPickup_Swapper_TA")
-  , ("Archetypes.SpecialPickups.SpecialPickup_Tornado", "TAGame.SpecialPickup_Tornado_TA")
-  , ("Archetypes.Teams.Team0", "TAGame.Team_Soccar_TA")
-  , ("Archetypes.Teams.Team1", "TAGame.Team_Soccar_TA")
-  , ("Archetypes.Tutorial.Cannon", "TAGame.Cannon_TA")
-  , ("GameInfo_Basketball.GameInfo.GameInfo_Basketball:GameReplicationInfoArchetype", "TAGame.GRI_TA")
-  , ("GameInfo_Breakout.GameInfo.GameInfo_Breakout:GameReplicationInfoArchetype", "TAGame.GRI_TA")
-  , ("GameInfo_FootBall.GameInfo.GameInfo_FootBall:Archetype", "TAGame.GameEvent_Football_TA")
-  , ("GameInfo_FootBall.GameInfo.GameInfo_FootBall:GameReplicationInfoArchetype", "TAGame.GRI_TA")
-  , ("gameinfo_godball.GameInfo.gameinfo_godball:Archetype", "TAGame.GameEvent_GodBall_TA")
-  , ("GameInfo_GodBall.GameInfo.GameInfo_GodBall:Archetype", "TAGame.GameEvent_GodBall_TA")
-  , ("gameinfo_godball.GameInfo.gameinfo_godball:GameReplicationInfoArchetype", "TAGame.GRI_TA")
-  , ("GameInfo_GodBall.GameInfo.GameInfo_GodBall:GameReplicationInfoArchetype", "TAGame.GRI_TA")
-  , ("Gameinfo_Hockey.GameInfo.Gameinfo_Hockey:GameReplicationInfoArchetype", "TAGame.GRI_TA")
-  , ("GameInfo_Items.GameInfo.GameInfo_Items:GameReplicationInfoArchetype", "TAGame.GRI_TA")
-  , ("GameInfo_Season.GameInfo.GameInfo_Season:GameReplicationInfoArchetype", "TAGame.GRI_TA")
-  , ("GameInfo_Soccar.GameInfo.GameInfo_Soccar:GameReplicationInfoArchetype", "TAGame.GRI_TA")
-  , ("GameInfo_Tutorial.GameEvent.GameEvent_Tutorial_Aerial", "TAGame.GameEvent_Tutorial_TA")
-  , ("GameInfo_Tutorial.GameInfo.GameInfo_Tutorial:GameReplicationInfoArchetype", "TAGame.GRI_TA")
-  , ("Haunted_TrainStation_P.TheWorld:PersistentLevel.HauntedBallTrapTrigger_TA_0", "TAGame.HauntedBallTrapTrigger_TA")
-  , ("Haunted_TrainStation_P.TheWorld:PersistentLevel.HauntedBallTrapTrigger_TA_1", "TAGame.HauntedBallTrapTrigger_TA")
-  , ("ProjectX.Default__NetModeReplicator_X", "ProjectX.NetModeReplicator")
-  , ("TAGame.Default__CameraSettingsActor_TA", "TAGame.CameraSettingsActor_TA")
-  , ("TAGame.Default__MaxTimeWarningData_TA", "TAGame.MaxTimeWarningData_TA")
-  , ("TAGame.Default__PickupTimer_TA", "TAGame.PickupTimer_TA")
-  , ("TAGame.Default__PRI_TA", "TAGame.PRI_TA")
-  , ("TAGame.Default__RumblePickups_TA", "TAGame.RumblePickups_TA")
-  , ("TheWorld:PersistentLevel.BreakOutActor_Platform_TA", "TAGame.BreakOutActor_Platform_TA")
-  , ("TheWorld:PersistentLevel.CrowdActor_TA", "TAGame.CrowdActor_TA")
-  , ("TheWorld:PersistentLevel.CrowdManager_TA", "TAGame.CrowdManager_TA")
-  , ("TheWorld:PersistentLevel.InMapScoreboard_TA", "TAGame.InMapScoreboard_TA")
-  , ("TheWorld:PersistentLevel.VehiclePickup_Boost_TA", "TAGame.VehiclePickup_Boost_TA")
-  ]
+objectClasses =
+  Map.fromList $
+    fmap
+      (Bifunctor.bimap Text.pack Text.pack)
+      [ ("Archetypes.Ball.Ball_Anniversary", "TAGame.Ball_TA"),
+        ("Archetypes.Ball.Ball_BasketBall_Mutator", "TAGame.Ball_TA"),
+        ("Archetypes.Ball.Ball_Basketball", "TAGame.Ball_TA"),
+        ("Archetypes.Ball.Ball_BasketBall", "TAGame.Ball_TA"),
+        ("Archetypes.Ball.Ball_Beachball", "TAGame.Ball_TA"),
+        ("Archetypes.Ball.Ball_Breakout", "TAGame.Ball_Breakout_TA"),
+        ("Archetypes.Ball.Ball_Default", "TAGame.Ball_TA"),
+        ("Archetypes.Ball.Ball_Football", "TAGame.Ball_TA"),
+        ("Archetypes.Ball.Ball_God", "TAGame.Ball_God_TA"),
+        ("Archetypes.Ball.Ball_Haunted", "TAGame.Ball_Haunted_TA"),
+        ("Archetypes.Ball.Ball_Puck", "TAGame.Ball_TA"),
+        ("Archetypes.Ball.Ball_Training", "TAGame.Ball_TA"),
+        ("Archetypes.Ball.Ball_Trajectory", "TAGame.Ball_TA"),
+        ("Archetypes.Ball.CubeBall", "TAGame.Ball_TA"),
+        ("Archetypes.Car.Car_Default", "TAGame.Car_TA"),
+        ("Archetypes.Car.Car_PostGameLobby", "TAGame.Car_TA"),
+        ("Archetypes.CarComponents.CarComponent_Boost", "TAGame.CarComponent_Boost_TA"),
+        ("Archetypes.CarComponents.CarComponent_Dodge", "TAGame.CarComponent_Dodge_TA"),
+        ("Archetypes.CarComponents.CarComponent_DoubleJump", "TAGame.CarComponent_DoubleJump_TA"),
+        ("Archetypes.CarComponents.CarComponent_FlipCar", "TAGame.CarComponent_FlipCar_TA"),
+        ("Archetypes.CarComponents.CarComponent_Jump", "TAGame.CarComponent_Jump_TA"),
+        ("Archetypes.GameEvent.GameEvent_Basketball", "TAGame.GameEvent_Soccar_TA"),
+        ("Archetypes.GameEvent.GameEvent_BasketballPrivate", "TAGame.GameEvent_SoccarPrivate_TA"),
+        ("Archetypes.GameEvent.GameEvent_BasketballSplitscreen", "TAGame.GameEvent_SoccarSplitscreen_TA"),
+        ("Archetypes.GameEvent.GameEvent_Breakout", "TAGame.GameEvent_Soccar_TA"),
+        ("Archetypes.GameEvent.GameEvent_Hockey", "TAGame.GameEvent_Soccar_TA"),
+        ("Archetypes.GameEvent.GameEvent_HockeyPrivate", "TAGame.GameEvent_SoccarPrivate_TA"),
+        ("Archetypes.GameEvent.GameEvent_HockeySplitscreen", "TAGame.GameEvent_SoccarSplitscreen_TA"),
+        ("Archetypes.GameEvent.GameEvent_Items", "TAGame.GameEvent_Soccar_TA"),
+        ("Archetypes.GameEvent.GameEvent_Season:CarArchetype", "TAGame.Car_TA"),
+        ("Archetypes.GameEvent.GameEvent_Season", "TAGame.GameEvent_Season_TA"),
+        ("Archetypes.GameEvent.GameEvent_Soccar", "TAGame.GameEvent_Soccar_TA"),
+        ("Archetypes.GameEvent.GameEvent_SoccarLan", "TAGame.GameEvent_Soccar_TA"),
+        ("Archetypes.GameEvent.GameEvent_SoccarPrivate", "TAGame.GameEvent_SoccarPrivate_TA"),
+        ("Archetypes.GameEvent.GameEvent_SoccarSplitscreen", "TAGame.GameEvent_SoccarSplitscreen_TA"),
+        ("Archetypes.SpecialPickups.SpecialPickup_BallFreeze", "TAGame.SpecialPickup_BallFreeze_TA"),
+        ("Archetypes.SpecialPickups.SpecialPickup_BallGrapplingHook", "TAGame.SpecialPickup_GrapplingHook_TA"),
+        ("Archetypes.SpecialPickups.SpecialPickup_BallLasso", "TAGame.SpecialPickup_BallLasso_TA"),
+        ("Archetypes.SpecialPickups.SpecialPickup_BallSpring", "TAGame.SpecialPickup_BallCarSpring_TA"),
+        ("Archetypes.SpecialPickups.SpecialPickup_BallVelcro", "TAGame.SpecialPickup_BallVelcro_TA"),
+        ("Archetypes.SpecialPickups.SpecialPickup_Batarang", "TAGame.SpecialPickup_Batarang_TA"),
+        ("Archetypes.SpecialPickups.SpecialPickup_BoostOverride", "TAGame.SpecialPickup_BoostOverride_TA"),
+        ("Archetypes.SpecialPickups.SpecialPickup_CarSpring", "TAGame.SpecialPickup_BallCarSpring_TA"),
+        ("Archetypes.SpecialPickups.SpecialPickup_Football", "TAGame.SpecialPickup_Football_TA"),
+        ("Archetypes.SpecialPickups.SpecialPickup_GravityWell", "TAGame.SpecialPickup_BallGravity_TA"),
+        ("Archetypes.SpecialPickups.SpecialPickup_HauntedBallBeam", "TAGame.SpecialPickup_HauntedBallBeam_TA"),
+        ("Archetypes.SpecialPickups.SpecialPickup_Rugby", "TAGame.SpecialPickup_Rugby_TA"),
+        ("Archetypes.SpecialPickups.SpecialPickup_StrongHit", "TAGame.SpecialPickup_HitForce_TA"),
+        ("Archetypes.SpecialPickups.SpecialPickup_Swapper", "TAGame.SpecialPickup_Swapper_TA"),
+        ("Archetypes.SpecialPickups.SpecialPickup_Tornado", "TAGame.SpecialPickup_Tornado_TA"),
+        ("Archetypes.Teams.Team0", "TAGame.Team_Soccar_TA"),
+        ("Archetypes.Teams.Team1", "TAGame.Team_Soccar_TA"),
+        ("Archetypes.Tutorial.Cannon", "TAGame.Cannon_TA"),
+        ("GameInfo_Basketball.GameInfo.GameInfo_Basketball:GameReplicationInfoArchetype", "TAGame.GRI_TA"),
+        ("GameInfo_Breakout.GameInfo.GameInfo_Breakout:GameReplicationInfoArchetype", "TAGame.GRI_TA"),
+        ("GameInfo_FootBall.GameInfo.GameInfo_FootBall:Archetype", "TAGame.GameEvent_Football_TA"),
+        ("GameInfo_FootBall.GameInfo.GameInfo_FootBall:GameReplicationInfoArchetype", "TAGame.GRI_TA"),
+        ("gameinfo_godball.GameInfo.gameinfo_godball:Archetype", "TAGame.GameEvent_GodBall_TA"),
+        ("GameInfo_GodBall.GameInfo.GameInfo_GodBall:Archetype", "TAGame.GameEvent_GodBall_TA"),
+        ("gameinfo_godball.GameInfo.gameinfo_godball:GameReplicationInfoArchetype", "TAGame.GRI_TA"),
+        ("GameInfo_GodBall.GameInfo.GameInfo_GodBall:GameReplicationInfoArchetype", "TAGame.GRI_TA"),
+        ("Gameinfo_Hockey.GameInfo.Gameinfo_Hockey:GameReplicationInfoArchetype", "TAGame.GRI_TA"),
+        ("GameInfo_Items.GameInfo.GameInfo_Items:GameReplicationInfoArchetype", "TAGame.GRI_TA"),
+        ("GameInfo_Season.GameInfo.GameInfo_Season:GameReplicationInfoArchetype", "TAGame.GRI_TA"),
+        ("GameInfo_Soccar.GameInfo.GameInfo_Soccar:GameReplicationInfoArchetype", "TAGame.GRI_TA"),
+        ("GameInfo_Tutorial.GameEvent.GameEvent_Tutorial_Aerial", "TAGame.GameEvent_Tutorial_TA"),
+        ("GameInfo_Tutorial.GameInfo.GameInfo_Tutorial:GameReplicationInfoArchetype", "TAGame.GRI_TA"),
+        ("Haunted_TrainStation_P.TheWorld:PersistentLevel.HauntedBallTrapTrigger_TA_0", "TAGame.HauntedBallTrapTrigger_TA"),
+        ("Haunted_TrainStation_P.TheWorld:PersistentLevel.HauntedBallTrapTrigger_TA_1", "TAGame.HauntedBallTrapTrigger_TA"),
+        ("ProjectX.Default__NetModeReplicator_X", "ProjectX.NetModeReplicator"),
+        ("TAGame.Default__CameraSettingsActor_TA", "TAGame.CameraSettingsActor_TA"),
+        ("TAGame.Default__MaxTimeWarningData_TA", "TAGame.MaxTimeWarningData_TA"),
+        ("TAGame.Default__PickupTimer_TA", "TAGame.PickupTimer_TA"),
+        ("TAGame.Default__PRI_TA", "TAGame.PRI_TA"),
+        ("TAGame.Default__RumblePickups_TA", "TAGame.RumblePickups_TA"),
+        ("TheWorld:PersistentLevel.BreakOutActor_Platform_TA", "TAGame.BreakOutActor_Platform_TA"),
+        ("TheWorld:PersistentLevel.CrowdActor_TA", "TAGame.CrowdActor_TA"),
+        ("TheWorld:PersistentLevel.CrowdManager_TA", "TAGame.CrowdManager_TA"),
+        ("TheWorld:PersistentLevel.InMapScoreboard_TA", "TAGame.InMapScoreboard_TA"),
+        ("TheWorld:PersistentLevel.VehiclePickup_Boost_TA", "TAGame.VehiclePickup_Boost_TA")
+      ]
 
 attributeTypes :: Map.Map Text.Text AttributeType.AttributeType
-attributeTypes = Map.fromList $ fmap
-  (Bifunctor.first Text.pack)
-  [ ("Engine.Actor:bBlockActors", AttributeType.Boolean)
-  , ("Engine.Actor:bCollideActors", AttributeType.Boolean)
-  , ("Engine.Actor:bHidden", AttributeType.Boolean)
-  , ("Engine.Actor:bTearOff", AttributeType.Boolean)
-  , ("Engine.Actor:DrawScale", AttributeType.Float)
-  , ("Engine.Actor:RemoteRole", AttributeType.Enum)
-  , ("Engine.Actor:Role", AttributeType.Enum)
-  , ("Engine.Actor:Rotation", AttributeType.Rotation)
-  , ("Engine.GameReplicationInfo:bMatchIsOver", AttributeType.Boolean)
-  , ("Engine.GameReplicationInfo:GameClass", AttributeType.FlaggedInt)
-  , ("Engine.GameReplicationInfo:ServerName", AttributeType.String)
-  , ("Engine.Pawn:HealthMax", AttributeType.Int)
-  , ("Engine.Pawn:PlayerReplicationInfo", AttributeType.FlaggedInt)
-  , ("Engine.PlayerReplicationInfo:bBot", AttributeType.Boolean)
-  , ("Engine.PlayerReplicationInfo:bIsSpectator", AttributeType.Boolean)
-  , ("Engine.PlayerReplicationInfo:bReadyToPlay", AttributeType.Boolean)
-  , ("Engine.PlayerReplicationInfo:bTimedOut", AttributeType.Boolean)
-  , ("Engine.PlayerReplicationInfo:bWaitingPlayer", AttributeType.Boolean)
-  , ("Engine.PlayerReplicationInfo:Ping", AttributeType.Byte)
-  , ("Engine.PlayerReplicationInfo:PlayerID", AttributeType.Int)
-  , ("Engine.PlayerReplicationInfo:PlayerName", AttributeType.String)
-  , ("Engine.PlayerReplicationInfo:RemoteUserData", AttributeType.String)
-  , ("Engine.PlayerReplicationInfo:Score", AttributeType.Int)
-  , ("Engine.PlayerReplicationInfo:Team", AttributeType.FlaggedInt)
-  , ("Engine.PlayerReplicationInfo:UniqueId", AttributeType.UniqueId)
-  , ("Engine.ReplicatedActor_ORS:ReplicatedOwner", AttributeType.FlaggedInt)
-  , ("Engine.TeamInfo:Score", AttributeType.Int)
-  , ("ProjectX.GRI_X:bGameStarted", AttributeType.Boolean)
-  , ("ProjectX.GRI_X:GameServerID", AttributeType.GameServer)
-  , ("ProjectX.GRI_X:MatchGuid", AttributeType.String)
-  , ("ProjectX.GRI_X:MatchGUID", AttributeType.String)
-  , ("ProjectX.GRI_X:ReplicatedGameMutatorIndex", AttributeType.Int)
-  , ("ProjectX.GRI_X:ReplicatedGamePlaylist", AttributeType.Int)
-  , ("ProjectX.GRI_X:ReplicatedServerRegion", AttributeType.String)
-  , ("ProjectX.GRI_X:Reservations", AttributeType.Reservation)
-  , ("TAGame.Ball_Breakout_TA:AppliedDamage", AttributeType.AppliedDamage)
-  , ("TAGame.Ball_Breakout_TA:DamageIndex", AttributeType.Int)
-  , ("TAGame.Ball_Breakout_TA:LastTeamTouch", AttributeType.Byte)
-  , ("TAGame.Ball_God_TA:TargetSpeed", AttributeType.Float)
-  , ("TAGame.Ball_Haunted_TA:bIsBallBeamed", AttributeType.Boolean)
-  , ("TAGame.Ball_Haunted_TA:DeactivatedGoalIndex", AttributeType.Byte)
-  , ("TAGame.Ball_Haunted_TA:LastTeamTouch", AttributeType.Byte)
-  , ("TAGame.Ball_Haunted_TA:ReplicatedBeamBrokenValue", AttributeType.Byte)
-  , ("TAGame.Ball_Haunted_TA:TotalActiveBeams", AttributeType.Byte)
-  , ("TAGame.Ball_TA:GameEvent", AttributeType.FlaggedInt)
-  , ("TAGame.Ball_TA:HitTeamNum", AttributeType.Byte)
-  , ("TAGame.Ball_TA:ReplicatedAddedCarBounceScale", AttributeType.Float)
-  , ("TAGame.Ball_TA:ReplicatedBallMaxLinearSpeedScale", AttributeType.Float)
-  , ("TAGame.Ball_TA:ReplicatedBallScale", AttributeType.Float)
-  , ("TAGame.Ball_TA:ReplicatedExplosionData", AttributeType.Explosion)
-  , ("TAGame.Ball_TA:ReplicatedExplosionDataExtended", AttributeType.ExtendedExplosion)
-  , ("TAGame.Ball_TA:ReplicatedPhysMatOverride", AttributeType.FlaggedInt)
-  , ("TAGame.Ball_TA:ReplicatedWorldBounceScale", AttributeType.Float)
-  , ("TAGame.BreakOutActor_Platform_TA:DamageState", AttributeType.DamageState)
-  , ("TAGame.CameraSettingsActor_TA:bMouseCameraToggleEnabled", AttributeType.Boolean)
-  , ("TAGame.CameraSettingsActor_TA:bUsingBehindView", AttributeType.Boolean)
-  , ("TAGame.CameraSettingsActor_TA:bUsingSecondaryCamera", AttributeType.Boolean)
-  , ("TAGame.CameraSettingsActor_TA:bUsingSwivel", AttributeType.Boolean)
-  , ("TAGame.CameraSettingsActor_TA:CameraPitch", AttributeType.Byte)
-  , ("TAGame.CameraSettingsActor_TA:CameraYaw", AttributeType.Byte)
-  , ("TAGame.CameraSettingsActor_TA:PRI", AttributeType.FlaggedInt)
-  , ("TAGame.CameraSettingsActor_TA:ProfileSettings", AttributeType.CamSettings)
-  , ("TAGame.Cannon_TA:FireCount", AttributeType.Byte)
-  , ("TAGame.Cannon_TA:Pitch", AttributeType.Float)
-  , ("TAGame.Car_TA:AddedBallForceMultiplier", AttributeType.Float)
-  , ("TAGame.Car_TA:AddedCarForceMultiplier", AttributeType.Float)
-  , ("TAGame.Car_TA:AttachedPickup", AttributeType.FlaggedInt)
-  , ("TAGame.Car_TA:ClubColors", AttributeType.ClubColors)
-  , ("TAGame.Car_TA:ReplicatedCarScale", AttributeType.Float)
-  , ("TAGame.Car_TA:ReplicatedDemolish_CustomFX", AttributeType.CustomDemolish)
-  , ("TAGame.Car_TA:ReplicatedDemolish", AttributeType.Demolish)
-  , ("TAGame.Car_TA:ReplicatedDemolishGoalExplosion", AttributeType.CustomDemolish)
-  , ("TAGame.Car_TA:RumblePickups", AttributeType.FlaggedInt)
-  , ("TAGame.Car_TA:TeamPaint", AttributeType.TeamPaint)
-  , ("TAGame.CarComponent_Boost_TA:bNoBoost", AttributeType.Boolean)
-  , ("TAGame.CarComponent_Boost_TA:BoostModifier", AttributeType.Float)
-  , ("TAGame.CarComponent_Boost_TA:bUnlimitedBoost", AttributeType.Boolean)
-  , ("TAGame.CarComponent_Boost_TA:RechargeDelay", AttributeType.Float)
-  , ("TAGame.CarComponent_Boost_TA:RechargeRate", AttributeType.Float)
-  , ("TAGame.CarComponent_Boost_TA:ReplicatedBoostAmount", AttributeType.Byte)
-  , ("TAGame.CarComponent_Boost_TA:UnlimitedBoostRefCount", AttributeType.Int)
-  , ("TAGame.CarComponent_Dodge_TA:DodgeImpulse", AttributeType.Location)
-  , ("TAGame.CarComponent_Dodge_TA:DodgeTorque", AttributeType.Location)
-  , ("TAGame.CarComponent_DoubleJump_TA:DoubleJumpImpulse", AttributeType.Location)
-  , ("TAGame.CarComponent_FlipCar_TA:bFlipRight", AttributeType.Boolean)
-  , ("TAGame.CarComponent_FlipCar_TA:FlipCarTime", AttributeType.Float)
-  , ("TAGame.CarComponent_TA:ReplicatedActive", AttributeType.Byte)
-  , ("TAGame.CarComponent_TA:ReplicatedActivityTime", AttributeType.Float)
-  , ("TAGame.CarComponent_TA:Vehicle", AttributeType.FlaggedInt)
-  , ("TAGame.CrowdActor_TA:GameEvent", AttributeType.FlaggedInt)
-  , ("TAGame.CrowdActor_TA:ModifiedNoise", AttributeType.Float)
-  , ("TAGame.CrowdActor_TA:ReplicatedCountDownNumber", AttributeType.Int)
-  , ("TAGame.CrowdActor_TA:ReplicatedOneShotSound", AttributeType.FlaggedInt)
-  , ("TAGame.CrowdActor_TA:ReplicatedRoundCountDownNumber", AttributeType.Int)
-  , ("TAGame.CrowdManager_TA:GameEvent", AttributeType.FlaggedInt)
-  , ("TAGame.CrowdManager_TA:ReplicatedGlobalOneShotSound", AttributeType.FlaggedInt)
-  , ("TAGame.GameEvent_Soccar_TA:bBallHasBeenHit", AttributeType.Boolean)
-  , ("TAGame.GameEvent_Soccar_TA:bClubMatch", AttributeType.Boolean)
-  , ("TAGame.GameEvent_Soccar_TA:bMatchEnded", AttributeType.Boolean)
-  , ("TAGame.GameEvent_Soccar_TA:bNoContest", AttributeType.Boolean)
-  , ("TAGame.GameEvent_Soccar_TA:bOverTime", AttributeType.Boolean)
-  , ("TAGame.GameEvent_Soccar_TA:bUnlimitedTime", AttributeType.Boolean)
-  , ("TAGame.GameEvent_Soccar_TA:GameTime", AttributeType.Int)
-  , ("TAGame.GameEvent_Soccar_TA:GameWinner", AttributeType.FlaggedInt)
-  , ("TAGame.GameEvent_Soccar_TA:MatchWinner", AttributeType.FlaggedInt)
-  , ("TAGame.GameEvent_Soccar_TA:MaxScore", AttributeType.Int)
-  , ("TAGame.GameEvent_Soccar_TA:MVP", AttributeType.FlaggedInt)
-  , ("TAGame.GameEvent_Soccar_TA:ReplicatedMusicStinger", AttributeType.MusicStinger)
-  , ("TAGame.GameEvent_Soccar_TA:ReplicatedScoredOnTeam", AttributeType.Byte)
-  , ("TAGame.GameEvent_Soccar_TA:ReplicatedServerPerformanceState", AttributeType.Byte)
-  , ("TAGame.GameEvent_Soccar_TA:ReplicatedStatEvent", AttributeType.StatEvent)
-  , ("TAGame.GameEvent_Soccar_TA:RoundNum", AttributeType.Int)
-  , ("TAGame.GameEvent_Soccar_TA:SecondsRemaining", AttributeType.Int)
-  , ("TAGame.GameEvent_Soccar_TA:SeriesLength", AttributeType.Int)
-  , ("TAGame.GameEvent_Soccar_TA:SubRulesArchetype", AttributeType.FlaggedInt)
-  , ("TAGame.GameEvent_SoccarPrivate_TA:MatchSettings", AttributeType.PrivateMatchSettings)
-  , ("TAGame.GameEvent_TA:bAllowReadyUp", AttributeType.Boolean)
-  , ("TAGame.GameEvent_TA:bCanVoteToForfeit", AttributeType.Boolean)
-  , ("TAGame.GameEvent_TA:bHasLeaveMatchPenalty", AttributeType.Boolean)
-  , ("TAGame.GameEvent_TA:BotSkill", AttributeType.Int)
-  , ("TAGame.GameEvent_TA:GameMode", AttributeType.GameMode)
-  , ("TAGame.GameEvent_TA:MatchTypeClass", AttributeType.FlaggedInt)
-  , ("TAGame.GameEvent_TA:ReplicatedGameStateTimeRemaining", AttributeType.Int)
-  , ("TAGame.GameEvent_TA:ReplicatedRoundCountDownNumber", AttributeType.Int)
-  , ("TAGame.GameEvent_TA:ReplicatedStateIndex", AttributeType.Byte)
-  , ("TAGame.GameEvent_TA:ReplicatedStateName", AttributeType.Int)
-  , ("TAGame.GameEvent_Team_TA:bForfeit", AttributeType.Boolean)
-  , ("TAGame.GameEvent_Team_TA:MaxTeamSize", AttributeType.Int)
-  , ("TAGame.GRI_TA:NewDedicatedServerIP", AttributeType.String)
-  , ("TAGame.MaxTimeWarningData_TA:EndGameEpochTime", AttributeType.Int64)
-  , ("TAGame.MaxTimeWarningData_TA:EndGameWarningEpochTime", AttributeType.Int64)
-  , ("TAGame.PRI_TA:bIsDistracted", AttributeType.Boolean)
-  , ("TAGame.PRI_TA:bIsInSplitScreen", AttributeType.Boolean)
-  , ("TAGame.PRI_TA:bMatchMVP", AttributeType.Boolean)
-  , ("TAGame.PRI_TA:bOnlineLoadoutSet", AttributeType.Boolean)
-  , ("TAGame.PRI_TA:bOnlineLoadoutsSet", AttributeType.Boolean)
-  , ("TAGame.PRI_TA:BotProductName", AttributeType.Int)
-  , ("TAGame.PRI_TA:bReady", AttributeType.Boolean)
-  , ("TAGame.PRI_TA:bUsingBehindView", AttributeType.Boolean)
-  , ("TAGame.PRI_TA:bUsingItems", AttributeType.Boolean)
-  , ("TAGame.PRI_TA:bUsingSecondaryCamera", AttributeType.Boolean)
-  , ("TAGame.PRI_TA:CameraPitch", AttributeType.Byte)
-  , ("TAGame.PRI_TA:CameraSettings", AttributeType.CamSettings)
-  , ("TAGame.PRI_TA:CameraYaw", AttributeType.Byte)
-  , ("TAGame.PRI_TA:ClientLoadout", AttributeType.Loadout)
-  , ("TAGame.PRI_TA:ClientLoadoutOnline", AttributeType.LoadoutOnline)
-  , ("TAGame.PRI_TA:ClientLoadouts", AttributeType.Loadouts)
-  , ("TAGame.PRI_TA:ClientLoadoutsOnline", AttributeType.LoadoutsOnline)
-  , ("TAGame.PRI_TA:ClubID", AttributeType.Int64)
-  , ("TAGame.PRI_TA:CurrentVoiceRoom", AttributeType.String)
-  , ("TAGame.PRI_TA:MatchAssists", AttributeType.Int)
-  , ("TAGame.PRI_TA:MatchBreakoutDamage", AttributeType.Int)
-  , ("TAGame.PRI_TA:MatchGoals", AttributeType.Int)
-  , ("TAGame.PRI_TA:MatchSaves", AttributeType.Int)
-  , ("TAGame.PRI_TA:MatchScore", AttributeType.Int)
-  , ("TAGame.PRI_TA:MatchShots", AttributeType.Int)
-  , ("TAGame.PRI_TA:MaxTimeTillItem", AttributeType.Int)
-  , ("TAGame.PRI_TA:PartyLeader", AttributeType.PartyLeader)
-  , ("TAGame.PRI_TA:PawnType", AttributeType.Byte)
-  , ("TAGame.PRI_TA:PersistentCamera", AttributeType.FlaggedInt)
-  , ("TAGame.PRI_TA:PlayerHistoryKey", AttributeType.PlayerHistoryKey)
-  , ("TAGame.PRI_TA:PlayerHistoryValid", AttributeType.Boolean)
-  , ("TAGame.PRI_TA:PrimaryTitle", AttributeType.Title)
-  , ("TAGame.PRI_TA:ReplicatedGameEvent", AttributeType.FlaggedInt)
-  , ("TAGame.PRI_TA:ReplicatedWorstNetQualityBeyondLatency", AttributeType.Byte)
-  , ("TAGame.PRI_TA:RepStatTitles", AttributeType.RepStatTitle)
-  , ("TAGame.PRI_TA:SecondaryTitle", AttributeType.Title)
-  , ("TAGame.PRI_TA:SkillTier", AttributeType.FlaggedByte)
-  , ("TAGame.PRI_TA:SpectatorShortcut", AttributeType.Int)
-  , ("TAGame.PRI_TA:SteeringSensitivity", AttributeType.Float)
-  , ("TAGame.PRI_TA:TimeTillItem", AttributeType.Int)
-  , ("TAGame.PRI_TA:Title", AttributeType.Int)
-  , ("TAGame.PRI_TA:TotalXP", AttributeType.Int)
-  , ("TAGame.RBActor_TA:bFrozen", AttributeType.Boolean)
-  , ("TAGame.RBActor_TA:bIgnoreSyncing", AttributeType.Boolean)
-  , ("TAGame.RBActor_TA:bReplayActor", AttributeType.Boolean)
-  , ("TAGame.RBActor_TA:ReplicatedRBState", AttributeType.RigidBodyState)
-  , ("TAGame.RBActor_TA:WeldedInfo", AttributeType.WeldedInfo)
-  , ("TAGame.RumblePickups_TA:AttachedPickup", AttributeType.FlaggedInt)
-  , ("TAGame.RumblePickups_TA:ConcurrentItemCount", AttributeType.Int)
-  , ("TAGame.RumblePickups_TA:PickupInfo", AttributeType.PickupInfo)
-  , ("TAGame.SpecialPickup_BallFreeze_TA:RepOrigSpeed", AttributeType.Float)
-  , ("TAGame.SpecialPickup_BallVelcro_TA:AttachTime", AttributeType.Float)
-  , ("TAGame.SpecialPickup_BallVelcro_TA:bBroken", AttributeType.Boolean)
-  , ("TAGame.SpecialPickup_BallVelcro_TA:bHit", AttributeType.Boolean)
-  , ("TAGame.SpecialPickup_BallVelcro_TA:BreakTime", AttributeType.Float)
-  , ("TAGame.SpecialPickup_Football_TA:WeldedBall", AttributeType.FlaggedInt)
-  , ("TAGame.SpecialPickup_Rugby_TA:bBallWelded", AttributeType.Boolean)
-  , ("TAGame.SpecialPickup_Targeted_TA:Targeted", AttributeType.FlaggedInt)
-  , ("TAGame.Team_Soccar_TA:GameScore", AttributeType.Int)
-  , ("TAGame.Team_TA:ClubColors", AttributeType.ClubColors)
-  , ("TAGame.Team_TA:ClubID", AttributeType.Int64)
-  , ("TAGame.Team_TA:CustomTeamName", AttributeType.String)
-  , ("TAGame.Team_TA:Difficulty", AttributeType.Int)
-  , ("TAGame.Team_TA:GameEvent", AttributeType.FlaggedInt)
-  , ("TAGame.Team_TA:LogoData", AttributeType.FlaggedInt)
-  , ("TAGame.Vehicle_TA:bDriving", AttributeType.Boolean)
-  , ("TAGame.Vehicle_TA:bPodiumMode", AttributeType.Boolean)
-  , ("TAGame.Vehicle_TA:bReplicatedHandbrake", AttributeType.Boolean)
-  , ("TAGame.Vehicle_TA:ReplicatedSteer", AttributeType.Byte)
-  , ("TAGame.Vehicle_TA:ReplicatedThrottle", AttributeType.Byte)
-  , ("TAGame.VehiclePickup_TA:bNoPickup", AttributeType.Boolean)
-  , ("TAGame.VehiclePickup_TA:NewReplicatedPickupData", AttributeType.PickupNew)
-  , ("TAGame.VehiclePickup_TA:ReplicatedPickupData", AttributeType.Pickup)
-  ]
+attributeTypes =
+  Map.fromList $
+    fmap
+      (Bifunctor.first Text.pack)
+      [ ("Engine.Actor:bBlockActors", AttributeType.Boolean),
+        ("Engine.Actor:bCollideActors", AttributeType.Boolean),
+        ("Engine.Actor:bHidden", AttributeType.Boolean),
+        ("Engine.Actor:bTearOff", AttributeType.Boolean),
+        ("Engine.Actor:DrawScale", AttributeType.Float),
+        ("Engine.Actor:RemoteRole", AttributeType.Enum),
+        ("Engine.Actor:Role", AttributeType.Enum),
+        ("Engine.Actor:Rotation", AttributeType.Rotation),
+        ("Engine.GameReplicationInfo:bMatchIsOver", AttributeType.Boolean),
+        ("Engine.GameReplicationInfo:GameClass", AttributeType.FlaggedInt),
+        ("Engine.GameReplicationInfo:ServerName", AttributeType.String),
+        ("Engine.Pawn:HealthMax", AttributeType.Int),
+        ("Engine.Pawn:PlayerReplicationInfo", AttributeType.FlaggedInt),
+        ("Engine.PlayerReplicationInfo:bBot", AttributeType.Boolean),
+        ("Engine.PlayerReplicationInfo:bIsSpectator", AttributeType.Boolean),
+        ("Engine.PlayerReplicationInfo:bReadyToPlay", AttributeType.Boolean),
+        ("Engine.PlayerReplicationInfo:bTimedOut", AttributeType.Boolean),
+        ("Engine.PlayerReplicationInfo:bWaitingPlayer", AttributeType.Boolean),
+        ("Engine.PlayerReplicationInfo:Ping", AttributeType.Byte),
+        ("Engine.PlayerReplicationInfo:PlayerID", AttributeType.Int),
+        ("Engine.PlayerReplicationInfo:PlayerName", AttributeType.String),
+        ("Engine.PlayerReplicationInfo:RemoteUserData", AttributeType.String),
+        ("Engine.PlayerReplicationInfo:Score", AttributeType.Int),
+        ("Engine.PlayerReplicationInfo:Team", AttributeType.FlaggedInt),
+        ("Engine.PlayerReplicationInfo:UniqueId", AttributeType.UniqueId),
+        ("Engine.ReplicatedActor_ORS:ReplicatedOwner", AttributeType.FlaggedInt),
+        ("Engine.TeamInfo:Score", AttributeType.Int),
+        ("ProjectX.GRI_X:bGameStarted", AttributeType.Boolean),
+        ("ProjectX.GRI_X:GameServerID", AttributeType.GameServer),
+        ("ProjectX.GRI_X:MatchGuid", AttributeType.String),
+        ("ProjectX.GRI_X:MatchGUID", AttributeType.String),
+        ("ProjectX.GRI_X:ReplicatedGameMutatorIndex", AttributeType.Int),
+        ("ProjectX.GRI_X:ReplicatedGamePlaylist", AttributeType.Int),
+        ("ProjectX.GRI_X:ReplicatedServerRegion", AttributeType.String),
+        ("ProjectX.GRI_X:Reservations", AttributeType.Reservation),
+        ("TAGame.Ball_Breakout_TA:AppliedDamage", AttributeType.AppliedDamage),
+        ("TAGame.Ball_Breakout_TA:DamageIndex", AttributeType.Int),
+        ("TAGame.Ball_Breakout_TA:LastTeamTouch", AttributeType.Byte),
+        ("TAGame.Ball_God_TA:TargetSpeed", AttributeType.Float),
+        ("TAGame.Ball_Haunted_TA:bIsBallBeamed", AttributeType.Boolean),
+        ("TAGame.Ball_Haunted_TA:DeactivatedGoalIndex", AttributeType.Byte),
+        ("TAGame.Ball_Haunted_TA:LastTeamTouch", AttributeType.Byte),
+        ("TAGame.Ball_Haunted_TA:ReplicatedBeamBrokenValue", AttributeType.Byte),
+        ("TAGame.Ball_Haunted_TA:TotalActiveBeams", AttributeType.Byte),
+        ("TAGame.Ball_TA:GameEvent", AttributeType.FlaggedInt),
+        ("TAGame.Ball_TA:HitTeamNum", AttributeType.Byte),
+        ("TAGame.Ball_TA:ReplicatedAddedCarBounceScale", AttributeType.Float),
+        ("TAGame.Ball_TA:ReplicatedBallMaxLinearSpeedScale", AttributeType.Float),
+        ("TAGame.Ball_TA:ReplicatedBallScale", AttributeType.Float),
+        ("TAGame.Ball_TA:ReplicatedExplosionData", AttributeType.Explosion),
+        ("TAGame.Ball_TA:ReplicatedExplosionDataExtended", AttributeType.ExtendedExplosion),
+        ("TAGame.Ball_TA:ReplicatedPhysMatOverride", AttributeType.FlaggedInt),
+        ("TAGame.Ball_TA:ReplicatedWorldBounceScale", AttributeType.Float),
+        ("TAGame.BreakOutActor_Platform_TA:DamageState", AttributeType.DamageState),
+        ("TAGame.CameraSettingsActor_TA:bMouseCameraToggleEnabled", AttributeType.Boolean),
+        ("TAGame.CameraSettingsActor_TA:bUsingBehindView", AttributeType.Boolean),
+        ("TAGame.CameraSettingsActor_TA:bUsingSecondaryCamera", AttributeType.Boolean),
+        ("TAGame.CameraSettingsActor_TA:bUsingSwivel", AttributeType.Boolean),
+        ("TAGame.CameraSettingsActor_TA:CameraPitch", AttributeType.Byte),
+        ("TAGame.CameraSettingsActor_TA:CameraYaw", AttributeType.Byte),
+        ("TAGame.CameraSettingsActor_TA:PRI", AttributeType.FlaggedInt),
+        ("TAGame.CameraSettingsActor_TA:ProfileSettings", AttributeType.CamSettings),
+        ("TAGame.Cannon_TA:FireCount", AttributeType.Byte),
+        ("TAGame.Cannon_TA:Pitch", AttributeType.Float),
+        ("TAGame.Car_TA:AddedBallForceMultiplier", AttributeType.Float),
+        ("TAGame.Car_TA:AddedCarForceMultiplier", AttributeType.Float),
+        ("TAGame.Car_TA:AttachedPickup", AttributeType.FlaggedInt),
+        ("TAGame.Car_TA:ClubColors", AttributeType.ClubColors),
+        ("TAGame.Car_TA:ReplicatedCarScale", AttributeType.Float),
+        ("TAGame.Car_TA:ReplicatedDemolish_CustomFX", AttributeType.CustomDemolish),
+        ("TAGame.Car_TA:ReplicatedDemolish", AttributeType.Demolish),
+        ("TAGame.Car_TA:ReplicatedDemolishGoalExplosion", AttributeType.CustomDemolish),
+        ("TAGame.Car_TA:RumblePickups", AttributeType.FlaggedInt),
+        ("TAGame.Car_TA:TeamPaint", AttributeType.TeamPaint),
+        ("TAGame.CarComponent_Boost_TA:bNoBoost", AttributeType.Boolean),
+        ("TAGame.CarComponent_Boost_TA:BoostModifier", AttributeType.Float),
+        ("TAGame.CarComponent_Boost_TA:bUnlimitedBoost", AttributeType.Boolean),
+        ("TAGame.CarComponent_Boost_TA:RechargeDelay", AttributeType.Float),
+        ("TAGame.CarComponent_Boost_TA:RechargeRate", AttributeType.Float),
+        ("TAGame.CarComponent_Boost_TA:ReplicatedBoostAmount", AttributeType.Byte),
+        ("TAGame.CarComponent_Boost_TA:UnlimitedBoostRefCount", AttributeType.Int),
+        ("TAGame.CarComponent_Dodge_TA:DodgeImpulse", AttributeType.Location),
+        ("TAGame.CarComponent_Dodge_TA:DodgeTorque", AttributeType.Location),
+        ("TAGame.CarComponent_DoubleJump_TA:DoubleJumpImpulse", AttributeType.Location),
+        ("TAGame.CarComponent_FlipCar_TA:bFlipRight", AttributeType.Boolean),
+        ("TAGame.CarComponent_FlipCar_TA:FlipCarTime", AttributeType.Float),
+        ("TAGame.CarComponent_TA:ReplicatedActive", AttributeType.Byte),
+        ("TAGame.CarComponent_TA:ReplicatedActivityTime", AttributeType.Float),
+        ("TAGame.CarComponent_TA:Vehicle", AttributeType.FlaggedInt),
+        ("TAGame.CrowdActor_TA:GameEvent", AttributeType.FlaggedInt),
+        ("TAGame.CrowdActor_TA:ModifiedNoise", AttributeType.Float),
+        ("TAGame.CrowdActor_TA:ReplicatedCountDownNumber", AttributeType.Int),
+        ("TAGame.CrowdActor_TA:ReplicatedOneShotSound", AttributeType.FlaggedInt),
+        ("TAGame.CrowdActor_TA:ReplicatedRoundCountDownNumber", AttributeType.Int),
+        ("TAGame.CrowdManager_TA:GameEvent", AttributeType.FlaggedInt),
+        ("TAGame.CrowdManager_TA:ReplicatedGlobalOneShotSound", AttributeType.FlaggedInt),
+        ("TAGame.GameEvent_Soccar_TA:bBallHasBeenHit", AttributeType.Boolean),
+        ("TAGame.GameEvent_Soccar_TA:bClubMatch", AttributeType.Boolean),
+        ("TAGame.GameEvent_Soccar_TA:bMatchEnded", AttributeType.Boolean),
+        ("TAGame.GameEvent_Soccar_TA:bNoContest", AttributeType.Boolean),
+        ("TAGame.GameEvent_Soccar_TA:bOverTime", AttributeType.Boolean),
+        ("TAGame.GameEvent_Soccar_TA:bUnlimitedTime", AttributeType.Boolean),
+        ("TAGame.GameEvent_Soccar_TA:GameTime", AttributeType.Int),
+        ("TAGame.GameEvent_Soccar_TA:GameWinner", AttributeType.FlaggedInt),
+        ("TAGame.GameEvent_Soccar_TA:MatchWinner", AttributeType.FlaggedInt),
+        ("TAGame.GameEvent_Soccar_TA:MaxScore", AttributeType.Int),
+        ("TAGame.GameEvent_Soccar_TA:MVP", AttributeType.FlaggedInt),
+        ("TAGame.GameEvent_Soccar_TA:ReplicatedMusicStinger", AttributeType.MusicStinger),
+        ("TAGame.GameEvent_Soccar_TA:ReplicatedScoredOnTeam", AttributeType.Byte),
+        ("TAGame.GameEvent_Soccar_TA:ReplicatedServerPerformanceState", AttributeType.Byte),
+        ("TAGame.GameEvent_Soccar_TA:ReplicatedStatEvent", AttributeType.StatEvent),
+        ("TAGame.GameEvent_Soccar_TA:RoundNum", AttributeType.Int),
+        ("TAGame.GameEvent_Soccar_TA:SecondsRemaining", AttributeType.Int),
+        ("TAGame.GameEvent_Soccar_TA:SeriesLength", AttributeType.Int),
+        ("TAGame.GameEvent_Soccar_TA:SubRulesArchetype", AttributeType.FlaggedInt),
+        ("TAGame.GameEvent_SoccarPrivate_TA:MatchSettings", AttributeType.PrivateMatchSettings),
+        ("TAGame.GameEvent_TA:bAllowReadyUp", AttributeType.Boolean),
+        ("TAGame.GameEvent_TA:bCanVoteToForfeit", AttributeType.Boolean),
+        ("TAGame.GameEvent_TA:bHasLeaveMatchPenalty", AttributeType.Boolean),
+        ("TAGame.GameEvent_TA:BotSkill", AttributeType.Int),
+        ("TAGame.GameEvent_TA:GameMode", AttributeType.GameMode),
+        ("TAGame.GameEvent_TA:MatchTypeClass", AttributeType.FlaggedInt),
+        ("TAGame.GameEvent_TA:ReplicatedGameStateTimeRemaining", AttributeType.Int),
+        ("TAGame.GameEvent_TA:ReplicatedRoundCountDownNumber", AttributeType.Int),
+        ("TAGame.GameEvent_TA:ReplicatedStateIndex", AttributeType.Byte),
+        ("TAGame.GameEvent_TA:ReplicatedStateName", AttributeType.Int),
+        ("TAGame.GameEvent_Team_TA:bForfeit", AttributeType.Boolean),
+        ("TAGame.GameEvent_Team_TA:MaxTeamSize", AttributeType.Int),
+        ("TAGame.GRI_TA:NewDedicatedServerIP", AttributeType.String),
+        ("TAGame.MaxTimeWarningData_TA:EndGameEpochTime", AttributeType.Int64),
+        ("TAGame.MaxTimeWarningData_TA:EndGameWarningEpochTime", AttributeType.Int64),
+        ("TAGame.PRI_TA:bIsDistracted", AttributeType.Boolean),
+        ("TAGame.PRI_TA:bIsInSplitScreen", AttributeType.Boolean),
+        ("TAGame.PRI_TA:bMatchMVP", AttributeType.Boolean),
+        ("TAGame.PRI_TA:bOnlineLoadoutSet", AttributeType.Boolean),
+        ("TAGame.PRI_TA:bOnlineLoadoutsSet", AttributeType.Boolean),
+        ("TAGame.PRI_TA:BotProductName", AttributeType.Int),
+        ("TAGame.PRI_TA:bReady", AttributeType.Boolean),
+        ("TAGame.PRI_TA:bUsingBehindView", AttributeType.Boolean),
+        ("TAGame.PRI_TA:bUsingItems", AttributeType.Boolean),
+        ("TAGame.PRI_TA:bUsingSecondaryCamera", AttributeType.Boolean),
+        ("TAGame.PRI_TA:CameraPitch", AttributeType.Byte),
+        ("TAGame.PRI_TA:CameraSettings", AttributeType.CamSettings),
+        ("TAGame.PRI_TA:CameraYaw", AttributeType.Byte),
+        ("TAGame.PRI_TA:ClientLoadout", AttributeType.Loadout),
+        ("TAGame.PRI_TA:ClientLoadoutOnline", AttributeType.LoadoutOnline),
+        ("TAGame.PRI_TA:ClientLoadouts", AttributeType.Loadouts),
+        ("TAGame.PRI_TA:ClientLoadoutsOnline", AttributeType.LoadoutsOnline),
+        ("TAGame.PRI_TA:ClubID", AttributeType.Int64),
+        ("TAGame.PRI_TA:CurrentVoiceRoom", AttributeType.String),
+        ("TAGame.PRI_TA:MatchAssists", AttributeType.Int),
+        ("TAGame.PRI_TA:MatchBreakoutDamage", AttributeType.Int),
+        ("TAGame.PRI_TA:MatchGoals", AttributeType.Int),
+        ("TAGame.PRI_TA:MatchSaves", AttributeType.Int),
+        ("TAGame.PRI_TA:MatchScore", AttributeType.Int),
+        ("TAGame.PRI_TA:MatchShots", AttributeType.Int),
+        ("TAGame.PRI_TA:MaxTimeTillItem", AttributeType.Int),
+        ("TAGame.PRI_TA:PartyLeader", AttributeType.PartyLeader),
+        ("TAGame.PRI_TA:PawnType", AttributeType.Byte),
+        ("TAGame.PRI_TA:PersistentCamera", AttributeType.FlaggedInt),
+        ("TAGame.PRI_TA:PlayerHistoryKey", AttributeType.PlayerHistoryKey),
+        ("TAGame.PRI_TA:PlayerHistoryValid", AttributeType.Boolean),
+        ("TAGame.PRI_TA:PrimaryTitle", AttributeType.Title),
+        ("TAGame.PRI_TA:ReplicatedGameEvent", AttributeType.FlaggedInt),
+        ("TAGame.PRI_TA:ReplicatedWorstNetQualityBeyondLatency", AttributeType.Byte),
+        ("TAGame.PRI_TA:RepStatTitles", AttributeType.RepStatTitle),
+        ("TAGame.PRI_TA:SecondaryTitle", AttributeType.Title),
+        ("TAGame.PRI_TA:SkillTier", AttributeType.FlaggedByte),
+        ("TAGame.PRI_TA:SpectatorShortcut", AttributeType.Int),
+        ("TAGame.PRI_TA:SteeringSensitivity", AttributeType.Float),
+        ("TAGame.PRI_TA:TimeTillItem", AttributeType.Int),
+        ("TAGame.PRI_TA:Title", AttributeType.Int),
+        ("TAGame.PRI_TA:TotalXP", AttributeType.Int),
+        ("TAGame.RBActor_TA:bFrozen", AttributeType.Boolean),
+        ("TAGame.RBActor_TA:bIgnoreSyncing", AttributeType.Boolean),
+        ("TAGame.RBActor_TA:bReplayActor", AttributeType.Boolean),
+        ("TAGame.RBActor_TA:ReplicatedRBState", AttributeType.RigidBodyState),
+        ("TAGame.RBActor_TA:WeldedInfo", AttributeType.WeldedInfo),
+        ("TAGame.RumblePickups_TA:AttachedPickup", AttributeType.FlaggedInt),
+        ("TAGame.RumblePickups_TA:ConcurrentItemCount", AttributeType.Int),
+        ("TAGame.RumblePickups_TA:PickupInfo", AttributeType.PickupInfo),
+        ("TAGame.SpecialPickup_BallFreeze_TA:RepOrigSpeed", AttributeType.Float),
+        ("TAGame.SpecialPickup_BallVelcro_TA:AttachTime", AttributeType.Float),
+        ("TAGame.SpecialPickup_BallVelcro_TA:bBroken", AttributeType.Boolean),
+        ("TAGame.SpecialPickup_BallVelcro_TA:bHit", AttributeType.Boolean),
+        ("TAGame.SpecialPickup_BallVelcro_TA:BreakTime", AttributeType.Float),
+        ("TAGame.SpecialPickup_Football_TA:WeldedBall", AttributeType.FlaggedInt),
+        ("TAGame.SpecialPickup_Rugby_TA:bBallWelded", AttributeType.Boolean),
+        ("TAGame.SpecialPickup_Targeted_TA:Targeted", AttributeType.FlaggedInt),
+        ("TAGame.Team_Soccar_TA:GameScore", AttributeType.Int),
+        ("TAGame.Team_TA:ClubColors", AttributeType.ClubColors),
+        ("TAGame.Team_TA:ClubID", AttributeType.Int64),
+        ("TAGame.Team_TA:CustomTeamName", AttributeType.String),
+        ("TAGame.Team_TA:Difficulty", AttributeType.Int),
+        ("TAGame.Team_TA:GameEvent", AttributeType.FlaggedInt),
+        ("TAGame.Team_TA:LogoData", AttributeType.FlaggedInt),
+        ("TAGame.Vehicle_TA:bDriving", AttributeType.Boolean),
+        ("TAGame.Vehicle_TA:bPodiumMode", AttributeType.Boolean),
+        ("TAGame.Vehicle_TA:bReplicatedHandbrake", AttributeType.Boolean),
+        ("TAGame.Vehicle_TA:ReplicatedSteer", AttributeType.Byte),
+        ("TAGame.Vehicle_TA:ReplicatedThrottle", AttributeType.Byte),
+        ("TAGame.VehiclePickup_TA:bNoPickup", AttributeType.Boolean),
+        ("TAGame.VehiclePickup_TA:NewReplicatedPickupData", AttributeType.PickupNew),
+        ("TAGame.VehiclePickup_TA:ReplicatedPickupData", AttributeType.Pickup)
+      ]
diff --git a/src/lib/Rattletrap/Get.hs b/src/lib/Rattletrap/Get.hs
--- a/src/lib/Rattletrap/Get.hs
+++ b/src/lib/Rattletrap/Get.hs
@@ -6,12 +6,12 @@
 import qualified Rattletrap.Exception.Empty as Empty
 import qualified Rattletrap.Exception.Fail as Fail
 
-newtype Get s m a = Get (s -> m (Either ([String], Exception.SomeException)  (s, a)))
+newtype Get s m a = Get (s -> m (Either ([String], Exception.SomeException) (s, a)))
 
-instance Functor m => Functor (Get s m) where
+instance (Functor m) => Functor (Get s m) where
   fmap f g = Get $ fmap (fmap (fmap f)) . run g
 
-instance Monad m => Applicative (Get s m) where
+instance (Monad m) => Applicative (Get s m) where
   pure x = Get $ \s -> pure $ Right (s, x)
 
   gf <*> gx = Get $ \s1 -> do
@@ -20,17 +20,17 @@
       Left e -> pure $ Left e
       Right (s2, f) -> run (fmap f gx) s2
 
-instance Monad m => Monad (Get s m) where
+instance (Monad m) => Monad (Get s m) where
   g >>= f = Get $ \s1 -> do
     r <- run g s1
     case r of
       Left e -> pure $ Left e
       Right (s2, x) -> run (f x) s2
 
-instance Monad m => MonadFail (Get s m) where
+instance (Monad m) => MonadFail (Get s m) where
   fail = throw . Fail.Fail
 
-instance Monad m => Applicative.Alternative (Get s m) where
+instance (Monad m) => Applicative.Alternative (Get s m) where
   empty = throw Empty.Empty
 
   gx <|> gy = Get $ \s -> do
@@ -42,27 +42,27 @@
 run :: Get s m a -> s -> m (Either ([String], Exception.SomeException) (s, a))
 run (Get f) = f
 
-get :: Applicative m => Get s m s
+get :: (Applicative m) => Get s m s
 get = Get $ \s -> pure $ Right (s, s)
 
-put :: Applicative m => s -> Get s m ()
+put :: (Applicative m) => s -> Get s m ()
 put s = Get $ \_ -> pure $ Right (s, ())
 
-lift :: Functor m => m a -> Get s m a
+lift :: (Functor m) => m a -> Get s m a
 lift m = Get $ \s -> fmap (\x -> Right (s, x)) m
 
 throw :: (Exception.Exception e, Applicative m) => e -> Get s m a
 throw = Get . const . pure . Left . (,) [] . Exception.toException
 
-embed :: Monad m => Get s m a -> s -> Get t m a
+embed :: (Monad m) => Get s m a -> s -> Get t m a
 embed g s = do
   r <- lift $ run g s
   case r of
     Left (ls, e) -> labels ls $ throw e
     Right (_, x) -> pure x
 
-labels :: Functor m => [String] -> Get s m a -> Get s m a
+labels :: (Functor m) => [String] -> Get s m a -> Get s m a
 labels ls g = Get $ fmap (Bifunctor.first $ Bifunctor.first (ls <>)) . run g
 
-label :: Functor m => String -> Get s m a -> Get s m a
+label :: (Functor m) => String -> Get s m a -> Get s m a
 label = labels . pure
diff --git a/src/lib/Rattletrap/Schema.hs b/src/lib/Rattletrap/Schema.hs
--- a/src/lib/Rattletrap/Schema.hs
+++ b/src/lib/Rattletrap/Schema.hs
@@ -4,48 +4,53 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data Schema = Schema
-  { name :: Text.Text
-  , json :: Json.Value
+  { name :: Text.Text,
+    json :: Json.Value
   }
   deriving (Eq, Show)
 
 named :: String -> Json.Value -> Schema
-named n j = Schema { name = Text.pack n, json = j }
+named n j = Schema {name = Text.pack n, json = j}
 
 ref :: Schema -> Json.Value
 ref s = Json.object [Json.pair "$ref" $ Text.pack "#/definitions/" <> name s]
 
 object :: [((Json.Key, Json.Value), Bool)] -> Json.Value
-object xs = Json.object
-  [ Json.pair "type" "object"
-  , Json.pair "properties" . Json.object $ fmap
-    ((\(k, v) -> Json.pair (Json.keyToString k) v) . fst)
-    xs
-  , Json.pair "required" . fmap (fst . fst) $ filter snd xs
-  ]
+object xs =
+  Json.object
+    [ Json.pair "type" "object",
+      Json.pair "properties" . Json.object $
+        fmap
+          ((\(k, v) -> Json.pair (Json.keyToString k) v) . fst)
+          xs,
+      Json.pair "required" . fmap (fst . fst) $ filter snd xs
+    ]
 
 maybe :: Schema -> Schema
-maybe s = Schema
-  { name = Text.pack "maybe-" <> name s
-  , json = oneOf [ref s, json Rattletrap.Schema.null]
-  }
+maybe s =
+  Schema
+    { name = Text.pack "maybe-" <> name s,
+      json = oneOf [ref s, json Rattletrap.Schema.null]
+    }
 
 oneOf :: [Json.Value] -> Json.Value
 oneOf xs = Json.object [Json.pair "oneOf" xs]
 
 tuple :: [Json.Value] -> Json.Value
-tuple xs = Json.object
-  [ Json.pair "type" "array"
-  , Json.pair "items" xs
-  , Json.pair "minItems" $ length xs
-  , Json.pair "maxItems" $ length xs
-  ]
+tuple xs =
+  Json.object
+    [ Json.pair "type" "array",
+      Json.pair "items" xs,
+      Json.pair "minItems" $ length xs,
+      Json.pair "maxItems" $ length xs
+    ]
 
 array :: Schema -> Schema
-array s = Schema
-  { name = Text.pack "array-" <> name s
-  , json = Json.object [Json.pair "type" "array", Json.pair "items" $ ref s]
-  }
+array s =
+  Schema
+    { name = Text.pack "array-" <> name s,
+      json = Json.object [Json.pair "type" "array", Json.pair "items" $ ref s]
+    }
 
 boolean :: Schema
 boolean = named "boolean" $ Json.object [Json.pair "type" "boolean"]
diff --git a/src/lib/Rattletrap/Type/Attribute.hs b/src/lib/Rattletrap/Type/Attribute.hs
--- a/src/lib/Rattletrap/Type/Attribute.hs
+++ b/src/lib/Rattletrap/Type/Attribute.hs
@@ -2,7 +2,6 @@
 
 import qualified Control.Exception as Exception
 import qualified Data.Map as Map
-import Prelude hiding (id)
 import qualified Rattletrap.BitGet as BitGet
 import qualified Rattletrap.BitPut as BitPut
 import qualified Rattletrap.Exception.MissingAttributeLimit as MissingAttributeLimit
@@ -16,13 +15,14 @@
 import qualified Rattletrap.Type.U32 as U32
 import qualified Rattletrap.Type.Version as Version
 import qualified Rattletrap.Utility.Json as Json
+import Prelude hiding (id)
 
 data Attribute = Attribute
-  { id :: CompressedWord.CompressedWord
-  , name :: Str.Str
-  -- ^ Read-only! Changing an attribute's name requires editing the class
-  -- attribute map.
-  , value :: AttributeValue.AttributeValue
+  { id :: CompressedWord.CompressedWord,
+    -- | Read-only! Changing an attribute's name requires editing the class
+    -- attribute map.
+    name :: Str.Str,
+    value :: AttributeValue.AttributeValue
   }
   deriving (Eq, Show)
 
@@ -31,72 +31,80 @@
     id <- Json.required object "id"
     name <- Json.required object "name"
     value <- Json.required object "value"
-    pure Attribute { id, name, value }
+    pure Attribute {id, name, value}
 
 instance Json.ToJSON Attribute where
-  toJSON x = Json.object
-    [ Json.pair "id" $ id x
-    , Json.pair "name" $ name x
-    , Json.pair "value" $ value x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "id" $ id x,
+        Json.pair "name" $ name x,
+        Json.pair "value" $ value x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute" $ Schema.object
-  [ (Json.pair "id" $ Schema.ref CompressedWord.schema, True)
-  , (Json.pair "name" $ Schema.ref Str.schema, True)
-  , (Json.pair "value" $ Schema.ref AttributeValue.schema, True)
-  ]
+schema =
+  Schema.named "attribute" $
+    Schema.object
+      [ (Json.pair "id" $ Schema.ref CompressedWord.schema, True),
+        (Json.pair "name" $ Schema.ref Str.schema, True),
+        (Json.pair "value" $ Schema.ref AttributeValue.schema, True)
+      ]
 
 bitPut :: Attribute -> BitPut.BitPut
 bitPut attribute =
   CompressedWord.bitPut (Rattletrap.Type.Attribute.id attribute)
     <> AttributeValue.bitPut (value attribute)
 
-bitGet
-  :: Version.Version
-  -> Maybe Str.Str
-  -> ClassAttributeMap.ClassAttributeMap
-  -> Map.Map CompressedWord.CompressedWord U32.U32
-  -> CompressedWord.CompressedWord
-  -> BitGet.BitGet Attribute
+bitGet ::
+  Version.Version ->
+  Maybe Str.Str ->
+  ClassAttributeMap.ClassAttributeMap ->
+  Map.Map CompressedWord.CompressedWord U32.U32 ->
+  CompressedWord.CompressedWord ->
+  BitGet.BitGet Attribute
 bitGet version buildVersion classes actors actor =
   BitGet.label "Attribute" $ do
     attributes <- lookupAttributeMap classes actors actor
     limit <- lookupAttributeIdLimit attributes actor
     id <- BitGet.label "id" $ CompressedWord.bitGet limit
     name <- lookupAttributeName classes attributes id
-    value <- BitGet.label "value" $ AttributeValue.bitGet
-      version
-      buildVersion
-      (ClassAttributeMap.objectMap classes)
-      name
-    pure Attribute { id, name, value }
+    value <-
+      BitGet.label "value" $
+        AttributeValue.bitGet
+          version
+          buildVersion
+          (ClassAttributeMap.objectMap classes)
+          name
+    pure Attribute {id, name, value}
 
-lookupAttributeMap
-  :: ClassAttributeMap.ClassAttributeMap
-  -> Map.Map CompressedWord.CompressedWord U32.U32
-  -> CompressedWord.CompressedWord
-  -> BitGet.BitGet (Map.Map U32.U32 U32.U32)
-lookupAttributeMap classes actors actor = fromMaybe
-  (UnknownActor.UnknownActor $ CompressedWord.value actor)
-  (ClassAttributeMap.getAttributeMap classes actors actor)
+lookupAttributeMap ::
+  ClassAttributeMap.ClassAttributeMap ->
+  Map.Map CompressedWord.CompressedWord U32.U32 ->
+  CompressedWord.CompressedWord ->
+  BitGet.BitGet (Map.Map U32.U32 U32.U32)
+lookupAttributeMap classes actors actor =
+  fromMaybe
+    (UnknownActor.UnknownActor $ CompressedWord.value actor)
+    (ClassAttributeMap.getAttributeMap classes actors actor)
 
-lookupAttributeIdLimit
-  :: Map.Map U32.U32 U32.U32
-  -> CompressedWord.CompressedWord
-  -> BitGet.BitGet Word
-lookupAttributeIdLimit attributes actor = fromMaybe
-  (MissingAttributeLimit.MissingAttributeLimit $ CompressedWord.value actor)
-  (ClassAttributeMap.getAttributeIdLimit attributes)
+lookupAttributeIdLimit ::
+  Map.Map U32.U32 U32.U32 ->
+  CompressedWord.CompressedWord ->
+  BitGet.BitGet Word
+lookupAttributeIdLimit attributes actor =
+  fromMaybe
+    (MissingAttributeLimit.MissingAttributeLimit $ CompressedWord.value actor)
+    (ClassAttributeMap.getAttributeIdLimit attributes)
 
-lookupAttributeName
-  :: ClassAttributeMap.ClassAttributeMap
-  -> Map.Map U32.U32 U32.U32
-  -> CompressedWord.CompressedWord
-  -> BitGet.BitGet Str.Str
-lookupAttributeName classes attributes attribute = fromMaybe
-  (MissingAttributeName.MissingAttributeName $ CompressedWord.value attribute)
-  (ClassAttributeMap.getAttributeName classes attributes attribute)
+lookupAttributeName ::
+  ClassAttributeMap.ClassAttributeMap ->
+  Map.Map U32.U32 U32.U32 ->
+  CompressedWord.CompressedWord ->
+  BitGet.BitGet Str.Str
+lookupAttributeName classes attributes attribute =
+  fromMaybe
+    (MissingAttributeName.MissingAttributeName $ CompressedWord.value attribute)
+    (ClassAttributeMap.getAttributeName classes attributes attribute)
 
-fromMaybe :: Exception.Exception e => e -> Maybe a -> BitGet.BitGet a
+fromMaybe :: (Exception.Exception e) => e -> Maybe a -> BitGet.BitGet a
 fromMaybe message = maybe (BitGet.throw message) pure
diff --git a/src/lib/Rattletrap/Type/Attribute/AppliedDamage.hs b/src/lib/Rattletrap/Type/Attribute/AppliedDamage.hs
--- a/src/lib/Rattletrap/Type/Attribute/AppliedDamage.hs
+++ b/src/lib/Rattletrap/Type/Attribute/AppliedDamage.hs
@@ -10,10 +10,10 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data AppliedDamage = AppliedDamage
-  { unknown1 :: U8.U8
-  , location :: Vector.Vector
-  , unknown3 :: I32.I32
-  , unknown4 :: I32.I32
+  { unknown1 :: U8.U8,
+    location :: Vector.Vector,
+    unknown3 :: I32.I32,
+    unknown4 :: I32.I32
   }
   deriving (Eq, Show)
 
@@ -23,23 +23,26 @@
     location <- Json.required object "location"
     unknown3 <- Json.required object "unknown3"
     unknown4 <- Json.required object "unknown4"
-    pure AppliedDamage { unknown1, location, unknown3, unknown4 }
+    pure AppliedDamage {unknown1, location, unknown3, unknown4}
 
 instance Json.ToJSON AppliedDamage where
-  toJSON x = Json.object
-    [ Json.pair "unknown1" $ unknown1 x
-    , Json.pair "location" $ location x
-    , Json.pair "unknown3" $ unknown3 x
-    , Json.pair "unknown4" $ unknown4 x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "unknown1" $ unknown1 x,
+        Json.pair "location" $ location x,
+        Json.pair "unknown3" $ unknown3 x,
+        Json.pair "unknown4" $ unknown4 x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-applied-damage" $ Schema.object
-  [ (Json.pair "unknown1" $ Schema.ref U8.schema, True)
-  , (Json.pair "location" $ Schema.ref Vector.schema, True)
-  , (Json.pair "unknown3" $ Schema.ref I32.schema, True)
-  , (Json.pair "unknown4" $ Schema.ref I32.schema, True)
-  ]
+schema =
+  Schema.named "attribute-applied-damage" $
+    Schema.object
+      [ (Json.pair "unknown1" $ Schema.ref U8.schema, True),
+        (Json.pair "location" $ Schema.ref Vector.schema, True),
+        (Json.pair "unknown3" $ Schema.ref I32.schema, True),
+        (Json.pair "unknown4" $ Schema.ref I32.schema, True)
+      ]
 
 bitPut :: AppliedDamage -> BitPut.BitPut
 bitPut appliedDamageAttribute =
@@ -54,4 +57,4 @@
   location <- BitGet.label "location" $ Vector.bitGet version
   unknown3 <- BitGet.label "unknown3" I32.bitGet
   unknown4 <- BitGet.label "unknown4" I32.bitGet
-  pure AppliedDamage { unknown1, location, unknown3, unknown4 }
+  pure AppliedDamage {unknown1, location, unknown3, unknown4}
diff --git a/src/lib/Rattletrap/Type/Attribute/Boolean.hs b/src/lib/Rattletrap/Type/Attribute/Boolean.hs
--- a/src/lib/Rattletrap/Type/Attribute/Boolean.hs
+++ b/src/lib/Rattletrap/Type/Attribute/Boolean.hs
@@ -7,7 +7,8 @@
 
 newtype Boolean = Boolean
   { value :: Bool
-  } deriving (Eq, Show)
+  }
+  deriving (Eq, Show)
 
 instance Json.FromJSON Boolean where
   parseJSON = fmap Boolean . Json.parseJSON
@@ -24,4 +25,4 @@
 bitGet :: BitGet.BitGet Boolean
 bitGet = BitGet.label "Boolean" $ do
   value <- BitGet.label "value" BitGet.bool
-  pure Boolean { value }
+  pure Boolean {value}
diff --git a/src/lib/Rattletrap/Type/Attribute/Byte.hs b/src/lib/Rattletrap/Type/Attribute/Byte.hs
--- a/src/lib/Rattletrap/Type/Attribute/Byte.hs
+++ b/src/lib/Rattletrap/Type/Attribute/Byte.hs
@@ -8,7 +8,8 @@
 
 newtype Byte = Byte
   { value :: U8.U8
-  } deriving (Eq, Show)
+  }
+  deriving (Eq, Show)
 
 instance Json.FromJSON Byte where
   parseJSON = fmap Byte . Json.parseJSON
@@ -25,4 +26,4 @@
 bitGet :: BitGet.BitGet Byte
 bitGet = BitGet.label "Byte" $ do
   value <- BitGet.label "value" U8.bitGet
-  pure Byte { value }
+  pure Byte {value}
diff --git a/src/lib/Rattletrap/Type/Attribute/CamSettings.hs b/src/lib/Rattletrap/Type/Attribute/CamSettings.hs
--- a/src/lib/Rattletrap/Type/Attribute/CamSettings.hs
+++ b/src/lib/Rattletrap/Type/Attribute/CamSettings.hs
@@ -9,13 +9,13 @@
 import qualified Rattletrap.Utility.Monad as Monad
 
 data CamSettings = CamSettings
-  { fov :: F32.F32
-  , height :: F32.F32
-  , angle :: F32.F32
-  , distance :: F32.F32
-  , stiffness :: F32.F32
-  , swivelSpeed :: F32.F32
-  , transitionSpeed :: Maybe F32.F32
+  { fov :: F32.F32,
+    height :: F32.F32,
+    angle :: F32.F32,
+    distance :: F32.F32,
+    stiffness :: F32.F32,
+    swivelSpeed :: F32.F32,
+    transitionSpeed :: Maybe F32.F32
   }
   deriving (Eq, Show)
 
@@ -28,39 +28,43 @@
     stiffness <- Json.required object "stiffness"
     swivelSpeed <- Json.required object "swivel_speed"
     transitionSpeed <- Json.optional object "transition_speed"
-    pure CamSettings
-      { fov
-      , height
-      , angle
-      , distance
-      , stiffness
-      , swivelSpeed
-      , transitionSpeed
-      }
+    pure
+      CamSettings
+        { fov,
+          height,
+          angle,
+          distance,
+          stiffness,
+          swivelSpeed,
+          transitionSpeed
+        }
 
 instance Json.ToJSON CamSettings where
-  toJSON x = Json.object
-    [ Json.pair "fov" $ fov x
-    , Json.pair "height" $ height x
-    , Json.pair "angle" $ angle x
-    , Json.pair "distance" $ distance x
-    , Json.pair "stiffness" $ stiffness x
-    , Json.pair "swivel_speed" $ swivelSpeed x
-    , Json.pair "transition_speed" $ transitionSpeed x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "fov" $ fov x,
+        Json.pair "height" $ height x,
+        Json.pair "angle" $ angle x,
+        Json.pair "distance" $ distance x,
+        Json.pair "stiffness" $ stiffness x,
+        Json.pair "swivel_speed" $ swivelSpeed x,
+        Json.pair "transition_speed" $ transitionSpeed x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-cam-settings" $ Schema.object
-  [ (Json.pair "fov" $ Schema.ref F32.schema, True)
-  , (Json.pair "height" $ Schema.ref F32.schema, True)
-  , (Json.pair "angle" $ Schema.ref F32.schema, True)
-  , (Json.pair "distance" $ Schema.ref F32.schema, True)
-  , (Json.pair "stiffness" $ Schema.ref F32.schema, True)
-  , (Json.pair "swivel_speed" $ Schema.ref F32.schema, True)
-  , ( Json.pair "transition_speed" . Schema.json $ Schema.maybe F32.schema
-    , False
-    )
-  ]
+schema =
+  Schema.named "attribute-cam-settings" $
+    Schema.object
+      [ (Json.pair "fov" $ Schema.ref F32.schema, True),
+        (Json.pair "height" $ Schema.ref F32.schema, True),
+        (Json.pair "angle" $ Schema.ref F32.schema, True),
+        (Json.pair "distance" $ Schema.ref F32.schema, True),
+        (Json.pair "stiffness" $ Schema.ref F32.schema, True),
+        (Json.pair "swivel_speed" $ Schema.ref F32.schema, True),
+        ( Json.pair "transition_speed" . Schema.json $ Schema.maybe F32.schema,
+          False
+        )
+      ]
 
 bitPut :: CamSettings -> BitPut.BitPut
 bitPut camSettingsAttribute =
@@ -80,14 +84,16 @@
   distance <- BitGet.label "distance" F32.bitGet
   stiffness <- BitGet.label "stiffness" F32.bitGet
   swivelSpeed <- BitGet.label "swivelSpeed" F32.bitGet
-  transitionSpeed <- BitGet.label "transitionSpeed"
-    $ Monad.whenMaybe (Version.atLeast 868 20 0 version) F32.bitGet
-  pure CamSettings
-    { fov
-    , height
-    , angle
-    , distance
-    , stiffness
-    , swivelSpeed
-    , transitionSpeed
-    }
+  transitionSpeed <-
+    BitGet.label "transitionSpeed" $
+      Monad.whenMaybe (Version.atLeast 868 20 0 version) F32.bitGet
+  pure
+    CamSettings
+      { fov,
+        height,
+        angle,
+        distance,
+        stiffness,
+        swivelSpeed,
+        transitionSpeed
+      }
diff --git a/src/lib/Rattletrap/Type/Attribute/ClubColors.hs b/src/lib/Rattletrap/Type/Attribute/ClubColors.hs
--- a/src/lib/Rattletrap/Type/Attribute/ClubColors.hs
+++ b/src/lib/Rattletrap/Type/Attribute/ClubColors.hs
@@ -7,10 +7,10 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data ClubColors = ClubColors
-  { blueFlag :: Bool
-  , blueColor :: U8.U8
-  , orangeFlag :: Bool
-  , orangeColor :: U8.U8
+  { blueFlag :: Bool,
+    blueColor :: U8.U8,
+    orangeFlag :: Bool,
+    orangeColor :: U8.U8
   }
   deriving (Eq, Show)
 
@@ -20,23 +20,26 @@
     blueColor <- Json.required object "blue_color"
     orangeFlag <- Json.required object "orange_flag"
     orangeColor <- Json.required object "orange_color"
-    pure ClubColors { blueFlag, blueColor, orangeFlag, orangeColor }
+    pure ClubColors {blueFlag, blueColor, orangeFlag, orangeColor}
 
 instance Json.ToJSON ClubColors where
-  toJSON x = Json.object
-    [ Json.pair "blue_flag" $ blueFlag x
-    , Json.pair "blue_color" $ blueColor x
-    , Json.pair "orange_flag" $ orangeFlag x
-    , Json.pair "orange_color" $ orangeColor x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "blue_flag" $ blueFlag x,
+        Json.pair "blue_color" $ blueColor x,
+        Json.pair "orange_flag" $ orangeFlag x,
+        Json.pair "orange_color" $ orangeColor x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-club-colors" $ Schema.object
-  [ (Json.pair "blue_flag" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "blue_color" $ Schema.ref U8.schema, True)
-  , (Json.pair "orange_flag" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "orange_color" $ Schema.ref U8.schema, True)
-  ]
+schema =
+  Schema.named "attribute-club-colors" $
+    Schema.object
+      [ (Json.pair "blue_flag" $ Schema.ref Schema.boolean, True),
+        (Json.pair "blue_color" $ Schema.ref U8.schema, True),
+        (Json.pair "orange_flag" $ Schema.ref Schema.boolean, True),
+        (Json.pair "orange_color" $ Schema.ref U8.schema, True)
+      ]
 
 bitPut :: ClubColors -> BitPut.BitPut
 bitPut clubColorsAttribute =
@@ -51,4 +54,4 @@
   blueColor <- BitGet.label "blueColor" U8.bitGet
   orangeFlag <- BitGet.label "orangeFlag" BitGet.bool
   orangeColor <- BitGet.label "orangeColor" U8.bitGet
-  pure ClubColors { blueFlag, blueColor, orangeFlag, orangeColor }
+  pure ClubColors {blueFlag, blueColor, orangeFlag, orangeColor}
diff --git a/src/lib/Rattletrap/Type/Attribute/CustomDemolish.hs b/src/lib/Rattletrap/Type/Attribute/CustomDemolish.hs
--- a/src/lib/Rattletrap/Type/Attribute/CustomDemolish.hs
+++ b/src/lib/Rattletrap/Type/Attribute/CustomDemolish.hs
@@ -1,6 +1,5 @@
 module Rattletrap.Type.Attribute.CustomDemolish where
 
-import Prelude hiding (id)
 import qualified Rattletrap.BitGet as BitGet
 import qualified Rattletrap.BitPut as BitPut
 import qualified Rattletrap.Schema as Schema
@@ -8,11 +7,12 @@
 import qualified Rattletrap.Type.I32 as I32
 import qualified Rattletrap.Type.Version as Version
 import qualified Rattletrap.Utility.Json as Json
+import Prelude hiding (id)
 
 data CustomDemolish = CustomDemolish
-  { flag :: Bool
-  , id :: I32.I32
-  , demolish :: Demolish.Demolish
+  { flag :: Bool,
+    id :: I32.I32,
+    demolish :: Demolish.Demolish
   }
   deriving (Eq, Show)
 
@@ -21,21 +21,24 @@
     flag <- Json.required object "flag"
     id <- Json.required object "id"
     demolish <- Json.required object "demolish"
-    pure CustomDemolish { flag, id, demolish }
+    pure CustomDemolish {flag, id, demolish}
 
 instance Json.ToJSON CustomDemolish where
-  toJSON x = Json.object
-    [ Json.pair "flag" $ flag x
-    , Json.pair "id" $ id x
-    , Json.pair "demolish" $ demolish x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "flag" $ flag x,
+        Json.pair "id" $ id x,
+        Json.pair "demolish" $ demolish x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-custom-demolish" $ Schema.object
-  [ (Json.pair "flag" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "id" $ Schema.ref I32.schema, True)
-  , (Json.pair "demolish" $ Schema.ref Demolish.schema, True)
-  ]
+schema =
+  Schema.named "attribute-custom-demolish" $
+    Schema.object
+      [ (Json.pair "flag" $ Schema.ref Schema.boolean, True),
+        (Json.pair "id" $ Schema.ref I32.schema, True),
+        (Json.pair "demolish" $ Schema.ref Demolish.schema, True)
+      ]
 
 bitPut :: CustomDemolish -> BitPut.BitPut
 bitPut x =
@@ -48,8 +51,9 @@
   flag <- BitGet.label "flag" BitGet.bool
   id <- BitGet.label "id" I32.bitGet
   demolish <- BitGet.label "demolish" $ Demolish.bitGet version
-  pure CustomDemolish
-    { flag
-    , Rattletrap.Type.Attribute.CustomDemolish.id
-    , demolish
-    }
+  pure
+    CustomDemolish
+      { flag,
+        Rattletrap.Type.Attribute.CustomDemolish.id,
+        demolish
+      }
diff --git a/src/lib/Rattletrap/Type/Attribute/DamageState.hs b/src/lib/Rattletrap/Type/Attribute/DamageState.hs
--- a/src/lib/Rattletrap/Type/Attribute/DamageState.hs
+++ b/src/lib/Rattletrap/Type/Attribute/DamageState.hs
@@ -10,12 +10,12 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data DamageState = DamageState
-  { unknown1 :: U8.U8
-  , unknown2 :: Bool
-  , unknown3 :: I32.I32
-  , unknown4 :: Vector.Vector
-  , unknown5 :: Bool
-  , unknown6 :: Bool
+  { unknown1 :: U8.U8,
+    unknown2 :: Bool,
+    unknown3 :: I32.I32,
+    unknown4 :: Vector.Vector,
+    unknown5 :: Bool,
+    unknown6 :: Bool
   }
   deriving (Eq, Show)
 
@@ -27,34 +27,38 @@
     unknown4 <- Json.required object "unknown4"
     unknown5 <- Json.required object "unknown5"
     unknown6 <- Json.required object "unknown6"
-    pure DamageState
-      { unknown1
-      , unknown2
-      , unknown3
-      , unknown4
-      , unknown5
-      , unknown6
-      }
+    pure
+      DamageState
+        { unknown1,
+          unknown2,
+          unknown3,
+          unknown4,
+          unknown5,
+          unknown6
+        }
 
 instance Json.ToJSON DamageState where
-  toJSON x = Json.object
-    [ Json.pair "unknown1" $ unknown1 x
-    , Json.pair "unknown2" $ unknown2 x
-    , Json.pair "unknown3" $ unknown3 x
-    , Json.pair "unknown4" $ unknown4 x
-    , Json.pair "unknown5" $ unknown5 x
-    , Json.pair "unknown6" $ unknown6 x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "unknown1" $ unknown1 x,
+        Json.pair "unknown2" $ unknown2 x,
+        Json.pair "unknown3" $ unknown3 x,
+        Json.pair "unknown4" $ unknown4 x,
+        Json.pair "unknown5" $ unknown5 x,
+        Json.pair "unknown6" $ unknown6 x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-damage-state" $ Schema.object
-  [ (Json.pair "unknown1" $ Schema.ref U8.schema, True)
-  , (Json.pair "unknown2" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "unknown3" $ Schema.ref I32.schema, True)
-  , (Json.pair "unknown4" $ Schema.ref Vector.schema, True)
-  , (Json.pair "unknown5" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "unknown6" $ Schema.ref Schema.boolean, True)
-  ]
+schema =
+  Schema.named "attribute-damage-state" $
+    Schema.object
+      [ (Json.pair "unknown1" $ Schema.ref U8.schema, True),
+        (Json.pair "unknown2" $ Schema.ref Schema.boolean, True),
+        (Json.pair "unknown3" $ Schema.ref I32.schema, True),
+        (Json.pair "unknown4" $ Schema.ref Vector.schema, True),
+        (Json.pair "unknown5" $ Schema.ref Schema.boolean, True),
+        (Json.pair "unknown6" $ Schema.ref Schema.boolean, True)
+      ]
 
 bitPut :: DamageState -> BitPut.BitPut
 bitPut damageStateAttribute =
@@ -73,11 +77,12 @@
   unknown4 <- BitGet.label "unknown4" $ Vector.bitGet version
   unknown5 <- BitGet.label "unknown5" BitGet.bool
   unknown6 <- BitGet.label "unknown6" BitGet.bool
-  pure DamageState
-    { unknown1
-    , unknown2
-    , unknown3
-    , unknown4
-    , unknown5
-    , unknown6
-    }
+  pure
+    DamageState
+      { unknown1,
+        unknown2,
+        unknown3,
+        unknown4,
+        unknown5,
+        unknown6
+      }
diff --git a/src/lib/Rattletrap/Type/Attribute/Demolish.hs b/src/lib/Rattletrap/Type/Attribute/Demolish.hs
--- a/src/lib/Rattletrap/Type/Attribute/Demolish.hs
+++ b/src/lib/Rattletrap/Type/Attribute/Demolish.hs
@@ -9,12 +9,12 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data Demolish = Demolish
-  { attackerFlag :: Bool
-  , attackerActorId :: U32.U32
-  , victimFlag :: Bool
-  , victimActorId :: U32.U32
-  , attackerVelocity :: Vector.Vector
-  , victimVelocity :: Vector.Vector
+  { attackerFlag :: Bool,
+    attackerActorId :: U32.U32,
+    victimFlag :: Bool,
+    victimActorId :: U32.U32,
+    attackerVelocity :: Vector.Vector,
+    victimVelocity :: Vector.Vector
   }
   deriving (Eq, Show)
 
@@ -26,34 +26,38 @@
     victimActorId <- Json.required object "victim_actor_id"
     attackerVelocity <- Json.required object "attacker_velocity"
     victimVelocity <- Json.required object "victim_velocity"
-    pure Demolish
-      { attackerFlag
-      , attackerActorId
-      , victimFlag
-      , victimActorId
-      , attackerVelocity
-      , victimVelocity
-      }
+    pure
+      Demolish
+        { attackerFlag,
+          attackerActorId,
+          victimFlag,
+          victimActorId,
+          attackerVelocity,
+          victimVelocity
+        }
 
 instance Json.ToJSON Demolish where
-  toJSON x = Json.object
-    [ Json.pair "attacker_flag" $ attackerFlag x
-    , Json.pair "attacker_actor_id" $ attackerActorId x
-    , Json.pair "victim_flag" $ victimFlag x
-    , Json.pair "victim_actor_id" $ victimActorId x
-    , Json.pair "attacker_velocity" $ attackerVelocity x
-    , Json.pair "victim_velocity" $ victimVelocity x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "attacker_flag" $ attackerFlag x,
+        Json.pair "attacker_actor_id" $ attackerActorId x,
+        Json.pair "victim_flag" $ victimFlag x,
+        Json.pair "victim_actor_id" $ victimActorId x,
+        Json.pair "attacker_velocity" $ attackerVelocity x,
+        Json.pair "victim_velocity" $ victimVelocity x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-demolish" $ Schema.object
-  [ (Json.pair "attacker_flag" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "attacker_actor_id" $ Schema.ref U32.schema, True)
-  , (Json.pair "victim_flag" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "victim_actor_id" $ Schema.ref U32.schema, True)
-  , (Json.pair "attacker_velocity" $ Schema.ref Vector.schema, True)
-  , (Json.pair "victim_velocity" $ Schema.ref Vector.schema, True)
-  ]
+schema =
+  Schema.named "attribute-demolish" $
+    Schema.object
+      [ (Json.pair "attacker_flag" $ Schema.ref Schema.boolean, True),
+        (Json.pair "attacker_actor_id" $ Schema.ref U32.schema, True),
+        (Json.pair "victim_flag" $ Schema.ref Schema.boolean, True),
+        (Json.pair "victim_actor_id" $ Schema.ref U32.schema, True),
+        (Json.pair "attacker_velocity" $ Schema.ref Vector.schema, True),
+        (Json.pair "victim_velocity" $ Schema.ref Vector.schema, True)
+      ]
 
 bitPut :: Demolish -> BitPut.BitPut
 bitPut demolishAttribute =
@@ -72,11 +76,12 @@
   victimActorId <- BitGet.label "victimActorId" U32.bitGet
   attackerVelocity <- BitGet.label "attackerVelocity" $ Vector.bitGet version
   victimVelocity <- BitGet.label "victimVelocity" $ Vector.bitGet version
-  pure Demolish
-    { attackerFlag
-    , attackerActorId
-    , victimFlag
-    , victimActorId
-    , attackerVelocity
-    , victimVelocity
-    }
+  pure
+    Demolish
+      { attackerFlag,
+        attackerActorId,
+        victimFlag,
+        victimActorId,
+        attackerVelocity,
+        victimVelocity
+      }
diff --git a/src/lib/Rattletrap/Type/Attribute/Enum.hs b/src/lib/Rattletrap/Type/Attribute/Enum.hs
--- a/src/lib/Rattletrap/Type/Attribute/Enum.hs
+++ b/src/lib/Rattletrap/Type/Attribute/Enum.hs
@@ -1,15 +1,16 @@
 module Rattletrap.Type.Attribute.Enum where
 
 import qualified Data.Word as Word
-import Prelude hiding (Enum)
 import qualified Rattletrap.BitGet as BitGet
 import qualified Rattletrap.BitPut as BitPut
 import qualified Rattletrap.Schema as Schema
 import qualified Rattletrap.Utility.Json as Json
+import Prelude hiding (Enum)
 
 newtype Enum = Enum
   { value :: Word.Word16
-  } deriving (Eq, Show)
+  }
+  deriving (Eq, Show)
 
 instance Json.FromJSON Enum where
   parseJSON = fmap Enum . Json.parseJSON
@@ -26,4 +27,4 @@
 bitGet :: BitGet.BitGet Enum
 bitGet = BitGet.label "Enum" $ do
   value <- BitGet.label "value" $ BitGet.bits 11
-  pure Enum { value }
+  pure Enum {value}
diff --git a/src/lib/Rattletrap/Type/Attribute/Explosion.hs b/src/lib/Rattletrap/Type/Attribute/Explosion.hs
--- a/src/lib/Rattletrap/Type/Attribute/Explosion.hs
+++ b/src/lib/Rattletrap/Type/Attribute/Explosion.hs
@@ -9,9 +9,9 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data Explosion = Explosion
-  { flag :: Bool
-  , actorId :: I32.I32
-  , location :: Vector.Vector
+  { flag :: Bool,
+    actorId :: I32.I32,
+    location :: Vector.Vector
   }
   deriving (Eq, Show)
 
@@ -20,21 +20,24 @@
     flag <- Json.required object "flag"
     actorId <- Json.required object "actor_id"
     location <- Json.required object "location"
-    pure Explosion { flag, actorId, location }
+    pure Explosion {flag, actorId, location}
 
 instance Json.ToJSON Explosion where
-  toJSON x = Json.object
-    [ Json.pair "flag" $ flag x
-    , Json.pair "actor_id" $ actorId x
-    , Json.pair "location" $ location x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "flag" $ flag x,
+        Json.pair "actor_id" $ actorId x,
+        Json.pair "location" $ location x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-explosion" $ Schema.object
-  [ (Json.pair "flag" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "actor_id" $ Schema.ref I32.schema, True)
-  , (Json.pair "location" $ Schema.ref Vector.schema, True)
-  ]
+schema =
+  Schema.named "attribute-explosion" $
+    Schema.object
+      [ (Json.pair "flag" $ Schema.ref Schema.boolean, True),
+        (Json.pair "actor_id" $ Schema.ref I32.schema, True),
+        (Json.pair "location" $ Schema.ref Vector.schema, True)
+      ]
 
 bitPut :: Explosion -> BitPut.BitPut
 bitPut explosionAttribute =
@@ -47,4 +50,4 @@
   flag <- BitGet.label "flag" BitGet.bool
   actorId <- BitGet.label "actorId" I32.bitGet
   location <- BitGet.label "location" $ Vector.bitGet version
-  pure Explosion { flag, actorId, location }
+  pure Explosion {flag, actorId, location}
diff --git a/src/lib/Rattletrap/Type/Attribute/ExtendedExplosion.hs b/src/lib/Rattletrap/Type/Attribute/ExtendedExplosion.hs
--- a/src/lib/Rattletrap/Type/Attribute/ExtendedExplosion.hs
+++ b/src/lib/Rattletrap/Type/Attribute/ExtendedExplosion.hs
@@ -9,8 +9,8 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data ExtendedExplosion = ExtendedExplosion
-  { explosion :: Explosion.Explosion
-  , unknown :: FlaggedInt.FlaggedInt
+  { explosion :: Explosion.Explosion,
+    unknown :: FlaggedInt.FlaggedInt
   }
   deriving (Eq, Show)
 
@@ -18,17 +18,20 @@
   parseJSON = Json.withObject "ExtendedExplosion" $ \object -> do
     explosion <- Json.required object "explosion"
     unknown <- Json.required object "unknown"
-    pure ExtendedExplosion { explosion, unknown }
+    pure ExtendedExplosion {explosion, unknown}
 
 instance Json.ToJSON ExtendedExplosion where
-  toJSON x = Json.object
-    [Json.pair "explosion" $ explosion x, Json.pair "unknown" $ unknown x]
+  toJSON x =
+    Json.object
+      [Json.pair "explosion" $ explosion x, Json.pair "unknown" $ unknown x]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-extended-explosion" $ Schema.object
-  [ (Json.pair "explosion" $ Schema.ref Explosion.schema, True)
-  , (Json.pair "unknown" $ Schema.ref FlaggedInt.schema, True)
-  ]
+schema =
+  Schema.named "attribute-extended-explosion" $
+    Schema.object
+      [ (Json.pair "explosion" $ Schema.ref Explosion.schema, True),
+        (Json.pair "unknown" $ Schema.ref FlaggedInt.schema, True)
+      ]
 
 bitPut :: ExtendedExplosion -> BitPut.BitPut
 bitPut x = Explosion.bitPut (explosion x) <> FlaggedInt.bitPut (unknown x)
@@ -37,4 +40,4 @@
 bitGet version = BitGet.label "ExtendedExplosion" $ do
   explosion <- BitGet.label "explosion" $ Explosion.bitGet version
   unknown <- BitGet.label "unknown" FlaggedInt.bitGet
-  pure ExtendedExplosion { explosion, unknown }
+  pure ExtendedExplosion {explosion, unknown}
diff --git a/src/lib/Rattletrap/Type/Attribute/FlaggedByte.hs b/src/lib/Rattletrap/Type/Attribute/FlaggedByte.hs
--- a/src/lib/Rattletrap/Type/Attribute/FlaggedByte.hs
+++ b/src/lib/Rattletrap/Type/Attribute/FlaggedByte.hs
@@ -7,8 +7,8 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data FlaggedByte = FlaggedByte
-  { flag :: Bool
-  , byte :: U8.U8
+  { flag :: Bool,
+    byte :: U8.U8
   }
   deriving (Eq, Show)
 
@@ -16,24 +16,27 @@
   parseJSON = Json.withObject "FlaggedByte" $ \object -> do
     flag <- Json.required object "flag"
     byte <- Json.required object "byte"
-    pure FlaggedByte { flag, byte }
+    pure FlaggedByte {flag, byte}
 
 instance Json.ToJSON FlaggedByte where
   toJSON x =
     Json.object [Json.pair "flag" $ flag x, Json.pair "byte" $ byte x]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-flagged-byte" $ Schema.object
-  [ (Json.pair "flag" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "byte" $ Schema.ref U8.schema, True)
-  ]
+schema =
+  Schema.named "attribute-flagged-byte" $
+    Schema.object
+      [ (Json.pair "flag" $ Schema.ref Schema.boolean, True),
+        (Json.pair "byte" $ Schema.ref U8.schema, True)
+      ]
 
 bitPut :: FlaggedByte -> BitPut.BitPut
-bitPut flaggedByteAttribute = BitPut.bool (flag flaggedByteAttribute)
-  <> U8.bitPut (byte flaggedByteAttribute)
+bitPut flaggedByteAttribute =
+  BitPut.bool (flag flaggedByteAttribute)
+    <> U8.bitPut (byte flaggedByteAttribute)
 
 bitGet :: BitGet.BitGet FlaggedByte
 bitGet = BitGet.label "FlaggedByte" $ do
   flag <- BitGet.label "flag" BitGet.bool
   byte <- BitGet.label "byte" U8.bitGet
-  pure FlaggedByte { flag, byte }
+  pure FlaggedByte {flag, byte}
diff --git a/src/lib/Rattletrap/Type/Attribute/FlaggedInt.hs b/src/lib/Rattletrap/Type/Attribute/FlaggedInt.hs
--- a/src/lib/Rattletrap/Type/Attribute/FlaggedInt.hs
+++ b/src/lib/Rattletrap/Type/Attribute/FlaggedInt.hs
@@ -7,8 +7,8 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data FlaggedInt = FlaggedInt
-  { flag :: Bool
-  , int :: I32.I32
+  { flag :: Bool,
+    int :: I32.I32
   }
   deriving (Eq, Show)
 
@@ -16,23 +16,26 @@
   parseJSON = Json.withObject "FlaggedInt" $ \object -> do
     flag <- Json.required object "flag"
     int <- Json.required object "int"
-    pure FlaggedInt { flag, int }
+    pure FlaggedInt {flag, int}
 
 instance Json.ToJSON FlaggedInt where
   toJSON x = Json.object [Json.pair "flag" $ flag x, Json.pair "int" $ int x]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-flagged-int" $ Schema.object
-  [ (Json.pair "flag" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "int" $ Schema.ref I32.schema, True)
-  ]
+schema =
+  Schema.named "attribute-flagged-int" $
+    Schema.object
+      [ (Json.pair "flag" $ Schema.ref Schema.boolean, True),
+        (Json.pair "int" $ Schema.ref I32.schema, True)
+      ]
 
 bitPut :: FlaggedInt -> BitPut.BitPut
-bitPut flaggedIntAttribute = BitPut.bool (flag flaggedIntAttribute)
-  <> I32.bitPut (int flaggedIntAttribute)
+bitPut flaggedIntAttribute =
+  BitPut.bool (flag flaggedIntAttribute)
+    <> I32.bitPut (int flaggedIntAttribute)
 
 bitGet :: BitGet.BitGet FlaggedInt
 bitGet = BitGet.label "FlaggedInt" $ do
   flag <- BitGet.label "flag" BitGet.bool
   int <- BitGet.label "int" I32.bitGet
-  pure FlaggedInt { flag, int }
+  pure FlaggedInt {flag, int}
diff --git a/src/lib/Rattletrap/Type/Attribute/Float.hs b/src/lib/Rattletrap/Type/Attribute/Float.hs
--- a/src/lib/Rattletrap/Type/Attribute/Float.hs
+++ b/src/lib/Rattletrap/Type/Attribute/Float.hs
@@ -1,15 +1,16 @@
 module Rattletrap.Type.Attribute.Float where
 
-import Prelude hiding (Float)
 import qualified Rattletrap.BitGet as BitGet
 import qualified Rattletrap.BitPut as BitPut
 import qualified Rattletrap.Schema as Schema
 import qualified Rattletrap.Type.F32 as F32
 import qualified Rattletrap.Utility.Json as Json
+import Prelude hiding (Float)
 
 newtype Float = Float
   { value :: F32.F32
-  } deriving (Eq, Show)
+  }
+  deriving (Eq, Show)
 
 instance Json.FromJSON Float where
   parseJSON = fmap Float . Json.parseJSON
@@ -26,4 +27,4 @@
 bitGet :: BitGet.BitGet Float
 bitGet = BitGet.label "Float" $ do
   value <- BitGet.label "value" F32.bitGet
-  pure Float { value }
+  pure Float {value}
diff --git a/src/lib/Rattletrap/Type/Attribute/GameMode.hs b/src/lib/Rattletrap/Type/Attribute/GameMode.hs
--- a/src/lib/Rattletrap/Type/Attribute/GameMode.hs
+++ b/src/lib/Rattletrap/Type/Attribute/GameMode.hs
@@ -8,12 +8,12 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data GameMode = GameMode
-  { numBits :: Int
-  -- ^ This field is guaranteed to be small. In other words, it won't overflow.
-  -- It's stored as a regular 'Int' rather than something more precise like an
-  -- 'Int8' because it just gets passed to functions that expect 'Int's.
-  -- There's no reason to do a bunch of conversions.
-  , word :: Word.Word8
+  { -- | This field is guaranteed to be small. In other words, it won't overflow.
+    -- It's stored as a regular 'Int' rather than something more precise like an
+    -- 'Int8' because it just gets passed to functions that expect 'Int's.
+    -- There's no reason to do a bunch of conversions.
+    numBits :: Int,
+    word :: Word.Word8
   }
   deriving (Eq, Show)
 
@@ -21,17 +21,19 @@
   parseJSON = Json.withObject "GameMode" $ \object -> do
     numBits <- Json.required object "num_bits"
     word <- Json.required object "word"
-    pure GameMode { numBits, word }
+    pure GameMode {numBits, word}
 
 instance Json.ToJSON GameMode where
   toJSON x =
     Json.object [Json.pair "num_bits" $ numBits x, Json.pair "word" $ word x]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-game-mode" $ Schema.object
-  [ (Json.pair "num_bits" $ Schema.ref Schema.integer, True)
-  , (Json.pair "word" $ Schema.ref Schema.integer, True)
-  ]
+schema =
+  Schema.named "attribute-game-mode" $
+    Schema.object
+      [ (Json.pair "num_bits" $ Schema.ref Schema.integer, True),
+        (Json.pair "word" $ Schema.ref Schema.integer, True)
+      ]
 
 bitPut :: GameMode -> BitPut.BitPut
 bitPut gameModeAttribute = do
@@ -41,4 +43,4 @@
 bitGet version = BitGet.label "GameMode" $ do
   let numBits = if Version.atLeast 868 12 0 version then 8 else 2 :: Int
   word <- BitGet.label "word" $ BitGet.bits numBits
-  pure GameMode { numBits, word }
+  pure GameMode {numBits, word}
diff --git a/src/lib/Rattletrap/Type/Attribute/GameServer.hs b/src/lib/Rattletrap/Type/Attribute/GameServer.hs
--- a/src/lib/Rattletrap/Type/Attribute/GameServer.hs
+++ b/src/lib/Rattletrap/Type/Attribute/GameServer.hs
@@ -14,8 +14,9 @@
   deriving (Eq, Show)
 
 instance Json.FromJSON GameServer where
-  parseJSON = Json.withObject "GameServer" $ \x -> Foldable.asum
-    [fmap Old $ Json.required x "old", fmap New $ Json.required x "new"]
+  parseJSON = Json.withObject "GameServer" $ \x ->
+    Foldable.asum
+      [fmap Old $ Json.required x "old", fmap New $ Json.required x "new"]
 
 instance Json.ToJSON GameServer where
   toJSON x = case x of
@@ -23,9 +24,11 @@
     New y -> Json.object [Json.pair "new" $ Json.toJSON y]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-game-server" . Schema.oneOf $ fmap
-  (\(k, v) -> Schema.object [(Json.pair k v, True)])
-  [("old", Schema.ref QWord.schema), ("new", Schema.ref Str.schema)]
+schema =
+  Schema.named "attribute-game-server" . Schema.oneOf $
+    fmap
+      (\(k, v) -> Schema.object [(Json.pair k v, True)])
+      [("old", Schema.ref QWord.schema), ("new", Schema.ref Str.schema)]
 
 bitPut :: GameServer -> BitPut.BitPut
 bitPut x = case x of
@@ -34,7 +37,7 @@
 
 bitGet :: Maybe Str.Str -> BitGet.BitGet GameServer
 bitGet buildVersion =
-  BitGet.label "GameServer"
-    $ if buildVersion >= Just (Str.fromString "221120.42953.406184")
-        then BitGet.label "New" $ fmap New Str.bitGet
-        else BitGet.label "Old" $ fmap Old QWord.bitGet
+  BitGet.label "GameServer" $
+    if buildVersion >= Just (Str.fromString "221120.42953.406184")
+      then BitGet.label "New" $ fmap New Str.bitGet
+      else BitGet.label "Old" $ fmap Old QWord.bitGet
diff --git a/src/lib/Rattletrap/Type/Attribute/Int.hs b/src/lib/Rattletrap/Type/Attribute/Int.hs
--- a/src/lib/Rattletrap/Type/Attribute/Int.hs
+++ b/src/lib/Rattletrap/Type/Attribute/Int.hs
@@ -1,15 +1,16 @@
 module Rattletrap.Type.Attribute.Int where
 
-import Prelude hiding (Int)
 import qualified Rattletrap.BitGet as BitGet
 import qualified Rattletrap.BitPut as BitPut
 import qualified Rattletrap.Schema as Schema
 import qualified Rattletrap.Type.I32 as I32
 import qualified Rattletrap.Utility.Json as Json
+import Prelude hiding (Int)
 
 newtype Int = Int
   { value :: I32.I32
-  } deriving (Eq, Show)
+  }
+  deriving (Eq, Show)
 
 instance Json.FromJSON Int where
   parseJSON = fmap Int . Json.parseJSON
@@ -26,4 +27,4 @@
 bitGet :: BitGet.BitGet Int
 bitGet = BitGet.label "Int" $ do
   value <- BitGet.label "value" I32.bitGet
-  pure Int { value }
+  pure Int {value}
diff --git a/src/lib/Rattletrap/Type/Attribute/Int64.hs b/src/lib/Rattletrap/Type/Attribute/Int64.hs
--- a/src/lib/Rattletrap/Type/Attribute/Int64.hs
+++ b/src/lib/Rattletrap/Type/Attribute/Int64.hs
@@ -8,7 +8,8 @@
 
 newtype Int64 = Int64
   { value :: I64.I64
-  } deriving (Eq, Show)
+  }
+  deriving (Eq, Show)
 
 instance Json.FromJSON Int64 where
   parseJSON = fmap Int64 . Json.parseJSON
@@ -25,4 +26,4 @@
 bitGet :: BitGet.BitGet Int64
 bitGet = BitGet.label "Int64" $ do
   value <- BitGet.label "value" I64.bitGet
-  pure Int64 { value }
+  pure Int64 {value}
diff --git a/src/lib/Rattletrap/Type/Attribute/Loadout.hs b/src/lib/Rattletrap/Type/Attribute/Loadout.hs
--- a/src/lib/Rattletrap/Type/Attribute/Loadout.hs
+++ b/src/lib/Rattletrap/Type/Attribute/Loadout.hs
@@ -9,24 +9,24 @@
 import qualified Rattletrap.Utility.Monad as Monad
 
 data Loadout = Loadout
-  { version :: U8.U8
-  , body :: U32.U32
-  , decal :: U32.U32
-  , wheels :: U32.U32
-  , rocketTrail :: U32.U32
-  -- ^ Now known as "rocket boost".
-  , antenna :: U32.U32
-  , topper :: U32.U32
-  , unknown1 :: U32.U32
-  , unknown2 :: Maybe U32.U32
-  , engineAudio :: Maybe U32.U32
-  , trail :: Maybe U32.U32
-  , goalExplosion :: Maybe U32.U32
-  , banner :: Maybe U32.U32
-  , unknown3 :: Maybe U32.U32
-  , unknown4 :: Maybe U32.U32
-  , unknown5 :: Maybe U32.U32
-  , unknown6 :: Maybe U32.U32
+  { version :: U8.U8,
+    body :: U32.U32,
+    decal :: U32.U32,
+    wheels :: U32.U32,
+    -- | Now known as "rocket boost".
+    rocketTrail :: U32.U32,
+    antenna :: U32.U32,
+    topper :: U32.U32,
+    unknown1 :: U32.U32,
+    unknown2 :: Maybe U32.U32,
+    engineAudio :: Maybe U32.U32,
+    trail :: Maybe U32.U32,
+    goalExplosion :: Maybe U32.U32,
+    banner :: Maybe U32.U32,
+    unknown3 :: Maybe U32.U32,
+    unknown4 :: Maybe U32.U32,
+    unknown5 :: Maybe U32.U32,
+    unknown6 :: Maybe U32.U32
   }
   deriving (Eq, Show)
 
@@ -49,67 +49,71 @@
     unknown4 <- Json.optional object "unknown4"
     unknown5 <- Json.optional object "unknown5"
     unknown6 <- Json.optional object "unknown6"
-    pure Loadout
-      { version
-      , body
-      , decal
-      , wheels
-      , rocketTrail
-      , antenna
-      , topper
-      , unknown1
-      , unknown2
-      , engineAudio
-      , trail
-      , goalExplosion
-      , banner
-      , unknown3
-      , unknown4
-      , unknown5
-      , unknown6
-      }
+    pure
+      Loadout
+        { version,
+          body,
+          decal,
+          wheels,
+          rocketTrail,
+          antenna,
+          topper,
+          unknown1,
+          unknown2,
+          engineAudio,
+          trail,
+          goalExplosion,
+          banner,
+          unknown3,
+          unknown4,
+          unknown5,
+          unknown6
+        }
 
 instance Json.ToJSON Loadout where
-  toJSON x = Json.object
-    [ Json.pair "version" $ version x
-    , Json.pair "body" $ body x
-    , Json.pair "decal" $ decal x
-    , Json.pair "wheels" $ wheels x
-    , Json.pair "rocket_trail" $ rocketTrail x
-    , Json.pair "antenna" $ antenna x
-    , Json.pair "topper" $ topper x
-    , Json.pair "unknown1" $ unknown1 x
-    , Json.pair "unknown2" $ unknown2 x
-    , Json.pair "engine_audio" $ engineAudio x
-    , Json.pair "trail" $ trail x
-    , Json.pair "goal_explosion" $ goalExplosion x
-    , Json.pair "banner" $ banner x
-    , Json.pair "unknown3" $ unknown3 x
-    , Json.pair "unknown4" $ unknown4 x
-    , Json.pair "unknown5" $ unknown5 x
-    , Json.pair "unknown6" $ unknown6 x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "version" $ version x,
+        Json.pair "body" $ body x,
+        Json.pair "decal" $ decal x,
+        Json.pair "wheels" $ wheels x,
+        Json.pair "rocket_trail" $ rocketTrail x,
+        Json.pair "antenna" $ antenna x,
+        Json.pair "topper" $ topper x,
+        Json.pair "unknown1" $ unknown1 x,
+        Json.pair "unknown2" $ unknown2 x,
+        Json.pair "engine_audio" $ engineAudio x,
+        Json.pair "trail" $ trail x,
+        Json.pair "goal_explosion" $ goalExplosion x,
+        Json.pair "banner" $ banner x,
+        Json.pair "unknown3" $ unknown3 x,
+        Json.pair "unknown4" $ unknown4 x,
+        Json.pair "unknown5" $ unknown5 x,
+        Json.pair "unknown6" $ unknown6 x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-loadout" $ Schema.object
-  [ (Json.pair "version" $ Schema.ref U8.schema, True)
-  , (Json.pair "body" $ Schema.ref U32.schema, True)
-  , (Json.pair "decal" $ Schema.ref U32.schema, True)
-  , (Json.pair "wheels" $ Schema.ref U32.schema, True)
-  , (Json.pair "rocket_trail" $ Schema.ref U32.schema, True)
-  , (Json.pair "antenna" $ Schema.ref U32.schema, True)
-  , (Json.pair "topper" $ Schema.ref U32.schema, True)
-  , (Json.pair "unknown1" $ Schema.ref U32.schema, True)
-  , (Json.pair "unknown2" . Schema.json $ Schema.maybe U32.schema, False)
-  , (Json.pair "engine_audio" . Schema.json $ Schema.maybe U32.schema, False)
-  , (Json.pair "trail" . Schema.json $ Schema.maybe U32.schema, False)
-  , (Json.pair "goal_explosion" . Schema.json $ Schema.maybe U32.schema, False)
-  , (Json.pair "banner" . Schema.json $ Schema.maybe U32.schema, False)
-  , (Json.pair "unknown3" . Schema.json $ Schema.maybe U32.schema, False)
-  , (Json.pair "unknown4" . Schema.json $ Schema.maybe U32.schema, False)
-  , (Json.pair "unknown5" . Schema.json $ Schema.maybe U32.schema, False)
-  , (Json.pair "unknown6" . Schema.json $ Schema.maybe U32.schema, False)
-  ]
+schema =
+  Schema.named "attribute-loadout" $
+    Schema.object
+      [ (Json.pair "version" $ Schema.ref U8.schema, True),
+        (Json.pair "body" $ Schema.ref U32.schema, True),
+        (Json.pair "decal" $ Schema.ref U32.schema, True),
+        (Json.pair "wheels" $ Schema.ref U32.schema, True),
+        (Json.pair "rocket_trail" $ Schema.ref U32.schema, True),
+        (Json.pair "antenna" $ Schema.ref U32.schema, True),
+        (Json.pair "topper" $ Schema.ref U32.schema, True),
+        (Json.pair "unknown1" $ Schema.ref U32.schema, True),
+        (Json.pair "unknown2" . Schema.json $ Schema.maybe U32.schema, False),
+        (Json.pair "engine_audio" . Schema.json $ Schema.maybe U32.schema, False),
+        (Json.pair "trail" . Schema.json $ Schema.maybe U32.schema, False),
+        (Json.pair "goal_explosion" . Schema.json $ Schema.maybe U32.schema, False),
+        (Json.pair "banner" . Schema.json $ Schema.maybe U32.schema, False),
+        (Json.pair "unknown3" . Schema.json $ Schema.maybe U32.schema, False),
+        (Json.pair "unknown4" . Schema.json $ Schema.maybe U32.schema, False),
+        (Json.pair "unknown5" . Schema.json $ Schema.maybe U32.schema, False),
+        (Json.pair "unknown6" . Schema.json $ Schema.maybe U32.schema, False)
+      ]
 
 bitPut :: Loadout -> BitPut.BitPut
 bitPut loadoutAttribute =
@@ -141,40 +145,50 @@
   antenna <- BitGet.label "antenna" U32.bitGet
   topper <- BitGet.label "topper" U32.bitGet
   unknown1 <- BitGet.label "unknown1" U32.bitGet
-  unknown2 <- BitGet.label "unknown2"
-    $ Monad.whenMaybe (U8.toWord8 version >= 11) U32.bitGet
-  engineAudio <- BitGet.label "engineAudio"
-    $ Monad.whenMaybe (U8.toWord8 version >= 16) U32.bitGet
-  trail <- BitGet.label "trail"
-    $ Monad.whenMaybe (U8.toWord8 version >= 16) U32.bitGet
-  goalExplosion <- BitGet.label "goalExplosion"
-    $ Monad.whenMaybe (U8.toWord8 version >= 16) U32.bitGet
-  banner <- BitGet.label "banner"
-    $ Monad.whenMaybe (U8.toWord8 version >= 17) U32.bitGet
-  unknown3 <- BitGet.label "unknown3"
-    $ Monad.whenMaybe (U8.toWord8 version >= 19) U32.bitGet
-  unknown4 <- BitGet.label "unknown4"
-    $ Monad.whenMaybe (U8.toWord8 version >= 22) U32.bitGet
-  unknown5 <- BitGet.label "unknown5"
-    $ Monad.whenMaybe (U8.toWord8 version >= 22) U32.bitGet
-  unknown6 <- BitGet.label "unknown6"
-    $ Monad.whenMaybe (U8.toWord8 version >= 22) U32.bitGet
-  pure Loadout
-    { version
-    , body
-    , decal
-    , wheels
-    , rocketTrail
-    , antenna
-    , topper
-    , unknown1
-    , unknown2
-    , engineAudio
-    , trail
-    , goalExplosion
-    , banner
-    , unknown3
-    , unknown4
-    , unknown5
-    , unknown6
-    }
+  unknown2 <-
+    BitGet.label "unknown2" $
+      Monad.whenMaybe (U8.toWord8 version >= 11) U32.bitGet
+  engineAudio <-
+    BitGet.label "engineAudio" $
+      Monad.whenMaybe (U8.toWord8 version >= 16) U32.bitGet
+  trail <-
+    BitGet.label "trail" $
+      Monad.whenMaybe (U8.toWord8 version >= 16) U32.bitGet
+  goalExplosion <-
+    BitGet.label "goalExplosion" $
+      Monad.whenMaybe (U8.toWord8 version >= 16) U32.bitGet
+  banner <-
+    BitGet.label "banner" $
+      Monad.whenMaybe (U8.toWord8 version >= 17) U32.bitGet
+  unknown3 <-
+    BitGet.label "unknown3" $
+      Monad.whenMaybe (U8.toWord8 version >= 19) U32.bitGet
+  unknown4 <-
+    BitGet.label "unknown4" $
+      Monad.whenMaybe (U8.toWord8 version >= 22) U32.bitGet
+  unknown5 <-
+    BitGet.label "unknown5" $
+      Monad.whenMaybe (U8.toWord8 version >= 22) U32.bitGet
+  unknown6 <-
+    BitGet.label "unknown6" $
+      Monad.whenMaybe (U8.toWord8 version >= 22) U32.bitGet
+  pure
+    Loadout
+      { version,
+        body,
+        decal,
+        wheels,
+        rocketTrail,
+        antenna,
+        topper,
+        unknown1,
+        unknown2,
+        engineAudio,
+        trail,
+        goalExplosion,
+        banner,
+        unknown3,
+        unknown4,
+        unknown5,
+        unknown6
+      }
diff --git a/src/lib/Rattletrap/Type/Attribute/LoadoutOnline.hs b/src/lib/Rattletrap/Type/Attribute/LoadoutOnline.hs
--- a/src/lib/Rattletrap/Type/Attribute/LoadoutOnline.hs
+++ b/src/lib/Rattletrap/Type/Attribute/LoadoutOnline.hs
@@ -14,7 +14,8 @@
 
 newtype LoadoutOnline = LoadoutOnline
   { value :: List.List (List.List Product.Product)
-  } deriving (Eq, Show)
+  }
+  deriving (Eq, Show)
 
 instance Json.FromJSON LoadoutOnline where
   parseJSON = fmap LoadoutOnline . Json.parseJSON
@@ -32,16 +33,15 @@
 bitPut :: LoadoutOnline -> BitPut.BitPut
 bitPut loadoutAttribute =
   let attributes = List.toList $ value loadoutAttribute
-  in
-    (U8.bitPut . U8.fromWord8 . fromIntegral $ length attributes)
-      <> foldMap Product.putProductAttributes attributes
+   in (U8.bitPut . U8.fromWord8 . fromIntegral $ length attributes)
+        <> foldMap Product.putProductAttributes attributes
 
-bitGet
-  :: Version.Version -> Map.Map U32.U32 Str.Str -> BitGet.BitGet LoadoutOnline
+bitGet ::
+  Version.Version -> Map.Map U32.U32 Str.Str -> BitGet.BitGet LoadoutOnline
 bitGet version objectMap = BitGet.label "LoadoutOnline" $ do
   size <- BitGet.label "size" U8.bitGet
   value <-
     BitGet.label "value"
-    . List.replicateM (fromIntegral $ U8.toWord8 size)
-    $ Product.decodeProductAttributesBits version objectMap
-  pure LoadoutOnline { value }
+      . List.replicateM (fromIntegral $ U8.toWord8 size)
+      $ Product.decodeProductAttributesBits version objectMap
+  pure LoadoutOnline {value}
diff --git a/src/lib/Rattletrap/Type/Attribute/Loadouts.hs b/src/lib/Rattletrap/Type/Attribute/Loadouts.hs
--- a/src/lib/Rattletrap/Type/Attribute/Loadouts.hs
+++ b/src/lib/Rattletrap/Type/Attribute/Loadouts.hs
@@ -7,8 +7,8 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data Loadouts = Loadouts
-  { blue :: Loadout.Loadout
-  , orange :: Loadout.Loadout
+  { blue :: Loadout.Loadout,
+    orange :: Loadout.Loadout
   }
   deriving (Eq, Show)
 
@@ -16,24 +16,27 @@
   parseJSON = Json.withObject "Loadouts" $ \object -> do
     blue <- Json.required object "blue"
     orange <- Json.required object "orange"
-    pure Loadouts { blue, orange }
+    pure Loadouts {blue, orange}
 
 instance Json.ToJSON Loadouts where
   toJSON x =
     Json.object [Json.pair "blue" $ blue x, Json.pair "orange" $ orange x]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-loadouts" $ Schema.object
-  [ (Json.pair "blue" $ Schema.ref Loadout.schema, True)
-  , (Json.pair "orange" $ Schema.ref Loadout.schema, True)
-  ]
+schema =
+  Schema.named "attribute-loadouts" $
+    Schema.object
+      [ (Json.pair "blue" $ Schema.ref Loadout.schema, True),
+        (Json.pair "orange" $ Schema.ref Loadout.schema, True)
+      ]
 
 bitPut :: Loadouts -> BitPut.BitPut
-bitPut loadoutsAttribute = Loadout.bitPut (blue loadoutsAttribute)
-  <> Loadout.bitPut (orange loadoutsAttribute)
+bitPut loadoutsAttribute =
+  Loadout.bitPut (blue loadoutsAttribute)
+    <> Loadout.bitPut (orange loadoutsAttribute)
 
 bitGet :: BitGet.BitGet Loadouts
 bitGet = BitGet.label "Loadouts" $ do
   blue <- BitGet.label "blue" Loadout.bitGet
   orange <- BitGet.label "orange" Loadout.bitGet
-  pure Loadouts { blue, orange }
+  pure Loadouts {blue, orange}
diff --git a/src/lib/Rattletrap/Type/Attribute/LoadoutsOnline.hs b/src/lib/Rattletrap/Type/Attribute/LoadoutsOnline.hs
--- a/src/lib/Rattletrap/Type/Attribute/LoadoutsOnline.hs
+++ b/src/lib/Rattletrap/Type/Attribute/LoadoutsOnline.hs
@@ -11,10 +11,10 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data LoadoutsOnline = LoadoutsOnline
-  { blue :: LoadoutOnline.LoadoutOnline
-  , orange :: LoadoutOnline.LoadoutOnline
-  , unknown1 :: Bool
-  , unknown2 :: Bool
+  { blue :: LoadoutOnline.LoadoutOnline,
+    orange :: LoadoutOnline.LoadoutOnline,
+    unknown1 :: Bool,
+    unknown2 :: Bool
   }
   deriving (Eq, Show)
 
@@ -24,23 +24,26 @@
     orange <- Json.required object "orange"
     unknown1 <- Json.required object "unknown1"
     unknown2 <- Json.required object "unknown2"
-    pure LoadoutsOnline { blue, orange, unknown1, unknown2 }
+    pure LoadoutsOnline {blue, orange, unknown1, unknown2}
 
 instance Json.ToJSON LoadoutsOnline where
-  toJSON x = Json.object
-    [ Json.pair "blue" $ blue x
-    , Json.pair "orange" $ orange x
-    , Json.pair "unknown1" $ unknown1 x
-    , Json.pair "unknown2" $ unknown2 x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "blue" $ blue x,
+        Json.pair "orange" $ orange x,
+        Json.pair "unknown1" $ unknown1 x,
+        Json.pair "unknown2" $ unknown2 x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-loadouts-online" $ Schema.object
-  [ (Json.pair "blue" $ Schema.ref LoadoutOnline.schema, True)
-  , (Json.pair "orange" $ Schema.ref LoadoutOnline.schema, True)
-  , (Json.pair "unknown1" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "unknown2" $ Schema.ref Schema.boolean, True)
-  ]
+schema =
+  Schema.named "attribute-loadouts-online" $
+    Schema.object
+      [ (Json.pair "blue" $ Schema.ref LoadoutOnline.schema, True),
+        (Json.pair "orange" $ Schema.ref LoadoutOnline.schema, True),
+        (Json.pair "unknown1" $ Schema.ref Schema.boolean, True),
+        (Json.pair "unknown2" $ Schema.ref Schema.boolean, True)
+      ]
 
 bitPut :: LoadoutsOnline -> BitPut.BitPut
 bitPut loadoutsOnlineAttribute =
@@ -49,11 +52,11 @@
     <> BitPut.bool (unknown1 loadoutsOnlineAttribute)
     <> BitPut.bool (unknown2 loadoutsOnlineAttribute)
 
-bitGet
-  :: Version.Version -> Map.Map U32.U32 Str.Str -> BitGet.BitGet LoadoutsOnline
+bitGet ::
+  Version.Version -> Map.Map U32.U32 Str.Str -> BitGet.BitGet LoadoutsOnline
 bitGet version objectMap = BitGet.label "LoadoutsOnline" $ do
   blue <- BitGet.label "blue" $ LoadoutOnline.bitGet version objectMap
   orange <- BitGet.label "orange" $ LoadoutOnline.bitGet version objectMap
   unknown1 <- BitGet.label "unknown1" BitGet.bool
   unknown2 <- BitGet.label "unknown2" BitGet.bool
-  pure LoadoutsOnline { blue, orange, unknown1, unknown2 }
+  pure LoadoutsOnline {blue, orange, unknown1, unknown2}
diff --git a/src/lib/Rattletrap/Type/Attribute/Location.hs b/src/lib/Rattletrap/Type/Attribute/Location.hs
--- a/src/lib/Rattletrap/Type/Attribute/Location.hs
+++ b/src/lib/Rattletrap/Type/Attribute/Location.hs
@@ -9,7 +9,8 @@
 
 newtype Location = Location
   { value :: Vector.Vector
-  } deriving (Eq, Show)
+  }
+  deriving (Eq, Show)
 
 instance Json.FromJSON Location where
   parseJSON = fmap Location . Json.parseJSON
@@ -26,4 +27,4 @@
 bitGet :: Version.Version -> BitGet.BitGet Location
 bitGet version = BitGet.label "Location" $ do
   value <- BitGet.label "value" $ Vector.bitGet version
-  pure Location { value }
+  pure Location {value}
diff --git a/src/lib/Rattletrap/Type/Attribute/MusicStinger.hs b/src/lib/Rattletrap/Type/Attribute/MusicStinger.hs
--- a/src/lib/Rattletrap/Type/Attribute/MusicStinger.hs
+++ b/src/lib/Rattletrap/Type/Attribute/MusicStinger.hs
@@ -8,9 +8,9 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data MusicStinger = MusicStinger
-  { flag :: Bool
-  , cue :: U32.U32
-  , trigger :: U8.U8
+  { flag :: Bool,
+    cue :: U32.U32,
+    trigger :: U8.U8
   }
   deriving (Eq, Show)
 
@@ -19,21 +19,24 @@
     flag <- Json.required object "flag"
     cue <- Json.required object "cue"
     trigger <- Json.required object "trigger"
-    pure MusicStinger { flag, cue, trigger }
+    pure MusicStinger {flag, cue, trigger}
 
 instance Json.ToJSON MusicStinger where
-  toJSON x = Json.object
-    [ Json.pair "flag" $ flag x
-    , Json.pair "cue" $ cue x
-    , Json.pair "trigger" $ trigger x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "flag" $ flag x,
+        Json.pair "cue" $ cue x,
+        Json.pair "trigger" $ trigger x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-music-stinger" $ Schema.object
-  [ (Json.pair "flag" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "cue" $ Schema.ref U32.schema, True)
-  , (Json.pair "trigger" $ Schema.ref U8.schema, True)
-  ]
+schema =
+  Schema.named "attribute-music-stinger" $
+    Schema.object
+      [ (Json.pair "flag" $ Schema.ref Schema.boolean, True),
+        (Json.pair "cue" $ Schema.ref U32.schema, True),
+        (Json.pair "trigger" $ Schema.ref U8.schema, True)
+      ]
 
 bitPut :: MusicStinger -> BitPut.BitPut
 bitPut musicStingerAttribute =
@@ -46,4 +49,4 @@
   flag <- BitGet.label "flag" BitGet.bool
   cue <- BitGet.label "cue" U32.bitGet
   trigger <- BitGet.label "trigger" U8.bitGet
-  pure MusicStinger { flag, cue, trigger }
+  pure MusicStinger {flag, cue, trigger}
diff --git a/src/lib/Rattletrap/Type/Attribute/PartyLeader.hs b/src/lib/Rattletrap/Type/Attribute/PartyLeader.hs
--- a/src/lib/Rattletrap/Type/Attribute/PartyLeader.hs
+++ b/src/lib/Rattletrap/Type/Attribute/PartyLeader.hs
@@ -9,9 +9,9 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data PartyLeader = PartyLeader
-  { systemId :: U8.U8
-  , remoteId :: Maybe RemoteId.RemoteId
-  , localId :: Maybe U8.U8
+  { systemId :: U8.U8,
+    remoteId :: Maybe RemoteId.RemoteId,
+    localId :: Maybe U8.U8
   }
   deriving (Eq, Show)
 
@@ -19,44 +19,52 @@
   parseJSON = Json.withObject "PartyLeader" $ \object -> do
     systemId <- Json.required object "system_id"
     maybeId <- Json.optional object "id"
-    pure PartyLeader
-      { systemId
-      , remoteId = fmap fst maybeId
-      , localId = fmap snd maybeId
-      }
+    pure
+      PartyLeader
+        { systemId,
+          remoteId = fmap fst maybeId,
+          localId = fmap snd maybeId
+        }
 
 instance Json.ToJSON PartyLeader where
-  toJSON x = Json.object
-    [ Json.pair "system_id" $ systemId x
-    , Json.pair "id" $ case (remoteId x, localId x) of
-      (Just r, Just l) -> Just (r, l)
-      _ -> Nothing
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "system_id" $ systemId x,
+        Json.pair "id" $ case (remoteId x, localId x) of
+          (Just r, Just l) -> Just (r, l)
+          _ -> Nothing
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-party-leader" $ Schema.object
-  [ (Json.pair "system_id" $ Schema.ref U8.schema, True)
-  , ( Json.pair "id" $ Schema.oneOf
-      [ Schema.tuple [Schema.ref RemoteId.schema, Schema.ref U8.schema]
-      , Schema.ref Schema.null
+schema =
+  Schema.named "attribute-party-leader" $
+    Schema.object
+      [ (Json.pair "system_id" $ Schema.ref U8.schema, True),
+        ( Json.pair "id" $
+            Schema.oneOf
+              [ Schema.tuple [Schema.ref RemoteId.schema, Schema.ref U8.schema],
+                Schema.ref Schema.null
+              ],
+          False
+        )
       ]
-    , False
-    )
-  ]
 
 bitPut :: PartyLeader -> BitPut.BitPut
 bitPut x =
-  U8.bitPut (systemId x) <> foldMap RemoteId.bitPut (remoteId x) <> foldMap
-    U8.bitPut
-    (localId x)
+  U8.bitPut (systemId x)
+    <> foldMap RemoteId.bitPut (remoteId x)
+    <> foldMap
+      U8.bitPut
+      (localId x)
 
 bitGet :: Version.Version -> BitGet.BitGet PartyLeader
 bitGet version = BitGet.label "PartyLeader" $ do
   systemId <- BitGet.label "systemId" U8.bitGet
-  (remoteId, localId) <- if systemId == U8.fromWord8 0
-    then pure (Nothing, Nothing)
-    else do
-      remoteId <- BitGet.label "remoteId" $ RemoteId.bitGet version systemId
-      localId <- BitGet.label "localId" U8.bitGet
-      pure (Just remoteId, Just localId)
-  pure PartyLeader { systemId, remoteId, localId }
+  (remoteId, localId) <-
+    if systemId == U8.fromWord8 0
+      then pure (Nothing, Nothing)
+      else do
+        remoteId <- BitGet.label "remoteId" $ RemoteId.bitGet version systemId
+        localId <- BitGet.label "localId" U8.bitGet
+        pure (Just remoteId, Just localId)
+  pure PartyLeader {systemId, remoteId, localId}
diff --git a/src/lib/Rattletrap/Type/Attribute/Pickup.hs b/src/lib/Rattletrap/Type/Attribute/Pickup.hs
--- a/src/lib/Rattletrap/Type/Attribute/Pickup.hs
+++ b/src/lib/Rattletrap/Type/Attribute/Pickup.hs
@@ -8,8 +8,8 @@
 import qualified Rattletrap.Utility.Monad as Monad
 
 data Pickup = Pickup
-  { instigatorId :: Maybe U32.U32
-  , pickedUp :: Bool
+  { instigatorId :: Maybe U32.U32,
+    pickedUp :: Bool
   }
   deriving (Eq, Show)
 
@@ -17,32 +17,36 @@
   parseJSON = Json.withObject "Pickup" $ \object -> do
     instigatorId <- Json.optional object "instigator_id"
     pickedUp <- Json.required object "picked_up"
-    pure Pickup { instigatorId, pickedUp }
+    pure Pickup {instigatorId, pickedUp}
 
 instance Json.ToJSON Pickup where
-  toJSON x = Json.object
-    [ Json.pair "instigator_id" $ instigatorId x
-    , Json.pair "picked_up" $ pickedUp x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "instigator_id" $ instigatorId x,
+        Json.pair "picked_up" $ pickedUp x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-pickup" $ Schema.object
-  [ (Json.pair "instigator_id" . Schema.json $ Schema.maybe U32.schema, False)
-  , (Json.pair "picked_up" $ Schema.ref Schema.boolean, True)
-  ]
+schema =
+  Schema.named "attribute-pickup" $
+    Schema.object
+      [ (Json.pair "instigator_id" . Schema.json $ Schema.maybe U32.schema, False),
+        (Json.pair "picked_up" $ Schema.ref Schema.boolean, True)
+      ]
 
 bitPut :: Pickup -> BitPut.BitPut
 bitPut x =
   maybe
-      (BitPut.bool False)
-      (\y -> BitPut.bool True <> U32.bitPut y)
-      (instigatorId x)
+    (BitPut.bool False)
+    (\y -> BitPut.bool True <> U32.bitPut y)
+    (instigatorId x)
     <> BitPut.bool (pickedUp x)
 
 bitGet :: BitGet.BitGet Pickup
 bitGet = BitGet.label "Pickup" $ do
   instigator <- BitGet.label "instigator" BitGet.bool
-  instigatorId <- BitGet.label "instigatorId"
-    $ Monad.whenMaybe instigator U32.bitGet
+  instigatorId <-
+    BitGet.label "instigatorId" $
+      Monad.whenMaybe instigator U32.bitGet
   pickedUp <- BitGet.label "pickedUp" BitGet.bool
-  pure Pickup { instigatorId, pickedUp }
+  pure Pickup {instigatorId, pickedUp}
diff --git a/src/lib/Rattletrap/Type/Attribute/PickupInfo.hs b/src/lib/Rattletrap/Type/Attribute/PickupInfo.hs
--- a/src/lib/Rattletrap/Type/Attribute/PickupInfo.hs
+++ b/src/lib/Rattletrap/Type/Attribute/PickupInfo.hs
@@ -8,13 +8,13 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data PickupInfo = PickupInfo
-  { unknown1 :: Bool
-  , unknown2 :: Bool
-  , unknown3 :: U32.U32
-  , unknown4 :: I32.I32
-  , unknown5 :: I32.I32
-  , unknown6 :: Bool
-  , unknown7 :: Bool
+  { unknown1 :: Bool,
+    unknown2 :: Bool,
+    unknown3 :: U32.U32,
+    unknown4 :: I32.I32,
+    unknown5 :: I32.I32,
+    unknown6 :: Bool,
+    unknown7 :: Bool
   }
   deriving (Eq, Show)
 
@@ -27,37 +27,41 @@
     unknown5 <- Json.required object "unknown5"
     unknown6 <- Json.required object "unknown6"
     unknown7 <- Json.required object "unknown7"
-    pure PickupInfo
-      { unknown1
-      , unknown2
-      , unknown3
-      , unknown4
-      , unknown5
-      , unknown6
-      , unknown7
-      }
+    pure
+      PickupInfo
+        { unknown1,
+          unknown2,
+          unknown3,
+          unknown4,
+          unknown5,
+          unknown6,
+          unknown7
+        }
 
 instance Json.ToJSON PickupInfo where
-  toJSON x = Json.object
-    [ Json.pair "unknown1" $ unknown1 x
-    , Json.pair "unknown2" $ unknown2 x
-    , Json.pair "unknown3" $ unknown3 x
-    , Json.pair "unknown4" $ unknown4 x
-    , Json.pair "unknown5" $ unknown5 x
-    , Json.pair "unknown6" $ unknown6 x
-    , Json.pair "unknown7" $ unknown7 x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "unknown1" $ unknown1 x,
+        Json.pair "unknown2" $ unknown2 x,
+        Json.pair "unknown3" $ unknown3 x,
+        Json.pair "unknown4" $ unknown4 x,
+        Json.pair "unknown5" $ unknown5 x,
+        Json.pair "unknown6" $ unknown6 x,
+        Json.pair "unknown7" $ unknown7 x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "pickup-info" $ Schema.object
-  [ (Json.pair "unknown1" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "unknown2" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "unknown3" $ Schema.ref U32.schema, True)
-  , (Json.pair "unknown4" $ Schema.ref I32.schema, True)
-  , (Json.pair "unknown5" $ Schema.ref I32.schema, True)
-  , (Json.pair "unknown6" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "unknown7" $ Schema.ref Schema.boolean, True)
-  ]
+schema =
+  Schema.named "pickup-info" $
+    Schema.object
+      [ (Json.pair "unknown1" $ Schema.ref Schema.boolean, True),
+        (Json.pair "unknown2" $ Schema.ref Schema.boolean, True),
+        (Json.pair "unknown3" $ Schema.ref U32.schema, True),
+        (Json.pair "unknown4" $ Schema.ref I32.schema, True),
+        (Json.pair "unknown5" $ Schema.ref I32.schema, True),
+        (Json.pair "unknown6" $ Schema.ref Schema.boolean, True),
+        (Json.pair "unknown7" $ Schema.ref Schema.boolean, True)
+      ]
 
 bitPut :: PickupInfo -> BitPut.BitPut
 bitPut x =
@@ -78,12 +82,13 @@
   unknown5 <- BitGet.label "unknown5" I32.bitGet
   unknown6 <- BitGet.label "unknown6" BitGet.bool
   unknown7 <- BitGet.label "unknown7" BitGet.bool
-  pure PickupInfo
-    { unknown1
-    , unknown2
-    , unknown3
-    , unknown4
-    , unknown5
-    , unknown6
-    , unknown7
-    }
+  pure
+    PickupInfo
+      { unknown1,
+        unknown2,
+        unknown3,
+        unknown4,
+        unknown5,
+        unknown6,
+        unknown7
+      }
diff --git a/src/lib/Rattletrap/Type/Attribute/PickupNew.hs b/src/lib/Rattletrap/Type/Attribute/PickupNew.hs
--- a/src/lib/Rattletrap/Type/Attribute/PickupNew.hs
+++ b/src/lib/Rattletrap/Type/Attribute/PickupNew.hs
@@ -9,8 +9,8 @@
 import qualified Rattletrap.Utility.Monad as Monad
 
 data PickupNew = PickupNew
-  { instigatorId :: Maybe U32.U32
-  , pickedUp :: U8.U8
+  { instigatorId :: Maybe U32.U32,
+    pickedUp :: U8.U8
   }
   deriving (Eq, Show)
 
@@ -18,32 +18,36 @@
   parseJSON = Json.withObject "PickupNew" $ \object -> do
     instigatorId <- Json.optional object "instigator_id"
     pickedUp <- Json.required object "picked_up"
-    pure PickupNew { instigatorId, pickedUp }
+    pure PickupNew {instigatorId, pickedUp}
 
 instance Json.ToJSON PickupNew where
-  toJSON x = Json.object
-    [ Json.pair "instigator_id" $ instigatorId x
-    , Json.pair "picked_up" $ pickedUp x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "instigator_id" $ instigatorId x,
+        Json.pair "picked_up" $ pickedUp x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-pickup-new" $ Schema.object
-  [ (Json.pair "instigator_id" . Schema.json $ Schema.maybe U32.schema, False)
-  , (Json.pair "picked_up" $ Schema.ref U8.schema, True)
-  ]
+schema =
+  Schema.named "attribute-pickup-new" $
+    Schema.object
+      [ (Json.pair "instigator_id" . Schema.json $ Schema.maybe U32.schema, False),
+        (Json.pair "picked_up" $ Schema.ref U8.schema, True)
+      ]
 
 bitPut :: PickupNew -> BitPut.BitPut
 bitPut x =
   maybe
-      (BitPut.bool False)
-      (\y -> BitPut.bool True <> U32.bitPut y)
-      (instigatorId x)
+    (BitPut.bool False)
+    (\y -> BitPut.bool True <> U32.bitPut y)
+    (instigatorId x)
     <> U8.bitPut (pickedUp x)
 
 bitGet :: BitGet.BitGet PickupNew
 bitGet = BitGet.label "PickupNew" $ do
   instigator <- BitGet.label "instigator" BitGet.bool
-  instigatorId <- BitGet.label "instigatorId"
-    $ Monad.whenMaybe instigator U32.bitGet
+  instigatorId <-
+    BitGet.label "instigatorId" $
+      Monad.whenMaybe instigator U32.bitGet
   pickedUp <- BitGet.label "pickedUp" U8.bitGet
-  pure PickupNew { instigatorId, pickedUp }
+  pure PickupNew {instigatorId, pickedUp}
diff --git a/src/lib/Rattletrap/Type/Attribute/PlayerHistoryKey.hs b/src/lib/Rattletrap/Type/Attribute/PlayerHistoryKey.hs
--- a/src/lib/Rattletrap/Type/Attribute/PlayerHistoryKey.hs
+++ b/src/lib/Rattletrap/Type/Attribute/PlayerHistoryKey.hs
@@ -8,7 +8,8 @@
 
 newtype PlayerHistoryKey = PlayerHistoryKey
   { unknown :: Word.Word16
-  } deriving (Eq, Show)
+  }
+  deriving (Eq, Show)
 
 instance Json.FromJSON PlayerHistoryKey where
   parseJSON = fmap PlayerHistoryKey . Json.parseJSON
@@ -26,4 +27,4 @@
 bitGet :: BitGet.BitGet PlayerHistoryKey
 bitGet = BitGet.label "PlayerHistoryKey" $ do
   unknown <- BitGet.label "unknown" $ BitGet.bits 14
-  pure PlayerHistoryKey { unknown }
+  pure PlayerHistoryKey {unknown}
diff --git a/src/lib/Rattletrap/Type/Attribute/PrivateMatchSettings.hs b/src/lib/Rattletrap/Type/Attribute/PrivateMatchSettings.hs
--- a/src/lib/Rattletrap/Type/Attribute/PrivateMatchSettings.hs
+++ b/src/lib/Rattletrap/Type/Attribute/PrivateMatchSettings.hs
@@ -8,12 +8,12 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data PrivateMatchSettings = PrivateMatchSettings
-  { mutators :: Str.Str
-  , joinableBy :: U32.U32
-  , maxPlayers :: U32.U32
-  , gameName :: Str.Str
-  , password :: Str.Str
-  , flag :: Bool
+  { mutators :: Str.Str,
+    joinableBy :: U32.U32,
+    maxPlayers :: U32.U32,
+    gameName :: Str.Str,
+    password :: Str.Str,
+    flag :: Bool
   }
   deriving (Eq, Show)
 
@@ -25,34 +25,38 @@
     gameName <- Json.required object "game_name"
     password <- Json.required object "password"
     flag <- Json.required object "flag"
-    pure PrivateMatchSettings
-      { mutators
-      , joinableBy
-      , maxPlayers
-      , gameName
-      , password
-      , flag
-      }
+    pure
+      PrivateMatchSettings
+        { mutators,
+          joinableBy,
+          maxPlayers,
+          gameName,
+          password,
+          flag
+        }
 
 instance Json.ToJSON PrivateMatchSettings where
-  toJSON x = Json.object
-    [ Json.pair "mutators" $ mutators x
-    , Json.pair "joinable_by" $ joinableBy x
-    , Json.pair "max_players" $ maxPlayers x
-    , Json.pair "game_name" $ gameName x
-    , Json.pair "password" $ password x
-    , Json.pair "flag" $ flag x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "mutators" $ mutators x,
+        Json.pair "joinable_by" $ joinableBy x,
+        Json.pair "max_players" $ maxPlayers x,
+        Json.pair "game_name" $ gameName x,
+        Json.pair "password" $ password x,
+        Json.pair "flag" $ flag x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-private-match-settings" $ Schema.object
-  [ (Json.pair "mutators" $ Schema.ref Str.schema, True)
-  , (Json.pair "joinable_by" $ Schema.ref U32.schema, True)
-  , (Json.pair "max_players" $ Schema.ref U32.schema, True)
-  , (Json.pair "game_name" $ Schema.ref Str.schema, True)
-  , (Json.pair "password" $ Schema.ref Str.schema, True)
-  , (Json.pair "flag" $ Schema.ref Schema.boolean, True)
-  ]
+schema =
+  Schema.named "attribute-private-match-settings" $
+    Schema.object
+      [ (Json.pair "mutators" $ Schema.ref Str.schema, True),
+        (Json.pair "joinable_by" $ Schema.ref U32.schema, True),
+        (Json.pair "max_players" $ Schema.ref U32.schema, True),
+        (Json.pair "game_name" $ Schema.ref Str.schema, True),
+        (Json.pair "password" $ Schema.ref Str.schema, True),
+        (Json.pair "flag" $ Schema.ref Schema.boolean, True)
+      ]
 
 bitPut :: PrivateMatchSettings -> BitPut.BitPut
 bitPut privateMatchSettingsAttribute =
@@ -71,11 +75,12 @@
   gameName <- BitGet.label "gameName" Str.bitGet
   password <- BitGet.label "password" Str.bitGet
   flag <- BitGet.label "flag" BitGet.bool
-  pure PrivateMatchSettings
-    { mutators
-    , joinableBy
-    , maxPlayers
-    , gameName
-    , password
-    , flag
-    }
+  pure
+    PrivateMatchSettings
+      { mutators,
+        joinableBy,
+        maxPlayers,
+        gameName,
+        password,
+        flag
+      }
diff --git a/src/lib/Rattletrap/Type/Attribute/Product.hs b/src/lib/Rattletrap/Type/Attribute/Product.hs
--- a/src/lib/Rattletrap/Type/Attribute/Product.hs
+++ b/src/lib/Rattletrap/Type/Attribute/Product.hs
@@ -13,11 +13,11 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data Product = Product
-  { unknown :: Bool
-  , objectId :: U32.U32
-  , objectName :: Maybe Str.Str
-  -- ^ read-only
-  , value :: ProductValue.ProductValue
+  { unknown :: Bool,
+    objectId :: U32.U32,
+    -- | read-only
+    objectName :: Maybe Str.Str,
+    value :: ProductValue.ProductValue
   }
   deriving (Eq, Show)
 
@@ -27,28 +27,31 @@
     objectId <- Json.required object "object_id"
     objectName <- Json.optional object "object_name"
     value <- Json.required object "value"
-    pure Product { unknown, objectId, objectName, value }
+    pure Product {unknown, objectId, objectName, value}
 
 instance Json.ToJSON Product where
-  toJSON x = Json.object
-    [ Json.pair "unknown" $ unknown x
-    , Json.pair "object_id" $ objectId x
-    , Json.pair "object_name" $ objectName x
-    , Json.pair "value" $ value x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "unknown" $ unknown x,
+        Json.pair "object_id" $ objectId x,
+        Json.pair "object_name" $ objectName x,
+        Json.pair "value" $ value x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-product" $ Schema.object
-  [ (Json.pair "unknown" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "object_id" $ Schema.ref U32.schema, True)
-  , (Json.pair "object_name" . Schema.json $ Schema.maybe Str.schema, False)
-  , (Json.pair "value" $ Schema.ref ProductValue.schema, True)
-  ]
+schema =
+  Schema.named "attribute-product" $
+    Schema.object
+      [ (Json.pair "unknown" $ Schema.ref Schema.boolean, True),
+        (Json.pair "object_id" $ Schema.ref U32.schema, True),
+        (Json.pair "object_name" . Schema.json $ Schema.maybe Str.schema, False),
+        (Json.pair "value" $ Schema.ref ProductValue.schema, True)
+      ]
 
 putProductAttributes :: List.List Product -> BitPut.BitPut
 putProductAttributes attributes =
   let v = List.toList attributes
-  in (U8.bitPut . U8.fromWord8 . fromIntegral $ length v) <> foldMap bitPut v
+   in (U8.bitPut . U8.fromWord8 . fromIntegral $ length v) <> foldMap bitPut v
 
 bitPut :: Product -> BitPut.BitPut
 bitPut attribute =
@@ -56,10 +59,10 @@
     <> U32.bitPut (objectId attribute)
     <> ProductValue.bitPut (value attribute)
 
-decodeProductAttributesBits
-  :: Version.Version
-  -> Map.Map U32.U32 Str.Str
-  -> BitGet.BitGet (List.List Product)
+decodeProductAttributesBits ::
+  Version.Version ->
+  Map.Map U32.U32 Str.Str ->
+  BitGet.BitGet (List.List Product)
 decodeProductAttributesBits version objectMap = do
   size <- U8.bitGet
   List.replicateM (fromIntegral $ U8.toWord8 size) $ bitGet version objectMap
@@ -69,6 +72,7 @@
   unknown <- BitGet.label "unknown" BitGet.bool
   objectId <- BitGet.label "objectId" U32.bitGet
   let objectName = Map.lookup objectId objectMap
-  value <- BitGet.label "value"
-    $ ProductValue.bitGet version objectId objectName
-  pure Product { unknown, objectId, objectName, value }
+  value <-
+    BitGet.label "value" $
+      ProductValue.bitGet version objectId objectName
+  pure Product {unknown, objectId, objectName, value}
diff --git a/src/lib/Rattletrap/Type/Attribute/ProductValue.hs b/src/lib/Rattletrap/Type/Attribute/ProductValue.hs
--- a/src/lib/Rattletrap/Type/Attribute/ProductValue.hs
+++ b/src/lib/Rattletrap/Type/Attribute/ProductValue.hs
@@ -26,16 +26,17 @@
   deriving (Eq, Show)
 
 instance Json.FromJSON ProductValue where
-  parseJSON = Json.withObject "ProductValue" $ \object -> Foldable.asum
-    [ fmap PaintedOld $ Json.required object "painted_old"
-    , fmap PaintedNew $ Json.required object "painted_new"
-    , fmap TeamEditionOld $ Json.required object "team_edition_old"
-    , fmap TeamEditionNew $ Json.required object "team_edition_new"
-    , fmap SpecialEdition $ Json.required object "special_edition"
-    , fmap UserColorOld $ Json.required object "user_color_old"
-    , fmap UserColorNew $ Json.required object "user_color_new"
-    , fmap TitleId $ Json.required object "title_id"
-    ]
+  parseJSON = Json.withObject "ProductValue" $ \object ->
+    Foldable.asum
+      [ fmap PaintedOld $ Json.required object "painted_old",
+        fmap PaintedNew $ Json.required object "painted_new",
+        fmap TeamEditionOld $ Json.required object "team_edition_old",
+        fmap TeamEditionNew $ Json.required object "team_edition_new",
+        fmap SpecialEdition $ Json.required object "special_edition",
+        fmap UserColorOld $ Json.required object "user_color_old",
+        fmap UserColorNew $ Json.required object "user_color_new",
+        fmap TitleId $ Json.required object "title_id"
+      ]
 
 instance Json.ToJSON ProductValue where
   toJSON x = case x of
@@ -49,17 +50,19 @@
     TitleId y -> Json.object [Json.pair "title_id" y]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-product-value" . Schema.oneOf $ fmap
-  (\(k, v) -> Schema.object [(Json.pair k v, True)])
-  [ ("painted_old", Schema.ref CompressedWord.schema)
-  , ("painted_new", Schema.ref Schema.integer)
-  , ("team_edition_old", Schema.ref CompressedWord.schema)
-  , ("team_edition_new", Schema.ref Schema.integer)
-  , ("special_edition", Schema.ref Schema.integer)
-  , ("user_color_old", Schema.json $ Schema.maybe Schema.integer)
-  , ("user_color_new", Schema.ref U32.schema)
-  , ("title_id", Schema.ref Str.schema)
-  ]
+schema =
+  Schema.named "attribute-product-value" . Schema.oneOf $
+    fmap
+      (\(k, v) -> Schema.object [(Json.pair k v, True)])
+      [ ("painted_old", Schema.ref CompressedWord.schema),
+        ("painted_new", Schema.ref Schema.integer),
+        ("team_edition_old", Schema.ref CompressedWord.schema),
+        ("team_edition_new", Schema.ref Schema.integer),
+        ("special_edition", Schema.ref Schema.integer),
+        ("user_color_old", Schema.json $ Schema.maybe Schema.integer),
+        ("user_color_new", Schema.ref U32.schema),
+        ("title_id", Schema.ref Str.schema)
+      ]
 
 bitPut :: ProductValue -> BitPut.BitPut
 bitPut val = case val of
@@ -74,8 +77,8 @@
   UserColorNew x -> U32.bitPut x
   TitleId x -> Str.bitPut x
 
-bitGet
-  :: Version.Version -> U32.U32 -> Maybe Str.Str -> BitGet.BitGet ProductValue
+bitGet ::
+  Version.Version -> U32.U32 -> Maybe Str.Str -> BitGet.BitGet ProductValue
 bitGet version objectId maybeObjectName =
   BitGet.label "ProductValue" $ case fmap Str.toString maybeObjectName of
     Just "TAGame.ProductAttribute_Painted_TA" -> decodePainted version
@@ -85,31 +88,36 @@
     Just "TAGame.ProductAttribute_UserColor_TA" -> decodeColor version
     Just x -> BitGet.throw $ UnknownProduct.UnknownProduct x
     Nothing ->
-      BitGet.throw . MissingProductName.MissingProductName $ U32.toWord32
-        objectId
+      BitGet.throw . MissingProductName.MissingProductName $
+        U32.toWord32
+          objectId
 
 decodeSpecialEdition :: BitGet.BitGet ProductValue
 decodeSpecialEdition =
   BitGet.label "SpecialEdition" . fmap SpecialEdition $ BitGet.bits 31
 
 decodePainted :: Version.Version -> BitGet.BitGet ProductValue
-decodePainted version = BitGet.label "Painted" $ if hasNewPainted version
-  then fmap PaintedNew $ BitGet.bits 31
-  else fmap PaintedOld $ CompressedWord.bitGet 13
+decodePainted version =
+  BitGet.label "Painted" $
+    if hasNewPainted version
+      then fmap PaintedNew $ BitGet.bits 31
+      else fmap PaintedOld $ CompressedWord.bitGet 13
 
 decodeTeamEdition :: Version.Version -> BitGet.BitGet ProductValue
 decodeTeamEdition version =
-  BitGet.label "TeamEdition" $ if hasNewPainted version
-    then fmap TeamEditionNew $ BitGet.bits 31
-    else fmap TeamEditionOld $ CompressedWord.bitGet 13
+  BitGet.label "TeamEdition" $
+    if hasNewPainted version
+      then fmap TeamEditionNew $ BitGet.bits 31
+      else fmap TeamEditionOld $ CompressedWord.bitGet 13
 
 decodeColor :: Version.Version -> BitGet.BitGet ProductValue
 decodeColor version =
-  BitGet.label "UserColor" $ if Version.atLeast 868 23 8 version
-    then fmap UserColorNew U32.bitGet
-    else do
-      hasValue <- BitGet.bool
-      fmap UserColorOld $ Monad.whenMaybe hasValue (BitGet.bits 31)
+  BitGet.label "UserColor" $
+    if Version.atLeast 868 23 8 version
+      then fmap UserColorNew U32.bitGet
+      else do
+        hasValue <- BitGet.bool
+        fmap UserColorOld $ Monad.whenMaybe hasValue (BitGet.bits 31)
 
 hasNewPainted :: Version.Version -> Bool
 hasNewPainted = Version.atLeast 868 18 0
diff --git a/src/lib/Rattletrap/Type/Attribute/QWord.hs b/src/lib/Rattletrap/Type/Attribute/QWord.hs
--- a/src/lib/Rattletrap/Type/Attribute/QWord.hs
+++ b/src/lib/Rattletrap/Type/Attribute/QWord.hs
@@ -8,7 +8,8 @@
 
 newtype QWord = QWord
   { value :: U64.U64
-  } deriving (Eq, Show)
+  }
+  deriving (Eq, Show)
 
 instance Json.FromJSON QWord where
   parseJSON = fmap QWord . Json.parseJSON
@@ -25,4 +26,4 @@
 bitGet :: BitGet.BitGet QWord
 bitGet = BitGet.label "QWord" $ do
   value <- BitGet.label "value" U64.bitGet
-  pure QWord { value }
+  pure QWord {value}
diff --git a/src/lib/Rattletrap/Type/Attribute/RepStatTitle.hs b/src/lib/Rattletrap/Type/Attribute/RepStatTitle.hs
--- a/src/lib/Rattletrap/Type/Attribute/RepStatTitle.hs
+++ b/src/lib/Rattletrap/Type/Attribute/RepStatTitle.hs
@@ -9,10 +9,10 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data RepStatTitle = RepStatTitle
-  { unknown :: Bool
-  , name :: Str.Str
-  , target :: FlaggedInt.FlaggedInt
-  , value :: U32.U32
+  { unknown :: Bool,
+    name :: Str.Str,
+    target :: FlaggedInt.FlaggedInt,
+    value :: U32.U32
   }
   deriving (Eq, Show)
 
@@ -22,23 +22,26 @@
     name <- Json.required object "name"
     target <- Json.required object "target"
     value <- Json.required object "value"
-    pure RepStatTitle { unknown, name, target, value }
+    pure RepStatTitle {unknown, name, target, value}
 
 instance Json.ToJSON RepStatTitle where
-  toJSON x = Json.object
-    [ Json.pair "unknown" $ unknown x
-    , Json.pair "name" $ name x
-    , Json.pair "target" $ target x
-    , Json.pair "value" $ value x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "unknown" $ unknown x,
+        Json.pair "name" $ name x,
+        Json.pair "target" $ target x,
+        Json.pair "value" $ value x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-rep-stat-title" $ Schema.object
-  [ (Json.pair "unknown" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "name" $ Schema.ref Str.schema, True)
-  , (Json.pair "target" $ Schema.ref FlaggedInt.schema, True)
-  , (Json.pair "value" $ Schema.ref U32.schema, True)
-  ]
+schema =
+  Schema.named "attribute-rep-stat-title" $
+    Schema.object
+      [ (Json.pair "unknown" $ Schema.ref Schema.boolean, True),
+        (Json.pair "name" $ Schema.ref Str.schema, True),
+        (Json.pair "target" $ Schema.ref FlaggedInt.schema, True),
+        (Json.pair "value" $ Schema.ref U32.schema, True)
+      ]
 
 bitPut :: RepStatTitle -> BitPut.BitPut
 bitPut x =
@@ -53,4 +56,4 @@
   name <- BitGet.label "name" Str.bitGet
   target <- BitGet.label "target" FlaggedInt.bitGet
   value <- BitGet.label "value" U32.bitGet
-  pure RepStatTitle { unknown, name, target, value }
+  pure RepStatTitle {unknown, name, target, value}
diff --git a/src/lib/Rattletrap/Type/Attribute/Reservation.hs b/src/lib/Rattletrap/Type/Attribute/Reservation.hs
--- a/src/lib/Rattletrap/Type/Attribute/Reservation.hs
+++ b/src/lib/Rattletrap/Type/Attribute/Reservation.hs
@@ -13,12 +13,12 @@
 import qualified Rattletrap.Utility.Monad as Monad
 
 data Reservation = Reservation
-  { number :: CompressedWord.CompressedWord
-  , uniqueId :: UniqueId.UniqueId
-  , name :: Maybe Str.Str
-  , unknown1 :: Bool
-  , unknown2 :: Bool
-  , unknown3 :: Maybe Word.Word8
+  { number :: CompressedWord.CompressedWord,
+    uniqueId :: UniqueId.UniqueId,
+    name :: Maybe Str.Str,
+    unknown1 :: Bool,
+    unknown2 :: Bool,
+    unknown3 :: Maybe Word.Word8
   }
   deriving (Eq, Show)
 
@@ -30,27 +30,30 @@
     unknown1 <- Json.required object "unknown1"
     unknown2 <- Json.required object "unknown2"
     unknown3 <- Json.optional object "unknown3"
-    pure Reservation { number, uniqueId, name, unknown1, unknown2, unknown3 }
+    pure Reservation {number, uniqueId, name, unknown1, unknown2, unknown3}
 
 instance Json.ToJSON Reservation where
-  toJSON x = Json.object
-    [ Json.pair "number" $ number x
-    , Json.pair "unique_id" $ uniqueId x
-    , Json.pair "name" $ name x
-    , Json.pair "unknown1" $ unknown1 x
-    , Json.pair "unknown2" $ unknown2 x
-    , Json.pair "unknown3" $ unknown3 x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "number" $ number x,
+        Json.pair "unique_id" $ uniqueId x,
+        Json.pair "name" $ name x,
+        Json.pair "unknown1" $ unknown1 x,
+        Json.pair "unknown2" $ unknown2 x,
+        Json.pair "unknown3" $ unknown3 x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-reservation" $ Schema.object
-  [ (Json.pair "number" $ Schema.ref CompressedWord.schema, True)
-  , (Json.pair "unique_id" $ Schema.ref UniqueId.schema, True)
-  , (Json.pair "name" . Schema.json $ Schema.maybe Str.schema, False)
-  , (Json.pair "unknown1" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "unknown2" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "unknown3" . Schema.json $ Schema.maybe Schema.integer, False)
-  ]
+schema =
+  Schema.named "attribute-reservation" $
+    Schema.object
+      [ (Json.pair "number" $ Schema.ref CompressedWord.schema, True),
+        (Json.pair "unique_id" $ Schema.ref UniqueId.schema, True),
+        (Json.pair "name" . Schema.json $ Schema.maybe Str.schema, False),
+        (Json.pair "unknown1" $ Schema.ref Schema.boolean, True),
+        (Json.pair "unknown2" $ Schema.ref Schema.boolean, True),
+        (Json.pair "unknown3" . Schema.json $ Schema.maybe Schema.integer, False)
+      ]
 
 bitPut :: Reservation -> BitPut.BitPut
 bitPut reservationAttribute =
@@ -65,13 +68,15 @@
 bitGet version = BitGet.label "Reservation" $ do
   number <- BitGet.label "number" $ CompressedWord.bitGet 7
   uniqueId <- BitGet.label "uniqueId" $ UniqueId.bitGet version
-  name <- BitGet.label "name" $ Monad.whenMaybe
-    (UniqueId.systemId uniqueId /= U8.fromWord8 0)
-    Str.bitGet
+  name <-
+    BitGet.label "name" $
+      Monad.whenMaybe
+        (UniqueId.systemId uniqueId /= U8.fromWord8 0)
+        Str.bitGet
   unknown1 <- BitGet.label "unknown1" BitGet.bool
   unknown2 <- BitGet.label "unknown2" BitGet.bool
   unknown3 <-
     BitGet.label "unknown3"
-    . Monad.whenMaybe (Version.atLeast 868 12 0 version)
-    $ BitGet.bits 6
-  pure Reservation { number, uniqueId, name, unknown1, unknown2, unknown3 }
+      . Monad.whenMaybe (Version.atLeast 868 12 0 version)
+      $ BitGet.bits 6
+  pure Reservation {number, uniqueId, name, unknown1, unknown2, unknown3}
diff --git a/src/lib/Rattletrap/Type/Attribute/RigidBodyState.hs b/src/lib/Rattletrap/Type/Attribute/RigidBodyState.hs
--- a/src/lib/Rattletrap/Type/Attribute/RigidBodyState.hs
+++ b/src/lib/Rattletrap/Type/Attribute/RigidBodyState.hs
@@ -10,11 +10,11 @@
 import qualified Rattletrap.Utility.Monad as Monad
 
 data RigidBodyState = RigidBodyState
-  { sleeping :: Bool
-  , location :: Vector.Vector
-  , rotation :: Rotation.Rotation
-  , linearVelocity :: Maybe Vector.Vector
-  , angularVelocity :: Maybe Vector.Vector
+  { sleeping :: Bool,
+    location :: Vector.Vector,
+    rotation :: Rotation.Rotation,
+    linearVelocity :: Maybe Vector.Vector,
+    angularVelocity :: Maybe Vector.Vector
   }
   deriving (Eq, Show)
 
@@ -25,35 +25,39 @@
     rotation <- Json.required object "rotation"
     linearVelocity <- Json.optional object "linear_velocity"
     angularVelocity <- Json.optional object "angular_velocity"
-    pure RigidBodyState
-      { sleeping
-      , location
-      , rotation
-      , linearVelocity
-      , angularVelocity
-      }
+    pure
+      RigidBodyState
+        { sleeping,
+          location,
+          rotation,
+          linearVelocity,
+          angularVelocity
+        }
 
 instance Json.ToJSON RigidBodyState where
-  toJSON x = Json.object
-    [ Json.pair "sleeping" $ sleeping x
-    , Json.pair "location" $ location x
-    , Json.pair "rotation" $ rotation x
-    , Json.pair "linear_velocity" $ linearVelocity x
-    , Json.pair "angular_velocity" $ angularVelocity x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "sleeping" $ sleeping x,
+        Json.pair "location" $ location x,
+        Json.pair "rotation" $ rotation x,
+        Json.pair "linear_velocity" $ linearVelocity x,
+        Json.pair "angular_velocity" $ angularVelocity x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-rigid-body-state" $ Schema.object
-  [ (Json.pair "sleeping" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "location" $ Schema.ref Vector.schema, True)
-  , (Json.pair "rotation" $ Schema.ref Rotation.schema, True)
-  , ( Json.pair "linear_velocity" . Schema.json $ Schema.maybe Vector.schema
-    , False
-    )
-  , ( Json.pair "angular_velocity" . Schema.json $ Schema.maybe Vector.schema
-    , False
-    )
-  ]
+schema =
+  Schema.named "attribute-rigid-body-state" $
+    Schema.object
+      [ (Json.pair "sleeping" $ Schema.ref Schema.boolean, True),
+        (Json.pair "location" $ Schema.ref Vector.schema, True),
+        (Json.pair "rotation" $ Schema.ref Rotation.schema, True),
+        ( Json.pair "linear_velocity" . Schema.json $ Schema.maybe Vector.schema,
+          False
+        ),
+        ( Json.pair "angular_velocity" . Schema.json $ Schema.maybe Vector.schema,
+          False
+        )
+      ]
 
 bitPut :: RigidBodyState -> BitPut.BitPut
 bitPut rigidBodyStateAttribute =
@@ -68,14 +72,17 @@
   sleeping <- BitGet.label "sleeping" BitGet.bool
   location <- BitGet.label "location" $ Vector.bitGet version
   rotation <- BitGet.label "rotation" $ Rotation.bitGet version
-  linearVelocity <- BitGet.label "linearVelocity"
-    $ Monad.whenMaybe (not sleeping) (Vector.bitGet version)
-  angularVelocity <- BitGet.label "angularVelocity"
-    $ Monad.whenMaybe (not sleeping) (Vector.bitGet version)
-  pure RigidBodyState
-    { sleeping
-    , location
-    , rotation
-    , linearVelocity
-    , angularVelocity
-    }
+  linearVelocity <-
+    BitGet.label "linearVelocity" $
+      Monad.whenMaybe (not sleeping) (Vector.bitGet version)
+  angularVelocity <-
+    BitGet.label "angularVelocity" $
+      Monad.whenMaybe (not sleeping) (Vector.bitGet version)
+  pure
+    RigidBodyState
+      { sleeping,
+        location,
+        rotation,
+        linearVelocity,
+        angularVelocity
+      }
diff --git a/src/lib/Rattletrap/Type/Attribute/Rotation.hs b/src/lib/Rattletrap/Type/Attribute/Rotation.hs
--- a/src/lib/Rattletrap/Type/Attribute/Rotation.hs
+++ b/src/lib/Rattletrap/Type/Attribute/Rotation.hs
@@ -8,7 +8,8 @@
 
 newtype Rotation = Rotation
   { value :: Int8Vector.Int8Vector
-  } deriving (Eq, Show)
+  }
+  deriving (Eq, Show)
 
 instance Json.FromJSON Rotation where
   parseJSON = fmap Rotation . Json.parseJSON
@@ -25,4 +26,4 @@
 bitGet :: BitGet.BitGet Rotation
 bitGet = BitGet.label "Rotation" $ do
   value <- BitGet.label "value" Int8Vector.bitGet
-  pure Rotation { value }
+  pure Rotation {value}
diff --git a/src/lib/Rattletrap/Type/Attribute/StatEvent.hs b/src/lib/Rattletrap/Type/Attribute/StatEvent.hs
--- a/src/lib/Rattletrap/Type/Attribute/StatEvent.hs
+++ b/src/lib/Rattletrap/Type/Attribute/StatEvent.hs
@@ -7,8 +7,8 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data StatEvent = StatEvent
-  { unknown :: Bool
-  , objectId :: I32.I32
+  { unknown :: Bool,
+    objectId :: I32.I32
   }
   deriving (Eq, Show)
 
@@ -16,24 +16,28 @@
   parseJSON = Json.withObject "StatEvent" $ \object -> do
     unknown <- Json.required object "unknown"
     objectId <- Json.required object "object_id"
-    pure StatEvent { unknown, objectId }
+    pure StatEvent {unknown, objectId}
 
 instance Json.ToJSON StatEvent where
-  toJSON x = Json.object
-    [Json.pair "unknown" $ unknown x, Json.pair "object_id" $ objectId x]
+  toJSON x =
+    Json.object
+      [Json.pair "unknown" $ unknown x, Json.pair "object_id" $ objectId x]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-stat-event" $ Schema.object
-  [ (Json.pair "unknown" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "object_id" $ Schema.ref I32.schema, True)
-  ]
+schema =
+  Schema.named "attribute-stat-event" $
+    Schema.object
+      [ (Json.pair "unknown" $ Schema.ref Schema.boolean, True),
+        (Json.pair "object_id" $ Schema.ref I32.schema, True)
+      ]
 
 bitPut :: StatEvent -> BitPut.BitPut
-bitPut statEventAttribute = BitPut.bool (unknown statEventAttribute)
-  <> I32.bitPut (objectId statEventAttribute)
+bitPut statEventAttribute =
+  BitPut.bool (unknown statEventAttribute)
+    <> I32.bitPut (objectId statEventAttribute)
 
 bitGet :: BitGet.BitGet StatEvent
 bitGet = BitGet.label "StatEvent" $ do
   unknown <- BitGet.label "unknown" BitGet.bool
   objectId <- BitGet.label "objectId" I32.bitGet
-  pure StatEvent { unknown, objectId }
+  pure StatEvent {unknown, objectId}
diff --git a/src/lib/Rattletrap/Type/Attribute/String.hs b/src/lib/Rattletrap/Type/Attribute/String.hs
--- a/src/lib/Rattletrap/Type/Attribute/String.hs
+++ b/src/lib/Rattletrap/Type/Attribute/String.hs
@@ -1,15 +1,16 @@
 module Rattletrap.Type.Attribute.String where
 
-import Prelude hiding (String)
 import qualified Rattletrap.BitGet as BitGet
 import qualified Rattletrap.BitPut as BitPut
 import qualified Rattletrap.Schema as Schema
 import qualified Rattletrap.Type.Str as Str
 import qualified Rattletrap.Utility.Json as Json
+import Prelude hiding (String)
 
 newtype String = String
   { value :: Str.Str
-  } deriving (Eq, Show)
+  }
+  deriving (Eq, Show)
 
 instance Json.FromJSON String where
   parseJSON = fmap String . Json.parseJSON
@@ -26,4 +27,4 @@
 bitGet :: BitGet.BitGet String
 bitGet = BitGet.label "String" $ do
   value <- BitGet.label "value" Str.bitGet
-  pure String { value }
+  pure String {value}
diff --git a/src/lib/Rattletrap/Type/Attribute/TeamPaint.hs b/src/lib/Rattletrap/Type/Attribute/TeamPaint.hs
--- a/src/lib/Rattletrap/Type/Attribute/TeamPaint.hs
+++ b/src/lib/Rattletrap/Type/Attribute/TeamPaint.hs
@@ -8,11 +8,11 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data TeamPaint = TeamPaint
-  { team :: U8.U8
-  , primaryColor :: U8.U8
-  , accentColor :: U8.U8
-  , primaryFinish :: U32.U32
-  , accentFinish :: U32.U32
+  { team :: U8.U8,
+    primaryColor :: U8.U8,
+    accentColor :: U8.U8,
+    primaryFinish :: U32.U32,
+    accentFinish :: U32.U32
   }
   deriving (Eq, Show)
 
@@ -23,31 +23,35 @@
     accentColor <- Json.required object "accent_color"
     primaryFinish <- Json.required object "primary_finish"
     accentFinish <- Json.required object "accent_finish"
-    pure TeamPaint
-      { team
-      , primaryColor
-      , accentColor
-      , primaryFinish
-      , accentFinish
-      }
+    pure
+      TeamPaint
+        { team,
+          primaryColor,
+          accentColor,
+          primaryFinish,
+          accentFinish
+        }
 
 instance Json.ToJSON TeamPaint where
-  toJSON x = Json.object
-    [ Json.pair "team" $ team x
-    , Json.pair "primary_color" $ primaryColor x
-    , Json.pair "accent_color" $ accentColor x
-    , Json.pair "primary_finish" $ primaryFinish x
-    , Json.pair "accent_finish" $ accentFinish x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "team" $ team x,
+        Json.pair "primary_color" $ primaryColor x,
+        Json.pair "accent_color" $ accentColor x,
+        Json.pair "primary_finish" $ primaryFinish x,
+        Json.pair "accent_finish" $ accentFinish x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-team-paint" $ Schema.object
-  [ (Json.pair "team" $ Schema.ref U8.schema, True)
-  , (Json.pair "primary_color" $ Schema.ref U8.schema, True)
-  , (Json.pair "accent_color" $ Schema.ref U8.schema, True)
-  , (Json.pair "primary_finish" $ Schema.ref U32.schema, True)
-  , (Json.pair "accent_finish" $ Schema.ref U32.schema, True)
-  ]
+schema =
+  Schema.named "attribute-team-paint" $
+    Schema.object
+      [ (Json.pair "team" $ Schema.ref U8.schema, True),
+        (Json.pair "primary_color" $ Schema.ref U8.schema, True),
+        (Json.pair "accent_color" $ Schema.ref U8.schema, True),
+        (Json.pair "primary_finish" $ Schema.ref U32.schema, True),
+        (Json.pair "accent_finish" $ Schema.ref U32.schema, True)
+      ]
 
 bitPut :: TeamPaint -> BitPut.BitPut
 bitPut teamPaintAttribute =
@@ -64,10 +68,11 @@
   accentColor <- BitGet.label "accentColor" U8.bitGet
   primaryFinish <- BitGet.label "primaryFinish" U32.bitGet
   accentFinish <- BitGet.label "accentFinish" U32.bitGet
-  pure TeamPaint
-    { team
-    , primaryColor
-    , accentColor
-    , primaryFinish
-    , accentFinish
-    }
+  pure
+    TeamPaint
+      { team,
+        primaryColor,
+        accentColor,
+        primaryFinish,
+        accentFinish
+      }
diff --git a/src/lib/Rattletrap/Type/Attribute/Title.hs b/src/lib/Rattletrap/Type/Attribute/Title.hs
--- a/src/lib/Rattletrap/Type/Attribute/Title.hs
+++ b/src/lib/Rattletrap/Type/Attribute/Title.hs
@@ -7,14 +7,14 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data Title = Title
-  { unknown1 :: Bool
-  , unknown2 :: Bool
-  , unknown3 :: U32.U32
-  , unknown4 :: U32.U32
-  , unknown5 :: U32.U32
-  , unknown6 :: U32.U32
-  , unknown7 :: U32.U32
-  , unknown8 :: Bool
+  { unknown1 :: Bool,
+    unknown2 :: Bool,
+    unknown3 :: U32.U32,
+    unknown4 :: U32.U32,
+    unknown5 :: U32.U32,
+    unknown6 :: U32.U32,
+    unknown7 :: U32.U32,
+    unknown8 :: Bool
   }
   deriving (Eq, Show)
 
@@ -28,40 +28,44 @@
     unknown6 <- Json.required object "unknown6"
     unknown7 <- Json.required object "unknown7"
     unknown8 <- Json.required object "unknown8"
-    pure Title
-      { unknown1
-      , unknown2
-      , unknown3
-      , unknown4
-      , unknown5
-      , unknown6
-      , unknown7
-      , unknown8
-      }
+    pure
+      Title
+        { unknown1,
+          unknown2,
+          unknown3,
+          unknown4,
+          unknown5,
+          unknown6,
+          unknown7,
+          unknown8
+        }
 
 instance Json.ToJSON Title where
-  toJSON x = Json.object
-    [ Json.pair "unknown1" $ unknown1 x
-    , Json.pair "unknown2" $ unknown2 x
-    , Json.pair "unknown3" $ unknown3 x
-    , Json.pair "unknown4" $ unknown4 x
-    , Json.pair "unknown5" $ unknown5 x
-    , Json.pair "unknown6" $ unknown6 x
-    , Json.pair "unknown7" $ unknown7 x
-    , Json.pair "unknown8" $ unknown8 x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "unknown1" $ unknown1 x,
+        Json.pair "unknown2" $ unknown2 x,
+        Json.pair "unknown3" $ unknown3 x,
+        Json.pair "unknown4" $ unknown4 x,
+        Json.pair "unknown5" $ unknown5 x,
+        Json.pair "unknown6" $ unknown6 x,
+        Json.pair "unknown7" $ unknown7 x,
+        Json.pair "unknown8" $ unknown8 x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-title" $ Schema.object
-  [ (Json.pair "unknown1" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "unknown2" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "unknown3" $ Schema.ref U32.schema, True)
-  , (Json.pair "unknown4" $ Schema.ref U32.schema, True)
-  , (Json.pair "unknown5" $ Schema.ref U32.schema, True)
-  , (Json.pair "unknown6" $ Schema.ref U32.schema, True)
-  , (Json.pair "unknown7" $ Schema.ref U32.schema, True)
-  , (Json.pair "unknown8" $ Schema.ref Schema.boolean, True)
-  ]
+schema =
+  Schema.named "attribute-title" $
+    Schema.object
+      [ (Json.pair "unknown1" $ Schema.ref Schema.boolean, True),
+        (Json.pair "unknown2" $ Schema.ref Schema.boolean, True),
+        (Json.pair "unknown3" $ Schema.ref U32.schema, True),
+        (Json.pair "unknown4" $ Schema.ref U32.schema, True),
+        (Json.pair "unknown5" $ Schema.ref U32.schema, True),
+        (Json.pair "unknown6" $ Schema.ref U32.schema, True),
+        (Json.pair "unknown7" $ Schema.ref U32.schema, True),
+        (Json.pair "unknown8" $ Schema.ref Schema.boolean, True)
+      ]
 
 bitPut :: Title -> BitPut.BitPut
 bitPut titleAttribute =
@@ -84,13 +88,14 @@
   unknown6 <- BitGet.label "unknown6" U32.bitGet
   unknown7 <- BitGet.label "unknown7" U32.bitGet
   unknown8 <- BitGet.label "unknown8" BitGet.bool
-  pure Title
-    { unknown1
-    , unknown2
-    , unknown3
-    , unknown4
-    , unknown5
-    , unknown6
-    , unknown7
-    , unknown8
-    }
+  pure
+    Title
+      { unknown1,
+        unknown2,
+        unknown3,
+        unknown4,
+        unknown5,
+        unknown6,
+        unknown7,
+        unknown8
+      }
diff --git a/src/lib/Rattletrap/Type/Attribute/UniqueId.hs b/src/lib/Rattletrap/Type/Attribute/UniqueId.hs
--- a/src/lib/Rattletrap/Type/Attribute/UniqueId.hs
+++ b/src/lib/Rattletrap/Type/Attribute/UniqueId.hs
@@ -9,9 +9,9 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data UniqueId = UniqueId
-  { systemId :: U8.U8
-  , remoteId :: RemoteId.RemoteId
-  , localId :: U8.U8
+  { systemId :: U8.U8,
+    remoteId :: RemoteId.RemoteId,
+    localId :: U8.U8
   }
   deriving (Eq, Show)
 
@@ -20,21 +20,24 @@
     systemId <- Json.required object "system_id"
     remoteId <- Json.required object "remote_id"
     localId <- Json.required object "local_id"
-    pure UniqueId { systemId, remoteId, localId }
+    pure UniqueId {systemId, remoteId, localId}
 
 instance Json.ToJSON UniqueId where
-  toJSON x = Json.object
-    [ Json.pair "system_id" $ systemId x
-    , Json.pair "remote_id" $ remoteId x
-    , Json.pair "local_id" $ localId x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "system_id" $ systemId x,
+        Json.pair "remote_id" $ remoteId x,
+        Json.pair "local_id" $ localId x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-unique-id" $ Schema.object
-  [ (Json.pair "system_id" $ Schema.ref U8.schema, True)
-  , (Json.pair "remote_id" $ Schema.ref RemoteId.schema, True)
-  , (Json.pair "local_id" $ Schema.ref U8.schema, True)
-  ]
+schema =
+  Schema.named "attribute-unique-id" $
+    Schema.object
+      [ (Json.pair "system_id" $ Schema.ref U8.schema, True),
+        (Json.pair "remote_id" $ Schema.ref RemoteId.schema, True),
+        (Json.pair "local_id" $ Schema.ref U8.schema, True)
+      ]
 
 bitPut :: UniqueId -> BitPut.BitPut
 bitPut uniqueIdAttribute =
@@ -47,4 +50,4 @@
   systemId <- BitGet.label "systemId" U8.bitGet
   remoteId <- BitGet.label "remoteId" $ RemoteId.bitGet version systemId
   localId <- BitGet.label "localId" U8.bitGet
-  pure UniqueId { systemId, remoteId, localId }
+  pure UniqueId {systemId, remoteId, localId}
diff --git a/src/lib/Rattletrap/Type/Attribute/WeldedInfo.hs b/src/lib/Rattletrap/Type/Attribute/WeldedInfo.hs
--- a/src/lib/Rattletrap/Type/Attribute/WeldedInfo.hs
+++ b/src/lib/Rattletrap/Type/Attribute/WeldedInfo.hs
@@ -11,11 +11,11 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data WeldedInfo = WeldedInfo
-  { active :: Bool
-  , actorId :: I32.I32
-  , offset :: Vector.Vector
-  , mass :: F32.F32
-  , rotation :: Int8Vector.Int8Vector
+  { active :: Bool,
+    actorId :: I32.I32,
+    offset :: Vector.Vector,
+    mass :: F32.F32,
+    rotation :: Int8Vector.Int8Vector
   }
   deriving (Eq, Show)
 
@@ -26,25 +26,28 @@
     offset <- Json.required object "offset"
     mass <- Json.required object "mass"
     rotation <- Json.required object "rotation"
-    pure WeldedInfo { active, actorId, offset, mass, rotation }
+    pure WeldedInfo {active, actorId, offset, mass, rotation}
 
 instance Json.ToJSON WeldedInfo where
-  toJSON x = Json.object
-    [ Json.pair "active" $ active x
-    , Json.pair "actor_id" $ actorId x
-    , Json.pair "offset" $ offset x
-    , Json.pair "mass" $ mass x
-    , Json.pair "rotation" $ rotation x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "active" $ active x,
+        Json.pair "actor_id" $ actorId x,
+        Json.pair "offset" $ offset x,
+        Json.pair "mass" $ mass x,
+        Json.pair "rotation" $ rotation x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-welded-info" $ Schema.object
-  [ (Json.pair "active" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "actor_id" $ Schema.ref I32.schema, True)
-  , (Json.pair "offset" $ Schema.ref Vector.schema, True)
-  , (Json.pair "mass" $ Schema.ref F32.schema, True)
-  , (Json.pair "rotation" $ Schema.ref Int8Vector.schema, True)
-  ]
+schema =
+  Schema.named "attribute-welded-info" $
+    Schema.object
+      [ (Json.pair "active" $ Schema.ref Schema.boolean, True),
+        (Json.pair "actor_id" $ Schema.ref I32.schema, True),
+        (Json.pair "offset" $ Schema.ref Vector.schema, True),
+        (Json.pair "mass" $ Schema.ref F32.schema, True),
+        (Json.pair "rotation" $ Schema.ref Int8Vector.schema, True)
+      ]
 
 bitPut :: WeldedInfo -> BitPut.BitPut
 bitPut weldedInfoAttribute =
@@ -61,4 +64,4 @@
   offset <- BitGet.label "offset" $ Vector.bitGet version
   mass <- BitGet.label "mass" F32.bitGet
   rotation <- BitGet.label "rotation" Int8Vector.bitGet
-  pure WeldedInfo { active, actorId, offset, mass, rotation }
+  pure WeldedInfo {active, actorId, offset, mass, rotation}
diff --git a/src/lib/Rattletrap/Type/AttributeMapping.hs b/src/lib/Rattletrap/Type/AttributeMapping.hs
--- a/src/lib/Rattletrap/Type/AttributeMapping.hs
+++ b/src/lib/Rattletrap/Type/AttributeMapping.hs
@@ -7,8 +7,8 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data AttributeMapping = AttributeMapping
-  { objectId :: U32.U32
-  , streamId :: U32.U32
+  { objectId :: U32.U32,
+    streamId :: U32.U32
   }
   deriving (Eq, Show)
 
@@ -16,17 +16,20 @@
   parseJSON = Json.withObject "AttributeMapping" $ \object -> do
     objectId <- Json.required object "object_id"
     streamId <- Json.required object "stream_id"
-    pure AttributeMapping { objectId, streamId }
+    pure AttributeMapping {objectId, streamId}
 
 instance Json.ToJSON AttributeMapping where
-  toJSON x = Json.object
-    [Json.pair "object_id" $ objectId x, Json.pair "stream_id" $ streamId x]
+  toJSON x =
+    Json.object
+      [Json.pair "object_id" $ objectId x, Json.pair "stream_id" $ streamId x]
 
 schema :: Schema.Schema
-schema = Schema.named "attributeMapping" $ Schema.object
-  [ (Json.pair "object_id" $ Schema.ref U32.schema, True)
-  , (Json.pair "stream_id" $ Schema.ref U32.schema, True)
-  ]
+schema =
+  Schema.named "attributeMapping" $
+    Schema.object
+      [ (Json.pair "object_id" $ Schema.ref U32.schema, True),
+        (Json.pair "stream_id" $ Schema.ref U32.schema, True)
+      ]
 
 bytePut :: AttributeMapping -> BytePut.BytePut
 bytePut x = U32.bytePut (objectId x) <> U32.bytePut (streamId x)
@@ -35,4 +38,4 @@
 byteGet = ByteGet.label "AttributeMapping" $ do
   objectId <- ByteGet.label "objectId" U32.byteGet
   streamId <- ByteGet.label "streamId" U32.byteGet
-  pure AttributeMapping { objectId, streamId }
+  pure AttributeMapping {objectId, streamId}
diff --git a/src/lib/Rattletrap/Type/AttributeValue.hs b/src/lib/Rattletrap/Type/AttributeValue.hs
--- a/src/lib/Rattletrap/Type/AttributeValue.hs
+++ b/src/lib/Rattletrap/Type/AttributeValue.hs
@@ -99,49 +99,50 @@
   deriving (Eq, Show)
 
 instance Json.FromJSON AttributeValue where
-  parseJSON = Json.withObject "AttributeValue" $ \object -> Foldable.asum
-    [ fmap AppliedDamage $ Json.required object "applied_damage"
-    , fmap Boolean $ Json.required object "boolean"
-    , fmap Byte $ Json.required object "byte"
-    , fmap CamSettings $ Json.required object "cam_settings"
-    , fmap ClubColors $ Json.required object "club_colors"
-    , fmap CustomDemolish $ Json.required object "custom_demolish"
-    , fmap DamageState $ Json.required object "damage_state"
-    , fmap Demolish $ Json.required object "demolish"
-    , fmap Enum $ Json.required object "enum"
-    , fmap Explosion $ Json.required object "explosion"
-    , fmap ExtendedExplosion $ Json.required object "extended_explosion"
-    , fmap FlaggedByte $ Json.required object "flagged_byte"
-    , fmap FlaggedInt $ Json.required object "flagged_int"
-    , fmap Float $ Json.required object "float"
-    , fmap GameMode $ Json.required object "game_mode"
-    , fmap GameServer $ Json.required object "game_server"
-    , fmap Int $ Json.required object "int"
-    , fmap Int64 $ Json.required object "int64"
-    , fmap Loadout $ Json.required object "loadout"
-    , fmap LoadoutOnline $ Json.required object "loadout_online"
-    , fmap Loadouts $ Json.required object "loadouts"
-    , fmap LoadoutsOnline $ Json.required object "loadouts_online"
-    , fmap Location $ Json.required object "location"
-    , fmap MusicStinger $ Json.required object "music_stinger"
-    , fmap PartyLeader $ Json.required object "party_leader"
-    , fmap Pickup $ Json.required object "pickup"
-    , fmap PickupInfo $ Json.required object "pickup_info"
-    , fmap PickupNew $ Json.required object "pickup_new"
-    , fmap PlayerHistoryKey $ Json.required object "player_history_key"
-    , fmap PrivateMatchSettings $ Json.required object "private_match_settings"
-    , fmap QWord $ Json.required object "q_word"
-    , fmap RepStatTitle $ Json.required object "rep_stat_title"
-    , fmap Reservation $ Json.required object "reservation"
-    , fmap RigidBodyState $ Json.required object "rigid_body_state"
-    , fmap Rotation $ Json.required object "rotation"
-    , fmap StatEvent $ Json.required object "stat_event"
-    , fmap String $ Json.required object "string"
-    , fmap TeamPaint $ Json.required object "team_paint"
-    , fmap Title $ Json.required object "title"
-    , fmap UniqueId $ Json.required object "unique_id"
-    , fmap WeldedInfo $ Json.required object "welded_info"
-    ]
+  parseJSON = Json.withObject "AttributeValue" $ \object ->
+    Foldable.asum
+      [ fmap AppliedDamage $ Json.required object "applied_damage",
+        fmap Boolean $ Json.required object "boolean",
+        fmap Byte $ Json.required object "byte",
+        fmap CamSettings $ Json.required object "cam_settings",
+        fmap ClubColors $ Json.required object "club_colors",
+        fmap CustomDemolish $ Json.required object "custom_demolish",
+        fmap DamageState $ Json.required object "damage_state",
+        fmap Demolish $ Json.required object "demolish",
+        fmap Enum $ Json.required object "enum",
+        fmap Explosion $ Json.required object "explosion",
+        fmap ExtendedExplosion $ Json.required object "extended_explosion",
+        fmap FlaggedByte $ Json.required object "flagged_byte",
+        fmap FlaggedInt $ Json.required object "flagged_int",
+        fmap Float $ Json.required object "float",
+        fmap GameMode $ Json.required object "game_mode",
+        fmap GameServer $ Json.required object "game_server",
+        fmap Int $ Json.required object "int",
+        fmap Int64 $ Json.required object "int64",
+        fmap Loadout $ Json.required object "loadout",
+        fmap LoadoutOnline $ Json.required object "loadout_online",
+        fmap Loadouts $ Json.required object "loadouts",
+        fmap LoadoutsOnline $ Json.required object "loadouts_online",
+        fmap Location $ Json.required object "location",
+        fmap MusicStinger $ Json.required object "music_stinger",
+        fmap PartyLeader $ Json.required object "party_leader",
+        fmap Pickup $ Json.required object "pickup",
+        fmap PickupInfo $ Json.required object "pickup_info",
+        fmap PickupNew $ Json.required object "pickup_new",
+        fmap PlayerHistoryKey $ Json.required object "player_history_key",
+        fmap PrivateMatchSettings $ Json.required object "private_match_settings",
+        fmap QWord $ Json.required object "q_word",
+        fmap RepStatTitle $ Json.required object "rep_stat_title",
+        fmap Reservation $ Json.required object "reservation",
+        fmap RigidBodyState $ Json.required object "rigid_body_state",
+        fmap Rotation $ Json.required object "rotation",
+        fmap StatEvent $ Json.required object "stat_event",
+        fmap String $ Json.required object "string",
+        fmap TeamPaint $ Json.required object "team_paint",
+        fmap Title $ Json.required object "title",
+        fmap UniqueId $ Json.required object "unique_id",
+        fmap WeldedInfo $ Json.required object "welded_info"
+      ]
 
 instance Json.ToJSON AttributeValue where
   toJSON x = case x of
@@ -189,50 +190,52 @@
     WeldedInfo y -> Json.object [Json.pair "welded_info" y]
 
 schema :: Schema.Schema
-schema = Schema.named "attribute-value" . Schema.oneOf $ fmap
-  (\(k, v) -> Schema.object [(Json.pair k $ Schema.ref v, True)])
-  [ ("applied_damage", AppliedDamage.schema)
-  , ("boolean", Boolean.schema)
-  , ("byte", Byte.schema)
-  , ("cam_settings", CamSettings.schema)
-  , ("club_colors", ClubColors.schema)
-  , ("custom_demolish", CustomDemolish.schema)
-  , ("damage_state", DamageState.schema)
-  , ("demolish", Demolish.schema)
-  , ("enum", Enum.schema)
-  , ("explosion", Explosion.schema)
-  , ("extended_explosion", ExtendedExplosion.schema)
-  , ("flagged_byte", FlaggedByte.schema)
-  , ("flagged_int", FlaggedInt.schema)
-  , ("float", Float.schema)
-  , ("game_mode", GameMode.schema)
-  , ("game_server", GameServer.schema)
-  , ("int", Int.schema)
-  , ("int64", Int64.schema)
-  , ("loadout_online", LoadoutOnline.schema)
-  , ("loadout", Loadout.schema)
-  , ("loadouts_online", LoadoutsOnline.schema)
-  , ("loadouts", Loadouts.schema)
-  , ("location", Location.schema)
-  , ("music_stinger", MusicStinger.schema)
-  , ("party_leader", PartyLeader.schema)
-  , ("pickup_info", PickupInfo.schema)
-  , ("pickup_new", PickupNew.schema)
-  , ("pickup", Pickup.schema)
-  , ("player_history_key", PlayerHistoryKey.schema)
-  , ("private_match_settings", PrivateMatchSettings.schema)
-  , ("q_word", QWord.schema)
-  , ("rep_stat_title", RepStatTitle.schema)
-  , ("reservation", Reservation.schema)
-  , ("rigid_body_state", RigidBodyState.schema)
-  , ("rotation", Rotation.schema)
-  , ("stat_event", StatEvent.schema)
-  , ("string", String.schema)
-  , ("team_paint", TeamPaint.schema)
-  , ("title", Title.schema)
-  , ("unique_id", UniqueId.schema)
-  , ("welded_info", WeldedInfo.schema)
-  ]
+schema =
+  Schema.named "attribute-value" . Schema.oneOf $
+    fmap
+      (\(k, v) -> Schema.object [(Json.pair k $ Schema.ref v, True)])
+      [ ("applied_damage", AppliedDamage.schema),
+        ("boolean", Boolean.schema),
+        ("byte", Byte.schema),
+        ("cam_settings", CamSettings.schema),
+        ("club_colors", ClubColors.schema),
+        ("custom_demolish", CustomDemolish.schema),
+        ("damage_state", DamageState.schema),
+        ("demolish", Demolish.schema),
+        ("enum", Enum.schema),
+        ("explosion", Explosion.schema),
+        ("extended_explosion", ExtendedExplosion.schema),
+        ("flagged_byte", FlaggedByte.schema),
+        ("flagged_int", FlaggedInt.schema),
+        ("float", Float.schema),
+        ("game_mode", GameMode.schema),
+        ("game_server", GameServer.schema),
+        ("int", Int.schema),
+        ("int64", Int64.schema),
+        ("loadout_online", LoadoutOnline.schema),
+        ("loadout", Loadout.schema),
+        ("loadouts_online", LoadoutsOnline.schema),
+        ("loadouts", Loadouts.schema),
+        ("location", Location.schema),
+        ("music_stinger", MusicStinger.schema),
+        ("party_leader", PartyLeader.schema),
+        ("pickup_info", PickupInfo.schema),
+        ("pickup_new", PickupNew.schema),
+        ("pickup", Pickup.schema),
+        ("player_history_key", PlayerHistoryKey.schema),
+        ("private_match_settings", PrivateMatchSettings.schema),
+        ("q_word", QWord.schema),
+        ("rep_stat_title", RepStatTitle.schema),
+        ("reservation", Reservation.schema),
+        ("rigid_body_state", RigidBodyState.schema),
+        ("rotation", Rotation.schema),
+        ("stat_event", StatEvent.schema),
+        ("string", String.schema),
+        ("team_paint", TeamPaint.schema),
+        ("title", Title.schema),
+        ("unique_id", UniqueId.schema),
+        ("welded_info", WeldedInfo.schema)
+      ]
 
 bitPut :: AttributeValue -> BitPut.BitPut
 bitPut value = case value of
@@ -278,12 +281,12 @@
   UniqueId x -> UniqueId.bitPut x
   WeldedInfo x -> WeldedInfo.bitPut x
 
-bitGet
-  :: Version.Version
-  -> Maybe Str.Str
-  -> Map.Map U32.U32 Str.Str
-  -> Str.Str
-  -> BitGet.BitGet AttributeValue
+bitGet ::
+  Version.Version ->
+  Maybe Str.Str ->
+  Map.Map U32.U32 Str.Str ->
+  Str.Str ->
+  BitGet.BitGet AttributeValue
 bitGet version buildVersion objectMap name =
   BitGet.label "AttributeValue" $ do
     constructor <- case Map.lookup (Str.toText name) Data.attributeTypes of
diff --git a/src/lib/Rattletrap/Type/Cache.hs b/src/lib/Rattletrap/Type/Cache.hs
--- a/src/lib/Rattletrap/Type/Cache.hs
+++ b/src/lib/Rattletrap/Type/Cache.hs
@@ -9,10 +9,10 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data Cache = Cache
-  { classId :: U32.U32
-  , parentCacheId :: U32.U32
-  , cacheId :: U32.U32
-  , attributeMappings :: List.List AttributeMapping.AttributeMapping
+  { classId :: U32.U32,
+    parentCacheId :: U32.U32,
+    cacheId :: U32.U32,
+    attributeMappings :: List.List AttributeMapping.AttributeMapping
   }
   deriving (Eq, Show)
 
@@ -22,26 +22,30 @@
     parentCacheId <- Json.required object "parent_cache_id"
     cacheId <- Json.required object "cache_id"
     attributeMappings <- Json.required object "attribute_mappings"
-    pure Cache { classId, parentCacheId, cacheId, attributeMappings }
+    pure Cache {classId, parentCacheId, cacheId, attributeMappings}
 
 instance Json.ToJSON Cache where
-  toJSON x = Json.object
-    [ Json.pair "class_id" $ classId x
-    , Json.pair "parent_cache_id" $ parentCacheId x
-    , Json.pair "cache_id" $ cacheId x
-    , Json.pair "attribute_mappings" $ attributeMappings x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "class_id" $ classId x,
+        Json.pair "parent_cache_id" $ parentCacheId x,
+        Json.pair "cache_id" $ cacheId x,
+        Json.pair "attribute_mappings" $ attributeMappings x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "cache" $ Schema.object
-  [ (Json.pair "class_id" $ Schema.ref U32.schema, True)
-  , (Json.pair "parent_cache_id" $ Schema.ref U32.schema, True)
-  , (Json.pair "cache_id" $ Schema.ref U32.schema, True)
-  , ( Json.pair "attribute_mappings" . Schema.json $ List.schema
-      AttributeMapping.schema
-    , True
-    )
-  ]
+schema =
+  Schema.named "cache" $
+    Schema.object
+      [ (Json.pair "class_id" $ Schema.ref U32.schema, True),
+        (Json.pair "parent_cache_id" $ Schema.ref U32.schema, True),
+        (Json.pair "cache_id" $ Schema.ref U32.schema, True),
+        ( Json.pair "attribute_mappings" . Schema.json $
+            List.schema
+              AttributeMapping.schema,
+          True
+        )
+      ]
 
 bytePut :: Cache -> BytePut.BytePut
 bytePut x =
@@ -55,6 +59,7 @@
   classId <- ByteGet.label "classId" U32.byteGet
   parentCacheId <- ByteGet.label "parentCacheId" U32.byteGet
   cacheId <- ByteGet.label "cacheId" U32.byteGet
-  attributeMappings <- ByteGet.label "attributeMappings"
-    $ List.byteGet AttributeMapping.byteGet
-  pure Cache { classId, parentCacheId, cacheId, attributeMappings }
+  attributeMappings <-
+    ByteGet.label "attributeMappings" $
+      List.byteGet AttributeMapping.byteGet
+  pure Cache {classId, parentCacheId, cacheId, attributeMappings}
diff --git a/src/lib/Rattletrap/Type/ClassAttributeMap.hs b/src/lib/Rattletrap/Type/ClassAttributeMap.hs
--- a/src/lib/Rattletrap/Type/ClassAttributeMap.hs
+++ b/src/lib/Rattletrap/Type/ClassAttributeMap.hs
@@ -22,14 +22,14 @@
 -- to each class are not fixed either. Converting the raw data into a usable
 -- structure is tedious; see 'make'.
 data ClassAttributeMap = ClassAttributeMap
-  { objectMap :: Map.Map U32.U32 Str.Str
-  -- ^ A map from object IDs to their names.
-  , objectClassMap :: Map.Map U32.U32 U32.U32
-  -- ^ A map from object IDs to their class IDs.
-  , value :: Map.Map U32.U32 (Map.Map U32.U32 U32.U32)
-  -- ^ A map from class IDs to a map from attribute stream IDs to attribute
-  -- IDs.
-  , nameMap :: IntMap.IntMap Str.Str
+  { -- | A map from object IDs to their names.
+    objectMap :: Map.Map U32.U32 Str.Str,
+    -- | A map from object IDs to their class IDs.
+    objectClassMap :: Map.Map U32.U32 U32.U32,
+    -- | A map from class IDs to a map from attribute stream IDs to attribute
+    -- IDs.
+    value :: Map.Map U32.U32 (Map.Map U32.U32 U32.U32),
+    nameMap :: IntMap.IntMap Str.Str
   }
   deriving (Eq, Show)
 
@@ -38,54 +38,55 @@
 bimap :: (Ord l, Ord r) => [(l, r)] -> Bimap l r
 bimap xs = (Map.fromList xs, Map.fromList (fmap Tuple.swap xs))
 
-lookupL :: Ord l => l -> Bimap l r -> Maybe r
+lookupL :: (Ord l) => l -> Bimap l r -> Maybe r
 lookupL k = Map.lookup k . fst
 
-lookupR :: Ord r => r -> Bimap l r -> Maybe l
+lookupR :: (Ord r) => r -> Bimap l r -> Maybe l
 lookupR k = Map.lookup k . snd
 
 -- | Makes a 'ClassAttributeMap' given the necessary fields from the
 -- 'Rattletrap.Content.Content'.
-make
-  :: List.List Str.Str
-  -- ^ From 'Rattletrap.Content.objects'.
-  -> List.List ClassMapping.ClassMapping
-  -- ^ From 'Rattletrap.Content.classMappings'.
-  -> List.List Cache.Cache
-  -- ^ From 'Rattletrap.Content.caches'.
-  -> List.List Str.Str
-  -- ^ From 'Rattletrap.Content.names'.
-  -> ClassAttributeMap
+make ::
+  -- | From 'Rattletrap.Content.objects'.
+  List.List Str.Str ->
+  -- | From 'Rattletrap.Content.classMappings'.
+  List.List ClassMapping.ClassMapping ->
+  -- | From 'Rattletrap.Content.caches'.
+  List.List Cache.Cache ->
+  -- | From 'Rattletrap.Content.names'.
+  List.List Str.Str ->
+  ClassAttributeMap
 make objects classMappings caches names =
-  let
-    objectMap_ = makeObjectMap objects
-    classMap = makeClassMap classMappings
-    objectClassMap_ = makeObjectClassMap objectMap_ classMap
-    classCache = makeClassCache classMap caches
-    attributeMap = makeAttributeMap caches
-    classIds = fmap (\(_, classId, _, _) -> classId) classCache
-    parentMap = makeParentMap classCache
-    value_ = Map.fromList
-      (fmap
-        (\classId ->
-          let
-            ownAttributes =
-              Maybe.fromMaybe Map.empty (Map.lookup classId attributeMap)
-            parentsAttributes = case Map.lookup classId parentMap of
-              Nothing -> []
-              Just parentClassIds -> fmap
-                (\parentClassId -> Maybe.fromMaybe
-                  Map.empty
-                  (Map.lookup parentClassId attributeMap)
-                )
-                parentClassIds
-            attributes = ownAttributes : parentsAttributes
-          in (classId, Map.fromList (concatMap Map.toList attributes))
-        )
-        classIds
-      )
-    nameMap_ = makeNameMap names
-  in ClassAttributeMap objectMap_ objectClassMap_ value_ nameMap_
+  let objectMap_ = makeObjectMap objects
+      classMap = makeClassMap classMappings
+      objectClassMap_ = makeObjectClassMap objectMap_ classMap
+      classCache = makeClassCache classMap caches
+      attributeMap = makeAttributeMap caches
+      classIds = fmap (\(_, classId, _, _) -> classId) classCache
+      parentMap = makeParentMap classCache
+      value_ =
+        Map.fromList
+          ( fmap
+              ( \classId ->
+                  let ownAttributes =
+                        Maybe.fromMaybe Map.empty (Map.lookup classId attributeMap)
+                      parentsAttributes = case Map.lookup classId parentMap of
+                        Nothing -> []
+                        Just parentClassIds ->
+                          fmap
+                            ( \parentClassId ->
+                                Maybe.fromMaybe
+                                  Map.empty
+                                  (Map.lookup parentClassId attributeMap)
+                            )
+                            parentClassIds
+                      attributes = ownAttributes : parentsAttributes
+                   in (classId, Map.fromList (concatMap Map.toList attributes))
+              )
+              classIds
+          )
+      nameMap_ = makeNameMap names
+   in ClassAttributeMap objectMap_ objectClassMap_ value_ nameMap_
 
 makeNameMap :: List.List Str.Str -> IntMap.IntMap Str.Str
 makeNameMap names =
@@ -95,99 +96,101 @@
 getName nameMap_ nameIndex =
   IntMap.lookup (fromIntegral (U32.toWord32 nameIndex)) nameMap_
 
-makeObjectClassMap
-  :: Map.Map U32.U32 Str.Str
-  -> Bimap U32.U32 Str.Str
-  -> Map.Map U32.U32 U32.U32
+makeObjectClassMap ::
+  Map.Map U32.U32 Str.Str ->
+  Bimap U32.U32 Str.Str ->
+  Map.Map U32.U32 U32.U32
 makeObjectClassMap objectMap_ classMap = do
   let objectIds = Map.keys objectMap_
   let classIds = fmap (getClassId objectMap_ classMap) objectIds
   let rawPairs = zip objectIds classIds
-  let
-    pairs = Maybe.mapMaybe
-      (\(objectId, maybeClassId) -> case maybeClassId of
-        Nothing -> Nothing
-        Just classId -> Just (objectId, classId)
-      )
-      rawPairs
+  let pairs =
+        Maybe.mapMaybe
+          ( \(objectId, maybeClassId) -> case maybeClassId of
+              Nothing -> Nothing
+              Just classId -> Just (objectId, classId)
+          )
+          rawPairs
   Map.fromList pairs
 
-getClassId
-  :: Map.Map U32.U32 Str.Str
-  -> Bimap U32.U32 Str.Str
-  -> U32.U32
-  -> Maybe U32.U32
+getClassId ::
+  Map.Map U32.U32 Str.Str ->
+  Bimap U32.U32 Str.Str ->
+  U32.U32 ->
+  Maybe U32.U32
 getClassId objectMap_ classMap objectId = do
   objectName <- getObjectName objectMap_ objectId
   className <- getClassName objectName
   lookupR className classMap
 
-makeClassCache
-  :: Bimap U32.U32 Str.Str
-  -> List.List Cache.Cache
-  -> [(Maybe Str.Str, U32.U32, U32.U32, U32.U32)]
-makeClassCache classMap caches = fmap
-  (\cache ->
-    let classId = Cache.classId cache
-    in
-      ( lookupL classId classMap
-      , classId
-      , Cache.cacheId cache
-      , Cache.parentCacheId cache
-      )
-  )
-  (List.toList caches)
+makeClassCache ::
+  Bimap U32.U32 Str.Str ->
+  List.List Cache.Cache ->
+  [(Maybe Str.Str, U32.U32, U32.U32, U32.U32)]
+makeClassCache classMap caches =
+  fmap
+    ( \cache ->
+        let classId = Cache.classId cache
+         in ( lookupL classId classMap,
+              classId,
+              Cache.cacheId cache,
+              Cache.parentCacheId cache
+            )
+    )
+    (List.toList caches)
 
 makeClassMap :: List.List ClassMapping.ClassMapping -> Bimap U32.U32 Str.Str
-makeClassMap classMappings = bimap
-  (fmap
-    (\classMapping ->
-      (ClassMapping.streamId classMapping, ClassMapping.name classMapping)
+makeClassMap classMappings =
+  bimap
+    ( fmap
+        ( \classMapping ->
+            (ClassMapping.streamId classMapping, ClassMapping.name classMapping)
+        )
+        (List.toList classMappings)
     )
-    (List.toList classMappings)
-  )
 
-makeAttributeMap
-  :: List.List Cache.Cache -> Map.Map U32.U32 (Map.Map U32.U32 U32.U32)
-makeAttributeMap caches = Map.fromList
-  (fmap
-    (\cache ->
-      ( Cache.classId cache
-      , Map.fromList
-        (fmap
-          (\attributeMapping ->
-            ( AttributeMapping.streamId attributeMapping
-            , AttributeMapping.objectId attributeMapping
+makeAttributeMap ::
+  List.List Cache.Cache -> Map.Map U32.U32 (Map.Map U32.U32 U32.U32)
+makeAttributeMap caches =
+  Map.fromList
+    ( fmap
+        ( \cache ->
+            ( Cache.classId cache,
+              Map.fromList
+                ( fmap
+                    ( \attributeMapping ->
+                        ( AttributeMapping.streamId attributeMapping,
+                          AttributeMapping.objectId attributeMapping
+                        )
+                    )
+                    (List.toList (Cache.attributeMappings cache))
+                )
             )
-          )
-          (List.toList (Cache.attributeMappings cache))
         )
-      )
+        (List.toList caches)
     )
-    (List.toList caches)
-  )
 
-makeShallowParentMap
-  :: [(Maybe Str.Str, U32.U32, U32.U32, U32.U32)] -> Map.Map U32.U32 U32.U32
-makeShallowParentMap classCache = Map.fromList
-  (Maybe.mapMaybe
-    (\xs -> case xs of
-      [] -> Nothing
-      (maybeClassName, classId, _, parentCacheId) : rest -> do
-        parentClassId <- getParentClass maybeClassName parentCacheId rest
-        pure (classId, parentClassId)
+makeShallowParentMap ::
+  [(Maybe Str.Str, U32.U32, U32.U32, U32.U32)] -> Map.Map U32.U32 U32.U32
+makeShallowParentMap classCache =
+  Map.fromList
+    ( Maybe.mapMaybe
+        ( \xs -> case xs of
+            [] -> Nothing
+            (maybeClassName, classId, _, parentCacheId) : rest -> do
+              parentClassId <- getParentClass maybeClassName parentCacheId rest
+              pure (classId, parentClassId)
+        )
+        (List.tails (reverse classCache))
     )
-    (List.tails (reverse classCache))
-  )
 
-makeParentMap
-  :: [(Maybe Str.Str, U32.U32, U32.U32, U32.U32)] -> Map.Map U32.U32 [U32.U32]
+makeParentMap ::
+  [(Maybe Str.Str, U32.U32, U32.U32, U32.U32)] -> Map.Map U32.U32 [U32.U32]
 makeParentMap classCache =
   let shallowParentMap = makeShallowParentMap classCache
-  in
-    Map.mapWithKey
-      (\classId _ -> getParentClasses shallowParentMap classId)
-      shallowParentMap
+   in Map.mapWithKey
+        (\classId _ -> getParentClasses shallowParentMap classId)
+        shallowParentMap
 
 getParentClasses :: Map.Map U32.U32 U32.U32 -> U32.U32 -> [U32.U32]
 getParentClasses shallowParentMap classId =
@@ -196,51 +199,54 @@
     Just parentClassId ->
       parentClassId : getParentClasses shallowParentMap parentClassId
 
-getParentClass
-  :: Maybe Str.Str
-  -> U32.U32
-  -> [(Maybe Str.Str, U32.U32, U32.U32, U32.U32)]
-  -> Maybe U32.U32
+getParentClass ::
+  Maybe Str.Str ->
+  U32.U32 ->
+  [(Maybe Str.Str, U32.U32, U32.U32, U32.U32)] ->
+  Maybe U32.U32
 getParentClass maybeClassName parentCacheId xs = case maybeClassName of
   Nothing -> getParentClassById parentCacheId xs
   Just className -> getParentClassByName className parentCacheId xs
 
-getParentClassById
-  :: U32.U32 -> [(Maybe Str.Str, U32.U32, U32.U32, U32.U32)] -> Maybe U32.U32
+getParentClassById ::
+  U32.U32 -> [(Maybe Str.Str, U32.U32, U32.U32, U32.U32)] -> Maybe U32.U32
 getParentClassById parentCacheId xs =
   case dropWhile (\(_, _, cacheId, _) -> cacheId /= parentCacheId) xs of
-    [] -> if parentCacheId == U32.fromWord32 0
-      then Nothing
-      else getParentClassById
-        (U32.fromWord32 (U32.toWord32 parentCacheId - 1))
-        xs
+    [] ->
+      if parentCacheId == U32.fromWord32 0
+        then Nothing
+        else
+          getParentClassById
+            (U32.fromWord32 (U32.toWord32 parentCacheId - 1))
+            xs
     (_, parentClassId, _, _) : _ -> Just parentClassId
 
-getParentClassByName
-  :: Str.Str
-  -> U32.U32
-  -> [(Maybe Str.Str, U32.U32, U32.U32, U32.U32)]
-  -> Maybe U32.U32
+getParentClassByName ::
+  Str.Str ->
+  U32.U32 ->
+  [(Maybe Str.Str, U32.U32, U32.U32, U32.U32)] ->
+  Maybe U32.U32
 getParentClassByName className parentCacheId xs =
   case Map.lookup (Str.toText className) Data.parentClasses of
     Nothing -> getParentClassById parentCacheId xs
-    Just parentClassName -> Maybe.maybe
-      (getParentClassById parentCacheId xs)
-      Just
-      (Maybe.listToMaybe
-        (fmap
-          (\(_, parentClassId, _, _) -> parentClassId)
-          (filter
-            (\(_, _, cacheId, _) -> cacheId <= parentCacheId)
-            (filter
-              (\(maybeClassName, _, _, _) ->
-                fmap Str.toText maybeClassName == Just parentClassName
-              )
-              xs
+    Just parentClassName ->
+      Maybe.maybe
+        (getParentClassById parentCacheId xs)
+        Just
+        ( Maybe.listToMaybe
+            ( fmap
+                (\(_, parentClassId, _, _) -> parentClassId)
+                ( filter
+                    (\(_, _, cacheId, _) -> cacheId <= parentCacheId)
+                    ( filter
+                        ( \(maybeClassName, _, _, _) ->
+                            fmap Str.toText maybeClassName == Just parentClassName
+                        )
+                        xs
+                    )
+                )
             )
-          )
         )
-      )
 
 makeObjectMap :: List.List Str.Str -> Map.Map U32.U32 Str.Str
 makeObjectMap objects =
@@ -250,30 +256,35 @@
 getObjectName objectMap_ objectId = Map.lookup objectId objectMap_
 
 getClassName :: Str.Str -> Maybe Str.Str
-getClassName rawObjectName = fmap Str.fromText $ Map.lookup
-  (Str.toText $ normalizeObjectName rawObjectName)
-  Data.objectClasses
+getClassName rawObjectName =
+  fmap Str.fromText $
+    Map.lookup
+      (Str.toText $ normalizeObjectName rawObjectName)
+      Data.objectClasses
 
 normalizeObjectName :: Str.Str -> Str.Str
 normalizeObjectName objectName =
-  let
-    name = Str.toText objectName
-    crowdActor = Text.pack "TheWorld:PersistentLevel.CrowdActor_TA"
-    crowdManager = Text.pack "TheWorld:PersistentLevel.CrowdManager_TA"
-    boostPickup = Text.pack "TheWorld:PersistentLevel.VehiclePickup_Boost_TA"
-    mapScoreboard = Text.pack "TheWorld:PersistentLevel.InMapScoreboard_TA"
-    breakout = Text.pack "TheWorld:PersistentLevel.BreakOutActor_Platform_TA"
-  in if Text.isInfixOf crowdActor name
-    then Str.fromText crowdActor
-    else if Text.isInfixOf crowdManager name
-      then Str.fromText crowdManager
-      else if Text.isInfixOf boostPickup name
-        then Str.fromText boostPickup
-        else if Text.isInfixOf mapScoreboard name
-          then Str.fromText mapScoreboard
-          else if Text.isInfixOf breakout name
-            then Str.fromText breakout
-            else objectName
+  let name = Str.toText objectName
+      crowdActor = Text.pack "TheWorld:PersistentLevel.CrowdActor_TA"
+      crowdManager = Text.pack "TheWorld:PersistentLevel.CrowdManager_TA"
+      boostPickup = Text.pack "TheWorld:PersistentLevel.VehiclePickup_Boost_TA"
+      mapScoreboard = Text.pack "TheWorld:PersistentLevel.InMapScoreboard_TA"
+      breakout = Text.pack "TheWorld:PersistentLevel.BreakOutActor_Platform_TA"
+   in if Text.isInfixOf crowdActor name
+        then Str.fromText crowdActor
+        else
+          if Text.isInfixOf crowdManager name
+            then Str.fromText crowdManager
+            else
+              if Text.isInfixOf boostPickup name
+                then Str.fromText boostPickup
+                else
+                  if Text.isInfixOf mapScoreboard name
+                    then Str.fromText mapScoreboard
+                    else
+                      if Text.isInfixOf breakout name
+                        then Str.fromText breakout
+                        else objectName
 
 classHasLocation :: Str.Str -> Bool
 classHasLocation className =
@@ -288,22 +299,22 @@
   ((streamId, _), _) <- Map.maxViewWithKey attributeMap
   pure (fromIntegral (U32.toWord32 streamId))
 
-getAttributeName
-  :: ClassAttributeMap
-  -> Map.Map U32.U32 U32.U32
-  -> CompressedWord.CompressedWord
-  -> Maybe Str.Str
+getAttributeName ::
+  ClassAttributeMap ->
+  Map.Map U32.U32 U32.U32 ->
+  CompressedWord.CompressedWord ->
+  Maybe Str.Str
 getAttributeName classAttributeMap attributeMap streamId = do
   let key = U32.fromWord32 (fromIntegral (CompressedWord.value streamId))
   attributeId <- Map.lookup key attributeMap
   let objectMap_ = objectMap classAttributeMap
   Map.lookup attributeId objectMap_
 
-getAttributeMap
-  :: ClassAttributeMap
-  -> Map.Map CompressedWord.CompressedWord U32.U32
-  -> CompressedWord.CompressedWord
-  -> Maybe (Map.Map U32.U32 U32.U32)
+getAttributeMap ::
+  ClassAttributeMap ->
+  Map.Map CompressedWord.CompressedWord U32.U32 ->
+  CompressedWord.CompressedWord ->
+  Maybe (Map.Map U32.U32 U32.U32)
 getAttributeMap classAttributeMap actorMap actorId = do
   objectId <- Map.lookup actorId actorMap
   let objectClassMap_ = objectClassMap classAttributeMap
diff --git a/src/lib/Rattletrap/Type/ClassMapping.hs b/src/lib/Rattletrap/Type/ClassMapping.hs
--- a/src/lib/Rattletrap/Type/ClassMapping.hs
+++ b/src/lib/Rattletrap/Type/ClassMapping.hs
@@ -8,8 +8,8 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data ClassMapping = ClassMapping
-  { name :: Str.Str
-  , streamId :: U32.U32
+  { name :: Str.Str,
+    streamId :: U32.U32
   }
   deriving (Eq, Show)
 
@@ -17,17 +17,19 @@
   parseJSON = Json.withObject "ClassMapping" $ \object -> do
     name <- Json.required object "name"
     streamId <- Json.required object "stream_id"
-    pure ClassMapping { name, streamId }
+    pure ClassMapping {name, streamId}
 
 instance Json.ToJSON ClassMapping where
   toJSON x =
     Json.object [Json.pair "name" $ name x, Json.pair "stream_id" $ streamId x]
 
 schema :: Schema.Schema
-schema = Schema.named "classMapping" $ Schema.object
-  [ (Json.pair "name" $ Schema.ref Str.schema, True)
-  , (Json.pair "stream_id" $ Schema.ref U32.schema, True)
-  ]
+schema =
+  Schema.named "classMapping" $
+    Schema.object
+      [ (Json.pair "name" $ Schema.ref Str.schema, True),
+        (Json.pair "stream_id" $ Schema.ref U32.schema, True)
+      ]
 
 bytePut :: ClassMapping -> BytePut.BytePut
 bytePut x = Str.bytePut (name x) <> U32.bytePut (streamId x)
@@ -36,4 +38,4 @@
 byteGet = ByteGet.label "ClassMapping" $ do
   name <- ByteGet.label "name" Str.byteGet
   streamId <- ByteGet.label "streamId" U32.byteGet
-  pure ClassMapping { name, streamId }
+  pure ClassMapping {name, streamId}
diff --git a/src/lib/Rattletrap/Type/CompressedWord.hs b/src/lib/Rattletrap/Type/CompressedWord.hs
--- a/src/lib/Rattletrap/Type/CompressedWord.hs
+++ b/src/lib/Rattletrap/Type/CompressedWord.hs
@@ -9,8 +9,8 @@
 -- | Although there's no guarantee that these values will not overflow, it's
 -- exceptionally unlikely. Most 'CompressedWord's are very small.
 data CompressedWord = CompressedWord
-  { limit :: Word
-  , value :: Word
+  { limit :: Word,
+    value :: Word
   }
   deriving (Eq, Ord, Show)
 
@@ -18,25 +18,26 @@
   parseJSON = Json.withObject "CompressedWord" $ \object -> do
     limit <- Json.required object "limit"
     value <- Json.required object "value"
-    pure CompressedWord { limit, value }
+    pure CompressedWord {limit, value}
 
 instance Json.ToJSON CompressedWord where
   toJSON x =
     Json.object [Json.pair "limit" $ limit x, Json.pair "value" $ value x]
 
 schema :: Schema.Schema
-schema = Schema.named "compressedWord" $ Schema.object
-  [ (Json.pair "limit" $ Json.object [Json.pair "type" "integer"], True)
-  , (Json.pair "value" $ Json.object [Json.pair "type" "integer"], True)
-  ]
+schema =
+  Schema.named "compressedWord" $
+    Schema.object
+      [ (Json.pair "limit" $ Json.object [Json.pair "type" "integer"], True),
+        (Json.pair "value" $ Json.object [Json.pair "type" "integer"], True)
+      ]
 
 bitPut :: CompressedWord -> BitPut.BitPut
 bitPut compressedWord =
-  let
-    limit_ = limit compressedWord
-    value_ = value compressedWord
-    maxBits = getMaxBits limit_
-  in putCompressedWordStep limit_ value_ maxBits 0 0
+  let limit_ = limit compressedWord
+      value_ = value compressedWord
+      maxBits = getMaxBits limit_
+   in putCompressedWordStep limit_ value_ maxBits 0 0
 
 putCompressedWordStep :: Word -> Word -> Int -> Int -> Word -> BitPut.BitPut
 putCompressedWordStep limit_ value_ maxBits position soFar =
@@ -46,44 +47,43 @@
       if maxBits > 1 && position == maxBits - 1 && soFar + x > limit_
         then mempty
         else
-          let
-            bit = Bits.testBit value_ position
-            delta = if bit then x else 0
-          in BitPut.bool bit <> putCompressedWordStep
-            limit_
-            value_
-            maxBits
-            (position + 1)
-            (soFar + delta)
+          let bit = Bits.testBit value_ position
+              delta = if bit then x else 0
+           in BitPut.bool bit
+                <> putCompressedWordStep
+                  limit_
+                  value_
+                  maxBits
+                  (position + 1)
+                  (soFar + delta)
     else mempty
 
 getMaxBits :: Word -> Int
 getMaxBits x =
-  let
-    n :: Int
-    n = max 1 (ceiling (logBase (2 :: Double) (fromIntegral (max 1 x))))
-  in if x < 1024 && x == 2 ^ n then n + 1 else n
+  let n :: Int
+      n = max 1 (ceiling (logBase (2 :: Double) (fromIntegral (max 1 x))))
+   in if x < 1024 && x == 2 ^ n then n + 1 else n
 
 bitGet :: Word -> BitGet.BitGet CompressedWord
 bitGet = bitGetNew
 
 bitGetNew :: Word -> BitGet.BitGet CompressedWord
 bitGetNew limit = do
-  value <- if limit < 1
-    then pure 0
-    else do
-      let
-        numBits =
-          max (0 :: Int)
-            . subtract 1
-            . ceiling
-            . logBase (2 :: Double)
-            $ fromIntegral limit
-      partial <- BitGet.bits numBits
-      let next = partial + Bits.shiftL 1 numBits
-      if next > limit
-        then pure partial
-        else do
-          x <- BitGet.bool
-          pure $ if x then next else partial
-  pure CompressedWord { limit, value }
+  value <-
+    if limit < 1
+      then pure 0
+      else do
+        let numBits =
+              max (0 :: Int)
+                . subtract 1
+                . ceiling
+                . logBase (2 :: Double)
+                $ fromIntegral limit
+        partial <- BitGet.bits numBits
+        let next = partial + Bits.shiftL 1 numBits
+        if next > limit
+          then pure partial
+          else do
+            x <- BitGet.bool
+            pure $ if x then next else partial
+  pure CompressedWord {limit, value}
diff --git a/src/lib/Rattletrap/Type/CompressedWordVector.hs b/src/lib/Rattletrap/Type/CompressedWordVector.hs
--- a/src/lib/Rattletrap/Type/CompressedWordVector.hs
+++ b/src/lib/Rattletrap/Type/CompressedWordVector.hs
@@ -7,9 +7,9 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data CompressedWordVector = CompressedWordVector
-  { x :: CompressedWord.CompressedWord
-  , y :: CompressedWord.CompressedWord
-  , z :: CompressedWord.CompressedWord
+  { x :: CompressedWord.CompressedWord,
+    y :: CompressedWord.CompressedWord,
+    z :: CompressedWord.CompressedWord
   }
   deriving (Eq, Show)
 
@@ -18,18 +18,20 @@
     x <- Json.required object "x"
     y <- Json.required object "y"
     z <- Json.required object "z"
-    pure CompressedWordVector { x, y, z }
+    pure CompressedWordVector {x, y, z}
 
 instance Json.ToJSON CompressedWordVector where
   toJSON a =
     Json.object [Json.pair "x" $ x a, Json.pair "y" $ y a, Json.pair "z" $ z a]
 
 schema :: Schema.Schema
-schema = Schema.named "compressed-word-vector" $ Schema.object
-  [ (Json.pair "x" $ Schema.ref CompressedWord.schema, True)
-  , (Json.pair "y" $ Schema.ref CompressedWord.schema, True)
-  , (Json.pair "z" $ Schema.ref CompressedWord.schema, True)
-  ]
+schema =
+  Schema.named "compressed-word-vector" $
+    Schema.object
+      [ (Json.pair "x" $ Schema.ref CompressedWord.schema, True),
+        (Json.pair "y" $ Schema.ref CompressedWord.schema, True),
+        (Json.pair "z" $ Schema.ref CompressedWord.schema, True)
+      ]
 
 bitPut :: CompressedWordVector -> BitPut.BitPut
 bitPut compressedWordVector =
@@ -42,7 +44,7 @@
   x <- CompressedWord.bitGet limit
   y <- CompressedWord.bitGet limit
   z <- CompressedWord.bitGet limit
-  pure CompressedWordVector { x, y, z }
+  pure CompressedWordVector {x, y, z}
 
 limit :: Word
 limit = 65536
diff --git a/src/lib/Rattletrap/Type/Content.hs b/src/lib/Rattletrap/Type/Content.hs
--- a/src/lib/Rattletrap/Type/Content.hs
+++ b/src/lib/Rattletrap/Type/Content.hs
@@ -27,41 +27,41 @@
 
 -- | Contains low-level game data about a 'Rattletrap.Replay.Replay'.
 data ContentWith frames = Content
-  { levels :: List.List Str.Str
-  -- ^ This typically only has one element, like @stadium_oob_audio_map@.
-  , keyframes :: List.List Keyframe.Keyframe
-  -- ^ A list of which frames are key frames. Although they aren't necessary
-  -- for replay, key frames are frames that replicate every actor. They
-  -- typically happen once every 10 seconds.
-  , streamSize :: U32.U32
-  -- ^ The size of the stream in bytes. This is only really necessary because
-  -- the stream has some arbitrary amount of padding at the end.
-  , frames :: frames
-  -- ^ The actual game data. This is where all the interesting information is.
-  , messages :: List.List Message.Message
-  -- ^ Debugging messages. In newer replays, this is always empty.
-  , marks :: List.List Mark.Mark
-  -- ^ Tick marks shown on the scrubber when watching a replay.
-  , packages :: List.List Str.Str
-  -- ^ A list of @.upk@ files to load, like
-  -- @..\\..\\TAGame\\CookedPCConsole\\Stadium_P.upk@.
-  , objects :: List.List Str.Str
-  -- ^ Objects in the stream. Used for the
-  -- 'Rattletrap.Type.ClassAttributeMap.ClassAttributeMap'.
-  , names :: List.List Str.Str
-  -- ^ It's not clear what these are used for. This list is usually not empty,
-  -- but appears unused otherwise.
-  , classMappings :: List.List ClassMapping.ClassMapping
-  -- ^ A mapping between classes and their ID in the stream. Used for the
-  -- 'Rattletrap.Type.ClassAttributeMap.ClassAttributeMap'.
-  , caches :: List.List Cache.Cache
-  -- ^ A list of classes along with their parent classes and attributes. Used
-  -- for the 'Rattletrap.Type.ClassAttributeMap.ClassAttributeMap'.
-  , unknown :: [Word.Word8]
+  { -- | This typically only has one element, like @stadium_oob_audio_map@.
+    levels :: List.List Str.Str,
+    -- | A list of which frames are key frames. Although they aren't necessary
+    -- for replay, key frames are frames that replicate every actor. They
+    -- typically happen once every 10 seconds.
+    keyframes :: List.List Keyframe.Keyframe,
+    -- | The size of the stream in bytes. This is only really necessary because
+    -- the stream has some arbitrary amount of padding at the end.
+    streamSize :: U32.U32,
+    -- | The actual game data. This is where all the interesting information is.
+    frames :: frames,
+    -- | Debugging messages. In newer replays, this is always empty.
+    messages :: List.List Message.Message,
+    -- | Tick marks shown on the scrubber when watching a replay.
+    marks :: List.List Mark.Mark,
+    -- | A list of @.upk@ files to load, like
+    -- @..\\..\\TAGame\\CookedPCConsole\\Stadium_P.upk@.
+    packages :: List.List Str.Str,
+    -- | Objects in the stream. Used for the
+    -- 'Rattletrap.Type.ClassAttributeMap.ClassAttributeMap'.
+    objects :: List.List Str.Str,
+    -- | It's not clear what these are used for. This list is usually not empty,
+    -- but appears unused otherwise.
+    names :: List.List Str.Str,
+    -- | A mapping between classes and their ID in the stream. Used for the
+    -- 'Rattletrap.Type.ClassAttributeMap.ClassAttributeMap'.
+    classMappings :: List.List ClassMapping.ClassMapping,
+    -- | A list of classes along with their parent classes and attributes. Used
+    -- for the 'Rattletrap.Type.ClassAttributeMap.ClassAttributeMap'.
+    caches :: List.List Cache.Cache,
+    unknown :: [Word.Word8]
   }
   deriving (Eq, Show)
 
-instance Json.FromJSON frames => Json.FromJSON (ContentWith frames) where
+instance (Json.FromJSON frames) => Json.FromJSON (ContentWith frames) where
   parseJSON = Json.withObject "Content" $ \object -> do
     levels <- Json.required object "levels"
     keyframes <- Json.required object "key_frames"
@@ -75,71 +75,77 @@
     classMappings <- Json.required object "class_mappings"
     caches <- Json.required object "caches"
     unknown <- Json.required object "unknown"
-    pure Content
-      { levels
-      , keyframes
-      , streamSize
-      , frames
-      , messages
-      , marks
-      , packages
-      , objects
-      , names
-      , classMappings
-      , caches
-      , unknown
-      }
+    pure
+      Content
+        { levels,
+          keyframes,
+          streamSize,
+          frames,
+          messages,
+          marks,
+          packages,
+          objects,
+          names,
+          classMappings,
+          caches,
+          unknown
+        }
 
-instance Json.ToJSON frames => Json.ToJSON (ContentWith frames) where
-  toJSON x = Json.object
-    [ Json.pair "levels" $ levels x
-    , Json.pair "key_frames" $ keyframes x
-    , Json.pair "stream_size" $ streamSize x
-    , Json.pair "frames" $ frames x
-    , Json.pair "messages" $ messages x
-    , Json.pair "marks" $ marks x
-    , Json.pair "packages" $ packages x
-    , Json.pair "objects" $ objects x
-    , Json.pair "names" $ names x
-    , Json.pair "class_mappings" $ classMappings x
-    , Json.pair "caches" $ caches x
-    , Json.pair "unknown" $ unknown x
-    ]
+instance (Json.ToJSON frames) => Json.ToJSON (ContentWith frames) where
+  toJSON x =
+    Json.object
+      [ Json.pair "levels" $ levels x,
+        Json.pair "key_frames" $ keyframes x,
+        Json.pair "stream_size" $ streamSize x,
+        Json.pair "frames" $ frames x,
+        Json.pair "messages" $ messages x,
+        Json.pair "marks" $ marks x,
+        Json.pair "packages" $ packages x,
+        Json.pair "objects" $ objects x,
+        Json.pair "names" $ names x,
+        Json.pair "class_mappings" $ classMappings x,
+        Json.pair "caches" $ caches x,
+        Json.pair "unknown" $ unknown x
+      ]
 
 schema :: Schema.Schema -> Schema.Schema
-schema s = Schema.named "content" $ Schema.object
-  [ (Json.pair "levels" . Schema.json $ List.schema Str.schema, True)
-  , (Json.pair "key_frames" . Schema.json $ List.schema Keyframe.schema, True)
-  , (Json.pair "stream_size" $ Schema.ref U32.schema, True)
-  , (Json.pair "frames" $ Schema.json s, True)
-  , (Json.pair "messages" . Schema.json $ List.schema Message.schema, True)
-  , (Json.pair "marks" . Schema.json $ List.schema Mark.schema, True)
-  , (Json.pair "packages" . Schema.json $ List.schema Str.schema, True)
-  , (Json.pair "objects" . Schema.json $ List.schema Str.schema, True)
-  , (Json.pair "names" . Schema.json $ List.schema Str.schema, True)
-  , ( Json.pair "class_mappings" . Schema.json $ List.schema
-      ClassMapping.schema
-    , True
-    )
-  , (Json.pair "caches" . Schema.json $ List.schema Cache.schema, True)
-  , (Json.pair "unknown" . Schema.json $ Schema.array U8.schema, True)
-  ]
+schema s =
+  Schema.named "content" $
+    Schema.object
+      [ (Json.pair "levels" . Schema.json $ List.schema Str.schema, True),
+        (Json.pair "key_frames" . Schema.json $ List.schema Keyframe.schema, True),
+        (Json.pair "stream_size" $ Schema.ref U32.schema, True),
+        (Json.pair "frames" $ Schema.json s, True),
+        (Json.pair "messages" . Schema.json $ List.schema Message.schema, True),
+        (Json.pair "marks" . Schema.json $ List.schema Mark.schema, True),
+        (Json.pair "packages" . Schema.json $ List.schema Str.schema, True),
+        (Json.pair "objects" . Schema.json $ List.schema Str.schema, True),
+        (Json.pair "names" . Schema.json $ List.schema Str.schema, True),
+        ( Json.pair "class_mappings" . Schema.json $
+            List.schema
+              ClassMapping.schema,
+          True
+        ),
+        (Json.pair "caches" . Schema.json $ List.schema Cache.schema, True),
+        (Json.pair "unknown" . Schema.json $ Schema.array U8.schema, True)
+      ]
 
 empty :: Content
-empty = Content
-  { levels = List.empty
-  , keyframes = List.empty
-  , streamSize = U32.fromWord32 0
-  , frames = List.empty
-  , messages = List.empty
-  , marks = List.empty
-  , packages = List.empty
-  , objects = List.empty
-  , names = List.empty
-  , classMappings = List.empty
-  , caches = List.empty
-  , unknown = []
-  }
+empty =
+  Content
+    { levels = List.empty,
+      keyframes = List.empty,
+      streamSize = U32.fromWord32 0,
+      frames = List.empty,
+      messages = List.empty,
+      marks = List.empty,
+      packages = List.empty,
+      objects = List.empty,
+      names = List.empty,
+      classMappings = List.empty,
+      caches = List.empty,
+      unknown = []
+    }
 
 bytePut :: Content -> BytePut.BytePut
 bytePut x =
@@ -157,80 +163,85 @@
 
 putFrames :: Content -> BytePut.BytePut
 putFrames x =
-  let
-    stream =
-      BytePut.toByteString . BitPut.toBytePut . Frame.putFrames $ frames x
-    -- This is a little strange. When parsing a binary replay, the stream size
-    -- is given before the stream itself. When generating the JSON, the stream
-    -- size is included. That allows a bit-for-bit identical binary replay to
-    -- be generated from the JSON. However if you modify the JSON before
-    -- converting it back into binary, the stream size might be different.
-    --
-    -- If it was possible to know how much padding the stream required without
-    -- carrying it along as extra data on the side, this logic could go away.
-    -- Unforunately that isn't currently known. See this issue for details:
-    -- <https://github.com/tfausak/rattletrap/issues/171>.
-    expectedStreamSize = streamSize x
-    actualStreamSize =
-      U32.fromWord32 . fromIntegral $ ByteString.length stream
-    streamSize_ = U32.fromWord32
-      $ max (U32.toWord32 expectedStreamSize) (U32.toWord32 actualStreamSize)
-  in U32.bytePut streamSize_
-    <> BytePut.byteString (Bytes.padBytes (U32.toWord32 streamSize_) stream)
+  let stream =
+        BytePut.toByteString . BitPut.toBytePut . Frame.putFrames $ frames x
+      -- This is a little strange. When parsing a binary replay, the stream size
+      -- is given before the stream itself. When generating the JSON, the stream
+      -- size is included. That allows a bit-for-bit identical binary replay to
+      -- be generated from the JSON. However if you modify the JSON before
+      -- converting it back into binary, the stream size might be different.
+      --
+      -- If it was possible to know how much padding the stream required without
+      -- carrying it along as extra data on the side, this logic could go away.
+      -- Unforunately that isn't currently known. See this issue for details:
+      -- <https://github.com/tfausak/rattletrap/issues/171>.
+      expectedStreamSize = streamSize x
+      actualStreamSize =
+        U32.fromWord32 . fromIntegral $ ByteString.length stream
+      streamSize_ =
+        U32.fromWord32 $
+          max (U32.toWord32 expectedStreamSize) (U32.toWord32 actualStreamSize)
+   in U32.bytePut streamSize_
+        <> BytePut.byteString (Bytes.padBytes (U32.toWord32 streamSize_) stream)
 
-byteGet
-  :: Maybe Str.Str
-  -> Version.Version
-  -- ^ Version numbers, usually from 'Rattletrap.Header.getVersion'.
-  -> Int
-  -- ^ The number of frames in the stream, usually from
+byteGet ::
+  Maybe Str.Str ->
+  -- | Version numbers, usually from 'Rattletrap.Header.getVersion'.
+  Version.Version ->
+  -- | The number of frames in the stream, usually from
   -- 'Rattletrap.Header.getNumFrames'.
-  -> Word
-  -- ^ The maximum number of channels in the stream, usually from
+  Int ->
+  -- | The maximum number of channels in the stream, usually from
   -- 'Rattletrap.Header.getMaxChannels'.
-  -> Maybe Str.Str
-  -- ^ 'Rattletrap.Header.getBuildVersion'
-  -> ByteGet.ByteGet Content
+  Word ->
+  -- | 'Rattletrap.Header.getBuildVersion'
+  Maybe Str.Str ->
+  ByteGet.ByteGet Content
 byteGet matchType version numFrames maxChannels buildVersion =
   ByteGet.label "Content" $ do
     levels <- ByteGet.label "levels" $ List.byteGet Str.byteGet
     keyframes <- ByteGet.label "keyframes" $ List.byteGet Keyframe.byteGet
     streamSize <- ByteGet.label "streamSize" U32.byteGet
     stream <-
-      ByteGet.label "stream" . ByteGet.byteString . fromIntegral $ U32.toWord32
-        streamSize
+      ByteGet.label "stream" . ByteGet.byteString . fromIntegral $
+        U32.toWord32
+          streamSize
     messages <- ByteGet.label "messages" $ List.byteGet Message.byteGet
     marks <- ByteGet.label "marks" $ List.byteGet Mark.byteGet
     packages <- ByteGet.label "packages" $ List.byteGet Str.byteGet
     objects <- ByteGet.label "objects" $ List.byteGet Str.byteGet
     names <- ByteGet.label "names" $ List.byteGet Str.byteGet
-    classMappings <- ByteGet.label "classMappings"
-      $ List.byteGet ClassMapping.byteGet
+    classMappings <-
+      ByteGet.label "classMappings" $
+        List.byteGet ClassMapping.byteGet
     caches <- ByteGet.label "caches" $ List.byteGet Cache.byteGet
-    let
-      classAttributeMap =
-        ClassAttributeMap.make objects classMappings caches names
-      getFrames = BitGet.toByteGet $ Frame.decodeFramesBits
-        matchType
-        version
-        buildVersion
-        numFrames
-        maxChannels
-        classAttributeMap
+    let classAttributeMap =
+          ClassAttributeMap.make objects classMappings caches names
+        getFrames =
+          BitGet.toByteGet $
+            Frame.decodeFramesBits
+              matchType
+              version
+              buildVersion
+              numFrames
+              maxChannels
+              classAttributeMap
     frames <- ByteGet.label "frames" $ ByteGet.embed getFrames stream
-    unknown <- ByteGet.label "unknown"
-      $ fmap LazyByteString.unpack ByteGet.remaining
-    pure Content
-      { levels
-      , keyframes
-      , streamSize
-      , frames
-      , messages
-      , marks
-      , packages
-      , objects
-      , names
-      , classMappings
-      , caches
-      , unknown
-      }
+    unknown <-
+      ByteGet.label "unknown" $
+        fmap LazyByteString.unpack ByteGet.remaining
+    pure
+      Content
+        { levels,
+          keyframes,
+          streamSize,
+          frames,
+          messages,
+          marks,
+          packages,
+          objects,
+          names,
+          classMappings,
+          caches,
+          unknown
+        }
diff --git a/src/lib/Rattletrap/Type/Dictionary.hs b/src/lib/Rattletrap/Type/Dictionary.hs
--- a/src/lib/Rattletrap/Type/Dictionary.hs
+++ b/src/lib/Rattletrap/Type/Dictionary.hs
@@ -11,55 +11,57 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data Dictionary a = Dictionary
-  { elements :: List.List (Str.Str, a)
-  , lastKey :: Str.Str
+  { elements :: List.List (Str.Str, a),
+    lastKey :: Str.Str
   }
   deriving (Eq, Show)
 
-instance Json.FromJSON a => Json.FromJSON (Dictionary a) where
+instance (Json.FromJSON a) => Json.FromJSON (Dictionary a) where
   parseJSON = Json.withObject "Dictionary" $ \o -> do
     keys <- Json.required o "keys"
     lastKey_ <- Json.required o "last_key"
     value <- Json.required o "value"
-    let
-      build
-        :: MonadFail m
-        => Map.Map Text.Text a
-        -> Int
-        -> [(Int, (Str.Str, a))]
-        -> [Text.Text]
-        -> m (List.List (Str.Str, a))
-      build m i xs ks = case ks of
-        [] -> pure . List.fromList . reverse $ fmap snd xs
-        k : t -> case Map.lookup k m of
-          Nothing -> fail $ "missing required key " <> show k
-          Just v -> build m (i + 1) ((i, (Str.fromText k, v)) : xs) t
+    let build ::
+          (MonadFail m) =>
+          Map.Map Text.Text a ->
+          Int ->
+          [(Int, (Str.Str, a))] ->
+          [Text.Text] ->
+          m (List.List (Str.Str, a))
+        build m i xs ks = case ks of
+          [] -> pure . List.fromList . reverse $ fmap snd xs
+          k : t -> case Map.lookup k m of
+            Nothing -> fail $ "missing required key " <> show k
+            Just v -> build m (i + 1) ((i, (Str.fromText k, v)) : xs) t
     elements_ <- build value 0 [] keys
-    pure Dictionary { elements = elements_, lastKey = lastKey_ }
+    pure Dictionary {elements = elements_, lastKey = lastKey_}
 
-instance Json.ToJSON a => Json.ToJSON (Dictionary a) where
-  toJSON x = Json.object
-    [ Json.pair "keys" . fmap fst . List.toList $ elements x
-    , Json.pair "last_key" $ lastKey x
-    , Json.pair "value"
-    . Map.fromList
-    . fmap (Bifunctor.first Str.toText)
-    . List.toList
-    $ elements x
-    ]
+instance (Json.ToJSON a) => Json.ToJSON (Dictionary a) where
+  toJSON x =
+    Json.object
+      [ Json.pair "keys" . fmap fst . List.toList $ elements x,
+        Json.pair "last_key" $ lastKey x,
+        Json.pair "value"
+          . Map.fromList
+          . fmap (Bifunctor.first Str.toText)
+          . List.toList
+          $ elements x
+      ]
 
 schema :: Schema.Schema -> Schema.Schema
 schema s =
-  Schema.named ("dictionary-" <> Text.unpack (Schema.name s)) $ Schema.object
-    [ (Json.pair "keys" . Schema.json $ Schema.array Str.schema, True)
-    , (Json.pair "last_key" $ Schema.ref Str.schema, True)
-    , ( Json.pair "value" $ Json.object
-        [ Json.pair "type" "object"
-        , Json.pair "additionalProperties" $ Schema.ref s
-        ]
-      , True
-      )
-    ]
+  Schema.named ("dictionary-" <> Text.unpack (Schema.name s)) $
+    Schema.object
+      [ (Json.pair "keys" . Schema.json $ Schema.array Str.schema, True),
+        (Json.pair "last_key" $ Schema.ref Str.schema, True),
+        ( Json.pair "value" $
+            Json.object
+              [ Json.pair "type" "object",
+                Json.pair "additionalProperties" $ Schema.ref s
+              ],
+          True
+        )
+      ]
 
 lookup :: Str.Str -> Dictionary a -> Maybe a
 lookup k = Prelude.lookup k . List.toList . elements
@@ -72,18 +74,20 @@
 byteGet :: ByteGet.ByteGet a -> ByteGet.ByteGet (Dictionary a)
 byteGet = ByteGet.label "Dictionary" . byteGetWith 0 []
 
-byteGetWith
-  :: Int
-  -> [(Int, (Str.Str, a))]
-  -> ByteGet.ByteGet a
-  -> ByteGet.ByteGet (Dictionary a)
+byteGetWith ::
+  Int ->
+  [(Int, (Str.Str, a))] ->
+  ByteGet.ByteGet a ->
+  ByteGet.ByteGet (Dictionary a)
 byteGetWith i xs f = do
   k <- ByteGet.label ("key (" <> show i <> ")") Str.byteGet
   if isNone k
-    then pure Dictionary
-      { elements = List.fromList . reverse $ fmap snd xs
-      , lastKey = k
-      }
+    then
+      pure
+        Dictionary
+          { elements = List.fromList . reverse $ fmap snd xs,
+            lastKey = k
+          }
     else do
       v <- ByteGet.label ("value (" <> Str.toString k <> ")") f
       byteGetWith (i + 1) ((i, (k, v)) : xs) f
diff --git a/src/lib/Rattletrap/Type/Frame.hs b/src/lib/Rattletrap/Type/Frame.hs
--- a/src/lib/Rattletrap/Type/Frame.hs
+++ b/src/lib/Rattletrap/Type/Frame.hs
@@ -15,12 +15,12 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data Frame = Frame
-  { time :: F32.F32
-  -- ^ Time in seconds since the beginning of the match.
-  , delta :: F32.F32
-  -- ^ Time in seconds since the last frame. Usually about 0.03 since there
-  -- are 30 frames per second.
-  , replications :: List.List Replication.Replication
+  { -- | Time in seconds since the beginning of the match.
+    time :: F32.F32,
+    -- | Time in seconds since the last frame. Usually about 0.03 since there
+    -- are 30 frames per second.
+    delta :: F32.F32,
+    replications :: List.List Replication.Replication
   }
   deriving (Eq, Show)
 
@@ -29,23 +29,26 @@
     time <- Json.required object "time"
     delta <- Json.required object "delta"
     replications <- Json.required object "replications"
-    pure Frame { time, delta, replications }
+    pure Frame {time, delta, replications}
 
 instance Json.ToJSON Frame where
-  toJSON x = Json.object
-    [ Json.pair "time" $ time x
-    , Json.pair "delta" $ delta x
-    , Json.pair "replications" $ replications x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "time" $ time x,
+        Json.pair "delta" $ delta x,
+        Json.pair "replications" $ replications x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "frame" $ Schema.object
-  [ (Json.pair "time" $ Schema.ref F32.schema, True)
-  , (Json.pair "delta" $ Schema.ref F32.schema, True)
-  , ( Json.pair "replications" . Schema.json $ List.schema Replication.schema
-    , True
-    )
-  ]
+schema =
+  Schema.named "frame" $
+    Schema.object
+      [ (Json.pair "time" $ Schema.ref F32.schema, True),
+        (Json.pair "delta" $ Schema.ref F32.schema, True),
+        ( Json.pair "replications" . Schema.json $ List.schema Replication.schema,
+          True
+        )
+      ]
 
 putFrames :: List.List Frame -> BitPut.BitPut
 putFrames = foldMap bitPut . List.toList
@@ -56,80 +59,82 @@
     <> F32.bitPut (delta frame)
     <> Replication.putReplications (replications frame)
 
-decodeFramesBits
-  :: Maybe Str.Str
-  -> Version.Version
-  -> Maybe Str.Str
-  -> Int
-  -> Word
-  -> ClassAttributeMap.ClassAttributeMap
-  -> BitGet.BitGet (List.List Frame)
+decodeFramesBits ::
+  Maybe Str.Str ->
+  Version.Version ->
+  Maybe Str.Str ->
+  Int ->
+  Word ->
+  ClassAttributeMap.ClassAttributeMap ->
+  BitGet.BitGet (List.List Frame)
 decodeFramesBits matchType version buildVersion count limit classes =
-  fmap snd $ decodeFramesBitsWith
-    matchType
-    version
-    buildVersion
-    count
-    limit
-    classes
-    Map.empty
-    0
-    []
+  fmap snd $
+    decodeFramesBitsWith
+      matchType
+      version
+      buildVersion
+      count
+      limit
+      classes
+      Map.empty
+      0
+      []
 
-decodeFramesBitsWith
-  :: Maybe Str.Str
-  -> Version.Version
-  -> Maybe Str.Str
-  -> Int
-  -> Word
-  -> ClassAttributeMap.ClassAttributeMap
-  -> Map.Map CompressedWord.CompressedWord U32.U32
-  -> Int
-  -> [Frame]
-  -> BitGet.BitGet
-       ( Map.Map
-           CompressedWord.CompressedWord
-           U32.U32
-       , List.List Frame
-       )
-decodeFramesBitsWith matchType version buildVersion count limit classes actorMap index frames
-  = if index >= count
+decodeFramesBitsWith ::
+  Maybe Str.Str ->
+  Version.Version ->
+  Maybe Str.Str ->
+  Int ->
+  Word ->
+  ClassAttributeMap.ClassAttributeMap ->
+  Map.Map CompressedWord.CompressedWord U32.U32 ->
+  Int ->
+  [Frame] ->
+  BitGet.BitGet
+    ( Map.Map
+        CompressedWord.CompressedWord
+        U32.U32,
+      List.List Frame
+    )
+decodeFramesBitsWith matchType version buildVersion count limit classes actorMap index frames =
+  if index >= count
     then pure (actorMap, List.fromList $ reverse frames)
     else do
       (newActorMap, frame) <-
-        BitGet.label ("element (" <> show index <> ")")
-          $ bitGet matchType version buildVersion limit classes actorMap
+        BitGet.label ("element (" <> show index <> ")") $
+          bitGet matchType version buildVersion limit classes actorMap
       decodeFramesBitsWith
-          matchType
-          version
-          buildVersion
-          count
-          limit
-          classes
-          newActorMap
-          (index + 1)
+        matchType
+        version
+        buildVersion
+        count
+        limit
+        classes
+        newActorMap
+        (index + 1)
         $ frame
-        : frames
+          : frames
 
-bitGet
-  :: Maybe Str.Str
-  -> Version.Version
-  -> Maybe Str.Str
-  -> Word
-  -> ClassAttributeMap.ClassAttributeMap
-  -> Map.Map CompressedWord.CompressedWord U32.U32
-  -> BitGet.BitGet
-       (Map.Map CompressedWord.CompressedWord U32.U32, Frame)
+bitGet ::
+  Maybe Str.Str ->
+  Version.Version ->
+  Maybe Str.Str ->
+  Word ->
+  ClassAttributeMap.ClassAttributeMap ->
+  Map.Map CompressedWord.CompressedWord U32.U32 ->
+  BitGet.BitGet
+    (Map.Map CompressedWord.CompressedWord U32.U32, Frame)
 bitGet matchType version buildVersion limit classes actorMap =
   BitGet.label "Frame" $ do
     time <- BitGet.label "time" F32.bitGet
     delta <- BitGet.label "delta" F32.bitGet
     (newActorMap, replications) <-
-      BitGet.label "replications" $ Replication.decodeReplicationsBits
-        matchType
-        version
-        buildVersion
-        limit
-        classes
-        actorMap
-    pure (newActorMap, Frame { time, delta, replications })
+      BitGet.label "replications" $
+        Replication.decodeReplicationsBits
+          matchType
+          version
+          buildVersion
+          limit
+          classes
+          actorMap
+    pure (newActorMap, Frame {time, delta, replications})
diff --git a/src/lib/Rattletrap/Type/Header.hs b/src/lib/Rattletrap/Type/Header.hs
--- a/src/lib/Rattletrap/Type/Header.hs
+++ b/src/lib/Rattletrap/Type/Header.hs
@@ -12,44 +12,44 @@
 
 -- | Contains high-level metadata about a 'Rattletrap.Replay.Replay'.
 data Header = Header
-  { version :: Version.Version
-  , label :: Str.Str
-  -- ^ Always @TAGame.Replay_Soccar_TA@.
-  , properties :: Dictionary.Dictionary Property.Property
-  -- ^ These properties determine how a replay will look in the list of
-  -- replays in-game. One element is required for the replay to show up:
-  --
-  -- - MapName: This is a 'Rattletrap.PropertyValue.NameProperty' with a
-  --   case-insensitive map identifier, like @Stadium_P@.
-  --
-  -- There are many other properties that affect how the replay looks in the
-  -- list of replays.
-  --
-  -- - Date: A 'Rattletrap.PropertyValue.StrProperty' with the format
-  --   @YYYY-mm-dd:HH-MM@. Dates are not validated, but the month must be
-  --   between 1 and 12 to show up. The hour is shown modulo 12 with AM or PM.
-  -- - MatchType: A 'Rattletrap.PropertyValue.NameProperty'. If this is not
-  --   one of the expected values, nothing will be shown next to the replay's
-  --   map. The expected values are: @Online@, @Offline@, @Private@, and
-  --   @Season@.
-  -- - NumFrames: This 'Rattletrap.PropertyValue.IntProperty' is used to
-  --   calculate the length of the match. There are 30 frames per second,
-  --   a typical 5-minute match has about 9,000 frames.
-  -- - PrimaryPlayerTeam: This is an 'Rattletrap.PropertyValue.IntProperty'.
-  --   It is either 0 (blue) or 1 (orange). Any other value is ignored. If
-  --   this would be 0, you don't have to set it at all.
-  -- - ReplayName: An optional 'Rattletrap.PropertyValue.StrProperty' with a
-  --   user-supplied name for the replay.
-  -- - Team0Score: The blue team's score as an
-  --   'Rattletrap.PropertyValue.IntProperty'. Can be omitted if the score is
-  --   0.
-  -- - Team1Score: The orange team's score as an
-  --   'Rattletrap.PropertyValue.IntProperty'. Can also be omitted if the
-  --   score is 0.
-  -- - TeamSize: An 'Rattletrap.PropertyValue.IntProperty' with the number of
-  --   players per team. This value is not validated, so you can put absurd
-  --   values like 99. To get an "unfair" team size like 1v4, you must set the
-  --   bUnfairBots 'Rattletrap.PropertyValue.BoolProperty' to @True@.
+  { version :: Version.Version,
+    -- | Always @TAGame.Replay_Soccar_TA@.
+    label :: Str.Str,
+    -- | These properties determine how a replay will look in the list of
+    -- replays in-game. One element is required for the replay to show up:
+    --
+    -- - MapName: This is a 'Rattletrap.PropertyValue.NameProperty' with a
+    --   case-insensitive map identifier, like @Stadium_P@.
+    --
+    -- There are many other properties that affect how the replay looks in the
+    -- list of replays.
+    --
+    -- - Date: A 'Rattletrap.PropertyValue.StrProperty' with the format
+    --   @YYYY-mm-dd:HH-MM@. Dates are not validated, but the month must be
+    --   between 1 and 12 to show up. The hour is shown modulo 12 with AM or PM.
+    -- - MatchType: A 'Rattletrap.PropertyValue.NameProperty'. If this is not
+    --   one of the expected values, nothing will be shown next to the replay's
+    --   map. The expected values are: @Online@, @Offline@, @Private@, and
+    --   @Season@.
+    -- - NumFrames: This 'Rattletrap.PropertyValue.IntProperty' is used to
+    --   calculate the length of the match. There are 30 frames per second,
+    --   a typical 5-minute match has about 9,000 frames.
+    -- - PrimaryPlayerTeam: This is an 'Rattletrap.PropertyValue.IntProperty'.
+    --   It is either 0 (blue) or 1 (orange). Any other value is ignored. If
+    --   this would be 0, you don't have to set it at all.
+    -- - ReplayName: An optional 'Rattletrap.PropertyValue.StrProperty' with a
+    --   user-supplied name for the replay.
+    -- - Team0Score: The blue team's score as an
+    --   'Rattletrap.PropertyValue.IntProperty'. Can be omitted if the score is
+    --   0.
+    -- - Team1Score: The orange team's score as an
+    --   'Rattletrap.PropertyValue.IntProperty'. Can also be omitted if the
+    --   score is 0.
+    -- - TeamSize: An 'Rattletrap.PropertyValue.IntProperty' with the number of
+    --   players per team. This value is not validated, so you can put absurd
+    --   values like 99. To get an "unfair" team size like 1v4, you must set the
+    --   bUnfairBots 'Rattletrap.PropertyValue.BoolProperty' to @True@.
+    properties :: Dictionary.Dictionary Property.Property
   }
   deriving (Eq, Show)
 
@@ -60,46 +60,54 @@
     patch <- Json.optional object "patch_version"
     label <- Json.required object "label"
     properties <- Json.required object "properties"
-    pure Header
-      { version = Version.Version
-        { Version.major
-        , Version.minor
-        , Version.patch
+    pure
+      Header
+        { version =
+            Version.Version
+              { Version.major,
+                Version.minor,
+                Version.patch
+              },
+          label,
+          properties
         }
-      , label
-      , properties
-      }
 
 instance Json.ToJSON Header where
-  toJSON x = Json.object
-    [ Json.pair "engine_version" . Version.major $ version x
-    , Json.pair "licensee_version" . Version.minor $ version x
-    , Json.pair "patch_version" . Version.patch $ version x
-    , Json.pair "label" $ label x
-    , Json.pair "properties" $ properties x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "engine_version" . Version.major $ version x,
+        Json.pair "licensee_version" . Version.minor $ version x,
+        Json.pair "patch_version" . Version.patch $ version x,
+        Json.pair "label" $ label x,
+        Json.pair "properties" $ properties x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "header" $ Schema.object
-  [ (Json.pair "engine_version" $ Schema.ref U32.schema, True)
-  , (Json.pair "licensee_version" $ Schema.ref U32.schema, True)
-  , (Json.pair "patch_version" . Schema.json $ Schema.maybe U32.schema, False)
-  , (Json.pair "label" $ Schema.ref Str.schema, True)
-  , ( Json.pair "properties" . Schema.json $ Dictionary.schema Property.schema
-    , True
-    )
-  ]
+schema =
+  Schema.named "header" $
+    Schema.object
+      [ (Json.pair "engine_version" $ Schema.ref U32.schema, True),
+        (Json.pair "licensee_version" $ Schema.ref U32.schema, True),
+        (Json.pair "patch_version" . Schema.json $ Schema.maybe U32.schema, False),
+        (Json.pair "label" $ Schema.ref Str.schema, True),
+        ( Json.pair "properties" . Schema.json $ Dictionary.schema Property.schema,
+          True
+        )
+      ]
 
 bytePut :: Header -> BytePut.BytePut
 bytePut x =
-  Version.bytePut (version x) <> Str.bytePut (label x) <> Dictionary.bytePut
-    Property.bytePut
-    (properties x)
+  Version.bytePut (version x)
+    <> Str.bytePut (label x)
+    <> Dictionary.bytePut
+      Property.bytePut
+      (properties x)
 
 byteGet :: ByteGet.ByteGet Header
 byteGet = ByteGet.label "Header" $ do
   version <- ByteGet.label "version" Version.byteGet
   label <- ByteGet.label "label" Str.byteGet
-  properties <- ByteGet.label "properties"
-    $ Dictionary.byteGet Property.byteGet
-  pure Header { version, label, properties }
+  properties <-
+    ByteGet.label "properties" $
+      Dictionary.byteGet Property.byteGet
+  pure Header {version, label, properties}
diff --git a/src/lib/Rattletrap/Type/I32.hs b/src/lib/Rattletrap/Type/I32.hs
--- a/src/lib/Rattletrap/Type/I32.hs
+++ b/src/lib/Rattletrap/Type/I32.hs
@@ -19,11 +19,13 @@
   toJSON = Json.toJSON . toInt32
 
 schema :: Schema.Schema
-schema = Schema.named "i32" $ Json.object
-  [ Json.pair "type" "integer"
-  , Json.pair "minimum" (minBound :: Int.Int32)
-  , Json.pair "maximum" (maxBound :: Int.Int32)
-  ]
+schema =
+  Schema.named "i32" $
+    Json.object
+      [ Json.pair "type" "integer",
+        Json.pair "minimum" (minBound :: Int.Int32),
+        Json.pair "maximum" (maxBound :: Int.Int32)
+      ]
 
 fromInt32 :: Int.Int32 -> I32
 fromInt32 = I32
diff --git a/src/lib/Rattletrap/Type/I64.hs b/src/lib/Rattletrap/Type/I64.hs
--- a/src/lib/Rattletrap/Type/I64.hs
+++ b/src/lib/Rattletrap/Type/I64.hs
@@ -16,17 +16,18 @@
 
 instance Json.FromJSON I64 where
   parseJSON =
-    Json.withText "I64"
-      $ either fail (pure . fromInt64)
-      . Read.readEither
-      . Text.unpack
+    Json.withText "I64" $
+      either fail (pure . fromInt64)
+        . Read.readEither
+        . Text.unpack
 
 instance Json.ToJSON I64 where
   toJSON = Json.toJSON . show . toInt64
 
 schema :: Schema.Schema
-schema = Schema.named "i64"
-  $ Json.object [Json.pair "type" "string", Json.pair "pattern" "^-?[0-9]+$"]
+schema =
+  Schema.named "i64" $
+    Json.object [Json.pair "type" "string", Json.pair "pattern" "^-?[0-9]+$"]
 
 fromInt64 :: Int.Int64 -> I64
 fromInt64 = I64
diff --git a/src/lib/Rattletrap/Type/I8.hs b/src/lib/Rattletrap/Type/I8.hs
--- a/src/lib/Rattletrap/Type/I8.hs
+++ b/src/lib/Rattletrap/Type/I8.hs
@@ -19,11 +19,13 @@
   toJSON = Json.toJSON . toInt8
 
 schema :: Schema.Schema
-schema = Schema.named "i8" $ Json.object
-  [ Json.pair "type" "integer"
-  , Json.pair "minimum" (minBound :: Int.Int8)
-  , Json.pair "maximum" (maxBound :: Int.Int8)
-  ]
+schema =
+  Schema.named "i8" $
+    Json.object
+      [ Json.pair "type" "integer",
+        Json.pair "minimum" (minBound :: Int.Int8),
+        Json.pair "maximum" (maxBound :: Int.Int8)
+      ]
 
 fromInt8 :: Int.Int8 -> I8
 fromInt8 = I8
diff --git a/src/lib/Rattletrap/Type/Initialization.hs b/src/lib/Rattletrap/Type/Initialization.hs
--- a/src/lib/Rattletrap/Type/Initialization.hs
+++ b/src/lib/Rattletrap/Type/Initialization.hs
@@ -10,12 +10,12 @@
 import qualified Rattletrap.Utility.Monad as Monad
 
 data Initialization = Initialization
-  { location :: Maybe Vector.Vector
-  -- ^ Not every class has an initial location. See
-  -- 'Rattletrap.Data.classesWithLocation'.
-  , rotation :: Maybe Int8Vector.Int8Vector
-  -- ^ Only classes with location can have rotation, but not every one does.
-  -- See 'Rattletrap.Data.classesWithRotation'.
+  { -- | Not every class has an initial location. See
+    -- 'Rattletrap.Data.classesWithLocation'.
+    location :: Maybe Vector.Vector,
+    -- | Only classes with location can have rotation, but not every one does.
+    -- See 'Rattletrap.Data.classesWithRotation'.
+    rotation :: Maybe Int8Vector.Int8Vector
   }
   deriving (Eq, Show)
 
@@ -23,19 +23,22 @@
   parseJSON = Json.withObject "Initialization" $ \object -> do
     location <- Json.optional object "location"
     rotation <- Json.optional object "rotation"
-    pure Initialization { location, rotation }
+    pure Initialization {location, rotation}
 
 instance Json.ToJSON Initialization where
-  toJSON x = Json.object
-    [Json.pair "location" $ location x, Json.pair "rotation" $ rotation x]
+  toJSON x =
+    Json.object
+      [Json.pair "location" $ location x, Json.pair "rotation" $ rotation x]
 
 schema :: Schema.Schema
-schema = Schema.named "initialization" $ Schema.object
-  [ (Json.pair "location" . Schema.json $ Schema.maybe Vector.schema, False)
-  , ( Json.pair "rotation" . Schema.json $ Schema.maybe Int8Vector.schema
-    , False
-    )
-  ]
+schema =
+  Schema.named "initialization" $
+    Schema.object
+      [ (Json.pair "location" . Schema.json $ Schema.maybe Vector.schema, False),
+        ( Json.pair "rotation" . Schema.json $ Schema.maybe Int8Vector.schema,
+          False
+        )
+      ]
 
 bitPut :: Initialization -> BitPut.BitPut
 bitPut initialization =
@@ -44,8 +47,10 @@
 
 bitGet :: Version.Version -> Bool -> Bool -> BitGet.BitGet Initialization
 bitGet version hasLocation hasRotation = BitGet.label "Initialization" $ do
-  location <- BitGet.label "location"
-    $ Monad.whenMaybe hasLocation (Vector.bitGet version)
-  rotation <- BitGet.label "rotation"
-    $ Monad.whenMaybe hasRotation Int8Vector.bitGet
-  pure Initialization { location, rotation }
+  location <-
+    BitGet.label "location" $
+      Monad.whenMaybe hasLocation (Vector.bitGet version)
+  rotation <-
+    BitGet.label "rotation" $
+      Monad.whenMaybe hasRotation Int8Vector.bitGet
+  pure Initialization {location, rotation}
diff --git a/src/lib/Rattletrap/Type/Int8Vector.hs b/src/lib/Rattletrap/Type/Int8Vector.hs
--- a/src/lib/Rattletrap/Type/Int8Vector.hs
+++ b/src/lib/Rattletrap/Type/Int8Vector.hs
@@ -8,9 +8,9 @@
 import qualified Rattletrap.Utility.Monad as Monad
 
 data Int8Vector = Int8Vector
-  { x :: Maybe I8.I8
-  , y :: Maybe I8.I8
-  , z :: Maybe I8.I8
+  { x :: Maybe I8.I8,
+    y :: Maybe I8.I8,
+    z :: Maybe I8.I8
   }
   deriving (Eq, Show)
 
@@ -19,18 +19,20 @@
     x <- Json.optional object "x"
     y <- Json.optional object "y"
     z <- Json.optional object "z"
-    pure Int8Vector { x, y, z }
+    pure Int8Vector {x, y, z}
 
 instance Json.ToJSON Int8Vector where
   toJSON a =
     Json.object [Json.pair "x" $ x a, Json.pair "y" $ y a, Json.pair "z" $ z a]
 
 schema :: Schema.Schema
-schema = Schema.named "int8Vector" $ Schema.object
-  [ (Json.pair "x" . Schema.json $ Schema.maybe I8.schema, False)
-  , (Json.pair "y" . Schema.json $ Schema.maybe I8.schema, False)
-  , (Json.pair "z" . Schema.json $ Schema.maybe I8.schema, False)
-  ]
+schema =
+  Schema.named "int8Vector" $
+    Schema.object
+      [ (Json.pair "x" . Schema.json $ Schema.maybe I8.schema, False),
+        (Json.pair "y" . Schema.json $ Schema.maybe I8.schema, False),
+        (Json.pair "z" . Schema.json $ Schema.maybe I8.schema, False)
+      ]
 
 bitPut :: Int8Vector -> BitPut.BitPut
 bitPut int8Vector =
@@ -48,7 +50,7 @@
   x <- BitGet.label "x" decodeFieldBits
   y <- BitGet.label "y" decodeFieldBits
   z <- BitGet.label "z" decodeFieldBits
-  pure Int8Vector { x, y, z }
+  pure Int8Vector {x, y, z}
 
 decodeFieldBits :: BitGet.BitGet (Maybe I8.I8)
 decodeFieldBits = do
diff --git a/src/lib/Rattletrap/Type/Keyframe.hs b/src/lib/Rattletrap/Type/Keyframe.hs
--- a/src/lib/Rattletrap/Type/Keyframe.hs
+++ b/src/lib/Rattletrap/Type/Keyframe.hs
@@ -8,12 +8,12 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data Keyframe = Keyframe
-  { time :: F32.F32
-  -- ^ When this key frame occurs, in seconds.
-  , frame :: U32.U32
-  -- ^ The frame number of this key frame, starting from 0.
-  , position :: U32.U32
-  -- ^ The bit position of this key frame in the stream.
+  { -- | When this key frame occurs, in seconds.
+    time :: F32.F32,
+    -- | The frame number of this key frame, starting from 0.
+    frame :: U32.U32,
+    -- | The bit position of this key frame in the stream.
+    position :: U32.U32
   }
   deriving (Eq, Show)
 
@@ -22,21 +22,24 @@
     time <- Json.required object "time"
     frame <- Json.required object "frame"
     position <- Json.required object "position"
-    pure Keyframe { time, frame, position }
+    pure Keyframe {time, frame, position}
 
 instance Json.ToJSON Keyframe where
-  toJSON x = Json.object
-    [ Json.pair "time" $ time x
-    , Json.pair "frame" $ frame x
-    , Json.pair "position" $ position x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "time" $ time x,
+        Json.pair "frame" $ frame x,
+        Json.pair "position" $ position x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "keyframe" $ Schema.object
-  [ (Json.pair "time" $ Schema.ref F32.schema, True)
-  , (Json.pair "frame" $ Schema.ref U32.schema, True)
-  , (Json.pair "position" $ Schema.ref U32.schema, True)
-  ]
+schema =
+  Schema.named "keyframe" $
+    Schema.object
+      [ (Json.pair "time" $ Schema.ref F32.schema, True),
+        (Json.pair "frame" $ Schema.ref U32.schema, True),
+        (Json.pair "position" $ Schema.ref U32.schema, True)
+      ]
 
 bytePut :: Keyframe -> BytePut.BytePut
 bytePut x =
@@ -47,4 +50,4 @@
   time <- ByteGet.label "time" F32.byteGet
   frame <- ByteGet.label "frame" U32.byteGet
   position <- ByteGet.label "position" U32.byteGet
-  pure Keyframe { time, frame, position }
+  pure Keyframe {time, frame, position}
diff --git a/src/lib/Rattletrap/Type/List.hs b/src/lib/Rattletrap/Type/List.hs
--- a/src/lib/Rattletrap/Type/List.hs
+++ b/src/lib/Rattletrap/Type/List.hs
@@ -11,10 +11,10 @@
   = List [a]
   deriving (Eq, Show)
 
-instance Json.FromJSON a => Json.FromJSON (List a) where
+instance (Json.FromJSON a) => Json.FromJSON (List a) where
   parseJSON = fmap fromList . Json.parseJSON
 
-instance Json.ToJSON a => Json.ToJSON (List a) where
+instance (Json.ToJSON a) => Json.ToJSON (List a) where
   toJSON = Json.toJSON . toList
 
 schema :: Schema.Schema -> Schema.Schema
@@ -32,24 +32,24 @@
 bytePut :: (a -> BytePut.BytePut) -> List a -> BytePut.BytePut
 bytePut f x =
   let v = toList x
-  in (U32.bytePut . U32.fromWord32 . fromIntegral $ length v) <> foldMap f v
+   in (U32.bytePut . U32.fromWord32 . fromIntegral $ length v) <> foldMap f v
 
 byteGet :: ByteGet.ByteGet a -> ByteGet.ByteGet (List a)
 byteGet f = ByteGet.label "List" $ do
   size <- ByteGet.label "size" U32.byteGet
-  generateM (fromIntegral $ U32.toWord32 size)
-    $ \i -> ByteGet.label ("element (" <> show i <> ")") f
+  generateM (fromIntegral $ U32.toWord32 size) $
+    \i -> ByteGet.label ("element (" <> show i <> ")") f
 
-generateM :: Monad m => Int -> (Int -> m a) -> m (List a)
+generateM :: (Monad m) => Int -> (Int -> m a) -> m (List a)
 generateM n f = fmap fromList $ mapM f [0 .. n - 1]
 
-replicateM :: Monad m => Int -> m a -> m (List a)
+replicateM :: (Monad m) => Int -> m a -> m (List a)
 replicateM n = fmap fromList . Monad.replicateM n
 
-untilM :: Monad m => m (Maybe a) -> m (List a)
+untilM :: (Monad m) => m (Maybe a) -> m (List a)
 untilM f = untilMWith f 0 []
 
-untilMWith :: Monad m => m (Maybe a) -> Int -> [(Int, a)] -> m (List a)
+untilMWith :: (Monad m) => m (Maybe a) -> Int -> [(Int, a)] -> m (List a)
 untilMWith f i xs = do
   m <- f
   case m of
diff --git a/src/lib/Rattletrap/Type/Mark.hs b/src/lib/Rattletrap/Type/Mark.hs
--- a/src/lib/Rattletrap/Type/Mark.hs
+++ b/src/lib/Rattletrap/Type/Mark.hs
@@ -8,10 +8,10 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data Mark = Mark
-  { value :: Str.Str
-  -- ^ Which type of mark this is, like @Team0Goal@.
-  , frame :: U32.U32
-  -- ^ Which frame this mark belongs to, starting from 0.
+  { -- | Which type of mark this is, like @Team0Goal@.
+    value :: Str.Str,
+    -- | Which frame this mark belongs to, starting from 0.
+    frame :: U32.U32
   }
   deriving (Eq, Show)
 
@@ -19,17 +19,19 @@
   parseJSON = Json.withObject "Mark" $ \object -> do
     value <- Json.required object "value"
     frame <- Json.required object "frame"
-    pure Mark { value, frame }
+    pure Mark {value, frame}
 
 instance Json.ToJSON Mark where
   toJSON x =
     Json.object [Json.pair "value" $ value x, Json.pair "frame" $ frame x]
 
 schema :: Schema.Schema
-schema = Schema.named "mark" $ Schema.object
-  [ (Json.pair "value" $ Schema.ref Str.schema, True)
-  , (Json.pair "frame" $ Schema.ref U32.schema, True)
-  ]
+schema =
+  Schema.named "mark" $
+    Schema.object
+      [ (Json.pair "value" $ Schema.ref Str.schema, True),
+        (Json.pair "frame" $ Schema.ref U32.schema, True)
+      ]
 
 bytePut :: Mark -> BytePut.BytePut
 bytePut x = Str.bytePut (value x) <> U32.bytePut (frame x)
@@ -38,4 +40,4 @@
 byteGet = ByteGet.label "Mark" $ do
   value <- ByteGet.label "value" Str.byteGet
   frame <- ByteGet.label "frame" U32.byteGet
-  pure Mark { value, frame }
+  pure Mark {value, frame}
diff --git a/src/lib/Rattletrap/Type/Message.hs b/src/lib/Rattletrap/Type/Message.hs
--- a/src/lib/Rattletrap/Type/Message.hs
+++ b/src/lib/Rattletrap/Type/Message.hs
@@ -8,12 +8,12 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data Message = Message
-  { frame :: U32.U32
-  -- ^ Which frame this message belongs to, starting from 0.
-  , name :: Str.Str
-  -- ^ The primary player's name.
-  , value :: Str.Str
-  -- ^ The content of the message.
+  { -- | Which frame this message belongs to, starting from 0.
+    frame :: U32.U32,
+    -- | The primary player's name.
+    name :: Str.Str,
+    -- | The content of the message.
+    value :: Str.Str
   }
   deriving (Eq, Show)
 
@@ -22,21 +22,24 @@
     frame <- Json.required object "frame"
     name <- Json.required object "name"
     value <- Json.required object "value"
-    pure Message { frame, name, value }
+    pure Message {frame, name, value}
 
 instance Json.ToJSON Message where
-  toJSON x = Json.object
-    [ Json.pair "frame" $ frame x
-    , Json.pair "name" $ name x
-    , Json.pair "value" $ value x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "frame" $ frame x,
+        Json.pair "name" $ name x,
+        Json.pair "value" $ value x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "message" $ Schema.object
-  [ (Json.pair "frame" $ Schema.ref U32.schema, True)
-  , (Json.pair "name" $ Schema.ref Str.schema, True)
-  , (Json.pair "value" $ Schema.ref Str.schema, True)
-  ]
+schema =
+  Schema.named "message" $
+    Schema.object
+      [ (Json.pair "frame" $ Schema.ref U32.schema, True),
+        (Json.pair "name" $ Schema.ref Str.schema, True),
+        (Json.pair "value" $ Schema.ref Str.schema, True)
+      ]
 
 bytePut :: Message -> BytePut.BytePut
 bytePut x =
@@ -47,4 +50,4 @@
   frame <- ByteGet.label "frame" U32.byteGet
   name <- ByteGet.label "name" Str.byteGet
   value <- ByteGet.label "value" Str.byteGet
-  pure Message { frame, name, value }
+  pure Message {frame, name, value}
diff --git a/src/lib/Rattletrap/Type/Property.hs b/src/lib/Rattletrap/Type/Property.hs
--- a/src/lib/Rattletrap/Type/Property.hs
+++ b/src/lib/Rattletrap/Type/Property.hs
@@ -9,10 +9,10 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data Property = Property
-  { kind :: Str.Str
-  , size :: U64.U64
-  -- ^ Not used.
-  , value :: PropertyValue.PropertyValue Property
+  { kind :: Str.Str,
+    -- | Not used.
+    size :: U64.U64,
+    value :: PropertyValue.PropertyValue Property
   }
   deriving (Eq, Show)
 
@@ -21,31 +21,36 @@
     kind <- Json.required object "kind"
     size <- Json.required object "size"
     value <- Json.required object "value"
-    pure Property { kind, size, value }
+    pure Property {kind, size, value}
 
 instance Json.ToJSON Property where
-  toJSON x = Json.object
-    [ Json.pair "kind" $ kind x
-    , Json.pair "size" $ size x
-    , Json.pair "value" $ value x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "kind" $ kind x,
+        Json.pair "size" $ size x,
+        Json.pair "value" $ value x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "property" $ Schema.object
-  [ (Json.pair "kind" $ Schema.ref Str.schema, True)
-  , (Json.pair "size" $ Schema.ref U64.schema, True)
-  , (Json.pair "value" . Schema.ref $ PropertyValue.schema schema, True)
-  ]
+schema =
+  Schema.named "property" $
+    Schema.object
+      [ (Json.pair "kind" $ Schema.ref Str.schema, True),
+        (Json.pair "size" $ Schema.ref U64.schema, True),
+        (Json.pair "value" . Schema.ref $ PropertyValue.schema schema, True)
+      ]
 
 bytePut :: Property -> BytePut.BytePut
 bytePut x =
-  Str.bytePut (kind x) <> U64.bytePut (size x) <> PropertyValue.bytePut
-    bytePut
-    (value x)
+  Str.bytePut (kind x)
+    <> U64.bytePut (size x)
+    <> PropertyValue.bytePut
+      bytePut
+      (value x)
 
 byteGet :: ByteGet.ByteGet Property
 byteGet = ByteGet.label "Property" $ do
   kind <- ByteGet.label "kind" Str.byteGet
   size <- ByteGet.label "size" U64.byteGet
   value <- ByteGet.label "value" $ PropertyValue.byteGet byteGet kind
-  pure Property { kind, size, value }
+  pure Property {kind, size, value}
diff --git a/src/lib/Rattletrap/Type/Property/Array.hs b/src/lib/Rattletrap/Type/Property/Array.hs
--- a/src/lib/Rattletrap/Type/Property/Array.hs
+++ b/src/lib/Rattletrap/Type/Property/Array.hs
@@ -17,16 +17,17 @@
 toList :: Array a -> List.List (Dictionary.Dictionary a)
 toList (Array x) = x
 
-instance Json.FromJSON a => Json.FromJSON (Array a) where
+instance (Json.FromJSON a) => Json.FromJSON (Array a) where
   parseJSON = fmap fromList . Json.parseJSON
 
-instance Json.ToJSON a => Json.ToJSON (Array a) where
+instance (Json.ToJSON a) => Json.ToJSON (Array a) where
   toJSON = Json.toJSON . toList
 
 schema :: Schema.Schema -> Schema.Schema
 schema s =
-  Schema.named "property-array" . Schema.json . List.schema $ Dictionary.schema
-    s
+  Schema.named "property-array" . Schema.json . List.schema $
+    Dictionary.schema
+      s
 
 bytePut :: (a -> BytePut.BytePut) -> Array a -> BytePut.BytePut
 bytePut f = List.bytePut (Dictionary.bytePut f) . toList
diff --git a/src/lib/Rattletrap/Type/Property/Bool.hs b/src/lib/Rattletrap/Type/Property/Bool.hs
--- a/src/lib/Rattletrap/Type/Property/Bool.hs
+++ b/src/lib/Rattletrap/Type/Property/Bool.hs
@@ -1,11 +1,11 @@
 module Rattletrap.Type.Property.Bool where
 
-import Prelude hiding (Bool)
 import qualified Rattletrap.ByteGet as ByteGet
 import qualified Rattletrap.BytePut as BytePut
 import qualified Rattletrap.Schema as Schema
 import qualified Rattletrap.Type.U8 as U8
 import qualified Rattletrap.Utility.Json as Json
+import Prelude hiding (Bool)
 
 newtype Bool
   = Bool U8.U8
diff --git a/src/lib/Rattletrap/Type/Property/Byte.hs b/src/lib/Rattletrap/Type/Property/Byte.hs
--- a/src/lib/Rattletrap/Type/Property/Byte.hs
+++ b/src/lib/Rattletrap/Type/Property/Byte.hs
@@ -8,22 +8,24 @@
 import qualified Rattletrap.Utility.Monad as Monad
 
 data Byte = Byte
-  { key :: Str.Str
-  , value :: Maybe Str.Str
+  { key :: Str.Str,
+    value :: Maybe Str.Str
   }
   deriving (Eq, Show)
 
 instance Json.FromJSON Byte where
   parseJSON json = do
     (key, value) <- Json.parseJSON json
-    pure Byte { key, value }
+    pure Byte {key, value}
 
 instance Json.ToJSON Byte where
   toJSON byte = Json.toJSON (key byte, value byte)
 
 schema :: Schema.Schema
-schema = Schema.named "property-byte" $ Schema.tuple
-  [Schema.ref Str.schema, Schema.json $ Schema.maybe Str.schema]
+schema =
+  Schema.named "property-byte" $
+    Schema.tuple
+      [Schema.ref Str.schema, Schema.json $ Schema.maybe Str.schema]
 
 bytePut :: Byte -> BytePut.BytePut
 bytePut byte = Str.bytePut (key byte) <> foldMap Str.bytePut (value byte)
@@ -31,9 +33,9 @@
 byteGet :: ByteGet.ByteGet Byte
 byteGet = ByteGet.label "Byte" $ do
   key <- ByteGet.label "key" Str.byteGet
-  let
-    isSteam = key == Str.fromString "OnlinePlatform_Steam"
-    isPlayStation = key == Str.fromString "OnlinePlatform_PS4"
-  value <- ByteGet.label "value"
-    $ Monad.whenMaybe (not $ isSteam || isPlayStation) Str.byteGet
-  pure Byte { key, value }
+  let isSteam = key == Str.fromString "OnlinePlatform_Steam"
+      isPlayStation = key == Str.fromString "OnlinePlatform_PS4"
+  value <-
+    ByteGet.label "value" $
+      Monad.whenMaybe (not $ isSteam || isPlayStation) Str.byteGet
+  pure Byte {key, value}
diff --git a/src/lib/Rattletrap/Type/Property/Float.hs b/src/lib/Rattletrap/Type/Property/Float.hs
--- a/src/lib/Rattletrap/Type/Property/Float.hs
+++ b/src/lib/Rattletrap/Type/Property/Float.hs
@@ -1,11 +1,11 @@
 module Rattletrap.Type.Property.Float where
 
-import Prelude hiding (Float)
 import qualified Rattletrap.ByteGet as ByteGet
 import qualified Rattletrap.BytePut as BytePut
 import qualified Rattletrap.Schema as Schema
 import qualified Rattletrap.Type.F32 as F32
 import qualified Rattletrap.Utility.Json as Json
+import Prelude hiding (Float)
 
 newtype Float
   = Float F32.F32
diff --git a/src/lib/Rattletrap/Type/Property/Int.hs b/src/lib/Rattletrap/Type/Property/Int.hs
--- a/src/lib/Rattletrap/Type/Property/Int.hs
+++ b/src/lib/Rattletrap/Type/Property/Int.hs
@@ -1,11 +1,11 @@
 module Rattletrap.Type.Property.Int where
 
-import Prelude hiding (Int)
 import qualified Rattletrap.ByteGet as ByteGet
 import qualified Rattletrap.BytePut as BytePut
 import qualified Rattletrap.Schema as Schema
 import qualified Rattletrap.Type.I32 as I32
 import qualified Rattletrap.Utility.Json as Json
+import Prelude hiding (Int)
 
 newtype Int
   = Int I32.I32
diff --git a/src/lib/Rattletrap/Type/PropertyValue.hs b/src/lib/Rattletrap/Type/PropertyValue.hs
--- a/src/lib/Rattletrap/Type/PropertyValue.hs
+++ b/src/lib/Rattletrap/Type/PropertyValue.hs
@@ -17,33 +17,34 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data PropertyValue a
-  = Array (Property.Array.Array a)
-  -- ^ Yes, a list of dictionaries. No, it doesn't make sense. These usually
-  -- only have one element.
+  = -- | Yes, a list of dictionaries. No, it doesn't make sense. These usually
+    -- only have one element.
+    Array (Property.Array.Array a)
   | Bool Property.Bool.Bool
-  | Byte Property.Byte.Byte
-  -- ^ This is a strange name for essentially a key-value pair.
+  | -- | This is a strange name for essentially a key-value pair.
+    Byte Property.Byte.Byte
   | Float Property.Float.Float
   | Int Property.Int.Int
-  | Name Property.Name.Name
-  -- ^ It's unclear how exactly this is different than a 'StrProperty'.
+  | -- | It's unclear how exactly this is different than a 'StrProperty'.
+    Name Property.Name.Name
   | QWord Property.QWord.QWord
   | Str Property.Str.Str
   deriving (Eq, Show)
 
-instance Json.FromJSON a => Json.FromJSON (PropertyValue a) where
-  parseJSON = Json.withObject "PropertyValue" $ \object -> Foldable.asum
-    [ fmap Array $ Json.required object "array"
-    , fmap Bool $ Json.required object "bool"
-    , fmap Byte $ Json.required object "byte"
-    , fmap Float $ Json.required object "float"
-    , fmap Int $ Json.required object "int"
-    , fmap Name $ Json.required object "name"
-    , fmap QWord $ Json.required object "q_word"
-    , fmap Str $ Json.required object "str"
-    ]
+instance (Json.FromJSON a) => Json.FromJSON (PropertyValue a) where
+  parseJSON = Json.withObject "PropertyValue" $ \object ->
+    Foldable.asum
+      [ fmap Array $ Json.required object "array",
+        fmap Bool $ Json.required object "bool",
+        fmap Byte $ Json.required object "byte",
+        fmap Float $ Json.required object "float",
+        fmap Int $ Json.required object "int",
+        fmap Name $ Json.required object "name",
+        fmap QWord $ Json.required object "q_word",
+        fmap Str $ Json.required object "str"
+      ]
 
-instance Json.ToJSON a => Json.ToJSON (PropertyValue a) where
+instance (Json.ToJSON a) => Json.ToJSON (PropertyValue a) where
   toJSON x = case x of
     Array y -> Json.object [Json.pair "array" y]
     Bool y -> Json.object [Json.pair "bool" y]
@@ -55,17 +56,19 @@
     Str y -> Json.object [Json.pair "str" y]
 
 schema :: Schema.Schema -> Schema.Schema
-schema s = Schema.named "property-value" . Schema.oneOf $ fmap
-  (\(k, v) -> Schema.object [(Json.pair k v, True)])
-  [ ("array", Schema.ref $ Property.Array.schema s)
-  , ("bool", Schema.ref Property.Bool.schema)
-  , ("byte", Schema.ref Property.Byte.schema)
-  , ("float", Schema.ref Property.Float.schema)
-  , ("int", Schema.ref Property.Int.schema)
-  , ("name", Schema.ref Property.Name.schema)
-  , ("q_word", Schema.ref Property.QWord.schema)
-  , ("str", Schema.ref Property.Str.schema)
-  ]
+schema s =
+  Schema.named "property-value" . Schema.oneOf $
+    fmap
+      (\(k, v) -> Schema.object [(Json.pair k v, True)])
+      [ ("array", Schema.ref $ Property.Array.schema s),
+        ("bool", Schema.ref Property.Bool.schema),
+        ("byte", Schema.ref Property.Byte.schema),
+        ("float", Schema.ref Property.Float.schema),
+        ("int", Schema.ref Property.Int.schema),
+        ("name", Schema.ref Property.Name.schema),
+        ("q_word", Schema.ref Property.QWord.schema),
+        ("str", Schema.ref Property.Str.schema)
+      ]
 
 bytePut :: (a -> BytePut.BytePut) -> PropertyValue a -> BytePut.BytePut
 bytePut putProperty value = case value of
diff --git a/src/lib/Rattletrap/Type/Quaternion.hs b/src/lib/Rattletrap/Type/Quaternion.hs
--- a/src/lib/Rattletrap/Type/Quaternion.hs
+++ b/src/lib/Rattletrap/Type/Quaternion.hs
@@ -11,10 +11,10 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data Quaternion = Quaternion
-  { x :: Double
-  , y :: Double
-  , z :: Double
-  , w :: Double
+  { x :: Double,
+    y :: Double,
+    z :: Double,
+    w :: Double
   }
   deriving (Eq, Show)
 
@@ -24,23 +24,26 @@
     y <- Json.required object "y"
     z <- Json.required object "z"
     w <- Json.required object "w"
-    pure Quaternion { x, y, z, w }
+    pure Quaternion {x, y, z, w}
 
 instance Json.ToJSON Quaternion where
-  toJSON a = Json.object
-    [ Json.pair "x" $ x a
-    , Json.pair "y" $ y a
-    , Json.pair "z" $ z a
-    , Json.pair "w" $ w a
-    ]
+  toJSON a =
+    Json.object
+      [ Json.pair "x" $ x a,
+        Json.pair "y" $ y a,
+        Json.pair "z" $ z a,
+        Json.pair "w" $ w a
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "quaternion" $ Schema.object
-  [ (Json.pair "x" $ Schema.ref Schema.number, True)
-  , (Json.pair "y" $ Schema.ref Schema.number, True)
-  , (Json.pair "z" $ Schema.ref Schema.number, True)
-  , (Json.pair "w" $ Schema.ref Schema.number, True)
-  ]
+schema =
+  Schema.named "quaternion" $
+    Schema.object
+      [ (Json.pair "x" $ Schema.ref Schema.number, True),
+        (Json.pair "y" $ Schema.ref Schema.number, True),
+        (Json.pair "z" $ Schema.ref Schema.number, True),
+        (Json.pair "w" $ Schema.ref Schema.number, True)
+      ]
 
 data Component
   = X
@@ -52,12 +55,11 @@
 toQuaternion :: Component -> Double -> Double -> Double -> Quaternion
 toQuaternion component a b c =
   let d = toPart a b c
-  in
-    case component of
-      X -> Quaternion d a b c
-      Y -> Quaternion a d b c
-      Z -> Quaternion a b d c
-      W -> Quaternion a b c d
+   in case component of
+        X -> Quaternion d a b c
+        Y -> Quaternion a d b c
+        Z -> Quaternion a b d c
+        W -> Quaternion a b c d
 
 toPart :: Double -> Double -> Double -> Double
 toPart a b c = sqrt (1 - (a * a) - (b * b) - (c * c))
@@ -82,23 +84,23 @@
 
 maxComponent :: Quaternion -> Component
 maxComponent quaternion =
-  let
-    x_ = x quaternion
-    y_ = y quaternion
-    z_ = z quaternion
-    w_ = w quaternion
-    parts = [(x_, X), (y_, Y), (z_, Z), (w_, W)]
-    biggestPart = maximumOn fst parts
-    roundTrip = decompressPart . compressPart
-    computedPart = Maybe.fromMaybe
-      biggestPart
-      (List.find (\(value, _) -> value /= roundTrip value) parts)
-  in snd
-    (if (biggestPart == computedPart)
-        || (abs (fst biggestPart - fst computedPart) > 0.00001)
-      then biggestPart
-      else computedPart
-    )
+  let x_ = x quaternion
+      y_ = y quaternion
+      z_ = z quaternion
+      w_ = w quaternion
+      parts = [(x_, X), (y_, Y), (z_, Z), (w_, W)]
+      biggestPart = maximumOn fst parts
+      roundTrip = decompressPart . compressPart
+      computedPart =
+        Maybe.fromMaybe
+          biggestPart
+          (List.find (\(value, _) -> value /= roundTrip value) parts)
+   in snd
+        ( if (biggestPart == computedPart)
+            || (abs (fst biggestPart - fst computedPart) > 0.00001)
+            then biggestPart
+            else computedPart
+        )
 
 maximumOn :: (Foldable t, Ord b) => (a -> b) -> t a -> a
 maximumOn f = List.maximumBy (Ord.comparing f)
@@ -118,24 +120,24 @@
 bitPut :: Quaternion -> BitPut.BitPut
 bitPut q =
   let c = maxComponent q
-  in
-    putComponent c <> case c of
-      X -> putParts (y q) (z q) (w q)
-      Y -> putParts (x q) (z q) (w q)
-      Z -> putParts (x q) (y q) (w q)
-      W -> putParts (x q) (y q) (z q)
+   in putComponent c <> case c of
+        X -> putParts (y q) (z q) (w q)
+        Y -> putParts (x q) (z q) (w q)
+        Z -> putParts (x q) (y q) (w q)
+        W -> putParts (x q) (y q) (z q)
 
 putComponent :: Component -> BitPut.BitPut
-putComponent component = CompressedWord.bitPut
-  (CompressedWord.CompressedWord
-    3
-    (case component of
-      X -> 0
-      Y -> 1
-      Z -> 2
-      W -> 3
+putComponent component =
+  CompressedWord.bitPut
+    ( CompressedWord.CompressedWord
+        3
+        ( case component of
+            X -> 0
+            Y -> 1
+            Z -> 2
+            W -> 3
+        )
     )
-  )
 
 putParts :: Double -> Double -> Double -> BitPut.BitPut
 putParts a b c = putPart a <> putPart b <> putPart c
diff --git a/src/lib/Rattletrap/Type/RemoteId.hs b/src/lib/Rattletrap/Type/RemoteId.hs
--- a/src/lib/Rattletrap/Type/RemoteId.hs
+++ b/src/lib/Rattletrap/Type/RemoteId.hs
@@ -21,8 +21,8 @@
   = PlayStation PlayStation.PlayStation
   | PsyNet PsyNet.PsyNet
   | QQ QQ.QQ
-  | Splitscreen Splitscreen.Splitscreen
-  -- ^ Really only 24 bits.
+  | -- | Really only 24 bits.
+    Splitscreen Splitscreen.Splitscreen
   | Steam Steam.Steam
   | Switch Switch.Switch
   | Xbox Xbox.Xbox
@@ -30,16 +30,17 @@
   deriving (Eq, Show)
 
 instance Json.FromJSON RemoteId where
-  parseJSON = Json.withObject "RemoteId" $ \object -> Foldable.asum
-    [ fmap PlayStation $ Json.required object "play_station"
-    , fmap PsyNet $ Json.required object "psy_net"
-    , fmap QQ $ Json.required object "qq"
-    , fmap Splitscreen $ Json.required object "splitscreen"
-    , fmap Steam $ Json.required object "steam"
-    , fmap Switch $ Json.required object "switch"
-    , fmap Xbox $ Json.required object "xbox"
-    , fmap Epic $ Json.required object "epic"
-    ]
+  parseJSON = Json.withObject "RemoteId" $ \object ->
+    Foldable.asum
+      [ fmap PlayStation $ Json.required object "play_station",
+        fmap PsyNet $ Json.required object "psy_net",
+        fmap QQ $ Json.required object "qq",
+        fmap Splitscreen $ Json.required object "splitscreen",
+        fmap Steam $ Json.required object "steam",
+        fmap Switch $ Json.required object "switch",
+        fmap Xbox $ Json.required object "xbox",
+        fmap Epic $ Json.required object "epic"
+      ]
 
 instance Json.ToJSON RemoteId where
   toJSON x = case x of
@@ -53,17 +54,19 @@
     Epic y -> Json.object [Json.pair "epic" y]
 
 schema :: Schema.Schema
-schema = Schema.named "remote-id" . Schema.oneOf $ fmap
-  (\(k, v) -> Schema.object [(Json.pair k v, True)])
-  [ ("play_station", Schema.ref PlayStation.schema)
-  , ("psy_net", Schema.ref PsyNet.schema)
-  , ("qq", Schema.ref QQ.schema)
-  , ("splitscreen", Schema.ref Splitscreen.schema)
-  , ("steam", Schema.ref Steam.schema)
-  , ("switch", Schema.ref Switch.schema)
-  , ("xbox", Schema.ref Xbox.schema)
-  , ("epic", Schema.ref Epic.schema)
-  ]
+schema =
+  Schema.named "remote-id" . Schema.oneOf $
+    fmap
+      (\(k, v) -> Schema.object [(Json.pair k v, True)])
+      [ ("play_station", Schema.ref PlayStation.schema),
+        ("psy_net", Schema.ref PsyNet.schema),
+        ("qq", Schema.ref QQ.schema),
+        ("splitscreen", Schema.ref Splitscreen.schema),
+        ("steam", Schema.ref Steam.schema),
+        ("switch", Schema.ref Switch.schema),
+        ("xbox", Schema.ref Xbox.schema),
+        ("epic", Schema.ref Epic.schema)
+      ]
 
 bitPut :: RemoteId -> BitPut.BitPut
 bitPut remoteId = case remoteId of
diff --git a/src/lib/Rattletrap/Type/RemoteId/PlayStation.hs b/src/lib/Rattletrap/Type/RemoteId/PlayStation.hs
--- a/src/lib/Rattletrap/Type/RemoteId/PlayStation.hs
+++ b/src/lib/Rattletrap/Type/RemoteId/PlayStation.hs
@@ -12,39 +12,41 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data PlayStation = PlayStation
-  { name :: Text.Text
-  , code :: [Word.Word8]
+  { name :: Text.Text,
+    code :: [Word.Word8]
   }
   deriving (Eq, Show)
 
 instance Json.FromJSON PlayStation where
   parseJSON json = do
     (name, code) <- Json.parseJSON json
-    pure PlayStation { name, code }
+    pure PlayStation {name, code}
 
 instance Json.ToJSON PlayStation where
   toJSON x = Json.toJSON (name x, code x)
 
 schema :: Schema.Schema
-schema = Schema.named "remote-id-play-station" $ Schema.tuple
-  [Schema.ref Schema.string, Schema.json $ Schema.array Schema.number]
+schema =
+  Schema.named "remote-id-play-station" $
+    Schema.tuple
+      [Schema.ref Schema.string, Schema.json $ Schema.array Schema.number]
 
 bitPut :: PlayStation -> BitPut.BitPut
 bitPut x =
-  let
-    nameBytes = Bytes.padBytes (16 :: Int) . Bytes.encodeLatin1 $ name x
-    codeBytes = ByteString.pack $ code x
-  in BitPut.byteString nameBytes <> BitPut.byteString codeBytes
+  let nameBytes = Bytes.padBytes (16 :: Int) . Bytes.encodeLatin1 $ name x
+      codeBytes = ByteString.pack $ code x
+   in BitPut.byteString nameBytes <> BitPut.byteString codeBytes
 
 bitGet :: Version.Version -> BitGet.BitGet PlayStation
 bitGet version = BitGet.label "PlayStation" $ do
   name <- BitGet.label "name" getCode
   code <- BitGet.label "code" $ getName version
-  pure PlayStation { name, code }
+  pure PlayStation {name, code}
 
 getCode :: BitGet.BitGet Text.Text
-getCode = fmap (Text.dropWhileEnd (== '\x00') . Text.decodeLatin1)
-  $ BitGet.byteString 16
+getCode =
+  fmap (Text.dropWhileEnd (== '\x00') . Text.decodeLatin1) $
+    BitGet.byteString 16
 
 getName :: Version.Version -> BitGet.BitGet [Word.Word8]
 getName version =
diff --git a/src/lib/Rattletrap/Type/RemoteId/PsyNet.hs b/src/lib/Rattletrap/Type/RemoteId/PsyNet.hs
--- a/src/lib/Rattletrap/Type/RemoteId/PsyNet.hs
+++ b/src/lib/Rattletrap/Type/RemoteId/PsyNet.hs
@@ -15,11 +15,10 @@
 
 instance Json.FromJSON PsyNet where
   parseJSON = Json.withObject "PsyNet" $ \object -> do
-    let
-      new = fmap New $ Json.required object "Left"
-      old = do
-        (a, b, c, d) <- Json.required object "Right"
-        pure $ Old a b c d
+    let new = fmap New $ Json.required object "Left"
+        old = do
+          (a, b, c, d) <- Json.required object "Right"
+          pure $ Old a b c d
     new Applicative.<|> old
 
 instance Json.ToJSON PsyNet where
@@ -28,14 +27,16 @@
     Old a b c d -> Json.object [Json.pair "Right" (a, b, c, d)]
 
 schema :: Schema.Schema
-schema = Schema.named "remote-id-psy-net" $ Schema.oneOf
-  [ Schema.object [(Json.pair "Left" $ Schema.ref U64.schema, True)]
-  , Schema.object
-    [ ( Json.pair "Right" . Schema.tuple . replicate 4 $ Schema.ref U64.schema
-      , True
-      )
-    ]
-  ]
+schema =
+  Schema.named "remote-id-psy-net" $
+    Schema.oneOf
+      [ Schema.object [(Json.pair "Left" $ Schema.ref U64.schema, True)],
+        Schema.object
+          [ ( Json.pair "Right" . Schema.tuple . replicate 4 $ Schema.ref U64.schema,
+              True
+            )
+          ]
+      ]
 
 bitPut :: PsyNet -> BitPut.BitPut
 bitPut x = case x of
@@ -43,11 +44,13 @@
   Old a b c d -> U64.bitPut a <> U64.bitPut b <> U64.bitPut c <> U64.bitPut d
 
 bitGet :: Version.Version -> BitGet.BitGet PsyNet
-bitGet version = BitGet.label "PsyNet" $ if Version.atLeast 868 24 10 version
-  then BitGet.label "New" $ fmap New U64.bitGet
-  else BitGet.label "Old" $ do
-    a <- U64.bitGet
-    b <- U64.bitGet
-    c <- U64.bitGet
-    d <- U64.bitGet
-    pure $ Old a b c d
+bitGet version =
+  BitGet.label "PsyNet" $
+    if Version.atLeast 868 24 10 version
+      then BitGet.label "New" $ fmap New U64.bitGet
+      else BitGet.label "Old" $ do
+        a <- U64.bitGet
+        b <- U64.bitGet
+        c <- U64.bitGet
+        d <- U64.bitGet
+        pure $ Old a b c d
diff --git a/src/lib/Rattletrap/Type/RemoteId/Switch.hs b/src/lib/Rattletrap/Type/RemoteId/Switch.hs
--- a/src/lib/Rattletrap/Type/RemoteId/Switch.hs
+++ b/src/lib/Rattletrap/Type/RemoteId/Switch.hs
@@ -7,25 +7,26 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data Switch = Switch
-  { a :: U64.U64
-  , b :: U64.U64
-  , c :: U64.U64
-  , d :: U64.U64
+  { a :: U64.U64,
+    b :: U64.U64,
+    c :: U64.U64,
+    d :: U64.U64
   }
   deriving (Eq, Show)
 
 instance Json.FromJSON Switch where
   parseJSON json = do
     (a, b, c, d) <- Json.parseJSON json
-    pure Switch { a, b, c, d }
+    pure Switch {a, b, c, d}
 
 instance Json.ToJSON Switch where
   toJSON x = Json.toJSON (a x, b x, c x, d x)
 
 schema :: Schema.Schema
 schema =
-  Schema.named "remote-id-switch" . Schema.tuple . replicate 4 $ Schema.ref
-    U64.schema
+  Schema.named "remote-id-switch" . Schema.tuple . replicate 4 $
+    Schema.ref
+      U64.schema
 
 bitPut :: Switch -> BitPut.BitPut
 bitPut x =
@@ -37,4 +38,4 @@
   b <- U64.bitGet
   c <- U64.bitGet
   d <- U64.bitGet
-  pure Switch { a, b, c, d }
+  pure Switch {a, b, c, d}
diff --git a/src/lib/Rattletrap/Type/Replay.hs b/src/lib/Rattletrap/Type/Replay.hs
--- a/src/lib/Rattletrap/Type/Replay.hs
+++ b/src/lib/Rattletrap/Type/Replay.hs
@@ -18,17 +18,17 @@
 import qualified Rattletrap.Utility.Json as Json
 import qualified Rattletrap.Version as Version
 
-type Replay
-  = ReplayWith
-      (Section.Section Header.Header)
-      (Section.Section Content.Content)
+type Replay =
+  ReplayWith
+    (Section.Section Header.Header)
+    (Section.Section Content.Content)
 
 -- | A Rocket League replay.
 data ReplayWith header content = Replay
-  { header :: header
-  -- ^ This has most of the high-level metadata.
-  , content :: content
-  -- ^ This has most of the low-level game data.
+  { -- | This has most of the high-level metadata.
+    header :: header,
+    -- | This has most of the low-level game data.
+    content :: content
   }
   deriving (Eq, Show)
 
@@ -36,33 +36,38 @@
   parseJSON = Json.withObject "Replay" $ \object -> do
     header <- Json.required object "header"
     content <- Json.required object "content"
-    pure Replay { header, content }
+    pure Replay {header, content}
 
 instance (Json.ToJSON h, Json.ToJSON c) => Json.ToJSON (ReplayWith h c) where
-  toJSON x = Json.object
-    [ Json.pair "$schema" schemaUrl
-    , Json.pair "header" $ header x
-    , Json.pair "content" $ content x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "$schema" schemaUrl,
+        Json.pair "header" $ header x,
+        Json.pair "content" $ content x
+      ]
 
 schema :: Schema.Schema -> Schema.Schema -> Schema.Schema
-schema h c = Schema.named "replay" $ Schema.object
-  [ (Json.pair "header" $ Schema.ref h, True)
-  , (Json.pair "content" $ Schema.ref c, True)
-  ]
+schema h c =
+  Schema.named "replay" $
+    Schema.object
+      [ (Json.pair "header" $ Schema.ref h, True),
+        (Json.pair "content" $ Schema.ref c, True)
+      ]
 
 schemaUrl :: String
-schemaUrl = mconcat
-  [ "https://github.com/tfausak/rattletrap/releases/download/"
-  , Version.string
-  , "/rattletrap-"
-  , Version.string
-  , "-schema.json"
-  ]
+schemaUrl =
+  mconcat
+    [ "https://github.com/tfausak/rattletrap/releases/download/",
+      Version.string,
+      "/rattletrap-",
+      Version.string,
+      "-schema.json"
+    ]
 
 bytePut :: Replay -> BytePut.BytePut
-bytePut x = Section.bytePut Header.bytePut (header x)
-  <> Section.bytePut Content.bytePut (content x)
+bytePut x =
+  Section.bytePut Header.bytePut (header x)
+    <> Section.bytePut Content.bytePut (content x)
 
 byteGet :: Bool -> Bool -> ByteGet.ByteGet Replay
 byteGet fast skip = ByteGet.label "Replay" $ do
@@ -70,28 +75,31 @@
     section <-
       Section.byteGet skip $ ByteGet.byteString . fromIntegral . U32.toWord32
     body <- ByteGet.embed Header.byteGet $ Section.body section
-    pure section { Section.body }
+    pure section {Section.body}
   content <- ByteGet.label "content" $ do
     section <-
       Section.byteGet skip $ ByteGet.byteString . fromIntegral . U32.toWord32
-    body <- if fast
-      then pure Content.empty
-      else ByteGet.embed (getContent $ Section.body header)
-        $ Section.body section
-    pure section { Section.body }
-  pure Replay { header, content }
+    body <-
+      if fast
+        then pure Content.empty
+        else
+          ByteGet.embed (getContent $ Section.body header) $
+            Section.body section
+    pure section {Section.body}
+  pure Replay {header, content}
 
 getContent :: Header.Header -> ByteGet.ByteGet Content.Content
-getContent h = Content.byteGet
-  (getMatchType h)
-  (Header.version h)
-  (getNumFrames h)
-  (getMaxChannels h)
-  (getBuildVersion h)
+getContent h =
+  Content.byteGet
+    (getMatchType h)
+    (Header.version h)
+    (getNumFrames h)
+    (getMaxChannels h)
+    (getBuildVersion h)
 
 getMatchType :: Header.Header -> Maybe Str.Str
 getMatchType header = do
-  Property.Property { Property.value } <-
+  Property.Property {Property.value} <-
     Dictionary.lookup (Str.fromString "MatchType") $ Header.properties header
   case value of
     PropertyValue.Name x -> Just $ Property.Name.toStr x
@@ -99,31 +107,28 @@
 
 getNumFrames :: Header.Header -> Int
 getNumFrames header_ =
-  case
-      Dictionary.lookup
-        (Str.fromString "NumFrames")
-        (Header.properties header_)
-    of
-      Just (Property.Property _ _ (PropertyValue.Int numFrames)) ->
-        fromIntegral (I32.toInt32 (Property.Int.toI32 numFrames))
-      _ -> 0
+  case Dictionary.lookup
+    (Str.fromString "NumFrames")
+    (Header.properties header_) of
+    Just (Property.Property _ _ (PropertyValue.Int numFrames)) ->
+      fromIntegral (I32.toInt32 (Property.Int.toI32 numFrames))
+    _ -> 0
 
 getMaxChannels :: Header.Header -> Word
 getMaxChannels header_ =
-  subtract 1
-    $ case
-        Dictionary.lookup
-          (Str.fromString "MaxChannels")
-          (Header.properties header_)
-      of
-        Just (Property.Property _ _ (PropertyValue.Int maxChannels)) ->
-          fromIntegral (I32.toInt32 (Property.Int.toI32 maxChannels))
-        _ -> 1023
+  subtract 1 $
+    case Dictionary.lookup
+      (Str.fromString "MaxChannels")
+      (Header.properties header_) of
+      Just (Property.Property _ _ (PropertyValue.Int maxChannels)) ->
+        fromIntegral (I32.toInt32 (Property.Int.toI32 maxChannels))
+      _ -> 1023
 
 getBuildVersion :: Header.Header -> Maybe Str.Str
 getBuildVersion header = do
-  property <- Dictionary.lookup (Str.fromString "BuildVersion")
-    $ Header.properties header
+  property <-
+    Dictionary.lookup (Str.fromString "BuildVersion") $
+      Header.properties header
   case Property.value property of
     PropertyValue.Str x -> Just $ Property.Str.toStr x
     _ -> Nothing
diff --git a/src/lib/Rattletrap/Type/Replication.hs b/src/lib/Rattletrap/Type/Replication.hs
--- a/src/lib/Rattletrap/Type/Replication.hs
+++ b/src/lib/Rattletrap/Type/Replication.hs
@@ -14,8 +14,8 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data Replication = Replication
-  { actorId :: CompressedWord.CompressedWord
-  , value :: ReplicationValue.ReplicationValue
+  { actorId :: CompressedWord.CompressedWord,
+    value :: ReplicationValue.ReplicationValue
   }
   deriving (Eq, Show)
 
@@ -23,17 +23,19 @@
   parseJSON = Json.withObject "Replication" $ \object -> do
     actorId <- Json.required object "actor_id"
     value <- Json.required object "value"
-    pure Replication { actorId, value }
+    pure Replication {actorId, value}
 
 instance Json.ToJSON Replication where
   toJSON x =
     Json.object [Json.pair "actor_id" $ actorId x, Json.pair "value" $ value x]
 
 schema :: Schema.Schema
-schema = Schema.named "replication" $ Schema.object
-  [ (Json.pair "actor_id" $ Schema.ref CompressedWord.schema, True)
-  , (Json.pair "value" $ Schema.ref ReplicationValue.schema, True)
-  ]
+schema =
+  Schema.named "replication" $
+    Schema.object
+      [ (Json.pair "actor_id" $ Schema.ref CompressedWord.schema, True),
+        (Json.pair "value" $ Schema.ref ReplicationValue.schema, True)
+      ]
 
 putReplications :: List.List Replication -> BitPut.BitPut
 putReplications xs =
@@ -41,20 +43,21 @@
     <> BitPut.bool False
 
 bitPut :: Replication -> BitPut.BitPut
-bitPut replication = CompressedWord.bitPut (actorId replication)
-  <> ReplicationValue.bitPut (value replication)
+bitPut replication =
+  CompressedWord.bitPut (actorId replication)
+    <> ReplicationValue.bitPut (value replication)
 
-decodeReplicationsBits
-  :: Maybe Str.Str
-  -> Version.Version
-  -> Maybe Str.Str
-  -> Word
-  -> ClassAttributeMap.ClassAttributeMap
-  -> Map.Map CompressedWord.CompressedWord U32.U32
-  -> BitGet.BitGet
-       ( Map.Map CompressedWord.CompressedWord U32.U32
-       , List.List Replication
-       )
+decodeReplicationsBits ::
+  Maybe Str.Str ->
+  Version.Version ->
+  Maybe Str.Str ->
+  Word ->
+  ClassAttributeMap.ClassAttributeMap ->
+  Map.Map CompressedWord.CompressedWord U32.U32 ->
+  BitGet.BitGet
+    ( Map.Map CompressedWord.CompressedWord U32.U32,
+      List.List Replication
+    )
 decodeReplicationsBits matchType version buildVersion limit classes actorMap =
   decodeReplicationsBitsWith
     matchType
@@ -66,58 +69,60 @@
     0
     []
 
-decodeReplicationsBitsWith
-  :: Maybe Str.Str
-  -> Version.Version
-  -> Maybe Str.Str
-  -> Word
-  -> ClassAttributeMap.ClassAttributeMap
-  -> Map.Map CompressedWord.CompressedWord U32.U32
-  -> Int
-  -> [Replication]
-  -> BitGet.BitGet
-       ( Map.Map CompressedWord.CompressedWord U32.U32
-       , List.List Replication
-       )
-decodeReplicationsBitsWith matchType version buildVersion limit classes actorMap index replications
-  = do
+decodeReplicationsBitsWith ::
+  Maybe Str.Str ->
+  Version.Version ->
+  Maybe Str.Str ->
+  Word ->
+  ClassAttributeMap.ClassAttributeMap ->
+  Map.Map CompressedWord.CompressedWord U32.U32 ->
+  Int ->
+  [Replication] ->
+  BitGet.BitGet
+    ( Map.Map CompressedWord.CompressedWord U32.U32,
+      List.List Replication
+    )
+decodeReplicationsBitsWith matchType version buildVersion limit classes actorMap index replications =
+  do
     hasReplication <- BitGet.bool
     if hasReplication
       then do
         (newActorMap, replication) <-
-          BitGet.label ("element (" <> show index <> ")")
-            $ bitGet matchType version buildVersion limit classes actorMap
+          BitGet.label ("element (" <> show index <> ")") $
+            bitGet matchType version buildVersion limit classes actorMap
         decodeReplicationsBitsWith
-            matchType
-            version
-            buildVersion
-            limit
-            classes
-            newActorMap
-            (index + 1)
+          matchType
+          version
+          buildVersion
+          limit
+          classes
+          newActorMap
+          (index + 1)
           $ replication
-          : replications
+            : replications
       else pure (actorMap, List.fromList $ reverse replications)
 
-bitGet
-  :: Maybe Str.Str
-  -> Version.Version
-  -> Maybe Str.Str
-  -> Word
-  -> ClassAttributeMap.ClassAttributeMap
-  -> Map.Map CompressedWord.CompressedWord U32.U32
-  -> BitGet.BitGet
-       ( Map.Map CompressedWord.CompressedWord U32.U32
-       , Replication
-       )
+bitGet ::
+  Maybe Str.Str ->
+  Version.Version ->
+  Maybe Str.Str ->
+  Word ->
+  ClassAttributeMap.ClassAttributeMap ->
+  Map.Map CompressedWord.CompressedWord U32.U32 ->
+  BitGet.BitGet
+    ( Map.Map CompressedWord.CompressedWord U32.U32,
+      Replication
+    )
 bitGet matchType version buildVersion limit classes actorMap =
   BitGet.label "Replication" $ do
     actorId <- BitGet.label "actorId" $ CompressedWord.bitGet limit
-    (newActorMap, value) <- BitGet.label "value" $ ReplicationValue.bitGet
-      matchType
-      version
-      buildVersion
-      classes
-      actorId
-      actorMap
-    pure (newActorMap, Replication { actorId, value })
+    (newActorMap, value) <-
+      BitGet.label "value" $
+        ReplicationValue.bitGet
+          matchType
+          version
+          buildVersion
+          classes
+          actorId
+          actorMap
+    pure (newActorMap, Replication {actorId, value})
diff --git a/src/lib/Rattletrap/Type/Replication/Spawned.hs b/src/lib/Rattletrap/Type/Replication/Spawned.hs
--- a/src/lib/Rattletrap/Type/Replication/Spawned.hs
+++ b/src/lib/Rattletrap/Type/Replication/Spawned.hs
@@ -17,20 +17,20 @@
 import qualified Rattletrap.Utility.Monad as Monad
 
 data Spawned = Spawned
-  { flag :: Bool
-  -- ^ Unclear what this is.
-  , nameIndex :: Maybe U32.U32
-  , name :: Maybe Str.Str
-  -- ^ Read-only! Changing a replication's name requires editing the
-  -- 'nameIndex' and maybe the class attribute map.
-  , objectId :: U32.U32
-  , objectName :: Str.Str
-  -- ^ Read-only! Changing a replication's object requires editing the class
-  -- attribute map.
-  , className :: Str.Str
-  -- ^ Read-only! Changing a replication's class requires editing the class
-  -- attribute map.
-  , initialization :: Initialization.Initialization
+  { -- | Unclear what this is.
+    flag :: Bool,
+    nameIndex :: Maybe U32.U32,
+    -- | Read-only! Changing a replication's name requires editing the
+    -- 'nameIndex' and maybe the class attribute map.
+    name :: Maybe Str.Str,
+    objectId :: U32.U32,
+    -- | Read-only! Changing a replication's object requires editing the class
+    -- attribute map.
+    objectName :: Str.Str,
+    -- | Read-only! Changing a replication's class requires editing the class
+    -- attribute map.
+    className :: Str.Str,
+    initialization :: Initialization.Initialization
   }
   deriving (Eq, Show)
 
@@ -43,37 +43,41 @@
     objectName <- Json.required object "object_name"
     className <- Json.required object "class_name"
     initialization <- Json.required object "initialization"
-    pure Spawned
-      { flag
-      , nameIndex
-      , name
-      , objectId
-      , objectName
-      , className
-      , initialization
-      }
+    pure
+      Spawned
+        { flag,
+          nameIndex,
+          name,
+          objectId,
+          objectName,
+          className,
+          initialization
+        }
 
 instance Json.ToJSON Spawned where
-  toJSON x = Json.object
-    [ Json.pair "flag" $ flag x
-    , Json.pair "name_index" $ nameIndex x
-    , Json.pair "name" $ name x
-    , Json.pair "object_id" $ objectId x
-    , Json.pair "object_name" $ objectName x
-    , Json.pair "class_name" $ className x
-    , Json.pair "initialization" $ initialization x
-    ]
+  toJSON x =
+    Json.object
+      [ Json.pair "flag" $ flag x,
+        Json.pair "name_index" $ nameIndex x,
+        Json.pair "name" $ name x,
+        Json.pair "object_id" $ objectId x,
+        Json.pair "object_name" $ objectName x,
+        Json.pair "class_name" $ className x,
+        Json.pair "initialization" $ initialization x
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "replication-spawned" $ Schema.object
-  [ (Json.pair "flag" $ Schema.ref Schema.boolean, True)
-  , (Json.pair "name_index" . Schema.json $ Schema.maybe U32.schema, False)
-  , (Json.pair "name" . Schema.json $ Schema.maybe Str.schema, False)
-  , (Json.pair "object_id" $ Schema.ref U32.schema, True)
-  , (Json.pair "object_name" $ Schema.ref Str.schema, True)
-  , (Json.pair "class_name" $ Schema.ref Str.schema, True)
-  , (Json.pair "initialization" $ Schema.ref Initialization.schema, True)
-  ]
+schema =
+  Schema.named "replication-spawned" $
+    Schema.object
+      [ (Json.pair "flag" $ Schema.ref Schema.boolean, True),
+        (Json.pair "name_index" . Schema.json $ Schema.maybe U32.schema, False),
+        (Json.pair "name" . Schema.json $ Schema.maybe Str.schema, False),
+        (Json.pair "object_id" $ Schema.ref U32.schema, True),
+        (Json.pair "object_name" $ Schema.ref Str.schema, True),
+        (Json.pair "class_name" $ Schema.ref Str.schema, True),
+        (Json.pair "initialization" $ Schema.ref Initialization.schema, True)
+      ]
 
 bitPut :: Spawned -> BitPut.BitPut
 bitPut spawnedReplication =
@@ -82,78 +86,79 @@
     <> U32.bitPut (objectId spawnedReplication)
     <> Initialization.bitPut (initialization spawnedReplication)
 
-bitGet
-  :: Maybe Str.Str
-  -> Version.Version
-  -> ClassAttributeMap.ClassAttributeMap
-  -> CompressedWord.CompressedWord
-  -> Map.Map CompressedWord.CompressedWord U32.U32
-  -> BitGet.BitGet
-       (Map.Map CompressedWord.CompressedWord U32.U32, Spawned)
+bitGet ::
+  Maybe Str.Str ->
+  Version.Version ->
+  ClassAttributeMap.ClassAttributeMap ->
+  CompressedWord.CompressedWord ->
+  Map.Map CompressedWord.CompressedWord U32.U32 ->
+  BitGet.BitGet
+    (Map.Map CompressedWord.CompressedWord U32.U32, Spawned)
 bitGet matchType version classAttributeMap actorId actorMap =
   BitGet.label "Spawned" $ do
     flag <- BitGet.label "flag" BitGet.bool
-    nameIndex <- BitGet.label "nameIndex"
-      $ Monad.whenMaybe (hasNameIndex matchType version) U32.bitGet
+    nameIndex <-
+      BitGet.label "nameIndex" $
+        Monad.whenMaybe (hasNameIndex matchType version) U32.bitGet
     name <- lookupName classAttributeMap nameIndex
     objectId <- BitGet.label "objectId" U32.bitGet
     objectName <- lookupObjectName classAttributeMap objectId
     className <- lookupClassName objectName
     let hasLocation = ClassAttributeMap.classHasLocation className
     let hasRotation = ClassAttributeMap.classHasRotation className
-    initialization <- BitGet.label "initialization"
-      $ Initialization.bitGet version hasLocation hasRotation
+    initialization <-
+      BitGet.label "initialization" $
+        Initialization.bitGet version hasLocation hasRotation
     pure
-      ( Map.insert actorId objectId actorMap
-      , Spawned
-        { flag
-        , nameIndex
-        , name
-        , objectId
-        , objectName
-        , className
-        , initialization
-        }
+      ( Map.insert actorId objectId actorMap,
+        Spawned
+          { flag,
+            nameIndex,
+            name,
+            objectId,
+            objectName,
+            className,
+            initialization
+          }
       )
 
 hasNameIndex :: Maybe Str.Str -> Version.Version -> Bool
 hasNameIndex matchType version =
   Version.atLeast 868 20 0 version
     || Version.atLeast 868 14 0 version
-    && (matchType /= Just (Str.fromString "Lan"))
+      && (matchType /= Just (Str.fromString "Lan"))
 
-lookupName
-  :: ClassAttributeMap.ClassAttributeMap
-  -> Maybe U32.U32
-  -> BitGet.BitGet (Maybe Str.Str)
+lookupName ::
+  ClassAttributeMap.ClassAttributeMap ->
+  Maybe U32.U32 ->
+  BitGet.BitGet (Maybe Str.Str)
 lookupName classAttributeMap maybeNameIndex = case maybeNameIndex of
   Nothing -> pure Nothing
   Just nameIndex_ ->
-    case
-        ClassAttributeMap.getName
-          (ClassAttributeMap.nameMap classAttributeMap)
-          nameIndex_
-      of
-        Nothing ->
-          BitGet.throw . UnknownName.UnknownName $ U32.toWord32 nameIndex_
-        Just name_ -> pure (Just name_)
+    case ClassAttributeMap.getName
+      (ClassAttributeMap.nameMap classAttributeMap)
+      nameIndex_ of
+      Nothing ->
+        BitGet.throw . UnknownName.UnknownName $ U32.toWord32 nameIndex_
+      Just name_ -> pure (Just name_)
 
-lookupObjectName
-  :: ClassAttributeMap.ClassAttributeMap -> U32.U32 -> BitGet.BitGet Str.Str
+lookupObjectName ::
+  ClassAttributeMap.ClassAttributeMap -> U32.U32 -> BitGet.BitGet Str.Str
 lookupObjectName classAttributeMap objectId_ =
-  case
-      ClassAttributeMap.getObjectName
-        (ClassAttributeMap.objectMap classAttributeMap)
-        objectId_
-    of
-      Nothing ->
-        BitGet.throw . MissingObjectName.MissingObjectName $ U32.toWord32
+  case ClassAttributeMap.getObjectName
+    (ClassAttributeMap.objectMap classAttributeMap)
+    objectId_ of
+    Nothing ->
+      BitGet.throw . MissingObjectName.MissingObjectName $
+        U32.toWord32
           objectId_
-      Just objectName_ -> pure objectName_
+    Just objectName_ -> pure objectName_
 
 lookupClassName :: Str.Str -> BitGet.BitGet Str.Str
 lookupClassName objectName_ =
   case ClassAttributeMap.getClassName objectName_ of
-    Nothing -> BitGet.throw . MissingClassName.MissingClassName $ Str.toString
-      objectName_
+    Nothing ->
+      BitGet.throw . MissingClassName.MissingClassName $
+        Str.toString
+          objectName_
     Just className_ -> pure className_
diff --git a/src/lib/Rattletrap/Type/Replication/Updated.hs b/src/lib/Rattletrap/Type/Replication/Updated.hs
--- a/src/lib/Rattletrap/Type/Replication/Updated.hs
+++ b/src/lib/Rattletrap/Type/Replication/Updated.hs
@@ -16,7 +16,8 @@
 
 newtype Updated = Updated
   { attributes :: List.List Attribute.Attribute
-  } deriving (Eq, Show)
+  }
+  deriving (Eq, Show)
 
 instance Json.FromJSON Updated where
   parseJSON = fmap Updated . Json.parseJSON
@@ -25,25 +26,27 @@
   toJSON = Json.toJSON . attributes
 
 schema :: Schema.Schema
-schema = Schema.named "replication-updated" . Schema.json $ List.schema
-  Attribute.schema
+schema =
+  Schema.named "replication-updated" . Schema.json $
+    List.schema
+      Attribute.schema
 
 bitPut :: Updated -> BitPut.BitPut
 bitPut x =
   foldMap
-      (\y -> BitPut.bool True <> Attribute.bitPut y)
-      (List.toList $ attributes x)
+    (\y -> BitPut.bool True <> Attribute.bitPut y)
+    (List.toList $ attributes x)
     <> BitPut.bool False
 
-bitGet
-  :: Version.Version
-  -> Maybe Str.Str
-  -> ClassAttributeMap.ClassAttributeMap
-  -> Map.Map CompressedWord.CompressedWord U32.U32
-  -> CompressedWord.CompressedWord
-  -> BitGet.BitGet Updated
+bitGet ::
+  Version.Version ->
+  Maybe Str.Str ->
+  ClassAttributeMap.ClassAttributeMap ->
+  Map.Map CompressedWord.CompressedWord U32.U32 ->
+  CompressedWord.CompressedWord ->
+  BitGet.BitGet Updated
 bitGet version buildVersion classes actors actor =
   BitGet.label "Updated" . fmap Updated . List.untilM $ do
     p <- BitGet.bool
-    Monad.whenMaybe p
-      $ Attribute.bitGet version buildVersion classes actors actor
+    Monad.whenMaybe p $
+      Attribute.bitGet version buildVersion classes actors actor
diff --git a/src/lib/Rattletrap/Type/ReplicationValue.hs b/src/lib/Rattletrap/Type/ReplicationValue.hs
--- a/src/lib/Rattletrap/Type/ReplicationValue.hs
+++ b/src/lib/Rattletrap/Type/ReplicationValue.hs
@@ -16,20 +16,21 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data ReplicationValue
-  = Spawned Spawned.Spawned
-  -- ^ Creates a new actor.
-  | Updated Updated.Updated
-  -- ^ Updates an existing actor.
-  | Destroyed Destroyed.Destroyed
-  -- ^ Destroys an existing actor.
+  = -- | Creates a new actor.
+    Spawned Spawned.Spawned
+  | -- | Updates an existing actor.
+    Updated Updated.Updated
+  | -- | Destroys an existing actor.
+    Destroyed Destroyed.Destroyed
   deriving (Eq, Show)
 
 instance Json.FromJSON ReplicationValue where
-  parseJSON = Json.withObject "ReplicationValue" $ \object -> Foldable.asum
-    [ fmap Spawned $ Json.required object "spawned"
-    , fmap Updated $ Json.required object "updated"
-    , fmap Destroyed $ Json.required object "destroyed"
-    ]
+  parseJSON = Json.withObject "ReplicationValue" $ \object ->
+    Foldable.asum
+      [ fmap Spawned $ Json.required object "spawned",
+        fmap Updated $ Json.required object "updated",
+        fmap Destroyed $ Json.required object "destroyed"
+      ]
 
 instance Json.ToJSON ReplicationValue where
   toJSON x = case x of
@@ -38,12 +39,14 @@
     Destroyed y -> Json.object [Json.pair "destroyed" y]
 
 schema :: Schema.Schema
-schema = Schema.named "replicationValue" . Schema.oneOf $ fmap
-  (\(k, v) -> Schema.object [(Json.pair k $ Schema.ref v, True)])
-  [ ("spawned", Spawned.schema)
-  , ("updated", Updated.schema)
-  , ("destroyed", Destroyed.schema)
-  ]
+schema =
+  Schema.named "replicationValue" . Schema.oneOf $
+    fmap
+      (\(k, v) -> Schema.object [(Json.pair k $ Schema.ref v, True)])
+      [ ("spawned", Spawned.schema),
+        ("updated", Updated.schema),
+        ("destroyed", Destroyed.schema)
+      ]
 
 bitPut :: ReplicationValue -> BitPut.BitPut
 bitPut value = case value of
@@ -51,17 +54,17 @@
   Updated x -> BitPut.bool True <> BitPut.bool False <> Updated.bitPut x
   Destroyed x -> BitPut.bool False <> Destroyed.bitPut x
 
-bitGet
-  :: Maybe Str.Str
-  -> Version.Version
-  -> Maybe Str.Str
-  -> ClassAttributeMap.ClassAttributeMap
-  -> CompressedWord.CompressedWord
-  -> Map.Map CompressedWord.CompressedWord U32.U32
-  -> BitGet.BitGet
-       ( Map.Map CompressedWord.CompressedWord U32.U32
-       , ReplicationValue
-       )
+bitGet ::
+  Maybe Str.Str ->
+  Version.Version ->
+  Maybe Str.Str ->
+  ClassAttributeMap.ClassAttributeMap ->
+  CompressedWord.CompressedWord ->
+  Map.Map CompressedWord.CompressedWord U32.U32 ->
+  BitGet.BitGet
+    ( Map.Map CompressedWord.CompressedWord U32.U32,
+      ReplicationValue
+    )
 bitGet matchType version buildVersion classAttributeMap actorId actorMap =
   BitGet.label "ReplicationValue" $ do
     isOpen <- BitGet.bool
@@ -70,20 +73,22 @@
         isNew <- BitGet.bool
         if isNew
           then do
-            (newActorMap, spawned) <- Spawned.bitGet
-              matchType
-              version
-              classAttributeMap
-              actorId
-              actorMap
+            (newActorMap, spawned) <-
+              Spawned.bitGet
+                matchType
+                version
+                classAttributeMap
+                actorId
+                actorMap
             pure (newActorMap, Spawned spawned)
           else do
-            updated <- Updated.bitGet
-              version
-              buildVersion
-              classAttributeMap
-              actorMap
-              actorId
+            updated <-
+              Updated.bitGet
+                version
+                buildVersion
+                classAttributeMap
+                actorMap
+                actorId
             pure (actorMap, Updated updated)
       else do
         destroyed <- Destroyed.bitGet
diff --git a/src/lib/Rattletrap/Type/Rotation.hs b/src/lib/Rattletrap/Type/Rotation.hs
--- a/src/lib/Rattletrap/Type/Rotation.hs
+++ b/src/lib/Rattletrap/Type/Rotation.hs
@@ -15,10 +15,11 @@
   deriving (Eq, Show)
 
 instance Json.FromJSON Rotation where
-  parseJSON = Json.withObject "Rotation" $ \object -> Foldable.asum
-    [ fmap CompressedWordVector $ Json.required object "compressed_word_vector"
-    , fmap Quaternion $ Json.required object "quaternion"
-    ]
+  parseJSON = Json.withObject "Rotation" $ \object ->
+    Foldable.asum
+      [ fmap CompressedWordVector $ Json.required object "compressed_word_vector",
+        fmap Quaternion $ Json.required object "quaternion"
+      ]
 
 instance Json.ToJSON Rotation where
   toJSON x = case x of
@@ -27,11 +28,13 @@
     Quaternion y -> Json.object [Json.pair "quaternion" y]
 
 schema :: Schema.Schema
-schema = Schema.named "rotation" . Schema.oneOf $ fmap
-  (\(k, v) -> Schema.object [(Json.pair k $ Schema.ref v, True)])
-  [ ("compressed_word_vector", CompressedWordVector.schema)
-  , ("quaternion", Quaternion.schema)
-  ]
+schema =
+  Schema.named "rotation" . Schema.oneOf $
+    fmap
+      (\(k, v) -> Schema.object [(Json.pair k $ Schema.ref v, True)])
+      [ ("compressed_word_vector", CompressedWordVector.schema),
+        ("quaternion", Quaternion.schema)
+      ]
 
 bitPut :: Rotation -> BitPut.BitPut
 bitPut r = case r of
@@ -39,6 +42,7 @@
   Quaternion q -> Quaternion.bitPut q
 
 bitGet :: Version.Version -> BitGet.BitGet Rotation
-bitGet version = if Version.atLeast 868 22 7 version
-  then fmap Quaternion Quaternion.bitGet
-  else fmap CompressedWordVector CompressedWordVector.bitGet
+bitGet version =
+  if Version.atLeast 868 22 7 version
+    then fmap Quaternion Quaternion.bitGet
+    else fmap CompressedWordVector CompressedWordVector.bitGet
diff --git a/src/lib/Rattletrap/Type/Section.hs b/src/lib/Rattletrap/Type/Section.hs
--- a/src/lib/Rattletrap/Type/Section.hs
+++ b/src/lib/Rattletrap/Type/Section.hs
@@ -16,81 +16,81 @@
 -- bunch of data (the body). This interface is provided so that you don't have
 -- to think about the size and CRC.
 data Section a = Section
-  { size :: U32.U32
-  -- ^ read only
-  , crc :: U32.U32
-  -- ^ read only
-  , body :: a
-  -- ^ The actual content in the section.
+  { -- | read only
+    size :: U32.U32,
+    -- | read only
+    crc :: U32.U32,
+    -- | The actual content in the section.
+    body :: a
   }
   deriving (Eq, Show)
 
-instance Json.FromJSON a => Json.FromJSON (Section a) where
+instance (Json.FromJSON a) => Json.FromJSON (Section a) where
   parseJSON = Json.withObject "Section" $ \object -> do
     size <- Json.required object "size"
     crc <- Json.required object "crc"
     body <- Json.required object "body"
-    pure Section { size, crc, body }
+    pure Section {size, crc, body}
 
-instance Json.ToJSON a => Json.ToJSON (Section a) where
-  toJSON x = Json.object
-    [ Json.pair "size" $ size x
-    , Json.pair "crc" $ crc x
-    , Json.pair "body" $ body x
-    ]
+instance (Json.ToJSON a) => Json.ToJSON (Section a) where
+  toJSON x =
+    Json.object
+      [ Json.pair "size" $ size x,
+        Json.pair "crc" $ crc x,
+        Json.pair "body" $ body x
+      ]
 
 schema :: Schema.Schema -> Schema.Schema
 schema s =
-  Schema.named ("section-" <> Text.unpack (Schema.name s)) $ Schema.object
-    [ (Json.pair "size" $ Schema.ref U32.schema, True)
-    , (Json.pair "crc" $ Schema.ref U32.schema, True)
-    , (Json.pair "body" $ Schema.ref s, True)
-    ]
+  Schema.named ("section-" <> Text.unpack (Schema.name s)) $
+    Schema.object
+      [ (Json.pair "size" $ Schema.ref U32.schema, True),
+        (Json.pair "crc" $ Schema.ref U32.schema, True),
+        (Json.pair "body" $ Schema.ref s, True)
+      ]
 
 create :: (a -> BytePut.BytePut) -> a -> Section a
 create encode body_ =
   let bytes = BytePut.toByteString $ encode body_
-  in
-    Section
-      { size = U32.fromWord32 . fromIntegral $ ByteString.length bytes
-      , crc = U32.fromWord32 $ Crc.compute bytes
-      , body = body_
-      }
+   in Section
+        { size = U32.fromWord32 . fromIntegral $ ByteString.length bytes,
+          crc = U32.fromWord32 $ Crc.compute bytes,
+          body = body_
+        }
 
 -- | Given a way to put the 'body', puts a section. This will also put
 -- the size and CRC.
 bytePut :: (a -> BytePut.BytePut) -> Section a -> BytePut.BytePut
 bytePut putBody section =
-  let
-    rawBody = BytePut.toByteString . putBody $ body section
-    size_ = ByteString.length rawBody
-    crc_ = Crc.compute rawBody
-  in
-    U32.bytePut (U32.fromWord32 (fromIntegral size_))
-    <> U32.bytePut (U32.fromWord32 crc_)
-    <> BytePut.byteString rawBody
+  let rawBody = BytePut.toByteString . putBody $ body section
+      size_ = ByteString.length rawBody
+      crc_ = Crc.compute rawBody
+   in U32.bytePut (U32.fromWord32 (fromIntegral size_))
+        <> U32.bytePut (U32.fromWord32 crc_)
+        <> BytePut.byteString rawBody
 
-byteGet
-  :: Bool -> (U32.U32 -> ByteGet.ByteGet a) -> ByteGet.ByteGet (Section a)
+byteGet ::
+  Bool -> (U32.U32 -> ByteGet.ByteGet a) -> ByteGet.ByteGet (Section a)
 byteGet skip getBody = ByteGet.label "Section" $ do
   size <- ByteGet.label "size" U32.byteGet
   crc <- ByteGet.label "crc" U32.byteGet
   body <- ByteGet.label "body" $ do
     rawBody <- ByteGet.byteString . fromIntegral $ U32.toWord32 size
     Monad.unless skip $ do
-      let
-        expected = U32.toWord32 crc
-        actual = Crc.compute rawBody
-      Monad.when (actual /= expected) . ByteGet.throw $ CrcMismatch.CrcMismatch
-        expected
-        actual
+      let expected = U32.toWord32 crc
+          actual = Crc.compute rawBody
+      Monad.when (actual /= expected) . ByteGet.throw $
+        CrcMismatch.CrcMismatch
+          expected
+          actual
     ByteGet.embed (getBody size) rawBody
-  pure Section { size, crc, body }
+  pure Section {size, crc, body}
 
 crcMessage :: U32.U32 -> U32.U32 -> String
-crcMessage actual expected = unwords
-  [ "[RT10] actual CRC"
-  , show actual
-  , "does not match expected CRC"
-  , show expected
-  ]
+crcMessage actual expected =
+  unwords
+    [ "[RT10] actual CRC",
+      show actual,
+      "does not match expected CRC",
+      show expected
+    ]
diff --git a/src/lib/Rattletrap/Type/Str.hs b/src/lib/Rattletrap/Type/Str.hs
--- a/src/lib/Rattletrap/Type/Str.hs
+++ b/src/lib/Rattletrap/Type/Str.hs
@@ -42,31 +42,32 @@
 
 bytePut :: Str -> BytePut.BytePut
 bytePut text =
-  let
-    size = getTextSize text
-    encode = getTextEncoder size
-  in I32.bytePut size <> (BytePut.byteString . encode . addNull $ toText text)
+  let size = getTextSize text
+      encode = getTextEncoder size
+   in I32.bytePut size <> (BytePut.byteString . encode . addNull $ toText text)
 
 bitPut :: Str -> BitPut.BitPut
 bitPut = BitPut.fromBytePut . bytePut
 
 getTextSize :: Str -> I32.I32
 getTextSize text =
-  let
-    value = toText text
-    scale = if Text.all Char.isLatin1 value then 1 else -1 :: Int.Int32
-    rawSize = if Text.null value
-      then 0
-      else fromIntegral (Text.length value) + 1 :: Int.Int32
-    size = if value == Text.pack "\x00\x00\x00None"
-      then 0x05000000
-      else scale * rawSize :: Int.Int32
-  in I32.fromInt32 size
+  let value = toText text
+      scale = if Text.all Char.isLatin1 value then 1 else -1 :: Int.Int32
+      rawSize =
+        if Text.null value
+          then 0
+          else fromIntegral (Text.length value) + 1 :: Int.Int32
+      size =
+        if value == Text.pack "\x00\x00\x00None"
+          then 0x05000000
+          else scale * rawSize :: Int.Int32
+   in I32.fromInt32 size
 
 getTextEncoder :: I32.I32 -> Text.Text -> ByteString.ByteString
-getTextEncoder size text = if I32.toInt32 size < 0
-  then Text.encodeUtf16LE text
-  else Bytes.encodeLatin1 text
+getTextEncoder size text =
+  if I32.toInt32 size < 0
+    then Text.encodeUtf16LE text
+    else Bytes.encodeLatin1 text
 
 addNull :: Text.Text -> Text.Text
 addNull text = if Text.null text then text else Text.snoc text '\x00'
@@ -83,18 +84,18 @@
   bytes <- BitGet.byteString (normalizeTextSize rawSize)
   pure (fromText (dropNull (getTextDecoder rawSize bytes)))
 
-normalizeTextSize :: Integral a => I32.I32 -> a
+normalizeTextSize :: (Integral a) => I32.I32 -> a
 normalizeTextSize size = case I32.toInt32 size of
   0x05000000 -> 8
   x -> if x < 0 then (-2 * fromIntegral x) else fromIntegral x
 
 getTextDecoder :: I32.I32 -> ByteString.ByteString -> Text.Text
 getTextDecoder size bytes =
-  let
-    decode = if I32.toInt32 size < 0
-      then Text.decodeUtf16LEWith Text.lenientDecode
-      else Text.decodeLatin1
-  in decode bytes
+  let decode =
+        if I32.toInt32 size < 0
+          then Text.decodeUtf16LEWith Text.lenientDecode
+          else Text.decodeLatin1
+   in decode bytes
 
 dropNull :: Text.Text -> Text.Text
 dropNull = Text.dropWhileEnd (== '\x00')
diff --git a/src/lib/Rattletrap/Type/U32.hs b/src/lib/Rattletrap/Type/U32.hs
--- a/src/lib/Rattletrap/Type/U32.hs
+++ b/src/lib/Rattletrap/Type/U32.hs
@@ -19,11 +19,13 @@
   toJSON = Json.toJSON . toWord32
 
 schema :: Schema.Schema
-schema = Schema.named "u32" $ Json.object
-  [ Json.pair "type" "integer"
-  , Json.pair "minimum" (minBound :: Word.Word32)
-  , Json.pair "maximum" (maxBound :: Word.Word32)
-  ]
+schema =
+  Schema.named "u32" $
+    Json.object
+      [ Json.pair "type" "integer",
+        Json.pair "minimum" (minBound :: Word.Word32),
+        Json.pair "maximum" (maxBound :: Word.Word32)
+      ]
 
 fromWord32 :: Word.Word32 -> U32
 fromWord32 = U32
diff --git a/src/lib/Rattletrap/Type/U64.hs b/src/lib/Rattletrap/Type/U64.hs
--- a/src/lib/Rattletrap/Type/U64.hs
+++ b/src/lib/Rattletrap/Type/U64.hs
@@ -16,17 +16,18 @@
 
 instance Json.FromJSON U64 where
   parseJSON =
-    Json.withText "U64"
-      $ either fail (pure . fromWord64)
-      . Read.readEither
-      . Text.unpack
+    Json.withText "U64" $
+      either fail (pure . fromWord64)
+        . Read.readEither
+        . Text.unpack
 
 instance Json.ToJSON U64 where
   toJSON = Json.toJSON . show . toWord64
 
 schema :: Schema.Schema
-schema = Schema.named "u64"
-  $ Json.object [Json.pair "type" "string", Json.pair "pattern" "^[0-9]+$"]
+schema =
+  Schema.named "u64" $
+    Json.object [Json.pair "type" "string", Json.pair "pattern" "^[0-9]+$"]
 
 fromWord64 :: Word.Word64 -> U64
 fromWord64 = U64
diff --git a/src/lib/Rattletrap/Type/U8.hs b/src/lib/Rattletrap/Type/U8.hs
--- a/src/lib/Rattletrap/Type/U8.hs
+++ b/src/lib/Rattletrap/Type/U8.hs
@@ -19,11 +19,13 @@
   toJSON = Json.toJSON . toWord8
 
 schema :: Schema.Schema
-schema = Schema.named "u8" $ Json.object
-  [ Json.pair "type" "integer"
-  , Json.pair "minimum" (minBound :: Word.Word8)
-  , Json.pair "maximum" (maxBound :: Word.Word8)
-  ]
+schema =
+  Schema.named "u8" $
+    Json.object
+      [ Json.pair "type" "integer",
+        Json.pair "minimum" (minBound :: Word.Word8),
+        Json.pair "maximum" (maxBound :: Word.Word8)
+      ]
 
 fromWord8 :: Word.Word8 -> U8
 fromWord8 = U8
diff --git a/src/lib/Rattletrap/Type/Vector.hs b/src/lib/Rattletrap/Type/Vector.hs
--- a/src/lib/Rattletrap/Type/Vector.hs
+++ b/src/lib/Rattletrap/Type/Vector.hs
@@ -8,18 +8,18 @@
 import qualified Rattletrap.Utility.Json as Json
 
 data Vector = Vector
-  { size :: CompressedWord.CompressedWord
-  , bias :: Word
-  -- ^ This field is guaranteed to be small. In other words, it won't overflow.
-  -- It's stored as a regular 'Word' rather than something more precise like a
-  -- 'Word8' because it just gets passed to a functions that expect 'Word's.
-  -- There's no reason to do a bunch of conversions.
-  , x :: Int
-  -- ^ See 'bias'.
-  , y :: Int
-  -- ^ See 'bias'.
-  , z :: Int
-  -- ^ See 'bias'.
+  { size :: CompressedWord.CompressedWord,
+    -- | This field is guaranteed to be small. In other words, it won't overflow.
+    -- It's stored as a regular 'Word' rather than something more precise like a
+    -- 'Word8' because it just gets passed to a functions that expect 'Word's.
+    -- There's no reason to do a bunch of conversions.
+    bias :: Word,
+    -- | See 'bias'.
+    x :: Int,
+    -- | See 'bias'.
+    y :: Int,
+    -- | See 'bias'.
+    z :: Int
   }
   deriving (Eq, Show)
 
@@ -30,54 +30,54 @@
     x <- Json.required object "x"
     y <- Json.required object "y"
     z <- Json.required object "z"
-    pure Vector { size, bias, x, y, z }
+    pure Vector {size, bias, x, y, z}
 
 instance Json.ToJSON Vector where
-  toJSON a = Json.object
-    [ Json.pair "size" $ size a
-    , Json.pair "bias" $ bias a
-    , Json.pair "x" $ x a
-    , Json.pair "y" $ y a
-    , Json.pair "z" $ z a
-    ]
+  toJSON a =
+    Json.object
+      [ Json.pair "size" $ size a,
+        Json.pair "bias" $ bias a,
+        Json.pair "x" $ x a,
+        Json.pair "y" $ y a,
+        Json.pair "z" $ z a
+      ]
 
 schema :: Schema.Schema
-schema = Schema.named "vector" $ Schema.object
-  [ (Json.pair "size" $ Schema.ref CompressedWord.schema, True)
-  , (Json.pair "bias" $ Schema.ref Schema.integer, True)
-  , (Json.pair "x" $ Schema.ref Schema.integer, True)
-  , (Json.pair "y" $ Schema.ref Schema.integer, True)
-  , (Json.pair "z" $ Schema.ref Schema.integer, True)
-  ]
+schema =
+  Schema.named "vector" $
+    Schema.object
+      [ (Json.pair "size" $ Schema.ref CompressedWord.schema, True),
+        (Json.pair "bias" $ Schema.ref Schema.integer, True),
+        (Json.pair "x" $ Schema.ref Schema.integer, True),
+        (Json.pair "y" $ Schema.ref Schema.integer, True),
+        (Json.pair "z" $ Schema.ref Schema.integer, True)
+      ]
 
 bitPut :: Vector -> BitPut.BitPut
 bitPut vector =
-  let
-    bitSize =
-      round (logBase (2 :: Float) (fromIntegral (bias vector))) - 1 :: Word
-    dx = fromIntegral (x vector + fromIntegral (bias vector)) :: Word
-    dy = fromIntegral (y vector + fromIntegral (bias vector)) :: Word
-    dz = fromIntegral (z vector + fromIntegral (bias vector)) :: Word
-    limit = 2 ^ (bitSize + 2) :: Word
-  in
-    CompressedWord.bitPut (size vector)
-    <> CompressedWord.bitPut (CompressedWord.CompressedWord limit dx)
-    <> CompressedWord.bitPut (CompressedWord.CompressedWord limit dy)
-    <> CompressedWord.bitPut (CompressedWord.CompressedWord limit dz)
+  let bitSize =
+        round (logBase (2 :: Float) (fromIntegral (bias vector))) - 1 :: Word
+      dx = fromIntegral (x vector + fromIntegral (bias vector)) :: Word
+      dy = fromIntegral (y vector + fromIntegral (bias vector)) :: Word
+      dz = fromIntegral (z vector + fromIntegral (bias vector)) :: Word
+      limit = 2 ^ (bitSize + 2) :: Word
+   in CompressedWord.bitPut (size vector)
+        <> CompressedWord.bitPut (CompressedWord.CompressedWord limit dx)
+        <> CompressedWord.bitPut (CompressedWord.CompressedWord limit dy)
+        <> CompressedWord.bitPut (CompressedWord.CompressedWord limit dz)
 
 bitGet :: Version.Version -> BitGet.BitGet Vector
 bitGet version = BitGet.label "Vector" $ do
   size <-
     BitGet.label "size"
-    . CompressedWord.bitGet
-    $ if Version.atLeast 868 22 7 version then 21 else 19
-  let
-    limit = getLimit size
-    bias = getBias size
+      . CompressedWord.bitGet
+      $ if Version.atLeast 868 22 7 version then 21 else 19
+  let limit = getLimit size
+      bias = getBias size
   x <- BitGet.label "x" $ getPart limit bias
   y <- BitGet.label "y" $ getPart limit bias
   z <- BitGet.label "z" $ getPart limit bias
-  pure Vector { size, bias, x, y, z }
+  pure Vector {size, bias, x, y, z}
 
 getPart :: Word -> Word -> BitGet.BitGet Int
 getPart limit bias = fmap (fromDelta bias) (CompressedWord.bitGet limit)
diff --git a/src/lib/Rattletrap/Type/Version.hs b/src/lib/Rattletrap/Type/Version.hs
--- a/src/lib/Rattletrap/Type/Version.hs
+++ b/src/lib/Rattletrap/Type/Version.hs
@@ -6,9 +6,9 @@
 import qualified Rattletrap.Utility.Monad as Monad
 
 data Version = Version
-  { major :: U32.U32
-  , minor :: U32.U32
-  , patch :: Maybe U32.U32
+  { major :: U32.U32,
+    minor :: U32.U32,
+    patch :: Maybe U32.U32
   }
   deriving (Eq, Show)
 
@@ -19,15 +19,20 @@
     && (maybe 0 U32.toWord32 (patch v) >= fromIntegral p)
 
 bytePut :: Version -> BytePut.BytePut
-bytePut x = U32.bytePut (major x) <> U32.bytePut (minor x) <> foldMap
-  U32.bytePut
-  (patch x)
+bytePut x =
+  U32.bytePut (major x)
+    <> U32.bytePut (minor x)
+    <> foldMap
+      U32.bytePut
+      (patch x)
 
 byteGet :: ByteGet.ByteGet Version
 byteGet = ByteGet.label "Version" $ do
   major <- ByteGet.label "major" U32.byteGet
   minor <- ByteGet.label "minor" U32.byteGet
-  patch <- ByteGet.label "patch" $ Monad.whenMaybe
-    (U32.toWord32 major >= 868 && U32.toWord32 minor >= 18)
-    U32.byteGet
-  pure Version { major, minor, patch }
+  patch <-
+    ByteGet.label "patch" $
+      Monad.whenMaybe
+        (U32.toWord32 major >= 868 && U32.toWord32 minor >= 18)
+        U32.byteGet
+  pure Version {major, minor, patch}
diff --git a/src/lib/Rattletrap/Utility/Bytes.hs b/src/lib/Rattletrap/Utility/Bytes.hs
--- a/src/lib/Rattletrap/Utility/Bytes.hs
+++ b/src/lib/Rattletrap/Utility/Bytes.hs
@@ -7,6 +7,7 @@
 encodeLatin1 :: Text.Text -> ByteString.ByteString
 encodeLatin1 text = Latin1.pack (Text.unpack text)
 
-padBytes :: Integral a => a -> ByteString.ByteString -> ByteString.ByteString
-padBytes size bytes = bytes
-  <> ByteString.replicate (fromIntegral size - ByteString.length bytes) 0x00
+padBytes :: (Integral a) => a -> ByteString.ByteString -> ByteString.ByteString
+padBytes size bytes =
+  bytes
+    <> ByteString.replicate (fromIntegral size - ByteString.length bytes) 0x00
diff --git a/src/lib/Rattletrap/Utility/Crc.hs b/src/lib/Rattletrap/Utility/Crc.hs
--- a/src/lib/Rattletrap/Utility/Crc.hs
+++ b/src/lib/Rattletrap/Utility/Crc.hs
@@ -19,11 +19,10 @@
 
 update :: Word.Word32 -> Word.Word8 -> Word.Word32
 update crc byte =
-  let
-    index = Bits.xor byte . unsafeWord32ToWord8 $ Bits.shiftR crc 24
-    left = table Array.! index
-    right = Bits.shiftL crc 8
-  in Bits.xor left right
+  let index = Bits.xor byte . unsafeWord32ToWord8 $ Bits.shiftR crc 24
+      left = table Array.! index
+      right = Bits.shiftL crc 8
+   in Bits.xor left right
 
 unsafeWord32ToWord8 :: Word.Word32 -> Word.Word8
 unsafeWord32ToWord8 = fromIntegral
@@ -32,262 +31,263 @@
 initial = Bits.complement 0xefcbf201
 
 table :: Array.Array Word.Word8 Word.Word32
-table = Array.listArray
-  (0, 255)
-  [ 0x00000000
-  , 0x04c11db7
-  , 0x09823b6e
-  , 0x0d4326d9
-  , 0x130476dc
-  , 0x17c56b6b
-  , 0x1a864db2
-  , 0x1e475005
-  , 0x2608edb8
-  , 0x22c9f00f
-  , 0x2f8ad6d6
-  , 0x2b4bcb61
-  , 0x350c9b64
-  , 0x31cd86d3
-  , 0x3c8ea00a
-  , 0x384fbdbd
-  , 0x4c11db70
-  , 0x48d0c6c7
-  , 0x4593e01e
-  , 0x4152fda9
-  , 0x5f15adac
-  , 0x5bd4b01b
-  , 0x569796c2
-  , 0x52568b75
-  , 0x6a1936c8
-  , 0x6ed82b7f
-  , 0x639b0da6
-  , 0x675a1011
-  , 0x791d4014
-  , 0x7ddc5da3
-  , 0x709f7b7a
-  , 0x745e66cd
-  , 0x9823b6e0
-  , 0x9ce2ab57
-  , 0x91a18d8e
-  , 0x95609039
-  , 0x8b27c03c
-  , 0x8fe6dd8b
-  , 0x82a5fb52
-  , 0x8664e6e5
-  , 0xbe2b5b58
-  , 0xbaea46ef
-  , 0xb7a96036
-  , 0xb3687d81
-  , 0xad2f2d84
-  , 0xa9ee3033
-  , 0xa4ad16ea
-  , 0xa06c0b5d
-  , 0xd4326d90
-  , 0xd0f37027
-  , 0xddb056fe
-  , 0xd9714b49
-  , 0xc7361b4c
-  , 0xc3f706fb
-  , 0xceb42022
-  , 0xca753d95
-  , 0xf23a8028
-  , 0xf6fb9d9f
-  , 0xfbb8bb46
-  , 0xff79a6f1
-  , 0xe13ef6f4
-  , 0xe5ffeb43
-  , 0xe8bccd9a
-  , 0xec7dd02d
-  , 0x34867077
-  , 0x30476dc0
-  , 0x3d044b19
-  , 0x39c556ae
-  , 0x278206ab
-  , 0x23431b1c
-  , 0x2e003dc5
-  , 0x2ac12072
-  , 0x128e9dcf
-  , 0x164f8078
-  , 0x1b0ca6a1
-  , 0x1fcdbb16
-  , 0x018aeb13
-  , 0x054bf6a4
-  , 0x0808d07d
-  , 0x0cc9cdca
-  , 0x7897ab07
-  , 0x7c56b6b0
-  , 0x71159069
-  , 0x75d48dde
-  , 0x6b93dddb
-  , 0x6f52c06c
-  , 0x6211e6b5
-  , 0x66d0fb02
-  , 0x5e9f46bf
-  , 0x5a5e5b08
-  , 0x571d7dd1
-  , 0x53dc6066
-  , 0x4d9b3063
-  , 0x495a2dd4
-  , 0x44190b0d
-  , 0x40d816ba
-  , 0xaca5c697
-  , 0xa864db20
-  , 0xa527fdf9
-  , 0xa1e6e04e
-  , 0xbfa1b04b
-  , 0xbb60adfc
-  , 0xb6238b25
-  , 0xb2e29692
-  , 0x8aad2b2f
-  , 0x8e6c3698
-  , 0x832f1041
-  , 0x87ee0df6
-  , 0x99a95df3
-  , 0x9d684044
-  , 0x902b669d
-  , 0x94ea7b2a
-  , 0xe0b41de7
-  , 0xe4750050
-  , 0xe9362689
-  , 0xedf73b3e
-  , 0xf3b06b3b
-  , 0xf771768c
-  , 0xfa325055
-  , 0xfef34de2
-  , 0xc6bcf05f
-  , 0xc27dede8
-  , 0xcf3ecb31
-  , 0xcbffd686
-  , 0xd5b88683
-  , 0xd1799b34
-  , 0xdc3abded
-  , 0xd8fba05a
-  , 0x690ce0ee
-  , 0x6dcdfd59
-  , 0x608edb80
-  , 0x644fc637
-  , 0x7a089632
-  , 0x7ec98b85
-  , 0x738aad5c
-  , 0x774bb0eb
-  , 0x4f040d56
-  , 0x4bc510e1
-  , 0x46863638
-  , 0x42472b8f
-  , 0x5c007b8a
-  , 0x58c1663d
-  , 0x558240e4
-  , 0x51435d53
-  , 0x251d3b9e
-  , 0x21dc2629
-  , 0x2c9f00f0
-  , 0x285e1d47
-  , 0x36194d42
-  , 0x32d850f5
-  , 0x3f9b762c
-  , 0x3b5a6b9b
-  , 0x0315d626
-  , 0x07d4cb91
-  , 0x0a97ed48
-  , 0x0e56f0ff
-  , 0x1011a0fa
-  , 0x14d0bd4d
-  , 0x19939b94
-  , 0x1d528623
-  , 0xf12f560e
-  , 0xf5ee4bb9
-  , 0xf8ad6d60
-  , 0xfc6c70d7
-  , 0xe22b20d2
-  , 0xe6ea3d65
-  , 0xeba91bbc
-  , 0xef68060b
-  , 0xd727bbb6
-  , 0xd3e6a601
-  , 0xdea580d8
-  , 0xda649d6f
-  , 0xc423cd6a
-  , 0xc0e2d0dd
-  , 0xcda1f604
-  , 0xc960ebb3
-  , 0xbd3e8d7e
-  , 0xb9ff90c9
-  , 0xb4bcb610
-  , 0xb07daba7
-  , 0xae3afba2
-  , 0xaafbe615
-  , 0xa7b8c0cc
-  , 0xa379dd7b
-  , 0x9b3660c6
-  , 0x9ff77d71
-  , 0x92b45ba8
-  , 0x9675461f
-  , 0x8832161a
-  , 0x8cf30bad
-  , 0x81b02d74
-  , 0x857130c3
-  , 0x5d8a9099
-  , 0x594b8d2e
-  , 0x5408abf7
-  , 0x50c9b640
-  , 0x4e8ee645
-  , 0x4a4ffbf2
-  , 0x470cdd2b
-  , 0x43cdc09c
-  , 0x7b827d21
-  , 0x7f436096
-  , 0x7200464f
-  , 0x76c15bf8
-  , 0x68860bfd
-  , 0x6c47164a
-  , 0x61043093
-  , 0x65c52d24
-  , 0x119b4be9
-  , 0x155a565e
-  , 0x18197087
-  , 0x1cd86d30
-  , 0x029f3d35
-  , 0x065e2082
-  , 0x0b1d065b
-  , 0x0fdc1bec
-  , 0x3793a651
-  , 0x3352bbe6
-  , 0x3e119d3f
-  , 0x3ad08088
-  , 0x2497d08d
-  , 0x2056cd3a
-  , 0x2d15ebe3
-  , 0x29d4f654
-  , 0xc5a92679
-  , 0xc1683bce
-  , 0xcc2b1d17
-  , 0xc8ea00a0
-  , 0xd6ad50a5
-  , 0xd26c4d12
-  , 0xdf2f6bcb
-  , 0xdbee767c
-  , 0xe3a1cbc1
-  , 0xe760d676
-  , 0xea23f0af
-  , 0xeee2ed18
-  , 0xf0a5bd1d
-  , 0xf464a0aa
-  , 0xf9278673
-  , 0xfde69bc4
-  , 0x89b8fd09
-  , 0x8d79e0be
-  , 0x803ac667
-  , 0x84fbdbd0
-  , 0x9abc8bd5
-  , 0x9e7d9662
-  , 0x933eb0bb
-  , 0x97ffad0c
-  , 0xafb010b1
-  , 0xab710d06
-  , 0xa6322bdf
-  , 0xa2f33668
-  , 0xbcb4666d
-  , 0xb8757bda
-  , 0xb5365d03
-  , 0xb1f740b4
-  ]
+table =
+  Array.listArray
+    (0, 255)
+    [ 0x00000000,
+      0x04c11db7,
+      0x09823b6e,
+      0x0d4326d9,
+      0x130476dc,
+      0x17c56b6b,
+      0x1a864db2,
+      0x1e475005,
+      0x2608edb8,
+      0x22c9f00f,
+      0x2f8ad6d6,
+      0x2b4bcb61,
+      0x350c9b64,
+      0x31cd86d3,
+      0x3c8ea00a,
+      0x384fbdbd,
+      0x4c11db70,
+      0x48d0c6c7,
+      0x4593e01e,
+      0x4152fda9,
+      0x5f15adac,
+      0x5bd4b01b,
+      0x569796c2,
+      0x52568b75,
+      0x6a1936c8,
+      0x6ed82b7f,
+      0x639b0da6,
+      0x675a1011,
+      0x791d4014,
+      0x7ddc5da3,
+      0x709f7b7a,
+      0x745e66cd,
+      0x9823b6e0,
+      0x9ce2ab57,
+      0x91a18d8e,
+      0x95609039,
+      0x8b27c03c,
+      0x8fe6dd8b,
+      0x82a5fb52,
+      0x8664e6e5,
+      0xbe2b5b58,
+      0xbaea46ef,
+      0xb7a96036,
+      0xb3687d81,
+      0xad2f2d84,
+      0xa9ee3033,
+      0xa4ad16ea,
+      0xa06c0b5d,
+      0xd4326d90,
+      0xd0f37027,
+      0xddb056fe,
+      0xd9714b49,
+      0xc7361b4c,
+      0xc3f706fb,
+      0xceb42022,
+      0xca753d95,
+      0xf23a8028,
+      0xf6fb9d9f,
+      0xfbb8bb46,
+      0xff79a6f1,
+      0xe13ef6f4,
+      0xe5ffeb43,
+      0xe8bccd9a,
+      0xec7dd02d,
+      0x34867077,
+      0x30476dc0,
+      0x3d044b19,
+      0x39c556ae,
+      0x278206ab,
+      0x23431b1c,
+      0x2e003dc5,
+      0x2ac12072,
+      0x128e9dcf,
+      0x164f8078,
+      0x1b0ca6a1,
+      0x1fcdbb16,
+      0x018aeb13,
+      0x054bf6a4,
+      0x0808d07d,
+      0x0cc9cdca,
+      0x7897ab07,
+      0x7c56b6b0,
+      0x71159069,
+      0x75d48dde,
+      0x6b93dddb,
+      0x6f52c06c,
+      0x6211e6b5,
+      0x66d0fb02,
+      0x5e9f46bf,
+      0x5a5e5b08,
+      0x571d7dd1,
+      0x53dc6066,
+      0x4d9b3063,
+      0x495a2dd4,
+      0x44190b0d,
+      0x40d816ba,
+      0xaca5c697,
+      0xa864db20,
+      0xa527fdf9,
+      0xa1e6e04e,
+      0xbfa1b04b,
+      0xbb60adfc,
+      0xb6238b25,
+      0xb2e29692,
+      0x8aad2b2f,
+      0x8e6c3698,
+      0x832f1041,
+      0x87ee0df6,
+      0x99a95df3,
+      0x9d684044,
+      0x902b669d,
+      0x94ea7b2a,
+      0xe0b41de7,
+      0xe4750050,
+      0xe9362689,
+      0xedf73b3e,
+      0xf3b06b3b,
+      0xf771768c,
+      0xfa325055,
+      0xfef34de2,
+      0xc6bcf05f,
+      0xc27dede8,
+      0xcf3ecb31,
+      0xcbffd686,
+      0xd5b88683,
+      0xd1799b34,
+      0xdc3abded,
+      0xd8fba05a,
+      0x690ce0ee,
+      0x6dcdfd59,
+      0x608edb80,
+      0x644fc637,
+      0x7a089632,
+      0x7ec98b85,
+      0x738aad5c,
+      0x774bb0eb,
+      0x4f040d56,
+      0x4bc510e1,
+      0x46863638,
+      0x42472b8f,
+      0x5c007b8a,
+      0x58c1663d,
+      0x558240e4,
+      0x51435d53,
+      0x251d3b9e,
+      0x21dc2629,
+      0x2c9f00f0,
+      0x285e1d47,
+      0x36194d42,
+      0x32d850f5,
+      0x3f9b762c,
+      0x3b5a6b9b,
+      0x0315d626,
+      0x07d4cb91,
+      0x0a97ed48,
+      0x0e56f0ff,
+      0x1011a0fa,
+      0x14d0bd4d,
+      0x19939b94,
+      0x1d528623,
+      0xf12f560e,
+      0xf5ee4bb9,
+      0xf8ad6d60,
+      0xfc6c70d7,
+      0xe22b20d2,
+      0xe6ea3d65,
+      0xeba91bbc,
+      0xef68060b,
+      0xd727bbb6,
+      0xd3e6a601,
+      0xdea580d8,
+      0xda649d6f,
+      0xc423cd6a,
+      0xc0e2d0dd,
+      0xcda1f604,
+      0xc960ebb3,
+      0xbd3e8d7e,
+      0xb9ff90c9,
+      0xb4bcb610,
+      0xb07daba7,
+      0xae3afba2,
+      0xaafbe615,
+      0xa7b8c0cc,
+      0xa379dd7b,
+      0x9b3660c6,
+      0x9ff77d71,
+      0x92b45ba8,
+      0x9675461f,
+      0x8832161a,
+      0x8cf30bad,
+      0x81b02d74,
+      0x857130c3,
+      0x5d8a9099,
+      0x594b8d2e,
+      0x5408abf7,
+      0x50c9b640,
+      0x4e8ee645,
+      0x4a4ffbf2,
+      0x470cdd2b,
+      0x43cdc09c,
+      0x7b827d21,
+      0x7f436096,
+      0x7200464f,
+      0x76c15bf8,
+      0x68860bfd,
+      0x6c47164a,
+      0x61043093,
+      0x65c52d24,
+      0x119b4be9,
+      0x155a565e,
+      0x18197087,
+      0x1cd86d30,
+      0x029f3d35,
+      0x065e2082,
+      0x0b1d065b,
+      0x0fdc1bec,
+      0x3793a651,
+      0x3352bbe6,
+      0x3e119d3f,
+      0x3ad08088,
+      0x2497d08d,
+      0x2056cd3a,
+      0x2d15ebe3,
+      0x29d4f654,
+      0xc5a92679,
+      0xc1683bce,
+      0xcc2b1d17,
+      0xc8ea00a0,
+      0xd6ad50a5,
+      0xd26c4d12,
+      0xdf2f6bcb,
+      0xdbee767c,
+      0xe3a1cbc1,
+      0xe760d676,
+      0xea23f0af,
+      0xeee2ed18,
+      0xf0a5bd1d,
+      0xf464a0aa,
+      0xf9278673,
+      0xfde69bc4,
+      0x89b8fd09,
+      0x8d79e0be,
+      0x803ac667,
+      0x84fbdbd0,
+      0x9abc8bd5,
+      0x9e7d9662,
+      0x933eb0bb,
+      0x97ffad0c,
+      0xafb010b1,
+      0xab710d06,
+      0xa6322bdf,
+      0xa2f33668,
+      0xbcb4666d,
+      0xb8757bda,
+      0xb5365d03,
+      0xb1f740b4
+    ]
diff --git a/src/lib/Rattletrap/Utility/Helper.hs b/src/lib/Rattletrap/Utility/Helper.hs
--- a/src/lib/Rattletrap/Utility/Helper.hs
+++ b/src/lib/Rattletrap/Utility/Helper.hs
@@ -2,6 +2,10 @@
 -- both their binary format and JSON.
 module Rattletrap.Utility.Helper where
 
+import qualified Control.Exception as Exception
+import qualified Data.Bifunctor as Bifunctor
+import qualified Data.ByteString as ByteString
+import qualified Data.ByteString.Lazy as LazyByteString
 import qualified Rattletrap.ByteGet as ByteGet
 import qualified Rattletrap.BytePut as BytePut
 import qualified Rattletrap.Exception.InvalidJson as InvalidJson
@@ -10,17 +14,12 @@
 import qualified Rattletrap.Type.Section as Section
 import qualified Rattletrap.Utility.Json as Json
 
-import qualified Control.Exception as Exception
-import qualified Data.Bifunctor as Bifunctor
-import qualified Data.ByteString as ByteString
-import qualified Data.ByteString.Lazy as LazyByteString
-
 -- | Parses a raw replay.
-decodeReplayFile
-  :: Bool
-  -> Bool
-  -> ByteString.ByteString
-  -> Either ([String], Exception.SomeException) Replay.Replay
+decodeReplayFile ::
+  Bool ->
+  Bool ->
+  ByteString.ByteString ->
+  Either ([String], Exception.SomeException) Replay.Replay
 decodeReplayFile fast = ByteGet.run . Replay.byteGet fast
 
 -- | Encodes a replay as JSON.
@@ -28,9 +27,9 @@
 encodeReplayJson = Json.encodePretty
 
 -- | Parses a JSON replay.
-decodeReplayJson
-  :: ByteString.ByteString
-  -> Either ([String], Exception.SomeException) Replay.Replay
+decodeReplayJson ::
+  ByteString.ByteString ->
+  Either ([String], Exception.SomeException) Replay.Replay
 decodeReplayJson =
   Bifunctor.first ((,) [] . Exception.toException . InvalidJson.InvalidJson)
     . Json.decode
@@ -38,8 +37,10 @@
 -- | Encodes a raw replay.
 encodeReplayFile :: Bool -> Replay.Replay -> LazyByteString.ByteString
 encodeReplayFile fast replay =
-  BytePut.toLazyByteString . Replay.bytePut $ if fast
-    then replay
-      { Replay.content = Section.create Content.bytePut Content.empty
-      }
-    else replay
+  BytePut.toLazyByteString . Replay.bytePut $
+    if fast
+      then
+        replay
+          { Replay.content = Section.create Content.bytePut Content.empty
+          }
+      else replay
diff --git a/src/lib/Rattletrap/Utility/Json.hs b/src/lib/Rattletrap/Utility/Json.hs
--- a/src/lib/Rattletrap/Utility/Json.hs
+++ b/src/lib/Rattletrap/Utility/Json.hs
@@ -1,15 +1,16 @@
 {- hlint ignore "Avoid restricted flags" -}
 module Rattletrap.Utility.Json
-  ( module Rattletrap.Utility.Json
-  , Aeson.FromJSON(parseJSON)
-  , Key.Key
-  , Aeson.ToJSON(toJSON)
-  , Aeson.Value
-  , Aeson.encode
-  , Aeson.object
-  , Aeson.withObject
-  , Aeson.withText
-  ) where
+  ( module Rattletrap.Utility.Json,
+    Aeson.FromJSON (parseJSON),
+    Key.Key,
+    Aeson.ToJSON (toJSON),
+    Aeson.Value,
+    Aeson.encode,
+    Aeson.object,
+    Aeson.withObject,
+    Aeson.withText,
+  )
+where
 
 import qualified Data.Aeson as Aeson
 import qualified Data.Aeson.Encode.Pretty as Aeson
@@ -21,26 +22,28 @@
 keyToString :: Key.Key -> String
 keyToString = Key.toString
 
-required
-  :: Aeson.FromJSON value => Aeson.Object -> String -> Aeson.Parser value
+required ::
+  (Aeson.FromJSON value) => Aeson.Object -> String -> Aeson.Parser value
 required object key = object Aeson..: Key.fromString key
 
-optional
-  :: Aeson.FromJSON value
-  => Aeson.Object
-  -> String
-  -> Aeson.Parser (Maybe value)
+optional ::
+  (Aeson.FromJSON value) =>
+  Aeson.Object ->
+  String ->
+  Aeson.Parser (Maybe value)
 optional object key = object Aeson..:? Key.fromString key
 
 pair :: (Aeson.ToJSON value, Aeson.KeyValue pair) => String -> value -> pair
 pair key value = Key.fromString key Aeson..= value
 
-decode :: Aeson.FromJSON a => ByteString.ByteString -> Either String a
+decode :: (Aeson.FromJSON a) => ByteString.ByteString -> Either String a
 decode = Aeson.eitherDecodeStrict'
 
-encodePretty :: Aeson.ToJSON a => a -> LazyByteString.ByteString
-encodePretty = Aeson.encodePretty' Aeson.defConfig
-  { Aeson.confCompare = compare
-  , Aeson.confIndent = Aeson.Tab
-  , Aeson.confTrailingNewline = True
-  }
+encodePretty :: (Aeson.ToJSON a) => a -> LazyByteString.ByteString
+encodePretty =
+  Aeson.encodePretty'
+    Aeson.defConfig
+      { Aeson.confCompare = compare,
+        Aeson.confIndent = Aeson.Tab,
+        Aeson.confTrailingNewline = True
+      }
diff --git a/src/lib/Rattletrap/Utility/Monad.hs b/src/lib/Rattletrap/Utility/Monad.hs
--- a/src/lib/Rattletrap/Utility/Monad.hs
+++ b/src/lib/Rattletrap/Utility/Monad.hs
@@ -1,4 +1,4 @@
 module Rattletrap.Utility.Monad where
 
-whenMaybe :: Applicative m => Bool -> m a -> m (Maybe a)
+whenMaybe :: (Applicative m) => Bool -> m a -> m (Maybe a)
 whenMaybe p f = if p then fmap Just f else pure Nothing
diff --git a/src/test/Main.hs b/src/test/Main.hs
--- a/src/test/Main.hs
+++ b/src/test/Main.hs
@@ -12,9 +12,10 @@
   mapM_ (testReplay directory) replays
 
 generateSchema :: FilePath -> IO ()
-generateSchema directory = Rattletrap.rattletrap
-  ""
-  ["--schema", "--output", FilePath.combine directory "schema.json"]
+generateSchema directory =
+  Rattletrap.rattletrap
+    ""
+    ["--schema", "--output", FilePath.combine directory "schema.json"]
 
 testReplay :: FilePath -> (FilePath, String) -> IO ()
 testReplay directory (uuid, name) = do
@@ -50,125 +51,125 @@
 
 replays :: [(String, String)]
 replays =
-  [ ("0008", "a flip time") -- https://github.com/tfausak/rattletrap/commit/ee7afa0
-  , ("000b", "nintendo switch") -- https://github.com/tfausak/rattletrap/pull/60
-  , ("0121", "RLCS 2") -- https://github.com/nickbabcock/boxcars/pull/120
-  , ("0416", "v1.78 demolition") -- https://github.com/tfausak/rattletrap/pull/164
-  , ("07e9", "a game mode before Neo Tokyo") -- https://github.com/tfausak/rattletrap/commit/b806f9b
-  , ("0ad2", "some Latin-1 text") -- https://github.com/tfausak/rattletrap/commit/13a8b2d
-  , ("0ca5", "with QQ remote ID") -- https://github.com/nickbabcock/boxcars/pull/69
-  , ("0e76", "v1.95 rumble") -- https://github.com/tfausak/rattletrap/pull/237
-  , ("1205", "rumble mode") -- https://github.com/tfausak/rattletrap/commit/5256500
-  , ("160c", "a dedicated server IP") -- https://github.com/tfausak/rattletrap/commit/5c64a6d
-  , ("16d5", "new property types") -- https://github.com/tfausak/rattletrap/pull/41
-  , ("18d6", "an online loadout attribute") -- https://github.com/tfausak/rattletrap/commit/a9900e7
-  , ("1a12", "overtime") -- https://github.com/tfausak/rattletrap/commit/ada6053
-  , ("1ae4", "a game time") -- https://github.com/tfausak/rattletrap/commit/d08176e
-  , ("1bc2", "no padding after the frames") -- https://github.com/tfausak/rattletrap/commit/c9a2dd8
-  , ("1d1d", "a camera pitch") -- https://github.com/tfausak/rattletrap/commit/ee7afa0
-  , ("1ec9", "a V1.63 match") -- https://github.com/tfausak/rattletrap/pull/132
-  , ("1ef9", "a private hoops match") -- https://github.com/tfausak/rattletrap/commit/5570839
-  , ("1f37", "splitscreen players") -- https://github.com/tfausak/rattletrap/commit/c4d2f32
-  , ("2114", "a match save") -- https://github.com/tfausak/rattletrap/commit/ee7afa0
-  , ("21a8", "v1.66") -- https://github.com/tfausak/rattletrap/pull/142
-  , ("2266", "dropshot") -- https://github.com/tfausak/rattletrap/pull/36
-  , ("22ba", "a vote to forfeit") -- https://github.com/tfausak/rattletrap/commit/86656bb
-  , ("27b6", "some UTF-16 text") -- https://github.com/tfausak/rattletrap/commit/c4d2f32
-  , ("29f5", "frames") -- https://github.com/tfausak/rattletrap/commit/bf4b6af
-  , ("2cf8", "demo v2.01") -- https://github.com/tfausak/rattletrap/pull/243
-  , ("2cfe", "a new playstation id") -- https://github.com/tfausak/rattletrap/issues/51
-  , ("3381", "patch 1.37") -- https://github.com/tfausak/rattletrap/pull/48
-  , ("35f6", "heatseeker v2.01") -- https://github.com/tfausak/rattletrap/commit/57d86c2
-  , ("372d", "a camera yaw attribute") -- https://github.com/tfausak/rattletrap/commit/9c1516c
-  , ("383e", "older unknown content field") -- https://github.com/tfausak/rattletrap/pull/123
-  , ("387f", "a frozen attribute") -- https://github.com/tfausak/rattletrap/commit/93ce196
-  , ("3abd", "rlcs") -- https://github.com/tfausak/rattletrap/pull/86
-  , ("3ea1", "a custom team name") -- https://github.com/tfausak/rattletrap/commit/cf4d145
-  , ("4050", "v2.08 dodge impulse") -- https://github.com/tfausak/rattletrap/issues/247
-  , ("4126", "a game mode after Neo Tokyo") -- https://github.com/tfausak/rattletrap/commit/a1cf21e
-  , ("419a", "a club match") -- https://github.com/tfausak/rattletrap/commit/8e35043
-  , ("42f0", "reservations after Neo Tokyo") -- https://github.com/tfausak/rattletrap/commit/163684f
-  , ("42f2", "anniversary ball") -- https://github.com/tfausak/rattletrap/issues/147
-  , ("43a9", "tutorial") -- https://github.com/nickbabcock/boxcars/pull/70
-  , ("4bc3", "with timed out attribute") -- https://github.com/tfausak/rattletrap/pull/98
-  , ("504e", "some messages") -- https://github.com/tfausak/rattletrap/commit/1d4a538
-  , ("5123", "rep stat title") -- https://github.com/nickbabcock/boxcars/pull/78
-  , ("520e", "no pickup attribute") -- https://github.com/tfausak/rattletrap/pull/38
-  , ("524f", "quat edge case") -- https://github.com/tfausak/rattletrap/pull/87
-  , ("52aa", "a match-ending attribute") -- https://github.com/tfausak/rattletrap/commit/5c64a6d
-  , ("540d", "a demolish attribute") -- https://github.com/tfausak/rattletrap/commit/65ce033
-  , ("54ae", "replicated car scale") -- https://github.com/nickbabcock/boxcars/pull/79
-  , ("551c", "private match settings") -- https://github.com/tfausak/rattletrap/commit/5c9ebfc
-  , ("59d3", "v2.23") -- https://github.com/tfausak/rattletrap/issues/274
-  , ("5a06", "esports items") -- https://github.com/tfausak/rattletrap/pull/114
-  , ("5e0b", "max channels") -- https://github.com/tfausak/rattletrap/issues/254
-  , ("6210", "different player history key") -- https://github.com/tfausak/rattletrap/pull/63
-  , ("6320", "a forfeit attribute") -- https://github.com/tfausak/rattletrap/pull/20
-  , ("6688", "a malformed byte property") -- https://github.com/tfausak/rattletrap/commit/b1ec18b
-  , ("6b0d", "patch 1.37") -- https://github.com/tfausak/rattletrap/pull/48
-  , ("6d1b", "a flip right") -- https://github.com/tfausak/rattletrap/commit/ee7afa0
-  , ("6f7c", "a map with numbers") -- https://github.com/tfausak/rattletrap/commit/2629511
-  , ("7083", "weird basketball capitalization") -- https://github.com/tfausak/rattletrap/pull/63
-  , ("7109", "a boost modifier") -- https://github.com/tfausak/rattletrap/commit/ee7afa0
-  , ("7256", "special edition") -- https://github.com/tfausak/rattletrap/pull/103
-  , ("7588", "another malformed byte property") -- https://github.com/nickbabcock/boxcars/pull/68
-  , ("75ce", "primary and secondary titles") -- https://github.com/tfausak/rattletrap/pull/69
-  , ("79ae", "voice update replay") -- https://github.com/tfausak/rattletrap/pull/265
-  , ("7bf6", "an online loadouts attribute") -- https://github.com/tfausak/rattletrap/commit/89d02f7
-  , ("81d1", "gridiron") -- https://github.com/tfausak/rattletrap/pull/180
-  , ("89cb", "remote user data") -- https://github.com/tfausak/rattletrap/commit/163684f
-  , ("8ae5", "new painted items") -- https://github.com/tfausak/rattletrap/pull/43
-  , ("92a6", "with server performance state") -- https://github.com/tfausak/rattletrap/pull/93
-  , ("946f", "patch 1.43") -- https://github.com/tfausak/rattletrap/pull/69
-  , ("9704", "a batarang") -- https://github.com/tfausak/rattletrap/commit/5958e5c
-  , ("98e5", "a player using behind view") -- https://github.com/tfausak/rattletrap/commit/163684f
-  , ("9a2c", "ghost hunt") -- https://github.com/tfausak/rattletrap/pull/160
-  , ("9e35", "spike rush") -- https://github.com/tfausak/rattletrap/pull/160
-  , ("9eaa", "newer replay without trailing bytes") -- https://github.com/tfausak/rattletrap/pull/126
-  , ("a09e", "a tournament") -- https://github.com/tfausak/rattletrap/pull/69
-  , ("a128", "a round count down") -- https://github.com/tfausak/rattletrap/commit/8bb778d
-  , ("a184", "max score") -- https://github.com/tfausak/rattletrap/pull/158
-  , ("a1c0", "epic system id") -- https://github.com/tfausak/rattletrap/pull/167
-  , ("a52f", "some more mutators") -- https://github.com/tfausak/rattletrap/commit/ee7afa0
-  , ("a558", "extended explosion data") -- https://github.com/tfausak/rattletrap/pull/44
-  , ("a671", "a waiting player") -- https://github.com/tfausak/rattletrap/commit/163684f
-  , ("a676", "new user color") -- https://github.com/tfausak/rattletrap/pull/93
-  , ("a7f0", "a ready attribute") -- https://github.com/tfausak/rattletrap/commit/78af1fd
-  , ("a9df", "salty shores patch 1.45") -- https://github.com/tfausak/rattletrap/pull/78
-  , ("aa70", "patch 1.50 - TitleID attribute") -- https://github.com/tfausak/rattletrap/pull/93
-  , ("ae46", "mvp") -- https://github.com/nickbabcock/boxcars/pull/80
-  , ("afb1", "patch 1.37") -- https://github.com/tfausak/rattletrap/pull/48
-  , ("b9f9", "a party leader") -- https://github.com/tfausak/rattletrap/commit/bba2cfd
-  , ("c14f", "some mutators") -- https://github.com/tfausak/rattletrap/commit/bba2cfd
-  , ("c23b", "new psynet id") -- https://github.com/tfausak/rattletrap/pull/118
-  , ("c62c", "more boolean attributes") -- https://github.com/nickbabcock/boxcars/pull/77
-  , ("c837", "a spectator") -- https://github.com/tfausak/rattletrap/commit/bba2cfd
-  , ("cc4c", "after Starbase ARC") -- https://github.com/tfausak/rattletrap/pull/20
-  , ("d044", "hoops mutators") -- https://github.com/tfausak/rattletrap/pull/34
-  , ("d1d5", "v1.68") -- https://github.com/tfausak/rattletrap/pull/146
-  , ("d236", "rlcs s2") -- https://github.com/tfausak/rattletrap/pull/88
-  , ("d428", "a private hockey match") -- https://github.com/tfausak/rattletrap/commit/4c104b2
-  , ("d44c", "ranked tournament") -- https://github.com/tfausak/rattletrap/pull/167
-  , ("d52e", "psynet system id") -- https://github.com/tfausak/rattletrap/pull/99
-  , ("d5d6", "health max") -- https://github.com/nickbabcock/boxcars/pull/80
-  , ("d7fb", "an explosion attribute") -- https://github.com/tfausak/rattletrap/commit/c554e3e
-  , ("d818", "heatseeker") -- https://github.com/tfausak/rattletrap/pull/160
-  , ("db70", "new lag indicator") -- https://github.com/tfausak/rattletrap/pull/69
-  , ("dcab", "weird ball attribute value") -- https://github.com/tfausak/rattletrap/issues/149
-  , ("dcb3", "a pawn type attribute") -- https://github.com/tfausak/rattletrap/commit/7d7f438
-  , ("dd14", "v1.88") -- https://github.com/tfausak/rattletrap/pull/170
-  , ("de56", "a problematic product attribute") -- https://github.com/tfausak/rattletrap/issues/51
-  , ("e2f9", "bTearOff") -- https://github.com/nickbabcock/boxcars/pull/76
-  , ("e80d", "unlimited time") -- https://github.com/tfausak/rattletrap/pull/76
-  , ("e978", "distracted") -- https://github.com/tfausak/rattletrap/issues/156
-  , ("eae3", "an actor/object ID collision") -- https://github.com/tfausak/rattletrap/commit/d8fad06
-  , ("eae8", "custom team colors") -- https://github.com/tfausak/rattletrap/commit/809240f
-  , ("ecd5", "new match guid attribute") -- https://github.com/tfausak/rattletrap/issues/270
-  , ("edbb", "remote role") -- https://github.com/tfausak/rattletrap/pull/106
-  , ("f08e", "post game lobby") -- https://github.com/jjbott/RocketLeagueReplayParser/issues/46
-  , ("f299", "a location attribute") -- https://github.com/tfausak/rattletrap/commit/21b09c5
-  , ("f7b9", "a hockey game event") -- https://github.com/tfausak/rattletrap/commit/3e16d7f
-  , ("f811", "no frames") -- https://github.com/tfausak/rattletrap/commit/bf4b6af
-  , ("fdc7", "an MVP") -- https://github.com/tfausak/rattletrap/commit/65019d2
-  , ("ffb7", "with difficulty") -- https://github.com/tfausak/rattletrap/pull/167
+  [ ("0008", "a flip time"), -- https://github.com/tfausak/rattletrap/commit/ee7afa0
+    ("000b", "nintendo switch"), -- https://github.com/tfausak/rattletrap/pull/60
+    ("0121", "RLCS 2"), -- https://github.com/nickbabcock/boxcars/pull/120
+    ("0416", "v1.78 demolition"), -- https://github.com/tfausak/rattletrap/pull/164
+    ("07e9", "a game mode before Neo Tokyo"), -- https://github.com/tfausak/rattletrap/commit/b806f9b
+    ("0ad2", "some Latin-1 text"), -- https://github.com/tfausak/rattletrap/commit/13a8b2d
+    ("0ca5", "with QQ remote ID"), -- https://github.com/nickbabcock/boxcars/pull/69
+    ("0e76", "v1.95 rumble"), -- https://github.com/tfausak/rattletrap/pull/237
+    ("1205", "rumble mode"), -- https://github.com/tfausak/rattletrap/commit/5256500
+    ("160c", "a dedicated server IP"), -- https://github.com/tfausak/rattletrap/commit/5c64a6d
+    ("16d5", "new property types"), -- https://github.com/tfausak/rattletrap/pull/41
+    ("18d6", "an online loadout attribute"), -- https://github.com/tfausak/rattletrap/commit/a9900e7
+    ("1a12", "overtime"), -- https://github.com/tfausak/rattletrap/commit/ada6053
+    ("1ae4", "a game time"), -- https://github.com/tfausak/rattletrap/commit/d08176e
+    ("1bc2", "no padding after the frames"), -- https://github.com/tfausak/rattletrap/commit/c9a2dd8
+    ("1d1d", "a camera pitch"), -- https://github.com/tfausak/rattletrap/commit/ee7afa0
+    ("1ec9", "a V1.63 match"), -- https://github.com/tfausak/rattletrap/pull/132
+    ("1ef9", "a private hoops match"), -- https://github.com/tfausak/rattletrap/commit/5570839
+    ("1f37", "splitscreen players"), -- https://github.com/tfausak/rattletrap/commit/c4d2f32
+    ("2114", "a match save"), -- https://github.com/tfausak/rattletrap/commit/ee7afa0
+    ("21a8", "v1.66"), -- https://github.com/tfausak/rattletrap/pull/142
+    ("2266", "dropshot"), -- https://github.com/tfausak/rattletrap/pull/36
+    ("22ba", "a vote to forfeit"), -- https://github.com/tfausak/rattletrap/commit/86656bb
+    ("27b6", "some UTF-16 text"), -- https://github.com/tfausak/rattletrap/commit/c4d2f32
+    ("29f5", "frames"), -- https://github.com/tfausak/rattletrap/commit/bf4b6af
+    ("2cf8", "demo v2.01"), -- https://github.com/tfausak/rattletrap/pull/243
+    ("2cfe", "a new playstation id"), -- https://github.com/tfausak/rattletrap/issues/51
+    ("3381", "patch 1.37"), -- https://github.com/tfausak/rattletrap/pull/48
+    ("35f6", "heatseeker v2.01"), -- https://github.com/tfausak/rattletrap/commit/57d86c2
+    ("372d", "a camera yaw attribute"), -- https://github.com/tfausak/rattletrap/commit/9c1516c
+    ("383e", "older unknown content field"), -- https://github.com/tfausak/rattletrap/pull/123
+    ("387f", "a frozen attribute"), -- https://github.com/tfausak/rattletrap/commit/93ce196
+    ("3abd", "rlcs"), -- https://github.com/tfausak/rattletrap/pull/86
+    ("3ea1", "a custom team name"), -- https://github.com/tfausak/rattletrap/commit/cf4d145
+    ("4050", "v2.08 dodge impulse"), -- https://github.com/tfausak/rattletrap/issues/247
+    ("4126", "a game mode after Neo Tokyo"), -- https://github.com/tfausak/rattletrap/commit/a1cf21e
+    ("419a", "a club match"), -- https://github.com/tfausak/rattletrap/commit/8e35043
+    ("42f0", "reservations after Neo Tokyo"), -- https://github.com/tfausak/rattletrap/commit/163684f
+    ("42f2", "anniversary ball"), -- https://github.com/tfausak/rattletrap/issues/147
+    ("43a9", "tutorial"), -- https://github.com/nickbabcock/boxcars/pull/70
+    ("4bc3", "with timed out attribute"), -- https://github.com/tfausak/rattletrap/pull/98
+    ("504e", "some messages"), -- https://github.com/tfausak/rattletrap/commit/1d4a538
+    ("5123", "rep stat title"), -- https://github.com/nickbabcock/boxcars/pull/78
+    ("520e", "no pickup attribute"), -- https://github.com/tfausak/rattletrap/pull/38
+    ("524f", "quat edge case"), -- https://github.com/tfausak/rattletrap/pull/87
+    ("52aa", "a match-ending attribute"), -- https://github.com/tfausak/rattletrap/commit/5c64a6d
+    ("540d", "a demolish attribute"), -- https://github.com/tfausak/rattletrap/commit/65ce033
+    ("54ae", "replicated car scale"), -- https://github.com/nickbabcock/boxcars/pull/79
+    ("551c", "private match settings"), -- https://github.com/tfausak/rattletrap/commit/5c9ebfc
+    ("59d3", "v2.23"), -- https://github.com/tfausak/rattletrap/issues/274
+    ("5a06", "esports items"), -- https://github.com/tfausak/rattletrap/pull/114
+    ("5e0b", "max channels"), -- https://github.com/tfausak/rattletrap/issues/254
+    ("6210", "different player history key"), -- https://github.com/tfausak/rattletrap/pull/63
+    ("6320", "a forfeit attribute"), -- https://github.com/tfausak/rattletrap/pull/20
+    ("6688", "a malformed byte property"), -- https://github.com/tfausak/rattletrap/commit/b1ec18b
+    ("6b0d", "patch 1.37"), -- https://github.com/tfausak/rattletrap/pull/48
+    ("6d1b", "a flip right"), -- https://github.com/tfausak/rattletrap/commit/ee7afa0
+    ("6f7c", "a map with numbers"), -- https://github.com/tfausak/rattletrap/commit/2629511
+    ("7083", "weird basketball capitalization"), -- https://github.com/tfausak/rattletrap/pull/63
+    ("7109", "a boost modifier"), -- https://github.com/tfausak/rattletrap/commit/ee7afa0
+    ("7256", "special edition"), -- https://github.com/tfausak/rattletrap/pull/103
+    ("7588", "another malformed byte property"), -- https://github.com/nickbabcock/boxcars/pull/68
+    ("75ce", "primary and secondary titles"), -- https://github.com/tfausak/rattletrap/pull/69
+    ("79ae", "voice update replay"), -- https://github.com/tfausak/rattletrap/pull/265
+    ("7bf6", "an online loadouts attribute"), -- https://github.com/tfausak/rattletrap/commit/89d02f7
+    ("81d1", "gridiron"), -- https://github.com/tfausak/rattletrap/pull/180
+    ("89cb", "remote user data"), -- https://github.com/tfausak/rattletrap/commit/163684f
+    ("8ae5", "new painted items"), -- https://github.com/tfausak/rattletrap/pull/43
+    ("92a6", "with server performance state"), -- https://github.com/tfausak/rattletrap/pull/93
+    ("946f", "patch 1.43"), -- https://github.com/tfausak/rattletrap/pull/69
+    ("9704", "a batarang"), -- https://github.com/tfausak/rattletrap/commit/5958e5c
+    ("98e5", "a player using behind view"), -- https://github.com/tfausak/rattletrap/commit/163684f
+    ("9a2c", "ghost hunt"), -- https://github.com/tfausak/rattletrap/pull/160
+    ("9e35", "spike rush"), -- https://github.com/tfausak/rattletrap/pull/160
+    ("9eaa", "newer replay without trailing bytes"), -- https://github.com/tfausak/rattletrap/pull/126
+    ("a09e", "a tournament"), -- https://github.com/tfausak/rattletrap/pull/69
+    ("a128", "a round count down"), -- https://github.com/tfausak/rattletrap/commit/8bb778d
+    ("a184", "max score"), -- https://github.com/tfausak/rattletrap/pull/158
+    ("a1c0", "epic system id"), -- https://github.com/tfausak/rattletrap/pull/167
+    ("a52f", "some more mutators"), -- https://github.com/tfausak/rattletrap/commit/ee7afa0
+    ("a558", "extended explosion data"), -- https://github.com/tfausak/rattletrap/pull/44
+    ("a671", "a waiting player"), -- https://github.com/tfausak/rattletrap/commit/163684f
+    ("a676", "new user color"), -- https://github.com/tfausak/rattletrap/pull/93
+    ("a7f0", "a ready attribute"), -- https://github.com/tfausak/rattletrap/commit/78af1fd
+    ("a9df", "salty shores patch 1.45"), -- https://github.com/tfausak/rattletrap/pull/78
+    ("aa70", "patch 1.50 - TitleID attribute"), -- https://github.com/tfausak/rattletrap/pull/93
+    ("ae46", "mvp"), -- https://github.com/nickbabcock/boxcars/pull/80
+    ("afb1", "patch 1.37"), -- https://github.com/tfausak/rattletrap/pull/48
+    ("b9f9", "a party leader"), -- https://github.com/tfausak/rattletrap/commit/bba2cfd
+    ("c14f", "some mutators"), -- https://github.com/tfausak/rattletrap/commit/bba2cfd
+    ("c23b", "new psynet id"), -- https://github.com/tfausak/rattletrap/pull/118
+    ("c62c", "more boolean attributes"), -- https://github.com/nickbabcock/boxcars/pull/77
+    ("c837", "a spectator"), -- https://github.com/tfausak/rattletrap/commit/bba2cfd
+    ("cc4c", "after Starbase ARC"), -- https://github.com/tfausak/rattletrap/pull/20
+    ("d044", "hoops mutators"), -- https://github.com/tfausak/rattletrap/pull/34
+    ("d1d5", "v1.68"), -- https://github.com/tfausak/rattletrap/pull/146
+    ("d236", "rlcs s2"), -- https://github.com/tfausak/rattletrap/pull/88
+    ("d428", "a private hockey match"), -- https://github.com/tfausak/rattletrap/commit/4c104b2
+    ("d44c", "ranked tournament"), -- https://github.com/tfausak/rattletrap/pull/167
+    ("d52e", "psynet system id"), -- https://github.com/tfausak/rattletrap/pull/99
+    ("d5d6", "health max"), -- https://github.com/nickbabcock/boxcars/pull/80
+    ("d7fb", "an explosion attribute"), -- https://github.com/tfausak/rattletrap/commit/c554e3e
+    ("d818", "heatseeker"), -- https://github.com/tfausak/rattletrap/pull/160
+    ("db70", "new lag indicator"), -- https://github.com/tfausak/rattletrap/pull/69
+    ("dcab", "weird ball attribute value"), -- https://github.com/tfausak/rattletrap/issues/149
+    ("dcb3", "a pawn type attribute"), -- https://github.com/tfausak/rattletrap/commit/7d7f438
+    ("dd14", "v1.88"), -- https://github.com/tfausak/rattletrap/pull/170
+    ("de56", "a problematic product attribute"), -- https://github.com/tfausak/rattletrap/issues/51
+    ("e2f9", "bTearOff"), -- https://github.com/nickbabcock/boxcars/pull/76
+    ("e80d", "unlimited time"), -- https://github.com/tfausak/rattletrap/pull/76
+    ("e978", "distracted"), -- https://github.com/tfausak/rattletrap/issues/156
+    ("eae3", "an actor/object ID collision"), -- https://github.com/tfausak/rattletrap/commit/d8fad06
+    ("eae8", "custom team colors"), -- https://github.com/tfausak/rattletrap/commit/809240f
+    ("ecd5", "new match guid attribute"), -- https://github.com/tfausak/rattletrap/issues/270
+    ("edbb", "remote role"), -- https://github.com/tfausak/rattletrap/pull/106
+    ("f08e", "post game lobby"), -- https://github.com/jjbott/RocketLeagueReplayParser/issues/46
+    ("f299", "a location attribute"), -- https://github.com/tfausak/rattletrap/commit/21b09c5
+    ("f7b9", "a hockey game event"), -- https://github.com/tfausak/rattletrap/commit/3e16d7f
+    ("f811", "no frames"), -- https://github.com/tfausak/rattletrap/commit/bf4b6af
+    ("fdc7", "an MVP"), -- https://github.com/tfausak/rattletrap/commit/65019d2
+    ("ffb7", "with difficulty") -- https://github.com/tfausak/rattletrap/pull/167
   ]
