init.lua 14 KB

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