forked from luanti-org/minetest_game
		
	Leafdecay: Node timer based implementation, API
This implements a node-timer based leafdecay mechanism, and exposes
an API to use it in mods.
The API is documented in game_api.txt.
`default.register_leafdecay(leafdecaydef)`
`leafdecaydef` is a table, with following members:
{
	trunks = { "default:tree"}, -- nodes considered trunks
	leaves = { "default:leaves", "default:apple"}, -- nodes considered leaves
	radius = 3, -- activates leafdecay this far from the trunk
}
The algorithm will drop `leaves` items in the area if no `trunks` are found
in the `trunk_radius` sized area around the position of the leaf. If a node
listed in `leaves` has a group `leafdecay_drop > 0`, then the item is dropped,
otherwise the item is removed but not dropped.
The algorithm also implements a value `default.leafdecay_speed` (default
15) which can be modified to increase or decrease of the leaf decay. The
algorithm will vary the actual speed a bit to introduce randomness.
Leaf decay is randomized by 0.1 seconds to reduce the chance that
decay happens many times on the same second interval. This requires
nodetimer_interval to be set to values lower than 1.0 to have an
effect.
The leaves will decay between 2 and 10 seconds after digging the trunk,
and happen at non-integer second intervals.
-- The API was added by sofar.
			
			
This commit is contained in:
		
							
								
								
									
										36
									
								
								game_api.txt
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								game_api.txt
									
									
									
									
									
								
							@@ -658,20 +658,36 @@ default.player_get_animation(player)
 | 
			
		||||
Leafdecay
 | 
			
		||||
---------
 | 
			
		||||
 | 
			
		||||
To enable leaf decay for a node, add it to the `leafdecay` group.
 | 
			
		||||
To enable leaf decay for leaves when a tree is cut down by a player,
 | 
			
		||||
register the tree with the default.register_leafdecay(leafdecaydef)
 | 
			
		||||
function.
 | 
			
		||||
 | 
			
		||||
The rating of the group determines how far from a node in the group `tree`
 | 
			
		||||
the node can be without decaying.
 | 
			
		||||
If `param2` of any registered 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.
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
The function `default.after_place_leaves` can be set as
 | 
			
		||||
`after_place_node of a node` to set param2 to 1 if the player places
 | 
			
		||||
the node (should not be used for nodes that use param2 otherwise
 | 
			
		||||
(e.g. facedir)).
 | 
			
		||||
 | 
			
		||||
The function `default.after_place_leaves` can be set as `after_place_node of a node`
 | 
			
		||||
to set param2 to 1 if the player places the node (should not be used for nodes
 | 
			
		||||
that use param2 otherwise (e.g. facedir)).
 | 
			
		||||
If the node is in the `leafdecay_drop` group then it will always be
 | 
			
		||||
dropped as an item.
 | 
			
		||||
 | 
			
		||||
`default.register_leafdecay(leafdecaydef)`
 | 
			
		||||
 | 
			
		||||
