diff --git a/doc/' b/doc/'
deleted file mode 100644
index aee3552b7a..0000000000
--- a/doc/'
+++ /dev/null
@@ -1,12073 +0,0 @@
-Luanti Lua Modding API Reference
-================================
-
-**WARNING**: if you're looking for the `minetest` namespace (e.g. `minetest.something`),
-it's now called `core` due to the renaming of Luanti (formerly Minetest).
-`minetest` will keep existing as an alias, so that old code won't break.
-
-Note that `core` has already existed since version 0.4.10, so you can use it
-safely without breaking backwards compatibility.
-
-* More information at
-* Additional documentation:
-* (Unofficial) Luanti Modding Book by rubenwardy:
-* Modding tools:
-
-Introduction
-------------
-
-Content and functionality can be added to Luanti using Lua scripting
-in run-time loaded mods.
-
-A mod is a self-contained bunch of scripts, textures and other related
-things, which is loaded by and interfaces with Luanti.
-
-Mods are contained and ran solely on the server side. Definitions and media
-files are automatically transferred to the client.
-
-If you see a deficiency in the API, feel free to attempt to add the
-functionality in the engine and API, and to document it here.
-
-Programming in Lua
-------------------
-
-If you have any difficulty in understanding this, please read
-[Programming in Lua](http://www.lua.org/pil/).
-
-Startup
--------
-
-Mods are loaded during server startup from the mod load paths by running
-the `init.lua` scripts in a shared environment.
-
-Paths
------
-
-Luanti keeps and looks for files mostly in two paths. `path_share` or `path_user`.
-
-`path_share` contains possibly read-only content for the engine (incl. games and mods).
-`path_user` contains mods or games installed by the user but also the users
-worlds or settings.
-
-With a local build (`RUN_IN_PLACE=1`) `path_share` and `path_user` both point to
-the build directory. For system-wide builds on Linux the share path is usually at
-`/usr/share/minetest` while the user path resides in `.minetest` in the home directory.
-Paths on other operating systems will differ.
-
-Games
-=====
-
-Games are looked up from:
-
-* `$path_share/games//`
-* `$path_user/games//`
-
-Where `` is unique to each game.
-
-The game directory can contain the following files:
-
-* `game.conf`, with the following keys:
- * `title`: Required, a human-readable title to address the game, e.g. `title = Minetest Game`.
- * `name`: (Deprecated) same as title.
- * `description`: Short description to be shown in the content tab.
- See [Translating content meta](#translating-content-meta).
- * `first_mod`: Use this to specify the mod that must be loaded before any other mod.
- * `last_mod`: Use this to specify the mod that must be loaded after all other mods
- * `allowed_mapgens = `
- e.g. `allowed_mapgens = v5,v6,flat`
- Mapgens not in this list are removed from the list of mapgens for the
- game.
- If not specified, all mapgens are allowed.
- * `disallowed_mapgens = `
- e.g. `disallowed_mapgens = v5,v6,flat`
- These mapgens are removed from the list of mapgens for the game.
- When both `allowed_mapgens` and `disallowed_mapgens` are
- specified, `allowed_mapgens` is applied before
- `disallowed_mapgens`.
- * `disallowed_mapgen_settings= `
- e.g. `disallowed_mapgen_settings = mgv5_spflags`
- These mapgen settings are hidden for this game in the world creation
- dialog and game start menu. Add `seed` to hide the seed input field.
- * `disabled_settings = `
- e.g. `disabled_settings = enable_damage, creative_mode`
- These settings are hidden for this game in the "Start game" tab
- and will be initialized as `false` when the game is started.
- Prepend a setting name with an exclamation mark to initialize it to `true`
- (this does not work for `enable_server`).
- Only these settings are supported:
- `enable_damage`, `creative_mode`, `enable_server`.
- * `map_persistent`: Specifies whether newly created worlds should use
- a persistent map backend. Defaults to `true` (= "sqlite3")
- * `author`: The author's ContentDB username.
- * `release`: Ignore this: Should only ever be set by ContentDB, as it is
- an internal ID used to track versions.
- * `textdomain`: Textdomain used to translate description. Defaults to game id.
- See [Translating content meta](#translating-content-meta).
-* `minetest.conf`:
- Used to set default settings when running this game.
-* `settingtypes.txt`:
- In the same format as the one in builtin.
- This settingtypes.txt will be parsed by the menu and the settings will be
- displayed in the "Games" category in the advanced settings tab.
-* If the game contains a folder called `textures` the server will load it as a
- texturepack, overriding mod textures.
- Any server texturepack will override mod textures and the game texturepack.
-
-Menu images
------------
-
-Games can provide custom main menu images. They are put inside a `menu`
-directory inside the game directory.
-
-The images are named `$identifier.png`, where `$identifier` is one of
-`overlay`, `background`, `footer`, `header`.
-If you want to specify multiple images for one identifier, add additional
-images named like `$identifier.$n.png`, with an ascending number $n starting
-with 1, and a random image will be chosen from the provided ones.
-
-Menu music
------------
-
-Games can provide custom main menu music. They are put inside a `menu`
-directory inside the game directory.
-
-The music files are named `theme.ogg`.
-If you want to specify multiple music files for one game, add additional
-images named like `theme.$n.ogg`, with an ascending number $n starting
-with 1 (max 10), and a random music file will be chosen from the provided ones.
-
-Mods
-====
-
-Mod load path
--------------
-
-Paths are relative to the directories listed in the [Paths](#paths) section above.
-
-* `games//mods/`
-* `mods/`
-* `worlds//worldmods/`
-
-World-specific games
---------------------
-
-It is possible to include a game in a world; in this case, no mods or
-games are loaded or checked from anywhere else.
-
-This is useful for e.g. adventure worlds and happens if the `/game/`
-directory exists.
-
-Mods should then be placed in `/game/mods/`.
-
-Modpacks
---------
-
-Mods can be put in a subdirectory, if the parent directory, which otherwise
-should be a mod, contains a file named `modpack.conf`.
-The file is a key-value store of modpack details.
-
-* `name`: The modpack name. Allows Luanti to determine the modpack name even
- if the folder is wrongly named.
-* `title`: A human-readable title to address the modpack. See [Translating content meta](#translating-content-meta).
-* `description`: Description of mod to be shown in the Mods tab of the main
- menu. See [Translating content meta](#translating-content-meta).
-* `author`: The author's ContentDB username.
-* `release`: Ignore this: Should only ever be set by ContentDB, as it is an
- internal ID used to track versions.
-* `textdomain`: Textdomain used to translate title and description. Defaults to modpack name.
- See [Translating content meta](#translating-content-meta).
-
-Note: to support 0.4.x, please also create an empty modpack.txt file.
-
-Mod directory structure
------------------------
-
- mods
- ├── modname
- │ ├── mod.conf
- │ ├── screenshot.png
- │ ├── settingtypes.txt
- │ ├── init.lua
- │ ├── models
- │ ├── textures
- │ │ ├── modname_stuff.png
- │ │ ├── modname_something_else.png
- │ │ ├── subfolder_foo
- │ │ │ ├── modname_more_stuff.png
- │ │ │ └── another_subfolder
- │ │ └── bar_subfolder
- │ ├── sounds
- │ ├── fonts
- │ ├── media
- │ ├── locale
- │ └──
- └── another
-
-### modname
-
-The location of this directory can be fetched by using
-`core.get_modpath(modname)`.
-
-### mod.conf
-
-A `Settings` file that provides meta information about the mod.
-
-* `name`: The mod name. Allows Luanti to determine the mod name even if the
- folder is wrongly named.
-* `title`: A human-readable title to address the mod. See [Translating content meta](#translating-content-meta).
-* `description`: Description of mod to be shown in the Mods tab of the main
- menu. See [Translating content meta](#translating-content-meta).
-* `depends`: A comma separated list of dependencies. These are mods that must be
- loaded before this mod.
-* `optional_depends`: A comma separated list of optional dependencies.
- Like a dependency, but no error if the mod doesn't exist.
-* `author`: The author's ContentDB username.
-* `release`: Ignore this: Should only ever be set by ContentDB, as it is an
- internal ID used to track versions.
-* `textdomain`: Textdomain used to translate title and description. Defaults to modname.
- See [Translating content meta](#translating-content-meta).
-
-### `screenshot.png`
-
-A screenshot shown in the mod manager within the main menu. It should
-have an aspect ratio of 3:2 and a minimum size of 300×200 pixels.
-
-### `depends.txt`
-
-**Deprecated:** you should use mod.conf instead.
-
-This file is used if there are no dependencies in mod.conf.
-
-List of mods that have to be loaded before loading this mod.
-
-A single line contains a single modname.
-
-Optional dependencies can be defined by appending a question mark
-to a single modname. This means that if the specified mod
-is missing, it does not prevent this mod from being loaded.
-
-### `description.txt`
-
-**Deprecated:** you should use mod.conf instead.
-
-This file is used if there is no description in mod.conf.
-
-A file containing a description to be shown in the Mods tab of the main menu.
-
-### `settingtypes.txt`
-
-The format is documented in `builtin/settingtypes.txt`.
-It is parsed by the main menu settings dialogue to list mod-specific
-settings in the "Mods" category.
-
-`core.settings` can be used to read custom or engine settings.
-See [Settings](#settings).
-
-### `init.lua`
-
-The main Lua script. Running this script should register everything it
-wants to register. Subsequent execution depends on Luanti calling the
-registered callbacks.
-
-### `textures`, `sounds`, `media`, `models`, `locale`, `fonts`
-
-Media files (textures, sounds, whatever) that will be transferred to the
-client and will be available for use by the mod and translation files for
-the clients (see [Translations](#translations)). Accepted characters for names are:
-
- a-zA-Z0-9_.-
-
-Accepted formats are:
-
- images: .png, .jpg, .tga
- sounds: .ogg vorbis
- models: .x, .b3d, .obj, (since version 5.10:) .gltf, .glb
- fonts: .ttf, .woff (both since version 5.11, see notes below)
-
-Currently the engine is unable to handle files over ~16MB in size. For best
-performance you should keep your media files as small as reasonably possible.
-
-Other formats won't be sent to the client (e.g. you can store .blend files
-in a folder for convenience, without the risk that such files are transferred)
-
-It is suggested to use the folders for the purpose they are thought for,
-eg. put textures into `textures`, translation files into `locale`,
-models for entities or meshnodes into `models` et cetera.
-
-These folders and subfolders can contain subfolders.
-Subfolders with names starting with `_` or `.` are ignored.
-If a subfolder contains a media file with the same name as a media file
-in one of its parents, the parent's file is used.
-
-Although it is discouraged, a mod can overwrite a media file of any mod that it
-depends on by supplying a file with an equal name.
-
-Only a subset of model file format features is supported:
-
-Simple textured meshes (with multiple textures), optionally with normals.
-The .x, .b3d and .gltf formats additionally support (a single) animation.
-
-#### glTF
-
-Binary glTF (`.glb`) files are supported and recommended over `.gltf` files
-due to their space savings.
-
-Bone weights should be normalized, e.g. using ["normalize all" in Blender](https://docs.blender.org/manual/en/4.2/grease_pencil/modes/weight_paint/weights_menu.html#normalize-all).
-
-Note that nodes using matrix transforms must not be animated.
-This also extends to bone overrides, which must not be applied to them.
-
-You can use the [Khronos glTF validator](https://github.com/KhronosGroup/glTF-Validator)
-to check whether a model is a valid glTF file.
-
-Many glTF features are not supported *yet*, including:
-
-* Animations
- * Only a single animation is supported, use frame ranges within this animation.
- * `CUBICSPLINE` interpolation is not supported.
-* Cameras
-* Materials
- * Only base color textures are supported
- * Backface culling is overridden
- * Double-sided materials don't work
-* Alternative means of supplying data
- * Embedded images. You can use `gltfutil.py` from the
- [modding tools](https://github.com/luanti-org/modtools) to strip or extract embedded images.
- * References to files via URIs
-
-Textures are supplied solely via the same means as for the other model file formats:
-The `textures` object property, the `tiles` node definition field and
-the list of textures used in the `model[]` formspec element.
-
-The order in which textures are to be supplied
-is that in which they appear in the `textures` array in the glTF file.
-
-Do not rely on glTF features not being supported; they may be supported in the future.
-The backwards compatibility guarantee does not extend to ignoring unsupported features.
-
-For example, if your model used an emissive material,
-you should expect that a future version of Luanti may respect this,
-and thus cause your model to render differently there.
-
-#### Custom fonts
-
-You can supply custom fonts in TrueType Font (`.ttf`) or Web Open Font Format (`.woff`) format.
-The former is supported primarily for convenience. The latter is preferred due to its compression.
-
-In the future, having multiple custom fonts and the ability to switch between them is planned,
-but for now this feature is limited to the ability to override Luanti's default fonts via mods.
-It is recommended that this only be used by game mods to set a look and feel.
-
-The stems (file names without extension) are self-explanatory:
-
-* Regular variants:
- * `regular`
- * `bold`
- * `italic`
- * `bold_italic`
-* Monospaced variants:
- * `mono`
- * `mono_bold`
- * `mono_italic`
- * `mono_bold_italic`
-
-Naming conventions
-------------------
-
-Registered names should generally be in this format:
-
- modname:
-
-`` can have these characters:
-
- a-zA-Z0-9_
-
-This is to prevent conflicting names from corrupting maps and is
-enforced by the mod loader.
-
-Registered names can be overridden by prefixing the name with `:`. This can
-be used for overriding the registrations of some other mod.
-
-The `:` prefix can also be used for maintaining backwards compatibility.
-
-### Example
-
-In the mod `experimental`, there is the ideal item/node/entity name `tnt`.
-So the name should be `experimental:tnt`.
-
-Any mod can redefine `experimental:tnt` by using the name
-
- :experimental:tnt
-
-when registering it. For this to work correctly, that mod must have
-`experimental` as a dependency.
-
-
-
-
-Aliases
-=======
-
-Aliases of itemnames can be added by using
-`core.register_alias(alias, original_name)` or
-`core.register_alias_force(alias, original_name)`.
-
-This adds an alias `alias` for the item called `original_name`.
-From now on, you can use `alias` to refer to the item `original_name`.
-
-The only difference between `core.register_alias` and
-`core.register_alias_force` is that if an item named `alias` already exists,
-`core.register_alias` will do nothing while
-`core.register_alias_force` will unregister it.
-
-This can be used for maintaining backwards compatibility.
-
-This can also set quick access names for things, e.g. if
-you have an item called `epiclylongmodname:stuff`, you could do
-
- core.register_alias("stuff", "epiclylongmodname:stuff")
-
-and be able to use `/giveme stuff`.
-
-Mapgen aliases
---------------
-
-In a game, a certain number of these must be set to tell core mapgens which
-of the game's nodes are to be used for core mapgen generation. For example:
-
- core.register_alias("mapgen_stone", "default:stone")
-
-### Aliases for non-V6 mapgens
-
-#### Essential aliases
-
-* `mapgen_stone`
-* `mapgen_water_source`
-* `mapgen_river_water_source`
-
-`mapgen_river_water_source` is required for mapgens with sloping rivers where
-it is necessary to have a river liquid node with a short `liquid_range` and
-`liquid_renewable = false` to avoid flooding.
-
-#### Optional aliases
-
-* `mapgen_lava_source`
-
-Fallback lava node used if cave liquids are not defined in biome definitions.
-Deprecated, define cave liquids in biome definitions instead.
-
-* `mapgen_cobble`
-
-Fallback node used if dungeon nodes are not defined in biome definitions.
-Deprecated, define dungeon nodes in biome definitions instead.
-
-### Aliases for Mapgen V6
-
-#### Essential
-
-* `mapgen_stone`
-* `mapgen_water_source`
-* `mapgen_lava_source`
-* `mapgen_dirt`
-* `mapgen_dirt_with_grass`
-* `mapgen_sand`
-
-* `mapgen_tree`
-* `mapgen_leaves`
-* `mapgen_apple`
-
-* `mapgen_cobble`
-
-#### Optional
-
-* `mapgen_gravel` (falls back to stone)
-* `mapgen_desert_stone` (falls back to stone)
-* `mapgen_desert_sand` (falls back to sand)
-* `mapgen_dirt_with_snow` (falls back to dirt_with_grass)
-* `mapgen_snowblock` (falls back to dirt_with_grass)
-* `mapgen_snow` (not placed if missing)
-* `mapgen_ice` (falls back to water_source)
-
-* `mapgen_jungletree` (falls back to tree)
-* `mapgen_jungleleaves` (falls back to leaves)
-* `mapgen_junglegrass` (not placed if missing)
-* `mapgen_pine_tree` (falls back to tree)
-* `mapgen_pine_needles` (falls back to leaves)
-
-* `mapgen_stair_cobble` (falls back to cobble)
-* `mapgen_mossycobble` (falls back to cobble)
-* `mapgen_stair_desert_stone` (falls back to desert_stone)
-
-### Setting the node used in Mapgen Singlenode
-
-By default the world is filled with air nodes. To set a different node use e.g.:
-
- core.register_alias("mapgen_singlenode", "default:stone")
-
-
-
-
-Textures
-========
-
-Mods should generally prefix their textures with `modname_`, e.g. given
-the mod name `foomod`, a texture could be called:
-
- foomod_foothing.png
-
-Textures are referred to by their complete name, or alternatively by
-stripping out the file extension:
-
-* e.g. `foomod_foothing.png`
-* e.g. `foomod_foothing`
-
-Supported texture formats are PNG (`.png`), JPEG (`.jpg`) and Targa (`.tga`).
-
-Luanti generally uses nearest-neighbor upscaling for textures to preserve the crisp
-look of pixel art (low-res textures).
-Users can optionally enable bilinear and/or trilinear filtering. However, to avoid
-everything becoming blurry, textures smaller than 192px will either not be filtered,
-or will be upscaled to that minimum resolution first without filtering.
-
-This is subject to change to move more control to the Lua API, but you can rely on
-low-res textures not suddenly becoming filtered.
-
-Texture modifiers
------------------
-
-There are various texture modifiers that can be used
-to let the client generate textures on-the-fly.
-The modifiers are applied directly in sRGB colorspace,
-i.e. without gamma-correction.
-
-### Notes
-
- * `TEXMOD_UPSCALE`: The texture with the lower resolution will be automatically
- upscaled to the higher resolution texture.
-
-### Texture overlaying
-
-Textures can be overlaid by putting a `^` between them.
-
-Warning: If the lower and upper pixels are both semi-transparent, this operation
-does *not* do alpha blending, and it is *not* associative. Otherwise it does
-alpha blending in srgb color space.
-
-Example:
-
- default_dirt.png^default_grass_side.png
-
-`default_grass_side.png` is overlaid over `default_dirt.png`.
-
-*See notes: `TEXMOD_UPSCALE`*
-
-
-### Texture grouping
-
-Textures can be grouped together by enclosing them in `(` and `)`.
-
-Example: `cobble.png^(thing1.png^thing2.png)`
-
-A texture for `thing1.png^thing2.png` is created and the resulting
-texture is overlaid on top of `cobble.png`.
-
-### Escaping
-
-Modifiers that accept texture names (e.g. `[combine`) accept escaping to allow
-passing complex texture names as arguments. Escaping is done with backslash and
-is required for `^`, `:` and `\`.
-
-Example: `cobble.png^[lowpart:50:color.png\^[mask\:trans.png`
-Or as a Lua string: `"cobble.png^[lowpart:50:color.png\\^[mask\\:trans.png"`
-
-The lower 50 percent of `color.png^[mask:trans.png` are overlaid
-on top of `cobble.png`.
-
-### Advanced texture modifiers
-
-#### Crack
-
-* `[crack::
`
-* `[cracko::
`
-* `[crack:::
`
-* `[cracko:::
`
-
-Parameters:
-
-* ``: tile count (in each direction)
-* ``: animation frame count
-* `
`: current animation frame
-
-Draw a step of the crack animation on the texture.
-`crack` draws it normally, while `cracko` lays it over, keeping transparent
-pixels intact.
-
-Example:
-
- default_cobble.png^[crack:10:1
-
-#### `[combine:x:,=:,=:...`
-
-* ``: width
-* ``: height
-* ``: x position, negative numbers allowed
-* ``: y position, negative numbers allowed
-* ``: texture to combine
-
-Creates a texture of size `` times `` and blits the listed files to their
-specified coordinates.
-
-Example:
-
- [combine:16x32:0,0=default_cobble.png:0,16=default_wood.png
-
-#### `[resize:x`
-
-Resizes the texture to the given dimensions.
-
-Example:
-
- default_sandstone.png^[resize:16x16
-
-#### `[opacity:`
-
-Makes the base image transparent according to the given ratio.
-
-`r` must be between 0 (transparent) and 255 (opaque).
-
-Example:
-
- default_sandstone.png^[opacity:127
-
-#### `[invert:`
-
-Inverts the given channels of the base image.
-Mode may contain the characters "r", "g", "b", "a".
-Only the channels that are mentioned in the mode string will be inverted.
-
-Example:
-
- default_apple.png^[invert:rgb
-
-#### `[brighten`
-
-Brightens the texture.
-
-Example:
-
- tnt_tnt_side.png^[brighten
-
-#### `[noalpha`
-
-Makes the texture completely opaque.
-
-Example:
-
- default_leaves.png^[noalpha
-
-#### `[makealpha:,,`
-
-Convert one color to transparency.
-
-Example:
-
- default_cobble.png^[makealpha:128,128,128
-
-#### `[transform`
-
-* ``: transformation(s) to apply
-
-Rotates and/or flips the image.
-
-`` can be a number (between 0 and 7) or a transform name.
-Rotations are counter-clockwise.
-
- 0 I identity
- 1 R90 rotate by 90 degrees
- 2 R180 rotate by 180 degrees
- 3 R270 rotate by 270 degrees
- 4 FX flip X
- 5 FXR90 flip X then rotate by 90 degrees
- 6 FY flip Y
- 7 FYR90 flip Y then rotate by 90 degrees
-
-Example:
-
- default_stone.png^[transformFXR90
-
-#### `[inventorycube{{{`
-
-Escaping does not apply here and `^` is replaced by `&` in texture names
-instead.
-
-Create an inventory cube texture using the side textures.
-
-Example:
-
- [inventorycube{grass.png{dirt.png&grass_side.png{dirt.png&grass_side.png
-
-Creates an inventorycube with `grass.png`, `dirt.png^grass_side.png` and
-`dirt.png^grass_side.png` textures
-
-#### `[fill:x:,:`
-
-* ``: width
-* ``: height
-* ``: x position
-* ``: y position
-* ``: a `ColorString`.
-
-Creates a texture of the given size and color, optionally with an `,`
-position. An alpha value may be specified in the `Colorstring`.
-
-The optional `,` position is only used if the `[fill` is being overlaid
-onto another texture with '^'.
-
-When `[fill` is overlaid onto another texture it will not upscale or change
-the resolution of the texture, the base texture will determine the output
-resolution.
-
-Examples:
-
- [fill:16x16:#20F02080
- texture.png^[fill:8x8:4,4:red
-
-#### `[lowpart::`
-
-Blit the lower ``% part of `` on the texture.
-
-Example:
-
- base.png^[lowpart:25:overlay.png
-
-#### `[verticalframe::`
-
-* ``: animation frame count
-* ``: current animation frame
-
-Crops the texture to a frame of a vertical animation.
-
-Example:
-
- default_torch_animated.png^[verticalframe:16:8
-
-#### `[mask:`
-
-Apply a mask to the base image.
-
-The mask is applied using binary AND.
-
-*See notes: `TEXMOD_UPSCALE`*
-
-#### `[sheet:x:,`
-
-Retrieves a tile at position x, y (in tiles, 0-indexed)
-from the base image, which it assumes to be a tilesheet
-with dimensions w, h (in tiles).
-
-#### `[colorize::`
-
-Colorize the textures with the given color.
-`` is specified as a `ColorString`.
-`` is an int ranging from 0 to 255 or the word "`alpha`". If
-it is an int, then it specifies how far to interpolate between the
-colors where 0 is only the texture color and 255 is only ``. If
-omitted, the alpha of `` will be used as the ratio. If it is
-the word "`alpha`", then each texture pixel will contain the RGB of
-`` and the alpha of `` multiplied by the alpha of the
-texture pixel.
-
-#### `[colorizehsl:::`
-
-Colorize the texture to the given hue. The texture will be converted into a
-greyscale image as seen through a colored glass, like "Colorize" in GIMP.
-Saturation and lightness can optionally be adjusted.
-
-`` should be from -180 to +180. The hue at 0° on an HSL color wheel is
-red, 60° is yellow, 120° is green, and 180° is cyan, while -60° is magenta
-and -120° is blue.
-
-`` and `` are optional adjustments.
-
-`` is from -100 to +100, with a default of 0
-
-`` is from 0 to 100, with a default of 50
-
-#### `[multiply:`
-
-Multiplies texture colors with the given color.
-`` is specified as a `ColorString`.
-Result is more like what you'd expect if you put a color on top of another
-color, meaning white surfaces get a lot of your new color while black parts
-don't change very much.
-
-A Multiply blend can be applied between two textures by using the overlay
-modifier with a brightness adjustment:
-
- textureA.png^[contrast:0:-64^[overlay:textureB.png
-
-#### `[screen:`
-
-Apply a Screen blend with the given color. A Screen blend is the inverse of
-a Multiply blend, lightening images instead of darkening them.
-
-`` is specified as a `ColorString`.
-
-A Screen blend can be applied between two textures by using the overlay
-modifier with a brightness adjustment:
-
- textureA.png^[contrast:0:64^[overlay:textureB.png
-
-#### `[hsl:::`
-
-Adjust the hue, saturation, and lightness of the texture. Like
-"Hue-Saturation" in GIMP, but with 0 as the mid-point.
-
-`` should be from -180 to +180
-
-`` and `` are optional, and both percentages.
-
-`` is from -100 to +100.
-
-`` goes down to -100 (fully desaturated) but may go above 100,
-allowing for even muted colors to become highly saturated.
-
-#### `[contrast::`
-
-Adjust the brightness and contrast of the texture. Conceptually like
-GIMP's "Brightness-Contrast" feature but allows brightness to be wound
-all the way up to white or down to black.
-
-`` is a value from -127 to +127.
-
-`` is an optional value, from -127 to +127.
-
-If only a boost in contrast is required, an alternative technique is to
-hardlight blend the texture with itself, this increases contrast in the same
-way as an S-shaped color-curve, which avoids dark colors clipping to black
-and light colors clipping to white:
-
- texture.png^[hardlight:texture.png
-
-#### `[overlay:`
-
-Applies an Overlay blend with the two textures, like the Overlay layer mode
-in GIMP. Overlay is the same as Hard light but with the role of the two
-textures swapped, see the `[hardlight` modifier description for more detail
-about these blend modes.
-
-*See notes: `TEXMOD_UPSCALE`*
-
-#### `[hardlight:`
-
-Applies a Hard light blend with the two textures, like the Hard light layer
-mode in GIMP.
-
-Hard light combines Multiply and Screen blend modes. Light parts of the
-`` texture will lighten (screen) the base texture, and dark parts of the
-`` texture will darken (multiply) the base texture. This can be useful
-for applying embossing or chiselled effects to textures. A Hard light with the
-same texture acts like applying an S-shaped color-curve, and can be used to
-increase contrast without clipping.
-
-Hard light is the same as Overlay but with the roles of the two textures
-swapped, i.e. `A.png^[hardlight:B.png` is the same as `B.png^[overlay:A.png`
-
-*See notes: `TEXMOD_UPSCALE`*
-
-#### `[png:`
-
-Embed a base64 encoded PNG image in the texture string.
-You can produce a valid string for this by calling
-`core.encode_base64(core.encode_png(tex))`,
-where `tex` is pixel data. Refer to the documentation of these
-functions for details.
-You can use this to send disposable images such as captchas
-to individual clients, or render things that would be too
-expensive to compose with `[combine:`.
-
-IMPORTANT: Avoid sending large images this way.
-This is not a replacement for asset files, do not use it to do anything
-that you could instead achieve by just using a file.
-In particular consider `core.dynamic_add_media` and test whether
-using other texture modifiers could result in a shorter string than
-embedding a whole image, this may vary by use case.
-
-*See notes: `TEXMOD_UPSCALE`*
-
-Hardware coloring
------------------
-
-The goal of hardware coloring is to simplify the creation of
-colorful nodes. If your textures use the same pattern, and they only
-differ in their color (like colored wool blocks), you can use hardware
-coloring instead of creating and managing many texture files.
-All of these methods use color multiplication (so a white-black texture
-with red coloring will result in red-black color).
-
-### Static coloring
-
-This method is useful if you wish to create nodes/items with
-the same texture, in different colors, each in a new node/item definition.
-
-#### Global color
-
-When you register an item or node, set its `color` field (which accepts a
-`ColorSpec`) to the desired color.
-
-An `ItemStack`'s static color can be overwritten by the `color` metadata
-field. If you set that field to a `ColorString`, that color will be used.
-
-#### Tile color
-
-Each tile may have an individual static color, which overwrites every
-other coloring method. To disable the coloring of a face,
-set its color to white (because multiplying with white does nothing).
-You can set the `color` property of the tiles in the node's definition
-if the tile is in table format.
-
-### Palettes
-
-For nodes and items which can have many colors, a palette is more
-suitable. A palette is a texture, which can contain up to 256 pixels.
-Each pixel is one possible color for the node/item.
-You can register one node/item, which can have up to 256 colors.
-
-#### Palette indexing
-
-When using palettes, you always provide a pixel index for the given
-node or `ItemStack`. The palette is read from left to right and from
-top to bottom. If the palette has less than 256 pixels, then it is
-stretched to contain exactly 256 pixels (after arranging the pixels
-to one line). The indexing starts from 0.
-
-Examples:
-
-* 16x16 palette, index = 0: the top left corner
-* 16x16 palette, index = 4: the fifth pixel in the first row
-* 16x16 palette, index = 16: the pixel below the top left corner
-* 16x16 palette, index = 255: the bottom right corner
-* 2 (width) x 4 (height) palette, index = 31: the top left corner.
- The palette has 8 pixels, so each pixel is stretched to 32 pixels,
- to ensure the total 256 pixels.
-* 2x4 palette, index = 32: the top right corner
-* 2x4 palette, index = 63: the top right corner
-* 2x4 palette, index = 64: the pixel below the top left corner
-
-#### Using palettes with items
-
-When registering an item, set the item definition's `palette` field to
-a texture. You can also use texture modifiers.
-
-The `ItemStack`'s color depends on the `palette_index` field of the
-stack's metadata. `palette_index` is an integer, which specifies the
-index of the pixel to use.
-
-#### Linking palettes with nodes
-
-When registering a node, set the item definition's `palette` field to
-a texture. You can also use texture modifiers.
-The node's color depends on its `param2`, so you also must set an
-appropriate `paramtype2`:
-
-* `paramtype2 = "color"` for nodes which use their full `param2` for
- palette indexing. These nodes can have 256 different colors.
- The palette should contain 256 pixels.
-* `paramtype2 = "colorwallmounted"` for nodes which use the first
- five bits (most significant) of `param2` for palette indexing.
- The remaining three bits are describing rotation, as in `wallmounted`
- paramtype2. Division by 8 yields the palette index (without stretching the
- palette). These nodes can have 32 different colors, and the palette
- should contain 32 pixels.
- Examples:
- * `param2 = 17` is 2 * 8 + 1, so the rotation is 1 and the third (= 2 + 1)
- pixel will be picked from the palette.
- * `param2 = 35` is 4 * 8 + 3, so the rotation is 3 and the fifth (= 4 + 1)
- pixel will be picked from the palette.
-* `paramtype2 = "colorfacedir"` for nodes which use the first
- three bits of `param2` for palette indexing. The remaining
- five bits are describing rotation, as in `facedir` paramtype2.
- Division by 32 yields the palette index (without stretching the
- palette). These nodes can have 8 different colors, and the
- palette should contain 8 pixels.
- Examples:
- * `param2 = 17` is 0 * 32 + 17, so the rotation is 17 and the
- first (= 0 + 1) pixel will be picked from the palette.
- * `param2 = 35` is 1 * 32 + 3, so the rotation is 3 and the
- second (= 1 + 1) pixel will be picked from the palette.
-* `paramtype2 = "color4dir"` for nodes which use the first
- six bits of `param2` for palette indexing. The remaining
- two bits are describing rotation, as in `4dir` paramtype2.
- Division by 4 yields the palette index (without stretching the
- palette). These nodes can have 64 different colors, and the
- palette should contain 64 pixels.
- Examples:
- * `param2 = 17` is 4 * 4 + 1, so the rotation is 1 and the
- fifth (= 4 + 1) pixel will be picked from the palette.
- * `param2 = 35` is 8 * 4 + 3, so the rotation is 3 and the
- ninth (= 8 + 1) pixel will be picked from the palette.
-
-To colorize a node on the map, set its `param2` value (according
-to the node's paramtype2).
-
-### Conversion between nodes in the inventory and on the map
-
-Static coloring is the same for both cases, there is no need
-for conversion.
-
-If the `ItemStack`'s metadata contains the `color` field, it will be
-lost on placement, because nodes on the map can only use palettes.
-
-If the `ItemStack`'s metadata contains the `palette_index` field, it is
-automatically transferred between node and item forms by the engine,
-when a player digs or places a colored node.
-You can disable this feature by setting the `drop` field of the node
-to itself (without metadata).
-To transfer the color to a special drop, you need a drop table.
-
-Example:
-
-```lua
-core.register_node("mod:stone", {
- description = "Stone",
- tiles = {"default_stone.png"},
- paramtype2 = "color",
- palette = "palette.png",
- drop = {
- items = {
- -- assume that mod:cobblestone also has the same palette
- {items = {"mod:cobblestone"}, inherit_color = true },
- }
- }
-})
-```
-
-### Colored items in craft recipes
-
-Craft recipes only support item strings, but fortunately item strings
-can also contain metadata. Example craft recipe registration:
-
-```lua
-core.register_craft({
- output = core.itemstring_with_palette("wool:block", 3),
- type = "shapeless",
- recipe = {
- "wool:block",
- "dye:red",
- },
-})
-```
-
-To set the `color` field, you can use `core.itemstring_with_color`.
-
-Metadata field filtering in the `recipe` field are not supported yet,
-so the craft output is independent of the color of the ingredients.
-
-Soft texture overlay
---------------------
-
-Sometimes hardware coloring is not enough, because it affects the
-whole tile. Soft texture overlays were added to Luanti to allow
-the dynamic coloring of only specific parts of the node's texture.
-For example a grass block may have colored grass, while keeping the
-dirt brown.
-
-These overlays are 'soft', because unlike texture modifiers, the layers
-are not merged in the memory, but they are simply drawn on top of each
-other. This allows different hardware coloring, but also means that
-tiles with overlays are drawn slower. Using too much overlays might
-cause FPS loss.
-
-For inventory and wield images you can specify overlays which
-hardware coloring does not modify. You have to set `inventory_overlay`
-and `wield_overlay` fields to an image name.
-
-To define a node overlay, simply set the `overlay_tiles` field of the node
-definition. These tiles are defined in the same way as plain tiles:
-they can have a texture name, color etc.
-To skip one face, set that overlay tile to an empty string.
-
-Example (colored grass block):
-
-```lua
-core.register_node("default:dirt_with_grass", {
- description = "Dirt with Grass",
- -- Regular tiles, as usual
- -- The dirt tile disables palette coloring
- tiles = {{name = "default_grass.png"},
- {name = "default_dirt.png", color = "white"}},
- -- Overlay tiles: define them in the same style
- -- The top and bottom tile does not have overlay
- overlay_tiles = {"", "",
- {name = "default_grass_side.png"}},
- -- Global color, used in inventory
- color = "green",
- -- Palette in the world
- paramtype2 = "color",
- palette = "default_foilage.png",
-})
-```
-
-
-
-Sounds
-======
-
-Only Ogg Vorbis files are supported.
-
-For positional playing of sounds, only single-channel (mono) files are
-supported. Otherwise OpenAL will play them non-positionally.
-
-Mods should generally prefix their sound files with `modname_`, e.g. given
-the mod name "`foomod`", a sound could be called:
-
- foomod_foosound.ogg
-
-Sound group
------------
-
-A sound group is the set of all sound files, whose filenames are of the following
-format:
-`[.].ogg`
-When a sound-group is played, one the files in the group is chosen at random.
-Sound files can only be referred to by their sound-group name.
-
-Example: When playing the sound `foomod_foosound`, the sound is chosen randomly
-from the available ones of the following files:
-
-* `foomod_foosound.ogg`
-* `foomod_foosound.0.ogg`
-* `foomod_foosound.1.ogg`
-* (...)
-* `foomod_foosound.9.ogg`
-
-`SimpleSoundSpec`
------------------
-
-Specifies a sound name, gain (=volume), pitch and fade.
-This is either a string or a table.
-
-In string form, you just specify the sound name or
-the empty string for no sound.
-
-Table form has the following fields:
-
-* `name`:
- Sound-group name.
- If == `""`, no sound is played.
-* `gain`:
- Volume (`1.0` = 100%), must be non-negative.
- At the end, OpenAL clamps sound gain to a maximum of `1.0`. By setting gain for
- a positional sound higher than `1.0`, one can increase the radius inside which
- maximal gain is reached.
- Furthermore, gain of positional sounds doesn't increase inside a 1 node radius.
- The gain given here describes the gain at a distance of 3 nodes.
-* `pitch`:
- Applies a pitch-shift to the sound.
- Each factor of `2.0` results in a pitch-shift of +12 semitones.
- Must be positive.
-* `fade`:
- If > `0.0`, the sound is faded in, with this value in gain per second, until
- `gain` is reached.
-
-`gain`, `pitch` and `fade` are optional and default to `1.0`, `1.0` and `0.0`.
-
-Examples:
-
-* `""`: No sound
-* `{}`: No sound
-* `"default_place_node"`: Play e.g. `default_place_node.ogg`
-* `{name = "default_place_node"}`: Same as above
-* `{name = "default_place_node", gain = 0.5}`: 50% volume
-* `{name = "default_place_node", gain = 0.9, pitch = 1.1}`: 90% volume, 110% pitch
-
-Sound parameter table
----------------------
-
-Table used to specify how a sound is played:
-
-```lua
-{
- gain = 1.0,
- -- Scales the gain specified in `SimpleSoundSpec`.
-
- pitch = 1.0,
- -- Overwrites the pitch specified in `SimpleSoundSpec`.
-
- fade = 0.0,
- -- Overwrites the fade specified in `SimpleSoundSpec`.
-
- start_time = 0.0,
- -- Start with a time-offset into the sound.
- -- The behavior is as if the sound was already playing for this many seconds.
- -- Negative values are relative to the sound's length, so the sound reaches
- -- its end in `-start_time` seconds.
- -- It is unspecified what happens if `loop` is false and `start_time` is
- -- smaller than minus the sound's length.
- -- Available since feature `sound_params_start_time`.
-
- loop = false,
- -- If true, sound is played in a loop.
-
- pos = {x = 1, y = 2, z = 3},
- -- Play sound at a position.
- -- Can't be used together with `object`.
-
- object = ,
- -- Attach the sound to an object.
- -- Can't be used together with `pos`.
-
- to_player = name,
- -- Only play for this player.
- -- Can't be used together with `exclude_player`.
-
- exclude_player = name,
- -- Don't play sound for this player.
- -- Can't be used together with `to_player`.
-
- max_hear_distance = 32,
- -- Only play for players that are at most this far away when the sound
- -- starts playing.
- -- Needs `pos` or `object` to be set.
- -- `32` is the default.
-}
-```
-
-Examples:
-
-```lua
--- Play locationless on all clients
-{
- gain = 1.0, -- default
- fade = 0.0, -- default
- pitch = 1.0, -- default
-}
--- Play locationless to one player
-{
- to_player = name,
- gain = 1.0, -- default
- fade = 0.0, -- default
- pitch = 1.0, -- default
-}
--- Play locationless to one player, looped
-{
- to_player = name,
- gain = 1.0, -- default
- loop = true,
-}
--- Play at a location, start the sound at offset 5 seconds
-{
- pos = {x = 1, y = 2, z = 3},
- gain = 1.0, -- default
- max_hear_distance = 32, -- default
- start_time = 5.0,
-}
--- Play connected to an object, looped
-{
- object = ,
- gain = 1.0, -- default
- max_hear_distance = 32, -- default
- loop = true,
-}
--- Play at a location, heard by anyone *but* the given player
-{
- pos = {x = 32, y = 0, z = 100},
- max_hear_distance = 40,
- exclude_player = name,
-}
-```
-
-Special sound-groups
---------------------
-
-These sound-groups are played back by the engine if provided.
-
- * `player_damage`: Played when the local player takes damage (gain = 0.5)
- * `player_falling_damage`: Played when the local player takes
- damage by falling (gain = 0.5)
- * `player_jump`: Played when the local player jumps
- * `default_dig_`: Default node digging sound (gain = 0.5)
- (see node sound definition for details)
-
-Registered definitions
-======================
-
-Anything added using certain [Registration functions](#registration-functions) gets added to one or more
-of the global [Registered definition tables](#registered-definition-tables)
-
-Note that in some cases you will stumble upon things that are not contained
-in these tables (e.g. when a mod has been removed). Always check for
-existence before trying to access the fields.
-
-Example:
-
-All nodes registered with `core.register_node` get added to the table
-`core.registered_nodes`.
-
-If you want to check the drawtype of a node, you could do it like this:
-
-```lua
-local def = core.registered_nodes[nodename]
-local drawtype = def and def.drawtype
-```
-
-
-
-Nodes
-=====
-
-Nodes are the bulk data of the world: cubes and other things that take the
-space of a cube. Huge amounts of them are handled efficiently, but they
-are quite static.
-
-The definition of a node is stored and can be accessed by using
-
-```lua
-core.registered_nodes[node.name]
-```
-
-See [Node definition](#node-definition)
-
-Nodes are passed by value between Lua and the engine.
-They are represented by a table:
-
-```lua
-{name="name", param1=num, param2=num}
-```
-
-`param1` and `param2` are 8-bit integers ranging from 0 to 255. The engine uses
-them for certain automated functions. If you don't use these functions, you can
-use them to store arbitrary values.
-
-Node paramtypes
----------------
-
-The functions of `param1` and `param2` are determined by certain fields in the
-node definition.
-
-The function of `param1` is determined by `paramtype` in node definition.
-`param1` is reserved for the engine when `paramtype != "none"`.
-
-* `paramtype = "light"`
- * The value stores light with and without sun in its lower and upper 4 bits
- respectively.
- * Required by a light source node to enable spreading its light.
- * Required by the following drawtypes as they determine their visual
- brightness from their internal light value:
- * torchlike
- * signlike
- * firelike
- * fencelike
- * raillike
- * nodebox
- * mesh
- * plantlike
- * plantlike_rooted
-* `paramtype = "none"`
- * `param1` will not be used by the engine and can be used to store
- an arbitrary value
-
-The function of `param2` is determined by `paramtype2` in node definition.
-`param2` is reserved for the engine when `paramtype2 != "none"`.
-
-* `paramtype2 = "flowingliquid"`
- * Used by `drawtype = "flowingliquid"` and `liquidtype = "flowing"`
- * The liquid level and a flag of the liquid are stored in `param2`
- * Bits 0-2: Liquid level (0-7). The higher, the more liquid is in this node;
- see `core.get_node_level`, `core.set_node_level` and `core.add_node_level`
- to access/manipulate the content of this field
- * Bit 3: If set, liquid is flowing downwards (no graphical effect)
-* `paramtype2 = "wallmounted"`
- * Supported drawtypes: "torchlike", "signlike", "plantlike",
- "plantlike_rooted", "normal", "nodebox", "mesh"
- * The rotation of the node is stored in `param2`
- * Node is 'mounted'/facing towards one of 6 directions
- * You can make this value by using `core.dir_to_wallmounted()`
- * Values range 0 - 7
- * The value denotes at which direction the node is "mounted":
- 0 = y+, 1 = y-, 2 = x+, 3 = x-, 4 = z+, 5 = z-
- 6 = y+, but rotated by 90°
- 7 = y-, but rotated by -90°
- * By default, on placement the param2 is automatically set to the
- appropriate rotation (0 to 5), depending on which side was
- pointed at. With the node field `wallmounted_rotate_vertical = true`,
- the param2 values 6 and 7 might additionally be set
-* `paramtype2 = "facedir"`
- * Supported drawtypes: "normal", "nodebox", "mesh"
- * The rotation of the node is stored in `param2`.
- * Node is rotated around face and axis; 24 rotations in total.
- * Can be made by using `core.dir_to_facedir()`.
- * Chests and furnaces can be rotated that way, and also 'flipped'
- * Values range 0 - 23
- * facedir / 4 = axis direction:
- 0 = y+, 1 = z+, 2 = z-, 3 = x+, 4 = x-, 5 = y-
- * The node is rotated 90 degrees around the X or Z axis so that its top face
- points in the desired direction. For the y- direction, it's rotated 180
- degrees around the Z axis.
- * facedir modulo 4 = left-handed rotation around the specified axis, in 90° steps.
- * By default, on placement the param2 is automatically set to the
- horizontal direction the player was looking at (values 0-3)
- * Special case: If the node is a connected nodebox, the nodebox
- will NOT rotate, only the textures will.
-* `paramtype2 = "4dir"`
- * Supported drawtypes: "normal", "nodebox", "mesh"
- * The rotation of the node is stored in `param2`.
- * Allows node to be rotated horizontally, 4 rotations in total
- * Can be made by using `core.dir_to_fourdir()`.
- * Chests and furnaces can be rotated that way, but not flipped
- * Values range 0 - 3
- * 4dir modulo 4 = rotation
- * Otherwise, behavior is identical to facedir
-* `paramtype2 = "leveled"`
- * Only valid for "nodebox" with 'type = "leveled"', and "plantlike_rooted".
- * Leveled nodebox:
- * The level of the top face of the nodebox is stored in `param2`.
- * The other faces are defined by 'fixed = {}' like 'type = "fixed"'
- nodeboxes.
- * The nodebox height is (`param2` / 64) nodes.
- * The maximum accepted value of `param2` is 127.
- * Rooted plantlike:
- * The height of the 'plantlike' section is stored in `param2`.
- * The height is (`param2` / 16) nodes.
-* `paramtype2 = "degrotate"`
- * Valid for `plantlike` and `mesh` drawtypes. The rotation of the node is
- stored in `param2`.
- * Values range 0–239. The value stored in `param2` is multiplied by 1.5 to
- get the actual rotation in degrees of the node.
-* `paramtype2 = "meshoptions"`
- * Only valid for "plantlike" drawtype. `param2` encodes the shape and
- optional modifiers of the "plant". `param2` is a bitfield.
- * Bits 0 to 2 select the shape.
- Use only one of the values below:
- * 0 = an "x" shaped plant (ordinary plant)
- * 1 = a "+" shaped plant (just rotated 45 degrees)
- * 2 = a "*" shaped plant with 3 faces instead of 2
- * 3 = a "#" shaped plant with 4 faces instead of 2
- * 4 = a "#" shaped plant with 4 faces that lean outwards
- * 5-7 are unused and reserved for future meshes.
- * Bits 3 to 7 are used to enable any number of optional modifiers.
- Just add the corresponding value(s) below to `param2`:
- * 8 - Makes the plant slightly vary placement horizontally
- * 16 - Makes the plant mesh 1.4x larger
- * 32 - Moves each face randomly a small bit down (1/8 max)
- * values 64 and 128 (bits 6-7) are reserved for future use.
- * Example: `param2 = 0` selects a normal "x" shaped plant
- * Example: `param2 = 17` selects a "+" shaped plant, 1.4x larger (1+16)
-* `paramtype2 = "color"`
- * `param2` tells which color is picked from the palette.
- The palette should have 256 pixels.
-* `paramtype2 = "colorfacedir"`
- * Same as `facedir`, but with colors.
- * The three most significant bits of `param2` tells which color is picked from the
- palette. The palette should have 8 pixels.
- * The five least significant bits contain the `facedir` value.
-* `paramtype2 = "color4dir"`
- * Same as `4dir`, but with colors.
- * The six most significant bits of `param2` tells which color is picked from the
- palette. The palette should have 64 pixels.
- * The two least significant bits contain the `4dir` rotation.
-* `paramtype2 = "colorwallmounted"`
- * Same as `wallmounted`, but with colors.
- * The five most significant bits of `param2` tells which color is picked from the
- palette. The palette should have 32 pixels.
- * The three least significant bits contain the `wallmounted` value.
-* `paramtype2 = "glasslikeliquidlevel"`
- * Only valid for "glasslike_framed" or "glasslike_framed_optional"
- drawtypes. "glasslike_framed_optional" nodes are only affected if the
- "Connected Glass" setting is enabled.
- * Bits 0-5 define 64 levels of internal liquid, 0 being empty and 63 being
- full.
- * Bits 6 and 7 modify the appearance of the frame and node faces. One or
- both of these values may be added to `param2`:
- * 64 - Makes the node not connect with neighbors above or below it.
- * 128 - Makes the node not connect with neighbors to its sides.
- * Liquid texture is defined using `special_tiles = {"modname_tilename.png"}`
-* `paramtype2 = "colordegrotate"`
- * Same as `degrotate`, but with colors.
- * The three most significant bits of `param2` tells which color is picked
- from the palette. The palette should have 8 pixels.
- * The five least significant bits store rotation in range 0–23 (i.e. in 15° steps)
-* `paramtype2 = "none"`
- * `param2` will not be used by the engine and can be used to store
- an arbitrary value
-
-Nodes can also contain extra data. See [Node Metadata](#node-metadata)
-
-Node drawtypes
---------------
-
-There are a bunch of different looking node types.
-
-* `normal`
- * A node-sized cube.
-* `airlike`
- * Invisible, uses no texture.
-* `liquid`
- * The cubic source node for a liquid.
- * Faces bordering to the same node are never rendered.
- * Connects to node specified in `liquid_alternative_flowing` if specified.
- * Use `backface_culling = false` for the tiles you want to make
- visible when inside the node.
-* `flowingliquid`
- * The flowing version of a liquid, appears with various heights and slopes.
- * Faces bordering to the same node are never rendered.
- * Connects to node specified in `liquid_alternative_source`.
- * You *must* set `liquid_alternative_flowing` to the node's own name.
- * Node textures are defined with `special_tiles` where the first tile
- is for the top and bottom faces and the second tile is for the side
- faces.
- * `tiles` is used for the item/inventory/wield image rendering.
- * Use `backface_culling = false` for the special tiles you want to make
- visible when inside the node
-* `glasslike`
- * Often used for partially-transparent nodes.
- * Only external sides of textures are visible.
-* `glasslike_framed`
- * All face-connected nodes are drawn as one volume within a surrounding
- frame.
- * The frame appearance is generated from the edges of the first texture
- specified in `tiles`. The width of the edges used are 1/16th of texture
- size: 1 pixel for 16x16, 2 pixels for 32x32 etc.
- * The glass 'shine' (or other desired detail) on each node face is supplied
- by the second texture specified in `tiles`.
-* `glasslike_framed_optional`
- * This switches between the above 2 drawtypes according to the menu setting
- 'Connected Glass'.
-* `allfaces`
- * Often used for partially-transparent nodes.
- * External sides of textures, and unlike other drawtypes, the external sides
- of other nodes, are visible from the inside.
-* `allfaces_optional`
- * Often used for leaves nodes.
- * This switches between `normal`, `glasslike` and `allfaces` according to
- the menu setting: Opaque Leaves / Simple Leaves / Fancy Leaves.
- * With 'Simple Leaves' selected, the texture specified in `special_tiles`
- is used instead, if present. This allows a visually thicker texture to be
- used to compensate for how `glasslike` reduces visual thickness.
-* `torchlike`
- * A single vertical texture.
- * If `paramtype2="[color]wallmounted"`:
- * If placed on top of a node, uses the first texture specified in `tiles`.
- * If placed against the underside of a node, uses the second texture
- specified in `tiles`.
- * If placed on the side of a node, uses the third texture specified in
- `tiles` and is perpendicular to that node.
- * If `paramtype2="none"`:
- * Will be rendered as if placed on top of a node (see
- above) and only the first texture is used.
-* `signlike`
- * A single texture parallel to, and mounted against, the top, underside or
- side of a node.
- * If `paramtype2="[color]wallmounted"`, it rotates according to `param2`
- * If `paramtype2="none"`, it will always be on the floor.
-* `plantlike`
- * Two vertical and diagonal textures at right-angles to each other.
- * See `paramtype2 = "meshoptions"` above for other options.
-* `firelike`
- * When above a flat surface, appears as 6 textures, the central 2 as
- `plantlike` plus 4 more surrounding those.
- * If not above a surface the central 2 do not appear, but the texture
- appears against the faces of surrounding nodes if they are present.
-* `fencelike`
- * A 3D model suitable for a wooden fence.
- * One placed node appears as a single vertical post.
- * Adjacently-placed nodes cause horizontal bars to appear between them.
-* `raillike`
- * Often used for tracks for mining carts.
- * Requires 4 textures to be specified in `tiles`, in order: Straight,
- curved, t-junction, crossing.
- * Each placed node automatically switches to a suitable rotated texture
- determined by the adjacent `raillike` nodes, in order to create a
- continuous track network.
- * Becomes a sloping node if placed against stepped nodes.
-* `nodebox`
- * Often used for stairs and slabs.
- * Allows defining nodes consisting of an arbitrary number of boxes.
- * See [Node boxes](#node-boxes) below for more information.
-* `mesh`
- * Uses models for nodes.
- * Tiles should hold model materials textures.
- * Only static meshes are implemented.
- * For supported model formats see Irrlicht engine documentation.
-* `plantlike_rooted`
- * Enables underwater `plantlike` without air bubbles around the nodes.
- * Consists of a base cube at the coordinates of the node plus a
- `plantlike` extension above
- * If `paramtype2="leveled", the `plantlike` extension has a height
- of `param2 / 16` nodes, otherwise it's the height of 1 node
- * If `paramtype2="wallmounted"`, the `plantlike` extension
- will be at one of the corresponding 6 sides of the base cube.
- Also, the base cube rotates like a `normal` cube would
- * The `plantlike` extension visually passes through any nodes above the
- base cube without affecting them.
- * The base cube texture tiles are defined as normal, the `plantlike`
- extension uses the defined special tile, for example:
- `special_tiles = {{name = "default_papyrus.png"}},`
-
-`*_optional` drawtypes need less rendering time if deactivated
-(always client-side).
-
-Node boxes
-----------
-
-Node selection boxes and collision boxes, and the appearance of the `nodebox`
-drawtype, are defined using "node boxes".
-
-A nodebox is defined as any of:
-
-```lua
-{
- -- A normal cube; the default in most things
- type = "regular"
-}
-{
- -- A fixed box (or boxes) (facedir param2 is used, if applicable)
- type = "fixed",
- fixed = box OR {box1, box2, ...}
-}
-{
- -- A variable height box (or boxes) with the top face position defined
- -- by the node parameter 'leveled = ', or if 'paramtype2 == "leveled"'
- -- by param2.
- -- Other faces are defined by 'fixed = {}' as with 'type = "fixed"'.
- type = "leveled",
- fixed = box OR {box1, box2, ...}
-}
-{
- -- A box like the selection box for torches
- -- (wallmounted param2 is used, if applicable)
- type = "wallmounted",
- wall_top = box,
- wall_bottom = box,
- wall_side = box
-}
-{
- -- A node that has optional boxes depending on neighboring nodes'
- -- presence and type. See also `connects_to`.
- type = "connected",
- fixed = box OR {box1, box2, ...}
- connect_top = box OR {box1, box2, ...}
- connect_bottom = box OR {box1, box2, ...}
- connect_front = box OR {box1, box2, ...}
- connect_left = box OR {box1, box2, ...}
- connect_back = box OR {box1, box2, ...}
- connect_right = box OR {box1, box2, ...}
- -- The following `disconnected_*` boxes are the opposites of the
- -- `connect_*` ones above, i.e. when a node has no suitable neighbor
- -- on the respective side, the corresponding disconnected box is drawn.
- disconnected_top = box OR {box1, box2, ...}
- disconnected_bottom = box OR {box1, box2, ...}
- disconnected_front = box OR {box1, box2, ...}
- disconnected_left = box OR {box1, box2, ...}
- disconnected_back = box OR {box1, box2, ...}
- disconnected_right = box OR {box1, box2, ...}
- disconnected = box OR {box1, box2, ...} -- when there is *no* neighbor
- disconnected_sides = box OR {box1, box2, ...} -- when there are *no*
- -- neighbors to the sides
-}
-```
-
-A `box` is defined as:
-
-```lua
-{x1, y1, z1, x2, y2, z2}
-```
-
-A box of a regular node would look like:
-
-```lua
-{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
-```
-
-To avoid collision issues, keep each value within the range of +/- 1.45.
-This also applies to leveled nodeboxes, where the final height shall not
-exceed this soft limit.
-
-
-
-Map terminology and coordinates
-===============================
-
-Nodes, mapblocks, mapchunks
----------------------------
-
-A 'node' is the fundamental cubic unit of a world and appears to a player as
-roughly 1x1x1 meters in size.
-
-A 'mapblock' (often abbreviated to 'block') is 16x16x16 nodes and is the
-fundamental region of a world that is stored in the world database, sent to
-clients and handled by many parts of the engine. This size is available as the
-constant `core.MAP_BLOCKSIZE` (=16).
-
-'mapblock' is preferred terminology to 'block' to help avoid confusion with
-'node', however 'block' often appears in the API.
-
-A 'mapchunk' (sometimes abbreviated to 'chunk') is usually 5x5x5 mapblocks
-(80x80x80 nodes) and is the volume of world generated in one operation by
-the map generator.
-The size in mapblocks has been chosen to optimize map generation.
-
-### Mapblock status
-
-A mapblock being "loaded" means that is in memory. These are the mapblocks that
-API functions like `core.get_node` or `core.set_node` can operate on. To reach
-this state, the mapblock must first go through the process of being "emerged".
-This means that it is loaded from disk, and/or, if it isn't yet generated,
-generated by the map generator.
-
-Mapblocks are loaded in a broad area around each player. They become "unloaded"
-again if no player is close enough. The engine commonly represents the contents
-of unloaded mapblocks as `"ignore"` nodes.
-
-A mapblock being "active" means that it is not only in memory, but also affected
-by world simulation:
-
-* Entities are active
- * They are in memory as `ServerActiveObject`, exposed to Lua as `ObjectRef`
- * They exist in Lua as luaentity tables
-* ABMs are executed
-* Node timers are executed
-
-Also, when a mapblock is "activated", LBMs are executed. Mapblocks are active
-in a smaller area around each player, and are "deactivated" again if no player
-is close enough.
-
-Related API functions:
-
-* `core.compare_block_status`
-* `core.forceload_block`
-* `core.load_area`
-* `core.emerge_area`
-
-Coordinates
------------
-
-### Orientation of axes
-
-For node and mapblock coordinates, +X is East, +Y is up, +Z is North.
-
-### Node coordinates
-
-Almost all positions used in the API use node coordinates.
-
-### Mapblock coordinates
-
-Occasionally the API uses 'blockpos' which refers to mapblock coordinates that
-specify a particular mapblock.
-For example blockpos (0,0,0) specifies the mapblock that extends from
-node position (0,0,0) to node position (15,15,15).
-
-#### Converting node position to the containing blockpos
-
-To calculate the blockpos of the mapblock that contains the node at 'nodepos',
-for each axis:
-
-* blockpos = math.floor(nodepos / core.MAP_BLOCKSIZE)
-
-#### Converting blockpos to min/max node positions
-
-To calculate the min/max node positions contained in the mapblock at 'blockpos',
-for each axis:
-
-* Minimum:
- nodepos = blockpos * core.MAP_BLOCKSIZE
-* Maximum:
- nodepos = (blockpos + 1) * core.MAP_BLOCKSIZE - 1
-
-
-
-
-HUD
-===
-
-HUD element types
------------------
-
-The `position` field is used for all element types.
-To account for differing resolutions, the position coordinates are the
-percentage of the screen, ranging in value from `0` to `1`.
-
-The `name` field is not yet used, but should contain a description of what the
-HUD element represents.
-
-The `direction` field is the direction in which something is drawn.
-`0` draws from left to right, `1` draws from right to left, `2` draws from
-top to bottom, and `3` draws from bottom to top.
-
-The `alignment` field specifies how the item will be aligned. It is a table
-where `x` and `y` range from `-1` to `1`, with `0` being central. `-1` is
-moved to the left/up, and `1` is to the right/down. Fractional values can be
-used.
-
-The `offset` field specifies a pixel offset from the position. Contrary to
-position, the offset is not scaled to screen size. This allows for some
-precisely positioned items in the HUD.
-
-**Note**: `offset` _will_ adapt to screen DPI as well as user defined scaling
-factor!
-
-The `z_index` field specifies the order of HUD elements from back to front.
-Lower z-index elements are displayed behind higher z-index elements. Elements
-with same z-index are displayed in an arbitrary order. Default 0.
-Supports negative values. By convention, the following values are recommended:
-
-* -400: Graphical effects, such as vignette
-* -300: Name tags, waypoints
-* -200: Wieldhand
-* -100: Things that block the player's view, e.g. masks
-* 0: Default. For standard in-game HUD elements like crosshair, hotbar,
- minimap, builtin statbars, etc.
-* 100: Temporary text messages or notification icons
-* 1000: Full-screen effects such as full-black screen or credits.
- This includes effects that cover the entire screen
-
-If your HUD element doesn't fit into any category, pick a number
-between the suggested values
-
-Below are the specific uses for fields in each type; fields not listed for that
-type are ignored.
-
-### `image`
-
-Displays an image on the HUD.
-
-* `scale`: The scale of the image, with `{x = 1, y = 1}` being the original texture size.
- The `x` and `y` fields apply to the respective axes.
- Positive values scale the source image.
- Negative values represent percentages relative to screen dimensions.
- Example: `{x = -20, y = 3}` means the image will be drawn 20% of screen width wide,
- and 3 times as high as the source image is.
-* `text`: The name of the texture that is displayed.
-* `alignment`: The alignment of the image.
-* `offset`: offset in pixels from position.
-
-### `text`
-
-Displays text on the HUD.
-
-* `scale`: Defines the bounding rectangle of the text.
- A value such as `{x=100, y=100}` should work.
-* `text`: The text to be displayed in the HUD element.
- Supports `core.translate` (always)
- and `core.colorize` (since protocol version 44)
-* `number`: An integer containing the RGB value of the color used to draw the
- text. Specify `0xFFFFFF` for white text, `0xFF0000` for red, and so on.
-* `alignment`: The alignment of the text.
-* `offset`: offset in pixels from position.
-* `size`: size of the text.
- The player-set font size is multiplied by size.x (y value isn't used).
-* `style`: determines font style
- Bitfield with 1 = bold, 2 = italic, 4 = monospace
-
-### `statbar`
-
-Displays a horizontal bar made up of half-images with an optional background.
-
-* `text`: The name of the texture to use.
-* `text2`: Optional texture name to enable a background / "off state"
- texture (useful to visualize the maximal value). Both textures
- must have the same size.
-* `number`: The number of half-textures that are displayed.
- If odd, will end with a vertically center-split texture.
-* `item`: Same as `number` but for the "off state" texture
-* `direction`: To which direction the images will extend to
-* `offset`: offset in pixels from position.
-* `size`: If used, will force full-image size to this value (override texture
- pack image size)
-
-### `inventory`
-
-* `text`: The name of the inventory list to be displayed.
-* `number`: Number of items in the inventory to be displayed.
-* `item`: Position of item that is selected.
-* `direction`: Direction the list will be displayed in
-* `offset`: offset in pixels from position.
-* `alignment`: The alignment of the inventory. Aligned at the top left corner if not specified.
-
-### `hotbar`
-
-* `direction`: Direction the list will be displayed in
-* `offset`: offset in pixels from position.
-* `alignment`: The alignment of the inventory.
-
-### `waypoint`
-
-Displays distance to selected world position.
-
-* `name`: The name of the waypoint.
-* `text`: Distance suffix. Can be blank.
-* `precision`: Waypoint precision, integer >= 0. Defaults to 10.
- If set to 0, distance is not shown. Shown value is `floor(distance*precision)/precision`.
- When the precision is an integer multiple of 10, there will be `log_10(precision)` digits after the decimal point.
- `precision = 1000`, for example, will show 3 decimal places (eg: `0.999`).
- `precision = 2` will show multiples of `0.5`; precision = 5 will show multiples of `0.2` and so on:
- `precision = n` will show multiples of `1/n`
-* `number:` An integer containing the RGB value of the color used to draw the
- text.
-* `world_pos`: World position of the waypoint.
-* `offset`: offset in pixels from position.
-* `alignment`: The alignment of the waypoint.
-
-### `image_waypoint`
-
-Same as `image`, but does not accept a `position`; the position is instead determined by `world_pos`, the world position of the waypoint.
-
-* `scale`: The scale of the image, with `{x = 1, y = 1}` being the original texture size.
- The `x` and `y` fields apply to the respective axes.
- Positive values scale the source image.
- Negative values represent percentages relative to screen dimensions.
- Example: `{x = -20, y = 3}` means the image will be drawn 20% of screen width wide,
- and 3 times as high as the source image is.
-* `text`: The name of the texture that is displayed.
-* `alignment`: The alignment of the image.
-* `world_pos`: World position of the waypoint.
-* `offset`: offset in pixels from position.
-
-### `compass`
-
-Displays an image oriented or translated according to current heading direction.
-
-* `size`: The size of this element. Negative values represent percentage
- of the screen; e.g. `x=-100` means 100% (width).
-* `scale`: Scale of the translated image (used only for dir = 2 or dir = 3).
-* `text`: The name of the texture to use.
-* `alignment`: The alignment of the image.
-* `offset`: Offset in pixels from position.
-* `direction`: How the image is rotated/translated:
- * 0 - Rotate as heading direction
- * 1 - Rotate in reverse direction
- * 2 - Translate as landscape direction
- * 3 - Translate in reverse direction
-
-If translation is chosen, texture is repeated horizontally to fill the whole element.
-
-### `minimap`
-
-Displays a minimap on the HUD.
-
-* `size`: Size of the minimap to display. Minimap should be a square to avoid
- distortion.
- * Negative values represent percentages of the screen. If either `x` or `y`
- is specified as a percentage, the resulting pixel size will be used for
- both `x` and `y`. Example: On a 1920x1080 screen, `{x = 0, y = -25}` will
- result in a 270x270 minimap.
- * Negative values are supported starting with protocol version 45.
-* `alignment`: The alignment of the minimap.
-* `offset`: offset in pixels from position.
-
-Representations of simple things
-================================
-
-Vector (ie. a position)
------------------------
-
-```lua
-vector.new(x, y, z)
-```
-
-See [Spatial Vectors](#spatial-vectors) for details.
-
-`pointed_thing`
----------------
-
-* `{type="nothing"}`
-* `{type="node", under=pos, above=pos}`
- * Indicates a pointed node selection box.
- * `under` refers to the node position behind the pointed face.
- * `above` refers to the node position in front of the pointed face.
-* `{type="object", ref=ObjectRef}`
-
-Exact pointing location (currently only `Raycast` supports these fields):
-
-* `pointed_thing.intersection_point`: The absolute world coordinates of the
- point on the selection box which is pointed at. May be in the selection box
- if the pointer is in the box too.
-* `pointed_thing.box_id`: The ID of the pointed selection box (counting starts
- from 1).
-* `pointed_thing.intersection_normal`: Unit vector, points outwards of the
- selected selection box. This specifies which face is pointed at.
- Is a null vector `vector.zero()` when the pointer is inside the selection box.
- For entities with rotated selection boxes, this will be rotated properly
- by the entity's rotation - it will always be in absolute world space.
-
-
-
-
-Flag Specifier Format
-=====================
-
-Flags using the standardized flag specifier format can be specified in either
-of two ways, by string or table.
-
-The string format is a comma-delimited set of flag names; whitespace and
-unrecognized flag fields are ignored. Specifying a flag in the string sets the
-flag, and specifying a flag prefixed by the string `"no"` explicitly
-clears the flag from whatever the default may be.
-
-In addition to the standard string flag format, the schematic flags field can
-also be a table of flag names to boolean values representing whether or not the
-flag is set. Additionally, if a field with the flag name prefixed with `"no"`
-is present, mapped to a boolean of any value, the specified flag is unset.
-
-E.g. A flag field of value
-
-```lua
-{place_center_x = true, place_center_y=false, place_center_z=true}
-```
-
-is equivalent to
-
-```lua
-{place_center_x = true, noplace_center_y=true, place_center_z=true}
-```
-
-which is equivalent to
-
-```lua
-"place_center_x, noplace_center_y, place_center_z"
-```
-
-or even
-
-```lua
-"place_center_x, place_center_z"
-```
-
-since, by default, no schematic attributes are set.
-
-
-
-
-Items
-=====
-
-Items are things that can be held by players, dropped in the map and
-stored in inventories.
-Items come in the form of item stacks, which are collections of equal
-items that occupy a single inventory slot.
-
-Item types
-----------
-
-There are three kinds of items: nodes, tools and craftitems.
-
-* Node: Placeable item form of a node in the world's voxel grid
-* Tool: Has a changeable wear property but cannot be stacked
-* Craftitem: Has no special properties
-
-Every registered node (the voxel in the world) has a corresponding
-item form (the thing in your inventory) that comes along with it.
-This item form can be placed which will create a node in the
-world (by default).
-Both the 'actual' node and its item form share the same identifier.
-For all practical purposes, you can treat the node and its item form
-interchangeably. We usually just say 'node' to the item form of
-the node as well.
-
-Note the definition of tools is purely technical. The only really
-unique thing about tools is their wear, and that's basically it.
-Beyond that, you can't make any gameplay-relevant assumptions
-about tools or non-tools. It is perfectly valid to register something
-that acts as tool in a gameplay sense as a craftitem, and vice-versa.
-
-Craftitems can be used for items that neither need to be a node
-nor a tool.
-
-Special Items
--------------
-The following items are predefined and have special properties.
-
-* `"unknown"`: An item that represents every item which has not been registered
-* `"air"`: The node which appears everywhere where no other node is
-* `"ignore"`: Mapblocks that are not loaded are represented using this node.
- * Also used for nodes that have not yet been set by the map generator.
- * This is also what appears outside of the map boundary.
-* `""`: The player's hand, which is in use whenever the player wields no item.
- * Its range and tool capabilities are also used as a fallback for the wielded item.
- * It can be overridden to change those properties:
- * globally using `core.override_item`
- * per-player using the special `"hand"` inventory list
-
-Amount and wear
----------------
-
-All item stacks have an amount between 0 and 65535. It is 1 by
-default. Tool item stacks cannot have an amount greater than 1.
-
-Tools use a wear (damage) value ranging from 0 to 65535. The
-value 0 is the default and is used for unworn tools. The values
-1 to 65535 are used for worn tools, where a higher value stands for
-a higher wear. Non-tools technically also have a wear property,
-but it is always 0. There is also a special 'toolrepair' crafting
-recipe that is only available to tools.
-
-Item formats
-------------
-
-Items and item stacks can exist in three formats: Serializes, table format
-and `ItemStack`.
-
-When an item must be passed to a function, it can usually be in any of
-these formats.
-
-### Serialized
-
-This is called "stackstring" or "itemstring". It is a simple string with
-1-4 components:
-
-1. Full item identifier ("item name")
-2. Optional amount
-3. Optional wear value
-4. Optional item metadata
-
-Syntax:
-
- [[ [ ]]]
-
-Examples:
-
-* `"default:apple"`: 1 apple
-* `"default:dirt 5"`: 5 dirt
-* `"default:pick_stone"`: a new stone pickaxe
-* `"default:pick_wood 1 21323"`: a wooden pickaxe, ca. 1/3 worn out
-* `[[default:pick_wood 1 21323 "\u0001description\u0002My worn out pick\u0003"]]`:
- * a wooden pickaxe from the `default` mod,
- * amount must be 1 (pickaxe is a tool), ca. 1/3 worn out (it's a tool),
- * with the `description` field set to `"My worn out pick"` in its metadata
-* `[[default:dirt 5 0 "\u0001description\u0002Special dirt\u0003"]]`:
- * analogous to the above example
- * note how the wear is set to `0` as dirt is not a tool
-
-You should ideally use the `ItemStack` format to build complex item strings
-(especially if they use item metadata)
-without relying on the serialization format. Example:
-
- local stack = ItemStack("default:pick_wood")
- stack:set_wear(21323)
- stack:get_meta():set_string("description", "My worn out pick")
- local itemstring = stack:to_string()
-
-Additionally the methods `core.itemstring_with_palette(item, palette_index)`
-and `core.itemstring_with_color(item, colorstring)` may be used to create
-item strings encoding color information in their metadata.
-
-### Table format
-
-Examples:
-
-5 dirt nodes:
-
-```lua
-{name="default:dirt", count=5, wear=0, metadata=""}
-```
-
-A wooden pick about 1/3 worn out:
-
-```lua
-{name="default:pick_wood", count=1, wear=21323, metadata=""}
-```
-
-An apple:
-
-```lua
-{name="default:apple", count=1, wear=0, metadata=""}
-```
-
-### `ItemStack` format
-
-A native C++ format with many helper methods. Useful for converting
-between formats. See the [Class Reference](#class-reference) section for details.
-
-
-
-
-Groups
-======
-
-In a number of places, there is a group table. Groups define the
-properties of a thing (item, node, armor of entity, tool capabilities)
-in such a way that the engine and other mods can can interact with
-the thing without actually knowing what the thing is.
-
-Usage
------
-
-Groups are stored in a table, having the group names with keys and the
-group ratings as values. Group ratings are integer values within the
-range [-32767, 32767]. For example:
-
-```lua
--- Default dirt
-groups = {crumbly=3, soil=1}
-
--- A more special dirt-kind of thing
-groups = {crumbly=2, soil=1, level=2, outerspace=1}
-```
-
-Groups always have a rating associated with them. If there is no
-useful meaning for a rating for an enabled group, it shall be `1`.
-
-When not defined, the rating of a group defaults to `0`. Thus when you
-read groups, you must interpret `nil` and `0` as the same value, `0`.
-
-You can read the rating of a group for an item or a node by using
-
-```lua
-core.get_item_group(itemname, groupname)
-```
-
-Groups of items
----------------
-
-Groups of items can define what kind of an item it is (e.g. wool).
-
-Groups of nodes
----------------
-
-In addition to the general item things, groups are used to define whether
-a node is destroyable and how long it takes to destroy by a tool.
-
-Groups of entities
-------------------
-
-For entities, groups are, as of now, used only for calculating damage.
-The rating is the percentage of damage caused by items with this damage group.
-See [Entity damage mechanism](#entity-damage-mechanism).
-
-```lua
-object:get_armor_groups() --> a group-rating table (e.g. {fleshy=100})
-object:set_armor_groups({fleshy=30, cracky=80})
-```
-
-Groups of tool capabilities
----------------------------
-
-Groups in tool capabilities define which groups of nodes and entities they
-are effective towards.
-
-Groups in crafting recipes
---------------------------
-
-In crafting recipes, you can specify a group as an input item.
-This means that any item in that group will be accepted as input.
-
-The basic syntax is:
-
-```lua
-"group:"
-```
-
-For example, `"group:meat"` will accept any item in the `meat` group.
-
-It is also possible to require an input item to be in
-multiple groups at once. The syntax for that is:
-
-```lua
-"group:,,(...),"
-```
-
-For example, `"group:leaves,birch,trimmed"` accepts any item which is member
-of *all* the groups `leaves` *and* `birch` *and* `trimmed`.
-
-An example recipe: Craft a raw meat soup from any meat, any water and any bowl:
-
-```lua
-{
- output = "food:meat_soup_raw",
- recipe = {
- {"group:meat"},
- {"group:water"},
- {"group:bowl"},
- },
-}
-```
-
-Another example: Craft red wool from white wool and red dye
-(here, "red dye" is defined as any item which is member of
-*both* the groups `dye` and `basecolor_red`).
-
-```lua
-{
- type = "shapeless",
- output = "wool:red",
- recipe = {"wool:white", "group:dye,basecolor_red"},
-}
-```
-
-Special groups
---------------
-
-The asterisk `(*)` after a group name describes that there is no engine
-functionality bound to it, and implementation is left up as a suggestion
-to games.
-
-### Node and item groups
-
-* `not_in_creative_inventory`: (*) Special group for inventory mods to indicate
- that the item should be hidden in item lists.
-
-
-### Node-only groups
-
-* `attached_node`: the node is 'attached' to a neighboring node. It checks
- whether the node it is attached to is walkable. If it
- isn't, the node will drop as an item.
- * `1`: if the node is wallmounted, the node is attached in the wallmounted
- direction. Otherwise, the node is attached to the node below.
- * `2`: if the node is facedir or 4dir, the facedir or 4dir direction is checked.
- No effect for other nodes.
- Note: The "attaching face" of this node is tile no. 5 (back face).
- * `3`: the node is always attached to the node below.
- * `4`: the node is always attached to the node above.
-* `bouncy`: value is bounce speed in percent.
- If positive, jump/sneak on floor impact will increase/decrease bounce height.
- Negative value is the same bounciness, but non-controllable.
-* `connect_to_raillike`: makes nodes of raillike drawtype with same group value
- connect to each other
-* `dig_immediate`: Player can always pick up node without reducing tool wear
- * `2`: the node always gets the digging time 0.5 seconds (rail, sign)
- * `3`: the node always gets the digging time 0 seconds (torch)
-* `disable_jump`: Player (and possibly other things) cannot jump from node
- or if their feet are in the node. Note: not supported for `new_move = false`
-* `disable_descend`: Player (and possibly other things) cannot *actively*
- descend in node using Sneak or Aux1 key (for liquids and climbable nodes
- only). Note: not supported for `new_move = false`
-* `fall_damage_add_percent`: modifies the fall damage suffered when hitting
- the top of this node. There's also an armor group with the same name.
- The final player damage is determined by the following formula:
- ```lua
- damage =
- collision speed
- * ((node_fall_damage_add_percent + 100) / 100) -- node group
- * ((player_fall_damage_add_percent + 100) / 100) -- player armor group
- - (14) -- constant tolerance
- ```
- Negative damage values are discarded as no damage.
-* `falling_node`: if there is no walkable block under the node it will fall
-* `float`: the node will not fall through liquids (`liquidtype ~= "none"`)
- * A liquid source with `groups = {falling_node = 1, float = 1}`
- will fall through flowing liquids.
-* `level`: Can be used to give an additional sense of progression in the game.
- * A larger level will cause e.g. a weapon of a lower level make much less
- damage, and get worn out much faster, or not be able to get drops
- from destroyed nodes.
- * `0` is something that is directly accessible at the start of gameplay
- * There is no upper limit
- * See also: `leveldiff` in [Tool Capabilities](#tool-capabilities)
-* `slippery`: Players and items will slide on the node.
- Slipperiness rises steadily with `slippery` value, starting at 1.
-
-
-### Tool-only groups
-
-* `disable_repair`: If set to 1 for a tool, it cannot be repaired using the
- `"toolrepair"` crafting recipe
-
-
-### `ObjectRef` armor groups
-
-* `immortal`: Skips all damage and breath handling for an object. This group
- will also hide the integrated HUD status bars for players. It is
- automatically set to all players when damage is disabled on the server and
- cannot be reset (subject to change).
-* `fall_damage_add_percent`: Modifies the fall damage suffered by players
- when they hit the ground. It is analog to the node group with the same
- name. See the node group above for the exact calculation.
-* `punch_operable`: For entities; disables the regular damage mechanism for
- players punching it by hand or a non-tool item, so that it can do something
- else than take damage.
-
-
-
-Known damage and digging time defining groups
----------------------------------------------
-
-* `crumbly`: dirt, sand
-* `cracky`: tough but crackable stuff like stone.
-* `snappy`: something that can be cut using things like scissors, shears,
- bolt cutters and the like, e.g. leaves, small plants, wire, sheets of metal
-* `choppy`: something that can be cut using force; e.g. trees, wooden planks
-* `fleshy`: Living things like animals and the player. This could imply
- some blood effects when hitting.
-* `explody`: Especially prone to explosions
-* `oddly_breakable_by_hand`:
- Can be added to nodes that shouldn't logically be breakable by the
- hand but are. Somewhat similar to `dig_immediate`, but times are more
- like `{[1]=3.50,[2]=2.00,[3]=0.70}` and this does not override the
- digging speed of an item if it can dig at a faster speed than this
- suggests for the hand.
-
-Examples of custom groups
--------------------------
-
-Item groups are often used for defining, well, _groups of items_.
-
-* `meat`: any meat-kind of a thing (rating might define the size or healing
- ability or be irrelevant -- it is not defined as of yet)
-* `eatable`: anything that can be eaten. Rating might define HP gain in half
- hearts.
-* `flammable`: can be set on fire. Rating might define the intensity of the
- fire, affecting e.g. the speed of the spreading of an open fire.
-* `wool`: any wool (any origin, any color)
-* `metal`: any metal
-* `weapon`: any weapon
-* `heavy`: anything considerably heavy
-
-Digging time calculation specifics
-----------------------------------
-
-Groups such as `crumbly`, `cracky` and `snappy` are used for this
-purpose. Rating is `1`, `2` or `3`. A higher rating for such a group implies
-faster digging time.
-
-The `level` group is used to limit the toughness of nodes an item capable
-of digging can dig and to scale the digging times / damage to a greater extent.
-
-**Please do understand this**, otherwise you cannot use the system to it's
-full potential.
-
-Items define their properties by a list of parameters for groups. They
-cannot dig other groups; thus it is important to use a standard bunch of
-groups to enable interaction with items.
-
-
-
-
-Tool Capabilities
-=================
-
-'Tool capabilities' is a property of items that defines two things:
-
-1) Which nodes it can dig and how fast
-2) Which objects it can hurt by punching and by how much
-
-Tool capabilities are available for all items, not just tools.
-But only tools can receive wear from digging and punching.
-
-Missing or incomplete tool capabilities will default to the
-player's hand.
-
-Tool capabilities definition
-----------------------------
-
-Tool capabilities define:
-
-* Full punch interval
-* Maximum drop level
-* For an arbitrary list of node groups:
- * Uses (until the tool breaks)
- * Maximum level (usually `0`, `1`, `2` or `3`)
- * Digging times
-* Damage groups
-* Punch attack uses (until the tool breaks)
-
-### Full punch interval `full_punch_interval`
-
-When used as a weapon, the item will do full damage if this time is spent
-between punches. If e.g. half the time is spent, the item will do half
-damage.
-
-### Maximum drop level `max_drop_level`
-
-Suggests the maximum level of node, when dug with the item, that will drop
-its useful item. (e.g. iron ore to drop a lump of iron).
-
-This value is not used in the engine; it is the responsibility of the game/mod
-code to implement this.
-
-### Uses `uses` (tools only)
-
-Determines how many uses the tool has when it is used for digging a node,
-of this group, of the maximum level. The maximum supported number of
-uses is 65535. The special number 0 is used for infinite uses.
-For lower leveled nodes, the use count is multiplied by `3^leveldiff`.
-`leveldiff` is the difference of the tool's `maxlevel` `groupcaps` and the
-node's `level` group. The node cannot be dug if `leveldiff` is less than zero.
-
-* `uses=10, leveldiff=0`: actual uses: 10
-* `uses=10, leveldiff=1`: actual uses: 30
-* `uses=10, leveldiff=2`: actual uses: 90
-
-For non-tools, this has no effect.
-
-### Maximum level `maxlevel`
-
-Tells what is the maximum level of a node of this group that the item will
-be able to dig.
-
-### Digging times `times`
-
-List of digging times for different ratings of the group, for nodes of the
-maximum level.
-
-For example, as a Lua table, `times={[2]=2.00, [3]=0.70}`. This would
-result in the item to be able to dig nodes that have a rating of `2` or `3`
-for this group, and unable to dig the rating `1`, which is the toughest.
-Unless there is a matching group that enables digging otherwise.
-
-If the result digging time is 0, a delay of 0.15 seconds is added between
-digging nodes. If the player releases LMB after digging, this delay is set to 0,
-i.e. players can more quickly click the nodes away instead of holding LMB.
-
-This extra delay is not applied in case of a digging time between 0 and 0.15,
-so a digging time of 0.01 is actually faster than a digging time of 0.
-
-### Damage groups
-
-List of damage for groups of entities. See [Entity damage mechanism](#entity-damage-mechanism).
-
-### Punch attack uses (tools only)
-
-Determines how many uses (before breaking) the tool has when dealing damage
-to an object, when the full punch interval (see above) was always
-waited out fully.
-
-Wear received by the tool is proportional to the time spent, scaled by
-the full punch interval.
-
-For non-tools, this has no effect.
-
-Example definition of the capabilities of an item
--------------------------------------------------
-
-```lua
-tool_capabilities = {
- groupcaps={
- crumbly={maxlevel=2, uses=20, times={[1]=1.60, [2]=1.20, [3]=0.80}}
- },
-}
-```
-
-This makes the item capable of digging nodes that fulfill both of these:
-
-* Have the `crumbly` group
-* Have a `level` group less or equal to `2`
-
-Table of resulting digging times:
-
- crumbly 0 1 2 3 4 <- level
- -> 0 - - - - -
- 1 0.80 1.60 1.60 - -
- 2 0.60 1.20 1.20 - -
- 3 0.40 0.80 0.80 - -
-
- level diff: 2 1 0 -1 -2
-
-Table of resulting tool uses:
-
- -> 0 - - - - -
- 1 180 60 20 - -
- 2 180 60 20 - -
- 3 180 60 20 - -
-
-**Notes**:
-
-* At `crumbly==0`, the node is not diggable.
-* At `crumbly==3`, the level difference digging time divider kicks in and makes
- easy nodes to be quickly breakable.
-* At `level > 2`, the node is not diggable, because it's `level > maxlevel`
-
-
-
-
-Entity damage mechanism
-=======================
-
-Damage calculation:
-
- damage = 0
- foreach group in cap.damage_groups:
- damage += cap.damage_groups[group]
- * limit(actual_interval / cap.full_punch_interval, 0.0, 1.0)
- * (object.armor_groups[group] / 100.0)
- -- Where object.armor_groups[group] is 0 for inexistent values
- return damage
-
-Client predicts damage based on damage groups. Because of this, it is able to
-give an immediate response when an entity is damaged or dies; the response is
-pre-defined somehow (e.g. by defining a sprite animation) (not implemented;
-TODO).
-Currently a smoke puff will appear when an entity dies.
-
-The group `immortal` completely disables normal damage.
-
-Entities can define a special armor group, which is `punch_operable`. This
-group disables the regular damage mechanism for players punching it by hand or
-a non-tool item, so that it can do something else than take damage.
-
-On the Lua side, every punch calls:
-
-```lua
-entity:on_punch(puncher, time_from_last_punch, tool_capabilities, direction,
- damage)
-```
-
-This should never be called directly, because damage is usually not handled by
-the entity itself.
-
-* `puncher` is the object performing the punch. Can be `nil`. Should never be
- accessed unless absolutely required, to encourage interoperability.
-* `time_from_last_punch` is time from last punch (by `puncher`) or `nil`.
-* `tool_capabilities` can be `nil`.
-* `direction` is a unit vector, pointing from the source of the punch to
- the punched object.
-* `damage` damage that will be done to entity
-Return value of this function will determine if damage is done by this function
-(retval true) or shall be done by engine (retval false)
-
-To punch an entity/object in Lua, call:
-
-```lua
-object:punch(puncher, time_from_last_punch, tool_capabilities, direction)
-```
-
-* Return value is tool wear.
-* Parameters are equal to the above callback.
-* If `direction` equals `nil` and `puncher` does not equal `nil`, `direction`
- will be automatically filled in based on the location of `puncher`.
-
-
-
-
-Metadata
-========
-
-Node Metadata
--------------
-
-The instance of a node in the world normally only contains the three values
-mentioned in [Nodes](#nodes). However, it is possible to insert extra data into a node.
-It is called "node metadata"; See `NodeMetaRef`.
-
-Node metadata contains two things:
-
-* A key-value store
-* An inventory
-
-Some of the values in the key-value store are handled specially:
-
-* `formspec`: Defines an inventory menu that is opened with the
- 'place/use' key. Only works if no `on_rightclick` was
- defined for the node. See also [Formspec](#formspec).
-* `infotext`: Text shown on the screen when the node is pointed at.
- Line-breaks will be applied automatically.
- If the infotext is very long, it will be truncated.
-
-Example:
-
-```lua
-local meta = core.get_meta(pos)
-
--- Set node formspec and infotext
-meta:set_string("formspec",
- "size[8,9]"..
- "list[context;main;0,0;8,4;]"..
- "list[current_player;main;0,5;8,4;]")
-meta:set_string("infotext", "Chest");
-
--- Set inventory list size of `"main"` list to 32
-local inv = meta:get_inventory()
-inv:set_size("main", 32)
-
--- Dump node metadata
-print(dump(meta:to_table()))
-
--- Set node metadata from a metadata table
-meta:from_table({
- inventory = {
- -- Set items of inventory in all 32 slots of the `"main"` list
- main = {[1] = "default:dirt", [2] = "", [3] = "", [4] = "",
- [5] = "", [6] = "", [7] = "", [8] = "", [9] = "",
- [10] = "", [11] = "", [12] = "", [13] = "",
- [14] = "default:cobble", [15] = "", [16] = "", [17] = "",
- [18] = "", [19] = "", [20] = "default:cobble", [21] = "",
- [22] = "", [23] = "", [24] = "", [25] = "", [26] = "",
- [27] = "", [28] = "", [29] = "", [30] = "", [31] = "",
- [32] = ""}
- },
- -- metadata fields
- fields = {
- formspec = "size[8,9]list[context;main;0,0;8,4;]list[current_player;main;0,5;8,4;]",
- infotext = "Chest"
- }
-})
-```
-
-Item Metadata
--------------
-
-Item stacks can store metadata too. See [`ItemStackMetaRef`](#itemstackmetaref)
-Note: They are not able to store the character `"\1"`, be very careful when storing binary data in them
-
-Item metadata only contains a key-value store.
-
-Some of the values in the key-value store are handled specially:
-
-* `description`: Set the item stack's description.
- See also: `get_description` in [`ItemStack`](#itemstack)
-* `short_description`: Set the item stack's short description.
- See also: `get_short_description` in [`ItemStack`](#itemstack)
-* `inventory_image`: Override inventory_image
-* `inventory_overlay`: Override inventory_overlay
-* `wield_image`: Override wield_image
-* `wield_overlay`: Override wield_overlay
-* `wield_scale`: Override wield_scale, use vector.to_string
-* `color`: A `ColorString`, which sets the stack's color.
-* `palette_index`: If the item has a palette, this is used to get the
- current color from the palette.
-* `count_meta`: Replace the displayed count with any string.
-* `count_alignment`: Set the alignment of the displayed count value. This is an
- int value. The lowest 2 bits specify the alignment in x-direction, the 3rd and
- 4th bit specify the alignment in y-direction:
- 0 = default, 1 = left / up, 2 = middle, 3 = right / down
- The default currently is the same as right/down.
- Example: 6 = 2 + 1*4 = middle,up
-* `range`: Overrides the pointing range
- Example: `meta:set_float("range", 4.2)`
-
-Example:
-
-```lua
-local meta = stack:get_meta()
-meta:set_string("key", "value")
-print(dump(meta:to_table()))
-```
-
-Example manipulations of "description" and expected output behaviors:
-
-```lua
-print(ItemStack("default:pick_steel"):get_description()) --> Steel Pickaxe
-print(ItemStack("foobar"):get_description()) --> Unknown Item
-
-local stack = ItemStack("default:stone")
-stack:get_meta():set_string("description", "Custom description\nAnother line")
-print(stack:get_description()) --> Custom description\nAnother line
-print(stack:get_short_description()) --> Custom description
-
-stack:get_meta():set_string("short_description", "Short")
-print(stack:get_description()) --> Custom description\nAnother line
-print(stack:get_short_description()) --> Short
-
-print(ItemStack("mod:item_with_no_desc"):get_description()) --> mod:item_with_no_desc
-```
-
-
-Formspec
-========
-
-Formspec defines a menu. This supports inventories and some of the
-typical widgets like buttons, checkboxes, text input fields, etc.
-It is a string, with a somewhat strange format.
-
-A formspec is made out of formspec elements, which includes widgets
-like buttons but also can be used to set stuff like background color.
-
-Many formspec elements have a `name`, which is a unique identifier which
-is used when the server receives user input. You must not use the name
-"quit" for formspec elements.
-
-Spaces and newlines can be inserted between the blocks, as is used in the
-examples.
-
-Position and size units are inventory slots unless the new coordinate system
-is enabled. `X` and `Y` position the formspec element relative to the top left
-of the menu or container. `W` and `H` are its width and height values.
-
-If the new system is enabled, all elements have unified coordinates for all
-elements with no padding or spacing in between. This is highly recommended
-for new forms. See `real_coordinates[]` and `Migrating to Real
-Coordinates`.
-
-Inventories with a `player:` inventory location are only sent to the
-player named ``.
-
-When displaying text which can contain formspec code, e.g. text set by a player,
-use `core.formspec_escape`.
-For colored text you can use `core.colorize`.
-
-Since formspec version 3, elements drawn in the order they are defined. All
-background elements are drawn before all other elements.
-
-**WARNING**: do _not_ use an element name starting with `key_`; those names are
-reserved to pass key press events to formspec!
-
-**WARNING**: names and values of elements cannot contain binary data such as ASCII
-control characters. For values, escape sequences used by the engine are an exception to this.
-
-**WARNING**: Luanti allows you to add elements to every single formspec instance
-using `player:set_formspec_prepend()`, which may be the reason backgrounds are
-appearing when you don't expect them to, or why things are styled differently
-to normal. See [`no_prepend[]`] and [Styling Formspecs](#styling-formspecs).
-
-Examples
---------
-
-### Chest
-
- size[8,9]
- list[context;main;0,0;8,4;]
- list[current_player;main;0,5;8,4;]
-
-### Furnace
-
- size[8,9]
- list[context;fuel;2,3;1,1;]
- list[context;src;2,1;1,1;]
- list[context;dst;5,1;2,2;]
- list[current_player;main;0,5;8,4;]
-
-### Minecraft-like player inventory
-
- size[8,7.5]
- image[1,0.6;1,2;player.png]
- list[current_player;main;0,3.5;8,4;]
- list[current_player;craft;3,0;3,3;]
- list[current_player;craftpreview;7,1;1,1;]
-
-Version History
----------------
-
-* Formspec version 1 (pre-5.1.0):
- * (too much)
-* Formspec version 2 (5.1.0):
- * Forced real coordinates
- * background9[]: 9-slice scaling parameters
-* Formspec version 3 (5.2.0):
- * Formspec elements are drawn in the order of definition
- * bgcolor[]: use 3 parameters (bgcolor, formspec (now an enum), fbgcolor)
- * box[] and image[] elements enable clipping by default
- * new element: scroll_container[]
-* Formspec version 4 (5.4.0):
- * Allow dropdown indexing events
-* Formspec version 5 (5.5.0):
- * Added padding[] element
-* Formspec version 6 (5.6.0):
- * Add nine-slice images, animated_image, and fgimg_middle
-* Formspec version 7 (5.8.0):
- * style[]: Add focused state for buttons
- * Add field_enter_after_edit[] (experimental)
-* Formspec version 8 (5.10.0)
- * scroll_container[]: content padding parameter
-* Formspec version 9 (5.12.0)
- * Add allow_close[]
- * label[]: Add "area label" variant
-* Formspec version 10 (5.13.0)
- * model[]: Support floating-point frames
-
-Elements
---------
-
-### `formspec_version[]`
-
-* Set the formspec version to a certain number. If not specified,
- version 1 is assumed.
-* Must be specified before `size` element.
-* Clients older than this version can neither show newer elements nor display
- elements with new arguments correctly.
-* Available since feature `formspec_version_element`.
-* See also: [Version History](#version-history).
-
-### `size[,,]`
-
-* Define the size of the menu in inventory slots
-* `fixed_size`: `true`/`false` (optional)
-* deprecated: `invsize[,;]`
-
-### `position[,]`
-
-* Must be used after `size` element.
-* Defines the position on the game window of the formspec's `anchor` point.
-* For X and Y, 0.0 and 1.0 represent opposite edges of the game window,
- for example:
- * [0.0, 0.0] sets the position to the top left corner of the game window.
- * [1.0, 1.0] sets the position to the bottom right of the game window.
-* Defaults to the center of the game window [0.5, 0.5].
-
-### `anchor[,]`
-
-* Must be used after both `size` and `position` (if present) elements.
-* Defines the location of the anchor point within the formspec.
-* For X and Y, 0.0 and 1.0 represent opposite edges of the formspec,
- for example:
- * [0.0, 1.0] sets the anchor to the bottom left corner of the formspec.
- * [1.0, 0.0] sets the anchor to the top right of the formspec.
-* Defaults to the center of the formspec [0.5, 0.5].
-
-* `position` and `anchor` elements need suitable values to avoid a formspec
- extending off the game window due to particular game window sizes.
-
-### `padding[,]`
-
-* Must be used after the `size`, `position`, and `anchor` elements (if present).
-* Defines how much space is padded around the formspec if the formspec tries to
- increase past the size of the screen and coordinates have to be shrunk.
-* For X and Y, 0.0 represents no padding (the formspec can touch the edge of the
- screen), and 0.5 represents half the screen (which forces the coordinate size
- to 0). If negative, the formspec can extend off the edge of the screen.
-* Defaults to [0.05, 0.05].
-
-### `no_prepend[]`
-
-* Must be used after the `size`, `position`, `anchor`, and `padding` elements
- (if present).
-* Disables player:set_formspec_prepend() from applying to this formspec.
-
-### `real_coordinates[]`
-
-* INFORMATION: Enable it automatically using `formspec_version` version 2 or newer.
-* When set to true, all following formspec elements will use the new coordinate system.
-* If used immediately after `size`, `position`, `anchor`, and `no_prepend` elements
- (if present), the form size will use the new coordinate system.
-* **Note**: Formspec prepends are not affected by the coordinates in the main form.
- They must enable it explicitly.
-* For information on converting forms to the new coordinate system, see `Migrating
- to Real Coordinates`.
-
-### `allow_close[]`
-
-* When set to false, the formspec will not close when the user tries to close
- it with the Escape key or similar. Default true.
-* The formspec can still be closed with `*_exit[]` elements and
- `core.close_formspec()`, regardless of this setting.
-
-### `container[,]`
-
-* Start of a container block, moves all physical elements in the container by
- (X, Y).
-* Must have matching `container_end`
-* Containers can be nested, in which case the offsets are added
- (child containers are relative to parent containers)
-
-### `container_end[]`
-
-* End of a container, following elements are no longer relative to this
- container.
-
-### `scroll_container[,;,;;;;]`
-
-* Start of a scroll_container block. All contained elements will ...
- * take the scroll_container coordinate as position origin,
- * be additionally moved by the current value of the scrollbar with the name
- `scrollbar name` times `scroll factor` along the orientation `orientation` and
- * be clipped to the rectangle defined by `X`, `Y`, `W` and `H`.
-* `orientation`: possible values are `vertical` and `horizontal`.
-* `scroll factor`: optional, defaults to `0.1`.
-* `content padding`: (optional), in formspec coordinate units
- * If specified, the scrollbar properties `max` and `thumbsize` are calculated automatically
- based on the content size plus `content padding` at the end of the container. `min` is set to 0.
- * Negative `scroll factor` is not supported.
- * When active, `scrollbaroptions[]` has no effect on the affected properties.
- * Defaults to empty value (= disabled).
-* Nesting is possible.
-* Some elements might work a little different if they are in a scroll_container.
-* Note: If you want the scroll_container to actually work, you also need to add a
- scrollbar element with the specified name. Furthermore, it is highly recommended
- to use a scrollbaroptions element on this scrollbar.
-
-### `scroll_container_end[]`
-
-* End of a scroll_container, following elements are no longer bound to this
- container.
-
-### `list[;;,;,;]`
-
-* Show an inventory list if it has been sent to the client.
-* If the inventory list changes (eg. it didn't exist before, it's resized, or its items
- are moved) while the formspec is open, the formspec element may (but is not guaranteed
- to) adapt to the new inventory list.
-* Item slots are drawn in a grid from left to right, then up to down, ordered
- according to the slot index.
-* `W` and `H` are in inventory slots, not in coordinates.
-* `starting item index` (Optional): The index of the first (upper-left) item to draw.
- Indices start at `0`. Default is `0`.
-* The number of shown slots is the minimum of `W*H` and the inventory list's size minus
- `starting item index`.
-* **Note**: With the new coordinate system, the spacing between inventory
- slots is one-fourth the size of an inventory slot by default. Also see
- [Styling Formspecs](#styling-formspecs) for changing the size of slots and spacing.
-
-### `listring[;]`
-
-* Appends to an internal ring of inventory lists.
-* Shift-clicking on items in one element of the ring
- will send them to the next inventory list inside the ring
-* The first occurrence of an element inside the ring will
- determine the inventory where items will be sent to
-
-### `listring[]`
-
-* Shorthand for doing `listring[;]`
- for the last two inventory lists added by list[...]
-
-### `listcolors[;]`
-
-* Sets background color of slots as `ColorString`
-* Sets background color of slots on mouse hovering
-
-### `listcolors[;;]`
-
-* Sets background color of slots as `ColorString`
-* Sets background color of slots on mouse hovering
-* Sets color of slots border
-
-### `listcolors[;;;;]`
-
-* Sets background color of slots as `ColorString`
-* Sets background color of slots on mouse hovering
-* Sets color of slots border
-* Sets default background color of tooltips
-* Sets default font color of tooltips
-
-### `tooltip[;;;]`
-
-* Adds tooltip for an element
-* `bgcolor` tooltip background color as `ColorString` (optional)
-* `fontcolor` tooltip font color as `ColorString` (optional)
-
-### `tooltip[,;,;;;]`
-
-* Adds tooltip for an area. Other tooltips will take priority when present.
-* `bgcolor` tooltip background color as `ColorString` (optional)
-* `fontcolor` tooltip font color as `ColorString` (optional)
-
-### `image[,;,;;]`
-
-* Show an image.
-* `middle` (optional): Makes the image render in 9-sliced mode and defines the middle rect.
- * Requires formspec version >= 6.
- * See `background9[]` documentation for more information.
-
-### `animated_image[,;,;;;;;;]`
-
-* Show an animated image. The image is drawn like a "vertical_frames" tile
- animation (See [Tile animation definition](#tile-animation-definition)), but uses a frame count/duration for simplicity
-* `name`: Element name to send when an event occurs. The event value is the index of the current frame.
-* `texture name`: The image to use.
-* `frame count`: The number of frames animating the image.
-* `frame duration`: Milliseconds between each frame. `0` means the frames don't advance.
-* `frame start` (optional): The index of the frame to start on. Default `1`.
-* `middle` (optional): Makes the image render in 9-sliced mode and defines the middle rect.
- * Requires formspec version >= 6.
- * See `background9[]` documentation for more information.
-
-### `model[,;,;;;;;;;;]`
-
-* Show a mesh model.
-* `name`: Element name that can be used for styling
-* `mesh`: The mesh model to use.
-* `textures`: The mesh textures to use according to the mesh materials.
- Texture names must be separated by commas.
-* `rotation` (Optional): Initial rotation of the camera, format `x,y`.
- The axes are euler angles in degrees.
-* `continuous` (Optional): Whether the rotation is continuous. Default `false`.
-* `mouse control` (Optional): Whether the model can be controlled with the mouse. Default `true`.
-* `frame loop range` (Optional): Range of the animation frames.
- * Defaults to the full range of all available frames.
- * Syntax: `,`
-* `animation speed` (Optional): Sets the animation speed. Default 0 FPS.
-
-### `item_image[,;,;]`
-
-* Show an inventory image of registered item/node
-
-### `bgcolor[;;]`
-
-* Sets background color of formspec.
-* `bgcolor` and `fbgcolor` (optional) are `ColorString`s, they define the color
- of the non-fullscreen and the fullscreen background.
-* `fullscreen` (optional) can be one of the following:
- * `false`: Only the non-fullscreen background color is drawn. (default)
- * `true`: Only the fullscreen background color is drawn.
- * `both`: The non-fullscreen and the fullscreen background color are drawn.
- * `neither`: No background color is drawn.
-* Note: Leave a parameter empty to not modify the value.
-* Note: `fbgcolor`, leaving parameters empty and values for `fullscreen` that
- are not bools are only available since formspec version 3.
-
-### `background[,;,;]`
-
-* Example for formspec 8x4 in 16x resolution: image shall be sized
- 8 times 16px times 4 times 16px.
-
-### `background[,;,;;]`
-
-* Example for formspec 8x4 in 16x resolution:
- image shall be sized 8 times 16px times 4 times 16px
-* If `auto_clip` is `true`, the background is clipped to the formspec size
- (`x` and `y` are used as offset values, `w` and `h` are ignored)
-
-### `background9[,;,;;;]`
-
-* 9-sliced background. See https://en.wikipedia.org/wiki/9-slice_scaling
-* Middle is a rect which defines the middle of the 9-slice.
- * `x` - The middle will be x pixels from all sides.
- * `x,y` - The middle will be x pixels from the horizontal and y from the vertical.
- * `x,y,x2,y2` - The middle will start at x,y, and end at x2, y2. Negative x2 and y2 values
- will be added to the width and height of the texture, allowing it to be used as the
- distance from the far end.
- * All numbers in middle are integers.
-* If `auto_clip` is `true`, the background is clipped to the formspec size
- (`x` and `y` are used as offset values, `w` and `h` are ignored)
-* Available since formspec version 2
-
-### `pwdfield[,;,;;