functions.lua 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. -- mods/default/functions.lua
  2. --
  3. -- Sounds
  4. --
  5. function default.node_sound_defaults(table)
  6. table = table or {}
  7. table.footstep = table.footstep or
  8. {name="", gain=1.0}
  9. table.dug = table.dug or
  10. {name="default_dug_node", gain=0.25}
  11. table.place = table.place or
  12. {name="default_place_node_hard", gain=1.0}
  13. return table
  14. end
  15. function default.node_sound_stone_defaults(table)
  16. table = table or {}
  17. table.footstep = table.footstep or
  18. {name="default_hard_footstep", gain=0.5}
  19. table.dug = table.dug or
  20. {name="default_hard_footstep", gain=1.0}
  21. default.node_sound_defaults(table)
  22. return table
  23. end
  24. function default.node_sound_dirt_defaults(table)
  25. table = table or {}
  26. table.footstep = table.footstep or
  27. {name="default_dirt_footstep", gain=1.0}
  28. table.dug = table.dug or
  29. {name="default_dirt_footstep", gain=1.5}
  30. table.place = table.place or
  31. {name="default_place_node", gain=1.0}
  32. default.node_sound_defaults(table)
  33. return table
  34. end
  35. function default.node_sound_sand_defaults(table)
  36. table = table or {}
  37. table.footstep = table.footstep or
  38. {name="default_sand_footstep", gain=0.5}
  39. table.dug = table.dug or
  40. {name="default_sand_footstep", gain=1.0}
  41. table.place = table.place or
  42. {name="default_place_node", gain=1.0}
  43. default.node_sound_defaults(table)
  44. return table
  45. end
  46. function default.node_sound_wood_defaults(table)
  47. table = table or {}
  48. table.footstep = table.footstep or
  49. {name="default_wood_footstep", gain=0.5}
  50. table.dug = table.dug or
  51. {name="default_wood_footstep", gain=1.0}
  52. default.node_sound_defaults(table)
  53. return table
  54. end
  55. function default.node_sound_leaves_defaults(table)
  56. table = table or {}
  57. table.footstep = table.footstep or
  58. {name="default_grass_footstep", gain=0.35}
  59. table.dug = table.dug or
  60. {name="default_grass_footstep", gain=0.85}
  61. table.dig = table.dig or
  62. {name="default_dig_crumbly", gain=0.4}
  63. table.place = table.place or
  64. {name="default_place_node", gain=1.0}
  65. default.node_sound_defaults(table)
  66. return table
  67. end
  68. function default.node_sound_glass_defaults(table)
  69. table = table or {}
  70. table.footstep = table.footstep or
  71. {name="default_glass_footstep", gain=0.5}
  72. table.dug = table.dug or
  73. {name="default_break_glass", gain=1.0}
  74. default.node_sound_defaults(table)
  75. return table
  76. end
  77. --
  78. -- Legacy
  79. --
  80. function default.spawn_falling_node(p, nodename)
  81. spawn_falling_node(p, nodename)
  82. end
  83. -- Horrible crap to support old code
  84. -- Don't use this and never do what this does, it's completely wrong!
  85. -- (More specifically, the client and the C++ code doesn't get the group)
  86. function default.register_falling_node(nodename, texture)
  87. minetest.log("error", debug.traceback())
  88. minetest.log('error', "WARNING: default.register_falling_node is deprecated")
  89. if minetest.registered_nodes[nodename] then
  90. minetest.registered_nodes[nodename].groups.falling_node = 1
  91. end
  92. end
  93. --
  94. -- Global callbacks
  95. --
  96. -- Global environment step function
  97. function on_step(dtime)
  98. -- print("on_step")
  99. end
  100. minetest.register_globalstep(on_step)
  101. function on_placenode(p, node)
  102. --print("on_placenode")
  103. end
  104. minetest.register_on_placenode(on_placenode)
  105. function on_dignode(p, node)
  106. --print("on_dignode")
  107. end
  108. minetest.register_on_dignode(on_dignode)
  109. function on_punchnode(p, node)
  110. end
  111. minetest.register_on_punchnode(on_punchnode)
  112. --
  113. -- Grow trees
  114. --
  115. minetest.register_abm({
  116. nodenames = {"default:sapling"},
  117. interval = 10,
  118. chance = 50,
  119. action = function(pos, node)
  120. local nu = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name
  121. local is_soil = minetest.get_item_group(nu, "soil")
  122. if is_soil == 0 then
  123. return
  124. end
  125. minetest.log("action", "A sapling grows into a tree at "..minetest.pos_to_string(pos))
  126. local vm = minetest.get_voxel_manip()
  127. local minp, maxp = vm:read_from_map({x=pos.x-16, y=pos.y, z=pos.z-16}, {x=pos.x+16, y=pos.y+16, z=pos.z+16})
  128. local a = VoxelArea:new{MinEdge=minp, MaxEdge=maxp}
  129. local data = vm:get_data()
  130. default.grow_tree(data, a, pos, math.random(1, 4) == 1, math.random(1,100000))
  131. vm:set_data(data)
  132. vm:write_to_map(data)
  133. vm:update_map()
  134. end
  135. })
  136. minetest.register_abm({
  137. nodenames = {"default:junglesapling"},
  138. interval = 10,
  139. chance = 50,
  140. action = function(pos, node)
  141. local nu = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name
  142. local is_soil = minetest.get_item_group(nu, "soil")
  143. if is_soil == 0 then
  144. return
  145. end
  146. minetest.log("action", "A jungle sapling grows into a tree at "..minetest.pos_to_string(pos))
  147. local vm = minetest.get_voxel_manip()
  148. local minp, maxp = vm:read_from_map({x=pos.x-16, y=pos.y-1, z=pos.z-16}, {x=pos.x+16, y=pos.y+16, z=pos.z+16})
  149. local a = VoxelArea:new{MinEdge=minp, MaxEdge=maxp}
  150. local data = vm:get_data()
  151. default.grow_jungletree(data, a, pos, math.random(1,100000))
  152. vm:set_data(data)
  153. vm:write_to_map(data)
  154. vm:update_map()
  155. end
  156. })
  157. --
  158. -- Lavacooling
  159. --
  160. default.cool_lava_source = function(pos)
  161. minetest.set_node(pos, {name="default:obsidian"})
  162. minetest.sound_play("default_cool_lava", {pos = pos, gain = 0.25})
  163. end
  164. default.cool_lava_flowing = function(pos)
  165. minetest.set_node(pos, {name="default:stone"})
  166. minetest.sound_play("default_cool_lava", {pos = pos, gain = 0.25})
  167. end
  168. minetest.register_abm({
  169. nodenames = {"default:lava_flowing"},
  170. neighbors = {"group:water"},
  171. interval = 1,
  172. chance = 1,
  173. action = function(pos, node, active_object_count, active_object_count_wider)
  174. default.cool_lava_flowing(pos, node, active_object_count, active_object_count_wider)
  175. end,
  176. })
  177. minetest.register_abm({
  178. nodenames = {"default:lava_source"},
  179. neighbors = {"group:water"},
  180. interval = 1,
  181. chance = 1,
  182. action = function(pos, node, active_object_count, active_object_count_wider)
  183. default.cool_lava_source(pos, node, active_object_count, active_object_count_wider)
  184. end,
  185. })
  186. --
  187. -- Papyrus and cactus growing
  188. --
  189. minetest.register_abm({
  190. nodenames = {"default:cactus"},
  191. neighbors = {"group:sand"},
  192. interval = 50,
  193. chance = 20,
  194. action = function(pos, node)
  195. pos.y = pos.y-1
  196. local name = minetest.get_node(pos).name
  197. if minetest.get_item_group(name, "sand") ~= 0 then
  198. pos.y = pos.y+1
  199. local height = 0
  200. while minetest.get_node(pos).name == "default:cactus" and height < 4 do
  201. height = height+1
  202. pos.y = pos.y+1
  203. end
  204. if height < 4 then
  205. if minetest.get_node(pos).name == "air" then
  206. minetest.set_node(pos, {name="default:cactus"})
  207. end
  208. end
  209. end
  210. end,
  211. })
  212. minetest.register_abm({
  213. nodenames = {"default:papyrus"},
  214. neighbors = {"default:dirt", "default:dirt_with_grass"},
  215. interval = 50,
  216. chance = 20,
  217. action = function(pos, node)
  218. pos.y = pos.y-1
  219. local name = minetest.get_node(pos).name
  220. if name == "default:dirt" or name == "default:dirt_with_grass" then
  221. if minetest.find_node_near(pos, 3, {"group:water"}) == nil then
  222. return
  223. end
  224. pos.y = pos.y+1
  225. local height = 0
  226. while minetest.get_node(pos).name == "default:papyrus" and height < 4 do
  227. height = height+1
  228. pos.y = pos.y+1
  229. end
  230. if height < 4 then
  231. if minetest.get_node(pos).name == "air" then
  232. minetest.set_node(pos, {name="default:papyrus"})
  233. end
  234. end
  235. end
  236. end,
  237. })
  238. --
  239. -- dig upwards
  240. --
  241. function default.dig_up(pos, node, digger)
  242. if digger == nil then return end
  243. local np = {x = pos.x, y = pos.y + 1, z = pos.z}
  244. local nn = minetest.get_node(np)
  245. if nn.name == node.name then
  246. minetest.node_dig(np, nn, digger)
  247. end
  248. end
  249. --
  250. -- Leafdecay
  251. --
  252. -- To enable leaf decay for a node, add it to the "leafdecay" group.
  253. --
  254. -- The rating of the group determines how far from a node in the group "tree"
  255. -- the node can be without decaying.
  256. --
  257. -- If param2 of the node is ~= 0, the node will always be preserved. Thus, if
  258. -- the player places a node of that kind, you will want to set param2=1 or so.
  259. --
  260. -- If the node is in the leafdecay_drop group then the it will always be dropped
  261. -- as an item
  262. default.leafdecay_trunk_cache = {}
  263. default.leafdecay_enable_cache = true
  264. -- Spread the load of finding trunks
  265. default.leafdecay_trunk_find_allow_accumulator = 0
  266. minetest.register_globalstep(function(dtime)
  267. local finds_per_second = 5000
  268. default.leafdecay_trunk_find_allow_accumulator =
  269. math.floor(dtime * finds_per_second)
  270. end)
  271. minetest.register_abm({
  272. nodenames = {"group:leafdecay"},
  273. neighbors = {"air", "group:liquid"},
  274. -- A low interval and a high inverse chance spreads the load
  275. interval = 2,
  276. chance = 5,
  277. action = function(p0, node, _, _)
  278. --print("leafdecay ABM at "..p0.x..", "..p0.y..", "..p0.z..")")
  279. local do_preserve = false
  280. local d = minetest.registered_nodes[node.name].groups.leafdecay
  281. if not d or d == 0 then
  282. --print("not groups.leafdecay")
  283. return
  284. end
  285. local n0 = minetest.get_node(p0)
  286. if n0.param2 ~= 0 then
  287. --print("param2 ~= 0")
  288. return
  289. end
  290. local p0_hash = nil
  291. if default.leafdecay_enable_cache then
  292. p0_hash = minetest.hash_node_position(p0)
  293. local trunkp = default.leafdecay_trunk_cache[p0_hash]
  294. if trunkp then
  295. local n = minetest.get_node(trunkp)
  296. local reg = minetest.registered_nodes[n.name]
  297. -- Assume ignore is a trunk, to make the thing work at the border of the active area
  298. if n.name == "ignore" or (reg and reg.groups.tree and reg.groups.tree ~= 0) then
  299. --print("cached trunk still exists")
  300. return
  301. end
  302. --print("cached trunk is invalid")
  303. -- Cache is invalid
  304. table.remove(default.leafdecay_trunk_cache, p0_hash)
  305. end
  306. end
  307. if default.leafdecay_trunk_find_allow_accumulator <= 0 then
  308. return
  309. end
  310. default.leafdecay_trunk_find_allow_accumulator =
  311. default.leafdecay_trunk_find_allow_accumulator - 1
  312. -- Assume ignore is a trunk, to make the thing work at the border of the active area
  313. local p1 = minetest.find_node_near(p0, d, {"ignore", "group:tree"})
  314. if p1 then
  315. do_preserve = true
  316. if default.leafdecay_enable_cache then
  317. --print("caching trunk")
  318. -- Cache the trunk
  319. default.leafdecay_trunk_cache[p0_hash] = p1
  320. end
  321. end
  322. if not do_preserve then
  323. -- Drop stuff other than the node itself
  324. itemstacks = minetest.get_node_drops(n0.name)
  325. for _, itemname in ipairs(itemstacks) do
  326. if minetest.get_item_group(n0.name, "leafdecay_drop") ~= 0 or
  327. itemname ~= n0.name then
  328. local p_drop = {
  329. x = p0.x - 0.5 + math.random(),
  330. y = p0.y - 0.5 + math.random(),
  331. z = p0.z - 0.5 + math.random(),
  332. }
  333. minetest.add_item(p_drop, itemname)
  334. end
  335. end
  336. -- Remove node
  337. minetest.remove_node(p0)
  338. nodeupdate(p0)
  339. end
  340. end
  341. })