1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-09-30 19:22:14 +00:00

Extend core.generate_decorations to generate biomes respecting the biome map (#16397)

Large structures which are generated in on_generated callbacks
independently by Lua cannot influence decoration placement. This
change enables such a callback to assume responsibility for generating
decorations itself, presumably after structures are placed, by
disabling decorations in mg_flags and executing
core.generate_decorations.

---------

Co-authored-by: Po Lu <luangruo@yahoo.com>
This commit is contained in:
Cora de la Mouche 2025-09-20 13:44:19 +02:00 committed by GitHub
parent 29490cb0f7
commit fc6bef7de6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 52 additions and 15 deletions

View file

@ -50,6 +50,7 @@ core.features = {
object_guids = true,
on_timer_four_args = true,
particlespawner_exclude_player = true,
generate_decorations_biomes = true,
}
function core.has_feature(arg)

View file

@ -5847,6 +5847,8 @@ Utilities
on_timer_four_args = true,
-- `ParticleSpawner` definition supports `exclude_player` field (5.14.0)
particlespawner_exclude_player = true,
-- core.generate_decorations() supports `use_mapgen_biomes` parameter (5.14.0)
generate_decorations_biomes = true,
}
```
@ -6739,10 +6741,14 @@ Environment access
* Generate all registered ores within the VoxelManip `vm` and in the area
from `pos1` to `pos2`.
* `pos1` and `pos2` are optional and default to mapchunk minp and maxp.
* `core.generate_decorations(vm[, pos1, pos2])`
* `core.generate_decorations(vm[, pos1, pos2, [use_mapgen_biomes]])`
* Generate all registered decorations within the VoxelManip `vm` and in the
area from `pos1` to `pos2`.
* `pos1` and `pos2` are optional and default to mapchunk minp and maxp.
* `use_mapgen_biomes` (optional boolean). For use in on_generated callbacks only.
If set to true, decorations are placed in respect to the biome map of the current chunk.
`pos1` and `pos2` must match the positions of the current chunk, or an error will be raised.
default: `false`
* `core.clear_objects([options])`
* Clear all objects in the environment
* Takes an optional table as an argument with the field `mode`.

View file

@ -1611,7 +1611,7 @@ int ModApiMapgen::l_generate_ores(lua_State *L)
}
// generate_decorations(vm, p1, p2)
// generate_decorations(vm, p1, p2, use_mapgen_biomes)
int ModApiMapgen::l_generate_decorations(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
@ -1621,26 +1621,56 @@ int ModApiMapgen::l_generate_decorations(lua_State *L)
return 0;
DecorationManager *decomgr;
if (auto mg = getMapgen(L))
Mapgen mg, *mgp = nullptr;
bool use_mapgen_biomes = readParam<bool>(L, 4, false);
MMVManip *oldvm = nullptr, *vm = checkObject<LuaVoxelManip>(L, 1)->vm;
if (auto mg = getMapgen(L)) {
decomgr = mg->m_emerge->decomgr;
else
if (use_mapgen_biomes) {
mgp = mg;
oldvm = mgp->vm;
if (!oldvm) {
goto no_vm;
}
}
} else {
if (use_mapgen_biomes) {
no_vm:
throw LuaError("use_mapgen_biomes specified outside a "
"map generation context");
}
decomgr = emerge->decomgr;
}
if (!mgp) {
mgp = &mg;
// Intentionally truncates to s32, see Mapgen::Mapgen()
mg.seed = (s32)emerge->mgparams->seed;
mg.ndef = emerge->ndef;
}
Mapgen mg;
// Intentionally truncates to s32, see Mapgen::Mapgen()
mg.seed = (s32)emerge->mgparams->seed;
mg.vm = checkObject<LuaVoxelManip>(L, 1)->vm;
mg.ndef = emerge->ndef;
v3s16 pmin = lua_istable(L, 2) ? check_v3s16(L, 2) :
mg.vm->m_area.MinEdge + v3s16(1,1,1) * MAP_BLOCKSIZE;
v3s16 pmax = lua_istable(L, 3) ? check_v3s16(L, 3) :
mg.vm->m_area.MaxEdge - v3s16(1,1,1) * MAP_BLOCKSIZE;
const v3s16 default_pmin = vm->m_area.MinEdge + MAP_BLOCKSIZE,
default_pmax = vm->m_area.MaxEdge - MAP_BLOCKSIZE;
v3s16 pmin = lua_istable(L, 2) ? check_v3s16(L, 2) : default_pmin;
v3s16 pmax = lua_istable(L, 3) ? check_v3s16(L, 3) : default_pmax;
sortBoxVerticies(pmin, pmax);
if (use_mapgen_biomes) {
assert(oldvm);
const v3s16 required_pmin = oldvm->m_area.MinEdge + MAP_BLOCKSIZE,
required_pmax = oldvm->m_area.MaxEdge - MAP_BLOCKSIZE;
if (pmin != required_pmin || pmax != required_pmax)
throw LuaError("use_mapgen_biomes requires extents matching chunk area");
}
u32 blockseed = Mapgen::getBlockSeed(pmin, mg.seed);
decomgr->placeAllDecos(&mg, blockseed, pmin, pmax);
mgp->vm = vm;
try {
decomgr->placeAllDecos(mgp, blockseed, pmin, pmax);
} catch (...) {
mgp->vm = oldvm;
throw;
}
mgp->vm = oldvm;
return 0;
}