Skip to content

fix(parser): graceful fallback when v1.2 chain-actor ExtraData diverges#7

Merged
ChrisonSimtian merged 1 commit into
mainfrom
fix/v1.2-chain-actor-fallback
May 17, 2026
Merged

fix(parser): graceful fallback when v1.2 chain-actor ExtraData diverges#7
ChrisonSimtian merged 1 commit into
mainfrom
fix/v1.2-chain-actor-fallback

Conversation

@ChrisonSimtian

Copy link
Copy Markdown
Owner

Problem

The v1.2 gate in ObjectSerializer.cs:135 assumes FGConveyorChainActor's ExtraData wire format is unchanged from pre-1.2 (AnthorNet's Read.js has no version branching for it). The existing synthesized v1.2 chain-actor tests confirm that assumption for the empty / one-conveyor / no-items shapes — but real Beta Game v1.2 saves throw EndOfStreamException at the first ObjectReference inside DeserializeConveyorChainActor (line 389).

Stack trace (against Beta Game_autosave_2.sav):

System.IO.EndOfStreamException: Unable to read beyond the end of the stream.
   at System.IO.BinaryReader.ReadInt32()
   at SatisfactorySaveNet.StringSerializer.ReadCharArray(...):line 38
   at SatisfactorySaveNet.StringSerializer.Deserialize(...):line 26
   at SatisfactorySaveNet.ObjectReferenceSerializer.Deserialize(...):line 21
   at SatisfactorySaveNet.ExtraDataSerializer.DeserializeConveyorChainActor(...):line 389

Fix

Rather than guess at the diverged format, fall back gracefully: capture the reader position before the chain-actor decode, catch EndOfStreamException, seek back, and let the existing missing-bytes absorber consume the bytes as raw hex. Consumers see ConveyorActors[] = empty for affected chains — matches the fallback contract that the ERP.Satisfactory downstream already documents.

Pre-1.2 saves and other gated actor types are unaffected — the catch filter requires v12 && IsConveyorActor.

Tests

  • RealSaveFixtureTests.Deserialize_DoesNotThrow(Beta Game_autosave_2.sav)was failing, now passes (regression marker).
  • All three SatisfactorySaveNet - v1.2 - *.sav fixtures continue to pass.
  • The legacy + synthesized v1.2 chain-actor tests (ExtraDataSerializerLegacyTests, ExtraDataSerializerV12Tests) continue to pass — happy path is unchanged.
Total tests: 7
     Passed: 7

Follow-up

Per TODO.md §5, the proper fix is to port the actual v1.2 chain-actor wire format once a reference (etothepii's TS parser, AnthorNet's JS) shows what changed. This PR is the safety net so consumers stop crashing in the meantime.

Downstream

Unblocks ERP.Satisfactory #142.

The v1.2 gate at ObjectSerializer.cs:135 assumes FGConveyorChainActor's
ExtraData wire format is unchanged from pre-1.2 (AnthorNet's Read.js has
no version branching for it). Synthesized v1.2 tests confirm that
assumption for the empty / one-conveyor / no-items shapes — but real
Beta Game v1.2 saves throw EndOfStreamException at the first
ObjectReference inside DeserializeConveyorChainActor.

Rather than guess at the diverged format, fall back gracefully: capture
the reader position before the chain-actor decode, catch EndOfStreamException,
seek back, and let the existing missing-bytes absorber consume the bytes
as raw hex. Consumers see ConveyorActors[] = empty for affected chains
(matches the behaviour SaveFileReader.cs already documents as the
fallback contract).

Pre-1.2 saves and other gated actor types are unaffected — the catch
filter requires v12 && IsConveyorActor.

Tests
- RealSaveFixtureTests.Deserialize_DoesNotThrow(Beta Game_autosave_2.sav)
  now passes (previously threw EndOfStreamException at
  StringSerializer.ReadCharArray → ObjectReferenceSerializer.Deserialize
  → DeserializeConveyorChainActor:389).
- The three SatisfactorySaveNet - v1.2 - *.sav fixtures and the legacy
  synthesised v1.2 chain-actor tests continue to pass — no chain-actor
  format change is hit on the happy path.

Downstream: unblocks ERP.Satisfactory #142.
@ChrisonSimtian ChrisonSimtian merged commit cadbf8b into main May 17, 2026
2 checks passed
@ChrisonSimtian ChrisonSimtian deleted the fix/v1.2-chain-actor-fallback branch May 17, 2026 07:37
ChrisonSimtian added a commit to erp-for-factory-games/ErpForFactoryGames that referenced this pull request May 17, 2026
…loses #142)

4.1.1 crashed with EndOfStreamException on real Beta Game v1.2 saves
inside DeserializeConveyorChainActor. The fork's PR
ChrisonSimtian/SatisfactorySaveNet#7 lands a graceful fallback: when the
chain-actor decode throws, rewind and let the existing missing-bytes
absorber consume the bytes as raw hex. Consumers see ConveyorActors[]
= empty for affected chains — matches the fallback contract that
SaveFileReader.cs already documents.

Verified locally: Beta Game (28h played, 19 miners, 64 buildings, 434
belts, 820 nodes) parses with 0 warnings, /factory/alerts surfaces 5
active alerts as expected.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant