Add decoration design

Bram van den Heuvel 2024-04-30 12:13:40 +02:00
parent 2809346af8
commit 1c74ea3c60
2 changed files with 187 additions and 8 deletions

111
API.md
View File

@ -14,6 +14,9 @@ For shapes, the following functions are available:
- `noordstar_caves.unregister_shape(name)` Remove a defined cave shape
- `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:
```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
-- 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_min = -31000,
-- Upper and lower limits of the cave biome.
@ -160,3 +157,105 @@ The biomes are defined as follows:
-- 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 inverted for decorations on the ceiling.
-- Ignored by 'y_min' and 'y_max' checks, which always refer to the
-- 'place_on' node.
}
```

View File

@ -92,6 +92,9 @@ noordstar_caves =
-- A public list of all registered biomes
, registered_biomes = {}
-- A public list of all registered decorations
, registered_decorations = {}
-- A public list of all registered shapes
, registered_shapes = {}
@ -102,6 +105,11 @@ function noordstar_caves.clear_registered_biomes()
noordstar_caves.registered_biomes = {}
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
function noordstar_caves.clear_registered_shapes()
noordstar_caves.registered_shapes = {}
@ -116,6 +124,15 @@ function noordstar_caves.register_biome(def)
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
function noordstar_caves.register_shape(def)
local d = internal.clean_shape_def(def)
@ -257,6 +274,63 @@ function internal.clean_biome_def(def)
return d
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,
}
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("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.
function internal.clean_shape_def(def)
if type(def.name) ~= "string" then
@ -649,7 +723,13 @@ function internal.generate_caves(data, minp, maxp)
elseif nt == internal.node_types.air then
place("air")
elseif nt == internal.node_types.floor_deco then
-- TODO: Place registered decoration
for _, deco in ipairs(noordstar_caves.registered_decorations) do
if deco.place_on ~= "floor" then
elseif math.random() > deco.fill_ratio then
else
-- TODO: Check for biome
end
end
else
-- Find appropriate biome
local heat = heat_points:get_index(i)
@ -684,7 +764,7 @@ end
-- Get the noise params for the cave biome temperature.
function internal.heat_noise_params()
return {
return {
offset = 50,
scale = 50,
spread = internal.biome_size,