Record MapBlock modification reasons as flags instead of strings

This improves performance of MapBlock::raiseModified by a factor of 6.
Also, clean up mapblock.h a bit and inline small functions.
This commit is contained in:
kwolekr 2015-05-17 22:14:26 -04:00
parent 4c9a8a91c4
commit 46684beec1
6 changed files with 294 additions and 241 deletions

@ -873,7 +873,7 @@ void ServerEnvironment::clearAllObjects()
if(block){ if(block){
block->m_static_objects.remove(id); block->m_static_objects.remove(id);
block->raiseModified(MOD_STATE_WRITE_NEEDED, block->raiseModified(MOD_STATE_WRITE_NEEDED,
"clearAllObjects"); MOD_REASON_CLEAR_ALL_OBJECTS);
obj->m_static_exists = false; obj->m_static_exists = false;
} }
} }
@ -952,7 +952,7 @@ void ServerEnvironment::clearAllObjects()
block->m_static_objects.m_stored.clear(); block->m_static_objects.m_stored.clear();
block->m_static_objects.m_active.clear(); block->m_static_objects.m_active.clear();
block->raiseModified(MOD_STATE_WRITE_NEEDED, block->raiseModified(MOD_STATE_WRITE_NEEDED,
"clearAllObjects"); MOD_REASON_CLEAR_ALL_OBJECTS);
num_objs_cleared += num_stored + num_active; num_objs_cleared += num_stored + num_active;
num_blocks_cleared++; num_blocks_cleared++;
} }
@ -1139,7 +1139,7 @@ void ServerEnvironment::step(float dtime)
// set block to be saved when it is unloaded // set block to be saved when it is unloaded
if(block->getTimestamp() > block->getDiskTimestamp() + 60) if(block->getTimestamp() > block->getDiskTimestamp() + 60)
block->raiseModified(MOD_STATE_WRITE_AT_UNLOAD, block->raiseModified(MOD_STATE_WRITE_AT_UNLOAD,
"Timestamp older than 60s (step)"); MOD_REASON_BLOCK_EXPIRED);
// Run node timers // Run node timers
std::map<v3s16, NodeTimer> elapsed_timers = std::map<v3s16, NodeTimer> elapsed_timers =
@ -1530,7 +1530,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
if(set_changed) if(set_changed)
block->raiseModified(MOD_STATE_WRITE_NEEDED, block->raiseModified(MOD_STATE_WRITE_NEEDED,
"addActiveObjectRaw"); MOD_REASON_ADD_ACTIVE_OBJECT_RAW);
} else { } else {
v3s16 p = floatToInt(objectpos, BS); v3s16 p = floatToInt(objectpos, BS);
errorstream<<"ServerEnvironment::addActiveObjectRaw(): " errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
@ -1579,7 +1579,7 @@ void ServerEnvironment::removeRemovedObjects()
if (block) { if (block) {
block->m_static_objects.remove(id); block->m_static_objects.remove(id);
block->raiseModified(MOD_STATE_WRITE_NEEDED, block->raiseModified(MOD_STATE_WRITE_NEEDED,
"removeRemovedObjects/remove"); MOD_REASON_REMOVE_OBJECTS_REMOVE);
obj->m_static_exists = false; obj->m_static_exists = false;
} else { } else {
infostream<<"Failed to emerge block from which an object to " infostream<<"Failed to emerge block from which an object to "
@ -1604,7 +1604,7 @@ void ServerEnvironment::removeRemovedObjects()
block->m_static_objects.m_stored.push_back(i->second); block->m_static_objects.m_stored.push_back(i->second);
block->m_static_objects.m_active.erase(id); block->m_static_objects.m_active.erase(id);
block->raiseModified(MOD_STATE_WRITE_NEEDED, block->raiseModified(MOD_STATE_WRITE_NEEDED,
"removeRemovedObjects/deactivate"); MOD_REASON_REMOVE_OBJECTS_DEACTIVATE);
} }
} else { } else {
infostream<<"Failed to emerge block from which an object to " infostream<<"Failed to emerge block from which an object to "
@ -1690,8 +1690,7 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
// Clear stored list // Clear stored list
block->m_static_objects.m_stored.clear(); block->m_static_objects.m_stored.clear();
block->raiseModified(MOD_STATE_WRITE_NEEDED, block->raiseModified(MOD_STATE_WRITE_NEEDED,
"stored list cleared in activateObjects due to " MOD_REASON_TOO_MANY_OBJECTS);
"large amount of objects");
return; return;
} }
@ -1812,7 +1811,7 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
block->m_static_objects.insert(id, s_obj); block->m_static_objects.insert(id, s_obj);
obj->m_static_block = blockpos_o; obj->m_static_block = blockpos_o;
block->raiseModified(MOD_STATE_WRITE_NEEDED, block->raiseModified(MOD_STATE_WRITE_NEEDED,
"deactivateFarObjects: Static data moved in"); MOD_REASON_STATIC_DATA_ADDED);
// Delete from block where object was located // Delete from block where object was located
block = m_map->emergeBlock(old_static_block, false); block = m_map->emergeBlock(old_static_block, false);
@ -1825,7 +1824,7 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
} }
block->m_static_objects.remove(id); block->m_static_objects.remove(id);
block->raiseModified(MOD_STATE_WRITE_NEEDED, block->raiseModified(MOD_STATE_WRITE_NEEDED,
"deactivateFarObjects: Static data moved out"); MOD_REASON_STATIC_DATA_REMOVED);
continue; continue;
} }
@ -1890,8 +1889,7 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
// Only mark block as modified if data changed considerably // Only mark block as modified if data changed considerably
if(shall_be_written) if(shall_be_written)
block->raiseModified(MOD_STATE_WRITE_NEEDED, block->raiseModified(MOD_STATE_WRITE_NEEDED,
"deactivateFarObjects: Static data " MOD_REASON_STATIC_DATA_CHANGED);
"changed considerably");
} }
} }
@ -1937,8 +1935,7 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
// Only mark block as modified if data changed considerably // Only mark block as modified if data changed considerably
if(shall_be_written) if(shall_be_written)
block->raiseModified(MOD_STATE_WRITE_NEEDED, block->raiseModified(MOD_STATE_WRITE_NEEDED,
"deactivateFarObjects: Static data " MOD_REASON_STATIC_DATA_CHANGED);
"changed considerably");
obj->m_static_exists = true; obj->m_static_exists = true;
obj->m_static_block = block->getPos(); obj->m_static_block = block->getPos();

