Lighting: Update lighting at block loading

This commit updates mapblocks' light if necessary when they are loaded.
This removes ghost lighting.
This commit is contained in:
Dániel Juhász 2016-10-27 23:25:44 +02:00 committed by paramat
parent 2bd10022cb
commit f17c9c45dc
7 changed files with 274 additions and 122 deletions

@ -283,12 +283,6 @@ void RemoteClient::GetNextBlocks (
surely_not_found_on_disk = true; surely_not_found_on_disk = true;
} }
// Block is valid if lighting is up-to-date and data exists
if(block->isValid() == false)
{
block_is_invalid = true;
}
if(block->isGenerated() == false) if(block->isGenerated() == false)
block_is_invalid = true; block_is_invalid = true;

@ -824,7 +824,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
// Update lighting // Update lighting
std::vector<std::pair<v3s16, MapNode> > oldnodes; std::vector<std::pair<v3s16, MapNode> > oldnodes;
oldnodes.push_back(std::pair<v3s16, MapNode>(p, oldnode)); oldnodes.push_back(std::pair<v3s16, MapNode>(p, oldnode));
voxalgo::update_lighting_nodes(this, m_nodedef, oldnodes, modified_blocks); voxalgo::update_lighting_nodes(this, oldnodes, modified_blocks);
for(std::map<v3s16, MapBlock*>::iterator for(std::map<v3s16, MapBlock*>::iterator
i = modified_blocks.begin(); i = modified_blocks.begin();
@ -1523,7 +1523,7 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
for (std::deque<v3s16>::iterator iter = must_reflow.begin(); iter != must_reflow.end(); ++iter) for (std::deque<v3s16>::iterator iter = must_reflow.begin(); iter != must_reflow.end(); ++iter)
m_transforming_liquid.push_back(*iter); m_transforming_liquid.push_back(*iter);
voxalgo::update_lighting_nodes(this, m_nodedef, changed_nodes, modified_blocks); voxalgo::update_lighting_nodes(this, changed_nodes, modified_blocks);
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
@ -1955,27 +1955,10 @@ void ServerMap::finishBlockMake(BlockMakeData *data,
v3s16 bpmax = data->blockpos_max; v3s16 bpmax = data->blockpos_max;
v3s16 extra_borders(1, 1, 1); v3s16 extra_borders(1, 1, 1);
v3s16 full_bpmin = bpmin - extra_borders;
v3s16 full_bpmax = bpmax + extra_borders;
bool enable_mapgen_debug_info = m_emerge->enable_mapgen_debug_info; bool enable_mapgen_debug_info = m_emerge->enable_mapgen_debug_info;
EMERGE_DBG_OUT("finishBlockMake(): " PP(bpmin) " - " PP(bpmax)); EMERGE_DBG_OUT("finishBlockMake(): " PP(bpmin) " - " PP(bpmax));
/*
Set lighting to non-expired state in all of them.
This is cheating, but it is not fast enough if all of them
would actually be updated.
*/
for (s16 x = full_bpmin.X; x <= full_bpmax.X; x++)
for (s16 z = full_bpmin.Z; z <= full_bpmax.Z; z++)
for (s16 y = full_bpmin.Y; y <= full_bpmax.Y; y++) {
MapBlock *block = emergeBlock(v3s16(x, y, z), false);
if (!block)
continue;
block->setLightingExpired(false);
}
/* /*
Blit generated stuff to map Blit generated stuff to map
NOTE: blitBackAll adds nearly everything to changed_blocks NOTE: blitBackAll adds nearly everything to changed_blocks
@ -2991,7 +2974,6 @@ void ServerMap::loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool
// We just loaded it from, so it's up-to-date. // We just loaded it from, so it's up-to-date.
block->resetModified(); block->resetModified();
} }
catch(SerializationError &e) catch(SerializationError &e)
{ {
@ -3015,71 +2997,80 @@ MapBlock* ServerMap::loadBlock(v3s16 blockpos)
{ {
DSTACK(FUNCTION_NAME); DSTACK(FUNCTION_NAME);
bool created_new = (getBlockNoCreateNoEx(blockpos) == NULL);
v2s16 p2d(blockpos.X, blockpos.Z); v2s16 p2d(blockpos.X, blockpos.Z);
std::string ret; std::string ret;
dbase->loadBlock(blockpos, &ret); dbase->loadBlock(blockpos, &ret);
if (ret != "") { if (ret != "") {
loadBlock(&ret, blockpos, createSector(p2d), false); loadBlock(&ret, blockpos, createSector(p2d), false);
return getBlockNoCreateNoEx(blockpos); } else {
} // Not found in database, try the files
// Not found in database, try the files
// The directory layout we're going to load from. // The directory layout we're going to load from.
// 1 - original sectors/xxxxzzzz/ // 1 - original sectors/xxxxzzzz/
// 2 - new sectors2/xxx/zzz/ // 2 - new sectors2/xxx/zzz/
// If we load from anything but the latest structure, we will // If we load from anything but the latest structure, we will
// immediately save to the new one, and remove the old. // immediately save to the new one, and remove the old.
int loadlayout = 1; int loadlayout = 1;
std::string sectordir1 = getSectorDir(p2d, 1); std::string sectordir1 = getSectorDir(p2d, 1);
std::string sectordir; std::string sectordir;
if(fs::PathExists(sectordir1)) if (fs::PathExists(sectordir1)) {
{ sectordir = sectordir1;
sectordir = sectordir1; } else {
} loadlayout = 2;
else sectordir = getSectorDir(p2d, 2);
{ }
loadlayout = 2;
sectordir = getSectorDir(p2d, 2);
}
/* /*
Make sure sector is loaded Make sure sector is loaded
*/ */
MapSector *sector = getSectorNoGenerateNoEx(p2d); MapSector *sector = getSectorNoGenerateNoEx(p2d);
if(sector == NULL) if (sector == NULL) {
{ try {
try{ sector = loadSectorMeta(sectordir, loadlayout != 2);
sector = loadSectorMeta(sectordir, loadlayout != 2); } catch(InvalidFilenameException &e) {
return NULL;
} catch(FileNotGoodException &e) {
return NULL;
} catch(std::exception &e) {
return NULL;
}
} }
catch(InvalidFilenameException &e)
{
return NULL; /*
} Make sure file exists
catch(FileNotGoodException &e) */
{
return NULL; std::string blockfilename = getBlockFilename(blockpos);
} if (fs::PathExists(sectordir + DIR_DELIM + blockfilename) == false)
catch(std::exception &e)
{
return NULL; return NULL;
/*
Load block and save it to the database
*/
loadBlock(sectordir, blockfilename, sector, true);
}
MapBlock *block = getBlockNoCreateNoEx(blockpos);
if (created_new && (block != NULL)) {
std::map<v3s16, MapBlock*> modified_blocks;
// Fix lighting if necessary
voxalgo::update_block_border_lighting(this, block, modified_blocks);
if (!modified_blocks.empty()) {
//Modified lighting, send event
MapEditEvent event;
event.type = MEET_OTHER;
std::map<v3s16, MapBlock *>::iterator it;
for (it = modified_blocks.begin();
it != modified_blocks.end(); ++it)
event.modified_blocks.insert(it->first);
dispatchEvent(&event);
} }
} }
return block;
/*
Make sure file exists
*/
std::string blockfilename = getBlockFilename(blockpos);
if(fs::PathExists(sectordir + DIR_DELIM + blockfilename) == false)
return NULL;
/*
Load block and save it to the database
*/
loadBlock(sectordir, blockfilename, sector, true);
return getBlockNoCreateNoEx(blockpos);
} }
bool ServerMap::deleteBlock(v3s16 blockpos) bool ServerMap::deleteBlock(v3s16 blockpos)

@ -73,7 +73,7 @@ MapBlock::MapBlock(Map *parent, v3s16 pos, IGameDef *gamedef, bool dummy):
m_modified(MOD_STATE_WRITE_NEEDED), m_modified(MOD_STATE_WRITE_NEEDED),
m_modified_reason(MOD_REASON_INITIAL), m_modified_reason(MOD_REASON_INITIAL),
is_underground(false), is_underground(false),
m_lighting_expired(true), m_lighting_complete(0xFFFF),
m_day_night_differs(false), m_day_night_differs(false),
m_day_night_differs_expired(true), m_day_night_differs_expired(true),
m_generated(false), m_generated(false),
@ -571,11 +571,12 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk)
flags |= 0x01; flags |= 0x01;
if(getDayNightDiff()) if(getDayNightDiff())
flags |= 0x02; flags |= 0x02;
if(m_lighting_expired)
flags |= 0x04;
if(m_generated == false) if(m_generated == false)
flags |= 0x08; flags |= 0x08;
writeU8(os, flags); writeU8(os, flags);
if (version >= 27) {
writeU16(os, m_lighting_complete);
}
/* /*
Bulk node data Bulk node data
@ -672,7 +673,11 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
u8 flags = readU8(is); u8 flags = readU8(is);
is_underground = (flags & 0x01) ? true : false; is_underground = (flags & 0x01) ? true : false;
m_day_night_differs = (flags & 0x02) ? true : false; m_day_night_differs = (flags & 0x02) ? true : false;
m_lighting_expired = (flags & 0x04) ? true : false; if (version < 27) {
m_lighting_complete = 0xFFFF;
} else {
m_lighting_complete = readU16(is);
}
m_generated = (flags & 0x08) ? false : true; m_generated = (flags & 0x08) ? false : true;
/* /*
@ -783,7 +788,7 @@ void MapBlock::deSerialize_pre22(std::istream &is, u8 version, bool disk)
// Initialize default flags // Initialize default flags
is_underground = false; is_underground = false;
m_day_night_differs = false; m_day_night_differs = false;
m_lighting_expired = false; m_lighting_complete = 0xFFFF;
m_generated = true; m_generated = true;
// Make a temporary buffer // Make a temporary buffer
@ -849,7 +854,6 @@ void MapBlock::deSerialize_pre22(std::istream &is, u8 version, bool disk)
is.read((char*)&flags, 1); is.read((char*)&flags, 1);
is_underground = (flags & 0x01) ? true : false; is_underground = (flags & 0x01) ? true : false;
m_day_night_differs = (flags & 0x02) ? true : false; m_day_night_differs = (flags & 0x02) ? true : false;
m_lighting_expired = (flags & 0x04) ? true : false;
if(version >= 18) if(version >= 18)
m_generated = (flags & 0x08) ? false : true; m_generated = (flags & 0x08) ? false : true;
@ -1027,10 +1031,7 @@ std::string analyze_block(MapBlock *block)
else else
desc<<"is_ug [ ], "; desc<<"is_ug [ ], ";
if(block->getLightingExpired()) desc<<"lighting_complete: "<<block->getLightingComplete()<<", ";
desc<<"lighting_exp [X], ";
else
desc<<"lighting_exp [ ], ";
if(block->isDummy()) if(block->isDummy())
{ {

@ -105,7 +105,7 @@ public:
#define MOD_REASON_INITIAL (1 << 0) #define MOD_REASON_INITIAL (1 << 0)
#define MOD_REASON_REALLOCATE (1 << 1) #define MOD_REASON_REALLOCATE (1 << 1)
#define MOD_REASON_SET_IS_UNDERGROUND (1 << 2) #define MOD_REASON_SET_IS_UNDERGROUND (1 << 2)
#define MOD_REASON_SET_LIGHTING_EXPIRED (1 << 3) #define MOD_REASON_SET_LIGHTING_COMPLETE (1 << 3)
#define MOD_REASON_SET_GENERATED (1 << 4) #define MOD_REASON_SET_GENERATED (1 << 4)
#define MOD_REASON_SET_NODE (1 << 5) #define MOD_REASON_SET_NODE (1 << 5)
#define MOD_REASON_SET_NODE_NO_CHECK (1 << 6) #define MOD_REASON_SET_NODE_NO_CHECK (1 << 6)
@ -213,17 +213,42 @@ public:
raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_IS_UNDERGROUND); raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_IS_UNDERGROUND);
} }
inline void setLightingExpired(bool expired) inline void setLightingComplete(u16 newflags)
{ {
if (expired != m_lighting_expired){ if (newflags != m_lighting_complete) {
m_lighting_expired = expired; m_lighting_complete = newflags;
raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_LIGHTING_EXPIRED); raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_LIGHTING_COMPLETE);
} }
} }
inline bool getLightingExpired() inline u16 getLightingComplete()
{ {
return m_lighting_expired; return m_lighting_complete;
}
inline void setLightingComplete(LightBank bank, u8 direction,
bool is_complete)
{
assert(direction >= 0 && direction <= 5);
if (bank == LIGHTBANK_NIGHT) {
direction += 6;
}
u16 newflags = m_lighting_complete;
if (is_complete) {
newflags |= 1 << direction;
} else {
newflags &= ~(1 << direction);
}
setLightingComplete(newflags);
}
inline bool isLightingComplete(LightBank bank, u8 direction)
{
assert(direction >= 0 && direction <= 5);
if (bank == LIGHTBANK_NIGHT) {
direction += 6;
}
return (m_lighting_complete & (1 << direction)) != 0;
} }
inline bool isGenerated() inline bool isGenerated()
@ -239,15 +264,6 @@ public:
} }
} }
inline bool isValid()
{
if (m_lighting_expired)
return false;
if (data == NULL)
return false;
return true;
}
//// ////
//// Position stuff //// Position stuff
//// ////
@ -613,14 +629,14 @@ private:
*/ */
bool is_underground; bool is_underground;
/* /*!
Set to true if changes has been made that make the old lighting * Each bit indicates if light spreading was finished
values wrong but the lighting hasn't been actually updated. * in a direction. (Because the neighbor could also be unloaded.)
* Bits: day X+, day Y+, day Z+, day Z-, day Y-, day X-,
If this is false, lighting is exactly right. * night X+, night Y+, night Z+, night Z-, night Y-, night X-,
If this is true, lighting might be wrong or right. * nothing, nothing, nothing, nothing.
*/ */
bool m_lighting_expired; u16 m_lighting_complete;
// Whether day and night lighting differs // Whether day and night lighting differs
bool m_day_night_differs; bool m_day_night_differs;

