0c1005272a9fbe7f5575d0b5d50866567b96acdb
[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=1.0}
13         table.place = table.place or
14                         {name="default_place_node", gain=0.5}
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.2}
22         default.node_sound_defaults(table)
23         return table
24 end
25
26 function default.node_sound_dirt_defaults(table)
27         table = table or {}
28         table.footstep = table.footstep or
29                         {name="", gain=0.5}
30         --table.dug = table.dug or
31         --              {name="default_dirt_break", gain=0.5}
32         default.node_sound_defaults(table)
33         return table
34 end
35
36 function default.node_sound_sand_defaults(table)
37         table = table or {}
38         table.footstep = table.footstep or
39                         {name="default_grass_footstep", gain=0.25}
40         --table.dug = table.dug or
41         --              {name="default_dirt_break", gain=0.25}
42         table.dug = table.dug or
43                         {name="", gain=0.25}
44         default.node_sound_defaults(table)
45         return table
46 end
47
48 function default.node_sound_wood_defaults(table)
49         table = table or {}
50         table.footstep = table.footstep or
51                         {name="default_hard_footstep", gain=0.3}
52         default.node_sound_defaults(table)
53         return table
54 end
55
56 function default.node_sound_leaves_defaults(table)
57         table = table or {}
58         table.footstep = table.footstep or
59                         {name="default_grass_footstep", gain=0.25}
60         table.dig = table.dig or
61                         {name="default_dig_crumbly", gain=0.4}
62         table.dug = table.dug or
63                         {name="", gain=1.0}
64         default.node_sound_defaults(table)
65         return table
66 end
67
68 function default.node_sound_glass_defaults(table)
69         table = table or {}
70         table.footstep = table.footstep or
71                         {name="default_hard_footstep", gain=0.25}
72         table.dug = table.dug or
73                         {name="default_break_glass", gain=1.0}
74         default.node_sound_defaults(table)
75         return table
76 end
77
78 --
79 -- Legacy
80 --
81
82 function default.spawn_falling_node(p, nodename)
83         spawn_falling_node(p, nodename)
84 end
85
86 -- Horrible crap to support old code
87 -- Don't use this and never do what this does, it's completely wrong!
88 -- (More specifically, the client and the C++ code doesn't get the group)
89 function default.register_falling_node(nodename, texture)
90         minetest.log("error", debug.traceback())
91         minetest.log('error', "WARNING: default.register_falling_node is deprecated")
92         if minetest.registered_nodes[nodename] then
93                 minetest.registered_nodes[nodename].groups.falling_node = 1
94         end
95 end
96
97 --
98 -- Global callbacks
99 --
100
101 -- Global environment step function
102 function on_step(dtime)
103         -- print("on_step")
104 end
105 minetest.register_globalstep(on_step)
106
107 function on_placenode(p, node)
108         --print("on_placenode")
109 end
110 minetest.register_on_placenode(on_placenode)
111
112 function on_dignode(p, node)
113         --print("on_dignode")
114 end
115 minetest.register_on_dignode(on_dignode)
116
117 function on_punchnode(p, node)
118 end
119 minetest.register_on_punchnode(on_punchnode)
120
121 --
122 -- Lavacooling
123 --
124
125 default.cool_lava_source = function(pos)
126         minetest.set_node(pos, {name="default:obsidian"})
127 end
128
129 default.cool_lava_flowing = function(pos)
130         minetest.set_node(pos, {name="default:stone"})
131 end
132
133 minetest.register_abm({
134         nodenames = {"default:lava_flowing"},
135         neighbors = {"group:water"},
136         interval = 1,
137         chance = 1,
138         action = function(pos, node, active_object_count, active_object_count_wider)
139                 default.cool_lava_flowing(pos, node, active_object_count, active_object_count_wider)
140         end,
141 })
142
143 minetest.register_abm({
144         nodenames = {"default:lava_source"},
145         neighbors = {"group:water"},
146         interval = 1,
147         chance = 1,
148         action = function(pos, node, active_object_count, active_object_count_wider)
149                 default.cool_lava_source(pos, node, active_object_count, active_object_count_wider)
150         end,
151 })
152
153 --
154 -- Papyrus and cactus growing
155 --
156
157 minetest.register_abm({
158         nodenames = {"default:cactus"},
159         neighbors = {"group:sand"},
160         interval = 50,
161         chance = 20,
162         action = function(pos, node)
163                 pos.y = pos.y-1
164                 local name = minetest.get_node(pos).name
165                 if minetest.get_item_group(name, "sand") ~= 0 then
166                         pos.y = pos.y+1
167                         local height = 0
168                         while minetest.get_node(pos).name == "default:cactus" and height < 4 do
169                                 height = height+1
170                                 pos.y = pos.y+1
171                         end
172                         if height < 4 then
173                                 if minetest.get_node(pos).name == "air" then
174                                         minetest.set_node(pos, {name="default:cactus"})
175                                 end
176                         end
177                 end
178         end,
179 })
180
181 minetest.register_abm({
182         nodenames = {"default:papyrus"},
183         neighbors = {"default:dirt", "default:dirt_with_grass"},
184         interval = 50,
185         chance = 20,
186         action = function(pos, node)
187                 pos.y = pos.y-1
188                 local name = minetest.get_node(pos).name
189                 if name == "default:dirt" or name == "default:dirt_with_grass" then
190                         if minetest.find_node_near(pos, 3, {"group:water"}) == nil then
191                                 return
192                         end
193                         pos.y = pos.y+1
194                         local height = 0
195                         while minetest.get_node(pos).name == "default:papyrus" and height < 4 do
196                                 height = height+1
197                                 pos.y = pos.y+1
198                         end
199                         if height < 4 then
200                                 if minetest.get_node(pos).name == "air" then
201                                         minetest.set_node(pos, {name="default:papyrus"})
202                                 end
203                         end
204                 end
205         end,
206 })
207
208 --
209 -- Leafdecay
210 --
211
212 -- To enable leaf decay for a node, add it to the "leafdecay" group.
213 --
214 -- The rating of the group determines how far from a node in the group "tree"
215 -- the node can be without decaying.
216 --
217 -- If param2 of the node is ~= 0, the node will always be preserved. Thus, if
218 -- the player places a node of that kind, you will want to set param2=1 or so.
219 --
220 -- If the node is in the leafdecay_drop group then the it will always be dropped
221 -- as an item
222
223 default.leafdecay_trunk_cache = {}
224 default.leafdecay_enable_cache = true
225 -- Spread the load of finding trunks
226 default.leafdecay_trunk_find_allow_accumulator = 0
227
228 minetest.register_globalstep(function(dtime)
229         local finds_per_second = 5000
230         default.leafdecay_trunk_find_allow_accumulator =
231                         math.floor(dtime * finds_per_second)
232 end)
233
234 minetest.register_abm({
235         nodenames = {"group:leafdecay"},
236         neighbors = {"air", "group:liquid"},
237         -- A low interval and a high inverse chance spreads the load
238         interval = 2,
239         chance = 5,
240
241         action = function(p0, node, _, _)
242                 --print("leafdecay ABM at "..p0.x..", "..p0.y..", "..p0.z..")")
243                 local do_preserve = false
244                 local d = minetest.registered_nodes[node.name].groups.leafdecay
245                 if not d or d == 0 then
246                         --print("not groups.leafdecay")
247                         return
248                 end
249                 local n0 = minetest.get_node(p0)
250                 if n0.param2 ~= 0 then
251                         --print("param2 ~= 0")
252                         return
253                 end
254                 local p0_hash = nil
255                 if default.leafdecay_enable_cache then
256                         p0_hash = minetest.hash_node_position(p0)
257                         local trunkp = default.leafdecay_trunk_cache[p0_hash]
258                         if trunkp then
259                                 local n = minetest.get_node(trunkp)
260                                 local reg = minetest.registered_nodes[n.name]
261                                 -- Assume ignore is a trunk, to make the thing work at the border of the active area
262                                 if n.name == "ignore" or (reg and reg.groups.tree and reg.groups.tree ~= 0) then
263                                         --print("cached trunk still exists")
264                                         return
265                                 end
266                                 --print("cached trunk is invalid")
267                                 -- Cache is invalid
268                                 table.remove(default.leafdecay_trunk_cache, p0_hash)
269                         end
270                 end
271                 if default.leafdecay_trunk_find_allow_accumulator <= 0 then
272                         return
273                 end
274                 default.leafdecay_trunk_find_allow_accumulator =
275                                 default.leafdecay_trunk_find_allow_accumulator - 1
276                 -- Assume ignore is a trunk, to make the thing 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                         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 })