init.lua 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  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. -- 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,
  276. })
  277. -- Flower spread
  278. -- Public function to enable override by mods
  279. function flowers.flower_spread(pos, node)
  280. pos.y = pos.y - 1
  281. local under = minetest.get_node(pos)
  282. pos.y = pos.y + 1
  283. -- Replace flora with dry shrub in desert sand and silver sand,
  284. -- as this is the only way to generate them.
  285. -- However, preserve grasses in sand dune biomes.
  286. if minetest.get_item_group(under.name, "sand") == 1 and
  287. under.name ~= "default:sand" then
  288. local name = "default:dry_shrub"
  289. if math.random(1, 2) == 1 then
  290. name = "default:dry_shrub2"
  291. end
  292. minetest.add_node(pos, {name = name})
  293. return false
  294. end
  295. if minetest.get_item_group(under.name, "soil") == 0 then
  296. return false
  297. end
  298. local light = minetest.get_node_light(pos) or 0
  299. if light < 13 then
  300. -- Is this just a daytime thing?
  301. if (minetest.get_node_light(pos, 0.5) or 0) < 13 then
  302. return false
  303. else
  304. return true -- Keep trying.
  305. end
  306. end
  307. local density = flowers.flora_density_for_surface({x=pos.x, y=pos.y-1, z=pos.z})
  308. local pos0 = vector.subtract(pos, 4)
  309. local pos1 = vector.add(pos, 4)
  310. if #minetest.find_nodes_in_area(pos0, pos1, "group:flora") > density then
  311. return false -- Max flora reached.
  312. end
  313. local soils = minetest.find_nodes_in_area_under_air(pos0, pos1, "group:soil")
  314. if #soils > 0 then
  315. local seedling = soils[math_random(1, #soils)]
  316. local seedling_above = {x=seedling.x, y=seedling.y+1, z=seedling.z}
  317. local light = minetest.get_node_light(seedling_above) or 0
  318. if light < 13 then
  319. -- Is this just a daytime thing?
  320. if (minetest.get_node_light(seedling_above, 0.5) or 0) < 13 then
  321. return false
  322. else
  323. return true -- Keep trying.
  324. end
  325. end
  326. -- Desert sand is in the soil group.
  327. if minetest.get_node(seedling).name == "default:desert_sand" then
  328. return false
  329. end
  330. minetest.add_node(seedling_above, {name = node.name, param2 = node.param2})
  331. return true
  332. end
  333. return false
  334. end
  335. -- Indexed array.
  336. flowers.mushroom_surfaces = {
  337. "default:dirt",
  338. "rackstone:dauthsand",
  339. "group:soil",
  340. "group:tree",
  341. "default:mossycobble",
  342. -- We disable these because they are much too common.
  343. -- Mushroom farms would be too easy to make, especially during a cave survival challenge.
  344. --"group:cavern_soil",
  345. --"darkage:silt",
  346. --"darkage:mud",
  347. }
  348. flowers.mushroom_nodes = {
  349. "flowers:mushroom_red",
  350. "flowers:mushroom_brown",
  351. "cavestuff:mycena",
  352. "cavestuff:fungus",
  353. }
  354. flowers.mushroom_mintime = 60*3
  355. flowers.mushroom_maxtime = 60*30
  356. function flowers.surface_can_spawn_mushroom(pos)
  357. local name = minetest.get_node(pos).name
  358. local nodes = flowers.mushroom_surfaces
  359. for i=1, #nodes do
  360. if string.find(nodes[i], "^group:") then
  361. local group = string.sub(nodes[i], 7)
  362. if minetest.get_item_group(name, group) ~= 0 then
  363. return true
  364. end
  365. elseif nodes[i] == name then
  366. return true
  367. end
  368. end
  369. return false
  370. end
  371. function flowers.on_mushroom_construct(pos)
  372. if flowers.surface_can_spawn_mushroom({x=pos.x, y=pos.y-1, z=pos.z}) then
  373. minetest.get_node_timer(pos):start(math_random(flowers.mushroom_mintime, flowers.mushroom_maxtime))
  374. end
  375. end
  376. function flowers.on_mushroom_destruct(pos)
  377. -- Notify nearby mushrooms.
  378. local minp = {x=pos.x-2, y=pos.y-2, z=pos.z-2}
  379. local maxp = {x=pos.x+2, y=pos.y+1, z=pos.z+2}
  380. local mushrooms = minetest.find_nodes_in_area_under_air(minp, maxp, flowers.mushroom_nodes)
  381. if mushrooms and #mushrooms > 0 then
  382. for i=1, #mushrooms do
  383. minetest.get_node_timer(mushrooms[i]):start(math_random(flowers.mushroom_mintime, flowers.mushroom_maxtime))
  384. end
  385. end
  386. end
  387. function flowers.on_mushroom_timer(pos, elapsed)
  388. --minetest.chat_send_player("MustTest", "Mushroom timer @ " .. minetest.pos_to_string(pos) .. "!")
  389. local node = minetest.get_node(pos)
  390. if flowers.mushroom_spread(pos, node) then
  391. minetest.get_node_timer(pos):start(math_random(flowers.mushroom_mintime, flowers.mushroom_maxtime))
  392. else
  393. -- Else timer should stop, cannot grow anymore.
  394. minetest.get_node_timer(pos):stop()
  395. end
  396. end
  397. function flowers.on_mushroom_punch(pos, node, puncher, pt)
  398. if flowers.surface_can_spawn_mushroom({x=pos.x, y=pos.y-1, z=pos.z}) then
  399. minetest.get_node_timer(pos):start(math_random(flowers.mushroom_mintime, flowers.mushroom_maxtime))
  400. end
  401. end
  402. if not flowers.reg2 then
  403. --
  404. -- Mushrooms
  405. --
  406. local eat_mushroom = minetest.item_eat(1)
  407. local function mushroom_poison(pname, step)
  408. local msg = "# Server: <" .. rename.gpn(pname) .. "> ate a mushroom. Desperate!"
  409. hb4.delayed_harm({name=pname, step=step, min=1, max=1, msg=msg, poison=true})
  410. end
  411. minetest.register_node("flowers:mushroom_red", {
  412. description = "Red Mushroom",
  413. tiles = {"flowers_mushroom_red.png"},
  414. inventory_image = "flowers_mushroom_red.png",
  415. wield_image = "flowers_mushroom_red.png",
  416. drawtype = "plantlike",
  417. paramtype = "light",
  418. sunlight_propagates = true,
  419. walkable = false,
  420. buildable_to = true,
  421. groups = utility.dig_groups("plant", {attached_node = 1, flammable = 1}),
  422. sounds = default.node_sound_leaves_defaults(),
  423. movement_speed_multiplier = default.SLOW_SPEED_PLANTS,
  424. on_use = function(itemstack, user, pointed_thing)
  425. if not user or not user:is_player() then return end
  426. minetest.after(1, mushroom_poison, user:get_player_name(), 5)
  427. return eat_mushroom(itemstack, user, pointed_thing)
  428. end,
  429. selection_box = {
  430. type = "fixed",
  431. fixed = {-0.3, -0.5, -0.3, 0.3, 0, 0.3}
  432. },
  433. on_construct = function(...)
  434. return flowers.on_mushroom_construct(...)
  435. end,
  436. on_destruct = function(...)
  437. return flowers.on_mushroom_destruct(...)
  438. end,
  439. on_timer = function(...)
  440. return flowers.on_mushroom_timer(...)
  441. end,
  442. on_punch = function(...)
  443. return flowers.on_mushroom_punch(...)
  444. end,
  445. })
  446. minetest.register_node("flowers:mushroom_brown", {
  447. description = "Brown Mushroom",
  448. tiles = {"flowers_mushroom_brown.png"},
  449. inventory_image = "flowers_mushroom_brown.png",
  450. wield_image = "flowers_mushroom_brown.png",
  451. drawtype = "plantlike",
  452. paramtype = "light",
  453. sunlight_propagates = true,
  454. walkable = false,
  455. buildable_to = true,
  456. groups = utility.dig_groups("plant", {attached_node = 1, flammable = 1}),
  457. sounds = default.node_sound_leaves_defaults(),
  458. on_use = minetest.item_eat(1),
  459. selection_box = {
  460. type = "fixed",
  461. fixed = {-0.3, -0.5, -0.3, 0.3, 0, 0.3}
  462. },
  463. movement_speed_multiplier = default.SLOW_SPEED_PLANTS,
  464. on_construct = function(...)
  465. return flowers.on_mushroom_construct(...)
  466. end,
  467. on_destruct = function(...)
  468. return flowers.on_mushroom_destruct(...)
  469. end,
  470. on_timer = function(...)
  471. return flowers.on_mushroom_timer(...)
  472. end,
  473. on_punch = function(...)
  474. return flowers.on_mushroom_punch(...)
  475. end,
  476. })
  477. flowers.reg2 = true
  478. end
  479. -- Called by the bonemeal mod.
  480. -- Returns 'true' or 'false' to indicate if a mushroom was spawned.
  481. function flowers.mushroom_spread(pos, node)
  482. if minetest.get_node_light(pos, nil) == 15 then
  483. minetest.remove_node(pos)
  484. return false
  485. end
  486. local minp = {x=pos.x-2, y=pos.y-2, z=pos.z-2}
  487. local maxp = {x=pos.x+2, y=pos.y+1, z=pos.z+2}
  488. local dirt = minetest.find_nodes_in_area_under_air(minp, maxp, flowers.mushroom_surfaces)
  489. if not dirt or #dirt == 0 then
  490. return false
  491. end
  492. local randp = dirt[math_random(1, #dirt)]
  493. local airp = {x=randp.x, y=randp.y+1, z=randp.z}
  494. local airn = minetest.get_node_or_nil(airp)
  495. if not airn or airn.name ~= "air" then
  496. return false
  497. end
  498. -- Mushrooms grow in nether regardless of light level.
  499. if pos.y < -25000 then
  500. minetest.add_node(airp, {name = node.name})
  501. return true
  502. end
  503. -- Otherwise, check light-level before growing.
  504. if minetest.get_node_light(pos, 0.5) <= 7 and
  505. minetest.get_node_light(airp, 0.5) <= 7 then
  506. minetest.add_node(airp, {name = node.name})
  507. return true
  508. end
  509. return false
  510. end
  511. if not flowers.reg3 then
  512. -- These old mushroom related nodes can be simplified now.
  513. minetest.register_alias("flowers:mushroom_spores_brown", "flowers:mushroom_brown")
  514. minetest.register_alias("flowers:mushroom_spores_red", "flowers:mushroom_red")
  515. minetest.register_alias("flowers:mushroom_fertile_brown", "flowers:mushroom_brown")
  516. minetest.register_alias("flowers:mushroom_fertile_red", "flowers:mushroom_red")
  517. minetest.register_alias("mushroom:brown_natural", "flowers:mushroom_brown")
  518. minetest.register_alias("mushroom:red_natural", "flowers:mushroom_red")
  519. --
  520. -- Waterlily
  521. --
  522. minetest.register_node("flowers:waterlily", {
  523. description = "Waterlily",
  524. drawtype = "nodebox",
  525. paramtype = "light",
  526. paramtype2 = "facedir",
  527. -- Horizontal rotation only!
  528. on_rotate = screwdriver.rotate_simple,
  529. tiles = {"flowers_waterlily.png", "flowers_waterlily_bottom.png"},
  530. inventory_image = "flowers_waterlily.png",
  531. wield_image = "flowers_waterlily.png",
  532. liquids_pointable = true,
  533. walkable = false,
  534. buildable_to = true,
  535. sunlight_propagates = true,
  536. floodable = true,
  537. -- Lily does not count as flora, it has special handling.
  538. groups = utility.dig_groups("plant", {flower = 1, flammable = 1}),
  539. sounds = default.node_sound_leaves_defaults(),
  540. node_placement_prediction = "",
  541. node_box = {
  542. type = "fixed",
  543. fixed = {-0.5, -31 / 64, -0.5, 0.5, -15 / 32, 0.5},
  544. },
  545. selection_box = {
  546. type = "fixed",
  547. fixed = {-0.5, -31 / 64, -0.5, 0.5, -15 / 32, 0.5},
  548. },
  549. on_place = function(itemstack, placer, pointed_thing)
  550. local pos = pointed_thing.above
  551. local node = minetest.get_node(pointed_thing.under).name
  552. local def = minetest.reg_ns_nodes[node]
  553. local player_name = placer:get_player_name()
  554. -- Lilies are placeable in any water.
  555. -- They only grow further in regular water sources.
  556. if def and def.liquidtype == "source" and
  557. minetest.get_item_group(node, "water") > 0 then
  558. if not minetest.is_protected(pos, player_name) then
  559. minetest.add_node(pos, {name = "flowers:waterlily",
  560. param2 = math_random(0, 3)})
  561. --if not minetest.setting_getbool("creative_mode") then
  562. itemstack:take_item()
  563. --end
  564. else
  565. minetest.chat_send_player(player_name, "# Server: Position is protected.")
  566. minetest.record_protection_violation(pos, player_name)
  567. end
  568. end
  569. return itemstack
  570. end,
  571. on_construct = function(...)
  572. return flowers.on_lily_construct(...)
  573. end,
  574. on_destruct = function(...)
  575. return flowers.on_lily_destruct(...)
  576. end,
  577. on_timer = function(...)
  578. return flowers.on_lily_timer(...)
  579. end,
  580. on_punch = function(...)
  581. return flowers.on_lily_punch(...)
  582. end,
  583. })
  584. minetest.register_node("flowers:lilyspawner", {
  585. drawtype = "airlike",
  586. description = "Lily Spawner (Please Report to Admin)",
  587. paramtype = "light",
  588. sunlight_propagates = true,
  589. walkable = false,
  590. pointable = false,
  591. groups = {immovable = 1},
  592. climbable = false,
  593. buildable_to = true,
  594. floodable = true,
  595. drop = "",
  596. on_construct = function(...)
  597. flowers.on_lily_construct(...)
  598. end,
  599. on_timer = function(pos, elapsed)
  600. -- Always remove node, even if spawn unsuccessful.
  601. minetest.remove_node(pos)
  602. if minetest.find_node_near(pos, 3, "group:melt_around") then
  603. flowers.lily_spread(pos)
  604. end
  605. end,
  606. on_finish_collapse = function(pos, node)
  607. minetest.remove_node(pos)
  608. end,
  609. on_collapse_to_entity = function(pos, node)
  610. -- Do nothing.
  611. end,
  612. })
  613. flowers.reg3 = true
  614. end
  615. -- Make mod reloadable.
  616. if not flowers.reg4 then
  617. local c = "flowers:core"
  618. local f = flowers.modpath .. "/init.lua"
  619. reload.register_file(c, f, false)
  620. flowers.reg4 = true
  621. end
  622. function flowers.create_lilyspawner_near(pos)
  623. local water = minetest.find_node_near(pos, 3, "default:water_source")
  624. if water then
  625. water.y = water.y + 1
  626. if minetest.get_node(water).name == "air" then
  627. if not minetest.find_node_near(pos, 2, "group:cold") then
  628. minetest.add_node(water, {name="flowers:lilyspawner"})
  629. return true
  630. end
  631. end
  632. end
  633. return false
  634. end
  635. function flowers.lily_density_for_pos(pos)
  636. local cold = 0
  637. if minetest.find_node_near(pos, 2, {
  638. "group:snow",
  639. "group:snowy",
  640. "group:ice",
  641. "group:cold",
  642. }) then
  643. cold = -6
  644. end
  645. -- Heat makes lilies grow denser.
  646. local heat = 0
  647. if minetest.find_node_near(pos, 3, "group:melt_around") then
  648. heat = 1
  649. end
  650. -- Minerals improve lily growth.
  651. local minerals = 0
  652. if minetest.find_node_near(pos, 3, "glowstone:minerals") then
  653. minerals = 1
  654. end
  655. -- Calc lily density.
  656. return 7 + minerals + heat + cold
  657. end
  658. flowers.lily_mintime = 60*2
  659. flowers.lily_maxtime = 60*15
  660. function flowers.surface_can_spawn_lily(pos)
  661. local name = minetest.get_node(pos).name
  662. if name == "default:water_source" then
  663. return true
  664. end
  665. return false
  666. end
  667. -- This is called for both lily and lilyspawner.
  668. function flowers.on_lily_construct(pos)
  669. if flowers.surface_can_spawn_lily({x=pos.x, y=pos.y-1, z=pos.z}) then
  670. minetest.get_node_timer(pos):start(math_random(flowers.lily_mintime, flowers.lily_maxtime))
  671. end
  672. end
  673. function flowers.on_lily_destruct(pos)
  674. -- Notify nearby lilies.
  675. local minp = vector.subtract(pos, 4)
  676. local maxp = vector.add(pos, 4)
  677. local lilies = minetest.find_nodes_in_area(minp, maxp, "flowers:waterlily")
  678. if lilies and #lilies > 0 then
  679. for i=1, #lilies do
  680. minetest.get_node_timer(lilies[i]):start(math_random(flowers.lily_mintime, flowers.lily_maxtime))
  681. end
  682. end
  683. end
  684. function flowers.on_lily_timer(pos, elapsed)
  685. --minetest.chat_send_player("MustTest", "Lily timer @ " .. minetest.pos_to_string(pos) .. "!")
  686. if flowers.lily_spread(pos) then
  687. minetest.get_node_timer(pos):start(math_random(flowers.lily_mintime, flowers.lily_maxtime))
  688. else
  689. -- Else timer should stop, cannot grow anymore.
  690. minetest.get_node_timer(pos):stop()
  691. end
  692. end
  693. function flowers.on_lily_punch(pos, node, puncher, pt)
  694. if flowers.surface_can_spawn_lily({x=pos.x, y=pos.y-1, z=pos.z}) then
  695. minetest.get_node_timer(pos):start(math_random(flowers.lily_mintime, flowers.lily_maxtime))
  696. end
  697. end
  698. -- This is called from lilyspawner and lily.
  699. function flowers.lily_spread(pos)
  700. if not flowers.surface_can_spawn_lily({x=pos.x, y=pos.y-1, z=pos.z}) then
  701. return false
  702. end
  703. local light = minetest.get_node_light(pos) or 0
  704. if light < 13 then
  705. -- Is this just a daytime thing?
  706. if (minetest.get_node_light(pos, 0.5) or 0) < 13 then
  707. return false
  708. else
  709. return true -- Keep trying.
  710. end
  711. end
  712. local density = flowers.lily_density_for_pos(pos)
  713. local pos0 = vector.subtract(pos, 4)
  714. local pos1 = vector.add(pos, 4)
  715. if #minetest.find_nodes_in_area(pos0, pos1, "flowers:waterlily") > density then
  716. return false -- Max lilies reached.
  717. end
  718. local water = minetest.find_nodes_in_area_under_air(pos0, pos1, "default:water_source")
  719. if #water > 0 then
  720. local growpos = water[math_random(1, #water)]
  721. growpos.y = growpos.y + 1
  722. local light = minetest.get_node_light(growpos) or 0
  723. if light < 13 then
  724. -- Is this just a daytime thing?
  725. if (minetest.get_node_light(growpos, 0.5) or 0) < 13 then
  726. return false
  727. else
  728. return true -- Keep trying.
  729. end
  730. end
  731. minetest.add_node(growpos, {name="flowers:waterlily", param2=math_random(0, 3)})
  732. return true
  733. end
  734. return false
  735. end