Default/mapgen: Fix missing taiga pine
[oweals/minetest_game.git] / mods / default / functions.lua
1 -- mods/default/functions.lua
2
3 --
4 -- Sounds
5 --
6
7 function default.node_sound_defaults(table)
8         table = table or {}
9         table.footstep = table.footstep or
10                         {name = "", gain = 1.0}
11         table.dug = table.dug or
12                         {name = "default_dug_node", gain = 0.25}
13         table.place = table.place or
14                         {name = "default_place_node_hard", gain = 1.0}
15         return table
16 end
17
18 function default.node_sound_stone_defaults(table)
19         table = table or {}
20         table.footstep = table.footstep or
21                         {name = "default_hard_footstep", gain = 0.5}
22         table.dug = table.dug or
23                         {name = "default_hard_footstep", gain = 1.0}
24         default.node_sound_defaults(table)
25         return table
26 end
27
28 function default.node_sound_dirt_defaults(table)
29         table = table or {}
30         table.footstep = table.footstep or
31                         {name = "default_dirt_footstep", gain = 1.0}
32         table.dug = table.dug or
33                         {name = "default_dirt_footstep", gain = 1.5}
34         table.place = table.place or
35                         {name = "default_place_node", gain = 1.0}
36         default.node_sound_defaults(table)
37         return table
38 end
39
40 function default.node_sound_sand_defaults(table)
41         table = table or {}
42         table.footstep = table.footstep or
43                         {name = "default_sand_footstep", gain = 0.2}
44         table.dug = table.dug or
45                         {name = "default_sand_footstep", gain = 0.4}
46         table.place = table.place or
47                         {name = "default_place_node", gain = 1.0}
48         default.node_sound_defaults(table)
49         return table
50 end
51
52 function default.node_sound_wood_defaults(table)
53         table = table or {}
54         table.footstep = table.footstep or
55                         {name = "default_wood_footstep", gain = 0.5}
56         table.dug = table.dug or
57                         {name = "default_wood_footstep", gain = 1.0}
58         default.node_sound_defaults(table)
59         return table
60 end
61
62 function default.node_sound_leaves_defaults(table)
63         table = table or {}
64         table.footstep = table.footstep or
65                         {name = "default_grass_footstep", gain = 0.35}
66         table.dug = table.dug or
67                         {name = "default_grass_footstep", gain = 0.7}
68         table.dig = table.dig or
69                         {name = "default_dig_crumbly", gain = 0.4}
70         table.place = table.place or
71                         {name = "default_place_node", gain = 1.0}
72         default.node_sound_defaults(table)
73         return table
74 end
75
76 function default.node_sound_glass_defaults(table)
77         table = table or {}
78         table.footstep = table.footstep or
79                         {name = "default_glass_footstep", gain = 0.5}
80         table.dug = table.dug or
81                         {name = "default_break_glass", gain = 1.0}
82         default.node_sound_defaults(table)
83         return table
84 end
85
86
87 --
88 -- Lavacooling
89 --
90
91 default.cool_lava_source = function(pos)
92         minetest.set_node(pos, {name = "default:obsidian"})
93         minetest.sound_play("default_cool_lava",
94                 {pos = pos, max_hear_distance = 16, gain = 0.25})
95 end
96
97 default.cool_lava_flowing = function(pos)
98         minetest.set_node(pos, {name = "default:stone"})
99         minetest.sound_play("default_cool_lava",
100                 {pos = pos, max_hear_distance = 16, gain = 0.25})
101 end
102
103 minetest.register_abm({
104         nodenames = {"default:lava_flowing"},
105         neighbors = {"group:water"},
106         interval = 1,
107         chance = 2,
108         action = function(...)
109                 default.cool_lava_flowing(...)
110         end,
111 })
112
113 minetest.register_abm({
114         nodenames = {"default:lava_source"},
115         neighbors = {"group:water"},
116         interval = 1,
117         chance = 2,
118         action = function(...)
119                 default.cool_lava_source(...)
120         end,
121 })
122
123
124 --
125 -- Papyrus and cactus growing
126 --
127
128 -- wrapping the functions in abm action is necessary to make overriding them possible
129
130 function default.grow_cactus(pos, node)
131         if node.param2 >= 4 then
132                 return
133         end
134         pos.y = pos.y - 1
135         if minetest.get_item_group(minetest.get_node(pos).name, "sand") == 0 then
136                 return
137         end
138         pos.y = pos.y + 1
139         local height = 0
140         while node.name == "default:cactus" and height < 4 do
141                 height = height + 1
142                 pos.y = pos.y + 1
143                 node = minetest.get_node(pos)
144         end
145         if height == 4 or node.name ~= "air" then
146                 return
147         end
148         minetest.set_node(pos, {name = "default:cactus"})
149         return true
150 end
151
152 function default.grow_papyrus(pos, node)
153         pos.y = pos.y - 1
154         local name = minetest.get_node(pos).name
155         if name ~= "default:dirt_with_grass" and name ~= "default:dirt" then
156                 return
157         end
158         if not minetest.find_node_near(pos, 3, {"group:water"}) then
159                 return
160         end
161         pos.y = pos.y + 1
162         local height = 0
163         while node.name == "default:papyrus" and height < 4 do
164                 height = height + 1
165                 pos.y = pos.y + 1
166                 node = minetest.get_node(pos)
167         end
168         if height == 4 or node.name ~= "air" then
169                 return
170         end
171         minetest.set_node(pos, {name = "default:papyrus"})
172         return true
173 end
174
175 minetest.register_abm({
176         nodenames = {"default:cactus"},
177         neighbors = {"group:sand"},
178         interval = 50,
179         chance = 20,
180         action = function(...)
181                 default.grow_cactus(...)
182         end
183 })
184
185 minetest.register_abm({
186         nodenames = {"default:papyrus"},
187         neighbors = {"default:dirt", "default:dirt_with_grass", "default:sand"},
188         interval = 50,
189         chance = 20,
190         action = function(...)
191                 default.grow_papyrus(...)
192         end
193 })
194
195
196 --
197 -- dig upwards
198 --
199
200 function default.dig_up(pos, node, digger)
201         if digger == nil then return end
202         local np = {x = pos.x, y = pos.y + 1, z = pos.z}
203         local nn = minetest.get_node(np)
204         if nn.name == node.name then
205                 minetest.node_dig(np, nn, digger)
206         end
207 end
208
209
210 --
211 -- Leafdecay
212 --
213
214 default.leafdecay_trunk_cache = {}
215 default.leafdecay_enable_cache = true
216 -- Spread the load of finding trunks
217 default.leafdecay_trunk_find_allow_accumulator = 0
218
219 minetest.register_globalstep(function(dtime)
220         local finds_per_second = 5000
221         default.leafdecay_trunk_find_allow_accumulator =
222                         math.floor(dtime * finds_per_second)
223 end)
224
225 default.after_place_leaves = function(pos, placer, itemstack, pointed_thing)
226         local node = minetest.get_node(pos)
227         node.param2 = 1
228         minetest.set_node(pos, node)
229 end
230
231 minetest.register_abm({
232         nodenames = {"group:leafdecay"},
233         neighbors = {"air", "group:liquid"},
234         -- A low interval and a high inverse chance spreads the load
235         interval = 2,
236         chance = 5,
237
238         action = function(p0, node, _, _)
239                 --print("leafdecay ABM at "..p0.x..", "..p0.y..", "..p0.z..")")
240                 local do_preserve = false
241                 local d = minetest.registered_nodes[node.name].groups.leafdecay
242                 if not d or d == 0 then
243                         --print("not groups.leafdecay")
244                         return
245                 end
246                 local n0 = minetest.get_node(p0)
247                 if n0.param2 ~= 0 then
248                         --print("param2 ~= 0")
249                         return
250                 end
251                 local p0_hash = nil
252                 if default.leafdecay_enable_cache then
253                         p0_hash = minetest.hash_node_position(p0)
254                         local trunkp = default.leafdecay_trunk_cache[p0_hash]
255                         if trunkp then
256                                 local n = minetest.get_node(trunkp)
257                                 local reg = minetest.registered_nodes[n.name]
258                                 -- Assume ignore is a trunk, to make the thing
259                                 -- work at the border of the active area
260                                 if n.name == "ignore" or (reg and reg.groups.tree and
261                                                 reg.groups.tree ~= 0) then
262                                         --print("cached trunk still exists")
263                                         return
264                                 end
265                                 --print("cached trunk is invalid")
266                                 -- Cache is invalid
267                                 table.remove(default.leafdecay_trunk_cache, p0_hash)
268                         end
269                 end
270                 if default.leafdecay_trunk_find_allow_accumulator <= 0 then
271                         return
272                 end
273                 default.leafdecay_trunk_find_allow_accumulator =
274                                 default.leafdecay_trunk_find_allow_accumulator - 1
275                 -- Assume ignore is a trunk, to make the thing
276                 -- work at the border of the active area
277                 local p1 = minetest.find_node_near(p0, d, {"ignore", "group:tree"})
278                 if p1 then
279                         do_preserve = true
280                         if default.leafdecay_enable_cache then
281                                 --print("caching trunk")
282                                 -- Cache the trunk
283                                 default.leafdecay_trunk_cache[p0_hash] = p1
284                         end
285                 end
286                 if not do_preserve then
287                         -- Drop stuff other than the node itself
288                         local itemstacks = minetest.get_node_drops(n0.name)
289                         for _, itemname in ipairs(itemstacks) do
290                                 if minetest.get_item_group(n0.name, "leafdecay_drop") ~= 0 or
291                                                 itemname ~= n0.name then
292                                         local p_drop = {
293                                                 x = p0.x - 0.5 + math.random(),
294                                                 y = p0.y - 0.5 + math.random(),
295                                                 z = p0.z - 0.5 + math.random(),
296                                         }
297                                         minetest.add_item(p_drop, itemname)
298                                 end
299                         end
300                         -- Remove node
301                         minetest.remove_node(p0)
302                         nodeupdate(p0)
303                 end
304         end
305 })
306
307
308 --
309 -- Grass growing on well-lit dirt
310 --
311
312 minetest.register_abm({
313         nodenames = {"default:dirt"},
314         interval = 2,
315         chance = 200,
316         action = function(pos, node)
317                 local above = {x = pos.x, y = pos.y + 1, z = pos.z}
318                 local name = minetest.get_node(above).name
319                 local nodedef = minetest.registered_nodes[name]
320                 if nodedef and (nodedef.sunlight_propagates or nodedef.paramtype == "light") and
321                                 nodedef.liquidtype == "none" and
322                                 (minetest.get_node_light(above) or 0) >= 13 then
323                         if name == "default:snow" or name == "default:snowblock" then
324                                 minetest.set_node(pos, {name = "default:dirt_with_snow"})
325                         else
326                                 minetest.set_node(pos, {name = "default:dirt_with_grass"})
327                         end
328                 end
329         end
330 })
331
332
333 --
334 -- Grass and dry grass removed in darkness
335 --
336
337 minetest.register_abm({
338         nodenames = {"default:dirt_with_grass", "default:dirt_with_dry_grass"},
339         interval = 2,
340         chance = 20,
341         action = function(pos, node)
342                 local above = {x = pos.x, y = pos.y + 1, z = pos.z}
343                 local name = minetest.get_node(above).name
344                 local nodedef = minetest.registered_nodes[name]
345                 if name ~= "ignore" and nodedef and not ((nodedef.sunlight_propagates or
346                                 nodedef.paramtype == "light") and
347                                 nodedef.liquidtype == "none") then
348                         minetest.set_node(pos, {name = "default:dirt"})
349                 end
350         end
351 })
352
353
354 --
355 -- Moss growth on cobble near water
356 --
357
358 minetest.register_abm({
359         nodenames = {"default:cobble"},
360         neighbors = {"group:water"},
361         interval = 17,
362         chance = 200,
363         catch_up = false,
364         action = function(pos, node)
365                 minetest.set_node(pos, {name = "default:mossycobble"})
366         end
367 })