3 function mcl_farming
:add_plant(identifier
, full_grown
, names
, interval
, chance
)
4 plant_lists
[identifier
] = {}
5 plant_lists
[identifier
].full_grown
= full_grown
6 plant_lists
[identifier
].names
= names
7 minetest
.register_abm({
8 label
= string.format("Farming plant growth (%s)", identifier
),
12 action
= function(pos
, node
)
13 if minetest
.get_node({x
=pos
.x
, y
=pos
.y
-1, z
=pos
.z
}).name
~= "mcl_farming:soil_wet" and math
.random(0, 9) > 0 then
16 mcl_farming
:grow_plant(identifier
, pos
, node
)
22 -- Attempts to advance a plant at pos by one or more growth stages (if possible)
23 -- identifier: Identifier of plant as defined by mcl_farming:add_plant
26 -- stages: Number of stages to advance (optional, defaults to 1)
28 -- Returns true if plant has been grown by 1 or more stages.
29 -- Returns false if nothing changed.
30 function mcl_farming
:grow_plant(identifier
, pos
, node
, stages
)
31 if not minetest
.get_node_light(pos
) then
34 if minetest
.get_node_light(pos
) < 10 then
38 local plant_info
= plant_lists
[identifier
]
41 for i
, name
in ipairs(plant_info
.names
) do
42 if name
== node
.name
then
53 local new_node
= {name
= plant_info
.names
[step
+stages
]}
54 if new_node
.name
== nil then
55 new_node
.name
= plant_info
.full_grown
57 new_node
.param
= node
.param
58 new_node
.param2
= node
.param2
59 minetest
.set_node(pos
, new_node
)
63 function mcl_farming
:place_seed(itemstack
, placer
, pointed_thing
, plantname
)
64 local pt
= pointed_thing
68 if pt
.type ~= "node" then
72 -- Use pointed node's on_rightclick function first, if present
73 local node
= minetest
.get_node(pt
.under
)
74 if placer
and not placer
:get_player_control().sneak
then
75 if minetest
.registered_nodes
[node
.name
] and minetest
.registered_nodes
[node
.name
].on_rightclick
then
76 return minetest
.registered_nodes
[node
.name
].on_rightclick(pt
.under
, node
, placer
, itemstack
) or itemstack
80 local pos
= {x
=pt
.above
.x
, y
=pt
.above
.y
-1, z
=pt
.above
.z
}
81 local farmland
= minetest
.get_node(pos
)
82 pos
= {x
=pt
.above
.x
, y
=pt
.above
.y
, z
=pt
.above
.z
}
83 local place_s
= minetest
.get_node(pos
)
85 if string.find(farmland
.name
, "mcl_farming:soil") and string.find(place_s
.name
, "air") then
86 minetest
.sound_play(minetest
.registered_nodes
[plantname
].sounds
.place
, {pos
= pos
})
87 minetest
.add_node(pos
, {name
=plantname
, param2
= minetest
.registered_nodes
[plantname
].place_param2
})
92 if not minetest
.settings
:get_bool("creative_mode") then
99 --[[ Helper function to create a gourd (e.g. melon, pumpkin), the connected stem nodes as
101 - full_unconnected_stem: itemstring of the full-grown but unconnceted stem node. This node must already be done
102 - connected_stem_basename: prefix of the itemstrings used for the 4 connected stem nodes to create
103 - stem_itemstring: Desired itemstring of the fully-grown unconnected stem node
104 - stem_def: Partial node definition of the fully-grown unconnected stem node. Many fields are already defined. You need to add `tiles` and `description` at minimum. Don't define on_construct without good reason
105 - stem_drop: Drop probability table for all stem
106 - gourd_itemstring: Desired itemstring of the full gourd node
107 - gourd_def: (almost) full definition of the gourd node. This function will add on_construct and after_dig_node to the definition for unconnecting any connected stems
108 - grow_interval: Will attempt to grow a gourd periodically at this interval in seconds
109 - grow_chance: Chance of 1/grow_chance to grow a gourd next to the full unconnected stem after grow_interval has passed. Must be a natural number
110 - connected_stem_texture: Texture of the connected stem
111 - gourd_on_construct_extra: Custom on_construct extra function for the gourd. Will be called after the stem check code
114 function mcl_farming
:add_gourd(full_unconnected_stem
, connected_stem_basename
, stem_itemstring
, stem_def
, stem_drop
, gourd_itemstring
, gourd_def
, grow_interval
, grow_chance
, connected_stem_texture
, gourd_on_construct_extra
)
116 local connected_stem_names
= {
117 connected_stem_basename
.. "_r",
118 connected_stem_basename
.. "_l",
119 connected_stem_basename
.. "_t",
120 connected_stem_basename
.. "_b",
130 -- Connect the stem at stempos to the first neighboring gourd block.
131 -- No-op if not a stem or no gourd block found
132 local try_connect_stem
= function(stempos
)
133 local stem
= minetest
.get_node(stempos
)
134 if stem
.name
~= full_unconnected_stem
then
137 for n
=1, #neighbors
do
138 local offset
= neighbors
[n
]
139 local blockpos
= vector
.add(stempos
, offset
)
140 local block
= minetest
.get_node(blockpos
)
141 if block
.name
== gourd_itemstring
then
142 if offset
.x
== 1 then
143 minetest
.set_node(stempos
, {name
=connected_stem_names
[1]})
144 elseif offset
.x
== -1 then
145 minetest
.set_node(stempos
, {name
=connected_stem_names
[2]})
146 elseif offset
.z
== 1 then
147 minetest
.set_node(stempos
, {name
=connected_stem_names
[3]})
148 elseif offset
.z
== -1 then
149 minetest
.set_node(stempos
, {name
=connected_stem_names
[4]})
157 if not gourd_def
.after_dig_node
then
158 gourd_def
.after_dig_node
= function(blockpos
, oldnode
, oldmetadata
, user
)
159 -- Disconnect any connected stems, turning them back to normal stems
160 for n
=1, #neighbors
do
161 local offset
= neighbors
[n
]
162 local expected_stem
= connected_stem_names
[n
]
163 local stempos
= vector
.add(blockpos
, offset
)
164 local stem
= minetest
.get_node(stempos
)
165 if stem
.name
== expected_stem
then
166 minetest
.add_node(stempos
, {name
=full_unconnected_stem
})
167 try_connect_stem(stempos
)
172 if not gourd_def
.on_construct
then
173 gourd_def
.on_construct
= function(blockpos
)
174 -- Connect all unconnected stems at full size
175 for n
=1, #neighbors
do
176 local stempos
= vector
.add(blockpos
, neighbors
[n
])
177 try_connect_stem(stempos
)
179 -- Call custom on_construct
180 if gourd_on_construct_extra
then
181 gourd_on_construct_extra(blockpos
)
185 minetest
.register_node(gourd_itemstring
, gourd_def
)
187 -- Register unconnected stem
189 -- Default values for the stem definition
190 if not stem_def
.selection_box
then
191 stem_def
.selection_box
= {
194 {-0.15, -0.5, -0.15, 0.15, 0.5, 0.15}
198 if not stem_def
.paramtype
then
199 stem_def
.paramtype
= "light"
201 if not stem_def
.drawtype
then
202 stem_def
.drawtype
= "plantlike"
204 if stem_def
.walkable
== nil then
205 stem_def
.walkable
= false
207 if stem_def
.sunlight_propagates
== nil then
208 stem_def
.sunlight_propagates
= true
210 if stem_def
.drop
== nil then
211 stem_def
.drop
= stem_drop
213 if stem_def
.groups
== nil then
214 stem_def
.groups
= {dig_immediate
=3, not_in_creative_inventory
=1, plant
=1,attached_node
=1, dig_by_water
=1,destroy_by_lava_flow
=1,}
216 if stem_def
.sounds
== nil then
217 stem_def
.sounds
= mcl_sounds
.node_sound_leaves_defaults()
220 if not stem_def
.on_construct
then
221 stem_def
.on_construct
= function(stempos
)
222 -- Connect stem to gourd (if possible)
223 try_connect_stem(stempos
)
226 minetest
.register_node(stem_itemstring
, stem_def
)
228 -- Register connected stems
230 local connected_stem_tiles
= {
232 "blank.png", -- bottom
233 "blank.png", -- right
235 connected_stem_texture
, -- back
236 connected_stem_texture
.."^[transformFX90" --front
239 "blank.png", -- bottom
240 "blank.png", -- right
242 connected_stem_texture
.."^[transformFX90", --back
243 connected_stem_texture
, -- front
246 "blank.png", -- bottom
247 connected_stem_texture
.."^[transformFX90", -- right
248 connected_stem_texture
, -- left
250 "blank.png", -- front
253 "blank.png", -- bottom
254 connected_stem_texture
, -- right
255 connected_stem_texture
.."^[transformFX90", -- left
257 "blank.png", -- front
260 local connected_stem_nodebox
= {
261 {-0.5, -0.5, 0, 0.5, 0.5, 0},
262 {-0.5, -0.5, 0, 0.5, 0.5, 0},
263 {0, -0.5, -0.5, 0, 0.5, 0.5},
264 {0, -0.5, -0.5, 0, 0.5, 0.5},
266 local connected_stem_selectionbox
= {
267 {-0.1, -0.5, -0.1, 0.5, 0.2, 0.1},
268 {-0.5, -0.5, -0.1, 0.1, 0.2, 0.1},
269 {-0.1, -0.5, -0.1, 0.1, 0.2, 0.5},
270 {-0.1, -0.5, -0.5, 0.1, 0.2, 0.1},
274 minetest
.register_node(connected_stem_names
[i
], {
275 _doc_items_create_entry
= false,
277 sunlight_propagates
= true,
280 drawtype
= "nodebox",
283 fixed
= connected_stem_nodebox
[i
]
287 fixed
= connected_stem_selectionbox
[i
]
289 tiles
= connected_stem_tiles
[i
],
290 groups
= {dig_immediate
=3, not_in_creative_inventory
=1, plant
=1,attached_node
=1, dig_by_water
=1,destroy_by_lava_flow
=1,},
291 sounds
= mcl_sounds
.node_sound_leaves_defaults(),
292 _mcl_blast_resistance
= 0,
295 if minetest
.get_modpath("doc") then
296 doc
.add_entry_alias("nodes", full_unconnected_stem
, "nodes", connected_stem_names
[i
])
300 minetest
.register_abm({
301 label
= "Grow gourd stem to gourd ("..full_unconnected_stem
.." → "..gourd_itemstring
..")",
302 nodenames
= {full_unconnected_stem
},
304 interval
= grow_interval
,
305 chance
= grow_chance
,
306 action
= function(stempos
)
307 local light
= minetest
.get_node_light(stempos
)
308 if light
and light
> 10 then
309 -- Check the four neighbors and filter out neighbors where gourds can't grow
316 local floorpos
, floor
317 for n
=#neighbors
, 1, -1 do
318 local offset
= neighbors
[n
]
319 local blockpos
= vector
.add(stempos
, offset
)
320 floorpos
= { x
=blockpos
.x
, y
=blockpos
.y
-1, z
=blockpos
.z
}
321 floor = minetest
.get_node(floorpos
)
322 local block
= minetest
.get_node(blockpos
)
323 local soilgroup
= minetest
.get_item_group(floor.name
, "soil")
324 if not ((minetest
.get_item_group(floor.name
, "grass_block") == 1 or floor.name
=="mcl_core:dirt" or soilgroup
== 2 or soilgroup
== 3) and block
.name
== "air") then
325 table.remove(neighbors
, n
)
329 -- Gourd needs at least 1 free neighbor to grow
330 if #neighbors
> 0 then
331 -- From the remaining neighbors, grow randomly
332 local r
= math
.random(1, #neighbors
)
333 local offset
= neighbors
[r
]
334 local blockpos
= vector
.add(stempos
, offset
)
336 if offset
.x
== 1 then
337 minetest
.set_node(stempos
, {name
=connected_stem_names
[1]})
339 elseif offset
.x
== -1 then
340 minetest
.set_node(stempos
, {name
=connected_stem_names
[2]})
342 elseif offset
.z
== 1 then
343 minetest
.set_node(stempos
, {name
=connected_stem_names
[3]})
345 elseif offset
.z
== -1 then
346 minetest
.set_node(stempos
, {name
=connected_stem_names
[4]})
350 if gourd_def
.paramtype2
== "facedir" then
351 minetest
.add_node(blockpos
, {name
=gourd_itemstring
, param2
=p2
})
353 minetest
.add_node(blockpos
, {name
=gourd_itemstring
})
355 -- Reset farmland, etc. to dirt when the gourd grows on top
356 if minetest
.get_item_group(floor.name
, "dirtifies_below_solid") == 1 then
357 minetest
.set_node(floorpos
, {name
= "mcl_core:dirt"})
365 -- Used for growing gourd stems. Returns the intermediate color between startcolor and endcolor at a step
366 -- * startcolor: ColorSpec in table form for the stem in its lowest growing stage
367 -- * endcolor: ColorSpec in table form for the stem in its final growing stage
368 -- * step: The nth growth step. Counting starts at 1
369 -- * step_count: The number of total growth steps
370 function mcl_farming
:stem_color(startcolor
, endcolor
, step
, step_count
)
372 local function get_component(startt
, endd
, step
, step_count
)
373 return math
.floor(math
.max(0, math
.min(255, (startt
+ (((step
-1)/step_count
) * endd
)))))
375 color
.r
= get_component(startcolor
.r
, endcolor
.r
, step
, step_count
)
376 color
.g
= get_component(startcolor
.g
, endcolor
.g
, step
, step_count
)
377 color
.b
= get_component(startcolor
.b
, endcolor
.b
, step
, step_count
)
378 local colorstring
= string.format("#%02X%02X%02X", color
.r
, color
.g
, color
.b
)