init.lua 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. bonemeal = {}
  2. local path = minetest.get_modpath("bonemeal")
  3. local table_insert = table.insert
  4. local min, max, random = math.min, math.max, math.random
  5. -- Load support for intllib
  6. local S, NS = dofile(path .. "/intllib.lua")
  7. -- creative check
  8. local creative_mode_cache = minetest.settings:get_bool("creative_mode")
  9. function is_creative(name)
  10. return creative_mode_cache or minetest.check_player_privs(name, {creative = true})
  11. end
  12. -- default crops
  13. local crops = {
  14. {"farming:cotton_", 8, "farming:seed_cotton"},
  15. {"farming:wheat_", 8, "farming:seed_wheat"}
  16. }
  17. -- special pine check for nearby snow
  18. local function pine_grow(pos)
  19. if minetest.find_node_near(pos, 1,
  20. {"default:snow", "default:snowblock", "default:dirt_with_snow"}) then
  21. default.grow_new_snowy_pine_tree(pos)
  22. else
  23. default.grow_new_pine_tree(pos)
  24. end
  25. end
  26. -- default saplings
  27. local saplings = {
  28. {"default:sapling", default.grow_new_apple_tree, "soil"},
  29. {"default:junglesapling", default.grow_new_jungle_tree, "soil"},
  30. {"default:emergent_jungle_sapling", default.grow_new_emergent_jungle_tree, "soil"},
  31. {"default:acacia_sapling", default.grow_new_acacia_tree, "soil"},
  32. {"default:aspen_sapling", default.grow_new_aspen_tree, "soil"},
  33. {"default:pine_sapling", pine_grow, "soil"},
  34. {"default:bush_sapling", default.grow_bush, "soil"},
  35. {"default:acacia_bush_sapling", default.grow_acacia_bush, "soil"},
  36. {"default:large_cactus_seedling", default.grow_large_cactus, "sand"},
  37. {"default:blueberry_bush_sapling", default.grow_blueberry_bush, "soil"},
  38. {"default:pine_bush_sapling", default.grow_pine_bush, "soil"},
  39. }
  40. -- helper tables ( "" denotes a blank item )
  41. local green_grass = {
  42. "default:grass_2", "default:grass_3", "default:grass_4",
  43. "default:grass_5", "", ""
  44. }
  45. local dry_grass = {
  46. "default:dry_grass_2", "default:dry_grass_3", "default:dry_grass_4",
  47. "default:dry_grass_5", "", ""
  48. }
  49. local flowers = {""}
  50. for node, def in pairs(minetest.registered_nodes) do
  51. if def.groups.flower 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. ----- local functions
  71. -- particles
  72. local function particle_effect(pos)
  73. minetest.add_particlespawner({
  74. amount = 4,
  75. time = 0.15,
  76. minpos = pos,
  77. maxpos = pos,
  78. minvel = {x = -1, y = 2, z = -1},
  79. maxvel = {x = 1, y = 4, z = 1},
  80. minacc = {x = -1, y = -1, z = -1},
  81. maxacc = {x = 1, y = 1, z = 1},
  82. minexptime = 1,
  83. maxexptime = 1,
  84. minsize = 1,
  85. maxsize = 3,
  86. texture = "bonemeal_particle.png"
  87. })
  88. end
  89. -- tree type check
  90. local function grow_tree(pos, object)
  91. if type(object) == "table" and object.axiom then
  92. -- grow L-system tree
  93. minetest.remove_node(pos)
  94. minetest.spawn_tree(pos, object)
  95. elseif type(object) == "string" and minetest.registered_nodes[object] then
  96. -- place node
  97. minetest.set_node(pos, {name = object})
  98. elseif type(object) == "function" then
  99. -- function
  100. object(pos)
  101. end
  102. end
  103. -- sapling check
  104. local function check_sapling(pos, nodename)
  105. -- what is sapling placed on?
  106. local under = minetest.get_node({
  107. x = pos.x,
  108. y = pos.y - 1,
  109. z = pos.z
  110. })
  111. local can_grow, grow_on
  112. -- check list for sapling and function
  113. for n = 1, #saplings do
  114. if saplings[n][1] == nodename then
  115. grow_on = saplings[n][3]
  116. -- sapling grows on top of specific node
  117. if grow_on
  118. and grow_on ~= "soil"
  119. and grow_on ~= "sand"
  120. and grow_on == under.name then
  121. can_grow = true
  122. end
  123. -- sapling grows on top of soil (default)
  124. if can_grow == nil
  125. and (grow_on == nil or grow_on == "soil")
  126. and minetest.get_item_group(under.name, "soil") > 0 then
  127. can_grow = true
  128. end
  129. -- sapling grows on top of sand
  130. if can_grow == nil
  131. and grow_on == "sand"
  132. and minetest.get_item_group(under.name, "sand") > 0 then
  133. can_grow = true
  134. end
  135. -- check if we can grow sapling
  136. if can_grow then
  137. particle_effect(pos)
  138. grow_tree(pos, saplings[n][2])
  139. return
  140. end
  141. end
  142. end
  143. end
  144. -- crops check
  145. local function check_crops(pos, nodename, strength)
  146. local mod, crop, stage, nod, def
  147. -- grow registered crops
  148. for n = 1, #crops do
  149. if nodename:find(crops[n][1])
  150. or nodename == crops[n][3] then
  151. -- separate mod and node name
  152. mod = nodename:split(":")[1] .. ":"
  153. crop = nodename:split(":")[2]
  154. -- get stage number or set to 0 for seed
  155. stage = tonumber( crop:split("_")[2] ) or 0
  156. stage = min(stage + strength, crops[n][2])
  157. -- check for place_param setting
  158. nod = crops[n][1] .. stage
  159. def = minetest.registered_nodes[nod]
  160. def = def and def.place_param2 or 0
  161. minetest.set_node(pos, {name = nod, param2 = def})
  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. local pos2, nod, def
  199. -- loop through soil
  200. for _, n in pairs(dirt) do
  201. pos2 = n
  202. pos2.y = pos2.y + 1
  203. if random(5) == 1 then
  204. if decor and #decor > 0 then
  205. -- place random decoration (rare)
  206. local dnum = #decor or 1
  207. nod = decor[random(dnum)] or ""
  208. end
  209. else
  210. if grass and #grass > 0 then
  211. -- place random grass (common)
  212. local dgra = #grass or 1
  213. nod = #grass > 0 and grass[random(dgra)] or ""
  214. end
  215. end
  216. if nod and nod ~= "" then
  217. def = minetest.registered_nodes[nod]
  218. def = def and def.place_param2 or 0
  219. minetest.set_node(pos2, {name = nod, param2 = def})
  220. end
  221. particle_effect(pos2)
  222. end
  223. end
  224. -- global functions
  225. -- add to sapling list
  226. -- {sapling node, schematic or function name, "soil"|"sand"|specific_node}
  227. --e.g. {"default:sapling", default.grow_new_apple_tree, "soil"}
  228. function bonemeal:add_sapling(list)
  229. for n = 1, #list do
  230. table_insert(saplings, list[n])
  231. end
  232. end
  233. -- add to crop list to force grow
  234. -- {crop name start_, growth steps, seed node (if required)}
  235. -- e.g. {"farming:wheat_", 8, "farming:seed_wheat"}
  236. function bonemeal:add_crop(list)
  237. for n = 1, #list do
  238. table_insert(crops, list[n])
  239. end
  240. end
  241. -- add grass and flower/plant decoration for specific dirt types
  242. -- {dirt_node, {grass_nodes}, {flower_nodes}
  243. -- e.g. {"default:dirt_with_dry_grass", dry_grass, flowers}
  244. -- if an entry already exists for a given dirt type, it will add new entries and all empty
  245. -- entries, allowing to both add decorations and decrease their frequency.
  246. function bonemeal:add_deco(list)
  247. for l = 1, #list do
  248. for n = 1, #deco do
  249. -- update existing entry
  250. if list[l][1] == deco[n][1] then
  251. -- adding grass types
  252. for _,extra in pairs(list[l][2]) do
  253. if extra ~= "" then
  254. for _, entry in pairs(deco[n][2]) do
  255. if extra == entry then
  256. extra = false
  257. break
  258. end
  259. end
  260. end
  261. if extra then
  262. table_insert(deco[n][2], extra)
  263. end
  264. end
  265. -- adding decoration types
  266. for _,extra in pairs(list[l][3]) do
  267. if extra ~= "" then
  268. for _, entry in pairs(deco[n][3]) do
  269. if extra == entry then
  270. extra = false
  271. break
  272. end
  273. end
  274. end
  275. if extra then
  276. table_insert(deco[n][3], extra)
  277. end
  278. end
  279. list[l] = false
  280. break
  281. end
  282. end
  283. if list[l] then
  284. table_insert(deco, list[l])
  285. end
  286. end
  287. end
  288. -- definitively set a decration scheme
  289. -- this function will either add a new entry as is, or replace the existing one
  290. function bonemeal:set_deco(list)
  291. for l = 1, #list do
  292. for n = 1, #deco do
  293. -- replace existing entry
  294. if list[l][1] == deco[n][1] then
  295. deco[n][2] = list[l][2]
  296. deco[n][3] = list[l][3]
  297. list[l] = false
  298. break
  299. end
  300. end
  301. if list[l] then
  302. table_insert(deco, list[l])
  303. end
  304. end
  305. end
  306. -- global on_use function for bonemeal
  307. function bonemeal:on_use(pos, strength, node)
  308. -- get node pointed at
  309. local node = node or minetest.get_node(pos)
  310. -- return if nothing there
  311. if node.name == "ignore" then
  312. return
  313. end
  314. -- make sure strength is between 1 and 4
  315. strength = strength or 1
  316. strength = max(strength, 1)
  317. strength = min(strength, 4)
  318. -- papyrus and cactus
  319. if node.name == "default:papyrus" then
  320. default.grow_papyrus(pos, node)
  321. particle_effect(pos)
  322. return
  323. elseif node.name == "default:cactus" then
  324. default.grow_cactus(pos, node)
  325. particle_effect(pos)
  326. return
  327. end
  328. -- grow grass and flowers
  329. if minetest.get_item_group(node.name, "soil") > 0
  330. or minetest.get_item_group(node.name, "sand") > 0
  331. or minetest.get_item_group(node.name, "can_bonemeal") > 0 then
  332. check_soil(pos, node.name, strength)
  333. return
  334. end
  335. -- light check depending on strength (strength of 4 = no light needed)
  336. if (minetest.get_node_light(pos) or 0) < (12 - (strength * 3)) then
  337. return
  338. end
  339. -- check for tree growth if pointing at sapling
  340. -- if minetest.get_item_group(node.name, "sapling") > 0
  341. if random(5 - strength) == 1 then
  342. check_sapling(pos, node.name)
  343. return
  344. end
  345. -- check for crop growth
  346. check_crops(pos, node.name, strength)
  347. end
  348. ----- items
  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. --- crafting recipes
  427. -- gelatin powder
  428. minetest.register_craft({
  429. output = "bonemeal:gelatin_powder 4",
  430. recipe = {
  431. {"bonemeal:bone", "bonemeal:bone", "bonemeal:bone"},
  432. {"bucket:bucket_water", "bucket:bucket_water", "bucket:bucket_water"},
  433. {"bucket:bucket_water", "default:torch", "bucket:bucket_water"},
  434. },
  435. replacements = {
  436. {"bucket:bucket_water", "bucket:bucket_empty 5"},
  437. },
  438. })
  439. -- bonemeal (from bone)
  440. minetest.register_craft({
  441. type = "shapeless",
  442. output = "bonemeal:bonemeal 2",
  443. recipe = {"bonemeal:bone"}
  444. })
  445. -- bonemeal (from player bones)
  446. minetest.register_craft({
  447. type = "shapeless",
  448. output = "bonemeal:bonemeal 4",
  449. recipe = {"bones:bones"}
  450. })
  451. -- bonemeal (from coral skeleton)
  452. minetest.register_craft({
  453. type = "shapeless",
  454. output = "bonemeal:bonemeal 2",
  455. recipe = {"default:coral_skeleton"}
  456. })
  457. -- mulch
  458. minetest.register_craft({
  459. type = "shapeless",
  460. output = "bonemeal:mulch 4",
  461. recipe = {
  462. "group:tree", "group:leaves", "group:leaves",
  463. "group:leaves", "group:leaves", "group:leaves",
  464. "group:leaves", "group:leaves", "group:leaves"
  465. }
  466. })
  467. -- fertiliser
  468. minetest.register_craft({
  469. type = "shapeless",
  470. output = "bonemeal:fertiliser 2",
  471. recipe = {"bonemeal:bonemeal", "bonemeal:mulch"}
  472. })
  473. -- add bones to dirt
  474. minetest.override_item("default:dirt", {
  475. drop = {
  476. max_items = 1,
  477. items = {
  478. {
  479. items = {"bonemeal:bone"},
  480. rarity = 30
  481. },
  482. {
  483. items = {"default:dirt"}
  484. }
  485. }
  486. }
  487. })
  488. -- add support for other mods
  489. dofile(path .. "/mods.lua")
  490. dofile(path .. "/lucky_block.lua")
  491. print (S("[MOD] bonemeal loaded"))