Achieved by adding a new element property called CarriesTypeIn, whose bits signal to save loading code which properties of particles of the element class in question carry element IDs. The bits in this property are numbered the same way as sim.FIELD_* constants for consistency. One would signal from Lua that a custom element carries element IDs in its tmp like this:
elem.property(id, "CarriesTypeIn", 2 ^ sim.FIELD_TMP)
"Carrying an element ID in a property" is to be interpreted as follows: the property is treated as a combination of a PMAPBITS-bit (so, currently 9-bit) unsigned integer lower part holding an element ID and a 32-PMAPBITS-bit (so, currently 23-bit) signed integer upper part holding whatever makes sense for the element. CONV, for example, uses this signed integer in its ctype as the extra "v" parameter for particle creation.
Namely:
- get rid of unsafe memory management;
- use vectors / Planes everywhere;
- return a vector from serialization functions;
- have read functions take a vector;
- improve constness;
- hide a few implementation details from GameSave.h;
- get rid of GameSave copy constructor;
- better member initialization;
- use the slightly more C++-looking BZ2 wrappers.
The BSON library still takes ownership of the data it parses, and GameSave
ownership is still a joke. Those will need to be fixed later.
... and everything built around them.
A GameSave would hold at least one but sometimes two representations of a save:
one serialized, and one "friendly", accessible for modification. Thus, a
GameSave would have three states:
- "Collapsed": only the serialized representation was present; this was the
initial state of GameSaves loaded from files;
- "Expanded With Data": both the serialized and the friendly representations
were present; this was the state of GameSaves loaded from files after a call
to Expand;
- "Expanded Without Data": only the friendly representation was present; this
was the initial state of GameSaves being prepared for being saved to files.
A GameSave would be able to go from Collapsed to Expanded With Data with a call
to Expand, and back with a call to Collapse. Of course, this latter transition
would discard any changes made to the friendly representation, for example with
Translate. A GameSave would however be unable to go from Expanded Without Data
to any other state; a call to Collapse in this state would have been a no-op.
There were two instances of Collapse being called, one in the GameSave
constructor taking the serialized representation, immediately after a call to
Expand, and another in SaveRenderer, which would Collapse a save "back down" if
it had originally been Collapsed. Now, consider that there reasons for
constructing a GameSave from the serialized representation are as follows:
- loading an online save at startup from the command line;
- loading a local save at startup from the command line;
- loading a local save when it is dropped into the window;
- loading a local save for placement of the most recently used stamp;
- loading a local save for stamp placement via Lua;
- loading an online save for preview generation while browsing;
- loading a local save in the stamp browser for thumbnail generation;
- loading a local save in the local save browser for thumbnail generation.
In some cases, the friendly representation is needed for thumbnail generation
by ThumbnailRendererTask. ThumbnailRendererTask operates on its own copy of the
GameSave, because it runs SaveRenderer on a thread different from the main one
and cannot be sure of the lifetime of the original GameSave. It destroys this
copy when it is done rendering, so the call SaveRenderer makes to Collapse is
pointless.
In all other cases, the friendly representation is needed immediately. In some
of these, SaveRenderer is used from the main thread, but since the friendly
representation of the GameSave will be needed for pasting anyway, the call
SaveRenderer makes to Collapse is pointless again.
So, Collapse goes away. This also means that it is pointless for GameSaves to
hold on to the serialized representation, since in all cases in which they have
access to it, the friendly representation is needed immediately, and with
Collapse gone, they will never need it again.
Also Disallow linking against non-C++ system Lua, unless configuring with -Dworkaround_noncpp_lua=true, add -Dworkaround_elusive_bzip2 and friends, and get rid of the -image_base hack for macos.
This made it possible to get rid of two GameSave constructors.
Also clean up Client::LoadSaveFile, Client::ReadFile, and Client::WriteFile in the process, and remove unused SaveRenderer::Render
Also add GameSave::PressureInTmp3 to check for elements with pressure memory and fix TUNG not sampling pressure on creation. This does not in itself fix#822 because tmp3 and tmp4 are still saved in 16 bits each, so full ctypes still don't fit in tmp3.
Update save format to optionally store type as two bits
PIPE now stores element in ctype
Disallow uploading saves using two bytes in type or other fields
update save format to store pmapbits and automatically convert data
When making a local save, then stamping and loading the stamp (without doing anything else in between), issues with the code would cause the unsigned int in the json to turn into a normal int. It would then think the authors data from the stamp was from something else and append it. For users that do an excessive amount of stamping, this causes duplication in the authors links that shouldn't have ever happened.
The logging is saved inside the bson data in all online saves, local saves, stamps, and clipboard pieces. It is loaded back when reloading each of those.
See #474 for the format of the data. It is the same format for the bson data. Note that "links" is an array of objects. It can be recursive.
There is some effort to not duplicate information, we don't care if you loaded a stamp 10 times or if you are using the clipboard in your own save. Extra information is mostly not saved for your own stuff, only when you take material from other saves.
Press ctrl+a in debug builds to show what info it is currently saving in Client. Also enabled in snapshots for now.
There is one unrelated change in here, which fixes a crash pointed out by QuanTech. It was also save related and it was too close to the other changes to separate it into another commit. It fixes a crash when saving signs with invalid unicode. the BSON library doesn't like this, it was returning an error but we ignored it, which caused a crash. It now notices those errors. I also had to update several Serialize calls to check if it actually returned save data, or else it then would have started crashing there instead.
Also some debug prints were removed