init.lua 22 KB

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