Use hardware coloring for tallgrass and friends
[MineClone/MineClone2.git] / mods / ITEMS / mcl_flowers / init.lua
blob8c793f16605814f23297ffbd3aae1648bf1551db
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
16 local colorize = 0
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
18 colorize = 1
19 end
21 --[[ Placement requirements:
22 * Dirt or grass block
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
30 light_ok = true
31 end
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
34 return ok, colorize
35 end)
37 local function add_simple_flower(name, desc, image, simple_selection_box)
38 minetest.register_node("mcl_flowers:"..name, {
39 description = desc,
40 _doc_items_longdesc = smallflowerlongdesc,
41 _doc_items_usagehelp = plant_usage_help,
42 drawtype = "plantlike",
43 waving = 1,
44 tiles = { image..".png" },
45 inventory_image = image..".png",
46 wield_image = image..".png",
47 sunlight_propagates = true,
48 paramtype = "light",
49 walkable = false,
50 stack_max = 64,
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,
55 selection_box = {
56 type = "fixed",
57 fixed = simple_selection_box,
60 end
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 = {
75 max_items = 1,
76 items = {
78 items = {'mcl_farming:wheat_seeds'},
79 rarity = 8,
84 -- CHECKME: How does tall grass behave when pushed by a piston?
86 --- Tall Grass ---
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,
93 waving = 1,
94 tiles = {"mcl_flowers_tallgrass.png"},
95 inventory_image = "mcl_flowers_tallgrass_inv.png",
96 wield_image = "mcl_flowers_tallgrass_inv.png",
97 selection_box = {
98 type = "fixed",
99 fixed = {{ -6/16, -8/16, -6/16, 6/16, 4/16, 6/16 }},
101 paramtype = "light",
102 paramtype2 = "color",
103 palette = "mcl_core_palette_grass.png",
104 sunlight_propagates = true,
105 walkable = false,
106 buildable_to = 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,
115 _mcl_hardness = 0,
117 minetest.register_node("mcl_flowers:tallgrass", def_tallgrass)
119 --- Fern ---
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 = {
128 type = "fixed",
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)
135 if not inv_img then
136 inv_img = top_img
138 local flowergroup, place_flowerlike, usagehelp, noncreative, create_entry, paramtype2, palette
139 if is_flower == nil then
140 is_flower = true
142 if is_flower then
143 flowergroup = 1
144 place_flowerlike = 1
145 else
146 place_flowerlike = 2
148 if grass_color then
149 paramtype2 = "color"
150 palette = "mcl_core_palette_grass.png"
152 if longdesc == nil then
153 noncreative = 1
154 create_entry = false
156 -- Drop itself by default
157 local drop_bottom, drop_top
158 if not drop then
159 drop_top = "mcl_flowers:"..name
160 else
161 drop_top = drop
162 drop_bottom = drop
164 minetest.register_node("mcl_flowers:"..name, {
165 description = desc,
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,
174 paramtype = "light",
175 paramtype2 = paramtype2,
176 palette = palette,
177 walkable = false,
178 buildable_to = true,
179 drop = drop_bottom,
180 _mcl_shears_drop = shears_drop,
181 node_placement_prediction = "",
182 selection_box = {
183 type = "fixed",
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
189 return
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)
204 local bottom
205 if not minetest.registered_nodes[ptu_node.name] then
206 return itemstack
208 if minetest.registered_nodes[ptu_node.name].buildable_to then
209 bottom = pointed_thing.under
210 else
211 bottom = pointed_thing.above
213 if not minetest.registered_nodes[minetest.get_node(bottom).name] then
214 return itemstack
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
221 return itemstack
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
228 light_ok = true
231 -- Placement rules:
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
237 local param2
238 if grass_color and (floorname == "mcl_core:dirt_with_dry_grass" or floorname == "mcl_core:dirt_with_dry_grass_snow") then
239 param2 = 1
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()
249 return itemstack
250 end,
251 after_destruct = function(pos, oldnode)
252 -- Remove top half of flower (if it exists)
253 local bottom = pos
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)
258 end,
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(),
263 -- Top
264 minetest.register_node("mcl_flowers:"..name.."_top", {
265 description = desc.." (Top Part)",
266 _doc_items_create_entry = false,
267 drawtype = "plantlike",
268 tiles = { top_img },
269 sunlight_propagates = true,
270 paramtype = "light",
271 paramtype2 = paramtype2,
272 palette = palette,
273 walkable = false,
274 buildable_to = true,
275 selection_box = {
276 type = "fixed",
277 fixed = { -selbox_radius, -0.5, -selbox_radius, selbox_radius, selbox_top_height, selbox_radius },
279 drop = drop_top,
280 _mcl_shears_drop = shears_drop,
281 after_destruct = function(pos, oldnode)
282 -- Remove bottom half of flower (if it exists)
283 local top = pos
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)
288 end,
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"},
316 interval = 12,
317 chance = 2,
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
321 return
323 local below = minetest.get_node_or_nil({x=pos.x, y=pos.y-1, z=pos.z})
324 if not below then
325 return
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)
330 return
332 end,
336 -- Lily Pad
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",
341 paramtype = "light",
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,
347 walkable = 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 = "",
352 node_box = {
353 type = "fixed",
354 fixed = {-0.5, -31/64, -0.5, 0.5, -15/32, 0.5}
356 selection_box = {
357 type = "fixed",
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()
370 if def then
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()
394 else
395 minetest.chat_send_player(player_name, "Node is protected")
396 minetest.record_protection_violation(pos, player_name)
401 return itemstack
405 -- Legacy support
406 minetest.register_alias("mcl_core:tallgrass", "mcl_flowers:tallgrass")
408 -- Show loading time
409 local time_to_load= os.clock() - init
410 print(string.format("[MOD] "..minetest.get_current_modname().." loaded in %.4f s", time_to_load))