1 function basic_dump2(o)
2 if type(o) == "number" then
4 elseif type(o) == "string" then
5 return string.format("%q", o)
6 elseif type(o) == "boolean" then
8 elseif type(o) == "function" then
10 elseif type(o) == "userdata" then
12 elseif type(o) == "nil" then
15 error("cannot dump a " .. type(o))
20 function dump2(o, name, dumped)
24 if type(o) == "number" or type(o) == "string" or type(o) == "boolean"
25 or type(o) == "function" or type(o) == "nil"
26 or type(o) == "userdata" then
27 io.write(basic_dump2(o), "\n")
28 elseif type(o) == "table" then
30 io.write(dumped[o], "\n")
33 io.write("{}\n") -- new table
34 for k,v in pairs(o) do
35 local fieldname = string.format("%s[%s]", name, basic_dump2(k))
36 dump2(v, fieldname, dumped)
40 error("cannot dump a " .. type(o))
45 function dump(o, dumped)
47 if type(o) == "number" then
49 elseif type(o) == "string" then
50 return string.format("%q", o)
51 elseif type(o) == "table" then
53 return "<circular reference>"
57 for k,v in pairs(o) do
58 t[#t+1] = "" .. k .. " = " .. dump(v, dumped)
60 return "{" .. table.concat(t, ", ") .. "}"
61 elseif type(o) == "boolean" then
63 elseif type(o) == "function" then
65 elseif type(o) == "userdata" then
67 elseif type(o) == "nil" then
70 error("cannot dump a " .. type(o))
76 -- Mods should prefix their textures with modname_, eg. given the mod
77 -- name "foomod", a texture could be called "foomod_superfurnace.png"
80 -- minetest.register_entity(name, prototype_table)
81 -- minetest.register_tool(name, {lots of stuff})
82 -- minetest.register_node(name, {lots of stuff})
83 -- minetest.register_craft({output=item, recipe={...})
84 -- minetest.register_globalstep(func)
85 -- minetest.register_on_placenode(func(pos, newnode, placer))
86 -- minetest.register_on_dignode(func(pos, oldnode, digger))
87 -- minetest.register_on_punchnode(func(pos, node, puncher))
90 -- minetest.env - environment reference
93 -- minetest.registered_entities
94 -- ^ List of registered entity prototypes, indexed by name
95 -- minetest.object_refs
96 -- ^ List of object references, indexed by active object id
97 -- minetest.luaentities
98 -- ^ List of lua entities, indexed by active object id
100 -- EnvRef is basically ServerEnvironment and ServerMap combined.
102 -- - add_node(pos, node)
103 -- - remove_node(pos)
105 -- - add_luaentity(pos, name)
107 -- ObjectRef is basically ServerActiveObject.
108 -- ObjectRef methods:
109 -- - remove(): remove object (after returning from Lua)
110 -- - getpos(): returns {x=num, y=num, z=num}
111 -- - setpos(pos); pos={x=num, y=num, z=num}
112 -- - moveto(pos, continuous=false): interpolated move
113 -- - add_to_inventory(itemstring): add an item to object inventory
115 -- Registered entities:
116 -- - Functions receive a "luaentity" as self:
117 -- - It has the member .object, which is an ObjectRef pointing to the object
118 -- - The original prototype stuff is visible directly via a metatable
120 -- - on_activate(self, staticdata)
121 -- - on_step(self, dtime)
122 -- - on_punch(self, hitter)
123 -- - on_rightclick(self, clicker)
124 -- - get_staticdata(self): return string
126 -- MapNode representation:
127 -- {name="name", param1=num, param2=num}
129 -- Position representation:
130 -- {x=num, y=num, z=num}
133 -- print("minetest dump: "..dump(minetest))
139 minetest.register_tool("WPick", {
140 image = "tool_woodpick.png",
143 dt_crackiness = -0.5,
152 minetest.register_tool("STPick", {
153 image = "tool_stonepick.png",
156 dt_crackiness = -0.5,
159 basedurability = 100,
165 minetest.register_tool("SteelPick", {
166 image = "tool_steelpick.png",
169 dt_crackiness = -0.5,
172 basedurability = 333,
178 minetest.register_tool("MesePick", {
179 image = "tool_mesepick.png",
185 basedurability = 1337,
191 minetest.register_tool("WShovel", {
192 image = "tool_woodshovel.png",
196 dt_crumbliness = -1.5,
197 dt_cuttability = 0.3,
204 minetest.register_tool("STShovel", {
205 image = "tool_stoneshovel.png",
209 dt_crumbliness = -1.5,
210 dt_cuttability = 0.1,
211 basedurability = 100,
217 minetest.register_tool("SteelShovel", {
218 image = "tool_steelshovel.png",
222 dt_crumbliness = -1.5,
223 dt_cuttability = 0.0,
224 basedurability = 330,
230 minetest.register_tool("WAxe", {
231 image = "tool_woodaxe.png",
234 dt_crackiness = -0.2,
236 dt_cuttability = -0.5,
243 minetest.register_tool("STAxe", {
244 image = "tool_stoneaxe.png",
247 dt_crackiness = -0.2,
249 dt_cuttability = -0.5,
250 basedurability = 100,
256 minetest.register_tool("SteelAxe", {
257 image = "tool_steelaxe.png",
260 dt_crackiness = -0.2,
262 dt_cuttability = -0.5,
263 basedurability = 330,
269 minetest.register_tool("WSword", {
270 image = "tool_woodsword.png",
282 minetest.register_tool("STSword", {
283 image = "tool_stonesword.png",
289 basedurability = 100,
295 minetest.register_tool("SteelSword", {
296 image = "tool_steelsword.png",
302 basedurability = 330,
308 minetest.register_tool("", {
323 minetest.register_tool("horribletool", {
339 -- Crafting definition
342 minetest.register_craft({
343 output = 'NodeItem "wood" 4',
349 minetest.register_craft({
350 output = 'CraftItem "Stick" 4',
356 minetest.register_craft({
357 output = 'NodeItem "wooden_fence" 2',
359 {'CraftItem "Stick"', 'CraftItem "Stick"', 'CraftItem "Stick"'},
360 {'CraftItem "Stick"', 'CraftItem "Stick"', 'CraftItem "Stick"'},
364 minetest.register_craft({
365 output = 'NodeItem "sign_wall" 1',
367 {'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
368 {'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
369 {'', 'CraftItem "Stick"', ''},
373 minetest.register_craft({
374 output = 'NodeItem "torch" 4',
376 {'CraftItem "lump_of_coal"'},
377 {'CraftItem "Stick"'},
381 minetest.register_craft({
382 output = 'ToolItem "WPick"',
384 {'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
385 {'', 'CraftItem "Stick"', ''},
386 {'', 'CraftItem "Stick"', ''},
390 minetest.register_craft({
391 output = 'ToolItem "STPick"',
393 {'NodeItem "cobble"', 'NodeItem "cobble"', 'NodeItem "cobble"'},
394 {'', 'CraftItem "Stick"', ''},
395 {'', 'CraftItem "Stick"', ''},
399 minetest.register_craft({
400 output = 'ToolItem "SteelPick"',
402 {'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"'},
403 {'', 'CraftItem "Stick"', ''},
404 {'', 'CraftItem "Stick"', ''},
408 minetest.register_craft({
409 output = 'ToolItem "MesePick"',
411 {'NodeItem "mese"', 'NodeItem "mese"', 'NodeItem "mese"'},
412 {'', 'CraftItem "Stick"', ''},
413 {'', 'CraftItem "Stick"', ''},
417 minetest.register_craft({
418 output = 'ToolItem "WShovel"',
421 {'CraftItem "Stick"'},
422 {'CraftItem "Stick"'},
426 minetest.register_craft({
427 output = 'ToolItem "STShovel"',
429 {'NodeItem "cobble"'},
430 {'CraftItem "Stick"'},
431 {'CraftItem "Stick"'},
435 minetest.register_craft({
436 output = 'ToolItem "SteelShovel"',
438 {'CraftItem "steel_ingot"'},
439 {'CraftItem "Stick"'},
440 {'CraftItem "Stick"'},
444 minetest.register_craft({
445 output = 'ToolItem "WAxe"',
447 {'NodeItem "wood"', 'NodeItem "wood"'},
448 {'NodeItem "wood"', 'CraftItem "Stick"'},
449 {'', 'CraftItem "Stick"'},
453 minetest.register_craft({
454 output = 'ToolItem "STAxe"',
456 {'NodeItem "cobble"', 'NodeItem "cobble"'},
457 {'NodeItem "cobble"', 'CraftItem "Stick"'},
458 {'', 'CraftItem "Stick"'},
462 minetest.register_craft({
463 output = 'ToolItem "SteelAxe"',
465 {'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"'},
466 {'CraftItem "steel_ingot"', 'CraftItem "Stick"'},
467 {'', 'CraftItem "Stick"'},
471 minetest.register_craft({
472 output = 'ToolItem "WSword"',
476 {'CraftItem "Stick"'},
480 minetest.register_craft({
481 output = 'ToolItem "STSword"',
483 {'NodeItem "cobble"'},
484 {'NodeItem "cobble"'},
485 {'CraftItem "Stick"'},
489 minetest.register_craft({
490 output = 'ToolItem "SteelSword"',
492 {'CraftItem "steel_ingot"'},
493 {'CraftItem "steel_ingot"'},
494 {'CraftItem "Stick"'},
498 minetest.register_craft({
499 output = 'NodeItem "rail" 15',
501 {'CraftItem "steel_ingot"', '', 'CraftItem "steel_ingot"'},
502 {'CraftItem "steel_ingot"', 'CraftItem "Stick"', 'CraftItem "steel_ingot"'},
503 {'CraftItem "steel_ingot"', '', 'CraftItem "steel_ingot"'},
507 minetest.register_craft({
508 output = 'NodeItem "chest" 1',
510 {'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
511 {'NodeItem "wood"', '', 'NodeItem "wood"'},
512 {'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
516 minetest.register_craft({
517 output = 'NodeItem "locked_chest" 1',
519 {'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
520 {'NodeItem "wood"', 'CraftItem "steel_ingot"', 'NodeItem "wood"'},
521 {'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
525 minetest.register_craft({
526 output = 'NodeItem "furnace" 1',
528 {'NodeItem "cobble"', 'NodeItem "cobble"', 'NodeItem "cobble"'},
529 {'NodeItem "cobble"', '', 'NodeItem "cobble"'},
530 {'NodeItem "cobble"', 'NodeItem "cobble"', 'NodeItem "cobble"'},
534 minetest.register_craft({
535 output = 'NodeItem "steelblock" 1',
537 {'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"'},
538 {'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"'},
539 {'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"'},
543 minetest.register_craft({
544 output = 'NodeItem "sandstone" 1',
546 {'NodeItem "sand"', 'NodeItem "sand"'},
547 {'NodeItem "sand"', 'NodeItem "sand"'},
551 minetest.register_craft({
552 output = 'NodeItem "clay" 1',
554 {'CraftItem "lump_of_clay"', 'CraftItem "lump_of_clay"'},
555 {'CraftItem "lump_of_clay"', 'CraftItem "lump_of_clay"'},
559 minetest.register_craft({
560 output = 'NodeItem "brick" 1',
562 {'CraftItem "clay_brick"', 'CraftItem "clay_brick"'},
563 {'CraftItem "clay_brick"', 'CraftItem "clay_brick"'},
567 minetest.register_craft({
568 output = 'CraftItem "paper" 1',
570 {'NodeItem "papyrus"', 'NodeItem "papyrus"', 'NodeItem "papyrus"'},
574 minetest.register_craft({
575 output = 'CraftItem "book" 1',
577 {'CraftItem "paper"'},
578 {'CraftItem "paper"'},
579 {'CraftItem "paper"'},
583 minetest.register_craft({
584 output = 'NodeItem "bookshelf" 1',
586 {'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
587 {'CraftItem "book"', 'CraftItem "book"', 'CraftItem "book"'},
588 {'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
592 minetest.register_craft({
593 output = 'NodeItem "ladder" 1',
595 {'CraftItem "Stick"', '', 'CraftItem "Stick"'},
596 {'CraftItem "Stick"', 'CraftItem "Stick"', 'CraftItem "Stick"'},
597 {'CraftItem "Stick"', '', 'CraftItem "Stick"'},
601 minetest.register_craft({
602 output = 'CraftItem "apple_iron" 1',
604 {'', 'CraftItem "steel_ingot"', ''},
605 {'CraftItem "steel_ingot"', 'CraftItem "apple"', 'CraftItem "steel_ingot"'},
606 {'', 'CraftItem "steel_ingot"', ''},
610 minetest.register_craft({
611 output = 'NodeItem "TNT" 4',
613 {'NodeItem "wood" 1'},
614 {'CraftItem "lump_of_coal" 1'},
615 {'NodeItem "wood" 1'}
619 minetest.register_craft({
620 output = 'NodeItem "somenode" 4',
622 {'CraftItem "Stick" 1'},
630 function digprop_constanttime(time)
632 diggability = "constant",
633 constant_time = time,
637 function digprop_stonelike(toughness)
639 diggablity = "normal",
640 weight = toughness * 5,
647 function digprop_dirtlike(toughness)
649 diggablity = "normal",
650 weight = toughness * 1.2,
657 function digprop_gravellike(toughness)
659 diggablity = "normal",
660 weight = toughness * 2,
667 function digprop_woodlike(toughness)
669 diggablity = "normal",
670 weight = toughness * 1.0,
677 function digprop_leaveslike(toughness)
679 diggablity = "normal",
680 weight = toughness * (-0.5),
687 function digprop_glasslike(toughness)
689 diggablity = "normal",
690 weight = toughness * 0.1,
697 function inventorycube(img1, img2, img3)
700 return "[inventorycube"
701 .. "{" .. img1:gsub("^", "&")
702 .. "{" .. img2:gsub("^", "&")
703 .. "{" .. img3:gsub("^", "&")
708 minetest.register_node("stone", {
709 tile_images = {"stone.png"},
710 inventory_image = inventorycube("stone.png"),
711 paramtype = "mineral",
712 is_ground_content = true,
713 often_contains_mineral = true, -- Texture atlas hint
714 material = digprop_stonelike(1.0),
717 minetest.register_node("dirt_with_grass", {
718 tile_images = {"grass.png", "mud.png", "mud.png^grass_side.png"},
719 inventory_image = inventorycube("mud.png^grass_side.png"),
720 is_ground_content = true,
721 material = digprop_dirtlike(1.0),
724 minetest.register_node("dirt_with_grass_footsteps", {
725 tile_images = {"grass_footsteps.png", "mud.png", "mud.png^grass_side.png"},
726 inventory_image = "grass_footsteps.png",
727 is_ground_content = true,
728 material = digprop_dirtlike(1.0),
731 minetest.register_node("dirt", {
732 tile_images = {"mud.png"},
733 inventory_image = inventorycube("mud.png"),
734 is_ground_content = true,
735 material = digprop_dirtlike(1.0),
740 minetest.register_node("somenode", {
741 tile_images = {"lava.png", "mese.png", "stone.png", "grass.png", "cobble.png", "tree_top.png"},
742 inventory_image = "treeprop.png",
744 diggability = "normal",
751 metadata_name = "chest",
754 minetest.register_node("TNT", {
755 tile_images = {"tnt_top.png", "tnt_bottom.png", "tnt_side.png", "tnt_side.png", "tnt_side.png", "tnt_side.png"},
756 inventory_image = "tnt_side.png",
757 dug_item = '', -- Get nothing
764 -- Some common functions
767 function nodeupdate_single(p)
768 n = minetest.env:get_node(p)
769 if n.name == "sand" or n.name == "gravel" then
770 p_bottom = {x=p.x, y=p.y-1, z=p.z}
771 n_bottom = minetest.env:get_node(p_bottom)
772 if n_bottom.name == "air" then
773 minetest.env:remove_node(p)
774 minetest.env:add_luaentity(p, "falling_"..n.name)
780 function nodeupdate(p)
784 p2 = {x=p.x+x, y=p.y+y, z=p.z+z}
785 nodeupdate_single(p2)
792 -- TNT (not functional)
797 physical = true, -- Collides with things
799 collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
801 textures = {"tnt_top.png","tnt_bottom.png","tnt_side.png","tnt_side.png","tnt_side.png","tnt_side.png"},
802 --visual = "single_sprite",
803 --textures = {"mese.png^[forcesingle"},
804 -- Initial value for our timer
806 -- Number of punches required to defuse
810 -- Called when a TNT object is created
811 function TNT:on_activate(staticdata)
812 print("TNT:on_activate()")
813 self.object:setvelocity({x=0, y=2, z=0})
814 self.object:setacceleration({x=0, y=-10, z=0})
817 -- Called periodically
818 function TNT:on_step(dtime)
819 --print("TNT:on_step()")
822 -- Called when object is punched
823 function TNT:on_punch(hitter)
824 print("TNT:on_punch()")
825 self.health = self.health - 1
826 if self.health <= 0 then
828 hitter:add_to_inventory("NodeItem TNT 1")
832 -- Called when object is right-clicked
833 function TNT:on_rightclick(clicker)
834 --pos = self.object:getpos()
835 --pos = {x=pos.x, y=pos.y+0.1, z=pos.z}
836 --self.object:moveto(pos, false)
839 print("TNT dump: "..dump(TNT))
841 print("Registering TNT");
842 minetest.register_entity("TNT", TNT)
848 function register_falling_node(nodename, texture)
849 minetest.register_entity("falling_"..nodename, {
852 collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
854 textures = {texture,texture,texture,texture,texture,texture},
857 on_step = function(self, dtime)
859 self.object:setacceleration({x=0, y=-10, z=0})
860 -- Turn to actual sand when collides to ground or just move
861 local pos = self.object:getpos()
862 local bcp = {x=pos.x, y=pos.y-0.7, z=pos.z} -- Position of bottom center point
863 local bcn = minetest.env:get_node(bcp)
864 if bcn.name ~= "air" then
865 -- Turn to a sand node
866 local np = {x=bcp.x, y=bcp.y+1, z=bcp.z}
867 minetest.env:add_node(np, {name=nodename})
876 register_falling_node("sand", "sand.png")
877 register_falling_node("gravel", "gravel.png")
880 minetest.register_entity("falling_sand", {
882 collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
884 textures = {"sand.png","sand.png","sand.png","sand.png","sand.png","sand.png"},
888 on_step = function(self, dtime)
890 self.fallspeed = self.fallspeed + dtime * 5
891 fp = self.object:getpos()
892 fp.y = fp.y - self.fallspeed * dtime
893 self.object:moveto(fp)
894 -- Turn to actual sand when collides to ground or just move
895 bcp = {x=fp.x, y=fp.y-0.5, z=fp.z} -- Position of bottom center point
896 bcn = minetest.env:get_node(bcp)
897 if bcn.name ~= "air" then
898 -- Turn to a sand node
899 np = {x=bcp.x, y=bcp.y+1, z=bcp.z}
900 minetest.env:add_node(np, {name="sand"})
913 -- Global environment step function
914 function on_step(dtime)
917 minetest.register_globalstep(on_step)
919 function on_placenode(p, node)
920 print("on_placenode")
923 minetest.register_on_placenode(on_placenode)
925 function on_dignode(p, node)
929 minetest.register_on_dignode(on_dignode)
931 function on_punchnode(p, node)
932 print("on_punchnode")
933 if node.name == "TNT" then
934 minetest.env:remove_node(p)
935 minetest.env:add_luaentity(p, "TNT")
939 minetest.register_on_punchnode(on_punchnode)
942 -- Done, print some random stuff
945 print("minetest.registered_entities:")
946 dump2(minetest.registered_entities)
949 -- Some random pre-implementation planning and drafting
953 function TNT:on_rightclick(clicker)
954 print("TNT:on_rightclick()")
955 print("self: "..dump(self))
956 print("getmetatable(self): "..dump(getmetatable(self)))
957 print("getmetatable(getmetatable(self)): "..dump(getmetatable(getmetatable(self))))
958 pos = self.object:getpos()
959 print("TNT:on_rightclick(): object position: "..dump(pos))
960 pos = {x=pos.x+0.5+1, y=pos.y+0.5, z=pos.z+0.5}
961 --minetest.env:add_node(pos, {name="stone")
968 textures = "stone.png",
970 get_dig_duration = function(env, pos, digger)
971 -- Check stuff like digger.current_tool
974 on_dig = function(env, pos, digger)
976 digger.inventory.put("MaterialItem2 0");
981 textures = {"grass.png","mud.png","mud_grass_side.png","mud_grass_side.png","mud_grass_side.png","mud_grass_side.png"},
983 get_dig_duration = function(env, pos, digger)
984 -- Check stuff like digger.current_tool
987 on_dig = function(env, pos, digger)
989 digger.inventory.put("MaterialItem2 1");
993 -- Consider the "miscellaneous block namespace" to be 0xc00...0xfff = 3072...4095
994 register_block(3072, {
995 textures = {"tnt_top.png","tnt_bottom.png","tnt_side.png","tnt_side.png","tnt_side.png","tnt_side.png"},
997 get_dig_duration = function(env, pos, digger)
1001 -- on_dig = function(env, pos, digger) end, -- Not implemented
1002 on_hit = function(env, pos, hitter)
1003 -- Replace with TNT object, which will explode after timer, follow gravity, blink and stuff
1004 env:add_object("tnt", pos)
1005 env:remove_node(pos)