diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp index 810456b0d..26b0dd1fa 100644 --- a/src/serverenvironment.cpp +++ b/src/serverenvironment.cpp @@ -335,12 +335,14 @@ void ActiveBlockList::update(std::vector &active_players, s16 active_block_range, s16 active_object_range, std::set &blocks_removed, - std::set &blocks_added) + std::set &blocks_added, + std::set &extra_blocks_added) { /* Create the new list */ std::set newlist = m_forceloaded_list; + std::set extralist; m_abm_list = m_forceloaded_list; for (const PlayerSAO *playersao : active_players) { v3s16 pos = getNodeBlockPos(floatToInt(playersao->getBasePosition(), BS)); @@ -360,29 +362,52 @@ void ActiveBlockList::update(std::vector &active_players, playersao->getEyePosition(), camera_dir, playersao->getFov(), - newlist); + extralist); } } - /* - Find out which blocks on the old list are not on the new list - */ - // Go through old list - for (v3s16 p : m_list) { - // If not on new list, it's been removed - if (newlist.find(p) == newlist.end()) - blocks_removed.insert(p); - } - /* Find out which blocks on the new list are not on the old list */ - // Go through new list for (v3s16 p : newlist) { + // also remove duplicate blocks from the extra list + extralist.erase(p); // If not on old list, it's been added if (m_list.find(p) == m_list.end()) blocks_added.insert(p); } + /* + Find out which blocks on the extra list are not on the old list + */ + for (v3s16 p : extralist) { + // also make sure newlist has all blocks + newlist.insert(p); + // If not on old list, it's been added + if (m_list.find(p) == m_list.end()) + extra_blocks_added.insert(p); + } + + /* + Find out which blocks on the old list are not on the new + extra list + */ + std::set_difference(m_list.begin(), m_list.end(), newlist.begin(), newlist.end(), + std::inserter(blocks_removed, blocks_removed.end())); + + /* + Some sanity checks + */ + assert(newlist.size() >= extralist.size()); + assert(blocks_removed.size() <= m_list.size()); + if (!blocks_added.empty()) + assert(newlist.count(*blocks_added.begin()) > 0); + if (!extra_blocks_added.empty()) { + assert(newlist.count(*extra_blocks_added.begin()) > 0); + assert(blocks_added.count(*extra_blocks_added.begin()) == 0); + } + if (!blocks_removed.empty()) { + assert(newlist.count(*blocks_removed.begin()) == 0); + assert(m_list.count(*blocks_removed.begin()) > 0); + } /* Update m_list @@ -1403,8 +1428,9 @@ void ServerEnvironment::step(float dtime) g_settings->getS16("active_block_range"); std::set blocks_removed; std::set blocks_added; + std::set extra_blocks_added; m_active_blocks.update(players, active_block_range, active_object_range, - blocks_removed, blocks_added); + blocks_removed, blocks_added, extra_blocks_added); /* Handle removed blocks @@ -1440,6 +1466,17 @@ void ServerEnvironment::step(float dtime) activateBlock(block); } + for (const v3s16 &p: extra_blocks_added) { + // only activate if the block is already loaded + MapBlock *block = m_map->getBlockNoCreateNoEx(p); + if (!block) { + m_active_blocks.remove(p); + continue; + } + + activateBlock(block); + } + // Some blocks may be removed again by the code above so do this here m_active_block_gauge->set(m_active_blocks.size()); diff --git a/src/serverenvironment.h b/src/serverenvironment.h index 215fd37ee..bb689ea2c 100644 --- a/src/serverenvironment.h +++ b/src/serverenvironment.h @@ -168,7 +168,8 @@ public: s16 active_block_range, s16 active_object_range, std::set &blocks_removed, - std::set &blocks_added); + std::set &blocks_added, + std::set &extra_blocks_added); bool contains(v3s16 p) const { return (m_list.find(p) != m_list.end());