diff --git a/mods/default/trees.lua b/mods/default/trees.lua index 03c3f198..ff99d09f 100644 --- a/mods/default/trees.lua +++ b/mods/default/trees.lua @@ -2,17 +2,19 @@ -- Grow trees -- +local random = math.random + local function can_grow(pos) - local node_under = minetest.get_node_or_nil({x = pos.x, y = pos.y - 1, z = pos.z}) - if not node_under then - return false - end - local name_under = node_under.name - local is_soil = minetest.get_item_group(name_under, "soil") - if is_soil == 0 then - return false - end - return true + local node_under = minetest.get_node_or_nil({x = pos.x, y = pos.y - 1, z = pos.z}) + if not node_under then + return false + end + local name_under = node_under.name + local is_soil = minetest.get_item_group(name_under, "soil") + if is_soil == 0 then + return false + end + return true end minetest.register_abm({ @@ -25,7 +27,7 @@ minetest.register_abm({ end minetest.log("action", "A sapling grows into a tree at "..minetest.pos_to_string(pos)) - default.grow_tree(pos, math.random(1, 4) == 1) + default.grow_tree(pos, random(1, 4) == 1) end }) @@ -38,15 +40,70 @@ minetest.register_abm({ return end - minetest.log("action", "A jungle sapling grows into a tree at "..minetest.pos_to_string(pos)) + minetest.log("action", "A jungle sapling grows into a tree at ".. + minetest.pos_to_string(pos)) default.grow_jungletree(pos) end }) + local c_air = minetest.get_content_id("air") +local c_apple = minetest.get_content_id("default:apple") + +local function add_trunk_and_leaves(data, a, pos, tree_cid, leaves_cid, + height, size, iters, is_apple_tree) + local x, y, z = pos.x, pos.y, pos.z + + -- Trunk + for y_dist = 0, height - 1 do + local vi = a:index(x, y + y_dist, z) + if y_dist == 0 or data[vi] == c_air then + data[vi] = tree_cid + end + end + + -- Force leaves near the trunk + for x_dist = -1, 1 do + for y_dist = -size, 1 do + for z_dist = -1, 1 do + local vi = a:index(x + x_dist, y + height + y_dist, z + z_dist) + if data[vi] == c_air then + if is_apple_tree and random(1, 8) == 1 then + data[vi] = c_apple + else + data[vi] = leaves_cid + end + end + end + end + end + + -- Randomly add leaves in 2x2x2 clusters. + for i = 1, iters do + local clust_x = x + random(-size, size - 1) + local clust_y = y + height + random(-size, 0) + local clust_z = z + random(-size, size - 1) + + for xi = 0, 1 do + for yi = 0, 1 do + for zi = 0, 1 do + local vi = a:index(clust_x + xi, clust_y + yi, clust_z + zi) + if data[vi] == c_air then + if is_apple_tree and random(1, 8) == 1 then + data[vi] = c_apple + else + data[vi] = leaves_cid + end + end + end + end + end + end +end + + local c_tree = minetest.get_content_id("default:tree") local c_leaves = minetest.get_content_id("default:leaves") -local c_apple = minetest.get_content_id("default:apple") function default.grow_tree(pos, is_apple_tree, bad) --[[ @@ -58,71 +115,19 @@ function default.grow_tree(pos, is_apple_tree, bad) error("Deprecated use of default.grow_tree") end + local x, y, z = pos.x, pos.y, pos.z + local height = random(4, 5) + local vm = minetest.get_voxel_manip() local minp, maxp = vm:read_from_map( {x = pos.x - 2, y = pos.y, z = pos.z - 2}, - {x = pos.x + 2, y = pos.y + 6, z = pos.z + 2} + {x = pos.x + 2, y = pos.y + height + 1, z = pos.z + 2} ) local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp}) local data = vm:get_data() - local random = math.random - local th = random(4, 5) - local x, y, z = pos.x, pos.y, pos.z - for yy = y, y + th - 1 do - local vi = a:index(x, yy, z) - if a:contains(x, yy, z) and (data[vi] == c_air or yy == y) then - data[vi] = c_tree - end - end - y = y + th - 1 -- (x, y, z) is now last piece of trunk - local leaves_a = VoxelArea:new({ - MinEdge = {x = -2, y = -1, z = -2}, - MaxEdge = {x = 2, y = 2, z = 2}, - }) - local leaves_buffer = {} + add_trunk_and_leaves(data, a, pos, c_tree, c_leaves, height, 2, 8, is_apple_tree) - -- Force leaves near the trunk - local d = 1 - for xi = -d, d do - for yi = -d, d do - for zi = -d, d do - leaves_buffer[leaves_a:index(xi, yi, zi)] = true - end - end - end - - -- Add leaves randomly - for iii = 1, 8 do - local d = 1 - local xx = random(leaves_a.MinEdge.x, leaves_a.MaxEdge.x - d) - local yy = random(leaves_a.MinEdge.y, leaves_a.MaxEdge.y - d) - local zz = random(leaves_a.MinEdge.z, leaves_a.MaxEdge.z - d) - - for xi = 0, d do - for yi = 0, d do - for zi = 0, d do - leaves_buffer[leaves_a:index(xx+xi, yy+yi, zz+zi)] = true - end - end - end - end - - -- Add the leaves - for xi = -2, 2 do - for yi = -1, 2 do - for zi = -2, 2 do - local vi = a:index(x + xi, y + yi, z + zi) - if data[vi] == c_air and leaves_buffer[leaves_a:index(xi, yi, zi)] then - if is_apple_tree and random(1, 100) <= 10 then - data[vi] = c_apple - else - data[vi] = c_leaves - end - end - end - end - end vm:set_data(data) vm:write_to_map() vm:update_map() @@ -141,85 +146,33 @@ function default.grow_jungletree(pos, bad) error("Deprecated use of default.grow_jungletree") end + local x, y, z = pos.x, pos.y, pos.z + local height = random(8, 12) + local vm = minetest.get_voxel_manip() local minp, maxp = vm:read_from_map( - {x = pos.x - 2, y = pos.y - 1, z = pos.z - 2}, - {x = pos.x + 2, y = pos.y + 12, z = pos.z + 2}) + {x = pos.x - 3, y = pos.y - 1, z = pos.z - 3}, + {x = pos.x + 3, y = pos.y + height + 1, z = pos.z + 3}) local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp}) local data = vm:get_data() - local random = math.random - local x, y, z = pos.x, pos.y, pos.z + add_trunk_and_leaves(data, a, pos, c_jungletree, c_jungleleaves, height, 3, 30, false) - -- Add the roots - for xi = -1, 1 do - for zi = -1, 1 do + -- Roots + for x_dist = -1, 1 do + for z_dist = -1, 1 do if random(1, 3) >= 2 then - local vi1 = a:index(x + xi, y, z + zi) - local vi2 = a:index(x + xi, y - 1, z + zi) - if data[vi2] == c_air then - data[vi2] = c_jungletree - elseif data[vi1] == c_air then - data[vi1] = c_jungletree + local vi_1 = a:index(x + x_dist, y - 1, z + z_dist) + local vi_2 = a:index(x + x_dist, y, z + z_dist) + if data[vi_1] == c_air then + data[vi_1] = c_jungletree + elseif data[vi_2] == c_air then + data[vi_2] = c_jungletree end end end end - -- Add the trunk - local th = random(8, 12) - for yy = y, y + th - 1 do - local vi = a:index(x, yy, z) - if data[vi] == c_air or yy == y then - data[vi] = c_jungletree - end - end - y = y + th - 1 -- (x, y, z) is now last piece of trunk - local leaves_a = VoxelArea:new({ - MinEdge = {x = -3, y = -2, z = -3}, - MaxEdge = {x = 3, y = 2, z = 3} - }) - local leaves_buffer = {} - - -- Force leaves near the trunk - local d = 1 - for xi = -d, d do - for yi = -d, d do - for zi = -d, d do - leaves_buffer[leaves_a:index(xi, yi, zi)] = true - end - end - end - - -- Add leaves randomly - for iii = 1, 30 do - local d = 1 - local xx = random(leaves_a.MinEdge.x, leaves_a.MaxEdge.x - d) - local yy = random(leaves_a.MinEdge.y, leaves_a.MaxEdge.y - d) - local zz = random(leaves_a.MinEdge.z, leaves_a.MaxEdge.z - d) - - for xi = 0, d do - for yi = 0, d do - for zi = 0, d do - leaves_buffer[leaves_a:index(xx + xi, yy + yi, zz + zi)] = true - end - end - end - end - - -- Add the leaves - for xi = -3, 3 do - for yi = -2, 2 do - for zi = -3, 3 do - local vi = a:index(x + xi, y + yi, z + zi) - if data[vi] == c_air then - if leaves_buffer[leaves_a:index(xi, yi, zi)] then - data[vi] = c_jungleleaves - end - end - end - end - end vm:set_data(data) vm:write_to_map() vm:update_map()