#include <list>
#include "irrlichttypes_bloated.h"
+#include "mapblock.h"
#include "mapnode.h"
#include "constants.h"
#include "voxel.h"
#include "modifiedstate.h"
#include "util/container.h"
#include "util/metricsbackend.h"
+#include "util/numeric.h"
#include "nodetimer.h"
#include "map_settings_manager.h"
#include "debug.h"
MapEditEvent() = default;
+ // Sets the event's position and marks the block as modified.
+ void setPositionModified(v3s16 pos)
+ {
+ p = pos;
+ modified_blocks.insert(getNodeBlockPos(pos));
+ }
+
VoxelArea getArea() const
{
switch(type){
case MEET_ADDNODE:
- return VoxelArea(p);
case MEET_REMOVENODE:
- return VoxelArea(p);
case MEET_SWAPNODE:
- return VoxelArea(p);
case MEET_BLOCK_NODE_METADATA_CHANGED:
- {
- v3s16 np1 = p*MAP_BLOCKSIZE;
- v3s16 np2 = np1 + v3s16(1,1,1)*MAP_BLOCKSIZE - v3s16(1,1,1);
- return VoxelArea(np1, np2);
- }
+ return VoxelArea(p);
case MEET_OTHER:
{
VoxelArea a;
bool isValidPosition(v3s16 p);
// throws InvalidPositionException if not found
- void setNode(v3s16 p, MapNode & n);
+ void setNode(v3s16 p, MapNode n);
// Returns a CONTENT_IGNORE node if not found
// If is_valid_position is not NULL then this will be set to true if the
Updates usage timers and unloads unused blocks and sectors.
Saves modified blocks before unloading if possible.
*/
- void timerUpdate(float dtime, float unload_timeout, u32 max_loaded_blocks,
+ void timerUpdate(float dtime, float unload_timeout, s32 max_loaded_blocks,
std::vector<v3s16> *unloaded_blocks=NULL);
/*
void removeNodeTimer(v3s16 p);
/*
- Variables
+ Utilities
*/
+ // Iterates through all nodes in the area in an unspecified order.
+ // The given callback takes the position as its first argument and the node
+ // as its second. If it returns false, forEachNodeInArea returns early.
+ template<typename F>
+ void forEachNodeInArea(v3s16 minp, v3s16 maxp, F func)
+ {
+ v3s16 bpmin = getNodeBlockPos(minp);
+ v3s16 bpmax = getNodeBlockPos(maxp);
+ for (s16 bz = bpmin.Z; bz <= bpmax.Z; bz++)
+ for (s16 bx = bpmin.X; bx <= bpmax.X; bx++)
+ for (s16 by = bpmin.Y; by <= bpmax.Y; by++) {
+ // y is iterated innermost to make use of the sector cache.
+ v3s16 bp(bx, by, bz);
+ MapBlock *block = getBlockNoCreateNoEx(bp);
+ v3s16 basep = bp * MAP_BLOCKSIZE;
+ s16 minx_block = rangelim(minp.X - basep.X, 0, MAP_BLOCKSIZE - 1);
+ s16 miny_block = rangelim(minp.Y - basep.Y, 0, MAP_BLOCKSIZE - 1);
+ s16 minz_block = rangelim(minp.Z - basep.Z, 0, MAP_BLOCKSIZE - 1);
+ s16 maxx_block = rangelim(maxp.X - basep.X, 0, MAP_BLOCKSIZE - 1);
+ s16 maxy_block = rangelim(maxp.Y - basep.Y, 0, MAP_BLOCKSIZE - 1);
+ s16 maxz_block = rangelim(maxp.Z - basep.Z, 0, MAP_BLOCKSIZE - 1);
+ for (s16 z_block = minz_block; z_block <= maxz_block; z_block++)
+ for (s16 y_block = miny_block; y_block <= maxy_block; y_block++)
+ for (s16 x_block = minx_block; x_block <= maxx_block; x_block++) {
+ v3s16 p = basep + v3s16(x_block, y_block, z_block);
+ MapNode n = block ?
+ block->getNodeNoCheck(x_block, y_block, z_block) :
+ MapNode(CONTENT_IGNORE);
+ if (!func(p, n))
+ return;
+ }
+ }
+ }
+
bool isBlockOccluded(MapBlock *block, v3s16 cam_pos_nodes);
protected:
IGameDef *m_gamedef;