mirror of
https://github.com/minetest/minetest.git
synced 2024-08-19 21:14:15 +02:00
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:
parent
2bd10022cb
commit
f17c9c45dc
@ -283,12 +283,6 @@ void RemoteClient::GetNextBlocks (
|
||||
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)
|
||||
block_is_invalid = true;
|
||||
|
||||
|
133
src/map.cpp
133
src/map.cpp
@ -824,7 +824,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
|
||||
// Update lighting
|
||||
std::vector<std::pair<v3s16, MapNode> > oldnodes;
|
||||
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
|
||||
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)
|
||||
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 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;
|
||||
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
|
||||
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.
|
||||
block->resetModified();
|
||||
|
||||
}
|
||||
catch(SerializationError &e)
|
||||
{
|
||||
@ -3015,71 +2997,80 @@ MapBlock* ServerMap::loadBlock(v3s16 blockpos)
|
||||
{
|
||||
DSTACK(FUNCTION_NAME);
|
||||
|
||||
bool created_new = (getBlockNoCreateNoEx(blockpos) == NULL);
|
||||
|
||||
v2s16 p2d(blockpos.X, blockpos.Z);
|
||||
|
||||
std::string ret;
|
||||
dbase->loadBlock(blockpos, &ret);
|
||||
if (ret != "") {
|
||||
loadBlock(&ret, blockpos, createSector(p2d), false);
|
||||
return getBlockNoCreateNoEx(blockpos);
|
||||
}
|
||||
// Not found in database, try the files
|
||||
} else {
|
||||
// Not found in database, try the files
|
||||
|
||||
// The directory layout we're going to load from.
|
||||
// 1 - original sectors/xxxxzzzz/
|
||||
// 2 - new sectors2/xxx/zzz/
|
||||
// If we load from anything but the latest structure, we will
|
||||
// immediately save to the new one, and remove the old.
|
||||
int loadlayout = 1;
|
||||
std::string sectordir1 = getSectorDir(p2d, 1);
|
||||
std::string sectordir;
|
||||
if(fs::PathExists(sectordir1))
|
||||
{
|
||||
sectordir = sectordir1;
|
||||
}
|
||||
else
|
||||
{
|
||||
loadlayout = 2;
|
||||
sectordir = getSectorDir(p2d, 2);
|
||||
}
|
||||
// The directory layout we're going to load from.
|
||||
// 1 - original sectors/xxxxzzzz/
|
||||
// 2 - new sectors2/xxx/zzz/
|
||||
// If we load from anything but the latest structure, we will
|
||||
// immediately save to the new one, and remove the old.
|
||||
int loadlayout = 1;
|
||||
std::string sectordir1 = getSectorDir(p2d, 1);
|
||||
std::string sectordir;
|
||||
if (fs::PathExists(sectordir1)) {
|
||||
sectordir = sectordir1;
|
||||
} else {
|
||||
loadlayout = 2;
|
||||
sectordir = getSectorDir(p2d, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
Make sure sector is loaded
|
||||
*/
|
||||
*/
|
||||
|
||||
MapSector *sector = getSectorNoGenerateNoEx(p2d);
|
||||
if(sector == NULL)
|
||||
{
|
||||
try{
|
||||
sector = loadSectorMeta(sectordir, loadlayout != 2);
|
||||
MapSector *sector = getSectorNoGenerateNoEx(p2d);
|
||||
if (sector == NULL) {
|
||||
try {
|
||||
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;
|
||||
}
|
||||
catch(FileNotGoodException &e)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
|
||||
|
||||
/*
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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);
|
||||
return block;
|
||||
}
|
||||
|
||||
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_reason(MOD_REASON_INITIAL),
|
||||
is_underground(false),
|
||||
m_lighting_expired(true),
|
||||
m_lighting_complete(0xFFFF),
|
||||
m_day_night_differs(false),
|
||||
m_day_night_differs_expired(true),
|
||||
m_generated(false),
|
||||
@ -571,11 +571,12 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk)
|
||||
flags |= 0x01;
|
||||
if(getDayNightDiff())
|
||||
flags |= 0x02;
|
||||
if(m_lighting_expired)
|
||||
flags |= 0x04;
|
||||
if(m_generated == false)
|
||||
flags |= 0x08;
|
||||
writeU8(os, flags);
|
||||
if (version >= 27) {
|
||||
writeU16(os, m_lighting_complete);
|
||||
}
|
||||
|
||||
/*
|
||||
Bulk node data
|
||||
@ -672,7 +673,11 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
|
||||
u8 flags = readU8(is);
|
||||
is_underground = (flags & 0x01) ? 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;
|
||||
|
||||
/*
|
||||
@ -783,7 +788,7 @@ void MapBlock::deSerialize_pre22(std::istream &is, u8 version, bool disk)
|
||||
// Initialize default flags
|
||||
is_underground = false;
|
||||
m_day_night_differs = false;
|
||||
m_lighting_expired = false;
|
||||
m_lighting_complete = 0xFFFF;
|
||||
m_generated = true;
|
||||
|
||||
// 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_underground = (flags & 0x01) ? true : false;
|
||||
m_day_night_differs = (flags & 0x02) ? true : false;
|
||||
m_lighting_expired = (flags & 0x04) ? true : false;
|
||||
if(version >= 18)
|
||||
m_generated = (flags & 0x08) ? false : true;
|
||||
|
||||
@ -1027,10 +1031,7 @@ std::string analyze_block(MapBlock *block)
|
||||
else
|
||||
desc<<"is_ug [ ], ";
|
||||
|
||||
if(block->getLightingExpired())
|
||||
desc<<"lighting_exp [X], ";
|
||||
else
|
||||
desc<<"lighting_exp [ ], ";
|
||||
desc<<"lighting_complete: "<<block->getLightingComplete()<<", ";
|
||||
|
||||
if(block->isDummy())
|
||||
{
|
||||
|
@ -105,7 +105,7 @@ public:
|
||||
#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_LIGHTING_COMPLETE (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)
|
||||
@ -213,17 +213,42 @@ public:
|
||||
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){
|
||||
m_lighting_expired = expired;
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_LIGHTING_EXPIRED);
|
||||
if (newflags != m_lighting_complete) {
|
||||
m_lighting_complete = newflags;
|
||||
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()
|
||||
@ -239,15 +264,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
inline bool isValid()
|
||||
{
|
||||
if (m_lighting_expired)
|
||||
return false;
|
||||
if (data == NULL)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
////
|
||||
//// Position stuff
|
||||
////
|
||||
@ -613,14 +629,14 @@ private:
|
||||
*/
|
||||
bool is_underground;
|
||||
|
||||
/*
|
||||
Set to true if changes has been made that make the old lighting
|
||||
values wrong but the lighting hasn't been actually updated.
|
||||
|
||||
If this is false, lighting is exactly right.
|
||||
If this is true, lighting might be wrong or right.
|
||||
/*!
|
||||
* Each bit indicates if light spreading was finished
|
||||
* in a direction. (Because the neighbor could also be unloaded.)
|
||||
* Bits: day X+, day Y+, day Z+, day Z-, day Y-, day X-,
|
||||
* night X+, night Y+, night Z+, night Z-, night Y-, night X-,
|
||||
* nothing, nothing, nothing, nothing.
|
||||
*/
|
||||
bool m_lighting_expired;
|
||||
u16 m_lighting_complete;
|
||||
|
||||
// Whether day and night lighting 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)
|
||||
25: Improved node timer format
|
||||
26: Never written; read the same as 25
|
||||
27: Added light spreading flags to blocks
|
||||
*/
|
||||
// This represents an uninitialized or invalid format
|
||||
#define SER_FMT_VER_INVALID 255
|
||||
// Highest supported serialization version
|
||||
#define SER_FMT_VER_HIGHEST_READ 26
|
||||
#define SER_FMT_VER_HIGHEST_READ 27
|
||||
// Saved on disk version
|
||||
#define SER_FMT_VER_HIGHEST_WRITE 25
|
||||
#define SER_FMT_VER_HIGHEST_WRITE 27
|
||||
// Lowest supported serialization version
|
||||
#define SER_FMT_VER_LOWEST_READ 0
|
||||
// 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)) {
|
||||
neighbor_block = map->getBlockNoCreateNoEx(neighbor_block_pos);
|
||||
if (neighbor_block == NULL) {
|
||||
current.block->setLightingComplete(bank, i, false);
|
||||
continue;
|
||||
}
|
||||
} 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
|
||||
*/
|
||||
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.
|
||||
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)) {
|
||||
neighbor_block = map->getBlockNoCreateNoEx(neighbor_block_pos);
|
||||
if (neighbor_block == NULL) {
|
||||
current.block->setLightingComplete(bank, i, false);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
@ -584,10 +587,11 @@ bool is_sunlight_above(Map *map, v3s16 pos, INodeDefManager *ndef)
|
||||
|
||||
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::map<v3s16, MapBlock*> &modified_blocks)
|
||||
{
|
||||
INodeDefManager *ndef = map->getNodeDefManager();
|
||||
// For node getter functions
|
||||
bool is_valid_position;
|
||||
|
||||
@ -596,6 +600,22 @@ void update_lighting_nodes(Map *map, INodeDefManager *ndef,
|
||||
LightBank bank = banks[i];
|
||||
UnlightQueue disappearing_lights(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 (std::vector<std::pair<v3s16, MapNode> >::iterator 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);
|
||||
if (is_valid) {
|
||||
u8 spread = n2.getLight(bank, ndef);
|
||||
// If the neighbor is at least as bright as
|
||||
// this node then its light is not from
|
||||
// this node.
|
||||
// Its light can spread to this node.
|
||||
if (spread > new_light && spread >= old_light) {
|
||||
// If it is sure that the neighbor won't be
|
||||
// unlighted, its light can spread to this node.
|
||||
if (spread > new_light && spread >= min_safe_light) {
|
||||
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(
|
||||
const v3f &start_position,
|
||||
const v3f &line_vector) :
|
||||
|
@ -22,8 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "voxel.h"
|
||||
#include "mapnode.h"
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include "util/container.h"
|
||||
#include "util/cpp11_container.h"
|
||||
|
||||
class Map;
|
||||
class MapBlock;
|
||||
@ -69,10 +69,21 @@ SunlightPropagateResult propagateSunlight(VoxelManipulator &v, VoxelArea a,
|
||||
*/
|
||||
void update_lighting_nodes(
|
||||
Map *map,
|
||||
INodeDefManager *ndef,
|
||||
std::vector<std::pair<v3s16, MapNode> > &oldnodes,
|
||||
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
|
||||
* a line. The collision detection does not see nodeboxes,
|
||||
|
Loading…
Reference in New Issue
Block a user