Groups of nodes
----------------
-In addition to the general item things, whether a node is diggable and how
-long it takes is defined by using groups.
+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
-------------------
damage, and get weared 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 tool wear)
- 2: node is removed without tool wear after 0.5 seconds or so
(rail, sign)
Known damage and digging time defining groups
----------------------------------------------
+Valid ratings for these are 0, 1, 2 and 3, unless otherwise stated.
- crumbly: dirt, sand
- cracky: tough but crackable stuff like stone.
- snappy: something that can be cut using fine tools; eg. leaves, small
purpose. Rating is 1, 2 or 3. A higher rating for such a group implies
faster digging time.
-Also, the **level** group is used.
+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.
-**Example definition of the digging capabilities of a tool:**
+**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
+
+**Full punch interval**:
+When used as a weapon, the tool will do full damage if this time is spent
+between punches. If eg. 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. (eg. 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 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.
+ * For entities, damage equals the amount of nodes dug in the time spent
+ between hits, with a maximum time of ''full_punch_interval''.
+
+Example definition of the capabilities of a tool
+-------------------------------------------------
tool_capabilities = {
full_punch_interval=1.5,
max_drop_level=1,
groupcaps={
- crumbly={maxwear=0.01, maxlevel=2, times={[1]=0.80, [2]=0.60, [3]=0.40}}
+ crumbly={maxlevel=2, uses=20, times={[1]=1.60, [2]=1.20, [3]=0.80}}
}
}
-**Tools define:**
- * Full punch interval Maximum drop level For an arbitrary list of groups:
- * Maximum level (usually 0, 1, 2 or 3) Maximum wear (0...1) Digging times
-
-**Full punch interval**: When used as a weapon, the tool will do full
-damage if this time is spent between punches. If eg. 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. (eg. iron ore to drop a lump of
-iron).
-
-**Maximum level** tells what is the maximum level of a node of this group
-that the tool will be able to dig.
-
-**Maximum wear** determines how much the tool wears out when it is used for
-digging a node, of this group, of the maximum level. For lower leveled
-tools, the wear is divided by //4// to the exponent //level difference//.
-This means for a maximum wear of 0.1, a level difference 1 will result in
-wear=0.1/4=0.025, and a level difference of 2 will result in
-wear=0.1/(4*4)=0.00625.
-
-**Digging times** is basically a list of digging times for different
-ratings of the group. It also determines the damage done to entities, based
-on their "armor groups".
- * For example, as a lua table, ''times={2=2.00, 3=0.70}''. This would
- * result 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. For
- * entities, damage equals the amount of nodes dug in the time spent
- * between hits, with a maximum of ''full_punch_interval''.
+This makes the tool be able to dig nodes that fullfill 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:
+- Take the time spent after the last hit
+- Limit time to full_punch_interval
+- Take the damage groups, assume a node has them
+- Damage in HP is the amount of nodes destroyed in this time.
+
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 (eg. by defining a sprite animation) (not implemented;
TODO).
+- Currently a smoke puff will appear when an entity dies.
The group **immortal** will completely disable normal damage.
^ Return object serialized as a string, handles reference loops
dump(obj, dumped={})
^ Return object serialized as a string
+string:split(separator)
+^ eg. string:split("a,b", ",") == {"a","b"}
+string:trim()
+^ eg. string.trim("\n \t\tfoo bar\t ") == "foo bar"
+minetest.pos_to_string({x=X,y=Y,z=Z}) -> "(X,Y,Z)"
+^ Convert position to a printable string
minetest namespace reference
-----------------------------
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_worldpath(modname) -> eg. "/home/user/.minetest/world"
+minetest.get_worldpath() -> eg. "/home/user/.minetest/world"
^ Useful for storing custom data
+minetest.is_singleplayer()
minetest.debug(line)
^ Goes to dstream
minetest.log(loglevel, line)
^ loglevel one of "error", "action", "info", "verbose"
+Registration functions: (Call these only at load time)
minetest.register_entity(name, prototype table)
minetest.register_abm(abm definition)
minetest.register_node(name, node definition)
minetest.register_craftitem(name, item definition)
minetest.register_alias(name, convert_to)
minetest.register_craft(recipe)
-
minetest.register_globalstep(func(dtime))
minetest.register_on_placenode(func(pos, newnode, placer))
minetest.register_on_dignode(func(pos, oldnode, digger))
minetest.register_on_punchnode(func(pos, node, puncher))
-minetest.register_on_generated(func(minp, maxp))
+minetest.register_on_generated(func(minp, maxp, blockseed))
minetest.register_on_newplayer(func(ObjectRef))
minetest.register_on_dieplayer(func(ObjectRef))
minetest.register_on_respawnplayer(func(ObjectRef))
^ return true in func to disable regular player placement
^ currently called _before_ repositioning of player occurs
minetest.register_on_chat_message(func(name, message))
-
-minetest.add_to_creative_inventory(itemstring)
+minetest.register_chatcommand(cmd, chatcommand definition)
+minetest.register_privilege(name, definition)
+^ definition: "description text"
+^ definition: {
+ description = "description text",
+ give_to_singleplayer = boolean, -- default: true
+ }
+minetest.register_authentication_handler(handler)
+^ See minetest.builtin_auth_handler in builtin.lua for reference
+
+Setting-related:
+minetest.setting_set(name, value)
minetest.setting_get(name) -> string or nil
minetest.setting_getbool(name) -> boolean value or nil
+minetest.add_to_creative_inventory(itemstring)
+Authentication:
+minetest.notify_authentication_modified(name)
+^ Should be called by the authentication handler if privileges change.
+^ To report everybody, set name=nil.
+minetest.get_password_hash(name, raw_password)
+^ Convert a name-password pair to a password hash that minetest can use
+minetest.string_to_privs(str) -> {priv1=true,...}
+minetest.privs_to_string(privs) -> "priv1,priv2,..."
+^ Convert between two privilege representations
+minetest.set_player_password(name, password_hash)
+minetest.set_player_privs(name, {priv1=true,...})
+minetest.get_player_privs(name) -> {priv1=true,...}
+minetest.auth_reload()
+^ These call the authentication handler
+minetest.check_player_privs(name, {priv1=true,...}) -> bool, missing_privs
+^ A quickhand for checking privileges
+
+Chat:
minetest.chat_send_all(text)
minetest.chat_send_player(name, text)
-minetest.get_player_privs(name) -> set of privs
+
+Inventory:
minetest.get_inventory(location) -> InvRef
^ location = eg. {type="player", name="celeron55"}
{type="node", pos={x=, y=, z=}}
+Item handling:
+minetest.inventorycube(img1, img2, img3)
+^ Returns a string for making an image of a cube (useful as an item image)
+minetest.get_pointed_thing_position(pointed_thing, above)
+^ Get position of a pointed_thing (that you can get from somewhere)
+minetest.dir_to_facedir(dir)
+^ Convert a vector to a facedir value, used in param2 for paramtype2="facedir"
+minetest.dir_to_wallmounted(dir)
+^ Convert a vector to a wallmounted value, used for paramtype2="wallmounted"
+minetest.get_node_drops(nodename, toolname)
+^ Returns list of item names.
+^ Note: This will be removed or modified in a future version.
+
+Defaults for the on_* item definition functions:
+(These return the leftover itemstack)
+minetest.item_place_node(itemstack, placer, pointed_thing)
+^ Place item as a node
+minetest.item_place_object(itemstack, placer, pointed_thing)
+^ Place item as-is
+minetest.item_place(itemstack, placer, pointed_thing)
+^ Use one of the above based on what the item is.
+minetest.item_drop(itemstack, dropper, pos)
+^ Drop the item
+minetest.item_eat(hp_change, replace_with_item)
+^ Eat the item. replace_with_item can be nil.
+
+Defaults for the on_punch and on_dig node definition callbacks:
+minetest.node_punch(pos, node, puncher)
+^ Calls functions registered by minetest.register_on_punchnode()
+minetest.node_dig(pos, node, digger)
+^ Checks if node can be dug, puts item into inventory, removes node
+^ Calls functions registered by minetest.registered_on_dignodes()
+
+Sounds:
minetest.sound_play(spec, parameters) -> handle
^ spec = SimpleSoundSpec
^ parameters = sound parameter table
minetest.sound_stop(handle)
-minetest.after(time, func)
+Timing:
+minetest.after(time, func, param)
^ Call function after time seconds
+^ param is optional; to pass multiple parameters, pass a table.
+
+Random:
+minetest.get_connected_players() -> list of ObjectRefs
+minetest.hash_node_position({x=,y=,z=}) -> 48-bit integer
+^ Gives a unique hash number for a node position (16+16+16=48bit)
Global objects:
minetest.env - environment reference
----------------
EnvRef: basically ServerEnvironment and ServerMap combined.
methods:
-- add_node(pos, node)
-- remove_node(pos)
+- set_node(pos, node)
+- add_node(pos, node): alias set_node(pos, node)
+- 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
-- add_entity(pos, name): Returns ObjectRef or nil if failed
-- add_item(pos, itemstring)
-- add_rat(pos)
-- add_firefly(pos)
+- add_entity(pos, name): Spawn Lua-defined entity at position
+ ^ Returns ObjectRef, or nil if failed
+- add_item(pos, itemstring): 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
- get_timeofday()
+- find_node_near(pos, radius, nodenames) -> pos or nil
+ ^ nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
+- get_perlin(seeddiff, octaves, persistence, scale)
+ ^ Return world-specific perlin noise (int(worldseed)+seeddiff)
+Deprecated:
+- add_rat(pos): Add C++ rat object (no-op)
+- add_firefly(pos): Add C++ firefly object (no-op)
NodeMetaRef (this stuff is subject to change in a future version)
methods:
- get_wield_index(): returns the index of the wielded item
- get_wielded_item() -> ItemStack
- set_wielded_item(item): replaces the wielded item, returns true if successful
+- set_armor_groups({group1=rating, group2=rating, ...})
+- set_properties(object property table)
LuaEntitySAO-only: (no-op for other objects)
- setvelocity({x=num, y=num, z=num})
- getvelocity() -> {x=num, y=num, z=num}
- select_horiz_by_yawpitch=false)
- ^ Select sprite from spritesheet with optional animation and DM-style
- texture selection based on yaw relative to camera
-- set_armor_groups({group1=rating, group2=rating, ...})
- get_entity_name() (DEPRECATED: Will be removed in a future version)
- get_luaentity()
Player-only: (no-op for other objects)
returns the items that were actually removed (as an ItemStack)
ItemStack: A stack of items.
+- Can be created via ItemStack(itemstack or itemstring or table or nil)
methods:
- is_empty(): return true if stack is empty
- get_name(): returns item name (e.g. "default:stone")
^ returns copied ItemStack
^ if n is omitted, n=1 is used
+PseudoRandom: A pseudorandom number generator
+- Can be created via PseudoRandom(seed)
+methods:
+- next(): return next integer random number [0...32767]
+- next(min, max): return next integer random number [min...max]
+ (max - min) must be 32767 or <= 6553 due to the simple
+ implementation making bad distribution otherwise.
+
+PerlinNoise: A perlin noise generator
+- Can be created via PerlinNoise(seed, octaves, persistence, scale)
+- Also minetest.env:get_perlin(seeddiff, octaves, persistence, scale)
+methods:
+- get2d(pos) -> 2d noise value at pos={x=,y=}
+- get3d(pos) -> 3d noise value at pos={x=,y=,z=}
+
Registered entities
--------------------
- Functions receive a "luaentity" as self:
Definition tables
------------------
-Entity definition (register_entity)
+Object Properties
{
physical = true,
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
- visual = "cube"/"sprite",
+ visual = "cube"/"sprite"/"upright_sprite",
visual_size = {x=1, y=1},
- textures = {texture,texture,texture,texture,texture,texture},
+ textures = {}, -- number of required textures depends on visual
spritediv = {x=1, y=1},
initial_sprite_basepos = {x=0, y=0},
+ is_visible = true,
+ makes_footstep_sound = false,
+}
+
+Entity definition (register_entity)
+{
+ (Deprecated: Everything in object properties is read directly from here)
+
+ initial_properties = <initial object properties>,
+
on_activate = function(self, staticdata),
on_step = function(self, dtime),
on_punch = function(self, hitter),
on_rightclick = function(self, clicker),
get_staticdata = function(self),
+ ^ Called sometimes; the string returned is passed to on_activate when
+ the entity is re-activated from static state
+
# Also you can define arbitrary member variables here
myvariable = whatever,
}
ABM (ActiveBlockModifier) definition (register_abm)
{
+ -- In the following two fields, also group:groupname will work.
nodenames = {"default:lava_source"},
neighbors = {"default:water_source", "default:water_flowing"}, -- (any of these)
^ If left out or empty, any neighbor will do
choppy={times={[3]=0.90}, maxwear=0.05, maxlevel=0}
}
}
- on_drop = func(item, dropper, pos),
- on_place = func(item, placer, pointed_thing),
- on_use = func(item, user, pointed_thing),
+ on_drop = func(itemstack, dropper, pos),
+ on_place = func(itemstack, placer, pointed_thing),
+ on_use = func(itemstack, user, pointed_thing),
+ ^ Function must return either nil if no item shall be removed from
+ inventory, or an itemstack to replace the original itemstack.
+ eg. itemstack:take_item(); return itemstack
+ ^ Otherwise, the function is free to do what it wants.
+ ^ The default functions handle regular use cases.
}
Node definition (register_node)
burntime = 1,
}
+Chatcommand definition (register_chatcommand)
+{
+ params = "<name> <privilege>", -- short parameter description
+ description = "Remove privilege from player", -- full description
+ privs = {privs=true}, -- require the "privs" privilege to run
+ func = function(name, param), -- called when command is run
+}