2019-09-10 19:09:51 +02:00
|
|
|
-- default/trees.lua
|
|
|
|
|
|
|
|
-- support for MT game translation.
|
|
|
|
local S = default.get_translator
|
|
|
|
|
2016-02-25 01:29:35 +01:00
|
|
|
local random = math.random
|
|
|
|
|
2014-06-13 20:03:14 +02:00
|
|
|
--
|
2015-08-07 21:24:12 +02:00
|
|
|
-- Grow trees from saplings
|
2014-06-13 20:03:14 +02:00
|
|
|
--
|
|
|
|
|
2016-02-25 01:29:35 +01:00
|
|
|
-- 'can grow' function
|
2014-06-13 20:03:14 +02:00
|
|
|
|
2015-11-23 01:55:11 +01:00
|
|
|
function default.can_grow(pos)
|
2014-06-13 20:03:14 +02:00
|
|
|
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
|
2020-04-07 19:36:03 +02:00
|
|
|
if minetest.get_item_group(node_under.name, "soil") == 0 then
|
2014-06-13 20:03:14 +02:00
|
|
|
return false
|
|
|
|
end
|
2015-10-27 02:10:25 +01:00
|
|
|
local light_level = minetest.get_node_light(pos)
|
|
|
|
if not light_level or light_level < 13 then
|
|
|
|
return false
|
2015-10-16 12:51:27 +02:00
|
|
|
end
|
2014-06-13 20:03:14 +02:00
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
2023-09-12 15:43:41 +02:00
|
|
|
function default.on_grow_failed(pos)
|
|
|
|
minetest.get_node_timer(pos):start(300)
|
|
|
|
end
|
|
|
|
|
2014-06-13 20:03:14 +02:00
|
|
|
|
2016-02-25 01:29:35 +01:00
|
|
|
-- 'is snow nearby' function
|
|
|
|
|
|
|
|
local function is_snow_nearby(pos)
|
2017-01-31 15:14:13 +01:00
|
|
|
return minetest.find_node_near(pos, 1, {"group:snowy"})
|
2016-02-25 01:29:35 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
|
2015-07-20 03:33:30 +02:00
|
|
|
|
2015-08-07 21:24:12 +02:00
|
|
|
--
|
|
|
|
-- Tree generation
|
|
|
|
--
|
2014-06-13 20:03:14 +02:00
|
|
|
|
2015-08-07 21:24:12 +02:00
|
|
|
-- Apple tree and jungle tree trunk and leaves function
|
2014-06-13 20:03:14 +02:00
|
|
|
|
|
|
|
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
|
2014-12-04 04:47:46 +01:00
|
|
|
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")
|
2014-06-13 20:03:14 +02:00
|
|
|
|
|
|
|
-- Trunk
|
2015-07-04 22:00:41 +02:00
|
|
|
data[a:index(x, y, z)] = tree_cid -- Force-place lowest trunk node to replace sapling
|
|
|
|
for yy = y + 1, y + height - 1 do
|
|
|
|
local vi = a:index(x, yy, z)
|
2014-12-04 04:47:46 +01:00
|
|
|
local node_id = data[vi]
|
2015-07-04 22:00:41 +02:00
|
|
|
if node_id == c_air or node_id == c_ignore or node_id == leaves_cid then
|
2014-06-13 20:03:14 +02:00
|
|
|
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
|
2014-12-04 04:47:46 +01:00
|
|
|
if data[vi] == c_air or data[vi] == c_ignore then
|
2014-06-13 20:03:14 +02:00
|
|
|
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)
|
2014-12-04 04:47:46 +01:00
|
|
|
if data[vi] == c_air or data[vi] == c_ignore then
|
2014-06-13 20:03:14 +02:00
|
|
|
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
|
|
|
|
|
2015-08-07 21:24:12 +02:00
|
|
|
|
|
|
|
-- Apple tree
|
2013-11-06 23:41:49 +01:00
|
|
|
|
2014-06-13 20:03:14 +02:00
|
|
|
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)
|
2014-12-04 04:47:46 +01:00
|
|
|
local c_tree = minetest.get_content_id("default:tree")
|
|
|
|
local c_leaves = minetest.get_content_id("default:leaves")
|
2014-06-13 20:03:14 +02:00
|
|
|
|
|
|
|
local vm = minetest.get_voxel_manip()
|
|
|
|
local minp, maxp = vm:read_from_map(
|
2016-06-26 13:34:14 +02:00
|
|
|
{x = x - 2, y = y, z = z - 2},
|
|
|
|
{x = x + 2, y = y + height + 1, z = z + 2}
|
2014-06-13 20:03:14 +02:00
|
|
|
)
|
|
|
|
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()
|
2013-11-06 23:41:49 +01:00
|
|
|
end
|
|
|
|
|
2015-08-07 21:24:12 +02:00
|
|
|
-- Jungle tree
|
2013-11-06 23:41:49 +01:00
|
|
|
|
2014-12-07 15:25:39 +01:00
|
|
|
function default.grow_jungle_tree(pos, bad)
|
2014-06-13 20:03:14 +02:00
|
|
|
--[[
|
2014-12-04 04:47:46 +01:00
|
|
|
NOTE: Jungletree-placing code is currently duplicated in the engine
|
2014-06-13 20:03:14 +02:00
|
|
|
and in games that have saplings; both are deprecated but not
|
|
|
|
replaced yet
|
|
|
|
--]]
|
|
|
|
if bad then
|
2014-12-07 15:25:39 +01:00
|
|
|
error("Deprecated use of default.grow_jungle_tree")
|
2014-06-13 20:03:14 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local x, y, z = pos.x, pos.y, pos.z
|
|
|
|
local height = random(8, 12)
|
2014-12-04 04:47:46 +01:00
|
|
|
local c_air = minetest.get_content_id("air")
|
|
|
|
local c_ignore = minetest.get_content_id("ignore")
|
|
|
|
local c_jungletree = minetest.get_content_id("default:jungletree")
|
|
|
|
local c_jungleleaves = minetest.get_content_id("default:jungleleaves")
|
2014-06-13 20:03:14 +02:00
|
|
|
|
|
|
|
local vm = minetest.get_voxel_manip()
|
|
|
|
local minp, maxp = vm:read_from_map(
|
2016-06-26 13:34:14 +02:00
|
|
|
{x = x - 3, y = y - 1, z = z - 3},
|
|
|
|
{x = x + 3, y = y + height + 1, z = z + 3}
|
2014-12-04 04:47:46 +01:00
|
|
|
)
|
2014-06-13 20:03:14 +02:00
|
|
|
local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp})
|
|
|
|
local data = vm:get_data()
|
|
|
|
|
2016-02-25 01:29:35 +01:00
|
|
|
add_trunk_and_leaves(data, a, pos, c_jungletree, c_jungleleaves,
|
|
|
|
height, 3, 30, false)
|
2014-06-13 20:03:14 +02:00
|
|
|
|
|
|
|
-- Roots
|
|
|
|
for z_dist = -1, 1 do
|
|
|
|
local vi_1 = a:index(x - 1, y - 1, z + z_dist)
|
2014-12-04 04:47:46 +01:00
|
|
|
local vi_2 = a:index(x - 1, y, z + z_dist)
|
2014-06-13 20:03:14 +02:00
|
|
|
for x_dist = -1, 1 do
|
|
|
|
if random(1, 3) >= 2 then
|
2014-12-04 04:47:46 +01:00
|
|
|
if data[vi_1] == c_air or data[vi_1] == c_ignore then
|
2014-06-13 20:03:14 +02:00
|
|
|
data[vi_1] = c_jungletree
|
2014-12-04 04:47:46 +01:00
|
|
|
elseif data[vi_2] == c_air or data[vi_2] == c_ignore then
|
2014-06-13 20:03:14 +02:00
|
|
|
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()
|
2013-11-06 23:41:49 +01:00
|
|
|
end
|
2014-06-13 20:03:14 +02:00
|
|
|
|
2015-08-07 21:24:12 +02:00
|
|
|
|
|
|
|
-- Pine tree from mg mapgen mod, design by sfan5, pointy top added by paramat
|
2014-12-04 04:47:46 +01:00
|
|
|
|
|
|
|
local function add_pine_needles(data, vi, c_air, c_ignore, c_snow, c_pine_needles)
|
2015-07-04 22:00:41 +02:00
|
|
|
local node_id = data[vi]
|
|
|
|
if node_id == c_air or node_id == c_ignore or node_id == c_snow then
|
2014-12-04 04:47:46 +01:00
|
|
|
data[vi] = c_pine_needles
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function add_snow(data, vi, c_air, c_ignore, c_snow)
|
2015-07-04 22:00:41 +02:00
|
|
|
local node_id = data[vi]
|
|
|
|
if node_id == c_air or node_id == c_ignore then
|
2014-12-04 04:47:46 +01:00
|
|
|
data[vi] = c_snow
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-02-25 01:29:35 +01:00
|
|
|
function default.grow_pine_tree(pos, snow)
|
2014-12-04 04:47:46 +01:00
|
|
|
local x, y, z = pos.x, pos.y, pos.z
|
|
|
|
local maxy = y + random(9, 13) -- Trunk top
|
|
|
|
|
|
|
|
local c_air = minetest.get_content_id("air")
|
|
|
|
local c_ignore = minetest.get_content_id("ignore")
|
2015-08-09 09:50:57 +02:00
|
|
|
local c_pine_tree = minetest.get_content_id("default:pine_tree")
|
2014-12-04 04:47:46 +01:00
|
|
|
local c_pine_needles = minetest.get_content_id("default:pine_needles")
|
|
|
|
local c_snow = minetest.get_content_id("default:snow")
|
|
|
|
|
|
|
|
local vm = minetest.get_voxel_manip()
|
|
|
|
local minp, maxp = vm:read_from_map(
|
2016-02-25 01:29:35 +01:00
|
|
|
{x = x - 3, y = y, z = z - 3},
|
2014-12-04 04:47:46 +01:00
|
|
|
{x = x + 3, y = maxy + 3, z = z + 3}
|
|
|
|
)
|
|
|
|
local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp})
|
|
|
|
local data = vm:get_data()
|
|
|
|
|
|
|
|
-- Upper branches layer
|
|
|
|
local dev = 3
|
|
|
|
for yy = maxy - 1, maxy + 1 do
|
|
|
|
for zz = z - dev, z + dev do
|
|
|
|
local vi = a:index(x - dev, yy, zz)
|
|
|
|
local via = a:index(x - dev, yy + 1, zz)
|
|
|
|
for xx = x - dev, x + dev do
|
|
|
|
if random() < 0.95 - dev * 0.05 then
|
|
|
|
add_pine_needles(data, vi, c_air, c_ignore, c_snow,
|
2015-07-04 22:00:41 +02:00
|
|
|
c_pine_needles)
|
2014-12-04 04:47:46 +01:00
|
|
|
if snow then
|
|
|
|
add_snow(data, via, c_air, c_ignore, c_snow)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
vi = vi + 1
|
|
|
|
via = via + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
dev = dev - 1
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Centre top nodes
|
|
|
|
add_pine_needles(data, a:index(x, maxy + 1, z), c_air, c_ignore, c_snow,
|
2015-07-04 22:00:41 +02:00
|
|
|
c_pine_needles)
|
2014-12-04 04:47:46 +01:00
|
|
|
add_pine_needles(data, a:index(x, maxy + 2, z), c_air, c_ignore, c_snow,
|
2015-07-04 22:00:41 +02:00
|
|
|
c_pine_needles) -- Paramat added a pointy top node
|
2014-12-04 04:47:46 +01:00
|
|
|
if snow then
|
|
|
|
add_snow(data, a:index(x, maxy + 3, z), c_air, c_ignore, c_snow)
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Lower branches layer
|
|
|
|
local my = 0
|
|
|
|
for i = 1, 20 do -- Random 2x2 squares of needles
|
|
|
|
local xi = x + random(-3, 2)
|
|
|
|
local yy = maxy + random(-6, -5)
|
|
|
|
local zi = z + random(-3, 2)
|
|
|
|
if yy > my then
|
|
|
|
my = yy
|
|
|
|
end
|
|
|
|
for zz = zi, zi+1 do
|
|
|
|
local vi = a:index(xi, yy, zz)
|
|
|
|
local via = a:index(xi, yy + 1, zz)
|
|
|
|
for xx = xi, xi + 1 do
|
|
|
|
add_pine_needles(data, vi, c_air, c_ignore, c_snow,
|
2015-07-04 22:00:41 +02:00
|
|
|
c_pine_needles)
|
2014-12-04 04:47:46 +01:00
|
|
|
if snow then
|
|
|
|
add_snow(data, via, c_air, c_ignore, c_snow)
|
|
|
|
end
|
|
|
|
vi = vi + 1
|
|
|
|
via = via + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-06-26 13:34:14 +02:00
|
|
|
dev = 2
|
2014-12-04 04:47:46 +01:00
|
|
|
for yy = my + 1, my + 2 do
|
|
|
|
for zz = z - dev, z + dev do
|
|
|
|
local vi = a:index(x - dev, yy, zz)
|
|
|
|
local via = a:index(x - dev, yy + 1, zz)
|
|
|
|
for xx = x - dev, x + dev do
|
|
|
|
if random() < 0.95 - dev * 0.05 then
|
|
|
|
add_pine_needles(data, vi, c_air, c_ignore, c_snow,
|
2015-07-04 22:00:41 +02:00
|
|
|
c_pine_needles)
|
2014-12-04 04:47:46 +01:00
|
|
|
if snow then
|
|
|
|
add_snow(data, via, c_air, c_ignore, c_snow)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
vi = vi + 1
|
|
|
|
via = via + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
dev = dev - 1
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Trunk
|
2016-02-25 01:29:35 +01:00
|
|
|
-- Force-place lowest trunk node to replace sapling
|
|
|
|
data[a:index(x, y, z)] = c_pine_tree
|
2015-07-04 22:00:41 +02:00
|
|
|
for yy = y + 1, maxy do
|
2014-12-04 04:47:46 +01:00
|
|
|
local vi = a:index(x, yy, z)
|
2015-07-04 22:00:41 +02:00
|
|
|
local node_id = data[vi]
|
2015-08-09 09:50:57 +02:00
|
|
|
if node_id == c_air or node_id == c_ignore or
|
|
|
|
node_id == c_pine_needles or node_id == c_snow then
|
|
|
|
data[vi] = c_pine_tree
|
2015-07-04 22:00:41 +02:00
|
|
|
end
|
2014-12-04 04:47:46 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
vm:set_data(data)
|
|
|
|
vm:write_to_map()
|
|
|
|
vm:update_map()
|
|
|
|
end
|
|
|
|
|
2015-08-07 21:24:12 +02:00
|
|
|
|
|
|
|
-- New apple tree
|
2015-07-20 03:33:30 +02:00
|
|
|
|
|
|
|
function default.grow_new_apple_tree(pos)
|
2016-02-25 01:29:35 +01:00
|
|
|
local path = minetest.get_modpath("default") ..
|
|
|
|
"/schematics/apple_tree_from_sapling.mts"
|
2018-08-21 00:56:00 +02:00
|
|
|
minetest.place_schematic({x = pos.x - 3, y = pos.y - 1, z = pos.z - 3},
|
2017-03-07 13:00:14 +01:00
|
|
|
path, "random", nil, false)
|
2015-07-20 03:33:30 +02:00
|
|
|
end
|
|
|
|
|
2015-08-07 21:24:12 +02:00
|
|
|
|
2015-07-20 03:33:30 +02:00
|
|
|
-- New jungle tree
|
|
|
|
|
|
|
|
function default.grow_new_jungle_tree(pos)
|
2016-02-25 01:29:35 +01:00
|
|
|
local path = minetest.get_modpath("default") ..
|
|
|
|
"/schematics/jungle_tree_from_sapling.mts"
|
2015-07-20 03:33:30 +02:00
|
|
|
minetest.place_schematic({x = pos.x - 2, y = pos.y - 1, z = pos.z - 2},
|
2016-03-21 09:03:52 +01:00
|
|
|
path, "random", nil, false)
|
2017-05-10 09:23:26 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
-- New emergent jungle tree
|
|
|
|
|
|
|
|
function default.grow_new_emergent_jungle_tree(pos)
|
|
|
|
local path = minetest.get_modpath("default") ..
|
|
|
|
"/schematics/emergent_jungle_tree_from_sapling.mts"
|
|
|
|
minetest.place_schematic({x = pos.x - 3, y = pos.y - 5, z = pos.z - 3},
|
|
|
|
path, "random", nil, false)
|
2015-07-20 03:33:30 +02:00
|
|
|
end
|
|
|
|
|
2015-08-07 21:24:12 +02:00
|
|
|
|
2015-07-20 03:33:30 +02:00
|
|
|
-- New pine tree
|
|
|
|
|
|
|
|
function default.grow_new_pine_tree(pos)
|
2018-03-04 20:47:06 +01:00
|
|
|
local path
|
|
|
|
if math.random() > 0.5 then
|
|
|
|
path = minetest.get_modpath("default") ..
|
|
|
|
"/schematics/pine_tree_from_sapling.mts"
|
|
|
|
else
|
|
|
|
path = minetest.get_modpath("default") ..
|
|
|
|
"/schematics/small_pine_tree_from_sapling.mts"
|
|
|
|
end
|
2016-02-25 01:29:35 +01:00
|
|
|
minetest.place_schematic({x = pos.x - 2, y = pos.y - 1, z = pos.z - 2},
|
|
|
|
path, "0", nil, false)
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
-- New snowy pine tree
|
|
|
|
|
|
|
|
function default.grow_new_snowy_pine_tree(pos)
|
2018-03-04 20:47:06 +01:00
|
|
|
local path
|
|
|
|
if math.random() > 0.5 then
|
|
|
|
path = minetest.get_modpath("default") ..
|
|
|
|
"/schematics/snowy_pine_tree_from_sapling.mts"
|
|
|
|
else
|
|
|
|
path = minetest.get_modpath("default") ..
|
|
|
|
"/schematics/snowy_small_pine_tree_from_sapling.mts"
|
|
|
|
end
|
2015-07-20 03:33:30 +02:00
|
|
|
minetest.place_schematic({x = pos.x - 2, y = pos.y - 1, z = pos.z - 2},
|
2016-02-25 01:29:35 +01:00
|
|
|
path, "random", nil, false)
|
2015-07-20 03:33:30 +02:00
|
|
|
end
|
|
|
|
|
2015-08-07 21:24:12 +02:00
|
|
|
|
2015-07-20 03:33:30 +02:00
|
|
|
-- New acacia tree
|
|
|
|
|
|
|
|
function default.grow_new_acacia_tree(pos)
|
2016-02-25 01:29:35 +01:00
|
|
|
local path = minetest.get_modpath("default") ..
|
|
|
|
"/schematics/acacia_tree_from_sapling.mts"
|
2015-07-20 03:33:30 +02:00
|
|
|
minetest.place_schematic({x = pos.x - 4, y = pos.y - 1, z = pos.z - 4},
|
2016-02-25 01:29:35 +01:00
|
|
|
path, "random", nil, false)
|
2015-07-20 03:33:30 +02:00
|
|
|
end
|
Aspen trees.
Adds a birch-like tree to the default_game. Aspen was chosen on
purpose instead of birch, as several birch tree mods already exist
and choosing a different name avoids any conflicts.
Schematics were made for both normal and sapling version, assuring
saplings will not be able to grief. The shape of the Aspen is "fanning
out at the top" and provides an easy tree to walk under, but still a
somewhat thick cover. The Aspen trunk is 4 to 6 blocks tall, with up
to three layers of leaves on top, making it slightly taller than an
Apple tree, but shorter than a Pine tree, which provides a good blend.
Textures were painted from scratch, except tree_top and _wood
variants, which are color modified versions of the pine_wood
variants. Appropriate licenses have been chosen for the new textures.
The leaf texture is light enough to contrast other trees, but dark
enough to offset against our light default grass color. The leaves
are drawn in the typical minetest default fashion with plenty of
transparancy, but enough definition to suggest that you're seeing
something that looks like leaves. The placement of leaves in the
schematic also suggests the top of the tree is sparse and you can
see the sky through the leaves.
Sapling texture is both traditional and different, with lush green
leaves and a well-defined stem, but slightly stick-like and skinny,
as these plants tend to grow up first, then out.
Add fallen Aspen logs. We make these logs a minimum of 2 blocks long,
and up to 3. This allows us to make these logs a place where both
red and brown mushrooms can be found, to these may be attractive to
players. However, the spawn rate for these has been reduced a lot
compared to the other logs, to account for the scarcity of Aspen.
Add stairs, slabs for these wood types as well.
Mapgen will place these trees in deciduous forests only, but in
a way that the biome is a range between entirely Apple trees, and
mostly entirely Aspen trees, with a bias to Apple trees. To make
fallen logs somewhat correlated with trees, we modify the planting
of Apple trees and logs to use perlin noise and not fill ratio,
otherwise you'd always end up with Apple logs in Aspen tree areas,
which would be suspicious. There still is a bit of a mix.
2016-01-05 02:56:20 +01:00
|
|
|
|
2016-07-19 02:01:59 +02:00
|
|
|
|
Aspen trees.
Adds a birch-like tree to the default_game. Aspen was chosen on
purpose instead of birch, as several birch tree mods already exist
and choosing a different name avoids any conflicts.
Schematics were made for both normal and sapling version, assuring
saplings will not be able to grief. The shape of the Aspen is "fanning
out at the top" and provides an easy tree to walk under, but still a
somewhat thick cover. The Aspen trunk is 4 to 6 blocks tall, with up
to three layers of leaves on top, making it slightly taller than an
Apple tree, but shorter than a Pine tree, which provides a good blend.
Textures were painted from scratch, except tree_top and _wood
variants, which are color modified versions of the pine_wood
variants. Appropriate licenses have been chosen for the new textures.
The leaf texture is light enough to contrast other trees, but dark
enough to offset against our light default grass color. The leaves
are drawn in the typical minetest default fashion with plenty of
transparancy, but enough definition to suggest that you're seeing
something that looks like leaves. The placement of leaves in the
schematic also suggests the top of the tree is sparse and you can
see the sky through the leaves.
Sapling texture is both traditional and different, with lush green
leaves and a well-defined stem, but slightly stick-like and skinny,
as these plants tend to grow up first, then out.
Add fallen Aspen logs. We make these logs a minimum of 2 blocks long,
and up to 3. This allows us to make these logs a place where both
red and brown mushrooms can be found, to these may be attractive to
players. However, the spawn rate for these has been reduced a lot
compared to the other logs, to account for the scarcity of Aspen.
Add stairs, slabs for these wood types as well.
Mapgen will place these trees in deciduous forests only, but in
a way that the biome is a range between entirely Apple trees, and
mostly entirely Aspen trees, with a bias to Apple trees. To make
fallen logs somewhat correlated with trees, we modify the planting
of Apple trees and logs to use perlin noise and not fill ratio,
otherwise you'd always end up with Apple logs in Aspen tree areas,
which would be suspicious. There still is a bit of a mix.
2016-01-05 02:56:20 +01:00
|
|
|
-- New aspen tree
|
|
|
|
|
|
|
|
function default.grow_new_aspen_tree(pos)
|
2016-02-25 01:29:35 +01:00
|
|
|
local path = minetest.get_modpath("default") ..
|
|
|
|
"/schematics/aspen_tree_from_sapling.mts"
|
Aspen trees.
Adds a birch-like tree to the default_game. Aspen was chosen on
purpose instead of birch, as several birch tree mods already exist
and choosing a different name avoids any conflicts.
Schematics were made for both normal and sapling version, assuring
saplings will not be able to grief. The shape of the Aspen is "fanning
out at the top" and provides an easy tree to walk under, but still a
somewhat thick cover. The Aspen trunk is 4 to 6 blocks tall, with up
to three layers of leaves on top, making it slightly taller than an
Apple tree, but shorter than a Pine tree, which provides a good blend.
Textures were painted from scratch, except tree_top and _wood
variants, which are color modified versions of the pine_wood
variants. Appropriate licenses have been chosen for the new textures.
The leaf texture is light enough to contrast other trees, but dark
enough to offset against our light default grass color. The leaves
are drawn in the typical minetest default fashion with plenty of
transparancy, but enough definition to suggest that you're seeing
something that looks like leaves. The placement of leaves in the
schematic also suggests the top of the tree is sparse and you can
see the sky through the leaves.
Sapling texture is both traditional and different, with lush green
leaves and a well-defined stem, but slightly stick-like and skinny,
as these plants tend to grow up first, then out.
Add fallen Aspen logs. We make these logs a minimum of 2 blocks long,
and up to 3. This allows us to make these logs a place where both
red and brown mushrooms can be found, to these may be attractive to
players. However, the spawn rate for these has been reduced a lot
compared to the other logs, to account for the scarcity of Aspen.
Add stairs, slabs for these wood types as well.
Mapgen will place these trees in deciduous forests only, but in
a way that the biome is a range between entirely Apple trees, and
mostly entirely Aspen trees, with a bias to Apple trees. To make
fallen logs somewhat correlated with trees, we modify the planting
of Apple trees and logs to use perlin noise and not fill ratio,
otherwise you'd always end up with Apple logs in Aspen tree areas,
which would be suspicious. There still is a bit of a mix.
2016-01-05 02:56:20 +01:00
|
|
|
minetest.place_schematic({x = pos.x - 2, y = pos.y - 1, z = pos.z - 2},
|
2016-02-25 01:29:35 +01:00
|
|
|
path, "0", nil, false)
|
Aspen trees.
Adds a birch-like tree to the default_game. Aspen was chosen on
purpose instead of birch, as several birch tree mods already exist
and choosing a different name avoids any conflicts.
Schematics were made for both normal and sapling version, assuring
saplings will not be able to grief. The shape of the Aspen is "fanning
out at the top" and provides an easy tree to walk under, but still a
somewhat thick cover. The Aspen trunk is 4 to 6 blocks tall, with up
to three layers of leaves on top, making it slightly taller than an
Apple tree, but shorter than a Pine tree, which provides a good blend.
Textures were painted from scratch, except tree_top and _wood
variants, which are color modified versions of the pine_wood
variants. Appropriate licenses have been chosen for the new textures.
The leaf texture is light enough to contrast other trees, but dark
enough to offset against our light default grass color. The leaves
are drawn in the typical minetest default fashion with plenty of
transparancy, but enough definition to suggest that you're seeing
something that looks like leaves. The placement of leaves in the
schematic also suggests the top of the tree is sparse and you can
see the sky through the leaves.
Sapling texture is both traditional and different, with lush green
leaves and a well-defined stem, but slightly stick-like and skinny,
as these plants tend to grow up first, then out.
Add fallen Aspen logs. We make these logs a minimum of 2 blocks long,
and up to 3. This allows us to make these logs a place where both
red and brown mushrooms can be found, to these may be attractive to
players. However, the spawn rate for these has been reduced a lot
compared to the other logs, to account for the scarcity of Aspen.
Add stairs, slabs for these wood types as well.
Mapgen will place these trees in deciduous forests only, but in
a way that the biome is a range between entirely Apple trees, and
mostly entirely Aspen trees, with a bias to Apple trees. To make
fallen logs somewhat correlated with trees, we modify the planting
of Apple trees and logs to use perlin noise and not fill ratio,
otherwise you'd always end up with Apple logs in Aspen tree areas,
which would be suspicious. There still is a bit of a mix.
2016-01-05 02:56:20 +01:00
|
|
|
end
|
2016-07-19 02:01:59 +02:00
|
|
|
|
|
|
|
|
2017-04-12 10:25:21 +02:00
|
|
|
-- Bushes do not need 'from sapling' schematic variants because
|
|
|
|
-- only the stem node is force-placed in the schematic.
|
|
|
|
|
|
|
|
-- Bush
|
|
|
|
|
|
|
|
function default.grow_bush(pos)
|
|
|
|
local path = minetest.get_modpath("default") ..
|
|
|
|
"/schematics/bush.mts"
|
|
|
|
minetest.place_schematic({x = pos.x - 1, y = pos.y - 1, z = pos.z - 1},
|
|
|
|
path, "0", nil, false)
|
|
|
|
end
|
|
|
|
|
2018-10-09 21:54:22 +02:00
|
|
|
-- Blueberry bush
|
|
|
|
|
|
|
|
function default.grow_blueberry_bush(pos)
|
|
|
|
local path = minetest.get_modpath("default") ..
|
|
|
|
"/schematics/blueberry_bush.mts"
|
|
|
|
minetest.place_schematic({x = pos.x - 1, y = pos.y, z = pos.z - 1},
|
|
|
|
path, "0", nil, false)
|
|
|
|
end
|
|
|
|
|
2017-04-12 10:25:21 +02:00
|
|
|
|
|
|
|
-- Acacia bush
|
|
|
|
|
|
|
|
function default.grow_acacia_bush(pos)
|
|
|
|
local path = minetest.get_modpath("default") ..
|
|
|
|
"/schematics/acacia_bush.mts"
|
|
|
|
minetest.place_schematic({x = pos.x - 1, y = pos.y - 1, z = pos.z - 1},
|
|
|
|
path, "0", nil, false)
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2018-07-13 02:17:07 +02:00
|
|
|
-- Pine bush
|
|
|
|
|
|
|
|
function default.grow_pine_bush(pos)
|
|
|
|
local path = minetest.get_modpath("default") ..
|
|
|
|
"/schematics/pine_bush.mts"
|
|
|
|
minetest.place_schematic({x = pos.x - 1, y = pos.y - 1, z = pos.z - 1},
|
|
|
|
path, "0", nil, false)
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2019-01-02 03:18:50 +01:00
|
|
|
-- Large cactus
|
|
|
|
|
|
|
|
function default.grow_large_cactus(pos)
|
|
|
|
local path = minetest.get_modpath("default") ..
|
|
|
|
"/schematics/large_cactus.mts"
|
|
|
|
minetest.place_schematic({x = pos.x - 2, y = pos.y - 1, z = pos.z - 2},
|
|
|
|
path, "random", nil, false)
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2016-07-19 02:01:59 +02:00
|
|
|
--
|
|
|
|
-- Sapling 'on place' function to check protection of node and resulting tree volume
|
|
|
|
--
|
|
|
|
|
|
|
|
function default.sapling_on_place(itemstack, placer, pointed_thing,
|
|
|
|
sapling_name, minp_relative, maxp_relative, interval)
|
|
|
|
-- Position of sapling
|
|
|
|
local pos = pointed_thing.under
|
2016-10-04 19:18:45 +02:00
|
|
|
local node = minetest.get_node_or_nil(pos)
|
|
|
|
local pdef = node and minetest.registered_nodes[node.name]
|
|
|
|
|
2017-10-01 15:41:58 +02:00
|
|
|
if pdef and pdef.on_rightclick and
|
|
|
|
not (placer and placer:is_player() and
|
|
|
|
placer:get_player_control().sneak) then
|
2016-10-04 19:18:45 +02:00
|
|
|
return pdef.on_rightclick(pos, node, placer, itemstack, pointed_thing)
|
|
|
|
end
|
|
|
|
|
2016-07-19 02:01:59 +02:00
|
|
|
if not pdef or not pdef.buildable_to then
|
|
|
|
pos = pointed_thing.above
|
2016-10-04 19:18:45 +02:00
|
|
|
node = minetest.get_node_or_nil(pos)
|
|
|
|
pdef = node and minetest.registered_nodes[node.name]
|
2016-07-19 02:01:59 +02:00
|
|
|
if not pdef or not pdef.buildable_to then
|
|
|
|
return itemstack
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-10-01 15:41:58 +02:00
|
|
|
local player_name = placer and placer:get_player_name() or ""
|
2016-07-19 02:01:59 +02:00
|
|
|
-- Check sapling position for protection
|
|
|
|
if minetest.is_protected(pos, player_name) then
|
|
|
|
minetest.record_protection_violation(pos, player_name)
|
|
|
|
return itemstack
|
|
|
|
end
|
|
|
|
-- Check tree volume for protection
|
2018-02-25 12:30:36 +01:00
|
|
|
if minetest.is_area_protected(
|
2016-07-19 02:01:59 +02:00
|
|
|
vector.add(pos, minp_relative),
|
|
|
|
vector.add(pos, maxp_relative),
|
|
|
|
player_name,
|
|
|
|
interval) then
|
|
|
|
minetest.record_protection_violation(pos, player_name)
|
|
|
|
-- Print extra information to explain
|
2019-09-10 19:09:51 +02:00
|
|
|
-- minetest.chat_send_player(player_name,
|
|
|
|
-- itemstack:get_definition().description .. " will intersect protection " ..
|
|
|
|
-- "on growth")
|
2019-01-02 03:18:50 +01:00
|
|
|
minetest.chat_send_player(player_name,
|
2019-09-10 19:09:51 +02:00
|
|
|
S("@1 will intersect protection on growth.",
|
|
|
|
itemstack:get_definition().description))
|
2017-03-11 13:52:20 +01:00
|
|
|
return itemstack
|
|
|
|
end
|
|
|
|
|
2022-05-06 20:04:55 +02:00
|
|
|
default.log_player_action(placer, "places node", sapling_name, "at", pos)
|
2017-03-11 13:52:20 +01:00
|
|
|
|
2020-12-13 18:59:19 +01:00
|
|
|
local take_item = not minetest.is_creative_enabled(player_name)
|
2017-03-11 13:52:20 +01:00
|
|
|
local newnode = {name = sapling_name}
|
|
|
|
local ndef = minetest.registered_nodes[sapling_name]
|
|
|
|
minetest.set_node(pos, newnode)
|
|
|
|
|
|
|
|
-- Run callback
|
|
|
|
if ndef and ndef.after_place_node then
|
|
|
|
-- Deepcopy place_to and pointed_thing because callback can modify it
|
|
|
|
if ndef.after_place_node(table.copy(pos), placer,
|
|
|
|
itemstack, table.copy(pointed_thing)) then
|
|
|
|
take_item = false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Run script hook
|
|
|
|
for _, callback in ipairs(minetest.registered_on_placenodes) do
|
|
|
|
-- Deepcopy pos, node and pointed_thing because callback can modify them
|
|
|
|
if callback(table.copy(pos), table.copy(newnode),
|
|
|
|
placer, table.copy(node or {}),
|
|
|
|
itemstack, table.copy(pointed_thing)) then
|
|
|
|
take_item = false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if take_item then
|
|
|
|
itemstack:take_item()
|
2016-07-19 02:01:59 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
return itemstack
|
|
|
|
end
|
2023-09-12 15:43:41 +02:00
|
|
|
|
|
|
|
-- Grow sapling
|
|
|
|
|
|
|
|
default.sapling_growth_defs = {}
|
|
|
|
|
|
|
|
function default.register_sapling_growth(name, def)
|
|
|
|
default.sapling_growth_defs[name] = {
|
|
|
|
can_grow = def.can_grow or default.can_grow,
|
|
|
|
on_grow_failed = def.on_grow_failed or default.on_grow_failed,
|
|
|
|
grow = assert(def.grow)
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
function default.grow_sapling(pos)
|
|
|
|
local node = minetest.get_node(pos)
|
|
|
|
local sapling_def = default.sapling_growth_defs[node.name]
|
|
|
|
|
|
|
|
if not sapling_def then
|
|
|
|
minetest.log("warning", "default.grow_sapling called on undefined sapling " .. node.name)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
if not sapling_def.can_grow(pos) then
|
|
|
|
sapling_def.on_grow_failed(pos)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
minetest.log("action", "Growing sapling " .. node.name .. " at " .. minetest.pos_to_string(pos))
|
|
|
|
sapling_def.grow(pos)
|
|
|
|
end
|
|
|
|
|
|
|
|
local function register_sapling_growth(nodename, grow)
|
|
|
|
default.register_sapling_growth("default:" .. nodename, {grow = grow})
|
|
|
|
end
|
|
|
|
|
|
|
|
if minetest.get_mapgen_setting("mg_name") == "v6" then
|
|
|
|
register_sapling_growth("sapling", function(pos)
|
|
|
|
default.grow_tree(pos, random(1, 4) == 1)
|
|
|
|
end)
|
|
|
|
register_sapling_growth("junglesapling", default.grow_jungle_tree)
|
|
|
|
register_sapling_growth("pine_sapling", function(pos)
|
|
|
|
local snow = is_snow_nearby(pos)
|
|
|
|
default.grow_pine_tree(pos, snow)
|
|
|
|
end)
|
|
|
|
else
|
|
|
|
register_sapling_growth("sapling", default.grow_new_apple_tree)
|
|
|
|
register_sapling_growth("junglesapling", default.grow_new_jungle_tree)
|
|
|
|
register_sapling_growth("pine_sapling", function(pos)
|
|
|
|
local snow = is_snow_nearby(pos)
|
|
|
|
if snow then
|
|
|
|
default.grow_new_snowy_pine_tree(pos)
|
|
|
|
else
|
|
|
|
default.grow_new_pine_tree(pos)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
register_sapling_growth("acacia_sapling", default.grow_new_acacia_tree)
|
|
|
|
register_sapling_growth("aspen_sapling", default.grow_new_aspen_tree)
|
|
|
|
register_sapling_growth("bush_sapling", default.grow_bush)
|
|
|
|
register_sapling_growth("blueberry_bush_sapling", default.grow_blueberry_bush)
|
|
|
|
register_sapling_growth("acacia_bush_sapling", default.grow_acacia_bush)
|
|
|
|
register_sapling_growth("pine_bush_sapling", default.grow_pine_bush)
|
|
|
|
register_sapling_growth("emergent_jungle_sapling", default.grow_new_emergent_jungle_tree)
|
|
|
|
|
|
|
|
-- Backwards compatibility for saplings that used to use ABMs; does not need to include newer saplings.
|
|
|
|
minetest.register_lbm({
|
|
|
|
name = "default:convert_saplings_to_node_timer",
|
|
|
|
nodenames = {"default:sapling", "default:junglesapling",
|
|
|
|
"default:pine_sapling", "default:acacia_sapling",
|
|
|
|
"default:aspen_sapling"},
|
|
|
|
action = function(pos)
|
|
|
|
minetest.get_node_timer(pos):start(math.random(300, 1500))
|
|
|
|
end
|
|
|
|
})
|