Compare commits
	
		
			7 Commits 
		
	
	
		
			fe881845ce
			...
			7d5a1a4dc9
		
	
	| Author | SHA1 | Date | 
|---|---|---|
|  | 7d5a1a4dc9 | |
|  | b1dbac00d3 | |
|  | 18fecc7eae | |
|  | 312ab54a46 | |
|  | 39406abfaf | |
|  | 5005ae7d32 | |
|  | 1c74ea3c60 | 
							
								
								
									
										127
									
								
								API.md
								
								
								
								
							
							
						
						
									
										127
									
								
								API.md
								
								
								
								
							|  | @ -14,6 +14,9 @@ For shapes, the following functions are available: | ||||||
| - `noordstar_caves.unregister_shape(name)` Remove a defined cave shape | - `noordstar_caves.unregister_shape(name)` Remove a defined cave shape | ||||||
| - `noordstar_caves.clear_registered_shapes()` Remove all known cave shapes | - `noordstar_caves.clear_registered_shapes()` Remove all known cave shapes | ||||||
| 
 | 
 | ||||||
|  | Generally, it is recommended to keep the number of cave shapes below 100. | ||||||
|  | A good number of shapes is 10 for diversity but performance. | ||||||
|  | 
 | ||||||
| The shapes are defined as follows: | The shapes are defined as follows: | ||||||
| 
 | 
 | ||||||
| ```lua | ```lua | ||||||
|  | @ -132,12 +135,6 @@ The biomes are defined as follows: | ||||||
|     -- Keep in mind that cave biomes can blend, so it might not always look |     -- Keep in mind that cave biomes can blend, so it might not always look | ||||||
|     -- very smooth. |     -- very smooth. | ||||||
| 
 | 
 | ||||||
|     node_shell = "foo:permafrost", |  | ||||||
|     depth_shell = 3, |  | ||||||
|     -- Node forming a layer around the entire cave and thickness of this layer |  | ||||||
|     -- You can make the depth as high as you want, but raising it past 16 |  | ||||||
|     -- might cause hard cut-offs at chunk edges. |  | ||||||
| 
 |  | ||||||
|     y_max = -100, |     y_max = -100, | ||||||
|     y_min = -31000, |     y_min = -31000, | ||||||
|     -- Upper and lower limits of the cave biome. |     -- Upper and lower limits of the cave biome. | ||||||
|  | @ -160,3 +157,121 @@ The biomes are defined as follows: | ||||||
|     -- but can exceed these values. |     -- but can exceed these values. | ||||||
| } | } | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
|  | ## Decorations | ||||||
|  | 
 | ||||||
|  | As a final part of generating the caves, decorations can be added to add unique | ||||||
|  | structures to cave biomes. | ||||||
|  | 
 | ||||||
|  | For decorations, the following functions are defined: | ||||||
|  | 
 | ||||||
|  | - `noordstar_caves.register_decoration(decoration def)` Define a new cave decoration | ||||||
|  | - `noordstar_caves.clear_registered_decorations()` Remove all known cave decorations | ||||||
|  | 
 | ||||||
|  | The decorations are defined as follows: | ||||||
|  | 
 | ||||||
