2 -- This file contains built-in stuff in Minetest implemented in Lua.
4 -- It is always loaded and executed after registration of the C API,
5 -- before loading and running any mods.
8 function basic_dump2(o)
9 if type(o) == "number" then
11 elseif type(o) == "string" then
12 return string.format("%q", o)
13 elseif type(o) == "boolean" then
15 elseif type(o) == "function" then
17 elseif type(o) == "userdata" then
19 elseif type(o) == "nil" then
22 error("cannot dump a " .. type(o))
27 function dump2(o, name, dumped)
31 if type(o) == "number" or type(o) == "string" or type(o) == "boolean"
32 or type(o) == "function" or type(o) == "nil"
33 or type(o) == "userdata" then
34 io.write(basic_dump2(o), "\n")
35 elseif type(o) == "table" then
37 io.write(dumped[o], "\n")
40 io.write("{}\n") -- new table
41 for k,v in pairs(o) do
42 local fieldname = string.format("%s[%s]", name, basic_dump2(k))
43 dump2(v, fieldname, dumped)
47 error("cannot dump a " .. type(o))
52 function dump(o, dumped)
54 if type(o) == "number" then
56 elseif type(o) == "string" then
57 return string.format("%q", o)
58 elseif type(o) == "table" then
60 return "<circular reference>"
64 for k,v in pairs(o) do
65 t[#t+1] = "" .. k .. " = " .. dump(v, dumped)
67 return "{" .. table.concat(t, ", ") .. "}"
68 elseif type(o) == "boolean" then
70 elseif type(o) == "function" then
72 elseif type(o) == "userdata" then
74 elseif type(o) == "nil" then
77 error("cannot dump a " .. type(o))
83 -- Item definition helpers
86 minetest.inventorycube = function(img1, img2, img3)
89 return "[inventorycube"
90 .. "{" .. img1:gsub("%^", "&")
91 .. "{" .. img2:gsub("%^", "&")
92 .. "{" .. img3:gsub("%^", "&")
95 minetest.get_pointed_thing_position = function(pointed_thing, above)
96 if pointed_thing.type == "node" then
98 -- The position where a node would be placed
99 return pointed_thing.above
101 -- The position where a node would be dug
102 return pointed_thing.under
104 elseif pointed_thing.type == "object" then
105 obj = pointed.thing.ref
116 function minetest.item_place(itemstack, placer, pointed_thing)
117 pos = minetest.get_pointed_thing_position(pointed_thing, true)
119 item = itemstack:take_item()
121 minetest.env:add_item(pos, item)
127 function minetest.item_drop(itemstack, dropper, pos)
128 minetest.env:add_item(pos, itemstack)
132 function minetest.item_eat(hp_change)
133 return function(itemstack, user, pointed_thing) -- closure
134 if itemstack:take_item() ~= nil then
135 user:set_hp(user:get_hp() + hp_change)
142 -- Item definition defaults
145 minetest.nodedef_default = {
148 -- name intentionally not defined here
150 inventory_image = "",
152 wield_scale = {x=1,y=1,z=1},
156 liquids_pointable = false,
157 tool_digging_properties = nil,
159 -- Interaction callbacks
160 on_place = nil, -- let C handle node placement for now
161 on_drop = minetest.item_drop,
168 special_materials = {
169 {image="", backface_culling=true},
170 {image="", backface_culling=true},
173 post_effect_color = {a=0, r=0, g=0, b=0},
175 is_ground_content = false,
176 sunlight_propagates = false,
181 buildable_to = false,
182 wall_mounted = false,
183 --dug_item intentionally not defined here
185 extra_dug_item_rarity = 2,
188 liquid_alternative_flowing = "",
189 liquid_alternative_source = "",
190 liquid_viscosity = 0,
192 damage_per_second = 0,
193 selection_box = {type="regular"},
195 diggablity = "normal",
204 minetest.craftitemdef_default = {
206 -- name intentionally not defined here
208 inventory_image = "",
210 wield_scale = {x=1,y=1,z=1},
212 liquids_pointable = false,
213 tool_digging_properties = nil,
215 -- Interaction callbacks
216 on_place = minetest.item_place,
217 on_drop = minetest.item_drop,
221 minetest.tooldef_default = {
223 -- name intentionally not defined here
225 inventory_image = "",
227 wield_scale = {x=1,y=1,z=1},
229 liquids_pointable = false,
230 tool_digging_properties = nil,
232 -- Interaction callbacks
233 on_place = minetest.item_place,
234 on_drop = minetest.item_drop,
238 minetest.noneitemdef_default = { -- This is used for the hand and unknown items
240 -- name intentionally not defined here
242 inventory_image = "",
244 wield_scale = {x=1,y=1,z=1},
246 liquids_pointable = false,
247 tool_digging_properties = nil,
249 -- Interaction callbacks
256 -- Make raw registration functions inaccessible to anyone except builtin.lua
259 local register_item_raw = minetest.register_item_raw
260 minetest.register_item_raw = nil
262 local register_alias_raw = minetest.register_alias_raw
263 minetest.register_item_raw = nil
266 -- Item / entity / ABM registration functions
269 minetest.registered_abms = {}
270 minetest.registered_entities = {}
271 minetest.registered_items = {}
272 minetest.registered_nodes = {}
273 minetest.registered_craftitems = {}
274 minetest.registered_tools = {}
275 minetest.registered_aliases = {}
277 -- For tables that are indexed by item name:
278 -- If table[X] does not exist, default to table[minetest.registered_aliases[X]]
279 local function set_alias_metatable(table)
280 setmetatable(table, {
281 __index = function(name)
282 return rawget(table, minetest.registered_aliases[name])
286 set_alias_metatable(minetest.registered_items)
287 set_alias_metatable(minetest.registered_nodes)
288 set_alias_metatable(minetest.registered_craftitems)
289 set_alias_metatable(minetest.registered_tools)
291 -- These item names may not be used because they would interfere
292 -- with legacy itemstrings
293 local forbidden_item_names = {
295 MaterialItem2 = true,
296 MaterialItem3 = true,
306 local function check_modname_prefix(name)
307 if name:sub(1,1) == ":" then
308 -- Escape the modname prefix enforcement mechanism
311 -- Modname prefix enforcement
312 local expected_prefix = minetest.get_current_modname() .. ":"
313 if name:sub(1, #expected_prefix) ~= expected_prefix then
314 error("Name " .. name .. " does not follow naming conventions: " ..
315 "\"modname:\" or \":\" prefix required")
317 local subname = name:sub(#expected_prefix+1)
318 if subname:find("[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]") then
319 error("Name " .. name .. " does not follow naming conventions: " ..
320 "contains unallowed characters")
326 function minetest.register_abm(spec)
327 -- Add to minetest.registered_abms
328 minetest.registered_abms[#minetest.registered_abms+1] = spec
331 function minetest.register_entity(name, prototype)
334 error("Unable to register entity: Name is nil")
336 name = check_modname_prefix(tostring(name))
338 prototype.name = name
339 prototype.__index = prototype -- so that it can be used as a metatable
341 -- Add to minetest.registered_entities
342 minetest.registered_entities[name] = prototype
345 function minetest.register_item(name, itemdef)
348 error("Unable to register item: Name is nil")
350 name = check_modname_prefix(tostring(name))
351 if forbidden_item_names[name] then
352 error("Unable to register item: Name is forbidden: " .. name)
356 -- Apply defaults and add to registered_* table
357 if itemdef.type == "node" then
358 setmetatable(itemdef, {__index = minetest.nodedef_default})
359 minetest.registered_nodes[itemdef.name] = itemdef
360 elseif itemdef.type == "craft" then
361 setmetatable(itemdef, {__index = minetest.craftitemdef_default})
362 minetest.registered_craftitems[itemdef.name] = itemdef
363 elseif itemdef.type == "tool" then
364 setmetatable(itemdef, {__index = minetest.tooldef_default})
365 minetest.registered_tools[itemdef.name] = itemdef
366 elseif itemdef.type == "none" then
367 setmetatable(itemdef, {__index = minetest.noneitemdef_default})
369 error("Unable to register item: Type is invalid: " .. dump(itemdef))
373 if itemdef.type == "node" and itemdef.dug_item == nil then
374 itemdef.dug_item = ItemStack({name=itemdef.name}):to_string()
378 if itemdef.cookresult_itemstring ~= nil and itemdef.cookresult_itemstring ~= "" then
379 minetest.register_craft({
381 output=itemdef.cookresult_itemstring,
383 cooktime=itemdef.furnace_cooktime
386 if itemdef.furnace_burntime ~= nil and itemdef.furnace_burntime >= 0 then
387 minetest.register_craft({
390 burntime=itemdef.furnace_burntime
394 -- Disable all further modifications
395 getmetatable(itemdef).__newindex = {}
397 --minetest.log("Registering item: " .. itemdef.name)
398 minetest.registered_items[itemdef.name] = itemdef
399 minetest.registered_aliases[itemdef.name] = nil
400 register_item_raw(itemdef)
403 function minetest.register_node(name, nodedef)
404 nodedef.type = "node"
405 minetest.register_item(name, nodedef)
408 function minetest.register_craftitem(name, craftitemdef)
409 craftitemdef.type = "craft"
412 if craftitemdef.inventory_image == nil and craftitemdef.image ~= nil then
413 craftitemdef.inventory_image = craftitemdef.image
416 minetest.register_item(name, craftitemdef)
419 function minetest.register_tool(name, tooldef)
420 tooldef.type = "tool"
421 tooldef.stack_max = 1
424 if tooldef.inventory_image == nil and tooldef.image ~= nil then
425 tooldef.inventory_image = tooldef.image
427 if tooldef.tool_digging_properties == nil and
428 (tooldef.full_punch_interval ~= nil or
429 tooldef.basetime ~= nil or
430 tooldef.dt_weight ~= nil or
431 tooldef.dt_crackiness ~= nil or
432 tooldef.dt_crumbliness ~= nil or
433 tooldef.dt_cuttability ~= nil or
434 tooldef.basedurability ~= nil or
435 tooldef.dd_weight ~= nil or
436 tooldef.dd_crackiness ~= nil or
437 tooldef.dd_crumbliness ~= nil or
438 tooldef.dd_cuttability ~= nil) then
439 tooldef.tool_digging_properties = {
440 full_punch_interval = tooldef.full_punch_interval,
441 basetime = tooldef.basetime,
442 dt_weight = tooldef.dt_weight,
443 dt_crackiness = tooldef.dt_crackiness,
444 dt_crumbliness = tooldef.dt_crumbliness,
445 dt_cuttability = tooldef.dt_cuttability,
446 basedurability = tooldef.basedurability,
447 dd_weight = tooldef.dd_weight,
448 dd_crackiness = tooldef.dd_crackiness,
449 dd_crumbliness = tooldef.dd_crumbliness,
450 dd_cuttability = tooldef.dd_cuttability,
454 minetest.register_item(name, tooldef)
457 function minetest.register_alias(name, convert_to)
458 if forbidden_item_names[name] then
459 error("Unable to register alias: Name is forbidden: " .. name)
461 if minetest.registered_items[name] ~= nil then
462 minetest.log("WARNING: Not registering alias, item with same name" ..
463 " is already defined: " .. name .. " -> " .. convert_to)
465 --minetest.log("Registering alias: " .. name .. " -> " .. convert_to)
466 minetest.registered_aliases[name] = convert_to
467 register_alias_raw(name, convert_to)
471 -- Alias the forbidden item names to "" so they can't be
472 -- created via itemstrings (e.g. /give)
474 for name in pairs(forbidden_item_names) do
475 minetest.registered_aliases[name] = ""
476 register_alias_raw(name, "")
481 -- Aliases for minetest.register_alias (how ironic...)
482 --minetest.alias_node = minetest.register_alias
483 --minetest.alias_tool = minetest.register_alias
484 --minetest.alias_craftitem = minetest.register_alias
487 -- Built-in node definitions. Also defined in C.
490 minetest.register_item(":", {
492 wield_image = "wieldhand.png",
493 wield_scale = {x=1,y=1,z=2.5},
494 tool_digging_properties = {
495 full_punch_interval = 2.0,
509 minetest.register_item(":unknown", {
511 description = "Unknown Item",
512 inventory_image = "unknown_item.png",
513 on_place = minetest.item_place,
514 on_drop = minetest.item_drop,
517 minetest.register_node(":air", {
518 description = "Air (you hacker you!)",
519 inventory_image = "unknown_block.png",
520 wield_image = "unknown_block.png",
521 drawtype = "airlike",
523 sunlight_propagates = true,
528 air_equivalent = true,
531 minetest.register_node(":ignore", {
532 description = "Ignore (you hacker you!)",
533 inventory_image = "unknown_block.png",
534 wield_image = "unknown_block.png",
535 drawtype = "airlike",
537 sunlight_propagates = false,
541 buildable_to = true, -- A way to remove accidentally placed ignores
542 air_equivalent = true,
546 -- Default material types
549 function minetest.digprop_constanttime(time)
551 diggability = "constant",
552 constant_time = time,
556 function minetest.digprop_stonelike(toughness)
558 diggablity = "normal",
559 weight = toughness * 5,
566 function minetest.digprop_dirtlike(toughness)
568 diggablity = "normal",
569 weight = toughness * 1.2,
576 function minetest.digprop_gravellike(toughness)
578 diggablity = "normal",
579 weight = toughness * 2,
586 function minetest.digprop_woodlike(toughness)
588 diggablity = "normal",
589 weight = toughness * 1.0,
596 function minetest.digprop_leaveslike(toughness)
598 diggablity = "normal",
599 weight = toughness * (-0.5),
606 function minetest.digprop_glasslike(toughness)
608 diggablity = "normal",
609 weight = toughness * 0.1,
617 -- Creative inventory
620 minetest.creative_inventory = {}
622 minetest.add_to_creative_inventory = function(itemstring)
623 table.insert(minetest.creative_inventory, itemstring)
627 -- Callback registration
630 local function make_registration()
632 local registerfunc = function(func) table.insert(t, func) end
633 return t, registerfunc
636 minetest.registered_on_chat_messages, minetest.register_on_chat_message = make_registration()
637 minetest.registered_globalsteps, minetest.register_globalstep = make_registration()
638 minetest.registered_on_placenodes, minetest.register_on_placenode = make_registration()
639 minetest.registered_on_dignodes, minetest.register_on_dignode = make_registration()
640 minetest.registered_on_punchnodes, minetest.register_on_punchnode = make_registration()
641 minetest.registered_on_generateds, minetest.register_on_generated = make_registration()
642 minetest.registered_on_newplayers, minetest.register_on_newplayer = make_registration()
643 minetest.registered_on_dieplayers, minetest.register_on_dieplayer = make_registration()
644 minetest.registered_on_respawnplayers, minetest.register_on_respawnplayer = make_registration()