1
0
mirror of https://github.com/luanti-org/luanti.git synced 2025-11-11 12:25:26 +01:00

Allow mapgen chunk size to be non-cubic (#16429)

This commit is contained in:
sfan5
2025-10-22 22:31:23 +02:00
committed by GitHub
parent 0f943e5810
commit f4977b1e33
14 changed files with 151 additions and 73 deletions

View File

@@ -100,7 +100,7 @@ Mapgen::Mapgen(int mapgenid, MapgenParams *params, EmergeParams *emerge) :
water_level = params->water_level;
mapgen_limit = params->mapgen_limit;
flags = params->flags;
csize = v3s16(1, 1, 1) * (params->chunksize * MAP_BLOCKSIZE);
csize = params->chunksize * MAP_BLOCKSIZE;
/*
We are losing half our entropy by doing this, but it is necessary to
@@ -1071,10 +1071,29 @@ void MapgenParams::readParams(const Settings *settings)
settings->getS16NoEx("water_level", water_level);
settings->getS16NoEx("mapgen_limit", mapgen_limit);
settings->getS16NoEx("chunksize", chunksize);
settings->getFlagStrNoEx("mg_flags", flags, flagdesc_mapgen);
chunksize = rangelim(chunksize, 1, 10);
std::string chunksize_str;
settings->getNoEx("chunksize", chunksize_str);
if (is_number(chunksize_str)) {
chunksize = v3s16(stoi(chunksize_str, 1, 999));
} else if (auto tmp = str_to_v3f(chunksize_str); tmp.has_value()) {
chunksize = v3s16(
rangelim(tmp->X, 1, 999),
rangelim(tmp->Y, 1, 999),
rangelim(tmp->Z, 1, 999)
);
} else if (!chunksize_str.empty()) {
errorstream << "MapgenParams: invalid chunksize \"" << chunksize_str
<< "\"" << std::endl;
}
// Finally check the volume limit
if (u32 v = chunksize.X * chunksize.Y * chunksize.Z; v > MAX_CHUNK_VOLUME) {
errorstream << "MapgenParams: chunksize " << chunksize
<< " is too big (volume > " << MAX_CHUNK_VOLUME
<< "), falling back to the default." << std::endl;
chunksize = v3s16(5);
}
delete bparams;
bparams = BiomeManager::createBiomeParams(BIOMEGEN_ORIGINAL);
@@ -1091,9 +1110,15 @@ void MapgenParams::writeParams(Settings *settings) const
settings->setU64("seed", seed);
settings->setS16("water_level", water_level);
settings->setS16("mapgen_limit", mapgen_limit);
settings->setS16("chunksize", chunksize);
settings->setFlagStr("mg_flags", flags, flagdesc_mapgen);
// Write as number if cubic, for backwards-compatibility
if (chunksize.X == chunksize.Y && chunksize.Y == chunksize.Z) {
settings->setS16("chunksize", chunksize.X);
} else {
settings->setV3F("chunksize", v3f::from(chunksize));
}
if (bparams)
bparams->writeParams(settings);
}
@@ -1101,29 +1126,14 @@ void MapgenParams::writeParams(Settings *settings) const
s32 MapgenParams::getSpawnRangeMax()
{
if (!m_mapgen_edges_calculated) {
std::pair<s16, s16> 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);
auto [emin, emax] = get_mapgen_edges(mapgen_limit, chunksize);
s32 min_xz = std::max(emin.X, emin.Z), max_xz = std::min(emax.X, emax.Z);
return std::min(-min_xz, max_xz);
}
std::pair<s16, s16> get_mapgen_edges(s16 mapgen_limit, s16 chunksize)
std::pair<v3s16, v3s16> get_mapgen_edges(s16 mapgen_limit, v3s16 chunksize)
{
// Central chunk offset, in blocks
s16 ccoff_b = -chunksize / 2;
// Chunksize, in nodes
s32 csize_n = chunksize * MAP_BLOCKSIZE;
// Minp/maxp of central chunk, in nodes
s16 ccmin = ccoff_b * MAP_BLOCKSIZE;
s16 ccmax = ccmin + csize_n - 1;
// Fullminp/fullmaxp of central chunk, in nodes
s16 ccfmin = ccmin - MAP_BLOCKSIZE;
s16 ccfmax = ccmax + MAP_BLOCKSIZE;
// Effective mapgen limit, in blocks
// Uses same calculation as ServerMap::blockpos_over_mapgen_limit(v3s16 p)
s16 mapgen_limit_b = rangelim(mapgen_limit,
@@ -1131,10 +1141,29 @@ std::pair<s16, s16> get_mapgen_edges(s16 mapgen_limit, s16 chunksize)
// Effective mapgen limits, in nodes
s16 mapgen_limit_min = -mapgen_limit_b * MAP_BLOCKSIZE;
s16 mapgen_limit_max = (mapgen_limit_b + 1) * MAP_BLOCKSIZE - 1;
// Number of complete chunks from central chunk fullminp/fullmaxp
// to effective mapgen limits.
s16 numcmin = MYMAX((ccfmin - mapgen_limit_min) / csize_n, 0);
s16 numcmax = MYMAX((mapgen_limit_max - ccfmax) / csize_n, 0);
const auto &calculate = [&] (s16 cs) -> std::pair<s16, s16> {
// Central chunk offset, in blocks
s16 ccoff_b = -cs / 2;
// Chunksize, in nodes
s32 csize_n = cs * MAP_BLOCKSIZE;
// Minp/maxp of central chunk, in nodes
s16 ccmin = ccoff_b * MAP_BLOCKSIZE;
s16 ccmax = ccmin + csize_n - 1;
// Fullminp/fullmaxp of central chunk, in nodes
s16 ccfmin = ccmin - MAP_BLOCKSIZE;
s16 ccfmax = ccmax + MAP_BLOCKSIZE;
// Number of complete chunks from central chunk fullminp/fullmaxp
// to effective mapgen limits.
s16 numcmin = std::max((ccfmin - mapgen_limit_min) / csize_n, 0);
s16 numcmax = std::max((mapgen_limit_max - ccfmax) / csize_n, 0);
return {ccmin - numcmin * csize_n, ccmax + numcmax * csize_n};
};
// Mapgen edges, in nodes
return std::pair<s16, s16>(ccmin - numcmin * csize_n, ccmax + numcmax * csize_n);
v3s16 emin, emax;
std::tie(emin.X, emax.X) = calculate(chunksize.X);
std::tie(emin.Y, emax.Y) = calculate(chunksize.Y);
std::tie(emin.Z, emax.Z) = calculate(chunksize.Z);
return {emin, emax};
}

View File

@@ -111,7 +111,7 @@ struct MapgenParams {
virtual ~MapgenParams();
MapgenType mgtype = MAPGEN_DEFAULT;
s16 chunksize = 5;
v3s16 chunksize = v3s16(5);
u64 seed = 0;
s16 water_level = 1;
s16 mapgen_limit = MAX_MAP_GENERATION_LIMIT;
@@ -121,9 +121,6 @@ struct MapgenParams {
BiomeParams *bparams = nullptr;
s16 mapgen_edge_min = -MAX_MAP_GENERATION_LIMIT;
s16 mapgen_edge_max = MAX_MAP_GENERATION_LIMIT;
virtual void readParams(const Settings *settings);
virtual void writeParams(Settings *settings) const;
// Default settings for g_settings such as flags
@@ -131,8 +128,8 @@ struct MapgenParams {
s32 getSpawnRangeMax();
private:
bool m_mapgen_edges_calculated = false;
// Mostly arbitrary limit
constexpr static u32 MAX_CHUNK_VOLUME = 2000;
};
@@ -329,4 +326,4 @@ protected:
// 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<s16, s16> get_mapgen_edges(s16 mapgen_limit, s16 chunksize);
std::pair<v3s16, v3s16> get_mapgen_edges(s16 mapgen_limit, v3s16 chunksize);