Save compatibility¶
Save data is a public compatibility boundary. A change is not complete merely because a newly created world works: existing worlds, stable IDs, serialized object ownership, and failure recovery must be considered.
Review checklist¶
- Identify every serialized field, owning type, and load path touched.
- Determine the oldest supported representation and whether missing fields already have safe defaults.
- Preserve stable JSON IDs. For a rename or removal, use the repository's supported migration or obsoletion mechanism instead of silently reusing an ID.
- Test on copies of representative saves. Never use the only copy of a user's world as a migration fixture.
- Test save, reload, a second save/reload cycle, and the affected gameplay operation. One successful parse may still leave invalid state.
- Record incompatibility explicitly in the pull request and release notes.
Failure handling¶
Do not catch and discard loader errors to make an old save appear accepted. Preserve the first diagnostic and enough context to identify the owning object without leaking personal paths or data. A migration should be deterministic, idempotent where practical, and covered by a focused regression test.
The savegame* and worldfactory implementations at the page's verified
commit are the runtime authority. Legacy prose explains concepts but cannot
override current serialization code and tests.
Finite-water save state¶
The remaining amount in finite ponds, pools, and channels is stored in the
submap's finite_liquids member rather than as ground items. Each record holds
the in-submap coordinates and remaining charges; a tile with no remaining
liquid has no record.
When an older finite-water save is loaded, the loader absorbs matching ground liquid from finite-water terrain into this hidden state and clamps it to the terrain's capacity. This removes the item sprite that covered the water and preserves the amount through later save/load cycles. Changes to this migration need coverage for legacy ground liquid, the new hidden state, and two consecutive save/load cycles.