We no longer need them. If you want to remove a field .. just
remove it! Because of the headers in the savegame, on loading,
it will do the right thing and skip the field.
Do remember to bump the savegame version, as otherwise older
clients can still load the game, but will reset the field you
have removed .. that might be unintentially.
We won't be able to make it fully self-descriptive (looking at you
MAP-chunks), but anything else can. With this framework, we can
add headers for each chunk explaining how each chunk looks like
in detail.
They also will all be tables, making it a lot easier to read in
external tooling, and opening the way to consider a database
(like SQLite) to use as savegame format.
Lastly, with the headers in the savegame, you can freely add
fields without needing a savegame version bump; older versions
of OpenTTD will simply ignore the new field. This also means
we can remove all the SLE_CONDNULL, as they are irrelevant.
The next few commits will start using this framework.
With std::variant all memory can be figured out at compile time, so the compiler needs to keep track of fewer elements. It also saves out a unique_ptr and its memory management, over a slight impact for resolving a setting.
It was rather confusing which one was for what, especially as some
SaveLoad flags were settings-only. Clean up this mess a bit by
having only Setting flags.
The comments for SettingDescType; it is a byte, so not 4 bytes and since it is not a flag there are about 250 other possibilities left instead of 9.
SettingGuiFlag is uint16 so has 2 bytes allocated.
SettingDescGlobVarList and related comments imply that global vars cannot be used elsewhere, but they are used for settings just fine. Even then the type is not used anywhere else but the definition of the table.
Many of the member variables that are used in save/load are inside types
that are not standard layout types. Using pointer arithmetics to determine
addresses of members inside types that are not standard layout is generally
undefined behaviour. If we'd use C++17, it is conditionally supported, which means
each compiler may or may not support it. And even then using it for individual
array elements is syntactically not supported the the standard offsetof function.
Unfortunately, the trickery employed for saving linkgraph settings causes quite some
clutter in the settings ini files.