a8e3b7ba781be784eb84f2048636f397c25f5b43
[oweals/minetest.git] / data / mods / default / init.lua
1 -- Helper functions defined by builtin.lua:
2 -- dump2(obj, name="_", dumped={})
3 -- dump(obj, dumped={})
4 --
5 -- Textures:
6 -- Mods should prefix their textures with modname_, eg. given the mod
7 -- name "foomod", a texture could be called "foomod_superfurnace.png"
8 --
9 -- Global functions:
10 -- minetest.register_entity(name, prototype_table)
11 -- minetest.register_tool(name, {lots of stuff})
12 -- minetest.register_node(name, {lots of stuff})
13 -- minetest.register_craftitem(name, {lots of stuff})
14 -- minetest.register_craft({output=item, recipe={...})
15 -- minetest.register_globalstep(func)
16 -- minetest.register_on_placenode(func(pos, newnode, placer))
17 -- minetest.register_on_dignode(func(pos, oldnode, digger))
18 -- minetest.register_on_punchnode(func(pos, node, puncher))
19 -- minetest.register_on_generated(func(minp, maxp))
20 -- minetest.register_on_newplayer(func(ObjectRef))
21 -- minetest.register_on_respawnplayer(func(ObjectRef))
22 -- ^ return true in func to disable regular player placement
23 -- minetest.register_on_chat_message(func(name, message))
24 -- minetest.setting_get(name)
25 -- minetest.setting_getbool(name)
26 -- minetest.chat_send_all(text)
27 -- minetest.chat_send_player(name, text)
28 --
29 -- Global objects:
30 -- minetest.env - environment reference
31 --
32 -- Global tables:
33 -- minetest.registered_nodes
34 -- ^ List of registered node definitions, indexed by name
35 -- minetest.registered_craftitems
36 -- ^ List of registered craft item definitions, indexed by name
37 -- minetest.registered_entities
38 -- ^ List of registered entity prototypes, indexed by name
39 -- minetest.object_refs
40 -- ^ List of object references, indexed by active object id
41 -- minetest.luaentities
42 -- ^ List of lua entities, indexed by active object id
43 --
44 -- EnvRef is basically ServerEnvironment and ServerMap combined.
45 -- EnvRef methods:
46 -- - add_node(pos, node)
47 -- - remove_node(pos)
48 -- - get_node(pos)
49 -- - add_luaentity(pos, name)
50 -- - add_item(pos, itemstring)
51 -- - add_rat(pos)
52 -- - add_firefly(pos)
53 -- - get_meta(pos) -- Get a NodeMetaRef at that position
54 --
55 -- NodeMetaRef
56 -- - get_type()
57 -- - allows_text_input()
58 -- - set_text(text) -- eg. set the text of a sign
59 -- - get_text()
60 -- - get_owner()
61 -- - set_infotext(infotext)
62 -- - inventory_set_list(name, {item1, item2, ...})
63 -- - inventory_get_list(name)
64 -- - set_inventory_draw_spec(string)
65 -- - set_allow_text_input(bool)
66 -- - set_allow_removal(bool)
67 -- - set_enforce_owner(bool)
68 -- - is_inventory_modified()
69 -- - reset_inventory_modified()
70 -- - is_text_modified()
71 -- - reset_text_modified()
72 -- - set_string(name, value)
73 -- - get_string(name)
74 --
75 -- ObjectRef is basically ServerActiveObject.
76 -- ObjectRef methods:
77 -- - remove(): remove object (after returning from Lua)
78 -- - getpos(): returns {x=num, y=num, z=num}
79 -- - setpos(pos); pos={x=num, y=num, z=num}
80 -- - moveto(pos, continuous=false): interpolated move
81 -- - add_to_inventory(itemstring): add an item to object inventory
82 -- - add_to_inventory_later(itemstring): like above, but after callback returns (only allowed for craftitem callbacks)
83 -- - get_hp(): returns number of hitpoints (2 * number of hearts)
84 -- - set_hp(hp): set number of hitpoints (2 * number of hearts)
85 -- - settexturemod(mod)
86 -- - setsprite(p={x=0,y=0}, num_frames=1, framelength=0.2,
87 -- -           select_horiz_by_yawpitch=false)
88 --
89 -- Registered entities:
90 -- - Functions receive a "luaentity" as self:
91 --   - It has the member .object, which is an ObjectRef pointing to the object
92 --   - The original prototype stuff is visible directly via a metatable
93 -- - Callbacks:
94 --   - on_activate(self, staticdata)
95 --   - on_step(self, dtime)
96 --   - on_punch(self, hitter)
97 --   - on_rightclick(self, clicker)
98 --   - get_staticdata(self): return string
99 --
100 -- MapNode representation:
101 -- {name="name", param1=num, param2=num}
102 --
103 -- Position representation:
104 -- {x=num, y=num, z=num}
105 --
106
107 -- print("minetest dump: "..dump(minetest))
108
109 WATER_ALPHA = 160
110 WATER_VISC = 1
111 LAVA_VISC = 7
112 LIGHT_MAX = 14
113
114 --
115 -- Tool definition
116 --
117
118 minetest.register_tool("WPick", {
119         image = "tool_woodpick.png",
120         basetime = 2.0,
121         dt_weight = 0,
122         dt_crackiness = -0.5,
123         dt_crumbliness = 2,
124         dt_cuttability = 0,
125         basedurability = 30,
126         dd_weight = 0,
127         dd_crackiness = 0,
128         dd_crumbliness = 0,
129         dd_cuttability = 0,
130 })
131 minetest.register_tool("STPick", {
132         image = "tool_stonepick.png",
133         basetime = 1.5,
134         dt_weight = 0,
135         dt_crackiness = -0.5,
136         dt_crumbliness = 2,
137         dt_cuttability = 0,
138         basedurability = 100,
139         dd_weight = 0,
140         dd_crackiness = 0,
141         dd_crumbliness = 0,
142         dd_cuttability = 0,
143 })
144 minetest.register_tool("SteelPick", {
145         image = "tool_steelpick.png",
146         basetime = 1.0,
147         dt_weight = 0,
148         dt_crackiness = -0.5,
149         dt_crumbliness = 2,
150         dt_cuttability = 0,
151         basedurability = 333,
152         dd_weight = 0,
153         dd_crackiness = 0,
154         dd_crumbliness = 0,
155         dd_cuttability = 0,
156 })
157 minetest.register_tool("MesePick", {
158         image = "tool_mesepick.png",
159         basetime = 0,
160         dt_weight = 0,
161         dt_crackiness = 0,
162         dt_crumbliness = 0,
163         dt_cuttability = 0,
164         basedurability = 1337,
165         dd_weight = 0,
166         dd_crackiness = 0,
167         dd_crumbliness = 0,
168         dd_cuttability = 0,
169 })
170 minetest.register_tool("WShovel", {
171         image = "tool_woodshovel.png",
172         basetime = 2.0,
173         dt_weight = 0.5,
174         dt_crackiness = 2,
175         dt_crumbliness = -1.5,
176         dt_cuttability = 0.3,
177         basedurability = 30,
178         dd_weight = 0,
179         dd_crackiness = 0,
180         dd_crumbliness = 0,
181         dd_cuttability = 0,
182 })
183 minetest.register_tool("STShovel", {
184         image = "tool_stoneshovel.png",
185         basetime = 1.5,
186         dt_weight = 0.5,
187         dt_crackiness = 2,
188         dt_crumbliness = -1.5,
189         dt_cuttability = 0.1,
190         basedurability = 100,
191         dd_weight = 0,
192         dd_crackiness = 0,
193         dd_crumbliness = 0,
194         dd_cuttability = 0,
195 })
196 minetest.register_tool("SteelShovel", {
197         image = "tool_steelshovel.png",
198         basetime = 1.0,
199         dt_weight = 0.5,
200         dt_crackiness = 2,
201         dt_crumbliness = -1.5,
202         dt_cuttability = 0.0,
203         basedurability = 330,
204         dd_weight = 0,
205         dd_crackiness = 0,
206         dd_crumbliness = 0,
207         dd_cuttability = 0,
208 })
209 minetest.register_tool("WAxe", {
210         image = "tool_woodaxe.png",
211         basetime = 2.0,
212         dt_weight = 0.5,
213         dt_crackiness = -0.2,
214         dt_crumbliness = 1,
215         dt_cuttability = -0.5,
216         basedurability = 30,
217         dd_weight = 0,
218         dd_crackiness = 0,
219         dd_crumbliness = 0,
220         dd_cuttability = 0,
221 })
222 minetest.register_tool("STAxe", {
223         image = "tool_stoneaxe.png",
224         basetime = 1.5,
225         dt_weight = 0.5,
226         dt_crackiness = -0.2,
227         dt_crumbliness = 1,
228         dt_cuttability = -0.5,
229         basedurability = 100,
230         dd_weight = 0,
231         dd_crackiness = 0,
232         dd_crumbliness = 0,
233         dd_cuttability = 0,
234 })
235 minetest.register_tool("SteelAxe", {
236         image = "tool_steelaxe.png",
237         basetime = 1.0,
238         dt_weight = 0.5,
239         dt_crackiness = -0.2,
240         dt_crumbliness = 1,
241         dt_cuttability = -0.5,
242         basedurability = 330,
243         dd_weight = 0,
244         dd_crackiness = 0,
245         dd_crumbliness = 0,
246         dd_cuttability = 0,
247 })
248 minetest.register_tool("WSword", {
249         image = "tool_woodsword.png",
250         basetime = 3.0,
251         dt_weight = 3,
252         dt_crackiness = 0,
253         dt_crumbliness = 1,
254         dt_cuttability = -1,
255         basedurability = 30,
256         dd_weight = 0,
257         dd_crackiness = 0,
258         dd_crumbliness = 0,
259         dd_cuttability = 0,
260 })
261 minetest.register_tool("STSword", {
262         image = "tool_stonesword.png",
263         basetime = 2.5,
264         dt_weight = 3,
265         dt_crackiness = 0,
266         dt_crumbliness = 1,
267         dt_cuttability = -1,
268         basedurability = 100,
269         dd_weight = 0,
270         dd_crackiness = 0,
271         dd_crumbliness = 0,
272         dd_cuttability = 0,
273 })
274 minetest.register_tool("SteelSword", {
275         image = "tool_steelsword.png",
276         basetime = 2.0,
277         dt_weight = 3,
278         dt_crackiness = 0,
279         dt_crumbliness = 1,
280         dt_cuttability = -1,
281         basedurability = 330,
282         dd_weight = 0,
283         dd_crackiness = 0,
284         dd_crumbliness = 0,
285         dd_cuttability = 0,
286 })
287 minetest.register_tool("", {
288         image = "",
289         basetime = 0.5,
290         dt_weight = 1,
291         dt_crackiness = 0,
292         dt_crumbliness = -1,
293         dt_cuttability = 0,
294         basedurability = 50,
295         dd_weight = 0,
296         dd_crackiness = 0,
297         dd_crumbliness = 0,
298         dd_cuttability = 0,
299 })
300
301 --[[
302 minetest.register_tool("horribletool", {
303         image = "lava.png",
304         basetime = 2.0
305         dt_weight = 0.2
306         dt_crackiness = 0.2
307         dt_crumbliness = 0.2
308         dt_cuttability = 0.2
309         basedurability = 50
310         dd_weight = -5
311         dd_crackiness = -5
312         dd_crumbliness = -5
313         dd_cuttability = -5
314 })
315 --]]
316
317 --
318 -- Crafting definition
319 --
320
321 minetest.register_craft({
322         output = 'NodeItem "wood" 4',
323         recipe = {
324                 {'NodeItem "tree"'},
325         }
326 })
327
328 minetest.register_craft({
329         output = 'CraftItem "Stick" 4',
330         recipe = {
331                 {'NodeItem "wood"'},
332         }
333 })
334
335 minetest.register_craft({
336         output = 'NodeItem "wooden_fence" 2',
337         recipe = {
338                 {'CraftItem "Stick"', 'CraftItem "Stick"', 'CraftItem "Stick"'},
339                 {'CraftItem "Stick"', 'CraftItem "Stick"', 'CraftItem "Stick"'},
340         }
341 })
342
343 minetest.register_craft({
344         output = 'NodeItem "sign_wall" 1',
345         recipe = {
346                 {'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
347                 {'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
348                 {'', 'CraftItem "Stick"', ''},
349         }
350 })
351
352 minetest.register_craft({
353         output = 'NodeItem "torch" 4',
354         recipe = {
355                 {'CraftItem "lump_of_coal"'},
356                 {'CraftItem "Stick"'},
357         }
358 })
359
360 minetest.register_craft({
361         output = 'ToolItem "WPick"',
362         recipe = {
363                 {'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
364                 {'', 'CraftItem "Stick"', ''},
365                 {'', 'CraftItem "Stick"', ''},
366         }
367 })
368
369 minetest.register_craft({
370         output = 'ToolItem "STPick"',
371         recipe = {
372                 {'NodeItem "cobble"', 'NodeItem "cobble"', 'NodeItem "cobble"'},
373                 {'', 'CraftItem "Stick"', ''},
374                 {'', 'CraftItem "Stick"', ''},
375         }
376 })
377
378 minetest.register_craft({
379         output = 'ToolItem "SteelPick"',
380         recipe = {
381                 {'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"'},
382                 {'', 'CraftItem "Stick"', ''},
383                 {'', 'CraftItem "Stick"', ''},
384         }
385 })
386
387 minetest.register_craft({
388         output = 'ToolItem "MesePick"',
389         recipe = {
390                 {'NodeItem "mese"', 'NodeItem "mese"', 'NodeItem "mese"'},
391                 {'', 'CraftItem "Stick"', ''},
392                 {'', 'CraftItem "Stick"', ''},
393         }
394 })
395
396 minetest.register_craft({
397         output = 'ToolItem "WShovel"',
398         recipe = {
399                 {'NodeItem "wood"'},
400                 {'CraftItem "Stick"'},
401                 {'CraftItem "Stick"'},
402         }
403 })
404
405 minetest.register_craft({
406         output = 'ToolItem "STShovel"',
407         recipe = {
408                 {'NodeItem "cobble"'},
409                 {'CraftItem "Stick"'},
410                 {'CraftItem "Stick"'},
411         }
412 })
413
414 minetest.register_craft({
415         output = 'ToolItem "SteelShovel"',
416         recipe = {
417                 {'CraftItem "steel_ingot"'},
418                 {'CraftItem "Stick"'},
419                 {'CraftItem "Stick"'},
420         }
421 })
422
423 minetest.register_craft({
424         output = 'ToolItem "WAxe"',
425         recipe = {
426                 {'NodeItem "wood"', 'NodeItem "wood"'},
427                 {'NodeItem "wood"', 'CraftItem "Stick"'},
428                 {'', 'CraftItem "Stick"'},
429         }
430 })
431
432 minetest.register_craft({
433         output = 'ToolItem "STAxe"',
434         recipe = {
435                 {'NodeItem "cobble"', 'NodeItem "cobble"'},
436                 {'NodeItem "cobble"', 'CraftItem "Stick"'},
437                 {'', 'CraftItem "Stick"'},
438         }
439 })
440
441 minetest.register_craft({
442         output = 'ToolItem "SteelAxe"',
443         recipe = {
444                 {'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"'},
445                 {'CraftItem "steel_ingot"', 'CraftItem "Stick"'},
446                 {'', 'CraftItem "Stick"'},
447         }
448 })
449
450 minetest.register_craft({
451         output = 'ToolItem "WSword"',
452         recipe = {
453                 {'NodeItem "wood"'},
454                 {'NodeItem "wood"'},
455                 {'CraftItem "Stick"'},
456         }
457 })
458
459 minetest.register_craft({
460         output = 'ToolItem "STSword"',
461         recipe = {
462                 {'NodeItem "cobble"'},
463                 {'NodeItem "cobble"'},
464                 {'CraftItem "Stick"'},
465         }
466 })
467
468 minetest.register_craft({
469         output = 'ToolItem "SteelSword"',
470         recipe = {
471                 {'CraftItem "steel_ingot"'},
472                 {'CraftItem "steel_ingot"'},
473                 {'CraftItem "Stick"'},
474         }
475 })
476
477 minetest.register_craft({
478         output = 'NodeItem "rail" 15',
479         recipe = {
480                 {'CraftItem "steel_ingot"', '', 'CraftItem "steel_ingot"'},
481                 {'CraftItem "steel_ingot"', 'CraftItem "Stick"', 'CraftItem "steel_ingot"'},
482                 {'CraftItem "steel_ingot"', '', 'CraftItem "steel_ingot"'},
483         }
484 })
485
486 minetest.register_craft({
487         output = 'NodeItem "chest" 1',
488         recipe = {
489                 {'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
490                 {'NodeItem "wood"', '', 'NodeItem "wood"'},
491                 {'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
492         }
493 })
494
495 minetest.register_craft({
496         output = 'NodeItem "locked_chest" 1',
497         recipe = {
498                 {'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
499                 {'NodeItem "wood"', 'CraftItem "steel_ingot"', 'NodeItem "wood"'},
500                 {'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
501         }
502 })
503
504 minetest.register_craft({
505         output = 'NodeItem "furnace" 1',
506         recipe = {
507                 {'NodeItem "cobble"', 'NodeItem "cobble"', 'NodeItem "cobble"'},
508                 {'NodeItem "cobble"', '', 'NodeItem "cobble"'},
509                 {'NodeItem "cobble"', 'NodeItem "cobble"', 'NodeItem "cobble"'},
510         }
511 })
512
513 minetest.register_craft({
514         output = 'NodeItem "steelblock" 1',
515         recipe = {
516                 {'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"'},
517                 {'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"'},
518                 {'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"', 'CraftItem "steel_ingot"'},
519         }
520 })
521
522 minetest.register_craft({
523         output = 'NodeItem "sandstone" 1',
524         recipe = {
525                 {'NodeItem "sand"', 'NodeItem "sand"'},
526                 {'NodeItem "sand"', 'NodeItem "sand"'},
527         }
528 })
529
530 minetest.register_craft({
531         output = 'NodeItem "clay" 1',
532         recipe = {
533                 {'CraftItem "lump_of_clay"', 'CraftItem "lump_of_clay"'},
534                 {'CraftItem "lump_of_clay"', 'CraftItem "lump_of_clay"'},
535         }
536 })
537
538 minetest.register_craft({
539         output = 'NodeItem "brick" 1',
540         recipe = {
541                 {'CraftItem "clay_brick"', 'CraftItem "clay_brick"'},
542                 {'CraftItem "clay_brick"', 'CraftItem "clay_brick"'},
543         }
544 })
545
546 minetest.register_craft({
547         output = 'CraftItem "paper" 1',
548         recipe = {
549                 {'NodeItem "papyrus"', 'NodeItem "papyrus"', 'NodeItem "papyrus"'},
550         }
551 })
552
553 minetest.register_craft({
554         output = 'CraftItem "book" 1',
555         recipe = {
556                 {'CraftItem "paper"'},
557                 {'CraftItem "paper"'},
558                 {'CraftItem "paper"'},
559         }
560 })
561
562 minetest.register_craft({
563         output = 'NodeItem "bookshelf" 1',
564         recipe = {
565                 {'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
566                 {'CraftItem "book"', 'CraftItem "book"', 'CraftItem "book"'},
567                 {'NodeItem "wood"', 'NodeItem "wood"', 'NodeItem "wood"'},
568         }
569 })
570
571 minetest.register_craft({
572         output = 'NodeItem "ladder" 1',
573         recipe = {
574                 {'CraftItem "Stick"', '', 'CraftItem "Stick"'},
575                 {'CraftItem "Stick"', 'CraftItem "Stick"', 'CraftItem "Stick"'},
576                 {'CraftItem "Stick"', '', 'CraftItem "Stick"'},
577         }
578 })
579
580 minetest.register_craft({
581         output = 'CraftItem "apple_iron" 1',
582         recipe = {
583                 {'', 'CraftItem "steel_ingot"', ''},
584                 {'CraftItem "steel_ingot"', 'CraftItem "apple"', 'CraftItem "steel_ingot"'},
585                 {'', 'CraftItem "steel_ingot"', ''},
586         }
587 })
588
589 minetest.register_craft({
590         output = 'NodeItem "TNT" 4',
591         recipe = {
592                 {'NodeItem "wood" 1'},
593                 {'CraftItem "lump_of_coal" 1'},
594                 {'NodeItem "wood" 1'}
595         }
596 })
597
598 minetest.register_craft({
599         output = 'NodeItem "somenode" 4',
600         recipe = {
601                 {'CraftItem "Stick" 1'},
602         }
603 })
604
605 --
606 -- Node definitions
607 --
608
609 function digprop_constanttime(time)
610         return {
611                 diggability = "constant",
612                 constant_time = time,
613         }
614 end
615
616 function digprop_stonelike(toughness)
617         return {
618                 diggablity = "normal",
619                 weight = toughness * 5,
620                 crackiness = 1,
621                 crumbliness = -0.1,
622                 cuttability = -0.2,
623         }
624 end
625
626 function digprop_dirtlike(toughness)
627         return {
628                 diggablity = "normal",
629                 weight = toughness * 1.2,
630                 crackiness = 0,
631                 crumbliness = 1.2,
632                 cuttability = -0.4,
633         }
634 end
635
636 function digprop_gravellike(toughness)
637         return {
638                 diggablity = "normal",
639                 weight = toughness * 2,
640                 crackiness = 0.2,
641                 crumbliness = 1.5,
642                 cuttability = -1.0,
643         }
644 end
645
646 function digprop_woodlike(toughness)
647         return {
648                 diggablity = "normal",
649                 weight = toughness * 1.0,
650                 crackiness = 0.75,
651                 crumbliness = -1.0,
652                 cuttability = 1.5,
653         }
654 end
655
656 function digprop_leaveslike(toughness)
657         return {
658                 diggablity = "normal",
659                 weight = toughness * (-0.5),
660                 crackiness = 0,
661                 crumbliness = 0,
662                 cuttability = 2.0,
663         }
664 end
665
666 function digprop_glasslike(toughness)
667         return {
668                 diggablity = "normal",
669                 weight = toughness * 0.1,
670                 crackiness = 2.0,
671                 crumbliness = -1.0,
672                 cuttability = -1.0,
673         }
674 end
675
676 function inventorycube(img1, img2, img3)
677         img2 = img2 or img1
678         img3 = img3 or img1
679         return "[inventorycube"
680                         .. "{" .. img1:gsub("%^", "&")
681                         .. "{" .. img2:gsub("%^", "&")
682                         .. "{" .. img3:gsub("%^", "&")
683 end
684
685 -- Legacy nodes
686
687 minetest.register_node("stone", {
688         tile_images = {"stone.png"},
689         inventory_image = inventorycube("stone.png"),
690         paramtype = "mineral",
691         is_ground_content = true,
692         often_contains_mineral = true, -- Texture atlas hint
693         material = digprop_stonelike(1.0),
694         dug_item = 'NodeItem "cobble" 1',
695 })
696
697 minetest.register_node("dirt_with_grass", {
698         tile_images = {"grass.png", "mud.png", "mud.png^grass_side.png"},
699         inventory_image = inventorycube("mud.png^grass_side.png"),
700         is_ground_content = true,
701         material = digprop_dirtlike(1.0),
702         dug_item = 'NodeItem "dirt" 1',
703 })
704
705 minetest.register_node("dirt_with_grass_footsteps", {
706         tile_images = {"grass_footsteps.png", "mud.png", "mud.png^grass_side.png"},
707         inventory_image = "grass_footsteps.png",
708         is_ground_content = true,
709         material = digprop_dirtlike(1.0),
710         dug_item = 'NodeItem "dirt" 1',
711 })
712
713 minetest.register_node("dirt", {
714         tile_images = {"mud.png"},
715         inventory_image = inventorycube("mud.png"),
716         is_ground_content = true,
717         material = digprop_dirtlike(1.0),
718 })
719
720 minetest.register_node("sand", {
721         tile_images = {"sand.png"},
722         inventory_image = inventorycube("sand.png"),
723         is_ground_content = true,
724         material = digprop_dirtlike(1.0),
725 })
726
727 minetest.register_node("gravel", {
728         tile_images = {"gravel.png"},
729         inventory_image = inventorycube("gravel.png"),
730         is_ground_content = true,
731         material = digprop_gravellike(1.0),
732 })
733
734 minetest.register_node("sandstone", {
735         tile_images = {"sandstone.png"},
736         inventory_image = inventorycube("sandstone.png"),
737         is_ground_content = true,
738         material = digprop_dirtlike(1.0),  -- FIXME should this be stonelike?
739         dug_item = 'NodeItem "sand" 1',  -- FIXME is this intentional?
740 })
741
742 minetest.register_node("clay", {
743         tile_images = {"clay.png"},
744         inventory_image = inventorycube("clay.png"),
745         is_ground_content = true,
746         material = digprop_dirtlike(1.0),
747         dug_item = 'CraftItem "lump_of_clay" 4',
748 })
749
750 minetest.register_node("brick", {
751         tile_images = {"brick.png"},
752         inventory_image = inventorycube("brick.png"),
753         is_ground_content = true,
754         material = digprop_stonelike(1.0),
755         dug_item = 'CraftItem "clay_brick" 4',
756 })
757
758 minetest.register_node("tree", {
759         tile_images = {"tree_top.png", "tree_top.png", "tree.png"},
760         inventory_image = inventorycube("tree_top.png", "tree.png", "tree.png"),
761         is_ground_content = true,
762         material = digprop_woodlike(1.0),
763         cookresult_item = 'CraftItem "lump_of_coal" 1',
764         furnace_burntime = 30,
765 })
766
767 minetest.register_node("jungletree", {
768         tile_images = {"jungletree_top.png", "jungletree_top.png", "jungletree.png"},
769         inventory_image = inventorycube("jungletree_top.png", "jungletree.png", "jungletree.png"),
770         is_ground_content = true,
771         material = digprop_woodlike(1.0),
772         cookresult_item = 'CraftItem "lump_of_coal" 1',
773         furnace_burntime = 30,
774 })
775
776 minetest.register_node("junglegrass", {
777         drawtype = "plantlike",
778         visual_scale = 1.3,
779         tile_images = {"junglegrass.png"},
780         inventory_image = "junglegrass.png",
781         light_propagates = true,
782         paramtype = "light",
783         walkable = false,
784         material = digprop_leaveslike(1.0),
785         furnace_burntime = 2,
786 })
787
788 minetest.register_node("leaves", {
789         drawtype = "allfaces_optional",
790         visual_scale = 1.3,
791         tile_images = {"leaves.png"},
792         inventory_image = "leaves.png",
793         light_propagates = true,
794         paramtype = "light",
795         material = digprop_leaveslike(1.0),
796         extra_dug_item = 'NodeItem "sapling" 1',
797         extra_dug_item_rarity = 20,
798         furnace_burntime = 1,
799 })
800
801 minetest.register_node("cactus", {
802         tile_images = {"cactus_top.png", "cactus_top.png", "cactus_side.png"},
803         inventory_image = inventorycube("cactus_top.png", "cactus_side.png", "cactus_side.png"),
804         is_ground_content = true,
805         material = digprop_woodlike(0.75),
806         furnace_burntime = 15,
807 })
808
809 minetest.register_node("papyrus", {
810         drawtype = "plantlike",
811         tile_images = {"papyrus.png"},
812         inventory_image = "papyrus.png",
813         light_propagates = true,
814         paramtype = "light",
815         is_ground_content = true,
816         walkable = false,
817         material = digprop_leaveslike(0.5),
818         furnace_burntime = 1,
819 })
820
821 minetest.register_node("bookshelf", {
822         tile_images = {"wood.png", "wood.png", "bookshelf.png"},
823         -- FIXME: inventorycube only cares for the first texture
824         --inventory_image = inventorycube("wood.png", "bookshelf.png", "bookshelf.png")
825         inventory_image = inventorycube("bookshelf.png"),
826         is_ground_content = true,
827         material = digprop_woodlike(0.75),
828         furnace_burntime = 30,
829 })
830
831 minetest.register_node("glass", {
832         drawtype = "glasslike",
833         tile_images = {"glass.png"},
834         inventory_image = inventorycube("glass.png"),
835         light_propagates = true,
836         paramtype = "light",
837         sunlight_propagates = true,
838         is_ground_content = true,
839         material = digprop_glasslike(1.0),
840 })
841
842 minetest.register_node("wooden_fence", {
843         drawtype = "fencelike",
844         tile_images = {"wood.png"},
845         inventory_image = "fence.png",
846         light_propagates = true,
847         paramtype = "light",
848         is_ground_content = true,
849         selection_box = {
850                 type = "fixed",
851                 fixed = {-1/7, -1/2, -1/7, 1/7, 1/2, 1/7},
852         },
853         furnace_burntime = 15,
854         material = digprop_woodlike(0.75),
855 })
856
857 minetest.register_node("rail", {
858         drawtype = "raillike",
859         tile_images = {"rail.png", "rail_curved.png", "rail_t_junction.png", "rail_crossing.png"},
860         inventory_image = "rail.png",
861         light_propagates = true,
862         paramtype = "light",
863         is_ground_content = true,
864         walkable = false,
865         selection_box = {
866                 type = "fixed",
867                 --fixed = <default>
868         },
869         material = digprop_dirtlike(0.75),
870 })
871
872 minetest.register_node("ladder", {
873         drawtype = "signlike",
874         tile_images = {"ladder.png"},
875         inventory_image = "ladder.png",
876         light_propagates = true,
877         paramtype = "light",
878         is_ground_content = true,
879         wall_mounted = true,
880         walkable = false,
881         climbable = true,
882         selection_box = {
883                 type = "wallmounted",
884                 --wall_top = = <default>
885                 --wall_bottom = = <default>
886                 --wall_side = = <default>
887         },
888         furnace_burntime = 5,
889         material = digprop_woodlike(0.5),
890 })
891
892 minetest.register_node("coalstone", {
893         tile_images = {"stone.png^mineral_coal.png"},
894         inventory_image = "stone.png^mineral_coal.png",
895         is_ground_content = true,
896         material = digprop_stonelike(1.5),
897 })
898
899 minetest.register_node("wood", {
900         tile_images = {"wood.png"},
901         inventory_image = inventorycube("wood.png"),
902         is_ground_content = true,
903         furnace_burntime = 7,
904         material = digprop_woodlike(0.75),
905 })
906
907 minetest.register_node("mese", {
908         tile_images = {"mese.png"},
909         inventory_image = inventorycube("mese.png"),
910         is_ground_content = true,
911         furnace_burntime = 30,
912         material = digprop_stonelike(0.5),
913 })
914
915 minetest.register_node("cloud", {
916         tile_images = {"cloud.png"},
917         inventory_image = inventorycube("cloud.png"),
918         is_ground_content = true,
919 })
920
921 minetest.register_node("water_flowing", {
922         drawtype = "flowingliquid",
923         tile_images = {"water.png"},
924         alpha = WATER_ALPHA,
925         inventory_image = inventorycube("water.png"),
926         paramtype = "light",
927         light_propagates = true,
928         walkable = false,
929         pointable = false,
930         diggable = false,
931         buildable_to = true,
932         liquidtype = "flowing",
933         liquid_alternative_flowing = "water_flowing",
934         liquid_alternative_source = "water_source",
935         liquid_viscosity = WATER_VISC,
936         post_effect_color = {a=64, r=100, g=100, b=200},
937         special_materials = {
938                 {image="water.png", backface_culling=false},
939                 {image="water.png", backface_culling=true},
940         },
941 })
942
943 minetest.register_node("water_source", {
944         drawtype = "liquid",
945         tile_images = {"water.png"},
946         alpha = WATER_ALPHA,
947         inventory_image = inventorycube("water.png"),
948         paramtype = "light",
949         light_propagates = true,
950         walkable = false,
951         pointable = false,
952         diggable = false,
953         buildable_to = true,
954         liquidtype = "source",
955         liquid_alternative_flowing = "water_flowing",
956         liquid_alternative_source = "water_source",
957         liquid_viscosity = WATER_VISC,
958         post_effect_color = {a=64, r=100, g=100, b=200},
959         special_materials = {
960                 -- New-style water source material (mostly unused)
961                 {image="water.png", backface_culling=false},
962         },
963 })
964
965 minetest.register_node("lava_flowing", {
966         drawtype = "flowingliquid",
967         tile_images = {"lava.png"},
968         inventory_image = inventorycube("lava.png"),
969         paramtype = "light",
970         light_propagates = false,
971         light_source = LIGHT_MAX - 1,
972         walkable = false,
973         pointable = false,
974         diggable = false,
975         buildable_to = true,
976         liquidtype = "flowing",
977         liquid_alternative_flowing = "lava_flowing",
978         liquid_alternative_source = "lava_source",
979         liquid_viscosity = LAVA_VISC,
980         damage_per_second = 4*2,
981         post_effect_color = {a=192, r=255, g=64, b=0},
982         special_materials = {
983                 {image="lava.png", backface_culling=false},
984                 {image="lava.png", backface_culling=true},
985         },
986 })
987
988 minetest.register_node("lava_source", {
989         drawtype = "liquid",
990         tile_images = {"lava.png"},
991         inventory_image = inventorycube("lava.png"),
992         paramtype = "light",
993         light_propagates = false,
994         light_source = LIGHT_MAX - 1,
995         walkable = false,
996         pointable = false,
997         diggable = false,
998         buildable_to = true,
999         liquidtype = "source",
1000         liquid_alternative_flowing = "lava_flowing",
1001         liquid_alternative_source = "lava_source",
1002         liquid_viscosity = LAVA_VISC,
1003         damage_per_second = 4*2,
1004         post_effect_color = {a=192, r=255, g=64, b=0},
1005         special_materials = {
1006                 -- New-style lava source material (mostly unused)
1007                 {image="lava.png", backface_culling=false},
1008         },
1009         furnace_burntime = 60,
1010 })
1011
1012 minetest.register_node("torch", {
1013         drawtype = "torchlike",
1014         tile_images = {"torch_on_floor.png", "torch_on_ceiling.png", "torch.png"},
1015         inventory_image = "torch_on_floor.png",
1016         paramtype = "light",
1017         light_propagates = true,
1018         sunlight_propagates = true,
1019         walkable = false,
1020         wall_mounted = true,
1021         light_source = LIGHT_MAX-1,
1022         selection_box = {
1023                 type = "wallmounted",
1024                 wall_top = {-0.1, 0.5-0.6, -0.1, 0.1, 0.5, 0.1},
1025                 wall_bottom = {-0.1, -0.5, -0.1, 0.1, -0.5+0.6, 0.1},
1026                 wall_side = {-0.5, -0.3, -0.1, -0.5+0.3, 0.3, 0.1},
1027         },
1028         material = digprop_constanttime(0.0),
1029         furnace_burntime = 4,
1030 })
1031
1032 minetest.register_node("sign_wall", {
1033         drawtype = "signlike",
1034         tile_images = {"sign_wall.png"},
1035         inventory_image = "sign_wall.png",
1036         paramtype = "light",
1037         light_propagates = true,
1038         sunlight_propagates = true,
1039         walkable = false,
1040         wall_mounted = true,
1041         metadata_name = "sign",
1042         selection_box = {
1043                 type = "wallmounted",
1044                 --wall_top = <default>
1045                 --wall_bottom = <default>
1046                 --wall_side = <default>
1047         },
1048         material = digprop_constanttime(0.5),
1049         furnace_burntime = 10,
1050 })
1051
1052 minetest.register_node("chest", {
1053         tile_images = {"chest_top.png", "chest_top.png", "chest_side.png",
1054                 "chest_side.png", "chest_side.png", "chest_front.png"},
1055         inventory_image = "chest_top.png",
1056         --inventory_image = inventorycube("chest_top.png", "chest_side.png", "chest_front.png"),
1057         paramtype = "facedir_simple",
1058         metadata_name = "chest",
1059         material = digprop_woodlike(1.0),
1060         furnace_burntime = 30,
1061 })
1062
1063 minetest.register_node("locked_chest", {
1064         tile_images = {"chest_top.png", "chest_top.png", "chest_side.png",
1065                 "chest_side.png", "chest_side.png", "chest_lock.png"},
1066         inventory_image = "chest_lock.png",
1067         paramtype = "facedir_simple",
1068         metadata_name = "locked_chest",
1069         material = digprop_woodlike(1.0),
1070         furnace_burntime = 30,
1071 })
1072
1073 minetest.register_node("furnace", {
1074         tile_images = {"furnace_side.png", "furnace_side.png", "furnace_side.png",
1075                 "furnace_side.png", "furnace_side.png", "furnace_front.png"},
1076         inventory_image = "furnace_front.png",
1077         paramtype = "facedir_simple",
1078         metadata_name = "furnace",
1079         material = digprop_stonelike(3.0),
1080 })
1081
1082 minetest.register_node("cobble", {
1083         tile_images = {"cobble.png"},
1084         inventory_image = inventorycube("cobble.png"),
1085         is_ground_content = true,
1086         cookresult_item = 'NodeItem "stone" 1',
1087         material = digprop_stonelike(0.9),
1088 })
1089
1090 minetest.register_node("mossycobble", {
1091         tile_images = {"mossycobble.png"},
1092         inventory_image = inventorycube("mossycobble.png"),
1093         is_ground_content = true,
1094         material = digprop_stonelike(0.8),
1095 })
1096
1097 minetest.register_node("steelblock", {
1098         tile_images = {"steel_block.png"},
1099         inventory_image = inventorycube("steel_block.png"),
1100         is_ground_content = true,
1101         material = digprop_stonelike(5.0),
1102 })
1103
1104 minetest.register_node("nyancat", {
1105         tile_images = {"nc_side.png", "nc_side.png", "nc_side.png",
1106                 "nc_side.png", "nc_back.png", "nc_front.png"},
1107         inventory_image = "nc_front.png",
1108         paramtype = "facedir_simple",
1109         material = digprop_stonelike(3.0),
1110         furnace_burntime = 1,
1111 })
1112
1113 minetest.register_node("nyancat_rainbow", {
1114         tile_images = {"nc_rb.png"},
1115         inventory_image = "nc_rb.png",
1116         material = digprop_stonelike(3.0),
1117         furnace_burntime = 1,
1118 })
1119
1120 minetest.register_node("sapling", {
1121         drawtype = "plantlike",
1122         visual_scale = 1.0,
1123         tile_images = {"sapling.png"},
1124         inventory_image = "sapling.png",
1125         paramtype = "light",
1126         light_propagates = true,
1127         walkable = false,
1128         material = digprop_constanttime(0.0),
1129         furnace_burntime = 10,
1130 })
1131
1132 minetest.register_node("apple", {
1133         drawtype = "plantlike",
1134         visual_scale = 1.0,
1135         tile_images = {"apple.png"},
1136         inventory_image = "apple.png",
1137         paramtype = "light",
1138         light_propagates = true,
1139         sunlight_propagates = true,
1140         walkable = false,
1141         dug_item = 'CraftItem "apple" 1',
1142         material = digprop_constanttime(0.0),
1143         furnace_burntime = 3,
1144 })
1145
1146 -- New nodes
1147
1148 minetest.register_node("somenode", {
1149         tile_images = {"lava.png", "mese.png", "stone.png", "grass.png", "cobble.png", "tree_top.png"},
1150         inventory_image = "treeprop.png",
1151         material = {
1152                 diggability = "normal",
1153                 weight = 0,
1154                 crackiness = 0,
1155                 crumbliness = 0,
1156                 cuttability = 0,
1157                 flammability = 0
1158         },
1159         metadata_name = "chest",
1160 })
1161
1162 minetest.register_node("TNT", {
1163         tile_images = {"tnt_top.png", "tnt_bottom.png", "tnt_side.png", "tnt_side.png", "tnt_side.png", "tnt_side.png"},
1164         inventory_image = "tnt_side.png",
1165         dug_item = '', -- Get nothing
1166         material = {
1167                 diggability = "not",
1168         },
1169 })
1170
1171 --
1172 -- Crafting items
1173 --
1174
1175 local craftitem_place_item = function(item, placer, pos)
1176         --print("craftitem_place_item")
1177         print("item: " .. dump(item))
1178         print("placer: " .. dump(placer))
1179         print("pos: " .. dump(pos))
1180         minetest.env:add_item(pos, 'CraftItem "' .. item .. '" 1')
1181         return true
1182 end
1183
1184 local craftitem_eat = function(hp_change)
1185         return function(item, user, pointed_thing)  -- closure
1186                 --print("craftitem_eat(" .. hp_change .. ")")
1187                 --print("item: " .. dump(item))
1188                 --print("user: " .. dump(user))
1189                 --print("pointed_thing: " .. dump(pointed_thing))
1190                 user:set_hp(user:get_hp() + hp_change)
1191                 return true
1192         end
1193 end
1194
1195 minetest.register_craftitem("Stick", {
1196         image = "stick.png",
1197         --furnace_burntime = ...,
1198         on_place_on_ground = craftitem_place_item,
1199 })
1200
1201 minetest.register_craftitem("paper", {
1202         image = "paper.png",
1203         on_place_on_ground = craftitem_place_item,
1204 })
1205
1206 minetest.register_craftitem("book", {
1207         image = "book.png",
1208         on_place_on_ground = craftitem_place_item,
1209 })
1210
1211 minetest.register_craftitem("lump_of_coal", {
1212         image = "lump_of_coal.png",
1213         furnace_burntime = 40;
1214         on_place_on_ground = craftitem_place_item,
1215 })
1216
1217 minetest.register_craftitem("lump_of_iron", {
1218         image = "lump_of_iron.png",
1219         cookresult_item = 'CraftItem "steel_ingot" 1',
1220         on_place_on_ground = craftitem_place_item,
1221 })
1222
1223 minetest.register_craftitem("lump_of_clay", {
1224         image = "lump_of_clay.png",
1225         cookresult_item = 'CraftItem "clay_brick" 1',
1226         on_place_on_ground = craftitem_place_item,
1227 })
1228
1229 minetest.register_craftitem("steel_ingot", {
1230         image = "steel_ingot.png",
1231         on_place_on_ground = craftitem_place_item,
1232 })
1233
1234 minetest.register_craftitem("clay_brick", {
1235         image = "clay_brick.png",
1236         on_place_on_ground = craftitem_place_item,
1237 })
1238
1239 minetest.register_craftitem("rat", {
1240         image = "rat.png",
1241         cookresult_item = 'CraftItem "cooked_rat" 1',
1242         on_drop = function(item, dropper, pos)
1243                 minetest.env:add_rat(pos)
1244                 return true
1245         end,
1246 })
1247
1248 minetest.register_craftitem("cooked_rat", {
1249         image = "cooked_rat.png",
1250         cookresult_item = 'CraftItem "scorched_stuff" 1',
1251         on_place_on_ground = craftitem_place_item,
1252         on_use = craftitem_eat(6),
1253 })
1254
1255 minetest.register_craftitem("scorched_stuff", {
1256         image = "scorched_stuff.png",
1257         on_place_on_ground = craftitem_place_item,
1258 })
1259
1260 minetest.register_craftitem("firefly", {
1261         image = "firefly.png",
1262         on_drop = function(item, dropper, pos)
1263                 minetest.env:add_firefly(pos)
1264                 return true
1265         end,
1266 })
1267
1268 minetest.register_craftitem("apple", {
1269         image = "apple.png",
1270         on_place_on_ground = craftitem_place_item,
1271         on_use = craftitem_eat(4),
1272 })
1273
1274 minetest.register_craftitem("apple_iron", {
1275         image = "apple_iron.png",
1276         on_place_on_ground = craftitem_place_item,
1277         on_use = craftitem_eat(8),
1278 })
1279
1280 print(dump(minetest.registered_craftitems))
1281
1282
1283 --
1284 -- Some common functions
1285 --
1286
1287 function nodeupdate_single(p)
1288         n = minetest.env:get_node(p)
1289         if n.name == "sand" or n.name == "gravel" then
1290                 p_bottom = {x=p.x, y=p.y-1, z=p.z}
1291                 n_bottom = minetest.env:get_node(p_bottom)
1292                 if n_bottom.name == "air" then
1293                         minetest.env:remove_node(p)
1294                         minetest.env:add_luaentity(p, "falling_"..n.name)
1295                         nodeupdate(p)
1296                 end
1297         end
1298 end
1299
1300 function nodeupdate(p)
1301         for x = -1,1 do
1302         for y = -1,1 do
1303         for z = -1,1 do
1304                 p2 = {x=p.x+x, y=p.y+y, z=p.z+z}
1305                 nodeupdate_single(p2)
1306         end
1307         end
1308         end
1309 end
1310
1311 --
1312 -- TNT (not functional)
1313 --
1314
1315 local TNT = {
1316         -- Static definition
1317         physical = true, -- Collides with things
1318         -- weight = 5,
1319         collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
1320         visual = "cube",
1321         textures = {"tnt_top.png","tnt_bottom.png","tnt_side.png","tnt_side.png","tnt_side.png","tnt_side.png"},
1322         -- Initial value for our timer
1323         timer = 0,
1324         -- Number of punches required to defuse
1325         health = 1,
1326         blinktimer = 0,
1327         blinkstatus = true,
1328 }
1329
1330 -- Called when a TNT object is created
1331 function TNT:on_activate(staticdata)
1332         print("TNT:on_activate()")
1333         self.object:setvelocity({x=0, y=4, z=0})
1334         self.object:setacceleration({x=0, y=-10, z=0})
1335         self.object:settexturemod("^[brighten")
1336 end
1337
1338 -- Called periodically
1339 function TNT:on_step(dtime)
1340         --print("TNT:on_step()")
1341         self.timer = self.timer + dtime
1342         self.blinktimer = self.blinktimer + dtime
1343         if self.blinktimer > 0.5 then
1344                 self.blinktimer = self.blinktimer - 0.5
1345                 if self.blinkstatus then
1346                         self.object:settexturemod("")
1347                 else
1348                         self.object:settexturemod("^[brighten")
1349                 end
1350                 self.blinkstatus = not self.blinkstatus
1351         end
1352 end
1353
1354 -- Called when object is punched
1355 function TNT:on_punch(hitter)
1356         print("TNT:on_punch()")
1357         self.health = self.health - 1
1358         if self.health <= 0 then
1359                 self.object:remove()
1360                 hitter:add_to_inventory("NodeItem TNT 1")
1361                 hitter:set_hp(hitter:get_hp() - 1)
1362         end
1363 end
1364
1365 -- Called when object is right-clicked
1366 function TNT:on_rightclick(clicker)
1367         --pos = self.object:getpos()
1368         --pos = {x=pos.x, y=pos.y+0.1, z=pos.z}
1369         --self.object:moveto(pos, false)
1370 end
1371
1372 print("TNT dump: "..dump(TNT))
1373
1374 print("Registering TNT");
1375 minetest.register_entity("TNT", TNT)
1376
1377
1378 minetest.register_entity("testentity", {
1379         -- Static definition
1380         physical = true, -- Collides with things
1381         -- weight = 5,
1382         collisionbox = {-0.7,-1.35,-0.7, 0.7,1.0,0.7},
1383         --collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
1384         visual = "sprite",
1385         visual_size = {x=2, y=3},
1386         textures = {"dungeon_master.png^[makealpha:128,0,0^[makealpha:128,128,0"},
1387         spritediv = {x=6, y=5},
1388         initial_sprite_basepos = {x=0, y=0},
1389
1390         on_activate = function(self, staticdata)
1391                 print("testentity.on_activate")
1392                 self.object:setsprite({x=0,y=0}, 1, 0, true)
1393                 --self.object:setsprite({x=0,y=0}, 4, 0.3, true)
1394
1395                 -- Set gravity
1396                 self.object:setacceleration({x=0, y=-10, z=0})
1397                 -- Jump a bit upwards
1398                 self.object:setvelocity({x=0, y=10, z=0})
1399         end,
1400
1401         on_punch = function(self, hitter)
1402                 self.object:remove()
1403                 hitter:add_to_inventory('CraftItem testobject1 1')
1404         end,
1405 })
1406
1407 --
1408 -- Falling stuff
1409 --
1410
1411 function register_falling_node(nodename, texture)
1412         minetest.register_entity("falling_"..nodename, {
1413                 -- Static definition
1414                 physical = true,
1415                 collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
1416                 visual = "cube",
1417                 textures = {texture,texture,texture,texture,texture,texture},
1418                 -- State
1419                 -- Methods
1420                 on_step = function(self, dtime)
1421                         -- Set gravity
1422                         self.object:setacceleration({x=0, y=-10, z=0})
1423                         -- Turn to actual sand when collides to ground or just move
1424                         local pos = self.object:getpos()
1425                         local bcp = {x=pos.x, y=pos.y-0.7, z=pos.z} -- Position of bottom center point
1426                         local bcn = minetest.env:get_node(bcp)
1427                         if bcn.name ~= "air" then
1428                                 -- Turn to a sand node
1429                                 local np = {x=bcp.x, y=bcp.y+1, z=bcp.z}
1430                                 minetest.env:add_node(np, {name=nodename})
1431                                 self.object:remove()
1432                         else
1433                                 -- Do nothing
1434                         end
1435                 end
1436         })
1437 end
1438
1439 register_falling_node("sand", "sand.png")
1440 register_falling_node("gravel", "gravel.png")
1441
1442 --
1443 -- Global callbacks
1444 --
1445
1446 -- Global environment step function
1447 function on_step(dtime)
1448         -- print("on_step")
1449 end
1450 minetest.register_globalstep(on_step)
1451
1452 function on_placenode(p, node)
1453         print("on_placenode")
1454         nodeupdate(p)
1455 end
1456 minetest.register_on_placenode(on_placenode)
1457
1458 function on_dignode(p, node)
1459         print("on_dignode")
1460         nodeupdate(p)
1461 end
1462 minetest.register_on_dignode(on_dignode)
1463
1464 function on_punchnode(p, node)
1465         print("on_punchnode")
1466         if node.name == "TNT" then
1467                 minetest.env:remove_node(p)
1468                 minetest.env:add_luaentity(p, "TNT")
1469                 --minetest.env:add_luaentity(p, "testentity")
1470                 --minetest.env:add_firefly(p)
1471                 nodeupdate(p)
1472         end
1473 end
1474 minetest.register_on_punchnode(on_punchnode)
1475
1476 minetest.register_on_respawnplayer(function(player)
1477         print("on_respawnplayer")
1478         -- player:setpos({x=0, y=30, z=0})
1479         -- return true
1480 end)
1481
1482 minetest.register_on_generated(function(minp, maxp)
1483         --print("on_generated: minp="..dump(minp).." maxp="..dump(maxp))
1484         --cp = {x=(minp.x+maxp.x)/2, y=(minp.y+maxp.y)/2, z=(minp.z+maxp.z)/2}
1485         --minetest.env:add_node(cp, {name="sand"})
1486 end)
1487
1488 -- Example setting get
1489 print("setting max_users = " .. dump(minetest.setting_get("max_users")))
1490 print("setting asdf = " .. dump(minetest.setting_get("asdf")))
1491
1492 minetest.register_on_chat_message(function(name, message)
1493         print("on_chat_message: name="..dump(name).." message="..dump(message))
1494         local cmd = "/testcommand"
1495         if message:sub(0, #cmd) == cmd then
1496                 print(cmd.." invoked")
1497                 return true
1498         end
1499         local cmd = "/help"
1500         if message:sub(0, #cmd) == cmd then
1501                 print("script-overridden help command")
1502                 minetest.chat_send_all("script-overridden help command")
1503                 return true
1504         end
1505 end)
1506
1507 -- Grow papyrus on TNT every 10 seconds
1508 minetest.register_abm({
1509         nodenames = {"TNT"},
1510         interval = 10.0,
1511         chance = 1,
1512         action = function(pos, node, active_object_count, active_object_count_wider)
1513                 print("TNT ABM action")
1514                 pos.y = pos.y + 1
1515                 minetest.env:add_node(pos, {name="papyrus"})
1516         end,
1517 })
1518
1519 -- Replace texts of alls signs with "foo" every 10 seconds
1520 --[[minetest.register_abm({
1521         nodenames = {"sign_wall"},
1522         interval = 10.0,
1523         chance = 1,
1524         action = function(pos, node, active_object_count, active_object_count_wider)
1525                 print("ABM: Sign text changed")
1526                 local meta = minetest.env:get_meta(pos)
1527                 meta:set_text("foo")
1528         end,
1529 })]]
1530
1531 --[[local ncpos = nil
1532 local ncq = 1
1533 local ncstuff = {
1534     {2, 1, 0, 3}, {3, 0, 1, 2}, {4, -1, 0, 1}, {5, -1, 0, 1}, {6, 0, -1, 0},
1535     {7, 0, -1, 0}, {8, 1, 0, 3}, {9, 1, 0, 3}, {10, 1, 0, 3}, {11, 0, 1, 2},
1536     {12, 0, 1, 2}, {13, 0, 1, 2}, {14, -1, 0, 1}, {15, -1, 0, 1}, {16, -1, 0, 1},
1537     {17, -1, 0, 1}, {18, 0, -1, 0}, {19, 0, -1, 0}, {20, 0, -1, 0}, {21, 0, -1, 0},
1538     {22, 1, 0, 3}, {23, 1, 0, 3}, {24, 1, 0, 3}, {25, 1, 0, 3}, {10, 0, 1, 2}
1539 }
1540 local ncold = {}
1541 local nctime = nil
1542
1543 minetest.register_abm({
1544     nodenames = {"dirt_with_grass"},
1545     interval = 100000.0,
1546     chance = 1,
1547     action = function(pos, node, active_object_count, active_object_count_wider)
1548         if ncpos ~= nil then
1549             return
1550         end
1551        
1552         if pos.x % 16 ~= 8 or pos.z % 16 ~= 8 then
1553             return
1554         end
1555        
1556         pos.y = pos.y + 1
1557         n = minetest.env:get_node(pos)
1558         print(dump(n))
1559         if n.name ~= "air" then
1560             return
1561         end
1562
1563         pos.y = pos.y + 2
1564         ncpos = pos
1565         nctime = os.clock()
1566         minetest.env:add_node(ncpos, {name="nyancat"})
1567     end
1568 })
1569
1570 minetest.register_abm({
1571     nodenames = {"nyancat"},
1572     interval = 1.0,
1573     chance = 1,
1574     action = function(pos, node, active_object_count, active_object_count_wider)
1575         if ncpos == nil then
1576             return
1577         end
1578         if pos.x == ncpos.x and pos.y == ncpos.y and pos.z == ncpos.z then
1579             clock = os.clock()
1580             if clock - nctime < 0.1 then
1581                 return
1582             end
1583             nctime = clock
1584            
1585             s0 = ncstuff[ncq]
1586             ncq = s0[1]
1587             s1 = ncstuff[ncq]
1588             p0 = pos
1589             p1 = {x = p0.x + s0[2], y = p0.y, z = p0.z + s0[3]}
1590             p2 = {x = p1.x + s1[2], y = p1.y, z = p1.z + s1[3]}
1591             table.insert(ncold, 1, p0)
1592             while #ncold >= 10 do
1593                 minetest.env:add_node(ncold[#ncold], {name="air"})
1594                 table.remove(ncold, #ncold)
1595             end
1596             minetest.env:add_node(p0, {name="nyancat_rainbow"})
1597             minetest.env:add_node(p1, {name="nyancat", param1=s0[4]})
1598             minetest.env:add_node(p2, {name="air"})
1599             ncpos = p1
1600         end
1601     end,
1602 })--]]
1603
1604 -- LuaNodeMetadata should support something like this
1605 --meta.setvar("somevariable", {x=0, y=0, z=0})
1606 --meta.getvar("somevariable") -> {x=0, y=0, z=0}
1607
1608 --
1609 -- Random stuff
1610 --
1611
1612 minetest.register_node("luafurnace", {
1613         tile_images = {"lava.png", "furnace_side.png", "furnace_side.png",
1614                 "furnace_side.png", "furnace_side.png", "furnace_front.png"},
1615         --inventory_image = "furnace_front.png",
1616         inventory_image = inventorycube("furnace_front.png"),
1617         paramtype = "facedir_simple",
1618         metadata_name = "generic",
1619         material = digprop_stonelike(3.0),
1620 })
1621
1622 minetest.register_on_placenode(function(pos, newnode, placer)
1623         if newnode.name == "luafurnace" then
1624                 print("get_meta");
1625                 local meta = minetest.env:get_meta(pos)
1626                 print("inventory_set_list");
1627                 meta:inventory_set_list("fuel", {""})
1628                 print("inventory_set_list");
1629                 meta:inventory_set_list("src", {""})
1630                 print("inventory_set_list");
1631                 meta:inventory_set_list("dst", {"","","",""})
1632                 print("set_inventory_draw_spec");
1633                 meta:set_inventory_draw_spec(
1634                         "invsize[8,9;]"
1635                         .."list[current_name;fuel;2,3;1,1;]"
1636                         .."list[current_name;src;2,1;1,1;]"
1637                         .."list[current_name;dst;5,1;2,2;]"
1638                         .."list[current_player;main;0,5;8,4;]"
1639                 )
1640                 
1641                 local total_cooked = 0;
1642                 print("set_string")
1643                 meta:set_string("total_cooked", total_cooked)
1644                 print("set_infotext");
1645                 meta:set_infotext("Lua Furnace: total cooked: "..total_cooked)
1646         end
1647 end)
1648
1649 function stackstring_take_item(stackstring)
1650         if stackstring == nil then
1651                 return '', nil
1652         end
1653         local stacktype = nil
1654         stacktype = string.match(stackstring,
1655                         '([%a%d]+Item[%a%d]*)')
1656         if stacktype == "NodeItem" or stacktype == "CraftItem" then
1657                 local itemtype = nil
1658                 local itemname = nil
1659                 local itemcount = nil
1660                 itemtype, itemname, itemcount = string.match(stackstring,
1661                                 '([%a%d]+Item[%a%d]*) "([^"]*)" (%d+)')
1662                 itemcount = tonumber(itemcount)
1663                 if itemcount == 0 then
1664                         return '', nil
1665                 elseif itemcount == 1 then
1666                         return '', {type=itemtype, name=itemname}
1667                 else
1668                         return itemtype.." \""..itemname.."\" "..(itemcount-1),
1669                                         {type=itemtype, name=itemname}
1670                 end
1671         elseif stacktype == "ToolItem" then
1672                 local itemtype = nil
1673                 local itemname = nil
1674                 local itemwear = nil
1675                 itemtype, itemname, itemwear = string.match(stackstring,
1676                                 '([%a%d]+Item[%a%d]*) "([^"]*)" (%d+)')
1677                 itemwear = tonumber(itemwear)
1678                 return '', {type=itemtype, name=itemname, wear=itemwear}
1679         end
1680 end
1681
1682 function stackstring_put_item(stackstring, item)
1683         if item == nil then
1684                 return stackstring, false
1685         end
1686         stackstring = stackstring or ''
1687         local stacktype = nil
1688         stacktype = string.match(stackstring,
1689                         '([%a%d]+Item[%a%d]*)')
1690         stacktype = stacktype or ''
1691         if stacktype ~= '' and stacktype ~= item.type then
1692                 return stackstring, false
1693         end
1694         if item.type == "NodeItem" or item.type == "CraftItem" then
1695                 local itemtype = nil
1696                 local itemname = nil
1697                 local itemcount = nil
1698                 itemtype, itemname, itemcount = string.match(stackstring,
1699                                 '([%a%d]+Item[%a%d]*) "([^"]*)" (%d+)')
1700                 itemtype = itemtype or item.type
1701                 itemname = itemname or item.name
1702                 if itemcount == nil then
1703                         itemcount = 0
1704                 end
1705                 itemcount = itemcount + 1
1706                 return itemtype.." \""..itemname.."\" "..itemcount, true
1707         elseif item.type == "ToolItem" then
1708                 if stacktype ~= nil then
1709                         return stackstring, false
1710                 end
1711                 local itemtype = nil
1712                 local itemname = nil
1713                 local itemwear = nil
1714                 itemtype, itemname, itemwear = string.match(stackstring,
1715                                 '([%a%d]+Item[%a%d]*) "([^"]*)" (%d+)')
1716                 itemwear = tonumber(itemwear)
1717                 return itemtype.." \""..itemname.."\" "..itemwear, true
1718         end
1719         return stackstring, false
1720 end
1721
1722 function stackstring_put_stackstring(stackstring, src)
1723         while src ~= '' do
1724                 --print("src="..dump(src))
1725                 src, item = stackstring_take_item(src)
1726                 --print("src="..dump(src).." item="..dump(item))
1727                 local success
1728                 stackstring, success = stackstring_put_item(stackstring, item)
1729                 if not success then
1730                         return stackstring, false
1731                 end
1732         end
1733         return stackstring, true
1734 end
1735
1736 function test_stack()
1737         local stack
1738         local item
1739         local success
1740
1741         stack, item = stackstring_take_item('NodeItem "TNT" 3')
1742         assert(stack == 'NodeItem "TNT" 2')
1743         assert(item.type == 'NodeItem')
1744         assert(item.name == 'TNT')
1745
1746         stack, item = stackstring_take_item('CraftItem "with spaces" 2')
1747         assert(stack == 'CraftItem "with spaces" 1')
1748         assert(item.type == 'CraftItem')
1749         assert(item.name == 'with spaces')
1750
1751         stack, item = stackstring_take_item('CraftItem "with spaces" 1')
1752         assert(stack == '')
1753         assert(item.type == 'CraftItem')
1754         assert(item.name == 'with spaces')
1755
1756         stack, item = stackstring_take_item('CraftItem "s8df2kj3" 0')
1757         assert(stack == '')
1758         assert(item == nil)
1759
1760         stack, item = stackstring_take_item('ToolItem "With Spaces" 32487')
1761         assert(stack == '')
1762         assert(item.type == 'ToolItem')
1763         assert(item.name == 'With Spaces')
1764         assert(item.wear == 32487)
1765
1766         stack, success = stackstring_put_item('NodeItem "With Spaces" 40',
1767                         {type='NodeItem', name='With Spaces'})
1768         assert(stack == 'NodeItem "With Spaces" 41')
1769         assert(success == true)
1770
1771         stack, success = stackstring_put_item('CraftItem "With Spaces" 40',
1772                         {type='CraftItem', name='With Spaces'})
1773         assert(stack == 'CraftItem "With Spaces" 41')
1774         assert(success == true)
1775
1776         stack, success = stackstring_put_item('ToolItem "With Spaces" 32487',
1777                         {type='ToolItem', name='With Spaces'})
1778         assert(stack == 'ToolItem "With Spaces" 32487')
1779         assert(success == false)
1780
1781         stack, success = stackstring_put_item('NodeItem "With Spaces" 40',
1782                         {type='ToolItem', name='With Spaces'})
1783         assert(stack == 'NodeItem "With Spaces" 40')
1784         assert(success == false)
1785         
1786         assert(stackstring_put_stackstring('NodeItem "With Spaces" 2',
1787                         'NodeItem "With Spaces" 1') == 'NodeItem "With Spaces" 3')
1788 end
1789 test_stack()
1790
1791 minetest.register_abm({
1792         nodenames = {"luafurnace"},
1793         interval = 1.0,
1794         chance = 1,
1795         action = function(pos, node, active_object_count, active_object_count_wider)
1796                 local meta = minetest.env:get_meta(pos)
1797                 local fuellist = meta:inventory_get_list("fuel")
1798                 local srclist = meta:inventory_get_list("src")
1799                 local dstlist = meta:inventory_get_list("dst")
1800                 if fuellist == nil or srclist == nil or dstlist == nil then
1801                         return
1802                 end
1803                 _, srcitem = stackstring_take_item(srclist[1])
1804                 _, fuelitem = stackstring_take_item(fuellist[1])
1805                 if not srcitem or not fuelitem then return end
1806                 if fuelitem.type == "NodeItem" then
1807                         local prop = minetest.registered_nodes[fuelitem.name]
1808                         if prop == nil then return end
1809                         if prop.furnace_burntime < 0 then return end
1810                 else
1811                         return
1812                 end
1813                 local resultstack = nil
1814                 if srcitem.type == "NodeItem" then
1815                         local prop = minetest.registered_nodes[srcitem.name]
1816                         if prop == nil then return end
1817                         if prop.cookresult_item == "" then return end
1818                         resultstack = prop.cookresult_item
1819                 else
1820                         return
1821                 end
1822
1823                 if resultstack == nil then
1824                         return
1825                 end
1826
1827                 dstlist[1], success = stackstring_put_stackstring(dstlist[1], resultstack)
1828                 if not success then
1829                         return
1830                 end
1831
1832                 fuellist[1], _ = stackstring_take_item(fuellist[1])
1833                 srclist[1], _ = stackstring_take_item(srclist[1])
1834
1835                 meta:inventory_set_list("fuel", fuellist)
1836                 meta:inventory_set_list("src", srclist)
1837                 meta:inventory_set_list("dst", dstlist)
1838
1839                 local total_cooked = meta:get_string("total_cooked")
1840                 total_cooked = tonumber(total_cooked) + 1
1841                 meta:set_string("total_cooked", total_cooked)
1842                 meta:set_infotext("Lua Furnace: total cooked: "..total_cooked)
1843         end,
1844 })
1845
1846 minetest.register_craft({
1847         output = 'NodeItem "luafurnace" 1',
1848         recipe = {
1849                 {'NodeItem "cobble"', 'NodeItem "cobble"', 'NodeItem "cobble"'},
1850                 {'NodeItem "cobble"', 'NodeItem "cobble"', 'NodeItem "cobble"'},
1851                 {'NodeItem "cobble"', 'NodeItem "cobble"', 'NodeItem "cobble"'},
1852         }
1853 })
1854
1855 --
1856 -- Done, print some random stuff
1857 --
1858
1859 print("minetest.registered_entities:")
1860 dump2(minetest.registered_entities)
1861
1862 -- END