tfausak / octane

:rocket: Parse Rocket League replays.
https://www.stackage.org/nightly/package/octane
Other
39 stars 1 forks source link

Fix replay generation #61

Closed tfausak closed 8 years ago

tfausak commented 8 years ago

This is a work in progress. It aims to fix #57.

tfausak commented 8 years ago

I think the class property map is correct. I still can't round-trip a replay, and I think the problem is compressed words. Usually they have relatively high limits — somewhere between 30 and 1024. Since my class property map only has the properties that are actually used in the replay, the number of properties per class is very low, sometimes as low as 2.

Putting property id 0 of 2 for "TAGame.Ball_TA"."TAGame.Ball_TA:GameEvent" = ValueFlaggedInt (FlaggedIntValue {flaggedIntValueFlag = Boolean {booleanUnpack = True}, flaggedIntValueInt = 6})
Putting property id 2 of 2 for "TAGame.Ball_TA"."TAGame.RBActor_TA:ReplicatedRBState" = ValueRigidBodyState (RigidBodyStateValue {rigidBodyStateValueSleeping = Boolean {booleanUnpack = True}, rigidBodyStateValuePosition = Vector {vectorX = 0, vectorY = 0, vectorZ = 93}, rigidBodyStateValueRotation = Vector {vectorX = -1.0000305, vectorY = -1.0000305, vectorZ = -1.0000305}, rigidBodyStateValueLinearVelocity = Nothing, rigidBodyStateValueAngularVelocity = Nothing})

Getting replication for actor 0
Getting existing replication properties for object 0 "Archetypes.Ball.Ball_Default" class 1 "TAGame.Ball_TA"
Getting property 0 of 2 "TAGame.Ball_TA:GameEvent"
Got property ValueFlaggedInt (FlaggedIntValue {flaggedIntValueFlag = Boolean {booleanUnpack = True}, flaggedIntValueInt = 6})
Getting property 0 of 2 "TAGame.Ball_TA:GameEvent" -- WRONG
Got property ValueFlaggedInt (FlaggedIntValue {flaggedIntValueFlag = Boolean {booleanUnpack = True}, flaggedIntValueInt = 16777234})

I think compressed words don't work for limits that low. I have something wrong in both my serializer and deserializer.

tfausak commented 8 years ago

I figured QuickCheck would have caught this, but it didn't. The Arbitrary instance for CompressedWord generates a limit between 1 and maxBound. Since the limit is a Word, the maxBound is 18446744073709551615 (on my machine). And since QuickCheck uses a normal distribution, the odds of getting a limit of (say) 2 are very low.

Changing the limit to 10 immediately found a problem.

      can round trip CompressedWord:   FAIL
        Falsifiable (after 2 tests): 
        Expected:  CompressedWord
          { compressedWordLimit = 8 , compressedWordValue = 8 }
        Actual: CompressedWord
          { compressedWordLimit = 8 , compressedWordValue = 0 }
        CompressedWord {compressedWordLimit = 8, compressedWordValue = 8}
tfausak commented 8 years ago

Yup. With a limit of 2, my code only thinks to read or write a single bit.

putting compressed word: limit = 2; maxBits = 1; value = 2
getting compressed word: limit = 2; maxBits = 1
tfausak commented 8 years ago

Bad news:

  1. The tests are broken.
  2. The generated replay crashes Rocket League.

😢