mirror of
https://git.minetest.land/MineClone2/MineClone2.git
synced 2024-12-25 02:42:25 +01:00
Merge pull request 'Refactor leaf decay mechanics.' (#3099) from refactor-leaves into master
Reviewed-on: https://git.minetest.land/MineClone2/MineClone2/pulls/3099 Reviewed-by: ancientmarinerdev <ancientmariner_dev@proton.me>
This commit is contained in:
commit
1859f44bd6
@ -74,6 +74,8 @@ Please read <http://minecraft.gamepedia.com/Breaking> to learn how digging times
|
||||
* `coral_species=X`: Specifies the species of a coral; equal X means equal species
|
||||
* `set_on_fire=X`: Sets any (not fire-resistant) mob or player on fire for X seconds when touching
|
||||
* `compostability=X`: Item can be used on a composter block; X (1-100) is the % chance of adding a level of compost
|
||||
* `leaves=X`: Node will spotaneously decay if no tree trunk nodes remain within 6 blocks distance.
|
||||
* `leaves_orphan`: See above, these nodes are in the process of decayed.
|
||||
|
||||
#### Footnotes
|
||||
|
||||
|
@ -1367,108 +1367,46 @@ function mcl_core.supports_vines(nodename)
|
||||
end
|
||||
|
||||
-- Leaf Decay
|
||||
|
||||
-- To enable leaf decay for a node, add it to the "leafdecay" group.
|
||||
--
|
||||
-- The rating of the group determines how far from a node in the group "tree"
|
||||
-- the node can be without decaying.
|
||||
-- Whenever a tree trunk node is removed, all `group:leaves` nodes in a radius
|
||||
-- of 6 blocks are checked from the trunk node's `after_destruct` handler.
|
||||
-- Any such nodes within that radius that has no trunk node present within a
|
||||
-- distance of 6 blocks is replaced with a `group:orphan_leaves` node.
|
||||
--
|
||||
-- If param2 of the node is ~= 0, the node will always be preserved. Thus, if
|
||||
-- the player places a node of that kind, you will want to set param2=1 or so.
|
||||
--
|
||||
|
||||
mcl_core.leafdecay_trunk_cache = {}
|
||||
mcl_core.leafdecay_enable_cache = true
|
||||
-- Spread the load of finding trunks
|
||||
mcl_core.leafdecay_trunk_find_allow_accumulator = 0
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
--local finds_per_second = 5000
|
||||
mcl_core.leafdecay_trunk_find_allow_accumulator = math.floor(dtime * 5000)
|
||||
end)
|
||||
|
||||
-- The `group:orphan_leaves` nodes are gradually decayed in this ABM.
|
||||
minetest.register_abm({
|
||||
label = "Leaf decay",
|
||||
nodenames = {"group:leafdecay"},
|
||||
neighbors = {"air", "group:liquid"},
|
||||
-- A low interval and a high inverse chance spreads the load
|
||||
interval = 2,
|
||||
chance = 5,
|
||||
nodenames = {"group:orphan_leaves"},
|
||||
interval = 5,
|
||||
chance = 10,
|
||||
action = function(pos, node)
|
||||
-- Spawn item entities for any of the leaf's drops
|
||||
local itemstacks = minetest.get_node_drops(node.name)
|
||||
for _, itemname in pairs(itemstacks) do
|
||||
local p_drop = vector.offset(pos, math.random() - 0.5, math.random() - 0.5, math.random() - 0.5)
|
||||
minetest.add_item(p_drop, itemname)
|
||||
end
|
||||
-- Remove the decayed node
|
||||
minetest.remove_node(pos)
|
||||
leafdecay_particles(pos, node)
|
||||
minetest.check_for_falling(pos)
|
||||
|
||||
action = function(p0, node, _, _)
|
||||
local do_preserve = false
|
||||
local d = minetest.registered_nodes[node.name].groups.leafdecay
|
||||
if not d or d == 0 then
|
||||
return
|
||||
end
|
||||
local n0 = minetest.get_node(p0)
|
||||
if n0.param2 ~= 0 then
|
||||
-- Prevent leafdecay for player-placed leaves.
|
||||
-- param2 is set to 1 after it was placed by the player
|
||||
return
|
||||
end
|
||||
local p0_hash = nil
|
||||
if mcl_core.leafdecay_enable_cache then
|
||||
p0_hash = minetest.hash_node_position(p0)
|
||||
local trunkp = mcl_core.leafdecay_trunk_cache[p0_hash]
|
||||
if trunkp then
|
||||
local n = minetest.get_node(trunkp)
|
||||
local reg = minetest.registered_nodes[n.name]
|
||||
-- Assume ignore is a trunk, to make the thing work at the border of the active area
|
||||
if n.name == "ignore" or (reg and reg.groups.tree and reg.groups.tree ~= 0) then
|
||||
return
|
||||
end
|
||||
-- Cache is invalid
|
||||
table.remove(mcl_core.leafdecay_trunk_cache, p0_hash)
|
||||
end
|
||||
end
|
||||
if mcl_core.leafdecay_trunk_find_allow_accumulator <= 0 then
|
||||
return
|
||||
end
|
||||
mcl_core.leafdecay_trunk_find_allow_accumulator =
|
||||
mcl_core.leafdecay_trunk_find_allow_accumulator - 1
|
||||
-- Assume ignore is a trunk, to make the thing work at the border of the active area
|
||||
local p1 = minetest.find_node_near(p0, d, {"ignore", "group:tree"})
|
||||
if p1 then
|
||||
do_preserve = true
|
||||
if mcl_core.leafdecay_enable_cache then
|
||||
-- Cache the trunk
|
||||
mcl_core.leafdecay_trunk_cache[p0_hash] = p1
|
||||
end
|
||||
end
|
||||
if not do_preserve then
|
||||
-- Drop stuff other than the node itself
|
||||
local itemstacks = minetest.get_node_drops(n0.name)
|
||||
for _, itemname in pairs(itemstacks) do
|
||||
local p_drop = {
|
||||
x = p0.x - 0.5 + math.random(),
|
||||
y = p0.y - 0.5 + math.random(),
|
||||
z = p0.z - 0.5 + math.random(),
|
||||
}
|
||||
minetest.add_item(p_drop, itemname)
|
||||
end
|
||||
-- Remove node
|
||||
minetest.remove_node(p0)
|
||||
leafdecay_particles(p0, n0)
|
||||
minetest.check_for_falling(p0)
|
||||
|
||||
-- Kill depending vines immediately to skip the vines decay delay
|
||||
local surround = {
|
||||
{ x = 0, y = 0, z = -1 },
|
||||
{ x = 0, y = 0, z = 1 },
|
||||
{ x = -1, y = 0, z = 0 },
|
||||
{ x = 1, y = 0, z = 0 },
|
||||
{ x = 0, y = -1, z = -1 },
|
||||
}
|
||||
for s=1, #surround do
|
||||
local spos = vector.add(p0, surround[s])
|
||||
local maybe_vine = minetest.get_node(spos)
|
||||
--local surround_inverse = vector.multiply(surround[s], -1)
|
||||
if maybe_vine.name == "mcl_core:vine" and (not mcl_core.check_vines_supported(spos, maybe_vine)) then
|
||||
minetest.remove_node(spos)
|
||||
vinedecay_particles(spos, maybe_vine)
|
||||
minetest.check_for_falling(spos)
|
||||
end
|
||||
-- Kill depending vines immediately to skip the vines decay delay
|
||||
local surround = {
|
||||
{ x = 0, y = 0, z = -1 },
|
||||
{ x = 0, y = 0, z = 1 },
|
||||
{ x = -1, y = 0, z = 0 },
|
||||
{ x = 1, y = 0, z = 0 },
|
||||
{ x = 0, y = -1, z = -1 },
|
||||
}
|
||||
for s=1, #surround do
|
||||
local spos = vector.add(pos, surround[s])
|
||||
local maybe_vine = minetest.get_node(spos)
|
||||
--local surround_inverse = vector.multiply(surround[s], -1)
|
||||
if maybe_vine.name == "mcl_core:vine" and (not mcl_core.check_vines_supported(spos, maybe_vine)) then
|
||||
minetest.remove_node(spos)
|
||||
vinedecay_particles(spos, maybe_vine)
|
||||
minetest.check_for_falling(spos)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -8,6 +8,40 @@ if mod_screwdriver then
|
||||
on_rotate = screwdriver.rotate_3way
|
||||
end
|
||||
|
||||
-- Check dug/destroyed tree trunks for orphaned leaves.
|
||||
--
|
||||
-- This function is meant to be called by the `after_destruct` handler of
|
||||
-- treetrunk nodes.
|
||||
--
|
||||
-- Whenever a trunk node is removed, all `group:leaves` nodes in a sphere
|
||||
-- with radius 6 are checked. Every such node that does not have a trunk
|
||||
-- node within a distance of 6 blocks is converted into a orphan leaf node.
|
||||
-- An ABM will gradually decay these nodes.
|
||||
--
|
||||
-- If param2 of the node is set to a nonzero value, the node will always
|
||||
-- be preserved. This is set automatically when leaves are placed manually.
|
||||
--
|
||||
-- @param pos the position of the removed trunk node.
|
||||
-- @param oldnode the node table of the removed trunk node.
|
||||
function mcl_core.update_leaves(pos, oldnode)
|
||||
local pos1, pos2 = vector.offset(pos, -6, -6, -6), vector.offset(pos, 6, 6, 6)
|
||||
local lnode
|
||||
local leaves = minetest.find_nodes_in_area(pos1, pos2, "group:leaves")
|
||||
for _, lpos in pairs(leaves) do
|
||||
lnode = minetest.get_node(lpos)
|
||||
-- skip already decaying leaf nodes
|
||||
if minetest.get_item_group(lnode.name, "orphan_leaves") ~= 1 then
|
||||
if not minetest.find_node_near(lpos, 6, "group:tree") then
|
||||
-- manually placed leaf nodes have param2
|
||||
-- set and will never decay automatically
|
||||
if lnode.param2 == 0 then
|
||||
minetest.swap_node(lpos, {name = lnode.name .. "_orphan"})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Register tree trunk (wood) and bark
|
||||
local function register_tree_trunk(subname, description_trunk, description_bark, longdesc, tile_inner, tile_bark, stripped_variant)
|
||||
minetest.register_node("mcl_core:"..subname, {
|
||||
@ -17,6 +51,7 @@ local function register_tree_trunk(subname, description_trunk, description_bark,
|
||||
tiles = {tile_inner, tile_inner, tile_bark},
|
||||
paramtype2 = "facedir",
|
||||
on_place = mcl_util.rotate_axis,
|
||||
after_destruct = mcl_core.update_leaves,
|
||||
stack_max = 64,
|
||||
groups = {handy=1,axey=1, tree=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5},
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
@ -107,10 +142,7 @@ local function register_wooden_planks(subname, description, tiles)
|
||||
})
|
||||
end
|
||||
|
||||
local function register_leaves(subname, description, longdesc, tiles, sapling, drop_apples, sapling_chances, leafdecay_distance)
|
||||
if leafdecay_distance == nil then
|
||||
leafdecay_distance = 4
|
||||
end
|
||||
local function register_leaves(subname, description, longdesc, tiles, sapling, drop_apples, sapling_chances)
|
||||
local apple_chances = {200, 180, 160, 120, 40}
|
||||
local stick_chances = {50, 45, 30, 35, 10}
|
||||
|
||||
@ -141,7 +173,7 @@ local function register_leaves(subname, description, longdesc, tiles, sapling, d
|
||||
return drop
|
||||
end
|
||||
|
||||
minetest.register_node("mcl_core:"..subname, {
|
||||
local l_def = {
|
||||
description = description,
|
||||
_doc_items_longdesc = longdesc,
|
||||
_doc_items_hidden = false,
|
||||
@ -153,9 +185,8 @@ local function register_leaves(subname, description, longdesc, tiles, sapling, d
|
||||
stack_max = 64,
|
||||
groups = {
|
||||
handy = 1, hoey = 1, shearsy = 1, swordy = 1, dig_by_piston = 1,
|
||||
leaves = 1, leafdecay = leafdecay_distance, deco_block = 1,
|
||||
flammable = 2, fire_encouragement = 30, fire_flammability = 60,
|
||||
compostability = 30
|
||||
leaves = 1, deco_block = 1, compostability = 30
|
||||
},
|
||||
drop = get_drops(0),
|
||||
_mcl_shears_drop = true,
|
||||
@ -164,7 +195,19 @@ local function register_leaves(subname, description, longdesc, tiles, sapling, d
|
||||
_mcl_hardness = 0.2,
|
||||
_mcl_silk_touch_drop = true,
|
||||
_mcl_fortune_drop = { get_drops(1), get_drops(2), get_drops(3), get_drops(4) },
|
||||
})
|
||||
}
|
||||
|
||||
minetest.register_node("mcl_core:" .. subname, l_def)
|
||||
|
||||
local o_def = table.copy(l_def)
|
||||
o_def._doc_items_create_entry = false
|
||||
o_def.place_param2 = nil
|
||||
o_def.groups.not_in_creative_inventory = 1
|
||||
o_def.groups.orphan_leaves = 1
|
||||
o_def._mcl_shears_drop = {"mcl_core:" .. subname}
|
||||
o_def._mcl_silk_touch_drop = {"mcl_core:" .. subname}
|
||||
|
||||
minetest.register_node("mcl_core:" .. subname .. "_orphan", o_def)
|
||||
end
|
||||
|
||||
local function register_sapling(subname, description, longdesc, tt_help, texture, selbox)
|
||||
|
@ -52,9 +52,9 @@ minetest.register_node("mcl_mangrove:mangrove_tree", {
|
||||
tiles = {"mcl_mangrove_log_top.png", "mcl_mangrove_log_top.png", "mcl_mangrove_log.png"},
|
||||
paramtype2 = "facedir",
|
||||
on_place = mcl_util.rotate_axis,
|
||||
after_destruct = mcl_core.update_leaves,
|
||||
groups = {handy=1,axey=1, tree=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5},
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
on_place = mcl_util.rotate_axis,
|
||||
_mcl_blast_resistance = 2,
|
||||
_mcl_hardness = 2,
|
||||
_mcl_stripped_variant = "mcl_mangrove:mangrove_stripped_trunk",
|
||||
@ -86,7 +86,7 @@ minetest.register_node("mcl_mangrove:mangrove_wood", {
|
||||
_mcl_hardness = 2,
|
||||
})
|
||||
|
||||
minetest.register_node("mcl_mangrove:mangroveleaves", {
|
||||
local l_def = {
|
||||
description = S("Mangrove Leaves"),
|
||||
_doc_items_longdesc = S("mangrove leaves are grown from mangrove trees."),
|
||||
_doc_items_hidden = false,
|
||||
@ -95,7 +95,11 @@ minetest.register_node("mcl_mangrove:mangroveleaves", {
|
||||
place_param2 = 1, -- Prevent leafdecay for placed nodes
|
||||
tiles = {"mcl_mangrove_leaves.png"},
|
||||
paramtype = "light",
|
||||
groups = {handy=1,shearsy=1,swordy=1, leafdecay=10, flammable=2, leaves=1, deco_block=1, dig_by_piston=1, fire_encouragement=30, fire_flammability=60},
|
||||
groups = {
|
||||
handy = 1, hoey = 1, shearsy = 1, swordy = 1, dig_by_piston = 1,
|
||||
flammable = 2, fire_encouragement = 30, fire_flammability = 60,
|
||||
leaves = 1, deco_block = 1, compostability = 30
|
||||
},
|
||||
drop = get_drops(0),
|
||||
_mcl_shears_drop = true,
|
||||
sounds = mcl_sounds.node_sound_leaves_defaults(),
|
||||
@ -103,7 +107,19 @@ minetest.register_node("mcl_mangrove:mangroveleaves", {
|
||||
_mcl_hardness = 0.2,
|
||||
_mcl_silk_touch_drop = true,
|
||||
_mcl_fortune_drop = { get_drops(1), get_drops(2), get_drops(3), get_drops(4) },
|
||||
})
|
||||
}
|
||||
|
||||
minetest.register_node("mcl_mangrove:mangroveleaves", l_def)
|
||||
|
||||
local o_def = table.copy(l_def)
|
||||
o_def._doc_items_create_entry = false
|
||||
o_def.place_param2 = nil
|
||||
o_def.groups.not_in_creative_inventory = 1
|
||||
o_def.groups.orphan_leaves = 1
|
||||
o_def._mcl_shears_drop = {"mcl_mangrove:mangroveleaves"}
|
||||
o_def._mcl_silk_touch_drop = {"mcl_mangrove:mangroveleaves"}
|
||||
|
||||
minetest.register_node("mcl_mangrove:mangroveleaves_orphan", o_def)
|
||||
|
||||
minetest.register_node("mcl_mangrove:mangrove_stripped_trunk", {
|
||||
description = S("Stripped Mangrove Wood"),
|
||||
@ -147,11 +163,13 @@ minetest.register_node("mcl_mangrove:mangrove_roots", {
|
||||
drawtype = "allfaces_optional",
|
||||
groups = {
|
||||
handy = 1, hoey = 1, shearsy = 1, axey = 1, swordy = 1, dig_by_piston = 0,
|
||||
leaves = 1, deco_block = 1,flammable = 10, fire_encouragement = 30, fire_flammability = 60, compostability = 30
|
||||
flammable = 10, fire_encouragement = 30, fire_flammability = 60,
|
||||
deco_block = 1, compostability = 30
|
||||
},
|
||||
drop = "mcl_mangrove:mangrove_roots",
|
||||
_mcl_shears_drop = true,
|
||||
sounds = mcl_sounds.node_sound_leaves_defaults(), _mcl_blast_resistance = 0.7,
|
||||
sounds = mcl_sounds.node_sound_leaves_defaults(),
|
||||
_mcl_blast_resistance = 0.7,
|
||||
_mcl_hardness = 0.7,
|
||||
_mcl_silk_touch_drop = true,
|
||||
_mcl_fortune_drop = { "mcl_mangrove:mangrove_roots 1", "mcl_mangrove:mangrove_roots 2", "mcl_mangrove:mangrove_roots 3", "mcl_mangrove:mangrove_roots 4" },
|
||||
@ -329,6 +347,9 @@ local wlroots = {
|
||||
end,
|
||||
}
|
||||
local rwlroots = table.copy(wlroots)
|
||||
-- FIXME luacheck complains that this is a repeated definition of water_tex.
|
||||
-- Maybe the tiles definition below should be replaced with the animated tile
|
||||
-- definition as per above?
|
||||
water_tex = "default_river_water_source_animated.png^[verticalframe:16:0"
|
||||
rwlroots.tiles = {
|
||||
"("..water_tex..")^mcl_mangrove_roots_top.png",
|
||||
|
Loading…
Reference in New Issue
Block a user