mirror of
				https://github.com/mt-mods/plantlife_modpack.git
				synced 2025-11-04 07:25:30 +01:00 
			
		
		
		
	split plants_lib off into its own repository
renamed it to biome_lib changed all relevant functions, tables, depends.txt, etc. in this modpack to call for the new name.
This commit is contained in:
		
							
								
								
									
										2
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								README
									
									
									
									
									
								
							@@ -22,7 +22,7 @@ that is necessary for them to spawn on, so they won't grow if placed on e.g.
 | 
			
		||||
cobble or homedecor flower pot, etc.  This doesn't affect wall-climbing poison
 | 
			
		||||
ivy, since it uses a different growth pattern.
 | 
			
		||||
 | 
			
		||||
All plants use multiple controls provided by plants_lib, to keep where they
 | 
			
		||||
All plants use multiple controls provided by biome_lib, to keep where they
 | 
			
		||||
grow under control - no more random spread of plants!  In addition, the density
 | 
			
		||||
of the plants in any region they appear in has been fixed and brought under
 | 
			
		||||
control.
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,3 @@
 | 
			
		||||
default
 | 
			
		||||
plants_lib
 | 
			
		||||
biome_lib
 | 
			
		||||
flowers_plus?
 | 
			
		||||
@@ -1,2 +1,2 @@
 | 
			
		||||
default
 | 
			
		||||
plants_lib
 | 
			
		||||
biome_lib
 | 
			
		||||