`leafdecaydef` is a table, with following members:
 | 
			
		||||
	{
 | 
			
		||||
		trunks = {"default:tree"}, -- nodes considered trunks
 | 
			
		||||
		leaves = {"default:leaves", "default:apple"},
 | 
			
		||||
			-- nodes considered for removal
 | 
			
		||||
		radius = 3, -- radius to consider for searching
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
Note: all the listed nodes in `trunks` have their `on_after_destruct`
 | 
			
		||||
callback overridden. All the nodes listed in `leaves` have their
 | 
			
		||||
`on_timer` callback overridden.
 | 
			
		||||
 | 
			
		||||
If the node is in the `leafdecay_drop` group then it will always be dropped as an
 | 
			
		||||
item.
 | 
			
		||||
 | 
			
		||||
Dyes
 | 
			
		||||
----
 | 
			
		||||
 
 | 
			
		||||
@@ -325,47 +325,64 @@ default.after_place_leaves = function(pos, placer, itemstack, pointed_thing)
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Leafdecay ABM
 | 
			
		||||
 | 
			
		||||
minetest.register_abm({
 | 
			
		||||
	label = "Leaf decay",
 | 
			
		||||
	nodenames = {"group:leafdecay"},
 | 
			
		||||
	neighbors = {"air"},
 | 
			
		||||
	interval = 2,
 | 
			
		||||
	chance = 10,
 | 
			
		||||
	catch_up = false,
 | 
			
		||||
 | 
			
		||||
	action = function(pos, node, _, _)
 | 
			
		||||
		-- Check if leaf is placed
 | 
			
		||||
		if node.param2 ~= 0 then
 | 
			
		||||
			return
 | 
			
		||||
-- 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)
 | 
			
		||||
		if node.param2 == 0 then
 | 
			
		||||
			minetest.get_node_timer(v):start(math.random(20, 120) / 10)
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
		local rad = minetest.registered_nodes[node.name].groups.leafdecay
 | 
			
		||||
		-- Assume ignore is a trunk, to make this
 | 
			
		||||
		-- work at the border of a loaded area
 | 
			
		||||
		if minetest.find_node_near(pos, rad, {"ignore", "group:tree"}) then
 | 
			
		||||
			return
 | 
			
		||||
		end
 | 
			
		||||
		-- Drop stuff
 | 
			
		||||
		local itemstacks = minetest.get_node_drops(node.name)
 | 
			
		||||
		for _, itemname in ipairs(itemstacks) do
 | 
			
		||||
			if itemname ~= node.name or
 | 
			
		||||
					minetest.get_item_group(node.name, "leafdecay_drop") ~= 0 then
 | 
			
		||||
				local p_drop = {
 | 
			
		||||
					x = pos.x - 0.5 + math.random(),
 | 
			
		||||
					y = pos.y - 0.5 + math.random(),
 | 
			
		||||
					z = pos.z - 0.5 + math.random(),
 | 
			
		||||
				}
 | 
			
		||||
				minetest.add_item(p_drop, itemname)
 | 
			
		||||
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
 | 
			
		||||
		-- Remove node
 | 
			
		||||
		minetest.remove_node(pos)
 | 
			
		||||
		minetest.check_for_falling(pos)
 | 
			
		||||
		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(def)
 | 
			
		||||
	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
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- Convert dirt to something that fits the environment
 | 
			
		||||
 
 | 
			
		||||
@@ -2072,3 +2072,57 @@ minetest.register_node("default:cloud", {
 | 
			
		||||
	sounds = default.node_sound_defaults(),
 | 
			
		||||
	groups = {not_in_creative_inventory = 1},
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- register trees for leafdecay
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
if minetest.get_mapgen_setting("mg_name") == "v6" then
 | 
			
		||||
	default.register_leafdecay({
 | 
			
		||||
		trunks = {"default:tree"},
 | 
			
		||||
		leaves = {"default:apple", "default:leaves"},
 | 
			
		||||
		radius = 2,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	default.register_leafdecay({
 | 
			
		||||
		trunks = {"default:jungletree"},
 | 
			
		||||
		leaves = {"default:jungleleaves"},
 | 
			
		||||
		radius = 3,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	default.register_leafdecay({
 | 
			
		||||
		trunks = {"default:pine_tree"},
 | 
			
		||||
		leaves = {"default:pine_needles"},
 | 
			
		||||
		radius = 3,
 | 
			
		||||
	})
 | 
			
		||||
else
 | 
			
		||||
	default.register_leafdecay({
 | 
			
		||||
		trunks = {"default:tree"},
 | 
			
		||||
		leaves = {"default:apple", "default:leaves"},
 | 
			
		||||
		radius = 3,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	default.register_leafdecay({
 | 
			
		||||
		trunks = {"default:jungletree"},
 | 
			
		||||
		leaves = {"default:jungleleaves"},
 | 
			
		||||
		radius = 2,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	default.register_leafdecay({
 | 
			
		||||
		trunks = {"default:pine_tree"},
 | 
			
		||||
		leaves = {"default:pine_needles"},
 | 
			
		||||
		radius = 2,
 | 
			
		||||
	})
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
default.register_leafdecay({
 | 
			
		||||
	trunks = {"default:acacia_tree"},
 | 
			
		||||
	leaves = {"default:acacia_leaves"},
 | 
			
		||||
	radius = 2,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
default.register_leafdecay({
 | 
			
		||||
	trunks = {"default:aspen_tree"},
 | 
			
		||||
	leaves = {"default:aspen_leaves"},
 | 
			
		||||
	radius = 3,
 | 
			
		||||
})
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user