@ -62,13 +62,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
24: 16-bit node ids and node timers (never released as stable) 24: 16-bit node ids and node timers (never released as stable)
25: Improved node timer format 25: Improved node timer format
26: Never written; read the same as 25 26: Never written; read the same as 25
27: Added light spreading flags to blocks
*/ */
// This represents an uninitialized or invalid format // This represents an uninitialized or invalid format
#define SER_FMT_VER_INVALID 255 #define SER_FMT_VER_INVALID 255
// Highest supported serialization version // Highest supported serialization version
#define SER_FMT_VER_HIGHEST_READ 26 #define SER_FMT_VER_HIGHEST_READ 27
// Saved on disk version // Saved on disk version
#define SER_FMT_VER_HIGHEST_WRITE 25 #define SER_FMT_VER_HIGHEST_WRITE 27
// Lowest supported serialization version // Lowest supported serialization version
#define SER_FMT_VER_LOWEST_READ 0 #define SER_FMT_VER_LOWEST_READ 0
// Lowest serialization version for writing // Lowest serialization version for writing

@ -423,6 +423,7 @@ void unspread_light(Map *map, INodeDefManager *nodemgr, LightBank bank,
if (step_rel_block_pos(i, neighbor_rel_pos, neighbor_block_pos)) { if (step_rel_block_pos(i, neighbor_rel_pos, neighbor_block_pos)) {
neighbor_block = map->getBlockNoCreateNoEx(neighbor_block_pos); neighbor_block = map->getBlockNoCreateNoEx(neighbor_block_pos);
if (neighbor_block == NULL) { if (neighbor_block == NULL) {
current.block->setLightingComplete(bank, i, false);
continue; continue;
} }
} else { } else {
@ -486,7 +487,8 @@ void unspread_light(Map *map, INodeDefManager *nodemgr, LightBank bank,
* \param modified_blocks output, all modified map blocks are added to this * \param modified_blocks output, all modified map blocks are added to this
*/ */
void spread_light(Map *map, INodeDefManager *nodemgr, LightBank bank, void spread_light(Map *map, INodeDefManager *nodemgr, LightBank bank,
LightQueue &light_sources, std::map<v3s16, MapBlock*> &modified_blocks) LightQueue &light_sources,
std::map<v3s16, MapBlock*> &modified_blocks)
{ {
// The light the current node can provide to its neighbors. // The light the current node can provide to its neighbors.
u8 spreading_light; u8 spreading_light;
@ -511,6 +513,7 @@ void spread_light(Map *map, INodeDefManager *nodemgr, LightBank bank,
if (step_rel_block_pos(i, neighbor_rel_pos, neighbor_block_pos)) { if (step_rel_block_pos(i, neighbor_rel_pos, neighbor_block_pos)) {
neighbor_block = map->getBlockNoCreateNoEx(neighbor_block_pos); neighbor_block = map->getBlockNoCreateNoEx(neighbor_block_pos);
if (neighbor_block == NULL) { if (neighbor_block == NULL) {
current.block->setLightingComplete(bank, i, false);
continue; continue;
} }
} else { } else {
@ -584,10 +587,11 @@ bool is_sunlight_above(Map *map, v3s16 pos, INodeDefManager *ndef)
static const LightBank banks[] = { LIGHTBANK_DAY, LIGHTBANK_NIGHT }; static const LightBank banks[] = { LIGHTBANK_DAY, LIGHTBANK_NIGHT };
void update_lighting_nodes(Map *map, INodeDefManager *ndef, void update_lighting_nodes(Map *map,
std::vector<std::pair<v3s16, MapNode> > &oldnodes, std::vector<std::pair<v3s16, MapNode> > &oldnodes,
std::map<v3s16, MapBlock*> &modified_blocks) std::map<v3s16, MapBlock*> &modified_blocks)
{ {
INodeDefManager *ndef = map->getNodeDefManager();
// For node getter functions // For node getter functions
bool is_valid_position; bool is_valid_position;
@ -596,6 +600,22 @@ void update_lighting_nodes(Map *map, INodeDefManager *ndef,
LightBank bank = banks[i]; LightBank bank = banks[i];
UnlightQueue disappearing_lights(256); UnlightQueue disappearing_lights(256);
ReLightQueue light_sources(256); ReLightQueue light_sources(256);
// Nodes that are brighter than the brightest modified node was
// won't change, since they didn't get their light from a
// modified node.
u8 min_safe_light = 0;
for (std::vector<std::pair<v3s16, MapNode> >::iterator it =
oldnodes.begin(); it < oldnodes.end(); ++it) {
u8 old_light = it->second.getLight(bank, ndef);
if (old_light > min_safe_light) {
min_safe_light = old_light;
}
}
// If only one node changed, even nodes with the same brightness
// didn't get their light from the changed node.
if (oldnodes.size() > 1) {
min_safe_light++;
}
// For each changed node process sunlight and initialize // For each changed node process sunlight and initialize
for (std::vector<std::pair<v3s16, MapNode> >::iterator it = for (std::vector<std::pair<v3s16, MapNode> >::iterator it =
oldnodes.begin(); it < oldnodes.end(); ++it) { oldnodes.begin(); it < oldnodes.end(); ++it) {
@ -634,11 +654,9 @@ void update_lighting_nodes(Map *map, INodeDefManager *ndef,
MapNode n2 = map->getNodeNoEx(p2, &is_valid); MapNode n2 = map->getNodeNoEx(p2, &is_valid);
if (is_valid) { if (is_valid) {
u8 spread = n2.getLight(bank, ndef); u8 spread = n2.getLight(bank, ndef);
// If the neighbor is at least as bright as // If it is sure that the neighbor won't be
// this node then its light is not from // unlighted, its light can spread to this node.
// this node. if (spread > new_light && spread >= min_safe_light) {
// Its light can spread to this node.
if (spread > new_light && spread >= old_light) {
new_light = spread - 1; new_light = spread - 1;
} }
} }
@ -747,6 +765,126 @@ void update_lighting_nodes(Map *map, INodeDefManager *ndef,
} }
} }
/*!
* Borders of a map block in relative node coordinates.
* Compatible with type 'direction'.
*/
const VoxelArea block_borders[] = {
VoxelArea(v3s16(15, 0, 0), v3s16(15, 15, 15)), //X+
VoxelArea(v3s16(0, 15, 0), v3s16(15, 15, 15)), //Y+
VoxelArea(v3s16(0, 0, 15), v3s16(15, 15, 15)), //Z+
VoxelArea(v3s16(0, 0, 0), v3s16(15, 15, 0)), //Z-
VoxelArea(v3s16(0, 0, 0), v3s16(15, 0, 15)), //Y-
VoxelArea(v3s16(0, 0, 0), v3s16(0, 15, 15)) //X-
};
/*!
* Returns true if:
* -the node has unloaded neighbors
* -the node doesn't have light
* -the node's light is the same as the maximum of
* its light source and its brightest neighbor minus one.
* .
*/
bool is_light_locally_correct(Map *map, INodeDefManager *ndef, LightBank bank,
v3s16 pos)
{
bool is_valid_position;
MapNode n = map->getNodeNoEx(pos, &is_valid_position);
const ContentFeatures &f = ndef->get(n);
if (f.param_type != CPT_LIGHT) {
return true;
}
u8 light = n.getLightNoChecks(bank, &f);
assert(f.light_source <= LIGHT_MAX);
u8 brightest_neighbor = f.light_source + 1;
for (direction d = 0; d < 6; ++d) {
MapNode n2 = map->getNodeNoEx(pos + neighbor_dirs[d],
&is_valid_position);
u8 light2 = n2.getLight(bank, ndef);
if (brightest_neighbor < light2) {
brightest_neighbor = light2;
}
}
assert(light <= LIGHT_SUN);
return brightest_neighbor == light + 1;
}
void update_block_border_lighting(Map *map, MapBlock *block,
std::map<v3s16, MapBlock*> &modified_blocks)
{
INodeDefManager *ndef = map->getNodeDefManager();
bool is_valid_position;
for (s32 i = 0; i < 2; i++) {
LightBank bank = banks[i];
UnlightQueue disappearing_lights(256);
ReLightQueue light_sources(256);
// Get incorrect lights
for (direction d = 0; d < 6; d++) {
// For each direction
// Get neighbor block
v3s16 otherpos = block->getPos() + neighbor_dirs[d];
MapBlock *other = map->getBlockNoCreateNoEx(otherpos);
if (other == NULL) {
continue;
}
// Only update if lighting was not completed.
if (block->isLightingComplete(bank, d) &&
other->isLightingComplete(bank, 5 - d))
continue;
// Reset flags
block->setLightingComplete(bank, d, true);
other->setLightingComplete(bank, 5 - d, true);
// The two blocks and their connecting surfaces
MapBlock *blocks[] = {block, other};
VoxelArea areas[] = {block_borders[d], block_borders[5 - d]};
// For both blocks
for (u8 blocknum = 0; blocknum < 2; blocknum++) {
MapBlock *b = blocks[blocknum];
VoxelArea a = areas[blocknum];
// For all nodes
for (s32 x = a.MinEdge.X; x <= a.MaxEdge.X; x++)
for (s32 z = a.MinEdge.Z; z <= a.MaxEdge.Z; z++)
for (s32 y = a.MinEdge.Y; y <= a.MaxEdge.Y; y++) {
MapNode n = b->getNodeNoCheck(x, y, z,
&is_valid_position);
u8 light = n.getLight(bank, ndef);
// Sunlight is fixed
if (light < LIGHT_SUN) {
// Unlight if not correct
if (!is_light_locally_correct(map, ndef, bank,
v3s16(x, y, z) + b->getPosRelative())) {
// Initialize for unlighting
n.setLight(bank, 0, ndef);
b->setNodeNoCheck(x, y, z, n);
modified_blocks[b->getPos()]=b;
disappearing_lights.push(light,
relative_v3(x, y, z), b->getPos(), b,
6);
}
}
}
}
}
// Remove lights
unspread_light(map, ndef, bank, disappearing_lights, light_sources,
modified_blocks);
// Initialize light values for light spreading.
for (u8 i = 0; i <= LIGHT_SUN; i++) {
const std::vector<ChangingLight> &lights = light_sources.lights[i];
for (std::vector<ChangingLight>::const_iterator it = lights.begin();
it < lights.end(); it++) {
MapNode n = it->block->getNodeNoCheck(it->rel_position,
&is_valid_position);
n.setLight(bank, i, ndef);
it->block->setNodeNoCheck(it->rel_position, n);
}
}
// Spread lights.
spread_light(map, ndef, bank, light_sources, modified_blocks);
}
}
VoxelLineIterator::VoxelLineIterator( VoxelLineIterator::VoxelLineIterator(
const v3f &start_position, const v3f &start_position,
const v3f &line_vector) : const v3f &line_vector) :

@ -22,8 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "voxel.h" #include "voxel.h"
#include "mapnode.h" #include "mapnode.h"
#include <set> #include "util/container.h"
#include <map> #include "util/cpp11_container.h"
class Map; class Map;
class MapBlock; class MapBlock;
@ -69,10 +69,21 @@ SunlightPropagateResult propagateSunlight(VoxelManipulator &v, VoxelArea a,
*/ */
void update_lighting_nodes( void update_lighting_nodes(
Map *map, Map *map,
INodeDefManager *ndef,
std::vector<std::pair<v3s16, MapNode> > &oldnodes, std::vector<std::pair<v3s16, MapNode> > &oldnodes,
std::map<v3s16, MapBlock*> &modified_blocks); std::map<v3s16, MapBlock*> &modified_blocks);
/*!
* Updates borders of the given mapblock.
* Only updates if the block was marked with incomplete
* lighting and the neighbor is also loaded.
*
* \param block the block to update
* \param modified_blocks output, contains all map blocks that
* the function modified
*/
void update_block_border_lighting(Map *map, MapBlock *block,
std::map<v3s16, MapBlock*> &modified_blocks);
/*! /*!
* This class iterates trough voxels that intersect with * This class iterates trough voxels that intersect with
* a line. The collision detection does not see nodeboxes, * a line. The collision detection does not see nodeboxes,