mirror of
https://github.com/minetest/minetest.git
synced 2025-03-06 20:48:40 +01:00
Prevent VoxelManipulator size overflow
This commit is contained in:
parent
2cdf3af1b8
commit
9dd09d1056
4 changed files with 33 additions and 31 deletions
|
@ -5044,7 +5044,7 @@ inside the VoxelManip.
|
|||
can use `core.emerge_area` to make sure that the area you want to
|
||||
read/write is already generated.
|
||||
|
||||
* Other mods, or the core itself, could possibly modify the area of the map
|
||||
* Other mods, or the engine itself, could possibly modify the area of the map
|
||||
currently loaded into a VoxelManip object. With the exception of Mapgen
|
||||
VoxelManips (see above section), the internal buffers are not updated. For
|
||||
this reason, it is strongly encouraged to complete the usage of a particular
|
||||
|
@ -5059,9 +5059,11 @@ inside the VoxelManip.
|
|||
Methods
|
||||
-------
|
||||
|
||||
* `read_from_map(p1, p2)`: Loads a chunk of map into the VoxelManip object
|
||||
* `read_from_map(p1, p2)`: Loads a chunk of map into the VoxelManip object
|
||||
containing the region formed by `p1` and `p2`.
|
||||
* returns actual emerged `pmin`, actual emerged `pmax`
|
||||
* Note that calling this multiple times will *add* to the area loaded in the
|
||||
VoxelManip, and not reset it.
|
||||
* `write_to_map([light])`: Writes the data loaded from the `VoxelManip` back to
|
||||
the map.
|
||||
* **important**: data must be set using `VoxelManip:set_data()` before
|
||||
|
@ -5120,8 +5122,8 @@ Methods
|
|||
generated mapchunk above are propagated down into the mapchunk, defaults
|
||||
to `true` if left out.
|
||||
* `update_liquids()`: Update liquid flow
|
||||
* `was_modified()`: Returns `true` if the data in the voxel manipulator has been modified
|
||||
since it was last read from the map. This means you have to call `get_data` again.
|
||||
* `was_modified()`: Returns `true` if the data in the VoxelManip has been modified
|
||||
since it was last read from the map. This means you have to call `get_data()` again.
|
||||
This only applies to a `VoxelManip` object from `core.get_mapgen_object`,
|
||||
where the engine will keep the map and the VM in sync automatically.
|
||||
* Note: this doesn't do what you think it does and is subject to removal. Don't use it!
|
||||
|
|
17
src/map.cpp
17
src/map.cpp
|
@ -752,17 +752,12 @@ MMVManip::MMVManip(Map *map):
|
|||
assert(map);
|
||||
}
|
||||
|
||||
void MMVManip::initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max,
|
||||
bool load_if_inexistent)
|
||||
void MMVManip::initialEmerge(v3s16 p_min, v3s16 p_max, bool load_if_inexistent)
|
||||
{
|
||||
TimeTaker timer1("initialEmerge", &emerge_time);
|
||||
|
||||
assert(m_map);
|
||||
|
||||
// Units of these are MapBlocks
|
||||
v3s16 p_min = blockpos_min;
|
||||
v3s16 p_max = blockpos_max;
|
||||
|
||||
VoxelArea block_area_nodes
|
||||
(p_min*MAP_BLOCKSIZE, (p_max+1)*MAP_BLOCKSIZE-v3s16(1,1,1));
|
||||
|
||||
|
@ -775,6 +770,7 @@ void MMVManip::initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max,
|
|||
infostream<<std::endl;
|
||||
}
|
||||
|
||||
const bool all_new = m_area.hasEmptyExtent() || block_area_nodes.contains(m_area);
|
||||
addArea(block_area_nodes);
|
||||
|
||||
for(s32 z=p_min.Z; z<=p_max.Z; z++)
|
||||
|
@ -812,16 +808,12 @@ void MMVManip::initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max,
|
|||
setFlags(a, VOXELFLAG_NO_DATA);
|
||||
}
|
||||
}
|
||||
/*else if (block->getNode(0, 0, 0).getContent() == CONTENT_IGNORE)
|
||||
{
|
||||
// Mark that block was loaded as blank
|
||||
flags |= VMANIP_BLOCK_CONTAINS_CIGNORE;
|
||||
}*/
|
||||
|
||||
m_loaded_blocks[p] = flags;
|
||||
}
|
||||
|
||||
m_is_dirty = false;
|
||||
if (all_new)
|
||||
m_is_dirty = false;
|
||||
}
|
||||
|
||||
void MMVManip::blitBackAll(std::map<v3s16, MapBlock*> *modified_blocks,
|
||||
|
@ -834,6 +826,7 @@ void MMVManip::blitBackAll(std::map<v3s16, MapBlock*> *modified_blocks,
|
|||
/*
|
||||
Copy data of all blocks
|
||||
*/
|
||||
assert(!m_loaded_blocks.empty());
|
||||
for (auto &loaded_block : m_loaded_blocks) {
|
||||
v3s16 p = loaded_block.first;
|
||||
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
||||
|
|
|
@ -298,9 +298,6 @@ protected:
|
|||
u32 needed_count);
|
||||
};
|
||||
|
||||
#define VMANIP_BLOCK_DATA_INEXIST 1
|
||||
#define VMANIP_BLOCK_CONTAINS_CIGNORE 2
|
||||
|
||||
class MMVManip : public VoxelManipulator
|
||||
{
|
||||
public:
|
||||
|
@ -344,4 +341,8 @@ protected:
|
|||
value = flags describing the block
|
||||
*/
|
||||
std::map<v3s16, u8> m_loaded_blocks;
|
||||
|
||||
enum : u8 {
|
||||
VMANIP_BLOCK_DATA_INEXIST = 1 << 0,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -113,6 +113,20 @@ void VoxelManipulator::print(std::ostream &o, const NodeDefManager *ndef,
|
|||
}
|
||||
}
|
||||
|
||||
static inline void checkArea(const VoxelArea &a)
|
||||
{
|
||||
// won't overflow since cbrt(2^64) > 2^16
|
||||
u64 real_volume = static_cast<u64>(a.getExtent().X) * a.getExtent().Y * a.getExtent().Z;
|
||||
|
||||
// Volume limit equal to 8 default mapchunks, (80 * 2) ^ 3 = 4,096,000
|
||||
// Note: the hard limit is somewhere around 2^31 due to s32 type
|
||||
constexpr u64 MAX_ALLOWED = 4096000;
|
||||
if (real_volume > MAX_ALLOWED) {
|
||||
throw BaseException("VoxelManipulator: "
|
||||
"Area volume exceeds allowed value of " + std::to_string(MAX_ALLOWED));
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelManipulator::addArea(const VoxelArea &area)
|
||||
{
|
||||
// Cancel if requested area has zero volume
|
||||
|
@ -124,18 +138,10 @@ void VoxelManipulator::addArea(const VoxelArea &area)
|
|||
return;
|
||||
|
||||
// Calculate new area
|
||||
VoxelArea new_area;
|
||||
// New area is the requested area if m_area has zero volume
|
||||
if(m_area.hasEmptyExtent())
|
||||
{
|
||||
new_area = area;
|
||||
}
|
||||
// Else add requested area to m_area
|
||||
else
|
||||
{
|
||||
new_area = m_area;
|
||||
new_area.addArea(area);
|
||||
}
|
||||
VoxelArea new_area = m_area;
|
||||
new_area.addArea(area);
|
||||
|
||||
checkArea(new_area);
|
||||
|
||||
u32 new_size = new_area.getVolume();
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue