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:
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,17 +225,19 @@ 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);
|
||||
{
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
// 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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user