init.lua 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  1. bonemeal = {}
  2. -- Load support for intllib.
  3. local MP = minetest.get_modpath(minetest.get_current_modname())
  4. local S, NS = dofile(MP .. "/intllib.lua")
  5. -- creative check
  6. local creative_mode_cache = minetest.settings:get_bool("creative_mode")
  7. function is_creative(name)
  8. return creative_mode_cache or minetest.check_player_privs(name, {creative = true})
  9. end
  10. -- default crops
  11. local crops = {
  12. {"farming:cotton_", 8, "farming:seed_cotton"},
  13. {"farming:wheat_", 8, "farming:seed_wheat"},
  14. }
  15. -- special pine check for nearby snow
  16. local function pine_grow(pos)
  17. if minetest.find_node_near(pos, 1,
  18. {"default:snow", "default:snowblock", "default:dirt_with_snow"}) then
  19. default.grow_new_snowy_pine_tree(pos)
  20. else
  21. default.grow_new_pine_tree(pos)
  22. end
  23. end
  24. -- default saplings
  25. local saplings = {
  26. {"default:sapling", default.grow_new_apple_tree, "soil"},
  27. {"default:junglesapling", default.grow_new_jungle_tree, "soil"},
  28. {"default:emergent_jungle_sapling", default.grow_new_emergent_jungle_tree, "soil"},
  29. {"default:acacia_sapling", default.grow_new_acacia_tree, "soil"},
  30. {"default:aspen_sapling", default.grow_new_aspen_tree, "soil"},
  31. {"default:pine_sapling", pine_grow, "soil"},
  32. {"default:bush_sapling", default.grow_bush, "soil"},
  33. {"default:acacia_bush_sapling", default.grow_acacia_bush, "soil"},
  34. {"default:large_cactus_seedling", default.grow_large_cactus, "sand"},
  35. {"default:blueberry_bush_sapling", default.grow_blueberry_bush, "soil"},
  36. {"default:pine_bush_sapling", default.grow_pine_bush, "soil"},
  37. }
  38. -- helper tables ( "" denotes a blank item )
  39. local green_grass = {
  40. "default:grass_2", "default:grass_3", "default:grass_4",
  41. "default:grass_5", "", ""
  42. }
  43. local dry_grass = {
  44. "default:dry_grass_2", "default:dry_grass_3", "default:dry_grass_4",
  45. "default:dry_grass_5", "", ""
  46. }
  47. local flowers = {
  48. "flowers:dandelion_white", "flowers:dandelion_yellow", "flowers:geranium",
  49. "flowers:rose", "flowers:tulip", "flowers:viola", ""
  50. }
  51. -- 5.0 flower check
  52. if minetest.registered_nodes["flowers:tulip_black"] then
  53. flowers[#flowers + 1] = "flowers:tulip_black"
  54. flowers[#flowers + 1] = "flowers:chrysanthemum_green"
  55. end
  56. -- add additional bakedclay flowers if enabled
  57. if minetest.get_modpath("bakedclay") then
  58. flowers[#flowers + 1] = "bakedclay:delphinium"
  59. flowers[#flowers + 1] = "bakedclay:thistle"
  60. flowers[#flowers + 1] = "bakedclay:lazarus"
  61. flowers[#flowers + 1] = "bakedclay:mannagrass"
  62. flowers[#flowers + 1] = ""
  63. end
  64. -- default biomes deco
  65. local deco = {
  66. {"default:dirt_with_dry_grass", dry_grass, flowers},
  67. {"default:sand", {}, {"default:dry_shrub", "", "", ""} },
  68. {"default:desert_sand", {}, {"default:dry_shrub", "", "", ""} },
  69. {"default:silver_sand", {}, {"default:dry_shrub", "", "", ""} },
  70. }
  71. ----- local functions
  72. -- particles
  73. local function particle_effect(pos)
  74. minetest.add_particlespawner({
  75. amount = 4,
  76. time = 0.15,
  77. minpos = pos,
  78. maxpos = pos,
  79. minvel = {x = -1, y = 2, z = -1},
  80. maxvel = {x = 1, y = 4, z = 1},
  81. minacc = {x = -1, y = -1, z = -1},
  82. maxacc = {x = 1, y = 1, z = 1},
  83. minexptime = 1,
  84. maxexptime = 1,
  85. minsize = 1,
  86. maxsize = 3,
  87. texture = "bonemeal_particle.png",
  88. })
  89. end
  90. -- tree type check
  91. local function grow_tree(pos, object)
  92. if type(object) == "table" and object.axiom then
  93. -- grow L-system tree
  94. minetest.remove_node(pos)
  95. minetest.spawn_tree(pos, object)
  96. elseif type(object) == "string" and minetest.registered_nodes[object] then
  97. -- place node
  98. minetest.set_node(pos, {name = object})
  99. elseif type(object) == "function" then
  100. -- function
  101. object(pos)
  102. end
  103. end
  104. -- sapling check
  105. local function check_sapling(pos, nodename)
  106. -- what is sapling placed on?
  107. local under = minetest.get_node({
  108. x = pos.x,
  109. y = pos.y - 1,
  110. z = pos.z
  111. })
  112. local can_grow, grow_on
  113. -- check list for sapling and function
  114. for n = 1, #saplings do
  115. if saplings[n][1] == nodename then
  116. grow_on = saplings[n][3]
  117. -- sapling grows on top of specific node
  118. if grow_on
  119. and grow_on ~= "soil"
  120. and grow_on ~= "sand"
  121. and grow_on == under.name then
  122. can_grow = true
  123. end
  124. -- sapling grows on top of soil (default)
  125. if can_grow == nil
  126. and (grow_on == nil or grow_on == "soil")
  127. and minetest.get_item_group(under.name, "soil") > 0 then
  128. can_grow = true
  129. end
  130. -- sapling grows on top of sand
  131. if can_grow == nil
  132. and grow_on == "sand"
  133. and minetest.get_item_group(under.name, "sand") > 0 then
  134. can_grow = true
  135. end
  136. -- check if we can grow sapling
  137. if can_grow then
  138. particle_effect(pos)
  139. grow_tree(pos, saplings[n][2])
  140. return
  141. end
  142. end
  143. end
  144. end
  145. -- crops check
  146. local function check_crops(pos, nodename, strength)
  147. local mod, crop, stage, nod, def
  148. -- grow registered crops
  149. for n = 1, #crops do
  150. if string.find(nodename, crops[n][1])
  151. or nodename == crops[n][3] then
  152. -- separate mod and node name
  153. mod = nodename:split(":")[1] .. ":"
  154. crop = nodename:split(":")[2]
  155. -- get stage number or set to 0 for seed
  156. stage = tonumber( crop:split("_")[2] ) or 0
  157. stage = math.min(stage + strength, crops[n][2])
  158. -- check for place_param setting
  159. nod = crops[n][1] .. stage
  160. def = minetest.registered_nodes[nod]
  161. def = def and def.place_param2 or 0
  162. minetest.set_node(pos, {name = nod, param2 = def})
  163. particle_effect(pos)
  164. return
  165. end
  166. end
  167. end
  168. -- check soil for specific decoration placement
  169. local function check_soil(pos, nodename, strength)
  170. -- set radius according to strength
  171. local side = strength - 1
  172. local tall = math.max(strength - 2, 0)
  173. local floor
  174. local groups = minetest.registered_items[nodename]
  175. and minetest.registered_items[nodename].groups or {}
  176. -- only place decoration on one type of surface
  177. if groups.soil then
  178. floor = {"group:soil"}
  179. elseif groups.sand then
  180. floor = {"group:sand"}
  181. else
  182. floor = {nodename}
  183. end
  184. -- get area of land with free space above
  185. local dirt = minetest.find_nodes_in_area_under_air(
  186. {x = pos.x - side, y = pos.y - tall, z = pos.z - side},
  187. {x = pos.x + side, y = pos.y + tall, z = pos.z + side}, floor)
  188. -- set default grass and decoration
  189. local grass = green_grass
  190. local decor = flowers
  191. -- choose grass and decoration to use on dirt patch
  192. for n = 1, #deco do
  193. -- do we have a grass match?
  194. if nodename == deco[n][1] then
  195. grass = deco[n][2] or {}
  196. decor = deco[n][3] or {}
  197. end
  198. end
  199. local pos2, nod, def
  200. -- loop through soil
  201. for _,n in pairs(dirt) do
  202. pos2 = n
  203. pos2.y = pos2.y + 1
  204. if math.random(1, 5) == 5 then
  205. if decor and #decor > 0 then
  206. -- place random decoration (rare)
  207. local dnum = #decor or 1
  208. nod = decor[math.random(1, dnum)] or ""
  209. end
  210. else
  211. if grass and #grass > 0 then
  212. -- place random grass (common)
  213. local dgra = #grass or 1
  214. nod = #grass > 0 and grass[math.random(1, dgra)] or ""
  215. end
  216. end
  217. if nod and nod ~= "" then
  218. def = minetest.registered_nodes[nod]
  219. def = def and def.place_param2 or 0
  220. minetest.set_node(pos2, {name = nod, param2 = def})
  221. end
  222. particle_effect(pos2)
  223. end
  224. end
  225. -- global functions
  226. -- add to sapling list
  227. -- {sapling node, schematic or function name, "soil"|"sand"|specific_node}
  228. --e.g. {"default:sapling", default.grow_new_apple_tree, "soil"}
  229. function bonemeal:add_sapling(list)
  230. for n = 1, #list do
  231. table.insert(saplings, list[n])
  232. end
  233. end
  234. -- add to crop list to force grow
  235. -- {crop name start_, growth steps, seed node (if required)}
  236. -- e.g. {"farming:wheat_", 8, "farming:seed_wheat"}
  237. function bonemeal:add_crop(list)
  238. for n = 1, #list do
  239. table.insert(crops, list[n])
  240. end
  241. end
  242. -- add grass and flower/plant decoration for specific dirt types
  243. -- {dirt_node, {grass_nodes}, {flower_nodes}
  244. -- e.g. {"default:dirt_with_dry_grass", dry_grass, flowers}
  245. -- if an entry already exists for a given dirt type, it will add new entries and all empty
  246. -- entries, allowing to both add decorations and decrease their frequency.
  247. function bonemeal:add_deco(list)
  248. for l = 1, #list do
  249. for n = 1, #deco do
  250. -- update existing entry
  251. if list[l][1] == deco[n][1] then
  252. -- adding grass types
  253. for _,extra in ipairs(list[l][2]) do
  254. if extra ~= "" then
  255. for __,entry in ipairs(deco[n][2]) do
  256. if extra == entry then
  257. extra = false
  258. break
  259. end
  260. end
  261. end
  262. if extra then
  263. table.insert(deco[n][2], extra)
  264. end
  265. end
  266. -- adding decoration types
  267. for _,extra in ipairs(list[l][3]) do
  268. if extra ~= "" then
  269. for __,entry in ipairs(deco[n][3]) do
  270. if extra == entry then
  271. extra = false
  272. break
  273. end
  274. end
  275. end
  276. if extra then
  277. table.insert(deco[n][3], extra)
  278. end
  279. end
  280. list[l] = false
  281. break
  282. end
  283. end
  284. if list[l] then
  285. table.insert(deco, list[l])
  286. end
  287. end
  288. end
  289. -- definitively set a decration scheme
  290. -- this function will either add a new entry as is, or replace the existing one
  291. function bonemeal:set_deco(list)
  292. for l = 1, #list do
  293. for n = 1, #deco do
  294. -- replace existing entry
  295. if list[l][1] == deco[n][1] then
  296. deco[n][2] = list[l][2]
  297. deco[n][3] = list[l][3]
  298. list[l] = false
  299. break
  300. end
  301. end
  302. if list[l] then
  303. table.insert(deco, list[l])
  304. end
  305. end
  306. end
  307. -- global on_use function for bonemeal
  308. function bonemeal:on_use(pos, strength, node)
  309. -- get node pointed at
  310. local node = node or minetest.get_node(pos)
  311. -- return if nothing there
  312. if node.name == "ignore" then
  313. return
  314. end
  315. -- make sure strength is between 1 and 4
  316. strength = strength or 1
  317. strength = math.max(strength, 1)
  318. strength = math.min(strength, 4)
  319. -- papyrus and cactus
  320. if node.name == "default:papyrus" then
  321. default.grow_papyrus(pos, node)
  322. particle_effect(pos)
  323. return
  324. elseif node.name == "default:cactus" then
  325. default.grow_cactus(pos, node)
  326. particle_effect(pos)
  327. return
  328. end
  329. -- grow grass and flowers
  330. if minetest.get_item_group(node.name, "soil") > 0
  331. or minetest.get_item_group(node.name, "sand") > 0
  332. or minetest.get_item_group(node.name, "can_bonemeal") > 0 then
  333. check_soil(pos, node.name, strength)
  334. return
  335. end
  336. -- light check depending on strength (strength of 4 = no light needed)
  337. if (minetest.get_node_light(pos) or 0) < (12 - (strength * 3)) then
  338. return
  339. end
  340. -- check for tree growth if pointing at sapling
  341. -- if minetest.get_item_group(node.name, "sapling") > 0
  342. if math.random(1, (5 - strength)) == 1 then
  343. check_sapling(pos, node.name)
  344. return
  345. end
  346. -- check for crop growth
  347. check_crops(pos, node.name, strength)
  348. end
  349. ----- items
  350. -- mulch (strength 1)
  351. minetest.register_craftitem("bonemeal:mulch", {
  352. description = S("Mulch"),
  353. inventory_image = "bonemeal_mulch.png",
  354. on_use = function(itemstack, user, pointed_thing)
  355. -- did we point at a node?
  356. if pointed_thing.type ~= "node" then
  357. return
  358. end
  359. -- is area protected?
  360. if minetest.is_protected(pointed_thing.under, user:get_player_name()) then
  361. return
  362. end
  363. -- take item if not in creative
  364. if not is_creative(user:get_player_name()) then
  365. itemstack:take_item()
  366. end
  367. -- call global on_use function with strength of 1
  368. bonemeal:on_use(pointed_thing.under, 1)
  369. return itemstack
  370. end,
  371. })
  372. -- bonemeal (strength 2)
  373. minetest.register_craftitem("bonemeal:bonemeal", {
  374. description = S("Bone Meal"),
  375. inventory_image = "bonemeal_item.png",
  376. on_use = function(itemstack, user, pointed_thing)
  377. -- did we point at a node?
  378. if pointed_thing.type ~= "node" then
  379. return
  380. end
  381. -- is area protected?
  382. if minetest.is_protected(pointed_thing.under, user:get_player_name()) then
  383. return
  384. end
  385. -- take item if not in creative
  386. if not is_creative(user:get_player_name()) then
  387. itemstack:take_item()
  388. end
  389. -- call global on_use function with strength of 2
  390. bonemeal:on_use(pointed_thing.under, 2)
  391. return itemstack
  392. end,
  393. })
  394. -- fertiliser (strength 3)
  395. minetest.register_craftitem("bonemeal:fertiliser", {
  396. description = S("Fertiliser"),
  397. inventory_image = "bonemeal_fertiliser.png",
  398. on_use = function(itemstack, user, pointed_thing)
  399. -- did we point at a node?
  400. if pointed_thing.type ~= "node" then
  401. return
  402. end
  403. -- is area protected?
  404. if minetest.is_protected(pointed_thing.under, user:get_player_name()) then
  405. return
  406. end
  407. -- take item if not in creative
  408. if not is_creative(user:get_player_name()) then
  409. itemstack:take_item()
  410. end
  411. -- call global on_use function with strength of 3
  412. bonemeal:on_use(pointed_thing.under, 3)
  413. return itemstack
  414. end,
  415. })
  416. -- bone
  417. minetest.register_craftitem("bonemeal:bone", {
  418. description = S("Bone"),
  419. inventory_image = "bonemeal_bone.png",
  420. })
  421. -- gelatin powder
  422. minetest.register_craftitem("bonemeal:gelatin_powder", {
  423. description = S("Gelatin Powder"),
  424. inventory_image = "bonemeal_gelatin_powder.png",
  425. groups = {food_gelatin = 1, flammable = 2},
  426. })
  427. --- crafting recipes
  428. -- gelatin powder
  429. minetest.register_craft({
  430. output = "bonemeal:gelatin_powder 4",
  431. recipe = {
  432. {"bonemeal:bone", "bonemeal:bone", "bonemeal:bone"},
  433. {"bucket:bucket_water", "bucket:bucket_water", "bucket:bucket_water"},
  434. {"bucket:bucket_water", "default:torch", "bucket:bucket_water"},
  435. },
  436. replacements = {
  437. {"bucket:bucket_water", "bucket:bucket_empty 5"},
  438. },
  439. })
  440. -- bonemeal (from bone)
  441. minetest.register_craft({
  442. type = "shapeless",
  443. output = "bonemeal:bonemeal 2",
  444. recipe = {"bonemeal:bone"},
  445. })
  446. -- bonemeal (from player bones)
  447. minetest.register_craft({
  448. type = "shapeless",
  449. output = "bonemeal:bonemeal 4",
  450. recipe = {"bones:bones"},
  451. })
  452. -- bonemeal (from coral skeleton)
  453. minetest.register_craft({
  454. type = "shapeless",
  455. output = "bonemeal:bonemeal 2",
  456. recipe = {"default:coral_skeleton"},
  457. })
  458. -- mulch
  459. minetest.register_craft({
  460. type = "shapeless",
  461. output = "bonemeal:mulch 4",
  462. recipe = {
  463. "group:tree", "group:leaves", "group:leaves",
  464. "group:leaves", "group:leaves", "group:leaves",
  465. "group:leaves", "group:leaves", "group:leaves"
  466. },
  467. })
  468. -- fertiliser
  469. minetest.register_craft({
  470. type = "shapeless",
  471. output = "bonemeal:fertiliser 2",
  472. recipe = {"bonemeal:bonemeal", "bonemeal:mulch"},
  473. })
  474. -- add bones to dirt
  475. minetest.override_item("default:dirt", {
  476. drop = {
  477. max_items = 1,
  478. items = {
  479. {
  480. items = {"bonemeal:bone"},
  481. rarity = 30,
  482. },
  483. {
  484. items = {"default:dirt"},
  485. }
  486. }
  487. },
  488. })
  489. -- add support for other mods
  490. local path = minetest.get_modpath("bonemeal")
  491. dofile(path .. "/mods.lua")
  492. dofile(path .. "/lucky_block.lua")
  493. print (S("[MOD] bonemeal loaded"))