forked from Mirrorlandia_minetest/minetest
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;
|
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;
|
||||||
|
|
||||||
|
73
src/map.cpp
73
src/map.cpp
@ -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,14 +2997,15 @@ 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.
|
||||||
@ -3033,12 +3016,9 @@ MapBlock* ServerMap::loadBlock(v3s16 blockpos)
|
|||||||
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 {
|
||||||
else
|
|
||||||
{
|
|
||||||
loadlayout = 2;
|
loadlayout = 2;
|
||||||
sectordir = getSectorDir(p2d, 2);
|
sectordir = getSectorDir(p2d, 2);
|
||||||
}
|
}
|
||||||
@ -3048,38 +3028,49 @@ MapBlock* ServerMap::loadBlock(v3s16 blockpos)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
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) {
|
||||||
catch(InvalidFilenameException &e)
|
|
||||||
{
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
} catch(FileNotGoodException &e) {
|
||||||
catch(FileNotGoodException &e)
|
|
||||||
{
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
} catch(std::exception &e) {
|
||||||
catch(std::exception &e)
|
|
||||||
{
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Make sure file exists
|
Make sure file exists
|
||||||
*/
|
*/
|
||||||
|
|
||||||
std::string blockfilename = getBlockFilename(blockpos);
|
std::string blockfilename = getBlockFilename(blockpos);
|
||||||
if(fs::PathExists(sectordir + DIR_DELIM + blockfilename) == false)
|
if (fs::PathExists(sectordir + DIR_DELIM + blockfilename) == false)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Load block and save it to the database
|
Load block and save it to the database
|
||||||
*/
|
*/
|
||||||
loadBlock(sectordir, blockfilename, sector, true);
|
loadBlock(sectordir, blockfilename, sector, true);
|
||||||
return getBlockNoCreateNoEx(blockpos);
|
}
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
|
Loading…
Reference in New Issue
Block a user