Skip to content

Commit 7a6e639

Browse files
authored
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>
1 parent 8350fb7 commit 7a6e639

5 files changed

Lines changed: 29 additions & 30 deletions

File tree

builtin/settingtypes.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2213,10 +2213,10 @@ client_mapblock_limit (Mapblock limit) [client] int 7500 -1 2147483647
22132213
# Maximum number of blocks that are simultaneously sent per client.
22142214
# The maximum total count is calculated dynamically:
22152215
# max_total = ceil((#clients + max_users) * per_client / 4)
2216-
max_simultaneous_block_sends_per_client (Maximum simultaneous block sends per client) [server] int 40 1 4294967295
2216+
max_simultaneous_block_sends_per_client (Maximum simultaneous block sends per client) [server] int 40 1
22172217

2218-
# To reduce lag, block transfers are slowed down when a player is building something.
2219-
# This determines how long they are slowed down after placing or removing a node.
2218+
# To save bandwidth, block transfers are slowed down when a player is building something.
2219+
# This determines how long the throttling lasts after placing a node.
22202220
full_block_send_enable_min_time_from_building (Delay in sending blocks after building) [server] float 2.0 0.0
22212221

22222222
# Maximum number of packets sent per send step in the low-level networking code.

src/constants.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@
3131
Server
3232
*/
3333

34-
// This many blocks are sent when player is building
35-
#define LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS 0
36-
// Override for the previous one when distance of block is very low
37-
#define BLOCK_SEND_DISABLE_LIMITS_MAX_D 1
34+
// Reduces block send rate while player is building
35+
#define LIMITED_BLOCK_SENDS_FACTOR 0.33f
36+
// Override for the previous one for blocks that are close by
37+
#define BLOCK_ALWAYS_SEND_MAX_D 1
3838

3939
/*
4040
Client/Server

src/network/serverpackethandler.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,11 +1173,6 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
11731173
std::optional<ItemStack> selected_item;
11741174
getWieldedItem(playersao, selected_item);
11751175

1176-
// Reset build time counter
1177-
if (pointed.type == POINTEDTHING_NODE &&
1178-
selected_item->getDefinition(m_itemdef).type == ITEM_NODE)
1179-
getClient(peer_id)->m_time_from_building = 0.0;
1180-
11811176
const bool had_prediction = !selected_item->getDefinition(m_itemdef).
11821177
node_placement_prediction.empty();
11831178

@@ -1214,6 +1209,8 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
12141209
if (pointed.type != POINTEDTHING_NODE)
12151210
return;
12161211

1212+
getClient(peer_id)->m_time_from_building = 0;
1213+
12171214
// If item has node placement prediction, always send the
12181215
// blocks to make sure the client knows what exactly happened
12191216
RemoteClient *client = getClient(peer_id);

src/server/clientiface.cpp

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ const char *ClientInterface::state2Name(ClientState state)
5656
RemoteClient::RemoteClient() :
5757
serialization_version(SER_FMT_VER_INVALID),
5858
m_pending_serialization_version(SER_FMT_VER_INVALID),
59-
m_max_simul_sends(g_settings->getU16("max_simultaneous_block_sends_per_client")),
59+
m_max_simul_sends(std::max<u16>(1,
60+
g_settings->getU16("max_simultaneous_block_sends_per_client"))),
6061
m_min_time_from_building(
6162
g_settings->getFloat("full_block_send_enable_min_time_from_building")),
6263
m_max_send_distance(g_settings->getS16("max_block_send_distance")),
@@ -149,14 +150,15 @@ void RemoteClient::GetNextBlocks (
149150
u16 max_simul_sends_usually = m_max_simul_sends;
150151

151152
/*
152-
Check the time from last addNode/removeNode.
153-
154153
Decrease send rate if player is building stuff.
154+
155+
The idea is that we can save some bandwidth since the player is busy
156+
and not looking around.
155157
*/
156158
m_time_from_building += dtime;
157159
if (m_time_from_building < m_min_time_from_building) {
158-
max_simul_sends_usually
159-
= LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
160+
max_simul_sends_usually *= LIMITED_BLOCK_SENDS_FACTOR;
161+
max_simul_sends_usually = MYMAX(1, max_simul_sends_usually);
160162
}
161163

162164
/*
@@ -223,17 +225,19 @@ void RemoteClient::GetNextBlocks (
223225
s16 d_max = full_d_max;
224226

225227
// Don't loop very much at a time
226-
s16 max_d_increment_at_time = 2;
228+
const s16 max_d_increment_at_time = 2;
227229
if (d_max > d_start + max_d_increment_at_time)
228230
d_max = d_start + max_d_increment_at_time;
229231

230-
// cos(angle between velocity and camera) * |velocity|
231-
// Limit to 0.0f in case player moves backwards.
232-
f32 dot = rangelim(camera_dir.dotProduct(playerspeed), 0.0f, 300.0f);
232+
{
233+
// cos(angle between velocity and camera) * |velocity|
234+
// Limit to 0.0f in case player moves backwards.
235+
f32 dot = rangelim(camera_dir.dotProduct(playerspeed), 0.0f, 300.0f);
233236

234-
// Reduce the field of view when a player moves and looks forward.
235-
// limit max fov effect to 50%, 60% at 20n/s fly speed
236-
camera_fov = camera_fov / (1 + dot / 300.0f);
237+
// Reduce the field of view when a player moves and looks forward.
238+
// limit max fov effect to 50%, 60% at 20n/s fly speed
239+
camera_fov = camera_fov / (1 + dot / 300.0f);
240+
}
237241

238242
s32 nearest_emerged_d = -1;
239243
s32 nearest_sent_d = -1;
@@ -260,11 +264,9 @@ void RemoteClient::GetNextBlocks (
260264
Also, don't send blocks that are already flying.
261265
*/
262266

263-
// Start with the usual maximum
264267
u16 max_simul_dynamic = max_simul_sends_usually;
265-
266268
// If block is very close, allow full maximum
267-
if (d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
269+
if (d <= BLOCK_ALWAYS_SEND_MAX_D)
268270
max_simul_dynamic = m_max_simul_sends;
269271

270272
/*
@@ -388,8 +390,8 @@ void RemoteClient::GetNextBlocks (
388390
new_nearest_unsent_d = 0;
389391
m_nothing_to_send_pause_timer = 2.0f;
390392
infostream << "Server: Player " << m_name << ", peer_id=" << peer_id
391-
<< ": full map send completed after " << m_map_send_completion_timer
392-
<< "s, restarting" << std::endl;
393+
<< ": full map send (d=" << d << ") completed after "
394+
<< m_map_send_completion_timer << "s, restarting" << std::endl;
393395
m_map_send_completion_timer = 0.0f;
394396
} else {
395397
if (nearest_sent_d != -1)

src/util/numeric.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
100100
v3f blockpos_relative = blockpos - camera_pos;
101101

102102
// Total distance
103-
f32 d = MYMAX(0, blockpos_relative.getLength() - BLOCK_MAX_RADIUS);
103+
f32 d = std::max(0.0f, blockpos_relative.getLength() - BLOCK_MAX_RADIUS);
104104

105105
if (distance_ptr)
106106
*distance_ptr = d;

0 commit comments

Comments
 (0)