Map::Map(std::ostream &dout, IGameDef *gamedef):
m_dout(dout),
m_gamedef(gamedef),
- m_sector_cache(NULL)
+ m_sector_cache(NULL),
+ m_transforming_liquid_loop_count_multiplier(1.0f),
+ m_unprocessed_count(0),
+ m_inc_trending_up_start_time(0),
+ m_queue_size_timer_started(false)
{
}
v3s16(-1,0,0), // left
};
- if(from_nodes.size() == 0)
+ if(from_nodes.empty())
return;
u32 blockchangecount = 0;
<<" for "<<from_nodes.size()<<" nodes"
<<std::endl;*/
- if(unlighted_nodes.size() > 0)
+ if(!unlighted_nodes.empty())
unspreadLight(bank, unlighted_nodes, light_sources, modified_blocks);
}
v3s16(-1,0,0), // left
};
- if(from_nodes.size() == 0)
+ if(from_nodes.empty())
return;
u32 blockchangecount = 0;
<<" for "<<from_nodes.size()<<" nodes"
<<std::endl;*/
- if(lighted_nodes.size() > 0)
+ if(!lighted_nodes.empty())
spreadLight(bank, lighted_nodes, modified_blocks);
}
void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
{
+
INodeDefManager *nodemgr = m_gamedef->ndef();
DSTACK(__FUNCTION_NAME);
// List of MapBlocks that will require a lighting update (due to lava)
std::map<v3s16, MapBlock*> lighting_modified_blocks;
- u16 loop_max = g_settings->getU16("liquid_loop_max");
+ u32 liquid_loop_max = g_settings->getS32("liquid_loop_max");
+ u32 loop_max = liquid_loop_max;
+
+#if 0
+
+ /* If liquid_loop_max is not keeping up with the queue size increase
+ * loop_max up to a maximum of liquid_loop_max * dedicated_server_step.
+ */
+ if (m_transforming_liquid.size() > loop_max * 2) {
+ // "Burst" mode
+ float server_step = g_settings->getFloat("dedicated_server_step");
+ if (m_transforming_liquid_loop_count_multiplier - 1.0 < server_step)
+ m_transforming_liquid_loop_count_multiplier *= 1.0 + server_step / 10;
+ } else {
+ m_transforming_liquid_loop_count_multiplier = 1.0;
+ }
+
+ loop_max *= m_transforming_liquid_loop_count_multiplier;
+#endif
while(m_transforming_liquid.size() != 0)
{
while (must_reflow.size() > 0)
m_transforming_liquid.push_back(must_reflow.pop_front());
updateLighting(lighting_modified_blocks, modified_blocks);
+
+
+ /* ----------------------------------------------------------------------
+ * Manage the queue so that it does not grow indefinately
+ */
+ u16 time_until_purge = g_settings->getU16("liquid_queue_purge_time");
+
+ if (time_until_purge == 0)
+ return; // Feature disabled
+
+ time_until_purge *= 1000; // seconds -> milliseconds
+
+ u32 curr_time = getTime(PRECISION_MILLI);
+ u32 prev_unprocessed = m_unprocessed_count;
+ m_unprocessed_count = m_transforming_liquid.size();
+
+ // if unprocessed block count is decreasing or stable
+ if (m_unprocessed_count <= prev_unprocessed) {
+ m_queue_size_timer_started = false;
+ } else {
+ if (!m_queue_size_timer_started)
+ m_inc_trending_up_start_time = curr_time;
+ m_queue_size_timer_started = true;
+ }
+
+ // Account for curr_time overflowing
+ if (m_queue_size_timer_started && m_inc_trending_up_start_time > curr_time)
+ m_queue_size_timer_started = false;
+
+ /* If the queue has been growing for more than liquid_queue_purge_time seconds
+ * and the number of unprocessed blocks is still > liquid_loop_max then we
+ * cannot keep up; dump the oldest blocks from the queue so that the queue
+ * has liquid_loop_max items in it
+ */
+ if (m_queue_size_timer_started
+ && curr_time - m_inc_trending_up_start_time > time_until_purge
+ && m_unprocessed_count > liquid_loop_max) {
+
+ size_t dump_qty = m_unprocessed_count - liquid_loop_max;
+
+ infostream << "transformLiquids(): DUMPING " << dump_qty
+ << " blocks from the queue" << std::endl;
+
+ while (dump_qty--)
+ m_transforming_liquid.pop_front();
+
+ m_queue_size_timer_started = false; // optimistically assume we can keep up now
+ m_unprocessed_count = m_transforming_liquid.size();
+ }
}
NodeMetadata *Map::getNodeMetadata(v3s16 p)
{
}
+void ManualMapVoxelManipulator::initializeBlank(v3s16 blockpos_min,
+ v3s16 blockpos_max)
+{
+ // Units of these are MapBlocks
+ v3s16 pmin = blockpos_min;
+ v3s16 pmax = blockpos_max;
+
+ VoxelArea block_area_nodes(pmin * MAP_BLOCKSIZE,
+ (pmax + 1) * MAP_BLOCKSIZE - v3s16(1,1,1));
+
+ addArea(block_area_nodes);
+ u32 extent = m_area.getVolume();
+ for (u32 i = 0; i != extent; i++)
+ m_data[i] = MapNode(CONTENT_IGNORE);
+
+ for (s32 z = pmin.Z; z <= pmax.Z; z++)
+ for (s32 y = pmin.Y; y <= pmax.Y; y++)
+ for (s32 x = pmin.X; x <= pmax.X; x++)
+ m_loaded_blocks[v3s16(x, y, z)] = 0;
+
+ m_is_dirty = false;
+}
+
void ManualMapVoxelManipulator::initialEmerge(v3s16 blockpos_min,
- v3s16 blockpos_max, bool load_if_inexistent)
+ v3s16 blockpos_max, bool load_if_inexistent)
{
TimeTaker timer1("initialEmerge", &emerge_time);