|
VersionNumbers
Summary of the different version numbers being used
Phase-Implementation API VersionCorsixTH is implemented as a mixture of Lua code and C/C++ code. There is an API layer between the two; various functions / classes are made available by the C/C++ code, and consumed by the Lua code. Over time, this API mutates - new functions / classes are added, or the behaviours of certain functions change. To ensure that the Lua code is expecting the same API as the C/C++ code is making available, an API version number is used. The file Lua/api_version.lua stores this version number. When the API changes, this number should be incremented to match the SVN revision number of the commit which changes the API. As this file also compiles as C code, this is the only place that the API version number needs to be changed, and anyone using an older version of the executable will receive a warning about the version number mismatch. Because the version number tracks SVN revisions, said warning can inform the user of what revision they have to update to. Note that the SVN snapshot page uses the revision number which changed api_version.lua as a basis for its compatibility guide, rather than the value actually stored in api_version.lua, which is another reason to keep the two values the same. Savegame VersionTo allow code bugs to be fixed, CorsixTH savegames store the data of the Lua universe, but do not store the code. Because of this, and of Lua's dynamic typing, if a new field is added to a class in its constructor, then this field will not be present if a savegame is loaded which was saved prior to the introduction of the field. To work around this, a savegame version number is used, which classes can use to determine whether they need to initialise new fields. The file Lua/app.lua stores the SAVEGAME_VERSION constant, which is incremented by one at each change. For an example, see r787, which introduced a new object_counts field to the World class' constructor, and hence incremented SAVEGAME_VERSION and added code to World:afterLoad which checked for previous savegame versions and then reconstructed the object_counts field if necessary. If you add an afterLoad function to a class, please always make sure that you call the afterLoad function of its superclass inside. For example, you add some variable to, say, UIGraphs. You add the function UIGraphs:afterLoad(old, new) to initialize the variable on load of an old savegame to a reasonable value. At the end of the function, don't forget to put UIFullscreen.afterLoad(self, old, new), or else the afterLoad instructions meant for all UIFullscreen windows (and, through another superclass call, all Windows) are not anymore applied to UIGraphs, which we don't want. Unfortunately this kind of mistake is hard to notice because errors will only happen if you load an old savegame under the right circumstances, so always try to remember this issue while coding. Map Savegame Format Version NumberThe C++ THMap class is exposed to Lua as userdata, and hence is responsible for the binary format which it uses when being serialised to a savegame. As this format has changed over time, and is likely to change again, a version number was introduced. The file Src/th_map.cpp contains all the references to this version number, specifically in the THMap::persist and THMap::depersist functions. THMap::persist writes a version number as the very first field in the binary blob (prior to the introduction of the version field, the first field was map width, which was always 128). This allows THMap::depersist to know what format to expect data in, and hence load map data from older versions and reconstruct the new fields. | |