moved example trees into this seperate mod
This commit is contained in:
commit
92d6f6201f
29
README.md
Normal file
29
README.md
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
These are examples as to how trees_lib for Minetest can be used.
|
||||
|
||||
Files:
|
||||
init.lua Just does dofile(..)
|
||||
example_tree.lua A complex tree example.
|
||||
trees_lib_growing_functions.lua Some adjusted growth functions
|
||||
taken from other mods.
|
||||
trees.lua Taken from and for minetest_game.
|
||||
|
||||
The example tree will look blueish and carry fruits that look like
|
||||
copper lumps. It exists only to demonstrate what can be done. Depending
|
||||
on the ground on which the sapling is placed, diffrent methods of
|
||||
growing are used, and the tree will display diffrent forms of growth.
|
||||
|
||||
trees.lua is not executed. If you want to use it, copy it to
|
||||
minetest_game/mods/default/trees.lua Create a backup of the existing file
|
||||
there first. Then comment out all definitions of tree trunks, wood,
|
||||
leaves and fruit nodes (=apple) in minetest_game/mods/default/nodes.lua
|
||||
as those will be created by trees.lua. All calls to leafdecay in nodes.lua
|
||||
have to be removed as well. Also remove the function leafdecay_after_destruct
|
||||
in minetest_game/mods/default/functions.lua
|
||||
|
||||
trees.lua and trees_lib have not yet been adjusted to the most recent
|
||||
changes in minetest_game (i.e. using of LBMs and timers instead of
|
||||
ABMs).
|
||||
|
||||
trees.lua is taken from minetest_game and modified so that trees_lib can be
|
||||
used by minetest_game.
|
2
depends.txt
Normal file
2
depends.txt
Normal file
@ -0,0 +1,2 @@
|
||||
trees_lib
|
||||
default
|
209
example_tree.lua
Normal file
209
example_tree.lua
Normal file
@ -0,0 +1,209 @@
|
||||
--
|
||||
-- This is an actual example of how trees_lib can be used
|
||||
--
|
||||
|
||||
local modname = minetest.get_current_modname();
|
||||
|
||||
-- this is taken as an example from https://github.com/duane-r/valleys_c/blob/master/*
|
||||
-- Create and initialize a table for a schematic.
|
||||
local function vmg_schematic_array(width, height, depth)
|
||||
-- Dimensions of data array.
|
||||
local s = {size={x=width, y=height, z=depth}}
|
||||
s.data = {}
|
||||
|
||||
for x = 0,width-1 do
|
||||
for y = 0,height-1 do
|
||||
for z = 0,depth-1 do
|
||||
local i = x*width*height + y*width + z + 1
|
||||
s.data[i] = {}
|
||||
s.data[i].name = "air"
|
||||
s.data[i].param1 = 000
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
s.yslice_prob = {}
|
||||
|
||||
return s
|
||||
end
|
||||
|
||||
|
||||
-- this is taken as an example from https://github.com/duane-r/valleys_c/blob/master/deco_banana.lua
|
||||
-- A shock of leaves at the top and some fruit.
|
||||
local function vmg_generate_banana_schematic(trunk_height)
|
||||
local height = trunk_height + 3
|
||||
local radius = 1
|
||||
local width = 3
|
||||
local s = vmg_schematic_array(width, height, width)
|
||||
|
||||
-- the main trunk
|
||||
for y = 0,trunk_height do
|
||||
local i = (0+radius)*width*height + y*width + (0+radius) + 1
|
||||
s.data[i].name = modname..":example_tree"
|
||||
s.data[i].param1 = 255
|
||||
end
|
||||
|
||||
-- leaves at the top
|
||||
for x = -1,1 do
|
||||
for y = trunk_height+1, height-1 do
|
||||
for z = -1,1 do
|
||||
local i = (x+radius)*width*height + y*width + (z+radius) + 1
|
||||
if y > height - 2 then
|
||||
s.data[i].name = modname..":example_leaves"
|
||||
if x == 0 and z == 0 then
|
||||
s.data[i].param1 = 255
|
||||
else
|
||||
s.data[i].param1 = 127
|
||||
end
|
||||
elseif x == 0 and z == 0 then
|
||||
s.data[i].name = modname..":example_leaves"
|
||||
s.data[i].param1 = 255
|
||||
elseif x ~= 0 or z ~= 0 then
|
||||
s.data[i].name = modname..":cfruit"
|
||||
s.data[i].param1 = 75
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return s
|
||||
end
|
||||
|
||||
|
||||
-- this function allows the tree to chose between diffrent growth functions (or provide its own)
|
||||
local example_tree_select_how_to_grow = function( pos, node, sapling_data_how_to_grow, ground_found )
|
||||
-- grow into a normal fruit tree on dirt or grass
|
||||
if( ground_found == "default:dirt"
|
||||
or ground_found == "default:dirt_with_grass" ) then
|
||||
return 1;
|
||||
|
||||
-- if growing on desert sand, then grow like an acacia
|
||||
elseif( ground_found == "default:desert_sand" ) then
|
||||
return 2;
|
||||
-- on normal sand, grow like the banana tree from valleys_c
|
||||
elseif( ground_found == "default:sand" ) then
|
||||
return 3;
|
||||
|
||||
-- on soil, grow like one of the birches from moretrees
|
||||
elseif( ground_found == "group:soil" ) then
|
||||
return math.random(4,5);
|
||||
|
||||
-- stone is not the ideal ground to grow on...
|
||||
elseif( ground_found == "group:stone" ) then
|
||||
-- this shows that we can also return new tree types
|
||||
return {
|
||||
use_function = trees_lib.generate_unhappy_tree,
|
||||
xoff = 1, zoff = 1, yoff = 0, height = 3,
|
||||
};
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- the actual example tree; it will grow in very diffrent ways depending on where it is placed;
|
||||
-- most of the node names and descriptions can be created automaticly;
|
||||
-- all we have to supply in such cases are the texture names
|
||||
trees_lib.register_tree( "example",
|
||||
{ tree = {
|
||||
--node_name = modname..":example_tree",
|
||||
--description = "example Tree",
|
||||
tiles = {"default_tree_top.png^[colorize:#015dbb70", "default_tree_top.png^[colorize:#015dbb70", "default_tree.png^[colorize:#015dbb70"},
|
||||
}, wood = {
|
||||
--node_name = modname..":example_wood",
|
||||
--description = "example Wooden Planks",
|
||||
tiles = {"default_wood.png^[colorize:#015dbb70"},
|
||||
}, leaves = {
|
||||
--node_name = modname..":example_leaves",
|
||||
--description = "example Leaves",
|
||||
tiles = {"default_leaves.png^[colorize:#01ffd870"},
|
||||
special_tiles= {"default_leaves_simple.png^[colorize:#01ffd870"},
|
||||
}, sapling = {
|
||||
--node_name = modname..":example_sapling",
|
||||
--description = "example Tree Sapling",
|
||||
tiles = {"default_sapling.png^[colorize:#ff840170"},
|
||||
|
||||
--rarity = 20,
|
||||
}, fruit = {
|
||||
-- the fruit diverges in name and description from what would automaticly be created
|
||||
node_name = modname..":cfruit",
|
||||
description = "Yellow Copper Fruit",
|
||||
tiles = {"default_copper_lump.png^[colorize:#e3ff0070"},
|
||||
-- the fruit can be eaten
|
||||
on_use = minetest.item_eat(2),
|
||||
}},
|
||||
-- the diffrent ways of how a tree can be grown
|
||||
{
|
||||
-- version 1
|
||||
-- one of these methods will be choosen randomly
|
||||
{
|
||||
-- a function - like that used to create the trees/apple trees in mapgen v6
|
||||
use_function = trees_lib.generate_fruit_tree,
|
||||
-- How far will the tree reach in each direction? We need to load a
|
||||
-- sufficiently large voxelmanip area.
|
||||
xoff = 2, zoff = 2, yoff = 0, height = 12,
|
||||
}, { -- version 2
|
||||
-- schematics can be used as well
|
||||
use_schematic = minetest.get_modpath("default").."/schematics/acacia_tree_from_sapling.mts",
|
||||
-- TODO: determine these values automaticly
|
||||
xoff = 4, zoff = 4, yoff = 0, height = 10,
|
||||
-- use a schematic with diffrent nodes
|
||||
use_replacements = {
|
||||
{"default:acacia_tree", modname..":example_tree"},
|
||||
{"default:acacia_leaves",modname..":example_leaves"},
|
||||
}
|
||||
}, { -- version 3
|
||||
-- schematics in table form are also acceptable
|
||||
use_schematic = vmg_generate_banana_schematic(3),
|
||||
-- TODO: determine these values automaticly
|
||||
xoff = 1, zoff = 1, yoff = 0, height = 8,
|
||||
-- TODO: minetest.place_schematic does not apply replacements for tables
|
||||
-- use a schematic with diffrent nodes
|
||||
use_replacements = {
|
||||
{"default:acacia_tree", modname..":example_tree"},
|
||||
{"default:acacia_leaves",modname..":example_leaves"},
|
||||
}
|
||||
}, { -- version 4
|
||||
-- this is moretrees.birch_model1
|
||||
use_lsystem = {
|
||||
axiom="FFFFFdddccA/FFFFFFcA/FFFFFFcB",
|
||||
rules_a="[&&&dddd^^ddddddd][&&&---dddd^^ddddddd][&&&+++dddd^^ddddddd][&&&++++++dddd^^ddddddd]",
|
||||
rules_b="[&&&ddd^^ddddd][&&&---ddd^^ddddd][&&&+++ddd^^ddddd][&&&++++++ddd^^ddddd]",
|
||||
rules_c="/",
|
||||
rules_d="F",
|
||||
trunk=modname..":example_tree", --"moretrees:birch_trunk",
|
||||
leaves=modname..":example_leaves", --"moretrees:birch_leaves",
|
||||
angle=30,
|
||||
iterations=2,
|
||||
random_level=0,
|
||||
trunk_type="single",
|
||||
thin_branches=true
|
||||
}
|
||||
},{ -- version 5
|
||||
-- this is moretrees.birch_model2
|
||||
use_lsystem = {
|
||||
axiom="FFFdddccA/FFFFFccA/FFFFFccB",
|
||||
rules_a="[&&&dFFF^^FFFdd][&&&---dFFF^^FFFdd][&&&+++dFFF^^FFFdd][&&&++++++dFFF^^FFFdd]",
|
||||
rules_b="[&&&dFF^^FFFd][&&&---dFFF^^FFFd][&&&+++dFF^^FFFd][&&&++++++dFF^^FFFd]",
|
||||
rules_c="/",
|
||||
rules_d="F",
|
||||
trunk=modname..":example_tree", --"moretrees:birch_trunk",
|
||||
leaves=modname..":example_leaves", --"moretrees:birch_leaves",
|
||||
angle=30,
|
||||
iterations=2,
|
||||
random_level=0,
|
||||
trunk_type="single",
|
||||
thin_branches=true
|
||||
}
|
||||
},
|
||||
},
|
||||
-- grows_on_node_type_list - the tree only grows on nodes of this type
|
||||
{"default:cobble", "group:soil", "default:dirt", "default:dirt_with_grass", "default:desert_sand","default:sand","group:soil","group:stone"},
|
||||
-- no (additional) limits as to where the tree can grow (no can_grow_function)
|
||||
nil,
|
||||
-- the tree will grow in a diffrent way depending on the ground it grows on; see the function below for details
|
||||
example_tree_select_how_to_grow,
|
||||
-- the interval for the sapling-growing abm in seconds
|
||||
10,
|
||||
-- the chance of the abm actually firing and growing the sapling (the higher the smaller)
|
||||
1
|
||||
);
|
||||
|
6
init.lua
Normal file
6
init.lua
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
local modpath = minetest.get_modpath( minetest.get_current_modname());
|
||||
-- some examples as to how tree growing functions can be implemented
|
||||
dofile( modpath.."/trees_lib_growing_functions.lua")
|
||||
-- as the name says: an example tree; just for documentation
|
||||
dofile( modpath.."/example_tree.lua")
|
545
trees.lua
Normal file
545
trees.lua
Normal file
@ -0,0 +1,545 @@
|
||||
--
|
||||
-- Grow trees from saplings
|
||||
--
|
||||
|
||||
-- Leafdecay
|
||||
local function leafdecay_after_destruct(pos, oldnode, def)
|
||||
for _, v in pairs(minetest.find_nodes_in_area(vector.subtract(pos, def.radius),
|
||||
vector.add(pos, def.radius), def.leaves)) do
|
||||
local node = minetest.get_node(v)
|
||||
local timer = minetest.get_node_timer(v)
|
||||
if node.param2 == 0 and not timer:is_started() then
|
||||
timer:start(math.random(20, 120) / 10)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function leafdecay_on_timer(pos, def)
|
||||
if minetest.find_node_near(pos, def.radius, def.trunks) then
|
||||
return false
|
||||
end
|
||||
|
||||
local node = minetest.get_node(pos)
|
||||
local drops = minetest.get_node_drops(node.name)
|
||||
for _, item in ipairs(drops) do
|
||||
local is_leaf
|
||||
for _, v in pairs(def.leaves) do
|
||||
if v == item then
|
||||
is_leaf = true
|
||||
end
|
||||
end
|
||||
if minetest.get_item_group(item, "leafdecay_drop") ~= 0 or
|
||||
not is_leaf then
|
||||
minetest.add_item({
|
||||
x = pos.x - 0.5 + math.random(),
|
||||
y = pos.y - 0.5 + math.random(),
|
||||
z = pos.z - 0.5 + math.random(),
|
||||
}, item)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.remove_node(pos)
|
||||
minetest.check_for_falling(pos)
|
||||
end
|
||||
|
||||
function default_register_leafdecay( tree_name, mod_prefix, nodes)
|
||||
-- TODO: how to handle radius? might be stored inside the leaf node definition as additional data
|
||||
local def = { leaves = {}, trunks = {nodes.tree.node_name}, radius = 2 };
|
||||
-- there can be up to 5 diffrent types of leaves; they all need to decay
|
||||
local leaves_id = {'leaves','leaves2','leaves3','leaves4','leaves5'};
|
||||
for _,k in ipairs( leaves_id ) do
|
||||
if( nodes[ k ] and nodes[ k ].node_name ) then
|
||||
table.insert( def.leaves, nodes[ k ].node_name );
|
||||
end
|
||||
end
|
||||
assert(def.leaves)
|
||||
assert(def.trunks)
|
||||
assert(def.radius)
|
||||
for _, v in pairs(def.trunks) do
|
||||
minetest.override_item(v, {
|
||||
after_destruct = function(pos, oldnode)
|
||||
leafdecay_after_destruct(pos, oldnode, def)
|
||||
end,
|
||||
})
|
||||
end
|
||||
for _, v in pairs(def.leaves) do
|
||||
minetest.override_item(v, {
|
||||
on_timer = function(pos)
|
||||
leafdecay_on_timer(pos, def)
|
||||
end,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- enable leafdecay for all registered trees
|
||||
trees_lib.register_on_new_tree_type( default_register_leafdecay );
|
||||
|
||||
|
||||
-- add craft receipes for turning 1 tree into 4 corresponding wood;
|
||||
-- this function will be called for each registered tree
|
||||
local default_craft_wood_from_tree = function( tree_name, mod_prefix, nodes )
|
||||
if( not( nodes )
|
||||
or not( nodes.tree ) or not( nodes.tree.node_name )
|
||||
or not( nodes.wood ) or not( nodes.wood.node_name )) then
|
||||
return;
|
||||
end
|
||||
|
||||
minetest.register_craft({
|
||||
-- the amount of wood given might be a global config variable
|
||||
output = nodes.wood.node_name..' 4',
|
||||
recipe = {
|
||||
{ nodes.tree.node_name },
|
||||
}
|
||||
});
|
||||
end
|
||||
|
||||
-- allow to craft wooden planks from all trees
|
||||
trees_lib.register_on_new_tree_type( default_craft_wood_from_tree );
|
||||
|
||||
|
||||
|
||||
-- 'Can grow' function
|
||||
|
||||
local random = math.random
|
||||
|
||||
local function can_grow(pos)
|
||||
local ll = minetest.get_node_light(pos)
|
||||
-- return -1 - no final abort, just don't grow yet
|
||||
if not ll or ll < 13 then -- Minimum light level for growth
|
||||
return -1 -- matches grass, wheat and cotton
|
||||
end
|
||||
return 1; -- the tree can grow
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- default trees grow using a function if they detect mapgen v6 - and a schematic otherwise
|
||||
local default_select_how_to_grow = function( pos, node, how_to_grow, ground_found )
|
||||
local mapgen = minetest.get_mapgen_params().mgname
|
||||
if mapgen == "v6" then
|
||||
-- select growing method 1 (previously set to a function)
|
||||
return 1;
|
||||
else
|
||||
-- select growing method 2 (previously set to a schematic)
|
||||
return 2;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- log successful growth; for that, we override the a_tree_has_grown function
|
||||
local old_a_tree_has_grown = trees_lib.a_tree_has_grown;
|
||||
trees_lib.a_tree_has_grown = function( pos, node, how_to_grow )
|
||||
minetest.log("action", "A "..tostring( node.name ).." grows into a tree at "..
|
||||
minetest.pos_to_string(pos))
|
||||
old_a_tree_has_grown( pos, node, how_to_grow );
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Tree generation
|
||||
--
|
||||
|
||||
-- Apple tree and jungle tree trunk and leaves function
|
||||
|
||||
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
|
||||
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")
|
||||
|
||||
-- Trunk
|
||||
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)
|
||||
local node_id = data[vi]
|
||||
if node_id == c_air or node_id == c_ignore or node_id == 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 or data[vi] == c_ignore 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 or data[vi] == c_ignore 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
|
||||
|
||||
|
||||
-- Apple tree
|
||||
|
||||
function default.grow_apple_tree( data, a, pos, sapling_data, extra_params )
|
||||
|
||||
-- translate parameter names
|
||||
local c_tree = sapling_data.cid.tree;
|
||||
local c_leaves = sapling_data.cid.leaves;
|
||||
-- about every 4th tree is an apple tree
|
||||
local is_apple_tree = (random(1, 4) == 1);
|
||||
local height = random(4, 5)
|
||||
|
||||
-- call the actual tree generation function
|
||||
add_trunk_and_leaves(data, a, pos, c_tree, c_leaves, height, 2, 8, is_apple_tree)
|
||||
end
|
||||
|
||||
|
||||
-- Jungle tree
|
||||
|
||||
function default.grow_jungle_tree(data, a, pos, sapling_data, extra_params )
|
||||
--[[
|
||||
NOTE: Jungletree-placing code is currently duplicated in the engine
|
||||
and in games that have saplings; both are deprecated but not
|
||||
replaced yet
|
||||
--]]
|
||||
|
||||
-- translate parameter names
|
||||
local c_jungletree = sapling_data.cid.tree;
|
||||
local c_jungleleaves = sapling_data.cid.leaves;
|
||||
|
||||
local height = random(8, 12)
|
||||
|
||||
add_trunk_and_leaves(data, a, pos, c_jungletree, c_jungleleaves, height, 3, 30, false)
|
||||
|
||||
-- further parameters for the roots
|
||||
local x, y, z = pos.x, pos.y, pos.z
|
||||
local c_air = minetest.get_content_id("air")
|
||||
local c_ignore = minetest.get_content_id("ignore")
|
||||
-- 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 or data[vi_1] == c_ignore then
|
||||
data[vi_1] = c_jungletree
|
||||
elseif data[vi_2] == c_air or data[vi_2] == c_ignore then
|
||||
data[vi_2] = c_jungletree
|
||||
end
|
||||
end
|
||||
vi_1 = vi_1 + 1
|
||||
vi_2 = vi_2 + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Pine tree from mg mapgen mod, design by sfan5, pointy top added by paramat
|
||||
|
||||
local function add_pine_needles(data, vi, c_air, c_ignore, c_snow, c_pine_needles)
|
||||
local node_id = data[vi]
|
||||
if node_id == c_air or node_id == c_ignore or node_id == c_snow then
|
||||
data[vi] = c_pine_needles
|
||||
end
|
||||
end
|
||||
|
||||
local function add_snow(data, vi, c_air, c_ignore, c_snow)
|
||||
local node_id = data[vi]
|
||||
if node_id == c_air or node_id == c_ignore then
|
||||
data[vi] = c_snow
|
||||
end
|
||||
end
|
||||
|
||||
function default.grow_pine_tree(data, a, pos, sapling_data, extra_params )
|
||||
|
||||
-- translate parameter names
|
||||
local c_pine_tree = sapling_data.cid.tree;
|
||||
local c_pine_needles = sapling_data.cid.leaves;
|
||||
|
||||
-- other internal parameters
|
||||
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")
|
||||
local c_snow = minetest.get_content_id("default:snow")
|
||||
local c_snowblock = minetest.get_content_id("default:snowblock")
|
||||
local c_dirtsnow = minetest.get_content_id("default:dirt_with_snow")
|
||||
|
||||
-- Scan for snow nodes near sapling to enable snow on branches
|
||||
local snow = false
|
||||
for yy = y - 1, y + 1 do
|
||||
for zz = z - 1, z + 1 do
|
||||
local vi = a:index(x - 1, yy, zz)
|
||||
for xx = x - 1, x + 1 do
|
||||
local nodid = data[vi]
|
||||
if nodid == c_snow or nodid == c_snowblock or nodid == c_dirtsnow then
|
||||
snow = true
|
||||
end
|
||||
vi = vi + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- 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,
|
||||
c_pine_needles)
|
||||
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,
|
||||
c_pine_needles)
|
||||
add_pine_needles(data, a:index(x, maxy + 2, z), c_air, c_ignore, c_snow,
|
||||
c_pine_needles) -- Paramat added a pointy top node
|
||||
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,
|
||||
c_pine_needles)
|
||||
if snow then
|
||||
add_snow(data, via, c_air, c_ignore, c_snow)
|
||||
end
|
||||
vi = vi + 1
|
||||
via = via + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local dev = 2
|
||||
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,
|
||||
c_pine_needles)
|
||||
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
|
||||
data[a:index(x, y, z)] = c_pine_tree -- Force-place lowest trunk node to replace sapling
|
||||
for yy = y + 1, maxy do
|
||||
local vi = a:index(x, yy, z)
|
||||
local node_id = data[vi]
|
||||
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
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Trees
|
||||
--
|
||||
|
||||
-- the normal tree does not have a special name and no space after it
|
||||
trees_lib.register_tree( "normal",
|
||||
{ tree = {
|
||||
node_name = "default:tree",
|
||||
tiles = {"default_tree_top.png", "default_tree_top.png", "default_tree.png"},
|
||||
paramtype2 = "facedir",
|
||||
}, wood = {
|
||||
node_name = "default:wood",
|
||||
description = "Wooden Planks",
|
||||
tiles = {"default_wood.png"},
|
||||
}, sapling = {
|
||||
node_name = "default:sapling",
|
||||
description = "Sapling",
|
||||
tiles = {"default_sapling.png"},
|
||||
}, leaves = {
|
||||
node_name = "default:leaves",
|
||||
description = "Leaves",
|
||||
tiles = {"default_leaves.png"},
|
||||
special_tiles = {"default_leaves_simple.png"},
|
||||
}, fruit = {
|
||||
node_name = "default:apple",
|
||||
description = "Apple",
|
||||
tiles = {"default_apple.png"},
|
||||
on_use = minetest.item_eat(2),
|
||||
}},
|
||||
-- growing methods:
|
||||
{
|
||||
{ -- the first growing method uses a function
|
||||
use_function = default.grow_apple_tree,
|
||||
xoff = 2, zoff = 2, yoff = 8, height = 15,
|
||||
}, { -- the second growing method (when mapgen is not v6) uses a schematic
|
||||
use_schematic = minetest.get_modpath("default") .. "/schematics/apple_tree_from_sapling.mts",
|
||||
xoff = 2, zoff = 2, yoff = 1, height = 10,
|
||||
}
|
||||
},
|
||||
-- grows on nodes of this type:
|
||||
{"group:soil"},
|
||||
-- can_grow_function: (in this case, checks if there is enough light)
|
||||
can_grow,
|
||||
-- select_how_to_grow_function:
|
||||
default_select_how_to_grow,
|
||||
-- interval (for the abm)
|
||||
10,
|
||||
-- chance (for the abm)
|
||||
50
|
||||
);
|
||||
|
||||
-- the jungletree has no space between tree name and fruther parts of the name
|
||||
trees_lib.register_tree( "jungle",
|
||||
{ tree = {
|
||||
node_name = "default:jungletree",
|
||||
description = "Jungle Tree",
|
||||
tiles = {"default_jungletree_top.png", "default_jungletree_top.png",
|
||||
"default_jungletree.png"},
|
||||
}, wood = {
|
||||
node_name = "default:junglewood",
|
||||
description = "Junglewood Planks",
|
||||
tiles = {"default_junglewood.png"},
|
||||
}, sapling = {
|
||||
node_name = "default:junglesapling",
|
||||
description = "Jungle Sapling",
|
||||
tiles = {"default_junglesapling.png"},
|
||||
}, leaves = {
|
||||
node_name = "default:jungleleaves",
|
||||
description = "Jungle Leaves",
|
||||
tiles = {"default_jungleleaves.png"},
|
||||
special_tiles = {"default_jungleleaves_simple.png"},
|
||||
-- the jungletree has no fruit
|
||||
}, fruit = {
|
||||
node_name = "air",
|
||||
}},
|
||||
{ { -- the first growing method uses a function
|
||||
use_function = default.grow_jungle_tree,
|
||||
xoff = 3, zoff = 3, yoff = 1, height = 15,
|
||||
},{ -- new jungle tree (grown from schematic)
|
||||
use_schematic = minetest.get_modpath("default") .. "/schematics/jungle_tree_from_sapling.mts",
|
||||
xoff = 2, zoff = 2, yoff = 1, height = 10,
|
||||
}
|
||||
},
|
||||
{"group:soil"},
|
||||
can_grow,
|
||||
default_select_how_to_grow,
|
||||
10, 50);
|
||||
|
||||
|
||||
-- the pine tree mostly follows naming conventions
|
||||
trees_lib.register_tree( "pine",
|
||||
-- ...except for the leaves, which are needles
|
||||
{ leaves = {
|
||||
node_name = "default:pine_needles",
|
||||
description = "Pine Needles",
|
||||
tiles = {"default_pine_needles.png"},
|
||||
-- the pine tree also has no fruit
|
||||
}, fruit = {
|
||||
node_name = "air",
|
||||
}},
|
||||
{
|
||||
{ -- the old pine tree (in mapgen v6) grows using a function
|
||||
use_function = default.grow_pine_tree,
|
||||
-- we need to know how much space will have to be loaded into voxelmanip
|
||||
xoff = 3, zoff = 3, yoff = 1, height = 18,
|
||||
}, { -- new pine tree (grown from schematic)
|
||||
use_schematic = minetest.get_modpath("default") .. "/schematics/pine_tree_from_sapling.mts",
|
||||
xoff = 2, zoff = 2, yoff = 1, height = 10,
|
||||
}
|
||||
},
|
||||
{"group:soil"},
|
||||
can_grow,
|
||||
default_select_how_to_grow,
|
||||
10, 50);
|
||||
|
||||
|
||||
-- the acacia tree follows naming conventions
|
||||
trees_lib.register_tree( "acacia",
|
||||
-- the acacia tree has no fruit
|
||||
{ fruit = {
|
||||
node_name = "air",
|
||||
}},
|
||||
-- the acacia only knows to grow from a schematic
|
||||
{
|
||||
{ -- new acacia tree (grown from schematic)
|
||||
use_schematic = minetest.get_modpath("default") .. "/schematics/acacia_tree_from_sapling.mts",
|
||||
xoff = 4, zoff = 4, yoff = 1, height = 10,
|
||||
}
|
||||
},
|
||||
{"group:soil","group:sand"},
|
||||
can_grow,
|
||||
-- the acacia only has the schematic version - there is no other growing method to select
|
||||
nil,
|
||||
10, 50);
|
||||
|
||||
|
||||
-- aspen tree - follows naming conventions as well
|
||||
trees_lib.register_tree( "aspen",
|
||||
{ fruit = {
|
||||
node_name = "air",
|
||||
}},
|
||||
{
|
||||
{
|
||||
use_schematic = minetest.get_modpath("default") .. "/schematics/aspen_tree_from_sapling.mts",
|
||||
xoff = 2, zoff = 2, yoff = 1, height = 16,
|
||||
}
|
||||
},
|
||||
{"group:soil"},
|
||||
can_grow,
|
||||
nil,
|
||||
10, 50);
|
||||
|
139
trees_lib_growing_functions.lua
Normal file
139
trees_lib_growing_functions.lua
Normal file
@ -0,0 +1,139 @@
|
||||
|
||||
|
||||
|
||||
--[[ the version from mg_villages
|
||||
-- this is more or less the code to grow an apple tree with v6
|
||||
trees_lib.generate_fruit_tree = function(data, a, pos, is_apple_tree, seed, snow)
|
||||
local leaves_type = c_leaves;
|
||||
if( snow
|
||||
or data[ a:index(pos.x, pos.y, pos.z) ] == c_snow
|
||||
or data[ a:index(pos.x, pos.y+1, pos.z) ] == c_snow ) then
|
||||
leaves_type = c_msnow_leaves2;
|
||||
end
|
||||
|
||||
local hight = math.random(4, 5)
|
||||
for x_area = -2, 2 do
|
||||
for y_area = -1, 2 do
|
||||
for z_area = -2, 2 do
|
||||
if math.random(1,30) < 23 then --randomize leaves
|
||||
local area_l = a:index(pos.x+x_area, pos.y+hight+y_area-1, pos.z+z_area) --sets area for leaves
|
||||
if data[area_l] == c_air or data[area_l] == c_ignore or data[area_l]== c_snow then --sets if it's air or ignore
|
||||
if( snow and c_msnow_leaves1 and math.random( 1,5 )==1) then
|
||||
data[area_l] = c_msnow_leaves1;
|
||||
else
|
||||
data[area_l] = leaves_type --add leaves now
|
||||
end
|
||||
end
|
||||
-- put a snow top on some leaves
|
||||
if ( snow and math.random(1,3)==1 )then
|
||||
mg_villages.trees_add_snow(data, a:index(pos.x+x_area, pos.y+hight+y_area, pos.z+z_area), c_air, c_ignore, c_snow)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for tree_h = 0, hight-1 do -- add the trunk
|
||||
local area_t = a:index(pos.x, pos.y+tree_h, pos.z) --set area for tree
|
||||
if data[area_t] == c_air or data[area_t] == c_leaves or data[area_t] == c_sapling or data[area_t] == c_snow or data[area_t] == c_msnow_top or data[area_t] == c_msnow_leaves1 or data[area_t] == c_msnow_leaves2 then --sets if air
|
||||
data[area_t] = c_tree --add tree now
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--]]
|
||||
|
||||
-- Apple tree and jungle tree trunk and leaves function
|
||||
|
||||
trees_lib.generate_fruit_tree = function(data, a, pos, sapling_data, extra_params )
|
||||
|
||||
local tree_cid = sapling_data.cid.tree;
|
||||
local leaves_cid = sapling_data.cid.leaves;
|
||||
local fruit_cid = sapling_data.cid.fruit;
|
||||
|
||||
local height = math.random(3,7);
|
||||
local size = 2; --math.random(1,3);
|
||||
local iters = 8;
|
||||
|
||||
local x, y, z = pos.x, pos.y, pos.z
|
||||
local c_air = minetest.get_content_id("air")
|
||||
local c_ignore = minetest.get_content_id("ignore")
|
||||
|
||||
-- Trunk
|
||||
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)
|
||||
local node_id = data[vi]
|
||||
if node_id == c_air or node_id == c_ignore or node_id == 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 or data[vi] == c_ignore then
|
||||
if fruit_cid and fruit_cid ~= leaves_cid and math.random(1, 8) == 1 then
|
||||
data[vi] = fruit_cid
|
||||
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 + math.random(-size, size - 1)
|
||||
local clust_y = y + height + math.random(-size, 0)
|
||||
local clust_z = z + math.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 or data[vi] == c_ignore then
|
||||
if fruit_cid and fruit_cid ~= leaves_cid and math.random(1, 8) == 1 then
|
||||
data[vi] = fruit_cid
|
||||
else
|
||||
data[vi] = leaves_cid
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- a very small tree
|
||||
trees_lib.generate_unhappy_tree = function(data, a, pos, sapling_data, extra_params )
|
||||
|
||||
local tree_cid = sapling_data.cid.tree;
|
||||
local leaves_cid = sapling_data.cid.leaves;
|
||||
|
||||
local x, y, z = pos.x, pos.y, pos.z
|
||||
local c_air = minetest.get_content_id("air")
|
||||
local c_ignore = minetest.get_content_id("ignore")
|
||||
|
||||
-- Trunk
|
||||
data[a:index(x, y, z)] = tree_cid;
|
||||
local found = data[a:index(x, y+1, z )];
|
||||
if( found==c_air or found==c_ignore ) then
|
||||
data[a:index(x, y+1, z)] = tree_cid;
|
||||
end
|
||||
for xv=-1,1 do
|
||||
for zv=-1,1 do
|
||||
if( math.random(1,2)==1 ) then
|
||||
local found = data[a:index(x+xv, y+1, z+zv )]
|
||||
if( found==c_air or found==c_ignore ) then
|
||||
data[a:index(x+xv, y+1, z+zv )] = leaves_cid;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user