1
0
mirror of https://github.com/luanti-org/luanti.git synced 2025-12-26 16:25:25 +01:00

Process (a chunk local) liquid queue early when blocks are generated (#16771)

When generating a new chunk, the chunk's liquid queue is processed immediately, instead of adding entries to the global liquid queue. Since the generated have not been sent to the client, this avoids sending duplicate blocks (that interfere with map sending) later when the global liquid queue is processed.
This commit is contained in:
lhofhansl
2025-12-24 10:02:26 +01:00
committed by GitHub
parent f91e58abab
commit 8883c4cb23
3 changed files with 33 additions and 21 deletions

View File

@@ -596,8 +596,7 @@ MapBlock *EmergeThread::finishGen(v3s16 pos, BlockMakeData *bmdata,
Perform post-processing on blocks (invalidate lighting, queue liquid
transforms, etc.) to finish block make
*/
m_map->finishBlockMake(bmdata, modified_blocks,
m_server->m_env->getGameTime());
m_map->finishBlockMake(bmdata, modified_blocks, m_server->m_env);
MapBlock *block = m_map->getBlockNoCreateNoEx(pos);
if (!block) {

View File

@@ -279,10 +279,11 @@ void ServerMap::cancelBlockMake(BlockMakeData *data)
}
void ServerMap::finishBlockMake(BlockMakeData *data,
std::map<v3s16, MapBlock*> *changed_blocks, u32 now)
std::map<v3s16, MapBlock*> *changed_blocks, ServerEnvironment *env)
{
assert(data);
assert(changed_blocks);
u32 now = env->getGameTime();
const v3s16 bpmin = data->blockpos_min;
const v3s16 bpmax = data->blockpos_max;
@@ -299,7 +300,13 @@ void ServerMap::finishBlockMake(BlockMakeData *data,
<< changed_blocks->size());
/*
Copy transforming liquid information
Process the chunk's liquid queue now.
This avoids sending many duplicate block updates.
*/
transformLiquidsLocal(*changed_blocks, data->transforming_liquid, env, g_settings->getS32("liquid_loop_max"));
/*
Copy remaining (if any) transforming liquid information
*/
while (!data->transforming_liquid.empty()) {
m_transforming_liquid.push_back(data->transforming_liquid.front());
@@ -919,11 +926,10 @@ void ServerMap::transforming_liquid_add(v3s16 p)
m_transforming_liquid.push_back(p);
}
void ServerMap::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks,
ServerEnvironment *env)
void ServerMap::transformLiquidsLocal(std::map<v3s16, MapBlock*> &modified_blocks, UniqueQueue<v3s16> &liquid_queue,
ServerEnvironment *env, u32 liquid_loop_max)
{
u32 loopcount = 0;
u32 initial_size = m_transforming_liquid.size();
/*if(initial_size != 0)
infostream<<"transformLiquids(): initial_size="<<initial_size<<std::endl;*/
@@ -935,21 +941,18 @@ void ServerMap::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks,
std::vector<v3s16> check_for_falling;
u32 liquid_loop_max = g_settings->getS32("liquid_loop_max");
u32 loop_max = liquid_loop_max;
while (m_transforming_liquid.size() != 0)
while (!liquid_queue.empty())
{
// This should be done here so that it is done when continue is used
if (loopcount >= initial_size || loopcount >= loop_max)
if (loopcount >= liquid_loop_max)
break;
loopcount++;
/*
Get a queued transforming liquid node
*/
v3s16 p0 = m_transforming_liquid.front();
m_transforming_liquid.pop_front();
v3s16 p0 = liquid_queue.front();
liquid_queue.pop_front();
MapNode n0 = getNode(p0);
@@ -1025,7 +1028,7 @@ void ServerMap::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks,
// should be enqueded for transformation regardless of whether the
// current node changes or not.
if (nb.t != NEIGHBOR_UPPER && liquid_type != LIQUID_NONE)
m_transforming_liquid.push_back(npos);
liquid_queue.push_back(npos);
// if the current node happens to be a flowing node, it will start to flow down here.
if (nb.t == NEIGHBOR_LOWER)
flowing_down = true;
@@ -1220,15 +1223,15 @@ void ServerMap::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks,
// make sure source flows into all neighboring nodes
for (u16 i = 0; i < num_flows; i++)
if (flows[i].t != NEIGHBOR_UPPER)
m_transforming_liquid.push_back(flows[i].p);
liquid_queue.push_back(flows[i].p);
for (u16 i = 0; i < num_airs; i++)
if (airs[i].t != NEIGHBOR_UPPER)
m_transforming_liquid.push_back(airs[i].p);
liquid_queue.push_back(airs[i].p);
break;
case LIQUID_NONE:
// this flow has turned to air; neighboring flows might need to do the same
for (u16 i = 0; i < num_flows; i++)
m_transforming_liquid.push_back(flows[i].p);
liquid_queue.push_back(flows[i].p);
break;
case LiquidType_END:
break;
@@ -1237,7 +1240,7 @@ void ServerMap::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks,
//infostream<<"Map::transformLiquids(): loopcount="<<loopcount<<std::endl;
for (const auto &iter : must_reflow)
m_transforming_liquid.push_back(iter);
liquid_queue.push_back(iter);
voxalgo::update_lighting_nodes(this, changed_nodes, modified_blocks);
@@ -1246,6 +1249,15 @@ void ServerMap::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks,
}
env->getScriptIface()->on_liquid_transformed(changed_nodes);
}
void ServerMap::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks,
ServerEnvironment *env)
{
// process the whole queue at most once, to rate-limit
u32 liquid_loop_max = std::min<u32>(m_transforming_liquid.size(), g_settings->getS32("liquid_loop_max"));
transformLiquidsLocal(modified_blocks, m_transforming_liquid, env, liquid_loop_max);
/* ----------------------------------------------------------------------
* Manage the queue so that it does not grow indefinitely

View File

@@ -66,7 +66,7 @@ public:
/// @brief write data back to map after mapgen
/// @param now current game time
void finishBlockMake(BlockMakeData *data,
std::map<v3s16, MapBlock*> *changed_blocks, u32 now);
std::map<v3s16, MapBlock*> *changed_blocks, ServerEnvironment *env);
void cancelBlockMake(BlockMakeData *data);
/*
@@ -158,7 +158,8 @@ public:
void transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks,
ServerEnvironment *env);
void transformLiquidsLocal(std::map<v3s16, MapBlock*> &modified_blocks, UniqueQueue<v3s16> &liquid_queue,
ServerEnvironment *env, u32 liquid_loop_max);
void transforming_liquid_add(v3s16 p);
MapSettingsManager settings_mgr;