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.
|
# 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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user