From 27430814a0d4677df5d85da734ab3c575a01afbe Mon Sep 17 00:00:00 2001 From: Vanessa Ezekowitz Date: Fri, 22 Aug 2014 22:44:33 -0400 Subject: [PATCH] allow multiple nodes to be specified as a table in the nodes_or_function_or_model field of the mapgen register call --- API.txt | 24 ++++++++----- plants_lib/init.lua | 86 +++++++++++++++++++++++++++------------------ 2 files changed, 68 insertions(+), 42 deletions(-) diff --git a/API.txt b/API.txt index 8701137..3bbedbb 100644 --- a/API.txt +++ b/API.txt @@ -238,12 +238,12 @@ checking is disabled. Same holds true for the nneighbors bit above that. ===== -plantslib:register_generate_plant(biome, node_or_function_or_treedef) +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 or table describing what to do if the engine finds a -suitable node (see below). +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 @@ -335,17 +335,25 @@ biome = { random_facedir = {table}, -- same as with the ABM spawner. } -Regarding node_or_function_or_treedef, this must either be table with an -L-Systems tree definition, or a string with a node or function name. +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, the code assumes this table contains an L-Systems -tree definition, then that definition will be passed directly to the -spawn_tree() function along with the position to spawn the tree on. +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 diff --git a/plants_lib/init.lua b/plants_lib/init.lua index 2491931..f38f185 100644 --- a/plants_lib/init.lua +++ b/plants_lib/init.lua @@ -114,26 +114,26 @@ 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, node_or_function_or_model) +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(node_or_function_or_model) == "string" - and string.find(node_or_function_or_model, ":") - and not minetest.registered_nodes[node_or_function_or_model] then - plantslib:dbg("Warning: Ignored registration for undefined spawn node: "..dump(node_or_function_or_model)) + 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(node_or_function_or_model) == "string" - and not string.find(node_or_function_or_model, ":") then - plantslib:dbg("Warning: Registered function call using deprecated string method: "..dump(node_or_function_or_model)) + 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(node_or_function_or_model)) - plantslib.actions_list_noaircheck[#plantslib.actions_list_noaircheck + 1] = { biomedef, node_or_function_or_model } + plantslib:dbg("Register no-air-check mapgen hook: "..dump(nodes_or_function_or_model)) + plantslib.actions_list_noaircheck[#plantslib.actions_list_noaircheck + 1] = { biomedef, nodes_or_function_or_model } local s = biomedef.surface if type(s) == "string" then if s and minetest.registered_nodes[s] then @@ -156,8 +156,8 @@ function plantslib:register_generate_plant(biomedef, node_or_function_or_model) end end else - plantslib:dbg("Register with-air-checking mapgen hook: "..dump(node_or_function_or_model)) - plantslib.actions_list[#plantslib.actions_list + 1] = { biomedef, node_or_function_or_model } + plantslib:dbg("Register with-air-checking mapgen hook: "..dump(nodes_or_function_or_model)) + plantslib.actions_list[#plantslib.actions_list + 1] = { biomedef, nodes_or_function_or_model } local s = biomedef.surface if type(s) == "string" then if s and minetest.registered_nodes[s] then @@ -209,7 +209,7 @@ function plantslib:generate_block_with_air_checking(minp, maxp, blockseed) for action = 1, #plantslib.actions_list do local biome = plantslib.actions_list[action][1] - local node_or_function_or_model = plantslib.actions_list[action][2] + local nodes_or_function_or_model = plantslib.actions_list[action][2] plantslib:set_defaults(biome) @@ -280,27 +280,36 @@ function plantslib:generate_block_with_air_checking(minp, maxp, blockseed) minetest.remove_node(pos) end - local objtype = type(node_or_function_or_model) + local objtype = type(nodes_or_function_or_model) if objtype == "table" then - plantslib:generate_tree(pos, node_or_function_or_model) - spawned = true + 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[node_or_function_or_model] then + 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 = node_or_function_or_model, param2 = fdir }) + minetest.set_node(p_top, { name = nodes_or_function_or_model, param2 = fdir }) spawned = true elseif objtype == "function" then - node_or_function_or_model(pos) + nodes_or_function_or_model(pos) spawned = true elseif objtype == "string" and pcall(loadstring(("return %s(...)"): - format(node_or_function_or_model)),pos) then + format(nodes_or_function_or_model)),pos) then spawned = true else - plantslib:dbg("Warning: Ignored invalid definition for object "..dump(node_or_function_or_model).." that was pointed at {"..dump(pos).."}") + 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 @@ -330,7 +339,7 @@ function plantslib:generate_block_no_air_check(minp, maxp, blockseed) for action = 1, #plantslib.actions_list_noaircheck do local biome = plantslib.actions_list_noaircheck[action][1] - local node_or_function_or_model = plantslib.actions_list_noaircheck[action][2] + local nodes_or_function_or_model = plantslib.actions_list_noaircheck[action][2] plantslib:set_defaults(biome) @@ -400,27 +409,36 @@ function plantslib:generate_block_no_air_check(minp, maxp, blockseed) minetest.remove_node(pos) end - local objtype = type(node_or_function_or_model) + local objtype = type(nodes_or_function_or_model) if objtype == "table" then - plantslib:generate_tree(pos, node_or_function_or_model) - spawned = true + 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[node_or_function_or_model] then + 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 = node_or_function_or_model, param2 = fdir }) + minetest.set_node(p_top, { name = nodes_or_function_or_model, param2 = fdir }) spawned = true elseif objtype == "function" then - node_or_function_or_model(pos) + nodes_or_function_or_model(pos) spawned = true elseif objtype == "string" and pcall(loadstring(("return %s(...)"): - format(node_or_function_or_model)),pos) then + format(nodes_or_function_or_model)),pos) then spawned = true else - plantslib:dbg("Warning: Ignored invalid definition for object "..dump(node_or_function_or_model).." that was pointed at {"..dump(pos).."}") + 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 @@ -666,14 +684,14 @@ end -- spawn_tree() on generate is routed through here so that other mods can hook -- into it. -function plantslib:generate_tree(pos, node_or_function_or_model) - minetest.spawn_tree(pos, node_or_function_or_model) +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, node_or_function_or_model) - minetest.spawn_tree(pos, node_or_function_or_model) +function plantslib:grow_tree(pos, nodes_or_function_or_model) + minetest.spawn_tree(pos, nodes_or_function_or_model) end -- Check for infinite stacks