From 199fa00b0beeab161ed6c160ee56de02bdf163ac Mon Sep 17 00:00:00 2001 From: Vanessa Ezekowitz Date: Sat, 23 Feb 2013 12:33:46 -0500 Subject: [PATCH] Added a couple features to the API to allow for turning off checking for air, deleting nodes surrounding the spawn target during the mapgen code, replacing the spawn target, and checking the type of node directly below the spawn target. --- API.txt | 25 +++++++++++++++++++++++-- plants_lib/init.lua | 30 ++++++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/API.txt b/API.txt index 4b24b34..f05d719 100644 --- a/API.txt +++ b/API.txt @@ -250,13 +250,18 @@ here than are available in the ABM-based spawner, as some stuff doesn't make sense at map-generation time. biome = { - surface = "string", -- What node to spawn on. Must specify one - -- node, such as "default:dirt_with_grass". + 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 or groups to avoid when -- spawning. avoid_radius = num, -- how much distance to leave between the @@ -311,6 +316,22 @@ biome = { -- plant (lowest Perlin temperature 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. + 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 four nodes surrounding the above + -- space, and the four nodes above those, + -- resulting in a two-node-deep cross-shaped + -- empty region above the spawn target. + -- Useful when adding trees to snow biomes. + -- Defaults to false. + spawn_replace_node = bool -- same as with the ABM spawner. } Regarding node_or_function_or_treedef, this must either be table with an diff --git a/plants_lib/init.lua b/plants_lib/init.lua index 82932f0..9c3b6dd 100644 --- a/plants_lib/init.lua +++ b/plants_lib/init.lua @@ -81,6 +81,7 @@ function plantslib:search_for_surfaces(minp, maxp, biomedef, node_or_function_or if not biome.near_nodes_vertical then biome.near_nodes_vertical = 1 end if not biome.humidity_min then biome.humidity_min = 1 end if not biome.humidity_max then biome.humidity_max = -1 end + if biome.check_air ~= false then biome.check_air = true end plantslib:dbg("Started checking generated mapblock volume...") local searchnodes = minetest.env:find_nodes_in_area(minp, maxp, biome.surface) @@ -94,7 +95,7 @@ function plantslib:search_for_surfaces(minp, maxp, biomedef, node_or_function_or 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 (not biome.depth or minetest.env:get_node({ x = pos.x, y = pos.y-biome.depth-1, z = pos.z }).name ~= biome.surface) - and minetest.env:get_node(p_top).name == "air" + and (not biome.check_air or (biome.check_air and minetest.env:get_node(p_top).name == "air")) and pos.y >= biome.min_elevation and pos.y <= biome.max_elevation and noise1 > biome.plantlife_limit @@ -105,13 +106,14 @@ function plantslib:search_for_surfaces(minp, maxp, biomedef, node_or_function_or and (not biome.ncount or 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}, biome.neighbors)) > biome.ncount) and (not biome.near_nodes or table.getn(minetest.env: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.env:get_node({x=pos.x, y=pos.y-1, z=pos.z}).name) ) then table.insert(in_biome_nodes, pos) num_in_biome_nodes = num_in_biome_nodes + 1 end end - plantslib:dbg("Found "..num_in_biome_nodes.." surface nodes of type "..biome.surface.." in 5x5x5 mapblock volume at {"..dump(minp)..":"..dump(maxp).."} to check.") + plantslib:dbg("Found "..num_in_biome_nodes.." surface nodes of type(s) "..dump(biome.surface).." in 5x5x5 mapblock volume at {"..dump(minp)..":"..dump(maxp).."} to check.") if num_in_biome_nodes > 0 then plantslib:dbg("Calculated maximum of "..math.min(biome.max_count*3, num_in_biome_nodes).." nodes to be checked in that list.") @@ -120,9 +122,33 @@ function plantslib:search_for_surfaces(minp, maxp, biomedef, node_or_function_or 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_radius and biome.avoid_nodes) or not minetest.env:find_node_near(p_top, biome.avoid_radius + math.random(-1.5,1.5), biome.avoid_nodes) then spawned = true + if biome.delete_above then + minetest.env:remove_node(p_top) + minetest.env:remove_node({x=p_top.x, y=p_top.y+1, z=p_top.z}) + end + + if biome.delete_above_surround then + minetest.env:remove_node({x=p_top.x-1, y=p_top.y, z=p_top.z}) + minetest.env:remove_node({x=p_top.x+1, y=p_top.y, z=p_top.z}) + minetest.env:remove_node({x=p_top.x, y=p_top.y, z=p_top.z-1}) + minetest.env:remove_node({x=p_top.x, y=p_top.y, z=p_top.z+1}) + + minetest.env:remove_node({x=p_top.x-1, y=p_top.y+1, z=p_top.z}) + minetest.env:remove_node({x=p_top.x+1, y=p_top.y+1, z=p_top.z}) + minetest.env:remove_node({x=p_top.x, y=p_top.y+1, z=p_top.z-1}) + minetest.env:remove_node({x=p_top.x, y=p_top.y+1, z=p_top.z+1}) + end + + if biome.spawn_replace_node then + minetest.env:remove_node(pos) + end + if type(node_or_function_or_model) == "table" then plantslib:dbg("Spawn tree at {"..dump(pos).."}") plantslib:generate_tree(pos, node_or_function_or_model)