From b3ffc4b327622bec63793476191b95bc174bf33c Mon Sep 17 00:00:00 2001 From: Jude Melton-Houghton Date: Sat, 3 Dec 2022 10:40:46 -0500 Subject: [PATCH] Add `minetest.get_mapgen_edges` (#12999) --- doc/lua_api.txt | 7 +++++ games/devtest/mods/unittests/misc.lua | 37 +++++++++++++++++++++++++++ src/mapgen/mapgen.cpp | 31 +++++++++++----------- src/mapgen/mapgen.h | 6 ++++- src/script/lua_api/l_mapgen.cpp | 36 ++++++++++++++++++++++++++ src/script/lua_api/l_mapgen.h | 3 +++ 6 files changed, 103 insertions(+), 17 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index b58c75d11..e9a95c9e7 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -5628,6 +5628,13 @@ Environment access prefix `"no"` is attached, clears instead. * `flags` is in the same format and has the same options as `mg_flags` in `minetest.conf`. +* `minetest.get_mapgen_edges([mapgen_limit[, chunksize]])` + * Returns the minimum and maximum possible generated node positions + in that order. + * `mapgen_limit` is an optional number. If it is absent, its value is that + of the *active* mapgen setting `"mapgen_limit"`. + * `chunksize` is an optional number. If it is absent, its value is that + of the *active* mapgen setting `"chunksize"`. * `minetest.get_mapgen_setting(name)` * Gets the *active* mapgen setting (or nil if none exists) in string format with the following order of precedence: diff --git a/games/devtest/mods/unittests/misc.lua b/games/devtest/mods/unittests/misc.lua index 7c16b7c82..3f327edec 100644 --- a/games/devtest/mods/unittests/misc.lua +++ b/games/devtest/mods/unittests/misc.lua @@ -110,3 +110,40 @@ local function test_game_info() assert(info.title == game_conf:get("title")) end unittests.register("test_game_info", test_game_info) + +local function test_mapgen_edges(cb) + -- Test that the map can extend to the expected edges and no further. + local min_edge, max_edge = minetest.get_mapgen_edges() + local min_finished = {} + local max_finished = {} + local function finish() + if #min_finished ~= 1 then + return cb("Expected 1 block to emerge around mapgen minimum edge") + end + if min_finished[1] ~= (min_edge / minetest.MAP_BLOCKSIZE):floor() then + return cb("Expected block within minimum edge to emerge") + end + if #max_finished ~= 1 then + return cb("Expected 1 block to emerge around mapgen maximum edge") + end + if max_finished[1] ~= (max_edge / minetest.MAP_BLOCKSIZE):floor() then + return cb("Expected block within maximum edge to emerge") + end + return cb() + end + local emerges_left = 2 + local function emerge_block(blockpos, action, blocks_left, finished) + if action ~= minetest.EMERGE_CANCELLED then + table.insert(finished, blockpos) + end + if blocks_left == 0 then + emerges_left = emerges_left - 1 + if emerges_left == 0 then + return finish() + end + end + end + minetest.emerge_area(min_edge:subtract(1), min_edge, emerge_block, min_finished) + minetest.emerge_area(max_edge, max_edge:add(1), emerge_block, max_finished) +end +unittests.register("test_mapgen_edges", test_mapgen_edges, {map=true, async=true}) diff --git a/src/mapgen/mapgen.cpp b/src/mapgen/mapgen.cpp index 0639f149f..ce281e2c1 100644 --- a/src/mapgen/mapgen.cpp +++ b/src/mapgen/mapgen.cpp @@ -1063,9 +1063,20 @@ void MapgenParams::writeParams(Settings *settings) const } -// Calculate exact edges of the outermost mapchunks that are within the -// set 'mapgen_limit'. -void MapgenParams::calcMapgenEdges() +s32 MapgenParams::getSpawnRangeMax() +{ + if (!m_mapgen_edges_calculated) { + std::pair edges = get_mapgen_edges(mapgen_limit, chunksize); + mapgen_edge_min = edges.first; + mapgen_edge_max = edges.second; + m_mapgen_edges_calculated = true; + } + + return MYMIN(-mapgen_edge_min, mapgen_edge_max); +} + + +std::pair get_mapgen_edges(s16 mapgen_limit, s16 chunksize) { // Central chunk offset, in blocks s16 ccoff_b = -chunksize / 2; @@ -1089,17 +1100,5 @@ void MapgenParams::calcMapgenEdges() s16 numcmin = MYMAX((ccfmin - mapgen_limit_min) / csize_n, 0); s16 numcmax = MYMAX((mapgen_limit_max - ccfmax) / csize_n, 0); // Mapgen edges, in nodes - mapgen_edge_min = ccmin - numcmin * csize_n; - mapgen_edge_max = ccmax + numcmax * csize_n; - - m_mapgen_edges_calculated = true; -} - - -s32 MapgenParams::getSpawnRangeMax() -{ - if (!m_mapgen_edges_calculated) - calcMapgenEdges(); - - return MYMIN(-mapgen_edge_min, mapgen_edge_max); + return std::pair(ccmin - numcmin * csize_n, ccmax + numcmax * csize_n); } diff --git a/src/mapgen/mapgen.h b/src/mapgen/mapgen.h index ef5de6029..b61608039 100644 --- a/src/mapgen/mapgen.h +++ b/src/mapgen/mapgen.h @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "nodedef.h" #include "util/string.h" #include "util/container.h" +#include #define MAPGEN_DEFAULT MAPGEN_V7 #define MAPGEN_DEFAULT_NAME "v7" @@ -139,7 +140,6 @@ struct MapgenParams { s32 getSpawnRangeMax(); private: - void calcMapgenEdges(); bool m_mapgen_edges_calculated = false; }; @@ -329,3 +329,7 @@ protected: s16 dungeon_ymin; s16 dungeon_ymax; }; + +// Calculate exact edges of the outermost mapchunks that are within the set +// mapgen_limit. Returns the minimum and maximum edges in nodes in that order. +std::pair get_mapgen_edges(s16 mapgen_limit, s16 chunksize); diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp index 1e4197df3..2e17d0d67 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -810,6 +810,41 @@ int ModApiMapgen::l_set_mapgen_params(lua_State *L) return 0; } +// get_mapgen_edges([mapgen_limit[, chunksize]]) +int ModApiMapgen::l_get_mapgen_edges(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + + MapSettingsManager *settingsmgr = getServer(L)->getEmergeManager()->map_settings_mgr; + + // MapSettingsManager::makeMapgenParams cannot be used here because it would + // make mapgen settings immutable from then on. Mapgen settings should stay + // mutable until after mod loading ends. + + s16 mapgen_limit; + if (lua_isnumber(L, 1)) { + mapgen_limit = lua_tointeger(L, 1); + } else { + std::string mapgen_limit_str; + settingsmgr->getMapSetting("mapgen_limit", &mapgen_limit_str); + mapgen_limit = stoi(mapgen_limit_str, 0, MAX_MAP_GENERATION_LIMIT); + } + + s16 chunksize; + if (lua_isnumber(L, 2)) { + chunksize = lua_tointeger(L, 2); + } else { + std::string chunksize_str; + settingsmgr->getMapSetting("chunksize", &chunksize_str); + chunksize = stoi(chunksize_str, -32768, 32767); + } + + std::pair edges = get_mapgen_edges(mapgen_limit, chunksize); + push_v3s16(L, v3s16(1, 1, 1) * edges.first); + push_v3s16(L, v3s16(1, 1, 1) * edges.second); + return 2; +} + // get_mapgen_setting(name) int ModApiMapgen::l_get_mapgen_setting(lua_State *L) { @@ -1782,6 +1817,7 @@ void ModApiMapgen::Initialize(lua_State *L, int top) API_FCT(get_mapgen_params); API_FCT(set_mapgen_params); + API_FCT(get_mapgen_edges); API_FCT(get_mapgen_setting); API_FCT(set_mapgen_setting); API_FCT(get_mapgen_setting_noiseparams); diff --git a/src/script/lua_api/l_mapgen.h b/src/script/lua_api/l_mapgen.h index 0bdc56fc5..1428a91c8 100644 --- a/src/script/lua_api/l_mapgen.h +++ b/src/script/lua_api/l_mapgen.h @@ -61,6 +61,9 @@ private: // set mapgen parameters static int l_set_mapgen_params(lua_State *L); + // get_mapgen_edges([mapgen_limit[, chunksize]]) + static int l_get_mapgen_edges(lua_State *L); + // get_mapgen_setting(name) static int l_get_mapgen_setting(lua_State *L);