-
Notifications
You must be signed in to change notification settings - Fork 23
Document compatibility guarantee precisely #223
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,157 @@ | ||||||||||||||||||||||||
--- | ||||||||||||||||||||||||
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 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. | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
{{< 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. | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
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 | ||||||||||||||||||||||||
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"]` | ||||||||||||||||||||||||
appgurueu marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||
{{< /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] | ||||||||||||||||||||||||
Comment on lines
+95
to
+101
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we compress this this?
Suggested change
|
||||||||||||||||||||||||
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 (`_`); | ||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Redundant documentation. Please refer to |
||||||||||||||||||||||||
if multiple mods share the same namespace, using the mod name for namespacing is recommended. | ||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Example might be good. |
||||||||||||||||||||||||
|
||||||||||||||||||||||||
[^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) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
--- | ||
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/) | ||
before 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, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thought: this whole file is written in a specification style ("should" over "is/are" or "will") which isn't very reassuring to readers There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would just shorten the entire section to this:
|
||
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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. curiously this sentence is assertive while in practice it's more of a "mostly" |
||
|
||
## 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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "... in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. generally, both in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't need more details, but context. "Omit punchers" without any context just sounds confusing. |
||
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. | ||
Comment on lines
+40
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. examples are good but this may be too technical There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i just wonder if the point is clear without the example. if not, maybe we can find a better example? |
||
|
||
Backwards compatibility is not absolute. | ||
Sometimes old mods or games will break because a bug has been fixed, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should probably also be in the for-creators file. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is here deliberately - it explains to players that sometimes the engine will break content, and the solution may be to upgrade that content. like with the bone override bugfix. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it should be here. But also in for-creators, because this info is part of the API backwards compatibility doc. Creators need to know that it is possible that bugs in (non-side) effects can be 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. | ||
appgurueu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should probably mention the Also, while serialization formats are usually not deprecated, db backends are. |
||
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, | ||
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) |
Uh oh!
There was an error while loading. Please reload this page.