From 1392ff483d234adf7b5a01be7526fb641ba17f53 Mon Sep 17 00:00:00 2001 From: Bram van den Heuvel Date: Tue, 30 Apr 2024 12:13:40 +0200 Subject: [PATCH] Add decoration design --- API.md | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- init.lua | 84 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 187 insertions(+), 8 deletions(-) diff --git a/API.md b/API.md index bce791c..0c92512 100644 --- a/API.md +++ b/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.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. +} +``` diff --git a/init.lua b/init.lua index e60370b..dc3fa98 100644 --- a/init.lua +++ b/init.lua @@ -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,