packages feed

rattletrap 11.2.14 → 12.0.0

raw patch · 15 files changed

+242/−135 lines, 15 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Rattletrap.Type.Attribute.GameServer: New :: Str -> GameServer
+ Rattletrap.Type.Attribute.GameServer: Old :: QWord -> GameServer
+ Rattletrap.Type.Attribute.GameServer: bitGet :: Maybe Str -> BitGet GameServer
+ Rattletrap.Type.Attribute.GameServer: bitPut :: GameServer -> BitPut
+ Rattletrap.Type.Attribute.GameServer: data GameServer
+ Rattletrap.Type.Attribute.GameServer: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.GameServer.GameServer
+ Rattletrap.Type.Attribute.GameServer: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.GameServer.GameServer
+ Rattletrap.Type.Attribute.GameServer: instance GHC.Classes.Eq Rattletrap.Type.Attribute.GameServer.GameServer
+ Rattletrap.Type.Attribute.GameServer: instance GHC.Show.Show Rattletrap.Type.Attribute.GameServer.GameServer
+ Rattletrap.Type.Attribute.GameServer: schema :: Schema
+ Rattletrap.Type.AttributeType: GameServer :: AttributeType
+ Rattletrap.Type.AttributeValue: GameServer :: GameServer -> AttributeValue
+ Rattletrap.Type.Replay: getBuildVersion :: Header -> Maybe Str
- Rattletrap.Type.Attribute: bitGet :: Version -> ClassAttributeMap -> Map CompressedWord U32 -> CompressedWord -> BitGet Attribute
+ Rattletrap.Type.Attribute: bitGet :: Version -> Maybe Str -> ClassAttributeMap -> Map CompressedWord U32 -> CompressedWord -> BitGet Attribute
- Rattletrap.Type.AttributeValue: bitGet :: Version -> Map U32 Str -> Str -> BitGet AttributeValue
+ Rattletrap.Type.AttributeValue: bitGet :: Version -> Maybe Str -> Map U32 Str -> Str -> BitGet AttributeValue
- Rattletrap.Type.Content: byteGet :: Maybe Str -> Version -> Int -> Word -> ByteGet Content
+ Rattletrap.Type.Content: byteGet :: Maybe Str -> Version -> Int -> Word -> Maybe Str -> ByteGet Content
- Rattletrap.Type.Frame: bitGet :: Maybe Str -> Version -> Word -> ClassAttributeMap -> Map CompressedWord U32 -> BitGet (Map CompressedWord U32, Frame)
+ Rattletrap.Type.Frame: bitGet :: Maybe Str -> Version -> Maybe Str -> Word -> ClassAttributeMap -> Map CompressedWord U32 -> BitGet (Map CompressedWord U32, Frame)
- Rattletrap.Type.Frame: decodeFramesBits :: Maybe Str -> Version -> Int -> Word -> ClassAttributeMap -> BitGet (List Frame)
+ Rattletrap.Type.Frame: decodeFramesBits :: Maybe Str -> Version -> Maybe Str -> Int -> Word -> ClassAttributeMap -> BitGet (List Frame)
- Rattletrap.Type.Frame: decodeFramesBitsWith :: Maybe Str -> Version -> Int -> Word -> ClassAttributeMap -> Map CompressedWord U32 -> Int -> [Frame] -> BitGet (Map CompressedWord U32, List Frame)
+ Rattletrap.Type.Frame: decodeFramesBitsWith :: Maybe Str -> Version -> Maybe Str -> Int -> Word -> ClassAttributeMap -> Map CompressedWord U32 -> Int -> [Frame] -> BitGet (Map CompressedWord U32, List Frame)
- Rattletrap.Type.Replication: bitGet :: Maybe Str -> Version -> Word -> ClassAttributeMap -> Map CompressedWord U32 -> BitGet (Map CompressedWord U32, Replication)
+ Rattletrap.Type.Replication: bitGet :: Maybe Str -> Version -> Maybe Str -> Word -> ClassAttributeMap -> Map CompressedWord U32 -> BitGet (Map CompressedWord U32, Replication)
- Rattletrap.Type.Replication: decodeReplicationsBits :: Maybe Str -> Version -> Word -> ClassAttributeMap -> Map CompressedWord U32 -> BitGet (Map CompressedWord U32, List Replication)
+ Rattletrap.Type.Replication: decodeReplicationsBits :: Maybe Str -> Version -> Maybe Str -> Word -> ClassAttributeMap -> Map CompressedWord U32 -> BitGet (Map CompressedWord U32, List Replication)
- Rattletrap.Type.Replication: decodeReplicationsBitsWith :: Maybe Str -> Version -> Word -> ClassAttributeMap -> Map CompressedWord U32 -> Int -> [Replication] -> BitGet (Map CompressedWord U32, List Replication)
+ Rattletrap.Type.Replication: decodeReplicationsBitsWith :: Maybe Str -> Version -> Maybe Str -> Word -> ClassAttributeMap -> Map CompressedWord U32 -> Int -> [Replication] -> BitGet (Map CompressedWord U32, List Replication)
- Rattletrap.Type.Replication.Updated: bitGet :: Version -> ClassAttributeMap -> Map CompressedWord U32 -> CompressedWord -> BitGet Updated
+ Rattletrap.Type.Replication.Updated: bitGet :: Version -> Maybe Str -> ClassAttributeMap -> Map CompressedWord U32 -> CompressedWord -> BitGet Updated
- Rattletrap.Type.ReplicationValue: bitGet :: Maybe Str -> Version -> ClassAttributeMap -> CompressedWord -> Map CompressedWord U32 -> BitGet (Map CompressedWord U32, ReplicationValue)
+ Rattletrap.Type.ReplicationValue: bitGet :: Maybe Str -> Version -> Maybe Str -> ClassAttributeMap -> CompressedWord -> Map CompressedWord U32 -> BitGet (Map CompressedWord U32, ReplicationValue)