@@ -194,7 +194,7 @@ abstract_bushes.grow_bush_node = function(pos,dir, leaf_type)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {
 | 
			
		||||
		"default:dirt_with_grass", 
 | 
			
		||||
		"stoneage:grass_with_silex",
 | 
			
		||||
@@ -239,7 +239,7 @@ abstract_bushes.grow_youngtree_node2 = function(pos, height)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {
 | 
			
		||||
		"default:dirt_with_grass", 
 | 
			
		||||
		"stoneage:grass_with_silex",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
local S = plantslib.intllib
 | 
			
		||||
local S = biome_lib.intllib
 | 
			
		||||
 | 
			
		||||
-- Basket
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,3 @@
 | 
			
		||||
plants_lib
 | 
			
		||||
biome_lib
 | 
			
		||||
farming?
 | 
			
		||||
farming_plus?
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
--
 | 
			
		||||
-- License:  WTFPL
 | 
			
		||||
 | 
			
		||||
local S = plantslib.intllib
 | 
			
		||||
local S = biome_lib.intllib
 | 
			
		||||
 | 
			
		||||
bushes_classic = {}
 | 
			
		||||
 | 
			
		||||
@@ -30,7 +30,7 @@ bushes_classic.spawn_list = {}
 | 
			
		||||
dofile(minetest.get_modpath('bushes_classic') .. '/cooking.lua')
 | 
			
		||||
dofile(minetest.get_modpath('bushes_classic') .. '/nodes.lua')
 | 
			
		||||
 | 
			
		||||
plantslib:spawn_on_surfaces({
 | 
			
		||||
biome_lib:spawn_on_surfaces({
 | 
			
		||||
	spawn_delay = 3600,
 | 
			
		||||
	spawn_plants = bushes_classic.spawn_list,
 | 
			
		||||
	avoid_radius = 10,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
local S = plantslib.intllib
 | 
			
		||||
local S = biome_lib.intllib
 | 
			
		||||
 | 
			
		||||
plantlife_bushes = {}
 | 
			
		||||
 | 
			
		||||
@@ -118,7 +118,7 @@ plantlife_bushes.after_place_node = function(pos, placer, itemstack)
 | 
			
		||||
	meta:set_string("bush_type", name_parts[1])
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- regrow berries (uses a base abm instead of plants_lib because of the use of metadata).
 | 
			
		||||
-- regrow berries (uses a base abm instead of biome_lib because of the use of metadata).
 | 
			
		||||
 | 
			
		||||
minetest.register_abm({
 | 
			
		||||
	nodenames = {"bushes:fruitless_bush"},
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,3 @@
 | 
			
		||||
default
 | 
			
		||||
plants_lib
 | 
			
		||||
biome_lib
 | 
			
		||||
farming?
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@ local mname		= "dryplants"
 | 
			
		||||
-- License (everything): 	WTFPL
 | 
			
		||||
-- Contains code from: 		default, farming 
 | 
			
		||||
-- Looked at code from:		darkage, sickle, stairs
 | 
			
		||||
-- Dependencies: 			default, farming, plants_lib
 | 
			
		||||
-- Dependencies: 			default, farming, biome_lib
 | 
			
		||||
-- Supports:				
 | 
			
		||||
-----------------------------------------------------------------------------------------------
 | 
			
		||||
abstract_dryplants = {}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
-- textures & ideas partly by Neuromancer
 | 
			
		||||
 | 
			
		||||
-- License (everything): 	WTFPL
 | 
			
		||||
-- Contains code from: 		plants_lib
 | 
			
		||||
-- Contains code from: 		biome_lib
 | 
			
		||||
-- Looked at code from:		default			
 | 
			
		||||
-----------------------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
@@ -84,7 +84,7 @@ minetest.register_node("dryplants:juncus_02", {
 | 
			
		||||
-- GENERATE SMALL JUNCUS
 | 
			
		||||
-----------------------------------------------------------------------------------------------
 | 
			
		||||
-- near water or swamp
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {
 | 
			
		||||
		"default:dirt_with_grass", 
 | 
			
		||||
		--"default:desert_sand",
 | 
			
		||||
@@ -105,7 +105,7 @@ plantslib:register_generate_plant({
 | 
			
		||||
  abstract_dryplants.grow_juncus
 | 
			
		||||
)
 | 
			
		||||
-- at dunes/beach
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {
 | 
			
		||||
		--"default:dirt_with_grass", 
 | 
			
		||||
		--"default:desert_sand",
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
-- by Mossmanikin
 | 
			
		||||
 | 
			
		||||
-- License (everything): 	WTFPL
 | 
			
		||||
-- Contains code from: 		plants_lib
 | 
			
		||||
-- Contains code from: 		biome_lib
 | 
			
		||||
-- Looked at code from:		default				
 | 
			
		||||
-----------------------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
@@ -13,7 +13,7 @@ abstract_dryplants.grow_grass_variation = function(pos)
 | 
			
		||||
	minetest.set_node(right_here, {name="dryplants:grass_short"})
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {
 | 
			
		||||
		"default:dirt_with_grass",
 | 
			
		||||
	},
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
-- by Mossmanikin
 | 
			
		||||
 | 
			
		||||
-- License (everything): 	WTFPL
 | 
			
		||||
-- Contains code from: 		plants_lib
 | 
			
		||||
-- Contains code from: 		biome_lib
 | 
			
		||||
-- Looked at code from:		default				
 | 
			
		||||
-----------------------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
@@ -17,7 +17,7 @@ abstract_dryplants.grow_grass = function(pos)
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {
 | 
			
		||||
		"default:dirt_with_grass",
 | 
			
		||||
		"stoneage:grass_with_silex",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
-- textures & ideas partly by Neuromancer
 | 
			
		||||
 | 
			
		||||
-- License (everything): 	WTFPL
 | 
			
		||||
-- Contains code from: 		plants_lib
 | 
			
		||||
-- Contains code from: 		biome_lib
 | 
			
		||||
-- Looked at code from:		default, trees				
 | 
			
		||||
-----------------------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
@@ -325,7 +325,7 @@ minetest.register_entity("dryplants:reedmace_water_entity",{
 | 
			
		||||
-----------------------------------------------------------------------------------------------
 | 
			
		||||
-- SPAWN REEDMACE
 | 
			
		||||
-----------------------------------------------------------------------------------------------
 | 
			
		||||
--[[plantslib:spawn_on_surfaces({
 | 
			
		||||
--[[biome_lib:spawn_on_surfaces({
 | 
			
		||||
	spawn_delay = 1200,
 | 
			
		||||
	spawn_plants = {"dryplants:reedmace_sapling"},
 | 
			
		||||
	spawn_chance = 400,
 | 
			
		||||
@@ -346,7 +346,7 @@ minetest.register_entity("dryplants:reedmace_water_entity",{
 | 
			
		||||
-- GENERATE REEDMACE
 | 
			
		||||
-----------------------------------------------------------------------------------------------
 | 
			
		||||
-- near water or swamp
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {
 | 
			
		||||
		"default:dirt_with_grass", 
 | 
			
		||||
		"default:desert_sand",
 | 
			
		||||
@@ -367,7 +367,7 @@ plantslib:register_generate_plant({
 | 
			
		||||
  abstract_dryplants.grow_reedmace
 | 
			
		||||
)
 | 
			
		||||
-- in water
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {
 | 
			
		||||
		"default:dirt",
 | 
			
		||||
		"default:dirt_with_grass", 
 | 
			
		||||
@@ -390,7 +390,7 @@ plantslib:register_generate_plant({
 | 
			
		||||
  abstract_dryplants.grow_reedmace_water
 | 
			
		||||
)
 | 
			
		||||
-- for oases & tropical beaches & tropical swamps
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {
 | 
			
		||||
		"default:sand",
 | 
			
		||||
		"sumpf:sumpf"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,2 +1,2 @@
 | 
			
		||||
default
 | 
			
		||||
plants_lib
 | 
			
		||||
biome_lib
 | 
			
		||||
@@ -3,9 +3,9 @@
 | 
			
		||||
-----------------------------------------------------------------------------------------------
 | 
			
		||||
-- by Mossmanikin
 | 
			
		||||
-- License (everything): 	WTFPL
 | 
			
		||||
-- Contains code from: 		plants_lib
 | 
			
		||||
-- Contains code from: 		biome_lib
 | 
			
		||||
-- Looked at code from:		default, flowers, painting, trees
 | 
			
		||||
-- Dependencies: 			plants_lib
 | 
			
		||||
-- Dependencies: 			biome_lib
 | 
			
		||||
-- Supports:				dryplants, stoneage, sumpf		
 | 
			
		||||
-----------------------------------------------------------------------------------------------
 | 
			
		||||
-- some inspiration from here
 | 
			
		||||
@@ -71,7 +71,7 @@ create_nodes()
 | 
			
		||||
-----------------------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
if abstract_ferns.config.lady_ferns_near_tree == true then
 | 
			
		||||
	plantslib:register_generate_plant({ -- near trees (woodlands)
 | 
			
		||||
	biome_lib:register_generate_plant({ -- near trees (woodlands)
 | 
			
		||||
		surface = {
 | 
			
		||||
			"default:dirt_with_grass",
 | 
			
		||||
			"default:mossycobble",
 | 
			
		||||
@@ -100,7 +100,7 @@ if abstract_ferns.config.lady_ferns_near_tree == true then
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
if abstract_ferns.config.lady_ferns_near_rock == true then
 | 
			
		||||
	plantslib:register_generate_plant({ -- near stone (mountains)
 | 
			
		||||
	biome_lib:register_generate_plant({ -- near stone (mountains)
 | 
			
		||||
		surface = {
 | 
			
		||||
			"default:dirt_with_grass",
 | 
			
		||||
			"default:mossycobble",
 | 
			
		||||
@@ -127,7 +127,7 @@ if abstract_ferns.config.lady_ferns_near_rock == true then
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
if abstract_ferns.config.lady_ferns_near_ores == true then -- this one causes a huge fps drop
 | 
			
		||||
	plantslib:register_generate_plant({ -- near ores (potential mining sites)
 | 
			
		||||
	biome_lib:register_generate_plant({ -- near ores (potential mining sites)
 | 
			
		||||
		surface = {
 | 
			
		||||
			"default:dirt_with_grass",
 | 
			
		||||
			"default:mossycobble",
 | 
			
		||||
@@ -165,7 +165,7 @@ if abstract_ferns.config.lady_ferns_near_ores == true then -- this one causes a
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
if abstract_ferns.config.lady_ferns_in_groups == true then -- this one is meant as a replacement of Ferns_near_Ores
 | 
			
		||||
	plantslib:register_generate_plant({
 | 
			
		||||
	biome_lib:register_generate_plant({
 | 
			
		||||
		surface = {
 | 
			
		||||
			"default:dirt_with_grass",
 | 
			
		||||
			"default:mossycobble",
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
-----------------------------------------------------------------------------------------------
 | 
			
		||||
-- by Mossmanikin
 | 
			
		||||
-- License (everything): 	WTFPL
 | 
			
		||||
-- Contains code from: 		plants_lib
 | 
			
		||||
-- Contains code from: 		biome_lib
 | 
			
		||||
-- Looked at code from:		4seasons, default
 | 
			
		||||
-- Supports:				vines			
 | 
			
		||||
-----------------------------------------------------------------------------------------------
 | 
			
		||||
@@ -285,7 +285,7 @@ minetest.register_abm({
 | 
			
		||||
 | 
			
		||||
-- in jungles
 | 
			
		||||
if abstract_ferns.config.enable_giant_treeferns_in_jungle == true then
 | 
			
		||||
	plantslib:register_generate_plant({
 | 
			
		||||
	biome_lib:register_generate_plant({
 | 
			
		||||
		surface = {
 | 
			
		||||
			"default:dirt_with_grass",
 | 
			
		||||
			"default:sand",
 | 
			
		||||
@@ -310,7 +310,7 @@ end
 | 
			
		||||
 | 
			
		||||
-- for oases & tropical beaches
 | 
			
		||||
if abstract_ferns.config.enable_giant_treeferns_in_oases == true then
 | 
			
		||||
	plantslib:register_generate_plant({
 | 
			
		||||
	biome_lib:register_generate_plant({
 | 
			
		||||
		surface = {
 | 
			
		||||
			"default:sand"--,
 | 
			
		||||
			--"default:desert_sand"
 | 
			
		||||
 
 | 
			
		||||
@@ -3,9 +3,9 @@
 | 
			
		||||
-----------------------------------------------------------------------------------------------
 | 
			
		||||
-- by Mossmanikin
 | 
			
		||||
-- License (everything): 	WTFPL
 | 
			
		||||
-- Contains code from: 		plants_lib
 | 
			
		||||
-- Contains code from: 		biome_lib
 | 
			
		||||
-- Looked at code from:		default, flowers, trees
 | 
			
		||||
-- Dependencies: 			plants_lib
 | 
			
		||||
-- Dependencies: 			biome_lib
 | 
			
		||||
-- Supports:				dryplants, stoneage, sumpf			
 | 
			
		||||
-----------------------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
@@ -74,7 +74,7 @@ create_nodes()
 | 
			
		||||
-- Spawning
 | 
			
		||||
-----------------------------------------------------------------------------------------------
 | 
			
		||||
if abstract_ferns.config.enable_horsetails_spawning == true then
 | 
			
		||||
	plantslib:spawn_on_surfaces({
 | 
			
		||||
	biome_lib:spawn_on_surfaces({
 | 
			
		||||
		spawn_delay = 1200,
 | 
			
		||||
		spawn_plants = node_names,
 | 
			
		||||
		spawn_chance = 400,
 | 
			
		||||
@@ -102,7 +102,7 @@ end
 | 
			
		||||
-----------------------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
if abstract_ferns.config.enable_horsetails_on_grass == true then
 | 
			
		||||
	plantslib:register_generate_plant({
 | 
			
		||||
	biome_lib:register_generate_plant({
 | 
			
		||||
		surface = {
 | 
			
		||||
			"default:dirt_with_grass",
 | 
			
		||||
			"sumpf:sumpf"
 | 
			
		||||
@@ -134,7 +134,7 @@ if abstract_ferns.config.enable_horsetails_on_grass == true then
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
if abstract_ferns.config.enable_horsetails_on_stones == true then
 | 
			
		||||
	plantslib:register_generate_plant({
 | 
			
		||||
	biome_lib:register_generate_plant({
 | 
			
		||||
		surface = {
 | 
			
		||||
			"default:gravel", -- roots go deep
 | 
			
		||||
			"default:mossycobble",
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
-----------------------------------------------------------------------------------------------
 | 
			
		||||
-- by Mossmanikin
 | 
			
		||||
-- License (everything): 	WTFPL
 | 
			
		||||
-- Contains code from: 		plants_lib
 | 
			
		||||
-- Contains code from: 		biome_lib
 | 
			
		||||
-- Looked at code from:		default	, trees			
 | 
			
		||||
-----------------------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
@@ -174,7 +174,7 @@ minetest.register_abm({
 | 
			
		||||
 | 
			
		||||
-- in jungles
 | 
			
		||||
if abstract_ferns.config.enable_treeferns_in_jungle == true then
 | 
			
		||||
	plantslib:register_generate_plant({
 | 
			
		||||
	biome_lib:register_generate_plant({
 | 
			
		||||
		surface = {
 | 
			
		||||
			"default:dirt_with_grass",
 | 
			
		||||
			"default:sand",
 | 
			
		||||
@@ -202,7 +202,7 @@ end
 | 
			
		||||
 | 
			
		||||
-- for oases & tropical beaches
 | 
			
		||||
if abstract_ferns.config.enable_treeferns_in_oases == true then
 | 
			
		||||
	plantslib:register_generate_plant({
 | 
			
		||||
	biome_lib:register_generate_plant({
 | 
			
		||||
		surface = {
 | 
			
		||||
			"default:sand"--,
 | 
			
		||||
			--"default:desert_sand"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,2 +1,2 @@
 | 
			
		||||
plants_lib
 | 
			
		||||
biome_lib
 | 
			
		||||
farming?
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
local S = plantslib.intllib
 | 
			
		||||
local S = biome_lib.intllib
 | 
			
		||||
 | 
			
		||||
-- This file supplies a few additional plants and some related crafts
 | 
			
		||||
-- for the plantlife modpack.  Last revision:  2013-04-24
 | 
			
		||||
@@ -76,16 +76,16 @@ for i in ipairs(lilies_list) do
 | 
			
		||||
			local above_node = minetest.get_node(pt.above)
 | 
			
		||||
			local top_node   = minetest.get_node(top_pos)
 | 
			
		||||
 | 
			
		||||
			if plantslib:get_nodedef_field(under_node.name, "buildable_to") then
 | 
			
		||||
			if biome_lib:get_nodedef_field(under_node.name, "buildable_to") then
 | 
			
		||||
				if under_node.name ~= "default:water_source" then
 | 
			
		||||
					place_pos = pt.under
 | 
			
		||||
				elseif top_node.name ~= "default:water_source" 
 | 
			
		||||
				       and plantslib:get_nodedef_field(top_node.name, "buildable_to") then
 | 
			
		||||
				       and biome_lib:get_nodedef_field(top_node.name, "buildable_to") then
 | 
			
		||||
					place_pos = top_pos
 | 
			
		||||
				else
 | 
			
		||||
					return
 | 
			
		||||
				end
 | 
			
		||||
			elseif plantslib:get_nodedef_field(above_node.name, "buildable_to") then
 | 
			
		||||
			elseif biome_lib:get_nodedef_field(above_node.name, "buildable_to") then
 | 
			
		||||
				place_pos = pt.above
 | 
			
		||||
			end
 | 
			
		||||
 | 
			
		||||
@@ -119,7 +119,7 @@ for i in ipairs(lilies_list) do
 | 
			
		||||
					minetest.set_node(place_pos, {name = "flowers:waterlily", param2 = fdir})
 | 
			
		||||
				end
 | 
			
		||||
 | 
			
		||||
				if not plantslib.expect_infinite_stacks then
 | 
			
		||||
				if not biome_lib.expect_infinite_stacks then
 | 
			
		||||
					itemstack:take_item()
 | 
			
		||||
				end
 | 
			
		||||
				return itemstack
 | 
			
		||||
@@ -176,16 +176,16 @@ for i in ipairs(algae_list) do
 | 
			
		||||
			local above_node = minetest.get_node(pt.above)
 | 
			
		||||
			local top_node   = minetest.get_node(top_pos)
 | 
			
		||||
 | 
			
		||||
			if plantslib:get_nodedef_field(under_node.name, "buildable_to") then
 | 
			
		||||
			if biome_lib:get_nodedef_field(under_node.name, "buildable_to") then
 | 
			
		||||
				if under_node.name ~= "default:water_source" then
 | 
			
		||||
					place_pos = pt.under
 | 
			
		||||
				elseif top_node.name ~= "default:water_source" 
 | 
			
		||||
				       and plantslib:get_nodedef_field(top_node.name, "buildable_to") then
 | 
			
		||||
				       and biome_lib:get_nodedef_field(top_node.name, "buildable_to") then
 | 
			
		||||
					place_pos = top_pos
 | 
			
		||||
				else
 | 
			
		||||
					return
 | 
			
		||||
				end
 | 
			
		||||
			elseif plantslib:get_nodedef_field(above_node.name, "buildable_to") then
 | 
			
		||||
			elseif biome_lib:get_nodedef_field(above_node.name, "buildable_to") then
 | 
			
		||||
				place_pos = pt.above
 | 
			
		||||
			end
 | 
			
		||||
 | 
			
		||||
@@ -211,7 +211,7 @@ for i in ipairs(algae_list) do
 | 
			
		||||
					minetest.set_node(place_pos, {name = "flowers:seaweed", param2 = fdir})
 | 
			
		||||
				end
 | 
			
		||||
 | 
			
		||||
				if not plantslib.expect_infinite_stacks then
 | 
			
		||||
				if not biome_lib.expect_infinite_stacks then
 | 
			
		||||
					itemstack:take_item()
 | 
			
		||||
				end
 | 
			
		||||
				return itemstack
 | 
			
		||||
@@ -297,7 +297,7 @@ flowers_plus.grow_waterlily = function(pos)
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {"default:water_source"},
 | 
			
		||||
    max_count = lilies_max_count,
 | 
			
		||||
    rarity = lilies_rarity,
 | 
			
		||||
@@ -319,7 +319,7 @@ flowers_plus.grow_seaweed = function(pos)
 | 
			
		||||
	minetest.set_node(right_here, {name="along_shore:seaweed_"..math.random(1,4), param2=math.random(1,3)})
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {"default:water_source"},
 | 
			
		||||
    max_count = seaweed_max_count,
 | 
			
		||||
    rarity = seaweed_rarity,
 | 
			
		||||
@@ -336,7 +336,7 @@ plantslib:register_generate_plant({
 | 
			
		||||
 | 
			
		||||
-- seaweed at beaches
 | 
			
		||||
-- MM: not satisfied with it, but IMHO some beaches should have some algae
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {"default:water_source"},
 | 
			
		||||
    max_count = seaweed_max_count,
 | 
			
		||||
    rarity = seaweed_rarity,
 | 
			
		||||
@@ -352,7 +352,7 @@ plantslib:register_generate_plant({
 | 
			
		||||
  },
 | 
			
		||||
  flowers_plus.grow_seaweed
 | 
			
		||||
)
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {"default:sand"},
 | 
			
		||||
    max_count = seaweed_max_count*2,
 | 
			
		||||
    rarity = seaweed_rarity/2,
 | 
			
		||||
@@ -369,7 +369,7 @@ plantslib:register_generate_plant({
 | 
			
		||||
  flowers_plus.grow_seaweed
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
	surface = {"default:dirt_with_grass"},
 | 
			
		||||
	avoid_nodes = { "flowers:sunflower" },
 | 
			
		||||
	max_count = sunflowers_max_count,
 | 
			
		||||
@@ -384,7 +384,7 @@ plantslib:register_generate_plant({
 | 
			
		||||
 | 
			
		||||
-- spawn ABM registrations
 | 
			
		||||
 | 
			
		||||
plantslib:spawn_on_surfaces({
 | 
			
		||||
biome_lib:spawn_on_surfaces({
 | 
			
		||||
	spawn_delay = SPAWN_DELAY/2,
 | 
			
		||||
	spawn_plants = {
 | 
			
		||||
		"flowers:waterlily",
 | 
			
		||||
@@ -406,7 +406,7 @@ plantslib:spawn_on_surfaces({
 | 
			
		||||
	random_facedir = {0,3}
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
plantslib:spawn_on_surfaces({
 | 
			
		||||
biome_lib:spawn_on_surfaces({
 | 
			
		||||
	spawn_delay = SPAWN_DELAY*2,
 | 
			
		||||
	spawn_plants = {"flowers:seaweed"},
 | 
			
		||||
	spawn_chance = SPAWN_CHANCE*2,
 | 
			
		||||
@@ -419,7 +419,7 @@ plantslib:spawn_on_surfaces({
 | 
			
		||||
	facedir = 1
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
plantslib:spawn_on_surfaces({
 | 
			
		||||
biome_lib:spawn_on_surfaces({
 | 
			
		||||
	spawn_delay = SPAWN_DELAY*2,
 | 
			
		||||
	spawn_plants = {"flowers:seaweed"},
 | 
			
		||||
	spawn_chance = SPAWN_CHANCE*2,
 | 
			
		||||
@@ -433,7 +433,7 @@ plantslib:spawn_on_surfaces({
 | 
			
		||||
	facedir = 1
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
plantslib:spawn_on_surfaces({
 | 
			
		||||
biome_lib:spawn_on_surfaces({
 | 
			
		||||
	spawn_delay = SPAWN_DELAY*2,
 | 
			
		||||
	spawn_plants = {"flowers:seaweed"},
 | 
			
		||||
	spawn_chance = SPAWN_CHANCE*2,
 | 
			
		||||
@@ -447,7 +447,7 @@ plantslib:spawn_on_surfaces({
 | 
			
		||||
	facedir = 1
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
plantslib:spawn_on_surfaces({
 | 
			
		||||
biome_lib:spawn_on_surfaces({
 | 
			
		||||
	spawn_delay = SPAWN_DELAY*2,
 | 
			
		||||
	spawn_plants = {"flowers:sunflower"},
 | 
			
		||||
	spawn_chance = SPAWN_CHANCE*2,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,2 +1,2 @@
 | 
			
		||||
default
 | 
			
		||||
plants_lib
 | 
			
		||||
biome_lib
 | 
			
		||||
@@ -92,7 +92,7 @@ abstract_molehills.place_molehill = function(pos)
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {"default:dirt_with_grass"},
 | 
			
		||||
    max_count = Molehills_Max_Count,
 | 
			
		||||
    rarity = Molehills_Rarity,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,579 +0,0 @@
 | 
			
		||||
This document describes the Plantlife mod API.
 | 
			
		||||
 | 
			
		||||
Last revision: 2015-02-16
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=========
 | 
			
		||||
Functions
 | 
			
		||||
=========
 | 
			
		||||
 | 
			
		||||
There are three main functions defined by the main "plants_lib" mod:
 | 
			
		||||
 | 
			
		||||
spawn_on_surfaces()
 | 
			
		||||
register_generate_plant()
 | 
			
		||||
grow_plants()
 | 
			
		||||
 | 
			
		||||
There are also several internal, helper functions that can be called if so
 | 
			
		||||
desired, but they are not really intended for use by other mods and may change
 | 
			
		||||
at any time.  They are briefly described below these main functions, but see
 | 
			
		||||
init.lua for details.
 | 
			
		||||
 | 
			
		||||
Most functions in plants lib are declared locally to avoid namespace
 | 
			
		||||
collisions with other mods.  They are accessible via the "plantslib" method,
 | 
			
		||||
e.g. plantslib:spawn_on_surfaces() and so forth.
 | 
			
		||||
 | 
			
		||||
=====
 | 
			
		||||
spawn_on_surfaces(biome)
 | 
			
		||||
spawn_on_surfaces(sdelay, splant, sradius, schance, ssurface, savoid)
 | 
			
		||||
 | 
			
		||||
This first function is an ABM-based spawner function originally created as
 | 
			
		||||
part of Ironzorg's flowers mod.  It has since been largely extended and
 | 
			
		||||
expanded.  There are two ways to call this function:  You can either pass it 
 | 
			
		||||
several individual string and number parameters to use the legacy interface,
 | 
			
		||||
or you can pass a single biome definition as a table, with all of your options
 | 
			
		||||
spelled out nicely.  This is the preferred method.
 | 
			
		||||
 | 
			
		||||
When used with the legacy interface, you must specify the parameters exactly
 | 
			
		||||
in order, with the first five being mandatory (even if some are set to nil),
 | 
			
		||||
and the last one being optional:
 | 
			
		||||
 | 
			
		||||
sdelay:		The value passed to the ABM's interval parameter, in seconds.
 | 
			
		||||
splant:		The node name of the item to spawn (e.g.
 | 
			
		||||
		"flowers:flower_rose").  A plant will of course only be
 | 
			
		||||
		spawned if the node about to be replaced is air.
 | 
			
		||||
sradius:	Don't spawn within this many nodes of the avoid items
 | 
			
		||||
		mentioned below.  If set to nil, this check is skipped.
 | 
			
		||||
schance:	The value passed to the ABM's chance parameter, normally in
 | 
			
		||||
		the 10-100 range (1-in-X chance of operating on a given node)
 | 
			
		||||
ssurface:	String with the name of the node on which to spawn the plant
 | 
			
		||||
		in question, such as "default:sand" or
 | 
			
		||||
		"default:dirt_with_grass".  It is not recommended to put air,
 | 
			
		||||
		stone, or plain dirt here if you can use some other node, as
 | 
			
		||||
		doing so will cause the engine to process potentially large
 | 
			
		||||
		numbers of such nodes when deciding when to execute the ABM
 | 
			
		||||
		and where it should operate.
 | 
			
		||||
savoid:		Table with a list of groups and/or node names to avoid when
 | 
			
		||||
		spawning the plant, such as {"group:flowers", "default:tree"}.
 | 
			
		||||
 | 
			
		||||
When passed a table as the argument, and thus using the modern calling method,
 | 
			
		||||
you must pass a number of arguments in the form of an ordinary keyed-value
 | 
			
		||||
table.  Below is a list of everything supported by this function:
 | 
			
		||||
 | 
			
		||||
biome = {
 | 
			
		||||
	spawn_plants = something, -- [*] String or table; see below.
 | 
			
		||||
	spawn_delay = number,	-- same as sdelay, above.
 | 
			
		||||
	spawn_chance = number,	-- same as schance, above.
 | 
			
		||||
	spawn_surfaces = {table}, -- List of node names on which the plants
 | 
			
		||||
				-- should be spawned.  As with the single-node "ssurface"
 | 
			
		||||
				-- option in the legacy API, you should not put stone, air,
 | 
			
		||||
				-- etc. here.
 | 
			
		||||
 | 
			
		||||
	---- From here down are a number of optional parameters.  You will
 | 
			
		||||
	---- most likely want to use at least some of these to limit how and
 | 
			
		||||
	---- where your objects are spawned.
 | 
			
		||||
 | 
			
		||||
	avoid_nodes = {table},	-- same meaning as savoid, above
 | 
			
		||||
	avoid_radius = num,	-- same as sradius
 | 
			
		||||
	seed_diff = num,	-- The Perlin seed difference value passed to the
 | 
			
		||||
						-- minetest.get_perlin() function.  Used along with
 | 
			
		||||
						-- the global Perlin controls below to create the
 | 
			
		||||
						-- "biome" in which the plants will spawn.  Defaults
 | 
			
		||||
						-- to 0 if not provided.
 | 
			
		||||
	light_min = num,	-- Minimum amount of light necessary to make a plant
 | 
			
		||||
						-- spawn.  Defaults to 0.
 | 
			
		||||
	light_max = num,	-- Maximum amount of light needed to spawn.  Defaults
 | 
			
		||||
						-- to the engine's MAX_LIGHT value of 14.
 | 
			
		||||
	neighbors = {table}, -- List of neighboring nodes that need to be
 | 
			
		||||
						-- immediately next to the node the plant is about to
 | 
			
		||||
						-- spawn on. Can also be a string with a single node
 | 
			
		||||
						-- name.  It is both passed to the ABM as the
 | 
			
		||||
						-- "neighbors" parameter, and is used to manually
 | 
			
		||||
						-- check the adjacent nodes.  It only takes one of
 | 
			
		||||
						-- these for the spawn routine to mark the target as
 | 
			
		||||
						-- spawnable.  Defaults to nil (ignored).
 | 
			
		||||
	ncount = num,		-- There must be at least this many of the above
 | 
			
		||||
						-- neighbors in the eight spaces immediately
 | 
			
		||||
						-- surrounding the node the plant is about to spawn on
 | 
			
		||||
						-- for it to happen.  If not provided, this check is
 | 
			
		||||
						-- disabled.
 | 
			
		||||
	facedir = num,		-- The value passed to the param2 variable when adding
 | 
			
		||||
						-- the node to the map.  Defaults to 0.  Be sure that
 | 
			
		||||
						-- the value you use here (and the range thereof) is
 | 
			
		||||
						-- appropriate for the type of node you're spawning.
 | 
			
		||||
	random_facedir = {table}, -- If set, the table should contain two values.
 | 
			
		||||
						-- If they're both provided, the spawned plant will be
 | 
			
		||||
						-- given a random facedir value in the range specified
 | 
			
		||||
						-- by these two numbers.  Overrides the facedir
 | 
			
		||||
						-- parameter above, if it exists.  Use {0,3} if you
 | 
			
		||||
						-- want the full range for wallmounted nodes, or {2,5}
 | 
			
		||||
						-- for most everything else, or any other pair of
 | 
			
		||||
						-- numbers appropriate for the node you want to spawn.
 | 
			
		||||
	depth_max = num,	-- If the object spawns on top of a water source, the
 | 
			
		||||
						-- water must be at most this deep.  Defaults to 1.
 | 
			
		||||
	min_elevation = num, -- Surface must be at this altitude or higher to
 | 
			
		||||
						-- spawn at all.  Defaults to -31000...
 | 
			
		||||
	max_elevation = num, -- ...but must be no higher than this altitude.
 | 
			
		||||
						-- Defaults to +31000.
 | 
			
		||||
	near_nodes = {table}, -- List of nodes that must be somewhere in the
 | 
			
		||||
						-- vicinity in order for the plant to spawn. Can also
 | 
			
		||||
						-- be a string with a single node name.  If not
 | 
			
		||||
						-- provided, this check is disabled.
 | 
			
		||||
	near_nodes_size = num,	-- How large of an area to check for the above
 | 
			
		||||
						-- node.  Specifically, this checks a flat, horizontal
 | 
			
		||||
						-- area centered on the node to be spawned on.
 | 
			
		||||
						-- Defaults to 0, but is ignored if the above
 | 
			
		||||
						-- near_nodes value is not set.
 | 
			
		||||
	near_nodes_vertical = num, -- Used with the size value above, this extends
 | 
			
		||||
						-- the vertical range of the near nodes search.
 | 
			
		||||
						-- Basically, this turns the flat region described
 | 
			
		||||
						-- above into a cuboid region.  The area to be checked
 | 
			
		||||
						-- will extend this high and this low above/below the
 | 
			
		||||
						-- target node, centered thereon.  Defaults to 1 (only
 | 
			
		||||
						-- check the layer above, the layer at, and the layer
 | 
			
		||||
						-- below the target node), but is ignored if
 | 
			
		||||
						-- near_nodes is not set.
 | 
			
		||||
	near_nodes_count = num,	-- How many of the above nodes must be within that
 | 
			
		||||
						-- radius.  Defaults to 1 but is ignored if near_nodes
 | 
			
		||||
						-- isn't set.  Bear in mind that the total area to be
 | 
			
		||||
						-- checked is equal to:
 | 
			
		||||
						-- (near_nodes_size^2)*near_nodes_vertical*2 
 | 
			
		||||
						-- For example, if size is 10 and vertical is 4, then
 | 
			
		||||
						-- the area is (10^2)*8 = 800 nodes in size, so you'll
 | 
			
		||||
						-- want to make sure you specify a value appropriate
 | 
			
		||||
						-- for the size of the area being tested.
 | 
			
		||||
	air_size = num,		-- How large of an area to check for air above and
 | 
			
		||||
						-- around the target.  If omitted, only the space
 | 
			
		||||
						-- above the target is checked.  This does not check
 | 
			
		||||
						-- for air at the sides or below the target.
 | 
			
		||||
	air_count = num,	-- How many of the surrounding nodes need to be air
 | 
			
		||||
						-- for the above check to return true. If omitted,
 | 
			
		||||
						-- only the space above the target is checked.
 | 
			
		||||
	plantlife_limit = num, -- The value compared against the generic "plants
 | 
			
		||||
						-- can grow here" Perlin noise layer. Smaller numbers
 | 
			
		||||
						-- result in more abundant plants.  Range of -1 to +1,
 | 
			
		||||
						-- with values in the range of about 0 to 0.5 being
 | 
			
		||||
						-- most useful.  Defaults to 0.1.
 | 
			
		||||
	temp_min = num,		-- Minimum temperature needed for the desired object
 | 
			
		||||
						-- to spawn.  This is a 2d Perlin value, which has an
 | 
			
		||||
						-- inverted range of +1 to -1.  Larger values
 | 
			
		||||
						-- represent *colder* temperatures, so this value is
 | 
			
		||||
						-- actually the upper end of the desired Perlin range.
 | 
			
		||||
						-- See the temperature map section at the bottom of
 | 
			
		||||
						-- this document for details on how these values work.
 | 
			
		||||
						-- Defaults to +1 (unlimited coldness).
 | 
			
		||||
	temp_max = num,		-- Maximum temperature/lower end of the Perlin range.
 | 
			
		||||
						-- Defaults to -1 (unlimited heat).
 | 
			
		||||
	humidity_min = num,	-- Minimum humidity for the plant to spawn in. Like
 | 
			
		||||
						-- the temperature map, this is a Perlin value where
 | 
			
		||||
						-- lower numbers mean more humidity in the area.
 | 
			
		||||
						-- Defaults to +1 (0% humidity).
 | 
			
		||||
	humidity_max = num,	-- Maximum humidity for the plant to spawn at.
 | 
			
		||||
						-- Defaults to -1 (100% humidity).
 | 
			
		||||
	verticals_list = {table}, -- List of nodes that should be considered to be
 | 
			
		||||
						-- natural walls.
 | 
			
		||||
	alt_wallnode = "string", -- If specified, this node will be substituted in
 | 
			
		||||
						-- place of the plant(s) defined by spawn_plants
 | 
			
		||||
						-- above, if the spawn target has one or more adjacent
 | 
			
		||||
						-- walls.  In such a case, the two above facedir
 | 
			
		||||
						-- parameters will be ignored.
 | 
			
		||||
	spawn_on_side = bool, -- Set this to true to immediately spawn the node on
 | 
			
		||||
						-- one side of the target node rather than the top.
 | 
			
		||||
						-- The code will search for an airspace to the side of
 | 
			
		||||
						-- the target, then spawn the plant at the first one
 | 
			
		||||
						-- found.  The above facedir and random_facedir
 | 
			
		||||
						-- parameters are ignored in this case.  If the above
 | 
			
		||||
						-- parameters for selecting generic wall nodes are
 | 
			
		||||
						-- provided, this option is ignored.  Important note:
 | 
			
		||||
						-- the facedir values assigned by this option only
 | 
			
		||||
						-- make sense with wallmounted nodes (nodes which
 | 
			
		||||
						-- don't use facedir won't be affected).
 | 
			
		||||
	choose_random_wall = bool, -- if set to true, and searching for walls is
 | 
			
		||||
						-- being done, just pick any random wall if there is
 | 
			
		||||
						-- one, rather than returning the first one.
 | 
			
		||||
	spawn_on_bottom = bool,	-- If set to true, spawn the object below the
 | 
			
		||||
						-- target node instead of above it.  The above
 | 
			
		||||
						-- spawn_on_side variable takes precedence over this
 | 
			
		||||
						-- one if both happen to be true. When using this
 | 
			
		||||
						-- option with the random facedir function above, the
 | 
			
		||||
						-- values given to the facedir parameter are for
 | 
			
		||||
						-- regular nodes, not wallmounted.
 | 
			
		||||
	spawn_replace_node = bool, -- If set to true, the target node itself is
 | 
			
		||||
						-- replaced by the spawned object.  Overrides the
 | 
			
		||||
						-- spawn_on_bottom and spawn_on_side settings.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[*] spawn_plants must be either a table or a string.  If it's a table, the
 | 
			
		||||
values therein are treated as a list of nodenames to pick from randomly on 
 | 
			
		||||
each application of the ABM code. The more nodes you can pack into this
 | 
			
		||||
parameter to avoid making too many calls to this function, the lower the CPU
 | 
			
		||||
load will likely be.
 | 
			
		||||
 | 
			
		||||
You can also specify a string containing the name of a function to execute.
 | 
			
		||||
In this case, the function will be passed a single position parameter
 | 
			
		||||
indicating where the function should place the desired object, and the checks
 | 
			
		||||
for spawning on top vs. sides vs. bottom vs. replacing the target node will be
 | 
			
		||||
skipped.
 | 
			
		||||
 | 
			
		||||
By default, if a biome node, size, and count are not defined, the biome
 | 
			
		||||
checking is disabled.  Same holds true for the nneighbors bit above that.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=====
 | 
			
		||||
plantslib:register_generate_plant(biome, nodes_or_function_or_treedef)
 | 
			
		||||
 | 
			
		||||
To register an object to be spawned at mapgen time rather than via an ABM,
 | 
			
		||||
call this function with two parameters:  a table with your object's biome
 | 
			
		||||
information, and a string, function, or table describing what to do if the
 | 
			
		||||
engine finds a suitable surface node (see below).
 | 
			
		||||
 | 
			
		||||
The biome table contains quite a number of options, though there are fewer 
 | 
			
		||||
here than are available in the ABM-based spawner, as some stuff doesn't make
 | 
			
		||||
sense at map-generation time.
 | 
			
		||||
 | 
			
		||||
biome = {
 | 
			
		||||
	surface = something, -- What node(s).  May be a string such as
 | 
			
		||||
						-- "default:dirt_with_grass" or a table with
 | 
			
		||||
						-- multiple such entries.
 | 
			
		||||
 | 
			
		||||
	---- Everything else is optional, but you'll definitely want to use
 | 
			
		||||
	---- some of these other fields to limit where and under what
 | 
			
		||||
	---- conditions the objects are spawned.
 | 
			
		||||
	
 | 
			
		||||
	below_nodes = {table}, -- List of nodes that must be below the target
 | 
			
		||||
						-- node.  Useful in snow biomes to keep objects from
 | 
			
		||||
						-- spawning in snow that's on the wrong surface for
 | 
			
		||||
						-- that object.
 | 
			
		||||
	avoid_nodes = {table}, -- List of nodes to avoid when spawning. Groups are
 | 
			
		||||
						-- not supported here.
 | 
			
		||||
	avoid_radius = num,	-- How much distance to leave between the object to be
 | 
			
		||||
						-- added and the objects to be avoided.  If this or
 | 
			
		||||
						-- the avoid_nodes value is nil/omitted, this check is
 | 
			
		||||
						-- skipped.  Avoid using excessively large radii.
 | 
			
		||||
	rarity = num,		-- How rare should this object be in its biome? Larger
 | 
			
		||||
						-- values make objects more rare, via:
 | 
			
		||||
						-- math.random(1,100) > this
 | 
			
		||||
	max_count = num,	-- The absolute maximum number of your object that
 | 
			
		||||
						-- should be allowed to spawn in a 5x5x5 mapblock area
 | 
			
		||||
						-- (80x80x80 nodes).  Defaults to 5, but be sure you
 | 
			
		||||
						-- set this to some reasonable value depending on your
 | 
			
		||||
						-- object and its size if 5 is insufficient.
 | 
			
		||||
	seed_diff = num,	-- Perlin seed-diff value.  Defaults to 0, which
 | 
			
		||||
						-- causes the function to inherit the global value of
 | 
			
		||||
						-- 329.
 | 
			
		||||
	neighbors = {table}, -- What ground nodes must be right next to and at the
 | 
			
		||||
						-- same elevation as the node to be spawned on.
 | 
			
		||||
	ncount = num,		-- At least this many of the above nodes must be next
 | 
			
		||||
						-- to the node to spawn on.  Any value greater than 8
 | 
			
		||||
						-- will probably cause the code to never spawn
 | 
			
		||||
						-- anything.  Defaults to 0.
 | 
			
		||||
	depth = num,		-- How deep/thick of a layer the spawned-on node must
 | 
			
		||||
						-- be.  Typically used for water.
 | 
			
		||||
	min_elevation = num, -- Minimum elevation in meters/nodes.  Defaults to
 | 
			
		||||
						-- -31000 (unlimited).
 | 
			
		||||
	max_elevation = num, -- Max elevation.  Defaults to +31000 (unlimited).
 | 
			
		||||
	near_nodes = {table}, -- what nodes must be in the general vicinity of the
 | 
			
		||||
						-- object being spawned.
 | 
			
		||||
	near_nodes_size = num, -- how wide of a search area to look for the nodes
 | 
			
		||||
						-- in that list.
 | 
			
		||||
	near_nodes_vertical = num, -- How high/low of an area to search from the
 | 
			
		||||
						-- target node.
 | 
			
		||||
	near_nodes_count = num,	-- at least this many of those nodes must be in
 | 
			
		||||
						-- the area.
 | 
			
		||||
	plantlife_limit = num, -- The value compared against the generic "plants
 | 
			
		||||
						-- can grow here" Perlin noise layer.  Smaller numbers
 | 
			
		||||
						-- result in more abundant plants.  Range of -1 to +1,
 | 
			
		||||
						-- with values in the range of about 0 to 0.5 being
 | 
			
		||||
						-- most useful.  Defaults to 0.1.
 | 
			
		||||
	temp_min = num,		-- Coldest allowable temperature for a plant to spawn
 | 
			
		||||
						-- (that is, the largest Perlin value).
 | 
			
		||||
	temp_max = num,		-- warmest allowable temperature to spawn a plant
 | 
			
		||||
						-- (lowest Perlin value).
 | 
			
		||||
	verticals_list = {table}, -- Same as with the spawn_on_surfaces function.
 | 
			
		||||
	check_air = bool,	-- Flag to tell the mapgen code to check for air above
 | 
			
		||||
						-- the spawn target.  Defaults to true if not
 | 
			
		||||
						-- explicitly set to false.  Set this to false VERY
 | 
			
		||||
						-- SPARINGLY, as it will slow the map generator down.
 | 
			
		||||
	delete_above = bool, -- Flag to tell the mapgen code to delete the two
 | 
			
		||||
						-- nodes directly above the spawn target just before
 | 
			
		||||
						-- adding the plant or tree.  Useful when generating
 | 
			
		||||
						-- in snow biomes.  Defaults to false.
 | 
			
		||||
	delete_above_surround = bool, -- Flag to tell the mapgen code to also
 | 
			
		||||
						-- delete the five nodes surrounding the above space,
 | 
			
		||||
						-- and the five nodes above those, resulting in a two-
 | 
			
		||||
						-- node-deep cross-shaped empty region above/around
 | 
			
		||||
						-- the spawn target.  Useful when adding trees to snow
 | 
			
		||||
						-- biomes.  Defaults to false.
 | 
			
		||||
	spawn_replace_node = bool, -- same as with the ABM spawner.
 | 
			
		||||
	random_facedir = {table}, -- same as with the ABM spawner.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Regarding nodes_or_function_or_treedef, this must either be a string naming
 | 
			
		||||
a node to spawn, a table with a list of nodes to choose from, a table with an
 | 
			
		||||
L-Systems tree definition, or a function.
 | 
			
		||||
 | 
			
		||||
If you specified a string, the code will attempt to determine whether that
 | 
			
		||||
string specifies a valid node name.  If it does, that node will be placed on
 | 
			
		||||
top of the target position directly (unless one of the other mapgen options
 | 
			
		||||
directs the code to do otherwise).
 | 
			
		||||
 | 
			
		||||
If you specified a table and there is no "axiom" field, the code assumes that
 | 
			
		||||
it is a list of nodes.  Simply name one node per entry in the list, e.g.
 | 
			
		||||
{"default:junglegrass", "default:dry_shrub"} and so on, for as many nodes as
 | 
			
		||||
you want to list.  A random node from the list will be chosen each time the
 | 
			
		||||
code goes to place a node.
 | 
			
		||||
 | 
			
		||||
If you specified a table, and there *is* an "axiom" field, the code assumes
 | 
			
		||||
that this table contains an L-Systems tree definition, which will be passed
 | 
			
		||||
directly to the engine's spawn_tree() function along with the position on
 | 
			
		||||
which to spawn the tree.
 | 
			
		||||
 | 
			
		||||
You can also supply a function to be directly executed, which is given the
 | 
			
		||||
current node position (the usual "pos" table format) as its sole argument.  It
 | 
			
		||||
will be called in the form:
 | 
			
		||||
 | 
			
		||||
	somefunction(pos)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=====
 | 
			
		||||
plantslib:grow_plants(options)
 | 
			
		||||
 | 
			
		||||
The third function, grow_plants() is used to turn the spawned nodes above
 | 
			
		||||
into something else over time.  This function has no return value, and accepts
 | 
			
		||||
a biome definition table as the only parameter.  These are defined like so:
 | 
			
		||||
 | 
			
		||||
options = {
 | 
			
		||||
	grow_plant = "string", -- Name of the node to be grown into something
 | 
			
		||||
						-- else.  This value is passed to the ABM as the
 | 
			
		||||
						-- "nodenames" parameter, so it is the plants
 | 
			
		||||
						-- themselves that are the ABM trigger, rather than
 | 
			
		||||
						-- the ground they spawned on.  A plant will only grow
 | 
			
		||||
						-- if the node above it is air.  Can also be a table,
 | 
			
		||||
						-- but note that all nodes referenced therein will be
 | 
			
		||||
						-- grown into the same object.
 | 
			
		||||
	grow_delay = num,	-- Passed as the ABM "interval" parameter, as with
 | 
			
		||||
						-- spawning.
 | 
			
		||||
	grow_chance = num,	-- Passed as the ABM "chance" parameter.
 | 
			
		||||
	grow_result = "string",	-- Name of the node into which the grow_plant
 | 
			
		||||
						-- node(s) should transform when the ABM executes.
 | 
			
		||||
 | 
			
		||||
	---- Everything from here down is optional.
 | 
			
		||||
 | 
			
		||||
	dry_early_node = "string", -- This value is ignored except for jungle
 | 
			
		||||
						-- grass (a corner case needed by that mod), where it
 | 
			
		||||
						-- indicates which node the grass must be on in order
 | 
			
		||||
						-- for it to turn from the short size to
 | 
			
		||||
						-- "default:dry_shrub" instead of the medium size.
 | 
			
		||||
	grow_nodes = {table}, -- One of these nodes must be under the plant in
 | 
			
		||||
						-- order for it to grow at all.  Normally this should
 | 
			
		||||
						-- be the same as the list of surfaces passed to the
 | 
			
		||||
						-- spawning ABM as the "nodenames" parameter.  This is
 | 
			
		||||
						-- so that the plant can be manually placed on
 | 
			
		||||
						-- something like a flower pot or something without it
 | 
			
		||||
						-- necessarily growing and perhaps dieing.  Defaults
 | 
			
		||||
						-- to "default:dirt_with_grass".
 | 
			
		||||
	facedir = num,		-- Same as with spawning a plant.
 | 
			
		||||
	need_wall = bool,	-- Set this to true if you the plant needs to grow
 | 
			
		||||
						-- against a wall.  Defaults to false.
 | 
			
		||||
	verticals_list = {table}, -- same as with spawning a plant.
 | 
			
		||||
	choose_random_wall = bool, -- same as with spawning a plant.
 | 
			
		||||
	grow_vertically = bool,	-- Set this to true if the plant needs to grow
 | 
			
		||||
						-- vertically, as in climbing poison ivy. Defaults to
 | 
			
		||||
						-- false.
 | 
			
		||||
	height_limit = num,	-- Set this to limit how tall the desired node can
 | 
			
		||||
						-- grow.  The mod will search straight down from the
 | 
			
		||||
						-- position being spawned at to find a ground node,
 | 
			
		||||
						-- set via the field below. Defaults to 5 nodes.
 | 
			
		||||
	ground_nodes = {table},	-- What nodes should be treated as "the ground"
 | 
			
		||||
						-- below a vertically-growing plant. Usually this
 | 
			
		||||
						-- should be the same as the grow_nodes table, but
 | 
			
		||||
						-- might also include, for example, water or some
 | 
			
		||||
						-- other surrounding material.  Defaults to
 | 
			
		||||
						-- "default:dirt_with_grass".
 | 
			
		||||
	grow_function = something, -- [*] see below.
 | 
			
		||||
	seed_diff = num,	-- [*] see below.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[*] grow_function can take one of three possible settings:  it can be nil (or
 | 
			
		||||
    not provided), a string, or a table.
 | 
			
		||||
 | 
			
		||||
If it is not provided or it's set to nil, all of the regular growing code is
 | 
			
		||||
executed normally, the value of seed_diff, if any, is ignored, and the node to
 | 
			
		||||
be placed is assumed to be specified in the grow_result variable.
 | 
			
		||||
 | 
			
		||||
If this value is set to a simple string, this is treated as the name of the
 | 
			
		||||
function to use to grow the plant.  In this case, all of the usual growing
 | 
			
		||||
code is executeed, but then instead of a plant being simply added to the
 | 
			
		||||
world, grow_result is ignored and the named function is executed and passed a
 | 
			
		||||
few parmeters in the following general form: 
 | 
			
		||||
 | 
			
		||||
	somefunction(pos, perlin1, perlin2)
 | 
			
		||||
 | 
			
		||||
These values represent the current position (the usual table), the Perlin
 | 
			
		||||
noise value for that spot in the generic "plants can grow here" map for the
 | 
			
		||||
seed_diff value above, the Perlin value for that same spot from the
 | 
			
		||||
temperature map, and the detected neighboring wall face, if there was one (or
 | 
			
		||||
nil if not).  If seed_diff is not provided, it defaults to 0.
 | 
			
		||||
 | 
			
		||||
If this variable is instead set to a table, it is treated an an L-Systems tree
 | 
			
		||||
definition.  All of the growing code is executed in the usual manner, then the
 | 
			
		||||
tree described by that definition is spawned at the current position instead,
 | 
			
		||||
and grow_result is ignored.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=====
 | 
			
		||||
find_adjacent_wall(pos, verticals, randomflag)
 | 
			
		||||
 | 
			
		||||
Of the few helper functions, this one expects a position parameter and a table
 | 
			
		||||
with the list of nodes that should be considered as walls.  The code will
 | 
			
		||||
search around the given position for a neighboring wall, returning the first
 | 
			
		||||
one it finds as a facedir value, or nil if there are no adjacent walls.
 | 
			
		||||
 | 
			
		||||
If randomflag is set to true, the function will just return the facedir of any
 | 
			
		||||
random wall it finds adjacent to the target position.  Defaults to false if 
 | 
			
		||||
not specified.
 | 
			
		||||
 | 
			
		||||
=====
 | 
			
		||||
is_node_loaded(pos)
 | 
			
		||||
 | 
			
		||||
This acts as a wrapper for the minetest.get_node_or_nil(node_pos)
 | 
			
		||||
function and accepts a single position parameter.  Returns true if the node in
 | 
			
		||||
question is already loaded, or false if not.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=====
 | 
			
		||||
dbg(string)
 | 
			
		||||
 | 
			
		||||
This is a simple debug output function which takes one string parameter.  It
 | 
			
		||||
just checks if DEBUG is true and outputs the phrase "[Plantlife] " followed by
 | 
			
		||||
the supplied string, via the print() function, if so.
 | 
			
		||||
 | 
			
		||||
=====
 | 
			
		||||
plantslib:generate_tree(pos, treemodel)
 | 
			
		||||
plantslib:grow_tree(pos, treemodel)
 | 
			
		||||
 | 
			
		||||
In the case of the growing code and the mapgen-based tree generator code, 
 | 
			
		||||
generating a tree is done via the above two calls, which in turn immediately
 | 
			
		||||
call the usual spawn_tree() functions.  This rerouting exists as a way for
 | 
			
		||||
other mods to hook into plants_lib's tree-growing functions in general,
 | 
			
		||||
perhaps to execute something extra whenever a tree is spawned.
 | 
			
		||||
 | 
			
		||||
plantslib:generate_tree(pos, treemodel) is called any time a tree is spawned
 | 
			
		||||
at map generation time.  'pos' is the position of the block on which the tree
 | 
			
		||||
is to be placed.  'treemodel' is the standard L-Systems tree definition table
 | 
			
		||||
expected by the spawn_tree() function.  Refer to the 'trunk' field in that
 | 
			
		||||
table to derive the name of the tree being spawned.
 | 
			
		||||
 | 
			
		||||
plantslib:grow_tree(pos, treemodel) does the same sort of thing whenever a 
 | 
			
		||||
tree is spawned within the abm-based growing code, for example when growing a
 | 
			
		||||
sapling into a tree.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=====
 | 
			
		||||
There are other, internal helper functions that are not meant for use by other
 | 
			
		||||
mods.  Don't rely on them, as they are subject to change without notice.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
===============
 | 
			
		||||
Global Settings
 | 
			
		||||
===============
 | 
			
		||||
 | 
			
		||||
Set this to true if you want the mod to spam your console with debug info :-)
 | 
			
		||||
 | 
			
		||||
	plantlife_debug = false
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
======================
 | 
			
		||||
Fertile Ground Mapping
 | 
			
		||||
======================
 | 
			
		||||
 | 
			
		||||
The mod uses Perlin noise to create "biomes" of the various plants, via the
 | 
			
		||||
minetest.get_perlin() function.  At present, there are three layers of
 | 
			
		||||
Perlin noise used.
 | 
			
		||||
 | 
			
		||||
The first one is for a "fertile ground" layer, which I tend to refer to as the
 | 
			
		||||
generic "stuff can potentially grow here" layer.  Its values are hard-coded:
 | 
			
		||||
 | 
			
		||||
	plantslib.plantlife_seed_diff = 329
 | 
			
		||||
	perlin_octaves = 3
 | 
			
		||||
	perlin_persistence = 0.6
 | 
			
		||||
	perlin_scale = 100
 | 
			
		||||
 | 
			
		||||
For more information on how Perlin noise is generated, you will need to search
 | 
			
		||||
the web, as these default values were from that which is used by minetest_game
 | 
			
		||||
to spawn jungle grass at mapgen time, and I'm still learning how Perlin noise
 | 
			
		||||
works.  ;-)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
===================
 | 
			
		||||
Temperature Mapping
 | 
			
		||||
===================
 | 
			
		||||
 | 
			
		||||
The second Perlin layer is a temperature map, with values taken from
 | 
			
		||||
SPlizard's Snow Biomes mod so that the two will be compatible, since that mod
 | 
			
		||||
appears to be the standard now.  Those values are:
 | 
			
		||||
 | 
			
		||||
	temperature_seeddiff = 112
 | 
			
		||||
	temperature_octaves = 3
 | 
			
		||||
	temperature_persistence = 0.5
 | 
			
		||||
	temperature_scale = 150
 | 
			
		||||
 | 
			
		||||
The way Perlin values are used by this mod, in keeping with the snow mod's 
 | 
			
		||||
apparent methods, larger values returned by the Perlin function represent
 | 
			
		||||
*colder* temperatures.  In this mod, the following table gives a rough
 | 
			
		||||
approximation of how temperature maps to these values, normalized to
 | 
			
		||||
0.53 = 0 °C and +1.0 = -25 °C.
 | 
			
		||||
 | 
			
		||||
Perlin		Approx. Temperature
 | 
			
		||||
-1.0		 81 °C	( 178 °F)
 | 
			
		||||
-0.75		 68 °C	( 155 °F)
 | 
			
		||||
-0.56		 58 °C	( 136 °F)
 | 
			
		||||
-0.5		 55 °C	( 131 °F)
 | 
			
		||||
-0.25		 41 °C	( 107 °F)
 | 
			
		||||
-0.18		 38 °C	( 100 °F)
 | 
			
		||||
 0		 28 °C	(  83 °F)
 | 
			
		||||
 0.13		 21 °C	(  70 °F)
 | 
			
		||||
 0.25		 15 °C	(  59 °F)
 | 
			
		||||
 0.5		  2 °C	(  35 °F)
 | 
			
		||||
 0.53		  0 °C	(  32 °F)
 | 
			
		||||
 0.75		-12 °C	(  11 °F)
 | 
			
		||||
 0.86		-18 °C	(   0 °F)
 | 
			
		||||
 1.0		-25 °C	(- 13 °F)
 | 
			
		||||
 | 
			
		||||
Included in this table are even 0.25 steps in Perlin values along with some
 | 
			
		||||
common temperatures on both the Centigrade and Fahrenheit scales.  Note that
 | 
			
		||||
unless you're trying to model the Moon or perhaps Mercury in your mods/maps, 
 | 
			
		||||
you probably won't need to bother with Perlin values of less than -0.56 or so.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
================
 | 
			
		||||
Humidity Mapping
 | 
			
		||||
================
 | 
			
		||||
 | 
			
		||||
Last but not least is a moisture/humidity map.  Like the temperature map
 | 
			
		||||
above, Perlin values can be tested to determine the approximate humidity of
 | 
			
		||||
the *air* in the area.  This humidity map is basically the perlin layer used
 | 
			
		||||
for deserts.
 | 
			
		||||
 | 
			
		||||
A value of +1.0 is very moist (basically a thick fog, if it could be seen), a
 | 
			
		||||
value of roughly +0.25 represents the edge of a desert as usually seen in the
 | 
			
		||||
game, and a value of -1.0 is as dry as a bone.
 | 
			
		||||
 | 
			
		||||
This does not check for nearby water, just general air humidity, and that
 | 
			
		||||
being the case, nearby ground does not affect the reported humidity of a
 | 
			
		||||
region (because this isn't yet possible to calculate yet).  Use the near_nodes
 | 
			
		||||
and avoid_nodes parameters and their related options to check for water and
 | 
			
		||||
such.
 | 
			
		||||
 | 
			
		||||
The Perlin values use for this layer are:
 | 
			
		||||
 | 
			
		||||
	humidity_seeddiff = 9130
 | 
			
		||||
	humidity_octaves = 3
 | 
			
		||||
	humidity_persistence = 0.5
 | 
			
		||||
	humidity_scale = 250
 | 
			
		||||
 | 
			
		||||
And this particular one is mapped slightly differently from the others:
 | 
			
		||||
 | 
			
		||||
	noise3 = perlin3:get2d({x=p_top.x+150, y=p_top.z+50})
 | 
			
		||||
 | 
			
		||||
(Note the +150 and +50 offsets)
 | 
			
		||||
 | 
			
		||||
@@ -1,3 +0,0 @@
 | 
			
		||||
default
 | 
			
		||||
intllib?
 | 
			
		||||
 | 
			
		||||
@@ -1,735 +0,0 @@
 | 
			
		||||
-- Plantlife library mod by Vanessa Ezekowitz
 | 
			
		||||
--
 | 
			
		||||
-- License:  WTFPL
 | 
			
		||||
--
 | 
			
		||||
-- I got the temperature map idea from "hmmmm", values used for it came from
 | 
			
		||||
-- Splizard's snow mod.
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
-- Various settings - most of these probably won't need to be changed
 | 
			
		||||
 | 
			
		||||
plantslib = {}
 | 
			
		||||
 | 
			
		||||
plantslib.blocklist_aircheck = {}
 | 
			
		||||
plantslib.blocklist_no_aircheck = {}
 | 
			
		||||
 | 
			
		||||
plantslib.surface_nodes_aircheck = {}
 | 
			
		||||
plantslib.surface_nodes_no_aircheck = {}
 | 
			
		||||
 | 
			
		||||
plantslib.surfaceslist_aircheck = {}
 | 
			
		||||
plantslib.surfaceslist_no_aircheck = {}
 | 
			
		||||
 | 
			
		||||
plantslib.actioncount_aircheck = {}
 | 
			
		||||
plantslib.actioncount_no_aircheck = {}
 | 
			
		||||
 | 
			
		||||
plantslib.actionslist_aircheck = {}
 | 
			
		||||
plantslib.actionslist_no_aircheck = {}
 | 
			
		||||
 | 
			
		||||
plantslib.modpath = minetest.get_modpath("plants_lib")
 | 
			
		||||
 | 
			
		||||
plantslib.total_no_aircheck_calls = 0
 | 
			
		||||
 | 
			
		||||
-- Boilerplate to support localized strings if intllib mod is installed.
 | 
			
		||||
local S
 | 
			
		||||
if minetest.get_modpath("intllib") then
 | 
			
		||||
	S = intllib.Getter()
 | 
			
		||||
else
 | 
			
		||||
	S = function(s) return s end
 | 
			
		||||
end
 | 
			
		||||
plantslib.intllib = S
 | 
			
		||||
 | 
			
		||||
local DEBUG = false --... except if you want to spam the console with debugging info :-)
 | 
			
		||||
 | 
			
		||||
function plantslib:dbg(msg)
 | 
			
		||||
	if DEBUG then
 | 
			
		||||
		print("[Plantlife] "..msg)
 | 
			
		||||
		minetest.log("verbose", "[Plantlife] "..msg)
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
plantslib.plantlife_seed_diff = 329	-- needs to be global so other mods can see it
 | 
			
		||||
 | 
			
		||||
local perlin_octaves = 3
 | 
			
		||||
local perlin_persistence = 0.6
 | 
			
		||||
local perlin_scale = 100
 | 
			
		||||
 | 
			
		||||
local temperature_seeddiff = 112
 | 
			
		||||
local temperature_octaves = 3
 | 
			
		||||
local temperature_persistence = 0.5
 | 
			
		||||
local temperature_scale = 150
 | 
			
		||||
 | 
			
		||||
local humidity_seeddiff = 9130
 | 
			
		||||
local humidity_octaves = 3
 | 
			
		||||
local humidity_persistence = 0.5
 | 
			
		||||
local humidity_scale = 250
 | 
			
		||||
 | 
			
		||||
local time_scale = 1
 | 
			
		||||
local time_speed = tonumber(minetest.setting_get("time_speed"))
 | 
			
		||||
 | 
			
		||||
if time_speed and time_speed > 0 then
 | 
			
		||||
	time_scale = 72 / time_speed
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--PerlinNoise(seed, octaves, persistence, scale)
 | 
			
		||||
 | 
			
		||||
plantslib.perlin_temperature = PerlinNoise(temperature_seeddiff, temperature_octaves, temperature_persistence, temperature_scale)
 | 
			
		||||
plantslib.perlin_humidity = PerlinNoise(humidity_seeddiff, humidity_octaves, humidity_persistence, humidity_scale)
 | 
			
		||||
 | 
			
		||||
-- Local functions
 | 
			
		||||
 | 
			
		||||
function plantslib:is_node_loaded(node_pos)
 | 
			
		||||
	local n = minetest.get_node_or_nil(node_pos)
 | 
			
		||||
	if (not n) or (n.name == "ignore") then
 | 
			
		||||
		return false
 | 
			
		||||
	end
 | 
			
		||||
	return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function plantslib:set_defaults(biome)
 | 
			
		||||
	biome.seed_diff = biome.seed_diff or 0
 | 
			
		||||
	biome.min_elevation = biome.min_elevation or -31000
 | 
			
		||||
	biome.max_elevation = biome.max_elevation or 31000
 | 
			
		||||
	biome.temp_min = biome.temp_min or 1
 | 
			
		||||
	biome.temp_max = biome.temp_max or -1
 | 
			
		||||
	biome.humidity_min = biome.humidity_min or 1
 | 
			
		||||
	biome.humidity_max = biome.humidity_max or -1
 | 
			
		||||
	biome.plantlife_limit = biome.plantlife_limit or 0.1
 | 
			
		||||
	biome.near_nodes_vertical = biome.near_nodes_vertical or 1
 | 
			
		||||
 | 
			
		||||
-- specific to on-generate
 | 
			
		||||
 | 
			
		||||
	biome.neighbors = biome.neighbors or biome.surface
 | 
			
		||||
	biome.near_nodes_size = biome.near_nodes_size or 0
 | 
			
		||||
	biome.near_nodes_count = biome.near_nodes_count or 1
 | 
			
		||||
	biome.rarity = biome.rarity or 50
 | 
			
		||||
	biome.max_count = biome.max_count or 5
 | 
			
		||||
	if biome.check_air ~= false then biome.check_air = true end
 | 
			
		||||
 | 
			
		||||
-- specific to abm spawner
 | 
			
		||||
	biome.seed_diff = biome.seed_diff or 0
 | 
			
		||||
	biome.light_min = biome.light_min or 0
 | 
			
		||||
	biome.light_max = biome.light_max or 15
 | 
			
		||||
	biome.depth_max = biome.depth_max or 1
 | 
			
		||||
	biome.facedir = biome.facedir or 0
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function search_table(t, s)
 | 
			
		||||
	for i = 1, #t do
 | 
			
		||||
		if t[i] == s then return true end
 | 
			
		||||
	end
 | 
			
		||||
	return false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- register the list of surfaces to spawn stuff on, filtering out all duplicates.
 | 
			
		||||
-- separate the items by air-checking or non-air-checking map eval methods
 | 
			
		||||
 | 
			
		||||
function plantslib:register_generate_plant(biomedef, nodes_or_function_or_model)
 | 
			
		||||
 | 
			
		||||
	-- if calling code passes an undefined node for a surface or 
 | 
			
		||||
	-- as a node to be spawned, don't register an action for it.
 | 
			
		||||
 | 
			
		||||
	if type(nodes_or_function_or_model) == "string"
 | 
			
		||||
	  and string.find(nodes_or_function_or_model, ":")
 | 
			
		||||
	  and not minetest.registered_nodes[nodes_or_function_or_model] then
 | 
			
		||||
		plantslib:dbg("Warning: Ignored registration for undefined spawn node: "..dump(nodes_or_function_or_model))
 | 
			
		||||
		return
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	if type(nodes_or_function_or_model) == "string"
 | 
			
		||||
	  and not string.find(nodes_or_function_or_model, ":") then
 | 
			
		||||
		plantslib:dbg("Warning: Registered function call using deprecated string method: "..dump(nodes_or_function_or_model))
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	if biomedef.check_air == false then 
 | 
			
		||||
		plantslib:dbg("Register no-air-check mapgen hook: "..dump(nodes_or_function_or_model))
 | 
			
		||||
		plantslib.actionslist_no_aircheck[#plantslib.actionslist_no_aircheck + 1] = { biomedef, nodes_or_function_or_model }
 | 
			
		||||
		local s = biomedef.surface
 | 
			
		||||
		if type(s) == "string" then
 | 
			
		||||
			if s and (string.find(s, "^group:") or minetest.registered_nodes[s]) then
 | 
			
		||||
				if not search_table(plantslib.surfaceslist_no_aircheck, s) then
 | 
			
		||||
					plantslib.surfaceslist_no_aircheck[#plantslib.surfaceslist_no_aircheck + 1] = s
 | 
			
		||||
				end
 | 
			
		||||
			else
 | 
			
		||||
				plantslib:dbg("Warning: Ignored no-air-check registration for undefined surface node: "..dump(s))
 | 
			
		||||
			end
 | 
			
		||||
		else
 | 
			
		||||
			for i = 1, #biomedef.surface do
 | 
			
		||||
				local s = biomedef.surface[i]
 | 
			
		||||
				if s and (string.find(s, "^group:") or minetest.registered_nodes[s]) then
 | 
			
		||||
					if not search_table(plantslib.surfaceslist_no_aircheck, s) then
 | 
			
		||||
						plantslib.surfaceslist_no_aircheck[#plantslib.surfaceslist_no_aircheck + 1] = s
 | 
			
		||||
					end
 | 
			
		||||
				else
 | 
			
		||||
					plantslib:dbg("Warning: Ignored no-air-check registration for undefined surface node: "..dump(s))
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	else
 | 
			
		||||
		plantslib:dbg("Register with-air-checking mapgen hook: "..dump(nodes_or_function_or_model))
 | 
			
		||||
		plantslib.actionslist_aircheck[#plantslib.actionslist_aircheck + 1] = { biomedef, nodes_or_function_or_model }
 | 
			
		||||
		local s = biomedef.surface
 | 
			
		||||
		if type(s) == "string" then
 | 
			
		||||
			if s and (string.find(s, "^group:") or minetest.registered_nodes[s]) then
 | 
			
		||||
				if not search_table(plantslib.surfaceslist_aircheck, s) then
 | 
			
		||||
					plantslib.surfaceslist_aircheck[#plantslib.surfaceslist_aircheck + 1] = s
 | 
			
		||||
				end
 | 
			
		||||
			else
 | 
			
		||||
				plantslib:dbg("Warning: Ignored with-air-checking registration for undefined surface node: "..dump(s))
 | 
			
		||||
			end
 | 
			
		||||
		else
 | 
			
		||||
			for i = 1, #biomedef.surface do
 | 
			
		||||
				local s = biomedef.surface[i]
 | 
			
		||||
				if s and (string.find(s, "^group:") or minetest.registered_nodes[s]) then
 | 
			
		||||
					if not search_table(plantslib.surfaceslist_aircheck, s) then
 | 
			
		||||
						plantslib.surfaceslist_aircheck[#plantslib.surfaceslist_aircheck + 1] = s
 | 
			
		||||
					end
 | 
			
		||||
				else
 | 
			
		||||
					plantslib:dbg("Warning: Ignored with-air-checking registration for undefined surface node: "..dump(s))
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function plantslib:populate_surfaces(biome, nodes_or_function_or_model, snodes, checkair)
 | 
			
		||||
 | 
			
		||||
	plantslib:set_defaults(biome)
 | 
			
		||||
 | 
			
		||||
	-- filter stage 1 - find nodes from the supplied surfaces that are within the current biome.
 | 
			
		||||
 | 
			
		||||
	local in_biome_nodes = {}
 | 
			
		||||
	local perlin_fertile_area = minetest.get_perlin(biome.seed_diff, perlin_octaves, perlin_persistence, perlin_scale)
 | 
			
		||||
 | 
			
		||||
	for i = 1, #snodes do
 | 
			
		||||
		local pos = snodes[i]
 | 
			
		||||
		local p_top = { x = pos.x, y = pos.y + 1, z = pos.z }
 | 
			
		||||
		local noise1 = perlin_fertile_area:get2d({x=pos.x, y=pos.z})
 | 
			
		||||
		local noise2 = plantslib.perlin_temperature:get2d({x=pos.x, y=pos.z})
 | 
			
		||||
		local noise3 = plantslib.perlin_humidity:get2d({x=pos.x+150, y=pos.z+50})
 | 
			
		||||
		local biome_surfaces_string = dump(biome.surface)
 | 
			
		||||
		local surface_ok = false
 | 
			
		||||
 | 
			
		||||
		if not biome.depth then
 | 
			
		||||
			local dest_node = minetest.get_node(pos)
 | 
			
		||||
			if string.find(biome_surfaces_string, dest_node.name) then
 | 
			
		||||
				surface_ok = true
 | 
			
		||||
			else
 | 
			
		||||
				if string.find(biome_surfaces_string, "group:") then
 | 
			
		||||
					for j = 1, #biome.surface do
 | 
			
		||||
						if string.find(biome.surface[j], "^group:") 
 | 
			
		||||
						  and minetest.get_item_group(dest_node.name, biome.surface[j]) then
 | 
			
		||||
							surface_ok = true
 | 
			
		||||
							break
 | 
			
		||||
						end
 | 
			
		||||
					end
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		elseif not string.find(biome_surfaces_string, minetest.get_node({ x = pos.x, y = pos.y-biome.depth-1, z = pos.z }).name) then
 | 
			
		||||
			surface_ok = true
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		if surface_ok
 | 
			
		||||
		  and (not checkair or minetest.get_node(p_top).name == "air")
 | 
			
		||||
		  and pos.y >= biome.min_elevation
 | 
			
		||||
		  and pos.y <= biome.max_elevation
 | 
			
		||||
		  and noise1 > biome.plantlife_limit
 | 
			
		||||
		  and noise2 <= biome.temp_min
 | 
			
		||||
		  and noise2 >= biome.temp_max
 | 
			
		||||
		  and noise3 <= biome.humidity_min
 | 
			
		||||
		  and noise3 >= biome.humidity_max
 | 
			
		||||
		  and (not biome.ncount or #(minetest.find_nodes_in_area({x=pos.x-1, y=pos.y, z=pos.z-1}, {x=pos.x+1, y=pos.y, z=pos.z+1}, biome.neighbors)) > biome.ncount)
 | 
			
		||||
		  and (not biome.near_nodes or #(minetest.find_nodes_in_area({x=pos.x-biome.near_nodes_size, y=pos.y-biome.near_nodes_vertical, z=pos.z-biome.near_nodes_size}, {x=pos.x+biome.near_nodes_size, y=pos.y+biome.near_nodes_vertical, z=pos.z+biome.near_nodes_size}, biome.near_nodes)) >= biome.near_nodes_count)
 | 
			
		||||
		  and math.random(1,100) > biome.rarity
 | 
			
		||||
		  and (not biome.below_nodes or string.find(dump(biome.below_nodes), minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name) )
 | 
			
		||||
		  then
 | 
			
		||||
			in_biome_nodes[#in_biome_nodes + 1] = pos
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	-- filter stage 2 - find places within that biome area to place the plants.
 | 
			
		||||
 | 
			
		||||
	local num_in_biome_nodes = #in_biome_nodes
 | 
			
		||||
 | 
			
		||||
	if num_in_biome_nodes > 0 then
 | 
			
		||||
		for i = 1, math.min(biome.max_count, num_in_biome_nodes) do
 | 
			
		||||
			local tries = 0
 | 
			
		||||
			local spawned = false
 | 
			
		||||
			while tries < 2 and not spawned do
 | 
			
		||||
				local pos = in_biome_nodes[math.random(1, num_in_biome_nodes)]
 | 
			
		||||
				if biome.spawn_replace_node then
 | 
			
		||||
					pos.y = pos.y-1
 | 
			
		||||
				end
 | 
			
		||||
				local p_top = { x = pos.x, y = pos.y + 1, z = pos.z }
 | 
			
		||||
 | 
			
		||||
				if not (biome.avoid_nodes and biome.avoid_radius and minetest.find_node_near(p_top, biome.avoid_radius + math.random(-1.5,2), biome.avoid_nodes)) then
 | 
			
		||||
					if biome.delete_above then
 | 
			
		||||
						minetest.remove_node(p_top)
 | 
			
		||||
						minetest.remove_node({x=p_top.x, y=p_top.y+1, z=p_top.z})
 | 
			
		||||
					end
 | 
			
		||||
 | 
			
		||||
					if biome.delete_above_surround then
 | 
			
		||||
						minetest.remove_node({x=p_top.x-1, y=p_top.y, z=p_top.z})
 | 
			
		||||
						minetest.remove_node({x=p_top.x+1, y=p_top.y, z=p_top.z})
 | 
			
		||||
						minetest.remove_node({x=p_top.x,   y=p_top.y, z=p_top.z-1})
 | 
			
		||||
						minetest.remove_node({x=p_top.x,   y=p_top.y, z=p_top.z+1})
 | 
			
		||||
 | 
			
		||||
						minetest.remove_node({x=p_top.x-1, y=p_top.y+1, z=p_top.z})
 | 
			
		||||
						minetest.remove_node({x=p_top.x+1, y=p_top.y+1, z=p_top.z})
 | 
			
		||||
						minetest.remove_node({x=p_top.x,   y=p_top.y+1, z=p_top.z-1})
 | 
			
		||||
						minetest.remove_node({x=p_top.x,   y=p_top.y+1, z=p_top.z+1})
 | 
			
		||||
					end
 | 
			
		||||
 | 
			
		||||
					if biome.spawn_replace_node then
 | 
			
		||||
						minetest.remove_node(pos)
 | 
			
		||||
					end
 | 
			
		||||
 | 
			
		||||
					local objtype = type(nodes_or_function_or_model)
 | 
			
		||||
 | 
			
		||||
					if objtype == "table" then
 | 
			
		||||
						if nodes_or_function_or_model.axiom then
 | 
			
		||||
							plantslib:generate_tree(pos, nodes_or_function_or_model)
 | 
			
		||||
							spawned = true
 | 
			
		||||
						else
 | 
			
		||||
							local fdir = nil
 | 
			
		||||
							if biome.random_facedir then
 | 
			
		||||
								fdir = math.random(biome.random_facedir[1], biome.random_facedir[2])
 | 
			
		||||
							end
 | 
			
		||||
							minetest.set_node(p_top, { name = nodes_or_function_or_model[math.random(#nodes_or_function_or_model)], param2 = fdir })
 | 
			
		||||
							spawned = true
 | 
			
		||||
						end
 | 
			
		||||
					elseif objtype == "string" and
 | 
			
		||||
					  minetest.registered_nodes[nodes_or_function_or_model] then
 | 
			
		||||
						local fdir = nil
 | 
			
		||||
						if biome.random_facedir then
 | 
			
		||||
							fdir = math.random(biome.random_facedir[1], biome.random_facedir[2])
 | 
			
		||||
						end
 | 
			
		||||
						minetest.set_node(p_top, { name = nodes_or_function_or_model, param2 = fdir })
 | 
			
		||||
						spawned = true
 | 
			
		||||
					elseif objtype == "function" then
 | 
			
		||||
						nodes_or_function_or_model(pos)
 | 
			
		||||
						spawned = true
 | 
			
		||||
					elseif objtype == "string" and pcall(loadstring(("return %s(...)"):
 | 
			
		||||
						format(nodes_or_function_or_model)),pos) then
 | 
			
		||||
						spawned = true
 | 
			
		||||
					else
 | 
			
		||||
						plantslib:dbg("Warning: Ignored invalid definition for object "..dump(nodes_or_function_or_model).." that was pointed at {"..dump(pos).."}")
 | 
			
		||||
					end
 | 
			
		||||
				else
 | 
			
		||||
					tries = tries + 1
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Primary mapgen spawner, for mods that can work with air checking enabled on
 | 
			
		||||
-- a surface during the initial map read stage.
 | 
			
		||||
 | 
			
		||||
function plantslib:generate_block_with_air_checking()
 | 
			
		||||
	if #plantslib.blocklist_aircheck > 0 then
 | 
			
		||||
 | 
			
		||||
		local minp =		plantslib.blocklist_aircheck[1][1]
 | 
			
		||||
		local maxp =		plantslib.blocklist_aircheck[1][2]
 | 
			
		||||
 | 
			
		||||
		-- use the block hash as a unique key into the surface nodes
 | 
			
		||||
		-- tables, so that we can write the tables thread-safely.
 | 
			
		||||
 | 
			
		||||
		local blockhash =	minetest.hash_node_position(minp)
 | 
			
		||||
 | 
			
		||||
		if not plantslib.surface_nodes_aircheck.blockhash then
 | 
			
		||||
 | 
			
		||||
			if type(minetest.find_nodes_in_area_under_air) == "function" then -- use newer API call
 | 
			
		||||
				plantslib.surface_nodes_aircheck.blockhash =
 | 
			
		||||
					minetest.find_nodes_in_area_under_air(minp, maxp, plantslib.surfaceslist_aircheck)
 | 
			
		||||
			else
 | 
			
		||||
				local search_area = minetest.find_nodes_in_area(minp, maxp, plantslib.surfaceslist_aircheck)
 | 
			
		||||
 | 
			
		||||
				-- search the generated block for air-bounded surfaces the slow way.
 | 
			
		||||
 | 
			
		||||
				plantslib.surface_nodes_aircheck.blockhash = {}
 | 
			
		||||
 | 
			
		||||
				for i = 1, #search_area do
 | 
			
		||||
				local pos = search_area[i]
 | 
			
		||||
					local p_top = { x=pos.x, y=pos.y+1, z=pos.z }
 | 
			
		||||
					if minetest.get_node(p_top).name == "air" then
 | 
			
		||||
						plantslib.surface_nodes_aircheck.blockhash[#plantslib.surface_nodes_aircheck.blockhash + 1] = pos
 | 
			
		||||
					end
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
			plantslib.actioncount_aircheck.blockhash = 1
 | 
			
		||||
 | 
			
		||||
		else
 | 
			
		||||
			if plantslib.actioncount_aircheck.blockhash <= #plantslib.actionslist_aircheck then
 | 
			
		||||
				-- [1] is biome, [2] is node/function/model
 | 
			
		||||
				plantslib:populate_surfaces(
 | 
			
		||||
					plantslib.actionslist_aircheck[plantslib.actioncount_aircheck.blockhash][1],
 | 
			
		||||
					plantslib.actionslist_aircheck[plantslib.actioncount_aircheck.blockhash][2],
 | 
			
		||||
					plantslib.surface_nodes_aircheck.blockhash, true)
 | 
			
		||||
				plantslib.actioncount_aircheck.blockhash = plantslib.actioncount_aircheck.blockhash + 1
 | 
			
		||||
			else
 | 
			
		||||
				if plantslib.surface_nodes_aircheck.blockhash then
 | 
			
		||||
					table.remove(plantslib.blocklist_aircheck, 1)
 | 
			
		||||
					plantslib.surface_nodes_aircheck.blockhash = nil
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Secondary mapgen spawner, for mods that require disabling of
 | 
			
		||||
-- checking for air during the initial map read stage.
 | 
			
		||||
 | 
			
		||||
function plantslib:generate_block_no_aircheck()
 | 
			
		||||
	if #plantslib.blocklist_no_aircheck > 0 then
 | 
			
		||||
 | 
			
		||||
		local minp =		plantslib.blocklist_no_aircheck[1][1]
 | 
			
		||||
		local maxp =		plantslib.blocklist_no_aircheck[1][2]
 | 
			
		||||
 | 
			
		||||
		local blockhash =	minetest.hash_node_position(minp)
 | 
			
		||||
 | 
			
		||||
		if not plantslib.surface_nodes_no_aircheck.blockhash then
 | 
			
		||||
 | 
			
		||||
			-- directly read the block to be searched into the chunk cache
 | 
			
		||||
 | 
			
		||||
			plantslib.surface_nodes_no_aircheck.blockhash =
 | 
			
		||||
				minetest.find_nodes_in_area(minp, maxp, plantslib.surfaceslist_no_aircheck)
 | 
			
		||||
			plantslib.actioncount_no_aircheck.blockhash = 1
 | 
			
		||||
 | 
			
		||||
		else
 | 
			
		||||
			if plantslib.actioncount_no_aircheck.blockhash <= #plantslib.actionslist_no_aircheck then
 | 
			
		||||
				plantslib:populate_surfaces(
 | 
			
		||||
					plantslib.actionslist_no_aircheck[plantslib.actioncount_no_aircheck.blockhash][1],
 | 
			
		||||
					plantslib.actionslist_no_aircheck[plantslib.actioncount_no_aircheck.blockhash][2],
 | 
			
		||||
					plantslib.surface_nodes_no_aircheck.blockhash, false)
 | 
			
		||||
				plantslib.actioncount_no_aircheck.blockhash = plantslib.actioncount_no_aircheck.blockhash + 1
 | 
			
		||||
			else
 | 
			
		||||
				if plantslib.surface_nodes_no_aircheck.blockhash then
 | 
			
		||||
					table.remove(plantslib.blocklist_no_aircheck, 1)
 | 
			
		||||
					plantslib.surface_nodes_no_aircheck.blockhash = nil
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- "Record" the chunks being generated by the core mapgen
 | 
			
		||||
 | 
			
		||||
minetest.register_on_generated(function(minp, maxp, blockseed)
 | 
			
		||||
	plantslib.blocklist_aircheck[#plantslib.blocklist_aircheck + 1] = { minp, maxp }
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
minetest.register_on_generated(function(minp, maxp, blockseed)
 | 
			
		||||
	plantslib.blocklist_no_aircheck[#plantslib.blocklist_no_aircheck + 1] = { minp, maxp }
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
-- "Play" them back, populating them with new stuff in the process
 | 
			
		||||
 | 
			
		||||
minetest.register_globalstep(function(dtime)
 | 
			
		||||
	if dtime < 0.2 and    -- don't attempt to populate if lag is already too high
 | 
			
		||||
	  (#plantslib.blocklist_aircheck > 0 or #plantslib.blocklist_no_aircheck > 0) then
 | 
			
		||||
		plantslib.globalstep_start_time = minetest.get_us_time()
 | 
			
		||||
		plantslib.globalstep_runtime = 0
 | 
			
		||||
		while (#plantslib.blocklist_aircheck > 0 or #plantslib.blocklist_no_aircheck > 0)
 | 
			
		||||
		  and plantslib.globalstep_runtime < 200000 do  -- 0.2 seconds, in uS.
 | 
			
		||||
			if #plantslib.blocklist_aircheck > 0 then
 | 
			
		||||
				plantslib:generate_block_with_air_checking()
 | 
			
		||||
			end
 | 
			
		||||
			if #plantslib.blocklist_no_aircheck > 0 then
 | 
			
		||||
				plantslib:generate_block_no_aircheck()
 | 
			
		||||
			end
 | 
			
		||||
			plantslib.globalstep_runtime = minetest.get_us_time() - plantslib.globalstep_start_time
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
-- Play out the entire log all at once on shutdown
 | 
			
		||||
-- to prevent unpopulated map areas
 | 
			
		||||
 | 
			
		||||
minetest.register_on_shutdown(function()
 | 
			
		||||
	print("[plants_lib] Stand by, playing out the rest of the aircheck mapblock log")
 | 
			
		||||
	print("(there are "..#plantslib.blocklist_aircheck.." entries)...")
 | 
			
		||||
	while true do
 | 
			
		||||
		plantslib:generate_block_with_air_checking(0.1)
 | 
			
		||||
		if #plantslib.blocklist_aircheck == 0 then return end
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
minetest.register_on_shutdown(function()
 | 
			
		||||
	print("[plants_lib] Stand by, playing out the rest of the no-aircheck mapblock log")
 | 
			
		||||
	print("(there are "..#plantslib.blocklist_aircheck.." entries)...")
 | 
			
		||||
	while true do
 | 
			
		||||
		plantslib:generate_block_no_aircheck(0.1)
 | 
			
		||||
		if #plantslib.blocklist_no_aircheck == 0 then return end
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
-- The spawning ABM
 | 
			
		||||
 | 
			
		||||
function plantslib:spawn_on_surfaces(sd,sp,sr,sc,ss,sa)
 | 
			
		||||
 | 
			
		||||
	local biome = {}
 | 
			
		||||
 | 
			
		||||
	if type(sd) ~= "table" then
 | 
			
		||||
		biome.spawn_delay = sd	-- old api expects ABM interval param here.
 | 
			
		||||
		biome.spawn_plants = {sp}
 | 
			
		||||
		biome.avoid_radius = sr
 | 
			
		||||
		biome.spawn_chance = sc
 | 
			
		||||
		biome.spawn_surfaces = {ss}
 | 
			
		||||
		biome.avoid_nodes = sa
 | 
			
		||||
	else
 | 
			
		||||
		biome = sd
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	if biome.spawn_delay*time_scale >= 1 then
 | 
			
		||||
		biome.interval = biome.spawn_delay*time_scale
 | 
			
		||||
	else
 | 
			
		||||
		biome.interval = 1
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	plantslib:set_defaults(biome)
 | 
			
		||||
	biome.spawn_plants_count = #(biome.spawn_plants)
 | 
			
		||||
 | 
			
		||||
	minetest.register_abm({
 | 
			
		||||
		nodenames = biome.spawn_surfaces,
 | 
			
		||||
		interval = biome.interval,
 | 
			
		||||
		chance = biome.spawn_chance,
 | 
			
		||||
		neighbors = biome.neighbors,
 | 
			
		||||
		action = function(pos, node, active_object_count, active_object_count_wider)
 | 
			
		||||
			local p_top = { x = pos.x, y = pos.y + 1, z = pos.z }	
 | 
			
		||||
			local n_top = minetest.get_node(p_top)
 | 
			
		||||
			local perlin_fertile_area = minetest.get_perlin(biome.seed_diff, perlin_octaves, perlin_persistence, perlin_scale)
 | 
			
		||||
			local noise1 = perlin_fertile_area:get2d({x=p_top.x, y=p_top.z})
 | 
			
		||||
			local noise2 = plantslib.perlin_temperature:get2d({x=p_top.x, y=p_top.z})
 | 
			
		||||
			local noise3 = plantslib.perlin_humidity:get2d({x=p_top.x+150, y=p_top.z+50})
 | 
			
		||||
			if noise1 > biome.plantlife_limit 
 | 
			
		||||
			  and noise2 <= biome.temp_min
 | 
			
		||||
			  and noise2 >= biome.temp_max
 | 
			
		||||
			  and noise3 <= biome.humidity_min
 | 
			
		||||
			  and noise3 >= biome.humidity_max
 | 
			
		||||
			  and plantslib:is_node_loaded(p_top) then
 | 
			
		||||
				local n_light = minetest.get_node_light(p_top, nil)
 | 
			
		||||
				if not (biome.avoid_nodes and biome.avoid_radius and minetest.find_node_near(p_top, biome.avoid_radius + math.random(-1.5,2), biome.avoid_nodes))
 | 
			
		||||
				  and n_light >= biome.light_min
 | 
			
		||||
				  and n_light <= biome.light_max
 | 
			
		||||
				  and (not(biome.neighbors and biome.ncount) or #(minetest.find_nodes_in_area({x=pos.x-1, y=pos.y, z=pos.z-1}, {x=pos.x+1, y=pos.y, z=pos.z+1}, biome.neighbors)) > biome.ncount )
 | 
			
		||||
				  and (not(biome.near_nodes and biome.near_nodes_count and biome.near_nodes_size) or #(minetest.find_nodes_in_area({x=pos.x-biome.near_nodes_size, y=pos.y-biome.near_nodes_vertical, z=pos.z-biome.near_nodes_size}, {x=pos.x+biome.near_nodes_size, y=pos.y+biome.near_nodes_vertical, z=pos.z+biome.near_nodes_size}, biome.near_nodes)) >= biome.near_nodes_count)
 | 
			
		||||
				  and (not(biome.air_count and biome.air_size) or #(minetest.find_nodes_in_area({x=p_top.x-biome.air_size, y=p_top.y, z=p_top.z-biome.air_size}, {x=p_top.x+biome.air_size, y=p_top.y, z=p_top.z+biome.air_size}, "air")) >= biome.air_count)
 | 
			
		||||
				  and pos.y >= biome.min_elevation
 | 
			
		||||
				  and pos.y <= biome.max_elevation
 | 
			
		||||
				  then
 | 
			
		||||
					local walldir = plantslib:find_adjacent_wall(p_top, biome.verticals_list, biome.choose_random_wall)
 | 
			
		||||
					if biome.alt_wallnode and walldir then
 | 
			
		||||
						if n_top.name == "air" then
 | 
			
		||||
							minetest.set_node(p_top, { name = biome.alt_wallnode, param2 = walldir })
 | 
			
		||||
						end
 | 
			
		||||
					else
 | 
			
		||||
						local currentsurface = minetest.get_node(pos).name
 | 
			
		||||
						if currentsurface ~= "default:water_source"
 | 
			
		||||
						  or (currentsurface == "default:water_source" and #(minetest.find_nodes_in_area({x=pos.x, y=pos.y-biome.depth_max-1, z=pos.z}, {x=pos.x, y=pos.y, z=pos.z}, {"default:dirt", "default:dirt_with_grass", "default:sand"})) > 0 )
 | 
			
		||||
						  then
 | 
			
		||||
							local rnd = math.random(1, biome.spawn_plants_count)
 | 
			
		||||
							local plant_to_spawn = biome.spawn_plants[rnd]
 | 
			
		||||
							local fdir = biome.facedir
 | 
			
		||||
							if biome.random_facedir then
 | 
			
		||||
								fdir = math.random(biome.random_facedir[1],biome.random_facedir[2])
 | 
			
		||||
							end
 | 
			
		||||
							if type(biome.spawn_plants) == "string" then
 | 
			
		||||
								assert(loadstring(biome.spawn_plants.."(...)"))(pos)
 | 
			
		||||
							elseif not biome.spawn_on_side and not biome.spawn_on_bottom and not biome.spawn_replace_node then
 | 
			
		||||
								if n_top.name == "air" then
 | 
			
		||||
									minetest.set_node(p_top, { name = plant_to_spawn, param2 = fdir })
 | 
			
		||||
								end
 | 
			
		||||
							elseif biome.spawn_replace_node then
 | 
			
		||||
								minetest.set_node(pos, { name = plant_to_spawn, param2 = fdir })
 | 
			
		||||
 | 
			
		||||
							elseif biome.spawn_on_side then
 | 
			
		||||
								local onside = plantslib:find_open_side(pos)
 | 
			
		||||
								if onside then 
 | 
			
		||||
									minetest.set_node(onside.newpos, { name = plant_to_spawn, param2 = onside.facedir })
 | 
			
		||||
								end
 | 
			
		||||
							elseif biome.spawn_on_bottom then
 | 
			
		||||
								if minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name == "air" then
 | 
			
		||||
									minetest.set_node({x=pos.x, y=pos.y-1, z=pos.z}, { name = plant_to_spawn, param2 = fdir} )
 | 
			
		||||
								end
 | 
			
		||||
							end
 | 
			
		||||
						end
 | 
			
		||||
					end
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	})
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- The growing ABM
 | 
			
		||||
 | 
			
		||||
function plantslib:grow_plants(opts)
 | 
			
		||||
 | 
			
		||||
	local options = opts
 | 
			
		||||
 | 
			
		||||
	options.height_limit = options.height_limit or 5
 | 
			
		||||
	options.ground_nodes = options.ground_nodes or { "default:dirt_with_grass" }
 | 
			
		||||
	options.grow_nodes = options.grow_nodes or { "default:dirt_with_grass" }
 | 
			
		||||
	options.seed_diff = options.seed_diff or 0
 | 
			
		||||
 | 
			
		||||
	if options.grow_delay*time_scale >= 1 then
 | 
			
		||||
		options.interval = options.grow_delay*time_scale
 | 
			
		||||
	else
 | 
			
		||||
		options.interval = 1
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	minetest.register_abm({
 | 
			
		||||
		nodenames = { options.grow_plant },
 | 
			
		||||
		interval = options.interval,
 | 
			
		||||
		chance = options.grow_chance,
 | 
			
		||||
		action = function(pos, node, active_object_count, active_object_count_wider)
 | 
			
		||||
			local p_top = {x=pos.x, y=pos.y+1, z=pos.z}
 | 
			
		||||
			local p_bot = {x=pos.x, y=pos.y-1, z=pos.z}
 | 
			
		||||
			local n_top = minetest.get_node(p_top)
 | 
			
		||||
			local n_bot = minetest.get_node(p_bot)
 | 
			
		||||
			local root_node = minetest.get_node({x=pos.x, y=pos.y-options.height_limit, z=pos.z})
 | 
			
		||||
			local walldir = nil
 | 
			
		||||
			if options.need_wall and options.verticals_list then
 | 
			
		||||
				walldir = plantslib:find_adjacent_wall(p_top, options.verticals_list, options.choose_random_wall)
 | 
			
		||||
			end
 | 
			
		||||
			if (n_top.name == "air" or n_top.name == "default:snow")
 | 
			
		||||
			  and (not options.need_wall or (options.need_wall and walldir)) then
 | 
			
		||||
				-- corner case for changing short junglegrass
 | 
			
		||||
				-- to dry shrub in desert
 | 
			
		||||
				if n_bot.name == options.dry_early_node and options.grow_plant == "junglegrass:short" then
 | 
			
		||||
					minetest.set_node(pos, { name = "default:dry_shrub" })
 | 
			
		||||
 | 
			
		||||
				elseif options.grow_vertically and walldir then
 | 
			
		||||
					if plantslib:search_downward(pos, options.height_limit, options.ground_nodes) then
 | 
			
		||||
						minetest.set_node(p_top, { name = options.grow_plant, param2 = walldir})
 | 
			
		||||
					end
 | 
			
		||||
 | 
			
		||||
				elseif not options.grow_result and not options.grow_function then
 | 
			
		||||
					minetest.remove_node(pos)
 | 
			
		||||
 | 
			
		||||
				else
 | 
			
		||||
					plantslib:replace_object(pos, options.grow_result, options.grow_function, options.facedir, options.seed_diff)
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	})
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Function to decide how to replace a plant - either grow it, replace it with
 | 
			
		||||
-- a tree, run a function, or die with an error.
 | 
			
		||||
 | 
			
		||||
function plantslib:replace_object(pos, replacement, grow_function, walldir, seeddiff)
 | 
			
		||||
	local growtype = type(grow_function)
 | 
			
		||||
	if growtype == "table" then
 | 
			
		||||
		minetest.remove_node(pos)
 | 
			
		||||
		plantslib:grow_tree(pos, grow_function)
 | 
			
		||||
		return
 | 
			
		||||
	elseif growtype == "function" then
 | 
			
		||||
		local perlin_fertile_area = minetest.get_perlin(seeddiff, perlin_octaves, perlin_persistence, perlin_scale)
 | 
			
		||||
		local noise1 = perlin_fertile_area:get2d({x=pos.x, y=pos.z})
 | 
			
		||||
		local noise2 = plantslib.perlin_temperature:get2d({x=pos.x, y=pos.z})
 | 
			
		||||
		grow_function(pos,noise1,noise2,walldir)
 | 
			
		||||
		return
 | 
			
		||||
	elseif growtype == "string" then
 | 
			
		||||
		local perlin_fertile_area = minetest.get_perlin(seeddiff, perlin_octaves, perlin_persistence, perlin_scale)
 | 
			
		||||
		local noise1 = perlin_fertile_area:get2d({x=pos.x, y=pos.z})
 | 
			
		||||
		local noise2 = plantslib.perlin_temperature:get2d({x=pos.x, y=pos.z})
 | 
			
		||||
		assert(loadstring(grow_function.."(...)"))(pos,noise1,noise2,walldir)
 | 
			
		||||
		return
 | 
			
		||||
	elseif growtype == "nil" then
 | 
			
		||||
		minetest.set_node(pos, { name = replacement, param2 = walldir})
 | 
			
		||||
		return
 | 
			
		||||
	elseif growtype ~= "nil" and growtype ~= "string" and growtype ~= "table" then
 | 
			
		||||
		error("Invalid grow function "..dump(grow_function).." used on object at ("..dump(pos)..")")
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- function to decide if a node has a wall that's in verticals_list{}
 | 
			
		||||
-- returns wall direction of valid node, or nil if invalid.
 | 
			
		||||
 | 
			
		||||
function plantslib:find_adjacent_wall(pos, verticals, randomflag)
 | 
			
		||||
	local verts = dump(verticals)
 | 
			
		||||
	if randomflag then
 | 
			
		||||
		local walltab = {}
 | 
			
		||||
		
 | 
			
		||||
		if string.find(verts, minetest.get_node({ x=pos.x-1, y=pos.y, z=pos.z   }).name) then walltab[#walltab + 1] = 3 end
 | 
			
		||||
		if string.find(verts, minetest.get_node({ x=pos.x+1, y=pos.y, z=pos.z   }).name) then walltab[#walltab + 1] = 2 end
 | 
			
		||||
		if string.find(verts, minetest.get_node({ x=pos.x  , y=pos.y, z=pos.z-1 }).name) then walltab[#walltab + 1] = 5 end
 | 
			
		||||
		if string.find(verts, minetest.get_node({ x=pos.x  , y=pos.y, z=pos.z+1 }).name) then walltab[#walltab + 1] = 4 end
 | 
			
		||||
 | 
			
		||||
		if #walltab > 0 then return walltab[math.random(1, #walltab)] end
 | 
			
		||||
 | 
			
		||||
	else
 | 
			
		||||
		if string.find(verts, minetest.get_node({ x=pos.x-1, y=pos.y, z=pos.z   }).name) then return 3 end
 | 
			
		||||
		if string.find(verts, minetest.get_node({ x=pos.x+1, y=pos.y, z=pos.z   }).name) then return 2 end
 | 
			
		||||
		if string.find(verts, minetest.get_node({ x=pos.x  , y=pos.y, z=pos.z-1 }).name) then return 5 end
 | 
			
		||||
		if string.find(verts, minetest.get_node({ x=pos.x  , y=pos.y, z=pos.z+1 }).name) then return 4 end
 | 
			
		||||
	end
 | 
			
		||||
	return nil
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Function to search downward from the given position, looking for the first
 | 
			
		||||
-- node that matches the ground table.  Returns the new position, or nil if
 | 
			
		||||
-- height limit is exceeded before finding it.
 | 
			
		||||
 | 
			
		||||
function plantslib:search_downward(pos, heightlimit, ground)
 | 
			
		||||
	for i = 0, heightlimit do
 | 
			
		||||
		if string.find(dump(ground), minetest.get_node({x=pos.x, y=pos.y-i, z = pos.z}).name) then
 | 
			
		||||
			return {x=pos.x, y=pos.y-i, z = pos.z}
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
	return false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function plantslib:find_open_side(pos)
 | 
			
		||||
	if minetest.get_node({ x=pos.x-1, y=pos.y, z=pos.z }).name == "air" then
 | 
			
		||||
		return {newpos = { x=pos.x-1, y=pos.y, z=pos.z }, facedir = 2}
 | 
			
		||||
	end
 | 
			
		||||
	if minetest.get_node({ x=pos.x+1, y=pos.y, z=pos.z }).name == "air" then
 | 
			
		||||
		return {newpos = { x=pos.x+1, y=pos.y, z=pos.z }, facedir = 3}
 | 
			
		||||
	end
 | 
			
		||||
	if minetest.get_node({ x=pos.x, y=pos.y, z=pos.z-1 }).name == "air" then
 | 
			
		||||
		return {newpos = { x=pos.x, y=pos.y, z=pos.z-1 }, facedir = 4}
 | 
			
		||||
	end
 | 
			
		||||
	if minetest.get_node({ x=pos.x, y=pos.y, z=pos.z+1 }).name == "air" then
 | 
			
		||||
		return {newpos = { x=pos.x, y=pos.y, z=pos.z+1 }, facedir = 5}
 | 
			
		||||
	end
 | 
			
		||||
	return nil
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- spawn_tree() on generate is routed through here so that other mods can hook
 | 
			
		||||
-- into it.
 | 
			
		||||
 | 
			
		||||
function plantslib:generate_tree(pos, nodes_or_function_or_model)
 | 
			
		||||
	minetest.spawn_tree(pos, nodes_or_function_or_model)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- and this one's for the call used in the growing code
 | 
			
		||||
 | 
			
		||||
function plantslib:grow_tree(pos, nodes_or_function_or_model)
 | 
			
		||||
	minetest.spawn_tree(pos, nodes_or_function_or_model)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Check for infinite stacks
 | 
			
		||||
 | 
			
		||||
if minetest.get_modpath("unified_inventory") or not minetest.setting_getbool("creative_mode") then
 | 
			
		||||
	plantslib.expect_infinite_stacks = false
 | 
			
		||||
else
 | 
			
		||||
	plantslib.expect_infinite_stacks = true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- read a field from a node's definition
 | 
			
		||||
 | 
			
		||||
function plantslib:get_nodedef_field(nodename, fieldname)
 | 
			
		||||
	if not minetest.registered_nodes[nodename] then
 | 
			
		||||
		return nil
 | 
			
		||||
	end
 | 
			
		||||
	return minetest.registered_nodes[nodename][fieldname]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
print("[Plants Lib] Loaded")
 | 
			
		||||
 | 
			
		||||
minetest.after(0, function()
 | 
			
		||||
	print("[Plants Lib] Registered a total of "..(#plantslib.surfaceslist_aircheck)+(#plantslib.surfaceslist_no_aircheck).." surface types to be evaluated, spread")
 | 
			
		||||
	print("[Plants Lib] across "..#plantslib.actionslist_aircheck.." actions with air-checking and "..#plantslib.actionslist_no_aircheck.." actions without.")
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
@@ -1,5 +0,0 @@
 | 
			
		||||
# Translation by Xanthin
 | 
			
		||||
 | 
			
		||||
someone = jemand
 | 
			
		||||
Sorry, %s owns that spot. = Entschuldige, %s gehoert diese Stelle.
 | 
			
		||||
[Plantlife Library] Loaded = [Plantlife Library] Geladen
 | 
			
		||||
@@ -1,5 +0,0 @@
 | 
			
		||||
# Template
 | 
			
		||||
 | 
			
		||||
someone = quelqu'un
 | 
			
		||||
Sorry, %s owns that spot. = Désolé, %s possède cet endroit.
 | 
			
		||||
[Plantlife Library] Loaded = [Librairie Plantlife] Chargée.
 | 
			
		||||
@@ -1,5 +0,0 @@
 | 
			
		||||
# Template
 | 
			
		||||
 | 
			
		||||
someone = 
 | 
			
		||||
Sorry, %s owns that spot. = 
 | 
			
		||||
[Plantlife Library] Loaded = 
 | 
			
		||||
@@ -1,5 +0,0 @@
 | 
			
		||||
# Turkish translation by mahmutelmas06
 | 
			
		||||
 | 
			
		||||
someone = birisi
 | 
			
		||||
Sorry, %s owns that spot. = Üzgünüm, buranın sahibi %s.
 | 
			
		||||
[Plantlife Library] Loaded = [Plantlife Library] yüklendi
 | 
			
		||||
@@ -1,2 +1,2 @@
 | 
			
		||||
plants_lib
 | 
			
		||||
biome_lib
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
-- This file supplies poison ivy for the plantlife modpack
 | 
			
		||||
-- Last revision:  2013-01-24
 | 
			
		||||
 | 
			
		||||
local S = plantslib.intllib
 | 
			
		||||
local S = biome_lib.intllib
 | 
			
		||||
 | 
			
		||||
local SPAWN_DELAY = 1000
 | 
			
		||||
local SPAWN_CHANCE = 200
 | 
			
		||||
@@ -69,7 +69,7 @@ minetest.register_node('poisonivy:climbing', {
 | 
			
		||||
	buildable_to = true,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
plantslib:spawn_on_surfaces({
 | 
			
		||||
biome_lib:spawn_on_surfaces({
 | 
			
		||||
	spawn_delay = SPAWN_DELAY,
 | 
			
		||||
	spawn_plants = {"poisonivy:seedling"},
 | 
			
		||||
	avoid_radius = 10,
 | 
			
		||||
@@ -82,7 +82,7 @@ plantslib:spawn_on_surfaces({
 | 
			
		||||
	verticals_list = walls_list
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
plantslib:grow_plants({
 | 
			
		||||
biome_lib:grow_plants({
 | 
			
		||||
	grow_delay = SPAWN_DELAY,
 | 
			
		||||
	grow_chance = GROW_CHANCE,
 | 
			
		||||
	grow_plant = "poisonivy:seedling",
 | 
			
		||||
@@ -90,7 +90,7 @@ plantslib:grow_plants({
 | 
			
		||||
	grow_nodes = {"default:dirt_with_grass"}
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
plantslib:grow_plants({
 | 
			
		||||
biome_lib:grow_plants({
 | 
			
		||||
	grow_delay = GROW_DELAY,
 | 
			
		||||
	grow_chance = GROW_CHANCE*2,
 | 
			
		||||
	grow_plant = "poisonivy:climbing",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
default
 | 
			
		||||
plants_lib
 | 
			
		||||
biome_lib
 | 
			
		||||
bushes?
 | 
			
		||||
ferns?
 | 
			
		||||
moretrees?
 | 
			
		||||
 
 | 
			
		||||
@@ -162,7 +162,7 @@ abstract_trunks.place_twig = function(pos)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
if Twigs_on_ground == true then
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {"default:dirt_with_grass"},
 | 
			
		||||
    max_count = Twigs_on_ground_Max_Count,
 | 
			
		||||
    rarity = Twigs_on_ground_Rarity,
 | 
			
		||||
@@ -179,7 +179,7 @@ plantslib:register_generate_plant({
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
if Twigs_on_water == true then
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {"default:water_source"},
 | 
			
		||||
    max_count = Twigs_on_water_Max_Count,
 | 
			
		||||
    rarity = Twigs_on_water_Rarity,
 | 
			
		||||
@@ -341,7 +341,7 @@ abstract_trunks.place_trunk = function(pos)
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {"default:dirt_with_grass"},
 | 
			
		||||
    max_count = Trunks_Max_Count, -- 320,
 | 
			
		||||
    rarity = Trunks_Rarity, -- 99,
 | 
			
		||||
@@ -374,7 +374,7 @@ abstract_trunks.grow_moss_on_ground = function(pos)
 | 
			
		||||
	
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {"default:dirt_with_grass"},
 | 
			
		||||
    max_count = Moss_on_ground_Max_Count,
 | 
			
		||||
    rarity = Moss_on_ground_Rarity,
 | 
			
		||||
@@ -458,7 +458,7 @@ abstract_trunks.grow_moss_on_trunk = function(pos)
 | 
			
		||||
	--end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {
 | 
			
		||||
		"default:tree",
 | 
			
		||||
		"default:jungletree",
 | 
			
		||||
@@ -535,7 +535,7 @@ abstract_trunks.grow_roots = function(pos)
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {"group:tree"},
 | 
			
		||||
    max_count = 1000,
 | 
			
		||||
    rarity = 1,
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,7 @@ table.
 | 
			
		||||
|description|   string|The vine's tooltip description|
 | 
			
		||||
|average_length|int|   The average length of vines|
 | 
			
		||||
 | 
			
		||||
For biome definitions please see the [plants_lib API documentation](https://github.com/VanessaE/plantlife_modpack/blob/master/API.txt)
 | 
			
		||||
For biome definitions please see the [biome_lib API documentation](https://github.com/VanessaE/biome_lib/blob/master/API.txt)
 | 
			
		||||
 | 
			
		||||
## Notice
 | 
			
		||||
Vines use after_destruct on registered leave nodes to remove vines from which
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,3 @@
 | 
			
		||||
default
 | 
			
		||||
plants_lib
 | 
			
		||||
biome_lib
 | 
			
		||||
moretrees?
 | 
			
		||||
 
 | 
			
		||||
@@ -91,7 +91,7 @@ vines.register_vine = function( name, defs, biome )
 | 
			
		||||
    end
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  plantslib:spawn_on_surfaces( biome )
 | 
			
		||||
  biome_lib:spawn_on_surfaces( biome )
 | 
			
		||||
 | 
			
		||||
  local override_nodes = function( nodes, defs )
 | 
			
		||||
    function override( index, registered )
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
default
 | 
			
		||||
plants_lib
 | 
			
		||||
biome_lib
 | 
			
		||||
bushes?
 | 
			
		||||
ferns?
 | 
			
		||||
moretrees?
 | 
			
		||||
 
 | 
			
		||||
@@ -73,7 +73,7 @@ abstract_woodsoils.place_soil = function(pos)
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {
 | 
			
		||||
		"group:tree",
 | 
			
		||||
		"ferns:fern_03",
 | 
			
		||||
@@ -94,7 +94,7 @@ plantslib:register_generate_plant({
 | 
			
		||||
  "abstract_woodsoils.place_soil"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {
 | 
			
		||||
		"moretrees:apple_tree_sapling_ongen",
 | 
			
		||||
		"moretrees:beech_sapling_ongen",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,2 +1,2 @@
 | 
			
		||||
default
 | 
			
		||||
plants_lib
 | 
			
		||||
biome_lib
 | 
			
		||||
@@ -130,7 +130,7 @@ abstract_youngtrees.grow_youngtree_node = function(pos, height)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
plantslib:register_generate_plant({
 | 
			
		||||
biome_lib:register_generate_plant({
 | 
			
		||||
    surface = {
 | 
			
		||||
		"default:dirt_with_grass", 
 | 
			
		||||
		"stoneage:grass_with_silex",
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user