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
 | 
					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`
 | 
					If `param2` of any registered node is ~= 0, the node will always be
 | 
				
			||||||
the node can be without decaying.
 | 
					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 function `default.after_place_leaves` can be set as
 | 
				
			||||||
the player places a node of that kind, you will want to set `param2 = 1` or so.
 | 
					`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`
 | 
					If the node is in the `leafdecay_drop` group then it will always be
 | 
				
			||||||
to set param2 to 1 if the player places the node (should not be used for nodes
 | 
					dropped as an item.
 | 
				
			||||||
that use param2 otherwise (e.g. facedir)).
 | 
					
 | 
				
			||||||
 | 
					`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
 | 
					Dyes
 | 
				
			||||||
----
 | 
					----
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -325,47 +325,64 @@ default.after_place_leaves = function(pos, placer, itemstack, pointed_thing)
 | 
				
			|||||||
	end
 | 
						end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- Leafdecay ABM
 | 
					-- Leafdecay
 | 
				
			||||||
 | 
					local function leafdecay_after_destruct(pos, oldnode, def)
 | 
				
			||||||
minetest.register_abm({
 | 
						for _, v in pairs(minetest.find_nodes_in_area(vector.subtract(pos, def.radius),
 | 
				
			||||||
	label = "Leaf decay",
 | 
								vector.add(pos, def.radius), def.leaves)) do
 | 
				
			||||||
	nodenames = {"group:leafdecay"},
 | 
							local node = minetest.get_node(v)
 | 
				
			||||||
	neighbors = {"air"},
 | 
							if node.param2 == 0 then
 | 
				
			||||||
	interval = 2,
 | 
								minetest.get_node_timer(v):start(math.random(20, 120) / 10)
 | 
				
			||||||
	chance = 10,
 | 
					 | 
				
			||||||
	catch_up = false,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	action = function(pos, node, _, _)
 | 
					 | 
				
			||||||
		-- Check if leaf is placed
 | 
					 | 
				
			||||||
		if node.param2 ~= 0 then
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		local rad = minetest.registered_nodes[node.name].groups.leafdecay
 | 
					local function leafdecay_on_timer(pos, def)
 | 
				
			||||||
		-- Assume ignore is a trunk, to make this
 | 
						if minetest.find_node_near(pos, def.radius, def.trunks) then
 | 
				
			||||||
		-- work at the border of a loaded area
 | 
							return false
 | 
				
			||||||
		if minetest.find_node_near(pos, rad, {"ignore", "group:tree"}) then
 | 
						end
 | 
				
			||||||
			return
 | 
					
 | 
				
			||||||
		end
 | 
						local node = minetest.get_node(pos)
 | 
				
			||||||
		-- Drop stuff
 | 
						local drops = minetest.get_node_drops(node.name)
 | 
				
			||||||
		local itemstacks = minetest.get_node_drops(node.name)
 | 
						for _, item in ipairs(drops) do
 | 
				
			||||||
		for _, itemname in ipairs(itemstacks) do
 | 
							local is_leaf
 | 
				
			||||||
			if itemname ~= node.name or
 | 
							for _, v in pairs(def.leaves) do
 | 
				
			||||||
					minetest.get_item_group(node.name, "leafdecay_drop") ~= 0 then
 | 
								if v == item then
 | 
				
			||||||
				local p_drop = {
 | 
									is_leaf = true
 | 
				
			||||||
					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)
 | 
					 | 
				
			||||||
			end
 | 
								end
 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
		-- Remove node
 | 
							if minetest.get_item_group(item, "leafdecay_drop") ~= 0 or
 | 
				
			||||||
		minetest.remove_node(pos)
 | 
									not is_leaf then
 | 
				
			||||||
		minetest.check_for_falling(pos)
 | 
								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
 | 
						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
 | 
					-- Convert dirt to something that fits the environment
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2072,3 +2072,57 @@ minetest.register_node("default:cloud", {
 | 
				
			|||||||
	sounds = default.node_sound_defaults(),
 | 
						sounds = default.node_sound_defaults(),
 | 
				
			||||||
	groups = {not_in_creative_inventory = 1},
 | 
						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