rattletrap 12.1.3 → 13.0.1
raw patch · 19 files changed
+221/−154 lines, 19 filesdep ~containersPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: containers
API changes (from Hackage documentation)
+ Rattletrap.Type.Attribute.Boost: Boost :: U8 -> U8 -> U8 -> U8 -> Boost
+ Rattletrap.Type.Attribute.Boost: [boostAmount] :: Boost -> U8
+ Rattletrap.Type.Attribute.Boost: [grantCount] :: Boost -> U8
+ Rattletrap.Type.Attribute.Boost: [unused1] :: Boost -> U8
+ Rattletrap.Type.Attribute.Boost: [unused2] :: Boost -> U8
+ Rattletrap.Type.Attribute.Boost: bitGet :: BitGet Boost
+ Rattletrap.Type.Attribute.Boost: bitPut :: Boost -> BitPut
+ Rattletrap.Type.Attribute.Boost: data Boost
+ Rattletrap.Type.Attribute.Boost: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.Boost.Boost
+ Rattletrap.Type.Attribute.Boost: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.Boost.Boost
+ Rattletrap.Type.Attribute.Boost: instance GHC.Classes.Eq Rattletrap.Type.Attribute.Boost.Boost
+ Rattletrap.Type.Attribute.Boost: instance GHC.Show.Show Rattletrap.Type.Attribute.Boost.Boost
+ Rattletrap.Type.Attribute.Boost: schema :: Schema
+ Rattletrap.Type.AttributeType: Boost :: AttributeType
+ Rattletrap.Type.AttributeValue: Boost :: Boost -> AttributeValue
- Rattletrap.Utility.Json: class FromJSON a
+ Rattletrap.Utility.Json: class () => FromJSON a
- Rattletrap.Utility.Json: class ToJSON a
+ Rattletrap.Utility.Json: class () => ToJSON a
- Rattletrap.Utility.Json: data Key
+ Rattletrap.Utility.Json: data () => Key
- Rattletrap.Utility.Json: data Value
+ Rattletrap.Utility.Json: data () => Value
- Rattletrap.Utility.Json: pair :: (ToJSON value, KeyValue p) => String -> value -> p
+ Rattletrap.Utility.Json: pair :: (ToJSON value, KeyValue e p) => String -> value -> p
Files
- LICENSE.markdown +1/−1
- README.markdown +7/−15
- rattletrap.cabal +26/−20
- src/lib/Rattletrap/Console/Main.hs +5/−3
- src/lib/Rattletrap/Data.hs +1/−0
- src/lib/Rattletrap/Type/Attribute/Boost.hs +57/−0
- src/lib/Rattletrap/Type/Attribute/LoadoutOnline.hs +6/−6
- src/lib/Rattletrap/Type/Attribute/Product.hs +5/−5
- src/lib/Rattletrap/Type/AttributeType.hs +1/−0
- src/lib/Rattletrap/Type/AttributeValue.hs +7/−0
- src/lib/Rattletrap/Type/Cache.hs +5/−5
- src/lib/Rattletrap/Type/ClassAttributeMap.hs +16/−16
- src/lib/Rattletrap/Type/Content.hs +48/−48
- src/lib/Rattletrap/Type/Dictionary.hs +9/−9
- src/lib/Rattletrap/Type/Frame.hs +8/−8
- src/lib/Rattletrap/Type/Property/Array.hs +7/−7
- src/lib/Rattletrap/Type/Replication.hs +6/−6
- src/lib/Rattletrap/Type/Replication/Updated.hs +5/−5
- src/test/Main.hs +1/−0
LICENSE.markdown view
@@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Taylor Fausak+Copyright (c) 2024 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
README.markdown view
@@ -1,7 +1,7 @@-# [Rattletrap][]+# [Rattletrap](https://github.com/tfausak/rattletrap) [](https://github.com/tfausak/rattletrap/actions/workflows/workflow.yaml)-[](https://hackage.haskell.org/package/rattletrap)+[](https://hackage.haskell.org/package/rattletrap) [](https://www.stackage.org/package/rattletrap) Rattletrap parses and generates [Rocket League][] replays. Parsing replays can@@ -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.23][], which was-released on 2022-11-29. If a replay can be played by the Rocket League client,+Rattletrap supports every version of Rocket League up to [2.38][], which was+released on 2024-04-16. 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@@ -23,10 +23,8 @@ The best way to get Rattletrap is by downloading [the latest release][] for your platform. -Rattletrap is written in [Haskell][]. To build Rattletrap from source, install-[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:+Rattletrap is written in [Haskell][]. If you'd like to use a program written in+a different language, consider one of the following: - <https://github.com/jjbott/RocketLeagueReplayParser> (C#) - <https://github.com/nickbabcock/rrrocket> (Rust)@@ -129,13 +127,7 @@ ``` [Rattletrap]: https://github.com/tfausak/rattletrap-[Version badge]: https://img.shields.io/hackage/v/rattletrap.svg?logo=haskell-[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 [Rocket League]: https://www.rocketleague.com-[2.23]: https://www.rocketleague.com/news/patch-notes-v2-23/+[2.38]: https://www.rocketleague.com/en/news/patch-notes-v2-38 [Ball Chasing]: https://ballchasing.com-[Haskell]: https://www.haskell.org [the latest release]: https://github.com/tfausak/rattletrap/releases/latest-[Stack]: https://docs.haskellstack.org/en/stable/README/
rattletrap.cabal view
@@ -1,13 +1,14 @@ cabal-version: 2.2- name: rattletrap-version: 12.1.3+version: 13.0.1 synopsis: Parse and generate Rocket League replays. description: Rattletrap parses and generates Rocket League replays.- build-type: Simple category: Game-extra-source-files: CHANGELOG.markdown README.markdown+extra-source-files:+ CHANGELOG.markdown+ README.markdown+ license-file: LICENSE.markdown license: MIT maintainer: Taylor Fausak@@ -22,7 +23,7 @@ manual: True common library- build-depends: base >= 4.16 && < 4.20+ build-depends: base >=4.16 && <4.20 default-extensions: NamedFieldPuns default-language: Haskell2010 ghc-options:@@ -48,26 +49,28 @@ common executable import: library- build-depends: rattletrap- ghc-options: -rtsopts -threaded+ ghc-options:+ -rtsopts+ -threaded library import: library- autogen-modules: Paths_rattletrap build-depends:- , aeson >= 2.0.3 && < 2.3- , aeson-pretty >= 0.8.9 && < 0.9- , array >= 0.5.4 && < 0.6- , bytestring >= 0.11.3 && < 0.13- , containers >= 0.6.5 && < 0.7- , filepath >= 1.4.2 && < 1.5- , http-client >= 0.7.13 && < 0.8- , http-client-tls >= 0.3.6 && < 0.4- , text >= 1.2.5 && < 1.3 || >= 2.0 && < 2.2+ aeson >=2.0.3 && <2.3,+ aeson-pretty >=0.8.9 && <0.9,+ array >=0.5.4 && <0.6,+ bytestring >=0.11.3 && <0.13,+ containers >=0.6.5 && <0.8,+ filepath >=1.4.2 && <1.5,+ http-client >=0.7.13 && <0.8,+ http-client-tls >=0.3.6 && <0.4,+ text >=1.2.5 && <1.3 || >=2.0 && <2.2,++ exposed-modules: Paths_rattletrap+ -- cabal-gild: discover src/lib exposed-modules:- Paths_rattletrap Rattletrap Rattletrap.BitBuilder Rattletrap.BitGet@@ -103,6 +106,7 @@ Rattletrap.Type.Attribute Rattletrap.Type.Attribute.AppliedDamage Rattletrap.Type.Attribute.Boolean+ Rattletrap.Type.Attribute.Boost Rattletrap.Type.Attribute.Byte Rattletrap.Type.Attribute.CamSettings Rattletrap.Type.Attribute.ClubColors@@ -206,18 +210,20 @@ Rattletrap.Utility.Json Rattletrap.Utility.Monad Rattletrap.Version+ hs-source-dirs: src/lib executable rattletrap import: executable- hs-source-dirs: src/exe main-is: Main.hs test-suite rattletrap-test-suite import: executable+ build-depends:+ bytestring,+ filepath, - build-depends: bytestring, filepath hs-source-dirs: src/test main-is: Main.hs type: exitcode-stdio-1.0
src/lib/Rattletrap/Console/Main.hs view
@@ -16,6 +16,7 @@ import qualified Rattletrap.Type.Attribute as Attribute import qualified Rattletrap.Type.Attribute.AppliedDamage as Attribute.AppliedDamage import qualified Rattletrap.Type.Attribute.Boolean as Attribute.Boolean+import qualified Rattletrap.Type.Attribute.Boost as Attribute.Boost import qualified Rattletrap.Type.Attribute.Byte as Attribute.Byte import qualified Rattletrap.Type.Attribute.CamSettings as Attribute.CamSettings import qualified Rattletrap.Type.Attribute.ClubColors as Attribute.ClubColors@@ -74,7 +75,7 @@ import qualified Rattletrap.Type.Initialization as Initialization import qualified Rattletrap.Type.Int8Vector as Int8Vector import qualified Rattletrap.Type.Keyframe as Keyframe-import qualified Rattletrap.Type.List as List+import qualified Rattletrap.Type.List as RList import qualified Rattletrap.Type.Mark as Mark import qualified Rattletrap.Type.Message as Message import qualified Rattletrap.Type.Property as Property@@ -162,7 +163,7 @@ schema :: Json.Value schema =- let contentSchema = Content.schema $ List.schema Frame.schema+ let contentSchema = Content.schema $ RList.schema Frame.schema in Json.object [ Json.pair "$schema" "http://json-schema.org/draft-07/schema", Json.pair "$id" Replay.schemaUrl,@@ -173,6 +174,7 @@ [ Attribute.schema, Attribute.AppliedDamage.schema, Attribute.Boolean.schema,+ Attribute.Boost.schema, Attribute.Byte.schema, Attribute.CamSettings.schema, Attribute.ClubColors.schema,@@ -231,7 +233,7 @@ Initialization.schema, Int8Vector.schema, Keyframe.schema,- List.schema Attribute.Product.schema,+ RList.schema Attribute.Product.schema, Mark.schema, Message.schema, Property.schema,
src/lib/Rattletrap/Data.hs view
@@ -337,6 +337,7 @@ ("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:ReplicatedBoost", AttributeType.Boost), ("TAGame.CarComponent_Boost_TA:ReplicatedBoostAmount", AttributeType.Byte), ("TAGame.CarComponent_Boost_TA:UnlimitedBoostRefCount", AttributeType.Int), ("TAGame.CarComponent_Dodge_TA:DodgeImpulse", AttributeType.Location),
+ src/lib/Rattletrap/Type/Attribute/Boost.hs view
@@ -0,0 +1,57 @@+module Rattletrap.Type.Attribute.Boost where++import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.U8 as U8+import qualified Rattletrap.Utility.Json as Json++data Boost = Boost+ { grantCount :: U8.U8,+ boostAmount :: U8.U8,+ unused1 :: U8.U8,+ unused2 :: U8.U8+ }+ deriving (Eq, Show)++instance Json.FromJSON Boost where+ parseJSON = Json.withObject "Boost" $ \object -> do+ grantCount <- Json.required object "grantCount"+ boostAmount <- Json.required object "boostAmount"+ unused1 <- Json.required object "unused1"+ unused2 <- Json.required object "unused2"+ pure Boost {grantCount, boostAmount, unused1, unused2}++instance Json.ToJSON Boost where+ toJSON x =+ Json.object+ [ Json.pair "grantCount" $ grantCount x,+ Json.pair "boostAmount" $ boostAmount x,+ Json.pair "unused1" $ unused1 x,+ Json.pair "unused2" $ unused2 x+ ]++schema :: Schema.Schema+schema =+ Schema.named "boost" $+ Schema.object+ [ (Json.pair "grantCount" $ Schema.ref U8.schema, True),+ (Json.pair "boostAmount" $ Schema.ref U8.schema, True),+ (Json.pair "unused1" $ Schema.ref U8.schema, True),+ (Json.pair "unused2" $ Schema.ref U8.schema, True)+ ]++bitPut :: Boost -> BitPut.BitPut+bitPut appliedDamageAttribute =+ U8.bitPut (grantCount appliedDamageAttribute)+ <> U8.bitPut (boostAmount appliedDamageAttribute)+ <> U8.bitPut (unused1 appliedDamageAttribute)+ <> U8.bitPut (unused2 appliedDamageAttribute)++bitGet :: BitGet.BitGet Boost+bitGet = BitGet.label "Boost" $ do+ grantCount <- BitGet.label "grantCount" U8.bitGet+ boostAmount <- BitGet.label "boostAmount" U8.bitGet+ unused1 <- BitGet.label "unused1" U8.bitGet+ unused2 <- BitGet.label "unused2" U8.bitGet+ pure Boost {grantCount, boostAmount, unused1, unused2}
src/lib/Rattletrap/Type/Attribute/LoadoutOnline.hs view
@@ -5,7 +5,7 @@ import qualified Rattletrap.BitPut as BitPut import qualified Rattletrap.Schema as Schema import qualified Rattletrap.Type.Attribute.Product as Product-import qualified Rattletrap.Type.List as List+import qualified Rattletrap.Type.List as RList import qualified Rattletrap.Type.Str as Str import qualified Rattletrap.Type.U32 as U32 import qualified Rattletrap.Type.U8 as U8@@ -13,7 +13,7 @@ import qualified Rattletrap.Utility.Json as Json newtype LoadoutOnline = LoadoutOnline- { value :: List.List (List.List Product.Product)+ { value :: RList.List (RList.List Product.Product) } deriving (Eq, Show) @@ -27,12 +27,12 @@ schema = Schema.named "attribute-loadout-online" . Schema.json- . List.schema- $ List.schema Product.schema+ . RList.schema+ $ RList.schema Product.schema bitPut :: LoadoutOnline -> BitPut.BitPut bitPut loadoutAttribute =- let attributes = List.toList $ value loadoutAttribute+ let attributes = RList.toList $ value loadoutAttribute in (U8.bitPut . U8.fromWord8 . fromIntegral $ length attributes) <> foldMap Product.putProductAttributes attributes @@ -42,6 +42,6 @@ size <- BitGet.label "size" U8.bitGet value <- BitGet.label "value"- . List.replicateM (fromIntegral $ U8.toWord8 size)+ . RList.replicateM (fromIntegral $ U8.toWord8 size) $ Product.decodeProductAttributesBits version objectMap pure LoadoutOnline {value}
src/lib/Rattletrap/Type/Attribute/Product.hs view
@@ -5,7 +5,7 @@ import qualified Rattletrap.BitPut as BitPut import qualified Rattletrap.Schema as Schema import qualified Rattletrap.Type.Attribute.ProductValue as ProductValue-import qualified Rattletrap.Type.List as List+import qualified Rattletrap.Type.List as RList import qualified Rattletrap.Type.Str as Str import qualified Rattletrap.Type.U32 as U32 import qualified Rattletrap.Type.U8 as U8@@ -48,9 +48,9 @@ (Json.pair "value" $ Schema.ref ProductValue.schema, True) ] -putProductAttributes :: List.List Product -> BitPut.BitPut+putProductAttributes :: RList.List Product -> BitPut.BitPut putProductAttributes attributes =- let v = List.toList attributes+ let v = RList.toList attributes in (U8.bitPut . U8.fromWord8 . fromIntegral $ length v) <> foldMap bitPut v bitPut :: Product -> BitPut.BitPut@@ -62,10 +62,10 @@ decodeProductAttributesBits :: Version.Version -> Map.Map U32.U32 Str.Str ->- BitGet.BitGet (List.List Product)+ BitGet.BitGet (RList.List Product) decodeProductAttributesBits version objectMap = do size <- U8.bitGet- List.replicateM (fromIntegral $ U8.toWord8 size) $ bitGet version objectMap+ RList.replicateM (fromIntegral $ U8.toWord8 size) $ bitGet version objectMap bitGet :: Version.Version -> Map.Map U32.U32 Str.Str -> BitGet.BitGet Product bitGet version objectMap = BitGet.label "Product" $ do
src/lib/Rattletrap/Type/AttributeType.hs view
@@ -3,6 +3,7 @@ data AttributeType = AppliedDamage | Boolean+ | Boost | Byte | CamSettings | ClubColors
src/lib/Rattletrap/Type/AttributeValue.hs view
@@ -9,6 +9,7 @@ import qualified Rattletrap.Schema as Schema import qualified Rattletrap.Type.Attribute.AppliedDamage as AppliedDamage import qualified Rattletrap.Type.Attribute.Boolean as Boolean+import qualified Rattletrap.Type.Attribute.Boost as Boost import qualified Rattletrap.Type.Attribute.Byte as Byte import qualified Rattletrap.Type.Attribute.CamSettings as CamSettings import qualified Rattletrap.Type.Attribute.ClubColors as ClubColors@@ -57,6 +58,7 @@ data AttributeValue = AppliedDamage AppliedDamage.AppliedDamage | Boolean Boolean.Boolean+ | Boost Boost.Boost | Byte Byte.Byte | CamSettings CamSettings.CamSettings | ClubColors ClubColors.ClubColors@@ -103,6 +105,7 @@ Foldable.asum [ fmap AppliedDamage $ Json.required object "applied_damage", fmap Boolean $ Json.required object "boolean",+ fmap Boost $ Json.required object "boost", fmap Byte $ Json.required object "byte", fmap CamSettings $ Json.required object "cam_settings", fmap ClubColors $ Json.required object "club_colors",@@ -148,6 +151,7 @@ toJSON x = case x of AppliedDamage y -> Json.object [Json.pair "applied_damage" y] Boolean y -> Json.object [Json.pair "boolean" y]+ Boost y -> Json.object [Json.pair "boost" y] Byte y -> Json.object [Json.pair "byte" y] CamSettings y -> Json.object [Json.pair "cam_settings" y] ClubColors y -> Json.object [Json.pair "club_colors" y]@@ -196,6 +200,7 @@ (\(k, v) -> Schema.object [(Json.pair k $ Schema.ref v, True)]) [ ("applied_damage", AppliedDamage.schema), ("boolean", Boolean.schema),+ ("boost", Boost.schema), ("byte", Byte.schema), ("cam_settings", CamSettings.schema), ("club_colors", ClubColors.schema),@@ -241,6 +246,7 @@ bitPut value = case value of AppliedDamage x -> AppliedDamage.bitPut x Boolean x -> Boolean.bitPut x+ Boost x -> Boost.bitPut x Byte x -> Byte.bitPut x CamSettings x -> CamSettings.bitPut x ClubColors x -> ClubColors.bitPut x@@ -297,6 +303,7 @@ AttributeType.AppliedDamage -> fmap AppliedDamage $ AppliedDamage.bitGet version AttributeType.Boolean -> fmap Boolean Boolean.bitGet+ AttributeType.Boost -> fmap Boost Boost.bitGet AttributeType.Byte -> fmap Byte Byte.bitGet AttributeType.CamSettings -> fmap CamSettings $ CamSettings.bitGet version
src/lib/Rattletrap/Type/Cache.hs view
@@ -4,7 +4,7 @@ import qualified Rattletrap.BytePut as BytePut import qualified Rattletrap.Schema as Schema import qualified Rattletrap.Type.AttributeMapping as AttributeMapping-import qualified Rattletrap.Type.List as List+import qualified Rattletrap.Type.List as RList import qualified Rattletrap.Type.U32 as U32 import qualified Rattletrap.Utility.Json as Json @@ -12,7 +12,7 @@ { classId :: U32.U32, parentCacheId :: U32.U32, cacheId :: U32.U32,- attributeMappings :: List.List AttributeMapping.AttributeMapping+ attributeMappings :: RList.List AttributeMapping.AttributeMapping } deriving (Eq, Show) @@ -41,7 +41,7 @@ (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+ RList.schema AttributeMapping.schema, True )@@ -52,7 +52,7 @@ U32.bytePut (classId x) <> U32.bytePut (parentCacheId x) <> U32.bytePut (cacheId x)- <> List.bytePut AttributeMapping.bytePut (attributeMappings x)+ <> RList.bytePut AttributeMapping.bytePut (attributeMappings x) byteGet :: ByteGet.ByteGet Cache byteGet = ByteGet.label "Cache" $ do@@ -61,5 +61,5 @@ cacheId <- ByteGet.label "cacheId" U32.byteGet attributeMappings <- ByteGet.label "attributeMappings" $- List.byteGet AttributeMapping.byteGet+ RList.byteGet AttributeMapping.byteGet pure Cache {classId, parentCacheId, cacheId, attributeMappings}
src/lib/Rattletrap/Type/ClassAttributeMap.hs view
@@ -12,7 +12,7 @@ import qualified Rattletrap.Type.Cache as Cache import qualified Rattletrap.Type.ClassMapping as ClassMapping import qualified Rattletrap.Type.CompressedWord as CompressedWord-import qualified Rattletrap.Type.List as List+import qualified Rattletrap.Type.List as RList import qualified Rattletrap.Type.Str as Str import qualified Rattletrap.Type.U32 as U32 @@ -48,13 +48,13 @@ -- 'Rattletrap.Content.Content'. make :: -- | From 'Rattletrap.Content.objects'.- List.List Str.Str ->+ RList.List Str.Str -> -- | From 'Rattletrap.Content.classMappings'.- List.List ClassMapping.ClassMapping ->+ RList.List ClassMapping.ClassMapping -> -- | From 'Rattletrap.Content.caches'.- List.List Cache.Cache ->+ RList.List Cache.Cache -> -- | From 'Rattletrap.Content.names'.- List.List Str.Str ->+ RList.List Str.Str -> ClassAttributeMap make objects classMappings caches names = let objectMap_ = makeObjectMap objects@@ -88,9 +88,9 @@ nameMap_ = makeNameMap names in ClassAttributeMap objectMap_ objectClassMap_ value_ nameMap_ -makeNameMap :: List.List Str.Str -> IntMap.IntMap Str.Str+makeNameMap :: RList.List Str.Str -> IntMap.IntMap Str.Str makeNameMap names =- IntMap.fromDistinctAscList (zip [0 ..] (List.toList names))+ IntMap.fromDistinctAscList (zip [0 ..] (RList.toList names)) getName :: IntMap.IntMap Str.Str -> U32.U32 -> Maybe Str.Str getName nameMap_ nameIndex =@@ -125,7 +125,7 @@ makeClassCache :: Bimap U32.U32 Str.Str ->- List.List Cache.Cache ->+ RList.List Cache.Cache -> [(Maybe Str.Str, U32.U32, U32.U32, U32.U32)] makeClassCache classMap caches = fmap@@ -137,20 +137,20 @@ Cache.parentCacheId cache ) )- (List.toList caches)+ (RList.toList caches) -makeClassMap :: List.List ClassMapping.ClassMapping -> Bimap U32.U32 Str.Str+makeClassMap :: RList.List ClassMapping.ClassMapping -> Bimap U32.U32 Str.Str makeClassMap classMappings = bimap ( fmap ( \classMapping -> (ClassMapping.streamId classMapping, ClassMapping.name classMapping) )- (List.toList classMappings)+ (RList.toList classMappings) ) makeAttributeMap ::- List.List Cache.Cache -> Map.Map U32.U32 (Map.Map U32.U32 U32.U32)+ RList.List Cache.Cache -> Map.Map U32.U32 (Map.Map U32.U32 U32.U32) makeAttributeMap caches = Map.fromList ( fmap@@ -163,11 +163,11 @@ AttributeMapping.objectId attributeMapping ) )- (List.toList (Cache.attributeMappings cache))+ (RList.toList (Cache.attributeMappings cache)) ) ) )- (List.toList caches)+ (RList.toList caches) ) makeShallowParentMap ::@@ -248,9 +248,9 @@ ) ) -makeObjectMap :: List.List Str.Str -> Map.Map U32.U32 Str.Str+makeObjectMap :: RList.List Str.Str -> Map.Map U32.U32 Str.Str makeObjectMap objects =- Map.fromAscList (zip (fmap U32.fromWord32 [0 ..]) (List.toList objects))+ Map.fromAscList (zip (fmap U32.fromWord32 [0 ..]) (RList.toList objects)) getObjectName :: Map.Map U32.U32 Str.Str -> U32.U32 -> Maybe Str.Str getObjectName objectMap_ objectId = Map.lookup objectId objectMap_
src/lib/Rattletrap/Type/Content.hs view
@@ -13,7 +13,7 @@ import qualified Rattletrap.Type.ClassMapping as ClassMapping import qualified Rattletrap.Type.Frame as Frame import qualified Rattletrap.Type.Keyframe as Keyframe-import qualified Rattletrap.Type.List as List+import qualified Rattletrap.Type.List as RList import qualified Rattletrap.Type.Mark as Mark import qualified Rattletrap.Type.Message as Message import qualified Rattletrap.Type.Str as Str@@ -23,40 +23,40 @@ import qualified Rattletrap.Utility.Bytes as Bytes import qualified Rattletrap.Utility.Json as Json -type Content = ContentWith (List.List Frame.Frame)+type Content = ContentWith (RList.List Frame.Frame) -- | Contains low-level game data about a 'Rattletrap.Replay.Replay'. data ContentWith frames = Content { -- | This typically only has one element, like @stadium_oob_audio_map@.- levels :: List.List Str.Str,+ levels :: RList.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,+ keyframes :: RList.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,+ messages :: RList.List Message.Message, -- | Tick marks shown on the scrubber when watching a replay.- marks :: List.List Mark.Mark,+ marks :: RList.List Mark.Mark, -- | A list of @.upk@ files to load, like -- @..\\..\\TAGame\\CookedPCConsole\\Stadium_P.upk@.- packages :: List.List Str.Str,+ packages :: RList.List Str.Str, -- | Objects in the stream. Used for the -- 'Rattletrap.Type.ClassAttributeMap.ClassAttributeMap'.- objects :: List.List Str.Str,+ objects :: RList.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,+ names :: RList.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,+ classMappings :: RList.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,+ caches :: RList.List Cache.Cache, unknown :: [Word.Word8] } deriving (Eq, Show)@@ -112,53 +112,53 @@ 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 "levels" . Schema.json $ RList.schema Str.schema, True),+ (Json.pair "key_frames" . Schema.json $ RList.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 "messages" . Schema.json $ RList.schema Message.schema, True),+ (Json.pair "marks" . Schema.json $ RList.schema Mark.schema, True),+ (Json.pair "packages" . Schema.json $ RList.schema Str.schema, True),+ (Json.pair "objects" . Schema.json $ RList.schema Str.schema, True),+ (Json.pair "names" . Schema.json $ RList.schema Str.schema, True), ( Json.pair "class_mappings" . Schema.json $- List.schema+ RList.schema ClassMapping.schema, True ),- (Json.pair "caches" . Schema.json $ List.schema Cache.schema, True),+ (Json.pair "caches" . Schema.json $ RList.schema Cache.schema, True), (Json.pair "unknown" . Schema.json $ Schema.array U8.schema, True) ] empty :: Content empty = Content- { levels = List.empty,- keyframes = List.empty,+ { levels = RList.empty,+ keyframes = RList.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,+ frames = RList.empty,+ messages = RList.empty,+ marks = RList.empty,+ packages = RList.empty,+ objects = RList.empty,+ names = RList.empty,+ classMappings = RList.empty,+ caches = RList.empty, unknown = [] } bytePut :: Content -> BytePut.BytePut bytePut x =- List.bytePut Str.bytePut (levels x)- <> List.bytePut Keyframe.bytePut (keyframes x)+ RList.bytePut Str.bytePut (levels x)+ <> RList.bytePut Keyframe.bytePut (keyframes x) <> putFrames x- <> List.bytePut Message.bytePut (messages x)- <> List.bytePut Mark.bytePut (marks x)- <> List.bytePut Str.bytePut (packages x)- <> List.bytePut Str.bytePut (objects x)- <> List.bytePut Str.bytePut (names x)- <> List.bytePut ClassMapping.bytePut (classMappings x)- <> List.bytePut Cache.bytePut (caches x)+ <> RList.bytePut Message.bytePut (messages x)+ <> RList.bytePut Mark.bytePut (marks x)+ <> RList.bytePut Str.bytePut (packages x)+ <> RList.bytePut Str.bytePut (objects x)+ <> RList.bytePut Str.bytePut (names x)+ <> RList.bytePut ClassMapping.bytePut (classMappings x)+ <> RList.bytePut Cache.bytePut (caches x) <> foldMap BytePut.word8 (unknown x) putFrames :: Content -> BytePut.BytePut@@ -199,22 +199,22 @@ 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+ levels <- ByteGet.label "levels" $ RList.byteGet Str.byteGet+ keyframes <- ByteGet.label "keyframes" $ RList.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+ messages <- ByteGet.label "messages" $ RList.byteGet Message.byteGet+ marks <- ByteGet.label "marks" $ RList.byteGet Mark.byteGet+ packages <- ByteGet.label "packages" $ RList.byteGet Str.byteGet+ objects <- ByteGet.label "objects" $ RList.byteGet Str.byteGet+ names <- ByteGet.label "names" $ RList.byteGet Str.byteGet classMappings <- ByteGet.label "classMappings" $- List.byteGet ClassMapping.byteGet- caches <- ByteGet.label "caches" $ List.byteGet Cache.byteGet+ RList.byteGet ClassMapping.byteGet+ caches <- ByteGet.label "caches" $ RList.byteGet Cache.byteGet let classAttributeMap = ClassAttributeMap.make objects classMappings caches names getFrames =
src/lib/Rattletrap/Type/Dictionary.hs view
@@ -6,12 +6,12 @@ import qualified Rattletrap.ByteGet as ByteGet import qualified Rattletrap.BytePut as BytePut import qualified Rattletrap.Schema as Schema-import qualified Rattletrap.Type.List as List+import qualified Rattletrap.Type.List as RList import qualified Rattletrap.Type.Str as Str import qualified Rattletrap.Utility.Json as Json data Dictionary a = Dictionary- { elements :: List.List (Str.Str, a),+ { elements :: RList.List (Str.Str, a), lastKey :: Str.Str } deriving (Eq, Show)@@ -27,9 +27,9 @@ Int -> [(Int, (Str.Str, a))] -> [Text.Text] ->- m (List.List (Str.Str, a))+ m (RList.List (Str.Str, a)) build m i xs ks = case ks of- [] -> pure . List.fromList . reverse $ fmap snd xs+ [] -> pure . RList.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@@ -39,12 +39,12 @@ instance (Json.ToJSON a) => Json.ToJSON (Dictionary a) where toJSON x = Json.object- [ Json.pair "keys" . fmap fst . List.toList $ elements x,+ [ Json.pair "keys" . fmap fst . RList.toList $ elements x, Json.pair "last_key" $ lastKey x, Json.pair "value" . Map.fromList . fmap (Bifunctor.first Str.toText)- . List.toList+ . RList.toList $ elements x ] @@ -64,11 +64,11 @@ ] lookup :: Str.Str -> Dictionary a -> Maybe a-lookup k = Prelude.lookup k . List.toList . elements+lookup k = Prelude.lookup k . RList.toList . elements bytePut :: (a -> BytePut.BytePut) -> Dictionary a -> BytePut.BytePut bytePut f x =- foldMap (\(k, v) -> Str.bytePut k <> f v) (List.toList $ elements x)+ foldMap (\(k, v) -> Str.bytePut k <> f v) (RList.toList $ elements x) <> Str.bytePut (lastKey x) byteGet :: ByteGet.ByteGet a -> ByteGet.ByteGet (Dictionary a)@@ -85,7 +85,7 @@ then pure Dictionary- { elements = List.fromList . reverse $ fmap snd xs,+ { elements = RList.fromList . reverse $ fmap snd xs, lastKey = k } else do
src/lib/Rattletrap/Type/Frame.hs view
@@ -7,7 +7,7 @@ import qualified Rattletrap.Type.ClassAttributeMap as ClassAttributeMap import qualified Rattletrap.Type.CompressedWord as CompressedWord import qualified Rattletrap.Type.F32 as F32-import qualified Rattletrap.Type.List as List+import qualified Rattletrap.Type.List as RList import qualified Rattletrap.Type.Replication as Replication import qualified Rattletrap.Type.Str as Str import qualified Rattletrap.Type.U32 as U32@@ -20,7 +20,7 @@ -- | 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+ replications :: RList.List Replication.Replication } deriving (Eq, Show) @@ -45,13 +45,13 @@ 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,+ ( Json.pair "replications" . Schema.json $ RList.schema Replication.schema, True ) ] -putFrames :: List.List Frame -> BitPut.BitPut-putFrames = foldMap bitPut . List.toList+putFrames :: RList.List Frame -> BitPut.BitPut+putFrames = foldMap bitPut . RList.toList bitPut :: Frame -> BitPut.BitPut bitPut frame =@@ -66,7 +66,7 @@ Int -> Word -> ClassAttributeMap.ClassAttributeMap ->- BitGet.BitGet (List.List Frame)+ BitGet.BitGet (RList.List Frame) decodeFramesBits matchType version buildVersion count limit classes = fmap snd $ decodeFramesBitsWith@@ -94,11 +94,11 @@ ( Map.Map CompressedWord.CompressedWord U32.U32,- List.List Frame+ RList.List Frame ) decodeFramesBitsWith matchType version buildVersion count limit classes actorMap index frames = if index >= count- then pure (actorMap, List.fromList $ reverse frames)+ then pure (actorMap, RList.fromList $ reverse frames) else do (newActorMap, frame) <- BitGet.label ("element (" <> show index <> ")") $
src/lib/Rattletrap/Type/Property/Array.hs view
@@ -4,17 +4,17 @@ import qualified Rattletrap.BytePut as BytePut import qualified Rattletrap.Schema as Schema import qualified Rattletrap.Type.Dictionary as Dictionary-import qualified Rattletrap.Type.List as List+import qualified Rattletrap.Type.List as RList import qualified Rattletrap.Utility.Json as Json newtype Array a- = Array (List.List (Dictionary.Dictionary a))+ = Array (RList.List (Dictionary.Dictionary a)) deriving (Eq, Show) -fromList :: List.List (Dictionary.Dictionary a) -> Array a+fromList :: RList.List (Dictionary.Dictionary a) -> Array a fromList = Array -toList :: Array a -> List.List (Dictionary.Dictionary a)+toList :: Array a -> RList.List (Dictionary.Dictionary a) toList (Array x) = x instance (Json.FromJSON a) => Json.FromJSON (Array a) where@@ -25,13 +25,13 @@ schema :: Schema.Schema -> Schema.Schema schema s =- Schema.named "property-array" . Schema.json . List.schema $+ Schema.named "property-array" . Schema.json . RList.schema $ Dictionary.schema s bytePut :: (a -> BytePut.BytePut) -> Array a -> BytePut.BytePut-bytePut f = List.bytePut (Dictionary.bytePut f) . toList+bytePut f = RList.bytePut (Dictionary.bytePut f) . toList byteGet :: ByteGet.ByteGet a -> ByteGet.ByteGet (Array a) byteGet =- ByteGet.label "Array" . fmap fromList . List.byteGet . Dictionary.byteGet+ ByteGet.label "Array" . fmap fromList . RList.byteGet . Dictionary.byteGet
src/lib/Rattletrap/Type/Replication.hs view
@@ -6,7 +6,7 @@ import qualified Rattletrap.Schema as Schema 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.List as RList import qualified Rattletrap.Type.ReplicationValue as ReplicationValue import qualified Rattletrap.Type.Str as Str import qualified Rattletrap.Type.U32 as U32@@ -37,9 +37,9 @@ (Json.pair "value" $ Schema.ref ReplicationValue.schema, True) ] -putReplications :: List.List Replication -> BitPut.BitPut+putReplications :: RList.List Replication -> BitPut.BitPut putReplications xs =- foldMap (\x -> BitPut.bool True <> bitPut x) (List.toList xs)+ foldMap (\x -> BitPut.bool True <> bitPut x) (RList.toList xs) <> BitPut.bool False bitPut :: Replication -> BitPut.BitPut@@ -56,7 +56,7 @@ Map.Map CompressedWord.CompressedWord U32.U32 -> BitGet.BitGet ( Map.Map CompressedWord.CompressedWord U32.U32,- List.List Replication+ RList.List Replication ) decodeReplicationsBits matchType version buildVersion limit classes actorMap = decodeReplicationsBitsWith@@ -80,7 +80,7 @@ [Replication] -> BitGet.BitGet ( Map.Map CompressedWord.CompressedWord U32.U32,- List.List Replication+ RList.List Replication ) decodeReplicationsBitsWith matchType version buildVersion limit classes actorMap index replications = do@@ -100,7 +100,7 @@ (index + 1) $ replication : replications- else pure (actorMap, List.fromList $ reverse replications)+ else pure (actorMap, RList.fromList $ reverse replications) bitGet :: Maybe Str.Str ->
src/lib/Rattletrap/Type/Replication/Updated.hs view
@@ -7,7 +7,7 @@ import qualified Rattletrap.Type.Attribute as Attribute 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.List as RList import qualified Rattletrap.Type.Str as Str import qualified Rattletrap.Type.U32 as U32 import qualified Rattletrap.Type.Version as Version@@ -15,7 +15,7 @@ import qualified Rattletrap.Utility.Monad as Monad newtype Updated = Updated- { attributes :: List.List Attribute.Attribute+ { attributes :: RList.List Attribute.Attribute } deriving (Eq, Show) @@ -28,14 +28,14 @@ schema :: Schema.Schema schema = Schema.named "replication-updated" . Schema.json $- List.schema+ RList.schema Attribute.schema bitPut :: Updated -> BitPut.BitPut bitPut x = foldMap (\y -> BitPut.bool True <> Attribute.bitPut y)- (List.toList $ attributes x)+ (RList.toList $ attributes x) <> BitPut.bool False bitGet ::@@ -46,7 +46,7 @@ CompressedWord.CompressedWord -> BitGet.BitGet Updated bitGet version buildVersion classes actors actor =- BitGet.label "Updated" . fmap Updated . List.untilM $ do+ BitGet.label "Updated" . fmap Updated . RList.untilM $ do p <- BitGet.bool Monad.whenMaybe p $ Attribute.bitGet version buildVersion classes actors actor
src/test/Main.hs view
@@ -72,6 +72,7 @@ ("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+ ("2066", "replicated boost"), -- https://github.com/tfausak/rattletrap/issues/296 ("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