Expanded the API to allow for additional biome controls.

See API.txt for details.
This commit is contained in:
Vanessa Ezekowitz 2013-01-09 21:33:37 -05:00
parent 9cb6f594ee
commit b0de25407d
2 changed files with 172 additions and 128 deletions

206
API.txt
View File

@ -15,7 +15,7 @@ dbg()
----- -----
The first of these, spawn_on_surfaces() is defined with quite a large number The first of these, spawn_on_surfaces() is defined with quite a large number
of variables. All of the variables below, if specified at all, must be of variables. All of the variables below, if specified at all, must be
specified exactly in the order given here. specified exactly in the order given here. This function has no return value.
spawn_on_surfaces = function(sdelay, splant, sradius, schance, ssurface, spawn_on_surfaces = function(sdelay, splant, sradius, schance, ssurface,
savoid, seed_diff, lightmin, lightmax, nneighbors, savoid, seed_diff, lightmin, lightmax, nneighbors,
@ -24,103 +24,139 @@ spawn_on_surfaces = function(sdelay, splant, sradius, schance, ssurface,
The first several of these are all required, and are from the last version of The first several of these are all required, and are from the last version of
the flowers mod, so this part of the API should be the same as before. the flowers mod, so this part of the API should be the same as before.
sdelay: The value passed to the ABM's interval parameter, usually in the sdelay: The value passed to the ABM's interval parameter, usually
1000-3000 range. in the 1000-3000 range.
splant: The node name of the item to spawn (e.g. "flowers:flower_rose"). splant: The node name of the item to spawn (e.g.
Note that if the plant is "poisonivy:seedling", and it's next to "flowers:flower_rose"). Note that if the plant is
a wall at spawn time, it automatically becomes the wall-climbing "poisonivy:seedling", and it's next to a wall at spawn
variety. A plant will of course only be spawned if the node about time, it automatically becomes the wall-climbing variety.
to be replaced is air. A plant will of course only be spawned if the node about
sradius: Don't spawn within this many nodes of the avoid items mentioned to be replaced is air.
below. sradius: Don't spawn within this many nodes of the avoid items
schance: The value passed to the ABM's chance parameter, normally in the mentioned below.
10-100 range. schance: The value passed to the ABM's chance parameter, normally
ssurface: Table with the names of the nodes on which to spawn the plant in in the 10-100 range.
question, such as {"default:sand","default:dirt_with_grass"}. It ssurface: Table with the names of the nodes on which to spawn the
is not recommended to put "default:dirt" or "default:stone" into plant in question, such as {"default:sand",
this table if you can do without it, as this will cause the engine "default:dirt_with_grass"}. It is not recommended to put
to process potentially large numbers of such nodes when deciding "default:dirt" or "default:stone" into this table if you
when to execute the ABM. can do without it, as this will cause the engine to
savoid: Table with a list of groups and/or node names to avoid when process potentially large numbers of such nodes when
spawning the plant, such as {"group:flowers","default:tree"}. 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"}.
From here down are several optional parameters. You can use as many as you From here down are several optional parameters. You can use as many as you
need, but you must specify them in order (so if you want lightmax, you need need, but you must specify them in order (so if you want lightmax, you need
lightmin and seed_diff also, but not the rest). lightmin and seed_diff also, but not the rest).
seed_diff: The perlin seed difference value passed to the seed_diff: The perlin seed difference value passed to the
minetest.env:get_perlin() function. Used along with the global minetest.env:get_perlin() function. Used along with the
perlin controls below to create the "biome" in which the plants global perlin controls below to create the "biome" in
will spawn. Usually a value of somewhere in the 10 to 100 range which the plants will spawn. Usually a value of somewhere
is good. Defaults to 0 if not provided in the 10 to 100 range is good. Defaults to 0 if not
lightmin: Minimum amount of light necessary to make a plant spawn. Defaults provided.
to 0. lightmin: Minimum amount of light necessary to make a plant spawn.
lightmax: Maximum amount of light present to allow a plant to spawn. Defaults to 0.
Defaults to the engine's MAX_LIGHT value of 14. lightmax: Maximum amount of light present to allow a plant to spawn.
nneighbors: Table with a list of neighboring nodes, passed to the ABM as the Defaults to the engine's MAX_LIGHT value of 14.
"neighbors" parameter, indicating what needs to be next to the nneighbors: Table with a list of neighboring nodes, passed to the ABM
node the plant is about to spawn on, such as as the "neighbors" parameter, indicating what needs to be
{"default:stone","default:water_source"}. Defaults to the value next to the node the plant is about to spawn on, such as
of ssurface if not provided. {"default:stone","default:water_source"}. Defaults to the
ocount: There must be at least this many of the above neighbors around the value of ssurface if not provided.
node the plant is about to spawn on for it to happen. Defaults to ocount: There must be at least this many of the above neighbors in
0. the eight spaces immediately surrounding the node the
facedir: The value passed to the param2 variable when adding the plant node plant is about to spawn on for it to happen. Defaults to
to the map. Defaults to 0. 0.
depthmax: If a node spawns on top of a water source, the water must be at facedir: The value passed to the param2 variable when adding the
most this deep. Defaults to 1 node. plant node to the map. Defaults to 0.
altitudemin: Items must be at this altitude or higher to spawn at all. depthmax: If a node spawns on top of a water source, the water must
Defaults to -31000. be at most this deep. Defaults to 1 node.
altitudemax: But no higher than this altitude. Defaults to +31000. altitudemin: Items must be at this altitude or higher to spawn at all.
Defaults to -31000.
altitudemax: But no higher than this altitude. Defaults to +31000.
sbiome: List of nodes that must be somewhere in the vicinity in
order for the plant to spawn. Typically this would be
something like "default:water_source" or "default:sand".
Defaults to the value of ssurface if not provided.
sbiomesize: How large of an area to check for the above node.
Specifically, this checks a cuboid area centered on the
node to be spawned on, 3 tall and this wide/long.
Defaults to 0.
sbiomecount: How many of the above nodes must be within that radius.
Defaults to 1.
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.
----- -----
The second function, grow_plants() is defined like so: The second function, grow_plants() is used to turn the spawned nodes above
into something else over time. This function has no return value, and is
defined like so:
grow_plants = function(gdelay, gchance, gplant, gresult, dry_early_node, grow_plants = function(gdelay, gchance, gplant, gresult, dry_early_node,
grow_nodes, facedir, need_wall, grow_vertically, height_limit, grow_nodes, facedir, need_wall, grow_vertically, height_limit,
ground_nodes) ground_nodes, grow_function)
gdelay: Passed as the ABM "interval" parameter, as with spawning. gdelay: Passed as the ABM "interval" parameter, as with spawning.
gchance: Passed as the ABM "chance" parameter. gchance: Passed as the ABM "chance" parameter.
gplant: Name of the node being grown. This value is passed as the gplant: Name of the node being grown. This value is passed as the
only item in the table given to the ABM as the nodenames only item in the table given to the ABM as the nodenames
parameter, so it is the plants themselves that are the ABM parameter, so it is the plants themselves that are the ABM
trigger, rather than the ground they spawned on. A plant trigger, rather than the ground they spawned on. A plant
will only grow if the node above it is air. will only grow if the node above it is air.
gresult: Name of the node into which the above should transform when gresult: Name of the node into which the above should transform
the ABM executes. when the ABM executes.
dry_early_node: This value is ignored except for jungle grass, where it dry_early_node: This value is ignored except for jungle grass, where it
indicates which node the grass must be on in order for it to indicates which node the grass must be on in order for it
turn from "short" to default:dry_shrub. to turn from "short" to default:dry_shrub.
grow_nodes: This node must be under the plant in order for it to grow at grow_nodes: This node must be under the plant in order for it to grow
all. Normally this should be the same as the list of at all. Normally this should be the same as the list of
surfaces passed to the spawning ABM as the "nodenames" surfaces passed to the spawning ABM as the "nodenames"
parameter, such as parameter, such as {"default:dirt_with_grass",
{"default:dirt_with_grass","default:sand"}. This is so that "default:sand"}. This is so that the plant can be
the plant can be manually placed on something like a flower manually placed on something like a flower pot or
pot or something without it growing and eventually dieing. something without it growing and eventually dieing.
facedir: Same as with spawning a plant. If supplied, this value is facedir: Same as with spawning a plant. If supplied, this value is
passed to the param2 variable when changing the plant. If nil passed to the param2 variable when changing the plant. If
or left out, no new param2 value is applied. nil or left out, no new param2 value is applied.
need_wall: Set this to true if you the plant needs to grow against a need_wall: Set this to true if you the plant needs to grow against a
wall. Defaults to false. wall. Defaults to false.
grow_vertically: Set this to true if the plant needs to grow vertically, as in grow_vertically: Set this to true if the plant needs to grow vertically, as
climbing poison ivy. Defaults to false. in climbing poison ivy. Defaults to false.
height_limit: Just how tall can a vertically-growing plant go? Set this height_limit: Just how tall can a vertically-growing plant go? Set this
accordingly. The mod will search straight down from the accordingly. The mod will search straight down from the
position being spawned at to find a ground node, below. position being spawned at to find a ground node, below.
Defaults to 62000 (unlimited). Defaults to 62000 (unlimited).
ground_nodes: What nodes should be treated as "the ground" below a ground_nodes: What nodes should be treated as "the ground" below a
vertically-growing plant. Usually this will be the same as vertically-growing plant. Usually this will be the same
the grow_nodes table, but might also include, for example, as the grow_nodes table, but might also include, for
water or some other surrounding material. Defaults to example, water or some other surrounding material.
"default:dirt_with_grass". Defaults to "default:dirt_with_grass".
grow_function: Execute the named function (which must be supplied as just
the name of the function as a string) when growing this
node, rather than using the method provided by the default
growing code. Note that if this is specified, only the
gdelay, gchance, and gplant variables will be used, the
rest will be ignored by the growing ABM. You can still
read them from within the function if you need to. The
function will be passed two parameters in order: The
position of the node to be "grown" (in the usual table
format), and the Perlin noise value at the location in
question.
seed_diff: The perlin seed diff to be use to calculate the noise
value given to the above grow_function. Should be the
same as the seed diff used when first spawning the plant
that's being grown.
----- -----
plant_valid_wall() expects only a single parameter, "pos", which is a table plant_valid_wall() expects only a single parameter, "pos", which is the usual
indicating the X,Y,Z coordinates to search for nearby adjacent walls. This table indicating the coordinates around which to search for adjacent walls.
function returns the location of the first wall found as a facedir value, or This function returns the location of the first wall found as a facedir value,
nil if there are no adjacent walls. or nil if there are no adjacent walls.
----- -----
is_node_loaded() is defined in exactly the same manner (that is, "node_pos" is is_node_loaded() is defined in exactly the same manner (that is, "node_pos" is

View File

@ -1,20 +1,13 @@
-- Plantlife mod by Vanessa Ezekowitz -- Plantlife library mod by Vanessa Ezekowitz
-- 2012-11-29 -- 2013-01-00
-- --
-- This mod combines all of the functionality from poison ivy, -- License: WTFPL
-- flowers, and jungle grass. If you have any of these, you no
-- longer need them.
--
-- License:
-- CC-BY-SA for most textures, except flowers
-- WTFPL for the flowers textures
-- WTFPL for all code and everything else
-- Various settings - most of these probably won't need to be changed -- Various settings - most of these probably won't need to be changed
plantlife_seed_diff = 329 -- needs to be global so other mods can see it plantlife_seed_diff = 329 -- needs to be global so other mods can see it
local plantlife_debug = false -- ...unless you want the modpack to spam the console ;-) local plantlife_debug = true -- ...unless you want the modpack to spam the console ;-)
local perlin_octaves = 3 local perlin_octaves = 3
local perlin_persistence = 0.6 local perlin_persistence = 0.6
@ -42,15 +35,18 @@ end
-- The spawning ABM -- The spawning ABM
spawn_on_surfaces = function(sdelay, splant, sradius, schance, ssurface, savoid, seed_diff, lightmin, lightmax, nneighbors, ocount, facedir, depthmax, altmin, altmax) spawn_on_surfaces = function(sdelay, splant, sradius, schance, ssurface, savoid, seed_diff, lightmin, lightmax, nneighbors, ocount, facedir, depthmax, altmin, altmax, sbiome, sbiomesize, sbiomecount)
if seed_diff == nil then seed_diff = 0 end if seed_diff == nil then seed_diff = 0 end
if lightmin == nil then lightmin = 0 end if lightmin == nil then lightmin = 0 end
if lightmax == nil then lightmax = LIGHT_MAX end if lightmax == nil then lightmax = LIGHT_MAX end
if nneighbors == nil then nneighbors = ssurface end if nneighbors == nil then nneighbors = ssurface end
if ocount == nil then ocount = 0 end if ocount == nil then ocount = -1 end
if depthmax == nil then depthmax = 1 end if depthmax == nil then depthmax = 1 end
if altmin == nil then altmin = -31000 end if altmin == nil then altmin = -31000 end
if altmax == nil then altmax = 31000 end if altmax == nil then altmax = 31000 end
if sbiome == nil then sbiome = "" end
if sbiomesize == nil then sbiomesize = 0 end
if sbiomecount == nil then sbiomecount = 1 end
minetest.register_abm({ minetest.register_abm({
nodenames = { ssurface }, nodenames = { ssurface },
interval = sdelay, interval = sdelay,
@ -66,7 +62,12 @@ spawn_on_surfaces = function(sdelay, splant, sradius, schance, ssurface, savoid,
if minetest.env:find_node_near(p_top, sradius + math.random(-1.5,2), savoid) == nil if minetest.env:find_node_near(p_top, sradius + math.random(-1.5,2), savoid) == nil
and n_light >= lightmin and n_light >= lightmin
and n_light <= lightmax and n_light <= lightmax
and table.getn(minetest.env: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}, nneighbors)) > ocount and
(table.getn(minetest.env: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}, nneighbors)) > ocount
or ocount == -1)
and
(table.getn(minetest.env:find_nodes_in_area({x=pos.x-sbiomesize, y=pos.y-1, z=pos.z-sbiomesize}, {x=pos.x+sbiomesize, y=pos.y+1, z=pos.z+sbiomesize}, sbiome)) >= sbiomecount
or sbiome == "")
and pos.y >= altmin and pos.y >= altmin
and pos.y <= altmax and pos.y <= altmax
then then
@ -91,7 +92,7 @@ end
-- The growing ABM -- The growing ABM
grow_plants = function(gdelay, gchance, gplant, gresult, dry_early_node, grow_nodes, facedir, need_wall, grow_vertically, height_limit, ground_nodes) grow_plants = function(gdelay, gchance, gplant, gresult, dry_early_node, grow_nodes, facedir, need_wall, grow_vertically, height_limit, ground_nodes, grow_function, seed_diff)
if need_wall ~= true then need_wall = false end if need_wall ~= true then need_wall = false end
if grow_vertically ~= true then grow_vertically = false end if grow_vertically ~= true then grow_vertically = false end
if height_limit == nil then height_limit = 62000 end if height_limit == nil then height_limit = 62000 end
@ -106,39 +107,46 @@ grow_plants = function(gdelay, gchance, gplant, gresult, dry_early_node, grow_no
local n_top = minetest.env:get_node(p_top) local n_top = minetest.env:get_node(p_top)
local n_bot = minetest.env:get_node(p_bot) local n_bot = minetest.env:get_node(p_bot)
local groundnode = minetest.env:get_node({x=pos.x, y=pos.y-height_limit, z=pos.z}) local groundnode = minetest.env:get_node({x=pos.x, y=pos.y-height_limit, z=pos.z})
if grow_function == nil then
if string.find(dump(grow_nodes), n_bot.name) ~= nil and n_top.name == "air" then if string.find(dump(grow_nodes), n_bot.name) ~= nil and n_top.name == "air" then
if grow_vertically then if grow_vertically then
if find_first_node(pos, height_limit, ground_nodes) ~= nil then if find_first_node(pos, height_limit, ground_nodes) ~= nil then
if need_wall then if need_wall then
local walldir=plant_valid_wall(p_top) local walldir=plant_valid_wall(p_top)
if walldir ~= nil then if walldir ~= nil then
dbg("Grow: "..gplant.." upwards to ("..dump(p_top)..") on wall "..walldir) dbg("Grow: "..gplant.." upwards to ("..dump(p_top)..") on wall "..walldir)
minetest.env:add_node(p_top, { name = gplant, param2 = walldir }) minetest.env:add_node(p_top, { name = gplant, param2 = walldir })
end
else
dbg("Grow: "..gplant.." upwards to ("..dump(p_top)..")")
minetest.env:add_node(p_top, { name = gplant })
end end
end
-- corner case for changing short junglegrass to dry shrub in desert
elseif n_bot.name == dry_early_node and gplant == "junglegrass:short" then
dbg("Die: "..gplant.." becomes default:dry_shrub at ("..dump(pos)..")")
minetest.env:add_node(pos, { name = "default:dry_shrub" })
elseif gresult == nil then
dbg("Die: "..gplant.." at ("..dump(pos)..")")
minetest.env:remove_node(pos)
elseif gresult ~= nil then
dbg("Grow: "..gplant.." becomes "..gresult.." at ("..dump(pos)..")")
if facedir == nil then
minetest.env:add_node(pos, { name = gresult })
else else
dbg("Grow: "..gplant.." upwards to ("..dump(p_top)..")") minetest.env:add_node(pos, { name = gresult, param2 = facedir })
minetest.env:add_node(p_top, { name = gplant })
end end
end end
-- corner case for changing short junglegrass to dry shrub in desert
elseif n_bot.name == dry_early_node and gplant == "junglegrass:short" then
dbg("Die: "..gplant.." becomes default:dry_shrub at ("..dump(pos)..")")
minetest.env:add_node(pos, { name = "default:dry_shrub" })
elseif gresult == nil then
dbg("Die: "..gplant.." at ("..dump(pos)..")")
minetest.env:remove_node(pos)
elseif gresult ~= nil then
dbg("Grow: "..gplant.." becomes "..gresult.." at ("..dump(pos)..")")
if facedir == nil then
minetest.env:add_node(pos, { name = gresult })
else
minetest.env:add_node(pos, { name = gresult, param2 = facedir })
end
end end
else
if seed_diff == nil then seed_diff = 0 end
local perlin = minetest.env:get_perlin(seed_diff, perlin_octaves, perlin_persistence, perlin_scale )
local noise = perlin:get2d({x=pos.x, y=pos.z})
dbg("Want to execute "..grow_function.."("..dump(pos)..","..noise..")")
assert(loadstring(grow_function.."("..dump(pos)..","..noise..")"))()
end end
end end
}) })