diff --git a/mods/ITEMS/mcl_cherry_blossom/growth.lua b/mods/ITEMS/mcl_cherry_blossom/growth.lua index c7bbf3044..701990204 100644 --- a/mods/ITEMS/mcl_cherry_blossom/growth.lua +++ b/mods/ITEMS/mcl_cherry_blossom/growth.lua @@ -1,19 +1,14 @@ -- Tree Growth -- TODO: Use better spawning behavior and wood api when wood api is finished. function mcl_cherry_blossom.generate_cherry_tree(pos) - local pr = PseudoRandom(pos.x+pos.y+pos.z) - local r = pr:next(1,3) - local modpath = minetest.get_modpath("mcl_cherry_blossom") - local path = modpath.."/schematics/mcl_cherry_blossom_tree_"..tostring(r)..".mts" - if mcl_core.check_growth_width(pos,7,8) then - minetest.set_node(pos, {name = "air"}) - if r == 1 then - minetest.place_schematic(vector.offset(pos, -2, 0, -2), path, "random", nil, false) - elseif r == 2 then - minetest.place_schematic(vector.offset(pos, -2, 0, -2), path, nil, nil, false) - elseif r == 3 then - minetest.place_schematic(vector.offset(pos, -3, 0, -3), path, nil, nil, false) - end + local r = math.random(1,3) + local path = minetest.get_modpath("mcl_cherry_blossom").."/schematics/mcl_cherry_blossom_tree_"..r..".mts" + if r == 1 then + minetest.place_schematic(vector.offset(pos, -2, 0, -2), path, "random", nil, false) + elseif r == 2 then + minetest.place_schematic(vector.offset(pos, -2, 0, -2), path, nil, nil, false) + elseif r == 3 then + minetest.place_schematic(vector.offset(pos, -3, 0, -3), path, nil, nil, false) end end @@ -21,10 +16,10 @@ minetest.register_abm({ label = "Cherry Tree Growth", nodenames = "mcl_cherry_blossom:cherrysapling", interval = 30, - chance = 5, - action = function(pos,node) - mcl_cherry_blossom.generate_cherry_tree(pos) - end, + chance = 3, + action = function(pos, node) + mcl_core.grow_cherry(pos, node, 1) + end }) local cherry_particle = { diff --git a/mods/ITEMS/mcl_core/functions.lua b/mods/ITEMS/mcl_core/functions.lua index ca0f75e1c..9bc813ecc 100644 --- a/mods/ITEMS/mcl_core/functions.lua +++ b/mods/ITEMS/mcl_core/functions.lua @@ -22,6 +22,7 @@ local SPRUCE_TREE_ID = 3 local ACACIA_TREE_ID = 4 local JUNGLE_TREE_ID = 5 local BIRCH_TREE_ID = 6 +local CHERRY_TREE_ID = 7 minetest.register_abm({ label = "Lava cooling", @@ -305,6 +306,8 @@ local function check_tree_growth(pos, tree_id, options) return check_growth_width(pos, 7, 8) elseif tree_id == DARK_OAK_TREE_ID and two_by_two then return check_growth_width(pos, 4, 7) + elseif tree_id == CHERRY_TREE_ID then + return check_growth_width(pos, 7, 8) end return false @@ -356,6 +359,8 @@ function mcl_core.generate_tree(pos, tree_type, options) end elseif tree_type == BIRCH_TREE_ID then mcl_core.generate_birch_tree(pos) + elseif tree_type == CHERRY_TREE_ID and mcl_cherry_blossom then + mcl_cherry_blossom.generate_cherry_tree(pos) end mcl_core.update_sapling_foliage_colors(pos) end @@ -822,35 +827,14 @@ minetest.register_lbm({ -------------------------- -- Try generate tree --- -------------------------- -local treelight = 9 +local TREE_MINIMUM_LIGHT = 9 local function sapling_grow_action(tree_id, soil_needed, one_by_one, two_by_two, sapling) - return function(pos) + return function(pos, node, grow_by) local meta = minetest.get_meta(pos) - if meta:get("grown") then return end -- Checks if the sapling at pos has enough light and the correct soil local light = minetest.get_node_light(pos) - if not light then return end - local low_light = light < treelight - - local delta = 1 - local current_game_time = minetest.get_day_count() + minetest.get_timeofday() - - local last_game_time = tonumber(meta:get_string("last_gametime")) - meta:set_string("last_gametime", tostring(current_game_time)) - - if last_game_time then - delta = current_game_time - last_game_time - elseif low_light then - return - end - - if low_light then - if delta < 1.2 then return end - if minetest.get_node_light(pos, 0.5) < treelight then return end - end - - -- TODO: delta is [days] missed in inactive area. Currently we just add it to stage, which is far from a perfect calculation... + if not light or light < TREE_MINIMUM_LIGHT then return end local soilnode = minetest.get_node(vector_offset(pos, 0, -1, 0)) local soiltype = minetest.get_item_group(soilnode.name, "soil_sapling") @@ -858,86 +842,80 @@ local function sapling_grow_action(tree_id, soil_needed, one_by_one, two_by_two, -- Increase and check growth stage local meta = minetest.get_meta(pos) - local stage = meta:get_int("stage") - if stage == nil then stage = 0 end - stage = stage + max(1, floor(delta)) - if stage >= 3 then - meta:set_string("grown", "true") - -- This sapling grows in a special way when there are 4 saplings in a 2x2 pattern - if two_by_two then - -- Check 8 surrounding saplings and try to find a 2x2 pattern - local function is_sapling(pos, sapling) - return minetest.get_node(pos).name == sapling - end - -- clockwise from x+1, coded right/bottom/left/top - local prr = vector_offset(pos, 1, 0, 0) -- right - local prb = vector_offset(pos, 1, 0, -1) -- right bottom - local pbb = vector_offset(pos, 0, 0, -1) -- bottom - local pbl = vector_offset(pos, -1, 0, -1) -- bottom left - local pll = vector_offset(pos, -1, 0, 0) -- left - local plt = vector_offset(pos, -1, 0, 1) -- left top - local ptt = vector_offset(pos, 0, 0, 1) -- top - local ptr = vector_offset(pos, 1, 0, 1) -- top right - local srr = is_sapling(prr, sapling) - local srb = is_sapling(prb, sapling) - local sbb = is_sapling(pbb, sapling) - local sbl = is_sapling(pbl, sapling) - local sll = is_sapling(pll, sapling) - local slt = is_sapling(plt, sapling) - local stt = is_sapling(ptt, sapling) - local str = is_sapling(ptr, sapling) - -- In a 3x3 field there are 4 possible 2x2 squares. We check them all. - if srr and srb and sbb and check_tree_growth(pos, tree_id, { two_by_two = true }) then - -- Success: Remove saplings and place tree - minetest.remove_node(pos) - minetest.remove_node(prr) - minetest.remove_node(prb) - minetest.remove_node(pbb) - mcl_core.generate_tree(pos, tree_id, { two_by_two = true }) -- center is top-left of 2x2 - return - elseif sbb and sbl and sll and check_tree_growth(pll, tree_id, { two_by_two = true }) then - minetest.remove_node(pos) - minetest.remove_node(pbb) - minetest.remove_node(pbl) - minetest.remove_node(pll) - mcl_core.generate_tree(pll, tree_id, { two_by_two = true }) -- ll is top-left of 2x2 - return - elseif sll and slt and stt and check_tree_growth(plt, tree_id, { two_by_two = true }) then - minetest.remove_node(pos) - minetest.remove_node(pll) - minetest.remove_node(plt) - minetest.remove_node(ptt) - mcl_core.generate_tree(plt, tree_id, { two_by_two = true }) -- lt is top-left of 2x2 - return - elseif stt and str and srr and check_tree_growth(ptt, tree_id, { two_by_two = true }) then - minetest.remove_node(pos) - minetest.remove_node(ptt) - minetest.remove_node(ptr) - minetest.remove_node(prr) - mcl_core.generate_tree(ptt, tree_id, { two_by_two = true }) -- tt is top-left of 2x2 - return - end - end - if one_by_one and tree_id == OAK_TREE_ID then - -- There is a chance that this tree wants to grow as a balloon oak - if random(1, 12) == 1 then - -- Check if there is room for that - if check_tree_growth(pos, tree_id, { balloon = true }) then - minetest.set_node(pos, {name="air"}) - mcl_core.generate_tree(pos, tree_id, { balloon = true }) - return - end - end - end - -- If this sapling can grow alone - if one_by_one and check_tree_growth(pos, tree_id) then - -- Single sapling - minetest.set_node(pos, {name="air"}) - mcl_core.generate_tree(pos, tree_id) + local stage = (meta:get_int("stage") or 0) + (grow_by or 1) + if stage < 3 then + meta:set_int("stage", stage) + return + end + -- This sapling grows in a special way when there are 4 saplings in a 2x2 pattern + if two_by_two then + -- Check 8 surrounding saplings and try to find a 2x2 pattern + -- clockwise from x+1, coded right/bottom/left/top + local prr = vector_offset(pos, 1, 0, 0) -- right + local prb = vector_offset(pos, 1, 0, -1) -- right bottom + local pbb = vector_offset(pos, 0, 0, -1) -- bottom + local pbl = vector_offset(pos, -1, 0, -1) -- bottom left + local pll = vector_offset(pos, -1, 0, 0) -- left + local plt = vector_offset(pos, -1, 0, 1) -- left top + local ptt = vector_offset(pos, 0, 0, 1) -- top + local ptr = vector_offset(pos, 1, 0, 1) -- top right + local srr = minetest.get_node(prr).name == sapling + local srb = minetest.get_node(prb).name == sapling + local sbb = minetest.get_node(pbb).name == sapling + local sbl = minetest.get_node(pbl).name == sapling + local sll = minetest.get_node(pll).name == sapling + local slt = minetest.get_node(plt).name == sapling + local stt = minetest.get_node(ptt).name == sapling + local str = minetest.get_node(ptr).name == sapling + -- In a 3x3 field there are 4 possible 2x2 squares. We check them all. + if srr and srb and sbb and check_tree_growth(pos, tree_id, { two_by_two = true }) then + -- Success: Remove saplings and place tree + minetest.remove_node(pos) + minetest.remove_node(prr) + minetest.remove_node(prb) + minetest.remove_node(pbb) + mcl_core.generate_tree(pos, tree_id, { two_by_two = true }) -- center is top-left of 2x2 + return + elseif sbb and sbl and sll and check_tree_growth(pll, tree_id, { two_by_two = true }) then + minetest.remove_node(pos) + minetest.remove_node(pbb) + minetest.remove_node(pbl) + minetest.remove_node(pll) + mcl_core.generate_tree(pll, tree_id, { two_by_two = true }) -- ll is top-left of 2x2 + return + elseif sll and slt and stt and check_tree_growth(plt, tree_id, { two_by_two = true }) then + minetest.remove_node(pos) + minetest.remove_node(pll) + minetest.remove_node(plt) + minetest.remove_node(ptt) + mcl_core.generate_tree(plt, tree_id, { two_by_two = true }) -- lt is top-left of 2x2 + return + elseif stt and str and srr and check_tree_growth(ptt, tree_id, { two_by_two = true }) then + minetest.remove_node(pos) + minetest.remove_node(ptt) + minetest.remove_node(ptr) + minetest.remove_node(prr) + mcl_core.generate_tree(ptt, tree_id, { two_by_two = true }) -- tt is top-left of 2x2 return end - else - meta:set_int("stage", stage) + end + if one_by_one and tree_id == OAK_TREE_ID then + -- There is a chance that this tree wants to grow as a balloon oak + if random(1, 12) == 1 then + -- Check if there is room for that + if check_tree_growth(pos, tree_id, { balloon = true }) then + minetest.set_node(pos, {name="air"}) + mcl_core.generate_tree(pos, tree_id, { balloon = true }) + return + end + end + end + -- If this sapling can grow alone + if one_by_one and check_tree_growth(pos, tree_id) then + -- Single sapling + minetest.set_node(pos, {name="air"}) + mcl_core.generate_tree(pos, tree_id) + return end end end @@ -948,6 +926,9 @@ local grow_jungle_tree = sapling_grow_action(JUNGLE_TREE_ID, 1, true, true, "mcl local grow_acacia = sapling_grow_action(ACACIA_TREE_ID, 2, true, false) local grow_spruce = sapling_grow_action(SPRUCE_TREE_ID, 1, true, true, "mcl_core:sprucesapling") local grow_birch = sapling_grow_action(BIRCH_TREE_ID, 1, true, false) +local grow_cherry = sapling_grow_action(CHERRY_TREE_ID, 1, true, false) +-- export for cherry tree module +mcl_core.grow_cherry = grow_cherry function mcl_core.update_sapling_foliage_colors(pos) local foliage = minetest.find_nodes_in_area( @@ -963,45 +944,37 @@ end -- node: Node table of the node at this position, from minetest.get_node -- Returns true on success and false on failure -- TODO: replace this with a proper tree API -function mcl_core.grow_sapling(pos, node) +function mcl_core.grow_sapling(pos, node, stages) if node.name == "mcl_core:sapling" then - grow_oak(pos) + grow_oak(pos, node, nil, nil, stages) elseif node.name == "mcl_core:darksapling" then - grow_dark_oak(pos) + grow_dark_oak(pos, node, nil, nil, stages) elseif node.name == "mcl_core:junglesapling" then - grow_jungle_tree(pos) + grow_jungle_tree(pos, node, nil, nil, stages) elseif node.name == "mcl_core:acaciasapling" then - grow_acacia(pos) + grow_acacia(pos, node, nil, nil, stages) elseif node.name == "mcl_core:sprucesapling" then - grow_spruce(pos) + grow_spruce(pos, node, nil, nil, stages) elseif node.name == "mcl_core:birchsapling" then - grow_birch(pos) + grow_birch(pos, node, nil, nil, stages) elseif node.name == "mcl_cherry_blossom:cherrysapling" then - return mcl_cherry_blossom.generate_cherry_tree(pos) + grow_cherry(pos, node, nil, nil, stages) else return false end return true end --- TODO: Use better tree models for everything --- TODO: Support 2x2 saplings - -- Oak tree minetest.register_abm({ label = "Oak tree growth", nodenames = {"mcl_core:sapling"}, neighbors = {"group:soil_sapling"}, - interval = 25, - chance = 2, - action = grow_oak -}) -minetest.register_lbm({ - label = "Add growth for unloaded oak tree", - name = "mcl_core:lbm_oak", - nodenames = {"mcl_core:sapling"}, - run_at_every_load = true, - action = grow_oak + interval = 30, + chance = 3, + action = function(pos, node) + grow_oak(pos, node, 1) + end }) -- Dark oak tree @@ -1009,16 +982,11 @@ minetest.register_abm({ label = "Dark oak tree growth", nodenames = {"mcl_core:darksapling"}, neighbors = {"group:soil_sapling"}, - interval = 25, - chance = 2, - action = grow_dark_oak -}) -minetest.register_lbm({ - label = "Add growth for unloaded dark oak tree", - name = "mcl_core:lbm_dark_oak", - nodenames = {"mcl_core:darksapling"}, - run_at_every_load = true, - action = grow_dark_oak + interval = 30, + chance = 3, + action = function(pos, node) + grow_dark_oak(pos, node, 1) + end }) -- Jungle Tree @@ -1026,16 +994,11 @@ minetest.register_abm({ label = "Jungle tree growth", nodenames = {"mcl_core:junglesapling"}, neighbors = {"group:soil_sapling"}, - interval = 25, - chance = 2, - action = grow_jungle_tree -}) -minetest.register_lbm({ - label = "Add growth for unloaded jungle tree", - name = "mcl_core:lbm_jungle_tree", - nodenames = {"mcl_core:junglesapling"}, - run_at_every_load = true, - action = grow_jungle_tree + interval = 30, + chance = 3, + action = function(pos, node) + grow_jungle_tree(pos, node, 1) + end }) -- Spruce tree @@ -1043,16 +1006,11 @@ minetest.register_abm({ label = "Spruce tree growth", nodenames = {"mcl_core:sprucesapling"}, neighbors = {"group:soil_sapling"}, - interval = 25, - chance = 2, - action = grow_spruce -}) -minetest.register_lbm({ - label = "Add growth for unloaded spruce tree", - name = "mcl_core:lbm_spruce", - nodenames = {"mcl_core:sprucesapling"}, - run_at_every_load = true, - action = grow_spruce + interval = 30, + chance = 3, + action = function(pos, node) + grow_spruce(pos, node, 1) + end }) -- Birch tree @@ -1060,16 +1018,11 @@ minetest.register_abm({ label = "Birch tree growth", nodenames = {"mcl_core:birchsapling"}, neighbors = {"group:soil_sapling"}, - interval = 25, - chance = 2, - action = grow_birch -}) -minetest.register_lbm({ - label = "Add growth for unloaded birch tree", - name = "mcl_core:lbm_birch", - nodenames = {"mcl_core:birchsapling"}, - run_at_every_load = true, - action = grow_birch + interval = 30, + chance = 3, + action = function(pos, node) + grow_birch(pos, node, 1) + end }) -- Acacia tree @@ -1077,18 +1030,37 @@ minetest.register_abm({ label = "Acacia tree growth", nodenames = {"mcl_core:acaciasapling"}, neighbors = {"group:soil_sapling"}, - interval = 20, - chance = 2, - action = grow_acacia + interval = 30, + chance = 3, + action = function(pos, node) + grow_acacia(pos, node, 1) + end }) + minetest.register_lbm({ - label = "Add growth for unloaded acacia tree", - name = "mcl_core:lbm_acacia", - nodenames = {"mcl_core:acaciasapling"}, + label = "Add growth for trees in unloaded blocks", + name = "mcl_core:tree_sapling_growth", + nodenames = { "group:sapling" }, + neighbors = {"group:soil_sapling"}, run_at_every_load = true, - action = grow_acacia + action = function(pos, node, dtime_s) + -- right now, all trees have 1/(30*3) chance + -- TODO: make this an API similar to farming + local interval, chance = 30, 3 + local rolls = floor(dtime_s / interval) + if rolls <= 0 then return end + -- simulate how often the block will be ticked + local stages = 0 + for i = 1,rolls do + if random(1, chance) == 1 then stages = stages + 1 end + end + if stages > 0 then + mcl_core.grow_sapling(pos, node, stages) + end + end, }) + local function leafdecay_particles(pos, node) minetest.add_particlespawner({ amount = random(10, 20),