write something there

This commit is contained in:
N-Nachtigal 2025-05-04 16:01:41 +02:00
commit b4b6c08f4f
8546 changed files with 309825 additions and 0 deletions

9
mods/abdecor/LICENSE Normal file
View file

@ -0,0 +1,9 @@
MIT License
Copyright © 2023 EmptyStar <https://github.com/EmptyStar>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

92
mods/abdecor/README.md Normal file
View file

@ -0,0 +1,92 @@
Advance Biome Decoration API
============================
Create advanced, complex biome decorations with the Advanced Biome Decoration API! While the internal Minetest biome API can be used to create many types of biome decorations, it has some limitations. Standard biome decorations cannot:
- Place wallmounted decorations on walls
- Check for complex patterns of nodes to determine placement, e.g., checking multiple nodes high above the ground
- Create structures that vary placement based on arbitrary conditions, e.g., place different colors of nodes based on whether x/z coordinates are odd or even
In order to facilitate more complex decorations, the Advanced Biome Decoration API uses a powerful and performant mechanism for targeting advanced decorations to the environment. The advanced decoration process works like so:
1. Call `abdecor.register_advanced_decoration(...)` to register an advanced decoration
2. Self-destructing 'marker nodes' are placed to mark locations where advanced decorations should be generated
3. The biome API gennotify mechanism is used to identify the marker nodes during map generation
4. An advanced decoration function (supplied during registration) is called for each marker node to generate the advanced decoration at each marker location
5. All advanced decorations are written to the map and rendered in the world
For working examples of what this API can do, see the [Advanced Biome Decoration Modpack](https://github.com/EmptyStar/abdecor_modpack) for reference.
API
---
Advanced decorations are created via `abdecor.register_advanced_decoration(name, definition)`. This function returns `true` when an advanced decoration registration is successful and `false` if the registration was not successful. If the function returns `false`, check your debug.txt file to see why it rejected registration and make any adjustments as necessary.
This function's parameters and definition schema are explained in the sections below.
### `name`
This is a simple string used to name the decoration. It should contain only `[a-zA-Z-0-9_]`. The name must be unique across all mods that use this API, so it is advised to do some simple namespacing, e.g., `mymod_mydecor1`.
### `definition`
This is a table that defines an advanced decoration. It must have certain keys that define how it is rendered in the world, plus other optional values that are important for certain use cases. Each key of the definition schema is described in detail below.
#### `target`
This is a table that represents a partial decoration definition as described in [the decoration definition section of the Minetest API docs](https://github.com/minetest/minetest/blob/cf5add14728f6f00eec0cc8221050ba91e6a9646/doc/lua_api.txt#L9140). This decoration definition is used to place mapgen nodes for your decoration in the environment, so you should try to target nodes in the environment that are closest to where you want to generate your advanced decoration.
The following decoration definition fields are set/overridden by this API and therefore should not be specified:
- `deco_type = "simple"`
- `name = <internal value>`
- `decoration = <internal marker node value>`
#### `fn`
This is a function that is called for each marker node that is placed in the environment for your advanced decoration. It is responsible for actually checking the surrounding nodes and placing nodes according to how they should be placed in the current mapchunk. It is effectively the implementation of your advanced decoration.
This function gets called for each advanced decoration that can be placed and gets passed a table with the following keys defined for each call:
- `pos`: This is a table that represents the absolute position of the current decoration in the form of `{ x = <int>, y = <int>, z = <int> }`.
- `voxelarea`: This is a [VoxelArea](https://github.com/minetest/minetest/blob/cf5add14728f6f00eec0cc8221050ba91e6a9646/doc/lua_api.txt#L4495) that represents the area of the current mapchunk being generated. It can be used to index the following two parameters.
- `data`: This is a flat [VoxelManip](https://github.com/minetest/minetest/blob/cf5add14728f6f00eec0cc8221050ba91e6a9646/doc/lua_api.txt#L4231) table that holds the node data for the current mapchunk being generated. This table can be read/written like any usual mapgen VoxelManip table.
- `param2`: This optional parameter is also a flat VoxelManip table, but it instead holds the [param2](https://github.com/minetest/minetest/blob/cf5add14728f6f00eec0cc8221050ba91e6a9646/doc/lua_api.txt#L1032) values for the nodes in the current mapchunk. This can be useful for rotating nodes, placing wallmounted nodes, etc. The value of this key is `nil` unless `param2 = true` is specified for the decoration's flags.
- `place_schematic`: This optional key is a function that passes through parameters to [`minetest.place_schematic_on_vmanip`](https://github.com/minetest/minetest/blob/cf5add14728f6f00eec0cc8221050ba91e6a9646/doc/lua_api.txt#L6285) for the current mapchunk being generated in order to place schematics in the current mapchunk. The value of this key is `nil` unless `schematic = true` is specified for the decoration's flags. The function takes a single table argument with the following keys:
- `pos`: The position at which to place the schematic. Must be a table in the form of `{ x = <int>, y = <int>, z = <int> }`. This value is required.
- `schematic`: The schematic to place. This value must be a [schematic specifier](https://github.com/minetest/minetest/blob/cf5add14728f6f00eec0cc8221050ba91e6a9646/doc/lua_api.txt#L4179). This value is required.
- `rotation`: Which direction the schematic should face. Optional value that defaults to `"random"`
- `replacements`: Which nodes to replace with other nodes in the schematic. Optional value that defaults to `{}`
- `force_placement`: Boolean flag that determines whether to force placement of the schematic if it would otherwise collide with nodes that are already placed. Optional value that defaults to `false`.
- `flags`: A comma-delimited string containing any of `place_center_x`, `place_center_y`, and `place_center_z`. Optional value that defaults to `""`
- `calc_lighting`: This key is a function that passes through its exact parameters to [`VoxelManip.calc_lighting`](https://github.com/minetest/minetest/blob/cf5add14728f6f00eec0cc8221050ba91e6a9646/doc/lua_api.txt#L4479)
- `index2d`: This key is a function that indexes a two-dimensional flat array for the current mapchunk such as the array returned from `minetest.get_mapgen_object("heatmap")` and other such functions. This function takes either two integer arguments that represent x/z coordinates, or a single table argument in the form of `{ x = <int>, z = <int> }` (`y` value is optional/unused).
- `minp`: This is the `minp` value for the current [`minetest.register_on_generated(...)`](https://github.com/minetest/minetest/blob/cf5add14728f6f00eec0cc8221050ba91e6a9646/doc/lua_api.txt#L5185) call.
- `maxp`: This is the `maxp` value for the current [`minetest.register_on_generated(...)`](https://github.com/minetest/minetest/blob/cf5add14728f6f00eec0cc8221050ba91e6a9646/doc/lua_api.txt#L5185) call.
- `seed`: This is the `blockseed` value for the current [`minetest.register_on_generated(...)`](https://github.com/minetest/minetest/blob/cf5add14728f6f00eec0cc8221050ba91e6a9646/doc/lua_api.txt#L5185) call.
This function does not directly interact with the VoxelManip object returned by `minetest.get_mapgen_object("voxelmanip")` and instead will only modify the current mapchunk using the values described above which are managed by the Advanced Biome Decoration API. Attempting to access the VoxelManip for the current mapchunk directly inside of this function is undefined and not recommended under any circumstances.
This function may be called many times per mapchunk depending on how common your advanced decorations are, so this function should be made as efficient as possible as not to slow down mapgen:
- Use the supplied VoxelArea and its `ystride`/`zstride` values to index the supplied `data`/`param2` arrays for best read/write performance.
- Make use of `return` to exit your decoration function quickly if an advanced decoration is not suitable at a given target location.
- Cache the results of lookup operations outside of your decoration function, such as calls to `minetest.get_content_id(...)` or `minetest.get_modpath(...)`.
#### `flags`
This optional parameter is a table that defines flags that each determine any special needs for an advanced decoration. Its keys and values are simple boolean flags that work as follows:
- `param2`: Whether or not to load/use the VoxelManip param2 data for the current mapchunk. This should be set if your advanced decoration function needs access to param2 data. If your decoration does not use param2, then this flag should remain unset for better performance. Defaults to `false`.
- `liquid`: Whether or not your advanced decoration function manipulates liquids. If set, then `VoxelManip.update_liquids()` is called before writing the values back to the mapchunk. This ensures that generated liquids flow as expected. Set if your advanced decoration function places liquids, else leave unset for better performance. Defaults to `false`.
- `schematic`: Whether or not your advanced decoration function may place schematics. If set, then the `place_schematic` function described above is made available to your advanced decoration function for the purpose of placing schematics. Defaults to `false`.
For clarity, the default flags table looks like this:
```lua
{
param2 = false, -- do not load param2 data
liquid = false, -- do not update liquids
schematic = false, -- decoration does not place schematics
}
```

227
mods/abdecor/init.lua Normal file
View file

@ -0,0 +1,227 @@
local modpath = minetest.get_modpath("abdecor")
abdecor = {}
abdecor.registered_names = {}
abdecor.registered_advanced_decorations = {}
abdecor.register_advanced_decoration = function(name, def)
-- Ensure that all necessary arguments are defined
if not name or not def.target or not def.fn then
minetest.warn("[abdecor] Advanced decoration '" .. (name or "???") .. "' was not provided with all necessary values.")
return false
end
-- Ensure that the name isn't already in use
local mapgen = nil
if abdecor.registered_names[name] then
minetest.warn("[abdecor] Advanced decoration '" .. name .. "' was already registered.")
return false
else
mapgen = {}
abdecor.registered_names[name] = true
end
-- Check for all_floors + all_ceilings flags which is unsupported due to
-- undefined mapgen node erasure
local is_ceiling = false
local is_water_surface = false
def.target.flags = def.target.flags or ""
if def.target.flags and def.target.flags:find("all_floors") and def.target.flags:find("all_ceilings") then
minetest.warn("[abdecor] Advanced decoration '" .. name .. "' specifies all_floors and all_ceilings which the abdecor API does not support.")
return false
else
is_ceiling = def.target.flags:find("all_ceilings") and true or false
is_water_surface = def.target.flags:find("water_surface") and true or false
end
-- Register node for targeted mapgen node
local mapgen_node_name = "abdecor:" .. name .. "_marker"
minetest.register_node(":" .. mapgen_node_name,{
drawtype = "airlike",
sunlight_propagates = true,
walkable = false,
pointable = true,
diggable = false,
climbable = false,
buildable_to = true,
floodable = false,
groups = { not_in_creative_inventory = 1 },
})
-- Register injected decor for targeted mapgen node placement
def.target.deco_type = "simple"
def.target.name = "abdecor:" .. name .. "_decoration"
def.target.decoration = mapgen_node_name
minetest.register_decoration(def.target)
local decoration_id = minetest.get_decoration_id(def.target.name)
minetest.set_gen_notify({ decoration = true },{decoration_id})
mapgen.decoration_id = "decoration#" .. decoration_id
abdecor.registered_advanced_decorations[mapgen.decoration_id] = mapgen
-- Compute decoration placement offset for automatic erasure during mapgen
mapgen.offset = (is_water_surface and 0 or 1) * (is_ceiling and -1 or 1) + (def.target.place_offset_y or 0)
-- Capture placement function and voxelmanip flags for later use
mapgen.fn = def.fn
if not def.flags then
def.flags = {}
end
if def.flags.param2 == nil then
def.flags.param2 = false
end
if def.flags.liquid == nil then
def.flags.liquid = false
end
if def.flags.schematic == nil then
def.flags.schematic = false
end
mapgen.flags = def.flags
-- Success!
return true
end
-- Schematic placement helper functions
abdecor._place_schematic_check = function(args)
-- Fail or set defaults for missing arguments
if not args.pos or not args.schematic then
return nil -- fail
end
args.rotation = args.rotation or "random"
args.replacements = args.replacements or {}
args.force_placement = (args.force_placement == nil) and false or true
args.flags = args.flags or ""
-- Arguments are good
return true
end
-- Register targeted mapgen generation
local vdata = {}
local vparam2 = {}
minetest.register_on_generated(function(minp, maxp, seed)
-- Lazy initializers for mapgen
local mapgen = {}
local is_mapgen_init = false
local function mapgen_init()
if not is_mapgen_init then
mapgen.vm, mapgen.emin, mapgen.emax = minetest.get_mapgen_object("voxelmanip")
mapgen.va = VoxelArea:new({MinEdge = mapgen.emin, MaxEdge = mapgen.emax})
is_mapgen_init = true
end
end
local is_vm_data_init = false
local function vm_data_init()
mapgen_init()
if not is_vm_data_init then
mapgen.vm:get_data(vdata)
is_vm_data_init = true
end
end
local is_vm_param2_init = false
local function vm_param2_init()
mapgen_init()
if not is_vm_param2_init then
mapgen.vm:get_param2_data(vparam2)
is_vm_param2_init = true
end
end
local is_schematic_init = false
local function schematic_init()
if not is_schematic_init then
mapgen.place_schematic = function(args)
mapgen.vm:set_data(vdata)
local retval = abdecor._place_schematic_check(args) and minetest.place_schematic_on_vmanip(mapgen.vm,args.pos,args.schematic,args.rotation,args.replacements,args.force_placement,args.flags)
if retval then
mapgen.vm:get_data(vdata)
end
return retval
end
is_schematic_init = true
end
end
mapgen.calc_lighting = function(p1,p2,propagate_shadow)
return mapgen.vm:calc_lighting(p1,p2,propagate_shadow)
end
local is_liquid = false
-- Place any targeted decorations that were generated
local gennotify = minetest.get_mapgen_object("gennotify")
for decoration_id,decorations in pairs(gennotify) do
local decoration = abdecor.registered_advanced_decorations[decoration_id]
if decoration then
-- Initialize vm data
vm_data_init()
-- Initialize param2 data if needed
if decoration.flags.param2 then
vm_param2_init()
end
-- Initialize schematic placement function if needed
if decoration.flags.schematic then
schematic_init()
end
-- Note liquid status
if decoration.flags.liquid then
is_liquid = true
end
-- Erase dummy mapgen nodes and process decorations
for i = 1, #decorations do
local pos = decorations[i]
vdata[mapgen.va:index(pos.x,pos.y + decoration.offset,pos.z)] = minetest.CONTENT_AIR
decoration.fn({
pos = pos,
voxelarea = mapgen.va,
data = vdata,
param2 = vparam2,
minp = minp,
maxp = maxp,
seed = seed,
place_schematic = mapgen.place_schematic,
calc_lighting = mapgen.calc_lighting,
index2d = function(x,z) -- (portions of this function © FaceDeer 2018, licensed MIT, copied from https://github.com/minetest-mods/mapgen_helper/blob/2521562a42472271d9d761f2b1e84ead59250a14/noise_manager.lua)
if type(x) == "table" then -- accept x/y/z pos table
z = x.z
x = x.x
end
return x - minp.x +
(maxp.x - minp.x + 1)
*(z - minp.z)
+ 1
end,
})
end
end
end
-- Write data back to voxelmanip if necessary
if is_mapgen_init then
if is_vm_data_init then
mapgen.vm:set_data(vdata)
end
if is_vm_param2_init then
mapgen.vm:set_param2_data(vparam2)
end
if is_liquid then
mapgen.vm:update_liquids()
end
if is_vm_data_init or is_vm_param2_init then
mapgen.vm:write_to_map()
end
end
end)

3
mods/abdecor/mod.conf Normal file
View file

@ -0,0 +1,3 @@
name = abdecor
title = Advanced Biome Decoration API
author = EmptyStar