m_clients(m_con),
m_admin_chat(iface),
m_on_shutdown_errmsg(on_shutdown_errmsg),
- m_async_globals_data(""),
m_modchannel_mgr(new ModChannelMgr())
{
if (m_path_world.empty())
"minetest_core_latency",
"Latency value (in seconds)");
- m_aom_buffer_counter = m_metrics_backend->addCounter(
- "minetest_core_aom_generated_count",
- "Number of active object messages generated");
+
+ const std::string aom_types[] = {"reliable", "unreliable"};
+ for (u32 i = 0; i < ARRLEN(aom_types); i++) {
+ std::string help_str("Number of active object messages generated (");
+ help_str.append(aom_types[i]).append(")");
+ m_aom_buffer_counter[i] = m_metrics_backend->addCounter(
+ "minetest_core_aom_generated_count", help_str,
+ {{"type", aom_types[i]}});
+ }
m_packet_recv_counter = m_metrics_backend->addCounter(
"minetest_core_server_packet_recv",
"minetest_core_server_packet_recv_processed",
"Valid received packets processed");
+ m_map_edit_event_counter = m_metrics_backend->addCounter(
+ "minetest_core_map_edit_events",
+ "Number of map edit events");
+
m_lag_gauge->set(g_settings->getFloat("dedicated_server_step"));
}
}
// Create emerge manager
- m_emerge = new EmergeManager(this);
+ m_emerge = new EmergeManager(this, m_metrics_backend.get());
// Create ban manager
std::string ban_path = m_path_world + DIR_DELIM "ipban.txt";
m_script->loadMod(getBuiltinLuaPath() + DIR_DELIM "init.lua", BUILTIN_MOD_NAME);
+ m_gamespec.checkAndLog();
m_modmgr->loadMods(m_script);
// Read Textures and calculate sha1 sums
// Initialize Environment
m_startup_server_map = nullptr; // Ownership moved to ServerEnvironment
- m_env = new ServerEnvironment(servermap, m_script, this, m_path_world);
+ m_env = new ServerEnvironment(servermap, m_script, this,
+ m_path_world, m_metrics_backend.get());
m_inventory_mgr->setEnv(m_env);
m_clients.setEnv(m_env);
actionstream << "World at [" << m_path_world << "]" << std::endl;
actionstream << "Server for gameid=\"" << m_gamespec.id
<< "\" listening on ";
- m_bind_addr.print(&actionstream);
+ m_bind_addr.print(actionstream);
actionstream << "." << std::endl;
}
max_lag = dtime;
}
m_env->reportMaxLagEstimate(max_lag);
+
// Step environment
m_env->step(dtime);
}
// Get active object messages from environment
ActiveObjectMessage aom(0);
- u32 aom_count = 0;
+ u32 count_reliable = 0, count_unreliable = 0;
for(;;) {
if (!m_env->getActiveObjectMessage(&aom))
break;
+ if (aom.reliable)
+ count_reliable++;
+ else
+ count_unreliable++;
std::vector<ActiveObjectMessage>* message_list = nullptr;
auto n = buffered_messages.find(aom.id);
message_list = n->second;
}
message_list->push_back(std::move(aom));
- aom_count++;
}
- m_aom_buffer_counter->increment(aom_count);
+ m_aom_buffer_counter[0]->increment(count_reliable);
+ m_aom_buffer_counter[1]->increment(count_unreliable);
{
ClientInterface::AutoLock clientlock(m_clients);
// We will be accessing the environment
MutexAutoLock lock(m_env_mutex);
- // Don't send too many at a time
- //u32 count = 0;
-
- // Single change sending is disabled if queue size is not small
+ // Single change sending is disabled if queue size is big
bool disable_single_change_sending = false;
if(m_unsent_map_edit_queue.size() >= 4)
disable_single_change_sending = true;
- int event_count = m_unsent_map_edit_queue.size();
+ const auto event_count = m_unsent_map_edit_queue.size();
+ m_map_edit_event_counter->increment(event_count);
// We'll log the amount of each
Profiler prof;
}
void Server::SendBlockNoLock(session_t peer_id, MapBlock *block, u8 ver,
- u16 net_proto_version)
+ u16 net_proto_version, SerializedBlockCache *cache)
{
- /*
- Create a packet with the block in the right format
- */
thread_local const int net_compression_level = rangelim(g_settings->getS16("map_compression_level_net"), -1, 9);
- std::ostringstream os(std::ios_base::binary);
- block->serialize(os, ver, false, net_compression_level);
- block->serializeNetworkSpecific(os);
- std::string s = os.str();
+ std::string s, *sptr = nullptr;
- NetworkPacket pkt(TOCLIENT_BLOCKDATA, 2 + 2 + 2 + s.size(), peer_id);
+ if (cache) {
+ auto it = cache->find({block->getPos(), ver});
+ if (it != cache->end())
+ sptr = &it->second;
+ }
+
+ // Serialize the block in the right format
+ if (!sptr) {
+ std::ostringstream os(std::ios_base::binary);
+ block->serialize(os, ver, false, net_compression_level);
+ block->serializeNetworkSpecific(os);
+ s = os.str();
+ sptr = &s;
+ }
+ NetworkPacket pkt(TOCLIENT_BLOCKDATA, 2 + 2 + 2 + sptr->size(), peer_id);
pkt << block->getPos();
- pkt.putRawString(s.c_str(), s.size());
+ pkt.putRawString(*sptr);
Send(&pkt);
+
+ // Store away in cache
+ if (cache && sptr == &s)
+ (*cache)[{block->getPos(), ver}] = std::move(s);
}
void Server::SendBlocks(float dtime)
std::vector<PrioritySortedBlockTransfer> queue;
- u32 total_sending = 0;
+ u32 total_sending = 0, unique_clients = 0;
{
ScopeProfiler sp2(g_profiler, "Server::SendBlocks(): Collect list");
continue;
total_sending += client->getSendingCount();
+ const auto old_count = queue.size();
client->GetNextBlocks(m_env,m_emerge, dtime, queue);
+ unique_clients += queue.size() > old_count ? 1 : 0;
}
}
ScopeProfiler sp(g_profiler, "Server::SendBlocks(): Send to clients");
Map &map = m_env->getMap();
+ SerializedBlockCache cache, *cache_ptr = nullptr;
+ if (unique_clients > 1) {
+ // caching is pointless with a single client
+ cache_ptr = &cache;
+ }
+
for (const PrioritySortedBlockTransfer &block_to_send : queue) {
if (total_sending >= max_blocks_to_send)
break;
continue;
SendBlockNoLock(block_to_send.peer_id, block, client->serialization_version,
- client->net_proto_version);
+ client->net_proto_version, cache_ptr);
client->SentBlock(block_to_send.pos);
total_sending++;
// Version
os << "version: " << g_version_string;
// Game
- os << " | game: " << (m_gamespec.name.empty() ? m_gamespec.id : m_gamespec.name);
+ os << " | game: " << (m_gamespec.title.empty() ? m_gamespec.id : m_gamespec.title);
// Uptime
os << " | uptime: " << duration_to_string((int) m_uptime_counter->get());
// Max lag estimate