Compare commits

...

9 Commits

Author SHA1 Message Date
David Leal 95845dfb08
Use organization's LuaCheck workflow 2024-02-13 14:30:15 -06:00
Niklp 3d217950b3 fix incorrect mod URLs 2022-07-09 13:23:23 +03:00
sys4-fr 20c89d0ee6
Delete description.txt, update mod.conf (#9)
Co-authored-by: sys4 <bricassa@sys4.fr>
2022-07-06 20:05:17 +02:00
Luke aka SwissalpS 396ca881df
typo in debug output 2022-01-20 06:34:51 +01:00
Jordan Leppert 932485a6fe
register_on_generate: tries and rarity_fertility (#8)
* Can specify the number of tries when generating
* Added rarity_fertility which means rarity can be affected by fertility level.
Rarity can now be a fraction.
A rarity of 100 (with rarity_fertility of 0) means the object will never appear, and a rarity of 0 means it will always appear.
2021-12-24 09:30:36 +01:00
Jordan Leppert bd92dc1b0b
Fixing humidity/temperature data (#5)
* Fixing humidity/temperature data returned from get_biome_data() to fix the range (and sign) of the original data
* Removing unused variables
Co-authored-by: OgelGames <olliverdc28@gmail.com>
2021-12-11 19:45:04 +01:00
Buckaroo Banzai a3ce221eed
Add luacheck and github workflow (#4)
Co-authored-by: BuckarooBanzay <BuckarooBanzay@users.noreply.github.com>
Co-authored-by: OgelGames <olliverdc28@gmail.com>
2021-12-10 13:45:31 +11:00
nixnoxus 3a1446e26e
Remove unused `intllib` translations (#6) 2021-12-10 13:16:36 +11:00
Jordan Leppert 823db77217
Enable generating objects on sides or bottom of nodes at mapgen time (#2)
* biome_lib.register_on_generate now supports spawn_on_sides and spawn_on_bottom flags
* biome_lib.register_on_generate now passes node position and face direction to node placement function
* Replacing spaces with tabs
* Fixing API to ensure it behaves same way it used to, when not passing spawn_on_sides or spawn_on_bottom flags.
2021-12-06 19:22:29 +01:00
17 changed files with 141 additions and 128 deletions

10
.github/workflows/luacheck.yml vendored Normal file
View File

@ -0,0 +1,10 @@
name: luacheck
on: [push, pull_request]
jobs:
luacheck:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@master
- name: Luacheck
uses: lunarmodules/luacheck@master

18
.luacheckrc Normal file
View File

@ -0,0 +1,18 @@
unused_args = false
globals = {
"biome_lib"
}
read_globals = {
-- Stdlib
string = {fields = {"split", "trim"}},
table = {fields = {"copy"}},
-- Minetest
"minetest", "vector",
"dump", "PerlinNoise",
-- mods
"default",
}

33
API.txt
View File

@ -26,7 +26,7 @@ biome_lib.register_active_spawner(sdelay, splant, sradius, schance, ssurface, sa
This first function is an ABM-based spawner function originally created as 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 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 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, 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 or you can pass a single biome definition as a table, with all of your options
spelled out nicely. This is the preferred method. spelled out nicely. This is the preferred method.
@ -135,7 +135,7 @@ biome = {
-- radius. Defaults to 1 but is ignored if near_nodes -- radius. Defaults to 1 but is ignored if near_nodes
-- isn't set. Bear in mind that the total area to be -- isn't set. Bear in mind that the total area to be
-- checked is equal to: -- checked is equal to:
-- (near_nodes_size^2)*near_nodes_vertical*2 -- (near_nodes_size^2)*near_nodes_vertical*2
-- For example, if size is 10 and vertical is 4, then -- For example, if size is 10 and vertical is 4, then
-- the area is (10^2)*8 = 800 nodes in size, so you'll -- the area is (10^2)*8 = 800 nodes in size, so you'll
-- want to make sure you specify a value appropriate -- want to make sure you specify a value appropriate
@ -202,7 +202,7 @@ biome = {
} }
[*] spawn_plants must be either a table or a string. If it's a table, the [*] 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 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 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 parameter to avoid making too many calls to this function, the lower the CPU
load will likely be. load will likely be.
@ -225,7 +225,7 @@ 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 information, and a string, function, or table describing what to do if the
engine finds a suitable surface node (see below). engine finds a suitable surface node (see below).
The biome table contains quite a number of options, though there are fewer 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 here than are available in the ABM-based spawner, as some stuff doesn't make
sense at map-generation time. sense at map-generation time.
@ -250,12 +250,21 @@ biome = {
-- skipped. Avoid using excessively large radii. -- skipped. Avoid using excessively large radii.
rarity = num, -- How rare should this object be in its biome? Larger rarity = num, -- How rare should this object be in its biome? Larger
-- values make objects more rare, via: -- values make objects more rare, via:
-- math.random(1,100) > this -- math.random() * 100 > this
rarity_fertility -- The amount that the rarity is reduced by fertility.
= num, -- This makes the rarity field the upper bound for
-- rarity, and (rarity - rarity_fertility) the lower
-- bound. Defaults to 0.
max_count = num, -- The absolute maximum number of your object that max_count = num, -- The absolute maximum number of your object that
-- should be allowed to spawn in a 5x5x5 mapblock area -- should be allowed to spawn in a 5x5x5 mapblock area
-- (80x80x80 nodes). Defaults to 5, but be sure you -- (80x80x80 nodes). Defaults to 5, but be sure you
-- set this to some reasonable value depending on your -- set this to some reasonable value depending on your
-- object and its size if 5 is insufficient. -- object and its size if 5 is insufficient.
tries = num, -- the number of attempts that will be made to spawn
-- an object, defaults to 2. This means if the first
-- attempt fails due to something blocking the object
-- for example, another attempt will be made in
-- another random location.
seed_diff = num, -- Perlin seed-diff value. Defaults to 0, which seed_diff = num, -- Perlin seed-diff value. Defaults to 0, which
-- causes the function to inherit the global value of -- causes the function to inherit the global value of
-- 329. -- 329.
@ -341,7 +350,7 @@ definition table as the only parameter. These are defined like so:
options = { options = {
label = string, -- set this to identify the ABM for Minetest's label = string, -- set this to identify the ABM for Minetest's
-- profiler. If not set, biome_lib will set it to -- profiler. If not set, biome_lib will set it to
-- "biome_lib.update_plant(): " appended with the node -- "biome_lib.update_plant(): " appended with the node
-- in grow_plant (or the first item if it's a table) -- in grow_plant (or the first item if it's a table)
grow_plant = "string" or {table}, -- Name(s) of the node(s) to be grown grow_plant = "string" or {table}, -- Name(s) of the node(s) to be grown
@ -406,7 +415,7 @@ 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 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 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 world, grow_result is ignored and the named function is executed and passed a
few parmeters in the following general form: few parmeters in the following general form:
somefunction(pos, perlin1, perlin2) somefunction(pos, perlin1, perlin2)
@ -431,7 +440,7 @@ 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. 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 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 random wall it finds adjacent to the target position. Defaults to false if
not specified. not specified.
===== =====
@ -463,7 +472,7 @@ spammy stuff.
biome_lib.generate_ltree(pos, treemodel) biome_lib.generate_ltree(pos, treemodel)
biome_lib.grow_ltree(pos, treemodel) biome_lib.grow_ltree(pos, treemodel)
In the case of the growing code and the mapgen-based tree generator code, 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 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 call the usual spawn_tree() functions. This rerouting exists as a way for
other mods to hook into biome_lib's tree-growing functions in general, other mods to hook into biome_lib's tree-growing functions in general,
@ -475,7 +484,7 @@ 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 expected by the spawn_tree() function. Refer to the 'trunk' field in that
table to derive the name of the tree being spawned. table to derive the name of the tree being spawned.
biome_lib.grow_ltree(pos, treemodel) does the same sort of thing whenever a biome_lib.grow_ltree(pos, treemodel) does the same sort of thing whenever a
tree is spawned within the abm-based growing code, for example when growing a tree is spawned within the abm-based growing code, for example when growing a
sapling into a tree. sapling into a tree.
@ -518,7 +527,7 @@ appears to be the standard now. Those values are:
temperature_persistence = 0.5 temperature_persistence = 0.5
temperature_scale = 150 temperature_scale = 150
The way Perlin values are used by this mod, in keeping with the snow mod's 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 apparent methods, larger values returned by the Perlin function represent
*colder* temperatures. In this mod, the following table gives a rough *colder* temperatures. In this mod, the following table gives a rough
approximation of how temperature maps to these values, normalized to approximation of how temperature maps to these values, normalized to
@ -542,7 +551,7 @@ Perlin Approx. Temperature
Included in this table are even 0.25 steps in Perlin values along with some 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 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, 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. you probably won't need to bother with Perlin values of less than -0.56 or so.

View File

@ -14,8 +14,8 @@ It is primarily intended for mapgen v6, but it should work fine when used with m
**Dependencies:** nothing, but if you don't use `minetest_game`, you'll need to supply some settings (see API.txt). **Dependencies:** nothing, but if you don't use `minetest_game`, you'll need to supply some settings (see API.txt).
**Recommends**: [Plantlife Modpack](https://github.com/minetest-mods/plantlife_modpack), **Recommends**: [Plantlife Modpack](https://github.com/mt-mods/plantlife_modpack),
[More Trees](https://github.com/minetest-mods/moretrees) [More Trees](https://github.com/mt-mods/moretrees)
**API**: This mod supplies a small number of very powerful functions. They are, briefly: **API**: This mod supplies a small number of very powerful functions. They are, briefly:

142
api.lua
View File

@ -14,16 +14,6 @@ biome_lib.fertile_perlin_octaves = 3
biome_lib.fertile_perlin_persistence = 0.6 biome_lib.fertile_perlin_persistence = 0.6
biome_lib.fertile_perlin_scale = 100 biome_lib.fertile_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_speed = tonumber(minetest.settings:get("time_speed")) local time_speed = tonumber(minetest.settings:get("time_speed"))
biome_lib.time_scale = 1 biome_lib.time_scale = 1
@ -35,19 +25,11 @@ biome_lib.air = {name = "air"}
-- the mapgen rarely creates useful surfaces outside this range, but mods can -- the mapgen rarely creates useful surfaces outside this range, but mods can
-- still specify a wider range if needed. -- still specify a wider range if needed.
biome_lib.mapgen_elevation_limit = { ["min"] = -16, ["max"] = 48 } biome_lib.mapgen_elevation_limit = { ["min"] = -16, ["max"] = 48 }
--PerlinNoise(seed, octaves, persistence, scale)
biome_lib.perlin_temperature = PerlinNoise(temperature_seeddiff, temperature_octaves, temperature_persistence, temperature_scale)
biome_lib.perlin_humidity = PerlinNoise(humidity_seeddiff, humidity_octaves, humidity_persistence, humidity_scale)
-- Local functions -- Local functions
local function tableize(s)
return string.split(string.trim(string.gsub(s, " ", "")))
end
function biome_lib.dbg(msg, level) function biome_lib.dbg(msg, level)
local l = tonumber(level) or 0 local l = tonumber(level) or 0
if biome_lib.debug_log_level >= l then if biome_lib.debug_log_level >= l then
@ -59,17 +41,10 @@ end
local function get_biome_data(pos, perlin_fertile) local function get_biome_data(pos, perlin_fertile)
local fertility = perlin_fertile:get_2d({x=pos.x, y=pos.z}) local fertility = perlin_fertile:get_2d({x=pos.x, y=pos.z})
if type(minetest.get_biome_data) == "function" then local data = minetest.get_biome_data(pos)
local data = minetest.get_biome_data(pos) -- Original values this method returned were +1 (lowest) to -1 (highest)
if data then -- so we need to convert the 0-100 range from get_biome_data() to that.
return fertility, data.heat / 100, data.humidity / 100 return fertility, 1 - (data.heat / 100 * 2), 1 - (data.humidity / 100 * 2)
end
end
local temperature = biome_lib.perlin_temperature:get2d({x=pos.x, y=pos.z})
local humidity = biome_lib.perlin_humidity:get2d({x=pos.x+150, y=pos.z+50})
return fertility, temperature, humidity
end end
function biome_lib.is_node_loaded(node_pos) function biome_lib.is_node_loaded(node_pos)
@ -98,7 +73,9 @@ function biome_lib.set_defaults(biome)
biome.near_nodes_size = biome.near_nodes_size or 0 biome.near_nodes_size = biome.near_nodes_size or 0
biome.near_nodes_count = biome.near_nodes_count or 1 biome.near_nodes_count = biome.near_nodes_count or 1
biome.rarity = biome.rarity or 50 biome.rarity = biome.rarity or 50
biome.rarity_fertility = biome.rarity_fertility or 0
biome.max_count = biome.max_count or 125 biome.max_count = biome.max_count or 125
biome.tries = biome.tries or 2
if biome.check_air ~= false then biome.check_air = true end if biome.check_air ~= false then biome.check_air = true end
-- specific to abm spawner -- specific to abm spawner
@ -122,19 +99,21 @@ end
function biome_lib.register_on_generate(biomedef, nodes_or_function_or_model) function biome_lib.register_on_generate(biomedef, nodes_or_function_or_model)
-- if calling code passes an undefined node for a surface or -- if calling code passes an undefined node for a surface or
-- as a node to be spawned, don't register an action for it. -- as a node to be spawned, don't register an action for it.
if type(nodes_or_function_or_model) == "string" if type(nodes_or_function_or_model) == "string"
and string.find(nodes_or_function_or_model, ":") and string.find(nodes_or_function_or_model, ":")
and not minetest.registered_nodes[nodes_or_function_or_model] then and not minetest.registered_nodes[nodes_or_function_or_model] then
biome_lib.dbg("Warning: Ignored registration for undefined spawn node: "..dump(nodes_or_function_or_model), 2) biome_lib.dbg("Warning: Ignored registration for undefined spawn node: "..
dump(nodes_or_function_or_model), 2)
return return
end end
if type(nodes_or_function_or_model) == "string" if type(nodes_or_function_or_model) == "string"
and not string.find(nodes_or_function_or_model, ":") then and not string.find(nodes_or_function_or_model, ":") then
biome_lib.dbg("Warning: Registered function call using deprecated string method: "..dump(nodes_or_function_or_model), 2) biome_lib.dbg("Warning: Registered function call using deprecated string method: "..
dump(nodes_or_function_or_model), 2)
end end
biome_lib.mapgen_elevation_limit.min = math.min(biomedef.min_elevation or 0, biome_lib.mapgen_elevation_limit.min) biome_lib.mapgen_elevation_limit.min = math.min(biomedef.min_elevation or 0, biome_lib.mapgen_elevation_limit.min)
@ -143,13 +122,14 @@ function biome_lib.register_on_generate(biomedef, nodes_or_function_or_model)
local decor_def = biome_lib.can_use_decorations(biomedef, nodes_or_function_or_model) local decor_def = biome_lib.can_use_decorations(biomedef, nodes_or_function_or_model)
if decor_def then if decor_def then
biome_lib.dbg("Using engine decorations instead of biome_lib functions for node(s): "..dump(nodes_or_function_or_model), 3) biome_lib.dbg("Using engine decorations instead of biome_lib functions for node(s): "..
dump(nodes_or_function_or_model), 3)
biome_lib.registered_decorations[#biome_lib.registered_decorations + 1] = nodes_or_function_or_model biome_lib.registered_decorations[#biome_lib.registered_decorations + 1] = nodes_or_function_or_model
minetest.register_decoration(decor_def) minetest.register_decoration(decor_def)
return return
elseif biomedef.check_air == false then elseif biomedef.check_air == false then
biome_lib.dbg("Register no-air-check mapgen hook: "..dump(nodes_or_function_or_model), 3) biome_lib.dbg("Register no-air-check mapgen hook: "..dump(nodes_or_function_or_model), 3)
biome_lib.actionslist_no_aircheck[#biome_lib.actionslist_no_aircheck + 1] = { biomedef, nodes_or_function_or_model } biome_lib.actionslist_no_aircheck[#biome_lib.actionslist_no_aircheck + 1] = {biomedef, nodes_or_function_or_model}
local s = biomedef.surface local s = biomedef.surface
if type(s) == "string" then if type(s) == "string" then
if s and (string.find(s, "^group:") or minetest.registered_nodes[s]) then if s and (string.find(s, "^group:") or minetest.registered_nodes[s]) then
@ -161,7 +141,7 @@ function biome_lib.register_on_generate(biomedef, nodes_or_function_or_model)
end end
else else
for i = 1, #biomedef.surface do for i = 1, #biomedef.surface do
local s = biomedef.surface[i] s = biomedef.surface[i]
if s and (string.find(s, "^group:") or minetest.registered_nodes[s]) then if s and (string.find(s, "^group:") or minetest.registered_nodes[s]) then
if not search_table(biome_lib.surfaceslist_no_aircheck, s) then if not search_table(biome_lib.surfaceslist_no_aircheck, s) then
biome_lib.surfaceslist_no_aircheck[#biome_lib.surfaceslist_no_aircheck + 1] = s biome_lib.surfaceslist_no_aircheck[#biome_lib.surfaceslist_no_aircheck + 1] = s
@ -185,7 +165,7 @@ function biome_lib.register_on_generate(biomedef, nodes_or_function_or_model)
end end
else else
for i = 1, #biomedef.surface do for i = 1, #biomedef.surface do
local s = biomedef.surface[i] s = biomedef.surface[i]
if s and (string.find(s, "^group:") or minetest.registered_nodes[s]) then if s and (string.find(s, "^group:") or minetest.registered_nodes[s]) then
if not search_table(biome_lib.surfaceslist_aircheck, s) then if not search_table(biome_lib.surfaceslist_aircheck, s) then
biome_lib.surfaceslist_aircheck[#biome_lib.surfaceslist_aircheck + 1] = s biome_lib.surfaceslist_aircheck[#biome_lib.surfaceslist_aircheck + 1] = s
@ -204,17 +184,21 @@ end
local function populate_single_surface(biome, pos, perlin_fertile_area, checkair) local function populate_single_surface(biome, pos, perlin_fertile_area, checkair)
local p_top = { x = pos.x, y = pos.y + 1, z = pos.z } local p_top = { x = pos.x, y = pos.y + 1, z = pos.z }
if math.random(1, 100) <= biome.rarity then if biome.rarity - biome.rarity_fertility == 100 then
return return
end end
local fertility, temperature, humidity = get_biome_data(pos, perlin_fertile_area) local fertility, temperature, humidity = get_biome_data(pos, perlin_fertile_area)
if math.random() * 100 <= (biome.rarity - ((fertility + 1) / 2 * biome.rarity_fertility)) then
return
end
local pos_biome_ok = pos.y >= biome.min_elevation and pos.y <= biome.max_elevation local pos_biome_ok = pos.y >= biome.min_elevation and pos.y <= biome.max_elevation
and fertility > biome.plantlife_limit and fertility >= biome.plantlife_limit
and temperature <= biome.temp_min and temperature >= biome.temp_max and temperature <= biome.temp_min and temperature >= biome.temp_max
and humidity <= biome.humidity_min and humidity >= biome.humidity_max and humidity <= biome.humidity_min and humidity >= biome.humidity_max
if not pos_biome_ok then if not pos_biome_ok then
return -- Y position mismatch, outside of biome return -- Y position mismatch, outside of biome
end end
@ -229,7 +213,7 @@ local function populate_single_surface(biome, pos, perlin_fertile_area, checkair
else else
if string.find(biome_surfaces_string, "group:") then if string.find(biome_surfaces_string, "group:") then
for j = 1, #biome.surface do for j = 1, #biome.surface do
if string.find(biome.surface[j], "^group:") if string.find(biome.surface[j], "^group:")
and minetest.get_item_group(dest_node.name, biome.surface[j]) then and minetest.get_item_group(dest_node.name, biome.surface[j]) then
surface_ok = true surface_ok = true
break break
@ -241,7 +225,7 @@ local function populate_single_surface(biome, pos, perlin_fertile_area, checkair
minetest.get_node({ x = pos.x, y = pos.y-biome.depth-1, z = pos.z }).name) then minetest.get_node({ x = pos.x, y = pos.y-biome.depth-1, z = pos.z }).name) then
surface_ok = true surface_ok = true
end end
if not surface_ok then if not surface_ok then
return -- Surface does not match the given node group/name return -- Surface does not match the given node group/name
end end
@ -269,7 +253,7 @@ local function populate_single_surface(biome, pos, perlin_fertile_area, checkair
if biome.near_nodes and if biome.near_nodes and
#minetest.find_nodes_in_area( #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},
{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
) < biome.near_nodes_count then ) < biome.near_nodes_count then
return -- Long distance neighbours do not match return -- Long distance neighbours do not match
@ -287,7 +271,8 @@ function biome_lib.populate_surfaces(b, nodes_or_function_or_model, snodes, chec
-- filter stage 1 - find nodes from the supplied surfaces that are within the current biome. -- filter stage 1 - find nodes from the supplied surfaces that are within the current biome.
local in_biome_nodes = {} local in_biome_nodes = {}
local perlin_fertile_area = minetest.get_perlin(biome.seed_diff, biome_lib.fertile_perlin_octaves, biome_lib.fertile_perlin_persistence, biome_lib.fertile_perlin_scale) local perlin_fertile_area = minetest.get_perlin(biome.seed_diff, biome_lib.fertile_perlin_octaves,
biome_lib.fertile_perlin_persistence, biome_lib.fertile_perlin_scale)
for i = 1, #snodes do for i = 1, #snodes do
local pos = vector.new(snodes[i]) local pos = vector.new(snodes[i])
@ -307,14 +292,36 @@ function biome_lib.populate_surfaces(b, nodes_or_function_or_model, snodes, chec
for i = 1, math.min(math.ceil(biome.max_count/25), num_in_biome_nodes) do for i = 1, math.min(math.ceil(biome.max_count/25), num_in_biome_nodes) do
local tries = 0 local tries = 0
local spawned = false local spawned = false
while tries < 2 and not spawned do while tries < biome.tries and not spawned do
local pos = in_biome_nodes[math.random(1, num_in_biome_nodes)] local pos = in_biome_nodes[math.random(1, num_in_biome_nodes)]
if biome.spawn_replace_node then
local will_place = true
local fdir = nil
if biome.random_facedir then
fdir = math.random(biome.random_facedir[1], biome.random_facedir[2])
end
if biome.spawn_on_side then
local onside = biome_lib.find_open_side(pos)
if onside then
pos = onside.newpos
fdir = onside.facedir
else
will_place = false
end
elseif biome.spawn_on_bottom then
if minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name == "air" then
pos.y = pos.y - 1
else
will_place = false
end
elseif biome.spawn_replace_node then
pos.y = pos.y-1 pos.y = pos.y-1
end end
local p_top = { x = pos.x, y = pos.y + 1, z = pos.z } local p_top = { x = pos.x, y = pos.y + 1, z = pos.z }
if not (biome.avoid_nodes and biome.avoid_radius if will_place and not (biome.avoid_nodes and biome.avoid_radius
and minetest.find_node_near(p_top, biome.avoid_radius and minetest.find_node_near(p_top, biome.avoid_radius
+ math.random(-1.5,2), biome.avoid_nodes)) then + math.random(-1.5,2), biome.avoid_nodes)) then
if biome.delete_above then if biome.delete_above then
@ -346,34 +353,30 @@ function biome_lib.populate_surfaces(b, nodes_or_function_or_model, snodes, chec
biome_lib.dbg("An L-tree was spawned at "..minetest.pos_to_string(p_top), 4) biome_lib.dbg("An L-tree was spawned at "..minetest.pos_to_string(p_top), 4)
spawned = true spawned = true
else else
local fdir = nil
if biome.random_facedir then
fdir = math.random(biome.random_facedir[1], biome.random_facedir[2])
end
local n=nodes_or_function_or_model[math.random(#nodes_or_function_or_model)] local n=nodes_or_function_or_model[math.random(#nodes_or_function_or_model)]
minetest.swap_node(p_top, { name = n, param2 = fdir }) minetest.swap_node(p_top, { name = n, param2 = fdir })
biome_lib.dbg("Node \""..n.."\" was randomly picked from a list and placed at "..minetest.pos_to_string(p_top), 4) biome_lib.dbg("Node \""..n.."\" was randomly picked from a list and placed at "..
minetest.pos_to_string(p_top), 4)
spawned = true spawned = true
end end
elseif objtype == "string" and elseif objtype == "string" and
minetest.registered_nodes[nodes_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.swap_node(p_top, { name = nodes_or_function_or_model, param2 = fdir }) minetest.swap_node(p_top, { name = nodes_or_function_or_model, param2 = fdir })
biome_lib.dbg("Node \""..nodes_or_function_or_model.."\" was placed at "..minetest.pos_to_string(p_top), 4) biome_lib.dbg("Node \""..nodes_or_function_or_model.."\" was placed at "..
minetest.pos_to_string(p_top), 4)
spawned = true spawned = true
elseif objtype == "function" then elseif objtype == "function" then
nodes_or_function_or_model(pos) nodes_or_function_or_model(pos, fdir)
biome_lib.dbg("A function was run on surface node at "..minetest.pos_to_string(pos), 4) biome_lib.dbg("A function was run on surface node at "..minetest.pos_to_string(pos), 4)
spawned = true spawned = true
elseif objtype == "string" and pcall(loadstring(("return %s(...)"): elseif objtype == "string" and pcall(loadstring(("return %s(...)"):
format(nodes_or_function_or_model)),pos) then format(nodes_or_function_or_model)),pos) then
spawned = true spawned = true
biome_lib.dbg("An obsolete string-specified function was run on surface node at "..minetest.pos_to_string(p_top), 4) biome_lib.dbg("An obsolete string-specified function was run on surface node at "..
minetest.pos_to_string(p_top), 4)
else else
biome_lib.dbg("Warning: Ignored invalid definition for object "..dump(nodes_or_function_or_model).." that was pointed at {"..dump(pos).."}", 2) biome_lib.dbg("Warning: Ignored invalid definition for object "..
dump(nodes_or_function_or_model).." that was pointed at {"..dump(pos).."}", 2)
end end
else else
tries = tries + 1 tries = tries + 1
@ -393,7 +396,7 @@ local function confirm_block_surroundings(p)
for x = -32,32,64 do -- step of 64 causes it to only check the 8 corner blocks for x = -32,32,64 do -- step of 64 causes it to only check the 8 corner blocks
for y = -32,32,64 do for y = -32,32,64 do
for z = -32,32,64 do for z = -32,32,64 do
local n=minetest.get_node_or_nil({x=p.x + x, y=p.y + y, z=p.z + z}) n = minetest.get_node_or_nil({x=p.x + x, y=p.y + y, z=p.z + z})
if not n or n.name == "ignore" then return false end if not n or n.name == "ignore" then return false end
end end
end end
@ -427,7 +430,6 @@ function biome_lib.generate_block(shutting_down)
local minp = blocklog[1][1] local minp = blocklog[1][1]
local maxp = blocklog[1][2] local maxp = blocklog[1][2]
local airflag = blocklog[1][3] local airflag = blocklog[1][3]
local pos_hash = minetest.hash_node_position(minp)
if not biome_lib.pos_hash then -- we need to read the maplock and get the surfaces list if not biome_lib.pos_hash then -- we need to read the maplock and get the surfaces list
local now = minetest.get_us_time() local now = minetest.get_us_time()
@ -435,7 +437,8 @@ function biome_lib.generate_block(shutting_down)
minetest.load_area(minp) minetest.load_area(minp)
if not confirm_block_surroundings(minp) if not confirm_block_surroundings(minp)
and not shutting_down and not shutting_down
and (blocklog[1][4] + biome_lib.block_timeout) > now then -- if any neighbors appear not to be loaded and the block hasn't expired yet, defer it -- if any neighbors appear not to be loaded and the block hasn't expired yet, defer it
and (blocklog[1][4] + biome_lib.block_timeout) > now then
if biome_lib.run_block_recheck_list then if biome_lib.run_block_recheck_list then
biome_lib.block_log[#biome_lib.block_log + 1] = table.copy(biome_lib.block_recheck_list[1]) biome_lib.block_log[#biome_lib.block_log + 1] = table.copy(biome_lib.block_recheck_list[1])
@ -542,9 +545,10 @@ function biome_lib.register_active_spawner(sd,sp,sr,sc,ss,sa)
neighbors = biome.neighbors, neighbors = biome.neighbors,
label = biome.label, label = biome.label,
action = function(pos, node, active_object_count, active_object_count_wider) 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_top = { x = pos.x, y = pos.y + 1, z = pos.z }
local n_top = minetest.get_node(p_top) local n_top = minetest.get_node(p_top)
local perlin_fertile_area = minetest.get_perlin(biome.seed_diff, biome_lib.fertile_perlin_octaves, biome_lib.fertile_perlin_persistence, biome_lib.fertile_perlin_scale) local perlin_fertile_area = minetest.get_perlin(biome.seed_diff, biome_lib.fertile_perlin_octaves,
biome_lib.fertile_perlin_persistence, biome_lib.fertile_perlin_scale)
local fertility, temperature, humidity = get_biome_data(pos, perlin_fertile_area) local fertility, temperature, humidity = get_biome_data(pos, perlin_fertile_area)
@ -654,12 +658,14 @@ function biome_lib.replace_plant(pos, replacement, grow_function, walldir, seedd
biome_lib.grow_ltree(pos, grow_function) biome_lib.grow_ltree(pos, grow_function)
return return
elseif growtype == "function" then elseif growtype == "function" then
local perlin_fertile_area = minetest.get_perlin(seeddiff, biome_lib.fertile_perlin_octaves, biome_lib.fertile_perlin_persistence, biome_lib.fertile_perlin_scale) local perlin_fertile_area = minetest.get_perlin(seeddiff, biome_lib.fertile_perlin_octaves,
biome_lib.fertile_perlin_persistence, biome_lib.fertile_perlin_scale)
local fertility, temperature, _ = get_biome_data(pos, perlin_fertile_area) local fertility, temperature, _ = get_biome_data(pos, perlin_fertile_area)
grow_function(pos, fertility, temperature, walldir) grow_function(pos, fertility, temperature, walldir)
return return
elseif growtype == "string" then elseif growtype == "string" then
local perlin_fertile_area = minetest.get_perlin(seeddiff, biome_lib.fertile_perlin_octaves, biome_lib.fertile_perlin_persistence, biome_lib.fertile_perlin_scale) local perlin_fertile_area = minetest.get_perlin(seeddiff, biome_lib.fertile_perlin_octaves,
biome_lib.fertile_perlin_persistence, biome_lib.fertile_perlin_scale)
local fertility, temperature, _ = get_biome_data(pos, perlin_fertile_area) local fertility, temperature, _ = get_biome_data(pos, perlin_fertile_area)
assert(loadstring(grow_function.."(...)"))(pos, fertility, temperature, walldir) assert(loadstring(grow_function.."(...)"))(pos, fertility, temperature, walldir)
return return

View File

@ -108,7 +108,8 @@ minetest.register_on_generated(function(minp, maxp, blockseed)
end end
end end
else else
biome_lib.dbg("Did not enqueue mapblocks at elevation "..miny.."m, they're out of range of any generate_plant() calls.", 4) biome_lib.dbg("Did not enqueue mapblocks at elevation "..miny..
"m, they're out of range of any generate_plant() calls.", 4)
end end
end end
biome_lib.run_block_recheck_list = true biome_lib.run_block_recheck_list = true

View File

@ -81,7 +81,7 @@ function biome_lib.can_use_decorations(b, nodes_or_function_or_treedef)
["y_min"] = biome.min_elevation, ["y_min"] = biome.min_elevation,
["y_max"] = biome.max_elevation, ["y_max"] = biome.max_elevation,
["spawn_by"] = biome.near_nodes, ["spawn_by"] = biome.near_nodes,
["num_spawn_by"] = biome.near_nodes and biome.near_nodes_count, ["num_spawn_by"] = biome.near_nodes and biome.near_nodes_count,
} }
local r = (100-biome.rarity)/100 local r = (100-biome.rarity)/100

View File

@ -1 +0,0 @@
The biome spawning and management library for Plantlife, Moretrees, Tiny Trees, and other mods that originally depended on plants_lib from the plantlife modpack.

View File

@ -48,7 +48,6 @@ function biome_lib.update_plant(opts)
local p_bot = {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_top = minetest.get_node(p_top)
local n_bot = minetest.get_node(p_bot) 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 local walldir = nil
if options.need_wall and options.verticals_list then if options.need_wall and options.verticals_list then
walldir = biome_lib.find_adjacent_wall(p_top, options.verticals_list, options.choose_random_wall) walldir = biome_lib.find_adjacent_wall(p_top, options.verticals_list, options.choose_random_wall)

View File

@ -7,18 +7,9 @@
biome_lib = {} biome_lib = {}
biome_lib.modpath = minetest.get_modpath("biome_lib") biome_lib.modpath = minetest.get_modpath("biome_lib")
-- Boilerplate to support localized strings if intllib mod is installed. local function tableize(s)
local S return string.split(string.trim(string.gsub(s, " ", "")))
if minetest.global_exists("intllib") then
if intllib.make_gettext_pair then
S = intllib.make_gettext_pair()
else
S = intllib.Getter()
end
else
S = function(s) return s end
end end
biome_lib.intllib = S
local c1 = minetest.settings:get("biome_lib_default_grow_through_nodes") local c1 = minetest.settings:get("biome_lib_default_grow_through_nodes")
biome_lib.default_grow_through_nodes = {["air"] = true} biome_lib.default_grow_through_nodes = {["air"] = true}
@ -85,15 +76,18 @@ minetest.after(0.01, function()
biome_lib.dbg("All mapgen registrations completed.", 0) biome_lib.dbg("All mapgen registrations completed.", 0)
if n > 0 then if n > 0 then
biome_lib.dbg("Total items/actions to handle manually: "..n.." ("..#biome_lib.actionslist_no_aircheck.." without air checks)", 0) biome_lib.dbg("Total items/actions to handle manually: "..n..
biome_lib.dbg("Total surface types to handle manually: "..#biome_lib.surfaceslist_aircheck + #biome_lib.surfaceslist_no_aircheck, 0) " ("..#biome_lib.actionslist_no_aircheck.." without air checks)", 0)
biome_lib.dbg("Total surface types to handle manually: "
..#biome_lib.surfaceslist_aircheck + #biome_lib.surfaceslist_no_aircheck, 0)
else else
biome_lib.dbg("There are no \"handle manually\" items/actions registered,", 0) biome_lib.dbg("There are no \"handle manually\" items/actions registered,", 0)
biome_lib.dbg("so the mapblock queue will not be not used this session.", 0) biome_lib.dbg("so the mapblock queue will not be used this session.", 0)
end end
biome_lib.dbg("Items sent to the engine's decorations handler: "..#biome_lib.registered_decorations, 0) biome_lib.dbg("Items sent to the engine's decorations handler: "..#biome_lib.registered_decorations, 0)
biome_lib.dbg("Elevation range: "..biome_lib.mapgen_elevation_limit.min.." to "..string.format("%+d", biome_lib.mapgen_elevation_limit.max).." meters.", 0) biome_lib.dbg("Elevation range: "..biome_lib.mapgen_elevation_limit.min.." to "..
string.format("%+d", biome_lib.mapgen_elevation_limit.max).." meters.", 0)
if n > 0 then if n > 0 then
dofile(biome_lib.modpath .. "/block_queue_checks.lua") dofile(biome_lib.modpath .. "/block_queue_checks.lua")

View File

@ -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

View File

@ -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.

View File

@ -1,5 +0,0 @@
# Translation by inpos
someone = кто-то
Sorry, %s owns that spot. = Извините, но %s уже является владельцем этой точки.
[Plantlife Library] Loaded = [Plantlife Library] Загружена

View File

@ -1,5 +0,0 @@
# Template
someone =
Sorry, %s owns that spot. =
[Plantlife Library] Loaded =

View File

@ -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

View File

@ -1,3 +1,5 @@
name = biome_lib name = biome_lib
title = Biome Library
description = The biome spawning and management library for Plantlife, Moretrees, Tiny Trees, and other mods that originally depended on plants_lib from the plantlife modpack.
optional_depends = default
min_minetest_version = 5.2.0 min_minetest_version = 5.2.0
optional_depends = default, intllib

View File

@ -6,7 +6,7 @@ function biome_lib.find_adjacent_wall(pos, verticals, randomflag)
local verts = dump(verticals) local verts = dump(verticals)
if randomflag then if randomflag then
local walltab = {} 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] = 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+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] = 5 end