From 2cdc81411092412621e88a4c6dcbcd3ece799e65 Mon Sep 17 00:00:00 2001 From: Lars Mueller Date: Tue, 4 Feb 2025 21:03:53 +0100 Subject: [PATCH 1/4] Document backwards compatibility guarantee --- content/backwards-compatibility.md | 123 +++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 content/backwards-compatibility.md diff --git a/content/backwards-compatibility.md b/content/backwards-compatibility.md new file mode 100644 index 0000000..74c33a1 --- /dev/null +++ b/content/backwards-compatibility.md @@ -0,0 +1,123 @@ +title: Backwards compatibility guarantee +--- + +# Backwards compatibility guarantee + +Luanti tries to guarantee backwards compatibility, but there are limits to this. + +## Client and Server + +Newer clients should be able to connect to and be able to play without issues on older servers, +"downgrading" to the feature set of an older client. + +Older clients should be able to connect to and be able to play on newer servers, +so long as they do not use any newer features they do not support. +It is on the game developer to decide whether this is game-breaking and older clients have to be prevented from playing, +or whether they can implement sensible fallbacks. +Some features however can be implemented purely on the server or on the client, +making them automatically compatible with older client and server versions respectively. + + + + +This means that, so long as the game remains the same, +it is possible to safely upgrade client and server independently. + +## Games and Mods + +Backwards compatibility ultimately only applies to the continued functioning of old games, +that is, sets of mods that were written against an older Luanti version. + +This means that there may be features which are, possibly necessarily, +incompatible with the assumptions older mods may make. + +Hence you may have a working configuration, add a new mod enabling one of these new features, +and by this cause issues with existing old mods. + +For example Luanti 5.9 allowed omitting punchers. +Mods that were written against 5.8 and older may index the puncher. +If a new mod now omits the puncher (as it may), this may cause a crash in an older mod, +which is inevitable: The older mod needs to decide what to do in case of a missing puncher. + +## Lua API + +It should go without saying, but: "Namespaces" and "classes" can and will be extended +by adding new functions or methods. + +Maybe there is no `core.frobnicate` today, but there might be tomorrow. +This is why you should use your own namespaces and wrappers +and not try to "extend" engine namespaces or classes yourself. + +Similarly, functions that return tables may return tables with *more* fields in the future. +Hence you **should not** iterate over fields: +Just get the fields you want and ignore extraneous fields. + +Functions that take tables might support more fields in the future. +Hence you **should not** provide extraneous fields. + +Functions that take multiple parameters might take more parameters in the future. +If you're hooking a function, +you should use a vararg to perfectly forward the parameter list, like this: + +```lua +local frobnicate = core.frobnicate +function core.frobnicate(...) + print("frobnication is starting! arguments are:", ...) + return frobnicate(...) +end +``` + +Functions that return multiple values might return more values in the future. +This means that when running a post-hook, +you should store all return values in a table ideally: + +```lua +local function pack(...) + return {n = select("#", ...), ...} +end + +local frobnicate = core.frobnicate +function core.frobnicate(...) + local results = pack(frobnicate(...)) + print("frobnication is done! results are:", unpack(results, 1, results.n)) + return unpack(results, 1, results.n) +end +``` + +Functions that take values of certain types today may take values of different types tomorrow. + +Generally, you can not assume that undocumented (but exposed) Lua APIs or behaviors are subject +to the backwards compatibility guarantee. +If you rely on an undocumented feature, please bring it to our attention +by filing a feature request, asking for it to be documented. + +## Command-Line Interface + +The backwards compatibility guarantee does currently not extend to the command-line interface, +which should not be considered stable. + +## Regressions + +There will unfortunately always be bugs that accidentally cause backwards compatibility to be broken. +These are called *regressions*: Something that used to work no longer does. + +Regressions are not strictly limited to documented behavior: +The documentation is not a practically complete specification, +so exceptions will be made as is sensible. + +## Minor Breakages + +Luanti will occasionally have minor compatibility breakages as is deemed sensible. +These will usually follow after a deprecation warning has been in for +a couple releases. + +If you're a mod developer, please check and act upon your warnings. + +## Major Breakages + +Planned major breakages are documented in `doc/breakages.md`. +They are to be done in the 6.0 release of Luanti. + +## Conclusion + +If you are unsure whether something is covered by the backwards compatibility guarantee, ask. From e682e8865fa3a5565168c7c30b55cc14f5935f7b Mon Sep 17 00:00:00 2001 From: Lars Mueller Date: Tue, 1 Apr 2025 01:27:38 +0200 Subject: [PATCH 2/4] Document compatibility guarantees precisely --- content/backwards-compatibility.md | 123 -------------------- content/for-creators/compatibility.md | 154 ++++++++++++++++++++++++++ content/for-players/compatibility.md | 68 ++++++++++++ 3 files changed, 222 insertions(+), 123 deletions(-) delete mode 100644 content/backwards-compatibility.md create mode 100644 content/for-creators/compatibility.md create mode 100644 content/for-players/compatibility.md diff --git a/content/backwards-compatibility.md b/content/backwards-compatibility.md deleted file mode 100644 index 74c33a1..0000000 --- a/content/backwards-compatibility.md +++ /dev/null @@ -1,123 +0,0 @@ -title: Backwards compatibility guarantee ---- - -# Backwards compatibility guarantee - -Luanti tries to guarantee backwards compatibility, but there are limits to this. - -## Client and Server - -Newer clients should be able to connect to and be able to play without issues on older servers, -"downgrading" to the feature set of an older client. - -Older clients should be able to connect to and be able to play on newer servers, -so long as they do not use any newer features they do not support. -It is on the game developer to decide whether this is game-breaking and older clients have to be prevented from playing, -or whether they can implement sensible fallbacks. -Some features however can be implemented purely on the server or on the client, -making them automatically compatible with older client and server versions respectively. - - - - -This means that, so long as the game remains the same, -it is possible to safely upgrade client and server independently. - -## Games and Mods - -Backwards compatibility ultimately only applies to the continued functioning of old games, -that is, sets of mods that were written against an older Luanti version. - -This means that there may be features which are, possibly necessarily, -incompatible with the assumptions older mods may make. - -Hence you may have a working configuration, add a new mod enabling one of these new features, -and by this cause issues with existing old mods. - -For example Luanti 5.9 allowed omitting punchers. -Mods that were written against 5.8 and older may index the puncher. -If a new mod now omits the puncher (as it may), this may cause a crash in an older mod, -which is inevitable: The older mod needs to decide what to do in case of a missing puncher. - -## Lua API - -It should go without saying, but: "Namespaces" and "classes" can and will be extended -by adding new functions or methods. - -Maybe there is no `core.frobnicate` today, but there might be tomorrow. -This is why you should use your own namespaces and wrappers -and not try to "extend" engine namespaces or classes yourself. - -Similarly, functions that return tables may return tables with *more* fields in the future. -Hence you **should not** iterate over fields: -Just get the fields you want and ignore extraneous fields. - -Functions that take tables might support more fields in the future. -Hence you **should not** provide extraneous fields. - -Functions that take multiple parameters might take more parameters in the future. -If you're hooking a function, -you should use a vararg to perfectly forward the parameter list, like this: - -```lua -local frobnicate = core.frobnicate -function core.frobnicate(...) - print("frobnication is starting! arguments are:", ...) - return frobnicate(...) -end -``` - -Functions that return multiple values might return more values in the future. -This means that when running a post-hook, -you should store all return values in a table ideally: - -```lua -local function pack(...) - return {n = select("#", ...), ...} -end - -local frobnicate = core.frobnicate -function core.frobnicate(...) - local results = pack(frobnicate(...)) - print("frobnication is done! results are:", unpack(results, 1, results.n)) - return unpack(results, 1, results.n) -end -``` - -Functions that take values of certain types today may take values of different types tomorrow. - -Generally, you can not assume that undocumented (but exposed) Lua APIs or behaviors are subject -to the backwards compatibility guarantee. -If you rely on an undocumented feature, please bring it to our attention -by filing a feature request, asking for it to be documented. - -## Command-Line Interface - -The backwards compatibility guarantee does currently not extend to the command-line interface, -which should not be considered stable. - -## Regressions - -There will unfortunately always be bugs that accidentally cause backwards compatibility to be broken. -These are called *regressions*: Something that used to work no longer does. - -Regressions are not strictly limited to documented behavior: -The documentation is not a practically complete specification, -so exceptions will be made as is sensible. - -## Minor Breakages - -Luanti will occasionally have minor compatibility breakages as is deemed sensible. -These will usually follow after a deprecation warning has been in for -a couple releases. - -If you're a mod developer, please check and act upon your warnings. - -## Major Breakages - -Planned major breakages are documented in `doc/breakages.md`. -They are to be done in the 6.0 release of Luanti. - -## Conclusion - -If you are unsure whether something is covered by the backwards compatibility guarantee, ask. diff --git a/content/for-creators/compatibility.md b/content/for-creators/compatibility.md new file mode 100644 index 0000000..f68e764 --- /dev/null +++ b/content/for-creators/compatibility.md @@ -0,0 +1,154 @@ +--- +title: Compatibility guarantee (for creators) +--- + +# Compatibility guarantee (for creators) + +Luanti tries to guarantee backwards compatibility to a reasonable extent +so that content usually continues to work as Luanti evolves. + +## Deprecations + +Deprecations are found along with the documentation of the deprecated features +in the various files in the `doc` folder, in particular, +[`lua_api.md`](https://github.com/luanti-org/luanti/blob/master/doc/lua_api.md). + +For many features, there are *deprecation warnings*, +some of which give you a stack trace that tells you where deprecated API usage originated. + +{{< notice tip >}} +- For you to see warnings at all in-game, you might want to set `chat_log_level` to `warning` or higher. +- Your `deprecated_lua_api_handling` setting should be set to at least `log`; + you should even consider `error` if you have a relatively clean game. +- Full stack traces for deprecation warnings are logged at the lower `info` log level, + so you will want to set `debug_log_level` to `info` to see them in `debug.txt`. +{{< /notice >}} + +### Minor Breakages + +Despite trying to abide by [semantic versioning](https://semver.org), +Luanti will occasionally have minor compatibility breakages in minor releases (but not in patch releases) as is deemed sensible. +These will usually follow after a deprecation warning has been in for a couple releases. + +{{< notice tip >}} +Make sure to follow [the changelog](https://docs.luanti.org/about/changelog/) for compatibility notes +including deprecations and minor breakages. +Test your content on newer engine versions and fix deprecation warnings. +{{< /notice >}} + +### Major Breakages + +Planned major breakages are documented in [`breakages.md`](https://github.com/luanti-org/luanti/blob/master/doc/breakages.md). +They are to be done eventually in the 6.0 release of Luanti, which is still far off. + +## Undocumented behavior + +Generally, you can not assume that undocumented (but exposed or observable) +APIs or behaviors are subject to the backwards compatibility guarantee. +You should always try to write your mods such that you only rely on documented behavior. +In particular, try to avoid "cargo culting": When taking code from somewhere else, +make sure to understand *why* it works and how (that) it uses the engine correctly. + +If you find that you rely on an undocumented feature, +please bring it to the attention of the Luanti community by +[filing a feature request](https://github.com/luanti-org/luanti/issues/new?labels=Feature+request&template=feature_request.yaml), +asking for it to be documented. +Otherwise it is possible that behavior is accidentally or deliberately changed, +simply because there is no reason to assume that anyone is relying on it. + +## Regressions + +There will unfortunately always be bugs that accidentally cause backwards compatibility to be broken. +These are called *regressions*: Something that used to work no longer does. + +Regressions are not strictly limited to documented behavior: +The documentation is not a practically complete specification, +so exceptions will be made as is sensible. +Depending on the impact, regressions concerning undocumented behavior +may also be considered important enough to be fixed. + +{{< notice tip >}} +If you find out that behavior unexpectedly changed, please +[file a bug report](https://github.com/luanti-org/luanti/issues/new?labels=Unconfirmed%20bug&template=bug_report.yaml). +{{< /notice >}} + +## Client and Server + +You need to decide whether older clients not supporting newer features +is game-breaking and older clients have to be prevented from playing, +or whether you can implement sensible fallbacks. + +{{< notice tip >}} +You can use `core.get_player_information` to get protocol versions and `core.protocol_versions` +to relate them to Luanti client versions. For example, to check whether a client +has at least the feature set of Luanti 5.8.0 or newer, you could do: +`core.get_player_information(player_name).protocol_version >= core.protocol_versions["5.8.0"]` +{{< /notice >}} + +## Lua API + +"Namespaces" (like `core`), "classes" (like `VoxelArea`) and "structs" +(like the return value of `player:get_player_control()`) +can and will be extended by adding new constants, functions or methods. +Generally, as a rule of thumb, "tables may have more fields in the future". + +Maybe there is no `core.frobnicate` today, but there might be tomorrow. +This is why you should use your own namespaces and wrappers +and not try to "extend" engine namespaces or classes yourself - +there could be collisions in the future. [^maintenance] +If you are forced to share a namespace with the engine (e.g. in entity definitions or item definitions), +the current convention is to prefix your fields with an underscore (`_`); +if multiple mods share the same namespace, using the mod name for namespacing is recommended. + +[^maintenance]: And additionally, even if the risk of this is low, +you make it harder for maintainers to see where something comes from. +A maintainer seeing `core.foo(...)` will expect it to be a Luanti function, +documented in the Luanti documentation, not something coming from some (which?) mod. + +Similarly, functions that return tables may return tables with *more* fields in the future. +Hence you **should not** iterate over fields and raise errors for fields you don't recognize: +Just get the fields you want and ignore extraneous fields. + +Functions that take tables might support more fields in the future. +Hence you **should not** provide extraneous fields in your tables +(it's also bad style and likely confusing to a reader). + +Functions that take multiple parameters might take more parameters in the future. +Be warned that not all engine functions are designed to be overridden ("hookable"). + +{{< notice tip >}} +If you're hooking a function, +you should use a vararg to perfectly forward the parameter list, like this: + +```lua +local frobnicate = core.frobnicate +function core.frobnicate(...) + print("frobnication is starting! arguments are:", ...) + return frobnicate(...) +end +``` + +This also applies conversely to perfectly forwarding return values. +This might require storing them in a table: + +```lua +local function pack(...) + return {n = select("#", ...), ...} +end + +local frobnicate = core.frobnicate +function core.frobnicate(...) + local results = pack(frobnicate(...)) + print("frobnication is done! results are:", unpack(results, 1, results.n)) + return unpack(results, 1, results.n) +end +``` +{{< /notice >}} + +Functions that take values of certain types today may take values of different types tomorrow. +For example it often happens that a parameter list is replaced with a single table argument. + +## See also + +- [Keeping world compatibility (as a creator)](/for-creators/keeping-world-compatibility/) +- [Compatibility guarantee for players](/for-players/compatibility) diff --git a/content/for-players/compatibility.md b/content/for-players/compatibility.md new file mode 100644 index 0000000..417a697 --- /dev/null +++ b/content/for-players/compatibility.md @@ -0,0 +1,68 @@ +--- +title: Compatibility guarantee (for players) +--- + +# Compatibility guarantee (for players) + +Luanti tries to guarantee backwards compatibility so you can usually +safely upgrade your client and continue playing the games and joining the servers you like. + +{{< notice tip >}} +Check out the compatibility notes in [the changelog](https://docs.luanti.org/about/changelog/) +when upgrading. +{{< /notice >}} + +## Client and Server + +Newer clients should be able to connect to and be able to play without issues on older servers, +"downgrading" largely to the feature set of an older client. +(Some features however can be implemented purely on the server or on the client, +making them automatically compatible with older client and server versions respectively.) + +Older clients should be able to connect to and be able to play on newer servers, +so long as they do not use any newer features they do not support. + +This means that, so long as the game remains the same, +it is possible to safely upgrade client and server independently. + +## Games and Mods + +Backwards compatibility applies to the continued functioning of old *games* +(or "mod soups" more broadly) - +sets of mods that were written against an older Luanti version. + +This means that there may be new features which are, possibly necessarily, +incompatible with the assumptions older mods may make, if they are used at all. + +Hence you may have a working configuration, add a new mod enabling/using one of these new features, +and by this cause issues with existing old mods. + +For example Luanti 5.9 allowed omitting punchers. +Mods that were written against older versions may expect there to always be a puncher. +If a new mod now omits the puncher (as it may), this may cause a crash in an older mod, +which is inevitable: The older mod needs to decide what to do in case of a missing puncher. + +Backwards compatibility is not absolute. +Sometimes old mods or games will break because a bug has been fixed, +or because a minor breakage has happened following a deprecation. +In these cases, you should try updating your mods and games, +and if the problem persists, report the issue to the respective maintainers. + +## Worlds + +Newer Luanti versions will be able to open old worlds. +This is taken extremely seriously and goes back more than a decade. + +However, once you open a world with a newer Luanti version, +that world need no longer be compatible with older Luanti versions, +e.g. because compression has been upgraded or legacy serialization formats +have been upgraded to more modern ones. + +## Command-Line Interface + +The backwards compatibility guarantee does currently not extend to the command-line interface, +which should not be considered stable (but nevertheless, for the most part, doesn't change very much). + +## See also + +- [Compatibility guarantee for creators](/for-creators/compatibility) From f32486808c3a0cd7a43a947cdb71fec0c7dd2c02 Mon Sep 17 00:00:00 2001 From: Lars Mueller Date: Tue, 1 Apr 2025 01:44:19 +0200 Subject: [PATCH 3/4] spellchecking woes --- cspell.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cspell.json b/cspell.json index c914aa4..62c9c75 100644 --- a/cspell.json +++ b/cspell.json @@ -153,6 +153,7 @@ "crossview", "currentline", "customised", + "culting", "dannydark", "Daretmavi", "darkrose", @@ -246,6 +247,8 @@ "freemove", "freetype", "Froggo", + "frobnicate", + "frobnication", "FSAA", "FTBFS", "FXAA", @@ -313,6 +316,7 @@ "humidmap", "hunterdelyx", "hypot", + "hookable", "ifdef", "IFRFSX", "Ilya", From 5e3ad189c86cb198b879990545f5e8b634d4ce60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20M=C3=BCller?= <34514239+appgurueu@users.noreply.github.com> Date: Fri, 4 Apr 2025 00:33:25 +0200 Subject: [PATCH 4/4] Apply suggestions from review Co-authored-by: sfan5 --- content/for-creators/compatibility.md | 5 ++++- content/for-players/compatibility.md | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/content/for-creators/compatibility.md b/content/for-creators/compatibility.md index f68e764..d969cea 100644 --- a/content/for-creators/compatibility.md +++ b/content/for-creators/compatibility.md @@ -63,7 +63,7 @@ These are called *regressions*: Something that used to work no longer does. Regressions are not strictly limited to documented behavior: The documentation is not a practically complete specification, -so exceptions will be made as is sensible. +so exceptions are commonly made, where the engine developers work to preserve a previous behavior even if it was undocumented. Depending on the impact, regressions concerning undocumented behavior may also be considered important enough to be fixed. @@ -78,6 +78,9 @@ You need to decide whether older clients not supporting newer features is game-breaking and older clients have to be prevented from playing, or whether you can implement sensible fallbacks. +When writing a game you can provide an appropriate default value for `protocol_version_min` +in `minetest.conf` to facilitate this. + {{< notice tip >}} You can use `core.get_player_information` to get protocol versions and `core.protocol_versions` to relate them to Luanti client versions. For example, to check whether a client diff --git a/content/for-players/compatibility.md b/content/for-players/compatibility.md index 417a697..2204ecf 100644 --- a/content/for-players/compatibility.md +++ b/content/for-players/compatibility.md @@ -9,7 +9,7 @@ safely upgrade your client and continue playing the games and joining the server {{< notice tip >}} Check out the compatibility notes in [the changelog](https://docs.luanti.org/about/changelog/) -when upgrading. +before upgrading. {{< /notice >}} ## Client and Server @@ -58,6 +58,8 @@ that world need no longer be compatible with older Luanti versions, e.g. because compression has been upgraded or legacy serialization formats have been upgraded to more modern ones. +If you want to be on the safe side, make regular backups of your worlds. + ## Command-Line Interface The backwards compatibility guarantee does currently not extend to the command-line interface,