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.
# The maximum total count is calculated dynamically:
# 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.
# This determines how long they are slowed down after placing or removing a node.
# To save bandwidth, block transfers are slowed down when a player is building something.
# 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
# Maximum number of packets sent per send step in the low-level networking code.

View File

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

View File

@@ -1173,11 +1173,6 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
std::optional<ItemStack> 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).
node_placement_prediction.empty();
@@ -1214,6 +1209,8 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
if (pointed.type != POINTEDTHING_NODE)
return;
getClient(peer_id)->m_time_from_building = 0;
// If item has node placement prediction, always send the
// blocks to make sure the client knows what exactly happened
RemoteClient *client = getClient(peer_id);

View File

@@ -56,7 +56,8 @@ const char *ClientInterface::state2Name(ClientState state)
RemoteClient::RemoteClient() :
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(
g_settings->getFloat("full_block_send_enable_min_time_from_building")),
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;
/*
Check the time from last addNode/removeNode.
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;
if (m_time_from_building < m_min_time_from_building) {
max_simul_sends_usually
= LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
max_simul_sends_usually *= LIMITED_BLOCK_SENDS_FACTOR;
max_simul_sends_usually = MYMAX(1, max_simul_sends_usually);
}
/*
@@ -223,10 +225,11 @@ void RemoteClient::GetNextBlocks (
s16 d_max = full_d_max;
// 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)
d_max = d_start + max_d_increment_at_time;
{
// cos(angle between velocity and camera) * |velocity|
// Limit to 0.0f in case player moves backwards.
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.
// limit max fov effect to 50%, 60% at 20n/s fly speed
camera_fov = camera_fov / (1 + dot / 300.0f);
}
s32 nearest_emerged_d = -1;
s32 nearest_sent_d = -1;
@@ -260,11 +264,9 @@ void RemoteClient::GetNextBlocks (
Also, don't send blocks that are already flying.
*/
// Start with the usual maximum
u16 max_simul_dynamic = max_simul_sends_usually;
// 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;
/*
@@ -388,8 +390,8 @@ queue_full_break:
new_nearest_unsent_d = 0;
m_nothing_to_send_pause_timer = 2.0f;
infostream << "Server: Player " << m_name << ", peer_id=" << peer_id
<< ": full map send completed after " << m_map_send_completion_timer
<< "s, restarting" << std::endl;
<< ": full map send (d=" << d << ") completed after "
<< m_map_send_completion_timer << "s, restarting" << std::endl;
m_map_send_completion_timer = 0.0f;
} else {
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;
// 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)
*distance_ptr = d;