init.lua 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765
  1. -- Minetest 0.4 mod: default
  2. -- See README.txt for licensing and other information.
  3. -- Mod is reloadable.
  4. -- Namespace for functions
  5. flowers = flowers or {}
  6. flowers.modpath = minetest.get_modpath("flowers")
  7. flowers.flora_mintime = 60*3
  8. flowers.flora_maxtime = 60*30
  9. function flowers.flora_density_for_surface(pos)
  10. local cold = 0
  11. if minetest.find_node_near(pos, 2, {
  12. "group:snow",
  13. "group:snowy",
  14. "group:ice",
  15. "group:cold",
  16. }) then
  17. cold = -2
  18. end
  19. -- Heat makes plants grow denser.
  20. local heat = 0
  21. if minetest.find_node_near(pos, 3, "group:melt_around") then
  22. heat = 1
  23. end
  24. -- Minerals improve flower growth.
  25. local minerals = 0
  26. if minetest.find_node_near(pos, 3, "glowstone:minerals") then
  27. minerals = 1
  28. end
  29. -- The presence of water increases the flower density.
  30. local water = 0
  31. if minetest.find_node_near(pos, 3, "group:water") then
  32. water = 1
  33. end
  34. -- Lush grass is better for flora than other grasses.
  35. if minetest.get_node(pos).name == "moregrass:darkgrass" then
  36. return 4 + water + minerals + heat + cold
  37. end
  38. -- Default flower density.
  39. return 3 + water + minerals + heat + cold
  40. end
  41. function flowers.surface_can_spawn_flora(pos)
  42. local name = minetest.get_node(pos).name
  43. if minetest.get_item_group(name, "soil") ~= 0 then
  44. -- Including desert sand, or else flora placed there would never turn to dry shrubs.
  45. return true
  46. end
  47. return false
  48. end
  49. function flowers.on_flora_construct(pos)
  50. if flowers.surface_can_spawn_flora({x=pos.x, y=pos.y-1, z=pos.z}) then
  51. minetest.get_node_timer(pos):start(math.random(flowers.flora_mintime, flowers.flora_maxtime))
  52. end
  53. end
  54. function flowers.on_flora_destruct(pos)
  55. -- Notify nearby flora.
  56. local minp = vector.subtract(pos, 4)
  57. local maxp = vector.add(pos, 4)
  58. local flora = minetest.find_nodes_in_area_under_air(minp, maxp, "group:flora")
  59. if flora and #flora > 0 then
  60. for i=1, #flora do
  61. minetest.get_node_timer(flora[i]):start(math.random(flowers.flora_mintime, flowers.flora_maxtime))
  62. end
  63. end
  64. end
  65. function flowers.on_flora_timer(pos, elapsed)
  66. --minetest.chat_send_player("MustTest", "Flora timer @ " .. minetest.pos_to_string(pos) .. "!")
  67. local node = minetest.get_node(pos)
  68. if flowers.flower_spread(pos, node) then
  69. minetest.get_node_timer(pos):start(math.random(flowers.flora_mintime, flowers.flora_maxtime))
  70. else
  71. -- Else timer should stop, cannot grow anymore.
  72. minetest.get_node_timer(pos):stop()
  73. end
  74. end
  75. function flowers.on_flora_punch(pos, node, puncher, pt)
  76. if flowers.surface_can_spawn_flora({x=pos.x, y=pos.y-1, z=pos.z}) then
  77. minetest.get_node_timer(pos):start(math.random(flowers.flora_mintime, flowers.flora_maxtime))
  78. end
  79. end
  80. --
  81. -- Flowers
  82. --
  83. if not flowers.registered then
  84. -- Aliases for original flowers mod
  85. minetest.register_alias("flowers:flower_rose", "flowers:rose")
  86. minetest.register_alias("flowers:flower_tulip", "flowers:tulip")
  87. minetest.register_alias("flowers:flower_dandelion_yellow", "flowers:dandelion_yellow")
  88. minetest.register_alias("flowers:flower_geranium", "flowers:geranium")
  89. minetest.register_alias("flowers:flower_viola", "flowers:viola")
  90. minetest.register_alias("flowers:flower_dandelion_white", "flowers:dandelion_white")
  91. -- Flower registration
  92. local function add_simple_flower(name, desc, box, f_groups)
  93. -- Common flowers' groups
  94. f_groups.flower = 1
  95. f_groups.flora = 1
  96. f_groups.attached_node = 1
  97. -- Flowers are supposed to be flammable! [MustTest]
  98. f_groups.flammable = 3
  99. minetest.register_node(":flowers:" .. name, {
  100. description = desc,
  101. drawtype = "plantlike",
  102. waving = 1,
  103. tiles = {"flowers_" .. name .. ".png"},
  104. inventory_image = "flowers_" .. name .. ".png",
  105. wield_image = "flowers_" .. name .. ".png",
  106. sunlight_propagates = true,
  107. paramtype = "light",
  108. walkable = false,
  109. buildable_to = true,
  110. --stack_max = 99,
  111. groups = utility.dig_groups("plant", f_groups),
  112. sounds = default.node_sound_leaves_defaults(),
  113. selection_box = {
  114. type = "fixed",
  115. fixed = box
  116. },
  117. movement_speed_multiplier = default.SLOW_SPEED_PLANTS,
  118. on_construct = function(...)
  119. return flowers.on_flora_construct(...)
  120. end,
  121. on_destruct = function(...)
  122. return flowers.on_flora_destruct(...)
  123. end,
  124. on_timer = function(...)
  125. return flowers.on_flora_timer(...)
  126. end,
  127. on_punch = function(...)
  128. return flowers.on_flora_punch(...)
  129. end,
  130. })
  131. end
  132. flowers.datas = {
  133. {
  134. "rose",
  135. "Red Rose",
  136. {-2 / 16, -0.5, -2 / 16, 2 / 16, 5 / 16, 2 / 16},
  137. {color_red = 1, flammable = 1}
  138. },
  139. {
  140. "tulip",
  141. "Orange Tulip",
  142. {-2 / 16, -0.5, -2 / 16, 2 / 16, 3 / 16, 2 / 16},
  143. {color_orange = 1, flammable = 1}
  144. },
  145. {
  146. "dandelion_yellow",
  147. "Yellow Dandelion",
  148. {-4 / 16, -0.5, -4 / 16, 4 / 16, -2 / 16, 4 / 16},
  149. {color_yellow = 1, flammable = 1}
  150. },
  151. {
  152. "chrysanthemum_green",
  153. "Green Chrysanthemum",
  154. {-4 / 16, -0.5, -4 / 16, 4 / 16, -1 / 16, 4 / 16},
  155. {color_green = 1, flammable = 1}
  156. },
  157. {
  158. "geranium",
  159. "Blue Geranium",
  160. {-2 / 16, -0.5, -2 / 16, 2 / 16, 2 / 16, 2 / 16},
  161. {color_blue = 1, flammable = 1}
  162. },
  163. {
  164. "viola",
  165. "Viola",
  166. {-5 / 16, -0.5, -5 / 16, 5 / 16, -1 / 16, 5 / 16},
  167. {color_violet = 1, flammable = 1}
  168. },
  169. {
  170. "dandelion_white",
  171. "White Dandelion",
  172. {-5 / 16, -0.5, -5 / 16, 5 / 16, -2 / 16, 5 / 16},
  173. {color_white = 1, flammable = 1}
  174. },
  175. {
  176. "tulip_black",
  177. "Black Tulip",
  178. {-2 / 16, -0.5, -2 / 16, 2 / 16, 3 / 16, 2 / 16},
  179. {color_black = 1, flammable = 1}
  180. },
  181. }
  182. for _,item in pairs(flowers.datas) do
  183. add_simple_flower(unpack(item))
  184. end
  185. flowers.registered = true
  186. end
  187. -- Flower spread
  188. -- Public function to enable override by mods
  189. function flowers.flower_spread(pos, node)
  190. pos.y = pos.y - 1
  191. local under = minetest.get_node(pos)
  192. pos.y = pos.y + 1
  193. -- Replace flora with dry shrub in desert sand and silver sand,
  194. -- as this is the only way to generate them.
  195. -- However, preserve grasses in sand dune biomes.
  196. if minetest.get_item_group(under.name, "sand") == 1 and
  197. under.name ~= "default:sand" then
  198. minetest.add_node(pos, {name = "default:dry_shrub"})
  199. return false
  200. end
  201. if minetest.get_item_group(under.name, "soil") == 0 then
  202. return false
  203. end
  204. local light = minetest.get_node_light(pos) or 0
  205. if light < 13 then
  206. -- Is this just a daytime thing?
  207. if (minetest.get_node_light(pos, 0.5) or 0) < 13 then
  208. return false
  209. else
  210. return true -- Keep trying.
  211. end
  212. end
  213. local density = flowers.flora_density_for_surface({x=pos.x, y=pos.y-1, z=pos.z})
  214. local pos0 = vector.subtract(pos, 4)
  215. local pos1 = vector.add(pos, 4)
  216. if #minetest.find_nodes_in_area(pos0, pos1, "group:flora") > density then
  217. return false -- Max flora reached.
  218. end
  219. local soils = minetest.find_nodes_in_area_under_air(pos0, pos1, "group:soil")
  220. if #soils > 0 then
  221. local seedling = soils[math.random(1, #soils)]
  222. local seedling_above = {x=seedling.x, y=seedling.y+1, z=seedling.z}
  223. local light = minetest.get_node_light(seedling_above) or 0
  224. if light < 13 then
  225. -- Is this just a daytime thing?
  226. if (minetest.get_node_light(seedling_above, 0.5) or 0) < 13 then
  227. return false
  228. else
  229. return true -- Keep trying.
  230. end
  231. end
  232. -- Desert sand is in the soil group.
  233. if minetest.get_node(seedling).name == "default:desert_sand" then
  234. return false
  235. end
  236. minetest.add_node(seedling_above, {name = node.name, param2 = node.param2})
  237. return true
  238. end
  239. return false
  240. end
  241. -- Indexed array.
  242. flowers.mushroom_surfaces = {
  243. "default:dirt",
  244. "rackstone:dauthsand",
  245. "group:soil",
  246. "group:tree",
  247. -- We disable these because they are much too common.
  248. -- Mushroom farms would be too easy to make, especially during a cave survival challenge.
  249. --"group:cavern_soil",
  250. --"darkage:silt",
  251. --"darkage:mud",
  252. }
  253. flowers.mushroom_nodes = {
  254. "flowers:mushroom_red",
  255. "flowers:mushroom_brown",
  256. "cavestuff:mycena",
  257. "cavestuff:fungus",
  258. }
  259. flowers.mushroom_mintime = 60*3
  260. flowers.mushroom_maxtime = 60*30
  261. function flowers.surface_can_spawn_mushroom(pos)
  262. local name = minetest.get_node(pos).name
  263. local nodes = flowers.mushroom_surfaces
  264. for i=1, #nodes do
  265. if string.find(nodes[i], "^group:") then
  266. local group = string.sub(nodes[i], 7)
  267. if minetest.get_item_group(name, group) ~= 0 then
  268. return true
  269. end
  270. elseif nodes[i] == name then
  271. return true
  272. end
  273. end
  274. return false
  275. end
  276. function flowers.on_mushroom_construct(pos)
  277. if flowers.surface_can_spawn_mushroom({x=pos.x, y=pos.y-1, z=pos.z}) then
  278. minetest.get_node_timer(pos):start(math.random(flowers.mushroom_mintime, flowers.mushroom_maxtime))
  279. end
  280. end
  281. function flowers.on_mushroom_destruct(pos)
  282. -- Notify nearby mushrooms.
  283. local minp = {x=pos.x-2, y=pos.y-2, z=pos.z-2}
  284. local maxp = {x=pos.x+2, y=pos.y+1, z=pos.z+2}
  285. local mushrooms = minetest.find_nodes_in_area_under_air(minp, maxp, flowers.mushroom_nodes)
  286. if mushrooms and #mushrooms > 0 then
  287. for i=1, #mushrooms do
  288. minetest.get_node_timer(mushrooms[i]):start(math.random(flowers.mushroom_mintime, flowers.mushroom_maxtime))
  289. end
  290. end
  291. end
  292. function flowers.on_mushroom_timer(pos, elapsed)
  293. --minetest.chat_send_player("MustTest", "Mushroom timer @ " .. minetest.pos_to_string(pos) .. "!")
  294. local node = minetest.get_node(pos)
  295. if flowers.mushroom_spread(pos, node) then
  296. minetest.get_node_timer(pos):start(math.random(flowers.mushroom_mintime, flowers.mushroom_maxtime))
  297. else
  298. -- Else timer should stop, cannot grow anymore.
  299. minetest.get_node_timer(pos):stop()
  300. end
  301. end
  302. function flowers.on_mushroom_punch(pos, node, puncher, pt)
  303. if flowers.surface_can_spawn_mushroom({x=pos.x, y=pos.y-1, z=pos.z}) then
  304. minetest.get_node_timer(pos):start(math.random(flowers.mushroom_mintime, flowers.mushroom_maxtime))
  305. end
  306. end
  307. if not flowers.reg2 then
  308. --
  309. -- Mushrooms
  310. --
  311. local eat_mushroom = minetest.item_eat(1)
  312. local function mushroom_poison(pname, step)
  313. local msg = "# Server: <" .. rename.gpn(pname) .. "> ate a mushroom. Desperate!"
  314. hb4.delayed_harm({name=pname, step=step, min=1, max=1, msg=msg, poison=true})
  315. end
  316. minetest.register_node("flowers:mushroom_red", {
  317. description = "Red Mushroom",
  318. tiles = {"flowers_mushroom_red.png"},
  319. inventory_image = "flowers_mushroom_red.png",
  320. wield_image = "flowers_mushroom_red.png",
  321. drawtype = "plantlike",
  322. paramtype = "light",
  323. sunlight_propagates = true,
  324. walkable = false,
  325. buildable_to = true,
  326. groups = utility.dig_groups("plant", {attached_node = 1, flammable = 1}),
  327. sounds = default.node_sound_leaves_defaults(),
  328. movement_speed_multiplier = default.SLOW_SPEED_PLANTS,
  329. on_use = function(itemstack, user, pointed_thing)
  330. if not user or not user:is_player() then return end
  331. minetest.after(1, mushroom_poison, user:get_player_name(), 5)
  332. return eat_mushroom(itemstack, user, pointed_thing)
  333. end,
  334. selection_box = {
  335. type = "fixed",
  336. fixed = {-0.3, -0.5, -0.3, 0.3, 0, 0.3}
  337. },
  338. on_construct = function(...)
  339. return flowers.on_mushroom_construct(...)
  340. end,
  341. on_destruct = function(...)
  342. return flowers.on_mushroom_destruct(...)
  343. end,
  344. on_timer = function(...)
  345. return flowers.on_mushroom_timer(...)
  346. end,
  347. on_punch = function(...)
  348. return flowers.on_mushroom_punch(...)
  349. end,
  350. })
  351. minetest.register_node("flowers:mushroom_brown", {
  352. description = "Brown Mushroom",
  353. tiles = {"flowers_mushroom_brown.png"},
  354. inventory_image = "flowers_mushroom_brown.png",
  355. wield_image = "flowers_mushroom_brown.png",
  356. drawtype = "plantlike",
  357. paramtype = "light",
  358. sunlight_propagates = true,
  359. walkable = false,
  360. buildable_to = true,
  361. groups = utility.dig_groups("plant", {attached_node = 1, flammable = 1}),
  362. sounds = default.node_sound_leaves_defaults(),
  363. on_use = minetest.item_eat(1),
  364. selection_box = {
  365. type = "fixed",
  366. fixed = {-0.3, -0.5, -0.3, 0.3, 0, 0.3}
  367. },
  368. movement_speed_multiplier = default.SLOW_SPEED_PLANTS,
  369. on_construct = function(...)
  370. return flowers.on_mushroom_construct(...)
  371. end,
  372. on_destruct = function(...)
  373. return flowers.on_mushroom_destruct(...)
  374. end,
  375. on_timer = function(...)
  376. return flowers.on_mushroom_timer(...)
  377. end,
  378. on_punch = function(...)
  379. return flowers.on_mushroom_punch(...)
  380. end,
  381. })
  382. flowers.reg2 = true
  383. end
  384. -- Called by the bonemeal mod.
  385. -- Returns 'true' or 'false' to indicate if a mushroom was spawned.
  386. function flowers.mushroom_spread(pos, node)
  387. if minetest.get_node_light(pos, nil) == 15 then
  388. minetest.remove_node(pos)
  389. return false
  390. end
  391. local minp = {x=pos.x-2, y=pos.y-2, z=pos.z-2}
  392. local maxp = {x=pos.x+2, y=pos.y+1, z=pos.z+2}
  393. local dirt = minetest.find_nodes_in_area_under_air(minp, maxp, flowers.mushroom_surfaces)
  394. if not dirt or #dirt == 0 then
  395. return false
  396. end
  397. local randp = dirt[math.random(1, #dirt)]
  398. local airp = {x=randp.x, y=randp.y+1, z=randp.z}
  399. local airn = minetest.get_node_or_nil(airp)
  400. if not airn or airn.name ~= "air" then
  401. return false
  402. end
  403. -- Mushrooms grow in nether regardless of light level.
  404. if pos.y < -25000 then
  405. minetest.add_node(airp, {name = node.name})
  406. return true
  407. end
  408. -- Otherwise, check light-level before growing.
  409. if minetest.get_node_light(pos, 0.5) <= 7 and
  410. minetest.get_node_light(airp, 0.5) <= 7 then
  411. minetest.add_node(airp, {name = node.name})
  412. return true
  413. end
  414. return false
  415. end
  416. if not flowers.reg3 then
  417. -- These old mushroom related nodes can be simplified now.
  418. minetest.register_alias("flowers:mushroom_spores_brown", "flowers:mushroom_brown")
  419. minetest.register_alias("flowers:mushroom_spores_red", "flowers:mushroom_red")
  420. minetest.register_alias("flowers:mushroom_fertile_brown", "flowers:mushroom_brown")
  421. minetest.register_alias("flowers:mushroom_fertile_red", "flowers:mushroom_red")
  422. minetest.register_alias("mushroom:brown_natural", "flowers:mushroom_brown")
  423. minetest.register_alias("mushroom:red_natural", "flowers:mushroom_red")
  424. --
  425. -- Waterlily
  426. --
  427. minetest.register_node("flowers:waterlily", {
  428. description = "Waterlily",
  429. drawtype = "nodebox",
  430. paramtype = "light",
  431. paramtype2 = "facedir",
  432. -- Horizontal rotation only!
  433. on_rotate = screwdriver.rotate_simple,
  434. tiles = {"flowers_waterlily.png", "flowers_waterlily_bottom.png"},
  435. inventory_image = "flowers_waterlily.png",
  436. wield_image = "flowers_waterlily.png",
  437. liquids_pointable = true,
  438. walkable = false,
  439. buildable_to = true,
  440. sunlight_propagates = true,
  441. floodable = true,
  442. -- Lily does not count as flora, it has special handling.
  443. groups = utility.dig_groups("plant", {flower = 1, flammable = 1}),
  444. sounds = default.node_sound_leaves_defaults(),
  445. node_placement_prediction = "",
  446. node_box = {
  447. type = "fixed",
  448. fixed = {-0.5, -31 / 64, -0.5, 0.5, -15 / 32, 0.5},
  449. },
  450. selection_box = {
  451. type = "fixed",
  452. fixed = {-0.5, -31 / 64, -0.5, 0.5, -15 / 32, 0.5},
  453. },
  454. on_place = function(itemstack, placer, pointed_thing)
  455. local pos = pointed_thing.above
  456. local node = minetest.get_node(pointed_thing.under).name
  457. local def = minetest.reg_ns_nodes[node]
  458. local player_name = placer:get_player_name()
  459. -- Lilies are placeable in any water.
  460. -- They only grow further in regular water sources.
  461. if def and def.liquidtype == "source" and
  462. minetest.get_item_group(node, "water") > 0 then
  463. if not minetest.is_protected(pos, player_name) then
  464. minetest.add_node(pos, {name = "flowers:waterlily",
  465. param2 = math.random(0, 3)})
  466. --if not minetest.setting_getbool("creative_mode") then
  467. itemstack:take_item()
  468. --end
  469. else
  470. minetest.chat_send_player(player_name, "# Server: Position is protected.")
  471. minetest.record_protection_violation(pos, player_name)
  472. end
  473. end
  474. return itemstack
  475. end,
  476. on_construct = function(...)
  477. return flowers.on_lily_construct(...)
  478. end,
  479. on_destruct = function(...)
  480. return flowers.on_lily_destruct(...)
  481. end,
  482. on_timer = function(...)
  483. return flowers.on_lily_timer(...)
  484. end,
  485. on_punch = function(...)
  486. return flowers.on_lily_punch(...)
  487. end,
  488. })
  489. minetest.register_node("flowers:lilyspawner", {
  490. drawtype = "airlike",
  491. description = "Lily Spawner (Please Report to Admin)",
  492. paramtype = "light",
  493. sunlight_propagates = true,
  494. walkable = false,
  495. pointable = false,
  496. groups = {immovable = 1},
  497. climbable = false,
  498. buildable_to = true,
  499. floodable = true,
  500. drop = "",
  501. on_construct = function(...)
  502. flowers.on_lily_construct(...)
  503. end,
  504. on_timer = function(pos, elapsed)
  505. -- Always remove node, even if spawn unsuccessful.
  506. minetest.remove_node(pos)
  507. if minetest.find_node_near(pos, 3, "group:melt_around") then
  508. flowers.lily_spread(pos)
  509. end
  510. end,
  511. on_finish_collapse = function(pos, node)
  512. minetest.remove_node(pos)
  513. end,
  514. on_collapse_to_entity = function(pos, node)
  515. -- Do nothing.
  516. end,
  517. })
  518. flowers.reg3 = true
  519. end
  520. -- Make mod reloadable.
  521. if not flowers.reg4 then
  522. local c = "flowers:core"
  523. local f = flowers.modpath .. "/init.lua"
  524. reload.register_file(c, f, false)
  525. flowers.reg4 = true
  526. end
  527. function flowers.create_lilyspawner_near(pos)
  528. local water = minetest.find_node_near(pos, 3, "default:water_source")
  529. if water then
  530. water.y = water.y + 1
  531. if minetest.get_node(water).name == "air" then
  532. if not minetest.find_node_near(pos, 2, "group:cold") then
  533. minetest.add_node(water, {name="flowers:lilyspawner"})
  534. return true
  535. end
  536. end
  537. end
  538. return false
  539. end
  540. function flowers.lily_density_for_pos(pos)
  541. local cold = 0
  542. if minetest.find_node_near(pos, 2, {
  543. "group:snow",
  544. "group:snowy",
  545. "group:ice",
  546. "group:cold",
  547. }) then
  548. cold = -6
  549. end
  550. -- Heat makes lilies grow denser.
  551. local heat = 0
  552. if minetest.find_node_near(pos, 3, "group:melt_around") then
  553. heat = 1
  554. end
  555. -- Minerals improve lily growth.
  556. local minerals = 0
  557. if minetest.find_node_near(pos, 3, "glowstone:minerals") then
  558. minerals = 1
  559. end
  560. -- Calc lily density.
  561. return 7 + minerals + heat + cold
  562. end
  563. flowers.lily_mintime = 60*2
  564. flowers.lily_maxtime = 60*15
  565. function flowers.surface_can_spawn_lily(pos)
  566. local name = minetest.get_node(pos).name
  567. if name == "default:water_source" then
  568. return true
  569. end
  570. return false
  571. end
  572. -- This is called for both lily and lilyspawner.
  573. function flowers.on_lily_construct(pos)
  574. if flowers.surface_can_spawn_lily({x=pos.x, y=pos.y-1, z=pos.z}) then
  575. minetest.get_node_timer(pos):start(math.random(flowers.lily_mintime, flowers.lily_maxtime))
  576. end
  577. end
  578. function flowers.on_lily_destruct(pos)
  579. -- Notify nearby lilies.
  580. local minp = vector.subtract(pos, 4)
  581. local maxp = vector.add(pos, 4)
  582. local lilies = minetest.find_nodes_in_area(minp, maxp, "flowers:waterlily")
  583. if lilies and #lilies > 0 then
  584. for i=1, #lilies do
  585. minetest.get_node_timer(lilies[i]):start(math.random(flowers.lily_mintime, flowers.lily_maxtime))
  586. end
  587. end
  588. end
  589. function flowers.on_lily_timer(pos, elapsed)
  590. --minetest.chat_send_player("MustTest", "Lily timer @ " .. minetest.pos_to_string(pos) .. "!")
  591. if flowers.lily_spread(pos) then
  592. minetest.get_node_timer(pos):start(math.random(flowers.lily_mintime, flowers.lily_maxtime))
  593. else
  594. -- Else timer should stop, cannot grow anymore.
  595. minetest.get_node_timer(pos):stop()
  596. end
  597. end
  598. function flowers.on_lily_punch(pos, node, puncher, pt)
  599. if flowers.surface_can_spawn_lily({x=pos.x, y=pos.y-1, z=pos.z}) then
  600. minetest.get_node_timer(pos):start(math.random(flowers.lily_mintime, flowers.lily_maxtime))
  601. end
  602. end
  603. -- This is called from lilyspawner and lily.
  604. function flowers.lily_spread(pos)
  605. if not flowers.surface_can_spawn_lily({x=pos.x, y=pos.y-1, z=pos.z}) then
  606. return false
  607. end
  608. local light = minetest.get_node_light(pos) or 0
  609. if light < 13 then
  610. -- Is this just a daytime thing?
  611. if (minetest.get_node_light(pos, 0.5) or 0) < 13 then
  612. return false
  613. else
  614. return true -- Keep trying.
  615. end
  616. end
  617. local density = flowers.lily_density_for_pos(pos)
  618. local pos0 = vector.subtract(pos, 4)
  619. local pos1 = vector.add(pos, 4)
  620. if #minetest.find_nodes_in_area(pos0, pos1, "flowers:waterlily") > density then
  621. return false -- Max lilies reached.
  622. end
  623. local water = minetest.find_nodes_in_area_under_air(pos0, pos1, "default:water_source")
  624. if #water > 0 then
  625. local growpos = water[math.random(1, #water)]
  626. growpos.y = growpos.y + 1
  627. local light = minetest.get_node_light(growpos) or 0
  628. if light < 13 then
  629. -- Is this just a daytime thing?
  630. if (minetest.get_node_light(growpos, 0.5) or 0) < 13 then
  631. return false
  632. else
  633. return true -- Keep trying.
  634. end
  635. end
  636. minetest.add_node(growpos, {name="flowers:waterlily", param2=math.random(0, 3)})
  637. return true
  638. end
  639. return false
  640. end