-Minetest Lua Modding API Reference 0.4.dev
+Minetest Lua Modding API Reference 0.4.0
==========================================
More information at http://c55.me/minetest/
They are represented by a table:
{name="name", param1=num, param2=num}
-param1 and param2 are 8 bit and 4 bit integers, respectively. The engine
-uses them for certain automated functions. If you don't use these
-functions, you can use them to store arbitrary values.
+param1 and param2 are 8 bit integers. The engine uses them for certain
+automated functions. If you don't use these functions, you can use them to
+store arbitrary values.
The functions of param1 and param2 are determined by certain fields in the
node definition:
Nodes can also contain extra data. See "Node Metadata".
+Node drawtypes
+---------------
+There are a bunch of different looking node types. These are mostly just
+copied from Minetest 0.3; more may be made in the future.
+
+Look for examples in games/minimal or games/minetest_game.
+
+- normal
+- airlike
+- liquid
+- flowingliquid
+- glasslike
+- allfaces
+- allfaces_optional
+- torchlike
+- signlike
+- plantlike
+- fencelike
+- raillike
+- nodebox -- See below. EXPERIMENTAL
+
+Node boxes
+-----------
+Node selection boxes are defined using "node boxes"
+
+The "nodebox" node drawtype allows defining visual of nodes consisting of
+arbitrary number of boxes. It allows defining stuff like stairs. Only the
+"fixed" box type is supported for these.
+^ Please note that this is still experimental, and may be incompatibly
+ changed in the future.
+
+A nodebox is defined as any of:
+{
+ -- A normal cube; the default in most things
+ type = "regular"
+}
+{
+ -- A fixed box (facedir param2 is used, if applicable)
+ type = "fixed",
+ 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 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},
+
Representations of simple things
--------------------------------
Position/vector:
Currently the API does not provide any helper functions for addition,
subtraction and whatever; you can define those that you need yourself.
+pointed_thing:
+ {type="nothing"}
+ {type="node", under=pos, above=pos}
+ {type="object", ref=ObjectRef}
+
Items
------
Node (register_node):
Groups in crafting recipes
---------------------------
-- Not implemented yet. (TODO)
-- Will probably look like this:
+An example:
{
output = 'food:meat_soup_raw',
recipe = {
{'group:water'},
{'group:bowl'},
},
- preserve = {'group:bowl'},
+ preserve = {'group:bowl'}, -- Not implemented yet (TODO)
}
Special groups
local meta = minetest.env:get_meta(pos)
meta:set_string("formspec",
"invsize[8,9;]"..
- "list[current_name;main;0,0;8,4;]"..
+ "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()
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 = "invsize[8,9;]list[current_name;main;0,0;8,4;]list[current_player;main;0,5;8,4;]",
+ formspec = "invsize[8,9;]list[context;main;0,0;8,4;]list[current_player;main;0,5;8,4;]",
infotext = "Chest"
}
})
Examples:
- Chest:
invsize[8,9;]
- list[current_name;main;0,0;8,4;]
+ list[context;main;0,0;8,4;]
list[current_player;main;0,5;8,4;]
- Furnace:
invsize[8,9;]
- list[current_name;fuel;2,3;1,1;]
- list[current_name;src;2,1;1,1;]
- list[current_name;dst;5,1;2,2;]
+ 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
+ invsize[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:
-invsize[<W>,<H>;]
+size[<W>,<H>]
^ Define the size of the menu in inventory slots
+^ deprecated: invsize[<W>,<H>;]
list[<inventory location>;<list name>;<X>,<Y>;<W>,<H>;]
+list[<inventory location>;<list name>;<X>,<Y>;<W>,<H>;<starting item index>]
^ Show an inventory list
image[<X>,<Y>;<W>,<H>;<texture name>]
^ Show an image
^ Position and size units are inventory slots
-^ Not implemented
field[<X>,<Y>;<W>,<H>;<name>;<label>;<default>]
^ Textual field; will be sent to server when a button is clicked
+^ x and y position the field relative to the top left of the menu
+^ w and h are the size of the field
+^ fields are a set height, but will be vertically centred on h
+^ Position and size units are inventory slots
+^ name is the name of the field as returned in fields to on_receive_fields
+^ label, if not blank, will be text printed on the top left above the field
+^ default is the default value of the field
+ ^ default may contain variable references such as '${text}' which
+ will fill the value from the metadata value 'text'
+ ^ Note: no extra text or more than a single variable is supported ATM.
+
+field[<name>;<label>;<default>]
+^ as above but without position/size units
+^ special field for creating simple forms, such as sign text input
+^ must be used without a size[] element
+^ a 'Proceed' button will be added automatically
+
+label[<X>,<Y>;<label>]
+^ x and y work as per field
+^ label is the text on the label
^ Position and size units are inventory slots
-^ Not implemented
button[<X>,<Y>;<W>,<H>;<name>;<label>]
^ Clickable button. When clicked, fields will be sent.
-^ Button will be visible as a field, with the value "active".
+^ x, y and name work as per field
+^ w and h are the size of the button
+^ label is the text on the button
^ Position and size units are inventory slots
-^ Not implemented
+
+image_button[<X>,<Y>;<W>,<H>;<texture name>;<name>;<label>]
+^ x, y, w, h, and name work as per button
+^ image is the filename of an image
+^ Position and size units are inventory slots
+
+button_exit[<X>,<Y>;<W>,<H>;<name>;<label>]
+^ When clicked, fields will be sent and the form will quit.
+
+image_button_exit[<X>,<Y>;<W>,<H>;<texture name>;<name>;<label>]
+^ When clicked, fields will be sent and the form will quit.
Inventory location:
-- "current_name": Selected node metadata
+
+- "context": Selected node metadata (deprecated: "current_name")
- "current_player": Player to whom the menu is shown
- "player:<name>": Any player
- "nodemeta:<X>,<Y>,<Z>": Any node metadata
+- "detached:<name>": A detached inventory
Helper functions
-----------------
minetest.get_current_modname() -> string
minetest.get_modpath(modname) -> eg. "/home/user/.minetest/usermods/modname"
^ Useful for loading additional .lua modules or static data from mod
+minetest.get_modnames() -> list of installed mods
+^ Return a list of installed mods, sorted alphabetically
minetest.get_worldpath() -> eg. "/home/user/.minetest/world"
^ Useful for storing custom data
minetest.is_singleplayer()
Global callback registration functions: (Call these only at load time)
minetest.register_globalstep(func(dtime))
^ Called every server step, usually interval of 0.05s
-minetest.register_on_placenode(func(pos, newnode, placer))
+minetest.register_on_placenode(func(pos, newnode, placer, oldnode))
^ Called when a node has been placed
+^ Deprecated: Use on_construct or after_place_node in node definition instead
minetest.register_on_dignode(func(pos, oldnode, digger))
-^ Called when a node has been dug. digger can be nil.
+^ Called when a node has been dug.
+^ Deprecated: Use on_destruct or after_dig_node in node definition instead
minetest.register_on_punchnode(func(pos, node, puncher))
^ Called when a node is punched
minetest.register_on_generated(func(minp, maxp, blockseed))
^ Called when player is to be respawned
^ Called _before_ repositioning of player occurs
^ return true in func to disable regular player placement
+minetest.register_on_joinplayer(func(ObjectRef))
+^ Called when a player joins the game
+minetest.register_on_leaveplayer(func(ObjectRef))
+^ Called when a player leaves the game
minetest.register_on_chat_message(func(name, message))
+^ Called always when a player says something
+minetest.register_on_player_receive_fields(func(player, formname, fields))
+^ Called when a button is pressed in player's inventory form
+^ Newest functions are called first
+^ If function returns true, remaining functions are not called
Other registration functions:
minetest.register_chatcommand(cmd, chatcommand definition)
minetest.get_inventory(location) -> InvRef
^ location = eg. {type="player", name="celeron55"}
{type="node", pos={x=, y=, z=}}
+ {type="detached", name="creative"}
+minetest.create_detached_inventory(name, callbacks) -> InvRef
+^ callbacks: See "Detached inventory callbacks"
+^ Creates a detached inventory. If it already exists, it is cleared.
Item handling:
minetest.inventorycube(img1, img2, img3)
^ output.item = ItemStack, if unsuccessful: empty ItemStack
^ output.time = number, if unsuccessful: 0
^ decremented_input = like input
+minetest.get_craft_recipe(output) -> input
+^ output is a node or item type such as 'default:torch'
+^ input.method = 'normal' or 'cooking' or 'fuel'
+^ input.width = for example 3
+^ input.items = for example { stack 1, stack 2, stack 3, stack 4,
+ stack 5, stack 6, stack 7, stack 8, stack 9 }
+^ input.items = nil if no recipe found
Defaults for the on_* item definition functions:
(These return the leftover itemstack)
^ Get rating of a group of an item. (0 = not in group)
minetest.get_node_group(name, group) -> rating
^ Deprecated: An alias for the former.
+minetest.serialize(table) -> string
+^ Convert a table containing tables, strings, numbers, booleans and nils
+ into string form readable by minetest.deserialize
+^ Example: serialize({foo='bar'}) -> 'return { ["foo"] = "bar" }'
+minetest.deserialize(string) -> table
+^ Convert a string returned by minetest.deserialize into a table
+^ String is loaded in an empty sandbox environment.
+^ Will load functions, but they cannot access the global environment.
+^ Example: deserialize('return { ["foo"] = "bar" }') -> {foo='bar'}
+^ Example: deserialize('print("foo")') -> nil (function call fails)
+ ^ error:[string "print("foo")"]:1: attempt to call global 'print' (a nil value)
Global objects:
minetest.env - EnvRef of the server environment and world.
methods:
- set_node(pos, node)
- add_node(pos, node): alias set_node(pos, node)
-- remove_node(pos): equivalent to set_node(pos, "air")
+ ^ Set node at position (node = {name="foo", param1=0, param2=0})
+- remove_node(pos)
+ ^ Equivalent to set_node(pos, "air")
- get_node(pos)
^ Returns {name="ignore", ...} for unloaded area
- get_node_or_nil(pos)
^ Returns nil for unloaded area
- get_node_light(pos, timeofday) -> 0...15 or nil
^ timeofday: nil = current time, 0 = night, 0.5 = day
+
+- place_node(pos, node)
+ ^ Place node with the same effects that a player would cause
+- dig_node(pos)
+ ^ Dig node with the same effects that a player would cause
+- punch_node(pos)
+ ^ Punch node with the same effects that a player would cause
+
+- get_meta(pos) -- Get a NodeMetaRef at that position
+- get_node_timer(pos) -- Get NodeTimerRef
+
- add_entity(pos, name): Spawn Lua-defined entity at position
^ Returns ObjectRef, or nil if failed
-- add_item(pos, itemstring): Spawn item
+- add_item(pos, item): Spawn item
^ Returns ObjectRef, or nil if failed
-- get_meta(pos) -- Get a NodeMetaRef at that position
- get_player_by_name(name) -- Get an ObjectRef to a player
- get_objects_inside_radius(pos, radius)
- set_timeofday(val): val: 0...1; 0 = midnight, 0.5 = midday
- to_table() -> nil or {fields = {...}, inventory = {list1 = {}, ...}}
- from_table(nil or {})
^ See "Node Metadata"
+
+NodeTimerRef: Node Timers - a high resolution persistent per-node timer
+- Can be gotten via minetest.env:get_node_timer(pos)
+methods:
+- set(timeout,elapsed)
+ ^ set a timer's state
+ ^ timeout is in seconds, and supports fractional values (0.1 etc)
+ ^ elapsed is in seconds, and supports fractional values (0.1 etc)
+ ^ will trigger the node's on_timer function after timeout-elapsed seconds
+- start(timeout)
+ ^ start a timer
+ ^ equivelent to set(timeout,0)
+- stop()
+ ^ stops the timer
+- get_timeout() -> current timeout in seconds
+ ^ if timeout is 0, timer is inactive
+- get_elapsed() -> current elapsed time in seconds
+ ^ the node's on_timer function will be called after timeout-elapsed seconds
+- is_started() -> boolean state of timer
+ ^ returns true if timer is started, otherwise false
ObjectRef: Moving things in the game are generally these
(basically reference to a C++ ServerActiveObject)
- settexturemod(mod)
- setsprite(p={x=0,y=0}, num_frames=1, framelength=0.2,
- select_horiz_by_yawpitch=false)
-- ^ Select sprite from spritesheet with optional animation and DM-style
-- texture selection based on yaw relative to camera
+ ^ Select sprite from spritesheet with optional animation and DM-style
+ texture selection based on yaw relative to camera
- get_entity_name() (DEPRECATED: Will be removed in a future version)
- get_luaentity()
Player-only: (no-op for other objects)
-- get_player_name(): will return nil if is not a player
+- is_player(): true for players, false for others
+- get_player_name(): returns "" if is not a player
- get_look_dir(): get camera direction as a unit vector
- get_look_pitch(): pitch in radians
- get_look_yaw(): yaw in radians (wraps around pretty randomly as of now)
+- set_inventory_formspec(formspec)
+ ^ Redefine player's inventory form
+ ^ Should usually be called in on_joinplayer
+- get_inventory_formspec() -> formspec string
InvRef: Reference to an inventory
methods:
+- is_empty(listname): return true if list is empty
- get_size(listname): get size of a list
- set_size(listname, size): set size of a list
- get_stack(listname, i): get a copy of stack index i in list
Object Properties
{
+ hp_max = 1,
physical = true,
+ weight = 5,
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
visual = "cube"/"sprite"/"upright_sprite",
visual_size = {x=1, y=1},
initial_sprite_basepos = {x=0, y=0},
is_visible = true,
makes_footstep_sound = false,
+ automatic_rotate = false,
}
Entity definition (register_entity)
choppy={times={[3]=0.90}, maxwear=0.05, maxlevel=0}
}
}
+ node_placement_prediction = nil,
+ ^ If nil and item is node, prediction is made automatically
+ ^ If nil and item is not a node, no prediction is made
+ ^ If "" and item is anything, no prediction is made
+ ^ Otherwise should be name of node which the client immediately places
+ on ground when the player places the item. Server will always update
+ actual result to client in a short moment.
on_place = func(itemstack, placer, pointed_thing),
+ ^ Shall place item and return the leftover itemstack
^ default: minetest.item_place
on_drop = func(itemstack, dropper, pos),
+ ^ Shall drop item and return the leftover itemstack
^ default: minetest.item_drop
on_use = func(itemstack, user, pointed_thing),
^ default: nil
^ The default functions handle regular use cases.
}
+Tile definition:
+- "image.png"
+- {name="image.png", animation={Tile Animation definition}}
+- {name="image.png", backface_culling=bool}
+ ^ backface culling only supported in special tiles
+- deprecated still supported field names:
+ - image -> name
+
+Tile animation definition:
+- {type="vertical_frames", aspect_w=16, aspect_h=16, length=3.0}
+
Node definition (register_node)
{
<all fields allowed in item definitions>,
- drawtype = "normal",
+ drawtype = "normal", -- See "Node drawtypes"
visual_scale = 1.0,
- tile_images = {"default_unknown_block.png"},
- special_materials = {
- {image="", backface_culling=true},
- {image="", backface_culling=true},
- },
+ tiles = {tile definition 1, def2, def3, def4, def5, def6},
+ ^ Textures of node; +Y, -Y, +X, -X, +Z, -Z (old field name: tile_images)
+ ^ List can be shortened to needed length
+ special_tiles = {tile definition 1, Tile definition 2},
+ ^ Special textures of node; used rarely (old field name: special_materials)
+ ^ List can be shortened to needed length
alpha = 255,
- post_effect_color = {a=0, r=0, g=0, b=0},
- paramtype = "none",
- paramtype2 = "none",
- is_ground_content = false,
- sunlight_propagates = false,
- walkable = true,
- pointable = true,
- diggable = true,
- climbable = false,
- buildable_to = false,
- drop = "",
- -- alternatively drop = { max_items = ..., items = { ... } }
- liquidtype = "none",
- liquid_alternative_flowing = "",
- liquid_alternative_source = "",
- liquid_viscosity = 0,
- light_source = 0,
- damage_per_second = 0,
- selection_box = {type="regular"},
+ post_effect_color = {a=0, r=0, g=0, b=0}, -- If player is inside node
+ paramtype = "none", -- See "Nodes"
+ paramtype2 = "none", -- See "Nodes"
+ is_ground_content = false, -- Currently not used for anything
+ sunlight_propagates = false, -- If true, sunlight will go infinitely through this
+ walkable = true, -- If true, objects collide with node
+ pointable = true, -- If true, can be pointed at
+ diggable = true, -- If false, can never be dug
+ climbable = false, -- If true, can be climbed on (ladder)
+ buildable_to = false, -- If true, placed nodes can replace this node
+ drop = "", -- alternatively drop = { max_items = ..., items = { ... } }
+ liquidtype = "none", -- "none"/"source"/"flowing"
+ liquid_alternative_flowing = "", -- Flowing version of source liquid
+ liquid_alternative_source = "", -- Source version of flowing liquid
+ liquid_viscosity = 0, -- Higher viscosity = slower flow (max. 7)
+ light_source = 0, -- Amount of light emitted by node
+ damage_per_second = 0, -- If player is inside node, this damage is caused
+ node_box = {type="regular"}, -- See "Node boxes"
+ selection_box = {type="regular"}, -- See "Node boxes"
legacy_facedir_simple = false, -- Support maps made in and before January 2012
legacy_wallmounted = false, -- Support maps made in and before January 2012
sounds = {
on_construct = func(pos),
^ Node constructor; always called after adding node
^ Can set up metadata and stuff like that
+ ^ default: nil
on_destruct = func(pos),
^ Node destructor; always called before removing node
+ ^ default: nil
+ after_destruct = func(pos, oldnode),
+ ^ Node destructor; always called after removing node
+ ^ default: nil
+
+ after_place_node = func(pos, placer),
+ ^ Called after constructing node when node was placed using
+ minetest.item_place_node / minetest.env:place_node
+ ^ default: nil
+ after_dig_node = func(pos, oldnode, oldmetadata, digger),
+ ^ oldmetadata is in table format
+ ^ Called after destructing node when node was dug using
+ minetest.node_dig / minetest.env:dig_node
+ ^ default: nil
+ can_dig = function(pos,player)
+ ^ returns true if node can be dug, or false if not
+ ^ default: nil
on_punch = func(pos, node, puncher),
^ default: minetest.node_punch
^ By default: does nothing
- on_dig = func(pos, node, digger),
+ on_dig = func(pos, node, digger),
^ default: minetest.node_dig
^ By default: checks privileges, wears out tool and removes node
+
+ on_timer = function(pos,elapsed),
+ ^ default: nil
+ ^ called by NodeTimers, see EnvRef and NodeTimerRef
+ ^ elapsed is the total time passed since the timer was started
+ ^ return true to run the timer for another cycle with the same timeout value
on_receive_fields = func(pos, formname, fields, sender),
^ fields = {name1 = value1, name2 = value2, ...}
^ Called when an UI form (eg. sign text input) returns data
^ default: nil
- on_metadata_inventory_move = func(pos, from_list, from_index,
- to_list, to_index, count, player),
- ^ Called when a player wants to move items inside the metadata
- ^ Should move items, or some items, if permitted. If not, should do
- nothing.
- ^ The engine ensures the action is valid, i.e. the stack fits at the
- given position
- ^ default: minetest.node_metadata_inventory_move_allow_all
-
- on_metadata_inventory_offer = func(pos, listname, index, stack, player),
- ^ Called when a player wants to put something into the metadata
- inventory
- ^ Should check if the action is permitted (the engine ensures the
- action is valid, i.e. the stack fits at the given position)
- ^ If permitted, modify the metadata inventory and return the
- "leftover" stack (normally nil).
- ^ If not permitted, return itemstack.
- ^ default: minetest.node_metadata_inventory_offer_allow_all
-
- on_metadata_inventory_take = func(pos, listname, index, count, player),
- ^ Called when a player wants to take something out of the metadata
- inventory
- ^ Should check if the action is permitted (the engine ensures the
- action is valid, i.e. there's a stack of at least “count” items at
- that position)
- ^ If permitted, modify the metadata inventory and return the
- stack of items
- ^ If not permitted, return nil.
- ^ default: minetest.node_metadata_inventory_take_allow_all
+ allow_metadata_inventory_move = func(pos, from_list, from_index,
+ to_list, to_index, count, player),
+ ^ Called when a player wants to move items inside the inventory
+ ^ Return value: number of items allowed to move
+
+ allow_metadata_inventory_put = func(pos, listname, index, stack, player),
+ ^ Called when a player wants to put something into the inventory
+ ^ Return value: number of items allowed to put
+
+ allow_metadata_inventory_take = func(pos, listname, index, count, player),
+ ^ Called when a player wants to take something out of the inventory
+ ^ Return value: number of items allowed to take
+
+ on_metadata_inventory_move = func(pos, from_list, from_index,
+ to_list, to_index, count, player),
+ on_metadata_inventory_put = func(pos, listname, index, stack, player),
+ on_metadata_inventory_take = func(pos, listname, index, count, player),
+ ^ Called after the actual action has happened, according to what was allowed.
+ ^ No return value
}
-Recipe: (register_craft)
+Recipe for register_craft: (shaped)
{
output = 'default:pick_stone',
recipe = {
{'default:cobble', 'default:cobble', 'default:cobble'},
{'', 'default:stick', ''},
- {'', 'default:stick', ''},
+ {'', 'default:stick', ''}, -- Also groups; eg. 'group:crumbly'
},
replacements = <optional list of item pairs,
replace one input item with another item on crafting>
}
-Recipe (shapeless):
+Recipe for register_craft (shapeless)
{
type = "shapeless",
output = 'mushrooms:mushroom_stew',
replace one input item with another item on crafting>
}
-Recipe (tool repair):
+Recipe for register_craft (tool repair)
{
type = "toolrepair",
additional_wear = -0.02,
}
-Recipe (cooking):
+Recipe for register_craft (cooking)
{
type = "cooking",
output = "default:glass",
cooktime = 3,
}
-Recipe (furnace fuel):
+Recipe for register_craft (furnace fuel)
{
type = "fuel",
recipe = "default:leaves",
func = function(name, param), -- called when command is run
}
+Detached inventory callbacks
+{
+ allow_move = func(inv, from_list, from_index, to_list, to_index, count, player),
+ ^ Called when a player wants to move items inside the inventory
+ ^ Return value: number of items allowed to move
+
+ allow_put = func(inv, listname, index, stack, player),
+ ^ Called when a player wants to put something into the inventory
+ ^ Return value: number of items allowed to put
+
+ allow_take = func(inv, listname, index, count, player),
+ ^ Called when a player wants to take something out of the inventory
+ ^ Return value: number of items allowed to take
+
+ on_move = func(inv, from_list, from_index, to_list, to_index, count, player),
+ on_put = func(inv, listname, index, stack, player),
+ on_take = func(inv, listname, index, count, player),
+ ^ Called after the actual action has happened, according to what was allowed.
+ ^ No return value
+}
+