Default/functions: Reduce lavacooling ABM/sound overload
[oweals/minetest_game.git] / mods / farming / api.lua
1 -- Wear out hoes, place soil
2 -- TODO Ignore group:flower
3 farming.hoe_on_use = function(itemstack, user, pointed_thing, uses)
4         local pt = pointed_thing
5         -- check if pointing at a node
6         if not pt then
7                 return
8         end
9         if pt.type ~= "node" then
10                 return
11         end
12         
13         local under = minetest.get_node(pt.under)
14         local p = {x=pt.under.x, y=pt.under.y+1, z=pt.under.z}
15         local above = minetest.get_node(p)
16         
17         -- return if any of the nodes is not registered
18         if not minetest.registered_nodes[under.name] then
19                 return
20         end
21         if not minetest.registered_nodes[above.name] then
22                 return
23         end
24         
25         -- check if the node above the pointed thing is air
26         if above.name ~= "air" then
27                 return
28         end
29         
30         -- check if pointing at soil
31         if minetest.get_item_group(under.name, "soil") ~= 1 then
32                 return
33         end
34         
35         -- check if (wet) soil defined
36         local regN = minetest.registered_nodes
37         if regN[under.name].soil == nil or regN[under.name].soil.wet == nil or regN[under.name].soil.dry == nil then
38                 return
39         end
40         
41         -- turn the node into soil, wear out item and play sound
42         minetest.set_node(pt.under, {name = regN[under.name].soil.dry})
43         minetest.sound_play("default_dig_crumbly", {
44                 pos = pt.under,
45                 gain = 0.5,
46         })
47         
48         if not minetest.setting_getbool("creative_mode") then
49                 itemstack:add_wear(65535/(uses-1))
50         end
51         return itemstack
52 end
53
54 -- Register new hoes
55 farming.register_hoe = function(name, def)
56         -- Check for : prefix (register new hoes in your mod's namespace)
57         if name:sub(1,1) ~= ":" then
58                 name = ":" .. name
59         end
60         -- Check def table
61         if def.description == nil then
62                 def.description = "Hoe"
63         end
64         if def.inventory_image == nil then
65                 def.inventory_image = "unknown_item.png"
66         end
67         if def.recipe == nil then
68                 def.recipe = {
69                         {"air","air",""},
70                         {"","group:stick",""},
71                         {"","group:stick",""}
72                 }
73         end
74         if def.max_uses == nil then
75                 def.max_uses = 30
76         end
77         -- Register the tool
78         minetest.register_tool(name, {
79                 description = def.description,
80                 inventory_image = def.inventory_image,
81                 on_use = function(itemstack, user, pointed_thing)
82                         return farming.hoe_on_use(itemstack, user, pointed_thing, def.max_uses)
83                 end
84         })
85         -- Register its recipe
86         if def.material == nil then
87                 minetest.register_craft({
88                         output = name:sub(2),
89                         recipe = def.recipe
90                 })
91         else
92                 minetest.register_craft({
93                         output = name:sub(2),
94                         recipe = {
95                                 {def.material, def.material, ""},
96                                 {"", "group:stick", ""},
97                                 {"", "group:stick", ""}
98                         }
99                 })
100                 -- Reverse Recipe
101                 minetest.register_craft({
102                         output = name:sub(2),
103                         recipe = {
104                                 {"", def.material, def.material},
105                                 {"", "group:stick", ""},
106                                 {"", "group:stick", ""}
107                         }
108                 })
109         end
110 end
111
112 -- Seed placement
113 farming.place_seed = function(itemstack, placer, pointed_thing, plantname)
114         local pt = pointed_thing
115         -- check if pointing at a node
116         if not pt then
117                 return
118         end
119         if pt.type ~= "node" then
120                 return
121         end
122         
123         local under = minetest.get_node(pt.under)
124         local above = minetest.get_node(pt.above)
125         
126         -- return if any of the nodes is not registered
127         if not minetest.registered_nodes[under.name] then
128                 return
129         end
130         if not minetest.registered_nodes[above.name] then
131                 return
132         end
133         
134         -- check if pointing at the top of the node
135         if pt.above.y ~= pt.under.y+1 then
136                 return
137         end
138         
139         -- check if you can replace the node above the pointed node
140         if not minetest.registered_nodes[above.name].buildable_to then
141                 return
142         end
143         
144         -- check if pointing at soil
145         if minetest.get_item_group(under.name, "soil") < 2 then
146                 return
147         end
148         
149         -- add the node and remove 1 item from the itemstack
150         minetest.add_node(pt.above, {name = plantname, param2 = 1})
151         if not minetest.setting_getbool("creative_mode") then
152                 itemstack:take_item()
153         end
154         return itemstack
155 end
156
157 -- Register plants
158 farming.register_plant = function(name, def)
159         local mname = name:split(":")[1]
160         local pname = name:split(":")[2]
161
162         -- Check def table
163         if not def.description then
164                 def.description = "Seed"
165         end
166         if not def.inventory_image then
167                 def.inventory_image = "unknown_item.png"
168         end
169         if not def.steps then
170                 return nil
171         end
172         if not def.minlight then
173                 def.minlight = 1
174         end
175         if not def.maxlight then
176                 def.maxlight = 14
177         end
178         if not def.fertility then
179                 def.fertility = {}
180         end
181
182         -- Register seed
183         local g = {seed = 1, snappy = 3, attached_node = 1}
184         for k, v in pairs(def.fertility) do
185                 g[v] = 1
186         end
187         minetest.register_node(":" .. mname .. ":seed_" .. pname, {
188                 description = def.description,
189                 tiles = {def.inventory_image},
190                 inventory_image = def.inventory_image,
191                 wield_image = def.inventory_image,
192                 drawtype = "signlike",
193                 groups = g,
194                 paramtype = "light",
195                 paramtype2 = "wallmounted",
196                 walkable = false,
197                 sunlight_propagates = true,
198                 selection_box = {
199                         type = "fixed",
200                         fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5},
201                 },
202                 fertility = def.fertility,
203                 on_place = function(itemstack, placer, pointed_thing)
204                         return farming.place_seed(itemstack, placer, pointed_thing, mname .. ":seed_" .. pname)
205                 end
206         })
207
208         -- Register harvest
209         minetest.register_craftitem(":" .. mname .. ":" .. pname, {
210                 description = pname:gsub("^%l", string.upper),
211                 inventory_image = mname .. "_" .. pname .. ".png",
212         })
213
214         -- Register growing steps
215         for i=1,def.steps do
216                 local drop = {
217                         items = {
218                                 {items = {mname .. ":" .. pname}, rarity = 9 - i},
219                                 {items = {mname .. ":" .. pname}, rarity= 18 - i * 2},
220                                 {items = {mname .. ":seed_" .. pname}, rarity = 9 - i},
221                                 {items = {mname .. ":seed_" .. pname}, rarity = 18 - i * 2},
222                         }
223                 }
224                 local nodegroups = {snappy = 3, flammable = 2, plant = 1, not_in_creative_inventory = 1, attached_node = 1}
225                 nodegroups[pname] = i
226                 minetest.register_node(mname .. ":" .. pname .. "_" .. i, {
227                         drawtype = "plantlike",
228                         waving = 1,
229                         tiles = {mname .. "_" .. pname .. "_" .. i .. ".png"},
230                         paramtype = "light",
231                         walkable = false,
232                         buildable_to = true,
233                         drop = drop,
234                         selection_box = {
235                                 type = "fixed",
236                                 fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5},
237                         },
238                         groups = nodegroups,
239                         sounds = default.node_sound_leaves_defaults(),
240                 })
241         end
242
243         -- Growing ABM
244         minetest.register_abm({
245                 nodenames = {"group:" .. pname, "group:seed"},
246                 neighbors = {"group:soil"},
247                 interval = 90,
248                 chance = 2,
249                 action = function(pos, node)
250                         local plant_height = minetest.get_item_group(node.name, pname)
251
252                         -- return if already full grown
253                         if plant_height == def.steps then
254                                 return
255                         end
256
257                         local node_def = minetest.registered_items[node.name] or nil
258
259                         -- grow seed
260                         if minetest.get_item_group(node.name, "seed") and node_def.fertility then
261                                 local can_grow = false
262                                 local soil_node = minetest.get_node_or_nil({x = pos.x, y = pos.y - 1, z = pos.z})
263                                 if not soil_node then
264                                         return
265                                 end
266                                 for _, v in pairs(node_def.fertility) do
267                                         if minetest.get_item_group(soil_node.name, v) ~= 0 then
268                                                 can_grow = true
269                                         end
270                                 end
271                                 if can_grow then
272                                         minetest.set_node(pos, {name = node.name:gsub("seed_", "") .. "_1"})
273                                 end
274                                 return
275                         end
276
277                         -- check if on wet soil
278                         pos.y = pos.y - 1
279                         local n = minetest.get_node(pos)
280                         if minetest.get_item_group(n.name, "soil") < 3 then
281                                 return
282                         end
283                         pos.y = pos.y + 1
284
285                         -- check light
286                         local ll = minetest.get_node_light(pos)
287
288                         if not ll or ll < def.minlight or ll > def.maxlight then
289                                 return
290                         end
291
292                         -- grow
293                         minetest.set_node(pos, {name = mname .. ":" .. pname .. "_" .. plant_height + 1})
294                 end
295         })
296
297         -- Return
298         local r = {
299                 seed = mname .. ":seed_" .. pname,
300                 harvest = mname .. ":" .. pname
301         }
302         return r
303 end