1 -- Minetest 0.4 mod: default
2 -- See README.txt for licensing and other information.
3 local init
= os
.clock()
5 -- Simple flower template
6 local smallflowerlongdesc
= "This is a small flower. Small flowers are mainly used for dye production and can also be potted."
7 local plant_usage_help
= "It can only be placed on a block on which it would also survive."
9 -- on_place function for flowers
10 local on_place_flower
= mcl_util
.generate_on_place_plant_function(function(pos
, node
, itemstack
)
11 local below
= {x
=pos
.x
, y
=pos
.y
-1, z
=pos
.z
}
12 local soil_node
= minetest
.get_node_or_nil(below
)
13 if not soil_node
then return false end
15 local has_palette
= minetest
.registered_nodes
[itemstack
:get_name()].palette
~= nil
17 if has_palette
and (soil_node
.name
== "mcl_core:dirt_with_dry_grass" or soil_node
.name
== "mcl_core:dirt_with_dry_grass_snow") then
21 --[[ Placement requirements:
23 * If not flower, also allowed on podzol and coarse dirt
24 * Light level >= 8 at any time or exposed to sunlight at day
26 local light_night
= minetest
.get_node_light(pos
, 0.0)
27 local light_day
= minetest
.get_node_light(pos
, 0.5)
28 local light_ok
= false
29 if (light_night
and light_night
>= 8) or (light_day
and light_day
>= minetest
.LIGHT_MAX
) then
32 local is_flower
= minetest
.get_item_group(itemstack
:get_name(), "flower") == 1
33 local ok
= (soil_node
.name
== "mcl_core:dirt" or minetest
.get_item_group(soil_node
.name
, "grass_block") == 1 or (not is_flower
and (soil_node
.name
== "mcl_core:coarse_dirt" or soil_node
.name
== "mcl_core:podzol" or soil_node
.name
== "mcl_core:podzol_snow"))) and light_ok
37 local function add_simple_flower(name
, desc
, image
, simple_selection_box
)
38 minetest
.register_node("mcl_flowers:"..name
, {
40 _doc_items_longdesc
= smallflowerlongdesc
,
41 _doc_items_usagehelp
= plant_usage_help
,
42 drawtype
= "plantlike",
44 tiles
= { image
..".png" },
45 inventory_image
= image
..".png",
46 wield_image
= image
..".png",
47 sunlight_propagates
= true,
51 groups
= {dig_immediate
=3,flammable
=2,plant
=1,flower
=1,place_flowerlike
=1,non_mycelium_plant
=1,attached_node
=1,dig_by_water
=1,destroy_by_lava_flow
=1,dig_by_piston
=1,enderman_takable
=1,deco_block
=1},
52 sounds
= mcl_sounds
.node_sound_leaves_defaults(),
53 node_placement_prediction
= "",
54 on_place
= on_place_flower
,
57 fixed
= simple_selection_box
,
62 add_simple_flower("poppy", "Poppy", "mcl_flowers_poppy", { -5/16, -0.5, -5/16, 5/16, 5/16, 5/16 })
63 add_simple_flower("dandelion", "Dandelion", "flowers_dandelion_yellow", { -4/16, -0.5, -4/16, 4/16, 3/16, 4/16 })
64 add_simple_flower("oxeye_daisy", "Oxeye Daisy", "mcl_flowers_oxeye_daisy", { -4/16, -0.5, -4/16, 4/16, 4/16, 4/16 })
65 add_simple_flower("tulip_orange", "Orange Tulip", "flowers_tulip", { -3/16, -0.5, -3/16, 3/16, 5/16, 3/16 })
66 add_simple_flower("tulip_pink", "Pink Tulip", "mcl_flowers_tulip_pink", { -3/16, -0.5, -3/16, 3/16, 5/16, 3/16 })
67 add_simple_flower("tulip_red", "Red Tulip", "mcl_flowers_tulip_red", { -3/16, -0.5, -3/16, 3/16, 6/16, 3/16 })
68 add_simple_flower("tulip_white", "White Tulip", "mcl_flowers_tulip_white", { -3/16, -0.5, -3/16, 3/16, 4/16, 3/16 })
69 add_simple_flower("allium", "Allium", "mcl_flowers_allium", { -5/16, -0.5, -5/16, 5/16, 6/16, 5/16 })
70 add_simple_flower("azure_bluet", "Azure Bluet", "mcl_flowers_azure_bluet", { -5/16, -0.5, -5/16, 5/16, 3/16, 5/16 })
71 add_simple_flower("blue_orchid", "Blue Orchid", "mcl_flowers_blue_orchid", { -5/16, -0.5, -5/16, 5/16, 7/16, 5/16 })
74 local wheat_seed_drop
= {
78 items
= {'mcl_farming:wheat_seeds'},
84 -- CHECKME: How does tall grass behave when pushed by a piston?
87 local def_tallgrass
= {
88 description
= "Tall Grass",
89 drawtype
= "plantlike",
90 _doc_items_longdesc
= "Tall grass is a small plant which often occours on the surface of grasslands. It can be harvested for wheat seeds. By using bone meal, tall grass can be turned into double tallgrass which is two blocks high.",
91 _doc_items_usagehelp
= plant_usage_help
,
92 _doc_items_hidden
= false,
94 tiles
= {"mcl_flowers_tallgrass.png"},
95 inventory_image
= "mcl_flowers_tallgrass_inv.png",
96 wield_image
= "mcl_flowers_tallgrass_inv.png",
99 fixed
= {{ -6/16, -8/16, -6/16, 6/16, 4/16, 6/16 }},
102 paramtype2
= "color",
103 palette
= "mcl_core_palette_grass.png",
104 sunlight_propagates
= true,
107 is_ground_content
= true,
108 groups
= {dig_immediate
=3, flammable
=3,attached_node
=1,plant
=1,place_flowerlike
=2,non_mycelium_plant
=1,dig_by_water
=1,destroy_by_lava_flow
=1,deco_block
=1},
109 sounds
= mcl_sounds
.node_sound_leaves_defaults(),
110 drop
= wheat_seed_drop
,
111 _mcl_shears_drop
= true,
112 node_placement_prediction
= "",
113 on_place
= on_place_flower
,
114 _mcl_blast_resistance
= 0,
117 minetest
.register_node("mcl_flowers:tallgrass", def_tallgrass
)
120 -- The fern is very similar to tall grass, so we can copy a lot from it.
121 local def_fern
= table.copy(def_tallgrass
)
122 def_fern
.description
= "Fern"
123 def_fern
._doc_items_longdesc
= "Ferns are small plants which occour naturally in grasslands. They can be harvested for wheat seeds. By using bone meal, a fern can be turned into a large fern which is two blocks high."
124 def_fern
.tiles
= { "mcl_flowers_fern.png" }
125 def_fern
.inventory_image
= "mcl_flowers_fern_inv.png"
126 def_fern
.wield_image
= "mcl_flowers_fern_inv.png"
127 def_fern
.selection_box
= {
129 fixed
= { -6/16, -0.5, -6/16, 6/16, 5/16, 6/16 },
132 minetest
.register_node("mcl_flowers:fern", def_fern
)
134 local function add_large_plant(name
, desc
, longdesc
, bottom_img
, top_img
, inv_img
, selbox_radius
, selbox_top_height
, drop
, shears_drop
, is_flower
, grass_color
)
138 local flowergroup
, place_flowerlike
, usagehelp
, noncreative
, create_entry
, paramtype2
, palette
139 if is_flower
== nil then
150 palette
= "mcl_core_palette_grass.png"
152 if longdesc
== nil then
156 -- Drop itself by default
157 local drop_bottom
, drop_top
159 drop_top
= "mcl_flowers:"..name
164 minetest
.register_node("mcl_flowers:"..name
, {
166 _doc_items_create_entry
= create_entry
,
167 _doc_items_longdesc
= longdesc
,
168 _doc_items_usagehelp
= plant_usage_help
,
169 drawtype
= "plantlike",
170 tiles
= { bottom_img
},
171 inventory_image
= inv_img
,
172 wield_image
= inv_img
,
173 sunlight_propagates
= true,
175 paramtype2
= paramtype2
,
180 _mcl_shears_drop
= shears_drop
,
181 node_placement_prediction
= "",
184 fixed
= { -selbox_radius
, -0.5, -selbox_radius
, selbox_radius
, 0.5, selbox_radius
},
186 on_place
= function(itemstack
, placer
, pointed_thing
)
187 -- We can only place on nodes
188 if pointed_thing
.type ~= "node" then
192 local itemstring
= "mcl_flowers:"..name
194 -- Call on_rightclick if the pointed node defines it
195 local node
= minetest
.get_node(pointed_thing
.under
)
196 if placer
and not placer
:get_player_control().sneak
then
197 if minetest
.registered_nodes
[node
.name
] and minetest
.registered_nodes
[node
.name
].on_rightclick
then
198 return minetest
.registered_nodes
[node
.name
].on_rightclick(pointed_thing
.under
, node
, placer
, itemstack
) or itemstack
202 -- Check for a floor and a space of 1×2×1
203 local ptu_node
= minetest
.get_node(pointed_thing
.under
)
205 if not minetest
.registered_nodes
[ptu_node
.name
] then
208 if minetest
.registered_nodes
[ptu_node
.name
].buildable_to
then
209 bottom
= pointed_thing
.under
211 bottom
= pointed_thing
.above
213 if not minetest
.registered_nodes
[minetest
.get_node(bottom
).name
] then
216 local top
= { x
= bottom
.x
, y
= bottom
.y
+ 1, z
= bottom
.z
}
217 local bottom_buildable
= minetest
.registered_nodes
[minetest
.get_node(bottom
).name
].buildable_to
218 local top_buildable
= minetest
.registered_nodes
[minetest
.get_node(top
).name
].buildable_to
219 local floorname
= minetest
.get_node({x
=bottom
.x
, y
=bottom
.y
-1, z
=bottom
.z
}).name
220 if not minetest
.registered_nodes
[floorname
] then
224 local light_night
= minetest
.get_node_light(bottom
, 0.0)
225 local light_day
= minetest
.get_node_light(bottom
, 0.5)
226 local light_ok
= false
227 if (light_night
and light_night
>= 8) or (light_day
and light_day
>= minetest
.LIGHT_MAX
) then
232 -- * Allowed on dirt or grass block
233 -- * If not a flower, also allowed on podzol and coarse dirt
234 -- * Only with light level >= 8
235 -- * Only if two enough space
236 if (floorname
== "mcl_core:dirt" or minetest
.get_item_group(floorname
, "grass_block") == 1 or (not is_flower
and (floorname
== "mcl_core:coarse_dirt" or floorname
== "mcl_core:podzol" or floorname
== "mcl_core:podzol_snow"))) and bottom_buildable
and top_buildable
and light_ok
then
238 if grass_color
and (floorname
== "mcl_core:dirt_with_dry_grass" or floorname
== "mcl_core:dirt_with_dry_grass_snow") then
241 -- Success! We can now place the flower
242 minetest
.sound_play(minetest
.registered_nodes
[itemstring
].sounds
.place
, {pos
= bottom
, gain
=1})
243 minetest
.set_node(bottom
, {name
=itemstring
, param2
=param2
})
244 minetest
.set_node(top
, {name
=itemstring
.."_top", param2
=param2
})
245 if not minetest
.settings
:get_bool("creative_mode") then
246 itemstack
:take_item()
251 after_destruct
= function(pos
, oldnode
)
252 -- Remove top half of flower (if it exists)
254 local top
= { x
= bottom
.x
, y
= bottom
.y
+ 1, z
= bottom
.z
}
255 if minetest
.get_node(bottom
).name
~= "mcl_flowers:"..name
and minetest
.get_node(top
).name
== "mcl_flowers:"..name
.."_top" then
256 minetest
.remove_node(top
)
259 groups
= {dig_immediate
=3,flammable
=2,flower
=flowergroup
,place_flowerlike
=place_flowerlike
,non_mycelium_plant
=1,attached_node
=1, dig_by_water
=1,destroy_by_lava_flow
=1,dig_by_piston
=1, plant
=1,double_plant
=1,deco_block
=1,not_in_creative_inventory
=noncreative
},
260 sounds
= mcl_sounds
.node_sound_leaves_defaults(),
264 minetest
.register_node("mcl_flowers:"..name
.."_top", {
265 description
= desc
.." (Top Part)",
266 _doc_items_create_entry
= false,
267 drawtype
= "plantlike",
269 sunlight_propagates
= true,
271 paramtype2
= paramtype2
,
277 fixed
= { -selbox_radius
, -0.5, -selbox_radius
, selbox_radius
, selbox_top_height
, selbox_radius
},
280 _mcl_shears_drop
= shears_drop
,
281 after_destruct
= function(pos
, oldnode
)
282 -- Remove bottom half of flower (if it exists)
284 local bottom
= { x
= top
.x
, y
= top
.y
- 1, z
= top
.z
}
285 if minetest
.get_node(top
).name
~= "mcl_flowers:"..name
.."_top" and minetest
.get_node(bottom
).name
== "mcl_flowers:"..name
then
286 minetest
.remove_node(bottom
)
289 groups
= {dig_immediate
=3,flammable
=2,flower
=flowergroup
,place_flowerlike
=place_flowerlike
,dig_by_water
=1,destroy_by_lava_flow
=1,dig_by_piston
=1, not_in_creative_inventory
= 1, plant
=1,double_plant
=2},
290 sounds
= mcl_sounds
.node_sound_leaves_defaults(),
293 if minetest
.get_modpath("doc") and longdesc
then
294 doc
.add_entry_alias("nodes", "mcl_flowers:"..name
, "nodes", "mcl_flowers:"..name
.."_top")
295 -- If no longdesc, help alias must be added manually
300 add_large_plant("peony", "Peony", "A peony is a large plant which occupies two blocks. It is mainly used in dye protection.", "mcl_flowers_double_plant_paeonia_bottom.png", "mcl_flowers_double_plant_paeonia_top.png", nil, 5/16, 6/16)
301 add_large_plant("rose_bush", "Rose Bush", "A rose bush is a large plant which occupies two blocks. It is safe to touch it. Rose bushes are mainly used in dye protection.", "mcl_flowers_double_plant_rose_bottom.png", "mcl_flowers_double_plant_rose_top.png", nil, 5/16, 1/16)
302 add_large_plant("lilac", "Lilac", "A lilac is a large plant which occupies two blocks. It is mainly used in dye production.", "mcl_flowers_double_plant_syringa_bottom.png", "mcl_flowers_double_plant_syringa_top.png", nil, 5/16, 6/16)
304 -- TODO: Make the sunflower face East. Requires a mesh for the top node.
305 add_large_plant("sunflower", "Sunflower", "A sunflower is a large plant which occupies two blocks. It is mainly used in dye production.", "mcl_flowers_double_plant_sunflower_bottom.png", "mcl_flowers_double_plant_sunflower_top.png^mcl_flowers_double_plant_sunflower_front.png", "mcl_flowers_double_plant_sunflower_front.png", 6/16, 6/16)
307 local longdesc_grass
= "Double tallgrass a variant of tall grass and occupies two blocks. It can be harvested for wheat seeds."
308 local longdesc_fern
= "Large fern is a variant of fern and occupies two blocks. It can be harvested for wheat seeds."
310 add_large_plant("double_grass", "Double Tallgrass", longdesc_grass
, "mcl_flowers_double_plant_grass_bottom.png", "mcl_flowers_double_plant_grass_top.png", "mcl_flowers_double_plant_grass_inv.png", 6/16, 4/16, wheat_seed_drop
, {"mcl_flowers:tallgrass 2"}, false, true)
311 add_large_plant("double_fern", "Large Fern", longdesc_fern
, "mcl_flowers_double_plant_fern_bottom.png", "mcl_flowers_double_plant_fern_top.png", "mcl_flowers_double_plant_fern_inv.png", 5/16, 5/16, wheat_seed_drop
, {"mcl_flowers:fern 2"}, false, true)
313 minetest
.register_abm({
314 label
= "Pop out flowers",
315 nodenames
= {"group:flower"},
318 action
= function(pos
, node
)
319 -- Ignore the upper part of double plants
320 if minetest
.get_item_group(node
.name
, "double_plant") == 2 then
323 local below
= minetest
.get_node_or_nil({x
=pos
.x
, y
=pos
.y
-1, z
=pos
.z
})
327 -- Pop out flower if not on dirt, grass block or too low brightness
328 if (below
.name
~= "mcl_core:dirt" and minetest
.get_item_group(below
.name
, "grass_block") ~= 1) or (minetest
.get_node_light(pos
, 0.5) < 8) then
329 minetest
.dig_node(pos
)
337 minetest
.register_node("mcl_flowers:waterlily", {
338 description
= "Lily Pad",
339 _doc_items_longdesc
= "A lily pad is a flat plant block which can be walked on. They can be placed on water sources, ice and frosted ice.",
340 drawtype
= "nodebox",
342 paramtype2
= "facedir",
343 tiles
= {"flowers_waterlily.png", "flowers_waterlily.png^[transformFY"},
344 inventory_image
= "flowers_waterlily.png",
345 wield_image
= "flowers_waterlily.png",
346 liquids_pointable
= true,
348 sunlight_propagates
= true,
349 groups
= {dig_immediate
= 3, plant
=1, dig_by_water
= 1,destroy_by_lava_flow
=1, dig_by_piston
= 1, deco_block
=1},
350 sounds
= mcl_sounds
.node_sound_leaves_defaults(),
351 node_placement_prediction
= "",
354 fixed
= {-0.5, -31/64, -0.5, 0.5, -15/32, 0.5}
358 fixed
= {-7 / 16, -0.5, -7 / 16, 7 / 16, -15 / 32, 7 / 16}
361 on_place
= function(itemstack
, placer
, pointed_thing
)
362 local pos
= pointed_thing
.above
363 local node
= minetest
.get_node(pointed_thing
.under
)
364 local nodename
= node
.name
365 local def
= minetest
.registered_nodes
[nodename
]
366 local node_above
= minetest
.get_node(pointed_thing
.above
).name
367 local def_above
= minetest
.registered_nodes
[node_above
]
368 local player_name
= placer
:get_player_name()
371 -- Use pointed node's on_rightclick function first, if present
372 if placer
and not placer
:get_player_control().sneak
then
373 if def
and def
.on_rightclick
then
374 return def
.on_rightclick(pointed_thing
.under
, node
, placer
, itemstack
) or itemstack
378 if (pointed_thing
.under
.x
== pointed_thing
.above
.x
and pointed_thing
.under
.z
== pointed_thing
.above
.z
) and
379 ((def
.liquidtype
== "source" and minetest
.get_item_group(nodename
, "water") > 0) or
380 (nodename
== "mcl_core:ice") or
381 (minetest
.get_item_group(nodename
, "frosted_ice") > 0)) and
382 (def_above
.buildable_to
and minetest
.get_item_group(node_above
, "liquid") == 0) then
383 if not minetest
.is_protected(pos
, player_name
) then
384 minetest
.set_node(pos
, {name
= "mcl_flowers:waterlily", param2
= math
.random(0, 3)})
385 local idef
= itemstack
:get_definition()
387 if idef
.sounds
and idef
.sounds
.place
then
388 minetest
.sound_play(idef
.sounds
.place
, {pos
=above
, gain
=1})
391 if not minetest
.settings
:get_bool("creative_mode") then
392 itemstack
:take_item()
395 minetest
.chat_send_player(player_name
, "Node is protected")
396 minetest
.record_protection_violation(pos
, player_name
)
406 minetest
.register_alias("mcl_core:tallgrass", "mcl_flowers:tallgrass")
409 local time_to_load
= os
.clock() - init
410 print(string.format("[MOD] "..minetest
.get_current_modname().." loaded in %.4f s", time_to_load
))