diff options
-rw-r--r-- | builtin/settingtypes.txt | 3 | ||||
-rw-r--r-- | src/defaultsettings.cpp | 1 | ||||
-rw-r--r-- | src/environment.cpp | 1 | ||||
-rw-r--r-- | src/environment.h | 1 | ||||
-rw-r--r-- | src/serverenvironment.cpp | 85 | ||||
-rw-r--r-- | src/serverenvironment.h | 5 | ||||
-rw-r--r-- | src/util/numeric.h | 10 |
7 files changed, 68 insertions, 38 deletions
diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 24b7008a1..fc628c88f 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -1085,6 +1085,9 @@ active_block_mgmt_interval (Active Block Management interval) float 2.0 # Length of time between ABM execution cycles abm_interval (Active Block Modifier interval) float 1.0 +# Length of time between active object step cycles +active_object_interval (Active Object interval) float 0.1 + # Length of time between NodeTimer execution cycles nodetimer_interval (NodeTimer interval) float 0.2 diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 6691b483f..cc113c6f6 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -345,6 +345,7 @@ void set_default_settings(Settings *settings) settings->setDefault("dedicated_server_step", "0.09"); settings->setDefault("active_block_mgmt_interval", "2.0"); settings->setDefault("abm_interval", "1.0"); + settings->setDefault("active_object_interval", "0.1"); settings->setDefault("nodetimer_interval", "0.2"); settings->setDefault("ignore_world_load_errors", "false"); settings->setDefault("remote_media", ""); diff --git a/src/environment.cpp b/src/environment.cpp index f9de13baa..23ec64573 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -36,6 +36,7 @@ Environment::Environment(IGameDef *gamedef): m_cache_enable_shaders = g_settings->getBool("enable_shaders"); m_cache_active_block_mgmt_interval = g_settings->getFloat("active_block_mgmt_interval"); m_cache_abm_interval = g_settings->getFloat("abm_interval"); + m_cache_ao_interval = g_settings->getFloat("active_object_interval"); m_cache_nodetimer_interval = g_settings->getFloat("nodetimer_interval"); m_time_of_day = g_settings->getU32("world_start_time"); diff --git a/src/environment.h b/src/environment.h index f568ba228..932a643a0 100644 --- a/src/environment.h +++ b/src/environment.h @@ -136,6 +136,7 @@ protected: bool m_cache_enable_shaders; float m_cache_active_block_mgmt_interval; float m_cache_abm_interval; + float m_cache_ao_interval; float m_cache_nodetimer_interval; IGameDef *m_gamedef; diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp index 92159a469..f2d55fccc 100644 --- a/src/serverenvironment.cpp +++ b/src/serverenvironment.cpp @@ -279,17 +279,17 @@ void LBMManager::applyLBMs(ServerEnvironment *env, MapBlock *block, u32 stamp) void fillRadiusBlock(v3s16 p0, s16 r, std::set<v3s16> &list) { + const s16 r2 = r * r; v3s16 p; - for(p.X=p0.X-r; p.X<=p0.X+r; p.X++) - for(p.Y=p0.Y-r; p.Y<=p0.Y+r; p.Y++) - for(p.Z=p0.Z-r; p.Z<=p0.Z+r; p.Z++) - { - // limit to a sphere - if (p.getDistanceFrom(p0) <= r) { - // Set in list - list.insert(p); - } - } + for (p.X = p0.X - r; p.X <= p0.X + r; p.X++) + for (p.Y = p0.Y - r; p.Y <= p0.Y + r; p.Y++) + for (p.Z = p0.Z - r; p.Z <= p0.Z + r; p.Z++) { + // limit to a sphere + if (p.getDistanceFromSQ(p0) <= r2) { + // Set in list + list.insert(p); + } + } } void fillViewConeBlock(v3s16 p0, @@ -364,10 +364,7 @@ void ActiveBlockList::update(std::vector<PlayerSAO*> &active_players, /* Update m_list */ - m_list.clear(); - for (v3s16 p : newlist) { - m_list.insert(p); - } + m_list = newlist; } /* @@ -1230,14 +1227,16 @@ void ServerEnvironment::step(float dtime) } } + // placeholder for the "real" time passed + float elapsed_time; + /* Mess around in active blocks */ - if (m_active_blocks_nodemetadata_interval.step(dtime, m_cache_nodetimer_interval)) { + if (m_active_blocks_nodemetadata_interval.step(dtime, m_cache_nodetimer_interval, + &elapsed_time)) { ScopeProfiler sp(g_profiler, "SEnv: mess in act. blocks avg per interval", SPT_AVG); - float dtime = m_cache_nodetimer_interval; - for (const v3s16 &p: m_active_blocks.m_list) { MapBlock *block = m_map->getBlockNoCreateNoEx(p); if (!block) @@ -1255,7 +1254,7 @@ void ServerEnvironment::step(float dtime) MOD_REASON_BLOCK_EXPIRED); // Run node timers - std::vector<NodeTimer> elapsed_timers = block->m_node_timers.step(dtime); + std::vector<NodeTimer> elapsed_timers = block->m_node_timers.step(elapsed_time); if (!elapsed_timers.empty()) { MapNode n; v3s16 p2; @@ -1271,18 +1270,14 @@ void ServerEnvironment::step(float dtime) } } - if (m_active_block_modifier_interval.step(dtime, m_cache_abm_interval)) + if (m_active_block_modifier_interval.step(dtime, + m_cache_abm_interval * m_active_block_interval_overload_skip, &elapsed_time)) do { // breakable - if (m_active_block_interval_overload_skip > 0) { - ScopeProfiler sp(g_profiler, "SEnv: ABM overload skips"); - m_active_block_interval_overload_skip--; - break; - } ScopeProfiler sp(g_profiler, "SEnv: modify in blocks avg per interval", SPT_AVG); TimeTaker timer("modify in active blocks per interval"); // Initialize handling of ActiveBlockModifiers - ABMHandler abmhandler(m_abms, m_cache_abm_interval, this, true); + ABMHandler abmhandler(m_abms, elapsed_time, this, true); for (const v3s16 &p : m_active_blocks.m_abm_list) { MapBlock *block = m_map->getBlockNoCreateNoEx(p); @@ -1296,13 +1291,16 @@ void ServerEnvironment::step(float dtime) abmhandler.apply(block); } - u32 time_ms = timer.stop(true); - u32 max_time_ms = 200; + const u32 time_ms = timer.stop(true); + // allow up to 10% of the budget interval + const u32 max_time_ms = m_cache_abm_interval * 1000.0f * 0.1f; if (time_ms > max_time_ms) { - warningstream<<"active block modifiers took " - <<time_ms<<"ms (longer than " - <<max_time_ms<<"ms)"<<std::endl; - m_active_block_interval_overload_skip = (time_ms / max_time_ms) + 1; + warningstream << "active block modifiers took " + << time_ms << "ms (longer than " + << max_time_ms << "ms)" << std::endl; + m_active_block_interval_overload_skip = ((float)time_ms / max_time_ms); + } else { + m_active_block_interval_overload_skip = 1.0f; } }while(0); @@ -1314,15 +1312,17 @@ void ServerEnvironment::step(float dtime) /* Step active objects */ - { + if (m_active_object_interval.step(dtime, + m_cache_ao_interval * m_active_object_interval_overload_skip, &elapsed_time)) { + ScopeProfiler sp(g_profiler, "SEnv: step act. objs avg", SPT_AVG); - //TimeTaker timer("Step active objects"); + TimeTaker timer("Step active objects"); g_profiler->avg("SEnv: num of objects", m_active_objects.size()); // This helps the objects to send data at the same time bool send_recommended = false; - m_send_recommended_timer += dtime; + m_send_recommended_timer += elapsed_time; if(m_send_recommended_timer > getSendRecommendedInterval()) { m_send_recommended_timer -= getSendRecommendedInterval(); @@ -1335,13 +1335,28 @@ void ServerEnvironment::step(float dtime) continue; // Step object - obj->step(dtime, send_recommended); + obj->step(elapsed_time, send_recommended); // Read messages from object while (!obj->m_messages_out.empty()) { m_active_object_messages.push(obj->m_messages_out.front()); obj->m_messages_out.pop(); } } + + // calculate a simple moving average + m_avg_ao_time = m_avg_ao_time * 0.9f + timer.stop(true) * 0.1f; + + // allow up to 20% of the budget interval + const float max_time_ms = m_cache_ao_interval * 1000.0f * 0.2f; + if (m_avg_ao_time > max_time_ms) { + warningstream << "active objects took " + << m_avg_ao_time << "ms (longer than " + << max_time_ms << "ms)" << std::endl; + // skip a few steps + m_active_object_interval_overload_skip = m_avg_ao_time / max_time_ms; + } else { + m_active_object_interval_overload_skip = 1.0f; + } } /* diff --git a/src/serverenvironment.h b/src/serverenvironment.h index cb813155d..a15d87ee2 100644 --- a/src/serverenvironment.h +++ b/src/serverenvironment.h @@ -422,8 +422,11 @@ private: ActiveBlockList m_active_blocks; IntervalLimiter m_active_blocks_management_interval; IntervalLimiter m_active_block_modifier_interval; + IntervalLimiter m_active_object_interval; IntervalLimiter m_active_blocks_nodemetadata_interval; - int m_active_block_interval_overload_skip = 0; + float m_active_block_interval_overload_skip = 1.0f; + float m_active_object_interval_overload_skip = 1.0f; + float m_avg_ao_time = 0.0f; // Time from the beginning of the game in seconds. // Incremented in step(). u32 m_game_time = 0; diff --git a/src/util/numeric.h b/src/util/numeric.h index 8ee2d585c..be3e49c56 100644 --- a/src/util/numeric.h +++ b/src/util/numeric.h @@ -230,7 +230,7 @@ inline u32 calc_parity(u32 v) u64 murmur_hash_64_ua(const void *key, int len, unsigned int seed); bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, - f32 camera_fov, f32 range, f32 *distance_ptr=NULL); + f32 camera_fov, f32 range, f32 *distance_ptr = NULL); s16 adjustDist(s16 dist, float zoom_fov); @@ -291,18 +291,24 @@ public: return value: true: action should be skipped false: action should be done + if passed, the elapsed time since this method last returned true + is written to elapsed_ptr */ - bool step(float dtime, float wanted_interval) + bool step(float dtime, float wanted_interval, float *elapsed_ptr = NULL) { m_accumulator += dtime; + if (elapsed_ptr) + *elapsed_ptr = m_accumulator - m_last_accumulator; if (m_accumulator < wanted_interval) return false; m_accumulator -= wanted_interval; + m_last_accumulator = m_accumulator; return true; } private: float m_accumulator = 0.0f; + float m_last_accumulator = 0.0f; }; |