-
-
Notifications
You must be signed in to change notification settings - Fork 0
Persistence
This module handles saving data to disk and has various utilities that help with organizing data and interfaces that streamline loading and saving.
Before looking at the interfaces we should look at the data containers first, as you primarily interact with those. The loading interfaces are just there to organize access and further work on persisted data that can easily be reproduced and streamlined.
The game saves work by saving the direct byte data. This data is persisted and then copied back into the programm and finally the structs. Despite these risks this approach was chosen for flexibility (any POD struct can be saved without serialization/deserialization methods This poses some challenges when going across platforms:
- If a compiler introduces padding to a struct, this can make it impossible to deserialize the data with a different compiler
- If the platform has a different endianess it could interpret bytes the wrong way
While these might seem scary at first it won't be a big issue. Generally across major compilers (GCC, Clang, MSVC) the behavior when it comes to padding structs is very equal. Apart from edge cases there shouldn't be many problems. If you see your saves not loading correctly you can explicitly introduce padding:
struct alignas(16) MyStruct { // Will be 32 bytes in size - 24 + 8 padded
char data[24];
};
Endianess is just a implementation detail that can be solved in the engine itself based on the target its compiled for. And most endusers will use the same endianess anyway.
Despite these risks this approach was chosen for several reasons:
- Any POD struct can be saved without serialization/deserialization methods
- Very fast and easy memory management (just plain data copies)
- Easier interface than serialization/deserialization methods