Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c32957f
commit 9670c27
Showing
2 changed files
with
173 additions
and
190 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,150 +1,183 @@ | ||
-- | ||
-- 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 | ||
end | ||
|
||
minetest.register_abm({ | ||
nodenames = {"default:sapling"}, | ||
interval = 10, | ||
chance = 50, | ||
action = function(pos, node) | ||
if not can_grow(pos) then | ||
return | ||
end | ||
|
||
minetest.log("action", "A sapling grows into a tree at "..minetest.pos_to_string(pos)) | ||
default.grow_tree(pos, random(1, 4) == 1) | ||
end | ||
}) | ||
|
||
minetest.register_abm({ | ||
nodenames = {"default:junglesapling"}, | ||
interval = 10, | ||
chance = 50, | ||
action = function(pos, node) | ||
if not can_grow(pos) then | ||
return | ||
end | ||
|
||
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_ignore = minetest.get_content_id("ignore") | ||
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 or data[vi] == leaves_cid then | ||
data[vi] = tree_cid | ||
end | ||
end | ||
|
||
-- Force leaves near the trunk | ||
for z_dist = -1, 1 do | ||
for y_dist = -size, 1 do | ||
local vi = a:index(x - 1, y + height + y_dist, z + z_dist) | ||
for x_dist = -1, 1 do | ||
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 | ||
vi = vi + 1 | ||
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(data, a, pos, is_apple_tree, seed) | ||
--[[ | ||
NOTE: Tree-placing code is currently duplicated in the engine | ||
and in games that have saplings; both are deprecated but not | ||
replaced yet | ||
]]-- | ||
local pr = PseudoRandom(seed) | ||
local th = pr:next(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 = {} | ||
|
||
-- 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 = pr:next(leaves_a.MinEdge.x, leaves_a.MaxEdge.x - d) | ||
local yy = pr:next(leaves_a.MinEdge.y, leaves_a.MaxEdge.y - d) | ||
local zz = pr:next(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 = leaves_a.MinEdge.x, leaves_a.MaxEdge.x do | ||
for yi = leaves_a.MinEdge.y, leaves_a.MaxEdge.y do | ||
for zi = leaves_a.MinEdge.z, leaves_a.MaxEdge.z do | ||
if a:contains(x+xi, y+yi, z+zi) then | ||
local vi = a:index(x+xi, y+yi, z+zi) | ||
if data[vi] == c_air or data[vi] == c_ignore then | ||
if leaves_buffer[leaves_a:index(xi, yi, zi)] then | ||
if is_apple_tree and pr:next(1, 100) <= 10 then | ||
data[vi] = c_apple | ||
else | ||
data[vi] = c_leaves | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
function default.grow_tree(pos, is_apple_tree, bad) | ||
--[[ | ||
NOTE: Tree-placing code is currently duplicated in the engine | ||
and in games that have saplings; both are deprecated but not | ||
replaced yet | ||
--]] | ||
if bad then | ||
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 + height + 1, z = pos.z + 2} | ||
) | ||
local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp}) | ||
local data = vm:get_data() | ||
add_trunk_and_leaves(data, a, pos, c_tree, c_leaves, height, 2, 8, is_apple_tree) | ||
vm:set_data(data) | ||
vm:write_to_map() | ||
vm:update_map() | ||
end | ||
local c_jungletree = minetest.get_content_id("default:jungletree") | ||
local c_jungleleaves = minetest.get_content_id("default:jungleleaves") | ||
function default.grow_jungletree(data, a, pos, seed) | ||
--[[ | ||
NOTE: Tree-placing code is currently duplicated in the engine | ||
and in games that have saplings; both are deprecated but not | ||
replaced yet | ||
]]-- | ||
local pr = PseudoRandom(seed) | ||
local x, y, z = pos.x, pos.y, pos.z | ||
for xi = -1, 1 do | ||
for zi = -1, 1 do | ||
if pr:next(1, 3) >= 2 then | ||
local vi1 = a:index(x+xi, y, z+zi) | ||
local vi2 = a:index(x+xi, y-1, z+zi) | ||
if a:contains(x+xi, y-1, z+zi) and data[vi2] == c_air then | ||
data[vi2] = c_jungletree | ||
elseif a:contains(x+xi, y, z+zi) and data[vi1] == c_air then | ||
data[vi1] = c_jungletree | ||
end | ||
end | ||
end | ||
end | ||
|
||
local th = pr:next(8, 12) | ||
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_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 = pr:next(leaves_a.MinEdge.x, leaves_a.MaxEdge.x - d) | ||
local yy = pr:next(leaves_a.MinEdge.y, leaves_a.MaxEdge.y - d) | ||
local zz = pr:next(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 = leaves_a.MinEdge.x, leaves_a.MaxEdge.x do | ||
for yi = leaves_a.MinEdge.y, leaves_a.MaxEdge.y do | ||
for zi = leaves_a.MinEdge.z, leaves_a.MaxEdge.z do | ||
if a:contains(x+xi, y+yi, z+zi) then | ||
local vi = a:index(x+xi, y+yi, z+zi) | ||
if data[vi] == c_air or data[vi] == c_ignore then | ||
if leaves_buffer[leaves_a:index(xi, yi, zi)] then | ||
data[vi] = c_jungleleaves | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
function default.grow_jungletree(pos, bad) | ||
--[[ | ||
NOTE: Tree-placing code is currently duplicated in the engine | ||
and in games that have saplings; both are deprecated but not | ||
replaced yet | ||
--]] | ||
if bad then | ||
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 - 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() | ||
add_trunk_and_leaves(data, a, pos, c_jungletree, c_jungleleaves, height, 3, 30, false) | ||
-- Roots | ||
for z_dist = -1, 1 do | ||
local vi_1 = a:index(x - 1, y - 1, z + z_dist) | ||
local vi_2 = a:index(x - 1, y, z + z_dist) | ||
for x_dist = -1, 1 do | ||
if random(1, 3) >= 2 then | ||
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 | ||
vi_1 = vi_1 + 1 | ||
vi_2 = vi_2 + 1 | ||
end | ||
end | ||
vm:set_data(data) | ||
vm:write_to_map() | ||
vm:update_map() | ||
end | ||