update
|
@ -74,8 +74,14 @@ load_mod_unifieddyes = true
|
||||||
load_mod_font_api = true
|
load_mod_font_api = true
|
||||||
load_mod_display_api = true
|
load_mod_display_api = true
|
||||||
load_mod_basic_materials = true
|
load_mod_basic_materials = true
|
||||||
|
load_mod_trees_lib = true
|
||||||
|
load_mod_biome_lib = true
|
||||||
|
load_mod_moretrees = true
|
||||||
|
load_mod_vines = true
|
||||||
load_mod_intllib = true
|
load_mod_intllib = true
|
||||||
" >> /home/minetest/.minetest/worlds/world/world.mt
|
" >> /home/minetest/.minetest/worlds/world/world.mt
|
||||||
|
|
||||||
chown minetest:minetest /home/minetest/ -cR
|
chown minetest:minetest /home/minetest/ -cR
|
||||||
|
|
||||||
|
echo "Start minetestsrv service"
|
||||||
systemctl start minetestsrv
|
systemctl start minetestsrv
|
||||||
|
|
|
@ -49,9 +49,13 @@ git clone --depth 1 --branch master https://github.com/minetest-mods/mymasonhamm
|
||||||
git clone --depth 1 --branch master https://github.com/minetest-mods/mywoodslopes.git
|
git clone --depth 1 --branch master https://github.com/minetest-mods/mywoodslopes.git
|
||||||
git clone --depth 1 --branch master https://github.com/minetest-mods/display_api.git
|
git clone --depth 1 --branch master https://github.com/minetest-mods/display_api.git
|
||||||
git clone --depth 1 --branch master https://github.com/minetest-mods/font_api.git
|
git clone --depth 1 --branch master https://github.com/minetest-mods/font_api.git
|
||||||
git clone --depth 1 --branch master https://github.com/minetest-mods/intllib.git
|
|
||||||
git clone --depth 1 --branch master https://gitlab.com/VanessaE/unifieddyes.git
|
git clone --depth 1 --branch master https://gitlab.com/VanessaE/unifieddyes.git
|
||||||
git clone --depth 1 --branch master https://gitlab.com/VanessaE/basic_materials.git
|
git clone --depth 1 --branch master https://gitlab.com/VanessaE/basic_materials.git
|
||||||
|
git clone --depth 1 --branch master https://github.com/minetest-mods/trees_lib.git
|
||||||
|
git clone --depth 1 --branch master https://gitlab.com/VanessaE/biome_lib.git
|
||||||
|
git clone --depth 1 --branch master https://gitlab.com/VanessaE/moretrees.git
|
||||||
|
git clone --depth 1 --branch master https://github.com/minetest-mods/intllib.git
|
||||||
|
git clone --depth 1 --branch master https://github.com/bas080/vines.git
|
||||||
rm */.git -rf
|
rm */.git -rf
|
||||||
rm */.gitignore -f
|
rm */.gitignore -f
|
||||||
rm */.gitattributes -f
|
rm */.gitattributes -f
|
||||||
|
|
590
mods/biome_lib/API.txt
Normal file
|
@ -0,0 +1,590 @@
|
||||||
|
This document describes the Plantlife mod API.
|
||||||
|
|
||||||
|
Last revision: 2015-02-16
|
||||||
|
|
||||||
|
|
||||||
|
=========
|
||||||
|
Functions
|
||||||
|
=========
|
||||||
|
|
||||||
|
There are three main functions defined by the main "biome_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 "biome_lib" method,
|
||||||
|
e.g. biome_lib: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.
|
||||||
|
|
||||||
|
label = string, -- set this to identify the ABM for Minetest's profiler
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
=====
|
||||||
|
biome_lib: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)
|
||||||
|
|
||||||
|
|
||||||
|
=====
|
||||||
|
biome_lib: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 = {
|
||||||
|
label = string, -- set this to identify the ABM for Minetest's
|
||||||
|
-- profiler. If not set, biome_lib will set it to
|
||||||
|
-- "biome_lib grow_plants(): " appended with the node
|
||||||
|
-- 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
|
||||||
|
-- into something else. This value is passed to the
|
||||||
|
-- ABM as the "nodenames" parameter, so the plants
|
||||||
|
-- themselves are the ABM trigger, rather than
|
||||||
|
-- the ground they spawned on. A plant will only grow
|
||||||
|
-- if the node above it is air. If you use a table,
|
||||||
|
-- note that all nodes referenced therein will be
|
||||||
|
-- grown into the same final 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.
|
||||||
|
|
||||||
|
=====
|
||||||
|
biome_lib:generate_tree(pos, treemodel)
|
||||||
|
biome_lib: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 biome_lib's tree-growing functions in general,
|
||||||
|
perhaps to execute something extra whenever a tree is spawned.
|
||||||
|
|
||||||
|
biome_lib: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.
|
||||||
|
|
||||||
|
biome_lib: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
|
||||||
|
|
||||||
|
To slow down the playback of the queue (e.g. for really slow machines where
|
||||||
|
the 0.2 second max limiter isn't enough), set:
|
||||||
|
|
||||||
|
biome_lib_queue_run_ratio = <some value 1 to 100>
|
||||||
|
|
||||||
|
Default is 100 (basically percent of maximum runtime)
|
||||||
|
|
||||||
|
======================
|
||||||
|
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:
|
||||||
|
|
||||||
|
biome_lib.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)
|
||||||
|
|
600
mods/biome_lib/LICENSE
Normal file
|
@ -0,0 +1,600 @@
|
||||||
|
License for code: LGPL 3.0
|
||||||
|
License for media and all other assets: CC-by-SA 4.0
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
This version of the GNU Lesser General Public License incorporates
|
||||||
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
|
0. Additional Definitions.
|
||||||
|
|
||||||
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
General Public License.
|
||||||
|
|
||||||
|
"The Library" refers to a covered work governed by this License,
|
||||||
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
|
An "Application" is any work that makes use of an interface provided
|
||||||
|
by the Library, but which is not otherwise based on the Library.
|
||||||
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
|
Application with the Library. The particular version of the Library
|
||||||
|
with which the Combined Work was made is also called the "Linked
|
||||||
|
Version".
|
||||||
|
|
||||||
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
|
object code and/or source code for the Application, including any data
|
||||||
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
|
facility refers to a function or data to be supplied by an Application
|
||||||
|
that uses the facility (other than as an argument passed when the
|
||||||
|
facility is invoked), then you may convey a copy of the modified
|
||||||
|
version:
|
||||||
|
|
||||||
|
a) under this License, provided that you make a good faith effort to
|
||||||
|
ensure that, in the event an Application does not supply the
|
||||||
|
function or data, the facility still operates, and performs
|
||||||
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
|
this License applicable to that copy.
|
||||||
|
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
|
The object code form of an Application may incorporate material from
|
||||||
|
a header file that is part of the Library. You may convey such object
|
||||||
|
code under terms of your choice, provided that, if the incorporated
|
||||||
|
material is not limited to numerical parameters, data structure
|
||||||
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the object code that the
|
||||||
|
Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
4. Combined Works.
|
||||||
|
|
||||||
|
You may convey a Combined Work under terms of your choice that,
|
||||||
|
taken together, effectively do not restrict modification of the
|
||||||
|
portions of the Library contained in the Combined Work and reverse
|
||||||
|
engineering for debugging such modifications, if you also do each of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
|
the Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
c) For a Combined Work that displays copyright notices during
|
||||||
|
execution, include the copyright notice for the Library among
|
||||||
|
these notices, as well as a reference directing the user to the
|
||||||
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
|
d) Do one of the following:
|
||||||
|
|
||||||
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
|
License, and the Corresponding Application Code in a form
|
||||||
|
suitable for, and under terms that permit, the user to
|
||||||
|
recombine or relink the Application with a modified version of
|
||||||
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
|
Corresponding Source.
|
||||||
|
|
||||||
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
|
a copy of the Library already present on the user's computer
|
||||||
|
system, and (b) will operate properly with a modified version
|
||||||
|
of the Library that is interface-compatible with the Linked
|
||||||
|
Version.
|
||||||
|
|
||||||
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
|
be required to provide such information under section 6 of the
|
||||||
|
GNU GPL, and only to the extent that such information is
|
||||||
|
necessary to install and execute a modified version of the
|
||||||
|
Combined Work produced by recombining or relinking the
|
||||||
|
Application with a modified version of the Linked Version. (If
|
||||||
|
you use option 4d0, the Installation Information must accompany
|
||||||
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
|
5. Combined Libraries.
|
||||||
|
|
||||||
|
You may place library facilities that are a work based on the
|
||||||
|
Library side by side in a single library together with other library
|
||||||
|
facilities that are not Applications and are not covered by this
|
||||||
|
License, and convey such a combined library under terms of your
|
||||||
|
choice, if you do both of the following:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work based
|
||||||
|
on the Library, uncombined with any other library facilities,
|
||||||
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library that part of it
|
||||||
|
is a work based on the Library, and explaining where to find the
|
||||||
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the GNU Lesser General Public License from time to time. Such new
|
||||||
|
versions will be similar in spirit to the present version, but may
|
||||||
|
differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Library as you received it specifies that a certain numbered version
|
||||||
|
of the GNU Lesser General Public License "or any later version"
|
||||||
|
applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that published version or of any later version
|
||||||
|
published by the Free Software Foundation. If the Library as you
|
||||||
|
received it does not specify a version number of the GNU Lesser
|
||||||
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Library as you received it specifies that a proxy can decide
|
||||||
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
|
permanent authorization for you to choose that version for the
|
||||||
|
Library.
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Attribution-ShareAlike 4.0 International
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Creative Commons Corporation ("Creative Commons") is not a law firm and
|
||||||
|
does not provide legal services or legal advice. Distribution of
|
||||||
|
Creative Commons public licenses does not create a lawyer-client or
|
||||||
|
other relationship. Creative Commons makes its licenses and related
|
||||||
|
information available on an "as-is" basis. Creative Commons gives no
|
||||||
|
warranties regarding its licenses, any material licensed under their
|
||||||
|
terms and conditions, or any related information. Creative Commons
|
||||||
|
disclaims all liability for damages resulting from their use to the
|
||||||
|
fullest extent possible.
|
||||||
|
|
||||||
|
Using Creative Commons Public Licenses
|
||||||
|
|
||||||
|
Creative Commons public licenses provide a standard set of terms and
|
||||||
|
conditions that creators and other rights holders may use to share
|
||||||
|
original works of authorship and other material subject to copyright
|
||||||
|
and certain other rights specified in the public license below. The
|
||||||
|
following considerations are for informational purposes only, are not
|
||||||
|
exhaustive, and do not form part of our licenses.
|
||||||
|
|
||||||
|
Considerations for licensors: Our public licenses are
|
||||||
|
intended for use by those authorized to give the public
|
||||||
|
permission to use material in ways otherwise restricted by
|
||||||
|
copyright and certain other rights. Our licenses are
|
||||||
|
irrevocable. Licensors should read and understand the terms
|
||||||
|
and conditions of the license they choose before applying it.
|
||||||
|
Licensors should also secure all rights necessary before
|
||||||
|
applying our licenses so that the public can reuse the
|
||||||
|
material as expected. Licensors should clearly mark any
|
||||||
|
material not subject to the license. This includes other CC-
|
||||||
|
licensed material, or material used under an exception or
|
||||||
|
limitation to copyright. More considerations for licensors:
|
||||||
|
wiki.creativecommons.org/Considerations_for_licensors
|
||||||
|
|
||||||
|
Considerations for the public: By using one of our public
|
||||||
|
licenses, a licensor grants the public permission to use the
|
||||||
|
licensed material under specified terms and conditions. If
|
||||||
|
the licensor's permission is not necessary for any reason--for
|
||||||
|
example, because of any applicable exception or limitation to
|
||||||
|
copyright--then that use is not regulated by the license. Our
|
||||||
|
licenses grant only permissions under copyright and certain
|
||||||
|
other rights that a licensor has authority to grant. Use of
|
||||||
|
the licensed material may still be restricted for other
|
||||||
|
reasons, including because others have copyright or other
|
||||||
|
rights in the material. A licensor may make special requests,
|
||||||
|
such as asking that all changes be marked or described.
|
||||||
|
Although not required by our licenses, you are encouraged to
|
||||||
|
respect those requests where reasonable. More considerations
|
||||||
|
for the public:
|
||||||
|
wiki.creativecommons.org/Considerations_for_licensees
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Creative Commons Attribution-ShareAlike 4.0 International Public
|
||||||
|
License
|
||||||
|
|
||||||
|
By exercising the Licensed Rights (defined below), You accept and agree
|
||||||
|
to be bound by the terms and conditions of this Creative Commons
|
||||||
|
Attribution-ShareAlike 4.0 International Public License ("Public
|
||||||
|
License"). To the extent this Public License may be interpreted as a
|
||||||
|
contract, You are granted the Licensed Rights in consideration of Your
|
||||||
|
acceptance of these terms and conditions, and the Licensor grants You
|
||||||
|
such rights in consideration of benefits the Licensor receives from
|
||||||
|
making the Licensed Material available under these terms and
|
||||||
|
conditions.
|
||||||
|
|
||||||
|
|
||||||
|
Section 1 -- Definitions.
|
||||||
|
|
||||||
|
a. Adapted Material means material subject to Copyright and Similar
|
||||||
|
Rights that is derived from or based upon the Licensed Material
|
||||||
|
and in which the Licensed Material is translated, altered,
|
||||||
|
arranged, transformed, or otherwise modified in a manner requiring
|
||||||
|
permission under the Copyright and Similar Rights held by the
|
||||||
|
Licensor. For purposes of this Public License, where the Licensed
|
||||||
|
Material is a musical work, performance, or sound recording,
|
||||||
|
Adapted Material is always produced where the Licensed Material is
|
||||||
|
synched in timed relation with a moving image.
|
||||||
|
|
||||||
|
b. Adapter's License means the license You apply to Your Copyright
|
||||||
|
and Similar Rights in Your contributions to Adapted Material in
|
||||||
|
accordance with the terms and conditions of this Public License.
|
||||||
|
|
||||||
|
c. BY-SA Compatible License means a license listed at
|
||||||
|
creativecommons.org/compatiblelicenses, approved by Creative
|
||||||
|
Commons as essentially the equivalent of this Public License.
|
||||||
|
|
||||||
|
d. Copyright and Similar Rights means copyright and/or similar rights
|
||||||
|
closely related to copyright including, without limitation,
|
||||||
|
performance, broadcast, sound recording, and Sui Generis Database
|
||||||
|
Rights, without regard to how the rights are labeled or
|
||||||
|
categorized. For purposes of this Public License, the rights
|
||||||
|
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
||||||
|
Rights.
|
||||||
|
|
||||||
|
e. Effective Technological Measures means those measures that, in the
|
||||||
|
absence of proper authority, may not be circumvented under laws
|
||||||
|
fulfilling obligations under Article 11 of the WIPO Copyright
|
||||||
|
Treaty adopted on December 20, 1996, and/or similar international
|
||||||
|
agreements.
|
||||||
|
|
||||||
|
f. Exceptions and Limitations means fair use, fair dealing, and/or
|
||||||
|
any other exception or limitation to Copyright and Similar Rights
|
||||||
|
that applies to Your use of the Licensed Material.
|
||||||
|
|
||||||
|
g. License Elements means the license attributes listed in the name
|
||||||
|
of a Creative Commons Public License. The License Elements of this
|
||||||
|
Public License are Attribution and ShareAlike.
|
||||||
|
|
||||||
|
h. Licensed Material means the artistic or literary work, database,
|
||||||
|
or other material to which the Licensor applied this Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
i. Licensed Rights means the rights granted to You subject to the
|
||||||
|
terms and conditions of this Public License, which are limited to
|
||||||
|
all Copyright and Similar Rights that apply to Your use of the
|
||||||
|
Licensed Material and that the Licensor has authority to license.
|
||||||
|
|
||||||
|
j. Licensor means the individual(s) or entity(ies) granting rights
|
||||||
|
under this Public License.
|
||||||
|
|
||||||
|
k. Share means to provide material to the public by any means or
|
||||||
|
process that requires permission under the Licensed Rights, such
|
||||||
|
as reproduction, public display, public performance, distribution,
|
||||||
|
dissemination, communication, or importation, and to make material
|
||||||
|
available to the public including in ways that members of the
|
||||||
|
public may access the material from a place and at a time
|
||||||
|
individually chosen by them.
|
||||||
|
|
||||||
|
l. Sui Generis Database Rights means rights other than copyright
|
||||||
|
resulting from Directive 96/9/EC of the European Parliament and of
|
||||||
|
the Council of 11 March 1996 on the legal protection of databases,
|
||||||
|
as amended and/or succeeded, as well as other essentially
|
||||||
|
equivalent rights anywhere in the world.
|
||||||
|
|
||||||
|
m. You means the individual or entity exercising the Licensed Rights
|
||||||
|
under this Public License. Your has a corresponding meaning.
|
||||||
|
|
||||||
|
|
||||||
|
Section 2 -- Scope.
|
||||||
|
|
||||||
|
a. License grant.
|
||||||
|
|
||||||
|
1. Subject to the terms and conditions of this Public License,
|
||||||
|
the Licensor hereby grants You a worldwide, royalty-free,
|
||||||
|
non-sublicensable, non-exclusive, irrevocable license to
|
||||||
|
exercise the Licensed Rights in the Licensed Material to:
|
||||||
|
|
||||||
|
a. reproduce and Share the Licensed Material, in whole or
|
||||||
|
in part; and
|
||||||
|
|
||||||
|
b. produce, reproduce, and Share Adapted Material.
|
||||||
|
|
||||||
|
2. Exceptions and Limitations. For the avoidance of doubt, where
|
||||||
|
Exceptions and Limitations apply to Your use, this Public
|
||||||
|
License does not apply, and You do not need to comply with
|
||||||
|
its terms and conditions.
|
||||||
|
|
||||||
|
3. Term. The term of this Public License is specified in Section
|
||||||
|
6(a).
|
||||||
|
|
||||||
|
4. Media and formats; technical modifications allowed. The
|
||||||
|
Licensor authorizes You to exercise the Licensed Rights in
|
||||||
|
all media and formats whether now known or hereafter created,
|
||||||
|
and to make technical modifications necessary to do so. The
|
||||||
|
Licensor waives and/or agrees not to assert any right or
|
||||||
|
authority to forbid You from making technical modifications
|
||||||
|
necessary to exercise the Licensed Rights, including
|
||||||
|
technical modifications necessary to circumvent Effective
|
||||||
|
Technological Measures. For purposes of this Public License,
|
||||||
|
simply making modifications authorized by this Section 2(a)
|
||||||
|
(4) never produces Adapted Material.
|
||||||
|
|
||||||
|
5. Downstream recipients.
|
||||||
|
|
||||||
|
a. Offer from the Licensor -- Licensed Material. Every
|
||||||
|
recipient of the Licensed Material automatically
|
||||||
|
receives an offer from the Licensor to exercise the
|
||||||
|
Licensed Rights under the terms and conditions of this
|
||||||
|
Public License.
|
||||||
|
|
||||||
|
b. Additional offer from the Licensor -- Adapted Material.
|
||||||
|
Every recipient of Adapted Material from You
|
||||||
|
automatically receives an offer from the Licensor to
|
||||||
|
exercise the Licensed Rights in the Adapted Material
|
||||||
|
under the conditions of the Adapter's License You apply.
|
||||||
|
|
||||||
|
c. No downstream restrictions. You may not offer or impose
|
||||||
|
any additional or different terms or conditions on, or
|
||||||
|
apply any Effective Technological Measures to, the
|
||||||
|
Licensed Material if doing so restricts exercise of the
|
||||||
|
Licensed Rights by any recipient of the Licensed
|
||||||
|
Material.
|
||||||
|
|
||||||
|
6. No endorsement. Nothing in this Public License constitutes or
|
||||||
|
may be construed as permission to assert or imply that You
|
||||||
|
are, or that Your use of the Licensed Material is, connected
|
||||||
|
with, or sponsored, endorsed, or granted official status by,
|
||||||
|
the Licensor or others designated to receive attribution as
|
||||||
|
provided in Section 3(a)(1)(A)(i).
|
||||||
|
|
||||||
|
b. Other rights.
|
||||||
|
|
||||||
|
1. Moral rights, such as the right of integrity, are not
|
||||||
|
licensed under this Public License, nor are publicity,
|
||||||
|
privacy, and/or other similar personality rights; however, to
|
||||||
|
the extent possible, the Licensor waives and/or agrees not to
|
||||||
|
assert any such rights held by the Licensor to the limited
|
||||||
|
extent necessary to allow You to exercise the Licensed
|
||||||
|
Rights, but not otherwise.
|
||||||
|
|
||||||
|
2. Patent and trademark rights are not licensed under this
|
||||||
|
Public License.
|
||||||
|
|
||||||
|
3. To the extent possible, the Licensor waives any right to
|
||||||
|
collect royalties from You for the exercise of the Licensed
|
||||||
|
Rights, whether directly or through a collecting society
|
||||||
|
under any voluntary or waivable statutory or compulsory
|
||||||
|
licensing scheme. In all other cases the Licensor expressly
|
||||||
|
reserves any right to collect such royalties.
|
||||||
|
|
||||||
|
|
||||||
|
Section 3 -- License Conditions.
|
||||||
|
|
||||||
|
Your exercise of the Licensed Rights is expressly made subject to the
|
||||||
|
following conditions.
|
||||||
|
|
||||||
|
a. Attribution.
|
||||||
|
|
||||||
|
1. If You Share the Licensed Material (including in modified
|
||||||
|
form), You must:
|
||||||
|
|
||||||
|
a. retain the following if it is supplied by the Licensor
|
||||||
|
with the Licensed Material:
|
||||||
|
|
||||||
|
i. identification of the creator(s) of the Licensed
|
||||||
|
Material and any others designated to receive
|
||||||
|
attribution, in any reasonable manner requested by
|
||||||
|
the Licensor (including by pseudonym if
|
||||||
|
designated);
|
||||||
|
|
||||||
|
ii. a copyright notice;
|
||||||
|
|
||||||
|
iii. a notice that refers to this Public License;
|
||||||
|
|
||||||
|
iv. a notice that refers to the disclaimer of
|
||||||
|
warranties;
|
||||||
|
|
||||||
|
v. a URI or hyperlink to the Licensed Material to the
|
||||||
|
extent reasonably practicable;
|
||||||
|
|
||||||
|
b. indicate if You modified the Licensed Material and
|
||||||
|
retain an indication of any previous modifications; and
|
||||||
|
|
||||||
|
c. indicate the Licensed Material is licensed under this
|
||||||
|
Public License, and include the text of, or the URI or
|
||||||
|
hyperlink to, this Public License.
|
||||||
|
|
||||||
|
2. You may satisfy the conditions in Section 3(a)(1) in any
|
||||||
|
reasonable manner based on the medium, means, and context in
|
||||||
|
which You Share the Licensed Material. For example, it may be
|
||||||
|
reasonable to satisfy the conditions by providing a URI or
|
||||||
|
hyperlink to a resource that includes the required
|
||||||
|
information.
|
||||||
|
|
||||||
|
3. If requested by the Licensor, You must remove any of the
|
||||||
|
information required by Section 3(a)(1)(A) to the extent
|
||||||
|
reasonably practicable.
|
||||||
|
|
||||||
|
b. ShareAlike.
|
||||||
|
|
||||||
|
In addition to the conditions in Section 3(a), if You Share
|
||||||
|
Adapted Material You produce, the following conditions also apply.
|
||||||
|
|
||||||
|
1. The Adapter's License You apply must be a Creative Commons
|
||||||
|
license with the same License Elements, this version or
|
||||||
|
later, or a BY-SA Compatible License.
|
||||||
|
|
||||||
|
2. You must include the text of, or the URI or hyperlink to, the
|
||||||
|
Adapter's License You apply. You may satisfy this condition
|
||||||
|
in any reasonable manner based on the medium, means, and
|
||||||
|
context in which You Share Adapted Material.
|
||||||
|
|
||||||
|
3. You may not offer or impose any additional or different terms
|
||||||
|
or conditions on, or apply any Effective Technological
|
||||||
|
Measures to, Adapted Material that restrict exercise of the
|
||||||
|
rights granted under the Adapter's License You apply.
|
||||||
|
|
||||||
|
|
||||||
|
Section 4 -- Sui Generis Database Rights.
|
||||||
|
|
||||||
|
Where the Licensed Rights include Sui Generis Database Rights that
|
||||||
|
apply to Your use of the Licensed Material:
|
||||||
|
|
||||||
|
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
||||||
|
to extract, reuse, reproduce, and Share all or a substantial
|
||||||
|
portion of the contents of the database;
|
||||||
|
|
||||||
|
b. if You include all or a substantial portion of the database
|
||||||
|
contents in a database in which You have Sui Generis Database
|
||||||
|
Rights, then the database in which You have Sui Generis Database
|
||||||
|
Rights (but not its individual contents) is Adapted Material,
|
||||||
|
|
||||||
|
including for purposes of Section 3(b); and
|
||||||
|
c. You must comply with the conditions in Section 3(a) if You Share
|
||||||
|
all or a substantial portion of the contents of the database.
|
||||||
|
|
||||||
|
For the avoidance of doubt, this Section 4 supplements and does not
|
||||||
|
replace Your obligations under this Public License where the Licensed
|
||||||
|
Rights include other Copyright and Similar Rights.
|
||||||
|
|
||||||
|
|
||||||
|
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
||||||
|
|
||||||
|
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
||||||
|
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
||||||
|
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
||||||
|
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
||||||
|
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
||||||
|
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
||||||
|
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
||||||
|
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
||||||
|
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
||||||
|
|
||||||
|
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
||||||
|
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
||||||
|
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
||||||
|
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
||||||
|
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
||||||
|
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
||||||
|
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
||||||
|
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
||||||
|
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
||||||
|
|
||||||
|
c. The disclaimer of warranties and limitation of liability provided
|
||||||
|
above shall be interpreted in a manner that, to the extent
|
||||||
|
possible, most closely approximates an absolute disclaimer and
|
||||||
|
waiver of all liability.
|
||||||
|
|
||||||
|
|
||||||
|
Section 6 -- Term and Termination.
|
||||||
|
|
||||||
|
a. This Public License applies for the term of the Copyright and
|
||||||
|
Similar Rights licensed here. However, if You fail to comply with
|
||||||
|
this Public License, then Your rights under this Public License
|
||||||
|
terminate automatically.
|
||||||
|
|
||||||
|
b. Where Your right to use the Licensed Material has terminated under
|
||||||
|
Section 6(a), it reinstates:
|
||||||
|
|
||||||
|
1. automatically as of the date the violation is cured, provided
|
||||||
|
it is cured within 30 days of Your discovery of the
|
||||||
|
violation; or
|
||||||
|
|
||||||
|
2. upon express reinstatement by the Licensor.
|
||||||
|
|
||||||
|
For the avoidance of doubt, this Section 6(b) does not affect any
|
||||||
|
right the Licensor may have to seek remedies for Your violations
|
||||||
|
of this Public License.
|
||||||
|
|
||||||
|
c. For the avoidance of doubt, the Licensor may also offer the
|
||||||
|
Licensed Material under separate terms or conditions or stop
|
||||||
|
distributing the Licensed Material at any time; however, doing so
|
||||||
|
will not terminate this Public License.
|
||||||
|
|
||||||
|
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
|
||||||
|
Section 7 -- Other Terms and Conditions.
|
||||||
|
|
||||||
|
a. The Licensor shall not be bound by any additional or different
|
||||||
|
terms or conditions communicated by You unless expressly agreed.
|
||||||
|
|
||||||
|
b. Any arrangements, understandings, or agreements regarding the
|
||||||
|
Licensed Material not stated herein are separate from and
|
||||||
|
independent of the terms and conditions of this Public License.
|
||||||
|
|
||||||
|
|
||||||
|
Section 8 -- Interpretation.
|
||||||
|
|
||||||
|
a. For the avoidance of doubt, this Public License does not, and
|
||||||
|
shall not be interpreted to, reduce, limit, restrict, or impose
|
||||||
|
conditions on any use of the Licensed Material that could lawfully
|
||||||
|
be made without permission under this Public License.
|
||||||
|
|
||||||
|
b. To the extent possible, if any provision of this Public License is
|
||||||
|
deemed unenforceable, it shall be automatically reformed to the
|
||||||
|
minimum extent necessary to make it enforceable. If the provision
|
||||||
|
cannot be reformed, it shall be severed from this Public License
|
||||||
|
without affecting the enforceability of the remaining terms and
|
||||||
|
conditions.
|
||||||
|
|
||||||
|
c. No term or condition of this Public License will be waived and no
|
||||||
|
failure to comply consented to unless expressly agreed to by the
|
||||||
|
Licensor.
|
||||||
|
|
||||||
|
d. Nothing in this Public License constitutes or may be interpreted
|
||||||
|
as a limitation upon, or waiver of, any privileges and immunities
|
||||||
|
that apply to the Licensor or You, including from the legal
|
||||||
|
processes of any jurisdiction or authority.
|
||||||
|
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Creative Commons is not a party to its public
|
||||||
|
licenses. Notwithstanding, Creative Commons may elect to apply one of
|
||||||
|
its public licenses to material it publishes and in those instances
|
||||||
|
will be considered the “Licensor.” The text of the Creative Commons
|
||||||
|
public licenses is dedicated to the public domain under the CC0 Public
|
||||||
|
Domain Dedication. Except for the limited purpose of indicating that
|
||||||
|
material is shared under a Creative Commons public license or as
|
||||||
|
otherwise permitted by the Creative Commons policies published at
|
||||||
|
creativecommons.org/policies, Creative Commons does not authorize the
|
||||||
|
use of the trademark "Creative Commons" or any other trademark or logo
|
||||||
|
of Creative Commons without its prior written consent including,
|
||||||
|
without limitation, in connection with any unauthorized modifications
|
||||||
|
to any of its public licenses or any other arrangements,
|
||||||
|
understandings, or agreements concerning use of licensed material. For
|
||||||
|
the avoidance of doubt, this paragraph does not form part of the
|
||||||
|
public licenses.
|
||||||
|
|
||||||
|
Creative Commons may be contacted at creativecommons.org.
|
28
mods/biome_lib/README.md
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# Biome Lib
|
||||||
|
|
||||||
|
This library's purpose is to allow other mods to add growing things to the map in a straightforward, simple manner. It contains all the core functions needed by mods and modpacks such as More Trees, Tiny Trees, Plantlife, and others.
|
||||||
|
|
||||||
|
Spawning of plants is optionally sensitive to the amount of available light, elevation, nearness to other nodes, plant-to-plant density, water depth, and a whole host of controls.
|
||||||
|
|
||||||
|
All objects spawned or generated using this mod use Perlin noise to stay within simple biomes, rather than just letting everything just spread around the map randomly.
|
||||||
|
|
||||||
|
This library also features a basic temperature map, which should blend in nicely with SPlizard's Snow Biomes mod (the same Perlin settings are used, with the assumption that the edge of a snow biome is 0° Centigrade).
|
||||||
|
|
||||||
|
Both mapgen-based spawning and ABM-based spawning is supported. Growing code is strictly ABM-based. L-system trees can be spawned at mapgen time via the engine's spawn_tree() function and are quite fast.
|
||||||
|
|
||||||
|
It is primarily intended for mapgen v6, but it should work fine when used with mapgen v7.
|
||||||
|
|
||||||
|
**Dependencies**: default from minetest_game
|
||||||
|
|
||||||
|
**Recommends**: [Plantlife Modpack](https://github.com/minetest-mods/plantlife_modpack),
|
||||||
|
[More Trees](https://github.com/minetest-mods/moretrees)
|
||||||
|
|
||||||
|
**API**: This mod supplies a small number of very powerful functions. They are, briefly:
|
||||||
|
|
||||||
|
* biome_lib:register_generate_plant()
|
||||||
|
* biome_lib:spawn_on_surfaces()
|
||||||
|
* biome_lib:grow_plants()
|
||||||
|
* biome_lib:find_valid_wall()
|
||||||
|
* biome_lib:is_node_loaded()
|
||||||
|
|
||||||
|
For a complete description of these functions as well as several of the internal variables within the mod, [read the API.txt document](https://raw.githubusercontent.com/minetest-mods/biome_lib/master/API.txt) included in this package.
|
3
mods/biome_lib/depends.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
default
|
||||||
|
intllib?
|
||||||
|
|
1
mods/biome_lib/description.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
The biome spawning and management library for Plantlife, Moretrees, Tiny Trees, and other mods that originally depended on plants_lib from the plantlife modpack.
|
90
mods/biome_lib/growth.lua
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
local time_scale = ...
|
||||||
|
|
||||||
|
-- The growing ABM
|
||||||
|
|
||||||
|
function biome_lib.check_surface(name, nodes)
|
||||||
|
if not nodes then return true end
|
||||||
|
if type(nodes) == "string" then return nodes == name end
|
||||||
|
if nodes.set and nodes[name] then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
for _, n in ipairs(nodes) do
|
||||||
|
if name == n then return true end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function biome_lib: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
|
||||||
|
|
||||||
|
local n
|
||||||
|
|
||||||
|
if type(options.grow_plant) == "table" then
|
||||||
|
n = "multi: "..options.grow_plant[1]..", ..."
|
||||||
|
else
|
||||||
|
n = options.grow_plant
|
||||||
|
end
|
||||||
|
|
||||||
|
options.label = options.label or "biome_lib grow_plants(): "..n
|
||||||
|
|
||||||
|
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,
|
||||||
|
label = options.label,
|
||||||
|
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 = biome_lib: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
|
||||||
|
if options.grow_vertically and walldir then
|
||||||
|
if biome_lib:search_downward(pos, options.height_limit, options.ground_nodes) then
|
||||||
|
minetest.swap_node(p_top, { name = options.grow_plant, param2 = walldir})
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif biome_lib.check_surface(n_bot.name, options.grow_nodes) then
|
||||||
|
if not options.grow_result and not options.grow_function then
|
||||||
|
minetest.swap_node(pos, biome_lib.air)
|
||||||
|
|
||||||
|
else
|
||||||
|
biome_lib:replace_object(pos, options.grow_result, options.grow_function, options.facedir, options.seed_diff)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- spawn_tree() on generate is routed through here so that other mods can hook
|
||||||
|
-- into it.
|
||||||
|
|
||||||
|
function biome_lib: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 biome_lib:grow_tree(pos, nodes_or_function_or_model)
|
||||||
|
minetest.spawn_tree(pos, nodes_or_function_or_model)
|
||||||
|
end
|
736
mods/biome_lib/init.lua
Normal file
|
@ -0,0 +1,736 @@
|
||||||
|
-- Biome library mod by Vanessa Ezekowitz
|
||||||
|
--
|
||||||
|
-- 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
|
||||||
|
|
||||||
|
biome_lib = {}
|
||||||
|
biome_lib.air = {name = "air"}
|
||||||
|
|
||||||
|
plantslib = setmetatable({}, { __index=function(t,k) print("Use of deprecated function:", k) return biome_lib[k] end })
|
||||||
|
|
||||||
|
biome_lib.blocklist_aircheck = {}
|
||||||
|
biome_lib.blocklist_no_aircheck = {}
|
||||||
|
|
||||||
|
biome_lib.surface_nodes_aircheck = {}
|
||||||
|
biome_lib.surface_nodes_no_aircheck = {}
|
||||||
|
|
||||||
|
biome_lib.surfaceslist_aircheck = {}
|
||||||
|
biome_lib.surfaceslist_no_aircheck = {}
|
||||||
|
|
||||||
|
biome_lib.actioncount_aircheck = {}
|
||||||
|
biome_lib.actioncount_no_aircheck = {}
|
||||||
|
|
||||||
|
biome_lib.actionslist_aircheck = {}
|
||||||
|
biome_lib.actionslist_no_aircheck = {}
|
||||||
|
|
||||||
|
biome_lib.modpath = minetest.get_modpath("biome_lib")
|
||||||
|
|
||||||
|
biome_lib.total_no_aircheck_calls = 0
|
||||||
|
|
||||||
|
biome_lib.queue_run_ratio = tonumber(minetest.settings:get("biome_lib_queue_run_ratio")) or 100
|
||||||
|
|
||||||
|
-- Boilerplate to support localized strings if intllib mod is installed.
|
||||||
|
local 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
|
||||||
|
biome_lib.intllib = S
|
||||||
|
|
||||||
|
local DEBUG = false --... except if you want to spam the console with debugging info :-)
|
||||||
|
|
||||||
|
function biome_lib:dbg(msg)
|
||||||
|
if DEBUG then
|
||||||
|
print("[Plantlife] "..msg)
|
||||||
|
minetest.log("verbose", "[Plantlife] "..msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
biome_lib.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.settings:get("time_speed"))
|
||||||
|
|
||||||
|
if time_speed and time_speed > 0 then
|
||||||
|
time_scale = 72 / time_speed
|
||||||
|
end
|
||||||
|
|
||||||
|
--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 function get_biome_data(pos, perlin_fertile)
|
||||||
|
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)
|
||||||
|
if data then
|
||||||
|
return fertility, data.heat / 100, data.humidity / 100
|
||||||
|
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
|
||||||
|
|
||||||
|
function biome_lib: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 biome_lib: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 biome_lib: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
|
||||||
|
biome_lib: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
|
||||||
|
biome_lib:dbg("Warning: Registered function call using deprecated string method: "..dump(nodes_or_function_or_model))
|
||||||
|
end
|
||||||
|
|
||||||
|
if biomedef.check_air == false then
|
||||||
|
biome_lib:dbg("Register no-air-check mapgen hook: "..dump(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
|
||||||
|
if type(s) == "string" 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
|
||||||
|
biome_lib.surfaceslist_no_aircheck[#biome_lib.surfaceslist_no_aircheck + 1] = s
|
||||||
|
end
|
||||||
|
else
|
||||||
|
biome_lib: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(biome_lib.surfaceslist_no_aircheck, s) then
|
||||||
|
biome_lib.surfaceslist_no_aircheck[#biome_lib.surfaceslist_no_aircheck + 1] = s
|
||||||
|
end
|
||||||
|
else
|
||||||
|
biome_lib:dbg("Warning: Ignored no-air-check registration for undefined surface node: "..dump(s))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
biome_lib:dbg("Register with-air-checking mapgen hook: "..dump(nodes_or_function_or_model))
|
||||||
|
biome_lib.actionslist_aircheck[#biome_lib.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(biome_lib.surfaceslist_aircheck, s) then
|
||||||
|
biome_lib.surfaceslist_aircheck[#biome_lib.surfaceslist_aircheck + 1] = s
|
||||||
|
end
|
||||||
|
else
|
||||||
|
biome_lib: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(biome_lib.surfaceslist_aircheck, s) then
|
||||||
|
biome_lib.surfaceslist_aircheck[#biome_lib.surfaceslist_aircheck + 1] = s
|
||||||
|
end
|
||||||
|
else
|
||||||
|
biome_lib:dbg("Warning: Ignored with-air-checking registration for undefined surface node: "..dump(s))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Function to check whether a position matches the given biome definition
|
||||||
|
-- Returns true when the surface can be populated
|
||||||
|
|
||||||
|
local function populate_single_surface(biome, pos, perlin_fertile_area, checkair)
|
||||||
|
local p_top = { x = pos.x, y = pos.y + 1, z = pos.z }
|
||||||
|
|
||||||
|
if math.random(1, 100) <= biome.rarity then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local fertility, temperature, humidity = get_biome_data(pos, perlin_fertile_area)
|
||||||
|
|
||||||
|
local pos_biome_ok = pos.y >= biome.min_elevation and pos.y <= biome.max_elevation
|
||||||
|
and fertility > biome.plantlife_limit
|
||||||
|
and temperature <= biome.temp_min and temperature >= biome.temp_max
|
||||||
|
and humidity <= biome.humidity_min and humidity >= biome.humidity_max
|
||||||
|
|
||||||
|
if not pos_biome_ok then
|
||||||
|
return -- Y position mismatch, outside of biome
|
||||||
|
end
|
||||||
|
|
||||||
|
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 not surface_ok then
|
||||||
|
return -- Surface does not match the given node group/name
|
||||||
|
end
|
||||||
|
|
||||||
|
if checkair and minetest.get_node(p_top).name ~= "air" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if biome.below_nodes and
|
||||||
|
not string.find(dump(biome.below_nodes),
|
||||||
|
minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name
|
||||||
|
) then
|
||||||
|
return -- Node below does not match
|
||||||
|
end
|
||||||
|
|
||||||
|
if biome.ncount and
|
||||||
|
#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 then
|
||||||
|
return -- Not enough similar biome nodes around
|
||||||
|
end
|
||||||
|
|
||||||
|
if biome.near_nodes and
|
||||||
|
#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 then
|
||||||
|
return -- Long distance neighbours do not match
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Position fits into given biome
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function biome_lib:populate_surfaces(biome, nodes_or_function_or_model, snodes, checkair)
|
||||||
|
|
||||||
|
biome_lib: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 = vector.new(snodes[i])
|
||||||
|
if populate_single_surface(biome, pos, perlin_fertile_area, checkair) 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
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
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.swap_node(p_top, biome_lib.air)
|
||||||
|
minetest.swap_node({x=p_top.x, y=p_top.y+1, z=p_top.z}, biome_lib.air)
|
||||||
|
end
|
||||||
|
|
||||||
|
if biome.delete_above_surround then
|
||||||
|
minetest.swap_node({x=p_top.x-1, y=p_top.y, z=p_top.z}, biome_lib.air)
|
||||||
|
minetest.swap_node({x=p_top.x+1, y=p_top.y, z=p_top.z}, biome_lib.air)
|
||||||
|
minetest.swap_node({x=p_top.x, y=p_top.y, z=p_top.z-1}, biome_lib.air)
|
||||||
|
minetest.swap_node({x=p_top.x, y=p_top.y, z=p_top.z+1}, biome_lib.air)
|
||||||
|
|
||||||
|
minetest.swap_node({x=p_top.x-1, y=p_top.y+1, z=p_top.z}, biome_lib.air)
|
||||||
|
minetest.swap_node({x=p_top.x+1, y=p_top.y+1, z=p_top.z}, biome_lib.air)
|
||||||
|
minetest.swap_node({x=p_top.x, y=p_top.y+1, z=p_top.z-1}, biome_lib.air)
|
||||||
|
minetest.swap_node({x=p_top.x, y=p_top.y+1, z=p_top.z+1}, biome_lib.air)
|
||||||
|
end
|
||||||
|
|
||||||
|
if biome.spawn_replace_node then
|
||||||
|
minetest.swap_node(pos, biome_lib.air)
|
||||||
|
end
|
||||||
|
|
||||||
|
local objtype = type(nodes_or_function_or_model)
|
||||||
|
|
||||||
|
if objtype == "table" then
|
||||||
|
if nodes_or_function_or_model.axiom then
|
||||||
|
biome_lib:generate_tree(p_top, 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.swap_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.swap_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
|
||||||
|
biome_lib: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
|
||||||
|
|
||||||
|
-- Primary mapgen spawner, for mods that can work with air checking enabled on
|
||||||
|
-- a surface during the initial map read stage.
|
||||||
|
|
||||||
|
function biome_lib:generate_block_with_air_checking()
|
||||||
|
if #biome_lib.blocklist_aircheck == 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local minp = biome_lib.blocklist_aircheck[1][1]
|
||||||
|
local maxp = biome_lib.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 biome_lib.surface_nodes_aircheck.blockhash then
|
||||||
|
|
||||||
|
if type(minetest.find_nodes_in_area_under_air) == "function" then -- use newer API call
|
||||||
|
biome_lib.surface_nodes_aircheck.blockhash =
|
||||||
|
minetest.find_nodes_in_area_under_air(minp, maxp, biome_lib.surfaceslist_aircheck)
|
||||||
|
else
|
||||||
|
local search_area = minetest.find_nodes_in_area(minp, maxp, biome_lib.surfaceslist_aircheck)
|
||||||
|
|
||||||
|
-- search the generated block for air-bounded surfaces the slow way.
|
||||||
|
|
||||||
|
biome_lib.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
|
||||||
|
biome_lib.surface_nodes_aircheck.blockhash[#biome_lib.surface_nodes_aircheck.blockhash + 1] = pos
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
biome_lib.actioncount_aircheck.blockhash = 1
|
||||||
|
|
||||||
|
else
|
||||||
|
if biome_lib.actioncount_aircheck.blockhash <= #biome_lib.actionslist_aircheck then
|
||||||
|
-- [1] is biome, [2] is node/function/model
|
||||||
|
biome_lib:populate_surfaces(
|
||||||
|
biome_lib.actionslist_aircheck[biome_lib.actioncount_aircheck.blockhash][1],
|
||||||
|
biome_lib.actionslist_aircheck[biome_lib.actioncount_aircheck.blockhash][2],
|
||||||
|
biome_lib.surface_nodes_aircheck.blockhash, true)
|
||||||
|
biome_lib.actioncount_aircheck.blockhash = biome_lib.actioncount_aircheck.blockhash + 1
|
||||||
|
else
|
||||||
|
if biome_lib.surface_nodes_aircheck.blockhash then
|
||||||
|
table.remove(biome_lib.blocklist_aircheck, 1)
|
||||||
|
biome_lib.surface_nodes_aircheck.blockhash = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Secondary mapgen spawner, for mods that require disabling of
|
||||||
|
-- checking for air during the initial map read stage.
|
||||||
|
|
||||||
|
function biome_lib:generate_block_no_aircheck()
|
||||||
|
if #biome_lib.blocklist_no_aircheck == 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local minp = biome_lib.blocklist_no_aircheck[1][1]
|
||||||
|
local maxp = biome_lib.blocklist_no_aircheck[1][2]
|
||||||
|
|
||||||
|
local blockhash = minetest.hash_node_position(minp)
|
||||||
|
|
||||||
|
if not biome_lib.surface_nodes_no_aircheck.blockhash then
|
||||||
|
|
||||||
|
-- directly read the block to be searched into the chunk cache
|
||||||
|
|
||||||
|
biome_lib.surface_nodes_no_aircheck.blockhash =
|
||||||
|
minetest.find_nodes_in_area(minp, maxp, biome_lib.surfaceslist_no_aircheck)
|
||||||
|
biome_lib.actioncount_no_aircheck.blockhash = 1
|
||||||
|
|
||||||
|
else
|
||||||
|
if biome_lib.actioncount_no_aircheck.blockhash <= #biome_lib.actionslist_no_aircheck then
|
||||||
|
biome_lib:populate_surfaces(
|
||||||
|
biome_lib.actionslist_no_aircheck[biome_lib.actioncount_no_aircheck.blockhash][1],
|
||||||
|
biome_lib.actionslist_no_aircheck[biome_lib.actioncount_no_aircheck.blockhash][2],
|
||||||
|
biome_lib.surface_nodes_no_aircheck.blockhash, false)
|
||||||
|
biome_lib.actioncount_no_aircheck.blockhash = biome_lib.actioncount_no_aircheck.blockhash + 1
|
||||||
|
else
|
||||||
|
if biome_lib.surface_nodes_no_aircheck.blockhash then
|
||||||
|
table.remove(biome_lib.blocklist_no_aircheck, 1)
|
||||||
|
biome_lib.surface_nodes_no_aircheck.blockhash = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- "Play" them back, populating them with new stuff in the process
|
||||||
|
|
||||||
|
local step_duration = tonumber(minetest.settings:get("dedicated_server_step"))
|
||||||
|
minetest.register_globalstep(function(dtime)
|
||||||
|
if dtime >= step_duration + 0.1 -- don't attempt to populate if lag is already too high
|
||||||
|
or math.random(100) > biome_lib.queue_run_ratio
|
||||||
|
or (#biome_lib.blocklist_aircheck == 0 and #biome_lib.blocklist_no_aircheck == 0) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
biome_lib.globalstep_start_time = minetest.get_us_time()
|
||||||
|
biome_lib.globalstep_runtime = 0
|
||||||
|
while (#biome_lib.blocklist_aircheck > 0 or #biome_lib.blocklist_no_aircheck > 0)
|
||||||
|
and biome_lib.globalstep_runtime < 200000 do -- 0.2 seconds, in uS.
|
||||||
|
if #biome_lib.blocklist_aircheck > 0 then
|
||||||
|
biome_lib:generate_block_with_air_checking()
|
||||||
|
end
|
||||||
|
if #biome_lib.blocklist_no_aircheck > 0 then
|
||||||
|
biome_lib:generate_block_no_aircheck()
|
||||||
|
end
|
||||||
|
biome_lib.globalstep_runtime = minetest.get_us_time() - biome_lib.globalstep_start_time
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Play out the entire log all at once on shutdown
|
||||||
|
-- to prevent unpopulated map areas
|
||||||
|
|
||||||
|
minetest.register_on_shutdown(function()
|
||||||
|
if #biome_lib.blocklist_aircheck == 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
print("[biome_lib] Stand by, playing out the rest of the aircheck mapblock log")
|
||||||
|
print("(there are "..#biome_lib.blocklist_aircheck.." entries)...")
|
||||||
|
while #biome_lib.blocklist_aircheck > 0 do
|
||||||
|
biome_lib:generate_block_with_air_checking(0.1)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
minetest.register_on_shutdown(function()
|
||||||
|
if #biome_lib.blocklist_aircheck == 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
print("[biome_lib] Stand by, playing out the rest of the no-aircheck mapblock log")
|
||||||
|
print("(there are "..#biome_lib.blocklist_no_aircheck.." entries)...")
|
||||||
|
while #biome_lib.blocklist_no_aircheck > 0 do
|
||||||
|
biome_lib:generate_block_no_aircheck(0.1)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- The spawning ABM
|
||||||
|
|
||||||
|
function biome_lib: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
|
||||||
|
|
||||||
|
biome_lib:set_defaults(biome)
|
||||||
|
biome.spawn_plants_count = #(biome.spawn_plants)
|
||||||
|
|
||||||
|
local n
|
||||||
|
if type(biome.spawn_plants) == "table" then
|
||||||
|
n = "random: "..biome.spawn_plants[1]..", ..."
|
||||||
|
else
|
||||||
|
n = biome.spawn_plants
|
||||||
|
end
|
||||||
|
biome.label = biome.label or "biome_lib spawn_on_surfaces(): "..n
|
||||||
|
|
||||||
|
minetest.register_abm({
|
||||||
|
nodenames = biome.spawn_surfaces,
|
||||||
|
interval = biome.interval,
|
||||||
|
chance = biome.spawn_chance,
|
||||||
|
neighbors = biome.neighbors,
|
||||||
|
label = biome.label,
|
||||||
|
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 fertility, temperature, humidity = get_biome_data(pos, perlin_fertile_area)
|
||||||
|
|
||||||
|
local pos_biome_ok = pos.y >= biome.min_elevation and pos.y <= biome.max_elevation
|
||||||
|
and fertility > biome.plantlife_limit
|
||||||
|
and temperature <= biome.temp_min and temperature >= biome.temp_max
|
||||||
|
and humidity <= biome.humidity_min and humidity >= biome.humidity_max
|
||||||
|
and biome_lib:is_node_loaded(p_top)
|
||||||
|
|
||||||
|
if not pos_biome_ok then
|
||||||
|
return -- Outside of biome
|
||||||
|
end
|
||||||
|
|
||||||
|
local n_light = minetest.get_node_light(p_top, nil)
|
||||||
|
if n_light < biome.light_min or n_light > biome.light_max then
|
||||||
|
return -- Too dark or too bright
|
||||||
|
end
|
||||||
|
|
||||||
|
if 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
|
||||||
|
return -- Nodes to avoid are nearby
|
||||||
|
end
|
||||||
|
|
||||||
|
if biome.neighbors and biome.ncount and
|
||||||
|
#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 then
|
||||||
|
return -- Near neighbour nodes are not present
|
||||||
|
end
|
||||||
|
|
||||||
|
local NEAR_DST = biome.near_nodes_size
|
||||||
|
if biome.near_nodes and biome.near_nodes_count and biome.near_nodes_size and
|
||||||
|
#minetest.find_nodes_in_area(
|
||||||
|
{x=pos.x-NEAR_DST, y=pos.y-biome.near_nodes_vertical, z=pos.z-NEAR_DST},
|
||||||
|
{x=pos.x+NEAR_DST, y=pos.y+biome.near_nodes_vertical, z=pos.z+NEAR_DST},
|
||||||
|
biome.near_nodes
|
||||||
|
) < biome.near_nodes_count then
|
||||||
|
return -- Far neighbour nodes are not present
|
||||||
|
end
|
||||||
|
|
||||||
|
if (biome.air_count and biome.air_size) and
|
||||||
|
#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 then
|
||||||
|
return -- Not enough air
|
||||||
|
end
|
||||||
|
|
||||||
|
local walldir = biome_lib: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.swap_node(p_top, { name = biome.alt_wallnode, param2 = walldir })
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local currentsurface = minetest.get_node(pos).name
|
||||||
|
|
||||||
|
if currentsurface == "default:water_source" and
|
||||||
|
#minetest.find_nodes_in_area(
|
||||||
|
{x=pos.x, y=pos.y-biome.depth_max-1, z=pos.z},
|
||||||
|
vector.new(pos),
|
||||||
|
{"default:dirt", "default:dirt_with_grass", "default:sand"}
|
||||||
|
) == 0 then
|
||||||
|
return -- On water but no ground nearby
|
||||||
|
end
|
||||||
|
|
||||||
|
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.swap_node(p_top, { name = plant_to_spawn, param2 = fdir })
|
||||||
|
end
|
||||||
|
elseif biome.spawn_replace_node then
|
||||||
|
minetest.swap_node(pos, { name = plant_to_spawn, param2 = fdir })
|
||||||
|
|
||||||
|
elseif biome.spawn_on_side then
|
||||||
|
local onside = biome_lib:find_open_side(pos)
|
||||||
|
if onside then
|
||||||
|
minetest.swap_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.swap_node({x=pos.x, y=pos.y-1, z=pos.z}, { name = plant_to_spawn, param2 = fdir} )
|
||||||
|
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 biome_lib:replace_object(pos, replacement, grow_function, walldir, seeddiff)
|
||||||
|
local growtype = type(grow_function)
|
||||||
|
if growtype == "table" then
|
||||||
|
minetest.swap_node(pos, biome_lib.air)
|
||||||
|
biome_lib: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 fertility, temperature, _ = get_biome_data(pos, perlin_fertile_area)
|
||||||
|
grow_function(pos, fertility, temperature, walldir)
|
||||||
|
return
|
||||||
|
elseif growtype == "string" then
|
||||||
|
local perlin_fertile_area = minetest.get_perlin(seeddiff, perlin_octaves, perlin_persistence, perlin_scale)
|
||||||
|
local fertility, temperature, _ = get_biome_data(pos, perlin_fertile_area)
|
||||||
|
assert(loadstring(grow_function.."(...)"))(pos, fertility, temperature, walldir)
|
||||||
|
return
|
||||||
|
elseif growtype == "nil" then
|
||||||
|
minetest.swap_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
|
||||||
|
|
||||||
|
|
||||||
|
dofile(biome_lib.modpath .. "/search_functions.lua")
|
||||||
|
assert(loadfile(biome_lib.modpath .. "/growth.lua"))(time_scale)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Check for infinite stacks
|
||||||
|
|
||||||
|
if minetest.get_modpath("unified_inventory") or not minetest.settings:get_bool("creative_mode") then
|
||||||
|
biome_lib.expect_infinite_stacks = false
|
||||||
|
else
|
||||||
|
biome_lib.expect_infinite_stacks = true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- read a field from a node's definition
|
||||||
|
|
||||||
|
function biome_lib:get_nodedef_field(nodename, fieldname)
|
||||||
|
if not minetest.registered_nodes[nodename] then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
return minetest.registered_nodes[nodename][fieldname]
|
||||||
|
end
|
||||||
|
|
||||||
|
print("[Biome Lib] Loaded")
|
||||||
|
|
||||||
|
minetest.after(0, function()
|
||||||
|
print("[Biome Lib] Registered a total of "..(#biome_lib.surfaceslist_aircheck)+(#biome_lib.surfaceslist_no_aircheck).." surface types to be evaluated, spread")
|
||||||
|
print("[Biome Lib] across "..#biome_lib.actionslist_aircheck.." actions with air-checking and "..#biome_lib.actionslist_no_aircheck.." actions without.")
|
||||||
|
end)
|
||||||
|
|
5
mods/biome_lib/locale/de.txt
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# Translation by Xanthin
|
||||||
|
|
||||||
|
someone = jemand
|
||||||
|
Sorry, %s owns that spot. = Entschuldige, %s gehoert diese Stelle.
|
||||||
|
[Plantlife Library] Loaded = [Plantlife Library] Geladen
|
5
mods/biome_lib/locale/fr.txt
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# Template
|
||||||
|
|
||||||
|
someone = quelqu'un
|
||||||
|
Sorry, %s owns that spot. = Désolé, %s possède cet endroit.
|
||||||
|
[Plantlife Library] Loaded = [Librairie Plantlife] Chargée.
|
5
mods/biome_lib/locale/ru.txt
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# Translation by inpos
|
||||||
|
|
||||||
|
someone = кто-то
|
||||||
|
Sorry, %s owns that spot. = Извините, но %s уже является владельцем этой точки.
|
||||||
|
[Plantlife Library] Loaded = [Plantlife Library] Загружена
|
5
mods/biome_lib/locale/template.txt
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# Template
|
||||||
|
|
||||||
|
someone =
|
||||||
|
Sorry, %s owns that spot. =
|
||||||
|
[Plantlife Library] Loaded =
|
5
mods/biome_lib/locale/tr.txt
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# 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
|
2
mods/biome_lib/mod.conf
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
name = biome_lib
|
||||||
|
min_minetest_version = 5.2.0
|
60
mods/biome_lib/search_functions.lua
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
|
||||||
|
-- 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 biome_lib: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 biome_lib: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 biome_lib: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
|
||||||
|
|
||||||
|
-- "Record" the chunks being generated by the core mapgen
|
||||||
|
|
||||||
|
minetest.register_on_generated(function(minp, maxp, blockseed)
|
||||||
|
biome_lib.blocklist_aircheck[#biome_lib.blocklist_aircheck + 1] = { minp, maxp }
|
||||||
|
biome_lib.blocklist_no_aircheck[#biome_lib.blocklist_no_aircheck + 1] = { minp, maxp }
|
||||||
|
end)
|
30
mods/moretrees/.luacheckrc
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
std = "lua51+minetest"
|
||||||
|
unused_args = false
|
||||||
|
allow_defined_top = true
|
||||||
|
max_line_length = 999
|
||||||
|
max_comment_line_length = 999
|
||||||
|
|
||||||
|
stds.minetest = {
|
||||||
|
read_globals = {
|
||||||
|
"minetest",
|
||||||
|
"vector",
|
||||||
|
"VoxelManip",
|
||||||
|
"VoxelArea",
|
||||||
|
"PseudoRandom",
|
||||||
|
"ItemStack",
|
||||||
|
"default",
|
||||||
|
table = {
|
||||||
|
fields = {
|
||||||
|
"copy",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"dump",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
read_globals = {
|
||||||
|
"biome_lib",
|
||||||
|
"stairsplus",
|
||||||
|
"stairs",
|
||||||
|
"doors",
|
||||||
|
}
|
620
mods/moretrees/LICENSE
Normal file
|
@ -0,0 +1,620 @@
|
||||||
|
Minetest mod moretrees
|
||||||
|
======================
|
||||||
|
|
||||||
|
All source code:
|
||||||
|
© 2013, Vanessa Ezekowitz <vanessaezekowitz@gmail.com>
|
||||||
|
Date & cocos palm code (date_palm.lua, cocos_palm.lua)
|
||||||
|
© 2016, Rogier <rogier777@gmail.com>
|
||||||
|
All date & date palm textures, date-based food, cocos flower & green coconuts,
|
||||||
|
and all poplar textures:
|
||||||
|
© 2016, Rogier <rogier777@gmail.com>
|
||||||
|
- Three of the date palm textures are modifications of existing moretrees textures
|
||||||
|
- The green coconuts are a modification of the brown coconut
|
||||||
|
- The date cake batter is a modification of the acorn muffin batter
|
||||||
|
All other sapling textures (textures/*_sapling.png):
|
||||||
|
© 2013, Tim Huppertz <mitroman@naturalnet.de>
|
||||||
|
All other textures:
|
||||||
|
© 2013, Vanessa Ezekowitz <vanessaezekowitz@gmail.com>
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
License for all code: LGPL 3.0
|
||||||
|
License for all media and all other assets: CC-by-SA 4.0
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
This version of the GNU Lesser General Public License incorporates
|
||||||
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
|
0. Additional Definitions.
|
||||||
|
|
||||||
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
General Public License.
|
||||||
|
|
||||||
|
"The Library" refers to a covered work governed by this License,
|
||||||
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
|
An "Application" is any work that makes use of an interface provided
|
||||||
|
by the Library, but which is not otherwise based on the Library.
|
||||||
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
|
Application with the Library. The particular version of the Library
|
||||||
|
with which the Combined Work was made is also called the "Linked
|
||||||
|
Version".
|
||||||
|
|
||||||
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
|
object code and/or source code for the Application, including any data
|
||||||
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
|
facility refers to a function or data to be supplied by an Application
|
||||||
|
that uses the facility (other than as an argument passed when the
|
||||||
|
facility is invoked), then you may convey a copy of the modified
|
||||||
|
version:
|
||||||
|
|
||||||
|
a) under this License, provided that you make a good faith effort to
|
||||||
|
ensure that, in the event an Application does not supply the
|
||||||
|
function or data, the facility still operates, and performs
|
||||||
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
|
this License applicable to that copy.
|
||||||
|
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
|
The object code form of an Application may incorporate material from
|
||||||
|
a header file that is part of the Library. You may convey such object
|
||||||
|
code under terms of your choice, provided that, if the incorporated
|
||||||
|
material is not limited to numerical parameters, data structure
|
||||||
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the object code that the
|
||||||
|
Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
4. Combined Works.
|
||||||
|
|
||||||
|
You may convey a Combined Work under terms of your choice that,
|
||||||
|
taken together, effectively do not restrict modification of the
|
||||||
|
portions of the Library contained in the Combined Work and reverse
|
||||||
|
engineering for debugging such modifications, if you also do each of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
|
the Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
c) For a Combined Work that displays copyright notices during
|
||||||
|
execution, include the copyright notice for the Library among
|
||||||
|
these notices, as well as a reference directing the user to the
|
||||||
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
|
d) Do one of the following:
|
||||||
|
|
||||||
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
|
License, and the Corresponding Application Code in a form
|
||||||
|
suitable for, and under terms that permit, the user to
|
||||||
|
recombine or relink the Application with a modified version of
|
||||||
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
|
Corresponding Source.
|
||||||
|
|
||||||
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
|
a copy of the Library already present on the user's computer
|
||||||
|
system, and (b) will operate properly with a modified version
|
||||||
|
of the Library that is interface-compatible with the Linked
|
||||||
|
Version.
|
||||||
|
|
||||||
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
|
be required to provide such information under section 6 of the
|
||||||
|
GNU GPL, and only to the extent that such information is
|
||||||
|
necessary to install and execute a modified version of the
|
||||||
|
Combined Work produced by recombining or relinking the
|
||||||
|
Application with a modified version of the Linked Version. (If
|
||||||
|
you use option 4d0, the Installation Information must accompany
|
||||||
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
|
5. Combined Libraries.
|
||||||
|
|
||||||
|
You may place library facilities that are a work based on the
|
||||||
|
Library side by side in a single library together with other library
|
||||||
|
facilities that are not Applications and are not covered by this
|
||||||
|
License, and convey such a combined library under terms of your
|
||||||
|
choice, if you do both of the following:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work based
|
||||||
|
on the Library, uncombined with any other library facilities,
|
||||||
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library that part of it
|
||||||
|
is a work based on the Library, and explaining where to find the
|
||||||
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the GNU Lesser General Public License from time to time. Such new
|
||||||
|
versions will be similar in spirit to the present version, but may
|
||||||
|
differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Library as you received it specifies that a certain numbered version
|
||||||
|
of the GNU Lesser General Public License "or any later version"
|
||||||
|
applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that published version or of any later version
|
||||||
|
published by the Free Software Foundation. If the Library as you
|
||||||
|
received it does not specify a version number of the GNU Lesser
|
||||||
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Library as you received it specifies that a proxy can decide
|
||||||
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
|
permanent authorization for you to choose that version for the
|
||||||
|
Library.
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Attribution-ShareAlike 4.0 International
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Creative Commons Corporation ("Creative Commons") is not a law firm and
|
||||||
|
does not provide legal services or legal advice. Distribution of
|
||||||
|
Creative Commons public licenses does not create a lawyer-client or
|
||||||
|
other relationship. Creative Commons makes its licenses and related
|
||||||
|
information available on an "as-is" basis. Creative Commons gives no
|
||||||
|
warranties regarding its licenses, any material licensed under their
|
||||||
|
terms and conditions, or any related information. Creative Commons
|
||||||
|
disclaims all liability for damages resulting from their use to the
|
||||||
|
fullest extent possible.
|
||||||
|
|
||||||
|
Using Creative Commons Public Licenses
|
||||||
|
|
||||||
|
Creative Commons public licenses provide a standard set of terms and
|
||||||
|
conditions that creators and other rights holders may use to share
|
||||||
|
original works of authorship and other material subject to copyright
|
||||||
|
and certain other rights specified in the public license below. The
|
||||||
|
following considerations are for informational purposes only, are not
|
||||||
|
exhaustive, and do not form part of our licenses.
|
||||||
|
|
||||||
|
Considerations for licensors: Our public licenses are
|
||||||
|
intended for use by those authorized to give the public
|
||||||
|
permission to use material in ways otherwise restricted by
|
||||||
|
copyright and certain other rights. Our licenses are
|
||||||
|
irrevocable. Licensors should read and understand the terms
|
||||||
|
and conditions of the license they choose before applying it.
|
||||||
|
Licensors should also secure all rights necessary before
|
||||||
|
applying our licenses so that the public can reuse the
|
||||||
|
material as expected. Licensors should clearly mark any
|
||||||
|
material not subject to the license. This includes other CC-
|
||||||
|
licensed material, or material used under an exception or
|
||||||
|
limitation to copyright. More considerations for licensors:
|
||||||
|
wiki.creativecommons.org/Considerations_for_licensors
|
||||||
|
|
||||||
|
Considerations for the public: By using one of our public
|
||||||
|
licenses, a licensor grants the public permission to use the
|
||||||
|
licensed material under specified terms and conditions. If
|
||||||
|
the licensor's permission is not necessary for any reason--for
|
||||||
|
example, because of any applicable exception or limitation to
|
||||||
|
copyright--then that use is not regulated by the license. Our
|
||||||
|
licenses grant only permissions under copyright and certain
|
||||||
|
other rights that a licensor has authority to grant. Use of
|
||||||
|
the licensed material may still be restricted for other
|
||||||
|
reasons, including because others have copyright or other
|
||||||
|
rights in the material. A licensor may make special requests,
|
||||||
|
such as asking that all changes be marked or described.
|
||||||
|
Although not required by our licenses, you are encouraged to
|
||||||
|
respect those requests where reasonable. More considerations
|
||||||
|
for the public:
|
||||||
|
wiki.creativecommons.org/Considerations_for_licensees
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Creative Commons Attribution-ShareAlike 4.0 International Public
|
||||||
|
License
|
||||||
|
|
||||||
|
By exercising the Licensed Rights (defined below), You accept and agree
|
||||||
|
to be bound by the terms and conditions of this Creative Commons
|
||||||
|
Attribution-ShareAlike 4.0 International Public License ("Public
|
||||||
|
License"). To the extent this Public License may be interpreted as a
|
||||||
|
contract, You are granted the Licensed Rights in consideration of Your
|
||||||
|
acceptance of these terms and conditions, and the Licensor grants You
|
||||||
|
such rights in consideration of benefits the Licensor receives from
|
||||||
|
making the Licensed Material available under these terms and
|
||||||
|
conditions.
|
||||||
|
|
||||||
|
|
||||||
|
Section 1 -- Definitions.
|
||||||
|
|
||||||
|
a. Adapted Material means material subject to Copyright and Similar
|
||||||
|
Rights that is derived from or based upon the Licensed Material
|
||||||
|
and in which the Licensed Material is translated, altered,
|
||||||
|
arranged, transformed, or otherwise modified in a manner requiring
|
||||||
|
permission under the Copyright and Similar Rights held by the
|
||||||
|
Licensor. For purposes of this Public License, where the Licensed
|
||||||
|
Material is a musical work, performance, or sound recording,
|
||||||
|
Adapted Material is always produced where the Licensed Material is
|
||||||
|
synched in timed relation with a moving image.
|
||||||
|
|
||||||
|
b. Adapter's License means the license You apply to Your Copyright
|
||||||
|
and Similar Rights in Your contributions to Adapted Material in
|
||||||
|
accordance with the terms and conditions of this Public License.
|
||||||
|
|
||||||
|
c. BY-SA Compatible License means a license listed at
|
||||||
|
creativecommons.org/compatiblelicenses, approved by Creative
|
||||||
|
Commons as essentially the equivalent of this Public License.
|
||||||
|
|
||||||
|
d. Copyright and Similar Rights means copyright and/or similar rights
|
||||||
|
closely related to copyright including, without limitation,
|
||||||
|
performance, broadcast, sound recording, and Sui Generis Database
|
||||||
|
Rights, without regard to how the rights are labeled or
|
||||||
|
categorized. For purposes of this Public License, the rights
|
||||||
|
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
||||||
|
Rights.
|
||||||
|
|
||||||
|
e. Effective Technological Measures means those measures that, in the
|
||||||
|
absence of proper authority, may not be circumvented under laws
|
||||||
|
fulfilling obligations under Article 11 of the WIPO Copyright
|
||||||
|
Treaty adopted on December 20, 1996, and/or similar international
|
||||||
|
agreements.
|
||||||
|
|
||||||
|
f. Exceptions and Limitations means fair use, fair dealing, and/or
|
||||||
|
any other exception or limitation to Copyright and Similar Rights
|
||||||
|
that applies to Your use of the Licensed Material.
|
||||||
|
|
||||||
|
g. License Elements means the license attributes listed in the name
|
||||||
|
of a Creative Commons Public License. The License Elements of this
|
||||||
|
Public License are Attribution and ShareAlike.
|
||||||
|
|
||||||
|
h. Licensed Material means the artistic or literary work, database,
|
||||||
|
or other material to which the Licensor applied this Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
i. Licensed Rights means the rights granted to You subject to the
|
||||||
|
terms and conditions of this Public License, which are limited to
|
||||||
|
all Copyright and Similar Rights that apply to Your use of the
|
||||||
|
Licensed Material and that the Licensor has authority to license.
|
||||||
|
|
||||||
|
j. Licensor means the individual(s) or entity(ies) granting rights
|
||||||
|
under this Public License.
|
||||||
|
|
||||||
|
k. Share means to provide material to the public by any means or
|
||||||
|
process that requires permission under the Licensed Rights, such
|
||||||
|
as reproduction, public display, public performance, distribution,
|
||||||
|
dissemination, communication, or importation, and to make material
|
||||||
|
available to the public including in ways that members of the
|
||||||
|
public may access the material from a place and at a time
|
||||||
|
individually chosen by them.
|
||||||
|
|
||||||
|
l. Sui Generis Database Rights means rights other than copyright
|
||||||
|
resulting from Directive 96/9/EC of the European Parliament and of
|
||||||
|
the Council of 11 March 1996 on the legal protection of databases,
|
||||||
|
as amended and/or succeeded, as well as other essentially
|
||||||
|
equivalent rights anywhere in the world.
|
||||||
|
|
||||||
|
m. You means the individual or entity exercising the Licensed Rights
|
||||||
|
under this Public License. Your has a corresponding meaning.
|
||||||
|
|
||||||
|
|
||||||
|
Section 2 -- Scope.
|
||||||
|
|
||||||
|
a. License grant.
|
||||||
|
|
||||||
|
1. Subject to the terms and conditions of this Public License,
|
||||||
|
the Licensor hereby grants You a worldwide, royalty-free,
|
||||||
|
non-sublicensable, non-exclusive, irrevocable license to
|
||||||
|
exercise the Licensed Rights in the Licensed Material to:
|
||||||
|
|
||||||
|
a. reproduce and Share the Licensed Material, in whole or
|
||||||
|
in part; and
|
||||||
|
|
||||||
|
b. produce, reproduce, and Share Adapted Material.
|
||||||
|
|
||||||
|
2. Exceptions and Limitations. For the avoidance of doubt, where
|
||||||
|
Exceptions and Limitations apply to Your use, this Public
|
||||||
|
License does not apply, and You do not need to comply with
|
||||||
|
its terms and conditions.
|
||||||
|
|
||||||
|
3. Term. The term of this Public License is specified in Section
|
||||||
|
6(a).
|
||||||
|
|
||||||
|
4. Media and formats; technical modifications allowed. The
|
||||||
|
Licensor authorizes You to exercise the Licensed Rights in
|
||||||
|
all media and formats whether now known or hereafter created,
|
||||||
|
and to make technical modifications necessary to do so. The
|
||||||
|
Licensor waives and/or agrees not to assert any right or
|
||||||
|
authority to forbid You from making technical modifications
|
||||||
|
necessary to exercise the Licensed Rights, including
|
||||||
|
technical modifications necessary to circumvent Effective
|
||||||
|
Technological Measures. For purposes of this Public License,
|
||||||
|
simply making modifications authorized by this Section 2(a)
|
||||||
|
(4) never produces Adapted Material.
|
||||||
|
|
||||||
|
5. Downstream recipients.
|
||||||
|
|
||||||
|
a. Offer from the Licensor -- Licensed Material. Every
|
||||||
|
recipient of the Licensed Material automatically
|
||||||
|
receives an offer from the Licensor to exercise the
|
||||||
|
Licensed Rights under the terms and conditions of this
|
||||||
|
Public License.
|
||||||
|
|
||||||
|
b. Additional offer from the Licensor -- Adapted Material.
|
||||||
|
Every recipient of Adapted Material from You
|
||||||
|
automatically receives an offer from the Licensor to
|
||||||
|
exercise the Licensed Rights in the Adapted Material
|
||||||
|
under the conditions of the Adapter's License You apply.
|
||||||
|
|
||||||
|
c. No downstream restrictions. You may not offer or impose
|
||||||
|
any additional or different terms or conditions on, or
|
||||||
|
apply any Effective Technological Measures to, the
|
||||||
|
Licensed Material if doing so restricts exercise of the
|
||||||
|
Licensed Rights by any recipient of the Licensed
|
||||||
|
Material.
|
||||||
|
|
||||||
|
6. No endorsement. Nothing in this Public License constitutes or
|
||||||
|
may be construed as permission to assert or imply that You
|
||||||
|
are, or that Your use of the Licensed Material is, connected
|
||||||
|
with, or sponsored, endorsed, or granted official status by,
|
||||||
|
the Licensor or others designated to receive attribution as
|
||||||
|
provided in Section 3(a)(1)(A)(i).
|
||||||
|
|
||||||
|
b. Other rights.
|
||||||
|
|
||||||
|
1. Moral rights, such as the right of integrity, are not
|
||||||
|
licensed under this Public License, nor are publicity,
|
||||||
|
privacy, and/or other similar personality rights; however, to
|
||||||
|
the extent possible, the Licensor waives and/or agrees not to
|
||||||
|
assert any such rights held by the Licensor to the limited
|
||||||
|
extent necessary to allow You to exercise the Licensed
|
||||||
|
Rights, but not otherwise.
|
||||||
|
|
||||||
|
2. Patent and trademark rights are not licensed under this
|
||||||
|
Public License.
|
||||||
|
|
||||||
|
3. To the extent possible, the Licensor waives any right to
|
||||||
|
collect royalties from You for the exercise of the Licensed
|
||||||
|
Rights, whether directly or through a collecting society
|
||||||
|
under any voluntary or waivable statutory or compulsory
|
||||||
|
licensing scheme. In all other cases the Licensor expressly
|
||||||
|
reserves any right to collect such royalties.
|
||||||
|
|
||||||
|
|
||||||
|
Section 3 -- License Conditions.
|
||||||
|
|
||||||
|
Your exercise of the Licensed Rights is expressly made subject to the
|
||||||
|
following conditions.
|
||||||
|
|
||||||
|
a. Attribution.
|
||||||
|
|
||||||
|
1. If You Share the Licensed Material (including in modified
|
||||||
|
form), You must:
|
||||||
|
|
||||||
|
a. retain the following if it is supplied by the Licensor
|
||||||
|
with the Licensed Material:
|
||||||
|
|
||||||
|
i. identification of the creator(s) of the Licensed
|
||||||
|
Material and any others designated to receive
|
||||||
|
attribution, in any reasonable manner requested by
|
||||||
|
the Licensor (including by pseudonym if
|
||||||
|
designated);
|
||||||
|
|
||||||
|
ii. a copyright notice;
|
||||||
|
|
||||||
|
iii. a notice that refers to this Public License;
|
||||||
|
|
||||||
|
iv. a notice that refers to the disclaimer of
|
||||||
|
warranties;
|
||||||
|
|
||||||
|
v. a URI or hyperlink to the Licensed Material to the
|
||||||
|
extent reasonably practicable;
|
||||||
|
|
||||||
|
b. indicate if You modified the Licensed Material and
|
||||||
|
retain an indication of any previous modifications; and
|
||||||
|
|
||||||
|
c. indicate the Licensed Material is licensed under this
|
||||||
|
Public License, and include the text of, or the URI or
|
||||||
|
hyperlink to, this Public License.
|
||||||
|
|
||||||
|
2. You may satisfy the conditions in Section 3(a)(1) in any
|
||||||
|
reasonable manner based on the medium, means, and context in
|
||||||
|
which You Share the Licensed Material. For example, it may be
|
||||||
|
reasonable to satisfy the conditions by providing a URI or
|
||||||
|
hyperlink to a resource that includes the required
|
||||||
|
information.
|
||||||
|
|
||||||
|
3. If requested by the Licensor, You must remove any of the
|
||||||
|
information required by Section 3(a)(1)(A) to the extent
|
||||||
|
reasonably practicable.
|
||||||
|
|
||||||
|
b. ShareAlike.
|
||||||
|
|
||||||
|
In addition to the conditions in Section 3(a), if You Share
|
||||||
|
Adapted Material You produce, the following conditions also apply.
|
||||||
|
|
||||||
|
1. The Adapter's License You apply must be a Creative Commons
|
||||||
|
license with the same License Elements, this version or
|
||||||
|
later, or a BY-SA Compatible License.
|
||||||
|
|
||||||
|
2. You must include the text of, or the URI or hyperlink to, the
|
||||||
|
Adapter's License You apply. You may satisfy this condition
|
||||||
|
in any reasonable manner based on the medium, means, and
|
||||||
|
context in which You Share Adapted Material.
|
||||||
|
|
||||||
|
3. You may not offer or impose any additional or different terms
|
||||||
|
or conditions on, or apply any Effective Technological
|
||||||
|
Measures to, Adapted Material that restrict exercise of the
|
||||||
|
rights granted under the Adapter's License You apply.
|
||||||
|
|
||||||
|
|
||||||
|
Section 4 -- Sui Generis Database Rights.
|
||||||
|
|
||||||
|
Where the Licensed Rights include Sui Generis Database Rights that
|
||||||
|
apply to Your use of the Licensed Material:
|
||||||
|
|
||||||
|
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
||||||
|
to extract, reuse, reproduce, and Share all or a substantial
|
||||||
|
portion of the contents of the database;
|
||||||
|
|
||||||
|
b. if You include all or a substantial portion of the database
|
||||||
|
contents in a database in which You have Sui Generis Database
|
||||||
|
Rights, then the database in which You have Sui Generis Database
|
||||||
|
Rights (but not its individual contents) is Adapted Material,
|
||||||
|
|
||||||
|
including for purposes of Section 3(b); and
|
||||||
|
c. You must comply with the conditions in Section 3(a) if You Share
|
||||||
|
all or a substantial portion of the contents of the database.
|
||||||
|
|
||||||
|
For the avoidance of doubt, this Section 4 supplements and does not
|
||||||
|
replace Your obligations under this Public License where the Licensed
|
||||||
|
Rights include other Copyright and Similar Rights.
|
||||||
|
|
||||||
|
|
||||||
|
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
||||||
|
|
||||||
|
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
||||||
|
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
||||||
|
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
||||||
|
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
||||||
|
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
||||||
|
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
||||||
|
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
||||||
|
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
||||||
|
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
||||||
|
|
||||||
|
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
||||||
|
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
||||||
|
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
||||||
|
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
||||||
|
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
||||||
|
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
||||||
|
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
||||||
|
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
||||||
|
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
||||||
|
|
||||||
|
c. The disclaimer of warranties and limitation of liability provided
|
||||||
|
above shall be interpreted in a manner that, to the extent
|
||||||
|
possible, most closely approximates an absolute disclaimer and
|
||||||
|
waiver of all liability.
|
||||||
|
|
||||||
|
|
||||||
|
Section 6 -- Term and Termination.
|
||||||
|
|
||||||
|
a. This Public License applies for the term of the Copyright and
|
||||||
|
Similar Rights licensed here. However, if You fail to comply with
|
||||||
|
this Public License, then Your rights under this Public License
|
||||||
|
terminate automatically.
|
||||||
|
|
||||||
|
b. Where Your right to use the Licensed Material has terminated under
|
||||||
|
Section 6(a), it reinstates:
|
||||||
|
|
||||||
|
1. automatically as of the date the violation is cured, provided
|
||||||
|
it is cured within 30 days of Your discovery of the
|
||||||
|
violation; or
|
||||||
|
|
||||||
|
2. upon express reinstatement by the Licensor.
|
||||||
|
|
||||||
|
For the avoidance of doubt, this Section 6(b) does not affect any
|
||||||
|
right the Licensor may have to seek remedies for Your violations
|
||||||
|
of this Public License.
|
||||||
|
|
||||||
|
c. For the avoidance of doubt, the Licensor may also offer the
|
||||||
|
Licensed Material under separate terms or conditions or stop
|
||||||
|
distributing the Licensed Material at any time; however, doing so
|
||||||
|
will not terminate this Public License.
|
||||||
|
|
||||||
|
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
|
||||||
|
Section 7 -- Other Terms and Conditions.
|
||||||
|
|
||||||
|
a. The Licensor shall not be bound by any additional or different
|
||||||
|
terms or conditions communicated by You unless expressly agreed.
|
||||||
|
|
||||||
|
b. Any arrangements, understandings, or agreements regarding the
|
||||||
|
Licensed Material not stated herein are separate from and
|
||||||
|
independent of the terms and conditions of this Public License.
|
||||||
|
|
||||||
|
|
||||||
|
Section 8 -- Interpretation.
|
||||||
|
|
||||||
|
a. For the avoidance of doubt, this Public License does not, and
|
||||||
|
shall not be interpreted to, reduce, limit, restrict, or impose
|
||||||
|
conditions on any use of the Licensed Material that could lawfully
|
||||||
|
be made without permission under this Public License.
|
||||||
|
|
||||||
|
b. To the extent possible, if any provision of this Public License is
|
||||||
|
deemed unenforceable, it shall be automatically reformed to the
|
||||||
|
minimum extent necessary to make it enforceable. If the provision
|
||||||
|
cannot be reformed, it shall be severed from this Public License
|
||||||
|
without affecting the enforceability of the remaining terms and
|
||||||
|
conditions.
|
||||||
|
|
||||||
|
c. No term or condition of this Public License will be waived and no
|
||||||
|
failure to comply consented to unless expressly agreed to by the
|
||||||
|
Licensor.
|
||||||
|
|
||||||
|
d. Nothing in this Public License constitutes or may be interpreted
|
||||||
|
as a limitation upon, or waiver of, any privileges and immunities
|
||||||
|
that apply to the Licensor or You, including from the legal
|
||||||
|
processes of any jurisdiction or authority.
|
||||||
|
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Creative Commons is not a party to its public
|
||||||
|
licenses. Notwithstanding, Creative Commons may elect to apply one of
|
||||||
|
its public licenses to material it publishes and in those instances
|
||||||
|
will be considered the “Licensor.” The text of the Creative Commons
|
||||||
|
public licenses is dedicated to the public domain under the CC0 Public
|
||||||
|
Domain Dedication. Except for the limited purpose of indicating that
|
||||||
|
material is shared under a Creative Commons public license or as
|
||||||
|
otherwise permitted by the Creative Commons policies published at
|
||||||
|
creativecommons.org/policies, Creative Commons does not authorize the
|
||||||
|
use of the trademark "Creative Commons" or any other trademark or logo
|
||||||
|
of Creative Commons without its prior written consent including,
|
||||||
|
without limitation, in connection with any unauthorized modifications
|
||||||
|
to any of its public licenses or any other arrangements,
|
||||||
|
understandings, or agreements concerning use of licensed material. For
|
||||||
|
the avoidance of doubt, this paragraph does not form part of the
|
||||||
|
public licenses.
|
||||||
|
|
||||||
|
Creative Commons may be contacted at creativecommons.org.
|
11
mods/moretrees/README.md
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
More trees!
|
||||||
|
|
||||||
|
This mod adds a whole bunch of new types of trees to the game
|
||||||
|
|
||||||
|
Much of the code here came from cisoun's conifers mod and bas080's
|
||||||
|
jungle trees mod, and big contributions by RealBadAngel.
|
||||||
|
|
||||||
|
Brought together into one mod and made L-systems compatible by Vanessa
|
||||||
|
Ezekowitz.
|
||||||
|
|
||||||
|
Dependencies: <a href="https://forum.minetest.net/viewtopic.php?f=11&t=12999">biome_lib</a> and default
|
301
mods/moretrees/biome_defs.lua
Normal file
|
@ -0,0 +1,301 @@
|
||||||
|
|
||||||
|
moretrees.beech_biome = {
|
||||||
|
surface = "default:dirt_with_grass",
|
||||||
|
avoid_nodes = moretrees.avoidnodes,
|
||||||
|
avoid_radius = 8,
|
||||||
|
seed_diff = 2,
|
||||||
|
rarity = 50,
|
||||||
|
max_count = 20,
|
||||||
|
}
|
||||||
|
|
||||||
|
moretrees.palm_biome = {
|
||||||
|
surface = "default:sand",
|
||||||
|
avoid_nodes = moretrees.avoidnodes,
|
||||||
|
avoid_radius = 5,
|
||||||
|
seed_diff = 330,
|
||||||
|
min_elevation = -1,
|
||||||
|
max_elevation = 1,
|
||||||
|
near_nodes = {"default:water_source"},
|
||||||
|
near_nodes_size = 15,
|
||||||
|
near_nodes_count = 10,
|
||||||
|
temp_min = 0.25,
|
||||||
|
temp_max = -0.15,
|
||||||
|
rarity = 50,
|
||||||
|
max_count = 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
moretrees.date_palm_biome = {
|
||||||
|
surface = "default:desert_sand",
|
||||||
|
avoid_nodes = moretrees.avoidnodes,
|
||||||
|
avoid_radius = 10,
|
||||||
|
seed_diff = 339,
|
||||||
|
min_elevation = -1,
|
||||||
|
max_elevation = 10,
|
||||||
|
near_nodes = {"default:water_source"},
|
||||||
|
near_nodes_size = 20,
|
||||||
|
near_nodes_count = 100,
|
||||||
|
near_nodes_vertical = 20,
|
||||||
|
temp_min = -0.20,
|
||||||
|
humidity_max = 0.20,
|
||||||
|
rarity = 10,
|
||||||
|
max_count = 30,
|
||||||
|
}
|
||||||
|
|
||||||
|
moretrees.date_palm_biome_2 = {
|
||||||
|
surface = "default:desert_sand",
|
||||||
|
avoid_nodes = moretrees.avoidnodes,
|
||||||
|
avoid_radius = 10,
|
||||||
|
seed_diff = 340,
|
||||||
|
min_elevation = 11,
|
||||||
|
max_elevation = 30,
|
||||||
|
near_nodes = {"default:water_source"},
|
||||||
|
near_nodes_size = 1,
|
||||||
|
near_nodes_count = 1,
|
||||||
|
near_nodes_vertical = 30,
|
||||||
|
temp_min = -0.20,
|
||||||
|
humidity_max = 0.20,
|
||||||
|
rarity = 10,
|
||||||
|
max_count = 30,
|
||||||
|
}
|
||||||
|
|
||||||
|
moretrees.apple_tree_biome = {
|
||||||
|
surface = "default:dirt_with_grass",
|
||||||
|
avoid_nodes = moretrees.avoidnodes,
|
||||||
|
avoid_radius = 10,
|
||||||
|
seed_diff = 331,
|
||||||
|
min_elevation = 1,
|
||||||
|
max_elevation = 10,
|
||||||
|
temp_min = 0.1,
|
||||||
|
temp_max = -0.15,
|
||||||
|
rarity = 75,
|
||||||
|
max_count = 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
moretrees.oak_biome = {
|
||||||
|
surface = "default:dirt_with_grass",
|
||||||
|
avoid_nodes = moretrees.avoidnodes,
|
||||||
|
avoid_radius = 15,
|
||||||
|
seed_diff = 332,
|
||||||
|
min_elevation = 0,
|
||||||
|
max_elevation = 10,
|
||||||
|
temp_min = 0.4,
|
||||||
|
temp_max = 0.2,
|
||||||
|
rarity = 50,
|
||||||
|
max_count = 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
moretrees.sequoia_biome = {
|
||||||
|
surface = "default:dirt_with_grass",
|
||||||
|
avoid_nodes = moretrees.avoidnodes,
|
||||||
|
avoid_radius = 10,
|
||||||
|
seed_diff = 333,
|
||||||
|
min_elevation = 0,
|
||||||
|
max_elevation = 10,
|
||||||
|
temp_min = 1,
|
||||||
|
temp_max = -0.4,
|
||||||
|
rarity = 90,
|
||||||
|
max_count = 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
moretrees.birch_biome = {
|
||||||
|
surface = "default:dirt_with_grass",
|
||||||
|
avoid_nodes = moretrees.avoidnodes,
|
||||||
|
avoid_radius = 5,
|
||||||
|
seed_diff = 334,
|
||||||
|
min_elevation = 10,
|
||||||
|
max_elevation = 15,
|
||||||
|
temp_min = 0.9,
|
||||||
|
temp_max = 0.3,
|
||||||
|
rarity = 50,
|
||||||
|
max_count = 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
moretrees.willow_biome = {
|
||||||
|
surface = "default:dirt_with_grass",
|
||||||
|
avoid_nodes = moretrees.avoidnodes,
|
||||||
|
avoid_radius = 10,
|
||||||
|
seed_diff = 337,
|
||||||
|
min_elevation = -5,
|
||||||
|
max_elevation = 5,
|
||||||
|
near_nodes = {"default:water_source"},
|
||||||
|
near_nodes_size = 15,
|
||||||
|
near_nodes_count = 5,
|
||||||
|
rarity = 75,
|
||||||
|
max_count = 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
moretrees.rubber_tree_biome = {
|
||||||
|
surface = "default:dirt_with_grass",
|
||||||
|
avoid_nodes = moretrees.avoidnodes,
|
||||||
|
avoid_radius = 10,
|
||||||
|
seed_diff = 338,
|
||||||
|
min_elevation = -5,
|
||||||
|
max_elevation = 5,
|
||||||
|
near_nodes = {"default:water_source"},
|
||||||
|
near_nodes_size = 15,
|
||||||
|
near_nodes_count = 10,
|
||||||
|
temp_min = -0.15,
|
||||||
|
rarity = 75,
|
||||||
|
max_count = 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
moretrees.jungletree_biome = {
|
||||||
|
surface = {
|
||||||
|
"default:dirt",
|
||||||
|
"default:dirt_with_grass",
|
||||||
|
"woodsoils:dirt_with_leaves_1",
|
||||||
|
"woodsoils:grass_with_leaves_1",
|
||||||
|
"woodsoils:grass_with_leaves_2"
|
||||||
|
},
|
||||||
|
avoid_nodes = {"moretrees:jungletree_trunk"},
|
||||||
|
max_count = 12,
|
||||||
|
avoid_radius = 3,
|
||||||
|
rarity = 85,
|
||||||
|
seed_diff = 329,
|
||||||
|
min_elevation = 1,
|
||||||
|
near_nodes = {"default:jungletree"},
|
||||||
|
near_nodes_size = 6,
|
||||||
|
near_nodes_vertical = 2,
|
||||||
|
near_nodes_count = 1,
|
||||||
|
plantlife_limit = -0.9,
|
||||||
|
}
|
||||||
|
|
||||||
|
moretrees.spruce_biome = {
|
||||||
|
surface = "default:dirt_with_grass",
|
||||||
|
avoid_nodes = moretrees.avoidnodes,
|
||||||
|
avoid_radius = 10,
|
||||||
|
seed_diff = 335,
|
||||||
|
min_elevation = 20,
|
||||||
|
temp_min = 0.9,
|
||||||
|
temp_max = 0.7,
|
||||||
|
rarity = 50,
|
||||||
|
max_count = 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
moretrees.cedar_biome = {
|
||||||
|
surface = "default:dirt_with_grass",
|
||||||
|
avoid_nodes = moretrees.avoidnodes,
|
||||||
|
avoid_radius = 10,
|
||||||
|
seed_diff = 336,
|
||||||
|
near_nodes = {"default:water_source"},
|
||||||
|
near_nodes_size = 15,
|
||||||
|
near_nodes_count = 5,
|
||||||
|
rarity = 50,
|
||||||
|
max_count = 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-- Poplar requires a lot of water.
|
||||||
|
moretrees.poplar_biome = {
|
||||||
|
surface = "default:dirt_with_grass",
|
||||||
|
avoid_nodes = moretrees.avoidnodes,
|
||||||
|
avoid_radius = 6,
|
||||||
|
seed_diff = 341,
|
||||||
|
min_elevation = 0,
|
||||||
|
max_elevation = 50,
|
||||||
|
near_nodes = {"default:water_source"},
|
||||||
|
near_nodes_size = 15,
|
||||||
|
near_nodes_vertical = 5,
|
||||||
|
near_nodes_count = 1,
|
||||||
|
humidity_min = -0.7,
|
||||||
|
humidity_max = -1,
|
||||||
|
rarity = 50,
|
||||||
|
max_count = 15,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- The humidity requirement it quite restrictive (apparently).
|
||||||
|
-- Spawn an occasional poplar elsewhere.
|
||||||
|
moretrees.poplar_biome_2 = {
|
||||||
|
surface = "default:dirt_with_grass",
|
||||||
|
avoid_nodes = moretrees.avoidnodes,
|
||||||
|
avoid_radius = 6,
|
||||||
|
seed_diff = 341,
|
||||||
|
min_elevation = 0,
|
||||||
|
max_elevation = 50,
|
||||||
|
near_nodes = {"default:water_source"},
|
||||||
|
near_nodes_size = 15,
|
||||||
|
near_nodes_vertical = 4,
|
||||||
|
near_nodes_count = 10,
|
||||||
|
humidity_min = 0.1,
|
||||||
|
humidity_max = -0.6,
|
||||||
|
rarity = 50,
|
||||||
|
max_count = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Subterranean lakes provide enough water for poplars to grow
|
||||||
|
moretrees.poplar_biome_3 = {
|
||||||
|
surface = "default:dirt_with_grass",
|
||||||
|
avoid_nodes = moretrees.avoidnodes,
|
||||||
|
avoid_radius = 6,
|
||||||
|
seed_diff = 342,
|
||||||
|
min_elevation = 0,
|
||||||
|
max_elevation = 50,
|
||||||
|
near_nodes = {"default:water_source"},
|
||||||
|
near_nodes_size = 1,
|
||||||
|
near_nodes_vertical = 25,
|
||||||
|
near_nodes_count = 1,
|
||||||
|
humidity_min = -0.5,
|
||||||
|
humidity_max = -1,
|
||||||
|
rarity = 0,
|
||||||
|
max_count = 30,
|
||||||
|
}
|
||||||
|
|
||||||
|
moretrees.poplar_small_biome = {
|
||||||
|
surface = "default:dirt_with_grass",
|
||||||
|
avoid_nodes = moretrees.avoidnodes,
|
||||||
|
avoid_radius = 4,
|
||||||
|
seed_diff = 343,
|
||||||
|
min_elevation = 0,
|
||||||
|
max_elevation = 50,
|
||||||
|
near_nodes = {"default:water_source"},
|
||||||
|
near_nodes_size = 10,
|
||||||
|
near_nodes_vertical = 5,
|
||||||
|
near_nodes_count = 1,
|
||||||
|
humidity_min = -0.7,
|
||||||
|
humidity_max = -1,
|
||||||
|
rarity = 50,
|
||||||
|
max_count = 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
moretrees.poplar_small_biome_2 = {
|
||||||
|
surface = "default:dirt_with_grass",
|
||||||
|
avoid_nodes = moretrees.avoidnodes,
|
||||||
|
avoid_radius = 4,
|
||||||
|
seed_diff = 343,
|
||||||
|
min_elevation = 0,
|
||||||
|
max_elevation = 50,
|
||||||
|
near_nodes = {"default:water_source"},
|
||||||
|
near_nodes_size = 10,
|
||||||
|
near_nodes_vertical = 4,
|
||||||
|
near_nodes_count = 5,
|
||||||
|
humidity_min = 0.1,
|
||||||
|
humidity_max = -0.6,
|
||||||
|
rarity = 50,
|
||||||
|
max_count = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
moretrees.fir_biome = {
|
||||||
|
surface = "default:dirt_with_grass",
|
||||||
|
avoid_nodes = moretrees.avoidnodes,
|
||||||
|
avoid_radius = 10,
|
||||||
|
seed_diff = 359,
|
||||||
|
min_elevation = 25,
|
||||||
|
temp_min = 0.9,
|
||||||
|
temp_max = 0.3,
|
||||||
|
rarity = 50,
|
||||||
|
max_count = 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
moretrees.fir_biome_snow = {
|
||||||
|
surface = {"snow:dirt_with_snow", "snow:snow"},
|
||||||
|
below_nodes = {"default:dirt", "default:dirt_with_grass", "snow:dirt_with_snow"},
|
||||||
|
avoid_nodes = moretrees.avoidnodes,
|
||||||
|
avoid_radius = 10,
|
||||||
|
seed_diff = 359,
|
||||||
|
rarity = 50,
|
||||||
|
max_count = 10,
|
||||||
|
check_air = false,
|
||||||
|
delete_above = true,
|
||||||
|
spawn_replace_node = true
|
||||||
|
}
|
335
mods/moretrees/cocos_palm.lua
Normal file
|
@ -0,0 +1,335 @@
|
||||||
|
-- © 2016, Rogier <rogier777@gmail.com>
|
||||||
|
-- Translation support
|
||||||
|
local S = minetest.get_translator("moretrees")
|
||||||
|
|
||||||
|
-- Some constants
|
||||||
|
|
||||||
|
local coconut_drop_ichance = 8
|
||||||
|
|
||||||
|
-- Make the cocos palm fruit trunk a real trunk (it is generated as a fruit)
|
||||||
|
local trunk = minetest.registered_nodes["moretrees:palm_trunk"]
|
||||||
|
local ftrunk = {}
|
||||||
|
local gftrunk = {}
|
||||||
|
for k,v in pairs(trunk) do
|
||||||
|
ftrunk[k] = v
|
||||||
|
gftrunk[k] = v
|
||||||
|
end
|
||||||
|
ftrunk.tiles = {}
|
||||||
|
gftrunk.tiles = {}
|
||||||
|
for k,v in pairs(trunk.tiles) do
|
||||||
|
ftrunk.tiles[k] = v
|
||||||
|
gftrunk.tiles[k] = v
|
||||||
|
end
|
||||||
|
ftrunk.drop = "moretrees:palm_trunk"
|
||||||
|
gftrunk.drop = "moretrees:palm_trunk"
|
||||||
|
ftrunk.after_destruct = function(pos, oldnode)
|
||||||
|
local coconuts = 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},
|
||||||
|
{"group:moretrees_coconut"}
|
||||||
|
)
|
||||||
|
for _,coconutpos in pairs(coconuts) do
|
||||||
|
-- minetest.dig_node(coconutpos) does not cause nearby coconuts to be dropped :-( ...
|
||||||
|
--minetest.dig_node(coconutpos)
|
||||||
|
local items = minetest.get_node_drops(minetest.get_node(coconutpos).name)
|
||||||
|
minetest.swap_node(coconutpos, biome_lib.air)
|
||||||
|
for _, itemname in pairs(items) do
|
||||||
|
minetest.add_item(coconutpos, itemname)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Make the different trunk types distinguishable (but barely)
|
||||||
|
ftrunk.tiles[1] = "moretrees_palm_trunk_top.png^[transformR90"
|
||||||
|
gftrunk.tiles[1] = "moretrees_palm_trunk_top.png^[transformR180"
|
||||||
|
gftrunk.description = gftrunk.description.." (gen)"
|
||||||
|
minetest.register_node("moretrees:palm_fruit_trunk", ftrunk)
|
||||||
|
minetest.register_node("moretrees:palm_fruit_trunk_gen", gftrunk)
|
||||||
|
|
||||||
|
local coconut_regrow_abm_spec = {
|
||||||
|
nodenames = { "moretrees:palm_fruit_trunk" },
|
||||||
|
interval = moretrees.coconut_flower_interval,
|
||||||
|
chance = moretrees.coconut_flower_chance,
|
||||||
|
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||||
|
local coconuts = 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},
|
||||||
|
"group:moretrees_coconut"
|
||||||
|
)
|
||||||
|
-- Expected growth interval increases exponentially with number of coconuts already hanging.
|
||||||
|
-- Also: if more coconuts are hanging, the chance of picking an empty spot decreases as well...
|
||||||
|
if math.random(2^#coconuts) <= 2 then
|
||||||
|
-- Grow in area of 3x3 round trunk
|
||||||
|
local dx=math.floor(math.random(3)-2)
|
||||||
|
local dz=math.floor(math.random(3)-2)
|
||||||
|
local coconutpos = {x=pos.x+dx, y=pos.y, z=pos.z+dz}
|
||||||
|
local coconutnode = minetest.get_node(coconutpos)
|
||||||
|
if coconutnode.name == "air" then
|
||||||
|
minetest.swap_node(coconutpos, {name="moretrees:coconut_0"})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
if moretrees.coconuts_regrow then
|
||||||
|
minetest.register_abm(coconut_regrow_abm_spec)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Spawn initial coconuts
|
||||||
|
|
||||||
|
-- Spawn initial coconuts
|
||||||
|
-- (Instead of coconuts, a generated-palm fruit trunk is generated with the tree. This
|
||||||
|
-- ABM converts the trunk to a regular fruit trunk, and spawns some coconuts)
|
||||||
|
minetest.register_abm({
|
||||||
|
nodenames = { "moretrees:palm_fruit_trunk_gen" },
|
||||||
|
interval = 1,
|
||||||
|
chance = 1,
|
||||||
|
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||||
|
minetest.swap_node(pos, {name="moretrees:palm_fruit_trunk"})
|
||||||
|
local poslist = 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},
|
||||||
|
"air"
|
||||||
|
)
|
||||||
|
local genlist = {}
|
||||||
|
for k,v in pairs(poslist) do
|
||||||
|
genlist[k] = {x = math.random(100), pos = v}
|
||||||
|
end
|
||||||
|
table.sort(genlist, function(a, b) return a.x < b.x; end)
|
||||||
|
local count = 0
|
||||||
|
for _, gen in pairs(genlist) do
|
||||||
|
minetest.swap_node(gen.pos, {name = "moretrees:coconut_3"})
|
||||||
|
count = count + 1
|
||||||
|
if count == 4 then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Register coconuts, and make them regrow
|
||||||
|
|
||||||
|
local coconut_growfn = function(pos, elapsed)
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
local delay = moretrees.coconut_grow_interval
|
||||||
|
if not node then
|
||||||
|
return
|
||||||
|
elseif not moretrees.coconuts_regrow then
|
||||||
|
-- Regrowing has been turned off. Make coconust grow instantly
|
||||||
|
minetest.swap_node(pos, {name="moretrees:coconut_3"})
|
||||||
|
return
|
||||||
|
elseif node.name == "moretrees:coconut_3" then
|
||||||
|
-- Drop coconuts (i.e. remove them), so that new coconuts can grow.
|
||||||
|
-- Coconuts will drop as items with a small chance
|
||||||
|
if math.random(coconut_drop_ichance) == 1 then
|
||||||
|
if moretrees.coconut_item_drop_ichance > 0
|
||||||
|
and math.random(moretrees.coconut_item_drop_ichance) == 1 then
|
||||||
|
local items = minetest.get_node_drops(minetest.get_node(pos).name)
|
||||||
|
for _, itemname in pairs(items) do
|
||||||
|
minetest.add_item(pos, itemname)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
minetest.swap_node(pos, biome_lib.air)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Grow coconuts to the next stage
|
||||||
|
local offset = string.len("moretrees:coconut_x")
|
||||||
|
local n = string.sub(node.name, offset)
|
||||||
|
minetest.swap_node(pos, {name=string.sub(node.name, 1, offset-1)..n+1})
|
||||||
|
end
|
||||||
|
-- Don't catch up when elapsed time is large. Regular visits are needed for growth...
|
||||||
|
local timer = minetest.get_node_timer(pos)
|
||||||
|
timer:start(delay + math.random(moretrees.coconut_grow_interval))
|
||||||
|
end
|
||||||
|
|
||||||
|
local coconut_starttimer = function(pos, elapsed)
|
||||||
|
local timer = minetest.get_node_timer(pos)
|
||||||
|
local base_interval = moretrees.coconut_grow_interval * 2 / 3
|
||||||
|
timer:set(base_interval + math.random(base_interval), elapsed or 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
for _,suffix in ipairs({"_0", "_1", "_2", "_3", ""}) do
|
||||||
|
local name
|
||||||
|
if suffix == "_0" then
|
||||||
|
name = S("Coconut Flower")
|
||||||
|
else
|
||||||
|
name = S("Coconut")
|
||||||
|
end
|
||||||
|
local drop = ""
|
||||||
|
local coco_group = 1
|
||||||
|
local tile = "moretrees_coconut"..suffix..".png"
|
||||||
|
local timerfn = coconut_growfn
|
||||||
|
local constructfn = coconut_starttimer
|
||||||
|
if suffix == "_3" then
|
||||||
|
drop = "moretrees:coconut"
|
||||||
|
tile = "moretrees_coconut.png"
|
||||||
|
elseif suffix == "" then
|
||||||
|
drop = nil
|
||||||
|
coco_group = nil
|
||||||
|
timerfn = nil
|
||||||
|
constructfn = nil
|
||||||
|
end
|
||||||
|
local coconutdef = {
|
||||||
|
description = name,
|
||||||
|
tiles = {tile},
|
||||||
|
drawtype = "plantlike",
|
||||||
|
paramtype = "light",
|
||||||
|
sunlight_propagates = true,
|
||||||
|
walkable = false,
|
||||||
|
groups = { fleshy=3, dig_immediate=3, flammable=2, moretrees_coconut=coco_group },
|
||||||
|
inventory_image = tile.."^[transformR180",
|
||||||
|
wield_image = tile.."^[transformR180",
|
||||||
|
sounds = default.node_sound_defaults(),
|
||||||
|
drop = drop,
|
||||||
|
selection_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {-0.3, -0.3, -0.3, 0.3, 0.3, 0.3}
|
||||||
|
},
|
||||||
|
on_timer = timerfn,
|
||||||
|
on_construct = constructfn,
|
||||||
|
|
||||||
|
}
|
||||||
|
minetest.register_node("moretrees:coconut"..suffix, coconutdef)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- convert exisiting cocos palms. This is a bit tricky...
|
||||||
|
-- Try to make sure that this is indeed a generated tree, and not manually-placed trunks and/or coconuts
|
||||||
|
if moretrees.coconuts_convert_existing_palms then
|
||||||
|
local spec = {
|
||||||
|
name = "moretrees:convert_existing_cocos_palms_to_regrow_coconuts",
|
||||||
|
nodenames = "moretrees:coconut",
|
||||||
|
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||||
|
local trunks
|
||||||
|
local cvtrunks
|
||||||
|
local leaves
|
||||||
|
local coconuts
|
||||||
|
-- One regular trunk must be adjacent to the coconut
|
||||||
|
trunks = 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},
|
||||||
|
"moretrees:palm_trunk"
|
||||||
|
)
|
||||||
|
if #trunks ~= 1 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local tpos = trunks[1]
|
||||||
|
-- 1 or 2 other trunks must be one level below to the trunk being converted.
|
||||||
|
trunks = minetest.find_nodes_in_area(
|
||||||
|
{x=tpos.x-1, y=tpos.y-1, z=tpos.z-1},
|
||||||
|
{x=tpos.x+1, y=tpos.y-1, z=tpos.z+1},
|
||||||
|
"moretrees:palm_trunk"
|
||||||
|
)
|
||||||
|
if #trunks < 1 or #trunks > 2 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
-- 1 or 2 other trunks must be two levels below to the trunk being converted.
|
||||||
|
trunks = minetest.find_nodes_in_area(
|
||||||
|
{x=tpos.x-1, y=tpos.y-2, z=tpos.z-1},
|
||||||
|
{x=tpos.x+1, y=tpos.y-2, z=tpos.z+1},
|
||||||
|
"moretrees:palm_trunk"
|
||||||
|
)
|
||||||
|
if #trunks < 1 or #trunks > 2 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
-- 1 or 2 trunks must at the level of the trunk being converted.
|
||||||
|
cvtrunks = minetest.find_nodes_in_area(
|
||||||
|
{x=tpos.x-1, y=tpos.y, z=tpos.z-1},
|
||||||
|
{x=tpos.x+1, y=tpos.y, z=tpos.z+1},
|
||||||
|
"moretrees:palm_trunk"
|
||||||
|
)
|
||||||
|
if #cvtrunks < 1 or #cvtrunks > 2 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
-- No trunks may be one level above the trunk being converted.
|
||||||
|
trunks = minetest.find_nodes_in_area(
|
||||||
|
{x=tpos.x-1, y=tpos.y+1, z=tpos.z-1},
|
||||||
|
{x=tpos.x+1, y=tpos.y+1, z=tpos.z+1},
|
||||||
|
"moretrees:palm_trunk"
|
||||||
|
)
|
||||||
|
if #trunks ~= 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
-- Leaves must be one level above the trunk being converted.
|
||||||
|
leaves = minetest.find_nodes_in_area(
|
||||||
|
{x=tpos.x-1, y=tpos.y+1, z=tpos.z-1},
|
||||||
|
{x=tpos.x+1, y=tpos.y+1, z=tpos.z+1},
|
||||||
|
"moretrees:palm_leaves"
|
||||||
|
)
|
||||||
|
if #leaves == 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
-- Leaves must be two levels above the trunk being converted.
|
||||||
|
leaves = minetest.find_nodes_in_area(
|
||||||
|
{x=tpos.x-1, y=tpos.y+2, z=tpos.z-1},
|
||||||
|
{x=tpos.x+1, y=tpos.y+2, z=tpos.z+1},
|
||||||
|
"moretrees:palm_leaves"
|
||||||
|
)
|
||||||
|
if #leaves == 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
-- No cocos fruit trunk may already be adjacent to the coconut
|
||||||
|
trunks = 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},
|
||||||
|
"moretrees:palm_fruit_trunk"
|
||||||
|
)
|
||||||
|
if #trunks ~= 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
-- No cocos fruit trunk may be adjacent to or below the trunk being converted.
|
||||||
|
trunks = minetest.find_nodes_in_area(
|
||||||
|
{x=tpos.x-1, y=tpos.y-2, z=tpos.z-1},
|
||||||
|
{x=tpos.x+1, y=tpos.y, z=tpos.z+1},
|
||||||
|
"moretrees:palm_fruit_trunk"
|
||||||
|
)
|
||||||
|
if #trunks ~= 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
-- Convert trunk and all coconuts nearby. Maybe convert 2 trunks, just in case...
|
||||||
|
for _, tpos_1 in pairs(cvtrunks) do
|
||||||
|
minetest.swap_node(tpos_1, {name = "moretrees:palm_fruit_trunk"})
|
||||||
|
coconuts = minetest.find_nodes_in_area(
|
||||||
|
{x=tpos_1.x-1, y=tpos_1.y, z=tpos_1.z-1},
|
||||||
|
{x=tpos_1.x+1, y=tpos_1.y, z=tpos_1.z+1},
|
||||||
|
"moretrees:coconut"
|
||||||
|
)
|
||||||
|
for _, coconutpos in pairs(coconuts) do
|
||||||
|
minetest.swap_node(coconutpos, {name = "moretrees:coconut_3"})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
if minetest.register_lbm then
|
||||||
|
minetest.register_lbm(spec)
|
||||||
|
else
|
||||||
|
spec.interval = 3691
|
||||||
|
spec.chance = 10
|
||||||
|
minetest.register_abm(spec)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- If regrowing was previously disabled, but is enabled now, make sure timers are started for existing coconuts
|
||||||
|
if moretrees.coconuts_regrow then
|
||||||
|
local spec = {
|
||||||
|
name = "moretrees:restart_coconut_regrow_timer",
|
||||||
|
nodenames = "group:moretrees_coconut",
|
||||||
|
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||||
|
local timer = minetest.get_node_timer(pos)
|
||||||
|
if not timer:is_started() then
|
||||||
|
coconut_starttimer(pos)
|
||||||
|
else
|
||||||
|
local timeout = timer:get_timeout()
|
||||||
|
local elapsed = timer:get_elapsed()
|
||||||
|
if timeout - elapsed > moretrees.coconut_grow_interval * 4/3 then
|
||||||
|
coconut_starttimer(pos, math.random(moretrees.coconut_grow_interval * 4/3))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
if minetest.register_lbm then
|
||||||
|
minetest.register_lbm(spec)
|
||||||
|
else
|
||||||
|
spec.interval = 3659
|
||||||
|
spec.chance = 10
|
||||||
|
minetest.register_abm(spec)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
271
mods/moretrees/crafts.lua
Normal file
|
@ -0,0 +1,271 @@
|
||||||
|
local S = minetest.get_translator("moretrees")
|
||||||
|
|
||||||
|
for i in ipairs(moretrees.treelist) do
|
||||||
|
local treename = moretrees.treelist[i][1]
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "shapeless",
|
||||||
|
output = "moretrees:"..treename.."_planks 4",
|
||||||
|
recipe = {
|
||||||
|
"moretrees:"..treename.."_trunk"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "fuel",
|
||||||
|
recipe = "moretrees:"..treename.."_sapling",
|
||||||
|
burntime = 10,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "shapeless",
|
||||||
|
output = "moretrees:rubber_tree_planks 4",
|
||||||
|
recipe = {
|
||||||
|
"moretrees:rubber_tree_trunk_empty"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "fuel",
|
||||||
|
recipe = "group:moretrees_leaves",
|
||||||
|
burntime = 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Food recipes!
|
||||||
|
|
||||||
|
minetest.register_craftitem("moretrees:coconut_milk", {
|
||||||
|
description = S("Coconut Milk"),
|
||||||
|
inventory_image = "moretrees_coconut_milk_inv.png",
|
||||||
|
wield_image = "moretrees_coconut_milk.png",
|
||||||
|
on_use = minetest.item_eat(2, "vessels:drinking_glass"),
|
||||||
|
groups = {vessel = 1},
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("moretrees:raw_coconut", {
|
||||||
|
description = S("Raw Coconut"),
|
||||||
|
inventory_image = "moretrees_raw_coconut.png",
|
||||||
|
on_use = minetest.item_eat(4),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("moretrees:date", {
|
||||||
|
description = S("Date"),
|
||||||
|
inventory_image = "moretrees_date.png",
|
||||||
|
on_use = minetest.item_eat(1),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("moretrees:date_nut_snack", {
|
||||||
|
description = S("Date & nut snack"),
|
||||||
|
inventory_image = "moretrees_date_nut_snack.png",
|
||||||
|
on_use = minetest.item_eat(4),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("moretrees:date_nut_batter", {
|
||||||
|
description = S("Date-nut cake batter"),
|
||||||
|
inventory_image = "moretrees_date_nut_batter.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("moretrees:date_nut_cake", {
|
||||||
|
description = S("Date-nut cake"),
|
||||||
|
inventory_image = "moretrees_date_nut_cake.png",
|
||||||
|
on_use = minetest.item_eat(32),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("moretrees:date_nut_bar", {
|
||||||
|
description = S("Date-nut energy bar"),
|
||||||
|
inventory_image = "moretrees_date_nut_bar.png",
|
||||||
|
on_use = minetest.item_eat(4),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("moretrees:acorn_muffin_batter", {
|
||||||
|
description = S("Acorn Muffin batter"),
|
||||||
|
inventory_image = "moretrees_acorn_muffin_batter.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("moretrees:acorn_muffin", {
|
||||||
|
description = S("Acorn Muffin"),
|
||||||
|
inventory_image = "moretrees_acorn_muffin.png",
|
||||||
|
on_use = minetest.item_eat(4),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("moretrees:spruce_nuts", {
|
||||||
|
description = S("Roasted Spruce Cone Nuts"),
|
||||||
|
inventory_image = "moretrees_spruce_nuts.png",
|
||||||
|
on_use = minetest.item_eat(1),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("moretrees:cedar_nuts", {
|
||||||
|
description = S("Roasted Cedar Cone Nuts"),
|
||||||
|
inventory_image = "moretrees_cedar_nuts.png",
|
||||||
|
on_use = minetest.item_eat(1),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("moretrees:fir_nuts", {
|
||||||
|
description = S("Roasted Fir Cone Nuts"),
|
||||||
|
inventory_image = "moretrees_fir_nuts.png",
|
||||||
|
on_use = minetest.item_eat(1),
|
||||||
|
})
|
||||||
|
|
||||||
|
for i in ipairs(moretrees.cutting_tools) do
|
||||||
|
local tool = moretrees.cutting_tools[i]
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "shapeless",
|
||||||
|
output = "moretrees:coconut_milk",
|
||||||
|
recipe = {
|
||||||
|
"moretrees:coconut",
|
||||||
|
"vessels:drinking_glass",
|
||||||
|
tool
|
||||||
|
},
|
||||||
|
replacements = {
|
||||||
|
{ "moretrees:coconut", "moretrees:raw_coconut" },
|
||||||
|
}
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- give tool back with wear preserved
|
||||||
|
minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv)
|
||||||
|
if (itemstack:get_name() == "moretrees:coconut_milk") then
|
||||||
|
for i, j in pairs(old_craft_grid) do
|
||||||
|
-- find tool used to do the craft
|
||||||
|
local ocg_name = j:get_name()
|
||||||
|
if ((ocg_name ~= "") and (ocg_name ~= "moretrees:coconut") and (ocg_name ~= "vessels:drinking_glass")) then
|
||||||
|
-- abort if using cutting board
|
||||||
|
if minetest.get_item_group(ocg_name, "food_cutting_board") == 1 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
-- create a new tool and set wear
|
||||||
|
local t = ItemStack(ocg_name)
|
||||||
|
local w = j:get_wear()
|
||||||
|
-- works if tool used is an axe
|
||||||
|
local uses = j:get_tool_capabilities().groupcaps.choppy.uses or 0
|
||||||
|
if (w == 0 and uses ~= 0) then
|
||||||
|
-- tool has never been used
|
||||||
|
-- use tool once
|
||||||
|
t:set_wear(65535/(9*(uses - 1)))
|
||||||
|
else
|
||||||
|
-- set wear back
|
||||||
|
t:set_wear(w)
|
||||||
|
-- use tool once
|
||||||
|
if (uses ~= 0) then
|
||||||
|
t:add_wear(65535/(9*(uses - 1)))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- add to craft inventory
|
||||||
|
craft_inv:add_item("craft", t)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- coconut milk using food_cutting_board from farming redo
|
||||||
|
if minetest.registered_items["farming:cutting_board"] then
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "shapeless",
|
||||||
|
output = "moretrees:coconut_milk",
|
||||||
|
recipe = {
|
||||||
|
"moretrees:coconut",
|
||||||
|
"vessels:drinking_glass",
|
||||||
|
"group:food_cutting_board",
|
||||||
|
},
|
||||||
|
replacements = {
|
||||||
|
{ "moretrees:coconut", "moretrees:raw_coconut" },
|
||||||
|
{ "group:food_cutting_board", "farming:cutting_board" },
|
||||||
|
}
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "shapeless",
|
||||||
|
output = "moretrees:date_nut_snack",
|
||||||
|
recipe = {
|
||||||
|
"moretrees:date",
|
||||||
|
"moretrees:date",
|
||||||
|
"moretrees:date",
|
||||||
|
"moretrees:spruce_nuts",
|
||||||
|
"moretrees:cedar_nuts",
|
||||||
|
"moretrees:fir_nuts",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
-- The date-nut cake is an exceptional food item due to its highly
|
||||||
|
-- concentrated nature (32 food units). Because of that, it requires
|
||||||
|
-- many different ingredients, and, starting from the base ingredients
|
||||||
|
-- found or harvested in nature, it requires many steps to prepare.
|
||||||
|
local flour
|
||||||
|
if minetest.registered_nodes["farming:flour"] then
|
||||||
|
flour = "farming:flour"
|
||||||
|
else
|
||||||
|
flour = "moretrees:acorn_muffin_batter"
|
||||||
|
end
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "shapeless",
|
||||||
|
output = "moretrees:date_nut_batter",
|
||||||
|
recipe = {
|
||||||
|
"moretrees:date_nut_snack",
|
||||||
|
"moretrees:date_nut_snack",
|
||||||
|
"moretrees:date_nut_snack",
|
||||||
|
"moretrees:coconut_milk",
|
||||||
|
"moretrees:date_nut_snack",
|
||||||
|
"moretrees:raw_coconut",
|
||||||
|
"moretrees:coconut_milk",
|
||||||
|
flour,
|
||||||
|
"moretrees:raw_coconut",
|
||||||
|
},
|
||||||
|
replacements = {
|
||||||
|
{ "moretrees:coconut_milk", "vessels:drinking_glass 2" }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "cooking",
|
||||||
|
output = "moretrees:date_nut_cake",
|
||||||
|
recipe = "moretrees:date_nut_batter",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "shapeless",
|
||||||
|
output = "moretrees:date_nut_bar 8",
|
||||||
|
recipe = {"moretrees:date_nut_cake"},
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "shapeless",
|
||||||
|
output = "moretrees:acorn_muffin_batter",
|
||||||
|
recipe = {
|
||||||
|
"moretrees:acorn",
|
||||||
|
"moretrees:acorn",
|
||||||
|
"moretrees:acorn",
|
||||||
|
"moretrees:acorn",
|
||||||
|
"moretrees:coconut_milk",
|
||||||
|
},
|
||||||
|
replacements = {
|
||||||
|
{ "moretrees:coconut_milk", "vessels:drinking_glass" }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "cooking",
|
||||||
|
output = "moretrees:acorn_muffin 4",
|
||||||
|
recipe = "moretrees:acorn_muffin_batter",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "cooking",
|
||||||
|
output = "moretrees:spruce_nuts 4",
|
||||||
|
recipe = "moretrees:spruce_cone",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "cooking",
|
||||||
|
output = "moretrees:cedar_nuts 4",
|
||||||
|
recipe = "moretrees:cedar_cone",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "cooking",
|
||||||
|
output = "moretrees:fir_nuts 4",
|
||||||
|
recipe = "moretrees:fir_cone",
|
||||||
|
})
|
||||||
|
|
||||||
|
|
762
mods/moretrees/date_palm.lua
Normal file
|
@ -0,0 +1,762 @@
|
||||||
|
-- Date palms.
|
||||||
|
--
|
||||||
|
-- Date palms grow in hot and dry desert, but they require water. This makes them
|
||||||
|
-- a bit harder to find. If found in the middle of the desert, their presence
|
||||||
|
-- indicates a water source below the surface.
|
||||||
|
--
|
||||||
|
-- As an additional feature (which can be disabled), dates automatically regrow after
|
||||||
|
-- harvesting (provided a male tree is sufficiently nearby).
|
||||||
|
-- If regrowing is enabled, then ripe dates will not hang forever. Most will disappear
|
||||||
|
-- (e.g. eaten by birds, ...), and a small fraction will drop as items.
|
||||||
|
|
||||||
|
-- © 2016, Rogier <rogier777@gmail.com>
|
||||||
|
|
||||||
|
local S = minetest.get_translator("moretrees")
|
||||||
|
|
||||||
|
-- Some constants
|
||||||
|
|
||||||
|
local dates_drop_ichance = 4
|
||||||
|
local stems_drop_ichance = 4
|
||||||
|
local flowers_wither_ichance = 3
|
||||||
|
|
||||||
|
-- implementation
|
||||||
|
|
||||||
|
local dates_regrow_prob
|
||||||
|
if moretrees.dates_regrow_unpollinated_percent <= 0 then
|
||||||
|
dates_regrow_prob = 0
|
||||||
|
elseif moretrees.dates_regrow_unpollinated_percent >= 100 then
|
||||||
|
dates_regrow_prob = 1
|
||||||
|
else
|
||||||
|
dates_regrow_prob = 1 - math.pow(moretrees.dates_regrow_unpollinated_percent/100, 1/flowers_wither_ichance)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Make the date palm fruit trunk a real trunk (it is generated as a fruit)
|
||||||
|
local trunk = minetest.registered_nodes["moretrees:date_palm_trunk"]
|
||||||
|
local ftrunk = {}
|
||||||
|
local fftrunk = {}
|
||||||
|
local mftrunk = {}
|
||||||
|
for k,v in pairs(trunk) do
|
||||||
|
ftrunk[k] = v
|
||||||
|
end
|
||||||
|
ftrunk.tiles = {}
|
||||||
|
for k,v in pairs(trunk.tiles) do
|
||||||
|
ftrunk.tiles[k] = v
|
||||||
|
end
|
||||||
|
ftrunk.drop = "moretrees:date_palm_trunk"
|
||||||
|
ftrunk.after_destruct = function(pos, oldnode)
|
||||||
|
local dates = minetest.find_nodes_in_area(
|
||||||
|
{x=pos.x-2, y=pos.y, z=pos.z-2},
|
||||||
|
{x=pos.x+2, y=pos.y, z=pos.z+2},
|
||||||
|
{"group:moretrees_dates"}
|
||||||
|
)
|
||||||
|
for _,datespos in pairs(dates) do
|
||||||
|
-- minetest.dig_node(datespos) does not cause nearby dates to be dropped :-( ...
|
||||||
|
local items = minetest.get_node_drops(minetest.get_node(datespos).name)
|
||||||
|
minetest.swap_node(datespos, biome_lib.air)
|
||||||
|
for _, itemname in pairs(items) do
|
||||||
|
minetest.add_item(datespos, itemname)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for k,v in pairs(ftrunk) do
|
||||||
|
mftrunk[k] = v
|
||||||
|
fftrunk[k] = v
|
||||||
|
end
|
||||||
|
fftrunk.tiles = {}
|
||||||
|
mftrunk.tiles = {}
|
||||||
|
for k,v in pairs(trunk.tiles) do
|
||||||
|
fftrunk.tiles[k] = v
|
||||||
|
mftrunk.tiles[k] = v
|
||||||
|
end
|
||||||
|
-- Make the different types of trunk distinguishable (but not too easily)
|
||||||
|
ftrunk.tiles[1] = "moretrees_date_palm_trunk_top.png^[transformR180"
|
||||||
|
ftrunk.description = ftrunk.description.." (gen)"
|
||||||
|
fftrunk.tiles[1] = "moretrees_date_palm_trunk_top.png^[transformR90"
|
||||||
|
mftrunk.tiles[1] = "moretrees_date_palm_trunk_top.png^[transformR-90"
|
||||||
|
minetest.register_node("moretrees:date_palm_fruit_trunk", ftrunk)
|
||||||
|
minetest.register_node("moretrees:date_palm_ffruit_trunk", fftrunk)
|
||||||
|
minetest.register_node("moretrees:date_palm_mfruit_trunk", mftrunk)
|
||||||
|
|
||||||
|
-- ABM to grow new date blossoms
|
||||||
|
local date_regrow_abm_spec = {
|
||||||
|
nodenames = { "moretrees:date_palm_ffruit_trunk", "moretrees:date_palm_mfruit_trunk" },
|
||||||
|
interval = moretrees.dates_flower_interval,
|
||||||
|
chance = moretrees.dates_flower_chance,
|
||||||
|
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||||
|
local dates = minetest.find_nodes_in_area({x=pos.x-2, y=pos.y, z=pos.z-2}, {x=pos.x+2, y=pos.y, z=pos.z+2}, "group:moretrees_dates")
|
||||||
|
|
||||||
|
-- New blossom interval increases exponentially with number of dates already hanging
|
||||||
|
-- In addition: if more dates are hanging, the chance of picking an empty spot decreases as well...
|
||||||
|
if math.random(2^#dates) <= 2 then
|
||||||
|
-- Grow in area of 5x5 round trunk; higher probability in 3x3 area close to trunk
|
||||||
|
local dx=math.floor((math.random(50)-18)/16)
|
||||||
|
local dz=math.floor((math.random(50)-18)/16)
|
||||||
|
local datepos = {x=pos.x+dx, y=pos.y, z=pos.z+dz}
|
||||||
|
local datenode = minetest.get_node(datepos)
|
||||||
|
if datenode.name == "air" then
|
||||||
|
if node.name == "moretrees:date_palm_ffruit_trunk" then
|
||||||
|
minetest.swap_node(datepos, {name="moretrees:dates_f0"})
|
||||||
|
else
|
||||||
|
minetest.swap_node(datepos, {name="moretrees:dates_m0"})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
if moretrees.dates_regrow_pollinated or moretrees.dates_regrow_unpollinated_percent > 0 then
|
||||||
|
minetest.register_abm(date_regrow_abm_spec)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Choose male or female palm, and spawn initial dates
|
||||||
|
-- (Instead of dates, a dates fruit trunk is generated with the tree. This
|
||||||
|
-- ABM converts the trunk to a female or male fruit trunk, and spawns some
|
||||||
|
-- hanging dates)
|
||||||
|
minetest.register_abm({
|
||||||
|
nodenames = { "moretrees:date_palm_fruit_trunk" },
|
||||||
|
interval = 1,
|
||||||
|
chance = 1,
|
||||||
|
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||||
|
local type
|
||||||
|
if math.random(100) <= moretrees.dates_female_percent then
|
||||||
|
type = "f"
|
||||||
|
minetest.swap_node(pos, {name="moretrees:date_palm_ffruit_trunk"})
|
||||||
|
else
|
||||||
|
type = "m"
|
||||||
|
minetest.swap_node(pos, {name="moretrees:date_palm_mfruit_trunk"})
|
||||||
|
end
|
||||||
|
local dates1 = 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},
|
||||||
|
"air"
|
||||||
|
)
|
||||||
|
for _,genpos in pairs(dates1) do
|
||||||
|
if math.random(100) <= 20 then
|
||||||
|
if type == "m" then
|
||||||
|
minetest.swap_node(genpos, {name = "moretrees:dates_n"})
|
||||||
|
else
|
||||||
|
minetest.swap_node(genpos, {name = "moretrees:dates_f4"})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local dates2 = minetest.find_nodes_in_area(
|
||||||
|
{x=pos.x-2, y=pos.y, z=pos.z-2},
|
||||||
|
{x=pos.x+2, y=pos.y, z=pos.z+2},
|
||||||
|
"air"
|
||||||
|
)
|
||||||
|
for _,genpos in pairs(dates2) do
|
||||||
|
if math.random(100) <= 5 then
|
||||||
|
if type == "m" then
|
||||||
|
minetest.swap_node(genpos, {name = "moretrees:dates_n"})
|
||||||
|
else
|
||||||
|
minetest.swap_node(genpos, {name = "moretrees:dates_f4"})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Dates growing functions.
|
||||||
|
|
||||||
|
-- This is a bit complex, as the purpose is to find male flowers at horizontal distances of over
|
||||||
|
-- 100 nodes. As searching such a large area is time consuming, this is optimized in four ways:
|
||||||
|
-- - The search result (the locations of male trees) is cached, so that it can be used again
|
||||||
|
-- - Only 1/9th of the desired area is searched at a time. A new search is only performed if no male
|
||||||
|
-- flowers are found in the previously searched parts.
|
||||||
|
-- - Search results are shared with other female palms nearby.
|
||||||
|
-- - If previous searches for male palms have consumed too much CPU time, the search is skipped
|
||||||
|
-- (This means no male palms will be found, and the pollination of the flowers affected will be
|
||||||
|
-- delayed. If this happens repeatedly, eventually, the female flowers will wither...)
|
||||||
|
-- A caching method was selected that is suited for the case where most date trees are long-lived,
|
||||||
|
-- and where the number of trees nearby is limited:
|
||||||
|
-- - Locations of male palms are stored as metadata for every female palm. This means that a player
|
||||||
|
-- visiting a remote area with some date palms will not cause extensive searches for male palms as
|
||||||
|
-- long overdue blossoming ABMs are triggered for every date palm.
|
||||||
|
-- - Even when male palms *are* cut down, a cache refill will only be performed if the cached results do not
|
||||||
|
-- contain a male palm with blossoms.
|
||||||
|
-- The method will probably perform suboptimally:
|
||||||
|
-- - If female palms are frequently chopped down and replanted.
|
||||||
|
-- Freshly grown palms will need to search for male palms again
|
||||||
|
-- (this is mitigated by the long blossoming interval, which increases the chance that search
|
||||||
|
-- results have already been shared)
|
||||||
|
-- - If an area contains a large number of male and female palms.
|
||||||
|
-- In this area, every female palm will have an almost identical list of male palm locations
|
||||||
|
-- as metadata.
|
||||||
|
-- - If all male palms within range of a number of female palms have been chopped down (with possibly
|
||||||
|
-- new ones planted). Although an attempt was made to share search results in this case as well,
|
||||||
|
-- a number of similar searches will unavoidably be performed by the different female palms.
|
||||||
|
-- - If no male palms are in range of a female palm. In that case, there will be frequent searches
|
||||||
|
-- for newly-grown male palms.
|
||||||
|
|
||||||
|
-- Search statistics - used to limit the search load.
|
||||||
|
local sect_search_stats = {} -- Search statistics - server-wide
|
||||||
|
local function reset_sect_search_stats()
|
||||||
|
sect_search_stats.count = 0 -- # of searches
|
||||||
|
sect_search_stats.skip = 0 -- # of times skipped
|
||||||
|
sect_search_stats.sum = 0 -- total time spent
|
||||||
|
sect_search_stats.min = 999999999 -- min time spent
|
||||||
|
sect_search_stats.max = 0 -- max time spent
|
||||||
|
end
|
||||||
|
reset_sect_search_stats()
|
||||||
|
sect_search_stats.last_us = 0 -- last time a search was done (microseconds, max: 2^32)
|
||||||
|
sect_search_stats.last_s = 0 -- last time a search was done (system time in seconds)
|
||||||
|
|
||||||
|
-- Find male trunks in one section (=1/9 th) of the searchable area.
|
||||||
|
-- sect is -4 to 4, where 0 is the center section
|
||||||
|
local function find_fruit_trunks_near(ftpos, sect)
|
||||||
|
local r = moretrees.dates_pollination_distance + 2 * math.sqrt(2)
|
||||||
|
local sect_hr = math.floor(r / 3 + 0.9999)
|
||||||
|
local sect_vr = math.floor(r / 2 + 0.9999)
|
||||||
|
local t0us = minetest.get_us_time()
|
||||||
|
local t0s = os.time()
|
||||||
|
|
||||||
|
-- Compute elapsed time since last search.
|
||||||
|
-- Unfortunately, the time value wraps after about 71 minutes (2^32 microseconds),
|
||||||
|
-- so it must be corrected to obtain the actual elapsed time.
|
||||||
|
if t0us < sect_search_stats.last_us then
|
||||||
|
-- Correct a simple wraparound.
|
||||||
|
-- This is not sufficient, as the time value may have wrapped more than once...
|
||||||
|
sect_search_stats.last_us = sect_search_stats.last_us - 2^32
|
||||||
|
end
|
||||||
|
if t0s - sect_search_stats.last_s > 2^32/1000000 then
|
||||||
|
-- One additional correction is enough for our purposes.
|
||||||
|
-- For exact results, more corrections may be needed though...
|
||||||
|
-- (and even not applying this correction at all would still only yield
|
||||||
|
-- a minimal risk of a non-serious miscalculation...)
|
||||||
|
sect_search_stats.last_us = sect_search_stats.last_us - 2^32
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Skip the search if it is consuming too much CPU time
|
||||||
|
if sect_search_stats.count > 0 and moretrees.dates_blossom_search_iload > 0
|
||||||
|
and sect_search_stats.sum / sect_search_stats.count > moretrees.dates_blossom_search_time_treshold
|
||||||
|
and t0us - sect_search_stats.last_us < moretrees.dates_blossom_search_iload * (sect_search_stats.sum / sect_search_stats.count) then
|
||||||
|
sect_search_stats.skip = sect_search_stats.skip + 1
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local basevec = { x = ftpos.x + 2 * sect.x * sect_hr,
|
||||||
|
y = ftpos.y,
|
||||||
|
z = ftpos.z + 2 * sect.z * sect_hr}
|
||||||
|
-- find_nodes_in_area is limited to 82^3, make sure to not overrun it
|
||||||
|
local sizevec = { x = sect_hr, y = sect_vr, z = sect_hr }
|
||||||
|
if sect_hr * sect_hr * sect_vr > 41^3 then
|
||||||
|
sizevec = vector.apply(sizevec, function(a) return math.min(a, 41) end)
|
||||||
|
end
|
||||||
|
|
||||||
|
local all_palms = minetest.find_nodes_in_area(
|
||||||
|
vector.subtract(basevec, sizevec),
|
||||||
|
vector.add(basevec, sizevec),
|
||||||
|
{"moretrees:date_palm_mfruit_trunk", "moretrees:date_palm_ffruit_trunk"})
|
||||||
|
|
||||||
|
-- Collect different palms in separate lists.
|
||||||
|
local female_palms = {}
|
||||||
|
local male_palms = {}
|
||||||
|
local all_male_palms = {}
|
||||||
|
for _, pos in pairs(all_palms) do
|
||||||
|
if pos.x ~= ftpos.x or pos.y ~= ftpos.y or pos.z ~= ftpos.z then
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
if node and node.name == "moretrees:date_palm_ffruit_trunk" then
|
||||||
|
table.insert(female_palms,pos)
|
||||||
|
elseif node then
|
||||||
|
table.insert(all_male_palms,pos)
|
||||||
|
-- In sector 0, all palms are of interest.
|
||||||
|
-- In other sectors, forget about palms that are too far away.
|
||||||
|
if sect == 0 then
|
||||||
|
table.insert(male_palms,pos)
|
||||||
|
else
|
||||||
|
local ssq = 0
|
||||||
|
for _, c in pairs({"x", "z"}) do
|
||||||
|
local dc = pos[c] - ftpos[c]
|
||||||
|
ssq = ssq + dc * dc
|
||||||
|
end
|
||||||
|
if math.sqrt(ssq) <= r then
|
||||||
|
table.insert(male_palms,pos)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Update search statistics
|
||||||
|
local t1us = minetest.get_us_time()
|
||||||
|
if t1us < t0us then
|
||||||
|
-- Wraparound. Assume the search lasted less than 2^32 microseconds (~71 min)
|
||||||
|
-- (so no need to apply another correction)
|
||||||
|
t0us = t0us - 2^32
|
||||||
|
end
|
||||||
|
sect_search_stats.last_us = t0us
|
||||||
|
sect_search_stats.last_s = t0s
|
||||||
|
sect_search_stats.count = sect_search_stats.count + 1
|
||||||
|
sect_search_stats.sum = sect_search_stats.sum + t1us-t0us
|
||||||
|
if t1us - t0us < sect_search_stats.min then
|
||||||
|
sect_search_stats.min = t1us - t0us
|
||||||
|
end
|
||||||
|
if t1us - t0us > sect_search_stats.max then
|
||||||
|
sect_search_stats.max = t1us - t0us
|
||||||
|
end
|
||||||
|
|
||||||
|
return male_palms, female_palms, all_male_palms
|
||||||
|
end
|
||||||
|
|
||||||
|
local function dates_print_search_stats(log)
|
||||||
|
local stats
|
||||||
|
if sect_search_stats.count > 0 then
|
||||||
|
stats = string.format("Male date tree searching stats: searches: %d/%d: average: %d µs (%d..%d)",
|
||||||
|
sect_search_stats.count, sect_search_stats.count + sect_search_stats.skip,
|
||||||
|
sect_search_stats.sum/sect_search_stats.count, sect_search_stats.min, sect_search_stats.max)
|
||||||
|
else
|
||||||
|
stats = string.format("Male date tree searching stats: searches: 0/0: average: (no searches yet)")
|
||||||
|
end
|
||||||
|
if log then
|
||||||
|
minetest.log("action", "[moretrees] " .. stats)
|
||||||
|
end
|
||||||
|
return true, stats
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_chatcommand("dates_stats", {
|
||||||
|
description = "Print male date palm search statistics",
|
||||||
|
params = "|chat|log|reset",
|
||||||
|
privs = { server = true },
|
||||||
|
func = function(name, param)
|
||||||
|
param = string.lower(param:gsub("%s+", ""))
|
||||||
|
if param == "" or param == "chat" then
|
||||||
|
return dates_print_search_stats(false)
|
||||||
|
elseif param == "log" then
|
||||||
|
return dates_print_search_stats(true)
|
||||||
|
elseif param == "reset" then
|
||||||
|
reset_sect_search_stats()
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false, "Invalid subcommand; expected: '' or 'chat' or 'log' or 'reset'"
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Find the female trunk near the female flowers to be pollinated
|
||||||
|
local function find_female_trunk(fbpos)
|
||||||
|
local trunks = minetest.find_nodes_in_area({x=fbpos.x-2, y=fbpos.y, z=fbpos.z-2},
|
||||||
|
{x=fbpos.x+2, y=fbpos.y, z=fbpos.z+2},
|
||||||
|
"moretrees:date_palm_ffruit_trunk")
|
||||||
|
local ftpos
|
||||||
|
local d = 99
|
||||||
|
for x, pos in pairs(trunks) do
|
||||||
|
local ssq = 0
|
||||||
|
for _, c in pairs({"x", "z"}) do
|
||||||
|
local dc = pos[c] - fbpos[c]
|
||||||
|
ssq = ssq + dc * dc
|
||||||
|
end
|
||||||
|
if math.sqrt(ssq) < d then
|
||||||
|
ftpos = pos
|
||||||
|
d = math.sqrt(ssq)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ftpos
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Find male blossom near a male trunk,
|
||||||
|
-- the male blossom must be in range of a specific female blossom as well
|
||||||
|
local function find_male_blossom_near_trunk(fbpos, mtpos)
|
||||||
|
local r = moretrees.dates_pollination_distance
|
||||||
|
local blossoms = minetest.find_nodes_in_area({x=mtpos.x-2, y=mtpos.y, z=mtpos.z-2},
|
||||||
|
{x=mtpos.x+2, y=mtpos.y, z=mtpos.z+2},
|
||||||
|
"moretrees:dates_m0")
|
||||||
|
for x, mbpos in pairs(blossoms) do
|
||||||
|
local ssq = 0
|
||||||
|
for _, c in pairs({"x", "z"}) do
|
||||||
|
local dc = mbpos[c] - fbpos[c]
|
||||||
|
ssq = ssq + dc * dc
|
||||||
|
end
|
||||||
|
if math.sqrt(ssq) <= r then
|
||||||
|
return mbpos
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Find a male blossom in range of a specific female blossom,
|
||||||
|
-- using a nested list of male blossom positions
|
||||||
|
local function find_male_blossom_in_mpalms(ftpos, fbpos, mpalms)
|
||||||
|
-- Process the elements of mpalms.sect (index -4 .. 4) in random order
|
||||||
|
-- First, compute the order in which the sectors will be searched
|
||||||
|
local sect_index = {}
|
||||||
|
local sect_rnd = {}
|
||||||
|
for i = -4,4 do
|
||||||
|
local n = math.random(1023)
|
||||||
|
sect_index[n] = i
|
||||||
|
table.insert(sect_rnd, n)
|
||||||
|
end
|
||||||
|
table.sort(sect_rnd)
|
||||||
|
|
||||||
|
-- Search the sectors
|
||||||
|
local sect_old = 0
|
||||||
|
local sect_time = minetest.get_gametime()
|
||||||
|
for _, n in pairs(sect_rnd) do
|
||||||
|
-- Record the oldest sector, so that it can be searched if no male
|
||||||
|
-- blossoms were found
|
||||||
|
if not mpalms.sect_time[sect_index[n]] then
|
||||||
|
sect_old = sect_index[n]
|
||||||
|
sect_time = 0
|
||||||
|
elseif mpalms.sect_time[sect_index[n]] < sect_time then
|
||||||
|
sect_old = sect_index[n]
|
||||||
|
sect_time = mpalms.sect_time[sect_index[n]]
|
||||||
|
end
|
||||||
|
if mpalms.sect[sect_index[n]] and #mpalms.sect[sect_index[n]] then
|
||||||
|
for px, mtpos in pairs(mpalms.sect[sect_index[n]]) do
|
||||||
|
local node = minetest.get_node(mtpos)
|
||||||
|
if node and node.name == "moretrees:date_palm_mfruit_trunk" then
|
||||||
|
local mbpos = find_male_blossom_near_trunk(fbpos, mtpos)
|
||||||
|
if mbpos then
|
||||||
|
return mbpos
|
||||||
|
end
|
||||||
|
elseif node and node.name ~= "ignore" then
|
||||||
|
-- no more male trunk here.
|
||||||
|
mpalms.sect[sect_index[n]][px] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil, sect_old
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Find a male blossom in range of a specific female blossom,
|
||||||
|
-- using the cache associated with the given female trunk
|
||||||
|
-- If necessary, recompute part of the cache
|
||||||
|
local last_search_result = {}
|
||||||
|
local function find_male_blossom_with_ftrunk(fbpos,ftpos)
|
||||||
|
local meta = minetest.get_meta(ftpos)
|
||||||
|
local mpalms
|
||||||
|
local cache_changed = true
|
||||||
|
|
||||||
|
-- Load cache. If distance has changed, start with empty cache instead.
|
||||||
|
local mpalms_dist = meta:get_int("male_palms_dist")
|
||||||
|
if mpalms_dist and mpalms_dist == moretrees.dates_pollination_distance then
|
||||||
|
mpalms = meta:get_string("male_palms")
|
||||||
|
if mpalms and mpalms ~= "" then
|
||||||
|
mpalms = minetest.deserialize(mpalms)
|
||||||
|
cache_changed = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not mpalms or not mpalms.sect then
|
||||||
|
mpalms = {}
|
||||||
|
mpalms.sect = {}
|
||||||
|
mpalms.sect_time = {}
|
||||||
|
meta:set_int("male_palms_dist", moretrees.dates_pollination_distance)
|
||||||
|
cache_changed = true
|
||||||
|
end
|
||||||
|
local fpalms_list
|
||||||
|
local all_mpalms_list
|
||||||
|
local sector0_searched = false
|
||||||
|
|
||||||
|
-- Always make sure that sector 0 is cached
|
||||||
|
if not mpalms.sect[0] then
|
||||||
|
mpalms.sect[0], fpalms_list, all_mpalms_list = find_fruit_trunks_near(ftpos, {x = 0, z = 0})
|
||||||
|
mpalms.sect_time[0] = minetest.get_gametime()
|
||||||
|
sector0_searched = true
|
||||||
|
cache_changed = true
|
||||||
|
last_search_result.female = fpalms_list
|
||||||
|
last_search_result.male = all_mpalms_list
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Find male palms
|
||||||
|
local mbpos, sect_old = find_male_blossom_in_mpalms(ftpos, fbpos, mpalms)
|
||||||
|
|
||||||
|
-- If not found, (re)generate the cache for an additional sector. But don't search it yet (for performance reasons)
|
||||||
|
-- (Use the globally cached results if possible)
|
||||||
|
if not mbpos and not sector0_searched then
|
||||||
|
if not mpalms.sect_time[0] or mpalms.sect_time[0] == 0 or math.random(3) == 1 then
|
||||||
|
-- Higher probability of re-searching the center sector
|
||||||
|
sect_old = 0
|
||||||
|
end
|
||||||
|
-- Use globally cached result if possible
|
||||||
|
mpalms.sect[sect_old] = nil
|
||||||
|
if sect_old == 0 and mpalms.sect_time[0] and mpalms.sect_time[0] > 0
|
||||||
|
and last_search_result.male and #last_search_result.male then
|
||||||
|
for _, pos in pairs(last_search_result.female) do
|
||||||
|
if pos.x == ftpos.x and pos.y == ftpos.y and pos.z == ftpos.z then
|
||||||
|
mpalms.sect[sect_old] = last_search_result.male
|
||||||
|
-- Next time, don't use the cached result
|
||||||
|
mpalms.sect_time[sect_old] = nil
|
||||||
|
cache_changed = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Else do a new search
|
||||||
|
if not mpalms.sect[sect_old] then
|
||||||
|
mpalms.sect[sect_old], fpalms_list, all_mpalms_list = find_fruit_trunks_near(ftpos, {x = (sect_old + 4) % 3 - 1, z = (sect_old + 4) / 3 - 1})
|
||||||
|
cache_changed = true
|
||||||
|
if sect_old == 0 then
|
||||||
|
-- Save the results if it is sector 0
|
||||||
|
-- (chance of reusing results from another sector are smaller)
|
||||||
|
last_search_result.female = fpalms_list
|
||||||
|
last_search_result.male = all_mpalms_list
|
||||||
|
end
|
||||||
|
if mpalms.sect[sect_old] then
|
||||||
|
mpalms.sect_time[sect_old] = minetest.get_gametime()
|
||||||
|
else
|
||||||
|
mpalms.sect_time[sect_old] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Share search results with other female trunks in the same area
|
||||||
|
-- Note that the list of female trunks doesn't (shouldn't :-) contain the current female trunk.
|
||||||
|
if fpalms_list and #fpalms_list and #all_mpalms_list then
|
||||||
|
local all_mpalms = {}
|
||||||
|
all_mpalms.sect = {}
|
||||||
|
all_mpalms.sect_time = {}
|
||||||
|
all_mpalms.sect[0] = all_mpalms_list
|
||||||
|
-- Don't set sect_time[0], so that the cached sector will be re-searched soon (if necessary)
|
||||||
|
local all_mpalms_serialized = minetest.serialize(all_mpalms)
|
||||||
|
for _, pos in pairs(fpalms_list) do
|
||||||
|
local fmeta = minetest.get_meta(pos)
|
||||||
|
local fdist = fmeta:get_int("male_palms_dist")
|
||||||
|
if not fdist or fdist ~= moretrees.dates_pollination_distance then
|
||||||
|
fmeta:set_string("male_palms", all_mpalms_serialized)
|
||||||
|
fmeta:set_int("male_palms_dist", moretrees.dates_pollination_distance)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Save cache.
|
||||||
|
if cache_changed then
|
||||||
|
meta:set_string("male_palms", minetest.serialize(mpalms))
|
||||||
|
end
|
||||||
|
|
||||||
|
return mbpos
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Find a male blossom in range of a specific female blossom
|
||||||
|
local function find_male_blossom(fbpos)
|
||||||
|
local ftpos = find_female_trunk(fbpos)
|
||||||
|
if ftpos then
|
||||||
|
return find_male_blossom_with_ftrunk(fbpos, ftpos)
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Growing function for dates
|
||||||
|
local dates_growfn = function(pos, elapsed)
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
local delay = moretrees.dates_grow_interval
|
||||||
|
local action
|
||||||
|
if not node then
|
||||||
|
return
|
||||||
|
elseif not moretrees.dates_regrow_pollinated and dates_regrow_prob == 0 then
|
||||||
|
-- Regrowing of dates is disabled.
|
||||||
|
if string.find(node.name, "moretrees:dates_f") then
|
||||||
|
minetest.swap_node(pos, {name="moretrees:dates_f4"})
|
||||||
|
elseif string.find(node.name, "moretrees:dates_m") then
|
||||||
|
minetest.swap_node(pos, {name="moretrees:dates_n"})
|
||||||
|
else
|
||||||
|
minetest.swap_node(pos, biome_lib.air)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
elseif node.name == "moretrees:dates_f0" and math.random(100) <= 100 * dates_regrow_prob then
|
||||||
|
-- Dates grow unpollinated
|
||||||
|
minetest.swap_node(pos, {name="moretrees:dates_f1"})
|
||||||
|
action = "nopollinate"
|
||||||
|
elseif node.name == "moretrees:dates_f0" and moretrees.dates_regrow_pollinated and find_male_blossom(pos) then
|
||||||
|
-- Pollinate flowers
|
||||||
|
minetest.swap_node(pos, {name="moretrees:dates_f1"})
|
||||||
|
action = "pollinate"
|
||||||
|
elseif string.match(node.name, "0$") then
|
||||||
|
-- Make female unpollinated and male flowers last a bit longer
|
||||||
|
if math.random(flowers_wither_ichance) == 1 then
|
||||||
|
if node.name == "moretrees:dates_f0" then
|
||||||
|
minetest.swap_node(pos, {name="moretrees:dates_fn"})
|
||||||
|
else
|
||||||
|
minetest.swap_node(pos, {name="moretrees:dates_n"})
|
||||||
|
end
|
||||||
|
action = "wither"
|
||||||
|
else
|
||||||
|
action = "nowither"
|
||||||
|
end
|
||||||
|
elseif node.name == "moretrees:dates_f4" then
|
||||||
|
-- Remove dates, and optionally drop them as items
|
||||||
|
if math.random(dates_drop_ichance) == 1 then
|
||||||
|
if moretrees.dates_item_drop_ichance > 0 and math.random(moretrees.dates_item_drop_ichance) == 1 then
|
||||||
|
local items = minetest.get_node_drops(minetest.get_node(pos).name)
|
||||||
|
for _, itemname in pairs(items) do
|
||||||
|
minetest.add_item(pos, itemname)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
minetest.swap_node(pos, {name="moretrees:dates_n"})
|
||||||
|
action = "drop"
|
||||||
|
else
|
||||||
|
action = "nodrop"
|
||||||
|
end
|
||||||
|
elseif string.match(node.name, "n$") then
|
||||||
|
-- Remove stems.
|
||||||
|
if math.random(stems_drop_ichance) == 1 then
|
||||||
|
minetest.swap_node(pos, biome_lib.air)
|
||||||
|
return "stemdrop"
|
||||||
|
end
|
||||||
|
action = "nostemdrop"
|
||||||
|
else
|
||||||
|
-- Grow dates
|
||||||
|
local offset = 18
|
||||||
|
local n = string.sub(node.name, offset)
|
||||||
|
minetest.swap_node(pos, {name=string.sub(node.name, 1, offset-1)..n+1})
|
||||||
|
action = "grow"
|
||||||
|
end
|
||||||
|
-- Don't catch up when elapsed time is large. Regular visits are needed for growth...
|
||||||
|
local timer = minetest.get_node_timer(pos)
|
||||||
|
timer:start(delay + math.random(moretrees.dates_grow_interval))
|
||||||
|
return action
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[
|
||||||
|
-- Alternate growth function for dates.
|
||||||
|
-- It calls the primary growth function, but also measures CPU time consumed.
|
||||||
|
-- Use this function to analyze date growing performance.
|
||||||
|
local stat = {}
|
||||||
|
stat.count = 0
|
||||||
|
local dates_growfn_profiling = function(pos, elapsed)
|
||||||
|
local t0 = minetest.get_us_time()
|
||||||
|
local action = dates_growfn(pos, elapsed)
|
||||||
|
local t1 = minetest.get_us_time()
|
||||||
|
if t1 < t0 then
|
||||||
|
t1 = t1 + 2^32
|
||||||
|
end
|
||||||
|
stat.count = stat.count + 1
|
||||||
|
if not stat[action] then
|
||||||
|
stat[action] = {}
|
||||||
|
stat[action].count = 0
|
||||||
|
stat[action].sum = 0
|
||||||
|
stat[action].min = 9999999999
|
||||||
|
stat[action].max = 0
|
||||||
|
end
|
||||||
|
stat[action].count = stat[action].count + 1
|
||||||
|
stat[action].sum = stat[action].sum + t1-t0
|
||||||
|
if t1-t0 < stat[action].min then
|
||||||
|
stat[action].min = t1-t0
|
||||||
|
end
|
||||||
|
if t1-t0 > stat[action].max then
|
||||||
|
stat[action].max = t1-t0
|
||||||
|
end
|
||||||
|
|
||||||
|
if stat.count % 10 == 0 then
|
||||||
|
io.write(".")
|
||||||
|
io.flush()
|
||||||
|
end
|
||||||
|
if stat.count % 100 == 0 then
|
||||||
|
print(string.format("Date grow statistics %5d:", stat.count))
|
||||||
|
local sum = 0
|
||||||
|
local count = 0
|
||||||
|
if sect_search_stats.count > 0 and stat.pollinate and stat.pollinate.count > 0 then
|
||||||
|
print(string.format("\t%-12s: %6d (%4.1f%%): %6dus (%d..%d)",
|
||||||
|
"search", sect_search_stats.count,
|
||||||
|
100*sect_search_stats.count/stat.pollinate.count,
|
||||||
|
sect_search_stats.sum/sect_search_stats.count,
|
||||||
|
sect_search_stats.min, sect_search_stats.max))
|
||||||
|
else
|
||||||
|
print(string.format("\t%-12s: %6d (%4.1f%%): %6dus (%d..%d)",
|
||||||
|
"search", sect_search_stats.count,
|
||||||
|
0, 0, 0, 0))
|
||||||
|
end
|
||||||
|
for action,data in pairs(stat) do
|
||||||
|
if action ~= "count" then
|
||||||
|
count = count + data.count
|
||||||
|
sum = sum + data.sum
|
||||||
|
print(string.format("\t%-12s: %6d (%4.1f%%): %6dus (%d..%d)",
|
||||||
|
action, data.count,
|
||||||
|
100*data.count/stat.count, data.sum/data.count,
|
||||||
|
data.min, data.max))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print(string.format("\t%-12s: %6d ( 100%%): %6dus",
|
||||||
|
"TOTAL", count, sum/count))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--]]
|
||||||
|
|
||||||
|
-- Register dates
|
||||||
|
|
||||||
|
local dates_starttimer = function(pos, elapsed)
|
||||||
|
local timer = minetest.get_node_timer(pos)
|
||||||
|
local base_interval = moretrees.dates_grow_interval * 2 / 3
|
||||||
|
timer:set(base_interval + math.random(base_interval), elapsed or 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
local dates_drop = {
|
||||||
|
items = {
|
||||||
|
{items = { "moretrees:date" }},
|
||||||
|
{items = { "moretrees:date" }},
|
||||||
|
{items = { "moretrees:date" }},
|
||||||
|
{items = { "moretrees:date" }},
|
||||||
|
{items = { "moretrees:date" }, rarity = 2 },
|
||||||
|
{items = { "moretrees:date" }, rarity = 2 },
|
||||||
|
{items = { "moretrees:date" }, rarity = 2 },
|
||||||
|
{items = { "moretrees:date" }, rarity = 2 },
|
||||||
|
{items = { "moretrees:date" }, rarity = 5 },
|
||||||
|
{items = { "moretrees:date" }, rarity = 5 },
|
||||||
|
{items = { "moretrees:date" }, rarity = 5 },
|
||||||
|
{items = { "moretrees:date" }, rarity = 5 },
|
||||||
|
{items = { "moretrees:date" }, rarity = 20 },
|
||||||
|
{items = { "moretrees:date" }, rarity = 20 },
|
||||||
|
{items = { "moretrees:date" }, rarity = 20 },
|
||||||
|
{items = { "moretrees:date" }, rarity = 20 },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _,suffix in ipairs({"f0", "f1", "f2", "f3", "f4", "m0", "fn", "n"}) do
|
||||||
|
local name
|
||||||
|
if suffix == "f0" or suffix == "m0" then
|
||||||
|
name = S("Date Flowers")
|
||||||
|
elseif suffix == "n" or suffix == "fn" then
|
||||||
|
name = S("Date Stem")
|
||||||
|
else
|
||||||
|
name = S("Dates")
|
||||||
|
end
|
||||||
|
local dropfn = suffix == "f4" and dates_drop or ""
|
||||||
|
local datedef = {
|
||||||
|
description = name,
|
||||||
|
tiles = {"moretrees_dates_"..suffix..".png"},
|
||||||
|
visual_scale = 2,
|
||||||
|
drawtype = "plantlike",
|
||||||
|
paramtype = "light",
|
||||||
|
sunlight_propagates = true,
|
||||||
|
walkable = false,
|
||||||
|
groups = { fleshy=3, dig_immediate=3, flammable=2, moretrees_dates=1 },
|
||||||
|
inventory_image = "moretrees_dates_"..suffix..".png^[transformR0",
|
||||||
|
wield_image = "moretrees_dates_"..suffix..".png^[transformR90",
|
||||||
|
sounds = default.node_sound_defaults(),
|
||||||
|
drop = dropfn,
|
||||||
|
selection_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {-0.3, -0.3, -0.3, 0.3, 3.5, 0.3}
|
||||||
|
},
|
||||||
|
on_timer = dates_growfn,
|
||||||
|
on_construct = (moretrees.dates_regrow_pollinated or moretrees.dates_regrow_unpollinated_percent > 0)
|
||||||
|
and dates_starttimer,
|
||||||
|
|
||||||
|
}
|
||||||
|
minetest.register_node("moretrees:dates_"..suffix, datedef)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- If regrowing was previously disabled, but is enabled now, make sure timers are started for existing dates
|
||||||
|
if moretrees.dates_regrow_pollinated or moretrees.dates_regrow_unpollinated_percent > 0 then
|
||||||
|
local spec = {
|
||||||
|
name = "moretrees:restart_dates_regrow_timer",
|
||||||
|
nodenames = "group:moretrees_dates",
|
||||||
|
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||||
|
local timer = minetest.get_node_timer(pos)
|
||||||
|
if not timer:is_started() then
|
||||||
|
dates_starttimer(pos)
|
||||||
|
else
|
||||||
|
local timeout = timer:get_timeout()
|
||||||
|
local elapsed = timer:get_elapsed()
|
||||||
|
if timeout - elapsed > moretrees.dates_grow_interval * 4/3 then
|
||||||
|
dates_starttimer(pos, math.random(moretrees.dates_grow_interval * 4/3))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
if minetest.register_lbm then
|
||||||
|
minetest.register_lbm(spec)
|
||||||
|
else
|
||||||
|
spec.interval = 3557
|
||||||
|
spec.chance = 10
|
||||||
|
minetest.register_abm(spec)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
135
mods/moretrees/default_settings.txt
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
-- Global configuration variables
|
||||||
|
|
||||||
|
-- Enable the various kinds of trees.
|
||||||
|
|
||||||
|
moretrees.enable_apple_tree = true
|
||||||
|
moretrees.enable_oak = true
|
||||||
|
moretrees.enable_sequoia = true
|
||||||
|
moretrees.enable_palm = true
|
||||||
|
moretrees.enable_date_palm = true
|
||||||
|
moretrees.enable_cedar = true
|
||||||
|
moretrees.enable_rubber_tree = true
|
||||||
|
moretrees.enable_willow = true
|
||||||
|
moretrees.enable_birch = true
|
||||||
|
moretrees.enable_spruce = true
|
||||||
|
moretrees.enable_jungle_tree = true
|
||||||
|
moretrees.enable_fir = true
|
||||||
|
moretrees.enable_poplar = true
|
||||||
|
moretrees.enable_beech = false
|
||||||
|
|
||||||
|
-- set this to true to make moretrees spawn saplings at mapgen time instead
|
||||||
|
-- of fully-grown trees, which will grow into full trees after a very short
|
||||||
|
-- delay. This reduces mapgen lag in some situations, and fixes situations
|
||||||
|
-- where the mapgen conflicts with the tree generator.
|
||||||
|
|
||||||
|
moretrees.spawn_saplings = true
|
||||||
|
|
||||||
|
-- Set this to true to allow defining stairs/slabs/etc. If Moreblocks is
|
||||||
|
-- installed, this will use that mod's Stairs Plus component. Otherwise, it
|
||||||
|
-- will use the default stairs mod in minetest_game, if present
|
||||||
|
|
||||||
|
moretrees.enable_stairs = true
|
||||||
|
|
||||||
|
-- If this variable is set to true, register fences for moretrees wood
|
||||||
|
|
||||||
|
moretrees.enable_fences = false
|
||||||
|
|
||||||
|
-- Set this to true if you want the plantlike drawtype for leaves, which
|
||||||
|
-- improves some peoples' framerates without resorting to making leaf nodes opaque.
|
||||||
|
-- Affects default leaves and default jungle leaves also.
|
||||||
|
|
||||||
|
moretrees.plantlike_leaves = false
|
||||||
|
|
||||||
|
-- Enable this if you want moretrees to redefine default apples so that they
|
||||||
|
-- fall when leaves decay/are dug.
|
||||||
|
|
||||||
|
moretrees.enable_redefine_apple = true
|
||||||
|
|
||||||
|
-- Set this to true to enable leaf decay of all trees except the default ones.
|
||||||
|
|
||||||
|
moretrees.enable_leafdecay = true
|
||||||
|
|
||||||
|
-- various related settings to configure leaf decay.
|
||||||
|
|
||||||
|
moretrees.leafdecay_delay = 2
|
||||||
|
moretrees.leafdecay_chance = 5
|
||||||
|
moretrees.leafdecay_radius = 5
|
||||||
|
moretrees.palm_leafdecay_radius = 10
|
||||||
|
|
||||||
|
-- Change these settings if you want default trees to be gradually cut down
|
||||||
|
-- above the elevation where firs normally generate.
|
||||||
|
|
||||||
|
moretrees.firs_remove_default_trees = false
|
||||||
|
moretrees.firs_remove_interval = 2
|
||||||
|
moretrees.firs_remove_chance = 150
|
||||||
|
|
||||||
|
-- Cocos palm settings
|
||||||
|
|
||||||
|
moretrees.coconuts_regrow = true
|
||||||
|
moretrees.coconuts_convert_existing_palms = true -- Converting existing palm trees will make coconuts regrow on them as well
|
||||||
|
-- Else, they will only regrow on newly-spawned palms
|
||||||
|
-- However, conversion is not an exact science, and although an attempt is
|
||||||
|
-- made to detect whether a trunk belongs to an actual palm, some coconut trunks
|
||||||
|
-- and some coconuts may be incorrectly converted.
|
||||||
|
moretrees.coconut_flower_interval = 59
|
||||||
|
moretrees.coconut_flower_chance = 67
|
||||||
|
moretrees.coconut_grow_interval = 2 * moretrees.coconut_flower_interval * moretrees.coconut_flower_chance
|
||||||
|
-- Actual interval will randomly vary between 67% and 133% of this value
|
||||||
|
-- 2 * 59 * 67 ~ 2 hours. So flowers become coconuts in about 6 hours
|
||||||
|
moretrees.coconut_item_drop_ichance = 10 -- inverse probability of ripe coconuts dropping as items (instead of disappearing)
|
||||||
|
|
||||||
|
-- Date palm settings
|
||||||
|
|
||||||
|
-- Suggested configuration alternatives:
|
||||||
|
-- - Dates grow only when pollinated:
|
||||||
|
-- - Set dates_regrow_pollinated to true
|
||||||
|
-- - Set dates_regrow_unpollinated_percent to 0
|
||||||
|
-- - Dates grow without pollination. Pollination disabled:
|
||||||
|
-- - Set dates_regrow_pollinated to false
|
||||||
|
-- - Set dates_regrow_unpollinated_percent to some larger positive value, e.g. 95
|
||||||
|
-- - Dates grow, but more and faster if male flowers are nearby
|
||||||
|
-- - Set dates_regrow_pollinated to true
|
||||||
|
-- - Set dates_regrow_unpollinated_percent to some small positive value, e.g. 33
|
||||||
|
-- - Optional but recommended: Reduce the pollination distance, e.g. to 30
|
||||||
|
|
||||||
|
-- Note that it should not be necessary to disable pollination for performance
|
||||||
|
-- reasons. A lot of effort has gone into ensuring that date growing will not cause lag.
|
||||||
|
--
|
||||||
|
-- If lag is suspected, use the chat command '/dates_stats' to obtain the male dates
|
||||||
|
-- search time, as well as the counts of total number of searches requested and the
|
||||||
|
-- number of searches actually performed.
|
||||||
|
|
||||||
|
moretrees.dates_regrow_pollinated = true -- Enable pollination. If enabled, male trees are required for dates to grow.
|
||||||
|
-- If disabled, dates_regrow_unpollinated_percent must be non-zero for dates to regrow.
|
||||||
|
moretrees.dates_regrow_unpollinated_percent = 0 -- Percentage of female dates becoming dates without being pollinated.
|
||||||
|
-- If 0, dates_regrow_pollinated must be enabled for dates to grow.
|
||||||
|
moretrees.dates_female_percent = 57 -- Ratio of female to male trees - tune this to improve # of generated trees that actually bear fruit
|
||||||
|
-- ~57% gives near optimal results for groups of 3 random trees, while it is only slightly suboptimal
|
||||||
|
-- for groups of 2 and 4 random trees (~2% less fruit than optimal).
|
||||||
|
-- Optimal values per group size: 2: 50%, 3: 57.78%, 4: 63%, 5: 66.9%, 6: 69.9%, [...], 12: 79.8%
|
||||||
|
-- So 57% is optimal for small groups of trees. As larger groups have more female palms anyway, a
|
||||||
|
-- less than optimal proportion of female to male trees is not a problem.
|
||||||
|
moretrees.dates_pollination_distance = 120
|
||||||
|
moretrees.dates_blossom_search_time_treshold = 1000 -- If average male blossom search time (in microseconds) exceeds this, start limiting the search load.
|
||||||
|
moretrees.dates_blossom_search_iload = 10 -- Inverse fraction of CPU time that male blossom searching search may consume.
|
||||||
|
-- As searching a large area (radius: dates_pollination_distance/3 per attempt) can cause lag,
|
||||||
|
-- this limits the search frequency server-wide so that the impact on server lag is minimised
|
||||||
|
-- For personal servers, this can be set lower, or even to 1 or 0 (0 disables load limiting).
|
||||||
|
-- Obtain the current average search time using /dates_stats
|
||||||
|
moretrees.dates_flower_interval = 59
|
||||||
|
moretrees.dates_flower_chance = 181
|
||||||
|
moretrees.dates_grow_interval = 2 * moretrees.dates_flower_interval * moretrees.dates_flower_chance
|
||||||
|
-- As date palms have a high yield, don't grow dates too fast
|
||||||
|
-- The actual interval will vary randomly between 67% and 133% of this value.
|
||||||
|
-- 2 * 59 * 181 ~ 6 hours. So by default flowers become dates in about one (human) day.
|
||||||
|
moretrees.dates_item_drop_ichance = 10 -- inverse probability of ripe dates dropping as items (instead of disappearing)
|
||||||
|
|
||||||
|
-- Sapling settings
|
||||||
|
|
||||||
|
moretrees.sapling_interval = 100
|
||||||
|
moretrees.sapling_chance = 5
|
||||||
|
|
||||||
|
-- If this variable is set to true, drop leaves out as entities during leaf
|
||||||
|
-- decay, rather than just disappearing them.
|
||||||
|
|
||||||
|
moretrees.decay_leaves_as_items = false
|
329
mods/moretrees/init.lua
Normal file
|
@ -0,0 +1,329 @@
|
||||||
|
-- More trees! 2013-04-07
|
||||||
|
--
|
||||||
|
-- This mod adds more types of trees to the game
|
||||||
|
--
|
||||||
|
-- Some of the node definitions and textures came from cisoun's conifers mod
|
||||||
|
-- and bas080's jungle trees mod.
|
||||||
|
--
|
||||||
|
-- Brought together into one mod and made L-systems compatible by Vanessa
|
||||||
|
-- Ezekowitz.
|
||||||
|
--
|
||||||
|
-- Firs and Jungle tree axioms/rules by Vanessa Dannenberg, with the
|
||||||
|
-- latter having been tweaked by RealBadAngel, most other axioms/rules written
|
||||||
|
-- by RealBadAngel.
|
||||||
|
--
|
||||||
|
|
||||||
|
moretrees = {}
|
||||||
|
|
||||||
|
minetest.override_item("default:sapling", {
|
||||||
|
description = "Sapling"
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.override_item("default:tree", {
|
||||||
|
description = "Tree"
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.override_item("default:wood", {
|
||||||
|
description = "Wooden Planks"
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.override_item("default:leaves", {
|
||||||
|
description = "Leaves"
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.override_item("default:fence_wood", {
|
||||||
|
description = "Wooden Fence"
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.override_item("default:fence_rail_wood", {
|
||||||
|
description = "Wooden Fence Rail"
|
||||||
|
})
|
||||||
|
|
||||||
|
if minetest.get_modpath("doors") then
|
||||||
|
minetest.override_item("doors:gate_wood_closed", {
|
||||||
|
description = "Wooden Fence Gate"
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.override_item("doors:gate_wood_open", {
|
||||||
|
description = "Wooden Fence Gate"
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Read the default config file (and if necessary, copy it to the world folder).
|
||||||
|
|
||||||
|
local worldpath=minetest.get_worldpath()
|
||||||
|
local modpath=minetest.get_modpath("moretrees")
|
||||||
|
|
||||||
|
dofile(modpath.."/default_settings.txt")
|
||||||
|
|
||||||
|
if io.open(worldpath.."/moretrees_settings.txt","r") then
|
||||||
|
io.close()
|
||||||
|
dofile(worldpath.."/moretrees_settings.txt")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- infinite stacks checking
|
||||||
|
|
||||||
|
if minetest.get_modpath("unified_inventory") or not
|
||||||
|
minetest.settings:get_bool("creative_mode") then
|
||||||
|
moretrees.expect_infinite_stacks = false
|
||||||
|
else
|
||||||
|
moretrees.expect_infinite_stacks = true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- tables, load other files
|
||||||
|
|
||||||
|
moretrees.cutting_tools = {
|
||||||
|
"default:axe_bronze",
|
||||||
|
"default:axe_diamond",
|
||||||
|
"default:axe_mese",
|
||||||
|
"default:axe_steel",
|
||||||
|
"glooptest:axe_alatro",
|
||||||
|
"glooptest:axe_arol",
|
||||||
|
"moreores:axe_mithril",
|
||||||
|
"moreores:axe_silver",
|
||||||
|
"titanium:axe",
|
||||||
|
}
|
||||||
|
|
||||||
|
dofile(modpath.."/tree_models.lua")
|
||||||
|
dofile(modpath.."/node_defs.lua")
|
||||||
|
dofile(modpath.."/date_palm.lua")
|
||||||
|
dofile(modpath.."/cocos_palm.lua")
|
||||||
|
dofile(modpath.."/biome_defs.lua")
|
||||||
|
dofile(modpath.."/saplings.lua")
|
||||||
|
dofile(modpath.."/crafts.lua")
|
||||||
|
|
||||||
|
-- tree spawning setup
|
||||||
|
|
||||||
|
if moretrees.spawn_saplings then
|
||||||
|
moretrees.spawn_beech_object = "moretrees:beech_sapling_ongen"
|
||||||
|
moretrees.spawn_apple_tree_object = "moretrees:apple_tree_sapling_ongen"
|
||||||
|
moretrees.spawn_oak_object = "moretrees:oak_sapling_ongen"
|
||||||
|
moretrees.spawn_sequoia_object = "moretrees:sequoia_sapling_ongen"
|
||||||
|
moretrees.spawn_palm_object = "moretrees:palm_sapling_ongen"
|
||||||
|
moretrees.spawn_date_palm_object = "moretrees:date_palm_sapling_ongen"
|
||||||
|
moretrees.spawn_cedar_object = "moretrees:cedar_sapling_ongen"
|
||||||
|
moretrees.spawn_rubber_tree_object = "moretrees:rubber_tree_sapling_ongen"
|
||||||
|
moretrees.spawn_willow_object = "moretrees:willow_sapling_ongen"
|
||||||
|
moretrees.spawn_birch_object = "moretrees:birch_sapling_ongen"
|
||||||
|
moretrees.spawn_spruce_object = "moretrees:spruce_sapling_ongen"
|
||||||
|
moretrees.spawn_jungletree_object = "moretrees:jungletree_sapling_ongen"
|
||||||
|
moretrees.spawn_fir_object = "moretrees:fir_sapling_ongen"
|
||||||
|
moretrees.spawn_fir_snow_object = "snow:sapling_pine"
|
||||||
|
moretrees.spawn_poplar_object = "moretrees:poplar_sapling_ongen"
|
||||||
|
moretrees.spawn_poplar_small_object = "moretrees:poplar_small_sapling_ongen"
|
||||||
|
else
|
||||||
|
moretrees.spawn_beech_object = moretrees.beech_model
|
||||||
|
moretrees.spawn_apple_tree_object = moretrees.apple_tree_model
|
||||||
|
moretrees.spawn_oak_object = moretrees.oak_model
|
||||||
|
moretrees.spawn_sequoia_object = moretrees.sequoia_model
|
||||||
|
moretrees.spawn_palm_object = moretrees.palm_model
|
||||||
|
moretrees.spawn_date_palm_object = moretrees.date_palm_model
|
||||||
|
moretrees.spawn_cedar_object = moretrees.cedar_model
|
||||||
|
moretrees.spawn_rubber_tree_object = moretrees.rubber_tree_model
|
||||||
|
moretrees.spawn_willow_object = moretrees.willow_model
|
||||||
|
moretrees.spawn_birch_object = "moretrees.grow_birch"
|
||||||
|
moretrees.spawn_spruce_object = "moretrees.grow_spruce"
|
||||||
|
moretrees.spawn_jungletree_object = "moretrees.grow_jungletree"
|
||||||
|
moretrees.spawn_fir_object = "moretrees.grow_fir"
|
||||||
|
moretrees.spawn_fir_snow_object = "moretrees.grow_fir_snow"
|
||||||
|
moretrees.spawn_poplar_object = moretrees.poplar_model
|
||||||
|
moretrees.spawn_poplar_small_object = moretrees.poplar_small_model
|
||||||
|
end
|
||||||
|
|
||||||
|
if moretrees.enable_beech then
|
||||||
|
biome_lib:register_generate_plant(moretrees.beech_biome, moretrees.spawn_beech_object)
|
||||||
|
end
|
||||||
|
|
||||||
|
if moretrees.enable_apple_tree then
|
||||||
|
biome_lib:register_generate_plant(moretrees.apple_tree_biome, moretrees.spawn_apple_tree_object)
|
||||||
|
end
|
||||||
|
|
||||||
|
if moretrees.enable_oak then
|
||||||
|
biome_lib:register_generate_plant(moretrees.oak_biome, moretrees.spawn_oak_object)
|
||||||
|
end
|
||||||
|
|
||||||
|
if moretrees.enable_sequoia then
|
||||||
|
biome_lib:register_generate_plant(moretrees.sequoia_biome, moretrees.spawn_sequoia_object)
|
||||||
|
end
|
||||||
|
|
||||||
|
if moretrees.enable_palm then
|
||||||
|
biome_lib:register_generate_plant(moretrees.palm_biome, moretrees.spawn_palm_object)
|
||||||
|
end
|
||||||
|
|
||||||
|
if moretrees.enable_date_palm then
|
||||||
|
biome_lib:register_generate_plant(moretrees.date_palm_biome, moretrees.spawn_date_palm_object)
|
||||||
|
biome_lib:register_generate_plant(moretrees.date_palm_biome_2, moretrees.spawn_date_palm_object)
|
||||||
|
end
|
||||||
|
|
||||||
|
if moretrees.enable_cedar then
|
||||||
|
biome_lib:register_generate_plant(moretrees.cedar_biome, moretrees.spawn_cedar_object)
|
||||||
|
end
|
||||||
|
|
||||||
|
if moretrees.enable_rubber_tree then
|
||||||
|
biome_lib:register_generate_plant(moretrees.rubber_tree_biome, moretrees.spawn_rubber_tree_object)
|
||||||
|
end
|
||||||
|
|
||||||
|
if moretrees.enable_willow then
|
||||||
|
biome_lib:register_generate_plant(moretrees.willow_biome, moretrees.spawn_willow_object)
|
||||||
|
end
|
||||||
|
|
||||||
|
if moretrees.enable_birch then
|
||||||
|
biome_lib:register_generate_plant(moretrees.birch_biome, moretrees.spawn_birch_object)
|
||||||
|
end
|
||||||
|
|
||||||
|
if moretrees.enable_spruce then
|
||||||
|
biome_lib:register_generate_plant(moretrees.spruce_biome, moretrees.spawn_spruce_object)
|
||||||
|
end
|
||||||
|
|
||||||
|
if moretrees.enable_jungle_tree then
|
||||||
|
biome_lib:register_generate_plant(moretrees.jungletree_biome, moretrees.spawn_jungletree_object)
|
||||||
|
end
|
||||||
|
|
||||||
|
if moretrees.enable_fir then
|
||||||
|
biome_lib:register_generate_plant(moretrees.fir_biome, moretrees.spawn_fir_object)
|
||||||
|
if minetest.get_modpath("snow") then
|
||||||
|
biome_lib:register_generate_plant(moretrees.fir_biome_snow, moretrees.spawn_fir_snow_object)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if moretrees.enable_poplar then
|
||||||
|
biome_lib:register_generate_plant(moretrees.poplar_biome, moretrees.spawn_poplar_object)
|
||||||
|
biome_lib:register_generate_plant(moretrees.poplar_biome_2, moretrees.spawn_poplar_object)
|
||||||
|
biome_lib:register_generate_plant(moretrees.poplar_biome_3, moretrees.spawn_poplar_object)
|
||||||
|
biome_lib:register_generate_plant(moretrees.poplar_small_biome, moretrees.spawn_poplar_small_object)
|
||||||
|
biome_lib:register_generate_plant(moretrees.poplar_small_biome_2, moretrees.spawn_poplar_small_object)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Code to spawn a birch tree
|
||||||
|
|
||||||
|
function moretrees.grow_birch(pos)
|
||||||
|
minetest.swap_node(pos, biome_lib.air)
|
||||||
|
if math.random(1,2) == 1 then
|
||||||
|
minetest.spawn_tree(pos, moretrees.birch_model1)
|
||||||
|
else
|
||||||
|
minetest.spawn_tree(pos, moretrees.birch_model2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Code to spawn a spruce tree
|
||||||
|
|
||||||
|
function moretrees.grow_spruce(pos)
|
||||||
|
minetest.swap_node(pos, biome_lib.air)
|
||||||
|
if math.random(1,2) == 1 then
|
||||||
|
minetest.spawn_tree(pos, moretrees.spruce_model1)
|
||||||
|
else
|
||||||
|
minetest.spawn_tree(pos, moretrees.spruce_model2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Code to spawn jungle trees
|
||||||
|
|
||||||
|
moretrees.jt_axiom1 = "FFFA"
|
||||||
|
moretrees.jt_rules_a1 = "FFF[&&-FBf[&&&Ff]^^^Ff][&&+FBFf[&&&FFf]^^^Ff][&&---FBFf[&&&Ff]^^^Ff][&&+++FBFf[&&&Ff]^^^Ff]F/A"
|
||||||
|
moretrees.jt_rules_b1 = "[-Ff&f][+Ff&f]B"
|
||||||
|
|
||||||
|
moretrees.jt_axiom2 = "FFFFFA"
|
||||||
|
moretrees.jt_rules_a2 = "FFFFF[&&-FFFBF[&&&FFff]^^^FFf][&&+FFFBFF[&&&FFff]^^^FFf][&&---FFFBFF[&&&FFff]^^^FFf][&&+++FFFBFF[&&&FFff]^^^FFf]FF/A"
|
||||||
|
moretrees.jt_rules_b2 = "[-FFf&ff][+FFf&ff]B"
|
||||||
|
|
||||||
|
moretrees.ct_rules_a1 = "FF[FF][&&-FBF][&&+FBF][&&---FBF][&&+++FBF]F/A"
|
||||||
|
moretrees.ct_rules_b1 = "[-FBf][+FBf]"
|
||||||
|
|
||||||
|
moretrees.ct_rules_a2 = "FF[FF][&&-FBF][&&+FBF][&&---FBF][&&+++FBF]F/A"
|
||||||
|
moretrees.ct_rules_b2 = "[-fB][+fB]"
|
||||||
|
|
||||||
|
function moretrees.grow_jungletree(pos)
|
||||||
|
local r1 = math.random(2)
|
||||||
|
local r2 = math.random(3)
|
||||||
|
if r1 == 1 then
|
||||||
|
moretrees.jungletree_model.leaves2 = "moretrees:jungletree_leaves_red"
|
||||||
|
else
|
||||||
|
moretrees.jungletree_model.leaves2 = "moretrees:jungletree_leaves_yellow"
|
||||||
|
end
|
||||||
|
moretrees.jungletree_model.leaves2_chance = math.random(25, 75)
|
||||||
|
|
||||||
|
if r2 == 1 then
|
||||||
|
moretrees.jungletree_model.trunk_type = "single"
|
||||||
|
moretrees.jungletree_model.iterations = 2
|
||||||
|
moretrees.jungletree_model.axiom = moretrees.jt_axiom1
|
||||||
|
moretrees.jungletree_model.rules_a = moretrees.jt_rules_a1
|
||||||
|
moretrees.jungletree_model.rules_b = moretrees.jt_rules_b1
|
||||||
|
elseif r2 == 2 then
|
||||||
|
moretrees.jungletree_model.trunk_type = "double"
|
||||||
|
moretrees.jungletree_model.iterations = 4
|
||||||
|
moretrees.jungletree_model.axiom = moretrees.jt_axiom2
|
||||||
|
moretrees.jungletree_model.rules_a = moretrees.jt_rules_a2
|
||||||
|
moretrees.jungletree_model.rules_b = moretrees.jt_rules_b2
|
||||||
|
elseif r2 == 3 then
|
||||||
|
moretrees.jungletree_model.trunk_type = "crossed"
|
||||||
|
moretrees.jungletree_model.iterations = 4
|
||||||
|
moretrees.jungletree_model.axiom = moretrees.jt_axiom2
|
||||||
|
moretrees.jungletree_model.rules_a = moretrees.jt_rules_a2
|
||||||
|
moretrees.jungletree_model.rules_b = moretrees.jt_rules_b2
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.swap_node(pos, biome_lib.air)
|
||||||
|
local leaves = minetest.find_nodes_in_area({x = pos.x-1, y = pos.y, z = pos.z-1}, {x = pos.x+1, y = pos.y+10, z = pos.z+1}, "default:leaves")
|
||||||
|
for leaf in ipairs(leaves) do
|
||||||
|
minetest.swap_node(leaves[leaf], biome_lib.air)
|
||||||
|
end
|
||||||
|
minetest.spawn_tree(pos, moretrees.jungletree_model)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- code to spawn fir trees
|
||||||
|
|
||||||
|
function moretrees.grow_fir(pos)
|
||||||
|
if math.random(2) == 1 then
|
||||||
|
moretrees.fir_model.leaves="moretrees:fir_leaves"
|
||||||
|
else
|
||||||
|
moretrees.fir_model.leaves="moretrees:fir_leaves_bright"
|
||||||
|
end
|
||||||
|
if math.random(2) == 1 then
|
||||||
|
moretrees.fir_model.rules_a = moretrees.ct_rules_a1
|
||||||
|
moretrees.fir_model.rules_b = moretrees.ct_rules_b1
|
||||||
|
else
|
||||||
|
moretrees.fir_model.rules_a = moretrees.ct_rules_a2
|
||||||
|
moretrees.fir_model.rules_b = moretrees.ct_rules_b2
|
||||||
|
end
|
||||||
|
|
||||||
|
moretrees.fir_model.iterations = 7
|
||||||
|
moretrees.fir_model.random_level = 5
|
||||||
|
|
||||||
|
minetest.swap_node(pos, biome_lib.air)
|
||||||
|
local leaves = minetest.find_nodes_in_area({x = pos.x, y = pos.y, z = pos.z}, {x = pos.x, y = pos.y+5, z = pos.z}, "default:leaves")
|
||||||
|
for leaf in ipairs(leaves) do
|
||||||
|
minetest.swap_node(leaves[leaf], biome_lib.air)
|
||||||
|
end
|
||||||
|
minetest.spawn_tree(pos,moretrees.fir_model)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- same thing, but a smaller version that grows only in snow biomes
|
||||||
|
|
||||||
|
function moretrees.grow_fir_snow(pos)
|
||||||
|
if math.random(2) == 1 then
|
||||||
|
moretrees.fir_model.leaves="moretrees:fir_leaves"
|
||||||
|
else
|
||||||
|
moretrees.fir_model.leaves="moretrees:fir_leaves_bright"
|
||||||
|
end
|
||||||
|
if math.random(2) == 1 then
|
||||||
|
moretrees.fir_model.rules_a = moretrees.ct_rules_a1
|
||||||
|
moretrees.fir_model.rules_b = moretrees.ct_rules_b1
|
||||||
|
else
|
||||||
|
moretrees.fir_model.rules_a = moretrees.ct_rules_a2
|
||||||
|
moretrees.fir_model.rules_b = moretrees.ct_rules_b2
|
||||||
|
end
|
||||||
|
|
||||||
|
moretrees.fir_model.iterations = 2
|
||||||
|
moretrees.fir_model.random_level = 2
|
||||||
|
|
||||||
|
minetest.swap_node(pos, biome_lib.air)
|
||||||
|
local leaves = minetest.find_nodes_in_area({x = pos.x, y = pos.y, z = pos.z}, {x = pos.x, y = pos.y+5, z = pos.z}, "default:leaves")
|
||||||
|
for leaf in ipairs(leaves) do
|
||||||
|
minetest.swap_node(leaves[leaf], biome_lib.air)
|
||||||
|
end
|
||||||
|
minetest.spawn_tree(pos,moretrees.fir_model)
|
||||||
|
end
|
||||||
|
|
||||||
|
print("[Moretrees] Loaded (2013-02-11)")
|
211
mods/moretrees/locale/moretrees.de.tr
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
# textdomain: moretrees
|
||||||
|
# Translation by Xanthin
|
||||||
|
|
||||||
|
|
||||||
|
### cocos_palm.lua ###
|
||||||
|
|
||||||
|
Coconut=Kokosnuss
|
||||||
|
Coconut Flower=
|
||||||
|
|
||||||
|
### crafts.lua ###
|
||||||
|
|
||||||
|
Acorn Muffin=Eichelmuffin
|
||||||
|
Acorn Muffin batter=Eichelmuffinteig
|
||||||
|
Coconut Milk=Kokosnussmilch
|
||||||
|
Date=
|
||||||
|
Date & nut snack=
|
||||||
|
Date-nut cake=
|
||||||
|
Date-nut cake batter=
|
||||||
|
Date-nut energy bar=
|
||||||
|
Raw Coconut=Kokosnussfleisch
|
||||||
|
Roasted Cedar Cone Nuts=
|
||||||
|
Roasted Fir Cone Nuts=Geroestete Tannenzapfen
|
||||||
|
Roasted Spruce Cone Nuts=Geroestete Fichtenzapfen
|
||||||
|
|
||||||
|
### date_palm.lua ###
|
||||||
|
|
||||||
|
Date Flowers=
|
||||||
|
Date Stem=
|
||||||
|
Dates=
|
||||||
|
|
||||||
|
### node_defs.lua ###
|
||||||
|
|
||||||
|
@1 (fast growth)=
|
||||||
|
Acorn=Eichel
|
||||||
|
Apple Tree=
|
||||||
|
Apple Tree Fence=
|
||||||
|
Apple Tree Fence Gate=
|
||||||
|
Apple Tree Fence Rail=
|
||||||
|
Apple Tree Leaves=Apfelbaumlaub
|
||||||
|
Apple Tree Planks=Apfelbaumbretter
|
||||||
|
Apple Tree Planks Slab=
|
||||||
|
Apple Tree Planks Stair=
|
||||||
|
Apple Tree Sapling=Apfelbaumsetzling
|
||||||
|
Apple Tree Trunk=Apfelbaumstamm
|
||||||
|
Apple Tree Trunk Slab=
|
||||||
|
Apple Tree Trunk Stair=
|
||||||
|
Beech Tree=
|
||||||
|
Beech Tree Fence=
|
||||||
|
Beech Tree Fence Gate=
|
||||||
|
Beech Tree Fence Rail=
|
||||||
|
Beech Tree Leaves=Buchenlaub
|
||||||
|
Beech Tree Planks=Buchebretter
|
||||||
|
Beech Tree Planks Slab=
|
||||||
|
Beech Tree Planks Stair=
|
||||||
|
Beech Tree Sapling=Buchesetzling
|
||||||
|
Beech Tree Trunk=Buchenstamm
|
||||||
|
Beech Tree Trunk Slab=
|
||||||
|
Beech Tree Trunk Stair=
|
||||||
|
Birch Tree=
|
||||||
|
Birch Tree Fence=
|
||||||
|
Birch Tree Fence Gate=
|
||||||
|
Birch Tree Fence Rail=
|
||||||
|
Birch Tree Leaves=Birkenlaub
|
||||||
|
Birch Tree Planks=Birkebretter
|
||||||
|
Birch Tree Planks Slab=
|
||||||
|
Birch Tree Planks Stair=
|
||||||
|
Birch Tree Sapling=Birkensetzling
|
||||||
|
Birch Tree Trunk=Birkenstamm
|
||||||
|
Birch Tree Trunk Slab=
|
||||||
|
Birch Tree Trunk Stair=
|
||||||
|
Cedar Cone=
|
||||||
|
Cedar Tree=
|
||||||
|
Cedar Tree Fence=
|
||||||
|
Cedar Tree Fence Gate=
|
||||||
|
Cedar Tree Fence Rail=
|
||||||
|
Cedar Tree Leaves=
|
||||||
|
Cedar Tree Planks=
|
||||||
|
Cedar Tree Planks Slab=
|
||||||
|
Cedar Tree Planks Stair=
|
||||||
|
Cedar Tree Sapling=
|
||||||
|
Cedar Tree Trunk=
|
||||||
|
Cedar Tree Trunk Slab=
|
||||||
|
Cedar Tree Trunk Stair=
|
||||||
|
Date Palm Tree=
|
||||||
|
Date Palm Tree Fence=
|
||||||
|
Date Palm Tree Fence Gate=
|
||||||
|
Date Palm Tree Fence Rail=
|
||||||
|
Date Palm Tree Leaves=
|
||||||
|
Date Palm Tree Planks=
|
||||||
|
Date Palm Tree Planks Slab=
|
||||||
|
Date Palm Tree Planks Stair=
|
||||||
|
Date Palm Tree Sapling=
|
||||||
|
Date Palm Tree Trunk=
|
||||||
|
Date Palm Tree Trunk Slab=
|
||||||
|
Date Palm Tree Trunk Stair=
|
||||||
|
Douglas Fir=
|
||||||
|
Douglas Fir Fence=
|
||||||
|
Douglas Fir Fence Gate=
|
||||||
|
Douglas Fir Fence Rail=
|
||||||
|
Douglas Fir Leaves=Douglasiennadeln
|
||||||
|
Douglas Fir Leaves (Bright)=Douglasiennadeln (breit)
|
||||||
|
Douglas Fir Planks=Douglasienbretter
|
||||||
|
Douglas Fir Planks Slab=
|
||||||
|
Douglas Fir Planks Stair=
|
||||||
|
Douglas Fir Sapling=Douglasiensetzling
|
||||||
|
Douglas Fir Trunk=Douglasienstamm
|
||||||
|
Douglas Fir Trunk Slab=
|
||||||
|
Douglas Fir Trunk Stair=
|
||||||
|
Fir Cone=Tannenzapfen
|
||||||
|
Giant Sequoia=
|
||||||
|
Giant Sequoia Fence=
|
||||||
|
Giant Sequoia Fence Gate=
|
||||||
|
Giant Sequoia Fence Rail=
|
||||||
|
Giant Sequoia Leaves=Riesenmammutbaumlaub
|
||||||
|
Giant Sequoia Planks=Riesenmammutbaumbretter
|
||||||
|
Giant Sequoia Planks Slab=
|
||||||
|
Giant Sequoia Planks Stair=
|
||||||
|
Giant Sequoia Sapling=Riesenmammutbaumsetzling
|
||||||
|
Giant Sequoia Trunk=Riesenmammutbaumstamm
|
||||||
|
Giant Sequoia Trunk Slab=
|
||||||
|
Giant Sequoia Trunk Stair=
|
||||||
|
Jungle Tree=
|
||||||
|
Jungle Tree Fence=
|
||||||
|
Jungle Tree Fence Gate=
|
||||||
|
Jungle Tree Fence Rail=
|
||||||
|
Jungle Tree Leaves=Tropenbaumlaub
|
||||||
|
Jungle Tree Leaves (@1)=Tropenbaumlaub (@1)
|
||||||
|
Jungle Tree Planks=Tropenholzbretter
|
||||||
|
Jungle Tree Planks Slab=
|
||||||
|
Jungle Tree Planks Stair=
|
||||||
|
Jungle Tree Sapling=Tropenbaumsetzling
|
||||||
|
Jungle Tree Trunk=Tropenbaumstamm
|
||||||
|
Jungle Tree Trunk Slab=
|
||||||
|
Jungle Tree Trunk Stair=
|
||||||
|
Oak Tree=
|
||||||
|
Oak Tree Fence=
|
||||||
|
Oak Tree Fence Gate=
|
||||||
|
Oak Tree Fence Rail=
|
||||||
|
Oak Tree Leaves=Eichenlaub
|
||||||
|
Oak Tree Planks=Eichenbretter
|
||||||
|
Oak Tree Planks Slab=
|
||||||
|
Oak Tree Planks Stair=
|
||||||
|
Oak Tree Sapling=Eichensetzling
|
||||||
|
Oak Tree Trunk=Eichenstamm
|
||||||
|
Oak Tree Trunk Slab=
|
||||||
|
Oak Tree Trunk Stair=
|
||||||
|
Palm Tree=
|
||||||
|
Palm Tree Fence=
|
||||||
|
Palm Tree Fence Gate=
|
||||||
|
Palm Tree Fence Rail=
|
||||||
|
Palm Tree Leaves=Palmenlaub
|
||||||
|
Palm Tree Planks=Palmenbretter
|
||||||
|
Palm Tree Planks Slab=
|
||||||
|
Palm Tree Planks Stair=
|
||||||
|
Palm Tree Sapling=Palmensetzling
|
||||||
|
Palm Tree Trunk=Palmenstamm
|
||||||
|
Palm Tree Trunk Slab=
|
||||||
|
Palm Tree Trunk Stair=
|
||||||
|
Poplar Tree=
|
||||||
|
Poplar Tree Fence=
|
||||||
|
Poplar Tree Fence Gate=
|
||||||
|
Poplar Tree Fence Rail=
|
||||||
|
Poplar Tree Leaves=
|
||||||
|
Poplar Tree Planks=
|
||||||
|
Poplar Tree Planks Slab=
|
||||||
|
Poplar Tree Planks Stair=
|
||||||
|
Poplar Tree Sapling=
|
||||||
|
Poplar Tree Trunk=
|
||||||
|
Poplar Tree Trunk Slab=
|
||||||
|
Poplar Tree Trunk Stair=
|
||||||
|
Red=rot
|
||||||
|
Rubber Tree=
|
||||||
|
Rubber Tree Fence=
|
||||||
|
Rubber Tree Fence Gate=
|
||||||
|
Rubber Tree Fence Rail=
|
||||||
|
Rubber Tree Leaves=Gummibaumlaub
|
||||||
|
Rubber Tree Planks=Gummibaumbretter
|
||||||
|
Rubber Tree Planks Slab=
|
||||||
|
Rubber Tree Planks Stair=
|
||||||
|
Rubber Tree Sapling=Gummibaumsetzling
|
||||||
|
Rubber Tree Trunk=Gummibaumstamm
|
||||||
|
Rubber Tree Trunk (Empty)=Gummibaumstamm (leer)
|
||||||
|
Rubber Tree Trunk Slab=
|
||||||
|
Rubber Tree Trunk Stair=
|
||||||
|
Small poplar Tree Sapling=
|
||||||
|
Spruce Cone=Fichtenzapfen
|
||||||
|
Spruce Tree=
|
||||||
|
Spruce Tree Fence=
|
||||||
|
Spruce Tree Fence Gate=
|
||||||
|
Spruce Tree Fence Rail=
|
||||||
|
Spruce Tree Leaves=Fichtennadeln
|
||||||
|
Spruce Tree Planks=Fichtenbretter
|
||||||
|
Spruce Tree Planks Slab=
|
||||||
|
Spruce Tree Planks Stair=
|
||||||
|
Spruce Tree Sapling=Fichtensetzling
|
||||||
|
Spruce Tree Trunk=Fichtenstamm
|
||||||
|
Spruce Tree Trunk Slab=
|
||||||
|
Spruce Tree Trunk Stair=
|
||||||
|
Willow Tree=
|
||||||
|
Willow Tree Fence=
|
||||||
|
Willow Tree Fence Gate=
|
||||||
|
Willow Tree Fence Rail=
|
||||||
|
Willow Tree Leaves=Weidenlaub
|
||||||
|
Willow Tree Planks=Weidenbretter
|
||||||
|
Willow Tree Planks Slab=
|
||||||
|
Willow Tree Planks Stair=
|
||||||
|
Willow Tree Sapling=Weidensetzling
|
||||||
|
Willow Tree Trunk=Weidenstamm
|
||||||
|
Willow Tree Trunk Slab=
|
||||||
|
Willow Tree Trunk Stair=
|
||||||
|
Yellow=gelb
|
211
mods/moretrees/locale/moretrees.es.tr
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
# textdomain: moretrees
|
||||||
|
# Translation by Carlos Barraza
|
||||||
|
|
||||||
|
|
||||||
|
### cocos_palm.lua ###
|
||||||
|
|
||||||
|
Coconut=Coco
|
||||||
|
Coconut Flower=
|
||||||
|
|
||||||
|
### crafts.lua ###
|
||||||
|
|
||||||
|
Acorn Muffin=Mollete de Bellota
|
||||||
|
Acorn Muffin batter= Masa de Mollete de Bellota
|
||||||
|
Coconut Milk=Leche de Coco
|
||||||
|
Date=Datilera
|
||||||
|
Date & nut snack=Datilera y Nueces
|
||||||
|
Date-nut cake=Pastel de Datilera
|
||||||
|
Date-nut cake batter=Pasta de torta de Datilera
|
||||||
|
Date-nut energy bar=Barra energetica de Datilera
|
||||||
|
Raw Coconut=Coco crudo
|
||||||
|
Roasted Cedar Cone Nuts=Coco de Alamo Tostado
|
||||||
|
Roasted Fir Cone Nuts=Cono de Abeto Tostado
|
||||||
|
Roasted Spruce Cone Nuts=Cono de Picea Tostado
|
||||||
|
|
||||||
|
### date_palm.lua ###
|
||||||
|
|
||||||
|
Date Flowers=Flores de Datilera
|
||||||
|
Date Stem=Tallo de Datilera
|
||||||
|
Dates=Datilera
|
||||||
|
|
||||||
|
### node_defs.lua ###
|
||||||
|
|
||||||
|
@1 (fast growth)=
|
||||||
|
Acorn=Bellota
|
||||||
|
Apple Tree=
|
||||||
|
Apple Tree Fence=
|
||||||
|
Apple Tree Fence Gate=
|
||||||
|
Apple Tree Fence Rail=
|
||||||
|
Apple Tree Leaves=Hojas de Arbol de Manzana
|
||||||
|
Apple Tree Planks=Madera de Arbol de Manzana
|
||||||
|
Apple Tree Planks Slab=
|
||||||
|
Apple Tree Planks Stair=
|
||||||
|
Apple Tree Sapling=Retoño de Arbol de Manzana
|
||||||
|
Apple Tree Trunk=Tronco de Arbol de Manzana
|
||||||
|
Apple Tree Trunk Slab=
|
||||||
|
Apple Tree Trunk Stair=
|
||||||
|
Beech Tree=
|
||||||
|
Beech Tree Fence=
|
||||||
|
Beech Tree Fence Gate=
|
||||||
|
Beech Tree Fence Rail=
|
||||||
|
Beech Tree Leaves=Hojas de Arbol de Haya
|
||||||
|
Beech Tree Planks=Madera de Arbol de Haya
|
||||||
|
Beech Tree Planks Slab=
|
||||||
|
Beech Tree Planks Stair=
|
||||||
|
Beech Tree Sapling=Retoño de Arbol de Haya
|
||||||
|
Beech Tree Trunk=Tronco de Arbol de Haya
|
||||||
|
Beech Tree Trunk Slab=
|
||||||
|
Beech Tree Trunk Stair=
|
||||||
|
Birch Tree=
|
||||||
|
Birch Tree Fence=
|
||||||
|
Birch Tree Fence Gate=
|
||||||
|
Birch Tree Fence Rail=
|
||||||
|
Birch Tree Leaves=Hojas de Arbol de Abedul
|
||||||
|
Birch Tree Planks=Madera de Arbol de Abedul
|
||||||
|
Birch Tree Planks Slab=
|
||||||
|
Birch Tree Planks Stair=
|
||||||
|
Birch Tree Sapling=Retoño de Arbol de Abedul
|
||||||
|
Birch Tree Trunk=Tronco de Arbol de Abedul
|
||||||
|
Birch Tree Trunk Slab=
|
||||||
|
Birch Tree Trunk Stair=
|
||||||
|
Cedar Cone=Coco de Alamo
|
||||||
|
Cedar Tree=
|
||||||
|
Cedar Tree Fence=
|
||||||
|
Cedar Tree Fence Gate=
|
||||||
|
Cedar Tree Fence Rail=
|
||||||
|
Cedar Tree Leaves=Hojas de Arbol de Cedro
|
||||||
|
Cedar Tree Planks=Madera de Arbol de Cedro
|
||||||
|
Cedar Tree Planks Slab=
|
||||||
|
Cedar Tree Planks Stair=
|
||||||
|
Cedar Tree Sapling=Retoño de Arbol de Cedro
|
||||||
|
Cedar Tree Trunk=Tronco de Arbol de Cedro
|
||||||
|
Cedar Tree Trunk Slab=
|
||||||
|
Cedar Tree Trunk Stair=
|
||||||
|
Date Palm Tree=
|
||||||
|
Date Palm Tree Fence=
|
||||||
|
Date Palm Tree Fence Gate=
|
||||||
|
Date Palm Tree Fence Rail=
|
||||||
|
Date Palm Tree Leaves=
|
||||||
|
Date Palm Tree Planks=Madera de Palmera Datilera
|
||||||
|
Date Palm Tree Planks Slab=
|
||||||
|
Date Palm Tree Planks Stair=
|
||||||
|
Date Palm Tree Sapling=
|
||||||
|
Date Palm Tree Trunk=Tronco de Palmera Datilera
|
||||||
|
Date Palm Tree Trunk Slab=
|
||||||
|
Date Palm Tree Trunk Stair=
|
||||||
|
Douglas Fir=
|
||||||
|
Douglas Fir Fence=
|
||||||
|
Douglas Fir Fence Gate=
|
||||||
|
Douglas Fir Fence Rail=
|
||||||
|
Douglas Fir Leaves=Hojas de Arbol de Abeto de Douglas
|
||||||
|
Douglas Fir Leaves (Bright)=Hojas de Arbol de Abeto de Douglas (Brillante)
|
||||||
|
Douglas Fir Planks=Madera de Arbol de Abeto de Douglas
|
||||||
|
Douglas Fir Planks Slab=
|
||||||
|
Douglas Fir Planks Stair=
|
||||||
|
Douglas Fir Sapling=Retoño de Arbol de Abeto de Douglas
|
||||||
|
Douglas Fir Trunk=Tronco de Arbol de Abeto de Douglas
|
||||||
|
Douglas Fir Trunk Slab=
|
||||||
|
Douglas Fir Trunk Stair=
|
||||||
|
Fir Cone=Coco de Abeto
|
||||||
|
Giant Sequoia=
|
||||||
|
Giant Sequoia Fence=
|
||||||
|
Giant Sequoia Fence Gate=
|
||||||
|
Giant Sequoia Fence Rail=
|
||||||
|
Giant Sequoia Leaves=Hojas de Sequoia Gigante
|
||||||
|
Giant Sequoia Planks=Madera de Sequoia Gigante
|
||||||
|
Giant Sequoia Planks Slab=
|
||||||
|
Giant Sequoia Planks Stair=
|
||||||
|
Giant Sequoia Sapling=Retoño de Arbol de Sequoia Gigante
|
||||||
|
Giant Sequoia Trunk=Tronco de Sequoia Gigante
|
||||||
|
Giant Sequoia Trunk Slab=
|
||||||
|
Giant Sequoia Trunk Stair=
|
||||||
|
Jungle Tree=Tronco de Arbol de Arbol de la Selva
|
||||||
|
Jungle Tree Fence=
|
||||||
|
Jungle Tree Fence Gate=
|
||||||
|
Jungle Tree Fence Rail=
|
||||||
|
Jungle Tree Leaves=Hojas de Arbol de la Selva
|
||||||
|
Jungle Tree Leaves (@1)=Hojas de Arbol de la Selva (@1)
|
||||||
|
Jungle Tree Planks=
|
||||||
|
Jungle Tree Planks Slab=
|
||||||
|
Jungle Tree Planks Stair=
|
||||||
|
Jungle Tree Sapling=
|
||||||
|
Jungle Tree Trunk=
|
||||||
|
Jungle Tree Trunk Slab=
|
||||||
|
Jungle Tree Trunk Stair=
|
||||||
|
Oak Tree=
|
||||||
|
Oak Tree Fence=
|
||||||
|
Oak Tree Fence Gate=
|
||||||
|
Oak Tree Fence Rail=
|
||||||
|
Oak Tree Leaves=Hojas de Arbol de Roble
|
||||||
|
Oak Tree Planks=Madera de Arbol de Roble
|
||||||
|
Oak Tree Planks Slab=
|
||||||
|
Oak Tree Planks Stair=
|
||||||
|
Oak Tree Sapling=Retoño de Arbol de Roble
|
||||||
|
Oak Tree Trunk=Tronco de Arbol de Roble
|
||||||
|
Oak Tree Trunk Slab=
|
||||||
|
Oak Tree Trunk Stair=
|
||||||
|
Palm Tree=
|
||||||
|
Palm Tree Fence=
|
||||||
|
Palm Tree Fence Gate=
|
||||||
|
Palm Tree Fence Rail=
|
||||||
|
Palm Tree Leaves=Hojas de Palmera
|
||||||
|
Palm Tree Planks=Madera de Palmera
|
||||||
|
Palm Tree Planks Slab=
|
||||||
|
Palm Tree Planks Stair=
|
||||||
|
Palm Tree Sapling=Retoño de Palmera
|
||||||
|
Palm Tree Trunk=Tronco de Palmera
|
||||||
|
Palm Tree Trunk Slab=
|
||||||
|
Palm Tree Trunk Stair=
|
||||||
|
Poplar Tree=
|
||||||
|
Poplar Tree Fence=
|
||||||
|
Poplar Tree Fence Gate=
|
||||||
|
Poplar Tree Fence Rail=
|
||||||
|
Poplar Tree Leaves=Hojas de Arbol de Alamo
|
||||||
|
Poplar Tree Planks=Madera de Arbol de Alamo
|
||||||
|
Poplar Tree Planks Slab=
|
||||||
|
Poplar Tree Planks Stair=
|
||||||
|
Poplar Tree Sapling=Retoño de Arbol de Alamo
|
||||||
|
Poplar Tree Trunk=Tronco de Arbol de Alamo
|
||||||
|
Poplar Tree Trunk Slab=
|
||||||
|
Poplar Tree Trunk Stair=
|
||||||
|
Red=Roja
|
||||||
|
Rubber Tree=
|
||||||
|
Rubber Tree Fence=
|
||||||
|
Rubber Tree Fence Gate=
|
||||||
|
Rubber Tree Fence Rail=
|
||||||
|
Rubber Tree Leaves=Hojas de Arbol de Arbol de Goma
|
||||||
|
Rubber Tree Planks=Madera de Arbol de Arbol de Goma
|
||||||
|
Rubber Tree Planks Slab=
|
||||||
|
Rubber Tree Planks Stair=
|
||||||
|
Rubber Tree Sapling=Retoño de Arbol de Arbol de Goma
|
||||||
|
Rubber Tree Trunk=Tronco de Arbol de Arbol de Goma
|
||||||
|
Rubber Tree Trunk (Empty)=Tronco de Arbol de Goma (Vacio)
|
||||||
|
Rubber Tree Trunk Slab=
|
||||||
|
Rubber Tree Trunk Stair=
|
||||||
|
Small poplar Tree Sapling=
|
||||||
|
Spruce Cone=Coco de Picea
|
||||||
|
Spruce Tree=
|
||||||
|
Spruce Tree Fence=
|
||||||
|
Spruce Tree Fence Gate=
|
||||||
|
Spruce Tree Fence Rail=
|
||||||
|
Spruce Tree Leaves=Hojas de Arbol de Abeto
|
||||||
|
Spruce Tree Planks=Madera de Arbol de Abeto
|
||||||
|
Spruce Tree Planks Slab=
|
||||||
|
Spruce Tree Planks Stair=
|
||||||
|
Spruce Tree Sapling=Retoño de Arbol de Abeto
|
||||||
|
Spruce Tree Trunk=Tronco de Arbol de Abeto
|
||||||
|
Spruce Tree Trunk Slab=
|
||||||
|
Spruce Tree Trunk Stair=
|
||||||
|
Willow Tree=
|
||||||
|
Willow Tree Fence=
|
||||||
|
Willow Tree Fence Gate=
|
||||||
|
Willow Tree Fence Rail=
|
||||||
|
Willow Tree Leaves=Hojas de Arbol de Sauce
|
||||||
|
Willow Tree Planks=Madera de Arbol de Sauce
|
||||||
|
Willow Tree Planks Slab=
|
||||||
|
Willow Tree Planks Stair=
|
||||||
|
Willow Tree Sapling=Retoño de Arbol de Sauce
|
||||||
|
Willow Tree Trunk=Tronco de Arbol de Sauce
|
||||||
|
Willow Tree Trunk Slab=
|
||||||
|
Willow Tree Trunk Stair=
|
||||||
|
Yellow=Amarilla
|
211
mods/moretrees/locale/moretrees.fr.tr
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
# textdomain: moretrees
|
||||||
|
# Translation by Yoan31 and Louis Royer
|
||||||
|
|
||||||
|
|
||||||
|
### cocos_palm.lua ###
|
||||||
|
|
||||||
|
Coconut=Noix de coco
|
||||||
|
Coconut Flower=Fleur de coco
|
||||||
|
|
||||||
|
### crafts.lua ###
|
||||||
|
|
||||||
|
Acorn Muffin=Muffins au gland
|
||||||
|
Acorn Muffin batter=Pate à muffins au Gland
|
||||||
|
Coconut Milk=Lait de coco
|
||||||
|
Date=Datte
|
||||||
|
Date & nut snack=Collation aux dattes et aux noix
|
||||||
|
Date-nut cake=Gâteau datte-noix
|
||||||
|
Date-nut cake batter=Pâte à gâteau datte-noix
|
||||||
|
Date-nut energy bar=Barre énergétique datte-noix
|
||||||
|
Raw Coconut=Noix de coco crue
|
||||||
|
Roasted Cedar Cone Nuts=Noix de pomme de pin roties
|
||||||
|
Roasted Fir Cone Nuts=Noix de cône de sapin roties
|
||||||
|
Roasted Spruce Cone Nuts=Noix de cône de sapin roties
|
||||||
|
|
||||||
|
### date_palm.lua ###
|
||||||
|
|
||||||
|
Date Flowers=Fleurs de datte
|
||||||
|
Date Stem=Tige de datte
|
||||||
|
Dates=Dattes
|
||||||
|
|
||||||
|
### node_defs.lua ###
|
||||||
|
|
||||||
|
@1 (fast growth)=@1 (croissance rapide)
|
||||||
|
Acorn=Gland
|
||||||
|
Apple Tree=Pommier
|
||||||
|
Apple Tree Fence=Barrière en bois de pommier
|
||||||
|
Apple Tree Fence Gate=Porte de clôture en bois de pommier
|
||||||
|
Apple Tree Fence Rail=Clôture en bois de pommier
|
||||||
|
Apple Tree Leaves=Feuilles de pommier
|
||||||
|
Apple Tree Planks=Planches de pommier
|
||||||
|
Apple Tree Planks Slab=Dalle en bois de pommier
|
||||||
|
Apple Tree Planks Stair=Escaliers en bois de pommier
|
||||||
|
Apple Tree Sapling=Pousse d'arbre de pommier
|
||||||
|
Apple Tree Trunk=Tronc d'arbre de pommier
|
||||||
|
Apple Tree Trunk Slab=Dalle en tronc de pommier
|
||||||
|
Apple Tree Trunk Stair=Escalier en tronc de pommier
|
||||||
|
Beech Tree=Hêtre
|
||||||
|
Beech Tree Fence=Barrière en bois de hêtre
|
||||||
|
Beech Tree Fence Gate=Porte de clôture en bois de hêtre
|
||||||
|
Beech Tree Fence Rail=Clôture en bois de hêtre
|
||||||
|
Beech Tree Leaves=Feuilles de hêtre
|
||||||
|
Beech Tree Planks=Planches de hêtre
|
||||||
|
Beech Tree Planks Slab=Dalle en bois de hêtre
|
||||||
|
Beech Tree Planks Stair=Escalier en bois de hêtre
|
||||||
|
Beech Tree Sapling=Pousse d'arbre de hêtre
|
||||||
|
Beech Tree Trunk=Tronc d'arbre de hêtre
|
||||||
|
Beech Tree Trunk Slab=Dalle en tronc de hêtre
|
||||||
|
Beech Tree Trunk Stair=Escalier en tronc de hêtre
|
||||||
|
Birch Tree=Bouleau
|
||||||
|
Birch Tree Fence=Barrière en bois de bouleau
|
||||||
|
Birch Tree Fence Gate=Porte de clôture en bois de bouleau
|
||||||
|
Birch Tree Fence Rail=Clôture en bois de bouleau
|
||||||
|
Birch Tree Leaves=Feuilles de bouleau
|
||||||
|
Birch Tree Planks=Planches d'arbre de bouleau
|
||||||
|
Birch Tree Planks Slab=Dalle en bois de bouleau
|
||||||
|
Birch Tree Planks Stair=Escalier en bois de bouleau
|
||||||
|
Birch Tree Sapling=Pousse d'arbre de bouleau
|
||||||
|
Birch Tree Trunk=Tronc d'arbre de bouleau
|
||||||
|
Birch Tree Trunk Slab=Dalle en tronc de bouleau
|
||||||
|
Birch Tree Trunk Stair=Escalier en tronc de bouleau
|
||||||
|
Cedar Cone=Pomme de pin
|
||||||
|
Cedar Tree=Pin
|
||||||
|
Cedar Tree Fence=Barrière en bois de pin
|
||||||
|
Cedar Tree Fence Gate=Porte de clôture en bois de pin
|
||||||
|
Cedar Tree Fence Rail=Clôture en bois de pin
|
||||||
|
Cedar Tree Leaves=Feuilles de pin
|
||||||
|
Cedar Tree Planks=Planches d'arbre de pin
|
||||||
|
Cedar Tree Planks Slab=Dalle en bois de pin
|
||||||
|
Cedar Tree Planks Stair=Escalier en bois de pin
|
||||||
|
Cedar Tree Sapling=Pousse d'arbre de pin
|
||||||
|
Cedar Tree Trunk=Tronc d'arbre de pin
|
||||||
|
Cedar Tree Trunk Slab=Dalle en tronc de pin
|
||||||
|
Cedar Tree Trunk Stair=Escalier en tronc de pin
|
||||||
|
Date Palm Tree=Dattier
|
||||||
|
Date Palm Tree Fence=Barrière en bois de dattier
|
||||||
|
Date Palm Tree Fence Gate=Porte de clôture en bois de dattier
|
||||||
|
Date Palm Tree Fence Rail=Clôture en bois de dattier
|
||||||
|
Date Palm Tree Leaves=Feuille de dattier
|
||||||
|
Date Palm Tree Planks=Planches de dattier
|
||||||
|
Date Palm Tree Planks Slab=Dalle en bois de dattier
|
||||||
|
Date Palm Tree Planks Stair=Escalier en bois de dattier
|
||||||
|
Date Palm Tree Sapling=Pousse de dattier
|
||||||
|
Date Palm Tree Trunk=Tronc de dattier
|
||||||
|
Date Palm Tree Trunk Slab=Dalle en tronc de dattier
|
||||||
|
Date Palm Tree Trunk Stair=Escalier en tronc de dattier
|
||||||
|
Douglas Fir=Sapin de Douglas
|
||||||
|
Douglas Fir Fence=Barrière en bois de sapin de Douglas
|
||||||
|
Douglas Fir Fence Gate=Porte de clôture en bois de sapin de Douglas
|
||||||
|
Douglas Fir Fence Rail=Clôture en bois de sapin de Douglas
|
||||||
|
Douglas Fir Leaves=Feuilles de sapin de Douglas
|
||||||
|
Douglas Fir Leaves (Bright)=Feuille de sapin de Douglas (brillant)
|
||||||
|
Douglas Fir Planks=Planches de sapin de Douglas
|
||||||
|
Douglas Fir Planks Slab=Dalle en bois de sapin de Douglas
|
||||||
|
Douglas Fir Planks Stair=Escalier en bois de sapin de Douglas
|
||||||
|
Douglas Fir Sapling=Pousse de sapin de Douglas
|
||||||
|
Douglas Fir Trunk=Tronc de sapin de Douglas
|
||||||
|
Douglas Fir Trunk Slab=Dalle en tronc de sapin de Douglas
|
||||||
|
Douglas Fir Trunk Stair=Escalier en tronc de sapin de Douglas
|
||||||
|
Fir Cone=Pomme de sapin
|
||||||
|
Giant Sequoia=Séquoia géant
|
||||||
|
Giant Sequoia Fence=Barrière en bois de séquoia géant
|
||||||
|
Giant Sequoia Fence Gate=Porte de clôture en bois de séquoia géant
|
||||||
|
Giant Sequoia Fence Rail=Clôture en bois de séquoia géant
|
||||||
|
Giant Sequoia Leaves=Feuilles de séquoia géant
|
||||||
|
Giant Sequoia Planks=Planches de séquoia géant
|
||||||
|
Giant Sequoia Planks Slab=Dalle en bois de séquoia géant
|
||||||
|
Giant Sequoia Planks Stair=Escalier en bois de séquoia géant
|
||||||
|
Giant Sequoia Sapling=Pousse de séquoia géant
|
||||||
|
Giant Sequoia Trunk=Tronc de séquoia géant
|
||||||
|
Giant Sequoia Trunk Slab=Dalle en tronc de séquoia géant
|
||||||
|
Giant Sequoia Trunk Stair=Escalier en tronc de séquoia géant
|
||||||
|
Jungle Tree=Arbre de la jungle
|
||||||
|
Jungle Tree Fence=Barrière en bois d'arbre de la jungle
|
||||||
|
Jungle Tree Fence Gate=Porte de clôture en bois d'arbre de la jungle
|
||||||
|
Jungle Tree Fence Rail=Clôture en bois d'arbre de la jungle
|
||||||
|
Jungle Tree Leaves=Feuilles d'arbre de la jungle
|
||||||
|
Jungle Tree Leaves (@1)=Feuilles d'arbre de la jungle (@1)
|
||||||
|
Jungle Tree Planks=Planches d'arbre de la jungle
|
||||||
|
Jungle Tree Planks Slab=Dalle en bois d'arbre de la jungle
|
||||||
|
Jungle Tree Planks Stair=Escalier en bois d'arbre de la jungle
|
||||||
|
Jungle Tree Sapling=Pousse d'arbre de la jungle
|
||||||
|
Jungle Tree Trunk=Tronc d'arbre de la jungle
|
||||||
|
Jungle Tree Trunk Slab=Dalle en tronc d'arbre de la jungle
|
||||||
|
Jungle Tree Trunk Stair=Escalier en tronc d'arbre de la jungle
|
||||||
|
Oak Tree=Chêne
|
||||||
|
Oak Tree Fence=Barrière en bois de chêne
|
||||||
|
Oak Tree Fence Gate=Porte de clôture en bois de chêne
|
||||||
|
Oak Tree Fence Rail=Clôture en bois de chêne
|
||||||
|
Oak Tree Leaves=Feuilles de chêne
|
||||||
|
Oak Tree Planks=Planches de chêne
|
||||||
|
Oak Tree Planks Slab=Dalle en bois de chêne
|
||||||
|
Oak Tree Planks Stair=Escalier en bois de chêne
|
||||||
|
Oak Tree Sapling=Pousse d'arbre de chêne
|
||||||
|
Oak Tree Trunk=Tronc d'arbre de chêne
|
||||||
|
Oak Tree Trunk Slab=Dalle en tronc de chêne
|
||||||
|
Oak Tree Trunk Stair=Escalier en tronc de chêne
|
||||||
|
Palm Tree=Palmier
|
||||||
|
Palm Tree Fence=Barrière en bois de palmier
|
||||||
|
Palm Tree Fence Gate=Porte de clôture en bois de palmier
|
||||||
|
Palm Tree Fence Rail=Clôture en bois de palmier
|
||||||
|
Palm Tree Leaves=Feuilles de palmier
|
||||||
|
Palm Tree Planks=Planches de palmier
|
||||||
|
Palm Tree Planks Slab=Dalle en bois de palmier
|
||||||
|
Palm Tree Planks Stair=Escalier en bois de palmier
|
||||||
|
Palm Tree Sapling=Pousse d'arbre de palmier
|
||||||
|
Palm Tree Trunk=Tronc d'arbre de palmier
|
||||||
|
Palm Tree Trunk Slab=Dalle en tronc de palmier
|
||||||
|
Palm Tree Trunk Stair=Escalier en tronc de palmier
|
||||||
|
Poplar Tree=Peuplier
|
||||||
|
Poplar Tree Fence=Barrière en bois de peuplier
|
||||||
|
Poplar Tree Fence Gate=Porte de clôture en bois de peuplier
|
||||||
|
Poplar Tree Fence Rail=Clôture en bois de peuplier
|
||||||
|
Poplar Tree Leaves=Feuilles de peuplier
|
||||||
|
Poplar Tree Planks=Plances de peuplier
|
||||||
|
Poplar Tree Planks Slab=Dalle en bois de peuplier
|
||||||
|
Poplar Tree Planks Stair=Escalier en bois de peuplier
|
||||||
|
Poplar Tree Sapling=Pousse de peuplier
|
||||||
|
Poplar Tree Trunk=Tronc de peuplier
|
||||||
|
Poplar Tree Trunk Slab=Dalle en tronc de peuplier
|
||||||
|
Poplar Tree Trunk Stair=Escalier en tronc de peuplier
|
||||||
|
Red=rouge
|
||||||
|
Rubber Tree=Arbre à caoutchouc
|
||||||
|
Rubber Tree Fence=Barrière en bois d'arbre à caoutchouc
|
||||||
|
Rubber Tree Fence Gate=Porte de clôture en bois d'arbre à caoutchouc
|
||||||
|
Rubber Tree Fence Rail=Clôture en bois d'arbre à caoutchouc
|
||||||
|
Rubber Tree Leaves=Feuilles d'arbre à caoutchouc
|
||||||
|
Rubber Tree Planks=Planches d'arbre à caoutchouc
|
||||||
|
Rubber Tree Planks Slab=Dalle en bois d'arbre à caoutchouc
|
||||||
|
Rubber Tree Planks Stair=Escalier en bois d'arbre à caoutchouc
|
||||||
|
Rubber Tree Sapling=Pousse d'arbre à caoutchouc
|
||||||
|
Rubber Tree Trunk=Tronc d'arbre a caoutchouc
|
||||||
|
Rubber Tree Trunk (Empty)=Tronc d'arbre à caoutchouc (vide)
|
||||||
|
Rubber Tree Trunk Slab=Dalle en tronc d'arbre à caoutchouc
|
||||||
|
Rubber Tree Trunk Stair=Escalier en tronc d'arbre à caoutchouc
|
||||||
|
Small poplar Tree Sapling=Pousse de petit peuplier
|
||||||
|
Spruce Cone=Cône de sapin
|
||||||
|
Spruce Tree=Épicéa
|
||||||
|
Spruce Tree Fence=Barrière en bois d'épicéa
|
||||||
|
Spruce Tree Fence Gate=Porte de clôture en bois d'épicéa
|
||||||
|
Spruce Tree Fence Rail=Clôture en bois d'épicéa
|
||||||
|
Spruce Tree Leaves=Feuilles d'épicéa
|
||||||
|
Spruce Tree Planks=Planches d'arbre d'épicéa
|
||||||
|
Spruce Tree Planks Slab=Dalle en bois d'épicéa
|
||||||
|
Spruce Tree Planks Stair=Escalier en bois d'épicéa
|
||||||
|
Spruce Tree Sapling=Pousse d'arbre d'épicéa
|
||||||
|
Spruce Tree Trunk=Tronc d'arbre d'épicéa
|
||||||
|
Spruce Tree Trunk Slab=Dalle en tronc d'épicéa
|
||||||
|
Spruce Tree Trunk Stair=Escalier en tronc d'épicéa
|
||||||
|
Willow Tree=Saule
|
||||||
|
Willow Tree Fence=Barrière en bois de saule
|
||||||
|
Willow Tree Fence Gate=Porte de clôture en bois de saule
|
||||||
|
Willow Tree Fence Rail=Clôture en bois de saule
|
||||||
|
Willow Tree Leaves=Feuilles de saule
|
||||||
|
Willow Tree Planks=Planches de saule
|
||||||
|
Willow Tree Planks Slab=Dalle en bois de saule
|
||||||
|
Willow Tree Planks Stair=Escalier en bois de saule
|
||||||
|
Willow Tree Sapling=Pousse de saule
|
||||||
|
Willow Tree Trunk=Tronc d'arbre de saule
|
||||||
|
Willow Tree Trunk Slab=Dalle en tronc de saule
|
||||||
|
Willow Tree Trunk Stair=Escalier en tronc de saule
|
||||||
|
Yellow=jaune
|
210
mods/moretrees/locale/template.txt
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
# textdomain: moretrees
|
||||||
|
|
||||||
|
|
||||||
|
### cocos_palm.lua ###
|
||||||
|
|
||||||
|
Coconut=
|
||||||
|
Coconut Flower=
|
||||||
|
|
||||||
|
### crafts.lua ###
|
||||||
|
|
||||||
|
Acorn Muffin=
|
||||||
|
Acorn Muffin batter=
|
||||||
|
Coconut Milk=
|
||||||
|
Date=
|
||||||
|
Date & nut snack=
|
||||||
|
Date-nut cake=
|
||||||
|
Date-nut cake batter=
|
||||||
|
Date-nut energy bar=
|
||||||
|
Raw Coconut=
|
||||||
|
Roasted Cedar Cone Nuts=
|
||||||
|
Roasted Fir Cone Nuts=
|
||||||
|
Roasted Spruce Cone Nuts=
|
||||||
|
|
||||||
|
### date_palm.lua ###
|
||||||
|
|
||||||
|
Date Flowers=
|
||||||
|
Date Stem=
|
||||||
|
Dates=
|
||||||
|
|
||||||
|
### node_defs.lua ###
|
||||||
|
|
||||||
|
@1 (fast growth)=
|
||||||
|
Acorn=
|
||||||
|
Apple Tree=
|
||||||
|
Apple Tree Fence=
|
||||||
|
Apple Tree Fence Gate=
|
||||||
|
Apple Tree Fence Rail=
|
||||||
|
Apple Tree Leaves=
|
||||||
|
Apple Tree Planks=
|
||||||
|
Apple Tree Planks Slab=
|
||||||
|
Apple Tree Planks Stair=
|
||||||
|
Apple Tree Sapling=
|
||||||
|
Apple Tree Trunk=
|
||||||
|
Apple Tree Trunk Slab=
|
||||||
|
Apple Tree Trunk Stair=
|
||||||
|
Beech Tree=
|
||||||
|
Beech Tree Fence=
|
||||||
|
Beech Tree Fence Gate=
|
||||||
|
Beech Tree Fence Rail=
|
||||||
|
Beech Tree Leaves=
|
||||||
|
Beech Tree Planks=
|
||||||
|
Beech Tree Planks Slab=
|
||||||
|
Beech Tree Planks Stair=
|
||||||
|
Beech Tree Sapling=
|
||||||
|
Beech Tree Trunk=
|
||||||
|
Beech Tree Trunk Slab=
|
||||||
|
Beech Tree Trunk Stair=
|
||||||
|
Birch Tree=
|
||||||
|
Birch Tree Fence=
|
||||||
|
Birch Tree Fence Gate=
|
||||||
|
Birch Tree Fence Rail=
|
||||||
|
Birch Tree Leaves=
|
||||||
|
Birch Tree Planks=
|
||||||
|
Birch Tree Planks Slab=
|
||||||
|
Birch Tree Planks Stair=
|
||||||
|
Birch Tree Sapling=
|
||||||
|
Birch Tree Trunk=
|
||||||
|
Birch Tree Trunk Slab=
|
||||||
|
Birch Tree Trunk Stair=
|
||||||
|
Cedar Cone=
|
||||||
|
Cedar Tree=
|
||||||
|
Cedar Tree Fence=
|
||||||
|
Cedar Tree Fence Gate=
|
||||||
|
Cedar Tree Fence Rail=
|
||||||
|
Cedar Tree Leaves=
|
||||||
|
Cedar Tree Planks=
|
||||||
|
Cedar Tree Planks Slab=
|
||||||
|
Cedar Tree Planks Stair=
|
||||||
|
Cedar Tree Sapling=
|
||||||
|
Cedar Tree Trunk=
|
||||||
|
Cedar Tree Trunk Slab=
|
||||||
|
Cedar Tree Trunk Stair=
|
||||||
|
Date Palm Tree=
|
||||||
|
Date Palm Tree Fence=
|
||||||
|
Date Palm Tree Fence Gate=
|
||||||
|
Date Palm Tree Fence Rail=
|
||||||
|
Date Palm Tree Leaves=
|
||||||
|
Date Palm Tree Planks=
|
||||||
|
Date Palm Tree Planks Slab=
|
||||||
|
Date Palm Tree Planks Stair=
|
||||||
|
Date Palm Tree Sapling=
|
||||||
|
Date Palm Tree Trunk=
|
||||||
|
Date Palm Tree Trunk Slab=
|
||||||
|
Date Palm Tree Trunk Stair=
|
||||||
|
Douglas Fir=
|
||||||
|
Douglas Fir Fence=
|
||||||
|
Douglas Fir Fence Gate=
|
||||||
|
Douglas Fir Fence Rail=
|
||||||
|
Douglas Fir Leaves=
|
||||||
|
Douglas Fir Leaves (Bright)=
|
||||||
|
Douglas Fir Planks=
|
||||||
|
Douglas Fir Planks Slab=
|
||||||
|
Douglas Fir Planks Stair=
|
||||||
|
Douglas Fir Sapling=
|
||||||
|
Douglas Fir Trunk=
|
||||||
|
Douglas Fir Trunk Slab=
|
||||||
|
Douglas Fir Trunk Stair=
|
||||||
|
Fir Cone=
|
||||||
|
Giant Sequoia=
|
||||||
|
Giant Sequoia Fence=
|
||||||
|
Giant Sequoia Fence Gate=
|
||||||
|
Giant Sequoia Fence Rail=
|
||||||
|
Giant Sequoia Leaves=
|
||||||
|
Giant Sequoia Planks=
|
||||||
|
Giant Sequoia Planks Slab=
|
||||||
|
Giant Sequoia Planks Stair=
|
||||||
|
Giant Sequoia Sapling=
|
||||||
|
Giant Sequoia Trunk=
|
||||||
|
Giant Sequoia Trunk Slab=
|
||||||
|
Giant Sequoia Trunk Stair=
|
||||||
|
Jungle Tree=
|
||||||
|
Jungle Tree Fence=
|
||||||
|
Jungle Tree Fence Gate=
|
||||||
|
Jungle Tree Fence Rail=
|
||||||
|
Jungle Tree Leaves=
|
||||||
|
Jungle Tree Leaves (@1)=
|
||||||
|
Jungle Tree Planks=
|
||||||
|
Jungle Tree Planks Slab=
|
||||||
|
Jungle Tree Planks Stair=
|
||||||
|
Jungle Tree Sapling=
|
||||||
|
Jungle Tree Trunk=
|
||||||
|
Jungle Tree Trunk Slab=
|
||||||
|
Jungle Tree Trunk Stair=
|
||||||
|
Oak Tree=
|
||||||
|
Oak Tree Fence=
|
||||||
|
Oak Tree Fence Gate=
|
||||||
|
Oak Tree Fence Rail=
|
||||||
|
Oak Tree Leaves=
|
||||||
|
Oak Tree Planks=
|
||||||
|
Oak Tree Planks Slab=
|
||||||
|
Oak Tree Planks Stair=
|
||||||
|
Oak Tree Sapling=
|
||||||
|
Oak Tree Trunk=
|
||||||
|
Oak Tree Trunk Slab=
|
||||||
|
Oak Tree Trunk Stair=
|
||||||
|
Palm Tree=
|
||||||
|
Palm Tree Fence=
|
||||||
|
Palm Tree Fence Gate=
|
||||||
|
Palm Tree Fence Rail=
|
||||||
|
Palm Tree Leaves=
|
||||||
|
Palm Tree Planks=
|
||||||
|
Palm Tree Planks Slab=
|
||||||
|
Palm Tree Planks Stair=
|
||||||
|
Palm Tree Sapling=
|
||||||
|
Palm Tree Trunk=
|
||||||
|
Palm Tree Trunk Slab=
|
||||||
|
Palm Tree Trunk Stair=
|
||||||
|
Poplar Tree=
|
||||||
|
Poplar Tree Fence=
|
||||||
|
Poplar Tree Fence Gate=
|
||||||
|
Poplar Tree Fence Rail=
|
||||||
|
Poplar Tree Leaves=
|
||||||
|
Poplar Tree Planks=
|
||||||
|
Poplar Tree Planks Slab=
|
||||||
|
Poplar Tree Planks Stair=
|
||||||
|
Poplar Tree Sapling=
|
||||||
|
Poplar Tree Trunk=
|
||||||
|
Poplar Tree Trunk Slab=
|
||||||
|
Poplar Tree Trunk Stair=
|
||||||
|
Red=
|
||||||
|
Rubber Tree=
|
||||||
|
Rubber Tree Fence=
|
||||||
|
Rubber Tree Fence Gate=
|
||||||
|
Rubber Tree Fence Rail=
|
||||||
|
Rubber Tree Leaves=
|
||||||
|
Rubber Tree Planks=
|
||||||
|
Rubber Tree Planks Slab=
|
||||||
|
Rubber Tree Planks Stair=
|
||||||
|
Rubber Tree Sapling=
|
||||||
|
Rubber Tree Trunk=
|
||||||
|
Rubber Tree Trunk (Empty)=
|
||||||
|
Rubber Tree Trunk Slab=
|
||||||
|
Rubber Tree Trunk Stair=
|
||||||
|
Small poplar Tree Sapling=
|
||||||
|
Spruce Cone=
|
||||||
|
Spruce Tree=
|
||||||
|
Spruce Tree Fence=
|
||||||
|
Spruce Tree Fence Gate=
|
||||||
|
Spruce Tree Fence Rail=
|
||||||
|
Spruce Tree Leaves=
|
||||||
|
Spruce Tree Planks=
|
||||||
|
Spruce Tree Planks Slab=
|
||||||
|
Spruce Tree Planks Stair=
|
||||||
|
Spruce Tree Sapling=
|
||||||
|
Spruce Tree Trunk=
|
||||||
|
Spruce Tree Trunk Slab=
|
||||||
|
Spruce Tree Trunk Stair=
|
||||||
|
Willow Tree=
|
||||||
|
Willow Tree Fence=
|
||||||
|
Willow Tree Fence Gate=
|
||||||
|
Willow Tree Fence Rail=
|
||||||
|
Willow Tree Leaves=
|
||||||
|
Willow Tree Planks=
|
||||||
|
Willow Tree Planks Slab=
|
||||||
|
Willow Tree Planks Stair=
|
||||||
|
Willow Tree Sapling=
|
||||||
|
Willow Tree Trunk=
|
||||||
|
Willow Tree Trunk Slab=
|
||||||
|
Willow Tree Trunk Stair=
|
||||||
|
Yellow=
|
4
mods/moretrees/mod.conf
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
name = moretrees
|
||||||
|
depends = default, biome_lib, vessels
|
||||||
|
optional_depends = doors, stairs, moreblocks, farming
|
||||||
|
min_minetest_version = 5.2.0
|
743
mods/moretrees/node_defs.lua
Normal file
|
@ -0,0 +1,743 @@
|
||||||
|
local S = minetest.get_translator("moretrees")
|
||||||
|
|
||||||
|
moretrees.avoidnodes = {}
|
||||||
|
|
||||||
|
moretrees.treelist = {
|
||||||
|
{"beech", S("Beech Tree")},
|
||||||
|
{"apple_tree", S("Apple Tree")},
|
||||||
|
{"oak", S("Oak Tree"), "acorn", S("Acorn"), {-0.2, -0.5, -0.2, 0.2, 0, 0.2}, 0.8 },
|
||||||
|
{"sequoia", S("Giant Sequoia")},
|
||||||
|
{"birch", S("Birch Tree")},
|
||||||
|
{"palm", S("Palm Tree"), "palm_fruit_trunk_gen", S("Palm Tree"), {-0.2, -0.5, -0.2, 0.2, 0, 0.2}, 1.0 },
|
||||||
|
{"date_palm", S("Date Palm Tree"), "date_palm_fruit_trunk", S("Date Palm Tree"), {0, 0, 0, 0, 0, 0}, 0.0 },
|
||||||
|
{"spruce", S("Spruce Tree"), "spruce_cone", S("Spruce Cone"), {-0.2, -0.5, -0.2, 0.2, 0, 0.2}, 0.8 },
|
||||||
|
{"cedar", S("Cedar Tree"), "cedar_cone", S("Cedar Cone"), {-0.2, -0.5, -0.2, 0.2, 0, 0.2}, 0.8 },
|
||||||
|
{"poplar", S("Poplar Tree")},
|
||||||
|
{"poplar_small", S("Poplar Tree")},
|
||||||
|
{"willow", S("Willow Tree")},
|
||||||
|
{"rubber_tree", S("Rubber Tree")},
|
||||||
|
{"fir", S("Douglas Fir"), "fir_cone", S("Fir Cone"), {-0.2, -0.5, -0.2, 0.2, 0, 0.2}, 0.8 },
|
||||||
|
{"jungletree", S("Jungle Tree"), nil, nil, nil, nil, "default_junglesapling.png" },
|
||||||
|
}
|
||||||
|
|
||||||
|
moretrees.treedesc = {
|
||||||
|
beech = {
|
||||||
|
trunk = S("Beech Tree Trunk"),
|
||||||
|
planks = S("Beech Tree Planks"),
|
||||||
|
sapling = S("Beech Tree Sapling"),
|
||||||
|
leaves = S("Beech Tree Leaves"),
|
||||||
|
trunk_stair = S("Beech Tree Trunk Stair"),
|
||||||
|
trunk_slab = S("Beech Tree Trunk Slab"),
|
||||||
|
planks_stair = S("Beech Tree Planks Stair"),
|
||||||
|
planks_slab = S("Beech Tree Planks Slab"),
|
||||||
|
fence = S("Beech Tree Fence"),
|
||||||
|
fence_rail = S("Beech Tree Fence Rail"),
|
||||||
|
fence_gate = S("Beech Tree Fence Gate"),
|
||||||
|
},
|
||||||
|
apple_tree = {
|
||||||
|
trunk = S("Apple Tree Trunk"),
|
||||||
|
planks = S("Apple Tree Planks"),
|
||||||
|
sapling = S("Apple Tree Sapling"),
|
||||||
|
leaves = S("Apple Tree Leaves"),
|
||||||
|
trunk_stair = S("Apple Tree Trunk Stair"),
|
||||||
|
trunk_slab = S("Apple Tree Trunk Slab"),
|
||||||
|
planks_stair = S("Apple Tree Planks Stair"),
|
||||||
|
planks_slab = S("Apple Tree Planks Slab"),
|
||||||
|
fence = S("Apple Tree Fence"),
|
||||||
|
fence_rail = S("Apple Tree Fence Rail"),
|
||||||
|
fence_gate = S("Apple Tree Fence Gate"),
|
||||||
|
},
|
||||||
|
oak = {
|
||||||
|
trunk = S("Oak Tree Trunk"),
|
||||||
|
planks = S("Oak Tree Planks"),
|
||||||
|
sapling = S("Oak Tree Sapling"),
|
||||||
|
leaves = S("Oak Tree Leaves"),
|
||||||
|
trunk_stair = S("Oak Tree Trunk Stair"),
|
||||||
|
trunk_slab = S("Oak Tree Trunk Slab"),
|
||||||
|
planks_stair = S("Oak Tree Planks Stair"),
|
||||||
|
planks_slab = S("Oak Tree Planks Slab"),
|
||||||
|
fence = S("Oak Tree Fence"),
|
||||||
|
fence_rail = S("Oak Tree Fence Rail"),
|
||||||
|
fence_gate = S("Oak Tree Fence Gate"),
|
||||||
|
},
|
||||||
|
sequoia = {
|
||||||
|
trunk = S("Giant Sequoia Trunk"),
|
||||||
|
planks = S("Giant Sequoia Planks"),
|
||||||
|
sapling = S("Giant Sequoia Sapling"),
|
||||||
|
leaves = S("Giant Sequoia Leaves"),
|
||||||
|
trunk_stair = S("Giant Sequoia Trunk Stair"),
|
||||||
|
trunk_slab = S("Giant Sequoia Trunk Slab"),
|
||||||
|
planks_stair = S("Giant Sequoia Planks Stair"),
|
||||||
|
planks_slab = S("Giant Sequoia Planks Slab"),
|
||||||
|
fence = S("Giant Sequoia Fence"),
|
||||||
|
fence_rail = S("Giant Sequoia Fence Rail"),
|
||||||
|
fence_gate = S("Giant Sequoia Fence Gate"),
|
||||||
|
},
|
||||||
|
birch = {
|
||||||
|
trunk = S("Birch Tree Trunk"),
|
||||||
|
planks = S("Birch Tree Planks"),
|
||||||
|
sapling = S("Birch Tree Sapling"),
|
||||||
|
leaves = S("Birch Tree Leaves"),
|
||||||
|
trunk_stair = S("Birch Tree Trunk Stair"),
|
||||||
|
trunk_slab = S("Birch Tree Trunk Slab"),
|
||||||
|
planks_stair = S("Birch Tree Planks Stair"),
|
||||||
|
planks_slab = S("Birch Tree Planks Slab"),
|
||||||
|
fence = S("Birch Tree Fence"),
|
||||||
|
fence_rail = S("Birch Tree Fence Rail"),
|
||||||
|
fence_gate = S("Birch Tree Fence Gate"),
|
||||||
|
},
|
||||||
|
palm = {
|
||||||
|
trunk = S("Palm Tree Trunk"),
|
||||||
|
planks = S("Palm Tree Planks"),
|
||||||
|
sapling = S("Palm Tree Sapling"),
|
||||||
|
leaves = S("Palm Tree Leaves"),
|
||||||
|
trunk_stair = S("Palm Tree Trunk Stair"),
|
||||||
|
trunk_slab = S("Palm Tree Trunk Slab"),
|
||||||
|
planks_stair = S("Palm Tree Planks Stair"),
|
||||||
|
planks_slab = S("Palm Tree Planks Slab"),
|
||||||
|
fence = S("Palm Tree Fence"),
|
||||||
|
fence_rail = S("Palm Tree Fence Rail"),
|
||||||
|
fence_gate = S("Palm Tree Fence Gate"),
|
||||||
|
},
|
||||||
|
date_palm = {
|
||||||
|
trunk = S("Date Palm Tree Trunk"),
|
||||||
|
planks = S("Date Palm Tree Planks"),
|
||||||
|
sapling = S("Date Palm Tree Sapling"),
|
||||||
|
leaves = S("Date Palm Tree Leaves"),
|
||||||
|
trunk_stair = S("Date Palm Tree Trunk Stair"),
|
||||||
|
trunk_slab = S("Date Palm Tree Trunk Slab"),
|
||||||
|
planks_stair = S("Date Palm Tree Planks Stair"),
|
||||||
|
planks_slab = S("Date Palm Tree Planks Slab"),
|
||||||
|
fence = S("Date Palm Tree Fence"),
|
||||||
|
fence_rail = S("Date Palm Tree Fence Rail"),
|
||||||
|
fence_gate = S("Date Palm Tree Fence Gate"),
|
||||||
|
},
|
||||||
|
spruce = {
|
||||||
|
trunk = S("Spruce Tree Trunk"),
|
||||||
|
planks = S("Spruce Tree Planks"),
|
||||||
|
sapling = S("Spruce Tree Sapling"),
|
||||||
|
leaves = S("Spruce Tree Leaves"),
|
||||||
|
trunk_stair = S("Spruce Tree Trunk Stair"),
|
||||||
|
trunk_slab = S("Spruce Tree Trunk Slab"),
|
||||||
|
planks_stair = S("Spruce Tree Planks Stair"),
|
||||||
|
planks_slab = S("Spruce Tree Planks Slab"),
|
||||||
|
fence = S("Spruce Tree Fence"),
|
||||||
|
fence_rail = S("Spruce Tree Fence Rail"),
|
||||||
|
fence_gate = S("Spruce Tree Fence Gate"),
|
||||||
|
},
|
||||||
|
cedar = {
|
||||||
|
trunk = S("Cedar Tree Trunk"),
|
||||||
|
planks = S("Cedar Tree Planks"),
|
||||||
|
sapling = S("Cedar Tree Sapling"),
|
||||||
|
leaves = S("Cedar Tree Leaves"),
|
||||||
|
trunk_stair = S("Cedar Tree Trunk Stair"),
|
||||||
|
trunk_slab = S("Cedar Tree Trunk Slab"),
|
||||||
|
planks_stair = S("Cedar Tree Planks Stair"),
|
||||||
|
planks_slab = S("Cedar Tree Planks Slab"),
|
||||||
|
fence = S("Cedar Tree Fence"),
|
||||||
|
fence_rail = S("Cedar Tree Fence Rail"),
|
||||||
|
fence_gate = S("Cedar Tree Fence Gate"),
|
||||||
|
},
|
||||||
|
poplar = {
|
||||||
|
trunk = S("Poplar Tree Trunk"),
|
||||||
|
planks = S("Poplar Tree Planks"),
|
||||||
|
sapling = S("Poplar Tree Sapling"),
|
||||||
|
leaves = S("Poplar Tree Leaves"),
|
||||||
|
trunk_stair = S("Poplar Tree Trunk Stair"),
|
||||||
|
trunk_slab = S("Poplar Tree Trunk Slab"),
|
||||||
|
planks_stair = S("Poplar Tree Planks Stair"),
|
||||||
|
planks_slab = S("Poplar Tree Planks Slab"),
|
||||||
|
fence = S("Poplar Tree Fence"),
|
||||||
|
fence_rail = S("Poplar Tree Fence Rail"),
|
||||||
|
fence_gate = S("Poplar Tree Fence Gate"),
|
||||||
|
},
|
||||||
|
poplar_small = {
|
||||||
|
sapling = S("Small poplar Tree Sapling"),
|
||||||
|
},
|
||||||
|
willow = {
|
||||||
|
trunk = S("Willow Tree Trunk"),
|
||||||
|
planks = S("Willow Tree Planks"),
|
||||||
|
sapling = S("Willow Tree Sapling"),
|
||||||
|
leaves = S("Willow Tree Leaves"),
|
||||||
|
trunk_stair = S("Willow Tree Trunk Stair"),
|
||||||
|
trunk_slab = S("Willow Tree Trunk Slab"),
|
||||||
|
planks_stair = S("Willow Tree Planks Stair"),
|
||||||
|
planks_slab = S("Willow Tree Planks Slab"),
|
||||||
|
fence = S("Willow Tree Fence"),
|
||||||
|
fence_rail = S("Willow Tree Fence Rail"),
|
||||||
|
fence_gate = S("Willow Tree Fence Gate"),
|
||||||
|
},
|
||||||
|
rubber_tree = {
|
||||||
|
trunk = S("Rubber Tree Trunk"),
|
||||||
|
planks = S("Rubber Tree Planks"),
|
||||||
|
sapling = S("Rubber Tree Sapling"),
|
||||||
|
leaves = S("Rubber Tree Leaves"),
|
||||||
|
trunk_stair = S("Rubber Tree Trunk Stair"),
|
||||||
|
trunk_slab = S("Rubber Tree Trunk Slab"),
|
||||||
|
planks_stair = S("Rubber Tree Planks Stair"),
|
||||||
|
planks_slab = S("Rubber Tree Planks Slab"),
|
||||||
|
fence = S("Rubber Tree Fence"),
|
||||||
|
fence_rail = S("Rubber Tree Fence Rail"),
|
||||||
|
fence_gate = S("Rubber Tree Fence Gate"),
|
||||||
|
},
|
||||||
|
fir = {
|
||||||
|
trunk = S("Douglas Fir Trunk"),
|
||||||
|
planks = S("Douglas Fir Planks"),
|
||||||
|
sapling = S("Douglas Fir Sapling"),
|
||||||
|
leaves = S("Douglas Fir Leaves"),
|
||||||
|
trunk_stair = S("Douglas Fir Trunk Stair"),
|
||||||
|
trunk_slab = S("Douglas Fir Trunk Slab"),
|
||||||
|
planks_stair = S("Douglas Fir Planks Stair"),
|
||||||
|
planks_slab = S("Douglas Fir Planks Slab"),
|
||||||
|
fence = S("Douglas Fir Fence"),
|
||||||
|
fence_rail = S("Douglas Fir Fence Rail"),
|
||||||
|
fence_gate = S("Douglas Fir Fence Gate"),
|
||||||
|
},
|
||||||
|
jungletree = {
|
||||||
|
trunk = S("Jungle Tree Trunk"),
|
||||||
|
planks = S("Jungle Tree Planks"),
|
||||||
|
sapling = S("Jungle Tree Sapling"),
|
||||||
|
leaves = S("Jungle Tree Leaves"),
|
||||||
|
trunk_stair = S("Jungle Tree Trunk Stair"),
|
||||||
|
trunk_slab = S("Jungle Tree Trunk Slab"),
|
||||||
|
planks_stair = S("Jungle Tree Planks Stair"),
|
||||||
|
planks_slab = S("Jungle Tree Planks Slab"),
|
||||||
|
fence = S("Jungle Tree Fence"),
|
||||||
|
fence_rail = S("Jungle Tree Fence Rail"),
|
||||||
|
fence_gate = S("Jungle Tree Fence Gate"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-- local dirs1 = { 21, 20, 23, 22, 21 }
|
||||||
|
local dirs2 = { 12, 9, 18, 7, 12 }
|
||||||
|
-- local dirs3 = { 14, 11, 16, 5, 14 }
|
||||||
|
|
||||||
|
local moretrees_new_leaves_drawtype = "allfaces_optional"
|
||||||
|
local moretrees_plantlike_leaves_visual_scale = 1
|
||||||
|
|
||||||
|
if moretrees.plantlike_leaves then
|
||||||
|
moretrees_new_leaves_drawtype = "plantlike"
|
||||||
|
moretrees_plantlike_leaves_visual_scale = math.sqrt(2)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- redefine default leaves to handle plantlike and/or leaf decay options
|
||||||
|
|
||||||
|
if moretrees.plantlike_leaves then
|
||||||
|
minetest.override_item("default:leaves", {
|
||||||
|
inventory_image = minetest.inventorycube("default_leaves.png"),
|
||||||
|
drawtype = "plantlike",
|
||||||
|
visual_scale = math.sqrt(2)
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- redefine default jungle leaves for same
|
||||||
|
|
||||||
|
if moretrees.plantlike_leaves then
|
||||||
|
minetest.override_item("default:jungleleaves", {
|
||||||
|
inventory_image = minetest.inventorycube("default_jungleleaves.png"),
|
||||||
|
drawtype = "plantlike",
|
||||||
|
visual_scale = math.sqrt(2)
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
for i in ipairs(moretrees.treelist) do
|
||||||
|
local treename = moretrees.treelist[i][1]
|
||||||
|
local fruit = moretrees.treelist[i][3]
|
||||||
|
local fruitdesc = moretrees.treelist[i][4]
|
||||||
|
local selbox = moretrees.treelist[i][5]
|
||||||
|
local vscale = moretrees.treelist[i][6]
|
||||||
|
|
||||||
|
local saptex = moretrees.treelist[i][7]
|
||||||
|
|
||||||
|
-- player will get a sapling with 1/100 chance
|
||||||
|
-- player will get leaves only if he/she gets no saplings,
|
||||||
|
-- this is because max_items is 1
|
||||||
|
|
||||||
|
local droprarity = 100
|
||||||
|
local decay = moretrees.leafdecay_radius
|
||||||
|
|
||||||
|
if treename == "palm" then
|
||||||
|
droprarity = 20
|
||||||
|
decay = moretrees.palm_leafdecay_radius
|
||||||
|
elseif treename == "date_palm" then
|
||||||
|
decay = moretrees.palm_leafdecay_radius
|
||||||
|
end
|
||||||
|
|
||||||
|
if treename ~= "jungletree" -- the default game provides jungle tree and pine trunk/planks nodes.
|
||||||
|
and treename ~= "poplar_small"
|
||||||
|
and treename ~= "pine" then
|
||||||
|
|
||||||
|
saptex = "moretrees_"..treename.."_sapling.png"
|
||||||
|
|
||||||
|
minetest.register_node("moretrees:"..treename.."_trunk", {
|
||||||
|
description = moretrees.treedesc[treename].trunk,
|
||||||
|
tiles = {
|
||||||
|
"moretrees_"..treename.."_trunk_top.png",
|
||||||
|
"moretrees_"..treename.."_trunk_top.png",
|
||||||
|
"moretrees_"..treename.."_trunk.png"
|
||||||
|
},
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
is_ground_content = false,
|
||||||
|
groups = {tree=1,snappy=1,choppy=2,oddly_breakable_by_hand=1,flammable=2},
|
||||||
|
sounds = default.node_sound_wood_defaults(),
|
||||||
|
on_place = minetest.rotate_node,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("moretrees:"..treename.."_planks", {
|
||||||
|
description = moretrees.treedesc[treename].planks,
|
||||||
|
tiles = {"moretrees_"..treename.."_wood.png"},
|
||||||
|
is_ground_content = false,
|
||||||
|
groups = {snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3,wood=1},
|
||||||
|
sounds = default.node_sound_wood_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("moretrees:"..treename.."_sapling", {
|
||||||
|
description = moretrees.treedesc[treename].sapling,
|
||||||
|
drawtype = "plantlike",
|
||||||
|
tiles = {saptex},
|
||||||
|
inventory_image = saptex,
|
||||||
|
paramtype = "light",
|
||||||
|
paramtype2 = "waving",
|
||||||
|
walkable = false,
|
||||||
|
is_ground_content = true,
|
||||||
|
selection_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {-0.3, -0.5, -0.3, 0.3, 0.35, 0.3}
|
||||||
|
},
|
||||||
|
groups = {snappy=2,dig_immediate=3,flammable=2,attached_node=1,sapling=1},
|
||||||
|
sounds = default.node_sound_defaults(),
|
||||||
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
|
itemstack = default.sapling_on_place(itemstack, placer, pointed_thing,
|
||||||
|
"moretrees:" ..treename.. "_sapling",
|
||||||
|
-- minp, maxp to be checked, relative to sapling pos
|
||||||
|
-- minp_relative.y = 1 because sapling pos has been checked
|
||||||
|
{x = -3, y = 1, z = -3},
|
||||||
|
{x = 3, y = 6, z = 3},
|
||||||
|
-- maximum interval of interior volume check
|
||||||
|
4)
|
||||||
|
|
||||||
|
return itemstack
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
local moretrees_leaves_inventory_image = nil
|
||||||
|
local moretrees_new_leaves_waving = nil
|
||||||
|
|
||||||
|
if moretrees.plantlike_leaves then
|
||||||
|
moretrees_leaves_inventory_image = minetest.inventorycube("moretrees_"..treename.."_leaves.png")
|
||||||
|
else
|
||||||
|
moretrees_new_leaves_waving = 1
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_node("moretrees:"..treename.."_leaves", {
|
||||||
|
description = moretrees.treedesc[treename].leaves,
|
||||||
|
drawtype = moretrees_new_leaves_drawtype,
|
||||||
|
waving = moretrees_new_leaves_waving,
|
||||||
|
visual_scale = moretrees_plantlike_leaves_visual_scale,
|
||||||
|
tiles = { "moretrees_"..treename.."_leaves.png" },
|
||||||
|
inventory_image = moretrees_leaves_inventory_image,
|
||||||
|
paramtype = "light",
|
||||||
|
is_ground_content = false,
|
||||||
|
groups = {snappy = 3, flammable = 2, leaves = 1, moretrees_leaves = 1, leafdecay = 1},
|
||||||
|
sounds = default.node_sound_leaves_defaults(),
|
||||||
|
|
||||||
|
drop = {
|
||||||
|
max_items = 1,
|
||||||
|
items = {
|
||||||
|
{items = {"moretrees:"..treename.."_sapling"}, rarity = droprarity },
|
||||||
|
{items = {"moretrees:"..treename.."_leaves"} }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if moretrees.enable_stairs then
|
||||||
|
if minetest.get_modpath("moreblocks") then
|
||||||
|
|
||||||
|
-- stairsplus:register_all(modname, subname, recipeitem, {fields})
|
||||||
|
|
||||||
|
stairsplus:register_all(
|
||||||
|
"moretrees",
|
||||||
|
treename.."_trunk",
|
||||||
|
"moretrees:"..treename.."_trunk",
|
||||||
|
{
|
||||||
|
groups = { snappy=1, choppy=2, oddly_breakable_by_hand=1, flammable=2, not_in_creative_inventory=1 },
|
||||||
|
tiles = {
|
||||||
|
"moretrees_"..treename.."_trunk_top.png",
|
||||||
|
"moretrees_"..treename.."_trunk_top.png",
|
||||||
|
"moretrees_"..treename.."_trunk.png"
|
||||||
|
},
|
||||||
|
description = moretrees.treedesc[treename].trunk,
|
||||||
|
drop = treename.."_trunk",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
stairsplus:register_all(
|
||||||
|
"moretrees",
|
||||||
|
treename.."_planks",
|
||||||
|
"moretrees:"..treename.."_planks",
|
||||||
|
{
|
||||||
|
groups = { snappy=1, choppy=2, oddly_breakable_by_hand=2, flammable=3, not_in_creative_inventory=1 },
|
||||||
|
tiles = { "moretrees_"..treename.."_wood.png" },
|
||||||
|
description = moretrees.treedesc[treename].planks,
|
||||||
|
drop = treename.."_planks",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
elseif minetest.get_modpath("stairs") then
|
||||||
|
stairs.register_stair_and_slab(
|
||||||
|
"moretrees_"..treename.."_trunk",
|
||||||
|
"moretrees:"..treename.."_trunk",
|
||||||
|
{ snappy=1, choppy=2, oddly_breakable_by_hand=1, flammable=2 },
|
||||||
|
{ "moretrees_"..treename.."_trunk_top.png",
|
||||||
|
"moretrees_"..treename.."_trunk_top.png",
|
||||||
|
"moretrees_"..treename.."_trunk.png"
|
||||||
|
},
|
||||||
|
moretrees.treedesc[treename].trunk_stair,
|
||||||
|
moretrees.treedesc[treename].trunk_slab,
|
||||||
|
default.node_sound_wood_defaults()
|
||||||
|
)
|
||||||
|
|
||||||
|
stairs.register_stair_and_slab(
|
||||||
|
"moretrees_"..treename.."_planks",
|
||||||
|
"moretrees:"..treename.."_planks",
|
||||||
|
{ snappy=1, choppy=2, oddly_breakable_by_hand=2, flammable=3 },
|
||||||
|
{ "moretrees_"..treename.."_wood.png" },
|
||||||
|
moretrees.treedesc[treename].planks_stair,
|
||||||
|
moretrees.treedesc[treename].planks_slab,
|
||||||
|
default.node_sound_wood_defaults()
|
||||||
|
)
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if moretrees.enable_fences then
|
||||||
|
local planks_name = "moretrees:" .. treename .. "_planks"
|
||||||
|
local planks_tile = "moretrees_" .. treename .. "_wood.png"
|
||||||
|
default.register_fence("moretrees:" .. treename .. "_fence", {
|
||||||
|
description = moretrees.treedesc[treename].fence,
|
||||||
|
texture = planks_tile,
|
||||||
|
inventory_image = "default_fence_overlay.png^" .. planks_tile ..
|
||||||
|
"^default_fence_overlay.png^[makealpha:255,126,126",
|
||||||
|
wield_image = "default_fence_overlay.png^" .. planks_tile ..
|
||||||
|
"^default_fence_overlay.png^[makealpha:255,126,126",
|
||||||
|
material = planks_name,
|
||||||
|
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
|
||||||
|
sounds = default.node_sound_wood_defaults()
|
||||||
|
})
|
||||||
|
default.register_fence_rail("moretrees:" .. treename .. "_fence_rail", {
|
||||||
|
description = moretrees.treedesc[treename].fence_rail,
|
||||||
|
texture = planks_tile,
|
||||||
|
inventory_image = "default_fence_rail_overlay.png^" .. planks_tile ..
|
||||||
|
"^default_fence_rail_overlay.png^[makealpha:255,126,126",
|
||||||
|
wield_image = "default_fence_rail_overlay.png^" .. planks_tile ..
|
||||||
|
"^default_fence_rail_overlay.png^[makealpha:255,126,126",
|
||||||
|
material = planks_name,
|
||||||
|
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
|
||||||
|
sounds = default.node_sound_wood_defaults()
|
||||||
|
})
|
||||||
|
if minetest.global_exists("doors") then
|
||||||
|
doors.register_fencegate("moretrees:" .. treename .. "_gate", {
|
||||||
|
description = moretrees.treedesc[treename].fence_gate,
|
||||||
|
texture = planks_tile,
|
||||||
|
material = planks_name,
|
||||||
|
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_node("moretrees:"..treename.."_sapling_ongen", {
|
||||||
|
description = S("@1 (fast growth)", moretrees.treedesc[treename].sapling),
|
||||||
|
drawtype = "plantlike",
|
||||||
|
tiles = {saptex},
|
||||||
|
inventory_image = saptex,
|
||||||
|
paramtype = "light",
|
||||||
|
paramtype2 = "waving",
|
||||||
|
walkable = false,
|
||||||
|
is_ground_content = true,
|
||||||
|
selection_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {-0.3, -0.5, -0.3, 0.3, 0.35, 0.3}
|
||||||
|
},
|
||||||
|
groups = {snappy=2,dig_immediate=3,flammable=2,attached_node=1,sapling=1},
|
||||||
|
sounds = default.node_sound_defaults(),
|
||||||
|
drop = "moretrees:"..treename.."_sapling",
|
||||||
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
|
itemstack = default.sapling_on_place(itemstack, placer, pointed_thing,
|
||||||
|
"moretrees:" ..treename.. "_sapling_ongen",
|
||||||
|
-- minp, maxp to be checked, relative to sapling pos
|
||||||
|
-- minp_relative.y = 1 because sapling pos has been checked
|
||||||
|
{x = -3, y = 1, z = -3},
|
||||||
|
{x = 3, y = 6, z = 3},
|
||||||
|
-- maximum interval of interior volume check
|
||||||
|
4)
|
||||||
|
|
||||||
|
return itemstack
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
local fruitname = nil
|
||||||
|
if fruit then
|
||||||
|
fruitname = "moretrees:"..fruit
|
||||||
|
minetest.register_node(fruitname, {
|
||||||
|
description = fruitdesc,
|
||||||
|
drawtype = "plantlike",
|
||||||
|
tiles = { "moretrees_"..fruit..".png" },
|
||||||
|
inventory_image = "moretrees_"..fruit..".png^[transformR180",
|
||||||
|
wield_image = "moretrees_"..fruit..".png^[transformR180",
|
||||||
|
visual_scale = vscale,
|
||||||
|
paramtype = "light",
|
||||||
|
sunlight_propagates = true,
|
||||||
|
is_ground_content = false,
|
||||||
|
walkable = false,
|
||||||
|
selection_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = selbox
|
||||||
|
},
|
||||||
|
groups = {fleshy=3,dig_immediate=3,flammable=2, attached_node=1, leafdecay = 1, leafdecay_drop = 1},
|
||||||
|
sounds = default.node_sound_defaults(),
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
if treename ~= "jungletree"
|
||||||
|
and treename ~= "poplar_small"
|
||||||
|
and treename ~= "pine" then
|
||||||
|
default.register_leafdecay({
|
||||||
|
trunks = { "moretrees:"..treename.."_trunk" },
|
||||||
|
leaves = { "moretrees:"..treename.."_leaves", fruitname },
|
||||||
|
radius = decay,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_abm({
|
||||||
|
nodenames = { "moretrees:"..treename.."_trunk_sideways" },
|
||||||
|
interval = 1,
|
||||||
|
chance = 1,
|
||||||
|
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||||
|
local fdir = node.param2 or 0
|
||||||
|
local nfdir = dirs2[fdir+1]
|
||||||
|
minetest.add_node(pos, {name = "moretrees:"..treename.."_trunk", param2 = nfdir})
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
table.insert(moretrees.avoidnodes, "moretrees:"..treename.."_trunk")
|
||||||
|
|
||||||
|
if moretrees.spawn_saplings then
|
||||||
|
table.insert(moretrees.avoidnodes, "moretrees:"..treename.."_sapling")
|
||||||
|
table.insert(moretrees.avoidnodes, "moretrees:"..treename.."_sapling_ongen")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add small poplar saplings
|
||||||
|
|
||||||
|
local poplar_sapling = minetest.registered_nodes["moretrees:poplar_sapling"]
|
||||||
|
local poplar_sapling_ongen = minetest.registered_nodes["moretrees:poplar_sapling_ongen"]
|
||||||
|
local poplar_small_sapling = {}
|
||||||
|
local poplar_small_sapling_ongen = {}
|
||||||
|
for k,v in pairs(poplar_sapling) do
|
||||||
|
poplar_small_sapling[k] = v
|
||||||
|
end
|
||||||
|
for k,v in pairs(poplar_sapling_ongen) do
|
||||||
|
poplar_small_sapling_ongen[k] = v
|
||||||
|
end
|
||||||
|
poplar_small_sapling.tiles = {"moretrees_poplar_small_sapling.png"}
|
||||||
|
poplar_small_sapling.inventory_image = "moretrees_poplar_small_sapling.png"
|
||||||
|
poplar_small_sapling.is_ground_content = true
|
||||||
|
poplar_small_sapling_ongen.tiles_ongen = {"moretrees_poplar_small_sapling.png"}
|
||||||
|
poplar_small_sapling_ongen.inventory_image_ongen = "moretrees_poplar_small_sapling.png"
|
||||||
|
poplar_small_sapling_ongen.drop = "moretrees:poplar_small_sapling"
|
||||||
|
poplar_small_sapling_ongen.is_ground_content = true
|
||||||
|
|
||||||
|
minetest.register_node("moretrees:poplar_small_sapling", poplar_small_sapling)
|
||||||
|
minetest.register_node("moretrees:poplar_small_sapling_ongen", poplar_small_sapling_ongen)
|
||||||
|
if moretrees.spawn_saplings then
|
||||||
|
table.insert(moretrees.avoidnodes, "moretrees:poplar_sapling")
|
||||||
|
table.insert(moretrees.avoidnodes, "moretrees:poplar_small_sapling_ongen")
|
||||||
|
end
|
||||||
|
|
||||||
|
local poplar_leaves_drop = minetest.registered_nodes["moretrees:poplar_leaves"].drop
|
||||||
|
minetest.override_item("moretrees:poplar_leaves", {
|
||||||
|
drop = {
|
||||||
|
max_items = poplar_leaves_drop.maxitems,
|
||||||
|
items = {
|
||||||
|
{items = {"moretrees:poplar_sapling"}, rarity = 1.33 * poplar_leaves_drop.items[1].rarity },
|
||||||
|
{items = {"moretrees:poplar_small_sapling"}, rarity = 1.33 * poplar_leaves_drop.items[1].rarity },
|
||||||
|
{items = {"moretrees:poplar_leaves"} }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Extra nodes for jungle trees:
|
||||||
|
|
||||||
|
local jungleleaves = {"yellow","red"}
|
||||||
|
local jungleleavesnames = {S("Yellow"), S("Red")}
|
||||||
|
for color = 1, #jungleleaves do
|
||||||
|
local leave_name = "moretrees:jungletree_leaves_"..jungleleaves[color]
|
||||||
|
|
||||||
|
local moretrees_leaves_inventory_image = nil
|
||||||
|
|
||||||
|
if moretrees.plantlike_leaves then
|
||||||
|
moretrees_leaves_inventory_image = minetest.inventorycube("moretrees_jungletree_leaves_"..jungleleaves[color]..".png")
|
||||||
|
else
|
||||||
|
moretrees_new_leaves_waving = 1
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_node(leave_name, {
|
||||||
|
description = S("Jungle Tree Leaves (@1)", jungleleavesnames[color]),
|
||||||
|
drawtype = moretrees_new_leaves_drawtype,
|
||||||
|
waving = moretrees_new_leaves_waving,
|
||||||
|
visual_scale = moretrees_plantlike_leaves_visual_scale,
|
||||||
|
tiles = {"moretrees_jungletree_leaves_"..jungleleaves[color]..".png"},
|
||||||
|
inventory_image = moretrees_leaves_inventory_image,
|
||||||
|
paramtype = "light",
|
||||||
|
is_ground_content = false,
|
||||||
|
groups = {snappy = 3, flammable = 2, leaves = 1, moretrees_leaves = 1, leafdecay = 3 },
|
||||||
|
drop = {
|
||||||
|
max_items = 1,
|
||||||
|
items = {
|
||||||
|
{items = {"default:junglesapling"}, rarity = 100 },
|
||||||
|
{items = {"moretrees:jungletree_leaves_"..jungleleaves[color]} }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sounds = default.node_sound_leaves_defaults(),
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- To get Moretrees to generate its own jungle trees among the default mapgen
|
||||||
|
-- we need our own copy of that node, which moretrees will match against.
|
||||||
|
|
||||||
|
local jungle_tree = table.copy(minetest.registered_nodes["default:jungletree"])
|
||||||
|
jungle_tree.drop = "default:jungletree"
|
||||||
|
minetest.register_node("moretrees:jungletree_trunk", jungle_tree)
|
||||||
|
|
||||||
|
default.register_leafdecay({
|
||||||
|
trunks = { "default:jungletree", "moretrees:jungletree_trunk" },
|
||||||
|
leaves = { "default:jungleleaves", "moretrees:jungletree_leaves_yellow", "moretrees:jungletree_leaves_red" },
|
||||||
|
radius = moretrees.leafdecay_radius,
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Extra needles for firs
|
||||||
|
|
||||||
|
local moretrees_leaves_inventory_image = nil
|
||||||
|
|
||||||
|
if moretrees.plantlike_leaves then
|
||||||
|
moretrees_leaves_inventory_image = minetest.inventorycube("moretrees_fir_leaves_bright.png")
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_node("moretrees:fir_leaves_bright", {
|
||||||
|
drawtype = moretrees_new_leaves_drawtype,
|
||||||
|
waving = moretrees_new_leaves_waving,
|
||||||
|
visual_scale = moretrees_plantlike_leaves_visual_scale,
|
||||||
|
description = S("Douglas Fir Leaves (Bright)"),
|
||||||
|
tiles = { "moretrees_fir_leaves_bright.png" },
|
||||||
|
inventory_image = moretrees_leaves_inventory_image,
|
||||||
|
paramtype = "light",
|
||||||
|
is_ground_content = false,
|
||||||
|
groups = {snappy = 3, flammable = 2, leaves = 1, moretrees_leaves = 1, leafdecay = 3 },
|
||||||
|
drop = {
|
||||||
|
max_items = 1,
|
||||||
|
items = {
|
||||||
|
{items = {'moretrees:fir_sapling'}, rarity = 100 },
|
||||||
|
{items = {'moretrees:fir_leaves_bright'} }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sounds = default.node_sound_leaves_defaults()
|
||||||
|
})
|
||||||
|
|
||||||
|
default.register_leafdecay({
|
||||||
|
trunks = { "moretrees:fir_trunk" },
|
||||||
|
leaves = { "moretrees:fir_leaves", "moretrees:fir_leaves_bright" },
|
||||||
|
radius = moretrees.leafdecay_radius,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
if moretrees.enable_redefine_apple then
|
||||||
|
local appledef = table.copy(minetest.registered_nodes["default:apple"])
|
||||||
|
appledef.groups.attached_node = 1
|
||||||
|
minetest.register_node(":default:apple", appledef)
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(moretrees.avoidnodes, "default:jungletree")
|
||||||
|
table.insert(moretrees.avoidnodes, "default:pine_tree")
|
||||||
|
table.insert(moretrees.avoidnodes, "default:acacia_tree")
|
||||||
|
table.insert(moretrees.avoidnodes, "moretrees:fir_trunk")
|
||||||
|
table.insert(moretrees.avoidnodes, "default:tree")
|
||||||
|
|
||||||
|
if moretrees.spawn_saplings then
|
||||||
|
table.insert(moretrees.avoidnodes, "snow:sapling_pine")
|
||||||
|
table.insert(moretrees.avoidnodes, "default:junglesapling")
|
||||||
|
table.insert(moretrees.avoidnodes, "default:pine_sapling")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- "empty" (tapped) rubber tree nodes
|
||||||
|
|
||||||
|
minetest.register_node("moretrees:rubber_tree_trunk_empty", {
|
||||||
|
description = S("Rubber Tree Trunk (Empty)"),
|
||||||
|
tiles = {
|
||||||
|
"moretrees_rubber_tree_trunk_top.png",
|
||||||
|
"moretrees_rubber_tree_trunk_top.png",
|
||||||
|
"moretrees_rubber_tree_trunk_empty.png"
|
||||||
|
},
|
||||||
|
groups = {tree=1,snappy=1,choppy=2,oddly_breakable_by_hand=1,flammable=2},
|
||||||
|
sounds = default.node_sound_wood_defaults(),
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
is_ground_content = false,
|
||||||
|
on_place = minetest.rotate_node,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_abm({
|
||||||
|
nodenames = { "moretrees:rubber_tree_trunk_empty_sideways" },
|
||||||
|
interval = 1,
|
||||||
|
chance = 1,
|
||||||
|
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||||
|
local fdir = node.param2 or 0
|
||||||
|
local nfdir = dirs2[fdir+1]
|
||||||
|
minetest.add_node(pos, {name = "moretrees:rubber_tree_trunk_empty", param2 = nfdir})
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
-- For compatibility with old nodes, recently-changed nodes, and default nodes
|
||||||
|
|
||||||
|
minetest.register_alias("technic:rubber_tree_full", "moretrees:rubber_tree_trunk")
|
||||||
|
minetest.register_alias("farming_plus:rubber_tree_full", "moretrees:rubber_tree_trunk")
|
||||||
|
minetest.register_alias("farming:rubber_tree_full", "moretrees:rubber_tree_trunk")
|
||||||
|
|
||||||
|
minetest.register_alias("technic:rubber_leaves", "moretrees:rubber_tree_leaves")
|
||||||
|
minetest.register_alias("farming_plus:rubber_leaves", "moretrees:rubber_tree_leaves")
|
||||||
|
minetest.register_alias("farming:rubber_leaves", "moretrees:rubber_tree_leaves")
|
||||||
|
|
||||||
|
minetest.register_alias("technic:rubber_tree_sapling", "moretrees:rubber_tree_sapling")
|
||||||
|
minetest.register_alias("farming_plus:rubber_sapling", "moretrees:rubber_tree_sapling")
|
||||||
|
minetest.register_alias("farming:rubber_sapling", "moretrees:rubber_tree_sapling")
|
||||||
|
|
||||||
|
minetest.register_alias("moretrees:conifer_trunk", "moretrees:fir_trunk")
|
||||||
|
minetest.register_alias("moretrees:conifer_trunk_sideways", "moretrees:fir_trunk_sideways")
|
||||||
|
minetest.register_alias("moretrees:conifer_leaves", "moretrees:fir_leaves")
|
||||||
|
minetest.register_alias("moretrees:conifer_leaves_bright", "moretrees:fir_leaves_bright")
|
||||||
|
minetest.register_alias("moretrees:conifer_sapling", "moretrees:fir_sapling")
|
||||||
|
|
||||||
|
minetest.register_alias("conifers:trunk", "moretrees:fir_trunk")
|
||||||
|
minetest.register_alias("conifers:trunk_reversed", "moretrees:fir_trunk_sideways")
|
||||||
|
minetest.register_alias("conifers:leaves", "moretrees:fir_leaves")
|
||||||
|
minetest.register_alias("conifers:leaves_special", "moretrees:fir_leaves_bright")
|
||||||
|
minetest.register_alias("conifers:sapling", "moretrees:fir_sapling")
|
||||||
|
|
||||||
|
minetest.register_alias("moretrees:jungletree_sapling", "default:junglesapling")
|
||||||
|
minetest.register_alias("moretrees:jungletree_trunk_sideways", "moreblocks:horizontal_jungle_tree")
|
||||||
|
minetest.register_alias("moretrees:jungletree_planks", "default:junglewood")
|
||||||
|
minetest.register_alias("moretrees:jungletree_leaves_green", "default:jungleleaves")
|
||||||
|
|
||||||
|
minetest.register_alias("moretrees:acacia_trunk", "default:acacia_tree")
|
||||||
|
minetest.register_alias("moretrees:acacia_planks", "default:acacia_wood")
|
||||||
|
minetest.register_alias("moretrees:acacia_sapling", "default:acacia_sapling")
|
||||||
|
minetest.register_alias("moretrees:acacia_leaves", "default:acacia_leaves")
|
||||||
|
|
||||||
|
minetest.register_alias("moretrees:pine_trunk", "moretrees:cedar_trunk")
|
||||||
|
minetest.register_alias("moretrees:pine_planks", "moretrees:cedar_planks")
|
||||||
|
minetest.register_alias("moretrees:pine_sapling", "moretrees:cedar_sapling")
|
||||||
|
minetest.register_alias("moretrees:pine_leaves", "moretrees:cedar_leaves")
|
||||||
|
minetest.register_alias("moretrees:pine_cone", "moretrees:cedar_cone")
|
||||||
|
minetest.register_alias("moretrees:pine_nuts", "moretrees:cedar_nuts")
|
||||||
|
minetest.register_alias("moretrees:pine_sapling_ongen", "moretrees:cedar_sapling_ongen")
|
||||||
|
|
||||||
|
minetest.register_alias("moretrees:dates", "moretrees:dates_f4")
|
84
mods/moretrees/saplings.lua
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
-- sapling growth
|
||||||
|
-- these tables only affect hand-placed saplings
|
||||||
|
-- mapgen-placed always use their biome def settings, which are much more
|
||||||
|
-- limited, in the interest of speed.
|
||||||
|
|
||||||
|
local dirt_surfaces = {
|
||||||
|
set = true,
|
||||||
|
["default:dirt"] = true,
|
||||||
|
["default:dirt_with_grass"] = true,
|
||||||
|
["default:dirt_with_dry_grass"] = true,
|
||||||
|
["default:dirt_with_coniferous_litter"] = true,
|
||||||
|
["default:dirt_with_rainforest_litter"] = true,
|
||||||
|
["woodsoils:dirt_with_leaves_1"] = true,
|
||||||
|
["woodsoils:dirt_with_leaves_2"] = true,
|
||||||
|
["woodsoils:grass_with_leaves_1"] = true,
|
||||||
|
["woodsoils:grass_with_leaves_2"] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
local conifer_surfaces = {
|
||||||
|
set = true,
|
||||||
|
["default:dirt"] = true,
|
||||||
|
["default:dirt_with_grass"] = true,
|
||||||
|
["default:dirt_with_dry_grass"] = true,
|
||||||
|
["default:dirt_with_coniferous_litter"] = true,
|
||||||
|
["default:dirt_with_rainforest_litter"] = true,
|
||||||
|
["woodsoils:dirt_with_leaves_1"] = true,
|
||||||
|
["woodsoils:dirt_with_leaves_2"] = true,
|
||||||
|
["woodsoils:grass_with_leaves_1"] = true,
|
||||||
|
["woodsoils:grass_with_leaves_2"] = true,
|
||||||
|
["default:dirt_with_snow"] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
local sand_surfaces = {
|
||||||
|
set = true,
|
||||||
|
["default:sand"] = true,
|
||||||
|
["default:desert_sand"] = true,
|
||||||
|
["cottages:loam"] = true,
|
||||||
|
-- note, no silver sand here.
|
||||||
|
-- too cold for a palm, too... well... sandy for anything else.
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in ipairs(moretrees.treelist) do
|
||||||
|
local treename = moretrees.treelist[i][1]
|
||||||
|
local tree_model = treename.."_model"
|
||||||
|
local tree_biome = treename.."_biome"
|
||||||
|
local surfaces
|
||||||
|
local grow_function = moretrees[tree_model]
|
||||||
|
|
||||||
|
if treename == "spruce"
|
||||||
|
or treename == "fir"
|
||||||
|
or treename == "cedar"
|
||||||
|
or treename == "pine" then
|
||||||
|
surfaces = conifer_surfaces
|
||||||
|
elseif string.find(treename, "palm") then
|
||||||
|
surfaces = sand_surfaces
|
||||||
|
else
|
||||||
|
surfaces = dirt_surfaces
|
||||||
|
end
|
||||||
|
|
||||||
|
if treename == "spruce"
|
||||||
|
or treename == "fir"
|
||||||
|
or treename == "birch"
|
||||||
|
or treename == "jungletree" then
|
||||||
|
grow_function = "moretrees.grow_"..treename
|
||||||
|
end
|
||||||
|
|
||||||
|
biome_lib:dbg(dump(moretrees[tree_biome].surface))
|
||||||
|
|
||||||
|
biome_lib:grow_plants({
|
||||||
|
grow_delay = moretrees.sapling_interval,
|
||||||
|
grow_chance = moretrees.sapling_chance,
|
||||||
|
grow_plant = "moretrees:"..treename.."_sapling",
|
||||||
|
grow_nodes = surfaces,
|
||||||
|
grow_function = grow_function,
|
||||||
|
})
|
||||||
|
|
||||||
|
biome_lib:grow_plants({
|
||||||
|
grow_delay = 2,
|
||||||
|
grow_chance = 1,
|
||||||
|
grow_plant = "moretrees:"..treename.."_sapling_ongen",
|
||||||
|
grow_nodes = surfaces,
|
||||||
|
grow_function = grow_function,
|
||||||
|
})
|
||||||
|
end
|
168
mods/moretrees/screenshot.lua
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
-- Usage:
|
||||||
|
-- - Create a new world
|
||||||
|
-- - Set world mapgen: v6
|
||||||
|
-- - Set world seed: 2625051331357512570
|
||||||
|
-- - Enable the moretrees mod
|
||||||
|
-- - Edit the moretrees source
|
||||||
|
-- - Disable all trees in default_settings.lua
|
||||||
|
-- - Recommended: make saplings grow fast in default_settings.lua:
|
||||||
|
-- sapling_interval = 5
|
||||||
|
-- sapling_chance = 1
|
||||||
|
-- - Apply the patch below to moretrees
|
||||||
|
-- (so that jungle trees are always large, and differently-colored):
|
||||||
|
-- use 'git apply --ignore-space-change'
|
||||||
|
-- - Make sure this file (you are reading) will be loaded when minetest starts !
|
||||||
|
-- (e.g. add 'dofile(modpath.."/screenshot.lua")' to init.lua)
|
||||||
|
-- - Start minetest
|
||||||
|
-- - Goto 700,y,-280 (approximately)
|
||||||
|
-- - Make sure the world is loaded between x = 650 .. 780 and z = -350 .. -180
|
||||||
|
-- - Give the chat command '/make-scene'
|
||||||
|
-- - Wait & walk/fly around until all trees have grown
|
||||||
|
-- - goto the platform at 780, 30, -277
|
||||||
|
-- - Set the viewing range to 300, with fog enabled
|
||||||
|
-- - Take a screenshot.
|
||||||
|
|
||||||
|
-- Patch to apply to moretrees
|
||||||
|
--[[
|
||||||
|
diff --git a/init.lua b/init.lua
|
||||||
|
index 8189ffd..afd4644 100644
|
||||||
|
--- a/init.lua
|
||||||
|
+++ b/init.lua
|
||||||
|
@@ -225,9 +225,12 @@ moretrees.ct_rules_b1 = "[-FBf][+FBf]"
|
||||||
|
moretrees.ct_rules_a2 = "FF[FF][&&-FBF][&&+FBF][&&---FBF][&&+++FBF]F/A"
|
||||||
|
moretrees.ct_rules_b2 = "[-fB][+fB]"
|
||||||
|
|
||||||
|
+local jleaves = 1
|
||||||
|
function moretrees.grow_jungletree(pos)
|
||||||
|
local r1 = math.random(2)
|
||||||
|
local r2 = math.random(3)
|
||||||
|
+ r1 = jleaves
|
||||||
|
+ jleaves = jleaves % 2 + 1
|
||||||
|
if r1 == 1 then
|
||||||
|
moretrees.jungletree_model.leaves2 = "moretrees:jungletree_leaves_red"
|
||||||
|
else
|
||||||
|
@@ -235,6 +238,7 @@ function moretrees.grow_jungletree(pos)
|
||||||
|
end
|
||||||
|
moretrees.jungletree_model.leaves2_chance = math.random(25, 75)
|
||||||
|
|
||||||
|
+ r2=3
|
||||||
|
if r2 == 1 then
|
||||||
|
moretrees.jungletree_model.trunk_type = "single"
|
||||||
|
moretrees.jungletree_model.iterations = 2
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_chatcommand("make-scene", {
|
||||||
|
func = function()
|
||||||
|
minetest.place_node({x=780, y=30, z=-277}, {name="default:obsidian"})
|
||||||
|
minetest.place_node({x=780, y=30, z=-278}, {name="default:obsidian"})
|
||||||
|
minetest.place_node({x=781, y=30, z=-277}, {name="default:obsidian"})
|
||||||
|
minetest.place_node({x=781, y=30, z=-278}, {name="default:obsidian"})
|
||||||
|
minetest.place_node({x=781, y=30, z=-276}, {name="default:obsidian"})
|
||||||
|
minetest.place_node({x=780, y=30, z=-276}, {name="default:obsidian"})
|
||||||
|
|
||||||
|
for z = -360, -300 do
|
||||||
|
local dy=2
|
||||||
|
for x = 630 + (-z - 360)/3, 660 + (-z - 300)/3 do
|
||||||
|
for y = 5, 22 do
|
||||||
|
minetest.place_node({x=x, y=y, z=z}, {name="default:desert_stone"})
|
||||||
|
end
|
||||||
|
for y = 23, 25 + dy do
|
||||||
|
minetest.place_node({x=x, y=y, z=z}, {name="default:desert_sand"})
|
||||||
|
end
|
||||||
|
dy = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.place_node({x=717, y=2, z=-298}, {name = "moretrees:palm_sapling"})
|
||||||
|
minetest.place_node({x=713, y=2, z=-302}, {name = "moretrees:palm_sapling"})
|
||||||
|
minetest.place_node({x=713, y=2, z=-307}, {name = "moretrees:palm_sapling"})
|
||||||
|
minetest.place_node({x=717, y=2, z=-318}, {name = "moretrees:palm_sapling"})
|
||||||
|
minetest.place_node({x=723, y=2, z=-320}, {name = "moretrees:palm_sapling"})
|
||||||
|
|
||||||
|
minetest.place_node({x=645, y=26, z=-314}, {name="moretrees:date_palm_sapling"})
|
||||||
|
minetest.place_node({x=653, y=26, z=-322}, {name="moretrees:date_palm_sapling"})
|
||||||
|
minetest.place_node({x=649, y=26, z=-334}, {name="moretrees:date_palm_sapling"})
|
||||||
|
minetest.place_node({x=662, y=26, z=-342}, {name="moretrees:date_palm_sapling"})
|
||||||
|
|
||||||
|
minetest.place_node({x=672, y=5, z=-305}, {name="moretrees:oak_sapling"})
|
||||||
|
minetest.place_node({x=690, y=6, z=-322}, {name="moretrees:oak_sapling"})
|
||||||
|
minetest.place_node({x=695, y=7, z=-335}, {name="moretrees:oak_sapling"})
|
||||||
|
minetest.place_node({x=699, y=4, z=-301}, {name="moretrees:oak_sapling"})
|
||||||
|
|
||||||
|
minetest.place_node({x=751, y=5, z=-254}, {name="moretrees:apple_tree_sapling"})
|
||||||
|
minetest.place_node({x=729, y=3, z=-275}, {name="moretrees:apple_tree_sapling"})
|
||||||
|
minetest.place_node({x=747, y=4, z=-270}, {name="moretrees:apple_tree_sapling"})
|
||||||
|
|
||||||
|
minetest.place_node({x=671, y=5, z=-283}, {name="default:junglesapling"})
|
||||||
|
minetest.place_node({x=680, y=4, z=-287}, {name="default:junglesapling"})
|
||||||
|
minetest.place_node({x=702, y=4, z=-288}, {name="default:junglesapling"})
|
||||||
|
|
||||||
|
minetest.place_node({x=646, y=12, z=-199}, {name="moretrees:spruce_sapling"})
|
||||||
|
minetest.place_node({x=644, y=14, z=-177}, {name="moretrees:spruce_sapling"})
|
||||||
|
minetest.place_node({x=678, y=9, z=-211}, {name="moretrees:spruce_sapling"})
|
||||||
|
minetest.place_node({x=663, y=10, z=-215}, {name="moretrees:spruce_sapling"})
|
||||||
|
|
||||||
|
minetest.place_node({x=637, y=3, z=-263}, {name="moretrees:sequoia_sapling"})
|
||||||
|
minetest.place_node({x=625, y=3, z=-250}, {name="moretrees:sequoia_sapling"})
|
||||||
|
minetest.place_node({x=616, y=3, z=-233}, {name="moretrees:sequoia_sapling"})
|
||||||
|
minetest.place_node({x=635, y=3, z=-276}, {name="moretrees:sequoia_sapling"})
|
||||||
|
minetest.place_node({x=681, y=11, z=-260}, {name="moretrees:sequoia_sapling"})
|
||||||
|
minetest.place_node({x=682, y=10, z=-247}, {name="moretrees:sequoia_sapling"})
|
||||||
|
|
||||||
|
minetest.place_node({x=737, y=7, z=-195}, {name="moretrees:cedar_sapling"})
|
||||||
|
minetest.place_node({x=720, y=8, z=-189}, {name="moretrees:cedar_sapling"})
|
||||||
|
minetest.place_node({x=704, y=7, z=-187}, {name="moretrees:cedar_sapling"})
|
||||||
|
|
||||||
|
minetest.place_node({x=731, y=2, z=-227}, {name="moretrees:poplar_sapling"})
|
||||||
|
minetest.place_node({x=721, y=2, z=-233}, {name="moretrees:poplar_sapling"})
|
||||||
|
minetest.place_node({x=712, y=1, z=-237}, {name="moretrees:poplar_sapling"})
|
||||||
|
minetest.place_node({x=743, y=3, z=-228}, {name="moretrees:poplar_small_sapling"})
|
||||||
|
minetest.place_node({x=750, y=3, z=-230}, {name="moretrees:poplar_small_sapling"})
|
||||||
|
minetest.place_node({x=731, y=5, z=-233}, {name="moretrees:poplar_small_sapling"})
|
||||||
|
|
||||||
|
minetest.place_node({x=702, y=2, z=-274}, {name="moretrees:birch_sapling"})
|
||||||
|
minetest.place_node({x=697, y=2, z=-271}, {name="moretrees:birch_sapling"})
|
||||||
|
minetest.place_node({x=696, y=2, z=-264}, {name="moretrees:birch_sapling"})
|
||||||
|
minetest.place_node({x=710, y=2, z=-265}, {name="moretrees:birch_sapling"})
|
||||||
|
|
||||||
|
minetest.place_node({x=707, y=8, z=-247}, {name="moretrees:fir_sapling"})
|
||||||
|
minetest.place_node({x=699, y=10, z=-254}, {name="moretrees:fir_sapling"})
|
||||||
|
minetest.place_node({x=729, y=5, z=-261}, {name="moretrees:fir_sapling"})
|
||||||
|
minetest.place_node({x=732, y=5, z=-252}, {name="moretrees:fir_sapling"})
|
||||||
|
minetest.place_node({x=741, y=4, z=-262}, {name="moretrees:fir_sapling"})
|
||||||
|
|
||||||
|
minetest.place_node({x=751, y=2, z=-286}, {name="moretrees:willow_sapling"})
|
||||||
|
|
||||||
|
minetest.place_node({x=760, y=5, z=-223}, {name="moretrees:rubber_tree_sapling"})
|
||||||
|
minetest.place_node({x=762, y=5, z=-230}, {name="moretrees:rubber_tree_sapling"})
|
||||||
|
minetest.place_node({x=766, y=5, z=-243}, {name="moretrees:rubber_tree_sapling"})
|
||||||
|
minetest.place_node({x=764, y=6, z=-252}, {name="moretrees:rubber_tree_sapling"})
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
--[[
|
||||||
|
The following is a search/replace command suitable for vi (/vim) or sed, to convert minetest log
|
||||||
|
messages to equivalent lua commands:
|
||||||
|
|
||||||
|
s/.*\(\(moretrees\|default\)[^ ]*\) at (\([-0-9]\+\),\([-0-9]\+\),\([-0-9]\+\)).*/\t\tminetest.place_node({x=\3, y=\4, z=\5}, {name="\1"})/
|
||||||
|
|
||||||
|
E.g. a minetest log line of the following kind:
|
||||||
|
2016-07-03 11:30:50: ACTION[Server]: singleplayer places node moretrees:rubber_tree_sapling at (760,5,-223)
|
||||||
|
Becomes:
|
||||||
|
minetest.place_node({x=760, y=5, z=-223}, {name="moretrees:rubber_tree_sapling"})
|
||||||
|
(Except that the example log line above has an extra space added, so it won't be converted)
|
||||||
|
|
||||||
|
vi/vim users: Add the minetest log lines to this file, then enter the following command, with
|
||||||
|
<expression> replaced with the search/replace expression above.
|
||||||
|
:%<expression>
|
||||||
|
|
||||||
|
sed users: Add the minetest log lines to this file, then execute the following command at the shell
|
||||||
|
prompt with <expression> replaced by the search/replace expression above. Don't forget the
|
||||||
|
single-quotes.
|
||||||
|
sed '<expression>' < screenshot.lua > screenshot-new.lua
|
||||||
|
|
||||||
|
Windows users: You're probably out of luck. And the effort of doing such a thing is probably
|
||||||
|
larger anyway than the effort of copying an existing line and typing things manually.
|
||||||
|
]]
|
||||||
|
|
BIN
mods/moretrees/screenshot.png
Normal file
After Width: | Height: | Size: 101 KiB |
BIN
mods/moretrees/textures/moretrees_acorn.png
Normal file
After Width: | Height: | Size: 417 B |
BIN
mods/moretrees/textures/moretrees_acorn_muffin.png
Normal file
After Width: | Height: | Size: 782 B |
BIN
mods/moretrees/textures/moretrees_acorn_muffin_batter.png
Normal file
After Width: | Height: | Size: 619 B |
BIN
mods/moretrees/textures/moretrees_apple_tree_leaves.png
Normal file
After Width: | Height: | Size: 351 B |
BIN
mods/moretrees/textures/moretrees_apple_tree_sapling.png
Normal file
After Width: | Height: | Size: 183 B |
BIN
mods/moretrees/textures/moretrees_apple_tree_trunk.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
mods/moretrees/textures/moretrees_apple_tree_trunk_top.png
Normal file
After Width: | Height: | Size: 503 B |
BIN
mods/moretrees/textures/moretrees_apple_tree_wood.png
Normal file
After Width: | Height: | Size: 464 B |
BIN
mods/moretrees/textures/moretrees_beech_leaves.png
Normal file
After Width: | Height: | Size: 201 B |
BIN
mods/moretrees/textures/moretrees_beech_sapling.png
Normal file
After Width: | Height: | Size: 177 B |
BIN
mods/moretrees/textures/moretrees_beech_trunk.png
Normal file
After Width: | Height: | Size: 980 B |
BIN
mods/moretrees/textures/moretrees_beech_trunk_top.png
Normal file
After Width: | Height: | Size: 926 B |
BIN
mods/moretrees/textures/moretrees_beech_wood.png
Normal file
After Width: | Height: | Size: 175 B |
BIN
mods/moretrees/textures/moretrees_birch_leaves.png
Normal file
After Width: | Height: | Size: 459 B |
BIN
mods/moretrees/textures/moretrees_birch_sapling.png
Normal file
After Width: | Height: | Size: 208 B |
BIN
mods/moretrees/textures/moretrees_birch_trunk.png
Normal file
After Width: | Height: | Size: 975 B |
BIN
mods/moretrees/textures/moretrees_birch_trunk_top.png
Normal file
After Width: | Height: | Size: 811 B |
BIN
mods/moretrees/textures/moretrees_birch_wood.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
mods/moretrees/textures/moretrees_cedar_cone.png
Normal file
After Width: | Height: | Size: 315 B |
BIN
mods/moretrees/textures/moretrees_cedar_leaves.png
Normal file
After Width: | Height: | Size: 205 B |
BIN
mods/moretrees/textures/moretrees_cedar_nuts.png
Normal file
After Width: | Height: | Size: 369 B |
BIN
mods/moretrees/textures/moretrees_cedar_sapling.png
Normal file
After Width: | Height: | Size: 202 B |
BIN
mods/moretrees/textures/moretrees_cedar_trunk.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
mods/moretrees/textures/moretrees_cedar_trunk_top.png
Normal file
After Width: | Height: | Size: 451 B |
BIN
mods/moretrees/textures/moretrees_cedar_wood.png
Normal file
After Width: | Height: | Size: 648 B |
BIN
mods/moretrees/textures/moretrees_coconut.png
Normal file
After Width: | Height: | Size: 963 B |
BIN
mods/moretrees/textures/moretrees_coconut_0.png
Normal file
After Width: | Height: | Size: 877 B |
BIN
mods/moretrees/textures/moretrees_coconut_1.png
Normal file
After Width: | Height: | Size: 429 B |
BIN
mods/moretrees/textures/moretrees_coconut_2.png
Normal file
After Width: | Height: | Size: 1,009 B |
BIN
mods/moretrees/textures/moretrees_coconut_milk.png
Normal file
After Width: | Height: | Size: 227 B |
BIN
mods/moretrees/textures/moretrees_coconut_milk_inv.png
Normal file
After Width: | Height: | Size: 199 B |
BIN
mods/moretrees/textures/moretrees_date.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
mods/moretrees/textures/moretrees_date_nut_bar.png
Normal file
After Width: | Height: | Size: 685 B |
BIN
mods/moretrees/textures/moretrees_date_nut_batter.png
Normal file
After Width: | Height: | Size: 608 B |
BIN
mods/moretrees/textures/moretrees_date_nut_cake.png
Normal file
After Width: | Height: | Size: 695 B |
BIN
mods/moretrees/textures/moretrees_date_nut_snack.png
Normal file
After Width: | Height: | Size: 450 B |
BIN
mods/moretrees/textures/moretrees_date_palm_leaves.png
Normal file
After Width: | Height: | Size: 757 B |
BIN
mods/moretrees/textures/moretrees_date_palm_sapling.png
Normal file
After Width: | Height: | Size: 261 B |
BIN
mods/moretrees/textures/moretrees_date_palm_trunk.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
mods/moretrees/textures/moretrees_date_palm_trunk_top.png
Normal file
After Width: | Height: | Size: 673 B |
BIN
mods/moretrees/textures/moretrees_date_palm_wood.png
Normal file
After Width: | Height: | Size: 735 B |
BIN
mods/moretrees/textures/moretrees_dates.png
Normal file
After Width: | Height: | Size: 9.2 KiB |
BIN
mods/moretrees/textures/moretrees_dates_f0.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
mods/moretrees/textures/moretrees_dates_f1.png
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
mods/moretrees/textures/moretrees_dates_f2.png
Normal file
After Width: | Height: | Size: 8.9 KiB |
BIN
mods/moretrees/textures/moretrees_dates_f3.png
Normal file
After Width: | Height: | Size: 8.1 KiB |
BIN
mods/moretrees/textures/moretrees_dates_f4.png
Normal file
After Width: | Height: | Size: 9 KiB |
BIN
mods/moretrees/textures/moretrees_dates_fn.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
mods/moretrees/textures/moretrees_dates_m0.png
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
mods/moretrees/textures/moretrees_dates_n.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
mods/moretrees/textures/moretrees_fir_cone.png
Normal file
After Width: | Height: | Size: 244 B |
BIN
mods/moretrees/textures/moretrees_fir_leaves.png
Normal file
After Width: | Height: | Size: 205 B |
BIN
mods/moretrees/textures/moretrees_fir_leaves_bright.png
Normal file
After Width: | Height: | Size: 205 B |
BIN
mods/moretrees/textures/moretrees_fir_nuts.png
Normal file
After Width: | Height: | Size: 361 B |
BIN
mods/moretrees/textures/moretrees_fir_sapling.png
Normal file
After Width: | Height: | Size: 166 B |
BIN
mods/moretrees/textures/moretrees_fir_trunk.png
Normal file
After Width: | Height: | Size: 753 B |
BIN
mods/moretrees/textures/moretrees_fir_trunk_top.png
Normal file
After Width: | Height: | Size: 924 B |
BIN
mods/moretrees/textures/moretrees_fir_wood.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
mods/moretrees/textures/moretrees_jungletree_leaves_green.png
Normal file
After Width: | Height: | Size: 201 B |
BIN
mods/moretrees/textures/moretrees_jungletree_leaves_red.png
Normal file
After Width: | Height: | Size: 201 B |
BIN
mods/moretrees/textures/moretrees_jungletree_leaves_yellow.png
Normal file
After Width: | Height: | Size: 201 B |
BIN
mods/moretrees/textures/moretrees_oak_leaves.png
Normal file
After Width: | Height: | Size: 730 B |
BIN
mods/moretrees/textures/moretrees_oak_sapling.png
Normal file
After Width: | Height: | Size: 172 B |
BIN
mods/moretrees/textures/moretrees_oak_trunk.png
Normal file
After Width: | Height: | Size: 998 B |
BIN
mods/moretrees/textures/moretrees_oak_trunk_top.png
Normal file
After Width: | Height: | Size: 519 B |
BIN
mods/moretrees/textures/moretrees_oak_wood.png
Normal file
After Width: | Height: | Size: 618 B |