write something there
This commit is contained in:
commit
b4b6c08f4f
8546 changed files with 309825 additions and 0 deletions
9
mods/abdecor/LICENSE
Normal file
9
mods/abdecor/LICENSE
Normal 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
92
mods/abdecor/README.md
Normal 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
227
mods/abdecor/init.lua
Normal 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
3
mods/abdecor/mod.conf
Normal file
|
@ -0,0 +1,3 @@
|
|||
name = abdecor
|
||||
title = Advanced Biome Decoration API
|
||||
author = EmptyStar
|
Loading…
Add table
Add a link
Reference in a new issue