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