Skip to content

Commit

Permalink
Lighting: Update lighting at block loading
Browse files Browse the repository at this point in the history
This commit updates mapblocks' light if necessary when they are loaded.
This removes ghost lighting.
  • Loading branch information
juhdanad authored and paramat committed Feb 13, 2017
1 parent 2bd1002 commit f17c9c4
Show file tree
Hide file tree
Showing 7 changed files with 273 additions and 121 deletions.
6 changes: 0 additions & 6 deletions src/clientiface.cpp
Expand Up @@ -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;

Expand Down
131 changes: 61 additions & 70 deletions src/map.cpp
Expand Up @@ -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();
Expand Down Expand Up @@ -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);


/* ----------------------------------------------------------------------
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
{
Expand All @@ -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

// 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);
}
} 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);
}

/*
/*
Make sure sector is loaded
*/
*/

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;
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;
}
}
}

/*

/*
Make sure file exists
*/
*/

std::string blockfilename = getBlockFilename(blockpos);
if(fs::PathExists(sectordir + DIR_DELIM + blockfilename) == false)
return NULL;
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);
*/
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;
}

bool ServerMap::deleteBlock(v3s16 blockpos)
Expand Down
21 changes: 11 additions & 10 deletions src/mapblock.cpp
Expand Up @@ -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),
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;

/*
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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())
{
Expand Down
62 changes: 39 additions & 23 deletions src/mapblock.h
Expand Up @@ -105,7 +105,7 @@ class NodeContainer
#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)
Expand Down Expand Up @@ -213,17 +213,42 @@ class MapBlock /*: public NodeContainer*/
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()
Expand All @@ -239,15 +264,6 @@ class MapBlock /*: public NodeContainer*/
}
}

inline bool isValid()
{
if (m_lighting_expired)
return false;
if (data == NULL)
return false;
return true;
}

////
//// Position stuff
////
Expand Down Expand Up @@ -613,14 +629,14 @@ class MapBlock /*: public NodeContainer*/
*/
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;
Expand Down
5 changes: 3 additions & 2 deletions src/serialization.h
Expand Up @@ -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
Expand Down

0 comments on commit f17c9c4

Please sign in to comment.