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)
{
}
void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
{
+
INodeDefManager *nodemgr = m_gamedef->ndef();
DSTACK(__FUNCTION_NAME);
u32 loopcount = 0;
u32 initial_size = m_transforming_liquid.size();
+ u32 curr_time = getTime(PRECISION_MILLI);
+
/*if(initial_size != 0)
infostream<<"transformLiquids(): initial_size="<<initial_size<<std::endl;*/
// 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;
+
+// std::cout << "transformLiquids(): loopmax initial="
+// << loop_max * m_transforming_liquid_loop_count_multiplier;
+
+ // 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;
+
+// std::cout << " queue sz=" << m_transforming_liquid.size()
+// << " loop_max=" << loop_max;
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);
+
+
+ /*
+ * Queue size limiting
+ */
+ 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;
+ }
+
+ u16 time_until_purge = g_settings->getU16("liquid_queue_purge_time");
+ time_until_purge *= 1000; // seconds -> milliseconds
+
+// std::cout << " growing for: "
+// << (m_queue_size_timer_started ? curr_time - m_inc_trend_up_start_time : 0)
+// << "ms" << std::endl;
+
+ // 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)