This commit is contained in:
proller committed 2026-02-09 23:45:36 +01:00
1 parent 30b1ab9eb0
commit cdcc08dcd0
8 files changed
+136 -92

No files matched your search

+21 -7
View File
@@ -298,23 +298,37 @@ void Client::handleCommand_BlockDataFm(NetworkPacket *pkt)
mesh_thread_pool.enqueue([this, block, step]() mutable {
auto &client_map = getEnv().getClientMap();
const auto &control = client_map.getControl();
const auto bpos = block->getPos();
if (!farmesh::inFarGrid(control,
getNodeBlockPos(client_map.far_blocks_last_cam_pos), bpos,
step)) {
const auto blockpos = block->getPos();
const auto res = farmesh::getFarParams(control,
getNodeBlockPos(client_map.far_blocks_last_cam_pos), blockpos);
if (!res)
return;
auto &far_blocks = client_map.m_far_blocks;
bool other_draw_block = false;
if (!(res->pos == blockpos && res->step == step)) {
const auto lock = far_blocks.lock_unique_rec();
if (const auto &it = far_blocks.find(res->pos);
it != far_blocks.end() && it->second->far_step == step) {
block = it->second;
other_draw_block = true;
// TODO: throttle ~1s to wait nearby block datas
} else {
return;
}
}
createFarMesh(block);
auto &far_blocks = client_map.m_far_blocks;
if (other_draw_block)
return;
const auto lock = far_blocks.lock_unique_rec();
if (const auto &it = far_blocks.find(bpos); it != far_blocks.end()) {
if (const auto &it = far_blocks.find(blockpos); it != far_blocks.end()) {
if (it->second->far_step != block->far_step) {
return;
}
block->far_iteration =
it->second->far_iteration.load(std::memory_order::relaxed);
far_blocks.at(bpos) = block;
far_blocks.at(blockpos) = block;
}
});
+3 -5
View File
@@ -26,10 +26,8 @@ const MapNode &FarContainer::getNodeRefUnsafe(const v3pos_t &pos)
const auto player_block_pos = getNodeBlockPos(client_map.far_blocks_last_cam_pos);
const auto &control = client_map.getControl();
const auto tree_result = farmesh::getFarParams(control, player_block_pos, block_pos);
if (!tree_result) {
return m_mg->visible_transparent;
}
const auto tree_result = farmesh::getFarParams(control, player_block_pos, block_pos, true);
if (tree_result) {
const auto &step = tree_result->step;
const v3bpos_t &bpos_aligned = tree_result->pos;
@@ -101,7 +99,7 @@ const MapNode &FarContainer::getNodeRefUnsafe(const v3pos_t &pos)
return n;
}
}
}
if (const auto &v = m_mg->visible_content(pos, use_weather); v.getContent()) {
return v;
}
+55 -29
View File
@@ -98,7 +98,7 @@ void FarMesh::makeFarBlock(const v3bpos_t &blockpos, block_step_t step, bool bne
block = it->second;
} else {
if (!block) {
m_client->getEnv().getClientMap().m_far_blocks_ask.emplace(
client_map.m_far_blocks_ask.emplace(
blockpos_actual, std::make_pair(step, far_iteration_complete));
block = client_map.createBlankBlockNoInsert(blockpos_actual);
@@ -121,7 +121,7 @@ void FarMesh::makeFarBlock(const v3bpos_t &blockpos, block_step_t step, bool bne
return;
}
void FarMesh::makeFarBlocks(const v3bpos_t &blockpos, block_step_t step)
void FarMesh::makeFarBlocks(const v3bpos_t &blockpos, const block_step_t step)
{
#if FARMESH_DEBUG || FARMESH_FAST
{
@@ -153,10 +153,13 @@ void FarMesh::makeFarBlocks(const v3bpos_t &blockpos, block_step_t step)
const auto step_width = 1 << (step - 1 + control.cell_size_pow);
for (const auto &dir : use_dirs) {
const auto bpos_dir = blockpos + dir * step_width;
const auto bpos = farmesh::getFarActualBlockPos(
const auto tree_result = farmesh::getFarParams(
control, getNodeBlockPos(m_camera_pos_aligned), bpos_dir);
const auto block_step_correct =
farmesh::getFarStep(control, getNodeBlockPos(m_camera_pos_aligned), bpos);
if (!tree_result) {
continue;
}
const auto &block_step_correct = tree_result->step;
const v3bpos_t &bpos = tree_result->pos;
makeFarBlock(bpos, block_step_correct, {}, bpos);
}
}
@@ -274,14 +277,14 @@ auto align_shift(auto pos, const auto amount)
int FarMesh::go_container()
{
const auto &draw_control = *m_control;
const auto cbpos = getNodeBlockPos(m_camera_pos_aligned);
const auto player_block_pos = getNodeBlockPos(m_camera_pos_aligned);
thread_local static const s16 farmesh_all_changed =
g_settings->getU32("farmesh_all_changed");
farmesh::runFarAll(cbpos, draw_control.cell_size_pow, draw_control.farmesh,
farmesh::runFarAll(player_block_pos, draw_control.cell_size_pow, draw_control.farmesh,
draw_control.farmesh_quality_pow, 0, false,
[this, &cbpos](const v3bpos_t &bpos, const bpos_t &size,
[this, &player_block_pos](const v3bpos_t &bpos, const bpos_t &size,
const block_step_t &step) -> bool {
if (step >= FARMESH_STEP_MAX) {
@@ -289,7 +292,7 @@ int FarMesh::go_container()
}
// TODO: use block center
const auto bdist = radius_box(cbpos, bpos);
const auto bdist = radius_box(player_block_pos, bpos);
if ((bdist << MAP_BLOCKP) > farmesh_all_changed) {
return false;
}
@@ -319,35 +322,57 @@ int FarMesh::go_flat()
return 0;
}
const auto cbpos = getNodeBlockPos(m_camera_pos_aligned);
const auto player_block_pos = getNodeBlockPos(m_camera_pos_aligned);
// todo: maybe save blocks while cam pos not changed
std::array<std::unordered_set<v3bpos_t>, FARMESH_STEP_MAX> blocks;
farmesh::runFarAll(cbpos, draw_control.cell_size_pow, draw_control.farmesh,
draw_control.farmesh_quality_pow, cbpos.Y ?: 1, true,
[this, &draw_control, &blocks](const v3bpos_t &bpos, const bpos_t &size,
const block_step_t &step) -> bool {
for (const auto &add : {
v2bpos_t(0, 0),
v2bpos_t(0, size - 1),
v2bpos_t(size - 1, 0),
v2bpos_t(size - 1, size - 1),
v2bpos_t(size >> 1, size >> 1),
}) {
v3bpos_t bpos_new(bpos.X + add.X, 0, bpos.Z + add.Y);
farmesh::runFarAll(player_block_pos, draw_control.cell_size_pow, draw_control.farmesh,
draw_control.farmesh_quality_pow, 1, false,
[this, &draw_control, &blocks, &player_block_pos](const v3bpos_t &bpos,
const bpos_t &size, const block_step_t &step) -> bool {
#if 0 // test only
{
v3bpos_t bpos_new{bpos.X, 0, bpos.Z};
bpos_new.Y = mg->getGroundLevelAtPoint(
v2pos_t((bpos_new.X << MAP_BLOCKP) - 1,
(bpos_new.Z << MAP_BLOCKP) - 1)) >>
MAP_BLOCKP;
const auto step_new = farmesh::getFarStep(draw_control,
getNodeBlockPos(m_camera_pos_aligned), bpos_new //, 0
);
const auto step_new =
farmesh::getFarStep(draw_control, player_block_pos, bpos_new);
if (step_new >= FARMESH_STEP_MAX)
return false;
blocks[step_new].emplace(bpos_new);
return false;
}
#endif
const auto add_size = size << draw_control.cell_size_pow;
for (const auto &add : {
v2bpos_t(0, 0),
v2bpos_t(0, add_size - 1),
v2bpos_t(add_size - 1, 0),
v2bpos_t(add_size - 1, add_size - 1),
v2bpos_t(add_size >> 1, add_size >> 1),
}) {
v3bpos_t bpos_new{bpos.X + add.X, 0, bpos.Z + add.Y};
bpos_new.Y = mg->getGroundLevelAtPoint(
v2pos_t((bpos_new.X << MAP_BLOCKP) - 1,
(bpos_new.Z << MAP_BLOCKP) - 1)) >>
MAP_BLOCKP;
const auto res = farmesh::getFarParams(
draw_control, player_block_pos, bpos_new);
if (!res)
continue;
const auto &bpos_correct = res->pos;
const auto &step_new = res->step;
if (step_new >= FARMESH_STEP_MAX)
continue;
blocks[step_new].emplace(bpos_new);
blocks[step_new].emplace(bpos_correct);
}
return false;
});
@@ -359,10 +384,11 @@ int FarMesh::go_flat()
for (const auto &bpos : blocks[last_step]) {
// just first suggestion
if (1 << (last_step + MAP_BLOCKP) > draw_control.farmesh &&
radius_box(bpos, cbpos) << MAP_BLOCKP > last_distance_max) {
radius_box(bpos, player_block_pos) << MAP_BLOCKP >
last_distance_max) {
return last_step;
}
makeFarBlocks(bpos, last_step);
makeFarBlock(bpos, last_step, {}, bpos);
}
}
+1 -1
View File
@@ -987,7 +987,7 @@ const auto is_each_mode= m_block_bounds_mode == BLOCK_BOUNDS_FAR_DRAWN_EACH;
far_step = mesh->far_step;
}
if (is_each_mode) {
fscale = 1 << block->far_step;
fscale = 1 << mesh_step;
}
const aabb3f box(oposToV3f(intToFloat((blockPos)*MAP_BLOCKSIZE, BS) -
offset - halfNode + 1),
+4 -3
View File
@@ -744,7 +744,8 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data):
buf->drop();
}
if (static const auto farlights = g_settings->getBool("farlights"); farlights && far_step) {
if (static const auto farlights = g_settings->getBool("farlights");
farlights && far_step) {
scene::SMeshBuffer *buffer = new scene::SMeshBuffer();
buffer->PrimitiveType = scene::EPT_POINTS;
buffer->Material.PointCloud = true;
@@ -787,8 +788,8 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data):
buffer->Indices->Data.emplace_back(index_i);
}
}
}
}
}
}
mesh->addMeshBuffer(buffer);
buffer->drop();
}
+4 -4
View File
@@ -623,7 +623,7 @@ uint32_t RemoteClient::SendFarBlocks(const int32_t uptime)
const auto playerpos = sao->getBasePosition();
const auto cbpos = floatToInt(playerpos, BS * MAP_BLOCKSIZE);
const auto player_block_pos = floatToInt(playerpos, BS * MAP_BLOCKSIZE);
const auto cell_size = 1; // FMTODO from remoteclient
const auto cell_size_pow = farmesh::rangeToStep(cell_size);
@@ -631,9 +631,9 @@ uint32_t RemoteClient::SendFarBlocks(const int32_t uptime)
g_settings->getU32("farmesh_all_changed");
const auto &use_farmesh_all_changed =
std::min(setting_farmesh_all_changed, farmesh_all_changed);
farmesh::runFarAll(cbpos, cell_size_pow, farmesh,
farmesh::runFarAll(player_block_pos, cell_size_pow, farmesh,
farmesh::rangeToStep(farmesh_quality), false, true,
[this, &ordered, &cbpos, &use_farmesh_all_changed](
[this, &ordered, &player_block_pos, &use_farmesh_all_changed](
const v3bpos_t &bpos, const bpos_t &size,
const block_step_t &step) -> bool {
if (!size) {
@@ -641,7 +641,7 @@ uint32_t RemoteClient::SendFarBlocks(const int32_t uptime)
}
// TODO: use block center
const auto bdist = radius_box(cbpos, bpos);
const auto bdist = radius_box(player_block_pos, bpos);
if (bdist << MAP_BLOCKP > use_farmesh_all_changed) {
return false;
}
+46 -41
View File
@@ -145,8 +145,8 @@ bool inFarGrid(const MapDrawControl &draw_control, const v3bpos_t &player_block_
struct find_param_t
{
const v3tpos_t &block_pos;
const v3tpos_t &player_pos;
const v3tpos_t &block_pos;
const uint8_t cell_size_pow;
const uint8_t farmesh_quality_pow;
const bool cell_size_each{0};
@@ -160,7 +160,7 @@ struct child_t
std::optional<tree_result_t> find(const find_param_t &param,
const child_t &child,
uint16_t depth = 0)
const uint16_t depth = 0)
{
const auto make_result = [&param](const auto &child) {
return tree_result_t{
@@ -184,7 +184,7 @@ std::optional<tree_result_t> find(const find_param_t &param,
}
}
if (child.size < (1 << (param.cell_size_pow))) {
if (child.size <= (1 << (param.cell_size_pow))) {
return make_result(child);
}
@@ -200,28 +200,29 @@ std::optional<tree_result_t> find(const find_param_t &param,
if (distance >= next_child_size) {
return make_result(child);
}
const auto childSizePos = childSize;
for (const auto &child : {
child_t{.pos{child.pos}, .size = childSize},
child_t{.pos = v3tpos_t(
child.pos.X + childSize, child.pos.Y, child.pos.Z),
child.pos.X + childSizePos, child.pos.Y, child.pos.Z),
.size = childSize},
child_t{.pos = v3tpos_t(
child.pos.X, child.pos.Y + childSize, child.pos.Z),
child.pos.X, child.pos.Y + childSizePos, child.pos.Z),
.size = childSize},
child_t{.pos = v3tpos_t(child.pos.X + childSize, child.pos.Y + childSize,
child.pos.Z),
child_t{.pos = v3tpos_t(child.pos.X + childSizePos,
child.pos.Y + childSizePos, child.pos.Z),
.size = childSize},
child_t{.pos = v3tpos_t(
child.pos.X, child.pos.Y, child.pos.Z + childSize),
child.pos.X, child.pos.Y, child.pos.Z + childSizePos),
.size = childSize},
child_t{.pos = v3tpos_t(child.pos.X + childSize, child.pos.Y,
child.pos.Z + childSize),
child_t{.pos = v3tpos_t(child.pos.X + childSizePos, child.pos.Y,
child.pos.Z + childSizePos),
.size = childSize},
child_t{.pos = v3tpos_t(child.pos.X, child.pos.Y + childSize,
child.pos.Z + childSize),
child_t{.pos = v3tpos_t(child.pos.X, child.pos.Y + childSizePos,
child.pos.Z + childSizePos),
.size = childSize},
child_t{.pos = v3tpos_t(child.pos.X + childSize, child.pos.Y + childSize,
child.pos.Z + childSize),
child_t{.pos = v3tpos_t(child.pos.X + childSizePos,
child.pos.Y + childSizePos, child.pos.Z + childSizePos),
.size = childSize},
}) {
@@ -264,17 +265,17 @@ const auto farmesh_to_tree_pow = [](const auto farmesh) {
rangeToStep(farmesh) - 1); // -2 ? TODO: test and tune
};
child_t tree_params_to_child(
const tree_params_t &tree_params, const v3bpos_t &ppos, pos_t two_d = {})
child_t tree_params_to_child(const tree_params_t &tree_params,
const v3bpos_t &player_block_pos, pos_t two_d = {})
{
return {.pos = v3tpos_t((((tpos_t)ppos.X >> tree_params.tree_align)
return {.pos = v3tpos_t((((tpos_t)player_block_pos.X >> tree_params.tree_align)
<< tree_params.tree_align) -
(tree_params.tree_align_size >> 1),
two_d
?: (((tpos_t)(ppos.Y) >> tree_params.tree_align)
?: (((tpos_t)(player_block_pos.Y) >> tree_params.tree_align)
<< tree_params.tree_align) -
(tree_params.tree_align_size >> 1),
(((tpos_t)(ppos.Z) >> tree_params.tree_align)
(((tpos_t)(player_block_pos.Z) >> tree_params.tree_align)
<< tree_params.tree_align) -
(tree_params.tree_align_size >> 1)),
.size{tree_params.tree_size}};
@@ -283,14 +284,13 @@ child_t tree_params_to_child(
std::optional<tree_result_t> getFarParams(const MapDrawControl &draw_control,
const v3bpos_t &player_block_pos, const v3bpos_t &blockpos, bool cell_each)
{
const auto blockpos_aligned_cell = blockpos;
const auto blockpos_aligned_cell = align_shift(blockpos, draw_control.cell_size_pow);
const tree_params_t tree_params{.tree_pow{farmesh_to_tree_pow(draw_control.farmesh)}};
const auto start = tree_params_to_child(tree_params, player_block_pos);
const auto res = find(
{.block_pos{blockpos_aligned_cell.X, blockpos_aligned_cell.Y,
blockpos_aligned_cell.Z},
.player_pos{
player_block_pos.X, player_block_pos.Y, player_block_pos.Z},
{.player_pos{player_block_pos.X, player_block_pos.Y, player_block_pos.Z},
.block_pos{blockpos_aligned_cell.X, blockpos_aligned_cell.Y,
blockpos_aligned_cell.Z},
.cell_size_pow{draw_control.cell_size_pow},
.farmesh_quality_pow{draw_control.farmesh_quality_pow},
.cell_size_each{cell_each}},
@@ -352,9 +352,9 @@ void each(const each_param_t &param, const child_t &child)
{
const tpos_t childSize = child.size >> 1;
const auto distance =
(std::max({std::abs((tpos_t)param.player_pos.X + (child.pos.X - childSize)),
std::abs((tpos_t)param.player_pos.Y + (child.pos.Y - childSize)),
std::abs((tpos_t)param.player_pos.Z + (child.pos.Z - childSize))}) >>
(std::max({std::abs((tpos_t)param.player_pos.X - (child.pos.X + childSize)),
std::abs((tpos_t)param.player_pos.Y - (child.pos.Y + childSize)),
std::abs((tpos_t)param.player_pos.Z - (child.pos.Z + childSize))}) >>
param.cell_size_pow)
<< param.cell_size_pow;
@@ -369,33 +369,37 @@ void each(const each_param_t &param, const child_t &child)
return;
}
const auto childSizeNext = childSize
<< (param.cell_size_each ? 0 : param.cell_size_pow);
uint8_t i{0};
for (const auto &child : {
// first with unchanged Y for 2d
child_t{.pos{child.pos}, .size = childSize},
child_t{.pos = v3tpos_t(
child.pos.X + childSize, child.pos.Y, child.pos.Z),
child.pos.X + childSizeNext, child.pos.Y, child.pos.Z),
.size = childSize},
child_t{.pos = v3tpos_t(
child.pos.X, child.pos.Y, child.pos.Z + childSize),
child.pos.X, child.pos.Y, child.pos.Z + childSizeNext),
.size = childSize},
child_t{.pos = v3tpos_t(child.pos.X + childSize, child.pos.Y,
child.pos.Z + childSize),
child_t{.pos = v3tpos_t(child.pos.X + childSizeNext, child.pos.Y,
child.pos.Z + childSizeNext),
.size = childSize},
// two_d ends here
child_t{.pos = v3tpos_t(
child.pos.X, child.pos.Y + childSize, child.pos.Z),
child.pos.X, child.pos.Y + childSizeNext, child.pos.Z),
.size = childSize},
child_t{.pos = v3tpos_t(child.pos.X + childSize, child.pos.Y + childSize,
child.pos.Z),
child_t{.pos = v3tpos_t(child.pos.X + childSizeNext,
child.pos.Y + childSizeNext, child.pos.Z),
.size = childSize},
child_t{.pos = v3tpos_t(child.pos.X, child.pos.Y + childSize,
child.pos.Z + childSize),
child_t{.pos = v3tpos_t(child.pos.X, child.pos.Y + childSizeNext,
child.pos.Z + childSizeNext),
.size = childSize},
child_t{.pos = v3tpos_t(child.pos.X + childSize, child.pos.Y + childSize,
child.pos.Z + childSize),
child_t{.pos = v3tpos_t(child.pos.X + childSizeNext,
child.pos.Y + childSizeNext,
child.pos.Z + childSizeNext),
.size = childSize},
}) {
@@ -420,13 +424,13 @@ void each(const each_param_t &param, const child_t &child)
}
}
void runFarAll(const v3bpos_t &ppos, uint8_t cell_size_pow, int farmesh,
void runFarAll(const v3bpos_t &player_block_pos, uint8_t cell_size_pow, int farmesh,
uint8_t farmesh_quality_pow, pos_t two_d, bool cell_each,
const std::function<bool(const v3bpos_t &, const bpos_t &, const block_step_t &)>
&func)
{
tree_params_t tree_params{.tree_pow{farmesh_to_tree_pow(farmesh)}};
const auto start = tree_params_to_child(tree_params, ppos, two_d);
const auto start = tree_params_to_child(tree_params, player_block_pos, two_d);
const auto func_convert = [&func](const tree_result_t &child) {
return func(
v3bpos_t{child.pos.X, child.pos.Y, child.pos.Z}, child.size, child.step);
@@ -435,7 +439,8 @@ void runFarAll(const v3bpos_t &ppos, uint8_t cell_size_pow, int farmesh,
// DUMP(start.pos, start.size, tree_align);
each(
{
.player_pos{ppos.X, ppos.Y, ppos.Z},
.player_pos{
player_block_pos.X, player_block_pos.Y, player_block_pos.Z},
.cell_size_pow{cell_size_pow},
.farmesh_quality_pow{farmesh_quality_pow},
.cell_size_each{cell_each},
+2 -2
View File
@@ -249,10 +249,10 @@ public:
std::map<uint16_t, std::pair<double, int32_t>> m_objects_last_pos_sent;
v3f m_last_direction;
float m_nearest_unsent_reset_timer{};
std::unordered_map<v3bpos_t, uint8_t> blocks;
//std::unordered_map<v3bpos_t, uint8_t> blocks;
void SetBlocksNotSent();
void SetBlockDeleted(const v3bpos_t &p);
std::vector<std::unordered_map<v3bpos_t, std::pair<uint8_t, int32_t>>>
std::vector<std::unordered_map<v3bpos_t, std::pair<block_step_t, int32_t>>>
far_blocks_requested{FARMESH_STEP_MAX};
std::mutex far_blocks_requested_mutex;
int GetNextBlocksFm(ServerEnvironment *env, EmergeManager *emerge, float dtime,