From ba80d1ce1f3ed4aeaf728f808ae74df12c0da5ca Mon Sep 17 00:00:00 2001 From: Pascal Abresch Date: Tue, 17 Jan 2023 17:19:35 +0100 Subject: [PATCH] Implement check_offset for decorations --- doc/lua_api.md | 9 +++++++-- src/mapgen/mg_decoration.cpp | 29 +++++++++++++++++++---------- src/mapgen/mg_decoration.h | 1 + src/script/lua_api/l_mapgen.cpp | 5 +++++ 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/doc/lua_api.md b/doc/lua_api.md index 95bc4a7f70d0..249c770716b7 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -9564,8 +9564,13 @@ See [Decoration types]. Used by `minetest.register_decoration`. spawn_by = "default:water", -- Node (or list of nodes) that the decoration only spawns next to. - -- Checks the 8 neighboring nodes on the same Y, and also the ones - -- at Y+1, excluding both center nodes. + -- Checks the 8 neighboring nodes on the same height, + -- and also the ones at the height plus the check_offset, excluding both center nodes. + + check_offset = -1, + -- Specifies the offset that spawn_by should also check + -- The default value of -1 is useful to e.g check for water next to the base node. + -- 0 disables additional checks, valid values: {-1, 0, 1} num_spawn_by = 1, -- Number of spawn_by nodes that must be surrounding the decoration diff --git a/src/mapgen/mg_decoration.cpp b/src/mapgen/mg_decoration.cpp index 369f7b4a0299..75764a9f1754 100644 --- a/src/mapgen/mg_decoration.cpp +++ b/src/mapgen/mg_decoration.cpp @@ -87,6 +87,9 @@ void Decoration::resolveNodeNames() bool Decoration::canPlaceDecoration(MMVManip *vm, v3s16 p) { + // Note that `p` refers to the node the decoration will be placed ontop of, + // not to the decoration itself. + // Check if the decoration can be placed on this node u32 vi = vm->m_area.index(p); if (!CONTAINS(c_place_on, vm->m_data[vi].getContent())) @@ -97,16 +100,7 @@ bool Decoration::canPlaceDecoration(MMVManip *vm, v3s16 p) return true; int nneighs = 0; - static const v3s16 dirs[16] = { - v3s16( 0, 0, 1), - v3s16( 0, 0, -1), - v3s16( 1, 0, 0), - v3s16(-1, 0, 0), - v3s16( 1, 0, 1), - v3s16(-1, 0, 1), - v3s16(-1, 0, -1), - v3s16( 1, 0, -1), - + static const v3s16 dirs[8] = { v3s16( 0, 1, 1), v3s16( 0, 1, -1), v3s16( 1, 1, 0), @@ -117,6 +111,7 @@ bool Decoration::canPlaceDecoration(MMVManip *vm, v3s16 p) v3s16( 1, 1, -1) }; + // Check these 16 neighboring nodes for enough spawnby nodes for (size_t i = 0; i != ARRLEN(dirs); i++) { u32 index = vm->m_area.index(p + dirs[i]); @@ -127,6 +122,19 @@ bool Decoration::canPlaceDecoration(MMVManip *vm, v3s16 p) nneighs++; } + if (check_offset != 0) { + const v3s16 dir_offset(0, check_offset, 0); + + for (size_t i = 0; i != ARRLEN(dirs); i++) { + u32 index = vm->m_area.index(p + dirs[i] + dir_offset); + if (!vm->m_area.contains(index)) + continue; + + if (CONTAINS(c_spawnby, vm->m_data[index].getContent())) + nneighs++; + } + + } if (nneighs < nspawnby) return false; @@ -280,6 +288,7 @@ void Decoration::cloneTo(Decoration *def) const def->flags = flags; def->mapseed = mapseed; def->c_place_on = c_place_on; + def->check_offset = check_offset; def->sidelen = sidelen; def->y_min = y_min; def->y_max = y_max; diff --git a/src/mapgen/mg_decoration.h b/src/mapgen/mg_decoration.h index 1ea02a527d0f..89d8d355fb0d 100644 --- a/src/mapgen/mg_decoration.h +++ b/src/mapgen/mg_decoration.h @@ -73,6 +73,7 @@ class Decoration : public ObjDef, public NodeResolver { std::vector c_spawnby; s16 nspawnby; s16 place_offset_y = 0; + s16 check_offset = -1; std::unordered_set biomes; diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp index 2e17d0d6749e..3dbd76ef8372 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -1097,6 +1097,7 @@ int ModApiMapgen::l_register_decoration(lua_State *L) deco->y_max = getintfield_default(L, index, "y_max", 31000); deco->nspawnby = getintfield_default(L, index, "num_spawn_by", -1); deco->place_offset_y = getintfield_default(L, index, "place_offset_y", 0); + deco->check_offset = getintfield_default(L, index, "check_offset", -1); deco->sidelen = getintfield_default(L, index, "sidelen", 8); if (deco->sidelen <= 0) { errorstream << "register_decoration: sidelen must be " @@ -1131,6 +1132,10 @@ int ModApiMapgen::l_register_decoration(lua_State *L) errorstream << "register_decoration: no spawn_by nodes defined," " but num_spawn_by specified" << std::endl; } + if (deco->check_offset < -1 || deco->check_offset > 1) { + delete deco; + luaL_error(L, "register_decoration: check_offset out of range! Allowed values: [-1, 0, 1]"); + } //// Handle decoration type-specific parameters bool success = false;