packages feed

rattletrap 9.4.1 → 10.0.0

raw patch · 305 files changed

+6364/−6357 lines, 305 filesdep +arraydep −scientificdep −template-haskelldep −temporaryPVP ok

version bump matches the API change (PVP)

Dependencies added: array

Dependencies removed: scientific, template-haskell, temporary

API changes (from Hackage documentation)

- Rattletrap: AppliedDamageAttribute :: Word8le -> Vector -> Int32le -> Int32le -> AppliedDamageAttribute
- Rattletrap: Attribute :: CompressedWord -> Str -> AttributeValue -> Attribute
- Rattletrap: AttributeMapping :: Word32le -> Word32le -> AttributeMapping
- Rattletrap: AttributeTypeAppliedDamage :: AttributeType
- Rattletrap: AttributeTypeBoolean :: AttributeType
- Rattletrap: AttributeTypeByte :: AttributeType
- Rattletrap: AttributeTypeCamSettings :: AttributeType
- Rattletrap: AttributeTypeClubColors :: AttributeType
- Rattletrap: AttributeTypeCustomDemolish :: AttributeType
- Rattletrap: AttributeTypeDamageState :: AttributeType
- Rattletrap: AttributeTypeDemolish :: AttributeType
- Rattletrap: AttributeTypeEnum :: AttributeType
- Rattletrap: AttributeTypeExplosion :: AttributeType
- Rattletrap: AttributeTypeExtendedExplosion :: AttributeType
- Rattletrap: AttributeTypeFlaggedByte :: AttributeType
- Rattletrap: AttributeTypeFlaggedInt :: AttributeType
- Rattletrap: AttributeTypeFloat :: AttributeType
- Rattletrap: AttributeTypeGameMode :: AttributeType
- Rattletrap: AttributeTypeInt :: AttributeType
- Rattletrap: AttributeTypeInt64 :: AttributeType
- Rattletrap: AttributeTypeLoadout :: AttributeType
- Rattletrap: AttributeTypeLoadoutOnline :: AttributeType
- Rattletrap: AttributeTypeLoadouts :: AttributeType
- Rattletrap: AttributeTypeLoadoutsOnline :: AttributeType
- Rattletrap: AttributeTypeLocation :: AttributeType
- Rattletrap: AttributeTypeMusicStinger :: AttributeType
- Rattletrap: AttributeTypePartyLeader :: AttributeType
- Rattletrap: AttributeTypePickup :: AttributeType
- Rattletrap: AttributeTypePickupNew :: AttributeType
- Rattletrap: AttributeTypePlayerHistoryKey :: AttributeType
- Rattletrap: AttributeTypePrivateMatchSettings :: AttributeType
- Rattletrap: AttributeTypeQWord :: AttributeType
- Rattletrap: AttributeTypeReservation :: AttributeType
- Rattletrap: AttributeTypeRigidBodyState :: AttributeType
- Rattletrap: AttributeTypeStatEvent :: AttributeType
- Rattletrap: AttributeTypeString :: AttributeType
- Rattletrap: AttributeTypeTeamPaint :: AttributeType
- Rattletrap: AttributeTypeTitle :: AttributeType
- Rattletrap: AttributeTypeUniqueId :: AttributeType
- Rattletrap: AttributeTypeWeldedInfo :: AttributeType
- Rattletrap: AttributeValueAppliedDamage :: AppliedDamageAttribute -> AttributeValue
- Rattletrap: AttributeValueBoolean :: BooleanAttribute -> AttributeValue
- Rattletrap: AttributeValueByte :: ByteAttribute -> AttributeValue
- Rattletrap: AttributeValueCamSettings :: CamSettingsAttribute -> AttributeValue
- Rattletrap: AttributeValueClubColors :: ClubColorsAttribute -> AttributeValue
- Rattletrap: AttributeValueCustomDemolish :: CustomDemolishAttribute -> AttributeValue
- Rattletrap: AttributeValueDamageState :: DamageStateAttribute -> AttributeValue
- Rattletrap: AttributeValueDemolish :: DemolishAttribute -> AttributeValue
- Rattletrap: AttributeValueEnum :: EnumAttribute -> AttributeValue
- Rattletrap: AttributeValueExplosion :: ExplosionAttribute -> AttributeValue
- Rattletrap: AttributeValueExtendedExplosion :: ExtendedExplosionAttribute -> AttributeValue
- Rattletrap: AttributeValueFlaggedByte :: FlaggedByteAttribute -> AttributeValue
- Rattletrap: AttributeValueFlaggedInt :: FlaggedIntAttribute -> AttributeValue
- Rattletrap: AttributeValueFloat :: FloatAttribute -> AttributeValue
- Rattletrap: AttributeValueGameMode :: GameModeAttribute -> AttributeValue
- Rattletrap: AttributeValueInt :: IntAttribute -> AttributeValue
- Rattletrap: AttributeValueInt64 :: Int64Attribute -> AttributeValue
- Rattletrap: AttributeValueLoadout :: LoadoutAttribute -> AttributeValue
- Rattletrap: AttributeValueLoadoutOnline :: LoadoutOnlineAttribute -> AttributeValue
- Rattletrap: AttributeValueLoadouts :: LoadoutsAttribute -> AttributeValue
- Rattletrap: AttributeValueLoadoutsOnline :: LoadoutsOnlineAttribute -> AttributeValue
- Rattletrap: AttributeValueLocation :: LocationAttribute -> AttributeValue
- Rattletrap: AttributeValueMusicStinger :: MusicStingerAttribute -> AttributeValue
- Rattletrap: AttributeValuePartyLeader :: PartyLeaderAttribute -> AttributeValue
- Rattletrap: AttributeValuePickup :: PickupAttribute -> AttributeValue
- Rattletrap: AttributeValuePickupNew :: PickupAttributeNew -> AttributeValue
- Rattletrap: AttributeValuePlayerHistoryKey :: PlayerHistoryKeyAttribute -> AttributeValue
- Rattletrap: AttributeValuePrivateMatchSettings :: PrivateMatchSettingsAttribute -> AttributeValue
- Rattletrap: AttributeValueQWord :: QWordAttribute -> AttributeValue
- Rattletrap: AttributeValueReservation :: ReservationAttribute -> AttributeValue
- Rattletrap: AttributeValueRigidBodyState :: RigidBodyStateAttribute -> AttributeValue
- Rattletrap: AttributeValueStatEvent :: StatEventAttribute -> AttributeValue
- Rattletrap: AttributeValueString :: StringAttribute -> AttributeValue
- Rattletrap: AttributeValueTeamPaint :: TeamPaintAttribute -> AttributeValue
- Rattletrap: AttributeValueTitle :: TitleAttribute -> AttributeValue
- Rattletrap: AttributeValueUniqueId :: UniqueIdAttribute -> AttributeValue
- Rattletrap: AttributeValueWeldedInfo :: WeldedInfoAttribute -> AttributeValue
- Rattletrap: BooleanAttribute :: Bool -> BooleanAttribute
- Rattletrap: ByteAttribute :: Word8le -> ByteAttribute
- Rattletrap: Cache :: Word32le -> Word32le -> Word32le -> List AttributeMapping -> Cache
- Rattletrap: CamSettingsAttribute :: Float32le -> Float32le -> Float32le -> Float32le -> Float32le -> Float32le -> Maybe Float32le -> CamSettingsAttribute
- Rattletrap: ClassAttributeMap :: Map Word32le Str -> Map Word32le Word32le -> Map Word32le (Map Word32le Word32le) -> IntMap Str -> ClassAttributeMap
- Rattletrap: ClassMapping :: Str -> Word32le -> ClassMapping
- Rattletrap: ClubColorsAttribute :: Bool -> Word8le -> Bool -> Word8le -> ClubColorsAttribute
- Rattletrap: CompressedWord :: Word -> Word -> CompressedWord
- Rattletrap: CompressedWordVector :: CompressedWord -> CompressedWord -> CompressedWord -> CompressedWordVector
- Rattletrap: Content :: List Str -> List KeyFrame -> Word32le -> [Frame] -> List Message -> List Mark -> List Str -> List Str -> List Str -> List ClassMapping -> List Cache -> [Word8] -> Content
- Rattletrap: DamageStateAttribute :: Word8le -> Bool -> Int32le -> Vector -> Bool -> Bool -> DamageStateAttribute
- Rattletrap: DemolishAttribute :: Bool -> Word32le -> Bool -> Word32le -> Vector -> Vector -> DemolishAttribute
- Rattletrap: DestroyedReplication :: DestroyedReplication
- Rattletrap: DictionaryElement :: Str -> a -> Dictionary a -> Dictionary a
- Rattletrap: DictionaryEnd :: Str -> Dictionary a
- Rattletrap: EnumAttribute :: Word16 -> EnumAttribute
- Rattletrap: ExplosionAttribute :: Bool -> Int32le -> Vector -> ExplosionAttribute
- Rattletrap: ExtendedExplosionAttribute :: ExplosionAttribute -> FlaggedIntAttribute -> ExtendedExplosionAttribute
- Rattletrap: FlaggedIntAttribute :: Bool -> Int32le -> FlaggedIntAttribute
- Rattletrap: Float32le :: Float -> Float32le
- Rattletrap: FloatAttribute :: Float32le -> FloatAttribute
- Rattletrap: Frame :: Float32le -> Float32le -> [Replication] -> Frame
- Rattletrap: GameModeAttribute :: Int -> Word8 -> GameModeAttribute
- Rattletrap: Header :: Word32le -> Word32le -> Maybe Word32le -> Str -> Dictionary Property -> Header
- Rattletrap: Initialization :: Maybe Vector -> Maybe Int8Vector -> Initialization
- Rattletrap: Int32le :: Int32 -> Int32le
- Rattletrap: Int64Attribute :: Int64le -> Int64Attribute
- Rattletrap: Int64le :: Int64 -> Int64le
- Rattletrap: Int8Vector :: Maybe Int8le -> Maybe Int8le -> Maybe Int8le -> Int8Vector
- Rattletrap: Int8le :: Int8 -> Int8le
- Rattletrap: IntAttribute :: Int32le -> IntAttribute
- Rattletrap: KeyFrame :: Float32le -> Word32le -> Word32le -> KeyFrame
- Rattletrap: List :: [a] -> List a
- Rattletrap: LoadoutAttribute :: Word8le -> Word32le -> Word32le -> Word32le -> Word32le -> Word32le -> Word32le -> Word32le -> Maybe Word32le -> Maybe Word32le -> Maybe Word32le -> Maybe Word32le -> Maybe Word32le -> Maybe Word32le -> Maybe Word32le -> Maybe Word32le -> Maybe Word32le -> LoadoutAttribute
- Rattletrap: LoadoutOnlineAttribute :: [[ProductAttribute]] -> LoadoutOnlineAttribute
- Rattletrap: LoadoutsAttribute :: LoadoutAttribute -> LoadoutAttribute -> LoadoutsAttribute
- Rattletrap: LoadoutsOnlineAttribute :: LoadoutOnlineAttribute -> LoadoutOnlineAttribute -> Bool -> Bool -> LoadoutsOnlineAttribute
- Rattletrap: LocationAttribute :: Vector -> LocationAttribute
- Rattletrap: Mark :: Str -> Word32le -> Mark
- Rattletrap: Message :: Word32le -> Str -> Str -> Message
- Rattletrap: MusicStingerAttribute :: Bool -> Word32le -> Word8le -> MusicStingerAttribute
- Rattletrap: PartyLeaderAttribute :: Word8le -> Maybe (RemoteId, Word8le) -> PartyLeaderAttribute
- Rattletrap: PickupAttribute :: Maybe Word32le -> Bool -> PickupAttribute
- Rattletrap: PlayerHistoryKeyAttribute :: Word16 -> PlayerHistoryKeyAttribute
- Rattletrap: PrivateMatchSettingsAttribute :: Str -> Word32le -> Word32le -> Str -> Str -> Bool -> PrivateMatchSettingsAttribute
- Rattletrap: ProductAttribute :: Bool -> Word32le -> Maybe Str -> ProductAttributeValue -> ProductAttribute
- Rattletrap: Property :: Str -> Word64le -> PropertyValue Property -> Property
- Rattletrap: PropertyValueArray :: List (Dictionary a) -> PropertyValue a
- Rattletrap: PropertyValueBool :: Word8le -> PropertyValue a
- Rattletrap: PropertyValueByte :: Str -> Maybe Str -> PropertyValue a
- Rattletrap: PropertyValueFloat :: Float32le -> PropertyValue a
- Rattletrap: PropertyValueInt :: Int32le -> PropertyValue a
- Rattletrap: PropertyValueName :: Str -> PropertyValue a
- Rattletrap: PropertyValueQWord :: Word64le -> PropertyValue a
- Rattletrap: PropertyValueStr :: Str -> PropertyValue a
- Rattletrap: QWordAttribute :: Word64le -> QWordAttribute
- Rattletrap: Quaternion :: Double -> Double -> Double -> Double -> Quaternion
- Rattletrap: RemoteIdEpic :: Str -> RemoteId
- Rattletrap: RemoteIdPlayStation :: Text -> [Word8] -> RemoteId
- Rattletrap: RemoteIdPsyNet :: Either Word64le (Word64le, Word64le, Word64le, Word64le) -> RemoteId
- Rattletrap: RemoteIdSplitscreen :: Word32 -> RemoteId
- Rattletrap: RemoteIdSteam :: Word64le -> RemoteId
- Rattletrap: RemoteIdSwitch :: Word64le -> Word64le -> Word64le -> Word64le -> RemoteId
- Rattletrap: RemoteIdXbox :: Word64le -> RemoteId
- Rattletrap: Replay :: Section Header -> Section content -> Replay content
- Rattletrap: Replication :: CompressedWord -> ReplicationValue -> Replication
- Rattletrap: ReplicationValueDestroyed :: DestroyedReplication -> ReplicationValue
- Rattletrap: ReplicationValueSpawned :: SpawnedReplication -> ReplicationValue
- Rattletrap: ReplicationValueUpdated :: UpdatedReplication -> ReplicationValue
- Rattletrap: ReservationAttribute :: CompressedWord -> UniqueIdAttribute -> Maybe Str -> Bool -> Bool -> Maybe Word8 -> ReservationAttribute
- Rattletrap: RigidBodyStateAttribute :: Bool -> Vector -> Rotation -> Maybe Vector -> Maybe Vector -> RigidBodyStateAttribute
- Rattletrap: RotationCompressedWordVector :: CompressedWordVector -> Rotation
- Rattletrap: RotationQuaternion :: Quaternion -> Rotation
- Rattletrap: Section :: Word32le -> Word32le -> a -> Section a
- Rattletrap: SpawnedReplication :: Bool -> Maybe Word32le -> Maybe Str -> Word32le -> Str -> Str -> Initialization -> SpawnedReplication
- Rattletrap: StatEventAttribute :: Bool -> Int32le -> StatEventAttribute
- Rattletrap: Str :: Text -> Str
- Rattletrap: StringAttribute :: Str -> StringAttribute
- Rattletrap: TeamPaintAttribute :: Word8le -> Word8le -> Word8le -> Word32le -> Word32le -> TeamPaintAttribute
- Rattletrap: TitleAttribute :: Bool -> Bool -> Word32le -> Word32le -> Word32le -> Word32le -> Word32le -> Bool -> TitleAttribute
- Rattletrap: UniqueIdAttribute :: Word8le -> RemoteId -> Word8le -> UniqueIdAttribute
- Rattletrap: UpdatedReplication :: [Attribute] -> UpdatedReplication
- Rattletrap: Vector :: CompressedWord -> Word -> Int -> Int -> Int -> Vector
- Rattletrap: WeldedInfoAttribute :: Bool -> Int32le -> Vector -> Float32le -> Int8Vector -> WeldedInfoAttribute
- Rattletrap: Word32le :: Word32 -> Word32le
- Rattletrap: Word64le :: Word64 -> Word64le
- Rattletrap: Word8le :: Word8 -> Word8le
- Rattletrap: [appliedDamageAttributeLocation] :: AppliedDamageAttribute -> Vector
- Rattletrap: [appliedDamageAttributeUnknown1] :: AppliedDamageAttribute -> Word8le
- Rattletrap: [appliedDamageAttributeUnknown3] :: AppliedDamageAttribute -> Int32le
- Rattletrap: [appliedDamageAttributeUnknown4] :: AppliedDamageAttribute -> Int32le
- Rattletrap: [attributeId] :: Attribute -> CompressedWord
- Rattletrap: [attributeMappingObjectId] :: AttributeMapping -> Word32le
- Rattletrap: [attributeMappingStreamId] :: AttributeMapping -> Word32le
- Rattletrap: [attributeName] :: Attribute -> Str
- Rattletrap: [attributeValue] :: Attribute -> AttributeValue
- Rattletrap: [booleanAttributeValue] :: BooleanAttribute -> Bool
- Rattletrap: [byteAttributeValue] :: ByteAttribute -> Word8le
- Rattletrap: [cacheAttributeMappings] :: Cache -> List AttributeMapping
- Rattletrap: [cacheCacheId] :: Cache -> Word32le
- Rattletrap: [cacheClassId] :: Cache -> Word32le
- Rattletrap: [cacheParentCacheId] :: Cache -> Word32le
- Rattletrap: [camSettingsAttributeAngle] :: CamSettingsAttribute -> Float32le
- Rattletrap: [camSettingsAttributeDistance] :: CamSettingsAttribute -> Float32le
- Rattletrap: [camSettingsAttributeFov] :: CamSettingsAttribute -> Float32le
- Rattletrap: [camSettingsAttributeHeight] :: CamSettingsAttribute -> Float32le
- Rattletrap: [camSettingsAttributeStiffness] :: CamSettingsAttribute -> Float32le
- Rattletrap: [camSettingsAttributeSwivelSpeed] :: CamSettingsAttribute -> Float32le
- Rattletrap: [camSettingsAttributeTransitionSpeed] :: CamSettingsAttribute -> Maybe Float32le
- Rattletrap: [classAttributeMapNameMap] :: ClassAttributeMap -> IntMap Str
- Rattletrap: [classAttributeMapObjectClassMap] :: ClassAttributeMap -> Map Word32le Word32le
- Rattletrap: [classAttributeMapObjectMap] :: ClassAttributeMap -> Map Word32le Str
- Rattletrap: [classAttributeMapValue] :: ClassAttributeMap -> Map Word32le (Map Word32le Word32le)
- Rattletrap: [classMappingName] :: ClassMapping -> Str
- Rattletrap: [classMappingStreamId] :: ClassMapping -> Word32le
- Rattletrap: [clubColorsAttributeBlueColor] :: ClubColorsAttribute -> Word8le
- Rattletrap: [clubColorsAttributeBlueFlag] :: ClubColorsAttribute -> Bool
- Rattletrap: [clubColorsAttributeOrangeColor] :: ClubColorsAttribute -> Word8le
- Rattletrap: [clubColorsAttributeOrangeFlag] :: ClubColorsAttribute -> Bool
- Rattletrap: [compressedWordLimit] :: CompressedWord -> Word
- Rattletrap: [compressedWordValue] :: CompressedWord -> Word
- Rattletrap: [compressedWordVectorX] :: CompressedWordVector -> CompressedWord
- Rattletrap: [compressedWordVectorY] :: CompressedWordVector -> CompressedWord
- Rattletrap: [compressedWordVectorZ] :: CompressedWordVector -> CompressedWord
- Rattletrap: [contentCaches] :: Content -> List Cache
- Rattletrap: [contentClassMappings] :: Content -> List ClassMapping
- Rattletrap: [contentFrames] :: Content -> [Frame]
- Rattletrap: [contentKeyFrames] :: Content -> List KeyFrame
- Rattletrap: [contentLevels] :: Content -> List Str
- Rattletrap: [contentMarks] :: Content -> List Mark
- Rattletrap: [contentMessages] :: Content -> List Message
- Rattletrap: [contentNames] :: Content -> List Str
- Rattletrap: [contentObjects] :: Content -> List Str
- Rattletrap: [contentPackages] :: Content -> List Str
- Rattletrap: [contentStreamSize] :: Content -> Word32le
- Rattletrap: [contentUnknown] :: Content -> [Word8]
- Rattletrap: [damageStateAttributeUnknown1] :: DamageStateAttribute -> Word8le
- Rattletrap: [damageStateAttributeUnknown2] :: DamageStateAttribute -> Bool
- Rattletrap: [damageStateAttributeUnknown3] :: DamageStateAttribute -> Int32le
- Rattletrap: [damageStateAttributeUnknown4] :: DamageStateAttribute -> Vector
- Rattletrap: [damageStateAttributeUnknown5] :: DamageStateAttribute -> Bool
- Rattletrap: [damageStateAttributeUnknown6] :: DamageStateAttribute -> Bool
- Rattletrap: [demolishAttributeAttackerActorId] :: DemolishAttribute -> Word32le
- Rattletrap: [demolishAttributeAttackerFlag] :: DemolishAttribute -> Bool
- Rattletrap: [demolishAttributeAttackerVelocity] :: DemolishAttribute -> Vector
- Rattletrap: [demolishAttributeVictimActorId] :: DemolishAttribute -> Word32le
- Rattletrap: [demolishAttributeVictimFlag] :: DemolishAttribute -> Bool
- Rattletrap: [demolishAttributeVictimVelocity] :: DemolishAttribute -> Vector
- Rattletrap: [enumAttributeValue] :: EnumAttribute -> Word16
- Rattletrap: [explosionAttributeActorId] :: ExplosionAttribute -> Int32le
- Rattletrap: [explosionAttributeFlag] :: ExplosionAttribute -> Bool
- Rattletrap: [explosionAttributeLocation] :: ExplosionAttribute -> Vector
- Rattletrap: [extendedExplosionAttributeExplosion] :: ExtendedExplosionAttribute -> ExplosionAttribute
- Rattletrap: [extendedExplosionAttributeUnknown] :: ExtendedExplosionAttribute -> FlaggedIntAttribute
- Rattletrap: [flaggedIntAttributeFlag] :: FlaggedIntAttribute -> Bool
- Rattletrap: [flaggedIntAttributeInt] :: FlaggedIntAttribute -> Int32le
- Rattletrap: [float32leValue] :: Float32le -> Float
- Rattletrap: [floatAttributeValue] :: FloatAttribute -> Float32le
- Rattletrap: [frameDelta] :: Frame -> Float32le
- Rattletrap: [frameReplications] :: Frame -> [Replication]
- Rattletrap: [frameTime] :: Frame -> Float32le
- Rattletrap: [gameModeAttributeNumBits] :: GameModeAttribute -> Int
- Rattletrap: [gameModeAttributeWord] :: GameModeAttribute -> Word8
- Rattletrap: [headerEngineVersion] :: Header -> Word32le
- Rattletrap: [headerLabel] :: Header -> Str
- Rattletrap: [headerLicenseeVersion] :: Header -> Word32le
- Rattletrap: [headerPatchVersion] :: Header -> Maybe Word32le
- Rattletrap: [headerProperties] :: Header -> Dictionary Property
- Rattletrap: [initializationLocation] :: Initialization -> Maybe Vector
- Rattletrap: [initializationRotation] :: Initialization -> Maybe Int8Vector
- Rattletrap: [int32leValue] :: Int32le -> Int32
- Rattletrap: [int64AttributeValue] :: Int64Attribute -> Int64le
- Rattletrap: [int64leValue] :: Int64le -> Int64
- Rattletrap: [int8VectorX] :: Int8Vector -> Maybe Int8le
- Rattletrap: [int8VectorY] :: Int8Vector -> Maybe Int8le
- Rattletrap: [int8VectorZ] :: Int8Vector -> Maybe Int8le
- Rattletrap: [int8leValue] :: Int8le -> Int8
- Rattletrap: [intAttributeValue] :: IntAttribute -> Int32le
- Rattletrap: [keyFrameFrame] :: KeyFrame -> Word32le
- Rattletrap: [keyFramePosition] :: KeyFrame -> Word32le
- Rattletrap: [keyFrameTime] :: KeyFrame -> Float32le
- Rattletrap: [listValue] :: List a -> [a]
- Rattletrap: [loadoutAttributeAntenna] :: LoadoutAttribute -> Word32le
- Rattletrap: [loadoutAttributeBanner] :: LoadoutAttribute -> Maybe Word32le
- Rattletrap: [loadoutAttributeBody] :: LoadoutAttribute -> Word32le
- Rattletrap: [loadoutAttributeDecal] :: LoadoutAttribute -> Word32le
- Rattletrap: [loadoutAttributeEngineAudio] :: LoadoutAttribute -> Maybe Word32le
- Rattletrap: [loadoutAttributeGoalExplosion] :: LoadoutAttribute -> Maybe Word32le
- Rattletrap: [loadoutAttributeRocketTrail] :: LoadoutAttribute -> Word32le
- Rattletrap: [loadoutAttributeTopper] :: LoadoutAttribute -> Word32le
- Rattletrap: [loadoutAttributeTrail] :: LoadoutAttribute -> Maybe Word32le
- Rattletrap: [loadoutAttributeUnknown1] :: LoadoutAttribute -> Word32le
- Rattletrap: [loadoutAttributeUnknown2] :: LoadoutAttribute -> Maybe Word32le
- Rattletrap: [loadoutAttributeUnknown3] :: LoadoutAttribute -> Maybe Word32le
- Rattletrap: [loadoutAttributeUnknown4] :: LoadoutAttribute -> Maybe Word32le
- Rattletrap: [loadoutAttributeUnknown5] :: LoadoutAttribute -> Maybe Word32le
- Rattletrap: [loadoutAttributeUnknown6] :: LoadoutAttribute -> Maybe Word32le
- Rattletrap: [loadoutAttributeValue] :: LoadoutOnlineAttribute -> [[ProductAttribute]]
- Rattletrap: [loadoutAttributeVersion] :: LoadoutAttribute -> Word8le
- Rattletrap: [loadoutAttributeWheels] :: LoadoutAttribute -> Word32le
- Rattletrap: [loadoutsAttributeBlue] :: LoadoutsAttribute -> LoadoutAttribute
- Rattletrap: [loadoutsAttributeOrange] :: LoadoutsAttribute -> LoadoutAttribute
- Rattletrap: [loadoutsOnlineAttributeBlue] :: LoadoutsOnlineAttribute -> LoadoutOnlineAttribute
- Rattletrap: [loadoutsOnlineAttributeOrange] :: LoadoutsOnlineAttribute -> LoadoutOnlineAttribute
- Rattletrap: [loadoutsOnlineAttributeUnknown1] :: LoadoutsOnlineAttribute -> Bool
- Rattletrap: [loadoutsOnlineAttributeUnknown2] :: LoadoutsOnlineAttribute -> Bool
- Rattletrap: [locationAttributeValue] :: LocationAttribute -> Vector
- Rattletrap: [markFrame] :: Mark -> Word32le
- Rattletrap: [markValue] :: Mark -> Str
- Rattletrap: [messageFrame] :: Message -> Word32le
- Rattletrap: [messageName] :: Message -> Str
- Rattletrap: [messageValue] :: Message -> Str
- Rattletrap: [musicStingerAttributeCue] :: MusicStingerAttribute -> Word32le
- Rattletrap: [musicStingerAttributeFlag] :: MusicStingerAttribute -> Bool
- Rattletrap: [musicStingerAttributeTrigger] :: MusicStingerAttribute -> Word8le
- Rattletrap: [partyLeaderAttributeId] :: PartyLeaderAttribute -> Maybe (RemoteId, Word8le)
- Rattletrap: [partyLeaderAttributeSystemId] :: PartyLeaderAttribute -> Word8le
- Rattletrap: [pickupAttributeInstigatorId] :: PickupAttribute -> Maybe Word32le
- Rattletrap: [pickupAttributePickedUp] :: PickupAttribute -> Bool
- Rattletrap: [playerHistoryKeyAttributeUnknown] :: PlayerHistoryKeyAttribute -> Word16
- Rattletrap: [privateMatchSettingsAttributeFlag] :: PrivateMatchSettingsAttribute -> Bool
- Rattletrap: [privateMatchSettingsAttributeGameName] :: PrivateMatchSettingsAttribute -> Str
- Rattletrap: [privateMatchSettingsAttributeJoinableBy] :: PrivateMatchSettingsAttribute -> Word32le
- Rattletrap: [privateMatchSettingsAttributeMaxPlayers] :: PrivateMatchSettingsAttribute -> Word32le
- Rattletrap: [privateMatchSettingsAttributeMutators] :: PrivateMatchSettingsAttribute -> Str
- Rattletrap: [privateMatchSettingsAttributePassword] :: PrivateMatchSettingsAttribute -> Str
- Rattletrap: [productAttributeObjectId] :: ProductAttribute -> Word32le
- Rattletrap: [productAttributeObjectName] :: ProductAttribute -> Maybe Str
- Rattletrap: [productAttributeUnknown] :: ProductAttribute -> Bool
- Rattletrap: [productAttributeValue] :: ProductAttribute -> ProductAttributeValue
- Rattletrap: [propertyKind] :: Property -> Str
- Rattletrap: [propertySize] :: Property -> Word64le
- Rattletrap: [propertyValue] :: Property -> PropertyValue Property
- Rattletrap: [qWordAttributeValue] :: QWordAttribute -> Word64le
- Rattletrap: [quaternionW] :: Quaternion -> Double
- Rattletrap: [quaternionX] :: Quaternion -> Double
- Rattletrap: [quaternionY] :: Quaternion -> Double
- Rattletrap: [quaternionZ] :: Quaternion -> Double
- Rattletrap: [replayContent] :: Replay content -> Section content
- Rattletrap: [replayHeader] :: Replay content -> Section Header
- Rattletrap: [replicationActorId] :: Replication -> CompressedWord
- Rattletrap: [replicationValue] :: Replication -> ReplicationValue
- Rattletrap: [reservationAttributeName] :: ReservationAttribute -> Maybe Str
- Rattletrap: [reservationAttributeNumber] :: ReservationAttribute -> CompressedWord
- Rattletrap: [reservationAttributeUniqueId] :: ReservationAttribute -> UniqueIdAttribute
- Rattletrap: [reservationAttributeUnknown1] :: ReservationAttribute -> Bool
- Rattletrap: [reservationAttributeUnknown2] :: ReservationAttribute -> Bool
- Rattletrap: [reservationAttributeUnknown3] :: ReservationAttribute -> Maybe Word8
- Rattletrap: [rigidBodyStateAttributeAngularVelocity] :: RigidBodyStateAttribute -> Maybe Vector
- Rattletrap: [rigidBodyStateAttributeLinearVelocity] :: RigidBodyStateAttribute -> Maybe Vector
- Rattletrap: [rigidBodyStateAttributeLocation] :: RigidBodyStateAttribute -> Vector
- Rattletrap: [rigidBodyStateAttributeRotation] :: RigidBodyStateAttribute -> Rotation
- Rattletrap: [rigidBodyStateAttributeSleeping] :: RigidBodyStateAttribute -> Bool
- Rattletrap: [sectionBody] :: Section a -> a
- Rattletrap: [sectionCrc] :: Section a -> Word32le
- Rattletrap: [sectionSize] :: Section a -> Word32le
- Rattletrap: [spawnedReplicationClassName] :: SpawnedReplication -> Str
- Rattletrap: [spawnedReplicationFlag] :: SpawnedReplication -> Bool
- Rattletrap: [spawnedReplicationInitialization] :: SpawnedReplication -> Initialization
- Rattletrap: [spawnedReplicationNameIndex] :: SpawnedReplication -> Maybe Word32le
- Rattletrap: [spawnedReplicationName] :: SpawnedReplication -> Maybe Str
- Rattletrap: [spawnedReplicationObjectId] :: SpawnedReplication -> Word32le
- Rattletrap: [spawnedReplicationObjectName] :: SpawnedReplication -> Str
- Rattletrap: [statEventAttributeObjectId] :: StatEventAttribute -> Int32le
- Rattletrap: [statEventAttributeUnknown] :: StatEventAttribute -> Bool
- Rattletrap: [strValue] :: Str -> Text
- Rattletrap: [stringAttributeValue] :: StringAttribute -> Str
- Rattletrap: [teamPaintAttributeAccentColor] :: TeamPaintAttribute -> Word8le
- Rattletrap: [teamPaintAttributeAccentFinish] :: TeamPaintAttribute -> Word32le
- Rattletrap: [teamPaintAttributePrimaryColor] :: TeamPaintAttribute -> Word8le
- Rattletrap: [teamPaintAttributePrimaryFinish] :: TeamPaintAttribute -> Word32le
- Rattletrap: [teamPaintAttributeTeam] :: TeamPaintAttribute -> Word8le
- Rattletrap: [titleAttributeUnknown1] :: TitleAttribute -> Bool
- Rattletrap: [titleAttributeUnknown2] :: TitleAttribute -> Bool
- Rattletrap: [titleAttributeUnknown3] :: TitleAttribute -> Word32le
- Rattletrap: [titleAttributeUnknown4] :: TitleAttribute -> Word32le
- Rattletrap: [titleAttributeUnknown5] :: TitleAttribute -> Word32le
- Rattletrap: [titleAttributeUnknown6] :: TitleAttribute -> Word32le
- Rattletrap: [titleAttributeUnknown7] :: TitleAttribute -> Word32le
- Rattletrap: [titleAttributeUnknown8] :: TitleAttribute -> Bool
- Rattletrap: [uniqueIdAttributeLocalId] :: UniqueIdAttribute -> Word8le
- Rattletrap: [uniqueIdAttributeRemoteId] :: UniqueIdAttribute -> RemoteId
- Rattletrap: [uniqueIdAttributeSystemId] :: UniqueIdAttribute -> Word8le
- Rattletrap: [updatedReplicationAttributes] :: UpdatedReplication -> [Attribute]
- Rattletrap: [vectorBias] :: Vector -> Word
- Rattletrap: [vectorSize] :: Vector -> CompressedWord
- Rattletrap: [vectorX] :: Vector -> Int
- Rattletrap: [vectorY] :: Vector -> Int
- Rattletrap: [vectorZ] :: Vector -> Int
- Rattletrap: [weldedInfoAttributeActive] :: WeldedInfoAttribute -> Bool
- Rattletrap: [weldedInfoAttributeActorId] :: WeldedInfoAttribute -> Int32le
- Rattletrap: [weldedInfoAttributeMass] :: WeldedInfoAttribute -> Float32le
- Rattletrap: [weldedInfoAttributeOffset] :: WeldedInfoAttribute -> Vector
- Rattletrap: [weldedInfoAttributeRotation] :: WeldedInfoAttribute -> Int8Vector
- Rattletrap: [word32leValue] :: Word32le -> Word32
- Rattletrap: [word64leValue] :: Word64le -> Word64
- Rattletrap: [word8leValue] :: Word8le -> Word8
- Rattletrap: data AppliedDamageAttribute
- Rattletrap: data Attribute
- Rattletrap: data AttributeMapping
- Rattletrap: data AttributeType
- Rattletrap: data AttributeValue
- Rattletrap: data Cache
- Rattletrap: data CamSettingsAttribute
- Rattletrap: data ClassAttributeMap
- Rattletrap: data ClassMapping
- Rattletrap: data ClubColorsAttribute
- Rattletrap: data CompressedWord
- Rattletrap: data CompressedWordVector
- Rattletrap: data Content
- Rattletrap: data DamageStateAttribute
- Rattletrap: data DemolishAttribute
- Rattletrap: data DestroyedReplication
- Rattletrap: data Dictionary a
- Rattletrap: data ExplosionAttribute
- Rattletrap: data ExtendedExplosionAttribute
- Rattletrap: data FlaggedIntAttribute
- Rattletrap: data Frame
- Rattletrap: data GameModeAttribute
- Rattletrap: data Header
- Rattletrap: data Initialization
- Rattletrap: data Int8Vector
- Rattletrap: data KeyFrame
- Rattletrap: data LoadoutAttribute
- Rattletrap: data LoadoutsAttribute
- Rattletrap: data LoadoutsOnlineAttribute
- Rattletrap: data Mark
- Rattletrap: data Message
- Rattletrap: data MusicStingerAttribute
- Rattletrap: data PartyLeaderAttribute
- Rattletrap: data PickupAttribute
- Rattletrap: data PrivateMatchSettingsAttribute
- Rattletrap: data ProductAttribute
- Rattletrap: data Property
- Rattletrap: data PropertyValue a
- Rattletrap: data Quaternion
- Rattletrap: data RemoteId
- Rattletrap: data Replay content
- Rattletrap: data Replication
- Rattletrap: data ReplicationValue
- Rattletrap: data ReservationAttribute
- Rattletrap: data RigidBodyStateAttribute
- Rattletrap: data Rotation
- Rattletrap: data Section a
- Rattletrap: data SpawnedReplication
- Rattletrap: data StatEventAttribute
- Rattletrap: data TeamPaintAttribute
- Rattletrap: data TitleAttribute
- Rattletrap: data UniqueIdAttribute
- Rattletrap: data Vector
- Rattletrap: data WeldedInfoAttribute
- Rattletrap: newtype BooleanAttribute
- Rattletrap: newtype ByteAttribute
- Rattletrap: newtype EnumAttribute
- Rattletrap: newtype Float32le
- Rattletrap: newtype FloatAttribute
- Rattletrap: newtype Int32le
- Rattletrap: newtype Int64Attribute
- Rattletrap: newtype Int64le
- Rattletrap: newtype Int8le
- Rattletrap: newtype IntAttribute
- Rattletrap: newtype List a
- Rattletrap: newtype LoadoutOnlineAttribute
- Rattletrap: newtype LocationAttribute
- Rattletrap: newtype PlayerHistoryKeyAttribute
- Rattletrap: newtype QWordAttribute
- Rattletrap: newtype Str
- Rattletrap: newtype StringAttribute
- Rattletrap: newtype UpdatedReplication
- Rattletrap: newtype Word32le
- Rattletrap: newtype Word64le
- Rattletrap: newtype Word8le
+ Paths_rattletrap: getBinDir :: IO FilePath
+ Paths_rattletrap: getDataDir :: IO FilePath
+ Paths_rattletrap: getDataFileName :: FilePath -> IO FilePath
+ Paths_rattletrap: getDynLibDir :: IO FilePath
+ Paths_rattletrap: getLibDir :: IO FilePath
+ Paths_rattletrap: getLibexecDir :: IO FilePath
+ Paths_rattletrap: getSysconfDir :: IO FilePath
+ Paths_rattletrap: version :: Version
+ Rattletrap.BitGet: binaryGetToByteGet :: Get a -> ByteGet a
+ Rattletrap.BitGet: bits :: Bits a => Int -> BitGet a
+ Rattletrap.BitGet: bool :: BitGet Bool
+ Rattletrap.BitGet: byteString :: Int -> BitGet ByteString
+ Rattletrap.BitGet: fromByteGet :: ByteGet a -> Int -> BitGet a
+ Rattletrap.BitGet: toByteGet :: BitGet a -> ByteGet a
+ Rattletrap.BitGet: type BitGet = BitGet
+ Rattletrap.BitGet: word8 :: Int -> BitGet Word8
+ Rattletrap.BitPut: BitPut :: BitPut () -> BitPut
+ Rattletrap.BitPut: bits :: Bits a => Int -> a -> BitPut
+ Rattletrap.BitPut: bool :: Bool -> BitPut
+ Rattletrap.BitPut: byteString :: ByteString -> BitPut
+ Rattletrap.BitPut: fromBinaryBits :: BitPut () -> BitPut
+ Rattletrap.BitPut: fromBytePut :: BytePut -> BitPut
+ Rattletrap.BitPut: instance GHC.Base.Monoid Rattletrap.BitPut.BitPut
+ Rattletrap.BitPut: instance GHC.Base.Semigroup Rattletrap.BitPut.BitPut
+ Rattletrap.BitPut: newtype BitPut
+ Rattletrap.BitPut: toBinaryBits :: BitPut -> BitPut ()
+ Rattletrap.BitPut: toBytePut :: BitPut -> BytePut
+ Rattletrap.BitPut: word8 :: Int -> Word8 -> BitPut
+ Rattletrap.ByteGet: byteString :: Int -> ByteGet ByteString
+ Rattletrap.ByteGet: float :: ByteGet Float
+ Rattletrap.ByteGet: int32 :: ByteGet Int32
+ Rattletrap.ByteGet: int64 :: ByteGet Int64
+ Rattletrap.ByteGet: int8 :: ByteGet Int8
+ Rattletrap.ByteGet: remaining :: ByteGet ByteString
+ Rattletrap.ByteGet: run :: ByteGet a -> ByteString -> Either String a
+ Rattletrap.ByteGet: type ByteGet = Get ByteString Identity
+ Rattletrap.ByteGet: word32 :: ByteGet Word32
+ Rattletrap.ByteGet: word64 :: ByteGet Word64
+ Rattletrap.ByteGet: word8 :: ByteGet Word8
+ Rattletrap.BytePut: byteString :: ByteString -> BytePut
+ Rattletrap.BytePut: float :: Float -> BytePut
+ Rattletrap.BytePut: int32 :: Int32 -> BytePut
+ Rattletrap.BytePut: int64 :: Int64 -> BytePut
+ Rattletrap.BytePut: int8 :: Int8 -> BytePut
+ Rattletrap.BytePut: toByteString :: BytePut -> ByteString
+ Rattletrap.BytePut: toLazyByteString :: BytePut -> ByteString
+ Rattletrap.BytePut: type BytePut = Builder
+ Rattletrap.BytePut: word32 :: Word32 -> BytePut
+ Rattletrap.BytePut: word64 :: Word64 -> BytePut
+ Rattletrap.BytePut: word8 :: Word8 -> BytePut
+ Rattletrap.Console.Config: Config :: Bool -> Bool -> Bool -> Maybe String -> Maybe Mode -> Maybe String -> Bool -> Bool -> Bool -> Config
+ Rattletrap.Console.Config: [compact] :: Config -> Bool
+ Rattletrap.Console.Config: [fast] :: Config -> Bool
+ Rattletrap.Console.Config: [help] :: Config -> Bool
+ Rattletrap.Console.Config: [input] :: Config -> Maybe String
+ Rattletrap.Console.Config: [mode] :: Config -> Maybe Mode
+ Rattletrap.Console.Config: [output] :: Config -> Maybe String
+ Rattletrap.Console.Config: [schema] :: Config -> Bool
+ Rattletrap.Console.Config: [skipCrc] :: Config -> Bool
+ Rattletrap.Console.Config: [version] :: Config -> Bool
+ Rattletrap.Console.Config: applyFlag :: Config -> Flag -> Either String Config
+ Rattletrap.Console.Config: data Config
+ Rattletrap.Console.Config: getMode :: Config -> Mode
+ Rattletrap.Console.Config: initial :: Config
+ Rattletrap.Console.Config: instance GHC.Classes.Eq Rattletrap.Console.Config.Config
+ Rattletrap.Console.Config: instance GHC.Show.Show Rattletrap.Console.Config.Config
+ Rattletrap.Console.Flag: Compact :: Flag
+ Rattletrap.Console.Flag: Fast :: Flag
+ Rattletrap.Console.Flag: Help :: Flag
+ Rattletrap.Console.Flag: Input :: FilePath -> Flag
+ Rattletrap.Console.Flag: Mode :: String -> Flag
+ Rattletrap.Console.Flag: Output :: FilePath -> Flag
+ Rattletrap.Console.Flag: Schema :: Flag
+ Rattletrap.Console.Flag: SkipCrc :: Flag
+ Rattletrap.Console.Flag: Version :: Flag
+ Rattletrap.Console.Flag: data Flag
+ Rattletrap.Console.Flag: instance GHC.Classes.Eq Rattletrap.Console.Flag.Flag
+ Rattletrap.Console.Flag: instance GHC.Show.Show Rattletrap.Console.Flag.Flag
+ Rattletrap.Console.Main: main :: IO ()
+ Rattletrap.Console.Main: rattletrap :: String -> [String] -> IO ()
+ Rattletrap.Console.Mode: Decode :: Mode
+ Rattletrap.Console.Mode: Encode :: Mode
+ Rattletrap.Console.Mode: data Mode
+ Rattletrap.Console.Mode: fromString :: String -> Either String Mode
+ Rattletrap.Console.Mode: instance GHC.Classes.Eq Rattletrap.Console.Mode.Mode
+ Rattletrap.Console.Mode: instance GHC.Show.Show Rattletrap.Console.Mode.Mode
+ Rattletrap.Console.Option: all :: [Option]
+ Rattletrap.Console.Option: compact :: Option
+ Rattletrap.Console.Option: fast :: Option
+ Rattletrap.Console.Option: help :: Option
+ Rattletrap.Console.Option: input :: Option
+ Rattletrap.Console.Option: mode :: Option
+ Rattletrap.Console.Option: output :: Option
+ Rattletrap.Console.Option: schema :: Option
+ Rattletrap.Console.Option: skipCrc :: Option
+ Rattletrap.Console.Option: type Option = OptDescr Flag
+ Rattletrap.Console.Option: version :: Option
+ Rattletrap.Data: attributeTypes :: Map Text AttributeType
+ Rattletrap.Data: classesWithLocation :: Set Text
+ Rattletrap.Data: classesWithRotation :: Set Text
+ Rattletrap.Data: objectClasses :: Map Text Text
+ Rattletrap.Data: parentClasses :: Map Text Text
+ Rattletrap.Get: Get :: (s -> m (Either String (s, a))) -> Get s m a
+ Rattletrap.Get: get :: Applicative m => Get s m s
+ Rattletrap.Get: instance GHC.Base.Functor m => GHC.Base.Functor (Rattletrap.Get.Get s m)
+ Rattletrap.Get: instance GHC.Base.Monad m => Control.Monad.Fail.MonadFail (Rattletrap.Get.Get s m)
+ Rattletrap.Get: instance GHC.Base.Monad m => GHC.Base.Alternative (Rattletrap.Get.Get s m)
+ Rattletrap.Get: instance GHC.Base.Monad m => GHC.Base.Applicative (Rattletrap.Get.Get s m)
+ Rattletrap.Get: instance GHC.Base.Monad m => GHC.Base.Monad (Rattletrap.Get.Get s m)
+ Rattletrap.Get: lift :: Functor m => m a -> Get s m a
+ Rattletrap.Get: newtype Get s m a
+ Rattletrap.Get: put :: Applicative m => s -> Get s m ()
+ Rattletrap.Get: run :: Get s m a -> s -> m (Either String (s, a))
+ Rattletrap.Schema: Schema :: Text -> Value -> Schema
+ Rattletrap.Schema: [json] :: Schema -> Value
+ Rattletrap.Schema: [name] :: Schema -> Text
+ Rattletrap.Schema: array :: Schema -> Schema
+ Rattletrap.Schema: boolean :: Schema
+ Rattletrap.Schema: data Schema
+ Rattletrap.Schema: instance GHC.Classes.Eq Rattletrap.Schema.Schema
+ Rattletrap.Schema: instance GHC.Show.Show Rattletrap.Schema.Schema
+ Rattletrap.Schema: integer :: Schema
+ Rattletrap.Schema: maybe :: Schema -> Schema
+ Rattletrap.Schema: named :: String -> Value -> Schema
+ Rattletrap.Schema: null :: Schema
+ Rattletrap.Schema: number :: Schema
+ Rattletrap.Schema: object :: [((Text, Value), Bool)] -> Value
+ Rattletrap.Schema: oneOf :: [Value] -> Value
+ Rattletrap.Schema: ref :: Schema -> Value
+ Rattletrap.Schema: string :: Schema
+ Rattletrap.Schema: tuple :: [Value] -> Value
+ Rattletrap.Type.Attribute: Attribute :: CompressedWord -> Str -> AttributeValue -> Attribute
+ Rattletrap.Type.Attribute: [id] :: Attribute -> CompressedWord
+ Rattletrap.Type.Attribute: [name] :: Attribute -> Str
+ Rattletrap.Type.Attribute: [value] :: Attribute -> AttributeValue
+ Rattletrap.Type.Attribute: bitGet :: Version -> ClassAttributeMap -> Map CompressedWord U32 -> CompressedWord -> BitGet Attribute
+ Rattletrap.Type.Attribute: bitPut :: Attribute -> BitPut
+ Rattletrap.Type.Attribute: data Attribute
+ Rattletrap.Type.Attribute: fromMaybe :: String -> Maybe a -> BitGet a
+ Rattletrap.Type.Attribute: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.Attribute
+ Rattletrap.Type.Attribute: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.Attribute
+ Rattletrap.Type.Attribute: instance GHC.Classes.Eq Rattletrap.Type.Attribute.Attribute
+ Rattletrap.Type.Attribute: instance GHC.Show.Show Rattletrap.Type.Attribute.Attribute
+ Rattletrap.Type.Attribute: lookupAttributeIdLimit :: Map U32 U32 -> CompressedWord -> BitGet Word
+ Rattletrap.Type.Attribute: lookupAttributeMap :: ClassAttributeMap -> Map CompressedWord U32 -> CompressedWord -> BitGet (Map U32 U32)
+ Rattletrap.Type.Attribute: lookupAttributeName :: ClassAttributeMap -> Map U32 U32 -> CompressedWord -> BitGet Str
+ Rattletrap.Type.Attribute: schema :: Schema
+ Rattletrap.Type.Attribute.AppliedDamage: AppliedDamage :: U8 -> Vector -> I32 -> I32 -> AppliedDamage
+ Rattletrap.Type.Attribute.AppliedDamage: [location] :: AppliedDamage -> Vector
+ Rattletrap.Type.Attribute.AppliedDamage: [unknown1] :: AppliedDamage -> U8
+ Rattletrap.Type.Attribute.AppliedDamage: [unknown3] :: AppliedDamage -> I32
+ Rattletrap.Type.Attribute.AppliedDamage: [unknown4] :: AppliedDamage -> I32
+ Rattletrap.Type.Attribute.AppliedDamage: bitGet :: Version -> BitGet AppliedDamage
+ Rattletrap.Type.Attribute.AppliedDamage: bitPut :: AppliedDamage -> BitPut
+ Rattletrap.Type.Attribute.AppliedDamage: data AppliedDamage
+ Rattletrap.Type.Attribute.AppliedDamage: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.AppliedDamage.AppliedDamage
+ Rattletrap.Type.Attribute.AppliedDamage: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.AppliedDamage.AppliedDamage
+ Rattletrap.Type.Attribute.AppliedDamage: instance GHC.Classes.Eq Rattletrap.Type.Attribute.AppliedDamage.AppliedDamage
+ Rattletrap.Type.Attribute.AppliedDamage: instance GHC.Show.Show Rattletrap.Type.Attribute.AppliedDamage.AppliedDamage
+ Rattletrap.Type.Attribute.AppliedDamage: schema :: Schema
+ Rattletrap.Type.Attribute.Boolean: Boolean :: Bool -> Boolean
+ Rattletrap.Type.Attribute.Boolean: [value] :: Boolean -> Bool
+ Rattletrap.Type.Attribute.Boolean: bitGet :: BitGet Boolean
+ Rattletrap.Type.Attribute.Boolean: bitPut :: Boolean -> BitPut
+ Rattletrap.Type.Attribute.Boolean: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.Boolean.Boolean
+ Rattletrap.Type.Attribute.Boolean: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.Boolean.Boolean
+ Rattletrap.Type.Attribute.Boolean: instance GHC.Classes.Eq Rattletrap.Type.Attribute.Boolean.Boolean
+ Rattletrap.Type.Attribute.Boolean: instance GHC.Show.Show Rattletrap.Type.Attribute.Boolean.Boolean
+ Rattletrap.Type.Attribute.Boolean: newtype Boolean
+ Rattletrap.Type.Attribute.Boolean: schema :: Schema
+ Rattletrap.Type.Attribute.Byte: Byte :: U8 -> Byte
+ Rattletrap.Type.Attribute.Byte: [value] :: Byte -> U8
+ Rattletrap.Type.Attribute.Byte: bitGet :: BitGet Byte
+ Rattletrap.Type.Attribute.Byte: bitPut :: Byte -> BitPut
+ Rattletrap.Type.Attribute.Byte: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.Byte.Byte
+ Rattletrap.Type.Attribute.Byte: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.Byte.Byte
+ Rattletrap.Type.Attribute.Byte: instance GHC.Classes.Eq Rattletrap.Type.Attribute.Byte.Byte
+ Rattletrap.Type.Attribute.Byte: instance GHC.Show.Show Rattletrap.Type.Attribute.Byte.Byte
+ Rattletrap.Type.Attribute.Byte: newtype Byte
+ Rattletrap.Type.Attribute.Byte: schema :: Schema
+ Rattletrap.Type.Attribute.CamSettings: CamSettings :: F32 -> F32 -> F32 -> F32 -> F32 -> F32 -> Maybe F32 -> CamSettings
+ Rattletrap.Type.Attribute.CamSettings: [angle] :: CamSettings -> F32
+ Rattletrap.Type.Attribute.CamSettings: [distance] :: CamSettings -> F32
+ Rattletrap.Type.Attribute.CamSettings: [fov] :: CamSettings -> F32
+ Rattletrap.Type.Attribute.CamSettings: [height] :: CamSettings -> F32
+ Rattletrap.Type.Attribute.CamSettings: [stiffness] :: CamSettings -> F32
+ Rattletrap.Type.Attribute.CamSettings: [swivelSpeed] :: CamSettings -> F32
+ Rattletrap.Type.Attribute.CamSettings: [transitionSpeed] :: CamSettings -> Maybe F32
+ Rattletrap.Type.Attribute.CamSettings: bitGet :: Version -> BitGet CamSettings
+ Rattletrap.Type.Attribute.CamSettings: bitPut :: CamSettings -> BitPut
+ Rattletrap.Type.Attribute.CamSettings: data CamSettings
+ Rattletrap.Type.Attribute.CamSettings: hasTransitionSpeed :: Version -> Bool
+ Rattletrap.Type.Attribute.CamSettings: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.CamSettings.CamSettings
+ Rattletrap.Type.Attribute.CamSettings: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.CamSettings.CamSettings
+ Rattletrap.Type.Attribute.CamSettings: instance GHC.Classes.Eq Rattletrap.Type.Attribute.CamSettings.CamSettings
+ Rattletrap.Type.Attribute.CamSettings: instance GHC.Show.Show Rattletrap.Type.Attribute.CamSettings.CamSettings
+ Rattletrap.Type.Attribute.CamSettings: schema :: Schema
+ Rattletrap.Type.Attribute.ClubColors: ClubColors :: Bool -> U8 -> Bool -> U8 -> ClubColors
+ Rattletrap.Type.Attribute.ClubColors: [blueColor] :: ClubColors -> U8
+ Rattletrap.Type.Attribute.ClubColors: [blueFlag] :: ClubColors -> Bool
+ Rattletrap.Type.Attribute.ClubColors: [orangeColor] :: ClubColors -> U8
+ Rattletrap.Type.Attribute.ClubColors: [orangeFlag] :: ClubColors -> Bool
+ Rattletrap.Type.Attribute.ClubColors: bitGet :: BitGet ClubColors
+ Rattletrap.Type.Attribute.ClubColors: bitPut :: ClubColors -> BitPut
+ Rattletrap.Type.Attribute.ClubColors: data ClubColors
+ Rattletrap.Type.Attribute.ClubColors: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.ClubColors.ClubColors
+ Rattletrap.Type.Attribute.ClubColors: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.ClubColors.ClubColors
+ Rattletrap.Type.Attribute.ClubColors: instance GHC.Classes.Eq Rattletrap.Type.Attribute.ClubColors.ClubColors
+ Rattletrap.Type.Attribute.ClubColors: instance GHC.Show.Show Rattletrap.Type.Attribute.ClubColors.ClubColors
+ Rattletrap.Type.Attribute.ClubColors: schema :: Schema
+ Rattletrap.Type.Attribute.CustomDemolish: CustomDemolish :: Bool -> I32 -> Demolish -> CustomDemolish
+ Rattletrap.Type.Attribute.CustomDemolish: [demolish] :: CustomDemolish -> Demolish
+ Rattletrap.Type.Attribute.CustomDemolish: [flag] :: CustomDemolish -> Bool
+ Rattletrap.Type.Attribute.CustomDemolish: [id] :: CustomDemolish -> I32
+ Rattletrap.Type.Attribute.CustomDemolish: bitGet :: Version -> BitGet CustomDemolish
+ Rattletrap.Type.Attribute.CustomDemolish: bitPut :: CustomDemolish -> BitPut
+ Rattletrap.Type.Attribute.CustomDemolish: data CustomDemolish
+ Rattletrap.Type.Attribute.CustomDemolish: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.CustomDemolish.CustomDemolish
+ Rattletrap.Type.Attribute.CustomDemolish: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.CustomDemolish.CustomDemolish
+ Rattletrap.Type.Attribute.CustomDemolish: instance GHC.Classes.Eq Rattletrap.Type.Attribute.CustomDemolish.CustomDemolish
+ Rattletrap.Type.Attribute.CustomDemolish: instance GHC.Show.Show Rattletrap.Type.Attribute.CustomDemolish.CustomDemolish
+ Rattletrap.Type.Attribute.CustomDemolish: schema :: Schema
+ Rattletrap.Type.Attribute.DamageState: DamageState :: U8 -> Bool -> I32 -> Vector -> Bool -> Bool -> DamageState
+ Rattletrap.Type.Attribute.DamageState: [unknown1] :: DamageState -> U8
+ Rattletrap.Type.Attribute.DamageState: [unknown2] :: DamageState -> Bool
+ Rattletrap.Type.Attribute.DamageState: [unknown3] :: DamageState -> I32
+ Rattletrap.Type.Attribute.DamageState: [unknown4] :: DamageState -> Vector
+ Rattletrap.Type.Attribute.DamageState: [unknown5] :: DamageState -> Bool
+ Rattletrap.Type.Attribute.DamageState: [unknown6] :: DamageState -> Bool
+ Rattletrap.Type.Attribute.DamageState: bitGet :: Version -> BitGet DamageState
+ Rattletrap.Type.Attribute.DamageState: bitPut :: DamageState -> BitPut
+ Rattletrap.Type.Attribute.DamageState: data DamageState
+ Rattletrap.Type.Attribute.DamageState: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.DamageState.DamageState
+ Rattletrap.Type.Attribute.DamageState: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.DamageState.DamageState
+ Rattletrap.Type.Attribute.DamageState: instance GHC.Classes.Eq Rattletrap.Type.Attribute.DamageState.DamageState
+ Rattletrap.Type.Attribute.DamageState: instance GHC.Show.Show Rattletrap.Type.Attribute.DamageState.DamageState
+ Rattletrap.Type.Attribute.DamageState: schema :: Schema
+ Rattletrap.Type.Attribute.Demolish: Demolish :: Bool -> U32 -> Bool -> U32 -> Vector -> Vector -> Demolish
+ Rattletrap.Type.Attribute.Demolish: [attackerActorId] :: Demolish -> U32
+ Rattletrap.Type.Attribute.Demolish: [attackerFlag] :: Demolish -> Bool
+ Rattletrap.Type.Attribute.Demolish: [attackerVelocity] :: Demolish -> Vector
+ Rattletrap.Type.Attribute.Demolish: [victimActorId] :: Demolish -> U32
+ Rattletrap.Type.Attribute.Demolish: [victimFlag] :: Demolish -> Bool
+ Rattletrap.Type.Attribute.Demolish: [victimVelocity] :: Demolish -> Vector
+ Rattletrap.Type.Attribute.Demolish: bitGet :: Version -> BitGet Demolish
+ Rattletrap.Type.Attribute.Demolish: bitPut :: Demolish -> BitPut
+ Rattletrap.Type.Attribute.Demolish: data Demolish
+ Rattletrap.Type.Attribute.Demolish: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.Demolish.Demolish
+ Rattletrap.Type.Attribute.Demolish: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.Demolish.Demolish
+ Rattletrap.Type.Attribute.Demolish: instance GHC.Classes.Eq Rattletrap.Type.Attribute.Demolish.Demolish
+ Rattletrap.Type.Attribute.Demolish: instance GHC.Show.Show Rattletrap.Type.Attribute.Demolish.Demolish
+ Rattletrap.Type.Attribute.Demolish: schema :: Schema
+ Rattletrap.Type.Attribute.Enum: Enum :: Word16 -> Enum
+ Rattletrap.Type.Attribute.Enum: [value] :: Enum -> Word16
+ Rattletrap.Type.Attribute.Enum: bitGet :: BitGet Enum
+ Rattletrap.Type.Attribute.Enum: bitPut :: Enum -> BitPut
+ Rattletrap.Type.Attribute.Enum: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.Enum.Enum
+ Rattletrap.Type.Attribute.Enum: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.Enum.Enum
+ Rattletrap.Type.Attribute.Enum: instance GHC.Classes.Eq Rattletrap.Type.Attribute.Enum.Enum
+ Rattletrap.Type.Attribute.Enum: instance GHC.Show.Show Rattletrap.Type.Attribute.Enum.Enum
+ Rattletrap.Type.Attribute.Enum: newtype Enum
+ Rattletrap.Type.Attribute.Enum: schema :: Schema
+ Rattletrap.Type.Attribute.Explosion: Explosion :: Bool -> I32 -> Vector -> Explosion
+ Rattletrap.Type.Attribute.Explosion: [actorId] :: Explosion -> I32
+ Rattletrap.Type.Attribute.Explosion: [flag] :: Explosion -> Bool
+ Rattletrap.Type.Attribute.Explosion: [location] :: Explosion -> Vector
+ Rattletrap.Type.Attribute.Explosion: bitGet :: Version -> BitGet Explosion
+ Rattletrap.Type.Attribute.Explosion: bitPut :: Explosion -> BitPut
+ Rattletrap.Type.Attribute.Explosion: data Explosion
+ Rattletrap.Type.Attribute.Explosion: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.Explosion.Explosion
+ Rattletrap.Type.Attribute.Explosion: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.Explosion.Explosion
+ Rattletrap.Type.Attribute.Explosion: instance GHC.Classes.Eq Rattletrap.Type.Attribute.Explosion.Explosion
+ Rattletrap.Type.Attribute.Explosion: instance GHC.Show.Show Rattletrap.Type.Attribute.Explosion.Explosion
+ Rattletrap.Type.Attribute.Explosion: schema :: Schema
+ Rattletrap.Type.Attribute.ExtendedExplosion: ExtendedExplosion :: Explosion -> FlaggedInt -> ExtendedExplosion
+ Rattletrap.Type.Attribute.ExtendedExplosion: [explosion] :: ExtendedExplosion -> Explosion
+ Rattletrap.Type.Attribute.ExtendedExplosion: [unknown] :: ExtendedExplosion -> FlaggedInt
+ Rattletrap.Type.Attribute.ExtendedExplosion: bitGet :: Version -> BitGet ExtendedExplosion
+ Rattletrap.Type.Attribute.ExtendedExplosion: bitPut :: ExtendedExplosion -> BitPut
+ Rattletrap.Type.Attribute.ExtendedExplosion: data ExtendedExplosion
+ Rattletrap.Type.Attribute.ExtendedExplosion: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.ExtendedExplosion.ExtendedExplosion
+ Rattletrap.Type.Attribute.ExtendedExplosion: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.ExtendedExplosion.ExtendedExplosion
+ Rattletrap.Type.Attribute.ExtendedExplosion: instance GHC.Classes.Eq Rattletrap.Type.Attribute.ExtendedExplosion.ExtendedExplosion
+ Rattletrap.Type.Attribute.ExtendedExplosion: instance GHC.Show.Show Rattletrap.Type.Attribute.ExtendedExplosion.ExtendedExplosion
+ Rattletrap.Type.Attribute.ExtendedExplosion: schema :: Schema
+ Rattletrap.Type.Attribute.FlaggedByte: FlaggedByte :: Bool -> U8 -> FlaggedByte
+ Rattletrap.Type.Attribute.FlaggedByte: [byte] :: FlaggedByte -> U8
+ Rattletrap.Type.Attribute.FlaggedByte: [flag] :: FlaggedByte -> Bool
+ Rattletrap.Type.Attribute.FlaggedByte: bitGet :: BitGet FlaggedByte
+ Rattletrap.Type.Attribute.FlaggedByte: bitPut :: FlaggedByte -> BitPut
+ Rattletrap.Type.Attribute.FlaggedByte: data FlaggedByte
+ Rattletrap.Type.Attribute.FlaggedByte: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.FlaggedByte.FlaggedByte
+ Rattletrap.Type.Attribute.FlaggedByte: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.FlaggedByte.FlaggedByte
+ Rattletrap.Type.Attribute.FlaggedByte: instance GHC.Classes.Eq Rattletrap.Type.Attribute.FlaggedByte.FlaggedByte
+ Rattletrap.Type.Attribute.FlaggedByte: instance GHC.Show.Show Rattletrap.Type.Attribute.FlaggedByte.FlaggedByte
+ Rattletrap.Type.Attribute.FlaggedByte: schema :: Schema
+ Rattletrap.Type.Attribute.FlaggedInt: FlaggedInt :: Bool -> I32 -> FlaggedInt
+ Rattletrap.Type.Attribute.FlaggedInt: [flag] :: FlaggedInt -> Bool
+ Rattletrap.Type.Attribute.FlaggedInt: [int] :: FlaggedInt -> I32
+ Rattletrap.Type.Attribute.FlaggedInt: bitGet :: BitGet FlaggedInt
+ Rattletrap.Type.Attribute.FlaggedInt: bitPut :: FlaggedInt -> BitPut
+ Rattletrap.Type.Attribute.FlaggedInt: data FlaggedInt
+ Rattletrap.Type.Attribute.FlaggedInt: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.FlaggedInt.FlaggedInt
+ Rattletrap.Type.Attribute.FlaggedInt: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.FlaggedInt.FlaggedInt
+ Rattletrap.Type.Attribute.FlaggedInt: instance GHC.Classes.Eq Rattletrap.Type.Attribute.FlaggedInt.FlaggedInt
+ Rattletrap.Type.Attribute.FlaggedInt: instance GHC.Show.Show Rattletrap.Type.Attribute.FlaggedInt.FlaggedInt
+ Rattletrap.Type.Attribute.FlaggedInt: schema :: Schema
+ Rattletrap.Type.Attribute.Float: Float :: F32 -> Float
+ Rattletrap.Type.Attribute.Float: [value] :: Float -> F32
+ Rattletrap.Type.Attribute.Float: bitGet :: BitGet Float
+ Rattletrap.Type.Attribute.Float: bitPut :: Float -> BitPut
+ Rattletrap.Type.Attribute.Float: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.Float.Float
+ Rattletrap.Type.Attribute.Float: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.Float.Float
+ Rattletrap.Type.Attribute.Float: instance GHC.Classes.Eq Rattletrap.Type.Attribute.Float.Float
+ Rattletrap.Type.Attribute.Float: instance GHC.Show.Show Rattletrap.Type.Attribute.Float.Float
+ Rattletrap.Type.Attribute.Float: newtype Float
+ Rattletrap.Type.Attribute.Float: schema :: Schema
+ Rattletrap.Type.Attribute.GameMode: GameMode :: Int -> Word8 -> GameMode
+ Rattletrap.Type.Attribute.GameMode: [numBits] :: GameMode -> Int
+ Rattletrap.Type.Attribute.GameMode: [word] :: GameMode -> Word8
+ Rattletrap.Type.Attribute.GameMode: bitGet :: Version -> BitGet GameMode
+ Rattletrap.Type.Attribute.GameMode: bitPut :: GameMode -> BitPut
+ Rattletrap.Type.Attribute.GameMode: data GameMode
+ Rattletrap.Type.Attribute.GameMode: has8Bits :: Version -> Bool
+ Rattletrap.Type.Attribute.GameMode: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.GameMode.GameMode
+ Rattletrap.Type.Attribute.GameMode: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.GameMode.GameMode
+ Rattletrap.Type.Attribute.GameMode: instance GHC.Classes.Eq Rattletrap.Type.Attribute.GameMode.GameMode
+ Rattletrap.Type.Attribute.GameMode: instance GHC.Show.Show Rattletrap.Type.Attribute.GameMode.GameMode
+ Rattletrap.Type.Attribute.GameMode: numBits_ :: Version -> Int
+ Rattletrap.Type.Attribute.GameMode: schema :: Schema
+ Rattletrap.Type.Attribute.Int: Int :: I32 -> Int
+ Rattletrap.Type.Attribute.Int: [value] :: Int -> I32
+ Rattletrap.Type.Attribute.Int: bitGet :: BitGet Int
+ Rattletrap.Type.Attribute.Int: bitPut :: Int -> BitPut
+ Rattletrap.Type.Attribute.Int: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.Int.Int
+ Rattletrap.Type.Attribute.Int: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.Int.Int
+ Rattletrap.Type.Attribute.Int: instance GHC.Classes.Eq Rattletrap.Type.Attribute.Int.Int
+ Rattletrap.Type.Attribute.Int: instance GHC.Show.Show Rattletrap.Type.Attribute.Int.Int
+ Rattletrap.Type.Attribute.Int: newtype Int
+ Rattletrap.Type.Attribute.Int: schema :: Schema
+ Rattletrap.Type.Attribute.Int64: Int64 :: I64 -> Int64
+ Rattletrap.Type.Attribute.Int64: [value] :: Int64 -> I64
+ Rattletrap.Type.Attribute.Int64: bitGet :: BitGet Int64
+ Rattletrap.Type.Attribute.Int64: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.Int64.Int64
+ Rattletrap.Type.Attribute.Int64: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.Int64.Int64
+ Rattletrap.Type.Attribute.Int64: instance GHC.Classes.Eq Rattletrap.Type.Attribute.Int64.Int64
+ Rattletrap.Type.Attribute.Int64: instance GHC.Show.Show Rattletrap.Type.Attribute.Int64.Int64
+ Rattletrap.Type.Attribute.Int64: newtype Int64
+ Rattletrap.Type.Attribute.Int64: putInt64Attribute :: Int64 -> BitPut
+ Rattletrap.Type.Attribute.Int64: schema :: Schema
+ Rattletrap.Type.Attribute.Loadout: Loadout :: U8 -> U32 -> U32 -> U32 -> U32 -> U32 -> U32 -> U32 -> Maybe U32 -> Maybe U32 -> Maybe U32 -> Maybe U32 -> Maybe U32 -> Maybe U32 -> Maybe U32 -> Maybe U32 -> Maybe U32 -> Loadout
+ Rattletrap.Type.Attribute.Loadout: [antenna] :: Loadout -> U32
+ Rattletrap.Type.Attribute.Loadout: [banner] :: Loadout -> Maybe U32
+ Rattletrap.Type.Attribute.Loadout: [body] :: Loadout -> U32
+ Rattletrap.Type.Attribute.Loadout: [decal] :: Loadout -> U32
+ Rattletrap.Type.Attribute.Loadout: [engineAudio] :: Loadout -> Maybe U32
+ Rattletrap.Type.Attribute.Loadout: [goalExplosion] :: Loadout -> Maybe U32
+ Rattletrap.Type.Attribute.Loadout: [rocketTrail] :: Loadout -> U32
+ Rattletrap.Type.Attribute.Loadout: [topper] :: Loadout -> U32
+ Rattletrap.Type.Attribute.Loadout: [trail] :: Loadout -> Maybe U32
+ Rattletrap.Type.Attribute.Loadout: [unknown1] :: Loadout -> U32
+ Rattletrap.Type.Attribute.Loadout: [unknown2] :: Loadout -> Maybe U32
+ Rattletrap.Type.Attribute.Loadout: [unknown3] :: Loadout -> Maybe U32
+ Rattletrap.Type.Attribute.Loadout: [unknown4] :: Loadout -> Maybe U32
+ Rattletrap.Type.Attribute.Loadout: [unknown5] :: Loadout -> Maybe U32
+ Rattletrap.Type.Attribute.Loadout: [unknown6] :: Loadout -> Maybe U32
+ Rattletrap.Type.Attribute.Loadout: [version] :: Loadout -> U8
+ Rattletrap.Type.Attribute.Loadout: [wheels] :: Loadout -> U32
+ Rattletrap.Type.Attribute.Loadout: bitGet :: BitGet Loadout
+ Rattletrap.Type.Attribute.Loadout: bitPut :: Loadout -> BitPut
+ Rattletrap.Type.Attribute.Loadout: data Loadout
+ Rattletrap.Type.Attribute.Loadout: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.Loadout.Loadout
+ Rattletrap.Type.Attribute.Loadout: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.Loadout.Loadout
+ Rattletrap.Type.Attribute.Loadout: instance GHC.Classes.Eq Rattletrap.Type.Attribute.Loadout.Loadout
+ Rattletrap.Type.Attribute.Loadout: instance GHC.Show.Show Rattletrap.Type.Attribute.Loadout.Loadout
+ Rattletrap.Type.Attribute.Loadout: schema :: Schema
+ Rattletrap.Type.Attribute.LoadoutOnline: LoadoutOnline :: List (List Product) -> LoadoutOnline
+ Rattletrap.Type.Attribute.LoadoutOnline: [value] :: LoadoutOnline -> List (List Product)
+ Rattletrap.Type.Attribute.LoadoutOnline: bitGet :: Version -> Map U32 Str -> BitGet LoadoutOnline
+ Rattletrap.Type.Attribute.LoadoutOnline: bitPut :: LoadoutOnline -> BitPut
+ Rattletrap.Type.Attribute.LoadoutOnline: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.LoadoutOnline.LoadoutOnline
+ Rattletrap.Type.Attribute.LoadoutOnline: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.LoadoutOnline.LoadoutOnline
+ Rattletrap.Type.Attribute.LoadoutOnline: instance GHC.Classes.Eq Rattletrap.Type.Attribute.LoadoutOnline.LoadoutOnline
+ Rattletrap.Type.Attribute.LoadoutOnline: instance GHC.Show.Show Rattletrap.Type.Attribute.LoadoutOnline.LoadoutOnline
+ Rattletrap.Type.Attribute.LoadoutOnline: newtype LoadoutOnline
+ Rattletrap.Type.Attribute.LoadoutOnline: schema :: Schema
+ Rattletrap.Type.Attribute.Loadouts: Loadouts :: Loadout -> Loadout -> Loadouts
+ Rattletrap.Type.Attribute.Loadouts: [blue] :: Loadouts -> Loadout
+ Rattletrap.Type.Attribute.Loadouts: [orange] :: Loadouts -> Loadout
+ Rattletrap.Type.Attribute.Loadouts: bitGet :: BitGet Loadouts
+ Rattletrap.Type.Attribute.Loadouts: bitPut :: Loadouts -> BitPut
+ Rattletrap.Type.Attribute.Loadouts: data Loadouts
+ Rattletrap.Type.Attribute.Loadouts: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.Loadouts.Loadouts
+ Rattletrap.Type.Attribute.Loadouts: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.Loadouts.Loadouts
+ Rattletrap.Type.Attribute.Loadouts: instance GHC.Classes.Eq Rattletrap.Type.Attribute.Loadouts.Loadouts
+ Rattletrap.Type.Attribute.Loadouts: instance GHC.Show.Show Rattletrap.Type.Attribute.Loadouts.Loadouts
+ Rattletrap.Type.Attribute.Loadouts: schema :: Schema
+ Rattletrap.Type.Attribute.LoadoutsOnline: LoadoutsOnline :: LoadoutOnline -> LoadoutOnline -> Bool -> Bool -> LoadoutsOnline
+ Rattletrap.Type.Attribute.LoadoutsOnline: [blue] :: LoadoutsOnline -> LoadoutOnline
+ Rattletrap.Type.Attribute.LoadoutsOnline: [orange] :: LoadoutsOnline -> LoadoutOnline
+ Rattletrap.Type.Attribute.LoadoutsOnline: [unknown1] :: LoadoutsOnline -> Bool
+ Rattletrap.Type.Attribute.LoadoutsOnline: [unknown2] :: LoadoutsOnline -> Bool
+ Rattletrap.Type.Attribute.LoadoutsOnline: bitGet :: Version -> Map U32 Str -> BitGet LoadoutsOnline
+ Rattletrap.Type.Attribute.LoadoutsOnline: bitPut :: LoadoutsOnline -> BitPut
+ Rattletrap.Type.Attribute.LoadoutsOnline: data LoadoutsOnline
+ Rattletrap.Type.Attribute.LoadoutsOnline: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.LoadoutsOnline.LoadoutsOnline
+ Rattletrap.Type.Attribute.LoadoutsOnline: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.LoadoutsOnline.LoadoutsOnline
+ Rattletrap.Type.Attribute.LoadoutsOnline: instance GHC.Classes.Eq Rattletrap.Type.Attribute.LoadoutsOnline.LoadoutsOnline
+ Rattletrap.Type.Attribute.LoadoutsOnline: instance GHC.Show.Show Rattletrap.Type.Attribute.LoadoutsOnline.LoadoutsOnline
+ Rattletrap.Type.Attribute.LoadoutsOnline: schema :: Schema
+ Rattletrap.Type.Attribute.Location: Location :: Vector -> Location
+ Rattletrap.Type.Attribute.Location: [value] :: Location -> Vector
+ Rattletrap.Type.Attribute.Location: bitGet :: Version -> BitGet Location
+ Rattletrap.Type.Attribute.Location: bitPut :: Location -> BitPut
+ Rattletrap.Type.Attribute.Location: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.Location.Location
+ Rattletrap.Type.Attribute.Location: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.Location.Location
+ Rattletrap.Type.Attribute.Location: instance GHC.Classes.Eq Rattletrap.Type.Attribute.Location.Location
+ Rattletrap.Type.Attribute.Location: instance GHC.Show.Show Rattletrap.Type.Attribute.Location.Location
+ Rattletrap.Type.Attribute.Location: newtype Location
+ Rattletrap.Type.Attribute.Location: schema :: Schema
+ Rattletrap.Type.Attribute.MusicStinger: MusicStinger :: Bool -> U32 -> U8 -> MusicStinger
+ Rattletrap.Type.Attribute.MusicStinger: [cue] :: MusicStinger -> U32
+ Rattletrap.Type.Attribute.MusicStinger: [flag] :: MusicStinger -> Bool
+ Rattletrap.Type.Attribute.MusicStinger: [trigger] :: MusicStinger -> U8
+ Rattletrap.Type.Attribute.MusicStinger: bitGet :: BitGet MusicStinger
+ Rattletrap.Type.Attribute.MusicStinger: bitPut :: MusicStinger -> BitPut
+ Rattletrap.Type.Attribute.MusicStinger: data MusicStinger
+ Rattletrap.Type.Attribute.MusicStinger: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.MusicStinger.MusicStinger
+ Rattletrap.Type.Attribute.MusicStinger: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.MusicStinger.MusicStinger
+ Rattletrap.Type.Attribute.MusicStinger: instance GHC.Classes.Eq Rattletrap.Type.Attribute.MusicStinger.MusicStinger
+ Rattletrap.Type.Attribute.MusicStinger: instance GHC.Show.Show Rattletrap.Type.Attribute.MusicStinger.MusicStinger
+ Rattletrap.Type.Attribute.MusicStinger: schema :: Schema
+ Rattletrap.Type.Attribute.PartyLeader: PartyLeader :: U8 -> Maybe (RemoteId, U8) -> PartyLeader
+ Rattletrap.Type.Attribute.PartyLeader: [id] :: PartyLeader -> Maybe (RemoteId, U8)
+ Rattletrap.Type.Attribute.PartyLeader: [systemId] :: PartyLeader -> U8
+ Rattletrap.Type.Attribute.PartyLeader: bitGet :: Version -> BitGet PartyLeader
+ Rattletrap.Type.Attribute.PartyLeader: bitPut :: PartyLeader -> BitPut
+ Rattletrap.Type.Attribute.PartyLeader: data PartyLeader
+ Rattletrap.Type.Attribute.PartyLeader: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.PartyLeader.PartyLeader
+ Rattletrap.Type.Attribute.PartyLeader: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.PartyLeader.PartyLeader
+ Rattletrap.Type.Attribute.PartyLeader: instance GHC.Classes.Eq Rattletrap.Type.Attribute.PartyLeader.PartyLeader
+ Rattletrap.Type.Attribute.PartyLeader: instance GHC.Show.Show Rattletrap.Type.Attribute.PartyLeader.PartyLeader
+ Rattletrap.Type.Attribute.PartyLeader: schema :: Schema
+ Rattletrap.Type.Attribute.Pickup: Pickup :: Maybe U32 -> Bool -> Pickup
+ Rattletrap.Type.Attribute.Pickup: [instigatorId] :: Pickup -> Maybe U32
+ Rattletrap.Type.Attribute.Pickup: [pickedUp] :: Pickup -> Bool
+ Rattletrap.Type.Attribute.Pickup: bitGet :: BitGet Pickup
+ Rattletrap.Type.Attribute.Pickup: bitPut :: Pickup -> BitPut
+ Rattletrap.Type.Attribute.Pickup: data Pickup
+ Rattletrap.Type.Attribute.Pickup: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.Pickup.Pickup
+ Rattletrap.Type.Attribute.Pickup: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.Pickup.Pickup
+ Rattletrap.Type.Attribute.Pickup: instance GHC.Classes.Eq Rattletrap.Type.Attribute.Pickup.Pickup
+ Rattletrap.Type.Attribute.Pickup: instance GHC.Show.Show Rattletrap.Type.Attribute.Pickup.Pickup
+ Rattletrap.Type.Attribute.Pickup: schema :: Schema
+ Rattletrap.Type.Attribute.PickupNew: PickupNew :: Maybe U32 -> U8 -> PickupNew
+ Rattletrap.Type.Attribute.PickupNew: [instigatorId] :: PickupNew -> Maybe U32
+ Rattletrap.Type.Attribute.PickupNew: [pickedUp] :: PickupNew -> U8
+ Rattletrap.Type.Attribute.PickupNew: bitGet :: BitGet PickupNew
+ Rattletrap.Type.Attribute.PickupNew: bitPut :: PickupNew -> BitPut
+ Rattletrap.Type.Attribute.PickupNew: data PickupNew
+ Rattletrap.Type.Attribute.PickupNew: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.PickupNew.PickupNew
+ Rattletrap.Type.Attribute.PickupNew: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.PickupNew.PickupNew
+ Rattletrap.Type.Attribute.PickupNew: instance GHC.Classes.Eq Rattletrap.Type.Attribute.PickupNew.PickupNew
+ Rattletrap.Type.Attribute.PickupNew: instance GHC.Show.Show Rattletrap.Type.Attribute.PickupNew.PickupNew
+ Rattletrap.Type.Attribute.PickupNew: schema :: Schema
+ Rattletrap.Type.Attribute.PlayerHistoryKey: PlayerHistoryKey :: Word16 -> PlayerHistoryKey
+ Rattletrap.Type.Attribute.PlayerHistoryKey: [unknown] :: PlayerHistoryKey -> Word16
+ Rattletrap.Type.Attribute.PlayerHistoryKey: bitGet :: BitGet PlayerHistoryKey
+ Rattletrap.Type.Attribute.PlayerHistoryKey: bitPut :: PlayerHistoryKey -> BitPut
+ Rattletrap.Type.Attribute.PlayerHistoryKey: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.PlayerHistoryKey.PlayerHistoryKey
+ Rattletrap.Type.Attribute.PlayerHistoryKey: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.PlayerHistoryKey.PlayerHistoryKey
+ Rattletrap.Type.Attribute.PlayerHistoryKey: instance GHC.Classes.Eq Rattletrap.Type.Attribute.PlayerHistoryKey.PlayerHistoryKey
+ Rattletrap.Type.Attribute.PlayerHistoryKey: instance GHC.Show.Show Rattletrap.Type.Attribute.PlayerHistoryKey.PlayerHistoryKey
+ Rattletrap.Type.Attribute.PlayerHistoryKey: newtype PlayerHistoryKey
+ Rattletrap.Type.Attribute.PlayerHistoryKey: schema :: Schema
+ Rattletrap.Type.Attribute.PrivateMatchSettings: PrivateMatchSettings :: Str -> U32 -> U32 -> Str -> Str -> Bool -> PrivateMatchSettings
+ Rattletrap.Type.Attribute.PrivateMatchSettings: [flag] :: PrivateMatchSettings -> Bool
+ Rattletrap.Type.Attribute.PrivateMatchSettings: [gameName] :: PrivateMatchSettings -> Str
+ Rattletrap.Type.Attribute.PrivateMatchSettings: [joinableBy] :: PrivateMatchSettings -> U32
+ Rattletrap.Type.Attribute.PrivateMatchSettings: [maxPlayers] :: PrivateMatchSettings -> U32
+ Rattletrap.Type.Attribute.PrivateMatchSettings: [mutators] :: PrivateMatchSettings -> Str
+ Rattletrap.Type.Attribute.PrivateMatchSettings: [password] :: PrivateMatchSettings -> Str
+ Rattletrap.Type.Attribute.PrivateMatchSettings: bitGet :: BitGet PrivateMatchSettings
+ Rattletrap.Type.Attribute.PrivateMatchSettings: bitPut :: PrivateMatchSettings -> BitPut
+ Rattletrap.Type.Attribute.PrivateMatchSettings: data PrivateMatchSettings
+ Rattletrap.Type.Attribute.PrivateMatchSettings: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.PrivateMatchSettings.PrivateMatchSettings
+ Rattletrap.Type.Attribute.PrivateMatchSettings: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.PrivateMatchSettings.PrivateMatchSettings
+ Rattletrap.Type.Attribute.PrivateMatchSettings: instance GHC.Classes.Eq Rattletrap.Type.Attribute.PrivateMatchSettings.PrivateMatchSettings
+ Rattletrap.Type.Attribute.PrivateMatchSettings: instance GHC.Show.Show Rattletrap.Type.Attribute.PrivateMatchSettings.PrivateMatchSettings
+ Rattletrap.Type.Attribute.PrivateMatchSettings: schema :: Schema
+ Rattletrap.Type.Attribute.Product: Product :: Bool -> U32 -> Maybe Str -> ProductValue -> Product
+ Rattletrap.Type.Attribute.Product: [objectId] :: Product -> U32
+ Rattletrap.Type.Attribute.Product: [objectName] :: Product -> Maybe Str
+ Rattletrap.Type.Attribute.Product: [unknown] :: Product -> Bool
+ Rattletrap.Type.Attribute.Product: [value] :: Product -> ProductValue
+ Rattletrap.Type.Attribute.Product: bitGet :: Version -> Map U32 Str -> BitGet Product
+ Rattletrap.Type.Attribute.Product: bitPut :: Product -> BitPut
+ Rattletrap.Type.Attribute.Product: data Product
+ Rattletrap.Type.Attribute.Product: decodeProductAttributesBits :: Version -> Map U32 Str -> BitGet (List Product)
+ Rattletrap.Type.Attribute.Product: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.Product.Product
+ Rattletrap.Type.Attribute.Product: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.Product.Product
+ Rattletrap.Type.Attribute.Product: instance GHC.Classes.Eq Rattletrap.Type.Attribute.Product.Product
+ Rattletrap.Type.Attribute.Product: instance GHC.Show.Show Rattletrap.Type.Attribute.Product.Product
+ Rattletrap.Type.Attribute.Product: putProductAttributes :: List Product -> BitPut
+ Rattletrap.Type.Attribute.Product: schema :: Schema
+ Rattletrap.Type.Attribute.ProductValue: PaintedNew :: Word32 -> ProductValue
+ Rattletrap.Type.Attribute.ProductValue: PaintedOld :: CompressedWord -> ProductValue
+ Rattletrap.Type.Attribute.ProductValue: SpecialEdition :: Word32 -> ProductValue
+ Rattletrap.Type.Attribute.ProductValue: TeamEditionNew :: Word32 -> ProductValue
+ Rattletrap.Type.Attribute.ProductValue: TeamEditionOld :: CompressedWord -> ProductValue
+ Rattletrap.Type.Attribute.ProductValue: TitleId :: Str -> ProductValue
+ Rattletrap.Type.Attribute.ProductValue: UserColorNew :: U32 -> ProductValue
+ Rattletrap.Type.Attribute.ProductValue: UserColorOld :: Maybe Word32 -> ProductValue
+ Rattletrap.Type.Attribute.ProductValue: bitGet :: Version -> U32 -> Maybe Str -> BitGet ProductValue
+ Rattletrap.Type.Attribute.ProductValue: bitPut :: ProductValue -> BitPut
+ Rattletrap.Type.Attribute.ProductValue: data ProductValue
+ Rattletrap.Type.Attribute.ProductValue: decodeColor :: Version -> BitGet ProductValue
+ Rattletrap.Type.Attribute.ProductValue: decodePainted :: Version -> BitGet ProductValue
+ Rattletrap.Type.Attribute.ProductValue: decodeSpecialEdition :: BitGet ProductValue
+ Rattletrap.Type.Attribute.ProductValue: decodeTeamEdition :: Version -> BitGet ProductValue
+ Rattletrap.Type.Attribute.ProductValue: decodeTitle :: BitGet ProductValue
+ Rattletrap.Type.Attribute.ProductValue: hasNewColor :: Version -> Bool
+ Rattletrap.Type.Attribute.ProductValue: hasNewPainted :: Version -> Bool
+ Rattletrap.Type.Attribute.ProductValue: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.ProductValue.ProductValue
+ Rattletrap.Type.Attribute.ProductValue: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.ProductValue.ProductValue
+ Rattletrap.Type.Attribute.ProductValue: instance GHC.Classes.Eq Rattletrap.Type.Attribute.ProductValue.ProductValue
+ Rattletrap.Type.Attribute.ProductValue: instance GHC.Show.Show Rattletrap.Type.Attribute.ProductValue.ProductValue
+ Rattletrap.Type.Attribute.ProductValue: schema :: Schema
+ Rattletrap.Type.Attribute.QWord: QWord :: U64 -> QWord
+ Rattletrap.Type.Attribute.QWord: [value] :: QWord -> U64
+ Rattletrap.Type.Attribute.QWord: bitGet :: BitGet QWord
+ Rattletrap.Type.Attribute.QWord: bitPut :: QWord -> BitPut
+ Rattletrap.Type.Attribute.QWord: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.QWord.QWord
+ Rattletrap.Type.Attribute.QWord: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.QWord.QWord
+ Rattletrap.Type.Attribute.QWord: instance GHC.Classes.Eq Rattletrap.Type.Attribute.QWord.QWord
+ Rattletrap.Type.Attribute.QWord: instance GHC.Show.Show Rattletrap.Type.Attribute.QWord.QWord
+ Rattletrap.Type.Attribute.QWord: newtype QWord
+ Rattletrap.Type.Attribute.QWord: schema :: Schema
+ Rattletrap.Type.Attribute.Reservation: Reservation :: CompressedWord -> UniqueId -> Maybe Str -> Bool -> Bool -> Maybe Word8 -> Reservation
+ Rattletrap.Type.Attribute.Reservation: [name] :: Reservation -> Maybe Str
+ Rattletrap.Type.Attribute.Reservation: [number] :: Reservation -> CompressedWord
+ Rattletrap.Type.Attribute.Reservation: [uniqueId] :: Reservation -> UniqueId
+ Rattletrap.Type.Attribute.Reservation: [unknown1] :: Reservation -> Bool
+ Rattletrap.Type.Attribute.Reservation: [unknown2] :: Reservation -> Bool
+ Rattletrap.Type.Attribute.Reservation: [unknown3] :: Reservation -> Maybe Word8
+ Rattletrap.Type.Attribute.Reservation: bitGet :: Version -> BitGet Reservation
+ Rattletrap.Type.Attribute.Reservation: bitPut :: Reservation -> BitPut
+ Rattletrap.Type.Attribute.Reservation: data Reservation
+ Rattletrap.Type.Attribute.Reservation: hasUnknown3 :: Version -> Bool
+ Rattletrap.Type.Attribute.Reservation: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.Reservation.Reservation
+ Rattletrap.Type.Attribute.Reservation: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.Reservation.Reservation
+ Rattletrap.Type.Attribute.Reservation: instance GHC.Classes.Eq Rattletrap.Type.Attribute.Reservation.Reservation
+ Rattletrap.Type.Attribute.Reservation: instance GHC.Show.Show Rattletrap.Type.Attribute.Reservation.Reservation
+ Rattletrap.Type.Attribute.Reservation: schema :: Schema
+ Rattletrap.Type.Attribute.RigidBodyState: RigidBodyState :: Bool -> Vector -> Rotation -> Maybe Vector -> Maybe Vector -> RigidBodyState
+ Rattletrap.Type.Attribute.RigidBodyState: [angularVelocity] :: RigidBodyState -> Maybe Vector
+ Rattletrap.Type.Attribute.RigidBodyState: [linearVelocity] :: RigidBodyState -> Maybe Vector
+ Rattletrap.Type.Attribute.RigidBodyState: [location] :: RigidBodyState -> Vector
+ Rattletrap.Type.Attribute.RigidBodyState: [rotation] :: RigidBodyState -> Rotation
+ Rattletrap.Type.Attribute.RigidBodyState: [sleeping] :: RigidBodyState -> Bool
+ Rattletrap.Type.Attribute.RigidBodyState: bitGet :: Version -> BitGet RigidBodyState
+ Rattletrap.Type.Attribute.RigidBodyState: bitPut :: RigidBodyState -> BitPut
+ Rattletrap.Type.Attribute.RigidBodyState: data RigidBodyState
+ Rattletrap.Type.Attribute.RigidBodyState: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.RigidBodyState.RigidBodyState
+ Rattletrap.Type.Attribute.RigidBodyState: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.RigidBodyState.RigidBodyState
+ Rattletrap.Type.Attribute.RigidBodyState: instance GHC.Classes.Eq Rattletrap.Type.Attribute.RigidBodyState.RigidBodyState
+ Rattletrap.Type.Attribute.RigidBodyState: instance GHC.Show.Show Rattletrap.Type.Attribute.RigidBodyState.RigidBodyState
+ Rattletrap.Type.Attribute.RigidBodyState: schema :: Schema
+ Rattletrap.Type.Attribute.StatEvent: StatEvent :: Bool -> I32 -> StatEvent
+ Rattletrap.Type.Attribute.StatEvent: [objectId] :: StatEvent -> I32
+ Rattletrap.Type.Attribute.StatEvent: [unknown] :: StatEvent -> Bool
+ Rattletrap.Type.Attribute.StatEvent: bitGet :: BitGet StatEvent
+ Rattletrap.Type.Attribute.StatEvent: bitPut :: StatEvent -> BitPut
+ Rattletrap.Type.Attribute.StatEvent: data StatEvent
+ Rattletrap.Type.Attribute.StatEvent: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.StatEvent.StatEvent
+ Rattletrap.Type.Attribute.StatEvent: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.StatEvent.StatEvent
+ Rattletrap.Type.Attribute.StatEvent: instance GHC.Classes.Eq Rattletrap.Type.Attribute.StatEvent.StatEvent
+ Rattletrap.Type.Attribute.StatEvent: instance GHC.Show.Show Rattletrap.Type.Attribute.StatEvent.StatEvent
+ Rattletrap.Type.Attribute.StatEvent: schema :: Schema
+ Rattletrap.Type.Attribute.String: String :: Str -> String
+ Rattletrap.Type.Attribute.String: [value] :: String -> Str
+ Rattletrap.Type.Attribute.String: bitGet :: BitGet String
+ Rattletrap.Type.Attribute.String: bitPut :: String -> BitPut
+ Rattletrap.Type.Attribute.String: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.String.String
+ Rattletrap.Type.Attribute.String: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.String.String
+ Rattletrap.Type.Attribute.String: instance GHC.Classes.Eq Rattletrap.Type.Attribute.String.String
+ Rattletrap.Type.Attribute.String: instance GHC.Show.Show Rattletrap.Type.Attribute.String.String
+ Rattletrap.Type.Attribute.String: newtype String
+ Rattletrap.Type.Attribute.String: schema :: Schema
+ Rattletrap.Type.Attribute.TeamPaint: TeamPaint :: U8 -> U8 -> U8 -> U32 -> U32 -> TeamPaint
+ Rattletrap.Type.Attribute.TeamPaint: [accentColor] :: TeamPaint -> U8
+ Rattletrap.Type.Attribute.TeamPaint: [accentFinish] :: TeamPaint -> U32
+ Rattletrap.Type.Attribute.TeamPaint: [primaryColor] :: TeamPaint -> U8
+ Rattletrap.Type.Attribute.TeamPaint: [primaryFinish] :: TeamPaint -> U32
+ Rattletrap.Type.Attribute.TeamPaint: [team] :: TeamPaint -> U8
+ Rattletrap.Type.Attribute.TeamPaint: bitGet :: BitGet TeamPaint
+ Rattletrap.Type.Attribute.TeamPaint: bitPut :: TeamPaint -> BitPut
+ Rattletrap.Type.Attribute.TeamPaint: data TeamPaint
+ Rattletrap.Type.Attribute.TeamPaint: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.TeamPaint.TeamPaint
+ Rattletrap.Type.Attribute.TeamPaint: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.TeamPaint.TeamPaint
+ Rattletrap.Type.Attribute.TeamPaint: instance GHC.Classes.Eq Rattletrap.Type.Attribute.TeamPaint.TeamPaint
+ Rattletrap.Type.Attribute.TeamPaint: instance GHC.Show.Show Rattletrap.Type.Attribute.TeamPaint.TeamPaint
+ Rattletrap.Type.Attribute.TeamPaint: schema :: Schema
+ Rattletrap.Type.Attribute.Title: Title :: Bool -> Bool -> U32 -> U32 -> U32 -> U32 -> U32 -> Bool -> Title
+ Rattletrap.Type.Attribute.Title: [unknown1] :: Title -> Bool
+ Rattletrap.Type.Attribute.Title: [unknown2] :: Title -> Bool
+ Rattletrap.Type.Attribute.Title: [unknown3] :: Title -> U32
+ Rattletrap.Type.Attribute.Title: [unknown4] :: Title -> U32
+ Rattletrap.Type.Attribute.Title: [unknown5] :: Title -> U32
+ Rattletrap.Type.Attribute.Title: [unknown6] :: Title -> U32
+ Rattletrap.Type.Attribute.Title: [unknown7] :: Title -> U32
+ Rattletrap.Type.Attribute.Title: [unknown8] :: Title -> Bool
+ Rattletrap.Type.Attribute.Title: bitGet :: BitGet Title
+ Rattletrap.Type.Attribute.Title: bitPut :: Title -> BitPut
+ Rattletrap.Type.Attribute.Title: data Title
+ Rattletrap.Type.Attribute.Title: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.Title.Title
+ Rattletrap.Type.Attribute.Title: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.Title.Title
+ Rattletrap.Type.Attribute.Title: instance GHC.Classes.Eq Rattletrap.Type.Attribute.Title.Title
+ Rattletrap.Type.Attribute.Title: instance GHC.Show.Show Rattletrap.Type.Attribute.Title.Title
+ Rattletrap.Type.Attribute.Title: schema :: Schema
+ Rattletrap.Type.Attribute.UniqueId: UniqueId :: U8 -> RemoteId -> U8 -> UniqueId
+ Rattletrap.Type.Attribute.UniqueId: [localId] :: UniqueId -> U8
+ Rattletrap.Type.Attribute.UniqueId: [remoteId] :: UniqueId -> RemoteId
+ Rattletrap.Type.Attribute.UniqueId: [systemId] :: UniqueId -> U8
+ Rattletrap.Type.Attribute.UniqueId: bitGet :: Version -> BitGet UniqueId
+ Rattletrap.Type.Attribute.UniqueId: bitPut :: UniqueId -> BitPut
+ Rattletrap.Type.Attribute.UniqueId: data UniqueId
+ Rattletrap.Type.Attribute.UniqueId: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.UniqueId.UniqueId
+ Rattletrap.Type.Attribute.UniqueId: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.UniqueId.UniqueId
+ Rattletrap.Type.Attribute.UniqueId: instance GHC.Classes.Eq Rattletrap.Type.Attribute.UniqueId.UniqueId
+ Rattletrap.Type.Attribute.UniqueId: instance GHC.Show.Show Rattletrap.Type.Attribute.UniqueId.UniqueId
+ Rattletrap.Type.Attribute.UniqueId: schema :: Schema
+ Rattletrap.Type.Attribute.WeldedInfo: WeldedInfo :: Bool -> I32 -> Vector -> F32 -> Int8Vector -> WeldedInfo
+ Rattletrap.Type.Attribute.WeldedInfo: [active] :: WeldedInfo -> Bool
+ Rattletrap.Type.Attribute.WeldedInfo: [actorId] :: WeldedInfo -> I32
+ Rattletrap.Type.Attribute.WeldedInfo: [mass] :: WeldedInfo -> F32
+ Rattletrap.Type.Attribute.WeldedInfo: [offset] :: WeldedInfo -> Vector
+ Rattletrap.Type.Attribute.WeldedInfo: [rotation] :: WeldedInfo -> Int8Vector
+ Rattletrap.Type.Attribute.WeldedInfo: bitGet :: Version -> BitGet WeldedInfo
+ Rattletrap.Type.Attribute.WeldedInfo: bitPut :: WeldedInfo -> BitPut
+ Rattletrap.Type.Attribute.WeldedInfo: data WeldedInfo
+ Rattletrap.Type.Attribute.WeldedInfo: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Attribute.WeldedInfo.WeldedInfo
+ Rattletrap.Type.Attribute.WeldedInfo: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Attribute.WeldedInfo.WeldedInfo
+ Rattletrap.Type.Attribute.WeldedInfo: instance GHC.Classes.Eq Rattletrap.Type.Attribute.WeldedInfo.WeldedInfo
+ Rattletrap.Type.Attribute.WeldedInfo: instance GHC.Show.Show Rattletrap.Type.Attribute.WeldedInfo.WeldedInfo
+ Rattletrap.Type.Attribute.WeldedInfo: schema :: Schema
+ Rattletrap.Type.AttributeMapping: AttributeMapping :: U32 -> U32 -> AttributeMapping
+ Rattletrap.Type.AttributeMapping: [objectId] :: AttributeMapping -> U32
+ Rattletrap.Type.AttributeMapping: [streamId] :: AttributeMapping -> U32
+ Rattletrap.Type.AttributeMapping: byteGet :: ByteGet AttributeMapping
+ Rattletrap.Type.AttributeMapping: bytePut :: AttributeMapping -> BytePut
+ Rattletrap.Type.AttributeMapping: data AttributeMapping
+ Rattletrap.Type.AttributeMapping: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.AttributeMapping.AttributeMapping
+ Rattletrap.Type.AttributeMapping: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.AttributeMapping.AttributeMapping
+ Rattletrap.Type.AttributeMapping: instance GHC.Classes.Eq Rattletrap.Type.AttributeMapping.AttributeMapping
+ Rattletrap.Type.AttributeMapping: instance GHC.Show.Show Rattletrap.Type.AttributeMapping.AttributeMapping
+ Rattletrap.Type.AttributeMapping: schema :: Schema
+ Rattletrap.Type.AttributeType: AppliedDamage :: AttributeType
+ Rattletrap.Type.AttributeType: Boolean :: AttributeType
+ Rattletrap.Type.AttributeType: Byte :: AttributeType
+ Rattletrap.Type.AttributeType: CamSettings :: AttributeType
+ Rattletrap.Type.AttributeType: ClubColors :: AttributeType
+ Rattletrap.Type.AttributeType: CustomDemolish :: AttributeType
+ Rattletrap.Type.AttributeType: DamageState :: AttributeType
+ Rattletrap.Type.AttributeType: Demolish :: AttributeType
+ Rattletrap.Type.AttributeType: Enum :: AttributeType
+ Rattletrap.Type.AttributeType: Explosion :: AttributeType
+ Rattletrap.Type.AttributeType: ExtendedExplosion :: AttributeType
+ Rattletrap.Type.AttributeType: FlaggedByte :: AttributeType
+ Rattletrap.Type.AttributeType: FlaggedInt :: AttributeType
+ Rattletrap.Type.AttributeType: Float :: AttributeType
+ Rattletrap.Type.AttributeType: GameMode :: AttributeType
+ Rattletrap.Type.AttributeType: Int :: AttributeType
+ Rattletrap.Type.AttributeType: Int64 :: AttributeType
+ Rattletrap.Type.AttributeType: Loadout :: AttributeType
+ Rattletrap.Type.AttributeType: LoadoutOnline :: AttributeType
+ Rattletrap.Type.AttributeType: Loadouts :: AttributeType
+ Rattletrap.Type.AttributeType: LoadoutsOnline :: AttributeType
+ Rattletrap.Type.AttributeType: Location :: AttributeType
+ Rattletrap.Type.AttributeType: MusicStinger :: AttributeType
+ Rattletrap.Type.AttributeType: PartyLeader :: AttributeType
+ Rattletrap.Type.AttributeType: Pickup :: AttributeType
+ Rattletrap.Type.AttributeType: PickupNew :: AttributeType
+ Rattletrap.Type.AttributeType: PlayerHistoryKey :: AttributeType
+ Rattletrap.Type.AttributeType: PrivateMatchSettings :: AttributeType
+ Rattletrap.Type.AttributeType: QWord :: AttributeType
+ Rattletrap.Type.AttributeType: Reservation :: AttributeType
+ Rattletrap.Type.AttributeType: RigidBodyState :: AttributeType
+ Rattletrap.Type.AttributeType: StatEvent :: AttributeType
+ Rattletrap.Type.AttributeType: String :: AttributeType
+ Rattletrap.Type.AttributeType: TeamPaint :: AttributeType
+ Rattletrap.Type.AttributeType: Title :: AttributeType
+ Rattletrap.Type.AttributeType: UniqueId :: AttributeType
+ Rattletrap.Type.AttributeType: WeldedInfo :: AttributeType
+ Rattletrap.Type.AttributeType: data AttributeType
+ Rattletrap.Type.AttributeType: instance GHC.Classes.Eq Rattletrap.Type.AttributeType.AttributeType
+ Rattletrap.Type.AttributeType: instance GHC.Show.Show Rattletrap.Type.AttributeType.AttributeType
+ Rattletrap.Type.AttributeValue: AppliedDamage :: AppliedDamage -> AttributeValue
+ Rattletrap.Type.AttributeValue: Boolean :: Boolean -> AttributeValue
+ Rattletrap.Type.AttributeValue: Byte :: Byte -> AttributeValue
+ Rattletrap.Type.AttributeValue: CamSettings :: CamSettings -> AttributeValue
+ Rattletrap.Type.AttributeValue: ClubColors :: ClubColors -> AttributeValue
+ Rattletrap.Type.AttributeValue: CustomDemolish :: CustomDemolish -> AttributeValue
+ Rattletrap.Type.AttributeValue: DamageState :: DamageState -> AttributeValue
+ Rattletrap.Type.AttributeValue: Demolish :: Demolish -> AttributeValue
+ Rattletrap.Type.AttributeValue: Enum :: Enum -> AttributeValue
+ Rattletrap.Type.AttributeValue: Explosion :: Explosion -> AttributeValue
+ Rattletrap.Type.AttributeValue: ExtendedExplosion :: ExtendedExplosion -> AttributeValue
+ Rattletrap.Type.AttributeValue: FlaggedByte :: FlaggedByte -> AttributeValue
+ Rattletrap.Type.AttributeValue: FlaggedInt :: FlaggedInt -> AttributeValue
+ Rattletrap.Type.AttributeValue: Float :: Float -> AttributeValue
+ Rattletrap.Type.AttributeValue: GameMode :: GameMode -> AttributeValue
+ Rattletrap.Type.AttributeValue: Int :: Int -> AttributeValue
+ Rattletrap.Type.AttributeValue: Int64 :: Int64 -> AttributeValue
+ Rattletrap.Type.AttributeValue: Loadout :: Loadout -> AttributeValue
+ Rattletrap.Type.AttributeValue: LoadoutOnline :: LoadoutOnline -> AttributeValue
+ Rattletrap.Type.AttributeValue: Loadouts :: Loadouts -> AttributeValue
+ Rattletrap.Type.AttributeValue: LoadoutsOnline :: LoadoutsOnline -> AttributeValue
+ Rattletrap.Type.AttributeValue: Location :: Location -> AttributeValue
+ Rattletrap.Type.AttributeValue: MusicStinger :: MusicStinger -> AttributeValue
+ Rattletrap.Type.AttributeValue: PartyLeader :: PartyLeader -> AttributeValue
+ Rattletrap.Type.AttributeValue: Pickup :: Pickup -> AttributeValue
+ Rattletrap.Type.AttributeValue: PickupNew :: PickupNew -> AttributeValue
+ Rattletrap.Type.AttributeValue: PlayerHistoryKey :: PlayerHistoryKey -> AttributeValue
+ Rattletrap.Type.AttributeValue: PrivateMatchSettings :: PrivateMatchSettings -> AttributeValue
+ Rattletrap.Type.AttributeValue: QWord :: QWord -> AttributeValue
+ Rattletrap.Type.AttributeValue: Reservation :: Reservation -> AttributeValue
+ Rattletrap.Type.AttributeValue: RigidBodyState :: RigidBodyState -> AttributeValue
+ Rattletrap.Type.AttributeValue: StatEvent :: StatEvent -> AttributeValue
+ Rattletrap.Type.AttributeValue: String :: String -> AttributeValue
+ Rattletrap.Type.AttributeValue: TeamPaint :: TeamPaint -> AttributeValue
+ Rattletrap.Type.AttributeValue: Title :: Title -> AttributeValue
+ Rattletrap.Type.AttributeValue: UniqueId :: UniqueId -> AttributeValue
+ Rattletrap.Type.AttributeValue: WeldedInfo :: WeldedInfo -> AttributeValue
+ Rattletrap.Type.AttributeValue: bitGet :: Version -> Map U32 Str -> Str -> BitGet AttributeValue
+ Rattletrap.Type.AttributeValue: bitPut :: AttributeValue -> BitPut
+ Rattletrap.Type.AttributeValue: data AttributeValue
+ Rattletrap.Type.AttributeValue: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.AttributeValue.AttributeValue
+ Rattletrap.Type.AttributeValue: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.AttributeValue.AttributeValue
+ Rattletrap.Type.AttributeValue: instance GHC.Classes.Eq Rattletrap.Type.AttributeValue.AttributeValue
+ Rattletrap.Type.AttributeValue: instance GHC.Show.Show Rattletrap.Type.AttributeValue.AttributeValue
+ Rattletrap.Type.AttributeValue: schema :: Schema
+ Rattletrap.Type.Cache: Cache :: U32 -> U32 -> U32 -> List AttributeMapping -> Cache
+ Rattletrap.Type.Cache: [attributeMappings] :: Cache -> List AttributeMapping
+ Rattletrap.Type.Cache: [cacheId] :: Cache -> U32
+ Rattletrap.Type.Cache: [classId] :: Cache -> U32
+ Rattletrap.Type.Cache: [parentCacheId] :: Cache -> U32
+ Rattletrap.Type.Cache: byteGet :: ByteGet Cache
+ Rattletrap.Type.Cache: bytePut :: Cache -> BytePut
+ Rattletrap.Type.Cache: data Cache
+ Rattletrap.Type.Cache: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Cache.Cache
+ Rattletrap.Type.Cache: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Cache.Cache
+ Rattletrap.Type.Cache: instance GHC.Classes.Eq Rattletrap.Type.Cache.Cache
+ Rattletrap.Type.Cache: instance GHC.Show.Show Rattletrap.Type.Cache.Cache
+ Rattletrap.Type.Cache: schema :: Schema
+ Rattletrap.Type.ClassAttributeMap: ClassAttributeMap :: Map U32 Str -> Map U32 U32 -> Map U32 (Map U32 U32) -> IntMap Str -> ClassAttributeMap
+ Rattletrap.Type.ClassAttributeMap: [nameMap] :: ClassAttributeMap -> IntMap Str
+ Rattletrap.Type.ClassAttributeMap: [objectClassMap] :: ClassAttributeMap -> Map U32 U32
+ Rattletrap.Type.ClassAttributeMap: [objectMap] :: ClassAttributeMap -> Map U32 Str
+ Rattletrap.Type.ClassAttributeMap: [value] :: ClassAttributeMap -> Map U32 (Map U32 U32)
+ Rattletrap.Type.ClassAttributeMap: classHasLocation :: Str -> Bool
+ Rattletrap.Type.ClassAttributeMap: classHasRotation :: Str -> Bool
+ Rattletrap.Type.ClassAttributeMap: data ClassAttributeMap
+ Rattletrap.Type.ClassAttributeMap: getAttributeIdLimit :: Map U32 U32 -> Maybe Word
+ Rattletrap.Type.ClassAttributeMap: getAttributeMap :: ClassAttributeMap -> Map CompressedWord U32 -> CompressedWord -> Maybe (Map U32 U32)
+ Rattletrap.Type.ClassAttributeMap: getAttributeName :: ClassAttributeMap -> Map U32 U32 -> CompressedWord -> Maybe Str
+ Rattletrap.Type.ClassAttributeMap: getClassName :: Str -> Maybe Str
+ Rattletrap.Type.ClassAttributeMap: getName :: IntMap Str -> U32 -> Maybe Str
+ Rattletrap.Type.ClassAttributeMap: getObjectName :: Map U32 Str -> U32 -> Maybe Str
+ Rattletrap.Type.ClassAttributeMap: instance GHC.Classes.Eq Rattletrap.Type.ClassAttributeMap.ClassAttributeMap
+ Rattletrap.Type.ClassAttributeMap: instance GHC.Show.Show Rattletrap.Type.ClassAttributeMap.ClassAttributeMap
+ Rattletrap.Type.ClassAttributeMap: make :: List Str -> List ClassMapping -> List Cache -> List Str -> ClassAttributeMap
+ Rattletrap.Type.ClassMapping: ClassMapping :: Str -> U32 -> ClassMapping
+ Rattletrap.Type.ClassMapping: [name] :: ClassMapping -> Str
+ Rattletrap.Type.ClassMapping: [streamId] :: ClassMapping -> U32
+ Rattletrap.Type.ClassMapping: byteGet :: ByteGet ClassMapping
+ Rattletrap.Type.ClassMapping: bytePut :: ClassMapping -> BytePut
+ Rattletrap.Type.ClassMapping: data ClassMapping
+ Rattletrap.Type.ClassMapping: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.ClassMapping.ClassMapping
+ Rattletrap.Type.ClassMapping: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.ClassMapping.ClassMapping
+ Rattletrap.Type.ClassMapping: instance GHC.Classes.Eq Rattletrap.Type.ClassMapping.ClassMapping
+ Rattletrap.Type.ClassMapping: instance GHC.Show.Show Rattletrap.Type.ClassMapping.ClassMapping
+ Rattletrap.Type.ClassMapping: schema :: Schema
+ Rattletrap.Type.CompressedWord: CompressedWord :: Word -> Word -> CompressedWord
+ Rattletrap.Type.CompressedWord: [limit] :: CompressedWord -> Word
+ Rattletrap.Type.CompressedWord: [value] :: CompressedWord -> Word
+ Rattletrap.Type.CompressedWord: bitGet :: Word -> BitGet CompressedWord
+ Rattletrap.Type.CompressedWord: bitPut :: CompressedWord -> BitPut
+ Rattletrap.Type.CompressedWord: data CompressedWord
+ Rattletrap.Type.CompressedWord: getMaxBits :: Word -> Int
+ Rattletrap.Type.CompressedWord: getMaxBits_ :: Word -> Word
+ Rattletrap.Type.CompressedWord: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.CompressedWord.CompressedWord
+ Rattletrap.Type.CompressedWord: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.CompressedWord.CompressedWord
+ Rattletrap.Type.CompressedWord: instance GHC.Classes.Eq Rattletrap.Type.CompressedWord.CompressedWord
+ Rattletrap.Type.CompressedWord: instance GHC.Classes.Ord Rattletrap.Type.CompressedWord.CompressedWord
+ Rattletrap.Type.CompressedWord: instance GHC.Show.Show Rattletrap.Type.CompressedWord.CompressedWord
+ Rattletrap.Type.CompressedWord: putCompressedWordStep :: Word -> Word -> Int -> Int -> Word -> BitPut
+ Rattletrap.Type.CompressedWord: schema :: Schema
+ Rattletrap.Type.CompressedWord: step :: Word -> Word -> Word -> Word -> BitGet Word
+ Rattletrap.Type.CompressedWordVector: CompressedWordVector :: CompressedWord -> CompressedWord -> CompressedWord -> CompressedWordVector
+ Rattletrap.Type.CompressedWordVector: [x] :: CompressedWordVector -> CompressedWord
+ Rattletrap.Type.CompressedWordVector: [y] :: CompressedWordVector -> CompressedWord
+ Rattletrap.Type.CompressedWordVector: [z] :: CompressedWordVector -> CompressedWord
+ Rattletrap.Type.CompressedWordVector: bitGet :: BitGet CompressedWordVector
+ Rattletrap.Type.CompressedWordVector: bitPut :: CompressedWordVector -> BitPut
+ Rattletrap.Type.CompressedWordVector: data CompressedWordVector
+ Rattletrap.Type.CompressedWordVector: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.CompressedWordVector.CompressedWordVector
+ Rattletrap.Type.CompressedWordVector: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.CompressedWordVector.CompressedWordVector
+ Rattletrap.Type.CompressedWordVector: instance GHC.Classes.Eq Rattletrap.Type.CompressedWordVector.CompressedWordVector
+ Rattletrap.Type.CompressedWordVector: instance GHC.Show.Show Rattletrap.Type.CompressedWordVector.CompressedWordVector
+ Rattletrap.Type.CompressedWordVector: limit :: Word
+ Rattletrap.Type.CompressedWordVector: schema :: Schema
+ Rattletrap.Type.Content: Content :: List Str -> List KeyFrame -> U32 -> frames -> List Message -> List Mark -> List Str -> List Str -> List Str -> List ClassMapping -> List Cache -> [Word8] -> ContentWith frames
+ Rattletrap.Type.Content: [caches] :: ContentWith frames -> List Cache
+ Rattletrap.Type.Content: [classMappings] :: ContentWith frames -> List ClassMapping
+ Rattletrap.Type.Content: [frames] :: ContentWith frames -> frames
+ Rattletrap.Type.Content: [keyFrames] :: ContentWith frames -> List KeyFrame
+ Rattletrap.Type.Content: [levels] :: ContentWith frames -> List Str
+ Rattletrap.Type.Content: [marks] :: ContentWith frames -> List Mark
+ Rattletrap.Type.Content: [messages] :: ContentWith frames -> List Message
+ Rattletrap.Type.Content: [names] :: ContentWith frames -> List Str
+ Rattletrap.Type.Content: [objects] :: ContentWith frames -> List Str
+ Rattletrap.Type.Content: [packages] :: ContentWith frames -> List Str
+ Rattletrap.Type.Content: [streamSize] :: ContentWith frames -> U32
+ Rattletrap.Type.Content: [unknown] :: ContentWith frames -> [Word8]
+ Rattletrap.Type.Content: byteGet :: Version -> Int -> Word -> ByteGet Content
+ Rattletrap.Type.Content: bytePut :: Content -> BytePut
+ Rattletrap.Type.Content: data ContentWith frames
+ Rattletrap.Type.Content: empty :: Content
+ Rattletrap.Type.Content: instance Data.Aeson.Types.FromJSON.FromJSON frames => Data.Aeson.Types.FromJSON.FromJSON (Rattletrap.Type.Content.ContentWith frames)
+ Rattletrap.Type.Content: instance Data.Aeson.Types.ToJSON.ToJSON frames => Data.Aeson.Types.ToJSON.ToJSON (Rattletrap.Type.Content.ContentWith frames)
+ Rattletrap.Type.Content: instance GHC.Classes.Eq frames => GHC.Classes.Eq (Rattletrap.Type.Content.ContentWith frames)
+ Rattletrap.Type.Content: instance GHC.Show.Show frames => GHC.Show.Show (Rattletrap.Type.Content.ContentWith frames)
+ Rattletrap.Type.Content: putFrames :: Content -> BytePut
+ Rattletrap.Type.Content: schema :: Schema -> Schema
+ Rattletrap.Type.Content: type Content = ContentWith (List Frame)
+ Rattletrap.Type.Dictionary: Dictionary :: List (Str, a) -> Str -> Dictionary a
+ Rattletrap.Type.Dictionary: [elements] :: Dictionary a -> List (Str, a)
+ Rattletrap.Type.Dictionary: [lastKey] :: Dictionary a -> Str
+ Rattletrap.Type.Dictionary: byteGet :: ByteGet a -> ByteGet (Dictionary a)
+ Rattletrap.Type.Dictionary: byteGetWith :: Int -> [(Int, (Str, a))] -> ByteGet a -> ByteGet (Dictionary a)
+ Rattletrap.Type.Dictionary: bytePut :: (a -> BytePut) -> Dictionary a -> BytePut
+ Rattletrap.Type.Dictionary: data Dictionary a
+ Rattletrap.Type.Dictionary: instance Data.Aeson.Types.FromJSON.FromJSON a => Data.Aeson.Types.FromJSON.FromJSON (Rattletrap.Type.Dictionary.Dictionary a)
+ Rattletrap.Type.Dictionary: instance Data.Aeson.Types.ToJSON.ToJSON a => Data.Aeson.Types.ToJSON.ToJSON (Rattletrap.Type.Dictionary.Dictionary a)
+ Rattletrap.Type.Dictionary: instance GHC.Classes.Eq a => GHC.Classes.Eq (Rattletrap.Type.Dictionary.Dictionary a)
+ Rattletrap.Type.Dictionary: instance GHC.Show.Show a => GHC.Show.Show (Rattletrap.Type.Dictionary.Dictionary a)
+ Rattletrap.Type.Dictionary: isNone :: Str -> Bool
+ Rattletrap.Type.Dictionary: lookup :: Str -> Dictionary a -> Maybe a
+ Rattletrap.Type.Dictionary: schema :: Schema -> Schema
+ Rattletrap.Type.F32: F32 :: Float -> F32
+ Rattletrap.Type.F32: bitGet :: BitGet F32
+ Rattletrap.Type.F32: bitPut :: F32 -> BitPut
+ Rattletrap.Type.F32: byteGet :: ByteGet F32
+ Rattletrap.Type.F32: bytePut :: F32 -> BytePut
+ Rattletrap.Type.F32: fromFloat :: Float -> F32
+ Rattletrap.Type.F32: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.F32.F32
+ Rattletrap.Type.F32: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.F32.F32
+ Rattletrap.Type.F32: instance GHC.Classes.Eq Rattletrap.Type.F32.F32
+ Rattletrap.Type.F32: instance GHC.Show.Show Rattletrap.Type.F32.F32
+ Rattletrap.Type.F32: newtype F32
+ Rattletrap.Type.F32: schema :: Schema
+ Rattletrap.Type.F32: toFloat :: F32 -> Float
+ Rattletrap.Type.Frame: Frame :: F32 -> F32 -> List Replication -> Frame
+ Rattletrap.Type.Frame: [delta] :: Frame -> F32
+ Rattletrap.Type.Frame: [replications] :: Frame -> List Replication
+ Rattletrap.Type.Frame: [time] :: Frame -> F32
+ Rattletrap.Type.Frame: bitGet :: Version -> Word -> ClassAttributeMap -> StateT (Map CompressedWord U32) BitGet Frame
+ Rattletrap.Type.Frame: bitPut :: Frame -> BitPut
+ Rattletrap.Type.Frame: data Frame
+ Rattletrap.Type.Frame: decodeFramesBits :: Version -> Int -> Word -> ClassAttributeMap -> StateT (Map CompressedWord U32) BitGet (List Frame)
+ Rattletrap.Type.Frame: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Frame.Frame
+ Rattletrap.Type.Frame: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Frame.Frame
+ Rattletrap.Type.Frame: instance GHC.Classes.Eq Rattletrap.Type.Frame.Frame
+ Rattletrap.Type.Frame: instance GHC.Show.Show Rattletrap.Type.Frame.Frame
+ Rattletrap.Type.Frame: putFrames :: List Frame -> BitPut
+ Rattletrap.Type.Frame: schema :: Schema
+ Rattletrap.Type.Header: Header :: U32 -> U32 -> Maybe U32 -> Str -> Dictionary Property -> Header
+ Rattletrap.Type.Header: [engineVersion] :: Header -> U32
+ Rattletrap.Type.Header: [label] :: Header -> Str
+ Rattletrap.Type.Header: [licenseeVersion] :: Header -> U32
+ Rattletrap.Type.Header: [patchVersion] :: Header -> Maybe U32
+ Rattletrap.Type.Header: [properties] :: Header -> Dictionary Property
+ Rattletrap.Type.Header: byteGet :: ByteGet Header
+ Rattletrap.Type.Header: bytePut :: Header -> BytePut
+ Rattletrap.Type.Header: data Header
+ Rattletrap.Type.Header: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Header.Header
+ Rattletrap.Type.Header: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Header.Header
+ Rattletrap.Type.Header: instance GHC.Classes.Eq Rattletrap.Type.Header.Header
+ Rattletrap.Type.Header: instance GHC.Show.Show Rattletrap.Type.Header.Header
+ Rattletrap.Type.Header: schema :: Schema
+ Rattletrap.Type.I32: I32 :: Int32 -> I32
+ Rattletrap.Type.I32: bitGet :: BitGet I32
+ Rattletrap.Type.I32: bitPut :: I32 -> BitPut
+ Rattletrap.Type.I32: byteGet :: ByteGet I32
+ Rattletrap.Type.I32: bytePut :: I32 -> BytePut
+ Rattletrap.Type.I32: fromInt32 :: Int32 -> I32
+ Rattletrap.Type.I32: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.I32.I32
+ Rattletrap.Type.I32: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.I32.I32
+ Rattletrap.Type.I32: instance GHC.Classes.Eq Rattletrap.Type.I32.I32
+ Rattletrap.Type.I32: instance GHC.Show.Show Rattletrap.Type.I32.I32
+ Rattletrap.Type.I32: newtype I32
+ Rattletrap.Type.I32: schema :: Schema
+ Rattletrap.Type.I32: toInt32 :: I32 -> Int32
+ Rattletrap.Type.I64: I64 :: Int64 -> I64
+ Rattletrap.Type.I64: bitGet :: BitGet I64
+ Rattletrap.Type.I64: bitPut :: I64 -> BitPut
+ Rattletrap.Type.I64: byteGet :: ByteGet I64
+ Rattletrap.Type.I64: bytePut :: I64 -> BytePut
+ Rattletrap.Type.I64: fromInt64 :: Int64 -> I64
+ Rattletrap.Type.I64: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.I64.I64
+ Rattletrap.Type.I64: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.I64.I64
+ Rattletrap.Type.I64: instance GHC.Classes.Eq Rattletrap.Type.I64.I64
+ Rattletrap.Type.I64: instance GHC.Show.Show Rattletrap.Type.I64.I64
+ Rattletrap.Type.I64: newtype I64
+ Rattletrap.Type.I64: schema :: Schema
+ Rattletrap.Type.I64: toInt64 :: I64 -> Int64
+ Rattletrap.Type.I8: I8 :: Int8 -> I8
+ Rattletrap.Type.I8: bitGet :: BitGet I8
+ Rattletrap.Type.I8: bitPut :: I8 -> BitPut
+ Rattletrap.Type.I8: byteGet :: ByteGet I8
+ Rattletrap.Type.I8: bytePut :: I8 -> BytePut
+ Rattletrap.Type.I8: fromInt8 :: Int8 -> I8
+ Rattletrap.Type.I8: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.I8.I8
+ Rattletrap.Type.I8: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.I8.I8
+ Rattletrap.Type.I8: instance GHC.Classes.Eq Rattletrap.Type.I8.I8
+ Rattletrap.Type.I8: instance GHC.Show.Show Rattletrap.Type.I8.I8
+ Rattletrap.Type.I8: newtype I8
+ Rattletrap.Type.I8: schema :: Schema
+ Rattletrap.Type.I8: toInt8 :: I8 -> Int8
+ Rattletrap.Type.Initialization: Initialization :: Maybe Vector -> Maybe Int8Vector -> Initialization
+ Rattletrap.Type.Initialization: [location] :: Initialization -> Maybe Vector
+ Rattletrap.Type.Initialization: [rotation] :: Initialization -> Maybe Int8Vector
+ Rattletrap.Type.Initialization: bitGet :: Version -> Bool -> Bool -> BitGet Initialization
+ Rattletrap.Type.Initialization: bitPut :: Initialization -> BitPut
+ Rattletrap.Type.Initialization: data Initialization
+ Rattletrap.Type.Initialization: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Initialization.Initialization
+ Rattletrap.Type.Initialization: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Initialization.Initialization
+ Rattletrap.Type.Initialization: instance GHC.Classes.Eq Rattletrap.Type.Initialization.Initialization
+ Rattletrap.Type.Initialization: instance GHC.Show.Show Rattletrap.Type.Initialization.Initialization
+ Rattletrap.Type.Initialization: schema :: Schema
+ Rattletrap.Type.Int8Vector: Int8Vector :: Maybe I8 -> Maybe I8 -> Maybe I8 -> Int8Vector
+ Rattletrap.Type.Int8Vector: [x] :: Int8Vector -> Maybe I8
+ Rattletrap.Type.Int8Vector: [y] :: Int8Vector -> Maybe I8
+ Rattletrap.Type.Int8Vector: [z] :: Int8Vector -> Maybe I8
+ Rattletrap.Type.Int8Vector: bitGet :: BitGet Int8Vector
+ Rattletrap.Type.Int8Vector: bitPut :: Int8Vector -> BitPut
+ Rattletrap.Type.Int8Vector: data Int8Vector
+ Rattletrap.Type.Int8Vector: decodeFieldBits :: BitGet (Maybe I8)
+ Rattletrap.Type.Int8Vector: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Int8Vector.Int8Vector
+ Rattletrap.Type.Int8Vector: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Int8Vector.Int8Vector
+ Rattletrap.Type.Int8Vector: instance GHC.Classes.Eq Rattletrap.Type.Int8Vector.Int8Vector
+ Rattletrap.Type.Int8Vector: instance GHC.Show.Show Rattletrap.Type.Int8Vector.Int8Vector
+ Rattletrap.Type.Int8Vector: putInt8VectorField :: Maybe I8 -> BitPut
+ Rattletrap.Type.Int8Vector: schema :: Schema
+ Rattletrap.Type.KeyFrame: KeyFrame :: F32 -> U32 -> U32 -> KeyFrame
+ Rattletrap.Type.KeyFrame: [frame] :: KeyFrame -> U32
+ Rattletrap.Type.KeyFrame: [position] :: KeyFrame -> U32
+ Rattletrap.Type.KeyFrame: [time] :: KeyFrame -> F32
+ Rattletrap.Type.KeyFrame: byteGet :: ByteGet KeyFrame
+ Rattletrap.Type.KeyFrame: bytePut :: KeyFrame -> BytePut
+ Rattletrap.Type.KeyFrame: data KeyFrame
+ Rattletrap.Type.KeyFrame: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.KeyFrame.KeyFrame
+ Rattletrap.Type.KeyFrame: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.KeyFrame.KeyFrame
+ Rattletrap.Type.KeyFrame: instance GHC.Classes.Eq Rattletrap.Type.KeyFrame.KeyFrame
+ Rattletrap.Type.KeyFrame: instance GHC.Show.Show Rattletrap.Type.KeyFrame.KeyFrame
+ Rattletrap.Type.KeyFrame: schema :: Schema
+ Rattletrap.Type.List: List :: [a] -> List a
+ Rattletrap.Type.List: byteGet :: ByteGet a -> ByteGet (List a)
+ Rattletrap.Type.List: bytePut :: (a -> BytePut) -> List a -> BytePut
+ Rattletrap.Type.List: empty :: List a
+ Rattletrap.Type.List: fromList :: [a] -> List a
+ Rattletrap.Type.List: instance Data.Aeson.Types.FromJSON.FromJSON a => Data.Aeson.Types.FromJSON.FromJSON (Rattletrap.Type.List.List a)
+ Rattletrap.Type.List: instance Data.Aeson.Types.ToJSON.ToJSON a => Data.Aeson.Types.ToJSON.ToJSON (Rattletrap.Type.List.List a)
+ Rattletrap.Type.List: instance GHC.Classes.Eq a => GHC.Classes.Eq (Rattletrap.Type.List.List a)
+ Rattletrap.Type.List: instance GHC.Show.Show a => GHC.Show.Show (Rattletrap.Type.List.List a)
+ Rattletrap.Type.List: newtype List a
+ Rattletrap.Type.List: replicateM :: Monad m => Int -> m a -> m (List a)
+ Rattletrap.Type.List: schema :: Schema -> Schema
+ Rattletrap.Type.List: toList :: List a -> [a]
+ Rattletrap.Type.List: untilM :: Monad m => m (Maybe a) -> m (List a)
+ Rattletrap.Type.List: untilMWith :: Monad m => m (Maybe a) -> Int -> [(Int, a)] -> m (List a)
+ Rattletrap.Type.Mark: Mark :: Str -> U32 -> Mark
+ Rattletrap.Type.Mark: [frame] :: Mark -> U32
+ Rattletrap.Type.Mark: [value] :: Mark -> Str
+ Rattletrap.Type.Mark: byteGet :: ByteGet Mark
+ Rattletrap.Type.Mark: bytePut :: Mark -> BytePut
+ Rattletrap.Type.Mark: data Mark
+ Rattletrap.Type.Mark: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Mark.Mark
+ Rattletrap.Type.Mark: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Mark.Mark
+ Rattletrap.Type.Mark: instance GHC.Classes.Eq Rattletrap.Type.Mark.Mark
+ Rattletrap.Type.Mark: instance GHC.Show.Show Rattletrap.Type.Mark.Mark
+ Rattletrap.Type.Mark: schema :: Schema
+ Rattletrap.Type.Message: Message :: U32 -> Str -> Str -> Message
+ Rattletrap.Type.Message: [frame] :: Message -> U32
+ Rattletrap.Type.Message: [name] :: Message -> Str
+ Rattletrap.Type.Message: [value] :: Message -> Str
+ Rattletrap.Type.Message: byteGet :: ByteGet Message
+ Rattletrap.Type.Message: bytePut :: Message -> BytePut
+ Rattletrap.Type.Message: data Message
+ Rattletrap.Type.Message: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Message.Message
+ Rattletrap.Type.Message: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Message.Message
+ Rattletrap.Type.Message: instance GHC.Classes.Eq Rattletrap.Type.Message.Message
+ Rattletrap.Type.Message: instance GHC.Show.Show Rattletrap.Type.Message.Message
+ Rattletrap.Type.Message: schema :: Schema
+ Rattletrap.Type.Property: Property :: Str -> U64 -> PropertyValue Property -> Property
+ Rattletrap.Type.Property: [kind] :: Property -> Str
+ Rattletrap.Type.Property: [size] :: Property -> U64
+ Rattletrap.Type.Property: [value] :: Property -> PropertyValue Property
+ Rattletrap.Type.Property: byteGet :: ByteGet Property
+ Rattletrap.Type.Property: bytePut :: Property -> BytePut
+ Rattletrap.Type.Property: data Property
+ Rattletrap.Type.Property: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Property.Property
+ Rattletrap.Type.Property: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Property.Property
+ Rattletrap.Type.Property: instance GHC.Classes.Eq Rattletrap.Type.Property.Property
+ Rattletrap.Type.Property: instance GHC.Show.Show Rattletrap.Type.Property.Property
+ Rattletrap.Type.Property: schema :: Schema
+ Rattletrap.Type.PropertyValue: Array :: List (Dictionary a) -> PropertyValue a
+ Rattletrap.Type.PropertyValue: Bool :: U8 -> PropertyValue a
+ Rattletrap.Type.PropertyValue: Byte :: Str -> Maybe Str -> PropertyValue a
+ Rattletrap.Type.PropertyValue: Float :: F32 -> PropertyValue a
+ Rattletrap.Type.PropertyValue: Int :: I32 -> PropertyValue a
+ Rattletrap.Type.PropertyValue: Name :: Str -> PropertyValue a
+ Rattletrap.Type.PropertyValue: QWord :: U64 -> PropertyValue a
+ Rattletrap.Type.PropertyValue: Str :: Str -> PropertyValue a
+ Rattletrap.Type.PropertyValue: byteGet :: ByteGet a -> Str -> ByteGet (PropertyValue a)
+ Rattletrap.Type.PropertyValue: bytePut :: (a -> BytePut) -> PropertyValue a -> BytePut
+ Rattletrap.Type.PropertyValue: data PropertyValue a
+ Rattletrap.Type.PropertyValue: instance Data.Aeson.Types.FromJSON.FromJSON a => Data.Aeson.Types.FromJSON.FromJSON (Rattletrap.Type.PropertyValue.PropertyValue a)
+ Rattletrap.Type.PropertyValue: instance Data.Aeson.Types.ToJSON.ToJSON a => Data.Aeson.Types.ToJSON.ToJSON (Rattletrap.Type.PropertyValue.PropertyValue a)
+ Rattletrap.Type.PropertyValue: instance GHC.Classes.Eq a => GHC.Classes.Eq (Rattletrap.Type.PropertyValue.PropertyValue a)
+ Rattletrap.Type.PropertyValue: instance GHC.Show.Show a => GHC.Show.Show (Rattletrap.Type.PropertyValue.PropertyValue a)
+ Rattletrap.Type.PropertyValue: schema :: Schema -> Schema
+ Rattletrap.Type.Quaternion: Quaternion :: Double -> Double -> Double -> Double -> Quaternion
+ Rattletrap.Type.Quaternion: W :: Component
+ Rattletrap.Type.Quaternion: X :: Component
+ Rattletrap.Type.Quaternion: Y :: Component
+ Rattletrap.Type.Quaternion: Z :: Component
+ Rattletrap.Type.Quaternion: [w] :: Quaternion -> Double
+ Rattletrap.Type.Quaternion: [x] :: Quaternion -> Double
+ Rattletrap.Type.Quaternion: [y] :: Quaternion -> Double
+ Rattletrap.Type.Quaternion: [z] :: Quaternion -> Double
+ Rattletrap.Type.Quaternion: bitGet :: BitGet Quaternion
+ Rattletrap.Type.Quaternion: bitPut :: Quaternion -> BitPut
+ Rattletrap.Type.Quaternion: compressPart :: Double -> CompressedWord
+ Rattletrap.Type.Quaternion: data Component
+ Rattletrap.Type.Quaternion: data Quaternion
+ Rattletrap.Type.Quaternion: decodeComponent :: BitGet Component
+ Rattletrap.Type.Quaternion: decodePart :: BitGet Double
+ Rattletrap.Type.Quaternion: decompressPart :: CompressedWord -> Double
+ Rattletrap.Type.Quaternion: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Quaternion.Quaternion
+ Rattletrap.Type.Quaternion: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Quaternion.Quaternion
+ Rattletrap.Type.Quaternion: instance GHC.Classes.Eq Rattletrap.Type.Quaternion.Component
+ Rattletrap.Type.Quaternion: instance GHC.Classes.Eq Rattletrap.Type.Quaternion.Quaternion
+ Rattletrap.Type.Quaternion: instance GHC.Show.Show Rattletrap.Type.Quaternion.Component
+ Rattletrap.Type.Quaternion: instance GHC.Show.Show Rattletrap.Type.Quaternion.Quaternion
+ Rattletrap.Type.Quaternion: maxComponent :: Quaternion -> Component
+ Rattletrap.Type.Quaternion: maxCompressedValue :: Word
+ Rattletrap.Type.Quaternion: maxValue :: Double
+ Rattletrap.Type.Quaternion: maximumOn :: (Foldable t, Ord b) => (a -> b) -> t a -> a
+ Rattletrap.Type.Quaternion: numBits :: Word
+ Rattletrap.Type.Quaternion: putComponent :: Component -> BitPut
+ Rattletrap.Type.Quaternion: putPart :: Double -> BitPut
+ Rattletrap.Type.Quaternion: putParts :: Double -> Double -> Double -> BitPut
+ Rattletrap.Type.Quaternion: schema :: Schema
+ Rattletrap.Type.Quaternion: toPart :: Double -> Double -> Double -> Double
+ Rattletrap.Type.Quaternion: toQuaternion :: Component -> Double -> Double -> Double -> Quaternion
+ Rattletrap.Type.Quaternion: wordToDouble :: Word -> Double
+ Rattletrap.Type.RemoteId: Epic :: Str -> RemoteId
+ Rattletrap.Type.RemoteId: PlayStation :: Text -> [Word8] -> RemoteId
+ Rattletrap.Type.RemoteId: PsyNet :: Either U64 (U64, U64, U64, U64) -> RemoteId
+ Rattletrap.Type.RemoteId: Splitscreen :: Word32 -> RemoteId
+ Rattletrap.Type.RemoteId: Steam :: U64 -> RemoteId
+ Rattletrap.Type.RemoteId: Switch :: U64 -> U64 -> U64 -> U64 -> RemoteId
+ Rattletrap.Type.RemoteId: Xbox :: U64 -> RemoteId
+ Rattletrap.Type.RemoteId: bitGet :: Version -> U8 -> BitGet RemoteId
+ Rattletrap.Type.RemoteId: bitPut :: RemoteId -> BitPut
+ Rattletrap.Type.RemoteId: data RemoteId
+ Rattletrap.Type.RemoteId: decodePsBytes :: Version -> BitGet [Word8]
+ Rattletrap.Type.RemoteId: decodePsName :: BitGet Text
+ Rattletrap.Type.RemoteId: getWord256 :: BitGet (U64, U64, U64, U64)
+ Rattletrap.Type.RemoteId: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.RemoteId.RemoteId
+ Rattletrap.Type.RemoteId: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.RemoteId.RemoteId
+ Rattletrap.Type.RemoteId: instance GHC.Classes.Eq Rattletrap.Type.RemoteId.RemoteId
+ Rattletrap.Type.RemoteId: instance GHC.Show.Show Rattletrap.Type.RemoteId.RemoteId
+ Rattletrap.Type.RemoteId: playStationIsU24 :: Version -> Bool
+ Rattletrap.Type.RemoteId: psyNetIsU64 :: Version -> Bool
+ Rattletrap.Type.RemoteId: putWord256 :: U64 -> U64 -> U64 -> U64 -> BitPut
+ Rattletrap.Type.RemoteId: schema :: Schema
+ Rattletrap.Type.RemoteId: uncurry4 :: (a -> b -> c -> d -> e) -> (a, b, c, d) -> e
+ Rattletrap.Type.Replay: Replay :: header -> content -> ReplayWith header content
+ Rattletrap.Type.Replay: [content] :: ReplayWith header content -> content
+ Rattletrap.Type.Replay: [header] :: ReplayWith header content -> header
+ Rattletrap.Type.Replay: byteGet :: Bool -> Bool -> ByteGet Replay
+ Rattletrap.Type.Replay: bytePut :: Replay -> BytePut
+ Rattletrap.Type.Replay: data ReplayWith header content
+ Rattletrap.Type.Replay: getContent :: Header -> ByteGet Content
+ Rattletrap.Type.Replay: getMaxChannels :: Header -> Word
+ Rattletrap.Type.Replay: getNumFrames :: Header -> Int
+ Rattletrap.Type.Replay: getPatchVersion :: Header -> Int
+ Rattletrap.Type.Replay: getVersion :: Header -> Version
+ Rattletrap.Type.Replay: instance (Data.Aeson.Types.FromJSON.FromJSON h, Data.Aeson.Types.FromJSON.FromJSON c) => Data.Aeson.Types.FromJSON.FromJSON (Rattletrap.Type.Replay.ReplayWith h c)
+ Rattletrap.Type.Replay: instance (Data.Aeson.Types.ToJSON.ToJSON h, Data.Aeson.Types.ToJSON.ToJSON c) => Data.Aeson.Types.ToJSON.ToJSON (Rattletrap.Type.Replay.ReplayWith h c)
+ Rattletrap.Type.Replay: instance (GHC.Classes.Eq header, GHC.Classes.Eq content) => GHC.Classes.Eq (Rattletrap.Type.Replay.ReplayWith header content)
+ Rattletrap.Type.Replay: instance (GHC.Show.Show header, GHC.Show.Show content) => GHC.Show.Show (Rattletrap.Type.Replay.ReplayWith header content)
+ Rattletrap.Type.Replay: schema :: Schema -> Schema -> Schema
+ Rattletrap.Type.Replay: schemaUrl :: String
+ Rattletrap.Type.Replay: type Replay = ReplayWith (Section Header) (Section Content)
+ Rattletrap.Type.Replication: Replication :: CompressedWord -> ReplicationValue -> Replication
+ Rattletrap.Type.Replication: [actorId] :: Replication -> CompressedWord
+ Rattletrap.Type.Replication: [value] :: Replication -> ReplicationValue
+ Rattletrap.Type.Replication: bitGet :: Version -> Word -> ClassAttributeMap -> StateT (Map CompressedWord U32) BitGet Replication
+ Rattletrap.Type.Replication: bitPut :: Replication -> BitPut
+ Rattletrap.Type.Replication: data Replication
+ Rattletrap.Type.Replication: decodeReplicationsBits :: Version -> Word -> ClassAttributeMap -> StateT (Map CompressedWord U32) BitGet (List Replication)
+ Rattletrap.Type.Replication: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Replication.Replication
+ Rattletrap.Type.Replication: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Replication.Replication
+ Rattletrap.Type.Replication: instance GHC.Classes.Eq Rattletrap.Type.Replication.Replication
+ Rattletrap.Type.Replication: instance GHC.Show.Show Rattletrap.Type.Replication.Replication
+ Rattletrap.Type.Replication: putReplications :: List Replication -> BitPut
+ Rattletrap.Type.Replication: schema :: Schema
+ Rattletrap.Type.Replication.Destroyed: Destroyed :: Destroyed
+ Rattletrap.Type.Replication.Destroyed: bitGet :: BitGet Destroyed
+ Rattletrap.Type.Replication.Destroyed: bitPut :: Destroyed -> BitPut
+ Rattletrap.Type.Replication.Destroyed: data Destroyed
+ Rattletrap.Type.Replication.Destroyed: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Replication.Destroyed.Destroyed
+ Rattletrap.Type.Replication.Destroyed: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Replication.Destroyed.Destroyed
+ Rattletrap.Type.Replication.Destroyed: instance GHC.Classes.Eq Rattletrap.Type.Replication.Destroyed.Destroyed
+ Rattletrap.Type.Replication.Destroyed: instance GHC.Show.Show Rattletrap.Type.Replication.Destroyed.Destroyed
+ Rattletrap.Type.Replication.Destroyed: schema :: Schema
+ Rattletrap.Type.Replication.Spawned: Spawned :: Bool -> Maybe U32 -> Maybe Str -> U32 -> Str -> Str -> Initialization -> Spawned
+ Rattletrap.Type.Replication.Spawned: [className] :: Spawned -> Str
+ Rattletrap.Type.Replication.Spawned: [flag] :: Spawned -> Bool
+ Rattletrap.Type.Replication.Spawned: [initialization] :: Spawned -> Initialization
+ Rattletrap.Type.Replication.Spawned: [nameIndex] :: Spawned -> Maybe U32
+ Rattletrap.Type.Replication.Spawned: [name] :: Spawned -> Maybe Str
+ Rattletrap.Type.Replication.Spawned: [objectId] :: Spawned -> U32
+ Rattletrap.Type.Replication.Spawned: [objectName] :: Spawned -> Str
+ Rattletrap.Type.Replication.Spawned: bitGet :: Version -> ClassAttributeMap -> CompressedWord -> StateT (Map CompressedWord U32) BitGet Spawned
+ Rattletrap.Type.Replication.Spawned: bitPut :: Spawned -> BitPut
+ Rattletrap.Type.Replication.Spawned: data Spawned
+ Rattletrap.Type.Replication.Spawned: hasNameIndex :: Version -> Bool
+ Rattletrap.Type.Replication.Spawned: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Replication.Spawned.Spawned
+ Rattletrap.Type.Replication.Spawned: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Replication.Spawned.Spawned
+ Rattletrap.Type.Replication.Spawned: instance GHC.Classes.Eq Rattletrap.Type.Replication.Spawned.Spawned
+ Rattletrap.Type.Replication.Spawned: instance GHC.Show.Show Rattletrap.Type.Replication.Spawned.Spawned
+ Rattletrap.Type.Replication.Spawned: lookupClassName :: Str -> Either String Str
+ Rattletrap.Type.Replication.Spawned: lookupName :: ClassAttributeMap -> Maybe U32 -> Either String (Maybe Str)
+ Rattletrap.Type.Replication.Spawned: lookupObjectName :: ClassAttributeMap -> U32 -> Either String Str
+ Rattletrap.Type.Replication.Spawned: schema :: Schema
+ Rattletrap.Type.Replication.Updated: Updated :: List Attribute -> Updated
+ Rattletrap.Type.Replication.Updated: [attributes] :: Updated -> List Attribute
+ Rattletrap.Type.Replication.Updated: bitGet :: Version -> ClassAttributeMap -> Map CompressedWord U32 -> CompressedWord -> BitGet Updated
+ Rattletrap.Type.Replication.Updated: bitPut :: Updated -> BitPut
+ Rattletrap.Type.Replication.Updated: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Replication.Updated.Updated
+ Rattletrap.Type.Replication.Updated: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Replication.Updated.Updated
+ Rattletrap.Type.Replication.Updated: instance GHC.Classes.Eq Rattletrap.Type.Replication.Updated.Updated
+ Rattletrap.Type.Replication.Updated: instance GHC.Show.Show Rattletrap.Type.Replication.Updated.Updated
+ Rattletrap.Type.Replication.Updated: newtype Updated
+ Rattletrap.Type.Replication.Updated: schema :: Schema
+ Rattletrap.Type.ReplicationValue: Destroyed :: Destroyed -> ReplicationValue
+ Rattletrap.Type.ReplicationValue: Spawned :: Spawned -> ReplicationValue
+ Rattletrap.Type.ReplicationValue: Updated :: Updated -> ReplicationValue
+ Rattletrap.Type.ReplicationValue: bitGet :: Version -> ClassAttributeMap -> CompressedWord -> StateT (Map CompressedWord U32) BitGet ReplicationValue
+ Rattletrap.Type.ReplicationValue: bitPut :: ReplicationValue -> BitPut
+ Rattletrap.Type.ReplicationValue: data ReplicationValue
+ Rattletrap.Type.ReplicationValue: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.ReplicationValue.ReplicationValue
+ Rattletrap.Type.ReplicationValue: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.ReplicationValue.ReplicationValue
+ Rattletrap.Type.ReplicationValue: instance GHC.Classes.Eq Rattletrap.Type.ReplicationValue.ReplicationValue
+ Rattletrap.Type.ReplicationValue: instance GHC.Show.Show Rattletrap.Type.ReplicationValue.ReplicationValue
+ Rattletrap.Type.ReplicationValue: schema :: Schema
+ Rattletrap.Type.Rotation: CompressedWordVector :: CompressedWordVector -> Rotation
+ Rattletrap.Type.Rotation: Quaternion :: Quaternion -> Rotation
+ Rattletrap.Type.Rotation: bitGet :: Version -> BitGet Rotation
+ Rattletrap.Type.Rotation: bitPut :: Rotation -> BitPut
+ Rattletrap.Type.Rotation: data Rotation
+ Rattletrap.Type.Rotation: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Rotation.Rotation
+ Rattletrap.Type.Rotation: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Rotation.Rotation
+ Rattletrap.Type.Rotation: instance GHC.Classes.Eq Rattletrap.Type.Rotation.Rotation
+ Rattletrap.Type.Rotation: instance GHC.Show.Show Rattletrap.Type.Rotation.Rotation
+ Rattletrap.Type.Rotation: isQuaternion :: Version -> Bool
+ Rattletrap.Type.Rotation: schema :: Schema
+ Rattletrap.Type.Section: Section :: U32 -> U32 -> a -> Section a
+ Rattletrap.Type.Section: [body] :: Section a -> a
+ Rattletrap.Type.Section: [crc] :: Section a -> U32
+ Rattletrap.Type.Section: [size] :: Section a -> U32
+ Rattletrap.Type.Section: byteGet :: Bool -> (U32 -> ByteGet a) -> ByteGet (Section a)
+ Rattletrap.Type.Section: bytePut :: (a -> BytePut) -> Section a -> BytePut
+ Rattletrap.Type.Section: crcMessage :: U32 -> U32 -> String
+ Rattletrap.Type.Section: create :: (a -> BytePut) -> a -> Section a
+ Rattletrap.Type.Section: data Section a
+ Rattletrap.Type.Section: instance Data.Aeson.Types.FromJSON.FromJSON a => Data.Aeson.Types.FromJSON.FromJSON (Rattletrap.Type.Section.Section a)
+ Rattletrap.Type.Section: instance Data.Aeson.Types.ToJSON.ToJSON a => Data.Aeson.Types.ToJSON.ToJSON (Rattletrap.Type.Section.Section a)
+ Rattletrap.Type.Section: instance GHC.Classes.Eq a => GHC.Classes.Eq (Rattletrap.Type.Section.Section a)
+ Rattletrap.Type.Section: instance GHC.Show.Show a => GHC.Show.Show (Rattletrap.Type.Section.Section a)
+ Rattletrap.Type.Section: schema :: Schema -> Schema
+ Rattletrap.Type.Str: Str :: Text -> Str
+ Rattletrap.Type.Str: addNull :: Text -> Text
+ Rattletrap.Type.Str: bitGet :: BitGet Str
+ Rattletrap.Type.Str: bitPut :: Str -> BitPut
+ Rattletrap.Type.Str: byteGet :: ByteGet Str
+ Rattletrap.Type.Str: bytePut :: Str -> BytePut
+ Rattletrap.Type.Str: dropNull :: Text -> Text
+ Rattletrap.Type.Str: fromString :: String -> Str
+ Rattletrap.Type.Str: fromText :: Text -> Str
+ Rattletrap.Type.Str: getTextDecoder :: I32 -> ByteString -> Text
+ Rattletrap.Type.Str: getTextEncoder :: I32 -> Text -> ByteString
+ Rattletrap.Type.Str: getTextSize :: Str -> I32
+ Rattletrap.Type.Str: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Str.Str
+ Rattletrap.Type.Str: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Str.Str
+ Rattletrap.Type.Str: instance GHC.Classes.Eq Rattletrap.Type.Str.Str
+ Rattletrap.Type.Str: instance GHC.Classes.Ord Rattletrap.Type.Str.Str
+ Rattletrap.Type.Str: instance GHC.Show.Show Rattletrap.Type.Str.Str
+ Rattletrap.Type.Str: newtype Str
+ Rattletrap.Type.Str: normalizeTextSize :: Integral a => I32 -> a
+ Rattletrap.Type.Str: schema :: Schema
+ Rattletrap.Type.Str: toString :: Str -> String
+ Rattletrap.Type.Str: toText :: Str -> Text
+ Rattletrap.Type.U32: U32 :: Word32 -> U32
+ Rattletrap.Type.U32: bitGet :: BitGet U32
+ Rattletrap.Type.U32: bitPut :: U32 -> BitPut
+ Rattletrap.Type.U32: byteGet :: ByteGet U32
+ Rattletrap.Type.U32: bytePut :: U32 -> BytePut
+ Rattletrap.Type.U32: fromWord32 :: Word32 -> U32
+ Rattletrap.Type.U32: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.U32.U32
+ Rattletrap.Type.U32: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.U32.U32
+ Rattletrap.Type.U32: instance GHC.Classes.Eq Rattletrap.Type.U32.U32
+ Rattletrap.Type.U32: instance GHC.Classes.Ord Rattletrap.Type.U32.U32
+ Rattletrap.Type.U32: instance GHC.Show.Show Rattletrap.Type.U32.U32
+ Rattletrap.Type.U32: newtype U32
+ Rattletrap.Type.U32: schema :: Schema
+ Rattletrap.Type.U32: toWord32 :: U32 -> Word32
+ Rattletrap.Type.U64: U64 :: Word64 -> U64
+ Rattletrap.Type.U64: bitGet :: BitGet U64
+ Rattletrap.Type.U64: bitPut :: U64 -> BitPut
+ Rattletrap.Type.U64: byteGet :: ByteGet U64
+ Rattletrap.Type.U64: bytePut :: U64 -> BytePut
+ Rattletrap.Type.U64: fromWord64 :: Word64 -> U64
+ Rattletrap.Type.U64: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.U64.U64
+ Rattletrap.Type.U64: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.U64.U64
+ Rattletrap.Type.U64: instance GHC.Classes.Eq Rattletrap.Type.U64.U64
+ Rattletrap.Type.U64: instance GHC.Show.Show Rattletrap.Type.U64.U64
+ Rattletrap.Type.U64: newtype U64
+ Rattletrap.Type.U64: schema :: Schema
+ Rattletrap.Type.U64: toWord64 :: U64 -> Word64
+ Rattletrap.Type.U8: U8 :: Word8 -> U8
+ Rattletrap.Type.U8: bitGet :: BitGet U8
+ Rattletrap.Type.U8: bitPut :: U8 -> BitPut
+ Rattletrap.Type.U8: byteGet :: ByteGet U8
+ Rattletrap.Type.U8: bytePut :: U8 -> BytePut
+ Rattletrap.Type.U8: fromWord8 :: Word8 -> U8
+ Rattletrap.Type.U8: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.U8.U8
+ Rattletrap.Type.U8: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.U8.U8
+ Rattletrap.Type.U8: instance GHC.Classes.Eq Rattletrap.Type.U8.U8
+ Rattletrap.Type.U8: instance GHC.Show.Show Rattletrap.Type.U8.U8
+ Rattletrap.Type.U8: newtype U8
+ Rattletrap.Type.U8: schema :: Schema
+ Rattletrap.Type.U8: toWord8 :: U8 -> Word8
+ Rattletrap.Type.Vector: Vector :: CompressedWord -> Word -> Int -> Int -> Int -> Vector
+ Rattletrap.Type.Vector: [bias] :: Vector -> Word
+ Rattletrap.Type.Vector: [size] :: Vector -> CompressedWord
+ Rattletrap.Type.Vector: [x] :: Vector -> Int
+ Rattletrap.Type.Vector: [y] :: Vector -> Int
+ Rattletrap.Type.Vector: [z] :: Vector -> Int
+ Rattletrap.Type.Vector: bitGet :: Version -> BitGet Vector
+ Rattletrap.Type.Vector: bitPut :: Vector -> BitPut
+ Rattletrap.Type.Vector: data Vector
+ Rattletrap.Type.Vector: fromDelta :: Word -> CompressedWord -> Int
+ Rattletrap.Type.Vector: getBias :: CompressedWord -> Word
+ Rattletrap.Type.Vector: getLimit :: CompressedWord -> Word
+ Rattletrap.Type.Vector: has21Bits :: Version -> Bool
+ Rattletrap.Type.Vector: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Vector.Vector
+ Rattletrap.Type.Vector: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Vector.Vector
+ Rattletrap.Type.Vector: instance GHC.Classes.Eq Rattletrap.Type.Vector.Vector
+ Rattletrap.Type.Vector: instance GHC.Show.Show Rattletrap.Type.Vector.Vector
+ Rattletrap.Type.Vector: schema :: Schema
+ Rattletrap.Type.Version: Version :: Int -> Int -> Int -> Version
+ Rattletrap.Type.Version: [major] :: Version -> Int
+ Rattletrap.Type.Version: [minor] :: Version -> Int
+ Rattletrap.Type.Version: [patch] :: Version -> Int
+ Rattletrap.Type.Version: data Version
+ Rattletrap.Type.Version: instance GHC.Classes.Eq Rattletrap.Type.Version.Version
+ Rattletrap.Type.Version: instance GHC.Show.Show Rattletrap.Type.Version.Version
+ Rattletrap.Utility.Bytes: encodeLatin1 :: Text -> ByteString
+ Rattletrap.Utility.Bytes: padBytes :: Integral a => a -> ByteString -> ByteString
+ Rattletrap.Utility.Bytes: reverseBytes :: ByteString -> ByteString
+ Rattletrap.Utility.Crc: compute :: ByteString -> Word32
+ Rattletrap.Utility.Helper: decodeReplayFile :: Bool -> Bool -> ByteString -> Either String Replay
+ Rattletrap.Utility.Helper: decodeReplayJson :: ByteString -> Either String Replay
+ Rattletrap.Utility.Helper: encodeReplayFile :: Bool -> Replay -> ByteString
+ Rattletrap.Utility.Helper: encodeReplayJson :: Replay -> ByteString
+ Rattletrap.Utility.Json: class FromJSON a
+ Rattletrap.Utility.Json: class ToJSON a
+ Rattletrap.Utility.Json: data Value
+ Rattletrap.Utility.Json: object :: [Pair] -> Value
+ Rattletrap.Utility.Json: optional :: FromJSON value => Object -> String -> Parser (Maybe value)
+ Rattletrap.Utility.Json: pair :: (ToJSON value, KeyValue pair) => String -> value -> pair
+ Rattletrap.Utility.Json: parseJSON :: FromJSON a => Value -> Parser a
+ Rattletrap.Utility.Json: required :: FromJSON value => Object -> String -> Parser value
+ Rattletrap.Utility.Json: toJSON :: ToJSON a => a -> Value
+ Rattletrap.Utility.Json: withObject :: String -> (Object -> Parser a) -> Value -> Parser a
+ Rattletrap.Utility.Json: withText :: String -> (Text -> Parser a) -> Value -> Parser a
+ Rattletrap.Utility.Monad: whenMaybe :: Applicative m => Bool -> m a -> m (Maybe a)
+ Rattletrap.Version: string :: String
- Rattletrap: decodeReplayFile :: Bool -> ByteString -> Either String FullReplay
+ Rattletrap: decodeReplayFile :: Bool -> Bool -> ByteString -> Either String Replay
- Rattletrap: decodeReplayJson :: ByteString -> Either String FullReplay
+ Rattletrap: decodeReplayJson :: ByteString -> Either String Replay
- Rattletrap: encodeReplayFile :: Bool -> FullReplay -> ByteString
+ Rattletrap: encodeReplayFile :: Bool -> Replay -> ByteString
- Rattletrap: encodeReplayJson :: FullReplay -> ByteString
+ Rattletrap: encodeReplayJson :: Replay -> ByteString

Files

rattletrap.cabal view
@@ -1,7 +1,7 @@-cabal-version: >= 1.10+cabal-version: 2.0  name: rattletrap-version: 9.4.1+version: 10.0.0 synopsis: Parse and generate Rocket League replays. description: Rattletrap parses and generates Rocket League replays. @@ -16,16 +16,13 @@   type: git   location: https://github.com/tfausak/rattletrap -flag static-  manual: True-  default: False- library   autogen-modules: Paths_rattletrap   build-depends:     base >= 4.14.1 && < 4.15     , aeson >= 1.5.5 && < 1.6     , aeson-pretty >= 0.8.8 && < 0.9+    , array >= 0.5.4 && < 0.6     , binary >= 0.8.8 && < 0.9     , bytestring >= 0.10.12 && < 0.11     , caerbannog >= 0.6.0 && < 0.7@@ -33,288 +30,139 @@     , filepath >= 1.4.2 && < 1.5     , http-client >= 0.6.4 && < 0.8     , http-client-tls >= 0.3.5 && < 0.4-    , scientific >= 0.3.6 && < 0.4-    , template-haskell >= 2.16.0 && < 2.17     , text >= 1.2.4 && < 1.3     , transformers >= 0.5.6 && < 0.6+  default-extensions: NamedFieldPuns   default-language: Haskell2010-  exposed-modules: Rattletrap-  ghc-options:-    -Weverything-    -Wno-all-missed-specialisations-    -Wno-implicit-prelude-    -Wno-missing-deriving-strategies-    -Wno-missing-exported-signatures-    -Wno-missing-import-lists-    -Wno-safe-    -Wno-unsafe-  hs-source-dirs: src/lib-  other-modules:+  exposed-modules:     Paths_rattletrap+    Rattletrap+    Rattletrap.BitGet+    Rattletrap.BitPut+    Rattletrap.ByteGet+    Rattletrap.BytePut+    Rattletrap.Console.Config+    Rattletrap.Console.Flag     Rattletrap.Console.Main+    Rattletrap.Console.Mode+    Rattletrap.Console.Option     Rattletrap.Data-    Rattletrap.Decode.AppliedDamageAttribute-    Rattletrap.Decode.Attribute-    Rattletrap.Decode.AttributeMapping-    Rattletrap.Decode.AttributeValue-    Rattletrap.Decode.BooleanAttribute-    Rattletrap.Decode.ByteAttribute-    Rattletrap.Decode.Cache-    Rattletrap.Decode.CamSettingsAttribute-    Rattletrap.Decode.ClassMapping-    Rattletrap.Decode.ClubColorsAttribute-    Rattletrap.Decode.Common-    Rattletrap.Decode.CompressedWord-    Rattletrap.Decode.CompressedWordVector-    Rattletrap.Decode.Content-    Rattletrap.Decode.CustomDemolishAttribute-    Rattletrap.Decode.DamageStateAttribute-    Rattletrap.Decode.DemolishAttribute-    Rattletrap.Decode.DestroyedReplication-    Rattletrap.Decode.Dictionary-    Rattletrap.Decode.EnumAttribute-    Rattletrap.Decode.ExplosionAttribute-    Rattletrap.Decode.ExtendedExplosionAttribute-    Rattletrap.Decode.FlaggedIntAttribute-    Rattletrap.Decode.FlaggedByteAttribute-    Rattletrap.Decode.Float32le-    Rattletrap.Decode.FloatAttribute-    Rattletrap.Decode.Frame-    Rattletrap.Decode.GameModeAttribute-    Rattletrap.Decode.Header-    Rattletrap.Decode.Initialization-    Rattletrap.Decode.Int32le-    Rattletrap.Decode.Int64Attribute-    Rattletrap.Decode.Int64le-    Rattletrap.Decode.Int8le-    Rattletrap.Decode.Int8Vector-    Rattletrap.Decode.IntAttribute-    Rattletrap.Decode.KeyFrame-    Rattletrap.Decode.List-    Rattletrap.Decode.LoadoutAttribute-    Rattletrap.Decode.LoadoutOnlineAttribute-    Rattletrap.Decode.LoadoutsAttribute-    Rattletrap.Decode.LoadoutsOnlineAttribute-    Rattletrap.Decode.LocationAttribute-    Rattletrap.Decode.Mark-    Rattletrap.Decode.Message-    Rattletrap.Decode.MusicStingerAttribute-    Rattletrap.Decode.PartyLeaderAttribute-    Rattletrap.Decode.PickupAttribute-    Rattletrap.Decode.PickupAttributeNew-    Rattletrap.Decode.PlayerHistoryKeyAttribute-    Rattletrap.Decode.PrivateMatchSettingsAttribute-    Rattletrap.Decode.ProductAttribute-    Rattletrap.Decode.Property-    Rattletrap.Decode.PropertyValue-    Rattletrap.Decode.Quaternion-    Rattletrap.Decode.QWordAttribute-    Rattletrap.Decode.RemoteId-    Rattletrap.Decode.Replay-    Rattletrap.Decode.Replication-    Rattletrap.Decode.ReplicationValue-    Rattletrap.Decode.ReservationAttribute-    Rattletrap.Decode.RigidBodyStateAttribute-    Rattletrap.Decode.Rotation-    Rattletrap.Decode.Section-    Rattletrap.Decode.SpawnedReplication-    Rattletrap.Decode.StatEventAttribute-    Rattletrap.Decode.Str-    Rattletrap.Decode.StringAttribute-    Rattletrap.Decode.TeamPaintAttribute-    Rattletrap.Decode.TitleAttribute-    Rattletrap.Decode.UniqueIdAttribute-    Rattletrap.Decode.UpdatedReplication-    Rattletrap.Decode.Vector-    Rattletrap.Decode.WeldedInfoAttribute-    Rattletrap.Decode.Word32le-    Rattletrap.Decode.Word64le-    Rattletrap.Decode.Word8le-    Rattletrap.Encode.AppliedDamageAttribute-    Rattletrap.Encode.Attribute-    Rattletrap.Encode.AttributeMapping-    Rattletrap.Encode.AttributeValue-    Rattletrap.Encode.BooleanAttribute-    Rattletrap.Encode.ByteAttribute-    Rattletrap.Encode.Cache-    Rattletrap.Encode.CamSettingsAttribute-    Rattletrap.Encode.ClassMapping-    Rattletrap.Encode.ClubColorsAttribute-    Rattletrap.Encode.Common-    Rattletrap.Encode.CompressedWord-    Rattletrap.Encode.CompressedWordVector-    Rattletrap.Encode.Content-    Rattletrap.Encode.CustomDemolishAttribute-    Rattletrap.Encode.DamageStateAttribute-    Rattletrap.Encode.DemolishAttribute-    Rattletrap.Encode.DestroyedReplication-    Rattletrap.Encode.Dictionary-    Rattletrap.Encode.EnumAttribute-    Rattletrap.Encode.ExplosionAttribute-    Rattletrap.Encode.ExtendedExplosionAttribute-    Rattletrap.Encode.FlaggedIntAttribute-    Rattletrap.Encode.FlaggedByteAttribute-    Rattletrap.Encode.Float32le-    Rattletrap.Encode.FloatAttribute-    Rattletrap.Encode.Frame-    Rattletrap.Encode.GameModeAttribute-    Rattletrap.Encode.Header-    Rattletrap.Encode.Initialization-    Rattletrap.Encode.Int32le-    Rattletrap.Encode.Int64Attribute-    Rattletrap.Encode.Int64le-    Rattletrap.Encode.Int8le-    Rattletrap.Encode.Int8Vector-    Rattletrap.Encode.IntAttribute-    Rattletrap.Encode.KeyFrame-    Rattletrap.Encode.List-    Rattletrap.Encode.LoadoutAttribute-    Rattletrap.Encode.LoadoutOnlineAttribute-    Rattletrap.Encode.LoadoutsAttribute-    Rattletrap.Encode.LoadoutsOnlineAttribute-    Rattletrap.Encode.LocationAttribute-    Rattletrap.Encode.Mark-    Rattletrap.Encode.Message-    Rattletrap.Encode.MusicStingerAttribute-    Rattletrap.Encode.PartyLeaderAttribute-    Rattletrap.Encode.PickupAttribute-    Rattletrap.Encode.PickupAttributeNew-    Rattletrap.Encode.PlayerHistoryKeyAttribute-    Rattletrap.Encode.PrivateMatchSettingsAttribute-    Rattletrap.Encode.ProductAttribute-    Rattletrap.Encode.Property-    Rattletrap.Encode.PropertyValue-    Rattletrap.Encode.Quaternion-    Rattletrap.Encode.QWordAttribute-    Rattletrap.Encode.RemoteId-    Rattletrap.Encode.Replay-    Rattletrap.Encode.Replication-    Rattletrap.Encode.ReplicationValue-    Rattletrap.Encode.ReservationAttribute-    Rattletrap.Encode.RigidBodyStateAttribute-    Rattletrap.Encode.Rotation-    Rattletrap.Encode.Section-    Rattletrap.Encode.SpawnedReplication-    Rattletrap.Encode.StatEventAttribute-    Rattletrap.Encode.Str-    Rattletrap.Encode.StringAttribute-    Rattletrap.Encode.TeamPaintAttribute-    Rattletrap.Encode.TitleAttribute-    Rattletrap.Encode.UniqueIdAttribute-    Rattletrap.Encode.UpdatedReplication-    Rattletrap.Encode.Vector-    Rattletrap.Encode.WeldedInfoAttribute-    Rattletrap.Encode.Word32le-    Rattletrap.Encode.Word64le-    Rattletrap.Encode.Word8le-    Rattletrap.Type.AppliedDamageAttribute+    Rattletrap.Get+    Rattletrap.Schema     Rattletrap.Type.Attribute+    Rattletrap.Type.Attribute.AppliedDamage+    Rattletrap.Type.Attribute.Boolean+    Rattletrap.Type.Attribute.Byte+    Rattletrap.Type.Attribute.CamSettings+    Rattletrap.Type.Attribute.ClubColors+    Rattletrap.Type.Attribute.CustomDemolish+    Rattletrap.Type.Attribute.DamageState+    Rattletrap.Type.Attribute.Demolish+    Rattletrap.Type.Attribute.Enum+    Rattletrap.Type.Attribute.Explosion+    Rattletrap.Type.Attribute.ExtendedExplosion+    Rattletrap.Type.Attribute.FlaggedByte+    Rattletrap.Type.Attribute.FlaggedInt+    Rattletrap.Type.Attribute.Float+    Rattletrap.Type.Attribute.GameMode+    Rattletrap.Type.Attribute.Int+    Rattletrap.Type.Attribute.Int64+    Rattletrap.Type.Attribute.Loadout+    Rattletrap.Type.Attribute.LoadoutOnline+    Rattletrap.Type.Attribute.Loadouts+    Rattletrap.Type.Attribute.LoadoutsOnline+    Rattletrap.Type.Attribute.Location+    Rattletrap.Type.Attribute.MusicStinger+    Rattletrap.Type.Attribute.PartyLeader+    Rattletrap.Type.Attribute.Pickup+    Rattletrap.Type.Attribute.PickupNew+    Rattletrap.Type.Attribute.PlayerHistoryKey+    Rattletrap.Type.Attribute.PrivateMatchSettings+    Rattletrap.Type.Attribute.Product+    Rattletrap.Type.Attribute.ProductValue+    Rattletrap.Type.Attribute.QWord+    Rattletrap.Type.Attribute.Reservation+    Rattletrap.Type.Attribute.RigidBodyState+    Rattletrap.Type.Attribute.StatEvent+    Rattletrap.Type.Attribute.String+    Rattletrap.Type.Attribute.TeamPaint+    Rattletrap.Type.Attribute.Title+    Rattletrap.Type.Attribute.UniqueId+    Rattletrap.Type.Attribute.WeldedInfo     Rattletrap.Type.AttributeMapping     Rattletrap.Type.AttributeType     Rattletrap.Type.AttributeValue-    Rattletrap.Type.BooleanAttribute-    Rattletrap.Type.ByteAttribute     Rattletrap.Type.Cache-    Rattletrap.Type.CamSettingsAttribute     Rattletrap.Type.ClassAttributeMap     Rattletrap.Type.ClassMapping-    Rattletrap.Type.ClubColorsAttribute-    Rattletrap.Type.Common     Rattletrap.Type.CompressedWord     Rattletrap.Type.CompressedWordVector     Rattletrap.Type.Content-    Rattletrap.Type.CustomDemolishAttribute-    Rattletrap.Type.DamageStateAttribute-    Rattletrap.Type.DemolishAttribute-    Rattletrap.Type.DestroyedReplication     Rattletrap.Type.Dictionary-    Rattletrap.Type.EnumAttribute-    Rattletrap.Type.ExplosionAttribute-    Rattletrap.Type.ExtendedExplosionAttribute-    Rattletrap.Type.FlaggedIntAttribute-    Rattletrap.Type.FlaggedByteAttribute-    Rattletrap.Type.Float32le-    Rattletrap.Type.FloatAttribute+    Rattletrap.Type.F32     Rattletrap.Type.Frame-    Rattletrap.Type.GameModeAttribute     Rattletrap.Type.Header+    Rattletrap.Type.I32+    Rattletrap.Type.I64+    Rattletrap.Type.I8     Rattletrap.Type.Initialization-    Rattletrap.Type.Int32le-    Rattletrap.Type.Int64Attribute-    Rattletrap.Type.Int64le-    Rattletrap.Type.Int8le     Rattletrap.Type.Int8Vector-    Rattletrap.Type.IntAttribute     Rattletrap.Type.KeyFrame     Rattletrap.Type.List-    Rattletrap.Type.LoadoutAttribute-    Rattletrap.Type.LoadoutOnlineAttribute-    Rattletrap.Type.LoadoutsAttribute-    Rattletrap.Type.LoadoutsOnlineAttribute-    Rattletrap.Type.LocationAttribute     Rattletrap.Type.Mark     Rattletrap.Type.Message-    Rattletrap.Type.MusicStingerAttribute-    Rattletrap.Type.PartyLeaderAttribute-    Rattletrap.Type.PickupAttribute-    Rattletrap.Type.PickupAttributeNew-    Rattletrap.Type.PlayerHistoryKeyAttribute-    Rattletrap.Type.PrivateMatchSettingsAttribute-    Rattletrap.Type.ProductAttribute     Rattletrap.Type.Property     Rattletrap.Type.PropertyValue     Rattletrap.Type.Quaternion-    Rattletrap.Type.QWordAttribute     Rattletrap.Type.RemoteId     Rattletrap.Type.Replay     Rattletrap.Type.Replication+    Rattletrap.Type.Replication.Destroyed+    Rattletrap.Type.Replication.Spawned+    Rattletrap.Type.Replication.Updated     Rattletrap.Type.ReplicationValue-    Rattletrap.Type.ReservationAttribute-    Rattletrap.Type.RigidBodyStateAttribute     Rattletrap.Type.Rotation     Rattletrap.Type.Section-    Rattletrap.Type.SpawnedReplication-    Rattletrap.Type.StatEventAttribute     Rattletrap.Type.Str-    Rattletrap.Type.StringAttribute-    Rattletrap.Type.TeamPaintAttribute-    Rattletrap.Type.TitleAttribute-    Rattletrap.Type.UniqueIdAttribute-    Rattletrap.Type.UpdatedReplication+    Rattletrap.Type.U32+    Rattletrap.Type.U64+    Rattletrap.Type.U8     Rattletrap.Type.Vector-    Rattletrap.Type.WeldedInfoAttribute-    Rattletrap.Type.Word32le-    Rattletrap.Type.Word64le-    Rattletrap.Type.Word8le+    Rattletrap.Type.Version     Rattletrap.Utility.Bytes     Rattletrap.Utility.Crc     Rattletrap.Utility.Helper--  if impl(ghc >= 8.10)-    ghc-options:-      -Wno-missing-safe-haskell-mode-      -Wno-prepositive-qualified-module+    Rattletrap.Utility.Json+    Rattletrap.Utility.Monad+    Rattletrap.Version+  ghc-options:+    -Weverything+    -Wno-all-missed-specialisations+    -Wno-implicit-prelude+    -Wno-missing-deriving-strategies+    -Wno-missing-export-lists+    -Wno-missing-exported-signatures+    -Wno-missing-import-lists+    -Wno-missing-safe-haskell-mode+    -Wno-prepositive-qualified-module+    -Wno-safe+    -Wno-unsafe+  hs-source-dirs: src/lib  executable rattletrap-  build-depends:-    base -any-    , rattletrap -any+  build-depends: base, rattletrap   default-language: Haskell2010   ghc-options: -rtsopts -threaded   hs-source-dirs: src/exe   main-is: Main.hs -  if flag(static)-    ld-options: -static- test-suite test   build-depends:-    base -any-    , bytestring -any-    , filepath -any+    base+    , bytestring+    , filepath     , HUnit >= 1.6.1 && < 1.7-    , rattletrap -any-    , temporary >= 1.3 && < 1.4+    , rattletrap   default-language: Haskell2010   ghc-options: -rtsopts -threaded   hs-source-dirs: src/test
src/exe/Main.hs view
@@ -1,6 +1,5 @@ module Main   ( main-  )-where+  ) where  import Rattletrap (main)
src/lib/Rattletrap.hs view
@@ -5,158 +5,7 @@   , Rattletrap.Utility.Helper.encodeReplayJson   , Rattletrap.Utility.Helper.decodeReplayJson   , Rattletrap.Utility.Helper.encodeReplayFile-  , Rattletrap.Type.AppliedDamageAttribute.AppliedDamageAttribute(..)-  , Rattletrap.Type.Attribute.Attribute(..)-  , Rattletrap.Type.AttributeMapping.AttributeMapping(..)-  , Rattletrap.Type.AttributeType.AttributeType(..)-  , Rattletrap.Type.AttributeValue.AttributeValue(..)-  , Rattletrap.Type.BooleanAttribute.BooleanAttribute(..)-  , Rattletrap.Type.ByteAttribute.ByteAttribute(..)-  , Rattletrap.Type.Cache.Cache(..)-  , Rattletrap.Type.CamSettingsAttribute.CamSettingsAttribute(..)-  , Rattletrap.Type.ClassAttributeMap.ClassAttributeMap(..)-  , Rattletrap.Type.ClassMapping.ClassMapping(..)-  , Rattletrap.Type.ClubColorsAttribute.ClubColorsAttribute(..)-  , Rattletrap.Type.CompressedWord.CompressedWord(..)-  , Rattletrap.Type.CompressedWordVector.CompressedWordVector(..)-  , Rattletrap.Type.Content.Content(..)-  , Rattletrap.Type.DamageStateAttribute.DamageStateAttribute(..)-  , Rattletrap.Type.DemolishAttribute.DemolishAttribute(..)-  , Rattletrap.Type.DestroyedReplication.DestroyedReplication(..)-  , Rattletrap.Type.Dictionary.Dictionary(..)-  , Rattletrap.Type.EnumAttribute.EnumAttribute(..)-  , Rattletrap.Type.ExplosionAttribute.ExplosionAttribute(..)-  , Rattletrap.Type.ExtendedExplosionAttribute.ExtendedExplosionAttribute(..)-  , Rattletrap.Type.FlaggedIntAttribute.FlaggedIntAttribute(..)-  , Rattletrap.Type.Float32le.Float32le(..)-  , Rattletrap.Type.FloatAttribute.FloatAttribute(..)-  , Rattletrap.Type.Frame.Frame(..)-  , Rattletrap.Type.GameModeAttribute.GameModeAttribute(..)-  , Rattletrap.Type.Header.Header(..)-  , Rattletrap.Type.Initialization.Initialization(..)-  , Rattletrap.Type.Int32le.Int32le(..)-  , Rattletrap.Type.Int64Attribute.Int64Attribute(..)-  , Rattletrap.Type.Int64le.Int64le(..)-  , Rattletrap.Type.Int8le.Int8le(..)-  , Rattletrap.Type.Int8Vector.Int8Vector(..)-  , Rattletrap.Type.IntAttribute.IntAttribute(..)-  , Rattletrap.Type.KeyFrame.KeyFrame(..)-  , Rattletrap.Type.List.List(..)-  , Rattletrap.Type.LoadoutAttribute.LoadoutAttribute(..)-  , Rattletrap.Type.LoadoutOnlineAttribute.LoadoutOnlineAttribute(..)-  , Rattletrap.Type.LoadoutsAttribute.LoadoutsAttribute(..)-  , Rattletrap.Type.LoadoutsOnlineAttribute.LoadoutsOnlineAttribute(..)-  , Rattletrap.Type.LocationAttribute.LocationAttribute(..)-  , Rattletrap.Type.Mark.Mark(..)-  , Rattletrap.Type.Message.Message(..)-  , Rattletrap.Type.MusicStingerAttribute.MusicStingerAttribute(..)-  , Rattletrap.Type.PartyLeaderAttribute.PartyLeaderAttribute(..)-  , Rattletrap.Type.PickupAttribute.PickupAttribute(..)-  , Rattletrap.Type.PlayerHistoryKeyAttribute.PlayerHistoryKeyAttribute(..)-  , Rattletrap.Type.PrivateMatchSettingsAttribute.PrivateMatchSettingsAttribute(..)-  , Rattletrap.Type.ProductAttribute.ProductAttribute(..)-  , Rattletrap.Type.Property.Property(..)-  , Rattletrap.Type.PropertyValue.PropertyValue(..)-  , Rattletrap.Type.Quaternion.Quaternion(..)-  , Rattletrap.Type.QWordAttribute.QWordAttribute(..)-  , Rattletrap.Type.RemoteId.RemoteId(..)-  , Rattletrap.Type.Replay.Replay(..)-  , Rattletrap.Type.Replication.Replication(..)-  , Rattletrap.Type.ReplicationValue.ReplicationValue(..)-  , Rattletrap.Type.ReservationAttribute.ReservationAttribute(..)-  , Rattletrap.Type.RigidBodyStateAttribute.RigidBodyStateAttribute(..)-  , Rattletrap.Type.Rotation.Rotation(..)-  , Rattletrap.Type.Section.Section(..)-  , Rattletrap.Type.SpawnedReplication.SpawnedReplication(..)-  , Rattletrap.Type.StatEventAttribute.StatEventAttribute(..)-  , Rattletrap.Type.Str.Str(..)-  , Rattletrap.Type.StringAttribute.StringAttribute(..)-  , Rattletrap.Type.TeamPaintAttribute.TeamPaintAttribute(..)-  , Rattletrap.Type.TitleAttribute.TitleAttribute(..)-  , Rattletrap.Type.UniqueIdAttribute.UniqueIdAttribute(..)-  , Rattletrap.Type.UpdatedReplication.UpdatedReplication(..)-  , Rattletrap.Type.Vector.Vector(..)-  , Rattletrap.Type.WeldedInfoAttribute.WeldedInfoAttribute(..)-  , Rattletrap.Type.Word32le.Word32le(..)-  , Rattletrap.Type.Word64le.Word64le(..)-  , Rattletrap.Type.Word8le.Word8le(..)-  )-where+  ) where  import qualified Rattletrap.Console.Main-import qualified Rattletrap.Type.AppliedDamageAttribute-import qualified Rattletrap.Type.Attribute-import qualified Rattletrap.Type.AttributeMapping-import qualified Rattletrap.Type.AttributeType-import qualified Rattletrap.Type.AttributeValue-import qualified Rattletrap.Type.BooleanAttribute-import qualified Rattletrap.Type.ByteAttribute-import qualified Rattletrap.Type.Cache-import qualified Rattletrap.Type.CamSettingsAttribute-import qualified Rattletrap.Type.ClassAttributeMap-import qualified Rattletrap.Type.ClassMapping-import qualified Rattletrap.Type.ClubColorsAttribute-import qualified Rattletrap.Type.CompressedWord-import qualified Rattletrap.Type.CompressedWordVector-import qualified Rattletrap.Type.Content-import qualified Rattletrap.Type.DamageStateAttribute-import qualified Rattletrap.Type.DemolishAttribute-import qualified Rattletrap.Type.DestroyedReplication-import qualified Rattletrap.Type.Dictionary-import qualified Rattletrap.Type.EnumAttribute-import qualified Rattletrap.Type.ExplosionAttribute-import qualified Rattletrap.Type.ExtendedExplosionAttribute-import qualified Rattletrap.Type.FlaggedIntAttribute-import qualified Rattletrap.Type.Float32le-import qualified Rattletrap.Type.FloatAttribute-import qualified Rattletrap.Type.Frame-import qualified Rattletrap.Type.GameModeAttribute-import qualified Rattletrap.Type.Header-import qualified Rattletrap.Type.Initialization-import qualified Rattletrap.Type.Int32le-import qualified Rattletrap.Type.Int64Attribute-import qualified Rattletrap.Type.Int64le-import qualified Rattletrap.Type.Int8le-import qualified Rattletrap.Type.Int8Vector-import qualified Rattletrap.Type.IntAttribute-import qualified Rattletrap.Type.KeyFrame-import qualified Rattletrap.Type.List-import qualified Rattletrap.Type.LoadoutAttribute-import qualified Rattletrap.Type.LoadoutOnlineAttribute-import qualified Rattletrap.Type.LoadoutsAttribute-import qualified Rattletrap.Type.LoadoutsOnlineAttribute-import qualified Rattletrap.Type.LocationAttribute-import qualified Rattletrap.Type.Mark-import qualified Rattletrap.Type.Message-import qualified Rattletrap.Type.MusicStingerAttribute-import qualified Rattletrap.Type.PartyLeaderAttribute-import qualified Rattletrap.Type.PickupAttribute-import qualified Rattletrap.Type.PlayerHistoryKeyAttribute-import qualified Rattletrap.Type.PrivateMatchSettingsAttribute-import qualified Rattletrap.Type.ProductAttribute-import qualified Rattletrap.Type.Property-import qualified Rattletrap.Type.PropertyValue-import qualified Rattletrap.Type.Quaternion-import qualified Rattletrap.Type.QWordAttribute-import qualified Rattletrap.Type.RemoteId-import qualified Rattletrap.Type.Replay-import qualified Rattletrap.Type.Replication-import qualified Rattletrap.Type.ReplicationValue-import qualified Rattletrap.Type.ReservationAttribute-import qualified Rattletrap.Type.RigidBodyStateAttribute-import qualified Rattletrap.Type.Rotation-import qualified Rattletrap.Type.Section-import qualified Rattletrap.Type.SpawnedReplication-import qualified Rattletrap.Type.StatEventAttribute-import qualified Rattletrap.Type.Str-import qualified Rattletrap.Type.StringAttribute-import qualified Rattletrap.Type.TeamPaintAttribute-import qualified Rattletrap.Type.TitleAttribute-import qualified Rattletrap.Type.UniqueIdAttribute-import qualified Rattletrap.Type.UpdatedReplication-import qualified Rattletrap.Type.Vector-import qualified Rattletrap.Type.WeldedInfoAttribute-import qualified Rattletrap.Type.Word32le-import qualified Rattletrap.Type.Word64le-import qualified Rattletrap.Type.Word8le import qualified Rattletrap.Utility.Helper
+ src/lib/Rattletrap/BitGet.hs view
@@ -0,0 +1,48 @@+module Rattletrap.BitGet where++import qualified Control.Monad as Monad+import qualified Data.Binary.Bits.Get as BinaryBits+import qualified Data.Binary.Get as Binary+import qualified Data.Bits as Bits+import qualified Data.ByteString as ByteString+import qualified Data.ByteString.Lazy as LazyByteString+import qualified Data.Word as Word+import qualified Rattletrap.ByteGet as ByteGet+import qualified Rattletrap.Get as Get+import qualified Rattletrap.Utility.Bytes as Utility++type BitGet = BinaryBits.BitGet++toByteGet :: BitGet a -> ByteGet.ByteGet a+toByteGet = binaryGetToByteGet . BinaryBits.runBitGet++binaryGetToByteGet :: Binary.Get a -> ByteGet.ByteGet a+binaryGetToByteGet g = do+  s1 <- Get.get+  case Binary.runGetOrFail g $ LazyByteString.fromStrict s1 of+    Left (_, _, x) -> fail x+    Right (s2, _, x) -> do+      Get.put $ LazyByteString.toStrict s2+      pure x++fromByteGet :: ByteGet.ByteGet a -> Int -> BitGet a+fromByteGet f n = do+  x <- BinaryBits.getByteString n+  either fail pure . ByteGet.run f $ Utility.reverseBytes x++bits :: Bits.Bits a => Int -> BitGet a+bits n =+  foldr+      (\bit x -> let y = Bits.shiftL x 1 in if bit then Bits.setBit y 0 else y+      )+      Bits.zeroBits+    <$> Monad.replicateM n bool++bool :: BitGet Bool+bool = BinaryBits.getBool++byteString :: Int -> BitGet ByteString.ByteString+byteString = BinaryBits.getByteString++word8 :: Int -> BitGet Word.Word8+word8 = BinaryBits.getWord8
+ src/lib/Rattletrap/BitPut.hs view
@@ -0,0 +1,41 @@+module Rattletrap.BitPut where++import qualified Data.Binary.Bits.Put as BinaryBits+import qualified Data.Binary.Put as Binary+import qualified Data.Bits as Bits+import qualified Data.ByteString as ByteString+import qualified Data.Word as Word+import qualified Rattletrap.BytePut as BytePut+import qualified Rattletrap.Utility.Bytes as Utility++newtype BitPut = BitPut (BinaryBits.BitPut ())++instance Semigroup BitPut where+  x <> y = fromBinaryBits $ toBinaryBits x >> toBinaryBits y++instance Monoid BitPut where+  mempty = fromBinaryBits $ pure ()++fromBinaryBits :: BinaryBits.BitPut () -> BitPut+fromBinaryBits = BitPut++toBinaryBits :: BitPut -> BinaryBits.BitPut ()+toBinaryBits (BitPut x) = x++toBytePut :: BitPut -> BytePut.BytePut+toBytePut = Binary.execPut . BinaryBits.runBitPut . toBinaryBits++fromBytePut :: BytePut.BytePut -> BitPut+fromBytePut = byteString . Utility.reverseBytes . BytePut.toByteString++bits :: Bits.Bits a => Int -> a -> BitPut+bits n x = foldMap (bool . Bits.testBit x) [0 .. n - 1]++bool :: Bool -> BitPut+bool = fromBinaryBits . BinaryBits.putBool++byteString :: ByteString.ByteString -> BitPut+byteString = fromBinaryBits . BinaryBits.putByteString++word8 :: Int -> Word.Word8 -> BitPut+word8 n = fromBinaryBits . BinaryBits.putWord8 n
+ src/lib/Rattletrap/ByteGet.hs view
@@ -0,0 +1,65 @@+module Rattletrap.ByteGet where++import qualified Data.Bits as Bits+import qualified Data.ByteString as ByteString+import qualified Data.ByteString.Lazy as LazyByteString+import qualified Data.Functor.Identity as Identity+import qualified Data.Int as Int+import qualified Data.Word as Word+import qualified GHC.Float as Float+import qualified Rattletrap.Get as Get++type ByteGet = Get.Get ByteString.ByteString Identity.Identity++run :: ByteGet a -> ByteString.ByteString -> Either String a+run g = fmap snd . Identity.runIdentity . Get.run g++byteString :: Int -> ByteGet ByteString.ByteString+byteString n = do+  s1 <- Get.get+  let (x, s2) = ByteString.splitAt n s1+  Get.put s2+  pure x++float :: ByteGet Float+float = Float.castWord32ToFloat <$> word32++int8 :: ByteGet Int.Int8+int8 = fromIntegral <$> word8++int32 :: ByteGet Int.Int32+int32 = fromIntegral <$> word32++int64 :: ByteGet Int.Int64+int64 = fromIntegral <$> word64++remaining :: ByteGet LazyByteString.ByteString+remaining = do+  x <- Get.get+  Get.put ByteString.empty+  pure $ LazyByteString.fromStrict x++word8 :: ByteGet Word.Word8+word8 = ByteString.head <$> byteString 1++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++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
+ src/lib/Rattletrap/BytePut.hs view
@@ -0,0 +1,39 @@+module Rattletrap.BytePut where++import qualified Data.ByteString as ByteString+import qualified Data.ByteString.Builder as Builder+import qualified Data.ByteString.Lazy as LazyByteString+import qualified Data.Int as Int+import qualified Data.Word as Word++type BytePut = Builder.Builder++toByteString :: BytePut -> ByteString.ByteString+toByteString = LazyByteString.toStrict . toLazyByteString++toLazyByteString :: BytePut -> LazyByteString.ByteString+toLazyByteString = Builder.toLazyByteString++byteString :: ByteString.ByteString -> BytePut+byteString = Builder.byteString++float :: Float -> BytePut+float = Builder.floatLE++int8 :: Int.Int8 -> BytePut+int8 = Builder.int8++int32 :: Int.Int32 -> BytePut+int32 = Builder.int32LE++int64 :: Int.Int64 -> BytePut+int64 = Builder.int64LE++word8 :: Word.Word8 -> BytePut+word8 = Builder.word8++word32 :: Word.Word32 -> BytePut+word32 = Builder.word32LE++word64 :: Word.Word64 -> BytePut+word64 = Builder.word64LE
+ src/lib/Rattletrap/Console/Config.hs view
@@ -0,0 +1,57 @@+module Rattletrap.Console.Config where++import qualified Rattletrap.Console.Flag as Flag+import qualified Rattletrap.Console.Mode as Mode+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+  }+  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+  }++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.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 }++getMode :: Config -> Mode.Mode+getMode config =+  let+    i = FilePath.takeExtension <$> input config+    o = 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
+ src/lib/Rattletrap/Console/Flag.hs view
@@ -0,0 +1,13 @@+module Rattletrap.Console.Flag where++data Flag+  = Compact+  | Fast+  | Help+  | Input FilePath+  | Mode String+  | Output FilePath+  | Schema+  | SkipCrc+  | Version+  deriving (Eq, Show)
src/lib/Rattletrap/Console/Main.hs view
@@ -1,25 +1,103 @@ module Rattletrap.Console.Main   ( main   , rattletrap-  )-where+  ) where  import qualified Control.Monad as Monad-import qualified Data.Aeson as Json-import qualified Data.ByteString as Bytes-import qualified Data.ByteString.Lazy as LazyBytes-import qualified Data.Version as Version+import qualified Data.Aeson as Aeson+import qualified Data.Aeson.Encode.Pretty as Aeson+import qualified Data.ByteString as ByteString+import qualified Data.ByteString.Lazy as LazyByteString import qualified Network.HTTP.Client as Client import qualified Network.HTTP.Client.TLS as Client-import qualified Paths_rattletrap as This-import qualified Rattletrap.Type.Replay as Rattletrap+import qualified Rattletrap.Console.Config as Config+import qualified Rattletrap.Console.Mode as Mode+import qualified Rattletrap.Console.Option as Option+import qualified Rattletrap.Schema as Schema+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.Byte as Attribute.Byte+import qualified Rattletrap.Type.Attribute.CamSettings as Attribute.CamSettings+import qualified Rattletrap.Type.Attribute.ClubColors as Attribute.ClubColors+import qualified Rattletrap.Type.Attribute.CustomDemolish as Attribute.CustomDemolish+import qualified Rattletrap.Type.Attribute.DamageState as Attribute.DamageState+import qualified Rattletrap.Type.Attribute.Demolish as Attribute.Demolish+import qualified Rattletrap.Type.Attribute.Enum as Attribute.Enum+import qualified Rattletrap.Type.Attribute.Explosion as Attribute.Explosion+import qualified Rattletrap.Type.Attribute.ExtendedExplosion as Attribute.ExtendedExplosion+import qualified Rattletrap.Type.Attribute.FlaggedByte as Attribute.FlaggedByte+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.Int as Attribute.Int+import qualified Rattletrap.Type.Attribute.Int64 as Attribute.Int64+import qualified Rattletrap.Type.Attribute.Loadout as Attribute.Loadout+import qualified Rattletrap.Type.Attribute.LoadoutOnline as Attribute.LoadoutOnline+import qualified Rattletrap.Type.Attribute.Loadouts as Attribute.Loadouts+import qualified Rattletrap.Type.Attribute.LoadoutsOnline as Attribute.LoadoutsOnline+import qualified Rattletrap.Type.Attribute.Location as Attribute.Location+import qualified Rattletrap.Type.Attribute.MusicStinger as Attribute.MusicStinger+import qualified Rattletrap.Type.Attribute.PartyLeader as Attribute.PartyLeader+import qualified Rattletrap.Type.Attribute.Pickup as Attribute.Pickup+import qualified Rattletrap.Type.Attribute.PickupNew as Attribute.PickupNew+import qualified Rattletrap.Type.Attribute.PlayerHistoryKey as Attribute.PlayerHistoryKey+import qualified Rattletrap.Type.Attribute.PrivateMatchSettings as Attribute.PrivateMatchSettings+import qualified Rattletrap.Type.Attribute.Product as Attribute.Product+import qualified Rattletrap.Type.Attribute.ProductValue as Attribute.ProductValue+import qualified Rattletrap.Type.Attribute.QWord as Attribute.QWord+import qualified Rattletrap.Type.Attribute.Reservation as Attribute.Reservation+import qualified Rattletrap.Type.Attribute.RigidBodyState as Attribute.RigidBodyState+import qualified Rattletrap.Type.Attribute.StatEvent as Attribute.StatEvent+import qualified Rattletrap.Type.Attribute.String as Attribute.String+import qualified Rattletrap.Type.Attribute.TeamPaint as Attribute.TeamPaint+import qualified Rattletrap.Type.Attribute.Title as Attribute.Title+import qualified Rattletrap.Type.Attribute.UniqueId as Attribute.UniqueId+import qualified Rattletrap.Type.Attribute.WeldedInfo as Attribute.WeldedInfo+import qualified Rattletrap.Type.AttributeMapping as AttributeMapping+import qualified Rattletrap.Type.AttributeValue as AttributeValue+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.CompressedWordVector as CompressedWordVector+import qualified Rattletrap.Type.Content as Content+import qualified Rattletrap.Type.Dictionary as Dictionary+import qualified Rattletrap.Type.F32 as F32+import qualified Rattletrap.Type.Frame as Frame+import qualified Rattletrap.Type.Header as Header+import qualified Rattletrap.Type.I32 as I32+import qualified Rattletrap.Type.I64 as I64+import qualified Rattletrap.Type.I8 as I8+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.Mark as Mark+import qualified Rattletrap.Type.Message as Message+import qualified Rattletrap.Type.Property as Property+import qualified Rattletrap.Type.PropertyValue as PropertyValue+import qualified Rattletrap.Type.Quaternion as Quaternion+import qualified Rattletrap.Type.RemoteId as RemoteId+import qualified Rattletrap.Type.Replay as Replay+import qualified Rattletrap.Type.Replication as Replication+import qualified Rattletrap.Type.Replication.Destroyed as Replication.Destroyed+import qualified Rattletrap.Type.Replication.Spawned as Replication.Spawned+import qualified Rattletrap.Type.Replication.Updated as Replication.Updated+import qualified Rattletrap.Type.ReplicationValue as ReplicationValue+import qualified Rattletrap.Type.Rotation as Rotation+import qualified Rattletrap.Type.Section as Section+import qualified Rattletrap.Type.Str as Str+import qualified Rattletrap.Type.U32 as U32+import qualified Rattletrap.Type.U64 as U64+import qualified Rattletrap.Type.U8 as U8+import qualified Rattletrap.Type.Vector as Vector import qualified Rattletrap.Utility.Helper as Rattletrap+import qualified Rattletrap.Utility.Json as Json+import qualified Rattletrap.Version as Version import qualified System.Console.GetOpt as Console import qualified System.Environment as Environment import qualified System.Exit as Exit-import qualified System.FilePath as Path import qualified System.IO as IO-import qualified Text.Printf as Printf  main :: IO () main = do@@ -30,209 +108,180 @@ rattletrap :: String -> [String] -> IO () rattletrap name arguments = do   config <- getConfig arguments-  Monad.when (configHelp config) (printHelp name *> Exit.exitFailure)-  Monad.when (configVersion config) (printVersion *> Exit.exitFailure)+  if Config.help config+    then helpMain name+    else if Config.version config+      then versionMain+      else if Config.schema config+        then schemaMain config+        else defaultMain config++helpMain :: String -> IO ()+helpMain name = do+  putStr $ Console.usageInfo+    (unwords [name, "version", Version.string])+    Option.all++versionMain :: IO ()+versionMain = do+  putStrLn Version.string++schemaMain :: Config.Config -> IO ()+schemaMain config = do+  let+    json = Aeson.encodePretty'+      Aeson.defConfig+        { Aeson.confCompare = compare+        , Aeson.confIndent = Aeson.Tab+        , Aeson.confTrailingNewline = True+        }+      schema+  case Config.output config of+    Nothing -> LazyByteString.putStr json+    Just file -> LazyByteString.writeFile file json++defaultMain :: Config.Config -> IO ()+defaultMain config = do   input <- getInput config   let decode = getDecoder config   replay <- either fail pure (decode input)   let encode = getEncoder config   putOutput config (encode replay) -getDecoder :: Config -> Bytes.ByteString -> Either String Rattletrap.FullReplay-getDecoder config = case getMode config of-  ModeDecode -> Rattletrap.decodeReplayFile $ configFast config-  ModeEncode -> Rattletrap.decodeReplayJson+schema :: Aeson.Value+schema =+  let contentSchema = Content.schema $ List.schema Frame.schema+  in+    Aeson.object+      [ Json.pair "$schema" "https://json-schema.org/draft-07/schema"+      , Json.pair "$id" Replay.schemaUrl+      , Json.pair "$ref" "#/definitions/replay"+      , Json.pair "definitions" . Aeson.object $ fmap+        (\s -> Schema.name s Aeson..= 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.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.PickupNew.schema+        , Attribute.PlayerHistoryKey.schema+        , Attribute.PrivateMatchSettings.schema+        , Attribute.Product.schema+        , Attribute.ProductValue.schema+        , Attribute.QWord.schema+        , Attribute.Reservation.schema+        , Attribute.RigidBodyState.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+        , PropertyValue.schema Property.schema+        , Quaternion.schema+        , RemoteId.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+        ]+      ] -getEncoder :: Config -> Rattletrap.FullReplay -> Bytes.ByteString-getEncoder config = case getMode config of-  ModeDecode -> if configCompact config-    then LazyBytes.toStrict . Json.encode-    else Rattletrap.encodeReplayJson-  ModeEncode -> Rattletrap.encodeReplayFile $ configFast config+getDecoder+  :: Config.Config -> ByteString.ByteString -> Either String Replay.Replay+getDecoder config = case Config.getMode config of+  Mode.Decode ->+    Rattletrap.decodeReplayFile (Config.fast config) (Config.skipCrc config)+  Mode.Encode -> Rattletrap.decodeReplayJson -getInput :: Config -> IO Bytes.ByteString-getInput config = case configInput config of-  Nothing -> Bytes.getContents+getEncoder :: Config.Config -> Replay.Replay -> LazyByteString.ByteString+getEncoder config = case Config.getMode config of+  Mode.Decode ->+    if Config.compact config then Aeson.encode else Rattletrap.encodeReplayJson+  Mode.Encode -> Rattletrap.encodeReplayFile $ Config.fast config++getInput :: Config.Config -> IO ByteString.ByteString+getInput config = case Config.input config of+  Nothing -> ByteString.getContents   Just fileOrUrl -> case Client.parseUrlThrow fileOrUrl of-    Nothing -> Bytes.readFile fileOrUrl+    Nothing -> ByteString.readFile fileOrUrl     Just request -> do       manager <- Client.newTlsManager       response <- Client.httpLbs request manager-      pure (LazyBytes.toStrict (Client.responseBody response))+      pure (LazyByteString.toStrict (Client.responseBody response)) -putOutput :: Config -> Bytes.ByteString -> IO ()-putOutput = maybe Bytes.putStr Bytes.writeFile . configOutput+putOutput :: Config.Config -> LazyByteString.ByteString -> IO ()+putOutput =+  maybe LazyByteString.putStr LazyByteString.writeFile . Config.output -getConfig :: [String] -> IO Config+getConfig :: [String] -> IO Config.Config getConfig arguments = do   let-    (updates, unexpectedArguments, unknownOptions, problems) =-      Console.getOpt' Console.Permute options arguments-  printUnexpectedArguments unexpectedArguments-  printUnknownOptions unknownOptions-  printProblems problems+    (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_ problems $ \x -> IO.hPutStr IO.stderr $ "ERROR: " <> x   Monad.unless (null problems) Exit.exitFailure-  either fail pure (Monad.foldM applyUpdate defaultConfig updates)--type Option = Console.OptDescr Update--type Update = Config -> Either String Config--options :: [Option]-options =-  [ compactOption-  , fastOption-  , helpOption-  , inputOption-  , modeOption-  , outputOption-  , versionOption-  ]--compactOption :: Option-compactOption = Console.Option-  ['c']-  ["compact"]-  (Console.NoArg (\config -> pure config { configCompact = True }))-  "minify JSON output"--fastOption :: Option-fastOption = Console.Option-  ['f']-  ["fast"]-  (Console.NoArg (\config -> pure config { configFast = True }))-  "only encode or decode the header"--helpOption :: Option-helpOption = Console.Option-  ['h']-  ["help"]-  (Console.NoArg (\config -> pure config { configHelp = True }))-  "show the help"--inputOption :: Option-inputOption = Console.Option-  ['i']-  ["input"]-  (Console.ReqArg-    (\input config -> pure config { configInput = Just input })-    "FILE|URL"-  )-  "input file or URL"--modeOption :: Option-modeOption = Console.Option-  ['m']-  ["mode"]-  (Console.ReqArg-    (\rawMode config -> do-      mode <- parseMode rawMode-      pure config { configMode = Just mode }-    )-    "MODE"-  )-  "decode or encode"--outputOption :: Option-outputOption = Console.Option-  ['o']-  ["output"]-  (Console.ReqArg-    (\output config -> pure config { configOutput = Just output })-    "FILE"-  )-  "output file"--versionOption :: Option-versionOption = Console.Option-  ['v']-  ["version"]-  (Console.NoArg (\config -> pure config { configVersion = True }))-  "show the version"--applyUpdate :: Config -> Update -> Either String Config-applyUpdate config update = update config--data Config = Config-  { configCompact :: Bool-  , configFast :: Bool-  , configHelp :: Bool-  , configInput :: Maybe String-  , configMode :: Maybe Mode-  , configOutput :: Maybe String-  , configVersion :: Bool-  } deriving (Show)--defaultConfig :: Config-defaultConfig = Config-  { configCompact = False-  , configFast = False-  , configHelp = False-  , configInput = Nothing-  , configMode = Nothing-  , configOutput = Nothing-  , configVersion = False-  }--getMode :: Config -> Mode-getMode config = case getExtension (configInput config) of-  ".json" -> ModeEncode-  ".replay" -> ModeDecode-  _ -> case getExtension (configOutput config) of-    ".json" -> ModeDecode-    ".replay" -> ModeEncode-    _ -> ModeDecode--getExtension :: Maybe String -> String-getExtension = maybe "" Path.takeExtension--data Mode-  = ModeDecode-  | ModeEncode-  deriving (Show)--parseMode :: String -> Either String Mode-parseMode mode = case mode of-  "decode" -> Right ModeDecode-  "encode" -> Right ModeEncode-  _ -> Left (Printf.printf "invalid mode: %s" (show mode))--printUnexpectedArguments :: [String] -> IO ()-printUnexpectedArguments = mapM_ printUnexpectedArgument--printUnexpectedArgument :: String -> IO ()-printUnexpectedArgument =-  warnLn . Printf.printf "WARNING: unexpected argument `%s'"--printUnknownOptions :: [String] -> IO ()-printUnknownOptions = mapM_ printUnknownOption--printUnknownOption :: String -> IO ()-printUnknownOption = warnLn . Printf.printf "WARNING: unknown option `%s'"--printProblems :: [String] -> IO ()-printProblems = mapM_ printProblem--printProblem :: String -> IO ()-printProblem = warn . Printf.printf "ERROR: %s"--printHelp :: String -> IO ()-printHelp = warn . help--help :: String -> String-help name = Console.usageInfo (header name) options--header :: String -> String-header name = unwords [name, "version", version]--version :: String-version = Version.showVersion This.version--printVersion :: IO ()-printVersion = warnLn version--warn :: String -> IO ()-warn = IO.hPutStr IO.stderr--warnLn :: String -> IO ()-warnLn = IO.hPutStrLn IO.stderr+  either fail pure $ Monad.foldM Config.applyFlag Config.initial flags
+ src/lib/Rattletrap/Console/Mode.hs view
@@ -0,0 +1,12 @@+module Rattletrap.Console.Mode where++data Mode+  = Decode+  | Encode+  deriving (Eq, Show)++fromString :: String -> Either String Mode+fromString string = case string of+  "decode" -> Right Decode+  "encode" -> Right Encode+  _ -> Left $ "invalid mode: " <> show string
+ src/lib/Rattletrap/Console/Option.hs view
@@ -0,0 +1,62 @@+module Rattletrap.Console.Option where++import qualified Rattletrap.Console.Flag as Flag+import qualified System.Console.GetOpt as Console++type Option = Console.OptDescr Flag.Flag++all :: [Option]+all = [compact, fast, help, input, mode, output, schema, skipCrc, version]++compact :: Option+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"++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"++mode :: Option+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"++schema :: Option+schema =+  Console.Option [] ["schema"] (Console.NoArg Flag.Schema) "output the schema"++skipCrc :: Option+skipCrc =+  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"
src/lib/Rattletrap/Data.hs view
@@ -1,18 +1,16 @@ -- brittany --columns 120-module Rattletrap.Data-  ( rawParentClasses-  , rawClassesWithLocation-  , rawClassesWithRotation-  , rawObjectClasses-  , rawAttributeTypes-  , rawCrc32Table-  )-where+module Rattletrap.Data where -import Rattletrap.Type.AttributeType+import qualified Rattletrap.Type.AttributeType as AttributeType -rawParentClasses :: [(String, String)]-rawParentClasses =+import qualified Data.Bifunctor as Bifunctor+import qualified Data.Map as Map+import qualified Data.Set as Set+import qualified Data.Text as Text++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")@@ -54,10 +52,10 @@   , ("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_Football_TA", "TAGame.SpecialPickup_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")@@ -74,8 +72,9 @@   , ("TAGame.VehiclePickup_TA", "Engine.ReplicationInfo")   ] -rawClassesWithLocation :: [String]-rawClassesWithLocation =+classesWithLocation :: Set.Set Text.Text+classesWithLocation = Set.fromList $ fmap+  Text.pack   [ "Archetypes.Ball.Ball_BasketBall_Mutator"   , "Archetypes.Ball.Ball_Basketball"   , "Archetypes.Ball.Ball_BasketBall"@@ -109,8 +108,8 @@   , "TAGame.GameEvent_SoccarSplitscreen_TA"   , "TAGame.GRI_TA"   , "TAGame.MaxTimeWarningData_TA"-  , "TAGame.RumblePickups_TA"   , "TAGame.PRI_TA"+  , "TAGame.RumblePickups_TA"   , "TAGame.SpecialPickup_BallCarSpring_TA"   , "TAGame.SpecialPickup_BallFreeze_TA"   , "TAGame.SpecialPickup_BallGravity_TA"@@ -133,8 +132,9 @@   , "TheWorld:PersistentLevel.VehiclePickup_Boost_TA"   ] -rawClassesWithRotation :: [String]-rawClassesWithRotation =+classesWithRotation :: Set.Set Text.Text+classesWithRotation = Set.fromList $ fmap+  Text.pack   [ "Archetypes.Ball.Ball_BasketBall_Mutator"   , "Archetypes.Ball.Ball_Basketball"   , "Archetypes.Ball.Ball_BasketBall"@@ -153,8 +153,9 @@   , "TAGame.Car_TA"   ] -rawObjectClasses :: [(String, String)]-rawObjectClasses =+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")@@ -219,8 +220,8 @@   , ("ProjectX.Default__NetModeReplicator_X", "ProjectX.NetModeReplicator")   , ("TAGame.Default__CameraSettingsActor_TA", "TAGame.CameraSettingsActor_TA")   , ("TAGame.Default__MaxTimeWarningData_TA", "TAGame.MaxTimeWarningData_TA")-  , ("TAGame.Default__RumblePickups_TA", "TAGame.RumblePickups_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")@@ -228,449 +229,190 @@   , ("TheWorld:PersistentLevel.VehiclePickup_Boost_TA", "TAGame.VehiclePickup_Boost_TA")   ] -rawAttributeTypes :: [(String, AttributeType)]-rawAttributeTypes =-  [ ("Engine.Actor:bBlockActors", AttributeTypeBoolean)-  , ("Engine.Actor:bCollideActors", AttributeTypeBoolean)-  , ("Engine.Actor:bHidden", AttributeTypeBoolean)-  , ("Engine.Actor:DrawScale", AttributeTypeFloat)-  , ("Engine.Actor:RemoteRole", AttributeTypeEnum)-  , ("Engine.Actor:Role", AttributeTypeEnum)-  , ("Engine.GameReplicationInfo:bMatchIsOver", AttributeTypeBoolean)-  , ("Engine.GameReplicationInfo:GameClass", AttributeTypeFlaggedInt)-  , ("TAGame.Car_TA:RumblePickups", AttributeTypeFlaggedInt)-  , ("Engine.GameReplicationInfo:ServerName", AttributeTypeString)-  , ("Engine.Pawn:PlayerReplicationInfo", AttributeTypeFlaggedInt)-  , ("Engine.PlayerReplicationInfo:bBot", AttributeTypeBoolean)-  , ("Engine.PlayerReplicationInfo:bIsSpectator", AttributeTypeBoolean)-  , ("Engine.PlayerReplicationInfo:bReadyToPlay", AttributeTypeBoolean)-  , ("Engine.PlayerReplicationInfo:bTimedOut", AttributeTypeBoolean)-  , ("Engine.PlayerReplicationInfo:bWaitingPlayer", AttributeTypeBoolean)-  , ("Engine.PlayerReplicationInfo:Ping", AttributeTypeByte)-  , ("Engine.PlayerReplicationInfo:PlayerID", AttributeTypeInt)-  , ("Engine.PlayerReplicationInfo:PlayerName", AttributeTypeString)-  , ("Engine.PlayerReplicationInfo:RemoteUserData", AttributeTypeString)-  , ("Engine.PlayerReplicationInfo:Score", AttributeTypeInt)-  , ("Engine.PlayerReplicationInfo:Team", AttributeTypeFlaggedInt)-  , ("Engine.PlayerReplicationInfo:UniqueId", AttributeTypeUniqueId)-  , ("Engine.ReplicatedActor_ORS:ReplicatedOwner", AttributeTypeFlaggedInt)-  , ("Engine.TeamInfo:Score", AttributeTypeInt)-  , ("ProjectX.GRI_X:bGameStarted", AttributeTypeBoolean)-  , ("ProjectX.GRI_X:GameServerID", AttributeTypeQWord)-  , ("ProjectX.GRI_X:MatchGUID", AttributeTypeString)-  , ("ProjectX.GRI_X:ReplicatedGameMutatorIndex", AttributeTypeInt)-  , ("ProjectX.GRI_X:ReplicatedGamePlaylist", AttributeTypeInt)-  , ("ProjectX.GRI_X:Reservations", AttributeTypeReservation)-  , ("TAGame.Ball_Breakout_TA:AppliedDamage", AttributeTypeAppliedDamage)-  , ("TAGame.Ball_Breakout_TA:DamageIndex", AttributeTypeInt)-  , ("TAGame.Ball_Breakout_TA:LastTeamTouch", AttributeTypeByte)-  , ("TAGame.Ball_God_TA:TargetSpeed", AttributeTypeFloat)-  , ("TAGame.Ball_Haunted_TA:bIsBallBeamed", AttributeTypeBoolean)-  , ("TAGame.Ball_Haunted_TA:DeactivatedGoalIndex", AttributeTypeByte)-  , ("TAGame.Ball_Haunted_TA:LastTeamTouch", AttributeTypeByte)-  , ("TAGame.Ball_Haunted_TA:ReplicatedBeamBrokenValue", AttributeTypeByte)-  , ("TAGame.Ball_Haunted_TA:TotalActiveBeams", AttributeTypeByte)-  , ("TAGame.Ball_TA:GameEvent", AttributeTypeFlaggedInt)-  , ("TAGame.Ball_TA:HitTeamNum", AttributeTypeByte)-  , ("TAGame.Ball_TA:ReplicatedAddedCarBounceScale", AttributeTypeFloat)-  , ("TAGame.Ball_TA:ReplicatedBallMaxLinearSpeedScale", AttributeTypeFloat)-  , ("TAGame.Ball_TA:ReplicatedBallScale", AttributeTypeFloat)-  , ("TAGame.Ball_TA:ReplicatedExplosionData", AttributeTypeExplosion)-  , ("TAGame.Ball_TA:ReplicatedExplosionDataExtended", AttributeTypeExtendedExplosion)-  , ("TAGame.Ball_TA:ReplicatedPhysMatOverride", AttributeTypeFlaggedInt)-  , ("TAGame.Ball_TA:ReplicatedWorldBounceScale", AttributeTypeFloat)-  , ("TAGame.BreakOutActor_Platform_TA:DamageState", AttributeTypeDamageState)-  , ("TAGame.CameraSettingsActor_TA:bMouseCameraToggleEnabled", AttributeTypeBoolean)-  , ("TAGame.CameraSettingsActor_TA:bUsingBehindView", AttributeTypeBoolean)-  , ("TAGame.CameraSettingsActor_TA:bUsingSecondaryCamera", AttributeTypeBoolean)-  , ("TAGame.CameraSettingsActor_TA:bUsingSwivel", AttributeTypeBoolean)-  , ("TAGame.CameraSettingsActor_TA:CameraPitch", AttributeTypeByte)-  , ("TAGame.CameraSettingsActor_TA:CameraYaw", AttributeTypeByte)-  , ("TAGame.CameraSettingsActor_TA:PRI", AttributeTypeFlaggedInt)-  , ("TAGame.CameraSettingsActor_TA:ProfileSettings", AttributeTypeCamSettings)-  , ("TAGame.Car_TA:AddedBallForceMultiplier", AttributeTypeFloat)-  , ("TAGame.Car_TA:AddedCarForceMultiplier", AttributeTypeFloat)-  , ("TAGame.Car_TA:AttachedPickup", AttributeTypeFlaggedInt)-  , ("TAGame.Car_TA:ClubColors", AttributeTypeClubColors)-  , ("TAGame.Car_TA:ReplicatedDemolish_CustomFX", AttributeTypeCustomDemolish)-  , ("TAGame.Car_TA:ReplicatedDemolish", AttributeTypeDemolish)-  , ("TAGame.Car_TA:TeamPaint", AttributeTypeTeamPaint)-  , ("TAGame.CarComponent_Boost_TA:bNoBoost", AttributeTypeBoolean)-  , ("TAGame.CarComponent_Boost_TA:BoostModifier", AttributeTypeFloat)-  , ("TAGame.CarComponent_Boost_TA:bUnlimitedBoost", AttributeTypeBoolean)-  , ("TAGame.CarComponent_Boost_TA:RechargeDelay", AttributeTypeFloat)-  , ("TAGame.CarComponent_Boost_TA:RechargeRate", AttributeTypeFloat)-  , ("TAGame.CarComponent_Boost_TA:ReplicatedBoostAmount", AttributeTypeByte)-  , ("TAGame.CarComponent_Boost_TA:UnlimitedBoostRefCount", AttributeTypeInt)-  , ("TAGame.CarComponent_Dodge_TA:DodgeTorque", AttributeTypeLocation)-  , ("TAGame.CarComponent_FlipCar_TA:bFlipRight", AttributeTypeBoolean)-  , ("TAGame.CarComponent_FlipCar_TA:FlipCarTime", AttributeTypeFloat)-  , ("TAGame.CarComponent_TA:ReplicatedActive", AttributeTypeByte)-  , ("TAGame.CarComponent_TA:ReplicatedActivityTime", AttributeTypeFloat)-  , ("TAGame.CarComponent_TA:Vehicle", AttributeTypeFlaggedInt)-  , ("TAGame.CrowdActor_TA:GameEvent", AttributeTypeFlaggedInt)-  , ("TAGame.CrowdActor_TA:ModifiedNoise", AttributeTypeFloat)-  , ("TAGame.CrowdActor_TA:ReplicatedCountDownNumber", AttributeTypeInt)-  , ("TAGame.CrowdActor_TA:ReplicatedOneShotSound", AttributeTypeFlaggedInt)-  , ("TAGame.CrowdActor_TA:ReplicatedRoundCountDownNumber", AttributeTypeInt)-  , ("TAGame.CrowdManager_TA:GameEvent", AttributeTypeFlaggedInt)-  , ("TAGame.CrowdManager_TA:ReplicatedGlobalOneShotSound", AttributeTypeFlaggedInt)-  , ("TAGame.GameEvent_Soccar_TA:bBallHasBeenHit", AttributeTypeBoolean)-  , ("TAGame.GameEvent_Soccar_TA:bClubMatch", AttributeTypeBoolean)-  , ("TAGame.GameEvent_Soccar_TA:bOverTime", AttributeTypeBoolean)-  , ("TAGame.GameEvent_Soccar_TA:bUnlimitedTime", AttributeTypeBoolean)-  , ("TAGame.GameEvent_Soccar_TA:GameTime", AttributeTypeInt)-  , ("TAGame.GameEvent_Soccar_TA:MaxScore", AttributeTypeInt)-  , ("TAGame.GameEvent_Soccar_TA:ReplicatedMusicStinger", AttributeTypeMusicStinger)-  , ("TAGame.GameEvent_Soccar_TA:ReplicatedScoredOnTeam", AttributeTypeByte)-  , ("TAGame.GameEvent_Soccar_TA:ReplicatedServerPerformanceState", AttributeTypeByte)-  , ("TAGame.GameEvent_Soccar_TA:ReplicatedStatEvent", AttributeTypeStatEvent)-  , ("TAGame.GameEvent_Soccar_TA:RoundNum", AttributeTypeInt)-  , ("TAGame.GameEvent_Soccar_TA:SecondsRemaining", AttributeTypeInt)-  , ("TAGame.GameEvent_Soccar_TA:SeriesLength", AttributeTypeInt)-  , ("TAGame.GameEvent_Soccar_TA:SubRulesArchetype", AttributeTypeFlaggedInt)-  , ("TAGame.GameEvent_SoccarPrivate_TA:MatchSettings", AttributeTypePrivateMatchSettings)-  , ("TAGame.GameEvent_TA:bCanVoteToForfeit", AttributeTypeBoolean)-  , ("TAGame.GameEvent_TA:bHasLeaveMatchPenalty", AttributeTypeBoolean)-  , ("TAGame.GameEvent_TA:BotSkill", AttributeTypeInt)-  , ("TAGame.GameEvent_TA:GameMode", AttributeTypeGameMode)-  , ("TAGame.GameEvent_TA:MatchTypeClass", AttributeTypeFlaggedInt)-  , ("TAGame.GameEvent_TA:ReplicatedGameStateTimeRemaining", AttributeTypeInt)-  , ("TAGame.GameEvent_TA:ReplicatedRoundCountDownNumber", AttributeTypeInt)-  , ("TAGame.GameEvent_TA:ReplicatedStateIndex", AttributeTypeByte)-  , ("TAGame.GameEvent_TA:ReplicatedStateName", AttributeTypeInt)-  , ("TAGame.GameEvent_Team_TA:bForfeit", AttributeTypeBoolean)-  , ("TAGame.GameEvent_Team_TA:MaxTeamSize", AttributeTypeInt)-  , ("TAGame.GRI_TA:NewDedicatedServerIP", AttributeTypeString)-  , ("TAGame.MaxTimeWarningData_TA:EndGameEpochTime", AttributeTypeInt64)-  , ("TAGame.MaxTimeWarningData_TA:EndGameWarningEpochTime", AttributeTypeInt64)-  , ("TAGame.PRI_TA:bIsDistracted", AttributeTypeBoolean)-  , ("TAGame.PRI_TA:bIsInSplitScreen", AttributeTypeBoolean)-  , ("TAGame.PRI_TA:bMatchMVP", AttributeTypeBoolean)-  , ("TAGame.PRI_TA:bOnlineLoadoutSet", AttributeTypeBoolean)-  , ("TAGame.PRI_TA:bOnlineLoadoutsSet", AttributeTypeBoolean)-  , ("TAGame.PRI_TA:BotProductName", AttributeTypeInt)-  , ("TAGame.PRI_TA:bReady", AttributeTypeBoolean)-  , ("TAGame.PRI_TA:bUsingBehindView", AttributeTypeBoolean)-  , ("TAGame.PRI_TA:bUsingItems", AttributeTypeBoolean)-  , ("TAGame.PRI_TA:bUsingSecondaryCamera", AttributeTypeBoolean)-  , ("TAGame.PRI_TA:CameraPitch", AttributeTypeByte)-  , ("TAGame.PRI_TA:CameraSettings", AttributeTypeCamSettings)-  , ("TAGame.PRI_TA:CameraYaw", AttributeTypeByte)-  , ("TAGame.PRI_TA:ClientLoadout", AttributeTypeLoadout)-  , ("TAGame.PRI_TA:ClientLoadoutOnline", AttributeTypeLoadoutOnline)-  , ("TAGame.PRI_TA:ClientLoadouts", AttributeTypeLoadouts)-  , ("TAGame.PRI_TA:ClientLoadoutsOnline", AttributeTypeLoadoutsOnline)-  , ("TAGame.PRI_TA:ClubID", AttributeTypeInt64)-  , ("TAGame.PRI_TA:MatchAssists", AttributeTypeInt)-  , ("TAGame.PRI_TA:MatchBreakoutDamage", AttributeTypeInt)-  , ("TAGame.PRI_TA:MatchGoals", AttributeTypeInt)-  , ("TAGame.PRI_TA:MatchSaves", AttributeTypeInt)-  , ("TAGame.PRI_TA:MatchScore", AttributeTypeInt)-  , ("TAGame.PRI_TA:MatchShots", AttributeTypeInt)-  , ("TAGame.PRI_TA:MaxTimeTillItem", AttributeTypeInt)-  , ("TAGame.PRI_TA:PartyLeader", AttributeTypePartyLeader)-  , ("TAGame.PRI_TA:PawnType", AttributeTypeByte)-  , ("TAGame.PRI_TA:PersistentCamera", AttributeTypeFlaggedInt)-  , ("TAGame.PRI_TA:PlayerHistoryKey", AttributeTypePlayerHistoryKey)-  , ("TAGame.PRI_TA:PlayerHistoryValid", AttributeTypeBoolean)-  , ("TAGame.PRI_TA:PrimaryTitle", AttributeTypeTitle)-  , ("TAGame.PRI_TA:ReplicatedGameEvent", AttributeTypeFlaggedInt)-  , ("TAGame.PRI_TA:ReplicatedWorstNetQualityBeyondLatency", AttributeTypeByte)-  , ("TAGame.PRI_TA:SecondaryTitle", AttributeTypeTitle)-  , ("TAGame.PRI_TA:SkillTier", AttributeTypeFlaggedByte)-  , ("TAGame.PRI_TA:SpectatorShortcut", AttributeTypeInt)-  , ("TAGame.PRI_TA:SteeringSensitivity", AttributeTypeFloat)-  , ("TAGame.PRI_TA:TimeTillItem", AttributeTypeInt)-  , ("TAGame.PRI_TA:Title", AttributeTypeInt)-  , ("TAGame.PRI_TA:TotalXP", AttributeTypeInt)-  , ("TAGame.RBActor_TA:bFrozen", AttributeTypeBoolean)-  , ("TAGame.RBActor_TA:bIgnoreSyncing", AttributeTypeBoolean)-  , ("TAGame.RBActor_TA:bReplayActor", AttributeTypeBoolean)-  , ("TAGame.RBActor_TA:ReplicatedRBState", AttributeTypeRigidBodyState)-  , ("TAGame.RBActor_TA:WeldedInfo", AttributeTypeWeldedInfo)-  , ("TAGame.RumblePickups_TA:AttachedPickup", AttributeTypeFlaggedInt)-  , ("TAGame.RumblePickups_TA:ConcurrentItemCount", AttributeTypeInt)-  , ("TAGame.SpecialPickup_BallFreeze_TA:RepOrigSpeed", AttributeTypeFloat)-  , ("TAGame.SpecialPickup_BallVelcro_TA:AttachTime", AttributeTypeFloat)-  , ("TAGame.SpecialPickup_BallVelcro_TA:bBroken", AttributeTypeBoolean)-  , ("TAGame.SpecialPickup_BallVelcro_TA:bHit", AttributeTypeBoolean)-  , ("TAGame.SpecialPickup_BallVelcro_TA:BreakTime", AttributeTypeFloat)-  , ("TAGame.SpecialPickup_Football_TA:WeldedBall", AttributeTypeFlaggedInt)-  , ("TAGame.SpecialPickup_Rugby_TA:bBallWelded", AttributeTypeBoolean)-  , ("TAGame.SpecialPickup_Targeted_TA:Targeted", AttributeTypeFlaggedInt)-  , ("TAGame.Team_Soccar_TA:GameScore", AttributeTypeInt)-  , ("TAGame.Team_TA:ClubColors", AttributeTypeClubColors)-  , ("TAGame.Team_TA:ClubID", AttributeTypeInt64)-  , ("TAGame.Team_TA:CustomTeamName", AttributeTypeString)-  , ("TAGame.Team_TA:Difficulty", AttributeTypeInt)-  , ("TAGame.Team_TA:GameEvent", AttributeTypeFlaggedInt)-  , ("TAGame.Team_TA:LogoData", AttributeTypeFlaggedInt)-  , ("TAGame.Vehicle_TA:bDriving", AttributeTypeBoolean)-  , ("TAGame.Vehicle_TA:bReplicatedHandbrake", AttributeTypeBoolean)-  , ("TAGame.Vehicle_TA:ReplicatedSteer", AttributeTypeByte)-  , ("TAGame.Vehicle_TA:ReplicatedThrottle", AttributeTypeByte)-  , ("TAGame.VehiclePickup_TA:bNoPickup", AttributeTypeBoolean)-  , ("TAGame.VehiclePickup_TA:NewReplicatedPickupData", AttributeTypePickupNew)-  , ("TAGame.VehiclePickup_TA:ReplicatedPickupData", AttributeTypePickup)-  ]--rawCrc32Table :: Integral a => [a]-rawCrc32Table =-  [ 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+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:DrawScale", AttributeType.Float)+  , ("Engine.Actor:RemoteRole", AttributeType.Enum)+  , ("Engine.Actor:Role", AttributeType.Enum)+  , ("Engine.GameReplicationInfo:bMatchIsOver", AttributeType.Boolean)+  , ("Engine.GameReplicationInfo:GameClass", AttributeType.FlaggedInt)+  , ("Engine.GameReplicationInfo:ServerName", AttributeType.String)+  , ("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.QWord)+  , ("ProjectX.GRI_X:MatchGUID", AttributeType.String)+  , ("ProjectX.GRI_X:ReplicatedGameMutatorIndex", AttributeType.Int)+  , ("ProjectX.GRI_X:ReplicatedGamePlaylist", AttributeType.Int)+  , ("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.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:ReplicatedDemolish_CustomFX", AttributeType.CustomDemolish)+  , ("TAGame.Car_TA:ReplicatedDemolish", AttributeType.Demolish)+  , ("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:DodgeTorque", 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:bOverTime", AttributeType.Boolean)+  , ("TAGame.GameEvent_Soccar_TA:bUnlimitedTime", AttributeType.Boolean)+  , ("TAGame.GameEvent_Soccar_TA:GameTime", AttributeType.Int)+  , ("TAGame.GameEvent_Soccar_TA:MaxScore", AttributeType.Int)+  , ("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: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: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: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.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: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)   ]
− src/lib/Rattletrap/Decode/AppliedDamageAttribute.hs
@@ -1,19 +0,0 @@-module Rattletrap.Decode.AppliedDamageAttribute-  ( decodeAppliedDamageAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Int32le-import Rattletrap.Decode.Vector-import Rattletrap.Decode.Word8le-import Rattletrap.Type.AppliedDamageAttribute--decodeAppliedDamageAttributeBits-  :: (Int, Int, Int) -> DecodeBits AppliedDamageAttribute-decodeAppliedDamageAttributeBits version =-  AppliedDamageAttribute-    <$> decodeWord8leBits-    <*> decodeVectorBits version-    <*> decodeInt32leBits-    <*> decodeInt32leBits
− src/lib/Rattletrap/Decode/Attribute.hs
@@ -1,73 +0,0 @@-module Rattletrap.Decode.Attribute-  ( decodeAttributesBits-  )-where--import Rattletrap.Decode.AttributeValue-import Rattletrap.Decode.Common-import Rattletrap.Decode.CompressedWord-import Rattletrap.Type.Attribute-import Rattletrap.Type.ClassAttributeMap-import Rattletrap.Type.Common-import Rattletrap.Type.CompressedWord-import Rattletrap.Type.Str-import Rattletrap.Type.Word32le--decodeAttributesBits-  :: (Int, Int, Int)-  -> ClassAttributeMap-  -> Map CompressedWord Word32le-  -> CompressedWord-  -> DecodeBits [Attribute]-decodeAttributesBits version classes actors actor = do-  hasAttribute <- getBool-  if hasAttribute-    then-      (:)-      <$> decodeAttributeBits version classes actors actor-      <*> decodeAttributesBits version classes actors actor-    else pure []--decodeAttributeBits-  :: (Int, Int, Int)-  -> ClassAttributeMap-  -> Map CompressedWord Word32le-  -> CompressedWord-  -> DecodeBits Attribute-decodeAttributeBits version classes actors actor = do-  attributes <- lookupAttributeMap classes actors actor-  limit <- lookupAttributeIdLimit attributes actor-  attribute <- decodeCompressedWordBits limit-  name <- lookupAttributeName classes attributes attribute-  Attribute attribute name-    <$> decodeAttributeValueBits-          version-          (classAttributeMapObjectMap classes)-          name--lookupAttributeMap-  :: ClassAttributeMap-  -> Map CompressedWord Word32le-  -> CompressedWord-  -> DecodeBits (Map Word32le Word32le)-lookupAttributeMap classes actors actor = fromMaybe-  ("[RT01] could not get attribute map for " <> show actor)-  (getAttributeMap classes actors actor)--lookupAttributeIdLimit-  :: Map Word32le Word32le -> CompressedWord -> DecodeBits Word-lookupAttributeIdLimit attributes actor = fromMaybe-  ("[RT02] could not get attribute ID limit for " <> show actor)-  (getAttributeIdLimit attributes)--lookupAttributeName-  :: ClassAttributeMap-  -> Map Word32le Word32le-  -> CompressedWord-  -> DecodeBits Str-lookupAttributeName classes attributes attribute = fromMaybe-  ("[RT03] could not get attribute name for " <> show attribute)-  (getAttributeName classes attributes attribute)--fromMaybe :: String -> Maybe a -> DecodeBits a-fromMaybe message = maybe (fail message) pure
− src/lib/Rattletrap/Decode/AttributeMapping.hs
@@ -1,12 +0,0 @@-module Rattletrap.Decode.AttributeMapping-  ( decodeAttributeMapping-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Word32le-import Rattletrap.Type.AttributeMapping--decodeAttributeMapping :: Decode AttributeMapping-decodeAttributeMapping =-  AttributeMapping <$> decodeWord32le <*> decodeWord32le
− src/lib/Rattletrap/Decode/AttributeValue.hs
@@ -1,131 +0,0 @@-module Rattletrap.Decode.AttributeValue-  ( decodeAttributeValueBits-  )-where--import Rattletrap.Data-import Rattletrap.Decode.AppliedDamageAttribute-import Rattletrap.Decode.BooleanAttribute-import Rattletrap.Decode.ByteAttribute-import Rattletrap.Decode.CamSettingsAttribute-import Rattletrap.Decode.ClubColorsAttribute-import Rattletrap.Decode.Common-import Rattletrap.Decode.CustomDemolishAttribute-import Rattletrap.Decode.DamageStateAttribute-import Rattletrap.Decode.DemolishAttribute-import Rattletrap.Decode.EnumAttribute-import Rattletrap.Decode.ExplosionAttribute-import Rattletrap.Decode.ExtendedExplosionAttribute-import Rattletrap.Decode.FlaggedIntAttribute-import Rattletrap.Decode.FlaggedByteAttribute-import Rattletrap.Decode.FloatAttribute-import Rattletrap.Decode.GameModeAttribute-import Rattletrap.Decode.Int64Attribute-import Rattletrap.Decode.IntAttribute-import Rattletrap.Decode.LoadoutAttribute-import Rattletrap.Decode.LoadoutOnlineAttribute-import Rattletrap.Decode.LoadoutsAttribute-import Rattletrap.Decode.LoadoutsOnlineAttribute-import Rattletrap.Decode.LocationAttribute-import Rattletrap.Decode.MusicStingerAttribute-import Rattletrap.Decode.PartyLeaderAttribute-import Rattletrap.Decode.PickupAttribute-import Rattletrap.Decode.PickupAttributeNew-import Rattletrap.Decode.PlayerHistoryKeyAttribute-import Rattletrap.Decode.PrivateMatchSettingsAttribute-import Rattletrap.Decode.QWordAttribute-import Rattletrap.Decode.ReservationAttribute-import Rattletrap.Decode.RigidBodyStateAttribute-import Rattletrap.Decode.StatEventAttribute-import Rattletrap.Decode.StringAttribute-import Rattletrap.Decode.TeamPaintAttribute-import Rattletrap.Decode.TitleAttribute-import Rattletrap.Decode.UniqueIdAttribute-import Rattletrap.Decode.WeldedInfoAttribute-import Rattletrap.Type.AttributeType-import Rattletrap.Type.AttributeValue-import Rattletrap.Type.Common-import Rattletrap.Type.Str-import Rattletrap.Type.Word32le--import qualified Data.Map as Map--decodeAttributeValueBits-  :: (Int, Int, Int) -> Map Word32le Str -> Str -> DecodeBits AttributeValue-decodeAttributeValueBits version objectMap name = do-  constructor <- maybe-    (fail ("[RT04] don't know how to get attribute value " <> show name))-    pure-    (Map.lookup name attributeTypes)-  case constructor of-    AttributeTypeAppliedDamage ->-      AttributeValueAppliedDamage <$> decodeAppliedDamageAttributeBits version-    AttributeTypeBoolean ->-      AttributeValueBoolean <$> decodeBooleanAttributeBits-    AttributeTypeByte -> AttributeValueByte <$> decodeByteAttributeBits-    AttributeTypeCamSettings ->-      AttributeValueCamSettings <$> decodeCamSettingsAttributeBits version-    AttributeTypeClubColors ->-      AttributeValueClubColors <$> decodeClubColorsAttributeBits-    AttributeTypeCustomDemolish ->-      AttributeValueCustomDemolish <$> decodeCustomDemolishAttributeBits version-    AttributeTypeDamageState ->-      AttributeValueDamageState <$> decodeDamageStateAttributeBits version-    AttributeTypeDemolish ->-      AttributeValueDemolish <$> decodeDemolishAttributeBits version-    AttributeTypeEnum -> AttributeValueEnum <$> decodeEnumAttributeBits-    AttributeTypeExplosion ->-      AttributeValueExplosion <$> decodeExplosionAttributeBits version-    AttributeTypeExtendedExplosion -> AttributeValueExtendedExplosion-      <$> decodeExtendedExplosionAttributeBits version-    AttributeTypeFlaggedInt ->-      AttributeValueFlaggedInt <$> decodeFlaggedIntAttributeBits-    AttributeTypeFlaggedByte ->-      AttributeValueFlaggedByte <$> decodeFlaggedByteAttributeBits-    AttributeTypeFloat -> AttributeValueFloat <$> decodeFloatAttributeBits-    AttributeTypeGameMode ->-      AttributeValueGameMode <$> decodeGameModeAttributeBits version-    AttributeTypeInt -> AttributeValueInt <$> decodeIntAttributeBits-    AttributeTypeInt64 -> AttributeValueInt64 <$> decodeInt64AttributeBits-    AttributeTypeLoadout ->-      AttributeValueLoadout <$> decodeLoadoutAttributeBits-    AttributeTypeLoadoutOnline ->-      AttributeValueLoadoutOnline-        <$> decodeLoadoutOnlineAttributeBits version objectMap-    AttributeTypeLoadouts ->-      AttributeValueLoadouts <$> decodeLoadoutsAttributeBits-    AttributeTypeLoadoutsOnline ->-      AttributeValueLoadoutsOnline-        <$> decodeLoadoutsOnlineAttributeBits version objectMap-    AttributeTypeLocation ->-      AttributeValueLocation <$> decodeLocationAttributeBits version-    AttributeTypeMusicStinger ->-      AttributeValueMusicStinger <$> decodeMusicStingerAttributeBits-    AttributeTypePartyLeader ->-      AttributeValuePartyLeader <$> decodePartyLeaderAttributeBits version-    AttributeTypePickup -> AttributeValuePickup <$> decodePickupAttributeBits-    AttributeTypePickupNew ->-      AttributeValuePickupNew <$> decodePickupAttributeNewBits-    AttributeTypePlayerHistoryKey ->-      AttributeValuePlayerHistoryKey <$> decodePlayerHistoryKeyAttributeBits-    AttributeTypePrivateMatchSettings ->-      AttributeValuePrivateMatchSettings-        <$> decodePrivateMatchSettingsAttributeBits-    AttributeTypeQWord -> AttributeValueQWord <$> decodeQWordAttributeBits-    AttributeTypeReservation ->-      AttributeValueReservation <$> decodeReservationAttributeBits version-    AttributeTypeRigidBodyState -> AttributeValueRigidBodyState-      <$> decodeRigidBodyStateAttributeBits version-    AttributeTypeStatEvent ->-      AttributeValueStatEvent <$> decodeStatEventAttributeBits-    AttributeTypeString -> AttributeValueString <$> decodeStringAttributeBits-    AttributeTypeTeamPaint ->-      AttributeValueTeamPaint <$> decodeTeamPaintAttributeBits-    AttributeTypeTitle -> AttributeValueTitle <$> decodeTitleAttributeBits-    AttributeTypeUniqueId ->-      AttributeValueUniqueId <$> decodeUniqueIdAttributeBits version-    AttributeTypeWeldedInfo ->-      AttributeValueWeldedInfo <$> decodeWeldedInfoAttributeBits version--attributeTypes :: Map Str AttributeType-attributeTypes = Map.mapKeys toStr (Map.fromList rawAttributeTypes)
− src/lib/Rattletrap/Decode/BooleanAttribute.hs
@@ -1,10 +0,0 @@-module Rattletrap.Decode.BooleanAttribute-  ( decodeBooleanAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Type.BooleanAttribute--decodeBooleanAttributeBits :: DecodeBits BooleanAttribute-decodeBooleanAttributeBits = BooleanAttribute <$> getBool
− src/lib/Rattletrap/Decode/ByteAttribute.hs
@@ -1,11 +0,0 @@-module Rattletrap.Decode.ByteAttribute-  ( decodeByteAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Word8le-import Rattletrap.Type.ByteAttribute--decodeByteAttributeBits :: DecodeBits ByteAttribute-decodeByteAttributeBits = ByteAttribute <$> decodeWord8leBits
− src/lib/Rattletrap/Decode/Cache.hs
@@ -1,18 +0,0 @@-module Rattletrap.Decode.Cache-  ( decodeCache-  )-where--import Rattletrap.Decode.AttributeMapping-import Rattletrap.Decode.Common-import Rattletrap.Decode.List-import Rattletrap.Decode.Word32le-import Rattletrap.Type.Cache--decodeCache :: Decode Cache-decodeCache =-  Cache-    <$> decodeWord32le-    <*> decodeWord32le-    <*> decodeWord32le-    <*> decodeList decodeAttributeMapping
− src/lib/Rattletrap/Decode/CamSettingsAttribute.hs
@@ -1,20 +0,0 @@-module Rattletrap.Decode.CamSettingsAttribute-  ( decodeCamSettingsAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Float32le-import Rattletrap.Type.CamSettingsAttribute--decodeCamSettingsAttributeBits-  :: (Int, Int, Int) -> DecodeBits CamSettingsAttribute-decodeCamSettingsAttributeBits version =-  CamSettingsAttribute-    <$> decodeFloat32leBits-    <*> decodeFloat32leBits-    <*> decodeFloat32leBits-    <*> decodeFloat32leBits-    <*> decodeFloat32leBits-    <*> decodeFloat32leBits-    <*> decodeWhen (version >= (868, 20, 0)) decodeFloat32leBits
− src/lib/Rattletrap/Decode/ClassMapping.hs
@@ -1,12 +0,0 @@-module Rattletrap.Decode.ClassMapping-  ( decodeClassMapping-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Str-import Rattletrap.Decode.Word32le-import Rattletrap.Type.ClassMapping--decodeClassMapping :: Decode ClassMapping-decodeClassMapping = ClassMapping <$> decodeStr <*> decodeWord32le
− src/lib/Rattletrap/Decode/ClubColorsAttribute.hs
@@ -1,16 +0,0 @@-module Rattletrap.Decode.ClubColorsAttribute-  ( decodeClubColorsAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Word8le-import Rattletrap.Type.ClubColorsAttribute--decodeClubColorsAttributeBits :: DecodeBits ClubColorsAttribute-decodeClubColorsAttributeBits =-  ClubColorsAttribute-    <$> getBool-    <*> decodeWord8leBits-    <*> getBool-    <*> decodeWord8leBits
− src/lib/Rattletrap/Decode/Common.hs
@@ -1,70 +0,0 @@-module Rattletrap.Decode.Common-  ( Decode-  , DecodeBits-  , decodeWhen-  , getBitsLE-  , getByteStringBits-  , getWord8Bits-  , runDecode-  , runDecodeBits-  , toBits-  , Binary.getFloatle-  , Binary.getByteString-  , Binary.getInt8-  , Binary.getInt32le-  , Binary.getInt64le-  , Binary.getWord8-  , Binary.getWord32le-  , Binary.getWord64le-  , BinaryBits.getBool-  )-where--import qualified Control.Applicative as Applicative-import qualified Control.Monad as Monad-import qualified Data.Binary as Binary-import qualified Data.Binary.Bits.Get as BinaryBits-import qualified Data.Binary.Get as Binary-import qualified Data.Bits as Bits-import qualified Data.ByteString as Bytes-import qualified Data.ByteString.Lazy as LazyBytes-import qualified Data.Word as Word-import qualified Rattletrap.Utility.Bytes as Utility--type Decode = Binary.Get--type DecodeBits = BinaryBits.BitGet--decodeWhen-  :: (Applicative m, Applicative.Alternative f) => Bool -> m a -> m (f a)-decodeWhen p f = if p then fmap pure f else pure Applicative.empty--getByteStringBits :: Int -> DecodeBits Bytes.ByteString-getByteStringBits = BinaryBits.getByteString--getWord8Bits :: Int -> DecodeBits Word.Word8-getWord8Bits = BinaryBits.getWord8--runDecode :: Decode a -> Bytes.ByteString -> Either String a-runDecode decode bytes =-  case Binary.runGetOrFail decode (LazyBytes.fromStrict bytes) of-    Left (_, _, x) -> Left x-    Right (_, _, x) -> Right x--runDecodeBits :: DecodeBits a -> Bytes.ByteString -> Either String a-runDecodeBits = runDecode . BinaryBits.runBitGet--toBits :: Decode a -> Int -> DecodeBits a-toBits decode size = do-  bytes <- BinaryBits.getByteString size-  case runDecode decode (Utility.reverseBytes bytes) of-    Left problem -> fail problem-    Right result -> pure result--getBitsLE :: Bits.Bits a => Int -> BinaryBits.BitGet a-getBitsLE size = do-  bits <- Monad.replicateM size BinaryBits.getBool-  pure $ foldr-    (\bit x -> let y = Bits.shiftL x 1 in if bit then Bits.setBit y 0 else y)-    Bits.zeroBits-    bits
− src/lib/Rattletrap/Decode/CompressedWord.hs
@@ -1,30 +0,0 @@-module Rattletrap.Decode.CompressedWord-  ( decodeCompressedWordBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Type.CompressedWord--import qualified Data.Bits as Bits--decodeCompressedWordBits :: Word -> DecodeBits CompressedWord-decodeCompressedWordBits limit =-  CompressedWord limit <$> step limit (getMaxBits limit) 0 0--getMaxBits :: Word -> Word-getMaxBits x = do-  let-    n :: Word-    n = max 1 (ceiling (logBase (2 :: Double) (fromIntegral (max 1 x))))-  if x < 1024 && x == 2 ^ n then n + 1 else n--step :: Word -> Word -> Word -> Word -> DecodeBits Word-step limit maxBits position value = do-  let x = Bits.shiftL 1 (fromIntegral position) :: Word-  if position < maxBits && value + x <= limit-    then do-      bit <- getBool-      let newValue = if bit then value + x else value-      step limit maxBits (position + 1) newValue-    else pure value
− src/lib/Rattletrap/Decode/CompressedWordVector.hs
@@ -1,18 +0,0 @@-module Rattletrap.Decode.CompressedWordVector-  ( decodeCompressedWordVectorBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.CompressedWord-import Rattletrap.Type.CompressedWordVector--decodeCompressedWordVectorBits :: DecodeBits CompressedWordVector-decodeCompressedWordVectorBits =-  CompressedWordVector-    <$> decodeCompressedWordBits limit-    <*> decodeCompressedWordBits limit-    <*> decodeCompressedWordBits limit--limit :: Word-limit = 65536
− src/lib/Rattletrap/Decode/Content.hs
@@ -1,71 +0,0 @@-module Rattletrap.Decode.Content-  ( decodeContent-  )-where--import Rattletrap.Decode.Cache-import Rattletrap.Decode.ClassMapping-import Rattletrap.Decode.Common-import Rattletrap.Decode.Frame-import Rattletrap.Decode.KeyFrame-import Rattletrap.Decode.List-import Rattletrap.Decode.Mark-import Rattletrap.Decode.Message-import Rattletrap.Decode.Str-import Rattletrap.Decode.Word32le-import Rattletrap.Type.ClassAttributeMap-import Rattletrap.Type.Content-import Rattletrap.Type.Word32le-import Rattletrap.Utility.Bytes--import qualified Control.Monad.Trans.State as State-import qualified Data.Binary.Get as Binary-import qualified Data.ByteString.Lazy as LazyBytes--decodeContent-  :: (Int, Int, Int)-  -- ^ Version numbers, usually from 'Rattletrap.Header.getVersion'.-  -> Int-  -- ^ The number of frames in the stream, usually from-  -- 'Rattletrap.Header.getNumFrames'.-  -> Word-  -- ^ The maximum number of channels in the stream, usually from-  -- 'Rattletrap.Header.getMaxChannels'.-  -> Decode Content-decodeContent version numFrames maxChannels = do-  (levels, keyFrames, streamSize) <--    (,,)-    <$> decodeList decodeStr-    <*> decodeList decodeKeyFrame-    <*> decodeWord32le-  (stream, messages, marks, packages, objects, names, classMappings, caches) <--    (,,,,,,,)-    <$> getByteString (fromIntegral (word32leValue streamSize))-    <*> decodeList decodeMessage-    <*> decodeList decodeMark-    <*> decodeList decodeStr-    <*> decodeList decodeStr-    <*> decodeList decodeStr-    <*> decodeList decodeClassMapping-    <*> decodeList decodeCache-  let-    classAttributeMap =-      makeClassAttributeMap objects classMappings caches names-    bitGet = State.evalStateT-      (decodeFramesBits version numFrames maxChannels classAttributeMap)-      mempty-  frames <- either fail pure (runDecodeBits bitGet (reverseBytes stream))-  Content-      levels-      keyFrames-      streamSize-      frames-      messages-      marks-      packages-      objects-      names-      classMappings-      caches-    . LazyBytes.unpack-    <$> Binary.getRemainingLazyByteString
− src/lib/Rattletrap/Decode/CustomDemolishAttribute.hs
@@ -1,16 +0,0 @@-module Rattletrap.Decode.CustomDemolishAttribute-  ( decodeCustomDemolishAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.DemolishAttribute-import Rattletrap.Decode.Int32le-import Rattletrap.Type.CustomDemolishAttribute--decodeCustomDemolishAttributeBits :: (Int, Int, Int) -> DecodeBits CustomDemolishAttribute-decodeCustomDemolishAttributeBits version =-  CustomDemolishAttribute-    <$> getBool-    <*> decodeInt32leBits-    <*> decodeDemolishAttributeBits version
− src/lib/Rattletrap/Decode/DamageStateAttribute.hs
@@ -1,21 +0,0 @@-module Rattletrap.Decode.DamageStateAttribute-  ( decodeDamageStateAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Int32le-import Rattletrap.Decode.Vector-import Rattletrap.Decode.Word8le-import Rattletrap.Type.DamageStateAttribute--decodeDamageStateAttributeBits-  :: (Int, Int, Int) -> DecodeBits DamageStateAttribute-decodeDamageStateAttributeBits version =-  DamageStateAttribute-    <$> decodeWord8leBits-    <*> getBool-    <*> decodeInt32leBits-    <*> decodeVectorBits version-    <*> getBool-    <*> getBool
− src/lib/Rattletrap/Decode/DemolishAttribute.hs
@@ -1,19 +0,0 @@-module Rattletrap.Decode.DemolishAttribute-  ( decodeDemolishAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Vector-import Rattletrap.Decode.Word32le-import Rattletrap.Type.DemolishAttribute--decodeDemolishAttributeBits :: (Int, Int, Int) -> DecodeBits DemolishAttribute-decodeDemolishAttributeBits version =-  DemolishAttribute-    <$> getBool-    <*> decodeWord32leBits-    <*> getBool-    <*> decodeWord32leBits-    <*> decodeVectorBits version-    <*> decodeVectorBits version
− src/lib/Rattletrap/Decode/DestroyedReplication.hs
@@ -1,10 +0,0 @@-module Rattletrap.Decode.DestroyedReplication-  ( decodeDestroyedReplicationBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Type.DestroyedReplication--decodeDestroyedReplicationBits :: DecodeBits DestroyedReplication-decodeDestroyedReplicationBits = pure DestroyedReplication
− src/lib/Rattletrap/Decode/Dictionary.hs
@@ -1,17 +0,0 @@-module Rattletrap.Decode.Dictionary-  ( decodeDictionary-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Str-import Rattletrap.Type.Dictionary-import Rattletrap.Type.Str--decodeDictionary :: Decode a -> Decode (Dictionary a)-decodeDictionary decodeValue = do-  key <- decodeStr-  case filter (/= '\x00') (fromStr key) of-    "None" -> pure (DictionaryEnd key)-    _ ->-      DictionaryElement key <$> decodeValue <*> decodeDictionary decodeValue
− src/lib/Rattletrap/Decode/EnumAttribute.hs
@@ -1,10 +0,0 @@-module Rattletrap.Decode.EnumAttribute-  ( decodeEnumAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Type.EnumAttribute--decodeEnumAttributeBits :: DecodeBits EnumAttribute-decodeEnumAttributeBits = EnumAttribute <$> getBitsLE 11
− src/lib/Rattletrap/Decode/ExplosionAttribute.hs
@@ -1,17 +0,0 @@-module Rattletrap.Decode.ExplosionAttribute-  ( decodeExplosionAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Int32le-import Rattletrap.Decode.Vector-import Rattletrap.Type.ExplosionAttribute--decodeExplosionAttributeBits-  :: (Int, Int, Int) -> DecodeBits ExplosionAttribute-decodeExplosionAttributeBits version =-  ExplosionAttribute-    <$> getBool-    <*> decodeInt32leBits-    <*> decodeVectorBits version
− src/lib/Rattletrap/Decode/ExtendedExplosionAttribute.hs
@@ -1,16 +0,0 @@-module Rattletrap.Decode.ExtendedExplosionAttribute-  ( decodeExtendedExplosionAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.ExplosionAttribute-import Rattletrap.Decode.FlaggedIntAttribute-import Rattletrap.Type.ExtendedExplosionAttribute--decodeExtendedExplosionAttributeBits-  :: (Int, Int, Int) -> DecodeBits ExtendedExplosionAttribute-decodeExtendedExplosionAttributeBits version =-  ExtendedExplosionAttribute-    <$> decodeExplosionAttributeBits version-    <*> decodeFlaggedIntAttributeBits
− src/lib/Rattletrap/Decode/FlaggedByteAttribute.hs
@@ -1,13 +0,0 @@-module Rattletrap.Decode.FlaggedByteAttribute-  ( decodeFlaggedByteAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Word8le-import Rattletrap.Type.FlaggedByteAttribute---decodeFlaggedByteAttributeBits :: DecodeBits FlaggedByteAttribute-decodeFlaggedByteAttributeBits =-  FlaggedByteAttribute <$> getBool <*> decodeWord8leBits
− src/lib/Rattletrap/Decode/FlaggedIntAttribute.hs
@@ -1,12 +0,0 @@-module Rattletrap.Decode.FlaggedIntAttribute-  ( decodeFlaggedIntAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Int32le-import Rattletrap.Type.FlaggedIntAttribute--decodeFlaggedIntAttributeBits :: DecodeBits FlaggedIntAttribute-decodeFlaggedIntAttributeBits =-  FlaggedIntAttribute <$> getBool <*> decodeInt32leBits
− src/lib/Rattletrap/Decode/Float32le.hs
@@ -1,14 +0,0 @@-module Rattletrap.Decode.Float32le-  ( decodeFloat32le-  , decodeFloat32leBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Type.Float32le--decodeFloat32le :: Decode Float32le-decodeFloat32le = Float32le <$> getFloatle--decodeFloat32leBits :: DecodeBits Float32le-decodeFloat32leBits = toBits decodeFloat32le 4
− src/lib/Rattletrap/Decode/FloatAttribute.hs
@@ -1,11 +0,0 @@-module Rattletrap.Decode.FloatAttribute-  ( decodeFloatAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Float32le-import Rattletrap.Type.FloatAttribute--decodeFloatAttributeBits :: DecodeBits FloatAttribute-decodeFloatAttributeBits = FloatAttribute <$> decodeFloat32leBits
− src/lib/Rattletrap/Decode/Frame.hs
@@ -1,43 +0,0 @@-module Rattletrap.Decode.Frame-  ( decodeFramesBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Float32le-import Rattletrap.Decode.Replication-import Rattletrap.Type.ClassAttributeMap-import Rattletrap.Type.CompressedWord-import Rattletrap.Type.Frame-import Rattletrap.Type.Word32le--import qualified Control.Monad.Trans.Class as Trans-import qualified Control.Monad.Trans.State as State-import qualified Data.Map as Map--decodeFramesBits-  :: (Int, Int, Int)-  -> Int-  -> Word-  -> ClassAttributeMap-  -> State.StateT-       (Map.Map CompressedWord Word32le)-       DecodeBits-       [Frame]-decodeFramesBits version count limit classes = if count <= 0-  then pure []-  else-    (:)-    <$> decodeFrameBits version limit classes-    <*> decodeFramesBits version (count - 1) limit classes--decodeFrameBits-  :: (Int, Int, Int)-  -> Word-  -> ClassAttributeMap-  -> State.StateT (Map.Map CompressedWord Word32le) DecodeBits Frame-decodeFrameBits version limit classes =-  Frame-    <$> Trans.lift decodeFloat32leBits-    <*> Trans.lift decodeFloat32leBits-    <*> decodeReplicationsBits version limit classes
− src/lib/Rattletrap/Decode/GameModeAttribute.hs
@@ -1,15 +0,0 @@-module Rattletrap.Decode.GameModeAttribute-  ( decodeGameModeAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Type.GameModeAttribute--decodeGameModeAttributeBits :: (Int, Int, Int) -> DecodeBits GameModeAttribute-decodeGameModeAttributeBits version =-  GameModeAttribute <$> pure (numBits version) <*> getWord8Bits-    (numBits version)--numBits :: (Int, Int, Int) -> Int-numBits version = if version >= (868, 12, 0) then 8 else 2
− src/lib/Rattletrap/Decode/Header.hs
@@ -1,22 +0,0 @@-module Rattletrap.Decode.Header-  ( decodeHeader-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Dictionary-import Rattletrap.Decode.Property-import Rattletrap.Decode.Str-import Rattletrap.Decode.Word32le-import Rattletrap.Type.Header-import Rattletrap.Type.Word32le--decodeHeader :: Decode Header-decodeHeader = do-  (major, minor) <- (,) <$> decodeWord32le <*> decodeWord32le-  Header major minor-    <$> decodeWhen-          (major >= Word32le 868 && minor >= Word32le 18)-          decodeWord32le-    <*> decodeStr-    <*> decodeDictionary decodeProperty
− src/lib/Rattletrap/Decode/Initialization.hs
@@ -1,16 +0,0 @@-module Rattletrap.Decode.Initialization-  ( decodeInitializationBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Int8Vector-import Rattletrap.Decode.Vector-import Rattletrap.Type.Initialization--decodeInitializationBits-  :: (Int, Int, Int) -> Bool -> Bool -> DecodeBits Initialization-decodeInitializationBits version hasLocation hasRotation =-  Initialization-    <$> decodeWhen hasLocation (decodeVectorBits version)-    <*> decodeWhen hasRotation decodeInt8VectorBits
− src/lib/Rattletrap/Decode/Int32le.hs
@@ -1,14 +0,0 @@-module Rattletrap.Decode.Int32le-  ( decodeInt32le-  , decodeInt32leBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Type.Int32le--decodeInt32le :: Decode Int32le-decodeInt32le = Int32le <$> getInt32le--decodeInt32leBits :: DecodeBits Int32le-decodeInt32leBits = toBits decodeInt32le 4
− src/lib/Rattletrap/Decode/Int64Attribute.hs
@@ -1,11 +0,0 @@-module Rattletrap.Decode.Int64Attribute-  ( decodeInt64AttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Int64le-import Rattletrap.Type.Int64Attribute--decodeInt64AttributeBits :: DecodeBits Int64Attribute-decodeInt64AttributeBits = Int64Attribute <$> decodeInt64leBits
− src/lib/Rattletrap/Decode/Int64le.hs
@@ -1,13 +0,0 @@-module Rattletrap.Decode.Int64le-  ( decodeInt64leBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Type.Int64le--decodeInt64le :: Decode Int64le-decodeInt64le = Int64le <$> getInt64le--decodeInt64leBits :: DecodeBits Int64le-decodeInt64leBits = toBits decodeInt64le 8
− src/lib/Rattletrap/Decode/Int8Vector.hs
@@ -1,18 +0,0 @@-module Rattletrap.Decode.Int8Vector-  ( decodeInt8VectorBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Int8le-import Rattletrap.Type.Int8Vector-import Rattletrap.Type.Int8le--decodeInt8VectorBits :: DecodeBits Int8Vector-decodeInt8VectorBits =-  Int8Vector <$> decodeFieldBits <*> decodeFieldBits <*> decodeFieldBits--decodeFieldBits :: DecodeBits (Maybe Int8le)-decodeFieldBits = do-  hasField <- getBool-  decodeWhen hasField decodeInt8leBits
− src/lib/Rattletrap/Decode/Int8le.hs
@@ -1,13 +0,0 @@-module Rattletrap.Decode.Int8le-  ( decodeInt8leBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Type.Int8le--decodeInt8le :: Decode Int8le-decodeInt8le = Int8le <$> getInt8--decodeInt8leBits :: DecodeBits Int8le-decodeInt8leBits = toBits decodeInt8le 1
− src/lib/Rattletrap/Decode/IntAttribute.hs
@@ -1,11 +0,0 @@-module Rattletrap.Decode.IntAttribute-  ( decodeIntAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Int32le-import Rattletrap.Type.IntAttribute--decodeIntAttributeBits :: DecodeBits IntAttribute-decodeIntAttributeBits = IntAttribute <$> decodeInt32leBits
− src/lib/Rattletrap/Decode/KeyFrame.hs
@@ -1,13 +0,0 @@-module Rattletrap.Decode.KeyFrame-  ( decodeKeyFrame-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Float32le-import Rattletrap.Decode.Word32le-import Rattletrap.Type.KeyFrame--decodeKeyFrame :: Decode KeyFrame-decodeKeyFrame =-  KeyFrame <$> decodeFloat32le <*> decodeWord32le <*> decodeWord32le
− src/lib/Rattletrap/Decode/List.hs
@@ -1,16 +0,0 @@-module Rattletrap.Decode.List-  ( decodeList-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Word32le-import Rattletrap.Type.List-import Rattletrap.Type.Word32le--import qualified Control.Monad as Monad--decodeList :: Decode a -> Decode (List a)-decodeList decodeElement = do-  size <- decodeWord32le-  List <$> Monad.replicateM (fromIntegral (word32leValue size)) decodeElement
− src/lib/Rattletrap/Decode/LoadoutAttribute.hs
@@ -1,31 +0,0 @@-module Rattletrap.Decode.LoadoutAttribute-  ( decodeLoadoutAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Word32le-import Rattletrap.Decode.Word8le-import Rattletrap.Type.LoadoutAttribute-import Rattletrap.Type.Word8le--decodeLoadoutAttributeBits :: DecodeBits LoadoutAttribute-decodeLoadoutAttributeBits = do-  version <- decodeWord8leBits-  LoadoutAttribute version-    <$> decodeWord32leBits-    <*> decodeWord32leBits-    <*> decodeWord32leBits-    <*> decodeWord32leBits-    <*> decodeWord32leBits-    <*> decodeWord32leBits-    <*> decodeWord32leBits-    <*> decodeWhen (version >= Word8le 11) decodeWord32leBits-    <*> decodeWhen (version >= Word8le 16) decodeWord32leBits-    <*> decodeWhen (version >= Word8le 16) decodeWord32leBits-    <*> decodeWhen (version >= Word8le 16) decodeWord32leBits-    <*> decodeWhen (version >= Word8le 17) decodeWord32leBits-    <*> decodeWhen (version >= Word8le 19) decodeWord32leBits-    <*> decodeWhen (version >= Word8le 22) decodeWord32leBits-    <*> decodeWhen (version >= Word8le 22) decodeWord32leBits-    <*> decodeWhen (version >= Word8le 22) decodeWord32leBits
− src/lib/Rattletrap/Decode/LoadoutOnlineAttribute.hs
@@ -1,25 +0,0 @@-module Rattletrap.Decode.LoadoutOnlineAttribute-  ( decodeLoadoutOnlineAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.ProductAttribute-import Rattletrap.Decode.Word8le-import Rattletrap.Type.LoadoutOnlineAttribute-import Rattletrap.Type.Str-import Rattletrap.Type.Word32le-import Rattletrap.Type.Word8le--import qualified Control.Monad as Monad-import qualified Data.Map as Map--decodeLoadoutOnlineAttributeBits-  :: (Int, Int, Int)-  -> Map.Map Word32le Str-  -> DecodeBits LoadoutOnlineAttribute-decodeLoadoutOnlineAttributeBits version objectMap = do-  size <- decodeWord8leBits-  LoadoutOnlineAttribute <$> Monad.replicateM-    (fromIntegral (word8leValue size))-    (decodeProductAttributesBits version objectMap)
− src/lib/Rattletrap/Decode/LoadoutsAttribute.hs
@@ -1,14 +0,0 @@-module Rattletrap.Decode.LoadoutsAttribute-  ( decodeLoadoutsAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.LoadoutAttribute-import Rattletrap.Type.LoadoutsAttribute--decodeLoadoutsAttributeBits :: DecodeBits LoadoutsAttribute-decodeLoadoutsAttributeBits =-  LoadoutsAttribute-    <$> decodeLoadoutAttributeBits-    <*> decodeLoadoutAttributeBits
− src/lib/Rattletrap/Decode/LoadoutsOnlineAttribute.hs
@@ -1,23 +0,0 @@-module Rattletrap.Decode.LoadoutsOnlineAttribute-  ( decodeLoadoutsOnlineAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.LoadoutOnlineAttribute-import Rattletrap.Type.LoadoutsOnlineAttribute-import Rattletrap.Type.Str-import Rattletrap.Type.Word32le--import qualified Data.Map as Map--decodeLoadoutsOnlineAttributeBits-  :: (Int, Int, Int)-  -> Map.Map Word32le Str-  -> DecodeBits LoadoutsOnlineAttribute-decodeLoadoutsOnlineAttributeBits version objectMap =-  LoadoutsOnlineAttribute-    <$> decodeLoadoutOnlineAttributeBits version objectMap-    <*> decodeLoadoutOnlineAttributeBits version objectMap-    <*> getBool-    <*> getBool
− src/lib/Rattletrap/Decode/LocationAttribute.hs
@@ -1,12 +0,0 @@-module Rattletrap.Decode.LocationAttribute-  ( decodeLocationAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Vector-import Rattletrap.Type.LocationAttribute--decodeLocationAttributeBits :: (Int, Int, Int) -> DecodeBits LocationAttribute-decodeLocationAttributeBits version =-  LocationAttribute <$> decodeVectorBits version
− src/lib/Rattletrap/Decode/Mark.hs
@@ -1,12 +0,0 @@-module Rattletrap.Decode.Mark-  ( decodeMark-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Str-import Rattletrap.Decode.Word32le-import Rattletrap.Type.Mark--decodeMark :: Decode Mark-decodeMark = Mark <$> decodeStr <*> decodeWord32le
− src/lib/Rattletrap/Decode/Message.hs
@@ -1,12 +0,0 @@-module Rattletrap.Decode.Message-  ( decodeMessage-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Str-import Rattletrap.Decode.Word32le-import Rattletrap.Type.Message--decodeMessage :: Decode Message-decodeMessage = Message <$> decodeWord32le <*> decodeStr <*> decodeStr
− src/lib/Rattletrap/Decode/MusicStingerAttribute.hs
@@ -1,16 +0,0 @@-module Rattletrap.Decode.MusicStingerAttribute-  ( decodeMusicStingerAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Word32le-import Rattletrap.Decode.Word8le-import Rattletrap.Type.MusicStingerAttribute--decodeMusicStingerAttributeBits :: DecodeBits MusicStingerAttribute-decodeMusicStingerAttributeBits =-  MusicStingerAttribute-    <$> getBool-    <*> decodeWord32leBits-    <*> decodeWord8leBits
− src/lib/Rattletrap/Decode/PartyLeaderAttribute.hs
@@ -1,18 +0,0 @@-module Rattletrap.Decode.PartyLeaderAttribute-  ( decodePartyLeaderAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.RemoteId-import Rattletrap.Decode.Word8le-import Rattletrap.Type.PartyLeaderAttribute-import Rattletrap.Type.Word8le--decodePartyLeaderAttributeBits-  :: (Int, Int, Int) -> DecodeBits PartyLeaderAttribute-decodePartyLeaderAttributeBits version = do-  systemId <- decodeWord8leBits-  PartyLeaderAttribute systemId <$> decodeWhen-    (systemId /= Word8le 0)-    ((,) <$> decodeRemoteIdBits version systemId <*> decodeWord8leBits)
− src/lib/Rattletrap/Decode/PickupAttribute.hs
@@ -1,13 +0,0 @@-module Rattletrap.Decode.PickupAttribute-  ( decodePickupAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Word32le-import Rattletrap.Type.PickupAttribute--decodePickupAttributeBits :: DecodeBits PickupAttribute-decodePickupAttributeBits = do-  instigator <- getBool-  PickupAttribute <$> decodeWhen instigator decodeWord32leBits <*> getBool
− src/lib/Rattletrap/Decode/PickupAttributeNew.hs
@@ -1,16 +0,0 @@-module Rattletrap.Decode.PickupAttributeNew-  ( decodePickupAttributeNewBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Word8le-import Rattletrap.Decode.Word32le-import Rattletrap.Type.PickupAttributeNew--decodePickupAttributeNewBits :: DecodeBits PickupAttributeNew-decodePickupAttributeNewBits = do-  instigator <- getBool-  PickupAttributeNew-    <$> decodeWhen instigator decodeWord32leBits-    <*> decodeWord8leBits
− src/lib/Rattletrap/Decode/PlayerHistoryKeyAttribute.hs
@@ -1,11 +0,0 @@-module Rattletrap.Decode.PlayerHistoryKeyAttribute-  ( decodePlayerHistoryKeyAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Type.PlayerHistoryKeyAttribute--decodePlayerHistoryKeyAttributeBits :: DecodeBits PlayerHistoryKeyAttribute-decodePlayerHistoryKeyAttributeBits =-  PlayerHistoryKeyAttribute <$> getBitsLE 14
− src/lib/Rattletrap/Decode/PrivateMatchSettingsAttribute.hs
@@ -1,20 +0,0 @@-module Rattletrap.Decode.PrivateMatchSettingsAttribute-  ( decodePrivateMatchSettingsAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Str-import Rattletrap.Decode.Word32le-import Rattletrap.Type.PrivateMatchSettingsAttribute--decodePrivateMatchSettingsAttributeBits-  :: DecodeBits PrivateMatchSettingsAttribute-decodePrivateMatchSettingsAttributeBits =-  PrivateMatchSettingsAttribute-    <$> decodeStrBits-    <*> decodeWord32leBits-    <*> decodeWord32leBits-    <*> decodeStrBits-    <*> decodeStrBits-    <*> getBool
− src/lib/Rattletrap/Decode/ProductAttribute.hs
@@ -1,70 +0,0 @@-module Rattletrap.Decode.ProductAttribute-  ( decodeProductAttributesBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.CompressedWord-import Rattletrap.Decode.Word32le-import Rattletrap.Decode.Word8le-import Rattletrap.Decode.Str-import Rattletrap.Type.Common-import Rattletrap.Type.ProductAttribute-import Rattletrap.Type.Str-import Rattletrap.Type.Word32le-import Rattletrap.Type.Word8le--import qualified Control.Monad as Monad-import qualified Data.Map as Map--decodeProductAttributesBits-  :: (Int, Int, Int) -> Map Word32le Str -> DecodeBits [ProductAttribute]-decodeProductAttributesBits version objectMap = do-  size <- decodeWord8leBits-  Monad.replicateM-    (fromIntegral (word8leValue size))-    (decodeProductAttributeBits version objectMap)--decodeProductAttributeBits-  :: (Int, Int, Int) -> Map Word32le Str -> DecodeBits ProductAttribute-decodeProductAttributeBits version objectMap = do-  flag <- getBool-  objectId <- decodeWord32leBits-  let maybeObjectName = Map.lookup objectId objectMap-  value <- case fromStr <$> maybeObjectName of-    Just "TAGame.ProductAttribute_Painted_TA" -> decodePainted version-    Just "TAGame.ProductAttribute_SpecialEdition_TA" -> decodeSpecialEdition-    Just "TAGame.ProductAttribute_TeamEdition_TA" -> decodeTeamEdition version-    Just "TAGame.ProductAttribute_TitleID_TA" -> decodeTitle-    Just "TAGame.ProductAttribute_UserColor_TA" -> decodeColor version-    Just objectName -> fail-      ("[RT05] unknown object name "-      <> show objectName-      <> " for ID "-      <> show objectId-      )-    Nothing -> fail ("[RT06] missing object name for ID " <> show objectId)-  pure (ProductAttribute flag objectId maybeObjectName value)--decodeSpecialEdition :: DecodeBits ProductAttributeValue-decodeSpecialEdition = ProductAttributeValueSpecialEdition <$> getBitsLE 31--decodePainted :: (Int, Int, Int) -> DecodeBits ProductAttributeValue-decodePainted version = if version >= (868, 18, 0)-  then ProductAttributeValuePaintedNew <$> getBitsLE 31-  else ProductAttributeValuePaintedOld <$> decodeCompressedWordBits 13--decodeTeamEdition :: (Int, Int, Int) -> DecodeBits ProductAttributeValue-decodeTeamEdition version = if version >= (868, 18, 0)-  then ProductAttributeValueTeamEditionNew <$> getBitsLE 31-  else ProductAttributeValueTeamEditionOld <$> decodeCompressedWordBits 13--decodeColor :: (Int, Int, Int) -> DecodeBits ProductAttributeValue-decodeColor version = if version >= (868, 23, 8)-  then ProductAttributeValueUserColorNew <$> decodeWord32leBits-  else do-    hasValue <- getBool-    ProductAttributeValueUserColorOld <$> decodeWhen hasValue (getBitsLE 31)--decodeTitle :: DecodeBits ProductAttributeValue-decodeTitle = ProductAttributeValueTitleId <$> decodeStrBits
− src/lib/Rattletrap/Decode/Property.hs
@@ -1,15 +0,0 @@-module Rattletrap.Decode.Property-  ( decodeProperty-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.PropertyValue-import Rattletrap.Decode.Str-import Rattletrap.Decode.Word64le-import Rattletrap.Type.Property--decodeProperty :: Decode Property-decodeProperty = do-  kind <- decodeStr-  Property kind <$> decodeWord64le <*> decodePropertyValue decodeProperty kind
− src/lib/Rattletrap/Decode/PropertyValue.hs
@@ -1,31 +0,0 @@-module Rattletrap.Decode.PropertyValue-  ( decodePropertyValue-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Dictionary-import Rattletrap.Decode.Float32le-import Rattletrap.Decode.Int32le-import Rattletrap.Decode.List-import Rattletrap.Decode.Str-import Rattletrap.Decode.Word64le-import Rattletrap.Decode.Word8le-import Rattletrap.Type.PropertyValue-import Rattletrap.Type.Str--decodePropertyValue :: Decode a -> Str -> Decode (PropertyValue a)-decodePropertyValue getProperty kind = case fromStr kind of-  "ArrayProperty" ->-    PropertyValueArray <$> decodeList (decodeDictionary getProperty)-  "BoolProperty" -> PropertyValueBool <$> decodeWord8le-  "ByteProperty" -> do-    k <- decodeStr-    PropertyValueByte k-      <$> decodeWhen (fromStr k /= "OnlinePlatform_Steam") decodeStr-  "FloatProperty" -> PropertyValueFloat <$> decodeFloat32le-  "IntProperty" -> PropertyValueInt <$> decodeInt32le-  "NameProperty" -> PropertyValueName <$> decodeStr-  "QWordProperty" -> PropertyValueQWord <$> decodeWord64le-  "StrProperty" -> PropertyValueStr <$> decodeStr-  _ -> fail ("[RT07] don't know how to read property value " <> show kind)
− src/lib/Rattletrap/Decode/QWordAttribute.hs
@@ -1,11 +0,0 @@-module Rattletrap.Decode.QWordAttribute-  ( decodeQWordAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Word64le-import Rattletrap.Type.QWordAttribute--decodeQWordAttributeBits :: DecodeBits QWordAttribute-decodeQWordAttributeBits = QWordAttribute <$> decodeWord64leBits
− src/lib/Rattletrap/Decode/Quaternion.hs
@@ -1,26 +0,0 @@-module Rattletrap.Decode.Quaternion-  ( decodeQuaternionBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.CompressedWord-import Rattletrap.Type.CompressedWord-import Rattletrap.Type.Quaternion--decodeQuaternionBits :: DecodeBits Quaternion-decodeQuaternionBits =-  toQuaternion <$> decodeComponent <*> decodePart <*> decodePart <*> decodePart--decodeComponent :: DecodeBits Component-decodeComponent = do-  x <- decodeCompressedWordBits 3-  case compressedWordValue x of-    0 -> pure ComponentX-    1 -> pure ComponentY-    2 -> pure ComponentZ-    3 -> pure ComponentW-    y -> fail ("[RT08] invalid component: " <> show y)--decodePart :: DecodeBits Double-decodePart = decompressPart <$> decodeCompressedWordBits maxCompressedValue
− src/lib/Rattletrap/Decode/RemoteId.hs
@@ -1,49 +0,0 @@-module Rattletrap.Decode.RemoteId-  ( decodeRemoteIdBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Str-import Rattletrap.Decode.Word64le-import Rattletrap.Type.RemoteId-import Rattletrap.Type.Word64le-import Rattletrap.Type.Word8le-import Rattletrap.Utility.Bytes--import qualified Data.ByteString as Bytes-import qualified Data.Text as Text-import qualified Data.Text.Encoding as Text-import qualified Data.Word as Word--decodeRemoteIdBits :: (Int, Int, Int) -> Word8le -> DecodeBits RemoteId-decodeRemoteIdBits version systemId = case word8leValue systemId of-  0 -> RemoteIdSplitscreen <$> getBitsLE 24-  1 -> RemoteIdSteam <$> decodeWord64leBits-  2 -> RemoteIdPlayStation <$> decodePsName <*> decodePsBytes version-  4 -> RemoteIdXbox <$> decodeWord64leBits-  6 -> do-    (a, b, c, d) <- getWord256-    pure $ RemoteIdSwitch a b c d-  7 -> if version >= (868, 24, 10)-    then RemoteIdPsyNet . Left <$> decodeWord64leBits-    else RemoteIdPsyNet . Right <$> getWord256-  11 -> RemoteIdEpic <$> decodeStrBits-  _ -> fail ("[RT09] unknown system id " <> show systemId)--decodePsName :: DecodeBits Text.Text-decodePsName = fmap-  (Text.dropWhileEnd (== '\x00') . Text.decodeLatin1 . reverseBytes)-  (getByteStringBits 16)--decodePsBytes :: (Int, Int, Int) -> DecodeBits [Word.Word8]-decodePsBytes version = Bytes.unpack-  <$> getByteStringBits (if version >= (868, 20, 1) then 24 else 16)--getWord256 :: DecodeBits (Word64le, Word64le, Word64le, Word64le)-getWord256 = do-  a <- decodeWord64leBits-  b <- decodeWord64leBits-  c <- decodeWord64leBits-  d <- decodeWord64leBits-  pure (a, b, c, d)
− src/lib/Rattletrap/Decode/Replay.hs
@@ -1,66 +0,0 @@-module Rattletrap.Decode.Replay-  ( decodeReplay-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Content-import Rattletrap.Decode.Header-import Rattletrap.Decode.Section-import Rattletrap.Encode.Content-import Rattletrap.Type.Content-import Rattletrap.Type.Dictionary-import Rattletrap.Type.Header-import Rattletrap.Type.Int32le-import Rattletrap.Type.Property-import Rattletrap.Type.PropertyValue-import Rattletrap.Type.Replay-import Rattletrap.Type.Section-import Rattletrap.Type.Str-import Rattletrap.Type.Word32le--decodeReplay :: Bool -> Decode FullReplay-decodeReplay fast = do-  header <- decodeSection decodeHeader-  content <- if fast-    then pure $ toSection putContent defaultContent-    else-      let body = sectionBody header-      in-        decodeSection $ decodeContent-          (getVersion body)-          (getNumFrames body)-          (getMaxChannels body)-  pure $ Replay header content--getVersion :: Header -> (Int, Int, Int)-getVersion header =-  ( fromIntegral (word32leValue (headerEngineVersion header))-  , fromIntegral (word32leValue (headerLicenseeVersion header))-  , getPatchVersion header-  )--getPatchVersion :: Header -> Int-getPatchVersion header = case headerPatchVersion header of-  Just version -> fromIntegral (word32leValue version)-  Nothing ->-    case dictionaryLookup (toStr "MatchType") (headerProperties header) of-      -- This is an ugly, ugly hack to handle replays from season 2 of RLCS.-      -- See `decodeSpawnedReplicationBits` and #85.-      Just Property { propertyValue = PropertyValueName str }-        | fromStr str == "Lan" -> -1-      _ -> 0--getNumFrames :: Header -> Int-getNumFrames header =-  case dictionaryLookup (toStr "NumFrames") (headerProperties header) of-    Just (Property _ _ (PropertyValueInt numFrames)) ->-      fromIntegral (int32leValue numFrames)-    _ -> 0--getMaxChannels :: Header -> Word-getMaxChannels header =-  case dictionaryLookup (toStr "MaxChannels") (headerProperties header) of-    Just (Property _ _ (PropertyValueInt numFrames)) ->-      fromIntegral (int32leValue numFrames)-    _ -> 1023
− src/lib/Rattletrap/Decode/Replication.hs
@@ -1,45 +0,0 @@-module Rattletrap.Decode.Replication-  ( decodeReplicationsBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.CompressedWord-import Rattletrap.Decode.ReplicationValue-import Rattletrap.Type.ClassAttributeMap-import Rattletrap.Type.CompressedWord-import Rattletrap.Type.Replication-import Rattletrap.Type.Word32le--import qualified Control.Monad.Trans.Class as Trans-import qualified Control.Monad.Trans.State as State-import qualified Data.Map as Map--decodeReplicationsBits-  :: (Int, Int, Int)-  -> Word-  -> ClassAttributeMap-  -> State.StateT-       (Map.Map CompressedWord Word32le)-       DecodeBits-       [Replication]-decodeReplicationsBits version limit classes = do-  hasReplication <- Trans.lift getBool-  if hasReplication-    then-      (:)-      <$> decodeReplicationBits version limit classes-      <*> decodeReplicationsBits version limit classes-    else pure []--decodeReplicationBits-  :: (Int, Int, Int)-  -> Word-  -> ClassAttributeMap-  -> State.StateT-       (Map.Map CompressedWord Word32le)-       DecodeBits-       Replication-decodeReplicationBits version limit classes = do-  actor <- Trans.lift (decodeCompressedWordBits limit)-  Replication actor <$> decodeReplicationValueBits version classes actor
− src/lib/Rattletrap/Decode/ReplicationValue.hs
@@ -1,45 +0,0 @@-module Rattletrap.Decode.ReplicationValue-  ( decodeReplicationValueBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.DestroyedReplication-import Rattletrap.Decode.SpawnedReplication-import Rattletrap.Decode.UpdatedReplication-import Rattletrap.Type.ClassAttributeMap-import Rattletrap.Type.CompressedWord-import Rattletrap.Type.ReplicationValue-import Rattletrap.Type.Word32le--import qualified Control.Monad.Trans.Class as Trans-import qualified Control.Monad.Trans.State as State-import qualified Data.Map as Map--decodeReplicationValueBits-  :: (Int, Int, Int)-  -> ClassAttributeMap-  -> CompressedWord-  -> State.StateT-       (Map.Map CompressedWord Word32le)-       DecodeBits-       ReplicationValue-decodeReplicationValueBits version classAttributeMap actorId = do-  actorMap <- State.get-  isOpen <- Trans.lift getBool-  if isOpen-    then do-      isNew <- Trans.lift getBool-      if isNew-        then-          ReplicationValueSpawned-            <$> decodeSpawnedReplicationBits version classAttributeMap actorId-        else ReplicationValueUpdated <$> Trans.lift-          (decodeUpdatedReplicationBits-            version-            classAttributeMap-            actorMap-            actorId-          )-    else ReplicationValueDestroyed-      <$> Trans.lift decodeDestroyedReplicationBits
− src/lib/Rattletrap/Decode/ReservationAttribute.hs
@@ -1,25 +0,0 @@-module Rattletrap.Decode.ReservationAttribute-  ( decodeReservationAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.CompressedWord-import Rattletrap.Decode.Str-import Rattletrap.Decode.UniqueIdAttribute-import Rattletrap.Type.ReservationAttribute-import Rattletrap.Type.UniqueIdAttribute-import Rattletrap.Type.Word8le--decodeReservationAttributeBits-  :: (Int, Int, Int) -> DecodeBits ReservationAttribute-decodeReservationAttributeBits version = do-  number <- decodeCompressedWordBits 7-  uniqueId <- decodeUniqueIdAttributeBits version-  ReservationAttribute number uniqueId-    <$> decodeWhen-          (uniqueIdAttributeSystemId uniqueId /= Word8le 0)-          decodeStrBits-    <*> getBool-    <*> getBool-    <*> decodeWhen (version >= (868, 12, 0)) (getWord8Bits 6)
− src/lib/Rattletrap/Decode/RigidBodyStateAttribute.hs
@@ -1,19 +0,0 @@-module Rattletrap.Decode.RigidBodyStateAttribute-  ( decodeRigidBodyStateAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Rotation-import Rattletrap.Decode.Vector-import Rattletrap.Type.RigidBodyStateAttribute--decodeRigidBodyStateAttributeBits-  :: (Int, Int, Int) -> DecodeBits RigidBodyStateAttribute-decodeRigidBodyStateAttributeBits version = do-  sleeping <- getBool-  RigidBodyStateAttribute sleeping-    <$> decodeVectorBits version-    <*> decodeRotationBits version-    <*> decodeWhen (not sleeping) (decodeVectorBits version)-    <*> decodeWhen (not sleeping) (decodeVectorBits version)
− src/lib/Rattletrap/Decode/Rotation.hs
@@ -1,14 +0,0 @@-module Rattletrap.Decode.Rotation-  ( decodeRotationBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.CompressedWordVector-import Rattletrap.Decode.Quaternion-import Rattletrap.Type.Rotation--decodeRotationBits :: (Int, Int, Int) -> DecodeBits Rotation-decodeRotationBits version = if version >= (868, 22, 7)-  then RotationQuaternion <$> decodeQuaternionBits-  else RotationCompressedWordVector <$> decodeCompressedWordVectorBits
− src/lib/Rattletrap/Decode/Section.hs
@@ -1,30 +0,0 @@-module Rattletrap.Decode.Section-  ( decodeSection-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Word32le-import Rattletrap.Type.Section-import Rattletrap.Type.Word32le-import Rattletrap.Utility.Crc--import qualified Control.Monad as Monad--decodeSection :: Decode a -> Decode (Section a)-decodeSection getBody = do-  size <- decodeWord32le-  crc <- decodeWord32le-  rawBody <- getByteString (fromIntegral (word32leValue size))-  let actualCrc = Word32le (getCrc32 rawBody)-  Monad.when (actualCrc /= crc) (fail (crcMessage actualCrc crc))-  body <- either fail pure (runDecode getBody rawBody)-  pure (Section size crc body)--crcMessage :: Word32le -> Word32le -> String-crcMessage actual expected = unwords-  [ "[RT10] actual CRC"-  , show actual-  , "does not match expected CRC"-  , show expected-  ]
− src/lib/Rattletrap/Decode/SpawnedReplication.hs
@@ -1,72 +0,0 @@-module Rattletrap.Decode.SpawnedReplication-  ( decodeSpawnedReplicationBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Initialization-import Rattletrap.Decode.Word32le-import Rattletrap.Type.ClassAttributeMap-import Rattletrap.Type.CompressedWord-import Rattletrap.Type.SpawnedReplication-import Rattletrap.Type.Str-import Rattletrap.Type.Word32le--import qualified Control.Monad.Trans.Class as Trans-import qualified Control.Monad.Trans.State as State-import qualified Data.Map as Map--decodeSpawnedReplicationBits-  :: (Int, Int, Int)-  -> ClassAttributeMap-  -> CompressedWord-  -> State.StateT-       (Map.Map CompressedWord Word32le)-       DecodeBits-       SpawnedReplication-decodeSpawnedReplicationBits version classAttributeMap actorId = do-  flag <- Trans.lift getBool-  nameIndex <- decodeWhen-    (version >= (868, 14, 0))-    (Trans.lift decodeWord32leBits)-  name <- either fail pure (lookupName classAttributeMap nameIndex)-  objectId <- Trans.lift decodeWord32leBits-  State.modify (Map.insert actorId objectId)-  objectName <- either fail pure (lookupObjectName classAttributeMap objectId)-  className <- either fail pure (lookupClassName objectName)-  let hasLocation = classHasLocation className-  let hasRotation = classHasRotation className-  initialization <- Trans.lift-    (decodeInitializationBits version hasLocation hasRotation)-  pure-    (SpawnedReplication-      flag-      nameIndex-      name-      objectId-      objectName-      className-      initialization-    )--lookupName :: ClassAttributeMap -> Maybe Word32le -> Either String (Maybe Str)-lookupName classAttributeMap maybeNameIndex = case maybeNameIndex of-  Nothing -> Right Nothing-  Just nameIndex ->-    case getName (classAttributeMapNameMap classAttributeMap) nameIndex of-      Nothing ->-        Left ("[RT11] could not get name for index " <> show nameIndex)-      Just name -> Right (Just name)--lookupObjectName :: ClassAttributeMap -> Word32le -> Either String Str-lookupObjectName classAttributeMap objectId =-  case getObjectName (classAttributeMapObjectMap classAttributeMap) objectId of-    Nothing ->-      Left ("[RT12] could not get object name for id " <> show objectId)-    Just objectName -> Right objectName--lookupClassName :: Str -> Either String Str-lookupClassName objectName = case getClassName objectName of-  Nothing ->-    Left ("[RT13] could not get class name for object " <> show objectName)-  Just className -> Right className
− src/lib/Rattletrap/Decode/StatEventAttribute.hs
@@ -1,12 +0,0 @@-module Rattletrap.Decode.StatEventAttribute-  ( decodeStatEventAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Int32le-import Rattletrap.Type.StatEventAttribute--decodeStatEventAttributeBits :: DecodeBits StatEventAttribute-decodeStatEventAttributeBits =-  StatEventAttribute <$> getBool <*> decodeInt32leBits
− src/lib/Rattletrap/Decode/Str.hs
@@ -1,47 +0,0 @@-module Rattletrap.Decode.Str-  ( decodeStr-  , decodeStrBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Int32le-import Rattletrap.Type.Int32le-import Rattletrap.Type.Str-import Rattletrap.Utility.Bytes--import qualified Data.ByteString as Bytes-import qualified Data.Text as Text-import qualified Data.Text.Encoding as Text-import qualified Data.Text.Encoding.Error as Text-import qualified Debug.Trace as Debug--decodeStr :: Decode Str-decodeStr = do-  rawSize <- decodeInt32le-  bytes <- getByteString (normalizeTextSize rawSize)-  pure (Str (dropNull (getTextDecoder rawSize bytes)))--decodeStrBits :: DecodeBits Str-decodeStrBits = do-  rawSize <- decodeInt32leBits-  bytes <- getByteStringBits (normalizeTextSize rawSize)-  pure (Str (dropNull (getTextDecoder rawSize (reverseBytes bytes))))--normalizeTextSize :: Integral a => Int32le -> a-normalizeTextSize size = case int32leValue size of-  0x05000000 -> 8-  x -> if x < 0 then (-2 * fromIntegral x) else fromIntegral x--getTextDecoder :: Int32le -> Bytes.ByteString -> Text.Text-getTextDecoder size bytes =-  let-    decode = if size < Int32le 0-      then Text.decodeUtf16LEWith $ \message input -> do-        Debug.traceM $ "WARNING: " <> show (Text.DecodeError message input)-        Text.lenientDecode message input-      else Text.decodeLatin1-  in decode bytes--dropNull :: Text.Text -> Text.Text-dropNull = Text.dropWhileEnd (== '\x00')
− src/lib/Rattletrap/Decode/StringAttribute.hs
@@ -1,11 +0,0 @@-module Rattletrap.Decode.StringAttribute-  ( decodeStringAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Str-import Rattletrap.Type.StringAttribute--decodeStringAttributeBits :: DecodeBits StringAttribute-decodeStringAttributeBits = StringAttribute <$> decodeStrBits
− src/lib/Rattletrap/Decode/TeamPaintAttribute.hs
@@ -1,18 +0,0 @@-module Rattletrap.Decode.TeamPaintAttribute-  ( decodeTeamPaintAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Word32le-import Rattletrap.Decode.Word8le-import Rattletrap.Type.TeamPaintAttribute--decodeTeamPaintAttributeBits :: DecodeBits TeamPaintAttribute-decodeTeamPaintAttributeBits =-  TeamPaintAttribute-    <$> decodeWord8leBits-    <*> decodeWord8leBits-    <*> decodeWord8leBits-    <*> decodeWord32leBits-    <*> decodeWord32leBits
− src/lib/Rattletrap/Decode/TitleAttribute.hs
@@ -1,20 +0,0 @@-module Rattletrap.Decode.TitleAttribute-  ( decodeTitleAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Word32le-import Rattletrap.Type.TitleAttribute--decodeTitleAttributeBits :: DecodeBits TitleAttribute-decodeTitleAttributeBits =-  TitleAttribute-    <$> getBool-    <*> getBool-    <*> decodeWord32leBits-    <*> decodeWord32leBits-    <*> decodeWord32leBits-    <*> decodeWord32leBits-    <*> decodeWord32leBits-    <*> getBool
− src/lib/Rattletrap/Decode/UniqueIdAttribute.hs
@@ -1,16 +0,0 @@-module Rattletrap.Decode.UniqueIdAttribute-  ( decodeUniqueIdAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.RemoteId-import Rattletrap.Decode.Word8le-import Rattletrap.Type.UniqueIdAttribute--decodeUniqueIdAttributeBits :: (Int, Int, Int) -> DecodeBits UniqueIdAttribute-decodeUniqueIdAttributeBits version = do-  systemId <- decodeWord8leBits-  UniqueIdAttribute systemId-    <$> decodeRemoteIdBits version systemId-    <*> decodeWord8leBits
− src/lib/Rattletrap/Decode/UpdatedReplication.hs
@@ -1,22 +0,0 @@-module Rattletrap.Decode.UpdatedReplication-  ( decodeUpdatedReplicationBits-  )-where--import Rattletrap.Decode.Attribute-import Rattletrap.Decode.Common-import Rattletrap.Type.ClassAttributeMap-import Rattletrap.Type.CompressedWord-import Rattletrap.Type.UpdatedReplication-import Rattletrap.Type.Word32le--import qualified Data.Map as Map--decodeUpdatedReplicationBits-  :: (Int, Int, Int)-  -> ClassAttributeMap-  -> Map.Map CompressedWord Word32le-  -> CompressedWord-  -> DecodeBits UpdatedReplication-decodeUpdatedReplicationBits version classes actors actor =-  UpdatedReplication <$> decodeAttributesBits version classes actors actor
− src/lib/Rattletrap/Decode/Vector.hs
@@ -1,29 +0,0 @@-module Rattletrap.Decode.Vector-  ( decodeVectorBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.CompressedWord-import Rattletrap.Type.CompressedWord-import Rattletrap.Type.Vector--decodeVectorBits :: (Int, Int, Int) -> DecodeBits Vector-decodeVectorBits version = do-  size <- decodeCompressedWordBits (if version >= (868, 22, 7) then 21 else 19)-  let-    limit = getLimit size-    bias = getBias size-  Vector size bias-    <$> fmap (fromDelta bias) (decodeCompressedWordBits limit)-    <*> fmap (fromDelta bias) (decodeCompressedWordBits limit)-    <*> fmap (fromDelta bias) (decodeCompressedWordBits limit)--getLimit :: CompressedWord -> Word-getLimit = (2 ^) . (+ 2) . compressedWordValue--getBias :: CompressedWord -> Word-getBias = (2 ^) . (+ 1) . compressedWordValue--fromDelta :: Word -> CompressedWord -> Int-fromDelta bias x = fromIntegral (compressedWordValue x) - fromIntegral bias
− src/lib/Rattletrap/Decode/WeldedInfoAttribute.hs
@@ -1,21 +0,0 @@-module Rattletrap.Decode.WeldedInfoAttribute-  ( decodeWeldedInfoAttributeBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Decode.Float32le-import Rattletrap.Decode.Int32le-import Rattletrap.Decode.Int8Vector-import Rattletrap.Decode.Vector-import Rattletrap.Type.WeldedInfoAttribute--decodeWeldedInfoAttributeBits-  :: (Int, Int, Int) -> DecodeBits WeldedInfoAttribute-decodeWeldedInfoAttributeBits version =-  WeldedInfoAttribute-    <$> getBool-    <*> decodeInt32leBits-    <*> decodeVectorBits version-    <*> decodeFloat32leBits-    <*> decodeInt8VectorBits
− src/lib/Rattletrap/Decode/Word32le.hs
@@ -1,14 +0,0 @@-module Rattletrap.Decode.Word32le-  ( decodeWord32le-  , decodeWord32leBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Type.Word32le--decodeWord32le :: Decode Word32le-decodeWord32le = Word32le <$> getWord32le--decodeWord32leBits :: DecodeBits Word32le-decodeWord32leBits = toBits decodeWord32le 4
− src/lib/Rattletrap/Decode/Word64le.hs
@@ -1,14 +0,0 @@-module Rattletrap.Decode.Word64le-  ( decodeWord64le-  , decodeWord64leBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Type.Word64le--decodeWord64le :: Decode Word64le-decodeWord64le = Word64le <$> getWord64le--decodeWord64leBits :: DecodeBits Word64le-decodeWord64leBits = toBits decodeWord64le 8
− src/lib/Rattletrap/Decode/Word8le.hs
@@ -1,14 +0,0 @@-module Rattletrap.Decode.Word8le-  ( decodeWord8le-  , decodeWord8leBits-  )-where--import Rattletrap.Decode.Common-import Rattletrap.Type.Word8le--decodeWord8le :: Decode Word8le-decodeWord8le = Word8le <$> getWord8--decodeWord8leBits :: DecodeBits Word8le-decodeWord8leBits = toBits decodeWord8le 1
− src/lib/Rattletrap/Encode/AppliedDamageAttribute.hs
@@ -1,18 +0,0 @@-module Rattletrap.Encode.AppliedDamageAttribute-  ( putAppliedDamageAttribute-  )-where--import Rattletrap.Encode.Int32le-import Rattletrap.Encode.Vector-import Rattletrap.Encode.Word8le-import Rattletrap.Type.AppliedDamageAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putAppliedDamageAttribute :: AppliedDamageAttribute -> BinaryBits.BitPut ()-putAppliedDamageAttribute appliedDamageAttribute = do-  putWord8Bits (appliedDamageAttributeUnknown1 appliedDamageAttribute)-  putVector (appliedDamageAttributeLocation appliedDamageAttribute)-  putInt32Bits (appliedDamageAttributeUnknown3 appliedDamageAttribute)-  putInt32Bits (appliedDamageAttributeUnknown4 appliedDamageAttribute)
− src/lib/Rattletrap/Encode/Attribute.hs
@@ -1,26 +0,0 @@-module Rattletrap.Encode.Attribute-  ( putAttributes-  )-where--import Rattletrap.Encode.AttributeValue-import Rattletrap.Encode.CompressedWord-import Rattletrap.Type.Attribute--import qualified Data.Binary.Bits.Put as BinaryBits--putAttributes :: [Attribute] -> BinaryBits.BitPut ()-putAttributes attributes = case attributes of-  [] -> BinaryBits.putBool False-  [attribute] -> do-    putAttribute attribute-    BinaryBits.putBool False-  first : rest -> do-    putAttribute first-    putAttributes rest--putAttribute :: Attribute -> BinaryBits.BitPut ()-putAttribute attribute = do-  BinaryBits.putBool True-  putCompressedWord (attributeId attribute)-  putAttributeValue (attributeValue attribute)
− src/lib/Rattletrap/Encode/AttributeMapping.hs
@@ -1,14 +0,0 @@-module Rattletrap.Encode.AttributeMapping-  ( putAttributeMapping-  )-where--import Rattletrap.Encode.Word32le-import Rattletrap.Type.AttributeMapping--import qualified Data.Binary as Binary--putAttributeMapping :: AttributeMapping -> Binary.Put-putAttributeMapping attributeMapping = do-  putWord32 (attributeMappingObjectId attributeMapping)-  putWord32 (attributeMappingStreamId attributeMapping)
− src/lib/Rattletrap/Encode/AttributeValue.hs
@@ -1,85 +0,0 @@-module Rattletrap.Encode.AttributeValue-  ( putAttributeValue-  )-where--import Rattletrap.Encode.AppliedDamageAttribute-import Rattletrap.Encode.BooleanAttribute-import Rattletrap.Encode.ByteAttribute-import Rattletrap.Encode.CamSettingsAttribute-import Rattletrap.Encode.ClubColorsAttribute-import Rattletrap.Encode.CustomDemolishAttribute-import Rattletrap.Encode.DamageStateAttribute-import Rattletrap.Encode.DemolishAttribute-import Rattletrap.Encode.EnumAttribute-import Rattletrap.Encode.ExplosionAttribute-import Rattletrap.Encode.ExtendedExplosionAttribute-import Rattletrap.Encode.FlaggedIntAttribute-import Rattletrap.Encode.FlaggedByteAttribute-import Rattletrap.Encode.FloatAttribute-import Rattletrap.Encode.GameModeAttribute-import Rattletrap.Encode.Int64Attribute-import Rattletrap.Encode.IntAttribute-import Rattletrap.Encode.LoadoutAttribute-import Rattletrap.Encode.LoadoutOnlineAttribute-import Rattletrap.Encode.LoadoutsAttribute-import Rattletrap.Encode.LoadoutsOnlineAttribute-import Rattletrap.Encode.LocationAttribute-import Rattletrap.Encode.MusicStingerAttribute-import Rattletrap.Encode.PartyLeaderAttribute-import Rattletrap.Encode.PickupAttribute-import Rattletrap.Encode.PickupAttributeNew-import Rattletrap.Encode.PlayerHistoryKeyAttribute-import Rattletrap.Encode.PrivateMatchSettingsAttribute-import Rattletrap.Encode.QWordAttribute-import Rattletrap.Encode.ReservationAttribute-import Rattletrap.Encode.RigidBodyStateAttribute-import Rattletrap.Encode.StatEventAttribute-import Rattletrap.Encode.StringAttribute-import Rattletrap.Encode.TeamPaintAttribute-import Rattletrap.Encode.TitleAttribute-import Rattletrap.Encode.UniqueIdAttribute-import Rattletrap.Encode.WeldedInfoAttribute-import Rattletrap.Type.AttributeValue--import qualified Data.Binary.Bits.Put as BinaryBits--putAttributeValue :: AttributeValue -> BinaryBits.BitPut ()-putAttributeValue value = case value of-  AttributeValueAppliedDamage x -> putAppliedDamageAttribute x-  AttributeValueBoolean x -> putBooleanAttribute x-  AttributeValueByte x -> putByteAttribute x-  AttributeValueCamSettings x -> putCamSettingsAttribute x-  AttributeValueClubColors x -> putClubColorsAttribute x-  AttributeValueCustomDemolish x -> putCustomDemolishAttribute x-  AttributeValueDamageState x -> putDamageStateAttribute x-  AttributeValueDemolish x -> putDemolishAttribute x-  AttributeValueEnum x -> putEnumAttribute x-  AttributeValueExplosion x -> putExplosionAttribute x-  AttributeValueExtendedExplosion x -> putExtendedExplosionAttribute x-  AttributeValueFlaggedInt x -> putFlaggedIntAttribute x-  AttributeValueFlaggedByte x -> putFlaggedByteAttribute x-  AttributeValueFloat x -> putFloatAttribute x-  AttributeValueGameMode x -> putGameModeAttribute x-  AttributeValueInt x -> putIntAttribute x-  AttributeValueInt64 x -> putInt64Attribute x-  AttributeValueLoadout x -> putLoadoutAttribute x-  AttributeValueLoadoutOnline x -> putLoadoutOnlineAttribute x-  AttributeValueLoadouts x -> putLoadoutsAttribute x-  AttributeValueLoadoutsOnline x -> putLoadoutsOnlineAttribute x-  AttributeValueLocation x -> putLocationAttribute x-  AttributeValueMusicStinger x -> putMusicStingerAttribute x-  AttributeValuePartyLeader x -> putPartyLeaderAttribute x-  AttributeValuePickup x -> putPickupAttribute x-  AttributeValuePickupNew x -> putPickupAttributeNew x-  AttributeValuePlayerHistoryKey x -> putPlayerHistoryKeyAttribute x-  AttributeValuePrivateMatchSettings x -> putPrivateMatchSettingsAttribute x-  AttributeValueQWord x -> putQWordAttribute x-  AttributeValueReservation x -> putReservationAttribute x-  AttributeValueRigidBodyState x -> putRigidBodyStateAttribute x-  AttributeValueStatEvent x -> putStatEventAttribute x-  AttributeValueString x -> putStringAttribute x-  AttributeValueTeamPaint x -> putTeamPaintAttribute x-  AttributeValueTitle x -> putTitleAttribute x-  AttributeValueUniqueId x -> putUniqueIdAttribute x-  AttributeValueWeldedInfo x -> putWeldedInfoAttribute x
− src/lib/Rattletrap/Encode/BooleanAttribute.hs
@@ -1,12 +0,0 @@-module Rattletrap.Encode.BooleanAttribute-  ( putBooleanAttribute-  )-where--import Rattletrap.Type.BooleanAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putBooleanAttribute :: BooleanAttribute -> BinaryBits.BitPut ()-putBooleanAttribute booleanAttribute =-  BinaryBits.putBool (booleanAttributeValue booleanAttribute)
− src/lib/Rattletrap/Encode/ByteAttribute.hs
@@ -1,13 +0,0 @@-module Rattletrap.Encode.ByteAttribute-  ( putByteAttribute-  )-where--import Rattletrap.Encode.Word8le-import Rattletrap.Type.ByteAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putByteAttribute :: ByteAttribute -> BinaryBits.BitPut ()-putByteAttribute byteAttribute =-  putWord8Bits (byteAttributeValue byteAttribute)
− src/lib/Rattletrap/Encode/Cache.hs
@@ -1,18 +0,0 @@-module Rattletrap.Encode.Cache-  ( putCache-  )-where--import Rattletrap.Encode.AttributeMapping-import Rattletrap.Encode.List-import Rattletrap.Encode.Word32le-import Rattletrap.Type.Cache--import qualified Data.Binary as Binary--putCache :: Cache -> Binary.Put-putCache cache = do-  putWord32 (cacheClassId cache)-  putWord32 (cacheParentCacheId cache)-  putWord32 (cacheCacheId cache)-  putList putAttributeMapping (cacheAttributeMappings cache)
− src/lib/Rattletrap/Encode/CamSettingsAttribute.hs
@@ -1,21 +0,0 @@-module Rattletrap.Encode.CamSettingsAttribute-  ( putCamSettingsAttribute-  )-where--import Rattletrap.Encode.Float32le-import Rattletrap.Type.CamSettingsAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putCamSettingsAttribute :: CamSettingsAttribute -> BinaryBits.BitPut ()-putCamSettingsAttribute camSettingsAttribute = do-  putFloat32Bits (camSettingsAttributeFov camSettingsAttribute)-  putFloat32Bits (camSettingsAttributeHeight camSettingsAttribute)-  putFloat32Bits (camSettingsAttributeAngle camSettingsAttribute)-  putFloat32Bits (camSettingsAttributeDistance camSettingsAttribute)-  putFloat32Bits (camSettingsAttributeStiffness camSettingsAttribute)-  putFloat32Bits (camSettingsAttributeSwivelSpeed camSettingsAttribute)-  case camSettingsAttributeTransitionSpeed camSettingsAttribute of-    Nothing -> pure ()-    Just transitionSpeed -> putFloat32Bits transitionSpeed
− src/lib/Rattletrap/Encode/ClassMapping.hs
@@ -1,15 +0,0 @@-module Rattletrap.Encode.ClassMapping-  ( putClassMapping-  )-where--import Rattletrap.Encode.Str-import Rattletrap.Encode.Word32le-import Rattletrap.Type.ClassMapping--import qualified Data.Binary as Binary--putClassMapping :: ClassMapping -> Binary.Put-putClassMapping classMapping = do-  putText (classMappingName classMapping)-  putWord32 (classMappingStreamId classMapping)
− src/lib/Rattletrap/Encode/ClubColorsAttribute.hs
@@ -1,16 +0,0 @@-module Rattletrap.Encode.ClubColorsAttribute-  ( putClubColorsAttribute-  )-where--import Rattletrap.Encode.Word8le-import Rattletrap.Type.ClubColorsAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putClubColorsAttribute :: ClubColorsAttribute -> BinaryBits.BitPut ()-putClubColorsAttribute clubColorsAttribute = do-  BinaryBits.putBool (clubColorsAttributeBlueFlag clubColorsAttribute)-  putWord8Bits (clubColorsAttributeBlueColor clubColorsAttribute)-  BinaryBits.putBool (clubColorsAttributeOrangeFlag clubColorsAttribute)-  putWord8Bits (clubColorsAttributeOrangeColor clubColorsAttribute)
− src/lib/Rattletrap/Encode/Common.hs
@@ -1,10 +0,0 @@-module Rattletrap.Encode.Common-  ( putBitsLE-  )-where--import qualified Data.Binary.Bits.Put as BinaryBits-import qualified Data.Bits as Bits--putBitsLE :: Bits.Bits a => Int -> a -> BinaryBits.BitPut ()-putBitsLE size x = mapM_ (BinaryBits.putBool . Bits.testBit x) [0 .. size - 1]
− src/lib/Rattletrap/Encode/CompressedWord.hs
@@ -1,44 +0,0 @@-module Rattletrap.Encode.CompressedWord-  ( putCompressedWord-  )-where--import Rattletrap.Type.CompressedWord--import qualified Data.Binary.Bits.Put as BinaryBits-import qualified Data.Bits as Bits--putCompressedWord :: CompressedWord -> BinaryBits.BitPut ()-putCompressedWord compressedWord =-  let-    limit = compressedWordLimit compressedWord-    value = compressedWordValue compressedWord-    maxBits = getMaxBits limit-  in putCompressedWordStep limit value maxBits 0 0--putCompressedWordStep-  :: Word -> Word -> Int -> Int -> Word -> BinaryBits.BitPut ()-putCompressedWordStep limit value maxBits position soFar =-  if position < maxBits-    then do-      let x = Bits.shiftL 1 position :: Word-      if maxBits > 1 && position == maxBits - 1 && soFar + x > limit-        then pure ()-        else do-          let bit = Bits.testBit value position-          BinaryBits.putBool bit-          let delta = if bit then x else 0-          putCompressedWordStep-            limit-            value-            maxBits-            (position + 1)-            (soFar + delta)-    else pure ()--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
− src/lib/Rattletrap/Encode/CompressedWordVector.hs
@@ -1,15 +0,0 @@-module Rattletrap.Encode.CompressedWordVector-  ( putCompressedWordVector-  )-where--import Rattletrap.Encode.CompressedWord-import Rattletrap.Type.CompressedWordVector--import qualified Data.Binary.Bits.Put as BinaryBits--putCompressedWordVector :: CompressedWordVector -> BinaryBits.BitPut ()-putCompressedWordVector compressedWordVector = do-  putCompressedWord (compressedWordVectorX compressedWordVector)-  putCompressedWord (compressedWordVectorY compressedWordVector)-  putCompressedWord (compressedWordVectorZ compressedWordVector)
− src/lib/Rattletrap/Encode/Content.hs
@@ -1,58 +0,0 @@-module Rattletrap.Encode.Content-  ( putContent-  )-where--import Rattletrap.Encode.Cache-import Rattletrap.Encode.ClassMapping-import Rattletrap.Encode.Frame-import Rattletrap.Encode.KeyFrame-import Rattletrap.Encode.List-import Rattletrap.Encode.Mark-import Rattletrap.Encode.Message-import Rattletrap.Encode.Str-import Rattletrap.Encode.Word32le-import Rattletrap.Type.Content-import Rattletrap.Type.Word32le-import Rattletrap.Utility.Bytes--import qualified Data.Binary as Binary-import qualified Data.Binary.Bits.Put as BinaryBits-import qualified Data.Binary.Put as Binary-import qualified Data.ByteString as Bytes-import qualified Data.ByteString.Lazy as LazyBytes--putContent :: Content -> Binary.Put-putContent content = do-  putList putText (contentLevels content)-  putList putKeyFrame (contentKeyFrames content)-  let-    stream = LazyBytes.toStrict-      (Binary.runPut (BinaryBits.runBitPut (putFrames (contentFrames content)))-      )-    -- 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 = contentStreamSize content-    actualStreamSize = Word32le . fromIntegral $ Bytes.length stream-    streamSize = Word32le $ max-      (word32leValue expectedStreamSize)-      (word32leValue actualStreamSize)-  putWord32 streamSize-  Binary.putByteString-    (reverseBytes (padBytes (word32leValue streamSize) stream))-  putList putMessage (contentMessages content)-  putList putMark (contentMarks content)-  putList putText (contentPackages content)-  putList putText (contentObjects content)-  putList putText (contentNames content)-  putList putClassMapping (contentClassMappings content)-  putList putCache (contentCaches content)-  mapM_ Binary.putWord8 (contentUnknown content)
− src/lib/Rattletrap/Encode/CustomDemolishAttribute.hs
@@ -1,16 +0,0 @@-module Rattletrap.Encode.CustomDemolishAttribute-  ( putCustomDemolishAttribute-  )-where--import Rattletrap.Encode.DemolishAttribute-import Rattletrap.Encode.Int32le-import Rattletrap.Type.CustomDemolishAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putCustomDemolishAttribute :: CustomDemolishAttribute -> BinaryBits.BitPut ()-putCustomDemolishAttribute x = do-  BinaryBits.putBool (customDemolishAttributeFlag x)-  putInt32Bits (customDemolishAttributeId x)-  putDemolishAttribute (customDemolishAttributeDemolish x)
− src/lib/Rattletrap/Encode/DamageStateAttribute.hs
@@ -1,20 +0,0 @@-module Rattletrap.Encode.DamageStateAttribute-  ( putDamageStateAttribute-  )-where--import Rattletrap.Encode.Int32le-import Rattletrap.Encode.Vector-import Rattletrap.Encode.Word8le-import Rattletrap.Type.DamageStateAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putDamageStateAttribute :: DamageStateAttribute -> BinaryBits.BitPut ()-putDamageStateAttribute damageStateAttribute = do-  putWord8Bits (damageStateAttributeUnknown1 damageStateAttribute)-  BinaryBits.putBool (damageStateAttributeUnknown2 damageStateAttribute)-  putInt32Bits (damageStateAttributeUnknown3 damageStateAttribute)-  putVector (damageStateAttributeUnknown4 damageStateAttribute)-  BinaryBits.putBool (damageStateAttributeUnknown5 damageStateAttribute)-  BinaryBits.putBool (damageStateAttributeUnknown6 damageStateAttribute)
− src/lib/Rattletrap/Encode/DemolishAttribute.hs
@@ -1,19 +0,0 @@-module Rattletrap.Encode.DemolishAttribute-  ( putDemolishAttribute-  )-where--import Rattletrap.Encode.Vector-import Rattletrap.Encode.Word32le-import Rattletrap.Type.DemolishAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putDemolishAttribute :: DemolishAttribute -> BinaryBits.BitPut ()-putDemolishAttribute demolishAttribute = do-  BinaryBits.putBool (demolishAttributeAttackerFlag demolishAttribute)-  putWord32Bits (demolishAttributeAttackerActorId demolishAttribute)-  BinaryBits.putBool (demolishAttributeVictimFlag demolishAttribute)-  putWord32Bits (demolishAttributeVictimActorId demolishAttribute)-  putVector (demolishAttributeAttackerVelocity demolishAttribute)-  putVector (demolishAttributeVictimVelocity demolishAttribute)
− src/lib/Rattletrap/Encode/DestroyedReplication.hs
@@ -1,11 +0,0 @@-module Rattletrap.Encode.DestroyedReplication-  ( putDestroyedReplication-  )-where--import Rattletrap.Type.DestroyedReplication--import qualified Data.Binary.Bits.Put as BinaryBits--putDestroyedReplication :: DestroyedReplication -> BinaryBits.BitPut ()-putDestroyedReplication _ = pure ()
− src/lib/Rattletrap/Encode/Dictionary.hs
@@ -1,17 +0,0 @@-module Rattletrap.Encode.Dictionary-  ( putDictionary-  )-where--import Rattletrap.Encode.Str-import Rattletrap.Type.Dictionary--import qualified Data.Binary as Binary--putDictionary :: (a -> Binary.Put) -> Dictionary a -> Binary.Put-putDictionary f x = case x of-  DictionaryElement k v y -> do-    putText k-    f v-    putDictionary f y-  DictionaryEnd y -> putText y
− src/lib/Rattletrap/Encode/EnumAttribute.hs
@@ -1,13 +0,0 @@-module Rattletrap.Encode.EnumAttribute-  ( putEnumAttribute-  )-where--import Rattletrap.Encode.Common-import Rattletrap.Type.EnumAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putEnumAttribute :: EnumAttribute -> BinaryBits.BitPut ()-putEnumAttribute enumAttribute =-  putBitsLE 11 (enumAttributeValue enumAttribute)
− src/lib/Rattletrap/Encode/ExplosionAttribute.hs
@@ -1,16 +0,0 @@-module Rattletrap.Encode.ExplosionAttribute-  ( putExplosionAttribute-  )-where--import Rattletrap.Encode.Int32le-import Rattletrap.Encode.Vector-import Rattletrap.Type.ExplosionAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putExplosionAttribute :: ExplosionAttribute -> BinaryBits.BitPut ()-putExplosionAttribute explosionAttribute = do-  BinaryBits.putBool False-  putInt32Bits (explosionAttributeActorId explosionAttribute)-  putVector (explosionAttributeLocation explosionAttribute)
− src/lib/Rattletrap/Encode/ExtendedExplosionAttribute.hs
@@ -1,16 +0,0 @@-module Rattletrap.Encode.ExtendedExplosionAttribute-  ( putExtendedExplosionAttribute-  )-where--import Rattletrap.Encode.ExplosionAttribute-import Rattletrap.Encode.FlaggedIntAttribute-import Rattletrap.Type.ExtendedExplosionAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putExtendedExplosionAttribute-  :: ExtendedExplosionAttribute -> BinaryBits.BitPut ()-putExtendedExplosionAttribute x = do-  putExplosionAttribute (extendedExplosionAttributeExplosion x)-  putFlaggedIntAttribute (extendedExplosionAttributeUnknown x)
− src/lib/Rattletrap/Encode/FlaggedByteAttribute.hs
@@ -1,14 +0,0 @@-module Rattletrap.Encode.FlaggedByteAttribute-  ( putFlaggedByteAttribute-  )-where--import Rattletrap.Encode.Word8le-import Rattletrap.Type.FlaggedByteAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putFlaggedByteAttribute :: FlaggedByteAttribute -> BinaryBits.BitPut ()-putFlaggedByteAttribute flaggedByteAttribute = do-  BinaryBits.putBool (flaggedByteAttributeFlag flaggedByteAttribute)-  putWord8Bits (flaggedByteAttributeByte flaggedByteAttribute)
− src/lib/Rattletrap/Encode/FlaggedIntAttribute.hs
@@ -1,14 +0,0 @@-module Rattletrap.Encode.FlaggedIntAttribute-  ( putFlaggedIntAttribute-  )-where--import Rattletrap.Encode.Int32le-import Rattletrap.Type.FlaggedIntAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putFlaggedIntAttribute :: FlaggedIntAttribute -> BinaryBits.BitPut ()-putFlaggedIntAttribute flaggedIntAttribute = do-  BinaryBits.putBool (flaggedIntAttributeFlag flaggedIntAttribute)-  putInt32Bits (flaggedIntAttributeInt flaggedIntAttribute)
− src/lib/Rattletrap/Encode/Float32le.hs
@@ -1,21 +0,0 @@-module Rattletrap.Encode.Float32le-  ( putFloat32-  , putFloat32Bits-  )-where--import Rattletrap.Type.Float32le-import Rattletrap.Utility.Bytes--import qualified Data.Binary as Binary-import qualified Data.Binary.Bits.Put as BinaryBits-import qualified Data.Binary.Put as Binary-import qualified Data.ByteString.Lazy as LazyBytes--putFloat32 :: Float32le -> Binary.Put-putFloat32 = Binary.putFloatle . float32leValue--putFloat32Bits :: Float32le -> BinaryBits.BitPut ()-putFloat32Bits float32 = do-  let bytes = LazyBytes.toStrict (Binary.runPut (putFloat32 float32))-  BinaryBits.putByteString (reverseBytes bytes)
− src/lib/Rattletrap/Encode/FloatAttribute.hs
@@ -1,13 +0,0 @@-module Rattletrap.Encode.FloatAttribute-  ( putFloatAttribute-  )-where--import Rattletrap.Encode.Float32le-import Rattletrap.Type.FloatAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putFloatAttribute :: FloatAttribute -> BinaryBits.BitPut ()-putFloatAttribute floatAttribute =-  putFloat32Bits (floatAttributeValue floatAttribute)
− src/lib/Rattletrap/Encode/Frame.hs
@@ -1,24 +0,0 @@-module Rattletrap.Encode.Frame-  ( putFrames-  )-where--import Rattletrap.Encode.Float32le-import Rattletrap.Encode.Replication-import Rattletrap.Type.Frame--import qualified Data.Binary.Bits.Put as BinaryBits--putFrames :: [Frame] -> BinaryBits.BitPut ()-putFrames frames = case frames of-  [] -> pure ()-  [frame] -> putFrame frame-  first : rest -> do-    putFrame first-    putFrames rest--putFrame :: Frame -> BinaryBits.BitPut ()-putFrame frame = do-  putFloat32Bits (frameTime frame)-  putFloat32Bits (frameDelta frame)-  putReplications (frameReplications frame)
− src/lib/Rattletrap/Encode/GameModeAttribute.hs
@@ -1,14 +0,0 @@-module Rattletrap.Encode.GameModeAttribute-  ( putGameModeAttribute-  )-where--import Rattletrap.Type.GameModeAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putGameModeAttribute :: GameModeAttribute -> BinaryBits.BitPut ()-putGameModeAttribute gameModeAttribute = do-  let numBits = gameModeAttributeNumBits gameModeAttribute-  let word = gameModeAttributeWord gameModeAttribute-  BinaryBits.putWord8 numBits word
− src/lib/Rattletrap/Encode/Header.hs
@@ -1,22 +0,0 @@-module Rattletrap.Encode.Header-  ( putHeader-  )-where--import Rattletrap.Encode.Dictionary-import Rattletrap.Encode.Property-import Rattletrap.Encode.Str-import Rattletrap.Encode.Word32le-import Rattletrap.Type.Header--import qualified Data.Binary as Binary--putHeader :: Header -> Binary.Put-putHeader header = do-  putWord32 (headerEngineVersion header)-  putWord32 (headerLicenseeVersion header)-  case headerPatchVersion header of-    Nothing -> pure ()-    Just patchVersion -> putWord32 patchVersion-  putText (headerLabel header)-  putDictionary putProperty (headerProperties header)
− src/lib/Rattletrap/Encode/Initialization.hs
@@ -1,19 +0,0 @@-module Rattletrap.Encode.Initialization-  ( putInitialization-  )-where--import Rattletrap.Encode.Int8Vector-import Rattletrap.Encode.Vector-import Rattletrap.Type.Initialization--import qualified Data.Binary.Bits.Put as BinaryBits--putInitialization :: Initialization -> BinaryBits.BitPut ()-putInitialization initialization = do-  case initializationLocation initialization of-    Nothing -> pure ()-    Just location -> putVector location-  case initializationRotation initialization of-    Nothing -> pure ()-    Just rotation -> putInt8Vector rotation
− src/lib/Rattletrap/Encode/Int32le.hs
@@ -1,21 +0,0 @@-module Rattletrap.Encode.Int32le-  ( putInt32-  , putInt32Bits-  )-where--import Rattletrap.Type.Int32le-import Rattletrap.Utility.Bytes--import qualified Data.Binary as Binary-import qualified Data.Binary.Bits.Put as BinaryBits-import qualified Data.Binary.Put as Binary-import qualified Data.ByteString.Lazy as LazyBytes--putInt32 :: Int32le -> Binary.Put-putInt32 int32 = Binary.putInt32le (int32leValue int32)--putInt32Bits :: Int32le -> BinaryBits.BitPut ()-putInt32Bits int32 = do-  let bytes = LazyBytes.toStrict (Binary.runPut (putInt32 int32))-  BinaryBits.putByteString (reverseBytes bytes)
− src/lib/Rattletrap/Encode/Int64Attribute.hs
@@ -1,13 +0,0 @@-module Rattletrap.Encode.Int64Attribute-  ( putInt64Attribute-  )-where--import Rattletrap.Encode.Int64le-import Rattletrap.Type.Int64Attribute--import qualified Data.Binary.Bits.Put as BinaryBits--putInt64Attribute :: Int64Attribute -> BinaryBits.BitPut ()-putInt64Attribute int64Attribute =-  putInt64Bits (int64AttributeValue int64Attribute)
− src/lib/Rattletrap/Encode/Int64le.hs
@@ -1,20 +0,0 @@-module Rattletrap.Encode.Int64le-  ( putInt64Bits-  )-where--import Rattletrap.Type.Int64le-import Rattletrap.Utility.Bytes--import qualified Data.Binary as Binary-import qualified Data.Binary.Bits.Put as BinaryBits-import qualified Data.Binary.Put as Binary-import qualified Data.ByteString.Lazy as LazyBytes--putInt64 :: Int64le -> Binary.Put-putInt64 int64 = Binary.putInt64le (int64leValue int64)--putInt64Bits :: Int64le -> BinaryBits.BitPut ()-putInt64Bits int64 = do-  let bytes = LazyBytes.toStrict (Binary.runPut (putInt64 int64))-  BinaryBits.putByteString (reverseBytes bytes)
− src/lib/Rattletrap/Encode/Int8Vector.hs
@@ -1,23 +0,0 @@-module Rattletrap.Encode.Int8Vector-  ( putInt8Vector-  )-where--import Rattletrap.Encode.Int8le-import Rattletrap.Type.Int8Vector-import Rattletrap.Type.Int8le--import qualified Data.Binary.Bits.Put as BinaryBits--putInt8Vector :: Int8Vector -> BinaryBits.BitPut ()-putInt8Vector int8Vector = do-  putInt8VectorField (int8VectorX int8Vector)-  putInt8VectorField (int8VectorY int8Vector)-  putInt8VectorField (int8VectorZ int8Vector)--putInt8VectorField :: Maybe Int8le -> BinaryBits.BitPut ()-putInt8VectorField maybeField = case maybeField of-  Nothing -> BinaryBits.putBool False-  Just field -> do-    BinaryBits.putBool True-    putInt8Bits field
− src/lib/Rattletrap/Encode/Int8le.hs
@@ -1,19 +0,0 @@-module Rattletrap.Encode.Int8le-  ( putInt8Bits-  )-where--import Rattletrap.Type.Int8le-import Rattletrap.Utility.Bytes--import qualified Data.Binary.Bits.Put as BinaryBits-import qualified Data.Binary.Put as Binary-import qualified Data.ByteString.Lazy as LazyBytes--putInt8 :: Int8le -> Binary.Put-putInt8 int8 = Binary.putInt8 (int8leValue int8)--putInt8Bits :: Int8le -> BinaryBits.BitPut ()-putInt8Bits int8 = do-  let bytes = LazyBytes.toStrict (Binary.runPut (putInt8 int8))-  BinaryBits.putByteString (reverseBytes bytes)
− src/lib/Rattletrap/Encode/IntAttribute.hs
@@ -1,12 +0,0 @@-module Rattletrap.Encode.IntAttribute-  ( putIntAttribute-  )-where--import Rattletrap.Encode.Int32le-import Rattletrap.Type.IntAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putIntAttribute :: IntAttribute -> BinaryBits.BitPut ()-putIntAttribute intAttribute = putInt32Bits (intAttributeValue intAttribute)
− src/lib/Rattletrap/Encode/KeyFrame.hs
@@ -1,16 +0,0 @@-module Rattletrap.Encode.KeyFrame-  ( putKeyFrame-  )-where--import Rattletrap.Encode.Float32le-import Rattletrap.Encode.Word32le-import Rattletrap.Type.KeyFrame--import qualified Data.Binary as Binary--putKeyFrame :: KeyFrame -> Binary.Put-putKeyFrame keyFrame = do-  putFloat32 (keyFrameTime keyFrame)-  putWord32 (keyFrameFrame keyFrame)-  putWord32 (keyFramePosition keyFrame)
− src/lib/Rattletrap/Encode/List.hs
@@ -1,16 +0,0 @@-module Rattletrap.Encode.List-  ( putList-  )-where--import Rattletrap.Encode.Word32le-import Rattletrap.Type.List-import Rattletrap.Type.Word32le--import qualified Data.Binary as Binary--putList :: (a -> Binary.Put) -> List a -> Binary.Put-putList putElement list = do-  let elements = listValue list-  putWord32 (Word32le (fromIntegral (length elements)))-  mapM_ putElement elements
− src/lib/Rattletrap/Encode/LoadoutAttribute.hs
@@ -1,35 +0,0 @@-module Rattletrap.Encode.LoadoutAttribute-  ( putLoadoutAttribute-  )-where--import Rattletrap.Encode.Word32le-import Rattletrap.Encode.Word8le-import Rattletrap.Type.LoadoutAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putLoadoutAttribute :: LoadoutAttribute -> BinaryBits.BitPut ()-putLoadoutAttribute loadoutAttribute = do-  putWord8Bits (loadoutAttributeVersion loadoutAttribute)-  putWord32Bits (loadoutAttributeBody loadoutAttribute)-  putWord32Bits (loadoutAttributeDecal loadoutAttribute)-  putWord32Bits (loadoutAttributeWheels loadoutAttribute)-  putWord32Bits (loadoutAttributeRocketTrail loadoutAttribute)-  putWord32Bits (loadoutAttributeAntenna loadoutAttribute)-  putWord32Bits (loadoutAttributeTopper loadoutAttribute)-  putWord32Bits (loadoutAttributeUnknown1 loadoutAttribute)-  putOptional (loadoutAttributeUnknown2 loadoutAttribute) putWord32Bits-  putOptional (loadoutAttributeEngineAudio loadoutAttribute) putWord32Bits-  putOptional (loadoutAttributeTrail loadoutAttribute) putWord32Bits-  putOptional (loadoutAttributeGoalExplosion loadoutAttribute) putWord32Bits-  putOptional (loadoutAttributeBanner loadoutAttribute) putWord32Bits-  putOptional (loadoutAttributeUnknown3 loadoutAttribute) putWord32Bits-  putOptional (loadoutAttributeUnknown4 loadoutAttribute) putWord32Bits-  putOptional (loadoutAttributeUnknown5 loadoutAttribute) putWord32Bits-  putOptional (loadoutAttributeUnknown6 loadoutAttribute) putWord32Bits--putOptional :: Maybe a -> (a -> BinaryBits.BitPut ()) -> BinaryBits.BitPut ()-putOptional m f = case m of-  Just x -> f x-  Nothing -> pure ()
− src/lib/Rattletrap/Encode/LoadoutOnlineAttribute.hs
@@ -1,17 +0,0 @@-module Rattletrap.Encode.LoadoutOnlineAttribute-  ( putLoadoutOnlineAttribute-  )-where--import Rattletrap.Encode.ProductAttribute-import Rattletrap.Encode.Word8le-import Rattletrap.Type.LoadoutOnlineAttribute-import Rattletrap.Type.Word8le--import qualified Data.Binary.Bits.Put as BinaryBits--putLoadoutOnlineAttribute :: LoadoutOnlineAttribute -> BinaryBits.BitPut ()-putLoadoutOnlineAttribute loadoutAttribute = do-  let attributes = loadoutAttributeValue loadoutAttribute-  putWord8Bits (Word8le (fromIntegral (length attributes)))-  mapM_ putProductAttributes attributes
− src/lib/Rattletrap/Encode/LoadoutsAttribute.hs
@@ -1,14 +0,0 @@-module Rattletrap.Encode.LoadoutsAttribute-  ( putLoadoutsAttribute-  )-where--import Rattletrap.Encode.LoadoutAttribute-import Rattletrap.Type.LoadoutsAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putLoadoutsAttribute :: LoadoutsAttribute -> BinaryBits.BitPut ()-putLoadoutsAttribute loadoutsAttribute = do-  putLoadoutAttribute (loadoutsAttributeBlue loadoutsAttribute)-  putLoadoutAttribute (loadoutsAttributeOrange loadoutsAttribute)
− src/lib/Rattletrap/Encode/LoadoutsOnlineAttribute.hs
@@ -1,18 +0,0 @@-module Rattletrap.Encode.LoadoutsOnlineAttribute-  ( putLoadoutsOnlineAttribute-  )-where--import Rattletrap.Encode.LoadoutOnlineAttribute-import Rattletrap.Type.LoadoutsOnlineAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putLoadoutsOnlineAttribute :: LoadoutsOnlineAttribute -> BinaryBits.BitPut ()-putLoadoutsOnlineAttribute loadoutsOnlineAttribute = do-  putLoadoutOnlineAttribute-    (loadoutsOnlineAttributeBlue loadoutsOnlineAttribute)-  putLoadoutOnlineAttribute-    (loadoutsOnlineAttributeOrange loadoutsOnlineAttribute)-  BinaryBits.putBool (loadoutsOnlineAttributeUnknown1 loadoutsOnlineAttribute)-  BinaryBits.putBool (loadoutsOnlineAttributeUnknown2 loadoutsOnlineAttribute)
− src/lib/Rattletrap/Encode/LocationAttribute.hs
@@ -1,13 +0,0 @@-module Rattletrap.Encode.LocationAttribute-  ( putLocationAttribute-  )-where--import Rattletrap.Encode.Vector-import Rattletrap.Type.LocationAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putLocationAttribute :: LocationAttribute -> BinaryBits.BitPut ()-putLocationAttribute locationAttribute =-  putVector (locationAttributeValue locationAttribute)
− src/lib/Rattletrap/Encode/Mark.hs
@@ -1,15 +0,0 @@-module Rattletrap.Encode.Mark-  ( putMark-  )-where--import Rattletrap.Encode.Str-import Rattletrap.Encode.Word32le-import Rattletrap.Type.Mark--import qualified Data.Binary as Binary--putMark :: Mark -> Binary.Put-putMark mark = do-  putText (markValue mark)-  putWord32 (markFrame mark)
− src/lib/Rattletrap/Encode/Message.hs
@@ -1,16 +0,0 @@-module Rattletrap.Encode.Message-  ( putMessage-  )-where--import Rattletrap.Encode.Str-import Rattletrap.Encode.Word32le-import Rattletrap.Type.Message--import qualified Data.Binary as Binary--putMessage :: Message -> Binary.Put-putMessage message = do-  putWord32 (messageFrame message)-  putText (messageName message)-  putText (messageValue message)
− src/lib/Rattletrap/Encode/MusicStingerAttribute.hs
@@ -1,16 +0,0 @@-module Rattletrap.Encode.MusicStingerAttribute-  ( putMusicStingerAttribute-  )-where--import Rattletrap.Encode.Word32le-import Rattletrap.Encode.Word8le-import Rattletrap.Type.MusicStingerAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putMusicStingerAttribute :: MusicStingerAttribute -> BinaryBits.BitPut ()-putMusicStingerAttribute musicStingerAttribute = do-  BinaryBits.putBool (musicStingerAttributeFlag musicStingerAttribute)-  putWord32Bits (musicStingerAttributeCue musicStingerAttribute)-  putWord8Bits (musicStingerAttributeTrigger musicStingerAttribute)
− src/lib/Rattletrap/Encode/PartyLeaderAttribute.hs
@@ -1,19 +0,0 @@-module Rattletrap.Encode.PartyLeaderAttribute-  ( putPartyLeaderAttribute-  )-where--import Rattletrap.Encode.RemoteId-import Rattletrap.Encode.Word8le-import Rattletrap.Type.PartyLeaderAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putPartyLeaderAttribute :: PartyLeaderAttribute -> BinaryBits.BitPut ()-putPartyLeaderAttribute partyLeaderAttribute = do-  putWord8Bits (partyLeaderAttributeSystemId partyLeaderAttribute)-  case partyLeaderAttributeId partyLeaderAttribute of-    Nothing -> pure ()-    Just (remoteId, localId) -> do-      putRemoteId remoteId-      putWord8Bits localId
− src/lib/Rattletrap/Encode/PickupAttribute.hs
@@ -1,18 +0,0 @@-module Rattletrap.Encode.PickupAttribute-  ( putPickupAttribute-  )-where--import Rattletrap.Encode.Word32le-import Rattletrap.Type.PickupAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putPickupAttribute :: PickupAttribute -> BinaryBits.BitPut ()-putPickupAttribute pickupAttribute = do-  case pickupAttributeInstigatorId pickupAttribute of-    Nothing -> BinaryBits.putBool False-    Just instigatorId -> do-      BinaryBits.putBool True-      putWord32Bits instigatorId-  BinaryBits.putBool (pickupAttributePickedUp pickupAttribute)
− src/lib/Rattletrap/Encode/PickupAttributeNew.hs
@@ -1,19 +0,0 @@-module Rattletrap.Encode.PickupAttributeNew-  ( putPickupAttributeNew-  )-where--import Rattletrap.Encode.Word32le-import Rattletrap.Encode.Word8le-import Rattletrap.Type.PickupAttributeNew--import qualified Data.Binary.Bits.Put as BinaryBits--putPickupAttributeNew :: PickupAttributeNew -> BinaryBits.BitPut ()-putPickupAttributeNew pickupAttributeNew = do-  case pickupAttributeNewInstigatorId pickupAttributeNew of-    Nothing -> BinaryBits.putBool False-    Just instigatorId -> do-      BinaryBits.putBool True-      putWord32Bits instigatorId-  putWord8Bits (pickupAttributeNewPickedUp pickupAttributeNew)
− src/lib/Rattletrap/Encode/PlayerHistoryKeyAttribute.hs
@@ -1,13 +0,0 @@-module Rattletrap.Encode.PlayerHistoryKeyAttribute-  ( putPlayerHistoryKeyAttribute-  )-where--import Rattletrap.Encode.Common-import Rattletrap.Type.PlayerHistoryKeyAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putPlayerHistoryKeyAttribute-  :: PlayerHistoryKeyAttribute -> BinaryBits.BitPut ()-putPlayerHistoryKeyAttribute = putBitsLE 14 . playerHistoryKeyAttributeUnknown
− src/lib/Rattletrap/Encode/PrivateMatchSettingsAttribute.hs
@@ -1,26 +0,0 @@-module Rattletrap.Encode.PrivateMatchSettingsAttribute-  ( putPrivateMatchSettingsAttribute-  )-where--import Rattletrap.Encode.Str-import Rattletrap.Encode.Word32le-import Rattletrap.Type.PrivateMatchSettingsAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putPrivateMatchSettingsAttribute-  :: PrivateMatchSettingsAttribute -> BinaryBits.BitPut ()-putPrivateMatchSettingsAttribute privateMatchSettingsAttribute = do-  putTextBits-    (privateMatchSettingsAttributeMutators privateMatchSettingsAttribute)-  putWord32Bits-    (privateMatchSettingsAttributeJoinableBy privateMatchSettingsAttribute)-  putWord32Bits-    (privateMatchSettingsAttributeMaxPlayers privateMatchSettingsAttribute)-  putTextBits-    (privateMatchSettingsAttributeGameName privateMatchSettingsAttribute)-  putTextBits-    (privateMatchSettingsAttributePassword privateMatchSettingsAttribute)-  BinaryBits.putBool-    (privateMatchSettingsAttributeFlag privateMatchSettingsAttribute)
− src/lib/Rattletrap/Encode/ProductAttribute.hs
@@ -1,37 +0,0 @@-module Rattletrap.Encode.ProductAttribute-  ( putProductAttributes-  )-where--import Rattletrap.Encode.Common-import Rattletrap.Encode.CompressedWord-import Rattletrap.Encode.Word32le-import Rattletrap.Encode.Word8le-import Rattletrap.Encode.Str-import Rattletrap.Type.ProductAttribute-import Rattletrap.Type.Word8le--import qualified Data.Binary.Bits.Put as BinaryBits--putProductAttributes :: [ProductAttribute] -> BinaryBits.BitPut ()-putProductAttributes attributes = do-  putWord8Bits (Word8le (fromIntegral (length attributes)))-  mapM_ putProductAttribute attributes--putProductAttribute :: ProductAttribute -> BinaryBits.BitPut ()-putProductAttribute attribute = do-  BinaryBits.putBool (productAttributeUnknown attribute)-  putWord32Bits (productAttributeObjectId attribute)-  case productAttributeValue attribute of-    ProductAttributeValuePaintedOld x -> putCompressedWord x-    ProductAttributeValuePaintedNew x -> putBitsLE 31 x-    ProductAttributeValueTeamEditionOld x -> putCompressedWord x-    ProductAttributeValueTeamEditionNew x -> putBitsLE 31 x-    ProductAttributeValueSpecialEdition x -> putBitsLE 31 x-    ProductAttributeValueUserColorOld x -> case x of-      Nothing -> BinaryBits.putBool False-      Just y -> do-        BinaryBits.putBool True-        putBitsLE 31 y-    ProductAttributeValueUserColorNew x -> putWord32Bits x-    ProductAttributeValueTitleId x -> putTextBits x
− src/lib/Rattletrap/Encode/Property.hs
@@ -1,17 +0,0 @@-module Rattletrap.Encode.Property-  ( putProperty-  )-where--import Rattletrap.Encode.PropertyValue-import Rattletrap.Encode.Str-import Rattletrap.Encode.Word64le-import Rattletrap.Type.Property--import qualified Data.Binary as Binary--putProperty :: Property -> Binary.Put-putProperty property = do-  putText (propertyKind property)-  putWord64 (propertySize property)-  putPropertyValue putProperty (propertyValue property)
− src/lib/Rattletrap/Encode/PropertyValue.hs
@@ -1,30 +0,0 @@-module Rattletrap.Encode.PropertyValue-  ( putPropertyValue-  )-where--import Rattletrap.Encode.Dictionary-import Rattletrap.Encode.Float32le-import Rattletrap.Encode.Int32le-import Rattletrap.Encode.List-import Rattletrap.Encode.Str-import Rattletrap.Encode.Word64le-import Rattletrap.Encode.Word8le-import Rattletrap.Type.PropertyValue--import qualified Data.Binary as Binary--putPropertyValue :: (a -> Binary.Put) -> PropertyValue a -> Binary.Put-putPropertyValue putProperty value = case value of-  PropertyValueArray list -> putList (putDictionary putProperty) list-  PropertyValueBool word8 -> putWord8 word8-  PropertyValueByte k mv -> do-    putText k-    case mv of-      Nothing -> pure ()-      Just v -> putText v-  PropertyValueFloat float32 -> putFloat32 float32-  PropertyValueInt int32 -> putInt32 int32-  PropertyValueName text -> putText text-  PropertyValueQWord word64 -> putWord64 word64-  PropertyValueStr text -> putText text
− src/lib/Rattletrap/Encode/QWordAttribute.hs
@@ -1,13 +0,0 @@-module Rattletrap.Encode.QWordAttribute-  ( putQWordAttribute-  )-where--import Rattletrap.Encode.Word64le-import Rattletrap.Type.QWordAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putQWordAttribute :: QWordAttribute -> BinaryBits.BitPut ()-putQWordAttribute qWordAttribute =-  putWord64Bits (qWordAttributeValue qWordAttribute)
− src/lib/Rattletrap/Encode/Quaternion.hs
@@ -1,41 +0,0 @@-module Rattletrap.Encode.Quaternion-  ( putQuaternion-  )-where--import Rattletrap.Encode.CompressedWord-import Rattletrap.Type.CompressedWord-import Rattletrap.Type.Quaternion--import qualified Data.Binary.Bits.Put as BinaryBits--putQuaternion :: Quaternion -> BinaryBits.BitPut ()-putQuaternion q = do-  let c = maxComponent q-  putComponent c-  case c of-    ComponentX -> putParts (quaternionY q) (quaternionZ q) (quaternionW q)-    ComponentY -> putParts (quaternionX q) (quaternionZ q) (quaternionW q)-    ComponentZ -> putParts (quaternionX q) (quaternionY q) (quaternionW q)-    ComponentW -> putParts (quaternionX q) (quaternionY q) (quaternionZ q)--putComponent :: Component -> BinaryBits.BitPut ()-putComponent component = putCompressedWord-  (CompressedWord-    3-    (case component of-      ComponentX -> 0-      ComponentY -> 1-      ComponentZ -> 2-      ComponentW -> 3-    )-  )--putParts :: Double -> Double -> Double -> BinaryBits.BitPut ()-putParts a b c = do-  putPart a-  putPart b-  putPart c--putPart :: Double -> BinaryBits.BitPut ()-putPart = putCompressedWord . compressPart
− src/lib/Rattletrap/Encode/RemoteId.hs
@@ -1,37 +0,0 @@-module Rattletrap.Encode.RemoteId-  ( putRemoteId-  )-where--import Rattletrap.Encode.Common-import Rattletrap.Encode.Str-import Rattletrap.Encode.Word64le-import Rattletrap.Type.RemoteId-import Rattletrap.Type.Word64le-import Rattletrap.Utility.Bytes--import qualified Data.Binary.Bits.Put as BinaryBits-import qualified Data.ByteString as Bytes--putRemoteId :: RemoteId -> BinaryBits.BitPut ()-putRemoteId remoteId = case remoteId of-  RemoteIdPlayStation name bytes -> do-    let rawName = reverseBytes (padBytes (16 :: Int) (encodeLatin1 name))-    BinaryBits.putByteString rawName-    BinaryBits.putByteString (Bytes.pack bytes)-  RemoteIdPsyNet e -> case e of-    Left l -> putWord64Bits l-    Right (a, b, c, d) -> putWord256 a b c d-  RemoteIdSplitscreen word24 -> putBitsLE 24 word24-  RemoteIdSteam word64 -> putWord64Bits word64-  RemoteIdSwitch a b c d -> putWord256 a b c d-  RemoteIdXbox word64 -> putWord64Bits word64-  RemoteIdEpic str -> putTextBits str--putWord256-  :: Word64le -> Word64le -> Word64le -> Word64le -> BinaryBits.BitPut ()-putWord256 a b c d = do-  putWord64Bits a-  putWord64Bits b-  putWord64Bits c-  putWord64Bits d
− src/lib/Rattletrap/Encode/Replay.hs
@@ -1,21 +0,0 @@-module Rattletrap.Encode.Replay-  ( putReplay-  )-where--import Rattletrap.Encode.Content-import Rattletrap.Encode.Header-import Rattletrap.Encode.Section-import Rattletrap.Type.Replay--import qualified Data.Binary as Binary---- | Generates a raw replay. Use this with 'Data.Binary.Put.runPut'.------ @--- let bytes = 'Data.Binary.Put.runPut' ('putReplay' replay)--- @-putReplay :: FullReplay -> Binary.Put-putReplay replay = do-  putSection putHeader (replayHeader replay)-  putSection putContent (replayContent replay)
− src/lib/Rattletrap/Encode/Replication.hs
@@ -1,26 +0,0 @@-module Rattletrap.Encode.Replication-  ( putReplications-  )-where--import Rattletrap.Encode.CompressedWord-import Rattletrap.Encode.ReplicationValue-import Rattletrap.Type.Replication--import qualified Data.Binary.Bits.Put as BinaryBits--putReplications :: [Replication] -> BinaryBits.BitPut ()-putReplications replications = case replications of-  [] -> BinaryBits.putBool False-  [replication] -> do-    putReplication replication-    BinaryBits.putBool False-  first : rest -> do-    putReplication first-    putReplications rest--putReplication :: Replication -> BinaryBits.BitPut ()-putReplication replication = do-  BinaryBits.putBool True-  putCompressedWord (replicationActorId replication)-  putReplicationValue (replicationValue replication)
− src/lib/Rattletrap/Encode/ReplicationValue.hs
@@ -1,25 +0,0 @@-module Rattletrap.Encode.ReplicationValue-  ( putReplicationValue-  )-where--import Rattletrap.Encode.DestroyedReplication-import Rattletrap.Encode.SpawnedReplication-import Rattletrap.Encode.UpdatedReplication-import Rattletrap.Type.ReplicationValue--import qualified Data.Binary.Bits.Put as BinaryBits--putReplicationValue :: ReplicationValue -> BinaryBits.BitPut ()-putReplicationValue value = case value of-  ReplicationValueSpawned x -> do-    BinaryBits.putBool True-    BinaryBits.putBool True-    putSpawnedReplication x-  ReplicationValueUpdated x -> do-    BinaryBits.putBool True-    BinaryBits.putBool False-    putUpdatedReplication x-  ReplicationValueDestroyed x -> do-    BinaryBits.putBool False-    putDestroyedReplication x
− src/lib/Rattletrap/Encode/ReservationAttribute.hs
@@ -1,24 +0,0 @@-module Rattletrap.Encode.ReservationAttribute-  ( putReservationAttribute-  )-where--import Rattletrap.Encode.CompressedWord-import Rattletrap.Encode.Str-import Rattletrap.Encode.UniqueIdAttribute-import Rattletrap.Type.ReservationAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putReservationAttribute :: ReservationAttribute -> BinaryBits.BitPut ()-putReservationAttribute reservationAttribute = do-  putCompressedWord (reservationAttributeNumber reservationAttribute)-  putUniqueIdAttribute (reservationAttributeUniqueId reservationAttribute)-  case reservationAttributeName reservationAttribute of-    Nothing -> pure ()-    Just name -> putTextBits name-  BinaryBits.putBool (reservationAttributeUnknown1 reservationAttribute)-  BinaryBits.putBool (reservationAttributeUnknown2 reservationAttribute)-  case reservationAttributeUnknown3 reservationAttribute of-    Nothing -> pure ()-    Just c -> BinaryBits.putWord8 6 c
− src/lib/Rattletrap/Encode/RigidBodyStateAttribute.hs
@@ -1,22 +0,0 @@-module Rattletrap.Encode.RigidBodyStateAttribute-  ( putRigidBodyStateAttribute-  )-where--import Rattletrap.Encode.Rotation-import Rattletrap.Encode.Vector-import Rattletrap.Type.RigidBodyStateAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putRigidBodyStateAttribute :: RigidBodyStateAttribute -> BinaryBits.BitPut ()-putRigidBodyStateAttribute rigidBodyStateAttribute = do-  BinaryBits.putBool (rigidBodyStateAttributeSleeping rigidBodyStateAttribute)-  putVector (rigidBodyStateAttributeLocation rigidBodyStateAttribute)-  putRotation (rigidBodyStateAttributeRotation rigidBodyStateAttribute)-  case rigidBodyStateAttributeLinearVelocity rigidBodyStateAttribute of-    Nothing -> pure ()-    Just linearVelocity -> putVector linearVelocity-  case rigidBodyStateAttributeAngularVelocity rigidBodyStateAttribute of-    Nothing -> pure ()-    Just angularVelocity -> putVector angularVelocity
− src/lib/Rattletrap/Encode/Rotation.hs
@@ -1,15 +0,0 @@-module Rattletrap.Encode.Rotation-  ( putRotation-  )-where--import Rattletrap.Encode.CompressedWordVector-import Rattletrap.Encode.Quaternion-import Rattletrap.Type.Rotation--import qualified Data.Binary.Bits.Put as BinaryBits--putRotation :: Rotation -> BinaryBits.BitPut ()-putRotation r = case r of-  RotationCompressedWordVector cwv -> putCompressedWordVector cwv-  RotationQuaternion q -> putQuaternion q
− src/lib/Rattletrap/Encode/Section.hs
@@ -1,31 +0,0 @@-module Rattletrap.Encode.Section-  ( putSection-  )-where--import Rattletrap.Encode.Word32le-import Rattletrap.Type.Section-import Rattletrap.Type.Word32le-import Rattletrap.Utility.Crc--import qualified Data.Binary as Binary-import qualified Data.Binary.Put as Binary-import qualified Data.ByteString as Bytes-import qualified Data.ByteString.Lazy as LazyBytes---- | Given a way to put the 'sectionBody', puts a section. This will also put--- the size and CRC.------ @--- let bytes = 'Data.Binary.Put.runPut' ('putSection' 'Rattletrap.Content.putContent' content)--- @-putSection :: (a -> Binary.Put) -> Section a -> Binary.Put-putSection putBody section = do-  let-    rawBody =-      LazyBytes.toStrict (Binary.runPut (putBody (sectionBody section)))-  let size = Bytes.length rawBody-  let crc = getCrc32 rawBody-  putWord32 (Word32le (fromIntegral size))-  putWord32 (Word32le crc)-  Binary.putByteString rawBody
− src/lib/Rattletrap/Encode/SpawnedReplication.hs
@@ -1,19 +0,0 @@-module Rattletrap.Encode.SpawnedReplication-  ( putSpawnedReplication-  )-where--import Rattletrap.Encode.Initialization-import Rattletrap.Encode.Word32le-import Rattletrap.Type.SpawnedReplication--import qualified Data.Binary.Bits.Put as BinaryBits--putSpawnedReplication :: SpawnedReplication -> BinaryBits.BitPut ()-putSpawnedReplication spawnedReplication = do-  BinaryBits.putBool (spawnedReplicationFlag spawnedReplication)-  case spawnedReplicationNameIndex spawnedReplication of-    Nothing -> pure ()-    Just nameIndex -> putWord32Bits nameIndex-  putWord32Bits (spawnedReplicationObjectId spawnedReplication)-  putInitialization (spawnedReplicationInitialization spawnedReplication)
− src/lib/Rattletrap/Encode/StatEventAttribute.hs
@@ -1,14 +0,0 @@-module Rattletrap.Encode.StatEventAttribute-  ( putStatEventAttribute-  )-where--import Rattletrap.Encode.Int32le-import Rattletrap.Type.StatEventAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putStatEventAttribute :: StatEventAttribute -> BinaryBits.BitPut ()-putStatEventAttribute statEventAttribute = do-  BinaryBits.putBool (statEventAttributeUnknown statEventAttribute)-  putInt32Bits (statEventAttributeObjectId statEventAttribute)
− src/lib/Rattletrap/Encode/Str.hs
@@ -1,53 +0,0 @@-module Rattletrap.Encode.Str-  ( putText-  , putTextBits-  )-where--import Rattletrap.Encode.Int32le-import Rattletrap.Type.Common-import Rattletrap.Type.Int32le-import Rattletrap.Type.Str-import Rattletrap.Utility.Bytes--import qualified Data.Binary as Binary-import qualified Data.Binary.Bits.Put as BinaryBits-import qualified Data.Binary.Put as Binary-import qualified Data.ByteString as Bytes-import qualified Data.Char as Char-import qualified Data.Text as Text-import qualified Data.Text.Encoding as Text--putText :: Str -> Binary.Put-putText text = do-  let size = getTextSize text-  let encode = getTextEncoder size-  putInt32 size-  Binary.putByteString (encode (addNull (strValue text)))--putTextBits :: Str -> BinaryBits.BitPut ()-putTextBits text = do-  let size = getTextSize text-  let encode = getTextEncoder size-  putInt32Bits size-  BinaryBits.putByteString (reverseBytes (encode (addNull (strValue text))))--getTextSize :: Str -> Int32le-getTextSize text =-  let-    value = strValue text-    scale = if Text.all Char.isLatin1 value then 1 else -1 :: Int32-    rawSize = if Text.null value-      then 0-      else fromIntegral (Text.length value) + 1 :: Int32-    size = if value == Text.pack "\x00\x00\x00None"-      then 0x05000000-      else scale * rawSize :: Int32-  in Int32le size--getTextEncoder :: Int32le -> Text.Text -> Bytes.ByteString-getTextEncoder size text =-  if size < Int32le 0 then Text.encodeUtf16LE text else encodeLatin1 text--addNull :: Text.Text -> Text.Text-addNull text = if Text.null text then text else Text.snoc text '\x00'
− src/lib/Rattletrap/Encode/StringAttribute.hs
@@ -1,13 +0,0 @@-module Rattletrap.Encode.StringAttribute-  ( putStringAttribute-  )-where--import Rattletrap.Encode.Str-import Rattletrap.Type.StringAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putStringAttribute :: StringAttribute -> BinaryBits.BitPut ()-putStringAttribute stringAttribute =-  putTextBits (stringAttributeValue stringAttribute)
− src/lib/Rattletrap/Encode/TeamPaintAttribute.hs
@@ -1,18 +0,0 @@-module Rattletrap.Encode.TeamPaintAttribute-  ( putTeamPaintAttribute-  )-where--import Rattletrap.Encode.Word32le-import Rattletrap.Encode.Word8le-import Rattletrap.Type.TeamPaintAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putTeamPaintAttribute :: TeamPaintAttribute -> BinaryBits.BitPut ()-putTeamPaintAttribute teamPaintAttribute = do-  putWord8Bits (teamPaintAttributeTeam teamPaintAttribute)-  putWord8Bits (teamPaintAttributePrimaryColor teamPaintAttribute)-  putWord8Bits (teamPaintAttributeAccentColor teamPaintAttribute)-  putWord32Bits (teamPaintAttributePrimaryFinish teamPaintAttribute)-  putWord32Bits (teamPaintAttributeAccentFinish teamPaintAttribute)
− src/lib/Rattletrap/Encode/TitleAttribute.hs
@@ -1,20 +0,0 @@-module Rattletrap.Encode.TitleAttribute-  ( putTitleAttribute-  )-where--import Rattletrap.Encode.Word32le-import Rattletrap.Type.TitleAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putTitleAttribute :: TitleAttribute -> BinaryBits.BitPut ()-putTitleAttribute titleAttribute = do-  BinaryBits.putBool (titleAttributeUnknown1 titleAttribute)-  BinaryBits.putBool (titleAttributeUnknown2 titleAttribute)-  putWord32Bits (titleAttributeUnknown3 titleAttribute)-  putWord32Bits (titleAttributeUnknown4 titleAttribute)-  putWord32Bits (titleAttributeUnknown5 titleAttribute)-  putWord32Bits (titleAttributeUnknown6 titleAttribute)-  putWord32Bits (titleAttributeUnknown7 titleAttribute)-  BinaryBits.putBool (titleAttributeUnknown8 titleAttribute)
− src/lib/Rattletrap/Encode/UniqueIdAttribute.hs
@@ -1,16 +0,0 @@-module Rattletrap.Encode.UniqueIdAttribute-  ( putUniqueIdAttribute-  )-where--import Rattletrap.Encode.RemoteId-import Rattletrap.Encode.Word8le-import Rattletrap.Type.UniqueIdAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putUniqueIdAttribute :: UniqueIdAttribute -> BinaryBits.BitPut ()-putUniqueIdAttribute uniqueIdAttribute = do-  putWord8Bits (uniqueIdAttributeSystemId uniqueIdAttribute)-  putRemoteId (uniqueIdAttributeRemoteId uniqueIdAttribute)-  putWord8Bits (uniqueIdAttributeLocalId uniqueIdAttribute)
− src/lib/Rattletrap/Encode/UpdatedReplication.hs
@@ -1,13 +0,0 @@-module Rattletrap.Encode.UpdatedReplication-  ( putUpdatedReplication-  )-where--import Rattletrap.Encode.Attribute-import Rattletrap.Type.UpdatedReplication--import qualified Data.Binary.Bits.Put as BinaryBits--putUpdatedReplication :: UpdatedReplication -> BinaryBits.BitPut ()-putUpdatedReplication updatedReplication =-  putAttributes (updatedReplicationAttributes updatedReplication)
− src/lib/Rattletrap/Encode/Vector.hs
@@ -1,27 +0,0 @@-module Rattletrap.Encode.Vector-  ( putVector-  )-where--import Rattletrap.Encode.CompressedWord-import Rattletrap.Type.CompressedWord-import Rattletrap.Type.Vector--import qualified Data.Binary.Bits.Put as BinaryBits--putVector :: Vector -> BinaryBits.BitPut ()-putVector vector = do-  let-    bitSize =-      round (logBase (2 :: Float) (fromIntegral (vectorBias vector))) - 1 :: Word-    dx =-      fromIntegral (vectorX vector + fromIntegral (vectorBias vector)) :: Word-    dy =-      fromIntegral (vectorY vector + fromIntegral (vectorBias vector)) :: Word-    dz =-      fromIntegral (vectorZ vector + fromIntegral (vectorBias vector)) :: Word-    limit = 2 ^ (bitSize + 2) :: Word-  putCompressedWord (vectorSize vector)-  putCompressedWord (CompressedWord limit dx)-  putCompressedWord (CompressedWord limit dy)-  putCompressedWord (CompressedWord limit dz)
− src/lib/Rattletrap/Encode/WeldedInfoAttribute.hs
@@ -1,20 +0,0 @@-module Rattletrap.Encode.WeldedInfoAttribute-  ( putWeldedInfoAttribute-  )-where--import Rattletrap.Encode.Float32le-import Rattletrap.Encode.Int32le-import Rattletrap.Encode.Int8Vector-import Rattletrap.Encode.Vector-import Rattletrap.Type.WeldedInfoAttribute--import qualified Data.Binary.Bits.Put as BinaryBits--putWeldedInfoAttribute :: WeldedInfoAttribute -> BinaryBits.BitPut ()-putWeldedInfoAttribute weldedInfoAttribute = do-  BinaryBits.putBool (weldedInfoAttributeActive weldedInfoAttribute)-  putInt32Bits (weldedInfoAttributeActorId weldedInfoAttribute)-  putVector (weldedInfoAttributeOffset weldedInfoAttribute)-  putFloat32Bits (weldedInfoAttributeMass weldedInfoAttribute)-  putInt8Vector (weldedInfoAttributeRotation weldedInfoAttribute)
− src/lib/Rattletrap/Encode/Word32le.hs
@@ -1,21 +0,0 @@-module Rattletrap.Encode.Word32le-  ( putWord32-  , putWord32Bits-  )-where--import Rattletrap.Type.Word32le-import Rattletrap.Utility.Bytes--import qualified Data.Binary as Binary-import qualified Data.Binary.Bits.Put as BinaryBits-import qualified Data.Binary.Put as Binary-import qualified Data.ByteString.Lazy as LazyBytes--putWord32 :: Word32le -> Binary.Put-putWord32 word32 = Binary.putWord32le (word32leValue word32)--putWord32Bits :: Word32le -> BinaryBits.BitPut ()-putWord32Bits word32 = do-  let bytes = LazyBytes.toStrict (Binary.runPut (putWord32 word32))-  BinaryBits.putByteString (reverseBytes bytes)
− src/lib/Rattletrap/Encode/Word64le.hs
@@ -1,21 +0,0 @@-module Rattletrap.Encode.Word64le-  ( putWord64-  , putWord64Bits-  )-where--import Rattletrap.Type.Word64le-import Rattletrap.Utility.Bytes--import qualified Data.Binary as Binary-import qualified Data.Binary.Bits.Put as BinaryBits-import qualified Data.Binary.Put as Binary-import qualified Data.ByteString.Lazy as LazyBytes--putWord64 :: Word64le -> Binary.Put-putWord64 word64 = Binary.putWord64le (word64leValue word64)--putWord64Bits :: Word64le -> BinaryBits.BitPut ()-putWord64Bits word64 = do-  let bytes = LazyBytes.toStrict (Binary.runPut (putWord64 word64))-  BinaryBits.putByteString (reverseBytes bytes)
− src/lib/Rattletrap/Encode/Word8le.hs
@@ -1,21 +0,0 @@-module Rattletrap.Encode.Word8le-  ( putWord8-  , putWord8Bits-  )-where--import Rattletrap.Type.Word8le-import Rattletrap.Utility.Bytes--import qualified Data.Binary as Binary-import qualified Data.Binary.Bits.Put as BinaryBits-import qualified Data.Binary.Put as Binary-import qualified Data.ByteString.Lazy as LazyBytes--putWord8 :: Word8le -> Binary.Put-putWord8 word8 = Binary.putWord8 (word8leValue word8)--putWord8Bits :: Word8le -> BinaryBits.BitPut ()-putWord8Bits word8 = do-  let bytes = LazyBytes.toStrict (Binary.runPut (putWord8 word8))-  BinaryBits.putByteString (reverseBytes bytes)
+ src/lib/Rattletrap/Get.hs view
@@ -0,0 +1,48 @@+module Rattletrap.Get where++import qualified Control.Applicative as Applicative++newtype Get s m a = Get (s -> m (Either String (s, a)))++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+  pure x = Get $ \s -> pure $ Right (s, x)++  gf <*> gx = Get $ \s1 -> do+    r <- run gf s1+    case r of+      Left e -> pure $ Left e+      Right (s2, f) -> run (fmap f gx) s2++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+  fail = Get . const . pure . Left++instance Monad m => Applicative.Alternative (Get s m) where+  empty = fail "empty"++  gx <|> gy = Get $ \s -> do+    r <- run gx s+    case r of+      Left _ -> run gy s+      Right x -> pure $ Right x++run :: Get s m a -> s -> m (Either String (s, a))+run (Get f) = f++get :: Applicative m => Get s m s+get = Get $ \s -> pure $ Right (s, s)++put :: Applicative m => s -> Get s m ()+put s = Get $ \_ -> pure $ Right (s, ())++lift :: Functor m => m a -> Get s m a+lift m = Get $ \s -> fmap (\x -> Right (s, x)) m
+ src/lib/Rattletrap/Schema.hs view
@@ -0,0 +1,61 @@+module Rattletrap.Schema where++import qualified Data.Text as Text+import qualified Rattletrap.Utility.Json as Json++data Schema = Schema+  { name :: Text.Text+  , json :: Json.Value+  }+  deriving (Eq, Show)++named :: String -> Json.Value -> Schema+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 :: [((Text.Text, Json.Value), Bool)] -> Json.Value+object xs = Json.object+  [ Json.pair "type" "object"+  , Json.pair "properties" . Json.object $ fmap 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]+  }++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+  ]++array :: Schema -> Schema+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"]++integer :: Schema+integer = named "integer" $ Json.object [Json.pair "type" "integer"]++null :: Schema+null = named "null" $ Json.object [Json.pair "type" "null"]++number :: Schema+number = named "number" $ Json.object [Json.pair "type" "number"]++string :: Schema+string = named "string" $ Json.object [Json.pair "type" "string"]
− src/lib/Rattletrap/Type/AppliedDamageAttribute.hs
@@ -1,20 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.AppliedDamageAttribute-  ( AppliedDamageAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Int32le-import Rattletrap.Type.Vector-import Rattletrap.Type.Word8le--data AppliedDamageAttribute = AppliedDamageAttribute-  { appliedDamageAttributeUnknown1 :: Word8le-  , appliedDamageAttributeLocation :: Vector-  , appliedDamageAttributeUnknown3 :: Int32le-  , appliedDamageAttributeUnknown4 :: Int32le-  } deriving (Eq, Ord, Show)--$(deriveJson ''AppliedDamageAttribute)
src/lib/Rattletrap/Type/Attribute.hs view
@@ -1,21 +1,95 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.Attribute-  ( Attribute(..)-  )-where+module Rattletrap.Type.Attribute where -import Rattletrap.Type.AttributeValue-import Rattletrap.Type.Common-import Rattletrap.Type.CompressedWord-import Rattletrap.Type.Str+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.Schema as Schema+import qualified Rattletrap.Type.AttributeValue as AttributeValue+import qualified Rattletrap.Type.ClassAttributeMap as ClassAttributeMap+import qualified Rattletrap.Type.CompressedWord as CompressedWord+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  data Attribute = Attribute-  { attributeId :: CompressedWord-  , attributeName :: Str+  { id :: CompressedWord.CompressedWord+  , name :: Str.Str   -- ^ Read-only! Changing an attribute's name requires editing the class   -- attribute map.-  , attributeValue :: AttributeValue-  } deriving (Eq, Ord, Show)+  , value :: AttributeValue.AttributeValue+  }+  deriving (Eq, Show) -$(deriveJson ''Attribute)+instance Json.FromJSON Attribute where+  parseJSON = Json.withObject "Attribute" $ \object -> do+    id <- Json.required object "id"+    name <- Json.required object "name"+    value <- Json.required object "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+    ]++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)+  ]++bitPut :: Attribute -> BitPut.BitPut+bitPut attribute =+  CompressedWord.bitPut (Rattletrap.Type.Attribute.id attribute)+    <> AttributeValue.bitPut (value attribute)++bitGet+  :: Version.Version+  -> ClassAttributeMap.ClassAttributeMap+  -> Map.Map CompressedWord.CompressedWord U32.U32+  -> CompressedWord.CompressedWord+  -> BitGet.BitGet Attribute+bitGet version classes actors actor = do+  attributes <- lookupAttributeMap classes actors actor+  limit <- lookupAttributeIdLimit attributes actor+  attribute <- CompressedWord.bitGet limit+  name_ <- lookupAttributeName classes attributes attribute+  Attribute attribute name_+    <$> AttributeValue.bitGet+          version+          (ClassAttributeMap.objectMap classes)+          name_++lookupAttributeMap+  :: ClassAttributeMap.ClassAttributeMap+  -> Map.Map CompressedWord.CompressedWord U32.U32+  -> CompressedWord.CompressedWord+  -> BitGet.BitGet (Map.Map U32.U32 U32.U32)+lookupAttributeMap classes actors actor = fromMaybe+  ("[RT01] could not get attribute map for " <> show actor)+  (ClassAttributeMap.getAttributeMap classes actors actor)++lookupAttributeIdLimit+  :: Map.Map U32.U32 U32.U32+  -> CompressedWord.CompressedWord+  -> BitGet.BitGet Word+lookupAttributeIdLimit attributes actor = fromMaybe+  ("[RT02] could not get attribute ID limit for " <> show actor)+  (ClassAttributeMap.getAttributeIdLimit attributes)++lookupAttributeName+  :: ClassAttributeMap.ClassAttributeMap+  -> Map.Map U32.U32 U32.U32+  -> CompressedWord.CompressedWord+  -> BitGet.BitGet Str.Str+lookupAttributeName classes attributes attribute = fromMaybe+  ("[RT03] could not get attribute name for " <> show attribute)+  (ClassAttributeMap.getAttributeName classes attributes attribute)++fromMaybe :: String -> Maybe a -> BitGet.BitGet a+fromMaybe message = maybe (fail message) pure
+ src/lib/Rattletrap/Type/Attribute/AppliedDamage.hs view
@@ -0,0 +1,57 @@+module Rattletrap.Type.Attribute.AppliedDamage where++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.Type.U8 as U8+import qualified Rattletrap.Type.Vector as Vector+import qualified Rattletrap.Type.Version as Version+import qualified Rattletrap.Utility.Json as Json++data AppliedDamage = AppliedDamage+  { unknown1 :: U8.U8+  , location :: Vector.Vector+  , unknown3 :: I32.I32+  , unknown4 :: I32.I32+  }+  deriving (Eq, Show)++instance Json.FromJSON AppliedDamage where+  parseJSON = Json.withObject "AppliedDamage" $ \object -> do+    unknown1 <- Json.required object "unknown1"+    location <- Json.required object "location"+    unknown3 <- Json.required object "unknown3"+    unknown4 <- Json.required object "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+    ]++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)+  ]++bitPut :: AppliedDamage -> BitPut.BitPut+bitPut appliedDamageAttribute =+  U8.bitPut (unknown1 appliedDamageAttribute)+    <> Vector.bitPut (location appliedDamageAttribute)+    <> I32.bitPut (unknown3 appliedDamageAttribute)+    <> I32.bitPut (unknown4 appliedDamageAttribute)++bitGet :: Version.Version -> BitGet.BitGet AppliedDamage+bitGet version =+  AppliedDamage+    <$> U8.bitGet+    <*> Vector.bitGet version+    <*> I32.bitGet+    <*> I32.bitGet
+ src/lib/Rattletrap/Type/Attribute/Boolean.hs view
@@ -0,0 +1,25 @@+module Rattletrap.Type.Attribute.Boolean where++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++newtype Boolean = Boolean+  { value :: Bool+  } deriving (Eq, Show)++instance Json.FromJSON Boolean where+  parseJSON = fmap Boolean . Json.parseJSON++instance Json.ToJSON Boolean where+  toJSON = Json.toJSON . value++schema :: Schema.Schema+schema = Schema.named "attribute-boolean" $ Schema.ref Schema.boolean++bitPut :: Boolean -> BitPut.BitPut+bitPut booleanAttribute = BitPut.bool (value booleanAttribute)++bitGet :: BitGet.BitGet Boolean+bitGet = Boolean <$> BitGet.bool
+ src/lib/Rattletrap/Type/Attribute/Byte.hs view
@@ -0,0 +1,26 @@+module Rattletrap.Type.Attribute.Byte 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++newtype Byte = Byte+  { value :: U8.U8+  } deriving (Eq, Show)++instance Json.FromJSON Byte where+  parseJSON = fmap Byte . Json.parseJSON++instance Json.ToJSON Byte where+  toJSON = Json.toJSON . value++schema :: Schema.Schema+schema = Schema.named "attribute-byte" $ Schema.ref U8.schema++bitPut :: Byte -> BitPut.BitPut+bitPut byteAttribute = U8.bitPut (value byteAttribute)++bitGet :: BitGet.BitGet Byte+bitGet = Byte <$> U8.bitGet
+ src/lib/Rattletrap/Type/Attribute/CamSettings.hs view
@@ -0,0 +1,88 @@+module Rattletrap.Type.Attribute.CamSettings where++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.Type.Version as Version+import qualified Rattletrap.Utility.Json as Json+import Rattletrap.Utility.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+  }+  deriving (Eq, Show)++instance Json.FromJSON CamSettings where+  parseJSON = Json.withObject "CamSettings" $ \object -> do+    fov <- Json.required object "fov"+    height <- Json.required object "height"+    angle <- Json.required object "angle"+    distance <- Json.required object "distance"+    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+      }++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+    ]++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+    )+  ]++bitPut :: CamSettings -> BitPut.BitPut+bitPut camSettingsAttribute =+  F32.bitPut (fov camSettingsAttribute)+    <> F32.bitPut (height camSettingsAttribute)+    <> F32.bitPut (angle camSettingsAttribute)+    <> F32.bitPut (distance camSettingsAttribute)+    <> F32.bitPut (stiffness camSettingsAttribute)+    <> F32.bitPut (swivelSpeed camSettingsAttribute)+    <> foldMap F32.bitPut (transitionSpeed camSettingsAttribute)++bitGet :: Version.Version -> BitGet.BitGet CamSettings+bitGet version =+  CamSettings+    <$> F32.bitGet+    <*> F32.bitGet+    <*> F32.bitGet+    <*> F32.bitGet+    <*> F32.bitGet+    <*> F32.bitGet+    <*> whenMaybe (hasTransitionSpeed version) F32.bitGet++hasTransitionSpeed :: Version.Version -> Bool+hasTransitionSpeed v =+  Version.major v >= 868 && Version.minor v >= 20 && Version.patch v >= 0
+ src/lib/Rattletrap/Type/Attribute/ClubColors.hs view
@@ -0,0 +1,50 @@+module Rattletrap.Type.Attribute.ClubColors 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 ClubColors = ClubColors+  { blueFlag :: Bool+  , blueColor :: U8.U8+  , orangeFlag :: Bool+  , orangeColor :: U8.U8+  }+  deriving (Eq, Show)++instance Json.FromJSON ClubColors where+  parseJSON = Json.withObject "ClubColors" $ \object -> do+    blueFlag <- Json.required object "blue_flag"+    blueColor <- Json.required object "blue_color"+    orangeFlag <- Json.required object "orange_flag"+    orangeColor <- Json.required object "orange_color"+    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+    ]++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)+  ]++bitPut :: ClubColors -> BitPut.BitPut+bitPut clubColorsAttribute =+  BitPut.bool (blueFlag clubColorsAttribute)+    <> U8.bitPut (blueColor clubColorsAttribute)+    <> BitPut.bool (orangeFlag clubColorsAttribute)+    <> U8.bitPut (orangeColor clubColorsAttribute)++bitGet :: BitGet.BitGet ClubColors+bitGet =+  ClubColors <$> BitGet.bool <*> U8.bitGet <*> BitGet.bool <*> U8.bitGet
+ src/lib/Rattletrap/Type/Attribute/CustomDemolish.hs view
@@ -0,0 +1,48 @@+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+import qualified Rattletrap.Type.Attribute.Demolish as Demolish+import qualified Rattletrap.Type.I32 as I32+import qualified Rattletrap.Type.Version as Version+import qualified Rattletrap.Utility.Json as Json++data CustomDemolish = CustomDemolish+  { flag :: Bool+  , id :: I32.I32+  , demolish :: Demolish.Demolish+  }+  deriving (Eq, Show)++instance Json.FromJSON CustomDemolish where+  parseJSON = Json.withObject "CustomDemolish" $ \object -> do+    flag <- Json.required object "flag"+    id <- Json.required object "id"+    demolish <- Json.required object "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+    ]++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)+  ]++bitPut :: CustomDemolish -> BitPut.BitPut+bitPut x =+  BitPut.bool (flag x)+    <> I32.bitPut (Rattletrap.Type.Attribute.CustomDemolish.id x)+    <> Demolish.bitPut (demolish x)++bitGet :: Version.Version -> BitGet.BitGet CustomDemolish+bitGet version =+  CustomDemolish <$> BitGet.bool <*> I32.bitGet <*> Demolish.bitGet version
+ src/lib/Rattletrap/Type/Attribute/DamageState.hs view
@@ -0,0 +1,76 @@+module Rattletrap.Type.Attribute.DamageState where++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.Type.U8 as U8+import qualified Rattletrap.Type.Vector as Vector+import qualified Rattletrap.Type.Version as Version+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+  }+  deriving (Eq, Show)++instance Json.FromJSON DamageState where+  parseJSON = Json.withObject "DamageState" $ \object -> do+    unknown1 <- Json.required object "unknown1"+    unknown2 <- Json.required object "unknown2"+    unknown3 <- Json.required object "unknown3"+    unknown4 <- Json.required object "unknown4"+    unknown5 <- Json.required object "unknown5"+    unknown6 <- Json.required object "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+    ]++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)+  ]++bitPut :: DamageState -> BitPut.BitPut+bitPut damageStateAttribute =+  U8.bitPut (unknown1 damageStateAttribute)+    <> BitPut.bool (unknown2 damageStateAttribute)+    <> I32.bitPut (unknown3 damageStateAttribute)+    <> Vector.bitPut (unknown4 damageStateAttribute)+    <> BitPut.bool (unknown5 damageStateAttribute)+    <> BitPut.bool (unknown6 damageStateAttribute)++bitGet :: Version.Version -> BitGet.BitGet DamageState+bitGet version =+  DamageState+    <$> U8.bitGet+    <*> BitGet.bool+    <*> I32.bitGet+    <*> Vector.bitGet version+    <*> BitGet.bool+    <*> BitGet.bool
+ src/lib/Rattletrap/Type/Attribute/Demolish.hs view
@@ -0,0 +1,75 @@+module Rattletrap.Type.Attribute.Demolish where++import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.U32 as U32+import qualified Rattletrap.Type.Vector as Vector+import qualified Rattletrap.Type.Version as Version+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+  }+  deriving (Eq, Show)++instance Json.FromJSON Demolish where+  parseJSON = Json.withObject "Demolish" $ \object -> do+    attackerFlag <- Json.required object "attacker_flag"+    attackerActorId <- Json.required object "attacker_actor_id"+    victimFlag <- Json.required object "victim_flag"+    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+      }++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+    ]++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)+  ]++bitPut :: Demolish -> BitPut.BitPut+bitPut demolishAttribute =+  BitPut.bool (attackerFlag demolishAttribute)+    <> U32.bitPut (attackerActorId demolishAttribute)+    <> BitPut.bool (victimFlag demolishAttribute)+    <> U32.bitPut (victimActorId demolishAttribute)+    <> Vector.bitPut (attackerVelocity demolishAttribute)+    <> Vector.bitPut (victimVelocity demolishAttribute)++bitGet :: Version.Version -> BitGet.BitGet Demolish+bitGet version =+  Demolish+    <$> BitGet.bool+    <*> U32.bitGet+    <*> BitGet.bool+    <*> U32.bitGet+    <*> Vector.bitGet version+    <*> Vector.bitGet version
+ src/lib/Rattletrap/Type/Attribute/Enum.hs view
@@ -0,0 +1,27 @@+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++newtype Enum = Enum+  { value :: Word.Word16+  } deriving (Eq, Show)++instance Json.FromJSON Enum where+  parseJSON = fmap Enum . Json.parseJSON++instance Json.ToJSON Enum where+  toJSON = Json.toJSON . value++schema :: Schema.Schema+schema = Schema.named "attribute-enum" $ Schema.ref Schema.integer++bitPut :: Enum -> BitPut.BitPut+bitPut enumAttribute = BitPut.bits 11 (value enumAttribute)++bitGet :: BitGet.BitGet Enum+bitGet = Enum <$> BitGet.bits 11
+ src/lib/Rattletrap/Type/Attribute/Explosion.hs view
@@ -0,0 +1,47 @@+module Rattletrap.Type.Attribute.Explosion where++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.Type.Vector as Vector+import qualified Rattletrap.Type.Version as Version+import qualified Rattletrap.Utility.Json as Json++data Explosion = Explosion+  { flag :: Bool+  , actorId :: I32.I32+  , location :: Vector.Vector+  }+  deriving (Eq, Show)++instance Json.FromJSON Explosion where+  parseJSON = Json.withObject "Explosion" $ \object -> do+    flag <- Json.required object "flag"+    actorId <- Json.required object "actor_id"+    location <- Json.required object "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+    ]++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)+  ]++bitPut :: Explosion -> BitPut.BitPut+bitPut explosionAttribute =+  BitPut.bool (flag explosionAttribute)+    <> I32.bitPut (actorId explosionAttribute)+    <> Vector.bitPut (location explosionAttribute)++bitGet :: Version.Version -> BitGet.BitGet Explosion+bitGet version =+  Explosion <$> BitGet.bool <*> I32.bitGet <*> Vector.bitGet version
+ src/lib/Rattletrap/Type/Attribute/ExtendedExplosion.hs view
@@ -0,0 +1,38 @@+module Rattletrap.Type.Attribute.ExtendedExplosion where++import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.Attribute.Explosion as Explosion+import qualified Rattletrap.Type.Attribute.FlaggedInt as FlaggedInt+import qualified Rattletrap.Type.Version as Version+import qualified Rattletrap.Utility.Json as Json++data ExtendedExplosion = ExtendedExplosion+  { explosion :: Explosion.Explosion+  , unknown :: FlaggedInt.FlaggedInt+  }+  deriving (Eq, Show)++instance Json.FromJSON ExtendedExplosion where+  parseJSON = Json.withObject "ExtendedExplosion" $ \object -> do+    explosion <- Json.required object "explosion"+    unknown <- Json.required object "unknown"+    pure ExtendedExplosion { explosion, unknown }++instance Json.ToJSON ExtendedExplosion where+  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)+  ]++bitPut :: ExtendedExplosion -> BitPut.BitPut+bitPut x = Explosion.bitPut (explosion x) <> FlaggedInt.bitPut (unknown x)++bitGet :: Version.Version -> BitGet.BitGet ExtendedExplosion+bitGet version =+  ExtendedExplosion <$> Explosion.bitGet version <*> FlaggedInt.bitGet
+ src/lib/Rattletrap/Type/Attribute/FlaggedByte.hs view
@@ -0,0 +1,36 @@+module Rattletrap.Type.Attribute.FlaggedByte 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 FlaggedByte = FlaggedByte+  { flag :: Bool+  , byte :: U8.U8+  }+  deriving (Eq, Show)++instance Json.FromJSON FlaggedByte where+  parseJSON = Json.withObject "FlaggedByte" $ \object -> do+    flag <- Json.required object "flag"+    byte <- Json.required object "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)+  ]++bitPut :: FlaggedByte -> BitPut.BitPut+bitPut flaggedByteAttribute = BitPut.bool (flag flaggedByteAttribute)+  <> U8.bitPut (byte flaggedByteAttribute)++bitGet :: BitGet.BitGet FlaggedByte+bitGet = FlaggedByte <$> BitGet.bool <*> U8.bitGet
+ src/lib/Rattletrap/Type/Attribute/FlaggedInt.hs view
@@ -0,0 +1,35 @@+module Rattletrap.Type.Attribute.FlaggedInt where++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++data FlaggedInt = FlaggedInt+  { flag :: Bool+  , int :: I32.I32+  }+  deriving (Eq, Show)++instance Json.FromJSON FlaggedInt where+  parseJSON = Json.withObject "FlaggedInt" $ \object -> do+    flag <- Json.required object "flag"+    int <- Json.required object "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)+  ]++bitPut :: FlaggedInt -> BitPut.BitPut+bitPut flaggedIntAttribute = BitPut.bool (flag flaggedIntAttribute)+  <> I32.bitPut (int flaggedIntAttribute)++bitGet :: BitGet.BitGet FlaggedInt+bitGet = FlaggedInt <$> BitGet.bool <*> I32.bitGet
+ src/lib/Rattletrap/Type/Attribute/Float.hs view
@@ -0,0 +1,27 @@+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++newtype Float = Float+  { value :: F32.F32+  } deriving (Eq, Show)++instance Json.FromJSON Float where+  parseJSON = fmap Float . Json.parseJSON++instance Json.ToJSON Float where+  toJSON = Json.toJSON . value++schema :: Schema.Schema+schema = Schema.named "attribute-float" $ Schema.ref F32.schema++bitPut :: Float -> BitPut.BitPut+bitPut floatAttribute = F32.bitPut (value floatAttribute)++bitGet :: BitGet.BitGet Float+bitGet = Float <$> F32.bitGet
+ src/lib/Rattletrap/Type/Attribute/GameMode.hs view
@@ -0,0 +1,49 @@+module Rattletrap.Type.Attribute.GameMode where++import qualified Data.Word as Word+import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.Version as Version+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+  }+  deriving (Eq, Show)++instance Json.FromJSON GameMode where+  parseJSON = Json.withObject "GameMode" $ \object -> do+    numBits <- Json.required object "num_bits"+    word <- Json.required object "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)+  ]++bitPut :: GameMode -> BitPut.BitPut+bitPut gameModeAttribute = do+  BitPut.word8 (numBits gameModeAttribute) (word gameModeAttribute)++bitGet :: Version.Version -> BitGet.BitGet GameMode+bitGet version =+  GameMode (numBits_ version) <$> BitGet.word8 (numBits_ version)++numBits_ :: Version.Version -> Int+numBits_ version = if has8Bits version then 8 else 2++has8Bits :: Version.Version -> Bool+has8Bits v =+  Version.major v >= 868 && Version.minor v >= 12 && Version.patch v >= 0
+ src/lib/Rattletrap/Type/Attribute/Int.hs view
@@ -0,0 +1,27 @@+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++newtype Int = Int+  { value :: I32.I32+  } deriving (Eq, Show)++instance Json.FromJSON Int where+  parseJSON = fmap Int . Json.parseJSON++instance Json.ToJSON Int where+  toJSON = Json.toJSON . value++schema :: Schema.Schema+schema = Schema.named "attribute-int" $ Schema.ref I32.schema++bitPut :: Int -> BitPut.BitPut+bitPut intAttribute = I32.bitPut (value intAttribute)++bitGet :: BitGet.BitGet Int+bitGet = Int <$> I32.bitGet
+ src/lib/Rattletrap/Type/Attribute/Int64.hs view
@@ -0,0 +1,26 @@+module Rattletrap.Type.Attribute.Int64 where++import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.I64 as I64+import qualified Rattletrap.Utility.Json as Json++newtype Int64 = Int64+  { value :: I64.I64+  } deriving (Eq, Show)++instance Json.FromJSON Int64 where+  parseJSON = fmap Int64 . Json.parseJSON++instance Json.ToJSON Int64 where+  toJSON = Json.toJSON . value++schema :: Schema.Schema+schema = Schema.named "attribute-int64" $ Schema.ref I64.schema++putInt64Attribute :: Int64 -> BitPut.BitPut+putInt64Attribute int64Attribute = I64.bitPut (value int64Attribute)++bitGet :: BitGet.BitGet Int64+bitGet = Int64 <$> I64.bitGet
+ src/lib/Rattletrap/Type/Attribute/Loadout.hs view
@@ -0,0 +1,153 @@+module Rattletrap.Type.Attribute.Loadout where++import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.U32 as U32+import qualified Rattletrap.Type.U8 as U8+import qualified Rattletrap.Utility.Json as Json+import Rattletrap.Utility.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+  }+  deriving (Eq, Show)++instance Json.FromJSON Loadout where+  parseJSON = Json.withObject "Loadout" $ \object -> do+    version <- Json.required object "version"+    body <- Json.required object "body"+    decal <- Json.required object "decal"+    wheels <- Json.required object "wheels"+    rocketTrail <- Json.required object "rocket_trail"+    antenna <- Json.required object "antenna"+    topper <- Json.required object "topper"+    unknown1 <- Json.required object "unknown1"+    unknown2 <- Json.optional object "unknown2"+    engineAudio <- Json.optional object "engine_audio"+    trail <- Json.optional object "trail"+    goalExplosion <- Json.optional object "goal_explosion"+    banner <- Json.optional object "banner"+    unknown3 <- Json.optional object "unknown3"+    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+      }++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+    ]++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)+  ]++bitPut :: Loadout -> BitPut.BitPut+bitPut loadoutAttribute =+  U8.bitPut (version loadoutAttribute)+    <> U32.bitPut (body loadoutAttribute)+    <> U32.bitPut (decal loadoutAttribute)+    <> U32.bitPut (wheels loadoutAttribute)+    <> U32.bitPut (rocketTrail loadoutAttribute)+    <> U32.bitPut (antenna loadoutAttribute)+    <> U32.bitPut (topper loadoutAttribute)+    <> U32.bitPut (unknown1 loadoutAttribute)+    <> foldMap U32.bitPut (unknown2 loadoutAttribute)+    <> foldMap U32.bitPut (engineAudio loadoutAttribute)+    <> foldMap U32.bitPut (trail loadoutAttribute)+    <> foldMap U32.bitPut (goalExplosion loadoutAttribute)+    <> foldMap U32.bitPut (banner loadoutAttribute)+    <> foldMap U32.bitPut (unknown3 loadoutAttribute)+    <> foldMap U32.bitPut (unknown4 loadoutAttribute)+    <> foldMap U32.bitPut (unknown5 loadoutAttribute)+    <> foldMap U32.bitPut (unknown6 loadoutAttribute)++bitGet :: BitGet.BitGet Loadout+bitGet = do+  version_ <- U8.bitGet+  Loadout version_+    <$> U32.bitGet+    <*> U32.bitGet+    <*> U32.bitGet+    <*> U32.bitGet+    <*> U32.bitGet+    <*> U32.bitGet+    <*> U32.bitGet+    <*> whenMaybe (U8.toWord8 version_ >= 11) U32.bitGet+    <*> whenMaybe (U8.toWord8 version_ >= 16) U32.bitGet+    <*> whenMaybe (U8.toWord8 version_ >= 16) U32.bitGet+    <*> whenMaybe (U8.toWord8 version_ >= 16) U32.bitGet+    <*> whenMaybe (U8.toWord8 version_ >= 17) U32.bitGet+    <*> whenMaybe (U8.toWord8 version_ >= 19) U32.bitGet+    <*> whenMaybe (U8.toWord8 version_ >= 22) U32.bitGet+    <*> whenMaybe (U8.toWord8 version_ >= 22) U32.bitGet+    <*> whenMaybe (U8.toWord8 version_ >= 22) U32.bitGet
+ src/lib/Rattletrap/Type/Attribute/LoadoutOnline.hs view
@@ -0,0 +1,46 @@+module Rattletrap.Type.Attribute.LoadoutOnline where++import qualified Rattletrap.BitGet as BitGet+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.Str as Str+import qualified Rattletrap.Type.U32 as U32+import qualified Rattletrap.Type.U8 as U8+import qualified Rattletrap.Type.Version as Version+import qualified Rattletrap.Utility.Json as Json++import qualified Data.Map as Map++newtype LoadoutOnline = LoadoutOnline+  { value :: List.List (List.List Product.Product)+  } deriving (Eq, Show)++instance Json.FromJSON LoadoutOnline where+  parseJSON = fmap LoadoutOnline . Json.parseJSON++instance Json.ToJSON LoadoutOnline where+  toJSON = Json.toJSON . value++schema :: Schema.Schema+schema =+  Schema.named "attribute-loadout-online"+    . Schema.json+    . List.schema+    $ List.schema Product.schema++bitPut :: LoadoutOnline -> BitPut.BitPut+bitPut loadoutAttribute =+  let attributes = List.toList $ value loadoutAttribute+  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 objectMap = do+  size <- U8.bitGet+  LoadoutOnline <$> List.replicateM+    (fromIntegral (U8.toWord8 size))+    (Product.decodeProductAttributesBits version objectMap)
+ src/lib/Rattletrap/Type/Attribute/Loadouts.hs view
@@ -0,0 +1,36 @@+module Rattletrap.Type.Attribute.Loadouts where++import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.Attribute.Loadout as Loadout+import qualified Rattletrap.Utility.Json as Json++data Loadouts = Loadouts+  { blue :: Loadout.Loadout+  , orange :: Loadout.Loadout+  }+  deriving (Eq, Show)++instance Json.FromJSON Loadouts where+  parseJSON = Json.withObject "Loadouts" $ \object -> do+    blue <- Json.required object "blue"+    orange <- Json.required object "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)+  ]++bitPut :: Loadouts -> BitPut.BitPut+bitPut loadoutsAttribute = Loadout.bitPut (blue loadoutsAttribute)+  <> Loadout.bitPut (orange loadoutsAttribute)++bitGet :: BitGet.BitGet Loadouts+bitGet = Loadouts <$> Loadout.bitGet <*> Loadout.bitGet
+ src/lib/Rattletrap/Type/Attribute/LoadoutsOnline.hs view
@@ -0,0 +1,60 @@+module Rattletrap.Type.Attribute.LoadoutsOnline where++import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.Attribute.LoadoutOnline as LoadoutOnline+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++import qualified Data.Map as Map++data LoadoutsOnline = LoadoutsOnline+  { blue :: LoadoutOnline.LoadoutOnline+  , orange :: LoadoutOnline.LoadoutOnline+  , unknown1 :: Bool+  , unknown2 :: Bool+  }+  deriving (Eq, Show)++instance Json.FromJSON LoadoutsOnline where+  parseJSON = Json.withObject "LoadoutsOnline" $ \object -> do+    blue <- Json.required object "blue"+    orange <- Json.required object "orange"+    unknown1 <- Json.required object "unknown1"+    unknown2 <- Json.required object "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+    ]++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)+  ]++bitPut :: LoadoutsOnline -> BitPut.BitPut+bitPut loadoutsOnlineAttribute =+  LoadoutOnline.bitPut (blue loadoutsOnlineAttribute)+    <> LoadoutOnline.bitPut (orange loadoutsOnlineAttribute)+    <> BitPut.bool (unknown1 loadoutsOnlineAttribute)+    <> BitPut.bool (unknown2 loadoutsOnlineAttribute)++bitGet+  :: Version.Version -> Map.Map U32.U32 Str.Str -> BitGet.BitGet LoadoutsOnline+bitGet version objectMap =+  LoadoutsOnline+    <$> LoadoutOnline.bitGet version objectMap+    <*> LoadoutOnline.bitGet version objectMap+    <*> BitGet.bool+    <*> BitGet.bool
+ src/lib/Rattletrap/Type/Attribute/Location.hs view
@@ -0,0 +1,27 @@+module Rattletrap.Type.Attribute.Location where++import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.Vector as Vector+import qualified Rattletrap.Type.Version as Version+import qualified Rattletrap.Utility.Json as Json++newtype Location = Location+  { value :: Vector.Vector+  } deriving (Eq, Show)++instance Json.FromJSON Location where+  parseJSON = fmap Location . Json.parseJSON++instance Json.ToJSON Location where+  toJSON = Json.toJSON . value++schema :: Schema.Schema+schema = Schema.named "attribute-location" $ Schema.ref Vector.schema++bitPut :: Location -> BitPut.BitPut+bitPut locationAttribute = Vector.bitPut (value locationAttribute)++bitGet :: Version.Version -> BitGet.BitGet Location+bitGet version = Location <$> Vector.bitGet version
+ src/lib/Rattletrap/Type/Attribute/MusicStinger.hs view
@@ -0,0 +1,45 @@+module Rattletrap.Type.Attribute.MusicStinger where++import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.U32 as U32+import qualified Rattletrap.Type.U8 as U8+import qualified Rattletrap.Utility.Json as Json++data MusicStinger = MusicStinger+  { flag :: Bool+  , cue :: U32.U32+  , trigger :: U8.U8+  }+  deriving (Eq, Show)++instance Json.FromJSON MusicStinger where+  parseJSON = Json.withObject "MusicStinger" $ \object -> do+    flag <- Json.required object "flag"+    cue <- Json.required object "cue"+    trigger <- Json.required object "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+    ]++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)+  ]++bitPut :: MusicStinger -> BitPut.BitPut+bitPut musicStingerAttribute =+  BitPut.bool (flag musicStingerAttribute)+    <> U32.bitPut (cue musicStingerAttribute)+    <> U8.bitPut (trigger musicStingerAttribute)++bitGet :: BitGet.BitGet MusicStinger+bitGet = MusicStinger <$> BitGet.bool <*> U32.bitGet <*> U8.bitGet
+ src/lib/Rattletrap/Type/Attribute/PartyLeader.hs view
@@ -0,0 +1,50 @@+module Rattletrap.Type.Attribute.PartyLeader where++import Prelude hiding (id)+import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.RemoteId as RemoteId+import qualified Rattletrap.Type.U8 as U8+import qualified Rattletrap.Type.Version as Version+import qualified Rattletrap.Utility.Json as Json+import Rattletrap.Utility.Monad++data PartyLeader = PartyLeader+  { systemId :: U8.U8+  , id :: Maybe (RemoteId.RemoteId, U8.U8)+  }+  deriving (Eq, Show)++instance Json.FromJSON PartyLeader where+  parseJSON = Json.withObject "PartyLeader" $ \object -> do+    systemId <- Json.required object "system_id"+    id <- Json.optional object "id"+    pure PartyLeader { systemId, id }++instance Json.ToJSON PartyLeader where+  toJSON x =+    Json.object [Json.pair "system_id" $ systemId x, Json.pair "id" $ id x]++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+      ]+    , False+    )+  ]++bitPut :: PartyLeader -> BitPut.BitPut+bitPut x = U8.bitPut (systemId x) <> foldMap+  (\(y, z) -> RemoteId.bitPut y <> U8.bitPut z)+  (Rattletrap.Type.Attribute.PartyLeader.id x)++bitGet :: Version.Version -> BitGet.BitGet PartyLeader+bitGet version = do+  systemId_ <- U8.bitGet+  PartyLeader systemId_ <$> whenMaybe+    (systemId_ /= U8.fromWord8 0)+    ((,) <$> RemoteId.bitGet version systemId_ <*> U8.bitGet)
+ src/lib/Rattletrap/Type/Attribute/Pickup.hs view
@@ -0,0 +1,45 @@+module Rattletrap.Type.Attribute.Pickup where++import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.U32 as U32+import qualified Rattletrap.Utility.Json as Json+import Rattletrap.Utility.Monad++data Pickup = Pickup+  { instigatorId :: Maybe U32.U32+  , pickedUp :: Bool+  }+  deriving (Eq, Show)++instance Json.FromJSON Pickup where+  parseJSON = Json.withObject "Pickup" $ \object -> do+    instigatorId <- Json.optional object "instigator_id"+    pickedUp <- Json.required object "picked_up"+    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+    ]++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)+  ]++bitPut :: Pickup -> BitPut.BitPut+bitPut x =+  maybe+      (BitPut.bool False)+      (\y -> BitPut.bool True <> U32.bitPut y)+      (instigatorId x)+    <> BitPut.bool (pickedUp x)++bitGet :: BitGet.BitGet Pickup+bitGet = do+  instigator <- BitGet.bool+  Pickup <$> whenMaybe instigator U32.bitGet <*> BitGet.bool
+ src/lib/Rattletrap/Type/Attribute/PickupNew.hs view
@@ -0,0 +1,46 @@+module Rattletrap.Type.Attribute.PickupNew where++import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.U32 as U32+import qualified Rattletrap.Type.U8 as U8+import qualified Rattletrap.Utility.Json as Json+import Rattletrap.Utility.Monad++data PickupNew = PickupNew+  { instigatorId :: Maybe U32.U32+  , pickedUp :: U8.U8+  }+  deriving (Eq, Show)++instance Json.FromJSON PickupNew where+  parseJSON = Json.withObject "PickupNew" $ \object -> do+    instigatorId <- Json.optional object "instigator_id"+    pickedUp <- Json.required object "picked_up"+    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+    ]++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)+  ]++bitPut :: PickupNew -> BitPut.BitPut+bitPut x =+  maybe+      (BitPut.bool False)+      (\y -> BitPut.bool True <> U32.bitPut y)+      (instigatorId x)+    <> U8.bitPut (pickedUp x)++bitGet :: BitGet.BitGet PickupNew+bitGet = do+  instigator <- BitGet.bool+  PickupNew <$> whenMaybe instigator U32.bitGet <*> U8.bitGet
+ src/lib/Rattletrap/Type/Attribute/PlayerHistoryKey.hs view
@@ -0,0 +1,27 @@+module Rattletrap.Type.Attribute.PlayerHistoryKey where++import qualified Data.Word as Word+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++newtype PlayerHistoryKey = PlayerHistoryKey+  { unknown :: Word.Word16+  } deriving (Eq, Show)++instance Json.FromJSON PlayerHistoryKey where+  parseJSON = fmap PlayerHistoryKey . Json.parseJSON++instance Json.ToJSON PlayerHistoryKey where+  toJSON = Json.toJSON . unknown++schema :: Schema.Schema+schema =+  Schema.named "attribute-player-history-key" $ Schema.ref Schema.number++bitPut :: PlayerHistoryKey -> BitPut.BitPut+bitPut = BitPut.bits 14 . unknown++bitGet :: BitGet.BitGet PlayerHistoryKey+bitGet = PlayerHistoryKey <$> BitGet.bits 14
+ src/lib/Rattletrap/Type/Attribute/PrivateMatchSettings.hs view
@@ -0,0 +1,74 @@+module Rattletrap.Type.Attribute.PrivateMatchSettings where++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.Type.U32 as U32+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+  }+  deriving (Eq, Show)++instance Json.FromJSON PrivateMatchSettings where+  parseJSON = Json.withObject "PrivateMatchSettings" $ \object -> do+    mutators <- Json.required object "mutators"+    joinableBy <- Json.required object "joinable_by"+    maxPlayers <- Json.required object "max_players"+    gameName <- Json.required object "game_name"+    password <- Json.required object "password"+    flag <- Json.required object "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+    ]++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)+  ]++bitPut :: PrivateMatchSettings -> BitPut.BitPut+bitPut privateMatchSettingsAttribute =+  Str.bitPut (mutators privateMatchSettingsAttribute)+    <> U32.bitPut (joinableBy privateMatchSettingsAttribute)+    <> U32.bitPut (maxPlayers privateMatchSettingsAttribute)+    <> Str.bitPut (gameName privateMatchSettingsAttribute)+    <> Str.bitPut (password privateMatchSettingsAttribute)+    <> BitPut.bool (flag privateMatchSettingsAttribute)++bitGet :: BitGet.BitGet PrivateMatchSettings+bitGet =+  PrivateMatchSettings+    <$> Str.bitGet+    <*> U32.bitGet+    <*> U32.bitGet+    <*> Str.bitGet+    <*> Str.bitGet+    <*> BitGet.bool
+ src/lib/Rattletrap/Type/Attribute/Product.hs view
@@ -0,0 +1,74 @@+module Rattletrap.Type.Attribute.Product where++import qualified Rattletrap.BitGet as BitGet+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.Str as Str+import qualified Rattletrap.Type.U32 as U32+import qualified Rattletrap.Type.U8 as U8+import qualified Rattletrap.Type.Version as Version+import qualified Rattletrap.Utility.Json as Json++import qualified Data.Map as Map++data Product = Product+  { unknown :: Bool+  , objectId :: U32.U32+  , objectName :: Maybe Str.Str+  -- ^ read-only+  , value :: ProductValue.ProductValue+  }+  deriving (Eq, Show)++instance Json.FromJSON Product where+  parseJSON = Json.withObject "Product" $ \object -> do+    unknown <- Json.required object "unknown"+    objectId <- Json.required object "object_id"+    objectName <- Json.optional object "object_name"+    value <- Json.required object "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+    ]++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)+  ]++putProductAttributes :: List.List Product -> BitPut.BitPut+putProductAttributes attributes =+  let v = List.toList attributes+  in (U8.bitPut . U8.fromWord8 . fromIntegral $ length v) <> foldMap bitPut v++bitPut :: Product -> BitPut.BitPut+bitPut attribute =+  BitPut.bool (unknown attribute)+    <> U32.bitPut (objectId attribute)+    <> ProductValue.bitPut (value attribute)++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++bitGet :: Version.Version -> Map.Map U32.U32 Str.Str -> BitGet.BitGet Product+bitGet version objectMap = do+  flag <- BitGet.bool+  objectId_ <- U32.bitGet+  let maybeObjectName = Map.lookup objectId_ objectMap+  value_ <- ProductValue.bitGet version objectId_ maybeObjectName+  pure (Product flag objectId_ maybeObjectName value_)
+ src/lib/Rattletrap/Type/Attribute/ProductValue.hs view
@@ -0,0 +1,121 @@+module Rattletrap.Type.Attribute.ProductValue where++import qualified Data.Foldable as Foldable+import qualified Data.Word as Word+import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.CompressedWord as CompressedWord+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+import Rattletrap.Utility.Monad++data ProductValue+  = PaintedOld CompressedWord.CompressedWord+  | PaintedNew Word.Word32+  | TeamEditionOld CompressedWord.CompressedWord+  | TeamEditionNew Word.Word32+  | SpecialEdition Word.Word32+  | UserColorOld (Maybe Word.Word32)+  | UserColorNew U32.U32+  | TitleId Str.Str+  deriving (Eq, Show)++instance Json.FromJSON ProductValue where+  parseJSON = Json.withObject "ProductValue" $ \object -> Foldable.asum+    [ PaintedOld <$> Json.required object "painted_old"+    , PaintedNew <$> Json.required object "painted_new"+    , TeamEditionOld <$> Json.required object "team_edition_old"+    , TeamEditionNew <$> Json.required object "team_edition_new"+    , SpecialEdition <$> Json.required object "special_edition"+    , UserColorOld <$> Json.required object "user_color_old"+    , UserColorNew <$> Json.required object "user_color_new"+    , TitleId <$> Json.required object "title_id"+    ]++instance Json.ToJSON ProductValue where+  toJSON x = case x of+    PaintedOld y -> Json.object [Json.pair "painted_old" y]+    PaintedNew y -> Json.object [Json.pair "painted_new" y]+    TeamEditionOld y -> Json.object [Json.pair "team_edition_old" y]+    TeamEditionNew y -> Json.object [Json.pair "team_edition_new" y]+    SpecialEdition y -> Json.object [Json.pair "special_edition" y]+    UserColorOld y -> Json.object [Json.pair "user_color_old" y]+    UserColorNew y -> Json.object [Json.pair "user_color_new" y]+    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)+  ]++bitPut :: ProductValue -> BitPut.BitPut+bitPut val = case val of+  PaintedOld x -> CompressedWord.bitPut x+  PaintedNew x -> BitPut.bits 31 x+  TeamEditionOld x -> CompressedWord.bitPut x+  TeamEditionNew x -> BitPut.bits 31 x+  SpecialEdition x -> BitPut.bits 31 x+  UserColorOld x -> case x of+    Nothing -> BitPut.bool False+    Just y -> BitPut.bool True <> BitPut.bits 31 y+  UserColorNew x -> U32.bitPut x+  TitleId x -> Str.bitPut x++bitGet+  :: Version.Version -> U32.U32 -> Maybe Str.Str -> BitGet.BitGet ProductValue+bitGet version objectId maybeObjectName =+  case Str.toString <$> maybeObjectName of+    Just "TAGame.ProductAttribute_Painted_TA" -> decodePainted version+    Just "TAGame.ProductAttribute_SpecialEdition_TA" -> decodeSpecialEdition+    Just "TAGame.ProductAttribute_TeamEdition_TA" -> decodeTeamEdition version+    Just "TAGame.ProductAttribute_TitleID_TA" -> decodeTitle+    Just "TAGame.ProductAttribute_UserColor_TA" -> decodeColor version+    Just objectName -> fail+      ("[RT05] unknown object name "+      <> show objectName+      <> " for ID "+      <> show objectId+      )+    Nothing -> fail ("[RT06] missing object name for ID " <> show objectId)++decodeSpecialEdition :: BitGet.BitGet ProductValue+decodeSpecialEdition = SpecialEdition <$> BitGet.bits 31++decodePainted :: Version.Version -> BitGet.BitGet ProductValue+decodePainted version = if hasNewPainted version+  then PaintedNew <$> BitGet.bits 31+  else PaintedOld <$> CompressedWord.bitGet 13++decodeTeamEdition :: Version.Version -> BitGet.BitGet ProductValue+decodeTeamEdition version = if hasNewPainted version+  then TeamEditionNew <$> BitGet.bits 31+  else TeamEditionOld <$> CompressedWord.bitGet 13++decodeColor :: Version.Version -> BitGet.BitGet ProductValue+decodeColor version = if hasNewColor version+  then UserColorNew <$> U32.bitGet+  else do+    hasValue <- BitGet.bool+    UserColorOld <$> whenMaybe hasValue (BitGet.bits 31)++hasNewPainted :: Version.Version -> Bool+hasNewPainted v =+  Version.major v >= 868 && Version.minor v >= 18 && Version.patch v >= 0++hasNewColor :: Version.Version -> Bool+hasNewColor v =+  Version.major v >= 868 && Version.minor v >= 23 && Version.patch v >= 8++decodeTitle :: BitGet.BitGet ProductValue+decodeTitle = TitleId <$> Str.bitGet
+ src/lib/Rattletrap/Type/Attribute/QWord.hs view
@@ -0,0 +1,26 @@+module Rattletrap.Type.Attribute.QWord where++import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.U64 as U64+import qualified Rattletrap.Utility.Json as Json++newtype QWord = QWord+  { value :: U64.U64+  } deriving (Eq, Show)++instance Json.FromJSON QWord where+  parseJSON = fmap QWord . Json.parseJSON++instance Json.ToJSON QWord where+  toJSON = Json.toJSON . value++schema :: Schema.Schema+schema = Schema.named "attribute-q-word" $ Schema.ref U64.schema++bitPut :: QWord -> BitPut.BitPut+bitPut qWordAttribute = U64.bitPut (value qWordAttribute)++bitGet :: BitGet.BitGet QWord+bitGet = QWord <$> U64.bitGet
+ src/lib/Rattletrap/Type/Attribute/Reservation.hs view
@@ -0,0 +1,76 @@+module Rattletrap.Type.Attribute.Reservation where++import qualified Data.Word as Word+import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.Attribute.UniqueId as UniqueId+import qualified Rattletrap.Type.CompressedWord as CompressedWord+import qualified Rattletrap.Type.Str as Str+import qualified Rattletrap.Type.U8 as U8+import qualified Rattletrap.Type.Version as Version+import qualified Rattletrap.Utility.Json as Json+import Rattletrap.Utility.Monad++data Reservation = Reservation+  { number :: CompressedWord.CompressedWord+  , uniqueId :: UniqueId.UniqueId+  , name :: Maybe Str.Str+  , unknown1 :: Bool+  , unknown2 :: Bool+  , unknown3 :: Maybe Word.Word8+  }+  deriving (Eq, Show)++instance Json.FromJSON Reservation where+  parseJSON = Json.withObject "Reservation" $ \object -> do+    number <- Json.required object "number"+    uniqueId <- Json.required object "unique_id"+    name <- Json.optional object "name"+    unknown1 <- Json.required object "unknown1"+    unknown2 <- Json.required object "unknown2"+    unknown3 <- Json.optional object "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+    ]++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)+  ]++bitPut :: Reservation -> BitPut.BitPut+bitPut reservationAttribute =+  CompressedWord.bitPut (number reservationAttribute)+    <> UniqueId.bitPut (uniqueId reservationAttribute)+    <> foldMap Str.bitPut (name reservationAttribute)+    <> BitPut.bool (unknown1 reservationAttribute)+    <> BitPut.bool (unknown2 reservationAttribute)+    <> foldMap (BitPut.word8 6) (unknown3 reservationAttribute)++bitGet :: Version.Version -> BitGet.BitGet Reservation+bitGet version = do+  number_ <- CompressedWord.bitGet 7+  uniqueId_ <- UniqueId.bitGet version+  Reservation number_ uniqueId_+    <$> whenMaybe (UniqueId.systemId uniqueId_ /= U8.fromWord8 0) Str.bitGet+    <*> BitGet.bool+    <*> BitGet.bool+    <*> whenMaybe (hasUnknown3 version) (BitGet.word8 6)++hasUnknown3 :: Version.Version -> Bool+hasUnknown3 v =+  Version.major v >= 868 && Version.minor v >= 12 && Version.patch v >= 0
+ src/lib/Rattletrap/Type/Attribute/RigidBodyState.hs view
@@ -0,0 +1,73 @@+module Rattletrap.Type.Attribute.RigidBodyState where++import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.Rotation as Rotation+import qualified Rattletrap.Type.Vector as Vector+import qualified Rattletrap.Type.Version as Version+import qualified Rattletrap.Utility.Json as Json+import Rattletrap.Utility.Monad++data RigidBodyState = RigidBodyState+  { sleeping :: Bool+  , location :: Vector.Vector+  , rotation :: Rotation.Rotation+  , linearVelocity :: Maybe Vector.Vector+  , angularVelocity :: Maybe Vector.Vector+  }+  deriving (Eq, Show)++instance Json.FromJSON RigidBodyState where+  parseJSON = Json.withObject "RigidBodyState" $ \object -> do+    sleeping <- Json.required object "sleeping"+    location <- Json.required object "location"+    rotation <- Json.required object "rotation"+    linearVelocity <- Json.optional object "linear_velocity"+    angularVelocity <- Json.optional object "angular_velocity"+    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+    ]++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+    )+  ]++bitPut :: RigidBodyState -> BitPut.BitPut+bitPut rigidBodyStateAttribute =+  BitPut.bool (sleeping rigidBodyStateAttribute)+    <> Vector.bitPut (location rigidBodyStateAttribute)+    <> Rotation.bitPut (rotation rigidBodyStateAttribute)+    <> foldMap Vector.bitPut (linearVelocity rigidBodyStateAttribute)+    <> foldMap Vector.bitPut (angularVelocity rigidBodyStateAttribute)++bitGet :: Version.Version -> BitGet.BitGet RigidBodyState+bitGet version = do+  sleeping_ <- BitGet.bool+  RigidBodyState sleeping_+    <$> Vector.bitGet version+    <*> Rotation.bitGet version+    <*> whenMaybe (not sleeping_) (Vector.bitGet version)+    <*> whenMaybe (not sleeping_) (Vector.bitGet version)
+ src/lib/Rattletrap/Type/Attribute/StatEvent.hs view
@@ -0,0 +1,36 @@+module Rattletrap.Type.Attribute.StatEvent where++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++data StatEvent = StatEvent+  { unknown :: Bool+  , objectId :: I32.I32+  }+  deriving (Eq, Show)++instance Json.FromJSON StatEvent where+  parseJSON = Json.withObject "StatEvent" $ \object -> do+    unknown <- Json.required object "unknown"+    objectId <- Json.required object "object_id"+    pure StatEvent { unknown, objectId }++instance Json.ToJSON StatEvent where+  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)+  ]++bitPut :: StatEvent -> BitPut.BitPut+bitPut statEventAttribute = BitPut.bool (unknown statEventAttribute)+  <> I32.bitPut (objectId statEventAttribute)++bitGet :: BitGet.BitGet StatEvent+bitGet = StatEvent <$> BitGet.bool <*> I32.bitGet
+ src/lib/Rattletrap/Type/Attribute/String.hs view
@@ -0,0 +1,27 @@+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++newtype String = String+  { value :: Str.Str+  } deriving (Eq, Show)++instance Json.FromJSON String where+  parseJSON = fmap String . Json.parseJSON++instance Json.ToJSON String where+  toJSON = Json.toJSON . value++schema :: Schema.Schema+schema = Schema.named "attribute-string" $ Schema.ref Str.schema++bitPut :: String -> BitPut.BitPut+bitPut stringAttribute = Str.bitPut (value stringAttribute)++bitGet :: BitGet.BitGet String+bitGet = String <$> Str.bitGet
+ src/lib/Rattletrap/Type/Attribute/TeamPaint.hs view
@@ -0,0 +1,67 @@+module Rattletrap.Type.Attribute.TeamPaint where++import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.U32 as U32+import qualified Rattletrap.Type.U8 as U8+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+  }+  deriving (Eq, Show)++instance Json.FromJSON TeamPaint where+  parseJSON = Json.withObject "TeamPaint" $ \object -> do+    team <- Json.required object "team"+    primaryColor <- Json.required object "primary_color"+    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+      }++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+    ]++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)+  ]++bitPut :: TeamPaint -> BitPut.BitPut+bitPut teamPaintAttribute =+  U8.bitPut (team teamPaintAttribute)+    <> U8.bitPut (primaryColor teamPaintAttribute)+    <> U8.bitPut (accentColor teamPaintAttribute)+    <> U32.bitPut (primaryFinish teamPaintAttribute)+    <> U32.bitPut (accentFinish teamPaintAttribute)++bitGet :: BitGet.BitGet TeamPaint+bitGet =+  TeamPaint+    <$> U8.bitGet+    <*> U8.bitGet+    <*> U8.bitGet+    <*> U32.bitGet+    <*> U32.bitGet
+ src/lib/Rattletrap/Type/Attribute/Title.hs view
@@ -0,0 +1,87 @@+module Rattletrap.Type.Attribute.Title where++import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.U32 as U32+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+  }+  deriving (Eq, Show)++instance Json.FromJSON Title where+  parseJSON = Json.withObject "Title" $ \object -> do+    unknown1 <- Json.required object "unknown1"+    unknown2 <- Json.required object "unknown2"+    unknown3 <- Json.required object "unknown3"+    unknown4 <- Json.required object "unknown4"+    unknown5 <- Json.required object "unknown5"+    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+      }++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+    ]++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)+  ]++bitPut :: Title -> BitPut.BitPut+bitPut titleAttribute =+  BitPut.bool (unknown1 titleAttribute)+    <> BitPut.bool (unknown2 titleAttribute)+    <> U32.bitPut (unknown3 titleAttribute)+    <> U32.bitPut (unknown4 titleAttribute)+    <> U32.bitPut (unknown5 titleAttribute)+    <> U32.bitPut (unknown6 titleAttribute)+    <> U32.bitPut (unknown7 titleAttribute)+    <> BitPut.bool (unknown8 titleAttribute)++bitGet :: BitGet.BitGet Title+bitGet =+  Title+    <$> BitGet.bool+    <*> BitGet.bool+    <*> U32.bitGet+    <*> U32.bitGet+    <*> U32.bitGet+    <*> U32.bitGet+    <*> U32.bitGet+    <*> BitGet.bool
+ src/lib/Rattletrap/Type/Attribute/UniqueId.hs view
@@ -0,0 +1,48 @@+module Rattletrap.Type.Attribute.UniqueId where++import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.RemoteId as RemoteId+import qualified Rattletrap.Type.U8 as U8+import qualified Rattletrap.Type.Version as Version+import qualified Rattletrap.Utility.Json as Json++data UniqueId = UniqueId+  { systemId :: U8.U8+  , remoteId :: RemoteId.RemoteId+  , localId :: U8.U8+  }+  deriving (Eq, Show)++instance Json.FromJSON UniqueId where+  parseJSON = Json.withObject "UniqueId" $ \object -> do+    systemId <- Json.required object "system_id"+    remoteId <- Json.required object "remote_id"+    localId <- Json.required object "local_id"+    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+    ]++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)+  ]++bitPut :: UniqueId -> BitPut.BitPut+bitPut uniqueIdAttribute =+  U8.bitPut (systemId uniqueIdAttribute)+    <> RemoteId.bitPut (remoteId uniqueIdAttribute)+    <> U8.bitPut (localId uniqueIdAttribute)++bitGet :: Version.Version -> BitGet.BitGet UniqueId+bitGet version = do+  systemId_ <- U8.bitGet+  UniqueId systemId_ <$> RemoteId.bitGet version systemId_ <*> U8.bitGet
+ src/lib/Rattletrap/Type/Attribute/WeldedInfo.hs view
@@ -0,0 +1,64 @@+module Rattletrap.Type.Attribute.WeldedInfo where++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.Type.I32 as I32+import qualified Rattletrap.Type.Int8Vector as Int8Vector+import qualified Rattletrap.Type.Vector as Vector+import qualified Rattletrap.Type.Version as Version+import qualified Rattletrap.Utility.Json as Json++data WeldedInfo = WeldedInfo+  { active :: Bool+  , actorId :: I32.I32+  , offset :: Vector.Vector+  , mass :: F32.F32+  , rotation :: Int8Vector.Int8Vector+  }+  deriving (Eq, Show)++instance Json.FromJSON WeldedInfo where+  parseJSON = Json.withObject "WeldedInfo" $ \object -> do+    active <- Json.required object "active"+    actorId <- Json.required object "actor_id"+    offset <- Json.required object "offset"+    mass <- Json.required object "mass"+    rotation <- Json.required object "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+    ]++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)+  ]++bitPut :: WeldedInfo -> BitPut.BitPut+bitPut weldedInfoAttribute =+  BitPut.bool (active weldedInfoAttribute)+    <> I32.bitPut (actorId weldedInfoAttribute)+    <> Vector.bitPut (offset weldedInfoAttribute)+    <> F32.bitPut (mass weldedInfoAttribute)+    <> Int8Vector.bitPut (rotation weldedInfoAttribute)++bitGet :: Version.Version -> BitGet.BitGet WeldedInfo+bitGet version =+  WeldedInfo+    <$> BitGet.bool+    <*> I32.bitGet+    <*> Vector.bitGet version+    <*> F32.bitGet+    <*> Int8Vector.bitGet
src/lib/Rattletrap/Type/AttributeMapping.hs view
@@ -1,16 +1,35 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.AttributeMapping-  ( AttributeMapping(..)-  )-where+module Rattletrap.Type.AttributeMapping where -import Rattletrap.Type.Common-import Rattletrap.Type.Word32le+import qualified Rattletrap.ByteGet as ByteGet+import qualified Rattletrap.BytePut as BytePut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.U32 as U32+import qualified Rattletrap.Utility.Json as Json  data AttributeMapping = AttributeMapping-  { attributeMappingObjectId :: Word32le-  , attributeMappingStreamId :: Word32le-  } deriving (Eq, Ord, Show)+  { objectId :: U32.U32+  , streamId :: U32.U32+  }+  deriving (Eq, Show) -$(deriveJson ''AttributeMapping)+instance Json.FromJSON AttributeMapping where+  parseJSON = Json.withObject "AttributeMapping" $ \object -> do+    objectId <- Json.required object "object_id"+    streamId <- Json.required object "stream_id"+    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]++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)+  ]++bytePut :: AttributeMapping -> BytePut.BytePut+bytePut x = U32.bytePut (objectId x) <> U32.bytePut (streamId x)++byteGet :: ByteGet.ByteGet AttributeMapping+byteGet = AttributeMapping <$> U32.byteGet <*> U32.byteGet
src/lib/Rattletrap/Type/AttributeType.hs view
@@ -1,50 +1,41 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.AttributeType-  ( AttributeType(..)-  )-where--import Rattletrap.Type.Common+module Rattletrap.Type.AttributeType where  data AttributeType-  = AttributeTypeAppliedDamage-  | AttributeTypeBoolean-  | AttributeTypeByte-  | AttributeTypeCamSettings-  | AttributeTypeClubColors-  | AttributeTypeCustomDemolish-  | AttributeTypeDamageState-  | AttributeTypeDemolish-  | AttributeTypeEnum-  | AttributeTypeExplosion-  | AttributeTypeExtendedExplosion-  | AttributeTypeFlaggedInt-  | AttributeTypeFlaggedByte-  | AttributeTypeFloat-  | AttributeTypeGameMode-  | AttributeTypeInt-  | AttributeTypeInt64-  | AttributeTypeLoadout-  | AttributeTypeLoadoutOnline-  | AttributeTypeLoadouts-  | AttributeTypeLoadoutsOnline-  | AttributeTypeLocation-  | AttributeTypeMusicStinger-  | AttributeTypePartyLeader-  | AttributeTypePickup-  | AttributeTypePickupNew-  | AttributeTypePlayerHistoryKey-  | AttributeTypePrivateMatchSettings-  | AttributeTypeQWord-  | AttributeTypeReservation-  | AttributeTypeRigidBodyState-  | AttributeTypeStatEvent-  | AttributeTypeString-  | AttributeTypeTeamPaint-  | AttributeTypeTitle-  | AttributeTypeUniqueId-  | AttributeTypeWeldedInfo-  deriving (Eq, Ord, Show)--$(deriveJson ''AttributeType)+  = AppliedDamage+  | Boolean+  | Byte+  | CamSettings+  | ClubColors+  | CustomDemolish+  | DamageState+  | Demolish+  | Enum+  | Explosion+  | ExtendedExplosion+  | FlaggedInt+  | FlaggedByte+  | Float+  | GameMode+  | Int+  | Int64+  | Loadout+  | LoadoutOnline+  | Loadouts+  | LoadoutsOnline+  | Location+  | MusicStinger+  | PartyLeader+  | Pickup+  | PickupNew+  | PlayerHistoryKey+  | PrivateMatchSettings+  | QWord+  | Reservation+  | RigidBodyState+  | StatEvent+  | String+  | TeamPaint+  | Title+  | UniqueId+  | WeldedInfo+  deriving (Eq, Show)
src/lib/Rattletrap/Type/AttributeValue.hs view
@@ -1,87 +1,312 @@-{-# LANGUAGE TemplateHaskell #-}+module Rattletrap.Type.AttributeValue where -module Rattletrap.Type.AttributeValue-  ( AttributeValue(..)-  )-where+import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Data as Data+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.Byte as Byte+import qualified Rattletrap.Type.Attribute.CamSettings as CamSettings+import qualified Rattletrap.Type.Attribute.ClubColors as ClubColors+import qualified Rattletrap.Type.Attribute.CustomDemolish as CustomDemolish+import qualified Rattletrap.Type.Attribute.DamageState as DamageState+import qualified Rattletrap.Type.Attribute.Demolish as Demolish+import qualified Rattletrap.Type.Attribute.Enum as Enum+import qualified Rattletrap.Type.Attribute.Explosion as Explosion+import qualified Rattletrap.Type.Attribute.ExtendedExplosion as ExtendedExplosion+import qualified Rattletrap.Type.Attribute.FlaggedByte as FlaggedByte+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.Int as Int+import qualified Rattletrap.Type.Attribute.Int64 as Int64+import qualified Rattletrap.Type.Attribute.Loadout as Loadout+import qualified Rattletrap.Type.Attribute.LoadoutOnline as LoadoutOnline+import qualified Rattletrap.Type.Attribute.Loadouts as Loadouts+import qualified Rattletrap.Type.Attribute.LoadoutsOnline as LoadoutsOnline+import qualified Rattletrap.Type.Attribute.Location as Location+import qualified Rattletrap.Type.Attribute.MusicStinger as MusicStinger+import qualified Rattletrap.Type.Attribute.PartyLeader as PartyLeader+import qualified Rattletrap.Type.Attribute.Pickup as Pickup+import qualified Rattletrap.Type.Attribute.PickupNew as PickupNew+import qualified Rattletrap.Type.Attribute.PlayerHistoryKey as PlayerHistoryKey+import qualified Rattletrap.Type.Attribute.PrivateMatchSettings as PrivateMatchSettings+import qualified Rattletrap.Type.Attribute.QWord as QWord+import qualified Rattletrap.Type.Attribute.Reservation as Reservation+import qualified Rattletrap.Type.Attribute.RigidBodyState as RigidBodyState+import qualified Rattletrap.Type.Attribute.StatEvent as StatEvent+import qualified Rattletrap.Type.Attribute.String as String+import qualified Rattletrap.Type.Attribute.TeamPaint as TeamPaint+import qualified Rattletrap.Type.Attribute.Title as Title+import qualified Rattletrap.Type.Attribute.UniqueId as UniqueId+import qualified Rattletrap.Type.Attribute.WeldedInfo as WeldedInfo+import qualified Rattletrap.Type.AttributeType as AttributeType+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 -import Rattletrap.Type.AppliedDamageAttribute-import Rattletrap.Type.BooleanAttribute-import Rattletrap.Type.ByteAttribute-import Rattletrap.Type.CamSettingsAttribute-import Rattletrap.Type.ClubColorsAttribute-import Rattletrap.Type.Common-import Rattletrap.Type.CustomDemolishAttribute-import Rattletrap.Type.DamageStateAttribute-import Rattletrap.Type.DemolishAttribute-import Rattletrap.Type.EnumAttribute-import Rattletrap.Type.ExplosionAttribute-import Rattletrap.Type.ExtendedExplosionAttribute-import Rattletrap.Type.FlaggedIntAttribute-import Rattletrap.Type.FlaggedByteAttribute-import Rattletrap.Type.FloatAttribute-import Rattletrap.Type.GameModeAttribute-import Rattletrap.Type.Int64Attribute-import Rattletrap.Type.IntAttribute-import Rattletrap.Type.LoadoutAttribute-import Rattletrap.Type.LoadoutOnlineAttribute-import Rattletrap.Type.LoadoutsAttribute-import Rattletrap.Type.LoadoutsOnlineAttribute-import Rattletrap.Type.LocationAttribute-import Rattletrap.Type.MusicStingerAttribute-import Rattletrap.Type.PartyLeaderAttribute-import Rattletrap.Type.PickupAttribute-import Rattletrap.Type.PickupAttributeNew-import Rattletrap.Type.PlayerHistoryKeyAttribute-import Rattletrap.Type.PrivateMatchSettingsAttribute-import Rattletrap.Type.QWordAttribute-import Rattletrap.Type.ReservationAttribute-import Rattletrap.Type.RigidBodyStateAttribute-import Rattletrap.Type.StatEventAttribute-import Rattletrap.Type.StringAttribute-import Rattletrap.Type.TeamPaintAttribute-import Rattletrap.Type.TitleAttribute-import Rattletrap.Type.UniqueIdAttribute-import Rattletrap.Type.WeldedInfoAttribute+import qualified Data.Foldable as Foldable+import qualified Data.Map as Map  data AttributeValue-  = AttributeValueAppliedDamage AppliedDamageAttribute-  | AttributeValueBoolean BooleanAttribute-  | AttributeValueByte ByteAttribute-  | AttributeValueCamSettings CamSettingsAttribute-  | AttributeValueClubColors ClubColorsAttribute-  | AttributeValueCustomDemolish CustomDemolishAttribute-  | AttributeValueDamageState DamageStateAttribute-  | AttributeValueDemolish DemolishAttribute-  | AttributeValueEnum EnumAttribute-  | AttributeValueExplosion ExplosionAttribute-  | AttributeValueExtendedExplosion ExtendedExplosionAttribute-  | AttributeValueFlaggedInt FlaggedIntAttribute-  | AttributeValueFlaggedByte FlaggedByteAttribute-  | AttributeValueFloat FloatAttribute-  | AttributeValueGameMode GameModeAttribute-  | AttributeValueInt IntAttribute-  | AttributeValueInt64 Int64Attribute-  | AttributeValueLoadout LoadoutAttribute-  | AttributeValueLoadoutOnline LoadoutOnlineAttribute-  | AttributeValueLoadouts LoadoutsAttribute-  | AttributeValueLoadoutsOnline LoadoutsOnlineAttribute-  | AttributeValueLocation LocationAttribute-  | AttributeValueMusicStinger MusicStingerAttribute-  | AttributeValuePartyLeader PartyLeaderAttribute-  | AttributeValuePickup PickupAttribute-  | AttributeValuePickupNew PickupAttributeNew-  | AttributeValuePlayerHistoryKey PlayerHistoryKeyAttribute-  | AttributeValuePrivateMatchSettings PrivateMatchSettingsAttribute-  | AttributeValueQWord QWordAttribute-  | AttributeValueReservation ReservationAttribute-  | AttributeValueRigidBodyState RigidBodyStateAttribute-  | AttributeValueStatEvent StatEventAttribute-  | AttributeValueString StringAttribute-  | AttributeValueTeamPaint TeamPaintAttribute-  | AttributeValueTitle TitleAttribute-  | AttributeValueUniqueId UniqueIdAttribute-  | AttributeValueWeldedInfo WeldedInfoAttribute-  deriving (Eq, Ord, Show)+  = AppliedDamage AppliedDamage.AppliedDamage+  | Boolean Boolean.Boolean+  | Byte Byte.Byte+  | CamSettings CamSettings.CamSettings+  | ClubColors ClubColors.ClubColors+  | CustomDemolish CustomDemolish.CustomDemolish+  | DamageState DamageState.DamageState+  | Demolish Demolish.Demolish+  | Enum Enum.Enum+  | Explosion Explosion.Explosion+  | ExtendedExplosion ExtendedExplosion.ExtendedExplosion+  | FlaggedInt FlaggedInt.FlaggedInt+  | FlaggedByte FlaggedByte.FlaggedByte+  | Float Float.Float+  | GameMode GameMode.GameMode+  | Int Int.Int+  | Int64 Int64.Int64+  | Loadout Loadout.Loadout+  | LoadoutOnline LoadoutOnline.LoadoutOnline+  | Loadouts Loadouts.Loadouts+  | LoadoutsOnline LoadoutsOnline.LoadoutsOnline+  | Location Location.Location+  | MusicStinger MusicStinger.MusicStinger+  | PartyLeader PartyLeader.PartyLeader+  | Pickup Pickup.Pickup+  | PickupNew PickupNew.PickupNew+  | PlayerHistoryKey PlayerHistoryKey.PlayerHistoryKey+  | PrivateMatchSettings PrivateMatchSettings.PrivateMatchSettings+  | QWord QWord.QWord+  | Reservation Reservation.Reservation+  | RigidBodyState RigidBodyState.RigidBodyState+  | StatEvent StatEvent.StatEvent+  | String String.String+  | TeamPaint TeamPaint.TeamPaint+  | Title Title.Title+  | UniqueId UniqueId.UniqueId+  | WeldedInfo WeldedInfo.WeldedInfo+  deriving (Eq, Show) -$(deriveJson ''AttributeValue)+instance Json.FromJSON AttributeValue where+  parseJSON = Json.withObject "AttributeValue" $ \object -> Foldable.asum+    [ AppliedDamage <$> Json.required object "applied_damage"+    , Boolean <$> Json.required object "boolean"+    , Byte <$> Json.required object "byte"+    , CamSettings <$> Json.required object "cam_settings"+    , ClubColors <$> Json.required object "club_colors"+    , CustomDemolish <$> Json.required object "custom_demolish"+    , DamageState <$> Json.required object "damage_state"+    , Demolish <$> Json.required object "demolish"+    , Enum <$> Json.required object "enum"+    , Explosion <$> Json.required object "explosion"+    , ExtendedExplosion <$> Json.required object "extended_explosion"+    , FlaggedByte <$> Json.required object "flagged_byte"+    , FlaggedInt <$> Json.required object "flagged_int"+    , Float <$> Json.required object "float"+    , GameMode <$> Json.required object "game_mode"+    , Int <$> Json.required object "int"+    , Int64 <$> Json.required object "int64"+    , Loadout <$> Json.required object "loadout"+    , LoadoutOnline <$> Json.required object "loadout_online"+    , Loadouts <$> Json.required object "loadouts"+    , LoadoutsOnline <$> Json.required object "loadouts_online"+    , Location <$> Json.required object "location"+    , MusicStinger <$> Json.required object "music_stinger"+    , PartyLeader <$> Json.required object "party_leader"+    , Pickup <$> Json.required object "pickup"+    , PickupNew <$> Json.required object "pickup_new"+    , PlayerHistoryKey <$> Json.required object "player_history_key"+    , PrivateMatchSettings <$> Json.required object "private_match_settings"+    , QWord <$> Json.required object "q_word"+    , Reservation <$> Json.required object "reservation"+    , RigidBodyState <$> Json.required object "rigid_body_state"+    , StatEvent <$> Json.required object "stat_event"+    , String <$> Json.required object "string"+    , TeamPaint <$> Json.required object "team_paint"+    , Title <$> Json.required object "title"+    , UniqueId <$> Json.required object "unique_id"+    , WeldedInfo <$> Json.required object "welded_info"+    ]++instance Json.ToJSON AttributeValue where+  toJSON x = case x of+    AppliedDamage y -> Json.object [Json.pair "applied_damage" y]+    Boolean y -> Json.object [Json.pair "boolean" 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]+    CustomDemolish y -> Json.object [Json.pair "custom_demolish" y]+    DamageState y -> Json.object [Json.pair "damage_state" y]+    Demolish y -> Json.object [Json.pair "demolish" y]+    Enum y -> Json.object [Json.pair "enum" y]+    Explosion y -> Json.object [Json.pair "explosion" y]+    ExtendedExplosion y -> Json.object [Json.pair "extended_explosion" y]+    FlaggedByte y -> Json.object [Json.pair "flagged_byte" y]+    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]+    Int y -> Json.object [Json.pair "int" y]+    Int64 y -> Json.object [Json.pair "int64" y]+    Loadout y -> Json.object [Json.pair "loadout" y]+    LoadoutOnline y -> Json.object [Json.pair "loadout_online" y]+    Loadouts y -> Json.object [Json.pair "loadouts" y]+    LoadoutsOnline y -> Json.object [Json.pair "loadouts_online" y]+    Location y -> Json.object [Json.pair "location" y]+    MusicStinger y -> Json.object [Json.pair "music_stinger" y]+    PartyLeader y -> Json.object [Json.pair "party_leader" y]+    Pickup y -> Json.object [Json.pair "pickup" y]+    PickupNew y -> Json.object [Json.pair "pickup_new" y]+    PlayerHistoryKey y -> Json.object [Json.pair "player_history_key" y]+    PrivateMatchSettings y ->+      Json.object [Json.pair "private_match_settings" y]+    QWord y -> Json.object [Json.pair "q_word" y]+    Reservation y -> Json.object [Json.pair "reservation" y]+    RigidBodyState y -> Json.object [Json.pair "rigid_body_state" y]+    StatEvent y -> Json.object [Json.pair "stat_event" y]+    String y -> Json.object [Json.pair "string" y]+    TeamPaint y -> Json.object [Json.pair "team_paint" y]+    Title y -> Json.object [Json.pair "title" y]+    UniqueId y -> Json.object [Json.pair "unique_id" y]+    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)+  , ("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_new", PickupNew.schema)+  , ("pickup", Pickup.schema)+  , ("player_history_key", PlayerHistoryKey.schema)+  , ("private_match_settings", PrivateMatchSettings.schema)+  , ("q_word", QWord.schema)+  , ("reservation", Reservation.schema)+  , ("rigid_body_state", RigidBodyState.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+  AppliedDamage x -> AppliedDamage.bitPut x+  Boolean x -> Boolean.bitPut x+  Byte x -> Byte.bitPut x+  CamSettings x -> CamSettings.bitPut x+  ClubColors x -> ClubColors.bitPut x+  CustomDemolish x -> CustomDemolish.bitPut x+  DamageState x -> DamageState.bitPut x+  Demolish x -> Demolish.bitPut x+  Enum x -> Enum.bitPut x+  Explosion x -> Explosion.bitPut x+  ExtendedExplosion x -> ExtendedExplosion.bitPut x+  FlaggedInt x -> FlaggedInt.bitPut x+  FlaggedByte x -> FlaggedByte.bitPut x+  Float x -> Float.bitPut x+  GameMode x -> GameMode.bitPut x+  Int x -> Int.bitPut x+  Int64 x -> Int64.putInt64Attribute x+  Loadout x -> Loadout.bitPut x+  LoadoutOnline x -> LoadoutOnline.bitPut x+  Loadouts x -> Loadouts.bitPut x+  LoadoutsOnline x -> LoadoutsOnline.bitPut x+  Location x -> Location.bitPut x+  MusicStinger x -> MusicStinger.bitPut x+  PartyLeader x -> PartyLeader.bitPut x+  Pickup x -> Pickup.bitPut x+  PickupNew x -> PickupNew.bitPut x+  PlayerHistoryKey x -> PlayerHistoryKey.bitPut x+  PrivateMatchSettings x -> PrivateMatchSettings.bitPut x+  QWord x -> QWord.bitPut x+  Reservation x -> Reservation.bitPut x+  RigidBodyState x -> RigidBodyState.bitPut x+  StatEvent x -> StatEvent.bitPut x+  String x -> String.bitPut x+  TeamPaint x -> TeamPaint.bitPut x+  Title x -> Title.bitPut x+  UniqueId x -> UniqueId.bitPut x+  WeldedInfo x -> WeldedInfo.bitPut x++bitGet+  :: Version.Version+  -> Map.Map U32.U32 Str.Str+  -> Str.Str+  -> BitGet.BitGet AttributeValue+bitGet version objectMap name = do+  constructor <- maybe+    (fail ("[RT04] don't know how to get attribute value " <> show name))+    pure+    (Map.lookup (Str.toText name) Data.attributeTypes)+  case constructor of+    AttributeType.AppliedDamage ->+      AppliedDamage <$> AppliedDamage.bitGet version+    AttributeType.Boolean -> Boolean <$> Boolean.bitGet+    AttributeType.Byte -> Byte <$> Byte.bitGet+    AttributeType.CamSettings -> CamSettings <$> CamSettings.bitGet version+    AttributeType.ClubColors -> ClubColors <$> ClubColors.bitGet+    AttributeType.CustomDemolish ->+      CustomDemolish <$> CustomDemolish.bitGet version+    AttributeType.DamageState -> DamageState <$> DamageState.bitGet version+    AttributeType.Demolish -> Demolish <$> Demolish.bitGet version+    AttributeType.Enum -> Enum <$> Enum.bitGet+    AttributeType.Explosion -> Explosion <$> Explosion.bitGet version+    AttributeType.ExtendedExplosion ->+      ExtendedExplosion <$> ExtendedExplosion.bitGet version+    AttributeType.FlaggedInt -> FlaggedInt <$> FlaggedInt.bitGet+    AttributeType.FlaggedByte -> FlaggedByte <$> FlaggedByte.bitGet+    AttributeType.Float -> Float <$> Float.bitGet+    AttributeType.GameMode -> GameMode <$> GameMode.bitGet version+    AttributeType.Int -> Int <$> Int.bitGet+    AttributeType.Int64 -> Int64 <$> Int64.bitGet+    AttributeType.Loadout -> Loadout <$> Loadout.bitGet+    AttributeType.LoadoutOnline ->+      LoadoutOnline <$> LoadoutOnline.bitGet version objectMap+    AttributeType.Loadouts -> Loadouts <$> Loadouts.bitGet+    AttributeType.LoadoutsOnline ->+      LoadoutsOnline <$> LoadoutsOnline.bitGet version objectMap+    AttributeType.Location -> Location <$> Location.bitGet version+    AttributeType.MusicStinger -> MusicStinger <$> MusicStinger.bitGet+    AttributeType.PartyLeader -> PartyLeader <$> PartyLeader.bitGet version+    AttributeType.Pickup -> Pickup <$> Pickup.bitGet+    AttributeType.PickupNew -> PickupNew <$> PickupNew.bitGet+    AttributeType.PlayerHistoryKey ->+      PlayerHistoryKey <$> PlayerHistoryKey.bitGet+    AttributeType.PrivateMatchSettings ->+      PrivateMatchSettings <$> PrivateMatchSettings.bitGet+    AttributeType.QWord -> QWord <$> QWord.bitGet+    AttributeType.Reservation -> Reservation <$> Reservation.bitGet version+    AttributeType.RigidBodyState ->+      RigidBodyState <$> RigidBodyState.bitGet version+    AttributeType.StatEvent -> StatEvent <$> StatEvent.bitGet+    AttributeType.String -> String <$> String.bitGet+    AttributeType.TeamPaint -> TeamPaint <$> TeamPaint.bitGet+    AttributeType.Title -> Title <$> Title.bitGet+    AttributeType.UniqueId -> UniqueId <$> UniqueId.bitGet version+    AttributeType.WeldedInfo -> WeldedInfo <$> WeldedInfo.bitGet version
− src/lib/Rattletrap/Type/BooleanAttribute.hs
@@ -1,14 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.BooleanAttribute-  ( BooleanAttribute(..)-  )-where--import Rattletrap.Type.Common--newtype BooleanAttribute = BooleanAttribute-  { booleanAttributeValue :: Bool-  } deriving (Eq, Ord, Show)--$(deriveJson ''BooleanAttribute)
− src/lib/Rattletrap/Type/ByteAttribute.hs
@@ -1,15 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.ByteAttribute-  ( ByteAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Word8le--newtype ByteAttribute = ByteAttribute-  { byteAttributeValue :: Word8le-  } deriving (Eq, Ord, Show)--$(deriveJson ''ByteAttribute)
src/lib/Rattletrap/Type/Cache.hs view
@@ -1,20 +1,59 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.Cache-  ( Cache(..)-  )-where+module Rattletrap.Type.Cache where -import Rattletrap.Type.AttributeMapping-import Rattletrap.Type.Common-import Rattletrap.Type.List-import Rattletrap.Type.Word32le+import qualified Rattletrap.ByteGet as ByteGet+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.U32 as U32+import qualified Rattletrap.Utility.Json as Json  data Cache = Cache-  { cacheClassId :: Word32le-  , cacheParentCacheId :: Word32le-  , cacheCacheId :: Word32le-  , cacheAttributeMappings :: List AttributeMapping-  } deriving (Eq, Ord, Show)+  { classId :: U32.U32+  , parentCacheId :: U32.U32+  , cacheId :: U32.U32+  , attributeMappings :: List.List AttributeMapping.AttributeMapping+  }+  deriving (Eq, Show) -$(deriveJson ''Cache)+instance Json.FromJSON Cache where+  parseJSON = Json.withObject "Cache" $ \object -> do+    classId <- Json.required object "class_id"+    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 }++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+    ]++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+    )+  ]++bytePut :: Cache -> BytePut.BytePut+bytePut x =+  U32.bytePut (classId x)+    <> U32.bytePut (parentCacheId x)+    <> U32.bytePut (cacheId x)+    <> List.bytePut AttributeMapping.bytePut (attributeMappings x)++byteGet :: ByteGet.ByteGet Cache+byteGet =+  Cache+    <$> U32.byteGet+    <*> U32.byteGet+    <*> U32.byteGet+    <*> List.byteGet AttributeMapping.byteGet
− src/lib/Rattletrap/Type/CamSettingsAttribute.hs
@@ -1,21 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.CamSettingsAttribute-  ( CamSettingsAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Float32le--data CamSettingsAttribute = CamSettingsAttribute-  { camSettingsAttributeFov :: Float32le-  , camSettingsAttributeHeight :: Float32le-  , camSettingsAttributeAngle :: Float32le-  , camSettingsAttributeDistance :: Float32le-  , camSettingsAttributeStiffness :: Float32le-  , camSettingsAttributeSwivelSpeed :: Float32le-  , camSettingsAttributeTransitionSpeed :: Maybe Float32le-  } deriving (Eq, Ord, Show)--$(deriveJson ''CamSettingsAttribute)
src/lib/Rattletrap/Type/ClassAttributeMap.hs view
@@ -8,19 +8,17 @@   , getClassName   , getName   , getObjectName-  , makeClassAttributeMap-  )-where+  , make+  ) where -import Rattletrap.Data-import Rattletrap.Type.AttributeMapping-import Rattletrap.Type.Cache-import Rattletrap.Type.ClassMapping-import Rattletrap.Type.Common-import Rattletrap.Type.CompressedWord-import Rattletrap.Type.List-import Rattletrap.Type.Str-import Rattletrap.Type.Word32le+import qualified Rattletrap.Data as Data+import qualified Rattletrap.Type.AttributeMapping as AttributeMapping+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.Str as Str+import qualified Rattletrap.Type.U32 as U32  import qualified Data.IntMap as IntMap import qualified Data.List as List@@ -34,19 +32,20 @@ -- attributes in the replay. The class hierarchy is not fixed; it is encoded -- in the 'Rattletrap.Content.Content'. Similarly, the attributes that belong -- to each class are not fixed either. Converting the raw data into a usable--- structure is tedious; see 'makeClassAttributeMap'.+-- structure is tedious; see 'make'. data ClassAttributeMap = ClassAttributeMap-  { classAttributeMapObjectMap :: Map Word32le Str+  { objectMap :: Map.Map U32.U32 Str.Str   -- ^ A map from object IDs to their names.-  , classAttributeMapObjectClassMap :: Map Word32le Word32le+  , objectClassMap :: Map.Map U32.U32 U32.U32   -- ^ A map from object IDs to their class IDs.-    , classAttributeMapValue :: Map Word32le (Map Word32le Word32le)+  , 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.-  , classAttributeMapNameMap :: IntMap.IntMap Str-  } deriving (Eq, Ord, Show)+  , nameMap :: IntMap.IntMap Str.Str+  }+  deriving (Eq, Show) -type Bimap l r = (Map l r, Map r l)+type Bimap l r = (Map.Map l r, Map.Map r l)  bimap :: (Ord l, Ord r) => [(l, r)] -> Bimap l r bimap xs = (Map.fromList xs, Map.fromList (fmap Tuple.swap xs))@@ -59,26 +58,26 @@  -- | Makes a 'ClassAttributeMap' given the necessary fields from the -- 'Rattletrap.Content.Content'.-makeClassAttributeMap-  :: List Str-  -- ^ From 'Rattletrap.Content.contentObjects'.-  -> List ClassMapping-  -- ^ From 'Rattletrap.Content.contentClassMappings'.-  -> List Cache-  -- ^ From 'Rattletrap.Content.contentCaches'.-  -> List Str-  -- ^ From 'Rattletrap.Content.contentNames'.+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-makeClassAttributeMap objects classMappings caches names =+make objects classMappings caches names =   let-    objectMap = makeObjectMap objects+    objectMap_ = makeObjectMap objects     classMap = makeClassMap classMappings-    objectClassMap = makeObjectClassMap objectMap classMap+    objectClassMap_ = makeObjectClassMap objectMap_ classMap     classCache = makeClassCache classMap caches     attributeMap = makeAttributeMap caches     classIds = fmap (\(_, classId, _, _) -> classId) classCache     parentMap = makeParentMap classCache-    value = Map.fromList+    value_ = Map.fromList       (fmap         (\classId ->           let@@ -97,21 +96,24 @@         )         classIds       )-    nameMap = makeNameMap names-  in ClassAttributeMap objectMap objectClassMap value nameMap+    nameMap_ = makeNameMap names+  in ClassAttributeMap objectMap_ objectClassMap_ value_ nameMap_ -makeNameMap :: List Str -> IntMap.IntMap Str-makeNameMap names = IntMap.fromDistinctAscList (zip [0 ..] (listValue names))+makeNameMap :: List.List Str.Str -> IntMap.IntMap Str.Str+makeNameMap names =+  IntMap.fromDistinctAscList (zip [0 ..] (List.toList names)) -getName :: IntMap.IntMap Str -> Word32le -> Maybe Str-getName nameMap nameIndex =-  IntMap.lookup (fromIntegral (word32leValue nameIndex)) nameMap+getName :: IntMap.IntMap Str.Str -> U32.U32 -> Maybe Str.Str+getName nameMap_ nameIndex =+  IntMap.lookup (fromIntegral (U32.toWord32 nameIndex)) nameMap_  makeObjectClassMap-  :: Map Word32le Str -> Bimap Word32le Str -> Map Word32le Word32le-makeObjectClassMap objectMap classMap = do-  let objectIds = Map.keys objectMap-  let classIds = fmap (getClassId objectMap classMap) objectIds+  :: 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@@ -123,58 +125,62 @@   Map.fromList pairs  getClassId-  :: Map Word32le Str -> Bimap Word32le Str -> Word32le -> Maybe Word32le-getClassId objectMap classMap objectId = do-  objectName <- getObjectName objectMap objectId+  :: 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 Word32le Str-  -> List Cache-  -> [(Maybe Str, Word32le, Word32le, Word32le)]+  :: 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 = cacheClassId cache+    let classId = Cache.classId cache     in       ( lookupL classId classMap       , classId-      , cacheCacheId cache-      , cacheParentCacheId cache+      , Cache.cacheId cache+      , Cache.parentCacheId cache       )   )-  (listValue caches)+  (List.toList caches) -makeClassMap :: List ClassMapping -> Bimap Word32le Str+makeClassMap :: List.List ClassMapping.ClassMapping -> Bimap U32.U32 Str.Str makeClassMap classMappings = bimap   (fmap     (\classMapping ->-      (classMappingStreamId classMapping, classMappingName classMapping)+      (ClassMapping.streamId classMapping, ClassMapping.name classMapping)     )-    (listValue classMappings)+    (List.toList classMappings)   ) -makeAttributeMap :: List Cache -> Map Word32le (Map Word32le Word32le)+makeAttributeMap+  :: List.List Cache.Cache -> Map.Map U32.U32 (Map.Map U32.U32 U32.U32) makeAttributeMap caches = Map.fromList   (fmap     (\cache ->-      ( cacheClassId cache+      ( Cache.classId cache       , Map.fromList         (fmap           (\attributeMapping ->-            ( attributeMappingStreamId attributeMapping-            , attributeMappingObjectId attributeMapping+            ( AttributeMapping.streamId attributeMapping+            , AttributeMapping.objectId attributeMapping             )           )-          (listValue (cacheAttributeMappings cache))+          (List.toList (Cache.attributeMappings cache))         )       )     )-    (listValue caches)+    (List.toList caches)   )  makeShallowParentMap-  :: [(Maybe Str, Word32le, Word32le, Word32le)] -> Map Word32le Word32le+  :: [(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@@ -187,7 +193,7 @@   )  makeParentMap-  :: [(Maybe Str, Word32le, Word32le, Word32le)] -> Map Word32le [Word32le]+  :: [(Maybe Str.Str, U32.U32, U32.U32, U32.U32)] -> Map.Map U32.U32 [U32.U32] makeParentMap classCache =   let shallowParentMap = makeShallowParentMap classCache   in@@ -195,7 +201,7 @@       (\classId _ -> getParentClasses shallowParentMap classId)       shallowParentMap -getParentClasses :: Map Word32le Word32le -> Word32le -> [Word32le]+getParentClasses :: Map.Map U32.U32 U32.U32 -> U32.U32 -> [U32.U32] getParentClasses shallowParentMap classId =   case Map.lookup classId shallowParentMap of     Nothing -> []@@ -203,30 +209,32 @@       parentClassId : getParentClasses shallowParentMap parentClassId  getParentClass-  :: Maybe Str-  -> Word32le-  -> [(Maybe Str, Word32le, Word32le, Word32le)]-  -> Maybe Word32le+  :: 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-  :: Word32le -> [(Maybe Str, Word32le, Word32le, Word32le)] -> Maybe Word32le+  :: 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 == Word32le 0+    [] -> if parentCacheId == U32.fromWord32 0       then Nothing-      else getParentClassById (Word32le (word32leValue parentCacheId - 1)) xs+      else getParentClassById+        (U32.fromWord32 (U32.toWord32 parentCacheId - 1))+        xs     (_, parentClassId, _, _) : _ -> Just parentClassId  getParentClassByName-  :: Str-  -> Word32le-  -> [(Maybe Str, Word32le, Word32le, Word32le)]-  -> Maybe Word32le+  :: Str.Str+  -> U32.U32+  -> [(Maybe Str.Str, U32.U32, U32.U32, U32.U32)]+  -> Maybe U32.U32 getParentClassByName className parentCacheId xs =-  case Map.lookup className parentClasses of+  case Map.lookup (Str.toText className) Data.parentClasses of     Nothing -> getParentClassById parentCacheId xs     Just parentClassName -> Maybe.maybe       (getParentClassById parentCacheId xs)@@ -238,7 +246,7 @@             (\(_, _, cacheId, _) -> cacheId <= parentCacheId)             (filter               (\(maybeClassName, _, _, _) ->-                maybeClassName == Just parentClassName+                fmap Str.toText maybeClassName == Just parentClassName               )               xs             )@@ -246,79 +254,73 @@         )       ) -parentClasses :: Map Str Str-parentClasses =-  Map.map toStr (Map.mapKeys toStr (Map.fromList rawParentClasses))--makeObjectMap :: List Str -> Map Word32le Str+makeObjectMap :: List.List Str.Str -> Map.Map U32.U32 Str.Str makeObjectMap objects =-  Map.fromAscList (zip (fmap Word32le [0 ..]) (listValue objects))+  Map.fromAscList (zip (fmap U32.fromWord32 [0 ..]) (List.toList objects)) -getObjectName :: Map Word32le Str -> Word32le -> Maybe Str-getObjectName objectMap objectId = Map.lookup objectId objectMap+getObjectName :: Map.Map U32.U32 Str.Str -> U32.U32 -> Maybe Str.Str+getObjectName objectMap_ objectId = Map.lookup objectId objectMap_ -getClassName :: Str -> Maybe Str+getClassName :: Str.Str -> Maybe Str.Str getClassName rawObjectName =-  Map.lookup (normalizeObjectName rawObjectName) objectClasses+  Str.fromText+    <$> Map.lookup+          (Str.toText $ normalizeObjectName rawObjectName)+          Data.objectClasses -normalizeObjectName :: Str -> Str+normalizeObjectName :: Str.Str -> Str.Str normalizeObjectName objectName =   let-    name = strValue objectName+    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 crowdActor+    then Str.fromText crowdActor     else if Text.isInfixOf crowdManager name-      then Str crowdManager+      then Str.fromText crowdManager       else if Text.isInfixOf boostPickup name-        then Str boostPickup+        then Str.fromText boostPickup         else if Text.isInfixOf mapScoreboard name-          then Str mapScoreboard+          then Str.fromText mapScoreboard           else if Text.isInfixOf breakout name-            then Str breakout+            then Str.fromText breakout             else objectName -objectClasses :: Map Str Str-objectClasses =-  Map.map toStr (Map.mapKeys toStr (Map.fromList rawObjectClasses))--classHasLocation :: Str -> Bool-classHasLocation className = Set.member className classesWithLocation--classesWithLocation :: Set.Set Str-classesWithLocation = Set.fromList (fmap toStr rawClassesWithLocation)--classHasRotation :: Str -> Bool-classHasRotation className = Set.member className classesWithRotation+classHasLocation :: Str.Str -> Bool+classHasLocation className =+  Set.member (Str.toText className) Data.classesWithLocation -classesWithRotation :: Set.Set Str-classesWithRotation = Set.fromList (fmap toStr rawClassesWithRotation)+classHasRotation :: Str.Str -> Bool+classHasRotation className =+  Set.member (Str.toText className) Data.classesWithRotation -getAttributeIdLimit :: Map Word32le Word32le -> Maybe Word+getAttributeIdLimit :: Map.Map U32.U32 U32.U32 -> Maybe Word getAttributeIdLimit attributeMap = do   ((streamId, _), _) <- Map.maxViewWithKey attributeMap-  pure (fromIntegral (word32leValue streamId))+  pure (fromIntegral (U32.toWord32 streamId))  getAttributeName-  :: ClassAttributeMap -> Map Word32le Word32le -> CompressedWord -> Maybe Str+  :: ClassAttributeMap+  -> Map.Map U32.U32 U32.U32+  -> CompressedWord.CompressedWord+  -> Maybe Str.Str getAttributeName classAttributeMap attributeMap streamId = do-  let key = Word32le (fromIntegral (compressedWordValue streamId))+  let key = U32.fromWord32 (fromIntegral (CompressedWord.value streamId))   attributeId <- Map.lookup key attributeMap-  let objectMap = classAttributeMapObjectMap classAttributeMap-  Map.lookup attributeId objectMap+  let objectMap_ = objectMap classAttributeMap+  Map.lookup attributeId objectMap_  getAttributeMap   :: ClassAttributeMap-  -> Map CompressedWord Word32le-  -> CompressedWord-  -> Maybe (Map Word32le Word32le)+  -> 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 = classAttributeMapObjectClassMap classAttributeMap-  classId <- Map.lookup objectId objectClassMap-  let value = classAttributeMapValue classAttributeMap-  Map.lookup classId value+  let objectClassMap_ = objectClassMap classAttributeMap+  classId <- Map.lookup objectId objectClassMap_+  let value_ = value classAttributeMap+  Map.lookup classId value_
src/lib/Rattletrap/Type/ClassMapping.hs view
@@ -1,17 +1,36 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.ClassMapping-  ( ClassMapping(..)-  )-where+module Rattletrap.Type.ClassMapping where -import Rattletrap.Type.Common-import Rattletrap.Type.Str-import Rattletrap.Type.Word32le+import qualified Rattletrap.ByteGet as ByteGet+import qualified Rattletrap.BytePut as BytePut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.Str as Str+import qualified Rattletrap.Type.U32 as U32+import qualified Rattletrap.Utility.Json as Json  data ClassMapping = ClassMapping-  { classMappingName :: Str-  , classMappingStreamId :: Word32le-  } deriving (Eq, Ord, Show)+  { name :: Str.Str+  , streamId :: U32.U32+  }+  deriving (Eq, Show) -$(deriveJson ''ClassMapping)+instance Json.FromJSON ClassMapping where+  parseJSON = Json.withObject "ClassMapping" $ \object -> do+    name <- Json.required object "name"+    streamId <- Json.required object "stream_id"+    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)+  ]++bytePut :: ClassMapping -> BytePut.BytePut+bytePut x = Str.bytePut (name x) <> U32.bytePut (streamId x)++byteGet :: ByteGet.ByteGet ClassMapping+byteGet = ClassMapping <$> Str.byteGet <*> U32.byteGet
− src/lib/Rattletrap/Type/ClubColorsAttribute.hs
@@ -1,18 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.ClubColorsAttribute-  ( ClubColorsAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Word8le--data ClubColorsAttribute = ClubColorsAttribute-  { clubColorsAttributeBlueFlag :: Bool-  , clubColorsAttributeBlueColor :: Word8le-  , clubColorsAttributeOrangeFlag :: Bool-  , clubColorsAttributeOrangeColor :: Word8le-  } deriving (Eq, Ord, Show)--$(deriveJson ''ClubColorsAttribute)
− src/lib/Rattletrap/Type/Common.hs
@@ -1,56 +0,0 @@-module Rattletrap.Type.Common-  ( Int.Int8-  , Int.Int32-  , Int.Int64-  , Map.Map-  , Text.Text-  , Word.Word8-  , Word.Word16-  , Word.Word32-  , Word.Word64-  , deriveJson-  )-where--import qualified Data.Aeson as Json-import qualified Data.Aeson.TH as Json-import qualified Data.Char as Char-import qualified Data.Int as Int-import qualified Data.Map as Map-import qualified Data.Maybe as Maybe-import qualified Data.Text as Text-import qualified Data.Word as Word-import qualified Language.Haskell.TH as TH--deriveJson :: TH.Name -> TH.Q [TH.Dec]-deriveJson name = Json.deriveJSON (jsonOptions (TH.nameBase name)) name--jsonOptions :: String -> Json.Options-jsonOptions prefix = Json.defaultOptions-  { Json.constructorTagModifier = toSnakeCase . partialDropPrefix prefix-  , Json.fieldLabelModifier = toSnakeCase-    . partialDropPrefix (lowerFirst prefix)-  , Json.omitNothingFields = True-  , Json.sumEncoding = Json.ObjectWithSingleField-  , Json.unwrapUnaryRecords = True-  }--lowerFirst :: String -> String-lowerFirst string = case string of-  "" -> string-  first : rest -> Char.toLower first : rest--toSnakeCase :: String -> String-toSnakeCase = Json.camelTo2 '_'--partialDropPrefix :: (Eq a, Show a) => [a] -> [a] -> [a]-partialDropPrefix prefix list = Maybe.fromMaybe-  (error (unwords [show prefix, "is not a prefix of", show list]))-  (dropPrefix prefix list)--dropPrefix :: Eq a => [a] -> [a] -> Maybe [a]-dropPrefix prefix list = case prefix of-  [] -> Just list-  ph : pt -> case list of-    [] -> Nothing-    lh : lt -> if ph == lh then dropPrefix pt lt else Nothing
src/lib/Rattletrap/Type/CompressedWord.hs view
@@ -1,17 +1,86 @@-{-# LANGUAGE TemplateHaskell #-}+module Rattletrap.Type.CompressedWord where -module Rattletrap.Type.CompressedWord-  ( CompressedWord(..)-  )-where+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 Rattletrap.Type.Common+import qualified Data.Bits as Bits  -- | Although there's no guarantee that these values will not overflow, it's -- exceptionally unlikely. Most 'CompressedWord's are very small. data CompressedWord = CompressedWord-  { compressedWordLimit :: Word-  , compressedWordValue :: Word-  } deriving (Eq, Ord, Show)+  { limit :: Word+  , value :: Word+  }+  deriving (Eq, Ord, Show) -$(deriveJson ''CompressedWord)+instance Json.FromJSON CompressedWord where+  parseJSON = Json.withObject "CompressedWord" $ \object -> do+    limit <- Json.required object "limit"+    value <- Json.required object "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)+  ]++bitPut :: CompressedWord -> BitPut.BitPut+bitPut compressedWord =+  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 =+  if position < maxBits+    then do+      let x = Bits.shiftL 1 position :: Word+      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)+    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++bitGet :: Word -> BitGet.BitGet CompressedWord+bitGet limit_ = CompressedWord limit_ <$> step limit_ (getMaxBits_ limit_) 0 0++getMaxBits_ :: Word -> Word+getMaxBits_ x = do+  let+    n :: Word+    n = max 1 (ceiling (logBase (2 :: Double) (fromIntegral (max 1 x))))+  if x < 1024 && x == 2 ^ n then n + 1 else n++step :: Word -> Word -> Word -> Word -> BitGet.BitGet Word+step limit_ maxBits position value_ = do+  let x = Bits.shiftL 1 (fromIntegral position) :: Word+  if position < maxBits && value_ + x <= limit_+    then do+      bit <- BitGet.bool+      let newValue = if bit then value_ + x else value_+      step limit_ maxBits (position + 1) newValue+    else pure value_
src/lib/Rattletrap/Type/CompressedWordVector.hs view
@@ -1,17 +1,48 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.CompressedWordVector-  ( CompressedWordVector(..)-  )-where+module Rattletrap.Type.CompressedWordVector where -import Rattletrap.Type.Common-import Rattletrap.Type.CompressedWord+import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.CompressedWord as CompressedWord+import qualified Rattletrap.Utility.Json as Json  data CompressedWordVector = CompressedWordVector-  { compressedWordVectorX :: CompressedWord-  , compressedWordVectorY :: CompressedWord-  , compressedWordVectorZ :: CompressedWord-  } deriving (Eq, Ord, Show)+  { x :: CompressedWord.CompressedWord+  , y :: CompressedWord.CompressedWord+  , z :: CompressedWord.CompressedWord+  }+  deriving (Eq, Show) -$(deriveJson ''CompressedWordVector)+instance Json.FromJSON CompressedWordVector where+  parseJSON = Json.withObject "CompressedWordVector" $ \object -> do+    x <- Json.required object "x"+    y <- Json.required object "y"+    z <- Json.required object "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)+  ]++bitPut :: CompressedWordVector -> BitPut.BitPut+bitPut compressedWordVector =+  CompressedWord.bitPut (x compressedWordVector)+    <> CompressedWord.bitPut (y compressedWordVector)+    <> CompressedWord.bitPut (z compressedWordVector)++bitGet :: BitGet.BitGet CompressedWordVector+bitGet =+  CompressedWordVector+    <$> CompressedWord.bitGet limit+    <*> CompressedWord.bitGet limit+    <*> CompressedWord.bitGet limit++limit :: Word+limit = 65536
src/lib/Rattletrap/Type/Content.hs view
@@ -1,71 +1,230 @@-{-# LANGUAGE TemplateHaskell #-}+module Rattletrap.Type.Content where -module Rattletrap.Type.Content-  ( Content(..)-  , defaultContent-  )-where+import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.ByteGet as ByteGet+import qualified Rattletrap.BytePut as BytePut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.Cache as Cache+import qualified Rattletrap.Type.ClassAttributeMap as ClassAttributeMap+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.Mark as Mark+import qualified Rattletrap.Type.Message as Message+import qualified Rattletrap.Type.Str as Str+import qualified Rattletrap.Type.U32 as U32+import qualified Rattletrap.Type.U8 as U8+import qualified Rattletrap.Type.Version as Version+import Rattletrap.Utility.Bytes+import qualified Rattletrap.Utility.Json as Json -import Rattletrap.Type.Cache-import Rattletrap.Type.ClassMapping-import Rattletrap.Type.Common-import Rattletrap.Type.Frame-import Rattletrap.Type.KeyFrame-import Rattletrap.Type.List-import Rattletrap.Type.Mark-import Rattletrap.Type.Message-import Rattletrap.Type.Str-import Rattletrap.Type.Word32le+import qualified Control.Monad.Trans.State as State+import qualified Data.ByteString as Bytes+import qualified Data.ByteString.Lazy as LazyBytes+import qualified Data.Word as Word +type Content = ContentWith (List.List Frame.Frame)+ -- | Contains low-level game data about a 'Rattletrap.Replay.Replay'.-data Content = Content-  { contentLevels :: List Str+data ContentWith frames = Content+  { levels :: List.List Str.Str   -- ^ This typically only has one element, like @stadium_oob_audio_map@.-  , contentKeyFrames :: List KeyFrame+  , 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.-  , contentStreamSize :: Word32le+  , 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.-  , contentFrames :: [Frame]+  , frames :: frames   -- ^ The actual game data. This is where all the interesting information is.-  , contentMessages :: List Message+  , messages :: List.List Message.Message   -- ^ Debugging messages. In newer replays, this is always empty.-  , contentMarks :: List Mark+  , marks :: List.List Mark.Mark   -- ^ Tick marks shown on the scrubber when watching a replay.-  , contentPackages :: List Str+  , packages :: List.List Str.Str   -- ^ A list of @.upk@ files to load, like   -- @..\\..\\TAGame\\CookedPCConsole\\Stadium_P.upk@.-  , contentObjects :: List Str+  , objects :: List.List Str.Str   -- ^ Objects in the stream. Used for the   -- 'Rattletrap.Type.ClassAttributeMap.ClassAttributeMap'.-  , contentNames :: List Str+  , names :: List.List Str.Str   -- ^ It's not clear what these are used for. This list is usually not empty,   -- but appears unused otherwise.-  , contentClassMappings :: List ClassMapping+  , classMappings :: List.List ClassMapping.ClassMapping   -- ^ A mapping between classes and their ID in the stream. Used for the   -- 'Rattletrap.Type.ClassAttributeMap.ClassAttributeMap'.-  , contentCaches :: List Cache+  , caches :: List.List Cache.Cache   -- ^ A list of classes along with their parent classes and attributes. Used   -- for the 'Rattletrap.Type.ClassAttributeMap.ClassAttributeMap'.-  , contentUnknown :: [Word8]-  } deriving (Eq, Ord, Show)+  , unknown :: [Word.Word8]+  }+  deriving (Eq, Show) -$(deriveJson ''Content)+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"+    streamSize <- Json.required object "stream_size"+    frames <- Json.required object "frames"+    messages <- Json.required object "messages"+    marks <- Json.required object "marks"+    packages <- Json.required object "packages"+    objects <- Json.required object "objects"+    names <- Json.required object "names"+    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+      } -defaultContent :: Content-defaultContent = Content-  { contentLevels = List []-  , contentKeyFrames = List []-  , contentStreamSize = Word32le 0-  , contentFrames = []-  , contentMessages = List []-  , contentMarks = List []-  , contentPackages = List []-  , contentObjects = List []-  , contentNames = List []-  , contentClassMappings = List []-  , contentCaches = List []-  , contentUnknown = []+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)+  ]++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 = []   }++bytePut :: Content -> BytePut.BytePut+bytePut x =+  List.bytePut Str.bytePut (levels x)+    <> List.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)+    <> foldMap BytePut.word8 (unknown x)++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 $ Bytes.length stream+    streamSize_ = U32.fromWord32+      $ max (U32.toWord32 expectedStreamSize) (U32.toWord32 actualStreamSize)+  in U32.bytePut streamSize_ <> BytePut.byteString+    (reverseBytes (padBytes (U32.toWord32 streamSize_) stream))++byteGet+  :: Version.Version+  -- ^ Version numbers, usually from 'Rattletrap.Header.getVersion'.+  -> Int+  -- ^ The number of frames in the stream, usually from+  -- 'Rattletrap.Header.getNumFrames'.+  -> Word+  -- ^ The maximum number of channels in the stream, usually from+  -- 'Rattletrap.Header.getMaxChannels'.+  -> ByteGet.ByteGet Content+byteGet version numFrames maxChannels = do+  (levels_, keyFrames_, streamSize_) <-+    (,,)+    <$> List.byteGet Str.byteGet+    <*> List.byteGet KeyFrame.byteGet+    <*> U32.byteGet+  (stream, messages_, marks_, packages_, objects_, names_, classMappings_, caches_) <-+    (,,,,,,,)+    <$> ByteGet.byteString (fromIntegral (U32.toWord32 streamSize_))+    <*> List.byteGet Message.byteGet+    <*> List.byteGet Mark.byteGet+    <*> List.byteGet Str.byteGet+    <*> List.byteGet Str.byteGet+    <*> List.byteGet Str.byteGet+    <*> List.byteGet ClassMapping.byteGet+    <*> List.byteGet Cache.byteGet+  let+    classAttributeMap =+      ClassAttributeMap.make objects_ classMappings_ caches_ names_+    bitGet = State.evalStateT+      (Frame.decodeFramesBits version numFrames maxChannels classAttributeMap)+      mempty+  frames_ <-+    either fail pure . ByteGet.run (BitGet.toByteGet bitGet) $ reverseBytes+      stream+  Content+      levels_+      keyFrames_+      streamSize_+      frames_+      messages_+      marks_+      packages_+      objects_+      names_+      classMappings_+      caches_+    . LazyBytes.unpack+    <$> ByteGet.remaining
− src/lib/Rattletrap/Type/CustomDemolishAttribute.hs
@@ -1,18 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.CustomDemolishAttribute-  ( CustomDemolishAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.DemolishAttribute-import Rattletrap.Type.Int32le--data CustomDemolishAttribute = CustomDemolishAttribute-  { customDemolishAttributeFlag :: Bool-  , customDemolishAttributeId :: Int32le-  , customDemolishAttributeDemolish :: DemolishAttribute-  } deriving (Eq, Ord, Show)--$(deriveJson ''CustomDemolishAttribute)
− src/lib/Rattletrap/Type/DamageStateAttribute.hs
@@ -1,22 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.DamageStateAttribute-  ( DamageStateAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Int32le-import Rattletrap.Type.Vector-import Rattletrap.Type.Word8le--data DamageStateAttribute = DamageStateAttribute-  { damageStateAttributeUnknown1 :: Word8le-  , damageStateAttributeUnknown2 :: Bool-  , damageStateAttributeUnknown3 :: Int32le-  , damageStateAttributeUnknown4 :: Vector-  , damageStateAttributeUnknown5 :: Bool-  , damageStateAttributeUnknown6 :: Bool-  } deriving (Eq, Ord, Show)--$(deriveJson ''DamageStateAttribute)
− src/lib/Rattletrap/Type/DemolishAttribute.hs
@@ -1,21 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.DemolishAttribute-  ( DemolishAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Vector-import Rattletrap.Type.Word32le--data DemolishAttribute = DemolishAttribute-  { demolishAttributeAttackerFlag :: Bool-  , demolishAttributeAttackerActorId :: Word32le-  , demolishAttributeVictimFlag :: Bool-  , demolishAttributeVictimActorId :: Word32le-  , demolishAttributeAttackerVelocity :: Vector-  , demolishAttributeVictimVelocity :: Vector-  } deriving (Eq, Ord, Show)--$(deriveJson ''DemolishAttribute)
− src/lib/Rattletrap/Type/DestroyedReplication.hs
@@ -1,16 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.DestroyedReplication-  ( DestroyedReplication(..)-  )-where--import Rattletrap.Type.Common---- | Destroyed replications don't actually contain any extra information. All--- you need to know is the actor's ID, which is given by the--- 'Rattletrap.Replication.Replication'.-data DestroyedReplication = DestroyedReplication-  deriving (Eq, Ord, Show)--$(deriveJson ''DestroyedReplication)
src/lib/Rattletrap/Type/Dictionary.hs view
@@ -1,69 +1,93 @@-module Rattletrap.Type.Dictionary-  ( Dictionary(..)-  , dictionaryLookup-  )-where+module Rattletrap.Type.Dictionary where -import Rattletrap.Type.Common-import Rattletrap.Type.Str+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.Str as Str+import qualified Rattletrap.Utility.Json as Json -import qualified Control.Monad as Monad-import qualified Data.Aeson as Json-import qualified Data.Aeson.Types as Json+import qualified Data.Bifunctor as Bifunctor import qualified Data.Map as Map import qualified Data.Text as Text -data Dictionary a-  = DictionaryElement Str a (Dictionary a)-  | DictionaryEnd Str-  deriving (Eq, Ord, Show)+data Dictionary a = Dictionary+  { elements :: List.List (Str.Str, a)+  , lastKey :: Str.Str+  }+  deriving (Eq, Show)  instance Json.FromJSON a => Json.FromJSON (Dictionary a) where-  parseJSON = Json.withObject-    "Dictionary"-    (\o -> do-      keys <- get o "keys"-      lastKey <- get o "last_key"-      value <- get o "value"-      Monad.foldM-        (\d k -> case Map.lookup k value of-          Nothing -> fail (unwords ["missing key", show k])-          Just v -> pure (DictionaryElement (Str k) v d)-        )-        (DictionaryEnd lastKey)-        (reverse keys)-    )+  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+    elements_ <- build value 0 [] keys+    pure Dictionary { elements = elements_, lastKey = lastKey_ }  instance Json.ToJSON a => Json.ToJSON (Dictionary a) where-  toJSON d = Json.object-    [ pair "keys" (dictionaryKeys d)-    , pair "last_key" (dictionaryLastKey d)-    , pair "value" (dictionaryValue d)+  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     ] -dictionaryKeys :: Dictionary a -> [Str]-dictionaryKeys = fmap fst . toList--dictionaryLastKey :: Dictionary a -> Str-dictionaryLastKey x = case x of-  DictionaryElement _ _ y -> dictionaryLastKey y-  DictionaryEnd y -> y+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+      )+    ] -dictionaryLookup :: Str -> Dictionary a -> Maybe a-dictionaryLookup k x = case x of-  DictionaryElement j v y -> if k == j then Just v else dictionaryLookup k y-  DictionaryEnd _ -> Nothing+lookup :: Str.Str -> Dictionary a -> Maybe a+lookup k = Prelude.lookup k . List.toList . elements -dictionaryValue :: Dictionary a -> Map Text a-dictionaryValue = Map.mapKeys strValue . Map.fromList . toList+bytePut :: (a -> BytePut.BytePut) -> Dictionary a -> BytePut.BytePut+bytePut f x =+  foldMap (\(k, v) -> Str.bytePut k <> f v) (List.toList $ elements x)+    <> Str.bytePut (lastKey x) -get :: Json.FromJSON a => Json.Object -> String -> Json.Parser a-get o k = o Json..: Text.pack k+byteGet :: ByteGet.ByteGet a -> ByteGet.ByteGet (Dictionary a)+byteGet = byteGetWith 0 [] -pair :: Json.ToJSON a => String -> a -> (Text, Json.Value)-pair k v = (Text.pack k, Json.toJSON v)+byteGetWith+  :: Int+  -> [(Int, (Str.Str, a))]+  -> ByteGet.ByteGet a+  -> ByteGet.ByteGet (Dictionary a)+byteGetWith i xs f = do+  k <- Str.byteGet+  if isNone k+    then pure Dictionary+      { elements = List.fromList . reverse $ fmap snd xs+      , lastKey = k+      }+    else do+      v <- f+      byteGetWith (i + 1) ((i, (k, v)) : xs) f -toList :: Dictionary a -> [(Str, a)]-toList x = case x of-  DictionaryElement k v y -> (k, v) : toList y-  DictionaryEnd _ -> []+isNone :: Str.Str -> Bool+isNone = (== Text.pack "None") . Text.filter (/= '\x00') . Str.toText
− src/lib/Rattletrap/Type/EnumAttribute.hs
@@ -1,14 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.EnumAttribute-  ( EnumAttribute(..)-  )-where--import Rattletrap.Type.Common--newtype EnumAttribute = EnumAttribute-  { enumAttributeValue :: Word16-  } deriving (Eq, Ord, Show)--$(deriveJson ''EnumAttribute)
− src/lib/Rattletrap/Type/ExplosionAttribute.hs
@@ -1,18 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.ExplosionAttribute-  ( ExplosionAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Int32le-import Rattletrap.Type.Vector--data ExplosionAttribute = ExplosionAttribute-  { explosionAttributeFlag :: Bool-  , explosionAttributeActorId :: Int32le-  , explosionAttributeLocation :: Vector-  } deriving (Eq, Ord, Show)--$(deriveJson ''ExplosionAttribute)
− src/lib/Rattletrap/Type/ExtendedExplosionAttribute.hs
@@ -1,17 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.ExtendedExplosionAttribute-  ( ExtendedExplosionAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.ExplosionAttribute-import Rattletrap.Type.FlaggedIntAttribute--data ExtendedExplosionAttribute = ExtendedExplosionAttribute-  { extendedExplosionAttributeExplosion :: ExplosionAttribute-  , extendedExplosionAttributeUnknown :: FlaggedIntAttribute-  } deriving (Eq, Ord, Show)--$(deriveJson ''ExtendedExplosionAttribute)
+ src/lib/Rattletrap/Type/F32.hs view
@@ -0,0 +1,39 @@+module Rattletrap.Type.F32 where++import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.ByteGet as ByteGet+import qualified Rattletrap.BytePut as BytePut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Utility.Json as Json++newtype F32+  = F32 Float+  deriving (Eq, Show)++instance Json.FromJSON F32 where+  parseJSON = fmap fromFloat . Json.parseJSON++instance Json.ToJSON F32 where+  toJSON = Json.toJSON . toFloat++schema :: Schema.Schema+schema = Schema.named "f32" $ Json.object [Json.pair "type" "number"]++fromFloat :: Float -> F32+fromFloat = F32++toFloat :: F32 -> Float+toFloat (F32 x) = x++bytePut :: F32 -> BytePut.BytePut+bytePut = BytePut.float . toFloat++bitPut :: F32 -> BitPut.BitPut+bitPut = BitPut.fromBytePut . bytePut++byteGet :: ByteGet.ByteGet F32+byteGet = fromFloat <$> ByteGet.float++bitGet :: BitGet.BitGet F32+bitGet = BitGet.fromByteGet byteGet 4
− src/lib/Rattletrap/Type/FlaggedByteAttribute.hs
@@ -1,16 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.FlaggedByteAttribute-  ( FlaggedByteAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Word8le--data FlaggedByteAttribute = FlaggedByteAttribute-  { flaggedByteAttributeFlag :: Bool-  , flaggedByteAttributeByte :: Word8le-  } deriving (Eq, Ord, Show)--$(deriveJson ''FlaggedByteAttribute)
− src/lib/Rattletrap/Type/FlaggedIntAttribute.hs
@@ -1,16 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.FlaggedIntAttribute-  ( FlaggedIntAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Int32le--data FlaggedIntAttribute = FlaggedIntAttribute-  { flaggedIntAttributeFlag :: Bool-  , flaggedIntAttributeInt :: Int32le-  } deriving (Eq, Ord, Show)--$(deriveJson ''FlaggedIntAttribute)
− src/lib/Rattletrap/Type/Float32le.hs
@@ -1,14 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.Float32le-  ( Float32le(..)-  )-where--import Rattletrap.Type.Common--newtype Float32le = Float32le-  { float32leValue :: Float-  } deriving (Eq, Ord, Show)--$(deriveJson ''Float32le)
− src/lib/Rattletrap/Type/FloatAttribute.hs
@@ -1,15 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.FloatAttribute-  ( FloatAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Float32le--newtype FloatAttribute = FloatAttribute-  { floatAttributeValue :: Float32le-  } deriving (Eq, Ord, Show)--$(deriveJson ''FloatAttribute)
src/lib/Rattletrap/Type/Frame.hs view
@@ -1,21 +1,85 @@-{-# LANGUAGE TemplateHaskell #-}+module Rattletrap.Type.Frame where -module Rattletrap.Type.Frame-  ( Frame(..)-  )-where+import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+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.Replication as Replication+import qualified Rattletrap.Type.U32 as U32+import qualified Rattletrap.Type.Version as Version+import qualified Rattletrap.Utility.Json as Json -import Rattletrap.Type.Common-import Rattletrap.Type.Float32le-import Rattletrap.Type.Replication+import qualified Control.Monad.Trans.Class as Trans+import qualified Control.Monad.Trans.State as State+import qualified Data.Map as Map  data Frame = Frame-  { frameTime :: Float32le+  { time :: F32.F32   -- ^ Time in seconds since the beginning of the match.-  , frameDelta :: Float32le+  , delta :: F32.F32   -- ^ Time in seconds since the last frame. Usually about 0.03 since there   -- are 30 frames per second.-  , frameReplications :: [Replication]-  } deriving (Eq, Ord, Show)+  , replications :: List.List Replication.Replication+  }+  deriving (Eq, Show) -$(deriveJson ''Frame)+instance Json.FromJSON Frame where+  parseJSON = Json.withObject "Frame" $ \object -> do+    time <- Json.required object "time"+    delta <- Json.required object "delta"+    replications <- Json.required object "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+    ]++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+    )+  ]++putFrames :: List.List Frame -> BitPut.BitPut+putFrames = foldMap bitPut . List.toList++bitPut :: Frame -> BitPut.BitPut+bitPut frame =+  F32.bitPut (time frame)+    <> F32.bitPut (delta frame)+    <> Replication.putReplications (replications frame)++decodeFramesBits+  :: Version.Version+  -> Int+  -> Word+  -> ClassAttributeMap.ClassAttributeMap+  -> State.StateT+       (Map.Map CompressedWord.CompressedWord U32.U32)+       BitGet.BitGet+       (List.List Frame)+decodeFramesBits version count limit classes =+  List.replicateM count $ bitGet version limit classes++bitGet+  :: Version.Version+  -> Word+  -> ClassAttributeMap.ClassAttributeMap+  -> State.StateT+       (Map.Map CompressedWord.CompressedWord U32.U32)+       BitGet.BitGet+       Frame+bitGet version limit classes =+  Frame+    <$> Trans.lift F32.bitGet+    <*> Trans.lift F32.bitGet+    <*> Replication.decodeReplicationsBits version limit classes
− src/lib/Rattletrap/Type/GameModeAttribute.hs
@@ -1,19 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.GameModeAttribute-  ( GameModeAttribute(..)-  )-where--import Rattletrap.Type.Common--data GameModeAttribute = GameModeAttribute-  { gameModeAttributeNumBits :: 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.-  , gameModeAttributeWord :: Word8-  } deriving (Eq, Ord, Show)--$(deriveJson ''GameModeAttribute)
src/lib/Rattletrap/Type/Header.hs view
@@ -1,27 +1,26 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.Header-  ( Header(..)-  )-where+module Rattletrap.Type.Header where -import Rattletrap.Type.Common-import Rattletrap.Type.Dictionary-import Rattletrap.Type.Property-import Rattletrap.Type.Str-import Rattletrap.Type.Word32le+import qualified Rattletrap.ByteGet as ByteGet+import qualified Rattletrap.BytePut as BytePut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.Dictionary as Dictionary+import qualified Rattletrap.Type.Property as Property+import qualified Rattletrap.Type.Str as Str+import qualified Rattletrap.Type.U32 as U32+import qualified Rattletrap.Utility.Json as Json+import Rattletrap.Utility.Monad  -- | Contains high-level metadata about a 'Rattletrap.Replay.Replay'. data Header = Header-  { headerEngineVersion :: Word32le+  { engineVersion :: U32.U32   -- ^ The "major" ("engine") version number.-  , headerLicenseeVersion :: Word32le+  , licenseeVersion :: U32.U32   -- ^ The "minor" ("licensee") version number.-  , headerPatchVersion :: Maybe Word32le+  , patchVersion :: Maybe U32.U32   -- ^ The "patch" ("net") version number.-  , headerLabel :: Str+  , label :: Str.Str   -- ^ Always @TAGame.Replay_Soccar_TA@.-  , headerProperties :: Dictionary Property+  , 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:   --@@ -56,6 +55,58 @@   --   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@.-  } deriving (Eq, Ord, Show)+  }+  deriving (Eq, Show) -$(deriveJson ''Header)+instance Json.FromJSON Header where+  parseJSON = Json.withObject "Header" $ \object -> do+    engineVersion <- Json.required object "engine_version"+    licenseeVersion <- Json.required object "licensee_version"+    patchVersion <- Json.optional object "patch_version"+    label <- Json.required object "label"+    properties <- Json.required object "properties"+    pure Header+      { engineVersion+      , licenseeVersion+      , patchVersion+      , label+      , properties+      }++instance Json.ToJSON Header where+  toJSON x = Json.object+    [ Json.pair "engine_version" $ engineVersion x+    , Json.pair "licensee_version" $ licenseeVersion x+    , Json.pair "patch_version" $ patchVersion 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+    )+  ]++bytePut :: Header -> BytePut.BytePut+bytePut x =+  U32.bytePut (engineVersion x)+    <> U32.bytePut (licenseeVersion x)+    <> foldMap U32.bytePut (patchVersion x)+    <> Str.bytePut (label x)+    <> Dictionary.bytePut Property.bytePut (properties x)++byteGet :: ByteGet.ByteGet Header+byteGet = do+  (major, minor) <- (,) <$> U32.byteGet <*> U32.byteGet+  Header major minor+    <$> whenMaybe+          (U32.toWord32 major >= 868 && U32.toWord32 minor >= 18)+          U32.byteGet+    <*> Str.byteGet+    <*> Dictionary.byteGet Property.byteGet
+ src/lib/Rattletrap/Type/I32.hs view
@@ -0,0 +1,44 @@+module Rattletrap.Type.I32 where++import qualified Data.Int as Int+import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.ByteGet as ByteGet+import qualified Rattletrap.BytePut as BytePut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Utility.Json as Json++newtype I32+  = I32 Int.Int32+  deriving (Eq, Show)++instance Json.FromJSON I32 where+  parseJSON = fmap fromInt32 . Json.parseJSON++instance Json.ToJSON I32 where+  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)+  ]++fromInt32 :: Int.Int32 -> I32+fromInt32 = I32++toInt32 :: I32 -> Int.Int32+toInt32 (I32 x) = x++bytePut :: I32 -> BytePut.BytePut+bytePut = BytePut.int32 . toInt32++bitPut :: I32 -> BitPut.BitPut+bitPut = BitPut.fromBytePut . bytePut++byteGet :: ByteGet.ByteGet I32+byteGet = fromInt32 <$> ByteGet.int32++bitGet :: BitGet.BitGet I32+bitGet = BitGet.fromByteGet byteGet 4
+ src/lib/Rattletrap/Type/I64.hs view
@@ -0,0 +1,48 @@+module Rattletrap.Type.I64 where++import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.ByteGet as ByteGet+import qualified Rattletrap.BytePut as BytePut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Utility.Json as Json++import qualified Data.Int as Int+import qualified Data.Text as Text+import qualified Text.Read as Read++newtype I64+  = I64 Int.Int64+  deriving (Eq, Show)++instance Json.FromJSON I64 where+  parseJSON =+    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]+$"]++fromInt64 :: Int.Int64 -> I64+fromInt64 = I64++toInt64 :: I64 -> Int.Int64+toInt64 (I64 x) = x++bytePut :: I64 -> BytePut.BytePut+bytePut = BytePut.int64 . toInt64++bitPut :: I64 -> BitPut.BitPut+bitPut = BitPut.fromBytePut . bytePut++byteGet :: ByteGet.ByteGet I64+byteGet = fromInt64 <$> ByteGet.int64++bitGet :: BitGet.BitGet I64+bitGet = BitGet.fromByteGet byteGet 8
+ src/lib/Rattletrap/Type/I8.hs view
@@ -0,0 +1,44 @@+module Rattletrap.Type.I8 where++import qualified Data.Int as Int+import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.ByteGet as ByteGet+import qualified Rattletrap.BytePut as BytePut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Utility.Json as Json++newtype I8+  = I8 Int.Int8+  deriving (Eq, Show)++instance Json.FromJSON I8 where+  parseJSON = fmap fromInt8 . Json.parseJSON++instance Json.ToJSON I8 where+  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)+  ]++fromInt8 :: Int.Int8 -> I8+fromInt8 = I8++toInt8 :: I8 -> Int.Int8+toInt8 (I8 x) = x++bytePut :: I8 -> BytePut.BytePut+bytePut = BytePut.int8 . toInt8++bitPut :: I8 -> BitPut.BitPut+bitPut = BitPut.fromBytePut . bytePut++byteGet :: ByteGet.ByteGet I8+byteGet = fromInt8 <$> ByteGet.int8++bitGet :: BitGet.BitGet I8+bitGet = BitGet.fromByteGet byteGet 1
src/lib/Rattletrap/Type/Initialization.hs view
@@ -1,21 +1,49 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.Initialization-  ( Initialization(..)-  )-where+module Rattletrap.Type.Initialization where -import Rattletrap.Type.Common-import Rattletrap.Type.Int8Vector-import Rattletrap.Type.Vector+import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.Int8Vector as Int8Vector+import qualified Rattletrap.Type.Vector as Vector+import qualified Rattletrap.Type.Version as Version+import qualified Rattletrap.Utility.Json as Json+import Rattletrap.Utility.Monad  data Initialization = Initialization-  { initializationLocation :: Maybe Vector+  { location :: Maybe Vector.Vector   -- ^ Not every class has an initial location. See-  -- 'Rattletrap.Data.rawClassesWithLocation'.-  , initializationRotation :: Maybe Int8Vector+  -- 'Rattletrap.Data.classesWithLocation'.+  , rotation :: Maybe Int8Vector.Int8Vector   -- ^ Only classes with location can have rotation, but not every one does.-  -- See 'Rattletrap.Data.rawClassesWithRotation'.-  } deriving (Eq, Ord, Show)+  -- See 'Rattletrap.Data.classesWithRotation'.+  }+  deriving (Eq, Show) -$(deriveJson ''Initialization)+instance Json.FromJSON Initialization where+  parseJSON = Json.withObject "Initialization" $ \object -> do+    location <- Json.optional object "location"+    rotation <- Json.optional object "rotation"+    pure Initialization { location, rotation }++instance Json.ToJSON Initialization where+  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+    )+  ]++bitPut :: Initialization -> BitPut.BitPut+bitPut initialization =+  foldMap Vector.bitPut (location initialization)+    <> foldMap Int8Vector.bitPut (rotation initialization)++bitGet :: Version.Version -> Bool -> Bool -> BitGet.BitGet Initialization+bitGet version hasLocation hasRotation =+  Initialization+    <$> whenMaybe hasLocation (Vector.bitGet version)+    <*> whenMaybe hasRotation Int8Vector.bitGet
− src/lib/Rattletrap/Type/Int32le.hs
@@ -1,14 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.Int32le-  ( Int32le(..)-  )-where--import Rattletrap.Type.Common--newtype Int32le = Int32le-  { int32leValue :: Int32-  } deriving (Eq, Ord, Show)--$(deriveJson ''Int32le)
− src/lib/Rattletrap/Type/Int64Attribute.hs
@@ -1,15 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.Int64Attribute-  ( Int64Attribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Int64le--newtype Int64Attribute = Int64Attribute-  { int64AttributeValue :: Int64le-  } deriving (Eq, Ord, Show)--$(deriveJson ''Int64Attribute)
− src/lib/Rattletrap/Type/Int64le.hs
@@ -1,28 +0,0 @@-module Rattletrap.Type.Int64le-  ( Int64le(..)-  )-where--import qualified Data.Aeson as Aeson-import qualified Data.Aeson.Types as Aeson-import qualified Data.Int as Int-import qualified Data.Scientific as Scientific-import qualified Data.Text as Text-import qualified Text.Read as Read--newtype Int64le = Int64le-  { int64leValue :: Int.Int64-  } deriving (Eq, Ord, Show)--instance Aeson.FromJSON Int64le where-  parseJSON value = case value of-    Aeson.String text -> case Read.readEither $ Text.unpack text of-      Left _ -> Aeson.typeMismatch "Int64le" value-      Right int64 -> pure $ Int64le int64-    Aeson.Number number -> case Scientific.toBoundedInteger number of-      Nothing -> Aeson.typeMismatch "Int64le" value-      Just int64 -> pure $ Int64le int64-    _ -> Aeson.typeMismatch "Int64le" value--instance Aeson.ToJSON Int64le where-  toJSON = Aeson.toJSON . show . int64leValue
src/lib/Rattletrap/Type/Int8Vector.hs view
@@ -1,17 +1,53 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.Int8Vector-  ( Int8Vector(..)-  )-where+module Rattletrap.Type.Int8Vector where -import Rattletrap.Type.Common-import Rattletrap.Type.Int8le+import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.I8 as I8+import qualified Rattletrap.Utility.Json as Json+import Rattletrap.Utility.Monad  data Int8Vector = Int8Vector-  { int8VectorX :: Maybe Int8le-  , int8VectorY :: Maybe Int8le-  , int8VectorZ :: Maybe Int8le-  } deriving (Eq, Ord, Show)+  { x :: Maybe I8.I8+  , y :: Maybe I8.I8+  , z :: Maybe I8.I8+  }+  deriving (Eq, Show) -$(deriveJson ''Int8Vector)+instance Json.FromJSON Int8Vector where+  parseJSON = Json.withObject "Int8Vector" $ \object -> do+    x <- Json.optional object "x"+    y <- Json.optional object "y"+    z <- Json.optional object "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)+  ]++bitPut :: Int8Vector -> BitPut.BitPut+bitPut int8Vector =+  putInt8VectorField (x int8Vector)+    <> putInt8VectorField (y int8Vector)+    <> putInt8VectorField (z int8Vector)++putInt8VectorField :: Maybe I8.I8 -> BitPut.BitPut+putInt8VectorField maybeField = case maybeField of+  Nothing -> BitPut.bool False+  Just field -> BitPut.bool True <> I8.bitPut field++bitGet :: BitGet.BitGet Int8Vector+bitGet =+  Int8Vector <$> decodeFieldBits <*> decodeFieldBits <*> decodeFieldBits++decodeFieldBits :: BitGet.BitGet (Maybe I8.I8)+decodeFieldBits = do+  hasField <- BitGet.bool+  whenMaybe hasField I8.bitGet
− src/lib/Rattletrap/Type/Int8le.hs
@@ -1,14 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.Int8le-  ( Int8le(..)-  )-where--import Rattletrap.Type.Common--newtype Int8le = Int8le-  { int8leValue :: Int8-  } deriving (Eq, Ord, Show)--$(deriveJson ''Int8le)
− src/lib/Rattletrap/Type/IntAttribute.hs
@@ -1,15 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.IntAttribute-  ( IntAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Int32le--newtype IntAttribute = IntAttribute-  { intAttributeValue :: Int32le-  } deriving (Eq, Ord, Show)--$(deriveJson ''IntAttribute)
src/lib/Rattletrap/Type/KeyFrame.hs view
@@ -1,21 +1,46 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.KeyFrame-  ( KeyFrame(..)-  )-where+module Rattletrap.Type.KeyFrame where -import Rattletrap.Type.Common-import Rattletrap.Type.Float32le-import Rattletrap.Type.Word32le+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.Type.U32 as U32+import qualified Rattletrap.Utility.Json as Json  data KeyFrame = KeyFrame-  { keyFrameTime :: Float32le+  { time :: F32.F32   -- ^ When this key frame occurs, in seconds.-  , keyFrameFrame :: Word32le+  , frame :: U32.U32   -- ^ The frame number of this key frame, starting from 0.-  , keyFramePosition :: Word32le+  , position :: U32.U32   -- ^ The bit position of this key frame in the stream.-  } deriving (Eq, Ord, Show)+  }+  deriving (Eq, Show) -$(deriveJson ''KeyFrame)+instance Json.FromJSON KeyFrame where+  parseJSON = Json.withObject "KeyFrame" $ \object -> do+    time <- Json.required object "time"+    frame <- Json.required object "frame"+    position <- Json.required object "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+    ]++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)+  ]++bytePut :: KeyFrame -> BytePut.BytePut+bytePut x =+  F32.bytePut (time x) <> U32.bytePut (frame x) <> U32.bytePut (position x)++byteGet :: ByteGet.ByteGet KeyFrame+byteGet = KeyFrame <$> F32.byteGet <*> U32.byteGet <*> U32.byteGet
src/lib/Rattletrap/Type/List.hs view
@@ -1,14 +1,54 @@-{-# LANGUAGE TemplateHaskell #-}+module Rattletrap.Type.List where -module Rattletrap.Type.List-  ( List(..)-  )-where+import qualified Rattletrap.ByteGet as ByteGet+import qualified Rattletrap.BytePut as BytePut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.U32 as U32+import qualified Rattletrap.Utility.Json as Json -import Rattletrap.Type.Common+import qualified Control.Monad as Monad -newtype List a = List-  { listValue :: [a]-  } deriving (Eq, Ord, Show)+newtype List a+  = List [a]+  deriving (Eq, Show) -$(deriveJson ''List)+instance Json.FromJSON a => Json.FromJSON (List a) where+  parseJSON = fmap fromList . Json.parseJSON++instance Json.ToJSON a => Json.ToJSON (List a) where+  toJSON = Json.toJSON . toList++schema :: Schema.Schema -> Schema.Schema+schema = Schema.array++fromList :: [a] -> List a+fromList = List++empty :: List a+empty = fromList []++toList :: List a -> [a]+toList (List x) = x++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++byteGet :: ByteGet.ByteGet a -> ByteGet.ByteGet (List a)+byteGet f = do+  size <- U32.byteGet+  replicateM (fromIntegral $ U32.toWord32 size) f++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 f = untilMWith f 0 []++untilMWith :: Monad m => m (Maybe a) -> Int -> [(Int, a)] -> m (List a)+untilMWith f i xs = do+  m <- f+  case m of+    Nothing -> pure . fromList . reverse $ fmap snd xs+    Just x -> untilMWith f (i + 1) ((i, x) : xs)
− src/lib/Rattletrap/Type/LoadoutAttribute.hs
@@ -1,33 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.LoadoutAttribute-  ( LoadoutAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Word32le-import Rattletrap.Type.Word8le--data LoadoutAttribute = LoadoutAttribute-  { loadoutAttributeVersion :: Word8le-  , loadoutAttributeBody :: Word32le-  , loadoutAttributeDecal :: Word32le-  , loadoutAttributeWheels :: Word32le-  , loadoutAttributeRocketTrail :: Word32le-  -- ^ Now known as "rocket boost".-  , loadoutAttributeAntenna :: Word32le-  , loadoutAttributeTopper :: Word32le-  , loadoutAttributeUnknown1 :: Word32le-  , loadoutAttributeUnknown2 :: Maybe Word32le-  , loadoutAttributeEngineAudio :: Maybe Word32le-  , loadoutAttributeTrail :: Maybe Word32le-  , loadoutAttributeGoalExplosion :: Maybe Word32le-  , loadoutAttributeBanner :: Maybe Word32le-  , loadoutAttributeUnknown3 :: Maybe Word32le-  , loadoutAttributeUnknown4 :: Maybe Word32le-  , loadoutAttributeUnknown5 :: Maybe Word32le-  , loadoutAttributeUnknown6 :: Maybe Word32le-  } deriving (Eq, Ord, Show)--$(deriveJson ''LoadoutAttribute)
− src/lib/Rattletrap/Type/LoadoutOnlineAttribute.hs
@@ -1,15 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.LoadoutOnlineAttribute-  ( LoadoutOnlineAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.ProductAttribute--newtype LoadoutOnlineAttribute = LoadoutOnlineAttribute-  { loadoutAttributeValue :: [[ProductAttribute]]-  } deriving (Eq, Ord, Show)--$(deriveJson ''LoadoutOnlineAttribute)
− src/lib/Rattletrap/Type/LoadoutsAttribute.hs
@@ -1,16 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.LoadoutsAttribute-  ( LoadoutsAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.LoadoutAttribute--data LoadoutsAttribute = LoadoutsAttribute-  { loadoutsAttributeBlue :: LoadoutAttribute-  , loadoutsAttributeOrange :: LoadoutAttribute-  } deriving (Eq, Ord, Show)--$(deriveJson ''LoadoutsAttribute)
− src/lib/Rattletrap/Type/LoadoutsOnlineAttribute.hs
@@ -1,18 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.LoadoutsOnlineAttribute-  ( LoadoutsOnlineAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.LoadoutOnlineAttribute--data LoadoutsOnlineAttribute = LoadoutsOnlineAttribute-  { loadoutsOnlineAttributeBlue :: LoadoutOnlineAttribute-  , loadoutsOnlineAttributeOrange :: LoadoutOnlineAttribute-  , loadoutsOnlineAttributeUnknown1 :: Bool-  , loadoutsOnlineAttributeUnknown2 :: Bool-  } deriving (Eq, Ord, Show)--$(deriveJson ''LoadoutsOnlineAttribute)
− src/lib/Rattletrap/Type/LocationAttribute.hs
@@ -1,15 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.LocationAttribute-  ( LocationAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Vector--newtype LocationAttribute = LocationAttribute-  { locationAttributeValue :: Vector-  } deriving (Eq, Ord, Show)--$(deriveJson ''LocationAttribute)
src/lib/Rattletrap/Type/Mark.hs view
@@ -1,19 +1,38 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.Mark-  ( Mark(..)-  )-where+module Rattletrap.Type.Mark where -import Rattletrap.Type.Common-import Rattletrap.Type.Str-import Rattletrap.Type.Word32le+import qualified Rattletrap.ByteGet as ByteGet+import qualified Rattletrap.BytePut as BytePut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.Str as Str+import qualified Rattletrap.Type.U32 as U32+import qualified Rattletrap.Utility.Json as Json  data Mark = Mark-  { markValue :: Str+  { value :: Str.Str   -- ^ Which type of mark this is, like @Team0Goal@.-  , markFrame :: Word32le+  , frame :: U32.U32   -- ^ Which frame this mark belongs to, starting from 0.-  } deriving (Eq, Ord, Show)+  }+  deriving (Eq, Show) -$(deriveJson ''Mark)+instance Json.FromJSON Mark where+  parseJSON = Json.withObject "Mark" $ \object -> do+    value <- Json.required object "value"+    frame <- Json.required object "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)+  ]++bytePut :: Mark -> BytePut.BytePut+bytePut x = Str.bytePut (value x) <> U32.bytePut (frame x)++byteGet :: ByteGet.ByteGet Mark+byteGet = Mark <$> Str.byteGet <*> U32.byteGet
src/lib/Rattletrap/Type/Message.hs view
@@ -1,21 +1,49 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.Message-  ( Message(..)-  )-where+module Rattletrap.Type.Message where -import Rattletrap.Type.Common-import Rattletrap.Type.Str-import Rattletrap.Type.Word32le+import qualified Rattletrap.ByteGet as ByteGet+import qualified Rattletrap.BytePut as BytePut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.Str as Str+import qualified Rattletrap.Type.U32 as U32+import qualified Rattletrap.Utility.Json as Json  data Message = Message-  { messageFrame :: Word32le+  { frame :: U32.U32   -- ^ Which frame this message belongs to, starting from 0.-  , messageName :: Str+  , name :: Str.Str   -- ^ The primary player's name.-  , messageValue :: Str+  , value :: Str.Str   -- ^ The content of the message.-  } deriving (Eq, Ord, Show)+  }+  deriving (Eq, Show) -$(deriveJson ''Message)+instance Json.FromJSON Message where+  parseJSON = Json.withObject "Message" $ \object -> do+    frame <- Json.required object "frame"+    name <- Json.required object "name"+    value <- Json.required object "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+    ]++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)+  ]++bytePut :: Message -> BytePut.BytePut+bytePut x =+  do+      U32.bytePut (frame x)+    <> Str.bytePut (name x)+    <> Str.bytePut (value x)++byteGet :: ByteGet.ByteGet Message+byteGet = Message <$> U32.byteGet <*> Str.byteGet <*> Str.byteGet
− src/lib/Rattletrap/Type/MusicStingerAttribute.hs
@@ -1,18 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.MusicStingerAttribute-  ( MusicStingerAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Word32le-import Rattletrap.Type.Word8le--data MusicStingerAttribute = MusicStingerAttribute-  { musicStingerAttributeFlag :: Bool-  , musicStingerAttributeCue :: Word32le-  , musicStingerAttributeTrigger :: Word8le-  } deriving (Eq, Ord, Show)--$(deriveJson ''MusicStingerAttribute)
− src/lib/Rattletrap/Type/PartyLeaderAttribute.hs
@@ -1,17 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.PartyLeaderAttribute-  ( PartyLeaderAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.RemoteId-import Rattletrap.Type.Word8le--data PartyLeaderAttribute = PartyLeaderAttribute-  { partyLeaderAttributeSystemId :: Word8le-  , partyLeaderAttributeId :: Maybe (RemoteId, Word8le)-  } deriving (Eq, Ord, Show)--$(deriveJson ''PartyLeaderAttribute)
− src/lib/Rattletrap/Type/PickupAttribute.hs
@@ -1,16 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.PickupAttribute-  ( PickupAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Word32le--data PickupAttribute = PickupAttribute-  { pickupAttributeInstigatorId :: Maybe Word32le-  , pickupAttributePickedUp :: Bool-  } deriving (Eq, Ord, Show)--$(deriveJson ''PickupAttribute)
− src/lib/Rattletrap/Type/PickupAttributeNew.hs
@@ -1,17 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.PickupAttributeNew-  ( PickupAttributeNew(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Word8le-import Rattletrap.Type.Word32le--data PickupAttributeNew = PickupAttributeNew-  { pickupAttributeNewInstigatorId :: Maybe Word32le-  , pickupAttributeNewPickedUp :: Word8le-  } deriving (Eq, Ord, Show)--$(deriveJson ''PickupAttributeNew)
− src/lib/Rattletrap/Type/PlayerHistoryKeyAttribute.hs
@@ -1,14 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.PlayerHistoryKeyAttribute-  ( PlayerHistoryKeyAttribute(..)-  )-where--import Rattletrap.Type.Common--newtype PlayerHistoryKeyAttribute = PlayerHistoryKeyAttribute-  { playerHistoryKeyAttributeUnknown :: Word16-  } deriving (Eq, Ord, Show)--$(deriveJson ''PlayerHistoryKeyAttribute)
− src/lib/Rattletrap/Type/PrivateMatchSettingsAttribute.hs
@@ -1,21 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.PrivateMatchSettingsAttribute-  ( PrivateMatchSettingsAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Str-import Rattletrap.Type.Word32le--data PrivateMatchSettingsAttribute = PrivateMatchSettingsAttribute-  { privateMatchSettingsAttributeMutators :: Str-  , privateMatchSettingsAttributeJoinableBy :: Word32le-  , privateMatchSettingsAttributeMaxPlayers :: Word32le-  , privateMatchSettingsAttributeGameName :: Str-  , privateMatchSettingsAttributePassword :: Str-  , privateMatchSettingsAttributeFlag :: Bool-  } deriving (Eq, Ord, Show)--$(deriveJson ''PrivateMatchSettingsAttribute)
− src/lib/Rattletrap/Type/ProductAttribute.hs
@@ -1,35 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.ProductAttribute-  ( ProductAttribute(..)-  , ProductAttributeValue(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.CompressedWord-import Rattletrap.Type.Str-import Rattletrap.Type.Word32le--data ProductAttributeValue-  = ProductAttributeValuePaintedOld CompressedWord-  | ProductAttributeValuePaintedNew Word32-  | ProductAttributeValueTeamEditionOld CompressedWord-  | ProductAttributeValueTeamEditionNew Word32-  | ProductAttributeValueSpecialEdition Word32-  | ProductAttributeValueUserColorOld (Maybe Word32)-  | ProductAttributeValueUserColorNew Word32le-  | ProductAttributeValueTitleId Str-  deriving (Eq, Ord, Show)--$(deriveJson ''ProductAttributeValue)--data ProductAttribute = ProductAttribute-  { productAttributeUnknown :: Bool-  , productAttributeObjectId :: Word32le-  , productAttributeObjectName :: Maybe Str-  -- ^ read-only-  , productAttributeValue :: ProductAttributeValue-  } deriving (Eq, Ord, Show)--$(deriveJson ''ProductAttribute)
src/lib/Rattletrap/Type/Property.hs view
@@ -1,20 +1,49 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.Property-  ( Property(..)-  )-where+module Rattletrap.Type.Property where -import Rattletrap.Type.Common-import Rattletrap.Type.PropertyValue-import Rattletrap.Type.Str-import Rattletrap.Type.Word64le+import qualified Rattletrap.ByteGet as ByteGet+import qualified Rattletrap.BytePut as BytePut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.PropertyValue as PropertyValue+import qualified Rattletrap.Type.Str as Str+import qualified Rattletrap.Type.U64 as U64+import qualified Rattletrap.Utility.Json as Json  data Property = Property-  { propertyKind :: Str-  , propertySize :: Word64le+  { kind :: Str.Str+  , size :: U64.U64   -- ^ Not used.-  , propertyValue :: PropertyValue Property-  } deriving (Eq, Ord, Show)+  , value :: PropertyValue.PropertyValue Property+  }+  deriving (Eq, Show) -$(deriveJson ''Property)+instance Json.FromJSON Property where+  parseJSON = Json.withObject "Property" $ \object -> do+    kind <- Json.required object "kind"+    size <- Json.required object "size"+    value <- Json.required object "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+    ]++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)+  ]++bytePut :: Property -> BytePut.BytePut+bytePut x =+  Str.bytePut (kind x) <> U64.bytePut (size x) <> PropertyValue.bytePut+    bytePut+    (value x)++byteGet :: ByteGet.ByteGet Property+byteGet = do+  kind_ <- Str.byteGet+  Property kind_ <$> U64.byteGet <*> PropertyValue.byteGet byteGet kind_
src/lib/Rattletrap/Type/PropertyValue.hs view
@@ -1,32 +1,98 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.PropertyValue-  ( PropertyValue(..)-  )-where+module Rattletrap.Type.PropertyValue where -import Rattletrap.Type.Common-import Rattletrap.Type.Dictionary-import Rattletrap.Type.Float32le-import Rattletrap.Type.Int32le-import Rattletrap.Type.List-import Rattletrap.Type.Str-import Rattletrap.Type.Word64le-import Rattletrap.Type.Word8le+import qualified Data.Foldable as Foldable+import qualified Data.Text as Text+import qualified Rattletrap.ByteGet as ByteGet+import qualified Rattletrap.BytePut as BytePut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.Dictionary as Dictionary+import qualified Rattletrap.Type.F32 as F32+import qualified Rattletrap.Type.I32 as I32+import qualified Rattletrap.Type.List as List+import qualified Rattletrap.Type.Str as Str+import qualified Rattletrap.Type.U64 as U64+import qualified Rattletrap.Type.U8 as U8+import qualified Rattletrap.Utility.Json as Json+import Rattletrap.Utility.Monad  data PropertyValue a-  = PropertyValueArray (List (Dictionary a))+  = Array (List.List (Dictionary.Dictionary a))   -- ^ Yes, a list of dictionaries. No, it doesn't make sense. These usually   -- only have one element.-  | PropertyValueBool Word8le-  | PropertyValueByte Str (Maybe Str)+  | Bool U8.U8+  | Byte Str.Str (Maybe Str.Str)   -- ^ This is a strange name for essentially a key-value pair.-  | PropertyValueFloat Float32le-  | PropertyValueInt Int32le-  | PropertyValueName Str+  | Float F32.F32+  | Int I32.I32+  | Name Str.Str   -- ^ It's unclear how exactly this is different than a 'StrProperty'.-  | PropertyValueQWord Word64le-  | PropertyValueStr Str-  deriving (Eq, Ord, Show)+  | QWord U64.U64+  | Str Str.Str+  deriving (Eq, Show) -$(deriveJson ''PropertyValue)+instance Json.FromJSON a => Json.FromJSON (PropertyValue a) where+  parseJSON = Json.withObject "PropertyValue" $ \object -> Foldable.asum+    [ Array <$> Json.required object "array"+    , Bool <$> Json.required object "bool"+    , uncurry Byte <$> Json.required object "byte"+    , Float <$> Json.required object "float"+    , Int <$> Json.required object "int"+    , Name <$> Json.required object "name"+    , QWord <$> Json.required object "q_word"+    , Str <$> Json.required object "str"+    ]++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]+    Byte y z -> Json.object [Json.pair "byte" (y, z)]+    Float y -> Json.object [Json.pair "float" y]+    Int y -> Json.object [Json.pair "int" y]+    Name y -> Json.object [Json.pair "name" y]+    QWord y -> Json.object [Json.pair "q_word" y]+    Str y -> Json.object [Json.pair "str" y]++schema :: Schema.Schema -> Schema.Schema+schema s =+  Schema.named ("property-value-" <> Text.unpack (Schema.name s))+    . Schema.oneOf+    $ fmap+        (\(k, v) -> Schema.object [(Json.pair k v, True)])+        [ ("array", Schema.json . List.schema $ Dictionary.schema s)+        , ("bool", Schema.ref U8.schema)+        , ( "byte"+          , Schema.tuple+            [Schema.ref Str.schema, Schema.json $ Schema.maybe Str.schema]+          )+        , ("float", Schema.ref F32.schema)+        , ("int", Schema.ref I32.schema)+        , ("name", Schema.ref Str.schema)+        , ("q_word", Schema.ref U64.schema)+        , ("str", Schema.ref Str.schema)+        ]++bytePut :: (a -> BytePut.BytePut) -> PropertyValue a -> BytePut.BytePut+bytePut putProperty value = case value of+  Array x -> List.bytePut (Dictionary.bytePut putProperty) x+  Bool x -> U8.bytePut x+  Byte k mv -> Str.bytePut k <> foldMap Str.bytePut mv+  Float x -> F32.bytePut x+  Int x -> I32.bytePut x+  Name x -> Str.bytePut x+  QWord x -> U64.bytePut x+  Str x -> Str.bytePut x++byteGet :: ByteGet.ByteGet a -> Str.Str -> ByteGet.ByteGet (PropertyValue a)+byteGet getProperty kind = case Str.toString kind of+  "ArrayProperty" -> Array <$> List.byteGet (Dictionary.byteGet getProperty)+  "BoolProperty" -> Bool <$> U8.byteGet+  "ByteProperty" -> do+    k <- Str.byteGet+    Byte k <$> whenMaybe (Str.toString k /= "OnlinePlatform_Steam") Str.byteGet+  "FloatProperty" -> Float <$> F32.byteGet+  "IntProperty" -> Int <$> I32.byteGet+  "NameProperty" -> Name <$> Str.byteGet+  "QWordProperty" -> QWord <$> U64.byteGet+  "StrProperty" -> Str <$> Str.byteGet+  _ -> fail ("[RT07] don't know how to read property value " <> show kind)
− src/lib/Rattletrap/Type/QWordAttribute.hs
@@ -1,15 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.QWordAttribute-  ( QWordAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Word64le--newtype QWordAttribute = QWordAttribute-  { qWordAttributeValue :: Word64le-  } deriving (Eq, Ord, Show)--$(deriveJson ''QWordAttribute)
src/lib/Rattletrap/Type/Quaternion.hs view
@@ -1,79 +1,94 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.Quaternion-  ( Quaternion(..)-  , Component(..)-  , toQuaternion-  , compressPart-  , decompressPart-  , maxComponent-  , maxCompressedValue-  )-where+module Rattletrap.Type.Quaternion where -import Rattletrap.Type.Common-import Rattletrap.Type.CompressedWord+import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.CompressedWord as CompressedWord+import qualified Rattletrap.Utility.Json as Json  import qualified Data.List as List import qualified Data.Maybe as Maybe+import qualified Data.Ord as Ord  data Quaternion = Quaternion-  { quaternionX :: Double-  , quaternionY :: Double-  , quaternionZ :: Double-  , quaternionW :: Double-  } deriving (Eq, Ord, Show)+  { x :: Double+  , y :: Double+  , z :: Double+  , w :: Double+  }+  deriving (Eq, Show) -$(deriveJson ''Quaternion)+instance Json.FromJSON Quaternion where+  parseJSON = Json.withObject "Quaternion" $ \object -> do+    x <- Json.required object "x"+    y <- Json.required object "y"+    z <- Json.required object "z"+    w <- Json.required object "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+    ]++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)+  ]+ data Component-  = ComponentX-  | ComponentY-  | ComponentZ-  | ComponentW-  deriving (Eq, Ord, Show)+  = X+  | Y+  | Z+  | W+  deriving (Eq, Show)  toQuaternion :: Component -> Double -> Double -> Double -> Quaternion toQuaternion component a b c =   let d = toPart a b c   in     case component of-      ComponentX -> Quaternion d a b c-      ComponentY -> Quaternion a d b c-      ComponentZ -> Quaternion a b d c-      ComponentW -> Quaternion a b c d+      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)) -compressPart :: Double -> CompressedWord+compressPart :: Double -> CompressedWord.CompressedWord compressPart =-  CompressedWord maxCompressedValue+  CompressedWord.CompressedWord maxCompressedValue     . round     . (* wordToDouble maxCompressedValue)     . (+ 0.5)     . (/ 2.0)     . (/ maxValue) -decompressPart :: CompressedWord -> Double-decompressPart x =+decompressPart :: CompressedWord.CompressedWord -> Double+decompressPart x_ =   (* maxValue)     . (* 2.0)     . subtract 0.5-    . (/ wordToDouble (compressedWordLimit x))+    . (/ wordToDouble (CompressedWord.limit x_))     . wordToDouble-    $ compressedWordValue x+    $ CompressedWord.value x_  maxComponent :: Quaternion -> Component maxComponent quaternion =   let-    x = quaternionX quaternion-    y = quaternionY quaternion-    z = quaternionZ quaternion-    w = quaternionW quaternion-    parts =-      [(x, ComponentX), (y, ComponentY), (z, ComponentZ), (w, ComponentW)]-    biggestPart = maximum parts+    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@@ -85,6 +100,9 @@       else computedPart     ) +maximumOn :: (Foldable t, Ord b) => (a -> b) -> t a -> a+maximumOn f = List.maximumBy (Ord.comparing f)+ numBits :: Word numBits = 18 @@ -96,3 +114,48 @@  maxValue :: Double maxValue = 1.0 / sqrt 2.0++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)++putComponent :: Component -> BitPut.BitPut+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++putPart :: Double -> BitPut.BitPut+putPart = CompressedWord.bitPut . compressPart++bitGet :: BitGet.BitGet Quaternion+bitGet =+  toQuaternion <$> decodeComponent <*> decodePart <*> decodePart <*> decodePart++decodeComponent :: BitGet.BitGet Component+decodeComponent = do+  x_ <- CompressedWord.bitGet 3+  case CompressedWord.value x_ of+    0 -> pure X+    1 -> pure Y+    2 -> pure Z+    3 -> pure W+    y_ -> fail ("[RT08] invalid component: " <> show y_)++decodePart :: BitGet.BitGet Double+decodePart = decompressPart <$> CompressedWord.bitGet maxCompressedValue
src/lib/Rattletrap/Type/RemoteId.hs view
@@ -1,23 +1,135 @@-{-# LANGUAGE TemplateHaskell #-}+module Rattletrap.Type.RemoteId where -module Rattletrap.Type.RemoteId-  ( RemoteId(..)-  )-where+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.Type.U64 as U64+import qualified Rattletrap.Type.U8 as U8+import qualified Rattletrap.Type.Version as Version+import Rattletrap.Utility.Bytes+import qualified Rattletrap.Utility.Json as Json -import Rattletrap.Type.Common-import Rattletrap.Type.Str-import Rattletrap.Type.Word64le+import qualified Data.ByteString as Bytes+import qualified Data.Foldable as Foldable+import qualified Data.Text as Text+import qualified Data.Text.Encoding as Text+import qualified Data.Word as Word  data RemoteId-  = RemoteIdPlayStation Text [Word8]-  | RemoteIdPsyNet (Either Word64le (Word64le, Word64le, Word64le, Word64le))-  | RemoteIdSplitscreen Word32+  = PlayStation Text.Text [Word.Word8]+  | PsyNet (Either U64.U64 (U64.U64, U64.U64, U64.U64, U64.U64))+  | Splitscreen Word.Word32   -- ^ Really only 24 bits.-  | RemoteIdSteam Word64le-  | RemoteIdSwitch Word64le Word64le Word64le Word64le-  | RemoteIdXbox Word64le-  | RemoteIdEpic Str-  deriving (Eq, Ord, Show)+  | Steam U64.U64+  | Switch U64.U64 U64.U64 U64.U64 U64.U64+  | Xbox U64.U64+  | Epic Str.Str+  deriving (Eq, Show) -$(deriveJson ''RemoteId)+instance Json.FromJSON RemoteId where+  parseJSON = Json.withObject "RemoteId" $ \object -> Foldable.asum+    [ uncurry PlayStation <$> Json.required object "play_station"+    , PsyNet <$> Json.required object "psy_net"+    , Splitscreen <$> Json.required object "splitscreen"+    , Steam <$> Json.required object "steam"+    , uncurry4 Switch <$> Json.required object "switch"+    , Xbox <$> Json.required object "xbox"+    , Epic <$> Json.required object "epic"+    ]++uncurry4 :: (a -> b -> c -> d -> e) -> (a, b, c, d) -> e+uncurry4 f (a, b, c, d) = f a b c d++instance Json.ToJSON RemoteId where+  toJSON x = case x of+    PlayStation y z -> Json.object [Json.pair "play_station" (y, z)]+    PsyNet y -> Json.object [Json.pair "psy_net" y]+    Splitscreen y -> Json.object [Json.pair "splitscreen" y]+    Steam y -> Json.object [Json.pair "steam" y]+    Switch y z a b -> Json.object [Json.pair "switch" (y, z, a, b)]+    Xbox y -> Json.object [Json.pair "xbox" y]+    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.tuple+      [Schema.ref Schema.string, Schema.json $ Schema.array Schema.number]+    )+  , ( "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+          )+        ]+      ]+    )+  , ("splitscreen", Schema.ref Schema.integer)+  , ("steam", Schema.ref U64.schema)+  , ("switch", Schema.tuple . replicate 4 $ Schema.ref U64.schema)+  , ("xbox", Schema.ref U64.schema)+  , ("epic", Schema.ref Str.schema)+  ]++bitPut :: RemoteId -> BitPut.BitPut+bitPut remoteId = case remoteId of+  PlayStation name bytes ->+    let rawName = reverseBytes (padBytes (16 :: Int) (encodeLatin1 name))+    in BitPut.byteString rawName <> BitPut.byteString (Bytes.pack bytes)+  PsyNet e -> case e of+    Left l -> U64.bitPut l+    Right (a, b, c, d) -> putWord256 a b c d+  Splitscreen word24 -> BitPut.bits 24 word24+  Steam word64 -> U64.bitPut word64+  Switch a b c d -> putWord256 a b c d+  Xbox word64 -> U64.bitPut word64+  Epic str -> Str.bitPut str++putWord256 :: U64.U64 -> U64.U64 -> U64.U64 -> U64.U64 -> BitPut.BitPut+putWord256 a b c d =+  U64.bitPut a <> U64.bitPut b <> U64.bitPut c <> U64.bitPut d++bitGet :: Version.Version -> U8.U8 -> BitGet.BitGet RemoteId+bitGet version systemId = case U8.toWord8 systemId of+  0 -> Splitscreen <$> BitGet.bits 24+  1 -> Steam <$> U64.bitGet+  2 -> PlayStation <$> decodePsName <*> decodePsBytes version+  4 -> Xbox <$> U64.bitGet+  6 -> do+    (a, b, c, d) <- getWord256+    pure $ Switch a b c d+  7 -> if psyNetIsU64 version+    then PsyNet . Left <$> U64.bitGet+    else PsyNet . Right <$> getWord256+  11 -> Epic <$> Str.bitGet+  _ -> fail ("[RT09] unknown system id " <> show systemId)++psyNetIsU64 :: Version.Version -> Bool+psyNetIsU64 v =+  Version.major v >= 868 && Version.minor v >= 24 && Version.patch v >= 10++decodePsName :: BitGet.BitGet Text.Text+decodePsName = fmap+  (Text.dropWhileEnd (== '\x00') . Text.decodeLatin1 . reverseBytes)+  (BitGet.byteString 16)++decodePsBytes :: Version.Version -> BitGet.BitGet [Word.Word8]+decodePsBytes version = Bytes.unpack+  <$> BitGet.byteString (if playStationIsU24 version then 24 else 16)++playStationIsU24 :: Version.Version -> Bool+playStationIsU24 v =+  Version.major v >= 868 && Version.minor v >= 20 && Version.patch v >= 1++getWord256 :: BitGet.BitGet (U64.U64, U64.U64, U64.U64, U64.U64)+getWord256 = do+  a <- U64.bitGet+  b <- U64.bitGet+  c <- U64.bitGet+  d <- U64.bitGet+  pure (a, b, c, d)
src/lib/Rattletrap/Type/Replay.hs view
@@ -1,24 +1,124 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.Replay-  ( FullReplay-  , Replay(..)-  )-where+module Rattletrap.Type.Replay where -import Rattletrap.Type.Common-import Rattletrap.Type.Content-import Rattletrap.Type.Header-import Rattletrap.Type.Section+import qualified Rattletrap.ByteGet as ByteGet+import qualified Rattletrap.BytePut as BytePut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.Content as Content+import qualified Rattletrap.Type.Dictionary as Dictionary+import qualified Rattletrap.Type.Header as Header+import qualified Rattletrap.Type.I32 as I32+import qualified Rattletrap.Type.Property as Property+import qualified Rattletrap.Type.PropertyValue as PropertyValue+import qualified Rattletrap.Type.Section as Section+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+import qualified Rattletrap.Version as Version -type FullReplay = Replay Content+type Replay+  = ReplayWith+      (Section.Section Header.Header)+      (Section.Section Content.Content)  -- | A Rocket League replay.-data Replay content = Replay-  { replayHeader :: Section Header+data ReplayWith header content = Replay+  { header :: header   -- ^ This has most of the high-level metadata.-  , replayContent :: Section content+  , content :: content   -- ^ This has most of the low-level game data.-  } deriving (Eq, Ord, Show)+  }+  deriving (Eq, Show) -$(deriveJson ''Replay)+instance (Json.FromJSON h, Json.FromJSON c) => Json.FromJSON (ReplayWith h c) where+  parseJSON = Json.withObject "Replay" $ \object -> do+    header <- Json.required object "header"+    content <- Json.required object "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+    ]++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)+  ]++schemaUrl :: String+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)++byteGet :: Bool -> Bool -> ByteGet.ByteGet Replay+byteGet fast skip = do+  hs <- Section.byteGet skip $ ByteGet.byteString . fromIntegral . U32.toWord32+  h <- either fail pure . ByteGet.run Header.byteGet $ Section.body hs+  cs <- Section.byteGet skip $ ByteGet.byteString . fromIntegral . U32.toWord32+  c <- if fast+    then pure Content.empty+    else either fail pure . ByteGet.run (getContent h) $ Section.body cs+  pure Replay+    { header = hs { Section.body = h }+    , content = cs { Section.body = c }+    }++getContent :: Header.Header -> ByteGet.ByteGet Content.Content+getContent h =+  Content.byteGet (getVersion h) (getNumFrames h) (getMaxChannels h)++getVersion :: Header.Header -> Version.Version+getVersion x = Version.Version+  { Version.major = fromIntegral . U32.toWord32 $ Header.engineVersion x+  , Version.minor = fromIntegral . U32.toWord32 $ Header.licenseeVersion x+  , Version.patch = getPatchVersion x+  }++getPatchVersion :: Header.Header -> Int+getPatchVersion header_ = case Header.patchVersion header_ of+  Just version -> fromIntegral (U32.toWord32 version)+  Nothing ->+    case+        Dictionary.lookup+          (Str.fromString "MatchType")+          (Header.properties header_)+      of+      -- This is an ugly, ugly hack to handle replays from season 2 of RLCS.+      -- See `decodeSpawnedReplicationBits` and #85.+        Just Property.Property { Property.value = PropertyValue.Name str }+          | Str.toString str == "Lan" -> -1+        _ -> 0++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 numFrames)+      _ -> 0++getMaxChannels :: Header.Header -> Word+getMaxChannels header_ =+  case+      Dictionary.lookup+        (Str.fromString "MaxChannels")+        (Header.properties header_)+    of+      Just (Property.Property _ _ (PropertyValue.Int numFrames)) ->+        fromIntegral (I32.toInt32 numFrames)+      _ -> 1023
src/lib/Rattletrap/Type/Replication.hs view
@@ -1,17 +1,71 @@-{-# LANGUAGE TemplateHaskell #-}+module Rattletrap.Type.Replication where -module Rattletrap.Type.Replication-  ( Replication(..)-  )-where+import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+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.ReplicationValue as ReplicationValue+import qualified Rattletrap.Type.U32 as U32+import qualified Rattletrap.Type.Version as Version+import qualified Rattletrap.Utility.Json as Json -import Rattletrap.Type.Common-import Rattletrap.Type.CompressedWord-import Rattletrap.Type.ReplicationValue+import qualified Control.Monad.Trans.Class as Trans+import qualified Control.Monad.Trans.State as State+import qualified Data.Map as Map  data Replication = Replication-  { replicationActorId :: CompressedWord-  , replicationValue :: ReplicationValue-  } deriving (Eq, Ord, Show)+  { actorId :: CompressedWord.CompressedWord+  , value :: ReplicationValue.ReplicationValue+  }+  deriving (Eq, Show) -$(deriveJson ''Replication)+instance Json.FromJSON Replication where+  parseJSON = Json.withObject "Replication" $ \object -> do+    actorId <- Json.required object "actor_id"+    value <- Json.required object "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)+  ]++putReplications :: List.List Replication -> BitPut.BitPut+putReplications xs =+  foldMap (\x -> BitPut.bool True <> bitPut x) (List.toList xs)+    <> BitPut.bool False++bitPut :: Replication -> BitPut.BitPut+bitPut replication = CompressedWord.bitPut (actorId replication)+  <> ReplicationValue.bitPut (value replication)++decodeReplicationsBits+  :: Version.Version+  -> Word+  -> ClassAttributeMap.ClassAttributeMap+  -> State.StateT+       (Map.Map CompressedWord.CompressedWord U32.U32)+       BitGet.BitGet+       (List.List Replication)+decodeReplicationsBits version limit classes = List.untilM $ do+  p <- Trans.lift BitGet.bool+  if p then Just <$> bitGet version limit classes else pure Nothing++bitGet+  :: Version.Version+  -> Word+  -> ClassAttributeMap.ClassAttributeMap+  -> State.StateT+       (Map.Map CompressedWord.CompressedWord U32.U32)+       BitGet.BitGet+       Replication+bitGet version limit classes = do+  actor <- Trans.lift (CompressedWord.bitGet limit)+  Replication actor <$> ReplicationValue.bitGet version classes actor
+ src/lib/Rattletrap/Type/Replication/Destroyed.hs view
@@ -0,0 +1,30 @@+module Rattletrap.Type.Replication.Destroyed where++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++-- | Destroyed replications don't actually contain any extra information. All+-- you need to know is the actor's ID, which is given by the+-- 'Rattletrap.Replication.Replication'.+data Destroyed = Destroyed+  deriving (Eq, Show)++instance Json.FromJSON Destroyed where+  parseJSON json = do+    () <- Json.parseJSON json+    pure Destroyed++instance Json.ToJSON Destroyed where+  toJSON = const $ Json.toJSON ()++schema :: Schema.Schema+schema =+  Schema.named "replication-destroyed" $ Json.object [Json.pair "type" "array"]++bitPut :: Destroyed -> BitPut.BitPut+bitPut _ = mempty++bitGet :: BitGet.BitGet Destroyed+bitGet = pure Destroyed
+ src/lib/Rattletrap/Type/Replication/Spawned.hs view
@@ -0,0 +1,156 @@+module Rattletrap.Type.Replication.Spawned where++import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.ClassAttributeMap as ClassAttributeMap+import qualified Rattletrap.Type.CompressedWord as CompressedWord+import qualified Rattletrap.Type.Initialization as Initialization+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+import Rattletrap.Utility.Monad++import qualified Control.Monad.Trans.Class as Trans+import qualified Control.Monad.Trans.State as State+import qualified Data.Map as Map++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+  }+  deriving (Eq, Show)++instance Json.FromJSON Spawned where+  parseJSON = Json.withObject "Spawned" $ \object -> do+    flag <- Json.required object "flag"+    nameIndex <- Json.optional object "name_index"+    name <- Json.optional object "name"+    objectId <- Json.required object "object_id"+    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+      }++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+    ]++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)+  ]++bitPut :: Spawned -> BitPut.BitPut+bitPut spawnedReplication =+  BitPut.bool (flag spawnedReplication)+    <> foldMap U32.bitPut (nameIndex spawnedReplication)+    <> U32.bitPut (objectId spawnedReplication)+    <> Initialization.bitPut (initialization spawnedReplication)++bitGet+  :: Version.Version+  -> ClassAttributeMap.ClassAttributeMap+  -> CompressedWord.CompressedWord+  -> State.StateT+       (Map.Map CompressedWord.CompressedWord U32.U32)+       BitGet.BitGet+       Spawned+bitGet version classAttributeMap actorId = do+  flag_ <- Trans.lift BitGet.bool+  nameIndex_ <- whenMaybe (hasNameIndex version) (Trans.lift U32.bitGet)+  name_ <- either fail pure (lookupName classAttributeMap nameIndex_)+  objectId_ <- Trans.lift U32.bitGet+  State.modify (Map.insert actorId objectId_)+  objectName_ <- either+    fail+    pure+    (lookupObjectName classAttributeMap objectId_)+  className_ <- either fail pure (lookupClassName objectName_)+  let hasLocation = ClassAttributeMap.classHasLocation className_+  let hasRotation = ClassAttributeMap.classHasRotation className_+  initialization_ <- Trans.lift+    (Initialization.bitGet version hasLocation hasRotation)+  pure+    (Spawned+      flag_+      nameIndex_+      name_+      objectId_+      objectName_+      className_+      initialization_+    )++hasNameIndex :: Version.Version -> Bool+hasNameIndex v =+  Version.major v >= 868 && Version.minor v >= 14 && Version.patch v >= 0++lookupName+  :: ClassAttributeMap.ClassAttributeMap+  -> Maybe U32.U32+  -> Either String (Maybe Str.Str)+lookupName classAttributeMap maybeNameIndex = case maybeNameIndex of+  Nothing -> Right Nothing+  Just nameIndex_ ->+    case+        ClassAttributeMap.getName+          (ClassAttributeMap.nameMap classAttributeMap)+          nameIndex_+      of+        Nothing ->+          Left ("[RT11] could not get name for index " <> show nameIndex_)+        Just name_ -> Right (Just name_)++lookupObjectName+  :: ClassAttributeMap.ClassAttributeMap -> U32.U32 -> Either String Str.Str+lookupObjectName classAttributeMap objectId_ =+  case+      ClassAttributeMap.getObjectName+        (ClassAttributeMap.objectMap classAttributeMap)+        objectId_+    of+      Nothing ->+        Left ("[RT12] could not get object name for id " <> show objectId_)+      Just objectName_ -> Right objectName_++lookupClassName :: Str.Str -> Either String Str.Str+lookupClassName objectName_ =+  case ClassAttributeMap.getClassName objectName_ of+    Nothing ->+      Left ("[RT13] could not get class name for object " <> show objectName_)+    Just className_ -> Right className_
+ src/lib/Rattletrap/Type/Replication/Updated.hs view
@@ -0,0 +1,47 @@+module Rattletrap.Type.Replication.Updated where++import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+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.U32 as U32+import qualified Rattletrap.Type.Version as Version+import qualified Rattletrap.Utility.Json as Json++import qualified Data.Map as Map++newtype Updated = Updated+  { attributes :: List.List Attribute.Attribute+  } deriving (Eq, Show)++instance Json.FromJSON Updated where+  parseJSON = fmap Updated . Json.parseJSON++instance Json.ToJSON Updated where+  toJSON = Json.toJSON . attributes++schema :: Schema.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)+    <> BitPut.bool False++bitGet+  :: Version.Version+  -> ClassAttributeMap.ClassAttributeMap+  -> Map.Map CompressedWord.CompressedWord U32.U32+  -> CompressedWord.CompressedWord+  -> BitGet.BitGet Updated+bitGet version classes actors actor = fmap Updated . List.untilM $ do+  p <- BitGet.bool+  if p+    then Just <$> Attribute.bitGet version classes actors actor+    else pure Nothing
src/lib/Rattletrap/Type/ReplicationValue.hs view
@@ -1,22 +1,74 @@-{-# LANGUAGE TemplateHaskell #-}+module Rattletrap.Type.ReplicationValue where -module Rattletrap.Type.ReplicationValue-  ( ReplicationValue(..)-  )-where+import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.ClassAttributeMap as ClassAttributeMap+import qualified Rattletrap.Type.CompressedWord as CompressedWord+import qualified Rattletrap.Type.Replication.Destroyed as Destroyed+import qualified Rattletrap.Type.Replication.Spawned as Spawned+import qualified Rattletrap.Type.Replication.Updated as Updated+import qualified Rattletrap.Type.U32 as U32+import qualified Rattletrap.Type.Version as Version+import qualified Rattletrap.Utility.Json as Json -import Rattletrap.Type.Common-import Rattletrap.Type.DestroyedReplication-import Rattletrap.Type.SpawnedReplication-import Rattletrap.Type.UpdatedReplication+import qualified Control.Monad.Trans.Class as Trans+import qualified Control.Monad.Trans.State as State+import qualified Data.Foldable as Foldable+import qualified Data.Map as Map  data ReplicationValue-  = ReplicationValueSpawned SpawnedReplication+  = Spawned Spawned.Spawned   -- ^ Creates a new actor.-  | ReplicationValueUpdated UpdatedReplication+  | Updated Updated.Updated   -- ^ Updates an existing actor.-  | ReplicationValueDestroyed DestroyedReplication+  | Destroyed Destroyed.Destroyed   -- ^ Destroys an existing actor.-  deriving (Eq, Ord, Show)+  deriving (Eq, Show) -$(deriveJson ''ReplicationValue)+instance Json.FromJSON ReplicationValue where+  parseJSON = Json.withObject "ReplicationValue" $ \object -> Foldable.asum+    [ Spawned <$> Json.required object "spawned"+    , Updated <$> Json.required object "updated"+    , Destroyed <$> Json.required object "destroyed"+    ]++instance Json.ToJSON ReplicationValue where+  toJSON x = case x of+    Spawned y -> Json.object [Json.pair "spawned" y]+    Updated y -> Json.object [Json.pair "updated" y]+    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)+  ]++bitPut :: ReplicationValue -> BitPut.BitPut+bitPut value = case value of+  Spawned x -> BitPut.bool True <> BitPut.bool True <> Spawned.bitPut x+  Updated x -> BitPut.bool True <> BitPut.bool False <> Updated.bitPut x+  Destroyed x -> BitPut.bool False <> Destroyed.bitPut x++bitGet+  :: Version.Version+  -> ClassAttributeMap.ClassAttributeMap+  -> CompressedWord.CompressedWord+  -> State.StateT+       (Map.Map CompressedWord.CompressedWord U32.U32)+       BitGet.BitGet+       ReplicationValue+bitGet version classAttributeMap actorId = do+  actorMap <- State.get+  isOpen <- Trans.lift BitGet.bool+  if isOpen+    then do+      isNew <- Trans.lift BitGet.bool+      if isNew+        then Spawned <$> Spawned.bitGet version classAttributeMap actorId+        else Updated <$> Trans.lift+          (Updated.bitGet version classAttributeMap actorMap actorId)+    else Destroyed <$> Trans.lift Destroyed.bitGet
− src/lib/Rattletrap/Type/ReservationAttribute.hs
@@ -1,22 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.ReservationAttribute-  ( ReservationAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.CompressedWord-import Rattletrap.Type.Str-import Rattletrap.Type.UniqueIdAttribute--data ReservationAttribute = ReservationAttribute-  { reservationAttributeNumber :: CompressedWord-  , reservationAttributeUniqueId :: UniqueIdAttribute-  , reservationAttributeName :: Maybe Str-  , reservationAttributeUnknown1 :: Bool-  , reservationAttributeUnknown2 :: Bool-  , reservationAttributeUnknown3 :: Maybe Word8-  } deriving (Eq, Ord, Show)--$(deriveJson ''ReservationAttribute)
− src/lib/Rattletrap/Type/RigidBodyStateAttribute.hs
@@ -1,20 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.RigidBodyStateAttribute-  ( RigidBodyStateAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Rotation-import Rattletrap.Type.Vector--data RigidBodyStateAttribute = RigidBodyStateAttribute-  { rigidBodyStateAttributeSleeping :: Bool-  , rigidBodyStateAttributeLocation :: Vector-  , rigidBodyStateAttributeRotation :: Rotation-  , rigidBodyStateAttributeLinearVelocity :: Maybe Vector-  , rigidBodyStateAttributeAngularVelocity :: Maybe Vector-  } deriving (Eq, Ord, Show)--$(deriveJson ''RigidBodyStateAttribute)
src/lib/Rattletrap/Type/Rotation.hs view
@@ -1,17 +1,48 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.Rotation-  ( Rotation(..)-  )-where+module Rattletrap.Type.Rotation where -import Rattletrap.Type.Common-import Rattletrap.Type.Quaternion-import Rattletrap.Type.CompressedWordVector+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.CompressedWordVector as CompressedWordVector+import qualified Rattletrap.Type.Quaternion as Quaternion+import qualified Rattletrap.Type.Version as Version+import qualified Rattletrap.Utility.Json as Json  data Rotation-  = RotationCompressedWordVector CompressedWordVector-  | RotationQuaternion Quaternion-  deriving (Eq, Ord, Show)+  = CompressedWordVector CompressedWordVector.CompressedWordVector+  | Quaternion Quaternion.Quaternion+  deriving (Eq, Show) -$(deriveJson ''Rotation)+instance Json.FromJSON Rotation where+  parseJSON = Json.withObject "Rotation" $ \object -> Foldable.asum+    [ CompressedWordVector <$> Json.required object "compressed_word_vector"+    , Quaternion <$> Json.required object "quaternion"+    ]++instance Json.ToJSON Rotation where+  toJSON x = case x of+    CompressedWordVector y ->+      Json.object [Json.pair "compressed_word_vector" y]+    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)+  ]++bitPut :: Rotation -> BitPut.BitPut+bitPut r = case r of+  CompressedWordVector cwv -> CompressedWordVector.bitPut cwv+  Quaternion q -> Quaternion.bitPut q++bitGet :: Version.Version -> BitGet.BitGet Rotation+bitGet version = if isQuaternion version+  then Quaternion <$> Quaternion.bitGet+  else CompressedWordVector <$> CompressedWordVector.bitGet++isQuaternion :: Version.Version -> Bool+isQuaternion v =+  Version.major v >= 868 && Version.minor v >= 22 && Version.patch v >= 7
src/lib/Rattletrap/Type/Section.hs view
@@ -1,41 +1,91 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.Section-  ( Section(..)-  , toSection-  )-where+module Rattletrap.Type.Section where -import Rattletrap.Type.Common-import Rattletrap.Type.Word32le-import Rattletrap.Utility.Crc+import qualified Rattletrap.ByteGet as ByteGet+import qualified Rattletrap.BytePut as BytePut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.U32 as U32+import qualified Rattletrap.Utility.Crc as Crc+import qualified Rattletrap.Utility.Json as Json -import qualified Data.Binary as Binary-import qualified Data.Binary.Put as Binary+import qualified Control.Monad as Monad import qualified Data.ByteString as Bytes-import qualified Data.ByteString.Lazy as LazyBytes+import qualified Data.Text as Text  -- | A section is a large piece of a 'Rattletrap.Replay.Replay'. It has a -- 32-bit size (in bytes), a 32-bit CRC (see "Rattletrap.Utility.Crc"), and then a -- 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-  { sectionSize :: Word32le+  { size :: U32.U32   -- ^ read only-  , sectionCrc :: Word32le+  , crc :: U32.U32   -- ^ read only-  , sectionBody :: a+  , body :: a   -- ^ The actual content in the section.-  } deriving (Eq, Ord, Show)+  }+  deriving (Eq, Show) -$(deriveJson ''Section)+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 } -toSection :: (a -> Binary.Put) -> a -> Section a-toSection encode body =-  let bytes = LazyBytes.toStrict . Binary.runPut $ encode 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+    ]++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)+    ]++create :: (a -> BytePut.BytePut) -> a -> Section a+create encode body_ =+  let bytes = BytePut.toByteString $ encode body_   in     Section-      { sectionSize = Word32le . fromIntegral $ Bytes.length bytes-      , sectionCrc = Word32le $ getCrc32 bytes-      , sectionBody = body+      { size = U32.fromWord32 . fromIntegral $ Bytes.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_ = Bytes.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 skip getBody = do+  size_ <- U32.byteGet+  crc_ <- U32.byteGet+  rawBody <- ByteGet.byteString (fromIntegral (U32.toWord32 size_))+  Monad.unless skip $ do+    let actualCrc = U32.fromWord32 (Crc.compute rawBody)+    Monad.when (actualCrc /= crc_) (fail (crcMessage actualCrc crc_))+  body_ <- either fail pure $ ByteGet.run (getBody size_) rawBody+  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+  ]
− src/lib/Rattletrap/Type/SpawnedReplication.hs
@@ -1,30 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.SpawnedReplication-  ( SpawnedReplication(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Initialization-import Rattletrap.Type.Str-import Rattletrap.Type.Word32le--data SpawnedReplication = SpawnedReplication-  { spawnedReplicationFlag :: Bool-  -- ^ Unclear what this is.-  , spawnedReplicationNameIndex :: Maybe Word32le-  , spawnedReplicationName :: Maybe Str-  -- ^ Read-only! Changing a replication's name requires editing the-  -- 'spawnedReplicationNameIndex' and maybe the class attribute map.-  , spawnedReplicationObjectId :: Word32le-  , spawnedReplicationObjectName :: Str-  -- ^ Read-only! Changing a replication's object requires editing the class-  -- attribute map.-  , spawnedReplicationClassName :: Str-  -- ^ Read-only! Changing a replication's class requires editing the class-  -- attribute map.-  , spawnedReplicationInitialization :: Initialization-  } deriving (Eq, Ord, Show)--$(deriveJson ''SpawnedReplication)
− src/lib/Rattletrap/Type/StatEventAttribute.hs
@@ -1,16 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.StatEventAttribute-  ( StatEventAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Int32le--data StatEventAttribute = StatEventAttribute-  { statEventAttributeUnknown :: Bool-  , statEventAttributeObjectId :: Int32le-  } deriving (Eq, Ord, Show)--$(deriveJson ''StatEventAttribute)
src/lib/Rattletrap/Type/Str.hs view
@@ -1,24 +1,103 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.Str-  ( Str(..)-  , toStr-  , fromStr-  )-where+module Rattletrap.Type.Str where -import Rattletrap.Type.Common+import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+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 Rattletrap.Utility.Bytes+import qualified Rattletrap.Utility.Json as Json +import qualified Data.ByteString as Bytes+import qualified Data.Char as Char+import qualified Data.Int as Int import qualified Data.Text as Text+import qualified Data.Text.Encoding as Text+import qualified Data.Text.Encoding.Error as Text+import qualified Debug.Trace as Debug -newtype Str = Str-  { strValue :: Text-  } deriving (Eq, Ord, Show)+newtype Str+  = Str Text.Text+  deriving (Eq, Ord, Show) -$(deriveJson ''Str)+instance Json.FromJSON Str where+  parseJSON = fmap fromText . Json.parseJSON -toStr :: String -> Str-toStr string = Str (Text.pack string)+instance Json.ToJSON Str where+  toJSON = Json.toJSON . toText -fromStr :: Str -> String-fromStr text = Text.unpack (strValue text)+schema :: Schema.Schema+schema = Schema.named "str" $ Json.object [Json.pair "type" "string"]++fromText :: Text.Text -> Str+fromText = Str++toText :: Str -> Text.Text+toText (Str x) = x++fromString :: String -> Str+fromString = fromText . Text.pack++toString :: Str -> String+toString = Text.unpack . toText++bytePut :: Str -> BytePut.BytePut+bytePut 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++getTextEncoder :: I32.I32 -> Text.Text -> Bytes.ByteString+getTextEncoder size text =+  if I32.toInt32 size < 0 then Text.encodeUtf16LE text else encodeLatin1 text++addNull :: Text.Text -> Text.Text+addNull text = if Text.null text then text else Text.snoc text '\x00'++byteGet :: ByteGet.ByteGet Str+byteGet = do+  rawSize <- I32.byteGet+  bytes <- ByteGet.byteString (normalizeTextSize rawSize)+  pure (fromText (dropNull (getTextDecoder rawSize bytes)))++bitGet :: BitGet.BitGet Str+bitGet = do+  rawSize <- I32.bitGet+  bytes <- BitGet.byteString (normalizeTextSize rawSize)+  pure (fromText (dropNull (getTextDecoder rawSize (reverseBytes bytes))))++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 -> Bytes.ByteString -> Text.Text+getTextDecoder size bytes =+  let+    decode = if I32.toInt32 size < 0+      then Text.decodeUtf16LEWith $ \message input -> do+        Debug.traceM $ "WARNING: " <> show (Text.DecodeError message input)+        Text.lenientDecode message input+      else Text.decodeLatin1+  in decode bytes++dropNull :: Text.Text -> Text.Text+dropNull = Text.dropWhileEnd (== '\x00')
− src/lib/Rattletrap/Type/StringAttribute.hs
@@ -1,15 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.StringAttribute-  ( StringAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Str--newtype StringAttribute = StringAttribute-  { stringAttributeValue :: Str-  } deriving (Eq, Ord, Show)--$(deriveJson ''StringAttribute)
− src/lib/Rattletrap/Type/TeamPaintAttribute.hs
@@ -1,20 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.TeamPaintAttribute-  ( TeamPaintAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Word32le-import Rattletrap.Type.Word8le--data TeamPaintAttribute = TeamPaintAttribute-  { teamPaintAttributeTeam :: Word8le-  , teamPaintAttributePrimaryColor :: Word8le-  , teamPaintAttributeAccentColor :: Word8le-  , teamPaintAttributePrimaryFinish :: Word32le-  , teamPaintAttributeAccentFinish :: Word32le-  } deriving (Eq, Ord, Show)--$(deriveJson ''TeamPaintAttribute)
− src/lib/Rattletrap/Type/TitleAttribute.hs
@@ -1,22 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.TitleAttribute-  ( TitleAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Word32le--data TitleAttribute = TitleAttribute-  { titleAttributeUnknown1 :: Bool-  , titleAttributeUnknown2 :: Bool-  , titleAttributeUnknown3 :: Word32le-  , titleAttributeUnknown4 :: Word32le-  , titleAttributeUnknown5 :: Word32le-  , titleAttributeUnknown6 :: Word32le-  , titleAttributeUnknown7 :: Word32le-  , titleAttributeUnknown8 :: Bool-  } deriving (Eq, Ord, Show)--$(deriveJson ''TitleAttribute)
+ src/lib/Rattletrap/Type/U32.hs view
@@ -0,0 +1,44 @@+module Rattletrap.Type.U32 where++import qualified Data.Word as Word+import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.ByteGet as ByteGet+import qualified Rattletrap.BytePut as BytePut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Utility.Json as Json++newtype U32+  = U32 Word.Word32+  deriving (Eq, Ord, Show)++instance Json.FromJSON U32 where+  parseJSON = fmap fromWord32 . Json.parseJSON++instance Json.ToJSON U32 where+  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)+  ]++fromWord32 :: Word.Word32 -> U32+fromWord32 = U32++toWord32 :: U32 -> Word.Word32+toWord32 (U32 x) = x++bytePut :: U32 -> BytePut.BytePut+bytePut = BytePut.word32 . toWord32++bitPut :: U32 -> BitPut.BitPut+bitPut = BitPut.fromBytePut . bytePut++byteGet :: ByteGet.ByteGet U32+byteGet = fromWord32 <$> ByteGet.word32++bitGet :: BitGet.BitGet U32+bitGet = BitGet.fromByteGet byteGet 4
+ src/lib/Rattletrap/Type/U64.hs view
@@ -0,0 +1,48 @@+module Rattletrap.Type.U64 where++import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.ByteGet as ByteGet+import qualified Rattletrap.BytePut as BytePut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Utility.Json as Json++import qualified Data.Text as Text+import qualified Data.Word as Word+import qualified Text.Read as Read++newtype U64+  = U64 Word.Word64+  deriving (Eq, Show)++instance Json.FromJSON U64 where+  parseJSON =+    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]+$"]++fromWord64 :: Word.Word64 -> U64+fromWord64 = U64++toWord64 :: U64 -> Word.Word64+toWord64 (U64 x) = x++bytePut :: U64 -> BytePut.BytePut+bytePut = BytePut.word64 . toWord64++bitPut :: U64 -> BitPut.BitPut+bitPut = BitPut.fromBytePut . bytePut++byteGet :: ByteGet.ByteGet U64+byteGet = fromWord64 <$> ByteGet.word64++bitGet :: BitGet.BitGet U64+bitGet = BitGet.fromByteGet byteGet 8
+ src/lib/Rattletrap/Type/U8.hs view
@@ -0,0 +1,44 @@+module Rattletrap.Type.U8 where++import qualified Data.Word as Word+import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.ByteGet as ByteGet+import qualified Rattletrap.BytePut as BytePut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Utility.Json as Json++newtype U8+  = U8 Word.Word8+  deriving (Eq, Show)++instance Json.FromJSON U8 where+  parseJSON = fmap fromWord8 . Json.parseJSON++instance Json.ToJSON U8 where+  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)+  ]++fromWord8 :: Word.Word8 -> U8+fromWord8 = U8++toWord8 :: U8 -> Word.Word8+toWord8 (U8 x) = x++bytePut :: U8 -> BytePut.BytePut+bytePut = BytePut.word8 . toWord8++bitPut :: U8 -> BitPut.BitPut+bitPut = BitPut.fromBytePut . bytePut++byteGet :: ByteGet.ByteGet U8+byteGet = fromWord8 <$> ByteGet.word8++bitGet :: BitGet.BitGet U8+bitGet = BitGet.fromByteGet byteGet 1
− src/lib/Rattletrap/Type/UniqueIdAttribute.hs
@@ -1,18 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.UniqueIdAttribute-  ( UniqueIdAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.RemoteId-import Rattletrap.Type.Word8le--data UniqueIdAttribute = UniqueIdAttribute-  { uniqueIdAttributeSystemId :: Word8le-  , uniqueIdAttributeRemoteId :: RemoteId-  , uniqueIdAttributeLocalId :: Word8le-  } deriving (Eq, Ord, Show)--$(deriveJson ''UniqueIdAttribute)
− src/lib/Rattletrap/Type/UpdatedReplication.hs
@@ -1,15 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.UpdatedReplication-  ( UpdatedReplication(..)-  )-where--import Rattletrap.Type.Attribute-import Rattletrap.Type.Common--newtype UpdatedReplication = UpdatedReplication-  { updatedReplicationAttributes :: [Attribute]-  } deriving (Eq, Ord, Show)--$(deriveJson ''UpdatedReplication)
src/lib/Rattletrap/Type/Vector.hs view
@@ -1,26 +1,91 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.Vector-  ( Vector(..)-  )-where+module Rattletrap.Type.Vector where -import Rattletrap.Type.Common-import Rattletrap.Type.CompressedWord+import qualified Rattletrap.BitGet as BitGet+import qualified Rattletrap.BitPut as BitPut+import qualified Rattletrap.Schema as Schema+import qualified Rattletrap.Type.CompressedWord as CompressedWord+import qualified Rattletrap.Type.Version as Version+import qualified Rattletrap.Utility.Json as Json  data Vector = Vector-  { vectorSize :: CompressedWord-  , vectorBias :: Word+  { 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.-  , vectorX :: Int-  -- ^ See 'vectorBias'.-  , vectorY :: Int-  -- ^ See 'vectorBias'.-  , vectorZ :: Int-  -- ^ See 'vectorBias'.-  } deriving (Eq, Ord, Show)+  , x :: Int+  -- ^ See 'bias'.+  , y :: Int+  -- ^ See 'bias'.+  , z :: Int+  -- ^ See 'bias'.+  }+  deriving (Eq, Show) -$(deriveJson ''Vector)+instance Json.FromJSON Vector where+  parseJSON = Json.withObject "Vector" $ \object -> do+    size <- Json.required object "size"+    bias <- Json.required object "bias"+    x <- Json.required object "x"+    y <- Json.required object "y"+    z <- Json.required object "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+    ]++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)+  ]++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)++bitGet :: Version.Version -> BitGet.BitGet Vector+bitGet version = do+  size_ <- CompressedWord.bitGet (if has21Bits version then 21 else 19)+  let+    limit = getLimit size_+    bias_ = getBias size_+  Vector size_ bias_+    <$> fmap (fromDelta bias_) (CompressedWord.bitGet limit)+    <*> fmap (fromDelta bias_) (CompressedWord.bitGet limit)+    <*> fmap (fromDelta bias_) (CompressedWord.bitGet limit)++has21Bits :: Version.Version -> Bool+has21Bits v =+  Version.major v >= 868 && Version.minor v >= 22 && Version.patch v >= 7++getLimit :: CompressedWord.CompressedWord -> Word+getLimit = (2 ^) . (+ 2) . CompressedWord.value++getBias :: CompressedWord.CompressedWord -> Word+getBias = (2 ^) . (+ 1) . CompressedWord.value++fromDelta :: Word -> CompressedWord.CompressedWord -> Int+fromDelta bias_ x_ =+  fromIntegral (CompressedWord.value x_) - fromIntegral bias_
+ src/lib/Rattletrap/Type/Version.hs view
@@ -0,0 +1,8 @@+module Rattletrap.Type.Version where++data Version = Version+  { major :: Int+  , minor :: Int+  , patch :: Int+  }+  deriving (Eq, Show)
− src/lib/Rattletrap/Type/WeldedInfoAttribute.hs
@@ -1,22 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.WeldedInfoAttribute-  ( WeldedInfoAttribute(..)-  )-where--import Rattletrap.Type.Common-import Rattletrap.Type.Float32le-import Rattletrap.Type.Int32le-import Rattletrap.Type.Int8Vector-import Rattletrap.Type.Vector--data WeldedInfoAttribute = WeldedInfoAttribute-  { weldedInfoAttributeActive :: Bool-  , weldedInfoAttributeActorId :: Int32le-  , weldedInfoAttributeOffset :: Vector-  , weldedInfoAttributeMass :: Float32le-  , weldedInfoAttributeRotation :: Int8Vector-  } deriving (Eq, Ord, Show)--$(deriveJson ''WeldedInfoAttribute)
− src/lib/Rattletrap/Type/Word32le.hs
@@ -1,14 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.Word32le-  ( Word32le(..)-  )-where--import Rattletrap.Type.Common--newtype Word32le = Word32le-  { word32leValue :: Word32-  } deriving (Eq, Ord, Show)--$(deriveJson ''Word32le)
− src/lib/Rattletrap/Type/Word64le.hs
@@ -1,28 +0,0 @@-module Rattletrap.Type.Word64le-  ( Word64le(..)-  )-where--import qualified Data.Aeson as Aeson-import qualified Data.Aeson.Types as Aeson-import qualified Data.Scientific as Scientific-import qualified Data.Text as Text-import qualified Data.Word as Word-import qualified Text.Read as Read--newtype Word64le = Word64le-  { word64leValue :: Word.Word64-  } deriving (Eq, Ord, Show)--instance Aeson.FromJSON Word64le where-  parseJSON value = case value of-    Aeson.String text -> case Read.readEither $ Text.unpack text of-      Left _ -> Aeson.typeMismatch "Word64le" value-      Right word64 -> pure $ Word64le word64-    Aeson.Number number -> case Scientific.toBoundedInteger number of-      Nothing -> Aeson.typeMismatch "Word64le" value-      Just word64 -> pure $ Word64le word64-    _ -> Aeson.typeMismatch "Word64le" value--instance Aeson.ToJSON Word64le where-  toJSON = Aeson.toJSON . show . word64leValue
− src/lib/Rattletrap/Type/Word8le.hs
@@ -1,14 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Rattletrap.Type.Word8le-  ( Word8le(..)-  )-where--import Rattletrap.Type.Common--newtype Word8le = Word8le-  { word8leValue :: Word8-  } deriving (Eq, Ord, Show)--$(deriveJson ''Word8le)
src/lib/Rattletrap/Utility/Bytes.hs view
@@ -2,8 +2,7 @@   ( encodeLatin1   , padBytes   , reverseBytes-  )-where+  ) where  import qualified Data.Bits as Bits import qualified Data.ByteString as Bytes
src/lib/Rattletrap/Utility/Crc.hs view
@@ -1,47 +1,295 @@ module Rattletrap.Utility.Crc-  ( getCrc32-  )-where--import Rattletrap.Data+  ( compute+  ) where +import qualified Data.Array.Unboxed as Array import qualified Data.Bits as Bits import qualified Data.ByteString as Bytes-import qualified Data.IntMap as IntMap import qualified Data.Word as Word  -- | Computes the CRC32 of some bytes. This is done to ensure that the bytes -- are valid before trying to parse them. -- -- @--- getCrc32 ('Data.ByteString.Lazy.pack' [0x00])+-- compute ('Data.ByteString.Lazy.pack' [0x00]) -- @ -- -- This CRC uses an initial value of @0xefcbf201@ and a polynomial of -- @0x04c11db7@.-getCrc32 :: Bytes.ByteString -> Word.Word32-getCrc32 bytes = do-  let-    update = crc32Update crc32Table-    initial = Bits.complement crc32Initial-    crc = Bytes.foldl update initial bytes-  Bits.complement crc+compute :: Bytes.ByteString -> Word.Word32+compute = Bits.complement . Bytes.foldl' update initial -crc32Update-  :: IntMap.IntMap Word.Word32 -> Word.Word32 -> Word.Word8 -> Word.Word32-crc32Update table crc byte = do+update :: Word.Word32 -> Word.Word8 -> Word.Word32+update crc byte =   let-    toWord8 :: (Integral a) => a -> Word.Word8-    toWord8 = fromIntegral-    toInt :: (Integral a) => a -> Int-    toInt = fromIntegral-    index = toInt (Bits.xor byte (toWord8 (Bits.shiftR crc 24)))-    left = table IntMap.! index+    index = Bits.xor byte . unsafeWord32ToWord8 $ Bits.shiftR crc 24+    left = table Array.! index     right = Bits.shiftL crc 8-  Bits.xor left right+  in Bits.xor left right -crc32Initial :: Word.Word32-crc32Initial = 0xefcbf201+unsafeWord32ToWord8 :: Word.Word32 -> Word.Word8+unsafeWord32ToWord8 = fromIntegral -crc32Table :: IntMap.IntMap Word.Word32-crc32Table = IntMap.fromDistinctAscList (zip [0 ..] rawCrc32Table)+initial :: Word.Word32+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+  ]
src/lib/Rattletrap/Utility/Helper.hs view
@@ -5,42 +5,41 @@   , encodeReplayJson   , decodeReplayJson   , encodeReplayFile-  )-where+  ) where -import Rattletrap.Decode.Common-import Rattletrap.Encode.Content-import Rattletrap.Decode.Replay-import Rattletrap.Encode.Replay-import Rattletrap.Type.Replay-import Rattletrap.Type.Section-import Rattletrap.Type.Content+import qualified Rattletrap.ByteGet as ByteGet+import qualified Rattletrap.BytePut as BytePut+import qualified Rattletrap.Type.Content as Content+import qualified Rattletrap.Type.Replay as Replay+import qualified Rattletrap.Type.Section as Section -import qualified Data.Aeson as Json-import qualified Data.Aeson.Encode.Pretty as Json-import qualified Data.Binary.Put as Binary+import qualified Data.Aeson as Aeson+import qualified Data.Aeson.Encode.Pretty as Aeson import qualified Data.ByteString as Bytes import qualified Data.ByteString.Lazy as LazyBytes  -- | Parses a raw replay.-decodeReplayFile :: Bool -> Bytes.ByteString -> Either String FullReplay-decodeReplayFile fast = runDecode $ decodeReplay fast+decodeReplayFile+  :: Bool -> Bool -> Bytes.ByteString -> Either String Replay.Replay+decodeReplayFile fast = ByteGet.run . Replay.byteGet fast  -- | Encodes a replay as JSON.-encodeReplayJson :: FullReplay -> Bytes.ByteString-encodeReplayJson = LazyBytes.toStrict . Json.encodePretty' Json.defConfig-  { Json.confCompare = compare-  , Json.confIndent = Json.Spaces 2-  , Json.confTrailingNewline = True+encodeReplayJson :: Replay.Replay -> LazyBytes.ByteString+encodeReplayJson = Aeson.encodePretty' Aeson.defConfig+  { Aeson.confCompare = compare+  , Aeson.confIndent = Aeson.Tab+  , Aeson.confTrailingNewline = True   }  -- | Parses a JSON replay.-decodeReplayJson :: Bytes.ByteString -> Either String FullReplay-decodeReplayJson = Json.eitherDecodeStrict'+decodeReplayJson :: Bytes.ByteString -> Either String Replay.Replay+decodeReplayJson = Aeson.eitherDecodeStrict'  -- | Encodes a raw replay.-encodeReplayFile :: Bool -> FullReplay -> Bytes.ByteString+encodeReplayFile :: Bool -> Replay.Replay -> LazyBytes.ByteString encodeReplayFile fast replay =-  LazyBytes.toStrict . Binary.runPut . putReplay $ if fast-    then replay { replayContent = toSection putContent defaultContent }+  BytePut.toLazyByteString . Replay.bytePut $ if fast+    then replay+      { Replay.content = Section.create Content.bytePut Content.empty+      }     else replay
+ src/lib/Rattletrap/Utility/Json.hs view
@@ -0,0 +1,23 @@+module Rattletrap.Utility.Json+  ( module Rattletrap.Utility.Json+  , Aeson.FromJSON(parseJSON)+  , Aeson.ToJSON(toJSON)+  , Aeson.Value+  , Aeson.object+  , Aeson.withObject+  , Aeson.withText+  ) where++import qualified Data.Aeson as Aeson+import qualified Data.Aeson.Types as Aeson+import qualified Data.Text as Text++required+  :: Aeson.FromJSON value => Aeson.Object -> String -> Aeson.Parser value+required object key = object Aeson..: Text.pack key++optional :: Aeson.FromJSON value => Aeson.Object -> String -> Aeson.Parser (Maybe value)+optional object key = object Aeson..:? Text.pack key++pair :: (Aeson.ToJSON value, Aeson.KeyValue pair) => String -> value -> pair+pair key value = Text.pack key Aeson..= value
+ src/lib/Rattletrap/Utility/Monad.hs view
@@ -0,0 +1,4 @@+module Rattletrap.Utility.Monad where++whenMaybe :: Applicative m => Bool -> m a -> m (Maybe a)+whenMaybe p f = if p then Just <$> f else pure Nothing
+ src/lib/Rattletrap/Version.hs view
@@ -0,0 +1,7 @@+module Rattletrap.Version where++import qualified Data.Version as Version+import qualified Paths_rattletrap as Package++string :: String+string = Version.showVersion Package.version
src/test/Main.hs view
@@ -1,76 +1,54 @@ module Main   ( main-  )-where+  ) where  import qualified Control.Monad as Monad-import qualified Data.ByteString.Lazy as Bytes-import qualified Data.Int as Int-import qualified Data.Word as Word+import qualified Data.ByteString as Bytes import qualified GHC.Clock as Clock import qualified Rattletrap import qualified System.Exit as Exit import qualified System.FilePath as Path-import qualified System.IO.Temp as Temp-import qualified System.Mem as Mem import qualified Test.HUnit as Test import qualified Text.Printf as Printf  main :: IO ()-main = Temp.withSystemTempDirectory "rattletrap-" (runTests . toTests)+main = runTests makeTests  runTests :: Test.Test -> IO () runTests test = do-  result <- Test.runTestTT test+  Rattletrap.rattletrap+    ""+    ["--schema", "--output", Path.combine directory "schema.json"]+  (result, elapsed) <- withElapsed $ Test.runTestTT test+  Printf.printf "Total time: %.3f seconds\n" elapsed   Monad.when     (Test.errors result > 0 || Test.failures result > 0)     Exit.exitFailure -toTests :: FilePath -> Test.Test-toTests directory = Test.TestList (fmap (toTest directory) replays)+makeTests :: Test.Test+makeTests = Test.TestList $ fmap toTest replays -toTest :: FilePath -> (String, String) -> Test.Test-toTest directory (uuid, name) = Test.TestLabel-  (toLabel uuid name)-  (Test.TestCase (toAssertion directory uuid))+toTest :: (String, String) -> Test.Test+toTest (uuid, name) =+  Test.TestLabel (toLabel uuid name) . Test.TestCase $ toAssertion uuid  toLabel :: String -> String -> String toLabel uuid name = uuid <> ": " <> name -toAssertion :: FilePath -> String -> Test.Assertion-toAssertion directory uuid = do+toAssertion :: String -> Test.Assertion+toAssertion uuid = do   let-    inputFile = Path.joinPath ["replays", Path.addExtension uuid ".replay"]-    jsonFile = Path.joinPath [directory, Path.addExtension uuid ".json"]-    outputFile = Path.joinPath [directory, Path.addExtension uuid ".replay"]+    inputFile = Path.combine "replays" $ uuid <> ".replay"+    jsonFile = Path.combine directory $ uuid <> ".json"+    outputFile = Path.combine directory $ uuid <> ".replay"   input <- Bytes.readFile inputFile-  putStrLn ("\t" <> uuid)-  do-    (((), allocated), elapsed) <- withElapsed-      (withAllocations (decode inputFile jsonFile))-    put "decoding" (Bytes.length input) elapsed allocated-  do-    (((), allocated), elapsed) <- withElapsed-      (withAllocations (encode jsonFile outputFile))-    put "encoding" (Bytes.length input) elapsed allocated+  decode inputFile jsonFile+  encode jsonFile outputFile   output <- Bytes.readFile outputFile   Monad.unless     (output == input)     (Test.assertFailure "output does not match input") -put :: String -> Int.Int64 -> Word.Word64 -> Int.Int64 -> IO ()-put label size elapsed allocated = Printf.printf-  "%s %d byte%s took %d nanosecond%s (%.3f MB/s) and allocated %d byte%s (%d x)\n"-  label-  size-  (if size == 1 then "" else "s")-  elapsed-  (if elapsed == 1 then "" else "s")-  ((1e9 * fromIntegral size) / (1048576 * fromIntegral elapsed) :: Double)-  allocated-  (if allocated == 1 then "" else "s")-  (div allocated size)- decode :: FilePath -> FilePath -> IO () decode input output =   Rattletrap.rattletrap "" ["--compact", "--input", input, "--output", output]@@ -79,19 +57,15 @@ encode input output =   Rattletrap.rattletrap "" ["--input", input, "--output", output] -withAllocations :: IO a -> IO (a, Int.Int64)-withAllocations action = do-  before <- Mem.getAllocationCounter-  result <- action-  after <- Mem.getAllocationCounter-  pure (result, before - after)--withElapsed :: IO a -> IO (a, Word.Word64)+withElapsed :: IO a -> IO (a, Double) withElapsed action = do-  before <- Clock.getMonotonicTimeNSec+  before <- Clock.getMonotonicTime   result <- action-  after <- Clock.getMonotonicTimeNSec+  after <- Clock.getMonotonicTime   pure (result, after - before)++directory :: FilePath+directory = "output"  replays :: [(String, String)] replays =