Remove unused MapBlock functionality

This commit is contained in:
Jude Melton-Houghton 2022-10-05 07:55:33 -04:00
parent 7a28f2c4fa
commit 8f996e4a7c
9 changed files with 110 additions and 250 deletions

@ -311,7 +311,7 @@ void RemoteClient::GetNextBlocks (
block->resetUsageTimer(); block->resetUsageTimer();
// Check whether the block exists (with data) // Check whether the block exists (with data)
if (block->isDummy() || !block->isGenerated()) if (!block->isGenerated())
block_not_found = true; block_not_found = true;
/* /*

@ -596,7 +596,7 @@ EmergeAction EmergeThread::getBlockOrStartGen(
// 1). Attempt to fetch block from memory // 1). Attempt to fetch block from memory
*block = m_map->getBlockNoCreateNoEx(pos); *block = m_map->getBlockNoCreateNoEx(pos);
if (*block && !(*block)->isDummy()) { if (*block) {
if ((*block)->isGenerated()) if ((*block)->isGenerated())
return EMERGE_FROM_MEMORY; return EMERGE_FROM_MEMORY;
} else { } else {

@ -1131,14 +1131,16 @@ static bool recompress_map_database(const GameParams &game_params, const Setting
iss.str(data); iss.str(data);
iss.clear(); iss.clear();
MapBlock mb(nullptr, v3s16(0,0,0), &server); {
u8 ver = readU8(iss); MapBlock mb(nullptr, v3s16(0,0,0), &server);
mb.deSerialize(iss, ver, true); u8 ver = readU8(iss);
mb.deSerialize(iss, ver, true);
oss.str(""); oss.str("");
oss.clear(); oss.clear();
writeU8(oss, serialize_as_ver); writeU8(oss, serialize_as_ver);
mb.serialize(oss, serialize_as_ver, true, -1); mb.serialize(oss, serialize_as_ver, true, -1);
}
db->saveBlock(*it, oss.str()); db->saveBlock(*it, oss.str());

@ -158,10 +158,9 @@ MapNode Map::getNode(v3s16 p, bool *is_valid_position)
} }
v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
bool is_valid_p; MapNode node = block->getNodeNoCheck(relpos);
MapNode node = block->getNodeNoCheck(relpos, &is_valid_p);
if (is_valid_position != NULL) if (is_valid_position != NULL)
*is_valid_position = is_valid_p; *is_valid_position = true;
return node; return node;
} }
@ -172,10 +171,9 @@ static void set_node_in_block(MapBlock *block, v3s16 relpos, MapNode n)
const NodeDefManager *nodedef = block->getParent()->getNodeDefManager(); const NodeDefManager *nodedef = block->getParent()->getNodeDefManager();
v3s16 blockpos = block->getPos(); v3s16 blockpos = block->getPos();
v3s16 p = blockpos * MAP_BLOCKSIZE + relpos; v3s16 p = blockpos * MAP_BLOCKSIZE + relpos;
bool temp_bool;
errorstream<<"Not allowing to place CONTENT_IGNORE" errorstream<<"Not allowing to place CONTENT_IGNORE"
<<" while trying to replace \"" <<" while trying to replace \""
<<nodedef->get(block->getNodeNoCheck(relpos, &temp_bool)).name <<nodedef->get(block->getNodeNoCheck(relpos)).name
<<"\" at "<<PP(p)<<" (block "<<PP(blockpos)<<")"<<std::endl; <<"\" at "<<PP(p)<<" (block "<<PP(blockpos)<<")"<<std::endl;
return; return;
} }
@ -200,12 +198,10 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
v3s16 blockpos = getNodeBlockPos(p); v3s16 blockpos = getNodeBlockPos(p);
MapBlock *block = getBlockNoCreate(blockpos); MapBlock *block = getBlockNoCreate(blockpos);
if (block->isDummy())
throw InvalidPositionException();
v3s16 relpos = p - blockpos * MAP_BLOCKSIZE; v3s16 relpos = p - blockpos * MAP_BLOCKSIZE;
// This is needed for updating the lighting // This is needed for updating the lighting
MapNode oldnode = block->getNodeUnsafe(relpos); MapNode oldnode = block->getNodeNoCheck(relpos);
// Remove node metadata // Remove node metadata
if (remove_metadata) { if (remove_metadata) {
@ -1515,8 +1511,6 @@ MapBlock * ServerMap::createBlock(v3s16 p)
MapBlock *block = sector->getBlockNoCreateNoEx(block_y); MapBlock *block = sector->getBlockNoCreateNoEx(block_y);
if (block) { if (block) {
if(block->isDummy())
block->unDummify();
return block; return block;
} }
// Create blank // Create blank
@ -1529,7 +1523,7 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool create_blank)
{ {
{ {
MapBlock *block = getBlockNoCreateNoEx(p); MapBlock *block = getBlockNoCreateNoEx(p);
if (block && !block->isDummy()) if (block)
return block; return block;
} }
@ -1756,13 +1750,6 @@ bool ServerMap::saveBlock(MapBlock *block, MapDatabase *db, int compression_leve
{ {
v3s16 p3d = block->getPos(); v3s16 p3d = block->getPos();
// Dummy blocks are not written
if (block->isDummy()) {
warningstream << "saveBlock: Not writing dummy block "
<< PP(p3d) << std::endl;
return true;
}
// Format used for writing // Format used for writing
u8 version = SER_FMT_VER_HIGHEST_WRITE; u8 version = SER_FMT_VER_HIGHEST_WRITE;
@ -1962,7 +1949,7 @@ void MMVManip::initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max,
TimeTaker timer2("emerge load", &emerge_load_time); TimeTaker timer2("emerge load", &emerge_load_time);
block = m_map->getBlockNoCreateNoEx(p); block = m_map->getBlockNoCreateNoEx(p);
if (!block || block->isDummy()) if (!block)
block_data_inexistent = true; block_data_inexistent = true;
else else
block->copyTo(*this); block->copyTo(*this);

@ -66,14 +66,14 @@ static const char *modified_reason_strings[] = {
MapBlock MapBlock
*/ */
MapBlock::MapBlock(Map *parent, v3s16 pos, IGameDef *gamedef, bool dummy): MapBlock::MapBlock(Map *parent, v3s16 pos, IGameDef *gamedef):
m_parent(parent), m_parent(parent),
m_pos(pos), m_pos(pos),
m_pos_relative(pos * MAP_BLOCKSIZE), m_pos_relative(pos * MAP_BLOCKSIZE),
m_gamedef(gamedef) m_gamedef(gamedef),
data(new MapNode[nodecount])
{ {
if (!dummy) reallocate();
reallocate();
} }
MapBlock::~MapBlock() MapBlock::~MapBlock()
@ -102,11 +102,6 @@ MapNode MapBlock::getNodeParent(v3s16 p, bool *is_valid_position)
if (!isValidPosition(p)) if (!isValidPosition(p))
return m_parent->getNode(getPosRelative() + p, is_valid_position); return m_parent->getNode(getPosRelative() + p, is_valid_position);
if (!data) {
if (is_valid_position)
*is_valid_position = false;
return {CONTENT_IGNORE};
}
if (is_valid_position) if (is_valid_position)
*is_valid_position = true; *is_valid_position = true;
return data[p.Z * zstride + p.Y * ystride + p.X]; return data[p.Z * zstride + p.Y * ystride + p.X];
@ -161,11 +156,6 @@ void MapBlock::actuallyUpdateDayNightDiff()
// Running this function un-expires m_day_night_differs // Running this function un-expires m_day_night_differs
m_day_night_differs_expired = false; m_day_night_differs_expired = false;
if (!data) {
m_day_night_differs = false;
return;
}
bool differs = false; bool differs = false;
/* /*
@ -209,12 +199,6 @@ void MapBlock::actuallyUpdateDayNightDiff()
void MapBlock::expireDayNightDiff() void MapBlock::expireDayNightDiff()
{ {
if (!data) {
m_day_night_differs = false;
m_day_night_differs_expired = false;
return;
}
m_day_night_differs_expired = true; m_day_night_differs_expired = true;
} }
@ -339,9 +323,6 @@ void MapBlock::serialize(std::ostream &os_compressed, u8 version, bool disk, int
if(!ser_ver_supported(version)) if(!ser_ver_supported(version))
throw VersionMismatchException("ERROR: MapBlock format not supported"); throw VersionMismatchException("ERROR: MapBlock format not supported");
if (!data)
throw SerializationError("ERROR: Not writing dummy block.");
FATAL_ERROR_IF(version < SER_FMT_VER_LOWEST_WRITE, "Serialisation version error"); FATAL_ERROR_IF(version < SER_FMT_VER_LOWEST_WRITE, "Serialisation version error");
std::ostringstream os_raw(std::ios_base::binary); std::ostringstream os_raw(std::ios_base::binary);
@ -446,10 +427,6 @@ void MapBlock::serialize(std::ostream &os_compressed, u8 version, bool disk, int
void MapBlock::serializeNetworkSpecific(std::ostream &os) void MapBlock::serializeNetworkSpecific(std::ostream &os)
{ {
if (!data) {
throw SerializationError("ERROR: Not writing dummy block.");
}
writeU8(os, 2); // version writeU8(os, 2); // version
} }
@ -861,52 +838,45 @@ std::string analyze_block(MapBlock *block)
desc<<"lighting_complete: "<<block->getLightingComplete()<<", "; desc<<"lighting_complete: "<<block->getLightingComplete()<<", ";
if(block->isDummy()) bool full_ignore = true;
bool some_ignore = false;
bool full_air = true;
bool some_air = false;
for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
{ {
desc<<"Dummy, "; v3s16 p(x0,y0,z0);
MapNode n = block->getNodeNoEx(p);
content_t c = n.getContent();
if(c == CONTENT_IGNORE)
some_ignore = true;
else
full_ignore = false;
if(c == CONTENT_AIR)
some_air = true;
else
full_air = false;
} }
else
{
bool full_ignore = true;
bool some_ignore = false;
bool full_air = true;
bool some_air = false;
for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
{
v3s16 p(x0,y0,z0);
MapNode n = block->getNodeNoEx(p);
content_t c = n.getContent();
if(c == CONTENT_IGNORE)
some_ignore = true;
else
full_ignore = false;
if(c == CONTENT_AIR)
some_air = true;
else
full_air = false;
}
desc<<"content {"; desc<<"content {";
std::ostringstream ss; std::ostringstream ss;
if(full_ignore) if(full_ignore)
ss<<"IGNORE (full), "; ss<<"IGNORE (full), ";
else if(some_ignore) else if(some_ignore)
ss<<"IGNORE, "; ss<<"IGNORE, ";
if(full_air) if(full_air)
ss<<"AIR (full), "; ss<<"AIR (full), ";
else if(some_air) else if(some_air)
ss<<"AIR, "; ss<<"AIR, ";
if(ss.str().size()>=2) if(ss.str().size()>=2)
desc<<ss.str().substr(0, ss.str().size()-2); desc<<ss.str().substr(0, ss.str().size()-2);
desc<<"}, "; desc<<"}, ";
}
return desc.str().substr(0, desc.str().size()-2); return desc.str().substr(0, desc.str().size()-2);
} }

@ -73,7 +73,7 @@ class VoxelManipulator;
class MapBlock class MapBlock
{ {
public: public:
MapBlock(Map *parent, v3s16 pos, IGameDef *gamedef, bool dummy=false); MapBlock(Map *parent, v3s16 pos, IGameDef *gamedef);
~MapBlock(); ~MapBlock();
/*virtual u16 nodeContainerId() const /*virtual u16 nodeContainerId() const
@ -88,11 +88,8 @@ public:
void reallocate() void reallocate()
{ {
delete[] data;
data = new MapNode[nodecount];
for (u32 i = 0; i < nodecount; i++) for (u32 i = 0; i < nodecount; i++)
data[i] = MapNode(CONTENT_IGNORE); data[i] = MapNode(CONTENT_IGNORE);
raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_REALLOCATE); raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_REALLOCATE);
} }
@ -140,17 +137,6 @@ public:
//// Flags //// Flags
//// ////
inline bool isDummy() const
{
return !data;
}
inline void unDummify()
{
assert(isDummy()); // Pre-condition
reallocate();
}
// is_underground getter/setter // is_underground getter/setter
inline bool getIsUnderground() inline bool getIsUnderground()
{ {
@ -242,8 +228,7 @@ public:
inline bool isValidPosition(s16 x, s16 y, s16 z) inline bool isValidPosition(s16 x, s16 y, s16 z)
{ {
return data return x >= 0 && x < MAP_BLOCKSIZE
&& x >= 0 && x < MAP_BLOCKSIZE
&& y >= 0 && y < MAP_BLOCKSIZE && y >= 0 && y < MAP_BLOCKSIZE
&& z >= 0 && z < MAP_BLOCKSIZE; && z >= 0 && z < MAP_BLOCKSIZE;
} }
@ -274,7 +259,7 @@ public:
return getNode(p.X, p.Y, p.Z, &is_valid); return getNode(p.X, p.Y, p.Z, &is_valid);
} }
inline void setNode(s16 x, s16 y, s16 z, MapNode & n) inline void setNode(s16 x, s16 y, s16 z, MapNode n)
{ {
if (!isValidPosition(x, y, z)) if (!isValidPosition(x, y, z))
throw InvalidPositionException(); throw InvalidPositionException();
@ -283,7 +268,7 @@ public:
raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_NODE); raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_NODE);
} }
inline 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);
} }
@ -292,46 +277,23 @@ public:
//// Non-checking variants of the above //// Non-checking variants of the above
//// ////
inline MapNode getNodeNoCheck(s16 x, s16 y, s16 z, bool *valid_position) inline MapNode getNodeNoCheck(s16 x, s16 y, s16 z)
{
*valid_position = data != nullptr;
if (!*valid_position)
return {CONTENT_IGNORE};
return data[z * zstride + y * ystride + x];
}
inline MapNode getNodeNoCheck(v3s16 p, bool *valid_position)
{
return getNodeNoCheck(p.X, p.Y, p.Z, valid_position);
}
////
//// Non-checking, unsafe variants of the above
//// MapBlock must be loaded by another function in the same scope/function
//// Caller must ensure that this is not a dummy block (by calling isDummy())
////
inline const MapNode &getNodeUnsafe(s16 x, s16 y, s16 z)
{ {
return data[z * zstride + y * ystride + x]; return data[z * zstride + y * ystride + x];
} }
inline const MapNode &getNodeUnsafe(v3s16 &p) inline MapNode getNodeNoCheck(v3s16 p)
{ {
return getNodeUnsafe(p.X, p.Y, p.Z); return getNodeNoCheck(p.X, p.Y, p.Z);
} }
inline void setNodeNoCheck(s16 x, s16 y, s16 z, MapNode & n) inline void setNodeNoCheck(s16 x, s16 y, s16 z, MapNode n)
{ {
if (!data)
throw InvalidPositionException();
data[z * zstride + y * ystride + x] = n; data[z * zstride + y * ystride + x] = n;
raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_NODE_NO_CHECK); raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_NODE_NO_CHECK);
} }
inline 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);
} }
@ -432,12 +394,12 @@ public:
//// Node Timers //// Node Timers
//// ////
inline NodeTimer getNodeTimer(const v3s16 &p) inline NodeTimer getNodeTimer(v3s16 p)
{ {
return m_node_timers.get(p); return m_node_timers.get(p);
} }
inline void removeNodeTimer(const v3s16 &p) inline void removeNodeTimer(v3s16 p)
{ {
m_node_timers.remove(p); m_node_timers.remove(p);
} }
@ -473,23 +435,6 @@ private:
void deSerialize_pre22(std::istream &is, u8 version, bool disk); void deSerialize_pre22(std::istream &is, u8 version, bool disk);
/*
Used only internally, because changes can't be tracked
*/
inline MapNode &getNodeRef(s16 x, s16 y, s16 z)
{
if (!isValidPosition(x, y, z))
throw InvalidPositionException();
return data[z * zstride + y * ystride + x];
}
inline MapNode &getNodeRef(v3s16 &p)
{
return getNodeRef(p.X, p.Y, p.Z);
}
public: public:
/* /*
Public member variables Public member variables
@ -536,11 +481,7 @@ private:
IGameDef *m_gamedef; IGameDef *m_gamedef;
/* MapNode *const data;
If NULL, block is a dummy block.
Dummy blocks are used for caching not-found-on-disk blocks.
*/
MapNode *data = nullptr;
/* /*
- On the server, this is used for telling whether the - On the server, this is used for telling whether the
@ -624,12 +565,12 @@ inline bool blockpos_over_max_limit(v3s16 p)
/* /*
Returns the position of the block where the node is located Returns the position of the block where the node is located
*/ */
inline v3s16 getNodeBlockPos(const v3s16 &p) inline v3s16 getNodeBlockPos(v3s16 p)
{ {
return getContainerPos(p, MAP_BLOCKSIZE); return getContainerPos(p, MAP_BLOCKSIZE);
} }
inline void getNodeBlockPosWithOffset(const v3s16 &p, v3s16 &block, v3s16 &offset) inline void getNodeBlockPosWithOffset(v3s16 p, v3s16 &block, v3s16 &offset)
{ {
getContainerPosWithOffset(p, MAP_BLOCKSIZE, block, offset); getContainerPosWithOffset(p, MAP_BLOCKSIZE, block, offset);
} }

@ -85,13 +85,12 @@ inline MapBlock *ReflowScan::lookupBlock(int x, int y, int z)
inline bool ReflowScan::isLiquidFlowableTo(int x, int y, int z) inline bool ReflowScan::isLiquidFlowableTo(int x, int y, int z)
{ {
// Tests whether (x,y,z) is a node to which liquid might flow. // Tests whether (x,y,z) is a node to which liquid might flow.
bool valid_position;
MapBlock *block = lookupBlock(x, y, z); MapBlock *block = lookupBlock(x, y, z);
if (block) { if (block) {
int dx = (MAP_BLOCKSIZE + x) % MAP_BLOCKSIZE; int dx = (MAP_BLOCKSIZE + x) % MAP_BLOCKSIZE;
int dy = (MAP_BLOCKSIZE + y) % MAP_BLOCKSIZE; int dy = (MAP_BLOCKSIZE + y) % MAP_BLOCKSIZE;
int dz = (MAP_BLOCKSIZE + z) % MAP_BLOCKSIZE; int dz = (MAP_BLOCKSIZE + z) % MAP_BLOCKSIZE;
MapNode node = block->getNodeNoCheck(dx, dy, dz, &valid_position); MapNode node = block->getNodeNoCheck(dx, dy, dz);
if (node.getContent() != CONTENT_IGNORE) { if (node.getContent() != CONTENT_IGNORE) {
const ContentFeatures &f = m_ndef->get(node); const ContentFeatures &f = m_ndef->get(node);
// NOTE: No need to check for flowing nodes with lower liquid level // NOTE: No need to check for flowing nodes with lower liquid level
@ -115,8 +114,6 @@ inline bool ReflowScan::isLiquidHorizontallyFlowable(int x, int y, int z)
void ReflowScan::scanColumn(int x, int z) void ReflowScan::scanColumn(int x, int z)
{ {
bool valid_position;
// Is the column inside a loaded block? // Is the column inside a loaded block?
MapBlock *block = lookupBlock(x, 0, z); MapBlock *block = lookupBlock(x, 0, z);
if (!block) if (!block)
@ -129,7 +126,7 @@ void ReflowScan::scanColumn(int x, int z)
// Get the state from the node above the scanned block // Get the state from the node above the scanned block
bool was_ignore, was_liquid; bool was_ignore, was_liquid;
if (above) { if (above) {
MapNode node = above->getNodeNoCheck(dx, 0, dz, &valid_position); MapNode node = above->getNodeNoCheck(dx, 0, dz);
was_ignore = node.getContent() == CONTENT_IGNORE; was_ignore = node.getContent() == CONTENT_IGNORE;
was_liquid = m_ndef->get(node).isLiquid(); was_liquid = m_ndef->get(node).isLiquid();
} else { } else {
@ -141,7 +138,7 @@ void ReflowScan::scanColumn(int x, int z)
// Scan through the whole block // Scan through the whole block
for (s16 y = MAP_BLOCKSIZE - 1; y >= 0; y--) { for (s16 y = MAP_BLOCKSIZE - 1; y >= 0; y--) {
MapNode node = block->getNodeNoCheck(dx, y, dz, &valid_position); MapNode node = block->getNodeNoCheck(dx, y, dz);
const ContentFeatures &f = m_ndef->get(node); const ContentFeatures &f = m_ndef->get(node);
bool is_ignore = node.getContent() == CONTENT_IGNORE; bool is_ignore = node.getContent() == CONTENT_IGNORE;
bool is_liquid = f.isLiquid(); bool is_liquid = f.isLiquid();
@ -179,7 +176,7 @@ void ReflowScan::scanColumn(int x, int z)
// Check the node below the current block // Check the node below the current block
MapBlock *below = lookupBlock(x, -1, z); MapBlock *below = lookupBlock(x, -1, z);
if (below) { if (below) {
MapNode node = below->getNodeNoCheck(dx, MAP_BLOCKSIZE - 1, dz, &valid_position); MapNode node = below->getNodeNoCheck(dx, MAP_BLOCKSIZE - 1, dz);
const ContentFeatures &f = m_ndef->get(node); const ContentFeatures &f = m_ndef->get(node);
bool is_ignore = node.getContent() == CONTENT_IGNORE; bool is_ignore = node.getContent() == CONTENT_IGNORE;
bool is_liquid = f.isLiquid(); bool is_liquid = f.isLiquid();

@ -258,7 +258,6 @@ void LBMManager::applyLBMs(ServerEnvironment *env, MapBlock *block, u32 stamp)
v3s16 pos; v3s16 pos;
MapNode n; MapNode n;
content_t c; content_t c;
bool pos_valid; // dummy, we know it's valid
auto it = getLBMsIntroducedAfter(stamp); auto it = getLBMsIntroducedAfter(stamp);
for (; it != m_lbm_lookup.end(); ++it) { for (; it != m_lbm_lookup.end(); ++it) {
// Cache previous version to speedup lookup which has a very high performance // Cache previous version to speedup lookup which has a very high performance
@ -269,7 +268,7 @@ void LBMManager::applyLBMs(ServerEnvironment *env, MapBlock *block, u32 stamp)
for (pos.X = 0; pos.X < MAP_BLOCKSIZE; pos.X++) for (pos.X = 0; pos.X < MAP_BLOCKSIZE; pos.X++)
for (pos.Y = 0; pos.Y < MAP_BLOCKSIZE; pos.Y++) for (pos.Y = 0; pos.Y < MAP_BLOCKSIZE; pos.Y++)
for (pos.Z = 0; pos.Z < MAP_BLOCKSIZE; pos.Z++) { for (pos.Z = 0; pos.Z < MAP_BLOCKSIZE; pos.Z++) {
n = block->getNodeNoCheck(pos, &pos_valid); n = block->getNodeNoCheck(pos);
c = n.getContent(); c = n.getContent();
// If content_t are not matching perform an LBM lookup // If content_t are not matching perform an LBM lookup
@ -850,7 +849,7 @@ public:
} }
void apply(MapBlock *block, int &blocks_scanned, int &abms_run, int &blocks_cached) void apply(MapBlock *block, int &blocks_scanned, int &abms_run, int &blocks_cached)
{ {
if(m_aabms.empty() || block->isDummy()) if(m_aabms.empty())
return; return;
// Check the content type cache first // Check the content type cache first
@ -884,7 +883,7 @@ public:
for(p0.Y=0; p0.Y<MAP_BLOCKSIZE; p0.Y++) for(p0.Y=0; p0.Y<MAP_BLOCKSIZE; p0.Y++)
for(p0.Z=0; p0.Z<MAP_BLOCKSIZE; p0.Z++) for(p0.Z=0; p0.Z<MAP_BLOCKSIZE; p0.Z++)
{ {
const MapNode &n = block->getNodeUnsafe(p0); const MapNode &n = block->getNodeNoCheck(p0);
content_t c = n.getContent(); content_t c = n.getContent();
// Cache content types as we go // Cache content types as we go
if (!block->contents_cached && !block->do_not_cache_contents) { if (!block->contents_cached && !block->do_not_cache_contents) {
@ -920,7 +919,7 @@ public:
if (block->isValidPosition(p1)) { if (block->isValidPosition(p1)) {
// if the neighbor is found on the same map block // if the neighbor is found on the same map block
// get it straight from there // get it straight from there
const MapNode &n = block->getNodeUnsafe(p1); const MapNode &n = block->getNodeNoCheck(p1);
c = n.getContent(); c = n.getContent();
} else { } else {
// otherwise consult the map // otherwise consult the map
@ -1589,7 +1588,7 @@ ServerEnvironment::BlockStatus ServerEnvironment::getBlockStatus(v3s16 blockpos)
return BS_ACTIVE; return BS_ACTIVE;
const MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos); const MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
if (block && !block->isDummy()) if (block)
return BS_LOADED; return BS_LOADED;
if (m_map->isBlockInQueue(blockpos)) if (m_map->isBlockInQueue(blockpos))

@ -256,8 +256,6 @@ void unspread_light(Map *map, const NodeDefManager *nodemgr, LightBank bank,
// Data of the current neighbor // Data of the current neighbor
mapblock_v3 neighbor_block_pos; mapblock_v3 neighbor_block_pos;
relative_v3 neighbor_rel_pos; relative_v3 neighbor_rel_pos;
// A dummy boolean
bool is_valid_position;
// Direction of the brightest neighbor of the node // Direction of the brightest neighbor of the node
direction source_dir; direction source_dir;
while (from_nodes.next(current_light, current)) { while (from_nodes.next(current_light, current)) {
@ -266,8 +264,7 @@ void unspread_light(Map *map, const NodeDefManager *nodemgr, LightBank bank,
// There is no brightest neighbor // There is no brightest neighbor
source_dir = 6; source_dir = 6;
// The current node // The current node
const MapNode &node = current.block->getNodeNoCheck( const MapNode &node = current.block->getNodeNoCheck(current.rel_position);
current.rel_position, &is_valid_position);
ContentLightingFlags f = nodemgr->getLightingFlags(node); ContentLightingFlags f = nodemgr->getLightingFlags(node);
// If the node emits light, it behaves like it had a // If the node emits light, it behaves like it had a
// brighter neighbor. // brighter neighbor.
@ -294,8 +291,7 @@ void unspread_light(Map *map, const NodeDefManager *nodemgr, LightBank bank,
neighbor_block = current.block; neighbor_block = current.block;
} }
// Get the neighbor itself // Get the neighbor itself
MapNode neighbor = neighbor_block->getNodeNoCheck(neighbor_rel_pos, MapNode neighbor = neighbor_block->getNodeNoCheck(neighbor_rel_pos);
&is_valid_position);
ContentLightingFlags neighbor_f = nodemgr->getLightingFlags( ContentLightingFlags neighbor_f = nodemgr->getLightingFlags(
neighbor.getContent()); neighbor.getContent());
u8 neighbor_light = neighbor.getLightRaw(bank, neighbor_f); u8 neighbor_light = neighbor.getLightRaw(bank, neighbor_f);
@ -361,8 +357,6 @@ void spread_light(Map *map, const NodeDefManager *nodemgr, LightBank bank,
// Position of the current neighbor. // Position of the current neighbor.
mapblock_v3 neighbor_block_pos; mapblock_v3 neighbor_block_pos;
relative_v3 neighbor_rel_pos; relative_v3 neighbor_rel_pos;
// A dummy boolean.
bool is_valid_position;
while (light_sources.next(spreading_light, current)) { while (light_sources.next(spreading_light, current)) {
spreading_light--; spreading_light--;
for (direction i = 0; i < 6; i++) { for (direction i = 0; i < 6; i++) {
@ -384,8 +378,7 @@ void spread_light(Map *map, const NodeDefManager *nodemgr, LightBank bank,
neighbor_block = current.block; neighbor_block = current.block;
} }
// Get the neighbor itself // Get the neighbor itself
MapNode neighbor = neighbor_block->getNodeNoCheck(neighbor_rel_pos, MapNode neighbor = neighbor_block->getNodeNoCheck(neighbor_rel_pos);
&is_valid_position);
ContentLightingFlags f = nodemgr->getLightingFlags(neighbor); ContentLightingFlags f = nodemgr->getLightingFlags(neighbor);
if (f.light_propagates) { if (f.light_propagates) {
// Light up the neighbor, if it has less light than it should. // Light up the neighbor, if it has less light than it should.
@ -445,22 +438,18 @@ bool is_sunlight_above(Map *map, v3s16 pos, const NodeDefManager *ndef)
sunlight = !node_block->getIsUnderground(); sunlight = !node_block->getIsUnderground();
} }
} else { } else {
bool is_valid_position; MapNode above = source_block->getNodeNoCheck(source_rel_pos);
MapNode above = source_block->getNodeNoCheck(source_rel_pos, if (above.getContent() == CONTENT_IGNORE) {
&is_valid_position); // Trust heuristics
if (is_valid_position) { if (source_block->getIsUnderground()) {
if (above.getContent() == CONTENT_IGNORE) { sunlight = false;
// Trust heuristics }
if (source_block->getIsUnderground()) { } else {
sunlight = false; ContentLightingFlags above_f = ndef->getLightingFlags(above);
} if (above.getLight(LIGHTBANK_DAY, above_f) != LIGHT_SUN) {
} else { // If the node above doesn't have sunlight, this
ContentLightingFlags above_f = ndef->getLightingFlags(above); // node is in shadow.
if (above.getLight(LIGHTBANK_DAY, above_f) != LIGHT_SUN) { sunlight = false;
// If the node above doesn't have sunlight, this
// node is in shadow.
sunlight = false;
}
} }
} }
} }
@ -504,14 +493,11 @@ void update_lighting_nodes(Map *map,
mapblock_v3 block_pos; mapblock_v3 block_pos;
getNodeBlockPosWithOffset(p, block_pos, rel_pos); getNodeBlockPosWithOffset(p, block_pos, rel_pos);
MapBlock *block = map->getBlockNoCreateNoEx(block_pos); MapBlock *block = map->getBlockNoCreateNoEx(block_pos);
if (block == NULL || block->isDummy()) { if (block == NULL) {
continue; continue;
} }
// Get the new node // Get the new node
MapNode n = block->getNodeNoCheck(rel_pos, &is_valid_position); MapNode n = block->getNodeNoCheck(rel_pos);
if (!is_valid_position) {
break;
}
// Light of the old node // Light of the old node
u8 old_light = it->second.getLight(bank, ndef->getLightingFlags(it->second)); u8 old_light = it->second.getLight(bank, ndef->getLightingFlags(it->second));
@ -530,9 +516,8 @@ void update_lighting_nodes(Map *map,
new_light = f.light_source; new_light = f.light_source;
for (const v3s16 &neighbor_dir : neighbor_dirs) { for (const v3s16 &neighbor_dir : neighbor_dirs) {
v3s16 p2 = p + neighbor_dir; v3s16 p2 = p + neighbor_dir;
bool is_valid; MapNode n2 = map->getNode(p2, &is_valid_position);
MapNode n2 = map->getNode(p2, &is_valid); if (is_valid_position) {
if (is_valid) {
u8 spread = n2.getLight(bank, ndef->getLightingFlags(n2)); u8 spread = n2.getLight(bank, ndef->getLightingFlags(n2));
// If it is sure that the neighbor won't be // If it is sure that the neighbor won't be
// unlighted, its light can spread to this node. // unlighted, its light can spread to this node.
@ -636,8 +621,7 @@ void update_lighting_nodes(Map *map,
const std::vector<ChangingLight> &lights = light_sources.lights[i]; const std::vector<ChangingLight> &lights = light_sources.lights[i];
for (std::vector<ChangingLight>::const_iterator it = lights.begin(); for (std::vector<ChangingLight>::const_iterator it = lights.begin();
it < lights.end(); ++it) { it < lights.end(); ++it) {
MapNode n = it->block->getNodeNoCheck(it->rel_position, MapNode n = it->block->getNodeNoCheck(it->rel_position);
&is_valid_position);
n.setLight(bank, i, ndef->getLightingFlags(n)); n.setLight(bank, i, ndef->getLightingFlags(n));
it->block->setNodeNoCheck(it->rel_position, n); it->block->setNodeNoCheck(it->rel_position, n);
} }
@ -696,7 +680,6 @@ void update_block_border_lighting(Map *map, MapBlock *block,
std::map<v3s16, MapBlock*> &modified_blocks) std::map<v3s16, MapBlock*> &modified_blocks)
{ {
const NodeDefManager *ndef = map->getNodeDefManager(); const NodeDefManager *ndef = map->getNodeDefManager();
bool is_valid_position;
for (LightBank bank : banks) { for (LightBank bank : banks) {
// Since invalid light is not common, do not allocate // Since invalid light is not common, do not allocate
// memory if not needed. // memory if not needed.
@ -729,8 +712,7 @@ void update_block_border_lighting(Map *map, MapBlock *block,
for (s32 x = a.MinEdge.X; x <= a.MaxEdge.X; x++) for (s32 x = a.MinEdge.X; x <= a.MaxEdge.X; x++)
for (s32 z = a.MinEdge.Z; z <= a.MaxEdge.Z; z++) for (s32 z = a.MinEdge.Z; z <= a.MaxEdge.Z; z++)
for (s32 y = a.MinEdge.Y; y <= a.MaxEdge.Y; y++) { for (s32 y = a.MinEdge.Y; y <= a.MaxEdge.Y; y++) {
MapNode n = b->getNodeNoCheck(x, y, z, MapNode n = b->getNodeNoCheck(x, y, z);
&is_valid_position);
ContentLightingFlags f = ndef->getLightingFlags(n); ContentLightingFlags f = ndef->getLightingFlags(n);
u8 light = n.getLight(bank, f); u8 light = n.getLight(bank, f);
// Sunlight is fixed // Sunlight is fixed
@ -758,8 +740,7 @@ void update_block_border_lighting(Map *map, MapBlock *block,
const std::vector<ChangingLight> &lights = light_sources.lights[i]; const std::vector<ChangingLight> &lights = light_sources.lights[i];
for (std::vector<ChangingLight>::const_iterator it = lights.begin(); for (std::vector<ChangingLight>::const_iterator it = lights.begin();
it < lights.end(); ++it) { it < lights.end(); ++it) {
MapNode n = it->block->getNodeNoCheck(it->rel_position, MapNode n = it->block->getNodeNoCheck(it->rel_position);
&is_valid_position);
n.setLight(bank, i, ndef->getLightingFlags(n)); n.setLight(bank, i, ndef->getLightingFlags(n));
it->block->setNodeNoCheck(it->rel_position, n); it->block->setNodeNoCheck(it->rel_position, n);
} }
@ -842,8 +823,7 @@ void is_sunlight_above_block(Map *map, mapblock_v3 pos,
// sunlight may be even slower. // sunlight may be even slower.
MapBlock *source_block = map->emergeBlock(source_block_pos, false); MapBlock *source_block = map->emergeBlock(source_block_pos, false);
// Trust only generated blocks. // Trust only generated blocks.
if (source_block == NULL || source_block->isDummy() if (source_block == NULL || !source_block->isGenerated()) {
|| !source_block->isGenerated()) {
// But if there is no block above, then use heuristics // But if there is no block above, then use heuristics
bool sunlight = true; bool sunlight = true;
MapBlock *node_block = map->getBlockNoCreateNoEx(pos); MapBlock *node_block = map->getBlockNoCreateNoEx(pos);
@ -856,14 +836,11 @@ void is_sunlight_above_block(Map *map, mapblock_v3 pos,
for (s16 x = 0; x < MAP_BLOCKSIZE; x++) for (s16 x = 0; x < MAP_BLOCKSIZE; x++)
light[z][x] = sunlight; light[z][x] = sunlight;
} else { } else {
// Dummy boolean, the position is valid.
bool is_valid_position;
// For each column: // For each column:
for (s16 z = 0; z < MAP_BLOCKSIZE; z++) for (s16 z = 0; z < MAP_BLOCKSIZE; z++)
for (s16 x = 0; x < MAP_BLOCKSIZE; x++) { for (s16 x = 0; x < MAP_BLOCKSIZE; x++) {
// Get the bottom block. // Get the bottom block.
MapNode above = source_block->getNodeNoCheck(x, 0, z, MapNode above = source_block->getNodeNoCheck(x, 0, z);
&is_valid_position);
ContentLightingFlags above_f = ndef->getLightingFlags(above); ContentLightingFlags above_f = ndef->getLightingFlags(above);
light[z][x] = above.getLight(LIGHTBANK_DAY, above_f) == LIGHT_SUN; light[z][x] = above.getLight(LIGHTBANK_DAY, above_f) == LIGHT_SUN;
} }
@ -886,13 +863,11 @@ bool propagate_block_sunlight(Map *map, const NodeDefManager *ndef,
bool modified = false; bool modified = false;
// Get the block. // Get the block.
MapBlock *block = map->getBlockNoCreateNoEx(data->target_block); MapBlock *block = map->getBlockNoCreateNoEx(data->target_block);
if (block == NULL || block->isDummy()) { if (block == NULL) {
// The work is done if the block does not contain data. // The work is done if the block does not contain data.
data->data.clear(); data->data.clear();
return false; return false;
} }
// Dummy boolean
bool is_valid;
// For each changing column of nodes: // For each changing column of nodes:
size_t index; size_t index;
for (index = 0; index < data->data.size(); index++) { for (index = 0; index < data->data.size(); index++) {
@ -904,7 +879,7 @@ bool propagate_block_sunlight(Map *map, const NodeDefManager *ndef,
// Propagate sunlight. // Propagate sunlight.
// For each node downwards: // For each node downwards:
for (; current_pos.Y >= 0; current_pos.Y--) { for (; current_pos.Y >= 0; current_pos.Y--) {
MapNode n = block->getNodeNoCheck(current_pos, &is_valid); MapNode n = block->getNodeNoCheck(current_pos);
ContentLightingFlags f = ndef->getLightingFlags(n); ContentLightingFlags f = ndef->getLightingFlags(n);
if (n.getLightRaw(LIGHTBANK_DAY, f) < LIGHT_SUN if (n.getLightRaw(LIGHTBANK_DAY, f) < LIGHT_SUN
&& f.sunlight_propagates) { && f.sunlight_propagates) {
@ -923,7 +898,7 @@ bool propagate_block_sunlight(Map *map, const NodeDefManager *ndef,
// Propagate shadow. // Propagate shadow.
// For each node downwards: // For each node downwards:
for (; current_pos.Y >= 0; current_pos.Y--) { for (; current_pos.Y >= 0; current_pos.Y--) {
MapNode n = block->getNodeNoCheck(current_pos, &is_valid); MapNode n = block->getNodeNoCheck(current_pos);
ContentLightingFlags f = ndef->getLightingFlags(n); ContentLightingFlags f = ndef->getLightingFlags(n);
if (n.getLightRaw(LIGHTBANK_DAY, f) == LIGHT_SUN) { if (n.getLightRaw(LIGHTBANK_DAY, f) == LIGHT_SUN) {
// The sunlight is no longer valid. // The sunlight is no longer valid.
@ -987,8 +962,6 @@ void finish_bulk_light_update(Map *map, mapblock_v3 minblock,
std::map<v3s16, MapBlock*> *modified_blocks) std::map<v3s16, MapBlock*> *modified_blocks)
{ {
const NodeDefManager *ndef = map->getNodeDefManager(); const NodeDefManager *ndef = map->getNodeDefManager();
// dummy boolean
bool is_valid;
// --- STEP 1: Do unlighting // --- STEP 1: Do unlighting
@ -1007,14 +980,14 @@ void finish_bulk_light_update(Map *map, mapblock_v3 minblock,
for (blockpos.Y = minblock.Y; blockpos.Y <= maxblock.Y; blockpos.Y++) for (blockpos.Y = minblock.Y; blockpos.Y <= maxblock.Y; blockpos.Y++)
for (blockpos.Z = minblock.Z; blockpos.Z <= maxblock.Z; blockpos.Z++) { for (blockpos.Z = minblock.Z; blockpos.Z <= maxblock.Z; blockpos.Z++) {
MapBlock *block = map->getBlockNoCreateNoEx(blockpos); MapBlock *block = map->getBlockNoCreateNoEx(blockpos);
if (!block || block->isDummy()) if (!block)
// Skip not existing blocks // Skip not existing blocks
continue; continue;
// For each node in the block: // For each node in the block:
for (relpos.X = 0; relpos.X < MAP_BLOCKSIZE; relpos.X++) for (relpos.X = 0; relpos.X < MAP_BLOCKSIZE; relpos.X++)
for (relpos.Z = 0; relpos.Z < MAP_BLOCKSIZE; relpos.Z++) for (relpos.Z = 0; relpos.Z < MAP_BLOCKSIZE; relpos.Z++)
for (relpos.Y = 0; relpos.Y < MAP_BLOCKSIZE; relpos.Y++) { for (relpos.Y = 0; relpos.Y < MAP_BLOCKSIZE; relpos.Y++) {
MapNode node = block->getNodeNoCheck(relpos.X, relpos.Y, relpos.Z, &is_valid); MapNode node = block->getNodeNoCheck(relpos.X, relpos.Y, relpos.Z);
ContentLightingFlags f = ndef->getLightingFlags(node); ContentLightingFlags f = ndef->getLightingFlags(node);
// For each light bank // For each light bank
@ -1041,8 +1014,7 @@ void finish_bulk_light_update(Map *map, mapblock_v3 minblock,
const std::vector<ChangingLight> &lights = relight[b].lights[i]; const std::vector<ChangingLight> &lights = relight[b].lights[i];
for (std::vector<ChangingLight>::const_iterator it = lights.begin(); for (std::vector<ChangingLight>::const_iterator it = lights.begin();
it < lights.end(); ++it) { it < lights.end(); ++it) {
MapNode n = it->block->getNodeNoCheck(it->rel_position, MapNode n = it->block->getNodeNoCheck(it->rel_position);
&is_valid);
n.setLight(bank, i, ndef->getLightingFlags(n)); n.setLight(bank, i, ndef->getLightingFlags(n));
it->block->setNodeNoCheck(it->rel_position, n); it->block->setNodeNoCheck(it->rel_position, n);
} }
@ -1064,8 +1036,6 @@ void blit_back_with_light(Map *map, MMVManip *vm,
// Will hold sunlight data. // Will hold sunlight data.
bool lights[MAP_BLOCKSIZE][MAP_BLOCKSIZE]; bool lights[MAP_BLOCKSIZE][MAP_BLOCKSIZE];
SunlightPropagationData data; SunlightPropagationData data;
// Dummy boolean.
bool is_valid;
// --- STEP 1: reset everything to sunlight // --- STEP 1: reset everything to sunlight
@ -1105,7 +1075,7 @@ void blit_back_with_light(Map *map, MMVManip *vm,
for (blockpos.Y = minblock.Y; blockpos.Y <= maxblock.Y; blockpos.Y++) for (blockpos.Y = minblock.Y; blockpos.Y <= maxblock.Y; blockpos.Y++)
for (blockpos.Z = minblock.Z; blockpos.Z <= maxblock.Z; blockpos.Z++) { for (blockpos.Z = minblock.Z; blockpos.Z <= maxblock.Z; blockpos.Z++) {
MapBlock *block = map->getBlockNoCreateNoEx(blockpos); MapBlock *block = map->getBlockNoCreateNoEx(blockpos);
if (!block || block->isDummy()) if (!block)
// Skip not existing blocks. // Skip not existing blocks.
continue; continue;
v3s16 offset = block->getPosRelative(); v3s16 offset = block->getPosRelative();
@ -1117,7 +1087,7 @@ void blit_back_with_light(Map *map, MMVManip *vm,
for (relpos.Y = a.MinEdge.Y; relpos.Y <= a.MaxEdge.Y; relpos.Y++) { for (relpos.Y = a.MinEdge.Y; relpos.Y <= a.MaxEdge.Y; relpos.Y++) {
// Get old and new node // Get old and new node
MapNode oldnode = block->getNodeNoCheck(relpos, &is_valid); MapNode oldnode = block->getNodeNoCheck(relpos);
ContentLightingFlags oldf = ndef->getLightingFlags(oldnode); ContentLightingFlags oldf = ndef->getLightingFlags(oldnode);
MapNode newnode = vm->getNodeNoExNoEmerge(relpos + offset); MapNode newnode = vm->getNodeNoExNoEmerge(relpos + offset);
ContentLightingFlags newf = ndef->getLightingFlags(newnode); ContentLightingFlags newf = ndef->getLightingFlags(newnode);
@ -1164,10 +1134,6 @@ void blit_back_with_light(Map *map, MMVManip *vm,
void fill_with_sunlight(MapBlock *block, const NodeDefManager *ndef, void fill_with_sunlight(MapBlock *block, const NodeDefManager *ndef,
bool light[MAP_BLOCKSIZE][MAP_BLOCKSIZE]) bool light[MAP_BLOCKSIZE][MAP_BLOCKSIZE])
{ {
if (block->isDummy())
return;
// dummy boolean
bool is_valid;
// For each column of nodes: // For each column of nodes:
for (s16 z = 0; z < MAP_BLOCKSIZE; z++) for (s16 z = 0; z < MAP_BLOCKSIZE; z++)
for (s16 x = 0; x < MAP_BLOCKSIZE; x++) { for (s16 x = 0; x < MAP_BLOCKSIZE; x++) {
@ -1175,7 +1141,7 @@ void fill_with_sunlight(MapBlock *block, const NodeDefManager *ndef,
bool lig = light[z][x]; bool lig = light[z][x];
// For each node, downwards: // For each node, downwards:
for (s16 y = MAP_BLOCKSIZE - 1; y >= 0; y--) { for (s16 y = MAP_BLOCKSIZE - 1; y >= 0; y--) {
MapNode n = block->getNodeNoCheck(x, y, z, &is_valid); MapNode n = block->getNodeNoCheck(x, y, z);
// Ignore IGNORE nodes, these are not generated yet. // Ignore IGNORE nodes, these are not generated yet.
if (n.getContent() == CONTENT_IGNORE) if (n.getContent() == CONTENT_IGNORE)
continue; continue;
@ -1197,7 +1163,7 @@ void fill_with_sunlight(MapBlock *block, const NodeDefManager *ndef,
void repair_block_light(Map *map, MapBlock *block, void repair_block_light(Map *map, MapBlock *block,
std::map<v3s16, MapBlock*> *modified_blocks) std::map<v3s16, MapBlock*> *modified_blocks)
{ {
if (!block || block->isDummy()) if (!block)
return; return;
const NodeDefManager *ndef = map->getNodeDefManager(); const NodeDefManager *ndef = map->getNodeDefManager();
// First queue is for day light, second is for night light. // First queue is for day light, second is for night light.
@ -1206,8 +1172,6 @@ void repair_block_light(Map *map, MapBlock *block,
// Will hold sunlight data. // Will hold sunlight data.
bool lights[MAP_BLOCKSIZE][MAP_BLOCKSIZE]; bool lights[MAP_BLOCKSIZE][MAP_BLOCKSIZE];
SunlightPropagationData data; SunlightPropagationData data;
// Dummy boolean.
bool is_valid;
// --- STEP 1: reset everything to sunlight // --- STEP 1: reset everything to sunlight
@ -1245,7 +1209,7 @@ void repair_block_light(Map *map, MapBlock *block,
for (relpos.Y = a.MinEdge.Y; relpos.Y <= a.MaxEdge.Y; relpos.Y++) { for (relpos.Y = a.MinEdge.Y; relpos.Y <= a.MaxEdge.Y; relpos.Y++) {
// Get node // Get node
MapNode node = block->getNodeNoCheck(relpos, &is_valid); MapNode node = block->getNodeNoCheck(relpos);
ContentLightingFlags f = ndef->getLightingFlags(node); ContentLightingFlags f = ndef->getLightingFlags(node);
// For each light bank // For each light bank
for (size_t b = 0; b < 2; b++) { for (size_t b = 0; b < 2; b++) {