Map generation limit: Fix checks for block/sector over-limit

Fix the maths that check if any part of a mapblock or sector is over the
set map_generation_limit.
Therefore avoid the loading of any over-limit blocks that were previously
generated when map_generation_limit was larger. The set limit can vary
for a world because it is not yet a per-world mapgen parameter, even when
it is sometimes it will be changed deliberately.
Therefore avoid a player being returned to world centre if they re-enter
a world while being over-limit.

Fix the createSector() crash caused by a mob spawning over-limit in an
over-limit mapblock
This commit is contained in:
paramat 2016-12-27 17:00:47 +00:00
parent 1fee649f15
commit ddcf8422a2
2 changed files with 36 additions and 14 deletions

@ -2064,15 +2064,26 @@ ServerMapSector *ServerMap::createSector(v2s16 p2d)
return sector; return sector;
} }
#endif #endif
/* /*
Do not create over-limit Do not create over-limit.
We are checking for any nodes of the mapblocks of the sector being beyond the limit.
A sector is a vertical column of mapblocks, so sectorpos is like a 2D blockpos.
At the negative limit we are checking for
block minimum nodepos < -mapgenlimit.
At the positive limit we are checking for
block maximum nodepos > mapgenlimit.
Block minimum nodepos = blockpos * mapblocksize.
Block maximum nodepos = (blockpos + 1) * mapblocksize - 1.
*/ */
const static u16 map_gen_limit = MYMIN(MAX_MAP_GENERATION_LIMIT, const static u16 map_gen_limit = MYMIN(MAX_MAP_GENERATION_LIMIT,
g_settings->getU16("map_generation_limit")); g_settings->getU16("map_generation_limit"));
if(p2d.X < -map_gen_limit / MAP_BLOCKSIZE if (p2d.X * MAP_BLOCKSIZE < -map_gen_limit
|| p2d.X > map_gen_limit / MAP_BLOCKSIZE || (p2d.X + 1) * MAP_BLOCKSIZE - 1 > map_gen_limit
|| p2d.Y < -map_gen_limit / MAP_BLOCKSIZE || p2d.Y * MAP_BLOCKSIZE < -map_gen_limit
|| p2d.Y > map_gen_limit / MAP_BLOCKSIZE) || (p2d.Y + 1) * MAP_BLOCKSIZE - 1 > map_gen_limit)
throw InvalidPositionException("createSector(): pos. over limit"); throw InvalidPositionException("createSector(): pos. over limit");
/* /*

@ -656,23 +656,34 @@ inline bool objectpos_over_limit(v3f p)
const static float map_gen_limit_bs = MYMIN(MAX_MAP_GENERATION_LIMIT, const static float map_gen_limit_bs = MYMIN(MAX_MAP_GENERATION_LIMIT,
g_settings->getU16("map_generation_limit")) * BS; g_settings->getU16("map_generation_limit")) * BS;
return (p.X < -map_gen_limit_bs return (p.X < -map_gen_limit_bs
|| p.X > map_gen_limit_bs || p.X > map_gen_limit_bs
|| p.Y < -map_gen_limit_bs || p.Y < -map_gen_limit_bs
|| p.Y > map_gen_limit_bs || p.Y > map_gen_limit_bs
|| p.Z < -map_gen_limit_bs || p.Z < -map_gen_limit_bs
|| p.Z > map_gen_limit_bs); || p.Z > map_gen_limit_bs);
} }
/*
We are checking for any node of the mapblock being beyond the limit.
At the negative limit we are checking for
block minimum nodepos < -mapgenlimit.
At the positive limit we are checking for
block maximum nodepos > mapgenlimit.
Block minimum nodepos = blockpos * mapblocksize.
Block maximum nodepos = (blockpos + 1) * mapblocksize - 1.
*/
inline bool blockpos_over_limit(v3s16 p) inline bool blockpos_over_limit(v3s16 p)
{ {
const static u16 map_gen_limit = MYMIN(MAX_MAP_GENERATION_LIMIT, const static u16 map_gen_limit = MYMIN(MAX_MAP_GENERATION_LIMIT,
g_settings->getU16("map_generation_limit")); g_settings->getU16("map_generation_limit"));
return (p.X < -map_gen_limit / MAP_BLOCKSIZE return (p.X * MAP_BLOCKSIZE < -map_gen_limit
|| p.X > map_gen_limit / MAP_BLOCKSIZE || (p.X + 1) * MAP_BLOCKSIZE - 1 > map_gen_limit
|| p.Y < -map_gen_limit / MAP_BLOCKSIZE || p.Y * MAP_BLOCKSIZE < -map_gen_limit
|| p.Y > map_gen_limit / MAP_BLOCKSIZE || (p.Y + 1) * MAP_BLOCKSIZE - 1 > map_gen_limit
|| p.Z < -map_gen_limit / MAP_BLOCKSIZE || p.Z * MAP_BLOCKSIZE < -map_gen_limit
|| p.Z > map_gen_limit / MAP_BLOCKSIZE); || (p.Z + 1) * MAP_BLOCKSIZE - 1 > map_gen_limit);
} }
/* /*