init.lua 22 KB

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