Files

README.markdown view
@@ -10,8 +10,8 @@ can be used to modify replays in order to force everyone into the same car or change the map a game was played on. -Rattletrap supports every version of Rocket League up to [2.21][], which was-released on 2022-10-11. If a replay can be played by the Rocket League client,+Rattletrap supports every version of Rocket League up to [2.23][], which was+released on 2022-11-29. If a replay can be played by the Rocket League client, it can be parsed by Rattletrap. (If not, that's a bug. Please report it!)  ## Install@@ -136,7 +136,7 @@ [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.21]: https://www.rocketleague.com/news/patch-notes-v2-21/+[2.23]: https://www.rocketleague.com/news/patch-notes-v2-23/ [Ball Chasing]: https://ballchasing.com [Haskell]: https://www.haskell.org [the latest release]: https://github.com/tfausak/rattletrap/releases/latest
rattletrap.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.2  name: rattletrap-version: 11.2.14+version: 12.0.0 synopsis: Parse and generate Rocket League replays. description: Rattletrap parses and generates Rocket League replays. @@ -114,6 +114,7 @@     Rattletrap.Type.Attribute.FlaggedInt     Rattletrap.Type.Attribute.Float     Rattletrap.Type.Attribute.GameMode+    Rattletrap.Type.Attribute.GameServer     Rattletrap.Type.Attribute.Int     Rattletrap.Type.Attribute.Int64     Rattletrap.Type.Attribute.Loadout
src/lib/Rattletrap/Console/Main.hs view
@@ -29,6 +29,7 @@ import qualified Rattletrap.Type.Attribute.FlaggedInt as Attribute.FlaggedInt import qualified Rattletrap.Type.Attribute.Float as Attribute.Float import qualified Rattletrap.Type.Attribute.GameMode as Attribute.GameMode+import qualified Rattletrap.Type.Attribute.GameServer as Attribute.GameServer import qualified Rattletrap.Type.Attribute.Int as Attribute.Int import qualified Rattletrap.Type.Attribute.Int64 as Attribute.Int64 import qualified Rattletrap.Type.Attribute.Loadout as Attribute.Loadout@@ -181,6 +182,7 @@         , Attribute.FlaggedInt.schema         , Attribute.Float.schema         , Attribute.GameMode.schema+        , Attribute.GameServer.schema         , Attribute.Int.schema         , Attribute.Int64.schema         , Attribute.Loadout.schema
src/lib/Rattletrap/Data.hs view
@@ -273,7 +273,7 @@   , ("Engine.ReplicatedActor_ORS:ReplicatedOwner", AttributeType.FlaggedInt)   , ("Engine.TeamInfo:Score", AttributeType.Int)   , ("ProjectX.GRI_X:bGameStarted", AttributeType.Boolean)-  , ("ProjectX.GRI_X:GameServerID", AttributeType.QWord)+  , ("ProjectX.GRI_X:GameServerID", AttributeType.GameServer)   , ("ProjectX.GRI_X:MatchGuid", AttributeType.String)   , ("ProjectX.GRI_X:MatchGUID", AttributeType.String)   , ("ProjectX.GRI_X:ReplicatedGameMutatorIndex", AttributeType.Int)
src/lib/Rattletrap/Type/Attribute.hs view
@@ -54,20 +54,23 @@  bitGet   :: Version.Version+  -> Maybe Str.Str   -> ClassAttributeMap.ClassAttributeMap   -> Map.Map CompressedWord.CompressedWord U32.U32   -> CompressedWord.CompressedWord   -> BitGet.BitGet Attribute-bitGet version 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-    (ClassAttributeMap.objectMap classes)-    name-  pure Attribute { id, name, value }+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 }  lookupAttributeMap   :: ClassAttributeMap.ClassAttributeMap
+ src/lib/Rattletrap/Type/Attribute/GameServer.hs view
@@ -0,0 +1,40 @@+module Rattletrap.Type.Attribute.GameServer where++import qualified Data.Foldable as Foldable+import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.Attribute.QWord as QWord+import qualified Rattletrap.Type.Str as Str+import qualified Rattletrap.Utility.Json as Json++data GameServer+  = Old QWord.QWord+  | New Str.Str+  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"]++instance Json.ToJSON GameServer where+  toJSON x = case x of+    Old y -> Json.object [Json.pair "old" $ Json.toJSON y]+    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)]++bitPut :: GameServer -> BitPut.BitPut+bitPut x = case x of+  Old y -> QWord.bitPut y+  New y -> Str.bitPut y++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
src/lib/Rattletrap/Type/AttributeType.hs view
@@ -16,6 +16,7 @@   | FlaggedByte   | Float   | GameMode+  | GameServer   | Int   | Int64   | Loadout
src/lib/Rattletrap/Type/AttributeValue.hs view
@@ -22,6 +22,7 @@ import qualified Rattletrap.Type.Attribute.FlaggedInt as FlaggedInt import qualified Rattletrap.Type.Attribute.Float as Float import qualified Rattletrap.Type.Attribute.GameMode as GameMode+import qualified Rattletrap.Type.Attribute.GameServer as GameServer import qualified Rattletrap.Type.Attribute.Int as Int import qualified Rattletrap.Type.Attribute.Int64 as Int64 import qualified Rattletrap.Type.Attribute.Loadout as Loadout@@ -69,6 +70,7 @@   | FlaggedByte FlaggedByte.FlaggedByte   | Float Float.Float   | GameMode GameMode.GameMode+  | GameServer GameServer.GameServer   | Int Int.Int   | Int64 Int64.Int64   | Loadout Loadout.Loadout@@ -113,6 +115,7 @@     , 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"@@ -157,6 +160,7 @@     FlaggedInt y -> Json.object [Json.pair "flagged_int" y]     Float y -> Json.object [Json.pair "float" y]     GameMode y -> Json.object [Json.pair "game_mode" y]+    GameServer y -> Json.object [Json.pair "game_server" y]     Int y -> Json.object [Json.pair "int" y]     Int64 y -> Json.object [Json.pair "int64" y]     Loadout y -> Json.object [Json.pair "loadout" y]@@ -202,6 +206,7 @@   , ("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)@@ -246,6 +251,7 @@   FlaggedByte x -> FlaggedByte.bitPut x   Float x -> Float.bitPut x   GameMode x -> GameMode.bitPut x+  GameServer x -> GameServer.bitPut x   Int x -> Int.bitPut x   Int64 x -> Int64.putInt64Attribute x   Loadout x -> Loadout.bitPut x@@ -274,60 +280,68 @@  bitGet   :: Version.Version+  -> Maybe Str.Str   -> Map.Map U32.U32 Str.Str   -> Str.Str   -> BitGet.BitGet AttributeValue-bitGet version objectMap name = BitGet.label "AttributeValue" $ do-  constructor <- case Map.lookup (Str.toText name) Data.attributeTypes of-    Nothing ->-      BitGet.throw . UnknownAttribute.UnknownAttribute $ Str.toString name-    Just x -> pure x-  case constructor of-    AttributeType.AppliedDamage ->-      fmap AppliedDamage $ AppliedDamage.bitGet version-    AttributeType.Boolean -> fmap Boolean Boolean.bitGet-    AttributeType.Byte -> fmap Byte Byte.bitGet-    AttributeType.CamSettings -> fmap CamSettings $ CamSettings.bitGet version-    AttributeType.ClubColors -> fmap ClubColors ClubColors.bitGet-    AttributeType.CustomDemolish ->-      fmap CustomDemolish $ CustomDemolish.bitGet version-    AttributeType.DamageState -> fmap DamageState $ DamageState.bitGet version-    AttributeType.Demolish -> fmap Demolish $ Demolish.bitGet version-    AttributeType.Enum -> fmap Enum Enum.bitGet-    AttributeType.Explosion -> fmap Explosion $ Explosion.bitGet version-    AttributeType.ExtendedExplosion ->-      fmap ExtendedExplosion $ ExtendedExplosion.bitGet version-    AttributeType.FlaggedInt -> fmap FlaggedInt FlaggedInt.bitGet-    AttributeType.FlaggedByte -> fmap FlaggedByte FlaggedByte.bitGet-    AttributeType.Float -> fmap Float Float.bitGet-    AttributeType.GameMode -> fmap GameMode $ GameMode.bitGet version-    AttributeType.Int -> fmap Int Int.bitGet-    AttributeType.Int64 -> fmap Int64 Int64.bitGet-    AttributeType.Loadout -> fmap Loadout Loadout.bitGet-    AttributeType.LoadoutOnline ->-      fmap LoadoutOnline $ LoadoutOnline.bitGet version objectMap-    AttributeType.Loadouts -> fmap Loadouts Loadouts.bitGet-    AttributeType.LoadoutsOnline ->-      fmap LoadoutsOnline $ LoadoutsOnline.bitGet version objectMap-    AttributeType.Location -> fmap Location $ Location.bitGet version-    AttributeType.MusicStinger -> fmap MusicStinger MusicStinger.bitGet-    AttributeType.PartyLeader -> fmap PartyLeader $ PartyLeader.bitGet version-    AttributeType.Pickup -> fmap Pickup Pickup.bitGet-    AttributeType.PickupInfo -> fmap PickupInfo PickupInfo.bitGet-    AttributeType.PickupNew -> fmap PickupNew PickupNew.bitGet-    AttributeType.PlayerHistoryKey ->-      fmap PlayerHistoryKey PlayerHistoryKey.bitGet-    AttributeType.PrivateMatchSettings ->-      fmap PrivateMatchSettings PrivateMatchSettings.bitGet-    AttributeType.QWord -> fmap QWord QWord.bitGet-    AttributeType.RepStatTitle -> fmap RepStatTitle RepStatTitle.bitGet-    AttributeType.Reservation -> fmap Reservation $ Reservation.bitGet version-    AttributeType.RigidBodyState ->-      fmap RigidBodyState $ RigidBodyState.bitGet version-    AttributeType.Rotation -> fmap Rotation Rotation.bitGet-    AttributeType.StatEvent -> fmap StatEvent StatEvent.bitGet-    AttributeType.String -> fmap String String.bitGet-    AttributeType.TeamPaint -> fmap TeamPaint TeamPaint.bitGet-    AttributeType.Title -> fmap Title Title.bitGet-    AttributeType.UniqueId -> fmap UniqueId $ UniqueId.bitGet version-    AttributeType.WeldedInfo -> fmap WeldedInfo $ WeldedInfo.bitGet version+bitGet version buildVersion objectMap name =+  BitGet.label "AttributeValue" $ do+    constructor <- case Map.lookup (Str.toText name) Data.attributeTypes of+      Nothing ->+        BitGet.throw . UnknownAttribute.UnknownAttribute $ Str.toString name+      Just x -> pure x+    case constructor of+      AttributeType.AppliedDamage ->+        fmap AppliedDamage $ AppliedDamage.bitGet version+      AttributeType.Boolean -> fmap Boolean Boolean.bitGet+      AttributeType.Byte -> fmap Byte Byte.bitGet+      AttributeType.CamSettings ->+        fmap CamSettings $ CamSettings.bitGet version+      AttributeType.ClubColors -> fmap ClubColors ClubColors.bitGet+      AttributeType.CustomDemolish ->+        fmap CustomDemolish $ CustomDemolish.bitGet version+      AttributeType.DamageState ->+        fmap DamageState $ DamageState.bitGet version+      AttributeType.Demolish -> fmap Demolish $ Demolish.bitGet version+      AttributeType.Enum -> fmap Enum Enum.bitGet+      AttributeType.Explosion -> fmap Explosion $ Explosion.bitGet version+      AttributeType.ExtendedExplosion ->+        fmap ExtendedExplosion $ ExtendedExplosion.bitGet version+      AttributeType.FlaggedInt -> fmap FlaggedInt FlaggedInt.bitGet+      AttributeType.FlaggedByte -> fmap FlaggedByte FlaggedByte.bitGet+      AttributeType.Float -> fmap Float Float.bitGet+      AttributeType.GameMode -> fmap GameMode $ GameMode.bitGet version+      AttributeType.GameServer ->+        fmap GameServer $ GameServer.bitGet buildVersion+      AttributeType.Int -> fmap Int Int.bitGet+      AttributeType.Int64 -> fmap Int64 Int64.bitGet+      AttributeType.Loadout -> fmap Loadout Loadout.bitGet+      AttributeType.LoadoutOnline ->+        fmap LoadoutOnline $ LoadoutOnline.bitGet version objectMap+      AttributeType.Loadouts -> fmap Loadouts Loadouts.bitGet+      AttributeType.LoadoutsOnline ->+        fmap LoadoutsOnline $ LoadoutsOnline.bitGet version objectMap+      AttributeType.Location -> fmap Location $ Location.bitGet version+      AttributeType.MusicStinger -> fmap MusicStinger MusicStinger.bitGet+      AttributeType.PartyLeader ->+        fmap PartyLeader $ PartyLeader.bitGet version+      AttributeType.Pickup -> fmap Pickup Pickup.bitGet+      AttributeType.PickupInfo -> fmap PickupInfo PickupInfo.bitGet+      AttributeType.PickupNew -> fmap PickupNew PickupNew.bitGet+      AttributeType.PlayerHistoryKey ->+        fmap PlayerHistoryKey PlayerHistoryKey.bitGet+      AttributeType.PrivateMatchSettings ->+        fmap PrivateMatchSettings PrivateMatchSettings.bitGet+      AttributeType.QWord -> fmap QWord QWord.bitGet+      AttributeType.RepStatTitle -> fmap RepStatTitle RepStatTitle.bitGet+      AttributeType.Reservation ->+        fmap Reservation $ Reservation.bitGet version+      AttributeType.RigidBodyState ->+        fmap RigidBodyState $ RigidBodyState.bitGet version+      AttributeType.Rotation -> fmap Rotation Rotation.bitGet+      AttributeType.StatEvent -> fmap StatEvent StatEvent.bitGet+      AttributeType.String -> fmap String String.bitGet+      AttributeType.TeamPaint -> fmap TeamPaint TeamPaint.bitGet+      AttributeType.Title -> fmap Title Title.bitGet+      AttributeType.UniqueId -> fmap UniqueId $ UniqueId.bitGet version+      AttributeType.WeldedInfo -> fmap WeldedInfo $ WeldedInfo.bitGet version
src/lib/Rattletrap/Type/Content.hs view
@@ -188,45 +188,49 @@   -> Word   -- ^ The maximum number of channels in the stream, usually from   -- 'Rattletrap.Header.getMaxChannels'.+  -> Maybe Str.Str+  -- ^ 'Rattletrap.Header.getBuildVersion'   -> ByteGet.ByteGet Content-byteGet matchType version numFrames maxChannels = 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-  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-  caches <- ByteGet.label "caches" $ List.byteGet Cache.byteGet-  let-    classAttributeMap =-      ClassAttributeMap.make objects classMappings caches names-    getFrames = BitGet.toByteGet $ Frame.decodeFramesBits-      matchType-      version-      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-    }+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+    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+    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+    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+      }
src/lib/Rattletrap/Type/Frame.hs view
@@ -59,14 +59,16 @@ decodeFramesBits   :: Maybe Str.Str   -> Version.Version+  -> Maybe Str.Str   -> Int   -> Word   -> ClassAttributeMap.ClassAttributeMap   -> BitGet.BitGet (List.List Frame)-decodeFramesBits matchType version count limit classes =+decodeFramesBits matchType version buildVersion count limit classes =   fmap snd $ decodeFramesBitsWith     matchType     version+    buildVersion     count     limit     classes@@ -77,6 +79,7 @@ decodeFramesBitsWith   :: Maybe Str.Str   -> Version.Version+  -> Maybe Str.Str   -> Int   -> Word   -> ClassAttributeMap.ClassAttributeMap@@ -84,19 +87,22 @@   -> Int   -> [Frame]   -> BitGet.BitGet-       ( Map.Map CompressedWord.CompressedWord U32.U32+       ( Map.Map+           CompressedWord.CompressedWord+           U32.U32        , List.List Frame        )-decodeFramesBitsWith matchType version count limit classes actorMap index frames+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 limit classes actorMap+          $ bitGet matchType version buildVersion limit classes actorMap       decodeFramesBitsWith           matchType           version+          buildVersion           count           limit           classes@@ -108,19 +114,22 @@ 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 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-      limit-      classes-      actorMap-  pure (newActorMap, Frame { time, delta, replications })+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 })
src/lib/Rattletrap/Type/Replay.hs view
@@ -10,6 +10,7 @@ import qualified Rattletrap.Type.Property as Property import qualified Rattletrap.Type.Property.Int as Property.Int import qualified Rattletrap.Type.Property.Name as Property.Name+import qualified Rattletrap.Type.Property.Str as Property.Str import qualified Rattletrap.Type.PropertyValue as PropertyValue import qualified Rattletrap.Type.Section as Section import qualified Rattletrap.Type.Str as Str@@ -86,6 +87,7 @@   (Header.version h)   (getNumFrames h)   (getMaxChannels h)+  (getBuildVersion h)  getMatchType :: Header.Header -> Maybe Str.Str getMatchType header = do@@ -117,3 +119,11 @@         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+  case Property.value property of+    PropertyValue.Str x -> Just $ Property.Str.toStr x+    _ -> Nothing
src/lib/Rattletrap/Type/Replication.hs view
@@ -47,6 +47,7 @@ decodeReplicationsBits   :: Maybe Str.Str   -> Version.Version+  -> Maybe Str.Str   -> Word   -> ClassAttributeMap.ClassAttributeMap   -> Map.Map CompressedWord.CompressedWord U32.U32@@ -54,12 +55,21 @@        ( Map.Map CompressedWord.CompressedWord U32.U32        , List.List Replication        )-decodeReplicationsBits matchType version limit classes actorMap =-  decodeReplicationsBitsWith matchType version limit classes actorMap 0 []+decodeReplicationsBits matchType version buildVersion limit classes actorMap =+  decodeReplicationsBitsWith+    matchType+    version+    buildVersion+    limit+    classes+    actorMap+    0+    []  decodeReplicationsBitsWith   :: Maybe Str.Str   -> Version.Version+  -> Maybe Str.Str   -> Word   -> ClassAttributeMap.ClassAttributeMap   -> Map.Map CompressedWord.CompressedWord U32.U32@@ -69,17 +79,18 @@        ( Map.Map CompressedWord.CompressedWord U32.U32        , List.List Replication        )-decodeReplicationsBitsWith matchType version limit classes actorMap index replications+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 limit classes actorMap+            $ bitGet matchType version buildVersion limit classes actorMap         decodeReplicationsBitsWith             matchType             version+            buildVersion             limit             classes             newActorMap@@ -91,6 +102,7 @@ bitGet   :: Maybe Str.Str   -> Version.Version+  -> Maybe Str.Str   -> Word   -> ClassAttributeMap.ClassAttributeMap   -> Map.Map CompressedWord.CompressedWord U32.U32@@ -98,9 +110,14 @@        ( Map.Map CompressedWord.CompressedWord U32.U32        , Replication        )-bitGet matchType version limit classes actorMap =+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 classes actorId actorMap+    (newActorMap, value) <- BitGet.label "value" $ ReplicationValue.bitGet+      matchType+      version+      buildVersion+      classes+      actorId+      actorMap     pure (newActorMap, Replication { actorId, value })
src/lib/Rattletrap/Type/Replication/Updated.hs view
@@ -8,6 +8,7 @@ import qualified Rattletrap.Type.ClassAttributeMap as ClassAttributeMap import qualified Rattletrap.Type.CompressedWord as CompressedWord import qualified Rattletrap.Type.List as List+import qualified Rattletrap.Type.Str as Str import qualified Rattletrap.Type.U32 as U32 import qualified Rattletrap.Type.Version as Version import qualified Rattletrap.Utility.Json as Json@@ -36,11 +37,13 @@  bitGet   :: Version.Version+  -> Maybe Str.Str   -> ClassAttributeMap.ClassAttributeMap   -> Map.Map CompressedWord.CompressedWord U32.U32   -> CompressedWord.CompressedWord   -> BitGet.BitGet Updated-bitGet version classes actors actor =+bitGet version buildVersion classes actors actor =   BitGet.label "Updated" . fmap Updated . List.untilM $ do     p <- BitGet.bool-    Monad.whenMaybe p $ Attribute.bitGet version classes actors actor+    Monad.whenMaybe p+      $ Attribute.bitGet version buildVersion classes actors actor
src/lib/Rattletrap/Type/ReplicationValue.hs view
@@ -54,6 +54,7 @@ bitGet   :: Maybe Str.Str   -> Version.Version+  -> Maybe Str.Str   -> ClassAttributeMap.ClassAttributeMap   -> CompressedWord.CompressedWord   -> Map.Map CompressedWord.CompressedWord U32.U32@@ -61,7 +62,7 @@        ( Map.Map CompressedWord.CompressedWord U32.U32        , ReplicationValue        )-bitGet matchType version classAttributeMap actorId actorMap =+bitGet matchType version buildVersion classAttributeMap actorId actorMap =   BitGet.label "ReplicationValue" $ do     isOpen <- BitGet.bool     if isOpen@@ -79,6 +80,7 @@           else do             updated <- Updated.bitGet               version+              buildVersion               classAttributeMap               actorMap               actorId
src/test/Main.hs view
@@ -99,6 +99,7 @@   , ("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