diff --git a/doc/lua_api.txt b/doc/lua_api.txt new file mode 100644 index 0000000..d2ab9de --- /dev/null +++ b/doc/lua_api.txt @@ -0,0 +1,6855 @@ +Minetest Lua Modding API Reference +================================== + +* More information at +* Developer Wiki: + + +Introduction +============ + +Content and functionality can be added to Minetest 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 Minetest. + +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 +----- + +* `RUN_IN_PLACE=1` (Windows release, local build) + * `$path_user`: `` + * `$path_share`: `` +* `RUN_IN_PLACE=0`: (Linux release) + * `$path_share`: + * Linux: `/usr/share/minetest` + * Windows: `/minetest-0.4.x` + * `$path_user`: + * Linux: `$HOME/.minetest` + * Windows: `C:/users//AppData/minetest` (maybe) + + + + +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: + * `name`: Required, human readable name e.g. `name = Minetest` + * `description`: Short description to be shown in the content tab + * `disallowed_mapgens = ` + e.g. `disallowed_mapgens = v5,v6,flat` + These mapgens are removed from the list of mapgens for the game. +* `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. + + + + +Mods +==== + +Mod load path +------------- + +Paths are relative to the directories listed in the [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. +* `description`: Description of mod to be shown in the Mods tab of the main + menu. + +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 + │   ├── sounds + │   ├── media + │   ├── locale + │   └── + └── another + +### modname + +The location of this directory can be fetched by using +`minetest.get_modpath(modname)`. + +### mod.conf + +A key-value store of mod details. + +* `name`: The mod name. Allows Minetest to determine the mod name even if the + folder is wrongly named. +* `description`: Description of mod to be shown in the Mods tab of the main + menu. +* `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. + +Note: to support 0.4.x, please also provide depends.txt. + +### `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` + +A file in the same format as the one in builtin. It will be parsed by the +settings menu and the settings will be displayed in the "Mods" category. + +### `init.lua` + +The main Lua script. Running this script should register everything it +wants to register. Subsequent execution depends on minetest calling the +registered callbacks. + +`minetest.settings` can be used to read custom or existing settings at load +time, if necessary. (See [`Settings`]) + +### `models` + +Models for entities or meshnodes. + +### `textures`, `sounds`, `media` + +Media files (textures, sounds, whatever) that will be transferred to the +client and will be available for use by the mod. + +### `locale` + +Translation files for the clients. (See [Translations]) + +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. That mod is required to have `experimental` as a +dependency. + + + + +Aliases +======= + +Aliases can be added by using `minetest.register_alias(name, convert_to)` or +`minetest.register_alias_force(name, convert_to)`. + +This converts anything called `name` to `convert_to`. + +The only difference between `minetest.register_alias` and +`minetest.register_alias_force` is that if an item called `name` exists, +`minetest.register_alias` will do nothing while +`minetest.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 + + minetest.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 by the core mapgens. For example: + + minetest.register_alias("mapgen_stone", "default:stone") + +### Aliases needed for all mapgens except Mapgen V6 + +#### Base terrain + +* mapgen_stone +* mapgen_water_source +* mapgen_river_water_source + +#### Caves + +Not required if cave liquid nodes are set in biome definitions. + +* mapgen_lava_source + +#### Dungeons + +Not required if dungeon nodes are set in biome definitions. + +* mapgen_cobble +* mapgen_stair_cobble +* mapgen_mossycobble +* mapgen_desert_stone +* mapgen_stair_desert_stone +* mapgen_sandstone +* mapgen_sandstonebrick +* mapgen_stair_sandstone_block + +### Aliases needed for Mapgen V6 + +#### Terrain and biomes + +* mapgen_stone +* mapgen_water_source +* mapgen_lava_source +* mapgen_dirt +* mapgen_dirt_with_grass +* mapgen_sand +* mapgen_gravel +* mapgen_desert_stone +* mapgen_desert_sand +* mapgen_dirt_with_snow +* mapgen_snowblock +* mapgen_snow +* mapgen_ice + +#### Flora + +* mapgen_tree +* mapgen_leaves +* mapgen_apple +* mapgen_jungletree +* mapgen_jungleleaves +* mapgen_junglegrass +* mapgen_pine_tree +* mapgen_pine_needles + +#### Dungeons + +* mapgen_cobble +* mapgen_stair_cobble +* mapgen_mossycobble +* mapgen_stair_desert_stone + +### Setting the node used in Mapgen Singlenode + +By default the world is filled with air nodes. To set a different node use, for +example: + + minetest.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` + +Texture modifiers +----------------- + +There are various texture modifiers that can be used +to generate textures on-the-fly. + +### Texture overlaying + +Textures can be overlaid by putting a `^` between them. + +Example: + + default_dirt.png^default_grass_side.png + +`default_grass_side.png` is overlaid over `default_dirt.png`. +The texture with the lower resolution will be automatically upscaled to +the higher resolution texture. + +### 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` + +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 +* ``: y position +* ``: 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 + +#### `[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. + +#### `[sheet:x:,` + +Retrieves a tile at position x,y from the base image +which it assumes to be a tilesheet with dimensions w,h. + +#### `[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. + +#### `[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. + +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. + +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: + + minetest.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: + + minetest.register_craft({ + output = minetest.itemstring_with_palette("wool:block", 3), + type = "shapeless", + recipe = { + "wool:block", + "dye:red", + }, + }) + +To set the `color` field, you can use `minetest.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 Minetest 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): + + minetest.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", tileable_vertical = false}}, + -- 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 sounds with `modname_`, e.g. given +the mod name "`foomod`", a sound could be called: + + foomod_foosound.ogg + +Sounds are referred to by their name with a dot, a single digit and the +file extension stripped out. When a sound is played, the actual sound file +is chosen randomly from the matching sounds. + +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` + +Examples of sound parameter tables: + + -- Play locationless on all clients + { + gain = 1.0, -- default + fade = 0.0, -- default, change to a value > 0 to fade the sound in + pitch = 1.0, -- default + } + -- Play locationless to one player + { + to_player = name, + gain = 1.0, -- default + fade = 0.0, -- default, change to a value > 0 to fade the sound in + pitch = 1.0, -- default + } + -- Play locationless to one player, looped + { + to_player = name, + gain = 1.0, -- default + loop = true, + } + -- Play in a location + { + pos = {x = 1, y = 2, z = 3}, + gain = 1.0, -- default + max_hear_distance = 32, -- default, uses an euclidean metric + } + -- Play connected to an object, looped + { + object = , + gain = 1.0, -- default + max_hear_distance = 32, -- default, uses an euclidean metric + loop = true, + } + +Looped sounds must either be connected to an object or played locationless to +one player using `to_player = name,` + +`SimpleSoundSpec` +----------------- + +* e.g. `""` +* e.g. `"default_place_node"` +* e.g. `{}` +* e.g. `{name = "default_place_node"}` +* e.g. `{name = "default_place_node", gain = 1.0}` +* e.g. `{name = "default_place_node", gain = 1.0, pitch = 1.0}` + + + + +Registered definitions +====================== + +Anything added using certain [Registration functions] gets added to one or more +of the global [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 register with `minetest.register_node` get added to the table +`minetest.registered_nodes`. + +If you want to check the drawtype of a node, you could do: + + local function get_nodedef_field(nodename, fieldname) + if not minetest.registered_nodes[nodename] then + return nil + end + return minetest.registered_nodes[nodename][fieldname] + end + local drawtype = get_nodedef_field(nodename, "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 + + minetest.registered_nodes[node.name] + +See [Registered definitions]. + +Nodes are passed by value between Lua and the engine. +They are represented by a table: + + {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. + +`param1` is reserved for the engine when `paramtype != "none"`: + +* `paramtype = "light"` + * The value stores light with and without sun in its upper and lower 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 + +`param2` is reserved for the engine when any of these are used: + +* `liquidtype = "flowing"` + * The level and some flags of the liquid is stored in `param2` +* `drawtype = "flowingliquid"` + * The drawn liquid level is read from `param2` +* `drawtype = "torchlike"` +* `drawtype = "signlike"` +* `paramtype2 = "wallmounted"` + * The rotation of the node is stored in `param2`. You can make this value + by using `minetest.dir_to_wallmounted()`. +* `paramtype2 = "facedir"` + * The rotation of the node is stored in `param2`. Furnaces and chests are + rotated this way. Can be made by using `minetest.dir_to_facedir()`. + * Values range 0 - 23 + * facedir / 4 = axis direction: + 0 = y+, 1 = z+, 2 = z-, 3 = x+, 4 = x-, 5 = y- + * facedir modulo 4 = rotation around that axis +* `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"` + * Only valid for "plantlike". The rotation of the node is stored in + `param2`. + * Values range 0 - 179. The value stored in `param2` is multiplied by two to + get the actual rotation in degrees of the node. +* `paramtype2 = "meshoptions"` + * Only valid for "plantlike". The value of `param2` becomes a bitfield which + can be used to change how the client draws plantlike nodes. + * Bits 0, 1 and 2 form a mesh selector. + Currently the following meshes are choosable: + * 0 = a "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 through 7 are optional flags that can be combined and give these + effects: + * bit 3 (0x08) - Makes the plant slightly vary placement horizontally + * bit 4 (0x10) - Makes the plant mesh 1.4x larger + * bit 5 (0x20) - Moves each face randomly a small bit down (1/8 max) + * bits 6-7 are reserved for future use. +* `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 first three bits of `param2` tells which color is picked from the + palette. The palette should have 8 pixels. +* `paramtype2 = "colorwallmounted"` + * Same as `wallmounted`, but with colors. + * The first five bits of `param2` tells which color is picked from the + palette. The palette should have 32 pixels. +* `paramtype2 = "glasslikeliquidlevel"` + * Only valid for "glasslike_framed" or "glasslike_framed_optional" + drawtypes. + * `param2` values 0-63 define 64 levels of internal liquid, 0 being empty + and 63 being full. + * Liquid texture is defined using `special_tiles = {"modname_tilename.png"}` + +Nodes can also contain extra data. See [Node Metadata]. + +Node drawtypes +-------------- + +There are a bunch of different looking node types. + +Look for examples in `games/minimal` or `games/minetest_game`. + +* `normal` + * A node-sized cube. +* `airlike` + * Invisible, uses no texture. +* `liquid` + * The cubic source node for a liquid. +* `flowingliquid` + * The flowing version of a liquid, appears with various heights and slopes. +* `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 and internal sides of textures are visible. +* `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 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. +* `signlike` + * A single texture parallel to, and mounted against, the top, underside or + side of a node. +* `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] 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 co-ordinates of the node plus a + `plantlike` extension above with a height of `param2 / 16` nodes. + * 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", tileable_vertical = true}},` + +`*_optional` drawtypes need less rendering time if deactivated +(always client-side). + +Node boxes +---------- + +Node selection boxes are defined using "node boxes". + +A nodebox is defined as any of: + + { + -- 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 neighbouring 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 neighbour + -- 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* neighbour + disconnected_sides = box OR {box1, box2, ...} -- when there are *no* + -- neighbours to the sides + } + +A `box` is defined as: + + {x1, y1, z1, x2, y2, z2} + +A box of a regular node would look like: + + {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, + + + + +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 ranges from +`-1` to `1`, with `0` being the center. `-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! + +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 1 being the original texture size. + Only the X coordinate scale is used (positive values). + Negative values represent that percentage of the screen it + should take; e.g. `x=-100` means 100% (width). +* `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. +* `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. + +### `statbar` + +Displays a horizontal bar made up of half-images. + +* `text`: The name of the texture that is used. +* `number`: The number of half-textures that are displayed. + If odd, will end with a vertically center-split texture. +* `direction` +* `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` +* `offset`: offset in pixels from position. + +### `waypoint` + +Displays distance to selected world position. + +* `name`: The name of the waypoint. +* `text`: Distance suffix. Can be blank. +* `number:` An integer containing the RGB value of the color used to draw the + text. +* `world_pos`: World position of the waypoint. + + + + +Representations of simple things +================================ + +Position/vector +--------------- + + {x=num, y=num, z=num} + +For helper functions see [Spatial Vectors]. + +`pointed_thing` +--------------- + +* `{type="nothing"}` +* `{type="node", under=pos, above=pos}` +* `{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 `{x = 0, y = 0, z = 0}` when the pointer is inside the + selection box. + + + + +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 + + {place_center_x = true, place_center_y=false, place_center_z=true} + +is equivalent to + + {place_center_x = true, noplace_center_y=true, place_center_z=true} + +which is equivalent to + + "place_center_x, noplace_center_y, place_center_z" + +or even + + "place_center_x, place_center_z" + +since, by default, no schematic attributes are set. + + + + +Items +===== + +Item types +---------- + +There are three kinds of items: nodes, tools and craftitems. + +* Node: Can be placed in the world's voxel grid +* Tool: Has a wear property but cannot be stacked. The default use action is to + dig nodes or hit objects according to its tool capabilities. +* Craftitem: Cannot dig nodes or be placed + +Amount and wear +--------------- + +All item stacks have an amount between 0 and 65535. It is 1 by +default. Tool item stacks can not 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 always have a wear value of 0. + +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-3 components: the full item identifier, an optional amount and an optional +wear value. 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 + +### Table format + +Examples: + +5 dirt nodes: + + {name="default:dirt", count=5, wear=0, metadata=""} + +A wooden pick about 1/3 worn out: + + {name="default:pick_wood", count=1, wear=21323, metadata=""} + +An apple: + + {name="default:apple", count=1, wear=0, metadata=""} + +### `ItemStack` + +A native C++ format with many helper methods. Useful for converting +between formats. See the [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, capabilities of +tool) 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. For example: + + -- 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 + + minetest.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 tools with this damage group. +See [Entity damage mechanism]. + + object.get_armor_groups() --> a group-rating table (e.g. {fleshy=100}) + object.set_armor_groups({fleshy=30, cracky=80}) + +Groups of tools +--------------- + +Groups in tools define which groups of nodes and entities they are +effective towards. + +Groups in crafting recipes +-------------------------- + +An example: Make meat soup from any meat, any water and any bowl: + + { + output = 'food:meat_soup_raw', + recipe = { + {'group:meat'}, + {'group:water'}, + {'group:bowl'}, + }, + -- preserve = {'group:bowl'}, -- Not implemented yet (TODO) + } + +Another example: Make red wool from white wool and red dye: + + { + type = 'shapeless', + output = 'wool:red', + recipe = {'wool:white', 'group:dye,basecolor_red'}, + } + +Special groups +-------------- + +* `immortal`: Disables the group damage system for an entity +* `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. +* `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 +* `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 +* `fall_damage_add_percent`: damage speed = `speed * (1 + value/100)` +* `bouncy`: value is bounce speed in percent +* `falling_node`: if there is no walkable block under the node it will fall +* `attached_node`: if the node under it is not a walkable block the node will be + dropped as an item. If the node is wallmounted the wallmounted direction is + checked. +* `connect_to_raillike`: makes nodes of raillike drawtype with same group value + connect to each other +* `slippery`: Players and items will slide on the node. + Slipperiness rises steadily with `slippery` value, starting at 1. +* `disable_repair`: If set to 1 for a tool, it cannot be repaired using the + `"toolrepair"` crafting recipe + +Known damage and digging time defining groups +--------------------------------------------- + +* `crumbly`: dirt, sand +* `cracky`: tough but crackable stuff like stone. +* `snappy`: something that can be cut using fine tools; 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 + speed of a tool if the tool 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 a tool 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. + +Tools 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 tools. + + + + +Tools +===== + +Tools definition +---------------- + +Tools define: + +* Full punch interval +* Maximum drop level +* For an arbitrary list of groups: + * Uses (until the tool breaks) + * Maximum level (usually `0`, `1`, `2` or `3`) + * Digging times + * Damage groups + +### Full punch interval + +When used as a weapon, the tool will do full damage if this time is spent +between punches. If e.g. half the time is spent, the tool will do half +damage. + +### Maximum drop level + +Suggests the maximum level of node, when dug with the tool, that will drop +it's useful item. (e.g. iron ore to drop a lump of iron). + +This is not automated; it is the responsibility of the node definition +to implement this. + +### Uses + +Determines how many uses the tool has when it is used for digging a node, +of this group, of the maximum level. For lower leveled nodes, the use count +is multiplied by `3^leveldiff`. + +* `uses=10, leveldiff=0`: actual uses: 10 +* `uses=10, leveldiff=1`: actual uses: 30 +* `uses=10, leveldiff=2`: actual uses: 90 + +### Maximum level + +Tells what is the maximum level of a node of this group that the tool will +be able to dig. + +### Digging 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 tool 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. + +### Damage groups + +List of damage for groups of entities. See [Entity damage mechanism]. + +Example definition of the capabilities of a tool +------------------------------------------------ + + tool_capabilities = { + full_punch_interval=1.5, + max_drop_level=1, + groupcaps={ + crumbly={maxlevel=2, uses=20, times={[1]=1.60, [2]=1.20, [3]=0.80}} + } + damage_groups = {fleshy=2}, + } + +This makes the tool be able to dig nodes that fulfil 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: + + 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: + + 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]. 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 a right-click inventory menu. See [Formspec]. +* `infotext`: Text shown on the screen when the node is pointed at + +Example: + + local meta = minetest.get_meta(pos) + 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"); + local inv = meta:get_inventory() + inv:set_size("main", 8*4) + print(dump(meta:to_table())) + meta:from_table({ + inventory = { + 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] = ""} + }, + 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`]. + +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. Defaults to + `idef.description`. +* `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. + +Example: + + local meta = stack:get_meta() + meta:set_string("key", "value") + print(dump(meta:to_table())) + + + + +Formspec +======== + +Formspec defines a menu. Currently not much else than inventories are +supported. It is a string, with a somewhat strange format. + +Spaces and newlines can be inserted between the blocks, as is used in the +examples. + +Position and size units are inventory slots, `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. +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 `minetest.formspec_escape`. +For coloured text you can use `minetest.colorize`. + +WARNING: Minetest 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. See [`no_prepend[]`]. + +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;] + +Elements +-------- + +### `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. + +### `no_prepend[]` + +* Must be used after the `size`, `position`, and `anchor` elements (if present). +* Disables player:set_formspec_prepend() from applying to this formspec. + +### `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. + +### `list[;;,;,;]` + +* Show an inventory list if it has been sent to the client. Nothing will + be shown if the inventory list is of size 0. + +### `list[;;,;,;]` + +* Show an inventory list if it has been sent to the client. Nothing will + be shown if the inventory list is of size 0. + +### `listring[;]` + +* Allows to create a 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 +* `` tooltip background color as `ColorString` (optional) +* `` tooltip font color as `ColorString` (optional) + +### `tooltip[,;,;;;]` + +* Adds tooltip for an area. Other tooltips will take priority when present. +* `` tooltip background color as `ColorString` (optional) +* `` tooltip font color as `ColorString` (optional) + +### `image[,;,;]` + +* Show an image + +### `item_image[,;,;]` + +* Show an inventory image of registered item/node + +### `bgcolor[;]` + +* Sets background color of formspec as `ColorString` +* If `true`, the background color is drawn fullscreen (does not affect the size + of the formspec). + +### `background[,;,;]` + +* Use a background. Inventory rectangles are not drawn then. +* Example for formspec 8x4 in 16x resolution: image shall be sized + 8 times 16px times 4 times 16px. + +### `background[,;,;;]` + +* Use a background. Inventory rectangles are not drawn then. +* 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) + +### `pwdfield[,;,;;