@ -1436,7 +1436,7 @@ void Map::timerUpdate(float dtime, float unload_timeout,
// Save if modified // Save if modified
if (block->getModified() != MOD_STATE_CLEAN && save_before_unloading) { if (block->getModified() != MOD_STATE_CLEAN && save_before_unloading) {
modprofiler.add(block->getModifiedReason(), 1); modprofiler.add(block->getModifiedReasonString(), 1);
if (!saveBlock(block)) if (!saveBlock(block))
continue; continue;
saved_blocks_count++; saved_blocks_count++;
@ -2412,7 +2412,7 @@ void ServerMap::finishBlockMake(BlockMakeData *data,
Set block as modified Set block as modified
*/ */
block->raiseModified(MOD_STATE_WRITE_NEEDED, block->raiseModified(MOD_STATE_WRITE_NEEDED,
"finishBlockMake expireDayNightDiff"); MOD_REASON_EXPIRE_DAYNIGHTDIFF);
} }
/* /*
@ -2981,7 +2981,7 @@ void ServerMap::save(ModifiedState save_level)
save_started = true; save_started = true;
} }
modprofiler.add(block->getModifiedReason(), 1); modprofiler.add(block->getModifiedReasonString(), 1);
saveBlock(block); saveBlock(block);
block_count++; block_count++;

@ -38,6 +38,30 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
static const char *modified_reason_strings[] = {
"initial",
"reallocate",
"setIsUnderground",
"setLightingExpired",
"setGenerated",
"setNode",
"setNodeNoCheck",
"setTimestamp",
"NodeMetaRef::reportMetadataChange",
"clearAllObjects",
"Timestamp expired (step)",
"addActiveObjectRaw",
"removeRemovedObjects/remove",
"removeRemovedObjects/deactivate",
"Stored list cleared in activateObjects due to overflow",
"deactivateFarObjects: Static data moved in",
"deactivateFarObjects: Static data moved out",
"deactivateFarObjects: Static data changed considerably",
"finishBlockMake: expireDayNightDiff"
"unknown",
};
/* /*
MapBlock MapBlock
*/ */
@ -47,8 +71,7 @@ MapBlock::MapBlock(Map *parent, v3s16 pos, IGameDef *gamedef, bool dummy):
m_pos(pos), m_pos(pos),
m_gamedef(gamedef), m_gamedef(gamedef),
m_modified(MOD_STATE_WRITE_NEEDED), m_modified(MOD_STATE_WRITE_NEEDED),
m_modified_reason("initial"), m_modified_reason(MOD_REASON_INITIAL),
m_modified_reason_too_long(false),
is_underground(false), is_underground(false),
m_lighting_expired(true), m_lighting_expired(true),
m_day_night_differs(false), m_day_night_differs(false),
@ -112,6 +135,27 @@ MapNode MapBlock::getNodeParent(v3s16 p, bool *is_valid_position)
return data[p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X]; return data[p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X];
} }
std::string MapBlock::getModifiedReasonString()
{
std::string reason;
const u32 ubound = MYMIN(sizeof(m_modified_reason) * CHAR_BIT,
ARRLEN(modified_reason_strings));
for (u32 i = 0; i != ubound; i++) {
if ((m_modified_reason & (1 << i)) == 0)
continue;
reason += modified_reason_strings[i];
reason += ", ";
}
if (reason.length() > 2)
reason.resize(reason.length() - 2);
return reason;
}
/* /*
Propagates sunlight down through the block. Propagates sunlight down through the block.
Doesn't modify nodes that are not affected by sunlight. Doesn't modify nodes that are not affected by sunlight.

@ -97,9 +97,34 @@ public:
}; };
#endif #endif
/* ////
MapBlock itself //// MapBlock modified reason flags
*/ ////
#define MOD_REASON_INITIAL (1 << 0)
#define MOD_REASON_REALLOCATE (1 << 1)
#define MOD_REASON_SET_IS_UNDERGROUND (1 << 2)
#define MOD_REASON_SET_LIGHTING_EXPIRED (1 << 3)
#define MOD_REASON_SET_GENERATED (1 << 4)
#define MOD_REASON_SET_NODE (1 << 5)
#define MOD_REASON_SET_NODE_NO_CHECK (1 << 6)
#define MOD_REASON_SET_TIMESTAMP (1 << 7)
#define MOD_REASON_REPORT_META_CHANGE (1 << 8)
#define MOD_REASON_CLEAR_ALL_OBJECTS (1 << 9)
#define MOD_REASON_BLOCK_EXPIRED (1 << 10)
#define MOD_REASON_ADD_ACTIVE_OBJECT_RAW (1 << 11)
#define MOD_REASON_REMOVE_OBJECTS_REMOVE (1 << 12)
#define MOD_REASON_REMOVE_OBJECTS_DEACTIVATE (1 << 13)
#define MOD_REASON_TOO_MANY_OBJECTS (1 << 14)
#define MOD_REASON_STATIC_DATA_ADDED (1 << 15)
#define MOD_REASON_STATIC_DATA_REMOVED (1 << 16)
#define MOD_REASON_STATIC_DATA_CHANGED (1 << 17)
#define MOD_REASON_EXPIRE_DAYNIGHTDIFF (1 << 18)
#define MOD_REASON_UNKNOWN (1 << 19)
////
//// MapBlock itself
////
class MapBlock /*: public NodeContainer*/ class MapBlock /*: public NodeContainer*/
{ {
@ -119,150 +144,125 @@ public:
void reallocate() void reallocate()
{ {
if(data != NULL)
delete[] data; delete[] data;
u32 l = MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE; u32 datasize = MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE;
data = new MapNode[l]; data = new MapNode[datasize];
for(u32 i=0; i<l; i++){ for (u32 i = 0; i < datasize; i++)
//data[i] = MapNode();
data[i] = MapNode(CONTENT_IGNORE); data[i] = MapNode(CONTENT_IGNORE);
}
raiseModified(MOD_STATE_WRITE_NEEDED, "reallocate"); raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_REALLOCATE);
} }
/* ////
Flags //// Modification tracking methods
*/ ////
void raiseModified(u32 mod, u32 reason=MOD_REASON_UNKNOWN)
{
if (mod > m_modified) {
m_modified = mod;
m_modified_reason = reason;
if (m_modified >= MOD_STATE_WRITE_AT_UNLOAD)
m_disk_timestamp = m_timestamp;
} else if (mod == m_modified) {
m_modified_reason |= reason;
}
}
bool isDummy() inline u32 getModified()
{
return m_modified;
}
inline u32 getModifiedReason()
{
return m_modified_reason;
}
std::string getModifiedReasonString();
inline void resetModified()
{
m_modified = MOD_STATE_CLEAN;
m_modified_reason = 0;
}
////
//// Flags
////
inline bool isDummy()
{ {
return (data == NULL); return (data == NULL);
} }
void unDummify()
inline void unDummify()
{ {
assert(isDummy()); // Pre-condition assert(isDummy()); // Pre-condition
reallocate(); reallocate();
} }
// m_modified methods
void raiseModified(u32 mod, const std::string &reason="unknown")
{
if(mod > m_modified){
m_modified = mod;
m_modified_reason = reason;
m_modified_reason_too_long = false;
if(m_modified >= MOD_STATE_WRITE_AT_UNLOAD){
m_disk_timestamp = m_timestamp;
}
} else if(mod == m_modified){
if(!m_modified_reason_too_long){
if(m_modified_reason.size() < 40)
m_modified_reason += ", " + reason;
else{
m_modified_reason += "...";
m_modified_reason_too_long = true;
}
}
}
}
void raiseModified(u32 mod, const char *reason)
{
if (mod > m_modified){
m_modified = mod;
m_modified_reason = reason;
m_modified_reason_too_long = false;
if (m_modified >= MOD_STATE_WRITE_AT_UNLOAD){
m_disk_timestamp = m_timestamp;
}
}
else if (mod == m_modified){
if (!m_modified_reason_too_long){
if (m_modified_reason.size() < 40)
m_modified_reason += ", " + std::string(reason);
else{
m_modified_reason += "...";
m_modified_reason_too_long = true;
}
}
}
}
u32 getModified()
{
return m_modified;
}
std::string getModifiedReason()
{
return m_modified_reason;
}
void resetModified()
{
m_modified = MOD_STATE_CLEAN;
m_modified_reason = "none";
m_modified_reason_too_long = false;
}
// is_underground getter/setter // is_underground getter/setter
bool getIsUnderground() inline bool getIsUnderground()
{ {
return is_underground; return is_underground;
} }
void setIsUnderground(bool a_is_underground)
inline void setIsUnderground(bool a_is_underground)
{ {
is_underground = a_is_underground; is_underground = a_is_underground;
raiseModified(MOD_STATE_WRITE_NEEDED, "setIsUnderground"); raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_IS_UNDERGROUND);
} }
void setLightingExpired(bool expired) inline void setLightingExpired(bool expired)
{ {
if(expired != m_lighting_expired){ if (expired != m_lighting_expired){
m_lighting_expired = expired; m_lighting_expired = expired;
raiseModified(MOD_STATE_WRITE_NEEDED, "setLightingExpired"); raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_LIGHTING_EXPIRED);
} }
} }
bool getLightingExpired()
inline bool getLightingExpired()
{ {
return m_lighting_expired; return m_lighting_expired;
} }
bool isGenerated() inline bool isGenerated()
{ {
return m_generated; return m_generated;
} }
void setGenerated(bool b)
inline void setGenerated(bool b)
{ {
if(b != m_generated){ if (b != m_generated) {
raiseModified(MOD_STATE_WRITE_NEEDED, "setGenerated"); raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_GENERATED);
m_generated = b; m_generated = b;
} }
} }
bool isValid() inline bool isValid()
{ {
if(m_lighting_expired) if (m_lighting_expired)
return false; return false;
if(data == NULL) if (data == NULL)
return false; return false;
return true; return true;
} }
/* ////
Position stuff //// Position stuff
*/ ////
v3s16 getPos() inline v3s16 getPos()
{ {
return m_pos; return m_pos;
} }
v3s16 getPosRelative() inline v3s16 getPosRelative()
{ {
return m_pos * MAP_BLOCKSIZE; return m_pos * MAP_BLOCKSIZE;
} }
core::aabbox3d<s16> getBox() inline core::aabbox3d<s16> getBox()
{ {
return core::aabbox3d<s16>(getPosRelative(), return core::aabbox3d<s16>(getPosRelative(),
getPosRelative() getPosRelative()
@ -270,11 +270,11 @@ public:
- v3s16(1,1,1)); - v3s16(1,1,1));
} }
/* ////
Regular MapNode get-setters //// Regular MapNode get-setters
*/ ////
bool isValidPosition(s16 x, s16 y, s16 z) inline bool isValidPosition(s16 x, s16 y, s16 z)
{ {
return data != NULL return data != NULL
&& x >= 0 && x < MAP_BLOCKSIZE && x >= 0 && x < MAP_BLOCKSIZE
@ -282,127 +282,122 @@ public:
&& z >= 0 && z < MAP_BLOCKSIZE; && z >= 0 && z < MAP_BLOCKSIZE;
} }
bool isValidPosition(v3s16 p) inline bool isValidPosition(v3s16 p)
{ {
return isValidPosition(p.X, p.Y, p.Z); return isValidPosition(p.X, p.Y, p.Z);
} }
MapNode getNode(s16 x, s16 y, s16 z, bool *valid_position) inline MapNode getNode(s16 x, s16 y, s16 z, bool *valid_position)
{ {
*valid_position = isValidPosition(x, y, z); *valid_position = isValidPosition(x, y, z);
if (!*valid_position) if (!*valid_position)
return MapNode(CONTENT_IGNORE); return MapNode(CONTENT_IGNORE);
return data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x]; return data[z * MAP_BLOCKSIZE * MAP_BLOCKSIZE + y * MAP_BLOCKSIZE + x];
} }
MapNode getNode(v3s16 p, bool *valid_position) inline MapNode getNode(v3s16 p, bool *valid_position)
{ {
return getNode(p.X, p.Y, p.Z, valid_position); return getNode(p.X, p.Y, p.Z, valid_position);
} }
MapNode getNodeNoEx(v3s16 p) inline MapNode getNodeNoEx(v3s16 p)
{ {
bool is_valid; bool is_valid;
MapNode node = getNode(p.X, p.Y, p.Z, &is_valid); MapNode node = getNode(p.X, p.Y, p.Z, &is_valid);
return is_valid ? node : MapNode(CONTENT_IGNORE); return is_valid ? node : MapNode(CONTENT_IGNORE);
} }
void setNode(s16 x, s16 y, s16 z, MapNode & n) inline void setNode(s16 x, s16 y, s16 z, MapNode & n)
{ {
if(data == NULL) if (!isValidPosition(x, y, z))
throw InvalidPositionException(); throw InvalidPositionException();
if(x < 0 || x >= MAP_BLOCKSIZE) throw InvalidPositionException();
if(y < 0 || y >= MAP_BLOCKSIZE) throw InvalidPositionException(); data[z * zstride + y * ystride + x] = n;
if(z < 0 || z >= MAP_BLOCKSIZE) throw InvalidPositionException(); raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_NODE);
data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x] = n;
raiseModified(MOD_STATE_WRITE_NEEDED, "setNode");
} }
void setNode(v3s16 p, MapNode & n) inline void setNode(v3s16 p, MapNode & n)
{ {
setNode(p.X, p.Y, p.Z, n); setNode(p.X, p.Y, p.Z, n);
} }
/* ////
Non-checking variants of the above //// Non-checking variants of the above
*/ ////
MapNode getNodeNoCheck(s16 x, s16 y, s16 z, bool *valid_position) inline MapNode getNodeNoCheck(s16 x, s16 y, s16 z, bool *valid_position)
{ {
*valid_position = data != NULL; *valid_position = data != NULL;
if(!valid_position) if (!valid_position)
return MapNode(CONTENT_IGNORE); return MapNode(CONTENT_IGNORE);
return data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x]; return data[z * zstride + y * ystride + x];
} }
MapNode getNodeNoCheck(v3s16 p, bool *valid_position) inline MapNode getNodeNoCheck(v3s16 p, bool *valid_position)
{ {
return getNodeNoCheck(p.X, p.Y, p.Z, valid_position); return getNodeNoCheck(p.X, p.Y, p.Z, valid_position);
} }
void setNodeNoCheck(s16 x, s16 y, s16 z, MapNode & n) inline void setNodeNoCheck(s16 x, s16 y, s16 z, MapNode & n)
{ {
if(data == NULL) if (data == NULL)
throw InvalidPositionException(); throw InvalidPositionException();
data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x] = n;
raiseModified(MOD_STATE_WRITE_NEEDED, "setNodeNoCheck"); data[z * zstride + y * ystride + x] = n;
raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_NODE_NO_CHECK);
} }
void setNodeNoCheck(v3s16 p, MapNode & n) inline void setNodeNoCheck(v3s16 p, MapNode & n)
{ {
setNodeNoCheck(p.X, p.Y, p.Z, n); setNodeNoCheck(p.X, p.Y, p.Z, n);
} }
/* // These functions consult the parent container if the position
These functions consult the parent container if the position // is not valid on this MapBlock.
is not valid on this MapBlock.
*/
bool isValidPositionParent(v3s16 p); bool isValidPositionParent(v3s16 p);
MapNode getNodeParent(v3s16 p, bool *is_valid_position = NULL); MapNode getNodeParent(v3s16 p, bool *is_valid_position = NULL);
void setNodeParent(v3s16 p, MapNode & n); void setNodeParent(v3s16 p, MapNode & n);
void drawbox(s16 x0, s16 y0, s16 z0, s16 w, s16 h, s16 d, MapNode node) inline void drawbox(s16 x0, s16 y0, s16 z0, s16 w, s16 h, s16 d, MapNode node)
{ {
for(u16 z=0; z<d; z++) for (u16 z = 0; z < d; z++)
for(u16 y=0; y<h; y++) for (u16 y = 0; y < h; y++)
for(u16 x=0; x<w; x++) for (u16 x = 0; x < w; x++)
setNode(x0+x, y0+y, z0+z, node); setNode(x0 + x, y0 + y, z0 + z, node);
} }
// See comments in mapblock.cpp // See comments in mapblock.cpp
bool propagateSunlight(std::set<v3s16> & light_sources, bool propagateSunlight(std::set<v3s16> &light_sources,
bool remove_light=false, bool *black_air_left=NULL); bool remove_light=false, bool *black_air_left=NULL);
// Copies data to VoxelManipulator to getPosRelative() // Copies data to VoxelManipulator to getPosRelative()
void copyTo(VoxelManipulator &dst); void copyTo(VoxelManipulator &dst);
// Copies data from VoxelManipulator getPosRelative() // Copies data from VoxelManipulator getPosRelative()
void copyFrom(VoxelManipulator &dst); void copyFrom(VoxelManipulator &dst);
/* // Update day-night lighting difference flag.
Update day-night lighting difference flag. // Sets m_day_night_differs to appropriate value.
Sets m_day_night_differs to appropriate value. // These methods don't care about neighboring blocks.
These methods don't care about neighboring blocks.
*/
void actuallyUpdateDayNightDiff(); void actuallyUpdateDayNightDiff();
/*
Call this to schedule what the previous function does to be done // Call this to schedule what the previous function does to be done
when the value is actually needed. // when the value is actually needed.
*/
void expireDayNightDiff(); void expireDayNightDiff();
bool getDayNightDiff() inline bool getDayNightDiff()
{ {
if(m_day_night_differs_expired) if (m_day_night_differs_expired)
actuallyUpdateDayNightDiff(); actuallyUpdateDayNightDiff();
return m_day_night_differs; return m_day_night_differs;
} }
/* ////
Miscellaneous stuff //// Miscellaneous stuff
*/ ////
/* /*
Tries to measure ground level. Tries to measure ground level.
@ -414,83 +409,98 @@ public:
*/ */
s16 getGroundLevel(v2s16 p2d); s16 getGroundLevel(v2s16 p2d);
/* ////
Timestamp (see m_timestamp) //// Timestamp (see m_timestamp)
NOTE: BLOCK_TIMESTAMP_UNDEFINED=0xffffffff means there is no timestamp. ////
*/
void setTimestamp(u32 time) // NOTE: BLOCK_TIMESTAMP_UNDEFINED=0xffffffff means there is no timestamp.
inline void setTimestamp(u32 time)
{ {
m_timestamp = time; m_timestamp = time;
raiseModified(MOD_STATE_WRITE_AT_UNLOAD, "setTimestamp"); raiseModified(MOD_STATE_WRITE_AT_UNLOAD, MOD_REASON_SET_TIMESTAMP);
} }
void setTimestampNoChangedFlag(u32 time)
inline void setTimestampNoChangedFlag(u32 time)
{ {
m_timestamp = time; m_timestamp = time;
} }
u32 getTimestamp()
inline u32 getTimestamp()
{ {
return m_timestamp; return m_timestamp;
} }
u32 getDiskTimestamp()
inline u32 getDiskTimestamp()
{ {
return m_disk_timestamp; return m_disk_timestamp;
} }
/* ////
See m_usage_timer //// Usage timer (see m_usage_timer)
*/ ////
void resetUsageTimer()
inline void resetUsageTimer()
{ {
m_usage_timer = 0; m_usage_timer = 0;
} }
void incrementUsageTimer(float dtime)
inline void incrementUsageTimer(float dtime)
{ {
m_usage_timer += dtime; m_usage_timer += dtime;
} }
float getUsageTimer()
inline float getUsageTimer()
{ {
return m_usage_timer; return m_usage_timer;
} }
/* ////
See m_refcount //// Reference counting (see m_refcount)
*/ ////
void refGrab()
inline void refGrab()
{ {
m_refcount++; m_refcount++;
} }
void refDrop()
inline void refDrop()
{ {
m_refcount--; m_refcount--;
} }
int refGet()
inline int refGet()
{ {
return m_refcount; return m_refcount;
} }
/* ////
Node Timers //// Node Timers
*/ ////
// Get timer
NodeTimer getNodeTimer(v3s16 p){ inline NodeTimer getNodeTimer(v3s16 p)
{
return m_node_timers.get(p); return m_node_timers.get(p);
} }
// Deletes timer
void removeNodeTimer(v3s16 p){ inline void removeNodeTimer(v3s16 p)
{
m_node_timers.remove(p); m_node_timers.remove(p);
} }
// Deletes old timer and sets a new one
void setNodeTimer(v3s16 p, NodeTimer t){ inline void setNodeTimer(v3s16 p, NodeTimer t)
{
m_node_timers.set(p,t); m_node_timers.set(p,t);
} }
// Deletes all timers
void clearNodeTimers(){ inline void clearNodeTimers()
{
m_node_timers.clear(); m_node_timers.clear();
} }
/* ////
Serialization //// Serialization
*/ ///
// These don't write or read version by itself // These don't write or read version by itself
// Set disk to true for on-disk format, false for over-the-network format // Set disk to true for on-disk format, false for over-the-network format
@ -514,16 +524,15 @@ private:
Used only internally, because changes can't be tracked Used only internally, because changes can't be tracked
*/ */
MapNode & getNodeRef(s16 x, s16 y, s16 z) inline MapNode &getNodeRef(s16 x, s16 y, s16 z)
{ {
if(data == NULL) if (!isValidPosition(x, y, z))
throw InvalidPositionException(); throw InvalidPositionException();
if(x < 0 || x >= MAP_BLOCKSIZE) throw InvalidPositionException();
if(y < 0 || y >= MAP_BLOCKSIZE) throw InvalidPositionException(); return data[z * zstride + y * ystride + x];
if(z < 0 || z >= MAP_BLOCKSIZE) throw InvalidPositionException();
return data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x];
} }
MapNode & getNodeRef(v3s16 &p)
inline MapNode &getNodeRef(v3s16 &p)
{ {
return getNodeRef(p.X, p.Y, p.Z); return getNodeRef(p.X, p.Y, p.Z);
} }
@ -541,6 +550,9 @@ public:
NodeTimerList m_node_timers; NodeTimerList m_node_timers;
StaticObjectList m_static_objects; StaticObjectList m_static_objects;
static const u32 ystride = MAP_BLOCKSIZE;
static const u32 zstride = MAP_BLOCKSIZE * MAP_BLOCKSIZE;
private: private:
/* /*
Private member variables Private member variables
@ -557,7 +569,7 @@ private:
If NULL, block is a dummy block. If NULL, block is a dummy block.
Dummy blocks are used for caching not-found-on-disk blocks. Dummy blocks are used for caching not-found-on-disk blocks.
*/ */
MapNode * data; MapNode *data;
/* /*
- On the server, this is used for telling whether the - On the server, this is used for telling whether the
@ -565,8 +577,7 @@ private:
- On the client, this is used for nothing. - On the client, this is used for nothing.
*/ */
u32 m_modified; u32 m_modified;
std::string m_modified_reason; u32 m_modified_reason;
bool m_modified_reason_too_long;
/* /*
When propagating sunlight and the above block doesn't exist, When propagating sunlight and the above block doesn't exist,

@ -178,7 +178,7 @@ bool RollbackAction::applyRevert(Map *map, InventoryManager *imgr, IGameDef *gam
MapBlock *block = map->getBlockNoCreateNoEx(blockpos); MapBlock *block = map->getBlockNoCreateNoEx(blockpos);
if (block) { if (block) {
block->raiseModified(MOD_STATE_WRITE_NEEDED, block->raiseModified(MOD_STATE_WRITE_NEEDED,
"NodeMetaRef::reportMetadataChange"); MOD_REASON_REPORT_META_CHANGE);
} }
} catch (InvalidPositionException &e) { } catch (InvalidPositionException &e) {
infostream << "RollbackAction::applyRevert(): " infostream << "RollbackAction::applyRevert(): "

@ -63,9 +63,10 @@ void NodeMetaRef::reportMetadataChange(NodeMetaRef *ref)
ref->m_env->getMap().dispatchEvent(&event); ref->m_env->getMap().dispatchEvent(&event);
// Set the block to be saved // Set the block to be saved
MapBlock *block = ref->m_env->getMap().getBlockNoCreateNoEx(blockpos); MapBlock *block = ref->m_env->getMap().getBlockNoCreateNoEx(blockpos);
if(block) if (block) {
block->raiseModified(MOD_STATE_WRITE_NEEDED, block->raiseModified(MOD_STATE_WRITE_NEEDED,
"NodeMetaRef::reportMetadataChange"); MOD_REASON_REPORT_META_CHANGE);
}
} }
// Exported functions // Exported functions