diff --git a/src/map.h b/src/map.h index db4d8be28..9ec66cfb9 100644 --- a/src/map.h +++ b/src/map.h @@ -47,6 +47,9 @@ struct MapEditEvent MapNode n = CONTENT_AIR; std::vector modified_blocks; // Represents a set bool is_private_change = false; + // Setting low_priority to true allows the server + // to send this change to clients with some delay. + bool low_priority = false; MapEditEvent() = default; diff --git a/src/server.cpp b/src/server.cpp index 4fe2d3c4a..bc3ee6c6e 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -755,6 +755,7 @@ void Server::AsyncRunStep(float dtime, bool initial_step) if (!modified_blocks.empty()) { MapEditEvent event; event.type = MEET_OTHER; + event.low_priority = true; event.setModifiedBlocks(modified_blocks); m_env->getMap().dispatchEvent(event); } @@ -1006,7 +1007,7 @@ void Server::AsyncRunStep(float dtime, bool initial_step) } case MEET_OTHER: prof.add("MEET_OTHER", 1); - m_clients.markBlocksNotSent(event->modified_blocks); + m_clients.markBlocksNotSent(event->modified_blocks, event->low_priority); break; default: prof.add("unknown", 1); @@ -1022,7 +1023,7 @@ void Server::AsyncRunStep(float dtime, bool initial_step) */ for (const u16 far_player : far_players) { if (RemoteClient *client = getClient(far_player)) - client->SetBlocksNotSent(event->modified_blocks); + client->SetBlocksNotSent(event->modified_blocks, event->low_priority); } delete event; diff --git a/src/server/clientiface.cpp b/src/server/clientiface.cpp index 7711ae6aa..13cf14c07 100644 --- a/src/server/clientiface.cpp +++ b/src/server/clientiface.cpp @@ -422,30 +422,34 @@ void RemoteClient::SentBlock(v3s16 p) " already in m_blocks_sending"< 0) { - // Note that we do NOT use the euclidean distance here. - // getNextBlocks builds successive cube-surfaces in the send loop. - // This resets the distance to the maximum cube size that - // still guarantees that this block will be scanned again right away. - // - // Using m_last_center is OK, as a change in center - // will reset m_nearest_unsent_d to 0 anyway (see getNextBlocks). - p -= m_last_center; - s16 this_d = std::max({std::abs(p.X), std::abs(p.Y), std::abs(p.Z)}); - m_nearest_unsent_d = std::min(m_nearest_unsent_d, this_d); + // If this is a low priority event, do not reset m_nearest_unsent_d. + // Instead, the send loop will get to the block in the next full loop iteration. + if (!low_priority) { + // Note that we do NOT use the euclidean distance here. + // getNextBlocks builds successive cube-surfaces in the send loop. + // This resets the distance to the maximum cube size that + // still guarantees that this block will be scanned again right away. + // + // Using m_last_center is OK, as a change in center + // will reset m_nearest_unsent_d to 0 anyway (see getNextBlocks). + p -= m_last_center; + s16 this_d = std::max({std::abs(p.X), std::abs(p.Y), std::abs(p.Z)}); + m_nearest_unsent_d = std::min(m_nearest_unsent_d, this_d); + } } } -void RemoteClient::SetBlocksNotSent(const std::vector &blocks) +void RemoteClient::SetBlocksNotSent(const std::vector &blocks, bool low_priority) { for (v3s16 p : blocks) { - SetBlockNotSent(p); + SetBlockNotSent(p, low_priority); } } @@ -664,12 +668,12 @@ std::vector ClientInterface::getClientIDs(ClientState min_state) return reply; } -void ClientInterface::markBlocksNotSent(const std::vector &positions) +void ClientInterface::markBlocksNotSent(const std::vector &positions, bool low_priority) { RecursiveMutexAutoLock clientslock(m_clients_mutex); for (const auto &client : m_clients) { if (client.second->getState() >= CS_Active) - client.second->SetBlocksNotSent(positions); + client.second->SetBlocksNotSent(positions, low_priority); } } diff --git a/src/server/clientiface.h b/src/server/clientiface.h index a46eceb3f..44b278e63 100644 --- a/src/server/clientiface.h +++ b/src/server/clientiface.h @@ -251,8 +251,8 @@ public: void SentBlock(v3s16 p); - void SetBlockNotSent(v3s16 p); - void SetBlocksNotSent(const std::vector &blocks); + void SetBlockNotSent(v3s16 p, bool low_priority = false); + void SetBlocksNotSent(const std::vector &blocks, bool low_priority = false); /** * tell client about this block being modified right now. @@ -443,7 +443,7 @@ public: std::vector getClientIDs(ClientState min_state=CS_Active); /* mark blocks as not sent on all active clients */ - void markBlocksNotSent(const std::vector &positions); + void markBlocksNotSent(const std::vector &positions, bool low_priority = false); /* verify is server user limit was reached */ bool isUserLimitReached(); diff --git a/src/servermap.cpp b/src/servermap.cpp index ab58510d2..a71fbecae 100644 --- a/src/servermap.cpp +++ b/src/servermap.cpp @@ -714,6 +714,7 @@ MapBlock *ServerMap::loadBlock(const std::string &blob, v3s16 p3d, bool save_aft if (!modified_blocks.empty()) { MapEditEvent event; event.type = MEET_OTHER; + event.low_priority = true; event.setModifiedBlocks(modified_blocks); dispatchEvent(event); }