Implement saved games (a.k.a. `Universe` serialization)
Among the reasons this is nontrivial:
- we want a schema that provides for future extensions or explicit versioning
Universeis a graph structure that may contain cycles- deserialization will require constructing
URefs before their referents exist
- deserialization will require constructing
In the long run I would like to have a save format where different parts of the universe are separate files (so that it's possible, if not necessarily wise, to e.g. change a block definition by swapping its file), but that is extremely hairy (filesystems are not transactional in the ways you'd like) and not necessary for a first iteration.
Partial proof-of-concept serialization support is pushed. Still to do:
- Hook up deserialized
URefs to theUniverse, and handle them being temporarily not ready during deserialization - Serialize all data fields and types (notably
Character,Inventory,BehaviorSet) - Compress
Spacedata - Hook up serialization to file load/save (
all-is-cubes-port) - Thoroughly test and maybe fuzz-test
Commit f570656ad93f9f9b10f5c52156955e1b319ad293 adds load (but not save) within all-is-cubes-port. Saving is tricky in this context because all-is-cubes-port has the idea of exporting an ExportSet of URefs, but serialization wants a whole Universe. My current plan is to add a thing where a UniverseSchema can be constructed from an ExportSet, enabling partial saves. This will require making UniverseSchema public, moving ExportSet to the all-is-cubes crate, or adding a special serialization helper function, so that the necessary cooperation can happen.
Commit 1b7dfdb394f625b45b134433e905fc3302e97fdd solves the above problem using a new type PartialUniverse.
Commit 7c13ef89230fb4e85f62339189ef58faad7da5b3 adds hooking up deserialized URefs.
Remaining work:
- Serialize all data fields and types
- Compress
Spacedata - Thoroughly test and maybe fuzz-test
Commit 219f4216ae49c4e9e126832dc4e344ce4a760b6e adds compression.
On a quick scan, the pieces that are still not serialized are:
Behaviors (this will require some kind of extensible registry, or a rethink)BlockAttributes::tick_action(which has lots of other missing features anyway)- [edit:]
Space::spawn
Also there might be some kind of recently-introduced bug where light is not serialized correctly. Still digging in to that one.
As of commit f603e121d78683023fc81c41db4adc22abb852ef, behaviors are theoretically serializable. However, none of the specific behaviors currently existant are serializable, so there isn't much test coverage. We will need an extension-registry mechanism to make the behaviors in all-is-cubes-content serializable (or replacing dyn Behavior with a "scripting" mechanism so the actual implementation can be a serialized script).
As of commit 25c4b4c5de24d4fb64dce90902c39908dd0aa1b0, Spawn is serializable, and serialized when it occurs in Space.
The sole remaining non-serialized data, if I haven't missed something is BlockAttributes::tick_action. The current type for that field is not very expressive (Option<VoxelBrush>; no conditionals or preconditions available at all), so I think that I will consider completion of this blocked on coming up with a better system for tick_actions, which will be valuable for adding actual gameplay mechanics anyway. That is mostly covered by issue #309 and some unpublished notes, but I might open another issue, or not.
Commit 1635b2874545b997ad9e9ac12b75d5cb4b2c9371 adds simple save button UI, but it isn't active yet due to missing implementations.
As of commit 6609d745a6b86ef467c9b4808a9f40a2344b0b28, tick actions are serializable; this means that the serialization is complete. We will still want to introduce new game elements and change some things about the schema, but hopefully they can maintain compatibility, and in the current version, nothing is lost during serialization or deserialization.
This issue remains open to track the user-interface problem of being able to perform saves.
As of commit 30f38958e92fe5b5bf447d12e35946858789ca51, the save button is barely functional. Limitations:
- Doesn't work on web.
- Only writes native JSON.
- No “save as” functionality, so in order to save changes you have to create a file via the command line, then open it.
- No atomic writes, so if there is any error it may overwrite a good file with bad data.