Skip to content

Commit 691cce2

Browse files
committed
Start documenting warnings
1 parent 09ef167 commit 691cce2

2 files changed

Lines changed: 270 additions & 0 deletions

File tree

content/for-creators/warnings.md

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
---
2+
title: Warnings
3+
---
4+
5+
# Warnings
6+
7+
When you run Luanti, it often produces helpful warnings
8+
that indicate issues with mods and games that need to be addressed.
9+
Most commonly, these are *deprecation warnings* for APIs that
10+
will change in a future Luanti version.
11+
This document explains some of the more frequently encountered warnings and how to resolve them.
12+
13+
## Log levels
14+
15+
As a mod developer, you might want to set `chat_log_level = warning` to see client warnings right in your chat.
16+
17+
Your `debug_log_level` should be at least `warning`; you can then find warnings in `debug.txt`.
18+
19+
If you run Luanti in a terminal, you should see warnings in its output.
20+
21+
Note that stack traces are logged at `info` log level.
22+
23+
## Global variable access
24+
25+
Using a static analysis tool like [luacheck](https://github.com/lunarmodules/luacheck/)
26+
to catch mistakes related to global variables *before the broken code is run* is strongly recommended.
27+
Luanti also has its own rudimentary warnings for some basic yet frequent mistakes *at runtime*:
28+
29+
> Undeclared global variable "..." accessed at ...
30+
31+
You are trying to access a global variable which does not exist.
32+
This is likely a bug: The intent is to access a (local) variable, but instead you get `nil`,
33+
for example because you mistyped the variable, the variable declaration was moved,
34+
or the assignment to a global variable was moved.
35+
36+
```lua
37+
local bar = 42
38+
...
39+
local foo = baz -- typo! meant bar!
40+
print(foo) -- unexpected nil
41+
```
42+
43+
If you want to check whether a global variable does exist, for example for a mod you're optionally depending on,
44+
you can use either `rawget(_G, "name")` or `core.global_exists("name")`.
45+
After you have done the check, you can simply access the global variable, though you may want to localize it instead:
46+
47+
```lua
48+
-- at the top of the file:
49+
local my_opt_dep = rawget(_G, "my_opt_dep")
50+
...
51+
-- somewhere deep in the remaining code:
52+
if my_opt_dep then my_opt_dep.frobnicate(...) end
53+
```
54+
55+
> Assignment to undeclared global variable "..."
56+
57+
You are assigning a value to a global variable which was not assigned at load time.
58+
This usually happens when you forgot to make a variable `local`:
59+
60+
```lua
61+
local function frognicate(...)
62+
pi = 3.14 -- oops! should be local!
63+
end
64+
```
65+
66+
This is typically just a minor code quality issue.
67+
However it is likely to lead to bugs, especially if this happens in multiple places:
68+
You may overwrite another mod's global variables accidentally;
69+
recursive functions may overwrite what ought to be local variables.
70+
71+
Instead, you should use a local variable.
72+
In general, mods should avoid polluting global variables.
73+
If your mod needs to expose an API, it is recommended to use a single global variable named after the mod.
74+
75+
## Media files
76+
77+
> Server: ignoring file as it has disallowed characters: "<filename>"
78+
79+
A file is not being considered as a media file as it contains disallowed characters.
80+
You can use `find -name <filename>` to find the path of the offending file.
81+
82+
Your media files should only use the following characters in their name:
83+
84+
* ASCII letters (`a`-`z`, `A`-`Z`)
85+
* ASCII digits (`0`-`9`)
86+
* Underscore (`_`)
87+
* Hyphen (`-`)
88+
* Period (`.`)
89+
90+
The fix is simply to rename or, if obsolete, remove the file.
91+
92+
By convention, your media file names should typically start with the mod name followed by an underscore.
93+
This avoids conflicts and makes it clear which mod a file belongs to.
94+
95+
### PNG
96+
97+
> iCCP: known incorrect sRGB profile
98+
99+
This warning concerning color profiles is produced by libpng.
100+
How to fix it is discussed e.g. [on StackOverflow](https://stackoverflow.com/questions/22745076/libpng-warning-iccp-known-incorrect-srgb-profile).
101+
Re-exporting images with a proper exporter, e.g. using ImageMagick's `mogrify`, fixes the files.
102+
103+
> Interlace handling should be turned on when using `png_read_image`
104+
105+
[Adam7 interlacing](https://en.wikipedia.org/wiki/Adam7_algorithm)
106+
lets someone who has only partially received an image see a degraded version of it.
107+
Because Luanti only loads images once they have been fully received,
108+
and interlacing typically increases file size, there is no point at all in using interlacing.
109+
110+
Export your images without interlacing.
111+
Make sure that the "Interlacing (Adam7)" checkbox is unchecked when exporting PNGs from GIMP.
112+
113+
### glTF
114+
115+
> embedded images are not supported
116+
117+
Your mesh contains embedded images which will be ignored by Luanti.
118+
This unnecessarily increases file size and might confuse people who work with the model.
119+
120+
Textures are supplied via the `textures` property (for entities) or the `tiles` node definition field (for nodes).
121+
122+
If you're already using a different texture or after you have extracted the texture, you can simply strip images.
123+
Both extracting and stripping images can be done using [gltfutil](https://github.com/luanti-org/modtools).
124+
(Since `.gltf` files are just JSON, they are also fairly easy to edit manually.
125+
In this case, you need to remove the `"images"` property and remove the `"source"` property from all textures.)
126+
127+
Note that URI references to external images are not supported by Luanti
128+
and hence should not appear in your glTF files either.
129+
130+
> multiple animations are not supported
131+
132+
The mesh contains multiple glTF animations ("timelines"),
133+
but Luanti only supports a single timeline and ignores all timelines except for the first one.
134+
135+
You need to batch all animations into a single one and use frame ranges within this animation.
136+
137+
See also [Using Blender](/for-creators/models/using-blender/).
138+
139+
> negative weights
140+
141+
The mesh contains negative vertex weights which were ignored.
142+
The affected weights should be set to zero (or outright removed via some other means) instead.
143+
144+
> nodes using matrix transforms must not be animated
145+
146+
A node uses a matrix transformation, yet there is an animation channel targeting this node.
147+
This is problematic because the TRS (translation, rotation, scale) decomposition of the matrix need not exist,
148+
and even if it does exist, need not be unique (e.g. half-turns are equivalent to inverting an axis).
149+
150+
For reasons like these, glTF does not allow animated nodes to use matrix transforms.
151+
Luanti will warn about this and ignore the animation.
152+
153+
If you do want to animate the node, decompose the matrix into TRS properties yourself.
154+
Otherwise simply remove the animation channel targeting the node.
155+
156+
## Deprecation warnings
157+
158+
Luanti typically logs deprecation warnings if you use the API in a way that will stop working in a future version.
159+
Make sure to check the "compatibility notes" section of the relevant changelog.
160+
161+
If you want to continue supporting older Luanti versions,
162+
you might have to check for the existence of an API and fall back to using the legacy API if necessary.
163+
164+
> Mod ... at ...:
165+
> Mods not having a `mod.conf` file with the name is deprecated.
166+
> `depends.txt` is deprecated, please use `mod.conf` instead.
167+
> `description.txt` is deprecated, please use `mod.conf` instead.
168+
169+
Very old Luanti versions used to expect mod metadata in a bunch of separate files.
170+
The mod name was taken to be simply the folder name.
171+
(This sometimes caused problems when users downloaded mods and got a folder with a different name, e.g. `mod-master`.)
172+
173+
Newer Luanti versions expect mod metadata, including the mod name, in a `mod.conf` file.
174+
175+
If `depends.txt` looked like this:
176+
177+
```
178+
my_dep_1
179+
my_dep_2
180+
my_opt_dep_1?
181+
my_opt_dep_2?
182+
```
183+
184+
you would create a `mod.conf` in the mod folder with the following contents:
185+
186+
```
187+
name = <folder name>
188+
depends = my_dep_1, my_dep_2
189+
optional_depends = my_opt_dep_1, my_opt_dep_2
190+
description = <contents of description.txt>
191+
```
192+
193+
> Field "use_texture_alpha" on node ...: Boolean values are deprecated; use the new choices
194+
195+
Luanti now gives more fine-grained control over node `use_texture_alpha`.
196+
If your node is supposed to be opaque (`use_texture_alpha = false`), you should use `use_texture_alpha = "opaque"`.
197+
This enables some optimizations and makes cheating with texture packs harder.
198+
If your node is supposed to have transparent areas, but each pixel is either fully opaque or fully transparent,
199+
use `use_texture_alpha = "clip"`.
200+
Only if your node needs semitransparent areas should you pick `use_texture_alpha = "blend"`.
201+
Always using `use_texture_alpha = "blend"` may have disastrous consequences for rendering performance.
202+
203+
> Field "image" on TileDef: Deprecated: new name is "name".
204+
205+
You have a node tile table with `{image = "...", ...}`; it should be `{name = "...", ...}` instead.
206+
207+
> Reading initial object properties directly from an entity definition is deprecated,
208+
> move it to the 'initial_properties' table instead. (Property 'prop' in entity '...')
209+
210+
This happens if your code looks something like this:
211+
212+
```lua
213+
core.register_entity("my_mod:my_ent", {
214+
prop = ..., -- initial property right in the entity definition table :(
215+
...,
216+
})
217+
```
218+
219+
which means that `self.prop` will evaluate to the *initial* property;
220+
modifying `self.prop` will modify the common *initial* property for everyone.
221+
This is a frequent source of mistakes.
222+
223+
If you want to work with per-instance properties, you need to use
224+
`self.object:set_properties({prop = ...})` for updates,
225+
and `self.object:get_properties().prop` to query them
226+
(for performance reasons, you might want to cache this).
227+
228+
Your entity definition should look like this:
229+
230+
```lua
231+
core.register_entity("my_mod:my_ent", {
232+
initial_properties = {
233+
prop = ..., -- initial property in the proper table :)
234+
...,
235+
},
236+
...
237+
})
238+
```
239+
240+
If you happened to access initial properties via `self.prop` or `entity_def.prop`,
241+
you of course now need to access them as
242+
`self.initial_properties.prop` resp. `entity_def.initial_properties.prop` instead.
243+
244+
> Deprecated call to `set_bone_position`, use `set_bone_override` instead
245+
246+
Do what it says and switch to the new API.
247+
Be careful: This is not just a rename, `set_bone_override` expects its arguments in a slightly different format.
248+
249+
> Deprecated call to `get_attribute`, use MetaDataRef methods instead.
250+
251+
Instead of `player:get_attribute(name)`, use `player:get_meta():get(name)`.
252+
253+
> Deprecated call to `set_attribute`, use MetaDataRef methods instead.
254+
255+
Instead of `player:set_attribute(name, value)`, use `player:get_meta():set_string(name, value)`.
256+
257+
> Calling `get_connected_players()` at mod load time is deprecated
258+
259+
Such a call is pointless as it will always be `{}`.
260+
Doing anything "for each connected player" at load time simply makes no sense:
261+
There are no connected players.
262+
263+
This warning likely requires eliminating some dead code,
264+
and possibly a bit of refactoring, to resolve properly.
265+
Often, it might makes sense to postpone the call to the first server step
266+
via `core.after(0, my_mod_step)`.
267+
(A common cause is that some mod "step" function is run initially at mod load time and iterates over connected players.)

cspell.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,9 @@
251251
"Freeminer",
252252
"freemove",
253253
"freetype",
254+
"frobnicate",
254255
"Froggo",
256+
"frognicate",
255257
"FSAA",
256258
"FTBFS",
257259
"FXAA",
@@ -530,6 +532,7 @@
530532
"modstorage",
531533
"modstore",
532534
"modtools",
535+
"mogrify",
533536
"monoids",
534537
"Montandalar",
535538
"moveresult",

0 commit comments

Comments
 (0)