trees.lua 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. local random = math.random
  2. local c_air = minetest.get_content_id("air")
  3. local c_leaves_1 = minetest.get_content_id("conifer:leaves_1")
  4. local c_leaves_2 = minetest.get_content_id("conifer:leaves_2")
  5. local c_snow = minetest.get_content_id("default:snow")
  6. local function add_trunk_and_leaves(data, a, pos, tree_cid, leaves_special, height, snow)
  7. local x, y, z = pos.x, pos.y, pos.z
  8. local leaves_cid = c_leaves_1
  9. if leaves_special then leaves_cid = c_leaves_2 else end
  10. -- Trunk
  11. for y_dist = 0, height - 1 do
  12. local vi = a:index(x, y + y_dist, z)
  13. if y_dist == 0 or data[vi] == c_air or data[vi] == c_leaves_1 or data[vi] == c_leaves_2 then
  14. data[vi] = tree_cid
  15. end
  16. end
  17. -- Add rings of leaves randomly
  18. local d = 0
  19. for yi = height+1, 4 + random(0, 2), -1 do
  20. for xi = -d, d do
  21. for zi = -d, d do
  22. if math.abs(xi) + math.abs(zi) <= d or math.abs(zi) + math.abs(xi) <= d then
  23. local vi = a:index(x + xi, y + yi, z + zi)
  24. if data[vi] == c_air then
  25. if leaves_special then
  26. data[vi] = c_leaves_2
  27. else
  28. data[vi] = c_leaves_1
  29. end
  30. -- Cover in snow
  31. if snow and random(1, 2) == 1 then
  32. local vi_snow = a:index(x + xi, y + yi + 1, z + zi)
  33. if data[vi_snow] == c_air then
  34. data[vi_snow] = c_snow
  35. end
  36. end
  37. end
  38. end
  39. end
  40. end
  41. d = d + 1
  42. if d > random(2,4) then d = 1 end
  43. end
  44. end
  45. local c_tree = minetest.get_content_id("conifer:tree")
  46. function conifer.grow_tree(pos, leaves_special, snow)
  47. local x, y, z = pos.x, pos.y, pos.z
  48. local height = random(12, 24)
  49. local vm = minetest.get_voxel_manip()
  50. local minp, maxp = vm:read_from_map(
  51. {x = pos.x - 3, y = pos.y - 1, z = pos.z - 3},
  52. {x = pos.x + 3, y = pos.y + height + 1, z = pos.z + 3}
  53. )
  54. local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp})
  55. local data = vm:get_data()
  56. add_trunk_and_leaves(data, a, pos, c_tree, leaves_special, height, snow)
  57. -- Roots
  58. for xi = -1, 1 do
  59. local vi_1 = a:index(x+xi, y, z)
  60. local vi_2 = a:index(x+xi, y-1, z)
  61. if data[vi_2] == c_air then
  62. data[vi_2] = c_tree
  63. elseif data[vi_1] == c_air then
  64. data[vi_1] = c_tree
  65. end
  66. end
  67. for zi = -1, 1 do
  68. local vi_1 = a:index(x, y, z+zi)
  69. local vi_2 = a:index(x, y-1, z+zi)
  70. if data[vi_2] == c_air then
  71. data[vi_2] = c_tree
  72. elseif data[vi_1] == c_air then
  73. data[vi_1] = c_tree
  74. end
  75. end
  76. vm:set_data(data)
  77. vm:write_to_map()
  78. vm:update_map()
  79. end
  80. function conifer.grow_conifersapling(pos)
  81. if not default.can_grow(pos) then return true end
  82. if minetest.find_node_near(pos, 3, {"group:tree", "group:sapling"}) then
  83. minetest.set_node(pos, {name="conifer:leaves_"..random(1, 2)})
  84. return
  85. end
  86. if not default.enough_light(pos) then
  87. minetest.get_node_timer(pos):start(math.random(60, 960))
  88. return
  89. end
  90. conifer.grow_tree(pos, random(1, 4) == 1)
  91. end
  92. minetest.register_lbm({
  93. name = "conifer:convert_saplings_to_node_timer",
  94. nodenames = {"conifer:sapling"},
  95. action = function(pos)
  96. minetest.get_node_timer(pos):start(random(600, 4800))
  97. end
  98. })