Limit entity speed to 250m/s.
[oweals/minetest_game.git] / mods / default / trees.lua
index eaf85f966fcfbaca05664d0090a7122375a173a5..de2452e4190a61408fc2805337b884e415c4f59d 100644 (file)
@@ -1,10 +1,12 @@
+local random = math.random
+
 --
--- Grow trees
+-- Grow trees from saplings
 --
 
-local random = math.random
+-- 'can grow' function
 
-local function can_grow(pos)
+function default.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
@@ -14,57 +16,106 @@ local function can_grow(pos)
        if is_soil == 0 then
                return false
        end
+       local light_level = minetest.get_node_light(pos)
+       if not light_level or light_level < 13 then
+               return false
+       end
        return true
 end
 
--- Sapling ABMs
 
-minetest.register_abm({
-       nodenames = {"default:sapling"},
-       interval = 10,
-       chance = 50,
-       action = function(pos, node)
-               if not can_grow(pos) then
-                       return
-               end
+-- 'is snow nearby' function
 
-               minetest.log("action", "A sapling grows into a tree at "..
-                               minetest.pos_to_string(pos))
-               default.grow_tree(pos, random(1, 4) == 1)
-       end
-})
+local function is_snow_nearby(pos)
+       local x, y, z = pos.x, pos.y, pos.z
+       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")
 
-minetest.register_abm({
-       nodenames = {"default:junglesapling"},
-       interval = 11,
-       chance = 50,
-       action = function(pos, node)
-               if not can_grow(pos) then
-                       return
-               end
+       local vm = minetest.get_voxel_manip()
+       local minp, maxp = vm:read_from_map(
+               {x = x - 1, y = y - 1, z = z - 1},
+               {x = x + 1, y = y + 1, z = z + 1}
+       )
+       local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp})
+       local data = vm:get_data()
 
-               minetest.log("action", "A jungle sapling grows into a tree at "..
-                               minetest.pos_to_string(pos))
-               default.grow_jungle_tree(pos)
+       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
+                               return true
+                       end
+                       vi  = vi + 1
+               end
        end
-})
+       end
+
+       return false
+end
+
+
+-- Sapling ABM
 
 minetest.register_abm({
-       nodenames = {"default:pine_sapling"},
-       interval = 12,
+       nodenames = {"default:sapling", "default:junglesapling",
+               "default:pine_sapling", "default:acacia_sapling",
+               "default:aspen_sapling"},
+       interval = 10,
        chance = 50,
        action = function(pos, node)
-               if not can_grow(pos) then
+               if not default.can_grow(pos) then
                        return
                end
 
-               minetest.log("action", "A pine sapling grows into a tree at "..
+               local mapgen = minetest.get_mapgen_params().mgname
+               if node.name == "default:sapling" then
+                       minetest.log("action", "A sapling grows into a tree at "..
+                               minetest.pos_to_string(pos))
+                       if mapgen == "v6" then
+                               default.grow_tree(pos, random(1, 4) == 1)
+                       else
+                               default.grow_new_apple_tree(pos)
+                       end
+               elseif node.name == "default:junglesapling" then
+                       minetest.log("action", "A jungle sapling grows into a tree at "..
+                               minetest.pos_to_string(pos))
+                       if mapgen == "v6" then
+                               default.grow_jungle_tree(pos)
+                       else
+                               default.grow_new_jungle_tree(pos)
+                       end
+               elseif node.name == "default:pine_sapling" then
+                       minetest.log("action", "A pine sapling grows into a tree at "..
+                               minetest.pos_to_string(pos))
+                       local snow = is_snow_nearby(pos)
+                       if mapgen == "v6" then
+                               default.grow_pine_tree(pos, snow)
+                       elseif snow then
+                               default.grow_new_snowy_pine_tree(pos)
+                       else
+                               default.grow_new_pine_tree(pos)
+                       end
+               elseif node.name == "default:acacia_sapling" then
+                       minetest.log("action", "An acacia sapling grows into a tree at "..
                                minetest.pos_to_string(pos))
-               default.grow_pine_tree(pos)
+                       default.grow_new_acacia_tree(pos)
+               elseif node.name == "default:aspen_sapling" then
+                       minetest.log("action", "An aspen sapling grows into a tree at "..
+                               minetest.pos_to_string(pos))
+                       default.grow_new_aspen_tree(pos)
+               end
        end
 })
 
--- Appletree, jungletree function
+
+--
+-- 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)
@@ -74,11 +125,11 @@ local function add_trunk_and_leaves(data, a, pos, tree_cid, leaves_cid,
        local c_apple = minetest.get_content_id("default:apple")
 
        -- Trunk
-       for y_dist = 0, height - 1 do
-               local vi = a:index(x, y + y_dist, z)
+       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 y_dist == 0 or node_id == c_air or node_id == c_ignore
-               or node_id == leaves_cid then
+               if node_id == c_air or node_id == c_ignore or node_id == leaves_cid then
                        data[vi] = tree_cid
                end
        end
@@ -123,7 +174,8 @@ local function add_trunk_and_leaves(data, a, pos, tree_cid, leaves_cid,
        end
 end
 
--- Appletree
+
+-- Apple tree
 
 function default.grow_tree(pos, is_apple_tree, bad)
        --[[
@@ -155,7 +207,8 @@ function default.grow_tree(pos, is_apple_tree, bad)
        vm:update_map()
 end
 
--- Jungletree
+
+-- Jungle tree
 
 function default.grow_jungle_tree(pos, bad)
        --[[
@@ -182,7 +235,8 @@ function default.grow_jungle_tree(pos, bad)
        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)
+       add_trunk_and_leaves(data, a, pos, c_jungletree, c_jungleleaves,
+               height, 3, 30, false)
 
        -- Roots
        for z_dist = -1, 1 do
@@ -206,57 +260,41 @@ function default.grow_jungle_tree(pos, bad)
        vm:update_map()
 end
 
--- Pinetree from mg mapgen mod, design by sfan5, pointy top added by paramat
+
+-- 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)
-       if data[vi] == c_air or data[vi] == c_ignore or data[vi] == c_snow then
+       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)
-       if data[vi] == c_air or data[vi] == c_ignore then
+       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(pos)
+function default.grow_pine_tree(pos, snow)
        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_pinetree = minetest.get_content_id("default:pinetree")
+       local c_pine_tree = minetest.get_content_id("default:pine_tree")
        local c_pine_needles  = minetest.get_content_id("default:pine_needles")
        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")
 
        local vm = minetest.get_voxel_manip()
        local minp, maxp = vm:read_from_map(
-               {x = x - 3, y = y - 1, z = z - 3},
+               {x = x - 3, y = y, z = z - 3},
                {x = x + 3, y = maxy + 3, z = z + 3}
        )
        local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp})
        local data = vm:get_data()
 
-       -- Scan for snow nodes near sapling
-       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
@@ -266,7 +304,7 @@ function default.grow_pine_tree(pos)
                        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)