|  | ```lua | ||||||
|  | { | ||||||
|  |     deco_type = "simple", | ||||||
|  |     -- Type. "simple" or "schematic" supported | ||||||
|  | 
 | ||||||
|  |     place_on = "floor", | ||||||
|  |     -- Side of the cave to place the decoration on. "floor" or "ceiling" supported | ||||||
|  | 
 | ||||||
|  |     fill_ratio = 0.02, | ||||||
|  |     -- Percentage of surface nodes on which this decoration will spawn | ||||||
|  | 
 | ||||||
|  |     biomes = { "noordstar_caves:tundra", "foo:desert" }, | ||||||
|  |     -- List of (cave!) biomes that this decoration will spawn in. Occurs in all | ||||||
|  |     -- biomes if this is omitted. | ||||||
|  | 
 | ||||||
|  |     y_min = -31000, | ||||||
|  |     y_max =  31000, | ||||||
|  |     -- Lower and upper limits for decoration (inclusive). | ||||||
|  |     -- These parameters refer to the Y-coordinate of the node where it is | ||||||
|  |     -- originally chosen to be placed. | ||||||
|  | 
 | ||||||
|  |     ----- Simple-type parameters | ||||||
|  | 
 | ||||||
|  |     decoration = "foo:grass", | ||||||
|  |     -- The node name used as the decoration. | ||||||
|  |     -- If instead a list of strings, a randomly selected node from the list | ||||||
|  |     -- is placed as the decoration. | ||||||
|  | 
 | ||||||
|  |     height = 1, | ||||||
|  |     -- Decoration height in nodes. | ||||||
|  |     -- If height_max is not 0, this is the lower limit of a randomly selected | ||||||
|  |     -- height. | ||||||
|  |     -- Height can not be over 16. | ||||||
|  | 
 | ||||||
|  |     height_max = 0, | ||||||
|  |     -- Upper limit of the randomly selected height. | ||||||
|  |     -- If absent, the parameter `height` is used as a constant. | ||||||
|  |     -- Max height will be capped at 16. | ||||||
|  | 
 | ||||||
|  |     place_offset_y = 0, | ||||||
|  |     -- Y offset of the decoration base node relative to the standard base node | ||||||
|  |     -- position. | ||||||
|  |     -- Can be positive or negative. Default is 0. | ||||||
|  | 
 | ||||||
|  |     ----- Schematic-type parameters | ||||||
|  | 
 | ||||||
|  |     schematic = "foobar.mts", | ||||||
|  |     -- If schematic is a string, it is the filepath relative to the correct | ||||||
|  |     -- working directory of the specified Minetest schematic file. | ||||||
|  |     -- Could also be the ID of a previously registered schematic. | ||||||
|  | 
 | ||||||
|  |     schematic = { | ||||||
|  |         size = {x = 4, y = 6, z = 4}, | ||||||
|  |         data = { | ||||||
|  |             {name = "default:cobble", param1 = 255, param2 = 0}, | ||||||
|  |             {name = "default:dirt_with_grass", param1 = 255, param2 = 0}, | ||||||
|  |             {name = "air", param1 = 255, param2 = 0}, | ||||||
|  |               ... | ||||||
|  |         }, | ||||||
|  |         yslice_prob = { | ||||||
|  |             {ypos = 2, prob = 128}, | ||||||
|  |             {ypos = 5, prob = 64}, | ||||||
|  |               ... | ||||||
|  |         }, | ||||||
|  |     }, | ||||||
|  |     -- Alternative schematic specification by supplying a table. The fields | ||||||
|  |     -- size and data are mandatory whereas yslice_prob is optional. | ||||||
|  |     -- See 'schematic specifier' in the Minetest Lua API documentation. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     replacements = {["oldname"] = "convert_to", ...}, | ||||||
|  |     -- Map of node names to replace in the schematic after reading it. | ||||||
|  | 
 | ||||||
|  |     flags = "place_center_x, place_center_y, place_center_z", | ||||||
|  |     -- Flags for schematic decorations. See 'Schematic attributes'. | ||||||
|  | 
 | ||||||
|  |     rotation = "90", | ||||||
|  |     -- Rotation can be "0", "90", "180", "270", or "random" | ||||||
|  | 
 | ||||||
|  |     place_offset_y = 0, | ||||||
|  |     -- If the flag 'place_center_y' is set this parameter is ignored. | ||||||
|  |     -- Y offset of the schematic base node layer relative to the 'place_on' | ||||||
|  |     -- node. | ||||||
|  |     -- Can be positive or negative. Default is 0. | ||||||
|  |     -- Effect is NOT inverted for decorations on the ceiling. | ||||||
|  |     -- Ignored by 'y_min' and 'y_max' checks, which always refer to the | ||||||
|  |     -- 'place_on' node. | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ## Ores | ||||||
|  | 
 | ||||||
|  | This mod does not support adding ores to the caves, as this is a feature that | ||||||
|  | is already well-supported by the Minetest Lua API and doesn't need a mod like | ||||||
|  | this. | ||||||
|  | 
 | ||||||
|  | ## Misc | ||||||
|  | 
 | ||||||
|  | In case you wish to do a few other operations, here's a few other functions | ||||||
|  | that might be helpful to you: | ||||||
|  | 
 | ||||||
|  | - `noordstar_caves.set_world_height(h)` Set the world's height to a given number. | ||||||
|  | 
 | ||||||
|  | This feature is currently only supported in VoxeLibre. Contributions that help | ||||||
|  | change the world depth in other games, are very welcome. | ||||||
|  |  | ||||||
							
								
								
									
										420
									
								
								init.lua
								
								
								
								
							
							
						
						
									
										420
									
								
								init.lua
								
								
								
								
							|  | @ -92,6 +92,9 @@ noordstar_caves = | ||||||
|     -- A public list of all registered biomes |     -- A public list of all registered biomes | ||||||
|     , registered_biomes = {} |     , registered_biomes = {} | ||||||
| 
 | 
 | ||||||
|  |     -- A public list of all registered decorations | ||||||
|  |     , registered_decorations = {} | ||||||
|  | 
 | ||||||
|     -- A public list of all registered shapes |     -- A public list of all registered shapes | ||||||
|     , registered_shapes = {} |     , registered_shapes = {} | ||||||
| 
 | 
 | ||||||
|  | @ -102,6 +105,11 @@ function noordstar_caves.clear_registered_biomes() | ||||||
|     noordstar_caves.registered_biomes = {} |     noordstar_caves.registered_biomes = {} | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
|  | -- Remove all registered decorations and start with a clean slate | ||||||
|  | function noordstar_caves.clear_registered_decoration() | ||||||
|  |     noordstar_caves.registered_decorations = {} | ||||||
|  | end | ||||||
|  | 
 | ||||||
| -- Remove all registered shapes and start with a clean slate | -- Remove all registered shapes and start with a clean slate | ||||||
| function noordstar_caves.clear_registered_shapes() | function noordstar_caves.clear_registered_shapes() | ||||||
|     noordstar_caves.registered_shapes = {} |     noordstar_caves.registered_shapes = {} | ||||||
|  | @ -116,6 +124,15 @@ function noordstar_caves.register_biome(def) | ||||||
|     end |     end | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
|  | -- Register a new cave decoration | ||||||
|  | function noordstar_caves.register_decoration(def) | ||||||
|  |     local d = internal.clean_deco_def(def) | ||||||
|  | 
 | ||||||
|  |     if d then | ||||||
|  |         table.insert(noordstar_caves.registered_decorations, d) | ||||||
|  |     end | ||||||
|  | end | ||||||
|  | 
 | ||||||
| -- Register a new cave shape | -- Register a new cave shape | ||||||
| function noordstar_caves.register_shape(def) | function noordstar_caves.register_shape(def) | ||||||
|     local d = internal.clean_shape_def(def) |     local d = internal.clean_shape_def(def) | ||||||
|  | @ -257,6 +274,64 @@ function internal.clean_biome_def(def) | ||||||
|     return d |     return d | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
|  | -- Clean the user input on a decoration definition before inserting it. | ||||||
|  | function internal.clean_deco_def(def) | ||||||
|  |     if def.deco_type ~= "simple" and def.deco_type ~= "schematic" then | ||||||
|  |         return nil | ||||||
|  |     end | ||||||
|  |     if def.deco_type == "simple" and type(def.decoration) ~= "string" then | ||||||
|  |         return nil | ||||||
|  |     end | ||||||
|  |     if def.deco_type == "schematic" then | ||||||
|  |         if type(def.schematic) == "string" then | ||||||
|  |         elseif type(def.schematic) == "table" then | ||||||
|  |         else | ||||||
|  |             return nil | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  |     if type(def.fill_ratio) ~= "number" then | ||||||
|  |         return nil | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     local d = { | ||||||
|  |         deco_type = def.deco_type, | ||||||
|  |         decoration = def.decoration, | ||||||
|  |         schematic = def.schematic, | ||||||
|  |         fill_ratio = def.fill_ratio, | ||||||
|  |         biomes = def.biomes, | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if def.place_on == "floor" or def.place_on == "ceiling" then | ||||||
|  |         d.place_on = def.place_on | ||||||
|  |     else | ||||||
|  |         d.place_on = "floor" | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     local function place(key, t, default) | ||||||
|  |         if type(def[key]) == t then | ||||||
|  |             d[key] = def[key] | ||||||
|  |         else | ||||||
|  |             d[key] = default | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     place("y_min", "number", internal.world_minp.y) | ||||||
|  |     place("y_max", "number", internal.world_maxp.y) | ||||||
|  |     place("height_max", "number", 0) | ||||||
|  |     place("height", "number", 1) | ||||||
|  |     place("place_offset_y", "number", 0) | ||||||
|  |     place("replacements", "table", {}) | ||||||
|  |     place("flags", "string", "place_center_x,place_center_z") | ||||||
|  |     place("rotation", "string", "0") | ||||||
|  | 
 | ||||||
|  |     d.height     = math.max(d.height    ,  0) | ||||||
|  |     d.height     = math.min(d.height    , 16) | ||||||
|  |     d.height_max = math.max(d.height_max,  0) | ||||||
|  |     d.height_max = math.min(d.height_max, 16) | ||||||
|  | 
 | ||||||
|  |     return d | ||||||
|  | end | ||||||
|  | 
 | ||||||
| -- Clean the user input on a shape definition before inserting it. | -- Clean the user input on a shape definition before inserting it. | ||||||
| function internal.clean_shape_def(def) | function internal.clean_shape_def(def) | ||||||
|     if type(def.name) ~= "string" then |     if type(def.name) ~= "string" then | ||||||
|  | @ -292,16 +367,18 @@ function internal.clean_shape_def(def) | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| -- Get the most nearby cave biome | -- Get the most nearby cave biome | ||||||
| function internal.closest_cave_biome(heat, humidity) | function internal.closest_cave_biome(heat, humidity, pos) | ||||||
|     local biome = internal.default_biome() |     local biome = internal.default_biome() | ||||||
|     local d = internal.biome_def_distance(biome, heat, humidity) |     local d = internal.biome_def_distance(biome, heat, humidity) | ||||||
| 
 | 
 | ||||||
|     for _, def in pairs(noordstar_caves.registered_biomes) do |     for _, def in pairs(noordstar_caves.registered_biomes) do | ||||||
|         local new_d = internal.biome_def_distance(def, heat, humidity) |         if internal.is_valid_pos(pos, def.minp, def.maxp) then | ||||||
| 
 |             local new_d = internal.biome_def_distance(def, heat, humidity) | ||||||
|         if new_d <= d then |      | ||||||
|             biome = def |             if new_d <= d then | ||||||
|             d = new_d |                 biome = def | ||||||
|  |                 d = new_d | ||||||
|  |             end | ||||||
|         end |         end | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|  | @ -309,16 +386,18 @@ function internal.closest_cave_biome(heat, humidity) | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| -- Get the most nearby cave shape | -- Get the most nearby cave shape | ||||||
| function internal.closest_cave_shape(cnct, vrtcl) | function internal.closest_cave_shape(cnct, vrtcl, y) | ||||||
|     local shape = internal.default_shape() |     local shape = internal.default_shape() | ||||||
|     local d = internal.shape_def_distance(shape, cnct, vrtcl) |     local d = internal.shape_def_distance(shape, cnct, vrtcl) | ||||||
| 
 | 
 | ||||||
|     for key, def in pairs(noordstar_caves.registered_shapes) do |     for key, def in pairs(noordstar_caves.registered_shapes) do | ||||||
|         local new_d = internal.shape_def_distance(def, cnct, vrtcl) |         if def.y_min <= y and y <= def.y_max then | ||||||
| 
 |             local new_d = internal.shape_def_distance(def, cnct, vrtcl) | ||||||
|         if new_d <= d then |      | ||||||
|             shape = def |             if new_d <= d then | ||||||
|             d = new_d |                 shape = def | ||||||
|  |                 d = new_d | ||||||
|  |             end | ||||||
|         end |         end | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|  | @ -442,7 +521,7 @@ function internal.flat_from_cave_bools(minp, maxp) | ||||||
|             local cnct = connectivity:get_index(i) |             local cnct = connectivity:get_index(i) | ||||||
|             local vrtcl = verticality:get_index(i) |             local vrtcl = verticality:get_index(i) | ||||||
| 
 | 
 | ||||||
|             local def = internal.closest_cave_shape(cnct, vrtcl) |             local def = internal.closest_cave_shape(cnct, vrtcl, pos.y) | ||||||
|              |              | ||||||
|             return def.name |             return def.name | ||||||
|     end) |     end) | ||||||
|  | @ -496,6 +575,11 @@ function internal.flat_from_node_types(bools, minp, maxp) | ||||||
|                 return nt.floor_deco |                 return nt.floor_deco | ||||||
|             end |             end | ||||||
| 
 | 
 | ||||||
|  |             if bools:get_index(i + bools.up) == false then | ||||||
|  |                 -- Block is near the ceiling | ||||||
|  |                 return nt.ceiling_deco | ||||||
|  |             end | ||||||
|  | 
 | ||||||
|             return nt.air |             return nt.air | ||||||
|         else |         else | ||||||
|             -- NOT PART OF CAVE |             -- NOT PART OF CAVE | ||||||
|  | @ -614,6 +698,8 @@ function internal.generate_caves(data, minp, maxp) | ||||||
|     -- Get cave bools |     -- Get cave bools | ||||||
|     local bools = internal.flat_from_cave_bools(bminp, bmaxp) |     local bools = internal.flat_from_cave_bools(bminp, bmaxp) | ||||||
| 
 | 
 | ||||||
|  |     timer.checkpoint("Calculate cave shape") | ||||||
|  | 
 | ||||||
|     -- Get node types |     -- Get node types | ||||||
|     local nts = internal.flat_from_node_types(bools, bminp, bmaxp) |     local nts = internal.flat_from_node_types(bools, bminp, bmaxp) | ||||||
| 
 | 
 | ||||||
|  | @ -625,13 +711,16 @@ function internal.generate_caves(data, minp, maxp) | ||||||
|         internal.humidity_noise_params(), bminp, bmaxp |         internal.humidity_noise_params(), bminp, bmaxp | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|  |     timer.checkpoint("Calculate block types & biomes") | ||||||
|  | 
 | ||||||
|     local air = minetest.get_content_id("air") |     local air = minetest.get_content_id("air") | ||||||
|  |     local schems = {} | ||||||
| 
 | 
 | ||||||
|     -- Place blocks where necessary |     -- Place blocks where necessary | ||||||
|     internal.iter_3d_area(bminp, bmaxp, function (i, pos) |     internal.iter_3d_area(bminp, bmaxp, function (i, pos) | ||||||
|          |          | ||||||
|  |         local vi = vmanip:pos_to_index(pos) | ||||||
|         local function place(name) |         local function place(name) | ||||||
|             local vi = vmanip:pos_to_index(pos) |  | ||||||
| 
 | 
 | ||||||
|             if vmanip:get_index(vi) == air then |             if vmanip:get_index(vi) == air then | ||||||
|             elseif type(name) == "string" then |             elseif type(name) == "string" then | ||||||
|  | @ -648,14 +737,12 @@ function internal.generate_caves(data, minp, maxp) | ||||||
|         elseif nt == internal.node_types.stick_edge then |         elseif nt == internal.node_types.stick_edge then | ||||||
|         elseif nt == internal.node_types.air then |         elseif nt == internal.node_types.air then | ||||||
|             place("air") |             place("air") | ||||||
|         elseif nt == internal.node_types.floor_deco then |  | ||||||
|             -- TODO: Place registered decoration |  | ||||||
|         else |         else | ||||||
|             -- Find appropriate biome |             -- Find appropriate biome | ||||||
|             local heat = heat_points:get_index(i) |             local heat = heat_points:get_index(i) | ||||||
|             local humidity = humidity_points:get_index(i) |             local humidity = humidity_points:get_index(i) | ||||||
| 
 | 
 | ||||||
|             local def = internal.closest_cave_biome(heat, humidity) |             local def = internal.closest_cave_biome(heat, humidity, pos) | ||||||
| 
 | 
 | ||||||
|             if nt == internal.node_types.floor then |             if nt == internal.node_types.floor then | ||||||
|                 place(def.node_floor) |                 place(def.node_floor) | ||||||
|  | @ -663,6 +750,41 @@ function internal.generate_caves(data, minp, maxp) | ||||||
|                 place(def.node_wall) |                 place(def.node_wall) | ||||||
|             elseif nt == internal.node_types.ceiling then |             elseif nt == internal.node_types.ceiling then | ||||||
|                 place(def.node_roof) |                 place(def.node_roof) | ||||||
|  |             elseif nt == internal.node_types.floor_deco or nt == internal.node_types.ceiling_deco then | ||||||
|  |                 local schem_placed = false | ||||||
|  |                 local appropriate_place = "floor" | ||||||
|  |                 if nt == internal.node_types.ceiling_deco then | ||||||
|  |                     appropriate_place = "ceiling" | ||||||
|  |                 end | ||||||
|  | 
 | ||||||
|  |                 if not schem_placed then | ||||||
|  |                     -- Prevent decorations from spawning in the air | ||||||
|  |                     if vmanip:get_index(vi) == air then | ||||||
|  |                         schem_placed = true | ||||||
|  |                     end | ||||||
|  |                 end | ||||||
|  | 
 | ||||||
|  |                 if not schem_placed then | ||||||
|  |                     for _, deco in ipairs(noordstar_caves.registered_decorations) do | ||||||
|  |                         if deco.place_on ~= appropriate_place then | ||||||
|  |                         elseif math.random() > deco.fill_ratio then | ||||||
|  |                         elseif not internal.is_deco_biome(deco, def.name) then | ||||||
|  |                         else | ||||||
|  |                             table.insert(schems, { pos = pos, deco = deco }) | ||||||
|  |                             schem_placed = true | ||||||
|  |                             break | ||||||
|  |                         end | ||||||
|  |                     end | ||||||
|  |                 end | ||||||
|  | 
 | ||||||
|  |                 if not schem_placed then | ||||||
|  |                     local n = "air" | ||||||
|  |                     if nt == internal.node_types.floor_deco then | ||||||
|  |                         n = def.node_dust or n | ||||||
|  |                     end | ||||||
|  |                     place(n) | ||||||
|  |                     schem_placed = true | ||||||
|  |                 end | ||||||
|             else |             else | ||||||
|                 error( |                 error( | ||||||
|                     table.concat( |                     table.concat( | ||||||
|  | @ -679,12 +801,12 @@ function internal.generate_caves(data, minp, maxp) | ||||||
|         end |         end | ||||||
|     end) |     end) | ||||||
| 
 | 
 | ||||||
|     return vmanip.arr |     return vmanip, schems | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| -- Get the noise params for the cave biome temperature. | -- Get the noise params for the cave biome temperature. | ||||||
| function internal.heat_noise_params() | function internal.heat_noise_params() | ||||||
|     return {  |     return { | ||||||
|         offset = 50, |         offset = 50, | ||||||
|         scale = 50, |         scale = 50, | ||||||
|         spread = internal.biome_size, |         spread = internal.biome_size, | ||||||
|  | @ -715,6 +837,23 @@ function internal.is_cave_node(noise, vastness) | ||||||
|     return noise > 1 - vastness |     return noise > 1 - vastness | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
|  | -- Return whether a given decoration definition can spawn in a given biome name | ||||||
|  | function internal.is_deco_biome(def, biome_name) | ||||||
|  |     if type(def.biomes) == "nil" then | ||||||
|  |         return true | ||||||
|  |     elseif type(def.biomes) == "string" then | ||||||
|  |         return def.biomes == biome_name | ||||||
|  |     elseif type(def.biomes) == "table" then | ||||||
|  |         for _, name in pairs(def.biomes) do | ||||||
|  |             if name == biome_name then | ||||||
|  |                 return true | ||||||
|  |             end | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     return false | ||||||
|  | end | ||||||
|  | 
 | ||||||
| -- Return a bool whether a position is within a given volume | -- Return a bool whether a position is within a given volume | ||||||
| function internal.is_valid_pos(pos, minp, maxp) | function internal.is_valid_pos(pos, minp, maxp) | ||||||
|     if minp.x <= pos.x and pos.x <= maxp.x then |     if minp.x <= pos.x and pos.x <= maxp.x then | ||||||
|  | @ -785,6 +924,85 @@ end | ||||||
| --     minetest.chat_send_all(os.time() .. " - " .. text) | --     minetest.chat_send_all(os.time() .. " - " .. text) | ||||||
| -- end | -- end | ||||||
| 
 | 
 | ||||||
|  | -- Place all schematic decorations into the world | ||||||
|  | function internal.place_schematic_decorations(vmanip, schems) | ||||||
|  |     for _, schem in ipairs(schems) do | ||||||
|  |         local pos  = { | ||||||
|  |             x = schem.pos.x, | ||||||
|  |             y = schem.pos.y + schem.deco.place_offset_y, | ||||||
|  |             z = schem.pos.z, | ||||||
|  |         } | ||||||
|  |         local deco = schem.deco | ||||||
|  | 
 | ||||||
|  |         if deco.deco_type ~= "schematic" then | ||||||
|  |         else | ||||||
|  |             if deco.place_on == "floor" then | ||||||
|  |                 minetest.place_schematic_on_vmanip( | ||||||
|  |                     vmanip, pos, | ||||||
|  |                     deco.schematic, deco.rotation, deco.replacement, | ||||||
|  |                     true, deco.flags | ||||||
|  |                 ) | ||||||
|  |             elseif deco.place_on == "ceiling" then | ||||||
|  |                 local h = deco.schematic | ||||||
|  | 
 | ||||||
|  |                 if type(deco.schematic) == "string" then | ||||||
|  |                     h = minetest.read_schematic(h, {}) | ||||||
|  | 
 | ||||||
|  |                     if type(h) == "nil" then | ||||||
|  |                         error("Could not find schematic! Perhaps it the filename is incorrect?") | ||||||
|  |                     end | ||||||
|  |                 end | ||||||
|  | 
 | ||||||
|  |                 h = h.size.y | ||||||
|  | 
 | ||||||
|  |                 minetest.place_schematic_on_vmanip( | ||||||
|  |                     vmanip, { x = pos.x, y = pos.y - h + 1, z = pos.z }, | ||||||
|  |                     deco.schematic, deco.rotation, deco.replacement, | ||||||
|  |                     true, deco.flags | ||||||
|  |                 ) | ||||||
|  |             else | ||||||
|  |                 error("Unknown place_on value `" .. deco.place_on .. "`") | ||||||
|  |             end | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | -- Place all simple decorations into the world | ||||||
|  | function internal.place_simple_decorations(flat, schems) | ||||||
|  |     for _, schem in ipairs(schems) do | ||||||
|  |         if schem.deco.deco_type == "simple" then | ||||||
|  |             local pos  = { | ||||||
|  |                 x = schem.pos.x, | ||||||
|  |                 y = schem.pos.y + schem.deco.place_offset_y, | ||||||
|  |                 z = schem.pos.z, | ||||||
|  |             } | ||||||
|  |             local deco = schem.deco | ||||||
|  |              | ||||||
|  |             local i = flat:pos_to_index(pos) | ||||||
|  |              | ||||||
|  |             local dir = nil | ||||||
|  |              | ||||||
|  |             if deco.place_on == "floor" then | ||||||
|  |                 dir = flat.up | ||||||
|  |             elseif deco.place_on == "ceiling" then | ||||||
|  |                 dir = flat.down | ||||||
|  |             else | ||||||
|  |                 error("Invalid place_on value `" .. deco.place_on .. "`") | ||||||
|  |             end | ||||||
|  |              | ||||||
|  |             local h_min = deco.height | ||||||
|  |             local h_max = math.max(deco.height, deco.height_max) | ||||||
|  |              | ||||||
|  |             for dy = 0, math.random(h_min, h_max) - 1, 1 do | ||||||
|  |                 local li = i + dir * dy | ||||||
|  |                  | ||||||
|  |                 flat:set_index(li, minetest.get_content_id(deco.decoration)) | ||||||
|  |             end | ||||||
|  |          | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  | end | ||||||
|  | 
 | ||||||
| -- Helper function to convert a set of coordinates to a readable string | -- Helper function to convert a set of coordinates to a readable string | ||||||
| function internal.pos_to_str(pos) | function internal.pos_to_str(pos) | ||||||
|     return "(" .. pos.x .. ", " .. pos.y .. ", " .. pos.z .. " )" |     return "(" .. pos.x .. ", " .. pos.y .. ", " .. pos.z .. " )" | ||||||
|  | @ -1006,13 +1224,25 @@ end | ||||||
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||||||
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||||||
| minetest.register_on_generated(function(minp, maxp, blockseed) | minetest.register_on_generated(function(minp, maxp, blockseed) | ||||||
|  |     timer.start() | ||||||
|  | 
 | ||||||
|  |     math.randomseed(blockseed) | ||||||
|  | 
 | ||||||
|     local vm = minetest.get_mapgen_object("voxelmanip") |     local vm = minetest.get_mapgen_object("voxelmanip") | ||||||
|     local data = vm:get_data() |     local data = vm:get_data() | ||||||
| 
 | 
 | ||||||
|     data = internal.generate_caves(data, minp, maxp) |     local flat, schems = internal.generate_caves(data, minp, maxp) | ||||||
|  |     timer.checkpoint("Place caves") | ||||||
| 
 | 
 | ||||||
|     vm:set_data(data) |     internal.place_simple_decorations(flat, schems) | ||||||
|  | 
 | ||||||
|  |     vm:set_data(flat.arr) | ||||||
|     vm:write_to_map() |     vm:write_to_map() | ||||||
|  | 
 | ||||||
|  |     internal.place_schematic_decorations(vm, schems) | ||||||
|  |     timer.checkpoint("Place decorations") | ||||||
|  | 
 | ||||||
|  |     timer.stop() | ||||||
| end) | end) | ||||||
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||||||
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||||||
|  | @ -1057,75 +1287,129 @@ noordstar_caves.register_shape({ | ||||||
|     connectivity_point = 10, |     connectivity_point = 10, | ||||||
|     verticality_point = 40, |     verticality_point = 40, | ||||||
| }) | }) | ||||||
| -- noordstar_caves.register_shape({ | noordstar_caves.register_shape({ | ||||||
| --     name = "noordstar_caves:cliffs", |     name = "noordstar_caves:cliffs", | ||||||
|      |      | ||||||
| --     noise_params = { |     noise_params = { | ||||||
| --         offset = 0.4, |         offset = 0.4, | ||||||
| --         scale = 0.5, |         scale = 0.5, | ||||||
| --         spread = { x = 20, y = 100, z = 20 }, |         spread = { x = 20, y = 100, z = 20 }, | ||||||
| --         seed = 97354, |         seed = 97354, | ||||||
| --         octaves = 4, |         octaves = 4, | ||||||
| --         persistence = 0.6, |         persistence = 0.6, | ||||||
| --         lacunarity = 2.0, |         lacunarity = 2.0, | ||||||
| --         flags = "" |         flags = "" | ||||||
| --     }, |     }, | ||||||
| 
 | 
 | ||||||
| --     func = function(pos, n) |     func = function(pos, n) | ||||||
| --         return n |         return n | ||||||
| --     end, |     end, | ||||||
| 
 | 
 | ||||||
| --     connectivity_point = 30, |     connectivity_point = 30, | ||||||
| --     verticality_point = 80, |     verticality_point = 80, | ||||||
| -- }) | }) | ||||||
| -- noordstar_caves.register_shape({ | noordstar_caves.register_shape({ | ||||||
| --     name = "noordstar_caves:donuts", |     name = "noordstar_caves:donuts", | ||||||
|      |      | ||||||
| --     noise_params = { |     noise_params = { | ||||||
| --         offset = 0.0, |         offset = 0.0, | ||||||
| --         scale = 1.0, |         scale = 1.0, | ||||||
| --         spread = { x = 30, y = 30, z = 30 }, |         spread = { x = 30, y = 30, z = 30 }, | ||||||
| --         seed = 3934, |         seed = 3934, | ||||||
| --         octaves = 1, |         octaves = 1, | ||||||
| --         persistence = 0.6, |         persistence = 0.6, | ||||||
| --         lacunarity = 2.0, |         lacunarity = 2.0, | ||||||
| --         flags = "eased" |         flags = "eased" | ||||||
| --     }, |     }, | ||||||
| 
 | 
 | ||||||
| --     func = function(pos, n) |     func = function(pos, n) | ||||||
| --         return 1 - 2 * math.abs(n)^0.5 |         return 1 - 2 * math.abs(n)^0.5 | ||||||
| --     end, |     end, | ||||||
| 
 | 
 | ||||||
| --     connectivity_point = 50, |     connectivity_point = 50, | ||||||
| --     verticality_point = 40, |     verticality_point = 40, | ||||||
| -- }) | }) | ||||||
| -- noordstar_caves.register_shape({ | noordstar_caves.register_shape({ | ||||||
| --     name = "noordstar_caves:wall", |     name = "noordstar_caves:wall", | ||||||
| 
 | 
 | ||||||
| --     func = function(pos, n) |     func = function(pos, n) | ||||||
| --         return -0.5 |         return -0.5 | ||||||
| --     end, |     end, | ||||||
| 
 | 
 | ||||||
| --     connectivity_point = 0, |     connectivity_point = 0, | ||||||
| --     verticality_point = 0, |     verticality_point = 0, | ||||||
| -- }) | }) | ||||||
| 
 | 
 | ||||||
| -- noordstar_caves.set_world_depth(-60) | -- noordstar_caves.set_world_depth(-60) | ||||||
| -- noordstar_caves.cave_vastness = function(pos) return math.abs(pos.y - 60) / 120 end | -- noordstar_caves.cave_vastness = function(pos) return math.abs(pos.y - 60) / 120 end | ||||||
| 
 | 
 | ||||||
| noordstar_caves.register_biome({ | noordstar_caves.register_biome({ | ||||||
|     name = "test", |     name = "nc:glowing_floor", | ||||||
|     node_floor = "mcl_core:crying_obsidian", |     node_floor = "mcl_core:crying_obsidian", | ||||||
|     node_wall = "mcl_core:sand", |     node_wall = "mcl_core:sand", | ||||||
|     node_roof = "mcl_ocean:sea_lantern", |     node_roof = "mcl_ocean:sea_lantern", | ||||||
|     heat_point = 0, |     node_dust = "mcl_core:snow", | ||||||
|  |     heat_point = 20, | ||||||
|     humidity_point = 0, |     humidity_point = 0, | ||||||
| }) | }) | ||||||
| noordstar_caves.register_biome({ | noordstar_caves.register_biome({ | ||||||
|     name = "test2", |     name = "nc:crazy_glowin_walls", | ||||||
|     node_floor = "mcl_amethyst:amethyst_block", |     node_floor = "mcl_amethyst:amethyst_block", | ||||||
|     node_wall = "mcl_crimson:shroomlight", |     node_wall = "mcl_crimson:shroomlight", | ||||||
|     node_roof = "mcl_colorblocks:glazed_terracotta_silver", |     node_roof = "mcl_colorblocks:glazed_terracotta_silver", | ||||||
|     heat_point = 100, |     heat_point = 100, | ||||||
|  |     humidity_point = 0, | ||||||
|  | }) | ||||||
|  | noordstar_caves.register_biome({ | ||||||
|  |     name = "nc:regular", | ||||||
|  |     heat_point = 50, | ||||||
|  |     humidity_point = 50, | ||||||
|  | }) | ||||||
|  | noordstar_caves.register_biome({ | ||||||
|  |     name = "nc:cold", | ||||||
|  |     node_dust = "mcl_core:snow", | ||||||
|  |     node_roof = "mcl_core:ice", | ||||||
|  |     heat_point = 10, | ||||||
|     humidity_point = 100, |     humidity_point = 100, | ||||||
| }) | }) | ||||||
|  | noordstar_caves.register_biome({ | ||||||
|  |     name = "nc:grass", | ||||||
|  |     node_floor = "mcl_core:dirt_with_grass", | ||||||
|  |     heat_point = 50, | ||||||
|  |     humidity_point = 70, | ||||||
|  | }) | ||||||
|  | noordstar_caves.register_biome({ | ||||||
|  |     name = "nc:dangerous_lava", | ||||||
|  |     node_floor = "mcl_core:lava_source", | ||||||
|  |     y_max = -40, | ||||||
|  |     heat_point = 100, | ||||||
|  |     humidity_point = 100, | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | noordstar_caves.register_decoration({ | ||||||
|  |     deco_type = "simple", | ||||||
|  |     place_on = "floor", | ||||||
|  |     fill_ratio = 0.01, | ||||||
|  |     decoration = "mcl_core:cactus", | ||||||
|  |     height = 3, | ||||||
|  |     height_max = 8, | ||||||
|  |     biomes = { "nc:glowing_floor" }, | ||||||
|  | }) | ||||||
|  | noordstar_caves.register_decoration({ | ||||||
|  |     deco_type = "simple", | ||||||
|  |     place_on = "ceiling", | ||||||
|  |     fill_ratio = 0.1, | ||||||
|  |     decoration = "mcl_ocean:sea_lantern", | ||||||
|  |     height = 1, | ||||||
|  |     height_max = 4, | ||||||
|  |     biomes = { "nc:crazy_glowin_walls" }, | ||||||
|  |     place_offset_y = -3, | ||||||
|  | }) | ||||||
|  | noordstar_caves.register_decoration({ | ||||||
|  |     deco_type = "schematic", | ||||||
|  |     place_on = "floor", | ||||||
|  |     fill_ratio = 0.001, | ||||||
|  |     schematic = squeak, | ||||||
|  |     rotation = "random", | ||||||
|  |     -- place_offset_y = 5, | ||||||
|  | }) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue