Default to identity mapping elements not in the palette for pre-98.0 saves

Newer saves include an element palette which maps save-space element numbers to element identifier strings, see 29189693b3. This is useful because the numbers of custom elements can change, while their identifiers are expected to not change. Not all elements make it into the palette, only the ones that are in use in the save.

98.0 is staged to extend this feature in two ways. First, it'll warn the user of missing custom elements when loading a save that uses such elements, see 36800a76cd. Second, it'll do a better job of deciding what to put in the element palette, see a13c29875f.

In order for detection of missing elements to work, a save's palette has to account for every element number used in the save, including built-in elements. To dispel a misunderstanding regarding that last part: yes, including built-in elements is not crucial if the set of built-in elements only ever grows, but this is not guaranteed.

98.0 creates such palettes, but older code didn't, for various reasons. One reason is that the palette at some point wasn't meant to include built-in elements, see e0d982367b, although this was rectified later in 67b87b1dab. Another reason is that not all cases of element numbers encoded in particle properties were considered, see for example f45d0d1683 and 1f1062408c.

Palettes in existing saves being thus incomplete didn't use to be a problem because older code would just assume that whatever element number wasn't listed in the palette referred to a built-in element and would just map such save-space element numbers to the same simulation-space element number, hence identity mapping.

However, this approach doesn't cover custom elements whose numbers can change, nor does it cover extra built-in elements added by a mod. Worse, a different mod with different extra built-in elements may map save-space element numbers not listed in the palette to its own extra elements.

As a solution to these problems and making use of the fact that palettes are now complete and comprehensive, 98.0 no longer does this default identity mapping, see 73be29aa61. Removing this identity mapping in itself would have broken older saves that use the old identifiers of some elements; that commit works around that by remapping these early in the loading process. By the way, these changes in identifiers are perfect examples of the set of built-in elements changing in ways other than growing.

This still doesn't address the problem in the case of pre-98.0 saves though. Such saves have seemingly valid element numbers (although it's impossible to tell whether these refer to built-in elements from vanilla or extra built-in elements from a mod) but no corresponding entry in their palettes. The user is warned about such elements also, see 9f8449357f. Lacking a better solution, this commit assumes that these elements are indeed vanilla elements and re-enables the default identity mapping for such saves.

In summary, this commit fixes the loading process for saves that were made in 97.0 or some older version and use built-in vanilla elements in ways that didn't trigger their inclusion in the element palette.

For example, until a13c29875f, CONV's tmp was not considered by the palette code, so any CONV with tmp set to an element that wasn't a built-in vanilla element, and which also wasn't used anywhere else in the save, would have been potentially corrupted by the loading process. An example a save that demonstrates this behaviour is id:2633868, which has CRAY particles on the right with ctype set to LIGH, but until this commit, these ctypes would have been set to 0 and the user would have been warned about element number 87 (LIGH) missing from the palette.
This commit is contained in:
Tamás Bálint Misius 2023-12-10 13:38:33 +01:00
parent 7ab52f8bec
commit a38e1c48bb
No known key found for this signature in database
GPG Key ID: 5B472A12F6ECA9F2
2 changed files with 20 additions and 2 deletions

View File

@ -59,9 +59,12 @@ void GameSave::MapPalette()
auto &elements = sd.elements;
if(palette.size())
{
for(int i = 0; i < PT_NUM; i++)
if (version >= Version(98, 0))
{
partMap[i] = 0;
for(int i = 0; i < PT_NUM; i++)
{
partMap[i] = 0;
}
}
for(auto &pi : palette)
{

View File

@ -27,6 +27,21 @@ struct Version
return *this < other || *this == other;
}
constexpr bool operator >=(const Version &other) const
{
return !(*this < other);
}
constexpr bool operator >(const Version &other) const
{
return !(*this <= other);
}
constexpr bool operator !=(const Version &other) const
{
return !(*this == other);
}
constexpr size_t operator [](size_t index) const
{
return components[index];