1
0
mirror of https://github.com/luanti-org/luanti.git synced 2025-11-09 03:25:28 +01:00

Tune "block send throttling while building" optimization (#16614)

it can lead to terrain not loading/updating at all if you're constantly building and moving.

for more see the IRC logs <https://irc.luanti.org/luanti/2025-10-26#i_6293100>
This commit is contained in:
sfan5
2025-11-04 11:44:49 +01:00
committed by GitHub
parent 8350fb734a
commit 7a6e639d61
5 changed files with 29 additions and 30 deletions

View File

@@ -2213,10 +2213,10 @@ client_mapblock_limit (Mapblock limit) [client] int 7500 -1 2147483647
# Maximum number of blocks that are simultaneously sent per client. # Maximum number of blocks that are simultaneously sent per client.
# The maximum total count is calculated dynamically: # The maximum total count is calculated dynamically:
# max_total = ceil((#clients + max_users) * per_client / 4) # max_total = ceil((#clients + max_users) * per_client / 4)
max_simultaneous_block_sends_per_client (Maximum simultaneous block sends per client) [server] int 40 1 4294967295 max_simultaneous_block_sends_per_client (Maximum simultaneous block sends per client) [server] int 40 1
# To reduce lag, block transfers are slowed down when a player is building something. # To save bandwidth, block transfers are slowed down when a player is building something.
# This determines how long they are slowed down after placing or removing a node. # This determines how long the throttling lasts after placing a node.
full_block_send_enable_min_time_from_building (Delay in sending blocks after building) [server] float 2.0 0.0 full_block_send_enable_min_time_from_building (Delay in sending blocks after building) [server] float 2.0 0.0
# Maximum number of packets sent per send step in the low-level networking code. # Maximum number of packets sent per send step in the low-level networking code.

View File

@@ -31,10 +31,10 @@
Server Server
*/ */
// This many blocks are sent when player is building // Reduces block send rate while player is building
#define LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS 0 #define LIMITED_BLOCK_SENDS_FACTOR 0.33f
// Override for the previous one when distance of block is very low // Override for the previous one for blocks that are close by
#define BLOCK_SEND_DISABLE_LIMITS_MAX_D 1 #define BLOCK_ALWAYS_SEND_MAX_D 1
/* /*
Client/Server Client/Server

View File

@@ -1173,11 +1173,6 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
std::optional<ItemStack> selected_item; std::optional<ItemStack> selected_item;
getWieldedItem(playersao, selected_item); getWieldedItem(playersao, selected_item);
// Reset build time counter
if (pointed.type == POINTEDTHING_NODE &&
selected_item->getDefinition(m_itemdef).type == ITEM_NODE)
getClient(peer_id)->m_time_from_building = 0.0;
const bool had_prediction = !selected_item->getDefinition(m_itemdef). const bool had_prediction = !selected_item->getDefinition(m_itemdef).
node_placement_prediction.empty(); node_placement_prediction.empty();
@@ -1214,6 +1209,8 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
if (pointed.type != POINTEDTHING_NODE) if (pointed.type != POINTEDTHING_NODE)
return; return;
getClient(peer_id)->m_time_from_building = 0;
// If item has node placement prediction, always send the // If item has node placement prediction, always send the
// blocks to make sure the client knows what exactly happened // blocks to make sure the client knows what exactly happened
RemoteClient *client = getClient(peer_id); RemoteClient *client = getClient(peer_id);

View File

@@ -56,7 +56,8 @@ const char *ClientInterface::state2Name(ClientState state)
RemoteClient::RemoteClient() : RemoteClient::RemoteClient() :
serialization_version(SER_FMT_VER_INVALID), serialization_version(SER_FMT_VER_INVALID),
m_pending_serialization_version(SER_FMT_VER_INVALID), m_pending_serialization_version(SER_FMT_VER_INVALID),
m_max_simul_sends(g_settings->getU16("max_simultaneous_block_sends_per_client")), m_max_simul_sends(std::max<u16>(1,
g_settings->getU16("max_simultaneous_block_sends_per_client"))),
m_min_time_from_building( m_min_time_from_building(
g_settings->getFloat("full_block_send_enable_min_time_from_building")), g_settings->getFloat("full_block_send_enable_min_time_from_building")),
m_max_send_distance(g_settings->getS16("max_block_send_distance")), m_max_send_distance(g_settings->getS16("max_block_send_distance")),
@@ -149,14 +150,15 @@ void RemoteClient::GetNextBlocks (
u16 max_simul_sends_usually = m_max_simul_sends; u16 max_simul_sends_usually = m_max_simul_sends;
/* /*
Check the time from last addNode/removeNode.
Decrease send rate if player is building stuff. Decrease send rate if player is building stuff.
The idea is that we can save some bandwidth since the player is busy
and not looking around.
*/ */
m_time_from_building += dtime; m_time_from_building += dtime;
if (m_time_from_building < m_min_time_from_building) { if (m_time_from_building < m_min_time_from_building) {
max_simul_sends_usually max_simul_sends_usually *= LIMITED_BLOCK_SENDS_FACTOR;
= LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS; max_simul_sends_usually = MYMAX(1, max_simul_sends_usually);
} }
/* /*
@@ -223,10 +225,11 @@ void RemoteClient::GetNextBlocks (
s16 d_max = full_d_max; s16 d_max = full_d_max;
// Don't loop very much at a time // Don't loop very much at a time
s16 max_d_increment_at_time = 2; const s16 max_d_increment_at_time = 2;
if (d_max > d_start + max_d_increment_at_time) if (d_max > d_start + max_d_increment_at_time)
d_max = d_start + max_d_increment_at_time; d_max = d_start + max_d_increment_at_time;
{
// cos(angle between velocity and camera) * |velocity| // cos(angle between velocity and camera) * |velocity|
// Limit to 0.0f in case player moves backwards. // Limit to 0.0f in case player moves backwards.
f32 dot = rangelim(camera_dir.dotProduct(playerspeed), 0.0f, 300.0f); f32 dot = rangelim(camera_dir.dotProduct(playerspeed), 0.0f, 300.0f);
@@ -234,6 +237,7 @@ void RemoteClient::GetNextBlocks (
// Reduce the field of view when a player moves and looks forward. // Reduce the field of view when a player moves and looks forward.
// limit max fov effect to 50%, 60% at 20n/s fly speed // limit max fov effect to 50%, 60% at 20n/s fly speed
camera_fov = camera_fov / (1 + dot / 300.0f); camera_fov = camera_fov / (1 + dot / 300.0f);
}
s32 nearest_emerged_d = -1; s32 nearest_emerged_d = -1;
s32 nearest_sent_d = -1; s32 nearest_sent_d = -1;
@@ -260,11 +264,9 @@ void RemoteClient::GetNextBlocks (
Also, don't send blocks that are already flying. Also, don't send blocks that are already flying.
*/ */
// Start with the usual maximum
u16 max_simul_dynamic = max_simul_sends_usually; u16 max_simul_dynamic = max_simul_sends_usually;
// If block is very close, allow full maximum // If block is very close, allow full maximum
if (d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D) if (d <= BLOCK_ALWAYS_SEND_MAX_D)
max_simul_dynamic = m_max_simul_sends; max_simul_dynamic = m_max_simul_sends;
/* /*
@@ -388,8 +390,8 @@ queue_full_break:
new_nearest_unsent_d = 0; new_nearest_unsent_d = 0;
m_nothing_to_send_pause_timer = 2.0f; m_nothing_to_send_pause_timer = 2.0f;
infostream << "Server: Player " << m_name << ", peer_id=" << peer_id infostream << "Server: Player " << m_name << ", peer_id=" << peer_id
<< ": full map send completed after " << m_map_send_completion_timer << ": full map send (d=" << d << ") completed after "
<< "s, restarting" << std::endl; << m_map_send_completion_timer << "s, restarting" << std::endl;
m_map_send_completion_timer = 0.0f; m_map_send_completion_timer = 0.0f;
} else { } else {
if (nearest_sent_d != -1) if (nearest_sent_d != -1)

View File

@@ -100,7 +100,7 @@ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
v3f blockpos_relative = blockpos - camera_pos; v3f blockpos_relative = blockpos - camera_pos;
// Total distance // Total distance
f32 d = MYMAX(0, blockpos_relative.getLength() - BLOCK_MAX_RADIUS); f32 d = std::max(0.0f, blockpos_relative.getLength() - BLOCK_MAX_RADIUS);
if (distance_ptr) if (distance_ptr)
*distance_ptr = d; *distance_ptr = d;