+                                               c_pine_needles)
                                        if snow then
                                                add_snow(data, via, c_air, c_ignore, c_snow)
                                        end
@@ -280,9 +318,9 @@ function default.grow_pine_tree(pos)
 
        -- Centre top nodes
        add_pine_needles(data, a:index(x, maxy + 1, z), c_air, c_ignore, c_snow,
-                       c_pine_needles)
+               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
+               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
@@ -301,7 +339,7 @@ function default.grow_pine_tree(pos)
                        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)
+                                       c_pine_needles)
                                if snow then
                                        add_snow(data, via, c_air, c_ignore, c_snow)
                                end
@@ -319,7 +357,7 @@ function default.grow_pine_tree(pos)
                        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)
+                                               c_pine_needles)
                                        if snow then
                                                add_snow(data, via, c_air, c_ignore, c_snow)
                                        end
@@ -332,9 +370,15 @@ function default.grow_pine_tree(pos)
        end
 
        -- Trunk
-       for yy = y, maxy do
+       -- Force-place lowest trunk node to replace sapling
+       data[a:index(x, y, z)] = c_pine_tree
+       for yy = y + 1, maxy do
                local vi = a:index(x, yy, z)
-               data[vi] = c_pinetree
+               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
 
        vm:set_data(data)
@@ -342,3 +386,61 @@ function default.grow_pine_tree(pos)
        vm:update_map()
 end
 
+
+-- New apple tree
+
+function default.grow_new_apple_tree(pos)
+       local path = minetest.get_modpath("default") ..
+               "/schematics/apple_tree_from_sapling.mts"
+       minetest.place_schematic({x = pos.x - 2, y = pos.y - 1, z = pos.z - 2},
+               path, "0", nil, false)
+end
+
+
+-- New jungle tree
+
+function default.grow_new_jungle_tree(pos)
+       local path = minetest.get_modpath("default") ..
+               "/schematics/jungle_tree_from_sapling.mts"
+       minetest.place_schematic({x = pos.x - 2, y = pos.y - 1, z = pos.z - 2},
+               path, "random", nil, false)
+end
+
+
+-- New pine tree
+
+function default.grow_new_pine_tree(pos)
+       local path = minetest.get_modpath("default") ..
+               "/schematics/pine_tree_from_sapling.mts"
+       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)
+       local path = minetest.get_modpath("default") ..
+               "/schematics/snowy_pine_tree_from_sapling.mts"
+       minetest.place_schematic({x = pos.x - 2, y = pos.y - 1, z = pos.z - 2},
+               path, "random", nil, false)
+end
+
+
+-- New acacia tree
+
+function default.grow_new_acacia_tree(pos)
+       local path = minetest.get_modpath("default") ..
+               "/schematics/acacia_tree_from_sapling.mts"
+       minetest.place_schematic({x = pos.x - 4, y = pos.y - 1, z = pos.z - 4},
+               path, "random", nil, false)
+end
+
+-- New aspen tree
+
+function default.grow_new_aspen_tree(pos)
+       local path = minetest.get_modpath("default") ..
+               "/schematics/aspen_tree_from_sapling.mts"
+       minetest.place_schematic({x = pos.x - 2, y = pos.y - 1, z = pos.z - 2},
+               path, "0", nil, false)
+end